@migor/agentia 0.6.3 → 0.7.1

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 (76) hide show
  1. package/CHANGELOG.md +250 -1
  2. package/README.en.md +4 -1
  3. package/README.md +23 -1
  4. package/dist/AGENTS.md +211 -24
  5. package/dist/container/container.d.ts +8 -1
  6. package/dist/container/container.js +8 -1
  7. package/dist/container/container.js.map +1 -1
  8. package/dist/core/run.d.ts +5 -1
  9. package/dist/core/timeout.d.ts +8 -0
  10. package/dist/core/timeout.js +14 -3
  11. package/dist/core/timeout.js.map +1 -1
  12. package/dist/core/tool.d.ts +64 -0
  13. package/dist/engine/budget.d.ts +17 -4
  14. package/dist/engine/budget.js +3 -3
  15. package/dist/engine/budget.js.map +1 -1
  16. package/dist/engine/loop.d.ts +7 -0
  17. package/dist/engine/loop.js +102 -6
  18. package/dist/engine/loop.js.map +1 -1
  19. package/dist/engine/spec.d.ts +18 -2
  20. package/dist/engine/spec.js.map +1 -1
  21. package/dist/engine/tracer.d.ts +11 -0
  22. package/dist/engine/tracer.js +25 -12
  23. package/dist/engine/tracer.js.map +1 -1
  24. package/dist/engine/turn.d.ts +25 -3
  25. package/dist/engine/turn.js +63 -4
  26. package/dist/engine/turn.js.map +1 -1
  27. package/dist/engine/types.d.ts +28 -1
  28. package/dist/engine/types.js.map +1 -1
  29. package/dist/index.d.ts +4 -4
  30. package/dist/index.js +4 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/integrations/anthropic.js +50 -5
  33. package/dist/integrations/anthropic.js.map +1 -1
  34. package/dist/integrations/mcp.d.ts +116 -11
  35. package/dist/integrations/mcp.js +523 -2
  36. package/dist/integrations/mcp.js.map +1 -1
  37. package/dist/integrations/metrics.d.ts +15 -0
  38. package/dist/integrations/metrics.js +114 -77
  39. package/dist/integrations/metrics.js.map +1 -1
  40. package/dist/integrations/openai.js +46 -0
  41. package/dist/integrations/openai.js.map +1 -1
  42. package/dist/integrations/otlp.js +15 -6
  43. package/dist/integrations/otlp.js.map +1 -1
  44. package/dist/runtime/run.d.ts +6 -0
  45. package/dist/runtime/run.js +23 -0
  46. package/dist/runtime/run.js.map +1 -1
  47. package/dist/store/fsStore.d.ts +2 -1
  48. package/dist/store/fsStore.js +15 -4
  49. package/dist/store/fsStore.js.map +1 -1
  50. package/dist/store/sqliteStore.js +7 -5
  51. package/dist/store/sqliteStore.js.map +1 -1
  52. package/dist/store/store.d.ts +17 -1
  53. package/dist/store/store.js +3 -2
  54. package/dist/store/store.js.map +1 -1
  55. package/dist/toolkit/asset.d.ts +3 -2
  56. package/dist/toolkit/asset.js +11 -2
  57. package/dist/toolkit/asset.js.map +1 -1
  58. package/dist/toolkit/module.d.ts +3 -2
  59. package/dist/toolkit/module.js +3 -0
  60. package/dist/toolkit/module.js.map +1 -1
  61. package/dist/toolkit/skill.js +46 -8
  62. package/dist/toolkit/skill.js.map +1 -1
  63. package/dist/toolkit/subagent.js +26 -1
  64. package/dist/toolkit/subagent.js.map +1 -1
  65. package/dist/toolkit/tool.d.ts +6 -0
  66. package/dist/toolkit/tool.js +1 -0
  67. package/dist/toolkit/tool.js.map +1 -1
  68. package/dist/transport/async.d.ts +74 -1
  69. package/dist/transport/async.js +257 -12
  70. package/dist/transport/async.js.map +1 -1
  71. package/dist/transport/http.d.ts +5 -0
  72. package/dist/transport/http.js +74 -2
  73. package/dist/transport/http.js.map +1 -1
  74. package/dist/transport/scheduler.js +33 -2
  75. package/dist/transport/scheduler.js.map +1 -1
  76. package/package.json +8 -4
@@ -1,19 +1,22 @@
1
1
  import type { AgentTool } from '../core/tool.js';
2
2
  /**
3
- * Agentia —— MCP 桥(D1,spec §10 决策记录)。
3
+ * Agentia —— MCP 桥(D1)+ 两个内置连接器(spec §10 决策记录)。
4
4
  *
5
- * 设计原则同 `RedisLike`:框架只定义**结构面**,不 import `@modelcontextprotocol/sdk`,
6
- * 也**不含任何传输实现**(stdio spawn / StreamableHTTP 都在独立可选包 `@migor/mcp`,
7
- * 或用户自己接 SDK 后实现 `McpClientLike`)。本文件只依赖 core,符合分层约定
8
- * (`integrations` → `core`)。
5
+ * **桥**:框架只定义**结构面** —— 不 import `@modelcontextprotocol/sdk`,任何实现了
6
+ * `McpClientLike` 的客户端都能接(同 `RedisLike` 的 duck-typing)。本文件只依赖 core,
7
+ * 符合分层约定(`integrations` → `core`)。
9
8
  *
10
- * 用法:在 `createApp({ providers })` 里放一个 provider 即可 ——
9
+ * **连接器**(2026-09-18 起**内置**,见文件末「连接器」一节与 spec §10 同日条):
10
+ * `createStdioMcpConnector` / `createStreamableHttpMcpConnector`。二者只用标准库
11
+ * (`node:child_process` + 全局 `fetch`),**不新增任何第三方依赖**。
12
+ *
13
+ * 用法(接入点是 `AppOptions.tools` 这条**裸工具缝**):
11
14
  * ```ts
12
- * createApp({
13
- * system: '…',
14
- * providers: [{ provide: 'mcp', useFactory: () => mcpTools(client, { server: 'time' }) }],
15
- * });
15
+ * const mcp = createStdioMcpConnector(['uvx', 'mcp-server-time']);
16
+ * createApp({ system: '…', tools: await mcpTools(mcp, { server: 'time' }) });
16
17
  * ```
18
+ * ⚠️ **不是** `providers: [{ provide: 'mcp', useFactory: … }]` —— 那条路落地时不成立
19
+ * (菜单只从装饰器注册表收集,`useFactory` 的返回值根本不进菜单;见 spec §10 2026-09-11)。
17
20
  * 复用既有装配 / 查重 / 中间件,**零新机制**(MCP 工具与本地 @Tool 同处一个命名空间,
18
21
  * 重名由 AgentApp 的装配期查重拦下)。
19
22
  *
@@ -37,7 +40,15 @@ export interface McpToolInfo {
37
40
  */
38
41
  export interface McpClientLike {
39
42
  listTools(): Promise<McpToolInfo[]>;
40
- callTool(name: string, args: Record<string, unknown>): Promise<unknown>;
43
+ /**
44
+ * `opts.abandoned`:裁判(引擎 `toolTimeoutMs` / 桥兜底超时)**放弃等待**的通知信号。
45
+ * 放弃 ≠ 取消 —— 但连接器应借此清掉这次调用的簿记(stdio 的 pending 条目、
46
+ * HTTP 的在飞 fetch),否则「server 活着但不回包」时每超时一次就泄漏一条。
47
+ * 只实现两个参数的旧客户端依然兼容(可选参数,鸭子类型)。
48
+ */
49
+ callTool(name: string, args: Record<string, unknown>, opts?: {
50
+ abandoned?: AbortSignal;
51
+ }): Promise<unknown>;
41
52
  }
42
53
  export interface McpToolsOptions {
43
54
  /**
@@ -86,3 +97,97 @@ export declare function withDeadline<T>(p: Promise<T>, timeoutMs: number, label:
86
97
  * 不做「把 content 拼成字符串」这类有损加工 —— 需要塑形请自行包一层工具。
87
98
  */
88
99
  export declare function mcpTools(client: McpClientLike, opts?: McpToolsOptions): Promise<AgentTool[]>;
100
+ /**
101
+ * 连接器公共面:`McpClientLike` + 一个关闭句柄(两个内置连接器都返回它)。
102
+ *
103
+ * 缝的形状没有变化 —— 需要自己的传输(官方 SDK / 远程 server / 复用长连接)时,
104
+ * 实现 `McpClientLike` 两个方法即可,不必碰这里。
105
+ */
106
+ export interface McpConnector extends McpClientLike {
107
+ /**
108
+ * 释放底层资源,**幂等**;stdio 侧**保证返回时子进程已终止**:
109
+ * 先 SIGTERM,宽限期({@link MCP_CLOSE_GRACE_MS})后 SIGKILL,然后**等真正的 `'exit'`**
110
+ * (2026-09-18 收紧:此前到点即返回、不等 reap,会留下孤儿进程而调用方无从知晓)。
111
+ * HTTP 侧 = 尽力 `DELETE` 终止会话(server 不认也无所谓,失败不抛)。
112
+ *
113
+ * 关闭后再调用 `listTools` / `callTool` 会抛出可读错误(不静默挂死)。
114
+ */
115
+ close(): Promise<void>;
116
+ }
117
+ /** `close()` 里 SIGTERM → SIGKILL 的宽限期(毫秒) */
118
+ export declare const MCP_CLOSE_GRACE_MS = 2000;
119
+ export interface StdioMcpConnectorOptions {
120
+ /** 追加 / 覆盖的环境变量(缺省继承 `process.env`) */
121
+ env?: Record<string, string>;
122
+ /** 子进程工作目录 */
123
+ cwd?: string;
124
+ /** 子进程 stderr 去向:`'inherit'`(缺省,server 日志直通终端)| `'ignore'` */
125
+ stderr?: 'inherit' | 'ignore';
126
+ /** 见 {@link DEFAULT_CLIENT_INFO} */
127
+ clientInfo?: {
128
+ name: string;
129
+ version: string;
130
+ };
131
+ /** 请求的协议版本,缺省 `'2024-11-05'` */
132
+ protocolVersion?: string;
133
+ /**
134
+ * 装配期超时(毫秒)—— 只作用于**握手 + `tools/list`**,缺省
135
+ * {@link MCP_DEFAULT_TIMEOUT_MS};非正数 = 不限。语义见 {@link Guard}。
136
+ *
137
+ * 超时同样只是一类账(`code='timeout'`):**不终止子进程**,与仓库其余「等待的终点」
138
+ * 一致(超时 = 放弃等待)。
139
+ */
140
+ timeoutMs?: number;
141
+ }
142
+ /**
143
+ * **stdio 连接器**:spawn 一个 MCP server 子进程,走换行分隔的 JSON-RPC 2.0
144
+ * (`initialize` → `notifications/initialized` → `tools/list` / `tools/call`)。
145
+ *
146
+ * 进程与握手都是**惰性**的 —— 构造不产生副作用,第一次 `listTools` / `callTool` 才 spawn;
147
+ * 握手只做一次(并发调用共享同一次握手)。
148
+ *
149
+ * 三处非显然的坑,这里都兜住了(此前 `scripts/e2e-mcp.ts` 内联的那 94 行踩过):
150
+ * 1. spawn **失败**(命令不存在 → `ENOENT`)是异步的 `'error'` 事件,不是抛出 ——
151
+ * 没有监听器就是未捕获异常、直接把宿主进程带崩,所以必须接住并拒绝在途请求;
152
+ * 2. 分帧:一条报文可能跨多个 chunk,必须自己攒 buffer 按 `\n` 切;
153
+ * 3. **协议层 `isError: true` 必须转成抛错** —— 否则模型收到一条「成功」的结果,
154
+ * trace 也把它记成成功的调用(`McpClientLike` 的约定,见其注释)。
155
+ */
156
+ export declare function createStdioMcpConnector(cmd: readonly string[], opts?: StdioMcpConnectorOptions): McpConnector;
157
+ export interface StreamableHttpMcpConnectorOptions {
158
+ /** 附加请求头(鉴权等)。会覆盖缺省的 `content-type` / `accept` 同名字段 */
159
+ headers?: Record<string, string>;
160
+ /** 见 {@link DEFAULT_CLIENT_INFO} */
161
+ clientInfo?: {
162
+ name: string;
163
+ version: string;
164
+ };
165
+ /** 请求的协议版本,缺省 `'2024-11-05'`;协商结果以 server 回的为准 */
166
+ protocolVersion?: string;
167
+ /** 装配期超时(毫秒)—— 只作用于**握手 + `tools/list`**,语义同 {@link StdioMcpConnectorOptions.timeoutMs} */
168
+ timeoutMs?: number;
169
+ /**
170
+ * 会话过期时被调一次(见 `rpc` 的 404 自愈)。**给可观测用**:默认自愈是静默的,
171
+ * 而「静默恢复」和「静默失效」在监控上看不出区别 —— 要计数 / 告警 / 打日志就挂这个钩子。
172
+ */
173
+ onSessionExpired?: () => void;
174
+ /** 注入 `fetch`(测试用;缺省全局 `fetch`,与 `createOpenAIClient` 同款) */
175
+ fetchImpl?: typeof fetch;
176
+ }
177
+ /**
178
+ * **StreamableHTTP 连接器**:一个 endpoint,POST JSON-RPC(MCP 2025-03-26 起的
179
+ * Streamable HTTP 传输)。
180
+ *
181
+ * - 两种响应形态**都要接**:`application/json`(整条报文)与 `text/event-stream`
182
+ * (报文按 SSE 帧下发,server 应在发完响应后关流);
183
+ * - 会话:`initialize` 响应里的 `Mcp-Session-Id` 会被记住并在后续请求上回带
184
+ * (后续响应不带该头时**不覆盖**);`close()` 尽力 `DELETE` 终止会话;
185
+ * **会话过期自愈**:带会话 id 收到 `404` ⇒ 视为「会话已终止、该请求未被 server 执行」
186
+ * ⇒ 丢会话 → 重新握手 → 把这一次**重试一次**(只一次,不再循环)。自愈是静默的,
187
+ * 所以给了 `onSessionExpired` 钩子给你计数 / 告警 —— 否则它和「静默失效」没区别。
188
+ * - 协议版本:请求头 `MCP-Protocol-Version` 带**协商到的**版本(2025-06-18 起要求,
189
+ * 老 server 忽略未知头);
190
+ * - HTTP 层失败**挂数值 `status`** ⇒ `engine/errors.ts::classifyError` 自动分流
191
+ * (429 → `rate_limit` 可重试 / ≥500 → `server` 可重试 / 其余 4xx → `api` 不可重试)。
192
+ */
193
+ export declare function createStreamableHttpMcpConnector(url: string, opts?: StreamableHttpMcpConnectorOptions): McpConnector;