feat(daemon): add opencode as supported agent provider (#341)

* feat(daemon): add opencode as supported agent provider

Add opencode backend alongside claude and codex. The backend spawns
`opencode run --format json`, parses streaming JSON events (text,
tool_use, error, step_start/finish), and supports --prompt for system
prompts. Includes CLI detection, AGENTS.md runtime config, native skill
discovery via .config/opencode/skills/, and 21 tests covering handlers,
JSON parsing, and integration-level processEvents scenarios.

* chore: add .tool-versions to gitignore
This commit is contained in:
Quake Wang 2026-04-02 18:52:07 +09:00 committed by GitHub
parent 09764c5f51
commit 36db325d50
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 1203 additions and 23 deletions

View file

@ -10,15 +10,16 @@ import (
// InjectRuntimeConfig writes the meta skill content into the runtime-specific
// config file so the agent discovers its environment through its native mechanism.
//
// For Claude: writes {workDir}/CLAUDE.md (skills discovered natively from .claude/skills/)
// For Codex: writes {workDir}/AGENTS.md (skills discovered natively via CODEX_HOME)
// For Claude: writes {workDir}/CLAUDE.md (skills discovered natively from .claude/skills/)
// For Codex: writes {workDir}/AGENTS.md (skills discovered natively via CODEX_HOME)
// For OpenCode: writes {workDir}/AGENTS.md (skills discovered natively from .config/opencode/skills/)
func InjectRuntimeConfig(workDir, provider string, ctx TaskContextForEnv) error {
content := buildMetaSkillContent(provider, ctx)
switch provider {
case "claude":
return os.WriteFile(filepath.Join(workDir, "CLAUDE.md"), []byte(content), 0o644)
case "codex":
case "codex", "opencode":
return os.WriteFile(filepath.Join(workDir, "AGENTS.md"), []byte(content), 0o644)
default:
// Unknown provider — skip config injection, prompt-only mode.
@ -114,8 +115,8 @@ func buildMetaSkillContent(provider string, ctx TaskContextForEnv) string {
case "claude":
// Claude discovers skills natively from .claude/skills/ — just list names.
b.WriteString("You have the following skills installed (discovered automatically):\n\n")
case "codex":
// Codex discovers skills natively via CODEX_HOME/skills/ — just list names.
case "codex", "opencode":
// Codex and OpenCode discover skills natively from their respective paths — just list names.
b.WriteString("You have the following skills installed (discovered automatically):\n\n")
default:
b.WriteString("Detailed skill instructions are in `.agent_context/skills/`. Each subdirectory contains a `SKILL.md`.\n\n")