@andyqiu/codeforge 0.8.16 → 0.8.18
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/index.js +125 -16
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22873,7 +22873,7 @@ class ApprovalStore {
|
|
|
22873
22873
|
await fs6.writeFile(file2, JSON.stringify(meta, null, 2), "utf8");
|
|
22874
22874
|
return file2;
|
|
22875
22875
|
}
|
|
22876
|
-
async
|
|
22876
|
+
async getLatestRaw(pendingId) {
|
|
22877
22877
|
const dir = path8.join(this.base, pendingId);
|
|
22878
22878
|
const files = await this.safeReaddir(dir);
|
|
22879
22879
|
const metaFiles = files.filter((f) => /^meta(?:-\d+)?\.json$/.test(f));
|
|
@@ -22890,6 +22890,33 @@ class ApprovalStore {
|
|
|
22890
22890
|
all.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
22891
22891
|
return all[0];
|
|
22892
22892
|
}
|
|
22893
|
+
async getLatest(pendingId) {
|
|
22894
|
+
const raw = await this.getLatestRaw(pendingId);
|
|
22895
|
+
if (!raw)
|
|
22896
|
+
return;
|
|
22897
|
+
if (raw.invalidatedAt)
|
|
22898
|
+
return;
|
|
22899
|
+
return raw;
|
|
22900
|
+
}
|
|
22901
|
+
async invalidateLatest(pendingId, reason) {
|
|
22902
|
+
const raw = await this.getLatestRaw(pendingId);
|
|
22903
|
+
if (!raw)
|
|
22904
|
+
return { ok: false, skipped: "no-record" };
|
|
22905
|
+
if (raw.invalidatedAt)
|
|
22906
|
+
return { ok: false, skipped: "already-invalidated" };
|
|
22907
|
+
const invalidatedRecord = {
|
|
22908
|
+
...raw,
|
|
22909
|
+
invalidatedAt: new Date().toISOString(),
|
|
22910
|
+
invalidatedReason: reason,
|
|
22911
|
+
createdAt: new Date().toISOString()
|
|
22912
|
+
};
|
|
22913
|
+
const dir = path8.join(this.base, pendingId);
|
|
22914
|
+
await fs6.mkdir(dir, { recursive: true });
|
|
22915
|
+
const filename = await this.pickRecordFilename(dir);
|
|
22916
|
+
const file2 = path8.join(dir, filename);
|
|
22917
|
+
await fs6.writeFile(file2, JSON.stringify(invalidatedRecord, null, 2), "utf8");
|
|
22918
|
+
return { ok: true, file: file2 };
|
|
22919
|
+
}
|
|
22893
22920
|
async findAliasApprovals(ownerSessionId) {
|
|
22894
22921
|
if (!ownerSessionId)
|
|
22895
22922
|
return [];
|
|
@@ -28116,6 +28143,35 @@ async function sendParentNotice(client, sessionID, text, opts = {}) {
|
|
|
28116
28143
|
|
|
28117
28144
|
// lib/spawner-production.ts
|
|
28118
28145
|
init_decision_parser();
|
|
28146
|
+
|
|
28147
|
+
// lib/approval-invalidation.ts
|
|
28148
|
+
async function invalidateLatestIfStale(store, pendingIds, reason, log5) {
|
|
28149
|
+
for (const pendingId of pendingIds) {
|
|
28150
|
+
try {
|
|
28151
|
+
const result = await store.invalidateLatest(pendingId, reason);
|
|
28152
|
+
if (result.ok) {
|
|
28153
|
+
log5?.("info", `[approval-invalidation] stale approval 已作废`, {
|
|
28154
|
+
pendingId,
|
|
28155
|
+
reason,
|
|
28156
|
+
file: result.file
|
|
28157
|
+
});
|
|
28158
|
+
} else {
|
|
28159
|
+
log5?.("info", `[approval-invalidation] 无需作废`, {
|
|
28160
|
+
pendingId,
|
|
28161
|
+
skipped: result.skipped
|
|
28162
|
+
});
|
|
28163
|
+
}
|
|
28164
|
+
} catch (err) {
|
|
28165
|
+
log5?.("warn", `[approval-invalidation] 作废失败(fail-open),stale 可能残留`, {
|
|
28166
|
+
pendingId,
|
|
28167
|
+
reason,
|
|
28168
|
+
err: err instanceof Error ? err.message : String(err)
|
|
28169
|
+
});
|
|
28170
|
+
}
|
|
28171
|
+
}
|
|
28172
|
+
}
|
|
28173
|
+
|
|
28174
|
+
// lib/spawner-production.ts
|
|
28119
28175
|
class ProductionSpawner {
|
|
28120
28176
|
opts;
|
|
28121
28177
|
constructor(opts) {
|
|
@@ -28153,23 +28209,34 @@ class ProductionSpawner {
|
|
|
28153
28209
|
} catch (err) {
|
|
28154
28210
|
throw err;
|
|
28155
28211
|
}
|
|
28212
|
+
let result;
|
|
28156
28213
|
if (r.llmError) {
|
|
28157
|
-
|
|
28214
|
+
result = {
|
|
28158
28215
|
decision: "REQUEST_CHANGES",
|
|
28159
28216
|
summary: `reviewer LLM error: ${describe4(r.llmError)}`
|
|
28160
28217
|
};
|
|
28161
|
-
}
|
|
28162
|
-
|
|
28163
|
-
|
|
28164
|
-
|
|
28165
|
-
|
|
28166
|
-
|
|
28218
|
+
} else {
|
|
28219
|
+
const parsed = parseDecision(r.text);
|
|
28220
|
+
if (parsed.token === null) {
|
|
28221
|
+
result = {
|
|
28222
|
+
decision: "REQUEST_CHANGES",
|
|
28223
|
+
summary: `decision parse failed: ${parsed.reason}
|
|
28167
28224
|
|
|
28168
28225
|
---
|
|
28169
28226
|
${r.text.slice(0, 800)}`
|
|
28170
|
-
|
|
28227
|
+
};
|
|
28228
|
+
} else {
|
|
28229
|
+
result = { decision: parsed.token, summary: r.text };
|
|
28230
|
+
}
|
|
28171
28231
|
}
|
|
28172
|
-
|
|
28232
|
+
if (result.decision !== "APPROVE" && ownerRoot) {
|
|
28233
|
+
const pendingIds = [`session:${ownerSessionId}`];
|
|
28234
|
+
if (args.sessionId && args.sessionId !== ownerSessionId) {
|
|
28235
|
+
pendingIds.push(`session:${args.sessionId}`);
|
|
28236
|
+
}
|
|
28237
|
+
await invalidateLatestIfStale(ApprovalStore.forProject(ownerRoot), pendingIds, `spawnReviewer round ${args.round}: decision=${result.decision}, invalidating stale approval`, this.opts.log).catch(() => {});
|
|
28238
|
+
}
|
|
28239
|
+
return result;
|
|
28173
28240
|
}
|
|
28174
28241
|
async spawnCoder(args) {
|
|
28175
28242
|
const prompt = buildCoderPrompt(args);
|
|
@@ -32690,7 +32757,7 @@ import * as https from "node:https";
|
|
|
32690
32757
|
// lib/version-injected.ts
|
|
32691
32758
|
function getInjectedVersion() {
|
|
32692
32759
|
try {
|
|
32693
|
-
const v = "0.8.
|
|
32760
|
+
const v = "0.8.18";
|
|
32694
32761
|
if (typeof v === "string" && /^\d+\.\d+\.\d+/.test(v)) {
|
|
32695
32762
|
return v;
|
|
32696
32763
|
}
|
|
@@ -32815,7 +32882,7 @@ function defaultHttpFetcher(url3, timeoutMs) {
|
|
|
32815
32882
|
|
|
32816
32883
|
// plugins/update-checker.ts
|
|
32817
32884
|
var PLUGIN_NAME19 = "update-checker";
|
|
32818
|
-
var PLUGIN_VERSION = "
|
|
32885
|
+
var PLUGIN_VERSION = "4.0.0";
|
|
32819
32886
|
var _updateCheckStarted = false;
|
|
32820
32887
|
function getCacheFile() {
|
|
32821
32888
|
return join27(process.env["CODEFORGE_CACHE_DIR"] ?? join27(homedir9(), ".cache", "codeforge"), "update-check.json");
|
|
@@ -32903,12 +32970,32 @@ function spawnAsync(cmd, args, opts = {}) {
|
|
|
32903
32970
|
}
|
|
32904
32971
|
async function resolveNodeBin() {
|
|
32905
32972
|
const w = process.platform === "win32";
|
|
32973
|
+
if (w) {
|
|
32974
|
+
try {
|
|
32975
|
+
const r = await spawnAsync("where", ["node.exe"], { timeout: 3000, shell: true });
|
|
32976
|
+
if (r.status === 0 && r.stdout.trim())
|
|
32977
|
+
return r.stdout.trim().split(/\r?\n/)[0].trim();
|
|
32978
|
+
} catch {}
|
|
32979
|
+
try {
|
|
32980
|
+
const r = await spawnAsync("where", ["node"], { timeout: 3000, shell: true });
|
|
32981
|
+
if (r.status === 0 && r.stdout.trim())
|
|
32982
|
+
return r.stdout.trim().split(/\r?\n/)[0].trim();
|
|
32983
|
+
} catch {}
|
|
32984
|
+
for (const c of ["C:\\Program Files\\nodejs\\node.exe", "C:\\Program Files (x86)\\nodejs\\node.exe"]) {
|
|
32985
|
+
try {
|
|
32986
|
+
const r = await spawnAsync(c, ["--version"], { timeout: 2000, shell: false });
|
|
32987
|
+
if (r.status === 0)
|
|
32988
|
+
return c;
|
|
32989
|
+
} catch {}
|
|
32990
|
+
}
|
|
32991
|
+
return process.execPath;
|
|
32992
|
+
}
|
|
32906
32993
|
try {
|
|
32907
|
-
const r = await spawnAsync(
|
|
32994
|
+
const r = await spawnAsync("which", ["node"], { timeout: 3000 });
|
|
32908
32995
|
if (r.status === 0 && r.stdout.trim())
|
|
32909
32996
|
return r.stdout.trim().split(/\r?\n/)[0].trim();
|
|
32910
32997
|
} catch {}
|
|
32911
|
-
for (const c of
|
|
32998
|
+
for (const c of ["/usr/local/bin/node", "/usr/bin/node", "/opt/homebrew/bin/node", "/opt/homebrew/opt/node/bin/node"]) {
|
|
32912
32999
|
try {
|
|
32913
33000
|
const r = await spawnAsync(c, ["--version"], { timeout: 2000 });
|
|
32914
33001
|
if (r.status === 0)
|
|
@@ -32919,12 +33006,34 @@ async function resolveNodeBin() {
|
|
|
32919
33006
|
}
|
|
32920
33007
|
async function resolveNpmBin() {
|
|
32921
33008
|
const w = process.platform === "win32";
|
|
33009
|
+
if (w) {
|
|
33010
|
+
try {
|
|
33011
|
+
const r = await spawnAsync("where", ["npm.cmd"], { timeout: 3000, shell: true });
|
|
33012
|
+
if (r.status === 0 && r.stdout.trim())
|
|
33013
|
+
return r.stdout.trim().split(/\r?\n/)[0].trim();
|
|
33014
|
+
} catch {}
|
|
33015
|
+
try {
|
|
33016
|
+
const r = await spawnAsync("where", ["npm"], { timeout: 3000, shell: true });
|
|
33017
|
+
if (r.status === 0 && r.stdout.trim()) {
|
|
33018
|
+
const p = r.stdout.trim().split(/\r?\n/)[0].trim();
|
|
33019
|
+
return p.replace(/\.cmd$/i, "") + ".cmd";
|
|
33020
|
+
}
|
|
33021
|
+
} catch {}
|
|
33022
|
+
for (const c of ["C:\\Program Files\\nodejs\\npm.cmd", "C:\\Program Files (x86)\\nodejs\\npm.cmd"]) {
|
|
33023
|
+
try {
|
|
33024
|
+
const r = await spawnAsync(c, ["--version"], { timeout: 2000, shell: true });
|
|
33025
|
+
if (r.status === 0)
|
|
33026
|
+
return c;
|
|
33027
|
+
} catch {}
|
|
33028
|
+
}
|
|
33029
|
+
return "npm.cmd";
|
|
33030
|
+
}
|
|
32922
33031
|
try {
|
|
32923
|
-
const r = await spawnAsync(
|
|
33032
|
+
const r = await spawnAsync("which", ["npm"], { timeout: 3000 });
|
|
32924
33033
|
if (r.status === 0 && r.stdout.trim())
|
|
32925
33034
|
return r.stdout.trim().split(/\r?\n/)[0].trim();
|
|
32926
33035
|
} catch {}
|
|
32927
|
-
for (const c of
|
|
33036
|
+
for (const c of ["/usr/local/bin/npm", "/usr/bin/npm", "/opt/homebrew/bin/npm"]) {
|
|
32928
33037
|
try {
|
|
32929
33038
|
const r = await spawnAsync(c, ["--version"], { timeout: 2000 });
|
|
32930
33039
|
if (r.status === 0)
|