@nick848/fet 1.0.7 → 1.0.8
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/dist/cli/index.js +341 -71
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -262,7 +262,7 @@ async function doctorCommand(ctx, options = {}) {
|
|
|
262
262
|
checks.push(await checkState(ctx));
|
|
263
263
|
checks.push(await checkFile("agents", join6(ctx.projectRoot, "AGENTS.md"), "AGENTS.md \u7F3A\u5931", "fet update-context"));
|
|
264
264
|
checks.push(await checkFile("config", join6(ctx.projectRoot, "openspec", "config.yaml"), "openspec/config.yaml \u7F3A\u5931", "fet init"));
|
|
265
|
-
checks.push(await checkPlaceholders(ctx
|
|
265
|
+
checks.push(await checkPlaceholders(ctx));
|
|
266
266
|
checks.push(await checkGitNexus(ctx));
|
|
267
267
|
for (const adapter of ctx.toolAdapters) {
|
|
268
268
|
checks.push(...await adapter.doctor(ctx.projectRoot));
|
|
@@ -299,12 +299,12 @@ async function checkGitNexus(ctx) {
|
|
|
299
299
|
return state.installed ? {
|
|
300
300
|
id: "gitnexus",
|
|
301
301
|
status: "pass",
|
|
302
|
-
message: `GitNexus detected: ${state.executablePath ?? "gitnexus"} (${state.version ?? "unknown"}), graph ${state.graphExists ? "found" : "not found"}`
|
|
302
|
+
message: ctx.language === "en" ? `GitNexus detected: ${state.executablePath ?? "gitnexus"} (${state.version ?? "unknown"}), graph ${state.graphExists ? "found" : "not found"}` : `\u68C0\u6D4B\u5230 GitNexus\uFF1A${state.executablePath ?? "gitnexus"}\uFF08${state.version ?? "unknown"}\uFF09\uFF0C\u4EE3\u7801\u56FE${state.graphExists ? "\u5DF2\u627E\u5230" : "\u672A\u627E\u5230"}`
|
|
303
303
|
} : {
|
|
304
304
|
id: "gitnexus",
|
|
305
305
|
status: "warn",
|
|
306
|
-
message: "Optional GitNexus code graph support is not installed",
|
|
307
|
-
suggestedCommand: "Install GitNexus later if you want OpenSpec artifacts to prefer a repository graph"
|
|
306
|
+
message: ctx.language === "en" ? "Optional GitNexus code graph support is not installed" : "\u5C1A\u672A\u5B89\u88C5\u53EF\u9009\u7684 GitNexus \u4EE3\u7801\u56FE\u652F\u6301",
|
|
307
|
+
suggestedCommand: ctx.language === "en" ? "Install GitNexus later if you want OpenSpec artifacts to prefer a repository graph" : "\u5982\u679C\u5E0C\u671B OpenSpec \u4EA7\u7269\u4F18\u5148\u53C2\u8003\u4ED3\u5E93\u4EE3\u7801\u56FE\uFF0C\u53EF\u4EE5\u7A0D\u540E\u5B89\u88C5 GitNexus"
|
|
308
308
|
};
|
|
309
309
|
}
|
|
310
310
|
async function checkOpenSpec(ctx) {
|
|
@@ -326,18 +326,27 @@ async function checkState(ctx) {
|
|
|
326
326
|
async function checkFile(id, path, missing, suggestedCommand) {
|
|
327
327
|
return await exists(path) ? { id, status: "pass", message: `${id} \u5B58\u5728` } : { id, status: "warn", message: missing, suggestedCommand };
|
|
328
328
|
}
|
|
329
|
-
async function checkPlaceholders(
|
|
329
|
+
async function checkPlaceholders(ctx) {
|
|
330
330
|
try {
|
|
331
|
-
await readFile4(join6(projectRoot, "AGENTS.md"), "utf8");
|
|
332
|
-
const count2 = await countAgentsLlmPlaceholders(projectRoot);
|
|
331
|
+
await readFile4(join6(ctx.projectRoot, "AGENTS.md"), "utf8");
|
|
332
|
+
const count2 = await countAgentsLlmPlaceholders(ctx.projectRoot);
|
|
333
333
|
return count2 ? {
|
|
334
334
|
id: "context-placeholders",
|
|
335
335
|
status: "warn",
|
|
336
|
-
message: `AGENTS.md has ${count2} LLM placeholder(s)`,
|
|
336
|
+
message: ctx.language === "en" ? `AGENTS.md has ${count2} LLM placeholder(s)` : `AGENTS.md \u4ECD\u6709 ${count2} \u4E2A LLM \u5360\u4F4D\u7B26`,
|
|
337
337
|
suggestedCommand: "fet fill-context"
|
|
338
|
-
} : {
|
|
338
|
+
} : {
|
|
339
|
+
id: "context-placeholders",
|
|
340
|
+
status: "pass",
|
|
341
|
+
message: ctx.language === "en" ? "AGENTS.md placeholders resolved" : "AGENTS.md \u5360\u4F4D\u7B26\u5DF2\u5904\u7406"
|
|
342
|
+
};
|
|
339
343
|
} catch {
|
|
340
|
-
return {
|
|
344
|
+
return {
|
|
345
|
+
id: "context-placeholders",
|
|
346
|
+
status: "warn",
|
|
347
|
+
message: ctx.language === "en" ? "AGENTS.md missing" : "AGENTS.md \u7F3A\u5931",
|
|
348
|
+
suggestedCommand: "fet update-context"
|
|
349
|
+
};
|
|
341
350
|
}
|
|
342
351
|
}
|
|
343
352
|
async function exists(path) {
|
|
@@ -459,38 +468,41 @@ async function graphCommand(ctx, action, args = []) {
|
|
|
459
468
|
}
|
|
460
469
|
async function graphStatusCommand(ctx) {
|
|
461
470
|
const result = await refreshGraphState(ctx, { runStatus: true });
|
|
462
|
-
const warnings = result.state.installed ? [] : [
|
|
471
|
+
const warnings = result.state.installed ? [] : [
|
|
472
|
+
ctx.language === "en" ? "GitNexus is not installed. Run fet graph setup for installation handoff instructions." : "\u5C1A\u672A\u5B89\u88C5 GitNexus\u3002\u8FD0\u884C fet graph setup \u83B7\u53D6\u5B89\u88C5\u4EA4\u63A5\u8BF4\u660E\u3002"
|
|
473
|
+
];
|
|
463
474
|
ctx.output.result({
|
|
464
475
|
ok: true,
|
|
465
476
|
command: "graph status",
|
|
466
|
-
summary: result.state.installed ? `GitNexus graph status checked. Graph ${result.state.graphExists ? "exists" : "does not exist"} at ${result.state.graphPath ?? ".gitnexus"}.` : "GitNexus is not installed. Graph support remains optional.",
|
|
477
|
+
summary: ctx.language === "en" ? result.state.installed ? `GitNexus graph status checked. Graph ${result.state.graphExists ? "exists" : "does not exist"} at ${result.state.graphPath ?? ".gitnexus"}.` : "GitNexus is not installed. Graph support remains optional." : result.state.installed ? `\u5DF2\u68C0\u67E5 GitNexus \u4EE3\u7801\u56FE\u72B6\u6001\u3002\u4EE3\u7801\u56FE${result.state.graphExists ? "\u5B58\u5728" : "\u4E0D\u5B58\u5728"}\uFF0C\u8DEF\u5F84\u4E3A ${result.state.graphPath ?? ".gitnexus"}\u3002` : "\u5C1A\u672A\u5B89\u88C5 GitNexus\u3002\u4EE3\u7801\u56FE\u80FD\u529B\u4FDD\u6301\u53EF\u9009\u3002",
|
|
467
478
|
warnings,
|
|
468
|
-
nextSteps: result.state.installed && !result.state.graphExists ? ["Run fet graph init to build the first GitNexus graph"] : void 0,
|
|
479
|
+
nextSteps: result.state.installed && !result.state.graphExists ? [ctx.language === "en" ? "Run fet graph init to build the first GitNexus graph" : "\u8FD0\u884C fet graph init \u751F\u6210\u7B2C\u4E00\u4EFD GitNexus \u4EE3\u7801\u56FE"] : void 0,
|
|
469
480
|
data: result
|
|
470
481
|
});
|
|
471
482
|
}
|
|
472
483
|
async function graphDoctorCommand(ctx) {
|
|
473
484
|
const result = await refreshGraphState(ctx, { runStatus: true });
|
|
474
485
|
const warnings = [
|
|
475
|
-
...!result.state.installed ? ["GitNexus is not installed."] : [],
|
|
476
|
-
...result.state.installed && !result.state.graphExists ? ["GitNexus is installed but no graph directory was found."] : [],
|
|
477
|
-
...!result.state.handoffPath ? ["Graph handoff instructions have not been generated."] : []
|
|
486
|
+
...!result.state.installed ? [ctx.language === "en" ? "GitNexus is not installed." : "\u5C1A\u672A\u5B89\u88C5 GitNexus\u3002"] : [],
|
|
487
|
+
...result.state.installed && !result.state.graphExists ? [ctx.language === "en" ? "GitNexus is installed but no graph directory was found." : "\u5DF2\u5B89\u88C5 GitNexus\uFF0C\u4F46\u672A\u53D1\u73B0\u4EE3\u7801\u56FE\u76EE\u5F55\u3002"] : [],
|
|
488
|
+
...!result.state.handoffPath ? [ctx.language === "en" ? "Graph handoff instructions have not been generated." : "\u5C1A\u672A\u751F\u6210\u4EE3\u7801\u56FE\u4F7F\u7528\u4EA4\u63A5\u8BF4\u660E\u3002"] : []
|
|
478
489
|
];
|
|
479
490
|
ctx.output.result({
|
|
480
491
|
ok: true,
|
|
481
492
|
command: "graph doctor",
|
|
482
|
-
summary: warnings.length ? `Graph doctor completed with ${warnings.length} warning(s).` : "Graph doctor completed without warnings.",
|
|
493
|
+
summary: ctx.language === "en" ? warnings.length ? `Graph doctor completed with ${warnings.length} warning(s).` : "Graph doctor completed without warnings." : warnings.length ? `\u4EE3\u7801\u56FE\u8BCA\u65AD\u5B8C\u6210\uFF0C\u53D1\u73B0 ${warnings.length} \u4E2A\u8B66\u544A\u3002` : "\u4EE3\u7801\u56FE\u8BCA\u65AD\u5B8C\u6210\uFF0C\u672A\u53D1\u73B0\u8B66\u544A\u3002",
|
|
483
494
|
warnings,
|
|
484
|
-
nextSteps: warnings.length ? ["Run fet graph setup", "Run fet graph handoff", "Run fet graph init when GitNexus is installed"] : void 0,
|
|
495
|
+
nextSteps: warnings.length ? ctx.language === "en" ? ["Run fet graph setup", "Run fet graph handoff", "Run fet graph init when GitNexus is installed"] : ["\u8FD0\u884C fet graph setup", "\u8FD0\u884C fet graph handoff", "\u5B89\u88C5 GitNexus \u540E\u8FD0\u884C fet graph init"] : void 0,
|
|
485
496
|
data: result
|
|
486
497
|
});
|
|
487
498
|
}
|
|
488
499
|
async function graphSetupCommand(ctx) {
|
|
489
500
|
let result;
|
|
490
501
|
const handoffPath = join8(ctx.projectRoot, ".fet", "graph-setup.md");
|
|
502
|
+
const installCommand = process.env.FET_GITNEXUS_INSTALL_COMMAND?.trim() || null;
|
|
491
503
|
await withProjectLock(ctx.projectRoot, { command: "graph setup", cwd: ctx.cwd, fetVersion: ctx.fetVersion }, async () => {
|
|
492
504
|
result = await refreshGraphState(ctx, { write: false });
|
|
493
|
-
await writeHandoffFile(handoffPath, renderGraphSetupHandoff(result.state));
|
|
505
|
+
await writeHandoffFile(handoffPath, renderGraphSetupHandoff(result.state, { installCommand, language: ctx.language }));
|
|
494
506
|
const global = await ctx.stateStore.getOrCreateGlobal();
|
|
495
507
|
global.graph ??= {};
|
|
496
508
|
global.graph.gitnexus = {
|
|
@@ -503,11 +515,19 @@ async function graphSetupCommand(ctx) {
|
|
|
503
515
|
ctx.output.result({
|
|
504
516
|
ok: true,
|
|
505
517
|
command: "graph setup",
|
|
506
|
-
summary: "GitNexus setup
|
|
507
|
-
warnings: result.state.installed ? [] : [
|
|
508
|
-
|
|
518
|
+
summary: ctx.language === "en" ? "GitNexus IDE-assisted setup playbook generated." : "\u5DF2\u751F\u6210 GitNexus IDE LLM \u8F85\u52A9\u5B89\u88C5\u4EFB\u52A1\u4E66\u3002",
|
|
519
|
+
warnings: result.state.installed ? [] : [
|
|
520
|
+
ctx.language === "en" ? "GitNexus is not installed. The playbook lets the current IDE LLM guide installation with user confirmation before risky commands." : "\u5C1A\u672A\u5B89\u88C5 GitNexus\u3002\u4EFB\u52A1\u4E66\u4F1A\u6307\u5BFC\u5F53\u524D IDE LLM \u63A8\u8FDB\u5B89\u88C5\uFF0C\u5E76\u5728\u9AD8\u98CE\u9669\u547D\u4EE4\u524D\u8BF7\u6C42\u7528\u6237\u786E\u8BA4\u3002"
|
|
521
|
+
],
|
|
522
|
+
nextSteps: result.state.installed ? [
|
|
523
|
+
ctx.language === "en" ? "Ask your IDE AI to read .fet/graph-setup.md and run the optional gitnexus setup flow if you want IDE/MCP integration" : "\u8BA9\u5F53\u524D IDE AI \u9605\u8BFB .fet/graph-setup.md\uFF0C\u5E76\u5728\u9700\u8981 IDE/MCP \u96C6\u6210\u65F6\u6309\u786E\u8BA4\u6D41\u7A0B\u8FD0\u884C gitnexus setup",
|
|
524
|
+
"fet graph init"
|
|
525
|
+
] : [
|
|
526
|
+
ctx.language === "en" ? "Ask your current IDE AI to read .fet/graph-setup.md and follow the installation playbook" : "\u8BA9\u5F53\u524D IDE AI \u9605\u8BFB .fet/graph-setup.md\uFF0C\u5E76\u6309\u5B89\u88C5\u4EFB\u52A1\u4E66\u63A8\u8FDB"
|
|
527
|
+
],
|
|
509
528
|
data: {
|
|
510
529
|
path: ".fet/graph-setup.md",
|
|
530
|
+
installCommandConfigured: Boolean(installCommand),
|
|
511
531
|
gitnexus: result.state
|
|
512
532
|
}
|
|
513
533
|
});
|
|
@@ -517,7 +537,7 @@ async function graphHandoffCommand(ctx) {
|
|
|
517
537
|
const handoffPath = join8(ctx.projectRoot, ".fet", "graph-handoff.md");
|
|
518
538
|
await withProjectLock(ctx.projectRoot, { command: "graph handoff", cwd: ctx.cwd, fetVersion: ctx.fetVersion }, async () => {
|
|
519
539
|
result = await refreshGraphState(ctx, { runStatus: true, write: false });
|
|
520
|
-
await writeHandoffFile(handoffPath, renderGraphUsageHandoff(result.state));
|
|
540
|
+
await writeHandoffFile(handoffPath, renderGraphUsageHandoff(result.state, ctx.language));
|
|
521
541
|
const global = await ctx.stateStore.getOrCreateGlobal();
|
|
522
542
|
global.graph ??= {};
|
|
523
543
|
global.graph.gitnexus = {
|
|
@@ -530,9 +550,11 @@ async function graphHandoffCommand(ctx) {
|
|
|
530
550
|
ctx.output.result({
|
|
531
551
|
ok: true,
|
|
532
552
|
command: "graph handoff",
|
|
533
|
-
summary: "GitNexus graph usage handoff generated.",
|
|
534
|
-
warnings: result.state.installed ? [] : [
|
|
535
|
-
|
|
553
|
+
summary: ctx.language === "en" ? "GitNexus graph usage handoff generated." : "\u5DF2\u751F\u6210 GitNexus \u4EE3\u7801\u56FE\u4F7F\u7528\u4EA4\u63A5\u8BF4\u660E\u3002",
|
|
554
|
+
warnings: result.state.installed ? [] : [
|
|
555
|
+
ctx.language === "en" ? "GitNexus is not installed. The handoff still documents the fallback behavior." : "\u5C1A\u672A\u5B89\u88C5 GitNexus\u3002\u4EA4\u63A5\u8BF4\u660E\u4ECD\u4F1A\u8BB0\u5F55\u56DE\u9000\u884C\u4E3A\u3002"
|
|
556
|
+
],
|
|
557
|
+
nextSteps: ctx.language === "en" ? ["Cursor/Codex/OpenCode: read .fet/graph-handoff.md before broad repository scans"] : ["Cursor/Codex/OpenCode\uFF1A\u5927\u8303\u56F4\u626B\u63CF\u4ED3\u5E93\u524D\u5148\u9605\u8BFB .fet/graph-handoff.md"],
|
|
536
558
|
data: {
|
|
537
559
|
path: ".fet/graph-handoff.md",
|
|
538
560
|
gitnexus: result.state
|
|
@@ -544,7 +566,7 @@ async function graphAnalyzeCommand(ctx, mode, args) {
|
|
|
544
566
|
if (!detection.installed) {
|
|
545
567
|
throw new FetError({
|
|
546
568
|
code: "GRAPH_PROVIDER_NOT_FOUND" /* GraphProviderNotFound */,
|
|
547
|
-
message: "GitNexus is not installed or is not available on PATH.",
|
|
569
|
+
message: ctx.language === "en" ? "GitNexus is not installed or is not available on PATH." : "\u5C1A\u672A\u5B89\u88C5 GitNexus\uFF0C\u6216 GitNexus \u4E0D\u5728 PATH \u4E2D\u3002",
|
|
548
570
|
details: { executable: detection.executablePath, error: detection.error },
|
|
549
571
|
suggestedCommand: "fet graph setup"
|
|
550
572
|
});
|
|
@@ -553,7 +575,7 @@ async function graphAnalyzeCommand(ctx, mode, args) {
|
|
|
553
575
|
if (run.exitCode !== 0) {
|
|
554
576
|
throw new FetError({
|
|
555
577
|
code: "GRAPH_COMMAND_FAILED" /* GraphCommandFailed */,
|
|
556
|
-
message: "GitNexus analyze failed.",
|
|
578
|
+
message: ctx.language === "en" ? "GitNexus analyze failed." : "GitNexus analyze \u6267\u884C\u5931\u8D25\u3002",
|
|
557
579
|
details: { command: run.command.join(" "), exitCode: run.exitCode, stdout: run.stdout, stderr: run.stderr },
|
|
558
580
|
suggestedCommand: "fet graph doctor"
|
|
559
581
|
});
|
|
@@ -569,9 +591,11 @@ async function graphAnalyzeCommand(ctx, mode, args) {
|
|
|
569
591
|
ctx.output.result({
|
|
570
592
|
ok: true,
|
|
571
593
|
command: `graph ${mode}`,
|
|
572
|
-
summary: mode === "init" ? "GitNexus graph initialized." : "GitNexus graph refreshed.",
|
|
573
|
-
warnings: result.state.graphExists ? [] : [
|
|
574
|
-
|
|
594
|
+
summary: ctx.language === "en" ? mode === "init" ? "GitNexus graph initialized." : "GitNexus graph refreshed." : mode === "init" ? "\u5DF2\u521D\u59CB\u5316 GitNexus \u4EE3\u7801\u56FE\u3002" : "\u5DF2\u5237\u65B0 GitNexus \u4EE3\u7801\u56FE\u3002",
|
|
595
|
+
warnings: result.state.graphExists ? [] : [
|
|
596
|
+
ctx.language === "en" ? "GitNexus analyze completed, but the configured graph directory was not found." : "GitNexus analyze \u5DF2\u5B8C\u6210\uFF0C\u4F46\u672A\u53D1\u73B0\u914D\u7F6E\u7684\u4EE3\u7801\u56FE\u76EE\u5F55\u3002"
|
|
597
|
+
],
|
|
598
|
+
nextSteps: ctx.language === "en" ? ["Run fet graph status", "Use .fet/graph-handoff.md or generated IDE prompts to prefer graph context"] : ["\u8FD0\u884C fet graph status", "\u4F7F\u7528 .fet/graph-handoff.md \u6216\u751F\u6210\u7684 IDE \u63D0\u793A\uFF0C\u4F18\u5148\u53C2\u8003\u4EE3\u7801\u56FE\u4E0A\u4E0B\u6587"],
|
|
575
599
|
data: {
|
|
576
600
|
gitnexus: global.graph.gitnexus,
|
|
577
601
|
run: {
|
|
@@ -614,15 +638,16 @@ async function writeHandoffFile(path, content) {
|
|
|
614
638
|
await mkdir4(dirname5(path), { recursive: true });
|
|
615
639
|
await atomicWrite(path, content);
|
|
616
640
|
}
|
|
617
|
-
function renderGraphSetupHandoff(state) {
|
|
618
|
-
|
|
641
|
+
function renderGraphSetupHandoff(state, options) {
|
|
642
|
+
if (options.language === "en") {
|
|
643
|
+
return `<!-- FET:MANAGED
|
|
619
644
|
schemaVersion: 1
|
|
620
645
|
generator: graph-setup
|
|
621
646
|
FET:END -->
|
|
622
647
|
|
|
623
|
-
# FET
|
|
648
|
+
# FET GitNexus IDE Setup Playbook
|
|
624
649
|
|
|
625
|
-
|
|
650
|
+
This file is written for the current IDE LLM. Use it to help the user install and verify optional GitNexus graph support. GitNexus is optional; FET/OpenSpec workflows must continue to work when it is unavailable.
|
|
626
651
|
|
|
627
652
|
Current status:
|
|
628
653
|
|
|
@@ -631,24 +656,70 @@ Current status:
|
|
|
631
656
|
- Version: ${state.version ?? "unknown"}
|
|
632
657
|
- Graph path: ${state.graphPath ?? ".gitnexus"}
|
|
633
658
|
- Graph exists: ${state.graphExists ? "yes" : "no"}
|
|
659
|
+
- Configured install command: ${options.installCommand ?? "none"}
|
|
634
660
|
|
|
635
|
-
|
|
661
|
+
IDE LLM setup flow:
|
|
636
662
|
|
|
637
|
-
1.
|
|
638
|
-
2.
|
|
639
|
-
3.
|
|
640
|
-
4.
|
|
663
|
+
1. Check the shell, operating system, package managers, and PATH. Run only read-only detection commands at first.
|
|
664
|
+
2. Run \`gitnexus --version\` or the executable shown above. If it succeeds, skip installation and continue to verification.
|
|
665
|
+
3. If GitNexus is missing and \`FET_GITNEXUS_INSTALL_COMMAND\` is configured, explain that command to the user and ask for approval before running it.
|
|
666
|
+
4. If no install command is configured, find the official GitNexus installation instructions or ask the user for the preferred install method. Do not invent an installer.
|
|
667
|
+
5. Before running any command that downloads software, installs globally, changes PATH, modifies user home files, or changes IDE/MCP configuration, show the exact command and wait for user approval.
|
|
668
|
+
6. After installation, verify with \`gitnexus --version\`.
|
|
669
|
+
7. If the user wants IDE/MCP integration, run \`gitnexus setup\` only after explaining what it may change and receiving approval.
|
|
670
|
+
8. Return to this project and run \`fet graph init\` to build the first graph.
|
|
671
|
+
9. Run \`fet graph handoff\` so future IDE AI work can prefer graph context before broad repository scans.
|
|
641
672
|
|
|
642
673
|
Guardrails:
|
|
643
674
|
|
|
644
675
|
- Do not block FET/OpenSpec commands when GitNexus is unavailable.
|
|
645
676
|
- Do not generate or modify application code during setup.
|
|
646
|
-
- Do not
|
|
677
|
+
- Do not silently install software or modify global/user-level configuration.
|
|
678
|
+
- If installation fails, summarize the failing command, stderr, and the next manual step.
|
|
647
679
|
`;
|
|
648
|
-
}
|
|
649
|
-
function renderGraphUsageHandoff(state) {
|
|
680
|
+
}
|
|
650
681
|
return `<!-- FET:MANAGED
|
|
651
682
|
schemaVersion: 1
|
|
683
|
+
generator: graph-setup
|
|
684
|
+
FET:END -->
|
|
685
|
+
|
|
686
|
+
# FET GitNexus IDE \u5B89\u88C5\u4EFB\u52A1\u4E66
|
|
687
|
+
|
|
688
|
+
\u672C\u6587\u6863\u5199\u7ED9\u5F53\u524D IDE LLM\u3002\u8BF7\u7528\u5B83\u5E2E\u52A9\u7528\u6237\u5B89\u88C5\u5E76\u9A8C\u8BC1\u53EF\u9009\u7684 GitNexus \u4EE3\u7801\u56FE\u80FD\u529B\u3002GitNexus \u662F\u53EF\u9009\u80FD\u529B\uFF1B\u5373\u4F7F\u4E0D\u53EF\u7528\uFF0CFET/OpenSpec \u4E3B\u6D41\u7A0B\u4E5F\u5FC5\u987B\u7EE7\u7EED\u53EF\u7528\u3002
|
|
689
|
+
|
|
690
|
+
\u5F53\u524D\u72B6\u6001\uFF1A
|
|
691
|
+
|
|
692
|
+
- \u5DF2\u5B89\u88C5\uFF1A${state.installed ? "\u662F" : "\u5426"}
|
|
693
|
+
- \u53EF\u6267\u884C\u6587\u4EF6\uFF1A${state.executablePath ?? "gitnexus"}
|
|
694
|
+
- \u7248\u672C\uFF1A${state.version ?? "unknown"}
|
|
695
|
+
- \u56FE\u8DEF\u5F84\uFF1A${state.graphPath ?? ".gitnexus"}
|
|
696
|
+
- \u56FE\u5DF2\u5B58\u5728\uFF1A${state.graphExists ? "\u662F" : "\u5426"}
|
|
697
|
+
- \u5DF2\u914D\u7F6E\u5B89\u88C5\u547D\u4EE4\uFF1A${options.installCommand ?? "\u65E0"}
|
|
698
|
+
|
|
699
|
+
IDE LLM \u5B89\u88C5\u6D41\u7A0B\uFF1A
|
|
700
|
+
|
|
701
|
+
1. \u5148\u68C0\u6D4B shell\u3001\u64CD\u4F5C\u7CFB\u7EDF\u3001\u5305\u7BA1\u7406\u5668\u548C PATH\u3002\u8D77\u6B65\u9636\u6BB5\u53EA\u8FD0\u884C\u53EA\u8BFB\u68C0\u6D4B\u547D\u4EE4\u3002
|
|
702
|
+
2. \u8FD0\u884C \`gitnexus --version\` \u6216\u4E0A\u65B9\u663E\u793A\u7684\u53EF\u6267\u884C\u6587\u4EF6\u3002\u5982\u679C\u6210\u529F\uFF0C\u8DF3\u8FC7\u5B89\u88C5\u5E76\u8FDB\u5165\u9A8C\u8BC1\u3002
|
|
703
|
+
3. \u5982\u679C GitNexus \u7F3A\u5931\u4E14\u5DF2\u914D\u7F6E \`FET_GITNEXUS_INSTALL_COMMAND\`\uFF0C\u5148\u5411\u7528\u6237\u89E3\u91CA\u8BE5\u547D\u4EE4\uFF0C\u518D\u7B49\u5F85\u7528\u6237\u6279\u51C6\u540E\u6267\u884C\u3002
|
|
704
|
+
4. \u5982\u679C\u6CA1\u6709\u914D\u7F6E\u5B89\u88C5\u547D\u4EE4\uFF0C\u67E5\u627E GitNexus \u5B98\u65B9\u5B89\u88C5\u8BF4\u660E\uFF0C\u6216\u8BE2\u95EE\u7528\u6237\u5E0C\u671B\u4F7F\u7528\u7684\u5B89\u88C5\u65B9\u5F0F\u3002\u4E0D\u8981\u81C6\u9020\u5B89\u88C5\u547D\u4EE4\u3002
|
|
705
|
+
5. \u4EFB\u4F55\u4F1A\u4E0B\u8F7D\u8F6F\u4EF6\u3001\u5168\u5C40\u5B89\u88C5\u3001\u4FEE\u6539 PATH\u3001\u5199\u5165\u7528\u6237\u76EE\u5F55\u6216\u4FEE\u6539 IDE/MCP \u914D\u7F6E\u7684\u547D\u4EE4\uFF0C\u6267\u884C\u524D\u90FD\u8981\u5C55\u793A\u5B8C\u6574\u547D\u4EE4\u5E76\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u3002
|
|
706
|
+
6. \u5B89\u88C5\u540E\u8FD0\u884C \`gitnexus --version\` \u9A8C\u8BC1\u3002
|
|
707
|
+
7. \u5982\u679C\u7528\u6237\u9700\u8981 IDE/MCP \u96C6\u6210\uFF0C\u5148\u8BF4\u660E \`gitnexus setup\` \u53EF\u80FD\u4FEE\u6539\u7684\u5185\u5BB9\uFF0C\u83B7\u5F97\u786E\u8BA4\u540E\u518D\u8FD0\u884C\u3002
|
|
708
|
+
8. \u56DE\u5230\u672C\u9879\u76EE\u8FD0\u884C \`fet graph init\`\uFF0C\u751F\u6210\u7B2C\u4E00\u4EFD\u4EE3\u7801\u56FE\u3002
|
|
709
|
+
9. \u8FD0\u884C \`fet graph handoff\`\uFF0C\u8BA9\u540E\u7EED IDE AI \u5728\u5927\u8303\u56F4\u626B\u63CF\u524D\u4F18\u5148\u4F7F\u7528\u4EE3\u7801\u56FE\u4E0A\u4E0B\u6587\u3002
|
|
710
|
+
|
|
711
|
+
\u7EA6\u675F\uFF1A
|
|
712
|
+
|
|
713
|
+
- GitNexus \u4E0D\u53EF\u7528\u65F6\uFF0C\u4E0D\u8981\u963B\u585E FET/OpenSpec \u547D\u4EE4\u3002
|
|
714
|
+
- \u5B89\u88C5\u8FC7\u7A0B\u4E2D\u4E0D\u8981\u751F\u6210\u6216\u4FEE\u6539\u4E1A\u52A1\u4EE3\u7801\u3002
|
|
715
|
+
- \u4E0D\u8981\u9759\u9ED8\u5B89\u88C5\u8F6F\u4EF6\uFF0C\u4E5F\u4E0D\u8981\u9759\u9ED8\u4FEE\u6539\u5168\u5C40\u6216\u7528\u6237\u7EA7\u914D\u7F6E\u3002
|
|
716
|
+
- \u5982\u679C\u5B89\u88C5\u5931\u8D25\uFF0C\u6C47\u603B\u5931\u8D25\u547D\u4EE4\u3001stderr \u548C\u4E0B\u4E00\u6B65\u4EBA\u5DE5\u5904\u7406\u5EFA\u8BAE\u3002
|
|
717
|
+
`;
|
|
718
|
+
}
|
|
719
|
+
function renderGraphUsageHandoff(state, language) {
|
|
720
|
+
if (language === "en") {
|
|
721
|
+
return `<!-- FET:MANAGED
|
|
722
|
+
schemaVersion: 1
|
|
652
723
|
generator: graph-handoff
|
|
653
724
|
FET:END -->
|
|
654
725
|
|
|
@@ -676,6 +747,37 @@ When producing OpenSpec artifacts:
|
|
|
676
747
|
- Use graph context to make proposal, design, specs, and tasks more precise.
|
|
677
748
|
- Avoid large repository scans when the graph already narrows the relevant area.
|
|
678
749
|
- Keep all generated artifacts in the normal OpenSpec change directory.
|
|
750
|
+
`;
|
|
751
|
+
}
|
|
752
|
+
return `<!-- FET:MANAGED
|
|
753
|
+
schemaVersion: 1
|
|
754
|
+
generator: graph-handoff
|
|
755
|
+
FET:END -->
|
|
756
|
+
|
|
757
|
+
# FET \u4EE3\u7801\u56FE\u4EA4\u63A5\u8BF4\u660E
|
|
758
|
+
|
|
759
|
+
\u5728\u5927\u8303\u56F4\u626B\u63CF\u4ED3\u5E93\u524D\uFF0C\u4F18\u5148\u628A GitNexus \u4EE3\u7801\u56FE\u4E0A\u4E0B\u6587\u4F5C\u4E3A\u53EF\u9009\u7684\u7B2C\u4E00\u8F6E\u7EBF\u7D22\u3002
|
|
760
|
+
|
|
761
|
+
\u5F53\u524D\u72B6\u6001\uFF1A
|
|
762
|
+
|
|
763
|
+
- \u5DF2\u5B89\u88C5\uFF1A${state.installed ? "\u662F" : "\u5426"}
|
|
764
|
+
- \u56FE\u8DEF\u5F84\uFF1A${state.graphPath ?? ".gitnexus"}
|
|
765
|
+
- \u56FE\u5DF2\u5B58\u5728\uFF1A${state.graphExists ? "\u662F" : "\u5426"}
|
|
766
|
+
- \u6700\u540E\u7D22\u5F15\u65F6\u95F4\uFF1A${state.lastIndexedAt ?? "unknown"}
|
|
767
|
+
- \u6700\u540E\u72B6\u6001\uFF1A${state.lastStatus ?? "unknown"}
|
|
768
|
+
|
|
769
|
+
\u4EE3\u7801\u56FE\u4E0A\u4E0B\u6587\u53EF\u7528\u65F6\uFF1A
|
|
770
|
+
|
|
771
|
+
1. \u7528\u4EE3\u7801\u56FE\u8BC6\u522B\u53EF\u80FD\u76F8\u5173\u7684\u6A21\u5757\u3001\u4F9D\u8D56\u548C\u63D2\u5165\u70B9\u3002
|
|
772
|
+
2. \u53EA\u8BFB\u53D6\u9700\u8981\u786E\u8BA4\u884C\u4E3A\u7684\u5177\u4F53\u6E90\u7801\u6587\u4EF6\u3002
|
|
773
|
+
3. \u5F53\u4EE3\u7801\u56FE\u63A8\u65AD\u4E0E OpenSpec \u4EA7\u7269\u6216 AGENTS.md \u51B2\u7A81\u65F6\uFF0C\u4F18\u5148\u76F8\u4FE1 OpenSpec \u4EA7\u7269\u548C AGENTS.md\u3002
|
|
774
|
+
4. \u5982\u679C\u4EE3\u7801\u56FE\u7F3A\u5931\u3001\u8FC7\u671F\u6216\u4E0D\u5B8C\u6574\uFF0C\u56DE\u9000\u5230\u666E\u901A\u4ED3\u5E93\u68C0\u67E5\u3002
|
|
775
|
+
|
|
776
|
+
\u751F\u6210 OpenSpec \u4EA7\u7269\u65F6\uFF1A
|
|
777
|
+
|
|
778
|
+
- \u7528\u4EE3\u7801\u56FE\u4E0A\u4E0B\u6587\u8BA9 proposal\u3001design\u3001specs \u548C tasks \u66F4\u7CBE\u786E\u3002
|
|
779
|
+
- \u5F53\u4EE3\u7801\u56FE\u5DF2\u7ECF\u7F29\u5C0F\u76F8\u5173\u8303\u56F4\u65F6\uFF0C\u907F\u514D\u5927\u8303\u56F4\u4ED3\u5E93\u626B\u63CF\u3002
|
|
780
|
+
- \u6240\u6709\u751F\u6210\u4EA7\u7269\u4ECD\u5199\u5165\u6B63\u5E38\u7684 OpenSpec change \u76EE\u5F55\u3002
|
|
679
781
|
`;
|
|
680
782
|
}
|
|
681
783
|
function firstLine(value) {
|
|
@@ -975,8 +1077,8 @@ function renderFetConfig(scan, language = "zh-CN") {
|
|
|
975
1077
|
var KARPATHY_SKILLS_SOURCE = "https://github.com/forrestchang/andrej-karpathy-skills";
|
|
976
1078
|
var BEGIN = "<!-- FET:BEGIN ANDREJ-KARPATHY-SKILLS -->";
|
|
977
1079
|
var END = "<!-- FET:END ANDREJ-KARPATHY-SKILLS -->";
|
|
978
|
-
function mergeKarpathyClaudeMd(existing) {
|
|
979
|
-
const block = renderManagedBlock(renderKarpathyClaudeGuidelines());
|
|
1080
|
+
function mergeKarpathyClaudeMd(existing, language = "zh-CN") {
|
|
1081
|
+
const block = renderManagedBlock(renderKarpathyClaudeGuidelines(language));
|
|
980
1082
|
if (!existing || !existing.trim()) {
|
|
981
1083
|
return `${block}
|
|
982
1084
|
`;
|
|
@@ -1021,10 +1123,10 @@ function renderManagedBlock(content) {
|
|
|
1021
1123
|
${content}
|
|
1022
1124
|
${END}`;
|
|
1023
1125
|
}
|
|
1024
|
-
function renderKarpathyClaudeGuidelines() {
|
|
1025
|
-
return `# Andrej Karpathy Inspired Coding Guidelines
|
|
1126
|
+
function renderKarpathyClaudeGuidelines(language) {
|
|
1127
|
+
return `# ${language === "en" ? "Andrej Karpathy Inspired Coding Guidelines" : "\u53D7 Andrej Karpathy \u542F\u53D1\u7684\u7F16\u7801\u6307\u5357"}
|
|
1026
1128
|
|
|
1027
|
-
${renderKarpathyGuidelinesBody()}`;
|
|
1129
|
+
${renderKarpathyGuidelinesBody(language)}`;
|
|
1028
1130
|
}
|
|
1029
1131
|
function renderKarpathyGuidelinesBody(language = "zh-CN") {
|
|
1030
1132
|
if (language === "en") {
|
|
@@ -1225,7 +1327,7 @@ async function updateContextFiles(ctx) {
|
|
|
1225
1327
|
}
|
|
1226
1328
|
await atomicWrite(agentsPath, replaceManagedRegion(existingAgents, renderAgentsMd(scan, ctx.language)));
|
|
1227
1329
|
await atomicWrite(configPath, await mergeFetConfig(configPath, renderFetConfig(scan, ctx.language)));
|
|
1228
|
-
await atomicWrite(claudePath, mergeKarpathyClaudeMd(existingClaude));
|
|
1330
|
+
await atomicWrite(claudePath, mergeKarpathyClaudeMd(existingClaude, ctx.language));
|
|
1229
1331
|
await atomicWrite(karpathyHandoffPath, renderKarpathyFetHandoff(ctx.language));
|
|
1230
1332
|
if (!existingKarpathyCursor || existingKarpathyCursor.includes("FET:MANAGED")) {
|
|
1231
1333
|
await atomicWrite(karpathyCursorPath, renderKarpathyCursorRule(ctx.language));
|
|
@@ -2013,10 +2115,10 @@ function getModelPolicyMode(env = process.env) {
|
|
|
2013
2115
|
if (value === "off" || env.FET_SKIP_MODEL_POLICY === "1") {
|
|
2014
2116
|
return "off";
|
|
2015
2117
|
}
|
|
2016
|
-
if (value === "
|
|
2017
|
-
return "
|
|
2118
|
+
if (value === "warn") {
|
|
2119
|
+
return "warn";
|
|
2018
2120
|
}
|
|
2019
|
-
return "
|
|
2121
|
+
return "confirm";
|
|
2020
2122
|
}
|
|
2021
2123
|
function getCommandModelPolicyMismatch(command, env = process.env) {
|
|
2022
2124
|
if (getModelPolicyMode(env) === "off") {
|
|
@@ -2060,14 +2162,14 @@ function formatModelPolicyMismatch(mismatch, language = "zh-CN") {
|
|
|
2060
2162
|
function renderIdeModelPolicy(command, language = "zh-CN") {
|
|
2061
2163
|
if (language === "en") {
|
|
2062
2164
|
if (command === "apply") {
|
|
2063
|
-
return "Model policy: this command is recommended to run with a high-capability/high-cost model such as GPT-5.5, GLM-5.1, GLM-5, Claude Opus, or Claude Sonnet.
|
|
2165
|
+
return "Model policy: this command is recommended to run with a high-capability/high-cost model such as GPT-5.5, GLM-5.1, GLM-5, Claude Opus, or Claude Sonnet. If the current IDE model is lower-cost, tell the user and ask whether to stop for a model switch or continue anyway. Continue only after the user chooses.";
|
|
2064
2166
|
}
|
|
2065
|
-
return "Model policy: this command is recommended to run with a low-cost model. If the current IDE model is GPT-5.5, GLM-5.1, GLM-5, Claude Opus, Claude Sonnet, or another high-cost model,
|
|
2167
|
+
return "Model policy: this command is recommended to run with a low-cost model. If the current IDE model is GPT-5.5, GLM-5.1, GLM-5, Claude Opus, Claude Sonnet, or another high-cost model, tell the user and ask whether to stop for a model switch or continue anyway. Continue only after the user chooses.";
|
|
2066
2168
|
}
|
|
2067
2169
|
if (command === "apply") {
|
|
2068
|
-
return "\u6A21\u578B\u7B56\u7565\uFF1A\u8BE5\u547D\u4EE4\u5EFA\u8BAE\u4F7F\u7528\u9AD8\u80FD\u529B/\u9AD8\u6210\u672C\u6A21\u578B\u8FD0\u884C\uFF0C\u4F8B\u5982 GPT-5.5\u3001GLM-5.1\u3001GLM-5\u3001Claude Opus \u6216 Claude Sonnet\u3002\
|
|
2170
|
+
return "\u6A21\u578B\u7B56\u7565\uFF1A\u8BE5\u547D\u4EE4\u5EFA\u8BAE\u4F7F\u7528\u9AD8\u80FD\u529B/\u9AD8\u6210\u672C\u6A21\u578B\u8FD0\u884C\uFF0C\u4F8B\u5982 GPT-5.5\u3001GLM-5.1\u3001GLM-5\u3001Claude Opus \u6216 Claude Sonnet\u3002\u82E5\u5F53\u524D IDE \u6A21\u578B\u80FD\u529B\u8F83\u4F4E\uFF0C\u8BF7\u544A\u77E5\u7528\u6237\u5E76\u8BE2\u95EE\u662F\u505C\u6B62\u540E\u5207\u6362\u6A21\u578B\uFF0C\u8FD8\u662F\u7EE7\u7EED\u6267\u884C\u5F53\u524D\u547D\u4EE4\uFF1B\u53EA\u6709\u5728\u7528\u6237\u9009\u62E9\u540E\u624D\u7EE7\u7EED\u3002";
|
|
2069
2171
|
}
|
|
2070
|
-
return "\u6A21\u578B\u7B56\u7565\uFF1A\u8BE5\u547D\u4EE4\u5EFA\u8BAE\u4F7F\u7528\u4F4E\u6210\u672C\u6A21\u578B\u8FD0\u884C\u3002\u82E5\u5F53\u524D IDE \u6A21\u578B\u662F GPT-5.5\u3001GLM-5.1\u3001GLM-5\u3001Claude Opus\u3001Claude Sonnet \u6216\u5176\u4ED6\u9AD8\u6210\u672C\u6A21\u578B\uFF0C\
|
|
2172
|
+
return "\u6A21\u578B\u7B56\u7565\uFF1A\u8BE5\u547D\u4EE4\u5EFA\u8BAE\u4F7F\u7528\u4F4E\u6210\u672C\u6A21\u578B\u8FD0\u884C\u3002\u82E5\u5F53\u524D IDE \u6A21\u578B\u662F GPT-5.5\u3001GLM-5.1\u3001GLM-5\u3001Claude Opus\u3001Claude Sonnet \u6216\u5176\u4ED6\u9AD8\u6210\u672C\u6A21\u578B\uFF0C\u8BF7\u544A\u77E5\u7528\u6237\u5E76\u8BE2\u95EE\u662F\u505C\u6B62\u540E\u5207\u6362\u6A21\u578B\uFF0C\u8FD8\u662F\u7EE7\u7EED\u6267\u884C\u5F53\u524D\u547D\u4EE4\uFF1B\u53EA\u6709\u5728\u7528\u6237\u9009\u62E9\u540E\u624D\u7EE7\u7EED\u3002";
|
|
2071
2173
|
}
|
|
2072
2174
|
|
|
2073
2175
|
// src/cli/context.ts
|
|
@@ -2107,18 +2209,9 @@ function renderFetAdapterUsage(command, args = "[...args]") {
|
|
|
2107
2209
|
|
|
2108
2210
|
// src/adapters/codex/templates.ts
|
|
2109
2211
|
function codexGuideFile(language = DEFAULT_LANGUAGE) {
|
|
2110
|
-
|
|
2111
|
-
path: ".codex/fet/context.md",
|
|
2112
|
-
content: `<!-- FET:MANAGED
|
|
2113
|
-
schemaVersion: 1
|
|
2114
|
-
fetVersion: ${FET_VERSION}
|
|
2115
|
-
generator: codex-adapter
|
|
2116
|
-
adapterVersion: 1
|
|
2117
|
-
FET:END -->
|
|
2118
|
-
|
|
2119
|
-
# FET For Codex
|
|
2212
|
+
const body = language === "en" ? `# FET For Codex
|
|
2120
2213
|
|
|
2121
|
-
##
|
|
2214
|
+
## Language
|
|
2122
2215
|
|
|
2123
2216
|
${languageInstruction(language)}
|
|
2124
2217
|
|
|
@@ -2134,7 +2227,35 @@ If GitNexus code graph context is available in the IDE or MCP tools, prefer it b
|
|
|
2134
2227
|
Use the terminal command \`fet <command>\` as the source of truth for workflow transitions. These files are Codex-readable guidance; they do not register native slash commands.
|
|
2135
2228
|
|
|
2136
2229
|
Command guides live in .codex/fet/commands/.
|
|
2137
|
-
`
|
|
2230
|
+
` : `# Codex \u7684 FET \u4F7F\u7528\u6307\u5357
|
|
2231
|
+
|
|
2232
|
+
## \u8BED\u8A00
|
|
2233
|
+
|
|
2234
|
+
${languageInstruction(language)}
|
|
2235
|
+
|
|
2236
|
+
\u5728 Codex \u4E2D\u6267\u884C FET \u6216 OpenSpec \u5DE5\u4F5C\u524D\uFF0C\u5148\u9605\u8BFB\uFF1A
|
|
2237
|
+
|
|
2238
|
+
- AGENTS.md
|
|
2239
|
+
- openspec/config.yaml
|
|
2240
|
+
- .codex/fet/karpathy-guidelines.md
|
|
2241
|
+
- \u5982\u679C\u5DF2\u9009\u62E9 change\uFF0C\u9605\u8BFB openspec/changes/<change-id>/ \u4E0B\u7684\u5F53\u524D\u4EA7\u7269
|
|
2242
|
+
|
|
2243
|
+
\u5982\u679C IDE \u6216 MCP \u5DE5\u5177\u4E2D\u53EF\u7528 GitNexus \u4EE3\u7801\u56FE\u4E0A\u4E0B\u6587\uFF0C\u5148\u7528\u5B83\u7F29\u5C0F\u4ED3\u5E93\u626B\u63CF\u8303\u56F4\uFF1B\u7528\u56FE\u8BC6\u522B\u76F8\u5173\u6A21\u5757\u3001\u4F9D\u8D56\u548C\u63D2\u5165\u70B9\uFF0C\u518D\u53EA\u8BFB\u53D6\u9700\u8981\u786E\u8BA4\u884C\u4E3A\u7684\u5177\u4F53\u6E90\u7801\u6587\u4EF6\u3002GitNexus \u4E0D\u53EF\u7528\u65F6\uFF0C\u6309\u666E\u901A FET/OpenSpec \u5DE5\u4F5C\u6D41\u7EE7\u7EED\u3002
|
|
2244
|
+
|
|
2245
|
+
\u5DE5\u4F5C\u6D41\u6D41\u8F6C\u4EE5\u7EC8\u7AEF\u547D\u4EE4 \`fet <command>\` \u4E3A\u51C6\u3002\u8FD9\u4E9B\u6587\u4EF6\u662F\u7ED9 Codex \u9605\u8BFB\u7684\u6307\u5BFC\uFF0C\u4E0D\u6CE8\u518C\u539F\u751F slash command\u3002
|
|
2246
|
+
|
|
2247
|
+
\u547D\u4EE4\u6307\u5357\u4F4D\u4E8E .codex/fet/commands/\u3002
|
|
2248
|
+
`;
|
|
2249
|
+
return {
|
|
2250
|
+
path: ".codex/fet/context.md",
|
|
2251
|
+
content: `<!-- FET:MANAGED
|
|
2252
|
+
schemaVersion: 1
|
|
2253
|
+
fetVersion: ${FET_VERSION}
|
|
2254
|
+
generator: codex-adapter
|
|
2255
|
+
adapterVersion: 1
|
|
2256
|
+
FET:END -->
|
|
2257
|
+
|
|
2258
|
+
${body}`
|
|
2138
2259
|
};
|
|
2139
2260
|
}
|
|
2140
2261
|
function codexCommandFiles(language = DEFAULT_LANGUAGE) {
|
|
@@ -2162,7 +2283,7 @@ generator: codex-adapter
|
|
|
2162
2283
|
adapterVersion: 1
|
|
2163
2284
|
FET:END -->
|
|
2164
2285
|
|
|
2165
|
-
# Andrej Karpathy Inspired Coding Guidelines
|
|
2286
|
+
# ${language === "en" ? "Andrej Karpathy Inspired Coding Guidelines" : "\u53D7 Andrej Karpathy \u542F\u53D1\u7684\u7F16\u7801\u6307\u5357"}
|
|
2166
2287
|
|
|
2167
2288
|
${renderKarpathyGuidelinesBody(language)}
|
|
2168
2289
|
`
|
|
@@ -2216,6 +2337,34 @@ After the command completes, report the important next steps from the FET output
|
|
|
2216
2337
|
function renderCommandZh(command) {
|
|
2217
2338
|
const usage = renderFetAdapterUsage(command, command === "fill-context" ? "" : command === "passthrough" ? "<openspec-command> [...args]" : "");
|
|
2218
2339
|
const title = commandTitleZh(command);
|
|
2340
|
+
if (command === "graph-setup") {
|
|
2341
|
+
return `<!-- FET:MANAGED
|
|
2342
|
+
schemaVersion: 1
|
|
2343
|
+
fetVersion: ${FET_VERSION}
|
|
2344
|
+
generator: codex-adapter
|
|
2345
|
+
adapterVersion: 1
|
|
2346
|
+
command: ${usage}
|
|
2347
|
+
FET:END -->
|
|
2348
|
+
|
|
2349
|
+
# ${usage}
|
|
2350
|
+
|
|
2351
|
+
${renderIdeModelPolicy(command, "zh-CN")}
|
|
2352
|
+
|
|
2353
|
+
${languageInstruction("zh-CN")}
|
|
2354
|
+
|
|
2355
|
+
\u7528\u4E8E\u6307\u5BFC\u5F53\u524D IDE LLM \u5728\u7528\u6237\u786E\u8BA4\u4E0B\u5B89\u88C5 GitNexus\u3002
|
|
2356
|
+
|
|
2357
|
+
\u5148\u8FD0\u884C\uFF1A
|
|
2358
|
+
|
|
2359
|
+
\`\`\`sh
|
|
2360
|
+
${usage}
|
|
2361
|
+
\`\`\`
|
|
2362
|
+
|
|
2363
|
+
\u7136\u540E\u9605\u8BFB .fet/graph-setup.md\uFF0C\u5E76\u4EE5\u5B83\u4F5C\u4E3A\u5B89\u88C5\u4EFB\u52A1\u4E66\u3002\u53EA\u8BFB\u68C0\u6D4B\u547D\u4EE4\u53EF\u4EE5\u76F4\u63A5\u8FD0\u884C\uFF1B\u4EFB\u4F55\u4F1A\u4E0B\u8F7D\u8F6F\u4EF6\u3001\u5168\u5C40\u5B89\u88C5\u3001\u4FEE\u6539 PATH\u3001\u5199\u5165\u7528\u6237\u7EA7\u6587\u4EF6\u6216\u4FEE\u6539 IDE/MCP \u914D\u7F6E\u7684\u547D\u4EE4\uFF0C\u6267\u884C\u524D\u90FD\u8981\u5C55\u793A\u5B8C\u6574\u547D\u4EE4\u5E76\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u3002
|
|
2364
|
+
|
|
2365
|
+
\u5B89\u88C5\u540E\u7528 \`gitnexus --version\` \u9A8C\u8BC1\u3002\u5408\u9002\u65F6\u7EE7\u7EED\u8FD0\u884C \`fet graph init\` \u548C \`fet graph handoff\`\u3002\u5982\u679C\u5B89\u88C5\u5931\u8D25\uFF0C\u62A5\u544A\u5931\u8D25\u547D\u4EE4\u3001stderr \u548C\u4E0B\u4E00\u6B65\u4EBA\u5DE5\u5904\u7406\u5EFA\u8BAE\u3002
|
|
2366
|
+
`;
|
|
2367
|
+
}
|
|
2219
2368
|
return `<!-- FET:MANAGED
|
|
2220
2369
|
schemaVersion: 1
|
|
2221
2370
|
fetVersion: ${FET_VERSION}
|
|
@@ -2279,6 +2428,34 @@ This preserves the FET entry point while allowing access to unmanaged or newly a
|
|
|
2279
2428
|
}
|
|
2280
2429
|
function renderGraphCommand(command, language) {
|
|
2281
2430
|
const usage = renderFetAdapterUsage(command, "");
|
|
2431
|
+
if (command === "graph-setup") {
|
|
2432
|
+
return `<!-- FET:MANAGED
|
|
2433
|
+
schemaVersion: 1
|
|
2434
|
+
fetVersion: ${FET_VERSION}
|
|
2435
|
+
generator: codex-adapter
|
|
2436
|
+
adapterVersion: 1
|
|
2437
|
+
command: ${usage}
|
|
2438
|
+
FET:END -->
|
|
2439
|
+
|
|
2440
|
+
# ${usage}
|
|
2441
|
+
|
|
2442
|
+
${renderIdeModelPolicy(command, language)}
|
|
2443
|
+
|
|
2444
|
+
${languageInstruction(language)}
|
|
2445
|
+
|
|
2446
|
+
Use this command to guide IDE-assisted GitNexus installation with user approval.
|
|
2447
|
+
|
|
2448
|
+
Run:
|
|
2449
|
+
|
|
2450
|
+
\`\`\`sh
|
|
2451
|
+
${usage}
|
|
2452
|
+
\`\`\`
|
|
2453
|
+
|
|
2454
|
+
Then read .fet/graph-setup.md and follow it as the source of truth. You may run read-only detection commands directly. Before downloading software, installing globally, changing PATH, writing user-level files, or modifying IDE/MCP configuration, show the exact command and wait for user approval.
|
|
2455
|
+
|
|
2456
|
+
After installation, verify \`gitnexus --version\`. If appropriate, continue with \`fet graph init\` and \`fet graph handoff\`. If installation fails, report the failing command, stderr, and next manual step.
|
|
2457
|
+
`;
|
|
2458
|
+
}
|
|
2282
2459
|
const subcommand = command.slice("graph-".length);
|
|
2283
2460
|
return `<!-- FET:MANAGED
|
|
2284
2461
|
schemaVersion: 1
|
|
@@ -2351,6 +2528,9 @@ function renderSlashPrompt(command, language) {
|
|
|
2351
2528
|
if (command === "passthrough") {
|
|
2352
2529
|
return renderPassthroughSlashPrompt(language);
|
|
2353
2530
|
}
|
|
2531
|
+
if (command === "graph-setup") {
|
|
2532
|
+
return renderGraphSetupSlashPrompt(language);
|
|
2533
|
+
}
|
|
2354
2534
|
const usage = renderFetAdapterUsage(command);
|
|
2355
2535
|
const isGraph = command.startsWith("graph-");
|
|
2356
2536
|
const shellCommand = isGraph ? `${renderFetAdapterUsage(command, "")} $ARGUMENTS` : `fet ${command} $ARGUMENTS`;
|
|
@@ -2385,6 +2565,9 @@ After it completes, summarize the important FET output and next steps.
|
|
|
2385
2565
|
`;
|
|
2386
2566
|
}
|
|
2387
2567
|
function renderSlashPromptZh(command) {
|
|
2568
|
+
if (command === "graph-setup") {
|
|
2569
|
+
return renderGraphSetupSlashPrompt("zh-CN");
|
|
2570
|
+
}
|
|
2388
2571
|
const usage = renderFetAdapterUsage(command, command === "fill-context" ? "" : command === "passthrough" ? "<openspec-command> [...args]" : "[...args]");
|
|
2389
2572
|
const argumentHint = command === "passthrough" ? "openspec-command [...args]" : void 0;
|
|
2390
2573
|
const argumentHintLine = argumentHint ? `argument-hint: ${argumentHint}
|
|
@@ -2778,6 +2961,62 @@ Guardrails:
|
|
|
2778
2961
|
language
|
|
2779
2962
|
);
|
|
2780
2963
|
}
|
|
2964
|
+
function renderGraphSetupSlashPrompt(language) {
|
|
2965
|
+
if (language === "en") {
|
|
2966
|
+
return renderManagedSlashPrompt(
|
|
2967
|
+
"fet graph setup",
|
|
2968
|
+
"Guide IDE-assisted GitNexus installation with user approval",
|
|
2969
|
+
`Guide optional GitNexus installation for this project.
|
|
2970
|
+
|
|
2971
|
+
Steps:
|
|
2972
|
+
|
|
2973
|
+
1. Run:
|
|
2974
|
+
\`\`\`sh
|
|
2975
|
+
fet graph setup
|
|
2976
|
+
\`\`\`
|
|
2977
|
+
2. Read .fet/graph-setup.md and follow it as the source of truth.
|
|
2978
|
+
3. Run read-only detection commands as needed, such as checking the shell, PATH, package managers, and \`gitnexus --version\`.
|
|
2979
|
+
4. If GitNexus is missing, use the configured \`FET_GITNEXUS_INSTALL_COMMAND\` when present; otherwise find the official GitNexus installation instructions or ask the user for the preferred method.
|
|
2980
|
+
5. Before any command that downloads software, installs globally, changes PATH, writes user-level files, or modifies IDE/MCP settings, show the exact command and wait for user approval.
|
|
2981
|
+
6. Verify installation with \`gitnexus --version\`.
|
|
2982
|
+
7. If the user wants IDE/MCP integration, explain \`gitnexus setup\` and run it only after approval.
|
|
2983
|
+
8. Run \`fet graph init\` and then \`fet graph handoff\` when GitNexus is available.
|
|
2984
|
+
|
|
2985
|
+
Guardrails:
|
|
2986
|
+
- GitNexus is optional; do not block FET/OpenSpec workflows if installation fails.
|
|
2987
|
+
- Do not modify application code during setup.
|
|
2988
|
+
- Report the failing command, stderr, and next manual step if blocked.`,
|
|
2989
|
+
void 0,
|
|
2990
|
+
language
|
|
2991
|
+
);
|
|
2992
|
+
}
|
|
2993
|
+
return renderManagedSlashPrompt(
|
|
2994
|
+
"fet graph setup",
|
|
2995
|
+
"\u6307\u5BFC IDE LLM \u5728\u7528\u6237\u786E\u8BA4\u4E0B\u5B89\u88C5 GitNexus",
|
|
2996
|
+
`\u4E3A\u5F53\u524D\u9879\u76EE\u5F15\u5BFC\u53EF\u9009\u7684 GitNexus \u5B89\u88C5\u3002
|
|
2997
|
+
|
|
2998
|
+
\u6B65\u9AA4\uFF1A
|
|
2999
|
+
|
|
3000
|
+
1. \u8FD0\u884C\uFF1A
|
|
3001
|
+
\`\`\`sh
|
|
3002
|
+
fet graph setup
|
|
3003
|
+
\`\`\`
|
|
3004
|
+
2. \u9605\u8BFB .fet/graph-setup.md\uFF0C\u5E76\u4EE5\u5B83\u4F5C\u4E3A\u5B89\u88C5\u4EFB\u52A1\u4E66\u3002
|
|
3005
|
+
3. \u6309\u9700\u8FD0\u884C\u53EA\u8BFB\u68C0\u6D4B\u547D\u4EE4\uFF0C\u4F8B\u5982\u68C0\u67E5 shell\u3001PATH\u3001\u5305\u7BA1\u7406\u5668\u548C \`gitnexus --version\`\u3002
|
|
3006
|
+
4. \u5982\u679C GitNexus \u7F3A\u5931\uFF0C\u4F18\u5148\u4F7F\u7528\u5DF2\u914D\u7F6E\u7684 \`FET_GITNEXUS_INSTALL_COMMAND\`\uFF1B\u6CA1\u6709\u914D\u7F6E\u65F6\uFF0C\u67E5\u627E GitNexus \u5B98\u65B9\u5B89\u88C5\u8BF4\u660E\uFF0C\u6216\u8BE2\u95EE\u7528\u6237\u5E0C\u671B\u4F7F\u7528\u7684\u5B89\u88C5\u65B9\u5F0F\u3002
|
|
3007
|
+
5. \u4EFB\u4F55\u4F1A\u4E0B\u8F7D\u8F6F\u4EF6\u3001\u5168\u5C40\u5B89\u88C5\u3001\u4FEE\u6539 PATH\u3001\u5199\u5165\u7528\u6237\u7EA7\u6587\u4EF6\u6216\u4FEE\u6539 IDE/MCP \u8BBE\u7F6E\u7684\u547D\u4EE4\uFF0C\u6267\u884C\u524D\u90FD\u8981\u5C55\u793A\u5B8C\u6574\u547D\u4EE4\u5E76\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u3002
|
|
3008
|
+
6. \u7528 \`gitnexus --version\` \u9A8C\u8BC1\u5B89\u88C5\u3002
|
|
3009
|
+
7. \u5982\u679C\u7528\u6237\u9700\u8981 IDE/MCP \u96C6\u6210\uFF0C\u5148\u8BF4\u660E \`gitnexus setup\`\uFF0C\u83B7\u5F97\u786E\u8BA4\u540E\u518D\u8FD0\u884C\u3002
|
|
3010
|
+
8. GitNexus \u53EF\u7528\u540E\u8FD0\u884C \`fet graph init\`\uFF0C\u518D\u8FD0\u884C \`fet graph handoff\`\u3002
|
|
3011
|
+
|
|
3012
|
+
\u7EA6\u675F\uFF1A
|
|
3013
|
+
- GitNexus \u662F\u53EF\u9009\u80FD\u529B\uFF1B\u5B89\u88C5\u5931\u8D25\u65F6\u4E0D\u8981\u963B\u585E FET/OpenSpec \u4E3B\u6D41\u7A0B\u3002
|
|
3014
|
+
- \u5B89\u88C5\u8FC7\u7A0B\u4E2D\u4E0D\u8981\u4FEE\u6539\u4E1A\u52A1\u4EE3\u7801\u3002
|
|
3015
|
+
- \u5982\u679C\u53D7\u963B\uFF0C\u62A5\u544A\u5931\u8D25\u547D\u4EE4\u3001stderr \u548C\u4E0B\u4E00\u6B65\u4EBA\u5DE5\u5904\u7406\u5EFA\u8BAE\u3002`,
|
|
3016
|
+
void 0,
|
|
3017
|
+
language
|
|
3018
|
+
);
|
|
3019
|
+
}
|
|
2781
3020
|
function renderExploreSlashPrompt(language) {
|
|
2782
3021
|
return renderManagedSlashPrompt(
|
|
2783
3022
|
"fet explore [...args]",
|
|
@@ -2897,6 +3136,7 @@ function renderManagedSlashPrompt(command, description, body, argumentHint, lang
|
|
|
2897
3136
|
const policyCommand = command.split(/\s+/)[1] ?? command;
|
|
2898
3137
|
const argumentHintLine = argumentHint ? `argument-hint: ${argumentHint}
|
|
2899
3138
|
` : "";
|
|
3139
|
+
const graphContextInstruction = language === "en" ? "If GitNexus graph context is available, consult it before broad source scans and use it to narrow the files you read. If it is unavailable, continue normally." : "\u5982\u679C GitNexus \u4EE3\u7801\u56FE\u4E0A\u4E0B\u6587\u53EF\u7528\uFF0C\u5148\u7528\u5B83\u7F29\u5C0F\u6E90\u7801\u626B\u63CF\u8303\u56F4\uFF1B\u4E0D\u53EF\u7528\u65F6\u6309\u666E\u901A\u6D41\u7A0B\u7EE7\u7EED\u3002";
|
|
2900
3140
|
return `<!-- FET:MANAGED
|
|
2901
3141
|
schemaVersion: 1
|
|
2902
3142
|
fetVersion: ${FET_VERSION}
|
|
@@ -2913,7 +3153,7 @@ ${renderIdeModelPolicy(policyCommand, language)}
|
|
|
2913
3153
|
|
|
2914
3154
|
${languageInstruction(language)}
|
|
2915
3155
|
|
|
2916
|
-
|
|
3156
|
+
${graphContextInstruction}
|
|
2917
3157
|
|
|
2918
3158
|
${body}
|
|
2919
3159
|
`;
|
|
@@ -3088,6 +3328,36 @@ ${languageInstruction(language)}
|
|
|
3088
3328
|
- openspec/config.yaml
|
|
3089
3329
|
|
|
3090
3330
|
\u68C0\u67E5 README\u3001package scripts\u3001\u8DEF\u7531\u3001\u6D4B\u8BD5\u3001\u6E90\u7801\u7ED3\u6784\u548C\u73B0\u6709\u7EA6\u5B9A\u540E\uFF0C\u628A AGENTS.md \u4E2D\u6BCF\u4E2A \`[NEEDS LLM INPUT]\` \u6216 \`[NEED LLM INPUT]\` \u5360\u4F4D\u7B26\u66FF\u6362\u4E3A\u5177\u4F53\u3001\u7B80\u6D01\u3001\u9879\u76EE\u76F8\u5173\u7684\u5185\u5BB9\u3002\u4FDD\u7559 FET \u6258\u7BA1\u6807\u8BB0\uFF0C\u4E0D\u8981\u4FEE\u6539\u4E1A\u52A1\u4EE3\u7801\u3002
|
|
3331
|
+
`;
|
|
3332
|
+
}
|
|
3333
|
+
if (command === "graph-setup") {
|
|
3334
|
+
return `<!-- FET:MANAGED
|
|
3335
|
+
schemaVersion: 1
|
|
3336
|
+
fetVersion: ${FET_VERSION}
|
|
3337
|
+
generator: cursor-adapter
|
|
3338
|
+
adapterVersion: 1
|
|
3339
|
+
command: fet graph setup
|
|
3340
|
+
FET:END -->
|
|
3341
|
+
|
|
3342
|
+
---
|
|
3343
|
+
name: fet-graph-setup
|
|
3344
|
+
description: ${language === "en" ? "Guide IDE-assisted GitNexus installation with user approval" : "\u6307\u5BFC IDE LLM \u5728\u7528\u6237\u786E\u8BA4\u4E0B\u5B89\u88C5 GitNexus"}
|
|
3345
|
+
disable-model-invocation: false
|
|
3346
|
+
---
|
|
3347
|
+
|
|
3348
|
+
${renderIdeModelPolicy(command, language)}
|
|
3349
|
+
|
|
3350
|
+
${languageInstruction(language)}
|
|
3351
|
+
|
|
3352
|
+
${language === "en" ? `Run \`fet graph setup\`, then read .fet/graph-setup.md and follow it as an installation playbook.
|
|
3353
|
+
|
|
3354
|
+
You may run read-only detection commands without extra confirmation. Before any command that downloads software, installs globally, changes PATH, writes user-level config, or modifies IDE/MCP settings, show the exact command and wait for user approval.
|
|
3355
|
+
|
|
3356
|
+
After installation, verify with \`gitnexus --version\`, then run \`fet graph init\` and \`fet graph handoff\` when appropriate. If installation fails, summarize the failing command and next manual step.` : `\u5148\u8FD0\u884C \`fet graph setup\`\uFF0C\u518D\u9605\u8BFB .fet/graph-setup.md\uFF0C\u5E76\u628A\u5B83\u4F5C\u4E3A\u5B89\u88C5\u4EFB\u52A1\u4E66\u6267\u884C\u3002
|
|
3357
|
+
|
|
3358
|
+
\u53EA\u8BFB\u68C0\u6D4B\u547D\u4EE4\u53EF\u4EE5\u76F4\u63A5\u8FD0\u884C\u3002\u4EFB\u4F55\u4F1A\u4E0B\u8F7D\u8F6F\u4EF6\u3001\u5168\u5C40\u5B89\u88C5\u3001\u4FEE\u6539 PATH\u3001\u5199\u5165\u7528\u6237\u7EA7\u914D\u7F6E\u6216\u4FEE\u6539 IDE/MCP \u8BBE\u7F6E\u7684\u547D\u4EE4\uFF0C\u6267\u884C\u524D\u90FD\u8981\u5C55\u793A\u5B8C\u6574\u547D\u4EE4\u5E76\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u3002
|
|
3359
|
+
|
|
3360
|
+
\u5B89\u88C5\u540E\u7528 \`gitnexus --version\` \u9A8C\u8BC1\uFF1B\u5408\u9002\u65F6\u7EE7\u7EED\u8FD0\u884C \`fet graph init\` \u548C \`fet graph handoff\`\u3002\u5982\u679C\u5B89\u88C5\u5931\u8D25\uFF0C\u6C47\u603B\u5931\u8D25\u547D\u4EE4\u548C\u4E0B\u4E00\u6B65\u4EBA\u5DE5\u5904\u7406\u5EFA\u8BAE\u3002`}
|
|
3091
3361
|
`;
|
|
3092
3362
|
}
|
|
3093
3363
|
return `<!-- FET:MANAGED
|
|
@@ -3805,7 +4075,7 @@ function renderModelPolicyActionHint(policyMode, language) {
|
|
|
3805
4075
|
if (policyMode === "confirm") {
|
|
3806
4076
|
return language === "en" ? "Choose whether to continue this command or stop and switch models." : "\u8BF7\u9009\u62E9\u7EE7\u7EED\u6267\u884C\u672C\u547D\u4EE4\uFF0C\u6216\u505C\u6B62\u540E\u624B\u52A8\u5207\u6362\u6A21\u578B\u3002";
|
|
3807
4077
|
}
|
|
3808
|
-
return language === "en" ? "This is advisory; the command will continue.
|
|
4078
|
+
return language === "en" ? "This is advisory because FET_MODEL_POLICY=warn; the command will continue." : "\u5F53\u524D\u8BBE\u7F6E FET_MODEL_POLICY=warn\uFF0C\u8BE5\u63D0\u9192\u4EC5\u4F5C\u4E3A\u5EFA\u8BAE\uFF0C\u547D\u4EE4\u4F1A\u7EE7\u7EED\u6267\u884C\u3002";
|
|
3809
4079
|
}
|
|
3810
4080
|
async function warnIfContextPlaceholdersRemain(ctx) {
|
|
3811
4081
|
if (["init", "update-context", "fill-context", "doctor"].includes(ctx.command)) {
|