pulls.review 0.1.0 → 0.2.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 (185) hide show
  1. package/README.md +16 -0
  2. package/bin.mjs +2 -0
  3. package/dist/client/assets/ChatWidget-BsnoQ6oS.js +1 -0
  4. package/dist/client/assets/DisplayFileIcon-DzBo3Ez5.js +151 -0
  5. package/dist/client/assets/GithubAvatar-CSsUV5vf.js +1 -0
  6. package/dist/client/assets/LandingHero-BkTBSu71.js +1 -0
  7. package/dist/client/assets/_repo_-Dcgj3PGg.js +22 -0
  8. package/dist/client/assets/analyze-509KQQBC.js +1 -0
  9. package/dist/client/assets/andromeeda-vGVdxbeo.js +1 -0
  10. package/dist/client/assets/anthropic-messages-Cd2DkgOC.js +41 -0
  11. package/dist/client/assets/aurora-x-CDeNXAV0.js +1 -0
  12. package/dist/client/assets/ayu-dark-DluEY0Gj.js +1 -0
  13. package/dist/client/assets/ayu-light-C3h-C4tm.js +1 -0
  14. package/dist/client/assets/ayu-mirage-Bqwy1Gya.js +1 -0
  15. package/dist/client/assets/browser-agent-rpc-BXhoSh1z-DrxWeI3_.js +1 -0
  16. package/dist/client/assets/c-BNQJhXlP.js +1 -0
  17. package/dist/client/assets/catppuccin-frappe-C9Q5zVZY.js +1 -0
  18. package/dist/client/assets/catppuccin-latte-CtsyrtPq.js +1 -0
  19. package/dist/client/assets/catppuccin-macchiato-R8nAf1vR.js +1 -0
  20. package/dist/client/assets/catppuccin-mocha-DjuaAJKi.js +1 -0
  21. package/dist/client/assets/clojure-DqKBuwfJ.js +1 -0
  22. package/dist/client/assets/cpp-7GgD5o7L.js +1 -0
  23. package/dist/client/assets/csharp-oqKa8noW.js +1 -0
  24. package/dist/client/assets/css-DlBQoFxe.js +1 -0
  25. package/dist/client/assets/dark-plus-Cs2F2srj.js +1 -0
  26. package/dist/client/assets/de-Bq9RfdAn.js +1 -0
  27. package/dist/client/assets/diff-BKQFn0my.js +37 -0
  28. package/dist/client/assets/diff-Bx6SazPw.js +1 -0
  29. package/dist/client/assets/diff-woXpYk--.js +1 -0
  30. package/dist/client/assets/diffs-store-ncE62OUU.js +1510 -0
  31. package/dist/client/assets/dist-Dh0a8u-Y.js +1 -0
  32. package/dist/client/assets/docker-IyjqRm3v.js +1 -0
  33. package/dist/client/assets/dracula-BHWKrbxM.js +1 -0
  34. package/dist/client/assets/dracula-soft-5eyTD99u.js +1 -0
  35. package/dist/client/assets/elixir-D3n0XgqJ.js +1 -0
  36. package/dist/client/assets/en-8hQdak1X.js +1 -0
  37. package/dist/client/assets/error-CJ3RHG07.js +1 -0
  38. package/dist/client/assets/es-QcvEBShr.js +1 -0
  39. package/dist/client/assets/everforest-dark-sB-x3p7T.js +1 -0
  40. package/dist/client/assets/everforest-light-Df2xbC6M.js +1 -0
  41. package/dist/client/assets/fr-DAWKVvDP.js +1 -0
  42. package/dist/client/assets/github-dark-C-LZuMrd.js +1 -0
  43. package/dist/client/assets/github-dark-default-DXG-b-1a.js +1 -0
  44. package/dist/client/assets/github-dark-dimmed-Bx1FflLF.js +1 -0
  45. package/dist/client/assets/github-dark-high-contrast-B_tTalzw.js +1 -0
  46. package/dist/client/assets/github-light-EUqPIrTm.js +1 -0
  47. package/dist/client/assets/github-light-default-BXViO-2h.js +1 -0
  48. package/dist/client/assets/github-light-high-contrast-B68TUdTA.js +1 -0
  49. package/dist/client/assets/go-rLFTqkRN.js +1 -0
  50. package/dist/client/assets/graphql-ki1Ij_uk.js +1 -0
  51. package/dist/client/assets/groovy-CacY0gHj.js +1 -0
  52. package/dist/client/assets/gruvbox-dark-hard-C820rvS2.js +1 -0
  53. package/dist/client/assets/gruvbox-dark-medium-BPjhmG05.js +1 -0
  54. package/dist/client/assets/gruvbox-dark-soft-MrdJrrXF.js +1 -0
  55. package/dist/client/assets/gruvbox-light-hard-BC_s9l72.js +1 -0
  56. package/dist/client/assets/gruvbox-light-medium-BAWPOn9u.js +1 -0
  57. package/dist/client/assets/gruvbox-light-soft-BSMLrYjP.js +1 -0
  58. package/dist/client/assets/haskell-D8IpX4py.js +1 -0
  59. package/dist/client/assets/horizon-CE9ld1lL.js +1 -0
  60. package/dist/client/assets/horizon-bright-DSNQnXHK.js +1 -0
  61. package/dist/client/assets/houston-CsvMBhTu.js +1 -0
  62. package/dist/client/assets/html-BC8aFsRK.js +1 -0
  63. package/dist/client/assets/i18n-CGV_MDS8.js +2 -0
  64. package/dist/client/assets/id-NIGs9Xhn.js +1 -0
  65. package/dist/client/assets/index-BCCy9wJJ.js +2 -0
  66. package/dist/client/assets/index-BDPZiDIt.css +1 -0
  67. package/dist/client/assets/ini-B5eOa1yu.js +1 -0
  68. package/dist/client/assets/install-B-q5w2uE.js +4 -0
  69. package/dist/client/assets/it-DjRuurmk.js +1 -0
  70. package/dist/client/assets/ja-BAKkDsQ5.js +1 -0
  71. package/dist/client/assets/java-D7h0NA_A.js +1 -0
  72. package/dist/client/assets/javascript-DcMHgNcu.js +1 -0
  73. package/dist/client/assets/json-qhed-kSA.js +1 -0
  74. package/dist/client/assets/jsonc-CYpm1nAK.js +1 -0
  75. package/dist/client/assets/jsx-BUUYi3qs.js +1 -0
  76. package/dist/client/assets/kanagawa-dragon-Bozd7klA.js +1 -0
  77. package/dist/client/assets/kanagawa-lotus-BmuOG9ZW.js +1 -0
  78. package/dist/client/assets/kanagawa-wave-BML5mF2J.js +1 -0
  79. package/dist/client/assets/ko-DHculY2W.js +1 -0
  80. package/dist/client/assets/kotlin-DhhofPvG.js +1 -0
  81. package/dist/client/assets/laserwave-C_8bwKvT.js +1 -0
  82. package/dist/client/assets/less-DVTAwKKz.js +1 -0
  83. package/dist/client/assets/light-plus-DVQuIRkW.js +1 -0
  84. package/dist/client/assets/llm-DYDmh8Ki.js +2 -0
  85. package/dist/client/assets/llm-store-CVM33nlB.js +2 -0
  86. package/dist/client/assets/locales-SpkpwNqX.js +1 -0
  87. package/dist/client/assets/lua-DCW0Dwo5.js +1 -0
  88. package/dist/client/assets/make-Dixweg8N.js +1 -0
  89. package/dist/client/assets/markdown-BYOwaDjH.js +1 -0
  90. package/dist/client/assets/material-theme-Bm3Qr25_.js +1 -0
  91. package/dist/client/assets/material-theme-darker-2IIEA8gg.js +1 -0
  92. package/dist/client/assets/material-theme-lighter-uhdI0v04.js +1 -0
  93. package/dist/client/assets/material-theme-ocean-CHQ94UKr.js +1 -0
  94. package/dist/client/assets/material-theme-palenight-B5W6OYN7.js +1 -0
  95. package/dist/client/assets/mdx-DQZ5AkYe.js +1 -0
  96. package/dist/client/assets/min-dark-BSWPekZh.js +1 -0
  97. package/dist/client/assets/min-light-DDpmG2fV.js +1 -0
  98. package/dist/client/assets/monokai-B_bV9PQ9.js +1 -0
  99. package/dist/client/assets/nginx-C4fSytnP.js +1 -0
  100. package/dist/client/assets/night-owl-DhmEMT88.js +1 -0
  101. package/dist/client/assets/night-owl-light-eJ-hLW7d.js +1 -0
  102. package/dist/client/assets/node.browser-BX-QLlU2.js +1 -0
  103. package/dist/client/assets/node.browser-DFtqp6Hr.js +1 -0
  104. package/dist/client/assets/nord-Cb4Vim4T.js +1 -0
  105. package/dist/client/assets/objective-c-D1A_Heim.js +1 -0
  106. package/dist/client/assets/objective-cpp-BsSzOQcm.js +1 -0
  107. package/dist/client/assets/one-dark-pro-CLwyXe_n.js +1 -0
  108. package/dist/client/assets/one-light-D7Lr4KcI.js +1 -0
  109. package/dist/client/assets/openai-completions-CSvY9IVo.js +21 -0
  110. package/dist/client/assets/pages-B5mEqsbn.js +1 -0
  111. package/dist/client/assets/pages-local-x_ACBinc.js +1 -0
  112. package/dist/client/assets/pages-web-DitAPN6U.js +21 -0
  113. package/dist/client/assets/patch-parser-k3Vbbmi0.js +5 -0
  114. package/dist/client/assets/perl-C8GHouAq.js +1 -0
  115. package/dist/client/assets/php-BahmaYs0.js +1 -0
  116. package/dist/client/assets/pierre-dark-CpLgRqie.js +1 -0
  117. package/dist/client/assets/pierre-dark-protanopia-deuteranopia-B35FxJx-.js +1 -0
  118. package/dist/client/assets/pierre-dark-soft-kZQmAZld.js +1 -0
  119. package/dist/client/assets/pierre-dark-tritanopia-CpjhbsIL.js +1 -0
  120. package/dist/client/assets/pierre-dark-vibrant-CpQYzh95.js +1 -0
  121. package/dist/client/assets/pierre-light-CoaEpmwp.js +1 -0
  122. package/dist/client/assets/pierre-light-protanopia-deuteranopia-0fSaH845.js +1 -0
  123. package/dist/client/assets/pierre-light-soft-lWLdNTOI.js +1 -0
  124. package/dist/client/assets/pierre-light-tritanopia-CEbqgOJL.js +1 -0
  125. package/dist/client/assets/pierre-light-vibrant-D80Fkn33.js +1 -0
  126. package/dist/client/assets/plastic-DQwYfKfQ.js +1 -0
  127. package/dist/client/assets/poimandres-DRFjx7u4.js +1 -0
  128. package/dist/client/assets/portalTarget-C60SzJiK.js +1 -0
  129. package/dist/client/assets/preload-helper-BaNbYf_w.js +1 -0
  130. package/dist/client/assets/proto-DB4EqR-F.js +1 -0
  131. package/dist/client/assets/pt-BR-LLtJ99P6.js +1 -0
  132. package/dist/client/assets/python-gzcpVVnB.js +1 -0
  133. package/dist/client/assets/r-C5FwQflr.js +1 -0
  134. package/dist/client/assets/red-DX1BQOs8.js +1 -0
  135. package/dist/client/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
  136. package/dist/client/assets/rose-pine-aMsaMD1D.js +1 -0
  137. package/dist/client/assets/rose-pine-dawn-8PwUyIlP.js +1 -0
  138. package/dist/client/assets/rose-pine-moon-DO-qXg-I.js +1 -0
  139. package/dist/client/assets/ru-DvkrOLxc.js +1 -0
  140. package/dist/client/assets/ruby-CfFGiaYl.js +1 -0
  141. package/dist/client/assets/runtime-dom.esm-bundler-CqL7__VR.js +2 -0
  142. package/dist/client/assets/rust-Cfkwpbl8.js +1 -0
  143. package/dist/client/assets/scala-BiFt_7mu.js +1 -0
  144. package/dist/client/assets/scss-C-_0yqZd.js +1 -0
  145. package/dist/client/assets/shellscript-CLZ0U2zV.js +1 -0
  146. package/dist/client/assets/shiki-wasm-noop-Gxv9UHE7.js +1 -0
  147. package/dist/client/assets/slack-dark-DnToyrRv.js +1 -0
  148. package/dist/client/assets/slack-ochin-B2OO5cIa.js +1 -0
  149. package/dist/client/assets/snazzy-light-4G7pJPwS.js +1 -0
  150. package/dist/client/assets/solarized-dark-UdsmMDCL.js +1 -0
  151. package/dist/client/assets/solarized-light-C1IUL_tW.js +1 -0
  152. package/dist/client/assets/source-hSji-yvG.js +2 -0
  153. package/dist/client/assets/sql-BsFa4tDR.js +1 -0
  154. package/dist/client/assets/swift-CyEgAFGc.js +1 -0
  155. package/dist/client/assets/synthwave-84-nFMaYfgc.js +1 -0
  156. package/dist/client/assets/terraform-DswuEJGm.js +1 -0
  157. package/dist/client/assets/time-ago-Bdao9Hh1.js +1 -0
  158. package/dist/client/assets/tokyo-night-oM2G3aXe.js +1 -0
  159. package/dist/client/assets/toml-CcmNWLt0.js +1 -0
  160. package/dist/client/assets/transform-messages-C8U1xonk.js +3 -0
  161. package/dist/client/assets/tsx-DvWhG4dC.js +1 -0
  162. package/dist/client/assets/typescript-BTGs5etX.js +1 -0
  163. package/dist/client/assets/upload-GnI9kmJu.js +1 -0
  164. package/dist/client/assets/uploadSession-BUj4FNau.js +1 -0
  165. package/dist/client/assets/useDocumentTitle-nuqxXiNo.js +185 -0
  166. package/dist/client/assets/vesper-DdrHHSXu.js +1 -0
  167. package/dist/client/assets/vitesse-black-fwtXNY1n.js +1 -0
  168. package/dist/client/assets/vitesse-dark-BZCL-v6S.js +1 -0
  169. package/dist/client/assets/vitesse-light-VbXTXTou.js +1 -0
  170. package/dist/client/assets/vue-BbYmdtmv.js +1 -0
  171. package/dist/client/assets/vue-html-BXjKVtKk.js +1 -0
  172. package/dist/client/assets/vue-i18n-DVI_S4Q5.js +5 -0
  173. package/dist/client/assets/xml-BsprbK0m.js +1 -0
  174. package/dist/client/assets/yaml-rwi0_p6S.js +1 -0
  175. package/dist/client/assets/zh-CN-BIibd6kG.js +1 -0
  176. package/dist/client/assets/zh-TW-3FtUHjoZ.js +1 -0
  177. package/dist/client/favicon.svg +1 -0
  178. package/dist/client/index.html +44 -0
  179. package/dist/client/og-dark.png +0 -0
  180. package/dist/client/og.png +0 -0
  181. package/dist/client/robots.txt +2 -0
  182. package/dist/devframe-CX5butdC.mjs +493 -0
  183. package/dist/devframe.mjs +2 -0
  184. package/dist/index.mjs +59 -118
  185. package/package.json +17 -9
package/dist/index.mjs CHANGED
@@ -1,126 +1,67 @@
1
- #!/usr/bin/env node
2
- import { readFileSync } from "node:fs";
1
+ import { t as devframe_default } from "./devframe-CX5butdC.mjs";
2
+ import { readFile } from "node:fs/promises";
3
3
  import process from "node:process";
4
+ import { fileURLToPath } from "node:url";
4
5
  import { parseArgs } from "node:util";
5
- import { githubTokenFromEnv, llmSettingsFromEnv } from "@pulls.review/core/env";
6
- import { runLlmAnalysis } from "@pulls.review/core/llm";
7
- import { Diagnostic, formatDiagnostic } from "nostics";
8
- import { DEFAULT_LOCALE, isLocale } from "@pulls.review/core/locales";
9
- import { resolveModel } from "@pulls.review/core/analyze";
10
- import { diagnostics } from "@pulls.review/core/diagnostics";
11
- import { createGithubPullRequestSource } from "@pulls.review/core/github";
12
- import { staticCredentials } from "@pulls.review/core/types";
13
- //#region src/config.ts
14
- /** The first value that is set and not blank: an Action passes unset inputs as `''`. */
15
- function first(...values) {
16
- return values.find((value) => value);
17
- }
18
- function resolveGithubToken(env) {
19
- const token = githubTokenFromEnv(env);
20
- if (!token) throw new Error("A GitHub token is required: set GITHUB_TOKEN (or PULLS_REVIEW_GITHUB_TOKEN).");
21
- return token;
22
- }
23
- function resolveLocale(env, flags = {}) {
24
- const requested = first(flags.locale, env.PULLS_REVIEW_LOCALE);
25
- if (requested === void 0) return DEFAULT_LOCALE;
26
- if (!isLocale(requested)) throw new Error(`Unsupported locale "${requested}".`);
27
- return requested;
28
- }
29
- /**
30
- * `owner/repo#123` or a github.com PR URL; in a workflow run, the PR the event is about.
31
- */
32
- function resolveTarget(arg, env, event) {
33
- if (arg) {
34
- const match = arg.match(/^(?:https:\/\/github\.com\/)?([^/\s]+)\/([^/#\s]+)(?:#|\/pull\/)(\d+)\/?$/);
35
- if (!match) throw new Error(`Cannot read a pull request from "${arg}": expected owner/repo#123 or a github.com pull request URL.`);
36
- return {
37
- owner: match[1],
38
- repo: match[2],
39
- number: match[3]
40
- };
41
- }
42
- const [owner, repo] = env.GITHUB_REPOSITORY?.split("/") ?? [];
43
- const number = event?.pull_request?.number;
44
- if (!owner || !repo || number === void 0) throw new Error("No pull request given. Pass owner/repo#123, or run on a pull_request event in GitHub Actions.");
45
- return {
46
- owner,
47
- repo,
48
- number: String(number)
49
- };
50
- }
51
- //#endregion
52
- //#region src/run.ts
53
- /** The author GitHub shows for a workflow's `GITHUB_TOKEN`, which cannot look itself up at `/user`. */
54
- const ACTIONS_BOT_LOGIN = "github-actions[bot]";
55
- function describeProgress(progress) {
56
- switch (progress.kind) {
57
- case "thinking": return `[${progress.step}] thinking`;
58
- case "reading": return `[${progress.step}] reading ${progress.paths.length} file${progress.paths.length === 1 ? "" : "s"}`;
59
- case "organizing": return `[${progress.step}] organizing groups`;
6
+ import { createDevServer } from "devframe/adapters/dev";
7
+ import { H3 } from "h3";
8
+ import { isLocalBranch, parseTarget, readCurrentBranch, resolveDefaultBranch } from "@pulls.review/core/local";
9
+ //#region src/page.ts
10
+ /** The page an argument opens (see the app's local routes). */
11
+ async function pageFor(cwd, arg, worktree) {
12
+ if (worktree) return "/worktree";
13
+ if (!arg) {
14
+ const [current, defaultBranch] = await Promise.all([readCurrentBranch(cwd), resolveDefaultBranch(cwd)]);
15
+ return current && defaultBranch && current !== defaultBranch.name ? `/branch/${current}` : "/";
60
16
  }
61
- }
62
- /**
63
- * Fetches the PR, analyzes it and upserts the shared-analysis comment, exactly like the
64
- * site's "share as comment" - one comment per author, found by its marker. A comment
65
- * already carrying the PR's current head sha is left alone, so re-runs on an unchanged
66
- * PR cost no model call.
67
- */
68
- async function run({ pr, githubToken, llm, locale, log }, analyze) {
69
- const resolved = resolveModel(llm);
70
- if (!resolved) throw diagnostics.llmNotConfigured();
71
- const source = createGithubPullRequestSource(pr, staticCredentials(githubToken));
72
- const [diff, login, comments] = await Promise.all([
73
- source.fetch(),
74
- source.viewer().then((viewer) => viewer?.login ?? ACTIONS_BOT_LOGIN, () => ACTIONS_BOT_LOGIN),
75
- source.sharing.list()
76
- ]);
77
- const headSha = diff.head?.sha ?? "";
78
- const existing = comments.find((comment) => comment.login === login);
79
- if (existing && existing.analysis.headSha === headSha) return {
80
- status: "up-to-date",
81
- url: existing.url
82
- };
83
- log(`Analyzing ${pr.owner}/${pr.repo}#${pr.number} (${diff.files.length} files) with ${resolved.model.provider}/${resolved.model.id}`);
84
- const { result } = await analyze(diff, resolved, locale, { onProgress: (progress) => log(describeProgress(progress)) });
85
- return {
86
- status: "posted",
87
- url: (await source.sharing.upsert(login, {
88
- headSha,
89
- result
90
- }, existing)).url
91
- };
17
+ if (parseTarget(arg).kind === "range") return `/compare/${arg}`;
18
+ return await isLocalBranch(cwd, arg) ? `/branch/${arg}` : `/commit/${arg}`;
92
19
  }
93
20
  //#endregion
94
21
  //#region src/index.ts
95
- const HELP = `Usage: pulls.review [owner/repo#123 | https://github.com/owner/repo/pull/123] [options]
22
+ const HELP = `Usage: pulls.review [target] [options]
23
+
24
+ Reviews local git changes in the browser, grouped and summarized. Run it inside
25
+ a git repository. The target only picks the page that opens; any other can be
26
+ picked from the browser.
96
27
 
97
- Analyzes the pull request with an LLM and posts (or updates) the grouped summary as
98
- a PR comment that pulls.review picks up. Without a target, reads the pull_request
99
- event of the running GitHub Actions job.
28
+ Target (git revision syntax):
29
+ (none) the current branch against the default branch, or the ref picker
30
+ when the default branch itself is checked out
31
+ <branch> what a branch adds since it forked from the default branch
32
+ <rev> one commit against its parent
33
+ A...B what B adds since it forked from A
34
+ A..B the tree diff between two revisions
100
35
 
101
36
  Options:
102
- --provider <name> gateway | anthropic | openai-compatible (PULLS_REVIEW_PROVIDER)
103
- --model <id> model id for the provider (PULLS_REVIEW_MODEL)
104
- --locale <tag> language of the summaries, default en (PULLS_REVIEW_LOCALE)
37
+ --worktree open the uncommitted changes against HEAD
38
+ --port <port> port to listen on
39
+ --no-open do not open the browser
105
40
  -h, --help
106
41
 
107
- Environment:
108
- GITHUB_TOKEN token with pull-requests: write (PULLS_REVIEW_GITHUB_TOKEN)
109
- AI_GATEWAY_API_KEY Vercel AI Gateway key (PULLS_REVIEW_API_KEY)
110
- ANTHROPIC_API_KEY Anthropic key (PULLS_REVIEW_API_KEY)
111
- OPENAI_API_KEY OpenAI-compatible key (PULLS_REVIEW_API_KEY)
112
- OPENAI_BASE_URL OpenAI-compatible endpoint (PULLS_REVIEW_BASE_URL)
42
+ To review a GitHub pull request in CI, use @pulls.review/actions.
113
43
  `;
114
- function readEvent(path) {
115
- return path ? JSON.parse(readFileSync(path, "utf-8")) : void 0;
44
+ /**
45
+ * devframe's SPA fallback skips any path that looks like a file, and refs do: `main...feat`
46
+ * ends in `.feat`, `v1.2` in `.2`. Pages whose path carries a ref get the SPA's
47
+ * `index.html` here, before devframe's static handler sees them.
48
+ */
49
+ function createAppWithRefRoutes() {
50
+ const app = new H3();
51
+ const index = fileURLToPath(new URL("./client/index.html", import.meta.url));
52
+ app.use(async (event, next) => {
53
+ if (!/^\/(?:compare|branch|commit)\//.test(event.url.pathname) || !event.req.headers.get("accept")?.includes("text/html")) return next();
54
+ return new Response(await readFile(index, "utf8"), { headers: { "Content-Type": "text/html; charset=utf-8" } });
55
+ });
56
+ return app;
116
57
  }
117
58
  async function main() {
118
59
  const { values: flags, positionals } = parseArgs({
119
60
  options: {
120
- provider: { type: "string" },
121
- model: { type: "string" },
122
- locale: { type: "string" },
123
- help: {
61
+ "worktree": { type: "boolean" },
62
+ "port": { type: "string" },
63
+ "no-open": { type: "boolean" },
64
+ "help": {
124
65
  type: "boolean",
125
66
  short: "h"
126
67
  }
@@ -128,21 +69,21 @@ async function main() {
128
69
  allowPositionals: true
129
70
  });
130
71
  if (flags.help) {
131
- console.log(HELP);
72
+ process.stdout.write(HELP);
132
73
  return;
133
74
  }
134
- const env = process.env;
135
- const outcome = await run({
136
- pr: resolveTarget(positionals[0], env, readEvent(env.GITHUB_EVENT_PATH)),
137
- githubToken: resolveGithubToken(env),
138
- llm: llmSettingsFromEnv(env, flags),
139
- locale: resolveLocale(env, flags),
140
- log: (line) => console.log(line)
141
- }, runLlmAnalysis);
142
- console.log(outcome.status === "up-to-date" ? `Comment already covers the current head: ${outcome.url}` : `Posted ${outcome.url}`);
75
+ const page = encodeURI(await pageFor(process.cwd(), positionals[0], !!flags.worktree));
76
+ await createDevServer(devframe_default, {
77
+ app: createAppWithRefRoutes(),
78
+ port: flags.port ? Number(flags.port) : void 0,
79
+ openBrowser: flags["no-open"] ? false : page,
80
+ onReady: ({ origin }) => {
81
+ process.stdout.write(`pulls.review is serving ${origin}${page}\n`);
82
+ }
83
+ });
143
84
  }
144
85
  main().catch((error) => {
145
- console.error(error instanceof Diagnostic ? formatDiagnostic(error) : error instanceof Error ? error.message : String(error));
86
+ console.error(error instanceof Error ? error.message : error);
146
87
  process.exitCode = 1;
147
88
  });
148
89
  //#endregion
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "pulls.review",
3
3
  "type": "module",
4
- "version": "0.1.0",
5
- "description": "Analyze a GitHub pull request with pulls.review and post the grouped summary as a PR comment.",
4
+ "version": "0.2.1",
5
+ "description": "Review local git changes - the working tree, a commit or any range - grouped and summarized in the browser.",
6
6
  "author": "Anthony Fu <hi@antfu.me>",
7
7
  "license": "MIT",
8
8
  "funding": "https://github.com/sponsors/antfu",
@@ -16,30 +16,38 @@
16
16
  "keywords": [
17
17
  "pull-request",
18
18
  "code-review",
19
- "github-actions",
20
- "llm"
19
+ "git",
20
+ "devframe"
21
21
  ],
22
+ "exports": {
23
+ "./devframe": "./dist/devframe.mjs"
24
+ },
22
25
  "bin": {
23
- "pulls.review": "./dist/index.mjs",
24
- "pulls-review": "./dist/index.mjs"
26
+ "pulls.review": "./bin.mjs",
27
+ "pulls-review": "./bin.mjs"
25
28
  },
26
29
  "files": [
30
+ "bin.mjs",
27
31
  "dist"
28
32
  ],
29
33
  "engines": {
30
34
  "node": ">=20"
31
35
  },
32
36
  "dependencies": {
33
- "@pulls.review/core": "^0.1.0",
34
- "nostics": "^1.3.0"
37
+ "@pulls.review/core": "^0.2.1",
38
+ "devframe": "^1.2.0",
39
+ "h3": "^2.0.1-rc.32",
40
+ "unstorage": "^1.17.5"
35
41
  },
36
42
  "devDependencies": {
37
43
  "@types/node": "^26.6.4",
44
+ "tsdown": "^0.23.0",
38
45
  "typescript": "^6.0.3",
39
46
  "vitest": "^5.0.3"
40
47
  },
41
48
  "scripts": {
42
- "build": "tsdown",
49
+ "build": "tsdown && pnpm -F @pulls.review/app run build:local",
50
+ "dev": "node bin.mjs",
43
51
  "typecheck": "tsc --noEmit",
44
52
  "test": "vitest run"
45
53
  }