@sema-agent/client-core 0.97.1 → 0.99.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 (353) hide show
  1. package/CHANGELOG.md +607 -0
  2. package/README.md +96 -46
  3. package/dist/adapt/arms.d.ts +1 -0
  4. package/dist/adapt/arms.js +188 -53
  5. package/dist/adapt/ids.d.ts +12 -1
  6. package/dist/adapt/ids.js +59 -8
  7. package/dist/adapt/instanceLedger.d.ts +50 -0
  8. package/dist/adapt/instanceLedger.js +147 -0
  9. package/dist/adapt/panelTasks.d.ts +1 -1
  10. package/dist/adapt/panelTasks.js +2 -2
  11. package/dist/adapt/textStream.d.ts +1 -0
  12. package/dist/adapt/textStream.js +24 -7
  13. package/dist/adapt/toolCards.d.ts +27 -5
  14. package/dist/adapt/toolCards.js +39 -6
  15. package/dist/adapt/wireShapes.js +6 -2
  16. package/dist/adapt.d.ts +2 -0
  17. package/dist/adapt.js +8 -3
  18. package/dist/adapter/activeRunSelfHeal.d.ts +9 -3
  19. package/dist/adapter/activeRunSelfHeal.js +205 -313
  20. package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -5
  21. package/dist/adapter/downstream/eventToSdkMessage.js +77 -36
  22. package/dist/adapter/downstream/terminalToSdkResult.js +11 -4
  23. package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +5 -2
  24. package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -0
  25. package/dist/adapter/runStream.js +79 -48
  26. package/dist/adapter/types.d.ts +4 -4
  27. package/dist/adapter/types.js +2 -1
  28. package/dist/agentSession/backgroundView.js +2 -1
  29. package/dist/agentSession/engineAgentRegistryRead.d.ts +2 -2
  30. package/dist/agentSession/engineAgentRegistryRead.js +12 -13
  31. package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
  32. package/dist/agentsWireCaps.d.ts +8 -11
  33. package/dist/agentsWireCaps.js +196 -194
  34. package/dist/approvalDecidedByCapability.d.ts +0 -4
  35. package/dist/approvalDecidedByCapability.js +0 -6
  36. package/dist/approvalsStreamLiveCapability.d.ts +0 -4
  37. package/dist/approvalsStreamLiveCapability.js +0 -6
  38. package/dist/assistantInbox.d.ts +34 -0
  39. package/dist/assistantInbox.js +118 -0
  40. package/dist/centerWiringCapability.js +9 -1
  41. package/dist/clientSlice.d.ts +0 -9
  42. package/dist/clientSlice.js +0 -3
  43. package/dist/cloudConfigWireCaps.d.ts +5 -3
  44. package/dist/cloudConfigWireCaps.js +106 -64
  45. package/dist/compensations.js +1 -1
  46. package/dist/connectorStatus.d.ts +21 -0
  47. package/dist/connectorStatus.js +112 -0
  48. package/dist/controlRouter.d.ts +18 -3
  49. package/dist/controlRouter.js +106 -67
  50. package/dist/coreValuePorts.d.ts +29 -4
  51. package/dist/coreValuePorts.js +10 -0
  52. package/dist/corruptSessionCopy.d.ts +2 -1
  53. package/dist/corruptSessionCopy.js +3 -3
  54. package/dist/decideReceipt.d.ts +2 -2
  55. package/dist/decideReceipt.js +5 -2
  56. package/dist/declared/supportFloorDeclared.js +3 -3
  57. package/dist/detachWire.js +3 -2
  58. package/dist/deviceExecutorManagementCapability.d.ts +0 -4
  59. package/dist/deviceExecutorManagementCapability.js +0 -6
  60. package/dist/deviceRebind.d.ts +49 -1
  61. package/dist/deviceRebind.js +221 -3
  62. package/dist/devicesFace.d.ts +34 -0
  63. package/dist/devicesFace.js +90 -0
  64. package/dist/displayUntrusted.d.ts +2 -0
  65. package/dist/displayUntrusted.js +253 -76
  66. package/dist/engineAgentAbsence.d.ts +1 -1
  67. package/dist/engineAgentPanelStore.d.ts +12 -4
  68. package/dist/engineAgentPanelStore.js +16 -11
  69. package/dist/engineCapReader.d.ts +2 -5
  70. package/dist/engineCapReader.js +8 -10
  71. package/dist/engineCapsCache.d.ts +12 -0
  72. package/dist/engineCapsCache.js +76 -18
  73. package/dist/engineCapsChange.d.ts +2 -0
  74. package/dist/engineCapsChange.js +9 -0
  75. package/dist/engineClosedSets.d.ts +1 -0
  76. package/dist/engineClosedSets.js +4 -1
  77. package/dist/engineErrorCodes.d.ts +11 -3
  78. package/dist/engineErrorCodes.js +11 -8
  79. package/dist/engineIdentity.d.ts +1 -0
  80. package/dist/engineIdentity.js +8 -0
  81. package/dist/engineRowRef.d.ts +28 -0
  82. package/dist/engineRowRef.js +114 -0
  83. package/dist/engineSessionMessages.d.ts +68 -0
  84. package/dist/engineSessionMessages.js +370 -0
  85. package/dist/engineTargetSeat.d.ts +27 -0
  86. package/dist/engineTargetSeat.js +199 -0
  87. package/dist/engineToolDirectory.d.ts +0 -9
  88. package/dist/engineToolDirectory.js +1 -94
  89. package/dist/engineUrl.d.ts +18 -0
  90. package/dist/engineUrl.js +52 -0
  91. package/dist/engineWireFor.js +3 -8
  92. package/dist/env/uiLanguage.d.ts +11 -1
  93. package/dist/env/uiLanguage.js +38 -2
  94. package/dist/eventLeg.d.ts +100 -0
  95. package/dist/eventLeg.js +305 -0
  96. package/dist/executionLaneCapability.d.ts +0 -4
  97. package/dist/executionLaneCapability.js +3 -16
  98. package/dist/fileHistoryCaptureCapability.d.ts +2 -5
  99. package/dist/fileHistoryCaptureCapability.js +13 -21
  100. package/dist/fileHistoryLegNotice.d.ts +2 -1
  101. package/dist/fileHistoryLegNotice.js +3 -3
  102. package/dist/fleet/fleetLedger.d.ts +0 -3
  103. package/dist/fleet/fleetLedger.js +21 -36
  104. package/dist/fleet/fleetProjection.d.ts +2 -2
  105. package/dist/fleet/fleetProjection.js +10 -8
  106. package/dist/frameBinding.d.ts +8 -0
  107. package/dist/frameBinding.js +35 -0
  108. package/dist/gateFailureCodes.d.ts +2 -0
  109. package/dist/gateFailureCodes.js +15 -0
  110. package/dist/gateOutcome.d.ts +3 -1
  111. package/dist/gateOutcome.js +41 -8
  112. package/dist/gateVocabulary.d.ts +10 -4
  113. package/dist/gateVocabulary.js +107 -47
  114. package/dist/generated/engineAskFaceTables.js +2 -2
  115. package/dist/generated/engineFactTables.d.ts +22 -3
  116. package/dist/generated/engineFactTables.js +51 -4
  117. package/dist/generated/engineNoticeTables.js +18 -3
  118. package/dist/generated/settingsSchemaFns.d.ts +6 -0
  119. package/dist/generated/settingsSchemaFns.js +57 -0
  120. package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
  121. package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
  122. package/dist/generated/settingsSchemaTables.d.ts +1 -0
  123. package/dist/generated/settingsSchemaTables.js +4 -0
  124. package/dist/generated/settingsSchemaTypes.d.ts +105 -0
  125. package/dist/generated/settingsSchemaTypes.js +1 -0
  126. package/dist/generated/toolNameTables.d.ts +1 -0
  127. package/dist/generated/toolNameTables.js +1 -0
  128. package/dist/hitl/allowRuleShadow.d.ts +8 -2
  129. package/dist/hitl/allowRuleShadow.js +36 -29
  130. package/dist/hitl/approvalCardReading.d.ts +15 -0
  131. package/dist/hitl/approvalCardReading.js +154 -0
  132. package/dist/hitl/approvalCardReasons.d.ts +14 -0
  133. package/dist/hitl/approvalCardReasons.js +119 -0
  134. package/dist/hitl/approvalHolds.d.ts +50 -15
  135. package/dist/hitl/approvalHolds.js +177 -27
  136. package/dist/hitl/approvalResolution.d.ts +51 -26
  137. package/dist/hitl/approvalResolution.js +86 -122
  138. package/dist/hitl/approvalsFeed.js +6 -18
  139. package/dist/hitl/askClassPair.d.ts +2 -0
  140. package/dist/hitl/askClassPair.js +17 -0
  141. package/dist/hitl/askGateWire.d.ts +20 -2
  142. package/dist/hitl/askGateWire.js +50 -1
  143. package/dist/hitl/askParkRowRouting.d.ts +5 -0
  144. package/dist/hitl/askParkRowRouting.js +32 -1
  145. package/dist/hitl/askSettlementLine.d.ts +28 -0
  146. package/dist/hitl/askSettlementLine.js +99 -0
  147. package/dist/hitl/automaticAnswerVerdict.d.ts +3 -2
  148. package/dist/hitl/automaticAnswerVerdict.js +29 -13
  149. package/dist/hitl/crashConverged.d.ts +11 -20
  150. package/dist/hitl/crashConverged.js +56 -0
  151. package/dist/hitl/crashConvergedNotice.d.ts +6 -3
  152. package/dist/hitl/crashConvergedNotice.js +48 -24
  153. package/dist/hitl/decisionConflict.js +3 -10
  154. package/dist/hitl/decisionRefusal.d.ts +40 -1
  155. package/dist/hitl/decisionRefusal.js +199 -42
  156. package/dist/hitl/frameRouter.d.ts +5 -2
  157. package/dist/hitl/frameRouter.js +27 -24
  158. package/dist/hitl/gateLedger.d.ts +2 -0
  159. package/dist/hitl/gateLedger.js +50 -13
  160. package/dist/hitl/hitlBridge.d.ts +2 -2
  161. package/dist/hitl/hitlBridge.js +13 -10
  162. package/dist/hitl/livePendingAsk.d.ts +3 -3
  163. package/dist/hitl/livePendingAsk.js +7 -18
  164. package/dist/hitl/parkResolver.d.ts +2 -24
  165. package/dist/hitl/parkResolver.js +61 -97
  166. package/dist/hitl/persistedRulesWire.d.ts +25 -0
  167. package/dist/hitl/persistedRulesWire.js +104 -2
  168. package/dist/hitl/planReviewWire.d.ts +31 -13
  169. package/dist/hitl/planReviewWire.js +120 -78
  170. package/dist/hitl/refusedToolNameProse.d.ts +0 -1
  171. package/dist/hitl/refusedToolNameProse.js +0 -3
  172. package/dist/hitl/replayedApproval.d.ts +4 -3
  173. package/dist/hitl/replayedApproval.js +7 -4
  174. package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
  175. package/dist/hitl/sessionPolicyDeliverable.js +48 -7
  176. package/dist/hitl/sessionPolicyWire.d.ts +34 -21
  177. package/dist/hitl/sessionPolicyWire.js +179 -70
  178. package/dist/hitl/standingRows.d.ts +20 -2
  179. package/dist/hitl/standingRows.js +69 -8
  180. package/dist/hitl/suspendedReopen.d.ts +2 -1
  181. package/dist/hitl/suspendedReopen.js +7 -10
  182. package/dist/hitl/toolApprovalWire.d.ts +103 -156
  183. package/dist/hitl/toolApprovalWire.js +661 -411
  184. package/dist/hookMatcherVerdict.d.ts +6 -1
  185. package/dist/hookMatcherVerdict.js +14 -7
  186. package/dist/hooksWireCaps.d.ts +2 -2
  187. package/dist/hooksWireCaps.js +174 -81
  188. package/dist/host.d.ts +21 -0
  189. package/dist/hostTurnSettings.d.ts +71 -0
  190. package/dist/hostTurnSettings.js +291 -0
  191. package/dist/humanTurn.d.ts +14 -1
  192. package/dist/humanTurn.js +100 -12
  193. package/dist/humanTurnRead.d.ts +2 -0
  194. package/dist/humanTurnRead.js +22 -1
  195. package/dist/i18n/messages.en.d.ts +703 -0
  196. package/dist/i18n/messages.en.js +701 -0
  197. package/dist/i18n/messages.zh.d.ts +3 -0
  198. package/dist/i18n/messages.zh.js +837 -0
  199. package/dist/i18n/translate.d.ts +25 -0
  200. package/dist/i18n/translate.js +127 -0
  201. package/dist/index.d.ts +78 -29
  202. package/dist/index.js +54 -18
  203. package/dist/inheritEnvCapability.d.ts +32 -0
  204. package/dist/inheritEnvCapability.js +104 -0
  205. package/dist/inheritEnvWire.d.ts +3 -2
  206. package/dist/inheritEnvWire.js +12 -14
  207. package/dist/interactiveHalt.js +17 -6
  208. package/dist/liveModelCatalog.d.ts +3 -3
  209. package/dist/liveModelCatalog.js +15 -13
  210. package/dist/liveQuestionStore.d.ts +2 -21
  211. package/dist/mcpLiveness.d.ts +2 -1
  212. package/dist/mcpPanel.d.ts +10 -1
  213. package/dist/mcpPanel.js +40 -13
  214. package/dist/mcpProbeCapability.d.ts +2 -1
  215. package/dist/mcpProbeCapability.js +7 -11
  216. package/dist/mcpProbeWire.d.ts +9 -2
  217. package/dist/mcpProbeWire.js +6 -1
  218. package/dist/mcpWireCaps.d.ts +47 -2
  219. package/dist/mcpWireCaps.js +164 -16
  220. package/dist/memoryEntriesWire.d.ts +4 -9
  221. package/dist/memoryEntriesWire.js +5 -10
  222. package/dist/model/modelSupplyRules.d.ts +0 -2
  223. package/dist/model/modelSupplyRules.js +3 -12
  224. package/dist/model/modelsPolicy.d.ts +0 -5
  225. package/dist/model/modelsPolicy.js +6 -36
  226. package/dist/model/onboardJudgement.d.ts +93 -0
  227. package/dist/model/onboardJudgement.js +415 -0
  228. package/dist/model/subagentModelWord.d.ts +31 -0
  229. package/dist/model/subagentModelWord.js +261 -0
  230. package/dist/model/tierVocabulary.d.ts +2 -0
  231. package/dist/model/tierVocabulary.js +17 -5
  232. package/dist/modelCapabilityProbe.d.ts +64 -0
  233. package/dist/modelCapabilityProbe.js +600 -0
  234. package/dist/modelIdentityResolvability.d.ts +3 -0
  235. package/dist/modelIdentityResolvability.js +26 -17
  236. package/dist/notifications.d.ts +6 -0
  237. package/dist/notifications.js +71 -23
  238. package/dist/outputStyleSeatCapability.d.ts +0 -3
  239. package/dist/outputStyleSeatCapability.js +0 -3
  240. package/dist/ownKey.d.ts +22 -0
  241. package/dist/ownKey.js +94 -3
  242. package/dist/panelReduce.d.ts +21 -10
  243. package/dist/panelReduce.js +728 -550
  244. package/dist/panelStateHolder.d.ts +3 -7
  245. package/dist/panelStateHolder.js +14 -130
  246. package/dist/peerLaneCapability.d.ts +0 -4
  247. package/dist/peerLaneCapability.js +0 -6
  248. package/dist/permissionRuleIssue.js +2 -0
  249. package/dist/permissionRulesWriteCapability.d.ts +2 -5
  250. package/dist/permissionRulesWriteCapability.js +8 -12
  251. package/dist/permissionWireCaps.d.ts +2 -2
  252. package/dist/permissionWireCaps.js +2 -0
  253. package/dist/permissionsAllowGrantCapability.d.ts +0 -4
  254. package/dist/permissionsAllowGrantCapability.js +0 -6
  255. package/dist/permissionsDeclaration.d.ts +0 -11
  256. package/dist/permissionsDeclaration.js +60 -53
  257. package/dist/pluginHooksWire.d.ts +46 -3
  258. package/dist/pluginHooksWire.js +219 -16
  259. package/dist/preemptWire.d.ts +44 -0
  260. package/dist/preemptWire.js +83 -0
  261. package/dist/printModelStatus.d.ts +63 -0
  262. package/dist/printModelStatus.js +155 -0
  263. package/dist/printToolResultFrame.js +15 -4
  264. package/dist/replayBody.d.ts +3 -0
  265. package/dist/replayBody.js +14 -0
  266. package/dist/request/taskRequest.d.ts +11 -6
  267. package/dist/request/taskRequest.js +112 -19
  268. package/dist/resumeRefusalCopy.d.ts +13 -9
  269. package/dist/resumeRefusalCopy.js +81 -118
  270. package/dist/retryStatus.d.ts +45 -0
  271. package/dist/retryStatus.js +185 -1
  272. package/dist/rewindArchiveCapability.d.ts +0 -4
  273. package/dist/rewindArchiveCapability.js +2 -10
  274. package/dist/rewindArchiveReading.d.ts +0 -1
  275. package/dist/rewindArchiveReading.js +0 -3
  276. package/dist/runCancelContext.d.ts +2 -1
  277. package/dist/runCancelContext.js +4 -2
  278. package/dist/runReattachPolicy.d.ts +31 -0
  279. package/dist/runReattachPolicy.js +46 -0
  280. package/dist/runTerminal.d.ts +3 -6
  281. package/dist/runTerminal.js +8 -9
  282. package/dist/sandboxWire.d.ts +3 -1
  283. package/dist/sandboxWire.js +76 -27
  284. package/dist/scenarioRefusal.d.ts +9 -0
  285. package/dist/scenarioRefusal.js +111 -0
  286. package/dist/scenarioWire.js +1 -1
  287. package/dist/seam.d.ts +48 -2
  288. package/dist/seam.js +25 -4
  289. package/dist/seatContract.d.ts +311 -18
  290. package/dist/seatContract.js +824 -100
  291. package/dist/selfOrchestrationDenial.js +7 -19
  292. package/dist/sessionIdSegment.d.ts +6 -0
  293. package/dist/sessionIdSegment.js +24 -0
  294. package/dist/sessionMemoryStatus.js +6 -11
  295. package/dist/sessionPolicyCapability.d.ts +2 -5
  296. package/dist/sessionPolicyCapability.js +8 -12
  297. package/dist/sessionSyncFileHistoryCapability.d.ts +0 -3
  298. package/dist/sessionSyncFileHistoryCapability.js +0 -3
  299. package/dist/settingsHooksSalvage.d.ts +44 -0
  300. package/dist/settingsHooksSalvage.js +211 -0
  301. package/dist/skillToolListsCapability.d.ts +2 -4
  302. package/dist/skillToolListsCapability.js +8 -9
  303. package/dist/sqlEngineCapability.d.ts +0 -4
  304. package/dist/sqlEngineCapability.js +0 -6
  305. package/dist/sseIdleTriage.js +3 -2
  306. package/dist/steerPriorityCapability.d.ts +0 -3
  307. package/dist/steerPriorityCapability.js +0 -3
  308. package/dist/streamDrainingLegs.d.ts +4 -0
  309. package/dist/streamDrainingLegs.js +6 -1
  310. package/dist/subagent/engineCompactWire.d.ts +0 -1
  311. package/dist/subagent/engineCompactWire.js +7 -5
  312. package/dist/subagent/engineSubagentResume.js +15 -9
  313. package/dist/subagent/engineTaskHandleWire.js +4 -7
  314. package/dist/subagentContentStore.d.ts +3 -0
  315. package/dist/subagentContentStore.js +22 -10
  316. package/dist/submitReopen.d.ts +24 -0
  317. package/dist/submitReopen.js +75 -0
  318. package/dist/terminalStatuses.d.ts +3 -0
  319. package/dist/terminalStatuses.js +10 -2
  320. package/dist/toolHistoryMismatch.js +3 -2
  321. package/dist/toolResult.d.ts +10 -1
  322. package/dist/toolResult.js +34 -6
  323. package/dist/toolRoster.d.ts +3 -4
  324. package/dist/toolRoster.js +21 -22
  325. package/dist/turnFailurePresentation.d.ts +39 -0
  326. package/dist/turnFailurePresentation.js +402 -0
  327. package/dist/usageAnalytics.js +6 -11
  328. package/dist/userAttachmentEnvelope.d.ts +1 -0
  329. package/dist/userAttachmentEnvelope.js +37 -7
  330. package/dist/userAttachmentSeat.d.ts +21 -0
  331. package/dist/userAttachmentSeat.js +75 -0
  332. package/dist/userInvokedSkillsCapability.d.ts +11 -4
  333. package/dist/userInvokedSkillsCapability.js +31 -10
  334. package/dist/webSearchBackendCapability.d.ts +0 -4
  335. package/dist/webSearchBackendCapability.js +0 -6
  336. package/dist/wireErrorTriage.d.ts +7 -0
  337. package/dist/wireErrorTriage.js +26 -23
  338. package/dist/wireFailureShape.d.ts +62 -5
  339. package/dist/wireFailureShape.js +106 -5
  340. package/dist/wireRefusalCopy.d.ts +25 -3
  341. package/dist/wireRefusalCopy.js +74 -80
  342. package/dist/workflowsJournalCapability.d.ts +2 -5
  343. package/dist/workflowsJournalCapability.js +8 -12
  344. package/dist/writeProtectionCapability.d.ts +0 -4
  345. package/dist/writeProtectionCapability.js +0 -6
  346. package/docs/INTEGRATION-CLIENTS.md +1775 -56
  347. package/package.json +6 -5
  348. package/dist/attachmentSeatCapability.d.ts +0 -12
  349. package/dist/attachmentSeatCapability.js +0 -23
  350. package/dist/hitl/approvalOutcomeNote.d.ts +0 -10
  351. package/dist/hitl/approvalOutcomeNote.js +0 -29
  352. package/dist/sessionReadRedactionCapability.d.ts +0 -13
  353. package/dist/sessionReadRedactionCapability.js +0 -35
@@ -1,10 +1,11 @@
1
1
  import type { WireHooksConfig } from './finalVerifyWire.js';
2
- import type { PluginHookSource } from './host.js';
2
+ import type { PluginHookSource, SessionHookOrigin, SessionHookSource } from './host.js';
3
+ import { type HooksSalvageDrop, type HooksSalvageMask, type HooksSalvageRejection } from './settingsHooksSalvage.js';
3
4
  export declare const ENGINE_FIRED_HOOK_EVENTS: readonly ["PreToolUse", "PostToolUse", "PostToolUseFailure", "PostToolBatch", "PreCompact", "PostCompact", "Stop", "StopFailure", "UserPromptSubmit"];
4
5
  export type EngineFiredHookEvent = (typeof ENGINE_FIRED_HOOK_EVENTS)[number];
5
6
  export declare const PLUGIN_HOOK_DISPOSITIONS: readonly ["engine", "shell", "not_run"];
6
7
  export type PluginHookDisposition = (typeof PLUGIN_HOOK_DISPOSITIONS)[number];
7
- export declare const PLUGIN_HOOK_REASONS: readonly ["projected", "shell_event", "no_executor", "engine_not_local", "engine_locality_unknown", "engine_capability_absent", "engine_capability_unknown", "not_command", "sensitive_options", "engine_limit", "shell_form_user_config", "user_config_unset", "malformed_entry", "engine_hooks_off", "engine_hooks_unknown", "engine_type_skipped", "engine_llm_limit", "engine_unconfirmed", "engine_elsewhere"];
8
+ export declare const PLUGIN_HOOK_REASONS: readonly ["projected", "shell_event", "no_executor", "engine_not_local", "engine_locality_unknown", "engine_capability_absent", "engine_capability_unknown", "not_command", "sensitive_options", "engine_limit", "shell_form_user_config", "user_config_unset", "malformed_entry", "engine_hooks_off", "engine_hooks_unknown", "engine_type_skipped", "engine_llm_limit", "engine_unconfirmed", "engine_elsewhere", "hooks_module", "scope_unsupported", "source_incomplete"];
8
9
  export type PluginHookReason = (typeof PLUGIN_HOOK_REASONS)[number];
9
10
  export declare const PLUGIN_HOOK_EXCLUSION_REASONS: readonly ["workspace_untrusted", "governance_unreadable", "policy_disable_all", "startup_mode", "managed_plugins_only", "prompt_not_user_authored"];
10
11
  export type PluginHookExclusionReason = (typeof PLUGIN_HOOK_EXCLUSION_REASONS)[number];
@@ -48,6 +49,28 @@ export interface SettingsHookExclusion {
48
49
  readonly hookIndex: number;
49
50
  readonly reason: PluginHookExclusionReason;
50
51
  }
52
+ export interface SettingsHooksSalvageRow {
53
+ readonly source: HookSettingsSource;
54
+ readonly outcome: 'loaded-partial' | 'rejected';
55
+ readonly dropped: readonly HooksSalvageDrop[];
56
+ readonly rejections: readonly HooksSalvageRejection[];
57
+ readonly notice: string;
58
+ }
59
+ export interface PluginHookModuleVerdict {
60
+ readonly pluginId: string;
61
+ readonly pluginName: string;
62
+ readonly disposition: PluginHookDisposition;
63
+ readonly reason: PluginHookReason;
64
+ }
65
+ export interface SessionHookVerdict {
66
+ readonly origin: SessionHookOrigin;
67
+ readonly name: string;
68
+ readonly event: string;
69
+ readonly groupIndex: number;
70
+ readonly hookIndex: number;
71
+ readonly disposition: PluginHookDisposition;
72
+ readonly reason: PluginHookReason;
73
+ }
51
74
  export interface HooksWireEngineFacts {
52
75
  readonly ownedByThisShell: boolean | null;
53
76
  readonly pluginHooksCapable: boolean | null;
@@ -62,6 +85,11 @@ export interface HooksWirePlan {
62
85
  readonly settingsDropped: readonly SettingsHookDrop[];
63
86
  readonly settingsVerdicts: readonly SettingsHookVerdict[];
64
87
  readonly settingsExcluded: readonly SettingsHookExclusion[];
88
+ readonly settingsSalvage: readonly SettingsHooksSalvageRow[];
89
+ readonly moduleVerdicts: readonly PluginHookModuleVerdict[];
90
+ readonly sessionVerdicts: readonly SessionHookVerdict[];
91
+ readonly sessionReader: PluginHookReaderState;
92
+ readonly closedBy: Extract<PluginHookExclusionReason, 'workspace_untrusted' | 'governance_unreadable' | 'policy_disable_all'> | null;
65
93
  readonly wire: WireHooksConfig | undefined;
66
94
  }
67
95
  export interface HooksWirePlanOptions {
@@ -70,7 +98,9 @@ export interface HooksWirePlanOptions {
70
98
  readonly shellHookEvents?: readonly string[];
71
99
  readonly shellHookTypesByEvent?: Readonly<Record<string, readonly string[]>>;
72
100
  readonly promptAuthoredByUser?: boolean;
101
+ readonly suppressedLocally?: readonly string[];
73
102
  }
103
+ export declare function hooksWirePlanShapeOf(v: unknown): 'plan' | 'not' | 'threw';
74
104
  export declare const ENGINE_HOOK_LIMITS: {
75
105
  readonly maxGroupsPerEvent: 16;
76
106
  readonly maxEntriesPerEvent: 32;
@@ -102,15 +132,27 @@ export interface PluginHookDecisionInput {
102
132
  readonly shellRuns: ShellRunsHook;
103
133
  readonly promptAuthoredByUser: boolean;
104
134
  readonly occupied: ReadonlyMap<string, EventOccupancy>;
135
+ readonly suppressedLocally?: ReadonlySet<string>;
105
136
  }
106
137
  export interface PluginHookDecision {
107
138
  readonly verdicts: readonly PluginHookVerdict[];
139
+ readonly modules: readonly PluginHookModuleVerdict[];
108
140
  readonly excluded: readonly PluginHookExclusion[];
109
141
  readonly projected: ReadonlyMap<string, readonly WireHookGroup[]>;
110
142
  readonly unreadable: number;
111
143
  }
112
144
  export declare function decidePluginHooks(input: PluginHookDecisionInput): PluginHookDecision;
113
- export declare function filterSettingsHookGroups(source: HookSettingsSource, event: string, groups: readonly WireHookGroup[], execFormCapable: boolean, shellRunsType: (type: string | undefined) => boolean, failLoudMcpTool: boolean, judge?: SettingsHookJudge): SettingsHookFilterResult;
145
+ export interface SessionHookDecisionInput {
146
+ readonly sources: readonly SessionHookSource[];
147
+ readonly engine: HooksWireEngineFacts;
148
+ readonly shellRuns: ShellRunsHook;
149
+ readonly promptAuthoredByUser: boolean;
150
+ }
151
+ export declare function decideSessionHooks(input: SessionHookDecisionInput): {
152
+ readonly verdicts: readonly SessionHookVerdict[];
153
+ readonly unreadable: number;
154
+ };
155
+ export declare function filterSettingsHookGroups(source: HookSettingsSource, event: string, groups: readonly WireHookGroup[], execFormCapable: boolean, shellRunsType: (type: string | undefined) => boolean, judge: SettingsHookJudge, mask?: HooksSalvageMask): SettingsHookFilterResult;
114
156
  export interface SettingsHookFilterResult {
115
157
  readonly groups: WireHookGroup[];
116
158
  readonly drops: SettingsHookDrop[];
@@ -140,4 +182,5 @@ export declare function pluginHookReasonText(reason: PluginHookReason): string;
140
182
  export declare function settingsHookDropText(reason: SettingsHookDropReason): string;
141
183
  export declare function pluginHookExecutorLabel(v: PluginHookVerdict): string;
142
184
  export declare function hooksNotRunNotice(plan: HooksWirePlan): readonly string[];
185
+ export declare function userPromptSubmitExecutorOf(plan: HooksWirePlan): 'shell' | 'engine' | 'unknown' | 'none';
143
186
  export {};
@@ -1,5 +1,6 @@
1
1
  import { displayUntrusted } from './displayUntrusted.js';
2
2
  import { SETTINGS_ENGINE_OWNED_HOOK_EVENTS } from './generated/settingsSchemaTables.js';
3
+ import { HOOK_SETTINGS_SOURCE_TEXT, hooksSalvageMaskOf, salvageSettingsHooksEntries, } from './settingsHooksSalvage.js';
3
4
  export const ENGINE_FIRED_HOOK_EVENTS = SETTINGS_ENGINE_OWNED_HOOK_EVENTS;
4
5
  export const PLUGIN_HOOK_DISPOSITIONS = ['engine', 'shell', 'not_run'];
5
6
  export const PLUGIN_HOOK_REASONS = [
@@ -22,6 +23,9 @@ export const PLUGIN_HOOK_REASONS = [
22
23
  'engine_llm_limit',
23
24
  'engine_unconfirmed',
24
25
  'engine_elsewhere',
26
+ 'hooks_module',
27
+ 'scope_unsupported',
28
+ 'source_incomplete',
25
29
  ];
26
30
  export const PLUGIN_HOOK_EXCLUSION_REASONS = [
27
31
  'workspace_untrusted',
@@ -32,6 +36,43 @@ export const PLUGIN_HOOK_EXCLUSION_REASONS = [
32
36
  'prompt_not_user_authored',
33
37
  ];
34
38
  export const SETTINGS_HOOK_DROP_REASONS = ['exec_form_unsupported', 'mcp_tool_unsupported'];
39
+ export function hooksWirePlanShapeOf(v) {
40
+ try {
41
+ if (typeof v !== 'object' || v === null || Array.isArray(v))
42
+ return 'not';
43
+ const o = v;
44
+ for (const k of PLAN_KEYS)
45
+ if (!Object.hasOwn(o, k) && !LATER_PLAN_KEYS.has(k))
46
+ return 'not';
47
+ const reader = o.pluginReader;
48
+ const engineFacts = o.engine;
49
+ const wire = o.wire;
50
+ const arrayOrAbsent = (k) => !Object.hasOwn(o, k) || Array.isArray(o[k]);
51
+ return Array.isArray(o.verdicts) &&
52
+ Array.isArray(o.excluded) &&
53
+ Array.isArray(o.settingsDropped) &&
54
+ arrayOrAbsent('settingsVerdicts') &&
55
+ arrayOrAbsent('settingsExcluded') &&
56
+ arrayOrAbsent('settingsSalvage') &&
57
+ arrayOrAbsent('moduleVerdicts') &&
58
+ arrayOrAbsent('sessionVerdicts') &&
59
+ (!Object.hasOwn(o, 'sessionReader') || o.sessionReader === 'present' || o.sessionReader === 'absent' || o.sessionReader === 'failed') &&
60
+ (!Object.hasOwn(o, 'closedBy') || o.closedBy === null || o.closedBy === 'workspace_untrusted' || o.closedBy === 'governance_unreadable' || o.closedBy === 'policy_disable_all') &&
61
+ (reader === 'present' || reader === 'absent' || reader === 'failed') &&
62
+ typeof engineFacts === 'object' &&
63
+ engineFacts !== null &&
64
+ (wire === undefined || (typeof wire === 'object' && wire !== null && !Array.isArray(wire)))
65
+ ? 'plan'
66
+ : 'not';
67
+ }
68
+ catch {
69
+ return 'threw';
70
+ }
71
+ }
72
+ const PLAN_KEYS = ['engine', 'pluginReader', 'verdicts', 'excluded', 'settingsDropped', 'settingsVerdicts', 'settingsExcluded', 'settingsSalvage', 'moduleVerdicts', 'sessionVerdicts', 'sessionReader', 'closedBy', 'wire'];
73
+ const LATER_PLAN_KEYS = new Set(['settingsVerdicts', 'settingsExcluded', 'settingsSalvage', 'moduleVerdicts', 'sessionVerdicts', 'sessionReader', 'closedBy']);
74
+ const _planKeysPin = [true, true];
75
+ void _planKeysPin;
35
76
  export const ENGINE_HOOK_LIMITS = { maxGroupsPerEvent: 16, maxEntriesPerEvent: 32, maxCommandChars: 8192, maxLlmEntriesPerEvent: 4 };
36
77
  const ENGINE_HOOK_TYPE_RUNS = new Set(['command', 'http', 'prompt', 'agent']);
37
78
  const COMPACTION_EVENTS = new Set(['PreCompact', 'PostCompact']);
@@ -39,6 +80,8 @@ const judged = (disposition, reason) => ({ kind: 'judged', disposition, reason }
39
80
  function hookExecutorOf(x) {
40
81
  if (x.event === 'UserPromptSubmit' && !x.promptAuthoredByUser)
41
82
  return { kind: 'excluded', reason: 'prompt_not_user_authored' };
83
+ if (x.source === 'session')
84
+ return judged(x.shellRuns ? 'shell' : 'not_run', 'scope_unsupported');
42
85
  if (x.source === 'settings') {
43
86
  const why = x.powershell
44
87
  ? { reason: 'engine_type_skipped', certain: true }
@@ -172,15 +215,25 @@ export function occupancyOf(wire) {
172
215
  export function decidePluginHooks(input) {
173
216
  const verdicts = [];
174
217
  const excluded = [];
218
+ const modules = [];
175
219
  const candidates = new Map();
176
220
  let unreadable = 0;
177
221
  const fallback = (event, type, reason) => input.shellRuns(event, typeof type === 'string' ? type : undefined) ? { disposition: 'shell', reason } : { disposition: 'not_run', reason };
178
222
  input.plugins.forEach((p, pluginIndex) => {
179
- if (!isRecord(p) || !isRecord(p.hooks)) {
223
+ if (!isRecord(p)) {
224
+ unreadable++;
225
+ return;
226
+ }
227
+ if (p.hooksModule === true && input.exclusion === undefined && !(input.managedOnly && p.managed !== true)) {
228
+ modules.push({ pluginId: typeof p.id === 'string' ? p.id : '', pluginName: typeof p.name === 'string' ? p.name : '', disposition: 'not_run', reason: 'hooks_module' });
229
+ }
230
+ if (!isRecord(p.hooks)) {
180
231
  unreadable++;
181
232
  return;
182
233
  }
183
234
  const src = p;
235
+ const sv = salvageSettingsHooksEntries({ hooks: p.hooks });
236
+ const pieceMask = hooksSalvageMaskOf(sv.outcome === 'loaded-partial' ? sv.dropped : []);
184
237
  const sourceOk = nonEmptyString(p.id) && nonEmptyString(p.name) && nonEmptyString(p.root) && nonEmptyString(p.dataDir);
185
238
  const pluginId = typeof p.id === 'string' ? p.id : '';
186
239
  const pluginName = typeof p.name === 'string' ? p.name : '';
@@ -207,7 +260,15 @@ export function decidePluginHooks(input) {
207
260
  return;
208
261
  }
209
262
  const entryType = isRecord(entry) && typeof entry.type === 'string' ? entry.type : undefined;
210
- const shape = sourceOk ? classifyEntry(entry, src.options) : { kind: 'malformed' };
263
+ if (!sourceOk) {
264
+ verdicts.push({ ...key, disposition: 'not_run', reason: 'source_incomplete' });
265
+ return;
266
+ }
267
+ if (!pieceMask.eventDropped(event) && pieceMask.entryDropped(event, groupIndex, hookIndex)) {
268
+ verdicts.push({ ...key, disposition: 'not_run', reason: 'malformed_entry' });
269
+ return;
270
+ }
271
+ const shape = classifyEntry(entry, src.options);
211
272
  if (shape.kind === 'malformed') {
212
273
  verdicts.push({ ...key, disposition: 'not_run', reason: 'malformed_entry' });
213
274
  return;
@@ -299,7 +360,79 @@ export function decidePluginHooks(input) {
299
360
  }
300
361
  projected.set(event, groupsOut);
301
362
  }
302
- return { verdicts, excluded, projected, unreadable };
363
+ const suppressed = input.suppressedLocally;
364
+ if (suppressed !== undefined && suppressed.size > 0) {
365
+ for (const v of verdicts) {
366
+ if (v.disposition !== 'shell' || !suppressed.has(v.pluginId))
367
+ continue;
368
+ v.disposition = 'not_run';
369
+ if (!ENGINE_EVENTS.has(v.event))
370
+ v.reason = 'no_executor';
371
+ }
372
+ }
373
+ return { verdicts, excluded, modules, projected, unreadable };
374
+ }
375
+ const SESSION_HOOK_ORIGINS = new Set(['skill', 'agent', 'sdk_host']);
376
+ const LOCAL_REGISTRATION_TYPES = new Set(['callback', 'function']);
377
+ const isLocalRegistration = (e) => isRecord(e) && typeof e.type === 'string' && LOCAL_REGISTRATION_TYPES.has(e.type);
378
+ const JUDGE_STAND_IN = Object.freeze({ type: 'command', command: 'true' });
379
+ function sessionHooksForJudge(hooks) {
380
+ const out = {};
381
+ for (const [event, groups] of Object.entries(hooks)) {
382
+ out[event] = Array.isArray(groups)
383
+ ? groups.map((g) => isRecord(g) && Array.isArray(g.hooks) && g.hooks.some(isLocalRegistration)
384
+ ? { ...g, hooks: g.hooks.map((e) => (isLocalRegistration(e) ? JUDGE_STAND_IN : e)) }
385
+ : g)
386
+ : groups;
387
+ }
388
+ return out;
389
+ }
390
+ export function decideSessionHooks(input) {
391
+ const out = [];
392
+ let unreadable = 0;
393
+ for (const src of input.sources) {
394
+ if (!isRecord(src) || typeof src.origin !== 'string' || !SESSION_HOOK_ORIGINS.has(src.origin) || !isRecord(src.hooks)) {
395
+ unreadable++;
396
+ continue;
397
+ }
398
+ const origin = src.origin;
399
+ const name = typeof src.name === 'string' ? src.name : '';
400
+ const sv = salvageSettingsHooksEntries({ hooks: sessionHooksForJudge(src.hooks) });
401
+ const rejectedWhole = sv.outcome === 'rejected';
402
+ const mask = hooksSalvageMaskOf(sv.outcome === 'loaded-partial' ? sv.dropped : []);
403
+ for (const [event, groups] of Object.entries(src.hooks)) {
404
+ if (!Array.isArray(groups)) {
405
+ unreadable++;
406
+ continue;
407
+ }
408
+ ;
409
+ groups.forEach((group, groupIndex) => {
410
+ if (!isRecord(group) || !Array.isArray(group.hooks)) {
411
+ unreadable++;
412
+ return;
413
+ }
414
+ ;
415
+ group.hooks.forEach((entry, hookIndex) => {
416
+ const key = { origin, name, event, groupIndex, hookIndex };
417
+ const type = isRecord(entry) && typeof entry.type === 'string' ? entry.type : undefined;
418
+ if (rejectedWhole || (!mask.eventDropped(event) && mask.entryDropped(event, groupIndex, hookIndex)) || type === undefined) {
419
+ out.push({ ...key, disposition: 'not_run', reason: 'malformed_entry' });
420
+ return;
421
+ }
422
+ const shellRuns = input.shellRuns(event, type);
423
+ if (!ENGINE_EVENTS.has(event)) {
424
+ out.push({ ...key, ...(shellRuns ? { disposition: 'shell', reason: 'shell_event' } : { disposition: 'not_run', reason: 'no_executor' }) });
425
+ return;
426
+ }
427
+ const ex = hookExecutorOf({ source: 'session', event, powershell: false, llmPosition: 0, engine: input.engine, shellRuns, promptAuthoredByUser: input.promptAuthoredByUser });
428
+ if (ex.kind === 'excluded')
429
+ return;
430
+ out.push({ ...key, disposition: ex.disposition, reason: ex.reason });
431
+ });
432
+ });
433
+ }
434
+ }
435
+ return { verdicts: out, unreadable };
303
436
  }
304
437
  const SHELL_INERT_COMMAND = /^[A-Za-z0-9_./:+-]+$/;
305
438
  function carriesArgs(entry) {
@@ -312,15 +445,16 @@ function carriesArgs(entry) {
312
445
  }
313
446
  return true;
314
447
  }
315
- export function filterSettingsHookGroups(source, event, groups, execFormCapable, shellRunsType, failLoudMcpTool, judge) {
448
+ export function filterSettingsHookGroups(source, event, groups, execFormCapable, shellRunsType, judge, mask) {
316
449
  const drops = [];
317
450
  const verdicts = [];
318
451
  const excluded = [];
319
452
  const out = [];
320
453
  let stripped = 0;
321
454
  const engineEvent = ENGINE_EVENTS.has(event);
322
- const keepMcpTool = failLoudMcpTool && engineEvent;
323
455
  groups.forEach((group, groupIndex) => {
456
+ if (mask !== undefined && mask.groupDropped(event, groupIndex))
457
+ return;
324
458
  if (!isRecord(group) || !Array.isArray(group.hooks)) {
325
459
  out.push(group);
326
460
  return;
@@ -328,12 +462,14 @@ export function filterSettingsHookGroups(source, event, groups, execFormCapable,
328
462
  const kept = [];
329
463
  let changed = false;
330
464
  group.hooks.forEach((entry, hookIndex) => {
465
+ if (mask !== undefined && mask.entryDropped(event, groupIndex, hookIndex)) {
466
+ changed = true;
467
+ return;
468
+ }
331
469
  const reason = !isRecord(entry)
332
470
  ? undefined
333
471
  : entry.type === 'mcp_tool'
334
- ? keepMcpTool
335
- ? undefined
336
- : 'mcp_tool_unsupported'
472
+ ? 'mcp_tool_unsupported'
337
473
  : entry.type === 'command' && carriesArgs(entry) && !execFormCapable
338
474
  ? 'exec_form_unsupported'
339
475
  : undefined;
@@ -342,7 +478,7 @@ export function filterSettingsHookGroups(source, event, groups, execFormCapable,
342
478
  changed = true;
343
479
  return;
344
480
  }
345
- if (judge !== undefined && engineEvent && isRecord(entry) && judgeableSettingsEntry(entry)) {
481
+ if (engineEvent && isRecord(entry) && judgeableSettingsEntry(entry)) {
346
482
  const ex = judge(event, group, entry);
347
483
  if (ex.kind === 'excluded') {
348
484
  excluded.push({ source, event, groupIndex, hookIndex, reason: ex.reason });
@@ -668,18 +804,15 @@ const REASON_TEXT = {
668
804
  engine_llm_limit: 'the engine may skip prompt or agent hooks after the first four on one event',
669
805
  engine_unconfirmed: 'it is sent to the engine, which is expected to run it, but this client cannot confirm that',
670
806
  engine_elsewhere: 'it is not confirmed that the engine was started by this client on this machine, so this client runs it itself',
807
+ hooks_module: 'hooks registered in code by a plugin module run neither in the engine nor in this client',
808
+ scope_unsupported: 'hooks registered for a skill, an agent or by the host application are not sent to the engine, and this client does not run this event',
809
+ source_incomplete: 'the plugin was reported without its id, name, root folder or data folder',
671
810
  };
672
811
  const DROP_TEXT = {
673
812
  exec_form_unsupported: 'exec-form hooks (with "args") are sent to the engine only once it reports support for them',
674
813
  mcp_tool_unsupported: 'MCP tool hooks are not supported by the engine',
675
814
  };
676
- const SOURCE_TEXT = {
677
- policySettings: 'Managed settings',
678
- userSettings: 'User settings',
679
- projectSettings: 'Project settings',
680
- localSettings: 'Local settings',
681
- flagSettings: 'Flag settings',
682
- };
815
+ const SOURCE_TEXT = HOOK_SETTINGS_SOURCE_TEXT;
683
816
  export function pluginHookReasonText(reason) {
684
817
  return REASON_TEXT[reason];
685
818
  }
@@ -789,5 +922,75 @@ export function hooksNotRunNotice(plan) {
789
922
  const events = row.events.map((e) => noticeLabel(e)).join(', ');
790
923
  lines.push(`${SOURCE_TEXT[row.source]}: ${events} ${row.count === 1 ? 'hook' : 'hooks'} will not run — ${pluginHookReasonText(row.reason)}.`);
791
924
  }
925
+ const moduleRows = plan.moduleVerdicts;
926
+ for (const raw of Array.isArray(moduleRows) ? moduleRows : []) {
927
+ if (!isRecord(raw) || ownField(raw, 'disposition') !== 'not_run')
928
+ continue;
929
+ const reason = ownField(raw, 'reason');
930
+ const name = ownField(raw, 'pluginName');
931
+ if (typeof reason !== 'string' || !REASON_SET.has(reason))
932
+ continue;
933
+ lines.push(`Plugin "${noticeLabel(typeof name === 'string' ? name : '') || '(unnamed)'}": hooks module will not run — ${pluginHookReasonText(reason)}.`);
934
+ }
935
+ const sessionRows = plan.sessionVerdicts;
936
+ const bySession = new Map();
937
+ for (const raw of Array.isArray(sessionRows) ? sessionRows : []) {
938
+ if (!isRecord(raw) || ownField(raw, 'disposition') !== 'not_run')
939
+ continue;
940
+ const origin = ownField(raw, 'origin');
941
+ const name = ownField(raw, 'name');
942
+ const reason = ownField(raw, 'reason');
943
+ const event = ownField(raw, 'event');
944
+ if (typeof origin !== 'string' || !SESSION_HOOK_ORIGINS.has(origin) || typeof reason !== 'string' || !REASON_SET.has(reason) || typeof event !== 'string')
945
+ continue;
946
+ const nm = typeof name === 'string' ? name : '';
947
+ const k = `${origin}\u0000${nm}\u0000${reason}`;
948
+ const row = bySession.get(k) ?? { origin: origin, name: nm, reason: reason, events: [], count: 0 };
949
+ if (!row.events.includes(event))
950
+ row.events.push(event);
951
+ row.count++;
952
+ bySession.set(k, row);
953
+ }
954
+ for (const row of bySession.values()) {
955
+ const events = row.events.map((e) => noticeLabel(e)).join(', ');
956
+ const who = row.origin === 'sdk_host' ? 'Host application hooks' : `${row.origin === 'skill' ? 'Skill' : 'Agent'} "${noticeLabel(row.name) || '(unnamed)'}"`;
957
+ lines.push(`${who}: ${events} ${row.count === 1 ? 'hook' : 'hooks'} will not run — ${pluginHookReasonText(row.reason)}.`);
958
+ }
959
+ const salvageRows = plan.settingsSalvage;
960
+ for (const row of Array.isArray(salvageRows) ? salvageRows : []) {
961
+ const notice = isRecord(row) ? ownField(row, 'notice') : undefined;
962
+ if (typeof notice === 'string' && notice.length > 0)
963
+ lines.push(notice);
964
+ }
792
965
  return lines;
793
966
  }
967
+ export function userPromptSubmitExecutorOf(plan) {
968
+ try {
969
+ const p = plan;
970
+ if (!isRecord(p))
971
+ return 'unknown';
972
+ const verdicts = ownField(p, 'verdicts');
973
+ if (!Array.isArray(verdicts))
974
+ return 'unknown';
975
+ const rows = [...verdicts];
976
+ for (const k of ['settingsVerdicts', 'sessionVerdicts']) {
977
+ const v = ownField(p, k);
978
+ if (v === undefined)
979
+ continue;
980
+ if (!Array.isArray(v))
981
+ return 'unknown';
982
+ rows.push(...v);
983
+ }
984
+ const ups = rows.filter((r) => isRecord(r) && ownField(r, 'event') === 'UserPromptSubmit').map((r) => ownField(r, 'disposition'));
985
+ if (ups.length === 0)
986
+ return 'none';
987
+ if (ups.some((d) => d === 'engine'))
988
+ return 'engine';
989
+ if (ups.every((d) => d === 'shell'))
990
+ return 'shell';
991
+ return 'unknown';
992
+ }
993
+ catch {
994
+ return 'unknown';
995
+ }
996
+ }
@@ -0,0 +1,44 @@
1
+ import type { AssistantTaskStatus, CancelAck } from '@sema-agent/sdk';
2
+ import { type SdkRunTerminalStatus } from './terminalStatuses.js';
3
+ export type PreemptParkedStatus = 'suspended' | 'needs_review';
4
+ export type PreemptOutcome = {
5
+ readonly kind: 'yield-requested';
6
+ readonly taskId: string;
7
+ } | {
8
+ readonly kind: 'not-eligible';
9
+ readonly taskId: string;
10
+ } | {
11
+ readonly kind: 'already-ended';
12
+ readonly taskId: string;
13
+ readonly status: SdkRunTerminalStatus;
14
+ } | {
15
+ readonly kind: 'already-parked';
16
+ readonly status?: PreemptParkedStatus;
17
+ } | {
18
+ readonly kind: 'approval-settled';
19
+ } | {
20
+ readonly kind: 'not-found';
21
+ } | {
22
+ readonly kind: 'unconfirmed';
23
+ readonly why: 'transport' | 'server-error' | 'unreadable-answer';
24
+ readonly status?: number;
25
+ } | {
26
+ readonly kind: 'refused';
27
+ readonly status: number;
28
+ readonly errorCode?: string;
29
+ } | {
30
+ readonly kind: 'no-run';
31
+ } | {
32
+ readonly kind: 'cancelled-instead';
33
+ readonly ack: CancelAck;
34
+ } | {
35
+ readonly kind: 'unavailable';
36
+ };
37
+ export type PreemptReading = Exclude<PreemptOutcome, {
38
+ readonly kind: 'no-run' | 'cancelled-instead' | 'unavailable';
39
+ }> | {
40
+ readonly kind: 'lane-absent';
41
+ };
42
+ export declare function preemptReadingOfAck(taskId: string, ack: AssistantTaskStatus): PreemptReading;
43
+ export declare function preemptReadingOfError(e: {} | null | undefined): PreemptReading;
44
+ export declare function preemptReceiptLine(outcome: PreemptOutcome): string;
@@ -0,0 +1,83 @@
1
+ import { isAssistantLaneAbsent } from './assistantInbox.js';
2
+ import { atMostOnceVerdictOf } from './atMostOnce.js';
3
+ import { readOwnDataValue } from './ownKey.js';
4
+ import { isSdkRunTerminal } from './terminalStatuses.js';
5
+ import { isDisplayableWireCode, readErrorString } from './wireFailureShape.js';
6
+ const ALREADY_SUSPENDED = 'conflict.already_suspended';
7
+ const APPROVAL_SETTLED = 'conflict.approval_settled';
8
+ function own(v, key) {
9
+ try {
10
+ return readOwnDataValue(v, key);
11
+ }
12
+ catch {
13
+ return undefined;
14
+ }
15
+ }
16
+ export function preemptReadingOfAck(taskId, ack) {
17
+ const body = ack;
18
+ const unreadable = { kind: 'unconfirmed', why: 'unreadable-answer' };
19
+ if (body === null || typeof body !== 'object')
20
+ return unreadable;
21
+ const echoed = own(body, 'taskId');
22
+ const status = own(body, 'status');
23
+ if (echoed !== taskId || typeof status !== 'string' || status === '')
24
+ return unreadable;
25
+ if (status === 'preempting')
26
+ return { kind: 'yield-requested', taskId };
27
+ if (status === 'running')
28
+ return { kind: 'not-eligible', taskId };
29
+ if (status === 'suspended' || status === 'needs_review')
30
+ return { kind: 'already-parked', status };
31
+ if (isSdkRunTerminal(status))
32
+ return { kind: 'already-ended', taskId, status };
33
+ return unreadable;
34
+ }
35
+ export function preemptReadingOfError(e) {
36
+ if (isAssistantLaneAbsent(e))
37
+ return { kind: 'lane-absent' };
38
+ const v = atMostOnceVerdictOf(e);
39
+ if (v.delivery === 'rejected' && v.status !== undefined) {
40
+ if (v.status === 409 && v.code === ALREADY_SUSPENDED) {
41
+ const word = e === null || e === undefined ? undefined : readErrorString(e, 'status');
42
+ return { kind: 'already-parked', ...(word === 'suspended' || word === 'needs_review' ? { status: word } : {}) };
43
+ }
44
+ if (v.status === 409 && v.code === APPROVAL_SETTLED)
45
+ return { kind: 'approval-settled' };
46
+ if (v.status === 404)
47
+ return { kind: 'not-found' };
48
+ return { kind: 'refused', status: v.status, ...(v.code !== undefined ? { errorCode: v.code } : {}) };
49
+ }
50
+ if (v.status !== undefined)
51
+ return { kind: 'unconfirmed', why: 'server-error', status: v.status };
52
+ return { kind: 'unconfirmed', why: 'transport' };
53
+ }
54
+ export function preemptReceiptLine(outcome) {
55
+ switch (outcome.kind) {
56
+ case 'yield-requested':
57
+ return 'Asked the run to yield — it will pause at its next clean turn boundary and can be resumed later.';
58
+ case 'not-eligible':
59
+ return 'This run cannot be asked to yield (it is a verification or cascade leg), so nothing changed and it keeps running — stop it instead if it has to end.';
60
+ case 'already-ended':
61
+ return isSdkRunTerminal(outcome.status)
62
+ ? `The run had already ended (${outcome.status}), so there was nothing to yield.`
63
+ : 'The run had already ended, so there was nothing to yield.';
64
+ case 'already-parked':
65
+ return 'The run is already paused waiting on a decision, so there is nothing to yield — answer what it is waiting on, or stop it.';
66
+ case 'approval-settled':
67
+ return 'The approval this run was waiting on was decided at the same moment, so the yield request did not apply — check the run and ask again if it is still active.';
68
+ case 'not-found':
69
+ return 'No such run is visible to you, so nothing was asked.';
70
+ case 'unconfirmed':
71
+ return 'The yield request was sent but no confirmation came back — it may or may not have been applied, so check the run before asking again.';
72
+ case 'refused':
73
+ return outcome.errorCode !== undefined && isDisplayableWireCode(outcome.errorCode)
74
+ ? `The engine refused the yield request (${outcome.status} ${outcome.errorCode}).`
75
+ : `The engine refused the yield request (${outcome.status}).`;
76
+ case 'no-run':
77
+ return 'There is no run in flight to yield.';
78
+ case 'cancelled-instead':
79
+ return 'Yielding is not available on this engine, so the run was stopped instead — that is a hard stop and the run cannot be resumed.';
80
+ case 'unavailable':
81
+ return 'Yielding is not available on this engine, so nothing was sent.';
82
+ }
83
+ }
@@ -0,0 +1,63 @@
1
+ import type { SDKAssistantMessageError } from '@sema-agent/agent-types';
2
+ import { type RetryStatus, type RetryStatusArmLike, type RetryStatusNotice } from './retryStatus.js';
3
+ export declare const PRINT_MODEL_STATUS_SUBTYPE = "_sema_model_status";
4
+ export declare const PRINT_LAST_MODEL_STATUS_KEY = "_sema_last_model_status";
5
+ export interface PrintModelStatusCtx {
6
+ readonly sessionId: string;
7
+ readonly nowMs: number;
8
+ readonly mintUuid: () => string;
9
+ readonly model?: string;
10
+ }
11
+ export interface PrintModelStatusPayload {
12
+ readonly kind: RetryStatus['kind'];
13
+ readonly terminal?: true;
14
+ readonly attempt?: number;
15
+ readonly max_retries?: number;
16
+ readonly retry_delay_ms?: number;
17
+ readonly error_status?: number;
18
+ readonly provider_condition?: string;
19
+ readonly err_class?: string;
20
+ readonly elapsed_ms?: number;
21
+ readonly timeout_ms?: number;
22
+ readonly model?: string;
23
+ readonly phase: RetryStatusNotice['phase'];
24
+ readonly recourse?: NonNullable<RetryStatusNotice['recourse']>;
25
+ readonly message: string;
26
+ }
27
+ export interface PrintApiRetryFrame {
28
+ readonly type: 'system';
29
+ readonly subtype: 'api_retry';
30
+ readonly attempt: number;
31
+ readonly max_retries: number;
32
+ readonly retry_delay_ms: number;
33
+ readonly error_status: number | null;
34
+ readonly error: SDKAssistantMessageError;
35
+ readonly _sema_provider_condition?: string;
36
+ readonly _sema_model?: string;
37
+ readonly _sema_message: string;
38
+ readonly uuid: string;
39
+ readonly session_id: string;
40
+ }
41
+ export interface PrintModelStatusSupersetFrame {
42
+ readonly type: 'system';
43
+ readonly subtype: typeof PRINT_MODEL_STATUS_SUBTYPE;
44
+ readonly _sema_model_status: PrintModelStatusPayload & {
45
+ readonly refresh?: true;
46
+ };
47
+ readonly uuid: string;
48
+ readonly session_id: string;
49
+ }
50
+ export type PrintModelStatusFrame = PrintApiRetryFrame | PrintModelStatusSupersetFrame;
51
+ export interface PrintModelStatusResultFields {
52
+ readonly _sema_last_model_status?: PrintModelStatusPayload;
53
+ }
54
+ export interface PrintLaneArmLike extends RetryStatusArmLike {
55
+ readonly type?: string;
56
+ readonly event?: RetryStatusArmLike;
57
+ }
58
+ export interface PrintModelStatusTracker {
59
+ take(msg: PrintLaneArmLike | null | undefined, ctx: PrintModelStatusCtx): PrintModelStatusFrame | null;
60
+ beginTurn(): void;
61
+ resultFields(nowMs: number): PrintModelStatusResultFields;
62
+ }
63
+ export declare function createPrintModelStatusTracker(): PrintModelStatusTracker;