@sema-agent/client-core 0.91.0 → 0.92.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 (123) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/README.md +31 -21
  3. package/dist/adapt/arms.js +4 -12
  4. package/dist/adapt/panelTasks.d.ts +0 -2
  5. package/dist/adapt/panelTasks.js +6 -26
  6. package/dist/adapt.js +2 -2
  7. package/dist/adapter/activeRunSelfHeal.d.ts +0 -2
  8. package/dist/adapter/activeRunSelfHeal.js +5 -27
  9. package/dist/adapter/downstream/terminalToSdkResult.js +16 -7
  10. package/dist/adapter/runStream.js +3 -1
  11. package/dist/askSurvivesStandingAnswer.d.ts +4 -1
  12. package/dist/askSurvivesStandingAnswer.js +13 -0
  13. package/dist/autoModeUnavailable.js +3 -2
  14. package/dist/cloudConfigWireCaps.js +5 -4
  15. package/dist/compensations.js +5 -5
  16. package/dist/controlRouter.d.ts +23 -23
  17. package/dist/controlRouter.js +114 -49
  18. package/dist/coreValuePorts.d.ts +4 -2
  19. package/dist/coreValuePorts.js +5 -0
  20. package/dist/decideFailureNote.js +4 -2
  21. package/dist/decideReceipt.d.ts +9 -0
  22. package/dist/decideReceipt.js +62 -1
  23. package/dist/displayUntrusted.js +2 -1
  24. package/dist/effectiveFacts.d.ts +14 -4
  25. package/dist/effectiveFacts.js +45 -5
  26. package/dist/engineAgentAbsence.js +2 -1
  27. package/dist/engineCapReader.js +16 -10
  28. package/dist/engineCapsCache.d.ts +2 -0
  29. package/dist/engineCapsCache.js +13 -2
  30. package/dist/engineErrorCodes.d.ts +14 -0
  31. package/dist/engineErrorCodes.js +37 -0
  32. package/dist/engineNoticeCodes.d.ts +14 -0
  33. package/dist/engineNoticeCodes.js +71 -0
  34. package/dist/executionLaneCapability.js +2 -0
  35. package/dist/gateOutcome.js +2 -17
  36. package/dist/gateVocabulary.d.ts +2 -4
  37. package/dist/gateVocabulary.js +3 -11
  38. package/dist/generated/engineFactTables.d.ts +16 -1
  39. package/dist/generated/engineFactTables.js +81 -0
  40. package/dist/generated/engineNoticeTables.js +3 -0
  41. package/dist/generated/settingsSchemaTables.d.ts +8 -0
  42. package/dist/generated/settingsSchemaTables.js +40 -0
  43. package/dist/hitl/allowRuleShadow.d.ts +21 -0
  44. package/dist/hitl/allowRuleShadow.js +167 -0
  45. package/dist/hitl/askClassPair.d.ts +14 -0
  46. package/dist/hitl/askClassPair.js +42 -0
  47. package/dist/hitl/askGateWire.js +1 -0
  48. package/dist/hitl/askSurvivesPosture.d.ts +5 -0
  49. package/dist/hitl/askSurvivesPosture.js +17 -0
  50. package/dist/hitl/automaticAnswerVerdict.d.ts +21 -0
  51. package/dist/hitl/automaticAnswerVerdict.js +143 -0
  52. package/dist/hitl/crashConverged.d.ts +1 -0
  53. package/dist/hitl/crashConverged.js +1 -1
  54. package/dist/hitl/frameRouter.d.ts +2 -0
  55. package/dist/hitl/frameRouter.js +66 -14
  56. package/dist/hitl/gateLedger.d.ts +6 -0
  57. package/dist/hitl/gateLedger.js +34 -5
  58. package/dist/hitl/hitlHostSurface.d.ts +2 -0
  59. package/dist/hitl/hitlHostSurface.js +7 -0
  60. package/dist/hitl/livePendingAsk.js +24 -5
  61. package/dist/hitl/parkResolver.js +3 -1
  62. package/dist/hitl/persistedRulesWire.d.ts +4 -1
  63. package/dist/hitl/persistedRulesWire.js +9 -2
  64. package/dist/hitl/planReviewWire.js +2 -2
  65. package/dist/hitl/replayedApproval.d.ts +21 -0
  66. package/dist/hitl/replayedApproval.js +89 -0
  67. package/dist/hitl/sessionPolicyDeliverable.js +20 -2
  68. package/dist/hitl/sessionPolicyWire.d.ts +8 -0
  69. package/dist/hitl/sessionPolicyWire.js +12 -2
  70. package/dist/hitl/toolApprovalWire.d.ts +6 -1
  71. package/dist/hitl/toolApprovalWire.js +20 -40
  72. package/dist/hookMatcherVerdict.js +2 -1
  73. package/dist/humanTurn.js +3 -4
  74. package/dist/index.d.ts +15 -5
  75. package/dist/index.js +12 -3
  76. package/dist/inheritEnvWire.js +3 -4
  77. package/dist/mcpLiveness.js +2 -1
  78. package/dist/memoryVerbsWire.d.ts +1 -1
  79. package/dist/memoryVerbsWire.js +3 -0
  80. package/dist/model/catalog.js +2 -1
  81. package/dist/model/providerPresets.d.ts +3 -1
  82. package/dist/model/tierVocabulary.d.ts +2 -1
  83. package/dist/model/tierVocabulary.js +3 -8
  84. package/dist/peerFrames.js +2 -2
  85. package/dist/permissionRuleIssue.js +9 -6
  86. package/dist/permissionsDeclaration.d.ts +7 -1
  87. package/dist/permissionsDeclaration.js +29 -20
  88. package/dist/pluginHooksWire.js +2 -11
  89. package/dist/promptProfileWireCaps.d.ts +2 -1
  90. package/dist/protocolSegment.d.ts +9 -0
  91. package/dist/protocolSegment.js +28 -0
  92. package/dist/request/taskRequest.js +1 -15
  93. package/dist/ruleCompileVerdict.d.ts +2 -0
  94. package/dist/ruleCompileVerdict.js +13 -0
  95. package/dist/ruleRemovalConsequence.d.ts +2 -1
  96. package/dist/runCancelContext.d.ts +12 -0
  97. package/dist/runCancelContext.js +83 -1
  98. package/dist/seam.js +1 -1
  99. package/dist/seatContract.d.ts +2 -1
  100. package/dist/sessionMemoryStatus.d.ts +2 -4
  101. package/dist/sessionSyncFileHistoryCapability.d.ts +18 -0
  102. package/dist/sessionSyncFileHistoryCapability.js +50 -0
  103. package/dist/skillToolListsCapability.d.ts +18 -0
  104. package/dist/skillToolListsCapability.js +50 -0
  105. package/dist/sqlEngineCapability.js +1 -8
  106. package/dist/steerPriorityCapability.d.ts +18 -0
  107. package/dist/steerPriorityCapability.js +80 -0
  108. package/dist/steerReceipt.d.ts +9 -0
  109. package/dist/steerReceipt.js +25 -0
  110. package/dist/subagent/engineSubagentSteer.js +2 -9
  111. package/dist/supportFloor.js +2 -2
  112. package/dist/toolResult.d.ts +8 -0
  113. package/dist/toolResult.js +47 -3
  114. package/dist/types/engineState.d.ts +2 -12
  115. package/dist/userInvokedSkillsCapability.d.ts +18 -0
  116. package/dist/userInvokedSkillsCapability.js +50 -0
  117. package/dist/wireFailureShape.d.ts +2 -0
  118. package/dist/wireFailureShape.js +4 -0
  119. package/dist/workflowsJournalCapability.d.ts +18 -0
  120. package/dist/workflowsJournalCapability.js +50 -0
  121. package/dist/writeProtectionCapability.d.ts +2 -4
  122. package/docs/INTEGRATION-CLIENTS.md +624 -12
  123. package/package.json +2 -2
@@ -8,7 +8,7 @@ import { projectDiagnosticsFrame } from '../diagnostics.js';
8
8
  import { recordEngineToolLabel } from '../engineToolLabelStore.js';
9
9
  import { registerSubagentAlias, registerSubagentContentAlias } from '../subagentContentStore.js';
10
10
  import { readAsyncLaunchedAgentReceipt } from '../toolResult.js';
11
- import { isWorkflowAgentTaskId, recordWorkflowAgentTaskId } from '../workflow.js';
11
+ import { recordWorkflowAgentTaskId } from '../workflow.js';
12
12
  import { isTerminalStatus } from '../runTerminal.js';
13
13
  import { readToolHistoryMismatchKey } from '../toolHistoryMismatch.js';
14
14
  import { readProviderRejectionResendKey } from '../providerRejection.js';
@@ -578,9 +578,7 @@ const taskProgressArm = function* (m, { ctx, cards, panel, inst }) {
578
578
  const explicitParentRaw = m.parentToolCallId;
579
579
  const explicitParent = typeof explicitParentRaw === 'string' ? explicitParentRaw : undefined;
580
580
  const workflowRunId = typeof m.workflowRunId === 'string' ? m.workflowRunId : undefined;
581
- if (workflowRunId !== undefined ||
582
- isWorkflowAgentTaskId(taskId) ||
583
- (explicitParent !== undefined && inst.isWorkflowCard(explicitParent))) {
581
+ if (workflowRunId !== undefined) {
584
582
  recordWorkflowAgentTaskId(taskId);
585
583
  if (workflowRunId !== undefined && explicitParent !== undefined && inst.isWorkflowCard(explicitParent))
586
584
  noteOwnWorkflowRun(workflowRunId);
@@ -588,19 +586,13 @@ const taskProgressArm = function* (m, { ctx, cards, panel, inst }) {
588
586
  t: ctx.now(),
589
587
  taskId,
590
588
  lane: 'workflow',
591
- via: workflowRunId !== undefined
592
- ? 'workflowRunId'
593
- : isWorkflowAgentTaskId(taskId)
594
- ? 'wa-id'
595
- : 'workflow-card-parent',
589
+ via: 'workflowRunId',
596
590
  }));
597
591
  return;
598
592
  }
599
593
  if (explicitParent !== undefined)
600
594
  registerSubagentAlias(explicitParent, taskId);
601
- const cardId = explicitParent === undefined && !panel.isBound(taskId) && panel.unboundCandidates() > 1
602
- ? undefined
603
- : panel.bind(taskId, explicitParent);
595
+ const cardId = panel.bind(taskId, explicitParent);
604
596
  const usage = (m.usage ?? {});
605
597
  ctx.probe?.('tick', JSON.stringify({
606
598
  t: ctx.now(),
@@ -3,9 +3,7 @@ import type { AdapterInstanceLedger } from './instanceLedger.js';
3
3
  import type { OpenCardView } from './toolCards.js';
4
4
  export interface PanelTaskLedger {
5
5
  bind(taskId: string, parentToolCallId?: string): string | undefined;
6
- unboundCandidates(): number;
7
6
  laneOf(taskId: string): LaneProof;
8
- isBound(taskId: string): boolean;
9
7
  isLiveBound(taskId: string): boolean;
10
8
  isLive(taskId: string): boolean;
11
9
  markLive(taskId: string): void;
@@ -21,44 +21,24 @@ export function createPanelTaskLedger(ctx, cards, inst) {
21
21
  };
22
22
  return {
23
23
  laneOf,
24
- isBound: (taskId) => taskCardBinding.has(taskId),
25
24
  isLiveBound: (taskId) => liveBoundPanelTasks.has(taskId),
26
25
  bind(taskId, parentToolCallId) {
27
26
  const existing = taskCardBinding.get(taskId);
28
27
  if (existing !== undefined)
29
28
  return existing;
30
- let target;
31
- if (parentToolCallId !== undefined) {
32
- const named = cards.peek(parentToolCallId);
33
- if (named !== undefined && !SUBAGENT_TOOL_NAMES.has(named.name))
34
- return undefined;
35
- target = parentToolCallId;
36
- }
37
- else {
38
- for (const [id, p] of cards.entries()) {
39
- if (!boundToolCalls.has(id) && SUBAGENT_TOOL_NAMES.has(p.name)) {
40
- target = id;
41
- break;
42
- }
43
- }
44
- }
45
- if (target === undefined)
29
+ if (parentToolCallId === undefined)
46
30
  return undefined;
31
+ const named = cards.peek(parentToolCallId);
32
+ if (named !== undefined && !SUBAGENT_TOOL_NAMES.has(named.name))
33
+ return undefined;
34
+ const target = parentToolCallId;
47
35
  taskCardBinding.set(taskId, target);
48
36
  boundToolCalls.add(target);
49
37
  if (cards.has(target))
50
38
  liveBoundPanelTasks.add(taskId);
51
- ctx.probe?.('bind', `bind ${taskId} -> ${target} via=${parentToolCallId !== undefined ? 'explicit' : 'fifo'}`);
39
+ ctx.probe?.('bind', `bind ${taskId} -> ${target} via=explicit`);
52
40
  return target;
53
41
  },
54
- unboundCandidates() {
55
- let n = 0;
56
- for (const [id, p] of cards.entries()) {
57
- if (!boundToolCalls.has(id) && SUBAGENT_TOOL_NAMES.has(p.name))
58
- n++;
59
- }
60
- return n;
61
- },
62
42
  isLive: (taskId) => livePanelTasks.has(taskId),
63
43
  markLive: (taskId) => {
64
44
  livePanelTasks.add(taskId);
package/dist/adapt.js CHANGED
@@ -107,10 +107,10 @@ export const ADAPTER_DIVERGENCES = [
107
107
  '(0.81.0–0.82.x 曾与 CC 内部转录面驼峰 `toolUseResult` 同引用并铸,0.83.0 删驼峰);cli 侧仍带驼峰 —— 所钉的本包' +
108
108
  '旧版本两键同铸,升级后在转录入口从 `tool_use_result` 同值起别名。守卫在两键同在场且同引用时略过驼峰键、' +
109
109
  '按 snake 比(两侧对称);cli 侧不再带驼峰后本条自然零触发 ⇒ 自退役。',
110
- 'DIVERGENCE-11(0.83.0,C-R103):system 转录行的到达时戳 —— 本包只给 user / assistant 行补 `timestamp`' +
110
+ 'DIVERGENCE-11(0.83.0):system 转录行的到达时戳 —— 本包只给 user / assistant 行补 `timestamp`' +
111
111
  '(agent-types 只在这两臂声明),system 行不补(入参自带的照旧原样过境);壳的接收口给每条转录行补到达时刻(只补缺席)。' +
112
112
  '守卫在逐字比对前只从壳侧 system 行上去掉这一位;本包侧 system 行若带 `timestamp`,照样判不等。',
113
- 'DIVERGENCE-12(0.83.0,C-R103):记忆写入 —— 本包发 chrome `memory_saved` 臂(`notes` = 笔记原文,`id` 由这次写入的 wire ' +
113
+ 'DIVERGENCE-12(0.83.0):记忆写入 —— 本包发 chrome `memory_saved` 臂(`notes` = 笔记原文,`id` 由这次写入的 wire ' +
114
114
  '稳定键派生),转录面零行;壳侧是一条 system/memory_saved 转录行(`writtenPaths` 装同一份笔记)。守卫把壳侧这类行移出逐字比对,' +
115
115
  '改比:事件 `notes` ⇔ 行 `writtenPaths` 逐项相等、位置相等(之前已覆盖转录行的条数);`id` 不与旧行 uuid 比(本版不承诺相等)。',
116
116
  ];
@@ -192,8 +192,6 @@ export interface SelfHealFollowDeclaration {
192
192
  }
193
193
  export declare function readCancelRequested(body: unknown): boolean | undefined;
194
194
  export declare function atMostOnceFailureClass(e: unknown): 'rejected' | 'unknown';
195
- export declare function readSteerDelivery(receipt: unknown): string | null;
196
- export declare function readSteerReceiptStatus(receipt: unknown): string | null;
197
195
  export declare function clearRunningChoiceOffer(taskId: string, sessionId?: string): void;
198
196
  export declare function __resetRunningChoiceLedgerForTests(): void;
199
197
  export interface ClaimReleaseVerdict {
@@ -1,6 +1,7 @@
1
1
  import { abortableSleep } from '../abortableSleep.js';
2
2
  import { corruptStoredRowContent, corruptStoredRowWhere, effectiveWireErrorCode } from '../wireErrorTriage.js';
3
- import { steeringRefusedBeforeEngine, steeringStatusIs4xx } from '../controlRouter.js';
3
+ import { steerBodyOf, steeringRefusedBeforeEngine, steeringStatusIs4xx, UNOBSERVED_STEER_PRIORITY } from '../controlRouter.js';
4
+ import { readSteerReceipt } from '../steerReceipt.js';
4
5
  export const PLAN_REVIEW_GATE_KIND = 'plan_review';
5
6
  export const PLAN_REVIEW_GATE_KINDS = Object.freeze([PLAN_REVIEW_GATE_KIND, 'dry_run_review']);
6
7
  export const ASK_PARK_GATE_KINDS = Object.freeze(['human', 'irreversible_ask', 'policy_ask', 'tool_approval']);
@@ -265,28 +266,6 @@ export function atMostOnceFailureClass(e) {
265
266
  return 'rejected';
266
267
  return typeof e === 'object' && e !== null && steeringRefusedBeforeEngine(e) !== undefined ? 'rejected' : 'unknown';
267
268
  }
268
- export function readSteerDelivery(receipt) {
269
- try {
270
- if (typeof receipt !== 'object' || receipt === null || !('delivery' in receipt))
271
- return null;
272
- const d = receipt.delivery;
273
- return typeof d === 'string' && d.length > 0 ? d : null;
274
- }
275
- catch {
276
- return null;
277
- }
278
- }
279
- export function readSteerReceiptStatus(receipt) {
280
- try {
281
- if (typeof receipt !== 'object' || receipt === null || !('status' in receipt))
282
- return null;
283
- const s = receipt.status;
284
- return typeof s === 'string' && s.length > 0 ? s : null;
285
- }
286
- catch {
287
- return null;
288
- }
289
- }
290
269
  const CANCEL_RELEASE_WAIT_MS = 10_000;
291
270
  const RUNNING_LIVENESS_RECHECK_TIMEOUT_MS = 4_000;
292
271
  const runningChoiceDeclined = new Set();
@@ -772,9 +751,8 @@ async function runningChoiceArm(taskId, status, busy, statusFromWire, runs, deps
772
751
  }
773
752
  if (choice === 'steer' && canSteer && runs?.steer !== undefined) {
774
753
  try {
775
- const receipt = await runs.steer(taskId, { text }, sessionOpts(deps));
776
- const delivery = readSteerDelivery(receipt);
777
- const receiptStatus = readSteerReceiptStatus(receipt);
754
+ const receipt = await runs.steer(taskId, steerBodyOf({ text }, UNOBSERVED_STEER_PRIORITY), sessionOpts(deps));
755
+ const { delivery, status: receiptStatus } = readSteerReceipt(receipt);
778
756
  if (delivery === 'queued') {
779
757
  const verdict = receiptStatus !== null && PLAN_REVIEW_STATES.includes(receiptStatus)
780
758
  ? await planVerdict(taskId, deps)
@@ -1071,7 +1049,7 @@ function activeRunSelfHealBaseRow(outcome, signal, wayOut, following = false, ke
1071
1049
  }
1072
1050
  case 'running-steer-failed':
1073
1051
  if (outcome.delivery === 'rejected') {
1074
- return (`The engine rejected handing your message to the running run (run ${outcome.taskId}): ${outcome.detail}. ` +
1052
+ return (`Handing your message to the running run (run ${outcome.taskId}) was refused: ${outcome.detail}. ` +
1075
1053
  `sema did NOT retry it (a steer is not safe to send twice) and it did NOT cancel that run. ` +
1076
1054
  `Your message was NOT sent; send it again if you still want it.`);
1077
1055
  }
@@ -7,8 +7,15 @@ import { isReviewPark, readRunTerminal, runTerminalCode, runTerminalGateToolName
7
7
  import { toCcModelUsage } from './turnUsageToModelUsage.js';
8
8
  import { LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, OUTPUT_INVALID, isCorruptSessionCode, isRewindFamilyCode, } from '../../engineErrorCodes.js';
9
9
  import { corruptSessionContent } from '../../corruptSessionCopy.js';
10
- function withSessionUnreadableNote(text, code) {
11
- return isCorruptSessionCode(code) ? `${text}\n${corruptSessionContent()}` : text;
10
+ import { abortCauseNoteOf, readAbortCause } from '../../runCancelContext.js';
11
+ function withTerminalNote(text, code, frame) {
12
+ const withCorrupt = isCorruptSessionCode(code) ? `${text}\n${corruptSessionContent()}` : text;
13
+ const abortNote = abortCauseNoteOf(frame);
14
+ return abortNote === undefined ? withCorrupt : `${withCorrupt}\n${abortNote}`;
15
+ }
16
+ function abortCauseWordOf(frame) {
17
+ const r = readAbortCause(frame);
18
+ return r === undefined ? undefined : r.kind === 'known' ? r.cause : r.word;
12
19
  }
13
20
  function finiteOr0(v) {
14
21
  return typeof v === 'number' && Number.isFinite(v) ? v : 0;
@@ -500,6 +507,7 @@ function errorResult(ctx, parts) {
500
507
  ...(parts.salvagedResult !== undefined ? { _sema_salvaged_result: parts.salvagedResult } : {}),
501
508
  ...(parts.outcomeUnknown === true ? { _sema_outcome: 'unknown' } : {}),
502
509
  ...(parts.parkFailedReason !== undefined ? { _sema_park_failed_reason: washCredentials(parts.parkFailedReason) } : {}),
510
+ ...(parts.abortCause !== undefined ? { _sema_abort_cause: parts.abortCause } : {}),
503
511
  });
504
512
  }
505
513
  export function doneToSdkResult(ev, ctx, observed) {
@@ -516,7 +524,7 @@ export function doneToSdkResult(ev, ctx, observed) {
516
524
  const degraded = degradedOf(r);
517
525
  const parkFailedRaw = ev._sema_park_failed_reason;
518
526
  const parkFailedReason = typeof parkFailedRaw === 'string' && parkFailedRaw.length > 0 ? parkFailedRaw : undefined;
519
- const errorBase = { durationMs, stats, model: r.model, errorCode, degraded, observed, facts: effectiveFactParts(rec), parkFailedReason };
527
+ const errorBase = { durationMs, stats, model: r.model, errorCode, degraded, observed, facts: effectiveFactParts(rec), parkFailedReason, abortCause: abortCauseWordOf(ev) };
520
528
  if (terminal?.kind === 'failed') {
521
529
  const failedCode = terminal.code;
522
530
  const failedMessage = terminal.message;
@@ -534,9 +542,9 @@ export function doneToSdkResult(ev, ctx, observed) {
534
542
  ...errorBase,
535
543
  subtype: failedSubtype,
536
544
  errors: [
537
- withSessionUnreadableNote(isRewindFamilyCode(failedCode) && failedMessage
545
+ withTerminalNote(isRewindFamilyCode(failedCode) && failedMessage
538
546
  ? `${failedMessage} (${failedCode})`
539
- : (failedMessage ?? 'run failed'), failedCode),
547
+ : (failedMessage ?? 'run failed'), failedCode, ev),
540
548
  ],
541
549
  });
542
550
  }
@@ -625,10 +633,11 @@ export function failedToSdkResult(ev, ctx, observed) {
625
633
  observed,
626
634
  durationMs: elapsedMs(ctx),
627
635
  errorCode: ev.errorCode,
636
+ abortCause: abortCauseWordOf(ev),
628
637
  errors: [
629
- withSessionUnreadableNote(isRewindFamilyCode(ev.errorCode) && ev.errorMessage
638
+ withTerminalNote(isRewindFamilyCode(ev.errorCode) && ev.errorMessage
630
639
  ? `${ev.errorMessage} (${ev.errorCode})`
631
- : (ev.errorMessage ?? ev.errorCode ?? 'run failed'), ev.errorCode),
640
+ : (ev.errorMessage ?? ev.errorCode ?? 'run failed'), ev.errorCode, ev),
632
641
  ],
633
642
  });
634
643
  }
@@ -5,6 +5,7 @@ import { readRunCostFacts, terminalToSdkResult, TOOL_INPUT_JOIN_MAX_CALLS } from
5
5
  import { coerceOutput, publishSubagentContentEvent } from '../subagentContentStore.js';
6
6
  import { ACTIVE_RUN_BUSY_ERROR_CODE, OUTPUT_INVALID, isCorruptSessionCode, isLimitsExceededCode } from '../engineErrorCodes.js';
7
7
  import { corruptSessionContent } from '../corruptSessionCopy.js';
8
+ import { abortCauseNoteOf } from '../runCancelContext.js';
8
9
  import { classifyToolHistoryMismatch, noteToolHistoryTerminal, openToolHistoryGeneration, TOOL_HISTORY_REWIND_SENTENCE, toolHistoryMismatchRowKey, toolHistoryRepeatSentence, toolHistoryRewindOffered, } from '../toolHistoryMismatch.js';
9
10
  import { isReviewPark, readRunTerminal, runTerminalCode } from '../runTerminal.js';
10
11
  import { providerRejectionResend } from '../providerRejection.js';
@@ -660,6 +661,7 @@ async function* runStreamInner(events, ctx, handle = {}) {
660
661
  const sessionUnreadable = ev.type === 'failed'
661
662
  ? isCorruptSessionCode(ev.errorCode)
662
663
  : doneTerminal?.kind === 'failed' && isCorruptSessionCode(doneTerminal.code);
664
+ const abortNote = abortCauseNoteOf(ev);
663
665
  const historyTerminal = apiErrorTerminalOfRowFrame(ev, rowFacts);
664
666
  const historyMismatch = classifyToolHistoryMismatch(historyTerminal.carrier);
665
667
  const historyEchoedSid = ev.type === 'done' ? engineSessionIdOf(ev.result) : undefined;
@@ -677,7 +679,7 @@ async function* runStreamInner(events, ctx, handle = {}) {
677
679
  : '';
678
680
  const resend = historyTerminal.detail !== undefined ? providerRejectionResend(historyTerminal.detail, historyTerminal.carrier) : undefined;
679
681
  const resendLine = resend !== undefined ? `\n${resend.text}` : '';
680
- yield syntheticTerminalRow(ctx, `${sessionUnreadable ? `${rowText}\n${corruptSessionContent()}` : rowText}${rewindLine}${resendLine}`, historyMismatch === null ? undefined : toolHistoryMismatchRowKey(historyMismatch, historyRepeat, rewindOffered), resend);
682
+ yield syntheticTerminalRow(ctx, `${sessionUnreadable ? `${rowText}\n${corruptSessionContent()}` : rowText}${abortNote !== undefined ? `\n${abortNote}` : ''}${rewindLine}${resendLine}`, historyMismatch === null ? undefined : toolHistoryMismatchRowKey(historyMismatch, historyRepeat, rewindOffered), resend);
681
683
  }
682
684
  else {
683
685
  const echoedSid = ev.type === 'done' ? engineSessionIdOf(ev.result) : undefined;
@@ -1,10 +1,13 @@
1
- export declare const MODE_ARBITRATION: Readonly<Record<"hook" | "write_protection" | "mode" | "rule_unreadable" | "content_question" | "ancestor" | "unverifiable_delete" | "transcript_write" | "org_rule" | "governance_unavailable" | "ask_rule" | "denial_limit_fallback" | "operator_forced" | "shell_floor" | "write_protection_unresolved" | "probe" | "tool_marks_mcp" | "tool_marks_a2a" | "policy_rra" | "artifact_shared_read" | "unstated" | "ordinary", import("./generated/engineFactTables.js").CoreModeArbitrationRow>>;
1
+ import { type AutomaticAnswerRoad, type AutomaticAnswerUnknownWhy } from './hitl/automaticAnswerVerdict.js';
2
+ export declare const MODE_ARBITRATION: Readonly<Record<"hook" | "write_protection" | "mode" | "rule_unreadable" | "content_question" | "ancestor" | "unverifiable_delete" | "transcript_write" | "org_rule" | "governance_unavailable" | "ask_rule" | "denial_limit_fallback" | "requires_user_interaction" | "operator_forced" | "shell_floor" | "write_protection_unresolved" | "probe" | "tool_marks_mcp" | "tool_marks_a2a" | "policy_rra" | "artifact_shared_read" | "unstated" | "ordinary", import("./generated/engineFactTables.js").CoreModeArbitrationRow>>;
2
3
  export type StandingAnswerVerdict = {
3
4
  readonly kind: 'must_ask';
4
5
  readonly by: string;
6
+ readonly road?: AutomaticAnswerRoad;
5
7
  } | {
6
8
  readonly kind: 'may_answer';
7
9
  } | {
8
10
  readonly kind: 'unknown';
11
+ readonly why?: AutomaticAnswerUnknownWhy;
9
12
  };
10
13
  export declare function askSurvivesStandingAnswer(card: object | null | undefined): StandingAnswerVerdict;
@@ -1,9 +1,22 @@
1
1
  import { CORE_MODE_ARBITRATION } from './generated/engineFactTables.js';
2
+ import { automaticAnswerVerdict } from './hitl/automaticAnswerVerdict.js';
2
3
  export const MODE_ARBITRATION = CORE_MODE_ARBITRATION;
3
4
  const MUST_ASK_MANDATED = Object.freeze({ kind: 'must_ask', by: 'mandated' });
4
5
  const MAY_ANSWER = Object.freeze({ kind: 'may_answer' });
5
6
  const UNKNOWN = Object.freeze({ kind: 'unknown' });
6
7
  export function askSurvivesStandingAnswer(card) {
8
+ const old = legacyStandingAnswerVerdict(card);
9
+ const neu = automaticAnswerVerdict(card, 'standing_rule');
10
+ if (old.kind === 'must_ask' || neu.kind === 'must_ask') {
11
+ const by = old.kind === 'must_ask' ? old.by : neu.kind === 'must_ask' ? (neu.askClass ?? neu.road) : 'mandated';
12
+ const road = neu.kind === 'must_ask' ? neu.road : by === 'mandated' ? 'mandated' : 'ask_class';
13
+ return Object.freeze({ kind: 'must_ask', by, road });
14
+ }
15
+ if (old.kind === 'unknown' || neu.kind === 'unknown')
16
+ return neu.kind === 'unknown' ? Object.freeze({ kind: 'unknown', why: neu.why }) : UNKNOWN;
17
+ return MAY_ANSWER;
18
+ }
19
+ function legacyStandingAnswerVerdict(card) {
7
20
  try {
8
21
  if (card === null || card === undefined || typeof card !== 'object')
9
22
  return UNKNOWN;
@@ -1,4 +1,5 @@
1
- export const CLASSIFIER_DENY_CAUSES = Object.freeze(['unavailable', 'parse_error']);
1
+ import { CORE_AUTO_MODE_UNAVAILABLE_CAUSES, CORE_CLASSIFIER_DENY_CAUSES } from './generated/engineFactTables.js';
2
+ export const CLASSIFIER_DENY_CAUSES = CORE_CLASSIFIER_DENY_CAUSES;
2
3
  const DENY_CAUSE_SET = new Set(CLASSIFIER_DENY_CAUSES);
3
4
  export function isClassifierDenyCause(v) {
4
5
  return typeof v === 'string' && DENY_CAUSE_SET.has(v);
@@ -26,7 +27,7 @@ function gateRecordOf(v) {
26
27
  return undefined;
27
28
  return g;
28
29
  }
29
- export const AUTO_MODE_UNAVAILABLE_CAUSES = Object.freeze(['error', 'timeout']);
30
+ export const AUTO_MODE_UNAVAILABLE_CAUSES = CORE_AUTO_MODE_UNAVAILABLE_CAUSES;
30
31
  const DENY_CAUSE_SENTENCES = Object.freeze({
31
32
  unavailable: 'denied because the auto-mode classifier could not run this round (the call may be retried later)',
32
33
  parse_error: 'denied because the auto-mode classifier answered outside its contract (its reply could not be parsed, so the call was blocked)',
@@ -1,6 +1,7 @@
1
1
  import { MCP_CAPS } from './mcpWireCaps.js';
2
2
  import { toCappedSpec } from './skillsWireCaps.js';
3
3
  import { TIER_ORDER } from './model/tierVocabulary.js';
4
+ import { SETTINGS_BUDGET_NUMBER_KEYS, SETTINGS_BUDGET_PER_MODEL_NUMBER_KEYS, SETTINGS_BUDGET_STRING_KEYS, SETTINGS_TIER_GROUP_NAME_RE, } from './generated/settingsSchemaTables.js';
4
5
  const asRec = (v) => (typeof v === 'object' && v !== null && !Array.isArray(v) ? v : undefined);
5
6
  const asArr = (v) => (Array.isArray(v) ? v : []);
6
7
  const asStr = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
@@ -129,7 +130,7 @@ function withoutRegistryAnnotations(e) {
129
130
  return out;
130
131
  }
131
132
  const TIER_WORDS = TIER_ORDER;
132
- const TIER_GROUP_NAME = /^[a-z0-9][a-z0-9._-]*$/i;
133
+ const TIER_GROUP_NAME = SETTINGS_TIER_GROUP_NAME_RE;
133
134
  const setOwn = (o, k, v) => {
134
135
  Object.defineProperty(o, k, { value: v, enumerable: true, writable: true, configurable: true });
135
136
  };
@@ -319,9 +320,9 @@ export function cloudRosterNames(rostersValue) {
319
320
  .map((e) => asStr(asRec(e)?.name))
320
321
  .filter((n) => !!n);
321
322
  }
322
- const BUDGET_NUMBER_KEYS = ['maxBudgetUsd', 'tpmLimit', 'rpmLimit', 'maxParallelRequests', 'maxRunCostUsd', 'maxIterations'];
323
- const BUDGET_STRING_KEYS = ['mode', 'budgetDuration', 'enforcement'];
324
- const PER_MODEL_NUMBER_KEYS = ['maxBudgetUsd', 'tpmLimit', 'rpmLimit'];
323
+ const BUDGET_NUMBER_KEYS = SETTINGS_BUDGET_NUMBER_KEYS;
324
+ const BUDGET_STRING_KEYS = SETTINGS_BUDGET_STRING_KEYS;
325
+ const PER_MODEL_NUMBER_KEYS = SETTINGS_BUDGET_PER_MODEL_NUMBER_KEYS;
325
326
  const _budgetKeysCovered = true;
326
327
  const _budgetKeysReal = true;
327
328
  const _perModelKeysCovered = true;
@@ -2,12 +2,12 @@ import { CHROME_ARMS } from './seam.js';
2
2
  export const MIGRATED_COMPENSATIONS = [
3
3
  {
4
4
  id: 'T32',
5
- what: 'bindTaskCard —— 把引擎子代行绑到它的委派工具卡上(显式父 / FIFO 猜父 / 含糊即 unbound)',
5
+ what: 'bindTaskCard —— 子代行按 typed 父键绑到委派工具卡上(点名的卡不合格 / 父键缺席即 unbound)',
6
6
  disposition: 'in-library',
7
7
  libraryHalf: 'adapt.ts bindTaskCard()',
8
8
  chromeArm: null,
9
9
  hostHalf: null,
10
- retireOn: 'RL-31',
10
+ retireOn: null,
11
11
  },
12
12
  {
13
13
  id: 'T34',
@@ -47,12 +47,12 @@ export const MIGRATED_COMPENSATIONS = [
47
47
  },
48
48
  {
49
49
  id: 'T47',
50
- what: 'workflow lane 三级判据门 —— workflow 子代的 tick 绝不进前台 subagent lane',
50
+ what: 'workflow lane 判据门(帧带 workflowRunId)—— workflow 子代的 tick 绝不进前台 subagent lane',
51
51
  disposition: 'in-library',
52
- libraryHalf: 'adapt.ts task_progress 臂的 workflowRunId / wa-id / workflow-card-parent 三级门',
52
+ libraryHalf: 'adapt.ts task_progress 臂的 workflowRunId 门',
53
53
  chromeArm: null,
54
54
  hostHalf: null,
55
- retireOn: 'RL-34',
55
+ retireOn: null,
56
56
  },
57
57
  {
58
58
  id: 'T48',
@@ -1,13 +1,11 @@
1
- import type { TaskRequest, RunReceipt, CancelAck, Scenario } from '@sema-agent/sdk';
1
+ import type { TaskRequest, RunReceipt, CancelAck, Scenario, SteerPriority } from '@sema-agent/sdk';
2
+ import { type SteerPriorityReading } from './steerPriorityCapability.js';
2
3
  export interface RunsResourceLike {
3
4
  create(req: TaskRequest, opts?: {
4
5
  idempotencyKey?: string | null;
5
6
  signal?: AbortSignal;
6
7
  }): Promise<RunReceipt>;
7
- steer(taskId: string, steer: {
8
- text: string;
9
- mode?: 'all' | 'one-at-a-time';
10
- }, opts?: {
8
+ steer(taskId: string, steer: SteerBodyInput, opts?: {
11
9
  signal?: AbortSignal;
12
10
  }): Promise<unknown>;
13
11
  cancel(taskId: string, opts?: {
@@ -17,7 +15,7 @@ export interface RunsResourceLike {
17
15
  export interface ControlClientLike {
18
16
  runs: RunsResourceLike;
19
17
  }
20
- export type ControlSafetyCode = 'not_running' | 'invalid_content' | 'queue_full' | 'duplicate_input_id' | 'ambiguous_target' | 'still_running' | 'blocked_by_hook' | 'ledger_unavailable' | 'steering_other' | 'cancel_lost_race' | 'cancel_run_not_running' | 'not_found';
18
+ export type ControlSafetyCode = 'not_running' | 'invalid_content' | 'queue_full' | 'duplicate_input_id' | 'ambiguous_target' | 'still_running' | 'blocked_by_hook' | 'ledger_unavailable' | 'steering_other' | 'cancel_lost_race' | 'cancel_run_not_running' | 'not_found' | 'priority_not_applied' | 'steer_input_invalid';
21
19
  export declare class ControlSafetyError extends Error {
22
20
  readonly code: ControlSafetyCode;
23
21
  readonly cause?: unknown | undefined;
@@ -28,11 +26,10 @@ export declare class ControlSafetyError extends Error {
28
26
  readonly status?: number;
29
27
  });
30
28
  }
31
- export type QueuePriority = 'now' | 'next' | 'later';
32
- export interface QueuedCommand {
33
- id: string;
34
- text: string;
35
- priority: QueuePriority;
29
+ export interface ControlRouterSteerOptions {
30
+ signal?: AbortSignal;
31
+ priority?: SteerPriority;
32
+ steerPriority?: SteerPriorityReading;
36
33
  }
37
34
  export interface ControlRouterOptions {
38
35
  sessionId?: string;
@@ -47,8 +44,6 @@ export declare class ControlRouter {
47
44
  private readonly jobId;
48
45
  private readonly scenario;
49
46
  private readonly systemPrompt;
50
- private readonly queue;
51
- private seq;
52
47
  constructor(client: ControlClientLike, opts?: ControlRouterOptions);
53
48
  activeTaskId(): string | null;
54
49
  activeSessionId(): string | undefined;
@@ -56,19 +51,10 @@ export declare class ControlRouter {
56
51
  signal?: AbortSignal;
57
52
  }): Promise<RunReceipt>;
58
53
  private buildTaskRequest;
59
- steer(text: string, mode?: 'all' | 'one-at-a-time', opts?: {
60
- signal?: AbortSignal;
61
- }): Promise<unknown>;
54
+ steer(text: string, mode?: 'all' | 'one-at-a-time', opts?: ControlRouterSteerOptions): Promise<unknown>;
62
55
  cancel(opts?: {
63
56
  signal?: AbortSignal;
64
57
  }): Promise<CancelAck>;
65
- enqueue(text: string, priority?: QueuePriority): QueuedCommand;
66
- dequeue(id: string): boolean;
67
- pending(): readonly QueuedCommand[];
68
- drainNext(opts?: {
69
- signal?: AbortSignal;
70
- }): Promise<RunReceipt | null>;
71
- private nextId;
72
58
  }
73
59
  export interface ErrCodes {
74
60
  code?: string | undefined;
@@ -80,7 +66,21 @@ export declare function steeringStatusIs4xx(e: object): boolean;
80
66
  export interface SteerRefusalAdvice {
81
67
  safety: ControlSafetyCode;
82
68
  advice: string;
69
+ happened: string;
70
+ nextStep: string;
83
71
  }
84
72
  export type SteeringRefusedBeforeEngine = SteerRefusalAdvice;
85
73
  export declare function steeringRefusedBeforeEngine(e: object): SteeringRefusedBeforeEngine | undefined;
86
74
  export declare function steerRefusalAdviceOf(e: object): SteerRefusalAdvice | undefined;
75
+ export interface SteerBody {
76
+ readonly text: string;
77
+ readonly mode?: 'all' | 'one-at-a-time';
78
+ readonly priority?: 'now' | 'later';
79
+ }
80
+ export interface SteerBodyInput {
81
+ text: string;
82
+ mode?: 'all' | 'one-at-a-time';
83
+ priority?: SteerPriority;
84
+ }
85
+ export declare const UNOBSERVED_STEER_PRIORITY: SteerPriorityReading;
86
+ export declare function steerBodyOf(input: SteerBodyInput, reading: SteerPriorityReading): SteerBody;