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 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
- ...refs.map((one) => ` prreviewbuddy review --base ${shorthandOf(one.ref)}`)
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 separator = line.indexOf("");
2326
- if (separator === -1) continue;
2327
- const name = line.slice(0, separator).trim();
2328
- const subject = line.slice(separator + 1).trim();
2329
- if (subject) subjects.push(subject);
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
- if (input.base) await verifyBase(root, input.base);
2750
- else await verifyDefaultBase(root);
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-BBjXPfMV.js";
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-BBjXPfMV.js";
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">&minus;${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
- <h2>Ask Buddy AI</h2>
5639
- <span class="prb-ask-scope" data-ask-scope>whole change</span>
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 &lt;commit&gt;</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.49.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: baseline;
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-left: auto;
1592
+ margin: 2px 0 0;
1522
1593
  font-size: var(--t-micro);
1523
1594
  color: var(--text-muted);
1524
- overflow: hidden;
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 scope label, which takes the free space with
4995
- `margin-left: auto`, so the control stays at the right edge beside it. */
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. */
@@ -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,e.title=sa?`Questions are answered about "${ca}"`:`Questions cover the whole change`)}function z(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}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">
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,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}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)}">&#9998;</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};