@nick848/fet 1.0.10 → 1.1.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/README_en.md
CHANGED
|
@@ -42,6 +42,7 @@ Check the installation:
|
|
|
42
42
|
```sh
|
|
43
43
|
fet --version
|
|
44
44
|
fet --help
|
|
45
|
+
fet update
|
|
45
46
|
```
|
|
46
47
|
|
|
47
48
|
## Quick Start
|
|
@@ -100,6 +101,7 @@ fet init --lang en
|
|
|
100
101
|
| Command | Usage | Description |
|
|
101
102
|
|---------|-------|-------------|
|
|
102
103
|
| `fet init` | `fet init [--yes] [--lang <language>]` | Initialize FET and OpenSpec; generate context, state, Cursor integration, and Codex workflow guides. |
|
|
104
|
+
| `fet update` | `fet update` | Check whether FET is the latest published version and automatically upgrade when a newer version is available. |
|
|
103
105
|
| `fet update-context` | `fet update-context [--yes]` | Rescan the project and update FET-managed regions in `AGENTS.md` and `openspec/config.yaml`. |
|
|
104
106
|
| `fet fill-context` | `fet fill-context [--yes]` | Refresh IDE handoff commands that ask AI to replace `AGENTS.md` placeholders. |
|
|
105
107
|
| `fet doctor` | `fet doctor [--fix-lock]` | Diagnose OpenSpec, FET state, context files, tool integration, and lock files. |
|
|
@@ -15,6 +15,7 @@ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
|
|
|
15
15
|
ErrorCode2["LockHeld"] = "LOCK_HELD";
|
|
16
16
|
ErrorCode2["UserCancelled"] = "USER_CANCELLED";
|
|
17
17
|
ErrorCode2["UnsafeScriptApprovalRequired"] = "UNSAFE_SCRIPT_APPROVAL_REQUIRED";
|
|
18
|
+
ErrorCode2["UpdateFailed"] = "UPDATE_FAILED";
|
|
18
19
|
ErrorCode2["ToolAdapterConflict"] = "TOOL_ADAPTER_CONFLICT";
|
|
19
20
|
ErrorCode2["ConfigInvalid"] = "CONFIG_INVALID";
|
|
20
21
|
ErrorCode2["FileSystemError"] = "FILE_SYSTEM_ERROR";
|
|
@@ -31,6 +32,7 @@ function exitCodeForError(code) {
|
|
|
31
32
|
return 3;
|
|
32
33
|
case "OPENSPEC_COMMAND_FAILED" /* OpenSpecCommandFailed */:
|
|
33
34
|
case "GRAPH_COMMAND_FAILED" /* GraphCommandFailed */:
|
|
35
|
+
case "UPDATE_FAILED" /* UpdateFailed */:
|
|
34
36
|
return 4;
|
|
35
37
|
case "OPENSPEC_STRUCTURE_UNKNOWN" /* OpenSpecStructureUnknown */:
|
|
36
38
|
case "STATE_SCHEMA_UNSUPPORTED" /* StateSchemaUnsupported */:
|
|
@@ -105,4 +107,4 @@ export {
|
|
|
105
107
|
FetError,
|
|
106
108
|
toFetError
|
|
107
109
|
};
|
|
108
|
-
//# sourceMappingURL=chunk-
|
|
110
|
+
//# sourceMappingURL=chunk-J5WB4KAL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors/codes.ts","../src/errors/fet-error.ts"],"sourcesContent":["export enum ErrorCode {\n Unknown = \"UNKNOWN\",\n InvalidArguments = \"INVALID_ARGUMENTS\",\n OpenSpecNotFound = \"OPENSPEC_NOT_FOUND\",\n OpenSpecUnsupportedVersion = \"OPENSPEC_UNSUPPORTED_VERSION\",\n OpenSpecCommandFailed = \"OPENSPEC_COMMAND_FAILED\",\n OpenSpecStructureUnknown = \"OPENSPEC_STRUCTURE_UNKNOWN\",\n GraphProviderNotFound = \"GRAPH_PROVIDER_NOT_FOUND\",\n GraphCommandFailed = \"GRAPH_COMMAND_FAILED\",\n StateSchemaUnsupported = \"STATE_SCHEMA_UNSUPPORTED\",\n StateCorrupted = \"STATE_CORRUPTED\",\n LockHeld = \"LOCK_HELD\",\n UserCancelled = \"USER_CANCELLED\",\n UnsafeScriptApprovalRequired = \"UNSAFE_SCRIPT_APPROVAL_REQUIRED\",\n UpdateFailed = \"UPDATE_FAILED\",\n ToolAdapterConflict = \"TOOL_ADAPTER_CONFLICT\",\n ConfigInvalid = \"CONFIG_INVALID\",\n FileSystemError = \"FILE_SYSTEM_ERROR\"\n}\n\nexport function exitCodeForError(code: ErrorCode): number {\n switch (code) {\n case ErrorCode.InvalidArguments:\n case ErrorCode.ConfigInvalid:\n return 2;\n case ErrorCode.OpenSpecNotFound:\n case ErrorCode.OpenSpecUnsupportedVersion:\n case ErrorCode.GraphProviderNotFound:\n return 3;\n case ErrorCode.OpenSpecCommandFailed:\n case ErrorCode.GraphCommandFailed:\n case ErrorCode.UpdateFailed:\n return 4;\n case ErrorCode.OpenSpecStructureUnknown:\n case ErrorCode.StateSchemaUnsupported:\n case ErrorCode.StateCorrupted:\n case ErrorCode.ToolAdapterConflict:\n case ErrorCode.FileSystemError:\n return 5;\n case ErrorCode.LockHeld:\n return 6;\n case ErrorCode.UserCancelled:\n return 7;\n case ErrorCode.UnsafeScriptApprovalRequired:\n return 8;\n case ErrorCode.Unknown:\n default:\n return 1;\n }\n}\n","import { ErrorCode, exitCodeForError } from \"./codes.js\";\n\nexport interface FetErrorOptions {\n code: ErrorCode;\n message: string;\n details?: unknown;\n recoverable?: boolean;\n suggestedCommand?: string;\n cause?: unknown;\n}\n\nexport class FetError extends Error {\n readonly code: ErrorCode;\n readonly exitCode: number;\n readonly details?: unknown;\n readonly recoverable: boolean;\n readonly suggestedCommand?: string;\n override readonly cause?: unknown;\n\n constructor(options: FetErrorOptions) {\n super(options.message);\n this.name = \"FetError\";\n this.code = options.code;\n this.exitCode = exitCodeForError(options.code);\n this.details = options.details;\n this.recoverable = options.recoverable ?? true;\n this.suggestedCommand = options.suggestedCommand;\n this.cause = options.cause;\n }\n\n toJSON() {\n return {\n code: this.code,\n exitCode: this.exitCode,\n message: this.message,\n details: this.details,\n recoverable: this.recoverable,\n suggestedCommand: this.suggestedCommand\n };\n }\n}\n\nexport function toFetError(error: unknown): FetError {\n if (error instanceof FetError) {\n return error;\n }\n\n if (error instanceof Error) {\n return new FetError({\n code: ErrorCode.Unknown,\n message: error.message,\n recoverable: false,\n cause: error\n });\n }\n\n return new FetError({\n code: ErrorCode.Unknown,\n message: \"Unknown error\",\n details: error,\n recoverable: false\n });\n}\n"],"mappings":";;;AAAO,IAAK,YAAL,kBAAKA,eAAL;AACL,EAAAA,WAAA,aAAU;AACV,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,gCAA6B;AAC7B,EAAAA,WAAA,2BAAwB;AACxB,EAAAA,WAAA,8BAA2B;AAC3B,EAAAA,WAAA,2BAAwB;AACxB,EAAAA,WAAA,wBAAqB;AACrB,EAAAA,WAAA,4BAAyB;AACzB,EAAAA,WAAA,oBAAiB;AACjB,EAAAA,WAAA,cAAW;AACX,EAAAA,WAAA,mBAAgB;AAChB,EAAAA,WAAA,kCAA+B;AAC/B,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,yBAAsB;AACtB,EAAAA,WAAA,mBAAgB;AAChB,EAAAA,WAAA,qBAAkB;AAjBR,SAAAA;AAAA,GAAA;AAoBL,SAAS,iBAAiB,MAAyB;AACxD,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL;AACE,aAAO;AAAA,EACX;AACF;;;ACtCO,IAAM,WAAN,cAAuB,MAAM;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACS;AAAA,EAElB,YAAY,SAA0B;AACpC,UAAM,QAAQ,OAAO;AACrB,SAAK,OAAO;AACZ,SAAK,OAAO,QAAQ;AACpB,SAAK,WAAW,iBAAiB,QAAQ,IAAI;AAC7C,SAAK,UAAU,QAAQ;AACvB,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,mBAAmB,QAAQ;AAChC,SAAK,QAAQ,QAAQ;AAAA,EACvB;AAAA,EAEA,SAAS;AACP,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,UAAU,KAAK;AAAA,MACf,SAAS,KAAK;AAAA,MACd,SAAS,KAAK;AAAA,MACd,aAAa,KAAK;AAAA,MAClB,kBAAkB,KAAK;AAAA,IACzB;AAAA,EACF;AACF;AAEO,SAAS,WAAW,OAA0B;AACnD,MAAI,iBAAiB,UAAU;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI,iBAAiB,OAAO;AAC1B,WAAO,IAAI,SAAS;AAAA,MAClB;AAAA,MACA,SAAS,MAAM;AAAA,MACf,aAAa;AAAA,MACb,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SAAO,IAAI,SAAS;AAAA,IAClB;AAAA,IACA,SAAS;AAAA,IACT,SAAS;AAAA,IACT,aAAa;AAAA,EACf,CAAC;AACH;","names":["ErrorCode"]}
|
package/dist/cli/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
FetError,
|
|
4
4
|
toFetError
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-J5WB4KAL.js";
|
|
6
6
|
|
|
7
7
|
// src/cli/index.ts
|
|
8
8
|
import { createInterface } from "readline/promises";
|
|
@@ -2254,6 +2254,195 @@ async function assertVerified(ctx) {
|
|
|
2254
2254
|
}
|
|
2255
2255
|
}
|
|
2256
2256
|
|
|
2257
|
+
// src/commands/update.ts
|
|
2258
|
+
import { spawn } from "child_process";
|
|
2259
|
+
var DEFAULT_PACKAGE_NAME = "@nick848/fet";
|
|
2260
|
+
async function updateCommand(ctx) {
|
|
2261
|
+
const packageName = process.env.FET_UPDATE_PACKAGE_NAME ?? DEFAULT_PACKAGE_NAME;
|
|
2262
|
+
const npmExecutable = process.env.FET_UPDATE_NPM_EXECUTABLE ?? defaultNpmExecutable();
|
|
2263
|
+
const latestVersion = await resolveLatestVersion(packageName, npmExecutable);
|
|
2264
|
+
const currentVersion = ctx.fetVersion;
|
|
2265
|
+
if (compareVersions(currentVersion, latestVersion) >= 0) {
|
|
2266
|
+
ctx.output.result({
|
|
2267
|
+
ok: true,
|
|
2268
|
+
command: "update",
|
|
2269
|
+
summary: ctx.language === "en" ? `FET is already up to date (${currentVersion}).` : `FET \u5DF2\u662F\u6700\u65B0\u7248 (${currentVersion})\u3002`,
|
|
2270
|
+
data: {
|
|
2271
|
+
packageName,
|
|
2272
|
+
currentVersion,
|
|
2273
|
+
latestVersion,
|
|
2274
|
+
updated: false
|
|
2275
|
+
}
|
|
2276
|
+
});
|
|
2277
|
+
return;
|
|
2278
|
+
}
|
|
2279
|
+
if (!ctx.json) {
|
|
2280
|
+
ctx.output.info(
|
|
2281
|
+
ctx.language === "en" ? `Updating FET from ${currentVersion} to ${latestVersion}...` : `\u6B63\u5728\u5C06 FET \u4ECE ${currentVersion} \u5347\u7EA7\u5230 ${latestVersion}...`
|
|
2282
|
+
);
|
|
2283
|
+
}
|
|
2284
|
+
const installArgs = ["install", "-g", `${packageName}@latest`];
|
|
2285
|
+
const result = await runNpm(npmExecutable, installArgs, {
|
|
2286
|
+
cwd: ctx.cwd,
|
|
2287
|
+
stdio: ctx.json ? "pipe" : "inherit"
|
|
2288
|
+
});
|
|
2289
|
+
if (result.exitCode !== 0) {
|
|
2290
|
+
throw new FetError({
|
|
2291
|
+
code: "UPDATE_FAILED" /* UpdateFailed */,
|
|
2292
|
+
message: ctx.language === "en" ? "FET update failed." : "FET \u5347\u7EA7\u5931\u8D25\u3002",
|
|
2293
|
+
details: result,
|
|
2294
|
+
suggestedCommand: `${npmExecutable} ${installArgs.join(" ")}`
|
|
2295
|
+
});
|
|
2296
|
+
}
|
|
2297
|
+
ctx.output.result({
|
|
2298
|
+
ok: true,
|
|
2299
|
+
command: "update",
|
|
2300
|
+
summary: ctx.language === "en" ? `FET updated from ${currentVersion} to ${latestVersion}.` : `FET \u5DF2\u4ECE ${currentVersion} \u5347\u7EA7\u5230 ${latestVersion}\u3002`,
|
|
2301
|
+
data: {
|
|
2302
|
+
packageName,
|
|
2303
|
+
currentVersion,
|
|
2304
|
+
latestVersion,
|
|
2305
|
+
updated: true,
|
|
2306
|
+
installCommand: `${npmExecutable} ${installArgs.join(" ")}`
|
|
2307
|
+
}
|
|
2308
|
+
});
|
|
2309
|
+
}
|
|
2310
|
+
async function resolveLatestVersion(packageName, npmExecutable) {
|
|
2311
|
+
const override = process.env.FET_UPDATE_LATEST_VERSION?.trim();
|
|
2312
|
+
if (override) {
|
|
2313
|
+
return override;
|
|
2314
|
+
}
|
|
2315
|
+
const result = await runNpm(npmExecutable, ["view", packageName, "version", "--json"], {
|
|
2316
|
+
cwd: process.cwd(),
|
|
2317
|
+
stdio: "pipe"
|
|
2318
|
+
});
|
|
2319
|
+
if (result.exitCode !== 0) {
|
|
2320
|
+
throw new FetError({
|
|
2321
|
+
code: "UPDATE_FAILED" /* UpdateFailed */,
|
|
2322
|
+
message: "Unable to check the latest FET version from npm.",
|
|
2323
|
+
details: result,
|
|
2324
|
+
suggestedCommand: `${npmExecutable} view ${packageName} version`
|
|
2325
|
+
});
|
|
2326
|
+
}
|
|
2327
|
+
const version = parseNpmVersion(result.stdout ?? "");
|
|
2328
|
+
if (!version) {
|
|
2329
|
+
throw new FetError({
|
|
2330
|
+
code: "UPDATE_FAILED" /* UpdateFailed */,
|
|
2331
|
+
message: "npm returned an invalid FET version.",
|
|
2332
|
+
details: { stdout: result.stdout }
|
|
2333
|
+
});
|
|
2334
|
+
}
|
|
2335
|
+
return version;
|
|
2336
|
+
}
|
|
2337
|
+
function parseNpmVersion(stdout) {
|
|
2338
|
+
const trimmed = stdout.trim();
|
|
2339
|
+
if (!trimmed) {
|
|
2340
|
+
return null;
|
|
2341
|
+
}
|
|
2342
|
+
try {
|
|
2343
|
+
const parsed = JSON.parse(trimmed);
|
|
2344
|
+
return typeof parsed === "string" && parsed.length > 0 ? parsed : null;
|
|
2345
|
+
} catch {
|
|
2346
|
+
return trimmed;
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
function runNpm(command, args, options) {
|
|
2350
|
+
return new Promise((resolve2, reject) => {
|
|
2351
|
+
const stdout = [];
|
|
2352
|
+
const stderr = [];
|
|
2353
|
+
const child = spawn(command, args, {
|
|
2354
|
+
cwd: options.cwd,
|
|
2355
|
+
stdio: options.stdio,
|
|
2356
|
+
shell: process.platform === "win32"
|
|
2357
|
+
});
|
|
2358
|
+
child.stdout?.on("data", (chunk) => stdout.push(chunk));
|
|
2359
|
+
child.stderr?.on("data", (chunk) => stderr.push(chunk));
|
|
2360
|
+
child.on("error", (error) => {
|
|
2361
|
+
reject(
|
|
2362
|
+
new FetError({
|
|
2363
|
+
code: "UPDATE_FAILED" /* UpdateFailed */,
|
|
2364
|
+
message: "Unable to run npm for FET update.",
|
|
2365
|
+
details: { command, args },
|
|
2366
|
+
cause: error,
|
|
2367
|
+
suggestedCommand: `${command} ${args.join(" ")}`
|
|
2368
|
+
})
|
|
2369
|
+
);
|
|
2370
|
+
});
|
|
2371
|
+
child.on("close", (exitCode, signal) => {
|
|
2372
|
+
resolve2({
|
|
2373
|
+
command,
|
|
2374
|
+
args,
|
|
2375
|
+
exitCode: exitCode ?? 1,
|
|
2376
|
+
signal,
|
|
2377
|
+
stdout: stdout.length ? Buffer.concat(stdout).toString("utf8") : void 0,
|
|
2378
|
+
stderr: stderr.length ? Buffer.concat(stderr).toString("utf8") : void 0
|
|
2379
|
+
});
|
|
2380
|
+
});
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
function defaultNpmExecutable() {
|
|
2384
|
+
return process.platform === "win32" ? "npm.cmd" : "npm";
|
|
2385
|
+
}
|
|
2386
|
+
function compareVersions(left, right) {
|
|
2387
|
+
const leftVersion = parseVersion(left);
|
|
2388
|
+
const rightVersion = parseVersion(right);
|
|
2389
|
+
for (let index = 0; index < 3; index += 1) {
|
|
2390
|
+
const diff = leftVersion.main[index] - rightVersion.main[index];
|
|
2391
|
+
if (diff !== 0) {
|
|
2392
|
+
return Math.sign(diff);
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
if (!leftVersion.prerelease.length && rightVersion.prerelease.length) {
|
|
2396
|
+
return 1;
|
|
2397
|
+
}
|
|
2398
|
+
if (leftVersion.prerelease.length && !rightVersion.prerelease.length) {
|
|
2399
|
+
return -1;
|
|
2400
|
+
}
|
|
2401
|
+
const length = Math.max(leftVersion.prerelease.length, rightVersion.prerelease.length);
|
|
2402
|
+
for (let index = 0; index < length; index += 1) {
|
|
2403
|
+
const leftPart = leftVersion.prerelease[index];
|
|
2404
|
+
const rightPart = rightVersion.prerelease[index];
|
|
2405
|
+
if (leftPart === void 0) {
|
|
2406
|
+
return -1;
|
|
2407
|
+
}
|
|
2408
|
+
if (rightPart === void 0) {
|
|
2409
|
+
return 1;
|
|
2410
|
+
}
|
|
2411
|
+
const diff = comparePrereleasePart(leftPart, rightPart);
|
|
2412
|
+
if (diff !== 0) {
|
|
2413
|
+
return diff;
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
return 0;
|
|
2417
|
+
}
|
|
2418
|
+
function parseVersion(version) {
|
|
2419
|
+
const [withoutBuild] = version.trim().replace(/^v/i, "").split("+");
|
|
2420
|
+
const [mainValue = "", prereleaseValue = ""] = withoutBuild.split("-");
|
|
2421
|
+
const mainParts = mainValue.split(".").map((part) => Number.parseInt(part, 10));
|
|
2422
|
+
return {
|
|
2423
|
+
main: [
|
|
2424
|
+
Number.isFinite(mainParts[0]) ? mainParts[0] : 0,
|
|
2425
|
+
Number.isFinite(mainParts[1]) ? mainParts[1] : 0,
|
|
2426
|
+
Number.isFinite(mainParts[2]) ? mainParts[2] : 0
|
|
2427
|
+
],
|
|
2428
|
+
prerelease: prereleaseValue ? prereleaseValue.split(".") : []
|
|
2429
|
+
};
|
|
2430
|
+
}
|
|
2431
|
+
function comparePrereleasePart(left, right) {
|
|
2432
|
+
const leftNumber = /^\d+$/.test(left) ? Number.parseInt(left, 10) : null;
|
|
2433
|
+
const rightNumber = /^\d+$/.test(right) ? Number.parseInt(right, 10) : null;
|
|
2434
|
+
if (leftNumber !== null && rightNumber !== null) {
|
|
2435
|
+
return Math.sign(leftNumber - rightNumber);
|
|
2436
|
+
}
|
|
2437
|
+
if (leftNumber !== null) {
|
|
2438
|
+
return -1;
|
|
2439
|
+
}
|
|
2440
|
+
if (rightNumber !== null) {
|
|
2441
|
+
return 1;
|
|
2442
|
+
}
|
|
2443
|
+
return left.localeCompare(right);
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2257
2446
|
// src/commands/verify.ts
|
|
2258
2447
|
import { createHash } from "crypto";
|
|
2259
2448
|
import { mkdir as mkdir7, readFile as readFile12, stat as stat5 } from "fs/promises";
|
|
@@ -3921,14 +4110,14 @@ function exec(command, args) {
|
|
|
3921
4110
|
}
|
|
3922
4111
|
|
|
3923
4112
|
// src/openspec/runner.ts
|
|
3924
|
-
import { spawn } from "child_process";
|
|
4113
|
+
import { spawn as spawn2 } from "child_process";
|
|
3925
4114
|
async function runOpenSpec(executablePath, command, args, options) {
|
|
3926
4115
|
const spawnCommand = executablePath === "npx openspec" ? "npx" : executablePath;
|
|
3927
4116
|
const spawnArgs = executablePath === "npx openspec" ? ["openspec", command, ...args] : [command, ...args];
|
|
3928
4117
|
return new Promise((resolve2, reject) => {
|
|
3929
4118
|
const stdout = [];
|
|
3930
4119
|
const stderr = [];
|
|
3931
|
-
const child =
|
|
4120
|
+
const child = spawn2(spawnCommand, spawnArgs, {
|
|
3932
4121
|
cwd: options.cwd,
|
|
3933
4122
|
stdio: options.stdio ?? "inherit",
|
|
3934
4123
|
shell: process.platform === "win32"
|
|
@@ -4350,6 +4539,7 @@ async function createCommandContext(command, options) {
|
|
|
4350
4539
|
var program = new Command();
|
|
4351
4540
|
program.name("fet").description("\u56F4\u7ED5 OpenSpec \u7684\u524D\u7AEF\u5F00\u53D1\u5DE5\u4F5C\u6D41\u7F16\u6392\u5DE5\u5177\u3002").enablePositionalOptions().version(FET_VERSION).option("--cwd <path>", "\u6307\u5B9A\u9879\u76EE\u6839\u76EE\u5F55").option("--change <id>", "\u6307\u5B9A OpenSpec change").option("--lang <language>", "\u6307\u5B9A FET \u4EA4\u4E92\u4FE1\u606F\u548C\u751F\u6210\u4EA7\u7269\u8BED\u8A00\uFF0C\u9ED8\u8BA4 zh-CN").option("--yes", "\u5BF9\u4F4E\u98CE\u9669\u786E\u8BA4\u4F7F\u7528\u9ED8\u8BA4\u540C\u610F").option("--json", "\u8F93\u51FA\u673A\u5668\u53EF\u8BFB JSON").option("--verbose", "\u8F93\u51FA\u8BCA\u65AD\u7EC6\u8282").option("--no-color", "\u7981\u7528\u7EC8\u7AEF\u989C\u8272");
|
|
4352
4541
|
addGlobalOptions(program.command("init")).description("\u521D\u59CB\u5316 FET + OpenSpec").action(wrap("init", initCommand));
|
|
4542
|
+
addGlobalOptions(program.command("update")).description("\u68C0\u67E5 FET \u662F\u5426\u4E3A\u6700\u65B0\u7248\uFF0C\u5E76\u5728\u9700\u8981\u65F6\u81EA\u52A8\u5347\u7EA7").action(wrap("update", updateCommand));
|
|
4353
4543
|
addGlobalOptions(program.command("update-context")).description("\u66F4\u65B0\u9879\u76EE\u4E0A\u4E0B\u6587").action(wrap("update-context", updateContextCommand));
|
|
4354
4544
|
addGlobalOptions(program.command("fill-context")).description("\u5237\u65B0 IDE \u586B\u5145 AGENTS.md \u5360\u4F4D\u7B26\u7684\u63D0\u793A\u6587\u4EF6").action(wrap("fill-context", fillContextCommand));
|
|
4355
4545
|
var graph = addGlobalOptions(program.command("graph").description("\u7BA1\u7406\u53EF\u9009\u7684 GitNexus \u4EE3\u7801\u56FE\u652F\u6301"));
|
|
@@ -4432,7 +4622,7 @@ function renderModelPolicyActionHint(policyMode, language) {
|
|
|
4432
4622
|
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";
|
|
4433
4623
|
}
|
|
4434
4624
|
async function warnIfContextPlaceholdersRemain(ctx) {
|
|
4435
|
-
if (["init", "update-context", "fill-context", "doctor"].includes(ctx.command)) {
|
|
4625
|
+
if (["init", "update", "update-context", "fill-context", "doctor"].includes(ctx.command)) {
|
|
4436
4626
|
return;
|
|
4437
4627
|
}
|
|
4438
4628
|
const count2 = await countAgentsLlmPlaceholders(ctx.projectRoot);
|