@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,6 +1,7 @@
1
1
  import type { McpProbeFace, McpServerSpec } from '@sema-agent/sdk';
2
2
  import { type WiringManifestMcpEntryView } from './adapter/downstream/eventToSdkMessage.js';
3
3
  import { type McpProbeReading } from './mcpProbeCapability.js';
4
+ import { type ScenarioRefusalReading } from './scenarioRefusal.js';
4
5
  export interface McpProbeFacade {
5
6
  mcpCapabilities(opts?: {
6
7
  signal?: AbortSignal;
@@ -9,7 +10,7 @@ export interface McpProbeFacade {
9
10
  signal?: AbortSignal;
10
11
  }): Promise<McpProbeFace>;
11
12
  }
12
- export declare const MCP_PROBE_REFUSAL_CAUSES: readonly ["face_absent", "client_too_old", "unreadable_request", "injection_not_honored", "body_shape", "field_invalid", "body_unparseable", "payload_too_large", "rate_limited", "unauthorized", "principal_required", "principal_unverified"];
13
+ export declare const MCP_PROBE_REFUSAL_CAUSES: readonly ["face_absent", "client_too_old", "unreadable_request", "injection_not_honored", "body_shape", "field_invalid", "body_unparseable", "payload_too_large", "rate_limited", "unauthorized", "principal_required", "principal_unverified", "scenario_refused"];
13
14
  export type McpProbeRefusalCause = (typeof MCP_PROBE_REFUSAL_CAUSES)[number];
14
15
  export declare const MCP_PROBE_UNKNOWN_WHYS: readonly ["no_verdict", "probe_incomplete", "server_fault", "result_unreadable", "index_misaligned", "unclassified"];
15
16
  export type McpProbeUnknownWhy = (typeof MCP_PROBE_UNKNOWN_WHYS)[number];
@@ -18,6 +19,7 @@ export type McpProbeRefused = {
18
19
  cause: McpProbeRefusalCause;
19
20
  message: string;
20
21
  retryAfterSec?: number;
22
+ scenarioRefusal?: ScenarioRefusalReading;
21
23
  };
22
24
  export type McpProbeUnknown = {
23
25
  status: 'unknown';
@@ -1,6 +1,7 @@
1
1
  import { projectMcpSection } from './adapter/downstream/eventToSdkMessage.js';
2
2
  import { wireFailureShapeOf } from './wireFailureShape.js';
3
3
  import { mcpProbeAvailable } from './mcpProbeCapability.js';
4
+ import { scenarioRefusalFromError } from './scenarioRefusal.js';
4
5
  export const MCP_PROBE_REFUSAL_CAUSES = Object.freeze([
5
6
  'face_absent',
6
7
  'client_too_old',
@@ -14,6 +15,7 @@ export const MCP_PROBE_REFUSAL_CAUSES = Object.freeze([
14
15
  'unauthorized',
15
16
  'principal_required',
16
17
  'principal_unverified',
18
+ 'scenario_refused',
17
19
  ]);
18
20
  export const MCP_PROBE_UNKNOWN_WHYS = Object.freeze([
19
21
  'no_verdict',
@@ -168,6 +170,9 @@ export async function readMcpCapabilities(facade, call, opts) {
168
170
  res = await facade.mcpCapabilities(opts);
169
171
  }
170
172
  catch (e) {
173
+ const refusal = scenarioRefusalFromError(e);
174
+ if (refusal !== null)
175
+ return { ...refusedBy('scenario_refused', wireFailureShapeOf(e).message), scenarioRefusal: refusal };
171
176
  return classifyMcpProbeFailure(e);
172
177
  }
173
178
  const narrowed = narrowProbeFace(res);
@@ -1,4 +1,5 @@
1
1
  import type { McpServerSpec } from '@sema-agent/sdk';
2
+ import type { UiLanguage } from './env/uiLanguage.js';
2
3
  export type { McpServerSpec };
3
4
  export declare const MCP_CAPS: {
4
5
  readonly items: 32;
@@ -13,6 +14,7 @@ export interface McpConfigLike {
13
14
  principalHeader?: string;
14
15
  assertionHeader?: string;
15
16
  allowTools?: string[];
17
+ elicitation?: {} | null | undefined;
16
18
  toolFaces?: unknown;
17
19
  toolAxes?: unknown;
18
20
  }
@@ -26,4 +28,36 @@ export type McpHttpIdentityHeaders = {
26
28
  export declare function readMcpHttpIdentityHeaders(transport: object): McpHttpIdentityHeaders;
27
29
  export declare function mcpConfigToSpec(name: string, c: McpConfigLike): McpServerSpec | null;
28
30
  export declare function mcpConfigsToSpecs(servers: Record<string, McpConfigLike> | undefined): McpServerSpec[];
31
+ export type McpToolAxesVerdict = {
32
+ readonly kind: 'ok';
33
+ readonly toolAxes?: Readonly<Record<string, object>>;
34
+ } | {
35
+ readonly kind: 'bad';
36
+ readonly problem: string;
37
+ } | {
38
+ readonly kind: 'unavailable';
39
+ };
40
+ export declare function mcpToolAxesVerdict(declared: {} | null | undefined): McpToolAxesVerdict;
41
+ export declare function mcpElicitationVerdict(declared: {} | null | undefined): {
42
+ readonly kind: 'ok';
43
+ readonly elicitation?: boolean;
44
+ } | {
45
+ readonly kind: 'bad';
46
+ };
47
+ export type McpConfigDropReason = 'name_blank' | 'name_edge_whitespace' | 'name_collides_after_trim' | 'tool_axes_invalid' | 'elicitation_invalid';
48
+ export interface McpConfigDropped {
49
+ readonly name: string;
50
+ readonly reason: McpConfigDropReason;
51
+ readonly problem?: string;
52
+ readonly notice: string;
53
+ }
54
+ export interface McpConfigProjection {
55
+ readonly specs: McpServerSpec[];
56
+ readonly dropped: readonly McpConfigDropped[];
57
+ }
58
+ export interface ProjectMcpConfigsOptions {
59
+ readonly sourceLabel?: (serverName: string) => string | undefined;
60
+ readonly lang?: UiLanguage;
61
+ }
62
+ export declare function projectMcpConfigs(servers: Record<string, McpConfigLike> | undefined, opts?: ProjectMcpConfigsOptions): McpConfigProjection;
29
63
  export declare function mcpAssertionHeaderNotSentNotice(specs: readonly McpServerSpec[]): string | undefined;
@@ -1,11 +1,15 @@
1
1
  import { guardedRead } from './ownKey.js';
2
+ import { readMcpToolAxes } from './coreValuePorts.js';
3
+ import { capForDisplay } from './fleetTaskDesc.js';
4
+ import { msg, renderMessage } from './i18n/translate.js';
2
5
  const _mcpServerSpecPin = true;
3
6
  void _mcpServerSpecPin;
4
7
  export const MCP_CAPS = { items: 32 };
5
- function transparentKeys(c) {
8
+ function transparentKeys(c, axes, elicitation) {
6
9
  return {
7
10
  ...(c.toolFaces !== undefined ? { toolFaces: c.toolFaces } : {}),
8
- ...(c.toolAxes !== undefined ? { toolAxes: c.toolAxes } : {}),
11
+ ...(axes !== undefined ? { toolAxes: axes } : {}),
12
+ ...(elicitation !== undefined ? { elicitation } : {}),
9
13
  };
10
14
  }
11
15
  function presentHeaderName(v) {
@@ -24,9 +28,24 @@ export function readMcpHttpIdentityHeaders(transport) {
24
28
  };
25
29
  }
26
30
  export function mcpConfigToSpec(name, c) {
27
- const n = (name ?? '').trim();
28
- if (!n)
29
- return null;
31
+ return mcpConfigEntry(name, c).spec;
32
+ }
33
+ function mcpConfigEntry(name, c) {
34
+ if (mcpNameFlaw(name) !== undefined)
35
+ return { spec: null };
36
+ const declared = c.toolAxes;
37
+ const verdict = mcpToolAxesVerdict(declared);
38
+ const elDeclared = c.elicitation;
39
+ const elVerdict = mcpElicitationVerdict(elDeclared);
40
+ if (verdict.kind === 'bad' || elVerdict.kind === 'bad') {
41
+ const rest = specOf(name, c, undefined, undefined);
42
+ if (rest === null)
43
+ return { spec: null };
44
+ return verdict.kind === 'bad' ? { spec: null, axesProblem: verdict.problem } : { spec: null, elicitationInvalid: true };
45
+ }
46
+ return { spec: specOf(name, c, verdict.kind === 'ok' ? verdict.toolAxes : declared, elVerdict.elicitation) };
47
+ }
48
+ function specOf(n, c, axes, elicitation) {
30
49
  const kind = c.type ?? 'stdio';
31
50
  if (kind === 'stdio') {
32
51
  if (!c.command)
@@ -39,8 +58,8 @@ export function mcpConfigToSpec(name, c) {
39
58
  ...(c.args && c.args.length > 0 ? { args: c.args } : {}),
40
59
  ...(c.env ? { env: c.env } : {}),
41
60
  },
42
- ...(c.allowTools && c.allowTools.length > 0 ? { allowTools: c.allowTools } : {}),
43
- ...transparentKeys(c),
61
+ ...(Array.isArray(c.allowTools) ? { allowTools: c.allowTools } : {}),
62
+ ...transparentKeys(c, axes, elicitation),
44
63
  };
45
64
  }
46
65
  if (kind === 'http') {
@@ -58,22 +77,103 @@ export function mcpConfigToSpec(name, c) {
58
77
  ...(id.principalHeader !== undefined ? { principalHeader: id.principalHeader } : {}),
59
78
  ...(id.assertionHeader !== undefined ? { assertionHeader: id.assertionHeader } : {}),
60
79
  },
61
- ...(c.allowTools && c.allowTools.length > 0 ? { allowTools: c.allowTools } : {}),
62
- ...transparentKeys(c),
80
+ ...(Array.isArray(c.allowTools) ? { allowTools: c.allowTools } : {}),
81
+ ...transparentKeys(c, axes, elicitation),
63
82
  };
64
83
  }
65
84
  return null;
66
85
  }
67
86
  export function mcpConfigsToSpecs(servers) {
68
- const out = [];
69
- for (const [name, c] of Object.entries(servers ?? {})) {
70
- if (out.length >= MCP_CAPS.items)
87
+ return projectMcpConfigs(servers).specs;
88
+ }
89
+ export function mcpToolAxesVerdict(declared) {
90
+ if (declared === undefined)
91
+ return Object.freeze({ kind: 'ok' });
92
+ const read = readMcpToolAxes(declared);
93
+ if (read === undefined || read === null || typeof read !== 'object')
94
+ return Object.freeze({ kind: 'unavailable' });
95
+ if (read.ok === true) {
96
+ const copy = read.toolAxes;
97
+ return Object.freeze(typeof copy === 'object' && copy !== null ? { kind: 'ok', toolAxes: copy } : { kind: 'ok' });
98
+ }
99
+ if (read.ok === false) {
100
+ const problem = read.problem;
101
+ return Object.freeze({ kind: 'bad', problem: typeof problem === 'string' && problem.length > 0 ? problem : renderMessage(msg('config.mcp.toolAxesFallbackProblem')) });
102
+ }
103
+ return Object.freeze({ kind: 'unavailable' });
104
+ }
105
+ export function mcpElicitationVerdict(declared) {
106
+ if (declared === undefined)
107
+ return Object.freeze({ kind: 'ok' });
108
+ return typeof declared === 'boolean' ? Object.freeze({ kind: 'ok', elicitation: declared }) : Object.freeze({ kind: 'bad' });
109
+ }
110
+ function mcpNameFlaw(name) {
111
+ if (typeof name !== 'string')
112
+ return 'name_blank';
113
+ const t = name.trim();
114
+ if (t.length === 0)
115
+ return 'name_blank';
116
+ return t === name ? undefined : 'name_edge_whitespace';
117
+ }
118
+ const DROP_NAME_SHOWN = 80;
119
+ const DROP_LABEL_SHOWN = 140;
120
+ const DROP_PROBLEM_SHOWN = 300;
121
+ function dropNotice(name, reason, problem, opts) {
122
+ let label;
123
+ try {
124
+ label = opts?.sourceLabel?.(name);
125
+ }
126
+ catch {
127
+ label = undefined;
128
+ }
129
+ const where = typeof label === 'string' && label.length > 0 ? ` (${capForDisplay(label, DROP_LABEL_SHOWN)})` : '';
130
+ const quoted = `"${capForDisplay(name, DROP_NAME_SHOWN)}"`;
131
+ const ref = reason === 'tool_axes_invalid'
132
+ ? msg('config.mcp.toolAxesInvalid', { name: quoted, where, problem: capForDisplay(problem ?? renderMessage(msg('config.mcp.toolAxesFallbackProblem')), DROP_PROBLEM_SHOWN) })
133
+ : reason === 'elicitation_invalid'
134
+ ? msg('config.mcp.elicitationInvalid', { name: quoted, where })
135
+ : reason === 'name_blank'
136
+ ? msg('config.mcp.nameBlank', { name: quoted, where })
137
+ : reason === 'name_collides_after_trim'
138
+ ? msg('config.mcp.nameCollides', { name: quoted, where })
139
+ : msg('config.mcp.nameEdgeWhitespace', { name: quoted, where });
140
+ return renderMessage(ref, opts?.lang);
141
+ }
142
+ export function projectMcpConfigs(servers, opts) {
143
+ const specs = [];
144
+ const dropped = [];
145
+ const entries = Object.entries(servers ?? {});
146
+ const exactNames = new Set();
147
+ const trimmedCount = new Map();
148
+ for (const [name] of entries) {
149
+ const flaw = mcpNameFlaw(name);
150
+ if (flaw === undefined)
151
+ exactNames.add(name);
152
+ else if (flaw === 'name_edge_whitespace')
153
+ trimmedCount.set(name.trim(), (trimmedCount.get(name.trim()) ?? 0) + 1);
154
+ }
155
+ for (const [name, c] of entries) {
156
+ if (specs.length >= MCP_CAPS.items)
71
157
  break;
72
- const spec = mcpConfigToSpec(name, c);
73
- if (spec)
74
- out.push(spec);
158
+ const flaw = mcpNameFlaw(name);
159
+ if (flaw !== undefined) {
160
+ const reason = flaw === 'name_edge_whitespace' && (exactNames.has(name.trim()) || (trimmedCount.get(name.trim()) ?? 0) > 1) ? 'name_collides_after_trim' : flaw;
161
+ dropped.push({ name, reason, notice: dropNotice(name, reason, undefined, opts) });
162
+ continue;
163
+ }
164
+ const out = mcpConfigEntry(name, c);
165
+ if (out.spec !== null) {
166
+ specs.push(out.spec);
167
+ continue;
168
+ }
169
+ if (out.axesProblem !== undefined) {
170
+ dropped.push({ name, reason: 'tool_axes_invalid', problem: out.axesProblem, notice: dropNotice(name, 'tool_axes_invalid', out.axesProblem, opts) });
171
+ }
172
+ else if (out.elicitationInvalid === true) {
173
+ dropped.push({ name, reason: 'elicitation_invalid', notice: dropNotice(name, 'elicitation_invalid', undefined, opts) });
174
+ }
75
175
  }
76
- return out;
176
+ return { specs, dropped: Object.freeze(dropped) };
77
177
  }
78
178
  function assertionDeclaringServerName(spec) {
79
179
  const t = spec?.transport;
@@ -97,6 +197,6 @@ export function mcpAssertionHeaderNotSentNotice(specs) {
97
197
  const parts = distinct.slice(0, ASSERTION_NOTICE_NAMES_SHOWN).map((x) => `"${x}"`);
98
198
  if (distinct.length > ASSERTION_NOTICE_NAMES_SHOWN)
99
199
  parts.push(`+${distinct.length - ASSERTION_NOTICE_NAMES_SHOWN} more`);
100
- return (`MCP servers that declare an assertion header (assertionHeader): ${parts.join(', ')} — server versions up to 7.129.1 accept this setting but do not send the header, ` +
200
+ return (`MCP servers that declare an assertion header (assertionHeader): ${parts.join(', ')} — server versions up to 7.131.0 accept this setting but do not send the header, ` +
101
201
  'and this client cannot tell whether the engine it uses sends it; a connector that requires the header will refuse requests from these servers');
102
202
  }
@@ -1,3 +1,4 @@
1
+ import { readThrownSlot, THROWN_SLOT_UNREADABLE } from './wireFailureShape.js';
1
2
  function nonEmptyString(v) {
2
3
  return typeof v === 'string' && v !== '';
3
4
  }
@@ -216,16 +217,10 @@ export function readMemoryEraseReceipt(body) {
216
217
  return { kind: 'malformed', why: 'body_unreadable' };
217
218
  o = body;
218
219
  envelopeSeen = ['v', 'requestId', 'status', 'erased', 'notFound'].some((k) => Object.hasOwn(o, k));
219
- rawV = Object.hasOwn(o, 'v') ? o.v : undefined;
220
- rawRequestId = o.requestId;
221
- rawStatus = o.status;
222
- rawEvidence = o.evidenceCapability;
223
- rawCustody = o.custodyState;
224
- rawSelected = o.resolvedIds;
225
- rawErased = o.erased;
226
- rawNotFound = o.notFound;
227
- rawPreviously = Object.hasOwn(o, 'erasedPreviously') ? o.erasedPreviously : undefined;
228
- rawConflicts = o.conflicts;
220
+ const slots = ['v', 'requestId', 'status', 'evidenceCapability', 'custodyState', 'resolvedIds', 'erased', 'notFound', 'erasedPreviously', 'conflicts'].map((k) => readThrownSlot(o, k, 'data'));
221
+ if (slots.includes(THROWN_SLOT_UNREADABLE))
222
+ return { kind: 'malformed', why: 'body_unreadable' };
223
+ [rawV, rawRequestId, rawStatus, rawEvidence, rawCustody, rawSelected, rawErased, rawNotFound, rawPreviously, rawConflicts] = slots;
229
224
  }
230
225
  catch {
231
226
  return { kind: 'malformed', why: 'body_unreadable' };
@@ -0,0 +1,93 @@
1
+ import type { ModelApiWord } from './providerPresets.js';
2
+ import type { OnboardCatalogIssue, OnboardProbeResult, OnboardProbeVerdict, OnboardRefusal } from '../seatContract.js';
3
+ import { type ModelProbeResult } from '../modelCapabilityProbe.js';
4
+ import type { UiLanguage } from '../env/uiLanguage.js';
5
+ export declare function onboardBaseUrlProblem(url: string, lang?: UiLanguage): string | undefined;
6
+ export interface OnboardProbeTarget {
7
+ readonly baseUrl: string;
8
+ readonly api: ModelApiWord;
9
+ readonly modelId?: string | undefined;
10
+ readonly apiKey?: string | undefined;
11
+ readonly auth?: 'bearer' | 'x-api-key' | undefined;
12
+ }
13
+ export interface OnboardProbeRequestInit {
14
+ method?: string;
15
+ headers: Record<string, string>;
16
+ body?: string;
17
+ redirect: 'manual';
18
+ signal: AbortSignal;
19
+ }
20
+ export interface OnboardProbeBodyReader {
21
+ read(): Promise<{
22
+ readonly done: boolean;
23
+ readonly value?: Uint8Array | undefined;
24
+ }>;
25
+ cancel(): Promise<void>;
26
+ }
27
+ export interface OnboardProbeResponse {
28
+ readonly status: number;
29
+ readonly ok: boolean;
30
+ readonly headers: {
31
+ get(name: string): string | null;
32
+ };
33
+ readonly body?: {
34
+ getReader(): OnboardProbeBodyReader;
35
+ } | null | undefined;
36
+ text(): Promise<string>;
37
+ }
38
+ export type OnboardProbeFetch = (url: string, init: OnboardProbeRequestInit) => Promise<OnboardProbeResponse>;
39
+ export interface OnboardProbeDeps {
40
+ readonly fetchImpl?: OnboardProbeFetch | undefined;
41
+ readonly timeoutMs?: number | undefined;
42
+ readonly firstTokenMs?: number | undefined;
43
+ }
44
+ export declare function probeModelEndpoint(target: OnboardProbeTarget, deps?: OnboardProbeDeps): Promise<OnboardProbeResult>;
45
+ export type OnboardWriteVerdict = {
46
+ readonly write: true;
47
+ readonly unverified: boolean;
48
+ } | {
49
+ readonly write: false;
50
+ readonly refusal: 'probe_failed' | 'probe_unverified';
51
+ };
52
+ export declare function onboardWriteVerdict(verdict: OnboardProbeVerdict, acceptUnverified?: boolean): OnboardWriteVerdict;
53
+ export declare function keyEnvNameForEntry(entryName: string): string;
54
+ export declare function poolEntryNameOf(modelId: string, channel: string, taken: ReadonlySet<string>): string;
55
+ export interface OnboardPlanEntry {
56
+ readonly modelId: string;
57
+ readonly api: ModelApiWord;
58
+ readonly baseUrl: string;
59
+ readonly apiKey: string;
60
+ readonly providerName: string;
61
+ readonly contextWindow: number;
62
+ readonly maxTokens: number;
63
+ readonly channel: string;
64
+ }
65
+ export interface OnboardJsonObject {
66
+ readonly [key: string]: {} | null;
67
+ }
68
+ export interface OnboardWritePlanInput {
69
+ readonly modelsDoc: OnboardJsonObject | undefined;
70
+ readonly settingsEnv: OnboardJsonObject | undefined;
71
+ readonly effectiveEnv: Readonly<Record<string, string | undefined>>;
72
+ readonly entry: OnboardPlanEntry;
73
+ readonly probe: OnboardProbeResult;
74
+ readonly makeDefault: boolean;
75
+ readonly now: number;
76
+ readonly thinking?: ModelProbeResult | undefined;
77
+ readonly engineMode?: 'local' | 'cloud' | undefined;
78
+ }
79
+ export type OnboardWritePlan = {
80
+ readonly ok: true;
81
+ readonly entryName: string;
82
+ readonly keyEnv: string;
83
+ readonly updatedExisting: boolean;
84
+ readonly nextModelsDoc: OnboardJsonObject;
85
+ readonly nextSettingsEnv: OnboardJsonObject;
86
+ readonly otherIssues: readonly OnboardCatalogIssue[];
87
+ } | {
88
+ readonly ok: false;
89
+ readonly refusal: Extract<OnboardRefusal, 'input' | 'catalog_unreadable' | 'credential_unpaired' | 'engine_is_remote' | 'env_catalog_present'>;
90
+ readonly detail: string;
91
+ };
92
+ export declare function onboardWritePlan(input: OnboardWritePlanInput): OnboardWritePlan;
93
+ export declare function onboardRefusalText(refusal: OnboardRefusal, lang?: UiLanguage): string;