prreviewbuddy 0.80.3 → 0.81.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/CHANGELOG.md +19 -0
- package/README.md +3 -4
- package/dist/{delete_review-CYiIfV5A.js → delete_review-CFVFygqb.js} +139 -13
- package/dist/main.js +21 -1
- package/dist/server.js +22 -10
- package/package.json +2 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.81.0
|
|
4
|
+
|
|
5
|
+
**Gemini CLI is turned off.** PR Review Buddy no longer runs reviews, updates, Buddy AI answers,
|
|
6
|
+
KISS reviews or repository maps with Gemini CLI. Google has ended Gemini CLI access for individual
|
|
7
|
+
accounts, and current Gemini CLI releases ignore the settings that kept it read-only, so a run could
|
|
8
|
+
no longer be guaranteed to leave your code alone. It is gone from every agent list. Naming it with
|
|
9
|
+
`--agent gemini`, or having it saved as your default, stops before anything starts and says to use
|
|
10
|
+
Claude Code or Codex instead.
|
|
11
|
+
|
|
12
|
+
Reviews Gemini made are kept as they are, still labelled Gemini CLI. They can't be updated or asked
|
|
13
|
+
about, because both continue with the agent that made the review. To carry one on, analyse it again
|
|
14
|
+
with `--reanalyse --agent claude` or `--agent codex`; the Gemini analysis stays as the one it
|
|
15
|
+
replaced. A Gemini review that was queued or stopped is refused before its checkout is made, without
|
|
16
|
+
a Retry button. If Settings has Gemini CLI saved as the default, it shows that and asks you to
|
|
17
|
+
choose another.
|
|
18
|
+
|
|
19
|
+
The Gemini provider for Buddy AI in the browser extension is unaffected: it calls Google's API with
|
|
20
|
+
your own key and never runs Gemini CLI.
|
|
21
|
+
|
|
3
22
|
## 0.80.3
|
|
4
23
|
|
|
5
24
|
**Runs name the agent that did the work.** Updating a review, and the checkout Buddy AI answers
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
A local review workspace that helps you understand code changes before you approve them.
|
|
6
6
|
|
|
7
|
-
Have Claude Code
|
|
7
|
+
Have Claude Code or Codex analyse a branch or pull request, then explore what it
|
|
8
8
|
found, the evidence behind it and your own follow-up questions in your browser.
|
|
9
9
|
|
|
10
10
|

|
|
@@ -69,9 +69,8 @@ being reviewed, so your working tree is never touched and you can carry on worki
|
|
|
69
69
|
## Local by design
|
|
70
70
|
|
|
71
71
|
PR Review Buddy uses a coding agent already installed on your machine, and that agent's existing
|
|
72
|
-
authentication: [Claude Code](https://claude.com/claude-code)
|
|
73
|
-
[Codex CLI](https://developers.openai.com/codex/cli)
|
|
74
|
-
[Gemini CLI](https://github.com/google-gemini/gemini-cli). There is no PR Review Buddy account and no
|
|
72
|
+
authentication: [Claude Code](https://claude.com/claude-code) or
|
|
73
|
+
[Codex CLI](https://developers.openai.com/codex/cli). There is no PR Review Buddy account and no
|
|
75
74
|
model API key.
|
|
76
75
|
|
|
77
76
|
Your code goes to the agent you chose, exactly as if you had run it yourself. It does not pass
|
|
@@ -1274,22 +1274,115 @@ var AGENTS = {
|
|
|
1274
1274
|
[GEMINI_AGENT_ID]: geminiAgent,
|
|
1275
1275
|
[CODEX_AGENT_ID]: codexAgent
|
|
1276
1276
|
};
|
|
1277
|
+
/**
|
|
1278
|
+
* Adapters this build ships and will not run, each with the sentence a person is shown instead.
|
|
1279
|
+
*
|
|
1280
|
+
* A parked id is still known: reviews it made keep their name and their history, telemetry still
|
|
1281
|
+
* recognises it, and a job queued under it is refused by name rather than treated as an agent this
|
|
1282
|
+
* build has never heard of. What it loses is everything that would start it. `agentById` throws
|
|
1283
|
+
* before an adapter is handed out, so no run site can reach one, and every list a person chooses
|
|
1284
|
+
* from is built from `AGENT_IDS`, which leaves it out.
|
|
1285
|
+
*
|
|
1286
|
+
* Gemini CLI, since 0.81.0. Its read-only boundary is not applied on current releases (the system
|
|
1287
|
+
* settings file that carried it is skipped unless root owns it), and Google has ended Gemini CLI
|
|
1288
|
+
* for individual accounts. `index.test.ts` holds a tripwire against unparking it before the adapter
|
|
1289
|
+
* enforces its boundary again.
|
|
1290
|
+
*/
|
|
1291
|
+
var PARKED = { [GEMINI_AGENT_ID]: "Gemini CLI is turned off in this version of PR Review Buddy. Google has ended Gemini CLI access for individual accounts, and its read-only mode can't be guaranteed on current versions." };
|
|
1277
1292
|
var DEFAULT_AGENT_ID = CLAUDE_AGENT_ID;
|
|
1278
1293
|
/**
|
|
1279
1294
|
* Every agent this build can run, for a surface that has to say which ones those are.
|
|
1280
1295
|
*
|
|
1281
1296
|
* Derived from the registry rather than written out, so a second adapter appears in the sentence a
|
|
1282
|
-
* user reads by being registered, and nobody has to remember a list in another package.
|
|
1297
|
+
* user reads by being registered, and nobody has to remember a list in another package. Parked
|
|
1298
|
+
* adapters are left out, which is how they leave every picker, listing and help sentence at once.
|
|
1299
|
+
*/
|
|
1300
|
+
var AGENT_IDS = Object.keys(AGENTS).filter((id) => !(id in PARKED));
|
|
1301
|
+
/**
|
|
1302
|
+
* Whether a string names an agent this build ships, answered by the registry rather than a list.
|
|
1303
|
+
*
|
|
1304
|
+
* True for a parked agent too. This answers "do we know this id", which is what a stored review, a
|
|
1305
|
+
* job record and telemetry need; "can it run" is `AGENT_IDS` and `agentById`.
|
|
1283
1306
|
*/
|
|
1284
|
-
var AGENT_IDS = Object.keys(AGENTS);
|
|
1285
|
-
/** Whether a string names an agent this build ships, answered by the registry rather than a list. */
|
|
1286
1307
|
function isAgentId(value) {
|
|
1287
1308
|
return value !== void 0 && value in AGENTS;
|
|
1288
1309
|
}
|
|
1310
|
+
/**
|
|
1311
|
+
* Why this agent will not run in this build, or undefined when nothing stops it here.
|
|
1312
|
+
*
|
|
1313
|
+
* For a surface that has to tell a person something more useful than "unknown agent" when they
|
|
1314
|
+
* name one that is parked.
|
|
1315
|
+
*/
|
|
1316
|
+
function parkedReason(id) {
|
|
1317
|
+
if (id === void 0 || !Object.hasOwn(PARKED, id)) return void 0;
|
|
1318
|
+
return `${PARKED[id]} Use ${runnableAgents().names} instead.`;
|
|
1319
|
+
}
|
|
1320
|
+
/**
|
|
1321
|
+
* The agents that can run, as a person reads them ("Claude Code or Codex") and as `--agent` takes
|
|
1322
|
+
* them ("`--agent claude` or `--agent codex`"), for a refusal that has to say what to do instead.
|
|
1323
|
+
*
|
|
1324
|
+
* Built from `AGENT_IDS` so no module outside this folder spells an agent out, and so the advice
|
|
1325
|
+
* stays true when an adapter is parked or added.
|
|
1326
|
+
*/
|
|
1327
|
+
function runnableAgents() {
|
|
1328
|
+
const ids = [...AGENT_IDS].sort();
|
|
1329
|
+
return {
|
|
1330
|
+
names: orList(ids.map((id) => AGENTS[id].displayName)),
|
|
1331
|
+
flags: orList(ids.map((id) => `\`--agent ${id}\``))
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
function orList(items) {
|
|
1335
|
+
if (items.length <= 1) return items[0] ?? "";
|
|
1336
|
+
return `${items.slice(0, -1).join(", ")} or ${items[items.length - 1]}`;
|
|
1337
|
+
}
|
|
1338
|
+
/**
|
|
1339
|
+
* A run was asked of a parked agent. An `AgentUnavailableError`, so every caller that already
|
|
1340
|
+
* answers "you have not got this agent" answers this with the parked sentence instead.
|
|
1341
|
+
*/
|
|
1342
|
+
var AgentParkedError = class extends AgentUnavailableError {
|
|
1343
|
+
agentId;
|
|
1344
|
+
constructor(agentId, reason) {
|
|
1345
|
+
super(reason);
|
|
1346
|
+
this.agentId = agentId;
|
|
1347
|
+
}
|
|
1348
|
+
};
|
|
1349
|
+
/**
|
|
1350
|
+
* Who an agent is, without the means to run it. For a parked agent, which `agentById` refuses, when
|
|
1351
|
+
* a surface has to name it: a refusal that says "Gemini CLI" rather than "gemini".
|
|
1352
|
+
*/
|
|
1353
|
+
function agentIdentityOf(id) {
|
|
1354
|
+
const { displayName, provider, modelSelectionHelp, setupNotes } = AGENTS[id];
|
|
1355
|
+
return {
|
|
1356
|
+
id,
|
|
1357
|
+
displayName,
|
|
1358
|
+
provider,
|
|
1359
|
+
...modelSelectionHelp ? { modelSelectionHelp } : {},
|
|
1360
|
+
...setupNotes ? { setupNotes } : {}
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* The environment a review made by this agent is pinned to, captured now.
|
|
1365
|
+
*
|
|
1366
|
+
* Works for a parked agent, because capturing starts nothing: it reads variables. A review made by
|
|
1367
|
+
* one still has a forge to watch and a conversation to re-read, under the account that made it, and
|
|
1368
|
+
* an agent run started from what this returns is refused at `agentFor` like any other.
|
|
1369
|
+
*/
|
|
1370
|
+
function captureEnvFor(id, source) {
|
|
1371
|
+
return AGENTS[id].captureEnv(source);
|
|
1372
|
+
}
|
|
1289
1373
|
function defaultAgent() {
|
|
1290
1374
|
return agentById(DEFAULT_AGENT_ID);
|
|
1291
1375
|
}
|
|
1376
|
+
/**
|
|
1377
|
+
* The adapter for this id, and the one way any run reaches one.
|
|
1378
|
+
*
|
|
1379
|
+
* A parked id throws here rather than handing out something that refuses later. Several callers
|
|
1380
|
+
* write before they run (a new job, a retired analysis, a KISS run), so a refusal at `run()` would
|
|
1381
|
+
* already have replaced what the reviewer was reading with a failure.
|
|
1382
|
+
*/
|
|
1292
1383
|
function agentById(id) {
|
|
1384
|
+
const reason = parkedReason(id);
|
|
1385
|
+
if (reason) throw new AgentParkedError(id, reason);
|
|
1293
1386
|
const agent = AGENTS[id];
|
|
1294
1387
|
if (!agent) throw new AgentUnavailableError(`This review was made with an agent called "${id}", which this version does not know how to run.`);
|
|
1295
1388
|
return agent;
|
|
@@ -1346,7 +1439,7 @@ function captureEnv(source) {
|
|
|
1346
1439
|
* against fakes that fail in ways no installed binary would.
|
|
1347
1440
|
*/
|
|
1348
1441
|
async function detectAgents() {
|
|
1349
|
-
return detectAgents$1(
|
|
1442
|
+
return detectAgents$1(AGENT_IDS.map((id) => AGENTS[id]));
|
|
1350
1443
|
}
|
|
1351
1444
|
//#endregion
|
|
1352
1445
|
//#region ../../packages/review-harness/src/workspace/store_root.ts
|
|
@@ -1724,7 +1817,7 @@ function countDiscussion(context) {
|
|
|
1724
1817
|
async function resolveAgent(request) {
|
|
1725
1818
|
if (request.flag) return named(request.flag, "flag");
|
|
1726
1819
|
const fromReview = request.review ? agentIdOf(request.review.session) : null;
|
|
1727
|
-
if (fromReview &&
|
|
1820
|
+
if (fromReview && isAgentId(fromReview)) return named(fromReview, "review");
|
|
1728
1821
|
const preferred = readAgentPreference();
|
|
1729
1822
|
if (preferred) return named(preferred, "preference");
|
|
1730
1823
|
const installed = (await detectAgents()).filter((agent) => agent.state === "installed");
|
|
@@ -1736,6 +1829,13 @@ async function resolveAgent(request) {
|
|
|
1736
1829
|
};
|
|
1737
1830
|
}
|
|
1738
1831
|
async function named(id, because) {
|
|
1832
|
+
const parked = parkedReason(id);
|
|
1833
|
+
if (parked && isAgentId(id)) return {
|
|
1834
|
+
kind: "unavailable",
|
|
1835
|
+
agent: agentIdentityOf(id),
|
|
1836
|
+
reason: parked,
|
|
1837
|
+
parked: true
|
|
1838
|
+
};
|
|
1739
1839
|
if (!AGENT_IDS.includes(id)) return {
|
|
1740
1840
|
kind: "unknown-id",
|
|
1741
1841
|
id
|
|
@@ -7177,7 +7277,7 @@ function advance(job, phase, progress) {
|
|
|
7177
7277
|
...phase === "done" ? { finishedAt: Date.now() } : {}
|
|
7178
7278
|
};
|
|
7179
7279
|
}
|
|
7180
|
-
function fail(job, message, kind, detail) {
|
|
7280
|
+
function fail(job, message, kind, detail, parked) {
|
|
7181
7281
|
return {
|
|
7182
7282
|
...job,
|
|
7183
7283
|
phase: "failed",
|
|
@@ -7185,7 +7285,8 @@ function fail(job, message, kind, detail) {
|
|
|
7185
7285
|
phase: job.phase,
|
|
7186
7286
|
message,
|
|
7187
7287
|
...detail && detail !== message ? { detail } : {},
|
|
7188
|
-
...kind ? { kind } : {}
|
|
7288
|
+
...kind ? { kind } : {},
|
|
7289
|
+
...parked ? { parked } : {}
|
|
7189
7290
|
},
|
|
7190
7291
|
updatedAt: Date.now(),
|
|
7191
7292
|
finishedAt: Date.now()
|
|
@@ -7212,11 +7313,11 @@ function fail(job, message, kind, detail) {
|
|
|
7212
7313
|
* last thing the agent said survives being failed. Only a driver whose own claim has gone is
|
|
7213
7314
|
* refused, so a job nobody holds -- a crashed driver's, a resumed run's -- is still failable.
|
|
7214
7315
|
*/
|
|
7215
|
-
function recordFailure(job, message, driver, kind, detail) {
|
|
7316
|
+
function recordFailure(job, message, driver, kind, detail, parked) {
|
|
7216
7317
|
const current = loadJob(job.id) ?? job;
|
|
7217
7318
|
const claim = liveClaim(job.id);
|
|
7218
7319
|
if (claim && claim.holder !== driver) return current;
|
|
7219
|
-
const failed = fail(current, message, kind, detail);
|
|
7320
|
+
const failed = fail(current, message, kind, detail, parked);
|
|
7220
7321
|
saveJob(failed);
|
|
7221
7322
|
return failed;
|
|
7222
7323
|
}
|
|
@@ -12970,7 +13071,7 @@ function agentEnvOf(workspace) {
|
|
|
12970
13071
|
const job = workspace.jobId ? loadJob(workspace.jobId) : null;
|
|
12971
13072
|
if (job?.env) return job.env;
|
|
12972
13073
|
const id = agentIdOf(workspace.session);
|
|
12973
|
-
return (
|
|
13074
|
+
return isAgentId(id) ? captureEnvFor(id) : defaultAgent().captureEnv();
|
|
12974
13075
|
}
|
|
12975
13076
|
//#endregion
|
|
12976
13077
|
//#region ../../packages/review-harness/src/domain/discussion/discussion_attribution.ts
|
|
@@ -16370,6 +16471,8 @@ async function drive(jobId, workspaceId, runners, driver, signal, source) {
|
|
|
16370
16471
|
saveJob(job);
|
|
16371
16472
|
try {
|
|
16372
16473
|
signal?.throwIfAborted();
|
|
16474
|
+
const parked = parkedReason(job.env.agentId);
|
|
16475
|
+
if (parked) throw new AgentParkedError(job.env.agentId, parked);
|
|
16373
16476
|
if (needs(from, "preparing")) {
|
|
16374
16477
|
job = update(job, "preparing", "Preparing an isolated checkout");
|
|
16375
16478
|
const path = await createWorktree({
|
|
@@ -16494,7 +16597,7 @@ async function drive(jobId, workspaceId, runners, driver, signal, source) {
|
|
|
16494
16597
|
}
|
|
16495
16598
|
const kind = error instanceof GuideRejected || error instanceof KissRejected ? "agent_output_invalid" : error instanceof AgentRunError ? error.kind : void 0;
|
|
16496
16599
|
const raw = message(error);
|
|
16497
|
-
job = recordFailure(job, explain(job, raw), driver, kind, raw);
|
|
16600
|
+
job = recordFailure(job, explain(job, raw), driver, kind, raw, error instanceof AgentParkedError ? true : void 0);
|
|
16498
16601
|
if (job.reviewType === "kiss") failCurrentKissRun(workspaceId, job, job.failure?.message ?? raw, kind, error instanceof KissRejected ? error.answer : void 0);
|
|
16499
16602
|
finished(job, workspaceId, startedAt, false, now);
|
|
16500
16603
|
announceJob(job);
|
|
@@ -17885,7 +17988,7 @@ async function recordKissRun(input) {
|
|
|
17885
17988
|
if (!workspace) throw new Error("No such review.");
|
|
17886
17989
|
const sha = reviewedCommit(workspace);
|
|
17887
17990
|
if (!sha) throw new Error("This review does not record which commit it describes, so KISS cannot run on it.");
|
|
17888
|
-
const agent =
|
|
17991
|
+
const agent = agentById(kissAgentId(workspace, input.agentId));
|
|
17889
17992
|
const sameAgent = !workspace.jobId || agent.id === agentIdOf(workspace.session);
|
|
17890
17993
|
const requestedModel = input.requestedModel ?? (sameAgent ? resolveModel({ review: workspace }) : null);
|
|
17891
17994
|
const started = await withReviewLock(workspace.id, () => {
|
|
@@ -17937,6 +18040,16 @@ async function recordKissRun(input) {
|
|
|
17937
18040
|
function startKissJob(input, runners = {}) {
|
|
17938
18041
|
return track(recordKissRun(input).then((job) => runJob(job.workspaceId, runners, "kiss")));
|
|
17939
18042
|
}
|
|
18043
|
+
/**
|
|
18044
|
+
* Which agent a KISS run of this review runs with: the one named, else the standard review's own,
|
|
18045
|
+
* else the default when there has been no standard review.
|
|
18046
|
+
*
|
|
18047
|
+
* Its own function so the page can refuse a run before answering. The route starts the run and
|
|
18048
|
+
* replies without waiting for it, so a refusal thrown inside the run never reached the page.
|
|
18049
|
+
*/
|
|
18050
|
+
function kissAgentId(workspace, agentId) {
|
|
18051
|
+
return agentId ?? (workspace.jobId ? agentIdOf(workspace.session) : DEFAULT_AGENT_ID);
|
|
18052
|
+
}
|
|
17940
18053
|
//#endregion
|
|
17941
18054
|
//#region ../../packages/review-harness/src/domain/ai_review/reconciliation.ts
|
|
17942
18055
|
/**
|
|
@@ -18829,6 +18942,17 @@ var RefreshUnavailableError = class extends Error {};
|
|
|
18829
18942
|
var FETCH_TIMEOUT_MS = 6e4;
|
|
18830
18943
|
/** Said wherever an update is asked of a commit review. One sentence, so both surfaces agree. */
|
|
18831
18944
|
var COMMIT_REVIEW_CANNOT_UPDATE = "This review is of one commit, and a commit cannot move, so there is nothing to bring it up to date with. To analyse the same commit again, reanalyse it instead.";
|
|
18945
|
+
/**
|
|
18946
|
+
* Why this review cannot be updated in this build, when the agent it would continue with is parked.
|
|
18947
|
+
*
|
|
18948
|
+
* Read from `agentEnvOf`, which is what the update's job would be pinned to, so this refuses
|
|
18949
|
+
* exactly the updates that would otherwise be refused at the run.
|
|
18950
|
+
*/
|
|
18951
|
+
function parkedUpdateRefusal(workspace) {
|
|
18952
|
+
const reason = parkedReason(agentEnvOf(workspace).agentId);
|
|
18953
|
+
if (!reason) return null;
|
|
18954
|
+
return `${reason} An update continues with the agent that made this review, so this one can't be brought up to date. To carry on with another agent, analyse it again with ${runnableAgents().names}.`;
|
|
18955
|
+
}
|
|
18832
18956
|
/** The installed agent's own answer, through the `agentFor` this module imports. */
|
|
18833
18957
|
var installedAgentVersion = (env) => agentVersionOf(agentFor(env), env);
|
|
18834
18958
|
/** What the notice says after a cancel, and what the terminal would print if it could cancel. */
|
|
@@ -18864,6 +18988,8 @@ async function updateReview(workspace, runners = {}) {
|
|
|
18864
18988
|
const startedAt = now();
|
|
18865
18989
|
const reviewedSha = workspace.session.metadata?.commitSha || null;
|
|
18866
18990
|
if (workspace.changeSet.targetType === "commit") return refuse(reviewedSha, false, COMMIT_REVIEW_CANNOT_UPDATE);
|
|
18991
|
+
const parked = parkedUpdateRefusal(workspace);
|
|
18992
|
+
if (parked) return refuse(reviewedSha, false, parked);
|
|
18867
18993
|
const held = await claimCheckoutJob(workspace, reviewedSha ?? "", {
|
|
18868
18994
|
purpose: "update",
|
|
18869
18995
|
...runners.source ? { source: runners.source } : {},
|
|
@@ -19753,4 +19879,4 @@ function lineageIds(id) {
|
|
|
19753
19879
|
return [.../* @__PURE__ */ new Set([id, ...lineage.map((review) => review.id)])];
|
|
19754
19880
|
}
|
|
19755
19881
|
//#endregion
|
|
19756
|
-
export {
|
|
19882
|
+
export { MIN_WORKSPACE_PORT as $, agentIdentityOf as $i, RUN_RECORD_RETENTION_MS as $n, readQueue as $r, markRead as $t, batchIdentity as A, WITHHELD_REASON as Ai, escapeHtml as An, presentedKissRunOf as Ar, loadArchitecture as At, bootstrapUrl as B, git as Bi, readMarker as Bn, activityAttributes as Br, ancestorsOf as Bt, RUN_KINDS as C, sourcePhrase as Ci, UNESTABLISHED_MOTIVATION as Cn, kissDecisionsOf as Cr, mapRuntimes as Ct, reportRun as D, extractJsonText as Di, renderMarkdown as Dn, matchingWorkspaceIds as Dr, formatDuration as Dt, endRun as E, asString$1 as Ei, GITHUB_MARKDOWN as En, loadWorkspace as Er, describeRuntimes as Et, activateQueued as F, isCommitReview as Fi, withReviewLock as Fn, summarise as Fr, storedScopes as Ft, serverEntryExists as G, clearAgentPreference as Gi, findExistingReview as Gn, lifecyclePill as Gr, subjectOf as Gt, ensureServer as H, resolveAgent as Hi, requestJobStop as Hn, isLifecycle as Hr, writeJsonAtomically as Ht, compactQueue as I, resolveBase as Ii, MANAGED_ROOT as In, touchWorkspace as Ir, trackedFiles as It, stopServer as J, CONFIG_PATH as Ji, followedBranch as Jn, sectionOf as Jr, createPrState as Jt, spawnServer as K, readAgentPreference as Ki, checkCodeFreshness as Kn, offersLifecycle as Kr, categoryOf as Kt, queueForReview as L, AmbiguousRefError as Li, createWorktree as Ln, workspaceRevision as Lr, ownersOf as Lt, parsePullRequestLink as M, resolveTarget as Mi, modelHelpLines as Mn, recentWorkspaces as Mr, readArchitecture as Mt, unsupportedReason as N, originRemote as Ni, ReviewBeingDeletedError as Nn, reviewedCommit as Nr, repositoryKey as Nt, stopRun as O, objectWithAnyOf as Oi, CODE_BLOCK_CLASS as On, mutateWorkspace as Or, ARCHITECTURE_DIR as Ot, runBatch as P, DetachedHeadError as Pi, isBusy as Pn, reviewedRepositories as Pr, storeArchitecture as Pt, MAX_WORKSPACE_PORT as Q, agentFor as Qi, fillFileUrlTemplate as Qn, queueStamp as Qr, markAllRead as Qt, settleQueue as R, shortNameOf as Ri, holdWorktree as Rn, workspaceStamps as Rr, QUOTE_LIMITS as Rt, track as S, reassessIn as Si, chatConversationSection as Sn, kissDecisionRefusal as Sr, waitingHistory as St, completeRun as T, followUpFindingId as Ti, hasAuthorContent as Tn, lineagePosition as Tr, RUNTIME_WORDS as Tt, readServerRecord as U, resolveModel as Ui, describeMovement as Un, lifecycleChip as Ur, announceJob as Ut, clearServerRecordOwnedBy as V, refExists as Vi, removeWorktree as Vn, activityLabel as Vr, isArchitectureId as Vt, reviewsUrl as W, agentIdOf as Wi, describeSubject as Wn, lifecycleItemLabel as Wr, branchOf as Wt, writeServerRecord as X, AGENT_IDS as Xi, fetchHead as Xn, queueAddMany as Xr, eventName as Xt, workspaceUrl as Y, STORE_ROOT as Yi, reviewedShaOf as Yn, queueAdd as Yr, createPrUpdate as Yt, DEFAULT_WORKSPACE_PORT as Z, agentById as Zi, forgeResolver as Zn, queueRemove as Zr, listNotifications as Zt, runningJobs as _, findingAssessment as _i, unforeseenFailure as _n, decideKissRecommendation as _r, telemetryUploadConsent as _t, wasBlocked as a, AgentUnavailableError as aa, resolvedByConversation as ai, removeNotification as an, loadJob as ar, observeReview as at, startKissJob as b, isGradeFor as bi, agentEnvOf as bn, indexKeptIds as br, PACKAGE_NAME as bt, RefreshUnavailableError as c, recommendationsOf as ci, unreadAround as cn, PHASES as cr, reanalyseReview as ct, mergeUpdateInto as d, isExplanationAction as di, existingPaths as dn, phasesFor as dr, append as dt, detectAgents as ea, doneVerb as ei, markReadForReview as en, allJobs as er, parseWorkspacePort as et, parkedUpdateRefusal as f, withExplanation as fi, ASK_REREAD_CEILING_MS as fn, progressSteps as fr, readEvents as ft, liveUpdateFor as g, currentGradeIn as gi, storedConversation as gn, CLAIM_LEASE_MS as gr, recordTelemetryUploadConsent as gt, UpdateAlreadyRunningError as h, assessmentLookup as hi, saveRefresh as hn, isClaimed as hr, deliver as ht, liveJobsFor as i, AgentCancelledError as ia, questionsOutstanding as ii, readStateOf as in, isTerminal as ir, failureOf as it, extractPullRequestLinks as j, kissOutcome as ji, renderInlineText as jn, previousKissResult as jr, partFiles as jt, relativeTime as k, describeAuthorship as ki, CODE_COPY_CLASS as kn, positionInLineage as kr, checkArchitecture as kt, cancelUpdate as l, explanationActionOf as li, unreadCount as ln, isLiveJob as lr, runJob as lt, askCheckout as m, analysisRefOf as mi, prepareConversationWithin as mn, clearClaim as mr, stamp as mt, deleteReview as n, parkedReason as na, isQuestionOutstanding as ni, pruneNotifications as nn, endedAt as nr, statedWorkspacePort as nt, discardJob as o, reviewerDispositions as oi, retireNotification as on, pruneJobResidue as or, prepareReview as ot, updateReview as p, ANALYSIS_ONLY as pi, adoptLegacyBaseline as pn, purposeOf as pr, record as pt, stopChild as q, writeAgentPreference as qi, checkReview as qn, parseLifecycle as qr, createArchitectureNotification as qt, lineageIds as r, runnableAgents as ra, issuesOutstanding as ri, readNotification as rn, fail as rr, writePortPreference as rt, FETCH_TIMEOUT_MS as s, processDiscussion as si, toneOf as sn, saveJob as sr, settleReview as st, deleteLineage as t, isAgentId as ta, isIssueOutstanding as ti, moveIds as tn, attemptIdOf as tr, resolveWorkspacePort as tt, cancellableHere as u, explanationOf as ui, withUsageRecorded as un, isTerminalJobPhase as ur, startJob as ut, kissAgentId as v, findingIn as vi, refreshPrContext as vn, followedRefName as vr, telemetryUploadEnabled as vt, beginRun as w, wasReassessed as wi, authorPreview as wn, latestKissRun as wr, recordRuntimeBestEffort as wt, isDriving as x, promptGrade as xi, EXPLAIN_SIMPLY_PROMPT as xn, indexReviewGroups as xr, feedbackUrl as xt, recordKissRun as y, gradeScale as yi, isUnchanged as yn, groupByLineage as yr, BUILD_VERSION as yt, readIndexToken as z, shorthandOf as zi, isWorktreeHeld as zn, LIFECYCLES as zr, REPOSITORY_SCOPE as zt };
|
package/dist/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { $ as MIN_WORKSPACE_PORT, A as batchIdentity, Ai as WITHHELD_REASON, B as bootstrapUrl, Bi as git, Bn as readMarker, Dr as matchingWorkspaceIds, Er as loadWorkspace, Fr as summarise, Gn as findExistingReview, H as ensureServer, Hi as resolveAgent, In as MANAGED_ROOT, J as stopServer, Ji as CONFIG_PATH, Ki as readAgentPreference, L as queueForReview, Mi as resolveTarget, Mn as modelHelpLines, Mr as recentWorkspaces, Or as mutateWorkspace, P as runBatch, Pr as reviewedRepositories, Q as MAX_WORKSPACE_PORT, Ui as resolveModel, Un as describeMovement, Vn as removeWorktree, W as reviewsUrl, Wn as describeSubject, Xi as AGENT_IDS, Y as workspaceUrl, Yi as STORE_ROOT, Z as DEFAULT_WORKSPACE_PORT, Zi as agentById, Zn as forgeResolver, _ as runningJobs, _t as telemetryUploadConsent, a as wasBlocked, ar as loadJob, bt as PACKAGE_NAME, cr as PHASES, ct as reanalyseReview, d as mergeUpdateInto, dt as append, ea as detectAgents, er as allJobs, et as parseWorkspacePort, f as parkedUpdateRefusal, fr as progressSteps, g as liveUpdateFor, gt as recordTelemetryUploadConsent, h as UpdateAlreadyRunningError, ht as deliver, i as liveJobsFor, ji as kissOutcome, k as relativeTime, kr as positionInLineage, mr as clearClaim, mt as stamp, n as deleteReview$1, na as parkedReason, nt as statedWorkspacePort, ot as prepareReview, p as updateReview, pr as purposeOf, pt as record$1, qi as writeAgentPreference, ra as runnableAgents, rt as writePortPreference, st as settleReview, ut as startJob, vr as followedRefName, vt as telemetryUploadEnabled, y as recordKissRun, yt as BUILD_VERSION, z as readIndexToken } from "./delete_review-CFVFygqb.js";
|
|
3
3
|
import { basename, dirname, join, resolve } from "node:path";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
5
|
import { existsSync, mkdirSync, readdirSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -1150,6 +1150,11 @@ function unknownSettingValue(key, value, known) {
|
|
|
1150
1150
|
*/
|
|
1151
1151
|
function unresolvedAgent(resolution) {
|
|
1152
1152
|
if (resolution.kind === "unknown-id") return unknownAgent(resolution.id, AGENT_IDS);
|
|
1153
|
+
if (resolution.kind === "unavailable" && resolution.parked) return [
|
|
1154
|
+
resolution.reason,
|
|
1155
|
+
"",
|
|
1156
|
+
`Nothing was started. Name another agent with ${runnableAgents().flags}, or change the default with \`prreviewbuddy config set agent <agent>\`.`
|
|
1157
|
+
].join("\n");
|
|
1153
1158
|
if (resolution.kind === "unavailable") return `${resolution.agent?.displayName} cannot be run here. ${resolution.reason}`;
|
|
1154
1159
|
if (resolution.kind === "none") return [
|
|
1155
1160
|
"No coding agent was found, so there is nothing to review with.",
|
|
@@ -2380,6 +2385,11 @@ async function operate(command, workspace) {
|
|
|
2380
2385
|
err(commitReviewCannotUpdate(workspace.changeSet.data.pullRequest.head.sha));
|
|
2381
2386
|
return 1;
|
|
2382
2387
|
}
|
|
2388
|
+
const parked = command.operation === "update" ? parkedUpdateRefusal(workspace) : null;
|
|
2389
|
+
if (parked) {
|
|
2390
|
+
err(parked);
|
|
2391
|
+
return 1;
|
|
2392
|
+
}
|
|
2383
2393
|
enqueue(command, workspace.id);
|
|
2384
2394
|
if (command.operation === "reanalyse") {
|
|
2385
2395
|
const agent = await chooseFor(command, workspace);
|
|
@@ -2718,6 +2728,11 @@ async function agents(command) {
|
|
|
2718
2728
|
out(agentList(detected, preferred));
|
|
2719
2729
|
return 0;
|
|
2720
2730
|
}
|
|
2731
|
+
const parked = parkedReason(command.id);
|
|
2732
|
+
if (parked) {
|
|
2733
|
+
err(parked);
|
|
2734
|
+
return 1;
|
|
2735
|
+
}
|
|
2721
2736
|
if (!AGENT_IDS.includes(command.id)) {
|
|
2722
2737
|
err(unknownAgent(command.id, AGENT_IDS));
|
|
2723
2738
|
return 1;
|
|
@@ -2802,6 +2817,11 @@ function agent(command) {
|
|
|
2802
2817
|
return 0;
|
|
2803
2818
|
}
|
|
2804
2819
|
const id = command.value;
|
|
2820
|
+
const parked = parkedReason(id);
|
|
2821
|
+
if (parked) {
|
|
2822
|
+
err(parked);
|
|
2823
|
+
return 1;
|
|
2824
|
+
}
|
|
2805
2825
|
if (!AGENT_IDS.includes(id)) {
|
|
2806
2826
|
err(unknownAgent(id, AGENT_IDS));
|
|
2807
2827
|
return 1;
|
package/dist/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as MIN_WORKSPACE_PORT, $i as agentIdentityOf, $n as RUN_RECORD_RETENTION_MS, $r as readQueue, $t as markRead, A as batchIdentity, Ai as WITHHELD_REASON, An as escapeHtml$1, Ar as presentedKissRunOf, At as loadArchitecture, Bi as git, Bn as readMarker, Br as activityAttributes, Bt as ancestorsOf, C as RUN_KINDS, Ci as sourcePhrase, Cn as UNESTABLISHED_MOTIVATION, Cr as kissDecisionsOf, Ct as mapRuntimes, D as reportRun, Di as extractJsonText, Dn as renderMarkdown, Dt as formatDuration, E as endRun, Ei as asString, En as GITHUB_MARKDOWN, Er as loadWorkspace, Et as describeRuntimes, F as activateQueued, Fi as isCommitReview, Fn as withReviewLock, Ft as storedScopes, G as serverEntryExists, Gi as clearAgentPreference, Gn as findExistingReview, Gr as lifecyclePill, Gt as subjectOf, Hi as resolveAgent, Hn as requestJobStop, Hr as isLifecycle, Ht as writeJsonAtomically, I as compactQueue, Ii as resolveBase, In as MANAGED_ROOT, Ir as touchWorkspace, It as trackedFiles, Jn as followedBranch, Jr as sectionOf, Jt as createPrState, K as spawnServer, Ki as readAgentPreference, Kn as checkCodeFreshness, Kr as offersLifecycle, Kt as categoryOf, Li as AmbiguousRefError, Ln as createWorktree, Lr as workspaceRevision, Lt as ownersOf, M as parsePullRequestLink, Mi as resolveTarget, Mr as recentWorkspaces, Mt as readArchitecture, N as unsupportedReason, Ni as originRemote, Nn as ReviewBeingDeletedError, Nr as reviewedCommit, Nt as repositoryKey, O as stopRun, Oi as objectWithAnyOf, On as CODE_BLOCK_CLASS, Or as mutateWorkspace, Ot as ARCHITECTURE_DIR, P as runBatch, Pi as DetachedHeadError, Pn as isBusy, Pt as storeArchitecture, Q as MAX_WORKSPACE_PORT, Qi as agentFor$1, Qn as fillFileUrlTemplate, Qr as queueStamp, Qt as markAllRead, R as settleQueue, Ri as shortNameOf, Rn as holdWorktree, Rr as workspaceStamps, Rt as QUOTE_LIMITS, S as track, Si as reassessIn, Sn as chatConversationSection, Sr as kissDecisionRefusal, St as waitingHistory, T as completeRun, Ti as followUpFindingId, Tn as hasAuthorContent, Tr as lineagePosition, Tt as RUNTIME_WORDS, U as readServerRecord, Ui as resolveModel, Ur as lifecycleChip, Ut as announceJob, V as clearServerRecordOwnedBy, Vi as refExists, Vn as removeWorktree, Vr as activityLabel, Vt as isArchitectureId, Wi as agentIdOf, Wr as lifecycleItemLabel, Wt as branchOf, X as writeServerRecord, Xi as AGENT_IDS, Xn as fetchHead, Xr as queueAddMany, Xt as eventName, Yi as STORE_ROOT, Yn as reviewedShaOf, Yr as queueAdd, Yt as createPrUpdate, Z as DEFAULT_WORKSPACE_PORT, Zi as agentById, Zn as forgeResolver, Zr as queueRemove, Zt as listNotifications, _i as findingAssessment, _n as unforeseenFailure, _r as decideKissRecommendation, _t as telemetryUploadConsent, a as wasBlocked, aa as AgentUnavailableError, ai as resolvedByConversation, an as removeNotification, ar as loadJob, at as observeReview, b as startKissJob, bi as isGradeFor, bn as agentEnvOf, br as indexKeptIds, c as RefreshUnavailableError, ci as recommendationsOf, cn as unreadAround, ct as reanalyseReview, d as mergeUpdateInto, di as isExplanationAction, dn as existingPaths, dr as phasesFor, ea as detectAgents, ei as doneVerb, en as markReadForReview, er as allJobs, et as parseWorkspacePort, fi as withExplanation, fn as ASK_REREAD_CEILING_MS, fr as progressSteps, ft as readEvents, g as liveUpdateFor, gi as currentGradeIn, gn as storedConversation, gt as recordTelemetryUploadConsent, h as UpdateAlreadyRunningError, hi as assessmentLookup, hn as saveRefresh, hr as isClaimed, i as liveJobsFor, ia as AgentCancelledError, ii as questionsOutstanding, in as readStateOf, ir as isTerminal, it as failureOf$1, j as extractPullRequestLinks, ji as kissOutcome, jn as renderInlineText, jr as previousKissResult, jt as partFiles, k as relativeTime$1, ki as describeAuthorship, kn as CODE_COPY_CLASS, kt as checkArchitecture, l as cancelUpdate, li as explanationActionOf, ln as unreadCount$1, lr as isLiveJob, lt as runJob, m as askCheckout, mi as analysisRefOf, mn as prepareConversationWithin, n as deleteReview, na as parkedReason, ni as isQuestionOutstanding, nn as pruneNotifications, nr as endedAt, nt as statedWorkspacePort, o as discardJob, oi as reviewerDispositions, on as retireNotification, or as pruneJobResidue, ot as prepareReview, p as updateReview, pi as ANALYSIS_ONLY, pn as adoptLegacyBaseline, pr as purposeOf, pt as record, q as stopChild, qi as writeAgentPreference, qn as checkReview, qr as parseLifecycle, qt as createArchitectureNotification, r as lineageIds, ra as runnableAgents, ri as issuesOutstanding, rn as readNotification, rr as fail$1, rt as writePortPreference, s as FETCH_TIMEOUT_MS, si as processDiscussion, sn as toneOf, sr as saveJob, st as settleReview, t as deleteLineage, ta as isAgentId, ti as isIssueOutstanding, tn as moveIds, tr as attemptIdOf, tt as resolveWorkspacePort, u as cancellableHere, ui as explanationOf, un as withUsageRecorded, ur as isTerminalJobPhase, v as kissAgentId, vi as findingIn, vn as refreshPrContext, vr as followedRefName, w as beginRun, wi as wasReassessed, wn as authorPreview, wr as latestKissRun, wt as recordRuntimeBestEffort, x as isDriving, xi as promptGrade, xn as EXPLAIN_SIMPLY_PROMPT, xr as indexReviewGroups, xt as feedbackUrl, yi as gradeScale, yn as isUnchanged, yr as groupByLineage, yt as BUILD_VERSION, z as readIndexToken, zi as shorthandOf, zn as isWorktreeHeld, zr as LIFECYCLES, zt as REPOSITORY_SCOPE } from "./delete_review-CFVFygqb.js";
|
|
2
2
|
import { basename, isAbsolute, join, relative, resolve } from "node:path";
|
|
3
3
|
import { execFile } from "node:child_process";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -4228,7 +4228,7 @@ function renderFailureBody(job, options = {}) {
|
|
|
4228
4228
|
if (job.failure.stopped) return `<p>${options.lead === false ? "" : "<strong>Review stopped.</strong> "}Nothing went wrong, and what it had finished is kept.</p>
|
|
4229
4229
|
<button type="button" class="prb-job-retry" data-job-retry>Carry on</button>
|
|
4230
4230
|
<p class="prb-job-note">It picks up from the ${escapeHtml$1(noun)}, not from the start.</p>`;
|
|
4231
|
-
const next = job.failure.kind === "agent_authentication_failed" ? `<p class="prb-job-note">Signing that agent in is what changes this. Once it is signed in, update the review.</p>` : `<button type="button" class="prb-job-retry" data-job-retry>Retry</button>
|
|
4231
|
+
const next = job.failure.parked ? "" : job.failure.kind === "agent_authentication_failed" ? `<p class="prb-job-note">Signing that agent in is what changes this. Once it is signed in, update the review.</p>` : `<button type="button" class="prb-job-retry" data-job-retry>Retry</button>
|
|
4232
4232
|
<p class="prb-job-note">Retry picks up from the ${escapeHtml$1(noun)}, not from the start.</p>`;
|
|
4233
4233
|
return `<p>${options.lead === false ? "" : "<strong>Review paused.</strong> "}${escapeHtml$1(job.failure.message)}</p>
|
|
4234
4234
|
${next}`;
|
|
@@ -7701,6 +7701,8 @@ function startArchitectureRun(workspace, scope, deps = {}) {
|
|
|
7701
7701
|
const now = deps.now ?? Date.now;
|
|
7702
7702
|
const startedAt = now();
|
|
7703
7703
|
const env = agentEnvOf(workspace);
|
|
7704
|
+
const parked = parkedReason(env.agentId);
|
|
7705
|
+
if (parked) return { refused: parked };
|
|
7704
7706
|
const agent = agentFor$1(env);
|
|
7705
7707
|
const requestedModel = resolveModel({ review: { session: workspace.session } }) ?? void 0;
|
|
7706
7708
|
const record = {
|
|
@@ -10489,6 +10491,7 @@ function readSettings() {
|
|
|
10489
10491
|
},
|
|
10490
10492
|
agent: readAgentPreference(),
|
|
10491
10493
|
agents: AGENT_IDS,
|
|
10494
|
+
agentParked: parkedReason(readAgentPreference() ?? void 0) ?? null,
|
|
10492
10495
|
usageCounts: telemetryUploadConsent(),
|
|
10493
10496
|
theme: readPreferences().theme ?? "system"
|
|
10494
10497
|
};
|
|
@@ -10513,6 +10516,11 @@ function saveSettings(change, minPort, maxPort) {
|
|
|
10513
10516
|
error: `\`${change.port}\` is not a port PR Review Buddy can use. Choose one between ${minPort} and ${maxPort}.`
|
|
10514
10517
|
};
|
|
10515
10518
|
}
|
|
10519
|
+
const parked = change.agent ? parkedReason(change.agent) : void 0;
|
|
10520
|
+
if (parked) return {
|
|
10521
|
+
settings: readSettings(),
|
|
10522
|
+
error: parked
|
|
10523
|
+
};
|
|
10516
10524
|
if (change.agent !== void 0 && change.agent !== "" && !AGENT_IDS.includes(change.agent)) return {
|
|
10517
10525
|
settings: readSettings(),
|
|
10518
10526
|
error: `There is no agent called \`${change.agent}\`.`
|
|
@@ -10668,11 +10676,15 @@ function renderReviewsSection(settings) {
|
|
|
10668
10676
|
<h2>Reviews</h2>
|
|
10669
10677
|
<label class="prb-field prb-settings-field">
|
|
10670
10678
|
<span>Default coding agent</span>
|
|
10671
|
-
<select data-settings-agent aria-describedby="prb-agent-help">${[
|
|
10679
|
+
<select data-settings-agent aria-describedby="prb-agent-help">${[
|
|
10680
|
+
`<option value=""${settings.agent ? "" : " selected"}>Ask each time</option>`,
|
|
10681
|
+
...settings.agents.map((id) => `<option value="${escapeHtml$1(id)}"${settings.agent === id ? " selected" : ""}>${escapeHtml$1(id)}</option>`),
|
|
10682
|
+
...settings.agentParked && settings.agent ? [`<option value="${escapeHtml$1(settings.agent)}" selected disabled>${escapeHtml$1(settings.agent)} (turned off)</option>`] : []
|
|
10683
|
+
].join("")}</select>
|
|
10672
10684
|
</label>
|
|
10673
10685
|
<p class="prb-settings-help" id="prb-agent-help">Used when a review does not name one. PR Review
|
|
10674
10686
|
Buddy uses an agent already installed on this machine and its existing sign-in, so this changes
|
|
10675
|
-
which one runs and never asks you for a credential.</p
|
|
10687
|
+
which one runs and never asks you for a credential.</p>${settings.agentParked ? `\n <p class="prb-settings-help" role="alert">${escapeHtml$1(settings.agentParked)} Choose another default, or Ask each time.</p>` : ""}
|
|
10676
10688
|
</section>`;
|
|
10677
10689
|
}
|
|
10678
10690
|
/**
|
|
@@ -11602,11 +11614,7 @@ function modelHelpOf(agentId) {
|
|
|
11602
11614
|
}
|
|
11603
11615
|
}
|
|
11604
11616
|
function agentNameOf(agentId) {
|
|
11605
|
-
|
|
11606
|
-
return agentById(agentId).displayName;
|
|
11607
|
-
} catch {
|
|
11608
|
-
return agentId;
|
|
11609
|
-
}
|
|
11617
|
+
return isAgentId(agentId) ? agentIdentityOf(agentId).displayName : agentId;
|
|
11610
11618
|
}
|
|
11611
11619
|
var refuse = (status, error, extra = {}) => ({
|
|
11612
11620
|
status,
|
|
@@ -12793,7 +12801,7 @@ function reviewHref(review) {
|
|
|
12793
12801
|
}
|
|
12794
12802
|
/** The agent's name, only where the record names one this build knows. */
|
|
12795
12803
|
function agentName(agentId) {
|
|
12796
|
-
return agentId && isAgentId(agentId) ?
|
|
12804
|
+
return agentId && isAgentId(agentId) ? agentIdentityOf(agentId).displayName : void 0;
|
|
12797
12805
|
}
|
|
12798
12806
|
/** Who asked and who ran it, each only when known. Two facts, never one guessed from the other. */
|
|
12799
12807
|
function provenance(source, agentId) {
|
|
@@ -15996,6 +16004,8 @@ async function handleReanalyse(req, res, workspace) {
|
|
|
15996
16004
|
if (req.method !== "POST") return send(res, 405, { error: "Analysing a review again needs a POST." });
|
|
15997
16005
|
const current = workspace.jobId ? loadJob(workspace.jobId) : null;
|
|
15998
16006
|
if (current && (!isTerminal(current) || isClaimed(current.id))) return send(res, 409, { error: "This review is still being made. Wait for it to finish before analysing it again." });
|
|
16007
|
+
const parked = parkedReason(agentIdOf(workspace.session));
|
|
16008
|
+
if (parked) return send(res, 409, { error: `${parked} To analyse this review again with another agent, run \`prreviewbuddy review --review ${workspace.id} --reanalyse\` with ${runnableAgents().flags}.` });
|
|
15999
16009
|
await new Promise((resolve) => {
|
|
16000
16010
|
const run = reanalyseReview(workspace.id, void 0, () => {
|
|
16001
16011
|
send(res, 200, { ok: true });
|
|
@@ -16036,6 +16046,8 @@ async function handleKiss(req, res, workspace) {
|
|
|
16036
16046
|
if (!audience) return send(res, 400, { error: "A KISS review is written either for the person who wrote the code or for somebody reviewing it. Choose which before running it." });
|
|
16037
16047
|
const current = latestKissRun(workspace);
|
|
16038
16048
|
if (current && current.status === "generating" && isClaimed(current.jobId)) return send(res, 409, { error: "A KISS review of this change is already running." });
|
|
16049
|
+
const parked = parkedReason(kissAgentId(workspace));
|
|
16050
|
+
if (parked) return send(res, 409, { error: `${parked} A KISS review started here uses the agent this review was made with. To run one with another agent, start it from the terminal with \`--lens kiss\` and ${runnableAgents().flags}.` });
|
|
16039
16051
|
startKissJob({
|
|
16040
16052
|
workspaceId: workspace.id,
|
|
16041
16053
|
audience,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prreviewbuddy",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Understand code changes before you approve them. Local branch and pull request reviews with Claude Code
|
|
3
|
+
"version": "0.81.0",
|
|
4
|
+
"description": "Understand code changes before you approve them. Local branch and pull request reviews with Claude Code or Codex.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"homepage": "https://prreviewbuddy.com",
|
|
7
7
|
"type": "module",
|
|
@@ -24,8 +24,6 @@
|
|
|
24
24
|
"claude",
|
|
25
25
|
"claude-code",
|
|
26
26
|
"codex",
|
|
27
|
-
"gemini",
|
|
28
|
-
"gemini-cli",
|
|
29
27
|
"ai"
|
|
30
28
|
],
|
|
31
29
|
"engines": {
|