@sema-agent/client-core 0.98.0 → 0.100.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 (236) hide show
  1. package/CHANGELOG.md +376 -0
  2. package/README.md +61 -35
  3. package/dist/adapt/arms.js +120 -55
  4. package/dist/adapt/panelTasks.d.ts +3 -2
  5. package/dist/adapt/panelTasks.js +34 -11
  6. package/dist/adapt/textStream.d.ts +1 -1
  7. package/dist/adapt/textStream.js +51 -28
  8. package/dist/adapter/activeRunSelfHeal.d.ts +11 -3
  9. package/dist/adapter/activeRunSelfHeal.js +210 -294
  10. package/dist/adapter/downstream/eventToSdkMessage.d.ts +25 -6
  11. package/dist/adapter/downstream/eventToSdkMessage.js +176 -12
  12. package/dist/adapter/downstream/terminalToSdkResult.js +10 -0
  13. package/dist/adapter/downstream/wiringManifestView.d.ts +3 -1
  14. package/dist/adapter/downstream/wiringManifestView.js +1 -0
  15. package/dist/adapter/runStream.js +82 -40
  16. package/dist/adapter/types.d.ts +2 -0
  17. package/dist/adapter/types.js +2 -1
  18. package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
  19. package/dist/agentsWireCaps.d.ts +7 -3
  20. package/dist/agentsWireCaps.js +133 -39
  21. package/dist/cloudConfigWireCaps.d.ts +10 -1
  22. package/dist/cloudConfigWireCaps.js +181 -65
  23. package/dist/compactionStatus.d.ts +34 -0
  24. package/dist/compactionStatus.js +196 -0
  25. package/dist/controlRouter.d.ts +4 -2
  26. package/dist/controlRouter.js +39 -51
  27. package/dist/coreValuePorts.d.ts +26 -1
  28. package/dist/coreValuePorts.js +10 -0
  29. package/dist/corruptSessionCopy.d.ts +2 -1
  30. package/dist/corruptSessionCopy.js +3 -3
  31. package/dist/decideFailureNote.js +3 -3
  32. package/dist/declared/supportFloorDeclared.js +1 -1
  33. package/dist/detachWire.js +3 -2
  34. package/dist/devicesFace.d.ts +34 -0
  35. package/dist/devicesFace.js +90 -0
  36. package/dist/displayUntrusted.d.ts +1 -0
  37. package/dist/displayUntrusted.js +153 -5
  38. package/dist/engineAgentPanelStore.d.ts +14 -4
  39. package/dist/engineAgentPanelStore.js +14 -0
  40. package/dist/engineCapReader.d.ts +2 -1
  41. package/dist/engineCapReader.js +7 -5
  42. package/dist/engineCapsCache.d.ts +8 -0
  43. package/dist/engineCapsCache.js +59 -6
  44. package/dist/engineCapsChange.d.ts +2 -0
  45. package/dist/engineCapsChange.js +9 -0
  46. package/dist/engineErrorCodes.d.ts +11 -2
  47. package/dist/engineErrorCodes.js +11 -12
  48. package/dist/engineRowRef.js +4 -0
  49. package/dist/engineSessionMessages.d.ts +1 -0
  50. package/dist/engineSessionMessages.js +7 -1
  51. package/dist/engineTargetSeat.d.ts +27 -0
  52. package/dist/engineTargetSeat.js +199 -0
  53. package/dist/engineToolDirectory.d.ts +3 -0
  54. package/dist/engineToolDirectory.js +4 -2
  55. package/dist/engineWireFor.js +3 -8
  56. package/dist/env/uiLanguage.d.ts +2 -1
  57. package/dist/env/uiLanguage.js +3 -2
  58. package/dist/eventLeg.d.ts +7 -5
  59. package/dist/eventLeg.js +68 -49
  60. package/dist/fileHistoryCaptureCapability.d.ts +2 -4
  61. package/dist/fileHistoryCaptureCapability.js +12 -22
  62. package/dist/fileHistoryLegNotice.d.ts +2 -1
  63. package/dist/fileHistoryLegNotice.js +3 -3
  64. package/dist/frameBinding.d.ts +3 -0
  65. package/dist/frameBinding.js +12 -0
  66. package/dist/gateOutcome.js +16 -2
  67. package/dist/gateVocabulary.d.ts +8 -7
  68. package/dist/gateVocabulary.js +71 -73
  69. package/dist/generated/engineFactTables.d.ts +18 -1
  70. package/dist/generated/engineFactTables.js +56 -0
  71. package/dist/generated/engineNoticeTables.js +12 -3
  72. package/dist/generated/settingsSchemaFns.d.ts +18 -0
  73. package/dist/generated/settingsSchemaFns.js +70 -0
  74. package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
  75. package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
  76. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -0
  77. package/dist/generated/settingsSchemaMcpRequestEntry.js +162 -0
  78. package/dist/generated/settingsSchemaTables.d.ts +2 -0
  79. package/dist/generated/settingsSchemaTables.js +9 -0
  80. package/dist/generated/settingsSchemaTypes.d.ts +133 -0
  81. package/dist/generated/settingsSchemaTypes.js +1 -0
  82. package/dist/hitl/allowRuleShadow.d.ts +2 -1
  83. package/dist/hitl/allowRuleShadow.js +18 -15
  84. package/dist/hitl/approvalCardReasons.d.ts +3 -2
  85. package/dist/hitl/approvalCardReasons.js +29 -30
  86. package/dist/hitl/approvalHolds.d.ts +17 -0
  87. package/dist/hitl/approvalHolds.js +114 -29
  88. package/dist/hitl/askClassPair.d.ts +2 -2
  89. package/dist/hitl/askClassPair.js +16 -0
  90. package/dist/hitl/askGateWire.js +2 -1
  91. package/dist/hitl/askSettlementLine.d.ts +14 -4
  92. package/dist/hitl/askSettlementLine.js +67 -47
  93. package/dist/hitl/attributionLadder.d.ts +23 -0
  94. package/dist/hitl/attributionLadder.js +67 -0
  95. package/dist/hitl/automaticAnswerVerdict.d.ts +2 -1
  96. package/dist/hitl/automaticAnswerVerdict.js +8 -8
  97. package/dist/hitl/crashConvergedNotice.d.ts +5 -4
  98. package/dist/hitl/crashConvergedNotice.js +28 -41
  99. package/dist/hitl/decisionLedger.d.ts +55 -0
  100. package/dist/hitl/decisionLedger.js +156 -0
  101. package/dist/hitl/decisionRefusal.d.ts +1 -0
  102. package/dist/hitl/decisionRefusal.js +1 -1
  103. package/dist/hitl/decisionSend.d.ts +113 -0
  104. package/dist/hitl/decisionSend.js +579 -0
  105. package/dist/hitl/frameRouter.js +7 -8
  106. package/dist/hitl/hitlBridge.d.ts +1 -0
  107. package/dist/hitl/hitlBridge.js +21 -9
  108. package/dist/hitl/persistedRulesWire.d.ts +6 -5
  109. package/dist/hitl/persistedRulesWire.js +55 -73
  110. package/dist/hitl/planReviewWire.d.ts +5 -0
  111. package/dist/hitl/planReviewWire.js +53 -76
  112. package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
  113. package/dist/hitl/sessionPolicyDeliverable.js +49 -9
  114. package/dist/hitl/sessionPolicyWire.d.ts +2 -1
  115. package/dist/hitl/sessionPolicyWire.js +23 -24
  116. package/dist/hitl/suspendedReopen.d.ts +2 -1
  117. package/dist/hitl/suspendedReopen.js +7 -10
  118. package/dist/hitl/toolApprovalWire.d.ts +17 -5
  119. package/dist/hitl/toolApprovalWire.js +120 -147
  120. package/dist/hooksWireCaps.js +145 -56
  121. package/dist/host.d.ts +21 -0
  122. package/dist/hostTurnSettings.d.ts +110 -0
  123. package/dist/hostTurnSettings.js +692 -0
  124. package/dist/humanTurn.d.ts +15 -1
  125. package/dist/humanTurn.js +100 -12
  126. package/dist/humanTurnRead.d.ts +2 -0
  127. package/dist/humanTurnRead.js +22 -1
  128. package/dist/i18n/messages.en.d.ts +713 -0
  129. package/dist/i18n/messages.en.js +713 -0
  130. package/dist/i18n/messages.zh.js +854 -1
  131. package/dist/index.d.ts +45 -13
  132. package/dist/index.js +27 -9
  133. package/dist/inheritEnvCapability.d.ts +4 -2
  134. package/dist/inheritEnvCapability.js +12 -5
  135. package/dist/inheritEnvWire.d.ts +3 -2
  136. package/dist/inheritEnvWire.js +14 -16
  137. package/dist/injectionLaneNotice.d.ts +5 -0
  138. package/dist/injectionLaneNotice.js +46 -0
  139. package/dist/interactiveHalt.js +17 -6
  140. package/dist/liveModelCatalog.d.ts +2 -1
  141. package/dist/liveModelCatalog.js +14 -8
  142. package/dist/mcpPanel.d.ts +10 -1
  143. package/dist/mcpPanel.js +42 -13
  144. package/dist/mcpProbeCapability.d.ts +2 -1
  145. package/dist/mcpProbeCapability.js +7 -11
  146. package/dist/mcpProbeWire.d.ts +3 -1
  147. package/dist/mcpProbeWire.js +5 -0
  148. package/dist/mcpReconnect.js +2 -2
  149. package/dist/mcpToolToggles.d.ts +6 -0
  150. package/dist/mcpToolToggles.js +46 -0
  151. package/dist/mcpWireCaps.d.ts +43 -3
  152. package/dist/mcpWireCaps.js +194 -59
  153. package/dist/mcpWireTransport.d.ts +4 -0
  154. package/dist/mcpWireTransport.js +18 -0
  155. package/dist/memoryEntriesWire.js +5 -10
  156. package/dist/model/onboardJudgement.d.ts +93 -0
  157. package/dist/model/onboardJudgement.js +415 -0
  158. package/dist/model/tierVocabulary.d.ts +2 -0
  159. package/dist/model/tierVocabulary.js +17 -5
  160. package/dist/modelCapabilityProbe.d.ts +65 -0
  161. package/dist/modelCapabilityProbe.js +601 -0
  162. package/dist/modelIdentityResolvability.d.ts +5 -0
  163. package/dist/modelIdentityResolvability.js +49 -22
  164. package/dist/ownKey.d.ts +33 -0
  165. package/dist/ownKey.js +109 -0
  166. package/dist/panelReduce.d.ts +11 -1
  167. package/dist/panelReduce.js +95 -16
  168. package/dist/panelStateHolder.d.ts +1 -0
  169. package/dist/panelStateHolder.js +10 -1
  170. package/dist/permissionRuleIssue.d.ts +2 -1
  171. package/dist/permissionRuleIssue.js +23 -20
  172. package/dist/permissionRulesWriteCapability.d.ts +2 -1
  173. package/dist/permissionRulesWriteCapability.js +8 -6
  174. package/dist/pluginHooksWire.d.ts +46 -3
  175. package/dist/pluginHooksWire.js +220 -12
  176. package/dist/prepareRefusal.d.ts +8 -0
  177. package/dist/prepareRefusal.js +72 -0
  178. package/dist/printModelStatus.d.ts +63 -0
  179. package/dist/printModelStatus.js +155 -0
  180. package/dist/request/taskRequest.d.ts +16 -10
  181. package/dist/request/taskRequest.js +195 -58
  182. package/dist/resumeRefusalCopy.d.ts +14 -9
  183. package/dist/resumeRefusalCopy.js +89 -144
  184. package/dist/retryStatus.d.ts +55 -0
  185. package/dist/retryStatus.js +155 -19
  186. package/dist/ruleRefusalSentence.d.ts +4 -0
  187. package/dist/ruleRefusalSentence.js +58 -0
  188. package/dist/sandboxWire.d.ts +2 -1
  189. package/dist/sandboxWire.js +55 -21
  190. package/dist/scenarioRefusal.d.ts +10 -0
  191. package/dist/scenarioRefusal.js +111 -0
  192. package/dist/seam.d.ts +48 -9
  193. package/dist/seam.js +54 -5
  194. package/dist/seatContract.d.ts +272 -14
  195. package/dist/seatContract.js +711 -23
  196. package/dist/selfOrchestrationDenial.js +7 -19
  197. package/dist/sessionIdSegment.d.ts +6 -0
  198. package/dist/sessionIdSegment.js +24 -0
  199. package/dist/sessionMemoryStatus.js +6 -11
  200. package/dist/sessionPolicyCapability.d.ts +2 -1
  201. package/dist/sessionPolicyCapability.js +8 -6
  202. package/dist/settingsCredentialKeyPaths.d.ts +8 -0
  203. package/dist/settingsCredentialKeyPaths.js +219 -0
  204. package/dist/settingsHooksSalvage.d.ts +44 -0
  205. package/dist/settingsHooksSalvage.js +211 -0
  206. package/dist/skillToolListsCapability.d.ts +2 -1
  207. package/dist/skillToolListsCapability.js +8 -6
  208. package/dist/skillsWireCaps.d.ts +0 -3
  209. package/dist/skillsWireCaps.js +1 -2
  210. package/dist/sseIdleTriage.js +3 -2
  211. package/dist/subagent/engineSubagentResume.js +15 -9
  212. package/dist/subagentContentStore.d.ts +4 -0
  213. package/dist/subagentContentStore.js +157 -27
  214. package/dist/toolHistoryMismatch.js +3 -2
  215. package/dist/toolRoster.d.ts +3 -2
  216. package/dist/toolRoster.js +21 -20
  217. package/dist/toolsFlagNames.d.ts +8 -0
  218. package/dist/toolsFlagNames.js +110 -0
  219. package/dist/turnFailurePresentation.d.ts +12 -1
  220. package/dist/turnFailurePresentation.js +220 -15
  221. package/dist/usageAnalytics.js +6 -11
  222. package/dist/userAttachmentEnvelope.d.ts +1 -0
  223. package/dist/userAttachmentEnvelope.js +37 -7
  224. package/dist/userAttachmentSeat.d.ts +21 -0
  225. package/dist/userAttachmentSeat.js +75 -0
  226. package/dist/userInvokedSkillsCapability.d.ts +11 -1
  227. package/dist/userInvokedSkillsCapability.js +31 -7
  228. package/dist/wireErrorTriage.d.ts +7 -0
  229. package/dist/wireErrorTriage.js +23 -1
  230. package/dist/wireFailureShape.js +2 -1
  231. package/dist/wireRefusalCopy.d.ts +62 -16
  232. package/dist/wireRefusalCopy.js +307 -148
  233. package/dist/workflowsJournalCapability.d.ts +2 -1
  234. package/dist/workflowsJournalCapability.js +8 -6
  235. package/docs/INTEGRATION-CLIENTS.md +951 -42
  236. package/package.json +5 -5
@@ -1,18 +1,25 @@
1
1
  import type { SkillSpec } from '@sema-agent/sdk';
2
2
  import type { McpServerSpec } from './mcpWireCaps.js';
3
3
  import type { EnvLike } from './hostEnv.js';
4
+ import type { McpEntryKeyIssue } from './generated/settingsSchemaTypes.js';
4
5
  export type { McpServerSpec };
5
6
  type Rec = Record<string, unknown>;
6
7
  export type { EnvLike };
7
- export type CloudMcpDropReason = 'disabled' | 'missing-field' | 'unknown-transport' | 'capped' | 'principal-and-assertion-header';
8
+ export type CloudMcpDropReason = 'disabled' | 'missing-field' | 'unknown-transport' | 'principal-and-assertion-header' | 'tool-axes-invalid' | 'elicitation-invalid' | 'name-unusable' | 'transport-invalid';
8
9
  export interface CloudMcpDroppedServer {
9
10
  name?: string;
10
11
  reason: CloudMcpDropReason;
12
+ path?: string;
13
+ }
14
+ export interface CloudMcpDegradedServer {
15
+ name: string;
16
+ lost: readonly McpEntryKeyIssue[];
11
17
  }
12
18
  export interface CloudMcpProjection {
13
19
  specs: McpServerSpec[];
14
20
  missingEnv: string[];
15
21
  droppedServers: CloudMcpDroppedServer[];
22
+ degradedServers: CloudMcpDegradedServer[];
16
23
  }
17
24
  export declare function cloudMcpToSpecs(servers: unknown, env: EnvLike): CloudMcpProjection;
18
25
  export declare function cloudSkillsToSpecs(manifestSkills: unknown, resolveBody: (contentHash: string) => string | null): SkillSpec[];
@@ -111,6 +118,7 @@ export interface CloudProjection {
111
118
  scope: string;
112
119
  skillsMissingBody: string[];
113
120
  droppedMcpServers: CloudMcpDroppedServer[];
121
+ degradedMcpServers: CloudMcpDegradedServer[];
114
122
  droppedModels: CloudDroppedModel[];
115
123
  execution: CloudExecutionProjection;
116
124
  effectiveWarnings: CloudEffectiveWarningsReading;
@@ -125,4 +133,5 @@ export interface CloudEffectiveNotice {
125
133
  }
126
134
  export declare function cloudEffectiveNotices(p: Pick<CloudProjection, 'effectiveWarnings' | 'budget' | 'runtimeCaps' | 'modelRefIssues' | 'droppedMcpServers'> & {
127
135
  readonly mcp?: readonly McpServerSpec[];
136
+ readonly degradedMcpServers?: readonly CloudMcpDegradedServer[];
128
137
  }): CloudEffectiveNotice[];
@@ -1,10 +1,14 @@
1
- import { MCP_CAPS, mcpAssertionHeaderNotSentNotice, readMcpHttpIdentityHeaders } from './mcpWireCaps.js';
1
+ import { mcpAssertionHeaderNotSentNotice, mcpElicitationVerdict, mcpToolAxesVerdict, readMcpHttpIdentityHeaders } from './mcpWireCaps.js';
2
2
  import { toCappedSpec } from './skillsWireCaps.js';
3
+ import { SETTINGS_DESCRIBE_BAD_WIRE_NAME, SETTINGS_IS_USABLE_WIRE_NAME, SETTINGS_READ_REQUEST_MCP_TRANSPORT } from './generated/settingsSchemaFns.js';
4
+ import { snapshotArgs, wireTransportOf } from './mcpWireTransport.js';
5
+ import { msg, renderMessage } from './i18n/translate.js';
3
6
  import { TIER_ORDER } from './model/tierVocabulary.js';
4
7
  import { SETTINGS_NARROW_AT_MENTION } from './generated/settingsSchemaFns.js';
5
8
  import { modelsPolicyOf } from './model/modelsPolicy.js';
6
9
  import { normalizeEngineBaseUrl } from './engineUrl.js';
7
10
  import { guardedRead, readOwnDataNonEmptyString, readOwnDataValue } from './ownKey.js';
11
+ import { capForDisplay } from './fleetTaskDesc.js';
8
12
  import { SETTINGS_BUDGET_NUMBER_KEYS, SETTINGS_BUDGET_PER_MODEL_NUMBER_KEYS, SETTINGS_BUDGET_STRING_KEYS, SETTINGS_TIER_GROUP_NAME_RE, } from './generated/settingsSchemaTables.js';
9
13
  const asRec = (v) => (typeof v === 'object' && v !== null && !Array.isArray(v) ? v : undefined);
10
14
  const asArr = (v) => (Array.isArray(v) ? v : []);
@@ -13,16 +17,13 @@ export function cloudMcpToSpecs(servers, env) {
13
17
  const specs = [];
14
18
  const missingEnv = [];
15
19
  const droppedServers = [];
16
- const drop = (name, reason) => {
17
- droppedServers.push({ ...(name ? { name } : {}), reason });
20
+ const degradedServers = [];
21
+ const drop = (name, reason, path) => {
22
+ droppedServers.push({ ...(name ? { name } : {}), reason, ...(path !== undefined ? { path } : {}) });
18
23
  };
19
24
  for (const raw of asArr(servers)) {
20
25
  const s = asRec(raw);
21
26
  const name = s ? asStr(s.name) : undefined;
22
- if (specs.length >= MCP_CAPS.items) {
23
- drop(name, 'capped');
24
- continue;
25
- }
26
27
  if (!s || s.enabled === false) {
27
28
  drop(name, s?.enabled === false ? 'disabled' : 'missing-field');
28
29
  continue;
@@ -32,77 +33,105 @@ export function cloudMcpToSpecs(servers, env) {
32
33
  drop(name, 'missing-field');
33
34
  continue;
34
35
  }
35
- let transport = null;
36
- if (t.kind === 'stdio') {
37
- const command = asStr(t.command);
38
- if (!command) {
39
- drop(name, 'missing-field');
40
- continue;
41
- }
42
- const envOut = {};
43
- for (const [target, ref] of Object.entries(asRec(t.envRefs) ?? {})) {
36
+ if (!SETTINGS_IS_USABLE_WIRE_NAME(name)) {
37
+ drop(name, 'name-unusable');
38
+ continue;
39
+ }
40
+ let candidate;
41
+ let requiredRaw;
42
+ const missingHere = [];
43
+ const resolveRefs = (refs) => {
44
+ const out = [];
45
+ for (const [target, ref] of Object.entries(asRec(refs) ?? {})) {
44
46
  const refName = asStr(ref);
45
47
  if (!refName)
46
48
  continue;
47
49
  const v = env[refName];
48
50
  if (v === undefined || v === '')
49
- missingEnv.push(refName);
51
+ missingHere.push(refName);
50
52
  else
51
- envOut[target] = v;
53
+ out.push([target, v]);
52
54
  }
53
- const args = asArr(t.args).filter((a) => typeof a === 'string');
54
- transport = {
55
- kind: 'stdio',
56
- command,
57
- ...(args.length > 0 ? { args } : {}),
58
- ...(Object.keys(envOut).length > 0 ? { env: envOut } : {}),
59
- };
60
- }
61
- else if (t.kind === 'http') {
62
- const url = asStr(t.url);
63
- if (!url) {
55
+ return out;
56
+ };
57
+ const dropHard = (issue, raw) => {
58
+ const missing = (issue.path === 'transport.command' || issue.path === 'transport.url') && asStr(raw) === undefined;
59
+ if (missing)
64
60
  drop(name, 'missing-field');
65
- continue;
66
- }
67
- const identity = readMcpHttpIdentityHeaders(t);
68
- if (identity.kind === 'both_set') {
69
- drop(name, 'principal-and-assertion-header');
70
- continue;
61
+ else
62
+ drop(name, 'transport-invalid', issue.path);
63
+ };
64
+ try {
65
+ if (t.kind === 'stdio') {
66
+ const command = t.command;
67
+ requiredRaw = command;
68
+ const head = SETTINGS_READ_REQUEST_MCP_TRANSPORT({ kind: 'stdio', command });
69
+ if (!head.ok) {
70
+ dropHard(head.issue, command);
71
+ continue;
72
+ }
73
+ const envEntries = resolveRefs(t.envRefs);
74
+ candidate = { kind: 'stdio', command, args: snapshotArgs(t.args), env: envEntries.length > 0 ? Object.fromEntries(envEntries) : undefined };
71
75
  }
72
- const headers = {};
73
- for (const [headerName, ref] of Object.entries(asRec(t.headerRefs) ?? {})) {
74
- const refName = asStr(ref);
75
- if (!refName)
76
+ else if (t.kind === 'http') {
77
+ const url = t.url;
78
+ requiredRaw = url;
79
+ const head = SETTINGS_READ_REQUEST_MCP_TRANSPORT({ kind: 'http', url });
80
+ if (!head.ok) {
81
+ dropHard(head.issue, url);
76
82
  continue;
77
- const v = env[refName];
78
- if (v === undefined || v === '')
79
- missingEnv.push(refName);
80
- else
81
- headers[headerName] = v;
83
+ }
84
+ const principalHeader = t.principalHeader;
85
+ const assertionHeader = t.assertionHeader;
86
+ if (readMcpHttpIdentityHeaders({ principalHeader, assertionHeader }).kind === 'both_set') {
87
+ drop(name, 'principal-and-assertion-header');
88
+ continue;
89
+ }
90
+ const headerEntries = resolveRefs(t.headerRefs);
91
+ candidate = { kind: 'http', url, headers: headerEntries.length > 0 ? Object.fromEntries(headerEntries) : undefined, principalHeader, assertionHeader };
92
+ }
93
+ else {
94
+ drop(name, 'unknown-transport');
95
+ continue;
82
96
  }
83
- transport = {
84
- kind: 'http',
85
- url,
86
- ...(Object.keys(headers).length > 0 ? { headers } : {}),
87
- ...(identity.principalHeader !== undefined ? { principalHeader: identity.principalHeader } : {}),
88
- ...(identity.assertionHeader !== undefined ? { assertionHeader: identity.assertionHeader } : {}),
89
- };
90
97
  }
91
- else {
92
- drop(name, 'unknown-transport');
98
+ catch {
99
+ drop(name, 'transport-invalid', 'transport');
93
100
  continue;
94
101
  }
102
+ const read = SETTINGS_READ_REQUEST_MCP_TRANSPORT(candidate);
103
+ if (!read.ok) {
104
+ dropHard(read.issue, requiredRaw);
105
+ continue;
106
+ }
107
+ missingEnv.push(...missingHere);
108
+ const transport = wireTransportOf(read.transport);
109
+ const axesDeclared = s.toolAxes;
110
+ const axesVerdict = mcpToolAxesVerdict(axesDeclared);
111
+ if (axesVerdict.kind === 'bad') {
112
+ drop(name, 'tool-axes-invalid');
113
+ continue;
114
+ }
115
+ const axesShipped = axesVerdict.kind === 'ok' ? axesVerdict.toolAxes : axesDeclared;
116
+ const elVerdict = mcpElicitationVerdict(s.elicitation);
117
+ if (elVerdict.kind === 'bad') {
118
+ drop(name, 'elicitation-invalid');
119
+ continue;
120
+ }
121
+ const allowToolsWritten = Array.isArray(s.allowTools);
95
122
  const allowTools = asArr(s.allowTools).filter((a) => typeof a === 'string');
123
+ if (read.lost.length > 0)
124
+ degradedServers.push({ name, lost: Object.freeze([...read.lost]) });
96
125
  specs.push({
97
126
  name,
98
127
  transport,
99
- ...(allowTools.length > 0 ? { allowTools } : {}),
100
- ...(s.elicitation === true ? { elicitation: true } : {}),
128
+ ...(allowToolsWritten ? { allowTools } : {}),
129
+ ...(elVerdict.elicitation !== undefined ? { elicitation: elVerdict.elicitation } : {}),
101
130
  ...(s.toolFaces !== undefined ? { toolFaces: s.toolFaces } : {}),
102
- ...(s.toolAxes !== undefined ? { toolAxes: s.toolAxes } : {}),
131
+ ...(axesShipped !== undefined ? { toolAxes: axesShipped } : {}),
103
132
  });
104
133
  }
105
- return { specs, missingEnv: [...new Set(missingEnv)], droppedServers };
134
+ return { specs, missingEnv: [...new Set(missingEnv)], droppedServers, degradedServers };
106
135
  }
107
136
  export function cloudSkillsToSpecs(manifestSkills, resolveBody) {
108
137
  const specs = [];
@@ -553,7 +582,7 @@ export function projectEffectiveBody(body, skillBodies, env, rostersValue, opts)
553
582
  const config = asRec(b.config) ?? {};
554
583
  const mcpDomain = asRec(config.mcp);
555
584
  const skillsDomain = asRec(config.skills);
556
- const { specs: mcp, missingEnv: mcpMissing, droppedServers: droppedMcpServers } = cloudMcpToSpecs(mcpDomain?.servers, env);
585
+ const { specs: mcp, missingEnv: mcpMissing, droppedServers: droppedMcpServers, degradedServers: degradedMcpServers } = cloudMcpToSpecs(mcpDomain?.servers, env);
557
586
  const manifest = asArr(skillsDomain?.skills);
558
587
  const skills = cloudSkillsToSpecs(manifest, (hash) => skillBodies[hash] ?? null);
559
588
  const skillsMissingBody = manifest
@@ -578,6 +607,7 @@ export function projectEffectiveBody(body, skillBodies, env, rostersValue, opts)
578
607
  scope: asStr(b.scope) ?? 'global',
579
608
  skillsMissingBody,
580
609
  droppedMcpServers,
610
+ degradedMcpServers,
581
611
  droppedModels: entriesRead === undefined ? [] : cloudModelsDropped({ models: entriesRead }),
582
612
  execution: cloudExecutionToPolicy(config.execution),
583
613
  effectiveWarnings: effectiveWarningsOf(b),
@@ -654,9 +684,21 @@ const MCP_DROP_SENTENCES = {
654
684
  level: 'warn',
655
685
  text: (who) => `cloud config: MCP server entries left out because they set both principalHeader and assertionHeader, which name the same identity header — keep only one of the two: ${who}`,
656
686
  },
657
- capped: {
687
+ 'tool-axes-invalid': {
688
+ level: 'warn',
689
+ text: (who) => renderMessage(msg('config.mcp.cloudToolAxesInvalid', { who })),
690
+ },
691
+ 'elicitation-invalid': {
658
692
  level: 'warn',
659
- text: (who) => `cloud config: MCP server entries left out because more than ${MCP_CAPS.items} were served to you and this client passes at most ${MCP_CAPS.items} to the engine: ${who}`,
693
+ text: (who) => renderMessage(msg('config.mcp.cloudElicitationInvalid', { who })),
694
+ },
695
+ 'name-unusable': {
696
+ level: 'warn',
697
+ text: (who) => renderMessage(msg('config.mcp.cloudNameUnusable', { who })),
698
+ },
699
+ 'transport-invalid': {
700
+ level: 'warn',
701
+ text: (who) => renderMessage(msg('config.mcp.cloudTransportInvalid', { who })),
660
702
  },
661
703
  disabled: {
662
704
  level: 'info',
@@ -666,9 +708,9 @@ const MCP_DROP_SENTENCES = {
666
708
  const MCP_DROP_UNRECOGNISED = (who) => `cloud config: MCP server entries left out for a reason this client does not recognise: ${who}`;
667
709
  const MCP_DROP_LIST_UNREADABLE = 'cloud config: the list of MCP server entries left out could not be read by this client — servers missing from the local tool list may have been left out without notice';
668
710
  const MCP_DROP_NAMES_SHOWN = 5;
669
- function mcpDropWho(names, unnamed) {
670
- const distinct = [...new Set(names)];
671
- const parts = distinct.slice(0, MCP_DROP_NAMES_SHOWN).map((n) => `"${n}"`);
711
+ function mcpDropWho(labels, unnamed) {
712
+ const distinct = [...new Set(labels)];
713
+ const parts = distinct.slice(0, MCP_DROP_NAMES_SHOWN);
672
714
  if (distinct.length > MCP_DROP_NAMES_SHOWN)
673
715
  parts.push(`+${distinct.length - MCP_DROP_NAMES_SHOWN} more`);
674
716
  if (unnamed > 0)
@@ -706,6 +748,8 @@ function droppedMcpNotices(carrier) {
706
748
  catch {
707
749
  return listUnreadable;
708
750
  }
751
+ if (typeof count !== 'number' || !Number.isSafeInteger(count) || count < 0)
752
+ return listUnreadable;
709
753
  const known = new Map();
710
754
  const unrecognised = { names: [], unnamed: 0 };
711
755
  for (let i = 0; i < count; i++) {
@@ -716,6 +760,15 @@ function droppedMcpNotices(carrier) {
716
760
  return typeof raw === 'string' && Object.hasOwn(MCP_DROP_SENTENCES, raw) ? raw : undefined;
717
761
  });
718
762
  const name = guarded(() => readOwnDataNonEmptyString(rowObj, 'name'));
763
+ const path = reason === 'transport-invalid' ? guarded(() => readOwnDataNonEmptyString(rowObj, 'path')) : undefined;
764
+ const pathLabel = path !== undefined && /^transport(\.[A-Za-z]{1,32})?$/.test(path) ? ` (${path})` : '';
765
+ const label = name === undefined
766
+ ? undefined
767
+ : reason === 'name-unusable'
768
+ ? SETTINGS_DESCRIBE_BAD_WIRE_NAME(name)
769
+ : reason === 'transport-invalid'
770
+ ? `"${capForDisplay(name, DEGRADED_NAME_SHOWN)}"${pathLabel}`
771
+ : `"${name}"${pathLabel}`;
719
772
  let bucket = unrecognised;
720
773
  if (reason !== undefined) {
721
774
  let b = known.get(reason);
@@ -723,10 +776,10 @@ function droppedMcpNotices(carrier) {
723
776
  known.set(reason, (b = { names: [], unnamed: 0 }));
724
777
  bucket = b;
725
778
  }
726
- if (name === undefined)
779
+ if (label === undefined)
727
780
  bucket.unnamed++;
728
781
  else
729
- bucket.names.push(name);
782
+ bucket.names.push(label);
730
783
  }
731
784
  const out = [];
732
785
  for (const reason of Object.keys(MCP_DROP_SENTENCES)) {
@@ -739,6 +792,68 @@ function droppedMcpNotices(carrier) {
739
792
  }
740
793
  return out;
741
794
  }
795
+ const DEGRADED_LOST_SHOWN = 80;
796
+ const DEGRADED_NAME_SHOWN = 128;
797
+ const LOST_PATH_SHAPE = /^transport(\.[A-Za-z_][A-Za-z0-9_]{0,31}){1,2}$/;
798
+ function degradedLostLabels(rowObj) {
799
+ const lost = readOwnDataValue(rowObj, 'lost');
800
+ const out = [];
801
+ if (!Array.isArray(lost))
802
+ return out;
803
+ const n = guarded(() => lost.length) ?? 0;
804
+ for (let i = 0; i < n; i++) {
805
+ const one = guarded(() => readOwnDataValue(lost, String(i)));
806
+ const issue = typeof one === 'object' && one !== null ? one : undefined;
807
+ const path = guarded(() => readOwnDataNonEmptyString(issue, 'path'));
808
+ if (path === undefined || !LOST_PATH_SHAPE.test(path))
809
+ continue;
810
+ const member = guarded(() => readOwnDataNonEmptyString(issue, 'member'));
811
+ out.push(member !== undefined && !path.endsWith(`.${member}`) ? `${path} (member "${capForDisplay(member, DEGRADED_LOST_SHOWN)}")` : path);
812
+ }
813
+ return [...new Set(out)];
814
+ }
815
+ function degradedMcpNotices(carrier) {
816
+ const unreadable = [{ level: 'warn', text: renderMessage(msg('config.mcp.cloudTransportDegradedUnreadable')) }];
817
+ let desc;
818
+ try {
819
+ desc = Object.getOwnPropertyDescriptor(carrier, 'degradedMcpServers');
820
+ }
821
+ catch {
822
+ return unreadable;
823
+ }
824
+ if (desc === undefined)
825
+ return [];
826
+ if (!Object.hasOwn(desc, 'value'))
827
+ return unreadable;
828
+ const rows = desc.value;
829
+ let count = 0;
830
+ try {
831
+ if (!Array.isArray(rows))
832
+ return unreadable;
833
+ count = rows.length;
834
+ }
835
+ catch {
836
+ return unreadable;
837
+ }
838
+ if (typeof count !== 'number' || !Number.isSafeInteger(count) || count < 0)
839
+ return unreadable;
840
+ const labels = [];
841
+ let unnamed = 0;
842
+ for (let i = 0; i < count; i++) {
843
+ const row = guarded(() => readOwnDataValue(rows, String(i)));
844
+ const rowObj = typeof row === 'object' && row !== null ? row : undefined;
845
+ const name = guarded(() => readOwnDataNonEmptyString(rowObj, 'name'));
846
+ if (name === undefined) {
847
+ unnamed++;
848
+ continue;
849
+ }
850
+ const paths = guarded(() => degradedLostLabels(rowObj)) ?? [];
851
+ labels.push(`"${capForDisplay(name, DEGRADED_NAME_SHOWN)}"${paths.length > 0 ? ` (${paths.join(', ')})` : ''}`);
852
+ }
853
+ if (labels.length + unnamed === 0)
854
+ return [];
855
+ return [{ level: 'warn', text: renderMessage(msg('config.mcp.cloudTransportDegraded', { who: mcpDropWho(labels, unnamed) })) }];
856
+ }
742
857
  function budgetNotice(r) {
743
858
  switch (r.kind) {
744
859
  case 'configured': {
@@ -807,6 +922,7 @@ export function cloudEffectiveNotices(p) {
807
922
  });
808
923
  }
809
924
  out.push(...droppedMcpNotices(p));
925
+ out.push(...degradedMcpNotices(p));
810
926
  const assertionLine = mcpAssertionHeaderNotSentNotice(guarded(() => readOwnDataValue(p, 'mcp')) ?? []);
811
927
  if (assertionLine !== undefined)
812
928
  out.push({ level: 'warn', text: `cloud config: ${assertionLine}` });
@@ -0,0 +1,34 @@
1
+ export interface CompactionStatusReading {
2
+ readonly compacting: boolean;
3
+ readonly since?: number;
4
+ }
5
+ export type CompactionStatusChange = {
6
+ readonly kind: 'opened';
7
+ readonly pass: string;
8
+ readonly since?: number;
9
+ } | {
10
+ readonly kind: 'closed';
11
+ readonly pass: string;
12
+ readonly result?: 'success' | 'failed';
13
+ readonly error?: string;
14
+ };
15
+ export interface CompactionStatusTracker {
16
+ take(input: {} | null | undefined): CompactionStatusChange | null;
17
+ streamEnded(): CompactionStatusChange | null;
18
+ reading(): CompactionStatusReading;
19
+ }
20
+ export interface PrintCompactionStatusFrame {
21
+ readonly type: 'system';
22
+ readonly subtype: 'status';
23
+ readonly status: 'compacting' | null;
24
+ readonly compact_result?: 'success' | 'failed';
25
+ readonly compact_error?: string;
26
+ readonly uuid: string;
27
+ readonly session_id: string;
28
+ }
29
+ export interface PrintCompactionStatusCtx {
30
+ readonly sessionId: string;
31
+ readonly mintUuid: () => string;
32
+ }
33
+ export declare function createCompactionStatusTracker(): CompactionStatusTracker;
34
+ export declare function compactionStatusFrameOf(change: CompactionStatusChange | null | undefined, ctx: PrintCompactionStatusCtx): PrintCompactionStatusFrame | null;
@@ -0,0 +1,196 @@
1
+ import { readOwnDataValue } from './ownKey.js';
2
+ import { snapshotIsSubFlow, snapshotSegmentIdentity } from './adapter/types.js';
3
+ const _printStatusFramePins = [true, true];
4
+ void _printStatusFramePins;
5
+ const CLOSED_PASS_MEMORY = 1024;
6
+ const nonEmpty = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
7
+ const own = (o, key) => (typeof o === 'object' && o !== null ? readOwnDataValue(o, key) : undefined);
8
+ function chromeLane(ev) {
9
+ const lane = own(own(ev, 'laneProof'), 'lane');
10
+ if (typeof lane !== 'string' || lane.length === 0)
11
+ return 'unreadable';
12
+ return lane === 'main' ? 'main' : 'other';
13
+ }
14
+ function armLane(m) {
15
+ const snap = snapshotSegmentIdentity(m);
16
+ if (snap === null)
17
+ return 'unreadable';
18
+ return snapshotIsSubFlow(snap) ? 'other' : 'main';
19
+ }
20
+ function openOf(pass, lane, startedAt, trigger) {
21
+ if (lane === 'unreadable')
22
+ return null;
23
+ if (nonEmpty(trigger) === undefined)
24
+ return null;
25
+ return { kind: 'open', pass, main: lane === 'main', ...(typeof startedAt === 'number' && Number.isFinite(startedAt) ? { startedAt } : {}) };
26
+ }
27
+ function parse(input) {
28
+ const plane = own(input, 'plane');
29
+ if (plane === 'chrome') {
30
+ const ev = own(input, 'event');
31
+ return typeof ev === 'object' && ev !== null ? parseChrome(ev) : null;
32
+ }
33
+ if (plane === 'transcript') {
34
+ const msg = own(input, 'message');
35
+ return typeof msg === 'object' && msg !== null ? parseMessage(msg) : null;
36
+ }
37
+ if (own(input, 'kind') !== undefined)
38
+ return parseChrome(input);
39
+ return parseMessage(input);
40
+ }
41
+ function parseChrome(ev) {
42
+ const kind = own(ev, 'kind');
43
+ const pass = nonEmpty(own(ev, 'pass'));
44
+ if (pass === undefined)
45
+ return null;
46
+ if (kind === 'compaction_started')
47
+ return openOf(pass, chromeLane(ev), own(ev, 'startedAt'), own(ev, 'trigger'));
48
+ if (kind === 'compaction_outcome') {
49
+ const outcome = nonEmpty(own(ev, 'outcome'));
50
+ const reason = nonEmpty(own(ev, 'reason'));
51
+ return { kind: 'close-outcome', pass, ...(outcome !== undefined ? { outcome } : {}), ...(reason !== undefined ? { reason } : {}) };
52
+ }
53
+ return null;
54
+ }
55
+ function parseMessage(m) {
56
+ const type = own(m, 'type');
57
+ if (type === 'system') {
58
+ if (own(m, 'subtype') !== 'compact_boundary')
59
+ return null;
60
+ const pass = nonEmpty(own(own(m, 'compact_metadata'), '_sema_pass'));
61
+ return pass === undefined ? null : { kind: 'close-landed', pass };
62
+ }
63
+ const pass = nonEmpty(own(m, 'pass'));
64
+ if (pass === undefined)
65
+ return null;
66
+ if (type === 'compaction_started')
67
+ return openOf(pass, armLane(m), own(m, 'startedAt'), own(m, 'trigger'));
68
+ if (type === 'compaction_outcome') {
69
+ const outcome = nonEmpty(own(m, 'outcome'));
70
+ const reason = nonEmpty(own(m, 'reason'));
71
+ return { kind: 'close-outcome', pass, ...(outcome !== undefined ? { outcome } : {}), ...(reason !== undefined ? { reason } : {}) };
72
+ }
73
+ return null;
74
+ }
75
+ export function createCompactionStatusTracker() {
76
+ const open = new Map();
77
+ const closed = new Set();
78
+ const remember = (pass) => {
79
+ closed.add(pass);
80
+ if (closed.size > CLOSED_PASS_MEMORY) {
81
+ const oldest = closed.values().next().value;
82
+ if (oldest !== undefined)
83
+ closed.delete(oldest);
84
+ }
85
+ };
86
+ const mainOpen = () => {
87
+ let n = 0;
88
+ for (const e of open.values())
89
+ if (e.main)
90
+ n++;
91
+ return n;
92
+ };
93
+ const since = () => {
94
+ let min;
95
+ for (const e of open.values())
96
+ if (e.main && e.startedAt !== undefined && (min === undefined || e.startedAt < min))
97
+ min = e.startedAt;
98
+ return min;
99
+ };
100
+ const reading = () => {
101
+ if (mainOpen() === 0)
102
+ return { compacting: false };
103
+ const s = since();
104
+ return { compacting: true, ...(s !== undefined ? { since: s } : {}) };
105
+ };
106
+ return {
107
+ take(input) {
108
+ try {
109
+ if (typeof input !== 'object' || input === null)
110
+ return null;
111
+ const p = parse(input);
112
+ if (p === null)
113
+ return null;
114
+ if (p.kind === 'open') {
115
+ if (open.has(p.pass) || closed.has(p.pass))
116
+ return null;
117
+ const before = mainOpen();
118
+ open.set(p.pass, { main: p.main === true, ...(p.startedAt !== undefined ? { startedAt: p.startedAt } : {}) });
119
+ if (before === 0 && p.main === true) {
120
+ const s = since();
121
+ return { kind: 'opened', pass: p.pass, ...(s !== undefined ? { since: s } : {}) };
122
+ }
123
+ return null;
124
+ }
125
+ const entry = open.get(p.pass);
126
+ remember(p.pass);
127
+ if (entry === undefined)
128
+ return null;
129
+ open.delete(p.pass);
130
+ if (!entry.main || mainOpen() > 0)
131
+ return null;
132
+ if (p.kind === 'close-landed')
133
+ return { kind: 'closed', pass: p.pass, result: 'success' };
134
+ if (p.outcome === 'failed')
135
+ return { kind: 'closed', pass: p.pass, result: 'failed', ...(p.reason !== undefined ? { error: p.reason } : {}) };
136
+ return { kind: 'closed', pass: p.pass };
137
+ }
138
+ catch {
139
+ return null;
140
+ }
141
+ },
142
+ streamEnded() {
143
+ try {
144
+ let lastMain;
145
+ for (const [pass, e] of open) {
146
+ if (e.main)
147
+ lastMain = pass;
148
+ remember(pass);
149
+ }
150
+ const wasCompacting = lastMain !== undefined;
151
+ open.clear();
152
+ return wasCompacting ? { kind: 'closed', pass: lastMain } : null;
153
+ }
154
+ catch {
155
+ return null;
156
+ }
157
+ },
158
+ reading() {
159
+ try {
160
+ return reading();
161
+ }
162
+ catch {
163
+ return { compacting: false };
164
+ }
165
+ },
166
+ };
167
+ }
168
+ export function compactionStatusFrameOf(change, ctx) {
169
+ try {
170
+ if (typeof change !== 'object' || change === null)
171
+ return null;
172
+ const sessionId = nonEmpty(own(ctx, 'sessionId'));
173
+ const mintUuid = own(ctx, 'mintUuid');
174
+ if (sessionId === undefined || typeof mintUuid !== 'function')
175
+ return null;
176
+ const kind = own(change, 'kind');
177
+ if (kind === 'opened')
178
+ return { type: 'system', subtype: 'status', status: 'compacting', uuid: String(mintUuid()), session_id: sessionId };
179
+ if (kind !== 'closed')
180
+ return null;
181
+ const result = own(change, 'result');
182
+ const error = result === 'failed' ? nonEmpty(own(change, 'error')) : undefined;
183
+ return {
184
+ type: 'system',
185
+ subtype: 'status',
186
+ status: null,
187
+ ...(result === 'success' || result === 'failed' ? { compact_result: result } : {}),
188
+ ...(error !== undefined ? { compact_error: error } : {}),
189
+ uuid: String(mintUuid()),
190
+ session_id: sessionId,
191
+ };
192
+ }
193
+ catch {
194
+ return null;
195
+ }
196
+ }
@@ -1,6 +1,7 @@
1
1
  import type { TaskRequest, RunReceipt, CancelAck, Scenario, SteerPriority, AssistantTaskStatus } from '@sema-agent/sdk';
2
2
  import { type SteerPriorityReading } from './steerPriorityCapability.js';
3
3
  import { type PreemptOutcome } from './preemptWire.js';
4
+ import type { UiLanguage } from './env/uiLanguage.js';
4
5
  export interface RunsResourceLike {
5
6
  create(req: TaskRequest, opts?: {
6
7
  idempotencyKey?: string | null;
@@ -75,6 +76,7 @@ export interface ErrCodes {
75
76
  status?: number | undefined;
76
77
  }
77
78
  export declare function errCodes(e: unknown): ErrCodes;
79
+ export type SteerHostQueueFact = 'queued_until_turn_end' | 'dropped' | 'unknown';
78
80
  export declare function steeringStatusIs4xx(e: object): boolean;
79
81
  export interface SteerRefusalAdvice {
80
82
  safety: ControlSafetyCode;
@@ -83,8 +85,8 @@ export interface SteerRefusalAdvice {
83
85
  nextStep: string;
84
86
  }
85
87
  export type SteeringRefusedBeforeEngine = SteerRefusalAdvice;
86
- export declare function steeringRefusedBeforeEngine(e: object): SteeringRefusedBeforeEngine | undefined;
87
- export declare function steerRefusalAdviceOf(e: object): SteerRefusalAdvice | undefined;
88
+ export declare function steeringRefusedBeforeEngine(e: object, hostQueue?: SteerHostQueueFact, lang?: UiLanguage): SteeringRefusedBeforeEngine | undefined;
89
+ export declare function steerRefusalAdviceOf(e: object, hostQueue?: SteerHostQueueFact, lang?: UiLanguage): SteerRefusalAdvice | undefined;
88
90
  export interface SteerBody {
89
91
  readonly text: string;
90
92
  readonly mode?: 'all' | 'one-at-a-time';