@sema-agent/client-core 0.107.0 → 0.109.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/CHANGELOG.md +239 -0
  2. package/README.md +54 -36
  3. package/dist/adapt/arms.js +23 -8
  4. package/dist/adapt/textStream.d.ts +2 -0
  5. package/dist/adapt/textStream.js +37 -16
  6. package/dist/adapter/activeRunSelfHeal.d.ts +2 -0
  7. package/dist/adapter/activeRunSelfHeal.js +21 -4
  8. package/dist/adapter/downstream/eventToSdkMessage.js +2 -1
  9. package/dist/agentSession/engineAgentRegistryRead.js +2 -0
  10. package/dist/bashExitReading.d.ts +12 -0
  11. package/dist/bashExitReading.js +44 -0
  12. package/dist/checkpointRowVerdict.d.ts +6 -1
  13. package/dist/checkpointRowVerdict.js +30 -2
  14. package/dist/cloudConfigWireCaps.d.ts +10 -0
  15. package/dist/cloudConfigWireCaps.js +33 -0
  16. package/dist/compensations.js +1 -1
  17. package/dist/coreValuePorts.d.ts +17 -1
  18. package/dist/coreValuePorts.js +5 -0
  19. package/dist/decideReceipt.js +2 -1
  20. package/dist/engineAgentAbsence.d.ts +2 -0
  21. package/dist/engineAgentAbsence.js +28 -0
  22. package/dist/engineErrorCodes.d.ts +9 -0
  23. package/dist/engineErrorCodes.js +9 -0
  24. package/dist/engineHealthFacts.d.ts +17 -0
  25. package/dist/engineHealthFacts.js +42 -3
  26. package/dist/engineNoticeCodes.d.ts +147 -1
  27. package/dist/engineNoticeCodes.js +694 -57
  28. package/dist/engineTargetSeat.js +1 -0
  29. package/dist/errorSupplementRoles.js +6 -1
  30. package/dist/eventLeg.js +1 -1
  31. package/dist/executionLaneWords.js +2 -1
  32. package/dist/fleetTaskDesc.js +3 -3
  33. package/dist/gateOutcome.d.ts +10 -1
  34. package/dist/gateOutcome.js +48 -1
  35. package/dist/generated/engineFactTables.d.ts +2 -0
  36. package/dist/generated/engineFactTables.js +11 -0
  37. package/dist/generated/engineNoticeTables.js +6 -0
  38. package/dist/generated/settingsSchemaFns.d.ts +4 -2
  39. package/dist/generated/settingsSchemaFns.js +9 -3
  40. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
  41. package/dist/generated/settingsSchemaMcpRequestEntry.js +9 -18
  42. package/dist/generated/settingsSchemaReservedMemberName.d.ts +1 -0
  43. package/dist/generated/settingsSchemaReservedMemberName.js +7 -0
  44. package/dist/generated/settingsSchemaTables.d.ts +2 -0
  45. package/dist/generated/settingsSchemaTables.js +10 -0
  46. package/dist/generated/settingsSchemaWireName.d.ts +1 -0
  47. package/dist/generated/settingsSchemaWireName.js +8 -0
  48. package/dist/headlessReconnectWire.js +12 -7
  49. package/dist/hitl/approvalAskers.d.ts +13 -0
  50. package/dist/hitl/approvalAskers.js +79 -0
  51. package/dist/hitl/approvalCardReasons.js +22 -4
  52. package/dist/hitl/approvalRequestFrameReading.d.ts +14 -0
  53. package/dist/hitl/approvalRequestFrameReading.js +79 -0
  54. package/dist/hitl/approvalResolution.d.ts +3 -0
  55. package/dist/hitl/approvalResolution.js +22 -4
  56. package/dist/hitl/approvalsFeed.js +4 -13
  57. package/dist/hitl/askParkRowRouting.js +10 -3
  58. package/dist/hitl/automaticAnswerVerdict.d.ts +5 -2
  59. package/dist/hitl/automaticAnswerVerdict.js +16 -2
  60. package/dist/hitl/decisionConflict.d.ts +2 -1
  61. package/dist/hitl/decisionConflict.js +4 -1
  62. package/dist/hitl/decisionRefusal.d.ts +1 -0
  63. package/dist/hitl/decisionRefusal.js +5 -2
  64. package/dist/hitl/decisionSend.js +2 -6
  65. package/dist/hitl/frameRouter.d.ts +3 -2
  66. package/dist/hitl/frameRouter.js +37 -7
  67. package/dist/hitl/gateLedger.d.ts +2 -0
  68. package/dist/hitl/gateLedger.js +3 -1
  69. package/dist/hitl/hitlBridge.d.ts +4 -0
  70. package/dist/hitl/hitlBridge.js +11 -8
  71. package/dist/hitl/livePendingAsk.js +17 -16
  72. package/dist/hitl/localAllowRule.js +2 -1
  73. package/dist/hitl/noAllowCause.d.ts +1 -1
  74. package/dist/hitl/noAllowCause.js +4 -2
  75. package/dist/hitl/parkExpiryJudgements.js +26 -1
  76. package/dist/hitl/parkOwnership.d.ts +2 -0
  77. package/dist/hitl/parkOwnership.js +48 -8
  78. package/dist/hitl/parkResolver.js +39 -30
  79. package/dist/hitl/parkRowBirthWait.d.ts +2 -0
  80. package/dist/hitl/parkRowBirthWait.js +8 -1
  81. package/dist/hitl/parkedUnresumable.d.ts +13 -0
  82. package/dist/hitl/parkedUnresumable.js +80 -0
  83. package/dist/hitl/permissionRuleScope.d.ts +4 -0
  84. package/dist/hitl/permissionRuleScope.js +31 -0
  85. package/dist/hitl/persistedRulesWire.d.ts +7 -1
  86. package/dist/hitl/persistedRulesWire.js +25 -8
  87. package/dist/hitl/planReviewWire.js +12 -16
  88. package/dist/hitl/policyDenyCause.d.ts +3 -0
  89. package/dist/hitl/policyDenyCause.js +16 -0
  90. package/dist/hitl/sessionAllowRoute.js +5 -4
  91. package/dist/hitl/sessionPolicyDeliverable.js +1 -1
  92. package/dist/hitl/standingRows.d.ts +1 -5
  93. package/dist/hitl/standingRows.js +15 -14
  94. package/dist/hitl/toolApprovalWire.d.ts +16 -4
  95. package/dist/hitl/toolApprovalWire.js +57 -17
  96. package/dist/hooksReaderGenerations.d.ts +1 -0
  97. package/dist/hooksReaderGenerations.js +12 -0
  98. package/dist/hooksWireCaps.js +12 -7
  99. package/dist/hostSettingsSource.js +2 -0
  100. package/dist/i18n/messages.en.d.ts +206 -1
  101. package/dist/i18n/messages.en.js +209 -4
  102. package/dist/i18n/messages.zh.js +214 -4
  103. package/dist/index.d.ts +35 -8
  104. package/dist/index.js +20 -5
  105. package/dist/liveModelCatalog.d.ts +4 -2
  106. package/dist/liveModelCatalog.js +164 -26
  107. package/dist/localEngineJudge.d.ts +75 -0
  108. package/dist/localEngineJudge.js +242 -0
  109. package/dist/localEngineOccupancy.d.ts +88 -0
  110. package/dist/localEngineOccupancy.js +269 -0
  111. package/dist/localEngineSeatReading.d.ts +29 -0
  112. package/dist/localEngineSeatReading.js +294 -0
  113. package/dist/localEngineSpawn.d.ts +113 -0
  114. package/dist/localEngineSpawn.js +486 -0
  115. package/dist/localEngineStep.d.ts +286 -0
  116. package/dist/localEngineStep.js +1086 -0
  117. package/dist/localEngineStopLadder.d.ts +29 -0
  118. package/dist/localEngineStopLadder.js +139 -0
  119. package/dist/localEngineSwapCard.d.ts +43 -0
  120. package/dist/localEngineSwapCard.js +205 -0
  121. package/dist/localEngineTiming.d.ts +8 -0
  122. package/dist/localEngineTiming.js +8 -0
  123. package/dist/mcpReconnect.js +12 -5
  124. package/dist/mcpWireCaps.js +2 -2
  125. package/dist/memoryEntriesWire.d.ts +1 -1
  126. package/dist/memoryEntriesWire.js +5 -0
  127. package/dist/model/catalogDefault.d.ts +25 -0
  128. package/dist/model/catalogDefault.js +44 -0
  129. package/dist/noticePresentation.d.ts +2 -0
  130. package/dist/noticePresentation.js +79 -1
  131. package/dist/ownKey.d.ts +10 -0
  132. package/dist/ownKey.js +15 -1
  133. package/dist/permissionWireCaps.d.ts +1 -0
  134. package/dist/permissionWireCaps.js +11 -0
  135. package/dist/pluginHooksWire.d.ts +5 -3
  136. package/dist/pluginHooksWire.js +116 -7
  137. package/dist/queuedDelivery.d.ts +1 -0
  138. package/dist/queuedDelivery.js +12 -0
  139. package/dist/resultFrameKeys.js +4 -2
  140. package/dist/resumeRefusalCopy.js +15 -8
  141. package/dist/ruleReadings.js +1 -1
  142. package/dist/runPermissionModeSwitch.d.ts +2 -1
  143. package/dist/runPermissionModeSwitch.js +16 -6
  144. package/dist/seam.d.ts +13 -2
  145. package/dist/seam.js +8 -1
  146. package/dist/seatContract.d.ts +103 -12
  147. package/dist/seatContract.js +344 -14
  148. package/dist/sessionBackground.js +2 -0
  149. package/dist/sessionEngine.d.ts +2 -1
  150. package/dist/sessionEngine.js +5 -0
  151. package/dist/settingsHooksSalvage.d.ts +5 -0
  152. package/dist/settingsHooksSalvage.js +54 -0
  153. package/dist/subagentContentStore.d.ts +12 -0
  154. package/dist/subagentContentStore.js +73 -12
  155. package/dist/supportFloor.js +2 -0
  156. package/dist/taskNotificationAdmission.d.ts +19 -0
  157. package/dist/taskNotificationAdmission.js +84 -0
  158. package/dist/toolResult.js +20 -6
  159. package/dist/webSearchWireCaps.js +9 -4
  160. package/dist/wireFailureShape.d.ts +20 -0
  161. package/dist/wireFailureShape.js +37 -6
  162. package/dist/wireRefusalCopy.d.ts +23 -2
  163. package/dist/wireRefusalCopy.js +93 -4
  164. package/docs/INTEGRATION-CLIENTS.md +1959 -15
  165. package/package.json +4 -4
@@ -7,7 +7,7 @@ import { retryStatusFromArm } from '../retryStatus.js';
7
7
  import { steeringInjectedToAttachments } from '../steering.js';
8
8
  import { projectDiagnosticsFrame } from '../diagnostics.js';
9
9
  import { recordEngineToolLabel } from '../engineToolLabelStore.js';
10
- import { registerSubagentAlias, registerSubagentContentAlias } from '../subagentContentStore.js';
10
+ import { applySubagentAlias } from '../subagentContentStore.js';
11
11
  import { readAsyncLaunchedAgentReceipt } from '../toolResult.js';
12
12
  import { recordWorkflowAgentTaskId } from '../workflow.js';
13
13
  import { isCoreTaskNotificationTerminal, isCoreTaskNotificationTerminalNotSuccess, isCoreTaskProgressTerminal, isCoreTaskProgressTerminalNotSuccess } from '../terminalStatuses.js';
@@ -15,7 +15,7 @@ import { readToolHistoryMismatchKey } from '../toolHistoryMismatch.js';
15
15
  import { isMintedRowCcError, readProviderRejectionResendKey } from '../providerRejection.js';
16
16
  import { rowKindOf } from '../rowKind.js';
17
17
  import { terminalCodedDetailOf } from '../runTerminal.js';
18
- import { contextUsageReadingOf, guardedRead, humanInputAttachmentsOf, ownSnapshotRecord, ownSnapshotWhenTyped, readOwnDataNonEmptyString, readOwnDataValue, promptManifestIdentityOfFrame, promptManifestSectionViewOf, readFrameStringKey, readFrameTrueMark, workflowCompletionExtrasOf } from '../ownKey.js';
18
+ import { contextUsageReadingOf, guardedRead, humanInputAttachmentsOf, humanInputAuthorKeys, ownSnapshotRecord, ownSnapshotWhenTyped, readOwnDataNonEmptyString, readOwnDataValue, promptManifestIdentityOfFrame, promptManifestSectionViewOf, readFrameStringKey, readFrameTrueMark, workflowCompletionExtrasOf } from '../ownKey.js';
19
19
  import { CORE_USER_ATTACHMENT_LABEL_MAX } from '../generated/engineFactTables.js';
20
20
  import { ESCAPE_FACE, paintAndCap, washCredentials } from '../displayUntrusted.js';
21
21
  import { resolveEnginePanelTaskId } from '../engineAgentPanelStore.js';
@@ -236,7 +236,9 @@ const userArm = function* (m, { ctx, idOf }) {
236
236
  return;
237
237
  yield transcript({ ...m, uuid: idOf(m), session_id: ctx.sessionId }, ctx.now());
238
238
  };
239
- const systemArm = function* (m, { ctx, idOf }) {
239
+ const systemArm = function* (m, { ctx, idOf, text }) {
240
+ if (readFrameStringKey(m, 'subtype') === 'compact_boundary')
241
+ text.noteModelSegmentBoundary();
240
242
  yield transcript(m, ctx.now());
241
243
  const attachedFiles = m._sema_attached_files;
242
244
  if (Array.isArray(attachedFiles)) {
@@ -325,13 +327,20 @@ const humanInputArm = function* (m) {
325
327
  ...(str(m.entryId) !== undefined ? { entryId: str(m.entryId) } : {}),
326
328
  ...(str(m.eventId) !== undefined ? { eventId: str(m.eventId) } : {}),
327
329
  ...humanInputAttachmentsForChrome(m),
330
+ ...humanInputAuthorKeys(m),
328
331
  });
329
332
  };
330
333
  function humanInputAttachmentsForChrome(m) {
331
334
  const rows = humanInputAttachmentsOf(m);
332
335
  if (rows === undefined)
333
336
  return {};
334
- return { attachments: rows.map((r) => (r.label !== undefined ? { ...r, label: paintAndCap(r.label, ESCAPE_FACE, CORE_USER_ATTACHMENT_LABEL_MAX) } : r)) };
337
+ return {
338
+ attachments: rows.map((r) => ({
339
+ ...r,
340
+ ...(r.label !== undefined ? { label: paintAndCap(r.label, ESCAPE_FACE, CORE_USER_ATTACHMENT_LABEL_MAX) } : {}),
341
+ ...(r.declinedBy !== undefined ? { declinedBy: { kind: r.declinedBy.kind, name: paintAndCap(r.declinedBy.name, ESCAPE_FACE, CORE_USER_ATTACHMENT_LABEL_MAX) } } : {}),
342
+ })),
343
+ };
335
344
  }
336
345
  const messageCommittedArm = function* (m) {
337
346
  if (typeof m.parentToolCallId === 'string')
@@ -623,6 +632,7 @@ const textSegmentEndArm = function* (m, { text }) {
623
632
  if (content.length === 0)
624
633
  return;
625
634
  text.anchorWindow(m);
635
+ yield* text.admitEndOnlyBlock(content, m);
626
636
  const r = text.replaceAnswerSegment(content, m);
627
637
  yield* text.drainLive();
628
638
  yield chrome({
@@ -677,8 +687,9 @@ const toolEndResultArm = function* (m, deps) {
677
687
  const structured = ownSnapshotWhenTyped(m.structured, 'task-output');
678
688
  if (callId !== undefined) {
679
689
  const launched = readAsyncLaunchedAgentReceipt(structured);
680
- if (launched !== null)
681
- registerSubagentContentAlias(callId, launched.taskId);
690
+ if (launched !== null && applySubagentAlias(callId, launched.taskId, 'content') !== 'rejected') {
691
+ yield chrome({ kind: 'subagent_alias', laneProof: { lane: 'subagent', parentToolCallId: callId }, parentToolCallId: callId, taskId: launched.taskId, scope: 'content' });
692
+ }
682
693
  }
683
694
  if (callId !== undefined && isUnsettledHeldToolEnd(m)) {
684
695
  const held = cards.detach(callId);
@@ -769,8 +780,12 @@ const taskProgressArm = function* (m, { ctx, cards, panel, inst }) {
769
780
  }));
770
781
  return;
771
782
  }
772
- if (explicitParent !== undefined)
773
- registerSubagentAlias(explicitParent, taskId);
783
+ if (explicitParent !== undefined) {
784
+ const aliasSeq = cycleSeqValue(m.seq);
785
+ if (applySubagentAlias(explicitParent, taskId, 'full', aliasSeq) !== 'rejected') {
786
+ yield chrome({ kind: 'subagent_alias', laneProof: { lane: 'subagent', parentToolCallId: explicitParent }, parentToolCallId: explicitParent, taskId, scope: 'full', ...(aliasSeq !== undefined ? { seq: aliasSeq } : {}) });
787
+ }
788
+ }
774
789
  const cardId = panel.bind(taskId, explicitParent);
775
790
  const usage = (m.usage ?? {});
776
791
  ctx.probe?.('tick', JSON.stringify({
@@ -18,6 +18,8 @@ interface ThinkingSegmentReplacement {
18
18
  }
19
19
  export interface TextStream {
20
20
  feedText(delta: string, frame: Frame): Generator<AdapterOutput>;
21
+ admitEndOnlyBlock(content: string, frame: Frame): Generator<AdapterOutput>;
22
+ noteModelSegmentBoundary(): void;
21
23
  feedThinking(delta: string, frame: Frame): Generator<AdapterOutput>;
22
24
  drainLive(): Generator<AdapterOutput>;
23
25
  takeThinking(): Generator<AdapterOutput>;
@@ -39,6 +39,10 @@ export function createTextStream(ctx, idOf) {
39
39
  let segmentCommitted = '';
40
40
  let previousSegmentCommitted = '';
41
41
  let segmentWindowCloseArmed = false;
42
+ let wholeBlockDelivered = false;
43
+ const closeWholeBlockMark = () => {
44
+ wholeBlockDelivered = false;
45
+ };
42
46
  const flushEveryMs = typeof ctx.coalesceIntervalMs === 'number' && ctx.coalesceIntervalMs >= 0
43
47
  ? ctx.coalesceIntervalMs
44
48
  : FLUSH_INTERVAL_MS;
@@ -122,6 +126,7 @@ export function createTextStream(ctx, idOf) {
122
126
  }
123
127
  function* takeAnswerSegment() {
124
128
  idleFlushUsedInSegment = false;
129
+ closeWholeBlockMark();
125
130
  yield* emitAnswerSegment();
126
131
  previousSegmentCommitted += segmentCommitted;
127
132
  segmentCommitted = '';
@@ -166,23 +171,37 @@ export function createTextStream(ctx, idOf) {
166
171
  textPending = '';
167
172
  }
168
173
  }
174
+ function* feedText(delta, frame) {
175
+ if (delta.length === 0 && segmentWindowCloseArmed && previousSegmentCommitted + segmentCommitted !== '')
176
+ return;
177
+ consumeArmedClose();
178
+ if (thinking.length > 0 || thinkingPending.length > 0) {
179
+ yield* drainLive();
180
+ yield* takeThinking();
181
+ }
182
+ if (answerSegment.length === 0)
183
+ segmentAnchor = frame;
184
+ segmentLast = frame;
185
+ openSegmentWindow(frame);
186
+ answer += delta;
187
+ answerSegment += delta;
188
+ textPending += delta;
189
+ }
190
+ function* admitEndOnlyBlock(content, frame) {
191
+ if (content.length === 0 || wholeBlockDelivered)
192
+ return;
193
+ const verdict = resolveTextSegmentAuthority(content, {
194
+ committedPrefix: previousSegmentCommitted + segmentCommitted,
195
+ openSegment: answerSegment,
196
+ });
197
+ if (verdict.form !== 'untouched')
198
+ return;
199
+ yield* feedText(content, frame);
200
+ }
169
201
  return {
170
- *feedText(delta, frame) {
171
- if (delta.length === 0 && segmentWindowCloseArmed && previousSegmentCommitted + segmentCommitted !== '')
172
- return;
173
- consumeArmedClose();
174
- if (thinking.length > 0 || thinkingPending.length > 0) {
175
- yield* drainLive();
176
- yield* takeThinking();
177
- }
178
- if (answerSegment.length === 0)
179
- segmentAnchor = frame;
180
- segmentLast = frame;
181
- openSegmentWindow(frame);
182
- answer += delta;
183
- answerSegment += delta;
184
- textPending += delta;
185
- },
202
+ feedText,
203
+ admitEndOnlyBlock,
204
+ noteModelSegmentBoundary: closeWholeBlockMark,
186
205
  *feedThinking(delta, frame) {
187
206
  if (thinkingSettled) {
188
207
  if (thinking.length > 0) {
@@ -335,6 +354,8 @@ export function createTextStream(ctx, idOf) {
335
354
  emittedAssistantText = true;
336
355
  if (typeof committed === 'string')
337
356
  committedText += committed;
357
+ if (typeof committed === 'string' && committed.length > 0)
358
+ wholeBlockDelivered = true;
338
359
  },
339
360
  replaceThinkingSegment: (content, anchor) => {
340
361
  const rows = committedThinking;
@@ -48,6 +48,7 @@ export type ReopenCardVerdict = {
48
48
  _sema_rowVerdict?: Exclude<CheckpointRowVerdictReading, {
49
49
  readonly kind: 'ok';
50
50
  }>;
51
+ _sema_rowDeadline?: number | null;
51
52
  } | {
52
53
  reopened: true;
53
54
  firstSight: boolean;
@@ -154,6 +155,7 @@ export type SelfHealOutcome = {
154
155
  rowVerdict?: Exclude<CheckpointRowVerdictReading, {
155
156
  readonly kind: 'ok';
156
157
  }>;
158
+ rowDeadline?: 'armed' | 'none';
157
159
  } | {
158
160
  kind: 'ask-decided-without-card';
159
161
  taskId: string;
@@ -5,8 +5,8 @@ import { registeredPlanReviewCardFacts } from '../planReviewCardFacts.js';
5
5
  import { DEFAULT_SESSION_KEY } from '../sessionSlot.js';
6
6
  import { ASK_PARK_AUTO_REOPEN_BLOCKS, askParkAutoReopenBlockedContent } from '../hitl/askParkAutoReopenBlock.js';
7
7
  import { corruptStoredRowContent, corruptStoredRowWhere, effectiveWireErrorCode } from '../wireErrorTriage.js';
8
- import { readThrownStatusSlot } from '../wireFailureShape.js';
9
- import { checkpointRowBarOf, checkpointRowBarSentence } from '../checkpointRowVerdict.js';
8
+ import { readThrownStatusSlot, slotReadOf } from '../wireFailureShape.js';
9
+ import { checkpointDeadlineStateOf, checkpointRowBarOf, checkpointRowBarSentence, rowBarWayOutContent } from '../checkpointRowVerdict.js';
10
10
  import { guardedRead, readOwnDataNonEmptyString, readOwnDataValue } from '../ownKey.js';
11
11
  import { steerBodyOf, UNOBSERVED_STEER_PRIORITY } from '../controlRouter.js';
12
12
  import { atMostOnceFailureClass } from '../atMostOnce.js';
@@ -215,6 +215,7 @@ const REOPEN_VERDICT_KEYS = [
215
215
  '_sema_reopenRefusal',
216
216
  '_sema_policyBlocked',
217
217
  '_sema_rowVerdict',
218
+ '_sema_rowDeadline',
218
219
  ];
219
220
  function snapshotReopenVerdict(raw) {
220
221
  if (raw === null || raw === undefined)
@@ -338,6 +339,20 @@ function reopenRowVerdictOf(verdict) {
338
339
  return undefined;
339
340
  }
340
341
  }
342
+ function reopenRowDeadlineStateOf(verdict) {
343
+ try {
344
+ if (verdict.reopened !== false)
345
+ return undefined;
346
+ const slot = slotReadOf(verdict, '_sema_rowDeadline');
347
+ if (slot.presence !== 'present')
348
+ return undefined;
349
+ const state = checkpointDeadlineStateOf({ deadline: slot.value });
350
+ return state === 'unknown' ? undefined : state;
351
+ }
352
+ catch {
353
+ return undefined;
354
+ }
355
+ }
341
356
  function reopenRefusalOf(verdict) {
342
357
  try {
343
358
  if (verdict.reopened !== false)
@@ -722,6 +737,7 @@ async function askParkArm(taskId, signal, runs, carrierVerdict, deps) {
722
737
  const noView = reopenRefusedForNoPresentationSurface(verdict);
723
738
  const policyBlocked = inFlight || noView ? undefined : reopenPolicyBlockedOf(verdict);
724
739
  const rowVerdict = inFlight ? undefined : reopenRowVerdictOf(verdict);
740
+ const rowDeadline = rowVerdict !== undefined ? reopenRowDeadlineStateOf(verdict) : undefined;
725
741
  const errorCode = inFlight || noView || reopenRefusedForUserDismissal(verdict) || policyBlocked !== undefined || rowVerdict !== undefined ? undefined : reopenErrorCodeOf(verdict);
726
742
  return {
727
743
  kind: 'ask-reopen-failed',
@@ -733,6 +749,7 @@ async function askParkArm(taskId, signal, runs, carrierVerdict, deps) {
733
749
  ...(errorCode !== undefined ? { errorCode } : {}),
734
750
  ...(policyBlocked !== undefined ? { policyBlocked } : {}),
735
751
  ...(rowVerdict !== undefined ? { rowVerdict } : {}),
752
+ ...(rowDeadline !== undefined ? { rowDeadline } : {}),
736
753
  };
737
754
  }
738
755
  async function probeRunStatusOnce(taskId, durable, durableGet, deps) {
@@ -1214,8 +1231,8 @@ function activeRunSelfHealBaseRow(outcome, wayOut, following = false, keepSessio
1214
1231
  if (outcome.rowVerdict !== undefined) {
1215
1232
  return say(lang, 'session.selfHeal.row.askReopenFailed.rowUnresumable', {
1216
1233
  taskId: outcome.taskId,
1217
- sentence: checkpointRowBarSentence(outcome.rowVerdict),
1218
- unbound: msg('approval.decide.unboundWayOut'),
1234
+ sentence: checkpointRowBarSentence(outcome.rowVerdict, lang),
1235
+ unbound: rowBarWayOutContent(outcome.rowVerdict, outcome.rowDeadline ?? 'unknown', lang),
1219
1236
  });
1220
1237
  }
1221
1238
  if (outcome.policyBlocked !== undefined)
@@ -5,7 +5,7 @@ import { ccToolDenialKindForToolEnd, gateOutcomeOf, toolInputRewriteOf } from '.
5
5
  import { projectToolRoster, projectToolRosterDelta } from '../../toolRoster.js';
6
6
  import { projectHandsSection } from '../../handsSeam.js';
7
7
  import { readMcpAuthorization, readMcpLiveness } from '../../mcpLiveness.js';
8
- import { contextUsageReadingOf, humanInputAttachmentsOf, guardedRead, markMcpSectionDroppedNamedRows, ownSnapshotTyped, promptManifestIdentityOfFrame, promptManifestSectionViewOf, readFrameStringKey, readFrameTrueMark, readOwnDataFiniteNumber, readOwnDataNonEmptyString, workflowCompletionExtrasOf } from '../../ownKey.js';
8
+ import { contextUsageReadingOf, humanInputAttachmentsOf, humanInputAuthorKeys, guardedRead, markMcpSectionDroppedNamedRows, ownSnapshotTyped, promptManifestIdentityOfFrame, promptManifestSectionViewOf, readFrameStringKey, readFrameTrueMark, readOwnDataFiniteNumber, readOwnDataNonEmptyString, workflowCompletionExtrasOf } from '../../ownKey.js';
9
9
  import { SEGMENT_END_IDENTITY_KEYS, eventSeq, stripToolUseSideChannels } from '../types.js';
10
10
  import { frozenSet } from '../../frozenSet.js';
11
11
  import { isCoreWorkflowRunTerminal } from '../../terminalStatuses.js';
@@ -954,6 +954,7 @@ function humanInputProjection(ev, ctx) {
954
954
  ...(str(ev.eventId) !== undefined ? { eventId: str(ev.eventId) } : {}),
955
955
  ...(str(ev.parentToolCallId) !== undefined ? { parentToolCallId: str(ev.parentToolCallId) } : {}),
956
956
  ...attachmentsKey(humanInputAttachmentsOf(ev)),
957
+ ...humanInputAuthorKeys(ev),
957
958
  })));
958
959
  }
959
960
  function attachmentsKey(rows) {
@@ -77,6 +77,7 @@ function readRow(v) {
77
77
  const description = Object.hasOwn(o, 'description') ? o.description : undefined;
78
78
  const createdAt = Object.hasOwn(o, 'createdAt') ? o.createdAt : undefined;
79
79
  const childSessionId = type === 'background_agent' ? guardedRead(() => readOwnDataValue(o, 'sessionId')) : undefined;
80
+ const retained = guardedRead(() => readOwnDataValue(o, 'retained')) === true;
80
81
  return {
81
82
  id,
82
83
  type,
@@ -84,6 +85,7 @@ function readRow(v) {
84
85
  ...(typeof description === 'string' && description.length > 0 ? { description } : {}),
85
86
  ...(typeof createdAt === 'number' && Number.isFinite(createdAt) ? { createdAt } : {}),
86
87
  ...(typeof childSessionId === 'string' && childSessionId.length > 0 ? { sessionId: childSessionId } : {}),
88
+ ...(retained ? { retained: true } : {}),
87
89
  };
88
90
  }
89
91
  export async function readEngineAgentRegistry(client, sessionId, capsBaseUrl, opts) {
@@ -8,3 +8,15 @@ export interface BashExitReading {
8
8
  }
9
9
  export declare function bashExitOf(structured: unknown, parseFrame: () => BashFrameExit | null): BashExitReading;
10
10
  export declare function bashExitReadingFailed(r: BashExitReading): boolean;
11
+ export type BashCurtailmentKind = 'timedOut' | 'livenessNoOutput' | 'aborted' | 'callbackError';
12
+ export interface BashCurtailment {
13
+ readonly kind: BashCurtailmentKind;
14
+ readonly timeoutSec?: number;
15
+ readonly noOutputSec?: number;
16
+ }
17
+ export declare function bashCurtailmentOf(structured: unknown): BashCurtailment | undefined;
18
+ export declare function bashCurtailmentSentence(c: BashCurtailment): string;
19
+ export declare function bashCurtailedResultPart(stderr: string, c: BashCurtailment | undefined): {
20
+ stderr: string;
21
+ _sema_curtailed?: BashCurtailment;
22
+ };
@@ -1,3 +1,4 @@
1
+ import { guardedRead, readOwnDataValue } from './ownKey.js';
1
2
  export function bashExitOf(structured, parseFrame) {
2
3
  const s = typeof structured === 'object' && structured !== null ? structured : undefined;
3
4
  const interp = typeof s?.returnCodeInterpretation === 'string' && s.returnCodeInterpretation.length > 0 ? s.returnCodeInterpretation : undefined;
@@ -10,3 +11,46 @@ export function bashExitOf(structured, parseFrame) {
10
11
  export function bashExitReadingFailed(r) {
11
12
  return r.exitCode !== null && r.exitCode !== 0 && r.benignNote === undefined;
12
13
  }
14
+ export function bashCurtailmentOf(structured) {
15
+ if (typeof structured !== 'object' || structured === null)
16
+ return undefined;
17
+ const own = (key) => guardedRead(() => readOwnDataValue(structured, key));
18
+ if (own('type') !== 'bash')
19
+ return undefined;
20
+ const secOf = (key) => {
21
+ const v = own(key);
22
+ return typeof v === 'number' && Number.isSafeInteger(v) && v >= 0 ? (v === 0 ? 0 : v) : undefined;
23
+ };
24
+ if (own('timedOut') === true) {
25
+ const timeoutSec = secOf('timeoutSec');
26
+ return timeoutSec === undefined ? { kind: 'timedOut' } : { kind: 'timedOut', timeoutSec };
27
+ }
28
+ if (own('livenessNoOutput') === true) {
29
+ const noOutputSec = secOf('noOutputSec');
30
+ return noOutputSec === undefined ? { kind: 'livenessNoOutput' } : { kind: 'livenessNoOutput', noOutputSec };
31
+ }
32
+ if (own('aborted') === true)
33
+ return { kind: 'aborted' };
34
+ if (own('callbackError') === true)
35
+ return { kind: 'callbackError' };
36
+ return undefined;
37
+ }
38
+ export function bashCurtailmentSentence(c) {
39
+ switch (c.kind) {
40
+ case 'timedOut':
41
+ return c.timeoutSec === undefined ? 'Command timed out' : `Command timed out after ${c.timeoutSec}s`;
42
+ case 'livenessNoOutput':
43
+ return c.noOutputSec === undefined ? 'Command killed: no output' : `Command killed: no output for ${c.noOutputSec}s`;
44
+ case 'aborted':
45
+ return 'Command was interrupted';
46
+ case 'callbackError':
47
+ return 'Command ended: output stream failed';
48
+ }
49
+ }
50
+ export function bashCurtailedResultPart(stderr, c) {
51
+ if (c === undefined)
52
+ return { stderr };
53
+ const sentence = bashCurtailmentSentence(c);
54
+ const alreadyLeads = stderr.startsWith(sentence) && stderr.charAt(sentence.length).trim() === '';
55
+ return { stderr: stderr.length === 0 ? sentence : alreadyLeads ? stderr : `${sentence} ${stderr}`, _sema_curtailed: { ...c } };
56
+ }
@@ -1,3 +1,4 @@
1
+ import { type UiLanguage } from './env/uiLanguage.js';
1
2
  export type CheckpointRowVerdictReading = {
2
3
  readonly kind: 'ok';
3
4
  } | {
@@ -26,4 +27,8 @@ export type CheckpointRowBar = Exclude<CheckpointRowVerdictReading, {
26
27
  }>;
27
28
  export declare function checkpointRowBarOf(row: object | null | undefined): CheckpointRowBar | undefined;
28
29
  export declare const CHECKPOINT_ROW_BAR_SENTENCE: string;
29
- export declare function checkpointRowBarSentence(bar: CheckpointRowBar): string;
30
+ export declare function checkpointRowBarSentence(bar: CheckpointRowBar, lang?: UiLanguage | (string & {})): string;
31
+ export type CheckpointDeadlineState = 'armed' | 'none' | 'unknown';
32
+ export declare function checkpointDeadlineStateOf(row: object | null | undefined): CheckpointDeadlineState;
33
+ export declare function unboundWayOutContent(state: CheckpointDeadlineState, lang?: UiLanguage | (string & {})): string;
34
+ export declare function rowBarWayOutContent(bar: CheckpointRowBar, state: CheckpointDeadlineState, lang?: UiLanguage | (string & {})): string;
@@ -1,5 +1,6 @@
1
1
  import { readErrorString, slotReadOf } from './wireFailureShape.js';
2
2
  import { msg, renderMessage } from './i18n/translate.js';
3
+ import { isUiLanguage } from './env/uiLanguage.js';
3
4
  const UNREADABLE = Object.freeze({ kind: 'unreadable' });
4
5
  const OK = Object.freeze({ kind: 'ok' });
5
6
  function ownNonEmptyString(o, key) {
@@ -93,6 +94,33 @@ export function checkpointRowBarOf(row) {
93
94
  return v === undefined || v.kind === 'ok' ? undefined : v;
94
95
  }
95
96
  export const CHECKPOINT_ROW_BAR_SENTENCE = renderMessage(msg('approval.rowUnresumable.fallback'));
96
- export function checkpointRowBarSentence(bar) {
97
- return bar.kind !== 'unreadable' && typeof bar.sentence === 'string' && bar.sentence !== '' ? bar.sentence : CHECKPOINT_ROW_BAR_SENTENCE;
97
+ export function checkpointRowBarSentence(bar, lang) {
98
+ return bar.kind !== 'unreadable' && typeof bar.sentence === 'string' && bar.sentence !== ''
99
+ ? bar.sentence
100
+ : renderMessage(msg('approval.rowUnresumable.fallback'), isUiLanguage(lang) ? lang : undefined);
101
+ }
102
+ export function checkpointDeadlineStateOf(row) {
103
+ try {
104
+ if (typeof row !== 'object' || row === null)
105
+ return 'unknown';
106
+ const r = slotReadOf(row, 'deadline');
107
+ if (r.presence !== 'present')
108
+ return 'unknown';
109
+ const v = r.value;
110
+ if (v === null)
111
+ return 'none';
112
+ return typeof v === 'number' && Number.isFinite(v) && v >= 0 ? 'armed' : 'unknown';
113
+ }
114
+ catch {
115
+ return 'unknown';
116
+ }
117
+ }
118
+ export function unboundWayOutContent(state, lang) {
119
+ const key = state === 'armed' ? 'approval.decide.unboundWayOut.armed' : state === 'none' ? 'approval.decide.unboundWayOut.none' : 'approval.decide.unboundWayOut.unknown';
120
+ return renderMessage(msg(key), isUiLanguage(lang) ? lang : undefined);
121
+ }
122
+ export function rowBarWayOutContent(bar, state, lang) {
123
+ if (bar.kind === 'lacking')
124
+ return renderMessage(msg('approval.rowUnresumable.lackingWayOut'), isUiLanguage(lang) ? lang : undefined);
125
+ return unboundWayOutContent(state, lang);
98
126
  }
@@ -63,6 +63,15 @@ export interface CloudExecutionProjection {
63
63
  }
64
64
  export declare function cloudExecutionToPolicy(execution: unknown): CloudExecutionProjection;
65
65
  export declare function cloudRosterNames(rostersValue: unknown): string[];
66
+ export type CloudA2aReading = {
67
+ readonly kind: 'present';
68
+ readonly peerNames: readonly string[];
69
+ readonly unreadableRows: number;
70
+ } | {
71
+ readonly kind: 'absent';
72
+ } | {
73
+ readonly kind: 'unreadable';
74
+ };
66
75
  export interface CloudEffectiveWarning {
67
76
  readonly kind: string;
68
77
  readonly domain?: string;
@@ -137,6 +146,7 @@ export interface CloudProjection {
137
146
  budget: CloudBudgetReading;
138
147
  runtimeCaps: CloudRuntimeCapsReading;
139
148
  modelRefIssues: CloudModelRefIssue[];
149
+ a2a: CloudA2aReading;
140
150
  }
141
151
  export declare function projectEffectiveBody(body: unknown, skillBodies: Record<string, string>, env: EnvLike, rostersValue?: unknown, opts?: CloudModelsDocOptions, skills?: CloudSkillsOptions): CloudProjection;
142
152
  export interface CloudEffectiveNotice {
@@ -1,6 +1,7 @@
1
1
  import { mcpAllowToolsVerdict, mcpAssertionHeaderNotSentNotice, mcpElicitationVerdict, mcpToolAxesVerdict, mcpToolFacesVerdict, readMcpHttpIdentityHeaders } from './mcpWireCaps.js';
2
2
  import { skillToolListsVerdict, toCappedSpec } from './skillsWireCaps.js';
3
3
  import { SETTINGS_DESCRIBE_BAD_MCP_SERVER_NAME, SETTINGS_IS_USABLE_MCP_SERVER_NAME, SETTINGS_READ_REQUEST_MCP_TRANSPORT } from './generated/settingsSchemaFns.js';
4
+ import { SETTINGS_IS_USABLE_WIRE_NAME } from './generated/settingsSchemaFns.js';
4
5
  import { snapshotArgs, wireTransportOf } from './mcpWireTransport.js';
5
6
  import { msg, renderMessage } from './i18n/translate.js';
6
7
  import { TIER_ORDER } from './model/tierVocabulary.js';
@@ -8,6 +9,7 @@ import { SETTINGS_NARROW_AT_MENTION } from './generated/settingsSchemaFns.js';
8
9
  import { modelsPolicyOf } from './model/modelsPolicy.js';
9
10
  import { normalizeEngineBaseUrl } from './engineUrl.js';
10
11
  import { guardedRead, readOwnDataNonEmptyString, readOwnDataValue } from './ownKey.js';
12
+ import { slotReadOf } from './wireFailureShape.js';
11
13
  import { capForDisplay } from './fleetTaskDesc.js';
12
14
  import { SETTINGS_BUDGET_NUMBER_KEYS, SETTINGS_BUDGET_PER_MODEL_NUMBER_KEYS, SETTINGS_BUDGET_STRING_KEYS, SETTINGS_TIER_GROUP_NAME_RE, } from './generated/settingsSchemaTables.js';
13
15
  const asRec = (v) => (typeof v === 'object' && v !== null && !Array.isArray(v) ? v : undefined);
@@ -535,6 +537,36 @@ export function cloudRosterNames(rostersValue) {
535
537
  .map((e) => asStr(asRec(e)?.name))
536
538
  .filter((n) => !!n);
537
539
  }
540
+ function cloudA2aOf(body) {
541
+ const cfg = slotReadOf(body, 'config');
542
+ const config = cfg.presence === 'present' ? guardedRead(() => asRec(cfg.value)) : undefined;
543
+ if (config === undefined)
544
+ return { kind: 'unreadable' };
545
+ const slot = slotReadOf(config, 'a2a');
546
+ if (slot.presence === 'absent')
547
+ return { kind: 'absent' };
548
+ const domain = slot.presence === 'present' ? guardedRead(() => asRec(slot.value)) : undefined;
549
+ if (domain === undefined)
550
+ return { kind: 'unreadable' };
551
+ const peersSlot = slotReadOf(domain, 'peers');
552
+ if (peersSlot.presence === 'absent')
553
+ return { kind: 'present', peerNames: [], unreadableRows: 0 };
554
+ const peers = peersSlot.presence === 'present' ? guardedRead(() => (Array.isArray(peersSlot.value) ? peersSlot.value : undefined)) : undefined;
555
+ const count = peers === undefined ? undefined : guardedRead(() => readOwnDataValue(peers, 'length'));
556
+ if (peers === undefined || typeof count !== 'number' || !Number.isSafeInteger(count) || count < 0)
557
+ return { kind: 'unreadable' };
558
+ const peerNames = [];
559
+ let unreadableRows = 0;
560
+ for (let i = 0; i < count; i++) {
561
+ const row = guardedRead(() => readOwnDataValue(peers, String(i)));
562
+ const name = typeof row === 'object' && row !== null ? guardedRead(() => readOwnDataValue(row, 'name')) : undefined;
563
+ if (typeof name === 'string' && SETTINGS_IS_USABLE_WIRE_NAME(name))
564
+ peerNames.push(name);
565
+ else
566
+ unreadableRows += 1;
567
+ }
568
+ return { kind: 'present', peerNames, unreadableRows };
569
+ }
538
570
  const BUDGET_NUMBER_KEYS = SETTINGS_BUDGET_NUMBER_KEYS;
539
571
  const BUDGET_STRING_KEYS = SETTINGS_BUDGET_STRING_KEYS;
540
572
  const PER_MODEL_NUMBER_KEYS = SETTINGS_BUDGET_PER_MODEL_NUMBER_KEYS;
@@ -702,6 +734,7 @@ export function projectEffectiveBody(body, skillBodies, env, rostersValue, opts,
702
734
  budget: budgetOf(b, view),
703
735
  runtimeCaps: runtimeCapsOf(b, view),
704
736
  modelRefIssues,
737
+ a2a: cloudA2aOf(b),
705
738
  };
706
739
  }
707
740
  const quoted = (s, fallback) => (s === undefined ? fallback : `the "${s}" settings`);
@@ -118,7 +118,7 @@ export const MIGRATED_COMPENSATIONS = [
118
118
  id: 'T49',
119
119
  what: 'subagent alias 只能在 tick 上学 —— content 帧只带 parentToolCallId、没有 taskId',
120
120
  disposition: 'in-library',
121
- libraryHalf: 'adapt.ts task_progress 臂 registerSubagentAlias(explicitParent, taskId)',
121
+ libraryHalf: 'adapt.ts task_progress 臂 applySubagentAlias(explicitParent, taskId, \'full\')(与 registerSubagentAlias 同一实现)',
122
122
  chromeArm: null,
123
123
  hostHalf: null,
124
124
  retireOn: 'RL-40',
@@ -153,6 +153,7 @@ export interface CoreValuePorts {
153
153
  IMPORTED_SETTINGS_LAYERS: readonly ['userSettings', 'projectSettings', 'localSettings'];
154
154
  runParkedOf(run: WorkflowRunParkedInputView): boolean;
155
155
  parkedAgentsOf(agents: ReadonlyArray<WorkflowAgentStatusView>): WorkflowAgentStatusView[];
156
+ modelFaceResolvable(face: object, options?: ModelFaceOptionsView): ModelFaceVerdictView;
156
157
  }
157
158
  export interface WorkflowAgentStatusView {
158
159
  readonly status: string;
@@ -161,7 +162,21 @@ export interface WorkflowRunParkedInputView {
161
162
  readonly status: string;
162
163
  readonly agents: ReadonlyArray<WorkflowAgentStatusView>;
163
164
  }
164
- export declare const CORE_VALUE_PORT_NAMES: readonly ["resolveAutonomousLoopPrompt", "loosenReasons", "combinePolicies", "createAllowDenyPolicy", "MCP_NAMESPACE", "protocolOf", "ruleToolGrammarOf", "validatePermissionRules", "mintNamespacePrefix", "compileAllowList", "routeKeyOf", "joinRequestUrl", "resolveRouteCredential", "adjudicateModelRoute", "routePairingStatus", "judgeRuleToolName", "readRuleEntry", "readMcpToolAxes", "ANTHROPIC_DEFAULT_BASE_URL", "readToolFaces", "ruleNameCovers", "IMPORTED_SETTINGS_LAYERS", "runParkedOf", "parkedAgentsOf"];
165
+ export interface ModelFaceOptionsView {
166
+ readonly spec?: {
167
+ readonly model?: string | object;
168
+ readonly modelRole?: string;
169
+ };
170
+ readonly when?: readonly ('per-task' | 'deployment')[];
171
+ }
172
+ export type ModelFaceVerdictView = {
173
+ readonly ok: true;
174
+ } | {
175
+ readonly ok: false;
176
+ readonly role: string;
177
+ readonly code: string;
178
+ };
179
+ export declare const CORE_VALUE_PORT_NAMES: readonly ["resolveAutonomousLoopPrompt", "loosenReasons", "combinePolicies", "createAllowDenyPolicy", "MCP_NAMESPACE", "protocolOf", "ruleToolGrammarOf", "validatePermissionRules", "mintNamespacePrefix", "compileAllowList", "routeKeyOf", "joinRequestUrl", "resolveRouteCredential", "adjudicateModelRoute", "routePairingStatus", "judgeRuleToolName", "readRuleEntry", "readMcpToolAxes", "ANTHROPIC_DEFAULT_BASE_URL", "readToolFaces", "ruleNameCovers", "IMPORTED_SETTINGS_LAYERS", "runParkedOf", "parkedAgentsOf", "modelFaceResolvable"];
165
180
  export type CoreValuePortName = (typeof CORE_VALUE_PORT_NAMES)[number];
166
181
  export declare function installCoreValuePorts(ports: Partial<CoreValuePorts> | null): () => void;
167
182
  export declare function hasCoreValuePorts(): boolean;
@@ -195,3 +210,4 @@ export declare function ruleNameCovers(ruleName: string, toolName: string): bool
195
210
  export declare function importedSettingsLayers(): CoreValuePorts['IMPORTED_SETTINGS_LAYERS'] | undefined;
196
211
  export declare function runParkedOf(run: WorkflowRunParkedInputView): boolean | undefined;
197
212
  export declare function parkedAgentsOf(agents: ReadonlyArray<WorkflowAgentStatusView>): WorkflowAgentStatusView[] | undefined;
213
+ export declare function modelFaceResolvable(face: object, options?: ModelFaceOptionsView): ModelFaceVerdictView | undefined;
@@ -23,6 +23,7 @@ export const CORE_VALUE_PORT_NAMES = Object.freeze([
23
23
  'IMPORTED_SETTINGS_LAYERS',
24
24
  'runParkedOf',
25
25
  'parkedAgentsOf',
26
+ 'modelFaceResolvable',
26
27
  ]);
27
28
  let installed = null;
28
29
  export function installCoreValuePorts(ports) {
@@ -137,3 +138,7 @@ export function parkedAgentsOf(agents) {
137
138
  const fn = port('parkedAgentsOf');
138
139
  return fn === undefined ? undefined : fn(agents);
139
140
  }
141
+ export function modelFaceResolvable(face, options) {
142
+ const fn = port('modelFaceResolvable');
143
+ return fn === undefined ? undefined : fn(face, options);
144
+ }
@@ -9,6 +9,7 @@ import { askRowEndingCauseFor } from './hitl/approvalEndingCause.js';
9
9
  import { SDK_DECIDE_BINDING_KEYS } from './generated/sdkFactTables.js';
10
10
  import { isUiLanguage } from './env/uiLanguage.js';
11
11
  import { msg, renderMessage } from './i18n/translate.js';
12
+ import { unboundWayOutContent } from './checkpointRowVerdict.js';
12
13
  const STATUS_RESUMING = 'resuming';
13
14
  function str(v) {
14
15
  return typeof v === 'string' && v.length > 0 ? v : undefined;
@@ -162,7 +163,7 @@ export function decideRequiresBindingFromError(e) {
162
163
  }
163
164
  }
164
165
  export function decideRequiresBindingContent(_detail, lang) {
165
- return renderMessage(msg('approval.decide.requiresBinding', { wayOut: msg('approval.decide.unboundWayOut') }), isUiLanguage(lang) ? lang : undefined);
166
+ return renderMessage(msg('approval.decide.requiresBinding', { wayOut: unboundWayOutContent('unknown', lang) }), isUiLanguage(lang) ? lang : undefined);
166
167
  }
167
168
  function askGoneRawCause(e) {
168
169
  let top;
@@ -56,6 +56,7 @@ export interface EngineAgentRegistryRowView {
56
56
  readonly description?: string;
57
57
  readonly createdAt?: number;
58
58
  readonly sessionId?: string;
59
+ readonly retained?: true;
59
60
  }
60
61
  export type EngineAgentRegistryUnavailableWhy = 'no_list_face' | 'capability_unknown' | 'route_absent' | 'ownership_required' | 'read_failed';
61
62
  export type EngineAgentRegistryListing = {
@@ -75,6 +76,7 @@ export interface EngineAgentRegistryReadingOptions {
75
76
  readonly sessionId?: string;
76
77
  }
77
78
  export declare function engineAgentRegistryReadingOf(listing: EngineAgentRegistryListing | null | undefined, registryKey: string | null | undefined, opts?: EngineAgentRegistryReadingOptions | null): EngineAgentRegistryReading;
79
+ export declare function localEngineSessionShellsOf(listings: readonly (EngineAgentRegistryListing | null | undefined)[]): number | 'unknown';
78
80
  export interface EngineAgentRegistryMissingRow {
79
81
  readonly id: string;
80
82
  readonly status: string;
@@ -214,6 +214,34 @@ function readingFromRecord(rec, registryKey, opts) {
214
214
  const single = ownOpt(opts, 'singleReplica');
215
215
  return single.given && single.value === true && REGISTRY_AGENT_HANDLE_RE.test(registryKey) ? 'not_listed' : 'unknown';
216
216
  }
217
+ const SESSION_SHELL_TYPES = new Set(Object.keys({ background_bash: true, monitor: true }));
218
+ export function localEngineSessionShellsOf(listings) {
219
+ try {
220
+ if (!Array.isArray(listings))
221
+ return 'unknown';
222
+ let count = 0;
223
+ for (let i = 0; i < listings.length; i++) {
224
+ if (!Object.hasOwn(listings, i))
225
+ return 'unknown';
226
+ const rec = registryListingProvenanceOf(listings[i]);
227
+ if (rec === undefined || rec.superseded || rec.rawRowCount >= REGISTRY_LIST_LIMIT)
228
+ return 'unknown';
229
+ for (const r of rec.rows) {
230
+ if (!SESSION_SHELL_TYPES.has(r.type) || r.retained === true)
231
+ continue;
232
+ const reading = registryStatusReading(r.status);
233
+ if (reading === 'unknown')
234
+ return 'unknown';
235
+ if (reading === 'running')
236
+ count++;
237
+ }
238
+ }
239
+ return count;
240
+ }
241
+ catch {
242
+ return 'unknown';
243
+ }
244
+ }
217
245
  function keySetOf(v) {
218
246
  if (v instanceof Set)
219
247
  return (k) => v.has(k);