co-maintainer 0.4.0-beta.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.
- package/LICENSE +21 -0
- package/README.md +105 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +9 -0
- package/dist/mod.d.ts +4 -0
- package/dist/mod.js +2 -0
- package/dist/package.json +54 -0
- package/dist/src/ai/batch.d.ts +16 -0
- package/dist/src/ai/batch.js +117 -0
- package/dist/src/ai/fake.d.ts +7 -0
- package/dist/src/ai/fake.js +40 -0
- package/dist/src/ai/hetzner.d.ts +16 -0
- package/dist/src/ai/hetzner.js +69 -0
- package/dist/src/ai/mermaid.d.ts +27 -0
- package/dist/src/ai/mermaid.js +457 -0
- package/dist/src/ai/mermaid_loop.d.ts +12 -0
- package/dist/src/ai/mermaid_loop.js +100 -0
- package/dist/src/ai/openrouter.d.ts +9 -0
- package/dist/src/ai/openrouter.js +29 -0
- package/dist/src/ai/provider.d.ts +4 -0
- package/dist/src/ai/provider.js +63 -0
- package/dist/src/cli/args.d.ts +5 -0
- package/dist/src/cli/args.js +252 -0
- package/dist/src/cli/commands/probe.d.ts +2 -0
- package/dist/src/cli/commands/probe.js +122 -0
- package/dist/src/cli/commands/review.d.ts +3 -0
- package/dist/src/cli/commands/review.js +84 -0
- package/dist/src/cli/commands/serve.d.ts +18 -0
- package/dist/src/cli/commands/serve.js +183 -0
- package/dist/src/cli/commands/set.d.ts +7 -0
- package/dist/src/cli/commands/set.js +171 -0
- package/dist/src/cli/main.d.ts +1 -0
- package/dist/src/cli/main.js +27 -0
- package/dist/src/cli/prompt.d.ts +4 -0
- package/dist/src/cli/prompt.js +26 -0
- package/dist/src/cli/review_args.d.ts +28 -0
- package/dist/src/cli/review_args.js +84 -0
- package/dist/src/cli/review_output.d.ts +2 -0
- package/dist/src/cli/review_output.js +10 -0
- package/dist/src/cli/review_result.d.ts +81 -0
- package/dist/src/cli/review_result.js +281 -0
- package/dist/src/config.d.ts +108 -0
- package/dist/src/config.js +138 -0
- package/dist/src/git/default_branch.d.ts +5 -0
- package/dist/src/git/default_branch.js +22 -0
- package/dist/src/github/app.d.ts +43 -0
- package/dist/src/github/app.js +120 -0
- package/dist/src/github/client.d.ts +17 -0
- package/dist/src/github/client.js +66 -0
- package/dist/src/github/collect.d.ts +7 -0
- package/dist/src/github/collect.js +368 -0
- package/dist/src/github/gh.d.ts +8 -0
- package/dist/src/github/gh.js +63 -0
- package/dist/src/github/jwt.d.ts +12 -0
- package/dist/src/github/jwt.js +84 -0
- package/dist/src/github/oauth.d.ts +9 -0
- package/dist/src/github/oauth.js +51 -0
- package/dist/src/github/pat.d.ts +10 -0
- package/dist/src/github/pat.js +60 -0
- package/dist/src/knowledge/facts.d.ts +3 -0
- package/dist/src/knowledge/facts.js +325 -0
- package/dist/src/knowledge/guide.d.ts +6 -0
- package/dist/src/knowledge/guide.js +82 -0
- package/dist/src/knowledge/probe.d.ts +12 -0
- package/dist/src/knowledge/probe.js +144 -0
- package/dist/src/knowledge/sections.d.ts +2 -0
- package/dist/src/knowledge/sections.js +13 -0
- package/dist/src/knowledge/skill.d.ts +10 -0
- package/dist/src/knowledge/skill.js +106 -0
- package/dist/src/knowledge/synthesis.d.ts +7 -0
- package/dist/src/knowledge/synthesis.js +315 -0
- package/dist/src/knowledge/types.d.ts +49 -0
- package/dist/src/knowledge/types.js +1 -0
- package/dist/src/knowledge/validate.d.ts +6 -0
- package/dist/src/knowledge/validate.js +134 -0
- package/dist/src/local/carry_over_store.d.ts +18 -0
- package/dist/src/local/carry_over_store.js +40 -0
- package/dist/src/local/codegraph_exclude.d.ts +3 -0
- package/dist/src/local/codegraph_exclude.js +26 -0
- package/dist/src/local/codegraph_prepare.d.ts +17 -0
- package/dist/src/local/codegraph_prepare.js +51 -0
- package/dist/src/local/git_ops.d.ts +12 -0
- package/dist/src/local/git_ops.js +98 -0
- package/dist/src/local/git_parse.d.ts +27 -0
- package/dist/src/local/git_parse.js +131 -0
- package/dist/src/local/git_revision.d.ts +15 -0
- package/dist/src/local/git_revision.js +141 -0
- package/dist/src/local/git_untracked.d.ts +21 -0
- package/dist/src/local/git_untracked.js +79 -0
- package/dist/src/local/review_local.d.ts +4 -0
- package/dist/src/local/review_local.js +273 -0
- package/dist/src/local/review_lock.d.ts +7 -0
- package/dist/src/local/review_lock.js +45 -0
- package/dist/src/pr/checkout.d.ts +25 -0
- package/dist/src/pr/checkout.js +136 -0
- package/dist/src/pr/codegraph_tool_args.d.ts +8 -0
- package/dist/src/pr/codegraph_tool_args.js +34 -0
- package/dist/src/pr/codegraph_tools.d.ts +15 -0
- package/dist/src/pr/codegraph_tools.js +408 -0
- package/dist/src/pr/diff_summary.d.ts +6 -0
- package/dist/src/pr/diff_summary.js +52 -0
- package/dist/src/pr/findings.d.ts +14 -0
- package/dist/src/pr/findings.js +94 -0
- package/dist/src/pr/github_revision.d.ts +4 -0
- package/dist/src/pr/github_revision.js +39 -0
- package/dist/src/pr/hunks.d.ts +18 -0
- package/dist/src/pr/hunks.js +73 -0
- package/dist/src/pr/reviewer.d.ts +40 -0
- package/dist/src/pr/reviewer.js +582 -0
- package/dist/src/pr/rounds.d.ts +17 -0
- package/dist/src/pr/rounds.js +43 -0
- package/dist/src/pr/scope.d.ts +35 -0
- package/dist/src/pr/scope.js +84 -0
- package/dist/src/pr/snapshot.d.ts +11 -0
- package/dist/src/pr/snapshot.js +1 -0
- package/dist/src/pr/suggestion.d.ts +17 -0
- package/dist/src/pr/suggestion.js +70 -0
- package/dist/src/remote/client.d.ts +4 -0
- package/dist/src/remote/client.js +199 -0
- package/dist/src/remote/client_tools.d.ts +13 -0
- package/dist/src/remote/client_tools.js +30 -0
- package/dist/src/remote/fixtures.d.ts +1 -0
- package/dist/src/remote/fixtures.js +30 -0
- package/dist/src/remote/revision_from_submit.d.ts +2 -0
- package/dist/src/remote/revision_from_submit.js +26 -0
- package/dist/src/remote/schema.d.ts +14 -0
- package/dist/src/remote/schema.js +30 -0
- package/dist/src/remote/server/body.d.ts +18 -0
- package/dist/src/remote/server/body.js +73 -0
- package/dist/src/remote/server/routes.d.ts +1 -0
- package/dist/src/remote/server/routes.js +150 -0
- package/dist/src/remote/server/sessions.d.ts +16 -0
- package/dist/src/remote/server/sessions.js +48 -0
- package/dist/src/remote/server/sync.d.ts +3 -0
- package/dist/src/remote/server/sync.js +90 -0
- package/dist/src/remote/tool_bridge.d.ts +15 -0
- package/dist/src/remote/tool_bridge.js +84 -0
- package/dist/src/remote/validate.d.ts +8 -0
- package/dist/src/remote/validate.js +248 -0
- package/dist/src/review/carry_over.d.ts +63 -0
- package/dist/src/review/carry_over.js +372 -0
- package/dist/src/review/engine.d.ts +13 -0
- package/dist/src/review/engine.js +4 -0
- package/dist/src/review/guides.d.ts +12 -0
- package/dist/src/review/guides.js +44 -0
- package/dist/src/review/revision.d.ts +26 -0
- package/dist/src/review/revision.js +57 -0
- package/dist/src/server/api/activity.d.ts +1 -0
- package/dist/src/server/api/activity.js +12 -0
- package/dist/src/server/api/analytics.d.ts +1 -0
- package/dist/src/server/api/analytics.js +9 -0
- package/dist/src/server/api/installations.d.ts +4 -0
- package/dist/src/server/api/installations.js +24 -0
- package/dist/src/server/api/jobs.d.ts +1 -0
- package/dist/src/server/api/jobs.js +86 -0
- package/dist/src/server/api/json_body.d.ts +1 -0
- package/dist/src/server/api/json_body.js +14 -0
- package/dist/src/server/api/remote_tokens.d.ts +1 -0
- package/dist/src/server/api/remote_tokens.js +71 -0
- package/dist/src/server/api/repos.d.ts +4 -0
- package/dist/src/server/api/repos.js +136 -0
- package/dist/src/server/api/settings.d.ts +1 -0
- package/dist/src/server/api/settings.js +210 -0
- package/dist/src/server/app.d.ts +27 -0
- package/dist/src/server/app.js +147 -0
- package/dist/src/server/assets.d.ts +3 -0
- package/dist/src/server/assets.js +21 -0
- package/dist/src/server/auth.d.ts +44 -0
- package/dist/src/server/auth.js +188 -0
- package/dist/src/server/errors.d.ts +8 -0
- package/dist/src/server/errors.js +10 -0
- package/dist/src/server/http.d.ts +8 -0
- package/dist/src/server/http.js +117 -0
- package/dist/src/server/logo.d.ts +1 -0
- package/dist/src/server/logo.js +2 -0
- package/dist/src/server/pages/activity.d.ts +4 -0
- package/dist/src/server/pages/activity.js +200 -0
- package/dist/src/server/pages/add_repo.d.ts +9 -0
- package/dist/src/server/pages/add_repo.js +56 -0
- package/dist/src/server/pages/analytics.d.ts +2 -0
- package/dist/src/server/pages/analytics.js +193 -0
- package/dist/src/server/pages/client.d.ts +2 -0
- package/dist/src/server/pages/client.js +2 -0
- package/dist/src/server/pages/home.d.ts +16 -0
- package/dist/src/server/pages/home.js +87 -0
- package/dist/src/server/pages/knowledge.d.ts +2 -0
- package/dist/src/server/pages/knowledge.js +64 -0
- package/dist/src/server/pages/layout.d.ts +32 -0
- package/dist/src/server/pages/layout.js +230 -0
- package/dist/src/server/pages/pr.d.ts +2 -0
- package/dist/src/server/pages/pr.js +109 -0
- package/dist/src/server/pages/repo.d.ts +2 -0
- package/dist/src/server/pages/repo.js +92 -0
- package/dist/src/server/pages/repo_prs.d.ts +2 -0
- package/dist/src/server/pages/repo_prs.js +75 -0
- package/dist/src/server/pages/repo_remote.d.ts +2 -0
- package/dist/src/server/pages/repo_remote.js +38 -0
- package/dist/src/server/pages/repo_settings.d.ts +3 -0
- package/dist/src/server/pages/repo_settings.js +127 -0
- package/dist/src/server/pages/router.d.ts +17 -0
- package/dist/src/server/pages/router.js +312 -0
- package/dist/src/server/pages/settings.d.ts +2 -0
- package/dist/src/server/pages/settings.js +337 -0
- package/dist/src/server/pages/setup.d.ts +5 -0
- package/dist/src/server/pages/setup.js +38 -0
- package/dist/src/server/pages/styles.d.ts +2 -0
- package/dist/src/server/pages/styles.js +2 -0
- package/dist/src/server/webhook/index.d.ts +1 -0
- package/dist/src/server/webhook/index.js +64 -0
- package/dist/src/server/webhook/signature.d.ts +7 -0
- package/dist/src/server/webhook/signature.js +41 -0
- package/dist/src/services/credentials.d.ts +19 -0
- package/dist/src/services/credentials.js +146 -0
- package/dist/src/services/dashboard.d.ts +165 -0
- package/dist/src/services/dashboard.js +200 -0
- package/dist/src/services/drift.d.ts +13 -0
- package/dist/src/services/drift.js +76 -0
- package/dist/src/services/jobs.d.ts +34 -0
- package/dist/src/services/jobs.js +222 -0
- package/dist/src/services/remote_review.d.ts +10 -0
- package/dist/src/services/remote_review.js +274 -0
- package/dist/src/services/remote_review_abort.d.ts +3 -0
- package/dist/src/services/remote_review_abort.js +11 -0
- package/dist/src/services/remote_token_jobs.d.ts +1 -0
- package/dist/src/services/remote_token_jobs.js +20 -0
- package/dist/src/services/remote_tokens.d.ts +13 -0
- package/dist/src/services/remote_tokens.js +57 -0
- package/dist/src/services/replies.d.ts +7 -0
- package/dist/src/services/replies.js +248 -0
- package/dist/src/services/review.d.ts +35 -0
- package/dist/src/services/review.js +671 -0
- package/dist/src/services/setup.d.ts +29 -0
- package/dist/src/services/setup.js +364 -0
- package/dist/src/services/webhook.d.ts +22 -0
- package/dist/src/services/webhook.js +401 -0
- package/dist/src/store/app_db.d.ts +10 -0
- package/dist/src/store/app_db.js +85 -0
- package/dist/src/store/cache_db.d.ts +4 -0
- package/dist/src/store/cache_db.js +63 -0
- package/dist/src/store/deliveries.d.ts +12 -0
- package/dist/src/store/deliveries.js +23 -0
- package/dist/src/store/drift.d.ts +4 -0
- package/dist/src/store/drift.js +22 -0
- package/dist/src/store/findings.d.ts +31 -0
- package/dist/src/store/findings.js +64 -0
- package/dist/src/store/installations.d.ts +9 -0
- package/dist/src/store/installations.js +35 -0
- package/dist/src/store/job_logs.d.ts +5 -0
- package/dist/src/store/job_logs.js +17 -0
- package/dist/src/store/jobs.d.ts +27 -0
- package/dist/src/store/jobs.js +86 -0
- package/dist/src/store/migrations.d.ts +5 -0
- package/dist/src/store/migrations.js +258 -0
- package/dist/src/store/remote_review_inputs.d.ts +11 -0
- package/dist/src/store/remote_review_inputs.js +25 -0
- package/dist/src/store/remote_tokens.d.ts +10 -0
- package/dist/src/store/remote_tokens.js +45 -0
- package/dist/src/store/replies.d.ts +24 -0
- package/dist/src/store/replies.js +79 -0
- package/dist/src/store/repos.d.ts +11 -0
- package/dist/src/store/repos.js +59 -0
- package/dist/src/store/reviews.d.ts +86 -0
- package/dist/src/store/reviews.js +220 -0
- package/dist/src/store/rows.d.ts +179 -0
- package/dist/src/store/rows.js +4 -0
- package/dist/src/store/sessions.d.ts +8 -0
- package/dist/src/store/sessions.js +34 -0
- package/dist/src/store/skill_state.d.ts +3 -0
- package/dist/src/store/skill_state.js +24 -0
- package/dist/src/store/sqlite.d.ts +39 -0
- package/dist/src/store/sqlite.js +77 -0
- package/dist/src/store/subjects.d.ts +15 -0
- package/dist/src/store/subjects.js +78 -0
- package/dist/src/tools/codegraph.d.ts +58 -0
- package/dist/src/tools/codegraph.js +165 -0
- package/dist/src/tools/codegraph_exec.d.ts +13 -0
- package/dist/src/tools/codegraph_exec.js +66 -0
- package/dist/src/types.d.ts +89 -0
- package/dist/src/types.js +1 -0
- package/dist/src/util/atomic.d.ts +4 -0
- package/dist/src/util/atomic.js +78 -0
- package/dist/src/util/keyed_lock.d.ts +3 -0
- package/dist/src/util/keyed_lock.js +33 -0
- package/dist/src/util/log.d.ts +11 -0
- package/dist/src/util/log.js +42 -0
- package/dist/src/util/redact.d.ts +5 -0
- package/dist/src/util/redact.js +30 -0
- package/dist/src/util/runtime.d.ts +90 -0
- package/dist/src/util/runtime.js +206 -0
- package/dist/src/util/time.d.ts +9 -0
- package/dist/src/util/time.js +36 -0
- package/dist/src/version.d.ts +1 -0
- package/dist/src/version.js +5 -0
- package/package.json +54 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const FILE_LINE = /(?<path>(?:[\w.-]+\/)*[\w.-]+\.[A-Za-z0-9]+):(?<from>\d+)(?:-(?<to>\d+))?/g;
|
|
2
|
+
const NEW_HEADING = /^\[(?<severity>P[0-3])\s*·\s*(?<impact>blocking|non-blocking)\]\s+(?<path>.+?)\s+—\s+(?<symbol>.+)$/;
|
|
3
|
+
function uncode(value) {
|
|
4
|
+
return value.trim().replace(/^`|`$/g, "").trim();
|
|
5
|
+
}
|
|
6
|
+
function location(block) {
|
|
7
|
+
const match = block.match(/^\s*(?:Location|File)\s*:\s*`?(.+?)`?\s*$/im);
|
|
8
|
+
const source = match?.[1] ?? block;
|
|
9
|
+
const found = [...source.matchAll(FILE_LINE)][0];
|
|
10
|
+
if (!found?.groups?.path || !found.groups.from)
|
|
11
|
+
return undefined;
|
|
12
|
+
const from = Number(found.groups.from);
|
|
13
|
+
return {
|
|
14
|
+
path: found.groups.path,
|
|
15
|
+
from,
|
|
16
|
+
to: found.groups.to ? Number(found.groups.to) : from,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function bodyWithoutLocation(block) {
|
|
20
|
+
return block.replace(/^\s*(?:Location|File)\s*:\s*`?.+?`?\s*$/im, "").trim();
|
|
21
|
+
}
|
|
22
|
+
function newFinding(header, block) {
|
|
23
|
+
const meta = NEW_HEADING.exec(header);
|
|
24
|
+
if (!meta?.groups)
|
|
25
|
+
return undefined;
|
|
26
|
+
const at = location(block);
|
|
27
|
+
if (!at)
|
|
28
|
+
return undefined;
|
|
29
|
+
const path = uncode(meta.groups.path);
|
|
30
|
+
const symbol = uncode(meta.groups.symbol);
|
|
31
|
+
const severity = meta.groups.severity;
|
|
32
|
+
const impact = meta.groups.impact;
|
|
33
|
+
const excerpt = bodyWithoutLocation(block);
|
|
34
|
+
const summary = excerpt.split(/\r?\n/).find((line) => line.trim()) ?? "";
|
|
35
|
+
return {
|
|
36
|
+
...at,
|
|
37
|
+
path,
|
|
38
|
+
heading: `[${severity} · ${impact}] \`${path}\` — \`${symbol}\``,
|
|
39
|
+
excerpt,
|
|
40
|
+
severity,
|
|
41
|
+
blocking: impact === "blocking",
|
|
42
|
+
symbol,
|
|
43
|
+
summary,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export function parseFindings(markdown) {
|
|
47
|
+
const previousHeading = markdown.search(/^## Previous findings\b/im);
|
|
48
|
+
const withoutVerdicts = previousHeading === -1 ? markdown : markdown.slice(0, previousHeading);
|
|
49
|
+
const findingsHeading = withoutVerdicts.search(/^## Findings\b/m);
|
|
50
|
+
const body = findingsHeading === -1
|
|
51
|
+
? withoutVerdicts
|
|
52
|
+
: withoutVerdicts.slice(findingsHeading);
|
|
53
|
+
if (/No actionable findings/i.test(body))
|
|
54
|
+
return [];
|
|
55
|
+
const findings = [];
|
|
56
|
+
const headings = [...body.matchAll(/^###\s+(.+)$/gm)];
|
|
57
|
+
for (let index = 0; index < headings.length; index++) {
|
|
58
|
+
const current = headings[index];
|
|
59
|
+
const start = (current.index ?? 0) + current[0].length;
|
|
60
|
+
const end = headings[index + 1]?.index ?? body.length;
|
|
61
|
+
const parsed = newFinding(current[1].trim(), body.slice(start, end));
|
|
62
|
+
if (parsed)
|
|
63
|
+
findings.push(parsed);
|
|
64
|
+
}
|
|
65
|
+
if (findings.length > 0)
|
|
66
|
+
return findings;
|
|
67
|
+
const seen = new Set();
|
|
68
|
+
for (const lined of body.matchAll(FILE_LINE)) {
|
|
69
|
+
if (!lined.groups?.path || !lined.groups.from)
|
|
70
|
+
continue;
|
|
71
|
+
const lineStart = body.lastIndexOf("\n", lined.index ?? 0) + 1;
|
|
72
|
+
if (/^\s*Suggestion\s*:/.test(body.slice(lineStart, lined.index)))
|
|
73
|
+
continue;
|
|
74
|
+
const from = Number(lined.groups.from);
|
|
75
|
+
const to = lined.groups.to ? Number(lined.groups.to) : from;
|
|
76
|
+
const key = `${lined.groups.path}:${from}-${to}`;
|
|
77
|
+
if (seen.has(key))
|
|
78
|
+
continue;
|
|
79
|
+
seen.add(key);
|
|
80
|
+
const at = lined.index ?? 0;
|
|
81
|
+
const headingStart = body.lastIndexOf("\n###", at);
|
|
82
|
+
const headingLine = headingStart >= 0
|
|
83
|
+
? body.slice(headingStart, body.indexOf("\n", headingStart + 1)).trim()
|
|
84
|
+
: "";
|
|
85
|
+
findings.push({
|
|
86
|
+
path: lined.groups.path,
|
|
87
|
+
from,
|
|
88
|
+
to,
|
|
89
|
+
heading: headingLine.replace(/^###\s*/, ""),
|
|
90
|
+
excerpt: body.slice(Math.max(0, at - 80), at + 200).trim(),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return findings;
|
|
94
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Json } from "../types.ts";
|
|
2
|
+
import { type Revision, type RevisionFile } from "../review/revision.ts";
|
|
3
|
+
export declare function githubFileToRevisionFile(file: Json): RevisionFile;
|
|
4
|
+
export declare function githubPullRequestToRevision(files: Json[], pr: Json, baseLabel: string): Revision;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { normalizePath, } from "../review/revision.js";
|
|
2
|
+
function githubStatus(raw) {
|
|
3
|
+
if (raw === "added")
|
|
4
|
+
return "added";
|
|
5
|
+
if (raw === "removed")
|
|
6
|
+
return "removed";
|
|
7
|
+
if (raw.startsWith("renamed"))
|
|
8
|
+
return "renamed";
|
|
9
|
+
return "modified";
|
|
10
|
+
}
|
|
11
|
+
export function githubFileToRevisionFile(file) {
|
|
12
|
+
const path = normalizePath(String(file.filename ?? ""));
|
|
13
|
+
const status = githubStatus(String(file.status ?? "modified"));
|
|
14
|
+
const additions = Number(file.additions ?? 0);
|
|
15
|
+
const deletions = Number(file.deletions ?? 0);
|
|
16
|
+
const patch = String(file.patch ?? "");
|
|
17
|
+
// GitHub omits large text patches; do not treat that as binary (plan §10.7).
|
|
18
|
+
const binary = false;
|
|
19
|
+
return {
|
|
20
|
+
path,
|
|
21
|
+
previousPath: file.previous_filename
|
|
22
|
+
? normalizePath(String(file.previous_filename))
|
|
23
|
+
: null,
|
|
24
|
+
status,
|
|
25
|
+
binary,
|
|
26
|
+
additions,
|
|
27
|
+
deletions,
|
|
28
|
+
patch,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function githubPullRequestToRevision(files, pr, baseLabel) {
|
|
32
|
+
return {
|
|
33
|
+
files: files.map((file) => githubFileToRevisionFile(file)),
|
|
34
|
+
title: String(pr.title ?? ""),
|
|
35
|
+
description: String(pr.body ?? ""),
|
|
36
|
+
baseLabel,
|
|
37
|
+
producer: "github",
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type Anchor = {
|
|
2
|
+
line: number;
|
|
3
|
+
start_line?: number;
|
|
4
|
+
};
|
|
5
|
+
/** New file line ranges each hunk covers. A hunk with a zero count (a
|
|
6
|
+
* deleted file) covers nothing on the RIGHT side. */
|
|
7
|
+
export declare function rightHunks(patch: string): [number, number][];
|
|
8
|
+
/** Where GitHub will accept a review comment for this span. The whole span
|
|
9
|
+
* when one hunk holds it, otherwise one end of it, otherwise nowhere. */
|
|
10
|
+
export declare function anchorFor(patch: string, from: number, to: number): Anchor | undefined;
|
|
11
|
+
/** Prefixes each diff line with its line number in the new file, so the
|
|
12
|
+
* reviewer copies Location numbers instead of counting from the @@ header.
|
|
13
|
+
* Removed lines get no number because GitHub cannot anchor a RIGHT side
|
|
14
|
+
* comment to them. */
|
|
15
|
+
export declare function numberPatch(patch: string): string;
|
|
16
|
+
/** The new file's text for every line the patch shows, without the diff
|
|
17
|
+
* prefix. */
|
|
18
|
+
export declare function rightLines(patch: string): Map<number, string>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const HUNK = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/;
|
|
2
|
+
const GUTTER = 6;
|
|
3
|
+
/** New file line ranges each hunk covers. A hunk with a zero count (a
|
|
4
|
+
* deleted file) covers nothing on the RIGHT side. */
|
|
5
|
+
export function rightHunks(patch) {
|
|
6
|
+
const ranges = [];
|
|
7
|
+
for (const match of patch.matchAll(new RegExp(HUNK.source, "gm"))) {
|
|
8
|
+
const start = Number(match[1]);
|
|
9
|
+
const count = match[2] === undefined ? 1 : Number(match[2]);
|
|
10
|
+
if (count > 0)
|
|
11
|
+
ranges.push([start, start + count - 1]);
|
|
12
|
+
}
|
|
13
|
+
return ranges;
|
|
14
|
+
}
|
|
15
|
+
/** Where GitHub will accept a review comment for this span. The whole span
|
|
16
|
+
* when one hunk holds it, otherwise one end of it, otherwise nowhere. */
|
|
17
|
+
export function anchorFor(patch, from, to) {
|
|
18
|
+
const low = Math.min(from, to);
|
|
19
|
+
const high = Math.max(from, to);
|
|
20
|
+
// GitHub withholds the patch for very large files, so there is nothing to
|
|
21
|
+
// check against. Keep the single line anchor reviews always used.
|
|
22
|
+
if (patch === "")
|
|
23
|
+
return { line: high };
|
|
24
|
+
const hunks = rightHunks(patch);
|
|
25
|
+
const inside = (a, b) => hunks.some(([start, end]) => a >= start && b <= end);
|
|
26
|
+
if (low < high && inside(low, high))
|
|
27
|
+
return { start_line: low, line: high };
|
|
28
|
+
if (inside(high, high))
|
|
29
|
+
return { line: high };
|
|
30
|
+
if (inside(low, low))
|
|
31
|
+
return { line: low };
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
function* walk(patch) {
|
|
35
|
+
let next = 0;
|
|
36
|
+
for (const text of patch.split("\n")) {
|
|
37
|
+
const hunk = HUNK.exec(text);
|
|
38
|
+
if (hunk) {
|
|
39
|
+
next = Number(hunk[1]);
|
|
40
|
+
yield { text, inHunk: false };
|
|
41
|
+
}
|
|
42
|
+
else if (next === 0 || text === "") {
|
|
43
|
+
yield { text, inHunk: false };
|
|
44
|
+
}
|
|
45
|
+
else if (text.startsWith("-") || text.startsWith("\\")) {
|
|
46
|
+
yield { text, inHunk: true };
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
yield { text, number: next++, inHunk: true };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Prefixes each diff line with its line number in the new file, so the
|
|
54
|
+
* reviewer copies Location numbers instead of counting from the @@ header.
|
|
55
|
+
* Removed lines get no number because GitHub cannot anchor a RIGHT side
|
|
56
|
+
* comment to them. */
|
|
57
|
+
export function numberPatch(patch) {
|
|
58
|
+
return [...walk(patch)]
|
|
59
|
+
.map(({ text, number, inHunk }) => !inHunk
|
|
60
|
+
? text
|
|
61
|
+
: `${number === undefined ? "".padStart(GUTTER) : String(number).padStart(GUTTER)} ${text}`)
|
|
62
|
+
.join("\n");
|
|
63
|
+
}
|
|
64
|
+
/** The new file's text for every line the patch shows, without the diff
|
|
65
|
+
* prefix. */
|
|
66
|
+
export function rightLines(patch) {
|
|
67
|
+
const lines = new Map();
|
|
68
|
+
for (const { text, number } of walk(patch)) {
|
|
69
|
+
if (number !== undefined)
|
|
70
|
+
lines.set(number, text.slice(1));
|
|
71
|
+
}
|
|
72
|
+
return lines;
|
|
73
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type ToolHandler } from "../ai/mermaid_loop.ts";
|
|
2
|
+
import type { Revision } from "../review/revision.ts";
|
|
3
|
+
import type { Snapshot } from "./snapshot.ts";
|
|
4
|
+
import type { AiProvider, AiResponse, GitHubClient, Json, Options } from "../types.ts";
|
|
5
|
+
type UsageSink = (response: AiResponse) => Promise<void>;
|
|
6
|
+
type ProgressSink = (message: string) => void;
|
|
7
|
+
export type ReviewExtras = {
|
|
8
|
+
carryPrompt?: string;
|
|
9
|
+
unchangedPaths?: string[];
|
|
10
|
+
prepareCodegraphTools?: () => Promise<ToolHandler[]>;
|
|
11
|
+
};
|
|
12
|
+
export declare const MERMAID_GUIDANCE = "Mermaid selection and minimal syntax:\nflowchart = decisions, branches, pipelines, and fallback paths;\nswimlane-beta = work crossing owners, actors, services, teams, or layers;\nsequenceDiagram = ordered calls, webhooks, retries, responses, and timing;\nclassDiagram = class, interface, type, inheritance, or composition relationships;\nstateDiagram-v2 = lifecycle and state transitions;\nerDiagram = database entities, keys, and cardinality;\nrequirementDiagram = requirements linked to tests or implementation;\nusecase-beta = actors and system capabilities;\nC4Context = users, systems, boundaries, and integrations;\nzenuml = compact nested call sequences;\npacket = binary fields, bit ranges, and protocol layout;\narchitecture-beta = services, containers, storage, and deployment topology;\neventmodeling = commands, events, processors, read models, and timelines;\ntreeView-beta = directory, file, module, or dependency hierarchy.\nIf a diagram is useful, call read-mermaid-syntaxes before writing any Mermaid.\nRequest every type you need in a single call, because repeated tool rounds are\ncapped. Use the smallest type that matches the evidence.";
|
|
13
|
+
/** Without tool support the model cannot read the Mermaid syntax docs, so
|
|
14
|
+
* asking for a diagram only invites invented syntax. */
|
|
15
|
+
export declare const NO_DIAGRAM_RULES = "Do not use Mermaid or any other diagram. Explain with prose only.";
|
|
16
|
+
export declare function reviewSystemPrompt(diagrams: boolean): string;
|
|
17
|
+
/** Shared PR and local/remote workspace review instructions: confirm claims
|
|
18
|
+
* against the indexed graph, not only the diff slice. */
|
|
19
|
+
export declare const CODEGRAPH_DIFF_VERIFICATION = "Examine the changes line by line, not just file by file \u2014 a single file can\ncontain more than one independent defect, and a change that looks fine in\nisolation can be wrong once you trace what calls it or what else it affects.\nWhen a finding depends on behavior outside the changed lines, confirm it with\ncodegraph-node, codegraph-callers, codegraph-callees, codegraph-impact, and\ncodegraph-affected before reporting it. Drop or correct findings that only seem\nplausible from the diff but contradict unchanged callers, callees, or the same\npattern elsewhere in the repo. Use those tools to check blast radius and whether\na test reaches the path \u2014 do not guess coverage or impact from the diff alone\nwhen a tool can answer. A missing regression test is not a substitute for\nidentifying the concrete input or code path that misbehaves when you can.";
|
|
20
|
+
/** GitHub omits `patch` entirely for files it considers too large, and the file
|
|
21
|
+
* still appears in the compare response with only its counts. Rendering that as
|
|
22
|
+
* an empty body reads as "this file did not change", and a reviewer then
|
|
23
|
+
* reports the absence as a finding (a lockfile that was in fact regenerated,
|
|
24
|
+
* say). Say plainly that the hunks are missing, and mark a per-file truncation
|
|
25
|
+
* for the same reason. */
|
|
26
|
+
export declare function filePatch(file: Json): string;
|
|
27
|
+
export declare function clampToolRounds(totalDiffLines: number): number;
|
|
28
|
+
export declare function clampImproveMatrix(matrix: number): number;
|
|
29
|
+
export declare function readGuide(repo: string, name: string): Promise<string>;
|
|
30
|
+
export type { Snapshot };
|
|
31
|
+
export declare function reviewPullRequest(client: GitHubClient, options: Options, usage?: UsageSink, snapshot?: Snapshot, ai?: AiProvider, progress?: ProgressSink, extras?: ReviewExtras): Promise<AiResponse & {
|
|
32
|
+
visiblePaths: string[];
|
|
33
|
+
guideBuiltAt: string | null;
|
|
34
|
+
}>;
|
|
35
|
+
/** Local workspace review — same prompt loop as PR review without GitHub. */
|
|
36
|
+
export declare function reviewWorkspaceRevision(revision: Revision, options: Options, headSha: string, usage?: UsageSink, ai?: AiProvider, progress?: ProgressSink, extras?: ReviewExtras): Promise<AiResponse & {
|
|
37
|
+
visiblePaths: string[];
|
|
38
|
+
guideBuiltAt: string | null;
|
|
39
|
+
codegraphState: "used" | "disabled" | "unavailable";
|
|
40
|
+
}>;
|