@sema-agent/client-core 0.93.1 → 0.95.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. package/CHANGELOG.md +554 -0
  2. package/README.md +89 -55
  3. package/dist/adapt/arms.js +13 -11
  4. package/dist/adapt/panelTasks.js +4 -10
  5. package/dist/adapt/toolCards.js +2 -2
  6. package/dist/adapt/wireShapes.js +3 -8
  7. package/dist/adapter/activeRunSelfHeal.d.ts +8 -3
  8. package/dist/adapter/activeRunSelfHeal.js +20 -12
  9. package/dist/adapter/downstream/eventToSdkMessage.js +24 -17
  10. package/dist/adapter/downstream/terminalToSdkResult.js +13 -6
  11. package/dist/adapter/runStream.js +2 -1
  12. package/dist/adapter/types.d.ts +7 -0
  13. package/dist/adapter/types.js +15 -0
  14. package/dist/agentSession/backgroundView.js +5 -1
  15. package/dist/agentSession/engineAgentRegistryRead.js +2 -1
  16. package/dist/agentSession/engineSessionBackgroundStop.js +5 -3
  17. package/dist/agentsWireCaps.d.ts +17 -0
  18. package/dist/agentsWireCaps.js +111 -1
  19. package/dist/approvalDecidedByCapability.d.ts +0 -1
  20. package/dist/approvalDecidedByCapability.js +2 -7
  21. package/dist/approvalReachWire.d.ts +18 -0
  22. package/dist/approvalReachWire.js +58 -0
  23. package/dist/approvalsStreamLiveCapability.d.ts +0 -1
  24. package/dist/approvalsStreamLiveCapability.js +15 -14
  25. package/dist/atMostOnce.d.ts +8 -0
  26. package/dist/atMostOnce.js +36 -0
  27. package/dist/attachmentSeatCapability.d.ts +0 -1
  28. package/dist/attachmentSeatCapability.js +0 -3
  29. package/dist/attachmentsWireCaps.js +11 -6
  30. package/dist/bashExitReading.d.ts +10 -0
  31. package/dist/bashExitReading.js +12 -0
  32. package/dist/callerCwdCapability.d.ts +15 -0
  33. package/dist/callerCwdCapability.js +42 -0
  34. package/dist/centerWiringCapability.d.ts +1 -3
  35. package/dist/centerWiringCapability.js +18 -21
  36. package/dist/classifierStatus.js +4 -4
  37. package/dist/cloudConfigWireCaps.js +43 -21
  38. package/dist/compensations.js +1 -1
  39. package/dist/controlRouter.js +3 -10
  40. package/dist/coreValuePorts.d.ts +64 -1
  41. package/dist/coreValuePorts.js +30 -0
  42. package/dist/cycleOrder.d.ts +15 -0
  43. package/dist/cycleOrder.js +45 -0
  44. package/dist/decideFailureNote.js +4 -1
  45. package/dist/decideReceipt.d.ts +2 -1
  46. package/dist/decideReceipt.js +41 -13
  47. package/dist/declared/supportFloorDeclared.d.ts +1 -0
  48. package/dist/declared/supportFloorDeclared.js +5 -0
  49. package/dist/detachWire.d.ts +1 -4
  50. package/dist/detachWire.js +1 -1
  51. package/dist/deviceExecutorManagementCapability.d.ts +0 -1
  52. package/dist/deviceExecutorManagementCapability.js +36 -40
  53. package/dist/deviceFlowPolling.d.ts +5 -0
  54. package/dist/deviceFlowPolling.js +28 -0
  55. package/dist/deviceRebind.d.ts +88 -0
  56. package/dist/deviceRebind.js +242 -0
  57. package/dist/displayUntrusted.d.ts +1 -0
  58. package/dist/displayUntrusted.js +963 -30
  59. package/dist/engineAgentAbsence.d.ts +2 -2
  60. package/dist/engineAgentPanelStore.d.ts +8 -18
  61. package/dist/engineAgentPanelStore.js +19 -537
  62. package/dist/engineCapReader.d.ts +6 -6
  63. package/dist/engineCapReader.js +30 -43
  64. package/dist/engineCapsCache.d.ts +7 -2
  65. package/dist/engineCapsCache.js +64 -26
  66. package/dist/engineCredentialRequirement.d.ts +9 -0
  67. package/dist/engineCredentialRequirement.js +23 -0
  68. package/dist/engineEnvSourcing.d.ts +53 -0
  69. package/dist/engineEnvSourcing.js +81 -0
  70. package/dist/engineErrorCodes.d.ts +19 -4
  71. package/dist/engineErrorCodes.js +39 -21
  72. package/dist/engineIdentity.js +2 -0
  73. package/dist/engineNoticeCodes.d.ts +22 -2
  74. package/dist/engineNoticeCodes.js +73 -6
  75. package/dist/engineRefusedToolName.d.ts +1 -0
  76. package/dist/engineRefusedToolName.js +8 -0
  77. package/dist/engineWireSdk.js +2 -2
  78. package/dist/executionLaneCapability.d.ts +2 -3
  79. package/dist/executionLaneCapability.js +28 -28
  80. package/dist/fileHistoryCaptureCapability.d.ts +0 -1
  81. package/dist/fileHistoryCaptureCapability.js +13 -12
  82. package/dist/fileHistoryLegNotice.d.ts +14 -2
  83. package/dist/fileHistoryLegNotice.js +101 -15
  84. package/dist/fleet/fleetLedger.d.ts +2 -0
  85. package/dist/fleet/fleetLedger.js +74 -52
  86. package/dist/fleet/fleetProjection.d.ts +0 -3
  87. package/dist/fleet/fleetProjection.js +9 -16
  88. package/dist/fleetAgentPanelProjection.d.ts +4 -17
  89. package/dist/fleetAgentPanelProjection.js +7 -197
  90. package/dist/fleetAgentRowLike.d.ts +16 -0
  91. package/dist/fleetAgentRowLike.js +1 -0
  92. package/dist/gateOutcome.d.ts +2 -1
  93. package/dist/gateOutcome.js +33 -18
  94. package/dist/gateVocabulary.js +1 -1
  95. package/dist/generated/engineAskFaceTables.d.ts +3 -0
  96. package/dist/generated/engineAskFaceTables.js +12 -0
  97. package/dist/generated/engineFactTables.d.ts +4 -2
  98. package/dist/generated/engineFactTables.js +13 -0
  99. package/dist/generated/engineNoticeTables.d.ts +5 -0
  100. package/dist/generated/engineNoticeTables.js +7 -0
  101. package/dist/generated/sdkFactTables.d.ts +5 -0
  102. package/dist/generated/sdkFactTables.js +34 -0
  103. package/dist/generated/settingsSchemaFns.d.ts +10 -0
  104. package/dist/generated/settingsSchemaFns.js +22 -0
  105. package/dist/generated/settingsSchemaTables.d.ts +3 -0
  106. package/dist/generated/settingsSchemaTables.js +3 -0
  107. package/dist/headlessPermissionModeWire.d.ts +2 -2
  108. package/dist/headlessPermissionModeWire.js +11 -21
  109. package/dist/headlessReconnectWire.js +49 -20
  110. package/dist/hitl/allowRuleShadow.d.ts +1 -1
  111. package/dist/hitl/allowRuleShadow.js +49 -8
  112. package/dist/hitl/approvalCompleteParked.d.ts +1 -0
  113. package/dist/hitl/approvalCompleteParked.js +14 -0
  114. package/dist/hitl/approvalEndingCause.d.ts +5 -0
  115. package/dist/hitl/approvalEndingCause.js +61 -0
  116. package/dist/hitl/approvalHolds.d.ts +46 -0
  117. package/dist/hitl/approvalHolds.js +140 -0
  118. package/dist/hitl/approvalOutcomeNote.js +2 -1
  119. package/dist/hitl/approvalResolution.js +9 -1
  120. package/dist/hitl/approvalsFeed.js +23 -6
  121. package/dist/hitl/askGateWire.d.ts +2 -1
  122. package/dist/hitl/askGateWire.js +29 -1
  123. package/dist/hitl/automaticAnswerVerdict.d.ts +8 -2
  124. package/dist/hitl/automaticAnswerVerdict.js +71 -23
  125. package/dist/hitl/crashConverged.js +2 -0
  126. package/dist/hitl/decisionConflict.d.ts +3 -0
  127. package/dist/hitl/decisionConflict.js +43 -0
  128. package/dist/hitl/decisionRefusal.d.ts +23 -0
  129. package/dist/hitl/decisionRefusal.js +88 -0
  130. package/dist/hitl/frameRouter.d.ts +10 -0
  131. package/dist/hitl/frameRouter.js +71 -32
  132. package/dist/hitl/gateLedger.d.ts +8 -0
  133. package/dist/hitl/gateLedger.js +38 -0
  134. package/dist/hitl/hitlBridge.d.ts +14 -3
  135. package/dist/hitl/hitlBridge.js +75 -62
  136. package/dist/hitl/hitlHostSurface.d.ts +3 -0
  137. package/dist/hitl/hitlHostSurface.js +17 -15
  138. package/dist/hitl/livePendingAsk.d.ts +16 -6
  139. package/dist/hitl/livePendingAsk.js +36 -4
  140. package/dist/hitl/localAllowRule.js +2 -1
  141. package/dist/hitl/noAllowCause.d.ts +9 -0
  142. package/dist/hitl/noAllowCause.js +26 -0
  143. package/dist/hitl/parkExpiryJudgements.d.ts +19 -0
  144. package/dist/hitl/parkExpiryJudgements.js +46 -0
  145. package/dist/hitl/parkResolver.d.ts +3 -7
  146. package/dist/hitl/parkResolver.js +55 -28
  147. package/dist/hitl/parkRowBirthWait.js +2 -1
  148. package/dist/hitl/persistedRulesWire.d.ts +6 -1
  149. package/dist/hitl/persistedRulesWire.js +16 -4
  150. package/dist/hitl/planReviewWire.d.ts +2 -3
  151. package/dist/hitl/planReviewWire.js +86 -39
  152. package/dist/hitl/replayedApproval.d.ts +8 -0
  153. package/dist/hitl/replayedApproval.js +125 -10
  154. package/dist/hitl/resumeRunningCard.d.ts +2 -0
  155. package/dist/hitl/resumeRunningCard.js +15 -4
  156. package/dist/hitl/sessionPolicyDeliverable.d.ts +1 -1
  157. package/dist/hitl/sessionPolicyDeliverable.js +3 -8
  158. package/dist/hitl/sessionPolicyWire.js +1 -1
  159. package/dist/hitl/toolApprovalWire.d.ts +50 -5
  160. package/dist/hitl/toolApprovalWire.js +368 -56
  161. package/dist/hooksWireCaps.js +38 -6
  162. package/dist/host.d.ts +5 -0
  163. package/dist/host.js +3 -1
  164. package/dist/hostCallbackGuard.d.ts +1 -0
  165. package/dist/hostCallbackGuard.js +25 -0
  166. package/dist/humanTurnRead.d.ts +15 -1
  167. package/dist/humanTurnRead.js +28 -2
  168. package/dist/index.d.ts +45 -14
  169. package/dist/index.js +33 -12
  170. package/dist/interactiveInterrupt.d.ts +8 -0
  171. package/dist/interactiveInterrupt.js +54 -0
  172. package/dist/limitsWire.d.ts +5 -1
  173. package/dist/limitsWire.js +51 -13
  174. package/dist/liveModelCatalog.d.ts +109 -0
  175. package/dist/liveModelCatalog.js +344 -18
  176. package/dist/mcpEngineLeg.d.ts +25 -0
  177. package/dist/mcpEngineLeg.js +71 -15
  178. package/dist/mcpPanel.js +2 -1
  179. package/dist/mcpProbeCapability.d.ts +0 -1
  180. package/dist/mcpProbeCapability.js +13 -12
  181. package/dist/mcpReconnect.d.ts +1 -3
  182. package/dist/mcpReconnect.js +20 -10
  183. package/dist/memoryComplianceCapability.d.ts +0 -1
  184. package/dist/memoryComplianceCapability.js +14 -13
  185. package/dist/memoryOriginCapability.d.ts +0 -1
  186. package/dist/memoryOriginCapability.js +14 -13
  187. package/dist/memoryVerbsWire.d.ts +1 -1
  188. package/dist/memoryVerbsWire.js +4 -0
  189. package/dist/model/liveCatalogShape.d.ts +14 -0
  190. package/dist/model/liveCatalogShape.js +71 -0
  191. package/dist/model/modelSupplyRules.d.ts +1 -0
  192. package/dist/model/modelSupplyRules.js +30 -9
  193. package/dist/model/modelsPolicy.d.ts +21 -0
  194. package/dist/model/modelsPolicy.js +90 -0
  195. package/dist/modelIdentityResolvability.d.ts +4 -2
  196. package/dist/modelIdentityResolvability.js +25 -5
  197. package/dist/modelSwitchFallback.d.ts +69 -0
  198. package/dist/modelSwitchFallback.js +206 -0
  199. package/dist/notifications.js +12 -11
  200. package/dist/outputStyleSeatCapability.d.ts +15 -0
  201. package/dist/outputStyleSeatCapability.js +42 -0
  202. package/dist/ownKey.d.ts +7 -0
  203. package/dist/ownKey.js +58 -0
  204. package/dist/panelReduce.d.ts +114 -0
  205. package/dist/panelReduce.js +1135 -0
  206. package/dist/panelStateHolder.d.ts +17 -0
  207. package/dist/panelStateHolder.js +201 -0
  208. package/dist/peerLaneCapability.d.ts +0 -1
  209. package/dist/peerLaneCapability.js +15 -14
  210. package/dist/permissionModesCapability.d.ts +0 -1
  211. package/dist/permissionModesCapability.js +5 -10
  212. package/dist/permissionRuleIssue.js +1 -1
  213. package/dist/permissionRulesWriteCapability.d.ts +0 -1
  214. package/dist/permissionRulesWriteCapability.js +15 -14
  215. package/dist/permissionsAllowGrantCapability.d.ts +2 -1
  216. package/dist/permissionsAllowGrantCapability.js +35 -19
  217. package/dist/permissionsDeclaration.d.ts +16 -1
  218. package/dist/permissionsDeclaration.js +142 -15
  219. package/dist/printToolResultFrame.js +2 -10
  220. package/dist/promptDelivery.js +0 -8
  221. package/dist/protocolSegment.d.ts +1 -0
  222. package/dist/protocolSegment.js +13 -1
  223. package/dist/request/taskRequest.d.ts +11 -3
  224. package/dist/request/taskRequest.js +13 -1
  225. package/dist/resultFrameKeys.d.ts +4 -0
  226. package/dist/resultFrameKeys.js +13 -0
  227. package/dist/resumeRefusalCopy.d.ts +18 -1
  228. package/dist/resumeRefusalCopy.js +132 -31
  229. package/dist/retryStatus.js +6 -4
  230. package/dist/rewindArchiveCapability.d.ts +2 -1
  231. package/dist/rewindArchiveCapability.js +28 -15
  232. package/dist/rewindEngineAction.d.ts +21 -0
  233. package/dist/rewindEngineAction.js +36 -0
  234. package/dist/rewindWireCaps.d.ts +2 -1
  235. package/dist/rewindWireCaps.js +1 -0
  236. package/dist/{hitl/rosterMountedNames.d.ts → rosterMountedNames.d.ts} +1 -1
  237. package/dist/runCancelContext.js +2 -1
  238. package/dist/runTerminal.d.ts +0 -11
  239. package/dist/runTerminal.js +4 -27
  240. package/dist/sdkRegistryTransit.d.ts +2 -1
  241. package/dist/sdkRegistryTransit.js +1 -0
  242. package/dist/sealedKeyCapability.d.ts +0 -1
  243. package/dist/sealedKeyCapability.js +19 -20
  244. package/dist/seatContract.d.ts +85 -28
  245. package/dist/seatContract.js +512 -148
  246. package/dist/sessionIdSegment.d.ts +1 -0
  247. package/dist/sessionIdSegment.js +11 -0
  248. package/dist/sessionMemoryErase.d.ts +1 -1
  249. package/dist/sessionMemoryErase.js +6 -1
  250. package/dist/sessionMemoryStatus.js +3 -2
  251. package/dist/sessionPolicyCapability.d.ts +0 -1
  252. package/dist/sessionPolicyCapability.js +14 -13
  253. package/dist/sessionReadRedactionCapability.d.ts +15 -0
  254. package/dist/sessionReadRedactionCapability.js +42 -0
  255. package/dist/sessionSyncFileHistoryCapability.d.ts +0 -1
  256. package/dist/sessionSyncFileHistoryCapability.js +13 -12
  257. package/dist/skillToolListsCapability.d.ts +0 -1
  258. package/dist/skillToolListsCapability.js +13 -12
  259. package/dist/skillsWireCaps.d.ts +4 -0
  260. package/dist/skillsWireCaps.js +66 -1
  261. package/dist/sqlEngineCapability.d.ts +0 -1
  262. package/dist/sqlEngineCapability.js +21 -21
  263. package/dist/steerPriorityCapability.d.ts +0 -1
  264. package/dist/steerPriorityCapability.js +18 -19
  265. package/dist/storePostureCapability.d.ts +1 -1
  266. package/dist/storePostureCapability.js +16 -16
  267. package/dist/streamDrainingLegs.d.ts +6 -0
  268. package/dist/streamDrainingLegs.js +23 -0
  269. package/dist/subagent/agentStateDetail.d.ts +1 -0
  270. package/dist/subagent/agentStateDetail.js +41 -0
  271. package/dist/subagent/engineCompactWire.d.ts +15 -0
  272. package/dist/subagent/engineCompactWire.js +82 -45
  273. package/dist/subagent/engineDelegatedPrompt.js +10 -6
  274. package/dist/subagent/engineSubagentOutput.d.ts +0 -1
  275. package/dist/subagent/engineSubagentOutput.js +5 -20
  276. package/dist/subagent/engineSubagentTail.d.ts +0 -1
  277. package/dist/subagent/engineSubagentTail.js +7 -32
  278. package/dist/subagentContentStore.js +3 -3
  279. package/dist/supportFloor.js +2 -5
  280. package/dist/taskRequestWords.d.ts +2 -4
  281. package/dist/taskRequestWords.js +3 -2
  282. package/dist/terminalStatuses.d.ts +30 -0
  283. package/dist/terminalStatuses.js +67 -0
  284. package/dist/toolResult.d.ts +5 -0
  285. package/dist/toolResult.js +88 -36
  286. package/dist/types/engineState.d.ts +2 -1
  287. package/dist/usageAnalytics.d.ts +146 -0
  288. package/dist/usageAnalytics.js +311 -0
  289. package/dist/userAttachmentEnvelope.d.ts +22 -1
  290. package/dist/userAttachmentEnvelope.js +90 -2
  291. package/dist/userInvokedSkillsCapability.d.ts +0 -1
  292. package/dist/userInvokedSkillsCapability.js +13 -12
  293. package/dist/webSearchBackendCapability.d.ts +0 -1
  294. package/dist/webSearchBackendCapability.js +20 -19
  295. package/dist/webSearchWireCaps.js +3 -11
  296. package/dist/wireErrorTriage.d.ts +11 -0
  297. package/dist/wireErrorTriage.js +35 -0
  298. package/dist/wireFailureShape.d.ts +10 -0
  299. package/dist/wireFailureShape.js +72 -5
  300. package/dist/wireRefusalCopy.d.ts +6 -1
  301. package/dist/wireRefusalCopy.js +23 -25
  302. package/dist/wiringInstructionsAttribution.d.ts +10 -0
  303. package/dist/wiringInstructionsAttribution.js +67 -0
  304. package/dist/workflowClient.js +19 -2
  305. package/dist/workflowsJournalCapability.d.ts +0 -1
  306. package/dist/workflowsJournalCapability.js +13 -12
  307. package/dist/writeProtectionCapability.d.ts +0 -1
  308. package/dist/writeProtectionCapability.js +26 -26
  309. package/docs/INTEGRATION-CLIENTS.md +1733 -52
  310. package/package.json +5 -5
  311. package/dist/askSurvivesStandingAnswer.d.ts +0 -13
  312. package/dist/askSurvivesStandingAnswer.js +0 -53
  313. package/dist/engineCapsGenerationGuard.d.ts +0 -4
  314. package/dist/engineCapsGenerationGuard.js +0 -19
  315. package/dist/hitl/askSurvivesPosture.d.ts +0 -20
  316. package/dist/hitl/askSurvivesPosture.js +0 -48
  317. package/dist/panelRunningHistory.d.ts +0 -22
  318. package/dist/panelRunningHistory.js +0 -82
  319. package/dist/registryConflict.d.ts +0 -3
  320. package/dist/registryConflict.js +0 -44
  321. /package/dist/{hitl/rosterMountedNames.js → rosterMountedNames.js} +0 -0
@@ -1,4 +1,7 @@
1
1
  import { PERMISSION_MODE_WORDS, REASONING_EFFORT_WORDS } from "./taskRequestWords.js";
2
+ import { liveDefaultModelCopy, liveModelRowCopy } from "./model/liveCatalogShape.js";
3
+ import { REWIND_MODES } from "./rewindWireCaps.js";
4
+ import { ownDataField, ownDataRefusalKeyOf, ownSendableField } from "./ownKey.js";
2
5
  const bad = (reason, field) => field === undefined ? { reason } : { reason, field };
3
6
  const nested = (prefix, verdict) => {
4
7
  const path = verdict.field === undefined
@@ -13,6 +16,63 @@ const isObject = (v) => typeof v === "object" && v !== null;
13
16
  const isAbsent = (v) => typeof v === "undefined";
14
17
  const optionalString = (v) => isAbsent(v) || typeof v === "string";
15
18
  const inTuple = (tuple, v) => tuple.includes(v);
19
+ const own = (o, k) => ownSendableField(o, k);
20
+ const ownItems = (a) => {
21
+ const n = ownDataField(a, "length");
22
+ const out = [];
23
+ if (typeof n !== "number")
24
+ return out;
25
+ for (let i = 0; i < n; i += 1)
26
+ out.push(own(a, String(i)));
27
+ return out;
28
+ };
29
+ const firstAccessorPath = (root) => {
30
+ const seen = new Set();
31
+ const stack = [[root, ""]];
32
+ while (stack.length > 0) {
33
+ const [v, path] = stack.pop();
34
+ if (typeof v !== "object" || v === null || seen.has(v))
35
+ continue;
36
+ seen.add(v);
37
+ for (const k of Reflect.ownKeys(v)) {
38
+ if (typeof k !== "string")
39
+ continue;
40
+ const d = Reflect.getOwnPropertyDescriptor(v, k);
41
+ if (d === undefined)
42
+ continue;
43
+ const at = path === "" ? k : `${path}.${k}`;
44
+ if (!Object.hasOwn(d, "value"))
45
+ return at;
46
+ stack.push([d.value, at]);
47
+ }
48
+ }
49
+ return undefined;
50
+ };
51
+ const NOT_PLAIN_DATA = "must be a plain enumerable data property (accessors are refused and never executed)";
52
+ const seatCheck = (fn) => (v) => {
53
+ try {
54
+ const at = firstAccessorPath(v);
55
+ if (at !== undefined)
56
+ return bad(NOT_PLAIN_DATA, at);
57
+ return fn(v);
58
+ }
59
+ catch (e) {
60
+ const key = ownDataRefusalKeyOf(e);
61
+ return key !== undefined ? bad(NOT_PLAIN_DATA, key) : bad("payload could not be read");
62
+ }
63
+ };
64
+ const seatCheckAt = (fn) => (v, field) => {
65
+ try {
66
+ const at = firstAccessorPath(v);
67
+ if (at !== undefined)
68
+ return bad(NOT_PLAIN_DATA, `${field}.${at}`);
69
+ return fn(v, field);
70
+ }
71
+ catch (e) {
72
+ const key = ownDataRefusalKeyOf(e);
73
+ return key !== undefined ? bad(NOT_PLAIN_DATA, `${field}.${key}`) : bad("payload could not be read", field);
74
+ }
75
+ };
16
76
  export const TOOL_PERMISSION_REQUEST_ID_DOMAINS = Object.freeze([
17
77
  "live:",
18
78
  "durable:",
@@ -72,325 +132,584 @@ export const HITL_RESOLUTION_OUTCOMES = [
72
132
  "decline",
73
133
  "cancel",
74
134
  ];
135
+ export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind"]);
136
+ const notReported = () => Object.freeze({ kind: "not_reported" });
137
+ const malformedReading = () => Object.freeze({ kind: "malformed" });
138
+ const reported = (available) => Object.freeze({ kind: "reported", available });
139
+ export function seatCapability(state, name) {
140
+ if (state === undefined)
141
+ return notReported();
142
+ try {
143
+ if (typeof state !== "object" || state === null || Array.isArray(state))
144
+ return malformedReading();
145
+ const proto = Object.getPrototypeOf(state);
146
+ if (proto !== Object.prototype && proto !== null)
147
+ return malformedReading();
148
+ const desc = Object.getOwnPropertyDescriptor(state, name);
149
+ if (desc === undefined)
150
+ return notReported();
151
+ if (!("value" in desc))
152
+ return malformedReading();
153
+ const v = desc.value;
154
+ if (v === undefined)
155
+ return notReported();
156
+ if (typeof v === "boolean")
157
+ return reported(v);
158
+ return malformedReading();
159
+ }
160
+ catch {
161
+ return malformedReading();
162
+ }
163
+ }
164
+ export function watchSeatCapability(store, name, onReading) {
165
+ if (store === undefined || store === null) {
166
+ onReading(notReported());
167
+ return () => { };
168
+ }
169
+ let active = true;
170
+ let off;
171
+ try {
172
+ if (typeof store !== "object" || typeof store.onStateChange !== "function" || typeof store.getStateSync !== "function") {
173
+ onReading(malformedReading());
174
+ return () => { };
175
+ }
176
+ off = store.onStateChange((state) => {
177
+ if (active)
178
+ onReading(seatCapability(state, name));
179
+ });
180
+ }
181
+ catch {
182
+ onReading(malformedReading());
183
+ return () => { };
184
+ }
185
+ let current;
186
+ try {
187
+ current = seatCapability(store.getStateSync(), name);
188
+ }
189
+ catch {
190
+ current = malformedReading();
191
+ }
192
+ if (active)
193
+ onReading(current);
194
+ return () => {
195
+ if (!active)
196
+ return;
197
+ active = false;
198
+ try {
199
+ if (typeof off === "function")
200
+ off();
201
+ }
202
+ catch {
203
+ }
204
+ };
205
+ }
206
+ const SEAT_CAPABILITY_PHRASES = Object.freeze({
207
+ pickFolder: Object.freeze({ action: "Opening a folder", ability: "show a folder picker", support: "folder picker support" }),
208
+ rewind: Object.freeze({ action: "Rewinding to an earlier message", ability: "rewind this session", support: "rewind support" }),
209
+ });
210
+ export function seatCapabilityUnavailableDetail(name, reading) {
211
+ const phrase = Object.hasOwn(SEAT_CAPABILITY_PHRASES, name)
212
+ ? SEAT_CAPABILITY_PHRASES[name]
213
+ : { action: "This action", ability: "do this", support: "support for it" };
214
+ let kind;
215
+ let available;
216
+ try {
217
+ kind = reading?.kind;
218
+ available = reading?.available;
219
+ }
220
+ catch {
221
+ kind = undefined;
222
+ }
223
+ if (kind === "reported" && available === true)
224
+ return undefined;
225
+ if (kind === "reported" && available === false)
226
+ return `${phrase.action} isn't available: this app reports it can't ${phrase.ability}.`;
227
+ if (kind === "not_reported")
228
+ return `${phrase.action} isn't available: this app hasn't reported ${phrase.support}.`;
229
+ return `${phrase.action} isn't available: this app's support report couldn't be read.`;
230
+ }
75
231
  export const PERMISSION_MODE_INTENTS = [...PERMISSION_MODE_WORDS];
76
232
  export const ATTACHMENT_IDS_PER_TASK_CAP = 16;
77
233
  export const SEAT_REASONING_EFFORTS = [...REASONING_EFFORT_WORDS];
78
234
  export const SEAT_TURN_SETTINGS_KEYS = ["ultracode"];
235
+ export const SEAT_TURN_SETTINGS_ORIGINS = Object.freeze({
236
+ ultracode: Object.freeze({ carriedBy: "renderer" }),
237
+ webSearch: Object.freeze({ hostSupplied: "联网检索的每请求配置来自宿主的设置源(可能带检索服务的凭据与私网地址);渲染端没有设置文件,也不该持有凭据" }),
238
+ hooks: Object.freeze({ hostSupplied: "hooks 表来自宿主的设置文件(宿主经设置端口与 hooksForWire 投影);渲染端没有设置文件、也不执行本机 hook" }),
239
+ resolved: Object.freeze({ hostSupplied: "设置解析器的生效快照(hooks / env / model / 已解析权限)由宿主跑解析器得出;渲染端没有设置源可解析" }),
240
+ outputStyle: Object.freeze({ hostSupplied: "输出风格正文由宿主的兜底层随请求带(风格文件在宿主);渲染端只选名字,不持正文" }),
241
+ });
242
+ export const SEAT_REWIND_INTENT_KEYS = ["mode", "targetMessageUuid"];
79
243
  export const ATTACHMENT_UPLOAD_REQUEST_KEYS = ["name", "mimeType", "bytes"];
80
244
  export const SESSION_SEARCH_RESULT_KEYS = ["sessionId", "title", "matches"];
81
245
  export const GET_TRANSCRIPT_RESULT_KEYS = ["sessionId", "messages"];
82
- const checkLocalSessionRecord = (s) => {
246
+ const checkLocalSessionRecord = seatCheck((s) => {
83
247
  if (!isObject(s))
84
248
  return bad("session record is not an object");
85
- if (typeof s.sessionId !== "string")
249
+ if (typeof own(s, "sessionId") !== "string")
86
250
  return bad("sessionId must be a string", "sessionId");
87
- if (!optionalString(s.engineSessionId))
251
+ if (!optionalString(own(s, "engineSessionId")))
88
252
  return bad("engineSessionId must be a string when present", "engineSessionId");
89
- if (!optionalString(s.model))
253
+ if (!optionalString(own(s, "model")))
90
254
  return bad("model must be a string when present", "model");
91
- if (!optionalString(s.title))
255
+ if (!optionalString(own(s, "title")))
92
256
  return bad("title must be a string when present", "title");
93
- if (typeof s.isRunning !== "boolean")
257
+ const cwd = own(s, "cwd");
258
+ if (!isAbsent(cwd) && (typeof cwd !== "string" || cwd.length === 0)) {
259
+ return bad("cwd must be a non-empty path string when present (absent = no folder chosen)", "cwd");
260
+ }
261
+ if (typeof own(s, "isRunning") !== "boolean")
94
262
  return bad("isRunning must be a boolean", "isRunning");
95
- if (typeof s.createdAt !== "string")
263
+ if (typeof own(s, "createdAt") !== "string")
96
264
  return bad("createdAt must be an ISO-8601 string", "createdAt");
97
- if (!optionalString(s.lastActivityAt))
265
+ if (!optionalString(own(s, "lastActivityAt")))
98
266
  return bad("lastActivityAt must be a string when present", "lastActivityAt");
99
- if (!isAbsent(s.queuedMessages)) {
100
- const q = s.queuedMessages;
101
- const okQueue = Array.isArray(q) && q.every((row) => isObject(row) && typeof row.uuid === "string" && typeof row.text === "string");
267
+ const q = own(s, "queuedMessages");
268
+ if (!isAbsent(q)) {
269
+ const okQueue = Array.isArray(q) && ownItems(q).every((row) => isObject(row) && typeof own(row, "uuid") === "string" && typeof own(row, "text") === "string");
102
270
  if (!okQueue)
103
271
  return bad("queuedMessages must be an array of {uuid,text}", "queuedMessages");
104
272
  }
105
- if (!isAbsent(s.parked) && typeof s.parked !== "boolean") {
273
+ const parked = own(s, "parked");
274
+ if (!isAbsent(parked) && typeof parked !== "boolean") {
106
275
  return bad("parked must be a boolean when present", "parked");
107
276
  }
108
277
  return true;
109
- };
278
+ });
110
279
  export function isLocalSessionRecord(s) {
111
280
  return checkLocalSessionRecord(s) === true;
112
281
  }
113
- const checkToctouBinding = (v) => {
282
+ const checkToctouBinding = seatCheck((v) => {
114
283
  if (!isObject(v))
115
284
  return bad("toctouBinding must be an object", "toctouBinding");
116
- if (typeof v.callId !== "string")
285
+ if (typeof own(v, "callId") !== "string")
117
286
  return bad("toctouBinding.callId must be a string", "toctouBinding.callId");
118
- if (typeof v.inputHash !== "string")
287
+ if (typeof own(v, "inputHash") !== "string")
119
288
  return bad("toctouBinding.inputHash must be a string", "toctouBinding.inputHash");
120
289
  return true;
121
- };
122
- const checkToolPermissionRequest = (r) => {
290
+ });
291
+ const checkToolPermissionRequest = seatCheck((r) => {
123
292
  if (!isObject(r))
124
293
  return bad("tool permission request is not an object");
125
- if (typeof r.requestId !== "string")
294
+ const requestId = own(r, "requestId");
295
+ if (typeof requestId !== "string")
126
296
  return bad("requestId must be a string", "requestId");
127
- if (toolPermissionRequestIdDomain(r.requestId) === undefined) {
297
+ if (toolPermissionRequestIdDomain(requestId) === undefined) {
128
298
  return bad(`requestId must carry a registered domain prefix (${TOOL_PERMISSION_REQUEST_ID_DOMAINS.join("|")})`, "requestId");
129
299
  }
130
- if (typeof r.sessionId !== "string")
300
+ if (typeof own(r, "sessionId") !== "string")
131
301
  return bad("sessionId must be a string", "sessionId");
132
- if (!isAbsent(r.toolName) && r.toolName !== null && typeof r.toolName !== "string") {
302
+ const toolName = own(r, "toolName");
303
+ if (!isAbsent(toolName) && toolName !== null && typeof toolName !== "string") {
133
304
  return bad("toolName must be a string or null when present", "toolName");
134
305
  }
135
- if (!isAbsent(r.toolCallId) && r.toolCallId !== null && typeof r.toolCallId !== "string") {
306
+ const toolCallId = own(r, "toolCallId");
307
+ if (!isAbsent(toolCallId) && toolCallId !== null && typeof toolCallId !== "string") {
136
308
  return bad("toolCallId must be a string or null when present", "toolCallId");
137
309
  }
138
- if (!optionalString(r.message))
310
+ if (!optionalString(own(r, "message")))
139
311
  return bad("message must be a string when present", "message");
140
- if (!isAbsent(r.toctouBinding)) {
141
- const verdict = checkToctouBinding(r.toctouBinding);
312
+ const toctouBinding = own(r, "toctouBinding");
313
+ if (!isAbsent(toctouBinding)) {
314
+ const verdict = checkToctouBinding(toctouBinding);
142
315
  if (verdict !== true)
143
316
  return verdict;
144
317
  }
145
- if (!isAbsent(r.createdAtMs) && typeof r.createdAtMs !== "number") {
318
+ const createdAtMs = own(r, "createdAtMs");
319
+ if (!isAbsent(createdAtMs) && typeof createdAtMs !== "number") {
146
320
  return bad("createdAtMs must be a number (epoch ms) when present", "createdAtMs");
147
321
  }
148
322
  return true;
149
- };
323
+ });
150
324
  export function isToolPermissionRequest(r) {
151
325
  return checkToolPermissionRequest(r) === true;
152
326
  }
153
- const checkLaneProof = (v, field) => {
327
+ const checkLaneProof = seatCheckAt((v, field) => {
154
328
  if (!isObject(v))
155
329
  return bad("laneProof must be an object", field);
156
- const lane = v.lane;
330
+ const lane = own(v, "lane");
157
331
  if (typeof lane !== "string" || !inTuple(LANE_PROOF_LANE_TUPLE, lane)) {
158
332
  return bad(`laneProof.lane must be one of ${LANE_PROOF_LANE_TUPLE.join("|")}`, `${field}.lane`);
159
333
  }
160
- if (lane === "subagent" && typeof v.parentToolCallId !== "string") {
334
+ if (lane === "subagent" && typeof own(v, "parentToolCallId") !== "string") {
161
335
  return bad("subagent laneProof needs parentToolCallId", `${field}.parentToolCallId`);
162
336
  }
163
- if (lane === "workflow" && (typeof v.via !== "string" || typeof v.key !== "string")) {
337
+ if (lane === "workflow" && (typeof own(v, "via") !== "string" || typeof own(v, "key") !== "string")) {
164
338
  return bad("workflow laneProof needs via + key", `${field}.via`);
165
339
  }
166
340
  return true;
167
- };
168
- const checkSeatChromeEnvelope = (v, field) => {
341
+ });
342
+ const checkSeatChromeEnvelope = seatCheckAt((v, field) => {
169
343
  if (!isObject(v))
170
344
  return bad("chrome must be an object", field);
171
- const kind = v.kind;
345
+ const kind = own(v, "kind");
172
346
  if (typeof kind !== "string")
173
347
  return bad("chrome.kind must be a string", `${field}.kind`);
174
348
  if (!inTuple(CHROME_EVENT_KIND_TUPLE, kind)) {
175
349
  return bad(`chrome.kind is not a renderer-wired arm (${CHROME_EVENT_KIND_TUPLE.join("|")})`, `${field}.kind`);
176
350
  }
177
- return checkLaneProof(v.laneProof, `${field}.laneProof`);
178
- };
179
- const checkLocalSessionEvent = (v) => {
351
+ return checkLaneProof(own(v, "laneProof"), `${field}.laneProof`);
352
+ });
353
+ const checkLocalSessionEvent = seatCheck((v) => {
180
354
  if (!isObject(v))
181
355
  return bad("event is not an object");
182
- const type = v.type;
356
+ const type = own(v, "type");
183
357
  if (typeof type !== "string")
184
358
  return bad("type must be a string", "type");
185
359
  if (!inTuple(SEAT_EVENT_TYPE_TUPLE, type)) {
186
360
  return bad(`type is not a registered seat event name (${SEAT_EVENT_TYPE_TUPLE.join("|")})`, "type");
187
361
  }
188
- if (typeof v.sessionId !== "string")
362
+ if (typeof own(v, "sessionId") !== "string")
189
363
  return bad("sessionId must be a string", "sessionId");
190
- if (!isAbsent(v.messages) && !Array.isArray(v.messages))
364
+ const messages = own(v, "messages");
365
+ if (!isAbsent(messages) && !Array.isArray(messages))
191
366
  return bad("messages must be an array", "messages");
192
- if (!optionalString(v.error))
367
+ if (!optionalString(own(v, "error")))
193
368
  return bad("error must be a string when present", "error");
194
- if (!optionalString(v.errorCategory))
369
+ if (!optionalString(own(v, "errorCategory")))
195
370
  return bad("errorCategory must be a string when present", "errorCategory");
196
- if (!isAbsent(v.code) && typeof v.code !== "number")
371
+ const code = own(v, "code");
372
+ if (!isAbsent(code) && typeof code !== "number")
197
373
  return bad("code must be a number when present", "code");
198
- if (!isAbsent(v.request)) {
199
- const verdict = checkToolPermissionRequest(v.request);
374
+ const request = own(v, "request");
375
+ if (!isAbsent(request)) {
376
+ const verdict = checkToolPermissionRequest(request);
200
377
  if (verdict !== true)
201
378
  return nested("request", verdict);
202
379
  }
203
- if (!optionalString(v.data))
380
+ if (!optionalString(own(v, "data")))
204
381
  return bad("data must be a string when present", "data");
205
- if (!isAbsent(v.sources)) {
206
- const okSources = Array.isArray(v.sources) && v.sources.every((t) => typeof t === "string");
382
+ const sources = own(v, "sources");
383
+ if (!isAbsent(sources)) {
384
+ const okSources = Array.isArray(sources) && ownItems(sources).every((t) => typeof t === "string");
207
385
  if (!okSources)
208
386
  return bad("sources must be a string[]", "sources");
209
387
  }
210
- if (!isAbsent(v.permissionMode)) {
211
- const mode = v.permissionMode;
388
+ const mode = own(v, "permissionMode");
389
+ if (!isAbsent(mode)) {
212
390
  if (typeof mode !== "string" || !inTuple(PERMISSION_MODE_INTENTS, mode)) {
213
391
  return bad(`permissionMode must be one of ${PERMISSION_MODE_INTENTS.join("|")}`, "permissionMode");
214
392
  }
215
393
  }
216
- if (!isAbsent(v.session)) {
217
- const verdict = checkLocalSessionRecord(v.session);
394
+ const session = own(v, "session");
395
+ if (!isAbsent(session)) {
396
+ const verdict = checkLocalSessionRecord(session);
218
397
  if (verdict !== true)
219
398
  return nested("session", verdict);
220
399
  }
221
- if (!optionalString(v.userMessageUuid))
400
+ if (!optionalString(own(v, "userMessageUuid")))
222
401
  return bad("userMessageUuid must be a string when present", "userMessageUuid");
223
- if (!isAbsent(v.hasPreClearSession) && typeof v.hasPreClearSession !== "boolean") {
402
+ const hasPreClearSession = own(v, "hasPreClearSession");
403
+ if (!isAbsent(hasPreClearSession) && typeof hasPreClearSession !== "boolean") {
224
404
  return bad("hasPreClearSession must be a boolean when present", "hasPreClearSession");
225
405
  }
226
- if (!optionalString(v.requestId))
406
+ if (!optionalString(own(v, "requestId")))
227
407
  return bad("requestId must be a string when present", "requestId");
228
- if (!optionalString(v.outcome))
408
+ const outcome = own(v, "outcome");
409
+ if (!optionalString(outcome))
229
410
  return bad("outcome must be a string when present", "outcome");
230
- if (!isAbsent(v.chrome)) {
231
- const verdict = checkSeatChromeEnvelope(v.chrome, "chrome");
411
+ const parked = own(v, "parked");
412
+ if (!isAbsent(parked)) {
413
+ if (parked !== true)
414
+ return bad("parked must be the literal true when present (absent = no park evidence)", "parked");
415
+ if (type !== "tool_permission_resolved" || outcome !== "expired") {
416
+ return bad('parked is only allowed on a tool_permission_resolved event whose outcome is "expired"', "parked");
417
+ }
418
+ }
419
+ const chrome = own(v, "chrome");
420
+ if (!isAbsent(chrome)) {
421
+ const verdict = checkSeatChromeEnvelope(chrome, "chrome");
232
422
  if (verdict !== true)
233
423
  return nested("chrome", verdict);
234
424
  }
235
425
  return true;
236
- };
426
+ });
237
427
  export function isLocalSessionEvent(v) {
238
428
  return checkLocalSessionEvent(v) === true;
239
429
  }
240
- const checkAttachmentUploadReceipt = (v) => {
430
+ const checkAttachmentUploadReceipt = seatCheck((v) => {
241
431
  if (!isObject(v))
242
432
  return bad("upload receipt is not an object");
243
- if (typeof v.id !== "string")
433
+ if (typeof own(v, "id") !== "string")
244
434
  return bad("id must be a string", "id");
245
- if (typeof v.name !== "string")
435
+ if (typeof own(v, "name") !== "string")
246
436
  return bad("name must be a string", "name");
247
- if (typeof v.mime !== "string")
437
+ if (typeof own(v, "mime") !== "string")
248
438
  return bad("mime must be a string", "mime");
249
- if (typeof v.sha256 !== "string")
439
+ if (typeof own(v, "sha256") !== "string")
250
440
  return bad("sha256 must be a string", "sha256");
251
- if (typeof v.sizeBytes !== "number")
441
+ if (typeof own(v, "sizeBytes") !== "number")
252
442
  return bad("sizeBytes must be a number", "sizeBytes");
253
443
  return true;
254
- };
444
+ });
255
445
  export function isAttachmentUploadReceipt(v) {
256
446
  return checkAttachmentUploadReceipt(v) === true;
257
447
  }
258
- const checkSeatModelInfo = (m, index) => {
259
- if (!isObject(m))
260
- return bad(`models[${index}] is not an object`, "models");
261
- if (typeof m.id !== "string")
262
- return bad(`models[${index}].id must be a string`, "models");
263
- if (!optionalString(m.name))
264
- return bad(`models[${index}].name must be a string when present`, "models");
265
- if (!optionalString(m.provider))
266
- return bad(`models[${index}].provider must be a string when present`, "models");
267
- if (!isAbsent(m.contextWindow) && typeof m.contextWindow !== "number") {
268
- return bad(`models[${index}].contextWindow must be a number when present`, "models");
269
- }
270
- if (!isAbsent(m.maxOutputTokens) && typeof m.maxOutputTokens !== "number") {
271
- return bad(`models[${index}].maxOutputTokens must be a number when present`, "models");
272
- }
273
- return true;
274
- };
275
- const checkApplyModelConfigResult = (v) => {
448
+ const checkApplyModelConfigResult = seatCheck((v) => {
276
449
  if (!isObject(v))
277
450
  return bad("applyModelConfig result is not an object");
278
- if (typeof v.ok !== "boolean")
451
+ const ok = own(v, "ok");
452
+ if (typeof ok !== "boolean")
279
453
  return bad("ok must be a boolean", "ok");
280
- if (typeof v.requiresRestart !== "boolean")
454
+ if (typeof own(v, "requiresRestart") !== "boolean")
281
455
  return bad("requiresRestart must be a boolean", "requiresRestart");
282
- if (v.ok === false && (typeof v.reason !== "string" || v.reason.length === 0)) {
456
+ const reason = own(v, "reason");
457
+ if (ok === false && (typeof reason !== "string" || reason.length === 0)) {
283
458
  return bad("reason must be a non-empty string when ok is false", "reason");
284
459
  }
285
- if (v.reason !== undefined && typeof v.reason !== "string")
460
+ if (reason !== undefined && typeof reason !== "string")
286
461
  return bad("reason must be a string when present", "reason");
287
462
  return true;
288
- };
289
- const checkSeatModelCatalog = (v) => {
290
- if (!isObject(v))
463
+ });
464
+ const checkLiveModelCatalog = seatCheck((v) => {
465
+ if (!isObject(v) || Array.isArray(v))
291
466
  return bad("model catalog is not an object");
292
- const models = v.models;
467
+ const models = own(v, "models");
293
468
  if (!Array.isArray(models))
294
469
  return bad("models must be an array", "models");
295
- for (let i = 0; i < models.length; i += 1) {
296
- const verdict = checkSeatModelInfo(models[i], i);
297
- if (verdict !== true)
298
- return verdict;
470
+ const rows = ownItems(models);
471
+ const names = new Set();
472
+ for (let i = 0; i < rows.length; i += 1) {
473
+ const row = liveModelRowCopy(rows[i]);
474
+ if (row === undefined)
475
+ return bad(`models[${i}] is not a catalog row (an object whose name is a non-empty string, JSON values only)`, `models[${i}]`);
476
+ if (names.has(row.name))
477
+ return bad(`models[${i}] repeats the name of an earlier row`, `models[${i}].name`);
478
+ names.add(row.name);
479
+ }
480
+ const dflt = own(v, "default");
481
+ if (typeof dflt !== "string" || dflt.length === 0)
482
+ return bad("default must be a non-empty string", "default");
483
+ const defaultModel = own(v, "defaultModel");
484
+ if (!isAbsent(defaultModel) && liveDefaultModelCopy(defaultModel) === undefined) {
485
+ return bad("defaultModel must be {id: non-empty string, name?: non-empty string} when present", "defaultModel");
299
486
  }
300
- if (!optionalString(v.defaultId))
301
- return bad("defaultId must be a string when present", "defaultId");
302
487
  return true;
303
- };
304
- export function isSeatModelCatalog(v) {
305
- return checkSeatModelCatalog(v) === true;
488
+ });
489
+ const checkSeatRewindIntent = seatCheck((v) => {
490
+ if (!isObject(v) || Array.isArray(v))
491
+ return bad("rewind must be an object {mode, targetMessageUuid}");
492
+ for (const k of Object.keys(v)) {
493
+ if (!inTuple(SEAT_REWIND_INTENT_KEYS, k))
494
+ return bad(`unknown key (closed shape: ${SEAT_REWIND_INTENT_KEYS.join(", ")})`, k);
495
+ }
496
+ const mode = own(v, "mode");
497
+ if (typeof mode !== "string" || !inTuple(REWIND_MODES, mode))
498
+ return bad(`mode must be one of ${REWIND_MODES.join("|")}`, "mode");
499
+ const target = own(v, "targetMessageUuid");
500
+ if (typeof target !== "string" || target.length === 0) {
501
+ return bad("targetMessageUuid must be a non-empty string", "targetMessageUuid");
502
+ }
503
+ return true;
504
+ });
505
+ const checkSeatTurnSettings = seatCheck((v) => {
506
+ if (!isObject(v) || Array.isArray(v))
507
+ return bad("settings must be an object");
508
+ for (const k of Object.keys(v)) {
509
+ if (!inTuple(SEAT_TURN_SETTINGS_KEYS, k)) {
510
+ const host = Object.hasOwn(SEAT_TURN_SETTINGS_ORIGINS, k);
511
+ return bad(host ? "this settings key is supplied by the host, not carried by the seat" : `unknown key (closed shape: ${SEAT_TURN_SETTINGS_KEYS.join(", ")})`, k);
512
+ }
513
+ }
514
+ const ultracode = own(v, "ultracode");
515
+ if (!isAbsent(ultracode) && typeof ultracode !== "boolean")
516
+ return bad("ultracode must be a boolean when present", "ultracode");
517
+ return true;
518
+ });
519
+ const checkRetainSubagentSessions = seatCheck((v) => {
520
+ if (typeof v === "boolean")
521
+ return true;
522
+ if (!isObject(v) || Array.isArray(v))
523
+ return bad("retainSubagentSessions must be a boolean or {ttlMs?, max?}");
524
+ for (const k of Object.keys(v)) {
525
+ if (k !== "ttlMs" && k !== "max")
526
+ return bad("unknown key (closed shape: ttlMs, max)", k);
527
+ const n = own(v, k);
528
+ if (!isAbsent(n) && (typeof n !== "number" || !Number.isSafeInteger(n) || n < 0))
529
+ return bad(`${k} must be a non-negative integer when present`, k);
530
+ }
531
+ return true;
532
+ });
533
+ export function checkSendMessageRequest(v) {
534
+ try {
535
+ if (!isObject(v) || Array.isArray(v))
536
+ return bad("sendMessage request is not an object");
537
+ const at = firstAccessorPath(v);
538
+ if (at !== undefined)
539
+ return bad(NOT_PLAIN_DATA, at);
540
+ const body = {};
541
+ for (const k of Object.keys(v)) {
542
+ if (!inTuple(SEND_MESSAGE_REQUEST_KEYS, k))
543
+ return bad(`unknown key (closed shape: ${SEND_MESSAGE_REQUEST_KEYS.join(", ")})`, k);
544
+ body[k] = own(v, k);
545
+ }
546
+ if (typeof body.sessionId !== "string" || body.sessionId.length === 0)
547
+ return bad("sessionId must be a non-empty string", "sessionId");
548
+ if (typeof body.text !== "string")
549
+ return bad("text must be a string", "text");
550
+ if (!optionalString(body.model))
551
+ return bad("model must be a string when present", "model");
552
+ if (!optionalString(body.userMessageUuid))
553
+ return bad("userMessageUuid must be a string when present", "userMessageUuid");
554
+ if (!isAbsent(body.permissionMode) && (typeof body.permissionMode !== "string" || !inTuple(PERMISSION_MODE_INTENTS, body.permissionMode))) {
555
+ return bad(`permissionMode must be one of ${PERMISSION_MODE_INTENTS.join("|")}`, "permissionMode");
556
+ }
557
+ if (!isAbsent(body.attachmentIds)) {
558
+ const raw = body.attachmentIds;
559
+ const ids = Array.isArray(raw) ? ownItems(raw) : undefined;
560
+ if (ids === undefined || !ids.every((id) => typeof id === "string" && id.length > 0)) {
561
+ return bad("attachmentIds must be an array of non-empty attachment ids", "attachmentIds");
562
+ }
563
+ if (ids.length > ATTACHMENT_IDS_PER_TASK_CAP)
564
+ return bad(`attachmentIds exceeds the per-task limit (${ATTACHMENT_IDS_PER_TASK_CAP})`, "attachmentIds");
565
+ }
566
+ if (!isAbsent(body.reasoningEffort) && (typeof body.reasoningEffort !== "string" || !inTuple(SEAT_REASONING_EFFORTS, body.reasoningEffort))) {
567
+ return bad(`reasoningEffort must be one of ${SEAT_REASONING_EFFORTS.join("|")}`, "reasoningEffort");
568
+ }
569
+ for (const k of ["retainBackgroundProcesses", "forwardSubagentEvents"]) {
570
+ if (!isAbsent(body[k]) && typeof body[k] !== "boolean")
571
+ return bad(`${k} must be a boolean when present`, k);
572
+ }
573
+ if (!isAbsent(body.retainSubagentSessions)) {
574
+ const verdict = checkRetainSubagentSessions(body.retainSubagentSessions);
575
+ if (verdict !== true)
576
+ return nested("retainSubagentSessions", verdict);
577
+ }
578
+ if (!isAbsent(body.settings)) {
579
+ const verdict = checkSeatTurnSettings(body.settings);
580
+ if (verdict !== true)
581
+ return nested("settings", verdict);
582
+ }
583
+ if (!optionalString(body.scenario))
584
+ return bad("scenario must be a string when present", "scenario");
585
+ if (!isAbsent(body.rewind)) {
586
+ const verdict = checkSeatRewindIntent(body.rewind);
587
+ if (verdict !== true)
588
+ return nested("rewind", verdict);
589
+ }
590
+ return true;
591
+ }
592
+ catch (e) {
593
+ const key = ownDataRefusalKeyOf(e);
594
+ return key !== undefined ? bad(NOT_PLAIN_DATA, key) : bad("sendMessage request could not be read");
595
+ }
596
+ }
597
+ export function isSendMessageRequest(v) {
598
+ return checkSendMessageRequest(v) === true;
306
599
  }
307
- const checkSendMessageAck = (v) => {
600
+ const checkSendMessageAck = seatCheck((v) => {
308
601
  if (!isObject(v))
309
602
  return bad("sendMessage ack is not an object");
310
- if (typeof v.sessionId !== "string")
603
+ if (typeof own(v, "sessionId") !== "string")
311
604
  return bad("sessionId must be a string", "sessionId");
312
- if (typeof v.userMessageUuid !== "string")
605
+ if (typeof own(v, "userMessageUuid") !== "string")
313
606
  return bad("userMessageUuid must be a string", "userMessageUuid");
314
- if (!isAbsent(v.queued) && typeof v.queued !== "boolean")
607
+ const queued = own(v, "queued");
608
+ if (!isAbsent(queued) && typeof queued !== "boolean")
315
609
  return bad("queued must be a boolean when present", "queued");
316
610
  return true;
317
- };
611
+ });
318
612
  export function isSendMessageAck(v) {
319
613
  return checkSendMessageAck(v) === true;
320
614
  }
321
- const checkInterruptAck = (v) => isObject(v) && typeof v.interrupted === "boolean" ? true : bad("interrupt ack needs boolean `interrupted`", "interrupted");
322
- const checkStopAck = (v) => isObject(v) && typeof v.stopped === "boolean" ? true : bad("stop ack needs boolean `stopped`", "stopped");
323
- const checkOkAck = (v) => isObject(v) && typeof v.ok === "boolean" ? true : bad("ack needs boolean `ok`", "ok");
615
+ const checkInterruptAck = seatCheck((v) => isObject(v) && typeof own(v, "interrupted") === "boolean" ? true : bad("interrupt ack needs boolean `interrupted`", "interrupted"));
616
+ const checkStopAck = seatCheck((v) => isObject(v) && typeof own(v, "stopped") === "boolean" ? true : bad("stop ack needs boolean `stopped`", "stopped"));
617
+ const checkOkAck = seatCheck((v) => isObject(v) && typeof own(v, "ok") === "boolean" ? true : bad("ack needs boolean `ok`", "ok"));
324
618
  const checkBooleanAck = (v) => typeof v === "boolean" ? true : bad("expected a bare boolean result");
325
- const checkGetTranscriptResult = (v) => {
619
+ const checkGetTranscriptResult = seatCheck((v) => {
326
620
  if (!isObject(v))
327
621
  return bad("transcript envelope is not an object");
328
- if (typeof v.sessionId !== "string")
622
+ if (typeof own(v, "sessionId") !== "string")
329
623
  return bad("sessionId must be a string", "sessionId");
330
- if (!Array.isArray(v.messages))
624
+ if (!Array.isArray(own(v, "messages")))
331
625
  return bad("messages must be an array", "messages");
332
626
  return true;
333
- };
334
- const checkSessionSearchResult = (v) => {
627
+ });
628
+ const checkSessionSearchResult = seatCheck((v) => {
335
629
  if (!isObject(v))
336
630
  return bad("search result row is not an object");
337
- if (typeof v.sessionId !== "string")
631
+ if (typeof own(v, "sessionId") !== "string")
338
632
  return bad("sessionId must be a string", "sessionId");
339
- if (!optionalString(v.title))
633
+ if (!optionalString(own(v, "title")))
340
634
  return bad("title must be a string when present", "title");
341
- if (!Array.isArray(v.matches))
635
+ const matches = own(v, "matches");
636
+ if (!Array.isArray(matches))
342
637
  return bad("matches must be an array", "matches");
343
- const okMatches = v.matches.every((m) => isObject(m) && typeof m.snippet === "string");
638
+ const okMatches = ownItems(matches).every((m) => isObject(m) && typeof own(m, "snippet") === "string");
344
639
  if (!okMatches)
345
640
  return bad("matches must be {snippet:string}[]", "matches");
346
641
  return true;
347
- };
348
- const checkSessionSearchEnvelope = (v) => {
642
+ });
643
+ const checkSessionSearchEnvelope = seatCheck((v) => {
349
644
  if (!isObject(v))
350
645
  return bad("search envelope is not an object");
351
- const results = v.results;
646
+ const results = own(v, "results");
352
647
  if (!Array.isArray(results))
353
648
  return bad("results must be an array", "results");
354
- for (let i = 0; i < results.length; i += 1) {
355
- const verdict = checkSessionSearchResult(results[i]);
649
+ const rows = ownItems(results);
650
+ for (let i = 0; i < rows.length; i += 1) {
651
+ const verdict = checkSessionSearchResult(rows[i]);
356
652
  if (verdict !== true)
357
653
  return nested(`results[${i}]`, verdict);
358
654
  }
359
655
  return true;
360
- };
361
- const checkSessionsState = (v) => {
656
+ });
657
+ const checkSessionsState = seatCheck((v) => {
362
658
  if (!isObject(v))
363
659
  return bad("sessions state is not an object");
364
- const sessions = v.sessions;
660
+ const sessions = own(v, "sessions");
365
661
  if (!Array.isArray(sessions))
366
662
  return bad("sessions must be an array", "sessions");
367
- for (let i = 0; i < sessions.length; i += 1) {
368
- const verdict = checkLocalSessionRecord(sessions[i]);
663
+ const rows = ownItems(sessions);
664
+ for (let i = 0; i < rows.length; i += 1) {
665
+ const verdict = checkLocalSessionRecord(rows[i]);
369
666
  if (verdict !== true)
370
667
  return nested(`sessions[${i}]`, verdict);
371
668
  }
372
669
  return true;
373
- };
374
- const checkFocusedSessionState = (v) => {
670
+ });
671
+ const checkFocusedSessionState = seatCheck((v) => {
375
672
  if (!isObject(v))
376
673
  return bad("focused session state is not an object");
377
- if (v.sessionId !== null && typeof v.sessionId !== "string") {
674
+ const sessionId = own(v, "sessionId");
675
+ if (sessionId !== null && typeof sessionId !== "string") {
378
676
  return bad("sessionId must be a string or null", "sessionId");
379
677
  }
380
678
  return true;
381
- };
382
- const checkSettingsState = (v) => {
679
+ });
680
+ const checkSettingsState = seatCheck((v) => {
383
681
  if (!isObject(v))
384
682
  return bad("settings state is not an object");
385
- if (v.defaultModel !== null && typeof v.defaultModel !== "string") {
683
+ const defaultModel = own(v, "defaultModel");
684
+ if (defaultModel !== null && typeof defaultModel !== "string") {
386
685
  return bad("defaultModel must be a string or null", "defaultModel");
387
686
  }
388
- if (!optionalString(v.engineVersion))
687
+ if (!optionalString(own(v, "engineVersion")))
389
688
  return bad("engineVersion must be a string when present", "engineVersion");
390
- if (!optionalString(v.dataRoot))
689
+ if (!optionalString(own(v, "dataRoot")))
391
690
  return bad("dataRoot must be a string when present", "dataRoot");
392
691
  return true;
393
- };
692
+ });
693
+ const checkPickFolderResult = (v) => v === null || (typeof v === "string" && v.length > 0)
694
+ ? true
695
+ : bad("pickFolder result must be null (cancelled) or a non-empty path string");
696
+ const checkSeatCapabilitiesState = seatCheck((v) => {
697
+ if (!isObject(v) || Array.isArray(v))
698
+ return bad("seat capabilities state is not an object");
699
+ const proto = Object.getPrototypeOf(v);
700
+ if (proto !== Object.prototype && proto !== null)
701
+ return bad("seat capabilities state is not a plain object");
702
+ for (const k of Reflect.ownKeys(v)) {
703
+ const name = typeof k === "string" ? k : String(k);
704
+ if (typeof k !== "string" || !inTuple(SEAT_CAPABILITY_NAMES, k)) {
705
+ return bad(`${name} is not a registered seat capability (${SEAT_CAPABILITY_NAMES.join("|")})`, name);
706
+ }
707
+ const value = own(v, k);
708
+ if (!isAbsent(value) && typeof value !== "boolean")
709
+ return bad(`${k} must be a boolean when present`, k);
710
+ }
711
+ return true;
712
+ });
394
713
  export const LOCAL_SESSIONS_SPEC = {
395
714
  ns: "sema.web",
396
715
  service: "LocalSessions",
@@ -408,8 +727,9 @@ export const LOCAL_SESSIONS_SPEC = {
408
727
  getTranscript: { kind: "invoke", check: checkGetTranscriptResult },
409
728
  searchSessions: { kind: "invoke", check: checkSessionSearchEnvelope },
410
729
  uploadAttachment: { kind: "invoke", check: checkAttachmentUploadReceipt },
411
- listModels: { kind: "invoke", check: checkSeatModelCatalog },
730
+ listModels: { kind: "invoke", check: checkLiveModelCatalog },
412
731
  applyModelConfig: { kind: "invoke", check: checkApplyModelConfigResult },
732
+ pickFolder: { kind: "invoke", check: checkPickFolderResult },
413
733
  onEvent: { kind: "event", check: checkLocalSessionEvent },
414
734
  onToolPermissionRequest: { kind: "event", check: checkToolPermissionRequest },
415
735
  },
@@ -417,6 +737,7 @@ export const LOCAL_SESSIONS_SPEC = {
417
737
  sessionsState: { check: checkSessionsState },
418
738
  focusedSessionState: { check: checkFocusedSessionState },
419
739
  settingsState: { check: checkSettingsState },
740
+ seatCapabilitiesState: { check: checkSeatCapabilitiesState },
420
741
  },
421
742
  };
422
743
  export const SEAT_METHOD_NAMES = [
@@ -435,6 +756,7 @@ export const SEAT_METHOD_NAMES = [
435
756
  "uploadAttachment",
436
757
  "listModels",
437
758
  "applyModelConfig",
759
+ "pickFolder",
438
760
  "onEvent",
439
761
  "onToolPermissionRequest",
440
762
  ];
@@ -442,6 +764,7 @@ export const SEAT_STORE_PROPS = [
442
764
  "sessionsStateStore",
443
765
  "focusedSessionStateStore",
444
766
  "settingsStateStore",
767
+ "seatCapabilitiesStateStore",
445
768
  ];
446
769
  export const SEAT_EVENT_METHOD_NAMES = ["onEvent", "onToolPermissionRequest"];
447
770
  export const LOCAL_SESSION_EVENT_KEYS = [
@@ -461,6 +784,7 @@ export const LOCAL_SESSION_EVENT_KEYS = [
461
784
  "hasPreClearSession",
462
785
  "requestId",
463
786
  "outcome",
787
+ "parked",
464
788
  "chrome",
465
789
  ];
466
790
  export const TOOL_PERMISSION_REQUEST_KEYS = [
@@ -486,6 +810,7 @@ export const LOCAL_SESSION_RECORD_KEYS = [
486
810
  "engineSessionId",
487
811
  "model",
488
812
  "title",
813
+ "cwd",
489
814
  "isRunning",
490
815
  "createdAt",
491
816
  "lastActivityAt",
@@ -505,6 +830,7 @@ export const SEND_MESSAGE_REQUEST_KEYS = [
505
830
  "retainSubagentSessions",
506
831
  "settings",
507
832
  "scenario",
833
+ "rewind",
508
834
  ];
509
835
  export const SEAT_SEND_MESSAGE_KEY_ORIGINS = {
510
836
  sessionId: { seatOnly: "座位会话句柄(渲染端持有的本地 id);引擎会话 id 由座位记录的 `engineSessionId` 承载 —— 与引擎请求体上的同名位**同名不同义**,绝不直传" },
@@ -519,6 +845,7 @@ export const SEAT_SEND_MESSAGE_KEY_ORIGINS = {
519
845
  retainSubagentSessions: { taskRequestKey: "retainSubagentSessions" },
520
846
  settings: { taskRequestKey: "settings" },
521
847
  scenario: { taskRequestKey: "scenario" },
848
+ rewind: { projectedBy: "rewindSpecForMode", taskRequestKeys: ["resumeAt", "resumeAtMode", "restoreFiles", "rewindFilesTo"] },
522
849
  };
523
850
  export const TOOL_PERMISSION_DECISION_KEYS = [
524
851
  "sessionId",
@@ -533,7 +860,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
533
860
  LocalSessionRecord: {
534
861
  guard: "isLocalSessionRecord",
535
862
  check: checkLocalSessionRecord,
536
- validated: ["sessionId", "engineSessionId", "model", "title", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked"],
863
+ validated: ["sessionId", "engineSessionId", "model", "title", "cwd", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked"],
537
864
  unchecked: [],
538
865
  },
539
866
  ToolPermissionRequest: {
@@ -563,7 +890,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
563
890
  },
564
891
  {
565
892
  key: "origin",
566
- why: "喂姿态谓词 askSurvivesPosture 的安全位(CC-203),按开集读(非空串原文字节、词表不校);权威窄读在卡口与过境口 toolPermissionRequestAskBits,座位门不设第二判官(为一个位拒掉整条 request = 把安全 ask 丢给引擎 TTL deny)。坏形的两种失效方向:非串 / 空串读成缺席 ⇒ 宿主报了没命中时姿态谓词可答可以放(放宽方向:真出身若是必问词就丢了);表外串读成不认识的词 ⇒ 答 unknown,宿主退回自己的规则(不放宽)。不经过境口自铸座位请求的宿主要自己按同一把窄读。",
893
+ why: "喂自动车道单一判定 automaticAnswerVerdict 的出身位(CC-203),按开集读(非空串原文字节、词表不校);权威窄读在卡口与过境口 toolPermissionRequestAskBits,座位门不设第二判官(为一个位拒掉整条 request = 把安全 ask 丢给引擎 TTL deny)。坏形的两种失效方向:非串 / 空串读成缺席 ⇒ 判定少一路必问证据(放宽方向:真出身若是收词、而卡上的类集恰没带它对应的类,这一路就丢了);表外串 ⇒ 不是收词,出身这一路不起作用(类集照读,不放宽)。不经过境口自铸座位请求的宿主要自己按同一把窄读。",
567
894
  },
568
895
  {
569
896
  key: "askClass",
@@ -598,6 +925,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
598
925
  "hasPreClearSession",
599
926
  "requestId",
600
927
  "outcome",
928
+ "parked",
601
929
  "chrome",
602
930
  ],
603
931
  unchecked: [
@@ -613,10 +941,34 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
613
941
  validated: ["id", "name", "mime", "sha256", "sizeBytes"],
614
942
  unchecked: [],
615
943
  },
616
- SeatModelCatalog: {
617
- guard: "isSeatModelCatalog",
618
- check: checkSeatModelCatalog,
619
- validated: ["models", "defaultId"],
944
+ LiveModelCatalog: {
945
+ check: checkLiveModelCatalog,
946
+ validated: ["models", "default", "defaultModel"],
947
+ unchecked: [
948
+ {
949
+ key: "droppedEntries",
950
+ why: "诊断面(哪些目录条目没被引擎收下),三态读法归 droppedModelEntriesOf(含坏形 malformed);出站门为它拒掉整份目录 = 选单为一行诊断整个消失。",
951
+ },
952
+ ],
953
+ },
954
+ SendMessageRequest: {
955
+ guard: "isSendMessageRequest",
956
+ check: checkSendMessageRequest,
957
+ validated: [
958
+ "sessionId",
959
+ "text",
960
+ "model",
961
+ "userMessageUuid",
962
+ "permissionMode",
963
+ "attachmentIds",
964
+ "reasoningEffort",
965
+ "retainBackgroundProcesses",
966
+ "forwardSubagentEvents",
967
+ "retainSubagentSessions",
968
+ "settings",
969
+ "scenario",
970
+ "rewind",
971
+ ],
620
972
  unchecked: [],
621
973
  },
622
974
  ApplyModelConfigResult: {
@@ -670,9 +1022,14 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
670
1022
  validated: ["defaultModel", "engineVersion", "dataRoot"],
671
1023
  unchecked: [],
672
1024
  },
673
- SeatModelInfo: {
674
- check: (v) => checkSeatModelInfo(v, 0),
675
- validated: ["id", "name", "provider", "contextWindow", "maxOutputTokens"],
1025
+ SeatCapabilitiesState: {
1026
+ check: checkSeatCapabilitiesState,
1027
+ validated: ["pickFolder", "rewind"],
1028
+ unchecked: [],
1029
+ },
1030
+ SeatRewindIntent: {
1031
+ check: checkSeatRewindIntent,
1032
+ validated: ["mode", "targetMessageUuid"],
676
1033
  unchecked: [],
677
1034
  },
678
1035
  SessionSearchResult: {
@@ -692,6 +1049,11 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
692
1049
  },
693
1050
  };
694
1051
  export const SEAT_VALIDATOR_COVERAGE_EXEMPT = [
1052
+ {
1053
+ label: "PickFolderResult",
1054
+ check: checkPickFolderResult,
1055
+ why: "载荷是**串或 null**(选中的路径 / 用户取消,CC-469),没有键面 ⇒ `keyof` 覆盖表在它身上无从谈起。判别力由 run-seat-wave2-test.mjs ST1-1 承担:认 null 与非空串、拒空串 / 数 / undefined / 对象 / 布尔五形。",
1056
+ },
695
1057
  {
696
1058
  label: "BooleanAck",
697
1059
  check: checkBooleanAck,
@@ -723,5 +1085,7 @@ const _seatContractPins = [
723
1085
  true, true, true, true, true, true, true, true,
724
1086
  true, true, true, true, true, true, true, true,
725
1087
  true, true, true, true, true, true, true, true,
1088
+ true, true, true, true, true,
1089
+ true, true, true, true, true, true, true, true,
726
1090
  ];
727
1091
  void _seatContractPins;