@sema-agent/client-core 0.98.0 → 0.99.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/CHANGELOG.md +199 -0
  2. package/README.md +35 -22
  3. package/dist/adapt/arms.js +61 -20
  4. package/dist/adapt/panelTasks.d.ts +1 -1
  5. package/dist/adapt/panelTasks.js +2 -2
  6. package/dist/adapter/activeRunSelfHeal.d.ts +4 -3
  7. package/dist/adapter/activeRunSelfHeal.js +162 -293
  8. package/dist/adapter/downstream/eventToSdkMessage.js +52 -4
  9. package/dist/adapter/runStream.js +52 -37
  10. package/dist/adapter/types.js +2 -1
  11. package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
  12. package/dist/agentsWireCaps.d.ts +0 -3
  13. package/dist/agentsWireCaps.js +33 -24
  14. package/dist/cloudConfigWireCaps.d.ts +1 -1
  15. package/dist/cloudConfigWireCaps.js +26 -4
  16. package/dist/controlRouter.d.ts +4 -2
  17. package/dist/controlRouter.js +39 -51
  18. package/dist/coreValuePorts.d.ts +26 -1
  19. package/dist/coreValuePorts.js +10 -0
  20. package/dist/corruptSessionCopy.d.ts +2 -1
  21. package/dist/corruptSessionCopy.js +3 -3
  22. package/dist/declared/supportFloorDeclared.js +1 -1
  23. package/dist/detachWire.js +3 -2
  24. package/dist/devicesFace.d.ts +34 -0
  25. package/dist/devicesFace.js +90 -0
  26. package/dist/displayUntrusted.d.ts +1 -0
  27. package/dist/displayUntrusted.js +3 -0
  28. package/dist/engineAgentPanelStore.d.ts +7 -0
  29. package/dist/engineAgentPanelStore.js +14 -0
  30. package/dist/engineCapReader.d.ts +2 -1
  31. package/dist/engineCapReader.js +7 -5
  32. package/dist/engineCapsCache.d.ts +8 -0
  33. package/dist/engineCapsCache.js +59 -6
  34. package/dist/engineCapsChange.d.ts +2 -0
  35. package/dist/engineCapsChange.js +9 -0
  36. package/dist/engineErrorCodes.d.ts +2 -1
  37. package/dist/engineErrorCodes.js +2 -7
  38. package/dist/engineRowRef.js +3 -0
  39. package/dist/engineSessionMessages.d.ts +1 -0
  40. package/dist/engineSessionMessages.js +7 -1
  41. package/dist/engineTargetSeat.d.ts +27 -0
  42. package/dist/engineTargetSeat.js +199 -0
  43. package/dist/engineWireFor.js +3 -8
  44. package/dist/env/uiLanguage.d.ts +2 -1
  45. package/dist/env/uiLanguage.js +3 -2
  46. package/dist/eventLeg.d.ts +8 -0
  47. package/dist/eventLeg.js +61 -41
  48. package/dist/fileHistoryCaptureCapability.d.ts +2 -1
  49. package/dist/fileHistoryCaptureCapability.js +12 -18
  50. package/dist/fileHistoryLegNotice.d.ts +2 -1
  51. package/dist/fileHistoryLegNotice.js +3 -3
  52. package/dist/frameBinding.d.ts +3 -0
  53. package/dist/frameBinding.js +12 -0
  54. package/dist/gateOutcome.js +16 -2
  55. package/dist/gateVocabulary.d.ts +8 -7
  56. package/dist/gateVocabulary.js +71 -73
  57. package/dist/generated/engineFactTables.d.ts +17 -1
  58. package/dist/generated/engineFactTables.js +29 -0
  59. package/dist/generated/engineNoticeTables.js +9 -3
  60. package/dist/generated/settingsSchemaFns.d.ts +6 -0
  61. package/dist/generated/settingsSchemaFns.js +57 -0
  62. package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
  63. package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
  64. package/dist/generated/settingsSchemaTables.d.ts +1 -0
  65. package/dist/generated/settingsSchemaTables.js +4 -0
  66. package/dist/generated/settingsSchemaTypes.d.ts +105 -0
  67. package/dist/generated/settingsSchemaTypes.js +1 -0
  68. package/dist/hitl/allowRuleShadow.d.ts +2 -1
  69. package/dist/hitl/allowRuleShadow.js +17 -14
  70. package/dist/hitl/approvalCardReasons.d.ts +3 -2
  71. package/dist/hitl/approvalCardReasons.js +27 -28
  72. package/dist/hitl/approvalHolds.d.ts +3 -0
  73. package/dist/hitl/approvalHolds.js +73 -29
  74. package/dist/hitl/askClassPair.d.ts +1 -1
  75. package/dist/hitl/askClassPair.js +16 -0
  76. package/dist/hitl/askGateWire.js +2 -1
  77. package/dist/hitl/askSettlementLine.d.ts +14 -4
  78. package/dist/hitl/askSettlementLine.js +67 -47
  79. package/dist/hitl/automaticAnswerVerdict.d.ts +2 -1
  80. package/dist/hitl/automaticAnswerVerdict.js +8 -8
  81. package/dist/hitl/crashConvergedNotice.d.ts +5 -4
  82. package/dist/hitl/crashConvergedNotice.js +28 -41
  83. package/dist/hitl/frameRouter.js +7 -8
  84. package/dist/hitl/hitlBridge.d.ts +1 -0
  85. package/dist/hitl/hitlBridge.js +3 -3
  86. package/dist/hitl/persistedRulesWire.d.ts +6 -5
  87. package/dist/hitl/persistedRulesWire.js +55 -73
  88. package/dist/hitl/planReviewWire.d.ts +5 -0
  89. package/dist/hitl/planReviewWire.js +8 -0
  90. package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
  91. package/dist/hitl/sessionPolicyDeliverable.js +46 -3
  92. package/dist/hitl/sessionPolicyWire.d.ts +2 -1
  93. package/dist/hitl/sessionPolicyWire.js +23 -24
  94. package/dist/hitl/suspendedReopen.d.ts +2 -1
  95. package/dist/hitl/suspendedReopen.js +7 -10
  96. package/dist/hitl/toolApprovalWire.d.ts +17 -5
  97. package/dist/hitl/toolApprovalWire.js +79 -40
  98. package/dist/hooksWireCaps.js +145 -56
  99. package/dist/host.d.ts +21 -0
  100. package/dist/hostTurnSettings.d.ts +71 -0
  101. package/dist/hostTurnSettings.js +291 -0
  102. package/dist/humanTurn.d.ts +14 -1
  103. package/dist/humanTurn.js +100 -12
  104. package/dist/humanTurnRead.d.ts +2 -0
  105. package/dist/humanTurnRead.js +22 -1
  106. package/dist/i18n/messages.en.d.ts +582 -0
  107. package/dist/i18n/messages.en.js +582 -0
  108. package/dist/i18n/messages.zh.js +718 -1
  109. package/dist/index.d.ts +29 -13
  110. package/dist/index.js +18 -9
  111. package/dist/inheritEnvCapability.d.ts +3 -2
  112. package/dist/inheritEnvCapability.js +3 -3
  113. package/dist/inheritEnvWire.d.ts +3 -2
  114. package/dist/inheritEnvWire.js +12 -14
  115. package/dist/interactiveHalt.js +17 -6
  116. package/dist/liveModelCatalog.d.ts +2 -1
  117. package/dist/liveModelCatalog.js +14 -8
  118. package/dist/mcpPanel.d.ts +10 -1
  119. package/dist/mcpPanel.js +40 -13
  120. package/dist/mcpProbeCapability.d.ts +2 -1
  121. package/dist/mcpProbeCapability.js +7 -11
  122. package/dist/mcpProbeWire.d.ts +3 -1
  123. package/dist/mcpProbeWire.js +5 -0
  124. package/dist/mcpWireCaps.d.ts +34 -0
  125. package/dist/mcpWireCaps.js +117 -17
  126. package/dist/memoryEntriesWire.js +5 -10
  127. package/dist/model/onboardJudgement.d.ts +93 -0
  128. package/dist/model/onboardJudgement.js +415 -0
  129. package/dist/model/tierVocabulary.d.ts +2 -0
  130. package/dist/model/tierVocabulary.js +17 -5
  131. package/dist/modelCapabilityProbe.d.ts +64 -0
  132. package/dist/modelCapabilityProbe.js +600 -0
  133. package/dist/modelIdentityResolvability.d.ts +3 -0
  134. package/dist/modelIdentityResolvability.js +26 -17
  135. package/dist/ownKey.d.ts +7 -0
  136. package/dist/ownKey.js +34 -0
  137. package/dist/panelReduce.d.ts +6 -1
  138. package/dist/panelReduce.js +50 -3
  139. package/dist/permissionRuleIssue.js +2 -0
  140. package/dist/permissionRulesWriteCapability.d.ts +2 -1
  141. package/dist/permissionRulesWriteCapability.js +8 -6
  142. package/dist/pluginHooksWire.d.ts +46 -3
  143. package/dist/pluginHooksWire.js +217 -11
  144. package/dist/printModelStatus.d.ts +63 -0
  145. package/dist/printModelStatus.js +155 -0
  146. package/dist/request/taskRequest.d.ts +11 -5
  147. package/dist/request/taskRequest.js +112 -16
  148. package/dist/resumeRefusalCopy.d.ts +12 -9
  149. package/dist/resumeRefusalCopy.js +70 -143
  150. package/dist/retryStatus.d.ts +37 -0
  151. package/dist/retryStatus.js +79 -0
  152. package/dist/scenarioRefusal.d.ts +9 -0
  153. package/dist/scenarioRefusal.js +111 -0
  154. package/dist/seam.d.ts +25 -1
  155. package/dist/seam.js +10 -1
  156. package/dist/seatContract.d.ts +260 -10
  157. package/dist/seatContract.js +692 -19
  158. package/dist/selfOrchestrationDenial.js +7 -19
  159. package/dist/sessionIdSegment.d.ts +6 -0
  160. package/dist/sessionIdSegment.js +24 -0
  161. package/dist/sessionMemoryStatus.js +6 -11
  162. package/dist/sessionPolicyCapability.d.ts +2 -1
  163. package/dist/sessionPolicyCapability.js +8 -6
  164. package/dist/settingsHooksSalvage.d.ts +44 -0
  165. package/dist/settingsHooksSalvage.js +211 -0
  166. package/dist/skillToolListsCapability.d.ts +2 -1
  167. package/dist/skillToolListsCapability.js +8 -6
  168. package/dist/sseIdleTriage.js +3 -2
  169. package/dist/subagent/engineSubagentResume.js +15 -9
  170. package/dist/subagentContentStore.d.ts +3 -0
  171. package/dist/subagentContentStore.js +22 -0
  172. package/dist/toolHistoryMismatch.js +3 -2
  173. package/dist/toolRoster.d.ts +3 -2
  174. package/dist/toolRoster.js +21 -20
  175. package/dist/turnFailurePresentation.d.ts +12 -1
  176. package/dist/turnFailurePresentation.js +212 -15
  177. package/dist/usageAnalytics.js +6 -11
  178. package/dist/userAttachmentEnvelope.d.ts +1 -0
  179. package/dist/userAttachmentEnvelope.js +37 -7
  180. package/dist/userAttachmentSeat.d.ts +21 -0
  181. package/dist/userAttachmentSeat.js +75 -0
  182. package/dist/userInvokedSkillsCapability.d.ts +11 -1
  183. package/dist/userInvokedSkillsCapability.js +31 -7
  184. package/dist/wireErrorTriage.d.ts +7 -0
  185. package/dist/wireErrorTriage.js +23 -1
  186. package/dist/wireFailureShape.js +2 -1
  187. package/dist/wireRefusalCopy.d.ts +13 -1
  188. package/dist/wireRefusalCopy.js +24 -28
  189. package/dist/workflowsJournalCapability.d.ts +2 -1
  190. package/dist/workflowsJournalCapability.js +8 -6
  191. package/docs/INTEGRATION-CLIENTS.md +542 -30
  192. package/package.json +5 -5
@@ -0,0 +1,254 @@
1
+ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
2
+ const HOOK_GUARD_EVENTS = ["PreToolUse", "PermissionRequest"];
3
+ const HOOK_SHELLS = ["bash", "powershell"];
4
+ const HOOK_ENTRY_COMMON_FIELDS = { if: "string?", timeout: "seconds?", statusMessage: "string?", once: "boolean?" };
5
+ const HOOK_ENTRY_FIELDS = {
6
+ command: { command: "text", shell: "shell?", async: "boolean?", asyncRewake: "boolean?", ...HOOK_ENTRY_COMMON_FIELDS },
7
+ prompt: { prompt: "text", model: "string?", ...HOOK_ENTRY_COMMON_FIELDS },
8
+ agent: { prompt: "text", model: "string?", ...HOOK_ENTRY_COMMON_FIELDS },
9
+ http: { url: "text", headers: "stringRecord?", allowedEnvVars: "stringList?", ...HOOK_ENTRY_COMMON_FIELDS },
10
+ mcp_tool: { server: "string", tool: "string", input: "record?", ...HOOK_ENTRY_COMMON_FIELDS },
11
+ };
12
+ function hookIsRecord(value) {
13
+ if (value === null || typeof value !== "object" || Array.isArray(value))
14
+ return false;
15
+ const proto = Object.getPrototypeOf(value);
16
+ return proto === Object.prototype || proto === null;
17
+ }
18
+ function hookGuardKeyOf(node) {
19
+ for (const key of Object.keys(node)) {
20
+ if (!HOOK_GUARD_EVENTS.includes(key))
21
+ continue;
22
+ const value = node[key];
23
+ if (value !== null && value !== undefined && !(Array.isArray(value) && value.length === 0))
24
+ return key;
25
+ }
26
+ return undefined;
27
+ }
28
+ function hookLooksLikeMatcher(value) {
29
+ if (!hookIsRecord(value))
30
+ return false;
31
+ const inner = Object.hasOwn(value, "hooks") ? value.hooks : undefined;
32
+ if (Array.isArray(inner))
33
+ return inner.length > 0;
34
+ return hookIsRecord(inner) && (Object.hasOwn(value, "matcher") || typeof inner.type === "string");
35
+ }
36
+ function hookGuardSignIn(root, rootPath, place) {
37
+ const frames = [];
38
+ const pending = [[root, -1, place]];
39
+ const seen = { matcherList: new Set(), matcher: new Set(), other: new Set() };
40
+ const pathTo = (frame, tail) => {
41
+ const segments = [...tail];
42
+ for (let f = frame; f >= 0; f = frames[f].parent)
43
+ segments.unshift(frames[f].key);
44
+ return [...rootPath, ...segments];
45
+ };
46
+ while (pending.length > 0) {
47
+ const [node, frame, at] = pending.pop();
48
+ if (node === null || typeof node !== "object" || seen[at].has(node))
49
+ continue;
50
+ seen[at].add(node);
51
+ if (Array.isArray(node)) {
52
+ for (let i = node.length - 1; i >= 0; i--) {
53
+ frames.push({ key: i, parent: frame });
54
+ pending.push([node[i], frames.length - 1, at === "matcherList" ? "matcher" : "other"]);
55
+ }
56
+ continue;
57
+ }
58
+ const guardKey = hookGuardKeyOf(node);
59
+ if (guardKey !== undefined)
60
+ return pathTo(frame, [guardKey]);
61
+ if (at !== "matcher" && hookLooksLikeMatcher(node))
62
+ return pathTo(frame, []);
63
+ const keys = Object.keys(node);
64
+ for (let i = keys.length - 1; i >= 0; i--) {
65
+ frames.push({ key: keys[i], parent: frame });
66
+ pending.push([node[keys[i]], frames.length - 1, "other"]);
67
+ }
68
+ }
69
+ return undefined;
70
+ }
71
+ function hookSignKeyOf(at, sign) {
72
+ const key = sign[at.length];
73
+ return key === undefined ? "hooks" : String(key);
74
+ }
75
+ function hookFieldFits(base, value) {
76
+ switch (base) {
77
+ case "text":
78
+ return typeof value === "string" && value.length > 0 && !value.includes("\0");
79
+ case "string":
80
+ return typeof value === "string";
81
+ case "shell":
82
+ return typeof value === "string" && HOOK_SHELLS.includes(value);
83
+ case "boolean":
84
+ return typeof value === "boolean";
85
+ case "seconds":
86
+ return typeof value === "number" && Number.isFinite(value) && value > 0;
87
+ case "stringRecord":
88
+ return hookIsRecord(value) && Object.values(value).every((v) => typeof v === "string");
89
+ case "stringList":
90
+ if (!Array.isArray(value))
91
+ return false;
92
+ for (let i = 0; i < value.length; i++)
93
+ if (typeof value[i] !== "string")
94
+ return false;
95
+ return true;
96
+ case "record":
97
+ return hookIsRecord(value);
98
+ default: {
99
+ const unknownKind = base;
100
+ throw new Error(`hook entry field table: unknown field kind '${String(unknownKind)}'`);
101
+ }
102
+ }
103
+ }
104
+ function hookEntryRead(entry) {
105
+ if (!hookIsRecord(entry))
106
+ return {};
107
+ const type = Object.hasOwn(entry, "type") ? entry.type : undefined;
108
+ if (typeof type !== "string" || !Object.hasOwn(HOOK_ENTRY_FIELDS, type))
109
+ return { field: "type" };
110
+ const fields = HOOK_ENTRY_FIELDS[type];
111
+ const out = { type };
112
+ for (const field of Object.keys(fields)) {
113
+ const kind = fields[field];
114
+ const optional = kind.endsWith("?");
115
+ const value = Object.hasOwn(entry, field) ? entry[field] : undefined;
116
+ if (value === undefined) {
117
+ if (optional)
118
+ continue;
119
+ return { field };
120
+ }
121
+ const base = (optional ? kind.slice(0, -1) : kind);
122
+ if (!hookFieldFits(base, value))
123
+ return { field };
124
+ out[field] = Array.isArray(value) ? value.slice() : hookIsRecord(value) ? Object.fromEntries(Object.entries(value)) : value;
125
+ }
126
+ return { entry: out };
127
+ }
128
+ function hookMatcherRead(matcher, at, guardEvent, reject, drop) {
129
+ if (!hookIsRecord(matcher)) {
130
+ if (guardEvent || hookGuardSignIn(matcher, at, "matcher") !== undefined)
131
+ reject("guard-matcher-invalid", at);
132
+ else
133
+ drop("matcher-invalid", at);
134
+ return undefined;
135
+ }
136
+ const entries = Object.hasOwn(matcher, "hooks") ? matcher.hooks : undefined;
137
+ const signField = hookGuardKeyOf(matcher) ??
138
+ Object.keys(matcher).find((key) => !(key === "hooks" && Array.isArray(entries)) && hookGuardSignIn(matcher[key], [...at, key], "other") !== undefined);
139
+ if (signField !== undefined) {
140
+ reject("guard-matcher-invalid", at, signField);
141
+ return undefined;
142
+ }
143
+ const entrySigns = [];
144
+ if (Array.isArray(entries))
145
+ for (let j = 0; j < entries.length; j++)
146
+ entrySigns.push(hookGuardSignIn(entries[j], [...at, "hooks", j], "other"));
147
+ const name = Object.hasOwn(matcher, "matcher") ? matcher.matcher : undefined;
148
+ const badField = name !== undefined && typeof name !== "string" ? "matcher" : !Array.isArray(entries) ? "hooks" : undefined;
149
+ if (badField !== undefined || !Array.isArray(entries)) {
150
+ if (guardEvent || entrySigns.some((sign) => sign !== undefined))
151
+ reject("guard-matcher-invalid", at, badField);
152
+ else
153
+ drop("matcher-invalid", at, badField);
154
+ return undefined;
155
+ }
156
+ const kept = [];
157
+ for (let j = 0; j < entries.length; j++) {
158
+ const where = [...at, "hooks", j];
159
+ const sign = entrySigns[j];
160
+ if (sign !== undefined) {
161
+ reject("guard-entry-invalid", where, hookIsRecord(entries[j]) ? hookSignKeyOf(where, sign) : undefined);
162
+ continue;
163
+ }
164
+ const read = hookEntryRead(entries[j]);
165
+ if (read.entry !== undefined)
166
+ kept.push(read.entry);
167
+ else if (guardEvent)
168
+ reject("guard-entry-invalid", where, read.field);
169
+ else
170
+ drop("entry-invalid", where, read.field);
171
+ }
172
+ return typeof name === "string" ? { matcher: name, hooks: kept } : { hooks: kept };
173
+ }
174
+ function hookBlockRead(hooks, reject, drop) {
175
+ if (!hookIsRecord(hooks)) {
176
+ if (Array.isArray(hooks) && hooks.some((x) => x !== null && typeof x === "object"))
177
+ reject("hooks-is-matcher", ["hooks"]);
178
+ else
179
+ drop("hooks-not-object", ["hooks"]);
180
+ return undefined;
181
+ }
182
+ if (hookLooksLikeMatcher(hooks) || typeof hooks.type === "string") {
183
+ reject("hooks-is-matcher", ["hooks"]);
184
+ return undefined;
185
+ }
186
+ const loaded = {};
187
+ for (const event of Object.keys(hooks)) {
188
+ const value = hooks[event];
189
+ const at = ["hooks", event];
190
+ if (!HOOK_EVENTS.includes(event)) {
191
+ if (hookGuardSignIn(value, at, Array.isArray(value) ? "matcherList" : "other") !== undefined)
192
+ reject("guard-under-unknown-event", at);
193
+ else
194
+ drop("unknown-event", at);
195
+ continue;
196
+ }
197
+ const guardEvent = HOOK_GUARD_EVENTS.includes(event);
198
+ if (!Array.isArray(value)) {
199
+ if ((guardEvent && value !== null) || hookGuardSignIn(value, at, "other") !== undefined)
200
+ reject("guard-event-not-array", at);
201
+ else
202
+ drop("event-not-array", at);
203
+ continue;
204
+ }
205
+ const matchers = [];
206
+ for (let i = 0; i < value.length; i++) {
207
+ const read = hookMatcherRead(value[i], [...at, i], guardEvent, reject, drop);
208
+ if (read !== undefined)
209
+ matchers.push(read);
210
+ }
211
+ loaded[event] = matchers;
212
+ }
213
+ return loaded;
214
+ }
215
+ function classifyHooksConfig(settingsDoc) {
216
+ const rejections = [];
217
+ const dropped = [];
218
+ const reject = (code, path, field) => {
219
+ rejections.push(field === undefined ? { code, path } : { code, path, field });
220
+ };
221
+ const drop = (code, path, field) => {
222
+ dropped.push(field === undefined ? { code, path } : { code, path, field });
223
+ };
224
+ let hooks;
225
+ if (settingsDoc !== null && typeof settingsDoc === "object" && !Array.isArray(settingsDoc)) {
226
+ const doc = settingsDoc;
227
+ for (const key of Object.keys(doc)) {
228
+ const value = doc[key];
229
+ if (key === "hooks") {
230
+ hooks = hookBlockRead(value, reject, drop);
231
+ continue;
232
+ }
233
+ const sign = key === "matcher" && hookLooksLikeMatcher(doc)
234
+ ? [key]
235
+ : HOOK_GUARD_EVENTS.includes(key) && value !== null && value !== undefined && !(Array.isArray(value) && value.length === 0)
236
+ ? [key]
237
+ : hookGuardSignIn(value, [key], "other");
238
+ if (sign !== undefined)
239
+ reject("guard-outside-hooks", sign);
240
+ }
241
+ }
242
+ else {
243
+ const sign = hookGuardSignIn(settingsDoc, [], "other");
244
+ if (sign !== undefined)
245
+ reject("guard-outside-hooks", sign);
246
+ }
247
+ if (rejections.length > 0)
248
+ return { outcome: "rejected", hooks: undefined, dropped: [], rejections };
249
+ if (dropped.length > 0)
250
+ return { outcome: "loaded-partial", hooks, dropped, rejections: [] };
251
+ return { outcome: "loaded", hooks, dropped: [], rejections: [] };
252
+ }
253
+ return classifyHooksConfig;
254
+ };
@@ -9,3 +9,4 @@ export declare const SETTINGS_BUDGET_STRING_KEYS: readonly ["mode", "budgetDurat
9
9
  export declare const SETTINGS_BUDGET_PER_MODEL_NUMBER_KEYS: readonly ["maxBudgetUsd", "tpmLimit", "rpmLimit"];
10
10
  export declare const SETTINGS_MODEL_API_WORDS: readonly ["openai-completions", "anthropic-messages"];
11
11
  export declare const SETTINGS_TOOL_NAME_MATCHER_EVENTS: readonly ["PreToolUse", "PostToolUse", "PostToolUseFailure"];
12
+ export declare const SETTINGS_UI_LANGUAGE_VALUES: readonly ["en", "zh"];
@@ -41,3 +41,7 @@ export const SETTINGS_TOOL_NAME_MATCHER_EVENTS = Object.freeze([
41
41
  "PostToolUse",
42
42
  "PostToolUseFailure",
43
43
  ]);
44
+ export const SETTINGS_UI_LANGUAGE_VALUES = Object.freeze([
45
+ "en",
46
+ "zh",
47
+ ]);
@@ -0,0 +1,105 @@
1
+ export type ConfigPath = readonly (string | number)[];
2
+ declare const HOOK_EVENTS: readonly ["PreToolUse", "PostToolUse", "PostToolUseFailure", "PostToolBatch", "Notification", "UserPromptSubmit", "UserPromptExpansion", "SessionStart", "SessionEnd", "Stop", "StopFailure", "SubagentStart", "SubagentStop", "PreCompact", "PostCompact", "PermissionRequest", "PermissionDenied", "Setup", "TeammateIdle", "TaskCreated", "TaskCompleted", "Elicitation", "ElicitationResult", "ConfigChange", "WorktreeCreate", "WorktreeRemove", "InstructionsLoaded", "CwdChanged", "FileChanged", "MessageDisplay", "DirectoryAdded", "PreModelSwitch", "PostModelSwitch"];
3
+ type HookEventWord = (typeof HOOK_EVENTS)[number];
4
+ declare const HOOK_ENTRY_TYPES: readonly ["command", "prompt", "agent", "http", "mcp_tool"];
5
+ export type HookEntryType = (typeof HOOK_ENTRY_TYPES)[number];
6
+ declare const HOOK_SHELLS: readonly ["bash", "powershell"];
7
+ declare const HOOK_ENTRY_FIELDS: {
8
+ readonly command: {
9
+ readonly if: "string?";
10
+ readonly timeout: "seconds?";
11
+ readonly statusMessage: "string?";
12
+ readonly once: "boolean?";
13
+ readonly command: "text";
14
+ readonly shell: "shell?";
15
+ readonly async: "boolean?";
16
+ readonly asyncRewake: "boolean?";
17
+ };
18
+ readonly prompt: {
19
+ readonly if: "string?";
20
+ readonly timeout: "seconds?";
21
+ readonly statusMessage: "string?";
22
+ readonly once: "boolean?";
23
+ readonly prompt: "text";
24
+ readonly model: "string?";
25
+ };
26
+ readonly agent: {
27
+ readonly if: "string?";
28
+ readonly timeout: "seconds?";
29
+ readonly statusMessage: "string?";
30
+ readonly once: "boolean?";
31
+ readonly prompt: "text";
32
+ readonly model: "string?";
33
+ };
34
+ readonly http: {
35
+ readonly if: "string?";
36
+ readonly timeout: "seconds?";
37
+ readonly statusMessage: "string?";
38
+ readonly once: "boolean?";
39
+ readonly url: "text";
40
+ readonly headers: "stringRecord?";
41
+ readonly allowedEnvVars: "stringList?";
42
+ };
43
+ readonly mcp_tool: {
44
+ readonly if: "string?";
45
+ readonly timeout: "seconds?";
46
+ readonly statusMessage: "string?";
47
+ readonly once: "boolean?";
48
+ readonly server: "string";
49
+ readonly tool: "string";
50
+ readonly input: "record?";
51
+ };
52
+ };
53
+ type HookFieldBaseValue<B> = B extends "text" | "string" ? string : B extends "shell" ? (typeof HOOK_SHELLS)[number] : B extends "boolean" ? boolean : B extends "seconds" ? number : B extends "stringRecord" ? Record<string, string> : B extends "stringList" ? string[] : B extends "record" ? Record<string, unknown> : never;
54
+ type HookFieldValue<K> = K extends `${infer B}?` ? HookFieldBaseValue<B> : HookFieldBaseValue<K>;
55
+ type Flat<O> = {
56
+ [K in keyof O]: O[K];
57
+ };
58
+ type HookEntryOf<T extends HookEntryType, F = (typeof HOOK_ENTRY_FIELDS)[T]> = Flat<{
59
+ type: T;
60
+ } & {
61
+ -readonly [K in keyof F as F[K] extends `${string}?` ? never : K]: HookFieldValue<F[K]>;
62
+ } & {
63
+ -readonly [K in keyof F as F[K] extends `${string}?` ? K : never]?: HookFieldValue<F[K]>;
64
+ }>;
65
+ export type HookEntry = {
66
+ [T in HookEntryType]: HookEntryOf<T>;
67
+ }[HookEntryType];
68
+ export type HookMatcherEntry = {
69
+ matcher?: string;
70
+ hooks: HookEntry[];
71
+ };
72
+ export type HooksConfig = Partial<Record<HookEventWord, HookMatcherEntry[]>>;
73
+ declare const HOOKS_CLASSIFICATION_OUTCOMES: readonly ["loaded", "loaded-partial", "rejected"];
74
+ export type HooksClassificationOutcome = (typeof HOOKS_CLASSIFICATION_OUTCOMES)[number];
75
+ declare const HOOKS_DROPPED_PIECE_CODES: readonly ["hooks-not-object", "unknown-event", "event-not-array", "matcher-invalid", "entry-invalid"];
76
+ export type HooksDroppedPieceCode = (typeof HOOKS_DROPPED_PIECE_CODES)[number];
77
+ declare const HOOKS_REJECTION_CODES: readonly ["guard-outside-hooks", "hooks-is-matcher", "guard-under-unknown-event", "guard-event-not-array", "guard-matcher-invalid", "guard-entry-invalid"];
78
+ export type HooksRejectionCode = (typeof HOOKS_REJECTION_CODES)[number];
79
+ export interface HooksDroppedPiece {
80
+ readonly code: HooksDroppedPieceCode;
81
+ readonly path: ConfigPath;
82
+ readonly field?: string;
83
+ }
84
+ export interface HooksRejection {
85
+ readonly code: HooksRejectionCode;
86
+ readonly path: ConfigPath;
87
+ readonly field?: string;
88
+ }
89
+ export type HooksClassification = {
90
+ readonly outcome: "loaded";
91
+ readonly hooks: HooksConfig | undefined;
92
+ readonly dropped: readonly [];
93
+ readonly rejections: readonly [];
94
+ } | {
95
+ readonly outcome: "loaded-partial";
96
+ readonly hooks: HooksConfig | undefined;
97
+ readonly dropped: readonly HooksDroppedPiece[];
98
+ readonly rejections: readonly [];
99
+ } | {
100
+ readonly outcome: "rejected";
101
+ readonly hooks: undefined;
102
+ readonly dropped: readonly [];
103
+ readonly rejections: readonly HooksRejection[];
104
+ };
105
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,4 @@
1
+ import type { UiLanguage } from '../env/uiLanguage.js';
1
2
  export interface ApprovalAllowRuleShadowMember {
2
3
  readonly member?: string;
3
4
  readonly known: boolean;
@@ -23,4 +24,4 @@ export declare function retiredAllowRuleShadowKeyPresent(carrier: object | null
23
24
  export declare function readAllowRuleShadowFromWire(carrier: object | null | undefined, leg: 'frame' | 'row'): ApprovalAllowRuleShadow | undefined;
24
25
  export declare function readApprovalAllowRuleShadow(card: object | null | undefined): ApprovalAllowRuleShadow | undefined;
25
26
  export declare function approvalAllowRuleShadowed(card: object | null | undefined): boolean;
26
- export declare function allowRuleShadowSentence(card: object | null | undefined): string | undefined;
27
+ export declare function allowRuleShadowSentence(card: object | null | undefined, lang?: UiLanguage): string | undefined;
@@ -1,5 +1,6 @@
1
1
  import { CORE_ALLOW_RULE_MEMBERS } from '../generated/engineFactTables.js';
2
2
  import { quoteUntrustedForSentence } from '../displayUntrusted.js';
3
+ import { msg, renderMessage } from '../i18n/translate.js';
3
4
  const KNOWN_MEMBERS = new Set(CORE_ALLOW_RULE_MEMBERS);
4
5
  function freezeMember(m) {
5
6
  return Object.freeze({ ...m });
@@ -162,7 +163,6 @@ export function approvalAllowRuleShadowed(card) {
162
163
  const ENTRY_MAX = 4096;
163
164
  const MEMBER_MAX = 64;
164
165
  const ENTRIES_SHOWN = 5;
165
- const UNREADABLE_LINE = 'An allow rule matched this call but cannot clear it; which rule could not be read, so this one is confirmed individually.';
166
166
  function singlePersistedEntry(shadow) {
167
167
  if (shadow.unreadable === true || shadow.members.length !== 1)
168
168
  return undefined;
@@ -173,12 +173,12 @@ function singlePersistedEntry(shadow) {
173
173
  return undefined;
174
174
  return quoteUntrustedForSentence(m.entries[0], ENTRY_MAX);
175
175
  }
176
- function memberPhrase(m) {
176
+ function memberPhrase(m, lang) {
177
177
  const memberWord = m.member === undefined ? undefined : KNOWN_MEMBERS.has(m.member) ? m.member : quoteUntrustedForSentence(m.member, MEMBER_MAX);
178
- const word = memberWord ?? 'an unrecognised source';
178
+ const word = memberWord ?? msg('approval.card.shadow.unrecognisedSource');
179
179
  const entries = m.entries ?? [];
180
180
  if (m.malformed === true && entries.length === 0)
181
- return `${word} (could not be read)`;
181
+ return renderMessage(msg('approval.card.shadow.memberUnreadable', { word }), lang);
182
182
  const listed = entries
183
183
  .map((e) => quoteUntrustedForSentence(e, ENTRY_MAX))
184
184
  .filter((e) => e !== undefined)
@@ -188,25 +188,28 @@ function memberPhrase(m) {
188
188
  if (listed.length > 0)
189
189
  parts.push(listed.join(', '));
190
190
  if (notListed > 0)
191
- parts.push(listed.length > 0 ? `and ${String(notListed)} more not listed` : `${String(notListed)} not listed`);
191
+ parts.push(renderMessage(listed.length > 0 ? msg('approval.card.shadow.moreNotListed', { count: notListed }) : msg('approval.card.shadow.notListed', { count: notListed }), lang));
192
192
  if (m.malformed === true)
193
- parts.push('part of it could not be read');
194
- return parts.length > 0 ? `${word}: ${parts.join('; ')}` : word;
193
+ parts.push(renderMessage(msg('approval.card.shadow.partUnreadable'), lang));
194
+ return parts.length > 0
195
+ ? renderMessage(msg('approval.card.shadow.memberWithParts', { word, parts: parts.join(renderMessage(msg('approval.card.shadow.partJoin'), lang)) }), lang)
196
+ : typeof word === 'string'
197
+ ? word
198
+ : renderMessage(word, lang);
195
199
  }
196
- export function allowRuleShadowSentence(card) {
200
+ export function allowRuleShadowSentence(card, lang) {
197
201
  const shadow = readApprovalAllowRuleShadow(card);
198
202
  if (shadow === undefined)
199
203
  return undefined;
200
204
  try {
201
205
  if (shadow.unreadable === true || shadow.members.length === 0)
202
- return UNREADABLE_LINE;
206
+ return renderMessage(msg('approval.card.shadow.unreadable'), lang);
203
207
  const single = singlePersistedEntry(shadow);
204
- if (single !== undefined) {
205
- return `Your saved permission rule ${single} still exists — it just cannot clear this particular call, so this one is confirmed individually.`;
206
- }
207
- return `Allow rules matched this call but cannot clear it, so this one is confirmed individually — ${shadow.members.map(memberPhrase).join(' · ')}.`;
208
+ if (single !== undefined)
209
+ return renderMessage(msg('approval.card.shadow.single', { entry: single }), lang);
210
+ return renderMessage(msg('approval.card.shadow.several', { members: shadow.members.map((m) => memberPhrase(m, lang)).join(' · ') }), lang);
208
211
  }
209
212
  catch {
210
- return UNREADABLE_LINE;
213
+ return renderMessage(msg('approval.card.shadow.unreadable'), lang);
211
214
  }
212
215
  }
@@ -1,3 +1,4 @@
1
+ import type { UiLanguage } from '../env/uiLanguage.js';
1
2
  import { type DenialLimitFallback } from './toolApprovalWire.js';
2
3
  export declare const APPROVAL_CARD_REASON_SOURCES: readonly ["payload_unreadable", "prior_cards", "message", "mandated", "mandate", "origin", "denial_limit", "probe", "allow_rule_shadow", "classifier_no_ruling", "bound_grants", "more"];
3
4
  export type ApprovalCardReasonSource = (typeof APPROVAL_CARD_REASON_SOURCES)[number];
@@ -9,5 +10,5 @@ export interface ApprovalCardReasonsOptions {
9
10
  readonly maxLines?: number;
10
11
  }
11
12
  export declare const APPROVAL_CARD_REASONS_DEFAULT_MAX_LINES = 4;
12
- export declare function denialLimitFallbackDetail(v: DenialLimitFallback | null | undefined): string | undefined;
13
- export declare function approvalCardReasons(card: object | null | undefined, opts?: ApprovalCardReasonsOptions | null): readonly ApprovalCardReasonLine[];
13
+ export declare function denialLimitFallbackDetail(v: DenialLimitFallback | null | undefined, lang?: UiLanguage): string | undefined;
14
+ export declare function approvalCardReasons(card: object | null | undefined, opts?: ApprovalCardReasonsOptions | null, lang?: UiLanguage): readonly ApprovalCardReasonLine[];
@@ -1,4 +1,5 @@
1
1
  import { displayUntrusted } from '../displayUntrusted.js';
2
+ import { msg, renderMessage } from '../i18n/translate.js';
2
3
  import { approvalMandateDetail, askOriginNoteOf } from '../gateVocabulary.js';
3
4
  import { readAskOrigin, readOwnDataValue, guardedRead } from '../ownKey.js';
4
5
  import { allowRuleShadowSentence } from './allowRuleShadow.js';
@@ -20,22 +21,20 @@ export const APPROVAL_CARD_REASON_SOURCES = Object.freeze([
20
21
  ]);
21
22
  export const APPROVAL_CARD_REASONS_DEFAULT_MAX_LINES = 4;
22
23
  const MESSAGE_DISPLAY_MAX = 300;
23
- const PAYLOAD_UNREADABLE_DETAIL = 'This client cannot read the format of this approval card, so only its basic facts are shown — decide from those, or deny it if you are not sure what it will do.';
24
- function moreDetail(n) {
25
- return n === 1 ? '1 more reason for this card is not shown.' : `${String(n)} more reasons for this card are not shown.`;
24
+ function payloadUnreadableDetail(lang) {
25
+ return renderMessage(msg('approval.card.payloadUnreadable'), lang);
26
26
  }
27
- export function denialLimitFallbackDetail(v) {
27
+ function moreDetail(n, lang) {
28
+ return renderMessage(n === 1 ? msg('approval.card.more.one') : msg('approval.card.more.other', { count: n }), lang);
29
+ }
30
+ export function denialLimitFallbackDetail(v, lang) {
28
31
  const d = readDenialLimitFallback(v);
29
32
  if (d === undefined)
30
33
  return undefined;
31
- const parts = [
32
- 'auto-deny limit reached — auto mode denied enough calls on its own that the engine now wants a real human decision',
33
- `${String(d.consecutive)} consecutive / ${String(d.total)} total automatic denials so far`,
34
- `the limit that tripped: ${displayUntrusted(d.limit, { max: 24 })}`,
35
- ];
36
- if (d.autoDenyAfterMs > 0)
37
- parts.push(`the engine auto-denies it in ${String(Math.round(d.autoDenyAfterMs / 1000))}s if nobody answers`);
38
- return parts.join('; ');
34
+ const limit = displayUntrusted(d.limit, { max: 24 });
35
+ return renderMessage(d.autoDenyAfterMs > 0
36
+ ? msg('approval.card.denialLimit.withAutoDeny', { consecutive: d.consecutive, total: d.total, limit, seconds: Math.round(d.autoDenyAfterMs / 1000) })
37
+ : msg('approval.card.denialLimit.plain', { consecutive: d.consecutive, total: d.total, limit }), lang);
39
38
  }
40
39
  function ownData(card, key) {
41
40
  return guardedRead(() => readOwnDataValue(card, key));
@@ -44,7 +43,7 @@ function readMaxLines(opts) {
44
43
  const raw = typeof opts === 'object' && opts !== null ? guardedRead(() => readOwnDataValue(opts, 'maxLines')) : undefined;
45
44
  return typeof raw === 'number' && Number.isSafeInteger(raw) && raw >= 1 ? raw : APPROVAL_CARD_REASONS_DEFAULT_MAX_LINES;
46
45
  }
47
- export function approvalCardReasons(card, opts) {
46
+ export function approvalCardReasons(card, opts, lang) {
48
47
  if (typeof card !== 'object' || card === null)
49
48
  return Object.freeze([]);
50
49
  const raw = [];
@@ -65,21 +64,21 @@ export function approvalCardReasons(card, opts) {
65
64
  catch {
66
65
  denialLimitReadable = false;
67
66
  }
68
- add('payload_unreadable', () => (ownData(card, 'cardPayloadUnreadable') === true ? PAYLOAD_UNREADABLE_DETAIL : undefined));
69
- add('prior_cards', () => approvalPriorCardsDetail(card));
67
+ add('payload_unreadable', () => (ownData(card, 'cardPayloadUnreadable') === true ? payloadUnreadableDetail(lang) : undefined));
68
+ add('prior_cards', () => approvalPriorCardsDetail(card, lang));
70
69
  add('message', () => {
71
- const msg = ownData(card, 'message');
72
- if (typeof msg !== 'string' || msg.trim() === '')
70
+ const engineMessage = ownData(card, 'message');
71
+ if (typeof engineMessage !== 'string' || engineMessage.trim() === '')
73
72
  return undefined;
74
73
  const tool = ownData(card, 'toolName');
75
- if (typeof tool === 'string' && msg.trim() === `approval required for "${tool}"`)
74
+ if (typeof tool === 'string' && engineMessage.trim() === `approval required for "${tool}"`)
76
75
  return undefined;
77
- return displayUntrusted(msg, { max: MESSAGE_DISPLAY_MAX });
76
+ return displayUntrusted(engineMessage, { max: MESSAGE_DISPLAY_MAX });
78
77
  });
79
- add('mandated', () => (approvalIsMandated(card) ? mandatedApprovalDetailOf(card) : undefined));
78
+ add('mandated', () => (approvalIsMandated(card) ? mandatedApprovalDetailOf(card, lang) : undefined));
80
79
  add('mandate', () => {
81
80
  const word = readApprovalMandate(card);
82
- return word !== undefined ? approvalMandateDetail(word) : undefined;
81
+ return word !== undefined ? approvalMandateDetail(word, lang) : undefined;
83
82
  });
84
83
  add('origin', () => {
85
84
  const origin = readAskOrigin(card);
@@ -87,18 +86,18 @@ export function approvalCardReasons(card, opts) {
87
86
  return undefined;
88
87
  if (origin === 'denial_limit_fallback' && denialLimitReadable)
89
88
  return undefined;
90
- return askOriginNoteOf(origin);
89
+ return askOriginNoteOf(origin, lang);
91
90
  });
92
- add('denial_limit', () => denialLimitFallbackDetail(ownData(card, 'denialLimitFallback')));
93
- add('probe', () => askProbeReasonDetail(card));
94
- add('allow_rule_shadow', () => allowRuleShadowSentence(card));
91
+ add('denial_limit', () => denialLimitFallbackDetail(ownData(card, 'denialLimitFallback'), lang));
92
+ add('probe', () => askProbeReasonDetail(card, lang));
93
+ add('allow_rule_shadow', () => allowRuleShadowSentence(card, lang));
95
94
  add('classifier_no_ruling', () => {
96
95
  const word = readApprovalClassifierNoRuling(card);
97
- return word !== undefined ? classifierNoRulingDetail(word) : undefined;
96
+ return word !== undefined ? classifierNoRulingDetail(word, lang) : undefined;
98
97
  });
99
98
  add('bound_grants', () => {
100
99
  const grants = readApprovalBoundGrants(card);
101
- return grants !== undefined ? approvalBoundGrantsDetail(grants) : undefined;
100
+ return grants !== undefined ? approvalBoundGrantsDetail(grants, lang) : undefined;
102
101
  });
103
102
  const seen = new Set();
104
103
  const lines = [];
@@ -115,6 +114,6 @@ export function approvalCardReasons(card, opts) {
115
114
  if (lines.length <= max)
116
115
  return Object.freeze(lines);
117
116
  const kept = lines.slice(0, max - 1);
118
- kept.push(Object.freeze({ source: 'more', text: moreDetail(lines.length - kept.length) }));
117
+ kept.push(Object.freeze({ source: 'more', text: moreDetail(lines.length - kept.length, lang) }));
119
118
  return Object.freeze(kept);
120
119
  }
@@ -67,6 +67,8 @@ export type ApprovalCardClaim = {
67
67
  } | {
68
68
  readonly kind: 'joined';
69
69
  readonly outcome: ApprovalResolution;
70
+ } | {
71
+ readonly kind: 'aborted';
70
72
  };
71
73
  export declare function claimApprovalCardFor(who: HoldIdentity, signal: AbortSignal | undefined): Promise<ApprovalCardClaim>;
72
74
  export interface ApprovalDecisionHoldTable {
@@ -85,6 +87,7 @@ export declare function settledApprovalOf(approvalId: string | undefined): Settl
85
87
  export declare function clearSettledApprovals(): void;
86
88
  export declare function anyApprovalSettled(): boolean;
87
89
  export declare function noteEngineClosedApproval(approvalId: string, parked: boolean): void;
90
+ export declare function settleEngineClosedApproval(frame: object, parked: boolean): boolean;
88
91
  export declare function noteHolderSettledApproval(approvalId: string, how: 'answered' | 'interrupted', outcome: ApprovalResolution): void;
89
92
  export declare function settledLiveCardOutcome(approvalId: string): ApprovalResolution | undefined;
90
93
  export declare function liveCardHoldOf(key: string): LiveCardHold | undefined;