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.
- package/.claude-plugin/plugin.json +13 -0
- package/LICENSE +21 -0
- package/README.md +120 -0
- package/SKILL.md +92 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +17 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +36 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/check.d.ts +191 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +186 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/ci.d.ts +8 -0
- package/dist/commands/ci.d.ts.map +1 -0
- package/dist/commands/ci.js +28 -0
- package/dist/commands/ci.js.map +1 -0
- package/dist/commands/hook-add.d.ts +2 -0
- package/dist/commands/hook-add.d.ts.map +1 -0
- package/dist/commands/hook-add.js +97 -0
- package/dist/commands/hook-add.js.map +1 -0
- package/dist/commands/hook-check.d.ts +2 -0
- package/dist/commands/hook-check.d.ts.map +1 -0
- package/dist/commands/hook-check.js +29 -0
- package/dist/commands/hook-check.js.map +1 -0
- package/dist/commands/reviews.d.ts +74 -0
- package/dist/commands/reviews.d.ts.map +1 -0
- package/dist/commands/reviews.js +133 -0
- package/dist/commands/reviews.js.map +1 -0
- package/dist/context.d.ts +13 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +53 -0
- package/dist/context.js.map +1 -0
- package/dist/github/auth.d.ts +9 -0
- package/dist/github/auth.d.ts.map +1 -0
- package/dist/github/auth.js +49 -0
- package/dist/github/auth.js.map +1 -0
- package/dist/github/checks.d.ts +19 -0
- package/dist/github/checks.d.ts.map +1 -0
- package/dist/github/checks.js +112 -0
- package/dist/github/checks.js.map +1 -0
- package/dist/github/comments.d.ts +86 -0
- package/dist/github/comments.d.ts.map +1 -0
- package/dist/github/comments.js +309 -0
- package/dist/github/comments.js.map +1 -0
- package/dist/github/fetch.d.ts +21 -0
- package/dist/github/fetch.d.ts.map +1 -0
- package/dist/github/fetch.js +177 -0
- package/dist/github/fetch.js.map +1 -0
- package/dist/github/index.d.ts +6 -0
- package/dist/github/index.d.ts.map +1 -0
- package/dist/github/index.js +6 -0
- package/dist/github/index.js.map +1 -0
- package/dist/github/repo.d.ts +27 -0
- package/dist/github/repo.d.ts.map +1 -0
- package/dist/github/repo.js +72 -0
- package/dist/github/repo.js.map +1 -0
- package/hooks/hooks.json +29 -0
- package/package.json +65 -0
- package/skills/bellwether/SKILL.md +92 -0
- package/src/bin.ts +15 -0
- package/src/cli.ts +39 -0
- package/src/commands/check.ts +251 -0
- package/src/commands/ci.ts +44 -0
- package/src/commands/hook-add.ts +139 -0
- package/src/commands/hook-check.ts +35 -0
- package/src/commands/reviews.ts +225 -0
- package/src/context.ts +86 -0
- package/src/github/auth.ts +40 -0
- package/src/github/checks.ts +187 -0
- package/src/github/comments.ts +522 -0
- package/src/github/fetch.ts +233 -0
- package/src/github/index.ts +35 -0
- package/src/github/repo.ts +146 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { z } from "incur";
|
|
2
|
+
import { resolvePR } from "../context.js";
|
|
3
|
+
import { fetchPRMergeState } from "../github/index.js";
|
|
4
|
+
import { getCISection } from "./ci.js";
|
|
5
|
+
import { getReviewsList, getReviewDetail, postReply, formatReviewsSection, commentSchema, } from "./reviews.js";
|
|
6
|
+
function buildPRSection(mergeState, ciStatus, unresolvedCount) {
|
|
7
|
+
return {
|
|
8
|
+
state: mergeState.state,
|
|
9
|
+
mergeable: mergeState.mergeableState,
|
|
10
|
+
ready: mergeState.state === "open" &&
|
|
11
|
+
mergeState.mergeableState === "clean" &&
|
|
12
|
+
ciStatus.failing === 0 &&
|
|
13
|
+
ciStatus.pending === 0 &&
|
|
14
|
+
unresolvedCount === 0,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export const checkCommand = {
|
|
18
|
+
description: "Show CI status and review comments for a PR",
|
|
19
|
+
hint: "Combines CI checks and review comments. Use --reply and --detail for review actions. With --watch, polls until CI completes.",
|
|
20
|
+
args: z.object({
|
|
21
|
+
pr: z.coerce.number().optional().describe("PR number (auto-detects from branch)"),
|
|
22
|
+
}),
|
|
23
|
+
options: z.object({
|
|
24
|
+
watch: z.boolean().default(false).describe("Poll until CI completes"),
|
|
25
|
+
interval: z.coerce.number().default(30).describe("Poll interval in seconds"),
|
|
26
|
+
timeout: z.coerce.number().default(1800).describe("Timeout in seconds"),
|
|
27
|
+
unresolved: z.boolean().default(false).describe("Show only unresolved comments"),
|
|
28
|
+
unanswered: z.boolean().default(false).describe("Show only unanswered comments"),
|
|
29
|
+
botsOnly: z.boolean().default(false).describe("Only bot comments"),
|
|
30
|
+
humansOnly: z.boolean().default(false).describe("Only human comments"),
|
|
31
|
+
reply: z.string().optional().describe("Reply to comment: <id>:<message>"),
|
|
32
|
+
resolve: z.boolean().default(false).describe("Resolve thread after replying"),
|
|
33
|
+
detail: z.coerce.number().optional().describe("Show full detail for comment ID"),
|
|
34
|
+
}),
|
|
35
|
+
alias: {
|
|
36
|
+
watch: "w",
|
|
37
|
+
interval: "i",
|
|
38
|
+
unresolved: "u",
|
|
39
|
+
unanswered: "a",
|
|
40
|
+
botsOnly: "b",
|
|
41
|
+
humansOnly: "H",
|
|
42
|
+
reply: "r",
|
|
43
|
+
detail: "d",
|
|
44
|
+
},
|
|
45
|
+
usage: [
|
|
46
|
+
{},
|
|
47
|
+
{ args: { pr: true } },
|
|
48
|
+
{ options: { watch: true } },
|
|
49
|
+
{ options: { detail: true } },
|
|
50
|
+
{ options: { reply: true } },
|
|
51
|
+
{ options: { reply: true, resolve: true } },
|
|
52
|
+
],
|
|
53
|
+
output: z.object({
|
|
54
|
+
pr: z
|
|
55
|
+
.object({
|
|
56
|
+
state: z.string().describe("open | closed | merged"),
|
|
57
|
+
mergeable: z
|
|
58
|
+
.string()
|
|
59
|
+
.describe("Merge state: clean, dirty, blocked, behind, unstable, unknown, has_hooks"),
|
|
60
|
+
ready: z
|
|
61
|
+
.boolean()
|
|
62
|
+
.describe("true when state=open, mergeableState=clean, all CI passing, zero unresolved reviews"),
|
|
63
|
+
})
|
|
64
|
+
.optional(),
|
|
65
|
+
ci: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
|
|
66
|
+
reviews: z.record(z.string(), z.union([z.string(), z.number()])).optional(),
|
|
67
|
+
comment: commentSchema.optional(),
|
|
68
|
+
replied: z.boolean().optional(),
|
|
69
|
+
commentId: z.number().optional(),
|
|
70
|
+
message: z.string().optional(),
|
|
71
|
+
url: z.string().optional(),
|
|
72
|
+
resolved: z.boolean().optional(),
|
|
73
|
+
allPassing: z.boolean().optional(),
|
|
74
|
+
timedOut: z.boolean().optional(),
|
|
75
|
+
}),
|
|
76
|
+
examples: [
|
|
77
|
+
{ description: "CI status + review comments for current branch" },
|
|
78
|
+
{ options: { watch: true }, description: "Watch until CI completes" },
|
|
79
|
+
{ options: { unresolved: true }, description: "Show only unresolved reviews" },
|
|
80
|
+
{ options: { detail: 456 }, description: "Full detail for comment 456" },
|
|
81
|
+
{ options: { reply: "456:Fixed in latest commit" }, description: "Reply to comment" },
|
|
82
|
+
{ options: { reply: "456:Done", resolve: true }, description: "Reply and resolve" },
|
|
83
|
+
],
|
|
84
|
+
async run(c) {
|
|
85
|
+
const ctx = c.var.ctx;
|
|
86
|
+
const { prNumber, headSha } = await resolvePR(ctx, c.args.pr);
|
|
87
|
+
const opts = c.options;
|
|
88
|
+
// Reply mode — no CI fetch needed
|
|
89
|
+
if (opts.reply) {
|
|
90
|
+
const result = await postReply(ctx, prNumber, opts.reply, opts.resolve);
|
|
91
|
+
return c.ok(result);
|
|
92
|
+
}
|
|
93
|
+
// Detail mode — no CI fetch needed
|
|
94
|
+
if (opts.detail) {
|
|
95
|
+
const comment = await getReviewDetail(ctx, prNumber, opts.detail);
|
|
96
|
+
if (!comment) {
|
|
97
|
+
return c.error({ message: `Comment ${opts.detail} not found` });
|
|
98
|
+
}
|
|
99
|
+
return c.ok({ comment });
|
|
100
|
+
}
|
|
101
|
+
const filterOpts = {
|
|
102
|
+
unresolved: opts.unresolved,
|
|
103
|
+
unanswered: opts.unanswered,
|
|
104
|
+
botsOnly: opts.botsOnly,
|
|
105
|
+
humansOnly: opts.humansOnly,
|
|
106
|
+
};
|
|
107
|
+
// Watch mode — poll until CI terminal
|
|
108
|
+
if (opts.watch) {
|
|
109
|
+
const start = Date.now();
|
|
110
|
+
while (true) {
|
|
111
|
+
const [mergeState, { status, flat: ciFlat }, reviewData] = await Promise.all([
|
|
112
|
+
fetchPRMergeState(ctx.repoInfo.owner, ctx.repoInfo.repo, prNumber, ctx.token, ctx.proxyFetch),
|
|
113
|
+
getCISection(ctx, prNumber, headSha),
|
|
114
|
+
getReviewsList(ctx, prNumber, filterOpts),
|
|
115
|
+
]);
|
|
116
|
+
const reviewsFlat = formatReviewsSection(reviewData.comments);
|
|
117
|
+
const unresolvedCount = reviewData.comments.filter((cm) => !(cm.isResolved || cm.hasHumanReply)).length;
|
|
118
|
+
const prSection = buildPRSection(mergeState, status, unresolvedCount);
|
|
119
|
+
if (status.failing === 0 && status.pending === 0) {
|
|
120
|
+
return c.ok({
|
|
121
|
+
pr: prSection,
|
|
122
|
+
ci: { ...ciFlat, allPassing: true },
|
|
123
|
+
reviews: reviewsFlat,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
if (status.failing > 0 && status.pending === 0) {
|
|
127
|
+
return c.ok({
|
|
128
|
+
pr: prSection,
|
|
129
|
+
ci: { ...ciFlat, allPassing: false },
|
|
130
|
+
reviews: reviewsFlat,
|
|
131
|
+
}, {
|
|
132
|
+
cta: {
|
|
133
|
+
description: "Failed checks detected:",
|
|
134
|
+
commands: [
|
|
135
|
+
{ command: "check --unresolved", description: "Show unresolved reviews" },
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if ((Date.now() - start) / 1000 >= opts.timeout) {
|
|
141
|
+
return c.ok({
|
|
142
|
+
pr: prSection,
|
|
143
|
+
ci: { ...ciFlat, timedOut: true },
|
|
144
|
+
reviews: reviewsFlat,
|
|
145
|
+
}, {
|
|
146
|
+
cta: {
|
|
147
|
+
description: "Timed out, checks still running:",
|
|
148
|
+
commands: [
|
|
149
|
+
{
|
|
150
|
+
command: `check --watch --timeout ${opts.timeout * 2}`,
|
|
151
|
+
description: "Retry with longer timeout",
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
await new Promise((r) => setTimeout(r, opts.interval * 1000));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Default: fetch all in parallel
|
|
161
|
+
const [mergeState, { status, flat: ciFlat }, reviewData] = await Promise.all([
|
|
162
|
+
fetchPRMergeState(ctx.repoInfo.owner, ctx.repoInfo.repo, prNumber, ctx.token, ctx.proxyFetch),
|
|
163
|
+
getCISection(ctx, prNumber, headSha),
|
|
164
|
+
getReviewsList(ctx, prNumber, filterOpts),
|
|
165
|
+
]);
|
|
166
|
+
const reviewsFlat = formatReviewsSection(reviewData.comments);
|
|
167
|
+
const unresolvedCount = reviewData.comments.filter((cm) => !(cm.isResolved || cm.hasHumanReply)).length;
|
|
168
|
+
const prSection = buildPRSection(mergeState, status, unresolvedCount);
|
|
169
|
+
return c.ok({ pr: prSection, ci: ciFlat, reviews: reviewsFlat }, {
|
|
170
|
+
cta: status.pending > 0
|
|
171
|
+
? {
|
|
172
|
+
description: "Checks still running:",
|
|
173
|
+
commands: [{ command: "check --watch", description: "Watch until complete" }],
|
|
174
|
+
}
|
|
175
|
+
: status.failing > 0
|
|
176
|
+
? {
|
|
177
|
+
description: "Checks failing:",
|
|
178
|
+
commands: [
|
|
179
|
+
{ command: "check --unresolved", description: "Show unresolved reviews" },
|
|
180
|
+
],
|
|
181
|
+
}
|
|
182
|
+
: undefined,
|
|
183
|
+
});
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Context } from "../context.js";
|
|
2
|
+
import { type CIStatus } from "../github/index.js";
|
|
3
|
+
export declare function flatten(status: CIStatus, extra?: Record<string, boolean>): Record<string, string | number | boolean>;
|
|
4
|
+
export declare function getCISection(ctx: Context, prNumber: number, headSha?: string): Promise<{
|
|
5
|
+
status: CIStatus;
|
|
6
|
+
flat: Record<string, string | number | boolean>;
|
|
7
|
+
}>;
|
|
8
|
+
//# sourceMappingURL=ci.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci.d.ts","sourceRoot":"","sources":["../../src/commands/ci.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAElE,wBAAgB,OAAO,CACrB,MAAM,EAAE,QAAQ,EAChB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAoB3C;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAA;CAAE,CAAC,CAWhF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {} from "../context.js";
|
|
2
|
+
import { fetchCIStatus } from "../github/index.js";
|
|
3
|
+
export function flatten(status, extra) {
|
|
4
|
+
const out = {
|
|
5
|
+
sha: status.sha,
|
|
6
|
+
checks: `${status.total} total, ${status.passing} passing, ${status.failing} failing, ${status.pending} pending`,
|
|
7
|
+
};
|
|
8
|
+
if (status.passed.length > 0) {
|
|
9
|
+
out.passed = status.passed.join(", ");
|
|
10
|
+
}
|
|
11
|
+
if (status.in_progress.length > 0) {
|
|
12
|
+
out.in_progress = status.in_progress.join(", ");
|
|
13
|
+
}
|
|
14
|
+
for (const f of status.failures) {
|
|
15
|
+
const label = f.conclusion === "failure" ? `FAIL ${f.name}` : `${f.conclusion.toUpperCase()} ${f.name}`;
|
|
16
|
+
out[label] = f.log;
|
|
17
|
+
}
|
|
18
|
+
if (extra) {
|
|
19
|
+
Object.assign(out, extra);
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
export async function getCISection(ctx, prNumber, headSha) {
|
|
24
|
+
const { token, repoInfo, proxyFetch } = ctx;
|
|
25
|
+
const status = await fetchCIStatus(repoInfo.owner, repoInfo.repo, prNumber, token, proxyFetch, headSha);
|
|
26
|
+
return { status, flat: flatten(status) };
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=ci.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci.js","sourceRoot":"","sources":["../../src/commands/ci.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAiB,MAAM,oBAAoB,CAAC;AAElE,MAAM,UAAU,OAAO,CACrB,MAAgB,EAChB,KAA+B;IAE/B,MAAM,GAAG,GAA8C;QACrD,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,WAAW,MAAM,CAAC,OAAO,aAAa,MAAM,CAAC,OAAO,aAAa,MAAM,CAAC,OAAO,UAAU;KACjH,CAAC;IACF,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,GAAG,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,KAAK,GACT,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5F,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;IACrB,CAAC;IACD,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAY,EACZ,QAAgB,EAChB,OAAgB;IAEhB,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC;IAC5C,MAAM,MAAM,GAAG,MAAM,aAAa,CAChC,QAAQ,CAAC,KAAK,EACd,QAAQ,CAAC,IAAI,EACb,QAAQ,EACR,KAAK,EACL,UAAU,EACV,OAAO,CACR,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-add.d.ts","sourceRoot":"","sources":["../../src/commands/hook-add.ts"],"names":[],"mappings":"AA2HA,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAezC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// Standalone hook installer — bypasses incur.
|
|
2
|
+
// Configures PostToolUse hooks in Claude Code and Codex globally.
|
|
3
|
+
// Idempotent: checks if already configured, updates if needed.
|
|
4
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
const HOOK_COMMAND = "npx -y bellwether@latest hook-check";
|
|
9
|
+
const HOOK_TIMEOUT = 15;
|
|
10
|
+
const BELLWETHER_MARKER = "bellwether@latest hook-check";
|
|
11
|
+
function buildClaudeHooks() {
|
|
12
|
+
return {
|
|
13
|
+
matcher: "Bash",
|
|
14
|
+
hooks: [
|
|
15
|
+
{ type: "command", if: "Bash(git push*)", command: HOOK_COMMAND, timeout: HOOK_TIMEOUT },
|
|
16
|
+
{ type: "command", if: "Bash(gh pr create*)", command: HOOK_COMMAND, timeout: HOOK_TIMEOUT },
|
|
17
|
+
{ type: "command", if: "Bash(gh pr ready*)", command: HOOK_COMMAND, timeout: HOOK_TIMEOUT },
|
|
18
|
+
],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
async function configureClaude() {
|
|
22
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
23
|
+
let settings = {};
|
|
24
|
+
if (existsSync(settingsPath)) {
|
|
25
|
+
settings = JSON.parse(await readFile(settingsPath, "utf-8"));
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
await mkdir(join(homedir(), ".claude"), { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
const hooks = (settings.hooks ?? {});
|
|
31
|
+
const postToolUse = (hooks.PostToolUse ?? []);
|
|
32
|
+
// Remove any existing bellwether hooks
|
|
33
|
+
const cleaned = [];
|
|
34
|
+
for (const group of postToolUse) {
|
|
35
|
+
const filtered = group.hooks.filter((h) => !h.command.includes(BELLWETHER_MARKER));
|
|
36
|
+
if (filtered.length > 0) {
|
|
37
|
+
cleaned.push({ ...group, hooks: filtered });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Add fresh bellwether hooks
|
|
41
|
+
cleaned.push(buildClaudeHooks());
|
|
42
|
+
hooks.PostToolUse = cleaned;
|
|
43
|
+
settings.hooks = hooks;
|
|
44
|
+
await writeFile(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
45
|
+
return settingsPath;
|
|
46
|
+
}
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// Codex: ~/.codex/hooks.json
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
async function configureCodex() {
|
|
51
|
+
const codexDir = join(homedir(), ".codex");
|
|
52
|
+
if (!existsSync(codexDir)) {
|
|
53
|
+
return null; // Codex not installed
|
|
54
|
+
}
|
|
55
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
56
|
+
let config = {};
|
|
57
|
+
if (existsSync(hooksPath)) {
|
|
58
|
+
config = JSON.parse(await readFile(hooksPath, "utf-8"));
|
|
59
|
+
}
|
|
60
|
+
const hooks = (config.hooks ?? {});
|
|
61
|
+
const postToolUse = (hooks.PostToolUse ?? []);
|
|
62
|
+
// Remove any existing bellwether hooks
|
|
63
|
+
const cleaned = [];
|
|
64
|
+
for (const group of postToolUse) {
|
|
65
|
+
const filtered = group.hooks.filter((h) => !h.command.includes(BELLWETHER_MARKER));
|
|
66
|
+
if (filtered.length > 0) {
|
|
67
|
+
cleaned.push({ ...group, hooks: filtered });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Add fresh codex hooks (no `if` — codex doesn't support it)
|
|
71
|
+
cleaned.push({
|
|
72
|
+
matcher: "^Bash$",
|
|
73
|
+
hooks: [{ type: "command", command: HOOK_COMMAND, timeout: HOOK_TIMEOUT }],
|
|
74
|
+
});
|
|
75
|
+
hooks.PostToolUse = cleaned;
|
|
76
|
+
config.hooks = hooks;
|
|
77
|
+
await writeFile(hooksPath, JSON.stringify(config, null, 2) + "\n");
|
|
78
|
+
return hooksPath;
|
|
79
|
+
}
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Main
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
export async function run() {
|
|
84
|
+
console.log("Configuring bellwether hooks...\n");
|
|
85
|
+
const claudePath = await configureClaude();
|
|
86
|
+
console.log(` Claude Code: ${claudePath}`);
|
|
87
|
+
const codexPath = await configureCodex();
|
|
88
|
+
if (codexPath) {
|
|
89
|
+
console.log(` Codex: ${codexPath}`);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
console.log(" Codex: skipped (not installed)");
|
|
93
|
+
}
|
|
94
|
+
console.log("\nHooks will trigger when git push or gh pr create/ready is detected.");
|
|
95
|
+
console.log("The LLM will be prompted to run bellwether to monitor the PR.");
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=hook-add.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-add.js","sourceRoot":"","sources":["../../src/commands/hook-add.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-check.d.ts","sourceRoot":"","sources":["../../src/commands/hook-check.ts"],"names":[],"mappings":"AAOA,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CA2BzC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Standalone hook handler — bypasses incur for speed.
|
|
2
|
+
// Reads Claude/Codex PostToolUse JSON from stdin.
|
|
3
|
+
// If the command is a PR-related action, outputs additionalContext
|
|
4
|
+
// telling the LLM to start monitoring with bellwether.
|
|
5
|
+
const PR_PATTERN = /\bgit\s+push\b|\bgh\s+pr\s+(create|ready)\b/;
|
|
6
|
+
export async function run() {
|
|
7
|
+
const chunks = [];
|
|
8
|
+
for await (const chunk of process.stdin) {
|
|
9
|
+
chunks.push(chunk);
|
|
10
|
+
}
|
|
11
|
+
let command = "";
|
|
12
|
+
try {
|
|
13
|
+
const input = JSON.parse(Buffer.concat(chunks).toString());
|
|
14
|
+
command = input.tool_input?.command ?? "";
|
|
15
|
+
if (PR_PATTERN.test(command)) {
|
|
16
|
+
const output = {
|
|
17
|
+
hookSpecificOutput: {
|
|
18
|
+
hookEventName: input.hook_event_name ?? "PostToolUse",
|
|
19
|
+
additionalContext: "PR pushed. Run `npx -y bellwether@latest check --watch` to monitor CI and reviews until merge-ready.",
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
process.stdout.write(JSON.stringify(output));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// Malformed input — exit silently
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=hook-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-check.js","sourceRoot":"","sources":["../../src/commands/hook-check.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,kDAAkD;AAClD,mEAAmE;AACnE,uDAAuD;AAEvD,MAAM,UAAU,GAAG,6CAA6C,CAAC;AAEjE,MAAM,CAAC,KAAK,UAAU,GAAG;IACvB,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,KAAe,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAGxD,CAAC;QACF,OAAO,GAAG,KAAK,CAAC,UAAU,EAAE,OAAO,IAAI,EAAE,CAAC;QAE1C,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG;gBACb,kBAAkB,EAAE;oBAClB,aAAa,EAAE,KAAK,CAAC,eAAe,IAAI,aAAa;oBACrD,iBAAiB,EACf,sGAAsG;iBACzG;aACF,CAAC;YACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,kCAAkC;IACpC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type Context } from "../context.js";
|
|
3
|
+
import { type ProcessedComment, type ProxyFetch } from "../github/index.js";
|
|
4
|
+
export declare const replySchema: z.ZodObject<{
|
|
5
|
+
id: z.ZodNumber;
|
|
6
|
+
user: z.ZodString;
|
|
7
|
+
body: z.ZodString;
|
|
8
|
+
createdAt: z.ZodString;
|
|
9
|
+
isBot: z.ZodBoolean;
|
|
10
|
+
}, z.core.$strip>;
|
|
11
|
+
export declare const commentSchema: z.ZodObject<{
|
|
12
|
+
id: z.ZodNumber;
|
|
13
|
+
type: z.ZodEnum<{
|
|
14
|
+
review_comment: "review_comment";
|
|
15
|
+
issue_comment: "issue_comment";
|
|
16
|
+
review: "review";
|
|
17
|
+
}>;
|
|
18
|
+
user: z.ZodString;
|
|
19
|
+
isBot: z.ZodBoolean;
|
|
20
|
+
path: z.ZodNullable<z.ZodString>;
|
|
21
|
+
line: z.ZodNullable<z.ZodNumber>;
|
|
22
|
+
diffHunk: z.ZodNullable<z.ZodString>;
|
|
23
|
+
body: z.ZodString;
|
|
24
|
+
createdAt: z.ZodString;
|
|
25
|
+
updatedAt: z.ZodString;
|
|
26
|
+
url: z.ZodString;
|
|
27
|
+
replies: z.ZodArray<z.ZodObject<{
|
|
28
|
+
id: z.ZodNumber;
|
|
29
|
+
user: z.ZodString;
|
|
30
|
+
body: z.ZodString;
|
|
31
|
+
createdAt: z.ZodString;
|
|
32
|
+
isBot: z.ZodBoolean;
|
|
33
|
+
}, z.core.$strip>>;
|
|
34
|
+
hasHumanReply: z.ZodBoolean;
|
|
35
|
+
hasAnyReply: z.ZodBoolean;
|
|
36
|
+
isResolved: z.ZodBoolean;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
export declare function getReviewsList(ctx: Context, prNumber: number, filterOpts: {
|
|
39
|
+
unresolved: boolean;
|
|
40
|
+
unanswered: boolean;
|
|
41
|
+
botsOnly: boolean;
|
|
42
|
+
humansOnly: boolean;
|
|
43
|
+
}): Promise<{
|
|
44
|
+
comments: ProcessedComment[];
|
|
45
|
+
total: number;
|
|
46
|
+
}>;
|
|
47
|
+
export declare function getReviewDetail(ctx: Context, prNumber: number, commentId: number): Promise<ProcessedComment | undefined>;
|
|
48
|
+
export declare function postReply(ctx: Context, prNumber: number, replyStr: string, shouldResolve: boolean): Promise<{
|
|
49
|
+
replied: boolean;
|
|
50
|
+
commentId: number;
|
|
51
|
+
message: string;
|
|
52
|
+
url: string;
|
|
53
|
+
resolved?: boolean;
|
|
54
|
+
resolveError?: string;
|
|
55
|
+
}>;
|
|
56
|
+
export declare function formatReviewsSection(comments: ProcessedComment[]): Record<string, string | number>;
|
|
57
|
+
export declare function watchForComments(context: {
|
|
58
|
+
owner: string;
|
|
59
|
+
repo: string;
|
|
60
|
+
prNumber: number;
|
|
61
|
+
token: string;
|
|
62
|
+
proxyFetch: ProxyFetch;
|
|
63
|
+
}, options: {
|
|
64
|
+
botsOnly?: boolean;
|
|
65
|
+
humansOnly?: boolean;
|
|
66
|
+
filter?: "unresolved" | "unanswered" | null;
|
|
67
|
+
watchInterval: number;
|
|
68
|
+
watchTimeout: number;
|
|
69
|
+
}): Promise<{
|
|
70
|
+
newComments: ProcessedComment[];
|
|
71
|
+
total: number;
|
|
72
|
+
timedOut: boolean;
|
|
73
|
+
}>;
|
|
74
|
+
//# sourceMappingURL=reviews.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviews.d.ts","sourceRoot":"","sources":["../../src/commands/reviews.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAML,KAAK,gBAAgB,EACrB,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAE5B,eAAO,MAAM,WAAW;;;;;;iBAMtB,CAAC;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkBxB,CAAC;AAMH,wBAAsB,cAAc,CAClC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE;IACV,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;CACrB,GACA,OAAO,CAAC;IAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAY1D;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAMvC;AAED,wBAAsB,SAAS,CAC7B,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,OAAO,GACrB,OAAO,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC,CAwCD;AAMD,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAoBjC;AAMD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE;IACP,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,UAAU,CAAC;CACxB,EACD,OAAO,EAAE;IACP,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,YAAY,GAAG,YAAY,GAAG,IAAI,CAAC;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;;;;GA6CF"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import {} from "../context.js";
|
|
3
|
+
import { fetchPRComments, processComments, filterComments, replyToComment, resolveThread, } from "../github/index.js";
|
|
4
|
+
export const replySchema = z.object({
|
|
5
|
+
id: z.number().describe("Reply ID"),
|
|
6
|
+
user: z.string().describe("Author login"),
|
|
7
|
+
body: z.string().describe("Reply body (cleaned)"),
|
|
8
|
+
createdAt: z.string().describe("ISO timestamp"),
|
|
9
|
+
isBot: z.boolean().describe("Whether author is a bot"),
|
|
10
|
+
});
|
|
11
|
+
export const commentSchema = z.object({
|
|
12
|
+
id: z.number().describe("Comment ID (use with --detail or --reply)"),
|
|
13
|
+
type: z
|
|
14
|
+
.enum(["review_comment", "issue_comment", "review"])
|
|
15
|
+
.describe("CODE = inline, COMMENT = PR-level, REVIEW = review summary"),
|
|
16
|
+
user: z.string().describe("Author login"),
|
|
17
|
+
isBot: z.boolean().describe("Whether author is a bot"),
|
|
18
|
+
path: z.string().nullable().describe("File path (inline comments only)"),
|
|
19
|
+
line: z.number().nullable().describe("Line number (inline comments only)"),
|
|
20
|
+
diffHunk: z.string().nullable().describe("Surrounding diff context"),
|
|
21
|
+
body: z.string().describe("Comment body (cleaned of bot boilerplate)"),
|
|
22
|
+
createdAt: z.string().describe("ISO timestamp"),
|
|
23
|
+
updatedAt: z.string().describe("ISO timestamp of last update"),
|
|
24
|
+
url: z.string().describe("GitHub URL"),
|
|
25
|
+
replies: z.array(replySchema).describe("Thread replies"),
|
|
26
|
+
hasHumanReply: z.boolean().describe("Whether a human has replied"),
|
|
27
|
+
hasAnyReply: z.boolean().describe("Whether any reply exists"),
|
|
28
|
+
isResolved: z.boolean().describe("Whether the thread is resolved"),
|
|
29
|
+
});
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Pure logic functions
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
export async function getReviewsList(ctx, prNumber, filterOpts) {
|
|
34
|
+
const { token, repoInfo, proxyFetch } = ctx;
|
|
35
|
+
const rawData = await fetchPRComments(repoInfo.owner, repoInfo.repo, prNumber, token, proxyFetch);
|
|
36
|
+
const processed = processComments(rawData);
|
|
37
|
+
const filtered = filterComments(processed, {
|
|
38
|
+
botsOnly: filterOpts.botsOnly,
|
|
39
|
+
humansOnly: filterOpts.humansOnly,
|
|
40
|
+
filter: filterOpts.unresolved ? "unresolved" : filterOpts.unanswered ? "unanswered" : null,
|
|
41
|
+
});
|
|
42
|
+
return { comments: filtered, total: filtered.length };
|
|
43
|
+
}
|
|
44
|
+
export async function getReviewDetail(ctx, prNumber, commentId) {
|
|
45
|
+
const { token, repoInfo, proxyFetch } = ctx;
|
|
46
|
+
const rawData = await fetchPRComments(repoInfo.owner, repoInfo.repo, prNumber, token, proxyFetch);
|
|
47
|
+
const processed = processComments(rawData);
|
|
48
|
+
return processed.find((cm) => cm.id === commentId);
|
|
49
|
+
}
|
|
50
|
+
export async function postReply(ctx, prNumber, replyStr, shouldResolve) {
|
|
51
|
+
const { token, repoInfo, proxyFetch } = ctx;
|
|
52
|
+
const colonIdx = replyStr.indexOf(":");
|
|
53
|
+
if (colonIdx === -1) {
|
|
54
|
+
throw new Error("--reply format is <id>:<message>");
|
|
55
|
+
}
|
|
56
|
+
const commentId = Number(replyStr.slice(0, colonIdx));
|
|
57
|
+
const message = replyStr.slice(colonIdx + 1);
|
|
58
|
+
const result = await replyToComment(repoInfo.owner, repoInfo.repo, prNumber, commentId, message, token, proxyFetch);
|
|
59
|
+
let resolved;
|
|
60
|
+
let resolveError;
|
|
61
|
+
if (shouldResolve) {
|
|
62
|
+
try {
|
|
63
|
+
const res = await resolveThread(repoInfo.owner, repoInfo.repo, prNumber, commentId, token, proxyFetch);
|
|
64
|
+
resolved = "resolved" in res && res.resolved;
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
resolved = false;
|
|
68
|
+
resolveError = error instanceof Error ? error.message : "Failed to resolve thread";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return { replied: true, commentId, message, url: result.html_url, resolved, resolveError };
|
|
72
|
+
}
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// Format helper
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
export function formatReviewsSection(comments) {
|
|
77
|
+
const unresolvedCount = comments.filter((c) => !(c.isResolved || c.hasHumanReply)).length;
|
|
78
|
+
const unansweredCount = comments.filter((c) => !c.hasAnyReply).length;
|
|
79
|
+
const result = {
|
|
80
|
+
total: `${unresolvedCount} unresolved, ${unansweredCount} unanswered`,
|
|
81
|
+
};
|
|
82
|
+
for (const comment of comments) {
|
|
83
|
+
const location = comment.path
|
|
84
|
+
? `${comment.path}${comment.line ? `:${comment.line}` : ""}`
|
|
85
|
+
: null;
|
|
86
|
+
const key = location ? `REVIEW ${comment.id} ${location}` : `REVIEW ${comment.id}`;
|
|
87
|
+
const body = comment.body;
|
|
88
|
+
result[key] = body;
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// Watch helper
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
export async function watchForComments(context, options) {
|
|
96
|
+
const { owner, repo, prNumber, token, proxyFetch } = context;
|
|
97
|
+
const seenIds = new Set();
|
|
98
|
+
const startTime = Date.now();
|
|
99
|
+
const initialData = await fetchPRComments(owner, repo, prNumber, token, proxyFetch);
|
|
100
|
+
const initialProcessed = processComments(initialData);
|
|
101
|
+
const initialFiltered = filterComments(initialProcessed, options);
|
|
102
|
+
for (const comment of initialFiltered) {
|
|
103
|
+
seenIds.add(comment.id);
|
|
104
|
+
}
|
|
105
|
+
while (true) {
|
|
106
|
+
await new Promise((r) => setTimeout(r, options.watchInterval * 1000));
|
|
107
|
+
const rawData = await fetchPRComments(owner, repo, prNumber, token, proxyFetch);
|
|
108
|
+
const processed = processComments(rawData);
|
|
109
|
+
const filtered = filterComments(processed, options);
|
|
110
|
+
const newComments = filtered.filter((cm) => !seenIds.has(cm.id));
|
|
111
|
+
if (newComments.length > 0) {
|
|
112
|
+
for (const cm of newComments) {
|
|
113
|
+
seenIds.add(cm.id);
|
|
114
|
+
}
|
|
115
|
+
// Grace period for bot batches
|
|
116
|
+
await new Promise((r) => setTimeout(r, 5_000));
|
|
117
|
+
const graceData = await fetchPRComments(owner, repo, prNumber, token, proxyFetch);
|
|
118
|
+
const graceProcessed = processComments(graceData);
|
|
119
|
+
const graceFiltered = filterComments(graceProcessed, options);
|
|
120
|
+
for (const cm of graceFiltered) {
|
|
121
|
+
if (!seenIds.has(cm.id)) {
|
|
122
|
+
seenIds.add(cm.id);
|
|
123
|
+
newComments.push(cm);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return { newComments, total: newComments.length, timedOut: false };
|
|
127
|
+
}
|
|
128
|
+
if (Math.round((Date.now() - startTime) / 1000) >= options.watchTimeout) {
|
|
129
|
+
return { newComments: [], total: 0, timedOut: true };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=reviews.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviews.js","sourceRoot":"","sources":["../../src/commands/reviews.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type RepoInfo, type ProxyFetch } from "./github/index.js";
|
|
2
|
+
export interface Context {
|
|
3
|
+
token: string;
|
|
4
|
+
repoInfo: RepoInfo;
|
|
5
|
+
proxyFetch: ProxyFetch;
|
|
6
|
+
}
|
|
7
|
+
export declare function bootstrap(): Promise<Context>;
|
|
8
|
+
export declare function resolvePR(ctx: Context, prArg?: number): Promise<{
|
|
9
|
+
prNumber: number;
|
|
10
|
+
prUrl: string;
|
|
11
|
+
headSha?: string;
|
|
12
|
+
}>;
|
|
13
|
+
//# sourceMappingURL=context.d.ts.map
|