diff --git a/index.ts b/index.ts index d3acf3e..1eea5ac 100644 --- a/index.ts +++ b/index.ts @@ -193,7 +193,7 @@ try { proc = spawn(`opencode`, [`serve`, `--hostname=${HOST}`, `--port=${PORT}`], { stdio: ["ignore", "inherit", "inherit"], }) - assertContextEvent("issue_comment", "pull_request_review_comment") + assertContextEvent("issue_comment", "pull_request_review_comment", "pull_request_review") assertPayloadKeyword() await assertOpencodeConnected() await opencodeLog({ service: "forgejo-workflow", level: "info", message: "Prepare to react to Forgejo Workflow event" }) @@ -338,9 +338,17 @@ async function forgejoFetch(url: string, options?: RequestInit): Promise { return res.json() as Promise } +function getTriggerBody(): string { + const context = useContext() + const p = context.payload as any + if (context.eventName === "pull_request_review") { + return (p.review?.body ?? "").toString() + } + return (p.comment?.body ?? "").toString() +} + function assertPayloadKeyword() { - const payload = useContext().payload as IssueCommentEvent | PullRequestReviewCommentEvent - const body = payload.comment.body.trim() + const body = getTriggerBody().trim() const mentions = (process.env["MENTIONS"] || "/opencode,/oc").split(",").map((m) => m.trim()) const escaped = mentions.map((m) => m.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|") const regex = new RegExp(`(?:^|\\s)(?:${escaped})(?=$|\\s)`, "i") @@ -446,12 +454,19 @@ function useContext() { } function useIssueId() { - const payload = useContext().payload as IssueCommentEvent - return payload.issue.number + const context = useContext() + const p = context.payload as any + if (context.eventName === "pull_request_review") { + return p.pull_request.number as number + } + return p.issue.number as number } function isPullRequest() { const context = useContext() + if (context.eventName === "pull_request_review" || context.eventName === "pull_request_review_comment") { + return true + } const payload = context.payload as IssueCommentEvent return Boolean((payload as any).issue?.pull_request) } @@ -486,8 +501,9 @@ type ForgejoRepoInfo = { async function createComment(): Promise { const context = useContext() - const payload = context.payload as IssueCommentEvent - const issueIndex = (payload.issue as any).index ?? payload.issue.number + const p = context.payload as any + const target = context.eventName === "pull_request_review" ? p.pull_request : p.issue + const issueIndex = target.index ?? target.number console.log("Creating comment...") return await forgejoFetch( @@ -522,8 +538,8 @@ async function fetchPR(): Promise { const context = useContext() - const payload = context.payload as IssueCommentEvent - const prNumber = payload.issue.number + const p = context.payload as any + const prNumber = (context.eventName === "pull_request_review" ? p.pull_request.number : p.issue.number) as number console.log("Fetching prompt data for PR #", prNumber) // 1. Get PR info @@ -910,21 +926,29 @@ async function chat(text: string, files: PromptFiles = []) { async function getUserPrompt(): Promise<{ userPrompt: string; promptFiles: PromptFiles }> { const context = useContext() - const payload = context.payload as IssueCommentEvent | PullRequestReviewCommentEvent + const p = context.payload as any const reviewContext = getReviewCommentContext() + const isReviewSubmission = context.eventName === "pull_request_review" + const reviewState: string | undefined = isReviewSubmission ? p.review?.state : undefined let prompt = (() => { - const body = payload.comment.body.trim() + const body = getTriggerBody().trim() if (body === "/opencode" || body === "/oc") { if (reviewContext) { return `Review this code change and suggest improvements for the commented lines:\n\nFile: ${reviewContext.file}\nLines: ${reviewContext.line}\n\n${reviewContext.diffHunk}` } + if (isReviewSubmission) { + return `Address the feedback from this pull request review (state: ${reviewState ?? "unknown"}).` + } return "Summarize this thread" } if (body.includes("/opencode") || body.includes("/oc")) { if (reviewContext) { return `${body}\n\nContext: You are reviewing a comment on file "${reviewContext.file}" at line ${reviewContext.line}.\n\nDiff context:\n${reviewContext.diffHunk}` } + if (isReviewSubmission) { + return `${body}\n\nContext: This was submitted as part of a pull request review (state: ${reviewState ?? "unknown"}).` + } return body } throw new Error("Comments must mention /opencode or /oc")