@dev.fast/whiteboard 0.2.5-preview.20261015.117 → 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.
Files changed (37) hide show
  1. package/dist/{account-alias-3-HnWkjz.js → account-alias-C1ixP6bt.js} +1 -1
  2. package/dist/agent-cli-CGapivA1.js +2 -0
  3. package/dist/{agent-cli-BabaNr6w.js → agent-cli-CPSnWc9V.js} +6 -6
  4. package/dist/{agent-client-DHKowVF7.js → agent-client-Dogh8I83.js} +3 -3
  5. package/dist/{authoring-tools-CuGm_pVC.js → authoring-tools-CtsslOEf.js} +2 -2
  6. package/dist/{background-server-xlTnBsup.js → background-server-BKR_lpYb.js} +1 -1
  7. package/dist/{background-server-3SrIevG5.js → background-server-DJT0CnYH.js} +2 -2
  8. package/dist/build-info.json +1 -1
  9. package/dist/{cli-C8eB7Ot9.js → cli-Df6p-C19.js} +1 -1
  10. package/dist/{cli-runner-VEEG16zJ.js → cli-runner-ZktCwlLk.js} +16 -16
  11. package/dist/cli.js +2 -2
  12. package/dist/{client-BBBwu0P7.js → client-_ltX1mah.js} +2 -2
  13. package/dist/{headless-host-CEaaG0YT.js → headless-host-Pj2xfGAo.js} +1 -1
  14. package/dist/{headless-host-DI82imwx.js → headless-host-ZNZ_6ZRo.js} +9 -9
  15. package/dist/{local-data-DcnL0cBy.js → local-data-D_9S--yI.js} +105 -5
  16. package/dist/{mcp-Cjs0MnoL.js → mcp-Blb7rzGw.js} +3 -3
  17. package/dist/profile-BUoTujrK.js +2 -0
  18. package/dist/{profile-BoWYDne6.js → profile-CKSB6UDi.js} +1 -1
  19. package/dist/{remote-attach-xGlaS772.js → remote-attach-CiOwonJ3.js} +3 -3
  20. package/dist/{remote-language-server-Chz8NQvC.js → remote-language-server-BQjBk81F.js} +1 -1
  21. package/dist/{remote-uninstall-DGdIgpEg.js → remote-uninstall-pzHb-Hfd.js} +3 -3
  22. package/dist/{request-origin-DjOEwBAK.js → request-origin-C-V9f3Fr.js} +1 -1
  23. package/dist/{review-app-launcher-BkNRvyip.js → review-app-launcher-S2FZBY4W.js} +2 -2
  24. package/dist/{review-telemetry-ycbk-YeT.js → review-telemetry-9ceqh4wz.js} +2 -2
  25. package/dist/server/desktop-host.js +10 -10
  26. package/dist/{server-discovery-BY_MN7tj.js → server-discovery-CqRxbsER.js} +1 -1
  27. package/dist/sharing/index.js +1 -1
  28. package/dist/{src-B8adXKNt.js → src-HnIPjtjx.js} +2 -1
  29. package/dist/{stored-document-migration-CVMl7Te5.js → stored-document-migration-DenDEYdI.js} +1 -1
  30. package/dist/{tool-failure--Jih7UeH.js → tool-failure-aSYcHDxP.js} +1 -1
  31. package/package.json +6 -6
  32. package/src/review-api/azure-devops-provider.ts +165 -0
  33. package/src/review-api/local-data.ts +2 -2
  34. package/src/review-api/origin.ts +1 -1
  35. package/src/review-api/provider.ts +2 -1
  36. package/dist/agent-cli-CGL0kFJI.js +0 -2
  37. package/dist/profile-BIwE4tC6.js +0 -2
@@ -1,4 +1,4 @@
1
- import { w as ReviewCliInstallStampSchema } from "./src-B8adXKNt.js";
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";
@@ -0,0 +1,2 @@
1
+ import { n as runReviewAgentCli } from "./agent-cli-CPSnWc9V.js";
2
+ export { runReviewAgentCli };
@@ -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-DHKowVF7.js";
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-BY_MN7tj.js";
6
- import { n as reviewSessionAgent } from "./review-telemetry-ycbk-YeT.js";
7
- import { n as REVIEW_VIA_HEADER, t as REVIEW_AGENT_HEADER } from "./request-origin-DjOEwBAK.js";
8
- import { i as publicTool, n as RECOVERY, r as callPublicTool, t as toolFailure } from "./tool-failure--Jih7UeH.js";
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-Cjs0MnoL.js");
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-B8adXKNt.js";
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-BY_MN7tj.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-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-xlTnBsup.js");
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-DcnL0cBy.js";
2
- import { S as publishedEditSchema, y as pathTargetSchema } from "./stored-document-migration-CVMl7Te5.js";
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-3SrIevG5.js";
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-BY_MN7tj.js";
5
- import { t as desktopApplicationInstalled } from "./review-app-launcher-BkNRvyip.js";
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";
@@ -1 +1 @@
1
- {"version":"0.2.5-preview.20261015.117","commit":"b93a4fc67175685fab7275af8c2d80577d50513b","dirty":true,"builtAt":"2026-10-15T14:00:53.987Z"}
1
+ {"version":"0.2.5-preview.20261015.118","commit":"dc3ea1aee29b6ccf8860a763db26bc86ca52532c","dirty":true,"builtAt":"2026-10-15T17:51:10.990Z"}
@@ -1,4 +1,4 @@
1
- import { r as connectReviewApi } from "./agent-client-DHKowVF7.js";
1
+ import { r as connectReviewApi } from "./agent-client-Dogh8I83.js";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { z } from "zod";
4
4
  //#region src/sharing/cli.ts
@@ -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-B8adXKNt.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-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-DHKowVF7.js";
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-BY_MN7tj.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-CqRxbsER.js";
11
11
  import { t as isDirectory } from "./fs-utils-BMPLt0cr.js";
12
- import { t as ReviewTelemetry } from "./review-telemetry-ycbk-YeT.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-3-HnWkjz.js";
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-BkNRvyip.js";
16
- import { t as reviewAgentCliHelp } from "./agent-cli-BabaNr6w.js";
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-xlTnBsup.js");
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-CEaaG0YT.js");
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-xlTnBsup.js");
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-BIwE4tC6.js"), import("./headless-host-CEaaG0YT.js")]);
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-xGlaS772.js");
4563
+ const { remoteAttach } = await import("./remote-attach-CiOwonJ3.js");
4564
4564
  let attach;
4565
4565
  try {
4566
4566
  attach = await remoteAttach({
@@ -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-DGdIgpEg.js");
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-C8eB7Ot9.js");
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-C8eB7Ot9.js");
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-CGL0kFJI.js");
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-B8adXKNt.js";
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-VEEG16zJ.js");
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-B8adXKNt.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-CVMl7Te5.js";
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-DI82imwx.js";
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-BBBwu0P7.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-DcnL0cBy.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-B8adXKNt.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-_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 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-CVMl7Te5.js";
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-BY_MN7tj.js";
13
- import { t as openReviewProfile } from "./profile-BoWYDne6.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-DjOEwBAK.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-CuGm_pVC.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-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-3SrIevG5.js";
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";
@@ -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-B8adXKNt.js";
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 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-CVMl7Te5.js";
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);
@@ -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 GitHub PR URL: https://github.com/owner/repository/pull/123, or the same path on a GitHub Enterprise host.");
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) {
@@ -4407,7 +4507,7 @@ var LocalReviewData = class {
4407
4507
  }
4408
4508
  const { host, slug } = address;
4409
4509
  const name = host === "github.com" ? slug : `${host}/${slug}`;
4410
- throw new ReviewInputError(repository.id ? `That checkout has no GitHub remote for ${name}. Add one, or omit repositoryId.` : `No registered checkout has a GitHub remote for ${name}. Register a checkout of ${name} with review_register_repository first, or pass a target.`, 404);
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);
4411
4511
  }
4412
4512
  async resolvePins(repositoryId, base, head) {
4413
4513
  const vcs = await this.vcs(repositoryId);
@@ -1,7 +1,7 @@
1
- import { a as toolResultText, s as ReviewApiError } from "./agent-client-DHKowVF7.js";
1
+ import { a as toolResultText, s as ReviewApiError } from "./agent-client-Dogh8I83.js";
2
2
  import { t as ReviewInputError } from "./input-error-OLgB_h31.js";
3
- import { n as REVIEW_STATUS_TOOL, t as authoringTools } from "./authoring-tools-CuGm_pVC.js";
4
- import { i as publicTool, n as RECOVERY, r as callPublicTool, t as toolFailure } from "./tool-failure--Jih7UeH.js";
3
+ import { n as REVIEW_STATUS_TOOL, t as authoringTools } from "./authoring-tools-CtsslOEf.js";
4
+ import { i as publicTool, n as RECOVERY, r as callPublicTool, t as toolFailure } from "./tool-failure-aSYcHDxP.js";
5
5
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
6
6
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
7
  import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
@@ -0,0 +1,2 @@
1
+ import { t as openReviewProfile } from "./profile-CKSB6UDi.js";
2
+ export { openReviewProfile };
@@ -1,4 +1,4 @@
1
- import { o as initializeReviewStoreSchema, t as openLocalReviewStore } from "./local-data-DcnL0cBy.js";
1
+ import { o as initializeReviewStoreSchema, t as openLocalReviewStore } from "./local-data-D_9S--yI.js";
2
2
  import "./review-home-paths-zwevIq4I.js";
3
3
  import { A as withFileLock } from "./s3-config-DDWWMh5x.js";
4
4
  import { access, mkdir } from "node:fs/promises";
@@ -1,7 +1,7 @@
1
1
  import { i as readReviewPackageVersion } from "./package-paths-BsuI4WUf.js";
2
- import { a as readReviewServerHealth, l as serverNotReady } from "./server-discovery-BY_MN7tj.js";
3
- import { c as stopBackgroundServer, o as recordedBackgroundServer, r as ensureBackgroundServer } from "./background-server-3SrIevG5.js";
4
- import { t as ensureRemoteLanguageServer } from "./remote-language-server-Chz8NQvC.js";
2
+ import { a as readReviewServerHealth, l as serverNotReady } from "./server-discovery-CqRxbsER.js";
3
+ import { c as stopBackgroundServer, o as recordedBackgroundServer, r as ensureBackgroundServer } from "./background-server-DJT0CnYH.js";
4
+ import { t as ensureRemoteLanguageServer } from "./remote-language-server-BQjBk81F.js";
5
5
  import path from "node:path";
6
6
  import { spawn } from "node:child_process";
7
7
  import { gt, valid } from "semver";
@@ -1,7 +1,7 @@
1
1
  import "./review-home-paths-zwevIq4I.js";
2
2
  import { A as withFileLock, k as processStartIdentity } from "./s3-config-DDWWMh5x.js";
3
3
  import { t as findReviewPackageRoot } from "./package-paths-BsuI4WUf.js";
4
- import { n as cliSpawn, s as spawnDetached } from "./background-server-3SrIevG5.js";
4
+ import { n as cliSpawn, s as spawnDetached } from "./background-server-DJT0CnYH.js";
5
5
  import { r as remoteServerPaths, t as ensureRemoteExtensions } from "./remote-extensions-D_4DSOhO.js";
6
6
  import { randomBytes } from "node:crypto";
7
7
  import { z } from "zod";
@@ -1,9 +1,9 @@
1
- import { b as REVIEW_REMOTE_INSTALL_LOCK, x as REVIEW_REMOTE_WRAPPER_MARK } from "./src-B8adXKNt.js";
1
+ import { b as REVIEW_REMOTE_INSTALL_LOCK, x as REVIEW_REMOTE_WRAPPER_MARK } from "./src-HnIPjtjx.js";
2
2
  import "./review-home-paths-zwevIq4I.js";
3
3
  import { j as DEV_REVIEW_HOME_ENV } from "./s3-config-DDWWMh5x.js";
4
- import { c as stopBackgroundServer, o as recordedBackgroundServer } from "./background-server-3SrIevG5.js";
4
+ import { c as stopBackgroundServer, o as recordedBackgroundServer } from "./background-server-DJT0CnYH.js";
5
5
  import { i as whiteboardRemoteHome } from "./remote-extensions-D_4DSOhO.js";
6
- import { n as remoteLanguageServerGroups, r as stopProcessGroup } from "./remote-language-server-Chz8NQvC.js";
6
+ import { n as remoteLanguageServerGroups, r as stopProcessGroup } from "./remote-language-server-BQjBk81F.js";
7
7
  import { existsSync } from "node:fs";
8
8
  import { lstat, mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
9
9
  import path from "node:path";
@@ -1,5 +1,5 @@
1
1
  import { a as jsonNumber, c as jsonString, i as jsonBoolean, n as isJsonObject } from "./src-X9phtB2j.js";
2
- import { S as REVIEW_THEME_CHOICES, h as REVIEW_DIFF_LAYOUT_SCOPES, m as REVIEW_DIFF_LAYOUTS } from "./src-B8adXKNt.js";
2
+ import { S as REVIEW_THEME_CHOICES, h as REVIEW_DIFF_LAYOUT_SCOPES, m as REVIEW_DIFF_LAYOUTS } from "./src-HnIPjtjx.js";
3
3
  import { z } from "zod";
4
4
  //#region src/telemetry-clean-text.ts
5
5
  const USER_DATA_REGEXES = [
@@ -1,5 +1,5 @@
1
- import { o as parseReviewVerbResponse } from "./src-B8adXKNt.js";
2
- import { b as selectReviewInstance, m as healthyReviewInstance, v as reviewInstanceStartHint, y as reviewInstanceUnavailable } from "./server-discovery-BY_MN7tj.js";
1
+ import { o as parseReviewVerbResponse } from "./src-HnIPjtjx.js";
2
+ import { b as selectReviewInstance, m as healthyReviewInstance, v as reviewInstanceStartHint, y as reviewInstanceUnavailable } from "./server-discovery-CqRxbsER.js";
3
3
  import { closeSync, existsSync, fstatSync, mkdtempSync, openSync, readSync } from "node:fs";
4
4
  import path from "node:path";
5
5
  import { homedir, tmpdir } from "node:os";
@@ -1,9 +1,9 @@
1
1
  import { c as jsonString, l as jsonValueSchema, o as jsonObject, u as parseJsonText } from "./src-X9phtB2j.js";
2
- import "./src-B8adXKNt.js";
2
+ import "./src-HnIPjtjx.js";
3
3
  import "./review-home-paths-zwevIq4I.js";
4
4
  import { A as withFileLock, M as devReviewHome, O as processIsAlive, P as writeFileAtomic } from "./s3-config-DDWWMh5x.js";
5
5
  import { i as readReviewPackageVersion, t as findReviewPackageRoot } from "./package-paths-BsuI4WUf.js";
6
- import "./request-origin-DjOEwBAK.js";
6
+ import "./request-origin-C-V9f3Fr.js";
7
7
  import { createHmac, randomUUID } from "node:crypto";
8
8
  import { z } from "zod";
9
9
  import { existsSync, readFileSync, rmSync } from "node:fs";
@@ -1,21 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import { S as splitGitPatchFiles, a as diff, o as diffFileSummaries } from "../src-BMPuxWv4.js";
3
3
  import { c as jsonString, i as jsonBoolean, n as isJsonObject, p as isObjectValue, s as jsonProperty, u as parseJsonText } from "../src-X9phtB2j.js";
4
- import { d as StreamLimitError, f as readBoundedStream, i as SharedReviewStore } from "../client-BBBwu0P7.js";
5
- import { A as reviewDiffrSummarizerInputSchema, E as ReviewGatewayHostSchema, T as ReviewConnectRequestSchema, c as ReviewBugReportMetaV2Schema, d as REVIEW_CLIENT_HEADER, f as REVIEW_CLIENT_REMOTE, g as REVIEW_HOST_HEADER, l as ReviewBugReportRequestSchema, r as parseReviewDesktopVerbFrame, s as parseZod, t as parseReviewCliInstallApplyRequest, u as parseReviewBugReportResponse } from "../src-B8adXKNt.js";
4
+ import { d as StreamLimitError, f as readBoundedStream, i as SharedReviewStore } from "../client-_ltX1mah.js";
5
+ import { A as reviewDiffrSummarizerInputSchema, E as ReviewGatewayHostSchema, T as ReviewConnectRequestSchema, c as ReviewBugReportMetaV2Schema, d as REVIEW_CLIENT_HEADER, f as REVIEW_CLIENT_REMOTE, g as REVIEW_HOST_HEADER, l as ReviewBugReportRequestSchema, r as parseReviewDesktopVerbFrame, s as parseZod, t as parseReviewCliInstallApplyRequest, u as parseReviewBugReportResponse } from "../src-HnIPjtjx.js";
6
6
  import { i as reviewInstanceDiscoveryPath, o as reviewLegacyDiscoveryPath } from "../review-home-paths-zwevIq4I.js";
7
- import { w as resourceReferences } from "../stored-document-migration-CVMl7Te5.js";
7
+ import { w as resourceReferences } from "../stored-document-migration-DenDEYdI.js";
8
8
  import { t as ReviewInputError } from "../input-error-OLgB_h31.js";
9
9
  import { I as writePrivateJsonAtomic, M as devReviewHome } from "../s3-config-DDWWMh5x.js";
10
10
  import { t as errorMessage } from "../error-message-OtiDonty.js";
11
11
  import { i as readReviewPackageVersion, t as findReviewPackageRoot } from "../package-paths-BsuI4WUf.js";
12
- import { _ as reviewInstanceIdentity, u as REVIEW_INSTANCE_ENV } from "../server-discovery-BY_MN7tj.js";
13
- import { t as openReviewProfile } from "../profile-BoWYDne6.js";
14
- import { r as reviewTelemetryChannel, t as ReviewTelemetry } from "../review-telemetry-ycbk-YeT.js";
15
- import { o as REVIEW_TELEMETRY_TABS } from "../request-origin-DjOEwBAK.js";
16
- import { C as saveDiffrSummarizer, D as findExecutable, E as cliAskTools, S as readDiffrConfig, T as testDiffrSummarizer, _ as DEFAULT_MAX_REQUEST_BYTES, a as drainServerCrashReport, b as GlobalReviewDesktopVerbRelay, c as answerErrorsAsJson, d as coverageModeSchema, f as captureSanitizedUiTelemetry, g as readBoundedRequestJson, h as createNodeRequestListener, l as createWhiteboardCore, m as recordClientError, o as installProcessErrorTelemetry, p as clientErrorsForSession, r as takeOverServerHome, s as serverCrashReportPath, u as serverJson, v as HttpJsonError, w as setDiffrConfigValue, x as migrateDiffrConfig, y as ReviewServerError } from "../headless-host-DI82imwx.js";
17
- import { c as removeLegacyReviewSkills, d as skipCliInstall, i as finishCliInstallUpdate, l as resetCliInstall, m as ALL_INSTALL_TARGETS, n as applyCliInstall, o as pathShimPath, r as declineCliInstall, s as removeCliInstall, t as aliasInstallationToAccount, u as resolveCliInstallStatus, v as reviewMcpLaunch, y as cursorInstallDeeplink } from "../account-alias-3-HnWkjz.js";
18
- import { c as readQuerySchemas } from "../authoring-tools-CuGm_pVC.js";
12
+ import { _ as reviewInstanceIdentity, u as REVIEW_INSTANCE_ENV } from "../server-discovery-CqRxbsER.js";
13
+ import { t as openReviewProfile } from "../profile-CKSB6UDi.js";
14
+ import { r as reviewTelemetryChannel, t as ReviewTelemetry } from "../review-telemetry-9ceqh4wz.js";
15
+ import { o as REVIEW_TELEMETRY_TABS } from "../request-origin-C-V9f3Fr.js";
16
+ import { C as saveDiffrSummarizer, D as findExecutable, E as cliAskTools, S as readDiffrConfig, T as testDiffrSummarizer, _ as DEFAULT_MAX_REQUEST_BYTES, a as drainServerCrashReport, b as GlobalReviewDesktopVerbRelay, c as answerErrorsAsJson, d as coverageModeSchema, f as captureSanitizedUiTelemetry, g as readBoundedRequestJson, h as createNodeRequestListener, l as createWhiteboardCore, m as recordClientError, o as installProcessErrorTelemetry, p as clientErrorsForSession, r as takeOverServerHome, s as serverCrashReportPath, u as serverJson, v as HttpJsonError, w as setDiffrConfigValue, x as migrateDiffrConfig, y as ReviewServerError } from "../headless-host-ZNZ_6ZRo.js";
17
+ import { c as removeLegacyReviewSkills, d as skipCliInstall, i as finishCliInstallUpdate, l as resetCliInstall, m as ALL_INSTALL_TARGETS, n as applyCliInstall, o as pathShimPath, r as declineCliInstall, s as removeCliInstall, t as aliasInstallationToAccount, u as resolveCliInstallStatus, v as reviewMcpLaunch, y as cursorInstallDeeplink } from "../account-alias-C1ixP6bt.js";
18
+ import { c as readQuerySchemas } from "../authoring-tools-CtsslOEf.js";
19
19
  import crypto, { createHash, randomBytes } from "node:crypto";
20
20
  import { z } from "zod";
21
21
  import fs, { existsSync, readFileSync } from "node:fs";
@@ -1,5 +1,5 @@
1
1
  import { a as jsonNumber, n as isJsonObject, s as jsonProperty, u as parseJsonText } from "./src-X9phtB2j.js";
2
- import { n as parseReviewDesktopDiscovery } from "./src-B8adXKNt.js";
2
+ import { n as parseReviewDesktopDiscovery } from "./src-HnIPjtjx.js";
3
3
  import { a as reviewInstancesDir, o as reviewLegacyDiscoveryPath, r as reviewDevInstanceKey, t as reviewDefaultInstancePath } from "./review-home-paths-zwevIq4I.js";
4
4
  import { M as devReviewHome, O as processIsAlive, j as DEV_REVIEW_HOME_ENV } from "./s3-config-DDWWMh5x.js";
5
5
  import { z } from "zod";
@@ -1,2 +1,2 @@
1
- import { a as sharedReviewId, c as verifyShareRepository, i as SharedReviewStore, l as exportShare, n as ShareClient, o as validateShareBundle } from "../client-BBBwu0P7.js";
1
+ import { a as sharedReviewId, c as verifyShareRepository, i as SharedReviewStore, l as exportShare, n as ShareClient, o as validateShareBundle } from "../client-_ltX1mah.js";
2
2
  export { ShareClient, SharedReviewStore, exportShare, sharedReviewId, validateShareBundle, verifyShareRepository };
@@ -779,7 +779,8 @@ z.discriminatedUnion("event", [
779
779
  apiSource: ReviewApiSelectionSourceSchema.optional(),
780
780
  anchor: z.object({
781
781
  x: z.number(),
782
- y: z.number()
782
+ y: z.number(),
783
+ right: z.number().optional()
783
784
  }).optional(),
784
785
  path: requiredString$1,
785
786
  range: ReviewRangeSchema,
@@ -1,5 +1,5 @@
1
1
  import { f as isNumberValue, l as jsonValueSchema, m as isStringValue, n as isJsonObject } from "./src-X9phtB2j.js";
2
- import "./src-B8adXKNt.js";
2
+ import "./src-HnIPjtjx.js";
3
3
  import { t as ReviewInputError } from "./input-error-OLgB_h31.js";
4
4
  import { z } from "zod";
5
5
  import { fromMarkdown } from "mdast-util-from-markdown";
@@ -1,5 +1,5 @@
1
1
  import { m as isStringValue, n as isJsonObject } from "./src-X9phtB2j.js";
2
- import { n as callAuthoringTool, s as ReviewApiError, t as ToolText } from "./agent-client-DHKowVF7.js";
2
+ import { n as callAuthoringTool, s as ReviewApiError, t as ToolText } from "./agent-client-Dogh8I83.js";
3
3
  import { t as ReviewInputError } from "./input-error-OLgB_h31.js";
4
4
  //#region src/review-api/public-tools.ts
5
5
  function publicDescription(text) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev.fast/whiteboard",
3
- "version": "0.2.5-preview.20261015.117",
3
+ "version": "0.2.5-preview.20261015.118",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -74,11 +74,11 @@
74
74
  "tsx": "4.21.0",
75
75
  "typescript": "6.0.3",
76
76
  "vitest": "4.1.11",
77
- "@dev.fast/review-share-protocol": "0.1.2",
78
- "@dev.fast/review-protocol": "0.0.0",
79
- "@dev.fast/trace-core": "0.0.0",
80
77
  "@dev.fast/json": "0.0.0",
81
- "@dev.fast/trace-protocol": "0.5.0"
78
+ "@dev.fast/trace-protocol": "0.5.0",
79
+ "@dev.fast/trace-core": "0.0.0",
80
+ "@dev.fast/review-protocol": "0.0.0",
81
+ "@dev.fast/review-share-protocol": "0.1.2"
82
82
  },
83
83
  "engines": {
84
84
  "node": ">=24 <25"
@@ -88,7 +88,7 @@
88
88
  "repo": "devdotfast/review",
89
89
  "docs": "packages/review/instructions/authoring.md"
90
90
  },
91
- "gitHead": "b93a4fc67175685fab7275af8c2d80577d50513b",
91
+ "gitHead": "dc3ea1aee29b6ccf8860a763db26bc86ca52532c",
92
92
  "scripts": {
93
93
  "prebuild": "pnpm run build:workspace-deps",
94
94
  "build": "node --max-old-space-size=8192 node_modules/tsdown/dist/run.mjs",
@@ -0,0 +1,165 @@
1
+ import { errorMessage } from "@dev.fast/trace-core";
2
+ import { z } from "zod";
3
+
4
+ import { ReviewInputError } from "./document.js";
5
+ import type { PullRequestProvider } from "./provider.js";
6
+ import { firstLine } from "./pull-request.js";
7
+
8
+ const AZ_TIMEOUT_MS = 30_000;
9
+
10
+ const PULL_REQUEST_URLS = [
11
+ /^https:\/\/dev\.azure\.com\/([A-Za-z0-9-]+)\/([^/]+)\/_git\/([^/]+)\/pullrequest\/([1-9]\d*)$/,
12
+ /^https:\/\/([A-Za-z0-9-]+)\.visualstudio\.com\/(?:DefaultCollection\/)?([^/]+)\/_git\/([^/]+)\/pullrequest\/([1-9]\d*)$/,
13
+ ];
14
+
15
+ const REMOTE_URLS = [
16
+ /^https:\/\/(?:[^@]+@)?dev\.azure\.com\/([^/]+)\/([^/]+)\/_git\/([^/]+?)(?:\.git)?\/?$/,
17
+ /^https:\/\/([^.]+)\.visualstudio\.com\/(?:DefaultCollection\/)?([^/]+)\/_git\/([^/]+?)(?:\.git)?\/?$/,
18
+ /^git@ssh\.dev\.azure\.com:v3\/([^/]+)\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/,
19
+ /^[^@]+@vs-ssh\.visualstudio\.com:v3\/([^/]+)\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/,
20
+ ];
21
+
22
+ const metadataSchema = z.object({
23
+ title: z.string(),
24
+ sourceRefName: z.string().min(1),
25
+ targetRefName: z.string().min(1),
26
+ lastMergeTargetCommit: z.object({ commitId: z.string().min(1) }).optional(),
27
+ repository: z.object({
28
+ name: z.string(),
29
+ project: z.object({ name: z.string() }),
30
+ }),
31
+ });
32
+
33
+ /** org/project/repository, decoded; undefined for malformed escapes. */
34
+ function slugOf(patterns: RegExp[], url: string) {
35
+ const match = patterns.map((pattern) => pattern.exec(url)).find(Boolean);
36
+
37
+ try {
38
+ return match && match.slice(1, 4).map(decodeURIComponent).join("/");
39
+ } catch {
40
+ return undefined;
41
+ }
42
+ }
43
+
44
+ function azFailure(url: string, failure: string) {
45
+ const unreadable = (hint: string) =>
46
+ new ReviewInputError(
47
+ `Could not read ${url}: az failed (${failure}). ${hint}`,
48
+ 409,
49
+ );
50
+
51
+ if (
52
+ /not recognized as an internal or external command|command not found|enoent/i.test(
53
+ failure,
54
+ )
55
+ )
56
+ return unreadable(
57
+ "Install the Azure CLI and the azure-devops extension, then retry.",
58
+ );
59
+
60
+ if (
61
+ /extension|unknown command ['"]repos['"]|'repos' is not in the 'az' command group/i.test(
62
+ failure,
63
+ )
64
+ )
65
+ return unreadable(
66
+ "Run `az extension add --name azure-devops`, then retry.",
67
+ );
68
+
69
+ if (/az login|aadsts/i.test(failure))
70
+ return unreadable("Run `az login` to sign in, then retry.");
71
+
72
+ if (/tf401027|not found|does not exist/i.test(failure))
73
+ return new ReviewInputError(
74
+ `${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}`,
75
+ 404,
76
+ );
77
+
78
+ return unreadable(
79
+ "Check your Azure DevOps connection and credentials, then retry.",
80
+ );
81
+ }
82
+
83
+ export const azureDevOpsProvider: PullRequestProvider = {
84
+ id: "azure-devops",
85
+
86
+ parseUrl(url) {
87
+ const slug = slugOf(PULL_REQUEST_URLS, url);
88
+ const number = Number(url.split("/").at(-1));
89
+
90
+ if (!slug || !Number.isSafeInteger(number)) return undefined;
91
+
92
+ return { host: "dev.azure.com", slug, number };
93
+ },
94
+
95
+ async readPullRequest({ host, slug, number }, deps) {
96
+ const [org, project, repo] = slug.split("/");
97
+ const url = `https://dev.azure.com/${org}/${project}/_git/${repo}/pullrequest/${number}`;
98
+
99
+ const args = [
100
+ "repos",
101
+ "pr",
102
+ "show",
103
+ "--id",
104
+ String(number),
105
+ "--detect",
106
+ "false",
107
+ "--organization",
108
+ `https://dev.azure.com/${org}`,
109
+ "--output",
110
+ "json",
111
+ "--only-show-errors",
112
+ ];
113
+
114
+ let stdout: string;
115
+
116
+ try {
117
+ // Windows installs az as az.cmd, which execFile cannot start directly.
118
+ stdout =
119
+ process.platform === "win32"
120
+ ? await deps.run("cmd.exe", ["/d", "/s", "/c", "az", ...args], {
121
+ timeoutMs: AZ_TIMEOUT_MS,
122
+ })
123
+ : await deps.run("az", args, { timeoutMs: AZ_TIMEOUT_MS });
124
+ } catch (error) {
125
+ throw azFailure(url, firstLine(errorMessage(error)));
126
+ }
127
+
128
+ let pr: z.infer<typeof metadataSchema>;
129
+
130
+ try {
131
+ pr = metadataSchema.parse(JSON.parse(stdout));
132
+ } catch {
133
+ throw new ReviewInputError(
134
+ `Could not read ${url}: the Azure DevOps response was malformed.`,
135
+ 409,
136
+ );
137
+ }
138
+
139
+ // PR numbers are unique per organization, so az ignores project and repository.
140
+ const actual = `${pr.repository.project.name}/${pr.repository.name}`;
141
+
142
+ if (actual.toLowerCase() !== `${project}/${repo}`.toLowerCase())
143
+ throw new ReviewInputError(
144
+ `${url} was not found: PR ${number} belongs to ${actual}.`,
145
+ 404,
146
+ );
147
+
148
+ return {
149
+ host,
150
+ slug,
151
+ number,
152
+ title: pr.title,
153
+ headRef: pr.sourceRefName,
154
+ baseRefName: pr.targetRefName.replace(/^refs\/heads\//, ""),
155
+ baseRefOid: pr.lastMergeTargetCommit?.commitId,
156
+ };
157
+ },
158
+
159
+ matchesRemote(remoteUrl, address) {
160
+ return (
161
+ slugOf(REMOTE_URLS, remoteUrl.trim())?.toLowerCase() ===
162
+ address.slug.toLowerCase()
163
+ );
164
+ },
165
+ };
@@ -1241,8 +1241,8 @@ export class LocalReviewData {
1241
1241
 
1242
1242
  throw new ReviewInputError(
1243
1243
  repository.id
1244
- ? `That checkout has no GitHub remote for ${name}. Add one, or omit repositoryId.`
1245
- : `No registered checkout has a GitHub remote for ${name}. Register a checkout of ${name} with review_register_repository first, or pass a target.`,
1244
+ ? `That checkout has no remote for ${name}. Add one, or omit repositoryId.`
1245
+ : `No registered checkout has a remote for ${name}. Register a checkout of ${name} with review_register_repository first, or pass a target.`,
1246
1246
  404,
1247
1247
  );
1248
1248
  }
@@ -7,7 +7,7 @@ export const pullRequestUrl = z
7
7
  .string()
8
8
  .refine(
9
9
  (url) => pullRequestProvider(url) !== undefined,
10
- "Use a canonical GitHub PR URL: https://github.com/owner/repository/pull/123, or the same path on a GitHub Enterprise host.",
10
+ "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.",
11
11
  );
12
12
 
13
13
  /** One key per PR: GitHub owner and repository names are case-insensitive,
@@ -1,3 +1,4 @@
1
+ import { azureDevOpsProvider } from "./azure-devops-provider.js";
1
2
  import { ReviewInputError } from "./document.js";
2
3
  import { githubProvider } from "./github-provider.js";
3
4
  import type { PullRequestDeps, PullRequestRecord } from "./pull-request.js";
@@ -22,7 +23,7 @@ export interface PullRequestProvider {
22
23
  matchesRemote(remoteUrl: string, address: PullRequestAddress): boolean;
23
24
  }
24
25
 
25
- const providers: PullRequestProvider[] = [githubProvider];
26
+ const providers: PullRequestProvider[] = [githubProvider, azureDevOpsProvider];
26
27
 
27
28
  export function pullRequestProvider(url: string) {
28
29
  for (const provider of providers) {
@@ -1,2 +0,0 @@
1
- import { n as runReviewAgentCli } from "./agent-cli-BabaNr6w.js";
2
- export { runReviewAgentCli };
@@ -1,2 +0,0 @@
1
- import { t as openReviewProfile } from "./profile-BoWYDne6.js";
2
- export { openReviewProfile };