@sema-agent/client-core 0.98.0 → 0.100.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 (236) hide show
  1. package/CHANGELOG.md +376 -0
  2. package/README.md +61 -35
  3. package/dist/adapt/arms.js +120 -55
  4. package/dist/adapt/panelTasks.d.ts +3 -2
  5. package/dist/adapt/panelTasks.js +34 -11
  6. package/dist/adapt/textStream.d.ts +1 -1
  7. package/dist/adapt/textStream.js +51 -28
  8. package/dist/adapter/activeRunSelfHeal.d.ts +11 -3
  9. package/dist/adapter/activeRunSelfHeal.js +210 -294
  10. package/dist/adapter/downstream/eventToSdkMessage.d.ts +25 -6
  11. package/dist/adapter/downstream/eventToSdkMessage.js +176 -12
  12. package/dist/adapter/downstream/terminalToSdkResult.js +10 -0
  13. package/dist/adapter/downstream/wiringManifestView.d.ts +3 -1
  14. package/dist/adapter/downstream/wiringManifestView.js +1 -0
  15. package/dist/adapter/runStream.js +82 -40
  16. package/dist/adapter/types.d.ts +2 -0
  17. package/dist/adapter/types.js +2 -1
  18. package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
  19. package/dist/agentsWireCaps.d.ts +7 -3
  20. package/dist/agentsWireCaps.js +133 -39
  21. package/dist/cloudConfigWireCaps.d.ts +10 -1
  22. package/dist/cloudConfigWireCaps.js +181 -65
  23. package/dist/compactionStatus.d.ts +34 -0
  24. package/dist/compactionStatus.js +196 -0
  25. package/dist/controlRouter.d.ts +4 -2
  26. package/dist/controlRouter.js +39 -51
  27. package/dist/coreValuePorts.d.ts +26 -1
  28. package/dist/coreValuePorts.js +10 -0
  29. package/dist/corruptSessionCopy.d.ts +2 -1
  30. package/dist/corruptSessionCopy.js +3 -3
  31. package/dist/decideFailureNote.js +3 -3
  32. package/dist/declared/supportFloorDeclared.js +1 -1
  33. package/dist/detachWire.js +3 -2
  34. package/dist/devicesFace.d.ts +34 -0
  35. package/dist/devicesFace.js +90 -0
  36. package/dist/displayUntrusted.d.ts +1 -0
  37. package/dist/displayUntrusted.js +153 -5
  38. package/dist/engineAgentPanelStore.d.ts +14 -4
  39. package/dist/engineAgentPanelStore.js +14 -0
  40. package/dist/engineCapReader.d.ts +2 -1
  41. package/dist/engineCapReader.js +7 -5
  42. package/dist/engineCapsCache.d.ts +8 -0
  43. package/dist/engineCapsCache.js +59 -6
  44. package/dist/engineCapsChange.d.ts +2 -0
  45. package/dist/engineCapsChange.js +9 -0
  46. package/dist/engineErrorCodes.d.ts +11 -2
  47. package/dist/engineErrorCodes.js +11 -12
  48. package/dist/engineRowRef.js +4 -0
  49. package/dist/engineSessionMessages.d.ts +1 -0
  50. package/dist/engineSessionMessages.js +7 -1
  51. package/dist/engineTargetSeat.d.ts +27 -0
  52. package/dist/engineTargetSeat.js +199 -0
  53. package/dist/engineToolDirectory.d.ts +3 -0
  54. package/dist/engineToolDirectory.js +4 -2
  55. package/dist/engineWireFor.js +3 -8
  56. package/dist/env/uiLanguage.d.ts +2 -1
  57. package/dist/env/uiLanguage.js +3 -2
  58. package/dist/eventLeg.d.ts +7 -5
  59. package/dist/eventLeg.js +68 -49
  60. package/dist/fileHistoryCaptureCapability.d.ts +2 -4
  61. package/dist/fileHistoryCaptureCapability.js +12 -22
  62. package/dist/fileHistoryLegNotice.d.ts +2 -1
  63. package/dist/fileHistoryLegNotice.js +3 -3
  64. package/dist/frameBinding.d.ts +3 -0
  65. package/dist/frameBinding.js +12 -0
  66. package/dist/gateOutcome.js +16 -2
  67. package/dist/gateVocabulary.d.ts +8 -7
  68. package/dist/gateVocabulary.js +71 -73
  69. package/dist/generated/engineFactTables.d.ts +18 -1
  70. package/dist/generated/engineFactTables.js +56 -0
  71. package/dist/generated/engineNoticeTables.js +12 -3
  72. package/dist/generated/settingsSchemaFns.d.ts +18 -0
  73. package/dist/generated/settingsSchemaFns.js +70 -0
  74. package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
  75. package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
  76. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -0
  77. package/dist/generated/settingsSchemaMcpRequestEntry.js +162 -0
  78. package/dist/generated/settingsSchemaTables.d.ts +2 -0
  79. package/dist/generated/settingsSchemaTables.js +9 -0
  80. package/dist/generated/settingsSchemaTypes.d.ts +133 -0
  81. package/dist/generated/settingsSchemaTypes.js +1 -0
  82. package/dist/hitl/allowRuleShadow.d.ts +2 -1
  83. package/dist/hitl/allowRuleShadow.js +18 -15
  84. package/dist/hitl/approvalCardReasons.d.ts +3 -2
  85. package/dist/hitl/approvalCardReasons.js +29 -30
  86. package/dist/hitl/approvalHolds.d.ts +17 -0
  87. package/dist/hitl/approvalHolds.js +114 -29
  88. package/dist/hitl/askClassPair.d.ts +2 -2
  89. package/dist/hitl/askClassPair.js +16 -0
  90. package/dist/hitl/askGateWire.js +2 -1
  91. package/dist/hitl/askSettlementLine.d.ts +14 -4
  92. package/dist/hitl/askSettlementLine.js +67 -47
  93. package/dist/hitl/attributionLadder.d.ts +23 -0
  94. package/dist/hitl/attributionLadder.js +67 -0
  95. package/dist/hitl/automaticAnswerVerdict.d.ts +2 -1
  96. package/dist/hitl/automaticAnswerVerdict.js +8 -8
  97. package/dist/hitl/crashConvergedNotice.d.ts +5 -4
  98. package/dist/hitl/crashConvergedNotice.js +28 -41
  99. package/dist/hitl/decisionLedger.d.ts +55 -0
  100. package/dist/hitl/decisionLedger.js +156 -0
  101. package/dist/hitl/decisionRefusal.d.ts +1 -0
  102. package/dist/hitl/decisionRefusal.js +1 -1
  103. package/dist/hitl/decisionSend.d.ts +113 -0
  104. package/dist/hitl/decisionSend.js +579 -0
  105. package/dist/hitl/frameRouter.js +7 -8
  106. package/dist/hitl/hitlBridge.d.ts +1 -0
  107. package/dist/hitl/hitlBridge.js +21 -9
  108. package/dist/hitl/persistedRulesWire.d.ts +6 -5
  109. package/dist/hitl/persistedRulesWire.js +55 -73
  110. package/dist/hitl/planReviewWire.d.ts +5 -0
  111. package/dist/hitl/planReviewWire.js +53 -76
  112. package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
  113. package/dist/hitl/sessionPolicyDeliverable.js +49 -9
  114. package/dist/hitl/sessionPolicyWire.d.ts +2 -1
  115. package/dist/hitl/sessionPolicyWire.js +23 -24
  116. package/dist/hitl/suspendedReopen.d.ts +2 -1
  117. package/dist/hitl/suspendedReopen.js +7 -10
  118. package/dist/hitl/toolApprovalWire.d.ts +17 -5
  119. package/dist/hitl/toolApprovalWire.js +120 -147
  120. package/dist/hooksWireCaps.js +145 -56
  121. package/dist/host.d.ts +21 -0
  122. package/dist/hostTurnSettings.d.ts +110 -0
  123. package/dist/hostTurnSettings.js +692 -0
  124. package/dist/humanTurn.d.ts +15 -1
  125. package/dist/humanTurn.js +100 -12
  126. package/dist/humanTurnRead.d.ts +2 -0
  127. package/dist/humanTurnRead.js +22 -1
  128. package/dist/i18n/messages.en.d.ts +713 -0
  129. package/dist/i18n/messages.en.js +713 -0
  130. package/dist/i18n/messages.zh.js +854 -1
  131. package/dist/index.d.ts +45 -13
  132. package/dist/index.js +27 -9
  133. package/dist/inheritEnvCapability.d.ts +4 -2
  134. package/dist/inheritEnvCapability.js +12 -5
  135. package/dist/inheritEnvWire.d.ts +3 -2
  136. package/dist/inheritEnvWire.js +14 -16
  137. package/dist/injectionLaneNotice.d.ts +5 -0
  138. package/dist/injectionLaneNotice.js +46 -0
  139. package/dist/interactiveHalt.js +17 -6
  140. package/dist/liveModelCatalog.d.ts +2 -1
  141. package/dist/liveModelCatalog.js +14 -8
  142. package/dist/mcpPanel.d.ts +10 -1
  143. package/dist/mcpPanel.js +42 -13
  144. package/dist/mcpProbeCapability.d.ts +2 -1
  145. package/dist/mcpProbeCapability.js +7 -11
  146. package/dist/mcpProbeWire.d.ts +3 -1
  147. package/dist/mcpProbeWire.js +5 -0
  148. package/dist/mcpReconnect.js +2 -2
  149. package/dist/mcpToolToggles.d.ts +6 -0
  150. package/dist/mcpToolToggles.js +46 -0
  151. package/dist/mcpWireCaps.d.ts +43 -3
  152. package/dist/mcpWireCaps.js +194 -59
  153. package/dist/mcpWireTransport.d.ts +4 -0
  154. package/dist/mcpWireTransport.js +18 -0
  155. package/dist/memoryEntriesWire.js +5 -10
  156. package/dist/model/onboardJudgement.d.ts +93 -0
  157. package/dist/model/onboardJudgement.js +415 -0
  158. package/dist/model/tierVocabulary.d.ts +2 -0
  159. package/dist/model/tierVocabulary.js +17 -5
  160. package/dist/modelCapabilityProbe.d.ts +65 -0
  161. package/dist/modelCapabilityProbe.js +601 -0
  162. package/dist/modelIdentityResolvability.d.ts +5 -0
  163. package/dist/modelIdentityResolvability.js +49 -22
  164. package/dist/ownKey.d.ts +33 -0
  165. package/dist/ownKey.js +109 -0
  166. package/dist/panelReduce.d.ts +11 -1
  167. package/dist/panelReduce.js +95 -16
  168. package/dist/panelStateHolder.d.ts +1 -0
  169. package/dist/panelStateHolder.js +10 -1
  170. package/dist/permissionRuleIssue.d.ts +2 -1
  171. package/dist/permissionRuleIssue.js +23 -20
  172. package/dist/permissionRulesWriteCapability.d.ts +2 -1
  173. package/dist/permissionRulesWriteCapability.js +8 -6
  174. package/dist/pluginHooksWire.d.ts +46 -3
  175. package/dist/pluginHooksWire.js +220 -12
  176. package/dist/prepareRefusal.d.ts +8 -0
  177. package/dist/prepareRefusal.js +72 -0
  178. package/dist/printModelStatus.d.ts +63 -0
  179. package/dist/printModelStatus.js +155 -0
  180. package/dist/request/taskRequest.d.ts +16 -10
  181. package/dist/request/taskRequest.js +195 -58
  182. package/dist/resumeRefusalCopy.d.ts +14 -9
  183. package/dist/resumeRefusalCopy.js +89 -144
  184. package/dist/retryStatus.d.ts +55 -0
  185. package/dist/retryStatus.js +155 -19
  186. package/dist/ruleRefusalSentence.d.ts +4 -0
  187. package/dist/ruleRefusalSentence.js +58 -0
  188. package/dist/sandboxWire.d.ts +2 -1
  189. package/dist/sandboxWire.js +55 -21
  190. package/dist/scenarioRefusal.d.ts +10 -0
  191. package/dist/scenarioRefusal.js +111 -0
  192. package/dist/seam.d.ts +48 -9
  193. package/dist/seam.js +54 -5
  194. package/dist/seatContract.d.ts +272 -14
  195. package/dist/seatContract.js +711 -23
  196. package/dist/selfOrchestrationDenial.js +7 -19
  197. package/dist/sessionIdSegment.d.ts +6 -0
  198. package/dist/sessionIdSegment.js +24 -0
  199. package/dist/sessionMemoryStatus.js +6 -11
  200. package/dist/sessionPolicyCapability.d.ts +2 -1
  201. package/dist/sessionPolicyCapability.js +8 -6
  202. package/dist/settingsCredentialKeyPaths.d.ts +8 -0
  203. package/dist/settingsCredentialKeyPaths.js +219 -0
  204. package/dist/settingsHooksSalvage.d.ts +44 -0
  205. package/dist/settingsHooksSalvage.js +211 -0
  206. package/dist/skillToolListsCapability.d.ts +2 -1
  207. package/dist/skillToolListsCapability.js +8 -6
  208. package/dist/skillsWireCaps.d.ts +0 -3
  209. package/dist/skillsWireCaps.js +1 -2
  210. package/dist/sseIdleTriage.js +3 -2
  211. package/dist/subagent/engineSubagentResume.js +15 -9
  212. package/dist/subagentContentStore.d.ts +4 -0
  213. package/dist/subagentContentStore.js +157 -27
  214. package/dist/toolHistoryMismatch.js +3 -2
  215. package/dist/toolRoster.d.ts +3 -2
  216. package/dist/toolRoster.js +21 -20
  217. package/dist/toolsFlagNames.d.ts +8 -0
  218. package/dist/toolsFlagNames.js +110 -0
  219. package/dist/turnFailurePresentation.d.ts +12 -1
  220. package/dist/turnFailurePresentation.js +220 -15
  221. package/dist/usageAnalytics.js +6 -11
  222. package/dist/userAttachmentEnvelope.d.ts +1 -0
  223. package/dist/userAttachmentEnvelope.js +37 -7
  224. package/dist/userAttachmentSeat.d.ts +21 -0
  225. package/dist/userAttachmentSeat.js +75 -0
  226. package/dist/userInvokedSkillsCapability.d.ts +11 -1
  227. package/dist/userInvokedSkillsCapability.js +31 -7
  228. package/dist/wireErrorTriage.d.ts +7 -0
  229. package/dist/wireErrorTriage.js +23 -1
  230. package/dist/wireFailureShape.js +2 -1
  231. package/dist/wireRefusalCopy.d.ts +62 -16
  232. package/dist/wireRefusalCopy.js +307 -148
  233. package/dist/workflowsJournalCapability.d.ts +2 -1
  234. package/dist/workflowsJournalCapability.js +8 -6
  235. package/docs/INTEGRATION-CLIENTS.md +951 -42
  236. package/package.json +5 -5
@@ -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
@@ -89,6 +92,124 @@ const seatCheckAt = (fn) => (v, field) => {
89
92
  return key !== undefined ? bad(NOT_PLAIN_DATA, `${field}.${key}`) : bad("payload could not be read", field);
90
93
  }
91
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
+ });
92
213
  export const TOOL_PERMISSION_REQUEST_ID_DOMAINS = Object.freeze([
93
214
  "live:",
94
215
  "durable:",
@@ -127,6 +248,7 @@ const SEAT_EVENT_TYPE_TUPLE = [
127
248
  "chrome_event",
128
249
  "error",
129
250
  "tool_permission_resolved",
251
+ "subagent_content",
130
252
  ];
131
253
  export const SEAT_EVENT_TYPES = Object.freeze(SEAT_EVENT_TYPE_TUPLE);
132
254
  const CHROME_EVENT_KIND_TUPLE = [
@@ -205,7 +327,7 @@ export function readSeatStreamDelta(message) {
205
327
  return Object.freeze({ kind: "malformed" });
206
328
  }
207
329
  }
208
- export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind", "recents", "patchSession"]);
330
+ export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles"]);
209
331
  const notReported = () => Object.freeze({ kind: "not_reported" });
210
332
  const malformedReading = () => Object.freeze({ kind: "malformed" });
211
333
  const reported = (available) => Object.freeze({ kind: "reported", available });
@@ -277,6 +399,10 @@ const SEAT_CAPABILITY_PHRASES = Object.freeze({
277
399
  pickFolder: Object.freeze({ action: "Opening a folder", ability: "show a folder picker", support: "folder picker support" }),
278
400
  rewind: Object.freeze({ action: "Rewinding to an earlier message", ability: "rewind this session", support: "rewind support" }),
279
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" }),
405
+ mcpToolToggles: Object.freeze({ action: "Per-tool switching", ability: "toggle tools", support: "per-tool switches" }),
280
406
  });
281
407
  export function seatCapabilityUnavailableDetail(name, reading) {
282
408
  const phrase = Object.hasOwn(SEAT_CAPABILITY_PHRASES, name)
@@ -395,16 +521,394 @@ export const SEAT_REASONING_EFFORTS = [...REASONING_EFFORT_WORDS];
395
521
  export const SEAT_TURN_SETTINGS_KEYS = ["ultracode"];
396
522
  export const SEAT_TURN_SETTINGS_ORIGINS = Object.freeze({
397
523
  ultracode: Object.freeze({ carriedBy: "renderer" }),
398
- webSearch: Object.freeze({ hostSupplied: "联网检索的每请求配置来自宿主的设置源(可能带检索服务的凭据与私网地址);渲染端没有设置文件,也不该持有凭据" }),
399
- hooks: Object.freeze({ hostSupplied: "hooks 表来自宿主的设置文件(宿主经设置端口与 hooksForWire 投影);渲染端没有设置文件、也不执行本机 hook" }),
400
- resolved: Object.freeze({ hostSupplied: "设置解析器的生效快照(hooks / env / model / 已解析权限)由宿主跑解析器得出;渲染端没有设置源可解析" }),
401
- outputStyle: Object.freeze({ hostSupplied: "输出风格正文由宿主的兜底层随请求带(风格文件在宿主);渲染端只选名字,不持正文" }),
524
+ webSearch: Object.freeze({ hostSupplied: "settings.webSearch" }),
525
+ hooks: Object.freeze({ hostSupplied: "settings.hooks" }),
526
+ resolved: Object.freeze({ hostSupplied: "settings.resolved" }),
527
+ outputStyle: Object.freeze({ hostSupplied: "settings.outputStyle" }),
402
528
  });
403
529
  export const SEAT_REWIND_INTENT_KEYS = ["mode", "targetMessageUuid"];
404
530
  export const ATTACHMENT_UPLOAD_REQUEST_KEYS = ["name", "mimeType", "bytes"];
405
531
  export const SESSION_ROW_PATCH_REQUEST_KEYS = Object.freeze(["sessionId", "title", "pinned"]);
406
532
  export const SESSION_SEARCH_RESULT_KEYS = ["sessionId", "title", "matches"];
407
533
  export const GET_TRANSCRIPT_RESULT_KEYS = ["sessionId", "messages"];
534
+ const DEVICE_REFUSED_SPEC = { status: reqF(R_INT0), errorCode: optF(R_STR), message: optF(R_STR) };
535
+ const DEVICE_LANE_ABSENT_SPEC = { runStoreOnly: optF(R_TRUE) };
536
+ const DEVICE_TRANSPORT_SPEC = { detail: optF(R_STR) };
537
+ const DEVICE_UNREADABLE_SPEC = { why: reqF(R_STR) };
538
+ const DEVICE_UNCONFIRMED_SPEC = {
539
+ why: reqF(oneOfRule("unconfirmed why", ["accepted-unreadable", "transport", "server-error"])),
540
+ detail: optF(R_STR),
541
+ mayStillBeRunning: reqF(R_BOOL),
542
+ };
543
+ const DEVICE_RATE_LIMITED_SPEC = { retryAfterSec: optF(R_NUM) };
544
+ const DEVICE_ROSTER_ROW = shapeRule("device row", {
545
+ deviceId: reqF(R_NONEMPTY),
546
+ name: optF(R_STR),
547
+ status: reqF(oneOfRule("device status", ["online", "offline", "unknown"])),
548
+ lastSeenAt: optF(R_STR),
549
+ });
550
+ const DEVICE_BINDING = shapeRule("device binding", {
551
+ deviceId: reqF(R_NONEMPTY),
552
+ rev: reqF(R_INT0),
553
+ boundAt: optF(R_STR),
554
+ });
555
+ const checkDeviceListOutcome = seatShapeCheck(armsRule("listDevices outcome", "kind", {
556
+ ok: { devices: reqF(arrayRule(DEVICE_ROSTER_ROW)), dropped: reqF(R_INT0) },
557
+ unreadable: DEVICE_UNREADABLE_SPEC,
558
+ "lane-absent": DEVICE_LANE_ABSENT_SPEC,
559
+ refused: DEVICE_REFUSED_SPEC,
560
+ transport: DEVICE_TRANSPORT_SPEC,
561
+ unarmed: {},
562
+ }));
563
+ const checkDeviceSessionBindingOutcome = seatShapeCheck(armsRule("readSessionBinding outcome", "kind", {
564
+ ok: { rootSessionId: reqF(R_NONEMPTY), boundDevice: reqF(DEVICE_BINDING) },
565
+ "not-found": {},
566
+ unreadable: DEVICE_UNREADABLE_SPEC,
567
+ "lane-absent": DEVICE_LANE_ABSENT_SPEC,
568
+ refused: DEVICE_REFUSED_SPEC,
569
+ transport: DEVICE_TRANSPORT_SPEC,
570
+ unarmed: {},
571
+ }));
572
+ const checkDeviceRebindOutcome = seatShapeCheck(armsRule("rebindSession outcome", "kind", {
573
+ ok: { deviceId: reqF(R_NONEMPTY), rev: reqF(R_INT0), workspaceCarryover: optF(oneOfRule("carryover", ["none"])) },
574
+ "active-run": { activeTaskId: optF(R_STR) },
575
+ "rev-conflict": { currentRev: optF(R_INT0) },
576
+ "not-found": {},
577
+ unconfirmed: DEVICE_UNCONFIRMED_SPEC,
578
+ "lane-absent": DEVICE_LANE_ABSENT_SPEC,
579
+ refused: DEVICE_REFUSED_SPEC,
580
+ unarmed: {},
581
+ }));
582
+ const ENROLL_TOKEN_ALLOW = new Set(["token"]);
583
+ const checkDeviceEnrollTokenOutcome = seatShapeCheck(armsRule("issueEnrollToken outcome", "kind", {
584
+ ok: { token: reqF(R_NONEMPTY), expiresAt: optF(R_STR), ttlSec: optF(R_INT1) },
585
+ "rate-limited": DEVICE_RATE_LIMITED_SPEC,
586
+ unreadable: DEVICE_UNREADABLE_SPEC,
587
+ "lane-absent": DEVICE_LANE_ABSENT_SPEC,
588
+ refused: DEVICE_REFUSED_SPEC,
589
+ transport: DEVICE_TRANSPORT_SPEC,
590
+ unarmed: {},
591
+ }), ENROLL_TOKEN_ALLOW);
592
+ const checkDeviceRevokeOutcome = seatShapeCheck(armsRule("revokeDevice outcome", "kind", {
593
+ ok: { deviceId: reqF(R_NONEMPTY), revokedAt: optF(R_STR) },
594
+ "not-found": {},
595
+ unconfirmed: DEVICE_UNCONFIRMED_SPEC,
596
+ "lane-absent": DEVICE_LANE_ABSENT_SPEC,
597
+ refused: DEVICE_REFUSED_SPEC,
598
+ unarmed: {},
599
+ }));
600
+ export const checkSeatDeviceRebindRequest = seatShapeCheck(shapeRule("rebindSession request", {
601
+ sessionId: reqF(R_NONEMPTY),
602
+ toDeviceId: reqF(R_NONEMPTY),
603
+ expectedRev: reqF(R_INT0),
604
+ fromDeviceId: reqF(R_NONEMPTY),
605
+ }));
606
+ export const checkSeatDeviceRevokeRequest = seatShapeCheck(shapeRule("revokeDevice request", { deviceId: reqF(R_NONEMPTY), reason: optF(R_STR) }));
607
+ export const ENGINE_TARGET_REFUSALS = Object.freeze([
608
+ "busy",
609
+ "switching",
610
+ "not_configured",
611
+ "not_signed_in",
612
+ "probe_failed",
613
+ "org_policy",
614
+ "url_refused",
615
+ "login_failed",
616
+ "storage_unavailable",
617
+ "no_local_runtime",
618
+ "input",
619
+ ]);
620
+ export const CLOUD_LOGIN_FAILURES = Object.freeze([
621
+ "access_denied",
622
+ "expired_token",
623
+ "invalid_grant",
624
+ "cancelled",
625
+ "transport",
626
+ "refused",
627
+ "no_tokens",
628
+ "other",
629
+ ]);
630
+ const R_ISO = R_NONEMPTY;
631
+ const R_LOGIN_FAILURE = oneOfRule("login failure", CLOUD_LOGIN_FAILURES);
632
+ const R_DISPLAY_URL = ruleOf("display url", (v) => {
633
+ if (typeof v !== "string" || v.length === 0)
634
+ return false;
635
+ let u;
636
+ try {
637
+ u = new URL(v);
638
+ }
639
+ catch {
640
+ return false;
641
+ }
642
+ return (u.protocol === "https:" || u.protocol === "http:") && u.username === "" && u.password === "" && u.search === "" && u.hash === "";
643
+ });
644
+ const R_VERIFICATION_URI_COMPLETE = ruleOf("verification uri", (v) => {
645
+ if (typeof v !== "string" || v.length === 0)
646
+ return false;
647
+ let text = v;
648
+ for (let i = 0; i < 4; i += 1) {
649
+ let next;
650
+ try {
651
+ next = decodeURIComponent(text);
652
+ }
653
+ catch {
654
+ return false;
655
+ }
656
+ if (next === text)
657
+ break;
658
+ text = next;
659
+ }
660
+ return !/device[_-]?code/i.test(text);
661
+ });
662
+ const ENGINE_PROBE_READING = shapeRule("engine probe", {
663
+ ok: reqF(R_BOOL),
664
+ version: optF(R_STR),
665
+ detail: optF(R_STR),
666
+ at: reqF(R_ISO),
667
+ });
668
+ const SEAT_LOCAL_MCP_ROW = shapeRule("mcp row", {
669
+ name: reqF(R_NONEMPTY),
670
+ status: reqF(R_STR),
671
+ toolCount: optF(R_INT0),
672
+ liveness: optF(R_STR),
673
+ errorCode: optF(R_STR),
674
+ forcedAsk: optF(arrayRule(R_NONEMPTY, true)),
675
+ });
676
+ const SEAT_LOCAL_MCP_READING = armsRule("mcp reading", "status", {
677
+ listed: { servers: reqF(arrayRule(SEAT_LOCAL_MCP_ROW)), readAt: reqF(R_ISO), restartRequired: optF(R_TRUE) },
678
+ unreadable: { cause: reqF(R_NONEMPTY), detail: optF(R_STR), readAt: reqF(R_ISO), restartRequired: optF(R_TRUE) },
679
+ });
680
+ const ENGINE_TARGET_CLOUD = shapeRule("cloud", {
681
+ configured: reqF(R_BOOL),
682
+ url: optF(R_DISPLAY_URL),
683
+ label: optF(R_STR),
684
+ auth: optF(armsRule("cloud auth", "kind", {
685
+ registry: { registryUrl: reqF(R_DISPLAY_URL), principal: optF(R_STR), role: optF(R_STR), scope: optF(R_STR) },
686
+ token: {},
687
+ })),
688
+ login: optF(armsRule("cloud login", "state", {
689
+ pending: {
690
+ registryUrl: reqF(R_DISPLAY_URL),
691
+ userCode: reqF(R_NONEMPTY),
692
+ verificationUri: reqF(R_DISPLAY_URL),
693
+ verificationUriComplete: optF(R_VERIFICATION_URI_COMPLETE),
694
+ expiresAt: reqF(R_ISO),
695
+ },
696
+ failed: { failure: reqF(R_LOGIN_FAILURE), status: optF(R_INT0), at: reqF(R_ISO) },
697
+ })),
698
+ lastProbe: optF(ENGINE_PROBE_READING),
699
+ authError: optF(shapeRule("auth error", {
700
+ failure: reqF(R_LOGIN_FAILURE),
701
+ status: optF(R_INT0),
702
+ at: reqF(R_ISO),
703
+ })),
704
+ orgEngine: optF(shapeRule("org engine", { url: reqF(R_DISPLAY_URL), required: reqF(R_BOOL) })),
705
+ });
706
+ const ENGINE_TARGET_LOCAL = shapeRule("local", {
707
+ lastBootError: optF(R_STR),
708
+ mcp: optF(SEAT_LOCAL_MCP_READING),
709
+ });
710
+ const ENGINE_TARGET_STATE = shapeRule("engine target", {
711
+ mode: reqF(oneOfRule("engine mode", ["local", "cloud"])),
712
+ generation: reqF(R_INT0),
713
+ cloud: reqF(ENGINE_TARGET_CLOUD),
714
+ local: reqF(ENGINE_TARGET_LOCAL),
715
+ });
716
+ const checkEngineTargetState = seatShapeCheck(ENGINE_TARGET_STATE);
717
+ const okArmsRule = (label, okSpec, refusedSpec) => ({
718
+ label,
719
+ test: (v, path) => {
720
+ if (!isPlainRecord(v))
721
+ return bad("not object", path === "" ? undefined : path);
722
+ const ok = own(v, "ok");
723
+ if (ok === true)
724
+ return shapeVerdict(okSpec, v, path, "ok");
725
+ if (ok === false)
726
+ return shapeVerdict(refusedSpec, v, path, "ok");
727
+ return bad("unknown arm", pathAt(path, "ok"));
728
+ },
729
+ });
730
+ const ENGINE_TARGET_REFUSED_SPEC = {
731
+ refusal: reqF(oneOfRule("engineTarget refusal", ENGINE_TARGET_REFUSALS)),
732
+ failure: optF(R_LOGIN_FAILURE),
733
+ status: optF(R_INT0),
734
+ detail: optF(R_STR),
735
+ };
736
+ const checkEngineTargetResult = seatShapeCheck(okArmsRule("engineTarget result", {}, ENGINE_TARGET_REFUSED_SPEC));
737
+ const checkCancelCloudLogin = seatShapeCheck(shapeRule("cancel ack", { ok: reqF(R_BOOL) }));
738
+ const checkCloudLoginStart = seatShapeCheck(okArmsRule("startCloudLogin result", {
739
+ verificationUri: reqF(R_DISPLAY_URL),
740
+ verificationUriComplete: optF(R_VERIFICATION_URI_COMPLETE),
741
+ userCode: reqF(R_NONEMPTY),
742
+ expiresAt: reqF(R_ISO),
743
+ }, ENGINE_TARGET_REFUSED_SPEC));
744
+ const checkCloudConnectResult = seatShapeCheck(okArmsRule("connect result", {
745
+ probe: reqF(shapeRule("probe", { version: optF(R_STR) })),
746
+ }, ENGINE_TARGET_REFUSED_SPEC));
747
+ export const checkCloudLoginRequest = seatShapeCheck(shapeRule("startCloudLogin request", { registryUrl: reqF(R_DISPLAY_URL) }));
748
+ export const checkCloudEngineConnectRequest = seatShapeCheck(shapeRule("connectCloudEngine request", { url: reqF(R_DISPLAY_URL) }));
749
+ const CONFIGURE_TOKEN_ALLOW = new Set(["token"]);
750
+ export const checkCloudEngineConfigureRequest = seatShapeCheck(shapeRule("configureCloudEngine request", { url: reqF(R_DISPLAY_URL), token: reqF(R_NONEMPTY) }), CONFIGURE_TOKEN_ALLOW);
751
+ export const ONBOARD_REFUSALS = Object.freeze([
752
+ "input",
753
+ "probe_failed",
754
+ "probe_unverified",
755
+ "credential_unpaired",
756
+ "catalog_unreadable",
757
+ "write_conflict",
758
+ "write_failed",
759
+ "engine_is_remote",
760
+ "env_catalog_present",
761
+ ]);
762
+ const R_API_WORD = oneOfRule("api", SETTINGS_MODEL_API_WORDS);
763
+ const ONBOARD_PROBE_RESULT = shapeRule("probe result", {
764
+ verdict: reqF(oneOfRule("probe verdict", PROBE_VERDICTS)),
765
+ detail: reqF(R_STR),
766
+ thinking: optF(R_NONEMPTY),
767
+ });
768
+ const ENGINE_UP_SPEC = { model: reqF(ruleOf("string|null", (x) => x === null || typeof x === "string")) };
769
+ const ENGINE_NOT_UP_SPEC = { reason: reqF(R_STR) };
770
+ const ENGINE_RESTART_OUTCOME = armsRule("engine restart", "state", {
771
+ started: ENGINE_UP_SPEC,
772
+ restarted: ENGINE_UP_SPEC,
773
+ pending: ENGINE_NOT_UP_SPEC,
774
+ failed: ENGINE_NOT_UP_SPEC,
775
+ skipped: ENGINE_NOT_UP_SPEC,
776
+ });
777
+ const ONBOARD_SOURCE = armsRule("onboard source", "kind", {
778
+ preset: { providerId: reqF(R_NONEMPTY) },
779
+ custom: {},
780
+ imported: { profileId: reqF(R_NONEMPTY) },
781
+ });
782
+ const ONBOARD_ENTRY_SPEC = {
783
+ source: reqF(ONBOARD_SOURCE),
784
+ modelId: reqF(R_NONEMPTY),
785
+ baseUrl: optF(R_NONEMPTY),
786
+ api: optF(R_API_WORD),
787
+ apiKey: optF(R_NONEMPTY),
788
+ contextWindow: optF(R_INT1),
789
+ maxTokens: optF(R_INT1),
790
+ };
791
+ const ONBOARD_KEY_ALLOW = new Set(["apiKey"]);
792
+ export const checkOnboardEntryRequest = seatShapeCheck(shapeRule("probeOnboardEntry request", ONBOARD_ENTRY_SPEC), ONBOARD_KEY_ALLOW);
793
+ export const checkOnboardApplyRequest = seatShapeCheck(shapeRule("applyOnboardEntry request", {
794
+ ...ONBOARD_ENTRY_SPEC,
795
+ makeDefault: optF(R_BOOL),
796
+ acceptUnverified: optF(R_BOOL),
797
+ }), ONBOARD_KEY_ALLOW);
798
+ const checkOnboardProbeResult = seatShapeCheck(ONBOARD_PROBE_RESULT);
799
+ const checkOnboardApplyResult = seatShapeCheck(okArmsRule("applyOnboardEntry result", {
800
+ entryName: reqF(R_NONEMPTY),
801
+ modelId: reqF(R_NONEMPTY),
802
+ keyEnv: reqF(R_NONEMPTY),
803
+ updatedExisting: reqF(R_BOOL),
804
+ probe: reqF(ONBOARD_PROBE_RESULT),
805
+ otherIssues: reqF(arrayRule(shapeRule("catalog issue", {
806
+ name: reqF(R_NONEMPTY),
807
+ modelId: reqF(R_STR),
808
+ issue: reqF(R_NONEMPTY),
809
+ }))),
810
+ engine: reqF(ENGINE_RESTART_OUTCOME),
811
+ }, {
812
+ refusal: reqF(oneOfRule("onboard refusal", ONBOARD_REFUSALS)),
813
+ detail: optF(R_STR),
814
+ probe: optF(ONBOARD_PROBE_RESULT),
815
+ }));
816
+ const checkOnboardProvidersResult = seatShapeCheck(shapeRule("onboard providers", {
817
+ providers: reqF(arrayRule(shapeRule("provider row", {
818
+ id: reqF(R_NONEMPTY),
819
+ name: reqF(R_NONEMPTY),
820
+ baseUrl: reqF(R_NONEMPTY),
821
+ api: reqF(R_API_WORD),
822
+ keyAuth: reqF(R_BOOL),
823
+ authEnv: reqF(R_STR),
824
+ models: reqF(arrayRule(shapeRule("provider model", {
825
+ id: reqF(R_NONEMPTY),
826
+ contextWindow: reqF(R_INT1),
827
+ maxTokens: reqF(R_INT1),
828
+ }))),
829
+ consoleUrl: optF(R_STR),
830
+ }))),
831
+ importable: optF(arrayRule(shapeRule("importable profile", {
832
+ id: reqF(R_NONEMPTY),
833
+ name: reqF(R_STR),
834
+ baseUrl: reqF(R_NONEMPTY),
835
+ api: reqF(R_API_WORD),
836
+ hasKey: reqF(R_BOOL),
837
+ models: reqF(arrayRule(R_NONEMPTY)),
838
+ }))),
839
+ }));
840
+ const checkSessionMcpPanelFailure = seatShapeCheck(armsRule("readSessionMcpPanel failure", "kind", {
841
+ unreadable: DEVICE_UNREADABLE_SPEC,
842
+ transport: DEVICE_TRANSPORT_SPEC,
843
+ unarmed: {},
844
+ }));
845
+ function mcpPanelLivenessArms() {
846
+ const arms = {};
847
+ for (const state of MCP_LIVENESS_STATES)
848
+ arms[state] = state === "unreachable" ? { observedAt: reqF(R_NUM), errorCode: optF(R_NONEMPTY) } : { observedAt: reqF(R_NUM) };
849
+ const keysPin = [true, true];
850
+ void keysPin;
851
+ return arms;
852
+ }
853
+ const MCP_PANEL_LIVENESS_VIEW = armsRule("mcp liveness", "state", mcpPanelLivenessArms());
854
+ const MCP_PANEL_LEG_ENTRY = shapeRule("leg entry", {
855
+ name: reqF(R_NONEMPTY),
856
+ status: reqF(R_NONEMPTY),
857
+ source: optF(R_NONEMPTY),
858
+ errorCode: optF(R_NONEMPTY),
859
+ toolCount: optF(R_NUM),
860
+ delivered: optF(R_NONEMPTY),
861
+ httpStatus: optF(R_NUM),
862
+ liveness: optF(MCP_PANEL_LIVENESS_VIEW),
863
+ livenessUnreadable: optF(R_TRUE),
864
+ });
865
+ const MCP_PANEL_LAST_LEG = shapeRule("last leg", {
866
+ runId: reqF(R_NONEMPTY),
867
+ at: reqF(R_NONEMPTY),
868
+ mcp: reqF(arrayRule(MCP_PANEL_LEG_ENTRY)),
869
+ });
870
+ const MCP_PANEL_SERVER_ROW = shapeRule("panel server", {
871
+ name: reqF(R_NONEMPTY),
872
+ status: reqF(R_NONEMPTY),
873
+ serverInfo: optF(shapeRule("server info", {
874
+ name: reqF(R_STR),
875
+ version: reqF(R_STR),
876
+ })),
877
+ toolNames: optF(arrayRule(R_STR)),
878
+ error: optF(R_STR),
879
+ });
880
+ const MCP_PANEL_SCENARIO_REFUSAL = shapeRule("scenario refusal", {
881
+ errorCode: optF(R_NONEMPTY),
882
+ error: optF(R_STR),
883
+ scenario: optF(R_NONEMPTY),
884
+ source: optF(oneOfRule("refusal source", ["ruling", "deployment"])),
885
+ });
886
+ const checkSessionMcpPanelServersView = seatShapeCheck(shapeRule("servers view", {
887
+ asOf: reqF(R_NONEMPTY),
888
+ lastLegMcp: optF(MCP_PANEL_LAST_LEG),
889
+ lastLegMcpUnreadable: optF(R_TRUE),
890
+ servers: reqF(arrayRule(MCP_PANEL_SERVER_ROW)),
891
+ degraded: optF(R_TRUE),
892
+ }));
893
+ const checkSessionMcpPanelRefusalView = seatShapeCheck(shapeRule("refusal view", {
894
+ asOf: reqF(R_NONEMPTY),
895
+ lastLegMcp: optF(MCP_PANEL_LAST_LEG),
896
+ lastLegMcpUnreadable: optF(R_TRUE),
897
+ scenarioRefusal: reqF(MCP_PANEL_SCENARIO_REFUSAL),
898
+ }));
899
+ const checkSessionMcpPanelResult = seatCheck((v) => {
900
+ if (!isPlainRecord(v))
901
+ return bad("mcp panel result is not a plain object");
902
+ if (Object.hasOwn(v, "kind"))
903
+ return checkSessionMcpPanelFailure(v);
904
+ return Object.hasOwn(v, "scenarioRefusal") ? checkSessionMcpPanelRefusalView(v) : checkSessionMcpPanelServersView(v);
905
+ });
906
+ const MCP_TOOL_TOGGLE_KEY = shapeRule("toggle key", {
907
+ server: reqF(R_NONEMPTY),
908
+ tool: reqF(R_NONEMPTY),
909
+ });
910
+ export const checkMcpToolToggleKey = seatShapeCheck(MCP_TOOL_TOGGLE_KEY);
911
+ const checkMcpToolTogglesResult = seatShapeCheck(shapeRule("toggles result", { off: reqF(arrayRule(MCP_TOOL_TOGGLE_KEY)) }));
408
912
  const checkLocalSessionRecord = seatCheck((s) => {
409
913
  if (!isPlainRecord(s))
410
914
  return bad("session record is not a plain object");
@@ -505,6 +1009,91 @@ const checkLaneProof = seatCheckAt((v, field) => {
505
1009
  }
506
1010
  return true;
507
1011
  });
1012
+ const R_NEVER = ruleOf("absent", () => false);
1013
+ const RETRY_ERROR_PAYLOAD = shapeRule("retry error", {
1014
+ formatted: reqF(R_STR),
1015
+ isNetworkDown: optF(R_BOOL),
1016
+ connection: optF(shapeRule("connection", { isSSLError: optF(R_BOOL) })),
1017
+ rateLimits: optF({
1018
+ label: "rate limits",
1019
+ test: (v, path) => v === null
1020
+ ? true
1021
+ : shapeVerdict({ resetsAt: optF(R_NUM), rateLimitType: optF(R_STR) }, v, path),
1022
+ }),
1023
+ });
1024
+ const RETRY_COMMON_SPEC = {
1025
+ deadline: reqF(R_NUM),
1026
+ attempt: optF(R_NUM),
1027
+ maxRetries: optF(R_NUM),
1028
+ errClass: optF(R_STR),
1029
+ retryAtMs: optF(R_NUM),
1030
+ errorStatus: optF(R_NUM),
1031
+ providerCondition: optF(R_STR),
1032
+ providerConditionSource: optF(R_STR),
1033
+ elapsedMs: optF(R_NUM),
1034
+ timeoutMs: optF(R_NUM),
1035
+ };
1036
+ const RETRY_STATUS = armsRule("retry status", "kind", {
1037
+ stalled: { ...RETRY_COMMON_SPEC, detail: optF(R_STR) },
1038
+ error: { ...RETRY_COMMON_SPEC, terminal: optF(R_TRUE), error: reqF(RETRY_ERROR_PAYLOAD) },
1039
+ waiting: { ...RETRY_COMMON_SPEC, terminal: optF(R_NEVER), error: reqF(RETRY_ERROR_PAYLOAD) },
1040
+ });
1041
+ const ENGINE_TURN_USAGE = shapeRule("engine usage", {
1042
+ inputTokens: reqF(R_NUM),
1043
+ totalInputTokens: reqF(R_NUM),
1044
+ outputTokens: reqF(R_NUM),
1045
+ cacheReadTokens: reqF(R_NUM),
1046
+ cacheWriteTokens: reqF(R_NUM),
1047
+ costMicroUsd: reqF(R_NUM),
1048
+ });
1049
+ const SEMA_MODEL_USAGE = shapeRule("model usage", {
1050
+ inputTokens: reqF(R_NUM),
1051
+ outputTokens: reqF(R_NUM),
1052
+ cacheReadInputTokens: reqF(R_NUM),
1053
+ cacheCreationInputTokens: reqF(R_NUM),
1054
+ webSearchRequests: reqF(R_NUM),
1055
+ costUSD: reqF(R_NUM),
1056
+ contextWindow: reqF(R_NUM),
1057
+ maxOutputTokens: reqF(R_NUM),
1058
+ canonicalModel: optF(R_STR),
1059
+ provider: optF(R_STR),
1060
+ _sema_cost_absent: optF(R_TRUE),
1061
+ _sema_web_search_requests_absent: optF(R_TRUE),
1062
+ _sema_context_window_absent: optF(R_TRUE),
1063
+ _sema_max_output_tokens_absent: optF(R_TRUE),
1064
+ });
1065
+ const SEAT_CHROME_PAYLOAD_SPECS = {
1066
+ retry_status: { status: reqF({ label: "retry status", test: (v, path) => (v === null ? true : RETRY_STATUS.test(v, path)) }) },
1067
+ context_usage: {
1068
+ usedTokens: optF(R_NUM),
1069
+ windowTokens: optF(R_NUM),
1070
+ compactAtTokens: optF(R_NUM),
1071
+ sections: optF(arrayRule(shapeRule("section", { id: reqF(R_STR), tokens: reqF(R_NUM), kind: optF(R_STR) }))),
1072
+ eventId: optF(R_NONEMPTY),
1073
+ },
1074
+ last_turn_usage: {
1075
+ usage: reqF(SEMA_MODEL_USAGE),
1076
+ engineUsage: optF(ENGINE_TURN_USAGE),
1077
+ engineUsageUnknownKeys: optF(R_INT1),
1078
+ usageMissing: optF(R_TRUE),
1079
+ stopReason: optF(R_STR),
1080
+ responseModel: optF(R_NONEMPTY),
1081
+ },
1082
+ bgshell_register: {
1083
+ taskId: reqF(R_NONEMPTY),
1084
+ registration: reqF(shapeRule("registration", {
1085
+ kind: reqF(oneOfRule("registration kind", ["register"])),
1086
+ taskId: reqF(R_NONEMPTY),
1087
+ command: reqF(R_STR),
1088
+ description: optF(R_STR),
1089
+ receipt: reqF(R_STR),
1090
+ source: reqF(oneOfRule("registration source", ["bash", "monitor"])),
1091
+ })),
1092
+ },
1093
+ bgshell_settle: { taskId: reqF(R_NONEMPTY), status: reqF(R_STR), outputPath: optF(R_STR) },
1094
+ memory_saved: { id: reqF(R_NONEMPTY), notes: reqF(arrayRule(R_NONEMPTY, true)) },
1095
+ };
1096
+ const ENVELOPE_ROWS = { kind: reqF({ label: "kind", test: () => true }), laneProof: reqF({ label: "laneProof", test: () => true }) };
508
1097
  const checkSeatChromeEnvelope = seatCheckAt((v, field) => {
509
1098
  if (!isPlainRecord(v))
510
1099
  return bad("chrome must be a plain object", field);
@@ -514,7 +1103,13 @@ const checkSeatChromeEnvelope = seatCheckAt((v, field) => {
514
1103
  if (!inTuple(CHROME_EVENT_KIND_TUPLE, kind)) {
515
1104
  return bad(`chrome.kind is not a renderer-wired arm (${CHROME_EVENT_KIND_TUPLE.join("|")})`, `${field}.kind`);
516
1105
  }
517
- return checkLaneProof(own(v, "laneProof"), `${field}.laneProof`);
1106
+ const lane = checkLaneProof(own(v, "laneProof"), `${field}.laneProof`);
1107
+ if (lane !== true)
1108
+ return lane;
1109
+ if (Object.hasOwn(SEAT_CHROME_PAYLOAD_SPECS, kind)) {
1110
+ return shapeVerdict({ ...ENVELOPE_ROWS, ...SEAT_CHROME_PAYLOAD_SPECS[kind] }, v, field);
1111
+ }
1112
+ return true;
518
1113
  });
519
1114
  const checkLocalSessionEvent = seatCheck((v) => {
520
1115
  if (!isPlainRecord(v))
@@ -534,18 +1129,6 @@ const checkLocalSessionEvent = seatCheck((v) => {
534
1129
  const code = own(v, "code");
535
1130
  if (!isAbsent(code) && typeof code !== "number")
536
1131
  return bad("code must be a number when present", "code");
537
- const request = own(v, "request");
538
- if (!isAbsent(request)) {
539
- const verdict = checkToolPermissionRequest(request);
540
- if (verdict !== true)
541
- return nested("request", verdict);
542
- }
543
- const sources = own(v, "sources");
544
- if (!isAbsent(sources)) {
545
- const okSources = Array.isArray(sources) && ownItems(sources).every((t) => typeof t === "string");
546
- if (!okSources)
547
- return bad("sources must be a string[]", "sources");
548
- }
549
1132
  const session = own(v, "session");
550
1133
  if (!isAbsent(session)) {
551
1134
  const verdict = checkLocalSessionRecord(session);
@@ -573,8 +1156,43 @@ const checkLocalSessionEvent = seatCheck((v) => {
573
1156
  if (verdict !== true)
574
1157
  return nested("chrome", verdict);
575
1158
  }
1159
+ const sub = own(v, "subagentContent");
1160
+ if (type === "subagent_content") {
1161
+ if (isAbsent(sub))
1162
+ return bad("missing key", "subagentContent");
1163
+ const verdict = SUBAGENT_CONTENT_SHAPE.test(sub, "subagentContent");
1164
+ if (verdict !== true)
1165
+ return verdict;
1166
+ }
1167
+ else if (!isAbsent(sub)) {
1168
+ return bad("unexpected key", "subagentContent");
1169
+ }
576
1170
  return true;
577
1171
  });
1172
+ const SUBAGENT_CONTENT_SHAPE = shapeRule("subagent content", {
1173
+ type: reqF(oneOfRule("content type", ["text_delta", "reasoning_delta", "text", "reasoning", "tool_start", "tool_end"])),
1174
+ taskId: reqF(R_NONEMPTY),
1175
+ parentToolCallId: reqF(R_NONEMPTY),
1176
+ delta: optF(R_STR),
1177
+ text: optF(R_STR),
1178
+ eventId: optF(R_STR),
1179
+ toolCallId: optF(R_STR),
1180
+ toolName: optF(R_STR),
1181
+ args: optF({ label: "passthrough", test: () => true }),
1182
+ output: optF(R_STR),
1183
+ isError: optF(R_BOOL),
1184
+ });
1185
+ export function readSeatSubagentContent(event) {
1186
+ try {
1187
+ if (checkLocalSessionEvent(event) !== true || own(event, "type") !== "subagent_content")
1188
+ return undefined;
1189
+ const sub = own(event, "subagentContent");
1190
+ return { ...sub };
1191
+ }
1192
+ catch {
1193
+ return undefined;
1194
+ }
1195
+ }
578
1196
  export function isLocalSessionEvent(v) {
579
1197
  return checkLocalSessionEvent(v) === true;
580
1198
  }
@@ -945,6 +1563,23 @@ export const LOCAL_SESSIONS_SPEC = {
945
1563
  pickFolder: { kind: "invoke", check: checkPickFolderResult },
946
1564
  listRecentFolders: { kind: "invoke", check: checkRecentFoldersResult },
947
1565
  noteRecentFolder: { kind: "invoke", check: checkOkAck }, patchSession: { kind: "invoke", check: checkLocalSessionRecord },
1566
+ listDevices: { kind: "invoke", check: checkDeviceListOutcome },
1567
+ readSessionBinding: { kind: "invoke", check: checkDeviceSessionBindingOutcome },
1568
+ rebindSession: { kind: "invoke", check: checkDeviceRebindOutcome },
1569
+ issueEnrollToken: { kind: "invoke", check: checkDeviceEnrollTokenOutcome },
1570
+ revokeDevice: { kind: "invoke", check: checkDeviceRevokeOutcome },
1571
+ setEngineMode: { kind: "invoke", check: checkEngineTargetResult },
1572
+ startCloudLogin: { kind: "invoke", check: checkCloudLoginStart },
1573
+ cancelCloudLogin: { kind: "invoke", check: checkCancelCloudLogin },
1574
+ connectCloudEngine: { kind: "invoke", check: checkCloudConnectResult },
1575
+ configureCloudEngine: { kind: "invoke", check: checkCloudConnectResult },
1576
+ clearCloudEngine: { kind: "invoke", check: checkEngineTargetResult },
1577
+ listOnboardProviders: { kind: "invoke", check: checkOnboardProvidersResult },
1578
+ probeOnboardEntry: { kind: "invoke", check: checkOnboardProbeResult },
1579
+ applyOnboardEntry: { kind: "invoke", check: checkOnboardApplyResult },
1580
+ readSessionMcpPanel: { kind: "invoke", check: checkSessionMcpPanelResult },
1581
+ listMcpToolToggles: { kind: "invoke", check: checkMcpToolTogglesResult },
1582
+ setMcpToolToggle: { kind: "invoke", check: checkOkAck },
948
1583
  onEvent: { kind: "event", check: checkLocalSessionEvent },
949
1584
  onToolPermissionRequest: { kind: "event", check: checkToolPermissionRequest },
950
1585
  },
@@ -953,6 +1588,7 @@ export const LOCAL_SESSIONS_SPEC = {
953
1588
  focusedSessionState: { check: checkFocusedSessionState },
954
1589
  settingsState: { check: checkSettingsState },
955
1590
  seatCapabilitiesState: { check: checkSeatCapabilitiesState },
1591
+ engineTargetState: { check: checkEngineTargetState },
956
1592
  },
957
1593
  };
958
1594
  export const SEAT_METHOD_NAMES = [
@@ -974,6 +1610,23 @@ export const SEAT_METHOD_NAMES = [
974
1610
  "pickFolder",
975
1611
  "listRecentFolders",
976
1612
  "noteRecentFolder", "patchSession",
1613
+ "listDevices",
1614
+ "readSessionBinding",
1615
+ "rebindSession",
1616
+ "issueEnrollToken",
1617
+ "revokeDevice",
1618
+ "setEngineMode",
1619
+ "startCloudLogin",
1620
+ "cancelCloudLogin",
1621
+ "connectCloudEngine",
1622
+ "configureCloudEngine",
1623
+ "clearCloudEngine",
1624
+ "listOnboardProviders",
1625
+ "probeOnboardEntry",
1626
+ "applyOnboardEntry",
1627
+ "readSessionMcpPanel",
1628
+ "listMcpToolToggles",
1629
+ "setMcpToolToggle",
977
1630
  "onEvent",
978
1631
  "onToolPermissionRequest",
979
1632
  ];
@@ -982,6 +1635,7 @@ export const SEAT_STORE_PROPS = [
982
1635
  "focusedSessionStateStore",
983
1636
  "settingsStateStore",
984
1637
  "seatCapabilitiesStateStore",
1638
+ "engineTargetStateStore",
985
1639
  ];
986
1640
  export const SEAT_EVENT_METHOD_NAMES = ["onEvent", "onToolPermissionRequest"];
987
1641
  export const LOCAL_SESSION_EVENT_KEYS = [
@@ -991,8 +1645,6 @@ export const LOCAL_SESSION_EVENT_KEYS = [
991
1645
  "error",
992
1646
  "errorCategory",
993
1647
  "code",
994
- "request",
995
- "sources",
996
1648
  "session",
997
1649
  "userMessageUuid",
998
1650
  "requestId",
@@ -1000,6 +1652,7 @@ export const LOCAL_SESSION_EVENT_KEYS = [
1000
1652
  "parked",
1001
1653
  "chrome",
1002
1654
  "_sema_turnFailure",
1655
+ "subagentContent",
1003
1656
  ];
1004
1657
  export const TOOL_PERMISSION_REQUEST_KEYS = [
1005
1658
  "requestId",
@@ -1135,14 +1788,13 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
1135
1788
  "error",
1136
1789
  "errorCategory",
1137
1790
  "code",
1138
- "request",
1139
- "sources",
1140
1791
  "session",
1141
1792
  "userMessageUuid",
1142
1793
  "requestId",
1143
1794
  "outcome",
1144
1795
  "parked",
1145
1796
  "chrome",
1797
+ "subagentContent",
1146
1798
  ],
1147
1799
  unchecked: [
1148
1800
  {
@@ -1254,7 +1906,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
1254
1906
  },
1255
1907
  SeatCapabilitiesState: {
1256
1908
  check: checkSeatCapabilitiesState,
1257
- validated: ["pickFolder", "rewind", "recents", "patchSession"],
1909
+ validated: ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles"],
1258
1910
  unchecked: [],
1259
1911
  },
1260
1912
  RecentFoldersResult: {
@@ -1287,8 +1939,41 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
1287
1939
  validated: ["kind", "laneProof"],
1288
1940
  unchecked: [],
1289
1941
  },
1942
+ SessionMcpPanelResult: {
1943
+ check: checkSessionMcpPanelResult,
1944
+ validated: ["kind", "why", "detail", "asOf", "servers", "lastLegMcp", "lastLegMcpUnreadable", "degraded", "scenarioRefusal"],
1945
+ unchecked: [],
1946
+ },
1290
1947
  };
1291
1948
  export const SEAT_VALIDATOR_COVERAGE_EXEMPT = [
1949
+ ...[
1950
+ ["DeviceListOutcome", checkDeviceListOutcome],
1951
+ ["DeviceSessionBindingOutcome", checkDeviceSessionBindingOutcome],
1952
+ ["DeviceRebindOutcome", checkDeviceRebindOutcome],
1953
+ ["DeviceEnrollTokenOutcome", checkDeviceEnrollTokenOutcome],
1954
+ ["DeviceRevokeOutcome", checkDeviceRevokeOutcome],
1955
+ ["SeatDeviceRebindRequest", checkSeatDeviceRebindRequest],
1956
+ ["SeatDeviceRevokeRequest", checkSeatDeviceRevokeRequest],
1957
+ ["EngineTargetState", checkEngineTargetState],
1958
+ ["EngineTargetResult", checkEngineTargetResult],
1959
+ ["CloudLoginStart", checkCloudLoginStart],
1960
+ ["CloudLoginCancelAck", checkCancelCloudLogin],
1961
+ ["CloudConnectResult", checkCloudConnectResult],
1962
+ ["CloudLoginRequest", checkCloudLoginRequest],
1963
+ ["CloudEngineConnectRequest", checkCloudEngineConnectRequest],
1964
+ ["CloudEngineConfigureRequest", checkCloudEngineConfigureRequest],
1965
+ ["OnboardProvidersResult", checkOnboardProvidersResult],
1966
+ ["OnboardProbeResult", checkOnboardProbeResult],
1967
+ ["OnboardApplyResult", checkOnboardApplyResult],
1968
+ ["OnboardEntryRequest", checkOnboardEntryRequest],
1969
+ ["OnboardApplyRequest", checkOnboardApplyRequest],
1970
+ ["McpToolTogglesResult", checkMcpToolTogglesResult],
1971
+ ["McpToolToggleKey", checkMcpToolToggleKey],
1972
+ ].map(([label, check]) => ({
1973
+ label,
1974
+ check,
1975
+ why: "座位闭形规则铸的判官(规格表型由对象型派生,键集与必选性编译期两向钉);逐臂逐键投毒在三只席位门(见上方注)。",
1976
+ })),
1292
1977
  {
1293
1978
  label: "PickFolderResult",
1294
1979
  check: checkPickFolderResult,
@@ -1333,5 +2018,8 @@ const _seatContractPins = [
1333
2018
  true, true, true, true, true, true,
1334
2019
  true, true,
1335
2020
  true, true, true, true,
2021
+ true, true, true,
2022
+ true,
2023
+ true, true, true,
1336
2024
  ];
1337
2025
  void _seatContractPins;