@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,237 @@
1
+ import { defineCommand } from "citty";
2
+ import { resolve } from "node:path";
3
+ import { existsSync } from "node:fs";
4
+ import { execFile } from "node:child_process";
5
+ import { promisify } from "node:util";
6
+ import { loadConfig } from "../../config/loader.js";
7
+ import { AgentStore } from "../../registry/store.js";
8
+ import { discoverAgent } from "../../registry/discovery.js";
9
+ import { McpClientManager } from "../../mcp/client-manager.js";
10
+ import { log, createSpinner } from "../utils/output.js";
11
+ import { checkForUpdate, getCurrentVersion, } from "../utils/update-checker.js";
12
+ const execFileAsync = promisify(execFile);
13
+ /** 推断旧 Agent(无 source 字段)的来源类型 */
14
+ export function inferSourceType(agent) {
15
+ if (agent.source) {
16
+ if (agent.source.type === "git")
17
+ return "git";
18
+ if (agent.source.type === "local")
19
+ return "local";
20
+ return "remote";
21
+ }
22
+ // 旧数据兼容:检查 installPath 下是否有 .git 目录
23
+ if (agent.transport.type === "streamable-http")
24
+ return "remote";
25
+ if (existsSync(resolve(agent.installPath, ".git")))
26
+ return "git";
27
+ return "local";
28
+ }
29
+ /** 更新 roll-core 自身 */
30
+ async function updateSelf(latest, dryRun) {
31
+ const current = getCurrentVersion();
32
+ if (current === latest) {
33
+ log.info(`roll 已是最新版本 (v${current})`);
34
+ return false;
35
+ }
36
+ log.info(`roll v${current} → v${latest}`);
37
+ if (dryRun) {
38
+ log.info("[dry-run] 跳过实际更新");
39
+ return true;
40
+ }
41
+ const spinner = createSpinner("正在更新 @roll-agent/core...").start();
42
+ try {
43
+ await execFileAsync("npm", ["install", "-g", `@roll-agent/core@${latest}`], {
44
+ timeout: 60_000,
45
+ });
46
+ spinner.succeed(`roll 已更新到 v${latest}`);
47
+ return true;
48
+ }
49
+ catch (err) {
50
+ spinner.fail("更新失败");
51
+ log.error(err instanceof Error ? err.message : String(err));
52
+ return false;
53
+ }
54
+ }
55
+ /** 更新 git 来源的 Agent */
56
+ async function updateGitAgent(agent) {
57
+ const spinner = createSpinner(`更新 ${agent.skill.name} (git pull)...`).start();
58
+ try {
59
+ await execFileAsync("git", ["pull"], { cwd: agent.installPath, timeout: 30_000 });
60
+ spinner.succeed(`${agent.skill.name} 代码已更新`);
61
+ // 重新安装依赖
62
+ const packageJsonPath = resolve(agent.installPath, "package.json");
63
+ if (existsSync(packageJsonPath)) {
64
+ const depSpinner = createSpinner(`安装 ${agent.skill.name} 依赖...`).start();
65
+ try {
66
+ await execFileAsync("pnpm", ["install"], { cwd: agent.installPath, timeout: 60_000 });
67
+ depSpinner.succeed(`${agent.skill.name} 依赖已更新`);
68
+ }
69
+ catch (err) {
70
+ depSpinner.fail(`${agent.skill.name} 依赖安装失败`);
71
+ log.error(err instanceof Error ? err.message : String(err));
72
+ return false;
73
+ }
74
+ }
75
+ return true;
76
+ }
77
+ catch (err) {
78
+ spinner.fail(`${agent.skill.name} 更新失败`);
79
+ log.error(err instanceof Error ? err.message : String(err));
80
+ return false;
81
+ }
82
+ }
83
+ /** 刷新远程 Agent 的 MCP 元数据 */
84
+ async function refreshRemoteAgent(agent) {
85
+ const spinner = createSpinner(`刷新 ${agent.skill.name} (MCP tools/list)...`).start();
86
+ const manager = new McpClientManager();
87
+ try {
88
+ const client = await manager.connect(agent.skill.name, agent.transport, agent.installPath);
89
+ const { tools } = await client.listTools();
90
+ spinner.succeed(`${agent.skill.name} 元数据已刷新(${tools.length} 个 tool)`);
91
+ return true;
92
+ }
93
+ catch (err) {
94
+ spinner.fail(`${agent.skill.name} 刷新失败`);
95
+ log.error(err instanceof Error ? err.message : String(err));
96
+ return false;
97
+ }
98
+ finally {
99
+ await manager.disconnectAll();
100
+ }
101
+ }
102
+ export default defineCommand({
103
+ meta: { description: "更新 roll 及已注册的 Agent" },
104
+ args: {
105
+ check: {
106
+ type: "boolean",
107
+ description: "仅检查可用更新,不执行",
108
+ default: false,
109
+ },
110
+ },
111
+ async run({ args }) {
112
+ const isCheckOnly = args.check;
113
+ // === 1. 检查 roll-core 自身 ===
114
+ log.info("检查 roll 更新...");
115
+ const info = await checkForUpdate({ forceRefresh: true });
116
+ if (info.hasUpdate) {
117
+ log.success(`roll 有新版本: v${info.current} → v${info.latest}`);
118
+ }
119
+ else {
120
+ log.info(`roll 已是最新版本 (v${info.current})`);
121
+ }
122
+ // === 2. 检查已注册 Agent ===
123
+ const { config } = loadConfig();
124
+ const store = new AgentStore(config.agents.dataDir);
125
+ const agents = store.list();
126
+ const agentSummary = [];
127
+ for (const agent of agents) {
128
+ const sourceType = inferSourceType(agent);
129
+ let action;
130
+ switch (sourceType) {
131
+ case "git":
132
+ action = "git pull + 重新安装依赖";
133
+ break;
134
+ case "remote":
135
+ action = "刷新 MCP 元数据 (tools/list)";
136
+ break;
137
+ case "local":
138
+ action = "跳过(本地 Agent 请手动更新)";
139
+ break;
140
+ }
141
+ agentSummary.push({ name: agent.skill.name, sourceType, action });
142
+ }
143
+ if (agents.length > 0) {
144
+ log.info(`\n已注册 Agent (${agents.length}):`);
145
+ for (const s of agentSummary) {
146
+ const tag = s.sourceType === "local" ? "⏭" : "⬆";
147
+ log.info(` ${tag} ${s.name} [${s.sourceType}] — ${s.action}`);
148
+ }
149
+ }
150
+ else {
151
+ log.info("无已注册 Agent");
152
+ }
153
+ // --check 模式到此结束
154
+ if (isCheckOnly)
155
+ return;
156
+ // === 3. 执行更新 ===
157
+ log.info("");
158
+ // 3a. 更新 roll-core
159
+ let selfUpdated = false;
160
+ let selfUpdateFailed = false;
161
+ if (info.hasUpdate) {
162
+ selfUpdated = await updateSelf(info.latest, false);
163
+ if (!selfUpdated)
164
+ selfUpdateFailed = true;
165
+ }
166
+ // 3b. 更新 Agent
167
+ let updatedCount = 0;
168
+ let skippedCount = 0;
169
+ let failedCount = 0;
170
+ for (const agent of agents) {
171
+ const sourceType = inferSourceType(agent);
172
+ switch (sourceType) {
173
+ case "git": {
174
+ const ok = await updateGitAgent(agent);
175
+ if (ok) {
176
+ // 重新解析 SKILL.md 并更新 store
177
+ try {
178
+ const discovered = discoverAgent(agent.installPath);
179
+ const updated = {
180
+ ...agent,
181
+ skill: discovered.skill,
182
+ transport: discovered.transport,
183
+ ...(discovered.skillBody.length > 0 ? { skillBody: discovered.skillBody } : {}),
184
+ };
185
+ const replaced = store.replace(agent.skill.name, updated);
186
+ if (!replaced) {
187
+ log.warn(`${agent.skill.name} 已从注册表中移除,跳过元数据刷新`);
188
+ }
189
+ }
190
+ catch (err) {
191
+ log.warn(`${agent.skill.name} SKILL.md 重新解析失败: ${err instanceof Error ? err.message : String(err)}`);
192
+ }
193
+ updatedCount++;
194
+ }
195
+ else {
196
+ failedCount++;
197
+ }
198
+ break;
199
+ }
200
+ case "remote": {
201
+ const ok = await refreshRemoteAgent(agent);
202
+ if (ok) {
203
+ updatedCount++;
204
+ }
205
+ else {
206
+ failedCount++;
207
+ }
208
+ break;
209
+ }
210
+ case "local":
211
+ log.warn(`${agent.skill.name} 是本地 Agent,请手动更新后运行 roll agent add <path> 重新注册`);
212
+ skippedCount++;
213
+ break;
214
+ }
215
+ }
216
+ // === 4. 总结 ===
217
+ log.info("");
218
+ const totalFailed = failedCount + (selfUpdateFailed ? 1 : 0);
219
+ if (totalFailed > 0) {
220
+ process.exitCode = 1;
221
+ const rollStatus = selfUpdateFailed
222
+ ? "roll 更新失败"
223
+ : selfUpdated
224
+ ? "roll ✓"
225
+ : "roll 无更新";
226
+ log.warn(`更新完成但有失败:${rollStatus}${failedCount > 0 ? `,${failedCount} 个 Agent 更新失败` : ""}${updatedCount > 0 ? `,${updatedCount} 个 Agent 已更新` : ""}${skippedCount > 0 ? `,${skippedCount} 个已跳过` : ""}`);
227
+ return;
228
+ }
229
+ if (selfUpdated || updatedCount > 0) {
230
+ log.success(`更新完成:${selfUpdated ? "roll ✓" : "roll 无更新"}${updatedCount > 0 ? `,${updatedCount} 个 Agent 已更新` : ""}${skippedCount > 0 ? `,${skippedCount} 个已跳过` : ""}`);
231
+ }
232
+ else {
233
+ log.success("一切都已是最新版本");
234
+ }
235
+ },
236
+ });
237
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../../src/cli/commands/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,cAAc,EACd,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AAGpC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,kCAAkC;AAClC,MAAM,UAAU,eAAe,CAC7B,KAAsB;IAEtB,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC;QAC9C,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,OAAO,CAAC;QAClD,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,oCAAoC;IACpC,IAAI,KAAK,CAAC,SAAS,CAAC,IAAI,KAAK,iBAAiB;QAAE,OAAO,QAAQ,CAAC;IAChE,IAAI,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACjE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,sBAAsB;AACtB,KAAK,UAAU,UAAU,CAAC,MAAc,EAAE,MAAe;IACvD,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAC;IACpC,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,GAAG,CAAC,IAAI,CAAC,iBAAiB,OAAO,GAAG,CAAC,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,SAAS,OAAO,OAAO,MAAM,EAAE,CAAC,CAAC;IAC1C,IAAI,MAAM,EAAE,CAAC;QACX,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,aAAa,CAAC,0BAA0B,CAAC,CAAC,KAAK,EAAE,CAAC;IAClE,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,oBAAoB,MAAM,EAAE,CAAC,EAAE;YAC1E,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC;QACH,OAAO,CAAC,OAAO,CAAC,cAAc,MAAM,EAAE,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,GAAG,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5D,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,uBAAuB;AACvB,KAAK,UAAU,cAAc,CAAC,KAAsB;IAClD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,gBAAgB,CAAC,CAAC,KAAK,EAAE,CAAC;IAC9E,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,CAAC;QAE7C,SAAS;QACT,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;QACnE,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;YACzE,IAAI,CAAC;gBACH,MAAM,aAAa,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;gBACtF,UAAU,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,CAAC;YAClD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,UAAU,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,CAAC;gBAC9C,GAAG,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC5D,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC;QACzC,GAAG,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5D,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,2BAA2B;AAC3B,KAAK,UAAU,kBAAkB,CAAC,KAAsB;IACtD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;IACpF,MAAM,OAAO,GAAG,IAAI,gBAAgB,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;QAC3F,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;QAC3C,OAAO,CAAC,OAAO,CACb,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC,MAAM,UAAU,CACrD,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC;QACzC,GAAG,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5D,OAAO,KAAK,CAAC;IACf,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC;IAChC,CAAC;AACH,CAAC;AAED,eAAe,aAAa,CAAC;IAC3B,IAAI,EAAE,EAAE,WAAW,EAAE,qBAAqB,EAAE;IAC5C,IAAI,EAAE;QACJ,KAAK,EAAE;YACL,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,aAAa;YAC1B,OAAO,EAAE,KAAK;SACf;KACF;IACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC;QAE/B,6BAA6B;QAC7B,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC1B,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;QAE1D,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,GAAG,CAAC,OAAO,CAAC,eAAe,IAAI,CAAC,OAAO,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,iBAAiB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QAC7C,CAAC;QAED,yBAAyB;QACzB,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAE5B,MAAM,YAAY,GAIb,EAAE,CAAC;QAER,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,UAAU,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;YAC1C,IAAI,MAAc,CAAC;YACnB,QAAQ,UAAU,EAAE,CAAC;gBACnB,KAAK,KAAK;oBACR,MAAM,GAAG,mBAAmB,CAAC;oBAC7B,MAAM;gBACR,KAAK,QAAQ;oBACX,MAAM,GAAG,yBAAyB,CAAC;oBACnC,MAAM;gBACR,KAAK,OAAO;oBACV,MAAM,GAAG,oBAAoB,CAAC;oBAC9B,MAAM;YACV,CAAC;YACD,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,GAAG,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;YAC5C,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;gBAC7B,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;gBACjD,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,UAAU,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACzB,CAAC;QAED,iBAAiB;QACjB,IAAI,WAAW;YAAE,OAAO;QAExB,kBAAkB;QAClB,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEb,mBAAmB;QACnB,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,IAAI,gBAAgB,GAAG,KAAK,CAAC;QAC7B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,WAAW,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YACnD,IAAI,CAAC,WAAW;gBAAE,gBAAgB,GAAG,IAAI,CAAC;QAC5C,CAAC;QAED,eAAe;QACf,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,IAAI,WAAW,GAAG,CAAC,CAAC;QAEpB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,UAAU,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;YAE1C,QAAQ,UAAU,EAAE,CAAC;gBACnB,KAAK,KAAK,CAAC,CAAC,CAAC;oBACX,MAAM,EAAE,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;oBACvC,IAAI,EAAE,EAAE,CAAC;wBACP,0BAA0B;wBAC1B,IAAI,CAAC;4BACH,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;4BACpD,MAAM,OAAO,GAAoB;gCAC/B,GAAG,KAAK;gCACR,KAAK,EAAE,UAAU,CAAC,KAAK;gCACvB,SAAS,EAAE,UAAU,CAAC,SAAS;gCAC/B,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;6BAChF,CAAC;4BACF,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;4BAC1D,IAAI,CAAC,QAAQ,EAAE,CAAC;gCACd,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,mBAAmB,CAAC,CAAC;4BACnD,CAAC;wBACH,CAAC;wBAAC,OAAO,GAAG,EAAE,CAAC;4BACb,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,qBAAqB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;wBACvG,CAAC;wBACD,YAAY,EAAE,CAAC;oBACjB,CAAC;yBAAM,CAAC;wBACN,WAAW,EAAE,CAAC;oBAChB,CAAC;oBACD,MAAM;gBACR,CAAC;gBACD,KAAK,QAAQ,CAAC,CAAC,CAAC;oBACd,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC;oBAC3C,IAAI,EAAE,EAAE,CAAC;wBACP,YAAY,EAAE,CAAC;oBACjB,CAAC;yBAAM,CAAC;wBACN,WAAW,EAAE,CAAC;oBAChB,CAAC;oBACD,MAAM;gBACR,CAAC;gBACD,KAAK,OAAO;oBACV,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,gDAAgD,CAAC,CAAC;oBAC9E,YAAY,EAAE,CAAC;oBACf,MAAM;YACV,CAAC;QACH,CAAC;QAED,gBAAgB;QAChB,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACb,MAAM,WAAW,GAAG,WAAW,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7D,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,MAAM,UAAU,GAAG,gBAAgB;gBACjC,CAAC,CAAC,WAAW;gBACb,CAAC,CAAC,WAAW;oBACX,CAAC,CAAC,QAAQ;oBACV,CAAC,CAAC,UAAU,CAAC;YACjB,GAAG,CAAC,IAAI,CACN,YAAY,UAAU,GACpB,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,WAAW,eAAe,CAAC,CAAC,CAAC,EACrD,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,YAAY,cAAc,CAAC,CAAC,CAAC,EAAE,GACvD,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,YAAY,OAAO,CAAC,CAAC,CAAC,EAC/C,EAAE,CACH,CAAC;YACF,OAAO;QACT,CAAC;QAED,IAAI,WAAW,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YACpC,GAAG,CAAC,OAAO,CACT,QAAQ,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,GACzC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,YAAY,cAAc,CAAC,CAAC,CAAC,EACtD,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,YAAY,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CACrD,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,31 @@
1
+ import { defineCommand, runMain } from "citty";
2
+ import chalk from "chalk";
3
+ import { checkForUpdate, getCurrentVersion } from "./utils/update-checker.js";
4
+ const CLI_VERSION = getCurrentVersion();
5
+ const main = defineCommand({
6
+ meta: {
7
+ name: "roll",
8
+ version: CLI_VERSION,
9
+ description: "花卷 Agent — 轻量级 Agent 编排系统",
10
+ },
11
+ subCommands: {
12
+ agent: () => import("./commands/agent.js").then((m) => m.default),
13
+ run: () => import("./commands/run.js").then((m) => m.default),
14
+ ask: () => import("./commands/ask.js").then((m) => m.default),
15
+ config: () => import("./commands/config.js").then((m) => m.default),
16
+ doctor: () => import("./commands/doctor.js").then((m) => m.default),
17
+ update: () => import("./commands/update.js").then((m) => m.default),
18
+ },
19
+ });
20
+ // 启动提示只读缓存,保证不阻塞 CLI 退出。
21
+ const updateCheckPromise = checkForUpdate({ allowNetwork: false }).catch(() => undefined);
22
+ runMain(main).then(() => {
23
+ updateCheckPromise
24
+ .then((info) => {
25
+ if (info?.hasUpdate) {
26
+ console.error(`\n${chalk.yellow("⬆")} roll ${chalk.green(`v${info.latest}`)} available (current: v${info.current}). Run ${chalk.cyan("roll update")} to upgrade.`);
27
+ }
28
+ })
29
+ .catch(() => undefined);
30
+ });
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9E,MAAM,WAAW,GAAG,iBAAiB,EAAE,CAAC;AAExC,MAAM,IAAI,GAAG,aAAa,CAAC;IACzB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,WAAW;QACpB,WAAW,EAAE,2BAA2B;KACzC;IACD,WAAW,EAAE;QACX,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACjE,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAC7D,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAC7D,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACnE,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACnE,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;KACpE;CACF,CAAC,CAAC;AAEH,yBAAyB;AACzB,MAAM,kBAAkB,GAAG,cAAc,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CACtE,GAAG,EAAE,CAAC,SAAS,CAChB,CAAC;AAEF,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;IACtB,kBAAkB;SACf,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QACb,IAAI,IAAI,EAAE,SAAS,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CACX,KAAK,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,yBAAyB,IAAI,CAAC,OAAO,UAAU,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,cAAc,CACpJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;SACD,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;AAC5B,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=smoke.e2e.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoke.e2e.d.ts","sourceRoot":"","sources":["../../src/cli/smoke.e2e.ts"],"names":[],"mappings":""}
@@ -0,0 +1,57 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
+ import { resolve } from "node:path";
5
+ import { tmpdir } from "node:os";
6
+ import { randomUUID } from "node:crypto";
7
+ import { spawnSync } from "node:child_process";
8
+ function runRoll(args, cwd, env = {}) {
9
+ const cliEntry = resolve(import.meta.dirname, "index.ts");
10
+ const result = spawnSync(process.execPath, ["--experimental-strip-types", cliEntry, ...args], {
11
+ cwd,
12
+ encoding: "utf-8",
13
+ env: { ...process.env, NO_COLOR: "1", ...env },
14
+ });
15
+ return {
16
+ status: result.status,
17
+ stdout: result.stdout,
18
+ stderr: result.stderr,
19
+ };
20
+ }
21
+ function buildConfigYaml(dataDir) {
22
+ return `llm:
23
+ default-provider: anthropic
24
+ default-model: claude-sonnet-4-20250514
25
+ providers: {}
26
+
27
+ router:
28
+ mode: declarative
29
+
30
+ agents:
31
+ data-dir: ${dataDir}
32
+ `;
33
+ }
34
+ test("e2e smoke: register boss-reply agent and run get_unread", { timeout: 120_000 }, () => {
35
+ const workspace = mkdtempSync(resolve(tmpdir(), `roll-e2e-${randomUUID()}-`));
36
+ try {
37
+ const repoRoot = resolve(import.meta.dirname, "../../../../");
38
+ const bossAgentPath = resolve(repoRoot, "agents/boss-reply");
39
+ const dataDir = resolve(workspace, "agents-data");
40
+ writeFileSync(resolve(workspace, "roll.config.yaml"), buildConfigYaml(dataDir), "utf-8");
41
+ const addResult = runRoll(["agent", "add", bossAgentPath], workspace, {
42
+ ROLL_SKIP_INSTALL: "1",
43
+ });
44
+ assert.equal(addResult.status, 0, `agent add failed\nstdout:\n${addResult.stdout}\nstderr:\n${addResult.stderr}`);
45
+ const listResult = runRoll(["agent", "list", "--json"], workspace);
46
+ assert.equal(listResult.status, 0, `agent list failed\nstdout:\n${listResult.stdout}\nstderr:\n${listResult.stderr}`);
47
+ const listedAgents = JSON.parse(listResult.stdout);
48
+ assert.ok(listedAgents.some((agent) => agent.skill.name === "boss-reply-agent"));
49
+ const runResult = runRoll(["run", "boss-reply-agent", "get_unread"], workspace);
50
+ assert.equal(runResult.status, 0, `roll run failed\nstdout:\n${runResult.stdout}\nstderr:\n${runResult.stderr}`);
51
+ assert.match(runResult.stdout, /"messages"\s*:\s*\[\]/);
52
+ }
53
+ finally {
54
+ rmSync(workspace, { recursive: true, force: true });
55
+ }
56
+ });
57
+ //# sourceMappingURL=smoke.e2e.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoke.e2e.js","sourceRoot":"","sources":["../../src/cli/smoke.e2e.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { Ora } from "ora";
2
+ /** 日志级别 */
3
+ declare const LOG_LEVELS: {
4
+ readonly debug: 0;
5
+ readonly info: 1;
6
+ readonly warn: 2;
7
+ readonly error: 3;
8
+ readonly silent: 4;
9
+ };
10
+ type LogLevel = keyof typeof LOG_LEVELS;
11
+ /** 设置全局日志级别 */
12
+ export declare function setLogLevel(level: LogLevel): void;
13
+ /** 结构化日志输出(写入 stderr,不干扰 stdout 数据流) */
14
+ export declare const log: {
15
+ debug(message: string): void;
16
+ info(message: string): void;
17
+ success(message: string): void;
18
+ warn(message: string): void;
19
+ error(message: string): void;
20
+ };
21
+ /** 创建 spinner(用于长时间操作的加载动画) */
22
+ export declare function createSpinner(text: string): Ora;
23
+ export {};
24
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/output.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE/B,WAAW;AACX,QAAA,MAAM,UAAU;;;;;;CAMN,CAAC;AAEX,KAAK,QAAQ,GAAG,MAAM,OAAO,UAAU,CAAC;AAKxC,eAAe;AACf,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAEjD;AAMD,wCAAwC;AACxC,eAAO,MAAM,GAAG;mBACC,MAAM,GAAG,IAAI;kBAKd,MAAM,GAAG,IAAI;qBAKV,MAAM,GAAG,IAAI;kBAKhB,MAAM,GAAG,IAAI;mBAKZ,MAAM,GAAG,IAAI;CAK7B,CAAC;AAEF,+BAA+B;AAC/B,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAE/C"}
@@ -0,0 +1,52 @@
1
+ import chalk from "chalk";
2
+ import ora from "ora";
3
+ /** 日志级别 */
4
+ const LOG_LEVELS = {
5
+ debug: 0,
6
+ info: 1,
7
+ warn: 2,
8
+ error: 3,
9
+ silent: 4,
10
+ };
11
+ /** 全局日志级别,可通过 setLogLevel 修改 */
12
+ let currentLevel = "info";
13
+ /** 设置全局日志级别 */
14
+ export function setLogLevel(level) {
15
+ currentLevel = level;
16
+ }
17
+ function shouldLog(level) {
18
+ return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel];
19
+ }
20
+ /** 结构化日志输出(写入 stderr,不干扰 stdout 数据流) */
21
+ export const log = {
22
+ debug(message) {
23
+ if (shouldLog("debug")) {
24
+ console.error(chalk.gray(`[debug] ${message}`));
25
+ }
26
+ },
27
+ info(message) {
28
+ if (shouldLog("info")) {
29
+ console.error(chalk.blue("→") + ` ${message}`);
30
+ }
31
+ },
32
+ success(message) {
33
+ if (shouldLog("info")) {
34
+ console.error(chalk.green("✓") + ` ${message}`);
35
+ }
36
+ },
37
+ warn(message) {
38
+ if (shouldLog("warn")) {
39
+ console.error(chalk.yellow("⚠") + ` ${message}`);
40
+ }
41
+ },
42
+ error(message) {
43
+ if (shouldLog("error")) {
44
+ console.error(chalk.red("✗") + ` ${message}`);
45
+ }
46
+ },
47
+ };
48
+ /** 创建 spinner(用于长时间操作的加载动画) */
49
+ export function createSpinner(text) {
50
+ return ora({ text, stream: process.stderr });
51
+ }
52
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/cli/utils/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AAGtB,WAAW;AACX,MAAM,UAAU,GAAG;IACjB,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC;CACD,CAAC;AAIX,gCAAgC;AAChC,IAAI,YAAY,GAAa,MAAM,CAAC;AAEpC,eAAe;AACf,MAAM,UAAU,WAAW,CAAC,KAAe;IACzC,YAAY,GAAG,KAAK,CAAC;AACvB,CAAC;AAED,SAAS,SAAS,CAAC,KAAe;IAChC,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC;AACvD,CAAC;AAED,wCAAwC;AACxC,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,KAAK,CAAC,OAAe;QACnB,IAAI,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IACD,IAAI,CAAC,OAAe;QAClB,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IACD,OAAO,CAAC,OAAe;QACrB,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IACD,IAAI,CAAC,OAAe;QAClB,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IACD,KAAK,CAAC,OAAe;QACnB,IAAI,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;CACF,CAAC;AAEF,+BAA+B;AAC/B,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/prompt.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ export {};
2
+ // Interactive input utilities
3
+ // TODO: implement
4
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../src/cli/utils/prompt.ts"],"names":[],"mappings":";AAAA,8BAA8B;AAC9B,kBAAkB"}
@@ -0,0 +1,24 @@
1
+ interface CheckForUpdateOptions {
2
+ /** 强制忽略缓存,始终尝试联网查询 */
3
+ readonly forceRefresh?: boolean;
4
+ /** 是否允许联网查询 npm registry */
5
+ readonly allowNetwork?: boolean;
6
+ }
7
+ /** 从 npm registry 查询最新版本 */
8
+ export declare function fetchLatestVersion(): Promise<string | undefined>;
9
+ /** 获取当前安装的版本 */
10
+ export declare function getCurrentVersion(): string;
11
+ export interface UpdateInfo {
12
+ readonly current: string;
13
+ readonly latest: string;
14
+ readonly hasUpdate: boolean;
15
+ }
16
+ /**
17
+ * 检查是否有新版本可用。
18
+ *
19
+ * 使用 24h 文件缓存避免频繁网络请求。
20
+ * 设计为不抛异常 — 任何失败静默返回无更新。
21
+ */
22
+ export declare function checkForUpdate(options?: CheckForUpdateOptions): Promise<UpdateInfo>;
23
+ export {};
24
+ //# sourceMappingURL=update-checker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-checker.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/update-checker.ts"],"names":[],"mappings":"AAwBA,UAAU,qBAAqB;IAC7B,sBAAsB;IACtB,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,4BAA4B;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAyCD,4BAA4B;AAC5B,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAWtE;AAED,gBAAgB;AAChB,wBAAgB,iBAAiB,IAAI,MAAM,CAc1C;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAiBD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,UAAU,CAAC,CA2CrB"}
@@ -0,0 +1,146 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
2
+ import { resolve, dirname } from "node:path";
3
+ import { execFile } from "node:child_process";
4
+ import { promisify } from "node:util";
5
+ import { homedir } from "node:os";
6
+ const execFileAsync = promisify(execFile);
7
+ /** 缓存有效期:24 小时 */
8
+ const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
9
+ /** 包名 */
10
+ const PACKAGE_NAME = "@roll-agent/core";
11
+ /** 缓存文件路径 */
12
+ function getCachePath() {
13
+ return resolve(homedir(), ".roll-agent", "update-check.json");
14
+ }
15
+ function isUpdateCache(value) {
16
+ if (typeof value !== "object" || value === null)
17
+ return false;
18
+ if (!("latestVersion" in value) || !("checkedAt" in value))
19
+ return false;
20
+ return (typeof value.latestVersion === "string" &&
21
+ typeof value.checkedAt === "number");
22
+ }
23
+ /** 读取缓存 */
24
+ function readCache() {
25
+ const cachePath = getCachePath();
26
+ if (!existsSync(cachePath))
27
+ return undefined;
28
+ try {
29
+ const raw = readFileSync(cachePath, "utf-8");
30
+ const parsed = JSON.parse(raw);
31
+ if (isUpdateCache(parsed))
32
+ return parsed;
33
+ }
34
+ catch {
35
+ // 缓存损坏,忽略
36
+ }
37
+ return undefined;
38
+ }
39
+ /** 写入缓存 */
40
+ function writeCache(latestVersion) {
41
+ try {
42
+ const cachePath = getCachePath();
43
+ const dir = dirname(cachePath);
44
+ if (!existsSync(dir)) {
45
+ mkdirSync(dir, { recursive: true });
46
+ }
47
+ const cache = { latestVersion, checkedAt: Date.now() };
48
+ writeFileSync(cachePath, JSON.stringify(cache), "utf-8");
49
+ }
50
+ catch {
51
+ // 缓存写入失败不影响主流程
52
+ }
53
+ }
54
+ /** 从 npm registry 查询最新版本 */
55
+ export async function fetchLatestVersion() {
56
+ try {
57
+ const { stdout } = await execFileAsync("npm", ["view", PACKAGE_NAME, "version"], {
58
+ timeout: 5000,
59
+ encoding: "utf-8",
60
+ });
61
+ const version = stdout.trim();
62
+ return version.length > 0 ? version : undefined;
63
+ }
64
+ catch {
65
+ return undefined;
66
+ }
67
+ }
68
+ /** 获取当前安装的版本 */
69
+ export function getCurrentVersion() {
70
+ // 从 package.json 读取,兼容开发和安装环境
71
+ try {
72
+ const pkgPath = resolve(import.meta.dirname, "../../../package.json");
73
+ const raw = readFileSync(pkgPath, "utf-8");
74
+ const pkg = JSON.parse(raw);
75
+ if (typeof pkg === "object" && pkg !== null && "version" in pkg) {
76
+ const version = pkg.version;
77
+ if (typeof version === "string")
78
+ return version;
79
+ }
80
+ }
81
+ catch {
82
+ // fallback
83
+ }
84
+ return "0.0.0";
85
+ }
86
+ /** 比较语义化版本,返回 a > b */
87
+ function isNewerVersion(latest, current) {
88
+ const parse = (v) => v.replace(/^v/, "").split(".").map(Number);
89
+ const l = parse(latest);
90
+ const c = parse(current);
91
+ for (let i = 0; i < 3; i++) {
92
+ const lv = l[i] ?? 0;
93
+ const cv = c[i] ?? 0;
94
+ if (lv > cv)
95
+ return true;
96
+ if (lv < cv)
97
+ return false;
98
+ }
99
+ return false;
100
+ }
101
+ /**
102
+ * 检查是否有新版本可用。
103
+ *
104
+ * 使用 24h 文件缓存避免频繁网络请求。
105
+ * 设计为不抛异常 — 任何失败静默返回无更新。
106
+ */
107
+ export async function checkForUpdate(options = {}) {
108
+ const forceRefresh = options.forceRefresh ?? false;
109
+ const allowNetwork = options.allowNetwork ?? true;
110
+ const current = getCurrentVersion();
111
+ const cache = readCache();
112
+ // 优先读缓存
113
+ if (!forceRefresh && cache && Date.now() - cache.checkedAt < CACHE_TTL_MS) {
114
+ return {
115
+ current,
116
+ latest: cache.latestVersion,
117
+ hasUpdate: isNewerVersion(cache.latestVersion, current),
118
+ };
119
+ }
120
+ if (!allowNetwork) {
121
+ if (cache) {
122
+ return {
123
+ current,
124
+ latest: cache.latestVersion,
125
+ hasUpdate: isNewerVersion(cache.latestVersion, current),
126
+ };
127
+ }
128
+ return { current, latest: current, hasUpdate: false };
129
+ }
130
+ // 缓存过期或不存在,查询 npm
131
+ const latest = await fetchLatestVersion();
132
+ if (latest) {
133
+ writeCache(latest);
134
+ return { current, latest, hasUpdate: isNewerVersion(latest, current) };
135
+ }
136
+ // 查询失败,使用旧缓存或返回无更新
137
+ if (cache) {
138
+ return {
139
+ current,
140
+ latest: cache.latestVersion,
141
+ hasUpdate: isNewerVersion(cache.latestVersion, current),
142
+ };
143
+ }
144
+ return { current, latest: current, hasUpdate: false };
145
+ }
146
+ //# sourceMappingURL=update-checker.js.map