prreviewbuddy 0.46.0 → 0.48.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 +50 -0
- package/dist/{delete_review-lmVdoybL.js → delete_review-D52wkt66.js} +133 -9
- package/dist/main.js +1 -1
- package/dist/server.js +425 -146
- package/package.json +1 -1
- package/static/chunk-BeqgAIrQ.js +1 -1
- package/static/chunk-DaUgQrSg.js +1 -0
- package/static/reviews.js +1 -1
- package/static/settings.js +1 -1
- package/static/shell.css +201 -115
- package/static/workspace.js +2 -2
- package/static/chunk-CmPWaXhU.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.48.0
|
|
4
|
+
|
|
5
|
+
**Active, Waiting and Done.** A review can now be marked **Waiting**, for when you have done your
|
|
6
|
+
pass and expect another round, or **Done**, for when you are finished with it. The reviews list keeps
|
|
7
|
+
your active reviews at the top, with **Waiting** below them and **Done** below that, folded away. Use
|
|
8
|
+
the **⋯** menu on a card, or select several and use the bar at the bottom. **Move to active** puts a
|
|
9
|
+
review back. This is separate from **Reviewed**, which still records that you have been through it.
|
|
10
|
+
|
|
11
|
+
**Waiting reviews come back when something changes.** If a Waiting review gets new commits, or its
|
|
12
|
+
pull request is merged, closed or reopened, it shows up in the main list again marked **Changed while
|
|
13
|
+
waiting**. Marking it Waiting again puts it back. A Done review never comes back by itself; if it
|
|
14
|
+
changes, it is marked **Changed since done** where it is. Marking a review Waiting starts watching
|
|
15
|
+
it straight away, so a push made soon after still brings it back. Adding a Waiting or Done review to
|
|
16
|
+
your review queue moves it back to Active.
|
|
17
|
+
|
|
18
|
+
**The list no longer reorders when you open a review.** Reviews are ordered by what last happened to
|
|
19
|
+
the change: when it was analysed, when new commits arrived, or when the pull request was merged,
|
|
20
|
+
closed or reopened. The time on each card now says which of those it was, for example "Updated
|
|
21
|
+
2 hours ago" or "Merged 1 day ago". Saved reviews still come first.
|
|
22
|
+
|
|
23
|
+
**Load more instead of pages.** Each section shows fifteen reviews and a **Load more** button for the
|
|
24
|
+
rest. Search and the filters still cover every review, in all three sections.
|
|
25
|
+
|
|
26
|
+
**Done reviews are kept longer.** Like saved reviews, Done reviews are kept for ninety days rather
|
|
27
|
+
than thirty, counting from the last time you opened or marked them.
|
|
28
|
+
|
|
29
|
+
**Light mode.** The workspace now has a light theme as well as the dark one. The rail, the top bars,
|
|
30
|
+
Buddy AI, the reviews list, Notifications and Settings are drawn in pale greys around a white
|
|
31
|
+
review, so the review stays the brightest thing on the screen. Purple is kept for what you have
|
|
32
|
+
chosen and for the main action, as a pale tint rather than a solid block.
|
|
33
|
+
|
|
34
|
+
**Follows your device, or stays put.** Settings has a new **Appearance** section with **System**,
|
|
35
|
+
**Light** and **Dark**. System is the default, and it changes with your device at once, without
|
|
36
|
+
reloading the page, when your Mac switches between light and dark. Choosing a theme shows it on the
|
|
37
|
+
Settings page straight away; **Save changes** keeps it. If you have not chosen, the workspace follows
|
|
38
|
+
your device, so on a Mac set to light it now opens in light mode.
|
|
39
|
+
|
|
40
|
+
**Readable in both.** Every piece of text in the light theme, including timestamps, counts and other
|
|
41
|
+
small details, meets the WCAG 4.5:1 contrast level against whatever it sits on.
|
|
42
|
+
|
|
43
|
+
**Fixed: buttons in a review that went blank on hover.** In the dark theme, pointing at **Open in**
|
|
44
|
+
your editor, **Show more of this file**, **View files**, **Regenerate** or a diagram's zoom buttons
|
|
45
|
+
turned the label white on the white review, so it disappeared. They now keep their dark label.
|
|
46
|
+
|
|
47
|
+
**A clearer message when OpenAI refuses Codex while it is signed in.** If Codex says it is signed in
|
|
48
|
+
but OpenAI answers "Incorrect API key", the review no longer suggests signing in again, and no longer
|
|
49
|
+
suggests looking for an API key of your own: the key in that error is Codex's own. It now suggests
|
|
50
|
+
`codex doctor` to see what Codex is using, and `codex features list` to find an experimental Codex
|
|
51
|
+
feature to turn off, which is what fixed it when we saw it.
|
|
52
|
+
|
|
3
53
|
## 0.46.0
|
|
4
54
|
|
|
5
55
|
**The change map: see what a change is about, and how its parts affect each other.** The Diagrams
|
|
@@ -1129,6 +1129,19 @@ var CodexUnavailableError = class extends AgentUnavailableError {};
|
|
|
1129
1129
|
*/
|
|
1130
1130
|
var AUTHENTICATION = /not (?:logged|signed) in|unauthori[sz]ed|401|authenticat|credential|sign[- ]?in|log ?in/i;
|
|
1131
1131
|
/**
|
|
1132
|
+
* OpenAI refusing a request Codex believes is signed in, which is not nobody being signed in.
|
|
1133
|
+
*
|
|
1134
|
+
* Seen with Codex reporting "Logged in using ChatGPT" and no API key anywhere in the reviewer's
|
|
1135
|
+
* environment: the key named in the error is Codex's own, not one of theirs. Signing in again did
|
|
1136
|
+
* not clear it; turning off an experimental Codex feature did. So the advice is Codex's own
|
|
1137
|
+
* diagnosis and its feature switches, never a login loop and never a hunt for an API key. Still an
|
|
1138
|
+
* authentication failure, so no Retry is offered.
|
|
1139
|
+
*/
|
|
1140
|
+
var REJECTED_KEY = /incorrect api key|invalid[_ ]api[_ ]key/i;
|
|
1141
|
+
function isAuthentication(detail) {
|
|
1142
|
+
return AUTHENTICATION.test(detail) || REJECTED_KEY.test(detail);
|
|
1143
|
+
}
|
|
1144
|
+
/**
|
|
1132
1145
|
* Which kind of failure the agent's own sentence describes.
|
|
1133
1146
|
*
|
|
1134
1147
|
* Only the one distinction that changes what a person is offered: a run that failed because nobody
|
|
@@ -1137,7 +1150,7 @@ var AUTHENTICATION = /not (?:logged|signed) in|unauthori[sz]ed|401|authenticat|c
|
|
|
1137
1150
|
* label for them.
|
|
1138
1151
|
*/
|
|
1139
1152
|
function kindOf(detail) {
|
|
1140
|
-
return
|
|
1153
|
+
return isAuthentication(detail) ? "agent_authentication_failed" : "agent_execution_failed";
|
|
1141
1154
|
}
|
|
1142
1155
|
var codexAgent = {
|
|
1143
1156
|
id: CODEX_AGENT_ID,
|
|
@@ -1147,8 +1160,10 @@ var codexAgent = {
|
|
|
1147
1160
|
captureEnv: captureEnv$1,
|
|
1148
1161
|
/** Which tool, which profile, and the one command that changes it. See `agent.ts` for the budget. */
|
|
1149
1162
|
explainFailure(detail, env = {}) {
|
|
1150
|
-
if (!
|
|
1151
|
-
|
|
1163
|
+
if (!isAuthentication(detail)) return null;
|
|
1164
|
+
const profile = env.CODEX_HOME ? `the Codex profile at \`${env.CODEX_HOME}\`` : "your default Codex profile";
|
|
1165
|
+
if (REJECTED_KEY.test(detail)) return `OpenAI refused a request from ${profile} even though Codex reports being signed in, which usually points to Codex's own setup rather than your sign-in. Run \`codex doctor\` to see what it is using, and check \`codex features list\` for an experimental feature to turn off with \`codex features disable <name>\`.`;
|
|
1166
|
+
return `Codex could not sign in. This review was started using ${profile}, so run \`codex login\` against that one.`;
|
|
1152
1167
|
},
|
|
1153
1168
|
/**
|
|
1154
1169
|
* Whether the command is here and runs. Deliberately not whether it is signed in.
|
|
@@ -4112,6 +4127,95 @@ function normalise(ids) {
|
|
|
4112
4127
|
return seen;
|
|
4113
4128
|
}
|
|
4114
4129
|
//#endregion
|
|
4130
|
+
//#region ../../packages/review-harness/src/workspace/lifecycle.ts
|
|
4131
|
+
/**
|
|
4132
|
+
* What happens next with a change, as the reviewer says it: still in play, parked until something
|
|
4133
|
+
* moves, or finished with.
|
|
4134
|
+
*
|
|
4135
|
+
* A separate axis from New / In progress / Reviewed, which says what the reviewer has *done*. A
|
|
4136
|
+
* change can be reviewed and waiting for another push, or reviewed and done, and one field cannot
|
|
4137
|
+
* hold both answers.
|
|
4138
|
+
*
|
|
4139
|
+
* One registry that the stored type, the card, the menus, the bulk bar and the route all derive
|
|
4140
|
+
* from. Pure on purpose: the reviews page's script imports it to move a card between sections after
|
|
4141
|
+
* a mark, without asking the server for the page again.
|
|
4142
|
+
*/
|
|
4143
|
+
var LIFECYCLES = [
|
|
4144
|
+
{
|
|
4145
|
+
id: "active",
|
|
4146
|
+
action: "Move to active"
|
|
4147
|
+
},
|
|
4148
|
+
{
|
|
4149
|
+
id: "waiting",
|
|
4150
|
+
action: "Mark waiting"
|
|
4151
|
+
},
|
|
4152
|
+
{
|
|
4153
|
+
id: "done",
|
|
4154
|
+
action: "Mark done"
|
|
4155
|
+
}
|
|
4156
|
+
];
|
|
4157
|
+
function isLifecycle(value) {
|
|
4158
|
+
return LIFECYCLES.some((lifecycle) => lifecycle.id === value);
|
|
4159
|
+
}
|
|
4160
|
+
/** A stored value read defensively: anything this code did not write reads as Active. */
|
|
4161
|
+
function parseLifecycle(raw) {
|
|
4162
|
+
if (typeof raw !== "object" || raw === null) return void 0;
|
|
4163
|
+
const { state, at } = raw;
|
|
4164
|
+
if (state !== "waiting" && state !== "done" || typeof at !== "number" || !Number.isFinite(at)) return void 0;
|
|
4165
|
+
return {
|
|
4166
|
+
state,
|
|
4167
|
+
at
|
|
4168
|
+
};
|
|
4169
|
+
}
|
|
4170
|
+
function lifecycleAction(lifecycle) {
|
|
4171
|
+
return LIFECYCLES.find((entry) => entry.id === lifecycle).action;
|
|
4172
|
+
}
|
|
4173
|
+
var ACTIVITY_LABELS = {
|
|
4174
|
+
created: "Created",
|
|
4175
|
+
updated: "Updated",
|
|
4176
|
+
merged: "Merged",
|
|
4177
|
+
closed: "Closed",
|
|
4178
|
+
reopened: "Reopened"
|
|
4179
|
+
};
|
|
4180
|
+
function activityLabel(kind) {
|
|
4181
|
+
return ACTIVITY_LABELS[kind];
|
|
4182
|
+
}
|
|
4183
|
+
/**
|
|
4184
|
+
* Which section a card is drawn in.
|
|
4185
|
+
*
|
|
4186
|
+
* Waiting means "bring this back when something changes", so a Waiting review whose change moved
|
|
4187
|
+
* after it was parked is drawn in Active. Derived, and nothing is written: the stored state stays
|
|
4188
|
+
* Waiting until the reviewer says otherwise, and marking it Waiting again moves the baseline.
|
|
4189
|
+
*
|
|
4190
|
+
* Done means "leave me alone", so it never comes back by itself. `created` can never resurface
|
|
4191
|
+
* anything either, because a new analysis is a new record, and a new record is Active.
|
|
4192
|
+
*/
|
|
4193
|
+
function sectionOf(lifecycle, activity) {
|
|
4194
|
+
if (!lifecycle) return "active";
|
|
4195
|
+
if (lifecycle.state === "waiting" && changedSince(lifecycle, activity)) return "active";
|
|
4196
|
+
return lifecycle.state;
|
|
4197
|
+
}
|
|
4198
|
+
/** The chip that says why a card is where it is, or absent when its section already says it. */
|
|
4199
|
+
function lifecycleChip(lifecycle, activity) {
|
|
4200
|
+
if (!lifecycle || !changedSince(lifecycle, activity)) return void 0;
|
|
4201
|
+
return lifecycle.state === "waiting" ? "Changed while waiting" : "Changed since done";
|
|
4202
|
+
}
|
|
4203
|
+
function changedSince(lifecycle, activity) {
|
|
4204
|
+
return activity !== void 0 && activity.kind !== "created" && activity.at > lifecycle.at;
|
|
4205
|
+
}
|
|
4206
|
+
/**
|
|
4207
|
+
* Which lifecycle items a card's menu offers.
|
|
4208
|
+
*
|
|
4209
|
+
* Every state but the one the card is already in, which would be an item that does nothing. A card
|
|
4210
|
+
* carrying a chip is the exception and offers all three: re-marking it is how the reviewer says
|
|
4211
|
+
* they have seen the change, so "Mark waiting" on a Waiting review that changed is the settle
|
|
4212
|
+
* action, not a no-op.
|
|
4213
|
+
*/
|
|
4214
|
+
function offersLifecycle(target, lifecycle, activity) {
|
|
4215
|
+
if (lifecycleChip(lifecycle, activity) !== void 0) return true;
|
|
4216
|
+
return target !== (lifecycle?.state ?? "active");
|
|
4217
|
+
}
|
|
4218
|
+
//#endregion
|
|
4115
4219
|
//#region ../../packages/review-harness/src/workspace/store.ts
|
|
4116
4220
|
var WORKSPACES_DIR = join(STORE_ROOT, "workspaces");
|
|
4117
4221
|
/**
|
|
@@ -4481,8 +4585,20 @@ function followedRefName(branch, followedRef) {
|
|
|
4481
4585
|
* can return is the two added together. Neither constant says that on its own, which is why it is
|
|
4482
4586
|
* said here.
|
|
4483
4587
|
*/
|
|
4484
|
-
function indexReviewGroups(limit, keptLimit, keptIds) {
|
|
4485
|
-
return selectIndexGroups(
|
|
4588
|
+
function indexReviewGroups(limit, keptLimit, keptIds, rank, groups = groupByLineage(recentWorkspaces(Number.MAX_SAFE_INTEGER))) {
|
|
4589
|
+
return selectIndexGroups(groups, limit, keptLimit, keptIds, rank);
|
|
4590
|
+
}
|
|
4591
|
+
/**
|
|
4592
|
+
* What the reviewer explicitly kept, which is what stops the recency window hiding it: the queue,
|
|
4593
|
+
* Saved, and anything marked Waiting or Done.
|
|
4594
|
+
*
|
|
4595
|
+
* Done is the reviewer's archive, and an archive the recency window can empty is not one. Waiting
|
|
4596
|
+
* is work they expect back, and a push to it must have a card to come back on.
|
|
4597
|
+
*/
|
|
4598
|
+
function indexKeptIds(reviews, queue) {
|
|
4599
|
+
const kept = new Set(queue);
|
|
4600
|
+
for (const review of reviews) if (review.pinned || review.lifecycle !== void 0) kept.add(review.id);
|
|
4601
|
+
return kept;
|
|
4486
4602
|
}
|
|
4487
4603
|
/**
|
|
4488
4604
|
* The choosing, with the disk left out, in the same spirit as `groupByLineage` next door.
|
|
@@ -4494,12 +4610,18 @@ function indexReviewGroups(limit, keptLimit, keptIds) {
|
|
|
4494
4610
|
*
|
|
4495
4611
|
* The kept side is capped for the same reason the recent side is: `queue.json` is a file on a disk
|
|
4496
4612
|
* somebody can edit, and an uncapped read of it is an index with five thousand cards on it.
|
|
4613
|
+
*
|
|
4614
|
+
* **Windowed by `rank`, which is what the list is ordered by.** The index passes what last happened
|
|
4615
|
+
* to each change, so a branch analysed two months ago and pushed to this morning is inside the
|
|
4616
|
+
* window rather than cut before its activity is ever looked at. Absent, it is when the newest
|
|
4617
|
+
* review was made, which is what every other caller has always meant by recent.
|
|
4497
4618
|
*/
|
|
4498
|
-
function selectIndexGroups(groups, limit, keptLimit, keptIds) {
|
|
4619
|
+
function selectIndexGroups(groups, limit, keptLimit, keptIds, rank = (group) => group.latest.createdAt) {
|
|
4499
4620
|
const kept = [];
|
|
4500
4621
|
const rest = [];
|
|
4501
4622
|
for (const group of groups) (group.history.some((review) => keptIds.has(review.id)) ? kept : rest).push(group);
|
|
4502
|
-
|
|
4623
|
+
const byRank = (a, b) => rank(b) - rank(a);
|
|
4624
|
+
return [...rest.sort(byRank).slice(0, limit), ...kept.sort(byRank).slice(0, keptLimit)].sort(byRank);
|
|
4503
4625
|
}
|
|
4504
4626
|
/**
|
|
4505
4627
|
* The grouping itself, with the disk left out.
|
|
@@ -4626,6 +4748,7 @@ function summarise(workspace) {
|
|
|
4626
4748
|
lastViewedAt: workspace.lastViewedAt,
|
|
4627
4749
|
completedAt: workspace.completedAt,
|
|
4628
4750
|
pinned: workspace.pinned === true,
|
|
4751
|
+
lifecycle: parseLifecycle(workspace.lifecycle),
|
|
4629
4752
|
paths: files.slice(0, MAX_INDEXED_PATHS).map((file) => file.name),
|
|
4630
4753
|
prNumber: workspace.changeSet.data.pullRequest?.number || workspace.prContext?.pullRequest.number,
|
|
4631
4754
|
commitSha: workspace.session.metadata?.commitSha || (workspace.changeSet.targetType === "commit" ? workspace.changeSet.data.pullRequest.head.sha : "") || void 0,
|
|
@@ -4803,7 +4926,8 @@ function isKept(entry, queued) {
|
|
|
4803
4926
|
const id = workspaceIdFrom(entry);
|
|
4804
4927
|
if (id === null) return false;
|
|
4805
4928
|
if (queued.has(id)) return true;
|
|
4806
|
-
|
|
4929
|
+
const workspace = loadWorkspace(id);
|
|
4930
|
+
return workspace?.pinned === true || parseLifecycle(workspace?.lifecycle)?.state === "done";
|
|
4807
4931
|
}
|
|
4808
4932
|
/** The review an entry belongs to, whether it is the record or the usage sidecar beside it. */
|
|
4809
4933
|
function workspaceIdFrom(entry) {
|
|
@@ -12651,4 +12775,4 @@ function lineageIds(id) {
|
|
|
12651
12775
|
return [.../* @__PURE__ */ new Set([id, ...lineage.map((review) => review.id)])];
|
|
12652
12776
|
}
|
|
12653
12777
|
//#endregion
|
|
12654
|
-
export { queueForReview as $,
|
|
12778
|
+
export { queueForReview as $, mutateWorkspace as $t, createPrState as A, describeAuthorship as An, allJobs as At, toneOf as B, CONFIG_PATH as Bn, purposeOf as Bt, readEvents as C, doneVerb as Cn, forgeFor as Ct, announceJob as D, questionsOutstanding as Dn, checkReview as Dt, telemetryUploadConsent as E, issuesOutstanding as En, checkCodeFreshness as Et, markAllRead as F, resolveAgent as Fn, saveJob as Ft, extractJsonText as G, agentFor as Gn, groupByLineage as Gt, withUsageRecorded as H, AGENT_IDS as Hn, driverGone as Ht, markRead as I, resolveModel as In, PHASES as It, readMarker as J, AgentUnavailableError as Jn, latestKissRun as Jt, ReviewBeingDeletedError as K, detectAgents as Kn, indexKeptIds as Kt, pruneNotifications as L, clearAgentPreference as Ln, isLiveJob as Lt, eventName as M, displayRef as Mn, fail as Mt, headline as N, isCommitReview as Nn, isTerminal as Nt, branchOf as O, reviewerDispositions as On, followedBranch as Ot, listNotifications as P, git as Pn, loadJob as Pt, compactQueue as Q, matchingWorkspaceIds as Qt, readNotification as R, readAgentPreference as Rn, phasesFor as Rt, startJob as S, readQueue as Sn, forgeResolver as St, recordTelemetryUploadConsent as T, isQuestionOutstanding as Tn, fillFileUrlTemplate as Tt, EXPLAIN_SIMPLY_PROMPT as U, DEFAULT_AGENT_ID as Un, isClaimed as Ut, unreadCount as V, STORE_ROOT as Vn, clearClaim as Vt, asString as W, agentById as Wn, followedRefName as Wt, modelHelpLines as X, lineagePosition as Xt, removeWorktree as Y, lineageKeyFor as Yt, relativeTime as Z, loadWorkspace as Zt, agentEnvOf as _, dequeueOnComplete as _n, parseWorkspacePort as _t, wasBlocked as a, summarise as an, reviewsUrl as at, reanalyseReview as b, queueRemove as bn, writePortPreference as bt, RefreshUnavailableError as c, workspaceStamps as cn, stopServer as ct, refreshPrContext as d, isLifecycle as dn, BUILD_VERSION as dt, positionInLineage as en, readIndexToken as et, isUnchanged as f, lifecycleAction as fn, PACKAGE_NAME as ft, runningJobs as g, sectionOf as gn, MIN_WORKSPACE_PORT as gt, liveUpdateFor as h, parseLifecycle as hn, MAX_WORKSPACE_PORT as ht, liveJobsFor as i, reviewedRepositories as in, readServerRecord as it, createPrUpdate as j, resolveTarget as jn, endedAt as jt, subjectOf as k, processDiscussion as kn, reviewedShaOf as kt, mergeUpdateInto as l, LIFECYCLES as ln, workspaceUrl as lt, UpdateAlreadyRunningError as m, offersLifecycle as mn, DEFAULT_WORKSPACE_PORT as mt, deleteReview as n, recentWorkspaces as nn, clearServerRecord as nt, discardJob as o, touchWorkspace as on, serverEntryExists as ot, askCheckout as p, lifecycleChip as pn, feedbackUrl as pt, MANAGED_ROOT as q, AgentCancelledError as qn, indexReviewGroups as qt, lineageIds as r, reviewedCommit as rn, ensureServer as rt, FETCH_TIMEOUT_MS as s, workspaceRevision as sn, spawnServer as st, deleteLineage as t, previousKissResult as tn, bootstrapUrl as tt, updateReview as u, activityLabel as un, writeServerRecord as ut, recordKissRun as v, queueAdd as vn, resolveWorkspacePort as vt, record as w, isIssueOutstanding as wn, remoteHost as wt, runJob as x, queueStamp as xn, claimRequestUrl as xt, startKissJob as y, queueAddMany as yn, statedWorkspacePort as yt, removeNotification as z, writeAgentPreference as zn, progressSteps as zt };
|
package/dist/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as queueForReview, $t as
|
|
2
|
+
import { $ as queueForReview, $t as mutateWorkspace, At as allJobs, Bn as CONFIG_PATH, Bt as purposeOf, Dt as checkReview, E as telemetryUploadConsent, Fn as resolveAgent, Gt as groupByLineage, Hn as AGENT_IDS, Ht as driverGone, In as resolveModel, It as PHASES, J as readMarker, Kn as detectAgents, Mn as displayRef, Nt as isTerminal, Pn as git, Pt as loadJob, Qt as matchingWorkspaceIds, Rn as readAgentPreference, S as startJob, St as forgeResolver, T as recordTelemetryUploadConsent, Un as DEFAULT_AGENT_ID, Ut as isClaimed, Vn as STORE_ROOT, Vt as clearClaim, Wn as agentById, Wt as followedRefName, X as modelHelpLines, Y as removeWorktree, Yt as lineageKeyFor, Z as relativeTime, Zt as loadWorkspace, _t as parseWorkspacePort, a as wasBlocked, an as summarise, at as reviewsUrl, b as reanalyseReview, bt as writePortPreference, ct as stopServer, dt as BUILD_VERSION, en as positionInLineage, et as readIndexToken, ft as PACKAGE_NAME, g as runningJobs, gt as MIN_WORKSPACE_PORT, h as liveUpdateFor, ht as MAX_WORKSPACE_PORT, i as liveJobsFor, in as reviewedRepositories, jn as resolveTarget, l as mergeUpdateInto, lt as workspaceUrl, m as UpdateAlreadyRunningError, mt as DEFAULT_WORKSPACE_PORT, n as deleteReview$1, nn as recentWorkspaces, q as MANAGED_ROOT, rt as ensureServer, tt as bootstrapUrl, u as updateReview, v as recordKissRun, w as record$1, x as runJob, yt as statedWorkspacePort, zn as writeAgentPreference, zt as progressSteps } from "./delete_review-D52wkt66.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";
|