@sema-agent/client-core 0.88.0 → 0.89.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.
@@ -1,25 +1,19 @@
1
1
  import { AUTO_MODE_UNAVAILABLE_CAUSES } from './autoModeUnavailable.js';
2
- import { CORE_ENGINE_NOTICE_CODES, CORE_MCP_INJECTION_DROP_REASONS, CORE_NOTICE_AUDIENCE } from './generated/engineNoticeTables.js';
2
+ import { CORE_ENGINE_NOTICE_CODES, CORE_MCP_INJECTION_DROP_REASONS, CORE_NOTICE_AUDIENCE, } from './generated/engineNoticeTables.js';
3
3
  import { CORE_ASK_UNRESOLVABLE_CAUSES, CORE_DURABLE_MANDATE_SOURCES, CORE_PERMISSION_MODE_FOLD_REASONS, } from './generated/engineFactTables.js';
4
4
  export const ENGINE_NOTICE_CODES = CORE_ENGINE_NOTICE_CODES;
5
5
  const CATALOG = new Set(ENGINE_NOTICE_CODES);
6
- export const SERVER_NOTICE_AUDIENCE = Object.freeze({
7
- 'instructions.source_changed': 'user',
8
- 'memory.layer_locked_legacy': 'operator',
9
- 'session.records_skipped': 'user',
10
- 'server.model_unreachable': 'user',
11
- });
12
6
  function audienceRow(table, code) {
13
7
  return Object.hasOwn(table, code) ? table[code] : undefined;
14
8
  }
15
9
  export function engineNoticeInCatalog(code) {
16
- return typeof code === 'string' && (CATALOG.has(code) || Object.hasOwn(SERVER_NOTICE_AUDIENCE, code));
10
+ return typeof code === 'string' && CATALOG.has(code);
17
11
  }
18
12
  export const ENGINE_NOTICE_AUDIENCE = CORE_NOTICE_AUDIENCE;
19
13
  export function noticeAudienceOf(code) {
20
14
  if (typeof code !== 'string')
21
15
  return 'operator';
22
- return audienceRow(ENGINE_NOTICE_AUDIENCE, code) ?? audienceRow(SERVER_NOTICE_AUDIENCE, code) ?? 'operator';
16
+ return audienceRow(ENGINE_NOTICE_AUDIENCE, code) ?? 'operator';
23
17
  }
24
18
  export const MCP_INJECTION_DROP_REASONS = CORE_MCP_INJECTION_DROP_REASONS;
25
19
  const DROP_REASONS = new Set(MCP_INJECTION_DROP_REASONS);
@@ -27,9 +21,9 @@ export function readMcpInjectionDrop(notice) {
27
21
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
28
22
  return undefined;
29
23
  const n = notice;
30
- if (n.code !== 'mcp.injection_dropped')
24
+ if (ownSeat(n, 'code') !== 'mcp.injection_dropped')
31
25
  return undefined;
32
- const d = n.detail;
26
+ const d = ownSeat(n, 'detail');
33
27
  if (typeof d !== 'object' || d === null || Array.isArray(d))
34
28
  return undefined;
35
29
  const o = d;
@@ -59,9 +53,9 @@ export function readAskUnresolvable(notice) {
59
53
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
60
54
  return undefined;
61
55
  const n = notice;
62
- if (n.code !== 'delegation.ask_unresolvable')
56
+ if (ownSeat(n, 'code') !== 'delegation.ask_unresolvable')
63
57
  return undefined;
64
- const d = n.detail;
58
+ const d = ownSeat(n, 'detail');
65
59
  if (typeof d !== 'object' || d === null || Array.isArray(d))
66
60
  return undefined;
67
61
  const o = d;
@@ -93,9 +87,9 @@ export function readDurableGateUnavailable(notice) {
93
87
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
94
88
  return undefined;
95
89
  const n = notice;
96
- if (n.code !== 'config.durable_gate_unavailable')
90
+ if (ownSeat(n, 'code') !== 'config.durable_gate_unavailable')
97
91
  return undefined;
98
- const d = n.detail;
92
+ const d = ownSeat(n, 'detail');
99
93
  if (typeof d !== 'object' || d === null || Array.isArray(d))
100
94
  return undefined;
101
95
  const o = d;
@@ -138,9 +132,9 @@ export function readSkillsListingTruncated(notice) {
138
132
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
139
133
  return undefined;
140
134
  const n = notice;
141
- if (n.code !== 'skills.listing_truncated')
135
+ if (ownSeat(n, 'code') !== 'skills.listing_truncated')
142
136
  return undefined;
143
- const d = n.detail;
137
+ const d = ownSeat(n, 'detail');
144
138
  if (typeof d !== 'object' || d === null || Array.isArray(d))
145
139
  return undefined;
146
140
  const o = d;
@@ -170,9 +164,9 @@ export function readMcpServerRedialed(notice) {
170
164
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
171
165
  return undefined;
172
166
  const n = notice;
173
- if (n.code !== 'mcp.server_redialed')
167
+ if (ownSeat(n, 'code') !== 'mcp.server_redialed')
174
168
  return undefined;
175
- const d = n.detail;
169
+ const d = ownSeat(n, 'detail');
176
170
  if (typeof d !== 'object' || d === null || Array.isArray(d))
177
171
  return undefined;
178
172
  const o = d;
@@ -205,9 +199,10 @@ function readRootGrantNoticeOf(notice) {
205
199
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
206
200
  return undefined;
207
201
  const n = notice;
208
- if (n.code !== 'approval.read_root_granted' && n.code !== 'approval.read_root_grant_rejected')
202
+ const code = ownSeat(n, 'code');
203
+ if (code !== 'approval.read_root_granted' && code !== 'approval.read_root_grant_rejected')
209
204
  return undefined;
210
- const d = n.detail;
205
+ const d = ownSeat(n, 'detail');
211
206
  if (typeof d !== 'object' || d === null || Array.isArray(d))
212
207
  return undefined;
213
208
  const o = d;
@@ -216,7 +211,7 @@ function readRootGrantNoticeOf(notice) {
216
211
  if (toolCallId === undefined)
217
212
  return undefined;
218
213
  const sessionId = str(o.sessionId);
219
- if (n.code === 'approval.read_root_granted') {
214
+ if (code === 'approval.read_root_granted') {
220
215
  const dir = str(o.dir);
221
216
  const root = str(o.root);
222
217
  if (dir === undefined || root === undefined)
@@ -248,9 +243,9 @@ export function readInstructionsSourceChanged(notice) {
248
243
  return undefined;
249
244
  try {
250
245
  const n = notice;
251
- if (n.code !== 'instructions.source_changed')
246
+ if (ownSeat(n, 'code') !== 'instructions.source_changed')
252
247
  return undefined;
253
- const d = n.detail;
248
+ const d = ownSeat(n, 'detail');
254
249
  if (typeof d !== 'object' || d === null || Array.isArray(d))
255
250
  return undefined;
256
251
  const o = d;
@@ -274,9 +269,9 @@ export function readSessionRecordsSkipped(notice) {
274
269
  return undefined;
275
270
  try {
276
271
  const n = notice;
277
- if (n.code !== 'session.records_skipped')
272
+ if (ownSeat(n, 'code') !== 'session.records_skipped')
278
273
  return undefined;
279
- const d = n.detail;
274
+ const d = ownSeat(n, 'detail');
280
275
  if (typeof d !== 'object' || d === null || Array.isArray(d))
281
276
  return undefined;
282
277
  const o = d;
@@ -320,9 +315,9 @@ function readRuleStoreUnavailableOf(notice) {
320
315
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
321
316
  return undefined;
322
317
  const n = notice;
323
- if (n.code !== 'permission.rule_store_unavailable')
318
+ if (ownSeat(n, 'code') !== 'permission.rule_store_unavailable')
324
319
  return undefined;
325
- const d = n.detail;
320
+ const d = ownSeat(n, 'detail');
326
321
  if (typeof d !== 'object' || d === null || Array.isArray(d))
327
322
  return undefined;
328
323
  const o = d;
@@ -344,9 +339,9 @@ function readClassifierUnavailableOf(notice) {
344
339
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
345
340
  return undefined;
346
341
  const n = notice;
347
- if (n.code !== 'classifier.unavailable')
342
+ if (ownSeat(n, 'code') !== 'classifier.unavailable')
348
343
  return undefined;
349
- const d = n.detail;
344
+ const d = ownSeat(n, 'detail');
350
345
  if (typeof d !== 'object' || d === null || Array.isArray(d))
351
346
  return undefined;
352
347
  const o = d;
@@ -380,9 +375,9 @@ function readPermissionModeUnavailableOf(notice) {
380
375
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
381
376
  return undefined;
382
377
  const n = notice;
383
- if (n.code !== 'config.permission_mode_unavailable')
378
+ if (ownSeat(n, 'code') !== 'config.permission_mode_unavailable')
384
379
  return undefined;
385
- const d = n.detail;
380
+ const d = ownSeat(n, 'detail');
386
381
  if (typeof d !== 'object' || d === null || Array.isArray(d))
387
382
  return undefined;
388
383
  const o = d;
@@ -405,9 +400,9 @@ function readAskReleasedByModeOf(notice) {
405
400
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
406
401
  return undefined;
407
402
  const n = notice;
408
- if (n.code !== 'permission.ask_released_by_mode')
403
+ if (ownSeat(n, 'code') !== 'permission.ask_released_by_mode')
409
404
  return undefined;
410
- const d = n.detail;
405
+ const d = ownSeat(n, 'detail');
411
406
  if (typeof d !== 'object' || d === null || Array.isArray(d))
412
407
  return undefined;
413
408
  const o = d;
@@ -440,9 +435,9 @@ function readReadDenyUnappliedOf(notice) {
440
435
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
441
436
  return undefined;
442
437
  const n = notice;
443
- if (n.code !== 'permission.read_deny_unapplied')
438
+ if (ownSeat(n, 'code') !== 'permission.read_deny_unapplied')
444
439
  return undefined;
445
- const d = n.detail;
440
+ const d = ownSeat(n, 'detail');
446
441
  if (typeof d !== 'object' || d === null || Array.isArray(d))
447
442
  return undefined;
448
443
  const o = d;
@@ -466,9 +461,9 @@ function readLegacyModeSeedMigratedOf(notice) {
466
461
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
467
462
  return undefined;
468
463
  const n = notice;
469
- if (n.code !== 'resume.legacy_mode_seed_migrated')
464
+ if (ownSeat(n, 'code') !== 'resume.legacy_mode_seed_migrated')
470
465
  return undefined;
471
- const d = n.detail;
466
+ const d = ownSeat(n, 'detail');
472
467
  if (typeof d !== 'object' || d === null || Array.isArray(d))
473
468
  return undefined;
474
469
  const o = d;
@@ -502,9 +497,9 @@ function readToolTurnRepairedOf(notice) {
502
497
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
503
498
  return undefined;
504
499
  const n = notice;
505
- if (n.code !== 'context.tool_turn_repaired')
500
+ if (ownSeat(n, 'code') !== 'context.tool_turn_repaired')
506
501
  return undefined;
507
- const d = n.detail;
502
+ const d = ownSeat(n, 'detail');
508
503
  if (typeof d !== 'object' || d === null || Array.isArray(d))
509
504
  return undefined;
510
505
  const o = d;
@@ -537,9 +532,9 @@ function readModelUnreachableOf(notice) {
537
532
  if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
538
533
  return undefined;
539
534
  const n = notice;
540
- if (n.code !== 'server.model_unreachable')
535
+ if (ownSeat(n, 'code') !== 'server.model_unreachable')
541
536
  return undefined;
542
- const d = n.detail;
537
+ const d = ownSeat(n, 'detail');
543
538
  if (typeof d !== 'object' || d === null || Array.isArray(d))
544
539
  return undefined;
545
540
  const o = d;
@@ -552,6 +547,109 @@ function readModelUnreachableOf(notice) {
552
547
  const proxyInUse = nonEmpty(optionalOwnSeat(o, 'proxyInUse'));
553
548
  return { code, targetHost, ...(proxyInUse !== undefined ? { proxyInUse } : {}), remedy, sessionId };
554
549
  }
550
+ const positiveInt = (v) => (typeof v === 'number' && Number.isInteger(v) && v > 0 ? v : undefined);
551
+ export function readToolTurnIncomplete(notice) {
552
+ return guardedRead(notice, readToolTurnIncompleteOf);
553
+ }
554
+ function optionalNameList(o, key) {
555
+ try {
556
+ const ids = nameList(ownSeat(o, key));
557
+ return ids !== undefined && ids.length > 0 ? ids : undefined;
558
+ }
559
+ catch {
560
+ return undefined;
561
+ }
562
+ }
563
+ function readToolTurnIncompleteOf(notice) {
564
+ if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
565
+ return undefined;
566
+ const n = notice;
567
+ if (ownSeat(n, 'code') !== 'task.tool_turn_incomplete')
568
+ return undefined;
569
+ const d = ownSeat(n, 'detail');
570
+ if (typeof d !== 'object' || d === null || Array.isArray(d))
571
+ return undefined;
572
+ const o = d;
573
+ const cause = nonEmpty(ownSeat(o, 'cause'));
574
+ const count = positiveInt(ownSeat(o, 'count'));
575
+ const toolCallIds = optionalNameList(o, 'toolCallIds');
576
+ const sessionId = nonEmpty(ownSeat(o, 'sessionId'));
577
+ const runId = nonEmpty(ownSeat(o, 'runId'));
578
+ if (cause === undefined || count === undefined || sessionId === undefined || runId === undefined)
579
+ return undefined;
580
+ return { cause, count, ...(toolCallIds !== undefined ? { toolCallIds } : {}), sessionId, runId };
581
+ }
582
+ export function readUserInputUndrained(notice) {
583
+ return guardedRead(notice, readUserInputUndrainedOf);
584
+ }
585
+ function readUserInputUndrainedOf(notice) {
586
+ if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
587
+ return undefined;
588
+ const n = notice;
589
+ const code = ownSeat(n, 'code');
590
+ const kind = code === 'task.user_steer_undrained' ? 'steer' : code === 'task.user_followup_undrained' ? 'followUp' : undefined;
591
+ if (kind === undefined)
592
+ return undefined;
593
+ const d = ownSeat(n, 'detail');
594
+ if (typeof d !== 'object' || d === null || Array.isArray(d))
595
+ return undefined;
596
+ const o = d;
597
+ const count = positiveInt(ownSeat(o, kind));
598
+ if (count === undefined)
599
+ return undefined;
600
+ const cause = nonEmpty(optionalOwnSeat(o, 'cause'));
601
+ const taskId = nonEmpty(optionalOwnSeat(o, 'taskId'));
602
+ const sessionId = nonEmpty(optionalOwnSeat(o, 'sessionId'));
603
+ const runId = nonEmpty(optionalOwnSeat(o, 'runId'));
604
+ return {
605
+ kind,
606
+ count,
607
+ ...(cause !== undefined ? { cause } : {}),
608
+ ...(taskId !== undefined ? { taskId } : {}),
609
+ ...(sessionId !== undefined ? { sessionId } : {}),
610
+ ...(runId !== undefined ? { runId } : {}),
611
+ };
612
+ }
613
+ const messagesPhrase = (n, noun) => `${n} ${noun}${n === 1 ? '' : 's'}`;
614
+ const verbBe = (n) => (n === 1 ? 'was' : 'were');
615
+ const itThem = (n) => (n === 1 ? 'it' : 'them');
616
+ const STEER_UNDRAINED_SENTENCE = Object.freeze({
617
+ leg_end: (n) => `${messagesPhrase(n, 'message')} you sent while the run was in progress ${verbBe(n)} not used before the run ended and will not be delivered. ` +
618
+ `Send ${itThem(n)} again if you still need ${itThem(n)}.`,
619
+ crashed: (n) => `${messagesPhrase(n, 'message')} you sent to an earlier run ${verbBe(n)} accepted, but the server stopped before that run finished, ` +
620
+ `so whether the run used ${itThem(n)} is not known. Check that run's transcript and results before sending ${itThem(n)} again.`,
621
+ });
622
+ const _steerSentencePin = true;
623
+ void _steerSentencePin;
624
+ const followUpUndrainedSentence = (n) => `${messagesPhrase(n, 'follow-up message')} you queued ${verbBe(n)} not used before the run ended and will not be delivered. ` +
625
+ `Send ${itThem(n)} again if you still need ${itThem(n)}.`;
626
+ const unrecognizedUndrainedSentence = (n, kind) => `${kind === 'followUp' ? `${messagesPhrase(n, 'follow-up message')} you queued` : `${messagesPhrase(n, 'message')} you sent during a run`} may not have been used, ` +
627
+ `and the reason was not reported in a form this version recognizes. Check the run's transcript before sending ${itThem(n)} again.`;
628
+ export function userInputUndrainedNotice(facts) {
629
+ let kind;
630
+ let count;
631
+ let cause;
632
+ try {
633
+ if (facts === null || typeof facts !== 'object' || Array.isArray(facts))
634
+ return undefined;
635
+ kind = Object.hasOwn(facts, 'kind') ? facts.kind : undefined;
636
+ count = Object.hasOwn(facts, 'count') ? facts.count : undefined;
637
+ cause = Object.hasOwn(facts, 'cause') ? facts.cause : undefined;
638
+ }
639
+ catch {
640
+ return undefined;
641
+ }
642
+ const n = positiveInt(count);
643
+ if (n === undefined || (kind !== 'steer' && kind !== 'followUp'))
644
+ return undefined;
645
+ if (kind === 'followUp') {
646
+ return cause === undefined || cause === 'leg_end' ? followUpUndrainedSentence(n) : unrecognizedUndrainedSentence(n, kind);
647
+ }
648
+ if (typeof cause === 'string' && Object.hasOwn(STEER_UNDRAINED_SENTENCE, cause)) {
649
+ return STEER_UNDRAINED_SENTENCE[cause](n);
650
+ }
651
+ return unrecognizedUndrainedSentence(n, kind);
652
+ }
555
653
  export const ENGINE_NOTICE_FACT_READERS = Object.freeze({
556
654
  'mcp.injection_dropped': readMcpInjectionDrop,
557
655
  'delegation.ask_unresolvable': readAskUnresolvable,
@@ -570,6 +668,9 @@ export const ENGINE_NOTICE_FACT_READERS = Object.freeze({
570
668
  'resume.legacy_mode_seed_migrated': readLegacyModeSeedMigrated,
571
669
  'context.tool_turn_repaired': readToolTurnRepaired,
572
670
  'server.model_unreachable': readModelUnreachable,
671
+ 'task.tool_turn_incomplete': readToolTurnIncomplete,
672
+ 'task.user_steer_undrained': readUserInputUndrained,
673
+ 'task.user_followup_undrained': readUserInputUndrained,
573
674
  });
574
675
  const _factReaderTablePin = true;
575
676
  void _factReaderTablePin;
@@ -579,10 +680,10 @@ export function readEngineNoticeFacts(notice) {
579
680
  let code;
580
681
  let detail;
581
682
  try {
582
- code = notice.code;
683
+ code = ownSeat(notice, 'code');
583
684
  if (typeof code !== 'string' || !Object.hasOwn(ENGINE_NOTICE_FACT_READERS, code))
584
685
  return undefined;
585
- detail = notice.detail;
686
+ detail = ownSeat(notice, 'detail');
586
687
  }
587
688
  catch {
588
689
  return undefined;
@@ -1,3 +1,6 @@
1
1
  export declare const CORE_ENGINE_NOTICE_CODES: readonly string[];
2
2
  export declare const CORE_NOTICE_AUDIENCE: Readonly<Record<string, 'user' | 'operator'>>;
3
3
  export declare const CORE_MCP_INJECTION_DROP_REASONS: readonly string[];
4
+ export declare const CORE_NOTICE_MINTER: Readonly<Record<string, 'engine' | 'server'>>;
5
+ export declare const CORE_USER_STEER_UNDRAINED_CAUSES: readonly ["leg_end", "crashed"];
6
+ export declare const CORE_TOOL_TURN_INCOMPLETE_CAUSES: readonly ["truncated", "unnamed", "bad_frame", "missing_result_synthesized"];
@@ -73,6 +73,7 @@ export const CORE_ENGINE_NOTICE_CODES = Object.freeze([
73
73
  "task.halt_unconsumed",
74
74
  "task.late_approval",
75
75
  "task.interrupt_unconsumed",
76
+ "task.tool_turn_incomplete",
76
77
  "approval.read_root_granted",
77
78
  "approval.read_root_grant_rejected",
78
79
  "memory.capture_opted_out",
@@ -80,6 +81,10 @@ export const CORE_ENGINE_NOTICE_CODES = Object.freeze([
80
81
  "skills.listing_truncated",
81
82
  "agents.listing_truncated",
82
83
  "tool_result.offload_put_failed",
84
+ "instructions.source_changed",
85
+ "session.records_skipped",
86
+ "memory.layer_locked_legacy",
87
+ "server.model_unreachable",
83
88
  ]);
84
89
  export const CORE_NOTICE_AUDIENCE = Object.freeze({
85
90
  "config.autocompact_window_clamped": "operator",
@@ -156,6 +161,7 @@ export const CORE_NOTICE_AUDIENCE = Object.freeze({
156
161
  "task.halt_unconsumed": "user",
157
162
  "task.late_approval": "user",
158
163
  "task.interrupt_unconsumed": "user",
164
+ "task.tool_turn_incomplete": "user",
159
165
  "approval.read_root_granted": "user",
160
166
  "approval.read_root_grant_rejected": "user",
161
167
  "memory.capture_opted_out": "user",
@@ -163,6 +169,10 @@ export const CORE_NOTICE_AUDIENCE = Object.freeze({
163
169
  "skills.listing_truncated": "operator",
164
170
  "agents.listing_truncated": "operator",
165
171
  "tool_result.offload_put_failed": "operator",
172
+ "instructions.source_changed": "user",
173
+ "session.records_skipped": "user",
174
+ "memory.layer_locked_legacy": "operator",
175
+ "server.model_unreachable": "user",
166
176
  });
167
177
  export const CORE_MCP_INJECTION_DROP_REASONS = Object.freeze([
168
178
  "malformed_entry",
@@ -170,3 +180,101 @@ export const CORE_MCP_INJECTION_DROP_REASONS = Object.freeze([
170
180
  "gate_closed",
171
181
  "over_cap",
172
182
  ]);
183
+ export const CORE_NOTICE_MINTER = Object.freeze({
184
+ "config.autocompact_window_clamped": "engine",
185
+ "config.env_timeout_discarded": "engine",
186
+ "config.materialize_env_discarded": "engine",
187
+ "config.models_swapped": "engine",
188
+ "config.context_settings_swapped": "engine",
189
+ "config.read_face_swapped": "engine",
190
+ "config.read_face_deployment_clamped": "engine",
191
+ "config.write_face_swapped": "engine",
192
+ "config.write_face_deployment_clamped": "engine",
193
+ "config.tool_model_gate_removed": "engine",
194
+ "config.tool_model_gate_unknown_class": "engine",
195
+ "config.tool_model_gate_env_invalid": "engine",
196
+ "config.artifact_host_invalid": "engine",
197
+ "config.task_root_not_canonical": "engine",
198
+ "config.write_protection_target_view_absent": "engine",
199
+ "config.write_protection_unresolved": "engine",
200
+ "config.execution_env_capability_invalid": "engine",
201
+ "config.tool_card_undeclared": "engine",
202
+ "config.tool_face_undeclared": "engine",
203
+ "config.tool_face_invalid": "engine",
204
+ "config.forward_sink_failed": "engine",
205
+ "config.durable_gate_unavailable": "engine",
206
+ "config.peer_admission_out_of_range": "engine",
207
+ "config.peer_lane_unmounted": "engine",
208
+ "config.secret_env_scrubbed": "engine",
209
+ "config.permission_mode_unavailable": "engine",
210
+ "permission.ask_released_by_mode": "engine",
211
+ "permission.read_deny_unapplied": "engine",
212
+ "permission.rule_store_unavailable": "engine",
213
+ "resume.legacy_mode_seed_migrated": "engine",
214
+ "peer.inbound_disposition": "engine",
215
+ "peer.held_settled": "engine",
216
+ "peer.idle_subscription": "engine",
217
+ "classifier.denial_limit": "engine",
218
+ "classifier.fallback": "engine",
219
+ "classifier.role_defaulted": "engine",
220
+ "classifier.contract_broken": "engine",
221
+ "classifier.unavailable": "engine",
222
+ "checkpoint.execution_outcome_unrecorded": "engine",
223
+ "delegation.transcript_integrity": "engine",
224
+ "delegation.ask_unresolvable": "engine",
225
+ "mcp.injection_dropped": "engine",
226
+ "mcp.revocation_probe_failed": "engine",
227
+ "mcp.server_redialed": "engine",
228
+ "workflow.governance_key_stripped": "engine",
229
+ "workflow.agent_option_ignored": "engine",
230
+ "memory.session_polluted": "engine",
231
+ "memory.harvest_quarantined": "engine",
232
+ "memory.delegation_static_mark_waived": "engine",
233
+ "memory.content_class_declared": "engine",
234
+ "memory.hold_opened": "engine",
235
+ "memory.hold_released": "engine",
236
+ "memory.hold_disposed": "engine",
237
+ "memory.consolidation_recommended": "engine",
238
+ "memory.consolidation_committed": "engine",
239
+ "memory.consolidation_conflict": "engine",
240
+ "memory.consolidation_incomplete": "engine",
241
+ "memory.consolidation_refused": "engine",
242
+ "memory.consolidation_withheld": "engine",
243
+ "memory.restore_withheld": "engine",
244
+ "memory.project_scope_absent": "engine",
245
+ "route.fallback_to_primary": "engine",
246
+ "route.classifier_unroutable": "engine",
247
+ "route.base_url_changed_key_unchanged": "engine",
248
+ "route.response_model_mismatch": "engine",
249
+ "route.tool_call_id_folded": "engine",
250
+ "context.tool_turn_repaired": "engine",
251
+ "task.user_steer_undrained": "engine",
252
+ "task.user_followup_undrained": "engine",
253
+ "steering.parked_input_blocked": "engine",
254
+ "task.turn_interrupted": "engine",
255
+ "task.halt_unconsumed": "engine",
256
+ "task.late_approval": "engine",
257
+ "task.interrupt_unconsumed": "engine",
258
+ "task.tool_turn_incomplete": "engine",
259
+ "approval.read_root_granted": "engine",
260
+ "approval.read_root_grant_rejected": "engine",
261
+ "memory.capture_opted_out": "engine",
262
+ "memory.capture_optout_unpersisted": "engine",
263
+ "skills.listing_truncated": "engine",
264
+ "agents.listing_truncated": "engine",
265
+ "tool_result.offload_put_failed": "engine",
266
+ "instructions.source_changed": "server",
267
+ "session.records_skipped": "server",
268
+ "memory.layer_locked_legacy": "server",
269
+ "server.model_unreachable": "server",
270
+ });
271
+ export const CORE_USER_STEER_UNDRAINED_CAUSES = Object.freeze([
272
+ "leg_end",
273
+ "crashed",
274
+ ]);
275
+ export const CORE_TOOL_TURN_INCOMPLETE_CAUSES = Object.freeze([
276
+ "truncated",
277
+ "unnamed",
278
+ "bad_frame",
279
+ "missing_result_synthesized",
280
+ ]);
@@ -144,6 +144,8 @@ export interface ApprovalCardRequest {
144
144
  mandate?: ApprovalMandateWord;
145
145
  denialLimitFallback?: DenialLimitFallback;
146
146
  origin?: string;
147
+ askClass?: string;
148
+ classes?: readonly string[];
147
149
  ruleStoreUnreadable?: RuleStoreUnreadableKind;
148
150
  }
149
151
  export type ApprovalCardPort = (req: ApprovalCardRequest) => Promise<ApprovalCardDecision>;
@@ -183,6 +185,8 @@ export interface ToolApprovalFrame {
183
185
  mandated?: true;
184
186
  mandate?: string;
185
187
  origin?: string;
188
+ askClass?: string;
189
+ classes?: readonly string[];
186
190
  inputHasBidi?: true;
187
191
  parked?: true;
188
192
  expiresInMs?: number;
@@ -200,7 +204,7 @@ export interface ToolApprovalDelegation {
200
204
  depth: number;
201
205
  agentName?: string;
202
206
  }
203
- export declare const TOOL_APPROVAL_FRAME_KEYS_MIRROR: readonly ["type", "approvalId", "toolCallId", "toolName", "sourceTaskId", "fromSubagent", "sourceAgentName", "message", "args", "argsOmitted", "governanceForced", "ruleSuggestions", "ruleOffers", "ruleOffersAbsence", "denialLimitFallback", "ruleStoreUnreadable", "readRootCandidate", "mandated", "mandate", "origin", "inputHasBidi", "parked", "persistedRuleShadowed", "probeCause", "ruleEvidence", "requiresRealApproval", "expiresInMs", "expiresAtMs", "serverNowMs", "delegation", "outcome"];
207
+ export declare const TOOL_APPROVAL_FRAME_KEYS_MIRROR: readonly ["type", "approvalId", "toolCallId", "toolName", "sourceTaskId", "fromSubagent", "sourceAgentName", "message", "args", "argsOmitted", "governanceForced", "ruleSuggestions", "ruleOffers", "ruleOffersAbsence", "denialLimitFallback", "ruleStoreUnreadable", "readRootCandidate", "mandated", "mandate", "origin", "askClass", "classes", "inputHasBidi", "parked", "persistedRuleShadowed", "probeCause", "ruleEvidence", "requiresRealApproval", "expiresInMs", "expiresAtMs", "serverNowMs", "delegation", "outcome"];
204
208
  export interface ApprovalMandatedFacts {
205
209
  readonly mandated?: true;
206
210
  readonly ruleOffersAbsence?: string;
@@ -210,7 +214,7 @@ export declare function approvalIsMandated(v: ApprovalMandatedFacts | undefined
210
214
  export declare function readApprovalMandate(v: {
211
215
  readonly mandate?: string;
212
216
  } | undefined | null): ApprovalMandateWord | undefined;
213
- export declare function toolPermissionRequestAskBits(card: object | null | undefined): Pick<ToolPermissionRequest, 'mandated' | 'mandate' | 'origin' | 'ruleOffersAbsence'>;
217
+ export declare function toolPermissionRequestAskBits(card: object | null | undefined): Pick<ToolPermissionRequest, 'mandated' | 'mandate' | 'origin' | 'ruleOffersAbsence' | 'askClass' | 'classes'>;
214
218
  export declare function isFromSubagent(frame: ToolApprovalFrame): boolean;
215
219
  export type ToolApprovalRespondDecision = 'allow' | 'allow_session' | 'deny';
216
220
  export interface RespondToolApprovalOpts {
@@ -210,6 +210,7 @@ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signa
210
210
  ...(hasOwnStrictTrue(pending, 'mandated') ? { mandated: true } : {}),
211
211
  ...((w) => (w !== undefined ? { mandate: w } : {}))(readApprovalMandate(pending)),
212
212
  ...((o) => (o !== undefined ? { origin: o } : {}))(readOwnNonEmptyString(pending, 'origin')),
213
+ ...(readAskClassPair(pending) ?? {}),
213
214
  ...(pending.gateKind === 'irreversible_ask' ? { irreversibleParkGate: true } : {}),
214
215
  ...(pending.hasBidiControls === true ? { hasBidiControls: true } : {}),
215
216
  ...(ruleOffersReadOnly !== undefined ? { ruleOffersReadOnly } : {}),
@@ -386,6 +387,8 @@ export const TOOL_APPROVAL_FRAME_KEYS_MIRROR = [
386
387
  'mandated',
387
388
  'mandate',
388
389
  'origin',
390
+ 'askClass',
391
+ 'classes',
389
392
  'inputHasBidi',
390
393
  'parked',
391
394
  'persistedRuleShadowed',
@@ -425,13 +428,39 @@ export function toolPermissionRequestAskBits(card) {
425
428
  const mandate = readApprovalMandate(card);
426
429
  const origin = readOwnNonEmptyString(card, 'origin');
427
430
  const ruleOffersAbsence = readOwnNonEmptyString(card, 'ruleOffersAbsence');
431
+ const askClassPair = readAskClassPair(card);
428
432
  return {
429
433
  ...(mandated ? { mandated: true } : {}),
430
434
  ...(mandate !== undefined ? { mandate } : {}),
431
435
  ...(origin !== undefined ? { origin } : {}),
432
436
  ...(ruleOffersAbsence !== undefined ? { ruleOffersAbsence } : {}),
437
+ ...(askClassPair ?? {}),
433
438
  };
434
439
  }
440
+ function readAskClassPair(v) {
441
+ if (typeof v !== 'object' || v === null)
442
+ return undefined;
443
+ const askClass = readOwnNonEmptyString(v, 'askClass');
444
+ if (askClass === undefined || !Object.hasOwn(v, 'classes'))
445
+ return undefined;
446
+ const raw = v.classes;
447
+ if (!Array.isArray(raw) || raw.length === 0)
448
+ return undefined;
449
+ const classes = [];
450
+ const seen = new Set();
451
+ for (let i = 0; i < raw.length; i++) {
452
+ if (!Object.hasOwn(raw, i))
453
+ return undefined;
454
+ const c = raw[i];
455
+ if (typeof c !== 'string' || c === '' || seen.has(c))
456
+ return undefined;
457
+ seen.add(c);
458
+ classes.push(c);
459
+ }
460
+ if (classes[0] !== askClass)
461
+ return undefined;
462
+ return { askClass, classes: Object.freeze(classes) };
463
+ }
435
464
  function hasOwnStrictTrue(v, key) {
436
465
  return Object.hasOwn(v, key) && v[key] === true;
437
466
  }
@@ -870,6 +899,7 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
870
899
  ...(denialLimitFallback !== undefined ? { denialLimitFallback } : {}),
871
900
  ...((k) => (k !== undefined ? { ruleStoreUnreadable: k } : {}))(readRuleStoreUnreadable(frame.ruleStoreUnreadable)),
872
901
  ...((o) => (o !== undefined ? { origin: o } : {}))(readOwnNonEmptyString(frame, 'origin')),
902
+ ...(readAskClassPair(frame) ?? {}),
873
903
  });
874
904
  if (argsNotRealInput && card.kind === 'allow' && card.updatedInput !== undefined) {
875
905
  hostLog('error', `liveToolApprovalWire: ${approvalId} card returned an edited approval on a card whose arguments are not the tool's real input (${lane?.argsUnavailable === true ? 'args-unavailable ask' : 'arguments omitted or absent on the frame'}) — nothing sent (the ask stays pending)`);