@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 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
- function cmdUpgrade(args) {
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(`CodeForge upgrade`)
296
- log(` 当前版本 : ${currentVersion}`)
297
- log(` dry-run : ${dryRun}`)
298
- hr()
300
+ log(`检查版本...`)
299
301
 
300
- const npmCmd = "npm"
301
- const npmArgs = ["install", "-g", "@andyqiu/codeforge@latest"]
302
- log(`步骤 1/2:${npmCmd} ${npmArgs.join(" ")}`)
303
-
304
- if (!dryRun) {
305
- const r = spawnSync(npmCmd, npmArgs, { stdio: "inherit", shell: true })
306
- if (r.status !== 0) {
307
- err(`npm install 失败 (exit=${r.status ?? 1})`)
308
- err(`提示:可手动跑 npm install -g @andyqiu/codeforge@latest`)
309
- return 1
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(`[dry-run] 跳过 npm install`)
336
+ log(`当前版本:${currentVersion} 最新版本:${latestVersion}`)
313
337
  }
314
338
 
315
339
  hr()
316
- log(`步骤 2/2:codeforge install --global`)
340
+ log(`正在升级...`)
317
341
 
318
- if (!dryRun) {
319
- const skipBuildFlag = process.platform === "win32" ? "-SkipBuild" : "--skip-build"
320
- const code = installOpencode({ scope: "global", dryRun: false, extraArgs: [skipBuildFlag] })
321
- if (code !== 0) {
322
- err(`install --global 失败 (exit=${code})`)
323
- return 1
324
- }
325
- } else {
326
- log(`[dry-run] 跳过 install --global`)
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
- hr()
330
- ok(`升级完成!运行 codeforge -v 查看新版本`)
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 [--dry-run] # 升级到 npm latest 并重新 install --global
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.12";
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 sanitized = command.split(worktreePath).join("");
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andyqiu/codeforge",
3
- "version": "0.5.12",
3
+ "version": "0.5.13",
4
4
  "description": "CodeForge — opencode 的零侵入扩展包",
5
5
  "type": "module",
6
6
  "private": false,