@geeseeker/easyai-dev 3.0.0-alpha.1 → 3.0.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 (169) hide show
  1. package/README.md +90 -88
  2. package/README_AI.md +143 -0
  3. package/bin/easyai-dev.js +127 -1
  4. package/lib/init.js +425 -0
  5. package/lib/server/index.d.ts +14 -0
  6. package/lib/server/index.d.ts.map +1 -0
  7. package/lib/server/index.js +126 -0
  8. package/lib/server/index.js.map +1 -0
  9. package/lib/server/resources/journal-resource.d.ts +8 -0
  10. package/lib/server/resources/journal-resource.d.ts.map +1 -0
  11. package/lib/server/resources/journal-resource.js +46 -0
  12. package/lib/server/resources/journal-resource.js.map +1 -0
  13. package/lib/server/resources/spec-resource.d.ts +11 -0
  14. package/lib/server/resources/spec-resource.d.ts.map +1 -0
  15. package/lib/server/resources/spec-resource.js +126 -0
  16. package/lib/server/resources/spec-resource.js.map +1 -0
  17. package/lib/server/resources/status-resource.d.ts +8 -0
  18. package/lib/server/resources/status-resource.d.ts.map +1 -0
  19. package/lib/server/resources/status-resource.js +36 -0
  20. package/lib/server/resources/status-resource.js.map +1 -0
  21. package/lib/server/resources/subtask-context-resource.d.ts +8 -0
  22. package/lib/server/resources/subtask-context-resource.d.ts.map +1 -0
  23. package/lib/server/resources/subtask-context-resource.js +93 -0
  24. package/lib/server/resources/subtask-context-resource.js.map +1 -0
  25. package/lib/server/resources/task-context-resource.d.ts +8 -0
  26. package/lib/server/resources/task-context-resource.d.ts.map +1 -0
  27. package/lib/server/resources/task-context-resource.js +76 -0
  28. package/lib/server/resources/task-context-resource.js.map +1 -0
  29. package/lib/server/tools/conflict-check.d.ts +7 -0
  30. package/lib/server/tools/conflict-check.d.ts.map +1 -0
  31. package/lib/server/tools/conflict-check.js +242 -0
  32. package/lib/server/tools/conflict-check.js.map +1 -0
  33. package/lib/server/tools/context-budget.d.ts +7 -0
  34. package/lib/server/tools/context-budget.d.ts.map +1 -0
  35. package/lib/server/tools/context-budget.js +178 -0
  36. package/lib/server/tools/context-budget.js.map +1 -0
  37. package/lib/server/tools/context-generate.d.ts +7 -0
  38. package/lib/server/tools/context-generate.d.ts.map +1 -0
  39. package/lib/server/tools/context-generate.js +208 -0
  40. package/lib/server/tools/context-generate.js.map +1 -0
  41. package/lib/server/tools/framework-tools.d.ts +20 -0
  42. package/lib/server/tools/framework-tools.d.ts.map +1 -0
  43. package/lib/server/tools/framework-tools.js +412 -0
  44. package/lib/server/tools/framework-tools.js.map +1 -0
  45. package/lib/server/tools/journal-append.d.ts +7 -0
  46. package/lib/server/tools/journal-append.d.ts.map +1 -0
  47. package/lib/server/tools/journal-append.js +55 -0
  48. package/lib/server/tools/journal-append.js.map +1 -0
  49. package/lib/server/tools/journal-search.d.ts +7 -0
  50. package/lib/server/tools/journal-search.d.ts.map +1 -0
  51. package/lib/server/tools/journal-search.js +63 -0
  52. package/lib/server/tools/journal-search.js.map +1 -0
  53. package/lib/server/tools/plan-validate.d.ts +7 -0
  54. package/lib/server/tools/plan-validate.d.ts.map +1 -0
  55. package/lib/server/tools/plan-validate.js +146 -0
  56. package/lib/server/tools/plan-validate.js.map +1 -0
  57. package/lib/server/tools/spec-validate.d.ts +7 -0
  58. package/lib/server/tools/spec-validate.d.ts.map +1 -0
  59. package/lib/server/tools/spec-validate.js +170 -0
  60. package/lib/server/tools/spec-validate.js.map +1 -0
  61. package/lib/server/tools/subtask-tools.d.ts +12 -0
  62. package/lib/server/tools/subtask-tools.d.ts.map +1 -0
  63. package/lib/server/tools/subtask-tools.js +383 -0
  64. package/lib/server/tools/subtask-tools.js.map +1 -0
  65. package/lib/server/tools/task-append-log.d.ts +7 -0
  66. package/lib/server/tools/task-append-log.d.ts.map +1 -0
  67. package/lib/server/tools/task-append-log.js +108 -0
  68. package/lib/server/tools/task-append-log.js.map +1 -0
  69. package/lib/server/tools/task-cancel.d.ts +7 -0
  70. package/lib/server/tools/task-cancel.d.ts.map +1 -0
  71. package/lib/server/tools/task-cancel.js +104 -0
  72. package/lib/server/tools/task-cancel.js.map +1 -0
  73. package/lib/server/tools/task-create.d.ts +7 -0
  74. package/lib/server/tools/task-create.d.ts.map +1 -0
  75. package/lib/server/tools/task-create.js +98 -0
  76. package/lib/server/tools/task-create.js.map +1 -0
  77. package/lib/server/tools/task-get.d.ts +7 -0
  78. package/lib/server/tools/task-get.d.ts.map +1 -0
  79. package/lib/server/tools/task-get.js +152 -0
  80. package/lib/server/tools/task-get.js.map +1 -0
  81. package/lib/server/tools/task-list.d.ts +7 -0
  82. package/lib/server/tools/task-list.d.ts.map +1 -0
  83. package/lib/server/tools/task-list.js +66 -0
  84. package/lib/server/tools/task-list.js.map +1 -0
  85. package/lib/server/tools/task-transition.d.ts +7 -0
  86. package/lib/server/tools/task-transition.d.ts.map +1 -0
  87. package/lib/server/tools/task-transition.js +259 -0
  88. package/lib/server/tools/task-transition.js.map +1 -0
  89. package/lib/server/tools/worktree-tools.d.ts +17 -0
  90. package/lib/server/tools/worktree-tools.d.ts.map +1 -0
  91. package/lib/server/tools/worktree-tools.js +336 -0
  92. package/lib/server/tools/worktree-tools.js.map +1 -0
  93. package/lib/server/utils/capability-gate.d.ts +50 -0
  94. package/lib/server/utils/capability-gate.d.ts.map +1 -0
  95. package/lib/server/utils/capability-gate.js +146 -0
  96. package/lib/server/utils/capability-gate.js.map +1 -0
  97. package/lib/server/utils/git-utils.d.ts +33 -0
  98. package/lib/server/utils/git-utils.d.ts.map +1 -0
  99. package/lib/server/utils/git-utils.js +84 -0
  100. package/lib/server/utils/git-utils.js.map +1 -0
  101. package/lib/server/utils/hash-utils.d.ts +78 -0
  102. package/lib/server/utils/hash-utils.d.ts.map +1 -0
  103. package/lib/server/utils/hash-utils.js +153 -0
  104. package/lib/server/utils/hash-utils.js.map +1 -0
  105. package/lib/server/utils/journal-utils.d.ts +69 -0
  106. package/lib/server/utils/journal-utils.d.ts.map +1 -0
  107. package/lib/server/utils/journal-utils.js +387 -0
  108. package/lib/server/utils/journal-utils.js.map +1 -0
  109. package/lib/server/utils/status-utils.d.ts +58 -0
  110. package/lib/server/utils/status-utils.d.ts.map +1 -0
  111. package/lib/server/utils/status-utils.js +70 -0
  112. package/lib/server/utils/status-utils.js.map +1 -0
  113. package/lib/server/utils/task-utils.d.ts +104 -0
  114. package/lib/server/utils/task-utils.d.ts.map +1 -0
  115. package/lib/server/utils/task-utils.js +396 -0
  116. package/lib/server/utils/task-utils.js.map +1 -0
  117. package/lib/server/utils/uri-utils.d.ts +9 -0
  118. package/lib/server/utils/uri-utils.d.ts.map +1 -0
  119. package/lib/server/utils/uri-utils.js +21 -0
  120. package/lib/server/utils/uri-utils.js.map +1 -0
  121. package/package.json +30 -21
  122. package/skeleton/.agents/rules/anti-hallucination.md +42 -0
  123. package/skeleton/.agents/rules/coding-standards.md +41 -0
  124. package/skeleton/.agents/rules/project-identity.md +71 -0
  125. package/skeleton/.agents/skills/common-framework-evolve/.gitkeep +0 -0
  126. package/skeleton/.agents/skills/common-framework-evolve/SKILL.md +105 -0
  127. package/skeleton/.agents/skills/common-session-close/.gitkeep +0 -0
  128. package/skeleton/.agents/skills/common-session-close/SKILL.md +83 -0
  129. package/skeleton/.agents/skills/common-spec-update/.gitkeep +0 -0
  130. package/skeleton/.agents/skills/common-spec-update/SKILL.md +87 -0
  131. package/skeleton/.agents/skills/pm-brainstorm/.gitkeep +0 -0
  132. package/skeleton/.agents/skills/pm-brainstorm/SKILL.md +114 -0
  133. package/skeleton/.agents/skills/pm-session-start/.gitkeep +0 -0
  134. package/skeleton/.agents/skills/pm-session-start/SKILL.md +73 -0
  135. package/skeleton/.agents/skills/pm-task-planning/SKILL.md +200 -0
  136. package/skeleton/.agents/skills/pm-task-review/.gitkeep +0 -0
  137. package/skeleton/.agents/skills/pm-task-review/SKILL.md +144 -0
  138. package/skeleton/.agents/skills/worker-check/.gitkeep +0 -0
  139. package/skeleton/.agents/skills/worker-check/SKILL.md +194 -0
  140. package/skeleton/.agents/skills/worker-debug/.gitkeep +0 -0
  141. package/skeleton/.agents/skills/worker-debug/SKILL.md +241 -0
  142. package/skeleton/.agents/skills/worker-implement/.gitkeep +0 -0
  143. package/skeleton/.agents/skills/worker-implement/SKILL.md +192 -0
  144. package/skeleton/.agents/workflows/pm.md +81 -0
  145. package/skeleton/.agents/workflows/worker.md +100 -0
  146. package/skeleton/.docs/README.md +25 -0
  147. package/skeleton/.docs/archive/.gitkeep +0 -0
  148. package/skeleton/.docs/design/.gitkeep +0 -0
  149. package/skeleton/.docs/guides/.gitkeep +0 -0
  150. package/skeleton/.docs/notes/.gitkeep +0 -0
  151. package/skeleton/.docs/requirements/.gitkeep +0 -0
  152. package/skeleton/.trellis/config/config.yaml +48 -0
  153. package/skeleton/.trellis/spec/backend/.gitkeep +0 -0
  154. package/skeleton/.trellis/spec/frontend/.gitkeep +0 -0
  155. package/skeleton/.trellis/spec/guides/.gitkeep +0 -0
  156. package/skeleton/.trellis/spec/guides/external-cli-guide.md +253 -0
  157. package/skeleton/.trellis/spec/guides/task-workflow.md +34 -0
  158. package/skeleton/.trellis/spec/guides/testing.md +32 -0
  159. package/skeleton/.trellis/spec/spec-schema.json +64 -0
  160. package/skeleton/.trellis/tasks/.gitkeep +0 -0
  161. package/skeleton/.trellis/workspace/.gitkeep +0 -0
  162. package/skeleton/README.md +25 -0
  163. package/LICENSE +0 -21
  164. package/src/cli/index.js +0 -40
  165. package/src/commands/init.js +0 -37
  166. package/src/commands/update.js +0 -33
  167. package/templates/README.md +0 -22
  168. package/templates/agents/README.md +0 -4
  169. package/templates/trellis/README.md +0 -4
package/lib/init.js ADDED
@@ -0,0 +1,425 @@
1
+ /**
2
+ * easyai-dev 初始化逻辑
3
+ *
4
+ * 提供三个核心函数:
5
+ * - doInit() — 初始化新项目或集成到已有项目
6
+ * - doCheck() — 检查框架完整性
7
+ * - doUpdate() — 更新框架(只更新 .agents/ 和 .trellis/spec/)
8
+ */
9
+
10
+ import * as fs from "node:fs";
11
+ import * as path from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+ import { execSync } from "node:child_process";
14
+
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = path.dirname(__filename);
17
+
18
+ // 颜色常量
19
+ const RED = "\x1b[31m";
20
+ const GREEN = "\x1b[32m";
21
+ const YELLOW = "\x1b[33m";
22
+ const BLUE = "\x1b[34m";
23
+ const BOLD = "\x1b[1m";
24
+ const NC = "\x1b[0m";
25
+
26
+ // skeleton 目录路径
27
+ const SKELETON_DIR = path.join(__dirname, "..", "skeleton");
28
+
29
+ // 框架版本
30
+ const FRAMEWORK_VERSION = "3.0.0";
31
+
32
+ // 需要检查的必需目录
33
+ const REQUIRED_DIRS = [
34
+ ".agents/rules",
35
+ ".agents/workflows",
36
+ ".agents/skills",
37
+ ".trellis/config",
38
+ ".trellis/spec",
39
+ ".trellis/tasks",
40
+ ".trellis/workspace",
41
+ ".docs/requirements",
42
+ ".docs/design",
43
+ ".docs/guides",
44
+ ".docs/notes",
45
+ ".docs/archive",
46
+ ];
47
+
48
+ // 需要检查的必需文件
49
+ const REQUIRED_FILES = [
50
+ ".agents/rules/project-identity.md",
51
+ ".agents/rules/anti-hallucination.md",
52
+ ".agents/rules/coding-standards.md",
53
+ ".agents/workflows/pm.md",
54
+ ".agents/workflows/worker.md",
55
+ ".trellis/config/config.yaml",
56
+ ".easyai-version",
57
+ ];
58
+
59
+ // 初始化时不应覆盖的文件(已有项目集成时)
60
+ const NO_OVERWRITE_FILES = [
61
+ "README.md",
62
+ ".gitignore",
63
+ ];
64
+
65
+ /**
66
+ * 递归复制目录
67
+ * @param src - 源目录
68
+ * @param dest - 目标目录
69
+ * @param options - 选项
70
+ */
71
+ function copyDirSync(
72
+ src,
73
+ dest,
74
+ options = { noOverwrite: false, log: true },
75
+ ) {
76
+ fs.mkdirSync(dest, { recursive: true });
77
+ const entries = fs.readdirSync(src, { withFileTypes: true });
78
+
79
+ for (const entry of entries) {
80
+ const srcPath = path.join(src, entry.name);
81
+ const destPath = path.join(dest, entry.name);
82
+
83
+ if (entry.isDirectory()) {
84
+ copyDirSync(srcPath, destPath, options);
85
+ } else {
86
+ if (options.noOverwrite && fs.existsSync(destPath)) {
87
+ if (options.log) {
88
+ console.log(` ${YELLOW}⊘${NC} ${path.relative(dest, destPath)}`
89
+ + ` — 已存在,跳过`);
90
+ }
91
+ continue;
92
+ }
93
+ fs.copyFileSync(srcPath, destPath);
94
+ }
95
+ }
96
+ }
97
+
98
+ /**
99
+ * 合并 .gitignore 文件
100
+ * 将新条目追加到已有的 .gitignore 中(不产生重复行)
101
+ */
102
+ function mergeGitignore(targetDir) {
103
+ const skeletonGitignore = path.join(SKELETON_DIR, ".gitignore");
104
+ const targetGitignore = path.join(targetDir, ".gitignore");
105
+
106
+ if (!fs.existsSync(skeletonGitignore)) {
107
+ return;
108
+ }
109
+
110
+ const skeletonLines = fs
111
+ .readFileSync(skeletonGitignore, "utf-8")
112
+ .split("\n")
113
+ .map((l) => l.trim())
114
+ .filter((l) => l && !l.startsWith("#"));
115
+
116
+ if (!fs.existsSync(targetGitignore)) {
117
+ // 如果目标没有 .gitignore,直接复制
118
+ fs.copyFileSync(skeletonGitignore, targetGitignore);
119
+ console.log(` ${GREEN}✓${NC} .gitignore — 已创建`);
120
+ return;
121
+ }
122
+
123
+ // 读取现有 .gitignore
124
+ const existingContent = fs.readFileSync(targetGitignore, "utf-8");
125
+ const existingLines = existingContent.split("\n").map((l) => l.trim());
126
+ const newLines = skeletonLines.filter((l) => !existingLines.includes(l));
127
+
128
+ if (newLines.length > 0) {
129
+ const appendContent =
130
+ "\n\n# easyAI 框架\n" + newLines.join("\n") + "\n";
131
+ fs.appendFileSync(targetGitignore, appendContent);
132
+ console.log(
133
+ ` ${GREEN}✓${NC} .gitignore — 已追加 ${newLines.length} 条规则`,
134
+ );
135
+ } else {
136
+ console.log(` ${YELLOW}⊘${NC} .gitignore — 无需追加`);
137
+ }
138
+ }
139
+
140
+ /**
141
+ * 初始化项目
142
+ * @param targetDir - 目标项目目录(绝对路径)
143
+ */
144
+ export async function doInit(targetDir) {
145
+ // 检查 skeleton 目录
146
+ if (!fs.existsSync(SKELETON_DIR)) {
147
+ console.error(`${RED}✗ 骨架目录不存在: ${SKELETON_DIR}${NC}`);
148
+ process.exit(1);
149
+ }
150
+
151
+ // 检查是否已初始化
152
+ const agentsDir = path.join(targetDir, ".agents");
153
+ const trellisDir = path.join(targetDir, ".trellis");
154
+ if (fs.existsSync(agentsDir) && fs.existsSync(trellisDir)) {
155
+ console.log(
156
+ `${YELLOW}⚠ 项目已初始化过(.agents/ 和 .trellis/ 已存在)${NC}`,
157
+ );
158
+ console.log(
159
+ `${YELLOW} 如需更新框架,请使用: easyai-dev update${NC}`,
160
+ );
161
+ console.log(
162
+ `${YELLOW} 如需重新初始化,请先手动删除 .agents/ 和 .trellis/${NC}`,
163
+ );
164
+ return;
165
+ }
166
+
167
+ // 检测是否是已有项目(非空目录)
168
+ const isExistingProject =
169
+ fs.existsSync(targetDir) &&
170
+ fs.readdirSync(targetDir).filter((f) => !f.startsWith(".")).length > 0;
171
+
172
+ console.log(`\n${BLUE}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`);
173
+ console.log(
174
+ `${BLUE}${BOLD}easyAI 框架初始化${NC}` +
175
+ (isExistingProject ? ` ${YELLOW}(集成模式)${NC}` : ""),
176
+ );
177
+ console.log(`${BLUE}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`);
178
+ console.log(`目标项目: ${GREEN}${targetDir}${NC}\n`);
179
+
180
+ // 确保目标目录存在
181
+ fs.mkdirSync(targetDir, { recursive: true });
182
+
183
+ // 复制 .agents/
184
+ const agentsSrc = path.join(SKELETON_DIR, ".agents");
185
+ if (fs.existsSync(agentsSrc)) {
186
+ copyDirSync(agentsSrc, path.join(targetDir, ".agents"));
187
+ console.log(` ${GREEN}✓${NC} .agents/ — 规则 + 工作流 + Skills`);
188
+ }
189
+
190
+ // 复制 .trellis/
191
+ const trellisSrc = path.join(SKELETON_DIR, ".trellis");
192
+ if (fs.existsSync(trellisSrc)) {
193
+ copyDirSync(trellisSrc, path.join(targetDir, ".trellis"));
194
+ console.log(` ${GREEN}✓${NC} .trellis/ — 配置 + 规范 + 任务骨架`);
195
+ }
196
+
197
+ // 复制 .docs/
198
+ const docsSrc = path.join(SKELETON_DIR, ".docs");
199
+ if (fs.existsSync(docsSrc)) {
200
+ copyDirSync(docsSrc, path.join(targetDir, ".docs"));
201
+ console.log(` ${GREEN}✓${NC} .docs/ — 文档空间`);
202
+ }
203
+
204
+ // 处理 .gitignore(合并而非覆盖)
205
+ mergeGitignore(targetDir);
206
+
207
+ // 处理 README.md
208
+ const readmeSrc = path.join(SKELETON_DIR, "README.md");
209
+ const readmeDest = path.join(targetDir, "README.md");
210
+ if (fs.existsSync(readmeSrc) && !fs.existsSync(readmeDest)) {
211
+ fs.copyFileSync(readmeSrc, readmeDest);
212
+ console.log(` ${GREEN}✓${NC} README.md — 已创建`);
213
+ } else if (fs.existsSync(readmeDest)) {
214
+ console.log(` ${YELLOW}⊘${NC} README.md — 已存在,跳过`);
215
+ }
216
+
217
+ // 写入版本清单
218
+ fs.writeFileSync(
219
+ path.join(targetDir, ".easyai-version"),
220
+ `${FRAMEWORK_VERSION}\n`,
221
+ );
222
+ console.log(` ${GREEN}✓${NC} .easyai-version — v${FRAMEWORK_VERSION}`);
223
+
224
+ // 输出完成信息
225
+ console.log(`\n${GREEN}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`);
226
+ console.log(`${GREEN}${BOLD}✅ easyAI 框架初始化完成!${NC}`);
227
+ console.log(`${GREEN}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`);
228
+ console.log(`
229
+ ${BOLD}下一步:配置 MCP Server${NC}
230
+
231
+ 在 Antigravity IDE 的 MCP 设置中添加:
232
+
233
+ {
234
+ "easyai-mcp-server": {
235
+ "command": "npx",
236
+ "args": ["-y", "@geeseeker/easyai-dev", "serve"]
237
+ }
238
+ }
239
+
240
+ 配置完成后,重启 IDE,输入 ${GREEN}/pm${NC} 启动项目经理。
241
+ `);
242
+ }
243
+
244
+ /**
245
+ * 检查框架完整性
246
+ * @param targetDir - 目标项目目录(绝对路径)
247
+ */
248
+ export async function doCheck(targetDir) {
249
+ let missing = 0;
250
+ let warnings = 0;
251
+
252
+ console.log(`\n${BLUE}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`);
253
+ console.log(`${BLUE}${BOLD}easyAI 框架完整性检查${NC}`);
254
+ console.log(`${BLUE}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`);
255
+ console.log(`目标项目: ${GREEN}${targetDir}${NC}\n`);
256
+
257
+ // 检查目录
258
+ console.log(`${BOLD}目录检查:${NC}`);
259
+ for (const dir of REQUIRED_DIRS) {
260
+ if (fs.existsSync(path.join(targetDir, dir))) {
261
+ console.log(` ${GREEN}✓${NC} ${dir}/`);
262
+ } else {
263
+ console.log(` ${RED}✗${NC} ${dir}/ ${RED}(缺失)${NC}`);
264
+ missing++;
265
+ }
266
+ }
267
+
268
+ // 检查文件
269
+ console.log(`\n${BOLD}文件检查:${NC}`);
270
+ for (const file of REQUIRED_FILES) {
271
+ if (fs.existsSync(path.join(targetDir, file))) {
272
+ console.log(` ${GREEN}✓${NC} ${file}`);
273
+ } else {
274
+ console.log(` ${RED}✗${NC} ${file} ${RED}(缺失)${NC}`);
275
+ missing++;
276
+ }
277
+ }
278
+
279
+ // 检查版本
280
+ console.log(`\n${BOLD}版本检查:${NC}`);
281
+ const versionFile = path.join(targetDir, ".easyai-version");
282
+ if (fs.existsSync(versionFile)) {
283
+ const installedVersion = fs.readFileSync(versionFile, "utf-8").trim();
284
+ if (installedVersion === FRAMEWORK_VERSION) {
285
+ console.log(
286
+ ` ${GREEN}✓${NC} 框架版本: v${installedVersion} (最新)`,
287
+ );
288
+ } else {
289
+ console.log(
290
+ ` ${YELLOW}⚠${NC} 框架版本: v${installedVersion}` +
291
+ ` (最新: v${FRAMEWORK_VERSION})`,
292
+ );
293
+ warnings++;
294
+ }
295
+ } else {
296
+ console.log(` ${RED}✗${NC} .easyai-version 不存在`);
297
+ missing++;
298
+ }
299
+
300
+ // 检查 Git 状态
301
+ console.log(`\n${BOLD}Git 状态:${NC}`);
302
+ try {
303
+ execSync("git rev-parse --is-inside-work-tree", {
304
+ cwd: targetDir,
305
+ stdio: "pipe",
306
+ });
307
+ console.log(` ${GREEN}✓${NC} Git 仓库已初始化`);
308
+ } catch {
309
+ console.log(
310
+ ` ${YELLOW}⚠${NC} 非 Git 仓库` +
311
+ ` — worktree 等功能将不可用`,
312
+ );
313
+ warnings++;
314
+ }
315
+
316
+ // 汇总
317
+ console.log("");
318
+ const total = REQUIRED_DIRS.length + REQUIRED_FILES.length + 1;
319
+ if (missing === 0 && warnings === 0) {
320
+ console.log(
321
+ `${GREEN}✅ 框架完整,共 ${total} 项全部通过${NC}`,
322
+ );
323
+ } else if (missing === 0) {
324
+ console.log(
325
+ `${YELLOW}⚠ 框架基本完整,有 ${warnings} 项警告${NC}`,
326
+ );
327
+ } else {
328
+ console.log(
329
+ `${RED}⚠ 发现 ${missing} 项缺失,` +
330
+ `${warnings} 项警告${NC}`,
331
+ );
332
+ console.log(
333
+ `${RED} 建议运行: npx @geeseeker/easyai-dev init .${NC}`,
334
+ );
335
+ }
336
+ }
337
+
338
+ /**
339
+ * 更新框架
340
+ * 只更新 .agents/ 和 .trellis/spec/,不覆盖用户数据
341
+ * @param targetDir - 目标项目目录(绝对路径)
342
+ */
343
+ export async function doUpdate(targetDir) {
344
+ // 检查是否已初始化
345
+ if (!fs.existsSync(path.join(targetDir, ".agents"))) {
346
+ console.error(
347
+ `${RED}✗ 项目未初始化,请先运行: easyai-dev init${NC}`,
348
+ );
349
+ process.exit(1);
350
+ }
351
+
352
+ // 检查版本
353
+ const versionFile = path.join(targetDir, ".easyai-version");
354
+ let installedVersion = "unknown";
355
+ if (fs.existsSync(versionFile)) {
356
+ installedVersion = fs.readFileSync(versionFile, "utf-8").trim();
357
+ }
358
+
359
+ if (installedVersion === FRAMEWORK_VERSION) {
360
+ console.log(
361
+ `${GREEN}✅ 框架已是最新版本 (v${FRAMEWORK_VERSION})${NC}`,
362
+ );
363
+ return;
364
+ }
365
+
366
+ console.log(`\n${BLUE}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`);
367
+ console.log(`${BLUE}${BOLD}easyAI 框架更新${NC}`);
368
+ console.log(`${BLUE}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`);
369
+ console.log(
370
+ `当前版本: ${YELLOW}v${installedVersion}${NC}` +
371
+ ` → 目标版本: ${GREEN}v${FRAMEWORK_VERSION}${NC}\n`,
372
+ );
373
+
374
+ // 更新 .agents/(完整替换)
375
+ const agentsSrc = path.join(SKELETON_DIR, ".agents");
376
+ const agentsDest = path.join(targetDir, ".agents");
377
+ if (fs.existsSync(agentsSrc)) {
378
+ // 备份当前 .agents/
379
+ const backupDir = path.join(
380
+ targetDir,
381
+ `.agents.bak.${Date.now()}`,
382
+ );
383
+ fs.renameSync(agentsDest, backupDir);
384
+ copyDirSync(agentsSrc, agentsDest, { noOverwrite: false, log: false });
385
+ console.log(
386
+ ` ${GREEN}✓${NC} .agents/ — 已更新(备份: ${path.basename(backupDir)})`,
387
+ );
388
+ }
389
+
390
+ // 更新 .trellis/spec/(完整替换)
391
+ const specSrc = path.join(SKELETON_DIR, ".trellis", "spec");
392
+ const specDest = path.join(targetDir, ".trellis", "spec");
393
+ if (fs.existsSync(specSrc)) {
394
+ const specBackup = path.join(
395
+ targetDir,
396
+ ".trellis",
397
+ `spec.bak.${Date.now()}`,
398
+ );
399
+ if (fs.existsSync(specDest)) {
400
+ fs.renameSync(specDest, specBackup);
401
+ }
402
+ copyDirSync(specSrc, specDest, { noOverwrite: false, log: false });
403
+ console.log(
404
+ ` ${GREEN}✓${NC} .trellis/spec/ — 已更新`,
405
+ );
406
+ }
407
+
408
+ // 更新版本清单
409
+ fs.writeFileSync(versionFile, `${FRAMEWORK_VERSION}\n`);
410
+ console.log(` ${GREEN}✓${NC} .easyai-version — v${FRAMEWORK_VERSION}`);
411
+
412
+ // 不更新的内容
413
+ console.log(`\n${BOLD}以下内容未被修改(保留用户数据):${NC}`);
414
+ console.log(` ${YELLOW}⊘${NC} .trellis/config/config.yaml`);
415
+ console.log(` ${YELLOW}⊘${NC} .trellis/tasks/`);
416
+ console.log(` ${YELLOW}⊘${NC} .trellis/workspace/`);
417
+ console.log(` ${YELLOW}⊘${NC} .docs/`);
418
+ console.log(` ${YELLOW}⊘${NC} README.md`);
419
+ console.log(` ${YELLOW}⊘${NC} .gitignore`);
420
+
421
+ console.log(`\n${GREEN}${BOLD}✅ 框架更新完成!${NC}`);
422
+ console.log(
423
+ `${YELLOW}注意: 旧版 .agents/ 已备份。确认无误后可手动删除。${NC}`,
424
+ );
425
+ }
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * easyAI MCP Server — 入口文件
4
+ *
5
+ * 完整版本(M01-M05):
6
+ * - 注册所有任务管理工具(task_list, task_get, task_create, task_transition, task_append_log, task_cancel)
7
+ * - 注册所有日志工具(journal_append, journal_search)
8
+ * - 注册项目状态工具(project_status)
9
+ * - 注册上下文管理工具(context_generate, context_budget, spec_validate, plan_validate)
10
+ * - 注册冲突检测工具(conflict_check)
11
+ * - 注册所有资源(status, task-context, subtask-context, spec, journal)
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;GAUG"}
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * easyAI MCP Server — 入口文件
4
+ *
5
+ * 完整版本(M01-M05):
6
+ * - 注册所有任务管理工具(task_list, task_get, task_create, task_transition, task_append_log, task_cancel)
7
+ * - 注册所有日志工具(journal_append, journal_search)
8
+ * - 注册项目状态工具(project_status)
9
+ * - 注册上下文管理工具(context_generate, context_budget, spec_validate, plan_validate)
10
+ * - 注册冲突检测工具(conflict_check)
11
+ * - 注册所有资源(status, task-context, subtask-context, spec, journal)
12
+ */
13
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
14
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
15
+ // 工具模块导入
16
+ import { register as registerTaskList } from "./tools/task-list.js";
17
+ import { register as registerTaskGet } from "./tools/task-get.js";
18
+ import { register as registerTaskCreate } from "./tools/task-create.js";
19
+ import { register as registerTaskTransition } from "./tools/task-transition.js";
20
+ import { register as registerTaskAppendLog } from "./tools/task-append-log.js";
21
+ import { register as registerTaskCancel } from "./tools/task-cancel.js";
22
+ import { register as registerJournalAppend } from "./tools/journal-append.js";
23
+ import { register as registerJournalSearch } from "./tools/journal-search.js";
24
+ import { registerSubtaskCreate, registerSubtaskDependencyGraph, } from "./tools/subtask-tools.js";
25
+ import { registerWorktreeCreate, registerWorktreeMerge, registerWorktreeCleanup, } from "./tools/worktree-tools.js";
26
+ import { register as registerContextGenerate } from "./tools/context-generate.js";
27
+ import { register as registerContextBudget } from "./tools/context-budget.js";
28
+ import { register as registerSpecValidate } from "./tools/spec-validate.js";
29
+ import { register as registerPlanValidate } from "./tools/plan-validate.js";
30
+ import { register as registerConflictCheck } from "./tools/conflict-check.js";
31
+ import { registerFrameworkInit, registerFrameworkCheck, registerFrameworkUpdate, } from "./tools/framework-tools.js";
32
+ // 资源模块导入
33
+ import { register as registerStatusResource } from "./resources/status-resource.js";
34
+ import { register as registerTaskContextResource } from "./resources/task-context-resource.js";
35
+ import { register as registerSubtaskContextResource } from "./resources/subtask-context-resource.js";
36
+ import { register as registerSpecResource } from "./resources/spec-resource.js";
37
+ import { register as registerJournalResource } from "./resources/journal-resource.js";
38
+ // 工具函数导入
39
+ import { getProjectStatusData } from "./utils/status-utils.js";
40
+ // 创建 MCP Server 实例
41
+ const server = new McpServer({
42
+ name: "easyai-mcp-server",
43
+ version: "0.1.0",
44
+ }, {
45
+ capabilities: {
46
+ logging: {},
47
+ resources: {},
48
+ },
49
+ });
50
+ // ============================================
51
+ // Tool: project_status
52
+ // 获取项目当前状态概览(Git 状态 + 活跃任务摘要 + 最新日志)
53
+ // ============================================
54
+ server.tool("project_status", "获取项目当前状态概览。返回 Git 分支/状态/最近提交、活跃任务列表、以及最新的日志条目。", {}, async () => {
55
+ try {
56
+ // 使用共享的状态聚合器
57
+ const statusData = getProjectStatusData(5, 3);
58
+ return {
59
+ content: [
60
+ {
61
+ type: "text",
62
+ text: JSON.stringify(statusData, null, 2),
63
+ },
64
+ ],
65
+ };
66
+ }
67
+ catch (error) {
68
+ return {
69
+ content: [
70
+ {
71
+ type: "text",
72
+ text: JSON.stringify({
73
+ error: true,
74
+ message: error instanceof Error ? error.message : String(error),
75
+ }),
76
+ },
77
+ ],
78
+ isError: true,
79
+ };
80
+ }
81
+ });
82
+ // ============================================
83
+ // 注册所有工具模块
84
+ // ============================================
85
+ registerTaskList(server);
86
+ registerTaskGet(server);
87
+ registerTaskCreate(server);
88
+ registerTaskTransition(server);
89
+ registerTaskAppendLog(server);
90
+ registerTaskCancel(server);
91
+ registerJournalAppend(server);
92
+ registerJournalSearch(server);
93
+ registerSubtaskCreate(server);
94
+ registerSubtaskDependencyGraph(server);
95
+ registerWorktreeCreate(server);
96
+ registerWorktreeMerge(server);
97
+ registerWorktreeCleanup(server);
98
+ registerContextGenerate(server);
99
+ registerContextBudget(server);
100
+ registerSpecValidate(server);
101
+ registerPlanValidate(server);
102
+ registerConflictCheck(server);
103
+ registerFrameworkInit(server);
104
+ registerFrameworkCheck(server);
105
+ registerFrameworkUpdate(server);
106
+ // ============================================
107
+ // 注册所有资源模块
108
+ // ============================================
109
+ registerStatusResource(server);
110
+ registerTaskContextResource(server);
111
+ registerSubtaskContextResource(server);
112
+ registerSpecResource(server);
113
+ registerJournalResource(server);
114
+ // ============================================
115
+ // 启动服务器
116
+ // ============================================
117
+ async function main() {
118
+ const transport = new StdioServerTransport();
119
+ await server.connect(transport);
120
+ console.error("easyAI MCP Server v0.1.0 started");
121
+ }
122
+ main().catch((error) => {
123
+ console.error("Failed to start easyAI MCP Server:", error);
124
+ process.exit(1);
125
+ });
126
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ /**
3
+ * 注册 journal 资源
4
+ * URI: trellis://journal/latest
5
+ * 返回: 最新的日志条目(最近 5 条)
6
+ */
7
+ export declare function register(server: McpServer): void;
8
+ //# sourceMappingURL=journal-resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal-resource.d.ts","sourceRoot":"","sources":["../../src/resources/journal-resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2ChD"}
@@ -0,0 +1,46 @@
1
+ import { getLatestEntries } from '../utils/journal-utils.js';
2
+ /**
3
+ * 注册 journal 资源
4
+ * URI: trellis://journal/latest
5
+ * 返回: 最新的日志条目(最近 5 条)
6
+ */
7
+ export function register(server) {
8
+ server.resource('最新日志', 'trellis://journal/latest', async () => {
9
+ try {
10
+ // 获取最新 5 条日志
11
+ const entries = getLatestEntries(5);
12
+ // 格式化输出
13
+ const formattedEntries = entries.map(entry => ({
14
+ date: entry.date,
15
+ tags: entry.tags,
16
+ tasks_touched: entry.tasks_touched,
17
+ content: entry.content,
18
+ }));
19
+ return {
20
+ contents: [
21
+ {
22
+ uri: 'trellis://journal/latest',
23
+ text: JSON.stringify({
24
+ count: formattedEntries.length,
25
+ entries: formattedEntries,
26
+ }, null, 2),
27
+ },
28
+ ],
29
+ };
30
+ }
31
+ catch (error) {
32
+ return {
33
+ contents: [
34
+ {
35
+ uri: 'trellis://journal/latest',
36
+ text: JSON.stringify({
37
+ error: true,
38
+ message: error instanceof Error ? error.message : String(error),
39
+ }),
40
+ },
41
+ ],
42
+ };
43
+ }
44
+ });
45
+ }
46
+ //# sourceMappingURL=journal-resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal-resource.js","sourceRoot":"","sources":["../../src/resources/journal-resource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,CAAC,QAAQ,CACb,MAAM,EACN,0BAA0B,EAC1B,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,aAAa;YACb,MAAM,OAAO,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;YAEpC,QAAQ;YACR,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAC7C,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,aAAa,EAAE,KAAK,CAAC,aAAa;gBAClC,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB,CAAC,CAAC,CAAC;YAEJ,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,0BAA0B;wBAC/B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,gBAAgB,CAAC,MAAM;4BAC9B,OAAO,EAAE,gBAAgB;yBAC1B,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,0BAA0B;wBAC/B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,IAAI;4BACX,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;yBAChE,CAAC;qBACH;iBACF;aACF,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * 注册 spec 资源
4
+ * 支持两种 URI 协议:
5
+ * 1. trellis://spec/{category}/{name} — 完整路径
6
+ * 2. spec://{category}/{name} — 简写语法(自动展开)
7
+ *
8
+ * 两者读取相同的 .trellis/spec/{category}/{name}.md 文件。
9
+ */
10
+ export declare function register(server: McpServer): void;
11
+ //# sourceMappingURL=spec-resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-resource.d.ts","sourceRoot":"","sources":["../../src/resources/spec-resource.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAuIpE;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAiBhD"}