opencode GitHub Action 实战指南:在 Issue 与 PR 评论区驱动编码代理
【免费下载链接】opencodeThe open source coding agent.项目地址: https://gitcode.com/GitHub_Trending/openc/opencode
opencode 提供了一套官方 GitHub Action,把 opencode 编码代理直接嵌入 GitHub 工作流:在 Issue 或 PR 中评论/opencode,Action 就会在 Actions Runner 上拉取代码、读取完整上下文、执行任务,并把结果(回复、新分支或 PR)写回评论区。本文以仓库中的 github/README.md 为核心,结合 github/index.ts 的完整实现与 github/action.yml 的输入参数定义,逐段讲解该 Action 的使用方式、参数细节与本地调试方法。读完本文,你可以独立完成安装、配置,并能在不出触发真实 Workflow 的情况下用 Mock 事件复现全链路行为。
四种典型用法
README 给出了四类触发场景,核心交互方式都是“评论里带上触发词”:
解释 Issue:在 Issue 中留下评论
/opencode explain this issue,opencode 会读取整个线程(包括全部评论)并回复清晰的解释。修复 Issue:评论
/opencode fix this,opencode 会创建新分支、实现改动,并自动开一个 PR 提交这些变更。评审并修改 PR:在 PR 中留下评论(如
Delete the attachment from S3 when the note is removed /oc),opencode 会实现所请求的修改,并把提交直接推到该 PR 分支上。针对具体代码行评论:在 PR 的 “Files” 标签页直接对某几行代码评论,例如:
/oc add error handling hereopencode 会自动检测到被评论的文件、行号和 diff 上下文,从而给出更精准的响应。从源码 github/index.ts 的
getReviewCommentContext()可以看到,它从pull_request_review_comment事件载荷中提取的信息包括:- 被评审的精确文件路径(
payload.comment.path) - 具体行号(
line/original_line/position) - 周围的 diff hunk(
diff_hunk) - 提交定位信息(
commit_id/original_commit_id)
这意味着行级评论场景下无需手动写明文件路径和行号。
- 被评审的精确文件路径(
触发词支持/opencode和/oc两种写法,且必须作为独立 token 出现。这一点在 github/index.ts 的assertPayloadKeyword()中由正则(?:^|\s)(?:\/opencode|\/oc)(?=$|\s)强制校验:不满足时 Action 直接报错Comments must mention /opencode or /oc。
安装与配置
一键安装
在仓库目录下的终端执行:
opencode github install该命令会引导你完成 GitHub App 安装、Workflow 文件创建和 Secrets 配置。命令的存在可以在 CLI 帮助快照中确认:help-snapshots.test.ts.snap 中列出了opencode github install(install the GitHub agent)与opencode github run(run the GitHub agent)两个子命令,其处理逻辑位于 github.handler.ts。
手动安装
如果不想走交互流程,可以手动完成三步:
安装名为
opencode-agent的 GitHub App,并确保它安装到了目标仓库上(README 给出的 App 入口为github.com/apps/opencode-agent)。在仓库中添加工作流文件
.github/workflows/opencode.yml,并按需设置model与环境变量中的 API Key。README 中的完整模板如下:name: opencode on: issue_comment: types: [created] pull_request_review_comment: types: [created] jobs: opencode: if: | contains(github.event.comment.body, '/oc') || contains(github.event.comment.body, '/opencode') runs-on: ubuntu-latest permissions: id-token: write steps: - name: Checkout repository uses: actions/checkout@v6 with: fetch-depth: 1 persist-credentials: false - name: Run opencode uses: anomalyco/opencode/github@latest env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: model: anthropic/claude-sonnet-4-20250514 use_github_token: true注意几个关键细节:
on只监听issue_comment与pull_request_review_comment的created事件,与 github/index.ts 中assertContextEvent("issue_comment", "pull_request_review_comment")支持的事件类型严格一致,其他事件类型会直接抛错。permissions: id-token: write是 OIDC 令牌交换所必需的,源码中通过core.getIDToken("opencode-github-action")获取 OIDC 令牌(见下文“令牌获取”小节)。if条件做的是粗过滤,真正的关键词校验由 Action 内部完成,二者互补。- 模板中
use_github_token: true表示直接使用GITHUB_TOKEN环境变量,跳过 GitHub App 的 OIDC 令牌交换;若不用该选项,则由opencode-agentApp 的 Installation Token 访问你的仓库。
在组织或项目的Settings → Secrets and variables → Actions中存储所需的 API Key(如
ANTHROPIC_API_KEY)。
Action 输入参数详解
github/action.yml 将该 Action 声明为一个composite复合 Action,并定义了如下输入项(这是 README 未展开、但配置时非常实用的部分):
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
model | 是 | — | 使用的模型,格式必须为provider/model,如anthropic/claude-sonnet-4-20250514 |
agent | 否 | — | 使用的 Agent 名。必须是 primary agent;找不到时回退到配置中的 default agent 或build |
share | 否 | 公共仓库默认 true | 是否分享 opencode 会话链接 |
prompt | 否 | — | 自定义 prompt,覆盖默认提示词 |
use_github_token | 否 | false | 为true时跳过 OIDC 交换,直接使用GITHUB_TOKEN环境变量 |
mentions | 否 | /opencode,/oc | 逗号分隔的触发词列表(不区分大小写) |
variant | 否 | — | 模型变体,用于 provider 特定的推理强度(如high、max、minimal) |
oidc_base_url | 否 | https://api.opencode.ai | OIDC 令牌交换 API 的基础地址,仅自装 GitHub App 时需要 |
model的格式校验在 github/index.ts 的useEnvModel()中实现:按第一个/拆分为providerID与modelID,任一部分为空即抛出Invalid model ... Model must be in the format "provider/model"。agent的处理见resolveAgent()(github/index.ts):通过 SDK 拉取 agent 列表做名称匹配,若不存在或属于 subagent,会告警并回退默认 agent。
复合 Action 自身的执行步骤为:
- 获取版本:请求 opencode 仓库的最新 release tag,写入
version输出; - 缓存:以
opencode-${runner.os}-${runner.arch}-${version}为 key 缓存~/.opencode/bin; - 安装:缓存未命中时执行
curl -fsSL https://opencode.ai/install | bash; - 加入 PATH:追加
$HOME/.opencode/bin; - 运行:调用
opencode github run,并把上述输入项原样透传为环境变量(MODEL、AGENT、SHARE、PROMPT、USE_GITHUB_TOKEN、MENTIONS、VARIANT、OIDC_BASE_URL,见 action.yml)。
依赖方面,该包 github/package.json 声明了@actions/core、@actions/github、@octokit/rest、@octokit/graphql与 workspace 内的@opencode-ai/sdk,即 GitHub 侧走 Octokit(REST + GraphQL),与 opencode 服务端通信走官方 SDK。
源码视角下的执行流程
github/index.ts 的主流程(第 127–229 行)是一条线性 pipeline,按顺序完成校验、准备、会话建立与结果写回,理解它对排查线上问题很有帮助。
1. 启动本地 opencode 服务并等待就绪
createOpencode()(github/index.ts)通过spawn启动opencode serve --hostname=127.0.0.1 --port=4096,并用createOpencodeClient({ baseUrl })建立客户端。随后assertOpencodeConnected()(github/index.ts)以 300ms 间隔、最多 30 次重试探测服务日志接口,失败则抛出Failed to connect to opencode server。
2. 令牌获取:OIDC 交换 vs GITHUB_TOKEN
getAccessToken()(github/index.ts)有三条路径:
- 若设置了
TOKEN环境变量(对应use_github_token: true),直接使用该令牌; - 正常生产路径:
core.getIDToken("opencode-github-action")换取 OIDC 令牌,再 POST 到https://api.opencode.ai/exchange_github_app_token,用opencode-agentApp 的 Installation 身份换取安装令牌; - Mock 路径(本地调试):以
MOCK_TOKEN(个人访问令牌)POST 到.../exchange_github_app_token_with_pat,同时带上{ owner, repo }。
拿到令牌后,assertPermissions()(github/index.ts)通过 REST 的getCollaboratorPermissionLevel检查发起评论的用户是否具备admin或write权限,否则拒绝执行;使用TOKEN时跳过该检查。
3. Prompt 组装:评论文本 + 图片附件
getUserPrompt()(github/index.ts)负责把评论转化为发给模型的 prompt:
- 评论体恰好是
/opencode或/oc时:行级评论场景生成“评审指定文件与行的改动并给出改进建议”的模板(含文件、行号、diff hunk);普通场景则使用Summarize this thread。 - 评论体包含触发词时:直接取评论正文作为 prompt;行级评论场景会额外追加
Context: You are reviewing a comment on file "..." at line ...与Diff context段落。 - 图片与附件解析:用两组正则分别匹配 Markdown 图片/链接语法(
!?\[.*?\]\((https:\/\/github\.com\/user-attachments\/[^)]+)\))与<img src="..."/>标签,命中后逐个fetch下载(带 Bearer 令牌),把 prompt 中的原 URL 原地替换为@文件名,并把下载内容以 base64 形式存入promptFiles。这些文件随后在chat()(github/index.ts)中作为type: "file"的 part(data:${mime};base64,...形式的 URL)随消息一起发送。content-type不是image/*时会按text/plain处理,因此附件不限于图片。
4. 会话创建与事件订阅
主流程创建 opencode 会话(client.session.create),并通过subscribeSessionEvents()(github/index.ts)打开 SSE 事件流${server.url}/event,实时把message.part.updated事件中的工具调用(todowrite、bash、edit、glob、grep、list、read、write、websearch各配一种 ANSI 颜色前缀)和文本输出打印到 Actions 日志,方便在运行记录里观察 agent 行为。
若允许分享(SHARE环境变量;未显式设置时私有仓库不分享),会调用client.session.share,并在后续回复中附带opencode.ai/s/<8位会话尾缀>的会话链接(footer 还会生成一张基于会话标题的社交卡片图片和指向本次 GitHub Run 的链接)。
5. 三种执行分支
代码按事件来源分成三个分支(github/index.ts):
- Issue 分支:
checkoutNewBranch()创建opencode/issue<编号>-<时间戳>形式的分支(generateBranchName(),github/index.ts);通过 GraphQL 拉取 Issue 标题、正文、作者、全部评论(buildPromptDataForIssue(),github/index.ts 会剔除本次 Action 自己刚创建的占位评论和触发评论本身),拼入<issue>上下文中发给模型。若工作区有改动(branchIsDirty()检查git status --porcelain),则推送新分支并创建 PR,PR 正文包含模型回复与Closes #<issue>;评论区更新为Created PR #<n>。若没有改动,则直接把模型回复写回评论。 - 同仓库 PR 分支:
checkoutLocalBranch()以max(commits.totalCount, 20)的深度 fetch 并 checkout 目标分支;PR 上下文由buildPromptDataForPR()(github/index.ts)构建,包含标题、正文、base/head 分支、增删行数、commit 列表、改动文件清单、全部 PR 评论以及所有 review(含行级评论的path:line);改动直接 commit 并 push 回该 PR 分支。 - Fork PR 分支:
checkoutForkBranch()(github/index.ts)添加名为fork的远程指向 fork 仓库,fetch 后建本地跟踪分支;完成后git push fork HEAD:<原分支>推回 fork,保持 PR 可见。
三个分支共同点:提交信息是模型生成的短摘要——summarize()(github/index.ts)让模型把回复压到 40 字符以内,失败时回退为Fix issue: <issue 标题>;每次 commit 都会追加Co-authored-by: <评论者> <评论者>@users.noreply.github.com。
6. Git 凭据注入与清理
configureGit()(github/index.ts)在开始前备份本地http.https://github.com/.extraheader,并写入基于 App 令牌的AUTHORIZATION: basic <base64(x-access-token:token)>,使 git push 使用 Installation 身份而不是 checkout 的凭据(所以 Workflow 模板中persist-credentials: false)。finally块(github/index.ts)保证无论如何都会:关闭 opencode 服务、恢复原 git config、并调用revokeAppToken()(github/index.ts)向https://api.github.com/installation/token发 DELETE 请求吊销刚换取的 Installation 令牌。出错时(含 bunShellError,会取 stderr 作为消息)同样会把错误信息写回评论并core.setFailed。
本地调试:不触发真实 Workflow 的 Mock 流程
README 的 Development 一节提供了完整的本地复现方式。先切到任意测试仓库,然后执行:
MODEL=anthropic/claude-sonnet-4-20250514 \ ANTHROPIC_API_KEY=sk-ant-api03-1234567890 \ GITHUB_RUN_ID=dummy \ MOCK_TOKEN=github_pat_1234567890 \ MOCK_EVENT='{"eventName":"issue_comment",...}' \ bun /path/to/opencode/github/index.ts各环境变量的含义:
MODEL:opencode 使用的模型,与工作流中model输入一致,须为provider/model格式;ANTHROPIC_API_KEY:模型 provider 的 API Key,与工作流 env 中的 Key 对应;GITHUB_RUN_ID:伪造的 Run ID,用于生成回复里的 GitHub Run 链接(useEnvRunUrl()拼接为/<owner>/<repo>/actions/runs/<id>);MOCK_TOKEN:你的 GitHub 个人访问令牌,用于验证你对测试仓库具有admin或write权限(可在 GitHub 的个人访问令牌设置页生成);设置MOCK_EVENT或MOCK_TOKEN任一即进入 Mock 模式(isMock(),github/index.ts),此时useContext()改从MOCK_EVENTJSON 解析事件上下文;MOCK_EVENT:模拟的 GitHub 事件载荷,模板见下;/path/to/opencode:你克隆的 opencode 仓库路径,bun .../github/index.ts即运行你本地的 Action 入口。
注意 Mock 模式下configureGit()会直接跳过(不改本地 git 配置),分享链接前缀也会切换为开发域名(useShareUrl()返回https://dev.opencode.ai,见 github/index.ts)。
事件模板
Issue 评论事件:
MOCK_EVENT='{"eventName":"issue_comment","repo":{"owner":"sst","repo":"hello-world"},"actor":"fwang","payload":{"issue":{"number":4},"comment":{"id":1,"body":"hey opencode, summarize thread"}}}'替换项:"owner":"sst"为仓库拥有者、"repo":"hello-world"为仓库名、"actor":"fwang"为评论者 GitHub 用户名、"number":4为 Issue 编号、"body"为评论正文。
带图片附件的 Issue 评论:
MOCK_EVENT='{"eventName":"issue_comment","repo":{"owner":"sst","repo":"hello-world"},"actor":"fwang","payload":{"issue":{"number":4},"comment":{"id":1,"body":"hey opencode, what is in my image "}}}'把https://github.com/user-attachments/assets/xxxxxxxx替换为有效的 GitHub 附件 URL(可在任意 Issue 中发一条带图评论生成一个)。
PR 评论事件(与 Issue 评论的区别是issue中带pull_request字段,isPullRequest()据此判断):
MOCK_EVENT='{"eventName":"issue_comment","repo":{"owner":"sst","repo":"hello-world"},"actor":"fwang","payload":{"issue":{"number":4,"pull_request":{}},"comment":{"id":1,"body":"hey opencode, summarize thread"}}}'PR 行级评审评论事件(对应pull_request_review_comment,携带文件路径、diff hunk、行号等字段):
MOCK_EVENT='{"eventName":"pull_request_review_comment","repo":{"owner":"sst","repo":"hello-world"},"actor":"fwang","payload":{"pull_request":{"number":7},"comment":{"id":1,"body":"hey opencode, add error handling","path":"src/components/Button.tsx","diff_hunk":"@@ -45,8 +45,11 @@\n- const handleClick = () => {\n- console.log('clicked')\n+ const handleClick = useCallback(() => {\n+ console.log('clicked')\n+ doSomething()\n+ }, [doSomething])","line":47,"original_line":45,"position":10,"commit_id":"abc123","original_commit_id":"def456"}}}'延伸阅读:仓库中的相关文件
- github/README.md:本 Action 的官方使用文档,即本文主骨架;
- github/index.ts:Action 入口,完整实现事件校验、令牌交换、prompt 组装、三分支执行与清理逻辑;
- github/action.yml:复合 Action 定义与全部输入参数;
- github/package.json:依赖声明(Octokit、@actions 系列、@opencode-ai/sdk);
- packages/opencode/src/cli/cmd/github.handler.ts:
opencode github install/opencode github run子命令的处理实现; - packages/function/src/api.ts:其中
exchange_github_app_token_with_pat端点用于本地测试opencode github run时用 PAT 换取 Installation 访问令牌。
需要提醒的是,README 在 Support 一节明确说明这是 early release;本文所有行为描述均以当前仓库源码为准,实际参数与端点若后续版本有调整,请以仓库最新代码为最终依据。
【免费下载链接】opencodeThe open source coding agent.项目地址: https://gitcode.com/GitHub_Trending/openc/opencode
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考