项目文件夹

文件
wehub-resource-sync b3a7f98e5a
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:23:53 +08:00

89 行
2.9 KiB
TypeScript

// Classify a reporter's reply to the bot's verification ask.
//
// Triggered by .github/workflows/reporter-reply.yml when the issue
// author comments on an issue that has the `triage/awaiting-reporter`
// label. The workflow YAML reads the classification from this run's
// output and decides whether to open a PR, retry, or ask for
// clarification.
//
// Cheap kimi prompt, no sandbox, no skills. Just structured output.
import type { FlueContext } from "@flue/runtime";
import { withCapacityRetry } from "../lib/capacity.js";
import {
classifier,
persistClassifierResult,
replyClassificationSchema,
type ReplyClassification,
} from "../lib/classifier.js";
interface ClassifyReplyPayload {
issueNumber: number;
replyBody: string;
/**
* The bot's original ask, so the model can decide what "yes" or
* "no" is in reference to. The orchestrator passes the previous
* bot comment body verbatim.
*/
botAsk?: string;
}
export async function run({
init,
payload,
log,
}: FlueContext<ClassifyReplyPayload>): Promise<ReplyClassification> {
if (!payload.replyBody) {
throw new Error("payload.replyBody is required");
}
const harness = await init(classifier);
const session = await harness.session();
const prompt = [
"You are reading a GitHub issue reporter's reply to the EmDash investigation bot's verification request.",
"Decide whether the reply confirms the proposed fix works, says it does not, or is too ambiguous to act on.",
"",
"## Bot's ask",
"",
payload.botAsk ??
"(unavailable; assume the bot asked the reporter to install a preview release and confirm whether their bug is fixed)",
"",
"## Reporter's reply",
"",
payload.replyBody,
"",
"## How to decide",
"",
"- `positive` -- the reporter clearly says the fix works, the bug is gone, the preview works, or otherwise indicates success.",
"- `negative` -- the reporter says the fix does not work, the bug persists, they hit a new problem, or the fix is wrong.",
"- `unclear` -- the reply is off-topic, asks a question without answering, requests changes without confirming or denying, or is too short to tell.",
"",
"Default to `unclear` when in doubt. A wrong `positive` opens a PR; a wrong `negative` re-runs an expensive investigation.",
"",
"Quote the specific phrase that drove your decision in the reasoning field.",
].join("\n");
const { data } = await withCapacityRetry(
(signal) => session.prompt(prompt, { result: replyClassificationSchema, signal }),
{
label: `classify-reply#${payload.issueNumber}`,
attempts: 4,
perAttemptTimeoutMs: 90_000,
onRetry: ({ attempt, delayMs, error }) =>
log.warn?.("model over capacity, backing off", {
issueNumber: payload.issueNumber,
attempt,
delayMs,
error: String(error),
}),
},
);
log.info("classified reply", {
issueNumber: payload.issueNumber,
classification: data.classification,
});
return persistClassifierResult(data);
}