@coldtea/pr-lens-cli 0.1.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 (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +117 -0
  3. package/dist/args.d.ts +18 -0
  4. package/dist/args.d.ts.map +1 -0
  5. package/dist/args.js +49 -0
  6. package/dist/args.js.map +1 -0
  7. package/dist/bin.d.ts +3 -0
  8. package/dist/bin.d.ts.map +1 -0
  9. package/dist/bin.js +8 -0
  10. package/dist/bin.js.map +1 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +97 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/commands/analyze.d.ts +4 -0
  16. package/dist/commands/analyze.d.ts.map +1 -0
  17. package/dist/commands/analyze.js +158 -0
  18. package/dist/commands/analyze.js.map +1 -0
  19. package/dist/commands/comment.d.ts +4 -0
  20. package/dist/commands/comment.d.ts.map +1 -0
  21. package/dist/commands/comment.js +63 -0
  22. package/dist/commands/comment.js.map +1 -0
  23. package/dist/commands/export.d.ts +4 -0
  24. package/dist/commands/export.d.ts.map +1 -0
  25. package/dist/commands/export.js +44 -0
  26. package/dist/commands/export.js.map +1 -0
  27. package/dist/commands/render.d.ts +4 -0
  28. package/dist/commands/render.d.ts.map +1 -0
  29. package/dist/commands/render.js +108 -0
  30. package/dist/commands/render.js.map +1 -0
  31. package/dist/commands/validate.d.ts +4 -0
  32. package/dist/commands/validate.d.ts.map +1 -0
  33. package/dist/commands/validate.js +49 -0
  34. package/dist/commands/validate.js.map +1 -0
  35. package/dist/comment.d.ts +16 -0
  36. package/dist/comment.d.ts.map +1 -0
  37. package/dist/comment.js +148 -0
  38. package/dist/comment.js.map +1 -0
  39. package/dist/config-file.d.ts +10 -0
  40. package/dist/config-file.d.ts.map +1 -0
  41. package/dist/config-file.js +19 -0
  42. package/dist/config-file.js.map +1 -0
  43. package/dist/corrections.d.ts +16 -0
  44. package/dist/corrections.d.ts.map +1 -0
  45. package/dist/corrections.js +80 -0
  46. package/dist/corrections.js.map +1 -0
  47. package/dist/document.d.ts +23 -0
  48. package/dist/document.d.ts.map +1 -0
  49. package/dist/document.js +75 -0
  50. package/dist/document.js.map +1 -0
  51. package/dist/errors.d.ts +15 -0
  52. package/dist/errors.d.ts.map +1 -0
  53. package/dist/errors.js +14 -0
  54. package/dist/errors.js.map +1 -0
  55. package/dist/extract.d.ts +54 -0
  56. package/dist/extract.d.ts.map +1 -0
  57. package/dist/extract.js +84 -0
  58. package/dist/extract.js.map +1 -0
  59. package/dist/git.d.ts +40 -0
  60. package/dist/git.d.ts.map +1 -0
  61. package/dist/git.js +104 -0
  62. package/dist/git.js.map +1 -0
  63. package/dist/io.d.ts +6 -0
  64. package/dist/io.d.ts.map +1 -0
  65. package/dist/io.js +35 -0
  66. package/dist/io.js.map +1 -0
  67. package/dist/prompt.d.ts +23 -0
  68. package/dist/prompt.d.ts.map +1 -0
  69. package/dist/prompt.js +69 -0
  70. package/dist/prompt.js.map +1 -0
  71. package/dist/providers/gemini.d.ts +3 -0
  72. package/dist/providers/gemini.d.ts.map +1 -0
  73. package/dist/providers/gemini.js +46 -0
  74. package/dist/providers/gemini.js.map +1 -0
  75. package/dist/providers/http.d.ts +5 -0
  76. package/dist/providers/http.d.ts.map +1 -0
  77. package/dist/providers/http.js +26 -0
  78. package/dist/providers/http.js.map +1 -0
  79. package/dist/providers/index.d.ts +48 -0
  80. package/dist/providers/index.d.ts.map +1 -0
  81. package/dist/providers/index.js +71 -0
  82. package/dist/providers/index.js.map +1 -0
  83. package/dist/providers/openai.d.ts +17 -0
  84. package/dist/providers/openai.d.ts.map +1 -0
  85. package/dist/providers/openai.js +42 -0
  86. package/dist/providers/openai.js.map +1 -0
  87. package/dist/snapshot.d.ts +15 -0
  88. package/dist/snapshot.d.ts.map +1 -0
  89. package/dist/snapshot.js +77 -0
  90. package/dist/snapshot.js.map +1 -0
  91. package/dist/terminal.d.ts +6 -0
  92. package/dist/terminal.d.ts.map +1 -0
  93. package/dist/terminal.js +5 -0
  94. package/dist/terminal.js.map +1 -0
  95. package/dist/version.d.ts +4 -0
  96. package/dist/version.d.ts.map +1 -0
  97. package/dist/version.js +4 -0
  98. package/dist/version.js.map +1 -0
  99. package/package.json +57 -0
  100. package/src/args.ts +52 -0
  101. package/src/bin.ts +10 -0
  102. package/src/cli.ts +120 -0
  103. package/src/commands/analyze.ts +206 -0
  104. package/src/commands/comment.ts +77 -0
  105. package/src/commands/export.ts +61 -0
  106. package/src/commands/render.ts +125 -0
  107. package/src/commands/validate.ts +57 -0
  108. package/src/comment.ts +190 -0
  109. package/src/config-file.ts +26 -0
  110. package/src/corrections.ts +86 -0
  111. package/src/document.ts +119 -0
  112. package/src/errors.ts +36 -0
  113. package/src/extract.ts +136 -0
  114. package/src/git.ts +151 -0
  115. package/src/io.ts +38 -0
  116. package/src/prompt.ts +87 -0
  117. package/src/providers/gemini.ts +61 -0
  118. package/src/providers/http.ts +54 -0
  119. package/src/providers/index.ts +124 -0
  120. package/src/providers/openai.ts +68 -0
  121. package/src/snapshot.ts +102 -0
  122. package/src/terminal.ts +9 -0
  123. package/src/version.ts +4 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ohans Emmanuel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,117 @@
1
+ # @coldtea/pr-lens-cli
2
+
3
+ PR Lens on the command line. It reads a diff with your own model key, checks the result against the contract, and hands you the pull request comment.
4
+
5
+ MIT © Ohans Emmanuel.
6
+
7
+ ```bash
8
+ npx @coldtea/pr-lens-cli analyze --base origin/main
9
+ ```
10
+
11
+ ## Bring your own key
12
+
13
+ The key is read from the environment, never from a flag: a flag lands in shell history and in the log of whatever CI runs it. The diff goes to the provider you name and nowhere else — there is no PR Lens service in this path.
14
+
15
+ ```bash
16
+ export GEMINI_API_KEY=…
17
+ pr-lens analyze --base origin/main --head HEAD
18
+ ```
19
+
20
+ Three request shapes are implemented rather than a list of vendors:
21
+
22
+ | `--provider` | Endpoint | Key |
23
+ | --- | --- | --- |
24
+ | `gemini` (default) | Google's own API | `GEMINI_API_KEY` |
25
+ | `openai` | OpenAI's own API | `OPENAI_API_KEY` |
26
+ | `openai-compatible` | anything else speaking `/chat/completions`, named by `--base-url` | `OPENAI_API_KEY` |
27
+
28
+ DeepSeek, Anthropic's compatibility endpoint, OpenRouter, Ollama and llama.cpp are all reached by pointing `--base-url` at them, and a new vendor needs no release here. OpenAI is listed separately from the servers that copied it because the two have drifted: it renamed the output limit to `max_completion_tokens` and its newer models reject `max_tokens`, which is the only spelling the others know. There is no field both accept, so you say which endpoint you are talking to rather than the CLI guessing from a hostname.
29
+
30
+ ```bash
31
+ pr-lens analyze --base origin/main \
32
+ --provider openai-compatible \
33
+ --base-url http://localhost:11434/v1 \
34
+ --model qwen3-coder \
35
+ --api-key-env OLLAMA_KEY
36
+ ```
37
+
38
+ ## The commands
39
+
40
+ ### `analyze`
41
+
42
+ Diff in, graph document out.
43
+
44
+ ```bash
45
+ pr-lens analyze --base origin/main --pr 42 -o pr-lens/graph.json
46
+ ```
47
+
48
+ The base is the merge base of the two refs, not the tip of the base branch: a diff against the tip would blame this pull request for every change made on the base branch since it forked.
49
+
50
+ The commit shas, the repository, the pull request number and the line counts are filled in from the repository itself, and anything the model writes there is discarded. A fact the model is free to restate is a fact that eventually disagrees with itself.
51
+
52
+ The answer is parsed against the contract. If it fails, the validation errors — paths and all — go back to the model once, and only once: a model that cannot fix a named path in one round does not fix it in three. `--dry-run` reports what would be sent and sends nothing.
53
+
54
+ ### `render`
55
+
56
+ ```bash
57
+ pr-lens render pr-lens/graph.json -o pr-lens/
58
+ ```
59
+
60
+ Draws the document as self-contained light and dark SVGs — one pair per drill-down section per lens, or one pair per lens when the document has no sections — and writes two files beside them: `manifest.json`, which says what was drawn and under which file name, and `drawn.graph.json`, the document those pictures actually show.
61
+
62
+ Both matter to what comes next. The manifest is where `comment` gets its file names, so neither command re-derives the other's. And `drawn.graph.json` exists because this is where corrections are applied: excluding a node can empty out a whole drill-down section, and the renderer then draws no picture for it. A comment composed from the document that went *in* would announce a section that came out of nothing.
63
+
64
+ The SVGs carry no script and no external reference, and the same document renders to the same bytes every time. `--theme light` or `--theme dark` draws one half of the pair.
65
+
66
+ ### `comment`
67
+
68
+ ```bash
69
+ pr-lens comment --graph pr-lens/drawn.graph.json --manifest pr-lens/manifest.json \
70
+ --asset-base-url https://raw.githubusercontent.com/owner/repo/pr-lens/42
71
+ ```
72
+
73
+ Composes the markdown — the `<picture>` pairs that read in both GitHub themes, the headline chips, the nested `<details>` tree — and prints it. Each diagram links to itself: a comment column is about 830 pixels wide and a system with several lanes is several times that, so it arrives scaled to fit and one click gives a reader the size the labels were drawn at. The two files have to belong to each other: the manifest records the hash of the document it came from, and a mismatched pair is refused rather than composed into a comment describing diagrams nobody drew. It posts nothing; posting is the caller's business, and `--print-marker` gives that caller the hidden marker that identifies an existing comment to update.
74
+
75
+ ### `validate`
76
+
77
+ ```bash
78
+ pr-lens validate pr-lens/graph.json .github/pr-lens.yml
79
+ ```
80
+
81
+ Parses graph documents, patch documents, render manifests and configs, JSON or YAML, and reports every problem in each rather than only the first. A file with no `kind` field is read as a config, because a config is the only one of the four a person writes by hand.
82
+
83
+ ### `export`
84
+
85
+ ```bash
86
+ pr-lens export pr-lens/graph.json -o .github/pr-lens.map.json
87
+ ```
88
+
89
+ Turns a pull-request document into the map of the system once that pull request has merged: elements the change deletes are dropped — with the edges and flow steps that hung from them — the rest stops being annotated, and the result is stamped with the single commit it reflects.
90
+
91
+ The map is a snapshot, not a source of truth. Nothing reads it back into the pipeline: a committed map that overrode inference would be hand-maintained rot with merge conflicts attached. Commit it so a repository has something to read, to diff, and to hand an agent.
92
+
93
+ ## Corrections
94
+
95
+ A repository's `.github/pr-lens.yml` is picked up automatically by `render` and applied at draw time — renames, exclusions, lane pins, groupings. It is an overlay: inference never writes back into it, so a correction keeps holding as the code moves and the model renames things between runs, and the document on disk stays the record of what was inferred.
96
+
97
+ ```yaml
98
+ schemaVersion: 0.1.0
99
+ map:
100
+ rename:
101
+ - match: functions/src/broadcast/sendBroadcastBulk.ts
102
+ to: Broadcast sender
103
+ exclude:
104
+ - "**/*.test.ts"
105
+ ```
106
+
107
+ A lane pin may name a lane the document never declared; the band is created and takes the id for its label. And `render` reports any correction that changed nothing about what it drew — a config that has drifted, usually because the file a selector named has moved, otherwise fails silently and forever.
108
+
109
+ `--config` points elsewhere and `--no-config` ignores it, on both `render` and `analyze` — `analyze` reads only `lenses` from it, since which lenses to fill is a question for extraction and the rest is a question for drawing.
110
+
111
+ ## Failures
112
+
113
+ Every failure carries a code, so a script can branch on it: `USAGE`, `UNREADABLE_FILE`, `UNKNOWN_DOCUMENT`, `INVALID_DOCUMENT`, `GIT_FAILED`, `EMPTY_DIFF`, `REPOSITORY_UNKNOWN`, `MISSING_API_KEY`, `PROVIDER_FAILED`, `MODEL_OUTPUT_INVALID`, `RENDER_FAILED`. Misuse exits 2, everything else exits 1.
114
+
115
+ ---
116
+
117
+ Part of [PR Lens](https://prlens.dev) — review what actually matters.
package/dist/args.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { type ParseArgsConfig } from "node:util";
2
+ type Options = NonNullable<ParseArgsConfig["options"]>;
3
+ /**
4
+ * `parseArgs` throws a plain `TypeError` on an unknown flag or a missing
5
+ * value, which would surface as a stack trace. Every one of them is a usage
6
+ * mistake and reads as one.
7
+ */
8
+ export declare const parseOptions: <Config extends Options>(args: readonly string[], options: Config) => {
9
+ values: Record<string, string | boolean | string[] | undefined>;
10
+ positionals: string[];
11
+ };
12
+ export declare const readString: (value: unknown, flag: string) => string | undefined;
13
+ export declare const readBoolean: (value: unknown) => boolean;
14
+ export declare const readInt: (value: unknown, flag: string, fallback: number) => number;
15
+ export declare const readList: (value: unknown, flag: string) => string[] | undefined;
16
+ export declare const expectOne: (positionals: readonly string[], what: string) => string;
17
+ export {};
18
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAG5D,KAAK,OAAO,GAAG,WAAW,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,OAAO,QAC3C,SAAS,MAAM,EAAE,WACd,MAAM,KACd;IAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAO1F,CAAC;AAEF,eAAO,MAAM,UAAU,UAAW,OAAO,QAAQ,MAAM,KAAG,MAAM,GAAG,SAIlE,CAAC;AAEF,eAAO,MAAM,WAAW,UAAW,OAAO,KAAG,OAAyB,CAAC;AAEvE,eAAO,MAAM,OAAO,UAAW,OAAO,QAAQ,MAAM,YAAY,MAAM,KAAG,MAQxE,CAAC;AAEF,eAAO,MAAM,QAAQ,UAAW,OAAO,QAAQ,MAAM,KAAG,MAAM,EAAE,GAAG,SAIlE,CAAC;AAEF,eAAO,MAAM,SAAS,gBAAiB,SAAS,MAAM,EAAE,QAAQ,MAAM,KAAG,MAKxE,CAAC"}
package/dist/args.js ADDED
@@ -0,0 +1,49 @@
1
+ import { parseArgs } from "node:util";
2
+ import { usageError } from "./errors.js";
3
+ /**
4
+ * `parseArgs` throws a plain `TypeError` on an unknown flag or a missing
5
+ * value, which would surface as a stack trace. Every one of them is a usage
6
+ * mistake and reads as one.
7
+ */
8
+ export const parseOptions = (args, options) => {
9
+ try {
10
+ const parsed = parseArgs({ args: [...args], options, allowPositionals: true, strict: true });
11
+ return { values: parsed.values, positionals: parsed.positionals };
12
+ }
13
+ catch (error) {
14
+ throw usageError(error instanceof Error ? error.message : String(error));
15
+ }
16
+ };
17
+ export const readString = (value, flag) => {
18
+ if (value === undefined)
19
+ return undefined;
20
+ if (typeof value !== "string")
21
+ throw usageError(`--${flag} needs a value`);
22
+ return value;
23
+ };
24
+ export const readBoolean = (value) => value === true;
25
+ export const readInt = (value, flag, fallback) => {
26
+ const text = readString(value, flag);
27
+ if (text === undefined)
28
+ return fallback;
29
+ const parsed = Number(text);
30
+ if (!Number.isInteger(parsed) || parsed <= 0)
31
+ throw usageError(`--${flag} needs a positive whole number, got ${JSON.stringify(text)}`);
32
+ return parsed;
33
+ };
34
+ export const readList = (value, flag) => {
35
+ if (value === undefined)
36
+ return undefined;
37
+ if (!Array.isArray(value))
38
+ throw usageError(`--${flag} needs a value`);
39
+ return value.flatMap((entry) => (typeof entry === "string" ? entry.split(",") : []));
40
+ };
41
+ export const expectOne = (positionals, what) => {
42
+ const [first, ...rest] = positionals;
43
+ if (first === undefined)
44
+ throw usageError(`expected ${what}`);
45
+ if (rest.length > 0)
46
+ throw usageError(`expected ${what}, got ${positionals.length} arguments`);
47
+ return first;
48
+ };
49
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAwB,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,IAAuB,EACvB,OAAe,EAC6E,EAAE;IAC9F,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7F,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;IACpE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,UAAU,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAc,EAAE,IAAY,EAAsB,EAAE;IAC7E,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,MAAM,UAAU,CAAC,KAAK,IAAI,gBAAgB,CAAC,CAAC;IAC3E,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAc,EAAW,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC;AAEvE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,KAAc,EAAE,IAAY,EAAE,QAAgB,EAAU,EAAE;IAChF,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACrC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAExC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC;QAC1C,MAAM,UAAU,CAAC,KAAK,IAAI,uCAAuC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3F,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAE,IAAY,EAAwB,EAAE;IAC7E,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,MAAM,UAAU,CAAC,KAAK,IAAI,gBAAgB,CAAC,CAAC;IACvE,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACvF,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,WAA8B,EAAE,IAAY,EAAU,EAAE;IAChF,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,WAAW,CAAC;IACrC,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,UAAU,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IAC9D,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,UAAU,CAAC,YAAY,IAAI,SAAS,WAAW,CAAC,MAAM,YAAY,CAAC,CAAC;IAC/F,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
package/dist/bin.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
package/dist/bin.js ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import { run } from "./cli.js";
3
+ import { processTerminal } from "./terminal.js";
4
+ process.exitCode = await run(process.argv.slice(2), processTerminal, process.env).catch((error) => {
5
+ processTerminal.err(error instanceof Error ? (error.stack ?? error.message) : String(error));
6
+ return 1;
7
+ });
8
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,CAAC,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CACrF,CAAC,KAAc,EAAE,EAAE;IACjB,eAAe,CAAC,GAAG,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7F,OAAO,CAAC,CAAC;AACX,CAAC,CACF,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { Terminal } from "./terminal.js";
2
+ export declare const run: (argv: readonly string[], terminal: Terminal, env: Record<string, string | undefined>) => Promise<number>;
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAkE9C,eAAO,MAAM,GAAG,SACR,SAAS,MAAM,EAAE,YACb,QAAQ,OACb,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KACtC,OAAO,CAAC,MAAM,CA0ChB,CAAC"}
package/dist/cli.js ADDED
@@ -0,0 +1,97 @@
1
+ import { assertNever } from "@coldtea/pr-lens-schema";
2
+ import { analyzeCommand, USAGE as ANALYZE_USAGE } from "./commands/analyze.js";
3
+ import { commentCommand, USAGE as COMMENT_USAGE } from "./commands/comment.js";
4
+ import { exportCommand, USAGE as EXPORT_USAGE } from "./commands/export.js";
5
+ import { renderCommand, USAGE as RENDER_USAGE } from "./commands/render.js";
6
+ import { USAGE as VALIDATE_USAGE, validateCommand } from "./commands/validate.js";
7
+ import { formatError, PrLensCliError } from "./errors.js";
8
+ import { CLI_VERSION } from "./version.js";
9
+ const COMMANDS = ["analyze", "render", "comment", "validate", "export"];
10
+ const isCommand = (value) => COMMANDS.some((command) => command === value);
11
+ const HELP = `pr-lens — review what actually matters
12
+
13
+ pr-lens analyze --base <ref> a diff, read by your own model, as a graph document
14
+ pr-lens render <graph.json> that document, as light and dark SVGs
15
+ pr-lens comment --graph --manifest the pull request comment, as markdown
16
+ pr-lens validate <file...> any PR Lens document, checked against the contract
17
+ pr-lens export <graph.json> the merged state, as a map worth committing
18
+
19
+ pr-lens <command> --help what a command takes
20
+ pr-lens --version
21
+
22
+ Your model key is read from the environment and goes only to the provider you
23
+ name. https://github.com/coldteadotai/pr-lens`;
24
+ const usageFor = (command) => {
25
+ switch (command) {
26
+ case "analyze":
27
+ return ANALYZE_USAGE;
28
+ case "render":
29
+ return RENDER_USAGE;
30
+ case "comment":
31
+ return COMMENT_USAGE;
32
+ case "validate":
33
+ return VALIDATE_USAGE;
34
+ case "export":
35
+ return EXPORT_USAGE;
36
+ default:
37
+ return assertNever(command, "Unhandled command");
38
+ }
39
+ };
40
+ const dispatch = (command, args, terminal, env) => {
41
+ switch (command) {
42
+ case "analyze":
43
+ return analyzeCommand(args, terminal, env);
44
+ case "render":
45
+ return renderCommand(args, terminal);
46
+ case "comment":
47
+ return commentCommand(args, terminal);
48
+ case "validate":
49
+ return validateCommand(args, terminal);
50
+ case "export":
51
+ return exportCommand(args, terminal);
52
+ default:
53
+ return assertNever(command, "Unhandled command");
54
+ }
55
+ };
56
+ const EXIT_OK = 0;
57
+ const EXIT_FAILED = 1;
58
+ const EXIT_MISUSED = 2;
59
+ export const run = async (argv, terminal, env) => {
60
+ const [name, ...args] = argv;
61
+ if (name === undefined) {
62
+ terminal.err(HELP);
63
+ return EXIT_MISUSED;
64
+ }
65
+ if (name === "--help" || name === "-h" || name === "help") {
66
+ terminal.out(HELP);
67
+ return EXIT_OK;
68
+ }
69
+ if (name === "--version" || name === "-v") {
70
+ terminal.out(CLI_VERSION);
71
+ return EXIT_OK;
72
+ }
73
+ if (!isCommand(name)) {
74
+ terminal.err(formatError(new PrLensCliError("USAGE", `unknown command ${JSON.stringify(name)}`)));
75
+ terminal.err(HELP);
76
+ return EXIT_MISUSED;
77
+ }
78
+ if (args.includes("--help") || args.includes("-h")) {
79
+ terminal.out(usageFor(name));
80
+ return EXIT_OK;
81
+ }
82
+ try {
83
+ await dispatch(name, args, terminal, env);
84
+ return EXIT_OK;
85
+ }
86
+ catch (error) {
87
+ if (!(error instanceof PrLensCliError))
88
+ throw error;
89
+ terminal.err(formatError(error));
90
+ if (error.code !== "USAGE")
91
+ return EXIT_FAILED;
92
+ terminal.err("");
93
+ terminal.err(usageFor(name));
94
+ return EXIT_MISUSED;
95
+ }
96
+ };
97
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Terminal } from "../terminal.js";
2
+ export declare const USAGE: string;
3
+ export declare const analyzeCommand: (args: readonly string[], terminal: Terminal, env: Record<string, string | undefined>) => Promise<void>;
4
+ //# sourceMappingURL=analyze.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAO/C,eAAO,MAAM,KAAK,QAsB+D,CAAC;AAyBlF,eAAO,MAAM,cAAc,SACnB,SAAS,MAAM,EAAE,YACb,QAAQ,OACb,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KACtC,OAAO,CAAC,IAAI,CAyId,CAAC"}
@@ -0,0 +1,158 @@
1
+ import { LENSES } from "@coldtea/pr-lens-schema";
2
+ import { createRequire } from "node:module";
3
+ import { parseOptions, readBoolean, readInt, readList, readString } from "../args.js";
4
+ import { discoverConfig, loadConfig } from "../config-file.js";
5
+ import { PrLensCliError, usageError } from "../errors.js";
6
+ import { extractGraph } from "../extract.js";
7
+ import { collectDiff, mergeBase, parseRepoSlug, remoteSlug, repositoryRoot, resolveCommit } from "../git.js";
8
+ import { readTextFile, writeJsonFile } from "../io.js";
9
+ import { buildExtractionPrompt, SYSTEM_PROMPT } from "../prompt.js";
10
+ import { completeJson, isProviderId, PROVIDER_IDS, resolveProvider } from "../providers/index.js";
11
+ import { CLI_VERSION, GENERATOR_NAME } from "../version.js";
12
+ const DEFAULT_OUT = "pr-lens/graph.json";
13
+ const DEFAULT_MAX_OUTPUT_TOKENS = 32_768;
14
+ const DEFAULT_MAX_DIFF_BYTES = 400_000;
15
+ export const USAGE = `pr-lens analyze --base <ref> [options]
16
+
17
+ Reads the diff between two commits and asks your own model to describe it as a
18
+ graph document. The key never leaves your machine: it is read from the
19
+ environment, and the diff goes straight to the provider you name.
20
+
21
+ --base <ref> what the change is measured against (required)
22
+ --head <ref> the tip of the change (default HEAD)
23
+ --repo <dir> repository to read (default .)
24
+ --provider <id> ${PROVIDER_IDS.join(" | ")} (default gemini)
25
+ --model <name> model to ask (required for openai-compatible)
26
+ --base-url <url> provider endpoint, for a compatible or local server
27
+ --api-key-env <name> environment variable holding the key
28
+ --lens <lens> ${LENSES.join(", ")} (repeatable, default both)
29
+ --config <file> read the lenses from this config (default the repository's)
30
+ --no-config ignore the repository's config
31
+ --pr <number> pull request number, recorded in provenance
32
+ --repo-slug <owner/name> override the slug read from the git remote
33
+ --remote <name> remote to read the slug from (default origin)
34
+ --max-diff-bytes <n> truncate the diff sent to the model (default ${DEFAULT_MAX_DIFF_BYTES})
35
+ --max-output-tokens <n> room for the answer (default ${DEFAULT_MAX_OUTPUT_TOKENS})
36
+ --dry-run report what would be sent, and send nothing
37
+ -o, --out <file> where to write the document (default ${DEFAULT_OUT})`;
38
+ const readLenses = (values) => {
39
+ const requested = readList(values.lens, "lens");
40
+ if (requested === undefined)
41
+ return undefined;
42
+ const unknown = requested.filter((lens) => !LENSES.some((known) => known === lens));
43
+ if (unknown.length > 0)
44
+ throw usageError(`unknown lens ${unknown.join(", ")}`, `known lenses: ${LENSES.join(", ")}`);
45
+ return LENSES.filter((lens) => requested.includes(lens));
46
+ };
47
+ const readProviderId = (values) => {
48
+ const id = readString(values.provider, "provider") ?? "gemini";
49
+ if (!isProviderId(id))
50
+ throw usageError(`unknown provider ${JSON.stringify(id)}`, `known providers: ${PROVIDER_IDS.join(", ")}`);
51
+ return id;
52
+ };
53
+ const graphJsonSchema = () => readTextFile(createRequire(import.meta.url).resolve("@coldtea/pr-lens-schema/json-schema/graph-doc.schema.json"));
54
+ export const analyzeCommand = async (args, terminal, env) => {
55
+ const { values, positionals } = parseOptions(args, {
56
+ base: { type: "string" },
57
+ head: { type: "string" },
58
+ repo: { type: "string" },
59
+ provider: { type: "string" },
60
+ model: { type: "string" },
61
+ "base-url": { type: "string" },
62
+ "api-key-env": { type: "string" },
63
+ lens: { type: "string", multiple: true },
64
+ config: { type: "string" },
65
+ "no-config": { type: "boolean" },
66
+ pr: { type: "string" },
67
+ "repo-slug": { type: "string" },
68
+ remote: { type: "string" },
69
+ "max-diff-bytes": { type: "string" },
70
+ "max-output-tokens": { type: "string" },
71
+ "dry-run": { type: "boolean" },
72
+ out: { type: "string", short: "o" },
73
+ });
74
+ if (positionals.length > 0)
75
+ throw usageError(`analyze takes no positional arguments, got ${positionals.join(" ")}`);
76
+ const base = readString(values.base, "base");
77
+ if (base === undefined)
78
+ throw usageError("--base is required", "it names the commit the change is measured against, e.g. --base origin/main");
79
+ const repo = readString(values.repo, "repo") ?? process.cwd();
80
+ const head = readString(values.head, "head") ?? "HEAD";
81
+ const maxDiffBytes = readInt(values["max-diff-bytes"], "max-diff-bytes", DEFAULT_MAX_DIFF_BYTES);
82
+ const slugOption = readString(values["repo-slug"], "repo-slug");
83
+ const slug = slugOption === undefined
84
+ ? await remoteSlug(repo, readString(values.remote, "remote") ?? "origin")
85
+ : parseRepoSlug(slugOption);
86
+ if (slug === undefined)
87
+ throw new PrLensCliError("REPOSITORY_UNKNOWN", "cannot tell which repository this is", "pass --repo-slug owner/name, or add a git remote the CLI can read");
88
+ const configPath = readString(values.config, "config");
89
+ const configured = readBoolean(values["no-config"])
90
+ ? undefined
91
+ : configPath === undefined
92
+ ? await discoverConfig(await repositoryRoot(repo))
93
+ : await loadConfig(configPath);
94
+ const requestedLenses = readLenses(values);
95
+ const lenses = requestedLenses ?? configured?.config.lenses ?? [...LENSES];
96
+ const headCommit = await resolveCommit(repo, head);
97
+ const baseCommit = await resolveCommit(repo, base);
98
+ const comparedAgainst = await mergeBase(repo, baseCommit.sha, headCommit.sha);
99
+ const diff = await collectDiff(repo, comparedAgainst, headCommit.sha, maxDiffBytes);
100
+ if (diff.files.length === 0)
101
+ throw new PrLensCliError("EMPTY_DIFF", `${base} and ${head} have the same content`, "there is nothing to draw");
102
+ const promptContext = {
103
+ repo: { owner: slug.owner, name: slug.name },
104
+ base: { sha: comparedAgainst, ref: baseCommit.ref },
105
+ head: { sha: headCommit.sha, ref: headCommit.ref },
106
+ diff,
107
+ lenses,
108
+ };
109
+ const user = buildExtractionPrompt(promptContext, await graphJsonSchema());
110
+ const provider = readBoolean(values["dry-run"])
111
+ ? undefined
112
+ : resolveProvider({
113
+ id: readProviderId(values),
114
+ model: readString(values.model, "model"),
115
+ baseUrl: readString(values["base-url"], "base-url"),
116
+ apiKeyEnv: readString(values["api-key-env"], "api-key-env"),
117
+ }, env);
118
+ terminal.err(`${diff.files.length} files, +${diff.additions} -${diff.deletions}, ${Buffer.byteLength(diff.patch, "utf8")} bytes of diff${diff.truncatedAt === undefined ? "" : " (truncated)"}`);
119
+ terminal.err(`prompt: ${Buffer.byteLength(user, "utf8")} bytes`);
120
+ if (provider === undefined) {
121
+ terminal.out(`✓ dry run — nothing was sent, and nothing was written`);
122
+ return;
123
+ }
124
+ const pr = values.pr === undefined ? undefined : readInt(values.pr, "pr", 0);
125
+ const pullRequest = pr === undefined
126
+ ? undefined
127
+ : { number: pr, url: `https://${slug.host}/${slug.owner}/${slug.name}/pull/${pr}` };
128
+ const provenance = {
129
+ repo: slug,
130
+ base: { sha: comparedAgainst, ref: baseCommit.ref },
131
+ head: { sha: headCommit.sha, ref: headCommit.ref },
132
+ ...(pullRequest === undefined ? {} : { pullRequest }),
133
+ generator: { name: GENERATOR_NAME, version: CLI_VERSION, model: provider.model },
134
+ };
135
+ terminal.err(`asking ${provider.id} (${provider.model})…`);
136
+ const { document, attempts } = await extractGraph({
137
+ system: SYSTEM_PROMPT,
138
+ user,
139
+ maxOutputTokens: readInt(values["max-output-tokens"], "max-output-tokens", DEFAULT_MAX_OUTPUT_TOKENS),
140
+ known: {
141
+ provenance,
142
+ lenses,
143
+ stats: {
144
+ filesChanged: diff.files.length,
145
+ additions: diff.additions,
146
+ deletions: diff.deletions,
147
+ },
148
+ generatedAt: new Date().toISOString(),
149
+ },
150
+ onAttempt: (attempt) => {
151
+ if (attempt > 1)
152
+ terminal.err(`the document did not validate — asking for a correction`);
153
+ },
154
+ }, (request) => completeJson(provider, request));
155
+ const written = await writeJsonFile(readString(values.out, "out") ?? DEFAULT_OUT, document);
156
+ terminal.out(`✓ ${written} — ${document.nodes.length} nodes, ${document.edges.length} edges, ${document.flows.length} flows${attempts > 1 ? ` (${attempts} attempts)` : ""}`);
157
+ };
158
+ //# sourceMappingURL=analyze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAiC,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,cAAc,EAAE,UAAU,EAAqB,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC7G,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAElG,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE5D,MAAM,WAAW,GAAG,oBAAoB,CAAC;AACzC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AACzC,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAEvC,MAAM,CAAC,MAAM,KAAK,GAAG;;;;;;;;;8BASS,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;;;;8BAIxB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;2EAM4B,sBAAsB;2DACtC,yBAAyB;;mEAEjB,WAAW,GAAG,CAAC;AAElF,MAAM,UAAU,GAAG,CAAC,MAA+B,EAAsB,EAAE;IACzE,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAChD,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAE9C,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC;IACpF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QACpB,MAAM,UAAU,CAAC,gBAAgB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,iBAAiB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAE/F,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3D,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,MAA+B,EAAE,EAAE;IACzD,MAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,QAAQ,CAAC;IAC/D,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QACnB,MAAM,UAAU,CAAC,oBAAoB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,oBAAoB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5G,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,GAAoB,EAAE,CAC5C,YAAY,CACV,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,2DAA2D,CAAC,CACpG,CAAC;AAEJ,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EACjC,IAAuB,EACvB,QAAkB,EAClB,GAAuC,EACxB,EAAE;IACjB,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,YAAY,CAAC,IAAI,EAAE;QACjD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACxB,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACxB,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACxB,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC5B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACzB,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC9B,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACjC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;QACxC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC1B,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QAChC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACtB,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC/B,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC1B,gBAAgB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACpC,mBAAmB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACvC,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QAC9B,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;KACpC,CAAC,CAAC;IAEH,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,UAAU,CAAC,8CAA8C,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEpH,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7C,IAAI,IAAI,KAAK,SAAS;QAAE,MAAM,UAAU,CAAC,oBAAoB,EAAE,6EAA6E,CAAC,CAAC;IAE9I,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC9D,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC;IACvD,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,EAAE,sBAAsB,CAAC,CAAC;IAEjG,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,UAAU,KAAK,SAAS;QACnC,CAAC,CAAC,MAAM,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,QAAQ,CAAC;QACzE,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAE9B,IAAI,IAAI,KAAK,SAAS;QACpB,MAAM,IAAI,cAAc,CACtB,oBAAoB,EACpB,sCAAsC,EACtC,mEAAmE,CACpE,CAAC;IAEJ,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvD,MAAM,UAAU,GAA6B,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC3E,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,UAAU,KAAK,SAAS;YACxB,CAAC,CAAC,MAAM,cAAc,CAAC,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;YAClD,CAAC,CAAC,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;IAEnC,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,eAAe,IAAI,UAAU,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;IAE3E,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnD,MAAM,eAAe,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IAC9E,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,eAAe,EAAE,UAAU,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAEpF,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QACzB,MAAM,IAAI,cAAc,CACtB,YAAY,EACZ,GAAG,IAAI,QAAQ,IAAI,wBAAwB,EAC3C,0BAA0B,CAC3B,CAAC;IAEJ,MAAM,aAAa,GAAG;QACpB,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;QAC5C,IAAI,EAAE,EAAE,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE;QACnD,IAAI,EAAE,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE;QAClD,IAAI;QACJ,MAAM;KACP,CAAC;IAEF,MAAM,IAAI,GAAG,qBAAqB,CAAC,aAAa,EAAE,MAAM,eAAe,EAAE,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC7C,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,eAAe,CACb;YACE,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC;YAC1B,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC;YACxC,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;YACnD,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;SAC5D,EACD,GAAG,CACJ,CAAC;IAEN,QAAQ,CAAC,GAAG,CACV,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,YAAY,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,iBAAiB,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,CACnL,CAAC;IACF,QAAQ,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEjE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,QAAQ,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;QACtE,OAAO;IACT,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7E,MAAM,WAAW,GACf,EAAE,KAAK,SAAS;QACd,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,WAAW,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,SAAS,EAAE,EAAE,EAAE,CAAC;IAExF,MAAM,UAAU,GAAgC;QAC9C,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,EAAE,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE;QACnD,IAAI,EAAE,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE;QAClD,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QACrD,SAAS,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE;KACjF,CAAC;IAEF,QAAQ,CAAC,GAAG,CAAC,UAAU,QAAQ,CAAC,EAAE,KAAK,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC;IAE3D,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,YAAY,CAC/C;QACE,MAAM,EAAE,aAAa;QACrB,IAAI;QACJ,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,yBAAyB,CAAC;QACrG,KAAK,EAAE;YACL,UAAU;YACV,MAAM;YACN,KAAK,EAAE;gBACL,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;gBAC/B,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,SAAS,EAAE,IAAI,CAAC,SAAS;aAC1B;YACD,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACtC;QACD,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;YACrB,IAAI,OAAO,GAAG,CAAC;gBAAE,QAAQ,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;QAC3F,CAAC;KACF,EACD,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAC7C,CAAC;IAEF,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC5F,QAAQ,CAAC,GAAG,CACV,KAAK,OAAO,MAAM,QAAQ,CAAC,KAAK,CAAC,MAAM,WAAW,QAAQ,CAAC,KAAK,CAAC,MAAM,WAAW,QAAQ,CAAC,KAAK,CAAC,MAAM,SAAS,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAChK,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Terminal } from "../terminal.js";
2
+ export declare const USAGE = "pr-lens comment --graph <graph.json> --manifest <manifest.json> [options]\n\nComposes the pull request comment: the diagrams as light/dark <picture> pairs,\nthe headline numbers, and the drill-down tree. It posts nothing \u2014 the markdown\ngoes to stdout, or to a file, for whatever does the posting.\n\n --graph <file> the document that was rendered \u2014 the one the render\n wrote beside the manifest, not the one it read\n --manifest <file> what the render produced (required)\n --asset-base-url <url> where the rendered SVGs are published, when the\n manifest records local paths\n --config <file> read 'branding' from a repository config\n --no-branding leave off the PR Lens footer\n --print-marker print the hidden marker that identifies the\n comment, and nothing else\n -o, --out <file> write the markdown here instead of stdout";
3
+ export declare const commentCommand: (args: readonly string[], terminal: Terminal) => Promise<void>;
4
+ //# sourceMappingURL=comment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment.d.ts","sourceRoot":"","sources":["../../src/commands/comment.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,eAAO,MAAM,KAAK,0/BAesD,CAAC;AAEzE,eAAO,MAAM,cAAc,SAAgB,SAAS,MAAM,EAAE,YAAY,QAAQ,KAAG,OAAO,CAAC,IAAI,CAkD9F,CAAC"}
@@ -0,0 +1,63 @@
1
+ import { graphContentHash } from "@coldtea/pr-lens-renderer";
2
+ import { parseOptions, readBoolean, readString } from "../args.js";
3
+ import { composeComment, COMMENT_MARKER } from "../comment.js";
4
+ import { loadConfig } from "../config-file.js";
5
+ import { readGraphDoc, readRenderManifest } from "../document.js";
6
+ import { usageError } from "../errors.js";
7
+ import { writeTextFile } from "../io.js";
8
+ export const USAGE = `pr-lens comment --graph <graph.json> --manifest <manifest.json> [options]
9
+
10
+ Composes the pull request comment: the diagrams as light/dark <picture> pairs,
11
+ the headline numbers, and the drill-down tree. It posts nothing — the markdown
12
+ goes to stdout, or to a file, for whatever does the posting.
13
+
14
+ --graph <file> the document that was rendered — the one the render
15
+ wrote beside the manifest, not the one it read
16
+ --manifest <file> what the render produced (required)
17
+ --asset-base-url <url> where the rendered SVGs are published, when the
18
+ manifest records local paths
19
+ --config <file> read 'branding' from a repository config
20
+ --no-branding leave off the PR Lens footer
21
+ --print-marker print the hidden marker that identifies the
22
+ comment, and nothing else
23
+ -o, --out <file> write the markdown here instead of stdout`;
24
+ export const commentCommand = async (args, terminal) => {
25
+ const { values, positionals } = parseOptions(args, {
26
+ graph: { type: "string" },
27
+ manifest: { type: "string" },
28
+ "asset-base-url": { type: "string" },
29
+ config: { type: "string" },
30
+ "no-branding": { type: "boolean" },
31
+ "print-marker": { type: "boolean" },
32
+ out: { type: "string", short: "o" },
33
+ });
34
+ if (positionals.length > 0)
35
+ throw usageError(`comment takes no positional arguments, got ${positionals.join(" ")}`);
36
+ if (readBoolean(values["print-marker"])) {
37
+ terminal.out(COMMENT_MARKER);
38
+ return;
39
+ }
40
+ const graphPath = readString(values.graph, "graph");
41
+ const manifestPath = readString(values.manifest, "manifest");
42
+ if (graphPath === undefined || manifestPath === undefined)
43
+ throw usageError("--graph and --manifest are both required");
44
+ const configPath = readString(values.config, "config");
45
+ const configured = configPath === undefined ? undefined : await loadConfig(configPath);
46
+ const graph = await readGraphDoc(graphPath);
47
+ const manifest = await readRenderManifest(manifestPath);
48
+ if (graphContentHash(graph) !== manifest.graph.contentHash)
49
+ throw usageError(`${graphPath} is not the document ${manifestPath} describes`, "corrections change what the diagrams show, so a comment built from a different document would announce sections that were never drawn. Pass the drawn.graph.json the render wrote beside the manifest");
50
+ const body = composeComment({
51
+ graph,
52
+ manifest,
53
+ assetBaseUrl: readString(values["asset-base-url"], "asset-base-url"),
54
+ branding: readBoolean(values["no-branding"]) ? false : (configured?.config.branding ?? true),
55
+ });
56
+ const out = readString(values.out, "out");
57
+ if (out === undefined) {
58
+ terminal.out(body.trimEnd());
59
+ return;
60
+ }
61
+ terminal.err(`✓ ${await writeTextFile(out, body)}`);
62
+ };
63
+ //# sourceMappingURL=comment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment.js","sourceRoot":"","sources":["../../src/commands/comment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Terminal } from "../terminal.js";
2
+ export declare const USAGE = "pr-lens export <graph.json> [options]\n\nTurns a pull-request document into the stored map of the system once that pull\nrequest has merged: elements the change deletes are dropped, the rest stops\nbeing annotated, and the result is stamped with the single commit it reflects.\n\nThe map is a snapshot, not a source of truth \u2014 nothing reads it back into the\npipeline. Committing it gives a repository something to read, to diff, and to\nhand an agent.\n\n -o, --out <file> where to write it (default .github/pr-lens.map.json)\n --id <id> map id, so a patch can name it (default <owner>/<name>)\n --sha <sha> the commit it reflects, in full (default the document's head)";
3
+ export declare const exportCommand: (args: readonly string[], terminal: Terminal) => Promise<void>;
4
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAI/C,eAAO,MAAM,KAAK,6rBAYiE,CAAC;AAEpF,eAAO,MAAM,aAAa,SAAgB,SAAS,MAAM,EAAE,YAAY,QAAQ,KAAG,OAAO,CAAC,IAAI,CAqC7F,CAAC"}