Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 40 additions & 9 deletions github/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,19 @@ function createOpencode() {
}
}

function useEnvMentions(): string[] {
return (process.env["MENTIONS"] || "/opencode,/oc")
.split(",")
.map((m) => m.trim().toLowerCase())
.filter(Boolean)
}

function assertPayloadKeyword() {
const payload = useContext().payload as IssueCommentEvent | PullRequestReviewCommentEvent
const body = payload.comment.body.trim()
if (!body.match(/(?:^|\s)(?:\/opencode|\/oc)(?=$|\s)/)) {
throw new Error("Comments must mention `/opencode` or `/oc`")
const body = payload.comment.body.trim().toLowerCase()
const mentions = useEnvMentions()
if (!mentions.some((m) => body === m || body.includes(m))) {
throw new Error(`Comments must mention ${mentions.map((m) => "`" + m + "`").join(" or ")}`)
}
}

Expand Down Expand Up @@ -339,7 +347,17 @@ function useEnvMock() {
}

function useEnvGithubToken() {
return process.env["TOKEN"]
const value = process.env["USE_GITHUB_TOKEN"]
if (!value || value === "false") return undefined
if (value === "true") {
const token = process.env["GITHUB_TOKEN"]
if (!token)
throw new Error(
"GITHUB_TOKEN environment variable is not set. When using use_github_token, you must provide GITHUB_TOKEN.",
)
return token
}
throw new Error(`Invalid use_github_token value: ${value}. Must be a boolean.`)
}

function isMock() {
Expand All @@ -353,6 +371,10 @@ function isPullRequest() {
return Boolean(payload.issue.pull_request)
}

function isScheduleEvent() {
return useContext().eventName === "schedule"
}

function useContext() {
return isMock() ? (JSON.parse(useEnvMock().mockEvent!) as GitHubContext) : github.context
}
Expand All @@ -366,15 +388,22 @@ function useShareUrl() {
return isMock() ? "https://dev.opencode.ai" : "https://opencode.ai"
}

function useEnvOidcBaseUrl() {
const value = process.env["OIDC_BASE_URL"]
if (!value) return "https://api.opencode.ai"
return value.replace(/\/+$/, "")
}

async function getAccessToken() {
const { repo } = useContext()

const envToken = useEnvGithubToken()
if (envToken) return envToken

const oidcBaseUrl = useEnvOidcBaseUrl()
let response
if (isMock()) {
response = await fetch("https://api.opencode.ai/exchange_github_app_token_with_pat", {
response = await fetch(`${oidcBaseUrl}/exchange_github_app_token_with_pat`, {
method: "POST",
headers: {
Authorization: `Bearer ${useEnvMock().mockToken}`,
Expand All @@ -383,7 +412,7 @@ async function getAccessToken() {
})
} else {
const oidcToken = await core.getIDToken("opencode-github-action")
response = await fetch("https://api.opencode.ai/exchange_github_app_token", {
response = await fetch(`${oidcBaseUrl}/exchange_github_app_token`, {
method: "POST",
headers: {
Authorization: `Bearer ${oidcToken}`,
Expand Down Expand Up @@ -416,21 +445,23 @@ async function getUserPrompt() {
const payload = context.payload as IssueCommentEvent | PullRequestReviewCommentEvent
const reviewContext = getReviewCommentContext()

const mentions = useEnvMentions()
let prompt = (() => {
const body = payload.comment.body.trim()
if (body === "/opencode" || body === "/oc") {
const bodyLower = body.toLowerCase()
if (mentions.some((m) => bodyLower === m)) {
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}`
}
return "Summarize this thread"
}
if (body.includes("/opencode") || body.includes("/oc")) {
if (mentions.some((m) => bodyLower.includes(m))) {
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}`
}
return body
}
throw new Error("Comments must mention `/opencode` or `/oc`")
throw new Error(`Comments must mention ${mentions.map((m) => "`" + m + "`").join(" or ")}`)
})()

// Handle images
Expand Down