@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
@@ -44,7 +44,7 @@ export function readEngineActiveBgTasksFor(sessionKey) {
44
44
  for (const view of viewsFor(sessionKey)) {
45
45
  try {
46
46
  const r = view.read();
47
- if (r.connected)
47
+ if (r.fresh)
48
48
  fresh = true;
49
49
  for (const row of r.rows)
50
50
  byId.set(row.id, row);
@@ -146,7 +146,6 @@ export function createFleetLedger(hooks = {}, opts = {}) {
146
146
  let droppedUnknownFrame = 0;
147
147
  let droppedForeignBgNotification = 0;
148
148
  let droppedStaleIngress = 0;
149
- let connected = false;
150
149
  let version = null;
151
150
  let scoped = null;
152
151
  let sessionScopedMeta;
@@ -154,12 +153,12 @@ export function createFleetLedger(hooks = {}, opts = {}) {
154
153
  let disposed = false;
155
154
  let epochSeq = 0;
156
155
  let liveStreamEpoch = 0;
156
+ let deliveredStreamEpoch = 0;
157
157
  let liveSnapshotEpoch = 0;
158
158
  let streamAnchor;
159
- let everIssuedStream = false;
160
159
  let contentAnchor;
161
160
  let contentAnchorSet = false;
162
- let ledgerWrites = 0;
161
+ const streamDelivering = () => !disposed && liveStreamEpoch !== 0 && deliveredStreamEpoch === liveStreamEpoch;
163
162
  const debug = (line) => {
164
163
  if (engineWireDebugEnabled())
165
164
  hostLog('debug', line);
@@ -242,7 +241,7 @@ export function createFleetLedger(hooks = {}, opts = {}) {
242
241
  continue;
243
242
  rows.push(toBgTask(r.row, true));
244
243
  }
245
- return { connected, rows };
244
+ return { fresh: streamDelivering(), rows };
246
245
  },
247
246
  sessionScoped: () => sessionScopedMeta,
248
247
  clearRetained: () => {
@@ -259,7 +258,6 @@ export function createFleetLedger(hooks = {}, opts = {}) {
259
258
  views.add(bgView);
260
259
  }
261
260
  function applyFrame(frame, ing) {
262
- ledgerWrites++;
263
261
  switch (frame.type) {
264
262
  case 'meta': {
265
263
  version = frame.version;
@@ -324,7 +322,7 @@ export function createFleetLedger(hooks = {}, opts = {}) {
324
322
  if (parentOwned)
325
323
  recordOwnEngineRun(childTid);
326
324
  if (parentOwned || sessionScopedMeta === true) {
327
- recordBgParentRun(childTid, parentTid, ing?.session, ing?.sessionKey);
325
+ recordBgParentRun(childTid, parentTid, ing.session, ing.sessionKey);
328
326
  }
329
327
  else {
330
328
  debug(`[fleet-frame] task row parent-map SKIPPED foreign/unowned(row=${row.id} parent=${parentTid})`);
@@ -409,7 +407,7 @@ export function createFleetLedger(hooks = {}, opts = {}) {
409
407
  return;
410
408
  }
411
409
  const serverFailClosed = bgNotifyFailClosedMeta && sessionScopedMeta === true;
412
- const anchor = ing !== null ? ing.session : engineSessionParamFor(sessionKey);
410
+ const anchor = ing.session;
413
411
  const ownByRoot = typeof n.rootSessionId === 'string' &&
414
412
  n.rootSessionId.length > 0 &&
415
413
  n.rootSessionId === anchor;
@@ -423,16 +421,14 @@ export function createFleetLedger(hooks = {}, opts = {}) {
423
421
  return;
424
422
  }
425
423
  const defaultSlot = sessionKey === DEFAULT_SESSION_KEY;
426
- const viaIngress = ing !== null;
427
- const ownRootTrusted = defaultSlot || viaIngress;
428
424
  const serverFailClosedTrusted = defaultSlot;
429
425
  const trustedSessionArm = serverFailClosed && serverFailClosedTrusted
430
426
  ? 'server_fail_closed'
431
- : ownByRoot && ownRootTrusted
427
+ : ownByRoot
432
428
  ? 'own_root'
433
429
  : undefined;
434
430
  const evidence = trustedSessionArm ??
435
- (serverFailClosed || ownByRoot
431
+ (serverFailClosed
436
432
  ? 'session_anchor_untrusted'
437
433
  : typeof n.parentTaskId === 'string' && n.parentTaskId.length > 0
438
434
  ? 'own_parent'
@@ -446,7 +442,7 @@ export function createFleetLedger(hooks = {}, opts = {}) {
446
442
  }
447
443
  if (isSdkFleetTaskTerminal(n.status)) {
448
444
  if (typeof n.parentTaskId === 'string' && n.parentTaskId) {
449
- recordBgParentRun(n.taskId, n.parentTaskId, ing?.session, ing?.sessionKey);
445
+ recordBgParentRun(n.taskId, n.parentTaskId, ing.session, ing.sessionKey);
450
446
  }
451
447
  if (typeof n.transcriptId === 'string' && n.transcriptId.length > 0) {
452
448
  recordEngineTranscriptId(n.taskId, n.transcriptId);
@@ -629,9 +625,13 @@ export function createFleetLedger(hooks = {}, opts = {}) {
629
625
  ` type=${String(frame.type)})`);
630
626
  return;
631
627
  }
632
- applyFrame(frame, { session, sessionKey });
628
+ if (kind === 'stream')
629
+ deliveredStreamEpoch = epoch;
630
+ else
631
+ closed = true;
633
632
  contentAnchor = session;
634
633
  contentAnchorSet = true;
634
+ applyFrame(frame, { session, sessionKey });
635
635
  },
636
636
  close() {
637
637
  closed = true;
@@ -649,8 +649,7 @@ export function createFleetLedger(hooks = {}, opts = {}) {
649
649
  bgNotifyFailClosedMeta = false;
650
650
  debug(`[fleet-frame] 连接级 meta 复位(${why})—— 新连接自报之前不许沿用上一条连接的让位/信任位`);
651
651
  };
652
- const hasLedgerContent = () => taskMap.size > 0 || wfMap.size > 0 || retained.size > 0;
653
- const shouldResetContentFor = (session) => contentAnchorSet ? contentAnchor !== session : hasLedgerContent();
652
+ const shouldResetContentFor = (session) => contentAnchorSet && contentAnchor !== session;
654
653
  const resetLedgerContentOnSessionChange = (from, to) => {
655
654
  taskMap.clear();
656
655
  wfMap.clear();
@@ -664,21 +663,14 @@ export function createFleetLedger(hooks = {}, opts = {}) {
664
663
  '(换会话不是重连:再渲上一会话的行就是跨会话残影)');
665
664
  };
666
665
  return {
667
- applyFrame(frame) {
668
- if (disposed)
669
- return;
670
- applyFrame(frame, null);
671
- },
672
666
  issueStream() {
673
667
  const session = engineSessionParamFor(sessionKey);
674
- if (shouldResetContentFor(session)) {
675
- resetLedgerContentOnSessionChange(contentAnchorSet ? contentAnchor : '<兼容入口,归属不可知>', session);
676
- }
668
+ if (shouldResetContentFor(session))
669
+ resetLedgerContentOnSessionChange(contentAnchor, session);
677
670
  resetConnectionMeta('新 stream ingress');
678
671
  const epoch = ++epochSeq;
679
672
  liveStreamEpoch = epoch;
680
673
  streamAnchor = session;
681
- everIssuedStream = true;
682
674
  liveSnapshotEpoch = 0;
683
675
  debug(`[fleet-frame] ingress issued(kind=stream key=${sessionKey} epoch=${epoch} session=${session ?? '-'})`);
684
676
  return {
@@ -688,13 +680,11 @@ export function createFleetLedger(hooks = {}, opts = {}) {
688
680
  },
689
681
  issueSnapshot(snapOpts) {
690
682
  const inStreamMode = liveStreamEpoch !== 0;
691
- const compatStreamLive = !inStreamMode && connected && !everIssuedStream;
692
- const duringLiveStream = inStreamMode || compatStreamLive;
683
+ const duringLiveStream = inStreamMode;
693
684
  const session = inStreamMode ? streamAnchor : engineSessionParamFor(sessionKey);
694
685
  if (!duringLiveStream) {
695
- if (shouldResetContentFor(session)) {
696
- resetLedgerContentOnSessionChange(contentAnchorSet ? contentAnchor : '<兼容入口,归属不可知>', session);
697
- }
686
+ if (shouldResetContentFor(session))
687
+ resetLedgerContentOnSessionChange(contentAnchor, session);
698
688
  resetConnectionMeta('快照连接:SDK 封装吞掉了它自己的 meta,不许沿用别条连接的信任位');
699
689
  }
700
690
  if (inStreamMode) {
@@ -704,9 +694,8 @@ export function createFleetLedger(hooks = {}, opts = {}) {
704
694
  const epoch = ++epochSeq;
705
695
  liveSnapshotEpoch = epoch;
706
696
  debug(`[fleet-frame] ingress issued(kind=snapshot key=${sessionKey} epoch=${epoch} session=${session ?? '-'})`);
707
- const writesAtIssue = ledgerWrites;
708
697
  const issuedDuringStream = duringLiveStream;
709
- const base = makeIngress('snapshot', epoch, session, () => liveSnapshotEpoch === epoch && !issuedDuringStream && ledgerWrites === writesAtIssue);
698
+ const base = makeIngress('snapshot', epoch, session, () => liveSnapshotEpoch === epoch && !issuedDuringStream);
710
699
  return {
711
700
  ...base,
712
701
  applySnapshot(snapshot) {
@@ -723,12 +712,8 @@ export function createFleetLedger(hooks = {}, opts = {}) {
723
712
  },
724
713
  };
725
714
  },
726
- setConnected(v) {
727
- connected = v;
728
- },
729
715
  project,
730
716
  status: () => ({
731
- connected,
732
717
  version,
733
718
  scoped,
734
719
  sessionScoped: sessionScopedMeta,
@@ -1,5 +1,5 @@
1
- import type { FleetTaskRow, FleetWorkflowRow } from '@sema-agent/sdk';
2
- export type FleetTaskStatus = 'queued' | 'running' | 'waiting' | 'stopping' | 'awaiting approval' | 'idle' | 'completed' | 'failed' | 'killed';
1
+ import type { FleetTaskRow, FleetWorkflowRow, FleetTaskStatus } from '@sema-agent/sdk';
2
+ export type { FleetTaskStatus };
3
3
  export interface FleetTaskView {
4
4
  id: string;
5
5
  name: string;
@@ -4,7 +4,10 @@ import { cycleSeqValue } from '../cycleOrder.js';
4
4
  import { frozenSet } from '../frozenSet.js';
5
5
  import { CORE_RESERVED_AGENT_NAMES } from '../generated/engineFactTables.js';
6
6
  export function coerceTaskStatus(s) {
7
- switch (s) {
7
+ if (s === 'parked')
8
+ return 'awaiting approval';
9
+ const word = s;
10
+ switch (word) {
8
11
  case 'queued':
9
12
  case 'running':
10
13
  case 'waiting':
@@ -14,11 +17,12 @@ export function coerceTaskStatus(s) {
14
17
  case 'completed':
15
18
  case 'failed':
16
19
  case 'killed':
17
- return s;
18
- case 'parked':
19
- return 'awaiting approval';
20
- default:
20
+ return word;
21
+ default: {
22
+ const unhandled = word;
23
+ void unhandled;
21
24
  return 'idle';
25
+ }
22
26
  }
23
27
  }
24
28
  export function coerceWorkflowStatus(s) {
@@ -49,11 +53,9 @@ function deriveAgentLabel(agentType, agentName, name, id) {
49
53
  const tail = rowIdTail(id).slice(-8);
50
54
  return tail ? `agent ${tail}` : 'agent';
51
55
  }
52
- const CONTROL_VERB_LEGACY_NAMES = ['Task', 'Fork'];
53
56
  const CONTROL_VERB_GOAL_NAMES = ['DeclareDone'];
54
57
  export const CONTROL_TOOL_VERBS = frozenSet([
55
58
  ...CORE_RESERVED_AGENT_NAMES,
56
- ...CONTROL_VERB_LEGACY_NAMES,
57
59
  ...CONTROL_VERB_GOAL_NAMES,
58
60
  ]);
59
61
  export function projectDescription(description) {
@@ -350,5 +352,5 @@ export const FLEET_TASK_ROW_KEYS_NOT_PROJECTED = {
350
352
  },
351
353
  };
352
354
  export const FLEET_WORKFLOW_ROW_KEYS_NOT_PROJECTED = {};
353
- const _fleetViewKeyPins = [true, true, true, true, true, true, true, true, true, true];
355
+ const _fleetViewKeyPins = [true, true, true, true, true, true, true, true];
354
356
  void _fleetViewKeyPins;
@@ -0,0 +1,8 @@
1
+ import type { AgentEvent } from '@sema-agent/sdk';
2
+ import type { EngineBoundRun } from './engineRowRef.js';
3
+ import type { ApprovalFrameContext } from './eventLeg.js';
4
+ export declare function registerApprovalFrameContext(frame: AgentEvent, ctx: ApprovalFrameContext): void;
5
+ export declare function approvalFrameContextOfFrame(frame: object | null | undefined): ApprovalFrameContext | undefined;
6
+ export declare function registerFrameBinding(frame: AgentEvent, binding: EngineBoundRun): void;
7
+ export declare function frameBindingOf(frame: AgentEvent): EngineBoundRun | undefined;
8
+ export declare function inheritFrameBinding<T extends AgentEvent>(from: AgentEvent, to: T): T;
@@ -0,0 +1,35 @@
1
+ const frameBindings = new WeakMap();
2
+ const approvalFrameContexts = new WeakMap();
3
+ export function registerApprovalFrameContext(frame, ctx) {
4
+ if (typeof frame !== 'object' || frame === null || approvalFrameContexts.has(frame))
5
+ return;
6
+ approvalFrameContexts.set(frame, ctx);
7
+ }
8
+ export function approvalFrameContextOfFrame(frame) {
9
+ return typeof frame === 'object' && frame !== null ? approvalFrameContexts.get(frame) : undefined;
10
+ }
11
+ export function registerFrameBinding(frame, binding) {
12
+ if (typeof frame !== 'object' || frame === null)
13
+ return;
14
+ if (binding.taskId === undefined && binding.sessionId === undefined)
15
+ return;
16
+ if (frameBindings.has(frame))
17
+ return;
18
+ frameBindings.set(frame, binding);
19
+ }
20
+ export function frameBindingOf(frame) {
21
+ if (typeof frame !== 'object' || frame === null)
22
+ return undefined;
23
+ return frameBindings.get(frame);
24
+ }
25
+ export function inheritFrameBinding(from, to) {
26
+ if (typeof from !== 'object' || from === null || typeof to !== 'object' || to === null || from === to)
27
+ return to;
28
+ const binding = frameBindings.get(from);
29
+ if (binding !== undefined && !frameBindings.has(to))
30
+ frameBindings.set(to, binding);
31
+ const ctx = approvalFrameContexts.get(from);
32
+ if (ctx !== undefined && !approvalFrameContexts.has(to))
33
+ approvalFrameContexts.set(to, ctx);
34
+ return to;
35
+ }
@@ -0,0 +1,2 @@
1
+ export declare function isGateStandingErrorCode(code: string | null | undefined, retriable?: boolean): boolean;
2
+ export declare function isCodeClassifiedGateFailure(code: string | null | undefined, retriable?: boolean): boolean;
@@ -0,0 +1,15 @@
1
+ import { DECIDE_WORKFLOW_PARK_FORKED, DECIDE_WORKFLOW_PARKS_UNREADABLE, PARKED_RESUME_STARTUP_FAILED, RESUME_POLICY_FOLD_CODE, RESUME_REOPEN_CODES, RESUME_RETRY_LATER_CODES, isRefusedParkCode } from './engineErrorCodes.js';
2
+ import { RESUME_REFUSAL_CODES } from './resumeRefusalCopy.js';
3
+ export function isGateStandingErrorCode(code, retriable) {
4
+ return (code === RESUME_POLICY_FOLD_CODE ||
5
+ code === 'corrupt' ||
6
+ (isRefusedParkCode(code) && retriable === true) ||
7
+ (typeof code === 'string' && RESUME_REOPEN_CODES.includes(code) && retriable === true) ||
8
+ code === DECIDE_WORKFLOW_PARKS_UNREADABLE ||
9
+ code === DECIDE_WORKFLOW_PARK_FORKED);
10
+ }
11
+ export function isCodeClassifiedGateFailure(code, retriable) {
12
+ return (isGateStandingErrorCode(code, retriable) ||
13
+ code === PARKED_RESUME_STARTUP_FAILED ||
14
+ (typeof code === 'string' && (RESUME_RETRY_LATER_CODES.includes(code) || RESUME_REFUSAL_CODES.includes(code))));
15
+ }
@@ -32,7 +32,7 @@ export interface GateModeReleaseView {
32
32
  mandate?: string;
33
33
  reason?: string;
34
34
  }
35
- export declare const GATE_MODE_RELEASE_REASON_WORDS: readonly ["rule_unreadable", "target_unresolved"];
35
+ export declare const GATE_MODE_RELEASE_REASON_WORDS: readonly ["target_unresolved"];
36
36
  export type GateModeReleaseReasonWord = (typeof CORE_MODE_RELEASE_REASONS)[number];
37
37
  export declare function isGateModeReleaseReasonWord(v: unknown): v is GateModeReleaseReasonWord;
38
38
  export declare function modeReleaseReasonSentence(reason: string | null | undefined): string | undefined;
@@ -58,10 +58,12 @@ export interface SettlementView {
58
58
  when?: number;
59
59
  note?: string;
60
60
  }
61
+ export type GateRecordSeat = 'settlement' | 'cause' | 'classifier';
61
62
  export interface GateOutcomeView {
62
63
  disposition: GateDispositionView;
63
64
  settlement?: SettlementView;
64
65
  origin?: string;
66
+ unreadable?: readonly GateRecordSeat[];
65
67
  }
66
68
  export declare function gateOutcomeOf(frame: unknown): GateOutcomeView | undefined;
67
69
  export declare function isGateParkedToolEnd(frame: unknown): boolean;
@@ -10,7 +10,6 @@ export function isGateModeReleaseReasonWord(v) {
10
10
  return typeof v === 'string' && CORE_MODE_RELEASE_REASONS.includes(v);
11
11
  }
12
12
  const MODE_RELEASE_SENTENCE_BY_REASON = Object.freeze({
13
- rule_unreadable: 'The permission mode let this call run without asking, even though it could not be checked against your saved permission rules.',
14
13
  target_unresolved: 'The permission mode let this call run without asking, even though it could not be determined where its write lands on disk, so whether it lands on a guarded location is unknown.',
15
14
  });
16
15
  const MODE_RELEASE_UNRECOGNISED_SENTENCE = 'The permission mode let this call run without asking, for a reason this client does not recognise.';
@@ -65,6 +64,9 @@ export function createReleaseDisclosureLedger() {
65
64
  });
66
65
  }
67
66
  export const SETTLEMENT_KIND_WORDS = CORE_SETTLEMENT_KINDS;
67
+ function isGateRecordSeat(x) {
68
+ return x === 'settlement' || x === 'cause' || x === 'classifier';
69
+ }
68
70
  function readWho(v) {
69
71
  if (typeof v !== 'object' || v === null || Array.isArray(v))
70
72
  return undefined;
@@ -151,6 +153,15 @@ function readClassifierRound(raw) {
151
153
  }
152
154
  return view;
153
155
  }
156
+ function carriedUnreadableSeats(v) {
157
+ const out = new Set();
158
+ if (!Array.isArray(v))
159
+ return out;
160
+ for (const x of v)
161
+ if (isGateRecordSeat(x))
162
+ out.add(x);
163
+ return out;
164
+ }
154
165
  function readGateRecord(frame) {
155
166
  if (typeof frame !== 'object' || frame === null || Array.isArray(frame))
156
167
  return undefined;
@@ -158,6 +169,7 @@ function readGateRecord(frame) {
158
169
  if (typeof g !== 'object' || g === null || Array.isArray(g))
159
170
  return undefined;
160
171
  const raw = g;
172
+ const carried = carriedUnreadableSeats(raw.unreadable);
161
173
  const d = raw.disposition;
162
174
  if (typeof d !== 'object' || d === null || Array.isArray(d))
163
175
  return undefined;
@@ -180,7 +192,7 @@ function readGateRecord(frame) {
180
192
  if (deniedBy === undefined)
181
193
  return undefined;
182
194
  const causeRaw = dr.cause;
183
- causePresent = causeRaw !== undefined;
195
+ causePresent = causeRaw !== undefined || carried.has('cause');
184
196
  const cause = str(causeRaw);
185
197
  const mode = str(dr.mode);
186
198
  const askClass = str(dr.askClass);
@@ -201,24 +213,47 @@ function readGateRecord(frame) {
201
213
  const settlementRaw = raw.settlement;
202
214
  const settlement = readSettlement(settlementRaw);
203
215
  const origin = readAskOrigin(raw);
216
+ const settlementPresent = settlementRaw !== undefined || carried.has('settlement');
217
+ const classifierPresent = classifierRaw !== undefined || carried.has('classifier');
218
+ const missing = {
219
+ settlement: settlementPresent && settlement === undefined,
220
+ cause: causePresent && disposition.kind === 'denied' && disposition.cause === undefined,
221
+ classifier: classifierPresent && disposition.classifier === undefined,
222
+ };
223
+ const unreadable = Object.keys(missing).filter((seat) => missing[seat]);
204
224
  return {
205
225
  view: {
206
226
  disposition,
207
227
  ...(settlement !== undefined ? { settlement } : {}),
208
228
  ...(origin !== undefined ? { origin } : {}),
229
+ ...(unreadable.length > 0 ? { unreadable: Object.freeze(unreadable) } : {}),
209
230
  },
210
- settlementPresent: settlementRaw !== undefined,
231
+ settlementPresent,
211
232
  causePresent,
212
- classifierPresent: classifierRaw !== undefined,
233
+ classifierPresent,
213
234
  };
214
235
  }
215
236
  export function gateOutcomeOf(frame) {
216
237
  return readGateRecord(frame)?.view;
217
238
  }
218
239
  export function isGateParkedToolEnd(frame) {
219
- if (typeof frame !== 'object' || frame === null || Array.isArray(frame))
240
+ if (typeof frame !== 'object' || frame === null)
241
+ return false;
242
+ try {
243
+ if (Array.isArray(frame))
244
+ return false;
245
+ if (readOwnDataValue(frame, 'errorCode') === GATE_PARKED_ERROR_CODE)
246
+ return true;
247
+ if (readOwnDataValue(frame, 'role') !== 'toolResult')
248
+ return false;
249
+ const details = readOwnDataValue(frame, 'details');
250
+ if (typeof details !== 'object' || details === null || Array.isArray(details))
251
+ return false;
252
+ return readOwnDataValue(details, 'code') === GATE_PARKED_ERROR_CODE;
253
+ }
254
+ catch {
220
255
  return false;
221
- return frame.errorCode === GATE_PARKED_ERROR_CODE;
256
+ }
222
257
  }
223
258
  export function gateModeRelease(g) {
224
259
  return g?.disposition.kind === 'allowed' ? g.disposition.released : undefined;
@@ -257,8 +292,6 @@ export function ccToolDenialKindForToolEnd(frame) {
257
292
  const stamped = frame._sema_denial_kind;
258
293
  if (isCcToolDenialKind(stamped))
259
294
  return stamped;
260
- if (frame._sema_denial_unclassified === true)
261
- return undefined;
262
295
  const record = readGateRecord(frame);
263
296
  const outcome = record?.view;
264
297
  const kind = outcome?.settlement?.kind;
@@ -1,4 +1,5 @@
1
1
  import { CORE_DENIED_BY_VALUES, CORE_PERSISTED_RULE_MANDATES } from './generated/engineFactTables.js';
2
+ import type { UiLanguage } from './env/uiLanguage.js';
2
3
  export declare const CC_TOOL_DENIAL_KINDS: readonly ["user-rejected", "permission-rule", "automode-blocked", "automode-unavailable", "automode-parsing-error", "interrupted", "cancelled"];
3
4
  export type CcToolDenialKind = (typeof CC_TOOL_DENIAL_KINDS)[number];
4
5
  export declare function isCcToolDenialKind(v: unknown): v is CcToolDenialKind;
@@ -7,10 +8,15 @@ export declare function ccToolDenialKindForSettledBy(settledBy: unknown): CcTool
7
8
  export type GateDeniedByWord = (typeof CORE_DENIED_BY_VALUES)[number];
8
9
  export declare const GATE_DENIED_BY_WORDS: readonly GateDeniedByWord[];
9
10
  export declare function isGateDeniedByWord(v: unknown): v is GateDeniedByWord;
10
- export declare function gateDeniedByDetail(deniedBy: unknown): string;
11
- export declare function askOriginDetail(origin: unknown): string;
12
- export declare function mandatedApprovalDetail(): string;
11
+ export declare function gateDeniedByDetail(deniedBy: unknown, lang?: UiLanguage): string;
12
+ export declare function askOriginDetail(origin: unknown, lang?: UiLanguage): string;
13
+ export declare function askOriginNoteOf(origin: string | undefined, lang?: UiLanguage): string | undefined;
14
+ export declare function ruleOffersAbsenceDetail(reason: string | undefined, opts?: {
15
+ readonly deploymentListSessionRow?: boolean;
16
+ }, lang?: UiLanguage): string | undefined;
17
+ export declare function ruleOfferUncoveredDetail(reason: string | undefined, lang?: UiLanguage): string;
18
+ export declare function mandatedApprovalDetail(lang?: UiLanguage): string;
13
19
  export declare const APPROVAL_MANDATE_WORDS: readonly (typeof CORE_PERSISTED_RULE_MANDATES)[number][];
14
20
  export type ApprovalMandateWord = (typeof APPROVAL_MANDATE_WORDS)[number];
15
21
  export declare function isApprovalMandateWord(v: unknown): v is ApprovalMandateWord;
16
- export declare function approvalMandateDetail(word: ApprovalMandateWord): string;
22
+ export declare function approvalMandateDetail(word: ApprovalMandateWord, lang?: UiLanguage): string;
@@ -1,4 +1,6 @@
1
1
  import { CORE_DENIED_BY_VALUES, CORE_PERSISTED_RULE_MANDATES } from './generated/engineFactTables.js';
2
+ import { guardedRead, readOwnDataValue } from './ownKey.js';
3
+ import { msg, renderMessage } from './i18n/translate.js';
2
4
  export const CC_TOOL_DENIAL_KINDS = Object.freeze([
3
5
  'user-rejected',
4
6
  'permission-rule',
@@ -24,52 +26,110 @@ export function ccToolDenialKindForSettledBy(settledBy) {
24
26
  export const GATE_DENIED_BY_WORDS = Object.freeze([...CORE_DENIED_BY_VALUES]);
25
27
  const _deniedByWordsPin = true;
26
28
  void _deniedByWordsPin;
27
- const DENIED_BY_SENTENCES = Object.freeze({
28
- policy: "denied by this deployment's permission policy",
29
- hook: 'denied by a PreToolUse hook',
30
- org: 'denied by an organization rule',
31
- persisted_rule: 'denied by a persisted rule',
32
- classifier: 'denied by the auto-mode classifier',
33
- compliance: 'denied by a compliance lock',
34
- write_protection: 'denied because the write landed on a write-protected path',
35
- ask_resolution: 'denied when the approval was resolved',
36
- read_boundary: 'denied by the read boundary',
37
- mode: "denied by this session's permission mode",
29
+ const DENIED_BY_KEYS = Object.freeze({
30
+ policy: 'approval.deniedBy.policy',
31
+ hook: 'approval.deniedBy.hook',
32
+ org: 'approval.deniedBy.org',
33
+ persisted_rule: 'approval.deniedBy.persistedRule',
34
+ classifier: 'approval.deniedBy.classifier',
35
+ compliance: 'approval.deniedBy.compliance',
36
+ write_protection: 'approval.deniedBy.writeProtection',
37
+ ask_resolution: 'approval.deniedBy.askResolution',
38
+ read_boundary: 'approval.deniedBy.readBoundary',
39
+ mode: 'approval.deniedBy.mode',
38
40
  });
39
41
  export function isGateDeniedByWord(v) {
40
42
  return typeof v === 'string' && GATE_DENIED_BY_WORDS.includes(v);
41
43
  }
42
- export function gateDeniedByDetail(deniedBy) {
43
- if (typeof deniedBy === 'string' && Object.hasOwn(DENIED_BY_SENTENCES, deniedBy)) {
44
- return DENIED_BY_SENTENCES[deniedBy];
44
+ export function gateDeniedByDetail(deniedBy, lang) {
45
+ if (typeof deniedBy === 'string' && Object.hasOwn(DENIED_BY_KEYS, deniedBy)) {
46
+ return renderMessage(msg(DENIED_BY_KEYS[deniedBy]), lang);
45
47
  }
46
- const word = typeof deniedBy === 'string' && deniedBy.length > 0 ? deniedBy : '(none)';
47
- return `denied by a layer this build does not know (${word}) — this build does not know this layer name, so it cannot say which layer refused this call or why`;
48
+ const word = typeof deniedBy === 'string' && deniedBy.length > 0 ? deniedBy : msg('approval.card.noWord');
49
+ return renderMessage(msg('approval.deniedBy.unknown', { word }), lang);
48
50
  }
49
- const ASK_ORIGIN_SENTENCES = Object.freeze({
50
- content_question: 'the tool itself asked you a question',
51
- ancestor_marked: 'an ancestor marked this call (an inherited approver-unavailable float, or a durable mandate; this client cannot tell which from the origin alone): it must reach the park with no synchronous decision-maker in between',
52
- org_unavailable: 'the organization policy was unavailable, so this call asks',
53
- org_rule: 'an organization rule asks about this call',
54
- rule_store_unavailable: 'this call could not be checked against your standing deny/ask rules, so it asks',
55
- hook: 'a PreToolUse hook asked about this call',
56
- ask_rule: 'a persisted ask rule matches this call',
57
- denial_limit_fallback: 'the auto-mode classifier hit its denial limit and handed this call back to you',
58
- shell_gate_tighten: 'the coarse shell check rates this command above the tier it lets through, so it asks',
59
- safety_tighten: 'the gate tightened on this call’s own facts (network egress, irreversibility, or a protected write; this client cannot tell which from the origin alone)',
60
- policy: 'this deployment’s permission policy asks about this call',
51
+ const ASK_ORIGIN_KEYS = Object.freeze({
52
+ content_question: 'approval.origin.contentQuestion',
53
+ plan_review: 'approval.origin.planReview',
54
+ ancestor_marked: 'approval.origin.ancestorMarked',
55
+ org_unavailable: 'approval.origin.orgUnavailable',
56
+ org_rule: 'approval.origin.orgRule',
57
+ rule_store_unavailable: 'approval.origin.ruleStoreUnavailable',
58
+ hook: 'approval.origin.hook',
59
+ ask_rule: 'approval.origin.askRule',
60
+ denial_limit_fallback: 'approval.origin.denialLimitFallback',
61
+ shell_gate_tighten: 'approval.origin.shellGateTighten',
62
+ safety_tighten: 'approval.origin.safetyTighten',
63
+ policy: 'approval.origin.policy',
61
64
  });
62
- export function askOriginDetail(origin) {
63
- const known = typeof origin === 'string' && Object.hasOwn(ASK_ORIGIN_SENTENCES, origin)
64
- ? ASK_ORIGIN_SENTENCES[origin]
65
+ export function askOriginDetail(origin, lang) {
66
+ const known = typeof origin === 'string' && Object.hasOwn(ASK_ORIGIN_KEYS, origin)
67
+ ? ASK_ORIGIN_KEYS[origin]
65
68
  : undefined;
66
69
  if (known !== undefined)
67
- return known;
68
- const word = typeof origin === 'string' && origin.length > 0 ? origin : '(none)';
69
- return `this call asks; its origin ${word} is a word newer than this client, so answer it as usual`;
70
+ return renderMessage(msg(known), lang);
71
+ const word = typeof origin === 'string' && origin.length > 0 ? origin : msg('approval.card.noWord');
72
+ return renderMessage(unknownAskOriginSentence(word), lang);
70
73
  }
71
- export function mandatedApprovalDetail() {
72
- return 'no saved allow rule and no remembered answer can retire this question; each call is settled on its own — by you here or by an automatic check the deployment runs — and an answer covers only that call';
74
+ function unknownAskOriginSentence(word) {
75
+ return word === undefined ? msg('approval.origin.unknownNoWord') : msg('approval.origin.unknownWithWord', { word });
76
+ }
77
+ const ASK_ORIGIN_QUIET = Object.freeze({
78
+ content_question: true,
79
+ plan_review: true,
80
+ ancestor_marked: false,
81
+ org_unavailable: false,
82
+ org_rule: false,
83
+ rule_store_unavailable: false,
84
+ hook: false,
85
+ ask_rule: true,
86
+ denial_limit_fallback: false,
87
+ shell_gate_tighten: false,
88
+ safety_tighten: false,
89
+ policy: true,
90
+ });
91
+ export function askOriginNoteOf(origin, lang) {
92
+ if (typeof origin !== 'string' || origin === '')
93
+ return undefined;
94
+ if (Object.hasOwn(ASK_ORIGIN_QUIET, origin)) {
95
+ return ASK_ORIGIN_QUIET[origin] === true ? undefined : askOriginDetail(origin, lang);
96
+ }
97
+ return renderMessage(unknownAskOriginSentence(undefined), lang);
98
+ }
99
+ const RULE_OFFERS_ABSENCE_KEYS = Object.freeze({
100
+ mandated: { line: null },
101
+ allow_outranked: { line: 'approval.ruleOffer.absence.allowOutranked' },
102
+ ask_rule_matched: {
103
+ line: 'approval.ruleOffer.absence.askRuleMatched',
104
+ deploymentList: 'approval.ruleOffer.absence.askRuleMatchedDeploymentList',
105
+ },
106
+ lane_cannot_speak: { line: 'approval.ruleOffer.absence.laneCannotSpeak' },
107
+ });
108
+ export function ruleOffersAbsenceDetail(reason, opts, lang) {
109
+ if (typeof reason !== 'string' || reason === '')
110
+ return undefined;
111
+ if (Object.hasOwn(RULE_OFFERS_ABSENCE_KEYS, reason)) {
112
+ const entry = RULE_OFFERS_ABSENCE_KEYS[reason];
113
+ if (entry.line === null)
114
+ return undefined;
115
+ const onList = guardedRead(() => readOwnDataValue(opts, 'deploymentListSessionRow')) === true;
116
+ return renderMessage(msg(onList && entry.deploymentList !== undefined ? entry.deploymentList : entry.line), lang);
117
+ }
118
+ return renderMessage(msg('approval.ruleOffer.absence.unknown'), lang);
119
+ }
120
+ const RULE_OFFER_UNCOVERED_KEYS = Object.freeze({
121
+ redirection: 'approval.ruleOffer.uncovered.redirection',
122
+ no_rule_form: 'approval.ruleOffer.uncovered.noRuleForm',
123
+ cap_overflow: 'approval.ruleOffer.uncovered.capOverflow',
124
+ });
125
+ export function ruleOfferUncoveredDetail(reason, lang) {
126
+ if (typeof reason === 'string' && Object.hasOwn(RULE_OFFER_UNCOVERED_KEYS, reason)) {
127
+ return renderMessage(msg(RULE_OFFER_UNCOVERED_KEYS[reason]), lang);
128
+ }
129
+ return renderMessage(msg('approval.ruleOffer.uncovered.unknown'), lang);
130
+ }
131
+ export function mandatedApprovalDetail(lang) {
132
+ return renderMessage(msg('approval.mandate.generic'), lang);
73
133
  }
74
134
  export const APPROVAL_MANDATE_WORDS = Object.freeze([...CORE_PERSISTED_RULE_MANDATES]);
75
135
  const _mandateWordsPin = true;
@@ -77,18 +137,18 @@ void _mandateWordsPin;
77
137
  export function isApprovalMandateWord(v) {
78
138
  return APPROVAL_MANDATE_SET.has(v);
79
139
  }
80
- const APPROVAL_MANDATE_SENTENCES = Object.freeze({
81
- operator_always: 'this deployment requires a separate confirmation for each shell command, and this call is one of them',
82
- tool_marks: 'this tool declares that it reaches outside this machine or makes changes that cannot be undone',
83
- probe_mandate: 'the check run on this call marked it as needing its own confirmation (the built-in shell check does so for a read outside the directories allowed for this session)',
84
- probe_unanswered: 'the check run on this call did not answer (it timed out or failed; this client cannot tell which), so whether the call stays inside the directories allowed for this session is unknown',
85
- write_protection: "this change lands on a protected location (the agent's own configuration), which is confirmed one change at a time",
86
- target_unresolved: 'where this change lands on disk could not be determined (a link on the way could not be examined, or the target could not be resolved), so whether it lands on a guarded location is unknown',
140
+ const APPROVAL_MANDATE_KEYS = Object.freeze({
141
+ operator_always: 'approval.mandate.word.operatorAlways',
142
+ tool_marks: 'approval.mandate.word.toolMarks',
143
+ probe_mandate: 'approval.mandate.word.probeMandate',
144
+ probe_unanswered: 'approval.mandate.word.probeUnanswered',
145
+ write_protection: 'approval.mandate.word.writeProtection',
146
+ target_unresolved: 'approval.mandate.word.targetUnresolved',
87
147
  });
88
148
  const APPROVAL_MANDATE_SET = new Set(APPROVAL_MANDATE_WORDS);
89
- export function approvalMandateDetail(word) {
90
- if (typeof word === 'string' && Object.hasOwn(APPROVAL_MANDATE_SENTENCES, word)) {
91
- return APPROVAL_MANDATE_SENTENCES[word];
149
+ export function approvalMandateDetail(word, lang) {
150
+ if (typeof word === 'string' && Object.hasOwn(APPROVAL_MANDATE_KEYS, word)) {
151
+ return renderMessage(msg(APPROVAL_MANDATE_KEYS[word]), lang);
92
152
  }
93
- return 'the reason reported for this confirmation is not one this client recognises, so it shows no reason';
153
+ return renderMessage(msg('approval.mandate.unknownWord'), lang);
94
154
  }