Conversation
Add OpenCode API proxy support on port 10004, routing to Anthropic API (OpenCode's default BYOK provider). Dynamic port range calculation in host-iptables ensures future ports are auto-included. - src/types.ts: Add OPENCODE port 10004 to API_PROXY_PORTS - containers/api-proxy/server.js: Add OpenCode proxy listener (-> Anthropic) - containers/api-proxy/Dockerfile: Expose port 10004 - src/host-iptables.ts: Use Object.values() for dynamic port range Companion to github/gh-aw#18403 (OpenCode engine integration) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This pull request adds OpenCode as a new provider-agnostic agentic engine with BYOK (Bring Your Own Key) support. It enables users to integrate OpenCode CLI with support for 75+ models across multiple providers (Anthropic, OpenAI, Google, etc.). The PR includes full API proxy support on port 10004, MCP Gateway integration, headless CI mode support, and comprehensive test coverage.
Changes:
- Added OpenCode engine implementation with installation, execution, and MCP configuration support
- Integrated OpenCode with AWF firewall and LLM gateway proxy on port 10004
- Added MCP Gateway converter script for OpenCode-specific configuration format
- Created smoke test workflow with 5 integration tests and 22 unit tests
- Updated schema, constants, and test expectations to include the new engine
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/opencode_engine.go | Core OpenCode engine implementation with installation and execution logic |
| pkg/workflow/opencode_mcp.go | MCP configuration rendering for OpenCode JSON format |
| pkg/workflow/opencode_engine_test.go | 22 unit tests covering engine identity, secrets, installation, execution, and firewall integration |
| pkg/workflow/domains.go | Domain allowlist infrastructure with provider-specific domain mappings (not fully utilized) |
| pkg/workflow/agentic_engine.go | Engine registry updated to include OpenCode |
| pkg/constants/constants.go | OpenCode constants including version (1.2.14), LLM gateway port (10004), and environment variables |
| actions/setup/sh/convert_gateway_config_opencode.sh | Shell script to convert MCP Gateway config to OpenCode's opencode.jsonc format |
| actions/setup/sh/start_mcp_gateway.sh | Added OpenCode routing case to MCP gateway startup script |
| pkg/parser/schemas/main_workflow_schema.json | Added "opencode" to engine ID enum with description |
| .github/workflows/smoke-opencode.md | Smoke test workflow definition with 5 test requirements |
| .github/workflows/smoke-opencode.lock.yml | Compiled smoke test workflow (1386 lines) |
| pkg/constants/constants_test.go | Updated to expect 4 engines including "opencode" |
| pkg/cli/completions_test.go | Updated to expect 5 engines in completions |
Comments suppressed due to low confidence (1)
pkg/workflow/domains.go:155
- The
extractProviderFromModelfunction is exported (starts with lowercase 'e' but used outside its package context in tests), suggesting it should be used elsewhere. However, this function is never called from production code - only fromGetOpenCodeDefaultDomainswhich itself is never called. This function should be used to implement the dynamic domain selection feature mentioned in the PR description.
// extractProviderFromModel extracts the provider name from an OpenCode model string.
// OpenCode uses "provider/model" format (e.g., "anthropic/claude-sonnet-4-20250514").
// Returns the provider prefix, or "anthropic" as default if no slash is found.
func extractProviderFromModel(model string) string {
if model == "" {
return "anthropic"
}
parts := strings.SplitN(model, "/", 2)
if len(parts) < 2 {
return "anthropic"
}
return strings.ToLower(parts[0])
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
* feat: add API proxy port 10004 for OpenCode engine Add OpenCode API proxy support on port 10004, routing to Anthropic API (OpenCode's default BYOK provider). Dynamic port range calculation in host-iptables ensures future ports are auto-included. - src/types.ts: Add OPENCODE port 10004 to API_PROXY_PORTS - containers/api-proxy/server.js: Add OpenCode proxy listener (-> Anthropic) - containers/api-proxy/Dockerfile: Expose port 10004 - src/host-iptables.ts: Use Object.values() for dynamic port range Companion to github/gh-aw#18403 (OpenCode engine integration) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address PR review comments on OpenCode proxy - Fix log injection: extract sanitized values before template literal - Add comment explaining why OpenCode gets a separate port from Claude (rate limiting isolation, metrics, future multi-provider routing) - docker-manager.ts env var not needed: gh-aw passes ANTHROPIC_BASE_URL via --env-all at the GitHub Actions level Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Great! Add open code version checking to the cli version checker. Smoke aw can go with the same label as gemini |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
This PR adds the OpenCode engine integration. Two observations: (1) ANTHROPIC_API_KEY is always included in required secrets even for non-Anthropic providers, and (2) the opencode.jsonc config sets all permissions to "allow" as a CI workaround, removing OpenCode's native sandboxing. Both are reasonable pragmatic choices for an experimental engine, but worth noting for future improvement.
📰 BREAKING: Report filed by Smoke Copilot
| } | ||
| } | ||
|
|
||
| // Add MCP gateway API key if MCP servers are present |
There was a problem hiding this comment.
The secrets slice starts with ANTHROPIC_API_KEY hardcoded as the "default provider". Since OpenCode supports 75+ models via BYOK, consider making this configurable rather than always including ANTHROPIC_API_KEY. A user could be using OpenAI/Gemini without needing Anthropic at all, which could cause unnecessary validation failures.
|
|
||
| // generateOpenCodeConfigStep writes opencode.jsonc with all permissions set to allow | ||
| // to prevent CI hanging on permission prompts. | ||
| func (e *OpenCodeEngine) generateOpenCodeConfigStep(_ *WorkflowData) GitHubActionStep { |
There was a problem hiding this comment.
The configJSON string hardcodes all permissions as "allow" to prevent CI hanging. While practical, this disables OpenCode's permission sandboxing entirely. Consider documenting this as a known trade-off, or allowing users to override specific permissions via frontmatter configuration in a future iteration.
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤 |
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
💥 Automated smoke test review - all systems nominal! This is a verification run from the smoke-claude workflow (Run 22733626450). No blocking issues found.
💥 [THE END] — Illustrated by Smoke Claude
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add --print-logs and --log-level DEBUG to opencode run command to diagnose why the agent exits silently after 2 seconds. Keep API proxy enabled (port 10004) as the AWF helper now adds it unconditionally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
✅ All tools validated successfully! Agent Container Smoke Test confirms agent container is ready. |
|
🎬 THE END — Smoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨ |
|
🎯 Smoke OpenCode MISSION COMPLETE! OpenCode has delivered. ⚡ |
|
📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing... |
|
🌑 The shadows whisper... Smoke Codex failed. The oracle requires further meditation... |
Agent Container Tool Check
Result: 12/12 tools available ✅ Overall Status: PASS
|
|
✅ Smoke Test Results — Run §22734274382
Overall:
|
There was a problem hiding this comment.
This PR adds the OpenCode engine integration and replaces hardcoded /opt/gh-aw paths with the configurable ${GH_AW_HOME:-/opt/gh-aw} pattern. The changes are well-structured and follow existing engine patterns. 🚀
📰 BREAKING: Report filed by Smoke Copilot
| @@ -357,6 +357,7 @@ func NewEngineRegistry() *EngineRegistry { | |||
| registry.Register(NewCodexEngine()) | |||
| registry.Register(NewCopilotEngine()) | |||
| registry.Register(NewGeminiEngine()) | |||
| registry.Register(NewOpenCodeEngine()) | |||
There was a problem hiding this comment.
Nice addition of NewOpenCodeEngine() to the registry! 🎉 This follows the same pattern as the other engine registrations and integrates cleanly with the existing EngineRegistry infrastructure.
| @@ -478,7 +479,7 @@ func GenerateMultiSecretValidationStep(secretNames []string, engineName, docsURL | |||
| stepLines := []string{ | |||
| stepName, | |||
| " id: validate-secret", | |||
| " run: /opt/gh-aw/actions/validate_multi_secret.sh " + scriptArgsStr, | |||
| " run: ${GH_AW_HOME:-/opt/gh-aw}/actions/validate_multi_secret.sh " + scriptArgsStr, | |||
There was a problem hiding this comment.
Good improvement: using \$\{GH_AW_HOME:-/opt/gh-aw} instead of hardcoding /opt/gh-aw makes the path configurable, which is important for environments where the installation location may differ. This increases portability across deployment scenarios.
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤 |
This comment has been minimized.
This comment has been minimized.
|
💥 KA-POW!! The Smoke Test Agent was HERE! 💥 WHOOSH! — Claude swooped in from the agentic void, ran ALL the tests, and emerged VICTORIOUS! 🦸
BAM! ✅ GitHub MCP — CHECKED! TO BE CONTINUED... in the next run! 🚀 — Claude, Engine of Justice, Run §22734274394
|
There was a problem hiding this comment.
💥 Automated smoke test review - all systems nominal!
💥 [THE END] — Illustrated by Smoke Claude
This comment has been minimized.
This comment has been minimized.
|
Hey @Mossaka 👋 — this is a genuinely impressive piece of work: a full OpenCode engine integration with 22 unit tests, MCP gateway support, dynamic domain allowlists, and detailed documentation. A lot of thought clearly went into the design. Here are a couple of things that need resolving before this can move forward:
|
Summary
opencode.jsoncconverter scriptanthropic/,openai/,google/, etc.)opencode run -qwith auto-configured permissionsNew files
pkg/workflow/opencode_engine.gopkg/workflow/opencode_mcp.gopkg/workflow/opencode_engine_test.goactions/setup/sh/convert_gateway_config_opencode.sh.github/workflows/smoke-opencode.md.github/workflows/smoke-opencode.lock.ymlModified files
pkg/constants/constants.go— Engine name, version (1.2.14), LLM gateway port (10004), env varspkg/workflow/domains.go— Dynamic domains withextractProviderFromModel(), provider-specific allowlistspkg/workflow/agentic_engine.go— Engine registrationactions/setup/sh/start_mcp_gateway.sh—opencode)case for MCP gateway routingpkg/parser/schemas/main_workflow_schema.json— Added "opencode" to engine ID enumKey design decisions
ANTHROPIC_API_KEY, override any provider viaengine.envopencode.jsoncwith all permissions set toallow(prevents CI hanging)experimental: true— can be toggled after smoke tests pass consistentlyCompanion PR
Test plan
make buildpassesmake lintclean🤖 Generated with Claude Code
Changeset
Warning
The following domain was blocked by the firewall during workflow execution:
github.comTo allow these domains, add them to the
network.allowedlist in your workflow frontmatter:See Network Configuration for more information.
✨ PR Review Safe Output Test - Run 22730805579
✨ PR Review Safe Output Test - Run 22733626450
✨ PR Review Safe Output Test - Run 22734274394