Initial documentation for route A (port claude-code-action to Gitea Actions). Research complete, no implementation code yet. See docs/02-roadmap.md for milestones.
112 lines
4.1 KiB
Markdown
112 lines
4.1 KiB
Markdown
# 02 - 路线图
|
||
|
||
## 调研结论(2026-05-25)
|
||
|
||
调研了 4 个候选 OSS:
|
||
|
||
| 项目 | Stars | 契合度 | 结论 |
|
||
|---|---|---|---|
|
||
| anthropics/claude-code-action | 7.7k | ⭐⭐⭐⭐⭐ | **GitHub Only**,移植到 Gitea 是这次项目的核心工作 |
|
||
| All-Hands-AI/OpenHands | 40k+ | ⭐⭐⭐ | 非 Claude 原生,Gitea 支持弱,引入了大量不需要的东西 |
|
||
| SWE-agent/SWE-agent | 19.3k | ⭐⭐ | 学术为主,一次性自动修,不擅长多轮交互 |
|
||
| Turrain/claude-gitea-app | 1 | ⭐⭐⭐ | 名字对路但太小(20KB),不能依赖 |
|
||
|
||
**Gitea 生态周边可复用**:
|
||
|
||
- [Sqcows/forgejo-mcp](https://github.com/Sqcows/forgejo-mcp) — Forgejo/Gitea MCP server,103 工具
|
||
- [pkulik0/gitea-skill](https://github.com/pkulik0/gitea-skill) — `tea` CLI 的 Claude Code Skill
|
||
|
||
**结论**:复刻 `claude-code-action` 是最直接的路径,OpenHands 等通用方案在交互性上不及。
|
||
|
||
---
|
||
|
||
## 路线 A:移植 `claude-code-action` 到 Gitea Actions(当前阶段)
|
||
|
||
**目标**:端到端跑通最小可用版本,体感先达到 "issue 里说话 → Claude 在评论里回复 → 同意后 PR 自动开"。
|
||
|
||
### Milestone A1:基础设施(第 1 周)
|
||
|
||
- [ ] fork upstream,确定 TS/Bun 工具链能在 act_runner 里跑
|
||
- [ ] 在 Gitea 控制面板创建 `@claude` bot 用户 + 对应 access token
|
||
- [ ] 验证 Gitea webhook → workflow_dispatch 链路
|
||
- [ ] 写 Gitea API 客户端(`src/gitea/api/`),覆盖:
|
||
- 评论 CRUD
|
||
- issue/PR 读取
|
||
- 分支创建 + push
|
||
- PR 创建
|
||
|
||
### Milestone A2:tag 模式跑通(第 2 周)
|
||
|
||
- [ ] 移植 `src/modes/tag/`(@claude 触发的最常用模式)
|
||
- [ ] 移植 `src/create-prompt/`(基本不动,确认 context 字段映射)
|
||
- [ ] 移植 `src/entrypoints/`(适配 Gitea 事件载荷格式)
|
||
- [ ] `.gitea/workflows/claude.yml` 示例工作流
|
||
- [ ] 在本仓库自己开 issue 验证"对话+提 PR"流程
|
||
|
||
### 验收标准
|
||
|
||
```
|
||
1. 我在某个 Gitea 仓库开 issue:「加一个返回当前时间的 /now 接口」
|
||
2. issue 正文末尾 @claude
|
||
3. 1 分钟内出现 Claude 评论:「先确认几点... a/b/c」
|
||
4. 我回复评论:「a 这样,b 那样」
|
||
5. Claude 再回复对齐 + 开始执行
|
||
6. Claude push 分支 + 开 PR,PR 描述里贴着完整对话和实现说明
|
||
```
|
||
|
||
---
|
||
|
||
## 路线 B:长驻 webhook 服务(未来)
|
||
|
||
**触发条件**:路线 A 跑通后,发现每轮交互 30s+ 冷启动太难受,再启动 B。
|
||
|
||
### 架构差异
|
||
|
||
```
|
||
路线 A:每次评论 → 启动 Action → 加载 context → 退出 (冷)
|
||
路线 B:每次评论 → POST 到长驻服务 → 复用 Claude session → 立刻回复 (热)
|
||
```
|
||
|
||
### 主要工作
|
||
|
||
- 用 Python 或 Node 写一个常驻 webhook server(FastAPI / Hono)
|
||
- 用 `@anthropic-ai/claude-agent-sdk` 维护 `{issue_id: ClaudeSession}` 字典
|
||
- 每条 Gitea 评论 webhook → 找到对应 session → `session.send_message()` → 回写评论
|
||
- 长会话超时回收策略(24h 不活跃释放)
|
||
- 加载 superpowers skills([skills 目录注入](https://docs.claude.com/api/agent-sdk))
|
||
- 部署:和 Gitea 同机 docker-compose,加一个 `claude-agent` 服务
|
||
|
||
### 升级路径
|
||
|
||
设计路线 A 代码时已保留两个抽象接口:
|
||
|
||
```typescript
|
||
interface EventDispatcher {
|
||
// A: read GITEA_EVENT_PATH file
|
||
// B: subscribe to webhook stream
|
||
next(): Promise<GiteaEvent>
|
||
}
|
||
|
||
interface SessionStore {
|
||
// A: fresh prompt each run
|
||
// B: persistent ClaudeSession per issue
|
||
get(key: string): Promise<Session>
|
||
save(key: string, session: Session): Promise<void>
|
||
}
|
||
```
|
||
|
||
切换路线时只需新实现这两个接口,核心业务逻辑(trigger 解析、Gitea API、PR 流程)不动。
|
||
|
||
---
|
||
|
||
## 不做的事(明确拒绝)
|
||
|
||
- ❌ **不**追求支持 GitHub + Gitea + GitLab 多平台。Gitea-only,避免抽象税
|
||
- ❌ **不**在路线 A 阶段做 Web UI / dashboard。命令行 + Gitea 评论已够
|
||
- ❌ **不**做"全自动决策合并 PR"。Claude 提 PR,人审核合并
|
||
- ❌ **不**移植上游所有 mode(review/agent 等),只做 tag mode
|
||
|
||
## 决策记录
|
||
|
||
非显然的设计选择记在 [04-decisions.md](04-decisions.md)。
|