bellwether 0.0.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 (77) hide show
  1. package/.claude-plugin/plugin.json +13 -0
  2. package/LICENSE +21 -0
  3. package/README.md +120 -0
  4. package/SKILL.md +92 -0
  5. package/dist/bin.d.ts +3 -0
  6. package/dist/bin.d.ts.map +1 -0
  7. package/dist/bin.js +17 -0
  8. package/dist/bin.js.map +1 -0
  9. package/dist/cli.d.ts +13 -0
  10. package/dist/cli.d.ts.map +1 -0
  11. package/dist/cli.js +36 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/commands/check.d.ts +191 -0
  14. package/dist/commands/check.d.ts.map +1 -0
  15. package/dist/commands/check.js +186 -0
  16. package/dist/commands/check.js.map +1 -0
  17. package/dist/commands/ci.d.ts +8 -0
  18. package/dist/commands/ci.d.ts.map +1 -0
  19. package/dist/commands/ci.js +28 -0
  20. package/dist/commands/ci.js.map +1 -0
  21. package/dist/commands/hook-add.d.ts +2 -0
  22. package/dist/commands/hook-add.d.ts.map +1 -0
  23. package/dist/commands/hook-add.js +97 -0
  24. package/dist/commands/hook-add.js.map +1 -0
  25. package/dist/commands/hook-check.d.ts +2 -0
  26. package/dist/commands/hook-check.d.ts.map +1 -0
  27. package/dist/commands/hook-check.js +29 -0
  28. package/dist/commands/hook-check.js.map +1 -0
  29. package/dist/commands/reviews.d.ts +74 -0
  30. package/dist/commands/reviews.d.ts.map +1 -0
  31. package/dist/commands/reviews.js +133 -0
  32. package/dist/commands/reviews.js.map +1 -0
  33. package/dist/context.d.ts +13 -0
  34. package/dist/context.d.ts.map +1 -0
  35. package/dist/context.js +53 -0
  36. package/dist/context.js.map +1 -0
  37. package/dist/github/auth.d.ts +9 -0
  38. package/dist/github/auth.d.ts.map +1 -0
  39. package/dist/github/auth.js +49 -0
  40. package/dist/github/auth.js.map +1 -0
  41. package/dist/github/checks.d.ts +19 -0
  42. package/dist/github/checks.d.ts.map +1 -0
  43. package/dist/github/checks.js +112 -0
  44. package/dist/github/checks.js.map +1 -0
  45. package/dist/github/comments.d.ts +86 -0
  46. package/dist/github/comments.d.ts.map +1 -0
  47. package/dist/github/comments.js +309 -0
  48. package/dist/github/comments.js.map +1 -0
  49. package/dist/github/fetch.d.ts +21 -0
  50. package/dist/github/fetch.d.ts.map +1 -0
  51. package/dist/github/fetch.js +177 -0
  52. package/dist/github/fetch.js.map +1 -0
  53. package/dist/github/index.d.ts +6 -0
  54. package/dist/github/index.d.ts.map +1 -0
  55. package/dist/github/index.js +6 -0
  56. package/dist/github/index.js.map +1 -0
  57. package/dist/github/repo.d.ts +27 -0
  58. package/dist/github/repo.d.ts.map +1 -0
  59. package/dist/github/repo.js +72 -0
  60. package/dist/github/repo.js.map +1 -0
  61. package/hooks/hooks.json +29 -0
  62. package/package.json +65 -0
  63. package/skills/bellwether/SKILL.md +92 -0
  64. package/src/bin.ts +15 -0
  65. package/src/cli.ts +39 -0
  66. package/src/commands/check.ts +251 -0
  67. package/src/commands/ci.ts +44 -0
  68. package/src/commands/hook-add.ts +139 -0
  69. package/src/commands/hook-check.ts +35 -0
  70. package/src/commands/reviews.ts +225 -0
  71. package/src/context.ts +86 -0
  72. package/src/github/auth.ts +40 -0
  73. package/src/github/checks.ts +187 -0
  74. package/src/github/comments.ts +522 -0
  75. package/src/github/fetch.ts +233 -0
  76. package/src/github/index.ts +35 -0
  77. package/src/github/repo.ts +146 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AACA,OAAO,EAOL,KAAK,QAAQ,EACb,KAAK,UAAU,EAChB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAsBlD;AAED,wBAAsB,SAAS,CAC7B,GAAG,EAAE,OAAO,EACZ,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAwChE"}
@@ -0,0 +1,53 @@
1
+ import * as clack from "@clack/prompts";
2
+ import { getGitHubToken, getProxyFetch, getRepoInfo, getCurrentBranch, findPRForBranch, listOpenPRs, } from "./github/index.js";
3
+ export async function bootstrap() {
4
+ const token = await getGitHubToken();
5
+ if (!token) {
6
+ throw new Error([
7
+ "GitHub token not found.",
8
+ "Fix: set GITHUB_TOKEN or GH_TOKEN env var, add to .env.local, or run `gh auth login`.",
9
+ ].join(" "));
10
+ }
11
+ const repoInfo = getRepoInfo();
12
+ if (!repoInfo) {
13
+ throw new Error([
14
+ "Could not determine repository.",
15
+ "Fix: run from a git repo with a github.com remote, or set GH_REPO=owner/repo.",
16
+ ].join(" "));
17
+ }
18
+ return { token, repoInfo, proxyFetch: getProxyFetch() };
19
+ }
20
+ export async function resolvePR(ctx, prArg) {
21
+ const { repoInfo, token, proxyFetch } = ctx;
22
+ if (prArg) {
23
+ return {
24
+ prNumber: prArg,
25
+ prUrl: `https://github.com/${repoInfo.owner}/${repoInfo.repo}/pull/${prArg}`,
26
+ };
27
+ }
28
+ const branch = getCurrentBranch();
29
+ if (branch && branch !== "main" && branch !== "master") {
30
+ const pr = await findPRForBranch(repoInfo.owner, repoInfo.repo, branch, token, proxyFetch);
31
+ if (pr) {
32
+ return { prNumber: pr.number, prUrl: pr.html_url, headSha: pr.head.sha };
33
+ }
34
+ }
35
+ const prs = await listOpenPRs(repoInfo.owner, repoInfo.repo, token, proxyFetch);
36
+ if (prs.length === 0) {
37
+ throw new Error("No open PRs found. Fix: pass a PR number as argument, e.g. `bellwether check 123`.");
38
+ }
39
+ const selected = await clack.select({
40
+ message: "Select a PR",
41
+ options: prs.map((pr) => ({
42
+ value: pr.number,
43
+ label: `#${pr.number} ${pr.title}`,
44
+ hint: pr.head.ref,
45
+ })),
46
+ });
47
+ if (clack.isCancel(selected)) {
48
+ process.exit(0);
49
+ }
50
+ const pr = prs.find((p) => p.number === selected);
51
+ return { prNumber: pr.number, prUrl: pr.html_url, headSha: pr.head.sha };
52
+ }
53
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Resolve a GitHub token from (in priority order):
3
+ * 1. GITHUB_TOKEN env var
4
+ * 2. GH_TOKEN env var
5
+ * 3. .env.local file in the repo root
6
+ * 4. `gh auth token` CLI
7
+ */
8
+ export declare function getGitHubToken(): Promise<string | null>;
9
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/github/auth.ts"],"names":[],"mappings":"AAaA;;;;;;GAMG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmB7D"}
@@ -0,0 +1,49 @@
1
+ import { join } from "node:path";
2
+ import { readFile, access } from "node:fs/promises";
3
+ import { spawnSync } from "node:child_process";
4
+ import { getRepoRoot } from "./repo.js";
5
+ function spawnText(cmd) {
6
+ const [command, ...args] = cmd;
7
+ if (!command) {
8
+ return null;
9
+ }
10
+ const result = spawnSync(command, args, { encoding: "utf-8" });
11
+ if (result.status !== 0) {
12
+ return null;
13
+ }
14
+ return result.stdout.trim();
15
+ }
16
+ /**
17
+ * Resolve a GitHub token from (in priority order):
18
+ * 1. GITHUB_TOKEN env var
19
+ * 2. GH_TOKEN env var
20
+ * 3. .env.local file in the repo root
21
+ * 4. `gh auth token` CLI
22
+ */
23
+ export async function getGitHubToken() {
24
+ if (process.env.GITHUB_TOKEN) {
25
+ return process.env.GITHUB_TOKEN;
26
+ }
27
+ if (process.env.GH_TOKEN) {
28
+ return process.env.GH_TOKEN;
29
+ }
30
+ const root = getRepoRoot();
31
+ if (root) {
32
+ const envPath = join(root, ".env.local");
33
+ try {
34
+ await access(envPath);
35
+ const content = await readFile(envPath, "utf-8");
36
+ const match = content.match(/^GITHUB_TOKEN=["']?([^"'\n]+)["']?/m);
37
+ if (match?.[1]) {
38
+ return match[1];
39
+ }
40
+ }
41
+ catch { }
42
+ }
43
+ const token = spawnText(["gh", "auth", "token"]);
44
+ if (token) {
45
+ return token;
46
+ }
47
+ return null;
48
+ }
49
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/github/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,SAAS,SAAS,CAAC,GAAa;IAC9B,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC;IAC/B,IAAI,CAAC,OAAO,EAAE,CAAC;QAAA,OAAO,IAAI,CAAC;IAAA,CAAC;IAC5B,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAC/D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAAA,OAAO,IAAI,CAAC;IAAA,CAAC;IACvC,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAAA,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAAA,CAAC;IAChE,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAAA,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IAAA,CAAC;IAExD,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;YACtB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACjD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;YACnE,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAAA,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;YAAA,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACjD,IAAI,KAAK,EAAE,CAAC;QAAA,OAAO,KAAK,CAAC;IAAA,CAAC;IAE1B,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type ProxyFetch } from "./fetch.js";
2
+ export interface FailingCheck {
3
+ name: string;
4
+ conclusion: string;
5
+ html_url: string;
6
+ log: string;
7
+ }
8
+ export interface CIStatus {
9
+ sha: string;
10
+ total: number;
11
+ passing: number;
12
+ failing: number;
13
+ pending: number;
14
+ passed: string[];
15
+ in_progress: string[];
16
+ failures: FailingCheck[];
17
+ }
18
+ export declare function fetchCIStatus(owner: string, repo: string, prNumber: number, token: string, proxyFetch: ProxyFetch, headSha?: string): Promise<CIStatus>;
19
+ //# sourceMappingURL=checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/github/checks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAMtD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAUD,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAqFD,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,UAAU,EACtB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,QAAQ,CAAC,CAgEnB"}
@@ -0,0 +1,112 @@
1
+ import { ghFetch } from "./fetch.js";
2
+ // ---------------------------------------------------------------------------
3
+ // Job log fetching + RTK-style filtering
4
+ // ---------------------------------------------------------------------------
5
+ const MAX_LINES = 60;
6
+ // eslint-disable-next-line no-control-regex
7
+ const ANSI_RE = /\u001b\[[0-9;]*[a-zA-Z]/g;
8
+ const TIMESTAMP_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z\s?/;
9
+ const GROUP_MARKERS = /^##\[(group|endgroup|command|section)\]/;
10
+ const NOISE_RE = /^(##\[debug\]|##\[notice\]|##\[save-state\]|##\[add-matcher\]|##\[remove-matcher\]|##\[set-output\]|##\[set-env\]|##\[add-path\]|##\[warning\]Couldn't find any|Downloading |Download action repository|Complete job name:|shell: \/|error: script ".*" exited with code|\$ )/;
11
+ // RTK "failure focus": strip passing test/check lines, keep only failures
12
+ const PASSING_LINE_RE = /^( *✓ | *✔ | *PASS | *√ | *ok \d| *\. |\s*\d+ passing)/;
13
+ function parseJobId(htmlUrl) {
14
+ const m = htmlUrl.match(/\/job\/(\d+)/);
15
+ return m?.[1] ?? null;
16
+ }
17
+ function filterLog(raw) {
18
+ const lines = raw.split("\n");
19
+ // Find the failed step: look for ##[error]Process completed with exit code
20
+ // and walk backwards to find its ##[group] start
21
+ let failStart = -1;
22
+ let failEnd = -1;
23
+ for (let i = lines.length - 1; i >= 0; i--) {
24
+ const line = lines[i];
25
+ if (failEnd === -1 && line.includes("##[error]Process completed with exit code")) {
26
+ failEnd = i;
27
+ }
28
+ if (failEnd !== -1 && line.includes("##[group]")) {
29
+ failStart = i;
30
+ break;
31
+ }
32
+ }
33
+ // If we found a failed step, extract just that; otherwise use entire log
34
+ const stepLines = failStart !== -1 && failEnd !== -1 ? lines.slice(failStart, failEnd) : lines;
35
+ const cleaned = stepLines
36
+ .map((l) => l.replace(ANSI_RE, "")) // strip ANSI
37
+ .map((l) => l.replace(TIMESTAMP_RE, "")) // strip timestamps
38
+ .filter((l) => !GROUP_MARKERS.test(l)) // strip ##[group] markers
39
+ .filter((l) => !NOISE_RE.test(l)) // strip debug/notice noise
40
+ .filter((l) => !PASSING_LINE_RE.test(l)) // strip passing test lines (failure focus)
41
+ .map((l) => l.replace(/^##\[error\]/, "")) // strip ##[error] prefix, keep content
42
+ .map((l) => l.replace(/^##\[warning\]/, "")) // strip ##[warning] prefix, keep content
43
+ .filter((l) => l.trim() !== "") // strip blank lines
44
+ .map((l) => (l.length > 200 ? l.slice(0, 200) + "…" : l)); // truncate long lines
45
+ // Tail: keep last N lines (error summaries are at the end)
46
+ const tail = cleaned.length > MAX_LINES ? cleaned.slice(-MAX_LINES) : cleaned;
47
+ return tail.join("\n");
48
+ }
49
+ async function fetchJobLog(owner, repo, jobId, token, proxyFetch) {
50
+ try {
51
+ const res = await ghFetch(`https://api.github.com/repos/${owner}/${repo}/actions/jobs/${jobId}/logs`, token, proxyFetch);
52
+ if (!res.ok) {
53
+ return `[failed to fetch logs: ${res.status}]`;
54
+ }
55
+ return filterLog(await res.text());
56
+ }
57
+ catch {
58
+ return "[failed to fetch logs]";
59
+ }
60
+ }
61
+ // ---------------------------------------------------------------------------
62
+ // Fetch CI status
63
+ // ---------------------------------------------------------------------------
64
+ export async function fetchCIStatus(owner, repo, prNumber, token, proxyFetch, headSha) {
65
+ let sha = headSha;
66
+ if (!sha) {
67
+ const prResponse = await ghFetch(`https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}`, token, proxyFetch);
68
+ if (!prResponse.ok) {
69
+ throw new Error(`Failed to fetch PR: ${prResponse.status}`);
70
+ }
71
+ const pr = (await prResponse.json());
72
+ sha = pr.head.sha;
73
+ }
74
+ // Fetch check runs for that SHA
75
+ const checksResponse = await ghFetch(`https://api.github.com/repos/${owner}/${repo}/commits/${sha}/check-runs?per_page=100`, token, proxyFetch);
76
+ if (!checksResponse.ok) {
77
+ throw new Error(`Failed to fetch checks: ${checksResponse.status}`);
78
+ }
79
+ const checksData = (await checksResponse.json());
80
+ const rawChecks = checksData.check_runs;
81
+ const isPassing = (c) => c.conclusion === "success" || c.conclusion === "skipped" || c.conclusion === "neutral";
82
+ const isFailing = (c) => c.conclusion === "failure" ||
83
+ c.conclusion === "timed_out" ||
84
+ c.conclusion === "action_required";
85
+ const passed = rawChecks.filter(isPassing).map((c) => c.name);
86
+ const in_progress = rawChecks.filter((c) => c.status !== "completed").map((c) => c.name);
87
+ const failingChecks = rawChecks.filter(isFailing);
88
+ // Fetch job logs for failing checks in parallel
89
+ const failures = await Promise.all(failingChecks.map(async (c) => {
90
+ const jobId = parseJobId(c.html_url);
91
+ const log = jobId
92
+ ? await fetchJobLog(owner, repo, jobId, token, proxyFetch)
93
+ : "[could not parse job ID from URL]";
94
+ return {
95
+ name: c.name,
96
+ conclusion: c.conclusion ?? "unknown",
97
+ html_url: c.html_url,
98
+ log,
99
+ };
100
+ }));
101
+ return {
102
+ sha,
103
+ total: rawChecks.length,
104
+ passing: passed.length,
105
+ failing: failingChecks.length,
106
+ pending: in_progress.length,
107
+ passed,
108
+ in_progress,
109
+ failures,
110
+ };
111
+ }
112
+ //# sourceMappingURL=checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.js","sourceRoot":"","sources":["../../src/github/checks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ import { type ProxyFetch } from "./fetch.js";
2
+ export interface ProcessedComment {
3
+ id: number;
4
+ type: "review_comment" | "issue_comment" | "review";
5
+ user: string;
6
+ isBot: boolean;
7
+ path: string | null;
8
+ line: number | null;
9
+ diffHunk: string | null;
10
+ body: string;
11
+ state?: string;
12
+ createdAt: string;
13
+ updatedAt: string;
14
+ url: string;
15
+ replies: Reply[];
16
+ hasHumanReply: boolean;
17
+ hasAnyReply: boolean;
18
+ isResolved: boolean;
19
+ }
20
+ export interface Reply {
21
+ id: number;
22
+ user: string;
23
+ body: string;
24
+ createdAt: string;
25
+ isBot: boolean;
26
+ }
27
+ export interface FilterOptions {
28
+ botsOnly?: boolean;
29
+ humansOnly?: boolean;
30
+ filter?: "unresolved" | "unanswered" | null;
31
+ }
32
+ interface RawGitHubUser {
33
+ login: string;
34
+ }
35
+ interface RawReviewComment {
36
+ id: number;
37
+ user?: RawGitHubUser;
38
+ body: string;
39
+ path: string;
40
+ line: number | null;
41
+ original_line: number | null;
42
+ diff_hunk: string | null;
43
+ created_at: string;
44
+ updated_at: string;
45
+ html_url: string;
46
+ in_reply_to_id?: number;
47
+ }
48
+ interface RawIssueComment {
49
+ id: number;
50
+ user?: RawGitHubUser;
51
+ body: string;
52
+ created_at: string;
53
+ updated_at: string;
54
+ html_url: string;
55
+ }
56
+ interface RawReview {
57
+ id: number;
58
+ user?: RawGitHubUser;
59
+ body: string | null;
60
+ state: string;
61
+ submitted_at: string;
62
+ html_url: string;
63
+ }
64
+ export interface RawCommentData {
65
+ reviewComments: RawReviewComment[];
66
+ issueComments: RawIssueComment[];
67
+ reviews: RawReview[];
68
+ }
69
+ export declare function fetchPRComments(owner: string, repo: string, prNumber: number, token: string, proxyFetch: ProxyFetch): Promise<RawCommentData>;
70
+ export declare function processComments(data: RawCommentData): ProcessedComment[];
71
+ export declare function filterComments(comments: ProcessedComment[], options: FilterOptions): ProcessedComment[];
72
+ export declare function replyToComment(owner: string, repo: string, prNumber: number, commentId: number, message: string, token: string, proxyFetch: ProxyFetch): Promise<{
73
+ html_url: string;
74
+ }>;
75
+ export declare function resolveThread(owner: string, repo: string, prNumber: number, commentId: number, token: string, proxyFetch: ProxyFetch): Promise<{
76
+ resolved: true;
77
+ threadId: string;
78
+ } | {
79
+ alreadyResolved: true;
80
+ threadId: string;
81
+ } | {
82
+ skipped: true;
83
+ reason: string;
84
+ }>;
85
+ export {};
86
+ //# sourceMappingURL=comments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../src/github/comments.ts"],"names":[],"mappings":"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"}