@sema-agent/client-core 0.94.0 → 0.95.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 (255) hide show
  1. package/CHANGELOG.md +341 -0
  2. package/README.md +70 -47
  3. package/dist/adapt/arms.js +5 -6
  4. package/dist/adapt/panelTasks.js +4 -10
  5. package/dist/adapt/toolCards.js +2 -2
  6. package/dist/adapt/wireShapes.js +3 -8
  7. package/dist/adapter/activeRunSelfHeal.d.ts +8 -3
  8. package/dist/adapter/activeRunSelfHeal.js +20 -12
  9. package/dist/adapter/downstream/eventToSdkMessage.js +24 -17
  10. package/dist/adapter/downstream/terminalToSdkResult.js +11 -3
  11. package/dist/adapter/runStream.js +2 -1
  12. package/dist/adapter/types.d.ts +7 -0
  13. package/dist/adapter/types.js +15 -0
  14. package/dist/agentSession/backgroundView.js +5 -1
  15. package/dist/agentSession/engineAgentRegistryRead.js +2 -1
  16. package/dist/agentSession/engineSessionBackgroundStop.js +3 -2
  17. package/dist/agentsWireCaps.d.ts +2 -0
  18. package/dist/approvalDecidedByCapability.d.ts +0 -1
  19. package/dist/approvalDecidedByCapability.js +2 -7
  20. package/dist/approvalsStreamLiveCapability.d.ts +0 -1
  21. package/dist/approvalsStreamLiveCapability.js +2 -6
  22. package/dist/atMostOnce.d.ts +8 -0
  23. package/dist/atMostOnce.js +36 -0
  24. package/dist/attachmentSeatCapability.d.ts +0 -1
  25. package/dist/attachmentSeatCapability.js +0 -3
  26. package/dist/attachmentsWireCaps.js +11 -6
  27. package/dist/bashExitReading.d.ts +10 -0
  28. package/dist/bashExitReading.js +12 -0
  29. package/dist/callerCwdCapability.d.ts +0 -1
  30. package/dist/callerCwdCapability.js +2 -7
  31. package/dist/centerWiringCapability.d.ts +1 -3
  32. package/dist/centerWiringCapability.js +18 -21
  33. package/dist/classifierStatus.js +4 -4
  34. package/dist/cloudConfigWireCaps.js +43 -21
  35. package/dist/compensations.js +1 -1
  36. package/dist/cycleOrder.d.ts +15 -0
  37. package/dist/cycleOrder.js +45 -0
  38. package/dist/decideFailureNote.js +4 -1
  39. package/dist/decideReceipt.d.ts +2 -1
  40. package/dist/decideReceipt.js +41 -13
  41. package/dist/declared/supportFloorDeclared.d.ts +1 -0
  42. package/dist/declared/supportFloorDeclared.js +5 -0
  43. package/dist/deviceExecutorManagementCapability.d.ts +0 -1
  44. package/dist/deviceExecutorManagementCapability.js +7 -16
  45. package/dist/deviceRebind.d.ts +88 -0
  46. package/dist/deviceRebind.js +242 -0
  47. package/dist/displayUntrusted.d.ts +1 -0
  48. package/dist/displayUntrusted.js +313 -11
  49. package/dist/engineAgentAbsence.d.ts +2 -2
  50. package/dist/engineAgentPanelStore.d.ts +8 -18
  51. package/dist/engineAgentPanelStore.js +19 -537
  52. package/dist/engineCapReader.d.ts +6 -6
  53. package/dist/engineCapReader.js +30 -43
  54. package/dist/engineCapsCache.d.ts +7 -2
  55. package/dist/engineCapsCache.js +64 -26
  56. package/dist/engineCredentialRequirement.d.ts +9 -0
  57. package/dist/engineCredentialRequirement.js +23 -0
  58. package/dist/engineEnvSourcing.d.ts +53 -0
  59. package/dist/engineEnvSourcing.js +81 -0
  60. package/dist/engineErrorCodes.d.ts +14 -3
  61. package/dist/engineErrorCodes.js +31 -10
  62. package/dist/engineIdentity.js +2 -0
  63. package/dist/engineWireSdk.js +2 -2
  64. package/dist/executionLaneCapability.d.ts +2 -3
  65. package/dist/executionLaneCapability.js +18 -23
  66. package/dist/fileHistoryCaptureCapability.d.ts +0 -1
  67. package/dist/fileHistoryCaptureCapability.js +2 -6
  68. package/dist/fileHistoryLegNotice.d.ts +3 -2
  69. package/dist/fileHistoryLegNotice.js +51 -2
  70. package/dist/fleet/fleetLedger.d.ts +2 -0
  71. package/dist/fleet/fleetLedger.js +69 -52
  72. package/dist/fleet/fleetProjection.d.ts +0 -3
  73. package/dist/fleet/fleetProjection.js +9 -16
  74. package/dist/fleetAgentPanelProjection.d.ts +4 -17
  75. package/dist/fleetAgentPanelProjection.js +7 -197
  76. package/dist/fleetAgentRowLike.d.ts +16 -0
  77. package/dist/fleetAgentRowLike.js +1 -0
  78. package/dist/gateOutcome.js +30 -18
  79. package/dist/generated/sdkFactTables.d.ts +2 -0
  80. package/dist/generated/sdkFactTables.js +17 -0
  81. package/dist/generated/settingsSchemaFns.d.ts +10 -0
  82. package/dist/generated/settingsSchemaFns.js +22 -0
  83. package/dist/headlessPermissionModeWire.d.ts +1 -1
  84. package/dist/headlessPermissionModeWire.js +1 -1
  85. package/dist/headlessReconnectWire.js +49 -20
  86. package/dist/hitl/allowRuleShadow.d.ts +1 -1
  87. package/dist/hitl/allowRuleShadow.js +49 -8
  88. package/dist/hitl/approvalCompleteParked.d.ts +1 -0
  89. package/dist/hitl/approvalCompleteParked.js +14 -0
  90. package/dist/hitl/approvalEndingCause.d.ts +5 -0
  91. package/dist/hitl/approvalEndingCause.js +61 -0
  92. package/dist/hitl/approvalHolds.d.ts +12 -2
  93. package/dist/hitl/approvalHolds.js +53 -2
  94. package/dist/hitl/approvalsFeed.js +23 -11
  95. package/dist/hitl/askGateWire.d.ts +2 -1
  96. package/dist/hitl/askGateWire.js +26 -1
  97. package/dist/hitl/automaticAnswerVerdict.js +2 -2
  98. package/dist/hitl/crashConverged.js +2 -0
  99. package/dist/hitl/decisionConflict.d.ts +3 -0
  100. package/dist/hitl/decisionConflict.js +43 -0
  101. package/dist/hitl/decisionRefusal.d.ts +4 -0
  102. package/dist/hitl/decisionRefusal.js +26 -1
  103. package/dist/hitl/frameRouter.js +26 -43
  104. package/dist/hitl/gateLedger.d.ts +5 -0
  105. package/dist/hitl/gateLedger.js +21 -0
  106. package/dist/hitl/hitlBridge.d.ts +12 -1
  107. package/dist/hitl/hitlBridge.js +68 -53
  108. package/dist/hitl/hitlHostSurface.js +3 -11
  109. package/dist/hitl/livePendingAsk.d.ts +16 -6
  110. package/dist/hitl/livePendingAsk.js +36 -4
  111. package/dist/hitl/parkExpiryJudgements.d.ts +19 -0
  112. package/dist/hitl/parkExpiryJudgements.js +46 -0
  113. package/dist/hitl/parkResolver.d.ts +3 -7
  114. package/dist/hitl/parkResolver.js +50 -26
  115. package/dist/hitl/persistedRulesWire.js +5 -1
  116. package/dist/hitl/planReviewWire.d.ts +2 -2
  117. package/dist/hitl/planReviewWire.js +56 -30
  118. package/dist/hitl/replayedApproval.d.ts +8 -0
  119. package/dist/hitl/replayedApproval.js +125 -10
  120. package/dist/hitl/resumeRunningCard.d.ts +2 -0
  121. package/dist/hitl/resumeRunningCard.js +15 -4
  122. package/dist/hitl/toolApprovalWire.d.ts +24 -4
  123. package/dist/hitl/toolApprovalWire.js +115 -38
  124. package/dist/hooksWireCaps.js +38 -6
  125. package/dist/host.d.ts +5 -0
  126. package/dist/host.js +3 -1
  127. package/dist/hostCallbackGuard.d.ts +1 -0
  128. package/dist/hostCallbackGuard.js +25 -0
  129. package/dist/index.d.ts +30 -11
  130. package/dist/index.js +20 -8
  131. package/dist/interactiveInterrupt.d.ts +8 -0
  132. package/dist/interactiveInterrupt.js +54 -0
  133. package/dist/limitsWire.d.ts +5 -0
  134. package/dist/limitsWire.js +49 -3
  135. package/dist/liveModelCatalog.d.ts +95 -0
  136. package/dist/liveModelCatalog.js +297 -32
  137. package/dist/mcpEngineLeg.d.ts +25 -0
  138. package/dist/mcpEngineLeg.js +71 -15
  139. package/dist/mcpPanel.js +2 -1
  140. package/dist/mcpProbeCapability.d.ts +0 -1
  141. package/dist/mcpProbeCapability.js +2 -6
  142. package/dist/mcpReconnect.d.ts +1 -3
  143. package/dist/mcpReconnect.js +10 -5
  144. package/dist/memoryComplianceCapability.d.ts +0 -1
  145. package/dist/memoryComplianceCapability.js +2 -6
  146. package/dist/memoryOriginCapability.d.ts +0 -1
  147. package/dist/memoryOriginCapability.js +2 -6
  148. package/dist/memoryVerbsWire.d.ts +1 -1
  149. package/dist/memoryVerbsWire.js +4 -0
  150. package/dist/model/liveCatalogShape.d.ts +14 -0
  151. package/dist/model/liveCatalogShape.js +71 -0
  152. package/dist/model/modelSupplyRules.d.ts +1 -0
  153. package/dist/model/modelSupplyRules.js +30 -9
  154. package/dist/model/modelsPolicy.d.ts +21 -0
  155. package/dist/model/modelsPolicy.js +90 -0
  156. package/dist/modelIdentityResolvability.d.ts +1 -1
  157. package/dist/modelIdentityResolvability.js +5 -12
  158. package/dist/modelSwitchFallback.d.ts +69 -0
  159. package/dist/modelSwitchFallback.js +206 -0
  160. package/dist/notifications.js +12 -11
  161. package/dist/outputStyleSeatCapability.d.ts +0 -1
  162. package/dist/outputStyleSeatCapability.js +2 -7
  163. package/dist/ownKey.d.ts +6 -0
  164. package/dist/ownKey.js +48 -0
  165. package/dist/panelReduce.d.ts +114 -0
  166. package/dist/panelReduce.js +1135 -0
  167. package/dist/panelStateHolder.d.ts +17 -0
  168. package/dist/panelStateHolder.js +201 -0
  169. package/dist/peerLaneCapability.d.ts +0 -1
  170. package/dist/peerLaneCapability.js +2 -6
  171. package/dist/permissionModesCapability.d.ts +0 -1
  172. package/dist/permissionModesCapability.js +5 -10
  173. package/dist/permissionRulesWriteCapability.d.ts +0 -1
  174. package/dist/permissionRulesWriteCapability.js +2 -6
  175. package/dist/permissionsAllowGrantCapability.d.ts +0 -1
  176. package/dist/permissionsAllowGrantCapability.js +3 -9
  177. package/dist/permissionsDeclaration.d.ts +6 -0
  178. package/dist/permissionsDeclaration.js +45 -0
  179. package/dist/printToolResultFrame.js +2 -10
  180. package/dist/promptDelivery.js +0 -8
  181. package/dist/resumeRefusalCopy.d.ts +18 -1
  182. package/dist/resumeRefusalCopy.js +126 -15
  183. package/dist/rewindArchiveCapability.d.ts +2 -1
  184. package/dist/rewindArchiveCapability.js +15 -7
  185. package/dist/rewindEngineAction.d.ts +21 -0
  186. package/dist/rewindEngineAction.js +36 -0
  187. package/dist/rewindWireCaps.d.ts +2 -1
  188. package/dist/rewindWireCaps.js +1 -0
  189. package/dist/runTerminal.d.ts +0 -11
  190. package/dist/runTerminal.js +4 -27
  191. package/dist/sdkRegistryTransit.d.ts +2 -1
  192. package/dist/sdkRegistryTransit.js +1 -0
  193. package/dist/sealedKeyCapability.d.ts +0 -1
  194. package/dist/sealedKeyCapability.js +3 -9
  195. package/dist/seatContract.d.ts +54 -25
  196. package/dist/seatContract.js +394 -171
  197. package/dist/sessionIdSegment.d.ts +1 -0
  198. package/dist/sessionIdSegment.js +11 -0
  199. package/dist/sessionMemoryErase.d.ts +1 -1
  200. package/dist/sessionMemoryErase.js +6 -1
  201. package/dist/sessionMemoryStatus.js +3 -2
  202. package/dist/sessionPolicyCapability.d.ts +0 -1
  203. package/dist/sessionPolicyCapability.js +2 -6
  204. package/dist/sessionReadRedactionCapability.d.ts +0 -1
  205. package/dist/sessionReadRedactionCapability.js +2 -7
  206. package/dist/sessionSyncFileHistoryCapability.d.ts +0 -1
  207. package/dist/sessionSyncFileHistoryCapability.js +2 -6
  208. package/dist/skillToolListsCapability.d.ts +0 -1
  209. package/dist/skillToolListsCapability.js +2 -6
  210. package/dist/skillsWireCaps.d.ts +4 -0
  211. package/dist/skillsWireCaps.js +66 -1
  212. package/dist/sqlEngineCapability.d.ts +0 -1
  213. package/dist/sqlEngineCapability.js +9 -14
  214. package/dist/steerPriorityCapability.d.ts +0 -1
  215. package/dist/steerPriorityCapability.js +3 -9
  216. package/dist/storePostureCapability.d.ts +1 -1
  217. package/dist/storePostureCapability.js +16 -16
  218. package/dist/streamDrainingLegs.d.ts +6 -0
  219. package/dist/streamDrainingLegs.js +23 -0
  220. package/dist/subagent/engineCompactWire.js +13 -38
  221. package/dist/subagent/engineDelegatedPrompt.js +10 -6
  222. package/dist/subagent/engineSubagentOutput.d.ts +0 -1
  223. package/dist/subagent/engineSubagentOutput.js +5 -20
  224. package/dist/subagent/engineSubagentTail.d.ts +0 -1
  225. package/dist/subagent/engineSubagentTail.js +7 -32
  226. package/dist/subagentContentStore.js +3 -3
  227. package/dist/supportFloor.js +2 -5
  228. package/dist/terminalStatuses.d.ts +30 -0
  229. package/dist/terminalStatuses.js +67 -0
  230. package/dist/toolResult.d.ts +5 -0
  231. package/dist/toolResult.js +88 -36
  232. package/dist/types/engineState.d.ts +2 -1
  233. package/dist/usageAnalytics.d.ts +146 -0
  234. package/dist/usageAnalytics.js +311 -0
  235. package/dist/userInvokedSkillsCapability.d.ts +0 -1
  236. package/dist/userInvokedSkillsCapability.js +2 -6
  237. package/dist/webSearchBackendCapability.d.ts +0 -1
  238. package/dist/webSearchBackendCapability.js +3 -7
  239. package/dist/webSearchWireCaps.js +3 -11
  240. package/dist/wireFailureShape.d.ts +4 -0
  241. package/dist/wireFailureShape.js +42 -2
  242. package/dist/wireRefusalCopy.js +2 -18
  243. package/dist/workflowClient.js +7 -11
  244. package/dist/workflowsJournalCapability.d.ts +0 -1
  245. package/dist/workflowsJournalCapability.js +2 -6
  246. package/dist/writeProtectionCapability.d.ts +0 -1
  247. package/dist/writeProtectionCapability.js +5 -10
  248. package/docs/INTEGRATION-CLIENTS.md +1033 -26
  249. package/package.json +5 -5
  250. package/dist/engineCapsGenerationGuard.d.ts +0 -4
  251. package/dist/engineCapsGenerationGuard.js +0 -19
  252. package/dist/panelRunningHistory.d.ts +0 -22
  253. package/dist/panelRunningHistory.js +0 -82
  254. package/dist/registryConflict.d.ts +0 -3
  255. package/dist/registryConflict.js +0 -44
@@ -9,7 +9,7 @@ import { recordEngineToolLabel } from '../engineToolLabelStore.js';
9
9
  import { registerSubagentAlias, registerSubagentContentAlias } from '../subagentContentStore.js';
10
10
  import { readAsyncLaunchedAgentReceipt } from '../toolResult.js';
11
11
  import { recordWorkflowAgentTaskId } from '../workflow.js';
12
- import { isTerminalStatus } from '../runTerminal.js';
12
+ import { isCoreTaskNotificationTerminal, isCoreTaskNotificationTerminalNotSuccess, isCoreTaskProgressTerminal, isCoreTaskProgressTerminalNotSuccess } from '../terminalStatuses.js';
13
13
  import { readToolHistoryMismatchKey } from '../toolHistoryMismatch.js';
14
14
  import { readProviderRejectionResendKey } from '../providerRejection.js';
15
15
  import { readFrameStringKey } from '../ownKey.js';
@@ -572,7 +572,6 @@ const toolEndResultArm = function* (m, { idOf, cards, panel }) {
572
572
  });
573
573
  }
574
574
  };
575
- const TERMINAL_TICK_STATUSES = new Set(['completed', 'failed']);
576
575
  const taskProgressArm = function* (m, { ctx, cards, panel, inst }) {
577
576
  const taskIdRaw = m.taskId;
578
577
  const taskId = typeof taskIdRaw === 'string' ? taskIdRaw : undefined;
@@ -661,9 +660,9 @@ const taskProgressArm = function* (m, { ctx, cards, panel, inst }) {
661
660
  totalTokens: typeof usage.totalTokens === 'number' ? usage.totalTokens : 0,
662
661
  },
663
662
  });
664
- if (typeof m.status === 'string' && TERMINAL_TICK_STATUSES.has(m.status) && !panel.isLiveBound(taskId)) {
663
+ if (isCoreTaskProgressTerminal(m.status) && !panel.isLiveBound(taskId)) {
665
664
  ctx.probe?.('tick', JSON.stringify({ t: ctx.now(), taskId, lane: 'foreground', settle: m.status }));
666
- yield* panel.settleFromTerminalTick(taskId, m.status === 'failed');
665
+ yield* panel.settleFromTerminalTick(taskId, isCoreTaskProgressTerminalNotSuccess(m.status));
667
666
  }
668
667
  };
669
668
  const streamEventArm = function* (m, { text }) {
@@ -766,7 +765,7 @@ const taskNotificationArm = function* (m, { ctx, idOf, panel, inst }) {
766
765
  return;
767
766
  const taskId = fields.taskId;
768
767
  const rawStatus = fields.status;
769
- const terminal = isTerminalStatus(rawStatus);
768
+ const terminal = isCoreTaskNotificationTerminal(rawStatus);
770
769
  const settleAllowed = n.task_type === undefined || n.task_type === 'background_bash' || n.task_type === 'monitor';
771
770
  if (settleAllowed && terminal) {
772
771
  yield chrome({
@@ -798,7 +797,7 @@ const taskNotificationArm = function* (m, { ctx, idOf, panel, inst }) {
798
797
  });
799
798
  dropQueuedNotificationsForRun(taskId);
800
799
  if (n.task_type !== 'background_bash' && n.task_type !== 'monitor') {
801
- yield* panel.settleFromNotification(taskId, rawStatus !== 'completed');
800
+ yield* panel.settleFromNotification(taskId, isCoreTaskNotificationTerminalNotSuccess(rawStatus));
802
801
  }
803
802
  }
804
803
  const peerFrame = classifyPeerNotification(n);
@@ -1,9 +1,9 @@
1
1
  import { clearEnginePanelTaskResident, clearEnginePanelTaskResidentByWire, markEnginePanelTaskResident } from '../engineAgentPanelStore.js';
2
+ import { panelEndFact } from '../panelReduce.js';
2
3
  import { chrome, mainLane } from './ids.js';
3
4
  import { SUBAGENT_TOOL_NAMES } from './wireShapes.js';
4
5
  export function createPanelTaskLedger(ctx, cards, inst) {
5
6
  const taskCardBinding = new Map();
6
- const boundToolCalls = new Set();
7
7
  const livePanelTasks = new Set();
8
8
  const endedPanelTasks = new Set();
9
9
  const liveBoundPanelTasks = new Set();
@@ -33,7 +33,6 @@ export function createPanelTaskLedger(ctx, cards, inst) {
33
33
  return undefined;
34
34
  const target = parentToolCallId;
35
35
  taskCardBinding.set(taskId, target);
36
- boundToolCalls.add(target);
37
36
  if (cards.has(target))
38
37
  liveBoundPanelTasks.add(taskId);
39
38
  ctx.probe?.('bind', `bind ${taskId} -> ${target} via=explicit`);
@@ -85,12 +84,7 @@ export function createPanelTaskLedger(ctx, cards, inst) {
85
84
  yield chrome({
86
85
  kind: 'panel_task',
87
86
  laneProof: mintLane(),
88
- event: {
89
- kind: 'end',
90
- taskId,
91
- isError,
92
- ...(cardId !== null && report !== undefined ? { report } : {}),
93
- },
87
+ event: panelEndFact(taskId, isError, cardId !== null && report !== undefined ? { report } : undefined),
94
88
  });
95
89
  }
96
90
  },
@@ -102,7 +96,7 @@ export function createPanelTaskLedger(ctx, cards, inst) {
102
96
  yield chrome({
103
97
  kind: 'panel_task',
104
98
  laneProof: mainLane(),
105
- event: { kind: 'end', taskId, isError },
99
+ event: panelEndFact(taskId, isError),
106
100
  });
107
101
  if (inst.hasFiredSubagentStart(taskId)) {
108
102
  yield chrome({
@@ -144,7 +138,7 @@ export function createPanelTaskLedger(ctx, cards, inst) {
144
138
  yield chrome({
145
139
  kind: 'panel_task',
146
140
  laneProof: mintLane(),
147
- event: { kind: 'end', taskId, isError },
141
+ event: panelEndFact(taskId, isError),
148
142
  });
149
143
  },
150
144
  };
@@ -34,15 +34,15 @@ export function createToolCardLedger(ctx, idOf) {
34
34
  let lastLiveTodos = [];
35
35
  function* buildToolResult(p, end) {
36
36
  const isError = end?.isError ?? false;
37
+ const parentToolCallId = end?.parentToolCallId ?? p.parentToolCallId;
37
38
  if ((p.name === 'Bash' || p.name === 'Monitor') && !isError) {
38
39
  const outputText = end?.output !== undefined ? flattenWireOutput(end.output) : undefined;
39
40
  const reg = detectEngineBgShellDetach(p.name, p.rawInput, end?.structured, outputText) ??
40
41
  detectEngineBgShellReceipt(p.name, p.rawInput, outputText, end?.structured);
41
42
  if (reg !== null) {
42
- yield chrome({ kind: 'bgshell_register', laneProof: mainLane(), taskId: reg.taskId, registration: reg });
43
+ yield chrome({ kind: 'bgshell_register', laneProof: parentToolCallId === undefined ? mainLane() : { lane: 'subagent', parentToolCallId }, taskId: reg.taskId, registration: reg });
43
44
  }
44
45
  }
45
- const parentToolCallId = end?.parentToolCallId ?? p.parentToolCallId;
46
46
  const outcome = toolResultOutcomeOf(p.name, end, p.rawInput, parentToolCallId === undefined ? 'leader' : 'subagent', (err) => {
47
47
  if (p.name !== 'TodoWrite')
48
48
  return null;
@@ -1,4 +1,5 @@
1
1
  import { frozenSet } from '../frozenSet.js';
2
+ import { stripToolUseSideChannels } from '../adapter/types.js';
2
3
  export const FLUSH_INTERVAL_MS = 100;
3
4
  export const IDLE_FLUSH_MS = 1500;
4
5
  export const SUBAGENT_TOOL_NAMES = frozenSet(['Task', 'Agent', 'Fork']);
@@ -47,14 +48,8 @@ export function shortTaskLabel(task) {
47
48
  return label || 'subagent';
48
49
  }
49
50
  export function sanitizeToolUseBlock(block) {
50
- const out = { ...block };
51
- const rawInput = out.input;
52
- const eventId = typeof out.eventId === 'string' ? out.eventId : undefined;
53
- const parentToolCallId = typeof out.parentToolCallId === 'string' ? out.parentToolCallId : undefined;
54
- const label = typeof out.label === 'string' ? out.label : undefined;
55
- delete out.label;
56
- delete out.eventId;
57
- delete out.parentToolCallId;
51
+ const rawInput = block.input;
52
+ const { block: out, eventId, parentToolCallId, label } = stripToolUseSideChannels(block);
58
53
  if (out.input && typeof out.input === 'object') {
59
54
  const cleaned = {};
60
55
  for (const [k, val] of Object.entries(out.input)) {
@@ -1,5 +1,6 @@
1
1
  import type { ActiveRunBusySignal } from './runStream.js';
2
2
  import type { PlanReviewReopenTrigger } from '../hitl/planReviewWire.js';
3
+ import { atMostOnceFailureClass } from '../atMostOnce.js';
3
4
  export declare const PLAN_REVIEW_GATE_KIND = "plan_review";
4
5
  export declare const PLAN_REVIEW_GATE_KINDS: readonly string[];
5
6
  export declare const ASK_PARK_GATE_KINDS: readonly string[];
@@ -9,7 +10,6 @@ export declare function askParkForeignGateKind(row: {
9
10
  export declare const PLAN_REVIEW_STATES: readonly string[];
10
11
  export declare const ASK_PARK_STATES: readonly string[];
11
12
  export declare const RUNNING_STATES: readonly string[];
12
- export declare const CLAIM_RELEASED_STATES: readonly string[];
13
13
  export declare const CLAIM_HELD_STATES: readonly string[];
14
14
  export interface DurableRunRecordView {
15
15
  readonly status?: unknown;
@@ -47,6 +47,7 @@ export interface RunningChoiceRequest {
47
47
  status: string;
48
48
  canSteer: boolean;
49
49
  canCancel: boolean;
50
+ canAttach?: true;
50
51
  }
51
52
  export interface StaleParkChoiceRequest {
52
53
  taskId: string;
@@ -62,7 +63,8 @@ export interface ActiveRunSelfHealDeps {
62
63
  trigger?: PlanReviewReopenTrigger;
63
64
  }) => ReopenCardVerdict | Promise<ReopenCardVerdict>;
64
65
  reopenAskPark?: (taskId: string) => Promise<ReopenCardVerdict>;
65
- offerRunningChoice?: (req: RunningChoiceRequest) => Promise<'steer' | 'cancel' | 'wait'>;
66
+ offerRunningChoice?: (req: RunningChoiceRequest) => Promise<'steer' | 'cancel' | 'wait' | 'attach'>;
67
+ canAttachRunning?: boolean;
66
68
  offerStaleParkChoice?: (req: StaleParkChoiceRequest) => Promise<'cancel' | 'wait'>;
67
69
  deniedMessage?: string;
68
70
  signal?: AbortSignal;
@@ -134,6 +136,9 @@ export type SelfHealOutcome = {
134
136
  taskId: string;
135
137
  detail: string;
136
138
  delivery: 'rejected' | 'unknown';
139
+ } | {
140
+ kind: 'running-attach';
141
+ taskId: string;
137
142
  } | {
138
143
  kind: 'running-cancelled';
139
144
  taskId: string;
@@ -191,7 +196,7 @@ export interface SelfHealFollowDeclaration {
191
196
  following?: boolean;
192
197
  }
193
198
  export declare function readCancelRequested(body: unknown): boolean | undefined;
194
- export declare function atMostOnceFailureClass(e: unknown): 'rejected' | 'unknown';
199
+ export { atMostOnceFailureClass };
195
200
  export declare function clearRunningChoiceOffer(taskId: string, sessionId?: string): void;
196
201
  export declare function __resetRunningChoiceLedgerForTests(): void;
197
202
  export interface ClaimReleaseVerdict {
@@ -1,7 +1,10 @@
1
1
  import { abortableSleep } from '../abortableSleep.js';
2
2
  import { corruptStoredRowContent, corruptStoredRowWhere, effectiveWireErrorCode } from '../wireErrorTriage.js';
3
- import { steerBodyOf, steeringRefusedBeforeEngine, steeringStatusIs4xx, UNOBSERVED_STEER_PRIORITY } from '../controlRouter.js';
3
+ import { steerBodyOf, UNOBSERVED_STEER_PRIORITY } from '../controlRouter.js';
4
+ import { atMostOnceFailureClass } from '../atMostOnce.js';
4
5
  import { readSteerReceipt } from '../steerReceipt.js';
6
+ import { resumeAttachReplayDisclosure, runningAttachOffered } from '../hitl/resumeRunningCard.js';
7
+ import { isSdkRunTerminal, SDK_PARKED_RUN_STATUSES } from '../terminalStatuses.js';
5
8
  export const PLAN_REVIEW_GATE_KIND = 'plan_review';
6
9
  export const PLAN_REVIEW_GATE_KINDS = Object.freeze([PLAN_REVIEW_GATE_KIND, 'dry_run_review']);
7
10
  export const ASK_PARK_GATE_KINDS = Object.freeze(['human', 'irreversible_ask', 'policy_ask', 'tool_approval']);
@@ -12,8 +15,7 @@ export function askParkForeignGateKind(row) {
12
15
  export const PLAN_REVIEW_STATES = Object.freeze(['needs_review']);
13
16
  export const ASK_PARK_STATES = Object.freeze(['suspended']);
14
17
  export const RUNNING_STATES = Object.freeze(['running']);
15
- export const CLAIM_RELEASED_STATES = Object.freeze(['completed', 'failed', 'blocked', 'timeout']);
16
- export const CLAIM_HELD_STATES = Object.freeze(['running', 'suspended', 'needs_review']);
18
+ export const CLAIM_HELD_STATES = Object.freeze(['running', ...SDK_PARKED_RUN_STATUSES]);
17
19
  export function selfHealSubmissionDisposition(outcome) {
18
20
  switch (outcome.kind) {
19
21
  case 'decision-pending':
@@ -29,6 +31,8 @@ export function selfHealSubmissionDisposition(outcome) {
29
31
  return 'not-delivered';
30
32
  case 'running-steered':
31
33
  return 'handed-off';
34
+ case 'running-attach':
35
+ return 'not-delivered';
32
36
  default:
33
37
  return 'not-delivered';
34
38
  }
@@ -261,11 +265,7 @@ function reopenedOfOutcome(outcome) {
261
265
  return null;
262
266
  }
263
267
  }
264
- export function atMostOnceFailureClass(e) {
265
- if (typeof e === 'object' && e !== null && steeringStatusIs4xx(e))
266
- return 'rejected';
267
- return typeof e === 'object' && e !== null && steeringRefusedBeforeEngine(e) !== undefined ? 'rejected' : 'unknown';
268
- }
268
+ export { atMostOnceFailureClass };
269
269
  const CANCEL_RELEASE_WAIT_MS = 10_000;
270
270
  const RUNNING_LIVENESS_RECHECK_TIMEOUT_MS = 4_000;
271
271
  const runningChoiceDeclined = new Set();
@@ -365,7 +365,7 @@ export async function waitForClaimRelease(taskId, deps) {
365
365
  if (holder === 'released') {
366
366
  return { released: true, waitedMs: waited(), aborted: false, lastStatus: status, lastHolder: holder };
367
367
  }
368
- if (status !== null && CLAIM_RELEASED_STATES.includes(status)) {
368
+ if (isSdkRunTerminal(status)) {
369
369
  return { released: true, waitedMs: waited(), aborted: false, lastStatus: status, lastHolder: holder };
370
370
  }
371
371
  }
@@ -698,7 +698,8 @@ async function runningChoiceArm(taskId, status, busy, statusFromWire, runs, deps
698
698
  const text = typeof deps?.deniedMessage === 'string' ? deps.deniedMessage : '';
699
699
  const canSteer = typeof runs?.steer === 'function' && text.length > 0;
700
700
  const canCancel = typeof runs?.cancel === 'function' && typeof runs?.get === 'function';
701
- if (!canSteer && !canCancel)
701
+ const canAttach = runningAttachOffered(deps?.canAttachRunning);
702
+ if (!canSteer && !canCancel && !canAttach)
702
703
  return notParked;
703
704
  if (injected && !canSteer)
704
705
  return notParked;
@@ -715,7 +716,7 @@ async function runningChoiceArm(taskId, status, busy, statusFromWire, runs, deps
715
716
  return planReviewArm(taskId, busy, deps);
716
717
  if (ASK_PARK_STATES.includes(fresh))
717
718
  return askParkArm(taskId, busy, runs, deps);
718
- if (CLAIM_RELEASED_STATES.includes(fresh))
719
+ if (isSdkRunTerminal(fresh))
719
720
  return { kind: 'running-settled', taskId, status: fresh };
720
721
  return { kind: 'not-parked', taskId, status: fresh };
721
722
  }
@@ -733,7 +734,7 @@ async function runningChoiceArm(taskId, status, busy, statusFromWire, runs, deps
733
734
  }
734
735
  else if (typeof offer === 'function') {
735
736
  try {
736
- choice = (await offer({ taskId, status, canSteer, canCancel })) ?? 'wait';
737
+ choice = (await offer({ taskId, status, canSteer, canCancel, ...(canAttach ? { canAttach: true } : {}) })) ?? 'wait';
737
738
  offerDelivered = true;
738
739
  }
739
740
  catch {
@@ -783,6 +784,8 @@ async function runningChoiceArm(taskId, status, busy, statusFromWire, runs, deps
783
784
  confirmedHeld: verdict.confirmedHeld,
784
785
  };
785
786
  }
787
+ if (choice === 'attach' && canAttach)
788
+ return { kind: 'running-attach', taskId };
786
789
  return notParked;
787
790
  }
788
791
  export const INTERACTIVE_WAY_OUT = 'run /clear to keep working in a fresh session';
@@ -841,6 +844,9 @@ const NO_CARD_VIEW_ATTACHED = 'this session has no view attached that can show d
841
844
  function injectedSubmissionRow(outcome, following = false) {
842
845
  const lead = INJECTED_LEAD;
843
846
  const id = 'taskId' in outcome && outcome.taskId ? ` (id ${outcome.taskId})` : '';
847
+ if (outcome.kind === 'running-attach') {
848
+ return `${lead} was not delivered: you chose to watch the reply already in progress${id} instead, and sema is replaying that reply here, so the part already shown above will appear again below. sema did not retry, so the model has not seen it.`;
849
+ }
844
850
  if (outcome.kind === 'running-steer-failed') {
845
851
  return outcome.delivery === 'unknown'
846
852
  ? `${lead} was passed to the reply already in progress${id}, but its delivery could not be confirmed ` +
@@ -1057,6 +1063,8 @@ function activeRunSelfHealBaseRow(outcome, signal, wayOut, following = false, ke
1057
1063
  `to it (${outcome.detail}). A steer is not safe to send twice, so sema did NOT retry it, and it did NOT ` +
1058
1064
  `cancel that run. That run may or may not have received your message — watch what it does next ` +
1059
1065
  `before sending it again.`);
1066
+ case 'running-attach':
1067
+ return (`${resumeAttachReplayDisclosure(outcome.taskId)} Your message was NOT sent; send it again once that run has finished.`);
1060
1068
  case 'running-cancelled':
1061
1069
  return outcome.releaseConfirmedByEngine === true
1062
1070
  ? `You chose to cancel run ${outcome.taskId}. The engine confirmed it is no longer holding this session, ` +
@@ -5,8 +5,10 @@ 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 { SEGMENT_END_IDENTITY_KEYS } from '../types.js';
8
+ import { markMcpSectionDroppedNamedRows } from '../../ownKey.js';
9
+ import { SEGMENT_END_IDENTITY_KEYS, stripToolUseSideChannels } from '../types.js';
9
10
  import { frozenSet } from '../../frozenSet.js';
11
+ import { isCoreWorkflowRunTerminal } from '../../terminalStatuses.js';
10
12
  function armBody(body) {
11
13
  return body;
12
14
  }
@@ -104,13 +106,13 @@ export function eventToSdkMessage(ev, ctx) {
104
106
  if (typeof ev.runId !== 'string' || ev.runId.length === 0) {
105
107
  return dropped('malformed', 'workflow_complete');
106
108
  }
107
- if (ev.status !== 'completed' && ev.status !== 'failed') {
109
+ if (!isCoreWorkflowRunTerminal(ev.status)) {
108
110
  return dropped('malformed', 'workflow_complete');
109
111
  }
110
112
  return projected(stamp(ctx, armBody({
111
113
  type: 'workflow_complete',
112
114
  runId: ev.runId,
113
- status: ev.status === 'failed' ? 'failed' : 'completed',
115
+ status: ev.status,
114
116
  summary: typeof ev.summary === 'string' ? ev.summary : '',
115
117
  })));
116
118
  }
@@ -126,20 +128,21 @@ export function eventToSdkMessage(ev, ctx) {
126
128
  delta: ev.delta,
127
129
  ...(ev.parentToolCallId !== undefined ? { parentToolCallId: ev.parentToolCallId } : {}),
128
130
  }));
129
- case 'tool_start':
130
- return projected(assistantArm(ctx, [
131
- {
132
- type: 'tool_use',
133
- id: ev.toolCallId,
134
- name: ev.toolName,
135
- input: ev.args,
136
- ...(typeof ev.label === 'string' && ev.label.length > 0 ? { label: ev.label } : {}),
137
- ...(ev.eventId !== undefined ? { eventId: ev.eventId } : {}),
138
- ...(ev.parentToolCallId !== undefined
139
- ? { parentToolCallId: ev.parentToolCallId }
140
- : {}),
141
- },
142
- ], ev.eventId, ev.parentToolCallId));
131
+ case 'tool_start': {
132
+ const toolUse = {
133
+ type: 'tool_use',
134
+ id: ev.toolCallId,
135
+ name: ev.toolName,
136
+ input: ev.args,
137
+ ...(typeof ev.label === 'string' && ev.label.length > 0 ? { label: ev.label } : {}),
138
+ ...(ev.eventId !== undefined ? { eventId: ev.eventId } : {}),
139
+ ...(ev.parentToolCallId !== undefined
140
+ ? { parentToolCallId: ev.parentToolCallId }
141
+ : {}),
142
+ };
143
+ const outBlock = ctx.lane === 'print' ? stripToolUseSideChannels(toolUse).block : toolUse;
144
+ return projected(assistantArm(ctx, [outBlock], ev.eventId, ev.parentToolCallId));
145
+ }
143
146
  case 'compacted': {
144
147
  const raw = ev;
145
148
  const freedTokens = typeof raw.freedTokens === 'number' && Number.isFinite(raw.freedTokens) && raw.freedTokens >= 0 ? raw.freedTokens : undefined;
@@ -470,12 +473,15 @@ export function projectMcpSection(raw) {
470
473
  if (!Array.isArray(raw))
471
474
  return undefined;
472
475
  const rows = [];
476
+ const droppedNamed = new Map();
473
477
  for (const e of raw) {
474
478
  if (typeof e !== 'object' || e === null || Array.isArray(e))
475
479
  continue;
476
480
  const r = e;
477
481
  const name = typeof r.name === 'string' && r.name.length > 0 ? r.name : undefined;
478
482
  const status = typeof r.status === 'string' && r.status.length > 0 ? r.status : undefined;
483
+ if (name !== undefined && status === undefined)
484
+ droppedNamed.set(name, (droppedNamed.get(name) ?? 0) + 1);
479
485
  if (name === undefined || status === undefined)
480
486
  continue;
481
487
  rows.push({
@@ -491,6 +497,7 @@ export function projectMcpSection(raw) {
491
497
  }
492
498
  if (raw.length > 0 && rows.length === 0)
493
499
  return undefined;
500
+ markMcpSectionDroppedNamedRows(rows, droppedNamed);
494
501
  return rows;
495
502
  }
496
503
  function projectModelGateSection(raw) {
@@ -79,6 +79,11 @@ function permissionDenialParts(stats, observed) {
79
79
  const hr = stats?.humanReview;
80
80
  const gatesRaw = hr !== null && typeof hr === 'object' ? hr.gates : undefined;
81
81
  const denials = [];
82
+ const mergedKindOf = (callId) => (denialKindByCallId?.has(callId) === true ? denialKindByCallId.get(callId) : undefined);
83
+ const settledAsAbort = (callId) => {
84
+ const k = mergedKindOf(callId);
85
+ return isCcToolDenialKind(k) && !isCcToolDenialKindADenial(k);
86
+ };
82
87
  const gates = Array.isArray(gatesRaw) ? gatesRaw : [];
83
88
  let complete = Array.isArray(gatesRaw);
84
89
  for (const g of gates) {
@@ -100,6 +105,8 @@ function permissionDenialParts(stats, observed) {
100
105
  const toolName = nonEmptyStr(row.toolName);
101
106
  const toolArg = nonEmptyStr(row.toolArg);
102
107
  const toolUseId = nonEmptyStr(row.toolCallId);
108
+ if (toolUseId !== undefined && settledAsAbort(toolUseId))
109
+ continue;
103
110
  const rawInput = row.toolInput;
104
111
  const ledgerInput = rawInput !== null && typeof rawInput === 'object' && !Array.isArray(rawInput)
105
112
  ? rawInput
@@ -151,9 +158,9 @@ function permissionDenialParts(stats, observed) {
151
158
  for (const [callId, toolNameRaw] of deniedToolNameByCallId) {
152
159
  if (typeof callId !== 'string' || callId.length === 0 || ledgerDeniedIds.has(callId))
153
160
  continue;
154
- const mergedKind = denialKindByCallId?.has(callId) === true ? denialKindByCallId.get(callId) : undefined;
155
- if (isCcToolDenialKind(mergedKind) && !isCcToolDenialKindADenial(mergedKind))
161
+ if (settledAsAbort(callId))
156
162
  continue;
163
+ const mergedKind = mergedKindOf(callId);
157
164
  if (ledgerHasIdlessDenial) {
158
165
  complete = false;
159
166
  continue;
@@ -178,7 +185,8 @@ function permissionDenialParts(stats, observed) {
178
185
  complete = false;
179
186
  }
180
187
  const ccList = denials.filter((d) => d.tool_name !== undefined && d.tool_use_id !== undefined && d.tool_input !== undefined);
181
- const claimable = complete && ccList.length === denials.length;
188
+ const streamCoversRun = observed?.streamSawRunOpen === true && observed.deniedToolNameByCallId !== undefined;
189
+ const claimable = complete && ccList.length === denials.length && streamCoversRun;
182
190
  const zeroOutputDenied = denials.length > 0 && observed?.streamSawRunOpen === true && observed.successfulToolEndObserved === false;
183
191
  return {
184
192
  permission_denials: ccList,
@@ -60,7 +60,8 @@ export function activeRunBusySignal(ev) {
60
60
  const result = ev.result;
61
61
  if (typeof result !== 'object' || result === null)
62
62
  return null;
63
- if (result.status !== 'failed')
63
+ const status = result.status;
64
+ if (status !== 'failed' && (status !== undefined || Array.isArray(result)))
64
65
  return null;
65
66
  carrier = result;
66
67
  }
@@ -31,6 +31,13 @@ export declare function stamp<T extends {
31
31
  uuid: string;
32
32
  session_id: string;
33
33
  };
34
+ export interface ToolUseSideChannelsStripped<B extends object> {
35
+ readonly block: Omit<B, 'label' | 'eventId' | 'parentToolCallId'>;
36
+ readonly eventId?: string;
37
+ readonly parentToolCallId?: string;
38
+ readonly label?: string;
39
+ }
40
+ export declare function stripToolUseSideChannels<B extends object>(block: B): ToolUseSideChannelsStripped<B>;
34
41
  export declare const SEGMENT_END_IDENTITY_KEYS: readonly ["parentToolCallId", "sourceTaskId", "bgAgentId"];
35
42
  export declare function isSubFlowSegmentEnd(m: object): boolean;
36
43
  export declare function snapshotSegmentIdentity(m: object): Record<string, unknown> | null;
@@ -14,6 +14,21 @@ export function uuid() {
14
14
  export function stamp(ctx, body) {
15
15
  return { ...body, uuid: body.uuid ?? uuid(), session_id: ctx.sessionId };
16
16
  }
17
+ export function stripToolUseSideChannels(block) {
18
+ const out = { ...block };
19
+ const eventId = typeof out.eventId === 'string' ? out.eventId : undefined;
20
+ const parentToolCallId = typeof out.parentToolCallId === 'string' ? out.parentToolCallId : undefined;
21
+ const label = typeof out.label === 'string' ? out.label : undefined;
22
+ delete out.label;
23
+ delete out.eventId;
24
+ delete out.parentToolCallId;
25
+ return {
26
+ block: out,
27
+ ...(eventId !== undefined ? { eventId } : {}),
28
+ ...(parentToolCallId !== undefined ? { parentToolCallId } : {}),
29
+ ...(label !== undefined ? { label } : {}),
30
+ };
31
+ }
17
32
  export const SEGMENT_END_IDENTITY_KEYS = Object.freeze(['parentToolCallId', 'sourceTaskId', 'bgAgentId']);
18
33
  export function isSubFlowSegmentEnd(m) {
19
34
  const rec = m;
@@ -157,7 +157,11 @@ export function createBackgroundView(client, opts) {
157
157
  }
158
158
  catch (err) {
159
159
  debugLog(`assistant.tasks degrade: ${String(err)}`);
160
- const health = capsApprovals === false || isNotImplemented(err) ? 'not-configured' : 'unavailable';
160
+ const health = capsApprovals === false || isNotImplemented(err)
161
+ ? 'not-configured'
162
+ : isReadCredentialRefusal(err)
163
+ ? 'unauthorized'
164
+ : 'unavailable';
161
165
  return { health, tasks: [] };
162
166
  }
163
167
  }
@@ -1,5 +1,6 @@
1
1
  import { errCodes } from '../controlRouter.js';
2
2
  import { hostLog } from '../host.js';
3
+ import { isSessionIdPathSegment } from '../sessionIdSegment.js';
3
4
  const unavailable = (why) => ({
4
5
  kind: 'unavailable',
5
6
  why,
@@ -95,7 +96,7 @@ export async function readEngineAgentRegistry(client, sessionId, caps, opts) {
95
96
  async function readOnce(client, sessionId, caps, opts) {
96
97
  if (!listFaceOn(caps))
97
98
  return unavailable('no_list_face');
98
- if (typeof sessionId !== 'string' || sessionId.length === 0) {
99
+ if (!isSessionIdPathSegment(sessionId)) {
99
100
  noteReadFailed('bad session id');
100
101
  return unavailable('read_failed');
101
102
  }
@@ -3,10 +3,11 @@ 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';
5
5
  import { hostLog } from '../host.js';
6
+ import { isSessionIdPathSegment } from '../sessionIdSegment.js';
6
7
  import { wireFailureTextsOf } from '../wireFailureShape.js';
7
8
  import { DEFAULT_SESSION_KEY } from '../sessionSlot.js';
8
9
  const NOTHING_SENT = ' — nothing sent';
9
- const DETAIL_BAD_SESSION = `the session id must be a non-empty string${NOTHING_SENT}`;
10
+ const DETAIL_BAD_SESSION = `the session id must be a non-empty string that is not a dot segment${NOTHING_SENT}`;
10
11
  const DETAIL_BAD_INCLUDE_RETAINED = `includeRetained must be true or false (the engine has no default for it)${NOTHING_SENT}`;
11
12
  const DETAIL_BAD_OPTIONS = `the options could not be read${NOTHING_SENT}`;
12
13
  const DETAIL_BAD_ARGUMENTS = `the arguments could not be read${NOTHING_SENT}`;
@@ -202,7 +203,7 @@ export async function stopEngineSessionBackground(sessionId, body, opts) {
202
203
  let signal;
203
204
  let sessionKey;
204
205
  try {
205
- if (typeof sessionId !== 'string' || sessionId.length === 0)
206
+ if (!isSessionIdPathSegment(sessionId))
206
207
  return unavailable('bad_input', DETAIL_BAD_SESSION);
207
208
  const flag = typeof body === 'object' && body !== null && Object.hasOwn(body, 'includeRetained') ? body.includeRetained : undefined;
208
209
  if (typeof flag !== 'boolean')
@@ -15,6 +15,8 @@ export type TaskAgentWireSkill = {
15
15
  name: string;
16
16
  description: string;
17
17
  content: string;
18
+ allowedTools?: string[];
19
+ disallowedTools?: string[];
18
20
  };
19
21
  export declare const AGENT_MEMORY_WORDS: ReadonlySet<string>;
20
22
  export type TaskAgentWireMemory = {
@@ -12,5 +12,4 @@ export declare function noteEngineCapsForApprovalDecidedBy(baseUrl: string, caps
12
12
  }): void;
13
13
  export declare function observedApprovalDecidedBy(baseUrl?: string | undefined): ApprovalDecidedByReading;
14
14
  export declare function approvalDecidedByAdmitted(reading: ApprovalDecidedByReading | undefined): boolean;
15
- export declare function forgetApprovalDecidedByReading(baseUrl: string | undefined): void;
16
15
  export declare function __resetApprovalDecidedByReadingsForTests(): void;
@@ -1,13 +1,11 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
- import { readOwnDataValue } from './ownKey.js';
3
+ import { ownDataField, readOwnDataValue } from './ownKey.js';
4
4
  export function projectApprovalDecidedByCapability(caps) {
5
5
  try {
6
6
  if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
7
7
  return undefined;
8
- if (!Object.hasOwn(caps, 'approvalDecidedBy'))
9
- return { kind: 'not_reported' };
10
- const v = caps.approvalDecidedBy;
8
+ const v = ownDataField(caps, 'approvalDecidedBy');
11
9
  if (v === undefined)
12
10
  return { kind: 'not_reported' };
13
11
  return v === true ? { kind: 'present', value: true } : undefined;
@@ -39,9 +37,6 @@ export function approvalDecidedByAdmitted(reading) {
39
37
  return false;
40
38
  }
41
39
  }
42
- export function forgetApprovalDecidedByReading(baseUrl) {
43
- reader.forget(baseUrl);
44
- }
45
40
  export function __resetApprovalDecidedByReadingsForTests() {
46
41
  reader.__resetForTests();
47
42
  }
@@ -13,5 +13,4 @@ export declare function noteEngineCapsForApprovalsStreamLive(baseUrl: string, ca
13
13
  export declare function observedApprovalsStreamLive(baseUrl?: string | undefined): ApprovalsStreamLiveReading;
14
14
  export declare function livePendingNeedsReconcile(reading: ApprovalsStreamLiveReading): boolean;
15
15
  export declare function approvalsStreamLiveDoctorDetail(reading: ApprovalsStreamLiveReading): string;
16
- export declare function forgetApprovalsStreamLiveReading(baseUrl: string | undefined): void;
17
16
  export declare function __resetApprovalsStreamLiveReadingsForTests(): void;
@@ -1,14 +1,13 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
+ import { ownDataField } from './ownKey.js';
3
4
  export function projectApprovalsStreamLiveCapability(caps) {
4
5
  try {
5
6
  if (caps === null || typeof caps !== 'object')
6
7
  return undefined;
7
8
  if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
8
9
  return undefined;
9
- if (!Object.hasOwn(caps, 'approvalsStreamLive'))
10
- return { kind: 'not_reported' };
11
- const v = caps.approvalsStreamLive;
10
+ const v = ownDataField(caps, 'approvalsStreamLive');
12
11
  if (v === undefined)
13
12
  return { kind: 'not_reported' };
14
13
  if (typeof v !== 'boolean')
@@ -45,9 +44,6 @@ export function approvalsStreamLiveDoctorDetail(reading) {
45
44
  : 'live approval push off on this deployment (no checkpoint store or tool approvals disabled; the engine reports one bit for both, so this client cannot tell which) — suspended asks are only visible through the reconcile cadence, so the client polls for them';
46
45
  }
47
46
  }
48
- export function forgetApprovalsStreamLiveReading(baseUrl) {
49
- reader.forget(baseUrl);
50
- }
51
47
  export function __resetApprovalsStreamLiveReadingsForTests() {
52
48
  reader.__resetForTests();
53
49
  }
@@ -0,0 +1,8 @@
1
+ export declare function atMostOnceFailureClass(e: unknown): 'rejected' | 'unknown';
2
+ export interface AtMostOnceVerdict {
3
+ readonly delivery: 'rejected' | 'unknown';
4
+ readonly status?: number;
5
+ readonly code?: string;
6
+ readonly name?: string;
7
+ }
8
+ export declare function atMostOnceVerdictOf(e: unknown): AtMostOnceVerdict;