@adanami/kaleido 0.1.0 → 0.2.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.
Files changed (107) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +9 -0
  3. package/dist/cli/index.js +409 -24
  4. package/dist/client/assets/{abnfDiagram-N423BO3Z-BNC_bOwN.js → abnfDiagram-N423BO3Z-BLtqS4V1.js} +1 -1
  5. package/dist/client/assets/{arc-BQjVBT7z.js → arc-DyLfH67M.js} +1 -1
  6. package/dist/client/assets/architecture-TIHT7OUA-B5Ma77Cd.js +1 -0
  7. package/dist/client/assets/{architectureDiagram-T3A2C74G-NbyTzj4B.js → architectureDiagram-T3A2C74G-tHSqReux.js} +1 -1
  8. package/dist/client/assets/{blockDiagram-VBNYF7ZC-D7RFrUDl.js → blockDiagram-VBNYF7ZC-qlFul3F2.js} +1 -1
  9. package/dist/client/assets/{c4Diagram-5PPSVZJV-CVtHbZ8m.js → c4Diagram-5PPSVZJV-8-iQf_3L.js} +1 -1
  10. package/dist/client/assets/channel-Cde_s6N9.js +1 -0
  11. package/dist/client/assets/{chunk-2GRJ4B5K-vymlEdvz.js → chunk-2GRJ4B5K-B6HO6-K5.js} +1 -1
  12. package/dist/client/assets/{chunk-4I5QYGJK-Dru7MVd5.js → chunk-4I5QYGJK-CbWygMHq.js} +1 -1
  13. package/dist/client/assets/{chunk-5RXB4S5H-_mW4jXZD.js → chunk-5RXB4S5H-qFn-JYXR.js} +1 -1
  14. package/dist/client/assets/{chunk-6Q2QTUOP-C-Jr6Q1u.js → chunk-6Q2QTUOP-CcE1vTzX.js} +1 -1
  15. package/dist/client/assets/{chunk-7Z6QIM7H-CH0etl6L.js → chunk-7Z6QIM7H-C08W_EwI.js} +1 -1
  16. package/dist/client/assets/{chunk-GF5L2VYU-l0ZYrFWn.js → chunk-GF5L2VYU-CHm7JrHM.js} +1 -1
  17. package/dist/client/assets/{chunk-I66GZJ75-CKcp5S17.js → chunk-I66GZJ75-DY6z-MCi.js} +1 -1
  18. package/dist/client/assets/{chunk-JQJVKLGR-BXKeK8Yn.js → chunk-JQJVKLGR-DKeiIUQ6.js} +1 -1
  19. package/dist/client/assets/{chunk-KBJHAD2P-DPP8q1jj.js → chunk-KBJHAD2P-CzT5-hAw.js} +1 -1
  20. package/dist/client/assets/{chunk-NSK5VX7P-CJvQSFjo.js → chunk-NSK5VX7P-ClHKnN2Z.js} +1 -1
  21. package/dist/client/assets/{chunk-QR6OTTB3-DAmoW-jk.js → chunk-QR6OTTB3-BOVrt91Y.js} +1 -1
  22. package/dist/client/assets/{chunk-RYQCIY6F-mEV_z1Vs.js → chunk-RYQCIY6F-DOPazF8k.js} +1 -1
  23. package/dist/client/assets/{chunk-UBXNYLIW-B9FQ3EVs.js → chunk-UBXNYLIW-CGh3W460.js} +1 -1
  24. package/dist/client/assets/{chunk-W5SLKNZC-B7q4L6_i.js → chunk-W5SLKNZC-8ST36NWH.js} +1 -1
  25. package/dist/client/assets/{chunk-WRU74C26-DwPGHVIY.js → chunk-WRU74C26-Dzc5jtNO.js} +1 -1
  26. package/dist/client/assets/{chunk-XXDRQBXY-B_1m3XyG.js → chunk-XXDRQBXY-Cu9anCqu.js} +1 -1
  27. package/dist/client/assets/classDiagram-JCYQIIEL-CRLogySI.js +1 -0
  28. package/dist/client/assets/classDiagram-v2-OCEON4UE-CRLogySI.js +1 -0
  29. package/dist/client/assets/{cose-bilkent-JH36ORCC-_wSiGHW9.js → cose-bilkent-JH36ORCC-DGh8pHuP.js} +1 -1
  30. package/dist/client/assets/{cynefin-VYW2F7L2-BSXkfF6B.js → cynefin-VYW2F7L2-BpvhYsbg.js} +1 -1
  31. package/dist/client/assets/{cynefinDiagram-MW4NZA55-DWqP9pCq.js → cynefinDiagram-MW4NZA55-43TbOIHI.js} +1 -1
  32. package/dist/client/assets/{dagre-VZM6K2ZE-D-6mKeP4.js → dagre-VZM6K2ZE-Cm58tyFt.js} +1 -1
  33. package/dist/client/assets/{diagram-7IWD3JNH-DwifWIOM.js → diagram-7IWD3JNH-vPJCjCki.js} +1 -1
  34. package/dist/client/assets/{diagram-B4RE2ZJO-CZy5Cter.js → diagram-B4RE2ZJO-Ba4DsVJc.js} +1 -1
  35. package/dist/client/assets/{diagram-LBJQPF4R-D64OHGQ1.js → diagram-LBJQPF4R-dtH5ElUa.js} +1 -1
  36. package/dist/client/assets/{diagram-Q27KOJAE-CYJYm3MT.js → diagram-Q27KOJAE-B6nCxEf9.js} +1 -1
  37. package/dist/client/assets/{diagram-UB23O5K3-D9XqDFWB.js → diagram-UB23O5K3-BZKG6s89.js} +1 -1
  38. package/dist/client/assets/{dist-D9557-UX.js → dist-dXsd7Pkc.js} +1 -1
  39. package/dist/client/assets/{ebnfDiagram-BXEA7PRR-DXv0laGY.js → ebnfDiagram-BXEA7PRR-66kiPxSS.js} +1 -1
  40. package/dist/client/assets/{erDiagram-JOGREHBK-DtgpDnFq.js → erDiagram-JOGREHBK-BMxnczHt.js} +1 -1
  41. package/dist/client/assets/eventmodeling-45OFAUF4-dP5YCAk6.js +1 -0
  42. package/dist/client/assets/flowDiagram-UKHOOZJN-BVSKDVqP.js +1 -0
  43. package/dist/client/assets/{freemarker2-C0K9bJg3.js → freemarker2-B66RkR3-.js} +1 -1
  44. package/dist/client/assets/{ganttDiagram-PKOTCBZU-DbPT_9cm.js → ganttDiagram-PKOTCBZU-Dfygs7SY.js} +1 -1
  45. package/dist/client/assets/{gitGraph-TEB2WS4Q-BSzJ-zot.js → gitGraph-TEB2WS4Q-D4bcJ5qF.js} +1 -1
  46. package/dist/client/assets/{gitGraphDiagram-DS77QQ5N-Dv47ST8y.js → gitGraphDiagram-DS77QQ5N-CpZ3u2XW.js} +1 -1
  47. package/dist/client/assets/{handlebars-C5Uh7yG8.js → handlebars-DKbKbvfy.js} +1 -1
  48. package/dist/client/assets/{html-CVq09h_T.js → html-ACV4rbgT.js} +1 -1
  49. package/dist/client/assets/{index-BdNjwiL_.css → index-C9ouroMB.css} +1 -1
  50. package/dist/client/assets/{index-C-Az4wQZ.js → index-DSoO6fwm.js} +190 -185
  51. package/dist/client/assets/{info-DKCQHKI2-DrnuTwtV.js → info-DKCQHKI2-DSdcmL_E.js} +1 -1
  52. package/dist/client/assets/{infoDiagram-6WML65LV-BbOLkXMO.js → infoDiagram-6WML65LV-CPjw27OG.js} +1 -1
  53. package/dist/client/assets/{ishikawaDiagram-WSZJBQD7-BU0Xf4Jv.js → ishikawaDiagram-WSZJBQD7-AUtwmA_E.js} +1 -1
  54. package/dist/client/assets/{javascript-BLNuR3ma.js → javascript-BrRHbE_m.js} +1 -1
  55. package/dist/client/assets/{journeyDiagram-NVQOT4AX-Be02AxgF.js → journeyDiagram-NVQOT4AX-dVKZ1J57.js} +1 -1
  56. package/dist/client/assets/{kanban-definition-27J2QSJJ-DAJOmq0i.js → kanban-definition-27J2QSJJ-yiBIweU4.js} +1 -1
  57. package/dist/client/assets/{line-CY8MZqA_.js → line-TmRvsmaZ.js} +1 -1
  58. package/dist/client/assets/{linear-VmQ0cgWf.js → linear-CGnxQxbf.js} +1 -1
  59. package/dist/client/assets/{liquid-CqxeTiTR.js → liquid-Dxzl-R2s.js} +1 -1
  60. package/dist/client/assets/{mdx-CZgnrcpZ.js → mdx-BzdRXa7m.js} +1 -1
  61. package/dist/client/assets/{mermaid-parser.core-BNyH4fWd.js → mermaid-parser.core-x3opGel5.js} +3 -3
  62. package/dist/client/assets/{mermaid.core-D6SqRXfj.js → mermaid.core-FMl-QNqU.js} +4 -4
  63. package/dist/client/assets/{mindmap-definition-FAOFIHXS-Cb4njDU8.js → mindmap-definition-FAOFIHXS-mTnBmq5M.js} +1 -1
  64. package/dist/client/assets/{packet-7NZHBO7P-C0OLtmrN.js → packet-7NZHBO7P-Dur5NQsS.js} +1 -1
  65. package/dist/client/assets/{pegDiagram-VL7TDLO6-CUlmavTd.js → pegDiagram-VL7TDLO6-Bx7c-RoO.js} +1 -1
  66. package/dist/client/assets/{pie-RZYD4A2V-BOaXF8wo.js → pie-RZYD4A2V-G_zAP186.js} +1 -1
  67. package/dist/client/assets/{pieDiagram-7S7Q4E2Y-DAuLOXyl.js → pieDiagram-7S7Q4E2Y-Dusuh84y.js} +1 -1
  68. package/dist/client/assets/{python-BKTOsIAC.js → python-CkiCBL2_.js} +1 -1
  69. package/dist/client/assets/{quadrantDiagram-CIZ2JOQS-6T2tUzKE.js → quadrantDiagram-CIZ2JOQS-saljoF_q.js} +1 -1
  70. package/dist/client/assets/{radar-I7S5WNFK-84ZPjfzV.js → radar-I7S5WNFK-SXVwHPoS.js} +1 -1
  71. package/dist/client/assets/{railroad-3IZDKUUU-BIancogu.js → railroad-3IZDKUUU-CNCO7Ky2.js} +1 -1
  72. package/dist/client/assets/railroad-abnf-AHOZXSZD-BDQOulCY.js +1 -0
  73. package/dist/client/assets/railroad-ebnf-EBAXGLYW-C7zEtpgH.js +1 -0
  74. package/dist/client/assets/railroad-peg-LSFZ7HO6-BRXwZ79v.js +1 -0
  75. package/dist/client/assets/{railroadDiagram-AXF67PYL-CG4n3oVN.js → railroadDiagram-AXF67PYL-DAlS2_gp.js} +1 -1
  76. package/dist/client/assets/{razor-D3D2-y9K.js → razor-CwkHcp-G.js} +1 -1
  77. package/dist/client/assets/{requirementDiagram-LRYGKXZP-mZX3Srsb.js → requirementDiagram-LRYGKXZP-Dl7nCbgE.js} +1 -1
  78. package/dist/client/assets/{sankeyDiagram-W5VNT64P-yPa5u_0L.js → sankeyDiagram-W5VNT64P-DpKvr-H6.js} +1 -1
  79. package/dist/client/assets/{sequenceDiagram-SI44F4Z6-CyNIlTWm.js → sequenceDiagram-SI44F4Z6-GHdgL3U8.js} +1 -1
  80. package/dist/client/assets/{src-CUuFImQF.js → src-I0atgFmE.js} +1 -1
  81. package/dist/client/assets/{stateDiagram-OKZ733FA-CPylCUxu.js → stateDiagram-OKZ733FA-BMQuOtg3.js} +1 -1
  82. package/dist/client/assets/stateDiagram-v2-UEYNNEHI-DJySabKQ.js +1 -0
  83. package/dist/client/assets/{swimlanes-SLNWSIFB-DBNGs0gR.js → swimlanes-SLNWSIFB-Bbv_31ln.js} +1 -1
  84. package/dist/client/assets/swimlanesDiagram-ULZ7WXOC-CT5Zed77.js +8 -0
  85. package/dist/client/assets/{timeline-definition-Z64GVDOM-BAUrOlpT.js → timeline-definition-Z64GVDOM-exSeDWTB.js} +1 -1
  86. package/dist/client/assets/{treeView-QDETBFTQ-DWU_Tu3e.js → treeView-QDETBFTQ-CNVUn1N1.js} +1 -1
  87. package/dist/client/assets/{treemap-6X3UGDF4-C0VSsv4b.js → treemap-6X3UGDF4-DwRfsOWe.js} +1 -1
  88. package/dist/client/assets/{typescript-DHaWXPl5.js → typescript-C48SvnqB.js} +1 -1
  89. package/dist/client/assets/{vennDiagram-T6HMQDX7-DMDrxVrh.js → vennDiagram-T6HMQDX7-CHNvZB5Q.js} +1 -1
  90. package/dist/client/assets/{wardley-OPB4EBWU-2FXuD4eH.js → wardley-OPB4EBWU-DmPs7uoZ.js} +1 -1
  91. package/dist/client/assets/{wardleyDiagram-T6FBY63Y-B6MdwST-.js → wardleyDiagram-T6FBY63Y-DGX-45LC.js} +1 -1
  92. package/dist/client/assets/{xml-UOCAZ6xX.js → xml-C8VlQ0O4.js} +1 -1
  93. package/dist/client/assets/{xychartDiagram-ELKLHX3M-4m0lgQEp.js → xychartDiagram-ELKLHX3M-DDMaGc1P.js} +1 -1
  94. package/dist/client/assets/{yaml-c5v3wojq.js → yaml-ZvDLP3To.js} +1 -1
  95. package/dist/client/index.html +2 -2
  96. package/package.json +3 -2
  97. package/dist/client/assets/architecture-TIHT7OUA-rtiyad39.js +0 -1
  98. package/dist/client/assets/channel-Cg-CR3Kv.js +0 -1
  99. package/dist/client/assets/classDiagram-JCYQIIEL-DN-cM4gO.js +0 -1
  100. package/dist/client/assets/classDiagram-v2-OCEON4UE-DN-cM4gO.js +0 -1
  101. package/dist/client/assets/eventmodeling-45OFAUF4-CIrFy3PN.js +0 -1
  102. package/dist/client/assets/flowDiagram-UKHOOZJN-CsaPoqV0.js +0 -1
  103. package/dist/client/assets/railroad-abnf-AHOZXSZD-DY5Umeyq.js +0 -1
  104. package/dist/client/assets/railroad-ebnf-EBAXGLYW-BvHqcDCh.js +0 -1
  105. package/dist/client/assets/railroad-peg-LSFZ7HO6-Bcfw7tSJ.js +0 -1
  106. package/dist/client/assets/stateDiagram-v2-UEYNNEHI-87clA1Da.js +0 -1
  107. package/dist/client/assets/swimlanesDiagram-ULZ7WXOC-DrshQU12.js +0 -8
package/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # Changelog
2
+
3
+ ## 0.2.0 (2026-09-09)
4
+
5
+ ### Added
6
+
7
+ - GitHub の pull request を開けるようにした (`kaleido pr 123` / PR の URL)。`gh` 経由で `refs/pull/<N>/head` を fetch するので、fork からの PR も checkout なしで読める
8
+ - PR の本文・会話・レビューコメントを閲覧できるようにした。行に紐づくレビューコメントはエディタ上にも表示する
9
+ - PR 表示中に GitHub の PR ページと github.dev を開くリンクを追加した
10
+ - ツールバーに refresh ボタンを追加し、タブが再表示されたときにも自動で取り直すようにした
11
+ - diff のファイルツリーで、ディレクトリ単位に viewed をトグルできるようにした
12
+ - Orca のターミナルから起動したときは Orca の内蔵ブラウザで開くようにした
13
+
14
+ ### Changed
15
+
16
+ - 行コメント追加ボタンを outlined なモノトーンにした
17
+ - Markdown プレビューの最大幅 (1280px) を外し、ペイン幅いっぱいに表示するようにした
18
+
19
+ ### Fixed
20
+
21
+ - merge 済み PR の diff が空になるのを直した。範囲セレクタに merged PR も並ぶようにした
22
+
23
+ ## 0.1.0 (2026-08-22)
24
+
25
+ 初回リリース。
package/README.md CHANGED
@@ -29,6 +29,8 @@ kaleido working # unstaged changes (index vs working tree)
29
29
  kaleido staged # staged changes (HEAD vs index)
30
30
  kaleido <commit> # そのコミットの diff (<commit>^ vs <commit>)
31
31
  kaleido <target> <base> # 任意の比較 (base vs target)
32
+ kaleido pr 123 # GitHub の pull request (base ブランチとの merge-base vs PR head)
33
+ kaleido https://github.com/owner/repo/pull/123 # PR の URL でも可
32
34
 
33
35
  kaleido comments [target] [base] # 保存済みコメントを AI プロンプト形式で stdout に出力
34
36
  ```
@@ -36,6 +38,8 @@ kaleido comments [target] [base] # 保存済みコメントを AI プロンプ
36
38
  位置引数は「ディレクトリ」または「比較範囲」。commit-ish として解決できなければディレクトリと解釈する (`--dir` で明示もできる)。
37
39
  引数なしのときは staged 変更 → working 変更 → 直近コミットの順に自動判定する。
38
40
 
41
+ PR の表示には [GitHub CLI](https://cli.github.com/) (`gh`、ログイン済み) が必要。`refs/pull/<N>/head` を `origin/pr/<N>` に fetch して開くので、fork からの PR も checkout なしで読める。
42
+
39
43
  表示中の状態は URL クエリ (`?target=&base=&path=&tab=`) に同期されるので、リロード・共有できる。
40
44
 
41
45
  | オプション | 説明 |
@@ -47,6 +51,8 @@ kaleido comments [target] [base] # 保存済みコメントを AI プロンプ
47
51
  | `--no-open` | ブラウザを自動で開かない |
48
52
  | `--no-keep-alive` | 全タブが閉じられたらサーバーを終了する |
49
53
 
54
+ [Orca](https://github.com/stablyai/orca) のターミナルから起動したときは、OS 既定のブラウザではなく Orca 内蔵ブラウザの新規タブに開く (`TERM_PROGRAM=Orca` で判定)。
55
+
50
56
  キーボード: `j` / `k` でファイル移動、`v` でレビュー済みトグル、⌘P で Quick Open、⌘B でサイドバー、⌘S で保存。
51
57
 
52
58
  ## 機能
@@ -57,6 +63,9 @@ kaleido comments [target] [base] # 保存済みコメントを AI プロンプ
57
63
  - **HTML プレビュー**: `/preview` から配信するので相対パスの CSS / JS / 画像も読め、スクリプトも動く
58
64
  - **型情報と診断**: hover / 型エラー / 定義ジャンプ / 参照検索と、プロジェクトの eslint による行マーカー
59
65
  - **レビュー** (git のみ): 比較範囲の切替、内容ハッシュで残るレビュー済みマーク、行/範囲コメント。状態はサーバー側にファイル保存されるのでブラウザを変えても消えない
66
+ - **Pull request** (GitHub のみ): 範囲セレクタに open な PR が並び、選ぶと最新の head を fetch して base ブランチとの merge-base 比較で開く。コメントは PR 単位で残る。セレクタの横から PR ページと github.dev を開ける
67
+ - Changes の先頭の **Overview** で PR の本文と会話 (コメント・approve など) を読める。GitHub 上の行コメントはエディタ内の該当行に読み取り専用で表示され、ファイル一覧にも件数が出る
68
+ - merge 済みの PR も開ける (GitHub が固定している base コミットとの merge-base で diff を出す)。セレクタには最近 merge された PR も並ぶ
60
69
  - **設定**: 歯車から配色 (既定は OS 追従) と文字サイズ、ライセンス表記
61
70
 
62
71
  ![型情報のホバーと行コメント](docs/kaleido-demo-hover-comment.gif)
package/dist/cli/index.js CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  // src/cli/index.ts
4
4
  import { Command } from "commander";
5
- import open from "open";
6
5
 
7
6
  // src/shared/commentFormat.ts
8
7
  function formatCommentPrompt(comment) {
@@ -20,6 +19,20 @@ function formatAllCommentsPrompt(comments) {
20
19
 
21
20
  // src/shared/types.ts
22
21
  var BROWSE_RANGE = { target: "browse", base: "browse" };
22
+ function pullRequestRef(number) {
23
+ return `origin/pr/${number}`;
24
+ }
25
+ function pullNumberOfRef(ref) {
26
+ const match = /^origin\/pr\/(\d+)$/.exec(ref);
27
+ return match ? Number(match[1]) : null;
28
+ }
29
+ function pullRange(pull) {
30
+ return {
31
+ target: pullRequestRef(pull.number),
32
+ base: pull.state === "OPEN" ? `origin/${pull.baseRefName}` : pull.baseRefOid,
33
+ baseMode: "merge-base"
34
+ };
35
+ }
23
36
  function rangeKey(range) {
24
37
  const sanitize = (s) => s.replace(/[^a-zA-Z0-9_.-]/g, "_");
25
38
  const mode = range.baseMode === "merge-base" ? "~mb" : "";
@@ -30,6 +43,8 @@ function describeRange(range) {
30
43
  if (range.target === "working") return "unstaged changes";
31
44
  if (range.target === "staged") return `${range.base}..staged`;
32
45
  if (range.target === ".") return `${range.base}..working tree`;
46
+ const pullNumber = pullNumberOfRef(range.target);
47
+ if (pullNumber !== null) return `PR #${pullNumber} (${range.base}...${range.target})`;
33
48
  const sep3 = range.baseMode === "merge-base" ? "..." : "..";
34
49
  return `${range.base}${sep3}${range.target}`;
35
50
  }
@@ -305,11 +320,41 @@ function createApp(ctx) {
305
320
  });
306
321
  app.get("/api/ranges", async (c) => {
307
322
  if (!ctx.gitRefs) {
308
- const empty = { branches: [], recentCommits: [], defaultBranch: null };
323
+ const empty = {
324
+ branches: [],
325
+ recentCommits: [],
326
+ defaultBranch: null,
327
+ pullRequests: [],
328
+ githubRepoUrl: null
329
+ };
309
330
  return c.json(empty);
310
331
  }
311
332
  return c.json(await ctx.gitRefs.getRanges());
312
333
  });
334
+ app.get("/api/pulls/:number", async (c) => {
335
+ if (!ctx.gitPulls) return c.json({ error: "Not a git repository" }, 400);
336
+ const number = Number(c.req.param("number"));
337
+ if (!Number.isInteger(number) || number <= 0) {
338
+ return c.json({ error: "Invalid pull request number" }, 400);
339
+ }
340
+ try {
341
+ return c.json(await ctx.gitPulls.detail(number));
342
+ } catch (error) {
343
+ return c.json({ error: error instanceof Error ? error.message : String(error) }, 502);
344
+ }
345
+ });
346
+ app.post("/api/pulls/:number/fetch", async (c) => {
347
+ if (!ctx.gitPulls) return c.json({ error: "Not a git repository" }, 400);
348
+ const number = Number(c.req.param("number"));
349
+ if (!Number.isInteger(number) || number <= 0) {
350
+ return c.json({ error: "Invalid pull request number" }, 400);
351
+ }
352
+ try {
353
+ return c.json(await ctx.gitPulls.fetch(number));
354
+ } catch (error) {
355
+ return c.json({ error: error instanceof Error ? error.message : String(error) }, 502);
356
+ }
357
+ });
313
358
  app.get("/api/files", async (c) => {
314
359
  if (ctx.gitDiff) {
315
360
  return c.json(applyExcludes(await ctx.gitDiff.listRepoFiles(), ctx.config));
@@ -542,11 +587,14 @@ function createApp(ctx) {
542
587
  "/api/viewed",
543
588
  zValidator(
544
589
  "json",
545
- z.object({ path: z.string().min(1), hash: z.string().min(1), viewed: z.boolean() })
590
+ z.object({
591
+ files: z.array(z.object({ path: z.string().min(1), hash: z.string().min(1) })).min(1),
592
+ viewed: z.boolean()
593
+ })
546
594
  ),
547
595
  (c) => {
548
- const { path, hash, viewed } = c.req.valid("json");
549
- ctx.reviewStore.setViewed(path, hash, viewed);
596
+ const { files, viewed } = c.req.valid("json");
597
+ ctx.reviewStore.setViewed(files, viewed);
550
598
  return c.json({ ok: true });
551
599
  }
552
600
  );
@@ -926,24 +974,300 @@ function decodeGitPath(rawPath) {
926
974
  return Buffer.from(bytes).toString("utf8");
927
975
  }
928
976
 
977
+ // src/server/git/pulls.ts
978
+ import { execFile as execFile2 } from "child_process";
979
+ import { promisify as promisify2 } from "util";
980
+ var execFileAsync2 = promisify2(execFile2);
981
+ var PR_JSON_FIELDS = "number,title,state,headRefName,baseRefName,baseRefOid,author,isDraft,url,updatedAt";
982
+ var PR_DETAIL_QUERY = `
983
+ query($owner: String!, $name: String!, $number: Int!) {
984
+ repository(owner: $owner, name: $name) {
985
+ pullRequest(number: $number) {
986
+ number title body state isDraft url createdAt updatedAt
987
+ baseRefName baseRefOid headRefName headRefOid additions deletions changedFiles
988
+ author { login }
989
+ comments(first: 100) {
990
+ nodes { id author { login } body createdAt url }
991
+ }
992
+ reviews(first: 100) {
993
+ nodes { id author { login } body state createdAt url }
994
+ }
995
+ reviewThreads(first: 100) {
996
+ nodes {
997
+ id path line startLine originalLine originalStartLine diffSide isResolved isOutdated
998
+ comments(first: 100) {
999
+ nodes { id author { login } body createdAt url diffHunk }
1000
+ }
1001
+ }
1002
+ }
1003
+ }
1004
+ }
1005
+ }`;
1006
+ function toDetail(pr) {
1007
+ const conversation = [
1008
+ ...pr.comments.nodes.map((c) => ({
1009
+ id: c.id,
1010
+ kind: "comment",
1011
+ author: c.author?.login ?? "",
1012
+ body: c.body,
1013
+ createdAt: c.createdAt,
1014
+ url: c.url
1015
+ })),
1016
+ // 本文のない COMMENTED レビューは行コメントの入れ物でしかないので会話には出さない
1017
+ ...pr.reviews.nodes.filter((r) => r.body.trim().length > 0 || r.state === "APPROVED" || r.state === "CHANGES_REQUESTED").map((r) => ({
1018
+ id: r.id,
1019
+ kind: "review",
1020
+ author: r.author?.login ?? "",
1021
+ body: r.body,
1022
+ createdAt: r.createdAt,
1023
+ url: r.url,
1024
+ reviewState: r.state
1025
+ }))
1026
+ ].sort((a, b) => a.createdAt.localeCompare(b.createdAt));
1027
+ const reviewThreads = pr.reviewThreads.nodes.map((t) => ({
1028
+ id: t.id,
1029
+ path: t.path,
1030
+ side: t.diffSide === "LEFT" ? "original" : "modified",
1031
+ line: t.line,
1032
+ startLine: t.startLine,
1033
+ originalLine: t.originalLine,
1034
+ originalStartLine: t.originalStartLine,
1035
+ isResolved: t.isResolved,
1036
+ isOutdated: t.isOutdated,
1037
+ diffHunk: t.comments.nodes[0]?.diffHunk ?? "",
1038
+ comments: t.comments.nodes.map((c) => ({
1039
+ id: c.id,
1040
+ author: c.author?.login ?? "",
1041
+ body: c.body,
1042
+ createdAt: c.createdAt,
1043
+ url: c.url
1044
+ }))
1045
+ }));
1046
+ return {
1047
+ number: pr.number,
1048
+ title: pr.title,
1049
+ headRefName: pr.headRefName,
1050
+ baseRefName: pr.baseRefName,
1051
+ baseRefOid: pr.baseRefOid,
1052
+ author: pr.author?.login ?? "",
1053
+ isDraft: pr.isDraft,
1054
+ url: pr.url,
1055
+ updatedAt: pr.updatedAt,
1056
+ body: pr.body,
1057
+ state: pr.state,
1058
+ createdAt: pr.createdAt,
1059
+ headRefOid: pr.headRefOid,
1060
+ additions: pr.additions,
1061
+ deletions: pr.deletions,
1062
+ changedFiles: pr.changedFiles,
1063
+ conversation,
1064
+ reviewThreads
1065
+ };
1066
+ }
1067
+ function toMeta(pr) {
1068
+ return {
1069
+ number: pr.number,
1070
+ title: pr.title,
1071
+ state: pr.state,
1072
+ headRefName: pr.headRefName,
1073
+ baseRefName: pr.baseRefName,
1074
+ baseRefOid: pr.baseRefOid,
1075
+ author: pr.author?.login ?? "",
1076
+ isDraft: pr.isDraft,
1077
+ url: pr.url,
1078
+ updatedAt: pr.updatedAt
1079
+ };
1080
+ }
1081
+ function isEnoent(error) {
1082
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
1083
+ }
1084
+ function stderrOf(error) {
1085
+ if (typeof error === "object" && error !== null && "stderr" in error) {
1086
+ return String(error.stderr).trim();
1087
+ }
1088
+ return error instanceof Error ? error.message : String(error);
1089
+ }
1090
+ function parsePullNumber(input) {
1091
+ const match = /^#?(\d+)$/.exec(input) ?? /^(?:pr|pull)\/(\d+)$/.exec(input) ?? /^https?:\/\/[^/]+\/[^/]+\/[^/]+\/pull\/(\d+)(?:[/?#].*)?$/.exec(input);
1092
+ return match ? Number(match[1]) : null;
1093
+ }
1094
+ var GitPulls = class {
1095
+ constructor(repoRoot) {
1096
+ this.repoRoot = repoRoot;
1097
+ }
1098
+ repoRoot;
1099
+ /** gh が未インストールなら以後は問い合わせない */
1100
+ isGhMissing = false;
1101
+ async gh(args) {
1102
+ const { stdout } = await execFileAsync2("gh", args, {
1103
+ cwd: this.repoRoot,
1104
+ encoding: "utf8",
1105
+ maxBuffer: 16 * 1024 * 1024,
1106
+ env: { ...process.env, GH_PROMPT_DISABLED: "1", GH_NO_UPDATE_NOTIFIER: "1" }
1107
+ });
1108
+ return stdout;
1109
+ }
1110
+ /**
1111
+ * open な PR (最大 30 件) と最近 merge された PR (最大 10 件)。
1112
+ * gh が使えない・GitHub リポジトリでない・オフラインなら空
1113
+ */
1114
+ async list() {
1115
+ if (this.isGhMissing) return [];
1116
+ try {
1117
+ const [open2, merged] = await Promise.all([
1118
+ this.listByState("open", 30),
1119
+ this.listByState("merged", 10)
1120
+ ]);
1121
+ return [...open2, ...merged];
1122
+ } catch (error) {
1123
+ if (isEnoent(error)) this.isGhMissing = true;
1124
+ return [];
1125
+ }
1126
+ }
1127
+ async listByState(state, limit) {
1128
+ const out = await this.gh([
1129
+ "pr",
1130
+ "list",
1131
+ "--state",
1132
+ state,
1133
+ "--limit",
1134
+ String(limit),
1135
+ "--json",
1136
+ PR_JSON_FIELDS
1137
+ ]);
1138
+ const prs = JSON.parse(out);
1139
+ return prs.map(toMeta);
1140
+ }
1141
+ async view(number) {
1142
+ try {
1143
+ const out = await this.gh(["pr", "view", String(number), "--json", PR_JSON_FIELDS]);
1144
+ const pr = JSON.parse(out);
1145
+ return toMeta(pr);
1146
+ } catch (error) {
1147
+ if (isEnoent(error)) {
1148
+ throw new Error("GitHub CLI (gh) is required to open pull requests: https://cli.github.com/");
1149
+ }
1150
+ throw new Error(`Could not read PR #${number}: ${stderrOf(error)}`);
1151
+ }
1152
+ }
1153
+ nameWithOwner = null;
1154
+ /** origin が指す GitHub リポジトリの owner/name (gh が解決する)。一度引いたら使い回す */
1155
+ async getNameWithOwner() {
1156
+ if (this.nameWithOwner === null) {
1157
+ const out = await this.gh(["repo", "view", "--json", "nameWithOwner", "--jq", ".nameWithOwner"]);
1158
+ this.nameWithOwner = out.trim();
1159
+ }
1160
+ const [owner, name] = this.nameWithOwner.split("/");
1161
+ if (!owner || !name) throw new Error(`Unexpected repository name: ${this.nameWithOwner}`);
1162
+ return { owner, name };
1163
+ }
1164
+ /** PR の本文・会話 (issue コメント / レビュー)・行コメントのスレッド */
1165
+ async detail(number) {
1166
+ try {
1167
+ const { owner, name } = await this.getNameWithOwner();
1168
+ const out = await this.gh([
1169
+ "api",
1170
+ "graphql",
1171
+ "-F",
1172
+ `owner=${owner}`,
1173
+ "-F",
1174
+ `name=${name}`,
1175
+ "-F",
1176
+ `number=${number}`,
1177
+ "-f",
1178
+ `query=${PR_DETAIL_QUERY}`
1179
+ ]);
1180
+ const parsed = JSON.parse(out);
1181
+ const pr = parsed.data?.repository?.pullRequest;
1182
+ if (!pr) throw new Error("not found");
1183
+ return toDetail(pr);
1184
+ } catch (error) {
1185
+ if (isEnoent(error)) {
1186
+ throw new Error("GitHub CLI (gh) is required to read pull requests: https://cli.github.com/");
1187
+ }
1188
+ throw new Error(`Could not read PR #${number}: ${stderrOf(error)}`);
1189
+ }
1190
+ }
1191
+ /** PR の head と base ブランチを origin から取り直し、比較範囲を返す */
1192
+ async fetch(number) {
1193
+ const pull = await this.view(number);
1194
+ try {
1195
+ await execFileAsync2(
1196
+ "git",
1197
+ [
1198
+ "fetch",
1199
+ "--no-tags",
1200
+ "origin",
1201
+ `+refs/pull/${number}/head:refs/remotes/${pullRequestRef(number)}`,
1202
+ `+refs/heads/${pull.baseRefName}:refs/remotes/origin/${pull.baseRefName}`
1203
+ ],
1204
+ {
1205
+ cwd: this.repoRoot,
1206
+ encoding: "utf8",
1207
+ // 認証が必要なときは対話せずに失敗させる (サーバー内で固まらないように)
1208
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
1209
+ }
1210
+ );
1211
+ } catch (error) {
1212
+ throw new Error(`Could not fetch PR #${number} from origin: ${stderrOf(error)}`);
1213
+ }
1214
+ if (pull.state !== "OPEN" && !await this.hasCommit(pull.baseRefOid)) {
1215
+ try {
1216
+ await execFileAsync2("git", ["fetch", "--no-tags", "origin", pull.baseRefOid], {
1217
+ cwd: this.repoRoot,
1218
+ encoding: "utf8",
1219
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
1220
+ });
1221
+ } catch (error) {
1222
+ throw new Error(
1223
+ `Could not fetch the base commit ${pull.baseRefOid.slice(0, 7)} of PR #${number}: ${stderrOf(error)}`
1224
+ );
1225
+ }
1226
+ }
1227
+ return { range: pullRange(pull), pull };
1228
+ }
1229
+ async hasCommit(sha) {
1230
+ try {
1231
+ await execFileAsync2("git", ["cat-file", "-e", `${sha}^{commit}`], { cwd: this.repoRoot });
1232
+ return true;
1233
+ } catch {
1234
+ return false;
1235
+ }
1236
+ }
1237
+ };
1238
+
929
1239
  // src/server/git/refs.ts
930
1240
  import { simpleGit as simpleGit2 } from "simple-git";
931
1241
  var GitRefs = class {
932
- git;
933
- constructor(repoRoot) {
1242
+ constructor(repoRoot, pulls) {
1243
+ this.pulls = pulls;
934
1244
  this.git = simpleGit2(repoRoot);
935
1245
  }
1246
+ pulls;
1247
+ git;
936
1248
  async getRanges() {
937
- const [branches, log, defaultBranch] = await Promise.all([
1249
+ const [branches, log, defaultBranch, pullRequests, githubRepoUrl] = await Promise.all([
938
1250
  this.getBranches(),
939
1251
  this.getRecentCommits(),
940
- this.getDefaultBranch()
1252
+ this.getDefaultBranch(),
1253
+ this.pulls.list(),
1254
+ this.getGithubRepoUrl()
941
1255
  ]);
942
- return { branches, recentCommits: log, defaultBranch };
1256
+ return { branches, recentCommits: log, defaultBranch, pullRequests, githubRepoUrl };
1257
+ }
1258
+ async getGithubRepoUrl() {
1259
+ try {
1260
+ const out = await this.git.raw(["remote", "get-url", "origin"]);
1261
+ return parseGithubRepoUrl(out.trim());
1262
+ } catch {
1263
+ return null;
1264
+ }
943
1265
  }
944
1266
  async getBranches() {
945
1267
  const summary = await this.git.branch(["--sort=-committerdate"]);
946
- return summary.all.filter((b) => !b.startsWith("remotes/") || b.startsWith("remotes/origin/"));
1268
+ return summary.all.filter(
1269
+ (b) => (!b.startsWith("remotes/") || b.startsWith("remotes/origin/")) && !b.startsWith("remotes/origin/pr/")
1270
+ );
947
1271
  }
948
1272
  async getRecentCommits() {
949
1273
  const log = await this.git.log({ maxCount: 50 });
@@ -970,6 +1294,14 @@ var GitRefs = class {
970
1294
  }
971
1295
  }
972
1296
  };
1297
+ function parseGithubRepoUrl(remote) {
1298
+ const match = /^(?:https?:\/\/|ssh:\/\/)?(?:[^@/]+@)?([^:/]+)(?::\d+)?[:/]([^/]+)\/([^/]+?)(?:\.git)?\/?$/.exec(remote);
1299
+ if (!match) return null;
1300
+ const [, host, owner, repo] = match;
1301
+ if (!host || !owner || !repo) return null;
1302
+ const isGithubHost = host === "github.com" || host.endsWith(".ghe.com") || host.startsWith("github.");
1303
+ return isGithubHost ? `https://${host}/${owner}/${repo}` : null;
1304
+ }
973
1305
 
974
1306
  // src/server/events.ts
975
1307
  var EventBus = class {
@@ -1053,12 +1385,15 @@ var ReviewStore = class {
1053
1385
  if (!data || data.version !== STORE_VERSION) return { entries: {} };
1054
1386
  return { entries: data.entries };
1055
1387
  }
1056
- setViewed(path, hash, isViewed) {
1388
+ setViewed(files, isViewed) {
1057
1389
  const state = this.getViewed();
1058
- if (isViewed) {
1059
- state.entries[path] = { hash, viewedAt: (/* @__PURE__ */ new Date()).toISOString() };
1060
- } else {
1061
- delete state.entries[path];
1390
+ const viewedAt = (/* @__PURE__ */ new Date()).toISOString();
1391
+ for (const { path, hash } of files) {
1392
+ if (isViewed) {
1393
+ state.entries[path] = { hash, viewedAt };
1394
+ } else {
1395
+ delete state.entries[path];
1396
+ }
1062
1397
  }
1063
1398
  this.writeAtomic(this.viewedPath, { version: STORE_VERSION, entries: state.entries });
1064
1399
  }
@@ -1197,6 +1532,7 @@ var TsWorkerClient = class {
1197
1532
  function createAppContext(rootDir, initialRange, options) {
1198
1533
  const realRoot = realpathSync3(rootDir);
1199
1534
  const repoId = computeRepoId(realRoot);
1535
+ const gitPulls = options.isGitRepo ? new GitPulls(realRoot) : null;
1200
1536
  return {
1201
1537
  rootDir: realRoot,
1202
1538
  repoId,
@@ -1204,7 +1540,8 @@ function createAppContext(rootDir, initialRange, options) {
1204
1540
  initialRange,
1205
1541
  config: loadViewerConfig(realRoot, options.excludes),
1206
1542
  gitDiff: options.isGitRepo ? new GitDiff(realRoot) : null,
1207
- gitRefs: options.isGitRepo ? new GitRefs(realRoot) : null,
1543
+ gitRefs: gitPulls ? new GitRefs(realRoot, gitPulls) : null,
1544
+ gitPulls,
1208
1545
  fileContent: new FileContent(realRoot, options.isGitRepo),
1209
1546
  tsService: new TsWorkerClient(realRoot),
1210
1547
  reviewStore: new ReviewStore(repoId, realRoot),
@@ -1330,8 +1667,32 @@ function isDirectory(path) {
1330
1667
  return false;
1331
1668
  }
1332
1669
  }
1333
- function resolveViewerTarget(params) {
1670
+ function parsePullTarget(target, base) {
1671
+ if (target === void 0) return null;
1672
+ if (target === "pr") {
1673
+ const number2 = base === void 0 ? null : parsePullNumber(base);
1674
+ if (number2 === null) {
1675
+ throw new Error("Usage: kaleido pr <number | GitHub PR URL>");
1676
+ }
1677
+ return number2;
1678
+ }
1679
+ if (!/^(#|pr\/|pull\/|https?:\/\/)/.test(target)) return null;
1680
+ const number = parsePullNumber(target);
1681
+ if (number === null) return null;
1682
+ if (base !== void 0) throw new Error("A base cannot be given when opening a pull request");
1683
+ return number;
1684
+ }
1685
+ async function resolveViewerTarget(params) {
1334
1686
  const { cwd, target, base } = params;
1687
+ const pullNumber = parsePullTarget(target, base);
1688
+ if (pullNumber !== null) {
1689
+ const startDir = params.dir === void 0 ? cwd : resolve3(cwd, params.dir);
1690
+ const gitRoot2 = findGitRoot(startDir);
1691
+ if (gitRoot2 === null) throw new Error(`Not a git repository: ${startDir}`);
1692
+ const pulls = new GitPulls(gitRoot2);
1693
+ const range = params.shouldFetchPull ? (await pulls.fetch(pullNumber)).range : pullRange(await pulls.view(pullNumber));
1694
+ return { rootDir: gitRoot2, isGitRepo: true, range };
1695
+ }
1335
1696
  if (params.dir !== void 0) {
1336
1697
  const dir = resolve3(cwd, params.dir);
1337
1698
  if (!isDirectory(dir)) throw new Error(`Not a directory: ${params.dir}`);
@@ -1412,20 +1773,44 @@ function resolveDefaultRange(rootDir) {
1412
1773
  return { target: ".", base: "HEAD" };
1413
1774
  }
1414
1775
 
1776
+ // src/cli/browser.ts
1777
+ import { execFile as execFile3 } from "child_process";
1778
+ import { promisify as promisify3 } from "util";
1779
+ import open from "open";
1780
+ var execFileAsync3 = promisify3(execFile3);
1781
+ function isInsideOrca(env = process.env) {
1782
+ return env.TERM_PROGRAM === "Orca" || env.ORCA_PANE_KEY !== void 0;
1783
+ }
1784
+ async function openInBrowser(url) {
1785
+ if (isInsideOrca()) {
1786
+ try {
1787
+ const orca = process.env.ORCA_CLI_COMMAND || "orca";
1788
+ await execFileAsync3(orca, ["tab", "create", "--url", url], { timeout: 15e3 });
1789
+ return;
1790
+ } catch (error) {
1791
+ const detail = typeof error === "object" && error !== null && "stderr" in error && String(error.stderr).trim() ? String(error.stderr).trim() : error instanceof Error ? error.message : String(error);
1792
+ console.error(`kaleido: could not open in Orca's browser, falling back to the default browser
1793
+ ${detail}`);
1794
+ }
1795
+ }
1796
+ await open(url);
1797
+ }
1798
+
1415
1799
  // src/cli/index.ts
1416
1800
  var program = new Command();
1417
1801
  var collect = (value, previous) => [...previous, value];
1418
1802
  program.name("kaleido").description("Monaco-based local web file viewer with TypeScript hover, diff and review tools").version("0.1.0");
1419
1803
  program.command("serve", { isDefault: true }).description("start the viewer (default command)").argument(
1420
1804
  "[target]",
1421
- 'directory to browse, commit-ish to view, or "working" / "staged" / "." (default: auto-detect)'
1805
+ 'directory to browse, commit-ish to view, "working" / "staged" / ".", or "pr <number|url>" (default: auto-detect)'
1422
1806
  ).argument("[base]", "commit-ish to compare against (default: HEAD or <target>^)").option("--port <port>", "preferred port (auto-increments if taken)", "4890").option("--host <host>", "host to bind", "127.0.0.1").option("--dir <path>", "directory to open (default: current directory)").option("--repo <path>", "alias of --dir").option("--exclude <pattern>", "extra path pattern to hide from the file tree", collect, []).option("--no-open", "do not open the browser").option("--no-keep-alive", "shut down the server when all browser tabs are closed").action(async (target, base, options) => {
1423
1807
  try {
1424
- const { rootDir, isGitRepo, range } = resolveViewerTarget({
1808
+ const { rootDir, isGitRepo, range } = await resolveViewerTarget({
1425
1809
  cwd: process.cwd(),
1426
1810
  dir: options.dir ?? options.repo,
1427
1811
  target,
1428
- base
1812
+ base,
1813
+ shouldFetchPull: true
1429
1814
  });
1430
1815
  const printCommentsAndExit = () => {
1431
1816
  try {
@@ -1455,16 +1840,16 @@ ${comments.length} comment(s) for ${describeRange(range)}:
1455
1840
  console.log(`kaleido: ${describeRange(range)} @ ${rootDir}`);
1456
1841
  console.log(` ${url}`);
1457
1842
  if (options.open) {
1458
- await open(url);
1843
+ await openInBrowser(url);
1459
1844
  }
1460
1845
  } catch (error) {
1461
1846
  console.error(error instanceof Error ? error.message : error);
1462
1847
  process.exit(1);
1463
1848
  }
1464
1849
  });
1465
- program.command("comments").description("print saved comments for a range as an AI prompt").argument("[target]", 'commit-ish, or "working" / "staged" / "." (default: ".")').argument("[base]", "commit-ish to compare against (default: HEAD or <target>^)").option("--dir <path>", "directory to read comments for (default: current directory)").option("--repo <path>", "alias of --dir").option("--json", "output as JSON instead of prompt text").action((target, base, options) => {
1850
+ program.command("comments").description("print saved comments for a range as an AI prompt").argument("[target]", 'commit-ish, "working" / "staged" / ".", or "pr <number|url>" (default: ".")').argument("[base]", "commit-ish to compare against (default: HEAD or <target>^)").option("--dir <path>", "directory to read comments for (default: current directory)").option("--repo <path>", "alias of --dir").option("--json", "output as JSON instead of prompt text").action(async (target, base, options) => {
1466
1851
  try {
1467
- const { rootDir, range } = resolveViewerTarget({
1852
+ const { rootDir, range } = await resolveViewerTarget({
1468
1853
  cwd: process.cwd(),
1469
1854
  dir: options.dir ?? options.repo,
1470
1855
  target,
@@ -1 +1 @@
1
- import{m as e,t}from"./mermaid-parser.core-BNyH4fWd.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-CUuFImQF.js";import"./chunk-I66GZJ75-CKcp5S17.js";import{n as i,r as a,t as o}from"./chunk-6Q2QTUOP-C-Jr6Q1u.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-D6SqRXfj.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
1
+ import{m as e,t}from"./mermaid-parser.core-x3opGel5.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-I0atgFmE.js";import"./chunk-I66GZJ75-DY6z-MCi.js";import{n as i,r as a,t as o}from"./chunk-6Q2QTUOP-CcE1vTzX.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-FMl-QNqU.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
@@ -1 +1 @@
1
- import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-D9557-UX.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i){if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
1
+ import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-dXsd7Pkc.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i){if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
@@ -0,0 +1 @@
1
+ import"./chunk-KEIR6QF5-BICK3FdT.js";import{M as e}from"./mermaid-parser.core-x3opGel5.js";export{e as createArchitectureServices};