@sema-agent/client-core 0.95.0 → 0.96.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 (181) hide show
  1. package/CHANGELOG.md +180 -0
  2. package/README.md +49 -25
  3. package/dist/adapt/arms.js +7 -1
  4. package/dist/adapt/toolCards.d.ts +1 -0
  5. package/dist/adapt/toolCards.js +16 -3
  6. package/dist/adapt/wireShapes.js +2 -16
  7. package/dist/adapter/activeRunSelfHeal.d.ts +4 -0
  8. package/dist/adapter/activeRunSelfHeal.js +30 -4
  9. package/dist/adapter/downstream/eventToSdkMessage.js +11 -3
  10. package/dist/adapter/downstream/terminalToSdkResult.js +8 -9
  11. package/dist/adapter/runStream.js +30 -47
  12. package/dist/agentSession/engineAgentRegistryRead.js +5 -4
  13. package/dist/agentSession/engineSessionBackgroundStop.js +22 -15
  14. package/dist/agentsWireCaps.js +13 -2
  15. package/dist/callerCwdCapability.d.ts +0 -4
  16. package/dist/callerCwdCapability.js +0 -6
  17. package/dist/centerWiringCapability.d.ts +0 -4
  18. package/dist/centerWiringCapability.js +0 -6
  19. package/dist/classifierVerdictWire.js +4 -16
  20. package/dist/clientSlice.js +1 -1
  21. package/dist/cloudConfigWireCaps.d.ts +3 -3
  22. package/dist/cloudConfigWireCaps.js +65 -45
  23. package/dist/coreValuePorts.d.ts +11 -7
  24. package/dist/coreValuePorts.js +5 -8
  25. package/dist/credentialProvenance.d.ts +28 -0
  26. package/dist/credentialProvenance.js +76 -0
  27. package/dist/decideFailureNote.js +3 -1
  28. package/dist/decideReceipt.js +7 -10
  29. package/dist/declared/supportFloorDeclared.js +3 -3
  30. package/dist/displayUntrusted.d.ts +7 -3
  31. package/dist/displayUntrusted.js +356 -60
  32. package/dist/engineCapsCache.d.ts +6 -0
  33. package/dist/engineCapsCache.js +226 -32
  34. package/dist/engineDirectory.d.ts +79 -0
  35. package/dist/engineDirectory.js +186 -0
  36. package/dist/engineErrorCodes.d.ts +14 -1
  37. package/dist/engineErrorCodes.js +37 -15
  38. package/dist/engineNoticeCodes.d.ts +17 -0
  39. package/dist/engineNoticeCodes.js +57 -3
  40. package/dist/engineWordRenames.d.ts +8 -0
  41. package/dist/engineWordRenames.js +13 -0
  42. package/dist/fileHistoryCaptureCapability.d.ts +14 -0
  43. package/dist/fileHistoryCaptureCapability.js +70 -0
  44. package/dist/fleet/bgSubagentRow.d.ts +15 -0
  45. package/dist/fleet/bgSubagentRow.js +67 -0
  46. package/dist/fleet/fleetLedger.d.ts +1 -0
  47. package/dist/fleet/fleetLedger.js +103 -89
  48. package/dist/fleet/fleetProjection.d.ts +1 -0
  49. package/dist/fleet/fleetProjection.js +10 -3
  50. package/dist/fleetTaskDesc.js +4 -17
  51. package/dist/gateOutcome.d.ts +12 -1
  52. package/dist/gateOutcome.js +58 -1
  53. package/dist/gateVocabulary.d.ts +7 -2
  54. package/dist/gateVocabulary.js +5 -1
  55. package/dist/generated/engineAskFaceTables.js +1 -1
  56. package/dist/generated/engineFactTables.d.ts +5 -3
  57. package/dist/generated/engineFactTables.js +17 -4
  58. package/dist/generated/engineNoticeTables.js +12 -3
  59. package/dist/generated/settingsSchemaFns.d.ts +3 -0
  60. package/dist/generated/settingsSchemaFns.js +53 -0
  61. package/dist/generated/toolNameTables.d.ts +1 -0
  62. package/dist/generated/toolNameTables.js +1 -0
  63. package/dist/hitl/approvalEndingCause.d.ts +2 -0
  64. package/dist/hitl/approvalEndingCause.js +31 -21
  65. package/dist/hitl/askParkRowRouting.js +1 -1
  66. package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
  67. package/dist/hitl/automaticAnswerVerdict.js +13 -8
  68. package/dist/hitl/decisionConflict.js +0 -2
  69. package/dist/hitl/decisionRefusal.d.ts +8 -0
  70. package/dist/hitl/decisionRefusal.js +48 -14
  71. package/dist/hitl/frameRouter.d.ts +0 -1
  72. package/dist/hitl/frameRouter.js +6 -14
  73. package/dist/hitl/hitlBridge.d.ts +6 -2
  74. package/dist/hitl/hitlBridge.js +28 -7
  75. package/dist/hitl/localAllowRule.d.ts +1 -0
  76. package/dist/hitl/localAllowRule.js +2 -2
  77. package/dist/hitl/noAllowCause.d.ts +2 -1
  78. package/dist/hitl/noAllowCause.js +3 -2
  79. package/dist/hitl/parkResolver.d.ts +1 -0
  80. package/dist/hitl/parkResolver.js +8 -54
  81. package/dist/hitl/parkRowBirthWait.d.ts +1 -0
  82. package/dist/hitl/parkRowBirthWait.js +2 -2
  83. package/dist/hitl/planReviewWire.d.ts +1 -0
  84. package/dist/hitl/planReviewWire.js +98 -20
  85. package/dist/hitl/replayedApproval.d.ts +1 -0
  86. package/dist/hitl/replayedApproval.js +14 -0
  87. package/dist/hitl/sessionPolicyDeliverable.js +8 -6
  88. package/dist/hitl/standingRows.d.ts +18 -0
  89. package/dist/hitl/standingRows.js +127 -0
  90. package/dist/hitl/toolApprovalWire.d.ts +15 -3
  91. package/dist/hitl/toolApprovalWire.js +238 -25
  92. package/dist/hookMatcherVerdict.d.ts +1 -9
  93. package/dist/hookMatcherVerdict.js +21 -61
  94. package/dist/hooksWireCaps.js +2 -2
  95. package/dist/hostCallbackGuard.d.ts +1 -0
  96. package/dist/hostCallbackGuard.js +6 -0
  97. package/dist/index.d.ts +21 -9
  98. package/dist/index.js +17 -8
  99. package/dist/mcpProbeCapability.d.ts +0 -4
  100. package/dist/mcpProbeCapability.js +0 -6
  101. package/dist/memoryComplianceCapability.d.ts +0 -4
  102. package/dist/memoryComplianceCapability.js +0 -6
  103. package/dist/memoryOriginCapability.d.ts +0 -4
  104. package/dist/memoryOriginCapability.js +0 -6
  105. package/dist/memorySpecWire.js +2 -2
  106. package/dist/modelIdentityResolvability.d.ts +2 -2
  107. package/dist/modelIdentityResolvability.js +12 -3
  108. package/dist/noticePresentation.d.ts +68 -0
  109. package/dist/noticePresentation.js +247 -0
  110. package/dist/outputStyleSeatCapability.d.ts +0 -1
  111. package/dist/outputStyleSeatCapability.js +0 -3
  112. package/dist/ownKey.d.ts +2 -0
  113. package/dist/ownKey.js +18 -0
  114. package/dist/peerFrames.js +13 -9
  115. package/dist/permissionModesCapability.d.ts +0 -4
  116. package/dist/permissionModesCapability.js +0 -6
  117. package/dist/permissionRuleIssue.js +0 -3
  118. package/dist/permissionsDeclaration.d.ts +2 -0
  119. package/dist/permissionsDeclaration.js +56 -41
  120. package/dist/printPermissionOutcome.d.ts +12 -0
  121. package/dist/printPermissionOutcome.js +50 -0
  122. package/dist/printToolResultFrame.d.ts +1 -0
  123. package/dist/printToolResultFrame.js +5 -9
  124. package/dist/promptBlockedCopy.d.ts +5 -0
  125. package/dist/promptBlockedCopy.js +35 -0
  126. package/dist/protocolSegment.d.ts +9 -6
  127. package/dist/protocolSegment.js +31 -21
  128. package/dist/providerRejection.d.ts +4 -0
  129. package/dist/providerRejection.js +75 -14
  130. package/dist/replayBody.d.ts +12 -0
  131. package/dist/replayBody.js +25 -0
  132. package/dist/resumeRefusalCopy.js +5 -21
  133. package/dist/retryStatus.d.ts +9 -1
  134. package/dist/retryStatus.js +9 -2
  135. package/dist/rewindArchiveCapability.d.ts +3 -13
  136. package/dist/rewindArchiveCapability.js +7 -58
  137. package/dist/rewindArchiveReading.d.ts +15 -0
  138. package/dist/rewindArchiveReading.js +56 -0
  139. package/dist/ruleCompileVerdict.d.ts +9 -1
  140. package/dist/ruleCompileVerdict.js +29 -4
  141. package/dist/runTerminal.d.ts +15 -1
  142. package/dist/runTerminal.js +56 -8
  143. package/dist/sandboxWire.js +13 -0
  144. package/dist/sealedKeyCapability.d.ts +0 -4
  145. package/dist/sealedKeyCapability.js +0 -6
  146. package/dist/seam.js +4 -2
  147. package/dist/seatContract.d.ts +73 -11
  148. package/dist/seatContract.js +195 -14
  149. package/dist/sessionReadRedactionCapability.d.ts +0 -4
  150. package/dist/sessionReadRedactionCapability.js +0 -6
  151. package/dist/sessionSyncFileHistory.d.ts +4 -0
  152. package/dist/sessionSyncFileHistory.js +66 -0
  153. package/dist/sessionSyncFileHistoryCapability.d.ts +0 -1
  154. package/dist/sessionSyncFileHistoryCapability.js +0 -3
  155. package/dist/skillToolListsCapability.d.ts +0 -1
  156. package/dist/skillToolListsCapability.js +0 -3
  157. package/dist/steerPriorityCapability.d.ts +0 -1
  158. package/dist/steerPriorityCapability.js +0 -3
  159. package/dist/storePostureCapability.d.ts +0 -4
  160. package/dist/storePostureCapability.js +0 -6
  161. package/dist/subagent/engineSubagentSteer.js +7 -5
  162. package/dist/subagentContentStore.js +4 -15
  163. package/dist/supportFloor.d.ts +1 -0
  164. package/dist/supportFloor.js +13 -9
  165. package/dist/systemReminderTag.d.ts +1 -0
  166. package/dist/systemReminderTag.js +8 -0
  167. package/dist/toolHistoryMismatch.d.ts +0 -3
  168. package/dist/toolHistoryMismatch.js +3 -7
  169. package/dist/toolResult.d.ts +1 -1
  170. package/dist/toolResult.js +2 -1
  171. package/dist/toolResultContent.d.ts +2 -0
  172. package/dist/toolResultContent.js +63 -0
  173. package/dist/usageAnalytics.js +40 -16
  174. package/dist/userInvokedSkillsCapability.d.ts +0 -1
  175. package/dist/userInvokedSkillsCapability.js +0 -3
  176. package/dist/wireErrorTriage.d.ts +2 -0
  177. package/dist/wireErrorTriage.js +34 -5
  178. package/dist/wireFailureShape.d.ts +19 -2
  179. package/dist/wireFailureShape.js +55 -50
  180. package/docs/INTEGRATION-CLIENTS.md +1262 -17
  181. package/package.json +5 -5
@@ -0,0 +1,247 @@
1
+ import { capDisplay, displayUntrusted } from './displayUntrusted.js';
2
+ import { engineNoticeInCatalog, noticeAudienceOf } from './engineNoticeCodes.js';
3
+ import { guardedRead, readOwnDataNonEmptyString, readOwnDataValue } from './ownKey.js';
4
+ const DEFAULT_CUT_MARK = '…';
5
+ const CUT_KEEP_DIVISOR = 2;
6
+ const CLOSERS = '"\')]”’」』)】';
7
+ const ASCII_SENTENCE_END = '.!?;';
8
+ const WIDE_SENTENCE_END = '。!?;';
9
+ const ASCII_CLAUSE_END = ',:';
10
+ const WIDE_CLAUSE_END = ',、:';
11
+ const EM_DASH = '—';
12
+ function isWs(c) {
13
+ return c !== '' && c.trim() === '';
14
+ }
15
+ function readCutOptions(opts) {
16
+ if (typeof opts !== 'object' || opts === null)
17
+ return { boundary: 'sentence', mark: DEFAULT_CUT_MARK };
18
+ const boundary = guardedRead(() => readOwnDataValue(opts, 'boundary'));
19
+ const mark = guardedRead(() => readOwnDataValue(opts, 'mark'));
20
+ return { boundary: boundary === 'word' ? 'word' : 'sentence', mark: typeof mark === 'string' ? mark : DEFAULT_CUT_MARK };
21
+ }
22
+ function sentenceEndAt(src, j) {
23
+ const c = src.charAt(j);
24
+ const ascii = ASCII_SENTENCE_END.includes(c);
25
+ if (!ascii && !WIDE_SENTENCE_END.includes(c))
26
+ return -1;
27
+ let k = j + 1;
28
+ while (k < src.length && CLOSERS.includes(src.charAt(k)))
29
+ k++;
30
+ if (!ascii)
31
+ return k;
32
+ return k === src.length || isWs(src.charAt(k)) ? k : -1;
33
+ }
34
+ function clauseEndAt(src, j) {
35
+ const c = src.charAt(j);
36
+ if (WIDE_CLAUSE_END.includes(c))
37
+ return j + 1;
38
+ if (!ASCII_CLAUSE_END.includes(c))
39
+ return -1;
40
+ const k = j + 1;
41
+ return k === src.length || isWs(src.charAt(k)) ? k : -1;
42
+ }
43
+ function pickCut(src, limit, floor, boundary) {
44
+ let sentence = -1;
45
+ let clause = -1;
46
+ let word = -1;
47
+ for (let j = 0; j <= limit && j < src.length; j++) {
48
+ const c = src.charAt(j);
49
+ if (isWs(c)) {
50
+ word = j;
51
+ continue;
52
+ }
53
+ if (boundary === 'word')
54
+ continue;
55
+ const s = sentenceEndAt(src, j);
56
+ if (s !== -1 && s <= limit)
57
+ sentence = Math.max(sentence, s);
58
+ else if (c === EM_DASH && j > 0 && isWs(src.charAt(j - 1)) && (j + 1 === src.length || isWs(src.charAt(j + 1))))
59
+ sentence = Math.max(sentence, j);
60
+ const k = clauseEndAt(src, j);
61
+ if (k !== -1 && k <= limit)
62
+ clause = Math.max(clause, k);
63
+ }
64
+ if (boundary === 'word')
65
+ return word >= floor ? word : -1;
66
+ if (sentence >= floor)
67
+ return sentence;
68
+ if (clause >= floor)
69
+ return clause;
70
+ return word >= floor ? word : -1;
71
+ }
72
+ export function cutForDisplay(text, budget, opts) {
73
+ const src = typeof text === 'string' ? text : (guardedRead(() => String(text ?? '')) ?? '');
74
+ if (typeof budget !== 'number' || !Number.isFinite(budget))
75
+ return { shown: src, truncated: false };
76
+ const limit = Math.max(0, Math.floor(budget));
77
+ if (src.length <= limit)
78
+ return { shown: src, truncated: false };
79
+ const { boundary, mark } = readCutOptions(opts);
80
+ const room = limit - mark.length;
81
+ if (room <= 0)
82
+ return { shown: limit >= mark.length ? mark : '', truncated: true };
83
+ const head = capDisplay(src, room, 'escape');
84
+ const floor = Math.ceil(head.length / CUT_KEEP_DIVISOR);
85
+ const at = pickCut(src, head.length, floor, boundary);
86
+ const kept = (at === -1 ? head : src.slice(0, at)).trimEnd();
87
+ return { shown: `${kept}${mark}`, truncated: true };
88
+ }
89
+ export const NOTICE_SEAT_CLASS = Object.freeze({
90
+ user: Object.freeze({ present: 'persistent+hint', unknown: 'persistent+hint', absent: 'persistent' }),
91
+ operator: Object.freeze({ present: 'transient', unknown: 'transient', absent: 'diagnostic' }),
92
+ unknown: Object.freeze({ present: 'persistent+hint', unknown: 'persistent+hint', absent: 'persistent+hint' }),
93
+ });
94
+ export function noticeSeatClassOf(audience, outlet, deployment) {
95
+ const a = typeof audience === 'string' && Object.hasOwn(NOTICE_SEAT_CLASS, audience) ? audience : 'unknown';
96
+ const row = a === 'operator' && deployment !== 'remote' ? NOTICE_SEAT_CLASS.user : NOTICE_SEAT_CLASS[a];
97
+ return typeof outlet === 'string' && Object.hasOwn(row, outlet) ? row[outlet] : row.unknown;
98
+ }
99
+ const OCCURRENCE_KEY_BY_CODE = Object.freeze({
100
+ 'memory.harvest_quarantined': 'reportId',
101
+ 'memory.hold_opened': 'reportId',
102
+ 'memory.hold_released': 'reportId',
103
+ 'memory.hold_disposed': 'reportId',
104
+ 'memory.consolidation_recommended': 'reportId',
105
+ 'memory.capture_opted_out': 'sessionId',
106
+ 'memory.delegation_static_mark_waived': 'runId',
107
+ });
108
+ export function noticePresentationFacts(notice, deployment) {
109
+ const envelope = typeof notice === 'object' && notice !== null ? notice : undefined;
110
+ const code = guardedRead(() => readOwnDataValue(envelope, 'code'));
111
+ const detailRaw = guardedRead(() => readOwnDataValue(envelope, 'detail'));
112
+ const detail = typeof detailRaw === 'object' && detailRaw !== null ? detailRaw : undefined;
113
+ const audience = typeof code === 'string' && engineNoticeInCatalog(code) ? noticeAudienceOf(code) : 'unknown';
114
+ const remedy = guardedRead(() => readOwnDataNonEmptyString(detail, 'remedy'));
115
+ const outlet = remedy !== undefined ? 'present' : 'unknown';
116
+ const keyField = typeof code === 'string' && Object.hasOwn(OCCURRENCE_KEY_BY_CODE, code) ? OCCURRENCE_KEY_BY_CODE[code] : undefined;
117
+ const identity = keyField !== undefined ? guardedRead(() => readOwnDataNonEmptyString(detail, keyField)) : undefined;
118
+ const occurrence = Object.freeze(identity !== undefined ? { kind: 'occurrence', key: identity } : { kind: 'event' });
119
+ return Object.freeze({
120
+ audience,
121
+ outlet,
122
+ ...(remedy !== undefined ? { remedy } : {}),
123
+ occurrence,
124
+ seatClass: noticeSeatClassOf(audience, outlet, deployment),
125
+ });
126
+ }
127
+ export const OUTLET_KINDS = Object.freeze(['slash-command', 'cli-command', 'http-endpoint', 'env-or-settings', 'operator-action', 'identity-attach', 'resend']);
128
+ function ctxSlot(ctx, key, closed) {
129
+ if (typeof ctx !== 'object' || ctx === null)
130
+ return undefined;
131
+ const v = guardedRead(() => readOwnDataValue(ctx, key));
132
+ return typeof v === 'string' && closed.includes(v) ? v : undefined;
133
+ }
134
+ function isOutletKind(v) {
135
+ return typeof v === 'string' && OUTLET_KINDS.includes(v);
136
+ }
137
+ export function outletReachable(kind, ctx) {
138
+ if (!isOutletKind(kind))
139
+ return 'unknown';
140
+ const lane = ctxSlot(ctx, 'lane', ['interactive', 'print']);
141
+ switch (kind) {
142
+ case 'resend':
143
+ case 'cli-command':
144
+ return 'reachable';
145
+ case 'slash-command':
146
+ return lane === 'interactive' ? 'reachable' : lane === 'print' ? 'unreachable' : 'unknown';
147
+ case 'http-endpoint': {
148
+ if (lane === 'interactive')
149
+ return 'unreachable';
150
+ const access = ctxSlot(ctx, 'endpointAccess', ['has-address-and-credential', 'no', 'unknown']);
151
+ if (access === 'no')
152
+ return 'unreachable';
153
+ return lane === 'print' && access === 'has-address-and-credential' ? 'reachable' : 'unknown';
154
+ }
155
+ case 'env-or-settings': {
156
+ const scope = ctxSlot(ctx, 'configScope', ['reaches-engine', 'does-not', 'unknown']);
157
+ if (scope === 'reaches-engine')
158
+ return 'reachable';
159
+ if (scope === 'does-not')
160
+ return 'unreachable';
161
+ return ctxSlot(ctx, 'engineManagedByShell', ['shell', 'external-local', 'remote', 'unknown']) === 'remote' ? 'unreachable' : 'unknown';
162
+ }
163
+ case 'operator-action': {
164
+ const op = ctxSlot(ctx, 'operator', ['present', 'absent', 'unknown']);
165
+ return op === 'present' ? 'reachable' : op === 'absent' ? 'unreachable' : 'unknown';
166
+ }
167
+ case 'identity-attach': {
168
+ const id = ctxSlot(ctx, 'identityAttach', ['available', 'unavailable', 'unknown']);
169
+ return id === 'available' ? 'reachable' : id === 'unavailable' ? 'unreachable' : 'unknown';
170
+ }
171
+ }
172
+ }
173
+ const LIST_READ_MAX = 64;
174
+ function listItems(list) {
175
+ if (guardedRead(() => (Array.isArray(list) ? true : undefined)) !== true)
176
+ return [];
177
+ const length = guardedRead(() => readOwnDataValue(list, 'length'));
178
+ if (typeof length !== 'number' || !Number.isInteger(length) || length < 0)
179
+ return [];
180
+ const out = [];
181
+ for (let i = 0; i < Math.min(length, LIST_READ_MAX); i++) {
182
+ const item = guardedRead(() => readOwnDataValue(list, String(i)));
183
+ if (item !== undefined)
184
+ out.push(item);
185
+ }
186
+ return out;
187
+ }
188
+ export function planOutletRendering(kinds, ctx) {
189
+ const state = [];
190
+ const confirm = [];
191
+ const omit = [];
192
+ const seen = new Set();
193
+ for (const k of listItems(kinds)) {
194
+ if (!isOutletKind(k) || seen.has(k))
195
+ continue;
196
+ seen.add(k);
197
+ const r = outletReachable(k, ctx);
198
+ (r === 'reachable' ? state : r === 'unknown' ? confirm : omit).push(k);
199
+ }
200
+ return Object.freeze({
201
+ state: Object.freeze(state),
202
+ confirm: Object.freeze(confirm),
203
+ omit: Object.freeze(omit),
204
+ nothingReachable: state.length === 0 && confirm.length === 0 && omit.length > 0,
205
+ });
206
+ }
207
+ export const NOTICE_FULL_TEXT_CAP = 8000;
208
+ const PRINT_BUDGET_USER = 1000;
209
+ const PRINT_BUDGET_OPERATOR = 160;
210
+ const PRINT_PREFIX = '[sema] ';
211
+ const NO_TEXT_SENTENCE = 'Engine notice (no message text)';
212
+ const PRINT_CODE_MAX = 160;
213
+ const PRE_CAP_SLACK = 2;
214
+ const PRINT_SESSION_MAX = 128;
215
+ function lineFace(max) {
216
+ return max === undefined ? { foldLines: false, mark: 'dot' } : { foldLines: false, mark: 'dot', max };
217
+ }
218
+ function printCarrier(carrier) {
219
+ if (typeof carrier !== 'object' || carrier === null)
220
+ return { kind: 'none' };
221
+ const kind = guardedRead(() => readOwnDataValue(carrier, 'kind'));
222
+ if (kind === 'stream-json')
223
+ return { kind };
224
+ if (kind === 'transcript') {
225
+ const sid = guardedRead(() => readOwnDataNonEmptyString(carrier, 'sessionId'));
226
+ if (sid !== undefined) {
227
+ const shown = displayUntrusted(sid, lineFace(PRINT_SESSION_MAX));
228
+ if (shown !== '')
229
+ return { kind, sessionId: shown };
230
+ }
231
+ }
232
+ return { kind: 'none' };
233
+ }
234
+ export function noticePrintLine(input) {
235
+ const textRaw = guardedRead(() => readOwnDataValue(input, 'text'));
236
+ const audience = guardedRead(() => readOwnDataValue(input, 'audience'));
237
+ const codeRaw = guardedRead(() => readOwnDataValue(input, 'code'));
238
+ const carrier = printCarrier(guardedRead(() => readOwnDataValue(input, 'carrier')));
239
+ const washed = displayUntrusted(typeof textRaw === 'string' ? textRaw : '', lineFace(NOTICE_FULL_TEXT_CAP + PRE_CAP_SLACK));
240
+ const bounded = cutForDisplay(washed, NOTICE_FULL_TEXT_CAP);
241
+ const text = bounded.shown.trim() === '' ? NO_TEXT_SENTENCE : bounded.shown;
242
+ const budget = audience === 'operator' ? PRINT_BUDGET_OPERATOR : PRINT_BUDGET_USER;
243
+ const cut = carrier.kind === 'none' ? { shown: text, truncated: bounded.truncated } : cutForDisplay(text, budget);
244
+ const where = cut.truncated && carrier.kind === 'transcript' ? ` (full text: sema -r ${carrier.sessionId})` : '';
245
+ const code = typeof codeRaw === 'string' && codeRaw !== '' ? displayUntrusted(codeRaw, lineFace(PRINT_CODE_MAX)) : '';
246
+ return Object.freeze({ line: `${PRINT_PREFIX}${cut.shown}${where}${code !== '' ? ` [${code}]` : ''}`, truncated: cut.truncated });
247
+ }
@@ -12,4 +12,3 @@ export declare function noteEngineCapsForOutputStyleSeat(baseUrl: string, caps:
12
12
  }): void;
13
13
  export declare function observedOutputStyleSeat(baseUrl?: string | undefined): OutputStyleSeatReading;
14
14
  export declare function outputStyleSeatAdmitted(reading: OutputStyleSeatReading | undefined): boolean;
15
- export declare function __resetOutputStyleSeatReadingsForTests(): void;
@@ -37,6 +37,3 @@ export function outputStyleSeatAdmitted(reading) {
37
37
  return false;
38
38
  }
39
39
  }
40
- export function __resetOutputStyleSeatReadingsForTests() {
41
- reader.__resetForTests();
42
- }
package/dist/ownKey.d.ts CHANGED
@@ -3,9 +3,11 @@ export declare function readOwnNonEmptyString(v: object | null | undefined, key:
3
3
  export declare function readAskOrigin(carrier: object | null | undefined): string | undefined;
4
4
  export declare function readOwnDataNonEmptyString(v: object | null | undefined, key: string): string | undefined;
5
5
  export declare function readOwnDataValue<T>(v: object | null | undefined, key: string): T | undefined;
6
+ export declare function guardedRead<T>(read: () => T | undefined): T | undefined;
6
7
  export declare function ownDataField(v: object, key: string): unknown;
7
8
  export declare function ownSendableField(v: object, key: string): unknown;
8
9
  export declare function ownDataRefusalKeyOf(e: unknown): string | undefined;
9
10
  export declare function readFrameStringKey(frame: unknown, key: string): string | undefined;
11
+ export declare function readFrameTrueMark(frame: object | null | undefined, key: string): boolean;
10
12
  export declare function markMcpSectionDroppedNamedRows(rows: object, dropped: ReadonlyMap<string, number>): void;
11
13
  export declare function mcpSectionDroppedNamedRowsOf(rows: object | null | undefined, name: string): number;
package/dist/ownKey.js CHANGED
@@ -25,6 +25,14 @@ export function readOwnDataValue(v, key) {
25
25
  const d = Object.getOwnPropertyDescriptor(v, key);
26
26
  return d !== undefined && Object.hasOwn(d, 'value') ? d.value : undefined;
27
27
  }
28
+ export function guardedRead(read) {
29
+ try {
30
+ return read();
31
+ }
32
+ catch {
33
+ return undefined;
34
+ }
35
+ }
28
36
  export function ownDataField(v, key) {
29
37
  return ownField(v, key, false);
30
38
  }
@@ -56,6 +64,16 @@ export function readFrameStringKey(frame, key) {
56
64
  return undefined;
57
65
  }
58
66
  }
67
+ export function readFrameTrueMark(frame, key) {
68
+ try {
69
+ if (frame === null || frame === undefined || typeof frame !== 'object' || Array.isArray(frame))
70
+ return false;
71
+ return ownDataField(frame, key) === true;
72
+ }
73
+ catch {
74
+ return false;
75
+ }
76
+ }
59
77
  const DROPPED_NAMED_ROWS = Symbol.for('@sema-agent/client-core/mcpSectionDroppedNamedRows');
60
78
  export function markMcpSectionDroppedNamedRows(rows, dropped) {
61
79
  if (dropped.size === 0)
@@ -1,4 +1,4 @@
1
- import { applyDisplayFace, LEGACY_NAME_FACE } from './displayUntrusted.js';
1
+ import { applyDisplayFace, PEER_NAME_FACE } from './displayUntrusted.js';
2
2
  import { CORE_ENGINE_AUTHORITY_ENVELOPE_TAGS, CORE_PERMISSION_MODE_CLASSES } from './generated/engineFactTables.js';
3
3
  const WIRE_KEY_FROM = 'from';
4
4
  const WIRE_KEY_BODY = 'body';
@@ -42,14 +42,16 @@ function nonEmptyString(v) {
42
42
  function finiteNumber(v) {
43
43
  return typeof v === 'number' && Number.isFinite(v) ? v : undefined;
44
44
  }
45
- function provenanceAgrees(n, lane, carrierFrom) {
45
+ function provenanceAgrees(n, lane, carrierFromRaw) {
46
46
  const prov = dataProp(n, WIRE_KEY_PROVENANCE);
47
47
  if (prov === null || typeof prov !== 'object')
48
48
  return false;
49
49
  if (dataProp(prov, WIRE_KEY_KIND) !== lane)
50
50
  return false;
51
- const provFrom = cleanName(dataProp(prov, WIRE_KEY_FROM));
52
- if (provFrom === undefined || (carrierFrom !== undefined && provFrom !== carrierFrom))
51
+ const provFromRaw = dataProp(prov, WIRE_KEY_FROM);
52
+ if (typeof provFromRaw !== 'string' || cleanName(provFromRaw) === undefined)
53
+ return false;
54
+ if (carrierFromRaw !== undefined && provFromRaw !== carrierFromRaw)
53
55
  return false;
54
56
  const taskId = nonEmptyString(dataProp(n, WIRE_KEY_TASK_ID));
55
57
  if (taskId === undefined || nonEmptyString(dataProp(prov, WIRE_KEY_PROV_TASK_ID)) !== taskId)
@@ -61,9 +63,10 @@ export function classifyPeerNotification(n) {
61
63
  const seq = finiteNumber(dataProp(n, WIRE_KEY_SEQ));
62
64
  const agentMessage = dataProp(n, WIRE_KEY_AGENT_MESSAGE);
63
65
  if (agentMessage !== undefined) {
64
- const from = cleanName(dataProp(agentMessage, WIRE_KEY_FROM));
66
+ const fromRaw = dataProp(agentMessage, WIRE_KEY_FROM);
67
+ const from = cleanName(fromRaw);
65
68
  const body = dataProp(agentMessage, WIRE_KEY_BODY);
66
- if (from !== undefined && typeof body === 'string' && provenanceAgrees(n, 'agent_message', from)) {
69
+ if (from !== undefined && typeof fromRaw === 'string' && typeof body === 'string' && provenanceAgrees(n, 'agent_message', fromRaw)) {
67
70
  const agentType = nonEmptyString(dataProp(dataProp(n, WIRE_KEY_PROVENANCE), WIRE_KEY_AGENT_TYPE));
68
71
  return {
69
72
  lane: 'agent_message',
@@ -77,9 +80,10 @@ export function classifyPeerNotification(n) {
77
80
  }
78
81
  const crossSessionMessage = dataProp(n, WIRE_KEY_CROSS_SESSION_MESSAGE);
79
82
  if (crossSessionMessage !== undefined) {
80
- const from = cleanName(dataProp(crossSessionMessage, WIRE_KEY_FROM));
83
+ const fromRaw = dataProp(crossSessionMessage, WIRE_KEY_FROM);
84
+ const from = cleanName(fromRaw);
81
85
  const body = dataProp(crossSessionMessage, WIRE_KEY_BODY);
82
- if (from === undefined || typeof body !== 'string' || !provenanceAgrees(n, 'cross_session_message', from))
86
+ if (from === undefined || typeof fromRaw !== 'string' || typeof body !== 'string' || !provenanceAgrees(n, 'cross_session_message', fromRaw))
83
87
  return null;
84
88
  const fromSession = nonEmptyString(dataProp(crossSessionMessage, WIRE_KEY_FROM_SESSION));
85
89
  const fromName = cleanName(dataProp(crossSessionMessage, WIRE_KEY_FROM_NAME));
@@ -117,7 +121,7 @@ function neutralizeAuthorityTags(text) {
117
121
  function cleanName(v) {
118
122
  if (typeof v !== 'string')
119
123
  return undefined;
120
- const t = applyDisplayFace(v, LEGACY_NAME_FACE);
124
+ const t = applyDisplayFace(v, PEER_NAME_FACE);
121
125
  return t.length > 0 ? t : undefined;
122
126
  }
123
127
  function escapeEnvelopeTag(tag, text) {
@@ -7,9 +7,5 @@ export type PermissionModesReading = {
7
7
  modes: readonly string[];
8
8
  };
9
9
  export declare function projectPermissionModesCapability(caps: unknown): PermissionModesReading | undefined;
10
- export declare function noteEngineCapsForPermissionModes(baseUrl: string, caps: unknown, opts?: {
11
- generation?: number;
12
- }): void;
13
10
  export declare function observedPermissionModes(baseUrl?: string | undefined): PermissionModesReading;
14
11
  export declare function permissionModeAdmitted(reading: PermissionModesReading | undefined, mode: string): boolean;
15
- export declare function __resetPermissionModesReadingsForTests(): void;
@@ -40,9 +40,6 @@ const reader = createEngineCapReader({
40
40
  project: projectPermissionModesCapability,
41
41
  makeUnobserved: () => ({ kind: 'unobserved' }),
42
42
  });
43
- export function noteEngineCapsForPermissionModes(baseUrl, caps, opts) {
44
- reader.note(baseUrl, caps, opts);
45
- }
46
43
  export function observedPermissionModes(baseUrl = engineWireTarget()?.baseUrl) {
47
44
  return reader.observed(baseUrl);
48
45
  }
@@ -61,6 +58,3 @@ export function permissionModeAdmitted(reading, mode) {
61
58
  return false;
62
59
  }
63
60
  }
64
- export function __resetPermissionModesReadingsForTests() {
65
- reader.__resetForTests();
66
- }
@@ -34,9 +34,6 @@ const ISSUE_SENTENCES = Object.freeze({
34
34
  'unsupported.path_base': 'this path rule is not supported as spelled: the base it is relative to is missing or is not a usable absolute path, so it would reach nothing and is refused rather than compiled',
35
35
  'unsupported.mcp_paren': 'a parenthesised parameter rule is not supported on an MCP tool name',
36
36
  'unsupported.covering_paren': 'a parenthesised parameter rule is not supported on a covering protocol name — the parameter grammar is keyed by an exact tool name, so no mounted tool could ever bear it',
37
- 'invalid.allow_param_rule': 'this rule is invalid: an allow rule cannot carry a parameter pattern — only bare tool rules auto-allow',
38
- 'unsupported.bash_prefix': 'a standing approval for a command belongs in the persisted-rule store, so this allow rule is not supported here (deny and ask rules with the same shape do compile)',
39
- 'unsupported.file_glob': 'a standing approval by path belongs in the consent store, so this allow rule is not supported here (deny and ask path rules do compile)',
40
37
  });
41
38
  const PARAM_SPLIT_WITH_COLON = 'this rule is invalid: a parameter rule is written name:pattern, and the name before the colon or the pattern after it is empty';
42
39
  const PARAM_SPLIT_NO_COLON = 'this rule is invalid: there is no colon inside the parentheses, so this is not a parameter rule (a parameter rule is written name:pattern)';
@@ -30,6 +30,8 @@ export interface PermissionsKeptRule {
30
30
  rule: string;
31
31
  bucket: 'deny' | 'ask' | 'allow';
32
32
  reason: PermissionsKeptReason;
33
+ code?: string;
34
+ message?: string;
33
35
  }
34
36
  export interface PermissionsRewrittenRule {
35
37
  from: string;
@@ -1,5 +1,5 @@
1
- import { compileAllowList, hasCoreValuePort, protocolOf, retiredToolNames, ruleToolGrammarOf } from './coreValuePorts.js';
2
- import { clientOwnedServerPrefix, protocolSegmentOf } from './protocolSegment.js';
1
+ import { compileAllowList, hasCoreValuePort, protocolOf, ruleToolGrammarOf } from './coreValuePorts.js';
2
+ import { clientOwnedServerPrefix, mintedPrefixOf, ruleToolNameVerdictOf } from './protocolSegment.js';
3
3
  import { ruleCompileVerdict } from './ruleCompileVerdict.js';
4
4
  import { allowRulesGate, allowWireForm } from './permissionsAllowGrantCapability.js';
5
5
  import { THROWN_SLOT_UNREADABLE, readThrownSlot } from './wireFailureShape.js';
@@ -74,22 +74,33 @@ function parseRule(rule) {
74
74
  return { toolName: normalizeLegacyToolName(toolName), ruleContent: unescapeRuleContent(rawContent) };
75
75
  }
76
76
  function requireRulePorts() {
77
- const required = ['MCP_NAMESPACE', 'RETIRED_TOOL_NAMES', 'protocolOf', 'ruleToolGrammarOf', 'validatePermissionRules'];
77
+ const required = ['MCP_NAMESPACE', 'judgeRuleToolName', 'protocolOf', 'ruleToolGrammarOf', 'validatePermissionRules'];
78
78
  const missing = required.filter((p) => !hasCoreValuePort(p));
79
79
  if (missing.length === 0)
80
80
  return;
81
81
  throw new Error(`permissionsDeclaration: 规则判据端口缺席(${missing.join(' / ')})—— 先用 installCoreValuePorts 装上 core 的同名实现。` +
82
82
  '缺席不等于全部合格:不判就发会让整份请求被引擎拒收,不判就删会静默丢掉 deny 规则,所以这里拒绝装配。');
83
83
  }
84
- function wireIssue(name) {
84
+ function nameCheck(name) {
85
85
  if (name.includes('('))
86
- return 'paren_in_tool_name';
87
- if (retiredToolNames().has(name))
88
- return 'retired_tool_name';
86
+ return { issue: 'paren_in_tool_name' };
87
+ const verdict = ruleToolNameVerdictOf(name);
88
+ if (verdict.kind === 'unknown') {
89
+ throw new Error('permissionsDeclaration: 规则工具名判官(judgeRuleToolName)答不上来(抛 / 回的不是 current · retired · unprefixed_namespace · unmintable_segment 之一)—— ' +
90
+ '装的必须是 core 的同名实现、原样装。判不出不等于够得着:不判就发会让整份请求被引擎拒收,不判就删会静默丢掉 deny 规则,所以这里拒绝装配。');
91
+ }
92
+ if (verdict.kind === 'retired')
93
+ return { issue: 'retired_tool_name' };
94
+ if (verdict.kind === 'unprefixed_namespace')
95
+ return { issue: 'unprefixed_namespaced_name' };
89
96
  const ns = protocolOf(name);
90
- if (ns === undefined)
91
- return name.includes('__') ? 'unprefixed_namespaced_name' : undefined;
92
- return ns.parse(name) !== undefined ? undefined : 'incomplete_protocol_name';
97
+ if (ns !== undefined && ns.parse(name) === undefined)
98
+ return { issue: 'incomplete_protocol_name' };
99
+ if (verdict.kind === 'unmintable_segment') {
100
+ const minted = mintedPrefixOf(name);
101
+ return { unminted: minted !== undefined ? { minted } : {} };
102
+ }
103
+ return { ok: true };
93
104
  }
94
105
  function wholeServerRuleName(name) {
95
106
  const read = name.trim();
@@ -101,11 +112,16 @@ function wholeServerRuleName(name) {
101
112
  }
102
113
  const compileVerdict = ruleCompileVerdict;
103
114
  const kept = (reason) => ({ sent: false, reason });
104
- function sentFate(wire, toolName, unchecked) {
105
- const segment = protocolSegmentOf(toolName);
106
- return segment.kind === 'unminted'
107
- ? { sent: true, wire, unchecked, unreachable: segment.minted !== undefined ? { minted: segment.minted } : {} }
108
- : { sent: true, wire, unchecked };
115
+ function compileRefused(verdict) {
116
+ return {
117
+ sent: false,
118
+ reason: 'compile_refused',
119
+ ...(verdict.code !== undefined ? { code: verdict.code } : {}),
120
+ ...(verdict.message !== undefined ? { message: verdict.message } : {}),
121
+ };
122
+ }
123
+ function sentFate(wire, check, unchecked) {
124
+ return 'unminted' in check ? { sent: true, wire, unchecked, unreachable: check.unminted } : { sent: true, wire, unchecked };
109
125
  }
110
126
  function judgeList(rules, behavior, allowForm = 'grant') {
111
127
  let portsChecked = false;
@@ -119,42 +135,34 @@ function judgeList(rules, behavior, allowForm = 'grant') {
119
135
  const parsed = parseRule(rule);
120
136
  if (parsed.ruleContent === undefined) {
121
137
  const name = wholeServerRuleName(parsed.toolName);
122
- const issue = wireIssue(name);
123
- if (issue !== undefined)
124
- return kept(issue);
125
- if (behavior === 'allow') {
126
- const segment = protocolSegmentOf(name);
127
- if (segment.kind === 'unminted')
128
- return kept('unminted_protocol_segment');
129
- if (segment.kind === 'unknown')
130
- return kept('judge_failed');
131
- }
138
+ const check = nameCheck(name);
139
+ if ('issue' in check)
140
+ return kept(check.issue);
141
+ if (behavior === 'allow' && 'unminted' in check)
142
+ return kept('unminted_protocol_segment');
132
143
  const verdict = compileVerdict(name, behavior === 'ask' ? 'ask' : 'deny');
133
- if (verdict === 'refused')
134
- return kept('compile_refused');
135
- if (verdict === 'unknown' && behavior === 'allow')
144
+ if (verdict.kind === 'refused')
145
+ return compileRefused(verdict);
146
+ if (verdict.kind === 'unknown' && behavior === 'allow')
136
147
  return kept('judge_failed');
137
- return behavior === 'allow' ? { sent: true, wire: name, unchecked: false } : sentFate(name, name, verdict === 'unknown');
148
+ return behavior === 'allow' ? { sent: true, wire: name, unchecked: false } : sentFate(name, check, verdict.kind === 'unknown');
138
149
  }
139
- const issue = wireIssue(parsed.toolName);
140
- if (issue !== undefined)
141
- return kept(issue);
150
+ const check = nameCheck(parsed.toolName);
151
+ if ('issue' in check)
152
+ return kept(check.issue);
142
153
  if (ruleToolGrammarOf(parsed.toolName) === 'path' && parsed.ruleContent.startsWith('~/'))
143
154
  return kept('home_relative_path');
144
155
  if (behavior === 'allow') {
145
156
  if (allowForm !== 'layer')
146
157
  return kept('content_form_not_grantable');
147
- const segment = protocolSegmentOf(parsed.toolName);
148
- if (segment.kind === 'unminted')
158
+ if ('unminted' in check)
149
159
  return kept('unminted_protocol_segment');
150
- if (segment.kind === 'unknown')
151
- return kept('judge_failed');
152
160
  return { sent: true, wire: rule, unchecked: false };
153
161
  }
154
162
  const verdict = compileVerdict(rule, behavior);
155
- if (verdict === 'refused')
156
- return kept('compile_refused');
157
- return sentFate(rule, parsed.toolName, verdict === 'unknown');
163
+ if (verdict.kind === 'refused')
164
+ return compileRefused(verdict);
165
+ return sentFate(rule, check, verdict.kind === 'unknown');
158
166
  });
159
167
  }
160
168
  function outsideSettingsFiles(origin) {
@@ -370,8 +378,15 @@ function assemble(input, caps) {
370
378
  for (const [bucket, slots, j] of rows) {
371
379
  slots.forEach((s, k) => {
372
380
  const f = j.fates[k];
373
- if (!f.sent)
374
- keptRows.push({ rule: s.rule, bucket, reason: f.reason });
381
+ if (!f.sent) {
382
+ keptRows.push({
383
+ rule: s.rule,
384
+ bucket,
385
+ reason: f.reason,
386
+ ...(f.code !== undefined ? { code: f.code } : {}),
387
+ ...(f.message !== undefined ? { message: f.message } : {}),
388
+ });
389
+ }
375
390
  });
376
391
  for (const wire of j.sent) {
377
392
  const winner = j.winnerOf.get(wire);
@@ -0,0 +1,12 @@
1
+ import { type GateOutcomeView } from './gateOutcome.js';
2
+ import { type NoticeOutlet, type NoticeSeatClass } from './noticePresentation.js';
3
+ export declare const PRINT_PERMISSION_OUTCOME_FORMS: readonly ["mode_denied", "no_approver", "mode_released"];
4
+ export type PrintPermissionOutcomeForm = (typeof PRINT_PERMISSION_OUTCOME_FORMS)[number];
5
+ export interface PrintPermissionOutcome {
6
+ readonly form: PrintPermissionOutcomeForm;
7
+ readonly sentence: string;
8
+ readonly audience: 'user';
9
+ readonly outlet: NoticeOutlet;
10
+ readonly seatClass: NoticeSeatClass;
11
+ }
12
+ export declare function printPermissionOutcomeOf(gate: GateOutcomeView | undefined): PrintPermissionOutcome | undefined;
@@ -0,0 +1,50 @@
1
+ import { modeReleaseReasonSentence } from './gateOutcome.js';
2
+ import { noticeSeatClassOf } from './noticePresentation.js';
3
+ import { guardedRead, readOwnDataValue } from './ownKey.js';
4
+ export const PRINT_PERMISSION_OUTCOME_FORMS = Object.freeze(['mode_denied', 'no_approver', 'mode_released']);
5
+ const ALLOW_RULE_REMEDY = 'add an allow rule for the tool in settings (or pass --allowedTools)';
6
+ const SENTENCES = Object.freeze({
7
+ dontAsk: {
8
+ sentence: `the dontAsk permission mode denies tools that need approval unless a permission rule allows them — ${ALLOW_RULE_REMEDY}`,
9
+ outlet: 'present',
10
+ },
11
+ bypassPermissions: {
12
+ sentence: 'the bypassPermissions permission mode refused a call because it could not tell whether the write it makes lands on a protected path',
13
+ outlet: 'absent',
14
+ },
15
+ mode: { sentence: "the session's permission mode denied a call that needed approval", outlet: 'absent' },
16
+ no_approver: {
17
+ sentence: `print mode has no approval channel: tools that need approval are denied unless a permission rule allows them — ${ALLOW_RULE_REMEDY}, or pass --permission-mode acceptEdits or auto`,
18
+ outlet: 'present',
19
+ },
20
+ });
21
+ function outcomeOf(form, sentence, outlet) {
22
+ return Object.freeze({ form, sentence, audience: 'user', outlet, seatClass: noticeSeatClassOf('user', outlet) });
23
+ }
24
+ function slot(from, key) {
25
+ return typeof from === 'object' && from !== null ? guardedRead(() => readOwnDataValue(from, key)) : undefined;
26
+ }
27
+ export function printPermissionOutcomeOf(gate) {
28
+ const disposition = slot(gate, 'disposition');
29
+ const kind = slot(disposition, 'kind');
30
+ if (kind === 'denied') {
31
+ const deniedBy = slot(disposition, 'deniedBy');
32
+ if (deniedBy === 'mode') {
33
+ const mode = slot(disposition, 'mode');
34
+ const row = mode === 'dontAsk' ? SENTENCES.dontAsk : mode === 'bypassPermissions' ? SENTENCES.bypassPermissions : SENTENCES.mode;
35
+ return outcomeOf('mode_denied', row.sentence, row.outlet);
36
+ }
37
+ if (deniedBy === 'ask_resolution') {
38
+ const settled = slot(slot(gate, 'settlement'), 'kind');
39
+ if (settled === 'no_approver' || settled === 'approver_unavailable')
40
+ return outcomeOf('no_approver', SENTENCES.no_approver.sentence, SENTENCES.no_approver.outlet);
41
+ }
42
+ return undefined;
43
+ }
44
+ if (kind === 'allowed') {
45
+ const reason = slot(slot(disposition, 'released'), 'reason');
46
+ const sentence = typeof reason === 'string' ? modeReleaseReasonSentence(reason) : undefined;
47
+ return sentence === undefined ? undefined : outcomeOf('mode_released', sentence, 'absent');
48
+ }
49
+ return undefined;
50
+ }
@@ -13,6 +13,7 @@ export interface ToolEndResultArmLike {
13
13
  delivered?: unknown;
14
14
  gatedCallId?: unknown;
15
15
  _sema_denial_kind?: unknown;
16
+ notExecuted?: true;
16
17
  parentToolCallId?: unknown;
17
18
  uuid?: unknown;
18
19
  session_id?: unknown;