@sema-agent/client-core 0.98.0 → 0.99.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 (192) hide show
  1. package/CHANGELOG.md +199 -0
  2. package/README.md +35 -22
  3. package/dist/adapt/arms.js +61 -20
  4. package/dist/adapt/panelTasks.d.ts +1 -1
  5. package/dist/adapt/panelTasks.js +2 -2
  6. package/dist/adapter/activeRunSelfHeal.d.ts +4 -3
  7. package/dist/adapter/activeRunSelfHeal.js +162 -293
  8. package/dist/adapter/downstream/eventToSdkMessage.js +52 -4
  9. package/dist/adapter/runStream.js +52 -37
  10. package/dist/adapter/types.js +2 -1
  11. package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
  12. package/dist/agentsWireCaps.d.ts +0 -3
  13. package/dist/agentsWireCaps.js +33 -24
  14. package/dist/cloudConfigWireCaps.d.ts +1 -1
  15. package/dist/cloudConfigWireCaps.js +26 -4
  16. package/dist/controlRouter.d.ts +4 -2
  17. package/dist/controlRouter.js +39 -51
  18. package/dist/coreValuePorts.d.ts +26 -1
  19. package/dist/coreValuePorts.js +10 -0
  20. package/dist/corruptSessionCopy.d.ts +2 -1
  21. package/dist/corruptSessionCopy.js +3 -3
  22. package/dist/declared/supportFloorDeclared.js +1 -1
  23. package/dist/detachWire.js +3 -2
  24. package/dist/devicesFace.d.ts +34 -0
  25. package/dist/devicesFace.js +90 -0
  26. package/dist/displayUntrusted.d.ts +1 -0
  27. package/dist/displayUntrusted.js +3 -0
  28. package/dist/engineAgentPanelStore.d.ts +7 -0
  29. package/dist/engineAgentPanelStore.js +14 -0
  30. package/dist/engineCapReader.d.ts +2 -1
  31. package/dist/engineCapReader.js +7 -5
  32. package/dist/engineCapsCache.d.ts +8 -0
  33. package/dist/engineCapsCache.js +59 -6
  34. package/dist/engineCapsChange.d.ts +2 -0
  35. package/dist/engineCapsChange.js +9 -0
  36. package/dist/engineErrorCodes.d.ts +2 -1
  37. package/dist/engineErrorCodes.js +2 -7
  38. package/dist/engineRowRef.js +3 -0
  39. package/dist/engineSessionMessages.d.ts +1 -0
  40. package/dist/engineSessionMessages.js +7 -1
  41. package/dist/engineTargetSeat.d.ts +27 -0
  42. package/dist/engineTargetSeat.js +199 -0
  43. package/dist/engineWireFor.js +3 -8
  44. package/dist/env/uiLanguage.d.ts +2 -1
  45. package/dist/env/uiLanguage.js +3 -2
  46. package/dist/eventLeg.d.ts +8 -0
  47. package/dist/eventLeg.js +61 -41
  48. package/dist/fileHistoryCaptureCapability.d.ts +2 -1
  49. package/dist/fileHistoryCaptureCapability.js +12 -18
  50. package/dist/fileHistoryLegNotice.d.ts +2 -1
  51. package/dist/fileHistoryLegNotice.js +3 -3
  52. package/dist/frameBinding.d.ts +3 -0
  53. package/dist/frameBinding.js +12 -0
  54. package/dist/gateOutcome.js +16 -2
  55. package/dist/gateVocabulary.d.ts +8 -7
  56. package/dist/gateVocabulary.js +71 -73
  57. package/dist/generated/engineFactTables.d.ts +17 -1
  58. package/dist/generated/engineFactTables.js +29 -0
  59. package/dist/generated/engineNoticeTables.js +9 -3
  60. package/dist/generated/settingsSchemaFns.d.ts +6 -0
  61. package/dist/generated/settingsSchemaFns.js +57 -0
  62. package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
  63. package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
  64. package/dist/generated/settingsSchemaTables.d.ts +1 -0
  65. package/dist/generated/settingsSchemaTables.js +4 -0
  66. package/dist/generated/settingsSchemaTypes.d.ts +105 -0
  67. package/dist/generated/settingsSchemaTypes.js +1 -0
  68. package/dist/hitl/allowRuleShadow.d.ts +2 -1
  69. package/dist/hitl/allowRuleShadow.js +17 -14
  70. package/dist/hitl/approvalCardReasons.d.ts +3 -2
  71. package/dist/hitl/approvalCardReasons.js +27 -28
  72. package/dist/hitl/approvalHolds.d.ts +3 -0
  73. package/dist/hitl/approvalHolds.js +73 -29
  74. package/dist/hitl/askClassPair.d.ts +1 -1
  75. package/dist/hitl/askClassPair.js +16 -0
  76. package/dist/hitl/askGateWire.js +2 -1
  77. package/dist/hitl/askSettlementLine.d.ts +14 -4
  78. package/dist/hitl/askSettlementLine.js +67 -47
  79. package/dist/hitl/automaticAnswerVerdict.d.ts +2 -1
  80. package/dist/hitl/automaticAnswerVerdict.js +8 -8
  81. package/dist/hitl/crashConvergedNotice.d.ts +5 -4
  82. package/dist/hitl/crashConvergedNotice.js +28 -41
  83. package/dist/hitl/frameRouter.js +7 -8
  84. package/dist/hitl/hitlBridge.d.ts +1 -0
  85. package/dist/hitl/hitlBridge.js +3 -3
  86. package/dist/hitl/persistedRulesWire.d.ts +6 -5
  87. package/dist/hitl/persistedRulesWire.js +55 -73
  88. package/dist/hitl/planReviewWire.d.ts +5 -0
  89. package/dist/hitl/planReviewWire.js +8 -0
  90. package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
  91. package/dist/hitl/sessionPolicyDeliverable.js +46 -3
  92. package/dist/hitl/sessionPolicyWire.d.ts +2 -1
  93. package/dist/hitl/sessionPolicyWire.js +23 -24
  94. package/dist/hitl/suspendedReopen.d.ts +2 -1
  95. package/dist/hitl/suspendedReopen.js +7 -10
  96. package/dist/hitl/toolApprovalWire.d.ts +17 -5
  97. package/dist/hitl/toolApprovalWire.js +79 -40
  98. package/dist/hooksWireCaps.js +145 -56
  99. package/dist/host.d.ts +21 -0
  100. package/dist/hostTurnSettings.d.ts +71 -0
  101. package/dist/hostTurnSettings.js +291 -0
  102. package/dist/humanTurn.d.ts +14 -1
  103. package/dist/humanTurn.js +100 -12
  104. package/dist/humanTurnRead.d.ts +2 -0
  105. package/dist/humanTurnRead.js +22 -1
  106. package/dist/i18n/messages.en.d.ts +582 -0
  107. package/dist/i18n/messages.en.js +582 -0
  108. package/dist/i18n/messages.zh.js +718 -1
  109. package/dist/index.d.ts +29 -13
  110. package/dist/index.js +18 -9
  111. package/dist/inheritEnvCapability.d.ts +3 -2
  112. package/dist/inheritEnvCapability.js +3 -3
  113. package/dist/inheritEnvWire.d.ts +3 -2
  114. package/dist/inheritEnvWire.js +12 -14
  115. package/dist/interactiveHalt.js +17 -6
  116. package/dist/liveModelCatalog.d.ts +2 -1
  117. package/dist/liveModelCatalog.js +14 -8
  118. package/dist/mcpPanel.d.ts +10 -1
  119. package/dist/mcpPanel.js +40 -13
  120. package/dist/mcpProbeCapability.d.ts +2 -1
  121. package/dist/mcpProbeCapability.js +7 -11
  122. package/dist/mcpProbeWire.d.ts +3 -1
  123. package/dist/mcpProbeWire.js +5 -0
  124. package/dist/mcpWireCaps.d.ts +34 -0
  125. package/dist/mcpWireCaps.js +117 -17
  126. package/dist/memoryEntriesWire.js +5 -10
  127. package/dist/model/onboardJudgement.d.ts +93 -0
  128. package/dist/model/onboardJudgement.js +415 -0
  129. package/dist/model/tierVocabulary.d.ts +2 -0
  130. package/dist/model/tierVocabulary.js +17 -5
  131. package/dist/modelCapabilityProbe.d.ts +64 -0
  132. package/dist/modelCapabilityProbe.js +600 -0
  133. package/dist/modelIdentityResolvability.d.ts +3 -0
  134. package/dist/modelIdentityResolvability.js +26 -17
  135. package/dist/ownKey.d.ts +7 -0
  136. package/dist/ownKey.js +34 -0
  137. package/dist/panelReduce.d.ts +6 -1
  138. package/dist/panelReduce.js +50 -3
  139. package/dist/permissionRuleIssue.js +2 -0
  140. package/dist/permissionRulesWriteCapability.d.ts +2 -1
  141. package/dist/permissionRulesWriteCapability.js +8 -6
  142. package/dist/pluginHooksWire.d.ts +46 -3
  143. package/dist/pluginHooksWire.js +217 -11
  144. package/dist/printModelStatus.d.ts +63 -0
  145. package/dist/printModelStatus.js +155 -0
  146. package/dist/request/taskRequest.d.ts +11 -5
  147. package/dist/request/taskRequest.js +112 -16
  148. package/dist/resumeRefusalCopy.d.ts +12 -9
  149. package/dist/resumeRefusalCopy.js +70 -143
  150. package/dist/retryStatus.d.ts +37 -0
  151. package/dist/retryStatus.js +79 -0
  152. package/dist/scenarioRefusal.d.ts +9 -0
  153. package/dist/scenarioRefusal.js +111 -0
  154. package/dist/seam.d.ts +25 -1
  155. package/dist/seam.js +10 -1
  156. package/dist/seatContract.d.ts +260 -10
  157. package/dist/seatContract.js +692 -19
  158. package/dist/selfOrchestrationDenial.js +7 -19
  159. package/dist/sessionIdSegment.d.ts +6 -0
  160. package/dist/sessionIdSegment.js +24 -0
  161. package/dist/sessionMemoryStatus.js +6 -11
  162. package/dist/sessionPolicyCapability.d.ts +2 -1
  163. package/dist/sessionPolicyCapability.js +8 -6
  164. package/dist/settingsHooksSalvage.d.ts +44 -0
  165. package/dist/settingsHooksSalvage.js +211 -0
  166. package/dist/skillToolListsCapability.d.ts +2 -1
  167. package/dist/skillToolListsCapability.js +8 -6
  168. package/dist/sseIdleTriage.js +3 -2
  169. package/dist/subagent/engineSubagentResume.js +15 -9
  170. package/dist/subagentContentStore.d.ts +3 -0
  171. package/dist/subagentContentStore.js +22 -0
  172. package/dist/toolHistoryMismatch.js +3 -2
  173. package/dist/toolRoster.d.ts +3 -2
  174. package/dist/toolRoster.js +21 -20
  175. package/dist/turnFailurePresentation.d.ts +12 -1
  176. package/dist/turnFailurePresentation.js +212 -15
  177. package/dist/usageAnalytics.js +6 -11
  178. package/dist/userAttachmentEnvelope.d.ts +1 -0
  179. package/dist/userAttachmentEnvelope.js +37 -7
  180. package/dist/userAttachmentSeat.d.ts +21 -0
  181. package/dist/userAttachmentSeat.js +75 -0
  182. package/dist/userInvokedSkillsCapability.d.ts +11 -1
  183. package/dist/userInvokedSkillsCapability.js +31 -7
  184. package/dist/wireErrorTriage.d.ts +7 -0
  185. package/dist/wireErrorTriage.js +23 -1
  186. package/dist/wireFailureShape.js +2 -1
  187. package/dist/wireRefusalCopy.d.ts +13 -1
  188. package/dist/wireRefusalCopy.js +24 -28
  189. package/dist/workflowsJournalCapability.d.ts +2 -1
  190. package/dist/workflowsJournalCapability.js +8 -6
  191. package/docs/INTEGRATION-CLIENTS.md +542 -30
  192. package/package.json +5 -5
@@ -1,30 +1,18 @@
1
1
  import { CAPABILITY_SELF_ORCHESTRATION_REQUIRED } from './engineErrorCodes.js';
2
+ import { readThrownSlot, THROWN_SLOT_UNREADABLE } from './wireFailureShape.js';
2
3
  const ENTITLEMENT_RESOLVER_ABSENT = 'entitlement_resolver_absent';
3
4
  export const SELF_ORCHESTRATION_RETRY_WITHOUT = Object.freeze(['selfOrchestration', 'settings.ultracode']);
4
5
  export function classifySelfOrchestrationRefusal(e) {
5
- let status;
6
- let code;
7
- try {
8
- const o = e;
9
- const rawStatus = o?.status;
10
- const rawCode = o?.errorCode;
11
- status = typeof rawStatus === 'number' ? rawStatus : undefined;
12
- code = typeof rawCode === 'string' ? rawCode : undefined;
13
- }
14
- catch {
15
- return null;
16
- }
6
+ const rawStatus = readThrownSlot(e, 'status', 'data');
7
+ const rawCode = readThrownSlot(e, 'errorCode', 'data');
8
+ const status = typeof rawStatus === 'number' ? rawStatus : undefined;
9
+ const code = typeof rawCode === 'string' ? rawCode : undefined;
17
10
  if (status !== 501)
18
11
  return null;
19
12
  if (code !== CAPABILITY_SELF_ORCHESTRATION_REQUIRED)
20
13
  return null;
21
- let denial;
22
- try {
23
- denial = e?.denial;
24
- }
25
- catch {
26
- denial = undefined;
27
- }
14
+ const rawDenial = readThrownSlot(e, 'denial', 'data');
15
+ const denial = rawDenial === THROWN_SLOT_UNREADABLE ? undefined : rawDenial;
28
16
  return {
29
17
  kind: 'self-orchestration-denied',
30
18
  retryWithout: SELF_ORCHESTRATION_RETRY_WITHOUT,
@@ -1 +1,7 @@
1
1
  export declare function isSessionIdPathSegment(id: unknown): id is string;
2
+ export type SessionIdRefusalWhy = 'not_string' | 'bad_shape' | 'bad_version' | 'bad_variant';
3
+ export interface SessionIdRefusal {
4
+ readonly why: SessionIdRefusalWhy;
5
+ }
6
+ export declare function canonicalSessionIdOf(raw: {} | null | undefined): string | null;
7
+ export declare function sessionIdRefusalOf(raw: {} | null | undefined): SessionIdRefusal | null;
@@ -9,3 +9,27 @@ export function isSessionIdPathSegment(id) {
9
9
  return false;
10
10
  }
11
11
  }
12
+ const UUID_ANY_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
13
+ function sessionIdReadingOf(raw) {
14
+ if (typeof raw !== 'string')
15
+ return { id: null, why: 'not_string' };
16
+ const folded = raw.replace(/[A-F]/g, (c) => c.toLowerCase());
17
+ if (UUID_ANY_RE.test(folded))
18
+ return { id: folded, why: null };
19
+ const version = folded.charAt(14);
20
+ const variant = folded.charAt(19);
21
+ const hex = '0123456789abcdef';
22
+ if (folded.length !== 36 || !hex.includes(version) || !hex.includes(variant))
23
+ return { id: null, why: 'bad_shape' };
24
+ const probe = `${folded.slice(0, 14)}4${folded.slice(15, 19)}8${folded.slice(20)}`;
25
+ if (!UUID_ANY_RE.test(probe))
26
+ return { id: null, why: 'bad_shape' };
27
+ return { id: null, why: '12345678'.includes(version) ? 'bad_variant' : 'bad_version' };
28
+ }
29
+ export function canonicalSessionIdOf(raw) {
30
+ return sessionIdReadingOf(raw).id;
31
+ }
32
+ export function sessionIdRefusalOf(raw) {
33
+ const r = sessionIdReadingOf(raw);
34
+ return r.why === null ? null : Object.freeze({ why: r.why });
35
+ }
@@ -1,17 +1,12 @@
1
1
  import { isSessionIdPathSegment } from './sessionIdSegment.js';
2
+ import { readThrownSlot, THROWN_SLOT_UNREADABLE } from './wireFailureShape.js';
2
3
  export function classifyMemoryStatusFailure(e) {
3
- let code;
4
- let status;
5
- try {
6
- const o = e;
7
- const rawCode = o?.errorCode;
8
- const rawStatus = o?.status;
9
- code = typeof rawCode === 'string' ? rawCode : undefined;
10
- status = typeof rawStatus === 'number' ? rawStatus : undefined;
11
- }
12
- catch {
4
+ const rawCode = readThrownSlot(e, 'errorCode', 'data');
5
+ const rawStatus = readThrownSlot(e, 'status', 'data');
6
+ if (rawCode === THROWN_SLOT_UNREADABLE || rawStatus === THROWN_SLOT_UNREADABLE)
13
7
  return { kind: 'failed', error: e };
14
- }
8
+ const code = typeof rawCode === 'string' ? rawCode : undefined;
9
+ const status = typeof rawStatus === 'number' ? rawStatus : undefined;
15
10
  if (code !== undefined) {
16
11
  if (code.startsWith('capability.'))
17
12
  return { kind: 'unsupported', reason: 'capability' };
@@ -1,3 +1,4 @@
1
+ import type { UiLanguage } from './env/uiLanguage.js';
1
2
  export type SessionPolicyReading = {
2
3
  kind: 'unobserved';
3
4
  } | {
@@ -12,4 +13,4 @@ export type SessionPolicyReading = {
12
13
  export declare function projectSessionPolicyCapability(caps: unknown): SessionPolicyReading | undefined;
13
14
  export declare function observedSessionPolicy(baseUrl?: string | undefined): SessionPolicyReading;
14
15
  export declare function sessionPolicyFaceAvailable(reading: SessionPolicyReading): 'yes' | 'no' | 'unknown';
15
- export declare function sessionPolicyDoctorDetail(reading: SessionPolicyReading): string;
16
+ export declare function sessionPolicyDoctorDetail(reading: SessionPolicyReading, lang?: UiLanguage): string;
@@ -1,5 +1,6 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader, unreadableReadingDetail } from './engineCapReader.js';
3
+ import { msg, renderMessage } from './i18n/translate.js';
3
4
  import { ownDataField } from './ownKey.js';
4
5
  export function projectSessionPolicyCapability(caps) {
5
6
  try {
@@ -31,17 +32,18 @@ export function sessionPolicyFaceAvailable(reading) {
31
32
  return 'no';
32
33
  return 'unknown';
33
34
  }
34
- export function sessionPolicyDoctorDetail(reading) {
35
+ export function sessionPolicyDoctorDetail(reading, lang) {
36
+ const subject = msg('notice.capability.subject.sessionPolicy');
35
37
  switch (reading.kind) {
36
38
  case 'unreadable':
37
- return unreadableReadingDetail('per-session rule face');
39
+ return unreadableReadingDetail(renderMessage(subject, lang), lang);
38
40
  case 'unobserved':
39
- return 'per-session rule face not observed — the engine reports it on /v1/capabilities (sessionPolicy); this process has no usable capabilities reading cached for it (none received, the last one was unreadable, or the last one was discarded when the engine connection was reset; this process cannot tell which)';
41
+ return renderMessage(msg('notice.capability.unobserved', { subject, key: 'sessionPolicy' }), lang);
40
42
  case 'not_reported':
41
- return 'per-session rule face not reported by this engine — this binary predates the position itself; it says nothing about whether the face exists, so read the rules rather than writing them blind';
43
+ return renderMessage(msg('notice.capability.sessionPolicy.notReported'), lang);
42
44
  case 'absent':
43
- return 'no per-session rule store on this deployment — reading and writing this session’s tool rules is unavailable here';
45
+ return renderMessage(msg('notice.capability.sessionPolicy.absent'), lang);
44
46
  case 'present':
45
- return 'per-session rule face on — this session’s tool rules can be read, and a tightening write is accepted or refused by the engine call by call';
47
+ return renderMessage(msg('notice.capability.sessionPolicy.present'), lang);
46
48
  }
47
49
  }
@@ -0,0 +1,44 @@
1
+ import type { WireHooksConfig } from './finalVerifyWire.js';
2
+ import type { SettingsDocument } from './host.js';
3
+ import type { HookSettingsSource } from './pluginHooksWire.js';
4
+ export type HooksSalvageOutcome = 'loaded' | 'loaded-partial' | 'rejected';
5
+ export type HooksSalvageDropCode = 'hooks-not-object' | 'unknown-event' | 'event-not-array' | 'matcher-invalid' | 'entry-invalid';
6
+ export type HooksSalvageRejectionCode = 'guard-outside-hooks' | 'hooks-is-matcher' | 'guard-under-unknown-event' | 'guard-event-not-array' | 'guard-matcher-invalid' | 'guard-entry-invalid';
7
+ export interface HooksSalvageDrop {
8
+ readonly code: HooksSalvageDropCode;
9
+ readonly path: readonly (string | number)[];
10
+ readonly field?: string;
11
+ }
12
+ export interface HooksSalvageRejection {
13
+ readonly code: HooksSalvageRejectionCode;
14
+ readonly path: readonly (string | number)[];
15
+ readonly field?: string;
16
+ }
17
+ export type HooksSalvage = {
18
+ readonly outcome: 'loaded';
19
+ readonly hooks: WireHooksConfig | undefined;
20
+ readonly dropped: readonly [];
21
+ readonly rejections: readonly [];
22
+ } | {
23
+ readonly outcome: 'loaded-partial';
24
+ readonly hooks: WireHooksConfig | undefined;
25
+ readonly dropped: readonly HooksSalvageDrop[];
26
+ readonly rejections: readonly [];
27
+ } | {
28
+ readonly outcome: 'rejected';
29
+ readonly hooks: undefined;
30
+ readonly dropped: readonly [];
31
+ readonly rejections: readonly HooksSalvageRejection[];
32
+ };
33
+ export interface HooksSalvageMask {
34
+ readonly hooksDropped: boolean;
35
+ eventDropped(event: string): boolean;
36
+ groupDropped(event: string, groupIndex: number): boolean;
37
+ entryDropped(event: string, groupIndex: number, hookIndex: number): boolean;
38
+ }
39
+ export declare function hooksSalvageMaskOf(dropped: readonly {
40
+ readonly path: readonly (string | number)[];
41
+ }[]): HooksSalvageMask;
42
+ export declare function salvageSettingsHooksEntries(doc: SettingsDocument | null | undefined): HooksSalvage;
43
+ export declare const HOOK_SETTINGS_SOURCE_TEXT: Readonly<Record<HookSettingsSource, string>>;
44
+ export declare function settingsHooksSalvageNotice(salvage: HooksSalvage, source: HookSettingsSource, doc?: SettingsDocument | null): string | undefined;
@@ -0,0 +1,211 @@
1
+ import { displayUntrusted } from './displayUntrusted.js';
2
+ import { SETTINGS_CLASSIFY_HOOKS_CONFIG, } from './generated/settingsSchemaFns.js';
3
+ const _tuplePins = [true, true, true, true, true, true];
4
+ void _tuplePins;
5
+ const _classifierPins = [true, true, true, true, true, true];
6
+ void _classifierPins;
7
+ const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
8
+ const own = (o, k) => (Object.hasOwn(o, k) ? o[k] : undefined);
9
+ const freezeRow = (row) => Object.freeze(row);
10
+ function pieceOf(p) {
11
+ return freezeRow({ code: p.code, path: Object.freeze([...p.path]), ...(typeof p.field === 'string' ? { field: p.field } : {}) });
12
+ }
13
+ const EMPTY_MASK = Object.freeze({
14
+ hooksDropped: false,
15
+ eventDropped: () => false,
16
+ groupDropped: () => false,
17
+ entryDropped: () => false,
18
+ });
19
+ export function hooksSalvageMaskOf(dropped) {
20
+ if (dropped.length === 0)
21
+ return EMPTY_MASK;
22
+ let all = false;
23
+ const events = new Set();
24
+ const groups = new Set();
25
+ const entries = new Set();
26
+ for (const d of dropped) {
27
+ const p = d.path;
28
+ if (p[0] !== 'hooks') {
29
+ all = true;
30
+ continue;
31
+ }
32
+ if (p.length === 1)
33
+ all = true;
34
+ else if (p.length === 2 && typeof p[1] === 'string')
35
+ events.add(p[1]);
36
+ else if (p.length === 3 && typeof p[1] === 'string' && typeof p[2] === 'number')
37
+ groups.add(`${p[1]}\u0000${p[2]}`);
38
+ else if (p.length === 5 && typeof p[1] === 'string' && typeof p[2] === 'number' && p[3] === 'hooks' && typeof p[4] === 'number')
39
+ entries.add(`${p[1]}\u0000${p[2]}\u0000${p[4]}`);
40
+ else
41
+ all = true;
42
+ }
43
+ return Object.freeze({
44
+ hooksDropped: all,
45
+ eventDropped: (event) => all || events.has(event),
46
+ groupDropped: (event, gi) => all || events.has(event) || groups.has(`${event}\u0000${gi}`),
47
+ entryDropped: (event, gi, hi) => all || events.has(event) || groups.has(`${event}\u0000${gi}`) || entries.has(`${event}\u0000${gi}\u0000${hi}`),
48
+ });
49
+ }
50
+ function pruneHooks(hooks, mask) {
51
+ if (mask.hooksDropped || !isRecord(hooks))
52
+ return undefined;
53
+ const out = [];
54
+ for (const event of Object.keys(hooks)) {
55
+ if (mask.eventDropped(event))
56
+ continue;
57
+ const groups = own(hooks, event);
58
+ if (!Array.isArray(groups)) {
59
+ out.push([event, groups]);
60
+ continue;
61
+ }
62
+ const keptGroups = [];
63
+ let changed = false;
64
+ groups.forEach((group, gi) => {
65
+ if (mask.groupDropped(event, gi)) {
66
+ changed = true;
67
+ return;
68
+ }
69
+ const entries = isRecord(group) ? own(group, 'hooks') : undefined;
70
+ if (!isRecord(group) || !Array.isArray(entries)) {
71
+ keptGroups.push(group);
72
+ return;
73
+ }
74
+ const keptEntries = entries.filter((_e, hi) => !mask.entryDropped(event, gi, hi));
75
+ if (keptEntries.length === entries.length) {
76
+ keptGroups.push(group);
77
+ return;
78
+ }
79
+ changed = true;
80
+ if (keptEntries.length > 0)
81
+ keptGroups.push({ ...group, hooks: keptEntries });
82
+ });
83
+ if (!changed)
84
+ out.push([event, groups]);
85
+ else if (keptGroups.length > 0)
86
+ out.push([event, keptGroups]);
87
+ }
88
+ return out.length > 0 ? Object.fromEntries(out) : undefined;
89
+ }
90
+ export function salvageSettingsHooksEntries(doc) {
91
+ const r = SETTINGS_CLASSIFY_HOOKS_CONFIG(doc);
92
+ if (r.outcome === 'rejected') {
93
+ return Object.freeze({ outcome: 'rejected', hooks: undefined, dropped: Object.freeze([]), rejections: Object.freeze(r.rejections.map(pieceOf)) });
94
+ }
95
+ const original = isRecord(doc) ? own(doc, 'hooks') : undefined;
96
+ if (r.outcome === 'loaded') {
97
+ return Object.freeze({
98
+ outcome: 'loaded',
99
+ hooks: isRecord(original) ? original : undefined,
100
+ dropped: Object.freeze([]),
101
+ rejections: Object.freeze([]),
102
+ });
103
+ }
104
+ const dropped = Object.freeze(r.dropped.map(pieceOf));
105
+ return Object.freeze({
106
+ outcome: 'loaded-partial',
107
+ hooks: pruneHooks(original, hooksSalvageMaskOf(dropped)),
108
+ dropped,
109
+ rejections: Object.freeze([]),
110
+ });
111
+ }
112
+ export const HOOK_SETTINGS_SOURCE_TEXT = Object.freeze({
113
+ policySettings: 'Managed settings',
114
+ userSettings: 'User settings',
115
+ projectSettings: 'Project settings',
116
+ localSettings: 'Local settings',
117
+ flagSettings: 'Flag settings',
118
+ });
119
+ const SALVAGE_LABEL_MAX = 80;
120
+ const SALVAGE_PIECES_SHOWN = 3;
121
+ const labelOf = (s) => (typeof s === 'number' ? String(s) : displayUntrusted(s, { max: SALVAGE_LABEL_MAX }));
122
+ function receivedOf(v) {
123
+ if (v === null)
124
+ return 'null';
125
+ if (Array.isArray(v))
126
+ return 'array';
127
+ return typeof v === 'object' ? 'object' : typeof v;
128
+ }
129
+ function valueAt(doc, path) {
130
+ let cur = doc;
131
+ for (const seg of path) {
132
+ if (typeof seg === 'number')
133
+ cur = Array.isArray(cur) ? cur[seg] : undefined;
134
+ else
135
+ cur = isRecord(cur) ? own(cur, seg) : undefined;
136
+ }
137
+ return cur;
138
+ }
139
+ function whereOf(path) {
140
+ const ev = path[1];
141
+ const gi = path[2];
142
+ const hi = path[4];
143
+ const evText = ev === undefined ? '' : `"${labelOf(ev)}"`;
144
+ if (typeof gi !== 'number')
145
+ return evText;
146
+ return typeof hi === 'number' ? `${evText} (matcher ${gi + 1}, hook ${hi + 1})` : `${evText} (matcher ${gi + 1})`;
147
+ }
148
+ const fieldTail = (field) => (field !== undefined ? ` (field "${labelOf(field)}")` : '');
149
+ function dropPhrase(d, doc) {
150
+ switch (d.code) {
151
+ case 'hooks-not-object':
152
+ return `"hooks" must be an object mapping event names to matcher arrays; received ${receivedOf(valueAt(doc, d.path))}. This field was ignored`;
153
+ case 'unknown-event':
154
+ return `Unknown hook event ${whereOf(d.path)} was ignored`;
155
+ case 'event-not-array':
156
+ return `Hook event ${whereOf(d.path)} must be an array of matchers; received ${receivedOf(valueAt(doc, d.path))}. This entry was ignored`;
157
+ case 'matcher-invalid':
158
+ return `an invalid matcher under hook event ${whereOf(d.path)}${fieldTail(d.field)} was ignored`;
159
+ case 'entry-invalid':
160
+ return `an invalid hook under hook event ${whereOf(d.path)}${fieldTail(d.field)} was ignored`;
161
+ }
162
+ }
163
+ function rejectionPhrase(r) {
164
+ switch (r.code) {
165
+ case 'guard-outside-hooks':
166
+ return `a PreToolUse or PermissionRequest hook is written outside "hooks" (at ${r.path.map(labelOf).join('.') || 'the top level'})`;
167
+ case 'hooks-is-matcher':
168
+ return '"hooks" is written as a matcher or a single hook instead of an object of hook events';
169
+ case 'guard-under-unknown-event':
170
+ return `${whereOf(r.path)} is not a hook event, but it holds PreToolUse or PermissionRequest hooks`;
171
+ case 'guard-event-not-array':
172
+ return `hook event ${whereOf(r.path)} is not an array of matchers`;
173
+ case 'guard-matcher-invalid':
174
+ return `a matcher under hook event ${whereOf(r.path)}${fieldTail(r.field)} is invalid or holds a misplaced hook`;
175
+ case 'guard-entry-invalid':
176
+ return `a hook under hook event ${whereOf(r.path)}${fieldTail(r.field)} is invalid or holds a misplaced hook`;
177
+ }
178
+ }
179
+ function joinPhrases(phrases) {
180
+ const seen = new Set();
181
+ const uniq = [];
182
+ for (const p of phrases) {
183
+ if (seen.has(p.key))
184
+ continue;
185
+ seen.add(p.key);
186
+ uniq.push(p.text);
187
+ }
188
+ const shown = uniq.slice(0, SALVAGE_PIECES_SHOWN).join('; ');
189
+ return uniq.length > SALVAGE_PIECES_SHOWN ? `${shown}; and ${uniq.length - SALVAGE_PIECES_SHOWN} more` : shown;
190
+ }
191
+ const GUARD_RISK_TAIL = 'a PreToolUse or PermissionRequest hook that cannot be loaded may be what guards the permissions declared beside it, so none of the hooks in this file are applied until it is fixed';
192
+ export function settingsHooksSalvageNotice(salvage, source, doc) {
193
+ const layer = HOOK_SETTINGS_SOURCE_TEXT[source] ?? 'Settings';
194
+ try {
195
+ if (salvage.outcome === 'loaded-partial') {
196
+ const what = joinPhrases(salvage.dropped.map((d) => ({ key: d.path.join('\u0000'), text: dropPhrase(d, doc) })));
197
+ return `${layer}: ${what}. The rest of this file's hooks are applied.`;
198
+ }
199
+ if (salvage.outcome === 'rejected') {
200
+ const why = joinPhrases(salvage.rejections.map((r) => ({ key: r.path.join('\u0000'), text: rejectionPhrase(r) })));
201
+ if (source === 'policySettings') {
202
+ return `${layer}: hooks could not be loaded — ${why}. Requests are not sent while the managed hooks cannot be applied; ask your administrator to fix the managed settings.`;
203
+ }
204
+ return `${layer}: hooks were not loaded — ${why}; ${GUARD_RISK_TAIL}.`;
205
+ }
206
+ return undefined;
207
+ }
208
+ catch {
209
+ return salvage.outcome === 'loaded' ? undefined : `${layer}: some hooks in this file could not be loaded.`;
210
+ }
211
+ }
@@ -1,3 +1,4 @@
1
+ import type { UiLanguage } from './env/uiLanguage.js';
1
2
  export type SkillToolListsReading = {
2
3
  kind: 'unobserved';
3
4
  } | {
@@ -12,4 +13,4 @@ export type SkillToolListsReading = {
12
13
  export declare function projectSkillToolListsCapability(caps: unknown): SkillToolListsReading | undefined;
13
14
  export declare function observedSkillToolLists(baseUrl?: string | undefined): SkillToolListsReading;
14
15
  export declare function skillToolListsAvailable(reading: SkillToolListsReading): 'yes' | 'no' | 'unknown';
15
- export declare function skillToolListsDoctorDetail(reading: SkillToolListsReading): string;
16
+ export declare function skillToolListsDoctorDetail(reading: SkillToolListsReading, lang?: UiLanguage): string;
@@ -1,5 +1,6 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader, unreadableReadingDetail } from './engineCapReader.js';
3
+ import { msg, renderMessage } from './i18n/translate.js';
3
4
  import { ownDataField } from './ownKey.js';
4
5
  export function projectSkillToolListsCapability(caps) {
5
6
  try {
@@ -30,17 +31,18 @@ export function skillToolListsAvailable(reading) {
30
31
  return 'no';
31
32
  return 'unknown';
32
33
  }
33
- export function skillToolListsDoctorDetail(reading) {
34
+ export function skillToolListsDoctorDetail(reading, lang) {
35
+ const subject = msg('notice.capability.subject.skillToolLists');
34
36
  switch (reading.kind) {
35
37
  case 'unreadable':
36
- return unreadableReadingDetail('skill tool lists');
38
+ return unreadableReadingDetail(renderMessage(subject, lang), lang);
37
39
  case 'unobserved':
38
- return 'skill tool lists not observed — the engine reports it on /v1/capabilities (skillToolLists); this process has no usable capabilities reading cached for it (none received, the last one was unreadable, or the last one was discarded when the engine connection was reset; this process cannot tell which)';
40
+ return renderMessage(msg('notice.capability.unobserved', { subject, key: 'skillToolLists' }), lang);
39
41
  case 'not_reported':
40
- return 'skill tool lists not reported by this engine — the engine predates them: tool lists on request skills are not read, so they do not limit any tool';
42
+ return renderMessage(msg('notice.capability.skillToolLists.notReported'), lang);
41
43
  case 'absent':
42
- return 'skill tool lists off on this deployment — tool lists on request skills are not read';
44
+ return renderMessage(msg('notice.capability.skillToolLists.absent'), lang);
43
45
  case 'present':
44
- return 'skill tool lists on — a request skill’s allowed and disallowed tool lists are read as this run’s rules';
46
+ return renderMessage(msg('notice.capability.skillToolLists.present'), lang);
45
47
  }
46
48
  }
@@ -1,5 +1,6 @@
1
1
  import { hostEnv } from './hostEnv.js';
2
2
  import { SseIdleError, probeHealth as sdkProbeHealth } from '@sema-agent/sdk';
3
+ import { readThrownSlot, thrownIsInstanceOf } from './wireFailureShape.js';
3
4
  export const SSE_HEARTBEAT_GRACE_ENV = 'SEMA_SSE_HEARTBEAT_GRACE_MS';
4
5
  export const SSE_GRACE_MIN_MS = 5_000;
5
6
  export const SSE_GRACE_MAX_MS = 600_000;
@@ -27,9 +28,9 @@ export function engineAliveIdleElapsedMs(err) {
27
28
  return typeof e.elapsedMs === 'number' && Number.isFinite(e.elapsedMs) ? e.elapsedMs : 0;
28
29
  }
29
30
  export function isSseIdleError(err) {
30
- if (err instanceof SseIdleError)
31
+ if (thrownIsInstanceOf(err, SseIdleError))
31
32
  return true;
32
- return err?.name === 'SseIdleError';
33
+ return readThrownSlot(err, 'name', 'data') === 'SseIdleError';
33
34
  }
34
35
  export async function probeEngineAlive(baseUrl, timeoutMs = 2_000) {
35
36
  return (await sdkProbeHealth(baseUrl, timeoutMs)).alive;
@@ -1,5 +1,6 @@
1
1
  import { hostLog } from '../host.js';
2
- import { resumeRetryLaterFromError } from '../wireErrorTriage.js';
2
+ import { isNotFoundFailure, resumeRetryLaterFromError } from '../wireErrorTriage.js';
3
+ import { readThrownSlot, THROWN_SLOT_UNREADABLE } from '../wireFailureShape.js';
3
4
  import { RESUME_SESSION_NOT_FOUND } from '../engineErrorCodes.js';
4
5
  import { displayUntrusted } from '../displayUntrusted.js';
5
6
  import { engineCapTrue } from '../engineCapsCache.js';
@@ -25,15 +26,22 @@ const RETENTION_LAPSED_CODES = new Set([
25
26
  RESUME_SESSION_NOT_FOUND,
26
27
  ]);
27
28
  function shapeOf(e) {
28
- const o = (e ?? {});
29
+ const status = readThrownSlot(e ?? {}, 'status', 'data');
30
+ const errorCode = readThrownSlot(e ?? {}, 'errorCode', 'data');
31
+ const message = readThrownSlot(e ?? {}, 'message');
32
+ if (status === THROWN_SLOT_UNREADABLE || errorCode === THROWN_SLOT_UNREADABLE) {
33
+ return { message: typeof message === 'string' && message !== '' ? message : String(e), unreadable: true };
34
+ }
29
35
  return {
30
- ...(typeof o.status === 'number' ? { status: o.status } : {}),
31
- ...(typeof o.errorCode === 'string' ? { errorCode: o.errorCode } : {}),
32
- message: typeof o.message === 'string' && o.message !== '' ? o.message : String(e),
36
+ ...(typeof status === 'number' ? { status } : {}),
37
+ ...(typeof errorCode === 'string' ? { errorCode } : {}),
38
+ message: typeof message === 'string' && message !== '' ? message : String(e),
33
39
  };
34
40
  }
35
41
  export function classifySubagentResumeFailure(e) {
36
- const { status, errorCode, message } = shapeOf(e);
42
+ const { status, errorCode, message, unreadable } = shapeOf(e);
43
+ if (unreadable === true)
44
+ return { reason: 'error', detail: message };
37
45
  if (status === undefined && errorCode === undefined) {
38
46
  const noAnswer = typeof e === 'object' ? noAnswerDetailFrom(e) : null;
39
47
  if (noAnswer !== null)
@@ -63,12 +71,10 @@ export function classifySubagentResumeFailure(e) {
63
71
  return { reason: 'row-contended', detail: message };
64
72
  if (errorCode === 'resume.row_gone')
65
73
  return { reason: 'row-gone', detail: message };
66
- if (errorCode === undefined && status === 404)
74
+ if (isNotFoundFailure(e) !== false)
67
75
  return { reason: 'not-found', detail: message };
68
76
  if (errorCode === undefined && status === 400)
69
77
  return { reason: 'bad-request', detail: message };
70
- if (errorCode?.startsWith('not_found.') === true)
71
- return { reason: 'not-found', detail: message };
72
78
  return { reason: 'error', detail: message };
73
79
  }
74
80
  export function resolveOwnerRunId(childTaskId, activeRunId) {
@@ -33,6 +33,9 @@ export interface SubagentContentEvent {
33
33
  isError?: boolean | undefined;
34
34
  }
35
35
  export declare function coerceOutput(v: unknown): string | undefined;
36
+ export declare function subagentContentEventOf(ev: {
37
+ readonly type: string;
38
+ }): SubagentContentEvent | undefined;
36
39
  export interface SubagentContentStoreConfig {
37
40
  maxBytesPerTask: number;
38
41
  maxBytesTotal: number;
@@ -3,6 +3,28 @@ import { toolEndOutputText } from './toolResultContent.js';
3
3
  export function coerceOutput(v) {
4
4
  return toolEndOutputText(v);
5
5
  }
6
+ export function subagentContentEventOf(ev) {
7
+ const t = ev.type;
8
+ if (t !== 'text_delta' && t !== 'reasoning_delta' && t !== 'text' && t !== 'reasoning' && t !== 'tool_start' && t !== 'tool_end')
9
+ return undefined;
10
+ const sub = ev;
11
+ const parent = sub.parentToolCallId;
12
+ if (typeof parent !== 'string')
13
+ return undefined;
14
+ return {
15
+ type: sub.type,
16
+ taskId: sub.taskId ?? parent,
17
+ parentToolCallId: parent,
18
+ delta: sub.delta,
19
+ text: sub.text,
20
+ eventId: sub.eventId,
21
+ toolCallId: sub.toolCallId,
22
+ toolName: sub.toolName,
23
+ args: sub.args,
24
+ output: coerceOutput(sub.output),
25
+ isError: sub.isError,
26
+ };
27
+ }
6
28
  const MAX_ITEMS_PER_TASK = 200;
7
29
  const MAX_TASKS = 32;
8
30
  const NOTIFY_COALESCE_MS = 250;
@@ -1,4 +1,5 @@
1
1
  import { rewindArchiveReadingAt, rewindConversationAvailability } from './rewindArchiveReading.js';
2
+ import { ownDataField } from './ownKey.js';
2
3
  export const TOOL_HISTORY_MISMATCH_KINDS = Object.freeze([
3
4
  'tool_use_without_result',
4
5
  'orphan_tool_result',
@@ -191,8 +192,8 @@ export function classifyToolHistoryMismatch(err) {
191
192
  let status;
192
193
  let rawMessage;
193
194
  try {
194
- code = err.code;
195
- status = err.status;
195
+ code = ownDataField(err, 'code');
196
+ status = ownDataField(err, 'status');
196
197
  rawMessage = err.message;
197
198
  }
198
199
  catch {
@@ -1,3 +1,4 @@
1
+ import type { UiLanguage } from './env/uiLanguage.js';
1
2
  export interface ToolRosterPathTargetView {
2
3
  param: string;
3
4
  access: string;
@@ -77,8 +78,8 @@ export type HandsSeamReading = {
77
78
  export declare function handsSeamReadingOf(view: {
78
79
  readonly hands?: WiringManifestHandsView;
79
80
  } | null | undefined): HandsSeamReading;
80
- export declare function handsSeamDetail(reading: HandsSeamReading): string;
81
- export declare function handsMountedDetail(reading: HandsMountedReading): string;
81
+ export declare function handsSeamDetail(reading: HandsSeamReading, lang?: UiLanguage): string;
82
+ export declare function handsMountedDetail(reading: HandsMountedReading, lang?: UiLanguage): string;
82
83
  export declare function toolRosterNames(roster: ToolRosterView | undefined): readonly string[];
83
84
  export interface ToolShim {
84
85
  name: string;