@sema-agent/client-core 0.112.0 → 0.113.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 (182) hide show
  1. package/CHANGELOG.md +153 -0
  2. package/README.md +37 -24
  3. package/dist/adapt/arms.js +7 -1
  4. package/dist/adapt/textStream.d.ts +2 -0
  5. package/dist/adapt/textStream.js +27 -1
  6. package/dist/adapter/activeRunSelfHeal.d.ts +7 -5
  7. package/dist/adapter/activeRunSelfHeal.js +38 -66
  8. package/dist/adapter/downstream/eventToSdkMessage.js +4 -0
  9. package/dist/adapter/downstream/terminalToSdkResult.d.ts +8 -0
  10. package/dist/adapter/downstream/terminalToSdkResult.js +36 -1
  11. package/dist/adapter/runStream.d.ts +2 -12
  12. package/dist/adapter/runStream.js +46 -19
  13. package/dist/agentSession/engineAgentRegistryRead.js +2 -1
  14. package/dist/agentSession/engineSessionBackgroundStop.js +2 -2
  15. package/dist/attachmentOutcome.d.ts +35 -0
  16. package/dist/attachmentOutcome.js +192 -0
  17. package/dist/attachmentPathPlan.d.ts +67 -0
  18. package/dist/attachmentPathPlan.js +203 -0
  19. package/dist/attachmentRoute.d.ts +9 -1
  20. package/dist/attachmentRoute.js +23 -2
  21. package/dist/declared/supportFloorDeclared.d.ts +1 -1
  22. package/dist/declared/supportFloorDeclared.js +1 -0
  23. package/dist/deviceRebind.js +2 -3
  24. package/dist/displayUntrusted.js +126 -19
  25. package/dist/engineAddress.d.ts +1 -1
  26. package/dist/engineAddress.js +9 -6
  27. package/dist/engineErrorCodes.d.ts +3 -0
  28. package/dist/engineErrorCodes.js +4 -0
  29. package/dist/engineNoticeCodes.d.ts +34 -4
  30. package/dist/engineNoticeCodes.js +133 -6
  31. package/dist/engineUnavailable.d.ts +4 -2
  32. package/dist/engineUnavailable.js +99 -17
  33. package/dist/fleet/fleetLedger.d.ts +9 -3
  34. package/dist/fleet/fleetLedger.js +112 -16
  35. package/dist/fleet/fleetProjection.d.ts +5 -0
  36. package/dist/fleet/fleetProjection.js +9 -1
  37. package/dist/gateVocabulary.d.ts +7 -0
  38. package/dist/gateVocabulary.js +40 -14
  39. package/dist/generated/engineFactTables.d.ts +4 -2
  40. package/dist/generated/engineFactTables.js +198 -2
  41. package/dist/generated/engineNoticeTables.js +56 -8
  42. package/dist/generated/settingsSchemaFns.d.ts +7 -0
  43. package/dist/generated/settingsSchemaFns.js +11 -0
  44. package/dist/generated/settingsSchemaHash.d.ts +1 -0
  45. package/dist/generated/settingsSchemaHash.js +58 -0
  46. package/dist/generated/settingsSchemaOwnKeyRead.js +6 -1
  47. package/dist/generated/settingsSchemaTables.d.ts +3 -2
  48. package/dist/generated/settingsSchemaTables.js +14 -0
  49. package/dist/generated/settingsSchemaTightenVerdict.d.ts +1 -0
  50. package/dist/generated/settingsSchemaTightenVerdict.js +125 -0
  51. package/dist/headlessPermissionModeWire.d.ts +7 -2
  52. package/dist/headlessPermissionModeWire.js +77 -8
  53. package/dist/hitl/approvalDecisionDoor.d.ts +24 -0
  54. package/dist/hitl/approvalDecisionDoor.js +77 -0
  55. package/dist/hitl/approvalDelivery.d.ts +6 -0
  56. package/dist/hitl/approvalDelivery.js +57 -7
  57. package/dist/hitl/approvalResolution.d.ts +6 -3
  58. package/dist/hitl/approvalResolution.js +24 -2
  59. package/dist/hitl/approvalsFeed.js +1 -1
  60. package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
  61. package/dist/hitl/decisionSend.d.ts +7 -4
  62. package/dist/hitl/decisionSend.js +90 -41
  63. package/dist/hitl/frameRouter.d.ts +3 -3
  64. package/dist/hitl/frameRouter.js +5 -0
  65. package/dist/hitl/hitlBridge.d.ts +1 -0
  66. package/dist/hitl/hitlBridge.js +17 -4
  67. package/dist/hitl/hitlHostSurface.d.ts +3 -2
  68. package/dist/hitl/hitlHostSurface.js +5 -3
  69. package/dist/hitl/legacyApprovalShapes.d.ts +142 -0
  70. package/dist/hitl/legacyApprovalShapes.js +1 -0
  71. package/dist/hitl/livePendingAsk.d.ts +4 -4
  72. package/dist/hitl/livePendingAsk.js +5 -3
  73. package/dist/hitl/parkResolver.js +1 -1
  74. package/dist/hitl/persistedRulesWire.js +2 -2
  75. package/dist/hitl/planReviewCard.d.ts +4 -2
  76. package/dist/hitl/planReviewCard.js +66 -1
  77. package/dist/hitl/planReviewWire.d.ts +34 -2
  78. package/dist/hitl/planReviewWire.js +326 -150
  79. package/dist/hitl/sessionPolicyWire.js +16 -7
  80. package/dist/hitl/subagentSource.d.ts +1 -0
  81. package/dist/hitl/subagentSource.js +11 -0
  82. package/dist/hitl/toolApprovalWire.d.ts +34 -10
  83. package/dist/hitl/toolApprovalWire.js +182 -33
  84. package/dist/hookMatcherVerdict.d.ts +2 -1
  85. package/dist/hookMatcherVerdict.js +3 -2
  86. package/dist/hooksReaderGenerations.d.ts +8 -0
  87. package/dist/hooksReaderGenerations.js +49 -0
  88. package/dist/hooksWireCaps.js +43 -18
  89. package/dist/hostSettingsSource.d.ts +1 -1
  90. package/dist/hostSettingsSource.js +2 -2
  91. package/dist/hostTurnSettings.d.ts +2 -2
  92. package/dist/hostTurnSettings.js +87 -47
  93. package/dist/humanTurn.d.ts +2 -1
  94. package/dist/humanTurn.js +44 -13
  95. package/dist/humanTurnRead.d.ts +7 -0
  96. package/dist/humanTurnRead.js +23 -14
  97. package/dist/humanTurnSentences.js +3 -0
  98. package/dist/i18n/messages.en.d.ts +93 -5
  99. package/dist/i18n/messages.en.js +100 -12
  100. package/dist/i18n/messages.zh.js +110 -15
  101. package/dist/index.d.ts +29 -15
  102. package/dist/index.js +17 -9
  103. package/dist/liveModelCatalog.js +1 -0
  104. package/dist/liveQuestionStore.d.ts +2 -0
  105. package/dist/liveQuestionStore.js +7 -2
  106. package/dist/localConfig/kernel.d.ts +2 -1
  107. package/dist/localConfig/kernel.js +12 -18
  108. package/dist/localConfig/mcp/edit.js +25 -27
  109. package/dist/localConfig/mcp/servers.js +5 -8
  110. package/dist/localConfig/modelPool.d.ts +6 -1
  111. package/dist/localConfig/modelPool.js +104 -27
  112. package/dist/localConfig/modelPoolWords.d.ts +2 -0
  113. package/dist/localConfig/modelPoolWords.js +1 -0
  114. package/dist/localConfig/settingsWrite.js +1 -14
  115. package/dist/localConfig/skills.js +9 -16
  116. package/dist/localEngineSpawn.d.ts +29 -1
  117. package/dist/localEngineSpawn.js +62 -1
  118. package/dist/mcpLiveness.d.ts +1 -1
  119. package/dist/mcpProbeWire.js +2 -2
  120. package/dist/mcpReconnect.js +2 -2
  121. package/dist/model/catalogLoader.js +3 -17
  122. package/dist/model/onboardJudgement.d.ts +8 -0
  123. package/dist/model/onboardJudgement.js +8 -3
  124. package/dist/model/onboardSteps.d.ts +19 -0
  125. package/dist/model/onboardSteps.js +76 -0
  126. package/dist/notifications.js +20 -12
  127. package/dist/ownKey.d.ts +4 -0
  128. package/dist/ownKey.js +61 -0
  129. package/dist/pathShape.d.ts +14 -0
  130. package/dist/pathShape.js +44 -0
  131. package/dist/planReviewCardFacts.d.ts +3 -0
  132. package/dist/planReviewCardFacts.js +20 -3
  133. package/dist/planReviewOutcomeCause.d.ts +2 -0
  134. package/dist/planReviewOutcomeCause.js +12 -0
  135. package/dist/pluginHooksWire.d.ts +20 -8
  136. package/dist/pluginHooksWire.js +204 -86
  137. package/dist/prepareRefusal.d.ts +2 -0
  138. package/dist/prepareRefusal.js +11 -1
  139. package/dist/request/taskRequest.js +3 -1
  140. package/dist/resultFrameKeys.d.ts +1 -0
  141. package/dist/resultFrameKeys.js +3 -0
  142. package/dist/resumeRefusalCopy.js +3 -1
  143. package/dist/retryStatus.d.ts +11 -1
  144. package/dist/retryStatus.js +15 -4
  145. package/dist/runTerminal.d.ts +1 -0
  146. package/dist/runTerminal.js +15 -1
  147. package/dist/sdkWireTransit.d.ts +1 -1
  148. package/dist/seatContract.d.ts +12 -3
  149. package/dist/seatContract.js +24 -13
  150. package/dist/sessionEngine.js +1 -1
  151. package/dist/sessionHooksRoster.js +8 -6
  152. package/dist/sessionIdSegment.d.ts +0 -1
  153. package/dist/sessionIdSegment.js +1 -3
  154. package/dist/sessionMemoryErase.js +2 -2
  155. package/dist/sessionMemoryStatus.js +2 -1
  156. package/dist/sessionOccupant.d.ts +29 -0
  157. package/dist/sessionOccupant.js +78 -0
  158. package/dist/settingsHooksSalvage.d.ts +4 -1
  159. package/dist/settingsHooksSalvage.js +22 -9
  160. package/dist/skillOverrideChain.d.ts +3 -0
  161. package/dist/skillOverrideChain.js +31 -4
  162. package/dist/skillsWireCaps.d.ts +16 -2
  163. package/dist/skillsWireCaps.js +47 -20
  164. package/dist/subagent/agentStateDetail.js +32 -8
  165. package/dist/subagent/engineCompactWire.js +48 -36
  166. package/dist/subagent/engineDelegatedPrompt.d.ts +3 -2
  167. package/dist/subagent/engineDelegatedPrompt.js +65 -28
  168. package/dist/subagentEditOutcomes.d.ts +9 -0
  169. package/dist/subagentEditOutcomes.js +43 -0
  170. package/dist/supportFloor.d.ts +2 -1
  171. package/dist/supportFloor.js +1 -1
  172. package/dist/toolResult.js +4 -2
  173. package/dist/toolRoster.d.ts +1 -0
  174. package/dist/toolRoster.js +1 -0
  175. package/dist/usageAnalytics.js +2 -1
  176. package/dist/userAttachmentEnvelope.d.ts +11 -0
  177. package/dist/userAttachmentEnvelope.js +7 -2
  178. package/dist/userAttachmentSeat.d.ts +7 -1
  179. package/dist/userAttachmentSeat.js +44 -7
  180. package/dist/wiringInstructionsAttribution.js +8 -2
  181. package/docs/INTEGRATION-CLIENTS.md +1654 -16
  182. package/package.json +5 -5
@@ -0,0 +1,142 @@
1
+ import type { AllowRuleShadow, ApprovalCardDelegation, ApprovalDecidedBy, ApprovalDecisionResult, ApprovalSettleCause, AskClass, AskOrigin, AutoModeFallbackCause, BoundGrantAbsence, BoundSkillGrants, DenialLimitFallback, PersistedRuleAnchor, PersistedRuleMandate, PersistRuleSelection, ReadRootCover, RuleOffer, RuleOffersAbsence, RuleRefusalReason, ToolApprovalCardWord } from '@sema-agent/sdk';
2
+ import type { ToolApprovalRespondDecision } from './toolApprovalWire.js';
3
+ type KnownOf<T> = {
4
+ [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K];
5
+ };
6
+ export type LegacyAskReason = {
7
+ by: 'hook';
8
+ cause: 'asked' | 'verdict_unreadable' | 'verdict_unfinished';
9
+ registration?: string;
10
+ words?: string;
11
+ } | {
12
+ by: 'policy' | 'content_question' | 'plan_review' | 'ancestor_marked' | 'org_unavailable' | 'org_rule' | 'rule_store_unavailable' | 'ask_rule' | 'denial_limit_fallback' | 'shell_gate_tighten' | 'safety_tighten';
13
+ words: string;
14
+ };
15
+ export type LegacyExtensionRequester = {
16
+ kind: 'extension';
17
+ name: string;
18
+ };
19
+ export type LegacyProbeCause = {
20
+ code: string;
21
+ roots: {
22
+ shown: string[];
23
+ total: number;
24
+ };
25
+ further?: {
26
+ shown: string[];
27
+ total: number;
28
+ };
29
+ };
30
+ export type LegacyRuleEvidence = {
31
+ orgRevision?: number;
32
+ orgRevisionAbsent?: 'not_wired' | 'not_adjudicated' | 'unavailable' | 'no_match' | 'not_reported' | (string & {});
33
+ orgRule?: string;
34
+ orgRuleAbsent?: 'not_wired' | 'not_adjudicated' | 'unavailable' | 'no_match' | 'not_reported' | (string & {});
35
+ personalRuleDots?: Array<{
36
+ actor: string;
37
+ counter: number;
38
+ }>;
39
+ personalRuleDotsAbsent?: 'not_wired' | 'not_adjudicated' | 'unavailable' | 'no_match' | 'not_reported' | (string & {});
40
+ };
41
+ export type LegacyReadRootCandidate = {
42
+ dir: string;
43
+ covers?: ReadRootCover;
44
+ clearsThisAsk: true;
45
+ };
46
+ export interface LegacyToolApprovalFrame {
47
+ type: 'tool_approval' | 'tool_approval_complete';
48
+ approvalId: string;
49
+ toolName?: string;
50
+ toolCallId?: string;
51
+ sourceSessionId?: string;
52
+ agentId?: string;
53
+ askReasons?: LegacyAskReason[];
54
+ fromSubagent?: true;
55
+ sourceAgentName?: string;
56
+ message?: string;
57
+ args?: unknown;
58
+ argsOmitted?: boolean;
59
+ governanceForced?: true;
60
+ rememberRefused?: true;
61
+ requiresRealApproval?: true;
62
+ origin?: AskOrigin;
63
+ approvalCard?: ToolApprovalCardWord;
64
+ askClass?: AskClass;
65
+ classes?: AskClass[];
66
+ boundGrantDigest?: string;
67
+ boundGrants?: BoundSkillGrants;
68
+ boundGrantAbsence?: BoundGrantAbsence;
69
+ classifierNoRuling?: AutoModeFallbackCause;
70
+ inputHasBidi?: true;
71
+ expiresAtMs?: number;
72
+ expiresInMs?: number;
73
+ serverNowMs?: number;
74
+ ruleOffers?: RuleOffer[];
75
+ ruleOffersAbsence?: RuleOffersAbsence | (string & {});
76
+ mandated?: true;
77
+ mandate?: PersistedRuleMandate;
78
+ denialLimitFallback?: DenialLimitFallback;
79
+ allowRuleShadowed?: AllowRuleShadow[];
80
+ probeCause?: LegacyProbeCause;
81
+ probeReason?: string;
82
+ requestedBy?: LegacyExtensionRequester;
83
+ ruleEvidence?: LegacyRuleEvidence;
84
+ delegation?: ApprovalCardDelegation;
85
+ parked?: true;
86
+ outcome?: 'allowed' | 'denied' | 'expired';
87
+ cause?: ApprovalSettleCause;
88
+ readRootCandidate?: LegacyReadRootCandidate;
89
+ [k: string]: unknown;
90
+ }
91
+ export interface LegacyToolApprovalRespondApplied {
92
+ approvalId: string;
93
+ delivery: 'applied';
94
+ decision: ToolApprovalRespondDecision;
95
+ rememberApplied?: boolean;
96
+ updatedInputForwarded?: boolean;
97
+ rulePersisted?: boolean;
98
+ ruleRefusal?: RuleRefusalReason;
99
+ persistedRule?: string;
100
+ persistedRules?: string[];
101
+ persistedRuleAnchors?: PersistedRuleAnchor[];
102
+ noteRecorded?: boolean;
103
+ consumerState?: 'absent';
104
+ }
105
+ export interface LegacyToolApprovalRespondReplayed {
106
+ approvalId: string;
107
+ askId: string;
108
+ idempotent: true;
109
+ decision: 'allow' | 'deny';
110
+ decidedAtMs: number;
111
+ decisionNote?: string;
112
+ rememberApplied?: false;
113
+ noteRecorded?: boolean;
114
+ rulePersisted?: false;
115
+ ruleRefusal?: Extract<RuleRefusalReason, 'rule_lane_unavailable'>;
116
+ }
117
+ export interface LegacyToolApprovalRespondParkedRedeemed extends KnownOf<ApprovalDecisionResult> {
118
+ approvalId: string;
119
+ askId: string;
120
+ accepted: 'parked_redeemed';
121
+ rememberApplied?: boolean;
122
+ rulePersisted?: boolean;
123
+ ruleRefusal?: RuleRefusalReason;
124
+ persistedRule?: string;
125
+ persistedRules?: string[];
126
+ persistedRuleAnchors?: PersistedRuleAnchor[];
127
+ }
128
+ export type LegacyToolApprovalRespondAck = LegacyToolApprovalRespondApplied | LegacyToolApprovalRespondReplayed | LegacyToolApprovalRespondParkedRedeemed;
129
+ export interface LegacyToolApprovalRespondBody {
130
+ decision: ToolApprovalRespondDecision;
131
+ updatedInput?: unknown;
132
+ persistRule?: PersistRuleSelection;
133
+ note?: string;
134
+ decidedBy?: ApprovalDecidedBy;
135
+ readRootGrant?: string;
136
+ }
137
+ export interface LegacyToolApprovalRespondVerb {
138
+ respond(id: string, body: LegacyToolApprovalRespondBody, opts?: {
139
+ signal?: AbortSignal;
140
+ }): Promise<LegacyToolApprovalRespondAck>;
141
+ }
142
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -2,7 +2,7 @@ import { type ApprovalRequestFrame } from '@sema-agent/sdk';
2
2
  import type { ApprovalResolution } from './approvalResolution.js';
3
3
  import type { ApprovalsFeedEmission } from './approvalsFeed.js';
4
4
  import type { ApprovalMandateWord } from '../gateVocabulary.js';
5
- import { type RespondToolApprovalFn, type ToolApprovalFrame, type ToolApprovalFrameLaneOpts } from './toolApprovalWire.js';
5
+ import { type RespondToolApprovalFn, type LegacyToolApprovalFrame, type ToolApprovalFrameLaneOpts } from './toolApprovalWire.js';
6
6
  export interface LivePendingAskView {
7
7
  approvalId: string;
8
8
  toolName: string;
@@ -12,8 +12,8 @@ export interface LivePendingAskView {
12
12
  requiresRealApproval?: true;
13
13
  governanceForced?: true;
14
14
  fromSubagent?: true;
15
- originTaskId?: string;
16
- frame?: ToolApprovalFrame | ApprovalRequestFrame;
15
+ sourceSessionId?: string;
16
+ frame?: LegacyToolApprovalFrame | ApprovalRequestFrame;
17
17
  mandated?: true;
18
18
  mandate?: ApprovalMandateWord;
19
19
  origin?: string;
@@ -49,7 +49,7 @@ export interface ApprovalsAwaitingDecisionCount {
49
49
  suspendedSubagent: number | null;
50
50
  }
51
51
  export declare function countApprovalsAwaitingDecision(snapshot: ApprovalsFeedEmission | null | undefined, filter: SuspendedAskFilter): ApprovalsAwaitingDecisionCount;
52
- export declare function livePendingRowToApprovalFrame(row: LivePendingAskView): ToolApprovalFrame;
52
+ export declare function livePendingRowToApprovalFrame(row: LivePendingAskView): LegacyToolApprovalFrame;
53
53
  export declare function surfaceSuspendedAskAndRespond(row: LivePendingAskView, respond: RespondToolApprovalFn, signal?: AbortSignal, lane?: ToolApprovalFrameLaneOpts): Promise<ApprovalResolution>;
54
54
  export interface SuspendedAskDelta {
55
55
  appeared: LivePendingAskView[];
@@ -1,8 +1,10 @@
1
1
  import { isApprovalRequestFrameV1 } from '@sema-agent/sdk';
2
2
  import { appendOwnElement, readOwnDataNonEmptyString } from '../ownKey.js';
3
+ import { settledApprovalOf, settledForDurableLane } from './approvalHolds.js';
3
4
  import { readRequiresRealApproval } from './approvalCardReading.js';
4
5
  import { pendingRowIsOfSession } from './parkRowDelegation.js';
5
6
  import { approvalLiveFaceOf, liveFaceCarried } from './approvalLiveFace.js';
7
+ import { livePendingRowSourceSessionOf } from './subagentSource.js';
6
8
  import { THROWN_SLOT_UNREADABLE, readThrownSlot } from '../wireFailureShape.js';
7
9
  import { isToolApprovalFrame, surfaceApprovalFrameWithId, } from './toolApprovalWire.js';
8
10
  function nonEmptyString(v) {
@@ -76,7 +78,7 @@ export function readLivePendingRows(body) {
76
78
  ...(readRequiresRealApproval(o) ? { requiresRealApproval: true } : {}),
77
79
  ...(o.governanceForced === true ? { governanceForced: true } : {}),
78
80
  ...(o.fromSubagent === true ? { fromSubagent: true } : {}),
79
- ...(nonEmptyString(o.originTaskId) ? { originTaskId: o.originTaskId } : {}),
81
+ ...((src) => (src !== undefined ? { sourceSessionId: src } : {}))(livePendingRowSourceSessionOf(o)),
80
82
  ...(frame !== undefined ? { frame } : {}),
81
83
  ...(frame === undefined ? liveFaceCarried(approvalLiveFaceOf(o)) : {}),
82
84
  });
@@ -133,7 +135,7 @@ export function countApprovalsAwaitingDecision(snapshot, filter) {
133
135
  return { durable, live: null, suspendedSubagent: null };
134
136
  if ((snapshot.livePendingDropped ?? 0) > 0)
135
137
  return { durable, live: null, suspendedSubagent: null };
136
- const live = bySession(snapshot.livePending);
138
+ const live = bySession(snapshot.livePending).filter(r => !settledForDurableLane(settledApprovalOf(r.approvalId)));
137
139
  return { durable, live: live.length, suspendedSubagent: live.filter(r => r.fromSubagent === true).length };
138
140
  }
139
141
  export function livePendingRowToApprovalFrame(row) {
@@ -142,7 +144,7 @@ export function livePendingRowToApprovalFrame(row) {
142
144
  approvalId: row.approvalId,
143
145
  toolName: row.toolName,
144
146
  ...(row.fromSubagent === true ? { fromSubagent: true } : {}),
145
- ...(row.originTaskId !== undefined ? { sourceSessionId: row.originTaskId } : {}),
147
+ ...(row.sourceSessionId !== undefined ? { sourceSessionId: row.sourceSessionId } : {}),
146
148
  ...(row.governanceForced === true ? { governanceForced: true } : {}),
147
149
  ...(readRequiresRealApproval(row) ? { requiresRealApproval: true } : {}),
148
150
  ...liveFaceCarried(approvalLiveFaceOf(row)),
@@ -339,7 +339,7 @@ function failsoftWayOutOf(outcome) {
339
339
  return 'cancel';
340
340
  if (outcome.kind === 'unsettled' && outcome.cause === 'engine_refused' && (refusedParkFromError(outcome.refusal) !== null || outcome.refusal?.conflict === 'row_integrity'))
341
341
  return 'cancel';
342
- if (outcome.kind === 'unsettled' && outcome.cause === 'engine_refused')
342
+ if (outcome.kind === 'unsettled' && (outcome.cause === 'engine_refused' || outcome.cause === 'route_missing'))
343
343
  return 'speak';
344
344
  return 'card';
345
345
  }
@@ -2,7 +2,7 @@ import { displayUntrusted, quoteUntrustedForSentence } from '../displayUntrusted
2
2
  import { engineCapTrue } from '../engineCapsCache.js';
3
3
  import { CORE_RULE_BEHAVIORS } from '../generated/engineFactTables.js';
4
4
  import { inValueOf, slotReadOf, wireFailureShapeOf } from '../wireFailureShape.js';
5
- import { CAPABILITY_OPERATOR_PRINCIPALS_REQUIRED } from '../engineErrorCodes.js';
5
+ import { CAPABILITY_OPERATOR_PRINCIPALS_REQUIRED, ROUTE_NOT_FOUND } from '../engineErrorCodes.js';
6
6
  import { hostLog } from '../host.js';
7
7
  import { msg, renderMessage } from '../i18n/translate.js';
8
8
  import { appendOwnElement, guardedRead, readOwnDataValue } from '../ownKey.js';
@@ -168,7 +168,7 @@ export function classifyRulesFailure(e, context) {
168
168
  return { kind: 'lane-unavailable', message };
169
169
  }
170
170
  if (status === 404) {
171
- if (errorCode === 'not_found.route')
171
+ if (errorCode === ROUTE_NOT_FOUND)
172
172
  return { kind: 'route-missing', message };
173
173
  if (errorCode === 'not_found.rule_ticket')
174
174
  return { kind: 'ticket-dead', message };
@@ -1,13 +1,15 @@
1
1
  import { type PlanReviewCardFacts, type PlanReviewFactsTaken } from '../planReviewCardFacts.js';
2
2
  import { type MessageRef } from '../i18n/translate.js';
3
+ import { type PlanReviewOutcomeCause } from '../planReviewOutcomeCause.js';
3
4
  import type { MessageKey } from '../i18n/messages.en.js';
4
5
  import type { UiLanguage } from '../env/uiLanguage.js';
5
6
  export declare function planReviewCardNoteRef(facts: PlanReviewCardFacts): MessageRef | undefined;
6
7
  export declare function planReviewUnreadableNoteRef(): MessageRef;
7
8
  export declare function planReviewCardNote(facts: PlanReviewCardFacts, lang?: UiLanguage): string | undefined;
8
9
  export declare function planReviewAskAgainKey(facts: PlanReviewCardFacts | undefined): MessageKey;
9
- export type PlanReviewDecisionReason = 'card_missing' | 'card_withholds' | 'gate_moved' | 'gate_untrusted';
10
- export declare function planReviewDecisionReasonRef(reason: PlanReviewDecisionReason, card?: PlanReviewCardFacts): MessageRef;
10
+ export type PlanReviewDecisionReason = Exclude<PlanReviewOutcomeCause, 'stored_form_unsupported'>;
11
+ export declare function planReviewDecisionReasonRef(reason: PlanReviewOutcomeCause, card?: PlanReviewCardFacts): MessageRef | undefined;
12
+ export declare function planReviewOutcomeNotice(outcome: object | null | undefined, cardOnScreen?: boolean, lang?: UiLanguage): string | undefined;
11
13
  export interface PlanReviewLedgerSource {
12
14
  readonly runRow: (taskId: string, signal: AbortSignal) => Promise<object>;
13
15
  readonly frames: (taskId: string, signal: AbortSignal) => AsyncIterable<object>;
@@ -1,5 +1,8 @@
1
1
  import { currentPlanReviewGateOf, isPlanReviewClaimFrame, mintPlanReviewCardFacts, openPlanReviewLedgerFold, planGateRowReadOf, planReviewBodyOf, planReviewCardFactsFrom, planReviewLedgerClaimOf, planReviewRunGeneration, beginPlanReviewFactsRead, commitPlanReviewFacts, samePlanClaim, stepPlanReviewLedgerFold, unknownBody, } from '../planReviewCardFacts.js';
2
- import { msg, renderMessage } from '../i18n/translate.js';
2
+ import { msg, renderLanguageOf, renderMessage } from '../i18n/translate.js';
3
+ import { planReviewOutcomeCauseOf } from '../planReviewOutcomeCause.js';
4
+ import { decisionRefusalWayOutContent, isDecisionRefusalWayOut } from '../checkpointRowVerdict.js';
5
+ import { guardedRead, readOwnDataValue } from '../ownKey.js';
3
6
  import { readRunLedgerSnapshot } from '../runLedgerSnapshot.js';
4
7
  import { snapshotIsSubFlow, snapshotSegmentIdentity } from '../adapter/types.js';
5
8
  import { settleWithinDeadline } from '../abortableSleep.js';
@@ -48,6 +51,8 @@ export function planReviewAskAgainKey(facts) {
48
51
  }
49
52
  export function planReviewDecisionReasonRef(reason, card) {
50
53
  switch (reason) {
54
+ case 'stored_form_unsupported':
55
+ return undefined;
51
56
  case 'card_missing':
52
57
  return msg('approval.planReview.decision.cardMissing');
53
58
  case 'card_withholds': {
@@ -67,6 +72,66 @@ export function planReviewDecisionReasonRef(reason, card) {
67
72
  return msg('approval.planReview.decision.gateUntrusted');
68
73
  }
69
74
  }
75
+ function noticeWhatKey(decision) {
76
+ switch (decision) {
77
+ case 'approve':
78
+ return 'approval.planReview.notice.what.approve';
79
+ case 'reject':
80
+ return 'approval.planReview.notice.what.reject';
81
+ case 'ask_again':
82
+ return 'approval.planReview.notice.what.askAgain';
83
+ default:
84
+ return 'approval.planReview.notice.what.unknown';
85
+ }
86
+ }
87
+ export function planReviewOutcomeNotice(outcome, cardOnScreen, lang) {
88
+ try {
89
+ if (outcome === null || typeof outcome !== 'object')
90
+ return undefined;
91
+ const own = (key) => guardedRead(() => readOwnDataValue(outcome, key));
92
+ const effect = own('effect');
93
+ const cause = planReviewOutcomeCauseOf(effect, own('cause'));
94
+ const decision = own('decision');
95
+ const gateIdOmitted = own('gateIdOmitted') === true;
96
+ const wayOutWord = own('wayOut');
97
+ let head;
98
+ switch (effect) {
99
+ case 'not_sent':
100
+ head = 'approval.planReview.notice.notSent';
101
+ break;
102
+ case 'not_applied':
103
+ head = 'approval.planReview.notice.refused';
104
+ break;
105
+ case 'still_parked':
106
+ head = cause === 'stored_form_unsupported' ? 'approval.planReview.notice.storedForm' : 'approval.planReview.notice.stillParked';
107
+ break;
108
+ case 'unconfirmed':
109
+ head = 'approval.planReview.notice.unconfirmed';
110
+ break;
111
+ case 'took_effect':
112
+ case 'advanced':
113
+ head = undefined;
114
+ break;
115
+ default:
116
+ return undefined;
117
+ }
118
+ const whatKey = noticeWhatKey(decision);
119
+ const reason = cause === 'card_missing' || cause === 'gate_moved' || cause === 'gate_untrusted' ? planReviewDecisionReasonRef(cause) : undefined;
120
+ const wayOut = effect === 'not_applied' && isDecisionRefusalWayOut(wayOutWord) ? decisionRefusalWayOutContent(wayOutWord, lang) : undefined;
121
+ const parts = [
122
+ head === undefined ? undefined : renderMessage(msg(head, { what: msg(whatKey) }), lang),
123
+ reason === undefined ? undefined : renderMessage(reason, lang),
124
+ wayOut === undefined ? undefined : renderMessage(msg('approval.planReview.notice.wayOut', { wayOut }), lang),
125
+ gateIdOmitted && effect !== 'not_sent' ? renderMessage(msg('approval.planReview.decision.sentWithoutGateId'), lang) : undefined,
126
+ cardOnScreen === true && head !== undefined ? renderMessage(msg('approval.planReview.notice.cardOnScreen'), lang) : undefined,
127
+ ];
128
+ const shown = parts.filter((p) => p !== undefined && p.length > 0);
129
+ return shown.length === 0 ? undefined : shown.join(renderLanguageOf(lang) === 'zh' ? '' : ' ');
130
+ }
131
+ catch {
132
+ return undefined;
133
+ }
134
+ }
70
135
  const PLAN_REVIEW_LEDGER_BUDGET_MS = 3_000;
71
136
  const planReviewFactsFlights = new Map();
72
137
  export function _resetPlanReviewFactsFlightsForTest() {
@@ -1,8 +1,11 @@
1
1
  import { type QuestionAnswer } from '../liveQuestionStore.js';
2
2
  import type { EngineWireInjection } from '../engineWireSdk.js';
3
+ import { type DecisionRefusalWayOut } from './decisionRefusal.js';
3
4
  import { type PlanReviewModeAfter } from './hitlBridge.js';
4
5
  import type { AgentClient } from '@sema-agent/sdk';
5
6
  import { isPlanReviewPark, type PlanReviewCardFacts } from '../planReviewCardFacts.js';
7
+ import { type PlanReviewOutcomeCause } from '../planReviewOutcomeCause.js';
8
+ export type { PlanReviewOutcomeCause } from '../planReviewOutcomeCause.js';
6
9
  import type { UiLanguage } from '../env/uiLanguage.js';
7
10
  import type { ReopenCardVerdict } from '../adapter/activeRunSelfHeal.js';
8
11
  export declare const PLAN_REVIEW_APPROVE_LABEL = "Yes, approve and run the plan";
@@ -39,6 +42,7 @@ export interface PlanReviewCardView {
39
42
  readonly facts?: PlanReviewCardFacts;
40
43
  readonly options: readonly PlanReviewOption[];
41
44
  readonly note?: string;
45
+ readonly heading: string;
42
46
  }
43
47
  export declare function planReviewCardViewOf(frame: object | null | undefined, lang?: UiLanguage): PlanReviewCardView | undefined;
44
48
  export type PlanReviewEvidenceMove = 'same' | 'moved' | 'unknown';
@@ -72,6 +76,8 @@ export interface ArmPlanReviewOptions {
72
76
  readGateInstanceKeys?: PlanReviewGateInstanceReader;
73
77
  wire?: PlanReviewWire;
74
78
  onOutcome?: PlanReviewDeliveryOptions['onOutcome'];
79
+ onAccepted?: PlanReviewDeliveryOptions['onAccepted'];
80
+ stillHere?: () => boolean | undefined;
75
81
  }
76
82
  export declare function armPlanReviewApproval(result: unknown, sessionKey?: string, opts?: ArmPlanReviewOptions): boolean;
77
83
  export type PlanReviewDecisionEffect = 'took_effect' | 'advanced' | 'still_parked' | 'not_sent' | 'not_applied' | 'unconfirmed';
@@ -80,10 +86,31 @@ export interface PlanReviewOutcomeMeta {
80
86
  dispatchNo: number;
81
87
  decision: 'approve' | 'reject' | 'ask_again';
82
88
  effect: PlanReviewDecisionEffect;
83
- cause?: 'stored_form_unsupported';
89
+ cause?: PlanReviewOutcomeCause;
84
90
  questionId?: string;
91
+ delivery?: 'submit' | 'follow';
92
+ gateIdOmitted?: true;
93
+ wayOut?: DecisionRefusalWayOut | (string & {});
85
94
  }
86
- export declare function planReviewOutcomeTail(taskId: string, decision: 'approve' | 'reject', effect: PlanReviewDecisionEffect, cause?: 'stored_form_unsupported'): string;
95
+ export interface PlanReviewAcceptedEngine {
96
+ readonly taskId?: string;
97
+ readonly sessionId?: string;
98
+ readonly status?: string;
99
+ readonly decisionCommitted?: true;
100
+ readonly checkpointId?: string;
101
+ }
102
+ export interface PlanReviewDecisionAccepted {
103
+ readonly taskId: string;
104
+ readonly dispatchNo: number;
105
+ readonly decision: 'approve' | 'reject' | 'ask_again';
106
+ readonly questionId?: string;
107
+ readonly engine: PlanReviewAcceptedEngine;
108
+ readonly decided?: {
109
+ readonly verdict: 'approved' | 'rejected';
110
+ readonly plan: string;
111
+ };
112
+ }
113
+ export declare function planReviewOutcomeTail(taskId: string, decision: 'approve' | 'reject', effect: PlanReviewDecisionEffect, cause?: PlanReviewOutcomeCause): string;
87
114
  export type PlanReviewWireClient = {
88
115
  assistant: Pick<AgentClient['assistant'], 'planReview'>;
89
116
  runs: Pick<AgentClient['runs'], 'get'> & Partial<Pick<AgentClient['runs'], 'events'>>;
@@ -100,6 +127,7 @@ export interface PlanReviewDecisionOutcome extends PlanReviewOutcomeMeta {
100
127
  export interface PlanReviewDeliveryOptions {
101
128
  wire?: PlanReviewWire;
102
129
  onOutcome?: (outcome: PlanReviewDecisionOutcome) => void;
130
+ onAccepted?: (accepted: PlanReviewDecisionAccepted) => void;
103
131
  }
104
132
  export interface DecidePlanReviewOptions extends PlanReviewDeliveryOptions {
105
133
  reason?: string;
@@ -124,18 +152,21 @@ export interface ReopenPlanReviewSharedOpts {
124
152
  readGateInstanceKeys?: PlanReviewGateInstanceReader;
125
153
  pendingReadStartedAt?: number;
126
154
  checkpointId?: string;
155
+ stillHere?: () => boolean | undefined;
127
156
  }
128
157
  export interface ReopenPlanReviewFreshOpts extends ReopenPlanReviewSharedOpts {
129
158
  mintFreshQuestionId?: true;
130
159
  deliverDecision?: (taskId: string, decision: Parameters<typeof decidePlanReview>[1], reason: string | undefined, card: PlanReviewCardFacts) => void | Promise<void>;
131
160
  wire?: PlanReviewWire;
132
161
  onOutcome?: PlanReviewDeliveryOptions['onOutcome'];
162
+ onAccepted?: PlanReviewDeliveryOptions['onAccepted'];
133
163
  }
134
164
  export interface ReopenPlanReviewReuseOpts extends ReopenPlanReviewSharedOpts {
135
165
  mintFreshQuestionId: false;
136
166
  deliverDecision?: never;
137
167
  wire?: never;
138
168
  onOutcome?: never;
169
+ onAccepted?: never;
139
170
  }
140
171
  export type ReopenPlanReviewOpts = ReopenPlanReviewFreshOpts | ReopenPlanReviewReuseOpts;
141
172
  export declare function _resetActiveReopenRespondersForTest(): void;
@@ -146,3 +177,4 @@ export interface ReadPlanReviewCardFactsOptions {
146
177
  readonly signal?: AbortSignal;
147
178
  }
148
179
  export declare function readPlanReviewCardFacts(taskId: string, opts?: ReadPlanReviewCardFactsOptions): Promise<PlanReviewCardFacts>;
180
+ export declare function readPlanReviewCurrentGate(e: {} | null | undefined): string | undefined;