@andyqiu/codeforge 0.5.12 → 0.5.13
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/bin/codeforge.mjs +77 -32
- package/dist/index.js +32 -2
- package/package.json +1 -1
package/bin/codeforge.mjs
CHANGED
|
@@ -95,7 +95,7 @@ function parseArgs(argv) {
|
|
|
95
95
|
// ────────────────────────────────────────────────────────────────────
|
|
96
96
|
// opencode installer:薄壳,调现成的 install.ps1 / install.sh
|
|
97
97
|
// ────────────────────────────────────────────────────────────────────
|
|
98
|
-
function installOpencode({ scope, dryRun, extraArgs }) {
|
|
98
|
+
function installOpencode({ scope, dryRun, extraArgs, quiet = false }) {
|
|
99
99
|
const isWin = process.platform === "win32"
|
|
100
100
|
const script = isWin ? path.join(REPO_ROOT, "install.ps1") : path.join(REPO_ROOT, "install.sh")
|
|
101
101
|
if (!existsSync(script)) {
|
|
@@ -116,7 +116,11 @@ function installOpencode({ scope, dryRun, extraArgs }) {
|
|
|
116
116
|
}
|
|
117
117
|
const all = [...baseArgs, ...flagArgs, ...(extraArgs ?? [])]
|
|
118
118
|
log(`opencode: ${cmd} ${all.join(" ")}`)
|
|
119
|
-
const r = spawnSync(cmd, all, { stdio: "inherit", cwd: REPO_ROOT })
|
|
119
|
+
const r = spawnSync(cmd, all, { stdio: quiet ? "pipe" : "inherit", cwd: REPO_ROOT })
|
|
120
|
+
if (quiet && r.status !== 0) {
|
|
121
|
+
if (r.stderr) process.stderr.write(r.stderr)
|
|
122
|
+
if (r.stdout) process.stderr.write(r.stdout)
|
|
123
|
+
}
|
|
120
124
|
return r.status ?? 1
|
|
121
125
|
}
|
|
122
126
|
|
|
@@ -288,46 +292,86 @@ function cmdRollback(args) {
|
|
|
288
292
|
// ────────────────────────────────────────────────────────────────────
|
|
289
293
|
// 子命令:upgrade —— 升级到 npm latest 并重新 install --global
|
|
290
294
|
// ────────────────────────────────────────────────────────────────────
|
|
291
|
-
|
|
295
|
+
|
|
296
|
+
async function cmdUpgrade(args) {
|
|
292
297
|
const dryRun = !!args.flags["dry-run"] || !!args.flags.dryRun
|
|
293
298
|
const currentVersion = getVersion()
|
|
294
299
|
|
|
295
|
-
log(
|
|
296
|
-
log(` 当前版本 : ${currentVersion}`)
|
|
297
|
-
log(` dry-run : ${dryRun}`)
|
|
298
|
-
hr()
|
|
300
|
+
log(`检查版本...`)
|
|
299
301
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
302
|
+
// 查询 npm registry 最新版本
|
|
303
|
+
let latestVersion = null
|
|
304
|
+
try {
|
|
305
|
+
latestVersion = await new Promise((resolve) => {
|
|
306
|
+
import("node:https").then((mod) => {
|
|
307
|
+
const https = mod.default ?? mod // node:https ESM 无 default export
|
|
308
|
+
const options = {
|
|
309
|
+
hostname: "registry.npmjs.org",
|
|
310
|
+
path: "/@andyqiu%2Fcodeforge/latest",
|
|
311
|
+
method: "GET",
|
|
312
|
+
headers: { "User-Agent": "codeforge-cli" },
|
|
313
|
+
timeout: 5000,
|
|
314
|
+
}
|
|
315
|
+
const req = https.get(options, (res) => {
|
|
316
|
+
let data = ""
|
|
317
|
+
res.on("data", (chunk) => { data += chunk })
|
|
318
|
+
res.on("end", () => {
|
|
319
|
+
try { resolve(JSON.parse(data).version ?? null) } catch { resolve(null) }
|
|
320
|
+
})
|
|
321
|
+
})
|
|
322
|
+
req.on("timeout", () => { req.destroy(); resolve(null) })
|
|
323
|
+
req.on("error", () => resolve(null))
|
|
324
|
+
}).catch(() => resolve(null))
|
|
325
|
+
})
|
|
326
|
+
} catch {
|
|
327
|
+
latestVersion = null
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (latestVersion === null) {
|
|
331
|
+
warn(`版本检查失败,继续升级流程`)
|
|
332
|
+
} else if (latestVersion === currentVersion) {
|
|
333
|
+
ok(`当前已是最新版本 v${currentVersion},无需升级`)
|
|
334
|
+
return 0
|
|
311
335
|
} else {
|
|
312
|
-
log(
|
|
336
|
+
log(`当前版本:${currentVersion} → 最新版本:${latestVersion}`)
|
|
313
337
|
}
|
|
314
338
|
|
|
315
339
|
hr()
|
|
316
|
-
log(
|
|
340
|
+
log(`正在升级...`)
|
|
317
341
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
342
|
+
const npmCmd = "npm"
|
|
343
|
+
// 有明确版本号时用精确版本,绕过 @latest dist-tag 缓存
|
|
344
|
+
const installTarget = latestVersion
|
|
345
|
+
? `@andyqiu/codeforge@${latestVersion}`
|
|
346
|
+
: "@andyqiu/codeforge@latest"
|
|
347
|
+
const npmArgs = ["install", "-g", installTarget]
|
|
348
|
+
|
|
349
|
+
if (dryRun) {
|
|
350
|
+
const displayNew = latestVersion ?? "未知(版本查询失败)"
|
|
351
|
+
ok(`[dry-run] 演示升级:${currentVersion} → ${displayNew}`)
|
|
352
|
+
ok(`[dry-run] 实际执行时将自动重启生效提示`)
|
|
353
|
+
return 0
|
|
327
354
|
}
|
|
328
355
|
|
|
329
|
-
|
|
330
|
-
|
|
356
|
+
const r = spawnSync(npmCmd, npmArgs, { stdio: "pipe", shell: true })
|
|
357
|
+
if (r.status !== 0) {
|
|
358
|
+
if (r.stderr) process.stderr.write(r.stderr)
|
|
359
|
+
if (r.stdout) process.stderr.write(r.stdout)
|
|
360
|
+
err(`npm install 失败 (exit=${r.status ?? 1})`)
|
|
361
|
+
err(`提示:可手动跑 npm install -g ${installTarget}`)
|
|
362
|
+
return 1
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const skipBuildFlag = process.platform === "win32" ? "-SkipBuild" : "--skip-build"
|
|
366
|
+
const code = installOpencode({ scope: "global", dryRun: false, extraArgs: [skipBuildFlag], quiet: true })
|
|
367
|
+
if (code !== 0) {
|
|
368
|
+
err(`install --global 失败 (exit=${code})`)
|
|
369
|
+
return 1
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// 升级后读取新版本(npm install 成功后本地 package.json 已更新)
|
|
373
|
+
const newVersion = latestVersion ?? getVersion()
|
|
374
|
+
ok(`升级完成:${currentVersion} → ${newVersion}`)
|
|
331
375
|
ok(`重启 opencode 后新版本生效`)
|
|
332
376
|
return 0
|
|
333
377
|
}
|
|
@@ -437,7 +481,7 @@ function cmdHelp() {
|
|
|
437
481
|
codeforge list
|
|
438
482
|
codeforge version
|
|
439
483
|
codeforge rollback [--target=<path>] [--dry-run] # 恢复最近 backup(auto_install 失败救场)
|
|
440
|
-
codeforge upgrade
|
|
484
|
+
codeforge upgrade|update [--dry-run] # 升级到 npm latest 并重新 install --global
|
|
441
485
|
codeforge runtime where [<path>] # 打印当前项目的全局运行时目录
|
|
442
486
|
codeforge adr-init [--force] [--dry-run] [--write-prepare] [--no-pre-push]
|
|
443
487
|
# 把 ADR 校验体系(hooks + scripts + 模板)下发到当前 git 项目
|
|
@@ -502,6 +546,7 @@ async function main() {
|
|
|
502
546
|
case "rollback":
|
|
503
547
|
return cmdRollback(args)
|
|
504
548
|
case "upgrade":
|
|
549
|
+
case "update":
|
|
505
550
|
return cmdUpgrade(args)
|
|
506
551
|
case "runtime":
|
|
507
552
|
return cmdRuntime(args)
|
package/dist/index.js
CHANGED
|
@@ -21774,7 +21774,7 @@ import * as zlib from "node:zlib";
|
|
|
21774
21774
|
// lib/version-injected.ts
|
|
21775
21775
|
function getInjectedVersion() {
|
|
21776
21776
|
try {
|
|
21777
|
-
const v = "0.5.
|
|
21777
|
+
const v = "0.5.13";
|
|
21778
21778
|
if (typeof v === "string" && /^\d+\.\d+\.\d+/.test(v)) {
|
|
21779
21779
|
return v;
|
|
21780
21780
|
}
|
|
@@ -23082,8 +23082,22 @@ var _touchCache = new Map;
|
|
|
23082
23082
|
var CLASS_B_CALLER_WHITELIST = new Set([
|
|
23083
23083
|
"codeforge",
|
|
23084
23084
|
"reviewer",
|
|
23085
|
+
"reviewer-lite",
|
|
23085
23086
|
"general"
|
|
23086
23087
|
]);
|
|
23088
|
+
var CODEFORGE_WORKTREE_DIR_NAME = path27.join(".git", "codeforge-worktrees");
|
|
23089
|
+
function worktreesRoot(mainRoot) {
|
|
23090
|
+
return path27.join(mainRoot, CODEFORGE_WORKTREE_DIR_NAME);
|
|
23091
|
+
}
|
|
23092
|
+
function isInsideAnyWorktreeDir(absPath, mainRoot) {
|
|
23093
|
+
if (!path27.isAbsolute(absPath))
|
|
23094
|
+
return false;
|
|
23095
|
+
const root = worktreesRoot(mainRoot);
|
|
23096
|
+
if (absPath === root)
|
|
23097
|
+
return false;
|
|
23098
|
+
const prefix = root.endsWith(path27.sep) ? root : root + path27.sep;
|
|
23099
|
+
return absPath.startsWith(prefix);
|
|
23100
|
+
}
|
|
23087
23101
|
function rewritePath(value, mainRoot, worktreeRoot) {
|
|
23088
23102
|
if (!value)
|
|
23089
23103
|
return null;
|
|
@@ -23092,6 +23106,9 @@ function rewritePath(value, mainRoot, worktreeRoot) {
|
|
|
23092
23106
|
if (resolved === worktreeRoot || resolved.startsWith(wtPrefix2)) {
|
|
23093
23107
|
return null;
|
|
23094
23108
|
}
|
|
23109
|
+
if (isInsideAnyWorktreeDir(resolved, mainRoot)) {
|
|
23110
|
+
return null;
|
|
23111
|
+
}
|
|
23095
23112
|
if (resolved === mainRoot)
|
|
23096
23113
|
return worktreeRoot;
|
|
23097
23114
|
const prefix = mainRoot.endsWith("/") ? mainRoot : mainRoot + "/";
|
|
@@ -23121,7 +23138,20 @@ function commandContainsMainRootExcludingWorktree(command, mainRoot, worktreePat
|
|
|
23121
23138
|
return true;
|
|
23122
23139
|
}
|
|
23123
23140
|
}
|
|
23124
|
-
const
|
|
23141
|
+
const wtRoot = worktreesRoot(mainRoot);
|
|
23142
|
+
const wtRootPrefix = wtRoot + path27.sep;
|
|
23143
|
+
const escapedWtRootPrefix = escapeRegex2(wtRootPrefix);
|
|
23144
|
+
const wtPathPattern = escapedWtRootPrefix + `[^\\s'"\\x60)]*`;
|
|
23145
|
+
const allWorktreePathsReForEscape = new RegExp(wtPathPattern, "g");
|
|
23146
|
+
const allWorktreePathsReForReplace = new RegExp(wtPathPattern, "g");
|
|
23147
|
+
for (const match of command.matchAll(allWorktreePathsReForEscape)) {
|
|
23148
|
+
const matchedPath = match[0];
|
|
23149
|
+
const tail = matchedPath.slice(wtRootPrefix.length);
|
|
23150
|
+
if (/(?:^|[/\\])\.\.(?:[/\\]|$)/.test(tail)) {
|
|
23151
|
+
return true;
|
|
23152
|
+
}
|
|
23153
|
+
}
|
|
23154
|
+
const sanitized = command.split(worktreePath).join("").replace(allWorktreePathsReForReplace, "");
|
|
23125
23155
|
return commandContainsMainRoot(sanitized, mainRoot);
|
|
23126
23156
|
}
|
|
23127
23157
|
function detectBashWriteIntent(command, mainRoot) {
|