@a9n-shoji/rvw 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,17 @@
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.13.0] - 2026-10-18
9
+
10
+ ### Added
11
+
12
+ - 引数なしの`rvw`で登録済みPull Requestの一覧をブラウザで開けるようにしました。リポジトリ外や未登録の環境からも起動できます。
13
+
14
+ ### Changed
15
+
16
+ - 一覧起動時はPRの検出やGit/GitHubへの問い合わせを行わず、既存の`rvw open [PR]`は従来どおり利用できます。
17
+ - 内部のviewer起動protocolを7へ更新しました。公開Agent protocolは6のままです。
18
+
8
19
  ## [0.12.0] - 2026-10-05
9
20
 
10
21
  ### Added
package/README.md CHANGED
@@ -32,12 +32,17 @@ gh auth setup-git
32
32
  # インストール
33
33
  npm install --global @a9n-shoji/rvw
34
34
 
35
- # baseリポジトリへ移動して起動
35
+ # 登録済みPRの一覧を開く(リポジトリの外でも実行可能)
36
+ rvw
37
+
38
+ # 初めてのPRを登録して開く
36
39
  cd /path/to/base-repository-clone
37
40
  rvw doctor
38
41
  rvw open https://github.com/owner/repository/pull/123
39
42
  ```
40
43
 
44
+ `rvw` だけで登録済みPRの一覧を開き、行を選んでレビューを再開できます。未登録の場合は `rvw open <PR URL>` でPRを追加してください。
45
+
41
46
  `http://127.0.0.1:43117` でブラウザが開きます。ブラウザのタブをすべて閉じると、サーバーも自動停止します。
42
47
 
43
48
  ---
package/dist/cli.mjs CHANGED
@@ -18753,7 +18753,7 @@ function parseWalkthroughUri(uri) {
18753
18753
  }
18754
18754
 
18755
18755
  // src/shared/constants.ts
18756
- var APP_VERSION = "0.12.0";
18756
+ var APP_VERSION = "0.13.0";
18757
18757
  var PROTOCOL_VERSION = 6;
18758
18758
  var VIEWER_ID_HEADER = "x-rvw-viewer-id";
18759
18759
  var VIEWER_OPEN_LEASE_HEADER = "x-rvw-viewer-open-lease";
@@ -51005,7 +51005,7 @@ import os4 from "node:os";
51005
51005
  import path10 from "node:path";
51006
51006
  var MAX_CLI_STDIN_BYTES = 40 * 1024 * 1024;
51007
51007
  var MAX_AGENT_MESSAGE_BYTES = MAX_CLI_STDIN_BYTES + 64 * 1024;
51008
- var AGENT_SOCKET_PROTOCOL_VERSION = 6;
51008
+ var AGENT_SOCKET_PROTOCOL_VERSION = 7;
51009
51009
  var RUNTIME_VIEWER_OPEN_OPERATION = "viewer.open";
51010
51010
  var AGENT_SOCKET_RESTART_SUGGESTION = "\u8D77\u52D5\u4E2D\u306Ervw viewer\u3092\u505C\u6B62\u3057\u3001\u66F4\u65B0\u5F8C\u306Ervw open\u3067\u518D\u8D77\u52D5\u3057\u3066\u304F\u3060\u3055\u3044\u3002";
51011
51011
  var DEFAULT_CONNECT_TIMEOUT_MS = 2e3;
@@ -51021,14 +51021,17 @@ var agentRequestEnvelopeSchema = external_exports.object({
51021
51021
  }).strict();
51022
51022
  var runtimeViewerOpenInputSchema = external_exports.object({
51023
51023
  reference: external_exports.string().min(1).optional(),
51024
+ list: external_exports.boolean().optional(),
51024
51025
  cwd: external_exports.string().min(1),
51025
51026
  requestedPort: external_exports.number().int().min(0).max(65535)
51026
- }).strict();
51027
+ }).strict().refine((input) => !input.list || input.reference === void 0, {
51028
+ message: "\u4E00\u89A7\u8D77\u52D5\u306B\u306FPR\u3092\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002"
51029
+ });
51027
51030
  var runtimeViewerOpenResultSchema = external_exports.object({
51028
51031
  url: external_exports.string().url(),
51029
51032
  origin: external_exports.string().url(),
51030
51033
  port: external_exports.number().int().min(1).max(65535),
51031
- pullRequestId: external_exports.string().min(1),
51034
+ pullRequestId: external_exports.string().min(1).nullable(),
51032
51035
  ownerPid: external_exports.number().int().positive(),
51033
51036
  viewerLeaseId: external_exports.uuid().optional()
51034
51037
  }).strict();
@@ -51897,6 +51900,7 @@ async function startRuntimeAgentSocket(databaseFilePath) {
51897
51900
  if (!parsed.success) throw invalidSocketInput(parsed.error);
51898
51901
  return await (await handlerPromise).openViewer({
51899
51902
  ...parsed.data.reference === void 0 ? {} : { reference: parsed.data.reference },
51903
+ ...parsed.data.list === void 0 ? {} : { list: parsed.data.list },
51900
51904
  cwd: parsed.data.cwd,
51901
51905
  requestedPort: parsed.data.requestedPort
51902
51906
  });
@@ -52348,6 +52352,16 @@ var OPEN_WORKER_PARENT_TIMEOUT_PADDING_MS = 5e3;
52348
52352
  var RUNTIME_REUSE_RETRY_MS = 50;
52349
52353
  var RUNTIME_VIEWER_HEARTBEAT_INTERVAL_MS = 3e4;
52350
52354
  var RUNTIME_VIEWER_REQUEST_TIMEOUT_MS = 5e3;
52355
+ function viewerLaunchOptions(command) {
52356
+ let options = { ...command.opts() };
52357
+ const parent = command.parent;
52358
+ for (const key2 of ["open", "foreground", "port"]) {
52359
+ if (command.getOptionValueSource(key2) !== "cli" && parent?.getOptionValueSource(key2) === "cli") {
52360
+ options = { ...options, [key2]: parent.opts()[key2] };
52361
+ }
52362
+ }
52363
+ return options;
52364
+ }
52351
52365
  function writeJson(value) {
52352
52366
  process.stdout.write(`${JSON.stringify(value)}
52353
52367
  `);
@@ -52560,13 +52574,14 @@ function staticDirectory() {
52560
52574
  ];
52561
52575
  return candidates.find((candidate) => existsSync6(candidate)) ?? candidates[0];
52562
52576
  }
52563
- function forkOpenWorker(reference, port, requestedPort) {
52577
+ function forkOpenWorker(reference, port, requestedPort, list2) {
52564
52578
  const modulePath = process.argv[1];
52565
52579
  if (!modulePath) {
52566
52580
  throw new RvwError("PROCESS_FAILED", "rvw CLI\u306E\u5B9F\u884Cpath\u3092\u89E3\u6C7A\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002");
52567
52581
  }
52568
52582
  const args = ["__open-worker", "--port", String(port), "--requested-port", String(requestedPort)];
52569
52583
  if (reference !== void 0) args.push("--reference", reference);
52584
+ if (list2) args.push("--list");
52570
52585
  return fork(path11.resolve(modulePath), args, {
52571
52586
  cwd: process.cwd(),
52572
52587
  env: process.env,
@@ -52574,11 +52589,12 @@ function forkOpenWorker(reference, port, requestedPort) {
52574
52589
  stdio: ["ignore", "ignore", "ignore", "ipc"]
52575
52590
  });
52576
52591
  }
52577
- async function startBackgroundOpen(reference, port, dependencies = {}) {
52592
+ async function startBackgroundOpen(reference, port, dependencies = {}, list2 = false) {
52578
52593
  const startupPort = port ?? DEFAULT_VIEWER_PORT;
52579
52594
  const requestedPort = port ?? 0;
52580
52595
  const input = {
52581
52596
  ...reference === void 0 ? {} : { reference },
52597
+ ...list2 ? { list: true } : {},
52582
52598
  cwd: process.cwd(),
52583
52599
  requestedPort
52584
52600
  };
@@ -52600,7 +52616,12 @@ async function startBackgroundOpen(reference, port, dependencies = {}) {
52600
52616
  { details: existing.details }
52601
52617
  );
52602
52618
  }
52603
- const child = (dependencies.forkWorker ?? forkOpenWorker)(reference, startupPort, requestedPort);
52619
+ const child = (dependencies.forkWorker ?? forkOpenWorker)(
52620
+ reference,
52621
+ startupPort,
52622
+ requestedPort,
52623
+ list2
52624
+ );
52604
52625
  return await completeBackgroundOpen(child, launchBrowser);
52605
52626
  }
52606
52627
  async function sendOpenWorkerMessage(message) {
@@ -52633,9 +52654,10 @@ async function waitForInitialViewer(firstViewerConnected, timeoutMs = DEFAULT_VI
52633
52654
  void firstViewerConnected.then(() => finish("connected"));
52634
52655
  });
52635
52656
  }
52636
- function runtimeViewerOpenInput(reference, cwd, requestedPort) {
52657
+ function runtimeViewerOpenInput(reference, cwd, requestedPort, list2) {
52637
52658
  return {
52638
52659
  ...reference === void 0 ? {} : { reference },
52660
+ ...list2 ? { list: true } : {},
52639
52661
  cwd,
52640
52662
  requestedPort
52641
52663
  };
@@ -52658,16 +52680,16 @@ function createRuntimeAgentSocketHandler(activeRuntime, running) {
52658
52680
  }
52659
52681
  const viewerLeaseId = running.reserveViewer();
52660
52682
  try {
52661
- const opened = await activeRuntime.service.openPullRequest(input.reference, input.cwd);
52683
+ const opened = input.list ? null : await activeRuntime.service.openPullRequest(input.reference, input.cwd);
52662
52684
  if (viewerLeaseId !== null) running.armViewerReservation(viewerLeaseId);
52663
52685
  const url2 = new URL(running.origin);
52664
- url2.searchParams.set("pullRequestId", opened.pullRequest.id);
52686
+ if (opened) url2.searchParams.set("pullRequestId", opened.pullRequest.id);
52665
52687
  if (viewerLeaseId !== null) url2.searchParams.set(VIEWER_OPEN_LEASE_QUERY, viewerLeaseId);
52666
52688
  return {
52667
52689
  url: url2.toString(),
52668
52690
  origin: running.origin,
52669
52691
  port: running.port,
52670
- pullRequestId: opened.pullRequest.id,
52692
+ pullRequestId: opened?.pullRequest.id ?? null,
52671
52693
  ownerPid: process.pid,
52672
52694
  ...viewerLeaseId === null ? {} : { viewerLeaseId }
52673
52695
  };
@@ -52792,7 +52814,7 @@ async function waitForWorkerParentDisconnect() {
52792
52814
  if (!process.connected) return;
52793
52815
  await new Promise((resolve) => process.once("disconnect", resolve));
52794
52816
  }
52795
- async function runOpenServer(runtimeFactory, reference, port, openAutomatically, useAgentSocket, reuseExisting) {
52817
+ async function runOpenServer(runtimeFactory, reference, port, openAutomatically, useAgentSocket, reuseExisting, list2 = false) {
52796
52818
  const startupPort = port ?? DEFAULT_VIEWER_PORT;
52797
52819
  const requestedPort = port ?? 0;
52798
52820
  let activeRuntime;
@@ -52803,7 +52825,7 @@ async function runOpenServer(runtimeFactory, reference, port, openAutomatically,
52803
52825
  const databaseFilePath = databasePathConfiguration().filePath;
52804
52826
  if (reuseExisting) {
52805
52827
  const startup = await acquireRuntimeOrReuseExisting(
52806
- runtimeViewerOpenInput(reference, process.cwd(), requestedPort),
52828
+ runtimeViewerOpenInput(reference, process.cwd(), requestedPort, list2),
52807
52829
  databaseFilePath
52808
52830
  );
52809
52831
  if (startup.kind === "reused") {
@@ -52830,7 +52852,7 @@ async function runOpenServer(runtimeFactory, reference, port, openAutomatically,
52830
52852
  }
52831
52853
  }
52832
52854
  activeRuntime = runtimeFactory();
52833
- const opened = await activeRuntime.service.openPullRequest(reference, process.cwd());
52855
+ const opened = list2 ? null : await activeRuntime.service.openPullRequest(reference, process.cwd());
52834
52856
  running = await startServer(activeRuntime.service, {
52835
52857
  port: startupPort,
52836
52858
  staticDirectory: staticDirectory(),
@@ -52838,7 +52860,7 @@ async function runOpenServer(runtimeFactory, reference, port, openAutomatically,
52838
52860
  });
52839
52861
  agentSocket?.setHandler(createRuntimeAgentSocketHandler(activeRuntime, running));
52840
52862
  const url2 = new URL(running.origin);
52841
- url2.searchParams.set("pullRequestId", opened.pullRequest.id);
52863
+ if (opened) url2.searchParams.set("pullRequestId", opened.pullRequest.id);
52842
52864
  process.stdout.write(`rvw: ${url2.toString()}
52843
52865
  `);
52844
52866
  if (openAutomatically) await open_default(url2.toString());
@@ -52850,7 +52872,7 @@ async function runOpenServer(runtimeFactory, reference, port, openAutomatically,
52850
52872
  await closeOwnedRuntime(agentSocket, running, activeRuntime);
52851
52873
  }
52852
52874
  }
52853
- async function runOpenWorker(runtimeFactory, reference, port, requestedPort) {
52875
+ async function runOpenWorker(runtimeFactory, reference, port, requestedPort, list2) {
52854
52876
  let activeRuntime;
52855
52877
  let running;
52856
52878
  let agentSocket;
@@ -52860,7 +52882,7 @@ async function runOpenWorker(runtimeFactory, reference, port, requestedPort) {
52860
52882
  }
52861
52883
  const databaseFilePath = databasePathConfiguration().filePath;
52862
52884
  const startup = await acquireRuntimeOrReuseExisting(
52863
- runtimeViewerOpenInput(reference, process.cwd(), requestedPort),
52885
+ runtimeViewerOpenInput(reference, process.cwd(), requestedPort, list2),
52864
52886
  databaseFilePath
52865
52887
  );
52866
52888
  if (startup.kind === "reused") {
@@ -52872,7 +52894,7 @@ async function runOpenWorker(runtimeFactory, reference, port, requestedPort) {
52872
52894
  }
52873
52895
  agentSocket = startup.agentSocket;
52874
52896
  activeRuntime = runtimeFactory();
52875
- const opened = await activeRuntime.service.openPullRequest(reference, process.cwd());
52897
+ const opened = list2 ? null : await activeRuntime.service.openPullRequest(reference, process.cwd());
52876
52898
  running = await startServer(activeRuntime.service, {
52877
52899
  port,
52878
52900
  staticDirectory: staticDirectory(),
@@ -52880,7 +52902,7 @@ async function runOpenWorker(runtimeFactory, reference, port, requestedPort) {
52880
52902
  });
52881
52903
  agentSocket.setHandler(createRuntimeAgentSocketHandler(activeRuntime, running));
52882
52904
  const url2 = new URL(running.origin);
52883
- url2.searchParams.set("pullRequestId", opened.pullRequest.id);
52905
+ if (opened) url2.searchParams.set("pullRequestId", opened.pullRequest.id);
52884
52906
  if (!await sendOpenWorkerMessage({ type: "ready", url: url2.toString() })) return;
52885
52907
  const firstViewerConnected = running.firstViewerConnected;
52886
52908
  if (!firstViewerConnected) {
@@ -52917,7 +52939,9 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
52917
52939
  return await direct();
52918
52940
  };
52919
52941
  const program2 = new Command();
52920
- program2.name("rvw").description("GitHub Pull Request\u3092commit\u5358\u4F4D\u3067\u95B2\u89A7\u30FB\u30B3\u30E1\u30F3\u30C8\u3059\u308B\u30ED\u30FC\u30AB\u30EBviewer").version(APP_VERSION).showHelpAfterError();
52942
+ program2.name("rvw").description(
52943
+ "GitHub Pull Request\u3092commit\u5358\u4F4D\u3067\u95B2\u89A7\u30FB\u30B3\u30E1\u30F3\u30C8\u3059\u308B\u30ED\u30FC\u30AB\u30EBviewer\u3002\u5F15\u6570\u306A\u3057\u3067\u767B\u9332\u6E08\u307FPR\u4E00\u89A7\u3092\u958B\u304F"
52944
+ ).version(APP_VERSION).enablePositionalOptions().showHelpAfterError();
52921
52945
  program2.command("doctor").description(
52922
52946
  "git\u3001gh\u8A8D\u8A3C\u3001repository\u3001DB\u3092\u78BA\u8A8D\uFF08RVW_DATABASE_PATH\u306Fchmod\u3057\u306A\u3044caller-managed DB\uFF09"
52923
52947
  ).option("--json", "JSON\u3067\u51FA\u529B").action(async (options) => {
@@ -53002,37 +53026,52 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
53002
53026
  writeOutput(options, { ok: ok2, ...status }, formatAgentTransportStatus(status));
53003
53027
  if (!ok2) process.exitCode = 2;
53004
53028
  });
53005
- program2.command("open").argument("[pull-request]", "PR URL\u307E\u305F\u306F\u756A\u53F7").option("--no-open", "\u30D6\u30E9\u30A6\u30B6\u3092\u958B\u304B\u306A\u3044").option("--foreground", "terminal\u306B\u63A5\u7D9A\u3057\u305F\u307E\u307Eviewer\u3092\u5B9F\u884C").option("--port <port>", `listen port\uFF08\u65E2\u5B9A${DEFAULT_VIEWER_PORT}\u30010\u306F\u81EA\u52D5\uFF09`, parsePort).description("Pull Request\u3092\u958B\u3044\u3066\u30ED\u30FC\u30AB\u30EBviewer\u3092\u8D77\u52D5").action(
53006
- async (reference, options) => {
53007
- if (options.open && !options.foreground && useAgentSocket) {
53008
- const url2 = await startBackgroundOpen(reference, options.port);
53009
- process.stdout.write(`rvw: ${url2}
53029
+ const launchViewer = async (reference, options, list2) => {
53030
+ if (options.open && !options.foreground && useAgentSocket) {
53031
+ const url2 = await startBackgroundOpen(reference, options.port, {}, list2);
53032
+ process.stdout.write(`rvw: ${url2}
53010
53033
  `);
53011
- return;
53012
- }
53013
- await runOpenServer(
53014
- getRuntime,
53015
- reference,
53016
- options.port,
53017
- options.open,
53018
- useAgentSocket,
53019
- !options.foreground
53020
- );
53034
+ return;
53035
+ }
53036
+ await runOpenServer(
53037
+ getRuntime,
53038
+ reference,
53039
+ options.port,
53040
+ options.open,
53041
+ useAgentSocket,
53042
+ !options.foreground,
53043
+ list2
53044
+ );
53045
+ };
53046
+ program2.option("--no-open", "\u30D6\u30E9\u30A6\u30B6\u3092\u958B\u304B\u306A\u3044").option("--foreground", "terminal\u306B\u63A5\u7D9A\u3057\u305F\u307E\u307Eviewer\u3092\u5B9F\u884C").option("--port <port>", `listen port\uFF08\u65E2\u5B9A${DEFAULT_VIEWER_PORT}\u30010\u306F\u81EA\u52D5\uFF09`, parsePort).action(async (options) => {
53047
+ await launchViewer(void 0, options, true);
53048
+ });
53049
+ program2.command("open").argument("[pull-request]", "PR URL\u307E\u305F\u306F\u756A\u53F7").option("--no-open", "\u30D6\u30E9\u30A6\u30B6\u3092\u958B\u304B\u306A\u3044").option("--foreground", "terminal\u306B\u63A5\u7D9A\u3057\u305F\u307E\u307Eviewer\u3092\u5B9F\u884C").option("--port <port>", `listen port\uFF08\u65E2\u5B9A${DEFAULT_VIEWER_PORT}\u30010\u306F\u81EA\u52D5\uFF09`, parsePort).description("Pull Request\u3092\u958B\u3044\u3066\u30ED\u30FC\u30AB\u30EBviewer\u3092\u8D77\u52D5").action(
53050
+ async (reference, _options, command) => {
53051
+ await launchViewer(reference, viewerLaunchOptions(command), false);
53021
53052
  }
53022
53053
  );
53023
- program2.command("__open-worker", { hidden: true }).option("--reference <pull-request>").requiredOption("--port <port>", "listen port", parsePort).requiredOption("--requested-port <port>", "requested listen port", parsePort).action(async (options) => {
53024
- try {
53025
- await runOpenWorker(getRuntime, options.reference, options.port, options.requestedPort);
53026
- } catch (error51) {
53027
- const rvwError = asRvwError(error51);
53028
- const sent = await sendOpenWorkerMessage({
53029
- type: "error",
53030
- error: { ...rvwError.toJSON(), status: rvwError.status }
53031
- });
53032
- if (!sent) throw error51;
53033
- process.exitCode = rvwError.status >= 500 ? 1 : 2;
53054
+ program2.command("__open-worker", { hidden: true }).option("--reference <pull-request>").option("--list", "\u767B\u9332\u6E08\u307FPR\u4E00\u89A7\u3092\u958B\u304F").requiredOption("--port <port>", "listen port", parsePort).requiredOption("--requested-port <port>", "requested listen port", parsePort).action(
53055
+ async (options) => {
53056
+ try {
53057
+ await runOpenWorker(
53058
+ getRuntime,
53059
+ options.reference,
53060
+ options.port,
53061
+ options.requestedPort,
53062
+ options.list ?? false
53063
+ );
53064
+ } catch (error51) {
53065
+ const rvwError = asRvwError(error51);
53066
+ const sent = await sendOpenWorkerMessage({
53067
+ type: "error",
53068
+ error: { ...rvwError.toJSON(), status: rvwError.status }
53069
+ });
53070
+ if (!sent) throw error51;
53071
+ process.exitCode = rvwError.status >= 500 ? 1 : 2;
53072
+ }
53034
53073
  }
53035
- });
53074
+ );
53036
53075
  const pr = program2.command("pr").description("Pull Request\u72B6\u614B\u3092\u7BA1\u7406");
53037
53076
  pr.command("list").option("--json", "JSON\u3067\u51FA\u529B").option("--offset <offset>", "\u958B\u59CB\u4F4D\u7F6E", "0").option("--limit <limit>", "\u53D6\u5F97\u4EF6\u6570\uFF08\u6700\u5927100\uFF09", "50").option("--include-archived", "\u30A2\u30FC\u30AB\u30A4\u30D6\u6E08\u307F\u3082\u542B\u3081\u308B").option("--include-closed", "Closed / Merged\u3082\u542B\u3081\u308B").action(
53038
53077
  async (options) => {
@@ -53548,7 +53587,7 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
53548
53587
  );
53549
53588
  });
53550
53589
  program2.hook("postAction", (_command, actionCommand) => {
53551
- if (actionCommand.name() !== "open" && actionCommand.name() !== "__open-worker") {
53590
+ if (actionCommand !== program2 && actionCommand.name() !== "open" && actionCommand.name() !== "__open-worker") {
53552
53591
  runtime?.close();
53553
53592
  }
53554
53593
  });
@@ -53588,6 +53627,7 @@ export {
53588
53627
  holdRuntimeViewerLease,
53589
53628
  runCli,
53590
53629
  startBackgroundOpen,
53630
+ viewerLaunchOptions,
53591
53631
  waitForServerShutdown
53592
53632
  };
53593
53633
  //# sourceMappingURL=cli.mjs.map