c0de-agent 0.0.0 → 1.0.0

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 (330) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +101 -0
  3. package/dist/cli/commands/acp.d.ts +19 -0
  4. package/dist/cli/commands/acp.js +50 -0
  5. package/dist/cli/commands/chat.d.ts +13 -0
  6. package/dist/cli/commands/chat.js +26 -0
  7. package/dist/cli/commands/config.d.ts +17 -0
  8. package/dist/cli/commands/config.js +77 -0
  9. package/dist/cli/commands/init.d.ts +9 -0
  10. package/dist/cli/commands/init.js +14 -0
  11. package/dist/cli/commands/plugin.d.ts +11 -0
  12. package/dist/cli/commands/plugin.js +31 -0
  13. package/dist/cli/commands/serve.d.ts +18 -0
  14. package/dist/cli/commands/serve.js +35 -0
  15. package/dist/cli/commands/update.d.ts +24 -0
  16. package/dist/cli/commands/update.js +40 -0
  17. package/dist/cli/deps.d.ts +19 -0
  18. package/dist/cli/deps.js +57 -0
  19. package/dist/cli/index.d.ts +8 -0
  20. package/dist/cli/index.js +149 -0
  21. package/dist/cli/modes/acp.d.ts +18 -0
  22. package/dist/cli/modes/acp.js +57 -0
  23. package/dist/cli/modes/print.d.ts +16 -0
  24. package/dist/cli/modes/print.js +30 -0
  25. package/dist/cli/parser.d.ts +19 -0
  26. package/dist/cli/parser.js +28 -0
  27. package/dist/cli/utils/output.d.ts +11 -0
  28. package/dist/cli/utils/output.js +23 -0
  29. package/dist/cli/utils/prompt.d.ts +12 -0
  30. package/dist/cli/utils/prompt.js +18 -0
  31. package/dist/core/agent.d.ts +12 -0
  32. package/dist/core/agent.js +95 -0
  33. package/dist/core/agents/builtin.d.ts +6 -0
  34. package/dist/core/agents/builtin.js +76 -0
  35. package/dist/core/agents/discovery.d.ts +6 -0
  36. package/dist/core/agents/discovery.js +96 -0
  37. package/dist/core/agents/index.d.ts +6 -0
  38. package/dist/core/agents/index.js +4 -0
  39. package/dist/core/agents/parallel.d.ts +13 -0
  40. package/dist/core/agents/parallel.js +37 -0
  41. package/dist/core/agents/registry.d.ts +4 -0
  42. package/dist/core/agents/registry.js +23 -0
  43. package/dist/core/agents/types.d.ts +37 -0
  44. package/dist/core/agents/types.js +1 -0
  45. package/dist/core/compact.d.ts +11 -0
  46. package/dist/core/compact.js +31 -0
  47. package/dist/core/config.d.ts +7 -0
  48. package/dist/core/config.js +84 -0
  49. package/dist/core/context.d.ts +23 -0
  50. package/dist/core/context.js +93 -0
  51. package/dist/core/index.d.ts +13 -0
  52. package/dist/core/index.js +11 -0
  53. package/dist/core/loop.d.ts +25 -0
  54. package/dist/core/loop.js +651 -0
  55. package/dist/core/metrics.d.ts +27 -0
  56. package/dist/core/metrics.js +94 -0
  57. package/dist/core/prompt-registry.d.ts +21 -0
  58. package/dist/core/prompt-registry.js +200 -0
  59. package/dist/core/prompt.d.ts +11 -0
  60. package/dist/core/prompt.js +13 -0
  61. package/dist/core/secret.d.ts +12 -0
  62. package/dist/core/secret.js +51 -0
  63. package/dist/core/slash.d.ts +15 -0
  64. package/dist/core/slash.js +114 -0
  65. package/dist/core/steering.d.ts +8 -0
  66. package/dist/core/steering.js +15 -0
  67. package/dist/core/title.d.ts +42 -0
  68. package/dist/core/title.js +115 -0
  69. package/dist/core/tool-exec.d.ts +20 -0
  70. package/dist/core/tool-exec.js +64 -0
  71. package/dist/core/types.d.ts +95 -0
  72. package/dist/core/types.js +1 -0
  73. package/dist/core/worktree.d.ts +24 -0
  74. package/dist/core/worktree.js +68 -0
  75. package/dist/dap/index.d.ts +6 -0
  76. package/dist/dap/index.js +4 -0
  77. package/dist/dap/protocol.d.ts +40 -0
  78. package/dist/dap/protocol.js +132 -0
  79. package/dist/dap/session.d.ts +23 -0
  80. package/dist/dap/session.js +130 -0
  81. package/dist/dap/transport.d.ts +8 -0
  82. package/dist/dap/transport.js +30 -0
  83. package/dist/dap/types.d.ts +50 -0
  84. package/dist/dap/types.js +2 -0
  85. package/dist/db/client.d.ts +22 -0
  86. package/dist/db/client.js +39 -0
  87. package/dist/db/index.d.ts +6 -0
  88. package/dist/db/index.js +4 -0
  89. package/dist/db/migrate.d.ts +9 -0
  90. package/dist/db/migrate.js +15 -0
  91. package/dist/db/schema.d.ts +965 -0
  92. package/dist/db/schema.js +112 -0
  93. package/dist/db/types.d.ts +11 -0
  94. package/dist/db/types.js +1 -0
  95. package/dist/llm/index.d.ts +13 -0
  96. package/dist/llm/index.js +8 -0
  97. package/dist/llm/protocols/openai-compat.d.ts +139 -0
  98. package/dist/llm/protocols/openai-compat.js +214 -0
  99. package/dist/llm/protocols/utils/index.d.ts +2 -0
  100. package/dist/llm/protocols/utils/index.js +2 -0
  101. package/dist/llm/protocols/utils/lifecycle.d.ts +23 -0
  102. package/dist/llm/protocols/utils/lifecycle.js +46 -0
  103. package/dist/llm/protocols/utils/tool-stream.d.ts +46 -0
  104. package/dist/llm/protocols/utils/tool-stream.js +94 -0
  105. package/dist/llm/provider-error.d.ts +5 -0
  106. package/dist/llm/provider-error.js +33 -0
  107. package/dist/llm/provider.d.ts +32 -0
  108. package/dist/llm/provider.js +191 -0
  109. package/dist/llm/registry.d.ts +44 -0
  110. package/dist/llm/registry.js +107 -0
  111. package/dist/llm/retry.d.ts +37 -0
  112. package/dist/llm/retry.js +82 -0
  113. package/dist/llm/routing.d.ts +36 -0
  114. package/dist/llm/routing.js +53 -0
  115. package/dist/llm/schema/errors.d.ts +88 -0
  116. package/dist/llm/schema/errors.js +33 -0
  117. package/dist/llm/schema/events.d.ts +135 -0
  118. package/dist/llm/schema/events.js +35 -0
  119. package/dist/llm/schema/ids.d.ts +22 -0
  120. package/dist/llm/schema/ids.js +3 -0
  121. package/dist/llm/schema/index.d.ts +5 -0
  122. package/dist/llm/schema/index.js +5 -0
  123. package/dist/llm/schema/messages.d.ts +97 -0
  124. package/dist/llm/schema/messages.js +18 -0
  125. package/dist/llm/schema/options.d.ts +54 -0
  126. package/dist/llm/schema/options.js +54 -0
  127. package/dist/llm/token.d.ts +2 -0
  128. package/dist/llm/token.js +13 -0
  129. package/dist/llm/transport.d.ts +31 -0
  130. package/dist/llm/transport.js +165 -0
  131. package/dist/mcp/index.d.ts +1 -0
  132. package/dist/mcp/index.js +3 -0
  133. package/dist/plugins/builtin.d.ts +6 -0
  134. package/dist/plugins/builtin.js +54 -0
  135. package/dist/plugins/hooks.d.ts +3 -0
  136. package/dist/plugins/hooks.js +79 -0
  137. package/dist/plugins/index.d.ts +9 -0
  138. package/dist/plugins/index.js +8 -0
  139. package/dist/plugins/init.d.ts +23 -0
  140. package/dist/plugins/init.js +30 -0
  141. package/dist/plugins/lifecycle.d.ts +6 -0
  142. package/dist/plugins/lifecycle.js +74 -0
  143. package/dist/plugins/loader.d.ts +16 -0
  144. package/dist/plugins/loader.js +68 -0
  145. package/dist/plugins/logger.d.ts +4 -0
  146. package/dist/plugins/logger.js +31 -0
  147. package/dist/plugins/registry.d.ts +7 -0
  148. package/dist/plugins/registry.js +24 -0
  149. package/dist/plugins/types.d.ts +113 -0
  150. package/dist/plugins/types.js +1 -0
  151. package/dist/project/detect.d.ts +4 -0
  152. package/dist/project/detect.js +131 -0
  153. package/dist/project/index.d.ts +4 -0
  154. package/dist/project/index.js +2 -0
  155. package/dist/project/project.d.ts +23 -0
  156. package/dist/project/project.js +87 -0
  157. package/dist/project/resolve.d.ts +8 -0
  158. package/dist/project/resolve.js +81 -0
  159. package/dist/server/agent-manager.d.ts +32 -0
  160. package/dist/server/agent-manager.js +54 -0
  161. package/dist/server/app.d.ts +5 -0
  162. package/dist/server/app.js +75 -0
  163. package/dist/server/context.d.ts +20 -0
  164. package/dist/server/context.js +47 -0
  165. package/dist/server/dev.d.ts +11 -0
  166. package/dist/server/dev.js +83 -0
  167. package/dist/server/index.d.ts +11 -0
  168. package/dist/server/index.js +7 -0
  169. package/dist/server/middleware/auth.d.ts +15 -0
  170. package/dist/server/middleware/auth.js +29 -0
  171. package/dist/server/middleware/cors.d.ts +16 -0
  172. package/dist/server/middleware/cors.js +44 -0
  173. package/dist/server/middleware/error.d.ts +15 -0
  174. package/dist/server/middleware/error.js +11 -0
  175. package/dist/server/permission/interactive.d.ts +24 -0
  176. package/dist/server/permission/interactive.js +56 -0
  177. package/dist/server/permission/store.d.ts +30 -0
  178. package/dist/server/permission/store.js +47 -0
  179. package/dist/server/routes/agent.d.ts +4 -0
  180. package/dist/server/routes/agent.js +19 -0
  181. package/dist/server/routes/catalog.d.ts +42 -0
  182. package/dist/server/routes/catalog.js +194 -0
  183. package/dist/server/routes/chat.d.ts +8 -0
  184. package/dist/server/routes/chat.js +282 -0
  185. package/dist/server/routes/commands.d.ts +5 -0
  186. package/dist/server/routes/commands.js +17 -0
  187. package/dist/server/routes/config.d.ts +4 -0
  188. package/dist/server/routes/config.js +27 -0
  189. package/dist/server/routes/files.d.ts +4 -0
  190. package/dist/server/routes/files.js +183 -0
  191. package/dist/server/routes/filesystem.d.ts +29 -0
  192. package/dist/server/routes/filesystem.js +108 -0
  193. package/dist/server/routes/health.d.ts +3 -0
  194. package/dist/server/routes/health.js +13 -0
  195. package/dist/server/routes/permissions.d.ts +5 -0
  196. package/dist/server/routes/permissions.js +23 -0
  197. package/dist/server/routes/project.d.ts +4 -0
  198. package/dist/server/routes/project.js +51 -0
  199. package/dist/server/routes/provider.d.ts +16 -0
  200. package/dist/server/routes/provider.js +66 -0
  201. package/dist/server/routes/session.d.ts +4 -0
  202. package/dist/server/routes/session.js +130 -0
  203. package/dist/server/routes/tool.d.ts +4 -0
  204. package/dist/server/routes/tool.js +28 -0
  205. package/dist/server/routes/update.d.ts +14 -0
  206. package/dist/server/routes/update.js +49 -0
  207. package/dist/server/server.d.ts +43 -0
  208. package/dist/server/server.js +197 -0
  209. package/dist/server/types.d.ts +73 -0
  210. package/dist/server/types.js +2 -0
  211. package/dist/server/util/safe-path.d.ts +7 -0
  212. package/dist/server/util/safe-path.js +7 -0
  213. package/dist/session/archive.d.ts +15 -0
  214. package/dist/session/archive.js +129 -0
  215. package/dist/session/branch.d.ts +9 -0
  216. package/dist/session/branch.js +63 -0
  217. package/dist/session/compaction.d.ts +27 -0
  218. package/dist/session/compaction.js +192 -0
  219. package/dist/session/context.d.ts +16 -0
  220. package/dist/session/context.js +173 -0
  221. package/dist/session/index.d.ts +10 -0
  222. package/dist/session/index.js +10 -0
  223. package/dist/session/message.d.ts +22 -0
  224. package/dist/session/message.js +145 -0
  225. package/dist/session/session.d.ts +37 -0
  226. package/dist/session/session.js +144 -0
  227. package/dist/session/snapshot.d.ts +11 -0
  228. package/dist/session/snapshot.js +60 -0
  229. package/dist/session/squash.d.ts +9 -0
  230. package/dist/session/squash.js +88 -0
  231. package/dist/session/token.d.ts +10 -0
  232. package/dist/session/token.js +33 -0
  233. package/dist/session/types.d.ts +122 -0
  234. package/dist/session/types.js +1 -0
  235. package/dist/shared/index.d.ts +2 -0
  236. package/dist/shared/index.js +1 -0
  237. package/dist/shared/types/agent.d.ts +202 -0
  238. package/dist/shared/types/agent.js +1 -0
  239. package/dist/shared/types/base.d.ts +32 -0
  240. package/dist/shared/types/base.js +1 -0
  241. package/dist/shared/types/config.d.ts +104 -0
  242. package/dist/shared/types/config.js +1 -0
  243. package/dist/shared/types/index.d.ts +6 -0
  244. package/dist/shared/types/index.js +1 -0
  245. package/dist/shared/types/llm.d.ts +122 -0
  246. package/dist/shared/types/llm.js +1 -0
  247. package/dist/shared/types/message.d.ts +71 -0
  248. package/dist/shared/types/message.js +1 -0
  249. package/dist/shared/types/tool.d.ts +134 -0
  250. package/dist/shared/types/tool.js +1 -0
  251. package/dist/shared/utils/path.d.ts +15 -0
  252. package/dist/shared/utils/path.js +23 -0
  253. package/dist/shared/utils.d.ts +5 -0
  254. package/dist/shared/utils.js +10 -0
  255. package/dist/tools/builtin/bash.d.ts +12 -0
  256. package/dist/tools/builtin/bash.js +121 -0
  257. package/dist/tools/builtin/dap.d.ts +23 -0
  258. package/dist/tools/builtin/dap.js +231 -0
  259. package/dist/tools/builtin/edit.d.ts +12 -0
  260. package/dist/tools/builtin/edit.js +151 -0
  261. package/dist/tools/builtin/glob.d.ts +11 -0
  262. package/dist/tools/builtin/glob.js +120 -0
  263. package/dist/tools/builtin/grep.d.ts +6 -0
  264. package/dist/tools/builtin/grep.js +141 -0
  265. package/dist/tools/builtin/read.d.ts +6 -0
  266. package/dist/tools/builtin/read.js +73 -0
  267. package/dist/tools/builtin/resolvers.d.ts +12 -0
  268. package/dist/tools/builtin/resolvers.js +79 -0
  269. package/dist/tools/builtin/task.d.ts +9 -0
  270. package/dist/tools/builtin/task.js +100 -0
  271. package/dist/tools/builtin/write.d.ts +6 -0
  272. package/dist/tools/builtin/write.js +36 -0
  273. package/dist/tools/builtin/yield.d.ts +9 -0
  274. package/dist/tools/builtin/yield.js +40 -0
  275. package/dist/tools/executor.d.ts +9 -0
  276. package/dist/tools/executor.js +54 -0
  277. package/dist/tools/hashline/index.d.ts +2 -0
  278. package/dist/tools/hashline/index.js +3 -0
  279. package/dist/tools/hashline/patch.d.ts +48 -0
  280. package/dist/tools/hashline/patch.js +201 -0
  281. package/dist/tools/index.d.ts +30 -0
  282. package/dist/tools/index.js +55 -0
  283. package/dist/tools/permission.d.ts +13 -0
  284. package/dist/tools/permission.js +39 -0
  285. package/dist/tools/registry.d.ts +15 -0
  286. package/dist/tools/registry.js +54 -0
  287. package/dist/tools/resolver.d.ts +15 -0
  288. package/dist/tools/resolver.js +47 -0
  289. package/dist/tools/truncate.d.ts +8 -0
  290. package/dist/tools/truncate.js +50 -0
  291. package/dist/tools/types.d.ts +101 -0
  292. package/dist/tools/types.js +1 -0
  293. package/dist/tools/validate.d.ts +8 -0
  294. package/dist/tools/validate.js +130 -0
  295. package/dist/tools/websearch/fetch.d.ts +11 -0
  296. package/dist/tools/websearch/fetch.js +21 -0
  297. package/dist/tools/websearch/index.d.ts +19 -0
  298. package/dist/tools/websearch/index.js +78 -0
  299. package/dist/tools/websearch/providers/brave.d.ts +5 -0
  300. package/dist/tools/websearch/providers/brave.js +53 -0
  301. package/dist/tools/websearch/providers/duckduckgo.d.ts +3 -0
  302. package/dist/tools/websearch/providers/duckduckgo.js +75 -0
  303. package/dist/tools/websearch/providers/tavily.d.ts +11 -0
  304. package/dist/tools/websearch/providers/tavily.js +89 -0
  305. package/dist/tools/websearch/types.d.ts +51 -0
  306. package/dist/tools/websearch/types.js +18 -0
  307. package/dist/tools/websearch/websearch.d.ts +10 -0
  308. package/dist/tools/websearch/websearch.js +48 -0
  309. package/dist/update/index.d.ts +10 -0
  310. package/dist/update/index.js +6 -0
  311. package/dist/update/ipc.d.ts +15 -0
  312. package/dist/update/ipc.js +41 -0
  313. package/dist/update/scheduler.d.ts +34 -0
  314. package/dist/update/scheduler.js +57 -0
  315. package/dist/update/snapshot.d.ts +39 -0
  316. package/dist/update/snapshot.js +99 -0
  317. package/dist/update/updater.d.ts +48 -0
  318. package/dist/update/updater.js +83 -0
  319. package/dist/update/version.d.ts +18 -0
  320. package/dist/update/version.js +49 -0
  321. package/drizzle/0000_magical_nightshade.sql +55 -0
  322. package/drizzle/0001_chemical_doctor_faustus.sql +13 -0
  323. package/drizzle/0002_amusing_micromacro.sql +12 -0
  324. package/drizzle/0003_regular_purifiers.sql +2 -0
  325. package/drizzle/meta/0000_snapshot.json +448 -0
  326. package/drizzle/meta/0001_snapshot.json +539 -0
  327. package/drizzle/meta/0002_snapshot.json +633 -0
  328. package/drizzle/meta/0003_snapshot.json +645 -0
  329. package/drizzle/meta/_journal.json +34 -0
  330. package/package.json +100 -8
@@ -0,0 +1,96 @@
1
+ import { readdir, readFile, stat } from 'node:fs/promises';
2
+ import { basename, join } from 'node:path';
3
+ /** 默认 agent markdown 目录(相对项目根)。 */
4
+ const AGENTS_DIR = '.c0de/agents';
5
+ /** 解析简单 YAML 行(key: value 或 key: [a, b])。不处理嵌套。 */
6
+ function parseFrontmatterLine(line) {
7
+ const idx = line.indexOf(':');
8
+ if (idx === -1)
9
+ return null;
10
+ const key = line.slice(0, idx).trim();
11
+ let value = line.slice(idx + 1).trim();
12
+ // 数组:[a, b, c]
13
+ if (typeof value === 'string' && value.startsWith('[') && value.endsWith(']')) {
14
+ value = value
15
+ .slice(1, -1)
16
+ .split(',')
17
+ .map((s) => s.trim())
18
+ .filter(Boolean);
19
+ }
20
+ else if (value === 'true') {
21
+ value = true;
22
+ }
23
+ else if (value === 'false') {
24
+ value = false;
25
+ }
26
+ else {
27
+ // 尝试数字
28
+ const num = Number(value);
29
+ if (!Number.isNaN(num) && value !== '')
30
+ value = num;
31
+ }
32
+ return [key, value];
33
+ }
34
+ /** 解析单个 markdown 文件为 AgentDefinition。无 frontmatter 返回 null。 */
35
+ async function loadAgentFile(filePath, source) {
36
+ let content;
37
+ try {
38
+ content = await readFile(filePath, 'utf-8');
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ // frontmatter 必须以 --- 开头
44
+ if (!content.startsWith('---'))
45
+ return null;
46
+ const endIdx = content.indexOf('\n---', 3);
47
+ if (endIdx === -1)
48
+ return null;
49
+ const fmRaw = content.slice(3, endIdx);
50
+ const body = content.slice(endIdx + 4).trim(); // 跳过 \n---
51
+ const fm = {};
52
+ for (const line of fmRaw.split('\n')) {
53
+ const parsed = parseFrontmatterLine(line);
54
+ if (parsed)
55
+ fm[parsed[0]] = parsed[1];
56
+ }
57
+ const name = fm.name ?? basename(filePath, '.md');
58
+ const description = fm.description ?? '';
59
+ const mode = fm.mode ?? 'subagent';
60
+ return {
61
+ name,
62
+ description,
63
+ systemPrompt: body,
64
+ ...(fm.tools ? { tools: fm.tools } : {}),
65
+ ...(fm.model ? { model: fm.model } : {}),
66
+ mode,
67
+ ...(fm.isolated !== undefined ? { isolated: fm.isolated } : {}),
68
+ ...(fm.maxRecursion !== undefined ? { maxRecursion: fm.maxRecursion } : {}),
69
+ source,
70
+ filePath,
71
+ };
72
+ }
73
+ /** 加载项目 agents 目录下所有 .md 为 AgentDefinition(源: project)。 */
74
+ async function loadAgents(projectDir) {
75
+ const agentsDir = join(projectDir, AGENTS_DIR);
76
+ let entries;
77
+ try {
78
+ const s = await stat(agentsDir);
79
+ if (!s.isDirectory())
80
+ return [];
81
+ entries = await readdir(agentsDir);
82
+ }
83
+ catch {
84
+ return [];
85
+ }
86
+ const defs = [];
87
+ for (const entry of entries) {
88
+ if (!entry.endsWith('.md'))
89
+ continue;
90
+ const def = await loadAgentFile(join(agentsDir, entry), 'project');
91
+ if (def)
92
+ defs.push(def);
93
+ }
94
+ return defs;
95
+ }
96
+ export { loadAgentFile, loadAgents };
@@ -0,0 +1,6 @@
1
+ export { BUILTIN_AGENTS, WORKER_BASE } from './builtin.js';
2
+ export { loadAgentFile, loadAgents } from './discovery.js';
3
+ export type { ParallelResult } from './parallel.js';
4
+ export { mapWithConcurrencyLimit } from './parallel.js';
5
+ export { createAgentRegistry } from './registry.js';
6
+ export type { AgentDefinition, AgentMode, AgentRegistry, AgentSource } from './types.js';
@@ -0,0 +1,4 @@
1
+ export { BUILTIN_AGENTS, WORKER_BASE } from './builtin.js';
2
+ export { loadAgentFile, loadAgents } from './discovery.js';
3
+ export { mapWithConcurrencyLimit } from './parallel.js';
4
+ export { createAgentRegistry } from './registry.js';
@@ -0,0 +1,13 @@
1
+ /** 并行执行结果。 */
2
+ interface ParallelResult<R> {
3
+ results: (R | undefined)[];
4
+ aborted: boolean;
5
+ }
6
+ /**
7
+ * 带 concurrency 上限的并行执行(worker 池)。
8
+ * 结果按输入顺序返回。abort 时取消未启动的、保留已完成的。
9
+ * 任一失败立即 reject(fail-fast)。
10
+ */
11
+ declare function mapWithConcurrencyLimit<T, R>(items: T[], concurrency: number, fn: (item: T, index: number, signal: AbortSignal) => Promise<R>, signal?: AbortSignal): Promise<ParallelResult<R>>;
12
+ export type { ParallelResult };
13
+ export { mapWithConcurrencyLimit };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * 带 concurrency 上限的并行执行(worker 池)。
3
+ * 结果按输入顺序返回。abort 时取消未启动的、保留已完成的。
4
+ * 任一失败立即 reject(fail-fast)。
5
+ */
6
+ async function mapWithConcurrencyLimit(items, concurrency, fn, signal) {
7
+ const limit = Math.max(1, Math.min(concurrency, items.length));
8
+ const results = new Array(items.length);
9
+ let nextIndex = 0;
10
+ const abortController = new AbortController();
11
+ const workerSignal = signal
12
+ ? AbortSignal.any([signal, abortController.signal])
13
+ : abortController.signal;
14
+ async function worker() {
15
+ while (true) {
16
+ if (workerSignal.aborted)
17
+ return;
18
+ const idx = nextIndex++;
19
+ if (idx >= items.length)
20
+ return;
21
+ const item = items[idx];
22
+ if (item === undefined)
23
+ return;
24
+ results[idx] = await fn(item, idx, workerSignal);
25
+ }
26
+ }
27
+ const workers = Array.from({ length: limit }, () => worker());
28
+ try {
29
+ await Promise.all(workers);
30
+ }
31
+ catch (e) {
32
+ abortController.abort();
33
+ throw e;
34
+ }
35
+ return { results, aborted: signal?.aborted ?? false };
36
+ }
37
+ export { mapWithConcurrencyLimit };
@@ -0,0 +1,4 @@
1
+ import type { AgentRegistry } from './types.js';
2
+ /** 创建空的 agent 注册表(内存 Map,后注册覆盖同名)。 */
3
+ declare function createAgentRegistry(): AgentRegistry;
4
+ export { createAgentRegistry };
@@ -0,0 +1,23 @@
1
+ /** 创建空的 agent 注册表(内存 Map,后注册覆盖同名)。 */
2
+ function createAgentRegistry() {
3
+ const defs = new Map();
4
+ return {
5
+ register(def) {
6
+ defs.set(def.name, def);
7
+ },
8
+ get(name) {
9
+ return defs.get(name);
10
+ },
11
+ list(mode) {
12
+ const all = Array.from(defs.values());
13
+ if (!mode)
14
+ return all;
15
+ // 'all' 模式的 agent 在任何过滤下都可见;subagent/primary 精确匹配。
16
+ return all.filter((d) => d.mode === 'all' || d.mode === mode);
17
+ },
18
+ has(name) {
19
+ return defs.has(name);
20
+ },
21
+ };
22
+ }
23
+ export { createAgentRegistry };
@@ -0,0 +1,37 @@
1
+ /** Agent 定义的来源层级(后加载覆盖先加载)。 */
2
+ type AgentSource = 'builtin' | 'user' | 'project';
3
+ /** Agent 可见性模式:subagent=仅子用,primary=仅主,all=皆可。 */
4
+ type AgentMode = 'subagent' | 'primary' | 'all';
5
+ /** 可配置的 agent 类型定义(由 markdown frontmatter 或代码构造)。 */
6
+ interface AgentDefinition {
7
+ /** 唯一标识,如 'researcher'。 */
8
+ name: string;
9
+ /** 何时用此 agent(注入 task 工具描述供模型选择)。 */
10
+ description: string;
11
+ /** 专属 system prompt(frontmatter 正文)。 */
12
+ systemPrompt: string;
13
+ /** 允许的工具集(默认全部注册工具)。 */
14
+ tools?: string[];
15
+ /** 模型覆盖(默认继承父 agent)。 */
16
+ model?: string;
17
+ /** 可见性模式。 */
18
+ mode: AgentMode;
19
+ /** 是否用 git worktree 隔离(默认 false)。 */
20
+ isolated?: boolean;
21
+ /** 递归派生深度上限(默认 0=禁止递归 task)。 */
22
+ maxRecursion?: number;
23
+ /** yield 结果的 JSON Schema(验证子 agent 输出)。 */
24
+ outputSchema?: object;
25
+ /** 来源层级。 */
26
+ source: AgentSource;
27
+ /** markdown 路径(调试用)。 */
28
+ filePath?: string;
29
+ }
30
+ /** Agent 类型注册表:内存 Map<name, definition>。 */
31
+ interface AgentRegistry {
32
+ register(def: AgentDefinition): void;
33
+ get(name: string): AgentDefinition | undefined;
34
+ list(mode?: AgentMode): AgentDefinition[];
35
+ has(name: string): boolean;
36
+ }
37
+ export type { AgentDefinition, AgentMode, AgentRegistry, AgentSource };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import type { DB } from '../db/client.js';
2
+ import type { Registry } from '../llm/registry.js';
3
+ import type { CompactionConfig, CompactionResult, Summarizer } from '../session/types.js';
4
+ /** Create a Summarizer backed by an LLM streaming call. */
5
+ declare function createSummarizer(registry: Registry, provider: string, model: string, opts?: {
6
+ maxTokens?: number;
7
+ signal?: AbortSignal;
8
+ }): Summarizer;
9
+ /** Run compaction on a session using the provided summarizer. */
10
+ declare function runCompaction(db: DB, sessionId: string, summarizer: Summarizer, config?: Partial<CompactionConfig>): Promise<CompactionResult>;
11
+ export { createSummarizer, runCompaction };
@@ -0,0 +1,31 @@
1
+ import { chatStream } from '../llm/provider.js';
2
+ import { compactSession } from '../session/compaction.js';
3
+ /** Create a Summarizer backed by an LLM streaming call. */
4
+ function createSummarizer(registry, provider, model, opts) {
5
+ return async (prompt) => {
6
+ const request = {
7
+ model,
8
+ messages: [{ role: 'user', content: prompt }],
9
+ stream: true,
10
+ ...(opts?.maxTokens !== undefined ? { maxTokens: opts.maxTokens } : {}),
11
+ };
12
+ const chunks = [];
13
+ for await (const chunk of chatStream({ registry, signal: opts?.signal }, request, {
14
+ provider,
15
+ model,
16
+ })) {
17
+ if (chunk._tag === 'text') {
18
+ chunks.push(chunk);
19
+ }
20
+ if (chunk._tag === 'error') {
21
+ throw new Error(chunk.error.message);
22
+ }
23
+ }
24
+ return chunks.map((c) => (c._tag === 'text' ? c.text : '')).join('');
25
+ };
26
+ }
27
+ /** Run compaction on a session using the provided summarizer. */
28
+ async function runCompaction(db, sessionId, summarizer, config) {
29
+ return compactSession(db, sessionId, summarizer, config);
30
+ }
31
+ export { createSummarizer, runCompaction };
@@ -0,0 +1,7 @@
1
+ import type { AgentsConfig, CompactionConfig, Config, MCPServerConfig, PermissionConfig, SecurityConfig, ToolMetricsConfig, UpdateConfig, WebSearchConfig } from '../shared/types/config.js';
2
+ declare const DEFAULT_CONFIG: Config;
3
+ declare function mergeConfig(...configs: (Partial<Config> | undefined)[]): Config;
4
+ declare function loadConfig(projectDir?: string): Promise<Config>;
5
+ declare function saveConfig(config: Config, scope: 'global' | 'project', projectDir?: string): Promise<void>;
6
+ export type { AgentsConfig, CompactionConfig, Config, MCPServerConfig, PermissionConfig, SecurityConfig, ToolMetricsConfig, UpdateConfig, WebSearchConfig, };
7
+ export { DEFAULT_CONFIG, loadConfig, mergeConfig, saveConfig };
@@ -0,0 +1,84 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ const GLOBAL_CONFIG_DIR = '.c0de';
5
+ const CONFIG_FILENAME = 'config.json';
6
+ const DEFAULT_CONFIG = {
7
+ providers: [],
8
+ defaultProvider: 'openai',
9
+ defaultModel: 'gpt-4o',
10
+ roleRouting: {},
11
+ fallback: { enabled: false, maxRetries: 3, retryDelay: 2000 },
12
+ compaction: {
13
+ enabled: true,
14
+ threshold: 0.8,
15
+ reserveTokens: 8000,
16
+ keepRecentTokens: 4000,
17
+ },
18
+ tools: { enabled: ['read', 'write', 'edit', 'glob', 'grep', 'bash', 'websearch'], disabled: [] },
19
+ plugins: { enabled: [] },
20
+ mcpServers: [],
21
+ slashCommands: { enabled: ['/compact', '/model', '/clear', '/help', '/fork', '/config'] },
22
+ toolMetrics: { enabled: true, threshold: 0.8, minSamples: 5 },
23
+ security: { authEnabled: false, allowedOrigins: [] },
24
+ websearch: { provider: 'auto' },
25
+ agents: { dir: '.c0de/agents', subagentConcurrency: 3 },
26
+ permission: { defaultMode: 'default' },
27
+ update: { enabled: true, intervalMs: 60 * 60 * 1000, initialDelayMs: 10_000, autoApply: false },
28
+ theme: 'system',
29
+ locale: 'en',
30
+ };
31
+ function mergeConfig(...configs) {
32
+ const result = structuredClone(DEFAULT_CONFIG);
33
+ for (const cfg of configs) {
34
+ if (!cfg)
35
+ continue;
36
+ for (const key of Object.keys(cfg)) {
37
+ const val = cfg[key];
38
+ if (val === undefined)
39
+ continue;
40
+ const current = result[key];
41
+ if (val !== null &&
42
+ typeof val === 'object' &&
43
+ !Array.isArray(val) &&
44
+ current !== null &&
45
+ typeof current === 'object' &&
46
+ !Array.isArray(current)) {
47
+ ;
48
+ result[key] = { ...current, ...val };
49
+ }
50
+ else {
51
+ ;
52
+ result[key] = val;
53
+ }
54
+ }
55
+ }
56
+ return result;
57
+ }
58
+ function readJsonIfExists(path) {
59
+ if (!existsSync(path))
60
+ return undefined;
61
+ try {
62
+ return JSON.parse(readFileSync(path, 'utf-8'));
63
+ }
64
+ catch {
65
+ return undefined;
66
+ }
67
+ }
68
+ async function loadConfig(projectDir) {
69
+ const globalPath = join(homedir(), GLOBAL_CONFIG_DIR, CONFIG_FILENAME);
70
+ const projectPath = join(projectDir ?? process.cwd(), '.c0de', CONFIG_FILENAME);
71
+ const global = readJsonIfExists(globalPath);
72
+ const project = readJsonIfExists(projectPath);
73
+ return mergeConfig(global, project);
74
+ }
75
+ async function saveConfig(config, scope, projectDir) {
76
+ const dir = scope === 'global'
77
+ ? join(homedir(), GLOBAL_CONFIG_DIR)
78
+ : join(projectDir ?? process.cwd(), '.c0de');
79
+ if (!existsSync(dir))
80
+ mkdirSync(dir, { recursive: true });
81
+ const path = join(dir, CONFIG_FILENAME);
82
+ writeFileSync(path, JSON.stringify(config, null, 2), 'utf-8');
83
+ }
84
+ export { DEFAULT_CONFIG, loadConfig, mergeConfig, saveConfig };
@@ -0,0 +1,23 @@
1
+ import type { TokenBudget } from '../shared/types/agent.js';
2
+ import type { Message } from '../shared/types/message.js';
3
+ import type { CompactionConfig } from './config.js';
4
+ declare function createTokenBudget(totalTokens: number, opts?: {
5
+ reserved?: number;
6
+ historyBudget?: number;
7
+ keepRecent?: number;
8
+ }): TokenBudget;
9
+ declare function estimateBudget(messages: Message[], factor?: number): number;
10
+ declare function fitToBudget(messages: Message[], budget: TokenBudget, factor?: number): Message[];
11
+ declare function shouldCompact(_messages: Message[], budget: TokenBudget, config: CompactionConfig): boolean;
12
+ /**
13
+ * 按真实 LLM input token 校准估算系数(指数移动平均)。
14
+ *
15
+ * `estimated` 与 `actual` 必须是同一口径——即「system prompt + 工具描述 + 历史消息」
16
+ * 全部 input 的 token 总和。这样 observed = actual/estimated 收敛到 estimateTokens
17
+ * 的系统性系数,可反哺 estimateBudget/fitToBudget 的裁剪与压缩判断。
18
+ *
19
+ * 极端值(首轮流式 chunk 异常等)被 clamp 到 [CALIBRATION_MIN, CALIBRATION_MAX],
20
+ * 避免单次噪声污染系数。
21
+ */
22
+ declare function calibrateEstimate(prevFactor: number, estimated: number, actual: number): number;
23
+ export { calibrateEstimate, createTokenBudget, estimateBudget, fitToBudget, shouldCompact };
@@ -0,0 +1,93 @@
1
+ import { estimateTokens } from '../session/token.js';
2
+ // Token 预算分配(spec §3.6 策略1):
3
+ // reserved 20% — system prompt + 工具描述
4
+ // historyBudget 60% — 历史消息上限
5
+ // 当前轮次 20% — available - historyBudget,预留给本轮用户输入与模型输出
6
+ const SYSTEM_PROMPT_RATIO = 0.2;
7
+ const HISTORY_RATIO = 0.6;
8
+ const KEEP_RECENT_RATIO = 0.1;
9
+ // calibrateEstimate 的指数移动平均参数与边界。
10
+ const CALIBRATION_ALPHA = 0.3;
11
+ const CALIBRATION_MIN = 0.25;
12
+ const CALIBRATION_MAX = 4;
13
+ function createTokenBudget(totalTokens, opts) {
14
+ const reserved = opts?.reserved ?? Math.floor(totalTokens * SYSTEM_PROMPT_RATIO);
15
+ return {
16
+ total: totalTokens,
17
+ reserved,
18
+ available: totalTokens - reserved,
19
+ historyBudget: opts?.historyBudget ?? Math.floor(totalTokens * HISTORY_RATIO),
20
+ used: 0,
21
+ keepRecent: opts?.keepRecent ?? Math.floor(totalTokens * KEEP_RECENT_RATIO),
22
+ };
23
+ }
24
+ /** 单条消息的原始 token 估算(不应用校准系数)。 */
25
+ function rawMessageTokens(m) {
26
+ if (m.tokenCount > 0)
27
+ return m.tokenCount;
28
+ return estimateTokens(m.content.map((p) => (p._tag === 'text' || p._tag === 'thinking' ? p.text : '')).join(''));
29
+ }
30
+ function estimateBudget(messages, factor = 1.0) {
31
+ const raw = messages.reduce((sum, m) => sum + rawMessageTokens(m), 0);
32
+ return factor === 1.0 ? raw : Math.round(raw * factor);
33
+ }
34
+ function fitToBudget(messages, budget, factor = 1.0) {
35
+ if (messages.length === 0)
36
+ return [];
37
+ let recentTokens = 0;
38
+ let recentStart = messages.length;
39
+ for (let i = messages.length - 1; i >= 0; i--) {
40
+ const m = messages[i];
41
+ if (!m)
42
+ continue;
43
+ const tc = rawMessageTokens(m) * factor;
44
+ if (recentTokens + tc > budget.keepRecent)
45
+ break;
46
+ recentTokens += tc;
47
+ recentStart = i;
48
+ }
49
+ // Always keep at least the last message
50
+ recentStart = Math.min(recentStart, messages.length - 1);
51
+ const result = [];
52
+ let used = 0;
53
+ // 历史消息最多占用 historyBudget,超出部分预留给当前轮次(spec §3.6 策略1)。
54
+ const historyCap = budget.historyBudget;
55
+ for (let i = 0; i < messages.length; i++) {
56
+ const m = messages[i];
57
+ if (!m)
58
+ continue;
59
+ const tc = rawMessageTokens(m) * factor;
60
+ const mustKeep = i >= recentStart;
61
+ if (mustKeep || used + tc <= historyCap) {
62
+ result.push(m);
63
+ used += tc;
64
+ }
65
+ }
66
+ return result;
67
+ }
68
+ function shouldCompact(_messages, budget, config) {
69
+ if (!config.enabled)
70
+ return false;
71
+ if (budget.available <= 0)
72
+ return false;
73
+ const ratio = budget.used / budget.available;
74
+ return ratio >= config.threshold;
75
+ }
76
+ /**
77
+ * 按真实 LLM input token 校准估算系数(指数移动平均)。
78
+ *
79
+ * `estimated` 与 `actual` 必须是同一口径——即「system prompt + 工具描述 + 历史消息」
80
+ * 全部 input 的 token 总和。这样 observed = actual/estimated 收敛到 estimateTokens
81
+ * 的系统性系数,可反哺 estimateBudget/fitToBudget 的裁剪与压缩判断。
82
+ *
83
+ * 极端值(首轮流式 chunk 异常等)被 clamp 到 [CALIBRATION_MIN, CALIBRATION_MAX],
84
+ * 避免单次噪声污染系数。
85
+ */
86
+ function calibrateEstimate(prevFactor, estimated, actual) {
87
+ if (estimated <= 0 || actual <= 0)
88
+ return prevFactor;
89
+ const observed = actual / estimated;
90
+ const clamped = Math.min(Math.max(observed, CALIBRATION_MIN), CALIBRATION_MAX);
91
+ return prevFactor * (1 - CALIBRATION_ALPHA) + clamped * CALIBRATION_ALPHA;
92
+ }
93
+ export { calibrateEstimate, createTokenBudget, estimateBudget, fitToBudget, shouldCompact };
@@ -0,0 +1,13 @@
1
+ export { abortAgent, createAgent, getAgentStatus, isAgentPaused, pauseAgent, resumeAgent, runAgent, } from './agent.js';
2
+ export { createSummarizer, runCompaction } from './compact.js';
3
+ export type { CompactionConfig, Config, MCPServerConfig } from './config.js';
4
+ export { DEFAULT_CONFIG, loadConfig, mergeConfig, saveConfig } from './config.js';
5
+ export { calibrateEstimate, createTokenBudget, estimateBudget, fitToBudget, shouldCompact, } from './context.js';
6
+ export { agentLoop } from './loop.js';
7
+ export { buildSystemPrompt } from './prompt.js';
8
+ export type { SlashRegistry } from './slash.js';
9
+ export { builtinCommands, createSlashRegistry, parseSlashInput } from './slash.js';
10
+ export { clearSteering, drainSteering, injectSteering } from './steering.js';
11
+ export type { CollectedToolCall, ToolCallResult } from './tool-exec.js';
12
+ export { executeToolCall, executeToolCalls, partitionByConflict } from './tool-exec.js';
13
+ export type { AgentConfig, AgentDependencies, AgentError, AgentEvent, AgentState, AgentStatus, CommandContext, CommandResult, LLMSegment, PendingToolCall, ProjectInfo, PromptContext, SlashCommand, TokenBudget, } from './types.js';
@@ -0,0 +1,11 @@
1
+ // Core package: agent loop, prompt building, config, context management,
2
+ // steering, slash commands, and compaction bridge.
3
+ export { abortAgent, createAgent, getAgentStatus, isAgentPaused, pauseAgent, resumeAgent, runAgent, } from './agent.js';
4
+ export { createSummarizer, runCompaction } from './compact.js';
5
+ export { DEFAULT_CONFIG, loadConfig, mergeConfig, saveConfig } from './config.js';
6
+ export { calibrateEstimate, createTokenBudget, estimateBudget, fitToBudget, shouldCompact, } from './context.js';
7
+ export { agentLoop } from './loop.js';
8
+ export { buildSystemPrompt } from './prompt.js';
9
+ export { builtinCommands, createSlashRegistry, parseSlashInput } from './slash.js';
10
+ export { clearSteering, drainSteering, injectSteering } from './steering.js';
11
+ export { executeToolCall, executeToolCalls, partitionByConflict } from './tool-exec.js';
@@ -0,0 +1,25 @@
1
+ import { chatStream as llmChatStream } from '../llm/provider.js';
2
+ import type { AgentEvent, AgentState } from '../shared/types/agent.js';
3
+ import type { SubAgentRequest, SubAgentResult } from '../shared/types/tool.js';
4
+ import type { AgentDependencies } from './types.js';
5
+ type LoopDeps = AgentDependencies & {
6
+ chatStream?: typeof llmChatStream;
7
+ /** 子 agent 运行时注入:yield 工具的结果收集器(透传到 ToolContext.collectYield)。 */
8
+ readonly _subagentYieldCollector?: (data: unknown) => void;
9
+ /** 子 agent 运行时注入:事件回调,子 agent 的 subagent_start/end 事件推入此 sink,
10
+ * 由父 agentLoop 缓冲后在工具执行后 yield 出去(spec §4.5 step 7)。 */
11
+ readonly _subagentEventSink?: (event: AgentEvent) => void;
12
+ /** 当前递归深度(0=顶层主 agent)。用于 maxRecursion 控制(spec §4.5 step 4)。 */
13
+ readonly _subagentDepth?: number;
14
+ };
15
+ export type { LoopDeps };
16
+ /** 运行一个按类型派发的子 agent(spec: multi-agent-design §4.5)。
17
+ *
18
+ * Host 端实现:查 agentRegistry 获取 AgentDefinition → 创建隔离子 session(agentType 记录)
19
+ * → 构建子 agent(专属 prompt + 受限工具集 + yield)→ 运行到 yield 或完成 → 返回结果。
20
+ * 发射 subagent_start/subagent_end 事件供父 agent 转发(spec §4.5 step 7)。
21
+ * abort 链接父→子。maxRecursion 控制子 agent 能否再递归派生 task(spec §4.5 step 4)。
22
+ * def.isolated 时在 git worktree 中运行,结束后把 delta 自动 apply 回父仓库(spec §4.6)。
23
+ * request.background 时 fork 异步运行,立即返回 running(spec §4.7)。 */
24
+ export declare function runSubAgent(deps: LoopDeps, parent: AgentState, request: SubAgentRequest): Promise<SubAgentResult>;
25
+ export declare function agentLoop(state: AgentState, deps: LoopDeps): AsyncGenerator<AgentEvent>;