@sema-agent/client-core 0.95.0 → 0.97.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 (233) hide show
  1. package/CHANGELOG.md +269 -0
  2. package/README.md +61 -31
  3. package/dist/adapt/arms.js +7 -1
  4. package/dist/adapt/toolCards.d.ts +1 -0
  5. package/dist/adapt/toolCards.js +16 -3
  6. package/dist/adapt/wireShapes.js +2 -16
  7. package/dist/adapter/activeRunSelfHeal.d.ts +4 -2
  8. package/dist/adapter/activeRunSelfHeal.js +32 -6
  9. package/dist/adapter/downstream/eventToSdkMessage.js +11 -3
  10. package/dist/adapter/downstream/terminalToSdkResult.js +14 -11
  11. package/dist/adapter/runStream.js +30 -47
  12. package/dist/agentSession/backgroundView.js +2 -15
  13. package/dist/agentSession/engineAgentRegistryRead.js +5 -4
  14. package/dist/agentSession/engineSessionBackgroundStop.js +22 -15
  15. package/dist/agentsWireCaps.d.ts +1 -1
  16. package/dist/agentsWireCaps.js +29 -12
  17. package/dist/approvalDecidedByCapability.d.ts +2 -0
  18. package/dist/approvalDecidedByCapability.js +0 -1
  19. package/dist/approvalsStreamLiveCapability.d.ts +2 -0
  20. package/dist/approvalsStreamLiveCapability.js +3 -2
  21. package/dist/attachmentSeatCapability.d.ts +2 -0
  22. package/dist/attachmentSeatCapability.js +0 -1
  23. package/dist/callerCwdCapability.d.ts +2 -4
  24. package/dist/callerCwdCapability.js +0 -7
  25. package/dist/centerWiringCapability.d.ts +2 -4
  26. package/dist/centerWiringCapability.js +4 -9
  27. package/dist/classifierVerdictWire.js +4 -16
  28. package/dist/clientSlice.js +1 -1
  29. package/dist/cloudConfigWireCaps.d.ts +4 -4
  30. package/dist/cloudConfigWireCaps.js +241 -85
  31. package/dist/coreValuePorts.d.ts +11 -7
  32. package/dist/coreValuePorts.js +5 -8
  33. package/dist/credentialProvenance.d.ts +28 -0
  34. package/dist/credentialProvenance.js +76 -0
  35. package/dist/decideFailureNote.js +3 -1
  36. package/dist/decideReceipt.js +7 -10
  37. package/dist/declared/supportFloorDeclared.js +3 -3
  38. package/dist/deviceExecutorManagementCapability.d.ts +2 -0
  39. package/dist/deviceExecutorManagementCapability.js +3 -2
  40. package/dist/displayUntrusted.d.ts +10 -3
  41. package/dist/displayUntrusted.js +371 -60
  42. package/dist/engineCapReader.d.ts +8 -2
  43. package/dist/engineCapReader.js +15 -7
  44. package/dist/engineCapsCache.d.ts +17 -3
  45. package/dist/engineCapsCache.js +268 -43
  46. package/dist/engineDirectory.d.ts +79 -0
  47. package/dist/engineDirectory.js +186 -0
  48. package/dist/engineErrorCodes.d.ts +17 -1
  49. package/dist/engineErrorCodes.js +46 -16
  50. package/dist/engineNoticeCodes.d.ts +17 -0
  51. package/dist/engineNoticeCodes.js +54 -1
  52. package/dist/executionLaneCapability.d.ts +2 -0
  53. package/dist/executionLaneCapability.js +3 -2
  54. package/dist/fileHistoryCaptureCapability.d.ts +16 -0
  55. package/dist/fileHistoryCaptureCapability.js +98 -2
  56. package/dist/fileHistoryLegNotice.js +4 -0
  57. package/dist/fleet/bgSubagentRow.d.ts +15 -0
  58. package/dist/fleet/bgSubagentRow.js +67 -0
  59. package/dist/fleet/fleetLedger.d.ts +1 -0
  60. package/dist/fleet/fleetLedger.js +164 -126
  61. package/dist/fleet/fleetProjection.d.ts +1 -0
  62. package/dist/fleet/fleetProjection.js +10 -3
  63. package/dist/fleetTaskDesc.js +4 -17
  64. package/dist/gateOutcome.d.ts +12 -1
  65. package/dist/gateOutcome.js +56 -1
  66. package/dist/gateVocabulary.d.ts +2 -2
  67. package/dist/gateVocabulary.js +4 -3
  68. package/dist/generated/engineAskFaceTables.js +1 -1
  69. package/dist/generated/engineFactTables.d.ts +5 -3
  70. package/dist/generated/engineFactTables.js +17 -4
  71. package/dist/generated/engineNoticeTables.js +12 -3
  72. package/dist/generated/sdkFactTables.d.ts +2 -0
  73. package/dist/generated/sdkFactTables.js +7 -0
  74. package/dist/generated/settingsSchemaFns.d.ts +3 -0
  75. package/dist/generated/settingsSchemaFns.js +53 -0
  76. package/dist/generated/toolNameTables.d.ts +1 -1
  77. package/dist/generated/toolNameTables.js +1 -42
  78. package/dist/hitl/approvalDecisionNoteAudit.js +2 -2
  79. package/dist/hitl/approvalEndingCause.d.ts +2 -0
  80. package/dist/hitl/approvalEndingCause.js +26 -21
  81. package/dist/hitl/approvalHolds.d.ts +16 -1
  82. package/dist/hitl/approvalHolds.js +52 -12
  83. package/dist/hitl/askGateWire.js +1 -0
  84. package/dist/hitl/askParkRowRouting.js +1 -1
  85. package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
  86. package/dist/hitl/automaticAnswerVerdict.js +13 -10
  87. package/dist/hitl/decisionConflict.js +4 -5
  88. package/dist/hitl/decisionRefusal.d.ts +8 -0
  89. package/dist/hitl/decisionRefusal.js +55 -14
  90. package/dist/hitl/frameRouter.d.ts +3 -1
  91. package/dist/hitl/frameRouter.js +58 -39
  92. package/dist/hitl/gateLedger.d.ts +0 -5
  93. package/dist/hitl/gateLedger.js +0 -21
  94. package/dist/hitl/hitlBridge.d.ts +6 -2
  95. package/dist/hitl/hitlBridge.js +46 -11
  96. package/dist/hitl/localAllowRule.d.ts +1 -0
  97. package/dist/hitl/localAllowRule.js +2 -2
  98. package/dist/hitl/noAllowCause.d.ts +2 -1
  99. package/dist/hitl/noAllowCause.js +3 -2
  100. package/dist/hitl/parkResolver.d.ts +1 -0
  101. package/dist/hitl/parkResolver.js +14 -56
  102. package/dist/hitl/parkRowBirthWait.d.ts +1 -0
  103. package/dist/hitl/parkRowBirthWait.js +2 -2
  104. package/dist/hitl/planReviewWire.d.ts +1 -0
  105. package/dist/hitl/planReviewWire.js +98 -20
  106. package/dist/hitl/replayedApproval.d.ts +3 -3
  107. package/dist/hitl/replayedApproval.js +21 -16
  108. package/dist/hitl/sessionPolicyDeliverable.d.ts +0 -1
  109. package/dist/hitl/sessionPolicyDeliverable.js +17 -17
  110. package/dist/hitl/sessionPolicyWire.d.ts +2 -0
  111. package/dist/hitl/sessionPolicyWire.js +15 -3
  112. package/dist/hitl/standingRows.d.ts +19 -0
  113. package/dist/hitl/standingRows.js +148 -0
  114. package/dist/hitl/suspendedReopen.js +2 -1
  115. package/dist/hitl/toolApprovalWire.d.ts +22 -10
  116. package/dist/hitl/toolApprovalWire.js +286 -47
  117. package/dist/hookMatcherVerdict.d.ts +1 -9
  118. package/dist/hookMatcherVerdict.js +21 -61
  119. package/dist/hooksWireCaps.js +2 -2
  120. package/dist/hostCallbackGuard.d.ts +1 -0
  121. package/dist/hostCallbackGuard.js +6 -0
  122. package/dist/index.d.ts +26 -12
  123. package/dist/index.js +20 -10
  124. package/dist/liveModelCatalog.d.ts +13 -0
  125. package/dist/liveModelCatalog.js +56 -0
  126. package/dist/mcpProbeCapability.d.ts +2 -4
  127. package/dist/mcpProbeCapability.js +3 -8
  128. package/dist/mcpWireCaps.d.ts +1 -0
  129. package/dist/mcpWireCaps.js +4 -1
  130. package/dist/memoryComplianceCapability.d.ts +2 -4
  131. package/dist/memoryComplianceCapability.js +3 -8
  132. package/dist/memoryOriginCapability.d.ts +2 -4
  133. package/dist/memoryOriginCapability.js +3 -8
  134. package/dist/memorySpecWire.js +2 -2
  135. package/dist/modelIdentityResolvability.d.ts +2 -2
  136. package/dist/modelIdentityResolvability.js +14 -5
  137. package/dist/noticePresentation.d.ts +68 -0
  138. package/dist/noticePresentation.js +247 -0
  139. package/dist/outputStyleSeatCapability.d.ts +2 -1
  140. package/dist/outputStyleSeatCapability.js +0 -4
  141. package/dist/ownKey.d.ts +2 -0
  142. package/dist/ownKey.js +18 -0
  143. package/dist/peerFrames.js +13 -9
  144. package/dist/peerLaneCapability.d.ts +2 -0
  145. package/dist/peerLaneCapability.js +3 -2
  146. package/dist/permissionModesCapability.d.ts +2 -4
  147. package/dist/permissionModesCapability.js +0 -7
  148. package/dist/permissionRuleIssue.js +0 -3
  149. package/dist/permissionRulesWriteCapability.d.ts +2 -0
  150. package/dist/permissionRulesWriteCapability.js +3 -2
  151. package/dist/permissionsAllowGrantCapability.d.ts +2 -0
  152. package/dist/permissionsAllowGrantCapability.js +4 -2
  153. package/dist/permissionsDeclaration.d.ts +2 -0
  154. package/dist/permissionsDeclaration.js +72 -59
  155. package/dist/printPermissionOutcome.d.ts +12 -0
  156. package/dist/printPermissionOutcome.js +50 -0
  157. package/dist/printToolResultFrame.d.ts +1 -0
  158. package/dist/printToolResultFrame.js +5 -9
  159. package/dist/promptBlockedCopy.d.ts +5 -0
  160. package/dist/promptBlockedCopy.js +35 -0
  161. package/dist/protocolSegment.d.ts +9 -6
  162. package/dist/protocolSegment.js +31 -21
  163. package/dist/providerRejection.d.ts +4 -0
  164. package/dist/providerRejection.js +75 -14
  165. package/dist/replayBody.d.ts +12 -0
  166. package/dist/replayBody.js +25 -0
  167. package/dist/request/taskRequest.d.ts +1 -4
  168. package/dist/request/taskRequest.js +74 -19
  169. package/dist/resumeRefusalCopy.js +9 -25
  170. package/dist/retryStatus.d.ts +9 -1
  171. package/dist/retryStatus.js +9 -2
  172. package/dist/rewindArchiveCapability.d.ts +3 -13
  173. package/dist/rewindArchiveCapability.js +12 -58
  174. package/dist/rewindArchiveReading.d.ts +17 -0
  175. package/dist/rewindArchiveReading.js +55 -0
  176. package/dist/ruleCompileVerdict.d.ts +9 -1
  177. package/dist/ruleCompileVerdict.js +29 -4
  178. package/dist/runTerminal.d.ts +48 -5
  179. package/dist/runTerminal.js +215 -12
  180. package/dist/sandboxWire.js +13 -0
  181. package/dist/sdkWireTransit.d.ts +2 -1
  182. package/dist/sdkWireTransit.js +1 -0
  183. package/dist/sealedKeyCapability.d.ts +2 -4
  184. package/dist/sealedKeyCapability.js +0 -7
  185. package/dist/seam.js +4 -2
  186. package/dist/seatContract.d.ts +76 -11
  187. package/dist/seatContract.js +222 -27
  188. package/dist/sessionPolicyCapability.d.ts +2 -0
  189. package/dist/sessionPolicyCapability.js +3 -2
  190. package/dist/sessionReadRedactionCapability.d.ts +2 -4
  191. package/dist/sessionReadRedactionCapability.js +0 -7
  192. package/dist/sessionSyncFileHistory.d.ts +4 -0
  193. package/dist/sessionSyncFileHistory.js +66 -0
  194. package/dist/sessionSyncFileHistoryCapability.d.ts +2 -1
  195. package/dist/sessionSyncFileHistoryCapability.js +3 -5
  196. package/dist/skillToolListsCapability.d.ts +2 -1
  197. package/dist/skillToolListsCapability.js +3 -5
  198. package/dist/sqlEngineCapability.d.ts +2 -0
  199. package/dist/sqlEngineCapability.js +4 -3
  200. package/dist/steerPriorityCapability.d.ts +2 -1
  201. package/dist/steerPriorityCapability.js +3 -5
  202. package/dist/storePostureCapability.d.ts +2 -4
  203. package/dist/storePostureCapability.js +4 -9
  204. package/dist/subagent/engineSubagentSteer.js +7 -5
  205. package/dist/subagentContentStore.js +4 -15
  206. package/dist/supportFloor.d.ts +1 -0
  207. package/dist/supportFloor.js +13 -9
  208. package/dist/systemReminderTag.d.ts +1 -0
  209. package/dist/systemReminderTag.js +8 -0
  210. package/dist/toolHistoryBadTurn.js +3 -2
  211. package/dist/toolHistoryMismatch.d.ts +0 -3
  212. package/dist/toolHistoryMismatch.js +3 -7
  213. package/dist/toolResult.d.ts +12 -1
  214. package/dist/toolResult.js +55 -1
  215. package/dist/toolResultContent.d.ts +2 -0
  216. package/dist/toolResultContent.js +63 -0
  217. package/dist/usageAnalytics.js +40 -16
  218. package/dist/userInvokedSkillsCapability.d.ts +2 -1
  219. package/dist/userInvokedSkillsCapability.js +3 -5
  220. package/dist/webSearchBackendCapability.d.ts +2 -0
  221. package/dist/webSearchBackendCapability.js +3 -2
  222. package/dist/wireErrorTriage.d.ts +2 -0
  223. package/dist/wireErrorTriage.js +91 -38
  224. package/dist/wireFailureShape.d.ts +20 -3
  225. package/dist/wireFailureShape.js +128 -72
  226. package/dist/workflowsJournalCapability.d.ts +2 -0
  227. package/dist/workflowsJournalCapability.js +3 -2
  228. package/dist/writeProtectionCapability.d.ts +2 -0
  229. package/dist/writeProtectionCapability.js +3 -2
  230. package/docs/INTEGRATION-CLIENTS.md +1784 -20
  231. package/package.json +5 -5
  232. package/dist/engineRefusedToolName.d.ts +0 -1
  233. package/dist/engineRefusedToolName.js +0 -8
@@ -12,7 +12,7 @@ import { recordWorkflowAgentTaskId } from '../workflow.js';
12
12
  import { isCoreTaskNotificationTerminal, isCoreTaskNotificationTerminalNotSuccess, isCoreTaskProgressTerminal, isCoreTaskProgressTerminalNotSuccess } from '../terminalStatuses.js';
13
13
  import { readToolHistoryMismatchKey } from '../toolHistoryMismatch.js';
14
14
  import { readProviderRejectionResendKey } from '../providerRejection.js';
15
- import { readFrameStringKey } from '../ownKey.js';
15
+ import { readFrameStringKey, readFrameTrueMark } from '../ownKey.js';
16
16
  import { washCredentials } from '../displayUntrusted.js';
17
17
  import { resolveEnginePanelTaskId } from '../engineAgentPanelStore.js';
18
18
  import { fleetRowAgentType } from '../fleet/fleetRowAgentType.js';
@@ -74,6 +74,7 @@ const assistantArm = function* (m, { ctx, idOf, text, cards, inst }) {
74
74
  uuid: idOf(m),
75
75
  session_id: ctx.sessionId,
76
76
  parent_tool_use_id: null,
77
+ ...(readFrameTrueMark(m, '_sema_tool_recovered') ? { _sema_tool_recovered: true } : {}),
77
78
  }, ctx.now());
78
79
  if (decision === 'reject' || decision === 'cancel') {
79
80
  cards.resetResponseId();
@@ -469,6 +470,7 @@ const textSegmentEndArm = function* (m, { text }) {
469
470
  if (content.length === 0)
470
471
  return;
471
472
  const r = text.replaceAnswerSegment(content, m);
473
+ yield* text.drainLive();
472
474
  yield chrome({
473
475
  kind: 'text_segment_end',
474
476
  laneProof: mainLane(),
@@ -491,6 +493,7 @@ const thinkingSegmentEndArm = function* (m, { text }) {
491
493
  if (content.length === 0)
492
494
  return;
493
495
  const r = text.replaceThinkingSegment(content, m);
496
+ yield* text.drainLive();
494
497
  yield chrome({
495
498
  kind: 'thinking_segment_end',
496
499
  laneProof: mainLane(),
@@ -542,6 +545,7 @@ const toolEndResultArm = function* (m, { idOf, cards, panel }) {
542
545
  eventId: closeEventId,
543
546
  parentToolCallId: closeParent,
544
547
  ...(typeof closeDenialKindRaw === 'string' ? { denialKind: closeDenialKindRaw } : {}),
548
+ ...(readFrameTrueMark(m, 'notExecuted') ? { notExecuted: true } : {}),
545
549
  });
546
550
  const s = structured !== undefined && structured !== null && typeof structured === 'object'
547
551
  ? structured
@@ -854,6 +858,8 @@ const retryStatusArm = function* (m, { ctx, flags }) {
854
858
  ...(typeof m.errorStatus === 'number' ? { errorStatus: m.errorStatus } : {}),
855
859
  ...(typeof m.elapsedMs === 'number' ? { elapsedMs: m.elapsedMs } : {}),
856
860
  ...(typeof m.timeoutMs === 'number' ? { timeoutMs: m.timeoutMs } : {}),
861
+ ...(typeof m.providerCondition === 'string' && m.providerCondition.length > 0 ? { providerCondition: m.providerCondition } : {}),
862
+ ...(typeof m.providerConditionSource === 'string' && m.providerConditionSource.length > 0 ? { providerConditionSource: m.providerConditionSource } : {}),
857
863
  }, ctx.now());
858
864
  if (status === null) {
859
865
  if (flags.takeRetryOverlay())
@@ -28,6 +28,7 @@ interface ToolEndPayload {
28
28
  eventId?: string | undefined;
29
29
  parentToolCallId?: string | undefined;
30
30
  denialKind?: string | undefined;
31
+ notExecuted?: boolean | undefined;
31
32
  }
32
33
  export interface OpenCardView {
33
34
  has(id: string): boolean;
@@ -2,6 +2,8 @@ import { deriveTranscriptId } from '../seam.js';
2
2
  import { degradedToolResultBody, detectEngineBgShellDetach, detectEngineBgShellReceipt, reportFindingsToolUseResult, structuredToToolUseResult, todoWriteToolUseResult, wireOutputToBody, } from '../toolResult.js';
3
3
  import { chrome, mainLane, transcript } from './ids.js';
4
4
  import { flattenWireOutput } from './wireShapes.js';
5
+ import { toolResultBlocksOf } from '../toolResultContent.js';
6
+ import { bashExitOf, bashExitReadingFailed } from '../bashExitReading.js';
5
7
  import { isCcToolDenialKind } from '../gateVocabulary.js';
6
8
  function toolUseResultParts(v) {
7
9
  return v !== undefined ? { tool_use_result: v } : {};
@@ -20,7 +22,17 @@ export function toolResultOutcomeOf(toolName, end, rawInput, owner, ledgerTier)
20
22
  if (rich === null && !isError && toolName === 'ReportFindings') {
21
23
  rich = reportFindingsToolUseResult(end?.structured, rawInput);
22
24
  }
23
- return { body, rich };
25
+ const failed = body.isError || rich?.isError === true || bashExitReadingFailed(bashExitOf(end?.structured, () => null));
26
+ const settled = failed && !body.isError ? { ...body, isError: true } : body;
27
+ return { body: withContentBlocks(settled, end), rich };
28
+ }
29
+ function withContentBlocks(body, end) {
30
+ if (body.isError || typeof body.content !== 'string' || end === undefined || end.output === undefined)
31
+ return body;
32
+ const blocks = toolResultBlocksOf(end.output, end.truncated === true);
33
+ if (blocks === undefined)
34
+ return body;
35
+ return { ...body, content: blocks, toolUseResult: body.toolUseResult !== undefined ? body.toolUseResult : body.content };
24
36
  }
25
37
  export function toolResultEnvelopeParts(o) {
26
38
  return {
@@ -52,7 +64,7 @@ export function createToolCardLedger(ctx, idOf) {
52
64
  lastLiveTodos = todo.newTodos;
53
65
  return { toolUseResult: todo.toolUseResult, isError: todo.isError };
54
66
  });
55
- const { body, rich } = outcome;
67
+ const { body } = outcome;
56
68
  const eventId = end?.eventId ?? p.eventId;
57
69
  yield transcript({
58
70
  type: 'user',
@@ -63,7 +75,7 @@ export function createToolCardLedger(ctx, idOf) {
63
75
  type: 'tool_result',
64
76
  tool_use_id: p.id,
65
77
  content: body.content,
66
- is_error: rich?.isError === true || body.isError,
78
+ is_error: body.isError,
67
79
  },
68
80
  ],
69
81
  },
@@ -72,6 +84,7 @@ export function createToolCardLedger(ctx, idOf) {
72
84
  ...(parentToolCallId !== undefined ? { parent_tool_use_id: parentToolCallId } : {}),
73
85
  ...toolResultEnvelopeParts(outcome),
74
86
  ...(isCcToolDenialKind(end?.denialKind) ? { _sema_denial_kind: end.denialKind } : {}),
87
+ ...(end?.notExecuted === true ? { _sema_not_executed: true } : {}),
75
88
  }, ctx.now());
76
89
  }
77
90
  function* closeCard(p, end) {
@@ -1,5 +1,6 @@
1
1
  import { frozenSet } from '../frozenSet.js';
2
2
  import { stripToolUseSideChannels } from '../adapter/types.js';
3
+ import { toolEndOutputText } from '../toolResultContent.js';
3
4
  export const FLUSH_INTERVAL_MS = 100;
4
5
  export const IDLE_FLUSH_MS = 1500;
5
6
  export const SUBAGENT_TOOL_NAMES = frozenSet(['Task', 'Agent', 'Fork']);
@@ -24,22 +25,7 @@ export function estimateCjkTokens(s) {
24
25
  return Math.round(t);
25
26
  }
26
27
  export function flattenWireOutput(output) {
27
- if (typeof output === 'string')
28
- return output;
29
- if (Array.isArray(output)) {
30
- const parts = [];
31
- for (const block of output) {
32
- if (block && typeof block === 'object') {
33
- const b = block;
34
- if (b.type === 'text' && typeof b.text === 'string')
35
- parts.push(b.text);
36
- else if (b.type === 'image')
37
- parts.push('[image]');
38
- }
39
- }
40
- return parts.join('');
41
- }
42
- return '';
28
+ return toolEndOutputText(output) ?? '';
43
29
  }
44
30
  export function shortTaskLabel(task) {
45
31
  const firstLine = (task.split('\n').find(l => l.trim()) ?? task).trim();
@@ -2,8 +2,10 @@ import type { ActiveRunBusySignal } from './runStream.js';
2
2
  import type { PlanReviewReopenTrigger } from '../hitl/planReviewWire.js';
3
3
  import { atMostOnceFailureClass } from '../atMostOnce.js';
4
4
  export declare const PLAN_REVIEW_GATE_KIND = "plan_review";
5
- export declare const PLAN_REVIEW_GATE_KINDS: readonly string[];
6
- export declare const ASK_PARK_GATE_KINDS: readonly string[];
5
+ export type DurableDecideLeg = 'approval' | 'plan_review' | 'other_gate' | 'unreadable' | 'absent';
6
+ export declare function durableDecideLegOf(row: {
7
+ readonly gateKind?: string | null;
8
+ } | null | undefined): DurableDecideLeg;
7
9
  export declare function askParkForeignGateKind(row: {
8
10
  gateKind?: string | null;
9
11
  }): string | null;
@@ -5,12 +5,37 @@ import { atMostOnceFailureClass } from '../atMostOnce.js';
5
5
  import { readSteerReceipt } from '../steerReceipt.js';
6
6
  import { resumeAttachReplayDisclosure, runningAttachOffered } from '../hitl/resumeRunningCard.js';
7
7
  import { isSdkRunTerminal, SDK_PARKED_RUN_STATUSES } from '../terminalStatuses.js';
8
+ import { SDK_APPROVAL_DECIDE_GATE_KINDS, SDK_PLAN_REVIEW_GATE_KINDS } from '../generated/sdkFactTables.js';
8
9
  export const PLAN_REVIEW_GATE_KIND = 'plan_review';
9
- export const PLAN_REVIEW_GATE_KINDS = Object.freeze([PLAN_REVIEW_GATE_KIND, 'dry_run_review']);
10
- export const ASK_PARK_GATE_KINDS = Object.freeze(['human', 'irreversible_ask', 'policy_ask', 'tool_approval']);
10
+ const APPROVAL_LEG_GATE_KINDS = SDK_APPROVAL_DECIDE_GATE_KINDS;
11
+ const PLAN_LEG_GATE_KINDS = SDK_PLAN_REVIEW_GATE_KINDS;
12
+ const CORE_GATE_KINDS = ['human', 'irreversible_ask', 'resource_limit', 'needs_review', 'plan_review', 'task_done'];
13
+ const _durableDecideLegPins = [true, true, true, true, true, true, true, true, true, true];
14
+ void _durableDecideLegPins;
15
+ function gateKindReadingOf(row) {
16
+ let kind;
17
+ try {
18
+ kind = row !== null && typeof row === 'object' ? row.gateKind : undefined;
19
+ }
20
+ catch {
21
+ return { leg: 'unreadable', kind: null };
22
+ }
23
+ if (typeof kind !== 'string' || kind === '')
24
+ return { leg: 'absent', kind: null };
25
+ if (APPROVAL_LEG_GATE_KINDS.includes(kind))
26
+ return { leg: 'approval', kind };
27
+ if (PLAN_LEG_GATE_KINDS.includes(kind))
28
+ return { leg: 'plan_review', kind };
29
+ if (CORE_GATE_KINDS.includes(kind))
30
+ return { leg: 'other_gate', kind };
31
+ return { leg: 'unreadable', kind };
32
+ }
33
+ export function durableDecideLegOf(row) {
34
+ return gateKindReadingOf(row).leg;
35
+ }
11
36
  export function askParkForeignGateKind(row) {
12
- const kind = typeof row.gateKind === 'string' && row.gateKind.length > 0 ? row.gateKind : null;
13
- return kind !== null && !ASK_PARK_GATE_KINDS.includes(kind) ? kind : null;
37
+ const r = gateKindReadingOf(row);
38
+ return r.leg === 'approval' || r.leg === 'absent' ? null : (r.kind ?? '(unreadable)');
14
39
  }
15
40
  export const PLAN_REVIEW_STATES = Object.freeze(['needs_review']);
16
41
  export const ASK_PARK_STATES = Object.freeze(['suspended']);
@@ -421,9 +446,10 @@ export async function attemptActiveRunSelfHeal(signal, runs, deps) {
421
446
  };
422
447
  }
423
448
  const gateKind = signal.pendingGate?.kind ?? null;
424
- if (gateKind !== null && PLAN_REVIEW_GATE_KINDS.includes(gateKind))
449
+ const gateLeg = gateKind !== null ? durableDecideLegOf({ gateKind }) : 'absent';
450
+ if (gateLeg === 'plan_review')
425
451
  return planReviewArm(taskId, signal, deps);
426
- if (gateKind !== null && ASK_PARK_GATE_KINDS.includes(gateKind))
452
+ if (gateLeg === 'approval')
427
453
  return askParkArm(taskId, signal, runs, deps);
428
454
  let status = signal.activeTaskStatus;
429
455
  if (status === null) {
@@ -5,7 +5,7 @@ import { ccToolDenialKindForToolEnd, gateOutcomeOf } from '../../gateOutcome.js'
5
5
  import { projectToolRoster, projectToolRosterDelta } from '../../toolRoster.js';
6
6
  import { projectHandsSection } from '../../handsSeam.js';
7
7
  import { readMcpLiveness } from '../../mcpLiveness.js';
8
- import { markMcpSectionDroppedNamedRows } from '../../ownKey.js';
8
+ import { markMcpSectionDroppedNamedRows, readFrameTrueMark } from '../../ownKey.js';
9
9
  import { SEGMENT_END_IDENTITY_KEYS, stripToolUseSideChannels } from '../types.js';
10
10
  import { frozenSet } from '../../frozenSet.js';
11
11
  import { isCoreWorkflowRunTerminal } from '../../terminalStatuses.js';
@@ -40,7 +40,7 @@ export const INTERNAL_SDK_ARM_TYPES = frozenSet([
40
40
  'approval_revoke',
41
41
  'message_committed',
42
42
  ]);
43
- function assistantArm(ctx, content, eventId, parentToolCallId) {
43
+ function assistantArm(ctx, content, eventId, parentToolCallId, recovered) {
44
44
  const id = typeof eventId === 'string' && eventId.length > 0 ? eventId : undefined;
45
45
  const parent = typeof parentToolCallId === 'string' && parentToolCallId.length > 0 ? parentToolCallId : undefined;
46
46
  const model = parent === undefined && typeof ctx.model === 'string' && ctx.model.length > 0 ? ctx.model : undefined;
@@ -53,6 +53,7 @@ function assistantArm(ctx, content, eventId, parentToolCallId) {
53
53
  ...(model !== undefined ? { model } : {}),
54
54
  },
55
55
  parent_tool_use_id: parent ?? null,
56
+ ...(recovered === true ? { _sema_tool_recovered: true } : {}),
56
57
  }));
57
58
  }
58
59
  function streamEventArm(ctx, event) {
@@ -141,7 +142,7 @@ export function eventToSdkMessage(ev, ctx) {
141
142
  : {}),
142
143
  };
143
144
  const outBlock = ctx.lane === 'print' ? stripToolUseSideChannels(toolUse).block : toolUse;
144
- return projected(assistantArm(ctx, [outBlock], ev.eventId, ev.parentToolCallId));
145
+ return projected(assistantArm(ctx, [outBlock], ev.eventId, ev.parentToolCallId, readFrameTrueMark(ev, 'recovered')));
145
146
  }
146
147
  case 'compacted': {
147
148
  const raw = ev;
@@ -178,6 +179,7 @@ export function eventToSdkMessage(ev, ctx) {
178
179
  const collateralAbort = ev._sema_collateral_abort;
179
180
  const denialKind = ccToolDenialKindForToolEnd(ev);
180
181
  const denialUnclassified = denialKind === undefined && toolEndGate?.disposition.kind === 'denied';
182
+ const toolEndNotExecuted = readFrameTrueMark(ev, 'notExecuted');
181
183
  return projected(stamp(ctx, armBody({
182
184
  type: 'tool_end_result',
183
185
  toolCallId: ev.toolCallId,
@@ -200,6 +202,7 @@ export function eventToSdkMessage(ev, ctx) {
200
202
  ...(collateralAbort === true ? { _sema_collateral_abort: true } : {}),
201
203
  ...(denialKind !== undefined ? { _sema_denial_kind: denialKind } : {}),
202
204
  ...(denialUnclassified ? { _sema_denial_unclassified: true } : {}),
205
+ ...(toolEndNotExecuted ? { notExecuted: true } : {}),
203
206
  ...(ev.eventId !== undefined ? { eventId: ev.eventId } : {}),
204
207
  ...(ev.parentToolCallId !== undefined
205
208
  ? { parentToolCallId: ev.parentToolCallId }
@@ -217,6 +220,9 @@ export function eventToSdkMessage(ev, ctx) {
217
220
  const elapsedMs = num(st2.elapsedMs);
218
221
  const timeoutMs = num(st2.timeoutMs);
219
222
  const errClass = typeof ev.errClass === 'string' && ev.errClass.length > 0 ? ev.errClass : undefined;
223
+ const nonEmptyStr = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
224
+ const providerCondition = nonEmptyStr(st2.providerCondition);
225
+ const providerConditionSource = nonEmptyStr(st2.providerConditionSource);
220
226
  return projected(stamp(ctx, armBody({
221
227
  type: 'retry_status',
222
228
  phase: ev.phase,
@@ -230,6 +236,8 @@ export function eventToSdkMessage(ev, ctx) {
230
236
  ...(errorStatus !== undefined ? { errorStatus } : {}),
231
237
  ...(elapsedMs !== undefined ? { elapsedMs } : {}),
232
238
  ...(timeoutMs !== undefined ? { timeoutMs } : {}),
239
+ ...(providerCondition !== undefined ? { providerCondition } : {}),
240
+ ...(providerConditionSource !== undefined ? { providerConditionSource } : {}),
233
241
  ...(typeof ev.eventId === 'string' ? { eventId: ev.eventId } : {}),
234
242
  ...(typeof ev.parentToolCallId === 'string' ? { parentToolCallId: ev.parentToolCallId } : {}),
235
243
  })));
@@ -4,12 +4,18 @@ import { putOwnKey, readFrameStringKey } from '../../ownKey.js';
4
4
  import { REDACTION_MARKER_PREFIX, washCredentials } from '../../displayUntrusted.js';
5
5
  import { readEffectiveReasoning, readEffectiveMemoryScopes } from '../../effectiveFacts.js';
6
6
  import { isReviewPark, readRunTerminal, runTerminalCode, runTerminalGateToolName, } from '../../runTerminal.js';
7
+ import { doneResultView } from '../../replayBody.js';
7
8
  import { toCcModelUsage } from './turnUsageToModelUsage.js';
8
- import { LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, OUTPUT_INVALID, isCorruptSessionCode, isRewindFamilyCode, } from '../../engineErrorCodes.js';
9
+ import { LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, OUTPUT_INVALID, isCorruptSessionCode, idempotencyPayloadMismatchContent, isIdempotencyPayloadMismatchCode, isRewindFamilyCode, } from '../../engineErrorCodes.js';
9
10
  import { corruptSessionContent } from '../../corruptSessionCopy.js';
11
+ import { runBlockedText } from '../../promptBlockedCopy.js';
10
12
  import { abortCauseNoteOf, readAbortCause } from '../../runCancelContext.js';
11
13
  function withTerminalNote(text, code, frame) {
12
- const withCorrupt = isCorruptSessionCode(code) ? `${text}\n${corruptSessionContent()}` : text;
14
+ const withCorrupt = isCorruptSessionCode(code)
15
+ ? `${text}\n${corruptSessionContent()}`
16
+ : isIdempotencyPayloadMismatchCode(code)
17
+ ? `${text}\n${idempotencyPayloadMismatchContent()}`
18
+ : text;
13
19
  const abortNote = abortCauseNoteOf(frame);
14
20
  return abortNote === undefined ? withCorrupt : `${withCorrupt}\n${abortNote}`;
15
21
  }
@@ -519,14 +525,16 @@ function errorResult(ctx, parts) {
519
525
  });
520
526
  }
521
527
  export function doneToSdkResult(ev, ctx, observed) {
522
- const rRaw = ev.result;
528
+ const view = doneResultView(ev.result);
529
+ const rRaw = view.engine;
523
530
  const rec = typeof rRaw === 'object' && rRaw !== null ? rRaw : {};
524
531
  const r = rec;
525
532
  const stats = r.stats;
526
- const echoedSid = r.sessionId;
533
+ const nestedSid = r.sessionId;
534
+ const echoedSid = typeof nestedSid === 'string' && nestedSid.length > 0 ? nestedSid : view.row?.sessionId;
527
535
  if (typeof echoedSid === 'string' && echoedSid.length > 0)
528
536
  ctx.sessionId = echoedSid;
529
- const terminal = readRunTerminal(rRaw);
537
+ const terminal = readRunTerminal(ev.result);
530
538
  const durationMs = elapsedMs(ctx);
531
539
  const errorCode = runTerminalCode(terminal);
532
540
  const degraded = degradedOf(r);
@@ -556,15 +564,10 @@ export function doneToSdkResult(ev, ctx, observed) {
556
564
  });
557
565
  }
558
566
  if (terminal?.kind === 'blocked') {
559
- const blockedReason = terminal.reason;
560
567
  return errorResult(ctx, {
561
568
  ...errorBase,
562
569
  subtype: 'error_during_execution',
563
- errors: [
564
- blockedReason !== undefined
565
- ? `Run blocked: ${blockedReason}`
566
- : 'Run blocked (the agent reported it cannot proceed)',
567
- ],
570
+ errors: [runBlockedText(terminal)],
568
571
  });
569
572
  }
570
573
  if (terminal?.kind === 'paused') {
@@ -3,13 +3,15 @@ import { eventToSdkMessage, turnEndUsage } from './downstream/eventToSdkMessage.
3
3
  import { turnUsageToModelUsage } from './downstream/turnUsageToModelUsage.js';
4
4
  import { readRunCostFacts, terminalToSdkResult, TOOL_INPUT_JOIN_MAX_CALLS } from './downstream/terminalToSdkResult.js';
5
5
  import { coerceOutput, publishSubagentContentEvent } from '../subagentContentStore.js';
6
- import { ACTIVE_RUN_BUSY_ERROR_CODE, OUTPUT_INVALID, isCorruptSessionCode, isLimitsExceededCode } from '../engineErrorCodes.js';
6
+ import { OUTPUT_INVALID, activeRunBusyCarrierOf, classifyActiveRunBusy, isCorruptSessionCode, isLimitsExceededCode } from '../engineErrorCodes.js';
7
+ import { doneResultView } from '../replayBody.js';
7
8
  import { corruptSessionContent } from '../corruptSessionCopy.js';
8
9
  import { abortCauseNoteOf } from '../runCancelContext.js';
9
10
  import { classifyToolHistoryMismatch, noteToolHistoryTerminal, openToolHistoryGeneration, TOOL_HISTORY_REWIND_SENTENCE, toolHistoryMismatchRowKey, toolHistoryRepeatSentence, toolHistoryRewindOffered, } from '../toolHistoryMismatch.js';
10
11
  import { isReviewPark, readRunTerminal, runTerminalCode } from '../runTerminal.js';
11
12
  import { providerRejectionResend } from '../providerRejection.js';
12
13
  import { washCredentials } from '../displayUntrusted.js';
14
+ import { PROMPT_BLOCKED_BY_HOOK_ROW_LEAD, runBlockedText } from '../promptBlockedCopy.js';
13
15
  import { ccToolDenialKindForToolEnd, gateDeniedBy, gateOutcomeOf } from '../gateOutcome.js';
14
16
  import { resumeReopenContent, resumeReopenFromError, suspendedReopenOf } from '../hitl/suspendedReopen.js';
15
17
  import { isCcToolDenialKind, isCcToolDenialKindADenial, isGateDeniedByWord } from '../gateVocabulary.js';
@@ -52,31 +54,10 @@ export function pendingGateIsProvablyDifferent(prev, next) {
52
54
  return a !== b;
53
55
  }
54
56
  export function activeRunBusySignal(ev) {
55
- if (typeof ev !== 'object' || ev === null || !('type' in ev))
56
- return null;
57
- const type = ev.type;
58
- let carrier;
59
- if (type === 'done') {
60
- const result = ev.result;
61
- if (typeof result !== 'object' || result === null)
62
- return null;
63
- const status = result.status;
64
- if (status !== 'failed' && (status !== undefined || Array.isArray(result)))
65
- return null;
66
- carrier = result;
67
- }
68
- else if (type === 'failed') {
69
- carrier = ev;
70
- }
71
- else {
72
- return null;
73
- }
74
- const cls = classifyActiveRunBusy({
75
- errorCode: typeof carrier.errorCode === 'string' ? carrier.errorCode : undefined,
76
- activeTaskId: carrier.activeTaskId,
77
- });
78
- if (!cls.busy)
57
+ const read = busyReadOfFrame(ev);
58
+ if (read === null || !read.cls.busy)
79
59
  return null;
60
+ const { carrier, cls } = read;
80
61
  const status = carrier.activeTaskStatus;
81
62
  const rawGate = carrier.pendingGate;
82
63
  let pendingGate = null;
@@ -100,19 +81,22 @@ export function activeRunBusySignal(ev) {
100
81
  ...(typeof msIdle === 'number' && Number.isFinite(msIdle) && msIdle >= 0 ? { msSinceLastActivity: msIdle } : {}),
101
82
  };
102
83
  }
103
- function classifyActiveRunBusy(input) {
104
- const handle = typeof input.activeTaskId === 'string' && input.activeTaskId.length > 0 ? input.activeTaskId : null;
105
- if (input.errorCode === ACTIVE_RUN_BUSY_ERROR_CODE)
106
- return { busy: true, handle };
107
- if (typeof input.activeTaskId === 'string')
108
- return { busy: true, handle };
109
- return { busy: false, handle };
84
+ function busyReadOfFrame(ev, doneTerminal, preReadActiveTaskId) {
85
+ const carrier = activeRunBusyCarrierOf(ev);
86
+ if (carrier === null)
87
+ return null;
88
+ const isDone = ev.type === 'done';
89
+ const terminal = isDone ? (doneTerminal !== undefined ? doneTerminal : readRunTerminal(ev.result)) : null;
90
+ const flatCode = typeof carrier.errorCode === 'string' ? carrier.errorCode : undefined;
91
+ const activeTaskId = preReadActiveTaskId !== undefined ? preReadActiveTaskId.value : carrier.activeTaskId;
92
+ const cls = classifyActiveRunBusy({ errorCode: (isDone ? runTerminalCode(terminal) : undefined) ?? flatCode, activeTaskId });
93
+ return { carrier, cls };
110
94
  }
111
95
  export const RUN_STOPPED_MESSAGE_PREFIX = 'Run stopped';
112
96
  export const RUN_BLOCKED_MESSAGE_PREFIX = 'Run blocked';
113
97
  export function isGovernanceStopRowText(text) {
114
98
  const t = text.trimStart();
115
- return t.startsWith(`${RUN_STOPPED_MESSAGE_PREFIX}:`) || t.startsWith(`${RUN_BLOCKED_MESSAGE_PREFIX}`);
99
+ return t.startsWith(`${RUN_STOPPED_MESSAGE_PREFIX}:`) || t.startsWith(`${RUN_BLOCKED_MESSAGE_PREFIX}`) || t.startsWith(PROMPT_BLOCKED_BY_HOOK_ROW_LEAD);
116
100
  }
117
101
  export const MODEL_OUTPUT_ERROR_PREFIX = 'Model output error';
118
102
  export function isModelOutputErrorText(text) {
@@ -133,13 +117,17 @@ function syntheticTerminalRow(ctx, text, historyKey, resend) {
133
117
  parent_tool_use_id: null,
134
118
  _sema_api_error_message: true,
135
119
  ...(historyKey !== undefined ? { _sema_tool_history_mismatch: historyKey } : {}),
136
- ...(resend !== undefined ? { _sema_provider_rejection_resend: { resend: resend.resend, text: resend.text } } : {}),
120
+ ...(resend !== undefined ? { _sema_provider_rejection_resend: { resend: resend.resend, text: resend.text, kind: resend.kind } } : {}),
137
121
  });
138
122
  }
139
123
  function engineRunIdOf(result) {
140
124
  const v = result?.runId;
141
125
  return typeof v === 'string' && v.length > 0 ? v : undefined;
142
126
  }
127
+ function engineResultOf(result) {
128
+ const v = doneResultView(result);
129
+ return v.replay ? (v.engine ?? result) : result;
130
+ }
143
131
  function engineSessionIdOf(result) {
144
132
  const v = result?.sessionId;
145
133
  return typeof v === 'string' && v.length > 0 ? v : undefined;
@@ -161,19 +149,14 @@ function terminalRowFacts(ev) {
161
149
  : doneTerminal?.kind === 'failed'
162
150
  ? (doneTerminal.message ?? doneTerminal.code ?? 'run failed')
163
151
  : doneTerminal?.kind === 'blocked'
164
- ? (doneTerminal.reason
165
- ? `Run blocked: ${doneTerminal.reason}`
166
- : 'Run blocked (the agent reported it cannot proceed)')
152
+ ? runBlockedText(doneTerminal)
167
153
  : null;
168
154
  const errText = errTextRaw === '' ? null : errTextRaw;
169
155
  if (errText === null)
170
156
  return { doneTerminal, errText, activeTaskId: undefined, busy: { busy: false, handle: null }, governance: false };
171
157
  const activeTaskId = (ev.type === 'done' ? ev.result?.activeTaskId : undefined) ??
172
158
  (ev.type === 'failed' ? ev.activeTaskId : undefined);
173
- const busy = classifyActiveRunBusy({
174
- errorCode: ev.type === 'failed' ? ev.errorCode : runTerminalCode(doneTerminal),
175
- activeTaskId,
176
- });
159
+ const busy = busyReadOfFrame(ev, doneTerminal, { value: activeTaskId })?.cls ?? { busy: false, handle: null };
177
160
  const governance = isGovernanceTerminal({
178
161
  status: ev.type === 'failed' ? undefined : doneTerminal?.kind === 'blocked' ? 'blocked' : undefined,
179
162
  errorCode: ev.type === 'failed' ? ev.errorCode : runTerminalCode(doneTerminal),
@@ -284,7 +267,7 @@ function apiErrorTerminalFromFacts(x, facts) {
284
267
  return none();
285
268
  if (type === 'failed')
286
269
  return { carrier: mintToolHistoryCarrier(nonEmptyStr(ownDataBit(x, 'errorCode')), undefined, nonEmptyStr(ownDataBit(x, 'errorMessage'))), detail: undefined };
287
- const result = type === 'done' ? plainObjectOf(ownDataBit(x, 'result')) : x;
270
+ const result = type === 'done' ? plainObjectOf(engineResultOf(ownDataBit(x, 'result'))) : x;
288
271
  if (result === undefined)
289
272
  return none();
290
273
  const snap = ownTerminalSnapshot(result);
@@ -667,12 +650,12 @@ async function* runStreamInner(events, ctx, handle = {}) {
667
650
  const abortNote = abortCauseNoteOf(ev);
668
651
  const historyTerminal = apiErrorTerminalOfRowFrame(ev, rowFacts);
669
652
  const historyMismatch = classifyToolHistoryMismatch(historyTerminal.carrier);
670
- const historyEchoedSid = ev.type === 'done' ? engineSessionIdOf(ev.result) : undefined;
653
+ const historyEchoedSid = ev.type === 'done' ? engineSessionIdOf(engineResultOf(ev.result)) : undefined;
671
654
  const historyRepeat = noteToolHistoryTerminal({
672
655
  sessionId: historyEchoedSid ?? ctx.sessionId,
673
656
  sessionEchoed: historyEchoedSid !== undefined,
674
657
  generation: historyGeneration,
675
- runId: ev.type === 'done' ? engineRunIdOf(ev.result) : undefined,
658
+ runId: ev.type === 'done' ? engineRunIdOf(engineResultOf(ev.result)) : undefined,
676
659
  replay: ev.type === 'done' && ev.replay === true,
677
660
  mismatch: historyMismatch,
678
661
  });
@@ -685,12 +668,12 @@ async function* runStreamInner(events, ctx, handle = {}) {
685
668
  yield syntheticTerminalRow(ctx, `${sessionUnreadable ? `${rowText}\n${corruptSessionContent()}` : rowText}${abortNote !== undefined ? `\n${abortNote}` : ''}${rewindLine}${resendLine}`, historyMismatch === null ? undefined : toolHistoryMismatchRowKey(historyMismatch, historyRepeat, rewindOffered), resend);
686
669
  }
687
670
  else {
688
- const echoedSid = ev.type === 'done' ? engineSessionIdOf(ev.result) : undefined;
671
+ const echoedSid = ev.type === 'done' ? engineSessionIdOf(engineResultOf(ev.result)) : undefined;
689
672
  noteToolHistoryTerminal({
690
673
  sessionId: echoedSid ?? ctx.sessionId,
691
674
  sessionEchoed: echoedSid !== undefined,
692
675
  generation: historyGeneration,
693
- runId: ev.type === 'done' ? engineRunIdOf(ev.result) : undefined,
676
+ runId: ev.type === 'done' ? engineRunIdOf(engineResultOf(ev.result)) : undefined,
694
677
  replay: ev.type === 'done' && ev.replay === true,
695
678
  mismatch: null,
696
679
  });
@@ -702,7 +685,7 @@ async function* runStreamInner(events, ctx, handle = {}) {
702
685
  catch { }
703
686
  }
704
687
  if (ev.type === 'done' && ctx.emitChrome) {
705
- const doneStats = ev.result?.stats;
688
+ const doneStats = engineResultOf(ev.result)?.stats;
706
689
  const costFacts = readRunCostFacts(doneStats, { usageMissingObserved });
707
690
  if (costFacts !== undefined) {
708
691
  emitChromeFireAndForget(ctx, { kind: 'run_cost_reconciled', laneProof: mainLane(), ...costFacts.reconcile });
@@ -122,7 +122,6 @@ export function createBackgroundView(client, opts) {
122
122
  let disposed = false;
123
123
  let current = null;
124
124
  let lastSerialized = null;
125
- let capsApprovals = null;
126
125
  const listeners = new Set();
127
126
  const abort = new AbortController();
128
127
  function notify() {
@@ -137,27 +136,16 @@ export function createBackgroundView(client, opts) {
137
136
  }
138
137
  }
139
138
  }
140
- async function probeCaps() {
141
- if (capsApprovals !== null)
142
- return;
143
- try {
144
- const caps = await client.capabilities({ signal: abort.signal });
145
- capsApprovals = caps.approvals === true;
146
- }
147
- catch (err) {
148
- debugLog(`caps probe unavailable (approvals 判别缺席,保持 ok 口径): ${String(err)}`);
149
- }
150
- }
151
139
  async function pullAssistant() {
152
140
  try {
153
141
  const { tasks } = await client.assistant.tasks({ signal: abort.signal });
154
142
  if (!Array.isArray(tasks))
155
143
  return { health: 'unavailable', tasks: [] };
156
- return { health: capsApprovals === false ? 'not-configured' : 'ok', tasks };
144
+ return { health: 'ok', tasks };
157
145
  }
158
146
  catch (err) {
159
147
  debugLog(`assistant.tasks degrade: ${String(err)}`);
160
- const health = capsApprovals === false || isNotImplemented(err)
148
+ const health = isNotImplemented(err)
161
149
  ? 'not-configured'
162
150
  : isReadCredentialRefusal(err)
163
151
  ? 'unauthorized'
@@ -183,7 +171,6 @@ export function createBackgroundView(client, opts) {
183
171
  }
184
172
  }
185
173
  async function pollOnce() {
186
- await probeCaps();
187
174
  const [assistant, fleet] = await Promise.all([pullAssistant(), pullFleet()]);
188
175
  if (disposed || abort.signal.aborted)
189
176
  return;
@@ -1,6 +1,7 @@
1
1
  import { errCodes } from '../controlRouter.js';
2
2
  import { hostLog } from '../host.js';
3
3
  import { isSessionIdPathSegment } from '../sessionIdSegment.js';
4
+ import { ownDataField } from '../ownKey.js';
4
5
  const unavailable = (why) => ({
5
6
  kind: 'unavailable',
6
7
  why,
@@ -58,12 +59,12 @@ export function isEngineAgentRegistryListingSuperseded(listing) {
58
59
  return registryListingProvenanceOf(listing)?.superseded === true;
59
60
  }
60
61
  function listFaceOn(caps) {
61
- if (typeof caps !== 'object' || caps === null || !Object.hasOwn(caps, 'background'))
62
+ if (typeof caps !== 'object' || caps === null)
62
63
  return false;
63
- const bg = caps.background;
64
- if (typeof bg !== 'object' || bg === null || !Object.hasOwn(bg, 'listFace'))
64
+ const bg = ownDataField(caps, 'background');
65
+ if (typeof bg !== 'object' || bg === null)
65
66
  return false;
66
- return bg.listFace === true;
67
+ return ownDataField(bg, 'listFace') === true;
67
68
  }
68
69
  function readRow(v) {
69
70
  if (typeof v !== 'object' || v === null || Array.isArray(v))
@@ -1,4 +1,4 @@
1
- import { engineCapValue } from '../engineCapsCache.js';
1
+ import { engineCapNestedValue } from '../engineCapsCache.js';
2
2
  import { isStatusDerivedCoarseCode } from '../engineErrorCodes.js';
3
3
  import { clientHasVerbs, engineWireFor, INJECTED_WIRE_SETTLE_MS, noAnswerDetailFrom, sendOnce, settleInjected } from '../engineWireFor.js';
4
4
  import { engineWireDebugEnabled } from '../engineWireTarget.js';
@@ -18,6 +18,8 @@ const DETAIL_NO_TARGET = `no engine connection is installed for this session${NO
18
18
  const DETAIL_NO_CLIENT = `an engine client could not be built from the installed connection${NOTHING_SENT}`;
19
19
  const DETAIL_CAPS_KEY_REQUIRED = `capability evidence for background.exitFaces is not available under the key the host named (capsBaseUrl)${NOTHING_SENT}`;
20
20
  const DETAIL_CAPS_UNOBSERVED = `the engine capabilities have not been read for this connection yet — wait for the capability probe to settle, then call again${NOTHING_SENT}`;
21
+ const DETAIL_CAPS_UNREADABLE = `the engine reported its capabilities in a form this client cannot read, so whether it offers the session background stop is unknown — calling again on this connection will not change that${NOTHING_SENT}`;
22
+ const DETAIL_CAPS_UNKNOWN_GENERIC = `whether the engine offers the session background stop is unknown${NOTHING_SENT}`;
21
23
  const DETAIL_NO_EXIT_FACE = `this engine does not offer the session background stop (capabilities.background.exitFaces is not true); background tasks may keep running${NOTHING_SENT}`;
22
24
  function refusedDetail(why) {
23
25
  switch (why) {
@@ -67,22 +69,27 @@ function unavailable(why, detail) {
67
69
  function usableStopClient(client) {
68
70
  return clientHasVerbs(client, [['sessions', 'backgroundStop']]);
69
71
  }
70
- function exitFaceGate(capsKey) {
71
- try {
72
- const v = engineCapValue(capsKey, 'background');
73
- if (v.kind === 'unobserved')
74
- return { why: 'capability_unknown', detail: DETAIL_CAPS_UNOBSERVED };
75
- if (v.kind !== 'value')
76
- return { why: 'no_exit_face', detail: DETAIL_NO_EXIT_FACE };
77
- const bg = v.value;
78
- if (typeof bg !== 'object' || bg === null || !Object.hasOwn(bg, 'exitFaces'))
79
- return { why: 'no_exit_face', detail: DETAIL_NO_EXIT_FACE };
80
- return bg.exitFaces === true ? null : { why: 'no_exit_face', detail: DETAIL_NO_EXIT_FACE };
81
- }
82
- catch {
83
- return { why: 'capability_unknown', detail: DETAIL_CAPS_UNOBSERVED };
72
+ function capsUnknownDetail(reason) {
73
+ switch (reason) {
74
+ case 'unobserved':
75
+ return DETAIL_CAPS_UNOBSERVED;
76
+ case 'unreadable':
77
+ return DETAIL_CAPS_UNREADABLE;
78
+ default: {
79
+ const unreachable = reason;
80
+ void unreachable;
81
+ return DETAIL_CAPS_UNKNOWN_GENERIC;
82
+ }
84
83
  }
85
84
  }
85
+ function exitFaceGate(capsKey) {
86
+ const v = engineCapNestedValue(capsKey, 'background', 'exitFaces');
87
+ if (v.kind === 'unobserved')
88
+ return { why: 'capability_unknown', detail: capsUnknownDetail('unobserved') };
89
+ if (v.kind === 'unreadable')
90
+ return { why: 'capability_unknown', detail: capsUnknownDetail('unreadable') };
91
+ return v.kind === 'value' && v.value === true ? null : { why: 'no_exit_face', detail: DETAIL_NO_EXIT_FACE };
92
+ }
86
93
  function readReceipt(v) {
87
94
  if (typeof v !== 'object' || v === null || Array.isArray(v))
88
95
  return undefined;