@next-open-ai/openbot 0.2.8 → 0.6.6

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 (94) hide show
  1. package/README.md +13 -3
  2. package/apps/desktop/renderer/dist/assets/index-BNuvb6Ay.css +10 -0
  3. package/apps/desktop/renderer/dist/assets/index-DvQjslfT.js +89 -0
  4. package/apps/desktop/renderer/dist/index.html +2 -2
  5. package/dist/core/agent/agent-manager.d.ts +17 -6
  6. package/dist/core/agent/agent-manager.js +62 -25
  7. package/dist/core/agent/run.js +2 -2
  8. package/dist/core/config/desktop-config.d.ts +17 -0
  9. package/dist/core/config/desktop-config.js +23 -1
  10. package/dist/core/installer/index.d.ts +1 -1
  11. package/dist/core/installer/index.js +1 -1
  12. package/dist/core/installer/skill-installer.d.ts +9 -0
  13. package/dist/core/installer/skill-installer.js +94 -0
  14. package/dist/core/mcp/adapter.d.ts +17 -0
  15. package/dist/core/mcp/adapter.js +49 -0
  16. package/dist/core/mcp/client.d.ts +24 -0
  17. package/dist/core/mcp/client.js +70 -0
  18. package/dist/core/mcp/config.d.ts +22 -0
  19. package/dist/core/mcp/config.js +69 -0
  20. package/dist/core/mcp/index.d.ts +18 -0
  21. package/dist/core/mcp/index.js +20 -0
  22. package/dist/core/mcp/operator.d.ts +15 -0
  23. package/dist/core/mcp/operator.js +72 -0
  24. package/dist/core/mcp/transport/index.d.ts +11 -0
  25. package/dist/core/mcp/transport/index.js +16 -0
  26. package/dist/core/mcp/transport/sse.d.ts +20 -0
  27. package/dist/core/mcp/transport/sse.js +82 -0
  28. package/dist/core/mcp/transport/stdio.d.ts +32 -0
  29. package/dist/core/mcp/transport/stdio.js +132 -0
  30. package/dist/core/mcp/types.d.ts +72 -0
  31. package/dist/core/mcp/types.js +5 -0
  32. package/dist/core/session-current-agent.d.ts +34 -0
  33. package/dist/core/session-current-agent.js +32 -0
  34. package/dist/core/tools/bookmark-tool.d.ts +9 -0
  35. package/dist/core/tools/bookmark-tool.js +118 -0
  36. package/dist/core/tools/create-agent-tool.d.ts +6 -0
  37. package/dist/core/tools/create-agent-tool.js +97 -0
  38. package/dist/core/tools/index.d.ts +4 -0
  39. package/dist/core/tools/index.js +4 -0
  40. package/dist/core/tools/list-agents-tool.d.ts +5 -0
  41. package/dist/core/tools/list-agents-tool.js +45 -0
  42. package/dist/core/tools/switch-agent-tool.d.ts +6 -0
  43. package/dist/core/tools/switch-agent-tool.js +54 -0
  44. package/dist/gateway/channel/adapters/feishu.d.ts +11 -0
  45. package/dist/gateway/channel/adapters/feishu.js +218 -0
  46. package/dist/gateway/channel/channel-core.d.ts +9 -0
  47. package/dist/gateway/channel/channel-core.js +127 -0
  48. package/dist/gateway/channel/registry.d.ts +16 -0
  49. package/dist/gateway/channel/registry.js +54 -0
  50. package/dist/gateway/channel/run-agent.d.ts +26 -0
  51. package/dist/gateway/channel/run-agent.js +137 -0
  52. package/dist/gateway/channel/session-persistence.d.ts +36 -0
  53. package/dist/gateway/channel/session-persistence.js +46 -0
  54. package/dist/gateway/channel/types.d.ts +70 -0
  55. package/dist/gateway/channel/types.js +4 -0
  56. package/dist/gateway/channel-handler.d.ts +3 -4
  57. package/dist/gateway/channel-handler.js +8 -2
  58. package/dist/gateway/methods/agent-chat.js +31 -12
  59. package/dist/gateway/methods/install-skill-from-upload.d.ts +14 -0
  60. package/dist/gateway/methods/install-skill-from-upload.js +13 -0
  61. package/dist/gateway/methods/run-scheduled-task.js +5 -2
  62. package/dist/gateway/server.js +74 -1
  63. package/dist/server/agent-config/agent-config.controller.d.ts +6 -1
  64. package/dist/server/agent-config/agent-config.service.d.ts +15 -1
  65. package/dist/server/agent-config/agent-config.service.js +12 -3
  66. package/dist/server/agents/agents.controller.d.ts +10 -0
  67. package/dist/server/agents/agents.controller.js +36 -4
  68. package/dist/server/agents/agents.gateway.js +18 -4
  69. package/dist/server/agents/agents.service.d.ts +5 -1
  70. package/dist/server/agents/agents.service.js +20 -2
  71. package/dist/server/app.module.js +2 -0
  72. package/dist/server/config/config.controller.d.ts +2 -0
  73. package/dist/server/config/config.service.d.ts +3 -0
  74. package/dist/server/config/config.service.js +3 -1
  75. package/dist/server/database/database.service.d.ts +7 -0
  76. package/dist/server/database/database.service.js +54 -5
  77. package/dist/server/saved-items/saved-items.controller.d.ts +57 -0
  78. package/dist/server/saved-items/saved-items.controller.js +229 -0
  79. package/dist/server/saved-items/saved-items.module.d.ts +2 -0
  80. package/dist/server/saved-items/saved-items.module.js +25 -0
  81. package/dist/server/saved-items/saved-items.service.d.ts +31 -0
  82. package/dist/server/saved-items/saved-items.service.js +105 -0
  83. package/dist/server/saved-items/tags.controller.d.ts +30 -0
  84. package/dist/server/saved-items/tags.controller.js +85 -0
  85. package/dist/server/saved-items/tags.service.d.ts +24 -0
  86. package/dist/server/saved-items/tags.service.js +84 -0
  87. package/dist/server/skills/skills.service.d.ts +2 -0
  88. package/dist/server/skills/skills.service.js +80 -16
  89. package/dist/server/workspace/workspace.service.d.ts +11 -0
  90. package/dist/server/workspace/workspace.service.js +40 -1
  91. package/package.json +6 -1
  92. package/skills/url-bookmark/SKILL.md +36 -0
  93. package/apps/desktop/renderer/dist/assets/index-BOS-F8a4.js +0 -89
  94. package/apps/desktop/renderer/dist/assets/index-DxqxayUL.css +0 -10
@@ -0,0 +1,69 @@
1
+ /**
2
+ * MCP 配置解析与校验。
3
+ * 从 getOrCreateSession 的 options.mcpServers 中取出并规范化,支持 stdio 与 sse。
4
+ */
5
+ /**
6
+ * 从会话选项里解析出本会话启用的 MCP 服务器配置列表。
7
+ * 支持 stdio(本地进程)与 sse(远程 HTTP)。
8
+ */
9
+ export function resolveMcpServersForSession(mcpServers) {
10
+ if (!Array.isArray(mcpServers) || mcpServers.length === 0) {
11
+ return [];
12
+ }
13
+ const result = [];
14
+ for (const s of mcpServers) {
15
+ if (!s || typeof s !== "object")
16
+ continue;
17
+ if (s.transport === "stdio") {
18
+ if (typeof s.command !== "string" || !s.command.trim()) {
19
+ console.warn("[mcp] 跳过无效 stdio 配置:缺少或无效 command");
20
+ continue;
21
+ }
22
+ result.push({
23
+ transport: "stdio",
24
+ command: s.command.trim(),
25
+ args: Array.isArray(s.args) ? s.args : undefined,
26
+ env: s.env && typeof s.env === "object" ? s.env : undefined,
27
+ });
28
+ }
29
+ else if (s.transport === "sse") {
30
+ const url = s.url?.trim();
31
+ if (!url) {
32
+ console.warn("[mcp] 跳过无效 sse 配置:缺少或无效 url");
33
+ continue;
34
+ }
35
+ result.push({
36
+ transport: "sse",
37
+ url,
38
+ headers: s.headers && typeof s.headers === "object" ? s.headers : undefined,
39
+ });
40
+ }
41
+ else {
42
+ console.warn("[mcp] 未知 transport:", s.transport);
43
+ }
44
+ }
45
+ return result;
46
+ }
47
+ /**
48
+ * 为 stdio 配置生成缓存键(用于 Operator 复用同一进程连接)
49
+ */
50
+ export function stdioConfigKey(config) {
51
+ const args = (config.args ?? []).join(" ");
52
+ const envStr = config.env ? JSON.stringify(config.env) : "";
53
+ return `stdio:${config.command}\0${args}\0${envStr}`;
54
+ }
55
+ /**
56
+ * 为 sse 配置生成缓存键
57
+ */
58
+ export function sseConfigKey(config) {
59
+ const headersStr = config.headers ? JSON.stringify(config.headers) : "";
60
+ return `sse:${config.url}\0${headersStr}`;
61
+ }
62
+ /**
63
+ * 任意 MCP 配置的缓存键
64
+ */
65
+ export function mcpConfigKey(config) {
66
+ if (config.transport === "stdio")
67
+ return stdioConfigKey(config);
68
+ return sseConfigKey(config);
69
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Core MCP 模块:为 SessionAgent 提供 MCP Tools 能力(Client 端)。
3
+ * 配置在创建 Session 时通过 options.mcpServers 传入,与 Skill 类似。
4
+ */
5
+ import type { ToolDefinition } from "@mariozechner/pi-coding-agent";
6
+ import type { McpServerConfig } from "./types.js";
7
+ export type { McpServerConfig, McpServerConfigStdio, McpServerConfigSse, McpTool } from "./types.js";
8
+ export { resolveMcpServersForSession, stdioConfigKey, sseConfigKey, mcpConfigKey } from "./config.js";
9
+ export { McpClient } from "./client.js";
10
+ export { getMcpToolDefinitions, shutdownMcpClients } from "./operator.js";
11
+ export { mcpToolToToolDefinition, mcpToolsToToolDefinitions } from "./adapter.js";
12
+ /**
13
+ * 根据会话选项中的 mcpServers 配置,返回该会话可用的 MCP 工具(ToolDefinition 数组)。
14
+ * 在 AgentManager.getOrCreateSession 中调用,并入 customTools。
15
+ */
16
+ export declare function createMcpToolsForSession(options: {
17
+ mcpServers?: McpServerConfig[];
18
+ }): Promise<ToolDefinition[]>;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Core MCP 模块:为 SessionAgent 提供 MCP Tools 能力(Client 端)。
3
+ * 配置在创建 Session 时通过 options.mcpServers 传入,与 Skill 类似。
4
+ */
5
+ import { resolveMcpServersForSession } from "./config.js";
6
+ import { getMcpToolDefinitions } from "./operator.js";
7
+ export { resolveMcpServersForSession, stdioConfigKey, sseConfigKey, mcpConfigKey } from "./config.js";
8
+ export { McpClient } from "./client.js";
9
+ export { getMcpToolDefinitions, shutdownMcpClients } from "./operator.js";
10
+ export { mcpToolToToolDefinition, mcpToolsToToolDefinitions } from "./adapter.js";
11
+ /**
12
+ * 根据会话选项中的 mcpServers 配置,返回该会话可用的 MCP 工具(ToolDefinition 数组)。
13
+ * 在 AgentManager.getOrCreateSession 中调用,并入 customTools。
14
+ */
15
+ export async function createMcpToolsForSession(options) {
16
+ const configs = resolveMcpServersForSession(options.mcpServers);
17
+ if (configs.length === 0)
18
+ return [];
19
+ return getMcpToolDefinitions(configs);
20
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * MCP Operator:管理 MCP 客户端生命周期,按配置为会话提供 ToolDefinition 列表。
3
+ * 支持 stdio(本地)与 sse(远程)两种传输。
4
+ */
5
+ import type { McpServerConfig } from "./types.js";
6
+ import type { ToolDefinition } from "@mariozechner/pi-coding-agent";
7
+ /**
8
+ * 为给定 MCP 服务器配置列表获取或创建客户端,并返回其工具对应的 ToolDefinition 数组。
9
+ * 连接失败或 list_tools 失败的 server 会被跳过并打日志,不阻塞整体。
10
+ */
11
+ export declare function getMcpToolDefinitions(serverConfigs: McpServerConfig[]): Promise<ToolDefinition[]>;
12
+ /**
13
+ * 关闭并移除所有缓存的 MCP 客户端(进程退出或显式清理时调用)。
14
+ */
15
+ export declare function shutdownMcpClients(): Promise<void>;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * MCP Operator:管理 MCP 客户端生命周期,按配置为会话提供 ToolDefinition 列表。
3
+ * 支持 stdio(本地)与 sse(远程)两种传输。
4
+ */
5
+ import { mcpConfigKey } from "./config.js";
6
+ import { McpClient } from "./client.js";
7
+ import { mcpToolsToToolDefinitions } from "./adapter.js";
8
+ /** 按配置键缓存的客户端 */
9
+ const clientCache = new Map();
10
+ function configLabel(config) {
11
+ if (config.transport === "stdio")
12
+ return config.command;
13
+ return config.url;
14
+ }
15
+ /**
16
+ * 为给定 MCP 服务器配置列表获取或创建客户端,并返回其工具对应的 ToolDefinition 数组。
17
+ * 连接失败或 list_tools 失败的 server 会被跳过并打日志,不阻塞整体。
18
+ */
19
+ export async function getMcpToolDefinitions(serverConfigs) {
20
+ const allTools = [];
21
+ for (let i = 0; i < serverConfigs.length; i++) {
22
+ const config = serverConfigs[i];
23
+ const key = mcpConfigKey(config);
24
+ let client = clientCache.get(key);
25
+ if (!client) {
26
+ client = new McpClient(config);
27
+ try {
28
+ await client.connect();
29
+ clientCache.set(key, client);
30
+ }
31
+ catch (err) {
32
+ console.warn(`[mcp] 连接失败 (${configLabel(config)}):`, err instanceof Error ? err.message : err);
33
+ continue;
34
+ }
35
+ }
36
+ if (!client.isConnected) {
37
+ clientCache.delete(key);
38
+ try {
39
+ await client.close();
40
+ }
41
+ catch { }
42
+ const newClient = new McpClient(config);
43
+ try {
44
+ await newClient.connect();
45
+ clientCache.set(key, newClient);
46
+ client = newClient;
47
+ }
48
+ catch (err) {
49
+ console.warn(`[mcp] 重连失败 (${configLabel(config)}):`, err instanceof Error ? err.message : err);
50
+ continue;
51
+ }
52
+ }
53
+ try {
54
+ const tools = await client.listTools();
55
+ const serverId = `mcp${i}`;
56
+ const definitions = mcpToolsToToolDefinitions(tools, client, serverId);
57
+ allTools.push(...definitions);
58
+ }
59
+ catch (err) {
60
+ console.warn(`[mcp] list_tools 失败 (${configLabel(config)}):`, err instanceof Error ? err.message : err);
61
+ }
62
+ }
63
+ return allTools;
64
+ }
65
+ /**
66
+ * 关闭并移除所有缓存的 MCP 客户端(进程退出或显式清理时调用)。
67
+ */
68
+ export async function shutdownMcpClients() {
69
+ const closeAll = Array.from(clientCache.values()).map((c) => c.close().catch(() => { }));
70
+ clientCache.clear();
71
+ await Promise.all(closeAll);
72
+ }
@@ -0,0 +1,11 @@
1
+ import type { McpServerConfig, IMcpTransport } from "../types.js";
2
+ export interface TransportOptions {
3
+ initTimeoutMs?: number;
4
+ requestTimeoutMs?: number;
5
+ }
6
+ /**
7
+ * 根据配置创建对应的传输层实例。
8
+ */
9
+ export declare function createTransport(config: McpServerConfig, options?: TransportOptions): IMcpTransport;
10
+ export { StdioTransport } from "./stdio.js";
11
+ export { SseTransport } from "./sse.js";
@@ -0,0 +1,16 @@
1
+ import { StdioTransport } from "./stdio.js";
2
+ import { SseTransport } from "./sse.js";
3
+ /**
4
+ * 根据配置创建对应的传输层实例。
5
+ */
6
+ export function createTransport(config, options) {
7
+ if (config.transport === "stdio") {
8
+ return new StdioTransport(config, options);
9
+ }
10
+ if (config.transport === "sse") {
11
+ return new SseTransport(config, options);
12
+ }
13
+ throw new Error(`Unsupported MCP transport: ${config.transport}`);
14
+ }
15
+ export { StdioTransport } from "./stdio.js";
16
+ export { SseTransport } from "./sse.js";
@@ -0,0 +1,20 @@
1
+ /**
2
+ * MCP SSE/HTTP 传输:通过 HTTP POST 向远程 URL 发送 JSON-RPC 请求,响应在 response body。
3
+ */
4
+ import type { McpServerConfigSse } from "../types.js";
5
+ import type { JsonRpcRequest, JsonRpcResponse } from "../types.js";
6
+ export interface SseTransportOptions {
7
+ initTimeoutMs?: number;
8
+ requestTimeoutMs?: number;
9
+ }
10
+ export declare class SseTransport {
11
+ private config;
12
+ private initTimeoutMs;
13
+ private requestTimeoutMs;
14
+ private _connected;
15
+ constructor(config: McpServerConfigSse, options?: SseTransportOptions);
16
+ start(): Promise<void>;
17
+ request(req: JsonRpcRequest, timeoutMs?: number): Promise<JsonRpcResponse>;
18
+ close(): Promise<void>;
19
+ get isConnected(): boolean;
20
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * MCP SSE/HTTP 传输:通过 HTTP POST 向远程 URL 发送 JSON-RPC 请求,响应在 response body。
3
+ */
4
+ const MCP_PROTOCOL_VERSION = "2024-11-05";
5
+ export class SseTransport {
6
+ config;
7
+ initTimeoutMs;
8
+ requestTimeoutMs;
9
+ _connected = false;
10
+ constructor(config, options = {}) {
11
+ this.config = config;
12
+ this.initTimeoutMs = options.initTimeoutMs ?? 15_000;
13
+ this.requestTimeoutMs = options.requestTimeoutMs ?? 30_000;
14
+ }
15
+ async start() {
16
+ if (this._connected)
17
+ return;
18
+ const url = (this.config.url ?? "").trim();
19
+ if (!url)
20
+ throw new Error("MCP SSE url is required");
21
+ const initResult = await this.request({
22
+ jsonrpc: "2.0",
23
+ id: 1,
24
+ method: "initialize",
25
+ params: {
26
+ protocolVersion: MCP_PROTOCOL_VERSION,
27
+ capabilities: {},
28
+ clientInfo: { name: "openbot", version: "0.1.0" },
29
+ },
30
+ }, this.initTimeoutMs);
31
+ if (initResult.error) {
32
+ throw new Error(`MCP initialize failed: ${initResult.error.message}`);
33
+ }
34
+ await this.request({ jsonrpc: "2.0", id: 2, method: "notifications/initialized" }, this.requestTimeoutMs).catch(() => ({}));
35
+ this._connected = true;
36
+ }
37
+ request(req, timeoutMs) {
38
+ const url = (this.config.url ?? "").trim();
39
+ if (!url) {
40
+ return Promise.reject(new Error("MCP SSE url is required"));
41
+ }
42
+ const t = timeoutMs ?? this.requestTimeoutMs;
43
+ const controller = new AbortController();
44
+ const timeoutId = setTimeout(() => controller.abort(), t);
45
+ const headers = {
46
+ "Content-Type": "application/json",
47
+ Accept: "application/json",
48
+ ...this.config.headers,
49
+ };
50
+ return fetch(url, {
51
+ method: "POST",
52
+ headers,
53
+ body: JSON.stringify(req),
54
+ signal: controller.signal,
55
+ })
56
+ .then(async (res) => {
57
+ clearTimeout(timeoutId);
58
+ if (!res.ok) {
59
+ const text = await res.text();
60
+ throw new Error(`MCP HTTP ${res.status}: ${text.slice(0, 200)}`);
61
+ }
62
+ const json = (await res.json());
63
+ if (!json || json.jsonrpc !== "2.0") {
64
+ throw new Error("Invalid MCP response");
65
+ }
66
+ return json;
67
+ })
68
+ .catch((err) => {
69
+ clearTimeout(timeoutId);
70
+ if (err.name === "AbortError") {
71
+ throw new Error(`MCP request timeout (${t}ms)`);
72
+ }
73
+ throw err;
74
+ });
75
+ }
76
+ async close() {
77
+ this._connected = false;
78
+ }
79
+ get isConnected() {
80
+ return this._connected;
81
+ }
82
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * MCP stdio 传输:子进程 + 标准输入/输出上的 Newline-delimited JSON-RPC。
3
+ */
4
+ import type { McpServerConfigStdio } from "../types.js";
5
+ import type { JsonRpcRequest, JsonRpcResponse } from "../types.js";
6
+ export interface StdioTransportOptions {
7
+ /** 初始化超时(毫秒) */
8
+ initTimeoutMs?: number;
9
+ /** 单次请求超时(毫秒) */
10
+ requestTimeoutMs?: number;
11
+ }
12
+ export declare class StdioTransport {
13
+ private process;
14
+ private config;
15
+ private initTimeoutMs;
16
+ private requestTimeoutMs;
17
+ private nextId;
18
+ private pending;
19
+ private buffer;
20
+ constructor(config: McpServerConfigStdio, options?: StdioTransportOptions);
21
+ /** 启动子进程并完成 MCP initialize 握手 */
22
+ start(): Promise<void>;
23
+ private flushLines;
24
+ private rejectAll;
25
+ private initialize;
26
+ private sendNotification;
27
+ /** 发送 JSON-RPC 请求并等待响应 */
28
+ request(req: JsonRpcRequest, timeoutMs?: number): Promise<JsonRpcResponse>;
29
+ /** 关闭子进程 */
30
+ close(): Promise<void>;
31
+ get isConnected(): boolean;
32
+ }
@@ -0,0 +1,132 @@
1
+ /**
2
+ * MCP stdio 传输:子进程 + 标准输入/输出上的 Newline-delimited JSON-RPC。
3
+ */
4
+ import { spawn } from "node:child_process";
5
+ const MCP_PROTOCOL_VERSION = "2024-11-05";
6
+ export class StdioTransport {
7
+ process = null;
8
+ config;
9
+ initTimeoutMs;
10
+ requestTimeoutMs;
11
+ nextId = 1;
12
+ pending = new Map();
13
+ buffer = "";
14
+ constructor(config, options = {}) {
15
+ this.config = config;
16
+ this.initTimeoutMs = options.initTimeoutMs ?? 10_000;
17
+ this.requestTimeoutMs = options.requestTimeoutMs ?? 30_000;
18
+ }
19
+ /** 启动子进程并完成 MCP initialize 握手 */
20
+ async start() {
21
+ if (this.process) {
22
+ return;
23
+ }
24
+ const env = { ...process.env, ...this.config.env };
25
+ this.process = spawn(this.config.command, this.config.args ?? [], {
26
+ env,
27
+ stdio: ["pipe", "pipe", "pipe"],
28
+ });
29
+ const child = this.process;
30
+ child.stdout?.on("data", (chunk) => {
31
+ this.buffer += chunk.toString("utf-8");
32
+ this.flushLines();
33
+ });
34
+ child.stderr?.on("data", (data) => {
35
+ const msg = data.toString("utf-8").trim();
36
+ if (msg)
37
+ console.warn("[mcp stdio stderr]", msg);
38
+ });
39
+ child.on("error", (err) => {
40
+ this.rejectAll(new Error(`MCP process error: ${err.message}`));
41
+ });
42
+ child.on("exit", (code, signal) => {
43
+ this.rejectAll(new Error(`MCP process exited: code=${code} signal=${signal}`));
44
+ this.process = null;
45
+ });
46
+ await this.initialize();
47
+ }
48
+ flushLines() {
49
+ const lines = this.buffer.split("\n");
50
+ this.buffer = lines.pop() ?? "";
51
+ for (const line of lines) {
52
+ const trimmed = line.trim();
53
+ if (!trimmed)
54
+ continue;
55
+ try {
56
+ const msg = JSON.parse(trimmed);
57
+ if ("id" in msg && msg.id !== undefined) {
58
+ const pending = this.pending.get(msg.id);
59
+ if (pending) {
60
+ clearTimeout(pending.timer);
61
+ this.pending.delete(msg.id);
62
+ if (msg.error) {
63
+ pending.reject(new Error(msg.error.message));
64
+ }
65
+ else {
66
+ pending.resolve(msg);
67
+ }
68
+ }
69
+ }
70
+ }
71
+ catch {
72
+ // 忽略非 JSON 行
73
+ }
74
+ }
75
+ }
76
+ rejectAll(err) {
77
+ for (const [, { reject, timer }] of this.pending) {
78
+ clearTimeout(timer);
79
+ reject(err);
80
+ }
81
+ this.pending.clear();
82
+ }
83
+ async initialize() {
84
+ const initResult = await this.request({
85
+ jsonrpc: "2.0",
86
+ id: this.nextId++,
87
+ method: "initialize",
88
+ params: {
89
+ protocolVersion: MCP_PROTOCOL_VERSION,
90
+ capabilities: {},
91
+ clientInfo: { name: "openbot", version: "0.1.0" },
92
+ },
93
+ }, this.initTimeoutMs);
94
+ if (initResult.error) {
95
+ throw new Error(`MCP initialize failed: ${initResult.error.message}`);
96
+ }
97
+ this.sendNotification({ jsonrpc: "2.0", method: "notifications/initialized" });
98
+ }
99
+ sendNotification(msg) {
100
+ if (!this.process?.stdin?.writable)
101
+ return;
102
+ this.process.stdin.write(JSON.stringify(msg) + "\n", "utf-8");
103
+ }
104
+ /** 发送 JSON-RPC 请求并等待响应 */
105
+ request(req, timeoutMs) {
106
+ return new Promise((resolve, reject) => {
107
+ if (!this.process?.stdin?.writable) {
108
+ reject(new Error("MCP transport not connected"));
109
+ return;
110
+ }
111
+ const t = timeoutMs ?? this.requestTimeoutMs;
112
+ const timer = setTimeout(() => {
113
+ if (this.pending.delete(req.id)) {
114
+ reject(new Error(`MCP request timeout (${t}ms)`));
115
+ }
116
+ }, t);
117
+ this.pending.set(req.id, { resolve, reject, timer });
118
+ this.process.stdin.write(JSON.stringify(req) + "\n", "utf-8");
119
+ });
120
+ }
121
+ /** 关闭子进程 */
122
+ async close() {
123
+ if (this.process) {
124
+ this.rejectAll(new Error("MCP transport closed"));
125
+ this.process.kill("SIGTERM");
126
+ this.process = null;
127
+ }
128
+ }
129
+ get isConnected() {
130
+ return this.process != null && this.process.stdin?.writable === true;
131
+ }
132
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * MCP (Model Context Protocol) 相关类型定义。
3
+ * 仅实现 Client 端 Tools 能力;Resources/Prompts 类型预留扩展。
4
+ */
5
+ /** stdio 传输:通过子进程 stdin/stdout 进行 JSON-RPC 通信 */
6
+ export interface McpServerConfigStdio {
7
+ transport: "stdio";
8
+ /** 可执行路径(禁止从用户输入拼接,需白名单或配置) */
9
+ command: string;
10
+ /** 命令行参数 */
11
+ args?: string[];
12
+ /** 环境变量(可选,合并到 process.env) */
13
+ env?: Record<string, string>;
14
+ }
15
+ /** SSE/HTTP 远程传输:通过 URL POST JSON-RPC 请求 */
16
+ export interface McpServerConfigSse {
17
+ transport: "sse";
18
+ /** 远程 MCP 服务地址(如 https://example.com/mcp) */
19
+ url: string;
20
+ /** 可选请求头(如 Authorization) */
21
+ headers?: Record<string, string>;
22
+ }
23
+ /** 单条 MCP 服务器配置(由调用方在创建 Session 时传入,与 Skill 类似) */
24
+ export type McpServerConfig = McpServerConfigStdio | McpServerConfigSse;
25
+ /** MCP 协议中 Tool 的 inputSchema 为 JSON Schema 对象 */
26
+ export interface McpToolInputSchema {
27
+ type?: string;
28
+ properties?: Record<string, unknown>;
29
+ required?: string[];
30
+ [key: string]: unknown;
31
+ }
32
+ /** MCP tools/list 返回的单个工具描述 */
33
+ export interface McpTool {
34
+ name: string;
35
+ description?: string;
36
+ inputSchema?: McpToolInputSchema;
37
+ }
38
+ /** MCP tools/call 返回的 content 项 */
39
+ export interface McpToolCallContentItem {
40
+ type: "text";
41
+ text: string;
42
+ }
43
+ /** MCP tools/call 的 result */
44
+ export interface McpToolCallResult {
45
+ content: McpToolCallContentItem[];
46
+ isError?: boolean;
47
+ }
48
+ /** JSON-RPC 2.0 请求 */
49
+ export interface JsonRpcRequest {
50
+ jsonrpc: "2.0";
51
+ id: number | string;
52
+ method: string;
53
+ params?: unknown;
54
+ }
55
+ /** JSON-RPC 2.0 成功响应 */
56
+ export interface JsonRpcResponse<T = unknown> {
57
+ jsonrpc: "2.0";
58
+ id: number | string;
59
+ result?: T;
60
+ error?: {
61
+ code: number;
62
+ message: string;
63
+ data?: unknown;
64
+ };
65
+ }
66
+ /** 传输层抽象:stdio / sse 等实现此接口供 McpClient 使用 */
67
+ export interface IMcpTransport {
68
+ start(): Promise<void>;
69
+ request(req: JsonRpcRequest, timeoutMs?: number): Promise<JsonRpcResponse>;
70
+ close(): Promise<void>;
71
+ readonly isConnected: boolean;
72
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * MCP (Model Context Protocol) 相关类型定义。
3
+ * 仅实现 Client 端 Tools 能力;Resources/Prompts 类型预留扩展。
4
+ */
5
+ export {};
@@ -0,0 +1,34 @@
1
+ /**
2
+ * 当前 session 使用的 agent 解析与更新、以及节点上 agent 列表提供。
3
+ * 由 Gateway 启动时注入,供 agent-chat、channel-core、以及 Core 层 switch_agent / list_agents 工具使用。
4
+ */
5
+ export type SessionCurrentAgentResolver = (sessionId: string) => string | undefined;
6
+ export type SessionCurrentAgentUpdater = (sessionId: string, agentId: string) => void;
7
+ export type AgentListProvider = () => Promise<{
8
+ id: string;
9
+ name?: string;
10
+ }[]>;
11
+ /** 创建智能体参数:由 create_agent 工具传入,缺省由工具层补齐 */
12
+ export type CreateAgentParams = {
13
+ name: string;
14
+ workspace: string;
15
+ systemPrompt?: string;
16
+ provider?: string;
17
+ model?: string;
18
+ modelItemCode?: string;
19
+ };
20
+ export type CreateAgentResult = {
21
+ id: string;
22
+ name: string;
23
+ } | {
24
+ error: string;
25
+ };
26
+ export type CreateAgentProvider = (params: CreateAgentParams) => Promise<CreateAgentResult>;
27
+ export declare function setSessionCurrentAgentResolver(fn: SessionCurrentAgentResolver | null): void;
28
+ export declare function getSessionCurrentAgentResolver(): SessionCurrentAgentResolver | null;
29
+ export declare function setSessionCurrentAgentUpdater(fn: SessionCurrentAgentUpdater | null): void;
30
+ export declare function getSessionCurrentAgentUpdater(): SessionCurrentAgentUpdater | null;
31
+ export declare function setAgentListProvider(fn: AgentListProvider | null): void;
32
+ export declare function getAgentListProvider(): AgentListProvider | null;
33
+ export declare function setCreateAgentProvider(fn: CreateAgentProvider | null): void;
34
+ export declare function getCreateAgentProvider(): CreateAgentProvider | null;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * 当前 session 使用的 agent 解析与更新、以及节点上 agent 列表提供。
3
+ * 由 Gateway 启动时注入,供 agent-chat、channel-core、以及 Core 层 switch_agent / list_agents 工具使用。
4
+ */
5
+ let resolver = null;
6
+ let updater = null;
7
+ let agentListProvider = null;
8
+ let createAgentProvider = null;
9
+ export function setSessionCurrentAgentResolver(fn) {
10
+ resolver = fn;
11
+ }
12
+ export function getSessionCurrentAgentResolver() {
13
+ return resolver;
14
+ }
15
+ export function setSessionCurrentAgentUpdater(fn) {
16
+ updater = fn;
17
+ }
18
+ export function getSessionCurrentAgentUpdater() {
19
+ return updater;
20
+ }
21
+ export function setAgentListProvider(fn) {
22
+ agentListProvider = fn;
23
+ }
24
+ export function getAgentListProvider() {
25
+ return agentListProvider;
26
+ }
27
+ export function setCreateAgentProvider(fn) {
28
+ createAgentProvider = fn;
29
+ }
30
+ export function getCreateAgentProvider() {
31
+ return createAgentProvider;
32
+ }
@@ -0,0 +1,9 @@
1
+ import type { ToolDefinition } from "@mariozechner/pi-coding-agent";
2
+ /**
3
+ * 获取当前系统中已维护的标签列表,供保存 URL 时选择匹配的标签。
4
+ */
5
+ export declare function createGetBookmarkTagsTool(): ToolDefinition;
6
+ /**
7
+ * 将 URL 保存为收藏,并关联指定标签(标签名须与 get_bookmark_tags 返回的一致)。
8
+ */
9
+ export declare function createSaveBookmarkTool(): ToolDefinition;