@a9n-shoji/rvw 0.3.0 → 0.3.1

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 (95) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +19 -7
  3. package/dist/cli.mjs +701 -87
  4. package/dist/cli.mjs.map +4 -4
  5. package/dist/web/assets/{DocumentViewer-DtusMl0r.js → DocumentViewer-C7UMfzam.js} +1 -1
  6. package/dist/web/assets/{MarkdownTable-BjwiOHQe.js → MarkdownTable-Dg8UkuDK.js} +1 -1
  7. package/dist/web/assets/{WalkthroughViewer-BNwKsKzk.js → WalkthroughViewer-BvS7o2T0.js} +1 -1
  8. package/dist/web/assets/{abnfDiagram-N423BO3Z-DtH8B7Z7.js → abnfDiagram-N423BO3Z-C2idvncb.js} +1 -1
  9. package/dist/web/assets/architecture-TIHT7OUA-C7fqtQhb.js +1 -0
  10. package/dist/web/assets/{architectureDiagram-T3A2C74G-5Fq3Xylv.js → architectureDiagram-T3A2C74G-Cdm5LY27.js} +1 -1
  11. package/dist/web/assets/{blockDiagram-VBNYF7ZC-BBG7PXeg.js → blockDiagram-VBNYF7ZC-C77pTjUb.js} +1 -1
  12. package/dist/web/assets/{c4Diagram-5PPSVZJV-oLErQeqr.js → c4Diagram-5PPSVZJV-DGHS-vVy.js} +1 -1
  13. package/dist/web/assets/channel-DwAsM5u1.js +1 -0
  14. package/dist/web/assets/{chunk-2GRJ4B5K-Bknsyt9u.js → chunk-2GRJ4B5K-DeUANCIz.js} +1 -1
  15. package/dist/web/assets/{chunk-4I5QYGJK-D-Icvgxq.js → chunk-4I5QYGJK-CMh2oglh.js} +1 -1
  16. package/dist/web/assets/{chunk-5RXB4S5H-B1iIyQwd.js → chunk-5RXB4S5H-DKTEiVyP.js} +1 -1
  17. package/dist/web/assets/{chunk-6Q2QTUOP-C09OFw2-.js → chunk-6Q2QTUOP-CcgtbZZN.js} +1 -1
  18. package/dist/web/assets/{chunk-7Z6QIM7H-BqCAUqX5.js → chunk-7Z6QIM7H-ktwy8mS7.js} +1 -1
  19. package/dist/web/assets/{chunk-GF5L2VYU-BHy3jGGE.js → chunk-GF5L2VYU-C3sn41mA.js} +1 -1
  20. package/dist/web/assets/{chunk-I66GZJ75-BBhE3jWF.js → chunk-I66GZJ75-PkPnHXQJ.js} +1 -1
  21. package/dist/web/assets/{chunk-JQJVKLGR-DNslGDt7.js → chunk-JQJVKLGR-C7Y_Zm_L.js} +1 -1
  22. package/dist/web/assets/{chunk-KBJHAD2P-J7tWEBhK.js → chunk-KBJHAD2P-CPGb1KEF.js} +1 -1
  23. package/dist/web/assets/{chunk-NSK5VX7P-retcSoJp.js → chunk-NSK5VX7P-CiYrTyo0.js} +1 -1
  24. package/dist/web/assets/{chunk-QR6OTTB3-DvFlp4db.js → chunk-QR6OTTB3-Cxc4CBz3.js} +1 -1
  25. package/dist/web/assets/{chunk-UBXNYLIW-gyX_iwb1.js → chunk-UBXNYLIW-Cu8_QUds.js} +1 -1
  26. package/dist/web/assets/{chunk-W5SLKNZC-BGNgHuYL.js → chunk-W5SLKNZC-xEW_C207.js} +1 -1
  27. package/dist/web/assets/{chunk-WRU74C26-66KXN6Rn.js → chunk-WRU74C26-lur1bNcP.js} +1 -1
  28. package/dist/web/assets/classDiagram-JCYQIIEL-ZOHoHid8.js +1 -0
  29. package/dist/web/assets/classDiagram-v2-OCEON4UE-ZOHoHid8.js +1 -0
  30. package/dist/web/assets/{cynefin-VYW2F7L2-Dj_jqvQa.js → cynefin-VYW2F7L2-D8ja_01T.js} +1 -1
  31. package/dist/web/assets/{cynefinDiagram-MW4NZA55-DSnUS3JS.js → cynefinDiagram-MW4NZA55-DRefzYPy.js} +1 -1
  32. package/dist/web/assets/{dagre-VZM6K2ZE-BTedug-5.js → dagre-VZM6K2ZE-DzKymXhT.js} +1 -1
  33. package/dist/web/assets/{diagram-7IWD3JNH-kSc1kTCk.js → diagram-7IWD3JNH-B1TUtKVL.js} +1 -1
  34. package/dist/web/assets/{diagram-B4RE2ZJO-DNtXohxd.js → diagram-B4RE2ZJO-DQ7yWH6C.js} +1 -1
  35. package/dist/web/assets/{diagram-LBJQPF4R-CVD-8DKW.js → diagram-LBJQPF4R-h5ld83dF.js} +1 -1
  36. package/dist/web/assets/{diagram-Q27KOJAE-DBEnUsLJ.js → diagram-Q27KOJAE-CQyWB8j1.js} +1 -1
  37. package/dist/web/assets/{diagram-UB23O5K3-DiPHfrk7.js → diagram-UB23O5K3-SmscW8SS.js} +1 -1
  38. package/dist/web/assets/{ebnfDiagram-BXEA7PRR-CE06v37i.js → ebnfDiagram-BXEA7PRR-B6Uv9Fga.js} +1 -1
  39. package/dist/web/assets/{erDiagram-JOGREHBK-jm3RTuJX.js → erDiagram-JOGREHBK-DlhKVbK5.js} +1 -1
  40. package/dist/web/assets/eventmodeling-45OFAUF4-hg8ilqKd.js +1 -0
  41. package/dist/web/assets/flowDiagram-UKHOOZJN-DlU6Mvry.js +1 -0
  42. package/dist/web/assets/{ganttDiagram-PKOTCBZU--GwSY0BM.js → ganttDiagram-PKOTCBZU-Buwx6kT-.js} +1 -1
  43. package/dist/web/assets/{gitGraph-TEB2WS4Q-C6oA29oA.js → gitGraph-TEB2WS4Q-DcKoIebc.js} +1 -1
  44. package/dist/web/assets/{gitGraphDiagram-DS77QQ5N-DR1mGQ6a.js → gitGraphDiagram-DS77QQ5N-6hyOioar.js} +1 -1
  45. package/dist/web/assets/index-CLhFOtpL.css +1 -0
  46. package/dist/web/assets/index-DYmdeW10.js +384 -0
  47. package/dist/web/assets/{info-DKCQHKI2-BT4oYSnk.js → info-DKCQHKI2-BTrntoWR.js} +1 -1
  48. package/dist/web/assets/{infoDiagram-6WML65LV-D0mnXRu0.js → infoDiagram-6WML65LV-C9vEklZc.js} +1 -1
  49. package/dist/web/assets/{ishikawaDiagram-WSZJBQD7-ErnJ_7Sr.js → ishikawaDiagram-WSZJBQD7-u7_elIzl.js} +1 -1
  50. package/dist/web/assets/{journeyDiagram-NVQOT4AX-CWvooGdp.js → journeyDiagram-NVQOT4AX-C2jFr8oy.js} +1 -1
  51. package/dist/web/assets/{kanban-definition-27J2QSJJ-DsIS6ipP.js → kanban-definition-27J2QSJJ-D-7UHdx4.js} +1 -1
  52. package/dist/web/assets/{line-DCcVjraC.js → line-CQAM_baC.js} +1 -1
  53. package/dist/web/assets/{mermaid-parser.core-BmDn4VB6.js → mermaid-parser.core-D2z7ZOcE.js} +3 -3
  54. package/dist/web/assets/{mermaid.core-Cus_gjGs.js → mermaid.core-d5lQFkUm.js} +4 -4
  55. package/dist/web/assets/{mindmap-definition-FAOFIHXS-DdsB9lmP.js → mindmap-definition-FAOFIHXS-tXNzs65p.js} +1 -1
  56. package/dist/web/assets/{packet-7NZHBO7P-BXuujfeh.js → packet-7NZHBO7P-Ck4WifuO.js} +1 -1
  57. package/dist/web/assets/{pegDiagram-VL7TDLO6-CBF6Uic6.js → pegDiagram-VL7TDLO6-CI2wa80w.js} +1 -1
  58. package/dist/web/assets/{pie-RZYD4A2V-DgssvIaB.js → pie-RZYD4A2V-HqKGJX8R.js} +1 -1
  59. package/dist/web/assets/{pieDiagram-7S7Q4E2Y-DejhR8Wh.js → pieDiagram-7S7Q4E2Y-DiANc3xh.js} +1 -1
  60. package/dist/web/assets/{quadrantDiagram-CIZ2JOQS-CryFsz7r.js → quadrantDiagram-CIZ2JOQS-Ck1WL56V.js} +1 -1
  61. package/dist/web/assets/{radar-I7S5WNFK-CoiIzjHC.js → radar-I7S5WNFK-BGZ0ArkI.js} +1 -1
  62. package/dist/web/assets/{railroad-3IZDKUUU-CWq6IkAh.js → railroad-3IZDKUUU-CG80mKUm.js} +1 -1
  63. package/dist/web/assets/railroad-abnf-AHOZXSZD-siyTaNqs.js +1 -0
  64. package/dist/web/assets/railroad-ebnf-EBAXGLYW-CXsuiW_x.js +1 -0
  65. package/dist/web/assets/railroad-peg-LSFZ7HO6-2Zrn2h_2.js +1 -0
  66. package/dist/web/assets/{railroadDiagram-AXF67PYL-DkePHtcR.js → railroadDiagram-AXF67PYL-DqLD6_Ag.js} +1 -1
  67. package/dist/web/assets/{requirementDiagram-LRYGKXZP-D2-9KlK1.js → requirementDiagram-LRYGKXZP-C-GtPNYS.js} +1 -1
  68. package/dist/web/assets/{sankeyDiagram-W5VNT64P-DSOFAzno.js → sankeyDiagram-W5VNT64P-DiFurH1m.js} +1 -1
  69. package/dist/web/assets/{sequenceDiagram-SI44F4Z6-BHEKSYJt.js → sequenceDiagram-SI44F4Z6-BBJvY7He.js} +1 -1
  70. package/dist/web/assets/{stateDiagram-OKZ733FA-f1GttDrB.js → stateDiagram-OKZ733FA-CJJJoWYF.js} +1 -1
  71. package/dist/web/assets/stateDiagram-v2-UEYNNEHI-Cwihtgsj.js +1 -0
  72. package/dist/web/assets/{swimlanes-SLNWSIFB-Dx7QlDaA.js → swimlanes-SLNWSIFB-DDD-kqF3.js} +1 -1
  73. package/dist/web/assets/swimlanesDiagram-ULZ7WXOC-CthM5wkr.js +8 -0
  74. package/dist/web/assets/{timeline-definition-Z64GVDOM-C7eeBnPC.js → timeline-definition-Z64GVDOM-CPtTrFUL.js} +1 -1
  75. package/dist/web/assets/{treeView-QDETBFTQ-BPsqqMsK.js → treeView-QDETBFTQ-CXpMsauD.js} +1 -1
  76. package/dist/web/assets/{treemap-6X3UGDF4-CmBU76N7.js → treemap-6X3UGDF4-DODWUMCI.js} +1 -1
  77. package/dist/web/assets/{vennDiagram-T6HMQDX7-DTIq1ec9.js → vennDiagram-T6HMQDX7-BjWQrcS4.js} +1 -1
  78. package/dist/web/assets/{wardley-OPB4EBWU-DLOnGzPl.js → wardley-OPB4EBWU-HV6ftDhi.js} +1 -1
  79. package/dist/web/assets/{wardleyDiagram-T6FBY63Y-BmzhEoo_.js → wardleyDiagram-T6FBY63Y-DHLZ0oPi.js} +1 -1
  80. package/dist/web/assets/{xychartDiagram-ELKLHX3M-CcCGC0u-.js → xychartDiagram-ELKLHX3M-CEJ_HkG9.js} +1 -1
  81. package/dist/web/index.html +2 -2
  82. package/package.json +1 -1
  83. package/dist/web/assets/architecture-TIHT7OUA-P_K7H_mW.js +0 -1
  84. package/dist/web/assets/channel-wXu0iczQ.js +0 -1
  85. package/dist/web/assets/classDiagram-JCYQIIEL-DOHE4q2M.js +0 -1
  86. package/dist/web/assets/classDiagram-v2-OCEON4UE-DOHE4q2M.js +0 -1
  87. package/dist/web/assets/eventmodeling-45OFAUF4-C344zcDl.js +0 -1
  88. package/dist/web/assets/flowDiagram-UKHOOZJN-BAHsb6fm.js +0 -1
  89. package/dist/web/assets/index-BiPhui1B.js +0 -384
  90. package/dist/web/assets/index-CHlqmhif.css +0 -1
  91. package/dist/web/assets/railroad-abnf-AHOZXSZD-D7Iqnp88.js +0 -1
  92. package/dist/web/assets/railroad-ebnf-EBAXGLYW-Dp2g2TtT.js +0 -1
  93. package/dist/web/assets/railroad-peg-LSFZ7HO6-DTqKNJKF.js +0 -1
  94. package/dist/web/assets/stateDiagram-v2-UEYNNEHI-CEn2YfQh.js +0 -1
  95. package/dist/web/assets/swimlanesDiagram-ULZ7WXOC-CX2pXGLK.js +0 -8
package/dist/cli.mjs CHANGED
@@ -7,6 +7,7 @@ var __export = (target, all4) => {
7
7
 
8
8
  // src/cli/main.ts
9
9
  import { fork } from "node:child_process";
10
+ import { randomUUID as randomUUID6 } from "node:crypto";
10
11
  import { existsSync as existsSync6 } from "node:fs";
11
12
  import path10 from "node:path";
12
13
  import { fileURLToPath as fileURLToPath5, pathToFileURL } from "node:url";
@@ -19093,6 +19094,11 @@ var RvwDatabase = class {
19093
19094
  listPullRequests() {
19094
19095
  return this.database.prepare("SELECT * FROM pull_requests ORDER BY updated_at DESC").all().map(mapPullRequest);
19095
19096
  }
19097
+ listPullRequestsNeedingStatusRefresh() {
19098
+ return this.database.prepare(
19099
+ "SELECT * FROM pull_requests WHERE github_state = 'OPEN' OR github_state IS NULL ORDER BY updated_at DESC"
19100
+ ).all().map(mapPullRequest);
19101
+ }
19096
19102
  listPullRequestSummaries(offset, limit, hideClosedOrMerged = true) {
19097
19103
  const hideClosedOrMergedValue = hideClosedOrMerged ? 1 : 0;
19098
19104
  const rows = this.database.prepare(
@@ -19165,6 +19171,25 @@ var RvwDatabase = class {
19165
19171
  total: numberValue(totalRow, "total")
19166
19172
  };
19167
19173
  }
19174
+ updatePullRequestGitHubStatuses(updates) {
19175
+ if (updates.length === 0) return;
19176
+ this.immediateTransaction(() => {
19177
+ const statement = this.database.prepare(
19178
+ "UPDATE pull_requests SET github_state = ?, github_is_draft = ? WHERE id = ?"
19179
+ );
19180
+ for (const update of updates) {
19181
+ const result = statement.run(update.state, update.isDraft ? 1 : 0, update.pullRequestId);
19182
+ if (Number(result.changes) !== 1) {
19183
+ throw new RvwError(
19184
+ "PR_NOT_FOUND",
19185
+ `Pull Request\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: ${update.pullRequestId}`,
19186
+ { status: 404 }
19187
+ );
19188
+ }
19189
+ }
19190
+ this.incrementChangeSequence();
19191
+ });
19192
+ }
19168
19193
  updateRepositoryLocation(id, repository) {
19169
19194
  this.immediateTransaction(() => {
19170
19195
  const result = this.database.prepare(
@@ -19870,9 +19895,11 @@ import path5 from "node:path";
19870
19895
  import { TextDecoder as TextDecoder2 } from "node:util";
19871
19896
 
19872
19897
  // src/shared/constants.ts
19873
- var APP_VERSION = "0.3.0";
19898
+ var APP_VERSION = "0.3.1";
19874
19899
  var PROTOCOL_VERSION = 4;
19875
19900
  var VIEWER_ID_HEADER = "x-rvw-viewer-id";
19901
+ var VIEWER_OPEN_LEASE_HEADER = "x-rvw-viewer-open-lease";
19902
+ var VIEWER_OPEN_LEASE_QUERY = "viewerLease";
19876
19903
  var GIT_OBJECT_ID_PATTERN = /^[0-9a-f]{40,64}$/i;
19877
19904
  var MAX_TEXT_DOCUMENT_BYTES = 1024 * 1024;
19878
19905
  var MAX_MARKDOWN_ASSET_BYTES = 5 * 1024 * 1024;
@@ -20643,6 +20670,10 @@ var ghPullRequestSchema = external_exports.object({
20643
20670
  headRefOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN),
20644
20671
  createdAt: external_exports.string()
20645
20672
  });
20673
+ var ghPullRequestStatusSchema = external_exports.object({
20674
+ state: external_exports.enum(["OPEN", "CLOSED", "MERGED"]),
20675
+ isDraft: external_exports.boolean()
20676
+ });
20646
20677
  function parsePullRequestUrl(url2) {
20647
20678
  const match2 = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)(?:\/.*)?$/.exec(url2);
20648
20679
  if (!match2?.[1] || !match2[2] || !match2[3]) {
@@ -20663,7 +20694,7 @@ var GitHubClient = class {
20663
20694
  return { version: version2.split("\n")[0] ?? version2, authenticated: auth.exitCode === 0 };
20664
20695
  }
20665
20696
  async assertAuthenticated() {
20666
- const status = await runProcess("gh", ["auth", "status", "--hostname", "github.com"], {
20697
+ const status = await this.processRunner("gh", ["auth", "status", "--hostname", "github.com"], {
20667
20698
  allowExitCodes: [1]
20668
20699
  });
20669
20700
  if (status.exitCode !== 0) {
@@ -20672,6 +20703,77 @@ var GitHubClient = class {
20672
20703
  });
20673
20704
  }
20674
20705
  }
20706
+ async getPullRequestStatus(reference) {
20707
+ let output;
20708
+ try {
20709
+ const result = await this.processRunner(
20710
+ "gh",
20711
+ ["pr", "view", reference, "--json", "state,isDraft"],
20712
+ { timeoutMs: 6e4 }
20713
+ );
20714
+ output = result.stdout.toString("utf8").trimEnd();
20715
+ } catch (error51) {
20716
+ if (error51 instanceof RvwError && error51.code === "PROCESS_FAILED") {
20717
+ throw new RvwError("GITHUB_ERROR", "Pull Request\u72B6\u614B\u3092GitHub\u304B\u3089\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002", {
20718
+ cause: error51,
20719
+ details: error51.details,
20720
+ suggestions: ["PR URL\u3068gh\u8A8D\u8A3C\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002"]
20721
+ });
20722
+ }
20723
+ throw error51;
20724
+ }
20725
+ let decoded;
20726
+ try {
20727
+ decoded = JSON.parse(output);
20728
+ } catch (error51) {
20729
+ throw new RvwError("GITHUB_ERROR", "GitHub CLI\u306EPull Request\u72B6\u614B\u5FDC\u7B54\u304C\u4E0D\u6B63\u3067\u3059\u3002", {
20730
+ cause: error51
20731
+ });
20732
+ }
20733
+ const parsed = ghPullRequestStatusSchema.safeParse(decoded);
20734
+ if (!parsed.success) {
20735
+ throw new RvwError("GITHUB_ERROR", "GitHub CLI\u306EPull Request\u72B6\u614B\u5FDC\u7B54\u304C\u4E0D\u6B63\u3067\u3059\u3002", {
20736
+ details: parsed.error.flatten()
20737
+ });
20738
+ }
20739
+ return parsed.data;
20740
+ }
20741
+ async getPullRequestStatuses(references) {
20742
+ if (references.length === 0) return [];
20743
+ await this.assertAuthenticated();
20744
+ const outcomes = Array.from(
20745
+ { length: references.length },
20746
+ () => void 0
20747
+ );
20748
+ let nextIndex = 0;
20749
+ const workerCount = Math.min(4, references.length);
20750
+ await Promise.all(
20751
+ Array.from({ length: workerCount }, async () => {
20752
+ while (nextIndex < references.length) {
20753
+ const index2 = nextIndex;
20754
+ nextIndex += 1;
20755
+ const reference = references[index2];
20756
+ if (!reference) continue;
20757
+ try {
20758
+ outcomes[index2] = {
20759
+ status: "fulfilled",
20760
+ value: await this.getPullRequestStatus(reference)
20761
+ };
20762
+ } catch (error51) {
20763
+ outcomes[index2] = { status: "rejected", error: error51 };
20764
+ }
20765
+ }
20766
+ })
20767
+ );
20768
+ return outcomes.map((outcome) => {
20769
+ if (!outcome) {
20770
+ throw new RvwError("INTERNAL_ERROR", "Pull Request\u72B6\u614B\u306E\u4E00\u62EC\u53D6\u5F97\u7D50\u679C\u304C\u4E0D\u8DB3\u3057\u3066\u3044\u307E\u3059\u3002", {
20771
+ status: 500
20772
+ });
20773
+ }
20774
+ return outcome;
20775
+ });
20776
+ }
20675
20777
  async getPullRequest(reference, cwd, options = {}) {
20676
20778
  await this.assertAuthenticated();
20677
20779
  const fields = [
@@ -41282,6 +41384,42 @@ var RvwService = class {
41282
41384
  }
41283
41385
  };
41284
41386
  }
41387
+ async refreshPullRequestStatuses() {
41388
+ const pullRequests = this.database.listPullRequestsNeedingStatusRefresh();
41389
+ if (pullRequests.length === 0) {
41390
+ return { attempted: 0, updated: 0, failures: [] };
41391
+ }
41392
+ const outcomes = await this.github.getPullRequestStatuses(
41393
+ pullRequests.map((pullRequest) => pullRequest.url)
41394
+ );
41395
+ if (outcomes.length !== pullRequests.length) {
41396
+ throw new RvwError("GITHUB_ERROR", "Pull Request\u72B6\u614B\u306E\u4E00\u62EC\u53D6\u5F97\u4EF6\u6570\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002", {
41397
+ status: 502
41398
+ });
41399
+ }
41400
+ const successful = outcomes.flatMap((outcome, index2) => {
41401
+ const pullRequest = pullRequests[index2];
41402
+ return outcome.status === "fulfilled" && pullRequest ? [{ pullRequestId: pullRequest.id, ...outcome.value }] : [];
41403
+ });
41404
+ this.database.updatePullRequestGitHubStatuses(successful);
41405
+ const failures = outcomes.flatMap((outcome, index2) => {
41406
+ const pullRequest = pullRequests[index2];
41407
+ return outcome.status === "rejected" && pullRequest ? [
41408
+ {
41409
+ pullRequestId: pullRequest.id,
41410
+ owner: pullRequest.owner,
41411
+ repository: pullRequest.repository,
41412
+ number: pullRequest.number,
41413
+ error: asRvwError(outcome.error).toJSON()
41414
+ }
41415
+ ] : [];
41416
+ });
41417
+ return {
41418
+ attempted: pullRequests.length,
41419
+ updated: successful.length,
41420
+ failures
41421
+ };
41422
+ }
41285
41423
  resolveStoredPullRequest(reference) {
41286
41424
  if (/^https:\/\/github\.com\//.test(reference)) {
41287
41425
  const parsed = parsePullRequestUrl(reference);
@@ -42639,6 +42777,9 @@ var SkillInstaller = class {
42639
42777
  }
42640
42778
  };
42641
42779
 
42780
+ // src/server/start-server.ts
42781
+ import { randomUUID as randomUUID4 } from "node:crypto";
42782
+
42642
42783
  // node_modules/.pnpm/@hono+node-server@2.1.0_hono@4.13.1/node_modules/@hono/node-server/dist/constants-BLSFu_RU.mjs
42643
42784
  var X_ALREADY_SENT = "x-hono-already-sent";
42644
42785
 
@@ -46532,7 +46673,11 @@ function createApp(service, options) {
46532
46673
  app.get("/api/meta/change-sequence", (context) => {
46533
46674
  const rawViewerId = context.req.header(VIEWER_ID_HEADER);
46534
46675
  if (rawViewerId !== void 0) {
46535
- options.viewerLifecycle?.heartbeat(viewerIdSchema.parse(rawViewerId));
46676
+ const rawViewerLease = context.req.header(VIEWER_OPEN_LEASE_HEADER);
46677
+ options.viewerLifecycle?.heartbeat(
46678
+ viewerIdSchema.parse(rawViewerId),
46679
+ rawViewerLease === void 0 ? void 0 : viewerIdSchema.parse(rawViewerLease)
46680
+ );
46536
46681
  }
46537
46682
  return context.json({ ok: true, changeSequence: service.database.getChangeSequence() });
46538
46683
  });
@@ -46560,6 +46705,10 @@ function createApp(service, options) {
46560
46705
  });
46561
46706
  return context.json({ ok: true, ...service.listPullRequests(query) });
46562
46707
  });
46708
+ app.post(
46709
+ "/api/pull-requests/refresh-statuses",
46710
+ async (context) => context.json({ ok: true, ...await service.refreshPullRequestStatuses() })
46711
+ );
46563
46712
  app.get(
46564
46713
  "/api/pull-requests/:id",
46565
46714
  async (context) => context.json({ ok: true, ...await service.getPullRequestView(context.req.param("id")) })
@@ -46837,14 +46986,17 @@ var ViewerLifecycle = class {
46837
46986
  constructor(options) {
46838
46987
  this.options = options;
46839
46988
  this.leaseTimeoutMs = options.leaseTimeoutMs ?? DEFAULT_VIEWER_LEASE_TIMEOUT_MS;
46989
+ this.startupTimeoutMs = options.startupTimeoutMs ?? DEFAULT_VIEWER_STARTUP_TIMEOUT_MS;
46840
46990
  this.closeGraceMs = options.closeGraceMs ?? DEFAULT_VIEWER_CLOSE_GRACE_MS;
46841
46991
  this.timerLatenessToleranceMs = options.timerLatenessToleranceMs ?? DEFAULT_TIMER_LATENESS_TOLERANCE_MS;
46842
46992
  }
46843
46993
  options;
46844
46994
  viewers = /* @__PURE__ */ new Map();
46995
+ pendingViewers = /* @__PURE__ */ new Map();
46845
46996
  // A poll already in flight can arrive after its pagehide release. Keep that document closed.
46846
46997
  releasedViewers = /* @__PURE__ */ new Set();
46847
46998
  leaseTimeoutMs;
46999
+ startupTimeoutMs;
46848
47000
  closeGraceMs;
46849
47001
  timerLatenessToleranceMs;
46850
47002
  timer = null;
@@ -46853,35 +47005,72 @@ var ViewerLifecycle = class {
46853
47005
  get activeViewerCount() {
46854
47006
  return this.viewers.size;
46855
47007
  }
46856
- heartbeat(viewerId) {
47008
+ get pendingViewerCount() {
47009
+ return this.pendingViewers.size;
47010
+ }
47011
+ reserveViewer(leaseId) {
47012
+ if (this.stopped) return false;
47013
+ this.pendingViewers.set(leaseId, { phase: "opening" });
47014
+ this.scheduleActivityCheck();
47015
+ return true;
47016
+ }
47017
+ armViewerReservation(leaseId) {
47018
+ if (this.stopped || !this.pendingViewers.has(leaseId)) return false;
47019
+ this.pendingViewers.set(leaseId, {
47020
+ phase: "startup",
47021
+ deadline: Date.now() + this.startupTimeoutMs,
47022
+ timeoutMs: this.startupTimeoutMs
47023
+ });
47024
+ this.scheduleActivityCheck();
47025
+ return true;
47026
+ }
47027
+ cancelViewerReservation(leaseId) {
47028
+ if (this.stopped || !this.pendingViewers.delete(leaseId)) return;
47029
+ this.scheduleNext();
47030
+ }
47031
+ heartbeat(viewerId, pendingLeaseId) {
46857
47032
  if (this.stopped || this.releasedViewers.has(viewerId)) return;
47033
+ if (pendingLeaseId !== void 0) this.pendingViewers.delete(pendingLeaseId);
46858
47034
  if (!this.viewerHasConnected) {
46859
47035
  this.viewerHasConnected = true;
46860
47036
  this.options.onFirstViewerConnected?.();
46861
47037
  }
46862
47038
  this.viewers.set(viewerId, Date.now());
46863
- this.scheduleLeaseCheck();
47039
+ this.scheduleActivityCheck();
46864
47040
  }
46865
47041
  release(viewerId) {
46866
47042
  if (this.stopped) return;
46867
47043
  this.releasedViewers.add(viewerId);
46868
47044
  if (!this.viewers.delete(viewerId)) return;
46869
- if (this.viewers.size === 0) this.scheduleEmptyShutdown();
46870
- else this.scheduleLeaseCheck();
47045
+ this.scheduleNext();
46871
47046
  }
46872
47047
  close() {
46873
47048
  this.stopped = true;
46874
47049
  this.clearTimer();
46875
47050
  this.viewers.clear();
47051
+ this.pendingViewers.clear();
46876
47052
  this.releasedViewers.clear();
46877
47053
  }
46878
- scheduleLeaseCheck() {
46879
- if (this.stopped || this.viewers.size === 0) return;
46880
- const earliestHeartbeat = Math.min(...this.viewers.values());
46881
- this.schedule("lease", earliestHeartbeat + this.leaseTimeoutMs);
47054
+ scheduleNext() {
47055
+ if (this.viewers.size > 0 || this.pendingViewers.size > 0) this.scheduleActivityCheck();
47056
+ else this.scheduleEmptyShutdown();
47057
+ }
47058
+ scheduleActivityCheck() {
47059
+ if (this.stopped) return;
47060
+ const deadlines = [
47061
+ ...Array.from(this.viewers.values(), (heartbeat) => heartbeat + this.leaseTimeoutMs),
47062
+ ...Array.from(this.pendingViewers.values()).filter(
47063
+ (pending) => pending.phase === "startup"
47064
+ ).map((pending) => pending.deadline)
47065
+ ];
47066
+ if (deadlines.length === 0) {
47067
+ this.clearTimer();
47068
+ return;
47069
+ }
47070
+ this.schedule("activity", Math.min(...deadlines));
46882
47071
  }
46883
47072
  scheduleEmptyShutdown() {
46884
- if (this.stopped || this.viewers.size > 0) return;
47073
+ if (this.stopped || this.viewers.size > 0 || this.pendingViewers.size > 0) return;
46885
47074
  this.schedule("empty", Date.now() + this.closeGraceMs);
46886
47075
  }
46887
47076
  schedule(kind, deadline) {
@@ -46895,23 +47084,33 @@ var ViewerLifecycle = class {
46895
47084
  const now = Date.now();
46896
47085
  if (now - deadline > this.timerLatenessToleranceMs) {
46897
47086
  for (const viewerId of this.viewers.keys()) this.viewers.set(viewerId, now);
46898
- if (this.viewers.size === 0) this.scheduleEmptyShutdown();
46899
- else this.scheduleLeaseCheck();
47087
+ for (const [leaseId, pending] of this.pendingViewers) {
47088
+ if (pending.phase !== "startup") continue;
47089
+ this.pendingViewers.set(leaseId, {
47090
+ phase: "startup",
47091
+ deadline: now + pending.timeoutMs,
47092
+ timeoutMs: pending.timeoutMs
47093
+ });
47094
+ }
47095
+ this.scheduleNext();
46900
47096
  return;
46901
47097
  }
46902
- if (kind === "lease") {
47098
+ if (kind === "activity") {
46903
47099
  for (const [viewerId, lastHeartbeat] of this.viewers) {
46904
47100
  if (now - lastHeartbeat >= this.leaseTimeoutMs) this.viewers.delete(viewerId);
46905
47101
  }
46906
- if (this.viewers.size > 0) this.scheduleLeaseCheck();
46907
- else this.scheduleEmptyShutdown();
47102
+ for (const [leaseId, pending] of this.pendingViewers) {
47103
+ if (pending.phase !== "startup") continue;
47104
+ if (now >= pending.deadline) this.pendingViewers.delete(leaseId);
47105
+ }
47106
+ this.scheduleNext();
46908
47107
  return;
46909
47108
  }
46910
- if (this.viewers.size === 0) {
47109
+ if (this.viewers.size === 0 && this.pendingViewers.size === 0) {
46911
47110
  this.stopped = true;
46912
47111
  this.options.onAllViewersClosed();
46913
47112
  } else {
46914
- this.scheduleLeaseCheck();
47113
+ this.scheduleActivityCheck();
46915
47114
  }
46916
47115
  }
46917
47116
  clearTimer() {
@@ -46921,6 +47120,7 @@ var ViewerLifecycle = class {
46921
47120
  };
46922
47121
 
46923
47122
  // src/server/start-server.ts
47123
+ var RUNTIME_STOPPING_REASON = "runtime-stopping";
46924
47124
  async function startServer(service, options = {}) {
46925
47125
  const host = "127.0.0.1";
46926
47126
  const security = { expectedHost: null, expectedOrigin: null };
@@ -46960,6 +47160,33 @@ async function startServer(service, options = {}) {
46960
47160
  origin,
46961
47161
  firstViewerConnected,
46962
47162
  allViewersClosed,
47163
+ reserveViewer: () => {
47164
+ if (!viewerLifecycle) return null;
47165
+ const leaseId = randomUUID4();
47166
+ if (!viewerLifecycle.reserveViewer(leaseId)) {
47167
+ throw new RvwError(
47168
+ "PROCESS_FAILED",
47169
+ "rvw runtime\u306F\u505C\u6B62\u51E6\u7406\u4E2D\u306E\u305F\u3081viewer\u3092\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3002",
47170
+ {
47171
+ details: { reason: RUNTIME_STOPPING_REASON },
47172
+ suggestions: ["rvw open\u3092\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"]
47173
+ }
47174
+ );
47175
+ }
47176
+ return leaseId;
47177
+ },
47178
+ armViewerReservation: (leaseId) => {
47179
+ if (!viewerLifecycle || viewerLifecycle.armViewerReservation(leaseId)) return;
47180
+ throw new RvwError(
47181
+ "PROCESS_FAILED",
47182
+ "rvw runtime\u306F\u505C\u6B62\u51E6\u7406\u4E2D\u306E\u305F\u3081viewer\u3092\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3002",
47183
+ {
47184
+ details: { reason: RUNTIME_STOPPING_REASON },
47185
+ suggestions: ["rvw open\u3092\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"]
47186
+ }
47187
+ );
47188
+ },
47189
+ cancelViewerReservation: (leaseId) => viewerLifecycle?.cancelViewerReservation(leaseId),
46963
47190
  close: () => closePromise ??= (async () => {
46964
47191
  viewerLifecycle?.close();
46965
47192
  await new Promise((closeResolve, closeReject) => {
@@ -46974,7 +47201,7 @@ async function startServer(service, options = {}) {
46974
47201
  }
46975
47202
 
46976
47203
  // src/server/agent-socket.ts
46977
- import { createHash as createHash5, randomUUID as randomUUID4 } from "node:crypto";
47204
+ import { createHash as createHash5, randomUUID as randomUUID5 } from "node:crypto";
46978
47205
  import {
46979
47206
  chmodSync as chmodSync2,
46980
47207
  existsSync as existsSync5,
@@ -46990,7 +47217,8 @@ import os4 from "node:os";
46990
47217
  import path9 from "node:path";
46991
47218
  var MAX_CLI_STDIN_BYTES = 40 * 1024 * 1024;
46992
47219
  var MAX_AGENT_MESSAGE_BYTES = MAX_CLI_STDIN_BYTES + 64 * 1024;
46993
- var AGENT_SOCKET_PROTOCOL_VERSION = 2;
47220
+ var AGENT_SOCKET_PROTOCOL_VERSION = 4;
47221
+ var RUNTIME_VIEWER_OPEN_OPERATION = "viewer.open";
46994
47222
  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";
46995
47223
  var DEFAULT_CONNECT_TIMEOUT_MS = 2e3;
46996
47224
  var DEFAULT_OPERATION_TIMEOUT_MS = 18e4;
@@ -47003,6 +47231,19 @@ var agentRequestEnvelopeSchema = external_exports.object({
47003
47231
  input: external_exports.unknown(),
47004
47232
  expectedDatabasePath: external_exports.string().min(1).optional()
47005
47233
  }).strict();
47234
+ var runtimeViewerOpenInputSchema = external_exports.object({
47235
+ reference: external_exports.string().min(1).optional(),
47236
+ cwd: external_exports.string().min(1),
47237
+ requestedPort: external_exports.number().int().min(0).max(65535)
47238
+ }).strict();
47239
+ var runtimeViewerOpenResultSchema = external_exports.object({
47240
+ url: external_exports.string().url(),
47241
+ origin: external_exports.string().url(),
47242
+ port: external_exports.number().int().min(1).max(65535),
47243
+ pullRequestId: external_exports.string().min(1),
47244
+ ownerPid: external_exports.number().int().positive(),
47245
+ viewerLeaseId: external_exports.uuid().optional()
47246
+ }).strict();
47006
47247
  function explicitAgentSocketPath() {
47007
47248
  const configuredPath = process.env.RVW_AGENT_SOCKET_PATH;
47008
47249
  if (configuredPath === void 0) return null;
@@ -47058,7 +47299,10 @@ function parseOperationInput(operation, value) {
47058
47299
  if (!parsed.success) throw invalidSocketInput(parsed.error);
47059
47300
  return parsed.data;
47060
47301
  }
47061
- async function dispatchAgentSocketRequest(service, rawRequest) {
47302
+ function resolveDatabaseIdentity(databaseFilePath) {
47303
+ return databaseFilePath === ":memory:" ? databaseFilePath : path9.resolve(databaseFilePath);
47304
+ }
47305
+ function validateAgentRequest(rawRequest, databaseFilePath) {
47062
47306
  const request = parseRequest(rawRequest);
47063
47307
  if (request.protocolVersion !== AGENT_SOCKET_PROTOCOL_VERSION) {
47064
47308
  throw new RvwError("STALE_PROTOCOL", "Agent socket protocol version\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002", {
@@ -47069,23 +47313,30 @@ async function dispatchAgentSocketRequest(service, rawRequest) {
47069
47313
  suggestions: [AGENT_SOCKET_RESTART_SUGGESTION]
47070
47314
  });
47071
47315
  }
47072
- if (request.expectedDatabasePath !== void 0 && path9.resolve(request.expectedDatabasePath) !== path9.resolve(service.database.filePath)) {
47316
+ if (request.expectedDatabasePath !== void 0 && databaseFilePath !== void 0 && resolveDatabaseIdentity(request.expectedDatabasePath) !== resolveDatabaseIdentity(databaseFilePath)) {
47073
47317
  throw new RvwError("DATABASE_ERROR", "Agent socket\u304C\u5225\u306Edatabase\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002", {
47074
47318
  details: {
47075
47319
  agentSocketDatabaseMismatch: true,
47076
- expectedDatabasePath: path9.resolve(request.expectedDatabasePath),
47077
- actualDatabasePath: path9.resolve(service.database.filePath)
47320
+ expectedDatabasePath: resolveDatabaseIdentity(request.expectedDatabasePath),
47321
+ actualDatabasePath: resolveDatabaseIdentity(databaseFilePath)
47078
47322
  }
47079
47323
  });
47080
47324
  }
47325
+ return request;
47326
+ }
47327
+ function pingResult(databaseFilePath) {
47328
+ return {
47329
+ protocolVersion: AGENT_SOCKET_PROTOCOL_VERSION,
47330
+ databasePath: resolveDatabaseIdentity(databaseFilePath),
47331
+ ownerPid: process.pid
47332
+ };
47333
+ }
47334
+ async function dispatchAgentSocketRequest(service, rawRequest) {
47335
+ const request = validateAgentRequest(rawRequest, service.database?.filePath);
47081
47336
  if (request.operation === "ping") {
47082
47337
  const ping = external_exports.object({}).strict().safeParse(request.input);
47083
47338
  if (!ping.success) throw invalidSocketInput(ping.error);
47084
- return {
47085
- protocolVersion: AGENT_SOCKET_PROTOCOL_VERSION,
47086
- databasePath: path9.resolve(service.database.filePath),
47087
- ownerPid: process.pid
47088
- };
47339
+ return pingResult(service.database.filePath);
47089
47340
  }
47090
47341
  if (!Object.hasOwn(agentCommandInputSchemas, request.operation)) {
47091
47342
  throw new RvwError("INVALID_INPUT", `\u672A\u5BFE\u5FDC\u306EAgent socket operation\u3067\u3059: ${request.operation}`);
@@ -47390,6 +47641,38 @@ async function tryAgentSocketRequest(operation, input, options = {}) {
47390
47641
  });
47391
47642
  });
47392
47643
  }
47644
+ async function tryRuntimeViewerOpen(input, databaseFilePath = databasePathConfiguration().filePath, options = {}) {
47645
+ const parsedInput = runtimeViewerOpenInputSchema.safeParse(input);
47646
+ if (!parsedInput.success) throw invalidSocketInput(parsedInput.error);
47647
+ const response = await tryAgentSocketRequest(
47648
+ RUNTIME_VIEWER_OPEN_OPERATION,
47649
+ parsedInput.data,
47650
+ {
47651
+ expectedDatabasePath: databaseFilePath,
47652
+ requireSocket: false,
47653
+ ...options
47654
+ }
47655
+ );
47656
+ if (!response.available) return response;
47657
+ const parsedResult = runtimeViewerOpenResultSchema.safeParse(response.result);
47658
+ if (!parsedResult.success) {
47659
+ throw new RvwError("PROCESS_FAILED", "\u8D77\u52D5\u4E2D\u306Ervw runtime\u304B\u3089\u4E0D\u6B63\u306A\u5FDC\u7B54\u3092\u53D7\u4FE1\u3057\u307E\u3057\u305F\u3002", {
47660
+ details: { issues: parsedResult.error.issues },
47661
+ suggestions: [AGENT_SOCKET_RESTART_SUGGESTION]
47662
+ });
47663
+ }
47664
+ return {
47665
+ available: true,
47666
+ result: {
47667
+ url: parsedResult.data.url,
47668
+ origin: parsedResult.data.origin,
47669
+ port: parsedResult.data.port,
47670
+ pullRequestId: parsedResult.data.pullRequestId,
47671
+ ownerPid: parsedResult.data.ownerPid,
47672
+ ...parsedResult.data.viewerLeaseId === void 0 ? {} : { viewerLeaseId: parsedResult.data.viewerLeaseId }
47673
+ }
47674
+ };
47675
+ }
47393
47676
  async function inspectAgentTransport(databaseFilePath = databasePathConfiguration().filePath) {
47394
47677
  const expectedDatabasePath = databaseFilePath === ":memory:" ? databaseFilePath : path9.resolve(databaseFilePath);
47395
47678
  const configuredSocketPath = explicitAgentSocketPath();
@@ -47492,7 +47775,7 @@ function socketOwnerPid(lockPath) {
47492
47775
  function tryAcquireSocketOwnerLock(socketPath) {
47493
47776
  const lockPath = `${socketPath}${OWNER_LOCK_SUFFIX}`;
47494
47777
  for (let attempt = 0; attempt < 2; attempt += 1) {
47495
- const stagingPath = `${lockPath}.${process.pid}.${randomUUID4()}.tmp`;
47778
+ const stagingPath = `${lockPath}.${process.pid}.${randomUUID5()}.tmp`;
47496
47779
  try {
47497
47780
  writeFileSync2(stagingPath, `${JSON.stringify({ pid: process.pid })}
47498
47781
  `, {
@@ -47536,7 +47819,7 @@ function releaseSocketOwnerLock(lock) {
47536
47819
  if (!lock) return;
47537
47820
  unlinkIfOwned(lock.path, lock.identity);
47538
47821
  }
47539
- function createAgentServer(service) {
47822
+ function createAgentServer(dispatch) {
47540
47823
  const server = net.createServer((socket) => {
47541
47824
  const chunks = [];
47542
47825
  let bytes = 0;
@@ -47561,7 +47844,7 @@ function createAgentServer(service) {
47561
47844
  const request = JSON.parse(Buffer.concat(chunks).toString("utf8"));
47562
47845
  response = {
47563
47846
  ok: true,
47564
- result: await dispatchAgentSocketRequest(service, parseRequest(request))
47847
+ result: await dispatch(parseRequest(request))
47565
47848
  };
47566
47849
  } catch (error51) {
47567
47850
  response = { ok: false, error: asRvwError(error51).toJSON() };
@@ -47589,8 +47872,8 @@ async function listen(server, socketPath) {
47589
47872
  server.listen(socketPath);
47590
47873
  });
47591
47874
  }
47592
- async function startAgentSocket(service, options = {}) {
47593
- const socketPath = agentSocketPath(service.database.filePath);
47875
+ async function startAgentSocketListener(databaseFilePath, dispatch, options) {
47876
+ const socketPath = agentSocketPath(databaseFilePath);
47594
47877
  ensurePrivateSocketDirectory(socketPath);
47595
47878
  const retryDelay = options.takeoverRetryMs ?? DEFAULT_TAKEOVER_RETRY_MS;
47596
47879
  let server = null;
@@ -47598,9 +47881,12 @@ async function startAgentSocket(service, options = {}) {
47598
47881
  let ownerLock = null;
47599
47882
  let retryTimer;
47600
47883
  let acquisition = null;
47884
+ let listenerDrain = null;
47885
+ let stopPromise = null;
47886
+ let releasePromise = null;
47601
47887
  let closed = false;
47602
47888
  const scheduleTakeover = () => {
47603
- if (closed || server || retryTimer) return;
47889
+ if (!options.retryOwnership || closed || server || retryTimer) return;
47604
47890
  retryTimer = setTimeout(() => {
47605
47891
  retryTimer = void 0;
47606
47892
  void acquire().catch(() => scheduleTakeover());
@@ -47629,7 +47915,7 @@ async function startAgentSocket(service, options = {}) {
47629
47915
  throw error51;
47630
47916
  }
47631
47917
  }
47632
- const candidate = createAgentServer(service);
47918
+ const candidate = createAgentServer(dispatch);
47633
47919
  try {
47634
47920
  await listen(candidate, socketPath);
47635
47921
  } catch (error51) {
@@ -47661,12 +47947,16 @@ async function startAgentSocket(service, options = {}) {
47661
47947
  ownerLock = candidateLock;
47662
47948
  candidate.on("error", () => {
47663
47949
  if (server !== candidate) return;
47664
- const failedIdentity = identity;
47665
- const failedOwnerLock = ownerLock;
47666
47950
  server = null;
47951
+ listenerDrain = new Promise((resolve) => candidate.close(() => resolve()));
47952
+ if (!options.retryOwnership) {
47953
+ return;
47954
+ }
47955
+ const failedIdentity = identity;
47667
47956
  identity = null;
47957
+ const failedOwnerLock = ownerLock;
47668
47958
  ownerLock = null;
47669
- candidate.close(() => {
47959
+ void listenerDrain.then(() => {
47670
47960
  unlinkIfOwned(socketPath, failedIdentity);
47671
47961
  releaseSocketOwnerLock(failedOwnerLock);
47672
47962
  scheduleTakeover();
@@ -47680,33 +47970,128 @@ async function startAgentSocket(service, options = {}) {
47680
47970
  }
47681
47971
  };
47682
47972
  await acquire();
47683
- return {
47684
- path: socketPath,
47685
- get owned() {
47686
- return server !== null;
47687
- },
47688
- close: async () => {
47973
+ const stopAccepting = async () => {
47974
+ await (stopPromise ??= (async () => {
47689
47975
  closed = true;
47690
47976
  if (retryTimer) clearTimeout(retryTimer);
47691
47977
  await acquisition;
47978
+ if (listenerDrain) await listenerDrain;
47692
47979
  const ownedServer = server;
47693
- const ownedIdentity = identity;
47694
- const ownedOwnerLock = ownerLock;
47695
47980
  server = null;
47696
- identity = null;
47697
- ownerLock = null;
47698
- if (!ownedServer) {
47699
- releaseSocketOwnerLock(ownedOwnerLock);
47700
- return;
47701
- }
47981
+ if (!ownedServer) return;
47982
+ listenerDrain = new Promise(
47983
+ (resolve, reject) => ownedServer.close((error51) => error51 ? reject(error51) : resolve())
47984
+ );
47985
+ await listenerDrain;
47986
+ })());
47987
+ };
47988
+ const releaseOwnership = async () => {
47989
+ await (releasePromise ??= (async () => {
47702
47990
  try {
47703
- await new Promise(
47704
- (resolve, reject) => ownedServer.close((error51) => error51 ? reject(error51) : resolve())
47705
- );
47991
+ await stopAccepting();
47706
47992
  } finally {
47707
- unlinkIfOwned(socketPath, ownedIdentity);
47708
- releaseSocketOwnerLock(ownedOwnerLock);
47993
+ const ownedIdentity = identity;
47994
+ const ownedOwnerLock = ownerLock;
47995
+ identity = null;
47996
+ ownerLock = null;
47997
+ try {
47998
+ unlinkIfOwned(socketPath, ownedIdentity);
47999
+ } finally {
48000
+ releaseSocketOwnerLock(ownedOwnerLock);
48001
+ }
48002
+ }
48003
+ })());
48004
+ };
48005
+ return {
48006
+ path: socketPath,
48007
+ get owned() {
48008
+ return ownerLock !== null;
48009
+ },
48010
+ stopAccepting,
48011
+ releaseOwnership,
48012
+ close: releaseOwnership
48013
+ };
48014
+ }
48015
+ async function startRuntimeAgentSocket(databaseFilePath) {
48016
+ let handler = null;
48017
+ let resolveHandler;
48018
+ let rejectHandler;
48019
+ const handlerPromise = new Promise((resolve, reject) => {
48020
+ resolveHandler = resolve;
48021
+ rejectHandler = reject;
48022
+ });
48023
+ void handlerPromise.catch(() => {
48024
+ });
48025
+ let accepting = true;
48026
+ const rejectUninitializedHandler = () => {
48027
+ if (handler) return;
48028
+ rejectHandler?.(new RvwError("PROCESS_FAILED", "rvw runtime\u304C\u521D\u671F\u5316\u3055\u308C\u308B\u524D\u306B\u505C\u6B62\u3057\u307E\u3057\u305F\u3002"));
48029
+ resolveHandler = void 0;
48030
+ rejectHandler = void 0;
48031
+ };
48032
+ const running = await startAgentSocketListener(
48033
+ databaseFilePath,
48034
+ async (rawRequest) => {
48035
+ const request = validateAgentRequest(rawRequest, databaseFilePath);
48036
+ if (request.operation === "ping") {
48037
+ const ping = external_exports.object({}).strict().safeParse(request.input);
48038
+ if (!ping.success) throw invalidSocketInput(ping.error);
48039
+ return pingResult(databaseFilePath);
48040
+ }
48041
+ if (request.operation === RUNTIME_VIEWER_OPEN_OPERATION) {
48042
+ const parsed = runtimeViewerOpenInputSchema.safeParse(request.input);
48043
+ if (!parsed.success) throw invalidSocketInput(parsed.error);
48044
+ return await (await handlerPromise).openViewer({
48045
+ ...parsed.data.reference === void 0 ? {} : { reference: parsed.data.reference },
48046
+ cwd: parsed.data.cwd,
48047
+ requestedPort: parsed.data.requestedPort
48048
+ });
48049
+ }
48050
+ return await dispatchAgentSocketRequest((await handlerPromise).service, request);
48051
+ },
48052
+ { retryOwnership: false }
48053
+ );
48054
+ return {
48055
+ path: running.path,
48056
+ get owned() {
48057
+ return running.owned;
48058
+ },
48059
+ setHandler(value) {
48060
+ if (!running.owned || !accepting) {
48061
+ throw new RvwError("PROCESS_FAILED", "\u6240\u6709\u3057\u3066\u3044\u306A\u3044runtime socket\u306F\u521D\u671F\u5316\u3067\u304D\u307E\u305B\u3093\u3002");
47709
48062
  }
48063
+ if (handler) {
48064
+ throw new RvwError("INTERNAL_ERROR", "runtime socket\u306F\u521D\u671F\u5316\u6E08\u307F\u3067\u3059\u3002", {
48065
+ status: 500
48066
+ });
48067
+ }
48068
+ if (resolveDatabaseIdentity(value.service.database.filePath) !== resolveDatabaseIdentity(databaseFilePath)) {
48069
+ throw new RvwError("DATABASE_ERROR", "runtime\u3068Agent socket\u306Edatabase\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002", {
48070
+ details: {
48071
+ socketDatabasePath: resolveDatabaseIdentity(databaseFilePath),
48072
+ runtimeDatabasePath: resolveDatabaseIdentity(value.service.database.filePath)
48073
+ }
48074
+ });
48075
+ }
48076
+ handler = value;
48077
+ resolveHandler?.(value);
48078
+ resolveHandler = void 0;
48079
+ rejectHandler = void 0;
48080
+ },
48081
+ stopAccepting: async () => {
48082
+ accepting = false;
48083
+ rejectUninitializedHandler();
48084
+ await running.stopAccepting();
48085
+ },
48086
+ releaseOwnership: async () => {
48087
+ accepting = false;
48088
+ rejectUninitializedHandler();
48089
+ await running.releaseOwnership();
48090
+ },
48091
+ close: async () => {
48092
+ accepting = false;
48093
+ rejectUninitializedHandler();
48094
+ await running.releaseOwnership();
47710
48095
  }
47711
48096
  };
47712
48097
  }
@@ -48067,6 +48452,9 @@ function formatCommentListOutput(result, state) {
48067
48452
  var MAX_STDIN_BYTES = MAX_CLI_STDIN_BYTES;
48068
48453
  var OPEN_WORKER_READY_TIMEOUT_MS = 12e4;
48069
48454
  var OPEN_WORKER_PARENT_TIMEOUT_PADDING_MS = 5e3;
48455
+ var RUNTIME_REUSE_RETRY_MS = 50;
48456
+ var RUNTIME_VIEWER_HEARTBEAT_INTERVAL_MS = 3e4;
48457
+ var RUNTIME_VIEWER_REQUEST_TIMEOUT_MS = 5e3;
48070
48458
  function writeJson(value) {
48071
48459
  process.stdout.write(`${JSON.stringify(value)}
48072
48460
  `);
@@ -48162,6 +48550,11 @@ function errorFromOpenWorker(error51) {
48162
48550
  ...error51.details === void 0 ? {} : { details: error51.details }
48163
48551
  });
48164
48552
  }
48553
+ function isRuntimeStoppingError(error51) {
48554
+ if (!(error51 instanceof RvwError) || error51.code !== "PROCESS_FAILED") return false;
48555
+ if (!error51.details || typeof error51.details !== "object") return false;
48556
+ return error51.details.reason === RUNTIME_STOPPING_REASON;
48557
+ }
48165
48558
  async function completeBackgroundOpen(child, launchBrowser, options = {}) {
48166
48559
  const readyTimeoutMs = options.readyTimeoutMs ?? OPEN_WORKER_READY_TIMEOUT_MS;
48167
48560
  const viewerTimeoutMs = options.viewerTimeoutMs ?? DEFAULT_VIEWER_STARTUP_TIMEOUT_MS + OPEN_WORKER_PARENT_TIMEOUT_PADDING_MS;
@@ -48285,11 +48678,31 @@ function forkOpenWorker(reference, port) {
48285
48678
  });
48286
48679
  }
48287
48680
  async function startBackgroundOpen(reference, port, dependencies = {}) {
48681
+ const input = {
48682
+ ...reference === void 0 ? {} : { reference },
48683
+ cwd: process.cwd(),
48684
+ requestedPort: port
48685
+ };
48686
+ const launchBrowser = dependencies.launchBrowser ?? (async (url2) => await open_default(url2));
48687
+ let existing = null;
48688
+ try {
48689
+ existing = await (dependencies.tryRuntimeOpen ?? tryRuntimeViewerOpen)(input);
48690
+ } catch (error51) {
48691
+ if (!isRuntimeStoppingError(error51)) throw error51;
48692
+ }
48693
+ if (existing?.available) {
48694
+ await launchBrowser(existing.result.url);
48695
+ return existing.result.url;
48696
+ }
48697
+ if (existing?.reason === "database-mismatch") {
48698
+ throw new RvwError(
48699
+ "AGENT_SOCKET_UNAVAILABLE",
48700
+ "\u8D77\u52D5\u4E2D\u306Ervw runtime\u304C\u5225\u306Edatabase\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002",
48701
+ { details: existing.details }
48702
+ );
48703
+ }
48288
48704
  const child = (dependencies.forkWorker ?? forkOpenWorker)(reference, port);
48289
- return await completeBackgroundOpen(
48290
- child,
48291
- dependencies.launchBrowser ?? (async (url2) => await open_default(url2))
48292
- );
48705
+ return await completeBackgroundOpen(child, launchBrowser);
48293
48706
  }
48294
48707
  async function sendOpenWorkerMessage(message) {
48295
48708
  if (!process.send || !process.connected) return false;
@@ -48321,17 +48734,208 @@ async function waitForInitialViewer(firstViewerConnected, timeoutMs = DEFAULT_VI
48321
48734
  void firstViewerConnected.then(() => finish("connected"));
48322
48735
  });
48323
48736
  }
48324
- async function runOpenServer(activeRuntime, reference, port, openAutomatically, useAgentSocket) {
48737
+ function runtimeViewerOpenInput(reference, cwd, requestedPort) {
48738
+ return {
48739
+ ...reference === void 0 ? {} : { reference },
48740
+ cwd,
48741
+ requestedPort
48742
+ };
48743
+ }
48744
+ function createRuntimeAgentSocketHandler(activeRuntime, running) {
48745
+ return {
48746
+ service: activeRuntime.service,
48747
+ openViewer: async (input) => {
48748
+ if (input.requestedPort !== 0 && input.requestedPort !== running.port) {
48749
+ throw new RvwError(
48750
+ "INVALID_INPUT",
48751
+ `\u540C\u3058database\u306Ervw runtime\u306Fport ${running.port} \u3067\u8D77\u52D5\u6E08\u307F\u3067\u3059\u3002`,
48752
+ {
48753
+ details: { activePort: running.port, requestedPort: input.requestedPort },
48754
+ suggestions: [
48755
+ "\u65E2\u5B58runtime\u3092\u505C\u6B62\u3057\u3066\u304B\u3089\u6307\u5B9Aport\u3067\u518D\u8D77\u52D5\u3059\u308B\u304B\u3001--port\u3092\u7701\u7565\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
48756
+ ]
48757
+ }
48758
+ );
48759
+ }
48760
+ const viewerLeaseId = running.reserveViewer();
48761
+ try {
48762
+ const opened = await activeRuntime.service.openPullRequest(input.reference, input.cwd);
48763
+ if (viewerLeaseId !== null) running.armViewerReservation(viewerLeaseId);
48764
+ const url2 = new URL(running.origin);
48765
+ url2.searchParams.set("pullRequestId", opened.pullRequest.id);
48766
+ if (viewerLeaseId !== null) url2.searchParams.set(VIEWER_OPEN_LEASE_QUERY, viewerLeaseId);
48767
+ return {
48768
+ url: url2.toString(),
48769
+ origin: running.origin,
48770
+ port: running.port,
48771
+ pullRequestId: opened.pullRequest.id,
48772
+ ownerPid: process.pid,
48773
+ ...viewerLeaseId === null ? {} : { viewerLeaseId }
48774
+ };
48775
+ } catch (error51) {
48776
+ if (viewerLeaseId !== null) running.cancelViewerReservation(viewerLeaseId);
48777
+ throw error51;
48778
+ }
48779
+ }
48780
+ };
48781
+ }
48782
+ async function holdRuntimeViewerLease(result, dependencies = {}) {
48783
+ const viewerLeaseId = result.viewerLeaseId;
48784
+ if (viewerLeaseId === void 0) return;
48785
+ const fetchRequest = dependencies.fetch ?? fetch;
48786
+ const viewerId = randomUUID6();
48787
+ const requestTimeoutMs = dependencies.requestTimeoutMs ?? RUNTIME_VIEWER_REQUEST_TIMEOUT_MS;
48788
+ const heartbeatUrl = new URL("/api/meta/change-sequence", result.origin);
48789
+ const releaseUrl = new URL("/api/meta/viewers/release", result.origin);
48790
+ const heartbeat = async () => {
48791
+ const response = await fetchRequest(heartbeatUrl, {
48792
+ signal: AbortSignal.timeout(requestTimeoutMs),
48793
+ headers: {
48794
+ [VIEWER_ID_HEADER]: viewerId,
48795
+ [VIEWER_OPEN_LEASE_HEADER]: viewerLeaseId
48796
+ }
48797
+ });
48798
+ if (!response.ok) {
48799
+ throw new RvwError("PROCESS_FAILED", "rvw runtime\u306Eviewer lease\u3092\u66F4\u65B0\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002", {
48800
+ details: { status: response.status, origin: result.origin }
48801
+ });
48802
+ }
48803
+ };
48804
+ const stopped = Promise.withResolvers();
48805
+ let heartbeatError;
48806
+ let heartbeatInFlight = false;
48807
+ const onSignal = () => stopped.resolve("signal");
48808
+ process.once("SIGINT", onSignal);
48809
+ process.once("SIGTERM", onSignal);
48810
+ let interval;
48811
+ let registered = false;
48812
+ try {
48813
+ await heartbeat();
48814
+ registered = true;
48815
+ interval = setInterval(() => {
48816
+ if (heartbeatInFlight) return;
48817
+ heartbeatInFlight = true;
48818
+ void heartbeat().catch((error51) => {
48819
+ heartbeatError = error51;
48820
+ stopped.resolve("heartbeat-failed");
48821
+ }).finally(() => {
48822
+ heartbeatInFlight = false;
48823
+ });
48824
+ }, dependencies.heartbeatIntervalMs ?? RUNTIME_VIEWER_HEARTBEAT_INTERVAL_MS);
48825
+ interval.unref();
48826
+ const reason = await stopped.promise;
48827
+ if (reason === "heartbeat-failed") throw heartbeatError;
48828
+ } finally {
48829
+ if (interval) clearInterval(interval);
48830
+ process.removeListener("SIGINT", onSignal);
48831
+ process.removeListener("SIGTERM", onSignal);
48832
+ if (registered) {
48833
+ await fetchRequest(releaseUrl, {
48834
+ method: "POST",
48835
+ signal: AbortSignal.timeout(requestTimeoutMs),
48836
+ headers: {
48837
+ origin: result.origin,
48838
+ "content-type": "application/json"
48839
+ },
48840
+ body: JSON.stringify({ viewerId })
48841
+ }).catch(() => void 0);
48842
+ }
48843
+ }
48844
+ }
48845
+ async function closeOwnedRuntime(agentSocket, running, activeRuntime) {
48846
+ try {
48847
+ await agentSocket?.stopAccepting();
48848
+ } finally {
48849
+ try {
48850
+ await running?.close();
48851
+ } finally {
48852
+ try {
48853
+ activeRuntime?.close();
48854
+ } finally {
48855
+ await agentSocket?.releaseOwnership();
48856
+ }
48857
+ }
48858
+ }
48859
+ }
48860
+ async function acquireRuntimeOrReuseExisting(input, databaseFilePath, timeoutMs = OPEN_WORKER_READY_TIMEOUT_MS, dependencies = {}) {
48861
+ const startSocket = dependencies.startSocket ?? startRuntimeAgentSocket;
48862
+ const tryRuntimeOpen = dependencies.tryRuntimeOpen ?? tryRuntimeViewerOpen;
48863
+ const wait = dependencies.wait ?? (async (milliseconds) => {
48864
+ await new Promise((resolve) => setTimeout(resolve, milliseconds));
48865
+ });
48866
+ const now = dependencies.now ?? Date.now;
48867
+ const deadline = now() + timeoutMs;
48868
+ do {
48869
+ const candidate = await startSocket(databaseFilePath);
48870
+ if (candidate.owned) return { kind: "owned", agentSocket: candidate };
48871
+ await candidate.close();
48872
+ let response = null;
48873
+ try {
48874
+ response = await tryRuntimeOpen(input, databaseFilePath);
48875
+ } catch (error51) {
48876
+ if (!isRuntimeStoppingError(error51)) throw error51;
48877
+ }
48878
+ if (response?.available) return { kind: "reused", result: response.result };
48879
+ if (response?.reason === "database-mismatch") {
48880
+ throw new RvwError(
48881
+ "AGENT_SOCKET_UNAVAILABLE",
48882
+ "\u8D77\u52D5\u4E2D\u306Ervw runtime\u304C\u5225\u306Edatabase\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002",
48883
+ { details: response.details }
48884
+ );
48885
+ }
48886
+ await wait(RUNTIME_REUSE_RETRY_MS);
48887
+ } while (now() < deadline);
48888
+ throw new RvwError("PROCESS_TIMEOUT", "\u8D77\u52D5\u4E2D\u306Ervw runtime\u3078\u306E\u63A5\u7D9A\u304C\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\u3057\u307E\u3057\u305F\u3002", {
48889
+ details: { timeoutMs }
48890
+ });
48891
+ }
48892
+ async function waitForWorkerParentDisconnect() {
48893
+ if (!process.connected) return;
48894
+ await new Promise((resolve) => process.once("disconnect", resolve));
48895
+ }
48896
+ async function runOpenServer(runtimeFactory, reference, port, openAutomatically, useAgentSocket, reuseExisting) {
48897
+ let activeRuntime;
48325
48898
  let running;
48326
48899
  let agentSocket;
48327
48900
  try {
48901
+ if (useAgentSocket) {
48902
+ const databaseFilePath = databasePathConfiguration().filePath;
48903
+ if (reuseExisting) {
48904
+ const startup = await acquireRuntimeOrReuseExisting(
48905
+ runtimeViewerOpenInput(reference, process.cwd(), port),
48906
+ databaseFilePath
48907
+ );
48908
+ if (startup.kind === "reused") {
48909
+ const result = startup.result;
48910
+ process.stdout.write(`rvw: ${result.url}
48911
+ `);
48912
+ if (!openAutomatically) await holdRuntimeViewerLease(result);
48913
+ return;
48914
+ }
48915
+ agentSocket = startup.agentSocket;
48916
+ } else {
48917
+ agentSocket = await startRuntimeAgentSocket(databaseFilePath);
48918
+ if (!agentSocket.owned) {
48919
+ throw new RvwError(
48920
+ "PROCESS_FAILED",
48921
+ "\u540C\u3058database\u306Ervw runtime\u304C\u65E2\u306B\u8D77\u52D5\u4E2D\u306E\u305F\u3081foreground server\u3092\u958B\u59CB\u3067\u304D\u307E\u305B\u3093\u3002",
48922
+ {
48923
+ suggestions: [
48924
+ "\u901A\u5E38\u306Ervw open\u3067\u65E2\u5B58runtime\u3092\u5229\u7528\u3059\u308B\u304B\u3001\u65E2\u5B58runtime\u3092\u505C\u6B62\u3057\u3066\u304B\u3089\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
48925
+ ]
48926
+ }
48927
+ );
48928
+ }
48929
+ }
48930
+ }
48931
+ activeRuntime = runtimeFactory();
48328
48932
  const opened = await activeRuntime.service.openPullRequest(reference, process.cwd());
48329
48933
  running = await startServer(activeRuntime.service, {
48330
48934
  port,
48331
48935
  staticDirectory: staticDirectory(),
48332
48936
  autoCloseWhenNoViewers: openAutomatically
48333
48937
  });
48334
- if (useAgentSocket) agentSocket = await startAgentSocket(activeRuntime.service);
48938
+ agentSocket?.setHandler(createRuntimeAgentSocketHandler(activeRuntime, running));
48335
48939
  const url2 = new URL(running.origin);
48336
48940
  url2.searchParams.set("pullRequestId", opened.pullRequest.id);
48337
48941
  process.stdout.write(`rvw: ${url2.toString()}
@@ -48342,31 +48946,38 @@ async function runOpenServer(activeRuntime, reference, port, openAutomatically,
48342
48946
  process.stdout.write("rvw: viewer\u3092\u9589\u3058\u305F\u305F\u3081server\u3092\u505C\u6B62\u3057\u307E\u3059\u3002\n");
48343
48947
  }
48344
48948
  } finally {
48345
- try {
48346
- await agentSocket?.close();
48347
- } finally {
48348
- try {
48349
- await running?.close();
48350
- } finally {
48351
- activeRuntime.close();
48352
- }
48353
- }
48949
+ await closeOwnedRuntime(agentSocket, running, activeRuntime);
48354
48950
  }
48355
48951
  }
48356
- async function runOpenWorker(activeRuntime, reference, port) {
48952
+ async function runOpenWorker(runtimeFactory, reference, port) {
48953
+ let activeRuntime;
48357
48954
  let running;
48358
48955
  let agentSocket;
48359
48956
  try {
48360
48957
  if (!process.send || !process.connected) {
48361
48958
  throw new RvwError("INVALID_INPUT", "\u5185\u90E8viewer worker\u306F\u89AACLI\u304B\u3089\u8D77\u52D5\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
48362
48959
  }
48960
+ const databaseFilePath = databasePathConfiguration().filePath;
48961
+ const startup = await acquireRuntimeOrReuseExisting(
48962
+ runtimeViewerOpenInput(reference, process.cwd(), port),
48963
+ databaseFilePath
48964
+ );
48965
+ if (startup.kind === "reused") {
48966
+ const result = startup.result;
48967
+ if (!await sendOpenWorkerMessage({ type: "ready", url: result.url })) return;
48968
+ if (!await sendOpenWorkerMessage({ type: "viewer-connected" })) return;
48969
+ await waitForWorkerParentDisconnect();
48970
+ return;
48971
+ }
48972
+ agentSocket = startup.agentSocket;
48973
+ activeRuntime = runtimeFactory();
48363
48974
  const opened = await activeRuntime.service.openPullRequest(reference, process.cwd());
48364
48975
  running = await startServer(activeRuntime.service, {
48365
48976
  port,
48366
48977
  staticDirectory: staticDirectory(),
48367
48978
  autoCloseWhenNoViewers: true
48368
48979
  });
48369
- agentSocket = await startAgentSocket(activeRuntime.service);
48980
+ agentSocket.setHandler(createRuntimeAgentSocketHandler(activeRuntime, running));
48370
48981
  const url2 = new URL(running.origin);
48371
48982
  url2.searchParams.set("pullRequestId", opened.pullRequest.id);
48372
48983
  if (!await sendOpenWorkerMessage({ type: "ready", url: url2.toString() })) return;
@@ -48386,15 +48997,7 @@ async function runOpenWorker(activeRuntime, reference, port) {
48386
48997
  await sendOpenWorkerMessage({ type: "viewer-connected" });
48387
48998
  await waitForServerShutdown(running.allViewersClosed);
48388
48999
  } finally {
48389
- try {
48390
- await agentSocket?.close();
48391
- } finally {
48392
- try {
48393
- await running?.close();
48394
- } finally {
48395
- activeRuntime.close();
48396
- }
48397
- }
49000
+ await closeOwnedRuntime(agentSocket, running, activeRuntime);
48398
49001
  }
48399
49002
  }
48400
49003
  var defaultRuntimeFactory = () => createRuntime();
@@ -48495,12 +49098,19 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
48495
49098
  `);
48496
49099
  return;
48497
49100
  }
48498
- await runOpenServer(getRuntime(), reference, options.port, options.open, useAgentSocket);
49101
+ await runOpenServer(
49102
+ getRuntime,
49103
+ reference,
49104
+ options.port,
49105
+ options.open,
49106
+ useAgentSocket,
49107
+ !options.foreground
49108
+ );
48499
49109
  }
48500
49110
  );
48501
49111
  program2.command("__open-worker", { hidden: true }).option("--reference <pull-request>").requiredOption("--port <port>", "listen port", parsePort).action(async (options) => {
48502
49112
  try {
48503
- await runOpenWorker(getRuntime(), options.reference, options.port);
49113
+ await runOpenWorker(getRuntime, options.reference, options.port);
48504
49114
  } catch (error51) {
48505
49115
  const rvwError = asRvwError(error51);
48506
49116
  const sent = await sendOpenWorkerMessage({
@@ -48861,8 +49471,12 @@ if (bundledCli || process.argv[1] && import.meta.url === pathToFileURL(process.a
48861
49471
  await runCli();
48862
49472
  }
48863
49473
  export {
49474
+ acquireRuntimeOrReuseExisting,
49475
+ closeOwnedRuntime,
48864
49476
  completeBackgroundOpen,
48865
49477
  createProgram,
49478
+ createRuntimeAgentSocketHandler,
49479
+ holdRuntimeViewerLease,
48866
49480
  runCli,
48867
49481
  startBackgroundOpen,
48868
49482
  waitForServerShutdown