@roll-agent/core 0.1.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 (162) hide show
  1. package/bin/roll.js +2 -0
  2. package/dist/cli/commands/agent-add.d.ts +9 -0
  3. package/dist/cli/commands/agent-add.d.ts.map +1 -0
  4. package/dist/cli/commands/agent-add.js +123 -0
  5. package/dist/cli/commands/agent-add.js.map +1 -0
  6. package/dist/cli/commands/agent-health.d.ts +14 -0
  7. package/dist/cli/commands/agent-health.d.ts.map +1 -0
  8. package/dist/cli/commands/agent-health.js +85 -0
  9. package/dist/cli/commands/agent-health.js.map +1 -0
  10. package/dist/cli/commands/agent-info.d.ts +9 -0
  11. package/dist/cli/commands/agent-info.d.ts.map +1 -0
  12. package/dist/cli/commands/agent-info.js +32 -0
  13. package/dist/cli/commands/agent-info.js.map +1 -0
  14. package/dist/cli/commands/agent-list.d.ts +9 -0
  15. package/dist/cli/commands/agent-list.d.ts.map +1 -0
  16. package/dist/cli/commands/agent-list.js +37 -0
  17. package/dist/cli/commands/agent-list.js.map +1 -0
  18. package/dist/cli/commands/agent-remove.d.ts +9 -0
  19. package/dist/cli/commands/agent-remove.d.ts.map +1 -0
  20. package/dist/cli/commands/agent-remove.js +22 -0
  21. package/dist/cli/commands/agent-remove.js.map +1 -0
  22. package/dist/cli/commands/agent-start.d.ts +9 -0
  23. package/dist/cli/commands/agent-start.d.ts.map +1 -0
  24. package/dist/cli/commands/agent-start.js +44 -0
  25. package/dist/cli/commands/agent-start.js.map +1 -0
  26. package/dist/cli/commands/agent-stop.d.ts +9 -0
  27. package/dist/cli/commands/agent-stop.d.ts.map +1 -0
  28. package/dist/cli/commands/agent-stop.js +29 -0
  29. package/dist/cli/commands/agent-stop.js.map +1 -0
  30. package/dist/cli/commands/agent.d.ts +3 -0
  31. package/dist/cli/commands/agent.d.ts.map +1 -0
  32. package/dist/cli/commands/agent.js +14 -0
  33. package/dist/cli/commands/agent.js.map +1 -0
  34. package/dist/cli/commands/ask.d.ts +14 -0
  35. package/dist/cli/commands/ask.d.ts.map +1 -0
  36. package/dist/cli/commands/ask.js +103 -0
  37. package/dist/cli/commands/ask.js.map +1 -0
  38. package/dist/cli/commands/config.d.ts +19 -0
  39. package/dist/cli/commands/config.d.ts.map +1 -0
  40. package/dist/cli/commands/config.js +142 -0
  41. package/dist/cli/commands/config.js.map +1 -0
  42. package/dist/cli/commands/doctor.d.ts +10 -0
  43. package/dist/cli/commands/doctor.d.ts.map +1 -0
  44. package/dist/cli/commands/doctor.js +123 -0
  45. package/dist/cli/commands/doctor.js.map +1 -0
  46. package/dist/cli/commands/run.d.ts +24 -0
  47. package/dist/cli/commands/run.d.ts.map +1 -0
  48. package/dist/cli/commands/run.js +124 -0
  49. package/dist/cli/commands/run.js.map +1 -0
  50. package/dist/cli/commands/update.d.ts +12 -0
  51. package/dist/cli/commands/update.d.ts.map +1 -0
  52. package/dist/cli/commands/update.js +237 -0
  53. package/dist/cli/commands/update.js.map +1 -0
  54. package/dist/cli/index.d.ts +2 -0
  55. package/dist/cli/index.d.ts.map +1 -0
  56. package/dist/cli/index.js +31 -0
  57. package/dist/cli/index.js.map +1 -0
  58. package/dist/cli/smoke.e2e.d.ts +2 -0
  59. package/dist/cli/smoke.e2e.d.ts.map +1 -0
  60. package/dist/cli/smoke.e2e.js +57 -0
  61. package/dist/cli/smoke.e2e.js.map +1 -0
  62. package/dist/cli/utils/output.d.ts +24 -0
  63. package/dist/cli/utils/output.d.ts.map +1 -0
  64. package/dist/cli/utils/output.js +52 -0
  65. package/dist/cli/utils/output.js.map +1 -0
  66. package/dist/cli/utils/prompt.d.ts +2 -0
  67. package/dist/cli/utils/prompt.d.ts.map +1 -0
  68. package/dist/cli/utils/prompt.js +4 -0
  69. package/dist/cli/utils/prompt.js.map +1 -0
  70. package/dist/cli/utils/update-checker.d.ts +24 -0
  71. package/dist/cli/utils/update-checker.d.ts.map +1 -0
  72. package/dist/cli/utils/update-checker.js +146 -0
  73. package/dist/cli/utils/update-checker.js.map +1 -0
  74. package/dist/config/defaults.d.ts +6 -0
  75. package/dist/config/defaults.d.ts.map +1 -0
  76. package/dist/config/defaults.js +20 -0
  77. package/dist/config/defaults.js.map +1 -0
  78. package/dist/config/index.d.ts +6 -0
  79. package/dist/config/index.d.ts.map +1 -0
  80. package/dist/config/index.js +4 -0
  81. package/dist/config/index.js.map +1 -0
  82. package/dist/config/loader.d.ts +24 -0
  83. package/dist/config/loader.d.ts.map +1 -0
  84. package/dist/config/loader.js +142 -0
  85. package/dist/config/loader.js.map +1 -0
  86. package/dist/config/schema.d.ts +145 -0
  87. package/dist/config/schema.d.ts.map +1 -0
  88. package/dist/config/schema.js +24 -0
  89. package/dist/config/schema.js.map +1 -0
  90. package/dist/llm/engine.d.ts +22 -0
  91. package/dist/llm/engine.d.ts.map +1 -0
  92. package/dist/llm/engine.js +31 -0
  93. package/dist/llm/engine.js.map +1 -0
  94. package/dist/llm/index.d.ts +4 -0
  95. package/dist/llm/index.d.ts.map +1 -0
  96. package/dist/llm/index.js +3 -0
  97. package/dist/llm/index.js.map +1 -0
  98. package/dist/llm/providers.d.ts +8 -0
  99. package/dist/llm/providers.d.ts.map +1 -0
  100. package/dist/llm/providers.js +38 -0
  101. package/dist/llm/providers.js.map +1 -0
  102. package/dist/mcp/client-manager.d.ts +34 -0
  103. package/dist/mcp/client-manager.d.ts.map +1 -0
  104. package/dist/mcp/client-manager.js +79 -0
  105. package/dist/mcp/client-manager.js.map +1 -0
  106. package/dist/mcp/index.d.ts +2 -0
  107. package/dist/mcp/index.d.ts.map +1 -0
  108. package/dist/mcp/index.js +2 -0
  109. package/dist/mcp/index.js.map +1 -0
  110. package/dist/mcp/sampling-handler.d.ts +12 -0
  111. package/dist/mcp/sampling-handler.d.ts.map +1 -0
  112. package/dist/mcp/sampling-handler.js +56 -0
  113. package/dist/mcp/sampling-handler.js.map +1 -0
  114. package/dist/registry/discovery.d.ts +16 -0
  115. package/dist/registry/discovery.d.ts.map +1 -0
  116. package/dist/registry/discovery.js +72 -0
  117. package/dist/registry/discovery.js.map +1 -0
  118. package/dist/registry/health-check.d.ts +18 -0
  119. package/dist/registry/health-check.d.ts.map +1 -0
  120. package/dist/registry/health-check.js +65 -0
  121. package/dist/registry/health-check.js.map +1 -0
  122. package/dist/registry/index.d.ts +5 -0
  123. package/dist/registry/index.d.ts.map +1 -0
  124. package/dist/registry/index.js +4 -0
  125. package/dist/registry/index.js.map +1 -0
  126. package/dist/registry/process-manager.d.ts +13 -0
  127. package/dist/registry/process-manager.d.ts.map +1 -0
  128. package/dist/registry/process-manager.js +82 -0
  129. package/dist/registry/process-manager.js.map +1 -0
  130. package/dist/registry/store.d.ts +21 -0
  131. package/dist/registry/store.d.ts.map +1 -0
  132. package/dist/registry/store.js +81 -0
  133. package/dist/registry/store.js.map +1 -0
  134. package/dist/router/declarative.d.ts +8 -0
  135. package/dist/router/declarative.d.ts.map +1 -0
  136. package/dist/router/declarative.js +9 -0
  137. package/dist/router/declarative.js.map +1 -0
  138. package/dist/router/index.d.ts +3 -0
  139. package/dist/router/index.d.ts.map +1 -0
  140. package/dist/router/index.js +3 -0
  141. package/dist/router/index.js.map +1 -0
  142. package/dist/router/llm-router.d.ts +12 -0
  143. package/dist/router/llm-router.d.ts.map +1 -0
  144. package/dist/router/llm-router.js +60 -0
  145. package/dist/router/llm-router.js.map +1 -0
  146. package/dist/types/agent.d.ts +57 -0
  147. package/dist/types/agent.d.ts.map +1 -0
  148. package/dist/types/agent.js +3 -0
  149. package/dist/types/agent.js.map +1 -0
  150. package/dist/types/config.d.ts +2 -0
  151. package/dist/types/config.d.ts.map +1 -0
  152. package/dist/types/config.js +2 -0
  153. package/dist/types/config.js.map +1 -0
  154. package/dist/types/mcp.d.ts +7 -0
  155. package/dist/types/mcp.d.ts.map +1 -0
  156. package/dist/types/mcp.js +2 -0
  157. package/dist/types/mcp.js.map +1 -0
  158. package/dist/types/router.d.ts +21 -0
  159. package/dist/types/router.d.ts.map +1 -0
  160. package/dist/types/router.js +8 -0
  161. package/dist/types/router.js.map +1 -0
  162. package/package.json +47 -0
@@ -0,0 +1,79 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
3
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
4
+ import { registerSamplingHandler } from "./sampling-handler.js";
5
+ /** 默认连接超时(毫秒) */
6
+ const DEFAULT_CONNECT_TIMEOUT_MS = 30_000;
7
+ /**
8
+ * MCP Client Manager — 管理到子 Agent MCP Server 的连接。
9
+ *
10
+ * 支持两种传输模式:
11
+ * - stdio:spawn 子进程,通过 stdin/stdout 通信
12
+ * - streamable-http:连接到远程 HTTP MCP Server
13
+ *
14
+ * 连接按 agent name 缓存复用,disconnect 时清理。
15
+ */
16
+ export class McpClientManager {
17
+ connections = new Map();
18
+ /**
19
+ * 获取或创建到指定 Agent 的 MCP 连接。
20
+ *
21
+ * @param cwd 仅 stdio 模式使用,作为子进程工作目录
22
+ */
23
+ async connect(agentName, transport, cwd, options = {}) {
24
+ const existing = this.connections.get(agentName);
25
+ if (existing) {
26
+ return existing.client;
27
+ }
28
+ const timeoutMs = options.timeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;
29
+ const samplingCapabilities = options.samplingModel ? { sampling: {} } : {};
30
+ const client = new Client({ name: `roll-client-${agentName}`, version: "0.0.1" }, { capabilities: samplingCapabilities });
31
+ // 注册 Sampling Handler(子 Agent 可通过 createMessage 使用指挥官 LLM)
32
+ if (options.samplingModel) {
33
+ registerSamplingHandler(client, options.samplingModel);
34
+ }
35
+ // 创建 MCP 传输(强制转换为 Transport 以绕过 exactOptionalPropertyTypes 与库类型的不兼容)
36
+ const mcpTransport = transport.type === "streamable-http"
37
+ ? new StreamableHTTPClientTransport(new URL(transport.endpoint))
38
+ : new StdioClientTransport({
39
+ command: transport.command,
40
+ args: [...(transport.args ?? [])],
41
+ cwd,
42
+ });
43
+ const connectPromise = client.connect(mcpTransport);
44
+ let timeoutId;
45
+ const timeoutPromise = new Promise((_resolve, reject) => {
46
+ timeoutId = setTimeout(() => reject(new Error(`Connection to "${agentName}" timed out after ${timeoutMs}ms`)), timeoutMs);
47
+ });
48
+ try {
49
+ await Promise.race([connectPromise, timeoutPromise]);
50
+ }
51
+ catch (err) {
52
+ await client.close().catch(() => { });
53
+ throw err;
54
+ }
55
+ finally {
56
+ clearTimeout(timeoutId);
57
+ }
58
+ this.connections.set(agentName, { client, transportType: transport.type });
59
+ return client;
60
+ }
61
+ /** 断开指定 Agent 的连接 */
62
+ async disconnect(agentName) {
63
+ const conn = this.connections.get(agentName);
64
+ if (!conn)
65
+ return;
66
+ await conn.client.close();
67
+ this.connections.delete(agentName);
68
+ }
69
+ /** 断开所有连接 */
70
+ async disconnectAll() {
71
+ const names = [...this.connections.keys()];
72
+ await Promise.all(names.map((name) => this.disconnect(name)));
73
+ }
74
+ /** 检查是否已连接 */
75
+ isConnected(agentName) {
76
+ return this.connections.has(agentName);
77
+ }
78
+ }
79
+ //# sourceMappingURL=client-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-manager.js","sourceRoot":"","sources":["../../src/mcp/client-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { McpClientManager } from "./client-manager.ts";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { McpClientManager } from "./client-manager.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import type { LanguageModelV3 } from "@ai-sdk/provider";
3
+ /**
4
+ * 在 MCP Client 上注册 Sampling Handler。
5
+ *
6
+ * 当子 Agent(MCP Server)调用 `createMessage` 请求 LLM 推理时,
7
+ * 该 handler 使用指挥官的 LLM Engine 完成推理并返回结果。
8
+ *
9
+ * @see https://spec.modelcontextprotocol.io/specification/client/sampling/
10
+ */
11
+ export declare function registerSamplingHandler(client: Client, model: LanguageModelV3): void;
12
+ //# sourceMappingURL=sampling-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sampling-handler.d.ts","sourceRoot":"","sources":["../../src/mcp/sampling-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAKxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAuBpF"}
@@ -0,0 +1,56 @@
1
+ import { CreateMessageRequestSchema } from "@modelcontextprotocol/sdk/types.js";
2
+ import { generateText } from "ai";
3
+ /**
4
+ * 在 MCP Client 上注册 Sampling Handler。
5
+ *
6
+ * 当子 Agent(MCP Server)调用 `createMessage` 请求 LLM 推理时,
7
+ * 该 handler 使用指挥官的 LLM Engine 完成推理并返回结果。
8
+ *
9
+ * @see https://spec.modelcontextprotocol.io/specification/client/sampling/
10
+ */
11
+ export function registerSamplingHandler(client, model) {
12
+ client.setRequestHandler(CreateMessageRequestSchema, async (request) => {
13
+ const messages = convertToModelMessages(request.params.messages);
14
+ const maxTokens = request.params.maxTokens;
15
+ let result;
16
+ try {
17
+ result = await generateText({
18
+ model,
19
+ messages,
20
+ ...(maxTokens > 0 ? { maxOutputTokens: maxTokens } : {}),
21
+ });
22
+ }
23
+ catch (error) {
24
+ throw new Error("Sampling handler: LLM generation failed", { cause: error });
25
+ }
26
+ return {
27
+ role: "assistant",
28
+ content: { type: "text", text: result.text },
29
+ model: result.response.modelId,
30
+ ...(result.finishReason === "length" ? { stopReason: "maxTokens" } : { stopReason: "endTurn" }),
31
+ };
32
+ });
33
+ }
34
+ /** 将 MCP SamplingMessage[] 转换为 AI SDK ModelMessage[] */
35
+ function convertToModelMessages(messages) {
36
+ return messages.map((msg) => {
37
+ const text = extractTextContent(msg.content);
38
+ if (msg.role === "assistant") {
39
+ return { role: "assistant", content: [{ type: "text", text }] };
40
+ }
41
+ return { role: "user", content: [{ type: "text", text }] };
42
+ });
43
+ }
44
+ /** 从 MCP content union 中提取文本 */
45
+ function extractTextContent(content) {
46
+ if (typeof content === "string")
47
+ return content;
48
+ if (typeof content === "object" && content !== null && "type" in content) {
49
+ const typed = content;
50
+ if (typed.type === "text" && typeof typed.text === "string") {
51
+ return typed.text;
52
+ }
53
+ }
54
+ return JSON.stringify(content);
55
+ }
56
+ //# sourceMappingURL=sampling-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sampling-handler.js","sourceRoot":"","sources":["../../src/mcp/sampling-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAEhF,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAIlC;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc,EAAE,KAAsB;IAC5E,MAAM,CAAC,iBAAiB,CAAC,0BAA0B,EAAE,KAAK,EAAE,OAAO,EAAgC,EAAE;QACnG,MAAM,QAAQ,GAAG,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjE,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;QAE3C,IAAI,MAAM,CAAC;QACX,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,YAAY,CAAC;gBAC1B,KAAK;gBACL,QAAQ;gBACR,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACzD,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,yCAAyC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,CAAC;QAED,OAAO;YACL,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE;YAC5C,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO;YAC9B,GAAG,CAAC,MAAM,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;SAChG,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,wDAAwD;AACxD,SAAS,sBAAsB,CAC7B,QAA6E;IAE7E,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAgB,EAAE;QACxC,MAAM,IAAI,GAAG,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE7C,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC7B,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAClE,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,gCAAgC;AAChC,SAAS,kBAAkB,CAAC,OAAgB;IAC1C,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAEhD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,MAAM,IAAI,OAAO,EAAE,CAAC;QACzE,MAAM,KAAK,GAAG,OAA0C,CAAC;QACzD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5D,OAAO,KAAK,CAAC,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { AgentSkill, AgentTransport } from "../types/agent.ts";
2
+ /** SKILL.md 解析结果 */
3
+ export interface DiscoveredAgent {
4
+ readonly skill: AgentSkill;
5
+ readonly transport: AgentTransport;
6
+ readonly skillPath: string;
7
+ /** SKILL.md body 内容(frontmatter 之后的 markdown 部分) */
8
+ readonly skillBody: string;
9
+ }
10
+ /**
11
+ * 解析指定目录下的 SKILL.md,提取 Agent 描述和传输配置。
12
+ *
13
+ * @throws 找不到 SKILL.md 或缺少必需字段时抛出错误
14
+ */
15
+ export declare function discoverAgent(agentDir: string): DiscoveredAgent;
16
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/registry/discovery.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEpE,oBAAoB;AACpB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,oDAAoD;IACpD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAKD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CA6C/D"}
@@ -0,0 +1,72 @@
1
+ import { readFileSync, existsSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import matter from "gray-matter";
4
+ /** SKILL.md 文件名 */
5
+ const SKILL_FILE_NAME = "SKILL.md";
6
+ /**
7
+ * 解析指定目录下的 SKILL.md,提取 Agent 描述和传输配置。
8
+ *
9
+ * @throws 找不到 SKILL.md 或缺少必需字段时抛出错误
10
+ */
11
+ export function discoverAgent(agentDir) {
12
+ const absDir = resolve(agentDir);
13
+ const skillPath = resolve(absDir, SKILL_FILE_NAME);
14
+ if (!existsSync(skillPath)) {
15
+ throw new Error(`SKILL.md not found in ${absDir}`);
16
+ }
17
+ const raw = readFileSync(skillPath, "utf-8");
18
+ const { data, content: skillBody } = matter(raw);
19
+ // 校验必需字段
20
+ const frontmatter = data;
21
+ const name = frontmatter["name"];
22
+ const description = frontmatter["description"];
23
+ if (typeof name !== "string" || name.length === 0) {
24
+ throw new Error(`SKILL.md missing required field "name" in ${skillPath}`);
25
+ }
26
+ if (typeof description !== "string" || description.length === 0) {
27
+ throw new Error(`SKILL.md missing required field "description" in ${skillPath}`);
28
+ }
29
+ // 提取 metadata
30
+ const rawMetadata = (frontmatter["metadata"] ?? {});
31
+ const metadata = {};
32
+ for (const [key, value] of Object.entries(rawMetadata)) {
33
+ metadata[key] = String(value);
34
+ }
35
+ const skill = {
36
+ name,
37
+ description,
38
+ ...(typeof frontmatter["license"] === "string" ? { license: frontmatter["license"] } : {}),
39
+ ...(typeof frontmatter["compatibility"] === "string"
40
+ ? { compatibility: frontmatter["compatibility"] }
41
+ : {}),
42
+ metadata,
43
+ };
44
+ // 从 metadata 中解析 Roll 扩展字段,直接通过字段访问收窄类型
45
+ const transport = resolveTransport(metadata);
46
+ return { skill, transport, skillPath, skillBody: skillBody.trim() };
47
+ }
48
+ /** 根据 SKILL.md metadata 确定传输模式 */
49
+ function resolveTransport(meta) {
50
+ const rawTransport = meta["roll-transport"];
51
+ const transportType = rawTransport === "streamable-http" ? "streamable-http" : "stdio";
52
+ if (transportType === "streamable-http") {
53
+ const endpoint = meta["roll-endpoint"];
54
+ if (!endpoint) {
55
+ throw new Error(`SKILL.md declares streamable-http transport but missing "roll-endpoint"`);
56
+ }
57
+ return { type: "streamable-http", endpoint };
58
+ }
59
+ // stdio 模式:使用 roll-command 或默认 node 启动
60
+ const command = meta["roll-command"] ?? "node --experimental-strip-types src/index.ts";
61
+ const parts = command.split(/\s+/);
62
+ const executable = parts[0];
63
+ const args = parts.slice(1);
64
+ if (!executable) {
65
+ throw new Error(`Invalid roll-command in SKILL.md`);
66
+ }
67
+ if (args.length > 0) {
68
+ return { type: "stdio", command: executable, args };
69
+ }
70
+ return { type: "stdio", command: executable };
71
+ }
72
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/registry/discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { AgentStore } from "./store.ts";
2
+ /** 健康检查结果 */
3
+ export interface HealthCheckResult {
4
+ readonly agentName: string;
5
+ readonly healthy: boolean;
6
+ readonly restarted: boolean;
7
+ readonly message: string;
8
+ }
9
+ /**
10
+ * 检查所有状态为 "online" 的 Agent 是否仍在运行。
11
+ *
12
+ * - 如果进程已死且 autoRestart 为 true,尝试自动重启
13
+ * - 更新 store 中的 Agent 状态
14
+ */
15
+ export declare function checkAgentHealth(store: AgentStore, dataDir: string, options?: {
16
+ readonly autoRestart: boolean;
17
+ }): ReadonlyArray<HealthCheckResult>;
18
+ //# sourceMappingURL=health-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health-check.d.ts","sourceRoot":"","sources":["../../src/registry/health-check.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,aAAa;AACb,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;CAA2B,GAClE,aAAa,CAAC,iBAAiB,CAAC,CAsClC"}
@@ -0,0 +1,65 @@
1
+ import { getAgentPid, startAgent } from "./process-manager.js";
2
+ /**
3
+ * 检查所有状态为 "online" 的 Agent 是否仍在运行。
4
+ *
5
+ * - 如果进程已死且 autoRestart 为 true,尝试自动重启
6
+ * - 更新 store 中的 Agent 状态
7
+ */
8
+ export function checkAgentHealth(store, dataDir, options = { autoRestart: false }) {
9
+ const agents = store.list();
10
+ const results = [];
11
+ for (const agent of agents) {
12
+ // 只检查 stdio 模式且预期在线的 Agent
13
+ if (agent.transport.type !== "stdio" || agent.status !== "online") {
14
+ continue;
15
+ }
16
+ const pid = getAgentPid(dataDir, agent.skill.name);
17
+ if (pid !== undefined) {
18
+ results.push({
19
+ agentName: agent.skill.name,
20
+ healthy: true,
21
+ restarted: false,
22
+ message: `运行中 (PID: ${String(pid)})`,
23
+ });
24
+ continue;
25
+ }
26
+ // 进程已死
27
+ if (options.autoRestart) {
28
+ const restarted = tryRestart(agent, store, dataDir);
29
+ results.push(restarted);
30
+ }
31
+ else {
32
+ store.updateStatus(agent.skill.name, "error");
33
+ results.push({
34
+ agentName: agent.skill.name,
35
+ healthy: false,
36
+ restarted: false,
37
+ message: "进程已退出,状态更新为 error",
38
+ });
39
+ }
40
+ }
41
+ return results;
42
+ }
43
+ /** 尝试重启 Agent */
44
+ function tryRestart(agent, store, dataDir) {
45
+ try {
46
+ const newPid = startAgent(agent, dataDir);
47
+ store.updateStatus(agent.skill.name, "online");
48
+ return {
49
+ agentName: agent.skill.name,
50
+ healthy: true,
51
+ restarted: true,
52
+ message: `已自动重启 (PID: ${String(newPid)})`,
53
+ };
54
+ }
55
+ catch (err) {
56
+ store.updateStatus(agent.skill.name, "error");
57
+ return {
58
+ agentName: agent.skill.name,
59
+ healthy: false,
60
+ restarted: false,
61
+ message: `重启失败: ${err instanceof Error ? err.message : String(err)}`,
62
+ };
63
+ }
64
+ }
65
+ //# sourceMappingURL=health-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health-check.js","sourceRoot":"","sources":["../../src/registry/health-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAY/D;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAiB,EACjB,OAAe,EACf,UAA6C,EAAE,WAAW,EAAE,KAAK,EAAE;IAEnE,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAwB,EAAE,CAAC;IAExC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,2BAA2B;QAC3B,IAAI,KAAK,CAAC,SAAS,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAClE,SAAS;QACX,CAAC;QAED,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEnD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC;gBACX,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI;gBAC3B,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,KAAK;gBAChB,OAAO,EAAE,aAAa,MAAM,CAAC,GAAG,CAAC,GAAG;aACrC,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,OAAO;QACP,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACxB,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,CAAC,IAAI,CAAC;gBACX,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI;gBAC3B,OAAO,EAAE,KAAK;gBACd,SAAS,EAAE,KAAK;gBAChB,OAAO,EAAE,mBAAmB;aAC7B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,iBAAiB;AACjB,SAAS,UAAU,CAAC,KAAsB,EAAE,KAAiB,EAAE,OAAe;IAC5E,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC1C,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC/C,OAAO;YACL,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI;YAC3B,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,eAAe,MAAM,CAAC,MAAM,CAAC,GAAG;SAC1C,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9C,OAAO;YACL,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI;YAC3B,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,SAAS,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SACrE,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { discoverAgent } from "./discovery.ts";
2
+ export type { DiscoveredAgent } from "./discovery.ts";
3
+ export { AgentStore } from "./store.ts";
4
+ export { startAgent, stopAgent, getAgentPid } from "./process-manager.ts";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { discoverAgent } from "./discovery.js";
2
+ export { AgentStore } from "./store.js";
3
+ export { startAgent, stopAgent, getAgentPid } from "./process-manager.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { RegisteredAgent } from "../types/agent.ts";
2
+ /** 读取 Agent 的 PID,如果不存在或进程已死则返回 undefined */
3
+ export declare function getAgentPid(dataDir: string, agentName: string): number | undefined;
4
+ /**
5
+ * 启动一个 Agent 为后台进程(detached)。
6
+ *
7
+ * 仅对 stdio 模式有意义——后台运行 MCP Server。
8
+ * Streamable HTTP Agent 应由用户自行管理(独立服务)。
9
+ */
10
+ export declare function startAgent(agent: RegisteredAgent, dataDir: string): number;
11
+ /** 停止一个后台运行的 Agent */
12
+ export declare function stopAgent(dataDir: string, agentName: string): boolean;
13
+ //# sourceMappingURL=process-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../../src/registry/process-manager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAiBzD,6CAA6C;AAC7C,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAWlF;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAkC1E;AAED,sBAAsB;AACtB,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAiBrE"}
@@ -0,0 +1,82 @@
1
+ import { spawn } from "node:child_process";
2
+ import { readFileSync, writeFileSync, existsSync, unlinkSync, mkdirSync } from "node:fs";
3
+ import { resolve, dirname } from "node:path";
4
+ /** PID 文件存放目录 */
5
+ function pidFilePath(dataDir, agentName) {
6
+ return resolve(dataDir, "pids", `${agentName}.pid`);
7
+ }
8
+ /** 检查进程是否仍在运行 */
9
+ function isProcessAlive(pid) {
10
+ try {
11
+ process.kill(pid, 0);
12
+ return true;
13
+ }
14
+ catch {
15
+ return false;
16
+ }
17
+ }
18
+ /** 读取 Agent 的 PID,如果不存在或进程已死则返回 undefined */
19
+ export function getAgentPid(dataDir, agentName) {
20
+ const pidFile = pidFilePath(dataDir, agentName);
21
+ if (!existsSync(pidFile))
22
+ return undefined;
23
+ const pid = Number(readFileSync(pidFile, "utf-8").trim());
24
+ if (Number.isNaN(pid) || !isProcessAlive(pid)) {
25
+ // 清理过期的 PID 文件
26
+ unlinkSync(pidFile);
27
+ return undefined;
28
+ }
29
+ return pid;
30
+ }
31
+ /**
32
+ * 启动一个 Agent 为后台进程(detached)。
33
+ *
34
+ * 仅对 stdio 模式有意义——后台运行 MCP Server。
35
+ * Streamable HTTP Agent 应由用户自行管理(独立服务)。
36
+ */
37
+ export function startAgent(agent, dataDir) {
38
+ if (agent.transport.type === "streamable-http") {
39
+ throw new Error(`Agent "${agent.skill.name}" 使用 streamable-http 传输,请手动启动服务。` +
40
+ `\n 端点: ${agent.transport.endpoint}`);
41
+ }
42
+ const existingPid = getAgentPid(dataDir, agent.skill.name);
43
+ if (existingPid !== undefined) {
44
+ throw new Error(`Agent "${agent.skill.name}" 已在运行 (PID: ${String(existingPid)})`);
45
+ }
46
+ const child = spawn(agent.transport.command, [...(agent.transport.args ?? [])], {
47
+ cwd: agent.installPath,
48
+ detached: true,
49
+ stdio: "ignore",
50
+ });
51
+ child.unref();
52
+ if (!child.pid) {
53
+ throw new Error(`Failed to start agent "${agent.skill.name}"`);
54
+ }
55
+ // 写入 PID 文件
56
+ const pidFile = pidFilePath(dataDir, agent.skill.name);
57
+ const pidDir = dirname(pidFile);
58
+ if (!existsSync(pidDir)) {
59
+ mkdirSync(pidDir, { recursive: true });
60
+ }
61
+ writeFileSync(pidFile, String(child.pid), "utf-8");
62
+ return child.pid;
63
+ }
64
+ /** 停止一个后台运行的 Agent */
65
+ export function stopAgent(dataDir, agentName) {
66
+ const pid = getAgentPid(dataDir, agentName);
67
+ if (pid === undefined)
68
+ return false;
69
+ try {
70
+ process.kill(pid, "SIGTERM");
71
+ }
72
+ catch {
73
+ // 进程可能已退出
74
+ }
75
+ // 清理 PID 文件
76
+ const pidFile = pidFilePath(dataDir, agentName);
77
+ if (existsSync(pidFile)) {
78
+ unlinkSync(pidFile);
79
+ }
80
+ return true;
81
+ }
82
+ //# sourceMappingURL=process-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-manager.js","sourceRoot":"","sources":["../../src/registry/process-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { RegisteredAgent } from "../types/agent.ts";
2
+ /** Agent Store — 管理已注册 Agent 的持久化存储(JSON 文件) */
3
+ export declare class AgentStore {
4
+ private readonly storePath;
5
+ constructor(dataDir: string);
6
+ /** 读取所有已注册 Agent */
7
+ list(): ReadonlyArray<RegisteredAgent>;
8
+ /** 根据名称查找 Agent */
9
+ findByName(name: string): RegisteredAgent | undefined;
10
+ /** 添加一个 Agent(名称重复则抛错) */
11
+ add(agent: RegisteredAgent): void;
12
+ /** 根据名称移除 Agent */
13
+ remove(name: string): boolean;
14
+ /** 原子替换指定 Agent(名称可变更) */
15
+ replace(name: string, next: RegisteredAgent): boolean;
16
+ /** 更新指定 Agent 的状态 */
17
+ updateStatus(name: string, status: RegisteredAgent["status"]): void;
18
+ /** 写入存储文件 */
19
+ private save;
20
+ }
21
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/registry/store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAKzD,gDAAgD;AAChD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,OAAO,EAAE,MAAM;IAI3B,oBAAoB;IACpB,IAAI,IAAI,aAAa,CAAC,eAAe,CAAC;IAoBtC,mBAAmB;IACnB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAIrD,0BAA0B;IAC1B,GAAG,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAYjC,mBAAmB;IACnB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAY7B,0BAA0B;IAC1B,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO;IAiBrD,qBAAqB;IACrB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,GAAG,IAAI;IAOnE,aAAa;IACb,OAAO,CAAC,IAAI;CAOb"}
@@ -0,0 +1,81 @@
1
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
2
+ import { resolve, dirname } from "node:path";
3
+ /** 持久化存储文件名 */
4
+ const STORE_FILE = "agents.json";
5
+ /** Agent Store — 管理已注册 Agent 的持久化存储(JSON 文件) */
6
+ export class AgentStore {
7
+ storePath;
8
+ constructor(dataDir) {
9
+ this.storePath = resolve(dataDir, STORE_FILE);
10
+ }
11
+ /** 读取所有已注册 Agent */
12
+ list() {
13
+ if (!existsSync(this.storePath)) {
14
+ return [];
15
+ }
16
+ let parsed;
17
+ try {
18
+ const raw = readFileSync(this.storePath, "utf-8");
19
+ parsed = JSON.parse(raw);
20
+ }
21
+ catch {
22
+ return [];
23
+ }
24
+ if (!Array.isArray(parsed)) {
25
+ return [];
26
+ }
27
+ return parsed;
28
+ }
29
+ /** 根据名称查找 Agent */
30
+ findByName(name) {
31
+ return this.list().find((agent) => agent.skill.name === name);
32
+ }
33
+ /** 添加一个 Agent(名称重复则抛错) */
34
+ add(agent) {
35
+ const agents = [...this.list()];
36
+ const existing = agents.findIndex((a) => a.skill.name === agent.skill.name);
37
+ if (existing !== -1) {
38
+ throw new Error(`Agent "${agent.skill.name}" is already registered`);
39
+ }
40
+ agents.push(agent);
41
+ this.save(agents);
42
+ }
43
+ /** 根据名称移除 Agent */
44
+ remove(name) {
45
+ const agents = this.list();
46
+ const filtered = agents.filter((a) => a.skill.name !== name);
47
+ if (filtered.length === agents.length) {
48
+ return false;
49
+ }
50
+ this.save([...filtered]);
51
+ return true;
52
+ }
53
+ /** 原子替换指定 Agent(名称可变更) */
54
+ replace(name, next) {
55
+ const agents = [...this.list()];
56
+ const targetIndex = agents.findIndex((a) => a.skill.name === name);
57
+ if (targetIndex === -1)
58
+ return false;
59
+ const conflictIndex = agents.findIndex((a, index) => index !== targetIndex && a.skill.name === next.skill.name);
60
+ if (conflictIndex !== -1) {
61
+ throw new Error(`Agent "${next.skill.name}" is already registered`);
62
+ }
63
+ agents[targetIndex] = next;
64
+ this.save(agents);
65
+ return true;
66
+ }
67
+ /** 更新指定 Agent 的状态 */
68
+ updateStatus(name, status) {
69
+ const agents = this.list().map((a) => a.skill.name === name ? { ...a, status } : a);
70
+ this.save([...agents]);
71
+ }
72
+ /** 写入存储文件 */
73
+ save(agents) {
74
+ const dir = dirname(this.storePath);
75
+ if (!existsSync(dir)) {
76
+ mkdirSync(dir, { recursive: true });
77
+ }
78
+ writeFileSync(this.storePath, JSON.stringify(agents, null, 2), "utf-8");
79
+ }
80
+ }
81
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/registry/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { RegisteredAgent } from "../types/agent.ts";
2
+ /**
3
+ * 声明式路由:按名称直接查找 Agent。
4
+ *
5
+ * 用于 `roll run <agent> <tool>` 场景,不涉及 LLM。
6
+ */
7
+ export declare function resolveAgent(agentName: string, agents: ReadonlyArray<RegisteredAgent>): RegisteredAgent | undefined;
8
+ //# sourceMappingURL=declarative.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declarative.d.ts","sourceRoot":"","sources":["../../src/router/declarative.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,GACrC,eAAe,GAAG,SAAS,CAE7B"}