@sema-agent/client-core 0.89.0 → 0.91.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 (104) hide show
  1. package/CHANGELOG.md +297 -0
  2. package/README.md +35 -24
  3. package/dist/adapt/arms.js +9 -0
  4. package/dist/adapter/downstream/eventToSdkMessage.js +4 -2
  5. package/dist/adapter/downstream/wiringManifestView.d.ts +6 -0
  6. package/dist/adapter/downstream/wiringManifestView.js +16 -0
  7. package/dist/adapter/runStream.d.ts +2 -0
  8. package/dist/adapter/runStream.js +180 -38
  9. package/dist/askSurvivesStandingAnswer.d.ts +10 -0
  10. package/dist/askSurvivesStandingAnswer.js +40 -0
  11. package/dist/attachmentSeatCapability.d.ts +11 -0
  12. package/dist/attachmentSeatCapability.js +27 -0
  13. package/dist/attachmentsWireCaps.d.ts +22 -2
  14. package/dist/attachmentsWireCaps.js +95 -22
  15. package/dist/compensations.js +10 -14
  16. package/dist/controlRouter.d.ts +9 -2
  17. package/dist/controlRouter.js +66 -28
  18. package/dist/coreValuePorts.d.ts +1 -0
  19. package/dist/decideFailureNote.js +4 -2
  20. package/dist/disableSkillsWire.d.ts +1 -0
  21. package/dist/disableSkillsWire.js +8 -1
  22. package/dist/displayUntrusted.js +153 -4
  23. package/dist/engineCapReader.js +12 -1
  24. package/dist/engineCapsCache.d.ts +3 -1
  25. package/dist/engineCapsCache.js +56 -6
  26. package/dist/engineClosedSets.d.ts +2 -0
  27. package/dist/engineClosedSets.js +3 -0
  28. package/dist/engineErrorCodes.d.ts +3 -0
  29. package/dist/engineErrorCodes.js +10 -0
  30. package/dist/engineNoticeCodes.d.ts +2 -9
  31. package/dist/engineNoticeCodes.js +19 -27
  32. package/dist/fileHistoryLegNotice.d.ts +20 -0
  33. package/dist/fileHistoryLegNotice.js +122 -0
  34. package/dist/gateOutcome.d.ts +1 -1
  35. package/dist/gateOutcome.js +1 -0
  36. package/dist/generated/engineFactTables.d.ts +13 -0
  37. package/dist/generated/engineFactTables.js +50 -0
  38. package/dist/generated/engineNoticeTables.js +0 -3
  39. package/dist/hitl/askGateWire.d.ts +1 -1
  40. package/dist/hitl/askGateWire.js +1 -1
  41. package/dist/hitl/crashConverged.d.ts +7 -0
  42. package/dist/hitl/crashConverged.js +57 -0
  43. package/dist/hitl/crashConvergedNotice.d.ts +4 -0
  44. package/dist/hitl/crashConvergedNotice.js +57 -0
  45. package/dist/hitl/hitlBridge.d.ts +7 -4
  46. package/dist/hitl/parkResolver.d.ts +7 -2
  47. package/dist/hitl/parkResolver.js +19 -7
  48. package/dist/hitl/planReviewWire.d.ts +1 -1
  49. package/dist/hitl/planReviewWire.js +18 -4
  50. package/dist/hitl/sessionPolicyWire.d.ts +5 -0
  51. package/dist/hitl/sessionPolicyWire.js +63 -0
  52. package/dist/hitl/suspendedReopen.js +2 -2
  53. package/dist/hitl/toolApprovalWire.d.ts +4 -1
  54. package/dist/hitl/toolApprovalWire.js +20 -0
  55. package/dist/hookMatcherVerdict.d.ts +29 -0
  56. package/dist/hookMatcherVerdict.js +265 -0
  57. package/dist/hookToolAliases.d.ts +3 -0
  58. package/dist/hookToolAliases.js +10 -0
  59. package/dist/humanTurn.d.ts +91 -0
  60. package/dist/humanTurn.js +253 -0
  61. package/dist/humanTurnRead.d.ts +105 -0
  62. package/dist/humanTurnRead.js +331 -0
  63. package/dist/index.d.ts +30 -5
  64. package/dist/index.js +19 -4
  65. package/dist/inheritEnvWire.js +1 -1
  66. package/dist/liveModelCatalog.d.ts +2 -0
  67. package/dist/liveModelCatalog.js +51 -3
  68. package/dist/permissionRuleIssue.d.ts +1 -1
  69. package/dist/permissionRuleIssue.js +22 -3
  70. package/dist/permissionsAllowGrantCapability.d.ts +18 -0
  71. package/dist/permissionsAllowGrantCapability.js +84 -0
  72. package/dist/permissionsDeclaration.d.ts +48 -0
  73. package/dist/permissionsDeclaration.js +307 -0
  74. package/dist/promptDelivery.d.ts +16 -5
  75. package/dist/promptDelivery.js +172 -32
  76. package/dist/providerRejection.d.ts +3 -1
  77. package/dist/providerRejection.js +27 -1
  78. package/dist/readDenyTiers.d.ts +10 -0
  79. package/dist/readDenyTiers.js +29 -0
  80. package/dist/request/taskRequest.js +27 -1
  81. package/dist/resumeRefusalCopy.d.ts +11 -0
  82. package/dist/resumeRefusalCopy.js +61 -4
  83. package/dist/rewindArchiveCapability.js +4 -4
  84. package/dist/rewindWireCaps.d.ts +2 -1
  85. package/dist/rewindWireCaps.js +19 -2
  86. package/dist/sdkRegistryTransit.d.ts +1 -0
  87. package/dist/sdkRegistryTransit.js +1 -0
  88. package/dist/seam.d.ts +2 -0
  89. package/dist/supportFloor.d.ts +10 -0
  90. package/dist/supportFloor.js +42 -0
  91. package/dist/taskRequestWords.d.ts +7 -0
  92. package/dist/taskRequestWords.js +24 -0
  93. package/dist/toolHistoryBadTurn.d.ts +1 -0
  94. package/dist/toolHistoryBadTurn.js +89 -0
  95. package/dist/toolHistoryMismatch.d.ts +2 -1
  96. package/dist/toolHistoryMismatch.js +19 -6
  97. package/dist/userAttachmentEnvelope.d.ts +61 -0
  98. package/dist/userAttachmentEnvelope.js +204 -0
  99. package/dist/wireFailureShape.d.ts +1 -0
  100. package/dist/wireFailureShape.js +4 -0
  101. package/dist/wireRefusalCopy.d.ts +6 -0
  102. package/dist/wireRefusalCopy.js +26 -3
  103. package/docs/INTEGRATION-CLIENTS.md +1369 -18
  104. package/package.json +3 -3
@@ -11,6 +11,7 @@ import { readAsyncLaunchedAgentReceipt } from '../toolResult.js';
11
11
  import { isWorkflowAgentTaskId, recordWorkflowAgentTaskId } from '../workflow.js';
12
12
  import { isTerminalStatus } from '../runTerminal.js';
13
13
  import { readToolHistoryMismatchKey } from '../toolHistoryMismatch.js';
14
+ import { readProviderRejectionResendKey } from '../providerRejection.js';
14
15
  import { resolveEnginePanelTaskId } from '../engineAgentPanelStore.js';
15
16
  import { fleetRowAgentType } from '../fleet/fleetRowAgentType.js';
16
17
  import { chrome, mainLane, transcript, messageIdentityOf } from './ids.js';
@@ -23,6 +24,13 @@ function toolHistoryKeyCarry(m) {
23
24
  const key = readToolHistoryMismatchKey(typeof raw === 'object' && raw !== null ? raw : undefined);
24
25
  return key === undefined ? {} : { _sema_tool_history_mismatch: key };
25
26
  }
27
+ function providerResendKeyCarry(m) {
28
+ if (m._sema_api_error_message !== true)
29
+ return {};
30
+ const raw = m._sema_provider_rejection_resend;
31
+ const key = readProviderRejectionResendKey(typeof raw === 'object' && raw !== null ? raw : undefined);
32
+ return key === undefined ? {} : { _sema_provider_rejection_resend: key };
33
+ }
26
34
  const assistantArm = function* (m, { ctx, idOf, text, cards, inst }) {
27
35
  const message = m.message;
28
36
  const blocks = Array.isArray(message?.content)
@@ -129,6 +137,7 @@ const assistantArm = function* (m, { ctx, idOf, text, cards, inst }) {
129
137
  parent_tool_use_id: null,
130
138
  ...(m._sema_api_error_message === true ? { _sema_api_error_message: true } : {}),
131
139
  ...toolHistoryKeyCarry(m),
140
+ ...providerResendKeyCarry(m),
132
141
  }, ctx.now());
133
142
  text.markEmittedText(textBlock.text);
134
143
  }
@@ -1,4 +1,4 @@
1
- import { readInstructionsSegment, wiringManifestViewOf } from './wiringManifestView.js';
1
+ import { readFleetSegment, readInstructionsSegment, wiringManifestViewOf } from './wiringManifestView.js';
2
2
  import { stamp, snapshotSegmentIdentity, } from '../types.js';
3
3
  import { turnUsageToModelUsage } from './turnUsageToModelUsage.js';
4
4
  import { ccToolDenialKindForToolEnd, gateOutcomeOf } from '../../gateOutcome.js';
@@ -551,7 +551,8 @@ function wiringManifestSupersetBody(ev) {
551
551
  const hands = projectHandsSection(ev);
552
552
  const fileHistory = projectFileHistorySection(ev);
553
553
  const instructions = readInstructionsSegment(ev, 'instructions');
554
- if (modelGate === undefined && autoMode === undefined && mcp === undefined && tools === undefined && hooks === undefined && lsp === undefined && writeProtection === undefined && autoConsolidation === undefined && readDeny === undefined && hands === undefined && fileHistory === undefined && instructions === undefined)
554
+ const fleet = readFleetSegment(ev, 'fleet');
555
+ if (modelGate === undefined && autoMode === undefined && mcp === undefined && tools === undefined && hooks === undefined && lsp === undefined && writeProtection === undefined && autoConsolidation === undefined && readDeny === undefined && hands === undefined && fileHistory === undefined && instructions === undefined && fleet === undefined)
555
556
  return undefined;
556
557
  return {
557
558
  ...(modelGate !== undefined ? { _sema_modelGate: modelGate } : {}),
@@ -566,6 +567,7 @@ function wiringManifestSupersetBody(ev) {
566
567
  ...(hands !== undefined ? { _sema_hands: hands } : {}),
567
568
  ...(fileHistory !== undefined ? { _sema_fileHistory: fileHistory } : {}),
568
569
  ...(instructions !== undefined ? { _sema_instructions: instructions } : {}),
570
+ ...(fleet !== undefined ? { _sema_fleet: fleet } : {}),
569
571
  };
570
572
  }
571
573
  function projectFileHistorySection(holder) {
@@ -15,8 +15,12 @@ export type WiringManifestSections = {
15
15
  _sema_instructions?: {
16
16
  readonly selected: readonly string[];
17
17
  };
18
+ _sema_fleet?: WiringManifestFleetView;
18
19
  eventId?: string;
19
20
  };
21
+ export interface WiringManifestFleetView {
22
+ readonly subagentTranscripts: string;
23
+ }
20
24
  export interface WiringManifestView {
21
25
  modelGate?: WiringManifestModelGate;
22
26
  autoMode?: WiringManifestAutoMode;
@@ -32,9 +36,11 @@ export interface WiringManifestView {
32
36
  instructions?: {
33
37
  readonly selected: readonly string[];
34
38
  };
39
+ fleet?: WiringManifestFleetView;
35
40
  eventId?: string;
36
41
  }
37
42
  export declare function readInstructionsSegment(holder: object, key: 'instructions' | '_sema_instructions'): {
38
43
  readonly selected: readonly string[];
39
44
  } | undefined;
45
+ export declare function readFleetSegment(holder: object, key: 'fleet' | '_sema_fleet'): WiringManifestFleetView | undefined;
40
46
  export declare function wiringManifestViewOf(s: WiringManifestSections): WiringManifestView | undefined;
@@ -27,9 +27,24 @@ export function readInstructionsSegment(holder, key) {
27
27
  return undefined;
28
28
  }
29
29
  }
30
+ export function readFleetSegment(holder, key) {
31
+ try {
32
+ if (!Object.hasOwn(holder, key))
33
+ return undefined;
34
+ const raw = holder[key];
35
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw) || !Object.hasOwn(raw, 'subagentTranscripts'))
36
+ return undefined;
37
+ const tier = raw.subagentTranscripts;
38
+ return typeof tier === 'string' && tier.length > 0 ? Object.freeze({ subagentTranscripts: tier }) : undefined;
39
+ }
40
+ catch {
41
+ return undefined;
42
+ }
43
+ }
30
44
  const isObj = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
31
45
  export function wiringManifestViewOf(s) {
32
46
  const instructions = readInstructionsSegment(s, '_sema_instructions');
47
+ const fleet = readFleetSegment(s, '_sema_fleet');
33
48
  const view = {
34
49
  ...(isObj(s._sema_modelGate) ? { modelGate: s._sema_modelGate } : {}),
35
50
  ...(isObj(s._sema_autoMode) ? { autoMode: s._sema_autoMode } : {}),
@@ -43,6 +58,7 @@ export function wiringManifestViewOf(s) {
43
58
  ...(isObj(s._sema_hands) && typeof s._sema_hands.mounted === 'boolean' ? { hands: s._sema_hands } : {}),
44
59
  ...(typeof s._sema_fileHistory === 'string' && s._sema_fileHistory.length > 0 ? { fileHistory: s._sema_fileHistory } : {}),
45
60
  ...(instructions !== undefined ? { instructions } : {}),
61
+ ...(fleet !== undefined ? { fleet } : {}),
46
62
  };
47
63
  if (Object.keys(view).length === 0)
48
64
  return undefined;
@@ -1,6 +1,7 @@
1
1
  import type { AgentEvent } from '@sema-agent/sdk';
2
2
  import { type SDKMessage, type EmitContext, type ModelUsage } from './types.js';
3
3
  import { type EngineTurnUsage } from './downstream/turnUsageToModelUsage.js';
4
+ import { type ToolHistoryErrorCarrier } from '../toolHistoryMismatch.js';
4
5
  export interface ActiveRunPendingGate {
5
6
  readonly kind: string | null;
6
7
  readonly decidePath: string | null;
@@ -27,6 +28,7 @@ export declare function isGovernanceTerminal(input: {
27
28
  status: string | undefined;
28
29
  errorCode: string | undefined;
29
30
  }): boolean;
31
+ export declare function toolHistoryErrorCarrierOf(terminalOrResult: object | null | undefined): ToolHistoryErrorCarrier;
30
32
  export declare function droppedWhySentence(why: string): string;
31
33
  export declare function _resetDroppedFrameReportForTest(): void;
32
34
  export declare function _droppedFrameMemoSizeForTest(): number;
@@ -7,6 +7,7 @@ import { ACTIVE_RUN_BUSY_ERROR_CODE, OUTPUT_INVALID, isCorruptSessionCode, isLim
7
7
  import { corruptSessionContent } from '../corruptSessionCopy.js';
8
8
  import { classifyToolHistoryMismatch, noteToolHistoryTerminal, openToolHistoryGeneration, TOOL_HISTORY_REWIND_SENTENCE, toolHistoryMismatchRowKey, toolHistoryRepeatSentence, toolHistoryRewindOffered, } from '../toolHistoryMismatch.js';
9
9
  import { isReviewPark, readRunTerminal, runTerminalCode } from '../runTerminal.js';
10
+ import { providerRejectionResend } from '../providerRejection.js';
10
11
  import { washCredentials } from '../displayUntrusted.js';
11
12
  import { ccToolDenialKindForToolEnd, gateDeniedBy, gateOutcomeOf } from '../gateOutcome.js';
12
13
  import { resumeReopenContent, resumeReopenFromError, suspendedReopenOf } from '../hitl/suspendedReopen.js';
@@ -121,7 +122,7 @@ export function isModelOutputErrorRowText(text) {
121
122
  return text.trimStart().startsWith(`${MODEL_OUTPUT_ERROR_PREFIX}:`);
122
123
  }
123
124
  export const OUTCOME_UNKNOWN_ROW_PREFIX = 'Outcome unknown';
124
- function syntheticTerminalRow(ctx, text, historyKey) {
125
+ function syntheticTerminalRow(ctx, text, historyKey, resend) {
125
126
  return stamp(ctx, {
126
127
  uuid: undefined,
127
128
  session_id: undefined,
@@ -130,6 +131,7 @@ function syntheticTerminalRow(ctx, text, historyKey) {
130
131
  parent_tool_use_id: null,
131
132
  _sema_api_error_message: true,
132
133
  ...(historyKey !== undefined ? { _sema_tool_history_mismatch: historyKey } : {}),
134
+ ...(resend !== undefined ? { _sema_provider_rejection_resend: { resend: resend.resend, text: resend.text } } : {}),
133
135
  });
134
136
  }
135
137
  function engineRunIdOf(result) {
@@ -140,11 +142,6 @@ function engineSessionIdOf(result) {
140
142
  const v = result?.sessionId;
141
143
  return typeof v === 'string' && v.length > 0 ? v : undefined;
142
144
  }
143
- function providerFailureStatusOf(result) {
144
- const af = result?.apiFailure;
145
- const status = typeof af === 'object' && af !== null ? af.status : undefined;
146
- return typeof status === 'number' && Number.isFinite(status) ? status : undefined;
147
- }
148
145
  export function isOutcomeUnknownRowText(text) {
149
146
  return text.trimStart().startsWith(`${OUTCOME_UNKNOWN_ROW_PREFIX}:`);
150
147
  }
@@ -155,6 +152,168 @@ export function isGovernanceTerminal(input) {
155
152
  return true;
156
153
  return input.errorCode === OUTPUT_INVALID;
157
154
  }
155
+ function terminalRowFacts(ev) {
156
+ const doneTerminal = ev.type === 'done' ? readRunTerminal(ev.result) : null;
157
+ const errTextRaw = ev.type === 'failed'
158
+ ? (ev.errorMessage ?? ev.errorCode ?? 'run failed')
159
+ : doneTerminal?.kind === 'failed'
160
+ ? (doneTerminal.message ?? doneTerminal.code ?? 'run failed')
161
+ : doneTerminal?.kind === 'blocked'
162
+ ? (doneTerminal.reason
163
+ ? `Run blocked: ${doneTerminal.reason}`
164
+ : 'Run blocked (the agent reported it cannot proceed)')
165
+ : null;
166
+ const errText = errTextRaw === '' ? null : errTextRaw;
167
+ if (errText === null)
168
+ return { doneTerminal, errText, activeTaskId: undefined, busy: { busy: false, handle: null }, governance: false };
169
+ const activeTaskId = (ev.type === 'done' ? ev.result?.activeTaskId : undefined) ??
170
+ (ev.type === 'failed' ? ev.activeTaskId : undefined);
171
+ const busy = classifyActiveRunBusy({
172
+ errorCode: ev.type === 'failed' ? ev.errorCode : runTerminalCode(doneTerminal),
173
+ activeTaskId,
174
+ });
175
+ const governance = isGovernanceTerminal({
176
+ status: ev.type === 'failed' ? undefined : doneTerminal?.kind === 'blocked' ? 'blocked' : undefined,
177
+ errorCode: ev.type === 'failed' ? ev.errorCode : runTerminalCode(doneTerminal),
178
+ });
179
+ return { doneTerminal, errText, activeTaskId, busy, governance };
180
+ }
181
+ const PROVIDER_REJECTED_DETAIL = 'provider_rejected';
182
+ function ownDataBit(o, k) {
183
+ try {
184
+ const d = Object.getOwnPropertyDescriptor(o, k);
185
+ return d !== undefined && Object.prototype.hasOwnProperty.call(d, 'value') ? d.value : undefined;
186
+ }
187
+ catch {
188
+ return undefined;
189
+ }
190
+ }
191
+ function plainObjectOf(v) {
192
+ if (typeof v !== 'object' || v === null)
193
+ return undefined;
194
+ try {
195
+ return Array.isArray(v) ? undefined : v;
196
+ }
197
+ catch {
198
+ return undefined;
199
+ }
200
+ }
201
+ function ownDataCopy(o, keys) {
202
+ const out = Object.create(null);
203
+ for (const k of keys) {
204
+ const v = ownDataBit(o, k);
205
+ if (v !== undefined)
206
+ out[k] = v;
207
+ }
208
+ return out;
209
+ }
210
+ function ownTerminalSnapshot(result) {
211
+ let causePlane;
212
+ try {
213
+ causePlane = 'terminal' in result;
214
+ }
215
+ catch {
216
+ return undefined;
217
+ }
218
+ const snap = ownDataCopy(result, ['status', 'errorCode', 'errorMessage']);
219
+ if (!causePlane)
220
+ return snap;
221
+ let d;
222
+ try {
223
+ d = Object.getOwnPropertyDescriptor(result, 'terminal');
224
+ }
225
+ catch {
226
+ return undefined;
227
+ }
228
+ if (d === undefined || !Object.prototype.hasOwnProperty.call(d, 'value'))
229
+ return undefined;
230
+ const t = plainObjectOf(d.value);
231
+ if (t === undefined) {
232
+ snap.terminal = null;
233
+ return snap;
234
+ }
235
+ const ts = ownDataCopy(t, ['kind', 'code', 'message']);
236
+ const detail = plainObjectOf(ownDataBit(t, 'detail'));
237
+ if (detail !== undefined)
238
+ ts.detail = ownDataCopy(detail, ['kind', 'status', 'code']);
239
+ snap.terminal = ts;
240
+ return snap;
241
+ }
242
+ function nonEmptyStr(v) {
243
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
244
+ }
245
+ function mintToolHistoryCarrier(code, status, message) {
246
+ const out = Object.create(null);
247
+ if (code !== undefined)
248
+ out.code = code;
249
+ if (status !== undefined)
250
+ out.status = status;
251
+ if (message !== undefined)
252
+ out.message = message;
253
+ return Object.freeze(out);
254
+ }
255
+ export function toolHistoryErrorCarrierOf(terminalOrResult) {
256
+ const empty = () => mintToolHistoryCarrier(undefined, undefined, undefined);
257
+ try {
258
+ const x = plainObjectOf(terminalOrResult);
259
+ if (x === undefined)
260
+ return empty();
261
+ const type = ownDataBit(x, 'type');
262
+ const frame = (type === 'done' || type === 'failed' ? x : { type: 'done', result: x });
263
+ return toolHistoryCarrierFromFacts(x, terminalRowFacts(frame));
264
+ }
265
+ catch {
266
+ return empty();
267
+ }
268
+ }
269
+ function terminalRowArmOf(facts) {
270
+ if (facts.errText === null)
271
+ return null;
272
+ return facts.busy.busy ? 'busy' : facts.governance ? 'governance' : isModelOutputErrorText(facts.errText) ? 'modelOutput' : 'apiError';
273
+ }
274
+ function toolHistoryCarrierFromFacts(x, facts) {
275
+ return apiErrorTerminalFromFacts(x, facts).carrier;
276
+ }
277
+ function apiErrorTerminalFromFacts(x, facts) {
278
+ const none = () => ({ carrier: mintToolHistoryCarrier(undefined, undefined, undefined), detail: undefined });
279
+ try {
280
+ const type = ownDataBit(x, 'type');
281
+ if (terminalRowArmOf(facts) !== 'apiError')
282
+ return none();
283
+ if (type === 'failed')
284
+ return { carrier: mintToolHistoryCarrier(nonEmptyStr(ownDataBit(x, 'errorCode')), undefined, nonEmptyStr(ownDataBit(x, 'errorMessage'))), detail: undefined };
285
+ const result = type === 'done' ? plainObjectOf(ownDataBit(x, 'result')) : x;
286
+ if (result === undefined)
287
+ return none();
288
+ const snap = ownTerminalSnapshot(result);
289
+ if (snap === undefined)
290
+ return none();
291
+ const read = readRunTerminal(snap);
292
+ if (read === null || read.kind !== 'failed')
293
+ return none();
294
+ const detail = plainObjectOf(ownDataBit(read, 'detail'));
295
+ const detailStatus = detail !== undefined && ownDataBit(detail, 'kind') === PROVIDER_REJECTED_DETAIL ? ownDataBit(detail, 'status') : undefined;
296
+ const apiFailure = plainObjectOf(ownDataBit(result, 'apiFailure'));
297
+ const apiStatus = apiFailure === undefined ? undefined : ownDataBit(apiFailure, 'status');
298
+ const status = typeof apiStatus === 'number' && Number.isFinite(apiStatus) ? apiStatus : typeof detailStatus === 'number' ? detailStatus : undefined;
299
+ return {
300
+ carrier: mintToolHistoryCarrier(nonEmptyStr(ownDataBit(read, 'code')), status, nonEmptyStr(ownDataBit(read, 'message'))),
301
+ detail: detail,
302
+ };
303
+ }
304
+ catch {
305
+ return none();
306
+ }
307
+ }
308
+ function apiErrorTerminalOfRowFrame(ev, facts) {
309
+ try {
310
+ const x = plainObjectOf(ev);
311
+ return x === undefined ? { carrier: mintToolHistoryCarrier(undefined, undefined, undefined), detail: undefined } : apiErrorTerminalFromFacts(x, facts);
312
+ }
313
+ catch {
314
+ return { carrier: mintToolHistoryCarrier(undefined, undefined, undefined), detail: undefined };
315
+ }
316
+ }
158
317
  const reportedDroppedTypes = new Set();
159
318
  const DROPPED_TYPE_MEMO_CAP = 64;
160
319
  const DROPPED_TYPE_DISPLAY_CAP = 60;
@@ -477,52 +636,32 @@ async function* runStreamInner(events, ctx, handle = {}) {
477
636
  continue;
478
637
  }
479
638
  if (ev.type === 'done' || ev.type === 'failed') {
480
- const doneTerminal = ev.type === 'done' ? readRunTerminal(ev.result) : null;
481
- const errText = ev.type === 'failed'
482
- ? (ev.errorMessage ?? ev.errorCode ?? 'run failed')
483
- : doneTerminal?.kind === 'failed'
484
- ? (doneTerminal.message ?? doneTerminal.code ?? 'run failed')
485
- : doneTerminal?.kind === 'blocked'
486
- ? (doneTerminal.reason
487
- ? `Run blocked: ${doneTerminal.reason}`
488
- : 'Run blocked (the agent reported it cannot proceed)')
489
- : null;
639
+ const rowFacts = terminalRowFacts(ev);
640
+ const doneTerminal = rowFacts.doneTerminal;
641
+ const errText = rowFacts.errText;
490
642
  if (errText) {
491
- const activeTaskId = (ev.type === 'done' ? ev.result?.activeTaskId : undefined) ??
492
- (ev.type === 'failed' ? ev.activeTaskId : undefined);
493
- const busy = classifyActiveRunBusy({
494
- errorCode: ev.type === 'failed' ? ev.errorCode : runTerminalCode(doneTerminal),
495
- activeTaskId,
496
- });
643
+ const busy = rowFacts.busy;
497
644
  const maxTokHint = /max_tokens/i.test(errText)
498
645
  ? '\nyour provider caps max_tokens lower — lower it in /model (press m, or M to type a value)'
499
646
  : '';
500
- const governance = isGovernanceTerminal({
501
- status: ev.type === 'failed' ? undefined : doneTerminal?.kind === 'blocked' ? 'blocked' : undefined,
502
- errorCode: ev.type === 'failed' ? ev.errorCode : runTerminalCode(doneTerminal),
503
- });
504
647
  const busyHandle = busy.handle;
505
- const rowText = busy.busy
648
+ const arm = terminalRowArmOf(rowFacts);
649
+ const rowText = arm === 'busy'
506
650
  ? `This session is locked by an earlier run${busyHandle ? ` (run ${busyHandle})` : ''} that ` +
507
651
  `has not been released, so this message was NOT sent. Nothing releases it on its own — ` +
508
652
  `cancel that run (POST /v1/runs/${busyHandle ?? '<id>'}/cancel), or start a new session.`
509
- : governance
653
+ : arm === 'governance'
510
654
  ?
511
655
  `${isGovernanceStopRowText(errText) ? errText : `${RUN_STOPPED_MESSAGE_PREFIX}: ${errText}`}${maxTokHint}`
512
- : isModelOutputErrorText(errText)
656
+ : arm === 'modelOutput'
513
657
  ?
514
658
  `${MODEL_OUTPUT_ERROR_PREFIX}: ${errText}${maxTokHint}`
515
659
  : `API Error: ${errText}${maxTokHint}`;
516
660
  const sessionUnreadable = ev.type === 'failed'
517
661
  ? isCorruptSessionCode(ev.errorCode)
518
662
  : doneTerminal?.kind === 'failed' && isCorruptSessionCode(doneTerminal.code);
519
- const historyMismatch = !busy.busy && !governance && !isModelOutputErrorText(errText)
520
- ? classifyToolHistoryMismatch({
521
- code: ev.type === 'failed' ? ev.errorCode : runTerminalCode(doneTerminal),
522
- status: ev.type === 'done' ? providerFailureStatusOf(ev.result) : undefined,
523
- message: errText,
524
- })
525
- : null;
663
+ const historyTerminal = apiErrorTerminalOfRowFrame(ev, rowFacts);
664
+ const historyMismatch = classifyToolHistoryMismatch(historyTerminal.carrier);
526
665
  const historyEchoedSid = ev.type === 'done' ? engineSessionIdOf(ev.result) : undefined;
527
666
  const historyRepeat = noteToolHistoryTerminal({
528
667
  sessionId: historyEchoedSid ?? ctx.sessionId,
@@ -532,10 +671,13 @@ async function* runStreamInner(events, ctx, handle = {}) {
532
671
  replay: ev.type === 'done' && ev.replay === true,
533
672
  mismatch: historyMismatch,
534
673
  });
535
- const rewindLine = historyMismatch !== null && ctx.lane !== 'print' && ctx.lane !== 'utility' && toolHistoryRewindOffered(ctx.offersRewind)
674
+ const rewindOffered = historyMismatch !== null && ctx.lane !== 'print' && ctx.lane !== 'utility' && toolHistoryRewindOffered(ctx.offersRewind);
675
+ const rewindLine = rewindOffered
536
676
  ? `\n${TOOL_HISTORY_REWIND_SENTENCE}${historyRepeat !== undefined && historyRepeat >= 2 ? ` ${toolHistoryRepeatSentence(historyRepeat)}` : ''}`
537
677
  : '';
538
- yield syntheticTerminalRow(ctx, `${sessionUnreadable ? `${rowText}\n${corruptSessionContent()}` : rowText}${rewindLine}`, historyMismatch === null ? undefined : toolHistoryMismatchRowKey(historyMismatch, historyRepeat));
678
+ const resend = historyTerminal.detail !== undefined ? providerRejectionResend(historyTerminal.detail, historyTerminal.carrier) : undefined;
679
+ const resendLine = resend !== undefined ? `\n${resend.text}` : '';
680
+ yield syntheticTerminalRow(ctx, `${sessionUnreadable ? `${rowText}\n${corruptSessionContent()}` : rowText}${rewindLine}${resendLine}`, historyMismatch === null ? undefined : toolHistoryMismatchRowKey(historyMismatch, historyRepeat, rewindOffered), resend);
539
681
  }
540
682
  else {
541
683
  const echoedSid = ev.type === 'done' ? engineSessionIdOf(ev.result) : undefined;
@@ -0,0 +1,10 @@
1
+ export declare const MODE_ARBITRATION: Readonly<Record<"hook" | "write_protection" | "mode" | "rule_unreadable" | "content_question" | "ancestor" | "unverifiable_delete" | "transcript_write" | "org_rule" | "governance_unavailable" | "ask_rule" | "denial_limit_fallback" | "operator_forced" | "shell_floor" | "write_protection_unresolved" | "probe" | "tool_marks_mcp" | "tool_marks_a2a" | "policy_rra" | "artifact_shared_read" | "unstated" | "ordinary", import("./generated/engineFactTables.js").CoreModeArbitrationRow>>;
2
+ export type StandingAnswerVerdict = {
3
+ readonly kind: 'must_ask';
4
+ readonly by: string;
5
+ } | {
6
+ readonly kind: 'may_answer';
7
+ } | {
8
+ readonly kind: 'unknown';
9
+ };
10
+ export declare function askSurvivesStandingAnswer(card: object | null | undefined): StandingAnswerVerdict;
@@ -0,0 +1,40 @@
1
+ import { CORE_MODE_ARBITRATION } from './generated/engineFactTables.js';
2
+ export const MODE_ARBITRATION = CORE_MODE_ARBITRATION;
3
+ const MUST_ASK_MANDATED = Object.freeze({ kind: 'must_ask', by: 'mandated' });
4
+ const MAY_ANSWER = Object.freeze({ kind: 'may_answer' });
5
+ const UNKNOWN = Object.freeze({ kind: 'unknown' });
6
+ export function askSurvivesStandingAnswer(card) {
7
+ try {
8
+ if (card === null || card === undefined || typeof card !== 'object')
9
+ return UNKNOWN;
10
+ if (Object.hasOwn(card, 'mandated') && card.mandated === true)
11
+ return MUST_ASK_MANDATED;
12
+ const classes = Object.hasOwn(card, 'classes') ? card.classes : undefined;
13
+ if (!Array.isArray(classes))
14
+ return UNKNOWN;
15
+ const length = classes.length;
16
+ if (typeof length !== 'number' || !Number.isSafeInteger(length) || length <= 0)
17
+ return UNKNOWN;
18
+ const names = [];
19
+ for (let i = 0; i < length; i += 1) {
20
+ if (!Object.hasOwn(classes, i))
21
+ return UNKNOWN;
22
+ const c = classes[i];
23
+ if (typeof c !== 'string')
24
+ return UNKNOWN;
25
+ names.push(c);
26
+ }
27
+ if (classes.length !== length)
28
+ return UNKNOWN;
29
+ for (const name of names) {
30
+ if (!Object.hasOwn(MODE_ARBITRATION, name))
31
+ return UNKNOWN;
32
+ if (MODE_ARBITRATION[name]?.ruleMayClear !== true)
33
+ return Object.freeze({ kind: 'must_ask', by: name });
34
+ }
35
+ return MAY_ANSWER;
36
+ }
37
+ catch {
38
+ return UNKNOWN;
39
+ }
40
+ }
@@ -0,0 +1,11 @@
1
+ export type AttachmentSeatReading = {
2
+ readonly kind: 'unobserved';
3
+ } | {
4
+ readonly kind: 'not_reported';
5
+ };
6
+ export declare function noteEngineCapsForAttachmentSeat(baseUrl: string, caps: unknown, opts?: {
7
+ generation?: number;
8
+ }): void;
9
+ export declare function observedAttachmentSeat(baseUrl?: string | undefined): AttachmentSeatReading;
10
+ export declare function forgetAttachmentSeatReading(baseUrl: string | undefined): void;
11
+ export declare function __resetAttachmentSeatReadingsForTests(): void;
@@ -0,0 +1,27 @@
1
+ import { engineWireTarget } from './engineWireTarget.js';
2
+ import { createEngineCapReader } from './engineCapReader.js';
3
+ function projectAttachmentSeat(caps) {
4
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
5
+ return undefined;
6
+ const p = Object.getPrototypeOf(caps);
7
+ if (p !== Object.prototype && p !== null)
8
+ return undefined;
9
+ return { kind: 'not_reported' };
10
+ }
11
+ const reader = createEngineCapReader({
12
+ name: 'attachmentSeat',
13
+ project: projectAttachmentSeat,
14
+ makeUnobserved: () => ({ kind: 'unobserved' }),
15
+ });
16
+ export function noteEngineCapsForAttachmentSeat(baseUrl, caps, opts) {
17
+ reader.note(baseUrl, caps, opts);
18
+ }
19
+ export function observedAttachmentSeat(baseUrl = engineWireTarget()?.baseUrl) {
20
+ return reader.observed(baseUrl);
21
+ }
22
+ export function forgetAttachmentSeatReading(baseUrl) {
23
+ reader.forget(baseUrl);
24
+ }
25
+ export function __resetAttachmentSeatReadingsForTests() {
26
+ reader.__resetForTests();
27
+ }
@@ -6,7 +6,6 @@ export interface AttachmentsSpec {
6
6
  changedFiles?: true | {
7
7
  maxFiles?: number;
8
8
  };
9
- planModeReminder?: true;
10
9
  budgetUsd?: true;
11
10
  backgroundTasks?: boolean;
12
11
  toolsDelta?: true;
@@ -14,6 +13,27 @@ export interface AttachmentsSpec {
14
13
  agentListing?: boolean;
15
14
  skillsListing?: boolean;
16
15
  }
17
- export declare const ATTACHMENTS_SPEC_KEYS: readonly ["todoReminder", "todoReminderMode", "changedFiles", "planModeReminder", "budgetUsd", "backgroundTasks", "toolsDelta", "mcpInstructions", "agentListing", "skillsListing"];
16
+ export declare const ATTACHMENTS_SPEC_KEYS: readonly ["todoReminder", "todoReminderMode", "changedFiles", "budgetUsd", "backgroundTasks", "toolsDelta", "mcpInstructions", "agentListing", "skillsListing"];
18
17
  export declare const ATTACHMENTS_DEFAULT_ON_KEYS: readonly ["agentListing", "skillsListing", "backgroundTasks"];
18
+ export declare class AttachmentsSpecRefused extends TypeError {
19
+ readonly token: string;
20
+ readonly why: string;
21
+ readonly allowed: readonly string[];
22
+ readonly key?: string;
23
+ constructor(message: string, init: {
24
+ readonly token: string;
25
+ readonly why: string;
26
+ readonly allowed: readonly string[];
27
+ readonly key?: string;
28
+ });
29
+ }
19
30
  export declare function attachmentsForRequest(env?: EnvLike): AttachmentsSpec | undefined;
31
+ export type AttachmentsSubmitVerdict = {
32
+ readonly ok: true;
33
+ readonly attachments: AttachmentsSpec;
34
+ } | {
35
+ readonly ok: false;
36
+ readonly sentence: string;
37
+ readonly refusedKey: string | undefined;
38
+ };
39
+ export declare function attachmentsSubmitVerdict(env?: EnvLike): AttachmentsSubmitVerdict;