Conversation
Add OpenCode as a new agentic engine supporting provider-agnostic AI coding with BYOK (Bring Your Own Key) and full MCP Gateway + API proxy support. New engine features: - Provider-agnostic: supports Anthropic, OpenAI, Google, Groq, etc. - Dynamic domain allowlists based on model provider prefix - API proxy on port 10004 (default: Anthropic routing) - MCP Gateway integration with opencode.jsonc converter - Headless CI mode via `opencode run -q` - Auto-configured permissions to prevent CI hanging - 22 unit tests covering all engine methods - Smoke test workflow (5 tests) Files: opencode_engine.go, opencode_mcp.go, opencode_engine_test.go, convert_gateway_config_opencode.sh, smoke-opencode.md/.lock.yml Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.
| // GetOpenCodeAllowedDomainsWithToolsAndRuntimes merges OpenCode default domains with NetworkPermissions, HTTP MCP server domains, and runtime ecosystem domains | ||
| // Returns a deduplicated, sorted, comma-separated string suitable for AWF's --allow-domains flag | ||
| func GetOpenCodeAllowedDomainsWithToolsAndRuntimes(network *NetworkPermissions, tools map[string]any, runtimes map[string]any) string { | ||
| return GetAllowedDomainsForEngine(constants.OpenCodeEngine, network, tools, runtimes) | ||
| } |
There was a problem hiding this comment.
The dynamic domain selection feature described in the PR is not fully implemented. The function GetOpenCodeDefaultDomains(model string) exists at lines 157-169 to provide model-specific domains based on provider prefix (e.g., "anthropic/", "openai/"), but this function is never called. Instead, line 174 uses GetAllowedDomainsForEngine(constants.OpenCodeEngine, ...) which looks up the static OpenCodeDefaultDomains constant from the engineDefaultDomains map (line 595).
To fix this, the function should extract the model from the workflow data (if firewall is enabled) and use it to calculate provider-specific domains. However, note that GetOpenCodeAllowedDomainsWithToolsAndRuntimes doesn't have access to WorkflowData to retrieve the model, and changing the signature would affect the calling code in opencode_engine.go line 213.
This issue also appears on line 143 of the same file.
This comment has been minimized.
This comment has been minimized.
|
Hi @Mossaka! 👋 Thanks for putting together this detailed OpenCode engine integration — it's clear you've put real effort into the implementation (tests, description, focused scope — all great signs!). However, based on the project's CONTRIBUTING.md, direct PRs from community contributors aren't the expected path here. The
What to do next:
Your work here is a great reference — the core team can use it as a starting point when implementing via the agentic workflow. Sorry for the friction, and thanks again for the contribution! 🙏
|
Add comprehensive external-facing documentation for the OpenCode engine: - New guide: docs/src/content/docs/guides/opencode.md (460 lines) - Quick start, auth/providers, network security, MCP support - Example workflows, engine comparison, known limitations - Update engines.md: add OpenCode to available agents list - Update auth.mdx: add OpenCode authentication reference - Update network.md: add OpenCode domain config + dynamic provider docs - Update astro.config.mjs: add sidebar link Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* 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 |
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