@sema-agent/client-core 0.107.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 (165) hide show
  1. package/CHANGELOG.md +239 -0
  2. package/README.md +54 -36
  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.d.ts +2 -0
  7. package/dist/adapter/activeRunSelfHeal.js +21 -4
  8. package/dist/adapter/downstream/eventToSdkMessage.js +2 -1
  9. package/dist/agentSession/engineAgentRegistryRead.js +2 -0
  10. package/dist/bashExitReading.d.ts +12 -0
  11. package/dist/bashExitReading.js +44 -0
  12. package/dist/checkpointRowVerdict.d.ts +6 -1
  13. package/dist/checkpointRowVerdict.js +30 -2
  14. package/dist/cloudConfigWireCaps.d.ts +10 -0
  15. package/dist/cloudConfigWireCaps.js +33 -0
  16. package/dist/compensations.js +1 -1
  17. package/dist/coreValuePorts.d.ts +17 -1
  18. package/dist/coreValuePorts.js +5 -0
  19. package/dist/decideReceipt.js +2 -1
  20. package/dist/engineAgentAbsence.d.ts +2 -0
  21. package/dist/engineAgentAbsence.js +28 -0
  22. package/dist/engineErrorCodes.d.ts +9 -0
  23. package/dist/engineErrorCodes.js +9 -0
  24. package/dist/engineHealthFacts.d.ts +17 -0
  25. package/dist/engineHealthFacts.js +42 -3
  26. package/dist/engineNoticeCodes.d.ts +147 -1
  27. package/dist/engineNoticeCodes.js +694 -57
  28. package/dist/engineTargetSeat.js +1 -0
  29. package/dist/errorSupplementRoles.js +6 -1
  30. package/dist/eventLeg.js +1 -1
  31. package/dist/executionLaneWords.js +2 -1
  32. package/dist/fleetTaskDesc.js +3 -3
  33. package/dist/gateOutcome.d.ts +10 -1
  34. package/dist/gateOutcome.js +48 -1
  35. package/dist/generated/engineFactTables.d.ts +2 -0
  36. package/dist/generated/engineFactTables.js +11 -0
  37. package/dist/generated/engineNoticeTables.js +6 -0
  38. package/dist/generated/settingsSchemaFns.d.ts +4 -2
  39. package/dist/generated/settingsSchemaFns.js +9 -3
  40. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
  41. package/dist/generated/settingsSchemaMcpRequestEntry.js +9 -18
  42. package/dist/generated/settingsSchemaReservedMemberName.d.ts +1 -0
  43. package/dist/generated/settingsSchemaReservedMemberName.js +7 -0
  44. package/dist/generated/settingsSchemaTables.d.ts +2 -0
  45. package/dist/generated/settingsSchemaTables.js +10 -0
  46. package/dist/generated/settingsSchemaWireName.d.ts +1 -0
  47. package/dist/generated/settingsSchemaWireName.js +8 -0
  48. package/dist/headlessReconnectWire.js +12 -7
  49. package/dist/hitl/approvalAskers.d.ts +13 -0
  50. package/dist/hitl/approvalAskers.js +79 -0
  51. package/dist/hitl/approvalCardReasons.js +22 -4
  52. package/dist/hitl/approvalRequestFrameReading.d.ts +14 -0
  53. package/dist/hitl/approvalRequestFrameReading.js +79 -0
  54. package/dist/hitl/approvalResolution.d.ts +3 -0
  55. package/dist/hitl/approvalResolution.js +22 -4
  56. package/dist/hitl/approvalsFeed.js +4 -13
  57. package/dist/hitl/askParkRowRouting.js +10 -3
  58. package/dist/hitl/automaticAnswerVerdict.d.ts +5 -2
  59. package/dist/hitl/automaticAnswerVerdict.js +16 -2
  60. package/dist/hitl/decisionConflict.d.ts +2 -1
  61. package/dist/hitl/decisionConflict.js +4 -1
  62. package/dist/hitl/decisionRefusal.d.ts +1 -0
  63. package/dist/hitl/decisionRefusal.js +5 -2
  64. package/dist/hitl/decisionSend.js +2 -6
  65. package/dist/hitl/frameRouter.d.ts +3 -2
  66. package/dist/hitl/frameRouter.js +37 -7
  67. package/dist/hitl/gateLedger.d.ts +2 -0
  68. package/dist/hitl/gateLedger.js +3 -1
  69. package/dist/hitl/hitlBridge.d.ts +4 -0
  70. package/dist/hitl/hitlBridge.js +11 -8
  71. package/dist/hitl/livePendingAsk.js +17 -16
  72. package/dist/hitl/localAllowRule.js +2 -1
  73. package/dist/hitl/noAllowCause.d.ts +1 -1
  74. package/dist/hitl/noAllowCause.js +4 -2
  75. package/dist/hitl/parkExpiryJudgements.js +26 -1
  76. package/dist/hitl/parkOwnership.d.ts +2 -0
  77. package/dist/hitl/parkOwnership.js +48 -8
  78. package/dist/hitl/parkResolver.js +39 -30
  79. package/dist/hitl/parkRowBirthWait.d.ts +2 -0
  80. package/dist/hitl/parkRowBirthWait.js +8 -1
  81. package/dist/hitl/parkedUnresumable.d.ts +13 -0
  82. package/dist/hitl/parkedUnresumable.js +80 -0
  83. package/dist/hitl/permissionRuleScope.d.ts +4 -0
  84. package/dist/hitl/permissionRuleScope.js +31 -0
  85. package/dist/hitl/persistedRulesWire.d.ts +7 -1
  86. package/dist/hitl/persistedRulesWire.js +25 -8
  87. package/dist/hitl/planReviewWire.js +12 -16
  88. package/dist/hitl/policyDenyCause.d.ts +3 -0
  89. package/dist/hitl/policyDenyCause.js +16 -0
  90. package/dist/hitl/sessionAllowRoute.js +5 -4
  91. package/dist/hitl/sessionPolicyDeliverable.js +1 -1
  92. package/dist/hitl/standingRows.d.ts +1 -5
  93. package/dist/hitl/standingRows.js +15 -14
  94. package/dist/hitl/toolApprovalWire.d.ts +16 -4
  95. package/dist/hitl/toolApprovalWire.js +57 -17
  96. package/dist/hooksReaderGenerations.d.ts +1 -0
  97. package/dist/hooksReaderGenerations.js +12 -0
  98. package/dist/hooksWireCaps.js +12 -7
  99. package/dist/hostSettingsSource.js +2 -0
  100. package/dist/i18n/messages.en.d.ts +206 -1
  101. package/dist/i18n/messages.en.js +209 -4
  102. package/dist/i18n/messages.zh.js +214 -4
  103. package/dist/index.d.ts +35 -8
  104. package/dist/index.js +20 -5
  105. package/dist/liveModelCatalog.d.ts +4 -2
  106. package/dist/liveModelCatalog.js +164 -26
  107. package/dist/localEngineJudge.d.ts +75 -0
  108. package/dist/localEngineJudge.js +242 -0
  109. package/dist/localEngineOccupancy.d.ts +88 -0
  110. package/dist/localEngineOccupancy.js +269 -0
  111. package/dist/localEngineSeatReading.d.ts +29 -0
  112. package/dist/localEngineSeatReading.js +294 -0
  113. package/dist/localEngineSpawn.d.ts +113 -0
  114. package/dist/localEngineSpawn.js +486 -0
  115. package/dist/localEngineStep.d.ts +286 -0
  116. package/dist/localEngineStep.js +1086 -0
  117. package/dist/localEngineStopLadder.d.ts +29 -0
  118. package/dist/localEngineStopLadder.js +139 -0
  119. package/dist/localEngineSwapCard.d.ts +43 -0
  120. package/dist/localEngineSwapCard.js +205 -0
  121. package/dist/localEngineTiming.d.ts +8 -0
  122. package/dist/localEngineTiming.js +8 -0
  123. package/dist/mcpReconnect.js +12 -5
  124. package/dist/mcpWireCaps.js +2 -2
  125. package/dist/memoryEntriesWire.d.ts +1 -1
  126. package/dist/memoryEntriesWire.js +5 -0
  127. package/dist/model/catalogDefault.d.ts +25 -0
  128. package/dist/model/catalogDefault.js +44 -0
  129. package/dist/noticePresentation.d.ts +2 -0
  130. package/dist/noticePresentation.js +79 -1
  131. package/dist/ownKey.d.ts +10 -0
  132. package/dist/ownKey.js +15 -1
  133. package/dist/permissionWireCaps.d.ts +1 -0
  134. package/dist/permissionWireCaps.js +11 -0
  135. package/dist/pluginHooksWire.d.ts +5 -3
  136. package/dist/pluginHooksWire.js +116 -7
  137. package/dist/queuedDelivery.d.ts +1 -0
  138. package/dist/queuedDelivery.js +12 -0
  139. package/dist/resultFrameKeys.js +4 -2
  140. package/dist/resumeRefusalCopy.js +15 -8
  141. package/dist/ruleReadings.js +1 -1
  142. package/dist/runPermissionModeSwitch.d.ts +2 -1
  143. package/dist/runPermissionModeSwitch.js +16 -6
  144. package/dist/seam.d.ts +13 -2
  145. package/dist/seam.js +8 -1
  146. package/dist/seatContract.d.ts +103 -12
  147. package/dist/seatContract.js +344 -14
  148. package/dist/sessionBackground.js +2 -0
  149. package/dist/sessionEngine.d.ts +2 -1
  150. package/dist/sessionEngine.js +5 -0
  151. package/dist/settingsHooksSalvage.d.ts +5 -0
  152. package/dist/settingsHooksSalvage.js +54 -0
  153. package/dist/subagentContentStore.d.ts +12 -0
  154. package/dist/subagentContentStore.js +73 -12
  155. package/dist/supportFloor.js +2 -0
  156. package/dist/taskNotificationAdmission.d.ts +19 -0
  157. package/dist/taskNotificationAdmission.js +84 -0
  158. package/dist/toolResult.js +20 -6
  159. package/dist/webSearchWireCaps.js +9 -4
  160. package/dist/wireFailureShape.d.ts +20 -0
  161. package/dist/wireFailureShape.js +37 -6
  162. package/dist/wireRefusalCopy.d.ts +23 -2
  163. package/dist/wireRefusalCopy.js +93 -4
  164. package/docs/INTEGRATION-CLIENTS.md +1959 -15
  165. package/package.json +4 -4
@@ -1,5 +1,6 @@
1
1
  import { displayUntrusted } from './displayUntrusted.js';
2
2
  import { msg, renderMessage } from './i18n/translate.js';
3
+ import { appendOwnElement } from './ownKey.js';
3
4
  import { SETTINGS_CLASSIFY_HOOKS_CONFIG, } from './generated/settingsSchemaFns.js';
4
5
  const _tuplePins = [true, true, true, true, true, true];
5
6
  void _tuplePins;
@@ -110,6 +111,59 @@ export function salvageSettingsHooksEntries(doc) {
110
111
  rejections: Object.freeze([]),
111
112
  });
112
113
  }
114
+ const READER_GROUP_WIRE_KEYS = ['source'];
115
+ const READER_COMMAND_WIRE_KEYS = ['plugin', 'args'];
116
+ function unreadOf(raw, carried, wireKeys, notRead) {
117
+ const out = [];
118
+ for (const k of Object.keys(raw)) {
119
+ if (own(raw, k) === undefined || wireKeys.includes(k))
120
+ continue;
121
+ if (Object.hasOwn(carried, k) && !notRead.includes(k))
122
+ continue;
123
+ appendOwnElement(out, k);
124
+ }
125
+ return Object.freeze(out);
126
+ }
127
+ function carriedGroupOf(event, group) {
128
+ const r = SETTINGS_CLASSIFY_HOOKS_CONFIG({ hooks: { [event]: [group] } });
129
+ if (r.outcome !== 'loaded' || !isRecord(r.hooks))
130
+ return undefined;
131
+ const groups = own(r.hooks, event);
132
+ const g = Array.isArray(groups) ? groups[0] : undefined;
133
+ return isRecord(g) ? g : undefined;
134
+ }
135
+ export function hooksGroupUnreadKeys(event, group) {
136
+ const raw = group;
137
+ const carried = carriedGroupOf(event, { ...raw, hooks: [] });
138
+ return carried === undefined ? undefined : unreadOf(raw, carried, READER_GROUP_WIRE_KEYS, []);
139
+ }
140
+ export function hooksGroupAuthoredSource(group) {
141
+ try {
142
+ const d = Object.getOwnPropertyDescriptor(group, READER_GROUP_WIRE_KEYS[0]);
143
+ if (d === undefined)
144
+ return 'absent';
145
+ if (!Object.hasOwn(d, 'value'))
146
+ return 'unreadable';
147
+ if (d.value !== undefined)
148
+ return 'present';
149
+ return Reflect.get(group, READER_GROUP_WIRE_KEYS[0]) === undefined ? 'absent' : 'unreadable';
150
+ }
151
+ catch {
152
+ return 'unreadable';
153
+ }
154
+ }
155
+ export function hooksEntryUnreadKeys(event, entry, notRead) {
156
+ const raw = entry;
157
+ const g = carriedGroupOf(event, { hooks: [raw] });
158
+ const entries = g === undefined ? undefined : own(g, 'hooks');
159
+ const carried = Array.isArray(entries) ? entries[0] : undefined;
160
+ if (!isRecord(carried))
161
+ return undefined;
162
+ return unreadOf(raw, carried, own(carried, 'type') === 'command' ? READER_COMMAND_WIRE_KEYS : [], notRead);
163
+ }
164
+ export function hooksKeyCoordinateText(path) {
165
+ return `settings.${path.map(labelOf).join('.')}`;
166
+ }
113
167
  export const HOOK_SETTINGS_SOURCE_TEXT = Object.freeze({
114
168
  policySettings: 'Managed settings',
115
169
  userSettings: 'User settings',
@@ -49,6 +49,18 @@ export declare function __resetSubagentContentStoreConfigForTests(): void;
49
49
  export declare function bindSubagentIdentityReader(fn: (id: string) => readonly string[] | undefined): void;
50
50
  export declare function registerSubagentContentAlias(parentToolCallId: string, taskId: string): void;
51
51
  export declare function registerSubagentAlias(parentToolCallId: string, taskId: string): void;
52
+ export declare const SUBAGENT_ALIAS_SCOPES: readonly ["content", "full"];
53
+ export type SubagentAliasScope = (typeof SUBAGENT_ALIAS_SCOPES)[number];
54
+ export type SubagentAliasOutcome = 'new' | 'unchanged' | 'rejected';
55
+ export declare function applySubagentAlias(parentToolCallId: string, taskId: string, scope: SubagentAliasScope, seq?: number): SubagentAliasOutcome;
56
+ export interface SeatSubagentAlias {
57
+ readonly parentToolCallId: string;
58
+ readonly taskId: string;
59
+ readonly scope: SubagentAliasScope;
60
+ readonly seq?: number;
61
+ }
62
+ export declare function readSeatSubagentAlias(ev: object | null | undefined): SeatSubagentAlias | undefined;
63
+ export declare function noteSeatSubagentAlias(ev: object | null | undefined): 'registered' | 'ignored';
52
64
  export declare function publishSubagentContentEvent(ev: SubagentContentEvent): void;
53
65
  export declare function pushSubagentLocalEcho(taskId: string, text: string): void;
54
66
  export interface SubagentContentSnapshot {
@@ -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)
@@ -812,7 +873,7 @@ export function recordSubagentOwnerFromProgress(ev, ownerRunId, ownerSessionId,
812
873
  if (typeof ev !== 'object' || ev === null)
813
874
  return;
814
875
  const o = ev;
815
- if (o.type !== 'task_progress')
876
+ if (o.type !== 'task_progress' && o.type !== 'task_started')
816
877
  return;
817
878
  if (typeof o.taskId !== 'string' || o.taskId === '')
818
879
  return;
@@ -40,6 +40,8 @@ function judgeAgainst(version, base, floor, caller) {
40
40
  const got = releaseTriple(version);
41
41
  if (got === undefined)
42
42
  return { need: need.text, tier: 'unknown' };
43
+ if (got[0] === 0)
44
+ return { need: need.text, tier: 'unknown' };
43
45
  return { need: need.text, tier: compareTriple(got, need.triple) >= 0 ? 'engine' : 'legacy' };
44
46
  }
45
47
  export function engineVersionTier(version, floor) {
@@ -0,0 +1,19 @@
1
+ import type { RunRecord } from '@sema-agent/sdk';
2
+ export type TaskNotificationAdmissionVerdict = 'admitted' | 'pending' | 'not_found' | 'unreadable';
3
+ export type TaskNotificationAdmissionWhy = 'admitted_at' | 'turns_positive' | 'zero_turns' | 'no_turn_count' | 'key_unbound' | 'read_error' | 'record_malformed' | 'input_unrecognized';
4
+ export type TaskNotificationRunRecordView = RunRecord & {
5
+ readonly admittedAt?: string | null;
6
+ };
7
+ export type TaskNotificationReadResult = {
8
+ readonly kind: 'record';
9
+ readonly record: TaskNotificationRunRecordView;
10
+ } | {
11
+ readonly kind: 'not_found';
12
+ } | {
13
+ readonly kind: 'error';
14
+ };
15
+ export interface TaskNotificationAdmission {
16
+ readonly verdict: TaskNotificationAdmissionVerdict;
17
+ readonly why: TaskNotificationAdmissionWhy;
18
+ }
19
+ export declare function taskNotificationAdmissionOf(readResult: TaskNotificationReadResult): TaskNotificationAdmission;
@@ -0,0 +1,84 @@
1
+ import { guardedRead, readOwnDataValue } from './ownKey.js';
2
+ function verdictOfWhy(why) {
3
+ switch (why) {
4
+ case 'admitted_at':
5
+ case 'turns_positive':
6
+ return 'admitted';
7
+ case 'zero_turns':
8
+ case 'no_turn_count':
9
+ return 'pending';
10
+ case 'key_unbound':
11
+ return 'not_found';
12
+ case 'read_error':
13
+ case 'record_malformed':
14
+ case 'input_unrecognized':
15
+ return 'unreadable';
16
+ default: {
17
+ const unreachable = why;
18
+ return unreachable;
19
+ }
20
+ }
21
+ }
22
+ function ownData(o, key) {
23
+ return guardedRead(() => readOwnDataValue(o, key));
24
+ }
25
+ function isJsonObject(v) {
26
+ if (typeof v !== 'object' || v === null)
27
+ return false;
28
+ try {
29
+ return !Array.isArray(v);
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ function admittedAtProves(v) {
36
+ if (typeof v !== 'string')
37
+ return false;
38
+ const m = /^(\d{4})-(\d{2})-(\d{2})T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/.exec(v);
39
+ if (m === null)
40
+ return false;
41
+ const year = Number(m[1]);
42
+ const month = Number(m[2]);
43
+ const day = Number(m[3]);
44
+ const leap = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
45
+ const daysInMonth = month === 2 ? (leap ? 29 : 28) : month === 4 || month === 6 || month === 9 || month === 11 ? 30 : 31;
46
+ return month >= 1 && month <= 12 && day >= 1 && day <= daysInMonth && Number.isFinite(Date.parse(v));
47
+ }
48
+ function recordWhy(record) {
49
+ if (admittedAtProves(ownData(record, 'admittedAt')))
50
+ return 'admitted_at';
51
+ const result = ownData(record, 'result');
52
+ const stats = isJsonObject(result) ? ownData(result, 'stats') : undefined;
53
+ const turns = isJsonObject(stats) ? ownData(stats, 'turns') : undefined;
54
+ if (typeof turns === 'number' && Number.isInteger(turns)) {
55
+ if (turns > 0)
56
+ return 'turns_positive';
57
+ if (turns === 0)
58
+ return 'zero_turns';
59
+ }
60
+ return 'no_turn_count';
61
+ }
62
+ function readWhy(readResult) {
63
+ if (typeof readResult !== 'object' || readResult === null)
64
+ return 'input_unrecognized';
65
+ const kind = ownData(readResult, 'kind');
66
+ if (kind === 'not_found')
67
+ return 'key_unbound';
68
+ if (kind === 'error')
69
+ return 'read_error';
70
+ if (kind !== 'record')
71
+ return 'input_unrecognized';
72
+ const record = ownData(readResult, 'record');
73
+ return isJsonObject(record) ? recordWhy(record) : 'record_malformed';
74
+ }
75
+ export function taskNotificationAdmissionOf(readResult) {
76
+ let why;
77
+ try {
78
+ why = readWhy(readResult);
79
+ }
80
+ catch {
81
+ why = 'input_unrecognized';
82
+ }
83
+ return Object.freeze({ verdict: verdictOfWhy(why), why });
84
+ }
@@ -3,17 +3,18 @@ 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';
10
10
  import { CORE_ENGINE_CARD_TYPES } from './generated/engineFactTables.js';
11
11
  export const STRUCTURED_DETAIL_TYPES = frozenSet(CORE_ENGINE_CARD_TYPES);
12
+ const LEGACY_STRUCTURED_DETAIL_TYPE = 'task-output';
12
13
  export function structuredDetailType(structured) {
13
14
  if (typeof structured !== 'object' || structured === null)
14
15
  return undefined;
15
16
  const t = structured.type;
16
- return typeof t === 'string' && STRUCTURED_DETAIL_TYPES.has(t) ? t : undefined;
17
+ return typeof t === 'string' && (STRUCTURED_DETAIL_TYPES.has(t) || t === LEGACY_STRUCTURED_DETAIL_TYPE) ? t : undefined;
17
18
  }
18
19
  const MAX_STRUCTURED_FIELD_CHARS = 1_000_000;
19
20
  export const PROTOCOL_MARKERS = {
@@ -369,6 +370,7 @@ export function wireOutputToBody(toolName, output, isError, truncated, flatten,
369
370
  let parsedMemo;
370
371
  const parseOnce = () => (parsedMemo === undefined ? (parsedMemo = parseModelFacingBash(text)) : parsedMemo);
371
372
  const exit = bashExitOf(structured, parseOnce);
373
+ const cut = bashCurtailmentOf(structured);
372
374
  const structuredSlots = sType === 'bash' && (typeof s?.stdout === 'string' || typeof s?.stderr === 'string');
373
375
  const textSlots = structuredSlots ? null : parseOnce();
374
376
  const slots = structuredSlots
@@ -391,26 +393,37 @@ export function wireOutputToBody(toolName, output, isError, truncated, flatten,
391
393
  }
392
394
  if (body.trim() === '' && text.trim() !== '')
393
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
+ }
394
402
  return { content: truncated ? `${body}\n…(truncated)` : body, isError: true };
395
403
  }
396
404
  const stdout = truncated ? `${slots.stdout}\n…(truncated)` : slots.stdout;
397
405
  const processedStdout = stdout.replace(/^(\s*\n)+/, '').trimEnd();
398
406
  return {
399
- content: [processedStdout, slots.stderr.trim()].filter(Boolean).join('\n'),
407
+ content: [cut !== undefined ? bashCurtailmentSentence(cut) : '', processedStdout, slots.stderr.trim()].filter(Boolean).join('\n'),
400
408
  isError: false,
401
409
  toolUseResult: {
402
410
  stdout,
403
- stderr: slots.stderr,
411
+ ...bashCurtailedResultPart(slots.stderr, cut),
404
412
  interrupted: false,
405
413
  ...(benignInterp !== undefined ? { returnCodeInterpretation: benignInterp } : {}),
406
414
  },
407
415
  };
408
416
  }
409
417
  const stdout = truncated ? `${text}\n…(truncated)` : text;
418
+ const cutSentence = cut !== undefined ? bashCurtailmentSentence(cut) : undefined;
410
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
+ }
411
423
  return { content: exit.exitCode === 137 ? `${stdout}\n${killedBySignalSentence(killCauseOf)}` : stdout, isError: true };
412
424
  }
413
- 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 } };
414
427
  }
415
428
  if (name === 'taskoutput' || name === 'task_output') {
416
429
  const body = truncated ? `${text}\n…(truncated)` : text;
@@ -497,10 +510,11 @@ export function structuredToToolUseResult(structured, modelText, leaderLedger =
497
510
  return null;
498
511
  const exit = bashExitOf(structured, () => null);
499
512
  const benignInterp = exit.benignNote;
513
+ const cut = bashCurtailmentOf(structured);
500
514
  return {
501
515
  toolUseResult: {
502
516
  stdout: typeof s.stdout === 'string' ? s.stdout : '',
503
- stderr: typeof s.stderr === 'string' ? s.stderr : '',
517
+ ...bashCurtailedResultPart(typeof s.stderr === 'string' ? s.stderr : '', cut),
504
518
  interrupted: false,
505
519
  ...(benignInterp !== undefined ? { returnCodeInterpretation: benignInterp } : {}),
506
520
  },
@@ -1,5 +1,6 @@
1
1
  import { SETTINGS_IS_HIERARCHICAL_URL } from './generated/settingsSchemaFns.js';
2
2
  import { hostEnv } from './hostEnv.js';
3
+ import { msg, renderMessage } from './i18n/translate.js';
3
4
  export const WEBSEARCH_ENV = {
4
5
  provider: 'SEMA_WEBSEARCH_PROVIDER',
5
6
  endpoint: 'SEMA_WEBSEARCH_ENDPOINT',
@@ -49,6 +50,9 @@ function apiKeyHeaderValue(provider, key) {
49
50
  return `Bearer ${key}`;
50
51
  }
51
52
  }
53
+ function apiKeyWayOutSentence() {
54
+ return renderMessage(msg('config.webSearch.apiKeyWayOut'));
55
+ }
52
56
  function judgeApiKey(provider, raw) {
53
57
  const text = judgeText(raw);
54
58
  if (!text.ok || text.value === undefined)
@@ -215,17 +219,18 @@ function envNameOfField(field) {
215
219
  export function webSearchVerdictMessage(verdict, context = 'submit') {
216
220
  if (verdict.kind !== 'malformed')
217
221
  return undefined;
222
+ const wayOut = verdict.field === 'apiKey' && verdict.issue === API_KEY_ISSUE ? ` ${apiKeyWayOutSentence()}` : '';
218
223
  if (verdict.source === 'host') {
219
224
  const head = `Web search is misconfigured: the API key your host supplied for webSearch is malformed; it ${verdict.issue}.`;
220
225
  return context === 'submit'
221
- ? `${head} The request was not sent — the key needs replacing where your host keeps it.`
222
- : `${head} Requests will be refused until the key is replaced where your host keeps it.`;
226
+ ? `${head} The request was not sent — the key needs replacing where your host keeps it.${wayOut}`
227
+ : `${head} Requests will be refused until the key is replaced where your host keeps it.${wayOut}`;
223
228
  }
224
229
  const where = verdict.source === 'env' ? envNameOfField(verdict.field) : verdict.field === 'section' ? 'the webSearch section in settings' : `webSearch.${verdict.field} in settings`;
225
230
  const fix = verdict.source === 'env' ? 'fix it or unset the SEMA_WEBSEARCH_* variables' : 'fix it or remove the webSearch section';
226
231
  return context === 'submit'
227
- ? `Web search is misconfigured: ${where} ${verdict.issue}. The request was not sent — ${fix}.`
228
- : `Web search is misconfigured: ${where} ${verdict.issue}. Requests will be refused until you ${fix}.`;
232
+ ? `Web search is misconfigured: ${where} ${verdict.issue}. The request was not sent — ${fix}.${wayOut}`
233
+ : `Web search is misconfigured: ${where} ${verdict.issue}. Requests will be refused until you ${fix}.${wayOut}`;
229
234
  }
230
235
  export function webSearchEndpointForDisplay(raw) {
231
236
  if (typeof raw !== 'string' || !SETTINGS_IS_HIERARCHICAL_URL(raw))
@@ -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";
@@ -143,7 +143,28 @@ export interface SessionArchiveStampedDetail {
143
143
  readonly code: typeof CONFLICT_SESSION_ARCHIVE_STAMPED;
144
144
  }
145
145
  export declare function sessionArchiveStampedFromError(err: {} | null | undefined): SessionArchiveStampedDetail | null;
146
- export declare function sessionArchiveStampedContent(lang?: UiLanguage): string;
146
+ export type SessionArchiveStampedScenario = 'fork' | 'push';
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;
147
168
  export interface UnsupportedRuleRefusalProblem {
148
169
  readonly code: string;
149
170
  readonly field?: string;