@sema-agent/client-core 0.100.0 → 0.101.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 (335) hide show
  1. package/CHANGELOG.md +395 -0
  2. package/README.md +164 -117
  3. package/dist/adapt/arms.js +51 -16
  4. package/dist/adapt/textStream.js +7 -4
  5. package/dist/adapt/toolCards.js +9 -8
  6. package/dist/adapt.js +7 -1
  7. package/dist/adapter/activeRunSelfHeal.d.ts +24 -2
  8. package/dist/adapter/activeRunSelfHeal.js +108 -6
  9. package/dist/adapter/downstream/eventToSdkMessage.js +33 -12
  10. package/dist/adapter/downstream/terminalToSdkResult.d.ts +60 -1
  11. package/dist/adapter/downstream/terminalToSdkResult.js +209 -39
  12. package/dist/adapter/runStream.d.ts +4 -4
  13. package/dist/adapter/runStream.js +158 -43
  14. package/dist/agentsWireCaps.d.ts +2 -7
  15. package/dist/agentsWireCaps.js +1 -2
  16. package/dist/approvalDecidedByCapability.js +2 -2
  17. package/dist/approvalFrameFamilies.d.ts +33 -0
  18. package/dist/approvalFrameFamilies.js +120 -0
  19. package/dist/approvalsStreamLiveCapability.js +2 -2
  20. package/dist/attachmentsWireCaps.js +41 -13
  21. package/dist/callerCwdCapability.js +2 -2
  22. package/dist/centerWiringCapability.js +2 -2
  23. package/dist/clockReading.d.ts +2 -0
  24. package/dist/clockReading.js +4 -0
  25. package/dist/cloudConfigWireCaps.d.ts +19 -5
  26. package/dist/cloudConfigWireCaps.js +193 -56
  27. package/dist/coreValuePorts.d.ts +12 -2
  28. package/dist/coreValuePorts.js +9 -0
  29. package/dist/decideFailureNote.js +5 -3
  30. package/dist/decideReceipt.js +2 -2
  31. package/dist/deviceExecutorManagementCapability.js +2 -2
  32. package/dist/deviceFlowPolling.js +1 -1
  33. package/dist/disableSkillsWire.d.ts +1 -1
  34. package/dist/disableSkillsWire.js +4 -3
  35. package/dist/displayUntrusted.d.ts +1 -0
  36. package/dist/displayUntrusted.js +65 -8
  37. package/dist/engineCapReader.js +1 -1
  38. package/dist/engineConfigDrift.js +1 -1
  39. package/dist/engineErrorCodes.d.ts +14 -5
  40. package/dist/engineErrorCodes.js +27 -6
  41. package/dist/engineGenerationConvergence.d.ts +39 -0
  42. package/dist/engineGenerationConvergence.js +95 -0
  43. package/dist/engineGenerationPort.d.ts +61 -0
  44. package/dist/engineGenerationPort.js +144 -0
  45. package/dist/engineHealthFacts.d.ts +23 -0
  46. package/dist/engineHealthFacts.js +92 -0
  47. package/dist/engineIdentity.d.ts +4 -0
  48. package/dist/engineIdentity.js +11 -0
  49. package/dist/engineNoticeCodes.d.ts +2 -5
  50. package/dist/engineRowRef.js +3 -0
  51. package/dist/engineSessionMessages.js +2 -2
  52. package/dist/engineToolDirectory.js +2 -2
  53. package/dist/engineWireFor.d.ts +99 -0
  54. package/dist/engineWireFor.js +248 -6
  55. package/dist/engineWireTarget.d.ts +1 -0
  56. package/dist/engineWireTarget.js +8 -0
  57. package/dist/env/uiLanguage.js +1 -1
  58. package/dist/errorSupplementRoles.d.ts +3 -0
  59. package/dist/errorSupplementRoles.js +37 -0
  60. package/dist/executionLaneCapability.js +2 -2
  61. package/dist/fileHistoryCaptureCapability.js +3 -3
  62. package/dist/finalVerifyWire.d.ts +6 -3
  63. package/dist/finalVerifyWire.js +6 -23
  64. package/dist/flagInput.d.ts +4 -0
  65. package/dist/flagInput.js +24 -0
  66. package/dist/fleet/fleetLedger.js +5 -2
  67. package/dist/fleet/fleetProjection.d.ts +1 -0
  68. package/dist/fleet/fleetProjection.js +15 -2
  69. package/dist/gateVocabulary.js +3 -0
  70. package/dist/generated/engineFactTables.d.ts +7 -3
  71. package/dist/generated/engineFactTables.js +52 -0
  72. package/dist/generated/engineNoticeTables.js +12 -0
  73. package/dist/generated/settingsSchemaActiveTiers.d.ts +1 -0
  74. package/dist/generated/settingsSchemaActiveTiers.js +14 -0
  75. package/dist/generated/settingsSchemaCallerTextEcho.d.ts +1 -0
  76. package/dist/generated/settingsSchemaCallerTextEcho.js +8 -0
  77. package/dist/generated/settingsSchemaControlAndBidi.d.ts +1 -0
  78. package/dist/generated/settingsSchemaControlAndBidi.js +8 -0
  79. package/dist/generated/settingsSchemaDefaultModel.d.ts +11 -0
  80. package/dist/generated/settingsSchemaDefaultModel.js +25 -0
  81. package/dist/generated/settingsSchemaFns.d.ts +54 -0
  82. package/dist/generated/settingsSchemaFns.js +26 -1
  83. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
  84. package/dist/generated/settingsSchemaMcpRequestEntry.js +1 -7
  85. package/dist/generated/settingsSchemaSafetyMergeSpec.d.ts +1 -0
  86. package/dist/generated/settingsSchemaSafetyMergeSpec.js +95 -0
  87. package/dist/generated/settingsSchemaSettingsSources.d.ts +1 -0
  88. package/dist/generated/settingsSchemaSettingsSources.js +58 -0
  89. package/dist/generated/settingsSchemaTables.d.ts +2 -0
  90. package/dist/generated/settingsSchemaTables.js +13 -0
  91. package/dist/generated/settingsSchemaUrlPattern.d.ts +1 -0
  92. package/dist/generated/settingsSchemaUrlPattern.js +183 -0
  93. package/dist/headlessPermissionModeWire.d.ts +18 -2
  94. package/dist/headlessPermissionModeWire.js +30 -19
  95. package/dist/hitl/allowRuleShadow.js +7 -5
  96. package/dist/hitl/approvalCardReading.d.ts +3 -0
  97. package/dist/hitl/approvalCardReading.js +17 -0
  98. package/dist/hitl/approvalCompleteParked.js +1 -1
  99. package/dist/hitl/approvalDelivery.d.ts +87 -0
  100. package/dist/hitl/approvalDelivery.js +193 -0
  101. package/dist/hitl/approvalResolution.d.ts +11 -0
  102. package/dist/hitl/approvalResolution.js +50 -11
  103. package/dist/hitl/askClassPair.d.ts +6 -0
  104. package/dist/hitl/askClassPair.js +30 -3
  105. package/dist/hitl/askParkAutoReopenBlock.d.ts +30 -0
  106. package/dist/hitl/askParkAutoReopenBlock.js +117 -0
  107. package/dist/hitl/askParkRowRouting.js +4 -1
  108. package/dist/hitl/attributionLadder.d.ts +42 -3
  109. package/dist/hitl/attributionLadder.js +79 -8
  110. package/dist/hitl/automaticAnswerVerdict.d.ts +6 -1
  111. package/dist/hitl/automaticAnswerVerdict.js +46 -11
  112. package/dist/hitl/crashConverged.js +2 -2
  113. package/dist/hitl/decisionConflict.d.ts +6 -2
  114. package/dist/hitl/decisionConflict.js +24 -9
  115. package/dist/hitl/decisionRefusal.d.ts +20 -10
  116. package/dist/hitl/decisionRefusal.js +99 -54
  117. package/dist/hitl/decisionSend.d.ts +3 -0
  118. package/dist/hitl/decisionSend.js +87 -103
  119. package/dist/hitl/frameRouter.d.ts +1 -0
  120. package/dist/hitl/frameRouter.js +9 -2
  121. package/dist/hitl/hitlBridge.d.ts +18 -6
  122. package/dist/hitl/hitlBridge.js +41 -37
  123. package/dist/hitl/livePendingAsk.js +4 -3
  124. package/dist/hitl/noAllowCause.js +1 -1
  125. package/dist/hitl/parkResolver.js +3 -2
  126. package/dist/hitl/persistedRulesWire.js +1 -0
  127. package/dist/hitl/planReviewWire.d.ts +4 -0
  128. package/dist/hitl/planReviewWire.js +59 -30
  129. package/dist/hitl/resumeRunningCard.d.ts +3 -2
  130. package/dist/hitl/resumeRunningCard.js +17 -11
  131. package/dist/hitl/sessionPolicyDeliverable.d.ts +5 -2
  132. package/dist/hitl/sessionPolicyDeliverable.js +62 -29
  133. package/dist/hitl/sessionPolicyWire.d.ts +13 -3
  134. package/dist/hitl/sessionPolicyWire.js +81 -16
  135. package/dist/hitl/standingRows.js +1 -1
  136. package/dist/hitl/toolApprovalWire.d.ts +9 -10
  137. package/dist/hitl/toolApprovalWire.js +72 -54
  138. package/dist/hookMatcherVerdict.d.ts +2 -0
  139. package/dist/hookMatcherVerdict.js +12 -0
  140. package/dist/hooksCompactTransition.d.ts +19 -0
  141. package/dist/hooksCompactTransition.js +41 -0
  142. package/dist/hooksWireCaps.d.ts +1 -1
  143. package/dist/hooksWireCaps.js +202 -203
  144. package/dist/host.d.ts +1 -14
  145. package/dist/host.js +0 -8
  146. package/dist/hostCallbackGuard.d.ts +1 -0
  147. package/dist/hostCallbackGuard.js +1 -1
  148. package/dist/hostSettingsSource.d.ts +172 -0
  149. package/dist/hostSettingsSource.js +675 -0
  150. package/dist/hostTurnSettings.d.ts +73 -17
  151. package/dist/hostTurnSettings.js +594 -97
  152. package/dist/httpHookPolicy.d.ts +37 -0
  153. package/dist/httpHookPolicy.js +176 -0
  154. package/dist/humanTurn.d.ts +2 -1
  155. package/dist/humanTurn.js +37 -7
  156. package/dist/humanTurnRead.js +4 -3
  157. package/dist/humanTurnSentences.d.ts +10 -0
  158. package/dist/humanTurnSentences.js +74 -0
  159. package/dist/i18n/messages.en.d.ts +184 -2
  160. package/dist/i18n/messages.en.js +187 -5
  161. package/dist/i18n/messages.zh.js +197 -5
  162. package/dist/i18n/translate.js +3 -3
  163. package/dist/index.d.ts +69 -15
  164. package/dist/index.js +45 -13
  165. package/dist/inheritEnvCapability.d.ts +3 -1
  166. package/dist/inheritEnvCapability.js +31 -17
  167. package/dist/inheritEnvWire.d.ts +2 -1
  168. package/dist/inheritEnvWire.js +11 -5
  169. package/dist/interactiveToolsWire.d.ts +4 -2
  170. package/dist/interactiveToolsWire.js +5 -5
  171. package/dist/jsonFaithful.d.ts +20 -0
  172. package/dist/jsonFaithful.js +152 -0
  173. package/dist/limitsWire.d.ts +7 -2
  174. package/dist/limitsWire.js +19 -13
  175. package/dist/liveInitToolFace.d.ts +6 -1
  176. package/dist/liveInitToolFace.js +5 -3
  177. package/dist/liveModelCatalog.d.ts +22 -0
  178. package/dist/liveModelCatalog.js +132 -18
  179. package/dist/mcpPanel.js +1 -1
  180. package/dist/mcpProbeCapability.js +2 -2
  181. package/dist/mcpStatusSupersetKeys.d.ts +24 -0
  182. package/dist/mcpStatusSupersetKeys.js +45 -0
  183. package/dist/mcpToolToggles.js +2 -1
  184. package/dist/mcpWireCaps.d.ts +39 -1
  185. package/dist/mcpWireCaps.js +254 -50
  186. package/dist/memoryComplianceCapability.js +2 -2
  187. package/dist/memoryOriginCapability.js +2 -2
  188. package/dist/model/catalogDefault.d.ts +24 -0
  189. package/dist/model/catalogDefault.js +4 -0
  190. package/dist/model/liveCatalogShape.js +5 -4
  191. package/dist/model/modelsPolicy.js +4 -3
  192. package/dist/model/onboardJudgement.d.ts +1 -0
  193. package/dist/model/onboardJudgement.js +1 -1
  194. package/dist/model/subagentModelWord.js +2 -2
  195. package/dist/modelCapabilityProbe.js +6 -6
  196. package/dist/modelIdentityResolvability.d.ts +10 -1
  197. package/dist/modelIdentityResolvability.js +62 -39
  198. package/dist/modsKernelIdentity.d.ts +10 -0
  199. package/dist/modsKernelIdentity.js +103 -0
  200. package/dist/modsKernelTransit.d.ts +8 -0
  201. package/dist/modsKernelTransit.js +6 -0
  202. package/dist/notifications.d.ts +30 -12
  203. package/dist/notifications.js +241 -53
  204. package/dist/outputStyleSeatCapability.js +2 -2
  205. package/dist/ownKey.d.ts +11 -0
  206. package/dist/ownKey.js +164 -3
  207. package/dist/panelReduce.js +1 -1
  208. package/dist/peerFrames.d.ts +1 -1
  209. package/dist/peerFrames.js +6 -2
  210. package/dist/peerLaneCapability.js +2 -2
  211. package/dist/permissionModesCapability.js +4 -4
  212. package/dist/permissionRuleIssue.js +2 -0
  213. package/dist/permissionRulesWriteCapability.js +2 -2
  214. package/dist/permissionsAllowGrantCapability.js +2 -2
  215. package/dist/permissionsDeclaration.d.ts +43 -4
  216. package/dist/permissionsDeclaration.js +102 -35
  217. package/dist/pluginHooksWire.d.ts +20 -4
  218. package/dist/pluginHooksWire.js +92 -53
  219. package/dist/prepareRefusal.d.ts +3 -2
  220. package/dist/prepareRefusal.js +27 -9
  221. package/dist/printInitToolFace.js +2 -2
  222. package/dist/printModelStatus.js +1 -1
  223. package/dist/projectMemory.d.ts +32 -0
  224. package/dist/projectMemory.js +70 -0
  225. package/dist/promptBlockedCopy.d.ts +2 -1
  226. package/dist/promptBlockedCopy.js +2 -1
  227. package/dist/promptDelivery.d.ts +23 -3
  228. package/dist/promptDelivery.js +169 -30
  229. package/dist/providerRejection.d.ts +19 -1
  230. package/dist/providerRejection.js +75 -4
  231. package/dist/queuedDelivery.d.ts +48 -0
  232. package/dist/queuedDelivery.js +233 -0
  233. package/dist/reattachWindow.d.ts +94 -0
  234. package/dist/reattachWindow.js +127 -0
  235. package/dist/request/printNotification.d.ts +1 -1
  236. package/dist/request/printNotification.js +5 -1
  237. package/dist/request/submissionIdentity.d.ts +37 -0
  238. package/dist/request/submissionIdentity.js +65 -0
  239. package/dist/request/taskRequest.d.ts +12 -4
  240. package/dist/request/taskRequest.js +221 -152
  241. package/dist/resultFrameKeys.d.ts +1 -0
  242. package/dist/resultFrameKeys.js +4 -1
  243. package/dist/retryStatus.d.ts +8 -0
  244. package/dist/retryStatus.js +57 -9
  245. package/dist/rewindArchiveCapability.js +2 -2
  246. package/dist/rewindEngineAction.d.ts +2 -0
  247. package/dist/rewindEngineAction.js +23 -1
  248. package/dist/rowKind.d.ts +36 -0
  249. package/dist/rowKind.js +97 -0
  250. package/dist/ruleCompileVerdict.d.ts +18 -0
  251. package/dist/ruleCompileVerdict.js +67 -2
  252. package/dist/ruleReadings.d.ts +58 -0
  253. package/dist/ruleReadings.js +132 -0
  254. package/dist/ruleRefusalSentence.d.ts +4 -0
  255. package/dist/ruleRefusalSentence.js +9 -3
  256. package/dist/runCancelContext.d.ts +0 -1
  257. package/dist/runCancelContext.js +1 -2
  258. package/dist/runTerminal.d.ts +5 -0
  259. package/dist/runTerminal.js +52 -17
  260. package/dist/sandboxWire.d.ts +1 -1
  261. package/dist/sandboxWire.js +4 -6
  262. package/dist/scenarioRefusal.js +1 -1
  263. package/dist/scenarioSkills.d.ts +20 -0
  264. package/dist/scenarioSkills.js +72 -0
  265. package/dist/scenarioWire.d.ts +5 -2
  266. package/dist/scenarioWire.js +9 -9
  267. package/dist/sealedKeyCapability.js +2 -2
  268. package/dist/seam.d.ts +2 -0
  269. package/dist/seam.js +2 -2
  270. package/dist/seatContract.d.ts +46 -1
  271. package/dist/seatContract.js +49 -19
  272. package/dist/selfOrchestrationDenial.js +1 -1
  273. package/dist/sessionPolicyCapability.js +2 -2
  274. package/dist/sessionRulesChildrenReadLive.d.ts +6 -0
  275. package/dist/sessionRulesChildrenReadLive.js +5 -0
  276. package/dist/sessionRulesNamespaceFormsCapability.d.ts +12 -0
  277. package/dist/sessionRulesNamespaceFormsCapability.js +29 -0
  278. package/dist/sessionSyncFileHistoryCapability.js +2 -2
  279. package/dist/settingsCredentialKeyPaths.js +60 -5
  280. package/dist/settingsHooksSalvage.d.ts +1 -0
  281. package/dist/settingsHooksSalvage.js +7 -1
  282. package/dist/settingsLayerAdmission.d.ts +4 -0
  283. package/dist/settingsLayerAdmission.js +16 -0
  284. package/dist/skillToolListsCapability.js +6 -5
  285. package/dist/skillsWireCaps.d.ts +14 -0
  286. package/dist/skillsWireCaps.js +47 -16
  287. package/dist/slashCommandGate.d.ts +24 -0
  288. package/dist/slashCommandGate.js +74 -0
  289. package/dist/slashCommandTable.d.ts +14 -0
  290. package/dist/slashCommandTable.js +99 -0
  291. package/dist/sqlEngineCapability.js +2 -2
  292. package/dist/steerPriorityCapability.js +2 -2
  293. package/dist/storePostureCapability.js +2 -2
  294. package/dist/subagent/agentStateDetail.js +1 -1
  295. package/dist/subagent/engineDelegatedPrompt.d.ts +9 -0
  296. package/dist/subagent/engineDelegatedPrompt.js +38 -7
  297. package/dist/subagent/engineRowStopGate.js +2 -2
  298. package/dist/subagent/engineSubagentResume.js +3 -3
  299. package/dist/subagent/engineTaskHandleWire.d.ts +1 -0
  300. package/dist/subagent/engineTaskHandleWire.js +10 -0
  301. package/dist/submitFailure.d.ts +8 -0
  302. package/dist/submitFailure.js +17 -0
  303. package/dist/supportFloor.d.ts +1 -0
  304. package/dist/supportFloor.js +7 -0
  305. package/dist/terminationIntent.d.ts +55 -0
  306. package/dist/terminationIntent.js +352 -0
  307. package/dist/toolHistoryMismatch.d.ts +8 -0
  308. package/dist/toolHistoryMismatch.js +37 -6
  309. package/dist/toolResult.d.ts +13 -3
  310. package/dist/toolResult.js +158 -9
  311. package/dist/toolResultContent.d.ts +13 -0
  312. package/dist/toolResultContent.js +82 -7
  313. package/dist/toolRoster.d.ts +18 -0
  314. package/dist/toolRoster.js +64 -0
  315. package/dist/turnFailurePresentation.js +27 -90
  316. package/dist/usageLimitAutoResume.d.ts +74 -0
  317. package/dist/usageLimitAutoResume.js +227 -0
  318. package/dist/userAttachmentEnvelope.js +1 -1
  319. package/dist/userAttachmentSeat.js +5 -5
  320. package/dist/userInvokedSkillsCapability.js +2 -2
  321. package/dist/webSearchBackendCapability.js +2 -2
  322. package/dist/wireErrorTriage.js +99 -50
  323. package/dist/wireFailureShape.d.ts +25 -1
  324. package/dist/wireFailureShape.js +92 -5
  325. package/dist/wireRefusalCopy.d.ts +24 -1
  326. package/dist/wireRefusalCopy.js +253 -32
  327. package/dist/wiringFleetDoctor.d.ts +3 -0
  328. package/dist/wiringFleetDoctor.js +21 -0
  329. package/dist/workflow.d.ts +2 -1
  330. package/dist/workflow.js +38 -1
  331. package/dist/workflowClient.d.ts +2 -7
  332. package/dist/workflowsJournalCapability.js +2 -2
  333. package/dist/writeProtectionCapability.js +2 -2
  334. package/docs/INTEGRATION-CLIENTS.md +607 -181
  335. package/package.json +14 -3
@@ -1,4 +1,5 @@
1
1
  import type { AgentClient } from '@sema-agent/sdk';
2
+ import type { UiLanguage } from '../env/uiLanguage.js';
2
3
  import type { EngineWireInjection } from '../engineWireSdk.js';
3
4
  export type DelegatedPromptWireClient = {
4
5
  sessions: Pick<AgentClient['sessions'], 'get'>;
@@ -11,9 +12,17 @@ export declare function delegatedPromptText(content: unknown): string | undefine
11
12
  export declare function pickDelegatedPrompt(messages: readonly unknown[]): string | undefined;
12
13
  type TranscriptWindowReader = (transcriptId: string) => Promise<readonly unknown[] | null>;
13
14
  export declare function __setTranscriptWindowReaderForTests(r: TranscriptWindowReader | null): void;
15
+ export declare const DELEGATED_PROMPT_ABSENCE_CAUSES: readonly ["not_owned_after_restart", "not_in_store", "forbidden", "prompt_absent", "unknown"];
16
+ export type DelegatedPromptAbsenceCause = (typeof DELEGATED_PROMPT_ABSENCE_CAUSES)[number];
17
+ export interface DelegatedPromptAbsence {
18
+ readonly cause: DelegatedPromptAbsenceCause;
19
+ readonly text: string;
20
+ }
21
+ export declare function delegatedPromptAbsenceSentence(cause: DelegatedPromptAbsenceCause | string, lang?: UiLanguage): string;
14
22
  export interface DelegatedPromptFetch {
15
23
  prompt?: string;
16
24
  outcome: 'hit' | 'skipped' | 'unreadable' | 'absent';
25
+ absence?: DelegatedPromptAbsence;
17
26
  }
18
27
  export declare function fetchDelegatedPrompt(taskId: string, opts?: {
19
28
  wire?: DelegatedPromptWire;
@@ -1,6 +1,8 @@
1
1
  import { stripSystemReminderBlocks } from '../systemReminderTag.js';
2
2
  import { hostLog } from '../host.js';
3
3
  import { isSessionIdPathSegment } from '../sessionIdSegment.js';
4
+ import { msg, renderMessage } from '../i18n/translate.js';
5
+ import { readThrownSlot } from '../wireFailureShape.js';
4
6
  import { clientHasVerbs, engineWireFor, INJECTED_WIRE_SETTLE_MS, settleInjected } from '../engineWireFor.js';
5
7
  import { resolveOwnerContext } from './engineSubagentResume.js';
6
8
  import { panelAnchorOf } from '../panelReduce.js';
@@ -22,7 +24,7 @@ export function __resetEngineDelegatedPromptForTests() {
22
24
  clearEnginePanelAnchors();
23
25
  promptHydrateInFlight.clear();
24
26
  }
25
- const promptHydrateInFlight = new Set();
27
+ const promptHydrateInFlight = new Map();
26
28
  function roleOf(entry) {
27
29
  if (typeof entry !== 'object' || entry === null)
28
30
  return undefined;
@@ -113,13 +115,38 @@ async function readTranscriptWindow(transcriptId, sessionKey, injectedWire) {
113
115
  const msgs = rec.messages;
114
116
  return Array.isArray(msgs) ? msgs : null;
115
117
  }
118
+ export const DELEGATED_PROMPT_ABSENCE_CAUSES = Object.freeze(['not_owned_after_restart', 'not_in_store', 'forbidden', 'prompt_absent', 'unknown']);
119
+ const ABSENCE_KEY = {
120
+ not_owned_after_restart: 'session.subagent.delegatedPrompt.absence.notOwnedAfterRestart',
121
+ not_in_store: 'session.subagent.delegatedPrompt.absence.notInStore',
122
+ forbidden: 'session.subagent.delegatedPrompt.absence.forbidden',
123
+ prompt_absent: 'session.subagent.delegatedPrompt.absence.promptAbsent',
124
+ unknown: 'session.subagent.delegatedPrompt.absence.unknown',
125
+ };
126
+ export function delegatedPromptAbsenceSentence(cause, lang) {
127
+ const known = typeof cause === 'string' && Object.hasOwn(ABSENCE_KEY, cause);
128
+ return renderMessage(msg(known ? ABSENCE_KEY[cause] : ABSENCE_KEY.unknown), lang);
129
+ }
130
+ function absenceOf(cause) {
131
+ return Object.freeze({ cause, text: delegatedPromptAbsenceSentence(cause) });
132
+ }
133
+ function absenceOfThrown(e) {
134
+ const status = readThrownSlot(e, 'status');
135
+ if (status === 404)
136
+ return absenceOf('not_in_store');
137
+ if (status === 401 || status === 403)
138
+ return absenceOf('forbidden');
139
+ return absenceOf('unknown');
140
+ }
116
141
  export async function fetchDelegatedPrompt(taskId, opts) {
117
- if (promptHydrateInFlight.has(taskId))
118
- return { outcome: 'skipped' };
142
+ if (promptHydrateInFlight.has(taskId)) {
143
+ const settled = promptHydrateInFlight.get(taskId);
144
+ return settled ? { outcome: 'skipped', absence: settled } : { outcome: 'skipped' };
145
+ }
119
146
  const transcriptId = getEngineTranscriptId(taskId);
120
147
  if (!isSessionIdPathSegment(transcriptId))
121
- return { outcome: 'skipped' };
122
- promptHydrateInFlight.add(taskId);
148
+ return { outcome: 'skipped', absence: absenceOf(transcriptId === undefined ? 'not_owned_after_restart' : 'unknown') };
149
+ promptHydrateInFlight.set(taskId, null);
123
150
  let msgs = null;
124
151
  try {
125
152
  msgs = await readTranscriptWindow(transcriptId, resolveOwnerContext(taskId).key, opts?.wire);
@@ -127,14 +154,18 @@ export async function fetchDelegatedPrompt(taskId, opts) {
127
154
  catch (e) {
128
155
  promptHydrateInFlight.delete(taskId);
129
156
  hostLog('debug', `[delegated-prompt] ${taskId} transcript ${transcriptId} read failed: ${String(e).slice(0, 160)}`);
130
- return { outcome: 'unreadable' };
157
+ return { outcome: 'unreadable', absence: absenceOfThrown(e) };
131
158
  }
132
159
  const prompt = msgs ? pickDelegatedPrompt(msgs) : undefined;
133
160
  if (!prompt) {
134
161
  if (msgs === null)
135
162
  promptHydrateInFlight.delete(taskId);
136
163
  hostLog('debug', `[delegated-prompt] ${taskId} transcript ${transcriptId}: ${msgs === null ? 'transcript unreadable (retryable)' : 'no delegated user message (final)'}`);
137
- return { outcome: msgs === null ? 'unreadable' : 'absent' };
164
+ if (msgs === null)
165
+ return { outcome: 'unreadable', absence: absenceOf('unknown') };
166
+ const settled = absenceOf('prompt_absent');
167
+ promptHydrateInFlight.set(taskId, settled);
168
+ return { outcome: 'absent', absence: settled };
138
169
  }
139
170
  hostLog('debug', `[delegated-prompt] ${taskId} <- transcript ${transcriptId} (${prompt.length} chars) head=${JSON.stringify(prompt.slice(0, 60))}`);
140
171
  return { prompt, outcome: 'hit' };
@@ -1,5 +1,5 @@
1
1
  import { engineCapTrue } from '../engineCapsCache.js';
2
- import { engineWireTargetFor } from '../engineWireTarget.js';
2
+ import { engineWireTargetBaseUrl } from '../engineWireTarget.js';
3
3
  import { DEFAULT_SESSION_KEY } from '../sessionSlot.js';
4
4
  export const engineOwnedRowIds = new Set();
5
5
  export const fleetViewStubRowIds = new Set();
@@ -7,7 +7,7 @@ export function isEngineViewRow(taskId) {
7
7
  return engineOwnedRowIds.has(taskId) || fleetViewStubRowIds.has(taskId);
8
8
  }
9
9
  export function engineTaskHandlesCapable(sessionKey = DEFAULT_SESSION_KEY, capsBaseUrl) {
10
- return engineCapTrue(capsBaseUrl ?? engineWireTargetFor(sessionKey)?.baseUrl, 'taskHandles');
10
+ return engineCapTrue(capsBaseUrl ?? engineWireTargetBaseUrl(sessionKey), 'taskHandles');
11
11
  }
12
12
  export function engineRowNeedsStopConfirm(taskId, sessionKey, capsBaseUrl) {
13
13
  return isEngineViewRow(taskId) && engineTaskHandlesCapable(sessionKey ?? DEFAULT_SESSION_KEY, capsBaseUrl);
@@ -5,13 +5,13 @@ import { RESUME_SESSION_NOT_FOUND } from '../engineErrorCodes.js';
5
5
  import { displayUntrusted } from '../displayUntrusted.js';
6
6
  import { engineCapTrue } from '../engineCapsCache.js';
7
7
  import { clientHasVerbs, engineWireFor, INJECTED_WIRE_SETTLE_MS, noAnswerDetailFrom, sendOnce, settleInjected } from '../engineWireFor.js';
8
- import { engineWireTargetFor } from '../engineWireTarget.js';
8
+ import { engineWireTargetBaseUrl } from '../engineWireTarget.js';
9
9
  import { activeEngineRunId, engineSessionParamFor } from '../engineSessionParam.js';
10
10
  import { DEFAULT_SESSION_KEY } from '../sessionSlot.js';
11
11
  import { getBgParentRunOwner, parentToolCallIdOf, } from '../subagentContentStore.js';
12
12
  export const SUBAGENT_RESUME_CAP = 'subagentResume';
13
13
  export function subagentResumeAvailable(baseUrl, sessionKey = DEFAULT_SESSION_KEY) {
14
- return engineCapTrue(baseUrl ?? engineWireTargetFor(sessionKey)?.baseUrl, SUBAGENT_RESUME_CAP);
14
+ return engineCapTrue(baseUrl ?? engineWireTargetBaseUrl(sessionKey), SUBAGENT_RESUME_CAP);
15
15
  }
16
16
  export function resolveSubagentContinueTarget(rowId, displayName) {
17
17
  const precise = parentToolCallIdOf(rowId);
@@ -149,7 +149,7 @@ export async function resumeSettledSubagent(facade, runId, target, content, opts
149
149
  }
150
150
  const warnedRetainWithoutWake = new Set();
151
151
  export function auditRetainWithoutWake(input) {
152
- const baseUrl = input.baseUrl ?? engineWireTargetFor(input.sessionKey ?? DEFAULT_SESSION_KEY)?.baseUrl;
152
+ const baseUrl = input.baseUrl ?? engineWireTargetBaseUrl(input.sessionKey ?? DEFAULT_SESSION_KEY);
153
153
  if (!engineCapTrue(baseUrl, SUBAGENT_RESUME_CAP))
154
154
  return undefined;
155
155
  if (input.retainRequested === false)
@@ -13,6 +13,7 @@ export interface EngineTaskOutputResult {
13
13
  status?: string;
14
14
  stoppedBy?: string;
15
15
  partialResult?: boolean;
16
+ exitCode?: number;
16
17
  }
17
18
  export declare function __resetTaskHandleWireForTests(): void;
18
19
  export declare function fetchEngineTaskOutput(handle: string, opts?: {
@@ -6,6 +6,7 @@ import { engineSessionParamFor } from '../engineSessionParam.js';
6
6
  import { resolveOwnerContext } from './engineSubagentResume.js';
7
7
  import { engineTaskHandlesCapable } from './engineRowStopGate.js';
8
8
  import { noteBgOwnerAbsence } from './subagentOwnerAbsence.js';
9
+ import { guardedRead, readOwnDataValue } from '../ownKey.js';
9
10
  function usableTaskOutputClient(client) {
10
11
  return clientHasVerbs(client, [['runs', 'taskOutput']]);
11
12
  }
@@ -27,6 +28,13 @@ function sessionOf(ctx) {
27
28
  const s = ctx.record?.sessionId ?? engineSessionParamFor(ctx.key);
28
29
  return s !== undefined ? { session: s } : {};
29
30
  }
31
+ function exitCodeOfTaskOutput(output) {
32
+ const details = guardedRead(() => readOwnDataValue(output, 'details'));
33
+ if (typeof details !== 'object' || details === null)
34
+ return undefined;
35
+ const code = guardedRead(() => readOwnDataValue(details, 'exitCode'));
36
+ return typeof code === 'number' && Number.isInteger(code) ? code : undefined;
37
+ }
30
38
  const accumulated = new Map();
31
39
  export function __resetTaskHandleWireForTests() {
32
40
  accumulated.clear();
@@ -67,11 +75,13 @@ export async function fetchEngineTaskOutput(handle, opts) {
67
75
  if (engineWireDebugEnabled()) {
68
76
  hostLog('debug', `[task-handle] output ${handle} via run ${runId}: ok fresh=${fresh.length}b merged=${merged.length}b status=${typeof out.status === 'string' ? out.status : '-'}`);
69
77
  }
78
+ const exitCode = exitCodeOfTaskOutput(out);
70
79
  return {
71
80
  content: merged,
72
81
  ...(typeof out.status === 'string' ? { status: out.status } : {}),
73
82
  ...(typeof out.stoppedBy === 'string' ? { stoppedBy: out.stoppedBy } : {}),
74
83
  ...(out.partial_result === true ? { partialResult: true } : {}),
84
+ ...(exitCode !== undefined ? { exitCode } : {}),
75
85
  };
76
86
  }
77
87
  catch (e) {
@@ -0,0 +1,8 @@
1
+ import type { SDKAssistantMessageError } from '@sema-agent/agent-types';
2
+ import type { SemaRowKind } from './rowKind.js';
3
+ export interface SubmitFailureClass {
4
+ readonly kind: Extract<SemaRowKind, 'api_error' | 'model_output_error'>;
5
+ readonly errorCode?: string;
6
+ readonly ccError?: SDKAssistantMessageError;
7
+ }
8
+ export declare function classifySubmitFailure(err: {} | null | undefined): SubmitFailureClass;
@@ -0,0 +1,17 @@
1
+ import { isModelOutputErrorText } from './adapter/runStream.js';
2
+ import { ccErrorOfProviderStatus } from './providerRejection.js';
3
+ import { classifyTurnWireError } from './wireErrorTriage.js';
4
+ export function classifySubmitFailure(err) {
5
+ const verdict = classifyTurnWireError(err);
6
+ const status = verdict.kind === 'http' ? verdict.status : undefined;
7
+ const errorCode = verdict.kind === 'http' && verdict.errorCode !== undefined && verdict.errorCode.length > 0 ? verdict.errorCode : undefined;
8
+ const text = verdict.kind === 'http' ? verdict.message : verdict.kind === 'transport' || verdict.kind === 'internal' ? verdict.detail : '';
9
+ const kind = isModelOutputErrorText(text) ? 'model_output_error' : 'api_error';
10
+ const mapped = status === undefined ? undefined : ccErrorOfProviderStatus(status);
11
+ const ccError = mapped === 'model_not_found' && errorCode !== undefined ? undefined : mapped;
12
+ return {
13
+ kind,
14
+ ...(errorCode !== undefined ? { errorCode } : {}),
15
+ ...(ccError !== undefined ? { ccError } : {}),
16
+ };
17
+ }
@@ -10,3 +10,4 @@ export type EngineVersionTier = 'engine' | 'legacy' | 'unknown';
10
10
  export declare function engineVersionTier(version: unknown, floor?: string): EngineVersionTier;
11
11
  export declare function engineSupportFloorEffective(floor?: string): string;
12
12
  export declare function coreVersionTier(version: unknown, floor?: string): EngineVersionTier;
13
+ export declare function compareReleaseVersions(a: string, b: string): -1 | 0 | 1 | undefined;
@@ -51,3 +51,10 @@ export function engineSupportFloorEffective(floor) {
51
51
  export function coreVersionTier(version, floor) {
52
52
  return judgeAgainst(version, SUPPORT_FLOOR.core, floor, 'coreVersionTier').tier;
53
53
  }
54
+ export function compareReleaseVersions(a, b) {
55
+ const ta = releaseTriple(a);
56
+ const tb = releaseTriple(b);
57
+ if (ta === undefined || tb === undefined)
58
+ return undefined;
59
+ return compareTriple(ta, tb);
60
+ }
@@ -0,0 +1,55 @@
1
+ import type { UiLanguage } from './env/uiLanguage.js';
2
+ export declare const TERMINATION_INTENT_TTL_MS = 60000;
3
+ export declare const TERMINATION_INTENT_WEAK_SOURCE = "esc-abort";
4
+ export declare const INTERRUPTED_SETTLE_BUDGET_MS = 10000;
5
+ export declare const INTERRUPTED_SETTLE_POLL_MS = 1000;
6
+ export type TerminationIntentSource = string;
7
+ export interface TerminationIntentSnapshot {
8
+ readonly source: TerminationIntentSource;
9
+ readonly at: number;
10
+ readonly abortAt: number | null;
11
+ }
12
+ export interface TerminationIntentLedgerOptions {
13
+ readonly now: () => number;
14
+ readonly ttlMs?: number;
15
+ readonly exemptAbortReasons?: readonly string[];
16
+ }
17
+ export interface TerminationIntentLedger {
18
+ record(taskId: string | null | undefined, source: TerminationIntentSource): number;
19
+ snapshot(taskId: string | null | undefined): TerminationIntentSnapshot | null;
20
+ restoreIf(taskId: string | null | undefined, version: number, snapshot: TerminationIntentSnapshot | null): boolean;
21
+ rollbackIf(taskId: string | null | undefined, version: number, prior: TerminationIntentSource | null): boolean;
22
+ rollback(taskId: string | null | undefined, prior: TerminationIntentSource | null): void;
23
+ wasRecentlyTerminatedByUs(taskId: string | null | undefined): boolean;
24
+ sourceOf(taskId: string | null | undefined): TerminationIntentSource | null;
25
+ armOnAbort(signal: AbortSignal | undefined, taskId: string): void;
26
+ forget(taskId: string | null | undefined): void;
27
+ size(): number;
28
+ }
29
+ export declare function createTerminationIntentLedger(options: TerminationIntentLedgerOptions): TerminationIntentLedger;
30
+ export type InterruptedRunSettleVerdict = {
31
+ readonly kind: 'settled';
32
+ readonly status: string;
33
+ } | {
34
+ readonly kind: 'still-running';
35
+ readonly waitedMs: number;
36
+ } | {
37
+ readonly kind: 'parked';
38
+ readonly status: string;
39
+ } | {
40
+ readonly kind: 'unknown';
41
+ };
42
+ export interface InterruptedRunRow {
43
+ readonly status?: string | null;
44
+ }
45
+ export interface InterruptedRunSettleDeps {
46
+ readonly getRun?: (taskId: string, opts?: {
47
+ signal?: AbortSignal;
48
+ }) => Promise<InterruptedRunRow | null>;
49
+ readonly signal?: AbortSignal;
50
+ readonly budgetMs?: number;
51
+ readonly intervalMs?: number;
52
+ readonly now?: () => number;
53
+ }
54
+ export declare function awaitInterruptedRunSettle(taskId: string, deps: InterruptedRunSettleDeps): Promise<InterruptedRunSettleVerdict>;
55
+ export declare function interruptedRunSettleRow(taskId: string, verdict: InterruptedRunSettleVerdict, lang?: UiLanguage): string | null;
@@ -0,0 +1,352 @@
1
+ import { usableClockMs } from './clockReading.js';
2
+ import { displayUntrusted } from './displayUntrusted.js';
3
+ import { linkedAbortSignal, readSignalAborted, readSignalReason, tryListenAbortOnce, tryUnlistenAbort } from './engineWireFor.js';
4
+ import { msg, renderMessage } from './i18n/translate.js';
5
+ import { abortableSleep } from './abortableSleep.js';
6
+ import { isSdkRunParked, isSdkRunTerminal } from './terminalStatuses.js';
7
+ export const TERMINATION_INTENT_TTL_MS = 60_000;
8
+ export const TERMINATION_INTENT_WEAK_SOURCE = 'esc-abort';
9
+ export const INTERRUPTED_SETTLE_BUDGET_MS = 10_000;
10
+ export const INTERRUPTED_SETTLE_POLL_MS = 1_000;
11
+ const MAX_ROWS = 256;
12
+ const MAX_TRACKED_WRITES = 1024;
13
+ const validId = (taskId) => typeof taskId === 'string' && taskId.length > 0;
14
+ const validSource = (s) => typeof s === 'string' && s.length > 0;
15
+ function readSnapshot(s) {
16
+ try {
17
+ if (typeof s !== 'object' || s === null)
18
+ return null;
19
+ const raw = s;
20
+ const source = raw.source;
21
+ const at = raw.at;
22
+ const abortAt = raw.abortAt;
23
+ if (!validSource(source) || usableClockMs(at) === null)
24
+ return null;
25
+ return { source, at: at, abortAt: typeof abortAt === 'number' && usableClockMs(abortAt) !== null ? abortAt : null };
26
+ }
27
+ catch {
28
+ return null;
29
+ }
30
+ }
31
+ export function createTerminationIntentLedger(options) {
32
+ if (typeof options !== 'object' || options === null || typeof options.now !== 'function') {
33
+ throw new TypeError('createTerminationIntentLedger: options.now must be a function returning milliseconds');
34
+ }
35
+ const readClock = options.now;
36
+ const ttl = typeof options.ttlMs === 'number' && Number.isFinite(options.ttlMs) && options.ttlMs > 0 ? options.ttlMs : TERMINATION_INTENT_TTL_MS;
37
+ const exempt = Object.freeze([...(options.exemptAbortReasons ?? ['background'])]);
38
+ const rows = new Map();
39
+ let nextVersion = 1;
40
+ const priors = new Map();
41
+ const refused = new Set();
42
+ const trackBounded = (m, k, v) => {
43
+ m.set(k, v);
44
+ while (m.size > MAX_TRACKED_WRITES) {
45
+ const oldest = m.keys().next();
46
+ if (oldest.done === true)
47
+ break;
48
+ m.delete(oldest.value);
49
+ }
50
+ };
51
+ const markRefused = (version) => {
52
+ if (typeof version !== 'number')
53
+ return;
54
+ refused.add(version);
55
+ while (refused.size > MAX_TRACKED_WRITES) {
56
+ const oldest = refused.values().next();
57
+ if (oldest.done === true)
58
+ break;
59
+ refused.delete(oldest.value);
60
+ }
61
+ };
62
+ const effectivePrior = (version) => {
63
+ if (!priors.has(version))
64
+ return { known: false, row: null };
65
+ let row = priors.get(version) ?? null;
66
+ for (let hops = 0; row !== null && refused.has(row.version) && priors.has(row.version) && hops < MAX_TRACKED_WRITES; hops += 1)
67
+ row = priors.get(row.version) ?? null;
68
+ return { known: true, row };
69
+ };
70
+ const clock = () => {
71
+ try {
72
+ return usableClockMs(readClock());
73
+ }
74
+ catch {
75
+ return null;
76
+ }
77
+ };
78
+ const isFresh = (now, at) => {
79
+ const age = now - at;
80
+ return age >= 0 && age < ttl;
81
+ };
82
+ const purge = (now) => {
83
+ for (const [taskId, row] of rows) {
84
+ if (isFresh(now, row.at))
85
+ continue;
86
+ if (row.abortAt !== null && isFresh(now, row.abortAt)) {
87
+ rows.set(taskId, { at: row.abortAt, source: TERMINATION_INTENT_WEAK_SOURCE, abortAt: row.abortAt, version: nextVersion++ });
88
+ }
89
+ else {
90
+ rows.delete(taskId);
91
+ }
92
+ }
93
+ };
94
+ const put = (taskId, row) => {
95
+ rows.delete(taskId);
96
+ while (rows.size >= MAX_ROWS) {
97
+ const oldest = rows.keys().next();
98
+ if (oldest.done === true)
99
+ break;
100
+ rows.delete(oldest.value);
101
+ }
102
+ rows.set(taskId, row);
103
+ };
104
+ const record = (taskId, source) => {
105
+ if (!validId(taskId) || !validSource(source))
106
+ return 0;
107
+ const now = clock();
108
+ if (now === null)
109
+ return 0;
110
+ purge(now);
111
+ const prev = rows.get(taskId);
112
+ const abortAt = prev?.abortAt ?? (source === TERMINATION_INTENT_WEAK_SOURCE ? now : null);
113
+ const version = nextVersion++;
114
+ trackBounded(priors, version, prev ?? null);
115
+ put(taskId, { at: now, source, abortAt, version });
116
+ return version;
117
+ };
118
+ const rollback = (taskId, prior) => {
119
+ if (!validId(taskId))
120
+ return;
121
+ const now = clock();
122
+ if (now === null)
123
+ return;
124
+ purge(now);
125
+ if (prior !== null && validSource(prior) && prior !== TERMINATION_INTENT_WEAK_SOURCE) {
126
+ record(taskId, prior);
127
+ return;
128
+ }
129
+ const row = rows.get(taskId);
130
+ const abortAt = row?.abortAt ?? null;
131
+ if (abortAt !== null && isFresh(now, abortAt)) {
132
+ put(taskId, { at: abortAt, source: TERMINATION_INTENT_WEAK_SOURCE, abortAt, version: nextVersion++ });
133
+ return;
134
+ }
135
+ rows.delete(taskId);
136
+ };
137
+ const restoreTo = (taskId, row, target, now) => {
138
+ if (target === null) {
139
+ rollback(taskId, null);
140
+ return;
141
+ }
142
+ const abortAt = target.abortAt === null ? row.abortAt : row.abortAt === null ? target.abortAt : Math.max(target.abortAt, row.abortAt);
143
+ put(taskId, { at: target.at, source: target.source, abortAt, version: target.version ?? nextVersion++ });
144
+ purge(now);
145
+ };
146
+ return {
147
+ record,
148
+ snapshot(taskId) {
149
+ if (!validId(taskId))
150
+ return null;
151
+ const now = clock();
152
+ if (now === null)
153
+ return null;
154
+ purge(now);
155
+ const row = rows.get(taskId);
156
+ return row === undefined ? null : Object.freeze({ source: row.source, at: row.at, abortAt: row.abortAt });
157
+ },
158
+ restoreIf(taskId, version, snapshot) {
159
+ if (!validId(taskId))
160
+ return false;
161
+ const now = clock();
162
+ if (now === null)
163
+ return false;
164
+ purge(now);
165
+ markRefused(version);
166
+ const row = rows.get(taskId);
167
+ if (row === undefined || row.version !== version)
168
+ return false;
169
+ const eff = effectivePrior(version);
170
+ restoreTo(taskId, row, eff.known ? eff.row : readSnapshot(snapshot), now);
171
+ return true;
172
+ },
173
+ rollbackIf(taskId, version, prior) {
174
+ if (!validId(taskId))
175
+ return false;
176
+ const now = clock();
177
+ if (now === null)
178
+ return false;
179
+ purge(now);
180
+ markRefused(version);
181
+ const row = rows.get(taskId);
182
+ if (row === undefined || row.version !== version)
183
+ return false;
184
+ const eff = effectivePrior(version);
185
+ if (eff.known)
186
+ restoreTo(taskId, row, eff.row, now);
187
+ else
188
+ rollback(taskId, prior);
189
+ return true;
190
+ },
191
+ rollback,
192
+ wasRecentlyTerminatedByUs(taskId) {
193
+ if (!validId(taskId))
194
+ return false;
195
+ const now = clock();
196
+ if (now === null)
197
+ return false;
198
+ purge(now);
199
+ return rows.has(taskId);
200
+ },
201
+ sourceOf(taskId) {
202
+ if (!validId(taskId))
203
+ return null;
204
+ const now = clock();
205
+ if (now === null)
206
+ return null;
207
+ purge(now);
208
+ return rows.get(taskId)?.source ?? null;
209
+ },
210
+ armOnAbort(signal, taskId) {
211
+ if (signal === undefined || signal === null || !validId(taskId))
212
+ return;
213
+ const onAbort = () => {
214
+ const read = readSignalReason(signal);
215
+ if (read === null)
216
+ return;
217
+ if (typeof read.reason === 'string' && exempt.includes(read.reason))
218
+ return;
219
+ const now = clock();
220
+ if (now === null)
221
+ return;
222
+ purge(now);
223
+ const existing = rows.get(taskId);
224
+ if (existing !== undefined && existing.source !== TERMINATION_INTENT_WEAK_SOURCE) {
225
+ put(taskId, { ...existing, abortAt: now });
226
+ return;
227
+ }
228
+ put(taskId, { at: now, source: TERMINATION_INTENT_WEAK_SOURCE, abortAt: now, version: nextVersion++ });
229
+ };
230
+ const aborted = readSignalAborted(signal);
231
+ if (aborted === null)
232
+ return;
233
+ if (aborted) {
234
+ onAbort();
235
+ return;
236
+ }
237
+ tryListenAbortOnce(signal, onAbort);
238
+ },
239
+ forget(taskId) {
240
+ if (!validId(taskId))
241
+ return;
242
+ rows.delete(taskId);
243
+ },
244
+ size() {
245
+ const now = clock();
246
+ if (now !== null)
247
+ purge(now);
248
+ return rows.size;
249
+ },
250
+ };
251
+ }
252
+ function readStatus(row) {
253
+ try {
254
+ const s = row?.status;
255
+ return typeof s === 'string' && s.length > 0 ? s : null;
256
+ }
257
+ catch {
258
+ return null;
259
+ }
260
+ }
261
+ const PROBE_STOPPED = Symbol('sema.interruptedSettleProbeStopped');
262
+ const PROBE_FAILED = Symbol('sema.interruptedSettleProbeFailed');
263
+ const positive = (v, fallback) => (typeof v === 'number' && Number.isFinite(v) && v > 0 ? v : fallback);
264
+ export async function awaitInterruptedRunSettle(taskId, deps) {
265
+ const getRun = deps?.getRun;
266
+ if (typeof getRun !== 'function')
267
+ return { kind: 'unknown' };
268
+ if (!validId(taskId))
269
+ return { kind: 'unknown' };
270
+ const budgetMs = positive(deps.budgetMs, INTERRUPTED_SETTLE_BUDGET_MS);
271
+ const intervalMs = positive(deps.intervalMs, INTERRUPTED_SETTLE_POLL_MS);
272
+ const clockNow = typeof deps.now === 'function' ? deps.now : () => performance.now();
273
+ const readNow = () => {
274
+ try {
275
+ const t = clockNow();
276
+ return Number.isFinite(t) ? t : 0;
277
+ }
278
+ catch {
279
+ return 0;
280
+ }
281
+ };
282
+ const started = readNow();
283
+ let sawRunning = false;
284
+ const isAborted = () => deps.signal?.aborted === true;
285
+ const budgetAc = new AbortController();
286
+ let budgetSpent = false;
287
+ let markStopped = () => { };
288
+ const stopped = new Promise((resolve) => {
289
+ markStopped = () => resolve(PROBE_STOPPED);
290
+ });
291
+ const onCallerAbort = () => markStopped();
292
+ const budgetTimer = setTimeout(() => {
293
+ budgetSpent = true;
294
+ budgetAc.abort();
295
+ markStopped();
296
+ }, budgetMs);
297
+ if (deps.signal !== undefined)
298
+ tryListenAbortOnce(deps.signal, onCallerAbort);
299
+ if (isAborted())
300
+ markStopped();
301
+ const linked = linkedAbortSignal(deps.signal, budgetAc.signal);
302
+ const probeSignal = linked.signal;
303
+ try {
304
+ for (;;) {
305
+ if (isAborted())
306
+ return { kind: 'unknown' };
307
+ if (budgetSpent)
308
+ break;
309
+ let probe;
310
+ try {
311
+ probe = Promise.resolve(getRun(taskId, { signal: probeSignal })).then((row) => row, () => PROBE_FAILED);
312
+ }
313
+ catch {
314
+ probe = Promise.resolve(PROBE_FAILED);
315
+ }
316
+ const outcome = await Promise.race([probe, stopped]);
317
+ if (isAborted())
318
+ return { kind: 'unknown' };
319
+ const status = outcome === PROBE_STOPPED || outcome === PROBE_FAILED ? null : readStatus(outcome);
320
+ if (status !== null) {
321
+ if (isSdkRunTerminal(status))
322
+ return { kind: 'settled', status };
323
+ if (isSdkRunParked(status))
324
+ return { kind: 'parked', status };
325
+ if (status === 'running')
326
+ sawRunning = true;
327
+ }
328
+ if (budgetSpent)
329
+ break;
330
+ const left = started + budgetMs - readNow();
331
+ if (left <= 0)
332
+ break;
333
+ await abortableSleep(Math.min(intervalMs, left), probeSignal);
334
+ if (isAborted())
335
+ return { kind: 'unknown' };
336
+ }
337
+ if (isAborted())
338
+ return { kind: 'unknown' };
339
+ return sawRunning ? { kind: 'still-running', waitedMs: Math.max(0, readNow() - started) } : { kind: 'unknown' };
340
+ }
341
+ finally {
342
+ clearTimeout(budgetTimer);
343
+ linked.dispose();
344
+ if (deps.signal !== undefined)
345
+ tryUnlistenAbort(deps.signal, onCallerAbort);
346
+ }
347
+ }
348
+ export function interruptedRunSettleRow(taskId, verdict, lang) {
349
+ if (typeof verdict !== 'object' || verdict === null || verdict.kind !== 'settled')
350
+ return null;
351
+ return renderMessage(msg('session.selfHeal.row.interrupted.settled', { taskId: displayUntrusted(String(taskId), { max: 120 }) }), lang);
352
+ }
@@ -29,6 +29,8 @@ export interface ToolHistoryMismatchRowKey {
29
29
  }
30
30
  export declare function toolHistoryMismatchRowKey(m: ToolHistoryMismatch, consecutive: number | undefined, rewindOffered: boolean): ToolHistoryMismatchRowKey;
31
31
  export declare function readToolHistoryMismatchKey(v: object | null | undefined): ToolHistoryMismatchRowKey | undefined;
32
+ export declare const SEMA_TOOL_HISTORY_ACCEPTED_KEY = "_sema_tool_history_accepted";
33
+ export declare function readToolHistoryAcceptedKey(frame: object | null | undefined): true | undefined;
32
34
  export declare const TOOL_HISTORY_LEDGER_CAP = 64;
33
35
  export declare function openToolHistoryGeneration(): number;
34
36
  export interface ToolHistoryTerminalNote {
@@ -38,8 +40,14 @@ export interface ToolHistoryTerminalNote {
38
40
  runId: string | undefined;
39
41
  replay: boolean;
40
42
  mismatch: ToolHistoryMismatch | null;
43
+ accepted?: boolean;
44
+ }
45
+ export interface ToolHistoryTerminalFacts {
46
+ readonly consecutive: number | undefined;
47
+ readonly acceptedSinceMismatch: true | undefined;
41
48
  }
42
49
  export declare function noteToolHistoryTerminal(note: ToolHistoryTerminalNote): number | undefined;
50
+ export declare function noteToolHistoryTerminalFacts(note: ToolHistoryTerminalNote): ToolHistoryTerminalFacts;
43
51
  export declare function _resetToolHistoryLedgerForTest(): void;
44
52
  export interface ToolHistoryRow {
45
53
  readonly toolUseIds?: readonly string[];