@dev.fast/whiteboard 0.2.5-preview.20261015.116 → 0.2.5-preview.20261015.118
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{account-alias-ChZR3RIU.js → account-alias-C1ixP6bt.js} +1 -1
- package/dist/agent-cli-CGapivA1.js +2 -0
- package/dist/{agent-cli-CR2PnA9G.js → agent-cli-CPSnWc9V.js} +6 -6
- package/dist/{agent-client-DVd-prfp.js → agent-client-Dogh8I83.js} +3 -3
- package/dist/{authoring-tools-BXKEwhfi.js → authoring-tools-CtsslOEf.js} +2 -2
- package/dist/{background-server-D2Rrr_e2.js → background-server-BKR_lpYb.js} +1 -1
- package/dist/{background-server-Cw7CcfaZ.js → background-server-DJT0CnYH.js} +2 -2
- package/dist/build-info.json +1 -1
- package/dist/{cli-CSrz_wGk.js → cli-Df6p-C19.js} +1 -1
- package/dist/{cli-runner-PlGqBeMw.js → cli-runner-ZktCwlLk.js} +19 -19
- package/dist/cli.js +2 -2
- package/dist/{client-DhZzPePs.js → client-_ltX1mah.js} +2 -2
- package/dist/{headless-host-Cp37C-v0.js → headless-host-Pj2xfGAo.js} +1 -1
- package/dist/{headless-host-CVXTSIlx.js → headless-host-ZNZ_6ZRo.js} +17 -11
- package/dist/{local-data-yfLp5PiJ.js → local-data-D_9S--yI.js} +188 -18
- package/dist/{mcp-DBbDwG4y.js → mcp-Blb7rzGw.js} +3 -3
- package/dist/profile-BUoTujrK.js +2 -0
- package/dist/{profile-pAzg7fxC.js → profile-CKSB6UDi.js} +1 -1
- package/dist/{remote-attach-BAt2eZx3.js → remote-attach-CiOwonJ3.js} +3 -3
- package/dist/{remote-extensions-2Cxf3hMo.js → remote-extensions-ByiuSl1D.js} +1 -1
- package/dist/{remote-extensions-BiNx6NQK.js → remote-extensions-D_4DSOhO.js} +6 -18
- package/dist/{remote-language-server-DQgWUNeV.js → remote-language-server-BQjBk81F.js} +6 -8
- package/dist/{remote-uninstall-DLtDG0o7.js → remote-uninstall-pzHb-Hfd.js} +4 -4
- package/dist/{request-origin-DaRIV3cB.js → request-origin-C-V9f3Fr.js} +1 -1
- package/dist/{review-app-launcher-D7I4DGoH.js → review-app-launcher-S2FZBY4W.js} +2 -2
- package/dist/{review-telemetry-BqB4CiTD.js → review-telemetry-9ceqh4wz.js} +2 -2
- package/dist/server/desktop-host.js +13 -15
- package/dist/{server-discovery-CifQ3yQS.js → server-discovery-CqRxbsER.js} +1 -1
- package/dist/sharing/index.d.ts +11 -5
- package/dist/sharing/index.js +1 -1
- package/dist/{src-Bgvf1sEN.js → src-HnIPjtjx.js} +2 -2
- package/dist/{stored-document-migration-CFOvjRwW.js → stored-document-migration-DenDEYdI.js} +15 -3
- package/dist/{tool-failure-BXWzQG8T.js → tool-failure-aSYcHDxP.js} +1 -1
- package/package.json +5 -4
- package/remote/install.sh +444 -0
- package/src/agent-selection.ts +11 -5
- package/src/cli-runner.ts +3 -3
- package/src/pinned-download.ts +4 -17
- package/src/remote-extensions.ts +4 -3
- package/src/remote-language-server.ts +3 -9
- package/src/review-api/azure-devops-provider.ts +165 -0
- package/src/review-api/document.ts +24 -1
- package/src/review-api/http.ts +1 -3
- package/src/review-api/local-data.ts +19 -10
- package/src/review-api/origin.ts +1 -1
- package/src/review-api/provider.ts +2 -1
- package/src/review-api/store.ts +91 -4
- package/src/review-api/version-cache.ts +36 -0
- package/src/server/hono-http.ts +16 -1
- package/src/server/review-gateway-hosts.ts +1 -7
- package/src/server/review-gateway.ts +2 -1
- package/src/vsix.ts +1 -12
- package/dist/agent-cli-CRPPmS3l.js +0 -2
- package/dist/profile-BSOkA6A-.js +0 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { w as ReviewCliInstallStampSchema } from "./src-
|
|
1
|
+
import { w as ReviewCliInstallStampSchema } from "./src-HnIPjtjx.js";
|
|
2
2
|
import { $ as removeAgentTraceHook, C as disableTraceMachine, E as traceMachineStatus, G as listTraceRepositoryRoots, K as traceRepositoryStatus, Q as installHarnessHooks, S as configureTraceMachine, T as traceMachineEnabled, U as disableAllTraceRepositories, W as enableTraceRepository, Y as AGENT_TRACE_HOOK_AGENTS, Z as describeTraceHookOwners, ft as StoreClient, n as reviewDesktopStateDir, rt as traceScope, st as readStoreAuth } from "./review-home-paths-zwevIq4I.js";
|
|
3
3
|
import { A as withFileLock, F as writeFileAtomicAsync, I as writePrivateJsonAtomic, M as devReviewHome } from "./s3-config-DDWWMh5x.js";
|
|
4
4
|
import { i as readReviewPackageVersion } from "./package-paths-BsuI4WUf.js";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { n as isJsonObject, u as parseJsonText } from "./src-X9phtB2j.js";
|
|
2
2
|
import { T as traceMachineEnabled } from "./review-home-paths-zwevIq4I.js";
|
|
3
|
-
import { a as toolResultText, i as connectReviewInstance, s as ReviewApiError } from "./agent-client-
|
|
3
|
+
import { a as toolResultText, i as connectReviewInstance, s as ReviewApiError } from "./agent-client-Dogh8I83.js";
|
|
4
4
|
import { M as devReviewHome } from "./s3-config-DDWWMh5x.js";
|
|
5
|
-
import { b as selectReviewInstance, u as REVIEW_INSTANCE_ENV } from "./server-discovery-
|
|
6
|
-
import { n as reviewSessionAgent } from "./review-telemetry-
|
|
7
|
-
import { n as REVIEW_VIA_HEADER, t as REVIEW_AGENT_HEADER } from "./request-origin-
|
|
8
|
-
import { i as publicTool, n as RECOVERY, r as callPublicTool, t as toolFailure } from "./tool-failure-
|
|
5
|
+
import { b as selectReviewInstance, u as REVIEW_INSTANCE_ENV } from "./server-discovery-CqRxbsER.js";
|
|
6
|
+
import { n as reviewSessionAgent } from "./review-telemetry-9ceqh4wz.js";
|
|
7
|
+
import { n as REVIEW_VIA_HEADER, t as REVIEW_AGENT_HEADER } from "./request-origin-C-V9f3Fr.js";
|
|
8
|
+
import { i as publicTool, n as RECOVERY, r as callPublicTool, t as toolFailure } from "./tool-failure-aSYcHDxP.js";
|
|
9
9
|
//#region src/review-api/agent-cli.ts
|
|
10
10
|
const reviewAgentCliHelp = "whiteboard api tools (one line per tool)\nwhiteboard api tools <tool-name> (its description and input schema)\nwhiteboard api <tool-name> '<json>'\nwhiteboard api <tool-name> - (read JSON from stdin)\nwhiteboard mcp (stdio MCP adapter; Whiteboard Desktop or whiteboard server start must be running)\nSelect headless state with DEV_REVIEW_SERVER_DIR or whiteboard --state-dir <path> api/mcp.\n";
|
|
11
11
|
async function runReviewAgentCli(input) {
|
|
@@ -20,7 +20,7 @@ async function runReviewAgentCli(input) {
|
|
|
20
20
|
if (extra.length || mode === "mcp" && name) throw new Error("Unexpected arguments. Use whiteboard api --help.");
|
|
21
21
|
const headers = Object.fromEntries([[REVIEW_VIA_HEADER, mode === "mcp" ? "mcp" : "api"], [REVIEW_AGENT_HEADER, reviewSessionAgent(env)]]);
|
|
22
22
|
if (mode === "mcp") {
|
|
23
|
-
const { serveReviewMcp } = await import("./mcp-
|
|
23
|
+
const { serveReviewMcp } = await import("./mcp-Blb7rzGw.js");
|
|
24
24
|
await serveReviewMcp(async (key, agentKind) => {
|
|
25
25
|
const connected = await connectReviewInstance(key ? {
|
|
26
26
|
...env,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { d as isBooleanValue, f as isNumberValue, m as isStringValue, u as parseJsonText } from "./src-X9phtB2j.js";
|
|
2
|
-
import "./src-
|
|
2
|
+
import "./src-HnIPjtjx.js";
|
|
3
3
|
import { t as ReviewInputError } from "./input-error-OLgB_h31.js";
|
|
4
|
-
import { b as selectReviewInstance, c as reviewServerStateDir, d as ReviewInstanceUnavailableError, i as readReviewServerDiscovery, l as serverNotReady, m as healthyReviewInstance, s as reviewServerIsHealthy, y as reviewInstanceUnavailable } from "./server-discovery-
|
|
4
|
+
import { b as selectReviewInstance, c as reviewServerStateDir, d as ReviewInstanceUnavailableError, i as readReviewServerDiscovery, l as serverNotReady, m as healthyReviewInstance, s as reviewServerIsHealthy, y as reviewInstanceUnavailable } from "./server-discovery-CqRxbsER.js";
|
|
5
5
|
//#region ../review-protocol/src/review-api-client.ts
|
|
6
6
|
const defaultRequest = (url, init) => fetch(url, init);
|
|
7
7
|
/** A non-2xx reply; the status tells a caller whether retrying can help. */
|
|
@@ -250,7 +250,7 @@ async function connectReviewInstance(env = process.env, headers = {}, options =
|
|
|
250
250
|
const selection = await selectReviewInstance({ env });
|
|
251
251
|
const discovery = healthyReviewInstance(selection);
|
|
252
252
|
if (!discovery) {
|
|
253
|
-
const { ensureServerWithoutDesktop } = await import("./background-server-
|
|
253
|
+
const { ensureServerWithoutDesktop } = await import("./background-server-BKR_lpYb.js");
|
|
254
254
|
const server = await ensureServerWithoutDesktop({
|
|
255
255
|
selection,
|
|
256
256
|
env,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { _ as activityUpdateSchema, g as activityEndSchema, h as activityBeginSchema, i as commandSchema, n as uploadSchema } from "./local-data-
|
|
2
|
-
import {
|
|
1
|
+
import { _ as activityUpdateSchema, g as activityEndSchema, h as activityBeginSchema, i as commandSchema, n as uploadSchema } from "./local-data-D_9S--yI.js";
|
|
2
|
+
import { S as publishedEditSchema, y as pathTargetSchema } from "./stored-document-migration-DenDEYdI.js";
|
|
3
3
|
import { t as ReviewInputError } from "./input-error-OLgB_h31.js";
|
|
4
4
|
import { t as findReviewPackageRoot } from "./package-paths-BsuI4WUf.js";
|
|
5
5
|
import { z } from "zod";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as headlessServerOwner, c as stopBackgroundServer, i as ensureServerWithoutDesktop, r as ensureBackgroundServer } from "./background-server-
|
|
1
|
+
import { a as headlessServerOwner, c as stopBackgroundServer, i as ensureServerWithoutDesktop, r as ensureBackgroundServer } from "./background-server-DJT0CnYH.js";
|
|
2
2
|
export { ensureBackgroundServer, ensureServerWithoutDesktop, headlessServerOwner, stopBackgroundServer };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "./review-home-paths-zwevIq4I.js";
|
|
2
2
|
import { D as liveLockOwner, O as processIsAlive } from "./s3-config-DDWWMh5x.js";
|
|
3
3
|
import { t as findReviewPackageRoot } from "./package-paths-BsuI4WUf.js";
|
|
4
|
-
import { a as readReviewServerHealth, c as reviewServerStateDir, i as readReviewServerDiscovery, n as desktopOwnsHome, p as desktopUsesHome, r as headlessServerLockPath } from "./server-discovery-
|
|
5
|
-
import { t as desktopApplicationInstalled } from "./review-app-launcher-
|
|
4
|
+
import { a as readReviewServerHealth, c as reviewServerStateDir, i as readReviewServerDiscovery, n as desktopOwnsHome, p as desktopUsesHome, r as headlessServerLockPath } from "./server-discovery-CqRxbsER.js";
|
|
5
|
+
import { t as desktopApplicationInstalled } from "./review-app-launcher-S2FZBY4W.js";
|
|
6
6
|
import { mkdir, open, readFile, realpath, stat } from "node:fs/promises";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import { spawn } from "node:child_process";
|
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.2.5-preview.20261015.
|
|
1
|
+
{"version":"0.2.5-preview.20261015.118","commit":"dc3ea1aee29b6ccf8860a763db26bc86ca52532c","dirty":true,"builtAt":"2026-10-15T17:51:10.990Z"}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { C as setLocalVcsCommandObserver, E as __toESM, T as __require, w as __commonJSMin } from "./src-BMPuxWv4.js";
|
|
2
2
|
import { c as jsonString, n as isJsonObject, u as parseJsonText } from "./src-X9phtB2j.js";
|
|
3
|
-
import { _ as REVIEW_REMOTE_AGENT_IDS, p as REVIEW_CLI_INSTALL_TARGET_LABELS, v as REVIEW_REMOTE_ATTACH_BEGIN, y as REVIEW_REMOTE_ATTACH_END } from "./src-
|
|
3
|
+
import { _ as REVIEW_REMOTE_AGENT_IDS, p as REVIEW_CLI_INSTALL_TARGET_LABELS, v as REVIEW_REMOTE_ATTACH_BEGIN, y as REVIEW_REMOTE_ATTACH_END } from "./src-HnIPjtjx.js";
|
|
4
4
|
import { A as runTraceDeny, E as traceMachineStatus, F as describeSelection, H as resolveTraceRepositoryTarget, J as HOSTED_CAPTURE_SCOPE_DESCRIPTION, K as traceRepositoryStatus, L as loadS3TraceStorage, M as runTraceSessions, N as runTraceStoreDelete, P as runTraceStoreInfo, T as traceMachineEnabled, V as requireTraceConsent, X as agentTraceHomeDirectory, _ as runTraceRepair, _t as jsonRequestedInArgv, b as runTraceGitHook, c as registerTraceCommands, ct as runStoreLogin, d as runTraceList$1, dt as StoreApiError, et as resolveTraceCommand, f as runTracePull$1, ft as StoreClient, g as runTraceInstallMachine, gt as humanStream, h as runTraceEnable, ht as failWithJsonError, it as DEFAULT_STORE_ORIGIN, j as runTraceOnboard, k as runTraceAllow, l as resolveTraceReadStorage, lt as runStoreLogout, m as runTraceDisable, mt as emitJsonEvent, nt as traceHomeDir, p as runTraceShow, pt as withStoreAuthorization, q as readTraceUserConfig, rt as traceScope, st as readStoreAuth, u as runTraceBlame, ut as runStoreWhoami, v as runTraceStatus, w as readLegacyCaptureSettings, x as runTraceHook, y as runTraceSync, z as selectTraceStorage } from "./review-home-paths-zwevIq4I.js";
|
|
5
|
-
import { o as ReviewApiClient, s as ReviewApiError } from "./agent-client-
|
|
5
|
+
import { o as ReviewApiClient, s as ReviewApiError } from "./agent-client-Dogh8I83.js";
|
|
6
6
|
import { t as resolveReviewRoot } from "./runtime-CKiWhGrf.js";
|
|
7
7
|
import { C as s3ProfileSchema, E as writeTraceConfigFile, M as devReviewHome, N as normalizeStoreOrigin, S as readTraceConfigFile, T as sameS3Profile, _ as emptyTraceConfig, c as resolveS3Setup, g as currentStore, h as TraceConfigurationError, i as isS3MockMode, n as clearTraceEnvCache, o as readTraceEnvFile, p as traceSettingsPath, w as s3Store } from "./s3-config-DDWWMh5x.js";
|
|
8
8
|
import { t as errorMessage } from "./error-message-OtiDonty.js";
|
|
9
9
|
import { i as readReviewPackageVersion, r as readBuildInfo, t as findReviewPackageRoot } from "./package-paths-BsuI4WUf.js";
|
|
10
|
-
import { a as readReviewServerHealth, b as selectReviewInstance, c as reviewServerStateDir, d as ReviewInstanceUnavailableError, f as clearDefaultReviewInstance, g as requireHealthyReviewDesktop, h as readDefaultReviewInstance, i as readReviewServerDiscovery, l as serverNotReady, m as healthyReviewInstance, p as desktopUsesHome, t as DESKTOP_TAKEOVER_SIGNAL, u as REVIEW_INSTANCE_ENV, x as writeDefaultReviewInstance, y as reviewInstanceUnavailable } from "./server-discovery-
|
|
10
|
+
import { a as readReviewServerHealth, b as selectReviewInstance, c as reviewServerStateDir, d as ReviewInstanceUnavailableError, f as clearDefaultReviewInstance, g as requireHealthyReviewDesktop, h as readDefaultReviewInstance, i as readReviewServerDiscovery, l as serverNotReady, m as healthyReviewInstance, p as desktopUsesHome, t as DESKTOP_TAKEOVER_SIGNAL, u as REVIEW_INSTANCE_ENV, x as writeDefaultReviewInstance, y as reviewInstanceUnavailable } from "./server-discovery-CqRxbsER.js";
|
|
11
11
|
import { t as isDirectory } from "./fs-utils-BMPLt0cr.js";
|
|
12
|
-
import { t as ReviewTelemetry } from "./review-telemetry-
|
|
13
|
-
import { _ as connectPrompts, a as isOwnedShim, f as windowsInstallerCommand, g as CONNECT_COMMANDS, h as isInstallTarget, m as ALL_INSTALL_TARGETS, o as pathShimPath, p as scanLegacySkills, t as aliasInstallationToAccount } from "./account-alias-
|
|
12
|
+
import { t as ReviewTelemetry } from "./review-telemetry-9ceqh4wz.js";
|
|
13
|
+
import { _ as connectPrompts, a as isOwnedShim, f as windowsInstallerCommand, g as CONNECT_COMMANDS, h as isInstallTarget, m as ALL_INSTALL_TARGETS, o as pathShimPath, p as scanLegacySkills, t as aliasInstallationToAccount } from "./account-alias-C1ixP6bt.js";
|
|
14
14
|
import { t as fuzzyRank } from "./fuzzy-match-BoAmcyak.js";
|
|
15
|
-
import { n as focusReviewDesktop, r as runReviewAppLaunch } from "./review-app-launcher-
|
|
16
|
-
import { t as reviewAgentCliHelp } from "./agent-cli-
|
|
15
|
+
import { n as focusReviewDesktop, r as runReviewAppLaunch } from "./review-app-launcher-S2FZBY4W.js";
|
|
16
|
+
import { t as reviewAgentCliHelp } from "./agent-cli-CPSnWc9V.js";
|
|
17
17
|
import { z } from "zod";
|
|
18
18
|
import { constants, existsSync, mkdirSync, renameSync, writeFileSync } from "node:fs";
|
|
19
19
|
import { access, readFile, realpath } from "node:fs/promises";
|
|
@@ -4451,7 +4451,7 @@ async function runReviewCli(input) {
|
|
|
4451
4451
|
if (!Number.isInteger(port) || port < 0 || port > 65535) throw new ReviewCliUsageError("--port must be an integer between 0 and 65535.");
|
|
4452
4452
|
const stateDir = reviewServerStateDir(authoringEnv(options.stateDir));
|
|
4453
4453
|
if (options.detach) {
|
|
4454
|
-
const { ensureBackgroundServer } = await import("./background-server-
|
|
4454
|
+
const { ensureBackgroundServer } = await import("./background-server-BKR_lpYb.js");
|
|
4455
4455
|
const { discovery, started } = await ensureBackgroundServer({
|
|
4456
4456
|
stateDir,
|
|
4457
4457
|
env,
|
|
@@ -4473,7 +4473,7 @@ async function runReviewCli(input) {
|
|
|
4473
4473
|
process.once("SIGINT", stop);
|
|
4474
4474
|
process.once("SIGTERM", stop);
|
|
4475
4475
|
process.once(DESKTOP_TAKEOVER_SIGNAL, takeover);
|
|
4476
|
-
const { HeadlessServerBusyError, runHeadlessServer } = await import("./headless-host-
|
|
4476
|
+
const { HeadlessServerBusyError, runHeadlessServer } = await import("./headless-host-Pj2xfGAo.js");
|
|
4477
4477
|
try {
|
|
4478
4478
|
await runHeadlessServer({
|
|
4479
4479
|
stateDir,
|
|
@@ -4510,7 +4510,7 @@ async function runReviewCli(input) {
|
|
|
4510
4510
|
configureJsonOutput(serverCommand.command("stop").description("Stop a background server started by --detach, the CLI, or Desktop").option("--state-dir <path>", "directory selected when starting the server"), "plain").action(async (_options, command) => {
|
|
4511
4511
|
const options = command.optsWithGlobals();
|
|
4512
4512
|
const stateDir = reviewServerStateDir(authoringEnv(options.stateDir));
|
|
4513
|
-
const { headlessServerOwner, stopBackgroundServer } = await import("./background-server-
|
|
4513
|
+
const { headlessServerOwner, stopBackgroundServer } = await import("./background-server-BKR_lpYb.js");
|
|
4514
4514
|
const owner = await headlessServerOwner(stateDir);
|
|
4515
4515
|
const discovery = await readReviewServerDiscovery(stateDir);
|
|
4516
4516
|
if (owner === void 0) {
|
|
@@ -4538,7 +4538,7 @@ async function runReviewCli(input) {
|
|
|
4538
4538
|
if (!existsSync(path.join(stateDir, "review-api.db"))) throw new Error(`No saved reviews in ${stateDir}, so there is no server id to reset. Check --state-dir.`);
|
|
4539
4539
|
const inUse = `A Whiteboard server is using ${stateDir}. Stop it first, then run whiteboard server reset-id again.`;
|
|
4540
4540
|
if (await desktopUsesHome(stateDir, env)) return refuse(inUse, options.json);
|
|
4541
|
-
const [{ openReviewProfile }, { withHeadlessServerLock }] = await Promise.all([import("./profile-
|
|
4541
|
+
const [{ openReviewProfile }, { withHeadlessServerLock }] = await Promise.all([import("./profile-BUoTujrK.js"), import("./headless-host-Pj2xfGAo.js")]);
|
|
4542
4542
|
const reset = await withHeadlessServerLock(await realpath(stateDir), async () => {
|
|
4543
4543
|
const local = await openReviewProfile(stateDir, { manageWorkspaces: false });
|
|
4544
4544
|
try {
|
|
@@ -4560,7 +4560,7 @@ async function runReviewCli(input) {
|
|
|
4560
4560
|
configureJsonOutput(remote.command("attach").description("Start a background server if none is healthy and report how to reach it").option("--state-dir <path>", "directory for saved reviews and server discovery").option("--groups <groups>", "comma-separated optional extension groups the Desktop has enabled, such as go").option("--replace", "stop a running server of another version that the CLI or Desktop started, and start this one"), "plain").action(async (_options, command) => {
|
|
4561
4561
|
const options = command.optsWithGlobals();
|
|
4562
4562
|
const stateDir = reviewServerStateDir(authoringEnv(options.stateDir));
|
|
4563
|
-
const { remoteAttach } = await import("./remote-attach-
|
|
4563
|
+
const { remoteAttach } = await import("./remote-attach-CiOwonJ3.js");
|
|
4564
4564
|
let attach;
|
|
4565
4565
|
try {
|
|
4566
4566
|
attach = await remoteAttach({
|
|
@@ -4583,11 +4583,11 @@ async function runReviewCli(input) {
|
|
|
4583
4583
|
state.exitCode = 1;
|
|
4584
4584
|
return;
|
|
4585
4585
|
}
|
|
4586
|
-
input.stdout.write(options.json ? `${REVIEW_REMOTE_ATTACH_BEGIN}\n${JSON.stringify(attach)}\n${REVIEW_REMOTE_ATTACH_END}\n` : `Whiteboard server ${attach.startedServer ? "started" : "already running"} at ${attach.url}\nLanguage features: ${attach.languageServer ? `
|
|
4586
|
+
input.stdout.write(options.json ? `${REVIEW_REMOTE_ATTACH_BEGIN}\n${JSON.stringify(attach)}\n${REVIEW_REMOTE_ATTACH_END}\n` : `Whiteboard server ${attach.startedServer ? "started" : "already running"} at ${attach.url}\nLanguage features: ${attach.languageServer ? `language server on port ${attach.languageServer.port}` : `unavailable (${attach.languageServerDetail})`}\n`);
|
|
4587
4587
|
});
|
|
4588
|
-
configureJsonOutput(remote.command("extensions").description("Language extensions for the
|
|
4588
|
+
configureJsonOutput(remote.command("extensions").description("Language extensions for the language server on a remote").command("ensure").description("Download the curated extensions for this machine and list them for the language server").option("--groups <groups>", "comma-separated optional extension groups the Desktop has enabled, such as go"), "plain").action(async (_options, command) => {
|
|
4589
4589
|
const { json, groups } = command.optsWithGlobals();
|
|
4590
|
-
const { ensureRemoteExtensions } = await import("./remote-extensions-
|
|
4590
|
+
const { ensureRemoteExtensions } = await import("./remote-extensions-ByiuSl1D.js");
|
|
4591
4591
|
const result = await ensureRemoteExtensions({
|
|
4592
4592
|
env,
|
|
4593
4593
|
groups: groups?.split(",").map((group) => group.trim())
|
|
@@ -4602,7 +4602,7 @@ async function runReviewCli(input) {
|
|
|
4602
4602
|
configureJsonOutput(remote.command("uninstall").description("Remove what Whiteboard Desktop installed on this host, stopping a server it started").addOption(new Option("--keep-reviews", "leave the saved reviews in place").conflicts("deleteReviews")).addOption(new Option("--delete-reviews", "also delete the saved reviews")).option("--state-dir <path>", "directory for saved reviews and server discovery"), "plain").action(async (_options, command) => {
|
|
4603
4603
|
const options = command.optsWithGlobals();
|
|
4604
4604
|
const stateDir = reviewServerStateDir(authoringEnv(options.stateDir));
|
|
4605
|
-
const { remoteUninstall } = await import("./remote-uninstall-
|
|
4605
|
+
const { remoteUninstall } = await import("./remote-uninstall-pzHb-Hfd.js");
|
|
4606
4606
|
let deleteReviews = options.deleteReviews ? true : options.keepReviews ? false : void 0;
|
|
4607
4607
|
if (deleteReviews === void 0 && !options.json && input.stdin?.isTTY) {
|
|
4608
4608
|
const prompt = createInterface$1({
|
|
@@ -4810,14 +4810,14 @@ async function runReviewCli(input) {
|
|
|
4810
4810
|
command.showHelpAfterError(false).error("Markdown review migration is no longer supported. Ask your agent to migrate your old Whiteboard reviews.");
|
|
4811
4811
|
});
|
|
4812
4812
|
configureJsonOutput(configureJsonOutput(program.command("share").description("Upload an immutable review snapshot and return its share link"), "plain").option("--review <id>", "review ID").option("--version <number>", "Saved version to share").option("--preview", "Open the share link in Whiteboard Preview by default").option("--request-id <uuid>", "Reuse this ID when retrying the same immutable upload").action(async (options) => {
|
|
4813
|
-
const { runShareCli } = await import("./cli-
|
|
4813
|
+
const { runShareCli } = await import("./cli-Df6p-C19.js");
|
|
4814
4814
|
state.exitCode = await runShareCli({
|
|
4815
4815
|
...input,
|
|
4816
4816
|
...options,
|
|
4817
4817
|
env: authoringEnv()
|
|
4818
4818
|
});
|
|
4819
4819
|
}).command("revoke <share-id>").description("Revoke future downloads of a share"), "plain").action(async (shareId, options) => {
|
|
4820
|
-
const { runShareCli } = await import("./cli-
|
|
4820
|
+
const { runShareCli } = await import("./cli-Df6p-C19.js");
|
|
4821
4821
|
state.exitCode = await runShareCli({
|
|
4822
4822
|
...input,
|
|
4823
4823
|
...options,
|
|
@@ -4898,7 +4898,7 @@ async function runReviewCli(input) {
|
|
|
4898
4898
|
return commands;
|
|
4899
4899
|
} });
|
|
4900
4900
|
for (const [name, description] of [["api", "Call a JSON review authoring tool on the running server"], ["mcp", "Serve the JSON review authoring tools over stdio MCP"]]) configureOutput(program.command(name).description(description).argument("[args...]", "tool name and JSON input").allowUnknownOption().allowExcessArguments().helpOption(false).passThroughOptions().addHelpText("after", `\n${reviewAgentCliHelp}`), "plain").action(async (args) => {
|
|
4901
|
-
const { runReviewAgentCli } = await import("./agent-cli-
|
|
4901
|
+
const { runReviewAgentCli } = await import("./agent-cli-CGapivA1.js");
|
|
4902
4902
|
state.exitCode = await runReviewAgentCli({
|
|
4903
4903
|
...input,
|
|
4904
4904
|
env: authoringEnv(),
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { a as jsonNumber, c as jsonString, o as jsonObject, u as parseJsonText } from "./src-X9phtB2j.js";
|
|
3
|
-
import "./src-
|
|
3
|
+
import "./src-HnIPjtjx.js";
|
|
4
4
|
import { existsSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import os from "node:os";
|
|
@@ -17,7 +17,7 @@ async function runCli(effectivePath) {
|
|
|
17
17
|
`);
|
|
18
18
|
return 1;
|
|
19
19
|
}
|
|
20
|
-
const { runReviewCli } = await import("./cli-runner-
|
|
20
|
+
const { runReviewCli } = await import("./cli-runner-ZktCwlLk.js");
|
|
21
21
|
return runReviewCli({
|
|
22
22
|
argv,
|
|
23
23
|
cliPaths: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { f as gitAt } from "./src-BMPuxWv4.js";
|
|
2
2
|
import { n as isJsonObject, u as parseJsonText } from "./src-X9phtB2j.js";
|
|
3
|
-
import "./src-
|
|
4
|
-
import { B as
|
|
3
|
+
import "./src-HnIPjtjx.js";
|
|
4
|
+
import { B as markdownNodes, C as resourceReference, D as sourceReferences, N as lensSchema, P as lensSelections, V as parseMarkdown, _ as hasCodeReferences, c as traceSchema, h as elements, k as checkReferences, l as textIncludesQuote, n as migrateStoredDocument, o as normalizedSoftwareElementSchema, p as documentSchema, q as sourceAnchors, r as migrateStoredLenses, s as normalizedSoftwareRelationshipSchema, t as liftFileLenses, u as anchorPins, w as resourceReferences, x as pinsSchema } from "./stored-document-migration-DenDEYdI.js";
|
|
5
5
|
import { t as ReviewInputError } from "./input-error-OLgB_h31.js";
|
|
6
6
|
import { createHash, randomUUID } from "node:crypto";
|
|
7
7
|
import { z } from "zod";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as withHeadlessServerLock, n as runHeadlessServer, r as takeOverServerHome, t as HeadlessServerBusyError } from "./headless-host-
|
|
1
|
+
import { i as withHeadlessServerLock, n as runHeadlessServer, r as takeOverServerHome, t as HeadlessServerBusyError } from "./headless-host-ZNZ_6ZRo.js";
|
|
2
2
|
export { HeadlessServerBusyError, runHeadlessServer, takeOverServerHome, withHeadlessServerLock };
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { d as git, r as defaultBranch } from "./src-BMPuxWv4.js";
|
|
2
2
|
import { c as jsonString, m as isStringValue, n as isJsonObject, p as isObjectValue, u as parseJsonText } from "./src-X9phtB2j.js";
|
|
3
|
-
import { a as sharedReviewId, c as verifyShareRepository, d as StreamLimitError, f as readBoundedStream, l as exportShare, m as shareIdSchema, n as ShareClient, p as parseShareLink, r as SharePreflightError, s as readShareRepository, t as ShareAuthError, u as validateShareSources } from "./client-
|
|
4
|
-
import { a as inspectSnapshot, b as diffrMissingError, c as askAgentIds, d as askPicksSchema, f as askQuestionSchema, i as commandSchema, l as askChoiceKinds, m as selectionMarkdown, p as AgentSelectionSchema, r as SCRATCHPAD_ID, s as applyAskChange, u as askPermissionsSchema, v as invalidateStructuralComparisons, y as diffrExecutable } from "./local-data-
|
|
5
|
-
import { A as reviewDiffrSummarizerInputSchema, D as ReviewOnboardingRunRequestSchema, a as parseReviewVerbRequest, g as REVIEW_HOST_HEADER, i as parseReviewDesktopVerbResult, j as decodeStructuralDiffEvent } from "./src-
|
|
3
|
+
import { a as sharedReviewId, c as verifyShareRepository, d as StreamLimitError, f as readBoundedStream, l as exportShare, m as shareIdSchema, n as ShareClient, p as parseShareLink, r as SharePreflightError, s as readShareRepository, t as ShareAuthError, u as validateShareSources } from "./client-_ltX1mah.js";
|
|
4
|
+
import { a as inspectSnapshot, b as diffrMissingError, c as askAgentIds, d as askPicksSchema, f as askQuestionSchema, i as commandSchema, l as askChoiceKinds, m as selectionMarkdown, p as AgentSelectionSchema, r as SCRATCHPAD_ID, s as applyAskChange, u as askPermissionsSchema, v as invalidateStructuralComparisons, y as diffrExecutable } from "./local-data-D_9S--yI.js";
|
|
5
|
+
import { A as reviewDiffrSummarizerInputSchema, D as ReviewOnboardingRunRequestSchema, a as parseReviewVerbRequest, g as REVIEW_HOST_HEADER, i as parseReviewDesktopVerbResult, j as decodeStructuralDiffEvent } from "./src-HnIPjtjx.js";
|
|
6
6
|
import { B as TraceStorageDeniedError, D as listReviewTraceSessions, I as isTraceStorageConfigured, O as loadReviewAgentTrace, R as resolveTraceStorage, T as traceMachineEnabled, at as clearStoreAuth, ct as runStoreLogin, it as DEFAULT_STORE_ORIGIN, ot as openUrlInBrowser, st as readStoreAuth, tt as shellQuote, z as selectTraceStorage } from "./review-home-paths-zwevIq4I.js";
|
|
7
|
-
import { $ as
|
|
7
|
+
import { $ as subtractIntervals, A as UNCATEGORIZED_LENS_ID, E as selectionReferences, G as resolveDiffSelection, H as anchorSelection, K as selectionKey, L as fileLineRangeSchema, P as lensSelections, Q as scopedCoverage, U as comparisonKey, W as formatAnchor, X as emptyCoverage, Y as coverageSources, et as unionIntervals, h as elements, u as anchorPins } from "./stored-document-migration-DenDEYdI.js";
|
|
8
8
|
import { t as ReviewInputError } from "./input-error-OLgB_h31.js";
|
|
9
9
|
import { A as withFileLock, I as writePrivateJsonAtomic, M as devReviewHome, h as TraceConfigurationError, i as isS3MockMode } from "./s3-config-DDWWMh5x.js";
|
|
10
10
|
import { t as errorMessage } from "./error-message-OtiDonty.js";
|
|
11
11
|
import { i as readReviewPackageVersion, n as readBuildCommit, t as findReviewPackageRoot } from "./package-paths-BsuI4WUf.js";
|
|
12
|
-
import { i as readReviewServerDiscovery, n as desktopOwnsHome, o as reviewServerDiscoveryPath, p as desktopUsesHome, r as headlessServerLockPath, t as DESKTOP_TAKEOVER_SIGNAL } from "./server-discovery-
|
|
13
|
-
import { t as openReviewProfile } from "./profile-
|
|
14
|
-
import { a as REVIEW_APP_SESSION_ID_HEADER, c as sanitizeUiTelemetryEvent, i as BUNDLE_FRAME_PATTERN, l as cleanTelemetryText, r as reviewRequestOrigin, s as isReportableCleanedMessage } from "./request-origin-
|
|
15
|
-
import { a as scratchpadAvailable, c as readQuerySchemas, i as renderInstructions, o as inspectQuerySchema, r as instructionsQuerySchema, s as queryAnchor, t as authoringTools } from "./authoring-tools-
|
|
12
|
+
import { i as readReviewServerDiscovery, n as desktopOwnsHome, o as reviewServerDiscoveryPath, p as desktopUsesHome, r as headlessServerLockPath, t as DESKTOP_TAKEOVER_SIGNAL } from "./server-discovery-CqRxbsER.js";
|
|
13
|
+
import { t as openReviewProfile } from "./profile-CKSB6UDi.js";
|
|
14
|
+
import { a as REVIEW_APP_SESSION_ID_HEADER, c as sanitizeUiTelemetryEvent, i as BUNDLE_FRAME_PATTERN, l as cleanTelemetryText, r as reviewRequestOrigin, s as isReportableCleanedMessage } from "./request-origin-C-V9f3Fr.js";
|
|
15
|
+
import { a as scratchpadAvailable, c as readQuerySchemas, i as renderInstructions, o as inspectQuerySchema, r as instructionsQuerySchema, s as queryAnchor, t as authoringTools } from "./authoring-tools-CtsslOEf.js";
|
|
16
16
|
import { t as fuzzyRank } from "./fuzzy-match-BoAmcyak.js";
|
|
17
|
-
import { a as headlessServerOwner, c as stopBackgroundServer } from "./background-server-
|
|
17
|
+
import { a as headlessServerOwner, c as stopBackgroundServer } from "./background-server-DJT0CnYH.js";
|
|
18
18
|
import { createRequire } from "node:module";
|
|
19
19
|
import crypto$1, { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
20
20
|
import { z } from "zod";
|
|
@@ -2146,8 +2146,14 @@ function applyCorsHeaders(request, response) {
|
|
|
2146
2146
|
response.headers.set("access-control-expose-headers", REVIEW_HOST_HEADER);
|
|
2147
2147
|
return response;
|
|
2148
2148
|
}
|
|
2149
|
+
/** The allowed origin, headers and methods hold for the server's lifetime, so
|
|
2150
|
+
* the client may reuse a preflight. Chromium otherwise keeps one for 5 s, and
|
|
2151
|
+
* nearly every request paid a second round trip. Two hours is Chromium's cap. */
|
|
2152
|
+
const PREFLIGHT_MAX_AGE_SECONDS = 7200;
|
|
2149
2153
|
function corsPreflightResponse(request) {
|
|
2150
|
-
|
|
2154
|
+
const response = applyCorsHeaders(request, new Response(null, { status: 204 }));
|
|
2155
|
+
response.headers.set("access-control-max-age", String(PREFLIGHT_MAX_AGE_SECONDS));
|
|
2156
|
+
return response;
|
|
2151
2157
|
}
|
|
2152
2158
|
function isAuthorizedRequest(request, expectedToken) {
|
|
2153
2159
|
const supplied = request.headers.get("x-review-token") ?? new URL(request.url).searchParams.get("token");
|
|
@@ -4262,7 +4268,7 @@ function createReviewApi(store, data, open, shared, capabilities = () => ({
|
|
|
4262
4268
|
head: `b/${diff.newPath}`
|
|
4263
4269
|
} : void 0);
|
|
4264
4270
|
return [
|
|
4265
|
-
|
|
4271
|
+
`Whiteboard: ${snapshot.title}`,
|
|
4266
4272
|
`Session ID: ${snapshot.reviewId}`,
|
|
4267
4273
|
`Version: ${snapshot.version}`,
|
|
4268
4274
|
...selection.apiSource?.commit ? [`Selected commit: ${selection.apiSource.commit}`] : [],
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { _ as parseGitRemote, a as diff, b as resolveRepoContextSync, c as diffFileSummariesWorkingTree, d as git, g as listTrackedFilesAtCommit, h as listCommitRange, i as detectLocalVcs, l as diffTrees, m as jjRevisionIsConflicted, n as createBlobBatchReader, p as gitCommonDir, s as diffFileSummariesTrees, t as LocalVcsToolsMissingError, u as diffWorkingTree, v as readFileAtCommit, x as resolveRevision, y as resolveRepoContext } from "./src-BMPuxWv4.js";
|
|
2
2
|
import { c as jsonString, o as jsonObject, u as parseJsonText } from "./src-X9phtB2j.js";
|
|
3
|
-
import { C as ReviewApiSelectionSourceSchema, M as structuralChangeCounts, O as ReviewSelectedDiffSchema, j as decodeStructuralDiffEvent, k as SCRATCHPAD_REVIEW_ID } from "./src-
|
|
3
|
+
import { C as ReviewApiSelectionSourceSchema, M as structuralChangeCounts, O as ReviewSelectedDiffSchema, j as decodeStructuralDiffEvent, k as SCRATCHPAD_REVIEW_ID } from "./src-HnIPjtjx.js";
|
|
4
4
|
import { s as safeStorageSegment } from "./review-home-paths-zwevIq4I.js";
|
|
5
|
-
import { $ as
|
|
5
|
+
import { $ as subtractIntervals, C as resourceReference, D as sourceReferences, F as SourceRangeError, I as checkSourcePath, J as coverageSchema, L as fileLineRangeSchema, M as lensEditSchema, O as summarizeEdit, P as lensSelections, R as requireVisibleSource, T as reviewTargetSchema, X as emptyCoverage, Z as intersectIntervals, a as defineSoftwareMap, b as pinnedRepositoryIds, c as traceSchema, d as applyEdit, et as unionIntervals, f as assignFreshIds, g as explicitPins, h as elements, i as SoftwareModelValidationError, j as applyLensEdit, k as checkReferences, l as textIncludesQuote, m as editSchema, n as migrateStoredDocument, p as documentSchema, q as sourceAnchors, r as migrateStoredLenses, t as liftFileLenses, tt as updateCoverage, u as anchorPins, v as isUnit, w as resourceReferences, x as pinsSchema, z as sliceSourceRange } from "./stored-document-migration-DenDEYdI.js";
|
|
6
6
|
import { t as ReviewInputError } from "./input-error-OLgB_h31.js";
|
|
7
7
|
import { A as withFileLock, I as writePrivateJsonAtomic, O as processIsAlive } from "./s3-config-DDWWMh5x.js";
|
|
8
8
|
import { t as errorMessage } from "./error-message-OtiDonty.js";
|
|
@@ -1388,6 +1388,106 @@ function firstLine(text) {
|
|
|
1388
1388
|
return text.split("\n")[0].slice(0, 300);
|
|
1389
1389
|
}
|
|
1390
1390
|
//#endregion
|
|
1391
|
+
//#region src/review-api/azure-devops-provider.ts
|
|
1392
|
+
const AZ_TIMEOUT_MS = 3e4;
|
|
1393
|
+
const PULL_REQUEST_URLS = [/^https:\/\/dev\.azure\.com\/([A-Za-z0-9-]+)\/([^/]+)\/_git\/([^/]+)\/pullrequest\/([1-9]\d*)$/, /^https:\/\/([A-Za-z0-9-]+)\.visualstudio\.com\/(?:DefaultCollection\/)?([^/]+)\/_git\/([^/]+)\/pullrequest\/([1-9]\d*)$/];
|
|
1394
|
+
const REMOTE_URLS = [
|
|
1395
|
+
/^https:\/\/(?:[^@]+@)?dev\.azure\.com\/([^/]+)\/([^/]+)\/_git\/([^/]+?)(?:\.git)?\/?$/,
|
|
1396
|
+
/^https:\/\/([^.]+)\.visualstudio\.com\/(?:DefaultCollection\/)?([^/]+)\/_git\/([^/]+?)(?:\.git)?\/?$/,
|
|
1397
|
+
/^git@ssh\.dev\.azure\.com:v3\/([^/]+)\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/,
|
|
1398
|
+
/^[^@]+@vs-ssh\.visualstudio\.com:v3\/([^/]+)\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/
|
|
1399
|
+
];
|
|
1400
|
+
const metadataSchema$1 = z.object({
|
|
1401
|
+
title: z.string(),
|
|
1402
|
+
sourceRefName: z.string().min(1),
|
|
1403
|
+
targetRefName: z.string().min(1),
|
|
1404
|
+
lastMergeTargetCommit: z.object({ commitId: z.string().min(1) }).optional(),
|
|
1405
|
+
repository: z.object({
|
|
1406
|
+
name: z.string(),
|
|
1407
|
+
project: z.object({ name: z.string() })
|
|
1408
|
+
})
|
|
1409
|
+
});
|
|
1410
|
+
/** org/project/repository, decoded; undefined for malformed escapes. */
|
|
1411
|
+
function slugOf(patterns, url) {
|
|
1412
|
+
const match = patterns.map((pattern) => pattern.exec(url)).find(Boolean);
|
|
1413
|
+
try {
|
|
1414
|
+
return match && match.slice(1, 4).map(decodeURIComponent).join("/");
|
|
1415
|
+
} catch {
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
function azFailure(url, failure) {
|
|
1420
|
+
const unreadable = (hint) => new ReviewInputError(`Could not read ${url}: az failed (${failure}). ${hint}`, 409);
|
|
1421
|
+
if (/not recognized as an internal or external command|command not found|enoent/i.test(failure)) return unreadable("Install the Azure CLI and the azure-devops extension, then retry.");
|
|
1422
|
+
if (/extension|unknown command ['"]repos['"]|'repos' is not in the 'az' command group/i.test(failure)) return unreadable("Run `az extension add --name azure-devops`, then retry.");
|
|
1423
|
+
if (/az login|aadsts/i.test(failure)) return unreadable("Run `az login` to sign in, then retry.");
|
|
1424
|
+
if (/tf401027|not found|does not exist/i.test(failure)) return new ReviewInputError(`${url} was not found: it does not exist, or it is private and az is not signed in to an account that can read it. az said: ${failure}`, 404);
|
|
1425
|
+
return unreadable("Check your Azure DevOps connection and credentials, then retry.");
|
|
1426
|
+
}
|
|
1427
|
+
const azureDevOpsProvider = {
|
|
1428
|
+
id: "azure-devops",
|
|
1429
|
+
parseUrl(url) {
|
|
1430
|
+
const slug = slugOf(PULL_REQUEST_URLS, url);
|
|
1431
|
+
const number = Number(url.split("/").at(-1));
|
|
1432
|
+
if (!slug || !Number.isSafeInteger(number)) return void 0;
|
|
1433
|
+
return {
|
|
1434
|
+
host: "dev.azure.com",
|
|
1435
|
+
slug,
|
|
1436
|
+
number
|
|
1437
|
+
};
|
|
1438
|
+
},
|
|
1439
|
+
async readPullRequest({ host, slug, number }, deps) {
|
|
1440
|
+
const [org, project, repo] = slug.split("/");
|
|
1441
|
+
const url = `https://dev.azure.com/${org}/${project}/_git/${repo}/pullrequest/${number}`;
|
|
1442
|
+
const args = [
|
|
1443
|
+
"repos",
|
|
1444
|
+
"pr",
|
|
1445
|
+
"show",
|
|
1446
|
+
"--id",
|
|
1447
|
+
String(number),
|
|
1448
|
+
"--detect",
|
|
1449
|
+
"false",
|
|
1450
|
+
"--organization",
|
|
1451
|
+
`https://dev.azure.com/${org}`,
|
|
1452
|
+
"--output",
|
|
1453
|
+
"json",
|
|
1454
|
+
"--only-show-errors"
|
|
1455
|
+
];
|
|
1456
|
+
let stdout;
|
|
1457
|
+
try {
|
|
1458
|
+
stdout = process.platform === "win32" ? await deps.run("cmd.exe", [
|
|
1459
|
+
"/d",
|
|
1460
|
+
"/s",
|
|
1461
|
+
"/c",
|
|
1462
|
+
"az",
|
|
1463
|
+
...args
|
|
1464
|
+
], { timeoutMs: AZ_TIMEOUT_MS }) : await deps.run("az", args, { timeoutMs: AZ_TIMEOUT_MS });
|
|
1465
|
+
} catch (error) {
|
|
1466
|
+
throw azFailure(url, firstLine(errorMessage(error)));
|
|
1467
|
+
}
|
|
1468
|
+
let pr;
|
|
1469
|
+
try {
|
|
1470
|
+
pr = metadataSchema$1.parse(JSON.parse(stdout));
|
|
1471
|
+
} catch {
|
|
1472
|
+
throw new ReviewInputError(`Could not read ${url}: the Azure DevOps response was malformed.`, 409);
|
|
1473
|
+
}
|
|
1474
|
+
const actual = `${pr.repository.project.name}/${pr.repository.name}`;
|
|
1475
|
+
if (actual.toLowerCase() !== `${project}/${repo}`.toLowerCase()) throw new ReviewInputError(`${url} was not found: PR ${number} belongs to ${actual}.`, 404);
|
|
1476
|
+
return {
|
|
1477
|
+
host,
|
|
1478
|
+
slug,
|
|
1479
|
+
number,
|
|
1480
|
+
title: pr.title,
|
|
1481
|
+
headRef: pr.sourceRefName,
|
|
1482
|
+
baseRefName: pr.targetRefName.replace(/^refs\/heads\//, ""),
|
|
1483
|
+
baseRefOid: pr.lastMergeTargetCommit?.commitId
|
|
1484
|
+
};
|
|
1485
|
+
},
|
|
1486
|
+
matchesRemote(remoteUrl, address) {
|
|
1487
|
+
return slugOf(REMOTE_URLS, remoteUrl.trim())?.toLowerCase() === address.slug.toLowerCase();
|
|
1488
|
+
}
|
|
1489
|
+
};
|
|
1490
|
+
//#endregion
|
|
1391
1491
|
//#region src/review-api/github-provider.ts
|
|
1392
1492
|
const GH_TIMEOUT_MS = 2e4;
|
|
1393
1493
|
const API_TIMEOUT_MS = 15e3;
|
|
@@ -1479,7 +1579,7 @@ const providers = [{
|
|
|
1479
1579
|
const remote = parseGitRemote(remoteUrl);
|
|
1480
1580
|
return remote?.host === address.host && remote.slug.toLowerCase() === address.slug.toLowerCase();
|
|
1481
1581
|
}
|
|
1482
|
-
}];
|
|
1582
|
+
}, azureDevOpsProvider];
|
|
1483
1583
|
function pullRequestProvider(url) {
|
|
1484
1584
|
for (const provider of providers) {
|
|
1485
1585
|
const address = provider.parseUrl(url);
|
|
@@ -1698,14 +1798,14 @@ const AgentSelectionSchema = z.strictObject({
|
|
|
1698
1798
|
});
|
|
1699
1799
|
function selectionMarkdown(selection, sourceExcerpt = "", diffPaths) {
|
|
1700
1800
|
const target = selection.target;
|
|
1701
|
-
if (selection.selectedDiff) return selectedDiffMarkdown(selection.selectedDiff, diffPaths)
|
|
1801
|
+
if (selection.selectedDiff) return `Selected diff:\n${selectedDiffMarkdown(selection.selectedDiff, diffPaths)}`;
|
|
1702
1802
|
if (target.kind === "review") return "";
|
|
1703
|
-
if (target.kind === "text") return target.quote.split(/\r?\n/).map((line) => `> ${line}`).join("\n")
|
|
1704
|
-
return [
|
|
1803
|
+
if (target.kind === "text") return `Selected text:\n${target.quote.split(/\r?\n/).map((line) => `> ${line}`).join("\n")}`;
|
|
1804
|
+
return `Selected code:\n${[
|
|
1705
1805
|
`## ${selection.title}`,
|
|
1706
1806
|
selection.detail ?? "",
|
|
1707
1807
|
sourceExcerpt
|
|
1708
|
-
].filter(Boolean).join("\n\n")
|
|
1808
|
+
].filter(Boolean).join("\n\n")}`;
|
|
1709
1809
|
}
|
|
1710
1810
|
function selectedDiffMarkdown(diff, paths) {
|
|
1711
1811
|
const oldCount = diff.rows.filter((row) => row.kind !== "added").length;
|
|
@@ -2196,7 +2296,7 @@ var AskHistory = class {
|
|
|
2196
2296
|
};
|
|
2197
2297
|
//#endregion
|
|
2198
2298
|
//#region src/review-api/origin.ts
|
|
2199
|
-
const pullRequestUrl = z.string().refine((url) => pullRequestProvider(url) !== void 0, "Use a canonical
|
|
2299
|
+
const pullRequestUrl = z.string().refine((url) => pullRequestProvider(url) !== void 0, "Use a canonical PR URL: https://github.com/owner/repository/pull/123, the same path on a GitHub Enterprise host, or https://dev.azure.com/org/project/_git/repository/pullrequest/123.");
|
|
2200
2300
|
/** One key per PR: GitHub owner and repository names are case-insensitive,
|
|
2201
2301
|
* and the URL pattern admits only ASCII, so lowercasing is canonical. */
|
|
2202
2302
|
function pullRequestKey(url) {
|
|
@@ -2376,16 +2476,63 @@ var ReviewStore = class {
|
|
|
2376
2476
|
};
|
|
2377
2477
|
}
|
|
2378
2478
|
refreshPending;
|
|
2479
|
+
/** What the last refresh saw of each review. A live worktree's snapshot is
|
|
2480
|
+
* kept, since every pass projects it again. */
|
|
2481
|
+
refreshed = /* @__PURE__ */ new Map();
|
|
2482
|
+
availableRepositories;
|
|
2483
|
+
/** Reviews whose source may have moved since the last pass: every live
|
|
2484
|
+
* worktree, and any other review that is new, edited, restored from trash or
|
|
2485
|
+
* reads from a repository that appeared or went away. */
|
|
2486
|
+
*reviewsToRefresh() {
|
|
2487
|
+
const available = new Set(this.repositories().filter((repository) => existsSync(repository.path)).map((repository) => repository.id));
|
|
2488
|
+
const previous = this.availableRepositories;
|
|
2489
|
+
this.availableRepositories = available;
|
|
2490
|
+
const flipped = (id) => !previous || previous.has(id) !== available.has(id);
|
|
2491
|
+
const rows = this.db.prepare("SELECT reviews.id, reviews.version, review_attention.deleted_at FROM reviews LEFT JOIN review_attention ON review_attention.review_id=reviews.id").all();
|
|
2492
|
+
const present = /* @__PURE__ */ new Set();
|
|
2493
|
+
for (const row of rows) {
|
|
2494
|
+
const reviewId = String(row.id);
|
|
2495
|
+
const version = Number(row.version);
|
|
2496
|
+
const state = `${version}\0${row.deleted_at ?? ""}`;
|
|
2497
|
+
present.add(reviewId);
|
|
2498
|
+
let seen = this.refreshed.get(reviewId);
|
|
2499
|
+
if (seen?.state === state) {
|
|
2500
|
+
if (seen.live) yield seen.live;
|
|
2501
|
+
else if ([...seen.repositories].some(flipped)) yield this.read(reviewId, version);
|
|
2502
|
+
continue;
|
|
2503
|
+
}
|
|
2504
|
+
const snapshot = row.deleted_at ? void 0 : this.read(reviewId, version);
|
|
2505
|
+
if (!snapshot) {
|
|
2506
|
+
this.refreshed.set(reviewId, {
|
|
2507
|
+
state,
|
|
2508
|
+
repositories: /* @__PURE__ */ new Set()
|
|
2509
|
+
});
|
|
2510
|
+
continue;
|
|
2511
|
+
}
|
|
2512
|
+
const live = snapshot.target?.kind === "worktree";
|
|
2513
|
+
seen = {
|
|
2514
|
+
state,
|
|
2515
|
+
repositories: live ? /* @__PURE__ */ new Set() : /* @__PURE__ */ new Set([...snapshot.pins ? [snapshot.pins.repositoryId] : [], ...pinnedRepositoryIds(snapshot.document)]),
|
|
2516
|
+
live: live ? snapshot : void 0
|
|
2517
|
+
};
|
|
2518
|
+
this.refreshed.set(reviewId, seen);
|
|
2519
|
+
yield snapshot;
|
|
2520
|
+
}
|
|
2521
|
+
for (const reviewId of this.refreshed.keys()) if (!present.has(reviewId)) this.refreshed.delete(reviewId);
|
|
2522
|
+
}
|
|
2379
2523
|
/** Refresh source state without writing authored document versions. Serialized with edits. */
|
|
2380
2524
|
refreshWorktrees() {
|
|
2381
2525
|
if (this.closing || !this.providers.resolveTarget) return Promise.resolve();
|
|
2382
2526
|
if (this.refreshPending) return this.refreshPending;
|
|
2383
2527
|
const run = this.pending.then(async () => {
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2528
|
+
let slice = performance.now();
|
|
2529
|
+
for (const snapshot of this.reviewsToRefresh()) {
|
|
2530
|
+
if (performance.now() - slice > 16) {
|
|
2531
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
2532
|
+
slice = performance.now();
|
|
2533
|
+
}
|
|
2387
2534
|
try {
|
|
2388
|
-
const live = this.liveSources.get(
|
|
2535
|
+
const live = this.liveSources.get(snapshot.reviewId);
|
|
2389
2536
|
const last = live?.version === snapshot.version ? live : snapshot;
|
|
2390
2537
|
const previous = last.pins;
|
|
2391
2538
|
const projected = await this.projectLiveSource(snapshot, last);
|
|
@@ -3139,6 +3286,27 @@ function inspectSnapshot(snapshot, targetId) {
|
|
|
3139
3286
|
}));
|
|
3140
3287
|
}
|
|
3141
3288
|
//#endregion
|
|
3289
|
+
//#region src/review-api/version-cache.ts
|
|
3290
|
+
/** A stored version never changes, so work derived from it runs once. Keeps
|
|
3291
|
+
* the `capacity` most recently used results. */
|
|
3292
|
+
var VersionCache = class {
|
|
3293
|
+
derive;
|
|
3294
|
+
options;
|
|
3295
|
+
results = /* @__PURE__ */ new Map();
|
|
3296
|
+
constructor(derive, options) {
|
|
3297
|
+
this.derive = derive;
|
|
3298
|
+
this.options = options;
|
|
3299
|
+
}
|
|
3300
|
+
get(input) {
|
|
3301
|
+
const key = this.options.key?.(input) ?? `${input.reviewId}\0${input.version}`;
|
|
3302
|
+
const result = this.results.get(key) ?? this.derive(input);
|
|
3303
|
+
this.results.delete(key);
|
|
3304
|
+
if (this.results.size >= this.options.capacity) this.results.delete(this.results.keys().next().value);
|
|
3305
|
+
this.results.set(key, result);
|
|
3306
|
+
return result;
|
|
3307
|
+
}
|
|
3308
|
+
};
|
|
3309
|
+
//#endregion
|
|
3142
3310
|
//#region src/review-api/workspaces.ts
|
|
3143
3311
|
const OWNED_ELSEWHERE = "Another Whiteboard server is managing this review's language workspaces. Retry once it stops.";
|
|
3144
3312
|
/** Local lifecycle only: source and authored history never depend on preparation.
|
|
@@ -3942,18 +4110,20 @@ var LocalReviewData = class {
|
|
|
3942
4110
|
if (!existsSync(this.store.repositoryPath(anchor.repositoryId))) throw unavailableCheckout();
|
|
3943
4111
|
return anchorPins({ pins: anchor }, void 0);
|
|
3944
4112
|
}
|
|
3945
|
-
/** References whose own repository is unregistered or gone from disk.
|
|
4113
|
+
/** References whose own repository is unregistered or gone from disk.
|
|
4114
|
+
* `snapshot` is a stored version. */
|
|
3946
4115
|
async unavailableAnchors(snapshot) {
|
|
3947
4116
|
const missing = /* @__PURE__ */ new Set();
|
|
3948
|
-
for (const
|
|
3949
|
-
|
|
4117
|
+
for (const repositoryId of pinnedRepositoryIds(snapshot.document)) try {
|
|
4118
|
+
if (!existsSync(this.store.repositoryPath(repositoryId))) missing.add(repositoryId);
|
|
3950
4119
|
} catch (error) {
|
|
3951
4120
|
if (!(error instanceof ReviewInputError)) throw error;
|
|
3952
|
-
missing.add(
|
|
4121
|
+
missing.add(repositoryId);
|
|
3953
4122
|
}
|
|
3954
4123
|
if (!missing.size) return [];
|
|
3955
|
-
return
|
|
4124
|
+
return this.storedReferences.get(snapshot).filter((ref) => ref.source.pins && missing.has(ref.source.pins.repositoryId)).map((ref) => ref.id);
|
|
3956
4125
|
}
|
|
4126
|
+
storedReferences = new VersionCache((snapshot) => sourceReferences(snapshot.document, { tolerant: true }), { capacity: 512 });
|
|
3957
4127
|
trackedFiles = /* @__PURE__ */ new Map();
|
|
3958
4128
|
repositories = /* @__PURE__ */ new Map();
|
|
3959
4129
|
readers = /* @__PURE__ */ new Map();
|
|
@@ -4337,7 +4507,7 @@ var LocalReviewData = class {
|
|
|
4337
4507
|
}
|
|
4338
4508
|
const { host, slug } = address;
|
|
4339
4509
|
const name = host === "github.com" ? slug : `${host}/${slug}`;
|
|
4340
|
-
throw new ReviewInputError(repository.id ? `That checkout has no
|
|
4510
|
+
throw new ReviewInputError(repository.id ? `That checkout has no remote for ${name}. Add one, or omit repositoryId.` : `No registered checkout has a remote for ${name}. Register a checkout of ${name} with review_register_repository first, or pass a target.`, 404);
|
|
4341
4511
|
}
|
|
4342
4512
|
async resolvePins(repositoryId, base, head) {
|
|
4343
4513
|
const vcs = await this.vcs(repositoryId);
|