@sema-agent/client-core 0.108.0 → 0.109.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 (103) hide show
  1. package/CHANGELOG.md +121 -0
  2. package/README.md +37 -24
  3. package/dist/adapt/arms.js +23 -8
  4. package/dist/adapt/textStream.d.ts +2 -0
  5. package/dist/adapt/textStream.js +37 -16
  6. package/dist/adapter/activeRunSelfHeal.js +1 -1
  7. package/dist/adapter/downstream/eventToSdkMessage.js +2 -1
  8. package/dist/agentSession/engineAgentRegistryRead.js +2 -0
  9. package/dist/bashExitReading.d.ts +12 -0
  10. package/dist/bashExitReading.js +44 -0
  11. package/dist/checkpointRowVerdict.d.ts +1 -1
  12. package/dist/checkpointRowVerdict.js +4 -2
  13. package/dist/compensations.js +1 -1
  14. package/dist/engineAgentAbsence.d.ts +2 -0
  15. package/dist/engineAgentAbsence.js +28 -0
  16. package/dist/engineErrorCodes.d.ts +4 -0
  17. package/dist/engineErrorCodes.js +4 -0
  18. package/dist/engineHealthFacts.d.ts +17 -0
  19. package/dist/engineHealthFacts.js +42 -3
  20. package/dist/engineNoticeCodes.d.ts +128 -0
  21. package/dist/engineNoticeCodes.js +630 -55
  22. package/dist/errorSupplementRoles.js +4 -1
  23. package/dist/fleetTaskDesc.js +3 -3
  24. package/dist/generated/engineFactTables.d.ts +1 -0
  25. package/dist/generated/engineFactTables.js +6 -0
  26. package/dist/generated/engineNoticeTables.js +3 -0
  27. package/dist/hitl/approvalCardReasons.js +22 -4
  28. package/dist/hitl/approvalRequestFrameReading.d.ts +14 -0
  29. package/dist/hitl/approvalRequestFrameReading.js +79 -0
  30. package/dist/hitl/approvalsFeed.js +1 -1
  31. package/dist/hitl/askParkRowRouting.js +5 -2
  32. package/dist/hitl/automaticAnswerVerdict.d.ts +5 -2
  33. package/dist/hitl/automaticAnswerVerdict.js +16 -2
  34. package/dist/hitl/decisionConflict.d.ts +2 -1
  35. package/dist/hitl/decisionConflict.js +4 -1
  36. package/dist/hitl/frameRouter.js +9 -1
  37. package/dist/hitl/hitlBridge.d.ts +4 -0
  38. package/dist/hitl/hitlBridge.js +9 -5
  39. package/dist/hitl/livePendingAsk.js +17 -16
  40. package/dist/hitl/localAllowRule.js +2 -1
  41. package/dist/hitl/noAllowCause.d.ts +1 -1
  42. package/dist/hitl/noAllowCause.js +4 -2
  43. package/dist/hitl/parkExpiryJudgements.js +26 -1
  44. package/dist/hitl/parkOwnership.d.ts +2 -0
  45. package/dist/hitl/parkOwnership.js +48 -8
  46. package/dist/hitl/parkResolver.js +7 -7
  47. package/dist/hitl/parkedUnresumable.d.ts +13 -0
  48. package/dist/hitl/parkedUnresumable.js +80 -0
  49. package/dist/hitl/permissionRuleScope.d.ts +4 -0
  50. package/dist/hitl/permissionRuleScope.js +31 -0
  51. package/dist/hitl/persistedRulesWire.d.ts +2 -0
  52. package/dist/hitl/persistedRulesWire.js +11 -10
  53. package/dist/hitl/sessionAllowRoute.js +5 -4
  54. package/dist/hitl/standingRows.d.ts +1 -5
  55. package/dist/hitl/standingRows.js +15 -14
  56. package/dist/hitl/toolApprovalWire.d.ts +8 -2
  57. package/dist/hitl/toolApprovalWire.js +35 -14
  58. package/dist/hooksWireCaps.js +4 -3
  59. package/dist/hostSettingsSource.js +2 -0
  60. package/dist/i18n/messages.en.d.ts +168 -0
  61. package/dist/i18n/messages.en.js +169 -1
  62. package/dist/i18n/messages.zh.js +169 -1
  63. package/dist/index.d.ts +29 -7
  64. package/dist/index.js +16 -4
  65. package/dist/localEngineJudge.d.ts +75 -0
  66. package/dist/localEngineJudge.js +242 -0
  67. package/dist/localEngineOccupancy.d.ts +88 -0
  68. package/dist/localEngineOccupancy.js +269 -0
  69. package/dist/localEngineSeatReading.d.ts +29 -0
  70. package/dist/localEngineSeatReading.js +294 -0
  71. package/dist/localEngineSpawn.d.ts +113 -0
  72. package/dist/localEngineSpawn.js +486 -0
  73. package/dist/localEngineStep.d.ts +286 -0
  74. package/dist/localEngineStep.js +1086 -0
  75. package/dist/localEngineStopLadder.d.ts +29 -0
  76. package/dist/localEngineStopLadder.js +139 -0
  77. package/dist/localEngineSwapCard.d.ts +43 -0
  78. package/dist/localEngineSwapCard.js +205 -0
  79. package/dist/localEngineTiming.d.ts +8 -0
  80. package/dist/localEngineTiming.js +8 -0
  81. package/dist/mcpReconnect.js +12 -5
  82. package/dist/mcpWireCaps.js +2 -2
  83. package/dist/memoryEntriesWire.d.ts +1 -1
  84. package/dist/memoryEntriesWire.js +5 -0
  85. package/dist/noticePresentation.d.ts +2 -0
  86. package/dist/noticePresentation.js +79 -1
  87. package/dist/ownKey.d.ts +10 -0
  88. package/dist/ownKey.js +15 -1
  89. package/dist/ruleReadings.js +1 -1
  90. package/dist/seam.d.ts +13 -2
  91. package/dist/seam.js +8 -1
  92. package/dist/seatContract.d.ts +42 -4
  93. package/dist/seatContract.js +180 -3
  94. package/dist/sessionBackground.js +2 -0
  95. package/dist/subagentContentStore.d.ts +12 -0
  96. package/dist/subagentContentStore.js +72 -11
  97. package/dist/toolResult.js +18 -5
  98. package/dist/wireFailureShape.d.ts +20 -0
  99. package/dist/wireFailureShape.js +37 -6
  100. package/dist/wireRefusalCopy.d.ts +21 -1
  101. package/dist/wireRefusalCopy.js +91 -2
  102. package/docs/INTEGRATION-CLIENTS.md +1152 -10
  103. package/package.json +3 -3
@@ -1,5 +1,6 @@
1
1
  import { DEFAULT_SESSION_KEY } from './sessionSlot.js';
2
- import { readFrameTrueMark } from './ownKey.js';
2
+ import { readFrameTrueMark, readOwnDataNonEmptyString, readOwnDataValue } from './ownKey.js';
3
+ import { cycleSeqValue } from './cycleOrder.js';
3
4
  import { toolEndOutputText } from './toolResultContent.js';
4
5
  export function coerceOutput(v) {
5
6
  return toolEndOutputText(v);
@@ -398,7 +399,7 @@ function scheduleNotify(taskId) {
398
399
  }, NOTIFY_COALESCE_MS);
399
400
  }
400
401
  export function registerSubagentContentAlias(parentToolCallId, taskId) {
401
- aliasContentKey(parentToolCallId, taskId);
402
+ applySubagentAlias(parentToolCallId, taskId, 'content');
402
403
  }
403
404
  function aliasContentKey(parentToolCallId, taskId) {
404
405
  if (!parentToolCallId || !taskId || parentToolCallId === taskId)
@@ -415,10 +416,72 @@ function aliasContentKey(parentToolCallId, taskId) {
415
416
  return true;
416
417
  }
417
418
  export function registerSubagentAlias(parentToolCallId, taskId) {
419
+ applySubagentAlias(parentToolCallId, taskId, 'full');
420
+ }
421
+ export const SUBAGENT_ALIAS_SCOPES = ['content', 'full'];
422
+ export function applySubagentAlias(parentToolCallId, taskId, scope, seq) {
423
+ const hadContent = parentToTask.get(parentToolCallId) === taskId;
418
424
  if (!aliasContentKey(parentToolCallId, taskId))
419
- return;
420
- if (taskToParent.get(taskId)?.card !== parentToolCallId)
421
- taskToParent.set(taskId, { card: parentToolCallId, stamp: ++parentStampSeq });
425
+ return 'rejected';
426
+ let changed = !hadContent;
427
+ if (scope === 'full') {
428
+ const cycle = cycleSeqValue(seq);
429
+ const cur = taskToParent.get(taskId);
430
+ if (cur?.card !== parentToolCallId) {
431
+ const stale = cur !== undefined && cycle !== undefined && cur.seq !== undefined && cycle < cur.seq;
432
+ if (!stale) {
433
+ taskToParent.set(taskId, { card: parentToolCallId, stamp: ++parentStampSeq, ...(cycle !== undefined ? { seq: cycle } : {}) });
434
+ changed = true;
435
+ }
436
+ }
437
+ else if (cycle !== undefined && (cur.seq === undefined || cycle > cur.seq)) {
438
+ taskToParent.set(taskId, { card: cur.card, stamp: cur.stamp, seq: cycle });
439
+ }
440
+ }
441
+ return changed ? 'new' : 'unchanged';
442
+ }
443
+ export function readSeatSubagentAlias(ev) {
444
+ try {
445
+ if (typeof ev !== 'object' || ev === null)
446
+ return undefined;
447
+ if (readOwnDataValue(ev, 'kind') !== 'subagent_alias')
448
+ return undefined;
449
+ const parentToolCallId = readOwnDataNonEmptyString(ev, 'parentToolCallId');
450
+ const taskId = readOwnDataNonEmptyString(ev, 'taskId');
451
+ const scope = readOwnDataNonEmptyString(ev, 'scope');
452
+ if (parentToolCallId === undefined || taskId === undefined || scope === undefined)
453
+ return undefined;
454
+ if (!SUBAGENT_ALIAS_SCOPES.includes(scope))
455
+ return undefined;
456
+ const proof = readOwnDataValue(ev, 'laneProof');
457
+ if (typeof proof !== 'object' || proof === null)
458
+ return undefined;
459
+ if (readOwnDataValue(proof, 'lane') !== 'subagent')
460
+ return undefined;
461
+ if (readOwnDataNonEmptyString(proof, 'parentToolCallId') !== parentToolCallId)
462
+ return undefined;
463
+ const seqDesc = Object.getOwnPropertyDescriptor(ev, 'seq');
464
+ let seq;
465
+ if (seqDesc !== undefined) {
466
+ if (!Object.hasOwn(seqDesc, 'value'))
467
+ return undefined;
468
+ if (seqDesc.value !== undefined) {
469
+ seq = cycleSeqValue(seqDesc.value);
470
+ if (seq === undefined)
471
+ return undefined;
472
+ }
473
+ }
474
+ return { parentToolCallId, taskId, scope: scope, ...(seq !== undefined ? { seq } : {}) };
475
+ }
476
+ catch {
477
+ return undefined;
478
+ }
479
+ }
480
+ export function noteSeatSubagentAlias(ev) {
481
+ const alias = readSeatSubagentAlias(ev);
482
+ if (alias === undefined)
483
+ return 'ignored';
484
+ return applySubagentAlias(alias.parentToolCallId, alias.taskId, alias.scope, alias.seq) === 'new' ? 'registered' : 'ignored';
422
485
  }
423
486
  function replaySeen(s, ev) {
424
487
  const id = ev.eventId;
@@ -661,18 +724,16 @@ export function planSubagentViewSlots(taskId) {
661
724
  export function parentToolCallIdOf(taskId) {
662
725
  const ids = sameSubagentIds(taskId);
663
726
  let stated;
664
- let statedStamp = -1;
665
727
  for (const id of ids) {
666
728
  const hit = taskToParent.get(id);
667
729
  if (hit === undefined)
668
730
  continue;
669
- if (stated === undefined || hit.stamp > statedStamp) {
670
- stated = hit.card;
671
- statedStamp = hit.stamp;
672
- }
731
+ const newer = hit.seq !== undefined && stated?.seq !== undefined && hit.seq !== stated.seq ? hit.seq > stated.seq : hit.stamp > (stated?.stamp ?? -1);
732
+ if (stated === undefined || newer)
733
+ stated = hit;
673
734
  }
674
735
  if (stated !== undefined)
675
- return stated;
736
+ return stated.card;
676
737
  for (const id of ids) {
677
738
  const fromContent = tasks.get(id)?.parentToolCallId;
678
739
  if (fromContent !== undefined)
@@ -3,7 +3,7 @@ import { markEngineWorkflowNotified, registerOutstandingBgTask, registerOutstand
3
3
  import { parseWorkflowPollEnvelope, projectWorkflowTaskOutput } from './workflow.js';
4
4
  import { asModelFallbackReason } from './engineErrorCodes.js';
5
5
  import { frozenSet } from './frozenSet.js';
6
- import { bashExitOf, bashExitReadingFailed } from './bashExitReading.js';
6
+ import { bashCurtailedResultPart, bashCurtailmentOf, bashCurtailmentSentence, bashExitOf, bashExitReadingFailed } from './bashExitReading.js';
7
7
  import { guardedRead, ownDataField, ownSnapshotWhenTyped, readFrameTrueMark, readFrameTrueMarkReading, readOwnDataFiniteNumber, readOwnDataNonEmptyString, readOwnDataValue, toolResultBlockOf, } from './ownKey.js';
8
8
  import { displayUntrusted } from './displayUntrusted.js';
9
9
  import { isCoreSemaTaskTerminal } from './terminalStatuses.js';
@@ -370,6 +370,7 @@ export function wireOutputToBody(toolName, output, isError, truncated, flatten,
370
370
  let parsedMemo;
371
371
  const parseOnce = () => (parsedMemo === undefined ? (parsedMemo = parseModelFacingBash(text)) : parsedMemo);
372
372
  const exit = bashExitOf(structured, parseOnce);
373
+ const cut = bashCurtailmentOf(structured);
373
374
  const structuredSlots = sType === 'bash' && (typeof s?.stdout === 'string' || typeof s?.stderr === 'string');
374
375
  const textSlots = structuredSlots ? null : parseOnce();
375
376
  const slots = structuredSlots
@@ -392,26 +393,37 @@ export function wireOutputToBody(toolName, output, isError, truncated, flatten,
392
393
  }
393
394
  if (body.trim() === '' && text.trim() !== '')
394
395
  body = text;
396
+ else if (cut !== undefined) {
397
+ if (body.trim() === '')
398
+ body = bashCurtailmentSentence(cut);
399
+ else if (reason.trim() !== '')
400
+ body = `${bashCurtailmentSentence(cut)}\n${body}`;
401
+ }
395
402
  return { content: truncated ? `${body}\n…(truncated)` : body, isError: true };
396
403
  }
397
404
  const stdout = truncated ? `${slots.stdout}\n…(truncated)` : slots.stdout;
398
405
  const processedStdout = stdout.replace(/^(\s*\n)+/, '').trimEnd();
399
406
  return {
400
- content: [processedStdout, slots.stderr.trim()].filter(Boolean).join('\n'),
407
+ content: [cut !== undefined ? bashCurtailmentSentence(cut) : '', processedStdout, slots.stderr.trim()].filter(Boolean).join('\n'),
401
408
  isError: false,
402
409
  toolUseResult: {
403
410
  stdout,
404
- stderr: slots.stderr,
411
+ ...bashCurtailedResultPart(slots.stderr, cut),
405
412
  interrupted: false,
406
413
  ...(benignInterp !== undefined ? { returnCodeInterpretation: benignInterp } : {}),
407
414
  },
408
415
  };
409
416
  }
410
417
  const stdout = truncated ? `${text}\n…(truncated)` : text;
418
+ const cutSentence = cut !== undefined ? bashCurtailmentSentence(cut) : undefined;
411
419
  if (isError || bashExitReadingFailed(exit)) {
420
+ if (cutSentence !== undefined && text.trim() === '' && exit.exitCode !== 137) {
421
+ return { content: truncated ? `${cutSentence}\n…(truncated)` : cutSentence, isError: true };
422
+ }
412
423
  return { content: exit.exitCode === 137 ? `${stdout}\n${killedBySignalSentence(killCauseOf)}` : stdout, isError: true };
413
424
  }
414
- return { content: stdout, isError, toolUseResult: { stdout, stderr: '', interrupted: false } };
425
+ const okContent = cutSentence === undefined ? stdout : text.trim() === '' ? (truncated ? `${cutSentence}\n…(truncated)` : cutSentence) : `${cutSentence}\n${stdout}`;
426
+ return { content: okContent, isError, toolUseResult: { stdout, ...bashCurtailedResultPart('', cut), interrupted: false } };
415
427
  }
416
428
  if (name === 'taskoutput' || name === 'task_output') {
417
429
  const body = truncated ? `${text}\n…(truncated)` : text;
@@ -498,10 +510,11 @@ export function structuredToToolUseResult(structured, modelText, leaderLedger =
498
510
  return null;
499
511
  const exit = bashExitOf(structured, () => null);
500
512
  const benignInterp = exit.benignNote;
513
+ const cut = bashCurtailmentOf(structured);
501
514
  return {
502
515
  toolUseResult: {
503
516
  stdout: typeof s.stdout === 'string' ? s.stdout : '',
504
- stderr: typeof s.stderr === 'string' ? s.stderr : '',
517
+ ...bashCurtailedResultPart(typeof s.stderr === 'string' ? s.stderr : '', cut),
505
518
  interrupted: false,
506
519
  ...(benignInterp !== undefined ? { returnCodeInterpretation: benignInterp } : {}),
507
520
  },
@@ -69,6 +69,26 @@ export interface OwnSlotRead {
69
69
  }
70
70
  export declare function slotPresenceOf(o: object, key: string): SlotPresence;
71
71
  export declare function slotReadOf(o: object, key: string): OwnSlotRead;
72
+ export type InSlotRead = {
73
+ readonly state: 'absent';
74
+ } | {
75
+ readonly state: 'present';
76
+ readonly value: {} | null | undefined;
77
+ } | {
78
+ readonly state: 'present_unreadable';
79
+ } | {
80
+ readonly state: 'unproven';
81
+ };
82
+ export declare function inSlotReadOf(o: object, key: string): InSlotRead;
83
+ export type InValueRead = {
84
+ readonly state: 'absent';
85
+ } | {
86
+ readonly state: 'present';
87
+ readonly value: {} | null | undefined;
88
+ } | {
89
+ readonly state: 'unproven';
90
+ };
91
+ export declare function inValueOf(o: object, key: string): InValueRead;
72
92
  export declare function readErrorNumber(o: object, key: string): number | undefined;
73
93
  export declare function readErrorRecord(o: object, key: string): object | undefined;
74
94
  export declare function readErrorPresent(o: object, key: string): {} | null | undefined;
@@ -181,31 +181,62 @@ export function readThrownStatusSlot(o, notePresence) {
181
181
  return undefined;
182
182
  return typeof raw === 'number' ? raw : THROWN_SLOT_UNREADABLE;
183
183
  }
184
- function readOwnSlot(o, key, withPresence) {
184
+ function observeOwnSlot(o, key, withPresence) {
185
185
  let d;
186
186
  try {
187
187
  d = Object.getOwnPropertyDescriptor(o, key);
188
188
  }
189
189
  catch {
190
- return { value: THROWN_SLOT_UNREADABLE, presence: 'unreadable' };
190
+ return { kind: 'thrown' };
191
191
  }
192
192
  if (d !== undefined)
193
- return Object.hasOwn(d, 'value') ? { value: d.value, presence: 'present' } : { value: THROWN_SLOT_UNREADABLE, presence: 'unreadable' };
193
+ return Object.hasOwn(d, 'value') ? { kind: 'data', value: d.value } : { kind: 'accessor' };
194
194
  if (!withPresence)
195
- return { value: undefined, presence: 'unreadable' };
195
+ return { kind: 'not-own', inChain: 'unasked' };
196
196
  try {
197
- return { value: undefined, presence: key in o ? 'unreadable' : 'absent' };
197
+ return { kind: 'not-own', inChain: key in o ? 'inherited' : 'none' };
198
198
  }
199
199
  catch {
200
- return { value: undefined, presence: 'unreadable' };
200
+ return { kind: 'not-own', inChain: 'in-thrown' };
201
201
  }
202
202
  }
203
+ function readOwnSlot(o, key, withPresence) {
204
+ const ob = observeOwnSlot(o, key, withPresence);
205
+ if (ob.kind === 'data')
206
+ return { value: ob.value, presence: 'present' };
207
+ if (ob.kind === 'thrown' || ob.kind === 'accessor')
208
+ return { value: THROWN_SLOT_UNREADABLE, presence: 'unreadable' };
209
+ return { value: undefined, presence: ob.inChain === 'none' ? 'absent' : 'unreadable' };
210
+ }
203
211
  export function slotPresenceOf(o, key) {
204
212
  return slotReadOf(o, key).presence;
205
213
  }
206
214
  export function slotReadOf(o, key) {
207
215
  return readOwnSlot(o, key, true);
208
216
  }
217
+ export function inSlotReadOf(o, key) {
218
+ const claimed = key in o;
219
+ const ob = observeOwnSlot(o, key, true);
220
+ if (ob.kind === 'thrown')
221
+ return { state: 'unproven' };
222
+ if (ob.kind === 'data' || ob.kind === 'accessor') {
223
+ if (!claimed)
224
+ return { state: 'unproven' };
225
+ return ob.kind === 'data' ? { state: 'present', value: ob.value } : { state: 'present_unreadable' };
226
+ }
227
+ if (ob.inChain === 'in-thrown' || ob.inChain === 'unasked')
228
+ return { state: 'unproven' };
229
+ const again = ob.inChain === 'inherited';
230
+ if (!claimed)
231
+ return again ? { state: 'unproven' } : { state: 'absent' };
232
+ return again ? { state: 'present_unreadable' } : { state: 'unproven' };
233
+ }
234
+ export function inValueOf(o, key) {
235
+ const s = inSlotReadOf(o, key);
236
+ if (s.state === 'present_unreadable')
237
+ return { state: 'present', value: o[key] };
238
+ return s;
239
+ }
209
240
  function readErrorSlot(obj, key, accept) {
210
241
  try {
211
242
  const topRaw = readThrownSlot(obj, key, 'data');
@@ -1,4 +1,4 @@
1
- import { CONFLICT_SESSION_ARCHIVE_STAMPED, FLEET_LEASE_UNAVAILABLE, REQUEST_AUTONOMY_LANE_REFUSED, USAGE_WINDOW_EXHAUSTED, USER_ATTACHMENT_INVALID_ERROR_CODE, USER_INVOKED_SKILL_UNKNOWN_ERROR_CODE } from './engineErrorCodes.js';
1
+ import { CONFLICT_SESSION_ARCHIVE_STAMPED, CONFLICT_SESSION_ID_RETIRED, FLEET_LEASE_UNAVAILABLE, LIMIT_RATE_EXCEEDED, RATE_EXCEEDED_RUN_CONCURRENCY_CAP, REQUEST_ENV_CREDENTIAL_REFUSED, REQUEST_AUTONOMY_LANE_REFUSED, USAGE_WINDOW_EXHAUSTED, USER_ATTACHMENT_INVALID_ERROR_CODE, USER_INVOKED_SKILL_UNKNOWN_ERROR_CODE } from './engineErrorCodes.js';
2
2
  import type { TaskRequestLike } from './request/taskRequest.js';
3
3
  import type { UiLanguage } from './env/uiLanguage.js';
4
4
  export declare const CONFLICT_APPROVAL_SETTLED = "conflict.approval_settled";
@@ -145,6 +145,26 @@ export interface SessionArchiveStampedDetail {
145
145
  export declare function sessionArchiveStampedFromError(err: {} | null | undefined): SessionArchiveStampedDetail | null;
146
146
  export type SessionArchiveStampedScenario = 'fork' | 'push';
147
147
  export declare function sessionArchiveStampedContent(lang?: UiLanguage, scenario?: SessionArchiveStampedScenario): string;
148
+ export interface EnvCredentialRefusalDetail {
149
+ readonly code: typeof REQUEST_ENV_CREDENTIAL_REFUSED;
150
+ readonly names?: readonly string[];
151
+ readonly folded?: true;
152
+ }
153
+ export declare function envCredentialRefusalFromError(err: {} | null | undefined): EnvCredentialRefusalDetail | null;
154
+ export declare function envCredentialRefusalContent(detail: Pick<EnvCredentialRefusalDetail, 'names' | 'folded'>, lang?: UiLanguage): string;
155
+ export interface SessionIdRetiredDetail {
156
+ readonly code: typeof CONFLICT_SESSION_ID_RETIRED;
157
+ readonly folded?: true;
158
+ }
159
+ export declare function sessionIdRetiredFromError(err: {} | null | undefined): SessionIdRetiredDetail | null;
160
+ export declare function sessionIdRetiredContent(detail: Pick<SessionIdRetiredDetail, 'folded'>, lang?: UiLanguage): string;
161
+ export interface RunConcurrencyCapDetail {
162
+ readonly code: typeof LIMIT_RATE_EXCEEDED;
163
+ readonly reason: typeof RATE_EXCEEDED_RUN_CONCURRENCY_CAP;
164
+ readonly retryAfterSec?: number;
165
+ }
166
+ export declare function runConcurrencyCapFromError(err: {} | null | undefined): RunConcurrencyCapDetail | null;
167
+ export declare function runConcurrencyCapContent(detail: Pick<RunConcurrencyCapDetail, 'retryAfterSec'>, lang?: UiLanguage): string;
148
168
  export interface UnsupportedRuleRefusalProblem {
149
169
  readonly code: string;
150
170
  readonly field?: string;
@@ -1,7 +1,8 @@
1
- import { PROTOCOL_ERROR_NAME, REFUSAL_PROBLEMS_READ_MAX, THROWN_SLOT_UNREADABLE, effectiveWireCodeReading, isSlotCarrier, protocolErrorNameOf, readErrorNumber, readErrorRecord, readErrorStrictStringList, readErrorString, readErrorStringList, readRefusalField, readThrownSlot, readThrownStatusSlot } from './wireFailureShape.js';
1
+ import { PROTOCOL_ERROR_NAME, REFUSAL_PROBLEMS_READ_MAX, THROWN_SLOT_UNREADABLE, effectiveWireCodeReading, isSlotCarrier, protocolErrorNameOf, readErrorNumber, readErrorPresent, readErrorRecord, readErrorStrictStringList, readErrorString, readErrorStringList, readRefusalField, readRefusalSlots, readThrownSlot, readThrownStatusSlot } from './wireFailureShape.js';
2
2
  import { appendOwnElement, guardedRead, readOwnDataValue, readOwnNonEmptyString } from './ownKey.js';
3
- import { ACTIVE_RUN_BUSY_ERROR_CODE, CONFLICT_SESSION_ARCHIVE_STAMPED, FLEET_LEASE_UNAVAILABLE, REQUEST_AUTONOMY_LANE_REFUSED, REQUEST_FIELD_CONFLICT, RESUME_OUTCOME_INVALID, USAGE_WINDOW_EXHAUSTED, USER_ATTACHMENT_INVALID_ERROR_CODE, USER_INVOKED_SKILL_UNKNOWN_ERROR_CODE } from './engineErrorCodes.js';
3
+ import { ACTIVE_RUN_BUSY_ERROR_CODE, CONFLICT_SESSION_ARCHIVE_STAMPED, CONFLICT_SESSION_ID_RETIRED, FLEET_LEASE_UNAVAILABLE, LIMIT_RATE_EXCEEDED, RATE_EXCEEDED_RUN_CONCURRENCY_CAP, REQUEST_ENV_CREDENTIAL_REFUSED, REQUEST_AUTONOMY_LANE_REFUSED, REQUEST_FIELD_CONFLICT, RESUME_OUTCOME_INVALID, USAGE_WINDOW_EXHAUSTED, USER_ATTACHMENT_INVALID_ERROR_CODE, USER_INVOKED_SKILL_UNKNOWN_ERROR_CODE } from './engineErrorCodes.js';
4
4
  import { capForDisplay } from './fleetTaskDesc.js';
5
+ import { quoteUntrustedForSentence } from './displayUntrusted.js';
5
6
  import { effectiveWireErrorCode } from './wireErrorTriage.js';
6
7
  import { CORE_TOOL_DECLARATION_CODES } from './generated/engineFactTables.js';
7
8
  import { SETTINGS_ECHO_CALLER_TEXT } from './generated/settingsSchemaFns.js';
@@ -815,6 +816,94 @@ export function sessionArchiveStampedFromError(err) {
815
816
  export function sessionArchiveStampedContent(lang, scenario) {
816
817
  return renderMessage(msg(scenario === 'fork' ? 'notice.wireRefusal.sessionArchiveStamped.fork' : 'notice.wireRefusal.sessionArchiveStamped'), lang);
817
818
  }
819
+ const ENV_CREDENTIAL_NAME_SHOWN_MAX = 80;
820
+ const ENV_CREDENTIAL_NAMES_SHOWN = 8;
821
+ export function envCredentialRefusalFromError(err) {
822
+ try {
823
+ if (typeof err !== 'object' || err === null)
824
+ return null;
825
+ const effective = effectiveWireCodeReading(err);
826
+ if (effective.code !== REQUEST_ENV_CREDENTIAL_REFUSED)
827
+ return null;
828
+ const names = guardedRead(() => envCredentialNamesOf(readErrorPresent(err, 'entries')));
829
+ return Object.freeze({
830
+ code: REQUEST_ENV_CREDENTIAL_REFUSED,
831
+ ...(names !== undefined ? { names } : {}),
832
+ ...(effective.folded ? { folded: true } : {}),
833
+ });
834
+ }
835
+ catch {
836
+ return null;
837
+ }
838
+ }
839
+ function envCredentialNamesOf(list) {
840
+ if (!Array.isArray(list))
841
+ return undefined;
842
+ const out = [];
843
+ const len = Math.min(list.length, REFUSAL_PROBLEMS_READ_MAX);
844
+ for (let i = 0; i < len; i++) {
845
+ const key = guardedRead(() => {
846
+ const item = readOwnDataValue(list, String(i));
847
+ if (typeof item !== 'object' || item === null)
848
+ return undefined;
849
+ const k = readOwnDataValue(item, 'key');
850
+ return typeof k === 'string' && k !== '' ? k : undefined;
851
+ });
852
+ if (key !== undefined && !out.includes(key))
853
+ appendOwnElement(out, key);
854
+ }
855
+ return out.length === 0 ? undefined : Object.freeze(out);
856
+ }
857
+ export function envCredentialRefusalContent(detail, lang) {
858
+ const head = renderMessage(msg(detail.folded === true ? 'notice.wireRefusal.envCredential.folded' : 'notice.wireRefusal.envCredential'), lang);
859
+ const quoted = (detail.names ?? []).slice(0, ENV_CREDENTIAL_NAMES_SHOWN).map((n) => quoteUntrustedForSentence(n, ENV_CREDENTIAL_NAME_SHOWN_MAX)).filter((q) => q !== undefined);
860
+ const more = (detail.names?.length ?? 0) > ENV_CREDENTIAL_NAMES_SHOWN ? ', …' : '';
861
+ const named = quoted.length > 0 ? ` · ${renderMessage(msg('notice.wireRefusal.envCredential.names', { names: quoted.join(', ') + more }), lang)}` : '';
862
+ return `${head}${named} · ${renderMessage(msg('notice.wireRefusal.envCredential.remedy'), lang)}`;
863
+ }
864
+ export function sessionIdRetiredFromError(err) {
865
+ try {
866
+ if (typeof err !== 'object' || err === null)
867
+ return null;
868
+ const effective = effectiveWireCodeReading(err);
869
+ if (effective.code !== CONFLICT_SESSION_ID_RETIRED)
870
+ return null;
871
+ return Object.freeze({ code: CONFLICT_SESSION_ID_RETIRED, ...(effective.folded ? { folded: true } : {}) });
872
+ }
873
+ catch {
874
+ return null;
875
+ }
876
+ }
877
+ export function sessionIdRetiredContent(detail, lang) {
878
+ return renderMessage(msg(detail.folded === true ? 'notice.wireRefusal.sessionIdRetired.folded' : 'notice.wireRefusal.sessionIdRetired'), lang);
879
+ }
880
+ export function runConcurrencyCapFromError(err) {
881
+ try {
882
+ if (typeof err !== 'object' || err === null)
883
+ return null;
884
+ if (effectiveWireCodeReading(err).code !== LIMIT_RATE_EXCEEDED)
885
+ return null;
886
+ if (readRefusalSlots(err, ['reason']).reason.word !== RATE_EXCEEDED_RUN_CONCURRENCY_CAP)
887
+ return null;
888
+ const rawSec = readErrorNumber(err, 'retryAfterSec');
889
+ const sec = nonNegativeFinite(rawSec)
890
+ ? Math.ceil(rawSec)
891
+ : (() => {
892
+ const rawMs = readThrownSlot(err, 'retryAfterMs', 'data');
893
+ return nonNegativeFinite(rawMs) ? Math.ceil(rawMs / 1000) : undefined;
894
+ })();
895
+ return Object.freeze({ code: LIMIT_RATE_EXCEEDED, reason: RATE_EXCEEDED_RUN_CONCURRENCY_CAP, ...(sec !== undefined ? { retryAfterSec: sec } : {}) });
896
+ }
897
+ catch {
898
+ return null;
899
+ }
900
+ }
901
+ export function runConcurrencyCapContent(detail, lang) {
902
+ const head = renderMessage(msg('notice.wireRefusal.runConcurrencyCap.head'), lang);
903
+ return detail.retryAfterSec !== undefined
904
+ ? `${head} · ${renderMessage(msg('notice.wireRefusal.sendAgainAbout', { wait: humanWait(detail.retryAfterSec) }), lang)}`
905
+ : `${head} · ${renderMessage(msg('notice.wireRefusal.runConcurrencyCap.unknownWait'), lang)}`;
906
+ }
818
907
  const REQUEST_UNPROCESSABLE = 'request.unprocessable';
819
908
  const UNSUPPORTED_RULE_PROBLEMS_MAX = REFUSAL_PROBLEMS_READ_MAX;
820
909
  const nonEmptyString = (v) => (typeof v === 'string' && v !== '' ? v : undefined);