@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,7 +1,10 @@
1
1
  import { PERMISSION_MODE_WORDS, REASONING_EFFORT_WORDS } from "./taskRequestWords.js";
2
2
  import { liveDefaultModelCopy, liveModelRowCopy } from "./model/liveCatalogShape.js";
3
3
  import { REWIND_MODES } from "./rewindWireCaps.js";
4
+ import { SETTINGS_MODEL_API_WORDS } from "./generated/settingsSchemaTables.js";
5
+ import { PROBE_VERDICTS } from "./modelCapabilityProbe.js";
4
6
  import { guardedRead, ownDataField, ownDataRefusalKeyOf, ownSendableField, readOwnDataValue } from "./ownKey.js";
7
+ import { MCP_LIVENESS_STATES } from "./mcpLiveness.js";
5
8
  const bad = (reason, field) => field === undefined ? { reason } : { reason, field };
6
9
  const nested = (prefix, verdict) => {
7
10
  const path = verdict.field === undefined
@@ -12,12 +15,11 @@ const nested = (prefix, verdict) => {
12
15
  const reason = verdict.reason.startsWith(`${prefix}:`) ? verdict.reason : `${prefix}: ${verdict.reason}`;
13
16
  return bad(reason, path);
14
17
  };
15
- const isObject = (v) => typeof v === "object" && v !== null;
16
18
  const isPlainRecord = (v) => {
17
- if (!isObject(v) || Array.isArray(v))
19
+ if (typeof v !== "object" || v === null || Array.isArray(v))
18
20
  return false;
19
21
  const proto = Object.getPrototypeOf(v);
20
- return proto === Object.prototype || proto === null;
22
+ return proto === null || (typeof proto === "object" && Object.getPrototypeOf(proto) === null);
21
23
  };
22
24
  const isAbsent = (v) => typeof v === "undefined";
23
25
  const optionalString = (v) => isAbsent(v) || typeof v === "string";
@@ -90,6 +92,124 @@ const seatCheckAt = (fn) => (v, field) => {
90
92
  return key !== undefined ? bad(NOT_PLAIN_DATA, `${field}.${key}`) : bad("payload could not be read", field);
91
93
  }
92
94
  };
95
+ const pathAt = (path, key) => (path === "" ? key : `${path}.${key}`);
96
+ const reqF = (rule) => ({ opt: false, rule });
97
+ const optF = (rule) => ({ opt: true, rule });
98
+ const ruleOf = (label, pred) => ({
99
+ label,
100
+ test: (v, path) => (pred(v) ? true : bad(`bad value (${label})`, path === "" ? undefined : path)),
101
+ });
102
+ function shapeVerdict(spec, v, path, disc) {
103
+ if (!isPlainRecord(v))
104
+ return bad("not object", path === "" ? undefined : path);
105
+ for (const k of sendableKeysOf(v)) {
106
+ if (k !== disc && !Object.hasOwn(spec, k))
107
+ return bad("unknown key", pathAt(path, k));
108
+ }
109
+ for (const k of Object.keys(spec)) {
110
+ const s = spec[k];
111
+ const val = own(v, k);
112
+ if (isAbsent(val)) {
113
+ if (!s.opt)
114
+ return bad("missing key", pathAt(path, k));
115
+ continue;
116
+ }
117
+ const verdict = s.rule.test(val, pathAt(path, k));
118
+ if (verdict !== true)
119
+ return verdict;
120
+ }
121
+ return true;
122
+ }
123
+ const shapeRule = (label, spec) => ({ label, test: (v, path) => shapeVerdict(spec, v, path) });
124
+ const armsRule = (label, disc, arms) => ({
125
+ label,
126
+ test: (v, path) => {
127
+ if (!isPlainRecord(v))
128
+ return bad("not object", path === "" ? undefined : path);
129
+ const d = own(v, disc);
130
+ if (typeof d !== "string" || !Object.hasOwn(arms, d))
131
+ return bad("unknown arm", pathAt(path, disc));
132
+ return shapeVerdict(arms[d], v, path, disc);
133
+ },
134
+ });
135
+ const isArraySlotKey = (k, n) => k === "length" || (/^(0|[1-9][0-9]*)$/.test(k) && Number(k) < n);
136
+ const arrayRule = (item, nonEmpty = false) => ({
137
+ label: `${item.label}[]`,
138
+ test: (v, path) => {
139
+ if (!Array.isArray(v))
140
+ return bad(`bad value (${item.label}[])`, path === "" ? undefined : path);
141
+ const n = ownDataField(v, "length");
142
+ for (const k of Reflect.ownKeys(v)) {
143
+ if (typeof k === "string" && !isArraySlotKey(k, typeof n === "number" ? n : 0))
144
+ return bad("unknown key", pathAt(path, k));
145
+ }
146
+ const rows = ownItems(v);
147
+ if (nonEmpty && rows.length === 0)
148
+ return bad(`bad value (${item.label}[])`, path === "" ? undefined : path);
149
+ for (let i = 0; i < rows.length; i += 1) {
150
+ const verdict = item.test(rows[i], `${path}[${i}]`);
151
+ if (verdict !== true)
152
+ return verdict;
153
+ }
154
+ return true;
155
+ },
156
+ });
157
+ const oneOfRule = (label, words) => ruleOf(label, (v) => typeof v === "string" && words.includes(v));
158
+ const R_STR = ruleOf("string", (v) => typeof v === "string");
159
+ const R_NONEMPTY = ruleOf("non-empty string", (v) => typeof v === "string" && v.length > 0);
160
+ const R_BOOL = ruleOf("boolean", (v) => typeof v === "boolean");
161
+ const R_TRUE = ruleOf("true", (v) => v === true);
162
+ const R_NUM = ruleOf("finite number", (v) => typeof v === "number" && Number.isFinite(v));
163
+ const R_INT0 = ruleOf("non-negative integer", (v) => typeof v === "number" && Number.isSafeInteger(v) && v >= 0);
164
+ const R_INT1 = ruleOf("positive integer", (v) => typeof v === "number" && Number.isSafeInteger(v) && v > 0);
165
+ const keyWords = (k) => k
166
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
167
+ .toLowerCase()
168
+ .split(/[^a-z0-9]+/)
169
+ .filter((w) => w.length > 0);
170
+ const SECRET_KEY_WORDS = new Set(["token", "secret", "password", "passwd", "authorization", "bearer", "sealed"]);
171
+ const SECRET_KEY_PAIRS = new Set(["api key", "device code", "access key", "private key"]);
172
+ const isSecretKeyName = (k) => {
173
+ const words = keyWords(k);
174
+ for (let i = 0; i < words.length; i += 1) {
175
+ if (SECRET_KEY_WORDS.has(words[i]))
176
+ return true;
177
+ if (i + 1 < words.length && SECRET_KEY_PAIRS.has(`${words[i]} ${words[i + 1]}`))
178
+ return true;
179
+ }
180
+ return false;
181
+ };
182
+ const firstSecretKeyPath = (root, allow) => {
183
+ const seen = new Set();
184
+ const stack = [[root, ""]];
185
+ while (stack.length > 0) {
186
+ const [v, path] = stack.pop();
187
+ if (typeof v !== "object" || v === null || seen.has(v))
188
+ continue;
189
+ seen.add(v);
190
+ const isArr = Array.isArray(v);
191
+ for (const k of Reflect.ownKeys(v)) {
192
+ if (typeof k !== "string" || (isArr && k === "length"))
193
+ continue;
194
+ const d = Reflect.getOwnPropertyDescriptor(v, k);
195
+ if (d === undefined || !Object.hasOwn(d, "value"))
196
+ continue;
197
+ const at = isArr && /^[0-9]+$/.test(k) ? `${path}[${k}]` : pathAt(path, k);
198
+ if (isSecretKeyName(k) && !allow.has(at))
199
+ return at;
200
+ stack.push([d.value, at]);
201
+ }
202
+ }
203
+ return undefined;
204
+ };
205
+ const NO_SECRET_ALLOW = new Set();
206
+ const seatShapeCheck = (rule, allow = NO_SECRET_ALLOW) => seatCheck((v) => {
207
+ const verdict = rule.test(v, "");
208
+ if (verdict !== true)
209
+ return verdict;
210
+ const secret = firstSecretKeyPath(v, allow);
211
+ return secret === undefined ? true : bad("secret key", secret);
212
+ });
93
213
  export const TOOL_PERMISSION_REQUEST_ID_DOMAINS = Object.freeze([
94
214
  "live:",
95
215
  "durable:",
@@ -128,6 +248,7 @@ const SEAT_EVENT_TYPE_TUPLE = [
128
248
  "chrome_event",
129
249
  "error",
130
250
  "tool_permission_resolved",
251
+ "subagent_content",
131
252
  ];
132
253
  export const SEAT_EVENT_TYPES = Object.freeze(SEAT_EVENT_TYPE_TUPLE);
133
254
  const CHROME_EVENT_KIND_TUPLE = [
@@ -137,6 +258,14 @@ const CHROME_EVENT_KIND_TUPLE = [
137
258
  "subagent_lifecycle",
138
259
  "text_segment_end",
139
260
  "thinking_segment_end",
261
+ "retry_status",
262
+ "context_usage",
263
+ "last_turn_usage",
264
+ "bgshell_register",
265
+ "bgshell_settle",
266
+ "memory_saved",
267
+ "result_replayed",
268
+ "tool_parked",
140
269
  ];
141
270
  export const CHROME_EVENT_KINDS = Object.freeze(CHROME_EVENT_KIND_TUPLE);
142
271
  const LANE_PROOF_LANE_TUPLE = ["main", "subagent", "workflow"];
@@ -151,7 +280,54 @@ export const HITL_RESOLUTION_OUTCOMES = [
151
280
  "decline",
152
281
  "cancel",
153
282
  ];
154
- export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind", "recents", "patchSession"]);
283
+ export const SEAT_STREAM_DELTA_TYPE_OF_CHANNEL = Object.freeze({ text: "text_delta", thinking: "thinking_delta" });
284
+ export function seatStreamDeltaMessage(event, ids) {
285
+ try {
286
+ const channel = ownDataField(event, "channel");
287
+ const text = ownDataField(event, "text");
288
+ const uuid = ownDataField(ids, "uuid");
289
+ const sessionId = ownDataField(ids, "sessionId");
290
+ if (typeof channel !== "string" || !Object.hasOwn(SEAT_STREAM_DELTA_TYPE_OF_CHANNEL, channel))
291
+ return undefined;
292
+ if (typeof text !== "string")
293
+ return undefined;
294
+ if (typeof uuid !== "string" || uuid.length === 0 || typeof sessionId !== "string" || sessionId.length === 0)
295
+ return undefined;
296
+ return {
297
+ type: "stream_event",
298
+ uuid,
299
+ session_id: sessionId,
300
+ event: { type: SEAT_STREAM_DELTA_TYPE_OF_CHANNEL[channel], delta: text },
301
+ parent_tool_use_id: null,
302
+ };
303
+ }
304
+ catch {
305
+ return undefined;
306
+ }
307
+ }
308
+ export function readSeatStreamDelta(message) {
309
+ try {
310
+ if (typeof message !== "object" || message === null)
311
+ return Object.freeze({ kind: "not_stream_event" });
312
+ if (ownDataField(message, "type") !== "stream_event")
313
+ return Object.freeze({ kind: "not_stream_event" });
314
+ const inner = ownDataField(message, "event");
315
+ if (typeof inner !== "object" || inner === null)
316
+ return Object.freeze({ kind: "malformed" });
317
+ const innerType = ownDataField(inner, "type");
318
+ if (typeof innerType !== "string")
319
+ return Object.freeze({ kind: "malformed" });
320
+ const channel = Object.keys(SEAT_STREAM_DELTA_TYPE_OF_CHANNEL).find((c) => SEAT_STREAM_DELTA_TYPE_OF_CHANNEL[c] === innerType);
321
+ if (channel === undefined)
322
+ return Object.freeze({ kind: "unknown_event" });
323
+ const delta = ownDataField(inner, "delta");
324
+ return typeof delta === "string" ? Object.freeze({ kind: "delta", channel, delta }) : Object.freeze({ kind: "malformed" });
325
+ }
326
+ catch {
327
+ return Object.freeze({ kind: "malformed" });
328
+ }
329
+ }
330
+ export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard"]);
155
331
  const notReported = () => Object.freeze({ kind: "not_reported" });
156
332
  const malformedReading = () => Object.freeze({ kind: "malformed" });
157
333
  const reported = (available) => Object.freeze({ kind: "reported", available });
@@ -159,10 +335,7 @@ export function seatCapability(state, name) {
159
335
  if (state === undefined)
160
336
  return notReported();
161
337
  try {
162
- if (typeof state !== "object" || state === null || Array.isArray(state))
163
- return malformedReading();
164
- const proto = Object.getPrototypeOf(state);
165
- if (proto !== Object.prototype && proto !== null)
338
+ if (!isPlainRecord(state))
166
339
  return malformedReading();
167
340
  const desc = Object.getOwnPropertyDescriptor(state, name);
168
341
  if (desc === undefined)
@@ -226,6 +399,9 @@ const SEAT_CAPABILITY_PHRASES = Object.freeze({
226
399
  pickFolder: Object.freeze({ action: "Opening a folder", ability: "show a folder picker", support: "folder picker support" }),
227
400
  rewind: Object.freeze({ action: "Rewinding to an earlier message", ability: "rewind this session", support: "rewind support" }),
228
401
  recents: Object.freeze({ action: "Remembering recent folders", ability: "remember recent folders", support: "recent folders support" }), patchSession: Object.freeze({ action: "Renaming or pinning a conversation", ability: "rename or pin conversations", support: "rename and pin support" }),
402
+ devices: Object.freeze({ action: "Managing devices", ability: "manage devices", support: "device support" }),
403
+ engineTarget: Object.freeze({ action: "Switching engines", ability: "switch engines", support: "engine-switching support" }),
404
+ onboard: Object.freeze({ action: "Model setup", ability: "add models", support: "model-setup support" }),
229
405
  });
230
406
  export function seatCapabilityUnavailableDetail(name, reading) {
231
407
  const phrase = Object.hasOwn(SEAT_CAPABILITY_PHRASES, name)
@@ -354,9 +530,381 @@ export const ATTACHMENT_UPLOAD_REQUEST_KEYS = ["name", "mimeType", "bytes"];
354
530
  export const SESSION_ROW_PATCH_REQUEST_KEYS = Object.freeze(["sessionId", "title", "pinned"]);
355
531
  export const SESSION_SEARCH_RESULT_KEYS = ["sessionId", "title", "matches"];
356
532
  export const GET_TRANSCRIPT_RESULT_KEYS = ["sessionId", "messages"];
533
+ const DEVICE_REFUSED_SPEC = { status: reqF(R_INT0), errorCode: optF(R_STR), message: optF(R_STR) };
534
+ const DEVICE_LANE_ABSENT_SPEC = { runStoreOnly: optF(R_TRUE) };
535
+ const DEVICE_TRANSPORT_SPEC = { detail: optF(R_STR) };
536
+ const DEVICE_UNREADABLE_SPEC = { why: reqF(R_STR) };
537
+ const DEVICE_UNCONFIRMED_SPEC = {
538
+ why: reqF(oneOfRule("unconfirmed why", ["accepted-unreadable", "transport", "server-error"])),
539
+ detail: optF(R_STR),
540
+ mayStillBeRunning: reqF(R_BOOL),
541
+ };
542
+ const DEVICE_RATE_LIMITED_SPEC = { retryAfterSec: optF(R_NUM) };
543
+ const DEVICE_ROSTER_ROW = shapeRule("device row", {
544
+ deviceId: reqF(R_NONEMPTY),
545
+ name: optF(R_STR),
546
+ status: reqF(oneOfRule("device status", ["online", "offline", "unknown"])),
547
+ lastSeenAt: optF(R_STR),
548
+ });
549
+ const DEVICE_BINDING = shapeRule("device binding", {
550
+ deviceId: reqF(R_NONEMPTY),
551
+ rev: reqF(R_INT0),
552
+ boundAt: optF(R_STR),
553
+ });
554
+ const checkDeviceListOutcome = seatShapeCheck(armsRule("listDevices outcome", "kind", {
555
+ ok: { devices: reqF(arrayRule(DEVICE_ROSTER_ROW)), dropped: reqF(R_INT0) },
556
+ unreadable: DEVICE_UNREADABLE_SPEC,
557
+ "lane-absent": DEVICE_LANE_ABSENT_SPEC,
558
+ refused: DEVICE_REFUSED_SPEC,
559
+ transport: DEVICE_TRANSPORT_SPEC,
560
+ unarmed: {},
561
+ }));
562
+ const checkDeviceSessionBindingOutcome = seatShapeCheck(armsRule("readSessionBinding outcome", "kind", {
563
+ ok: { rootSessionId: reqF(R_NONEMPTY), boundDevice: reqF(DEVICE_BINDING) },
564
+ "not-found": {},
565
+ unreadable: DEVICE_UNREADABLE_SPEC,
566
+ "lane-absent": DEVICE_LANE_ABSENT_SPEC,
567
+ refused: DEVICE_REFUSED_SPEC,
568
+ transport: DEVICE_TRANSPORT_SPEC,
569
+ unarmed: {},
570
+ }));
571
+ const checkDeviceRebindOutcome = seatShapeCheck(armsRule("rebindSession outcome", "kind", {
572
+ ok: { deviceId: reqF(R_NONEMPTY), rev: reqF(R_INT0), workspaceCarryover: optF(oneOfRule("carryover", ["none"])) },
573
+ "active-run": { activeTaskId: optF(R_STR) },
574
+ "rev-conflict": { currentRev: optF(R_INT0) },
575
+ "not-found": {},
576
+ unconfirmed: DEVICE_UNCONFIRMED_SPEC,
577
+ "lane-absent": DEVICE_LANE_ABSENT_SPEC,
578
+ refused: DEVICE_REFUSED_SPEC,
579
+ unarmed: {},
580
+ }));
581
+ const ENROLL_TOKEN_ALLOW = new Set(["token"]);
582
+ const checkDeviceEnrollTokenOutcome = seatShapeCheck(armsRule("issueEnrollToken outcome", "kind", {
583
+ ok: { token: reqF(R_NONEMPTY), expiresAt: optF(R_STR), ttlSec: optF(R_INT1) },
584
+ "rate-limited": DEVICE_RATE_LIMITED_SPEC,
585
+ unreadable: DEVICE_UNREADABLE_SPEC,
586
+ "lane-absent": DEVICE_LANE_ABSENT_SPEC,
587
+ refused: DEVICE_REFUSED_SPEC,
588
+ transport: DEVICE_TRANSPORT_SPEC,
589
+ unarmed: {},
590
+ }), ENROLL_TOKEN_ALLOW);
591
+ const checkDeviceRevokeOutcome = seatShapeCheck(armsRule("revokeDevice outcome", "kind", {
592
+ ok: { deviceId: reqF(R_NONEMPTY), revokedAt: optF(R_STR) },
593
+ "not-found": {},
594
+ unconfirmed: DEVICE_UNCONFIRMED_SPEC,
595
+ "lane-absent": DEVICE_LANE_ABSENT_SPEC,
596
+ refused: DEVICE_REFUSED_SPEC,
597
+ unarmed: {},
598
+ }));
599
+ export const checkSeatDeviceRebindRequest = seatShapeCheck(shapeRule("rebindSession request", {
600
+ sessionId: reqF(R_NONEMPTY),
601
+ toDeviceId: reqF(R_NONEMPTY),
602
+ expectedRev: reqF(R_INT0),
603
+ fromDeviceId: reqF(R_NONEMPTY),
604
+ }));
605
+ export const checkSeatDeviceRevokeRequest = seatShapeCheck(shapeRule("revokeDevice request", { deviceId: reqF(R_NONEMPTY), reason: optF(R_STR) }));
606
+ export const ENGINE_TARGET_REFUSALS = Object.freeze([
607
+ "busy",
608
+ "switching",
609
+ "not_configured",
610
+ "not_signed_in",
611
+ "probe_failed",
612
+ "org_policy",
613
+ "url_refused",
614
+ "login_failed",
615
+ "storage_unavailable",
616
+ "no_local_runtime",
617
+ "input",
618
+ ]);
619
+ export const CLOUD_LOGIN_FAILURES = Object.freeze([
620
+ "access_denied",
621
+ "expired_token",
622
+ "invalid_grant",
623
+ "cancelled",
624
+ "transport",
625
+ "refused",
626
+ "no_tokens",
627
+ "other",
628
+ ]);
629
+ const R_ISO = R_NONEMPTY;
630
+ const R_LOGIN_FAILURE = oneOfRule("login failure", CLOUD_LOGIN_FAILURES);
631
+ const R_DISPLAY_URL = ruleOf("display url", (v) => {
632
+ if (typeof v !== "string" || v.length === 0)
633
+ return false;
634
+ let u;
635
+ try {
636
+ u = new URL(v);
637
+ }
638
+ catch {
639
+ return false;
640
+ }
641
+ return (u.protocol === "https:" || u.protocol === "http:") && u.username === "" && u.password === "" && u.search === "" && u.hash === "";
642
+ });
643
+ const R_VERIFICATION_URI_COMPLETE = ruleOf("verification uri", (v) => {
644
+ if (typeof v !== "string" || v.length === 0)
645
+ return false;
646
+ let text = v;
647
+ for (let i = 0; i < 4; i += 1) {
648
+ let next;
649
+ try {
650
+ next = decodeURIComponent(text);
651
+ }
652
+ catch {
653
+ return false;
654
+ }
655
+ if (next === text)
656
+ break;
657
+ text = next;
658
+ }
659
+ return !/device[_-]?code/i.test(text);
660
+ });
661
+ const ENGINE_PROBE_READING = shapeRule("engine probe", {
662
+ ok: reqF(R_BOOL),
663
+ version: optF(R_STR),
664
+ detail: optF(R_STR),
665
+ at: reqF(R_ISO),
666
+ });
667
+ const SEAT_LOCAL_MCP_ROW = shapeRule("mcp row", {
668
+ name: reqF(R_NONEMPTY),
669
+ status: reqF(R_STR),
670
+ toolCount: optF(R_INT0),
671
+ liveness: optF(R_STR),
672
+ errorCode: optF(R_STR),
673
+ forcedAsk: optF(arrayRule(R_NONEMPTY, true)),
674
+ });
675
+ const SEAT_LOCAL_MCP_READING = armsRule("mcp reading", "status", {
676
+ listed: { servers: reqF(arrayRule(SEAT_LOCAL_MCP_ROW)), readAt: reqF(R_ISO), restartRequired: optF(R_TRUE) },
677
+ unreadable: { cause: reqF(R_NONEMPTY), detail: optF(R_STR), readAt: reqF(R_ISO), restartRequired: optF(R_TRUE) },
678
+ });
679
+ const ENGINE_TARGET_CLOUD = shapeRule("cloud", {
680
+ configured: reqF(R_BOOL),
681
+ url: optF(R_DISPLAY_URL),
682
+ label: optF(R_STR),
683
+ auth: optF(armsRule("cloud auth", "kind", {
684
+ registry: { registryUrl: reqF(R_DISPLAY_URL), principal: optF(R_STR), role: optF(R_STR), scope: optF(R_STR) },
685
+ token: {},
686
+ })),
687
+ login: optF(armsRule("cloud login", "state", {
688
+ pending: {
689
+ registryUrl: reqF(R_DISPLAY_URL),
690
+ userCode: reqF(R_NONEMPTY),
691
+ verificationUri: reqF(R_DISPLAY_URL),
692
+ verificationUriComplete: optF(R_VERIFICATION_URI_COMPLETE),
693
+ expiresAt: reqF(R_ISO),
694
+ },
695
+ failed: { failure: reqF(R_LOGIN_FAILURE), status: optF(R_INT0), at: reqF(R_ISO) },
696
+ })),
697
+ lastProbe: optF(ENGINE_PROBE_READING),
698
+ authError: optF(shapeRule("auth error", {
699
+ failure: reqF(R_LOGIN_FAILURE),
700
+ status: optF(R_INT0),
701
+ at: reqF(R_ISO),
702
+ })),
703
+ orgEngine: optF(shapeRule("org engine", { url: reqF(R_DISPLAY_URL), required: reqF(R_BOOL) })),
704
+ });
705
+ const ENGINE_TARGET_LOCAL = shapeRule("local", {
706
+ lastBootError: optF(R_STR),
707
+ mcp: optF(SEAT_LOCAL_MCP_READING),
708
+ });
709
+ const ENGINE_TARGET_STATE = shapeRule("engine target", {
710
+ mode: reqF(oneOfRule("engine mode", ["local", "cloud"])),
711
+ generation: reqF(R_INT0),
712
+ cloud: reqF(ENGINE_TARGET_CLOUD),
713
+ local: reqF(ENGINE_TARGET_LOCAL),
714
+ });
715
+ const checkEngineTargetState = seatShapeCheck(ENGINE_TARGET_STATE);
716
+ const okArmsRule = (label, okSpec, refusedSpec) => ({
717
+ label,
718
+ test: (v, path) => {
719
+ if (!isPlainRecord(v))
720
+ return bad("not object", path === "" ? undefined : path);
721
+ const ok = own(v, "ok");
722
+ if (ok === true)
723
+ return shapeVerdict(okSpec, v, path, "ok");
724
+ if (ok === false)
725
+ return shapeVerdict(refusedSpec, v, path, "ok");
726
+ return bad("unknown arm", pathAt(path, "ok"));
727
+ },
728
+ });
729
+ const ENGINE_TARGET_REFUSED_SPEC = {
730
+ refusal: reqF(oneOfRule("engineTarget refusal", ENGINE_TARGET_REFUSALS)),
731
+ failure: optF(R_LOGIN_FAILURE),
732
+ status: optF(R_INT0),
733
+ detail: optF(R_STR),
734
+ };
735
+ const checkEngineTargetResult = seatShapeCheck(okArmsRule("engineTarget result", {}, ENGINE_TARGET_REFUSED_SPEC));
736
+ const checkCancelCloudLogin = seatShapeCheck(shapeRule("cancel ack", { ok: reqF(R_BOOL) }));
737
+ const checkCloudLoginStart = seatShapeCheck(okArmsRule("startCloudLogin result", {
738
+ verificationUri: reqF(R_DISPLAY_URL),
739
+ verificationUriComplete: optF(R_VERIFICATION_URI_COMPLETE),
740
+ userCode: reqF(R_NONEMPTY),
741
+ expiresAt: reqF(R_ISO),
742
+ }, ENGINE_TARGET_REFUSED_SPEC));
743
+ const checkCloudConnectResult = seatShapeCheck(okArmsRule("connect result", {
744
+ probe: reqF(shapeRule("probe", { version: optF(R_STR) })),
745
+ }, ENGINE_TARGET_REFUSED_SPEC));
746
+ export const checkCloudLoginRequest = seatShapeCheck(shapeRule("startCloudLogin request", { registryUrl: reqF(R_DISPLAY_URL) }));
747
+ export const checkCloudEngineConnectRequest = seatShapeCheck(shapeRule("connectCloudEngine request", { url: reqF(R_DISPLAY_URL) }));
748
+ const CONFIGURE_TOKEN_ALLOW = new Set(["token"]);
749
+ export const checkCloudEngineConfigureRequest = seatShapeCheck(shapeRule("configureCloudEngine request", { url: reqF(R_DISPLAY_URL), token: reqF(R_NONEMPTY) }), CONFIGURE_TOKEN_ALLOW);
750
+ export const ONBOARD_REFUSALS = Object.freeze([
751
+ "input",
752
+ "probe_failed",
753
+ "probe_unverified",
754
+ "credential_unpaired",
755
+ "catalog_unreadable",
756
+ "write_conflict",
757
+ "write_failed",
758
+ "engine_is_remote",
759
+ "env_catalog_present",
760
+ ]);
761
+ const R_API_WORD = oneOfRule("api", SETTINGS_MODEL_API_WORDS);
762
+ const ONBOARD_PROBE_RESULT = shapeRule("probe result", {
763
+ verdict: reqF(oneOfRule("probe verdict", PROBE_VERDICTS)),
764
+ detail: reqF(R_STR),
765
+ thinking: optF(R_NONEMPTY),
766
+ });
767
+ const ENGINE_UP_SPEC = { model: reqF(ruleOf("string|null", (x) => x === null || typeof x === "string")) };
768
+ const ENGINE_NOT_UP_SPEC = { reason: reqF(R_STR) };
769
+ const ENGINE_RESTART_OUTCOME = armsRule("engine restart", "state", {
770
+ started: ENGINE_UP_SPEC,
771
+ restarted: ENGINE_UP_SPEC,
772
+ pending: ENGINE_NOT_UP_SPEC,
773
+ failed: ENGINE_NOT_UP_SPEC,
774
+ skipped: ENGINE_NOT_UP_SPEC,
775
+ });
776
+ const ONBOARD_SOURCE = armsRule("onboard source", "kind", {
777
+ preset: { providerId: reqF(R_NONEMPTY) },
778
+ custom: {},
779
+ imported: { profileId: reqF(R_NONEMPTY) },
780
+ });
781
+ const ONBOARD_ENTRY_SPEC = {
782
+ source: reqF(ONBOARD_SOURCE),
783
+ modelId: reqF(R_NONEMPTY),
784
+ baseUrl: optF(R_NONEMPTY),
785
+ api: optF(R_API_WORD),
786
+ apiKey: optF(R_NONEMPTY),
787
+ contextWindow: optF(R_INT1),
788
+ maxTokens: optF(R_INT1),
789
+ };
790
+ const ONBOARD_KEY_ALLOW = new Set(["apiKey"]);
791
+ export const checkOnboardEntryRequest = seatShapeCheck(shapeRule("probeOnboardEntry request", ONBOARD_ENTRY_SPEC), ONBOARD_KEY_ALLOW);
792
+ export const checkOnboardApplyRequest = seatShapeCheck(shapeRule("applyOnboardEntry request", {
793
+ ...ONBOARD_ENTRY_SPEC,
794
+ makeDefault: optF(R_BOOL),
795
+ acceptUnverified: optF(R_BOOL),
796
+ }), ONBOARD_KEY_ALLOW);
797
+ const checkOnboardProbeResult = seatShapeCheck(ONBOARD_PROBE_RESULT);
798
+ const checkOnboardApplyResult = seatShapeCheck(okArmsRule("applyOnboardEntry result", {
799
+ entryName: reqF(R_NONEMPTY),
800
+ modelId: reqF(R_NONEMPTY),
801
+ keyEnv: reqF(R_NONEMPTY),
802
+ updatedExisting: reqF(R_BOOL),
803
+ probe: reqF(ONBOARD_PROBE_RESULT),
804
+ otherIssues: reqF(arrayRule(shapeRule("catalog issue", {
805
+ name: reqF(R_NONEMPTY),
806
+ modelId: reqF(R_STR),
807
+ issue: reqF(R_NONEMPTY),
808
+ }))),
809
+ engine: reqF(ENGINE_RESTART_OUTCOME),
810
+ }, {
811
+ refusal: reqF(oneOfRule("onboard refusal", ONBOARD_REFUSALS)),
812
+ detail: optF(R_STR),
813
+ probe: optF(ONBOARD_PROBE_RESULT),
814
+ }));
815
+ const checkOnboardProvidersResult = seatShapeCheck(shapeRule("onboard providers", {
816
+ providers: reqF(arrayRule(shapeRule("provider row", {
817
+ id: reqF(R_NONEMPTY),
818
+ name: reqF(R_NONEMPTY),
819
+ baseUrl: reqF(R_NONEMPTY),
820
+ api: reqF(R_API_WORD),
821
+ keyAuth: reqF(R_BOOL),
822
+ authEnv: reqF(R_STR),
823
+ models: reqF(arrayRule(shapeRule("provider model", {
824
+ id: reqF(R_NONEMPTY),
825
+ contextWindow: reqF(R_INT1),
826
+ maxTokens: reqF(R_INT1),
827
+ }))),
828
+ consoleUrl: optF(R_STR),
829
+ }))),
830
+ importable: optF(arrayRule(shapeRule("importable profile", {
831
+ id: reqF(R_NONEMPTY),
832
+ name: reqF(R_STR),
833
+ baseUrl: reqF(R_NONEMPTY),
834
+ api: reqF(R_API_WORD),
835
+ hasKey: reqF(R_BOOL),
836
+ models: reqF(arrayRule(R_NONEMPTY)),
837
+ }))),
838
+ }));
839
+ const checkSessionMcpPanelFailure = seatShapeCheck(armsRule("readSessionMcpPanel failure", "kind", {
840
+ unreadable: DEVICE_UNREADABLE_SPEC,
841
+ transport: DEVICE_TRANSPORT_SPEC,
842
+ unarmed: {},
843
+ }));
844
+ function mcpPanelLivenessArms() {
845
+ const arms = {};
846
+ for (const state of MCP_LIVENESS_STATES)
847
+ arms[state] = state === "unreachable" ? { observedAt: reqF(R_NUM), errorCode: optF(R_NONEMPTY) } : { observedAt: reqF(R_NUM) };
848
+ const keysPin = [true, true];
849
+ void keysPin;
850
+ return arms;
851
+ }
852
+ const MCP_PANEL_LIVENESS_VIEW = armsRule("mcp liveness", "state", mcpPanelLivenessArms());
853
+ const MCP_PANEL_LEG_ENTRY = shapeRule("leg entry", {
854
+ name: reqF(R_NONEMPTY),
855
+ status: reqF(R_NONEMPTY),
856
+ source: optF(R_NONEMPTY),
857
+ errorCode: optF(R_NONEMPTY),
858
+ toolCount: optF(R_NUM),
859
+ delivered: optF(R_NONEMPTY),
860
+ httpStatus: optF(R_NUM),
861
+ liveness: optF(MCP_PANEL_LIVENESS_VIEW),
862
+ livenessUnreadable: optF(R_TRUE),
863
+ });
864
+ const MCP_PANEL_LAST_LEG = shapeRule("last leg", {
865
+ runId: reqF(R_NONEMPTY),
866
+ at: reqF(R_NONEMPTY),
867
+ mcp: reqF(arrayRule(MCP_PANEL_LEG_ENTRY)),
868
+ });
869
+ const MCP_PANEL_SERVER_ROW = shapeRule("panel server", {
870
+ name: reqF(R_NONEMPTY),
871
+ status: reqF(R_NONEMPTY),
872
+ serverInfo: optF(shapeRule("server info", {
873
+ name: reqF(R_STR),
874
+ version: reqF(R_STR),
875
+ })),
876
+ toolNames: optF(arrayRule(R_STR)),
877
+ error: optF(R_STR),
878
+ });
879
+ const MCP_PANEL_SCENARIO_REFUSAL = shapeRule("scenario refusal", {
880
+ errorCode: optF(R_NONEMPTY),
881
+ error: optF(R_STR),
882
+ scenario: optF(R_NONEMPTY),
883
+ source: optF(oneOfRule("refusal source", ["ruling", "deployment"])),
884
+ });
885
+ const checkSessionMcpPanelServersView = seatShapeCheck(shapeRule("servers view", {
886
+ asOf: reqF(R_NONEMPTY),
887
+ lastLegMcp: optF(MCP_PANEL_LAST_LEG),
888
+ lastLegMcpUnreadable: optF(R_TRUE),
889
+ servers: reqF(arrayRule(MCP_PANEL_SERVER_ROW)),
890
+ degraded: optF(R_TRUE),
891
+ }));
892
+ const checkSessionMcpPanelRefusalView = seatShapeCheck(shapeRule("refusal view", {
893
+ asOf: reqF(R_NONEMPTY),
894
+ lastLegMcp: optF(MCP_PANEL_LAST_LEG),
895
+ lastLegMcpUnreadable: optF(R_TRUE),
896
+ scenarioRefusal: reqF(MCP_PANEL_SCENARIO_REFUSAL),
897
+ }));
898
+ const checkSessionMcpPanelResult = seatCheck((v) => {
899
+ if (!isPlainRecord(v))
900
+ return bad("mcp panel result is not a plain object");
901
+ if (Object.hasOwn(v, "kind"))
902
+ return checkSessionMcpPanelFailure(v);
903
+ return Object.hasOwn(v, "scenarioRefusal") ? checkSessionMcpPanelRefusalView(v) : checkSessionMcpPanelServersView(v);
904
+ });
357
905
  const checkLocalSessionRecord = seatCheck((s) => {
358
- if (!isObject(s))
359
- return bad("session record is not an object");
906
+ if (!isPlainRecord(s))
907
+ return bad("session record is not a plain object");
360
908
  if (typeof own(s, "sessionId") !== "string")
361
909
  return bad("sessionId must be a string", "sessionId");
362
910
  if (!optionalString(own(s, "engineSessionId")))
@@ -377,7 +925,7 @@ const checkLocalSessionRecord = seatCheck((s) => {
377
925
  return bad("lastActivityAt must be a string when present", "lastActivityAt");
378
926
  const q = own(s, "queuedMessages");
379
927
  if (!isAbsent(q)) {
380
- const okQueue = Array.isArray(q) && ownItems(q).every((row) => isObject(row) && typeof own(row, "uuid") === "string" && typeof own(row, "text") === "string");
928
+ const okQueue = Array.isArray(q) && ownItems(q).every((row) => isPlainRecord(row) && typeof own(row, "uuid") === "string" && typeof own(row, "text") === "string");
381
929
  if (!okQueue)
382
930
  return bad("queuedMessages must be an array of {uuid,text}", "queuedMessages");
383
931
  }
@@ -395,8 +943,8 @@ export function isLocalSessionRecord(s) {
395
943
  return checkLocalSessionRecord(s) === true;
396
944
  }
397
945
  const checkToctouBinding = seatCheck((v) => {
398
- if (!isObject(v))
399
- return bad("toctouBinding must be an object", "toctouBinding");
946
+ if (!isPlainRecord(v))
947
+ return bad("toctouBinding must be a plain object", "toctouBinding");
400
948
  if (typeof own(v, "callId") !== "string")
401
949
  return bad("toctouBinding.callId must be a string", "toctouBinding.callId");
402
950
  if (typeof own(v, "inputHash") !== "string")
@@ -404,8 +952,8 @@ const checkToctouBinding = seatCheck((v) => {
404
952
  return true;
405
953
  });
406
954
  const checkToolPermissionRequest = seatCheck((r) => {
407
- if (!isObject(r))
408
- return bad("tool permission request is not an object");
955
+ if (!isPlainRecord(r))
956
+ return bad("tool permission request is not a plain object");
409
957
  const requestId = own(r, "requestId");
410
958
  if (typeof requestId !== "string")
411
959
  return bad("requestId must be a string", "requestId");
@@ -440,8 +988,8 @@ export function isToolPermissionRequest(r) {
440
988
  return checkToolPermissionRequest(r) === true;
441
989
  }
442
990
  const checkLaneProof = seatCheckAt((v, field) => {
443
- if (!isObject(v))
444
- return bad("laneProof must be an object", field);
991
+ if (!isPlainRecord(v))
992
+ return bad("laneProof must be a plain object", field);
445
993
  const lane = own(v, "lane");
446
994
  if (typeof lane !== "string" || !inTuple(LANE_PROOF_LANE_TUPLE, lane)) {
447
995
  return bad(`laneProof.lane must be one of ${LANE_PROOF_LANE_TUPLE.join("|")}`, `${field}.lane`);
@@ -454,20 +1002,111 @@ const checkLaneProof = seatCheckAt((v, field) => {
454
1002
  }
455
1003
  return true;
456
1004
  });
1005
+ const R_NEVER = ruleOf("absent", () => false);
1006
+ const RETRY_ERROR_PAYLOAD = shapeRule("retry error", {
1007
+ formatted: reqF(R_STR),
1008
+ isNetworkDown: optF(R_BOOL),
1009
+ connection: optF(shapeRule("connection", { isSSLError: optF(R_BOOL) })),
1010
+ rateLimits: optF({
1011
+ label: "rate limits",
1012
+ test: (v, path) => v === null
1013
+ ? true
1014
+ : shapeVerdict({ resetsAt: optF(R_NUM), rateLimitType: optF(R_STR) }, v, path),
1015
+ }),
1016
+ });
1017
+ const RETRY_COMMON_SPEC = {
1018
+ deadline: reqF(R_NUM),
1019
+ attempt: optF(R_NUM),
1020
+ maxRetries: optF(R_NUM),
1021
+ errClass: optF(R_STR),
1022
+ retryAtMs: optF(R_NUM),
1023
+ errorStatus: optF(R_NUM),
1024
+ providerCondition: optF(R_STR),
1025
+ providerConditionSource: optF(R_STR),
1026
+ elapsedMs: optF(R_NUM),
1027
+ timeoutMs: optF(R_NUM),
1028
+ };
1029
+ const RETRY_STATUS = armsRule("retry status", "kind", {
1030
+ stalled: { ...RETRY_COMMON_SPEC, detail: optF(R_STR) },
1031
+ error: { ...RETRY_COMMON_SPEC, terminal: optF(R_TRUE), error: reqF(RETRY_ERROR_PAYLOAD) },
1032
+ waiting: { ...RETRY_COMMON_SPEC, terminal: optF(R_NEVER), error: reqF(RETRY_ERROR_PAYLOAD) },
1033
+ });
1034
+ const ENGINE_TURN_USAGE = shapeRule("engine usage", {
1035
+ inputTokens: reqF(R_NUM),
1036
+ totalInputTokens: reqF(R_NUM),
1037
+ outputTokens: reqF(R_NUM),
1038
+ cacheReadTokens: reqF(R_NUM),
1039
+ cacheWriteTokens: reqF(R_NUM),
1040
+ costMicroUsd: reqF(R_NUM),
1041
+ });
1042
+ const SEMA_MODEL_USAGE = shapeRule("model usage", {
1043
+ inputTokens: reqF(R_NUM),
1044
+ outputTokens: reqF(R_NUM),
1045
+ cacheReadInputTokens: reqF(R_NUM),
1046
+ cacheCreationInputTokens: reqF(R_NUM),
1047
+ webSearchRequests: reqF(R_NUM),
1048
+ costUSD: reqF(R_NUM),
1049
+ contextWindow: reqF(R_NUM),
1050
+ maxOutputTokens: reqF(R_NUM),
1051
+ canonicalModel: optF(R_STR),
1052
+ provider: optF(R_STR),
1053
+ _sema_cost_absent: optF(R_TRUE),
1054
+ _sema_web_search_requests_absent: optF(R_TRUE),
1055
+ _sema_context_window_absent: optF(R_TRUE),
1056
+ _sema_max_output_tokens_absent: optF(R_TRUE),
1057
+ });
1058
+ const SEAT_CHROME_PAYLOAD_SPECS = {
1059
+ retry_status: { status: reqF({ label: "retry status", test: (v, path) => (v === null ? true : RETRY_STATUS.test(v, path)) }) },
1060
+ context_usage: {
1061
+ usedTokens: optF(R_NUM),
1062
+ windowTokens: optF(R_NUM),
1063
+ compactAtTokens: optF(R_NUM),
1064
+ sections: optF(arrayRule(shapeRule("section", { id: reqF(R_STR), tokens: reqF(R_NUM), kind: optF(R_STR) }))),
1065
+ eventId: optF(R_NONEMPTY),
1066
+ },
1067
+ last_turn_usage: {
1068
+ usage: reqF(SEMA_MODEL_USAGE),
1069
+ engineUsage: optF(ENGINE_TURN_USAGE),
1070
+ engineUsageUnknownKeys: optF(R_INT1),
1071
+ usageMissing: optF(R_TRUE),
1072
+ stopReason: optF(R_STR),
1073
+ responseModel: optF(R_NONEMPTY),
1074
+ },
1075
+ bgshell_register: {
1076
+ taskId: reqF(R_NONEMPTY),
1077
+ registration: reqF(shapeRule("registration", {
1078
+ kind: reqF(oneOfRule("registration kind", ["register"])),
1079
+ taskId: reqF(R_NONEMPTY),
1080
+ command: reqF(R_STR),
1081
+ description: optF(R_STR),
1082
+ receipt: reqF(R_STR),
1083
+ source: reqF(oneOfRule("registration source", ["bash", "monitor"])),
1084
+ })),
1085
+ },
1086
+ bgshell_settle: { taskId: reqF(R_NONEMPTY), status: reqF(R_STR), outputPath: optF(R_STR) },
1087
+ memory_saved: { id: reqF(R_NONEMPTY), notes: reqF(arrayRule(R_NONEMPTY, true)) },
1088
+ };
1089
+ const ENVELOPE_ROWS = { kind: reqF({ label: "kind", test: () => true }), laneProof: reqF({ label: "laneProof", test: () => true }) };
457
1090
  const checkSeatChromeEnvelope = seatCheckAt((v, field) => {
458
- if (!isObject(v))
459
- return bad("chrome must be an object", field);
1091
+ if (!isPlainRecord(v))
1092
+ return bad("chrome must be a plain object", field);
460
1093
  const kind = own(v, "kind");
461
1094
  if (typeof kind !== "string")
462
1095
  return bad("chrome.kind must be a string", `${field}.kind`);
463
1096
  if (!inTuple(CHROME_EVENT_KIND_TUPLE, kind)) {
464
1097
  return bad(`chrome.kind is not a renderer-wired arm (${CHROME_EVENT_KIND_TUPLE.join("|")})`, `${field}.kind`);
465
1098
  }
466
- return checkLaneProof(own(v, "laneProof"), `${field}.laneProof`);
1099
+ const lane = checkLaneProof(own(v, "laneProof"), `${field}.laneProof`);
1100
+ if (lane !== true)
1101
+ return lane;
1102
+ if (Object.hasOwn(SEAT_CHROME_PAYLOAD_SPECS, kind)) {
1103
+ return shapeVerdict({ ...ENVELOPE_ROWS, ...SEAT_CHROME_PAYLOAD_SPECS[kind] }, v, field);
1104
+ }
1105
+ return true;
467
1106
  });
468
1107
  const checkLocalSessionEvent = seatCheck((v) => {
469
- if (!isObject(v))
470
- return bad("event is not an object");
1108
+ if (!isPlainRecord(v))
1109
+ return bad("event is not a plain object");
471
1110
  const type = own(v, "type");
472
1111
  if (typeof type !== "string")
473
1112
  return bad("type must be a string", "type");
@@ -476,9 +1115,6 @@ const checkLocalSessionEvent = seatCheck((v) => {
476
1115
  }
477
1116
  if (typeof own(v, "sessionId") !== "string")
478
1117
  return bad("sessionId must be a string", "sessionId");
479
- const messages = own(v, "messages");
480
- if (!isAbsent(messages) && !Array.isArray(messages))
481
- return bad("messages must be an array", "messages");
482
1118
  if (!optionalString(own(v, "error")))
483
1119
  return bad("error must be a string when present", "error");
484
1120
  if (!optionalString(own(v, "errorCategory")))
@@ -486,26 +1122,6 @@ const checkLocalSessionEvent = seatCheck((v) => {
486
1122
  const code = own(v, "code");
487
1123
  if (!isAbsent(code) && typeof code !== "number")
488
1124
  return bad("code must be a number when present", "code");
489
- const request = own(v, "request");
490
- if (!isAbsent(request)) {
491
- const verdict = checkToolPermissionRequest(request);
492
- if (verdict !== true)
493
- return nested("request", verdict);
494
- }
495
- if (!optionalString(own(v, "data")))
496
- return bad("data must be a string when present", "data");
497
- const sources = own(v, "sources");
498
- if (!isAbsent(sources)) {
499
- const okSources = Array.isArray(sources) && ownItems(sources).every((t) => typeof t === "string");
500
- if (!okSources)
501
- return bad("sources must be a string[]", "sources");
502
- }
503
- const mode = own(v, "permissionMode");
504
- if (!isAbsent(mode)) {
505
- if (typeof mode !== "string" || !inTuple(PERMISSION_MODE_INTENTS, mode)) {
506
- return bad(`permissionMode must be one of ${PERMISSION_MODE_INTENTS.join("|")}`, "permissionMode");
507
- }
508
- }
509
1125
  const session = own(v, "session");
510
1126
  if (!isAbsent(session)) {
511
1127
  const verdict = checkLocalSessionRecord(session);
@@ -514,10 +1130,6 @@ const checkLocalSessionEvent = seatCheck((v) => {
514
1130
  }
515
1131
  if (!optionalString(own(v, "userMessageUuid")))
516
1132
  return bad("userMessageUuid must be a string when present", "userMessageUuid");
517
- const hasPreClearSession = own(v, "hasPreClearSession");
518
- if (!isAbsent(hasPreClearSession) && typeof hasPreClearSession !== "boolean") {
519
- return bad("hasPreClearSession must be a boolean when present", "hasPreClearSession");
520
- }
521
1133
  if (!optionalString(own(v, "requestId")))
522
1134
  return bad("requestId must be a string when present", "requestId");
523
1135
  const outcome = own(v, "outcome");
@@ -537,14 +1149,49 @@ const checkLocalSessionEvent = seatCheck((v) => {
537
1149
  if (verdict !== true)
538
1150
  return nested("chrome", verdict);
539
1151
  }
1152
+ const sub = own(v, "subagentContent");
1153
+ if (type === "subagent_content") {
1154
+ if (isAbsent(sub))
1155
+ return bad("missing key", "subagentContent");
1156
+ const verdict = SUBAGENT_CONTENT_SHAPE.test(sub, "subagentContent");
1157
+ if (verdict !== true)
1158
+ return verdict;
1159
+ }
1160
+ else if (!isAbsent(sub)) {
1161
+ return bad("unexpected key", "subagentContent");
1162
+ }
540
1163
  return true;
541
1164
  });
1165
+ const SUBAGENT_CONTENT_SHAPE = shapeRule("subagent content", {
1166
+ type: reqF(oneOfRule("content type", ["text_delta", "reasoning_delta", "text", "reasoning", "tool_start", "tool_end"])),
1167
+ taskId: reqF(R_NONEMPTY),
1168
+ parentToolCallId: reqF(R_NONEMPTY),
1169
+ delta: optF(R_STR),
1170
+ text: optF(R_STR),
1171
+ eventId: optF(R_STR),
1172
+ toolCallId: optF(R_STR),
1173
+ toolName: optF(R_STR),
1174
+ args: optF({ label: "passthrough", test: () => true }),
1175
+ output: optF(R_STR),
1176
+ isError: optF(R_BOOL),
1177
+ });
1178
+ export function readSeatSubagentContent(event) {
1179
+ try {
1180
+ if (checkLocalSessionEvent(event) !== true || own(event, "type") !== "subagent_content")
1181
+ return undefined;
1182
+ const sub = own(event, "subagentContent");
1183
+ return { ...sub };
1184
+ }
1185
+ catch {
1186
+ return undefined;
1187
+ }
1188
+ }
542
1189
  export function isLocalSessionEvent(v) {
543
1190
  return checkLocalSessionEvent(v) === true;
544
1191
  }
545
1192
  const checkAttachmentUploadReceipt = seatCheck((v) => {
546
- if (!isObject(v))
547
- return bad("upload receipt is not an object");
1193
+ if (!isPlainRecord(v))
1194
+ return bad("upload receipt is not a plain object");
548
1195
  if (typeof own(v, "id") !== "string")
549
1196
  return bad("id must be a string", "id");
550
1197
  if (typeof own(v, "name") !== "string")
@@ -560,43 +1207,62 @@ const checkAttachmentUploadReceipt = seatCheck((v) => {
560
1207
  export function isAttachmentUploadReceipt(v) {
561
1208
  return checkAttachmentUploadReceipt(v) === true;
562
1209
  }
1210
+ export const APPLY_MODEL_CONFIG_REASONS = Object.freeze([
1211
+ "shadowed_by_models_json",
1212
+ "cheap_provider_unsupported",
1213
+ "invalid_request",
1214
+ "write_failed",
1215
+ "unavailable",
1216
+ ]);
1217
+ const APPLY_MODEL_CONFIG_REASON_DETAILS = Object.freeze({
1218
+ shadowed_by_models_json: "Models are managed in the local engine setup window on this device — open it to change the model (Engine ▸ Set up local engine…). Nothing was saved here.",
1219
+ cheap_provider_unsupported: "The cheap model has to use the default model's provider on this desktop seat (same base URL, API and key). Nothing was saved.",
1220
+ invalid_request: "The model configuration was not valid, so it was not applied.",
1221
+ write_failed: "The model configuration could not be saved.",
1222
+ unavailable: "The model configuration can't be changed from this app right now. Nothing was saved.",
1223
+ });
1224
+ export function applyModelConfigReasonDetail(reason) {
1225
+ if (typeof reason === "string" && inTuple(APPLY_MODEL_CONFIG_REASONS, reason))
1226
+ return APPLY_MODEL_CONFIG_REASON_DETAILS[reason];
1227
+ return "The seat rejected this configuration.";
1228
+ }
563
1229
  const checkApplyModelConfigResult = seatCheck((v) => {
564
- if (!isObject(v))
565
- return bad("applyModelConfig result is not an object");
1230
+ if (!isPlainRecord(v))
1231
+ return bad("applyModelConfig result is not a plain object");
566
1232
  const ok = own(v, "ok");
567
1233
  if (typeof ok !== "boolean")
568
1234
  return bad("ok must be a boolean", "ok");
569
1235
  if (typeof own(v, "requiresRestart") !== "boolean")
570
1236
  return bad("requiresRestart must be a boolean", "requiresRestart");
571
1237
  const reason = own(v, "reason");
572
- if (ok === false && (typeof reason !== "string" || reason.length === 0)) {
573
- return bad("reason must be a non-empty string when ok is false", "reason");
1238
+ if (!isAbsent(reason) && (typeof reason !== "string" || !inTuple(APPLY_MODEL_CONFIG_REASONS, reason))) {
1239
+ return bad(`reason must be one of ${APPLY_MODEL_CONFIG_REASONS.join("|")} when present`, "reason");
574
1240
  }
575
- if (reason !== undefined && typeof reason !== "string")
576
- return bad("reason must be a string when present", "reason");
1241
+ if (ok === false && isAbsent(reason)) {
1242
+ return bad(`reason must be present when ok is false (one of ${APPLY_MODEL_CONFIG_REASONS.join("|")})`, "reason");
1243
+ }
1244
+ if (!optionalString(own(v, "detail")))
1245
+ return bad("detail must be a string when present", "detail");
577
1246
  return true;
578
1247
  });
579
1248
  const checkLiveModelCatalog = seatCheck((v) => {
580
- if (!isObject(v) || Array.isArray(v))
581
- return bad("model catalog is not an object");
1249
+ if (!isPlainRecord(v))
1250
+ return bad("model catalog is not a plain object");
582
1251
  const models = own(v, "models");
583
1252
  if (!Array.isArray(models))
584
1253
  return bad("models must be an array", "models");
585
1254
  const rows = ownItems(models);
586
1255
  const names = new Set();
587
1256
  for (let i = 0; i < rows.length; i += 1) {
588
- const row = liveModelRowCopy(rows[i]);
1257
+ const row = isPlainRecord(rows[i]) ? liveModelRowCopy(rows[i]) : undefined;
589
1258
  if (row === undefined)
590
- return bad(`models[${i}] is not a catalog row (an object whose name is a non-empty string, JSON values only)`, `models[${i}]`);
1259
+ return bad(`models[${i}] is not a catalog row (a plain object whose name is a non-empty string, JSON values only)`, `models[${i}]`);
591
1260
  if (names.has(row.name))
592
1261
  return bad(`models[${i}] repeats the name of an earlier row`, `models[${i}].name`);
593
1262
  names.add(row.name);
594
1263
  }
595
- const dflt = own(v, "default");
596
- if (typeof dflt !== "string" || dflt.length === 0)
597
- return bad("default must be a non-empty string", "default");
598
1264
  const defaultModel = own(v, "defaultModel");
599
- if (!isAbsent(defaultModel) && liveDefaultModelCopy(defaultModel) === undefined) {
1265
+ if (!isAbsent(defaultModel) && (!isPlainRecord(defaultModel) || liveDefaultModelCopy(defaultModel) === undefined)) {
600
1266
  return bad("defaultModel must be {id: non-empty string, name?: non-empty string} when present", "defaultModel");
601
1267
  }
602
1268
  return true;
@@ -737,8 +1403,8 @@ export function isSessionRowPatchRequest(v) {
737
1403
  return checkSessionRowPatchRequest(v) === true;
738
1404
  }
739
1405
  const checkSendMessageAck = seatCheck((v) => {
740
- if (!isObject(v))
741
- return bad("sendMessage ack is not an object");
1406
+ if (!isPlainRecord(v))
1407
+ return bad("sendMessage ack is not a plain object");
742
1408
  if (typeof own(v, "sessionId") !== "string")
743
1409
  return bad("sessionId must be a string", "sessionId");
744
1410
  if (typeof own(v, "userMessageUuid") !== "string")
@@ -751,13 +1417,13 @@ const checkSendMessageAck = seatCheck((v) => {
751
1417
  export function isSendMessageAck(v) {
752
1418
  return checkSendMessageAck(v) === true;
753
1419
  }
754
- const checkInterruptAck = seatCheck((v) => isObject(v) && typeof own(v, "interrupted") === "boolean" ? true : bad("interrupt ack needs boolean `interrupted`", "interrupted"));
755
- const checkStopAck = seatCheck((v) => isObject(v) && typeof own(v, "stopped") === "boolean" ? true : bad("stop ack needs boolean `stopped`", "stopped"));
756
- const checkOkAck = seatCheck((v) => isObject(v) && typeof own(v, "ok") === "boolean" ? true : bad("ack needs boolean `ok`", "ok"));
1420
+ const checkInterruptAck = seatCheck((v) => isPlainRecord(v) && typeof own(v, "interrupted") === "boolean" ? true : bad("interrupt ack needs a plain object with boolean `interrupted`", "interrupted"));
1421
+ const checkStopAck = seatCheck((v) => isPlainRecord(v) && typeof own(v, "stopped") === "boolean" ? true : bad("stop ack needs a plain object with boolean `stopped`", "stopped"));
1422
+ const checkOkAck = seatCheck((v) => isPlainRecord(v) && typeof own(v, "ok") === "boolean" ? true : bad("ack needs a plain object with boolean `ok`", "ok"));
757
1423
  const checkBooleanAck = (v) => typeof v === "boolean" ? true : bad("expected a bare boolean result");
758
1424
  const checkGetTranscriptResult = seatCheck((v) => {
759
- if (!isObject(v))
760
- return bad("transcript envelope is not an object");
1425
+ if (!isPlainRecord(v))
1426
+ return bad("transcript envelope is not a plain object");
761
1427
  if (typeof own(v, "sessionId") !== "string")
762
1428
  return bad("sessionId must be a string", "sessionId");
763
1429
  if (!Array.isArray(own(v, "messages")))
@@ -765,8 +1431,8 @@ const checkGetTranscriptResult = seatCheck((v) => {
765
1431
  return true;
766
1432
  });
767
1433
  const checkSessionSearchResult = seatCheck((v) => {
768
- if (!isObject(v))
769
- return bad("search result row is not an object");
1434
+ if (!isPlainRecord(v))
1435
+ return bad("search result row is not a plain object");
770
1436
  if (typeof own(v, "sessionId") !== "string")
771
1437
  return bad("sessionId must be a string", "sessionId");
772
1438
  if (!optionalString(own(v, "title")))
@@ -774,14 +1440,14 @@ const checkSessionSearchResult = seatCheck((v) => {
774
1440
  const matches = own(v, "matches");
775
1441
  if (!Array.isArray(matches))
776
1442
  return bad("matches must be an array", "matches");
777
- const okMatches = ownItems(matches).every((m) => isObject(m) && typeof own(m, "snippet") === "string");
1443
+ const okMatches = ownItems(matches).every((m) => isPlainRecord(m) && typeof own(m, "snippet") === "string");
778
1444
  if (!okMatches)
779
1445
  return bad("matches must be {snippet:string}[]", "matches");
780
1446
  return true;
781
1447
  });
782
1448
  const checkSessionSearchEnvelope = seatCheck((v) => {
783
- if (!isObject(v))
784
- return bad("search envelope is not an object");
1449
+ if (!isPlainRecord(v))
1450
+ return bad("search envelope is not a plain object");
785
1451
  const results = own(v, "results");
786
1452
  if (!Array.isArray(results))
787
1453
  return bad("results must be an array", "results");
@@ -794,8 +1460,8 @@ const checkSessionSearchEnvelope = seatCheck((v) => {
794
1460
  return true;
795
1461
  });
796
1462
  const checkSessionsState = seatCheck((v) => {
797
- if (!isObject(v))
798
- return bad("sessions state is not an object");
1463
+ if (!isPlainRecord(v))
1464
+ return bad("sessions state is not a plain object");
799
1465
  const sessions = own(v, "sessions");
800
1466
  if (!Array.isArray(sessions))
801
1467
  return bad("sessions must be an array", "sessions");
@@ -808,8 +1474,8 @@ const checkSessionsState = seatCheck((v) => {
808
1474
  return true;
809
1475
  });
810
1476
  const checkFocusedSessionState = seatCheck((v) => {
811
- if (!isObject(v))
812
- return bad("focused session state is not an object");
1477
+ if (!isPlainRecord(v))
1478
+ return bad("focused session state is not a plain object");
813
1479
  const sessionId = own(v, "sessionId");
814
1480
  if (sessionId !== null && typeof sessionId !== "string") {
815
1481
  return bad("sessionId must be a string or null", "sessionId");
@@ -855,10 +1521,7 @@ const checkRecentFoldersResult = seatCheck((v) => {
855
1521
  return true;
856
1522
  });
857
1523
  const checkSeatCapabilitiesState = seatCheck((v) => {
858
- if (!isObject(v) || Array.isArray(v))
859
- return bad("seat capabilities state is not an object");
860
- const proto = Object.getPrototypeOf(v);
861
- if (proto !== Object.prototype && proto !== null)
1524
+ if (!isPlainRecord(v))
862
1525
  return bad("seat capabilities state is not a plain object");
863
1526
  for (const k of Reflect.ownKeys(v)) {
864
1527
  const name = typeof k === "string" ? k : String(k);
@@ -893,6 +1556,21 @@ export const LOCAL_SESSIONS_SPEC = {
893
1556
  pickFolder: { kind: "invoke", check: checkPickFolderResult },
894
1557
  listRecentFolders: { kind: "invoke", check: checkRecentFoldersResult },
895
1558
  noteRecentFolder: { kind: "invoke", check: checkOkAck }, patchSession: { kind: "invoke", check: checkLocalSessionRecord },
1559
+ listDevices: { kind: "invoke", check: checkDeviceListOutcome },
1560
+ readSessionBinding: { kind: "invoke", check: checkDeviceSessionBindingOutcome },
1561
+ rebindSession: { kind: "invoke", check: checkDeviceRebindOutcome },
1562
+ issueEnrollToken: { kind: "invoke", check: checkDeviceEnrollTokenOutcome },
1563
+ revokeDevice: { kind: "invoke", check: checkDeviceRevokeOutcome },
1564
+ setEngineMode: { kind: "invoke", check: checkEngineTargetResult },
1565
+ startCloudLogin: { kind: "invoke", check: checkCloudLoginStart },
1566
+ cancelCloudLogin: { kind: "invoke", check: checkCancelCloudLogin },
1567
+ connectCloudEngine: { kind: "invoke", check: checkCloudConnectResult },
1568
+ configureCloudEngine: { kind: "invoke", check: checkCloudConnectResult },
1569
+ clearCloudEngine: { kind: "invoke", check: checkEngineTargetResult },
1570
+ listOnboardProviders: { kind: "invoke", check: checkOnboardProvidersResult },
1571
+ probeOnboardEntry: { kind: "invoke", check: checkOnboardProbeResult },
1572
+ applyOnboardEntry: { kind: "invoke", check: checkOnboardApplyResult },
1573
+ readSessionMcpPanel: { kind: "invoke", check: checkSessionMcpPanelResult },
896
1574
  onEvent: { kind: "event", check: checkLocalSessionEvent },
897
1575
  onToolPermissionRequest: { kind: "event", check: checkToolPermissionRequest },
898
1576
  },
@@ -901,6 +1579,7 @@ export const LOCAL_SESSIONS_SPEC = {
901
1579
  focusedSessionState: { check: checkFocusedSessionState },
902
1580
  settingsState: { check: checkSettingsState },
903
1581
  seatCapabilitiesState: { check: checkSeatCapabilitiesState },
1582
+ engineTargetState: { check: checkEngineTargetState },
904
1583
  },
905
1584
  };
906
1585
  export const SEAT_METHOD_NAMES = [
@@ -922,6 +1601,21 @@ export const SEAT_METHOD_NAMES = [
922
1601
  "pickFolder",
923
1602
  "listRecentFolders",
924
1603
  "noteRecentFolder", "patchSession",
1604
+ "listDevices",
1605
+ "readSessionBinding",
1606
+ "rebindSession",
1607
+ "issueEnrollToken",
1608
+ "revokeDevice",
1609
+ "setEngineMode",
1610
+ "startCloudLogin",
1611
+ "cancelCloudLogin",
1612
+ "connectCloudEngine",
1613
+ "configureCloudEngine",
1614
+ "clearCloudEngine",
1615
+ "listOnboardProviders",
1616
+ "probeOnboardEntry",
1617
+ "applyOnboardEntry",
1618
+ "readSessionMcpPanel",
925
1619
  "onEvent",
926
1620
  "onToolPermissionRequest",
927
1621
  ];
@@ -930,27 +1624,24 @@ export const SEAT_STORE_PROPS = [
930
1624
  "focusedSessionStateStore",
931
1625
  "settingsStateStore",
932
1626
  "seatCapabilitiesStateStore",
1627
+ "engineTargetStateStore",
933
1628
  ];
934
1629
  export const SEAT_EVENT_METHOD_NAMES = ["onEvent", "onToolPermissionRequest"];
935
1630
  export const LOCAL_SESSION_EVENT_KEYS = [
936
1631
  "type",
937
1632
  "sessionId",
938
1633
  "message",
939
- "messages",
940
1634
  "error",
941
1635
  "errorCategory",
942
1636
  "code",
943
- "request",
944
- "data",
945
- "sources",
946
- "permissionMode",
947
1637
  "session",
948
1638
  "userMessageUuid",
949
- "hasPreClearSession",
950
1639
  "requestId",
951
1640
  "outcome",
952
1641
  "parked",
953
1642
  "chrome",
1643
+ "_sema_turnFailure",
1644
+ "subagentContent",
954
1645
  ];
955
1646
  export const TOOL_PERMISSION_REQUEST_KEYS = [
956
1647
  "requestId",
@@ -1083,27 +1774,26 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
1083
1774
  validated: [
1084
1775
  "type",
1085
1776
  "sessionId",
1086
- "messages",
1087
1777
  "error",
1088
1778
  "errorCategory",
1089
1779
  "code",
1090
- "request",
1091
- "data",
1092
- "sources",
1093
- "permissionMode",
1094
1780
  "session",
1095
1781
  "userMessageUuid",
1096
- "hasPreClearSession",
1097
1782
  "requestId",
1098
1783
  "outcome",
1099
1784
  "parked",
1100
1785
  "chrome",
1786
+ "subagentContent",
1101
1787
  ],
1102
1788
  unchecked: [
1103
1789
  {
1104
1790
  key: "message",
1105
1791
  why: "transcript 面直通位(CC fQe 逐字姿态:SDKMessage 体不做 schema 校验)—— 校它 = 引擎加一种消息体的那天整条转录被门吃掉。",
1106
1792
  },
1793
+ {
1794
+ key: "_sema_turnFailure",
1795
+ why: "turn 失败的呈现判决(CC-378 TK-9),核形在包读口 readSeatTurnFailure(坏形 / 表外类别词 ⇒ undefined、渲染端只渲 error 文本);出站门为它拒掉整条 error 事件 = 宿主 settle 照走、渲染端把失败轮渲成完成,所以门只登键不拒。",
1796
+ },
1107
1797
  ],
1108
1798
  },
1109
1799
  AttachmentUploadReceipt: {
@@ -1114,7 +1804,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
1114
1804
  },
1115
1805
  LiveModelCatalog: {
1116
1806
  check: checkLiveModelCatalog,
1117
- validated: ["models", "default", "defaultModel"],
1807
+ validated: ["models", "defaultModel"],
1118
1808
  unchecked: [
1119
1809
  {
1120
1810
  key: "droppedEntries",
@@ -1154,7 +1844,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
1154
1844
  },
1155
1845
  ApplyModelConfigResult: {
1156
1846
  check: checkApplyModelConfigResult,
1157
- validated: ["ok", "requiresRestart", "reason"],
1847
+ validated: ["ok", "requiresRestart", "reason", "detail"],
1158
1848
  unchecked: [],
1159
1849
  },
1160
1850
  SendMessageAck: {
@@ -1205,7 +1895,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
1205
1895
  },
1206
1896
  SeatCapabilitiesState: {
1207
1897
  check: checkSeatCapabilitiesState,
1208
- validated: ["pickFolder", "rewind", "recents", "patchSession"],
1898
+ validated: ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard"],
1209
1899
  unchecked: [],
1210
1900
  },
1211
1901
  RecentFoldersResult: {
@@ -1238,8 +1928,39 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
1238
1928
  validated: ["kind", "laneProof"],
1239
1929
  unchecked: [],
1240
1930
  },
1931
+ SessionMcpPanelResult: {
1932
+ check: checkSessionMcpPanelResult,
1933
+ validated: ["kind", "why", "detail", "asOf", "servers", "lastLegMcp", "lastLegMcpUnreadable", "degraded", "scenarioRefusal"],
1934
+ unchecked: [],
1935
+ },
1241
1936
  };
1242
1937
  export const SEAT_VALIDATOR_COVERAGE_EXEMPT = [
1938
+ ...[
1939
+ ["DeviceListOutcome", checkDeviceListOutcome],
1940
+ ["DeviceSessionBindingOutcome", checkDeviceSessionBindingOutcome],
1941
+ ["DeviceRebindOutcome", checkDeviceRebindOutcome],
1942
+ ["DeviceEnrollTokenOutcome", checkDeviceEnrollTokenOutcome],
1943
+ ["DeviceRevokeOutcome", checkDeviceRevokeOutcome],
1944
+ ["SeatDeviceRebindRequest", checkSeatDeviceRebindRequest],
1945
+ ["SeatDeviceRevokeRequest", checkSeatDeviceRevokeRequest],
1946
+ ["EngineTargetState", checkEngineTargetState],
1947
+ ["EngineTargetResult", checkEngineTargetResult],
1948
+ ["CloudLoginStart", checkCloudLoginStart],
1949
+ ["CloudLoginCancelAck", checkCancelCloudLogin],
1950
+ ["CloudConnectResult", checkCloudConnectResult],
1951
+ ["CloudLoginRequest", checkCloudLoginRequest],
1952
+ ["CloudEngineConnectRequest", checkCloudEngineConnectRequest],
1953
+ ["CloudEngineConfigureRequest", checkCloudEngineConfigureRequest],
1954
+ ["OnboardProvidersResult", checkOnboardProvidersResult],
1955
+ ["OnboardProbeResult", checkOnboardProbeResult],
1956
+ ["OnboardApplyResult", checkOnboardApplyResult],
1957
+ ["OnboardEntryRequest", checkOnboardEntryRequest],
1958
+ ["OnboardApplyRequest", checkOnboardApplyRequest],
1959
+ ].map(([label, check]) => ({
1960
+ label,
1961
+ check,
1962
+ why: "座位闭形规则铸的判官(规格表型由对象型派生,键集与必选性编译期两向钉);逐臂逐键投毒在三只席位门(见上方注)。",
1963
+ })),
1243
1964
  {
1244
1965
  label: "PickFolderResult",
1245
1966
  check: checkPickFolderResult,
@@ -1282,5 +2003,8 @@ const _seatContractPins = [
1282
2003
  true, true,
1283
2004
  true, true, true, true,
1284
2005
  true, true, true, true, true, true,
2006
+ true, true,
2007
+ true, true, true, true,
2008
+ true, true, true,
1285
2009
  ];
1286
2010
  void _seatContractPins;