prreviewbuddy 0.49.0 → 0.50.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 +33 -0
- package/dist/{delete_review-BBjXPfMV.js → delete_review-BIXqUnpx.js} +91 -12
- package/dist/main.js +41 -1
- package/dist/server.js +158 -4
- package/package.json +1 -1
- package/static/help.js +1 -0
- package/static/shell.css +112 -8
- package/static/workspace.js +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.50.0
|
|
4
|
+
|
|
5
|
+
**Every review says which commits it covers.** Beside the branch at the top of a review is its
|
|
6
|
+
commit count. Open it to see where your branch split off from the base, every commit in the review,
|
|
7
|
+
and a reminder that uncommitted changes are never included. A review is always the combined change
|
|
8
|
+
across all of those commits, not just the latest one.
|
|
9
|
+
|
|
10
|
+
**Help, in the workspace.** A new **Help** place in the sidebar explains what gets reviewed: how
|
|
11
|
+
the base sets the split point, why your local main and origin/main can give different reviews, and
|
|
12
|
+
how to choose between them. The commit count on a review links to it.
|
|
13
|
+
|
|
14
|
+
**Choosing between local main and origin/main tells you what each would review.** When the two are
|
|
15
|
+
different commits and you have not named a base, PR Review Buddy still asks which one you mean,
|
|
16
|
+
and now lists under each choice how many commits it would review and which ones.
|
|
17
|
+
|
|
18
|
+
**`prreviewbuddy review --help` works.** It used to say `review` does not take `--help`. Every
|
|
19
|
+
command now prints the help, which has a new section on what gets reviewed, with examples.
|
|
20
|
+
|
|
21
|
+
## 0.49.2
|
|
22
|
+
|
|
23
|
+
**Buddy AI remembers which theme you asked in.** Your earlier questions now reach Buddy with the
|
|
24
|
+
theme you had open when you asked them, or a note that they were about the whole change. Asking
|
|
25
|
+
"what is risky here?" in one theme and then "how does that compare?" in another no longer reads to
|
|
26
|
+
Buddy as two questions about the same thing.
|
|
27
|
+
|
|
28
|
+
## 0.49.1
|
|
29
|
+
|
|
30
|
+
**Buddy AI says what your question is about.** A line under **Ask Buddy AI** now reads **Asking
|
|
31
|
+
about: the whole change**, or the name of the theme you have open in the Review Path. Buddy always
|
|
32
|
+
sees the whole change; an open theme tells it where to focus, so "what is the risk here?" is
|
|
33
|
+
answered about that theme. The line used to be a small grey label beside the title, cut short, with
|
|
34
|
+
its meaning only in a tooltip. Theme names are now shown in full.
|
|
35
|
+
|
|
3
36
|
## 0.49.0
|
|
4
37
|
|
|
5
38
|
**Change a review from the review itself.** The **⋯** menu at the top of a review now has
|
|
@@ -1876,6 +1876,11 @@ var AmbiguousRefError = class extends Error {
|
|
|
1876
1876
|
divergence;
|
|
1877
1877
|
/** Whether the name was named by the reviewer or discovered as the default. Changes the wording. */
|
|
1878
1878
|
discovered;
|
|
1879
|
+
/**
|
|
1880
|
+
* What a review against each of the two would contain. Absent until `withReviewRanges` adds it,
|
|
1881
|
+
* which needs the head being reviewed and so cannot happen where the name is resolved.
|
|
1882
|
+
*/
|
|
1883
|
+
ranges;
|
|
1879
1884
|
constructor(detail) {
|
|
1880
1885
|
super(describeAmbiguity(detail));
|
|
1881
1886
|
this.name = "AmbiguousRefError";
|
|
@@ -1884,9 +1889,49 @@ var AmbiguousRefError = class extends Error {
|
|
|
1884
1889
|
this.remote = detail.remote;
|
|
1885
1890
|
if (detail.divergence) this.divergence = detail.divergence;
|
|
1886
1891
|
this.discovered = detail.discovered;
|
|
1892
|
+
if (detail.ranges) this.ranges = detail.ranges;
|
|
1887
1893
|
}
|
|
1888
1894
|
};
|
|
1889
1895
|
/**
|
|
1896
|
+
* The same refusal, now saying what choosing each ref would review.
|
|
1897
|
+
*
|
|
1898
|
+
* Counted from the split point, `git merge-base <ref> <head>`, and not as `<ref>..<head>`: the
|
|
1899
|
+
* review diffs from the merge-base, so this has to walk the same boundary or the refusal and the
|
|
1900
|
+
* review it leads to could disagree about which commits are in it. Added after resolution because
|
|
1901
|
+
* the resolver is shared with the review's own target, which has no head to measure against.
|
|
1902
|
+
*/
|
|
1903
|
+
async function withReviewRanges(error, repoPath, head) {
|
|
1904
|
+
const [local, remote] = await Promise.all([reviewedCommits(repoPath, error.local.ref, head), reviewedCommits(repoPath, error.remote.ref, head)]);
|
|
1905
|
+
return new AmbiguousRefError({
|
|
1906
|
+
requested: error.requested,
|
|
1907
|
+
local: error.local,
|
|
1908
|
+
remote: error.remote,
|
|
1909
|
+
...error.divergence ? { divergence: error.divergence } : {},
|
|
1910
|
+
discovered: error.discovered,
|
|
1911
|
+
ranges: {
|
|
1912
|
+
...local ? { local } : {},
|
|
1913
|
+
...remote ? { remote } : {}
|
|
1914
|
+
}
|
|
1915
|
+
});
|
|
1916
|
+
}
|
|
1917
|
+
async function reviewedCommits(repoPath, ref, head) {
|
|
1918
|
+
try {
|
|
1919
|
+
const split = (await git(repoPath, [
|
|
1920
|
+
"merge-base",
|
|
1921
|
+
ref,
|
|
1922
|
+
head
|
|
1923
|
+
])).trim();
|
|
1924
|
+
if (!split) return void 0;
|
|
1925
|
+
return (await git(repoPath, [
|
|
1926
|
+
"rev-list",
|
|
1927
|
+
"--abbrev-commit",
|
|
1928
|
+
`${split}..${head}`
|
|
1929
|
+
])).split("\n").filter(Boolean);
|
|
1930
|
+
} catch {
|
|
1931
|
+
return;
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
/**
|
|
1890
1935
|
* `refs/heads/feat/foo` and `refs/remotes/origin/feat/foo` are both `feat/foo`.
|
|
1891
1936
|
*
|
|
1892
1937
|
* Structural rather than asked of git: the first path segment under `refs/remotes/` is the
|
|
@@ -1996,10 +2041,19 @@ function describeAmbiguity(detail) {
|
|
|
1996
2041
|
...refs.map((one) => ` ${one.ref.padEnd(width)} ${one.sha.slice(0, 7)}`),
|
|
1997
2042
|
...detail.divergence ? ["", divergenceLine(name, shorthandOf(detail.remote.ref), detail.divergence)] : [],
|
|
1998
2043
|
"",
|
|
2044
|
+
...detail.ranges ? [SPLIT_POINT, ""] : [],
|
|
1999
2045
|
"Name the one you mean:",
|
|
2000
|
-
...
|
|
2046
|
+
...[[detail.local, detail.ranges?.local], [detail.remote, detail.ranges?.remote]].flatMap(([one, commits]) => [` prreviewbuddy review --base ${shorthandOf(one.ref)}`, ...commits ? [` ${rangeLine(commits)}`] : []])
|
|
2001
2047
|
].join("\n");
|
|
2002
2048
|
}
|
|
2049
|
+
var SPLIT_POINT = "The base determines the split point. PR Review Buddy reviews the changes on your branch since that point.";
|
|
2050
|
+
/** "changes across", because a review is one combined diff and not a review of each commit. */
|
|
2051
|
+
function rangeLine(commits) {
|
|
2052
|
+
if (commits.length === 0) return "no commits: nothing on your branch is new against this base";
|
|
2053
|
+
const listed = commits.slice(0, 10).join(" ");
|
|
2054
|
+
const more = commits.length > 10 ? ` and ${commits.length - 10} more` : "";
|
|
2055
|
+
return `changes across ${commits.length} commit${commits.length === 1 ? "" : "s"}: ${listed}${more}`;
|
|
2056
|
+
}
|
|
2003
2057
|
/**
|
|
2004
2058
|
* How a person spells this ref: the shortest form that still says which one.
|
|
2005
2059
|
*
|
|
@@ -2176,7 +2230,7 @@ async function buildChangeSet(options) {
|
|
|
2176
2230
|
disagreement(files.length, base.display, options.expected);
|
|
2177
2231
|
const blobShas = await headBlobShas(repoPath);
|
|
2178
2232
|
for (const file of files) file.sha = blobShas.get(file.name) ?? "";
|
|
2179
|
-
const { subjects, authors } = await commitLog(repoPath, base.exact && !await refExists(repoPath, mergeBase) ? "HEAD" : `${mergeBase}..HEAD`);
|
|
2233
|
+
const { subjects, authors, commits } = await commitLog(repoPath, base.exact && !await refExists(repoPath, mergeBase) ? "HEAD" : `${mergeBase}..HEAD`);
|
|
2180
2234
|
return {
|
|
2181
2235
|
data: {
|
|
2182
2236
|
pullRequest: {
|
|
@@ -2205,7 +2259,8 @@ async function buildChangeSet(options) {
|
|
|
2205
2259
|
includesUncommitted: false,
|
|
2206
2260
|
isLinkedWorktree,
|
|
2207
2261
|
checkoutName: basename(repoPath),
|
|
2208
|
-
authors
|
|
2262
|
+
authors,
|
|
2263
|
+
commits
|
|
2209
2264
|
};
|
|
2210
2265
|
}
|
|
2211
2266
|
/**
|
|
@@ -2316,21 +2371,22 @@ async function commitLog(repoPath, range) {
|
|
|
2316
2371
|
const out = await git(repoPath, [
|
|
2317
2372
|
"log",
|
|
2318
2373
|
"--reverse",
|
|
2319
|
-
"--format=%an%x1f%s",
|
|
2374
|
+
"--format=%H%x1f%an%x1f%s",
|
|
2320
2375
|
range
|
|
2321
2376
|
]);
|
|
2322
2377
|
const subjects = [];
|
|
2323
2378
|
const counts = /* @__PURE__ */ new Map();
|
|
2379
|
+
const commits = [];
|
|
2324
2380
|
for (const line of out.split("\n")) {
|
|
2325
|
-
const
|
|
2326
|
-
if (
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
if (
|
|
2330
|
-
if (name) counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
2381
|
+
const [sha, name, subject] = line.split("");
|
|
2382
|
+
if (!sha || name === void 0) continue;
|
|
2383
|
+
commits.push(sha.trim());
|
|
2384
|
+
if (subject?.trim()) subjects.push(subject.trim());
|
|
2385
|
+
if (name.trim()) counts.set(name.trim(), (counts.get(name.trim()) ?? 0) + 1);
|
|
2331
2386
|
}
|
|
2332
2387
|
return {
|
|
2333
2388
|
subjects,
|
|
2389
|
+
commits: commits.reverse(),
|
|
2334
2390
|
authors: [...counts].map(([name, commits]) => ({
|
|
2335
2391
|
name,
|
|
2336
2392
|
commits
|
|
@@ -2746,8 +2802,14 @@ async function peel(repoPath, named) {
|
|
|
2746
2802
|
async function resolveTarget(input) {
|
|
2747
2803
|
const root = await repositoryRoot(input.repoPath);
|
|
2748
2804
|
if (input.commitRef) return commitTarget(root, input.commitRef);
|
|
2749
|
-
|
|
2750
|
-
|
|
2805
|
+
try {
|
|
2806
|
+
if (input.base) await verifyBase(root, input.base);
|
|
2807
|
+
else await verifyDefaultBase(root);
|
|
2808
|
+
} catch (error) {
|
|
2809
|
+
if (!(error instanceof AmbiguousRefError)) throw error;
|
|
2810
|
+
const head = await headToMeasure(root, input);
|
|
2811
|
+
throw head ? await withReviewRanges(error, root, head) : error;
|
|
2812
|
+
}
|
|
2751
2813
|
const named = input.base ? { base: input.base } : {};
|
|
2752
2814
|
if (input.prUrl) {
|
|
2753
2815
|
if (!input.resolveRequest) throw new TargetError(`${input.prUrl} is a pull request, but nothing here can look one up. Check the request out locally and review the branch instead.`);
|
|
@@ -2896,6 +2958,23 @@ async function verifyBase(root, base) {
|
|
|
2896
2958
|
throw new TargetError(`There is nothing called \`${base}\` in this repository to compare against. Tried ${candidateRefs(base).map((one) => `\`${one}\``).join(" and ")}. Run \`git fetch\` if it is on the remote and this clone has not seen it yet.`);
|
|
2897
2959
|
}
|
|
2898
2960
|
/**
|
|
2961
|
+
* The commit the review would be of, as far as it is known before the target is resolved.
|
|
2962
|
+
*
|
|
2963
|
+
* A pull request's head is not known until the forge is asked, and the refusal exists to come
|
|
2964
|
+
* before that, so it gets none and its refusal lists no ranges. A named branch is resolved rather
|
|
2965
|
+
* than handed to git as typed, because a name that is itself ambiguous would be settled by git's own
|
|
2966
|
+
* preference, which is the guess this module refuses to make.
|
|
2967
|
+
*/
|
|
2968
|
+
async function headToMeasure(root, input) {
|
|
2969
|
+
if (input.prUrl) return void 0;
|
|
2970
|
+
if (!input.branchRef) return "HEAD";
|
|
2971
|
+
try {
|
|
2972
|
+
return (await resolveBranchRef(root, input.branchRef))?.sha;
|
|
2973
|
+
} catch {
|
|
2974
|
+
return;
|
|
2975
|
+
}
|
|
2976
|
+
}
|
|
2977
|
+
/**
|
|
2899
2978
|
* The same check for the base nobody named, which is the one the reported failure came down.
|
|
2900
2979
|
*
|
|
2901
2980
|
* A bare `prreviewbuddy review` has no base to verify, so this ran nothing and the refusal landed
|
package/dist/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $t as matchingWorkspaceIds, Bn as writeAgentPreference, Bt as progressSteps, Ct as forgeResolver, E as telemetryUploadConsent, Fn as git, Ft as loadJob, Gn as agentById, Gt as followedRefName, Hn as STORE_ROOT, Ht as clearClaim, In as resolveAgent, J as readMarker, Kt as groupByLineage, Ln as resolveModel, Lt as PHASES, Mn as resolveTarget, Nn as displayRef, Ot as checkReview, Pt as isTerminal, Qt as loadWorkspace, S as startJob, T as recordTelemetryUploadConsent, Un as AGENT_IDS, Ut as driverGone, Vn as CONFIG_PATH, Vt as purposeOf, Wn as DEFAULT_AGENT_ID, Wt as isClaimed, X as modelHelpLines, Xt as lineageKeyFor, Y as removeWorktree, Z as relativeTime, _t as MIN_WORKSPACE_PORT, a as wasBlocked, an as reviewedRepositories, b as reanalyseReview, bt as statedWorkspacePort, en as mutateWorkspace, et as queueForReview, ft as BUILD_VERSION, g as runningJobs, gt as MAX_WORKSPACE_PORT, h as liveUpdateFor, ht as DEFAULT_WORKSPACE_PORT, i as liveJobsFor, it as ensureServer, jt as allJobs, l as mergeUpdateInto, lt as stopServer, m as UpdateAlreadyRunningError, n as deleteReview$1, nt as bootstrapUrl, on as summarise, ot as reviewsUrl, pt as PACKAGE_NAME, q as MANAGED_ROOT, qn as detectAgents, rn as recentWorkspaces, tn as positionInLineage, tt as readIndexToken, u as updateReview, ut as workspaceUrl, v as recordKissRun, vt as parseWorkspacePort, w as record$1, x as runJob, xt as writePortPreference, zn as readAgentPreference } from "./delete_review-
|
|
2
|
+
import { $t as matchingWorkspaceIds, Bn as writeAgentPreference, Bt as progressSteps, Ct as forgeResolver, E as telemetryUploadConsent, Fn as git, Ft as loadJob, Gn as agentById, Gt as followedRefName, Hn as STORE_ROOT, Ht as clearClaim, In as resolveAgent, J as readMarker, Kt as groupByLineage, Ln as resolveModel, Lt as PHASES, Mn as resolveTarget, Nn as displayRef, Ot as checkReview, Pt as isTerminal, Qt as loadWorkspace, S as startJob, T as recordTelemetryUploadConsent, Un as AGENT_IDS, Ut as driverGone, Vn as CONFIG_PATH, Vt as purposeOf, Wn as DEFAULT_AGENT_ID, Wt as isClaimed, X as modelHelpLines, Xt as lineageKeyFor, Y as removeWorktree, Z as relativeTime, _t as MIN_WORKSPACE_PORT, a as wasBlocked, an as reviewedRepositories, b as reanalyseReview, bt as statedWorkspacePort, en as mutateWorkspace, et as queueForReview, ft as BUILD_VERSION, g as runningJobs, gt as MAX_WORKSPACE_PORT, h as liveUpdateFor, ht as DEFAULT_WORKSPACE_PORT, i as liveJobsFor, it as ensureServer, jt as allJobs, l as mergeUpdateInto, lt as stopServer, m as UpdateAlreadyRunningError, n as deleteReview$1, nt as bootstrapUrl, on as summarise, ot as reviewsUrl, pt as PACKAGE_NAME, q as MANAGED_ROOT, qn as detectAgents, rn as recentWorkspaces, tn as positionInLineage, tt as readIndexToken, u as updateReview, ut as workspaceUrl, v as recordKissRun, vt as parseWorkspacePort, w as record$1, x as runJob, xt as writePortPreference, zn as readAgentPreference } from "./delete_review-BIXqUnpx.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";
|
|
@@ -115,6 +115,7 @@ function parse(argv) {
|
|
|
115
115
|
name: "error",
|
|
116
116
|
message: unknownCommand(head)
|
|
117
117
|
};
|
|
118
|
+
if (rest.includes("--help") || rest.includes("-h")) return { name: "help" };
|
|
118
119
|
const values = {};
|
|
119
120
|
const flags = /* @__PURE__ */ new Set();
|
|
120
121
|
const positional = [];
|
|
@@ -1064,6 +1065,45 @@ running the same command again carries each one on from where it got to.
|
|
|
1064
1065
|
|
|
1065
1066
|
Reviews can also be deleted from the list in your browser, one at a time or a whole branch at once.
|
|
1066
1067
|
|
|
1068
|
+
What gets reviewed
|
|
1069
|
+
|
|
1070
|
+
A review is the combined change between a base and the branch you review, as one diff. It is not
|
|
1071
|
+
just the latest commit. The base determines the split point (git's merge-base of the base and your
|
|
1072
|
+
branch), and PR Review Buddy reviews the changes on your branch since that point.
|
|
1073
|
+
|
|
1074
|
+
main: A---B---C
|
|
1075
|
+
\\
|
|
1076
|
+
feature: D---E
|
|
1077
|
+
|
|
1078
|
+
prreviewbuddy review --base main reviews D and E together
|
|
1079
|
+
|
|
1080
|
+
C is on main but not on your branch, so it is not part of the review, and the review does not show
|
|
1081
|
+
its changes as removed. Commits already in the base are never reviewed again.
|
|
1082
|
+
|
|
1083
|
+
When your local main and origin/main are different commits, which one you name moves the split
|
|
1084
|
+
point:
|
|
1085
|
+
|
|
1086
|
+
origin/main: A---B
|
|
1087
|
+
\\
|
|
1088
|
+
local main: C---D
|
|
1089
|
+
\\
|
|
1090
|
+
feature: E
|
|
1091
|
+
|
|
1092
|
+
--base refs/heads/main reviews E
|
|
1093
|
+
--base origin/main reviews C, D and E together
|
|
1094
|
+
|
|
1095
|
+
Without --base, the repository's default branch is the base. If its local and remote copies are
|
|
1096
|
+
different commits, PR Review Buddy asks which one you mean and says what each would review.
|
|
1097
|
+
Uncommitted changes are never included: a review is a fixed snapshot of your commits.
|
|
1098
|
+
|
|
1099
|
+
Common examples
|
|
1100
|
+
|
|
1101
|
+
prreviewbuddy review --base refs/heads/main
|
|
1102
|
+
everything on this branch since it left your local main
|
|
1103
|
+
prreviewbuddy review --base origin/main
|
|
1104
|
+
everything on this branch not yet on origin/main
|
|
1105
|
+
prreviewbuddy review --commit <commit> one commit, against its parent
|
|
1106
|
+
|
|
1067
1107
|
There is no account and no API key. PR Review Buddy uses a coding agent installed on your machine
|
|
1068
1108
|
and that agent's existing authentication, and nothing here ever asks you for a credential.
|
|
1069
1109
|
|
package/dist/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as compactQueue, A as createPrState, An as processDiscussion, At as reviewedShaOf, B as toneOf, Bn as writeAgentPreference, Bt as progressSteps, C as readEvents, Cn as readQueue, D as announceJob, Dn as issuesOutstanding, Dt as checkCodeFreshness, E as telemetryUploadConsent, En as isQuestionOutstanding, Et as fillFileUrlTemplate, F as markAllRead, Fn as git, Ft as loadJob, G as extractJsonText, Gt as followedRefName, H as withUsageRecorded, Hn as STORE_ROOT, I as markRead, It as saveJob, J as readMarker, Jn as AgentCancelledError, Jt as indexReviewGroups, K as ReviewBeingDeletedError, Kn as agentFor, Kt as groupByLineage, L as pruneNotifications, Ln as resolveModel, M as eventName, Mt as endedAt, N as headline, Nt as fail, O as branchOf, On as questionsOutstanding, Ot as checkReview, P as listNotifications, Pn as isCommitReview, Pt as isTerminal, Q as activateQueued, Qt as loadWorkspace, R as readNotification, Rn as clearAgentPreference, Rt as isLiveJob, Sn as queueStamp, St as claimRequestUrl, T as recordTelemetryUploadConsent, Tn as isIssueOutstanding, Tt as remoteHost, U as EXPLAIN_SIMPLY_PROMPT, Un as AGENT_IDS, V as unreadCount$1, Vt as purposeOf, W as asString, Wt as isClaimed, Y as removeWorktree, Yn as AgentUnavailableError, Yt as latestKissRun, Z as relativeTime$1, Zt as lineagePosition, _ as agentEnvOf, _n as parseLifecycle, _t as MIN_WORKSPACE_PORT, a as wasBlocked, at as readServerRecord, bn as queueAddMany, bt as statedWorkspacePort, c as RefreshUnavailableError, cn as workspaceRevision, ct as spawnServer, d as refreshPrContext, dn as activityLabel, dt as writeServerRecord, en as mutateWorkspace, f as isUnchanged, fn as isLifecycle, ft as BUILD_VERSION, gn as offersLifecycle, gt as MAX_WORKSPACE_PORT, h as liveUpdateFor, hn as lifecyclePill, ht as DEFAULT_WORKSPACE_PORT, i as liveJobsFor, in as reviewedCommit, j as createPrUpdate, jn as describeAuthorship, jt as allJobs, k as subjectOf, kn as reviewerDispositions, kt as followedBranch, l as mergeUpdateInto, ln as workspaceStamps, m as UpdateAlreadyRunningError, mn as lifecycleChip, mt as feedbackUrl, n as deleteReview, nn as previousKissResult, o as discardJob, p as askCheckout, pn as lifecycleAction, q as MANAGED_ROOT, qt as indexKeptIds, r as lineageIds, rn as recentWorkspaces, rt as clearServerRecord, s as FETCH_TIMEOUT_MS, sn as touchWorkspace, st as serverEntryExists, t as deleteLineage, tt as readIndexToken, u as updateReview, un as LIFECYCLES, vn as sectionOf, vt as parseWorkspacePort, w as record, wn as doneVerb, wt as forgeFor, x as runJob, xn as queueRemove, xt as writePortPreference, y as startKissJob, yn as queueAdd, yt as resolveWorkspacePort, z as removeNotification, zn as readAgentPreference, zt as phasesFor } from "./delete_review-
|
|
1
|
+
import { $ as compactQueue, A as createPrState, An as processDiscussion, At as reviewedShaOf, B as toneOf, Bn as writeAgentPreference, Bt as progressSteps, C as readEvents, Cn as readQueue, D as announceJob, Dn as issuesOutstanding, Dt as checkCodeFreshness, E as telemetryUploadConsent, En as isQuestionOutstanding, Et as fillFileUrlTemplate, F as markAllRead, Fn as git, Ft as loadJob, G as extractJsonText, Gt as followedRefName, H as withUsageRecorded, Hn as STORE_ROOT, I as markRead, It as saveJob, J as readMarker, Jn as AgentCancelledError, Jt as indexReviewGroups, K as ReviewBeingDeletedError, Kn as agentFor, Kt as groupByLineage, L as pruneNotifications, Ln as resolveModel, M as eventName, Mt as endedAt, N as headline, Nt as fail, O as branchOf, On as questionsOutstanding, Ot as checkReview, P as listNotifications, Pn as isCommitReview, Pt as isTerminal, Q as activateQueued, Qt as loadWorkspace, R as readNotification, Rn as clearAgentPreference, Rt as isLiveJob, Sn as queueStamp, St as claimRequestUrl, T as recordTelemetryUploadConsent, Tn as isIssueOutstanding, Tt as remoteHost, U as EXPLAIN_SIMPLY_PROMPT, Un as AGENT_IDS, V as unreadCount$1, Vt as purposeOf, W as asString, Wt as isClaimed, Y as removeWorktree, Yn as AgentUnavailableError, Yt as latestKissRun, Z as relativeTime$1, Zt as lineagePosition, _ as agentEnvOf, _n as parseLifecycle, _t as MIN_WORKSPACE_PORT, a as wasBlocked, at as readServerRecord, bn as queueAddMany, bt as statedWorkspacePort, c as RefreshUnavailableError, cn as workspaceRevision, ct as spawnServer, d as refreshPrContext, dn as activityLabel, dt as writeServerRecord, en as mutateWorkspace, f as isUnchanged, fn as isLifecycle, ft as BUILD_VERSION, gn as offersLifecycle, gt as MAX_WORKSPACE_PORT, h as liveUpdateFor, hn as lifecyclePill, ht as DEFAULT_WORKSPACE_PORT, i as liveJobsFor, in as reviewedCommit, j as createPrUpdate, jn as describeAuthorship, jt as allJobs, k as subjectOf, kn as reviewerDispositions, kt as followedBranch, l as mergeUpdateInto, ln as workspaceStamps, m as UpdateAlreadyRunningError, mn as lifecycleChip, mt as feedbackUrl, n as deleteReview, nn as previousKissResult, o as discardJob, p as askCheckout, pn as lifecycleAction, q as MANAGED_ROOT, qt as indexKeptIds, r as lineageIds, rn as recentWorkspaces, rt as clearServerRecord, s as FETCH_TIMEOUT_MS, sn as touchWorkspace, st as serverEntryExists, t as deleteLineage, tt as readIndexToken, u as updateReview, un as LIFECYCLES, vn as sectionOf, vt as parseWorkspacePort, w as record, wn as doneVerb, wt as forgeFor, x as runJob, xn as queueRemove, xt as writePortPreference, y as startKissJob, yn as queueAdd, yt as resolveWorkspacePort, z as removeNotification, zn as readAgentPreference, zt as phasesFor } from "./delete_review-BIXqUnpx.js";
|
|
2
2
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { createHash, timingSafeEqual } from "node:crypto";
|
|
@@ -371,6 +371,7 @@ var PATHS = {
|
|
|
371
371
|
reviews: "<path d=\"M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01\"/>",
|
|
372
372
|
notifications: "<path d=\"M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9\"/><path d=\"M13.7 21a2 2 0 0 1-3.4 0\"/>",
|
|
373
373
|
settings: "<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z\"/>",
|
|
374
|
+
help: "<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M9.1 9a3 3 0 0 1 5.8 1c0 2-3 3-3 3\"/><path d=\"M12 17h.01\"/>",
|
|
374
375
|
feedback: "<path d=\"m22 2-7 20-4-9-9-4z\"/><path d=\"M22 2 11 13\"/>",
|
|
375
376
|
stop: "<path d=\"M12 2v10\"/><path d=\"M18.4 6.6a9 9 0 1 1-12.8 0\"/>",
|
|
376
377
|
restart: "<path d=\"M21 12a9 9 0 1 1-2.64-6.36\"/><path d=\"M21 3v6h-6\"/>"
|
|
@@ -444,6 +445,12 @@ var WORKSPACE_PLACES = [
|
|
|
444
445
|
href: "/settings",
|
|
445
446
|
icon: "settings",
|
|
446
447
|
label: "Settings"
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
place: "help",
|
|
451
|
+
href: "/help",
|
|
452
|
+
icon: "help",
|
|
453
|
+
label: "Help"
|
|
447
454
|
}
|
|
448
455
|
];
|
|
449
456
|
/**
|
|
@@ -5011,6 +5018,43 @@ function renderSubject(changeSet) {
|
|
|
5011
5018
|
<span>${against}</span>`;
|
|
5012
5019
|
}
|
|
5013
5020
|
/**
|
|
5021
|
+
* Which commits this review is of, opened from the bar beside what it compares.
|
|
5022
|
+
*
|
|
5023
|
+
* Beside `.prb-change-ref` rather than inside it, because that element clips to keep the bar one
|
|
5024
|
+
* line and a panel inside it would be cut off. The pill's own label is a fact (how many commits),
|
|
5025
|
+
* so the bar gains information even closed. Facts only, and about this review: the general
|
|
5026
|
+
* explanation is the Help page's, linked when there is a server to answer the link.
|
|
5027
|
+
*
|
|
5028
|
+
* The count comes from the stored commit list, or from the authors' counts for a review made before
|
|
5029
|
+
* the list was recorded, which then says how many without listing them. Neither: no count at all,
|
|
5030
|
+
* never a zero.
|
|
5031
|
+
*/
|
|
5032
|
+
function renderRange(changeSet, live) {
|
|
5033
|
+
const commits = changeSet.commits;
|
|
5034
|
+
const count = commits?.length ?? changeSet.authors?.reduce((sum, author) => sum + author.commits, 0);
|
|
5035
|
+
const counted = count !== void 0 && count > 0 ? count : void 0;
|
|
5036
|
+
const plural = (n) => `${n} commit${n === 1 ? "" : "s"}`;
|
|
5037
|
+
const sha = (value) => `<code>${escapeHtml$1(value.slice(0, 7))}</code>`;
|
|
5038
|
+
const lines = [];
|
|
5039
|
+
if (changeSet.targetType === "commit") {
|
|
5040
|
+
const parent = changeSet.parentSha;
|
|
5041
|
+
const against = !parent ? "the empty tree" : `its ${(changeSet.parentCount ?? 1) > 1 ? "first parent" : "parent"} ${sha(parent)}`;
|
|
5042
|
+
lines.push(`The change commit ${sha(changeSet.data.pullRequest.head.sha)} made, compared against ${against}.`);
|
|
5043
|
+
} else {
|
|
5044
|
+
lines.push(changeSet.mergeBase ? `Compared against <code>${escapeHtml$1(changeSet.baseRef)}</code>, from where this branch split off at ${sha(changeSet.mergeBase)}.` : `Compared against <code>${escapeHtml$1(changeSet.baseRef)}</code>.`);
|
|
5045
|
+
if (commits && commits.length > 0) {
|
|
5046
|
+
const more = commits.length > 10 ? ` and ${commits.length - 10} more` : "";
|
|
5047
|
+
lines.push(`Changes across ${plural(commits.length)}: ${commits.slice(0, 10).map(sha).join(" ")}${more}.`);
|
|
5048
|
+
} else if (counted) lines.push(`Changes across ${plural(counted)}.`);
|
|
5049
|
+
}
|
|
5050
|
+
lines.push(changeSet.includesUncommitted ? "This review also read uncommitted changes in the working tree." : "Uncommitted changes are never part of a review.");
|
|
5051
|
+
if (live) lines.push("<a href=\"/help#what-gets-reviewed\">How review ranges work</a>");
|
|
5052
|
+
return `<details class="prb-range" data-range-details>
|
|
5053
|
+
<summary class="prb-range-summary">${changeSet.targetType === "commit" ? "1 commit" : counted ? plural(counted) : "Range"}</summary>
|
|
5054
|
+
<div class="prb-range-panel">${lines.map((line) => `<p>${line}</p>`).join("")}</div>
|
|
5055
|
+
</details>`;
|
|
5056
|
+
}
|
|
5057
|
+
/**
|
|
5014
5058
|
* The review's own bar, below the global strip.
|
|
5015
5059
|
*
|
|
5016
5060
|
* Everything here is about this review and nothing else is: the strip above carries the workspace's
|
|
@@ -5031,6 +5075,7 @@ function renderReviewBar(view, freshness) {
|
|
|
5031
5075
|
${changeSet.includesUncommitted ? "<span class=\"prb-file-status\">+ working tree</span>" : ""}
|
|
5032
5076
|
${renderAuthor(view)}
|
|
5033
5077
|
</span>
|
|
5078
|
+
${renderRange(changeSet, Boolean(view.token))}
|
|
5034
5079
|
<div class="prb-header-stats">
|
|
5035
5080
|
<span>${fileCount} file${fileCount === 1 ? "" : "s"}</span>
|
|
5036
5081
|
<span><span class="prb-add">+${additions}</span> <span class="prb-del">−${deletions}</span></span>
|
|
@@ -5635,8 +5680,10 @@ function renderAsk(view, sections, paused = false) {
|
|
|
5635
5680
|
tabindex="0"
|
|
5636
5681
|
></div>
|
|
5637
5682
|
<div class="prb-ask-header">
|
|
5638
|
-
<
|
|
5639
|
-
|
|
5683
|
+
<hgroup class="prb-ask-heading">
|
|
5684
|
+
<h2>Ask Buddy AI</h2>
|
|
5685
|
+
<p class="prb-ask-scope">Asking about: <span data-ask-scope>the whole change</span></p>
|
|
5686
|
+
</hgroup>
|
|
5640
5687
|
${renderFocusToggle("buddy", "Buddy AI")}
|
|
5641
5688
|
<button type="button" class="prb-ask-hide" data-ask-toggle aria-controls="prb-ask" aria-label="Hide Buddy AI">${ASK_HIDE_ICON}</button>
|
|
5642
5689
|
</div>
|
|
@@ -7900,6 +7947,87 @@ function defaultFetchDeps() {
|
|
|
7900
7947
|
};
|
|
7901
7948
|
}
|
|
7902
7949
|
//#endregion
|
|
7950
|
+
//#region ../../packages/review-harness/src/workspace/help_page.ts
|
|
7951
|
+
/** The diagrams are text on purpose: they are the same ones `prreviewbuddy --help` prints. */
|
|
7952
|
+
var TOPICS = [{
|
|
7953
|
+
id: "what-gets-reviewed",
|
|
7954
|
+
title: "What gets reviewed",
|
|
7955
|
+
body: `<p>A review is the combined change between a base and the branch you review, shown as one
|
|
7956
|
+
diff. It is not just the latest commit. The base determines the split point: the commit where
|
|
7957
|
+
your branch left it (git calls this the merge-base). PR Review Buddy reviews the changes on your
|
|
7958
|
+
branch since that point.</p>
|
|
7959
|
+
<pre class="prb-help-diagram">main: A---B---C
|
|
7960
|
+
\\
|
|
7961
|
+
feature: D---E</pre>
|
|
7962
|
+
<p>Reviewing <code>feature</code> against <code>main</code> covers D and E together. C is on
|
|
7963
|
+
main but not on your branch, so it is not part of the review, and the review does not show its
|
|
7964
|
+
changes as removed. Commits already in the base are never reviewed again.</p>
|
|
7965
|
+
|
|
7966
|
+
<h3>Local main and origin/main</h3>
|
|
7967
|
+
<p>Your local <code>main</code> can hold commits that are not on <code>origin/main</code> yet,
|
|
7968
|
+
such as a merge you have not pushed. When the two are different commits, the one you choose
|
|
7969
|
+
moves the split point.</p>
|
|
7970
|
+
<pre class="prb-help-diagram">origin/main: A---B
|
|
7971
|
+
\\
|
|
7972
|
+
local main: C---D
|
|
7973
|
+
\\
|
|
7974
|
+
feature: E</pre>
|
|
7975
|
+
<ul>
|
|
7976
|
+
<li>Against local <code>main</code>, the review covers E.</li>
|
|
7977
|
+
<li>Against <code>origin/main</code>, it covers C, D and E together.</li>
|
|
7978
|
+
</ul>
|
|
7979
|
+
<p>When nobody names a base and the two differ, PR Review Buddy does not guess. It asks which
|
|
7980
|
+
one you mean and says which commits each would review.</p>
|
|
7981
|
+
|
|
7982
|
+
<h3>Uncommitted changes</h3>
|
|
7983
|
+
<p>Never included. A review is a fixed snapshot of your commits, made in a checkout of its own,
|
|
7984
|
+
so work you have not committed is not part of it.</p>
|
|
7985
|
+
|
|
7986
|
+
<h3>Choosing a base</h3>
|
|
7987
|
+
<p>The base is chosen when the review is made, in the terminal:</p>
|
|
7988
|
+
<ul>
|
|
7989
|
+
<li><code>prreviewbuddy review --base refs/heads/main</code> for everything on your branch since it left your local main</li>
|
|
7990
|
+
<li><code>prreviewbuddy review --base origin/main</code> for everything on your branch not yet on origin/main</li>
|
|
7991
|
+
<li><code>prreviewbuddy review --commit <commit></code> for one commit, against its parent</li>
|
|
7992
|
+
</ul>
|
|
7993
|
+
<p>Every review shows its own range. The commit count beside the branch name at the top of a
|
|
7994
|
+
review opens its split point and the commits it covers.</p>`
|
|
7995
|
+
}];
|
|
7996
|
+
function renderHelpPage(view) {
|
|
7997
|
+
return `<!doctype html>
|
|
7998
|
+
<html lang="en"${themeAttribute(view.theme)}>
|
|
7999
|
+
<head>
|
|
8000
|
+
<meta charset="utf-8">
|
|
8001
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
8002
|
+
<title>Help · PR Review Buddy</title>
|
|
8003
|
+
<link rel="icon" type="image/png" href="/assets/icon128.png">
|
|
8004
|
+
<link rel="stylesheet" href="/assets/sidebar.css">
|
|
8005
|
+
<link rel="stylesheet" href="/assets/shell.css">
|
|
8006
|
+
</head>
|
|
8007
|
+
<body class="prb-index-body" data-way-back="${escapeHtml$1(wayBackSentence())}">
|
|
8008
|
+
${renderGlobalBar({
|
|
8009
|
+
current: "help",
|
|
8010
|
+
unread: view.unreadNotifications ?? 0,
|
|
8011
|
+
driving: view.driving
|
|
8012
|
+
})}
|
|
8013
|
+
${renderContextBar("Help", "")}
|
|
8014
|
+
<div class="prb-shell">
|
|
8015
|
+
${renderWorkspaceRail({
|
|
8016
|
+
current: "help",
|
|
8017
|
+
unread: view.unreadNotifications ?? 0
|
|
8018
|
+
})}
|
|
8019
|
+
<main class="prb-index prb-help">
|
|
8020
|
+
${TOPICS.map((topic) => `<section class="prb-help-topic" id="${topic.id}">
|
|
8021
|
+
<h2>${escapeHtml$1(topic.title)}</h2>
|
|
8022
|
+
${topic.body}
|
|
8023
|
+
</section>`).join("")}
|
|
8024
|
+
</main>
|
|
8025
|
+
</div>
|
|
8026
|
+
<script src="/assets/help.js" type="module"><\/script>
|
|
8027
|
+
</body>
|
|
8028
|
+
</html>`;
|
|
8029
|
+
}
|
|
8030
|
+
//#endregion
|
|
7903
8031
|
//#region ../../packages/review-harness/src/workspace/notifications_page.ts
|
|
7904
8032
|
function renderNotificationsPage(view) {
|
|
7905
8033
|
const unread = view.notifications.filter((notification) => notification.readAt === void 0).length;
|
|
@@ -8250,12 +8378,25 @@ function buildPrompt$2(workspace, question, sectionId, cwd) {
|
|
|
8250
8378
|
...recent.length > 0 ? [
|
|
8251
8379
|
"---",
|
|
8252
8380
|
"EARLIER IN THIS CONVERSATION:",
|
|
8253
|
-
recent.map((entry) => `Q: ${entry.question}\nA: ${entry.answer}`).join("\n\n")
|
|
8381
|
+
recent.map((entry) => `Q ${askedWhere(workspace, entry.sectionId)}: ${entry.question}\nA: ${entry.answer}`).join("\n\n")
|
|
8254
8382
|
] : [],
|
|
8255
8383
|
"---",
|
|
8256
8384
|
`QUESTION: ${question}`
|
|
8257
8385
|
].join("\n");
|
|
8258
8386
|
}
|
|
8387
|
+
/**
|
|
8388
|
+
* Where an earlier question was asked, which the question alone does not say.
|
|
8389
|
+
*
|
|
8390
|
+
* "What is risky here?" in one theme followed by "and how does that compare?" in another reads, as
|
|
8391
|
+
* bare text, as two questions about the same thing. A theme that has since gone, because the
|
|
8392
|
+
* review was updated, is said to have gone rather than dropped: dropping it would present a
|
|
8393
|
+
* theme's question as one about the whole change.
|
|
8394
|
+
*/
|
|
8395
|
+
function askedWhere(workspace, sectionId) {
|
|
8396
|
+
if (sectionId === null) return "(asked about the whole change)";
|
|
8397
|
+
const section = workspace.session.result?.sections.find((s) => s.id === sectionId);
|
|
8398
|
+
return section ? `(asked while reading the "${section.title}" theme)` : "(asked while reading a theme that is no longer in the review)";
|
|
8399
|
+
}
|
|
8259
8400
|
//#endregion
|
|
8260
8401
|
//#region ../../packages/review-harness/src/workspace/assistant_runs.ts
|
|
8261
8402
|
var RUN_KINDS = ["ask", "diagram"];
|
|
@@ -9263,6 +9404,7 @@ async function handle(req, res, options) {
|
|
|
9263
9404
|
if (url.pathname === "/open") return handleOpen(req, res, url.searchParams, options.indexToken);
|
|
9264
9405
|
if (url.pathname === "/settings") return void handleSettings(req, res, url.searchParams, options.indexToken);
|
|
9265
9406
|
if (url.pathname === "/notifications") return void handleNotifications(req, res, url.searchParams, options.indexToken);
|
|
9407
|
+
if (url.pathname === "/help") return void handleHelp(req, res, url.searchParams, options.indexToken);
|
|
9266
9408
|
if (url.pathname === "/notifications/open") return handleNotificationOpen(req, res, url.searchParams, options.indexToken);
|
|
9267
9409
|
if (url.pathname === "/notifications/recent") return handleRecentNotifications(req, res, url.searchParams, options.indexToken);
|
|
9268
9410
|
if (url.pathname === "/pin") return handlePin(req, res, options.indexToken);
|
|
@@ -9472,6 +9614,18 @@ async function handleSettings(req, res, params, indexToken) {
|
|
|
9472
9614
|
}), indexCookieHeader(indexToken));
|
|
9473
9615
|
}
|
|
9474
9616
|
/**
|
|
9617
|
+
* Help. Static, but still behind the index's credential like every other workspace place: its
|
|
9618
|
+
* rail and strip carry the unread count, which is this machine's state.
|
|
9619
|
+
*/
|
|
9620
|
+
function handleHelp(req, res, params, indexToken) {
|
|
9621
|
+
if (!indexAuthorised(req, params, indexToken)) return refuseIndex(req, res);
|
|
9622
|
+
sendHtml(res, 200, renderHelpPage({
|
|
9623
|
+
unreadNotifications: unreadCount$1(),
|
|
9624
|
+
driving: isDriving(),
|
|
9625
|
+
theme: readPreferences().theme
|
|
9626
|
+
}), indexCookieHeader(indexToken));
|
|
9627
|
+
}
|
|
9628
|
+
/**
|
|
9475
9629
|
* Whether the caller is a browser navigating, rather than something reading the API.
|
|
9476
9630
|
*
|
|
9477
9631
|
* `Accept` is the only signal available and browsers are consistent about it: a navigation asks
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prreviewbuddy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.50.0",
|
|
4
4
|
"description": "Review a branch or pull request in an isolated checkout, from your terminal, with the coding agent you already have installed.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"homepage": "https://prreviewbuddy.com",
|
package/static/help.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as e,t}from"./chunk-BeL0x-wt.js";t(`/restart`),e(window,()=>window.location.reload());
|
package/static/shell.css
CHANGED
|
@@ -318,6 +318,69 @@ body > * { flex: 0 0 auto; }
|
|
|
318
318
|
}
|
|
319
319
|
.prb-change-ref .prb-arrow { color: var(--text-muted); }
|
|
320
320
|
|
|
321
|
+
/* ── Review range ──
|
|
322
|
+
Which commits the review is of. A sibling of `.prb-change-ref`, never a child: that element clips
|
|
323
|
+
to keep the bar on one line, and would cut the panel off. The label is a fact, so it reads as
|
|
324
|
+
part of the bar's state rather than as a control competing with it. */
|
|
325
|
+
.prb-range {
|
|
326
|
+
position: relative;
|
|
327
|
+
flex: none;
|
|
328
|
+
margin-left: -8px;
|
|
329
|
+
}
|
|
330
|
+
.prb-range-summary {
|
|
331
|
+
display: inline-flex;
|
|
332
|
+
align-items: center;
|
|
333
|
+
gap: 5px;
|
|
334
|
+
padding: 2px 9px;
|
|
335
|
+
border: 1px solid var(--border);
|
|
336
|
+
border-radius: 999px;
|
|
337
|
+
color: var(--text-secondary);
|
|
338
|
+
font-size: var(--t-meta);
|
|
339
|
+
white-space: nowrap;
|
|
340
|
+
cursor: pointer;
|
|
341
|
+
user-select: none;
|
|
342
|
+
list-style: none;
|
|
343
|
+
}
|
|
344
|
+
.prb-range-summary::-webkit-details-marker { display: none; }
|
|
345
|
+
.prb-range-summary::after {
|
|
346
|
+
content: '\25BE';
|
|
347
|
+
font-size: 9px; /* the disclosure caret, sized to the mark, not the type scale */
|
|
348
|
+
line-height: 1;
|
|
349
|
+
}
|
|
350
|
+
.prb-range[open] .prb-range-summary::after { content: '\25B4'; }
|
|
351
|
+
.prb-range-summary:hover { color: var(--text-primary); background: var(--surface-2); }
|
|
352
|
+
.prb-range-summary:focus-visible { outline: 2px solid var(--brand-hover); outline-offset: 2px; }
|
|
353
|
+
/* Anchored under the pill and out of flow, so opening it never moves the bar or the review. */
|
|
354
|
+
.prb-range-panel {
|
|
355
|
+
position: absolute;
|
|
356
|
+
top: calc(100% + 8px);
|
|
357
|
+
left: 0;
|
|
358
|
+
z-index: 3;
|
|
359
|
+
width: max-content;
|
|
360
|
+
max-width: min(420px, calc(100vw - 32px));
|
|
361
|
+
padding: 10px 14px;
|
|
362
|
+
border: 1px solid var(--border);
|
|
363
|
+
border-radius: 9px;
|
|
364
|
+
background: var(--surface-raised);
|
|
365
|
+
box-shadow: 0 10px 28px var(--shadow-float);
|
|
366
|
+
font-size: var(--t-meta);
|
|
367
|
+
line-height: var(--lh-body);
|
|
368
|
+
color: var(--text-secondary);
|
|
369
|
+
white-space: normal;
|
|
370
|
+
overflow-wrap: anywhere;
|
|
371
|
+
}
|
|
372
|
+
.prb-range-panel p { margin: 0 0 6px; }
|
|
373
|
+
.prb-range-panel p:last-child { margin-bottom: 0; }
|
|
374
|
+
.prb-range-panel code { font-size: var(--t-code); color: var(--text-primary); }
|
|
375
|
+
.prb-range-panel a { color: var(--brand-hover); }
|
|
376
|
+
/* Phone width: anchored to the pill, the panel ran off the right edge. Here it keeps its place just
|
|
377
|
+
under the pill (static top) but spans the page with the usual 16px gutter. Placed after the base
|
|
378
|
+
rules above, which it overrides at the same specificity. */
|
|
379
|
+
@media (max-width: 600px) {
|
|
380
|
+
.prb-range { position: static; }
|
|
381
|
+
.prb-range-panel { top: auto; left: 16px; right: 16px; margin-top: 8px; width: auto; max-width: none; }
|
|
382
|
+
}
|
|
383
|
+
|
|
321
384
|
.prb-header-stats {
|
|
322
385
|
margin-left: auto;
|
|
323
386
|
display: flex;
|
|
@@ -1506,26 +1569,32 @@ a.prb-rail-item { text-decoration: none; }
|
|
|
1506
1569
|
|
|
1507
1570
|
.prb-ask-header {
|
|
1508
1571
|
display: flex;
|
|
1509
|
-
align-items:
|
|
1572
|
+
align-items: center;
|
|
1510
1573
|
gap: 8px;
|
|
1511
1574
|
padding: 16px 18px 12px;
|
|
1512
1575
|
border-bottom: 1px solid var(--border);
|
|
1513
1576
|
}
|
|
1577
|
+
/* The title and what the next question is about, stacked. It takes the free space, which keeps
|
|
1578
|
+
the two icon controls at the right edge. */
|
|
1579
|
+
.prb-ask-heading {
|
|
1580
|
+
flex: 1;
|
|
1581
|
+
min-width: 0;
|
|
1582
|
+
margin: 0;
|
|
1583
|
+
}
|
|
1514
1584
|
.prb-ask-header h2 {
|
|
1515
1585
|
margin: 0;
|
|
1516
1586
|
font-size: var(--t-section);
|
|
1517
1587
|
font-weight: 600;
|
|
1518
1588
|
color: var(--text-primary);
|
|
1519
1589
|
}
|
|
1590
|
+
/* Never truncated: the theme's name is the whole point of the line, so it wraps however long. */
|
|
1520
1591
|
.prb-ask-scope {
|
|
1521
|
-
margin
|
|
1592
|
+
margin: 2px 0 0;
|
|
1522
1593
|
font-size: var(--t-micro);
|
|
1523
1594
|
color: var(--text-muted);
|
|
1524
|
-
overflow:
|
|
1525
|
-
text-overflow: ellipsis;
|
|
1526
|
-
white-space: nowrap;
|
|
1527
|
-
max-width: 150px;
|
|
1595
|
+
overflow-wrap: anywhere;
|
|
1528
1596
|
}
|
|
1597
|
+
.prb-ask-scope [data-ask-scope] { color: var(--text-secondary); }
|
|
1529
1598
|
|
|
1530
1599
|
.prb-ask-log {
|
|
1531
1600
|
flex: 1;
|
|
@@ -4782,6 +4851,41 @@ a.prb-rail-item { text-decoration: none; }
|
|
|
4782
4851
|
color: var(--text-secondary);
|
|
4783
4852
|
}
|
|
4784
4853
|
.prb-settings-help code { font-size: var(--t-code); color: var(--text-primary); }
|
|
4854
|
+
|
|
4855
|
+
/* ── Help ──
|
|
4856
|
+
Reading, not settings: prose at a readable measure, one topic per section, each with an anchor a
|
|
4857
|
+
place elsewhere in the product can link to. */
|
|
4858
|
+
.prb-help-topic {
|
|
4859
|
+
max-width: 46rem;
|
|
4860
|
+
padding: 20px 0;
|
|
4861
|
+
border-bottom: 1px solid var(--border);
|
|
4862
|
+
font-size: var(--t-body);
|
|
4863
|
+
line-height: var(--lh-body);
|
|
4864
|
+
color: var(--text-secondary);
|
|
4865
|
+
/* Clear of the sticky bars when arrived at by its anchor. */
|
|
4866
|
+
scroll-margin-top: 96px;
|
|
4867
|
+
}
|
|
4868
|
+
.prb-help-topic:first-of-type { padding-top: 4px; }
|
|
4869
|
+
.prb-help-topic:last-of-type { border-bottom: 0; }
|
|
4870
|
+
.prb-help-topic h2 { margin: 0 0 12px; font-size: var(--t-section); font-weight: 600; color: var(--text-primary); }
|
|
4871
|
+
.prb-help-topic h3 { margin: 20px 0 8px; font-size: var(--t-body); font-weight: 600; color: var(--text-primary); }
|
|
4872
|
+
.prb-help-topic p { margin: 0 0 10px; }
|
|
4873
|
+
.prb-help-topic ul { margin: 0 0 10px; padding-left: 20px; }
|
|
4874
|
+
.prb-help-topic li { margin-bottom: 4px; }
|
|
4875
|
+
.prb-help-topic code { font-size: var(--t-code); color: var(--text-primary); }
|
|
4876
|
+
/* A diagram's spacing is its meaning, so it never wraps: a narrow window scrolls it instead. */
|
|
4877
|
+
.prb-help-diagram {
|
|
4878
|
+
margin: 0 0 12px;
|
|
4879
|
+
padding: 12px 14px;
|
|
4880
|
+
overflow-x: auto;
|
|
4881
|
+
border: 1px solid var(--border);
|
|
4882
|
+
border-radius: 8px;
|
|
4883
|
+
background: var(--surface-2);
|
|
4884
|
+
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;
|
|
4885
|
+
font-size: var(--t-code);
|
|
4886
|
+
line-height: 1.4;
|
|
4887
|
+
color: var(--text-primary);
|
|
4888
|
+
}
|
|
4785
4889
|
/* Empty until there is something wrong, and it collapses when there is not: an always-present gap
|
|
4786
4890
|
under a field reads as a control that is missing part of itself. */
|
|
4787
4891
|
.prb-settings-error {
|
|
@@ -4991,8 +5095,8 @@ body .prb-body[data-focus='buddy'] .prb-msg-user { max-width: min(90%, 78ch); }
|
|
|
4991
5095
|
.prb-focus-toggle .prb-focus-collapse,
|
|
4992
5096
|
.prb-focus-toggle[aria-pressed='true'] .prb-focus-expand { display: none; }
|
|
4993
5097
|
.prb-focus-toggle[aria-pressed='true'] .prb-focus-collapse { display: block; }
|
|
4994
|
-
/* In the assistant's header it follows the
|
|
4995
|
-
|
|
5098
|
+
/* In the assistant's header it follows the heading, which takes the free space, so the control
|
|
5099
|
+
stays at the right edge beside it. */
|
|
4996
5100
|
.prb-ask-header :is(.prb-focus-toggle, .prb-ask-hide) { align-self: center; }
|
|
4997
5101
|
|
|
4998
5102
|
/* The same control in the light document pane, in the pane's palette. */
|
package/static/workspace.js
CHANGED
|
@@ -37,7 +37,7 @@ import{c as e,i as t,t as n}from"./chunk-BeL0x-wt.js";import{C as r,S as i,_ as
|
|
|
37
37
|
|
|
38
38
|
`);return o.trim()?(o.length>n?`${o.slice(0,n).trimEnd()}…`:o).split(`
|
|
39
39
|
`).map(e=>`> ${e}`.trimEnd()).join(`
|
|
40
|
-
`):``}function rt(e,t,n={}){let r=nt(e,n);if(!r)return null;let i=[...Qe,...T,...et].find(e=>e.id===t);return i?i.instruction?`${r}\n\n${i.instruction}`:`${r}\n\n`:null}Object.freeze([{id:`default-assumptions`,name:`What does it assume?`,prompt:`What assumptions does this change make? Say which are stated, which are implied, and what happens if one turns out to be wrong.`},{id:`default-explain-educational`,name:`Teach me this`,prompt:`Explain this in an educational way: the concepts it relies on, why it is built this way, and what I should take away from it.`},{id:`default-what-could-go-wrong`,name:`What could go wrong?`,prompt:`What could go wrong here? Think about edge cases, failure modes and the existing callers this could break.`},{id:`default-walkthrough`,name:`Walk me through it`,prompt:`Walk me through the implementation step by step, in the order the code runs.`},{id:`default-verify-manually`,name:`What should I verify?`,prompt:`What should I verify manually before approving this, and how would I check each one?`}].map(e=>Object.freeze(e)));var it=`saved:`,at=`Your prompts`;function ot(e){return`${it}${e}`}function st(e){return e.startsWith(`saved:`)?e.slice(6):null}var ct=[`progress`,`overview`,`guide`,`issues`,`questions`,`files`,`prcontext`,`map`,`diagram`,`kiss`,`kissrecs`],lt=`#theme-`,ut=[`buddy`,`overview`,`guide`,`map`,`diagram`,`issues`,`questions`,`files`,`prcontext`,`kiss`,`kissrecs`,`progress`],dt=`&focus=`;function ft(e){return`#${e}`}function pt(e){return`${lt}${encodeURIComponent(e)}`}function mt(e){let t=e.kind===`view`?ft(e.view):pt(e.sectionId);return e.focus?`${t}${dt}${e.focus}`:t}function ht(e){let{focus:t,...n}=e;return n}function gt(e,t){return e.kind!==`view`||e.view!==`guide`||!t?e:{kind:`section`,sectionId:t,...e.focus?{focus:e.focus}:{}}}function _t(e){return ut.includes(e)}function vt(e){let t=e.indexOf(dt);if(t===-1)return yt(e);let n=yt(e.slice(0,t));if(!n)return null;let r=e.slice(t+7);return _t(r)?{...n,focus:r}:n}function yt(e){if(e.startsWith(lt)){let t=e.slice(7);if(!t)return null;try{return{kind:`section`,sectionId:decodeURIComponent(t)}}catch{return null}}let t=e.replace(/^#/,``);return ct.includes(t)?{kind:`view`,view:t}:null}var bt=`pushedFocus`;function xt(e){let{[bt]:t,...n}=e;return n}function St(e,t){return e.kind===`view`&&t.kind===`view`?e.view===t.view:e.kind===`section`&&t.kind===`section`&&e.sectionId===t.sectionId}function Ct(e,t,n){if(e.focus===t)return;let r={...ht(xt(e)),focus:t};e.focus&&n.history.state?.[bt]?n.history.replaceState({...r,[bt]:!0},``,mt(r)):n.history.pushState({...r,[bt]:!0},``,mt(r)),n.apply(r)}function wt(e,t){if(!e.focus)return;if(t.history.state?.[bt]){t.history.back();return}let n=ht(xt(e));t.history.replaceState(n,``,mt(n)),t.apply(n)}function Tt(e,t,n){if(!n||e.key!==`Escape`||e.defaultPrevented||t.querySelector(`dialog[open], [data-menu-panel]:not([hidden]), [data-analysis-details][open], .pr-helper-selection-popover`))return!1;let r=e.target;return!(r?.closest?.(`[data-ask-resize]`)||r instanceof HTMLInputElement&&r.value!==``)}function Et(e,t,n){e&&(n?e.dataset.focus=n:delete e.dataset.focus);for(let e of t.querySelectorAll(`[data-focus-toggle]`)){let t=e.dataset.focusToggle===n,r=e.dataset.focusName??`this`,i=t?`Exit focus on ${r}`:`Expand ${r}`;e.setAttribute(`aria-pressed`,String(t)),e.setAttribute(`aria-label`,i),e.setAttribute(`title`,t?`${i} (Esc)`:i)}}function Dt(e,t,n,r){let i=n===`finding`?{maxChars:1/0}:{},a=st(e);if(a===null)return rt(t,e,i);let o=r(a);if(!o)return null;let s=nt(t,i);return s?`${s}\n\n${o}`:null}function Ot(e,t,n){let r=Dt(e,t.text,t.context,n.savedPrompt);if(!r)return null;let i=$e(e)||st(e)!==null;return t.context===`selection`||i?(n.stage(r),`staged`):(n.send(r),`sent`)}var kt=`button:not([disabled])`;function At(e){return e.querySelector(`[data-menu-panel]`)}function jt(e){return e.querySelector(`[data-menu-trigger]`)}function Mt(e){let t=At(e);return t?[...t.querySelectorAll(kt)].filter(e=>!e.closest(`[hidden]`)):[]}function Nt(e,t={}){let n=null,r=(e,r={})=>{let i=At(e);if(!i||i.hidden)return;i.hidden=!0;let a=jt(e);a?.setAttribute(`aria-expanded`,`false`),n===e&&(n=null),t.onClose?.(e),r.returnFocus&&a?.focus()},i=()=>{for(let t of e.querySelectorAll(`[data-menu]`))r(t)},a=(e,r)=>{let a=At(e);a&&(i(),t.onOpen?.(e),a.hidden=!1,jt(e)?.setAttribute(`aria-expanded`,`true`),n=e,r&&Mt(e)[0]?.focus())};return e.addEventListener(`click`,e=>{let t=e.target,o=t?.closest?.(`[data-menu]`)??null;if(!o){i();return}if(t?.closest(`[data-menu-trigger]`)){let t=e.detail===0;At(o)?.hidden?a(o,t):r(o);return}n&&n!==o&&r(n)}),e.addEventListener(`keydown`,e=>{if(!n)return;let t=n;if(e.key===`Escape`){e.preventDefault(),r(t,{returnFocus:!0});return}if(!t.contains(e.target))return;if(e.key===`Tab`){r(t);return}let i=Mt(t);if(i.length===0)return;let a=i.indexOf(e.target),o=e.key===`ArrowDown`?i[(a+1)%i.length]:e.key===`ArrowUp`?i[(a-1+i.length)%i.length]:e.key===`Home`?i[0]:e.key===`End`?i[i.length-1]:null;o&&(e.preventDefault(),o.focus())}),{close:r,closeAll:i}}function Pt(e){return e.reviewerClosed>0?`dealt with`:`resolved`}({claude:`Claude Code`,codex:`Codex`,gemini:`Gemini CLI`}).claude;function E(e,t=``){return typeof e==`string`?e:t}var Ft=`Dismissed by you — you decided this finding needs no action. It stops counting towards what is left, and stays here so the decision is visible rather than lost.`;function It(e,t,n=`resolved`){return t===0?`<span class="pr-helper-questions-progress-check" aria-hidden="true">\u2713</span><span class="pr-helper-questions-progress-count">All ${e} issues ${n}</span>`:`<span class="pr-helper-questions-progress-count">${t} of ${e} still open</span>`}function Lt(e){let t=e.done-e.reviewerClosed;return e.reviewerClosed===0?`Resolved by the new commits (${e.done})`:t===0?`Dismissed by you (${e.done})`:`Dealt with (${e.done})`}function Rt(e,t){return t===0?`<span class="pr-helper-questions-progress-check" aria-hidden="true">✓</span><span class="pr-helper-questions-progress-count">All ${e} questions answered</span>`:`<span class="pr-helper-questions-progress-count">${t} of ${e} unanswered</span>`}function zt(e){let t=[...document.querySelectorAll(`[data-guide-detail]`)],n=t.find(t=>t.dataset.guideDetail===e);if(!n)return null;for(let e of t)e.hidden=e!==n;return n}function Bt(e){return e instanceof Element&&e.closest(`[data-guide-jump]`)?.dataset.guideJump||null}function Vt(e){for(let t of document.querySelectorAll(`[data-goto-section]`))t.setAttribute(`aria-current`,String(t.dataset.gotoSection===e))}function Ht(){for(let e of document.querySelectorAll(`.prb-rail [data-goto-section]`))e.setAttribute(`aria-current`,`false`)}function Ut(e,t){let n=e.trim();return n?`${n}\n\n${t}`:t}function Wt(e){if(!Number.isFinite(e))return``;let t=Math.round((Date.now()-e)/6e4);if(t<1)return`just now`;if(t<60)return`${t} minute${t===1?``:`s`} ago`;let n=Math.round(t/60);if(n<24)return`${n} hour${n===1?``:`s`} ago`;let r=Math.round(n/24);return`${r} day${r===1?``:`s`} ago`}function Gt(){return`<button type="button" class="prb-update-btn" data-review-update>Update review</button>`}var Kt=`Updating this review checks the latest commits and refreshes the PR conversation. Your progress and Buddy AI history will be kept.`;function qt(e){return`<details class="prb-update-alt">
|
|
40
|
+
`):``}function rt(e,t,n={}){let r=nt(e,n);if(!r)return null;let i=[...Qe,...T,...et].find(e=>e.id===t);return i?i.instruction?`${r}\n\n${i.instruction}`:`${r}\n\n`:null}Object.freeze([{id:`default-assumptions`,name:`What does it assume?`,prompt:`What assumptions does this change make? Say which are stated, which are implied, and what happens if one turns out to be wrong.`},{id:`default-explain-educational`,name:`Teach me this`,prompt:`Explain this in an educational way: the concepts it relies on, why it is built this way, and what I should take away from it.`},{id:`default-what-could-go-wrong`,name:`What could go wrong?`,prompt:`What could go wrong here? Think about edge cases, failure modes and the existing callers this could break.`},{id:`default-walkthrough`,name:`Walk me through it`,prompt:`Walk me through the implementation step by step, in the order the code runs.`},{id:`default-verify-manually`,name:`What should I verify?`,prompt:`What should I verify manually before approving this, and how would I check each one?`}].map(e=>Object.freeze(e)));var it=`saved:`,at=`Your prompts`;function ot(e){return`${it}${e}`}function st(e){return e.startsWith(`saved:`)?e.slice(6):null}var ct=[`progress`,`overview`,`guide`,`issues`,`questions`,`files`,`prcontext`,`map`,`diagram`,`kiss`,`kissrecs`],lt=`#theme-`,ut=[`buddy`,`overview`,`guide`,`map`,`diagram`,`issues`,`questions`,`files`,`prcontext`,`kiss`,`kissrecs`,`progress`],dt=`&focus=`;function ft(e){return`#${e}`}function pt(e){return`${lt}${encodeURIComponent(e)}`}function mt(e){let t=e.kind===`view`?ft(e.view):pt(e.sectionId);return e.focus?`${t}${dt}${e.focus}`:t}function ht(e){let{focus:t,...n}=e;return n}function gt(e,t){return e.kind!==`view`||e.view!==`guide`||!t?e:{kind:`section`,sectionId:t,...e.focus?{focus:e.focus}:{}}}function _t(e){return ut.includes(e)}function vt(e){let t=e.indexOf(dt);if(t===-1)return yt(e);let n=yt(e.slice(0,t));if(!n)return null;let r=e.slice(t+7);return _t(r)?{...n,focus:r}:n}function yt(e){if(e.startsWith(lt)){let t=e.slice(7);if(!t)return null;try{return{kind:`section`,sectionId:decodeURIComponent(t)}}catch{return null}}let t=e.replace(/^#/,``);return ct.includes(t)?{kind:`view`,view:t}:null}var bt=`pushedFocus`;function xt(e){let{[bt]:t,...n}=e;return n}function St(e,t){return e.kind===`view`&&t.kind===`view`?e.view===t.view:e.kind===`section`&&t.kind===`section`&&e.sectionId===t.sectionId}function Ct(e,t,n){if(e.focus===t)return;let r={...ht(xt(e)),focus:t};e.focus&&n.history.state?.[bt]?n.history.replaceState({...r,[bt]:!0},``,mt(r)):n.history.pushState({...r,[bt]:!0},``,mt(r)),n.apply(r)}function wt(e,t){if(!e.focus)return;if(t.history.state?.[bt]){t.history.back();return}let n=ht(xt(e));t.history.replaceState(n,``,mt(n)),t.apply(n)}function Tt(e,t,n){if(!n||e.key!==`Escape`||e.defaultPrevented||t.querySelector(`dialog[open], [data-menu-panel]:not([hidden]), [data-analysis-details][open], [data-range-details][open], .pr-helper-selection-popover`))return!1;let r=e.target;return!(r?.closest?.(`[data-ask-resize]`)||r instanceof HTMLInputElement&&r.value!==``)}function Et(e,t,n){e&&(n?e.dataset.focus=n:delete e.dataset.focus);for(let e of t.querySelectorAll(`[data-focus-toggle]`)){let t=e.dataset.focusToggle===n,r=e.dataset.focusName??`this`,i=t?`Exit focus on ${r}`:`Expand ${r}`;e.setAttribute(`aria-pressed`,String(t)),e.setAttribute(`aria-label`,i),e.setAttribute(`title`,t?`${i} (Esc)`:i)}}function Dt(e,t,n,r){let i=n===`finding`?{maxChars:1/0}:{},a=st(e);if(a===null)return rt(t,e,i);let o=r(a);if(!o)return null;let s=nt(t,i);return s?`${s}\n\n${o}`:null}function Ot(e,t,n){let r=Dt(e,t.text,t.context,n.savedPrompt);if(!r)return null;let i=$e(e)||st(e)!==null;return t.context===`selection`||i?(n.stage(r),`staged`):(n.send(r),`sent`)}var kt=`button:not([disabled])`;function At(e){return e.querySelector(`[data-menu-panel]`)}function jt(e){return e.querySelector(`[data-menu-trigger]`)}function Mt(e){let t=At(e);return t?[...t.querySelectorAll(kt)].filter(e=>!e.closest(`[hidden]`)):[]}function Nt(e,t={}){let n=null,r=(e,r={})=>{let i=At(e);if(!i||i.hidden)return;i.hidden=!0;let a=jt(e);a?.setAttribute(`aria-expanded`,`false`),n===e&&(n=null),t.onClose?.(e),r.returnFocus&&a?.focus()},i=()=>{for(let t of e.querySelectorAll(`[data-menu]`))r(t)},a=(e,r)=>{let a=At(e);a&&(i(),t.onOpen?.(e),a.hidden=!1,jt(e)?.setAttribute(`aria-expanded`,`true`),n=e,r&&Mt(e)[0]?.focus())};return e.addEventListener(`click`,e=>{let t=e.target,o=t?.closest?.(`[data-menu]`)??null;if(!o){i();return}if(t?.closest(`[data-menu-trigger]`)){let t=e.detail===0;At(o)?.hidden?a(o,t):r(o);return}n&&n!==o&&r(n)}),e.addEventListener(`keydown`,e=>{if(!n)return;let t=n;if(e.key===`Escape`){e.preventDefault(),r(t,{returnFocus:!0});return}if(!t.contains(e.target))return;if(e.key===`Tab`){r(t);return}let i=Mt(t);if(i.length===0)return;let a=i.indexOf(e.target),o=e.key===`ArrowDown`?i[(a+1)%i.length]:e.key===`ArrowUp`?i[(a-1+i.length)%i.length]:e.key===`Home`?i[0]:e.key===`End`?i[i.length-1]:null;o&&(e.preventDefault(),o.focus())}),{close:r,closeAll:i}}function Pt(e){return e.reviewerClosed>0?`dealt with`:`resolved`}({claude:`Claude Code`,codex:`Codex`,gemini:`Gemini CLI`}).claude;function E(e,t=``){return typeof e==`string`?e:t}var Ft=`Dismissed by you — you decided this finding needs no action. It stops counting towards what is left, and stays here so the decision is visible rather than lost.`;function It(e,t,n=`resolved`){return t===0?`<span class="pr-helper-questions-progress-check" aria-hidden="true">\u2713</span><span class="pr-helper-questions-progress-count">All ${e} issues ${n}</span>`:`<span class="pr-helper-questions-progress-count">${t} of ${e} still open</span>`}function Lt(e){let t=e.done-e.reviewerClosed;return e.reviewerClosed===0?`Resolved by the new commits (${e.done})`:t===0?`Dismissed by you (${e.done})`:`Dealt with (${e.done})`}function Rt(e,t){return t===0?`<span class="pr-helper-questions-progress-check" aria-hidden="true">✓</span><span class="pr-helper-questions-progress-count">All ${e} questions answered</span>`:`<span class="pr-helper-questions-progress-count">${t} of ${e} unanswered</span>`}function zt(e){let t=[...document.querySelectorAll(`[data-guide-detail]`)],n=t.find(t=>t.dataset.guideDetail===e);if(!n)return null;for(let e of t)e.hidden=e!==n;return n}function Bt(e){return e instanceof Element&&e.closest(`[data-guide-jump]`)?.dataset.guideJump||null}function Vt(e){for(let t of document.querySelectorAll(`[data-goto-section]`))t.setAttribute(`aria-current`,String(t.dataset.gotoSection===e))}function Ht(){for(let e of document.querySelectorAll(`.prb-rail [data-goto-section]`))e.setAttribute(`aria-current`,`false`)}function Ut(e,t){let n=e.trim();return n?`${n}\n\n${t}`:t}function Wt(e){if(!Number.isFinite(e))return``;let t=Math.round((Date.now()-e)/6e4);if(t<1)return`just now`;if(t<60)return`${t} minute${t===1?``:`s`} ago`;let n=Math.round(t/60);if(n<24)return`${n} hour${n===1?``:`s`} ago`;let r=Math.round(n/24);return`${r} day${r===1?``:`s`} ago`}function Gt(){return`<button type="button" class="prb-update-btn" data-review-update>Update review</button>`}var Kt=`Updating this review checks the latest commits and refreshes the PR conversation. Your progress and Buddy AI history will be kept.`;function qt(e){return`<details class="prb-update-alt">
|
|
41
41
|
<summary>Start a new review</summary>
|
|
42
42
|
<span>A brand new review, with its own findings and its own path through the change. Run <code>${p(e)}</code> in your session.<button type="button" class="prb-fresh-quiet" data-copy-command="${p(e)}">Copy</button></span>
|
|
43
43
|
</details>`}var Jt=`prreviewbuddy review --fresh`;function Yt(e,t){return e?e.code.state===`fixed`?{label:`Freshness: Fixed`,state:`fixed`}:t?{label:`PR updated`,state:`changed`}:e.code.state===`changed`?{label:e.code.rewritten?`Code rewritten`:`Code changed`,state:`changed`}:e.code.state===`current`?{label:`Review up to date`,state:`current`}:{label:`Freshness unknown`,state:`unknown`}:t?{label:`PR updated`,state:`changed`}:{label:`Check for updates`,state:`unknown`}}function Xt(e,t={}){let n=e??(t.remote?nn(t.remote):null);if(!n)return``;let r=n.code.state===`fixed`?null:t.remote??null,i=n.code.state===`changed`||r!==null,a=n.code.reason===`missing-commit`,o=t.availability?.state===`missing`,s=r?.sha??n.code.latestSha,c=t.dismissedSha!==void 0&&t.dismissedSha===s;if(!t.open&&!o&&(!(i||a)||c))return``;let l=r?rn(n.code,r):tn(n.code,t.availability??null),u=e?[...l.facts,`checked ${p(Wt(n.checkedAt))}`]:l.facts;return`<div class="prb-fresh" data-state="${i||a?`changed`:`quiet`}" role="status">
|
|
@@ -137,7 +137,7 @@ import{c as e,i as t,t as n}from"./chunk-BeL0x-wt.js";import{C as r,S as i,_ as
|
|
|
137
137
|
<button type="button" class="prb-code-nav-step" data-change-step="next"${a?``:` disabled`}>Next \u2193</button>
|
|
138
138
|
</span>`}function bi(e,t){let n=(e.dataset.changeKeys??``).split(`,`).filter(Boolean).map(Number),r=Number(e.dataset.changePosition)||0,i=t===`next`?n.find(e=>e>r):[...n].reverse().find(e=>e<r);return i===void 0?null:{key:i,anchor:vi(i)}}function xi(e,t){return e.querySelector(t.deletion?`tr[data-before-line="${t.line}"]`:`tr[data-line="${t.line}"]`)}function Si(e){return(e.dataset.changeKeys??``).split(`,`).filter(Boolean).map(Number).map(vi)}function Ci(e){if(!e)return;let t=Number(e.dataset.changePosition)||0;return(e.dataset.changeKeys??``).split(`,`).filter(Boolean).map(Number).includes(t)?vi(t):void 0}function wi(e,t){return Math.max(e,+!t)+1}var Ti=8;function Ei(e){for(let t=e.parentElement;t;t=t.parentElement){let e=getComputedStyle(t).overflowY;if(e===`auto`||e===`scroll`)return t}return null}function Di(e){let t=e.panel-e.scroller;return Math.max(340,Math.floor(e.pane-t-16))}function Oi(e){let t=e.getBoundingClientRect().top;for(let n of e.querySelectorAll(`tr`)){let e=n.getBoundingClientRect();if(e.bottom>t)return{row:n,offset:e.top-t}}return null}function ki(e,t){let n=t.row.getBoundingClientRect().top-e.getBoundingClientRect().top-t.offset;e.scrollTop+=n}function Ai(e){if(!e.hasAttribute(`data-expanded`))return;let t=Ei(e),n=e.querySelector(`.prb-code-scroll`);if(!t||!n)return;let r=Di({pane:t.clientHeight,panel:e.offsetHeight,scroller:n.offsetHeight});e.style.setProperty(`--prb-code-expanded`,`${r}px`)}function ji(e){let t=e.querySelector(`[data-code-expand]`),n=e.querySelector(`.prb-code-scroll`);if(!t||!n)return;let r=e.hasAttribute(`data-expanded`);t.hidden=!r&&n.scrollHeight<=n.clientHeight,t.textContent=r?`Collapse`:`Expand`,t.setAttribute(`aria-expanded`,String(r))}var Mi=!1;function Ni(){Mi||(Mi=!0,window.addEventListener(`resize`,()=>{for(let e of document.querySelectorAll(`.prb-code[data-expanded]`))Ai(e)}))}function Pi(e,t){let n=e.querySelector(`.prb-code-scroll`),r=n?Oi(n):null;t?(e.setAttribute(`data-expanded`,``),Ai(e),Ni()):(e.removeAttribute(`data-expanded`),e.style.removeProperty(`--prb-code-expanded`)),ji(e),n&&r&&ki(n,r);let i=t?Ei(e):null;i&&(i.scrollTop+=e.getBoundingClientRect().top-i.getBoundingClientRect().top-Ti)}var Fi={rb:`ruby`,js:`javascript`,mjs:`javascript`,cjs:`javascript`,ts:`typescript`,mts:`typescript`,cts:`typescript`,jsx:`jsx`,tsx:`tsx`,json:`json`,yml:`yaml`,yaml:`yaml`,md:`markdown`,html:`html`,css:`css`,scss:`scss`,sql:`sql`,py:`python`,java:`java`,kt:`kotlin`,kts:`kotlin`,go:`go`,rs:`rust`,sh:`shellscript`,bash:`shellscript`,zsh:`shellscript`,tf:`terraform`,tfvars:`terraform`};function Ii(e){let t=e.slice(e.lastIndexOf(`/`)+1);if(t===`Dockerfile`||t.startsWith(`Dockerfile.`))return`docker`;let n=t.lastIndexOf(`.`);return n<=0?null:Fi[t.slice(n+1).toLowerCase()]??null}function Li(e){let t=new Set;for(let n of e){let e=Ii(n);e&&t.add(e)}return[...t]}var Ri={ruby:()=>O(()=>import(`./chunk-CAnKkQXq.js`),__vite__mapDeps([19,20,21,22,23,24,25,26,27,28,29])),javascript:()=>O(()=>import(`./chunk-D2pwppYQ.js`),__vite__mapDeps([30,21])),typescript:()=>O(()=>import(`./chunk-Cjc271yU.js`),__vite__mapDeps([31,26])),jsx:()=>O(()=>import(`./chunk-B2PgDgse.js`),__vite__mapDeps([32,24])),tsx:()=>O(()=>import(`./chunk-D95j_xjm.js`),__vite__mapDeps([33,27])),json:()=>O(()=>import(`./chunk-qhed-kSA.js`),[]),yaml:()=>O(()=>import(`./chunk-Cv3JjNkX.js`),__vite__mapDeps([34,29])),markdown:()=>O(()=>import(`./chunk-BYOwaDjH.js`),[]),html:()=>O(()=>import(`./chunk-EIJEcyW-.js`),__vite__mapDeps([35,22,20,21])),css:()=>O(()=>import(`./chunk-C3nvJp0N.js`),__vite__mapDeps([36,20])),scss:()=>O(()=>import(`./chunk-D2NZorQR.js`),__vite__mapDeps([37,20])),sql:()=>O(()=>import(`./chunk-NzFayA7r.js`),__vite__mapDeps([38,25])),python:()=>O(()=>import(`./chunk-gzcpVVnB.js`),[]),java:()=>O(()=>import(`./chunk-AdYjtsZU.js`),__vite__mapDeps([39,23])),kotlin:()=>O(()=>import(`./chunk-DhhofPvG.js`),[]),go:()=>O(()=>import(`./chunk-rLFTqkRN.js`),[]),rust:()=>O(()=>import(`./chunk-Cfkwpbl8.js`),[]),shellscript:()=>O(()=>import(`./chunk-pNSm1SyV.js`),__vite__mapDeps([40,28])),docker:()=>O(()=>import(`./chunk-IyjqRm3v.js`),[]),terraform:()=>O(()=>import(`./chunk-DswuEJGm.js`),[])},zi=`github-light-default`,Bi=null,Vi=new Map;function Hi(){return Bi??=Promise.all([O(()=>import(`./chunk-c-cg1wCO.js`),__vite__mapDeps([41,3])),O(()=>import(`./chunk-CBrdyqSx.js`),__vite__mapDeps([42,3])),O(()=>import(`./chunk-BXViO-2h.js`),[])]).then(([{createHighlighterCore:e},{createOnigurumaEngine:t},n])=>e({themes:[n.default],langs:[],engine:t(O(()=>import(`./chunk-BnjxR4X6.js`),[]))})).catch(()=>null),Bi}function Ui(e){let t=Vi.get(e);return t||(t=Hi().then(async t=>t?(await t.loadLanguage(Ri[e]),!0):!1).catch(()=>!1),Vi.set(e,t)),t.then(e=>e?Hi():null)}var Wi={async preload(e){await Ui(e)},async tokenize(e,t){let n=await Ui(t);if(!n)return null;try{let{tokens:r,fg:i}=n.codeToTokens(e,{lang:t,theme:zi}),a=i?.toLowerCase();return r.map(e=>e.map(e=>({content:e.content,...e.color&&e.color.toLowerCase()!==a?{color:e.color}:{}})))}catch{return null}}};function Gi(e,t=Wi){return Promise.all(e.map(e=>t.preload(e))).then(()=>void 0)}var Ki=/^#[0-9a-f]{3,8}$/i;function qi(e,t){return!t||t.map(e=>e.content).join(``)!==e?null:t.map(e=>e.color&&Ki.test(e.color)?`<span style="color:${e.color}">${ci(e.content)}</span>`:ci(e.content)).join(``)}function Ji(e){return e.length>1e3?e.slice(0,li):e}function Yi(e,t,n){if(!e||t===``)return;let r=qi(Ji(t),n);if(r===null)return;if(t.length<=1e3){if(e.childElementCount!==0||e.textContent!==t)return;e.innerHTML=r;return}let i=e.querySelector(`[data-full-line]`);i&&(e.innerHTML=`${r}… `,e.append(i))}async function Xi(e,t,n=Wi){let r=Ii(t.path);if(!r){delete e.dataset.syntax;return}e.dataset.syntax=r;let i=e.querySelector(`tbody`);if(!i)return;let a=()=>i.isConnected&&e.querySelector(`tbody`)===i,o=await n.tokenize(t.lines.map(Ji).join(`
|
|
139
139
|
`),r);if(a()){o&&t.lines.forEach((e,n)=>{Yi(i.querySelector(`tr[data-line="${t.from+n}"] .prb-code-line`),e,o[n])});for(let e of t.deletions??[]){if(!i.querySelector(`tr[data-before-line="${e.beforeLine}"]`))continue;let t=await n.tokenize(e.lines.map(e=>Ji(e.text)).join(`
|
|
140
|
-
`),r);if(!a())return;if(!t)continue;let o=i.querySelector(`tr[data-before-line="${e.beforeLine}"]`)?.nextElementSibling;for(let[n,r]of e.lines.entries()){if(!o?.classList.contains(`prb-code-deleted`))break;Yi(o.querySelector(`.prb-code-line`),r.text,t[n]),o=o.nextElementSibling}}}}async function Zi(e,t=Wi){let n=e.closest(`.prb-code`)?.dataset.syntax,r=e.textContent??``;if(!n||!(n in Ri)||r===``)return;let i=await t.tokenize(r,n);if(!e.isConnected||e.childElementCount!==0||e.textContent!==r)return;let a=qi(r,i?.[0]);a!==null&&i?.length===1&&(e.innerHTML=a)}var F=document.body,Qi=F.dataset.apiBase??``,$i=F.dataset.token??``,ea=F.dataset.editorLabel??``,ta=F.dataset.editorTemplate??``,na=F.dataset.repoPath??``,ra=F.dataset.explainPrompt??``,ia=F.dataset.sessionId??``;function I(e){return`${Qi}${e}?t=${encodeURIComponent($i)}`}function L(e){fetch(I(`/event`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e),keepalive:!0}).catch(()=>{})}var aa=Jn({endpoint:I,showDiagrams:()=>_a(`diagram`),showMap:()=>_a(`map`),showChangeMap:e=>oa.show(e)}),oa=Kr({endpoint:I,showView:e=>_a(e)}),sa=null,ca=`whole change`;function la(e){let t=gt(e,ua),n=mt(t);window.location.hash!==n&&history.pushState(t,``,n),da(t)}var R=null,ua=document.querySelector(`[data-guide-start]`)?.dataset.guideStart??null;function da(e){let t=gt(e,ua);if(t!==e){let{kind:e,view:n,focus:r,...i}=history.state??{};history.replaceState({...i,...t},``,mt(t))}let n=!R||!St(R,t);R=t,n&&(t.kind===`view`?ya(t.view):Ca(t.sectionId)),ma(t.focus??null)}var fa={history,apply:da},pa=Nt(document,{onOpen:e=>e.hasAttribute(`data-ask-buddy-menu`)?Wo(e):Go(e),onClose:Go});function ma(e){Et(document.querySelector(`.prb-body`),document,e),pa.closeAll(),e===`buddy`&&lo()}function ha(e){R&&(R.focus===e?wt(R,fa):Ct(R,e,fa))}window.addEventListener(`keydown`,e=>{!R||!Tt(e,document,!!R.focus)||(e.preventDefault(),wt(R,fa))},!0);var ga=[`map`,`diagram`];function _a(e){la({kind:`view`,view:e,...ga.includes(e)&&ga.includes(R?.focus??``)?{focus:e}:{}})}function va(e){la({kind:`section`,sectionId:e,...R?.focus===`guide`?{focus:`guide`}:{}})}function ya(e){for(let t of document.querySelectorAll(`.prb-view`))t.hidden=t.dataset.view!==e;for(let t of document.querySelectorAll(`[data-view-nav]:not([role="tab"])`))t.setAttribute(`aria-current`,String(t.dataset.viewNav===e||t.dataset.viewAlso===e));L({event:`view_opened`,view:e}),e===`diagram`&&aa.drawPane(),e===`map`&&oa.layout(),ba(),document.querySelector(`.prb-doc`)?.scrollTo({top:0})}function ba(){Ht(),sa=null,ca=`whole change`,wa()}function xa(e,t){let n=document.getElementById(e.getAttribute(`aria-controls`)??``);n&&(e.setAttribute(`aria-expanded`,String(t)),e.setAttribute(`aria-label`,`${t?`Collapse`:`Expand`} ${e.dataset.railToggle??`this section`}`),n.hidden=!t)}function Sa(){for(let e of document.querySelectorAll(`[data-rail-toggle]`)){let t=document.getElementById(e.getAttribute(`aria-controls`)??``);(t?.contains(document.getElementById(`prb-rail-path`))||t?.id===`prb-rail-path`)&&xa(e,!0)}}function Ca(e){ya(`guide`),Sa(),Vt(e);let t=zt(e);if(!t)return;let n=document.querySelector(`[data-goto-section="${CSS.escape(e)}"]`);L({event:`theme_opened`,themeIndex:Number(n?.dataset.themeIndex??-1),attention:n?.querySelector(`.prb-attention`)?.dataset.attention??`medium`,isRecommendedStart:n?.dataset.recommendedStart===`true`}),sa=e,ca=t.querySelector(`.pr-helper-guide-section-title`)?.textContent?.trim()??`this theme`,wa()}function wa(){let e=document.querySelector(`[data-ask-scope]`);e&&(e.textContent=ca
|
|
140
|
+
`),r);if(!a())return;if(!t)continue;let o=i.querySelector(`tr[data-before-line="${e.beforeLine}"]`)?.nextElementSibling;for(let[n,r]of e.lines.entries()){if(!o?.classList.contains(`prb-code-deleted`))break;Yi(o.querySelector(`.prb-code-line`),r.text,t[n]),o=o.nextElementSibling}}}}async function Zi(e,t=Wi){let n=e.closest(`.prb-code`)?.dataset.syntax,r=e.textContent??``;if(!n||!(n in Ri)||r===``)return;let i=await t.tokenize(r,n);if(!e.isConnected||e.childElementCount!==0||e.textContent!==r)return;let a=qi(r,i?.[0]);a!==null&&i?.length===1&&(e.innerHTML=a)}var F=document.body,Qi=F.dataset.apiBase??``,$i=F.dataset.token??``,ea=F.dataset.editorLabel??``,ta=F.dataset.editorTemplate??``,na=F.dataset.repoPath??``,ra=F.dataset.explainPrompt??``,ia=F.dataset.sessionId??``;function I(e){return`${Qi}${e}?t=${encodeURIComponent($i)}`}function L(e){fetch(I(`/event`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e),keepalive:!0}).catch(()=>{})}var aa=Jn({endpoint:I,showDiagrams:()=>_a(`diagram`),showMap:()=>_a(`map`),showChangeMap:e=>oa.show(e)}),oa=Kr({endpoint:I,showView:e=>_a(e)}),sa=null,ca=`the whole change`;function la(e){let t=gt(e,ua),n=mt(t);window.location.hash!==n&&history.pushState(t,``,n),da(t)}var R=null,ua=document.querySelector(`[data-guide-start]`)?.dataset.guideStart??null;function da(e){let t=gt(e,ua);if(t!==e){let{kind:e,view:n,focus:r,...i}=history.state??{};history.replaceState({...i,...t},``,mt(t))}let n=!R||!St(R,t);R=t,n&&(t.kind===`view`?ya(t.view):Ca(t.sectionId)),ma(t.focus??null)}var fa={history,apply:da},pa=Nt(document,{onOpen:e=>e.hasAttribute(`data-ask-buddy-menu`)?Wo(e):Go(e),onClose:Go});function ma(e){Et(document.querySelector(`.prb-body`),document,e),pa.closeAll(),e===`buddy`&&lo()}function ha(e){R&&(R.focus===e?wt(R,fa):Ct(R,e,fa))}window.addEventListener(`keydown`,e=>{!R||!Tt(e,document,!!R.focus)||(e.preventDefault(),wt(R,fa))},!0);var ga=[`map`,`diagram`];function _a(e){la({kind:`view`,view:e,...ga.includes(e)&&ga.includes(R?.focus??``)?{focus:e}:{}})}function va(e){la({kind:`section`,sectionId:e,...R?.focus===`guide`?{focus:`guide`}:{}})}function ya(e){for(let t of document.querySelectorAll(`.prb-view`))t.hidden=t.dataset.view!==e;for(let t of document.querySelectorAll(`[data-view-nav]:not([role="tab"])`))t.setAttribute(`aria-current`,String(t.dataset.viewNav===e||t.dataset.viewAlso===e));L({event:`view_opened`,view:e}),e===`diagram`&&aa.drawPane(),e===`map`&&oa.layout(),ba(),document.querySelector(`.prb-doc`)?.scrollTo({top:0})}function ba(){Ht(),sa=null,ca=`the whole change`,wa()}function xa(e,t){let n=document.getElementById(e.getAttribute(`aria-controls`)??``);n&&(e.setAttribute(`aria-expanded`,String(t)),e.setAttribute(`aria-label`,`${t?`Collapse`:`Expand`} ${e.dataset.railToggle??`this section`}`),n.hidden=!t)}function Sa(){for(let e of document.querySelectorAll(`[data-rail-toggle]`)){let t=document.getElementById(e.getAttribute(`aria-controls`)??``);(t?.contains(document.getElementById(`prb-rail-path`))||t?.id===`prb-rail-path`)&&xa(e,!0)}}function Ca(e){ya(`guide`),Sa(),Vt(e);let t=zt(e);if(!t)return;let n=document.querySelector(`[data-goto-section="${CSS.escape(e)}"]`);L({event:`theme_opened`,themeIndex:Number(n?.dataset.themeIndex??-1),attention:n?.querySelector(`.prb-attention`)?.dataset.attention??`medium`,isRecommendedStart:n?.dataset.recommendedStart===`true`}),sa=e,ca=t.querySelector(`.pr-helper-guide-section-title`)?.textContent?.trim()??`this theme`,wa()}function wa(){let e=document.querySelector(`[data-ask-scope]`);e&&(e.textContent=ca)}function z(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`)}function Ta(e){return e.tagName===`LI`?{parent:e,position:`beforeend`}:{parent:e,position:`afterend`}}async function Ea(e){let t=e.tagName===`LI`?e.querySelector(`:scope > .prb-code`):e.nextElementSibling;if(t?.classList.contains(`prb-code`)){t.remove(),e.setAttribute(`aria-expanded`,`false`);return}let n=e.dataset.file;if(!n)return;let r=Number(e.dataset.line)||0,i=e.tagName!==`LI`,a=document.createElement(`div`);a.className=`prb-code`,a.innerHTML=`<p class="prb-code-status">Reading…</p>`;let{parent:o,position:s}=Ta(e);o.insertAdjacentElement(s,a),e.setAttribute(`aria-expanded`,`true`),L({event:`file_opened`,fromFinding:i,targeted:r>0}),await Da(a,n,{cited:r,centre:r,expand:0,position:r?2*r:0})}async function Da(e,t,n){try{let{centre:r,expand:i}=n,a=`&path=${encodeURIComponent(t)}${r?`&line=${r}`:``}${i?`&expand=${i}`:``}`,o=await fetch(`${I(`/file`)}${a}`),s=await o.json();if(!o.ok){e.innerHTML=`<p class="prb-code-status">${z(s?.error??`Could not read that file.`)}</p>`;return}Oa(e,s,n)}catch{e.innerHTML=`<p class="prb-code-status">Could not reach PR Review Buddy. The workspace server may have stopped.</p>`}}function Oa(e,t,n){let{cited:r,centre:i,expand:a}=n,o=pi(t,r),s=ta&&na?t.checkout===`absent`?`<button type="button" class="prb-code-open" disabled>Not in your working folder</button>`:`<button type="button" class="prb-code-open" data-open-editor="${z(t.path)}" data-open-line="${r||t.from}">${z(`Open in ${ea||`editor`}`)}</button>`:``,c=t.pullRequest&&t.pullRequest.precise?`<a class="prb-code-open prb-code-pr" href="${z(t.pullRequest.href)}" target="_blank" rel="noopener noreferrer">${z(t.pullRequest.label)}</a>`:``,l=t.truncated?`<button type="button" class="prb-code-more" data-expand-file="${z(t.path)}" data-expand-line="${i||0}" data-expand-cited="${r||0}" data-expand-step="${wi(a,i)}">Show more of this file</button>`:``,u=t.checkout===`differs`?` · your editor will show a different version`:t.checkout===`absent`?` · not in your working folder`:``,d=t.changes===`unavailable`?` · change details unavailable`:``,f=`<div class="prb-code-source"><span>${t.source===`commit`?`Viewing reviewed version${t.sourceSha?` <code>${z(t.sourceSha.slice(0,7))}</code>`:``}${u}${d}`:`Viewing your working folder${d}`}</span>${yi(t.changeAnchors??[],n.position)}</div>`,p=e.hasAttribute(`data-expanded`),m=`<button type="button" class="prb-code-open" data-code-expand aria-expanded="${p}">${p?`Collapse`:`Expand`}</button>`;e.innerHTML=`<div class="prb-code-header">
|
|
141
141
|
<span class="prb-code-range">lines ${t.from}\u2013${t.to} of ${t.totalLines}</span>
|
|
142
142
|
${c}
|
|
143
143
|
${s}
|
|
@@ -148,4 +148,4 @@ import{c as e,i as t,t as n}from"./chunk-BeL0x-wt.js";import{C as r,S as i,_ as
|
|
|
148
148
|
${l}`,hi(e,t),Ai(e),ji(e),(n.focus?xi(e,n.focus):e.querySelector(`.prb-code-target`))?.scrollIntoView({block:`center`}),Xi(e,t)}async function ka(e,t,n){let r=bi(t,n);if(!r)return;let i=xi(e,r.anchor);if(i)t.outerHTML=yi(Si(t),r.key),i.scrollIntoView({block:`center`});else{let t=e.querySelector(`[data-expand-file]`);if(!t?.dataset.expandFile)return;await Da(e,t.dataset.expandFile,{cited:Number(t.dataset.expandCited)||0,centre:r.anchor.line,expand:Math.max(1,(Number(t.dataset.expandStep)||1)-1),position:r.key,focus:r.anchor})}let a=e.querySelector(`[data-change-step="${n}"]`),o=e.querySelector(`[data-change-step="${n===`next`?`previous`:`next`}"]`);(a&&!a.disabled?a:o)?.focus({preventScroll:!0})}function Aa(e,t,n){let r=`${na.replace(/\/$/,``)}/${e}`,i=ta.replace(`{path}`,r).replace(`{line}`,String(Math.max(1,t)));L({event:`editor_opened`,fromFinding:n}),window.location.href=i}var B=document.querySelector(`[data-ask-log]`);B&&B.querySelector(`.prb-msg`)&&B.scrollTo({top:B.scrollHeight});var ja=document.querySelector(`[data-ask-form]`),V=ja?.querySelector(`textarea`);function Ma(e,t){let n=document.createElement(`div`);return n.className=e===`user`?`prb-msg prb-msg-user`:`prb-msg prb-msg-${e===`error`?`error`:`assistant`}`,e===`assistant`?(n.classList.add(`prb-md`),n.innerHTML=re(t)+me(t)):n.textContent=t,B?.appendChild(n),B?.scrollTo({top:B.scrollHeight}),n}function Na(){let e=document.createElement(`div`);return e.className=`prb-thinking`,e.innerHTML=`<i></i><i></i><i></i><span>Reading the change…</span>`,B?.appendChild(e),B?.scrollTo({top:B.scrollHeight}),e}var H=null,U=!!B?.querySelector(`[data-ask-pending]`);function Pa(){let e=document.createElement(`div`);e.className=`prb-stopped`,e.textContent=`Stopped.`,B?.appendChild(e),B?.scrollTo({top:B.scrollHeight})}async function Fa(e,t=`free_text`){let n=e.trim();if(!n||H||U)return;document.querySelector(`.prb-ask-empty`)?.remove(),Ma(`user`,n);let r=Na();H=new AbortController,Ia(!0);try{let e=await fetch(I(`/ask`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({question:n,sectionId:sa,source:t}),signal:H.signal}),i=await e.json().catch(()=>null);if(e.status===409&&(i?.running||i?.updating)){window.location.reload();return}if(r.remove(),i?.stopped){Pa();return}if(!e.ok||!i?.answer){Ma(`error`,i?.error??`Buddy AI did not answer. Check the terminal running PR Review Buddy.`);return}Ma(`assistant`,i.answer)}catch(e){r.remove(),e instanceof DOMException&&e.name===`AbortError`?(Pa(),V&&!V.value&&(V.value=n)):Ma(`error`,`Could not reach PR Review Buddy. The workspace server may have stopped.`)}finally{H=null,Ia(!1)}}function Ia(e){let t=ja?.querySelector(`button`);t&&(t.textContent=e?`Stop`:`Ask`,t.toggleAttribute(`data-stop`,e),t.disabled=!1),V&&(V.disabled=e);for(let t of document.querySelectorAll(La))t.disabled=e;e&&pa.closeAll(),e||V?.focus()}var La=`[data-suggestion], .pr-helper-explain-simply-button`;function Ra(){let e=ja?.querySelector(`button`);e&&(e.textContent=`Stopping…`,e.disabled=!0),fetch(I(`/stop`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({kind:`ask`})}).catch(()=>{}).finally(()=>{H?.abort()})}ja?.addEventListener(`submit`,e=>{if(e.preventDefault(),H||U)return Ra();let t=V?.value??``;V&&(V.value=``),Fa(t,Ba(t))}),U&&Ia(!0);var za=null;function Ba(e){return za&&e.includes(za.text)?za.source:`free_text`}V?.addEventListener(`keydown`,e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),ja?.requestSubmit())}),V?.addEventListener(`input`,()=>{V&&(V.style.height=`auto`,V.style.height=`${Math.min(V.scrollHeight,140)}px`)});async function Va(e){try{await fetch(I(`/state`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({answeredQuestionIds:e})})}catch{}}function Ha(){return[...document.querySelectorAll(`[data-question-answered][data-answered="true"]`)].map(e=>e.dataset.questionAnswered??``).filter(Boolean)}function Ua(e,t){e.dataset.answered=String(t),e.textContent=t?`Mark as unanswered`:`Mark answered`;let n=e.closest(`[data-finding-card]`);n?.classList.toggle(`pr-helper-question-card-answered`,t),n&&Ya(n,t,`questions`),to()}function Wa(){return[...document.querySelectorAll(`[data-issue-dismissed][data-dismissed="true"]`)].map(e=>({id:e.dataset.issueDismissed??``,sessionId:e.dataset.dismissedIn||ia})).filter(e=>e.id)}async function Ga(e){try{await fetch(I(`/state`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({dismissedIssues:e})})}catch{}}function Ka(e,t){e.dataset.dismissed=String(t),e.textContent=t?`Reopen`:`Dismiss`,delete e.dataset.stale,t?e.dataset.dismissedIn=ia:delete e.dataset.dismissedIn;let n=e.closest(`[data-finding-card]`);n&&(n.classList.toggle(`pr-helper-issue-card-dismissed`,t),n.querySelector(`.pr-helper-dismissal-stale`)?.remove(),n.querySelector(`.pr-helper-finding-status-dismissed`)?.remove(),t&&n.querySelector(`.pr-helper-issue-badges`)?.prepend(qa()),Ya(n,t||e.dataset.settled===`true`,`issues`),ro())}function qa(){let e=document.createElement(`span`);return e.className=`pr-helper-finding-status pr-helper-finding-status-dismissed pr-helper-tip`,e.dataset.tip=Ft,e.textContent=`Dismissed by you`,e}var Ja=new WeakMap;function Ya(e,t,n){let r=e.closest(`.pr-helper-closed-findings-list`);if(t!==!!r){if(t){let t=e.parentElement;t&&Ja.set(e,{parent:t,before:e.nextElementSibling}),$a(n).append(e),t&&Qa(t)}else Xa(e,n),(r?.children.length===0?r.closest(`.pr-helper-closed-findings`):null)?.remove();eo(n)}}function Xa(e,t){let n=Ja.get(e);if(n?.parent.isConnected)n.parent.insertBefore(e,n.before);else{let n=Za(e)??document.querySelector(`[data-view="${t}"]`);n?.insertBefore(e,n.querySelector(`.pr-helper-closed-findings`))}e.closest(`.pr-helper-question-group`)?.removeAttribute(`hidden`)}function Za(e){let t=e.dataset.sectionId;return t?document.querySelector(`[data-question-group="${CSS.escape(t)}"]`):null}function Qa(e){let t=e.closest(`.pr-helper-question-group`);t&&!t.querySelector(`[data-finding-card]`)&&(t.hidden=!0)}function $a(e){let t=document.querySelector(`[data-view="${e}"]`),n=t?.querySelector(`[data-closed-findings="${e}"] .pr-helper-closed-findings-list`);if(n)return n;let r=document.createElement(`details`);r.className=`pr-helper-closed-findings`,r.dataset.closedFindings=e;let i=document.createElement(`summary`);i.className=`pr-helper-closed-findings-summary`,i.setAttribute(`data-closed-findings-summary`,``);let a=document.createElement(`div`);return a.className=`pr-helper-closed-findings-list`,r.append(i,a),t?.append(r),a}function eo(e){let t=document.querySelector(`[data-closed-findings="${e}"]`),n=t?.querySelector(`[data-closed-findings-summary]`);if(!t||!n)return;let r=document.querySelectorAll(`[data-view="${e}"] [data-finding-card]`).length,i=t.querySelectorAll(`[data-finding-card]`).length;if(t.toggleAttribute(`data-nothing-open`,r===i),e===`questions`){n.textContent=`Answered (${i})`;return}n.textContent=Lt(no())}function to(){let e=[...document.querySelectorAll(`[data-question-answered]`)];if(e.length===0)return;let t=e.filter(e=>e.dataset.answered!==`true`&&e.dataset.settled!==`true`).length,n=document.querySelector(`.pr-helper-questions-progress`);n&&(n.innerHTML=Rt(e.length,t)),io(`questions`,e.length,t,`question`,`answered`)}function no(){let e=[...document.querySelectorAll(`[data-issue-dismissed]`)],t=0,n=0;for(let r of e){let e=r.dataset.settled===`true`,i=r.dataset.dismissed===`true`&&r.dataset.stale!==`true`;!e&&!i?t+=1:!e&&i&&(n+=1)}return{total:e.length,open:t,done:e.length-t,reviewerClosed:n}}function ro(){let e=no();if(e.total===0)return;let t=document.querySelector(`[data-view="issues"]`),n=t?.querySelector(`.pr-helper-findings-progress`);!n&&t&&e.done>0&&(n=document.createElement(`div`),n.className=`pr-helper-findings-progress`,n.setAttribute(`role`,`status`),t.querySelector(`.prb-doc-title`)?.after(n)),n&&(n.innerHTML=It(e.total,e.open,Pt(e))),io(`issues`,e.total,e.open,`issue`,Pt(e))}function io(e,t,n,r,i){let a=document.querySelector(`[data-view-nav="${e}"] .prb-rail-count`);if(!a)return;let o=e=>`${e} ${r}${e===1?``:`s`}`,s=t-n;a.classList.toggle(`prb-rail-count-done`,t>0&&n===0),t===0?(a.textContent=`0`,a.setAttribute(`aria-label`,`No ${r}s`)):n===0?(a.textContent=`✓`,a.setAttribute(`aria-label`,`All ${o(t)} ${i}`)):(a.textContent=String(n),a.setAttribute(`aria-label`,s===0?o(t):`${n} of ${o(t)} left, ${s} ${i}`))}document.addEventListener(`click`,e=>{let t=e.target,n=t.closest(`[data-rail-toggle]`);if(n){xa(n,n.getAttribute(`aria-expanded`)!==`true`);return}let r=t.closest(`[data-view-nav]`);if(r?.dataset.viewNav){_a(r.dataset.viewNav);return}let i=t.closest(`[data-overview-nav]`);if(i?.dataset.overviewNav){_a(i.dataset.overviewNav===`guide`?`guide`:i.dataset.overviewNav);return}let a=t.closest(`[data-goto-section]`);if(a?.dataset.gotoSection){va(a.dataset.gotoSection);return}let o=t.closest(`[data-open-editor]`);if(o?.dataset.openEditor){Aa(o.dataset.openEditor,Number(o.dataset.openLine)||1,!0);return}let s=t.closest(`[data-deletion-toggle]`);if(s){mi(s);return}let c=t.closest(`[data-code-expand]`);if(c){let e=c.closest(`.prb-code`);e&&Pi(e,!e.hasAttribute(`data-expanded`));return}let l=t.closest(`[data-change-step]`);if(l){let e=l.closest(`[data-change-navigator]`),t=l.closest(`.prb-code`);e&&t&&!l.disabled&&ka(t,e,l.dataset.changeStep===`previous`?`previous`:`next`);return}let u=t.closest(`[data-full-line]`);if(u){let e=gi(u);e&&Zi(e);return}let d=t.closest(`[data-expand-file]`);if(d?.dataset.expandFile){let e=d.closest(`.prb-code`);if(e){let t=e.querySelector(`[data-change-navigator]`);Da(e,d.dataset.expandFile,{cited:Number(d.dataset.expandCited)||0,centre:Number(d.dataset.expandLine)||0,expand:Number(d.dataset.expandStep)||1,position:Number(t?.dataset.changePosition)||0,focus:Ci(t)})}return}let f=t.closest(`[data-focus-toggle]`);if(f?.dataset.focusToggle){ha(f.dataset.focusToggle);return}let p=t.closest(`[data-prompt-toggle]`);if(p){No(p.getAttribute(`aria-expanded`)===`true`);return}if(t.closest(`[data-ask-buddy-menu]`))return;let m=t.closest(`[data-file]`);if(m?.dataset.file){Ea(m);return}let h=Bt(t);if(h){va(h);return}let g=t.closest(`[data-question-answered]`);if(g?.dataset.questionAnswered){Ua(g,g.dataset.answered!==`true`);let e=Ha();Va(e),L({event:`question_marked_answered`,answered:e.length,total:document.querySelectorAll(`[data-question-answered]`).length});return}let _=t.closest(`[data-issue-dismissed]`);if(_?.dataset.issueDismissed){Ka(_,_.dataset.stale===`true`||_.dataset.dismissed!==`true`);let e=Wa();Ga(e),L({event:`issue_dismissed`,dismissed:e.length,total:document.querySelectorAll(`[data-issue-dismissed]`).length});return}let v=t.closest(`[data-suggestion]`);if(v){Fa(v.textContent??``,`suggestion`);return}if(t.closest(`.pr-helper-explain-simply-button`)){lo(),Fa(ra,`explain_simply`);return}let ee=t.closest(`[data-prompt-use]`);if(ee?.dataset.promptUse){Po(ee.dataset.promptUse);return}let te=t.closest(`[data-prompt-edit]`);if(te?.dataset.promptEdit){Qo(te.dataset.promptEdit);return}if(t.closest(`[data-prompt-add]`)){Qo(``);return}if(t.closest(`[data-ask-toggle]`)){let e=R?.focus;e?(wt(R,fa),so(e!==`buddy`)):so(!oo())}});var W=document.querySelector(`.prb-body`),ao=document.querySelector(`.prb-ask`);function oo(){return!!ao&&getComputedStyle(ao).display!==`none`}function so(e){W&&(W.dataset.ask=e?`open`:`closed`),co(e)}function co(e){for(let t of document.querySelectorAll(`[data-ask-toggle]`))t.setAttribute(`aria-expanded`,String(e))}function lo(){R?.focus&&R.focus!==`buddy`&&wt(R,fa),so(!0)}function uo(){co(oo())}window.addEventListener(`resize`,uo),n(I(`/restart`));var fo=document.querySelector(`[data-file-filter]`),po=document.querySelector(`[data-file-count]`),mo=document.querySelector(`[data-file-none]`);function ho(){let e=(fo?.value??``).trim().toLowerCase(),t=0,n=0;for(let r of document.querySelectorAll(`[data-view="files"] .prb-file`)){let i=e===``||(r.dataset.search??``).includes(e);r.hidden=!i,i&&(n+=1,r.classList.contains(`prb-file-referenced`)||(t+=1));let a=r.nextElementSibling;a?.classList.contains(`prb-code`)&&(a.hidden=!i)}for(let t of document.querySelectorAll(`[data-file-group]`)){let n=t.querySelectorAll(`.prb-file:not([hidden])`).length;t.hidden=n===0;let r=t.querySelector(`[data-group-heading]`);if(!r)continue;let i=Number(r.dataset.groupTotal)||0;r.textContent=e&&n!==i?`${r.dataset.groupHeading} · ${n} of ${i}`:`${r.dataset.groupHeading} · ${i}`}mo&&(mo.hidden=n>0),po&&(po.textContent=e?`${t} of ${go} file${go===1?``:`s`}`:`${go} file${go===1?``:`s`}`)}var go=document.querySelectorAll(`[data-view="files"] .prb-file:not(.prb-file-referenced)`).length;fo?.addEventListener(`input`,ho),fo?.addEventListener(`keydown`,e=>{e.key===`Escape`&&fo.value!==``&&(e.preventDefault(),fo.value=``,ho())}),document.addEventListener(`keydown`,e=>{if(e.key!==`Enter`&&e.key!==` `)return;let t=e.target,n=t.closest(`.prb-file[data-file][role="button"]`);!n||n!==t||(e.preventDefault(),Ea(n))});var _o=320,vo=()=>Math.round(window.innerWidth/2),yo=e=>Math.round(Math.min(vo(),Math.max(_o,e)));function bo(e){W&&(e===null?W.style.removeProperty(`--ask-width`):W.style.setProperty(`--ask-width`,`${e}px`))}function xo(){return ao?Math.round(ao.getBoundingClientRect().width):_o}function So(e){fetch(I(`/prefs`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({askWidth:e})}).catch(()=>{})}var G=document.querySelector(`[data-ask-resize]`);G?.addEventListener(`pointerdown`,e=>{if(e.button!==0||!W||!ao)return;e.preventDefault(),G.setPointerCapture(e.pointerId),W.dataset.resizing=`true`;let t=e.clientX,n=xo(),r=e=>{bo(yo(n+(t-e.clientX)))},i=()=>{G.removeEventListener(`pointermove`,r),G.removeEventListener(`pointerup`,i),G.removeEventListener(`pointercancel`,i),delete W.dataset.resizing,So(xo())};G.addEventListener(`pointermove`,r),G.addEventListener(`pointerup`,i),G.addEventListener(`pointercancel`,i)}),G?.addEventListener(`keydown`,e=>{let t=e.shiftKey?64:16;if(e.key===`ArrowLeft`||e.key===`ArrowRight`){e.preventDefault();let n=e.key===`ArrowLeft`?t:-t,r=yo(xo()+n);bo(r),So(r);return}(e.key===`Home`||e.key===`Escape`)&&(e.preventDefault(),bo(null),So(null))}),G?.addEventListener(`dblclick`,()=>{bo(null),So(null)}),window.addEventListener(`resize`,()=>{oo()&&W?.style.getPropertyValue(`--ask-width`)&&bo(yo(xo()))});var Co=3e4,wo=document.visibilityState===`visible`?Date.now():null,To=0;function Eo(){wo!==null&&(To+=Date.now()-wo,wo=Date.now())}function Do(){Eo();let e=Math.round(To/1e3);return To-=e*1e3,e}document.addEventListener(`visibilitychange`,()=>{document.visibilityState===`visible`?wo=Date.now():(Eo(),wo=null)}),setInterval(()=>{let e=Do();e>0&&L({event:`workspace_heartbeat`,visibleSeconds:e})},Co),window.addEventListener(`pagehide`,()=>{let e=I(`/event`),t=JSON.stringify({event:`review_completed`,trailingSeconds:Do()});navigator.sendBeacon?.(e,new Blob([t],{type:`application/json`}))||fetch(e,{method:`POST`,headers:{"content-type":`application/json`},body:t,keepalive:!0}).catch(()=>{})});var Oo=document.querySelector(`[data-prompt-bank]`),ko=document.querySelector(`[data-prompt-list]`),K=Ao();function Ao(){try{let e=JSON.parse(Oo?.dataset.prompts??`[]`);return Array.isArray(e)?e:[]}catch{return[]}}function jo(){if(!ko)return;ko.innerHTML=K.map(e=>`<span class="prb-bank-item">
|
|
149
149
|
<button type="button" class="prb-bank-use" data-prompt-use="${z(e.id)}" title="${z(e.prompt)}">${z(e.name)}</button>
|
|
150
150
|
<button type="button" class="prb-bank-edit" data-prompt-edit="${z(e.id)}" aria-label="Edit ${z(e.name)}">✎</button>
|
|
151
|
-
</span>`).join(``);let e=document.querySelector(`[data-prompt-count]`);e&&(e.textContent=String(K.length)),Bo()}async function Mo(e){try{let t=await(await fetch(I(`/prompts`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({prompts:e})})).json().catch(()=>null);K=Array.isArray(t?.prompts)?t.prompts:K}catch{}jo()}function No(e){document.querySelector(`[data-prompt-toggle]`)?.setAttribute(`aria-expanded`,String(!e)),Oo?.toggleAttribute(`data-collapsed`,e),ko&&(ko.hidden=e),fetch(I(`/prefs`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({promptsCollapsed:e})}).catch(()=>{})}function Po(e){let t=K.find(t=>t.id===e);!t||!V||(V.value=Ut(V.value,t.prompt),lo(),V.focus(),V.setSelectionRange(V.value.length,V.value.length),V.dispatchEvent(new Event(`input`)))}var Fo=document.querySelector(`.prb-doc`),Io=null,Lo=null;function Ro(){B&&(Lo?.(),Lo=Ze(B,{layout:`flat`,actions:et.map(e=>({id:e.id,label:e.label})),onChoose:(e,t)=>Vo(e,`selection`,t)}))}function zo(){return[...Qe.map(e=>({id:e.id,label:e.label})),...K.map(e=>({id:ot(e.id),label:e.name,section:at}))]}function Bo(){Fo&&(Io?.(),Io=Ze(Fo,{triggerLabel:`Ask Buddy AI`,actions:zo(),ignoreWithin:`[data-ask-buddy-menu]`,onChoose:(e,t)=>Vo(e,`selection`,t)}))}function Vo(e,t,n){Ot(e,{context:t,text:n},{savedPrompt:e=>K.find(t=>t.id===e)?.prompt??null,stage:e=>Ho(e,t),send:e=>{lo(),Fa(e,`finding`)}})}function Ho(e,t){V&&(za={text:e,source:t},V.value=Ut(V.value,e),lo(),V.focus(),V.setSelectionRange(V.value.length,V.value.length),V.dispatchEvent(new Event(`input`)))}function Uo(e){return e.closest(`[data-finding-card]`)?.querySelector(`[data-copy-source]`)?.getAttribute(`data-copy-source`)??``}function Wo(e){let t=e.querySelector(`[data-menu-panel]`);if(t){t.innerHTML=Ue(zo());for(let e of t.querySelectorAll(`[data-selection-action]`))e.setAttribute(`role`,`menuitem`);if(H||U)for(let e of t.querySelectorAll(`button`))e.disabled=!0}}function Go(e){let t=e.querySelector(`[data-menu-items]`),n=e.querySelector(`[data-menu-confirm]`);t&&(t.hidden=!1),n&&(n.hidden=!0),e.querySelector(`[data-menu-error]`)?.remove()}document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-ask-buddy-menu] [data-selection-action]`),n=t?.closest(`[data-ask-buddy-menu]`),r=t?.dataset.selectionAction;if(!n||!r)return;let i=Uo(n);pa.close(n),i&&Vo(r,`finding`,i)}),Bo(),Ro(),Te(document);var Ko=document.querySelector(`[data-prompt-dialog]`),qo=document.querySelector(`[data-prompt-name]`),Jo=document.querySelector(`[data-prompt-text]`),Yo=document.querySelector(`[data-prompt-delete]`),Xo=document.getElementById(`prb-prompt-title`),Zo=``;function Qo(e){let t=K.find(t=>t.id===e);Zo=t?.id??``,Xo&&(Xo.textContent=t?`Edit prompt`:`Save a prompt`),qo&&(qo.value=t?.name??``),Jo&&(Jo.value=t?.prompt??``),Yo&&(Yo.hidden=!t),Ko?.showModal(),qo?.focus()}async function $o(){let e=qo?.value.trim()??``,t=Jo?.value.trim()??``;if(!e||!t){(e?Jo:qo)?.focus();return}let n=Zo?K.map(n=>n.id===Zo?{...n,name:e,prompt:t}:n):[...K,{id:crypto.randomUUID(),name:e,prompt:t}];Ko?.close(),await Mo(n)}async function es(){if(!Zo)return;let e=K.filter(e=>e.id!==Zo);Ko?.close(),await Mo(e)}document.querySelector(`[data-prompt-cancel]`)?.addEventListener(`click`,()=>Ko?.close()),Yo?.addEventListener(`click`,()=>void es()),document.querySelector(`[data-prompt-save]`)?.addEventListener(`click`,()=>void $o());var q=document.querySelector(`[data-fresh-region]`),J=document.querySelector(`[data-fresh-status]`),ts=document.querySelector(`[data-fresh-check]`),Y=us(q?.dataset.report),ns=`prb-fresh-reopen`,rs=cs(),is=q?.dataset.dismissedSha,as=ss(q?.dataset.availability),X=os(q?.dataset.remote);function os(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}function ss(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}function cs(){try{return sessionStorage.getItem(ns)!==null&&(sessionStorage.removeItem(ns),!0)}catch{return!1}}rs&&Ts(),ts?.addEventListener(`click`,()=>void ps()),q?.addEventListener(`click`,e=>{let t=e.target;if(t.closest(`[data-fresh-close]`))return rs=!1,Ts();let n=t.closest(`[data-fresh-dismiss]`);n&&(is=n.dataset.freshDismiss||void 0,rs=!1,Ts(),ls())});function ls(){fetch(I(`/state`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({dismissFreshnessSha:is??null})}).catch(()=>{})}function us(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}var ds=Dn(),fs=!1,Z=null;async function ps(){if(fs)return;fs=!0,ys(!0),Z&&await Z;let e=bs(Y,X),t=await hs(!1);ys(!1),t&&ws(),fs=!1,t&&(Y?.code.state===`changed`||X!==null)&&is!==void 0&&(is=void 0,ls()),Ts(),ms(t?bs(Y,X)===e?`No change`:`Updated`:`Could not check`)}function ms(e){J&&(J.textContent=e,window.setTimeout(Es,2600))}async function hs(e){let t=ds.snapshot();try{let n=await(await fetch(`${I(`/freshness`)}${e?`&quiet=1`:``}`)).json();Y=n.report??null,as=n.availability??null,X=n.remote??null,xs=n.kiss??null,n.kissDismissedSha!==void 0&&(Ss=n.kissDismissedSha??void 0),n.prState!==void 0&&vs(n.prState);let r=En(n.standing);return r&&ds.current(t)&&_n(document,r),!0}catch{return!1}}async function gs(){if(fs||Z||!q)return;let e=bs(Y,X),t=JSON.stringify(xs);Z=hs(!0);let n=await Z;Z=null,_s=Date.now(),n&&(bs(Y,X)!==e&&Ts(),JSON.stringify(xs)!==t&&ws())}var _s=Date.now();function vs(e){let t=document.querySelector(`[data-pr-state-slot]`);if(!t)return;let n=gn(e,t.hasAttribute(`data-beside-number`));t.innerHTML!==n&&(t.innerHTML=n)}function ys(e){ts&&(ts.disabled=e),J&&e&&(J.textContent=`Checking…`,J.dataset.state=`checking`)}function bs(e,t){if(!e)return JSON.stringify({report:`none`,remote:t});let{checkedAt:n,...r}=e;return JSON.stringify({...r,remote:t})}var Q=document.querySelector(`[data-kiss-fresh-region]`),xs=Cs(Q?.dataset.freshness),Ss=Q?.dataset.dismissedSha;function Cs(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}function ws(){Q&&(Q.innerHTML=hn(Q.dataset.reviewedSha??``,xs,{dismissedSha:Ss,actions:$i!==``}))}Q?.addEventListener(`click`,e=>{let t=e.target.closest(`[data-kiss-freshness-dismiss]`);t&&(Ss=t.dataset.kissFreshnessDismiss||void 0,ws(),fetch(I(`/state`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({dismissKissFreshnessSha:Ss??null})}).catch(()=>{}))});function Ts(){q&&(q.innerHTML=Xt(Y,{dismissedSha:is,open:rs,actions:$i!==``,availability:as,remote:X}),Es())}function Es(){if(J&&(Y||X)){let{label:e,state:t}=Yt(Y,X);J.textContent=e,J.dataset.state=t}}document.addEventListener(`click`,e=>{let t=e.target,n=t.closest(`[data-copy-command]`);if(n)return Ds(n);let r=t.closest(`[data-notice-dismiss]`);if(r){r.closest(`[data-notice]`)?.remove(),fetch(I(`/prefs`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({dismissNotice:r.dataset.noticeDismiss})}).catch(()=>{});return}let i=t.closest(`[data-pr-recheck]`);if(i)return void ks(i);let a=t.closest(`[data-review-update]`);if(a)return void Ms(a);t.closest(`[data-update-close]`)&&document.querySelector(`[data-update-result]`)?.remove()});function Ds(e){let t=e.dataset.copyCommand??``;navigator.clipboard?.writeText(t).then(()=>Os(e,`Copied`),()=>Os(e,`Select it`))}function Os(e,t,n=1400){let r=e.textContent;e.textContent=t,setTimeout(()=>{e.textContent=r},n)}async function ks(e){let t=[...document.querySelectorAll(`[data-pr-recheck]`)];for(let e of t)e.disabled=!0;let n=Date.now(),r=()=>{let e=Math.max(1,Math.round((Date.now()-n)/1e3));for(let n of t){let t=As(n);t?t.innerHTML=`<span class="prb-spinner" aria-hidden="true"></span>Re-checking the conversation, ${e}s. ${Ns}`:n.innerHTML=`<span class="prb-spinner" aria-hidden="true"></span>Checking… ${e}s`}};r();let i=window.setInterval(r,1e3),a=As(e)?null:Ps(e);try{await fetch(I(`/refresh`),{method:`POST`})}catch{}finally{window.clearInterval(i),a?.remove()}As(e)&&js(),window.location.reload()}function As(e){return e.closest(`.prb-fresh-notes p`)}function js(){try{sessionStorage.setItem(ns,`1`)}catch{}}async function Ms(e){let t=[...document.querySelectorAll(`[data-review-update]`)];for(let e of t)e.disabled=!0,e.innerHTML=`<span class="prb-spinner" aria-hidden="true"></span>Updating…`;let n=!1,r=()=>{n||(n=!0,window.clearInterval(i),window.location.reload())},i=window.setInterval(async()=>{try{let e=await(await fetch(I(`/job`))).json();e.update&&e.update.phase!==`none`&&!cn(e.update.phase)&&r()}catch{}},500);try{await fetch(I(`/update`),{method:`POST`})}catch{}r()}var Ns=`Fetching the latest threads from your pull request. This usually takes under a minute.`;function Ps(e){let t=e.parentElement;if(!t)return null;let n=document.createElement(`span`);return n.className=`prb-recheck-status`,n.setAttribute(`role`,`status`),n.textContent=Ns,t.appendChild(n),n}var Fs=An(document),Is=null,Ls=Date.now();function Rs(){Is===null&&(Is=window.setTimeout(()=>{Is=null,zs()},i(Date.now()-Ls)))}async function zs(){try{let e=await(await fetch(I(`/job`))).json();if(U&&!e.ask||Vs&&!e.diagram){window.location.reload();return}let t={job:e,kiss:e.kiss,update:e.update};for(let[e,n]of Fs){let r=t[e];if(r){if(jn(e,r,document)){window.location.reload();return}e===`update`||n.matches(`[data-progress-pane]`)?(Nn(n,r.phase,r.progress),Pn(n)):Bs(n,r.progress)}}}catch{}Rs()}function Bs(e,t){if(!t)return;let n=e.querySelector(`.prb-job-progress`);n||(n=document.createElement(`span`),n.className=`prb-job-progress`,e.querySelector(`p`)?.appendChild(n)),n.textContent=` ${t}`}var Vs=document.querySelector(`[data-diagram-running]`)!==null;(Fs.size>0||U||Vs)&&(Ls=Date.now(),Rs());function Hs(e){let t=e.parentElement;if(!t)return;let n=t.querySelector(`.prb-job-retry-status`);n||(n=document.createElement(`p`),n.className=`prb-job-retry-status`,n.setAttribute(`role`,`status`),t.insertBefore(n,e.nextSibling)),n.textContent=`The retry could not be started. You can try again.`}function Us(e){e.parentElement?.querySelector(`.prb-job-retry-status`)?.remove()}document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-job-retry]`);t&&(t.disabled=!0,t.textContent=`Retrying…`,Us(t),fetch(I(`/retry`),{method:`POST`}).then(e=>{if(!e.ok)throw Error(`refused`);Ls=Date.now(),Rs()}).catch(()=>{t.disabled=!1,t.textContent=`Retry`,Hs(t)}))}),document.addEventListener(`change`,e=>{let t=e.target.closest(`[data-kiss-audience]`);if(!t)return;let n=t.closest(`[data-kiss-run-control]`)?.querySelector(`[data-kiss-run]`);n&&(n.disabled=!1)}),document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-kiss-run]`);if(!t||t.disabled)return;let n=t.closest(`[data-kiss-run-control]`),r=n?.querySelector(`[data-kiss-audience]:checked`)?.value;r&&(t.disabled=!0,t.innerHTML=`<span class="prb-spinner" aria-hidden="true"></span>Starting…`,fetch(I(`/kiss`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({audience:r})}).then(e=>{if(e.ok)window.location.reload();else throw Error(`refused`)}).catch(()=>{t.disabled=!1,t.textContent=`Run KISS review`;let e=document.createElement(`p`);e.className=`prb-kiss-refused`,e.setAttribute(`role`,`status`),e.textContent=`The KISS review could not be started. You can try again.`,n?.querySelector(`.prb-kiss-refused`)?.remove(),n?.appendChild(e)}))});var Ws=document.body.dataset.defaultView||`overview`;window.addEventListener(`popstate`,e=>{da(e.state??vt(window.location.hash)??{kind:`view`,view:Ws})});var Gs=vt(window.location.hash);Gs?da(Gs):(R={kind:`view`,view:Ws},history.replaceState(R,``,window.location.pathname+window.location.search)),uo(),wa();var Ks=e=>{for(let t of document.querySelectorAll(`[data-analysis-details][open]`))(!e||!t.contains(e))&&(t.open=!1)};document.addEventListener(`click`,e=>{Ks(e.target)}),document.addEventListener(`keydown`,e=>{if(e.key!==`Escape`)return;let t=document.querySelector(`[data-analysis-details][open]`);t&&(Ks(),t.querySelector(`summary`)?.focus())});var $=document.querySelector(`.prb-header [data-menu]`);if($){let e=$.querySelector(`[data-menu-panel]`),t=$.querySelector(`[data-menu-items]`),n=$.querySelector(`[data-menu-confirm]`),i=$.querySelector(`[data-confirm-delete]`),o=()=>Go($);$.addEventListener(`click`,e=>{let i=e.target,a=i?.closest(`[data-copy-id]`);if(a?.dataset.copyId){e.stopPropagation(),r(a,a.dataset.copyId);return}let u=i?.closest(`[data-save-toggle]`);if(u){e.stopPropagation(),c(u);return}if(i?.closest(`[data-fresh-check]`)){pa.closeAll();return}let d=i?.closest(`[data-mark-status]`);if(d){e.stopPropagation(),s(d,`/state`,{complete:d.dataset.markStatus===`complete`},e=>({complete:typeof e.completedAt==`number`,queued:e.queued===!0}));return}let f=i?.closest(`[data-lifecycle-set]`);if(f){e.stopPropagation(),s(f,`/lifecycle`,{state:f.dataset.lifecycleSet},e=>({lifecycle:wn(e.lifecycle),queued:e.queued===!0}));return}let p=i?.closest(`[data-queue-action]`);if(p){e.stopPropagation(),s(p,`/queue`,{action:p.dataset.queueAction},e=>({lifecycle:wn(e.lifecycle),queued:e.queued===!0}));return}if(i?.closest(`[data-delete]`)){e.stopPropagation(),t&&(t.hidden=!0),n&&(n.hidden=!1);return}if(i?.closest(`[data-cancel-delete]`)){e.stopPropagation(),o();return}i?.closest(`[data-confirm-delete]`)&&(e.stopPropagation(),l())});let s=async(t,n,r,i)=>{$.querySelector(`[data-menu-error]`)?.remove(),t.disabled=!0;let a=ds.begin(),o=null;try{let e=await fetch(I(n),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(r)}),t=await e.json().catch(()=>null);e.ok&&t?_n(document,i(t)):o=typeof t?.error==`string`?t.error:`That could not be changed.`}catch{o=`The workspace server did not answer. It may have stopped.`}finally{a()}if(t.disabled=!1,o===null)return void pa.closeAll();let s=document.createElement(`p`);s.className=`prb-menu-error`,s.setAttribute(`data-menu-error`,``),s.textContent=o,e?.append(s)},c=async e=>{let t=e.getAttribute(`aria-pressed`)!==`true`;e.disabled=!0;let n=null;try{let e=await fetch(I(`/state`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({pinned:t})});e.ok&&(n=(await e.json()).pinned===!0)}catch{}if(e.disabled=!1,n===null){e.textContent=`Could not save`,window.setTimeout(()=>{e.textContent=a(e.getAttribute(`aria-pressed`)===`true`)},1600);return}e.setAttribute(`aria-pressed`,String(n)),e.textContent=a(n)},l=async()=>{i&&(i.disabled=!0,i.textContent=`Deleting`);let t;try{let e=await fetch(I(`/delete`),{method:`POST`});if(e.ok)return void window.location.replace(`/`);t=(await e.json().catch(()=>null))?.error??`That could not be deleted.`}catch{t=`The workspace server did not answer. It may have stopped.`}i&&(i.disabled=!1,i.textContent=`Delete`),o();let n=document.createElement(`p`);n.className=`prb-menu-error`,n.setAttribute(`data-menu-error`,``),n.textContent=t,e?.append(n)}}t(),setTimeout(()=>{Gi(Li([...document.querySelectorAll(`[data-view="files"] [data-file]`)].map(e=>e.dataset.file??``)))},0),e(window,()=>window.location.reload()),d(window,document.querySelector(`main.prb-doc`));var qs=15e3,Js=6e4;function Ys(){return $i!==``&&document.visibilityState===`visible`&&!Fs.has(`update`)}document.addEventListener(`visibilitychange`,()=>{Ys()&&Date.now()-_s>=qs&&gs()}),window.setInterval(()=>{Ys()&&gs()},Js);export{O as t};
|
|
151
|
+
</span>`).join(``);let e=document.querySelector(`[data-prompt-count]`);e&&(e.textContent=String(K.length)),Bo()}async function Mo(e){try{let t=await(await fetch(I(`/prompts`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({prompts:e})})).json().catch(()=>null);K=Array.isArray(t?.prompts)?t.prompts:K}catch{}jo()}function No(e){document.querySelector(`[data-prompt-toggle]`)?.setAttribute(`aria-expanded`,String(!e)),Oo?.toggleAttribute(`data-collapsed`,e),ko&&(ko.hidden=e),fetch(I(`/prefs`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({promptsCollapsed:e})}).catch(()=>{})}function Po(e){let t=K.find(t=>t.id===e);!t||!V||(V.value=Ut(V.value,t.prompt),lo(),V.focus(),V.setSelectionRange(V.value.length,V.value.length),V.dispatchEvent(new Event(`input`)))}var Fo=document.querySelector(`.prb-doc`),Io=null,Lo=null;function Ro(){B&&(Lo?.(),Lo=Ze(B,{layout:`flat`,actions:et.map(e=>({id:e.id,label:e.label})),onChoose:(e,t)=>Vo(e,`selection`,t)}))}function zo(){return[...Qe.map(e=>({id:e.id,label:e.label})),...K.map(e=>({id:ot(e.id),label:e.name,section:at}))]}function Bo(){Fo&&(Io?.(),Io=Ze(Fo,{triggerLabel:`Ask Buddy AI`,actions:zo(),ignoreWithin:`[data-ask-buddy-menu]`,onChoose:(e,t)=>Vo(e,`selection`,t)}))}function Vo(e,t,n){Ot(e,{context:t,text:n},{savedPrompt:e=>K.find(t=>t.id===e)?.prompt??null,stage:e=>Ho(e,t),send:e=>{lo(),Fa(e,`finding`)}})}function Ho(e,t){V&&(za={text:e,source:t},V.value=Ut(V.value,e),lo(),V.focus(),V.setSelectionRange(V.value.length,V.value.length),V.dispatchEvent(new Event(`input`)))}function Uo(e){return e.closest(`[data-finding-card]`)?.querySelector(`[data-copy-source]`)?.getAttribute(`data-copy-source`)??``}function Wo(e){let t=e.querySelector(`[data-menu-panel]`);if(t){t.innerHTML=Ue(zo());for(let e of t.querySelectorAll(`[data-selection-action]`))e.setAttribute(`role`,`menuitem`);if(H||U)for(let e of t.querySelectorAll(`button`))e.disabled=!0}}function Go(e){let t=e.querySelector(`[data-menu-items]`),n=e.querySelector(`[data-menu-confirm]`);t&&(t.hidden=!1),n&&(n.hidden=!0),e.querySelector(`[data-menu-error]`)?.remove()}document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-ask-buddy-menu] [data-selection-action]`),n=t?.closest(`[data-ask-buddy-menu]`),r=t?.dataset.selectionAction;if(!n||!r)return;let i=Uo(n);pa.close(n),i&&Vo(r,`finding`,i)}),Bo(),Ro(),Te(document);var Ko=document.querySelector(`[data-prompt-dialog]`),qo=document.querySelector(`[data-prompt-name]`),Jo=document.querySelector(`[data-prompt-text]`),Yo=document.querySelector(`[data-prompt-delete]`),Xo=document.getElementById(`prb-prompt-title`),Zo=``;function Qo(e){let t=K.find(t=>t.id===e);Zo=t?.id??``,Xo&&(Xo.textContent=t?`Edit prompt`:`Save a prompt`),qo&&(qo.value=t?.name??``),Jo&&(Jo.value=t?.prompt??``),Yo&&(Yo.hidden=!t),Ko?.showModal(),qo?.focus()}async function $o(){let e=qo?.value.trim()??``,t=Jo?.value.trim()??``;if(!e||!t){(e?Jo:qo)?.focus();return}let n=Zo?K.map(n=>n.id===Zo?{...n,name:e,prompt:t}:n):[...K,{id:crypto.randomUUID(),name:e,prompt:t}];Ko?.close(),await Mo(n)}async function es(){if(!Zo)return;let e=K.filter(e=>e.id!==Zo);Ko?.close(),await Mo(e)}document.querySelector(`[data-prompt-cancel]`)?.addEventListener(`click`,()=>Ko?.close()),Yo?.addEventListener(`click`,()=>void es()),document.querySelector(`[data-prompt-save]`)?.addEventListener(`click`,()=>void $o());var q=document.querySelector(`[data-fresh-region]`),J=document.querySelector(`[data-fresh-status]`),ts=document.querySelector(`[data-fresh-check]`),Y=us(q?.dataset.report),ns=`prb-fresh-reopen`,rs=cs(),is=q?.dataset.dismissedSha,as=ss(q?.dataset.availability),X=os(q?.dataset.remote);function os(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}function ss(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}function cs(){try{return sessionStorage.getItem(ns)!==null&&(sessionStorage.removeItem(ns),!0)}catch{return!1}}rs&&Ts(),ts?.addEventListener(`click`,()=>void ps()),q?.addEventListener(`click`,e=>{let t=e.target;if(t.closest(`[data-fresh-close]`))return rs=!1,Ts();let n=t.closest(`[data-fresh-dismiss]`);n&&(is=n.dataset.freshDismiss||void 0,rs=!1,Ts(),ls())});function ls(){fetch(I(`/state`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({dismissFreshnessSha:is??null})}).catch(()=>{})}function us(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}var ds=Dn(),fs=!1,Z=null;async function ps(){if(fs)return;fs=!0,ys(!0),Z&&await Z;let e=bs(Y,X),t=await hs(!1);ys(!1),t&&ws(),fs=!1,t&&(Y?.code.state===`changed`||X!==null)&&is!==void 0&&(is=void 0,ls()),Ts(),ms(t?bs(Y,X)===e?`No change`:`Updated`:`Could not check`)}function ms(e){J&&(J.textContent=e,window.setTimeout(Es,2600))}async function hs(e){let t=ds.snapshot();try{let n=await(await fetch(`${I(`/freshness`)}${e?`&quiet=1`:``}`)).json();Y=n.report??null,as=n.availability??null,X=n.remote??null,xs=n.kiss??null,n.kissDismissedSha!==void 0&&(Ss=n.kissDismissedSha??void 0),n.prState!==void 0&&vs(n.prState);let r=En(n.standing);return r&&ds.current(t)&&_n(document,r),!0}catch{return!1}}async function gs(){if(fs||Z||!q)return;let e=bs(Y,X),t=JSON.stringify(xs);Z=hs(!0);let n=await Z;Z=null,_s=Date.now(),n&&(bs(Y,X)!==e&&Ts(),JSON.stringify(xs)!==t&&ws())}var _s=Date.now();function vs(e){let t=document.querySelector(`[data-pr-state-slot]`);if(!t)return;let n=gn(e,t.hasAttribute(`data-beside-number`));t.innerHTML!==n&&(t.innerHTML=n)}function ys(e){ts&&(ts.disabled=e),J&&e&&(J.textContent=`Checking…`,J.dataset.state=`checking`)}function bs(e,t){if(!e)return JSON.stringify({report:`none`,remote:t});let{checkedAt:n,...r}=e;return JSON.stringify({...r,remote:t})}var Q=document.querySelector(`[data-kiss-fresh-region]`),xs=Cs(Q?.dataset.freshness),Ss=Q?.dataset.dismissedSha;function Cs(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}function ws(){Q&&(Q.innerHTML=hn(Q.dataset.reviewedSha??``,xs,{dismissedSha:Ss,actions:$i!==``}))}Q?.addEventListener(`click`,e=>{let t=e.target.closest(`[data-kiss-freshness-dismiss]`);t&&(Ss=t.dataset.kissFreshnessDismiss||void 0,ws(),fetch(I(`/state`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({dismissKissFreshnessSha:Ss??null})}).catch(()=>{}))});function Ts(){q&&(q.innerHTML=Xt(Y,{dismissedSha:is,open:rs,actions:$i!==``,availability:as,remote:X}),Es())}function Es(){if(J&&(Y||X)){let{label:e,state:t}=Yt(Y,X);J.textContent=e,J.dataset.state=t}}document.addEventListener(`click`,e=>{let t=e.target,n=t.closest(`[data-copy-command]`);if(n)return Ds(n);let r=t.closest(`[data-notice-dismiss]`);if(r){r.closest(`[data-notice]`)?.remove(),fetch(I(`/prefs`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({dismissNotice:r.dataset.noticeDismiss})}).catch(()=>{});return}let i=t.closest(`[data-pr-recheck]`);if(i)return void ks(i);let a=t.closest(`[data-review-update]`);if(a)return void Ms(a);t.closest(`[data-update-close]`)&&document.querySelector(`[data-update-result]`)?.remove()});function Ds(e){let t=e.dataset.copyCommand??``;navigator.clipboard?.writeText(t).then(()=>Os(e,`Copied`),()=>Os(e,`Select it`))}function Os(e,t,n=1400){let r=e.textContent;e.textContent=t,setTimeout(()=>{e.textContent=r},n)}async function ks(e){let t=[...document.querySelectorAll(`[data-pr-recheck]`)];for(let e of t)e.disabled=!0;let n=Date.now(),r=()=>{let e=Math.max(1,Math.round((Date.now()-n)/1e3));for(let n of t){let t=As(n);t?t.innerHTML=`<span class="prb-spinner" aria-hidden="true"></span>Re-checking the conversation, ${e}s. ${Ns}`:n.innerHTML=`<span class="prb-spinner" aria-hidden="true"></span>Checking… ${e}s`}};r();let i=window.setInterval(r,1e3),a=As(e)?null:Ps(e);try{await fetch(I(`/refresh`),{method:`POST`})}catch{}finally{window.clearInterval(i),a?.remove()}As(e)&&js(),window.location.reload()}function As(e){return e.closest(`.prb-fresh-notes p`)}function js(){try{sessionStorage.setItem(ns,`1`)}catch{}}async function Ms(e){let t=[...document.querySelectorAll(`[data-review-update]`)];for(let e of t)e.disabled=!0,e.innerHTML=`<span class="prb-spinner" aria-hidden="true"></span>Updating…`;let n=!1,r=()=>{n||(n=!0,window.clearInterval(i),window.location.reload())},i=window.setInterval(async()=>{try{let e=await(await fetch(I(`/job`))).json();e.update&&e.update.phase!==`none`&&!cn(e.update.phase)&&r()}catch{}},500);try{await fetch(I(`/update`),{method:`POST`})}catch{}r()}var Ns=`Fetching the latest threads from your pull request. This usually takes under a minute.`;function Ps(e){let t=e.parentElement;if(!t)return null;let n=document.createElement(`span`);return n.className=`prb-recheck-status`,n.setAttribute(`role`,`status`),n.textContent=Ns,t.appendChild(n),n}var Fs=An(document),Is=null,Ls=Date.now();function Rs(){Is===null&&(Is=window.setTimeout(()=>{Is=null,zs()},i(Date.now()-Ls)))}async function zs(){try{let e=await(await fetch(I(`/job`))).json();if(U&&!e.ask||Vs&&!e.diagram){window.location.reload();return}let t={job:e,kiss:e.kiss,update:e.update};for(let[e,n]of Fs){let r=t[e];if(r){if(jn(e,r,document)){window.location.reload();return}e===`update`||n.matches(`[data-progress-pane]`)?(Nn(n,r.phase,r.progress),Pn(n)):Bs(n,r.progress)}}}catch{}Rs()}function Bs(e,t){if(!t)return;let n=e.querySelector(`.prb-job-progress`);n||(n=document.createElement(`span`),n.className=`prb-job-progress`,e.querySelector(`p`)?.appendChild(n)),n.textContent=` ${t}`}var Vs=document.querySelector(`[data-diagram-running]`)!==null;(Fs.size>0||U||Vs)&&(Ls=Date.now(),Rs());function Hs(e){let t=e.parentElement;if(!t)return;let n=t.querySelector(`.prb-job-retry-status`);n||(n=document.createElement(`p`),n.className=`prb-job-retry-status`,n.setAttribute(`role`,`status`),t.insertBefore(n,e.nextSibling)),n.textContent=`The retry could not be started. You can try again.`}function Us(e){e.parentElement?.querySelector(`.prb-job-retry-status`)?.remove()}document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-job-retry]`);t&&(t.disabled=!0,t.textContent=`Retrying…`,Us(t),fetch(I(`/retry`),{method:`POST`}).then(e=>{if(!e.ok)throw Error(`refused`);Ls=Date.now(),Rs()}).catch(()=>{t.disabled=!1,t.textContent=`Retry`,Hs(t)}))}),document.addEventListener(`change`,e=>{let t=e.target.closest(`[data-kiss-audience]`);if(!t)return;let n=t.closest(`[data-kiss-run-control]`)?.querySelector(`[data-kiss-run]`);n&&(n.disabled=!1)}),document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-kiss-run]`);if(!t||t.disabled)return;let n=t.closest(`[data-kiss-run-control]`),r=n?.querySelector(`[data-kiss-audience]:checked`)?.value;r&&(t.disabled=!0,t.innerHTML=`<span class="prb-spinner" aria-hidden="true"></span>Starting…`,fetch(I(`/kiss`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({audience:r})}).then(e=>{if(e.ok)window.location.reload();else throw Error(`refused`)}).catch(()=>{t.disabled=!1,t.textContent=`Run KISS review`;let e=document.createElement(`p`);e.className=`prb-kiss-refused`,e.setAttribute(`role`,`status`),e.textContent=`The KISS review could not be started. You can try again.`,n?.querySelector(`.prb-kiss-refused`)?.remove(),n?.appendChild(e)}))});var Ws=document.body.dataset.defaultView||`overview`;window.addEventListener(`popstate`,e=>{da(e.state??vt(window.location.hash)??{kind:`view`,view:Ws})});var Gs=vt(window.location.hash);Gs?da(Gs):(R={kind:`view`,view:Ws},history.replaceState(R,``,window.location.pathname+window.location.search)),uo(),wa();var Ks=e=>{for(let t of document.querySelectorAll(`[data-analysis-details][open], [data-range-details][open]`))(!e||!t.contains(e))&&(t.open=!1)};document.addEventListener(`click`,e=>{Ks(e.target)}),document.addEventListener(`keydown`,e=>{if(e.key!==`Escape`)return;let t=document.querySelector(`[data-analysis-details][open], [data-range-details][open]`);t&&(Ks(),t.querySelector(`summary`)?.focus())});var $=document.querySelector(`.prb-header [data-menu]`);if($){let e=$.querySelector(`[data-menu-panel]`),t=$.querySelector(`[data-menu-items]`),n=$.querySelector(`[data-menu-confirm]`),i=$.querySelector(`[data-confirm-delete]`),o=()=>Go($);$.addEventListener(`click`,e=>{let i=e.target,a=i?.closest(`[data-copy-id]`);if(a?.dataset.copyId){e.stopPropagation(),r(a,a.dataset.copyId);return}let u=i?.closest(`[data-save-toggle]`);if(u){e.stopPropagation(),c(u);return}if(i?.closest(`[data-fresh-check]`)){pa.closeAll();return}let d=i?.closest(`[data-mark-status]`);if(d){e.stopPropagation(),s(d,`/state`,{complete:d.dataset.markStatus===`complete`},e=>({complete:typeof e.completedAt==`number`,queued:e.queued===!0}));return}let f=i?.closest(`[data-lifecycle-set]`);if(f){e.stopPropagation(),s(f,`/lifecycle`,{state:f.dataset.lifecycleSet},e=>({lifecycle:wn(e.lifecycle),queued:e.queued===!0}));return}let p=i?.closest(`[data-queue-action]`);if(p){e.stopPropagation(),s(p,`/queue`,{action:p.dataset.queueAction},e=>({lifecycle:wn(e.lifecycle),queued:e.queued===!0}));return}if(i?.closest(`[data-delete]`)){e.stopPropagation(),t&&(t.hidden=!0),n&&(n.hidden=!1);return}if(i?.closest(`[data-cancel-delete]`)){e.stopPropagation(),o();return}i?.closest(`[data-confirm-delete]`)&&(e.stopPropagation(),l())});let s=async(t,n,r,i)=>{$.querySelector(`[data-menu-error]`)?.remove(),t.disabled=!0;let a=ds.begin(),o=null;try{let e=await fetch(I(n),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(r)}),t=await e.json().catch(()=>null);e.ok&&t?_n(document,i(t)):o=typeof t?.error==`string`?t.error:`That could not be changed.`}catch{o=`The workspace server did not answer. It may have stopped.`}finally{a()}if(t.disabled=!1,o===null)return void pa.closeAll();let s=document.createElement(`p`);s.className=`prb-menu-error`,s.setAttribute(`data-menu-error`,``),s.textContent=o,e?.append(s)},c=async e=>{let t=e.getAttribute(`aria-pressed`)!==`true`;e.disabled=!0;let n=null;try{let e=await fetch(I(`/state`),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({pinned:t})});e.ok&&(n=(await e.json()).pinned===!0)}catch{}if(e.disabled=!1,n===null){e.textContent=`Could not save`,window.setTimeout(()=>{e.textContent=a(e.getAttribute(`aria-pressed`)===`true`)},1600);return}e.setAttribute(`aria-pressed`,String(n)),e.textContent=a(n)},l=async()=>{i&&(i.disabled=!0,i.textContent=`Deleting`);let t;try{let e=await fetch(I(`/delete`),{method:`POST`});if(e.ok)return void window.location.replace(`/`);t=(await e.json().catch(()=>null))?.error??`That could not be deleted.`}catch{t=`The workspace server did not answer. It may have stopped.`}i&&(i.disabled=!1,i.textContent=`Delete`),o();let n=document.createElement(`p`);n.className=`prb-menu-error`,n.setAttribute(`data-menu-error`,``),n.textContent=t,e?.append(n)}}t(),setTimeout(()=>{Gi(Li([...document.querySelectorAll(`[data-view="files"] [data-file]`)].map(e=>e.dataset.file??``)))},0),e(window,()=>window.location.reload()),d(window,document.querySelector(`main.prb-doc`));var qs=15e3,Js=6e4;function Ys(){return $i!==``&&document.visibilityState===`visible`&&!Fs.has(`update`)}document.addEventListener(`visibilitychange`,()=>{Ys()&&Date.now()-_s>=qs&&gs()}),window.setInterval(()=>{Ys()&&gs()},Js);export{O as t};
|