@sema-agent/client-core 0.109.0 → 0.110.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 +173 -0
  2. package/README.md +46 -22
  3. package/dist/adapt/arms.js +20 -7
  4. package/dist/adapter/downstream/eventToSdkMessage.js +11 -6
  5. package/dist/declared/supportFloorDeclared.js +1 -1
  6. package/dist/displayUntrusted.js +132 -14
  7. package/dist/engineErrorCodes.d.ts +3 -0
  8. package/dist/engineErrorCodes.js +3 -0
  9. package/dist/engineHealthFacts.d.ts +9 -0
  10. package/dist/engineHealthFacts.js +21 -1
  11. package/dist/engineInlineTaskStats.d.ts +4 -3
  12. package/dist/engineInlineTaskStats.js +18 -2
  13. package/dist/engineNoticeCodes.d.ts +10 -0
  14. package/dist/engineNoticeCodes.js +33 -1
  15. package/dist/engineRepoint.d.ts +140 -0
  16. package/dist/engineRepoint.js +285 -0
  17. package/dist/engineRowRef.js +2 -0
  18. package/dist/engineSessionMessages.d.ts +2 -1
  19. package/dist/engineSessionMessages.js +5 -0
  20. package/dist/errorSupplementRoles.js +2 -1
  21. package/dist/fleet/fleetProjection.js +3 -2
  22. package/dist/generated/engineFactTables.d.ts +2 -0
  23. package/dist/generated/engineFactTables.js +12 -0
  24. package/dist/generated/sdkFactTables.d.ts +1 -0
  25. package/dist/generated/sdkFactTables.js +4 -0
  26. package/dist/hitl/approvalAskers.d.ts +6 -0
  27. package/dist/hitl/approvalAskers.js +30 -0
  28. package/dist/hitl/approvalCardReasons.js +6 -3
  29. package/dist/hitl/approvalRequestFrameReading.d.ts +7 -0
  30. package/dist/hitl/approvalRequestFrameReading.js +11 -0
  31. package/dist/hitl/approvalResolution.d.ts +8 -1
  32. package/dist/hitl/approvalResolution.js +4 -0
  33. package/dist/hitl/askGateWire.js +0 -2
  34. package/dist/hitl/automaticAnswerVerdict.js +2 -2
  35. package/dist/hitl/decisionConflict.js +6 -3
  36. package/dist/hitl/decisionRefusal.js +1 -0
  37. package/dist/hitl/decisionSend.d.ts +3 -0
  38. package/dist/hitl/decisionSend.js +29 -11
  39. package/dist/hitl/editedApprovalAcceptance.d.ts +25 -0
  40. package/dist/hitl/editedApprovalAcceptance.js +26 -0
  41. package/dist/hitl/frameRouter.js +4 -18
  42. package/dist/hitl/gateLedger.d.ts +0 -4
  43. package/dist/hitl/gateLedger.js +0 -19
  44. package/dist/hitl/hitlBridge.d.ts +1 -0
  45. package/dist/hitl/hitlBridge.js +4 -4
  46. package/dist/hitl/hitlHostSurface.d.ts +1 -0
  47. package/dist/hitl/hitlHostSurface.js +7 -2
  48. package/dist/hitl/hostWithdrawal.d.ts +15 -0
  49. package/dist/hitl/hostWithdrawal.js +38 -0
  50. package/dist/hitl/parkResolver.js +25 -9
  51. package/dist/hitl/persistedRulesWire.js +2 -2
  52. package/dist/hitl/planReviewWire.js +14 -4
  53. package/dist/hitl/sessionPolicyWire.js +6 -4
  54. package/dist/hitl/standingRows.d.ts +1 -0
  55. package/dist/hitl/standingRows.js +15 -1
  56. package/dist/hitl/toolApprovalWire.d.ts +35 -8
  57. package/dist/hitl/toolApprovalWire.js +235 -33
  58. package/dist/hooksWireCaps.js +31 -1
  59. package/dist/hostTurnSettings.d.ts +10 -4
  60. package/dist/hostTurnSettings.js +112 -5
  61. package/dist/i18n/messages.en.d.ts +83 -0
  62. package/dist/i18n/messages.en.js +86 -2
  63. package/dist/i18n/messages.zh.js +96 -2
  64. package/dist/index.d.ts +21 -7
  65. package/dist/index.js +14 -4
  66. package/dist/inheritEnvCapability.js +2 -0
  67. package/dist/inputAuthor.d.ts +16 -0
  68. package/dist/inputAuthor.js +44 -0
  69. package/dist/interruptRefusalNote.d.ts +2 -0
  70. package/dist/interruptRefusalNote.js +17 -0
  71. package/dist/liveModelCatalog.d.ts +2 -0
  72. package/dist/liveModelCatalog.js +21 -7
  73. package/dist/liveQuestionStore.d.ts +4 -1
  74. package/dist/liveQuestionStore.js +12 -3
  75. package/dist/mcpEngineLeg.d.ts +3 -0
  76. package/dist/mcpEngineLeg.js +38 -1
  77. package/dist/mcpPanel.js +2 -0
  78. package/dist/mcpReconnect.d.ts +9 -1
  79. package/dist/mcpReconnect.js +121 -16
  80. package/dist/modelCapabilityProbe.js +4 -3
  81. package/dist/modsFace.d.ts +8 -1
  82. package/dist/modsFace.js +27 -0
  83. package/dist/notifications.d.ts +17 -6
  84. package/dist/notifications.js +67 -19
  85. package/dist/ownKey.d.ts +0 -5
  86. package/dist/ownKey.js +0 -7
  87. package/dist/peerFrames.d.ts +40 -2
  88. package/dist/peerFrames.js +158 -3
  89. package/dist/pluginHooksWire.d.ts +2 -1
  90. package/dist/pluginHooksWire.js +56 -1
  91. package/dist/replayBody.js +10 -2
  92. package/dist/request/taskRequest.d.ts +5 -0
  93. package/dist/request/taskRequest.js +138 -21
  94. package/dist/resumeRefusalCopy.d.ts +1 -3
  95. package/dist/resumeRefusalCopy.js +2 -1
  96. package/dist/retryStatus.d.ts +2 -2
  97. package/dist/retryStatus.js +2 -0
  98. package/dist/seam.d.ts +12 -1
  99. package/dist/seam.js +7 -1
  100. package/dist/seatContract.d.ts +86 -9
  101. package/dist/seatContract.js +196 -7
  102. package/dist/sessionBackground.js +2 -1
  103. package/dist/sessionBackgroundHandoff.js +2 -1
  104. package/dist/sessionEngine.d.ts +2 -0
  105. package/dist/sessionEngine.js +111 -0
  106. package/dist/sessionMemoryStatus.d.ts +2 -1
  107. package/dist/sessionSyncFileHistory.d.ts +4 -0
  108. package/dist/sessionSyncFileHistory.js +28 -0
  109. package/dist/sseIdleTriage.d.ts +13 -1
  110. package/dist/sseIdleTriage.js +24 -6
  111. package/dist/subagent/engineSubagentTail.js +6 -0
  112. package/dist/terminalStatuses.d.ts +1 -0
  113. package/dist/terminalStatuses.js +4 -1
  114. package/dist/turnFailurePresentation.js +9 -2
  115. package/dist/typePins.d.ts +11 -0
  116. package/dist/usageAnalytics.d.ts +17 -0
  117. package/dist/usageAnalytics.js +44 -2
  118. package/dist/wireFailureShape.d.ts +2 -5
  119. package/dist/wireFailureShape.js +10 -20
  120. package/dist/wireRefusalCopy.d.ts +10 -0
  121. package/dist/wireRefusalCopy.js +76 -0
  122. package/docs/INTEGRATION-CLIENTS.md +2126 -20
  123. package/package.json +3 -3
@@ -86,11 +86,17 @@ async function surfaceGateAndDecide(deps, taskId, askArgsByCall, signal, parkGat
86
86
  };
87
87
  }
88
88
  const questionId = askGateQuestionId(approvalCallKey(gatedCallId, taskId));
89
+ let withdrawn;
89
90
  const answer = await new Promise(resolve => {
90
91
  const unregister = registerLocalQuestionResponder(questionId, async (_id, a) => {
91
92
  cleanup();
92
93
  resolve(a);
93
94
  return { ok: true };
95
+ }, (w) => {
96
+ withdrawn = w;
97
+ cleanup();
98
+ publishQuestionFrame({ type: 'question_complete', questionId });
99
+ resolve(null);
94
100
  });
95
101
  const onAbort = () => {
96
102
  cleanup();
@@ -109,6 +115,10 @@ async function surfaceGateAndDecide(deps, taskId, askArgsByCall, signal, parkGat
109
115
  onPresented?.();
110
116
  publishQuestionFrame({ type: 'question', questionId, questions, ...(questionsFromModelCall ? { _sema_questionsFromModelCall: true } : {}) });
111
117
  });
118
+ if (withdrawn !== undefined) {
119
+ hostLog('debug', `liveHitlAskWire: question-withdrawn-by-host card=${questionId} verdict=${withdrawn.rowVerdict.kind}`);
120
+ return { kind: 'not_sent', ...at, cause: 'withdrawn', toldBy: withdrawn.toldBy, rowVerdict: withdrawn.rowVerdict };
121
+ }
112
122
  const bridge = new HitlBridge(deps.client, taskId, deps.onDecideOperation ? { onDecideOperation: deps.onDecideOperation } : undefined);
113
123
  if (answer === null) {
114
124
  observeCancelByDeny(bridge.decideTool({ decision: 'deny', reason: INTERRUPT_DENY_REASON }, gatedCallId, undefined, pending), taskId);
@@ -155,7 +165,7 @@ function isFetchStepNoPending(outcome) {
155
165
  return outcome.kind === 'not_sent' && outcome.cause === 'no_pending' && outcome.gatedCallId === undefined;
156
166
  }
157
167
  function isHumanDisposition(r) {
158
- return r.kind === 'decided' || (r.kind === 'unsettled' && r.cause === 'interrupted') || (r.kind === 'not_sent' && r.cause === 'retracted');
168
+ return r.kind === 'decided' || (r.kind === 'unsettled' && r.cause === 'interrupted') || (r.kind === 'not_sent' && (r.cause === 'retracted' || r.cause === 'withdrawn'));
159
169
  }
160
170
  function failureReasonOf(r) {
161
171
  if (r.kind === 'decided')
@@ -282,7 +292,8 @@ export async function resolvePark(park, ctx) {
282
292
  if (outcome.kind !== 'decided') {
283
293
  hostLog('debug', `liveHitlAskWire: gate not decided (${outcome.kind}/${outcome.cause}: ${failureReasonOf(outcome)}) — fail-soft to suspended terminal`);
284
294
  const interrupted = outcome.kind === 'unsettled' && outcome.cause === 'interrupted';
285
- const failedReason = interrupted
295
+ const toldByHost = outcome.kind === 'not_sent' && outcome.cause === 'withdrawn';
296
+ const failedReason = interrupted || toldByHost
286
297
  ? undefined
287
298
  : outcome.kind === 'not_sent' && outcome.cause === 'retracted'
288
299
  ? 'the approval card was retracted by the host without a decision (nothing was sent; the run stays parked and remains decidable elsewhere)'
@@ -312,13 +323,19 @@ export async function resolvePark(park, ctx) {
312
323
  };
313
324
  }
314
325
  function failsoftWayOutOf(outcome) {
326
+ if (outcome === undefined)
327
+ return 'card';
328
+ if (typeof outcome !== 'object' || outcome === null)
329
+ return 'speak';
315
330
  if (outcome.kind === 'not_sent' && (outcome.cause === 'row_unresumable' || (outcome.cause === 'safety_stop' && outcome.safetyCode === 'binding_missing')))
316
331
  return 'reason';
317
- if (outcome.kind === 'unsettled' && outcome.cause === 'engine_refused' && refusedParkFromError(outcome.refusal) !== null)
332
+ if (outcome.kind === 'unsettled' && outcome.cause === 'engine_refused' && (refusedParkFromError(outcome.refusal) !== null || outcome.refusal?.conflict === 'row_integrity'))
318
333
  return 'cancel';
334
+ if (outcome.kind === 'unsettled' && outcome.cause === 'engine_refused')
335
+ return 'speak';
319
336
  return 'card';
320
337
  }
321
- function failsoftReasonSentence(park, failedReason, terminal, wayOut = 'card') {
338
+ function failsoftReasonSentence(park, failedReason, terminal, wayOut) {
322
339
  if (terminal !== undefined)
323
340
  return terminal.errorMessage;
324
341
  if (failedReason === undefined)
@@ -328,10 +345,9 @@ function failsoftReasonSentence(park, failedReason, terminal, wayOut = 'card') {
328
345
  return renderMessage(msg('approval.park.stillParked', { gate, reason: failedReason }));
329
346
  if (wayOut === 'cancel')
330
347
  return renderMessage(msg('approval.park.refusedNotResumable', { gate, reason: failedReason }));
331
- return (`${park.gate === 'fs' ? 'Tool approval' : 'AskUserQuestion'} gate could not be answered: ${failedReason}` +
332
- ' — the run is still parked on this approval: decide it on the card when it is shown again, or cancel the run.');
348
+ return renderMessage(msg(wayOut === 'speak' ? 'approval.park.resume.speak' : 'approval.park.resume.card', { gate, reason: failedReason }));
333
349
  }
334
- function failsoftEvents(park, ctx, gateAbortedByUser, failedReason, terminal, noDecisionSurface = false, wayOut = 'card') {
350
+ function failsoftEvents(park, ctx, gateAbortedByUser, failedReason, terminal, noDecisionSurface, wayOut) {
335
351
  const events = [
336
352
  ...flushHeldWithInterruptRewrite(ctx.led, {
337
353
  terminal: park.pendingDone,
@@ -360,12 +376,12 @@ export function stalledTerminal(park, ctx, stalledRounds, lastStallReason, decid
360
376
  `stopped re-attaching. Your last decision was accepted; sema did not observe the run move on after it — check the ` +
361
377
  `transcript, decide the call again if the card comes back, or cancel the run.`;
362
378
  hostLog('debug', `liveHitlAskWire: ${errorMessage}`);
363
- return { kind: 'failsoft', events: failsoftEvents(park, ctx, false, undefined, { errorCode: 'hitl_stalled', errorMessage }) };
379
+ return { kind: 'failsoft', events: failsoftEvents(park, ctx, false, undefined, { errorCode: 'hitl_stalled', errorMessage }, false, failsoftWayOutOf(undefined)) };
364
380
  }
365
381
  const reason = `the run stayed parked across ${stalledRounds} consecutive re-attach rounds without any host progress ` +
366
382
  `(last: ${lastStallReason ?? 'the engine kept parking'})`;
367
383
  hostLog('debug', `liveHitlAskWire: ${reason} — fail-soft after the round committed`);
368
- return { kind: 'failsoft', events: failsoftEvents(park, ctx, false, reason) };
384
+ return { kind: 'failsoft', events: failsoftEvents(park, ctx, false, reason, undefined, false, failsoftWayOutOf(undefined)) };
369
385
  }
370
386
  function notifyParkReattach(ctx, attempt, max, reason) {
371
387
  invokeHostCallbackIsolated('liveHitlAskWire: onParkReattach', () => {
@@ -7,7 +7,7 @@ import { hostLog } from '../host.js';
7
7
  import { msg, renderMessage } from '../i18n/translate.js';
8
8
  import { appendOwnElement, guardedRead, readOwnDataValue } from '../ownKey.js';
9
9
  import { observedPermissionRulesWrite, permissionRulesWriteAvailable } from '../permissionRulesWriteCapability.js';
10
- import { isToolApprovalRespondReplayed, readToolApprovalRespondAck } from './toolApprovalWire.js';
10
+ import { isToolApprovalRespondParkedRedeemed, isToolApprovalRespondReplayed, readToolApprovalRespondAck } from './toolApprovalWire.js';
11
11
  export function persistedRulesLaneAvailable(baseUrl) {
12
12
  return engineCapTrue(baseUrl, 'permissionRules');
13
13
  }
@@ -637,7 +637,7 @@ export function classifySkippedReason(reason) {
637
637
  }
638
638
  export function readRulePersistOutcome(ack) {
639
639
  const parsed = readToolApprovalRespondAck(ack);
640
- if (parsed === undefined || isToolApprovalRespondReplayed(parsed))
640
+ if (parsed === undefined || isToolApprovalRespondReplayed(parsed) || isToolApprovalRespondParkedRedeemed(parsed))
641
641
  return { state: 'unknown' };
642
642
  if (parsed.rulePersisted === true)
643
643
  return { state: 'persisted' };
@@ -498,11 +498,15 @@ export function armPlanReviewApproval(result, sessionKey, opts) {
498
498
  armedPlanReviews.set(taskId, instance);
499
499
  armedTaskId = taskId;
500
500
  let unregister = () => { };
501
+ const onWithdraw = () => {
502
+ hostLog('debug', `planReviewWire: card-withdrawn-by-host task=${taskId} card=${questionId}`);
503
+ retireArmedPlanReview(taskId, instance);
504
+ };
501
505
  const responder = async (_id, answer) => {
502
506
  const choice = planReviewAnswerChoiceOf(questionId, answer);
503
507
  if (choice === 'inadmissible') {
504
508
  if (armedPlanReviews.get(taskId) === instance && !hasLocalQuestionResponder(questionId))
505
- unregister = registerLocalQuestionResponder(questionId, responder);
509
+ unregister = registerLocalQuestionResponder(questionId, responder, onWithdraw);
506
510
  hostLog('debug', `planReviewWire: answer-inadmissible card=${questionId}`);
507
511
  return { ok: false, inadmissible: true };
508
512
  }
@@ -523,7 +527,7 @@ export function armPlanReviewApproval(result, sessionKey, opts) {
523
527
  void decidePlanReviewFor(taskId, decided, modeAfter, cardDelivery, facts);
524
528
  return { ok: true };
525
529
  };
526
- unregister = registerLocalQuestionResponder(questionId, responder);
530
+ unregister = registerLocalQuestionResponder(questionId, responder, onWithdraw);
527
531
  publishArmedPlanReviewCard(instance);
528
532
  hostLog('debug', `planReviewWire: approval card armed for parked plan (task ${taskId})`);
529
533
  }
@@ -1160,11 +1164,17 @@ function mintPlanReviewReopenCard(taskId, opts, sessionKey, receiptMs, taken) {
1160
1164
  });
1161
1165
  const activeKey = `${sessionKey}\u0000${canonicalId}`;
1162
1166
  let unregister = () => { };
1167
+ const onWithdraw = () => {
1168
+ hostLog('debug', `planReviewWire: card-withdrawn-by-host task=${taskId} card=${questionId}`);
1169
+ if (activeReopenResponders.get(activeKey)?.questionId === questionId)
1170
+ activeReopenResponders.delete(activeKey);
1171
+ publishQuestionFrameFor(sessionKey, { type: 'question_complete', questionId });
1172
+ };
1163
1173
  const responder = async (_id, answer) => {
1164
1174
  const choice = planReviewAnswerChoiceOf(questionId, answer);
1165
1175
  if (choice === 'inadmissible') {
1166
1176
  if (activeReopenResponders.get(activeKey)?.questionId === questionId && !hasLocalQuestionResponder(questionId)) {
1167
- unregister = registerLocalQuestionResponder(questionId, responder);
1177
+ unregister = registerLocalQuestionResponder(questionId, responder, onWithdraw);
1168
1178
  }
1169
1179
  hostLog('debug', `planReviewWire: answer-inadmissible card=${questionId}`);
1170
1180
  return { ok: false, inadmissible: true };
@@ -1190,7 +1200,7 @@ function mintPlanReviewReopenCard(taskId, opts, sessionKey, receiptMs, taken) {
1190
1200
  return { ok: true };
1191
1201
  };
1192
1202
  const shape = cardShapeOf(facts, false);
1193
- unregister = registerLocalQuestionResponder(questionId, responder);
1203
+ unregister = registerLocalQuestionResponder(questionId, responder, onWithdraw);
1194
1204
  activeReopenResponders.set(activeKey, { questionId, unregister: () => unregister(), shape });
1195
1205
  const receipt = waitForGateArmedFor(sessionKey, [questionId], receiptMs);
1196
1206
  publishQuestionFrameFor(sessionKey, planReviewQuestionFrame(questionId, REOPEN_QUESTION, shape, facts));
@@ -701,10 +701,12 @@ export function sessionPolicyRemovalNotice(outcome, deployment) {
701
701
  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.';
702
702
  case 'judge_failed':
703
703
  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.';
704
- case 'loosen_forbidden':
705
- if (deploymentHasNoOperator(deployment))
706
- return renderMessage(msg('rules.sessionPolicy.deployment.noOperator.removeLoosenForbidden'));
707
- 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.';
704
+ case 'loosen_forbidden': {
705
+ const stem = msg('rules.sessionPolicy.remove.loosenForbiddenStem');
706
+ return deploymentHasNoOperator(deployment)
707
+ ? renderMessage(msg('rules.sessionPolicy.deployment.noOperator.removeLoosenForbidden', { stem }))
708
+ : renderMessage(msg('rules.sessionPolicy.remove.loosenForbidden', { stem }));
709
+ }
708
710
  case 'conflict':
709
711
  return 'This session’s rule record was changed by someone else while the refused entries were being removed, twice in a row — nothing was changed. Try again once the other change has finished.';
710
712
  case 'read_failed':
@@ -18,6 +18,7 @@ export interface StandingRowsHostFacts {
18
18
  }
19
19
  export declare function standingRowsOf(card: object | null | undefined, host?: StandingRowsHostFacts | null): StandingRows;
20
20
  export declare function seatSessionRowOf(card: object | null | undefined, requestId: string | undefined): boolean;
21
+ export declare function seatAllowNoteCarriedOf(card: object | null | undefined, requestId: string | undefined): boolean;
21
22
  export type RememberOffer = 'offerable' | 'refused' | 'unknown';
22
23
  export interface RememberOfferable {
23
24
  readonly session: RememberOffer;
@@ -1,6 +1,6 @@
1
1
  import { DEPLOYMENT_LIST_ASK_CLASSES, readAskClassPairState } from './askClassPair.js';
2
2
  import { askLevelVerdict } from './automaticAnswerVerdict.js';
3
- import { readApprovalCardWord, readRuleOffers } from './toolApprovalWire.js';
3
+ import { answerCarriage, readApprovalCardWord, readRuleOffers } from './toolApprovalWire.js';
4
4
  import { CORE_SKILL_TOOL_NAME } from '../generated/toolNameTables.js';
5
5
  import { inSlotReadOf, inValueOf } from '../wireFailureShape.js';
6
6
  import { toolPermissionRequestIdDomain } from '../seatContract.js';
@@ -153,6 +153,20 @@ export function seatSessionRowOf(card, requestId) {
153
153
  return false;
154
154
  }
155
155
  }
156
+ export function seatAllowNoteCarriedOf(card, requestId) {
157
+ if (typeof card !== 'object' || card === null)
158
+ return false;
159
+ try {
160
+ if (Object.hasOwn(card, 'requestId'))
161
+ return false;
162
+ if (toolPermissionRequestIdDomain(requestId) !== 'durable:')
163
+ return false;
164
+ return answerCarriage(card).allowNote === 'model';
165
+ }
166
+ catch {
167
+ return false;
168
+ }
169
+ }
156
170
  const SESSION_OFFER = Object.freeze({
157
171
  given: 'offerable',
158
172
  card_unreadable: 'unknown',
@@ -1,6 +1,6 @@
1
1
  import { type HitlClientLike, type DecideOperationObserver } from './hitlBridge.js';
2
- import { type ApprovalAskReason } from './approvalAskers.js';
3
- export type { ApprovalAskReason, ApprovalAskReasonByHook, ApprovalAskReasonByPolicy } from './approvalAskers.js';
2
+ import { type ApprovalAskReason, type ApprovalRequestedBy } from './approvalAskers.js';
3
+ export type { ApprovalAskReason, ApprovalAskReasonByHook, ApprovalAskReasonByPolicy, ApprovalRequestedBy } from './approvalAskers.js';
4
4
  import { readApprovalCardWord, type ApprovalCardWord } from './approvalCardReading.js';
5
5
  import { type ApprovalAllowRuleShadow } from './allowRuleShadow.js';
6
6
  import { CORE_PERSISTED_RULE_MATCHES } from '../generated/engineFactTables.js';
@@ -8,6 +8,7 @@ import type { UiLanguage } from '../env/uiLanguage.js';
8
8
  import type { SessionRuleInertReason } from './sessionPolicyWire.js';
9
9
  import { type ApprovalCardClaim } from './approvalHolds.js';
10
10
  import { type ApprovalResolution } from './approvalResolution.js';
11
+ import { type HostWithdrawal } from './hostWithdrawal.js';
11
12
  import { type ApprovalMandateWord } from '../gateVocabulary.js';
12
13
  import type { ToolPermissionRequest } from '../seatContract.js';
13
14
  import { type ApprovalDecidedByReading } from '../approvalDecidedByCapability.js';
@@ -88,13 +89,18 @@ export type ApprovalCardDecision = ApprovalCardAllowDecision | ApprovalCardDenyD
88
89
  } | {
89
90
  kind: typeof RETRACTED_CARD_DECISION_KIND;
90
91
  reason?: string;
91
- };
92
+ } | ({
93
+ kind: typeof WITHDRAWN_CARD_DECISION_KIND;
94
+ } & HostWithdrawal);
92
95
  export declare const RETRACTED_CARD_DECISION_KIND: "retracted";
96
+ export declare const WITHDRAWN_CARD_DECISION_KIND: "withdrawn";
97
+ export type ApprovalInputSource = 'record' | 'stream';
93
98
  export interface ApprovalCardRequest {
94
99
  toolName: string;
95
100
  args: object;
96
101
  callKey: string;
97
102
  toolCallId?: string;
103
+ taskId?: string;
98
104
  signal?: AbortSignal;
99
105
  workerBadge?: {
100
106
  name: string;
@@ -103,6 +109,7 @@ export interface ApprovalCardRequest {
103
109
  wireNote?: string;
104
110
  argsUnavailable?: true;
105
111
  argsRewritten?: true;
112
+ inputSource?: ApprovalInputSource;
106
113
  governanceForced?: true;
107
114
  delegation?: ToolApprovalDelegation;
108
115
  ruleOffers?: RuleOfferReading[];
@@ -132,6 +139,7 @@ export interface ApprovalCardRequest {
132
139
  classes?: readonly string[];
133
140
  agentId?: string;
134
141
  askReasons?: readonly ApprovalAskReason[];
142
+ requestedBy?: ApprovalRequestedBy;
135
143
  boundGrants?: BoundSkillGrantsWire;
136
144
  grantBinding?: ApprovalGrantBinding;
137
145
  unreadableEvidence?: readonly string[];
@@ -198,7 +206,7 @@ export declare function readApprovalMandate(v: {
198
206
  readonly mandate?: string;
199
207
  } | undefined | null): ApprovalMandateWord | undefined;
200
208
  export { readApprovalCardWord };
201
- export declare function toolPermissionRequestAskBits(card: object | null | undefined, requestId?: string): Pick<ToolPermissionRequest, 'mandated' | 'mandate' | 'origin' | 'ruleOffersAbsence' | 'askClass' | 'classes' | 'sessionRow'>;
209
+ export declare function toolPermissionRequestAskBits(card: object | null | undefined, requestId?: string): Pick<ToolPermissionRequest, 'mandated' | 'mandate' | 'origin' | 'ruleOffersAbsence' | 'askClass' | 'classes' | 'sessionRow' | 'probeReason' | 'probeCause' | 'feedbackCapable' | 'requestedBy' | 'frameReading' | 'inputSource'>;
202
210
  export declare function isFromSubagent(frame: ToolApprovalFrame): boolean;
203
211
  export type ToolApprovalRespondDecision = SdkToolApprovalDecision;
204
212
  export declare const RESPOND_DECISIONS: readonly ["allow", "allow_session", "deny"];
@@ -212,18 +220,26 @@ export interface RespondAnswerPayload extends Pick<RespondToolApprovalOpts, 'upd
212
220
  export interface DecideApprovePayload extends Pick<ApprovalCardAllowDecision, 'updatedInput'> {
213
221
  readonly decision: 'approve';
214
222
  readonly remember?: 'session';
223
+ readonly feedback?: string;
215
224
  }
216
225
  export interface DecideDenyPayload {
217
226
  readonly decision: 'deny';
218
227
  readonly reason: string;
219
228
  }
220
229
  export type DecideAnswerPayload = DecideApprovePayload | DecideDenyPayload;
230
+ export declare function allowNoteReadingOf(answer: object): {
231
+ readonly kind: 'text';
232
+ readonly text: string;
233
+ } | {
234
+ readonly kind: 'absent' | 'blank' | 'invalid';
235
+ };
221
236
  export declare function answerPayloadFor(answer: ApprovalCardDecision, lane: 'respond', caps?: AnswerPayloadCaps | null): RespondAnswerPayload | undefined;
222
237
  export declare function answerPayloadFor(answer: ApprovalCardDecision, lane: 'decide', caps?: AnswerPayloadCaps | null): DecideAnswerPayload | undefined;
223
238
  export interface AnswerCarriage {
224
239
  readonly allowNote: 'model' | 'none';
225
240
  }
226
- export declare function answerCarriage(card: Pick<ApprovalCardRequest, 'callKey'> | null | undefined): AnswerCarriage;
241
+ export declare function answerCarriage(card: Pick<ApprovalCardRequest, 'callKey' | 'parkRow'> | null | undefined): AnswerCarriage;
242
+ export declare function allowNoteNotCarriedSentence(lang?: UiLanguage): string;
227
243
  export interface ApprovalAnswerCommitted {
228
244
  readonly callKey: string;
229
245
  readonly lane: AnswerPayloadLane;
@@ -242,8 +258,19 @@ export interface RespondToolApprovalOpts {
242
258
  decidedBy?: Extract<ApprovalDecidedBy, 'policy'>;
243
259
  }
244
260
  export type RespondToolApprovalFn = (approvalId: string, decision: ToolApprovalRespondDecision, opts?: RespondToolApprovalOpts) => Promise<ToolApprovalRespondAck | void>;
245
- export type ToolApprovalRespondAckView = ToolApprovalRespondAck;
261
+ export type ToolApprovalRespondAckView = ToolApprovalRespondAck | ToolApprovalRespondRedeemedView;
262
+ export interface ToolApprovalRespondRedeemedView {
263
+ readonly approvalId: string;
264
+ readonly askId: string;
265
+ readonly accepted: 'parked_redeemed';
266
+ readonly idempotent?: true;
267
+ readonly decision?: string;
268
+ readonly rememberApplied?: boolean;
269
+ }
246
270
  export declare function isToolApprovalRespondReplayed(ack: ToolApprovalRespondAckView): ack is ToolApprovalRespondReplayed;
271
+ export declare function isToolApprovalRespondParkedRedeemed(ack: object): ack is ToolApprovalRespondRedeemedView;
272
+ export declare function replayedFirstDecisionOf(ack: ToolApprovalRespondAckView | undefined): 'allow' | 'deny' | undefined;
273
+ export declare function settlementAckOf(read: ToolApprovalRespondAckView | undefined): ToolApprovalRespondAckView | undefined;
247
274
  export type { PersistedRuleAnchor };
248
275
  export declare function readToolApprovalRespondAck(v: unknown): ToolApprovalRespondAckView | undefined;
249
276
  export interface ToolApprovalRespondParkingView {
@@ -284,8 +311,8 @@ export declare function approvalSupersedesDetail(card: Pick<ApprovalCardRequest,
284
311
  export declare function readDenialLimitFallback(v: unknown): DenialLimitFallback | undefined;
285
312
  export declare function readRuleOffers(v: unknown): RuleOfferReading[] | undefined;
286
313
  export declare function readRuleOfferSupply(offers: unknown): RuleOfferReading[] | undefined;
287
- export type ApprovalCardV1Facts = Pick<ApprovalCardRequest, 'toolName' | 'args'> & Pick<ApprovalCardRequest, 'toolCallId' | 'workerBadge' | 'wireNote' | 'argsUnavailable' | 'governanceForced' | 'delegation' | 'ruleOffersReadOnly' | 'inputHasBidi' | 'allowRuleShadow' | 'probeCause' | 'rememberRefused' | 'ruleEvidence' | 'requiresRealApproval' | 'ruleOffersAbsence' | 'denialLimitFallback' | 'askClass' | 'classes' | 'agentId' | 'askReasons' | 'grantBinding' | 'unreadableEvidence' | 'message' | 'approvalCard'>;
288
- export type ApprovalCardFacts = ApprovalCardV1Facts & Pick<ApprovalCardRequest, 'argsRewritten' | 'ruleOffers' | 'probeReason' | 'mandated' | 'mandate' | 'readRootCandidate' | 'origin' | 'boundGrants' | 'classifierNoRuling' | 'allowSessionCarried' | 'cardPayloadUnreadable' | 'cardPayloadUnreadableWhy'>;
314
+ export type ApprovalCardV1Facts = Pick<ApprovalCardRequest, 'toolName' | 'args'> & Pick<ApprovalCardRequest, 'toolCallId' | 'workerBadge' | 'wireNote' | 'argsUnavailable' | 'inputSource' | 'governanceForced' | 'delegation' | 'ruleOffersReadOnly' | 'inputHasBidi' | 'allowRuleShadow' | 'probeCause' | 'rememberRefused' | 'ruleEvidence' | 'requiresRealApproval' | 'ruleOffersAbsence' | 'denialLimitFallback' | 'askClass' | 'classes' | 'agentId' | 'askReasons' | 'grantBinding' | 'unreadableEvidence' | 'message' | 'approvalCard'>;
315
+ export type ApprovalCardFacts = ApprovalCardV1Facts & Pick<ApprovalCardRequest, 'argsRewritten' | 'ruleOffers' | 'probeReason' | 'mandated' | 'mandate' | 'readRootCandidate' | 'origin' | 'boundGrants' | 'classifierNoRuling' | 'allowSessionCarried' | 'cardPayloadUnreadable' | 'cardPayloadUnreadableWhy' | 'requestedBy'>;
289
316
  export interface ApprovalCardFrameFactsOptions {
290
317
  readonly streamArgs?: object;
291
318
  readonly argsUnavailable?: true;