@roarpeng/graphflow 1.1.0 → 1.3.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.
- package/CHANGELOG.md +23 -0
- package/README.md +49 -3
- package/dist/agents/insight.js +5 -3
- package/dist/agents/insight.js.map +1 -1
- package/dist/agents/planner.d.ts.map +1 -1
- package/dist/agents/planner.js +7 -2
- package/dist/agents/planner.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +1 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/embedding-factory.d.ts.map +1 -1
- package/dist/config/embedding-factory.js +23 -12
- package/dist/config/embedding-factory.js.map +1 -1
- package/dist/config/loader.d.ts +11 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +103 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/core/agent-assignment.d.ts +39 -0
- package/dist/core/agent-assignment.d.ts.map +1 -0
- package/dist/core/agent-assignment.js +73 -0
- package/dist/core/agent-assignment.js.map +1 -0
- package/dist/core/agent-delegation.d.ts +1 -0
- package/dist/core/agent-delegation.d.ts.map +1 -1
- package/dist/core/agent-delegation.js +30 -1
- package/dist/core/agent-delegation.js.map +1 -1
- package/dist/core/dag-checkpoint.d.ts +83 -0
- package/dist/core/dag-checkpoint.d.ts.map +1 -0
- package/dist/core/dag-checkpoint.js +164 -0
- package/dist/core/dag-checkpoint.js.map +1 -0
- package/dist/core/dag-engine.d.ts +9 -0
- package/dist/core/dag-engine.d.ts.map +1 -1
- package/dist/core/dag-engine.js +42 -0
- package/dist/core/dag-engine.js.map +1 -1
- package/dist/core/merge-agent-insight.d.ts.map +1 -1
- package/dist/core/merge-agent-insight.js +39 -8
- package/dist/core/merge-agent-insight.js.map +1 -1
- package/dist/core/orchestrator-context.d.ts +10 -0
- package/dist/core/orchestrator-context.d.ts.map +1 -0
- package/dist/core/orchestrator-context.js +112 -0
- package/dist/core/orchestrator-context.js.map +1 -0
- package/dist/core/orchestrator-episode.d.ts +13 -0
- package/dist/core/orchestrator-episode.d.ts.map +1 -0
- package/dist/core/orchestrator-episode.js +128 -0
- package/dist/core/orchestrator-episode.js.map +1 -0
- package/dist/core/orchestrator-route.d.ts +20 -0
- package/dist/core/orchestrator-route.d.ts.map +1 -0
- package/dist/core/orchestrator-route.js +51 -0
- package/dist/core/orchestrator-route.js.map +1 -0
- package/dist/core/orchestrator.d.ts +2 -38
- package/dist/core/orchestrator.d.ts.map +1 -1
- package/dist/core/orchestrator.js +97 -286
- package/dist/core/orchestrator.js.map +1 -1
- package/dist/core/triage.d.ts +21 -0
- package/dist/core/triage.d.ts.map +1 -1
- package/dist/core/triage.js +25 -6
- package/dist/core/triage.js.map +1 -1
- package/dist/core/types.d.ts +53 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/graph/context-slicer-types.d.ts +62 -0
- package/dist/graph/context-slicer-types.d.ts.map +1 -0
- package/dist/graph/context-slicer-types.js +13 -0
- package/dist/graph/context-slicer-types.js.map +1 -0
- package/dist/graph/context-slicer-utils.d.ts +24 -0
- package/dist/graph/context-slicer-utils.d.ts.map +1 -0
- package/dist/graph/context-slicer-utils.js +118 -0
- package/dist/graph/context-slicer-utils.js.map +1 -0
- package/dist/graph/context-slicer.d.ts +6 -61
- package/dist/graph/context-slicer.d.ts.map +1 -1
- package/dist/graph/context-slicer.js +73 -170
- package/dist/graph/context-slicer.js.map +1 -1
- package/dist/graph/file-indexer-cache.d.ts +34 -0
- package/dist/graph/file-indexer-cache.d.ts.map +1 -0
- package/dist/graph/file-indexer-cache.js +105 -0
- package/dist/graph/file-indexer-cache.js.map +1 -0
- package/dist/graph/file-indexer-edges.d.ts +55 -0
- package/dist/graph/file-indexer-edges.d.ts.map +1 -0
- package/dist/graph/file-indexer-edges.js +258 -0
- package/dist/graph/file-indexer-edges.js.map +1 -0
- package/dist/graph/file-indexer-nodes.d.ts +43 -0
- package/dist/graph/file-indexer-nodes.d.ts.map +1 -0
- package/dist/graph/file-indexer-nodes.js +137 -0
- package/dist/graph/file-indexer-nodes.js.map +1 -0
- package/dist/graph/file-indexer-walker.d.ts +35 -0
- package/dist/graph/file-indexer-walker.d.ts.map +1 -0
- package/dist/graph/file-indexer-walker.js +80 -0
- package/dist/graph/file-indexer-walker.js.map +1 -0
- package/dist/graph/file-indexer.d.ts +13 -39
- package/dist/graph/file-indexer.d.ts.map +1 -1
- package/dist/graph/file-indexer.js +167 -600
- package/dist/graph/file-indexer.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/agent-mcp-installer.d.ts +25 -1
- package/dist/integrations/agent-mcp-installer.d.ts.map +1 -1
- package/dist/integrations/agent-mcp-installer.js +174 -13
- package/dist/integrations/agent-mcp-installer.js.map +1 -1
- package/dist/integrations/skill-installer.d.ts +80 -0
- package/dist/integrations/skill-installer.d.ts.map +1 -0
- package/dist/integrations/skill-installer.js +612 -0
- package/dist/integrations/skill-installer.js.map +1 -0
- package/dist/learning/embeddings.d.ts +11 -0
- package/dist/learning/embeddings.d.ts.map +1 -1
- package/dist/learning/embeddings.js +24 -0
- package/dist/learning/embeddings.js.map +1 -1
- package/dist/learning/episodic-memory.d.ts +3 -2
- package/dist/learning/episodic-memory.d.ts.map +1 -1
- package/dist/learning/episodic-memory.js +105 -10
- package/dist/learning/episodic-memory.js.map +1 -1
- package/dist/learning/local-embedding.d.ts.map +1 -1
- package/dist/learning/local-embedding.js +16 -0
- package/dist/learning/local-embedding.js.map +1 -1
- package/dist/learning/seed-skills.d.ts +21 -0
- package/dist/learning/seed-skills.d.ts.map +1 -0
- package/dist/learning/seed-skills.js +113 -0
- package/dist/learning/seed-skills.js.map +1 -0
- package/dist/learning/skill-evolution.d.ts +1 -1
- package/dist/learning/skill-evolution.d.ts.map +1 -1
- package/dist/learning/skill-evolution.js +1 -1
- package/dist/learning/skill-evolution.js.map +1 -1
- package/dist/learning/skill-package.d.ts +55 -0
- package/dist/learning/skill-package.d.ts.map +1 -0
- package/dist/learning/skill-package.js +115 -0
- package/dist/learning/skill-package.js.map +1 -0
- package/dist/learning/triage-telemetry.d.ts +43 -0
- package/dist/learning/triage-telemetry.d.ts.map +1 -0
- package/dist/learning/triage-telemetry.js +114 -0
- package/dist/learning/triage-telemetry.js.map +1 -0
- package/dist/surfaces/cli/index.js +74 -0
- package/dist/surfaces/cli/index.js.map +1 -1
- package/dist/surfaces/cli/init.d.ts +28 -2
- package/dist/surfaces/cli/init.d.ts.map +1 -1
- package/dist/surfaces/cli/init.js +163 -30
- package/dist/surfaces/cli/init.js.map +1 -1
- package/dist/surfaces/cli/output.d.ts.map +1 -1
- package/dist/surfaces/cli/output.js +6 -0
- package/dist/surfaces/cli/output.js.map +1 -1
- package/dist/surfaces/cli/runtime/graph.d.ts +23 -0
- package/dist/surfaces/cli/runtime/graph.d.ts.map +1 -1
- package/dist/surfaces/cli/runtime/graph.js +40 -0
- package/dist/surfaces/cli/runtime/graph.js.map +1 -1
- package/dist/surfaces/cli/runtime/routing.d.ts.map +1 -1
- package/dist/surfaces/cli/runtime/routing.js +8 -1
- package/dist/surfaces/cli/runtime/routing.js.map +1 -1
- package/dist/surfaces/cli/runtime.d.ts +1 -1
- package/dist/surfaces/cli/runtime.d.ts.map +1 -1
- package/dist/surfaces/cli/runtime.js +4 -1
- package/dist/surfaces/cli/runtime.js.map +1 -1
- package/dist/surfaces/mcp/tool-definitions.js +20 -20
- package/dist/surfaces/mcp/tool-definitions.js.map +1 -1
- package/package.json +4 -3
- package/scripts/safe-postinstall.cjs +323 -5
|
@@ -1,11 +1,56 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const { existsSync, mkdirSync, copyFileSync, readFileSync } = require("node:fs");
|
|
2
|
+
const { existsSync, mkdirSync, copyFileSync, readFileSync, writeFileSync, unlinkSync } = require("node:fs");
|
|
3
3
|
const { join } = require("node:path");
|
|
4
4
|
const { homedir } = require("node:os");
|
|
5
5
|
const { spawnSync } = require("node:child_process");
|
|
6
6
|
|
|
7
7
|
const isWindows = process.platform === "win32";
|
|
8
8
|
|
|
9
|
+
// ─── 版本比较与自动更新 ───
|
|
10
|
+
|
|
11
|
+
/** 版本标记文件路径:记录上次安装的 GraphFlow 版本号 */
|
|
12
|
+
const VERSION_FILE = join(homedir(), ".graphflow-install-version");
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 读取上次安装时记录的版本号
|
|
16
|
+
* @returns {string | null} 上次版本号,不存在则返回 null
|
|
17
|
+
*/
|
|
18
|
+
function readPreviousVersion() {
|
|
19
|
+
try {
|
|
20
|
+
if (existsSync(VERSION_FILE)) {
|
|
21
|
+
return readFileSync(VERSION_FILE, "utf8").trim();
|
|
22
|
+
}
|
|
23
|
+
} catch {
|
|
24
|
+
// 忽略读取失败
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 将当前版本号写入标记文件
|
|
31
|
+
* @param {string} version 当前版本号
|
|
32
|
+
*/
|
|
33
|
+
function writeCurrentVersion(version) {
|
|
34
|
+
try {
|
|
35
|
+
writeFileSync(VERSION_FILE, version, "utf8");
|
|
36
|
+
} catch {
|
|
37
|
+
// 忽略写入失败
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 比较版本号,判断是否需要强制更新 Skill/Rules/MCP 文件
|
|
43
|
+
* @param {string} currentVersion 当前安装的版本号
|
|
44
|
+
* @returns {boolean} 是否需要强制更新
|
|
45
|
+
*/
|
|
46
|
+
function needsForceUpdate(currentVersion) {
|
|
47
|
+
const previousVersion = readPreviousVersion();
|
|
48
|
+
if (!previousVersion) {
|
|
49
|
+
return true; // 首次安装或无版本记录,强制更新
|
|
50
|
+
}
|
|
51
|
+
return previousVersion !== currentVersion;
|
|
52
|
+
}
|
|
53
|
+
|
|
9
54
|
function resolveHomePaths() {
|
|
10
55
|
const home = homedir();
|
|
11
56
|
const appData = process.env.APPDATA || (isWindows ? join(home, "AppData", "Roaming") : "");
|
|
@@ -147,6 +192,231 @@ function isGlobalInstall() {
|
|
|
147
192
|
return false;
|
|
148
193
|
}
|
|
149
194
|
|
|
195
|
+
/**
|
|
196
|
+
* 获取 Cursor Rules 源文件路径(graphflow.mdc)
|
|
197
|
+
* 优先从 dist 目录查找,回退到 src 目录。
|
|
198
|
+
* @returns {string | null} 源文件路径,不存在则返回 null
|
|
199
|
+
*/
|
|
200
|
+
function getCursorRulesSourceFile() {
|
|
201
|
+
const candidates = [
|
|
202
|
+
join(__dirname, "..", "dist", "surfaces", "cursor-rules", "graphflow.mdc"),
|
|
203
|
+
join(__dirname, "..", "src", "surfaces", "cursor-rules", "graphflow.mdc"),
|
|
204
|
+
];
|
|
205
|
+
for (const filePath of candidates) {
|
|
206
|
+
if (existsSync(filePath)) {
|
|
207
|
+
return filePath;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* 获取 CLAUDE.md 源文件路径
|
|
215
|
+
* 优先从包根目录查找。
|
|
216
|
+
* @returns {string | null} 源文件路径,不存在则返回 null
|
|
217
|
+
*/
|
|
218
|
+
function getClaudeMdSourceFile() {
|
|
219
|
+
const candidates = [
|
|
220
|
+
join(__dirname, "..", "CLAUDE.md"),
|
|
221
|
+
];
|
|
222
|
+
for (const filePath of candidates) {
|
|
223
|
+
if (existsSync(filePath)) {
|
|
224
|
+
return filePath;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* 获取 Cursor rules 目录列表。
|
|
232
|
+
* Cursor 的 rules 目录为 ~/.cursor/rules/(跨平台一致),
|
|
233
|
+
* 也有用户使用 %APPDATA%/Cursor/User/rules/。
|
|
234
|
+
* @returns {Array<{name: string, rulesDir: string}>} Cursor rules 目录列表
|
|
235
|
+
*/
|
|
236
|
+
function getCursorRulesDirs() {
|
|
237
|
+
const { home, appData } = resolveHomePaths();
|
|
238
|
+
const dirs = [];
|
|
239
|
+
|
|
240
|
+
// ~/.cursor/rules — Cursor 的标准 rules 目录
|
|
241
|
+
if (existsSync(join(home, ".cursor"))) {
|
|
242
|
+
dirs.push({
|
|
243
|
+
name: "Cursor (~/.cursor)",
|
|
244
|
+
rulesDir: join(home, ".cursor", "rules"),
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// %APPDATA%/Cursor/User/rules — Windows 上的备选目录
|
|
249
|
+
if (isWindows && existsSync(join(appData, "Cursor", "User"))) {
|
|
250
|
+
dirs.push({
|
|
251
|
+
name: "Cursor (AppData)",
|
|
252
|
+
rulesDir: join(appData, "Cursor", "User", "rules"),
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return dirs;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* 通用文件安装逻辑:检测 marker → 创建目标目录 → 复制文件 → 已存在且内容相同则跳过
|
|
261
|
+
* @param {string} sourceFile 源文件路径
|
|
262
|
+
* @param {string} destDir 目标目录
|
|
263
|
+
* @param {string} destFileName 目标文件名
|
|
264
|
+
* @returns {{status: string, reason?: string}} 安装结果
|
|
265
|
+
*/
|
|
266
|
+
function installFileToDir(sourceFile, destDir, destFileName) {
|
|
267
|
+
if (!existsSync(sourceFile)) {
|
|
268
|
+
return { status: "skipped", reason: "源文件不存在" };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const destFile = join(destDir, destFileName);
|
|
272
|
+
const existed = existsSync(destFile);
|
|
273
|
+
|
|
274
|
+
if (existed) {
|
|
275
|
+
const existingContent = readFileSync(destFile, "utf8");
|
|
276
|
+
const newContent = readFileSync(sourceFile, "utf8");
|
|
277
|
+
if (existingContent === newContent) {
|
|
278
|
+
return { status: "skipped", reason: "已是最新" };
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
mkdirSync(destDir, { recursive: true });
|
|
283
|
+
copyFileSync(sourceFile, destFile);
|
|
284
|
+
|
|
285
|
+
return { status: existed ? "updated" : "created" };
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* 检测并安装 Cursor Rules(graphflow.mdc)到 Cursor rules 目录
|
|
290
|
+
* @returns {{status: string, reason?: string} | null} 安装结果,无需安装则返回 null
|
|
291
|
+
*/
|
|
292
|
+
function installCursorRules() {
|
|
293
|
+
const sourceFile = getCursorRulesSourceFile();
|
|
294
|
+
if (!sourceFile) {
|
|
295
|
+
return { status: "skipped", reason: "Cursor Rules 源文件不存在" };
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const dirs = getCursorRulesDirs();
|
|
299
|
+
if (dirs.length === 0) {
|
|
300
|
+
return null; // 未检测到 Cursor,跳过
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// 只需要安装到第一个有效目录
|
|
304
|
+
const target = dirs[0];
|
|
305
|
+
return installFileToDir(sourceFile, target.rulesDir, "graphflow.mdc");
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* 检测并安装 CLAUDE.md 到 ~/.claude/CLAUDE.md(Claude Code 约定)
|
|
310
|
+
* @returns {{status: string, reason?: string} | null} 安装结果,无需安装则返回 null
|
|
311
|
+
*/
|
|
312
|
+
function installClaudeMd() {
|
|
313
|
+
const sourceFile = getClaudeMdSourceFile();
|
|
314
|
+
if (!sourceFile) {
|
|
315
|
+
return { status: "skipped", reason: "CLAUDE.md 源文件不存在" };
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const { home } = resolveHomePaths();
|
|
319
|
+
const claudeDir = join(home, ".claude");
|
|
320
|
+
|
|
321
|
+
// 检测 ~/.claude 是否存在(Claude Code 的 marker 目录)
|
|
322
|
+
if (!existsSync(claudeDir)) {
|
|
323
|
+
return null; // 未检测到 Claude Code,跳过
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return installFileToDir(sourceFile, claudeDir, "CLAUDE.md");
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* 注入 workspace 级 MCP 配置到已存在的 workspace MCP 文件。
|
|
331
|
+
* 仅在检测到 .cursor/mcp.json 或 .vscode/mcp.json 时生效(更安全,只在当前项目内)。
|
|
332
|
+
* @param {string} workspaceRoot 当前项目根目录
|
|
333
|
+
* @returns {Array<{configPath: string, status: string}>} 注入结果列表
|
|
334
|
+
*/
|
|
335
|
+
function installWorkspaceLevelMcp(workspaceRoot) {
|
|
336
|
+
const results = [];
|
|
337
|
+
const configFiles = [
|
|
338
|
+
{ path: join(workspaceRoot, ".cursor", "mcp.json"), name: "Cursor", key: "mcpServers" },
|
|
339
|
+
{ path: join(workspaceRoot, ".vscode", "mcp.json"), name: "VS Code", key: "servers" },
|
|
340
|
+
];
|
|
341
|
+
|
|
342
|
+
const mcpEntry = {
|
|
343
|
+
command: "npx",
|
|
344
|
+
args: ["-y", "--package=@roarpeng/graphflow", "graphflow-mcp"],
|
|
345
|
+
env: { GRAPHFLOW_MCP_STDIO: "1", GRAPHFLOW_LOG_JSON: "1" },
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
for (const config of configFiles) {
|
|
349
|
+
if (!existsSync(config.path)) {
|
|
350
|
+
continue; // 该 workspace 级配置不存在,跳过
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
try {
|
|
354
|
+
let json = {};
|
|
355
|
+
try {
|
|
356
|
+
json = JSON.parse(readFileSync(config.path, "utf8"));
|
|
357
|
+
} catch {
|
|
358
|
+
// 配置文件为空或损坏,初始化为空对象
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const servers = json[config.key] || {};
|
|
362
|
+
if (servers.graphflow) {
|
|
363
|
+
results.push({ configPath: config.path, status: "skipped", name: config.name, reason: "already configured" });
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
servers.graphflow = mcpEntry;
|
|
368
|
+
json[config.key] = servers;
|
|
369
|
+
writeFileSync(config.path, JSON.stringify(json, null, 2) + "\n", "utf8");
|
|
370
|
+
results.push({ configPath: config.path, status: "created", name: config.name });
|
|
371
|
+
console.log(`[GraphFlow] Workspace 级 MCP 已注入到 ${config.path} (${config.name})`);
|
|
372
|
+
} catch (err) {
|
|
373
|
+
results.push({ configPath: config.path, status: "error", name: config.name, reason: err.message });
|
|
374
|
+
console.log(`[GraphFlow] Workspace 级 MCP 注入失败 ${config.path}: ${err.message}`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return results;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* 在 workspace 级创建 .graphflow/skills/ 目录并复制 Skill 文件。
|
|
383
|
+
* 仅在检测到 .cursor/mcp.json 或 .vscode/mcp.json 时生效。
|
|
384
|
+
* @param {string} workspaceRoot 当前项目根目录
|
|
385
|
+
*/
|
|
386
|
+
function installWorkspaceLevelSkills(workspaceRoot) {
|
|
387
|
+
const configFiles = [
|
|
388
|
+
join(workspaceRoot, ".cursor", "mcp.json"),
|
|
389
|
+
join(workspaceRoot, ".vscode", "mcp.json"),
|
|
390
|
+
];
|
|
391
|
+
const hasWorkspaceConfig = configFiles.some((p) => existsSync(p));
|
|
392
|
+
|
|
393
|
+
if (!hasWorkspaceConfig) {
|
|
394
|
+
return; // 无 workspace 级 MCP 配置,跳过 Skill 安装
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const skillSourceDir = getSkillSourceDir();
|
|
398
|
+
if (!skillSourceDir) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// 在 .graphflow/skills/graphflow/ 下创建 workspace 级 Skill
|
|
403
|
+
const skillDestDir = join(workspaceRoot, ".graphflow", "skills", "graphflow");
|
|
404
|
+
const result = installSkill(skillDestDir, skillSourceDir);
|
|
405
|
+
if (result.status !== "skipped") {
|
|
406
|
+
console.log(`[GraphFlow] Workspace 级 Skill: ${result.status}${result.reason ? ` (${result.reason})` : ""} -> ${skillDestDir}`);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// 同时安装 Cursor Rules 到 workspace 级 .cursor/rules/
|
|
410
|
+
const cursorRulesSource = getCursorRulesSourceFile();
|
|
411
|
+
if (cursorRulesSource && existsSync(join(workspaceRoot, ".cursor"))) {
|
|
412
|
+
const cursorRulesDir = join(workspaceRoot, ".cursor", "rules");
|
|
413
|
+
const rulesResult = installFileToDir(cursorRulesSource, cursorRulesDir, "graphflow.mdc");
|
|
414
|
+
if (rulesResult.status !== "skipped") {
|
|
415
|
+
console.log(`[GraphFlow] Workspace 级 Cursor Rules: ${rulesResult.status}${rulesResult.reason ? ` (${rulesResult.reason})` : ""}`);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
150
420
|
function main() {
|
|
151
421
|
if (process.env.GRAPHFLOW_SKIP_POSTINSTALL === "1" || process.env.CI === "true") {
|
|
152
422
|
process.exit(0);
|
|
@@ -156,13 +426,44 @@ function main() {
|
|
|
156
426
|
const explicitlyEnabled = process.env.GRAPHFLOW_ENABLE_POSTINSTALL === "1";
|
|
157
427
|
|
|
158
428
|
if (!globalInstall && !explicitlyEnabled) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
429
|
+
// 本地安装:检测 workspace 级 MCP 配置,若有则自动注入 workspace 级 MCP + Skill
|
|
430
|
+
const workspaceRoot = process.cwd();
|
|
431
|
+
const workspaceMcpResults = installWorkspaceLevelMcp(workspaceRoot);
|
|
432
|
+
const hasWorkspaceConfig = workspaceMcpResults.some((r) => r.status === "created" || r.status === "skipped");
|
|
433
|
+
|
|
434
|
+
if (hasWorkspaceConfig) {
|
|
435
|
+
console.log("[GraphFlow] 检测到 workspace 级 MCP 配置,已自动注入 workspace 级 GraphFlow MCP。");
|
|
436
|
+
installWorkspaceLevelSkills(workspaceRoot);
|
|
437
|
+
console.log("[GraphFlow] 如需完整安装(用户级 MCP + Trae Skill),运行:");
|
|
438
|
+
console.log("[GraphFlow] npx @roarpeng/graphflow install");
|
|
439
|
+
} else {
|
|
440
|
+
console.log("[GraphFlow] Local install detected. Auto-setup skipped to avoid modifying your global config.");
|
|
441
|
+
console.log("[GraphFlow] To install GraphFlow MCP + Skill, run:");
|
|
442
|
+
console.log("[GraphFlow] npx @roarpeng/graphflow install");
|
|
443
|
+
}
|
|
162
444
|
process.exit(0);
|
|
163
445
|
}
|
|
164
446
|
|
|
447
|
+
// 读取当前版本号,用于版本比较和强制更新
|
|
448
|
+
let currentVersion = "unknown";
|
|
449
|
+
try {
|
|
450
|
+
const pkg = require("../package.json");
|
|
451
|
+
currentVersion = pkg.version || "unknown";
|
|
452
|
+
} catch {
|
|
453
|
+
// npm 包中 package.json 在上层目录;如果读取失败则跳过版本比较
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const forceUpdate = needsForceUpdate(currentVersion);
|
|
457
|
+
const previousVersion = readPreviousVersion();
|
|
458
|
+
|
|
165
459
|
console.log(`[GraphFlow] Running post-install setup (${globalInstall ? "global install" : "explicitly enabled"})...`);
|
|
460
|
+
console.log(`[GraphFlow] 版本: ${currentVersion}`);
|
|
461
|
+
|
|
462
|
+
if (forceUpdate && previousVersion) {
|
|
463
|
+
console.log(`[GraphFlow] 检测到版本变化 (${previousVersion} → ${currentVersion}),将强制更新所有 Skill/Rules/MCP 文件`);
|
|
464
|
+
} else if (forceUpdate && !previousVersion) {
|
|
465
|
+
console.log("[GraphFlow] 首次安装,将安装所有 Skill/Rules/MCP 文件");
|
|
466
|
+
}
|
|
166
467
|
|
|
167
468
|
const skillSourceDir = getSkillSourceDir();
|
|
168
469
|
const traeDirs = getTraeUserDirs();
|
|
@@ -185,6 +486,23 @@ function main() {
|
|
|
185
486
|
console.log(`[GraphFlow] MCP install skipped: ${mcpResult.reason}`);
|
|
186
487
|
}
|
|
187
488
|
|
|
489
|
+
// ─── Cursor Rules 安装 ───
|
|
490
|
+
const cursorRulesResult = installCursorRules();
|
|
491
|
+
if (cursorRulesResult) {
|
|
492
|
+
console.log(`[GraphFlow] Cursor Rules: ${cursorRulesResult.status}${cursorRulesResult.reason ? ` (${cursorRulesResult.reason})` : ""}`);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// ─── Claude Code 约定安装 ───
|
|
496
|
+
const claudeMdResult = installClaudeMd();
|
|
497
|
+
if (claudeMdResult) {
|
|
498
|
+
console.log(`[GraphFlow] Claude Code 约定: ${claudeMdResult.status}${claudeMdResult.reason ? ` (${claudeMdResult.reason})` : ""}`);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// 写入当前版本号标记文件
|
|
502
|
+
if (currentVersion !== "unknown") {
|
|
503
|
+
writeCurrentVersion(currentVersion);
|
|
504
|
+
}
|
|
505
|
+
|
|
188
506
|
console.log("[GraphFlow] Post-install complete.");
|
|
189
507
|
}
|
|
190
508
|
|
|
@@ -192,4 +510,4 @@ if (require.main === module) {
|
|
|
192
510
|
main();
|
|
193
511
|
}
|
|
194
512
|
|
|
195
|
-
module.exports = { installSkill, detectTrae, getTraeUserDirs, getSkillSourceDir };
|
|
513
|
+
module.exports = { installSkill, detectTrae, getTraeUserDirs, getSkillSourceDir, readPreviousVersion, writeCurrentVersion, needsForceUpdate, VERSION_FILE };
|