@migor/agentia 0.10.1 → 0.10.3
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.
- package/CHANGELOG.md +917 -34
- package/README.en.md +6 -4
- package/README.md +4 -3
- package/dist/AGENTS.md +106 -33
- package/dist/core/limits.d.ts +33 -1
- package/dist/core/limits.js +37 -1
- package/dist/core/limits.js.map +1 -1
- package/dist/core/run.d.ts +2 -2
- package/dist/core/timeout.d.ts +5 -5
- package/dist/core/timeout.js +5 -5
- package/dist/core/tool.d.ts +2 -2
- package/dist/core/trace.d.ts +10 -1
- package/dist/core/trace.js +10 -1
- package/dist/core/trace.js.map +1 -1
- package/dist/engine/concurrency.d.ts +1 -1
- package/dist/engine/concurrency.js +1 -1
- package/dist/engine/errors.d.ts +2 -2
- package/dist/engine/errors.js +2 -2
- package/dist/engine/loop-result.d.ts +2 -2
- package/dist/engine/loop.js +91 -56
- package/dist/engine/loop.js.map +1 -1
- package/dist/engine/mcp-server-http.js +69 -36
- package/dist/engine/mcp-server-http.js.map +1 -1
- package/dist/engine/mcp-server-stdio.d.ts +0 -13
- package/dist/engine/mcp-server-stdio.js +42 -25
- package/dist/engine/mcp-server-stdio.js.map +1 -1
- package/dist/engine/mcp-server.d.ts +15 -0
- package/dist/engine/mcp-server.js +39 -8
- package/dist/engine/mcp-server.js.map +1 -1
- package/dist/engine/resume-input.d.ts +1 -1
- package/dist/engine/resume-input.js +1 -1
- package/dist/engine/retry.d.ts +15 -0
- package/dist/engine/retry.js +51 -2
- package/dist/engine/retry.js.map +1 -1
- package/dist/engine/span-scope.d.ts +15 -0
- package/dist/engine/span-scope.js +8 -1
- package/dist/engine/span-scope.js.map +1 -1
- package/dist/engine/spec.d.ts +5 -1
- package/dist/engine/spec.js.map +1 -1
- package/dist/engine/tracer.d.ts +8 -4
- package/dist/engine/tracer.js +24 -17
- package/dist/engine/tracer.js.map +1 -1
- package/dist/engine/turn.d.ts +2 -2
- package/dist/engine/turn.js +19 -4
- package/dist/engine/turn.js.map +1 -1
- package/dist/engine/types.d.ts +8 -3
- package/dist/eval/export.js +2 -2
- package/dist/eval/export.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/integrations/anthropic.d.ts +1 -1
- package/dist/integrations/anthropic.js +1 -1
- package/dist/integrations/anthropic.js.map +1 -1
- package/dist/integrations/file-sink.d.ts +2 -2
- package/dist/integrations/file-sink.js +2 -2
- package/dist/integrations/mcp-http.js +15 -88
- package/dist/integrations/mcp-http.js.map +1 -1
- package/dist/integrations/mcp-protocol.d.ts +86 -10
- package/dist/integrations/mcp-protocol.js +147 -1
- package/dist/integrations/mcp-protocol.js.map +1 -1
- package/dist/integrations/mcp-stdio.js +87 -52
- package/dist/integrations/mcp-stdio.js.map +1 -1
- package/dist/integrations/mcp.d.ts +1 -1
- package/dist/integrations/mcp.js +19 -3
- package/dist/integrations/mcp.js.map +1 -1
- package/dist/integrations/metrics-otlp.d.ts +1 -1
- package/dist/integrations/metrics-otlp.js +8 -2
- package/dist/integrations/metrics-otlp.js.map +1 -1
- package/dist/integrations/metrics-render.js +1 -1
- package/dist/integrations/metrics-render.js.map +1 -1
- package/dist/integrations/metrics-state.d.ts +2 -2
- package/dist/integrations/metrics-state.js +4 -4
- package/dist/integrations/metrics-state.js.map +1 -1
- package/dist/integrations/metrics.d.ts +2 -2
- package/dist/integrations/openai.d.ts +4 -1
- package/dist/integrations/openai.js +25 -6
- package/dist/integrations/openai.js.map +1 -1
- package/dist/integrations/otlp.d.ts +29 -6
- package/dist/integrations/otlp.js +128 -7
- package/dist/integrations/otlp.js.map +1 -1
- package/dist/integrations/report.d.ts +14 -2
- package/dist/integrations/report.js +39 -6
- package/dist/integrations/report.js.map +1 -1
- package/dist/runtime/memory.d.ts +5 -0
- package/dist/runtime/memory.js.map +1 -1
- package/dist/store/fsStore.js +9 -5
- package/dist/store/fsStore.js.map +1 -1
- package/dist/store/record.d.ts +2 -2
- package/dist/store/record.js +1 -1
- package/dist/store/sqliteStore.d.ts +2 -2
- package/dist/store/sqliteStore.js +3 -3
- package/dist/store/sqliteStore.js.map +1 -1
- package/dist/store/store.d.ts +32 -6
- package/dist/store/store.js +36 -5
- package/dist/store/store.js.map +1 -1
- package/dist/toolkit/collect.d.ts +11 -5
- package/dist/toolkit/collect.js +10 -4
- package/dist/toolkit/collect.js.map +1 -1
- package/dist/toolkit/module.js +78 -1
- package/dist/toolkit/module.js.map +1 -1
- package/dist/toolkit/prompt.d.ts +1 -1
- package/dist/toolkit/prompt.js +2 -2
- package/dist/toolkit/prompt.js.map +1 -1
- package/dist/toolkit/subagent.js +17 -3
- package/dist/toolkit/subagent.js.map +1 -1
- package/dist/transport/approval-policy.js +1 -1
- package/dist/transport/approval-policy.js.map +1 -1
- package/dist/transport/approval-supervisor.d.ts +8 -0
- package/dist/transport/approval-supervisor.js +23 -3
- package/dist/transport/approval-supervisor.js.map +1 -1
- package/dist/transport/async.d.ts +5 -4
- package/dist/transport/async.js +166 -145
- package/dist/transport/async.js.map +1 -1
- package/dist/transport/http-endpoints.js +1 -1
- package/dist/transport/http-route.js +2 -2
- package/dist/transport/http-route.js.map +1 -1
- package/dist/transport/http-shapes.d.ts +1 -1
- package/dist/transport/http-shapes.js +1 -1
- package/dist/transport/resume-scanner.d.ts +7 -0
- package/dist/transport/resume-scanner.js +40 -9
- package/dist/transport/resume-scanner.js.map +1 -1
- package/dist/transport/run-call-options.d.ts +77 -0
- package/dist/transport/run-call-options.js +76 -0
- package/dist/transport/run-call-options.js.map +1 -0
- package/dist/transport/run-outcome.d.ts +109 -0
- package/dist/transport/run-outcome.js +100 -0
- package/dist/transport/run-outcome.js.map +1 -0
- package/dist/transport/scheduler.js +5 -0
- package/dist/transport/scheduler.js.map +1 -1
- package/dist/transport/signal-supervisor.d.ts +10 -2
- package/dist/transport/signal-supervisor.js +15 -2
- package/dist/transport/signal-supervisor.js.map +1 -1
- package/dist/transport/wake-policy.d.ts +1 -1
- package/package.json +2 -2
|
@@ -3,8 +3,8 @@ import { dirname } from 'node:path';
|
|
|
3
3
|
/**
|
|
4
4
|
* Agentia —— JSONL 文件 sink:一行一条**裸 Trace** 追加落盘。
|
|
5
5
|
*
|
|
6
|
-
* 这是 CLI
|
|
7
|
-
*
|
|
6
|
+
* 这是 CLI 四件套 `agentia report` / `agentia diff` / `agentia harvest` / `agentia export`
|
|
7
|
+
* 的**输入格式**(每行一个 JSON,裸 Trace)—— 消费侧早就吃这个文件,产出侧此前要用户手写
|
|
8
8
|
* `appendFileSync` 的 sink,这里把它收进框架。
|
|
9
9
|
*
|
|
10
10
|
* 语义:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_CLIENT_INFO, DEFAULT_PROTOCOL_VERSION, MCP_DEFAULT_TIMEOUT_MS,
|
|
1
|
+
import { DEFAULT_CLIENT_INFO, DEFAULT_PROTOCOL_VERSION, MCP_DEFAULT_TIMEOUT_MS, assertToolResultNotError, canSelfHealSession, mcpHttpError, parseToolList, readMcpResult, readMcpText, toolsCallParams, withDeadline, } from './mcp-protocol.js';
|
|
2
2
|
/**
|
|
3
3
|
* **StreamableHTTP 连接器**:一个 endpoint,POST JSON-RPC(MCP 2025-03-26 起的
|
|
4
4
|
* Streamable HTTP 传输)。
|
|
@@ -36,20 +36,6 @@ export function createStreamableHttpMcpConnector(url, opts = {}) {
|
|
|
36
36
|
let reinit = null;
|
|
37
37
|
let nextId = 1;
|
|
38
38
|
const guard = (p, label) => withDeadline(p, timeoutMs, label);
|
|
39
|
-
/** HTTP 层失败:带上数值 `status`,让 `classifyError` 能按状态分流 */
|
|
40
|
-
const httpError = (status, method, body) => {
|
|
41
|
-
const e = new Error(`MCP ${method} HTTP ${status}${body ? `:${body}` : ''}`);
|
|
42
|
-
e.status = status;
|
|
43
|
-
return e;
|
|
44
|
-
};
|
|
45
|
-
const readText = async (res) => {
|
|
46
|
-
try {
|
|
47
|
-
return await res.text();
|
|
48
|
-
}
|
|
49
|
-
catch {
|
|
50
|
-
return '';
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
39
|
const post = async (payload, o = {}) => {
|
|
54
40
|
if (closed)
|
|
55
41
|
throw new Error('MCP 连接器已 close —— 请重新创建一个');
|
|
@@ -73,55 +59,6 @@ export function createStreamableHttpMcpConnector(url, opts = {}) {
|
|
|
73
59
|
sessionId = sid;
|
|
74
60
|
return res;
|
|
75
61
|
};
|
|
76
|
-
/** 非 SSE 报文(单条 JSON-RPC)→ 取 result;SSE 里可能有别的通知帧,只取与 `id` 配对的 */
|
|
77
|
-
const pickResult = (msg, id, method) => {
|
|
78
|
-
// id 必须**等值**配对(与 SSE 分支同款):只验「是带 id 的响应」会把别的请求的
|
|
79
|
-
// 结果当本次的返回(代理串包/通知帧),静默错值比报错难查得多。
|
|
80
|
-
if (!isJsonRpcResponse(msg) || msg.id !== id) {
|
|
81
|
-
throw new Error(`MCP ${method}:响应里没有 id 为 ${id} 的 JSON-RPC 报文`);
|
|
82
|
-
}
|
|
83
|
-
return unwrap(msg, method);
|
|
84
|
-
};
|
|
85
|
-
/**
|
|
86
|
-
* 从响应取结果。SSE 分支一次性读完整个 body 再解析 —— StreamableHTTP 约定 server 发完
|
|
87
|
-
* 响应即关流,读全比手写增量解析器稳(`text/event-stream` 里 `data:` 行按规范可跨多行拼接)。
|
|
88
|
-
*/
|
|
89
|
-
const readResult = async (res, id, method) => {
|
|
90
|
-
const ct = (res.headers.get('content-type') ?? '').toLowerCase();
|
|
91
|
-
const text = await readText(res);
|
|
92
|
-
if (ct.includes('text/event-stream')) {
|
|
93
|
-
for (const frame of text.split(/\r?\n\r?\n/)) {
|
|
94
|
-
const data = frame
|
|
95
|
-
.split(/\r?\n/)
|
|
96
|
-
.filter((l) => l.startsWith('data:'))
|
|
97
|
-
.map((l) => l.slice(5).trim())
|
|
98
|
-
.join('');
|
|
99
|
-
if (data === '')
|
|
100
|
-
continue;
|
|
101
|
-
let msg;
|
|
102
|
-
try {
|
|
103
|
-
msg = JSON.parse(data);
|
|
104
|
-
}
|
|
105
|
-
catch {
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
if (isJsonRpcResponse(msg) && msg.id === id)
|
|
109
|
-
return unwrap(msg, method);
|
|
110
|
-
}
|
|
111
|
-
throw new Error(`MCP ${method}:SSE 响应里没有 id 为 ${id} 的报文`);
|
|
112
|
-
}
|
|
113
|
-
if (text.trim() === '') {
|
|
114
|
-
throw new Error(`MCP ${method}:响应体为空(期望 id 为 ${id} 的 JSON-RPC 报文)`);
|
|
115
|
-
}
|
|
116
|
-
let msg;
|
|
117
|
-
try {
|
|
118
|
-
msg = JSON.parse(text);
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
throw new Error(`MCP ${method}:响应不是合法 JSON:${brief(text)}`);
|
|
122
|
-
}
|
|
123
|
-
return pickResult(msg, id, method);
|
|
124
|
-
};
|
|
125
62
|
/**
|
|
126
63
|
* 会话过期自愈的互斥:并发请求同时吃到 404 时**共享同一次重握手**。
|
|
127
64
|
* 没有这层时,两个并发调用各自执行 `ready = null`(第二个会把第一个刚建的握手
|
|
@@ -154,20 +91,20 @@ export function createStreamableHttpMcpConnector(url, opts = {}) {
|
|
|
154
91
|
const rpc = async (method, params, withVersion, allowReinit = true, abandoned) => {
|
|
155
92
|
const id = nextId++;
|
|
156
93
|
const res = await post({ jsonrpc: '2.0', id, method, params }, { withVersion, ...(abandoned !== undefined ? { signal: abandoned } : {}) });
|
|
157
|
-
if (res.status
|
|
158
|
-
await
|
|
94
|
+
if (canSelfHealSession(res.status, sessionId !== null, allowReinit)) {
|
|
95
|
+
await readMcpText(res); // 排空,别把连接晾着
|
|
159
96
|
opts.onSessionExpired?.();
|
|
160
97
|
await reinitialize();
|
|
161
98
|
// 自愈重试那次同样带上 abandoned —— 裁判放弃时两条在飞 fetch 都要被掐
|
|
162
99
|
return rpc(method, params, withVersion, false, abandoned);
|
|
163
100
|
}
|
|
164
101
|
if (!res.ok)
|
|
165
|
-
throw
|
|
102
|
+
throw mcpHttpError(res.status, method, await readMcpText(res));
|
|
166
103
|
// 计时裁判权在调用方(initialize / notifications / tools/list 都在调用点自带
|
|
167
104
|
// guard —— 它们是装配期路径、没有别的裁判);`tools/call` 不在此起计时器:
|
|
168
|
-
// 它的裁判是引擎的 `toolTimeoutMs`(spec §10 2026-09-17
|
|
105
|
+
// 它的裁判是引擎的 `toolTimeoutMs`(spec §10 2026-09-17 ref-mcp-timeout-single-source 超时单源化)——
|
|
169
106
|
// 再包一层 guard 就是双计时器,同一事件两本账(stdio 侧就没有这层)。
|
|
170
|
-
return
|
|
107
|
+
return readMcpResult(res, id, method);
|
|
171
108
|
};
|
|
172
109
|
const ensureReady = () => {
|
|
173
110
|
if (ready)
|
|
@@ -181,33 +118,23 @@ export function createStreamableHttpMcpConnector(url, opts = {}) {
|
|
|
181
118
|
}
|
|
182
119
|
const res = await guard(post({ jsonrpc: '2.0', method: 'notifications/initialized', params: {} }, { withVersion: true }), 'notifications/initialized');
|
|
183
120
|
if (!res.ok) {
|
|
184
|
-
throw
|
|
121
|
+
throw mcpHttpError(res.status, 'notifications/initialized', await readMcpText(res));
|
|
185
122
|
}
|
|
186
|
-
await
|
|
123
|
+
await readMcpText(res); // 排空:202 + 空体是合法应答,但别把连接晾着
|
|
187
124
|
})();
|
|
188
125
|
return ready;
|
|
189
126
|
};
|
|
190
127
|
const listTools = async () => {
|
|
191
128
|
await ensureReady();
|
|
192
129
|
const r = await guard(rpc('tools/list', {}, true), 'tools/list');
|
|
193
|
-
|
|
194
|
-
throw new Error(`MCP tools/list 返回了非对象:${brief(r)}`);
|
|
195
|
-
}
|
|
196
|
-
const listed = r.tools;
|
|
197
|
-
if (listed === undefined)
|
|
198
|
-
return [];
|
|
199
|
-
if (!Array.isArray(listed)) {
|
|
200
|
-
throw new Error(`MCP tools/list 的 tools 不是数组:${brief(listed)}`);
|
|
201
|
-
}
|
|
202
|
-
return listed;
|
|
130
|
+
return parseToolList(r);
|
|
203
131
|
};
|
|
204
132
|
const callTool = async (name, args, callOpts) => {
|
|
205
133
|
await ensureReady();
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
134
|
+
// `toolsCallParams` 把 SEP-414 的 traceparent 放进 params._meta(裸键);没有则不留 _meta 键
|
|
135
|
+
const r = await rpc('tools/call', toolsCallParams(name, args, callOpts?.traceparent), true, true, callOpts?.abandoned);
|
|
136
|
+
// 承重同 stdio:协议层 isError 只有连接器看得见(判定与文案在 mcp-protocol.ts)
|
|
137
|
+
assertToolResultNotError(r, name);
|
|
211
138
|
return r;
|
|
212
139
|
};
|
|
213
140
|
return {
|
|
@@ -228,7 +155,7 @@ export function createStreamableHttpMcpConnector(url, opts = {}) {
|
|
|
228
155
|
// **抛错**,兜不住**挂死** —— server 接受连接后不回(半开 / 卡在代理后面),
|
|
229
156
|
// `close()` 就永久挂住,而调用方(宿主停机路径)会一直等它。**挂住比失败更糟**,
|
|
230
157
|
// 与「best-effort、不抛错」的承诺相悖。fetch 与排空**一起**进 guard:
|
|
231
|
-
// 只护住响应头、body 照样能卡(`
|
|
158
|
+
// 只护住响应头、body 照样能卡(`readMcpText` 读的是 body)。
|
|
232
159
|
await guard((async () => {
|
|
233
160
|
const res = await fetchImpl(url, {
|
|
234
161
|
method: 'DELETE',
|
|
@@ -238,7 +165,7 @@ export function createStreamableHttpMcpConnector(url, opts = {}) {
|
|
|
238
165
|
'mcp-protocol-version': negotiated,
|
|
239
166
|
},
|
|
240
167
|
});
|
|
241
|
-
await
|
|
168
|
+
await readMcpText(res);
|
|
242
169
|
})(), 'close');
|
|
243
170
|
}
|
|
244
171
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-http.js","sourceRoot":"","sources":["../../src/integrations/mcp-http.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,sBAAsB,EACtB,
|
|
1
|
+
{"version":3,"file":"mcp-http.js","sourceRoot":"","sources":["../../src/integrations/mcp-http.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,6 +26,26 @@ export interface McpToolInfo {
|
|
|
26
26
|
/** MCP 协议里已是 JSON Schema → 直接当框架的 `inputSchema` 用 */
|
|
27
27
|
inputSchema?: unknown;
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* `callTool` 的第三参(桥与两个连接器**共用**这一份 —— 2026-10-12 SEP-414 起多了
|
|
31
|
+
* `traceparent`,形状只许有一处定义)。
|
|
32
|
+
*/
|
|
33
|
+
export interface McpCallOptions {
|
|
34
|
+
/**
|
|
35
|
+
* 裁判(引擎 `toolTimeoutMs` / 桥兜底超时)**放弃等待**的通知信号。
|
|
36
|
+
* 放弃 ≠ 取消 —— 但连接器应借此清掉这次调用的簿记(stdio 的 pending 条目、
|
|
37
|
+
* HTTP 的在飞 fetch),否则「server 活着但不回包」时每超时一次就泄漏一条。
|
|
38
|
+
*/
|
|
39
|
+
abandoned?: AbortSignal;
|
|
40
|
+
/**
|
|
41
|
+
* 出站传播(SEP-414,Final):本次调用的 W3C `traceparent`,连接器把它放进
|
|
42
|
+
* `params._meta.traceparent`(**裸键,不加前缀**;与 `name` / `arguments` 平级,
|
|
43
|
+
* **绝不进 `arguments`** —— 那是模型可见的工具签名,trace 上下文进去就污染 schema)。
|
|
44
|
+
* 缺席时 params **不落 `_meta` 键**:「没有上下文可传」与「传一个空上下文」不是一回事。
|
|
45
|
+
* 不认识该字段的旧客户端忽略即可(可选参数,鸭子类型)。
|
|
46
|
+
*/
|
|
47
|
+
traceparent?: string;
|
|
48
|
+
}
|
|
29
49
|
/**
|
|
30
50
|
* MCP client 的最小结构面:任何实现了 `tools/list` + `tools/call` 的客户端都能接,
|
|
31
51
|
* 无需继承、无需 import 任何 SDK(duck-typed,与 `RedisLike` 同款)。
|
|
@@ -36,15 +56,8 @@ export interface McpToolInfo {
|
|
|
36
56
|
*/
|
|
37
57
|
export interface McpClientLike {
|
|
38
58
|
listTools(): Promise<McpToolInfo[]>;
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
* 放弃 ≠ 取消 —— 但连接器应借此清掉这次调用的簿记(stdio 的 pending 条目、
|
|
42
|
-
* HTTP 的在飞 fetch),否则「server 活着但不回包」时每超时一次就泄漏一条。
|
|
43
|
-
* 只实现两个参数的旧客户端依然兼容(可选参数,鸭子类型)。
|
|
44
|
-
*/
|
|
45
|
-
callTool(name: string, args: Record<string, unknown>, opts?: {
|
|
46
|
-
abandoned?: AbortSignal;
|
|
47
|
-
}): Promise<unknown>;
|
|
59
|
+
/** 选项见 {@link McpCallOptions};只实现两个参数的旧客户端依然兼容(可选参数,鸭子类型)。 */
|
|
60
|
+
callTool(name: string, args: Record<string, unknown>, opts?: McpCallOptions): Promise<unknown>;
|
|
48
61
|
}
|
|
49
62
|
/**
|
|
50
63
|
* 连接器公共面:`McpClientLike` + 一个关闭句柄(两个内置连接器都返回它)。
|
|
@@ -90,7 +103,7 @@ export declare const DEFAULT_PROTOCOL_VERSION = "2024-11-05";
|
|
|
90
103
|
* 给一次 MCP 调用套超时。⚠️ 与引擎的工具超时同样是**放弃等待**而非取消 ——
|
|
91
104
|
* MCP 的 `notifications/cancelled` 属于连接器职责,桥这一层拿不到取消句柄。
|
|
92
105
|
*
|
|
93
|
-
* 实现是 `core/timeout.ts` 共享原语的**薄封装**(2026-09-17 单源化,见 spec §10 2026-09-17
|
|
106
|
+
* 实现是 `core/timeout.ts` 共享原语的**薄封装**(2026-09-17 单源化,见 spec §10 2026-09-17 ref-mcp-timeout-single-source):
|
|
94
107
|
* 「一次调用只有一个预算判定」在引擎与桥之间只允许有一份实现。此前桥自带一份**纯竞速**
|
|
95
108
|
* 版本,于是 2026-09-14 的「超时是硬的」收紧只落进引擎,桥继续把**超预算**的调用记成成功。
|
|
96
109
|
*
|
|
@@ -113,3 +126,66 @@ export declare function unwrap(msg: {
|
|
|
113
126
|
result?: unknown;
|
|
114
127
|
error?: unknown;
|
|
115
128
|
}, method: string): unknown;
|
|
129
|
+
/**
|
|
130
|
+
* 读响应体文本;读失败**返回空串而非抛**。
|
|
131
|
+
*
|
|
132
|
+
* 为什么吞:调用方用它的地方(排空、错误文案、SSE 解析)都不该因为「body 读不出来」二次失败
|
|
133
|
+
* —— 真正的原因由 `res.status` / 网络层给出,这里再抛只会把第一条错误盖掉。
|
|
134
|
+
*/
|
|
135
|
+
export declare function readMcpText(res: Response): Promise<string>;
|
|
136
|
+
/** HTTP 层失败:带上数值 `status`,让 `classifyError` 能按状态分流 */
|
|
137
|
+
export declare function mcpHttpError(status: number, method: string, body: string): Error;
|
|
138
|
+
/**
|
|
139
|
+
* 非 SSE 报文(单条 JSON-RPC)→ 取 result。
|
|
140
|
+
*
|
|
141
|
+
* ⚠️ id 必须**等值**配对(与 SSE 分支同款):只验「是带 id 的响应」会把别的请求的结果
|
|
142
|
+
* 当本次的返回(代理串包 / 通知帧),**静默错值比报错难查得多**。
|
|
143
|
+
*/
|
|
144
|
+
export declare function pickJsonRpcResult(msg: unknown, id: number, method: string): unknown;
|
|
145
|
+
/**
|
|
146
|
+
* 从 HTTP 响应取结果 —— 两种响应形态**都要接**(StreamableHTTP 的规范面)。
|
|
147
|
+
*
|
|
148
|
+
* SSE 分支一次性读完整个 body 再解析:StreamableHTTP 约定 server 发完响应即关流,
|
|
149
|
+
* 读全比手写增量解析器稳(`text/event-stream` 里 `data:` 行按规范可跨多行拼接)。
|
|
150
|
+
* SSE 里可能有别的通知帧或别的请求的应答,**只取与 `id` 配对的**那一条。
|
|
151
|
+
*/
|
|
152
|
+
export declare function readMcpResult(res: Response, id: number, method: string): Promise<unknown>;
|
|
153
|
+
/**
|
|
154
|
+
* `tools/list` 的应答 → 工具表。**两条连接器共用一份**(此前逐字写了两遍)。
|
|
155
|
+
*
|
|
156
|
+
* 形状不对一律**响亮失败**:把协议不符吞成空菜单,用户看到的是「这个 server 一个工具都没有」
|
|
157
|
+
* 而不是「server 坏了」—— 前者会被当成正常结果排错到别处去。只有 `tools` **缺席**才当空表
|
|
158
|
+
* (那是合法的「没有工具」)。
|
|
159
|
+
*/
|
|
160
|
+
export declare function parseToolList(r: unknown): McpToolInfo[];
|
|
161
|
+
/**
|
|
162
|
+
* `tools/call` 的结果里协议层 `isError: true` ⇒ **必须转成抛错**。
|
|
163
|
+
*
|
|
164
|
+
* 承重:这个位只有连接器看得见,吞了它模型会收到一条「成功」的结果、trace 也记成成功调用
|
|
165
|
+
* (见 `McpClientLike` 的约定)。两条连接器共用一份。
|
|
166
|
+
*/
|
|
167
|
+
export declare function assertToolResultNotError(r: unknown, name: string): void;
|
|
168
|
+
/**
|
|
169
|
+
* **会话过期自愈**的判定(MCP Streamable HTTP 的规范语义)。
|
|
170
|
+
*
|
|
171
|
+
* 带会话 id 收到 `404` 的含义是「这个会话我不认识」⇒ **该请求没有被执行** ⇒ 丢会话、
|
|
172
|
+
* 重新握手、把这一次**重试一次**是安全的(不会重复执行副作用);规范也要求客户端此时
|
|
173
|
+
* **必须**新建会话。`allowReinit` 那一位保证**只重试一次**:第二次再 404 说明对面不是
|
|
174
|
+
* 「会话过期」而是别的问题,直接抛(不循环)。
|
|
175
|
+
*
|
|
176
|
+
* 抽成纯函数是为了让这三条判据**可以被单独钉住** —— 它此前内联在 `rpc` 的 `if` 里,
|
|
177
|
+
* 三个条件任意一个写反都没有用例看得见(症状是「重试带着旧会话再 404」或「无限重握」)。
|
|
178
|
+
*/
|
|
179
|
+
export declare function canSelfHealSession(status: number, hasSessionId: boolean, allowReinit: boolean): boolean;
|
|
180
|
+
/**
|
|
181
|
+
* 拼 `tools/call` 的 params(**两条连接器共用一份** —— 承载 SEP-414 的 `_meta` 形状
|
|
182
|
+
* 只许存在一处,否则改一处漏一处没有任何用例看得见)。
|
|
183
|
+
*
|
|
184
|
+
* `traceparent`(W3C 串)落在 params 的**兄弟键 `_meta`**:SEP-414 明说这是 `_meta`
|
|
185
|
+
* DNS 前缀惯例的**例外**(裸键 `traceparent`,不许加成 `io.modelcontextprotocol.traceparent`
|
|
186
|
+
* —— 加了前缀跨实现的链就断了)。⚠️ **绝不进 `arguments`**:那是模型可见、server 按
|
|
187
|
+
* inputSchema 校验的工具签名,trace 上下文进去会污染契约(纪律②)。
|
|
188
|
+
* `traceparent` 缺席时**不落 `_meta` 键**(纪律③:不造空上下文 —— 空 `_meta` 对宽容的
|
|
189
|
+
* server 无害,但它让「这次到底有没有链路」变得不可判)。
|
|
190
|
+
*/
|
|
191
|
+
export declare function toolsCallParams(name: string, args: Record<string, unknown>, traceparent: string | undefined): Record<string, unknown>;
|
|
@@ -18,7 +18,7 @@ export const DEFAULT_PROTOCOL_VERSION = '2024-11-05';
|
|
|
18
18
|
* 给一次 MCP 调用套超时。⚠️ 与引擎的工具超时同样是**放弃等待**而非取消 ——
|
|
19
19
|
* MCP 的 `notifications/cancelled` 属于连接器职责,桥这一层拿不到取消句柄。
|
|
20
20
|
*
|
|
21
|
-
* 实现是 `core/timeout.ts` 共享原语的**薄封装**(2026-09-17 单源化,见 spec §10 2026-09-17
|
|
21
|
+
* 实现是 `core/timeout.ts` 共享原语的**薄封装**(2026-09-17 单源化,见 spec §10 2026-09-17 ref-mcp-timeout-single-source):
|
|
22
22
|
* 「一次调用只有一个预算判定」在引擎与桥之间只允许有一份实现。此前桥自带一份**纯竞速**
|
|
23
23
|
* 版本,于是 2026-09-14 的「超时是硬的」收紧只落进引擎,桥继续把**超预算**的调用记成成功。
|
|
24
24
|
*
|
|
@@ -66,4 +66,150 @@ export function unwrap(msg, method) {
|
|
|
66
66
|
throw new Error(`MCP ${method}:响应里既没有 result 也没有 error`);
|
|
67
67
|
return msg.result;
|
|
68
68
|
}
|
|
69
|
+
// ───────────────────────── 下面这一组:两个内置连接器**共用**的纯件(2026-10-11 抽) ─────────────────────────
|
|
70
|
+
//
|
|
71
|
+
// 为什么抽在这里:它们此前**逐字重复**在两个连接器里(`tools/list` 与 `tools/call` 的结果校验
|
|
72
|
+
// 一字不差地写了两遍),或者只属于协议面的知识(SSE 帧 / JSON-RPC 信封 / id 配对)——
|
|
73
|
+
// 正是本文件头注那句「新增『桥与连接器都要用』的东西请加在这里」。
|
|
74
|
+
//
|
|
75
|
+
// ⚠️ 抽出去的另一半效果是**读数**:`integrations/mcp-http.ts` 与 `mcp-stdio.ts` 的
|
|
76
|
+
// 「最大可调用体」因此从 265 / 252 降下来(见 `tests/architecture/method-size.test.ts`)。
|
|
77
|
+
// 那不是目的、是副作用 —— 目的是这两条连接器从此只有「各自传输那一份」的代码。
|
|
78
|
+
/**
|
|
79
|
+
* 读响应体文本;读失败**返回空串而非抛**。
|
|
80
|
+
*
|
|
81
|
+
* 为什么吞:调用方用它的地方(排空、错误文案、SSE 解析)都不该因为「body 读不出来」二次失败
|
|
82
|
+
* —— 真正的原因由 `res.status` / 网络层给出,这里再抛只会把第一条错误盖掉。
|
|
83
|
+
*/
|
|
84
|
+
export async function readMcpText(res) {
|
|
85
|
+
try {
|
|
86
|
+
return await res.text();
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return '';
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** HTTP 层失败:带上数值 `status`,让 `classifyError` 能按状态分流 */
|
|
93
|
+
export function mcpHttpError(status, method, body) {
|
|
94
|
+
const e = new Error(`MCP ${method} HTTP ${status}${body ? `:${body}` : ''}`);
|
|
95
|
+
e.status = status;
|
|
96
|
+
return e;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 非 SSE 报文(单条 JSON-RPC)→ 取 result。
|
|
100
|
+
*
|
|
101
|
+
* ⚠️ id 必须**等值**配对(与 SSE 分支同款):只验「是带 id 的响应」会把别的请求的结果
|
|
102
|
+
* 当本次的返回(代理串包 / 通知帧),**静默错值比报错难查得多**。
|
|
103
|
+
*/
|
|
104
|
+
export function pickJsonRpcResult(msg, id, method) {
|
|
105
|
+
if (!isJsonRpcResponse(msg) || msg.id !== id) {
|
|
106
|
+
throw new Error(`MCP ${method}:响应里没有 id 为 ${id} 的 JSON-RPC 报文`);
|
|
107
|
+
}
|
|
108
|
+
return unwrap(msg, method);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* 从 HTTP 响应取结果 —— 两种响应形态**都要接**(StreamableHTTP 的规范面)。
|
|
112
|
+
*
|
|
113
|
+
* SSE 分支一次性读完整个 body 再解析:StreamableHTTP 约定 server 发完响应即关流,
|
|
114
|
+
* 读全比手写增量解析器稳(`text/event-stream` 里 `data:` 行按规范可跨多行拼接)。
|
|
115
|
+
* SSE 里可能有别的通知帧或别的请求的应答,**只取与 `id` 配对的**那一条。
|
|
116
|
+
*/
|
|
117
|
+
export async function readMcpResult(res, id, method) {
|
|
118
|
+
const ct = (res.headers.get('content-type') ?? '').toLowerCase();
|
|
119
|
+
const text = await readMcpText(res);
|
|
120
|
+
if (ct.includes('text/event-stream')) {
|
|
121
|
+
for (const frame of text.split(/\r?\n\r?\n/)) {
|
|
122
|
+
const data = frame
|
|
123
|
+
.split(/\r?\n/)
|
|
124
|
+
.filter((l) => l.startsWith('data:'))
|
|
125
|
+
.map((l) => l.slice(5).trim())
|
|
126
|
+
.join('');
|
|
127
|
+
if (data === '')
|
|
128
|
+
continue;
|
|
129
|
+
let msg;
|
|
130
|
+
try {
|
|
131
|
+
msg = JSON.parse(data);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (isJsonRpcResponse(msg) && msg.id === id)
|
|
137
|
+
return unwrap(msg, method);
|
|
138
|
+
}
|
|
139
|
+
throw new Error(`MCP ${method}:SSE 响应里没有 id 为 ${id} 的报文`);
|
|
140
|
+
}
|
|
141
|
+
if (text.trim() === '') {
|
|
142
|
+
throw new Error(`MCP ${method}:响应体为空(期望 id 为 ${id} 的 JSON-RPC 报文)`);
|
|
143
|
+
}
|
|
144
|
+
let msg;
|
|
145
|
+
try {
|
|
146
|
+
msg = JSON.parse(text);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
throw new Error(`MCP ${method}:响应不是合法 JSON:${brief(text)}`);
|
|
150
|
+
}
|
|
151
|
+
return pickJsonRpcResult(msg, id, method);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* `tools/list` 的应答 → 工具表。**两条连接器共用一份**(此前逐字写了两遍)。
|
|
155
|
+
*
|
|
156
|
+
* 形状不对一律**响亮失败**:把协议不符吞成空菜单,用户看到的是「这个 server 一个工具都没有」
|
|
157
|
+
* 而不是「server 坏了」—— 前者会被当成正常结果排错到别处去。只有 `tools` **缺席**才当空表
|
|
158
|
+
* (那是合法的「没有工具」)。
|
|
159
|
+
*/
|
|
160
|
+
export function parseToolList(r) {
|
|
161
|
+
if (typeof r !== 'object' || r === null) {
|
|
162
|
+
throw new Error(`MCP tools/list 返回了非对象:${brief(r)}`);
|
|
163
|
+
}
|
|
164
|
+
const listed = r.tools;
|
|
165
|
+
if (listed === undefined)
|
|
166
|
+
return [];
|
|
167
|
+
if (!Array.isArray(listed)) {
|
|
168
|
+
throw new Error(`MCP tools/list 的 tools 不是数组:${brief(listed)}`);
|
|
169
|
+
}
|
|
170
|
+
return listed;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* `tools/call` 的结果里协议层 `isError: true` ⇒ **必须转成抛错**。
|
|
174
|
+
*
|
|
175
|
+
* 承重:这个位只有连接器看得见,吞了它模型会收到一条「成功」的结果、trace 也记成成功调用
|
|
176
|
+
* (见 `McpClientLike` 的约定)。两条连接器共用一份。
|
|
177
|
+
*/
|
|
178
|
+
export function assertToolResultNotError(r, name) {
|
|
179
|
+
if (typeof r === 'object' && r !== null && r.isError) {
|
|
180
|
+
throw new Error(`MCP 工具 ${name} 返回 isError: ${brief(r.content)}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* **会话过期自愈**的判定(MCP Streamable HTTP 的规范语义)。
|
|
185
|
+
*
|
|
186
|
+
* 带会话 id 收到 `404` 的含义是「这个会话我不认识」⇒ **该请求没有被执行** ⇒ 丢会话、
|
|
187
|
+
* 重新握手、把这一次**重试一次**是安全的(不会重复执行副作用);规范也要求客户端此时
|
|
188
|
+
* **必须**新建会话。`allowReinit` 那一位保证**只重试一次**:第二次再 404 说明对面不是
|
|
189
|
+
* 「会话过期」而是别的问题,直接抛(不循环)。
|
|
190
|
+
*
|
|
191
|
+
* 抽成纯函数是为了让这三条判据**可以被单独钉住** —— 它此前内联在 `rpc` 的 `if` 里,
|
|
192
|
+
* 三个条件任意一个写反都没有用例看得见(症状是「重试带着旧会话再 404」或「无限重握」)。
|
|
193
|
+
*/
|
|
194
|
+
export function canSelfHealSession(status, hasSessionId, allowReinit) {
|
|
195
|
+
return status === 404 && hasSessionId && allowReinit;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* 拼 `tools/call` 的 params(**两条连接器共用一份** —— 承载 SEP-414 的 `_meta` 形状
|
|
199
|
+
* 只许存在一处,否则改一处漏一处没有任何用例看得见)。
|
|
200
|
+
*
|
|
201
|
+
* `traceparent`(W3C 串)落在 params 的**兄弟键 `_meta`**:SEP-414 明说这是 `_meta`
|
|
202
|
+
* DNS 前缀惯例的**例外**(裸键 `traceparent`,不许加成 `io.modelcontextprotocol.traceparent`
|
|
203
|
+
* —— 加了前缀跨实现的链就断了)。⚠️ **绝不进 `arguments`**:那是模型可见、server 按
|
|
204
|
+
* inputSchema 校验的工具签名,trace 上下文进去会污染契约(纪律②)。
|
|
205
|
+
* `traceparent` 缺席时**不落 `_meta` 键**(纪律③:不造空上下文 —— 空 `_meta` 对宽容的
|
|
206
|
+
* server 无害,但它让「这次到底有没有链路」变得不可判)。
|
|
207
|
+
*/
|
|
208
|
+
export function toolsCallParams(name, args, traceparent) {
|
|
209
|
+
return {
|
|
210
|
+
name,
|
|
211
|
+
arguments: args,
|
|
212
|
+
...(traceparent !== undefined ? { _meta: { traceparent } } : {}),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
69
215
|
//# sourceMappingURL=mcp-protocol.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-protocol.js","sourceRoot":"","sources":["../../src/integrations/mcp-protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-protocol.js","sourceRoot":"","sources":["../../src/integrations/mcp-protocol.ts"],"names":[],"mappings":"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"}
|