@sema-agent/client-core 0.84.1 → 0.85.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 (84) hide show
  1. package/CHANGELOG.md +149 -0
  2. package/README.md +18 -11
  3. package/dist/adapt/arms.js +1 -1
  4. package/dist/adapt.d.ts +1 -1
  5. package/dist/adapt.js +1 -1
  6. package/dist/adapter/downstream/terminalToSdkResult.js +9 -5
  7. package/dist/adapter/runStream.js +6 -2
  8. package/dist/agentSession/engineSessionBackgroundStop.d.ts +50 -0
  9. package/dist/agentSession/engineSessionBackgroundStop.js +291 -0
  10. package/dist/agentsWireCaps.d.ts +2 -1
  11. package/dist/cloudConfigWireCaps.js +2 -1
  12. package/dist/corruptSession.d.ts +3 -0
  13. package/dist/corruptSession.js +29 -0
  14. package/dist/corruptSessionCopy.d.ts +1 -0
  15. package/dist/corruptSessionCopy.js +4 -0
  16. package/dist/decideFailureNote.js +4 -1
  17. package/dist/decideReceipt.d.ts +6 -0
  18. package/dist/decideReceipt.js +30 -1
  19. package/dist/effortWire.d.ts +2 -1
  20. package/dist/effortWire.js +2 -4
  21. package/dist/engineErrorCodes.d.ts +9 -0
  22. package/dist/engineErrorCodes.js +29 -0
  23. package/dist/engineNoticeCodes.d.ts +9 -0
  24. package/dist/engineNoticeCodes.js +44 -156
  25. package/dist/engineWireFor.d.ts +43 -0
  26. package/dist/engineWireFor.js +399 -0
  27. package/dist/engineWireSdk.d.ts +4 -0
  28. package/dist/fileHistoryCaptureCapability.d.ts +4 -1
  29. package/dist/fileHistoryCaptureCapability.js +43 -9
  30. package/dist/gateVocabulary.d.ts +1 -2
  31. package/dist/gateVocabulary.js +1 -22
  32. package/dist/generated/engineNoticeTables.d.ts +3 -0
  33. package/dist/generated/engineNoticeTables.js +156 -0
  34. package/dist/generated/toolNameTables.d.ts +2 -0
  35. package/dist/generated/toolNameTables.js +43 -0
  36. package/dist/headlessPermissionModeWire.js +2 -4
  37. package/dist/hitl/frameRouter.js +4 -2
  38. package/dist/hitl/parkResolver.js +3 -1
  39. package/dist/hitl/planReviewWire.d.ts +11 -0
  40. package/dist/hitl/planReviewWire.js +177 -69
  41. package/dist/hitl/rosterMountedNames.d.ts +2 -0
  42. package/dist/hitl/rosterMountedNames.js +38 -0
  43. package/dist/hitl/sessionPolicyDeliverable.d.ts +6 -2
  44. package/dist/hitl/sessionPolicyDeliverable.js +25 -45
  45. package/dist/hitl/sessionPolicyWire.js +1 -38
  46. package/dist/hitl/toolApprovalWire.d.ts +4 -2
  47. package/dist/hitl/toolApprovalWire.js +4 -2
  48. package/dist/index.d.ts +9 -3
  49. package/dist/index.js +6 -2
  50. package/dist/permissionWireCaps.d.ts +2 -1
  51. package/dist/permissionWireCaps.js +2 -7
  52. package/dist/request/taskRequest.d.ts +2 -0
  53. package/dist/request/taskRequest.js +18 -1
  54. package/dist/resumeRefusalCopy.js +4 -2
  55. package/dist/runTerminal.js +4 -0
  56. package/dist/sandboxWire.js +1 -1
  57. package/dist/sealedKeyCapability.d.ts +17 -0
  58. package/dist/sealedKeyCapability.js +42 -0
  59. package/dist/seatContract.d.ts +2 -1
  60. package/dist/seatContract.js +5 -21
  61. package/dist/subagent/engineCompactWire.d.ts +13 -2
  62. package/dist/subagent/engineCompactWire.js +48 -37
  63. package/dist/subagent/engineDelegatedPrompt.d.ts +9 -1
  64. package/dist/subagent/engineDelegatedPrompt.js +16 -16
  65. package/dist/subagent/engineRowStopGate.d.ts +2 -2
  66. package/dist/subagent/engineRowStopGate.js +4 -4
  67. package/dist/subagent/engineSubagentOutput.d.ts +8 -0
  68. package/dist/subagent/engineSubagentOutput.js +37 -18
  69. package/dist/subagent/engineSubagentResume.d.ts +11 -2
  70. package/dist/subagent/engineSubagentResume.js +28 -14
  71. package/dist/subagent/engineSubagentSteer.d.ts +10 -1
  72. package/dist/subagent/engineSubagentSteer.js +16 -11
  73. package/dist/subagent/engineSubagentTail.d.ts +10 -1
  74. package/dist/subagent/engineSubagentTail.js +35 -17
  75. package/dist/subagent/engineTaskHandleWire.d.ts +13 -0
  76. package/dist/subagent/engineTaskHandleWire.js +41 -20
  77. package/dist/taskRequestWords.d.ts +5 -0
  78. package/dist/taskRequestWords.js +4 -0
  79. package/dist/wireErrorTriage.d.ts +1 -0
  80. package/dist/wireErrorTriage.js +3 -1
  81. package/dist/wireRefusalCopy.d.ts +10 -0
  82. package/dist/wireRefusalCopy.js +62 -2
  83. package/docs/INTEGRATION-CLIENTS.md +679 -18
  84. package/package.json +1 -1
package/dist/adapt.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { isEngineWorkflowNotified, isWorkflowCompletionCardEnqueued, listNotifiedRuns, listWorkflowCompletionCardsEnqueued, markEngineWorkflowNotified, noteWorkflowCompletionCardEnqueued, parseTranscriptNotificationSeeds, } from './notifications.js';
2
- export { CANCEL_MESSAGE, estimateCjkTokens, flattenWireOutput, FLUSH_INTERVAL_MS, IDLE_FLUSH_MS, REJECT_MESSAGE, sanitizeToolUseBlock, shortTaskLabel, SUBAGENT_TOOL_NAMES, WORKFLOW_TOOL_NAMES, } from './adapt/wireShapes.js';
2
+ export { CANCEL_MESSAGE, estimateCjkTokens, flattenWireOutput, FLUSH_INTERVAL_MS, IDLE_FLUSH_MS, REJECT_MESSAGE, sanitizeToolUseBlock, SUBAGENT_TOOL_NAMES, WORKFLOW_TOOL_NAMES, } from './adapt/wireShapes.js';
3
3
  import { IDLE_FLUSH_MS } from './adapt/wireShapes.js';
4
4
  import { chrome, mainLane, makeIdOf } from './adapt/ids.js';
5
5
  import { createTextStream } from './adapt/textStream.js';
@@ -5,7 +5,11 @@ import { REDACTION_MARKER_PREFIX, washCredentials } from '../../displayUntrusted
5
5
  import { readEffectiveReasoning, readEffectiveMemoryScopes } from '../../effectiveFacts.js';
6
6
  import { isReviewPark, readRunTerminal, runTerminalCode, runTerminalGateToolName, } from '../../runTerminal.js';
7
7
  import { toCcModelUsage } from './turnUsageToModelUsage.js';
8
- import { LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, OUTPUT_INVALID, isRewindFamilyCode, } from '../../engineErrorCodes.js';
8
+ import { LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, OUTPUT_INVALID, isCorruptSessionCode, isRewindFamilyCode, } from '../../engineErrorCodes.js';
9
+ import { corruptSessionContent } from '../../corruptSessionCopy.js';
10
+ function withSessionUnreadableNote(text, code) {
11
+ return isCorruptSessionCode(code) ? `${text}\n${corruptSessionContent()}` : text;
12
+ }
9
13
  function finiteOr0(v) {
10
14
  return typeof v === 'number' && Number.isFinite(v) ? v : 0;
11
15
  }
@@ -527,9 +531,9 @@ export function doneToSdkResult(ev, ctx, observed) {
527
531
  ...errorBase,
528
532
  subtype: failedSubtype,
529
533
  errors: [
530
- isRewindFamilyCode(failedCode) && failedMessage
534
+ withSessionUnreadableNote(isRewindFamilyCode(failedCode) && failedMessage
531
535
  ? `${failedMessage} (${failedCode})`
532
- : (failedMessage ?? 'run failed'),
536
+ : (failedMessage ?? 'run failed'), failedCode),
533
537
  ],
534
538
  });
535
539
  }
@@ -619,9 +623,9 @@ export function failedToSdkResult(ev, ctx, observed) {
619
623
  durationMs: elapsedMs(ctx),
620
624
  errorCode: ev.errorCode,
621
625
  errors: [
622
- isRewindFamilyCode(ev.errorCode) && ev.errorMessage
626
+ withSessionUnreadableNote(isRewindFamilyCode(ev.errorCode) && ev.errorMessage
623
627
  ? `${ev.errorMessage} (${ev.errorCode})`
624
- : (ev.errorMessage ?? ev.errorCode ?? 'run failed'),
628
+ : (ev.errorMessage ?? ev.errorCode ?? 'run failed'), ev.errorCode),
625
629
  ],
626
630
  });
627
631
  }
@@ -3,7 +3,8 @@ import { eventToSdkMessage, turnEndUsage } from './downstream/eventToSdkMessage.
3
3
  import { turnUsageToModelUsage } from './downstream/turnUsageToModelUsage.js';
4
4
  import { readRunCostFacts, terminalToSdkResult, TOOL_INPUT_JOIN_MAX_CALLS } from './downstream/terminalToSdkResult.js';
5
5
  import { coerceOutput, publishSubagentContentEvent } from '../subagentContentStore.js';
6
- import { ACTIVE_RUN_BUSY_ERROR_CODE, OUTPUT_INVALID, isLimitsExceededCode } from '../engineErrorCodes.js';
6
+ import { ACTIVE_RUN_BUSY_ERROR_CODE, OUTPUT_INVALID, isCorruptSessionCode, isLimitsExceededCode } from '../engineErrorCodes.js';
7
+ import { corruptSessionContent } from '../corruptSessionCopy.js';
7
8
  import { isReviewPark, readRunTerminal, runTerminalCode } from '../runTerminal.js';
8
9
  import { washCredentials } from '../displayUntrusted.js';
9
10
  import { ccToolDenialKindForToolEnd, gateDeniedBy, gateOutcomeOf } from '../gateOutcome.js';
@@ -474,7 +475,10 @@ async function* runStreamInner(events, ctx, handle = {}) {
474
475
  ?
475
476
  `${MODEL_OUTPUT_ERROR_PREFIX}: ${errText}${maxTokHint}`
476
477
  : `API Error: ${errText}${maxTokHint}`;
477
- yield syntheticTerminalRow(ctx, rowText);
478
+ const sessionUnreadable = ev.type === 'failed'
479
+ ? isCorruptSessionCode(ev.errorCode)
480
+ : doneTerminal?.kind === 'failed' && isCorruptSessionCode(doneTerminal.code);
481
+ yield syntheticTerminalRow(ctx, sessionUnreadable ? `${rowText}\n${corruptSessionContent()}` : rowText);
478
482
  }
479
483
  if (ev.type === 'done' && isReviewPark(doneTerminal) && ctx.emitChrome) {
480
484
  try {
@@ -0,0 +1,50 @@
1
+ import type { AgentClient, SessionBackgroundStopOutcome } from '@sema-agent/sdk';
2
+ import type { EngineWireInjection } from '../engineWireSdk.js';
3
+ export type EngineSessionBackgroundStopClient = {
4
+ sessions: Pick<AgentClient['sessions'], 'backgroundStop'>;
5
+ };
6
+ export type EngineSessionBackgroundStopWire = EngineWireInjection<EngineSessionBackgroundStopClient>;
7
+ export interface EngineSessionBackgroundStopOptions {
8
+ wire?: EngineSessionBackgroundStopWire;
9
+ signal?: AbortSignal;
10
+ sessionKey?: string;
11
+ }
12
+ export interface EngineSessionBackgroundReceipt {
13
+ readonly id: string;
14
+ readonly outcome: SessionBackgroundStopOutcome | (string & {});
15
+ }
16
+ export type EngineSessionBackgroundStopUnavailableWhy = 'bad_input' | 'no_wire' | 'capability_unknown' | 'no_exit_face';
17
+ export type EngineSessionBackgroundStopRefusedWhy = 'credentials_required' | 'not_permitted' | 'ownership_required' | 'session_not_found' | 'route_absent' | 'bad_request' | 'rate_limited' | 'other';
18
+ export type EngineSessionBackgroundStopResult = {
19
+ kind: 'stopped';
20
+ receipts?: readonly EngineSessionBackgroundReceipt[];
21
+ unreadableReceipts?: number;
22
+ } | {
23
+ kind: 'unavailable';
24
+ why: EngineSessionBackgroundStopUnavailableWhy;
25
+ detail: string;
26
+ } | {
27
+ kind: 'refused';
28
+ why: EngineSessionBackgroundStopRefusedWhy;
29
+ detail: string;
30
+ status?: number;
31
+ errorCode?: string;
32
+ retryAfterMs?: number;
33
+ } | {
34
+ kind: 'error';
35
+ detail: string;
36
+ status?: number;
37
+ errorCode?: string;
38
+ unconfirmed?: true;
39
+ };
40
+ export declare function stopEngineSessionBackground(sessionId: string, body: {
41
+ readonly includeRetained: boolean;
42
+ }, opts?: EngineSessionBackgroundStopOptions): Promise<EngineSessionBackgroundStopResult>;
43
+ export type EngineSessionBackgroundReceiptState = 'stopped' | 'still_running' | 'may_be_running';
44
+ export declare const ENGINE_SESSION_BACKGROUND_RECEIPT_STATES: readonly EngineSessionBackgroundReceiptState[];
45
+ export interface EngineSessionBackgroundReceiptReading {
46
+ readonly state: EngineSessionBackgroundReceiptState;
47
+ readonly text: string;
48
+ readonly unrecognizedOutcome?: string;
49
+ }
50
+ export declare function engineSessionBackgroundReceiptReadingOf(outcome: string): EngineSessionBackgroundReceiptReading;
@@ -0,0 +1,291 @@
1
+ import { engineCapValue } from '../engineCapsCache.js';
2
+ import { isStatusDerivedCoarseCode } from '../engineErrorCodes.js';
3
+ import { clientHasVerbs, engineWireFor, INJECTED_WIRE_SETTLE_MS, noAnswerDetailFrom, sendOnce, settleInjected } from '../engineWireFor.js';
4
+ import { engineWireDebugEnabled } from '../engineWireTarget.js';
5
+ import { hostLog } from '../host.js';
6
+ import { DEFAULT_SESSION_KEY } from '../sessionSlot.js';
7
+ const NOTHING_SENT = ' — nothing sent';
8
+ const DETAIL_BAD_SESSION = `the session id must be a non-empty string${NOTHING_SENT}`;
9
+ const DETAIL_BAD_INCLUDE_RETAINED = `includeRetained must be true or false (the engine has no default for it)${NOTHING_SENT}`;
10
+ const DETAIL_BAD_OPTIONS = `the options could not be read${NOTHING_SENT}`;
11
+ const DETAIL_BAD_ARGUMENTS = `the arguments could not be read${NOTHING_SENT}`;
12
+ const DETAIL_BAD_SESSION_KEY = `the session key must be a non-empty string${NOTHING_SENT}`;
13
+ const DETAIL_BAD_SIGNAL = `the signal must be an AbortSignal${NOTHING_SENT}`;
14
+ const DETAIL_INJECTED_UNUSABLE = `the connection supplied by the host cannot send this request (no usable sessions.backgroundStop)${NOTHING_SENT}`;
15
+ const DETAIL_NO_TARGET = `no engine connection is installed for this session${NOTHING_SENT}`;
16
+ const DETAIL_NO_CLIENT = `an engine client could not be built from the installed connection${NOTHING_SENT}`;
17
+ const DETAIL_CAPS_KEY_REQUIRED = `capability evidence for background.exitFaces is not available under the key the host named (capsBaseUrl)${NOTHING_SENT}`;
18
+ const DETAIL_CAPS_UNOBSERVED = `the engine capabilities have not been read for this connection yet — wait for the capability probe to settle, then call again${NOTHING_SENT}`;
19
+ const DETAIL_NO_EXIT_FACE = `this engine does not offer the session background stop (capabilities.background.exitFaces is not true); background tasks may keep running${NOTHING_SENT}`;
20
+ function refusedDetail(why) {
21
+ switch (why) {
22
+ case 'credentials_required':
23
+ return 'this engine does not accept stop requests until it is configured with a service credential';
24
+ case 'not_permitted':
25
+ return 'this caller is not permitted to stop the background tasks of this session';
26
+ case 'ownership_required':
27
+ return 'this engine has no session ownership face, so it cannot stop session background tasks';
28
+ case 'session_not_found':
29
+ return 'the engine does not know this session';
30
+ case 'route_absent':
31
+ return 'this engine has no session background stop route';
32
+ case 'bad_request':
33
+ return 'the engine rejected the request shape';
34
+ case 'rate_limited':
35
+ return 'the engine is rate-limiting stop requests — try again later';
36
+ case 'other':
37
+ return 'the engine refused the stop';
38
+ default: {
39
+ const unreachable = why;
40
+ return unreachable;
41
+ }
42
+ }
43
+ }
44
+ function note(msg) {
45
+ try {
46
+ hostLog('debug', `[session-background] stop: ${msg}`);
47
+ return true;
48
+ }
49
+ catch {
50
+ return false;
51
+ }
52
+ }
53
+ function debugOn() {
54
+ try {
55
+ return engineWireDebugEnabled();
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
61
+ function unavailable(why, detail) {
62
+ note(`unavailable (${why})`);
63
+ return { kind: 'unavailable', why, detail };
64
+ }
65
+ function usableStopClient(client) {
66
+ return clientHasVerbs(client, [['sessions', 'backgroundStop']]);
67
+ }
68
+ function exitFaceGate(capsKey) {
69
+ try {
70
+ const v = engineCapValue(capsKey, 'background');
71
+ if (v.kind === 'unobserved')
72
+ return { why: 'capability_unknown', detail: DETAIL_CAPS_UNOBSERVED };
73
+ if (v.kind !== 'value')
74
+ return { why: 'no_exit_face', detail: DETAIL_NO_EXIT_FACE };
75
+ const bg = v.value;
76
+ if (typeof bg !== 'object' || bg === null || !Object.hasOwn(bg, 'exitFaces'))
77
+ return { why: 'no_exit_face', detail: DETAIL_NO_EXIT_FACE };
78
+ return bg.exitFaces === true ? null : { why: 'no_exit_face', detail: DETAIL_NO_EXIT_FACE };
79
+ }
80
+ catch {
81
+ return { why: 'capability_unknown', detail: DETAIL_CAPS_UNOBSERVED };
82
+ }
83
+ }
84
+ function readReceipt(v) {
85
+ if (typeof v !== 'object' || v === null || Array.isArray(v))
86
+ return undefined;
87
+ const id = Object.hasOwn(v, 'id') ? v.id : undefined;
88
+ const outcome = Object.hasOwn(v, 'outcome') ? v.outcome : undefined;
89
+ if (typeof id !== 'string' || id.length === 0 || typeof outcome !== 'string' || outcome.length === 0)
90
+ return undefined;
91
+ return { id, outcome };
92
+ }
93
+ function readStopped(body) {
94
+ if (typeof body !== 'object' || body === null || !Object.hasOwn(body, 'receipts')) {
95
+ note('stopped (receipt list unreadable)');
96
+ return { kind: 'stopped' };
97
+ }
98
+ const raw = body.receipts;
99
+ if (!Array.isArray(raw)) {
100
+ note('stopped (receipt list unreadable)');
101
+ return { kind: 'stopped' };
102
+ }
103
+ const receipts = [];
104
+ let unreadable = 0;
105
+ for (const r of raw) {
106
+ const got = readReceipt(r);
107
+ if (got === undefined)
108
+ unreadable++;
109
+ else
110
+ receipts.push(got);
111
+ }
112
+ if (unreadable > 0)
113
+ note(`stopped (${unreadable} receipt(s) unreadable)`);
114
+ else if (debugOn())
115
+ note(`stopped (${receipts.length} receipt(s))`);
116
+ return { kind: 'stopped', receipts, ...(unreadable > 0 ? { unreadableReceipts: unreadable } : {}) };
117
+ }
118
+ function refusedWhyOf(rawCode, status) {
119
+ const code = rawCode !== undefined && status !== undefined && isStatusDerivedCoarseCode(rawCode) ? undefined : rawCode;
120
+ if (code !== undefined) {
121
+ if (code === 'auth.service_token_required')
122
+ return 'credentials_required';
123
+ if (code === 'capability.session_ownership_required')
124
+ return 'ownership_required';
125
+ if (code === 'not_found.session')
126
+ return 'session_not_found';
127
+ if (code === 'not_found.route')
128
+ return 'route_absent';
129
+ if (code === 'limit.rate_exceeded')
130
+ return 'rate_limited';
131
+ if (code.startsWith('auth.'))
132
+ return 'not_permitted';
133
+ if (code.startsWith('request.'))
134
+ return 'bad_request';
135
+ }
136
+ if (status === undefined)
137
+ return undefined;
138
+ if (status === 429)
139
+ return 'rate_limited';
140
+ if (status === 401 || status === 403)
141
+ return 'not_permitted';
142
+ if (status === 400)
143
+ return 'bad_request';
144
+ if (status >= 400 && status < 500)
145
+ return 'other';
146
+ return undefined;
147
+ }
148
+ function diagOf(e) {
149
+ const o = e;
150
+ const rawStatus = o.status ?? o.statusCode;
151
+ const status = typeof rawStatus === 'number' && Number.isInteger(rawStatus) ? rawStatus : undefined;
152
+ const errorCode = typeof o.errorCode === 'string' && o.errorCode.length > 0 ? o.errorCode : undefined;
153
+ const ra = o.retryAfterMs;
154
+ const retryAfterMs = typeof ra === 'number' && Number.isFinite(ra) && ra >= 0 ? ra : undefined;
155
+ const message = typeof o.message === 'string' && o.message.length > 0 ? o.message : undefined;
156
+ return {
157
+ ...(status !== undefined ? { status } : {}),
158
+ ...(errorCode !== undefined ? { errorCode } : {}),
159
+ ...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
160
+ ...(message !== undefined ? { message } : {}),
161
+ };
162
+ }
163
+ function classifyFailure(e) {
164
+ try {
165
+ if (typeof e !== 'object' || e === null) {
166
+ note('error (non-object failure)');
167
+ return { kind: 'error', detail: `the stop request failed: ${String(e).slice(0, 200)}` };
168
+ }
169
+ const d = diagOf(e);
170
+ if (d.status === undefined && d.errorCode === undefined) {
171
+ const noAnswer = noAnswerDetailFrom(e);
172
+ if (noAnswer !== null) {
173
+ note('error (no answer — the stop may have taken effect)');
174
+ return { kind: 'error', detail: noAnswer, unconfirmed: true };
175
+ }
176
+ }
177
+ const diag = { ...(d.status !== undefined ? { status: d.status } : {}), ...(d.errorCode !== undefined ? { errorCode: d.errorCode } : {}) };
178
+ const bits = [d.status !== undefined ? `status=${d.status}` : '', d.errorCode !== undefined ? `errorCode=${d.errorCode}` : ''].filter((b) => b.length > 0).join(' ');
179
+ const why = refusedWhyOf(d.errorCode, d.status);
180
+ if (why !== undefined) {
181
+ note(`refused (${why})${bits.length > 0 ? ` ${bits}` : ''}`);
182
+ return {
183
+ kind: 'refused',
184
+ why,
185
+ detail: `${refusedDetail(why)}${bits.length > 0 ? ` (${bits})` : ''}`,
186
+ ...diag,
187
+ ...(why === 'rate_limited' && d.retryAfterMs !== undefined ? { retryAfterMs: d.retryAfterMs } : {}),
188
+ };
189
+ }
190
+ note(`error${bits.length > 0 ? ` ${bits}` : ''}`);
191
+ return { kind: 'error', detail: (d.message ?? 'the stop request failed').slice(0, 300), ...diag };
192
+ }
193
+ catch {
194
+ note('error (the failure could not be read)');
195
+ return { kind: 'error', detail: 'the stop request failed (the error could not be read)' };
196
+ }
197
+ }
198
+ export async function stopEngineSessionBackground(sessionId, body, opts) {
199
+ let includeRetained;
200
+ let wireIn;
201
+ let signal;
202
+ let sessionKey;
203
+ try {
204
+ if (typeof sessionId !== 'string' || sessionId.length === 0)
205
+ return unavailable('bad_input', DETAIL_BAD_SESSION);
206
+ const flag = typeof body === 'object' && body !== null && Object.hasOwn(body, 'includeRetained') ? body.includeRetained : undefined;
207
+ if (typeof flag !== 'boolean')
208
+ return unavailable('bad_input', DETAIL_BAD_INCLUDE_RETAINED);
209
+ includeRetained = flag;
210
+ if (opts !== undefined && opts !== null && typeof opts !== 'object')
211
+ return unavailable('bad_input', DETAIL_BAD_OPTIONS);
212
+ wireIn = opts?.wire;
213
+ const sig = opts?.signal;
214
+ if (sig !== undefined && sig !== null && (typeof sig !== 'object' || typeof sig.addEventListener !== 'function' || typeof sig.aborted !== 'boolean')) {
215
+ return unavailable('bad_input', DETAIL_BAD_SIGNAL);
216
+ }
217
+ signal = sig ?? undefined;
218
+ const key = opts?.sessionKey;
219
+ if (key !== undefined && (typeof key !== 'string' || key.length === 0))
220
+ return unavailable('bad_input', DETAIL_BAD_SESSION_KEY);
221
+ sessionKey = key ?? DEFAULT_SESSION_KEY;
222
+ }
223
+ catch {
224
+ return unavailable('bad_input', DETAIL_BAD_ARGUMENTS);
225
+ }
226
+ let resolved;
227
+ try {
228
+ resolved = engineWireFor(wireIn, sessionKey, usableStopClient);
229
+ }
230
+ catch {
231
+ return unavailable('no_wire', wireIn !== undefined ? DETAIL_INJECTED_UNUSABLE : DETAIL_NO_TARGET);
232
+ }
233
+ if (resolved.kind === 'injected-unusable')
234
+ return unavailable('no_wire', DETAIL_INJECTED_UNUSABLE);
235
+ if (resolved.kind === 'no-target')
236
+ return unavailable('no_wire', DETAIL_NO_TARGET);
237
+ if (resolved.kind === 'injected' && resolved.capsBaseUrl === undefined)
238
+ return unavailable('capability_unknown', DETAIL_CAPS_KEY_REQUIRED);
239
+ const gate = exitFaceGate(resolved.kind === 'injected' ? resolved.capsBaseUrl : resolved.target.baseUrl);
240
+ if (gate !== null)
241
+ return unavailable(gate.why, gate.detail);
242
+ let client;
243
+ try {
244
+ client = resolved.kind === 'injected' ? resolved.client : resolved.make();
245
+ }
246
+ catch {
247
+ client = null;
248
+ }
249
+ if (client === null)
250
+ return unavailable('no_wire', DETAIL_NO_CLIENT);
251
+ const stopBody = { includeRetained };
252
+ const stopOnce = (s) => client.sessions.backgroundStop(sessionId, stopBody, s !== undefined ? { signal: s } : undefined);
253
+ let answered;
254
+ try {
255
+ answered = resolved.kind === 'injected' ? await settleInjected(INJECTED_WIRE_SETTLE_MS, signal, stopOnce) : await sendOnce(signal, () => stopOnce(signal));
256
+ }
257
+ catch (e) {
258
+ return classifyFailure(e);
259
+ }
260
+ try {
261
+ return readStopped(answered);
262
+ }
263
+ catch {
264
+ note('stopped (receipt list unreadable)');
265
+ return { kind: 'stopped' };
266
+ }
267
+ }
268
+ const RECEIPT_STATE_TEXT = {
269
+ stopped: 'Stopped.',
270
+ still_running: 'Still running — it was set to keep running, so it was left in place.',
271
+ may_be_running: 'May still be running — the engine could not confirm that it ended.',
272
+ };
273
+ export const ENGINE_SESSION_BACKGROUND_RECEIPT_STATES = Object.freeze(Object.keys(RECEIPT_STATE_TEXT));
274
+ function receiptReading(state) {
275
+ return { state, text: RECEIPT_STATE_TEXT[state] };
276
+ }
277
+ export function engineSessionBackgroundReceiptReadingOf(outcome) {
278
+ if (typeof outcome !== 'string')
279
+ return receiptReading('may_be_running');
280
+ switch (outcome) {
281
+ case 'killed':
282
+ case 'already_gone':
283
+ return receiptReading('stopped');
284
+ case 'retained_skipped':
285
+ return receiptReading('still_running');
286
+ case 'no_pgid':
287
+ return receiptReading('may_be_running');
288
+ default:
289
+ return { ...receiptReading('may_be_running'), unrecognizedOutcome: outcome };
290
+ }
291
+ }
@@ -1,4 +1,5 @@
1
1
  import { type EngineProbeOpts, type WireAuthTokenSource } from './engineWireSdk.js';
2
+ import type { ReasoningEffort } from './effortWire.js';
2
3
  export declare const MAX_TASK_AGENTS = 32;
3
4
  export declare const MAX_AGENT_NAME_CHARS = 64;
4
5
  export declare const MAX_AGENT_TEXT_CHARS = 4096;
@@ -8,7 +9,7 @@ export declare const MAX_AGENT_TOOL_NAME_CHARS = 128;
8
9
  export declare const MAX_AGENT_SKILL_CONTENT_CHARS = 1048576;
9
10
  export declare const MAX_AGENT_MAX_TURNS = 1000;
10
11
  export declare const TASK_AGENT_WIRE_FIELDS: readonly ["name", "whenToUse", "whenToUseLean", "allowTools", "denyTools", "skills", "background", "isolation", "model", "thinking", "systemPrompt", "maxTurns", "memory", "observer", "observerMessage"];
11
- export type WireThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
12
+ export type WireThinkingLevel = ReasoningEffort;
12
13
  export type TaskAgentWireSkill = {
13
14
  name: string;
14
15
  description: string;
@@ -1,5 +1,6 @@
1
1
  import { MCP_CAPS } from './mcpWireCaps.js';
2
2
  import { toCappedSpec } from './skillsWireCaps.js';
3
+ import { TIER_ORDER } from './model/tierVocabulary.js';
3
4
  const asRec = (v) => (typeof v === 'object' && v !== null && !Array.isArray(v) ? v : undefined);
4
5
  const asArr = (v) => (Array.isArray(v) ? v : []);
5
6
  const asStr = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
@@ -127,7 +128,7 @@ function withoutRegistryAnnotations(e) {
127
128
  }
128
129
  return out;
129
130
  }
130
- const TIER_WORDS = Object.freeze(['ultra', 'max', 'pro', 'flash', 'lite']);
131
+ const TIER_WORDS = TIER_ORDER;
131
132
  const TIER_GROUP_NAME = /^[a-z0-9][a-z0-9._-]*$/i;
132
133
  const setOwn = (o, k, v) => {
133
134
  Object.defineProperty(o, k, { value: v, enumerable: true, writable: true, configurable: true });
@@ -0,0 +1,3 @@
1
+ export declare function isCorruptSessionError(err: unknown): boolean;
2
+ export declare function isCorruptSessionResult(result: unknown): boolean;
3
+ export declare function isCorruptSessionRunRow(row: unknown): boolean;
@@ -0,0 +1,29 @@
1
+ import { isCorruptSessionCode } from './engineErrorCodes.js';
2
+ import { effectiveWireErrorCode } from './wireErrorTriage.js';
3
+ import { readRunTerminal } from './runTerminal.js';
4
+ export function isCorruptSessionError(err) {
5
+ return isCorruptSessionCode(effectiveWireErrorCode(err));
6
+ }
7
+ export function isCorruptSessionResult(result) {
8
+ try {
9
+ const read = readRunTerminal(result);
10
+ return read !== null && read.kind === 'failed' && isCorruptSessionCode(read.code);
11
+ }
12
+ catch {
13
+ return false;
14
+ }
15
+ }
16
+ export function isCorruptSessionRunRow(row) {
17
+ if (typeof row !== 'object' || row === null || Array.isArray(row))
18
+ return false;
19
+ try {
20
+ const read = readRunTerminal(row.result);
21
+ if (read !== null)
22
+ return read.kind === 'failed' && isCorruptSessionCode(read.code);
23
+ const column = row.errorCode;
24
+ return typeof column === 'string' && isCorruptSessionCode(column);
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ }
@@ -0,0 +1 @@
1
+ export declare function corruptSessionContent(): string;
@@ -0,0 +1,4 @@
1
+ export function corruptSessionContent() {
2
+ return ("This session's saved history cannot be read — its stored log is damaged — so the engine cannot open this session. " +
3
+ 'Retrying will not help: whoever operates this engine has to repair or remove that stored log. Until then, continue in a new session.');
4
+ }
@@ -1,10 +1,13 @@
1
1
  import { corruptStoredRowContent, corruptStoredRowWhere } from './wireErrorTriage.js';
2
2
  import { parkedResumeStartupContent, parkedResumeStartupFromError, resumePolicyBlockContent, resumePolicyBlockFromError, } from './resumeRefusalCopy.js';
3
+ import { decideParkMovedContent, decideParkMovedFromError } from './decideReceipt.js';
3
4
  export function decideFailureNote(err, decision) {
4
5
  const where = corruptStoredRowWhere(err);
5
6
  const fold = resumePolicyBlockFromError(err);
6
7
  const startup = parkedResumeStartupFromError(err, decision);
8
+ const moved = decideParkMovedFromError(err);
7
9
  return ((where === undefined ? '' : ` — ${corruptStoredRowContent(where)}`) +
8
10
  (fold === null ? '' : ` — ${resumePolicyBlockContent(fold)}`) +
9
- (startup === null ? '' : ` — ${parkedResumeStartupContent(startup)}`));
11
+ (startup === null ? '' : ` — ${parkedResumeStartupContent(startup)}`) +
12
+ (moved === null ? '' : ` — ${decideParkMovedContent(moved)}`));
10
13
  }
@@ -21,3 +21,9 @@ export interface DecideRefusalDetail {
21
21
  resendable: boolean;
22
22
  }
23
23
  export declare function decideRefusalFromError(e: unknown): DecideRefusalDetail | null;
24
+ export interface DecideParkMovedDetail {
25
+ code: string;
26
+ taskId?: string;
27
+ }
28
+ export declare function decideParkMovedFromError(e: unknown): DecideParkMovedDetail | null;
29
+ export declare function decideParkMovedContent(detail: Pick<DecideParkMovedDetail, 'code'>): string;
@@ -1,6 +1,8 @@
1
1
  import { gateOutcomeOf } from './gateOutcome.js';
2
2
  import { resumeReopenFromError } from './resumeRefusalCopy.js';
3
- import { DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, } from './engineErrorCodes.js';
3
+ import { DECIDE_CLAIM_LOST, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, isDecideParkMovedCode, } from './engineErrorCodes.js';
4
+ import { effectiveWireErrorCode } from './wireErrorTriage.js';
5
+ import { readErrorString } from './wireFailureShape.js';
4
6
  const STATUS_RESUMING = 'resuming';
5
7
  function str(v) {
6
8
  return typeof v === 'string' && v.length > 0 ? v : undefined;
@@ -77,3 +79,30 @@ export function decideRefusalFromError(e) {
77
79
  resendable: Object.hasOwn(DECIDE_RESENDABLE, code) ? DECIDE_RESENDABLE[code] === true : false,
78
80
  };
79
81
  }
82
+ export function decideParkMovedFromError(e) {
83
+ const code = effectiveWireErrorCode(e);
84
+ if (code === undefined || !isDecideParkMovedCode(code))
85
+ return null;
86
+ const taskId = readErrorString(e, 'taskId');
87
+ return { code, ...(taskId !== undefined && taskId.length > 0 ? { taskId } : {}) };
88
+ }
89
+ const DECIDE_PARK_MOVED_WHAT = Object.freeze({
90
+ [DECIDE_NOT_PARKED]: 'This approval was no longer waiting when the decision arrived (the agent was stopped, the approval was decided elsewhere, or the session it belongs to was deleted)',
91
+ [DECIDE_GATE_MOVED]: 'This approval moved while the decision was on its way (it was parked again, or settled elsewhere)',
92
+ [DECIDE_CLAIM_LOST]: 'Another decision on this approval got there first, or an earlier attempt is still holding it until the engine clears that hold on its own',
93
+ });
94
+ export function decideParkMovedContent(detail) {
95
+ let code;
96
+ try {
97
+ const raw = detail !== null && typeof detail === 'object' ? detail.code : undefined;
98
+ code = typeof raw === 'string' ? raw : undefined;
99
+ }
100
+ catch {
101
+ code = undefined;
102
+ }
103
+ const what = code !== undefined && Object.hasOwn(DECIDE_PARK_MOVED_WHAT, code)
104
+ ? DECIDE_PARK_MOVED_WHAT[code]
105
+ : 'This approval changed state while the decision was on its way';
106
+ const extra = code === DECIDE_CLAIM_LOST ? '; if this approval is still listed, wait a little before deciding it again' : '';
107
+ return `${what} · This decision was not applied — fetch the pending approvals again and decide from what is pending now${extra}`;
108
+ }
@@ -1,2 +1,3 @@
1
- export type ReasoningEffort = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
1
+ import { type TaskRequestReasoningEffort } from './taskRequestWords.js';
2
+ export type ReasoningEffort = TaskRequestReasoningEffort;
2
3
  export declare function effortToReasoningEffort(effort: unknown): ReasoningEffort | undefined;
@@ -1,7 +1,5 @@
1
- const REASONING_EFFORT_TUPLE = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'];
2
- const _effortPins = [true, true];
3
- void _effortPins;
4
- const REASONING_EFFORTS = new Set(REASONING_EFFORT_TUPLE);
1
+ import { REASONING_EFFORT_WORDS } from './taskRequestWords.js';
2
+ const REASONING_EFFORTS = new Set(REASONING_EFFORT_WORDS);
5
3
  export function effortToReasoningEffort(effort) {
6
4
  return typeof effort === 'string' && REASONING_EFFORTS.has(effort) ? effort : undefined;
7
5
  }
@@ -28,6 +28,8 @@ export declare function isInterruptedToolEndCode(code: string | undefined): bool
28
28
  export declare const CAPABILITY_SELF_ORCHESTRATION_REQUIRED = "capability.self_orchestration_required";
29
29
  export declare const GATE_PARKED_ERROR_CODE = "gate.parked";
30
30
  export declare const ACTIVE_RUN_BUSY_ERROR_CODE = "conflict.session_active_run";
31
+ export declare const CORRUPT_SESSION_ERROR_CODE = "corrupt_session";
32
+ export declare function isCorruptSessionCode(code: string | null | undefined): boolean;
31
33
  export declare const STOP_PARK_ARBITER_UNREACHABLE = "stop.park_arbiter_unreachable";
32
34
  export declare const STOP_PARK_RESUME_WON = "stop.park_resume_won";
33
35
  export declare const STOP_NOT_LANDED = "stop.not_landed";
@@ -36,6 +38,8 @@ export declare const STOP_PARKED = "stop.parked";
36
38
  export declare const STOP_CONFLICT_CODES: readonly ["stop.park_arbiter_unreachable", "stop.park_resume_won", "stop.not_landed", "stop.not_local", "stop.parked"];
37
39
  export declare const OUTPUT_INVALID = "output.invalid";
38
40
  export declare const RESUME_POLICY_FOLD_CODE = "resume_blocked_by_policy";
41
+ export declare const STATUS_DERIVED_COARSE_CODES: readonly ["request.rejected", "auth.unauthorized", "auth.forbidden", "not_found.resource", "request.payload_too_large", "request.unprocessable", "limit.rate_exceeded", "capability.unavailable", "internal.error"];
42
+ export declare function isStatusDerivedCoarseCode(code: string | null | undefined): boolean;
39
43
  export declare const RESUME_AT_ERROR_CODE_PREFIX = "resume_at.";
40
44
  export declare const REWIND_ERROR_CODE_PREFIXES: readonly ["resume_at.", "rewind_snapshot."];
41
45
  export declare function isRewindFamilyCode(code: string | undefined): boolean;
@@ -52,6 +56,11 @@ export declare const PARKED_RESUME_STARTUP_FAILED = "parked_resume.startup_faile
52
56
  export declare const DECIDE_WORKFLOW_HOST_UNKNOWN = "decide.workflow_host_unknown";
53
57
  export declare const DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED = "decide.workflow_remember_unsupported";
54
58
  export declare const DECIDE_WORKFLOW_LANE_CODES: readonly string[];
59
+ export declare const DECIDE_NOT_PARKED = "decide.not_parked";
60
+ export declare const DECIDE_GATE_MOVED = "decide.gate_moved";
61
+ export declare const DECIDE_CLAIM_LOST = "decide.claim_lost";
62
+ export declare const DECIDE_PARK_MOVED_CODES: readonly string[];
63
+ export declare function isDecideParkMovedCode(code: string | null | undefined): boolean;
55
64
  export declare const WORKFLOW_PARK_REFUSAL_CODES: readonly string[];
56
65
  export declare function isWorkflowParkRefusalCode(code: unknown): boolean;
57
66
  export declare const DRAINING_ERROR_CODE = "draining";
@@ -59,6 +59,10 @@ export function isInterruptedToolEndCode(code) {
59
59
  export const CAPABILITY_SELF_ORCHESTRATION_REQUIRED = 'capability.self_orchestration_required';
60
60
  export const GATE_PARKED_ERROR_CODE = 'gate.parked';
61
61
  export const ACTIVE_RUN_BUSY_ERROR_CODE = 'conflict.session_active_run';
62
+ export const CORRUPT_SESSION_ERROR_CODE = 'corrupt_session';
63
+ export function isCorruptSessionCode(code) {
64
+ return code === CORRUPT_SESSION_ERROR_CODE;
65
+ }
62
66
  export const STOP_PARK_ARBITER_UNREACHABLE = 'stop.park_arbiter_unreachable';
63
67
  export const STOP_PARK_RESUME_WON = 'stop.park_resume_won';
64
68
  export const STOP_NOT_LANDED = 'stop.not_landed';
@@ -73,6 +77,20 @@ export const STOP_CONFLICT_CODES = Object.freeze([
73
77
  ]);
74
78
  export const OUTPUT_INVALID = 'output.invalid';
75
79
  export const RESUME_POLICY_FOLD_CODE = 'resume_blocked_by_policy';
80
+ export const STATUS_DERIVED_COARSE_CODES = Object.freeze([
81
+ 'request.rejected',
82
+ 'auth.unauthorized',
83
+ 'auth.forbidden',
84
+ 'not_found.resource',
85
+ 'request.payload_too_large',
86
+ 'request.unprocessable',
87
+ 'limit.rate_exceeded',
88
+ 'capability.unavailable',
89
+ 'internal.error',
90
+ ]);
91
+ export function isStatusDerivedCoarseCode(code) {
92
+ return typeof code === 'string' && STATUS_DERIVED_COARSE_CODES.includes(code);
93
+ }
76
94
  export const RESUME_AT_ERROR_CODE_PREFIX = 'resume_at.';
77
95
  export const REWIND_ERROR_CODE_PREFIXES = Object.freeze([RESUME_AT_ERROR_CODE_PREFIX, 'rewind_snapshot.']);
78
96
  export function isRewindFamilyCode(code) {
@@ -101,6 +119,17 @@ export const DECIDE_WORKFLOW_LANE_CODES = Object.freeze([
101
119
  DECIDE_WORKFLOW_HOST_UNKNOWN,
102
120
  DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED,
103
121
  ]);
122
+ export const DECIDE_NOT_PARKED = 'decide.not_parked';
123
+ export const DECIDE_GATE_MOVED = 'decide.gate_moved';
124
+ export const DECIDE_CLAIM_LOST = 'decide.claim_lost';
125
+ export const DECIDE_PARK_MOVED_CODES = Object.freeze([
126
+ DECIDE_NOT_PARKED,
127
+ DECIDE_GATE_MOVED,
128
+ DECIDE_CLAIM_LOST,
129
+ ]);
130
+ export function isDecideParkMovedCode(code) {
131
+ return typeof code === 'string' && DECIDE_PARK_MOVED_CODES.includes(code);
132
+ }
104
133
  const WORKFLOW_PARK_TRUTH_UNREADABLE = 'workflow.park_truth_unreadable';
105
134
  const WORKFLOW_PARK_NOT_PENDING = 'workflow.park_not_pending';
106
135
  const WORKFLOW_PARK_BINDING_BROKEN = 'workflow.park_binding_broken';