@sema-agent/client-core 0.96.0 → 0.97.1

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 (145) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/README.md +29 -22
  3. package/dist/adapter/activeRunSelfHeal.d.ts +0 -2
  4. package/dist/adapter/activeRunSelfHeal.js +7 -7
  5. package/dist/adapter/downstream/terminalToSdkResult.js +6 -2
  6. package/dist/agentSession/backgroundView.js +2 -15
  7. package/dist/agentsWireCaps.d.ts +3 -1
  8. package/dist/agentsWireCaps.js +67 -39
  9. package/dist/approvalDecidedByCapability.d.ts +2 -0
  10. package/dist/approvalDecidedByCapability.js +0 -1
  11. package/dist/approvalsStreamLiveCapability.d.ts +2 -0
  12. package/dist/approvalsStreamLiveCapability.js +3 -2
  13. package/dist/attachmentSeatCapability.d.ts +2 -0
  14. package/dist/attachmentSeatCapability.js +0 -1
  15. package/dist/callerCwdCapability.d.ts +2 -0
  16. package/dist/callerCwdCapability.js +0 -1
  17. package/dist/centerWiringCapability.d.ts +2 -0
  18. package/dist/centerWiringCapability.js +4 -3
  19. package/dist/cloudConfigWireCaps.d.ts +2 -2
  20. package/dist/cloudConfigWireCaps.js +192 -56
  21. package/dist/declared/supportFloorDeclared.js +3 -3
  22. package/dist/deviceExecutorManagementCapability.d.ts +2 -0
  23. package/dist/deviceExecutorManagementCapability.js +3 -2
  24. package/dist/displayUntrusted.d.ts +3 -0
  25. package/dist/displayUntrusted.js +15 -0
  26. package/dist/engineCapReader.d.ts +8 -2
  27. package/dist/engineCapReader.js +15 -7
  28. package/dist/engineCapsCache.d.ts +11 -3
  29. package/dist/engineCapsCache.js +54 -23
  30. package/dist/engineErrorCodes.d.ts +3 -0
  31. package/dist/engineErrorCodes.js +9 -1
  32. package/dist/engineNoticeCodes.js +2 -3
  33. package/dist/engineToolDirectory.d.ts +27 -0
  34. package/dist/engineToolDirectory.js +178 -0
  35. package/dist/executionLaneCapability.d.ts +2 -0
  36. package/dist/executionLaneCapability.js +3 -2
  37. package/dist/fileHistoryCaptureCapability.d.ts +2 -0
  38. package/dist/fileHistoryCaptureCapability.js +34 -8
  39. package/dist/fileHistoryLegNotice.js +4 -0
  40. package/dist/fleet/fleetLedger.js +129 -105
  41. package/dist/gateOutcome.js +2 -4
  42. package/dist/gateVocabulary.d.ts +1 -6
  43. package/dist/gateVocabulary.js +2 -5
  44. package/dist/generated/sdkFactTables.d.ts +2 -0
  45. package/dist/generated/sdkFactTables.js +7 -0
  46. package/dist/generated/toolNameTables.d.ts +0 -1
  47. package/dist/generated/toolNameTables.js +0 -42
  48. package/dist/hitl/approvalDecisionNoteAudit.js +2 -2
  49. package/dist/hitl/approvalEndingCause.js +2 -7
  50. package/dist/hitl/approvalHolds.d.ts +16 -1
  51. package/dist/hitl/approvalHolds.js +52 -12
  52. package/dist/hitl/askGateWire.js +1 -0
  53. package/dist/hitl/automaticAnswerVerdict.js +5 -7
  54. package/dist/hitl/decisionConflict.js +4 -3
  55. package/dist/hitl/decisionRefusal.js +19 -12
  56. package/dist/hitl/frameRouter.d.ts +3 -0
  57. package/dist/hitl/frameRouter.js +52 -25
  58. package/dist/hitl/gateLedger.d.ts +0 -5
  59. package/dist/hitl/gateLedger.js +0 -21
  60. package/dist/hitl/hitlBridge.js +18 -4
  61. package/dist/hitl/parkResolver.js +7 -3
  62. package/dist/hitl/replayedApproval.d.ts +2 -3
  63. package/dist/hitl/replayedApproval.js +7 -16
  64. package/dist/hitl/sessionPolicyDeliverable.d.ts +0 -1
  65. package/dist/hitl/sessionPolicyDeliverable.js +15 -17
  66. package/dist/hitl/sessionPolicyWire.d.ts +2 -0
  67. package/dist/hitl/sessionPolicyWire.js +15 -3
  68. package/dist/hitl/standingRows.d.ts +1 -0
  69. package/dist/hitl/standingRows.js +38 -17
  70. package/dist/hitl/suspendedReopen.js +2 -1
  71. package/dist/hitl/toolApprovalWire.d.ts +8 -8
  72. package/dist/hitl/toolApprovalWire.js +50 -24
  73. package/dist/index.d.ts +8 -4
  74. package/dist/index.js +5 -3
  75. package/dist/liveModelCatalog.d.ts +13 -0
  76. package/dist/liveModelCatalog.js +56 -0
  77. package/dist/mcpProbeCapability.d.ts +2 -0
  78. package/dist/mcpProbeCapability.js +3 -2
  79. package/dist/mcpWireCaps.d.ts +1 -0
  80. package/dist/mcpWireCaps.js +4 -1
  81. package/dist/memoryComplianceCapability.d.ts +2 -0
  82. package/dist/memoryComplianceCapability.js +3 -2
  83. package/dist/memoryOriginCapability.d.ts +2 -0
  84. package/dist/memoryOriginCapability.js +3 -2
  85. package/dist/modelIdentityResolvability.js +2 -2
  86. package/dist/noticePresentation.js +2 -2
  87. package/dist/outputStyleSeatCapability.d.ts +2 -0
  88. package/dist/outputStyleSeatCapability.js +0 -1
  89. package/dist/peerLaneCapability.d.ts +2 -0
  90. package/dist/peerLaneCapability.js +3 -2
  91. package/dist/permissionModesCapability.d.ts +2 -0
  92. package/dist/permissionModesCapability.js +0 -1
  93. package/dist/permissionRulesWriteCapability.d.ts +2 -0
  94. package/dist/permissionRulesWriteCapability.js +3 -2
  95. package/dist/permissionsAllowGrantCapability.d.ts +2 -0
  96. package/dist/permissionsAllowGrantCapability.js +4 -2
  97. package/dist/permissionsDeclaration.js +19 -21
  98. package/dist/request/taskRequest.d.ts +1 -4
  99. package/dist/request/taskRequest.js +74 -19
  100. package/dist/resumeRefusalCopy.js +4 -4
  101. package/dist/rewindArchiveCapability.js +5 -0
  102. package/dist/rewindArchiveReading.d.ts +2 -0
  103. package/dist/rewindArchiveReading.js +0 -1
  104. package/dist/runTerminal.d.ts +33 -4
  105. package/dist/runTerminal.js +170 -15
  106. package/dist/sdkWireTransit.d.ts +2 -1
  107. package/dist/sdkWireTransit.js +1 -0
  108. package/dist/sealedKeyCapability.d.ts +2 -0
  109. package/dist/sealedKeyCapability.js +0 -1
  110. package/dist/seatContract.d.ts +7 -4
  111. package/dist/seatContract.js +34 -20
  112. package/dist/sessionPolicyCapability.d.ts +2 -0
  113. package/dist/sessionPolicyCapability.js +3 -2
  114. package/dist/sessionReadRedactionCapability.d.ts +2 -0
  115. package/dist/sessionReadRedactionCapability.js +0 -1
  116. package/dist/sessionSyncFileHistoryCapability.d.ts +2 -0
  117. package/dist/sessionSyncFileHistoryCapability.js +3 -2
  118. package/dist/skillToolListsCapability.d.ts +2 -0
  119. package/dist/skillToolListsCapability.js +3 -2
  120. package/dist/sqlEngineCapability.d.ts +2 -0
  121. package/dist/sqlEngineCapability.js +4 -3
  122. package/dist/steerPriorityCapability.d.ts +2 -0
  123. package/dist/steerPriorityCapability.js +3 -2
  124. package/dist/storePostureCapability.d.ts +2 -0
  125. package/dist/storePostureCapability.js +4 -3
  126. package/dist/toolHistoryBadTurn.js +3 -2
  127. package/dist/toolResult.d.ts +11 -0
  128. package/dist/toolResult.js +53 -0
  129. package/dist/userInvokedSkillsCapability.d.ts +2 -0
  130. package/dist/userInvokedSkillsCapability.js +3 -2
  131. package/dist/webSearchBackendCapability.d.ts +2 -0
  132. package/dist/webSearchBackendCapability.js +3 -2
  133. package/dist/wireErrorTriage.js +58 -34
  134. package/dist/wireFailureShape.d.ts +1 -1
  135. package/dist/wireFailureShape.js +76 -25
  136. package/dist/workflowsJournalCapability.d.ts +2 -0
  137. package/dist/workflowsJournalCapability.js +3 -2
  138. package/dist/writeProtectionCapability.d.ts +2 -0
  139. package/dist/writeProtectionCapability.js +3 -2
  140. package/docs/INTEGRATION-CLIENTS.md +585 -14
  141. package/package.json +4 -4
  142. package/dist/engineRefusedToolName.d.ts +0 -1
  143. package/dist/engineRefusedToolName.js +0 -8
  144. package/dist/engineWordRenames.d.ts +0 -8
  145. package/dist/engineWordRenames.js +0 -13
@@ -1,6 +1,6 @@
1
1
  import { wireFailureShapeOf } from '../wireFailureShape.js';
2
2
  import { hostLog } from '../host.js';
3
- import { isEngineRefusedToolName } from './sessionPolicyDeliverable.js';
3
+ import { ruleToolNameVerdictOf } from '../protocolSegment.js';
4
4
  import { RULES_LEGACY_TOOL_NAME_WRITE_NOTE } from './refusedToolNameProse.js';
5
5
  import { RULES_LEGACY_TOOL_NAME, isRulesRefusalCode } from '../engineErrorCodes.js';
6
6
  import { rosterMountedNames } from '../rosterMountedNames.js';
@@ -434,7 +434,14 @@ function withoutRefusedEntries(prior, mounted) {
434
434
  const kept = [];
435
435
  const seen = new Set();
436
436
  for (const x of list) {
437
- if (!isEngineRefusedToolName(x) || mounted.has(x)) {
437
+ if (mounted.has(x)) {
438
+ kept.push(x);
439
+ continue;
440
+ }
441
+ const kind = ruleToolNameVerdictOf(x).kind;
442
+ if (kind === 'unknown')
443
+ return 'judge_failed';
444
+ if (kind === 'current') {
438
445
  kept.push(x);
439
446
  continue;
440
447
  }
@@ -479,7 +486,10 @@ async function attemptRemoval(facade, sessionId, mounted, opts) {
479
486
  return { done: removalFailed(read.failure, 'read') };
480
487
  if (read.kind === 'malformed')
481
488
  return { done: { kind: 'read_failed', why: 'read_unreadable', message: read.detail } };
482
- const { next, removed } = withoutRefusedEntries(read.rules, mounted);
489
+ const judged = withoutRefusedEntries(read.rules, mounted);
490
+ if (judged === 'judge_failed')
491
+ return { done: { kind: 'judge_failed' } };
492
+ const { next, removed } = judged;
483
493
  if (removed.length === 0)
484
494
  return { done: { kind: 'nothing_to_remove', rev: read.rev } };
485
495
  let receipt;
@@ -563,6 +573,8 @@ export function sessionPolicyRemovalNotice(outcome) {
563
573
  }
564
574
  case 'nothing_to_remove':
565
575
  return 'This session’s rule record holds no entry naming a tool the engine refuses that the supplied roster does not mount, so nothing was changed. If runs still fail at startup over a refused tool name, that entry is set somewhere this record does not cover — the settings sent with the run, a parent session’s rule record, or the deployment’s own tool rules — or it is a name the engine refuses that this version does not yet recognise, or the failing run does not mount a tool the supplied roster has under that name.';
576
+ case 'judge_failed':
577
+ return 'Nothing was changed: this client could not check which entries in this session’s rule record name a tool the engine refuses (its copy of the engine’s tool-name check is unavailable or gave no clear answer), so it removed none rather than guess. Removing them needs that check available in this client.';
566
578
  case 'loosen_forbidden':
567
579
  return 'The engine refused to take these entries out of this session’s rule record: on this engine only an operator can remove entries from it, so the record is unchanged. Ask an operator to remove them, or continue in a new session.';
568
580
  case 'conflict':
@@ -16,3 +16,4 @@ export interface StandingRowsHostFacts {
16
16
  readonly wholeToolRuleSent?: boolean;
17
17
  }
18
18
  export declare function standingRowsOf(card: object | null | undefined, host?: StandingRowsHostFacts | null): StandingRows;
19
+ export declare function seatSessionRowOf(card: object | null | undefined, requestId: string | undefined): boolean;
@@ -1,6 +1,7 @@
1
1
  import { readAskClassPairState } from './askClassPair.js';
2
2
  import { automaticAnswerVerdict } from './automaticAnswerVerdict.js';
3
3
  import { readRuleOffers } from './toolApprovalWire.js';
4
+ import { toolPermissionRequestIdDomain } from '../seatContract.js';
4
5
  const DEPLOYMENT_LIST_ASK_CLASSES = Object.freeze(['ask_rule']);
5
6
  const UNREADABLE = Symbol('unreadable');
6
7
  function ownData(v, key) {
@@ -80,27 +81,32 @@ function persistentRowOf(card, host, evidenceUnreadable) {
80
81
  return { row: 'none', why: 'rule_not_sent' };
81
82
  return { row: 'local_whole_tool', why: 'given' };
82
83
  }
84
+ function enginePremiseOf(card) {
85
+ const refused = present(card, 'rememberRefused');
86
+ if (refused === UNREADABLE)
87
+ return 'card_unreadable';
88
+ if (refused.inCard)
89
+ return refused.value === true ? 'remember_refused' : 'remember_unreadable';
90
+ const evidence = present(card, 'unreadableEvidence');
91
+ if (evidence === UNREADABLE)
92
+ return 'card_unreadable';
93
+ if (!evidence.inCard)
94
+ return { evidenceUnreadable: false };
95
+ const list = ownData(card, 'unreadableEvidence');
96
+ if (!Array.isArray(list) || !list.every((k) => typeof k === 'string'))
97
+ return 'card_unreadable';
98
+ if (list.includes('rememberRefused'))
99
+ return 'remember_unreadable';
100
+ return { evidenceUnreadable: list.length > 0 };
101
+ }
83
102
  export function standingRowsOf(card, host) {
84
103
  if (typeof card !== 'object' || card === null)
85
104
  return allClosed('card_unreadable');
86
105
  try {
87
- const refused = present(card, 'rememberRefused');
88
- if (refused === UNREADABLE)
89
- return allClosed('card_unreadable');
90
- if (refused.inCard)
91
- return allClosed(refused.value === true ? 'remember_refused' : 'remember_unreadable');
92
- const evidence = present(card, 'unreadableEvidence');
93
- if (evidence === UNREADABLE)
94
- return allClosed('card_unreadable');
95
- let evidenceUnreadable = false;
96
- if (evidence.inCard) {
97
- const list = ownData(card, 'unreadableEvidence');
98
- if (!Array.isArray(list) || !list.every((k) => typeof k === 'string'))
99
- return allClosed('card_unreadable');
100
- if (list.includes('rememberRefused'))
101
- return allClosed('remember_unreadable');
102
- evidenceUnreadable = list.length > 0;
103
- }
106
+ const premise = enginePremiseOf(card);
107
+ if (typeof premise === 'string')
108
+ return allClosed(premise);
109
+ const evidenceUnreadable = premise.evidenceUnreadable;
104
110
  const sessionRow = ownData(card, 'allowSessionCarried') === true;
105
111
  const sessionWhy = sessionRow ? 'given' : 'route_cannot_carry';
106
112
  let deploymentList;
@@ -125,3 +131,18 @@ export function standingRowsOf(card, host) {
125
131
  return allClosed('card_unreadable');
126
132
  }
127
133
  }
134
+ export function seatSessionRowOf(card, requestId) {
135
+ if (typeof card !== 'object' || card === null)
136
+ return false;
137
+ try {
138
+ if (Object.hasOwn(card, 'requestId'))
139
+ return false;
140
+ const domain = toolPermissionRequestIdDomain(requestId);
141
+ if (domain !== 'live:' && domain !== 'durable:')
142
+ return false;
143
+ return typeof enginePremiseOf(card) !== 'string';
144
+ }
145
+ catch {
146
+ return false;
147
+ }
148
+ }
@@ -1,4 +1,5 @@
1
1
  import { RESUME_REOPEN_CODES, RESUME_ENV_FAILED, RESUME_TOOL_UNAVAILABLE, refusalSaysStillPending } from '../engineErrorCodes.js';
2
+ import { guardedRead, ownDataField } from '../ownKey.js';
2
3
  const UNSTATED = Object.freeze({ kind: 'unstated' });
3
4
  const NOT_REOPENED = Object.freeze({ kind: 'not_reopened' });
4
5
  export function suspendedReopenOf(ev) {
@@ -22,7 +23,7 @@ export function suspendedReopenOf(ev) {
22
23
  export function resumeReopenFromError(err) {
23
24
  if (typeof err !== 'object' || err === null)
24
25
  return null;
25
- const code = err.errorCode;
26
+ const code = guardedRead(() => ownDataField(err, 'errorCode'));
26
27
  if (typeof code !== 'string' || !RESUME_REOPEN_CODES.includes(code))
27
28
  return null;
28
29
  if (!refusalSaysStillPending(err))
@@ -6,11 +6,7 @@ import { type DenyAttributionRefusalDetail } from '../wireRefusalCopy.js';
6
6
  import { type ApprovalDecidedByReading } from '../approvalDecidedByCapability.js';
7
7
  import { type DecideReceiptView } from '../decideReceipt.js';
8
8
  import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS } from '@sema-agent/sdk';
9
- import type { ApprovalDecidedBy, ApprovalSettleCause, ToolApprovalRespondAck, PersistedRuleAnchor as SdkPersistedRuleAnchor, RuleOfferMatch as SdkRuleOfferMatch, RuleOfferBatchMember as SdkRuleOfferBatchMember, RuleOfferUncoveredDetail as SdkRuleOfferUncoveredDetail, RuleOfferUncoveredReason as SdkRuleOfferUncoveredReason, AskOrigin as SdkAskOrigin, RuleOffersAbsence as SdkRuleOffersAbsence, DenialLimitKind as SdkDenialLimitKind, DenialLimitFallback as SdkDenialLimitFallback } from '@sema-agent/sdk';
10
- export declare function isFsApprovalGate(gate: {
11
- kind?: unknown;
12
- toolName?: unknown;
13
- } | undefined | null): boolean;
9
+ import type { ApprovalDecidedBy, ApprovalSettleCause, ToolApprovalRespondAck, PersistedRuleAnchor as SdkPersistedRuleAnchor, RuleOfferMatch as SdkRuleOfferMatch, RuleOfferBatchMember as SdkRuleOfferBatchMember, RuleOfferUncoveredDetail as SdkRuleOfferUncoveredDetail, RuleOfferUncoveredReason as SdkRuleOfferUncoveredReason, AskOrigin as SdkAskOrigin, RuleOffersAbsence as SdkRuleOffersAbsence, DenialLimitKind as SdkDenialLimitKind, DenialLimitFallback as SdkDenialLimitFallback, ToolApprovalCardWord } from '@sema-agent/sdk';
14
10
  export declare function toolNameIsFsWrite(name: string): boolean;
15
11
  export declare function toolNameIsShellExec(name: string): boolean;
16
12
  export declare function isToolApprovalGate(gate: {
@@ -155,6 +151,7 @@ export interface ApprovalCardRequest {
155
151
  mandate?: ApprovalMandateWord;
156
152
  denialLimitFallback?: DenialLimitFallback;
157
153
  origin?: string;
154
+ approvalCard?: ToolApprovalCardWord;
158
155
  askClass?: string;
159
156
  classes?: readonly string[];
160
157
  boundGrants?: BoundSkillGrantsWire;
@@ -177,12 +174,13 @@ export declare function approvalCardPortMissesFor(sessionKey: string): number;
177
174
  export declare function hasApprovalCardPort(): boolean;
178
175
  export declare function hasApprovalCardPortFor(sessionKey: string): boolean;
179
176
  export declare function approvalCardPortFor(sessionKey: string): ApprovalCardPort | null;
177
+ export declare function __resetSettledApprovalsForTests(): void;
180
178
  export declare function _resetApprovalCardPortForTest(): void;
181
179
  export declare function surfaceApprovalCard(req: ApprovalCardRequest): Promise<ApprovalCardDecision>;
182
180
  declare const REMEMBER_REFUSAL_CODES: readonly ["remember_not_in_proof", "remember_requires_binding", "capability.store_required", "decide.workflow_remember_unsupported", "decide.parked_remember_unsupported"];
183
181
  export type RememberRefusalCode = (typeof REMEMBER_REFUSAL_CODES)[number];
184
182
  export declare function rememberRefusalOf(error: unknown): RememberRefusalCode | undefined;
185
- export declare function surfaceFsApprovalAndDecide(deps: FsApprovalWireDeps, taskId: string, argsByCall: Map<string, unknown>, signal?: AbortSignal, parkGatedCallId?: string): Promise<FsApprovalOutcome>;
183
+ export declare function surfaceFsApprovalAndDecide(deps: FsApprovalWireDeps, taskId: string, argsByCall: Map<string, unknown>, signal?: AbortSignal, parkGatedCallId?: string, parkToolName?: string): Promise<FsApprovalOutcome>;
186
184
  export interface BoundSkillGrantsWire {
187
185
  readonly skill: string | null;
188
186
  readonly allowedTools: readonly string[];
@@ -219,6 +217,7 @@ export interface ToolApprovalFrame {
219
217
  mandated?: true;
220
218
  mandate?: string;
221
219
  origin?: string;
220
+ approvalCard?: string;
222
221
  askClass?: string;
223
222
  classes?: readonly string[];
224
223
  inputHasBidi?: true;
@@ -238,7 +237,7 @@ export interface ToolApprovalDelegation {
238
237
  depth: number;
239
238
  agentName?: string;
240
239
  }
241
- export declare const TOOL_APPROVAL_FRAME_KEYS_MIRROR: readonly ["type", "approvalId", "toolCallId", "toolName", "sourceTaskId", "fromSubagent", "sourceAgentName", "message", "args", "argsOmitted", "governanceForced", "ruleOffers", "ruleOffersAbsence", "denialLimitFallback", "readRootCandidate", "mandated", "mandate", "origin", "askClass", "classes", "inputHasBidi", "parked", "persistedRuleShadowed", "allowRuleShadowed", "probeCause", "probeReason", "rememberRefused", "boundGrantDigest", "boundGrants", "classifierNoRuling", "ruleEvidence", "requiresRealApproval", "expiresInMs", "expiresAtMs", "serverNowMs", "delegation", "outcome", "cause"];
240
+ export declare const TOOL_APPROVAL_FRAME_KEYS_MIRROR: readonly ["type", "approvalId", "toolCallId", "toolName", "sourceTaskId", "fromSubagent", "sourceAgentName", "message", "args", "argsOmitted", "governanceForced", "ruleOffers", "ruleOffersAbsence", "denialLimitFallback", "readRootCandidate", "mandated", "mandate", "origin", "approvalCard", "askClass", "classes", "inputHasBidi", "parked", "persistedRuleShadowed", "allowRuleShadowed", "probeCause", "probeReason", "rememberRefused", "boundGrantDigest", "boundGrants", "classifierNoRuling", "ruleEvidence", "requiresRealApproval", "expiresInMs", "expiresAtMs", "serverNowMs", "delegation", "outcome", "cause"];
242
241
  export interface ApprovalMandatedFacts {
243
242
  readonly mandated?: true;
244
243
  readonly ruleOffersAbsence?: string;
@@ -248,7 +247,8 @@ export declare function approvalIsMandated(v: ApprovalMandatedFacts | undefined
248
247
  export declare function readApprovalMandate(v: {
249
248
  readonly mandate?: string;
250
249
  } | undefined | null): ApprovalMandateWord | undefined;
251
- export declare function toolPermissionRequestAskBits(card: object | null | undefined): Pick<ToolPermissionRequest, 'mandated' | 'mandate' | 'origin' | 'ruleOffersAbsence' | 'askClass' | 'classes' | 'rememberRefused'>;
250
+ export declare function readApprovalCardWord(carrier: unknown): ToolApprovalCardWord | undefined;
251
+ export declare function toolPermissionRequestAskBits(card: object | null | undefined, requestId?: string): Pick<ToolPermissionRequest, 'mandated' | 'mandate' | 'origin' | 'ruleOffersAbsence' | 'askClass' | 'classes' | 'sessionRow'>;
252
252
  export declare function isFromSubagent(frame: ToolApprovalFrame): boolean;
253
253
  export type ToolApprovalRespondDecision = 'allow' | 'allow_session' | 'deny';
254
254
  export interface RespondToolApprovalOpts {
@@ -1,7 +1,9 @@
1
1
  import { APPROVAL_CARD_PORT_KEY_MISMATCH_REASON, DEFAULT_DENY_REASON, DecideTransportRetryExhaustedError, HitlBridge, NO_APPROVAL_CARD_PORT_REASON, denyReasonForWire, findPendingForTask, hitlSafetyCodeOf, readDecideCurrentPending, readWireCodes, readWireErrorCodeReading, } from './hitlBridge.js';
2
2
  import { askParkRowArm } from './askParkRowRouting.js';
3
+ import { parkGateArmOf } from './frameRouter.js';
4
+ import { seatSessionRowOf } from './standingRows.js';
3
5
  import { hostLog } from '../host.js';
4
- import { readAskOrigin, readOwnDataNonEmptyString, readOwnDataValue, readOwnNonEmptyString } from '../ownKey.js';
6
+ import { guardedRead, readAskOrigin, readOwnDataNonEmptyString, readOwnDataValue, readOwnNonEmptyString } from '../ownKey.js';
5
7
  import { readAskClassPair } from './askClassPair.js';
6
8
  import { readAllowRuleShadowFromWire } from './allowRuleShadow.js';
7
9
  import { createSessionSlot, DEFAULT_SESSION_KEY } from '../sessionSlot.js';
@@ -10,7 +12,7 @@ import { CORE_SKILL_TOOL_NAME } from '../generated/toolNameTables.js';
10
12
  import { INTERRUPT_DENY_REASON, observeCancelByDeny, surfaceApprovalParking, surfaceRememberNotApplied, surfaceEditNotForwarded, surfaceEditRefusedOnBlindAsk, surfaceRuleArmNotSent, surfaceRuleArmRejected } from './hitlHostSurface.js';
11
13
  import { approvalCallKey, liveFrameCallKey } from './gateIdentity.js';
12
14
  import { displayUntrusted } from '../displayUntrusted.js';
13
- import { approvalDecisionHolds, awaitLiveCardHolder, holdLiveCard, joinLiveCard, liveCardHoldFor, liveCardHoldOf } from './approvalHolds.js';
15
+ import { approvalDecisionHolds, awaitLiveCardHolder, holdLiveCard, joinLiveCard, liveCardHoldFor, liveCardHoldOf, clearSettledApprovals, settledApprovalOf, settledForDurableLane, settledLiveCardOutcome } from './approvalHolds.js';
14
16
  import { approvalResolutionOf } from './approvalResolution.js';
15
17
  import { isApprovalMandateWord } from '../gateVocabulary.js';
16
18
  import { denyAttributionRefusalFromError } from '../wireRefusalCopy.js';
@@ -21,14 +23,7 @@ import { refusalCauseWordOf } from './approvalEndingCause.js';
21
23
  import { readDecisionRefusalAsk } from './decisionRefusal.js';
22
24
  import { DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, refusalSaysStillPending } from '../engineErrorCodes.js';
23
25
  import { readDecideReceipt } from '../decideReceipt.js';
24
- import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS, ASK_ORIGINS, } from '@sema-agent/sdk';
25
- export function isFsApprovalGate(gate) {
26
- if (!gate)
27
- return false;
28
- if (gate.kind === 'tool_approval')
29
- return true;
30
- return typeof gate.toolName === 'string' && toolNameIsFsWrite(gate.toolName);
31
- }
26
+ import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS, ASK_ORIGINS, TOOL_APPROVAL_CARD_WORDS, } from '@sema-agent/sdk';
32
27
  export function toolNameIsFsWrite(name) {
33
28
  const n = name.replace(/[\s_-]+/g, '').toLowerCase();
34
29
  return (n === 'write' || n === 'filewrite' || n === 'edit' || n === 'fileedit' || n === 'multiedit' || n === 'notebookedit');
@@ -37,9 +32,13 @@ export function toolNameIsShellExec(name) {
37
32
  return name.replace(/[\s_-]+/g, '').toLowerCase() === 'bash';
38
33
  }
39
34
  export function isToolApprovalGate(gate) {
40
- if (isFsApprovalGate(gate))
41
- return true;
42
- return typeof gate?.toolName === 'string' && toolNameIsShellExec(gate.toolName);
35
+ return parkGateArmOf(gate) === 'fs';
36
+ }
37
+ function fallbackRowMatcherFor(parkToolName) {
38
+ const family = (toolName) => toolName !== undefined && (toolNameIsFsWrite(toolName) || toolNameIsShellExec(toolName));
39
+ if (parkToolName === undefined || parkToolName === '' || family(parkToolName))
40
+ return family;
41
+ return (toolName) => toolName === parkToolName;
43
42
  }
44
43
  export function structurallyEqual(a, b) {
45
44
  if (a === b)
@@ -113,6 +112,9 @@ export function hasApprovalCardPortFor(sessionKey) {
113
112
  export function approvalCardPortFor(sessionKey) {
114
113
  return cardPortByKey.get(sessionKey) ?? null;
115
114
  }
115
+ export function __resetSettledApprovalsForTests() {
116
+ clearSettledApprovals();
117
+ }
116
118
  export function _resetApprovalCardPortForTest() {
117
119
  cardPortByKey.clear();
118
120
  cardPortMissesByKey.clear();
@@ -283,13 +285,13 @@ async function joinDurableDecision(hold, deps, signal) {
283
285
  }
284
286
  return { ...o, joinedInFlight: true };
285
287
  }
286
- export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signal, parkGatedCallId) {
288
+ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signal, parkGatedCallId, parkToolName) {
287
289
  const decidedByReading = decidedByReadingSnapshotOf(deps);
288
290
  const readMark = openDurableRead();
289
291
  let found;
290
292
  let held;
291
293
  try {
292
- found = await findPendingForTask(deps.client, taskId, (toolName) => toolName !== undefined && (toolNameIsFsWrite(toolName) || toolNameIsShellExec(toolName)), signal ? { signal } : undefined, parkGatedCallId, (row) => askParkRowArm(row) === 'tool-gate');
294
+ found = await findPendingForTask(deps.client, taskId, fallbackRowMatcherFor(parkToolName), signal ? { signal } : undefined, parkGatedCallId, (row) => askParkRowArm(row) === 'tool-gate');
293
295
  if (found.ok)
294
296
  held = heldDurableDecision(durableHoldKey(found.pending, approvalCallKey(found.gatedCallId, taskId)), readMark);
295
297
  }
@@ -305,7 +307,7 @@ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signa
305
307
  const joined = await awaitLiveCardHolder(liveHolder, signal);
306
308
  if (joined !== undefined)
307
309
  return fsOutcomeOfJoinedLiveCard(joined, found.gatedCallId);
308
- return surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signal, parkGatedCallId);
310
+ return surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signal, parkGatedCallId, parkToolName);
309
311
  }
310
312
  const callKey = approvalCallKey(found.gatedCallId, taskId);
311
313
  const fetched = found;
@@ -383,6 +385,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
383
385
  ...(hasOwnStrictTrue(pending, 'mandated') ? { mandated: true } : {}),
384
386
  ...((w) => (w !== undefined ? { mandate: w } : {}))(readApprovalMandate(pending)),
385
387
  ...((o) => (o !== undefined ? { origin: o } : {}))(readAskOrigin(pending)),
388
+ ...((w) => (w !== undefined ? { approvalCard: w } : {}))(readApprovalCardWord(pending)),
386
389
  ...(readAskClassPair(pending) ?? {}),
387
390
  ...(pending.gateKind === 'irreversible_ask' ? { irreversibleParkGate: true } : {}),
388
391
  ...(pending.hasBidiControls === true ? { hasBidiControls: true } : {}),
@@ -596,6 +599,7 @@ export const TOOL_APPROVAL_FRAME_KEYS_MIRROR = [
596
599
  'mandated',
597
600
  'mandate',
598
601
  'origin',
602
+ 'approvalCard',
599
603
  'askClass',
600
604
  'classes',
601
605
  'inputHasBidi',
@@ -637,7 +641,21 @@ export function readApprovalMandate(v) {
637
641
  const raw = v.mandate;
638
642
  return isApprovalMandateWord(raw) ? raw : undefined;
639
643
  }
640
- export function toolPermissionRequestAskBits(card) {
644
+ const APPROVAL_CARD_WORD_SET = new Set(TOOL_APPROVAL_CARD_WORDS);
645
+ export function readApprovalCardWord(carrier) {
646
+ try {
647
+ if (typeof carrier !== 'object' || carrier === null)
648
+ return undefined;
649
+ const d = Object.getOwnPropertyDescriptor(carrier, 'approvalCard');
650
+ if (d === undefined || !('value' in d))
651
+ return undefined;
652
+ return APPROVAL_CARD_WORD_SET.has(d.value) ? d.value : undefined;
653
+ }
654
+ catch {
655
+ return undefined;
656
+ }
657
+ }
658
+ export function toolPermissionRequestAskBits(card, requestId) {
641
659
  if (typeof card !== 'object' || card === null)
642
660
  return {};
643
661
  const mandated = hasOwnStrictTrue(card, 'mandated');
@@ -651,7 +669,7 @@ export function toolPermissionRequestAskBits(card) {
651
669
  ...(origin !== undefined ? { origin } : {}),
652
670
  ...(ruleOffersAbsence !== undefined ? { ruleOffersAbsence } : {}),
653
671
  ...(askClassPair ?? {}),
654
- ...(readApprovalRememberRefused(card) ? { rememberRefused: true } : {}),
672
+ ...(seatSessionRowOf(card, requestId) ? { sessionRow: true } : {}),
655
673
  };
656
674
  }
657
675
  function hasOwnStrictTrue(v, key) {
@@ -843,8 +861,9 @@ export function readToolApprovalRespondRefusal(err) {
843
861
  return undefined;
844
862
  }
845
863
  };
846
- const rawStatus = pick('status');
847
- const rawCode = pick('errorCode');
864
+ const pickMachine = (key) => guardedRead(() => (typeof err === 'object' && err !== null ? readOwnDataValue(err, key) : undefined));
865
+ const rawStatus = pickMachine('status');
866
+ const rawCode = pickMachine('errorCode');
848
867
  const status = typeof rawStatus === 'number' && Number.isFinite(rawStatus) ? rawStatus : undefined;
849
868
  const errorCode = typeof rawCode === 'string' && rawCode.length > 0 ? rawCode : undefined;
850
869
  const message = refusalTextOf(err, pick('message'));
@@ -1466,6 +1485,9 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
1466
1485
  const held = liveCardHoldOf(liveFrameCallKey(approvalId));
1467
1486
  if (held !== undefined)
1468
1487
  return joinLiveCard(held, signal);
1488
+ const settled = settledLiveCardOutcome(approvalId);
1489
+ if (settled !== undefined)
1490
+ return Promise.resolve(settled);
1469
1491
  return holdLiveCard(liveCardIdentityOf(approvalId, frame, run), signal, async (hold) => {
1470
1492
  const slot = {};
1471
1493
  const out = await presentToolApprovalFrameAndRespond(frame, approvalId, respond, streamArgs, signal, lane, hold, slot);
@@ -1504,9 +1526,12 @@ function readApprovalHolderIdentity(v) {
1504
1526
  return out;
1505
1527
  }
1506
1528
  export async function joinApprovalHolder(identity, signal) {
1507
- const hold = liveCardHoldFor(readApprovalHolderIdentity(identity));
1508
- if (hold === undefined)
1509
- return { kind: 'free' };
1529
+ const who = readApprovalHolderIdentity(identity);
1530
+ const hold = liveCardHoldFor(who);
1531
+ if (hold === undefined) {
1532
+ const entry = settledApprovalOf(who.approvalId);
1533
+ return settledForDurableLane(entry) && entry !== undefined ? { kind: 'joined', outcome: { ...entry.outcome, joinedInFlight: true } } : { kind: 'free' };
1534
+ }
1510
1535
  const joined = await awaitLiveCardHolder(hold, signal);
1511
1536
  return joined !== undefined ? { kind: 'joined', outcome: joined } : { kind: 'free' };
1512
1537
  }
@@ -1581,6 +1606,7 @@ async function presentToolApprovalFrameAndRespond(frame, approvalId, respond, st
1581
1606
  : {}),
1582
1607
  ...(denialLimitFallback !== undefined ? { denialLimitFallback } : {}),
1583
1608
  ...((o) => (o !== undefined ? { origin: o } : {}))(readAskOrigin(frame)),
1609
+ ...((w) => (w !== undefined ? { approvalCard: w } : {}))(readApprovalCardWord(frame)),
1584
1610
  ...(readAskClassPair(frame) ?? {}),
1585
1611
  ...((g) => (g !== undefined ? { boundGrants: g } : {}))(readApprovalBoundGrants(frame)),
1586
1612
  ...((w) => (w !== undefined ? { classifierNoRuling: w } : {}))(readApprovalClassifierNoRuling(frame)),
@@ -1613,7 +1639,7 @@ async function presentToolApprovalFrameAndRespond(frame, approvalId, respond, st
1613
1639
  catch (e) {
1614
1640
  interruptDeny = Promise.reject(e);
1615
1641
  }
1616
- hold.trailing = interruptDeny.then(() => undefined, () => undefined);
1642
+ hold.trailing = interruptDeny.then((body) => readToolApprovalRespondParking(body) === undefined, () => false);
1617
1643
  observeCancelByDeny(interruptDeny, approvalId);
1618
1644
  hostLog('debug', `liveToolApprovalWire: ${approvalId} card aborted — one tool-level deny issued to settle the pending ask`);
1619
1645
  return { decision: 'unresolved', aborted: true };
package/dist/index.d.ts CHANGED
@@ -24,8 +24,8 @@ export { _resetLiveQuestionStore, hasLocalQuestionResponder, hasQuestionOverlay,
24
24
  export type { AskQuestion, AskQuestionOption, QuestionAnswer, QuestionFrame, } from './liveQuestionStore.js';
25
25
  export * from './engineInlineTaskStats.js';
26
26
  export * from './printToolResultFrame.js';
27
- export { __resetEngineCapsCacheForTests, engineCapState, engineCapString, engineCapsGeneration, engineCapsSettled, engineCapTrue, engineCapValue, invalidateEngineCaps, kickEngineCapsProbe, } from './engineCapsCache.js';
28
- export type { EngineCapState, EngineCapValueState, } from './engineCapsCache.js';
27
+ export { __resetEngineCapsCacheForTests, engineCapState, engineCapString, engineCapsGeneration, engineCapsLandingOf, engineCapsSettled, engineCapTrue, engineCapValue, invalidateEngineCaps, kickEngineCapsProbe, rotateEngineCapsProbe, } from './engineCapsCache.js';
28
+ export type { EngineCapState, EngineCapsLanding, EngineCapsProbeRotation, EngineCapValueState, } from './engineCapsCache.js';
29
29
  export * from './sqlEngineCapability.js';
30
30
  export * from './writeProtectionCapability.js';
31
31
  export * from './webSearchBackendCapability.js';
@@ -46,7 +46,7 @@ export * from './hitl/parkExpiryJudgements.js';
46
46
  export * from './usageAnalytics.js';
47
47
  export * from './leaderConflict.js';
48
48
  export * from './runTerminal.js';
49
- export { CORE_SEMA_TASK_TERMINAL_STATUSES, CORE_TASK_NOTIFICATION_TERMINAL_STATUSES, CORE_TERMINAL_CAUSE_KINDS, SDK_FLEET_TASK_TERMINAL_STATUSES, SDK_RUN_TERMINAL_STATUSES, ccTaskTerminalStatusOf, isCoreSemaTaskTerminal, isCoreTaskNotificationTerminal, isCoreTaskNotificationTerminalNotSuccess, isCoreTerminalCauseKind, isSdkFleetTaskTerminal, isSdkFleetTaskTerminalNotSuccess, isSdkRunTerminal, isSdkRunTerminalNotSuccess, } from './terminalStatuses.js';
49
+ export { CORE_SEMA_TASK_TERMINAL_STATUSES, CORE_TASK_NOTIFICATION_TERMINAL_STATUSES, CORE_TERMINAL_CAUSE_KINDS, SDK_FLEET_TASK_TERMINAL_STATUSES, SDK_PARKED_RUN_STATUSES, SDK_RUN_TERMINAL_STATUSES, ccTaskTerminalStatusOf, isCoreSemaTaskTerminal, isCoreTaskNotificationTerminal, isCoreTaskNotificationTerminalNotSuccess, isCoreTerminalCauseKind, isSdkFleetTaskTerminal, isSdkFleetTaskTerminalNotSuccess, isSdkRunParked, isSdkRunTerminal, isSdkRunTerminalNotSuccess, } from './terminalStatuses.js';
50
50
  export type { CcTaskTerminalStatus, CoreSemaTaskTerminalStatus, CoreTaskNotificationTerminalStatus, CoreTerminalCauseKind, SdkFleetTaskTerminalStatus, SdkRunTerminalStatus, } from './terminalStatuses.js';
51
51
  export type { ProviderRejectionResend, ProviderRejectionKind } from './providerRejection.js';
52
52
  export { PROVIDER_REJECTION_KINDS } from './providerRejection.js';
@@ -96,9 +96,11 @@ export * from './engineWireSdk.js';
96
96
  export * from './classifierVerdictWire.js';
97
97
  export { stripSystemReminderBlocks, unwrapSystemReminder } from './systemReminderTag.js';
98
98
  export { findSystemReminderOpenTag, type SystemReminderOpenTagSpan } from './systemReminderTag.js';
99
- export { ACTIVE_RUN_BUSY_ERROR_CODE, APPROVAL_EXPIRED, ASK_GONE, asModelFallbackReason, CAPABILITY_IMAGE_INDEX_REQUIRED, CAPABILITY_OPERATOR_PRINCIPALS_REQUIRED, CAPABILITY_SELF_ORCHESTRATION_REQUIRED, CONFIG_AGENT_UNKNOWN_TOOL, CONFIG_DELEGATION_ENTRY_CAPS, CONFIG_IMAGE_INVALID, CONFIG_LEGACY_TOOL_NAME, CONFIG_LIMIT_INVALID, CONFIG_LIMIT_UNKNOWN_KEY, CONFIG_MEMORY_PROJECT_KEY_SPELLING, CONFIG_MEMORY_WRITE_SCOPE_MISMATCH, CONFIG_OUTPUT_STYLE_INVALID, CONFIG_STRATEGY_FIND_LIMIT_INVALID, CONFIG_STRATEGY_MAX_SIZE_INVALID, CORRUPT_SESSION_ERROR_CODE, DECIDE_CLAIM_LOST, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_PARK_MOVED_CODES, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_PARK_FORKED, DECIDE_WORKFLOW_PARKS_UNREADABLE, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, DELEGATION_CAP_CODES, DELEGATION_CONCURRENCY_CAP, DELEGATION_SESSION_CAP, delegationCapDispositionOf, DRAINING_ERROR_CODE, ENGINE_STOP_REASONS, engineStopReasonToCc, ENV_LIFETIME_EXPIRED, FLEET_LEASE_UNAVAILABLE, GATE_PARKED_ERROR_CODE, imageInvalidFailureNoteOf, isConfigRefusalCode, isCorruptSessionCode, isDecideParkMovedCode, isDelegationCapCode, isInterruptedToolEndCode, isLimitsExceededCode, isRewindFamilyCode, isRulesRefusalCode, isStatusDerivedCoarseCode, isWorkflowParkRefusalCode, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, MCP_SERVER_REVOKED, MODEL_FALLBACK_INHERIT_NO_TIER_BINDING, operatorGateRefusalContent, OUTPUT_INVALID, PARKED_RESUME_STARTUP_FAILED, REQUEST_AUTONOMY_LANE_REFUSED, RESUME_AT_ERROR_CODE_PREFIX, RESUME_CONTEXT_UNAVAILABLE, RESUME_ENV_FAILED, RESUME_PLACEMENT_MISMATCH, RESUME_POLICY_FOLD_CODE, RESUME_PREFLIGHT_REJECTED, RESUME_REOPEN_CODES, RESUME_RETRY_LATER_CODES, RESUME_TOOL_CONTRACT_MISMATCH, RESUME_TOOL_UNAVAILABLE, RESUME_USAGE_WINDOW_EXHAUSTED, REWIND_ERROR_CODE_PREFIXES, RULES_LEGACY_TOOL_NAME, RUN_DEATH_VERDICT_CODES, RUN_ORPHANED, RUN_STALLED, runDeathVerdictNoteOf, SCENARIO_ASSIGNMENT_UNKNOWN_ERROR_CODE, SCENARIO_NOT_ALLOWED_ERROR_CODE, STATUS_DERIVED_COARSE_CODES, STOP_CONFLICT_CODES, STREAM_MAX_DURATION, TOOL_END_INTERRUPTED_NEVER_STARTED, TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN, USAGE_WINDOW_EXHAUSTED, WORKFLOW_PARK_REFUSAL_CODES, } from './engineErrorCodes.js';
99
+ export { ACTIVE_RUN_BUSY_ERROR_CODE, APPROVAL_EXPIRED, ASK_GONE, asModelFallbackReason, CAPABILITY_IMAGE_INDEX_REQUIRED, CAPABILITY_OPERATOR_PRINCIPALS_REQUIRED, CAPABILITY_SELF_ORCHESTRATION_REQUIRED, CONFIG_AGENT_UNKNOWN_TOOL, CONFIG_DELEGATION_ENTRY_CAPS, CONFIG_IMAGE_INVALID, CONFIG_LEGACY_TOOL_NAME, CONFIG_LIMIT_INVALID, CONFIG_LIMIT_UNKNOWN_KEY, CONFIG_MEMORY_PROJECT_KEY_SPELLING, CONFIG_MEMORY_WRITE_SCOPE_MISMATCH, CONFIG_OUTPUT_STYLE_INVALID, CONFIG_STRATEGY_FIND_LIMIT_INVALID, CONFIG_STRATEGY_MAX_SIZE_INVALID, CONFLICT_IDEMPOTENCY_PAYLOAD_MISMATCH, CORRUPT_SESSION_ERROR_CODE, DECIDE_CLAIM_LOST, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_PARK_MOVED_CODES, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_PARK_FORKED, DECIDE_WORKFLOW_PARKS_UNREADABLE, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, DELEGATION_CAP_CODES, DELEGATION_CONCURRENCY_CAP, DELEGATION_SESSION_CAP, delegationCapDispositionOf, DRAINING_ERROR_CODE, ENGINE_STOP_REASONS, engineStopReasonToCc, ENV_LIFETIME_EXPIRED, FLEET_LEASE_UNAVAILABLE, GATE_PARKED_ERROR_CODE, idempotencyPayloadMismatchContent, imageInvalidFailureNoteOf, isConfigRefusalCode, isCorruptSessionCode, isDecideParkMovedCode, isDelegationCapCode, isIdempotencyPayloadMismatchCode, isInterruptedToolEndCode, isLimitsExceededCode, isRewindFamilyCode, isRulesRefusalCode, isStatusDerivedCoarseCode, isWorkflowParkRefusalCode, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, MCP_SERVER_REVOKED, MODEL_FALLBACK_INHERIT_NO_TIER_BINDING, operatorGateRefusalContent, OUTPUT_INVALID, PARKED_RESUME_STARTUP_FAILED, REQUEST_AUTONOMY_LANE_REFUSED, RESUME_AT_ERROR_CODE_PREFIX, RESUME_CONTEXT_UNAVAILABLE, RESUME_ENV_FAILED, RESUME_PLACEMENT_MISMATCH, RESUME_POLICY_FOLD_CODE, RESUME_PREFLIGHT_REJECTED, RESUME_REOPEN_CODES, RESUME_RETRY_LATER_CODES, RESUME_TOOL_CONTRACT_MISMATCH, RESUME_TOOL_UNAVAILABLE, RESUME_USAGE_WINDOW_EXHAUSTED, REWIND_ERROR_CODE_PREFIXES, RULES_LEGACY_TOOL_NAME, RUN_DEATH_VERDICT_CODES, RUN_ORPHANED, RUN_STALLED, runDeathVerdictNoteOf, SCENARIO_ASSIGNMENT_UNKNOWN_ERROR_CODE, SCENARIO_NOT_ALLOWED_ERROR_CODE, STATUS_DERIVED_COARSE_CODES, STOP_CONFLICT_CODES, STREAM_MAX_DURATION, TOOL_END_INTERRUPTED_NEVER_STARTED, TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN, USAGE_WINDOW_EXHAUSTED, WORKFLOW_PARK_REFUSAL_CODES, } from './engineErrorCodes.js';
100
100
  export type { DelegationCapDisposition, ModelFallbackReason, OperatorGateRefusal, RunDeathVerdictCode, } from './engineErrorCodes.js';
101
101
  export * from './agentsWireCaps.js';
102
+ export { engineToolDirectoryOf, excludeToolsAgainstDirectory } from './engineToolDirectory.js';
103
+ export type { EngineToolDirectory, EngineToolDirectorySource, ExcludeToolsAgainstDirectory } from './engineToolDirectory.js';
102
104
  export * from './attachmentsWireCaps.js';
103
105
  export * from './clientContextWireCaps.js';
104
106
  export * from './cloudConfigWireCaps.js';
@@ -232,6 +234,8 @@ export type { ClassifierDenyContext, HitlHostSurface, HitlNotice, } from './hitl
232
234
  export * from './hitl/toolApprovalWire.js';
233
235
  export * from './hitl/editedRuleTextPrecheck.js';
234
236
  export * from './coreValuePorts.js';
237
+ export { ruleToolNameVerdictOf } from './protocolSegment.js';
238
+ export type { RuleToolNameReading } from './protocolSegment.js';
235
239
  export * from './hitl/askGateWire.js';
236
240
  export * from './hitl/planReviewWire.js';
237
241
  export { PLAN_REVIEW_QUESTION_ID_PREFIX, REOPEN_ID_TAIL, approvalCallKey, askGateQuestionId, planReviewQuestionId, liveFrameCallKey, armedKeyFromQuestionId, } from './hitl/gateIdentity.js';
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ export { reducePanelFrame, createPanelReduceState, PANEL_DELTA_OPS } from './pan
19
19
  export { _resetLiveQuestionStore, hasLocalQuestionResponder, hasQuestionOverlay, hasQuestionOverlayFor, onQuestionFrame, onQuestionFrameFor, publishQuestionFrame, publishQuestionFrameFor, registerLocalQuestionResponder, respondToQuestion, setQuestionRespond, } from './liveQuestionStore.js';
20
20
  export * from './engineInlineTaskStats.js';
21
21
  export * from './printToolResultFrame.js';
22
- export { __resetEngineCapsCacheForTests, engineCapState, engineCapString, engineCapsGeneration, engineCapsSettled, engineCapTrue, engineCapValue, invalidateEngineCaps, kickEngineCapsProbe, } from './engineCapsCache.js';
22
+ export { __resetEngineCapsCacheForTests, engineCapState, engineCapString, engineCapsGeneration, engineCapsLandingOf, engineCapsSettled, engineCapTrue, engineCapValue, invalidateEngineCaps, kickEngineCapsProbe, rotateEngineCapsProbe, } from './engineCapsCache.js';
23
23
  export * from './sqlEngineCapability.js';
24
24
  export * from './writeProtectionCapability.js';
25
25
  export * from './webSearchBackendCapability.js';
@@ -39,7 +39,7 @@ export * from './hitl/parkExpiryJudgements.js';
39
39
  export * from './usageAnalytics.js';
40
40
  export * from './leaderConflict.js';
41
41
  export * from './runTerminal.js';
42
- export { CORE_SEMA_TASK_TERMINAL_STATUSES, CORE_TASK_NOTIFICATION_TERMINAL_STATUSES, CORE_TERMINAL_CAUSE_KINDS, SDK_FLEET_TASK_TERMINAL_STATUSES, SDK_RUN_TERMINAL_STATUSES, ccTaskTerminalStatusOf, isCoreSemaTaskTerminal, isCoreTaskNotificationTerminal, isCoreTaskNotificationTerminalNotSuccess, isCoreTerminalCauseKind, isSdkFleetTaskTerminal, isSdkFleetTaskTerminalNotSuccess, isSdkRunTerminal, isSdkRunTerminalNotSuccess, } from './terminalStatuses.js';
42
+ export { CORE_SEMA_TASK_TERMINAL_STATUSES, CORE_TASK_NOTIFICATION_TERMINAL_STATUSES, CORE_TERMINAL_CAUSE_KINDS, SDK_FLEET_TASK_TERMINAL_STATUSES, SDK_PARKED_RUN_STATUSES, SDK_RUN_TERMINAL_STATUSES, ccTaskTerminalStatusOf, isCoreSemaTaskTerminal, isCoreTaskNotificationTerminal, isCoreTaskNotificationTerminalNotSuccess, isCoreTerminalCauseKind, isSdkFleetTaskTerminal, isSdkFleetTaskTerminalNotSuccess, isSdkRunParked, isSdkRunTerminal, isSdkRunTerminalNotSuccess, } from './terminalStatuses.js';
43
43
  export { PROVIDER_REJECTION_KINDS } from './providerRejection.js';
44
44
  export * from './runCancelContext.js';
45
45
  export * from './argvFlagValue.js';
@@ -84,8 +84,9 @@ export * from './engineWireSdk.js';
84
84
  export * from './classifierVerdictWire.js';
85
85
  export { stripSystemReminderBlocks, unwrapSystemReminder } from './systemReminderTag.js';
86
86
  export { findSystemReminderOpenTag } from './systemReminderTag.js';
87
- export { ACTIVE_RUN_BUSY_ERROR_CODE, APPROVAL_EXPIRED, ASK_GONE, asModelFallbackReason, CAPABILITY_IMAGE_INDEX_REQUIRED, CAPABILITY_OPERATOR_PRINCIPALS_REQUIRED, CAPABILITY_SELF_ORCHESTRATION_REQUIRED, CONFIG_AGENT_UNKNOWN_TOOL, CONFIG_DELEGATION_ENTRY_CAPS, CONFIG_IMAGE_INVALID, CONFIG_LEGACY_TOOL_NAME, CONFIG_LIMIT_INVALID, CONFIG_LIMIT_UNKNOWN_KEY, CONFIG_MEMORY_PROJECT_KEY_SPELLING, CONFIG_MEMORY_WRITE_SCOPE_MISMATCH, CONFIG_OUTPUT_STYLE_INVALID, CONFIG_STRATEGY_FIND_LIMIT_INVALID, CONFIG_STRATEGY_MAX_SIZE_INVALID, CORRUPT_SESSION_ERROR_CODE, DECIDE_CLAIM_LOST, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_PARK_MOVED_CODES, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_PARK_FORKED, DECIDE_WORKFLOW_PARKS_UNREADABLE, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, DELEGATION_CAP_CODES, DELEGATION_CONCURRENCY_CAP, DELEGATION_SESSION_CAP, delegationCapDispositionOf, DRAINING_ERROR_CODE, ENGINE_STOP_REASONS, engineStopReasonToCc, ENV_LIFETIME_EXPIRED, FLEET_LEASE_UNAVAILABLE, GATE_PARKED_ERROR_CODE, imageInvalidFailureNoteOf, isConfigRefusalCode, isCorruptSessionCode, isDecideParkMovedCode, isDelegationCapCode, isInterruptedToolEndCode, isLimitsExceededCode, isRewindFamilyCode, isRulesRefusalCode, isStatusDerivedCoarseCode, isWorkflowParkRefusalCode, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, MCP_SERVER_REVOKED, MODEL_FALLBACK_INHERIT_NO_TIER_BINDING, operatorGateRefusalContent, OUTPUT_INVALID, PARKED_RESUME_STARTUP_FAILED, REQUEST_AUTONOMY_LANE_REFUSED, RESUME_AT_ERROR_CODE_PREFIX, RESUME_CONTEXT_UNAVAILABLE, RESUME_ENV_FAILED, RESUME_PLACEMENT_MISMATCH, RESUME_POLICY_FOLD_CODE, RESUME_PREFLIGHT_REJECTED, RESUME_REOPEN_CODES, RESUME_RETRY_LATER_CODES, RESUME_TOOL_CONTRACT_MISMATCH, RESUME_TOOL_UNAVAILABLE, RESUME_USAGE_WINDOW_EXHAUSTED, REWIND_ERROR_CODE_PREFIXES, RULES_LEGACY_TOOL_NAME, RUN_DEATH_VERDICT_CODES, RUN_ORPHANED, RUN_STALLED, runDeathVerdictNoteOf, SCENARIO_ASSIGNMENT_UNKNOWN_ERROR_CODE, SCENARIO_NOT_ALLOWED_ERROR_CODE, STATUS_DERIVED_COARSE_CODES, STOP_CONFLICT_CODES, STREAM_MAX_DURATION, TOOL_END_INTERRUPTED_NEVER_STARTED, TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN, USAGE_WINDOW_EXHAUSTED, WORKFLOW_PARK_REFUSAL_CODES, } from './engineErrorCodes.js';
87
+ export { ACTIVE_RUN_BUSY_ERROR_CODE, APPROVAL_EXPIRED, ASK_GONE, asModelFallbackReason, CAPABILITY_IMAGE_INDEX_REQUIRED, CAPABILITY_OPERATOR_PRINCIPALS_REQUIRED, CAPABILITY_SELF_ORCHESTRATION_REQUIRED, CONFIG_AGENT_UNKNOWN_TOOL, CONFIG_DELEGATION_ENTRY_CAPS, CONFIG_IMAGE_INVALID, CONFIG_LEGACY_TOOL_NAME, CONFIG_LIMIT_INVALID, CONFIG_LIMIT_UNKNOWN_KEY, CONFIG_MEMORY_PROJECT_KEY_SPELLING, CONFIG_MEMORY_WRITE_SCOPE_MISMATCH, CONFIG_OUTPUT_STYLE_INVALID, CONFIG_STRATEGY_FIND_LIMIT_INVALID, CONFIG_STRATEGY_MAX_SIZE_INVALID, CONFLICT_IDEMPOTENCY_PAYLOAD_MISMATCH, CORRUPT_SESSION_ERROR_CODE, DECIDE_CLAIM_LOST, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_PARK_MOVED_CODES, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_PARK_FORKED, DECIDE_WORKFLOW_PARKS_UNREADABLE, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, DELEGATION_CAP_CODES, DELEGATION_CONCURRENCY_CAP, DELEGATION_SESSION_CAP, delegationCapDispositionOf, DRAINING_ERROR_CODE, ENGINE_STOP_REASONS, engineStopReasonToCc, ENV_LIFETIME_EXPIRED, FLEET_LEASE_UNAVAILABLE, GATE_PARKED_ERROR_CODE, idempotencyPayloadMismatchContent, imageInvalidFailureNoteOf, isConfigRefusalCode, isCorruptSessionCode, isDecideParkMovedCode, isDelegationCapCode, isIdempotencyPayloadMismatchCode, isInterruptedToolEndCode, isLimitsExceededCode, isRewindFamilyCode, isRulesRefusalCode, isStatusDerivedCoarseCode, isWorkflowParkRefusalCode, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, MCP_SERVER_REVOKED, MODEL_FALLBACK_INHERIT_NO_TIER_BINDING, operatorGateRefusalContent, OUTPUT_INVALID, PARKED_RESUME_STARTUP_FAILED, REQUEST_AUTONOMY_LANE_REFUSED, RESUME_AT_ERROR_CODE_PREFIX, RESUME_CONTEXT_UNAVAILABLE, RESUME_ENV_FAILED, RESUME_PLACEMENT_MISMATCH, RESUME_POLICY_FOLD_CODE, RESUME_PREFLIGHT_REJECTED, RESUME_REOPEN_CODES, RESUME_RETRY_LATER_CODES, RESUME_TOOL_CONTRACT_MISMATCH, RESUME_TOOL_UNAVAILABLE, RESUME_USAGE_WINDOW_EXHAUSTED, REWIND_ERROR_CODE_PREFIXES, RULES_LEGACY_TOOL_NAME, RUN_DEATH_VERDICT_CODES, RUN_ORPHANED, RUN_STALLED, runDeathVerdictNoteOf, SCENARIO_ASSIGNMENT_UNKNOWN_ERROR_CODE, SCENARIO_NOT_ALLOWED_ERROR_CODE, STATUS_DERIVED_COARSE_CODES, STOP_CONFLICT_CODES, STREAM_MAX_DURATION, TOOL_END_INTERRUPTED_NEVER_STARTED, TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN, USAGE_WINDOW_EXHAUSTED, WORKFLOW_PARK_REFUSAL_CODES, } from './engineErrorCodes.js';
88
88
  export * from './agentsWireCaps.js';
89
+ export { engineToolDirectoryOf, excludeToolsAgainstDirectory } from './engineToolDirectory.js';
89
90
  export * from './attachmentsWireCaps.js';
90
91
  export * from './clientContextWireCaps.js';
91
92
  export * from './cloudConfigWireCaps.js';
@@ -200,6 +201,7 @@ export { _resetHitlHostSurfaceForTest, APPROVAL_PARKING_WARN_TEXT, CANCEL_DENY_B
200
201
  export * from './hitl/toolApprovalWire.js';
201
202
  export * from './hitl/editedRuleTextPrecheck.js';
202
203
  export * from './coreValuePorts.js';
204
+ export { ruleToolNameVerdictOf } from './protocolSegment.js';
203
205
  export * from './hitl/askGateWire.js';
204
206
  export * from './hitl/planReviewWire.js';
205
207
  export { PLAN_REVIEW_QUESTION_ID_PREFIX, REOPEN_ID_TAIL, approvalCallKey, askGateQuestionId, planReviewQuestionId, liveFrameCallKey, armedKeyFromQuestionId, } from './hitl/gateIdentity.js';
@@ -21,6 +21,7 @@ export interface LiveModelCatalog {
21
21
  readonly name?: string;
22
22
  };
23
23
  droppedEntries?: readonly LiveModelDroppedEntry[];
24
+ candidateRejected?: unknown;
24
25
  }
25
26
  export declare function setLiveModelCatalog(next: LiveModelCatalog | null): void;
26
27
  export declare function setLiveModelCatalogRefresher(fn: (() => Promise<LiveModelCatalog | null>) | null): void;
@@ -69,6 +70,18 @@ export type ModelDroppedEntriesReading = {
69
70
  readonly why: 'no_catalog' | 'malformed' | 'unreadable';
70
71
  };
71
72
  export declare function droppedModelEntriesOf(catalog?: LiveModelCatalog | null): ModelDroppedEntriesReading;
73
+ export type ModelCandidateRejectedReading = {
74
+ readonly kind: 'not_reported';
75
+ } | {
76
+ readonly kind: 'rejected';
77
+ readonly domains: readonly string[];
78
+ readonly at: string;
79
+ readonly source: string;
80
+ } | {
81
+ readonly kind: 'unreadable';
82
+ };
83
+ export declare function modelCandidateRejectedOf(catalog?: LiveModelCatalog | null): ModelCandidateRejectedReading;
84
+ export declare function modelCandidateRejectedContent(reading: ModelCandidateRejectedReading): string | undefined;
72
85
  export interface RoutePairingVerdict {
73
86
  verdict: 'ok' | 'broken' | 'unknown';
74
87
  posture?: string;
@@ -228,6 +228,59 @@ export function droppedModelEntriesOf(catalog = getLiveModelCatalog()) {
228
228
  return unknownDropped('unreadable');
229
229
  }
230
230
  }
231
+ export function modelCandidateRejectedOf(catalog = getLiveModelCatalog()) {
232
+ const unreadable = Object.freeze({ kind: 'unreadable' });
233
+ try {
234
+ if (catalog === null || typeof catalog !== 'object' || Array.isArray(catalog))
235
+ return Object.freeze({ kind: 'not_reported' });
236
+ if (!Object.hasOwn(catalog, 'candidateRejected'))
237
+ return Object.freeze({ kind: 'not_reported' });
238
+ const d = Object.getOwnPropertyDescriptor(catalog, 'candidateRejected');
239
+ if (d === undefined || !('value' in d))
240
+ return unreadable;
241
+ const v = d.value;
242
+ if (v === undefined)
243
+ return Object.freeze({ kind: 'not_reported' });
244
+ if (v === null || typeof v !== 'object' || Array.isArray(v))
245
+ return unreadable;
246
+ const own = (k) => {
247
+ const od = Object.getOwnPropertyDescriptor(v, k);
248
+ return od !== undefined && 'value' in od ? od.value : undefined;
249
+ };
250
+ const rawDomains = own('domains');
251
+ const at = own('at');
252
+ const source = own('source');
253
+ if (!Array.isArray(rawDomains) || typeof at !== 'string' || at.length === 0 || typeof source !== 'string' || source.length === 0)
254
+ return unreadable;
255
+ const n = Object.getOwnPropertyDescriptor(rawDomains, 'length')?.value;
256
+ if (typeof n !== 'number' || !Number.isSafeInteger(n) || n <= 0)
257
+ return unreadable;
258
+ const domains = [];
259
+ for (let i = 0; i < n; i += 1) {
260
+ const id = Object.getOwnPropertyDescriptor(rawDomains, String(i));
261
+ if (id === undefined || !('value' in id) || typeof id.value !== 'string' || id.value.length === 0)
262
+ return unreadable;
263
+ domains.push(id.value);
264
+ }
265
+ return Object.freeze({ kind: 'rejected', domains: Object.freeze(domains), at, source });
266
+ }
267
+ catch {
268
+ return unreadable;
269
+ }
270
+ }
271
+ const CONFIG_DOMAIN_WORD = /^[a-z][a-z0-9_.-]{0,63}$/;
272
+ export function modelCandidateRejectedContent(reading) {
273
+ try {
274
+ if (reading === null || typeof reading !== 'object' || reading.kind !== 'rejected')
275
+ return undefined;
276
+ const named = reading.domains.filter((w) => CONFIG_DOMAIN_WORD.test(w));
277
+ const which = named.length > 0 && named.length === reading.domains.length ? ` (${named.join(', ')})` : '';
278
+ return `The deployment refused its most recent configuration change${which} and is still running on the configuration before it — models or settings added by that change are not in effect`;
279
+ }
280
+ catch {
281
+ return undefined;
282
+ }
283
+ }
231
284
  const ROUTE_PAIRING_OK = new Set(['ok:per-model', 'ok:paired', 'ok:unpinned', 'ok:keyless']);
232
285
  const ROUTE_PAIRING_BROKEN = new Set(['broken:credential_mismatch', 'broken:credential_missing']);
233
286
  export function routePairingVerdict(v) {
@@ -256,6 +309,7 @@ export function readLiveModelCatalog(body) {
256
309
  const defaultKey = envelopeKey(body, 'default');
257
310
  const defaultModelKey = envelopeKey(body, 'defaultModel');
258
311
  const droppedKey = envelopeKey(body, 'droppedEntries');
312
+ const candidateKey = envelopeKey(body, 'candidateRejected');
259
313
  const raw = modelsKey.present ? modelsKey.value : undefined;
260
314
  if (!Array.isArray(raw))
261
315
  return unreadableCatalog('models_not_array');
@@ -292,6 +346,8 @@ export function readLiveModelCatalog(body) {
292
346
  const dropped = droppedEntriesCopy(droppedKey.value);
293
347
  out.droppedEntries = dropped;
294
348
  }
349
+ if (candidateKey.present && candidateKey.value !== undefined)
350
+ out.candidateRejected = frozenJsonCopyOf(candidateKey.value) ?? null;
295
351
  return Object.freeze({ kind: 'read', catalog: Object.freeze(out), unreadableRows, ...(defaultModelMalformed ? { defaultModelMalformed: true } : {}) });
296
352
  }
297
353
  catch {
@@ -1,5 +1,7 @@
1
1
  export type McpProbeReading = {
2
2
  kind: 'unobserved';
3
+ } | {
4
+ kind: 'unreadable';
3
5
  } | {
4
6
  kind: 'not_reported';
5
7
  } | {
@@ -1,5 +1,5 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
- import { createEngineCapReader } from './engineCapReader.js';
2
+ import { createEngineCapReader, unreadableReadingDetail } from './engineCapReader.js';
3
3
  import { ownDataField } from './ownKey.js';
4
4
  export function projectMcpProbeCapability(caps) {
5
5
  try {
@@ -19,7 +19,6 @@ export function projectMcpProbeCapability(caps) {
19
19
  const reader = createEngineCapReader({
20
20
  name: 'mcpProbe',
21
21
  project: projectMcpProbeCapability,
22
- makeUnobserved: () => ({ kind: 'unobserved' }),
23
22
  });
24
23
  export function observedMcpProbe(baseUrl = engineWireTarget()?.baseUrl) {
25
24
  return reader.observed(baseUrl);
@@ -33,6 +32,8 @@ export function mcpProbeAvailable(reading) {
33
32
  }
34
33
  export function mcpProbeDoctorDetail(reading) {
35
34
  switch (reading.kind) {
35
+ case 'unreadable':
36
+ return unreadableReadingDetail('per-server MCP status face');
36
37
  case 'unobserved':
37
38
  return ('per-server MCP status face not observed — the engine reports whether it has one on /v1/capabilities; ' +
38
39
  'this process has no usable capabilities reading cached for it (none received, the last one was unreadable, or the last one was discarded when the engine connection was reset; this process cannot tell which)');