-
Notifications
You must be signed in to change notification settings - Fork 28
fix(api-proxy): OpenCode port 10004 defaults to Copilot/OpenAI routing instead of Anthropic #1979
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
d76b22c
0686756
4ec4311
85857a7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| --- | ||
| description: Smoke test workflow that validates OpenCode engine functionality by testing AWF firewall capabilities | ||
| on: | ||
| roles: all | ||
| schedule: every 12h | ||
| workflow_dispatch: | ||
| pull_request: | ||
| types: [opened, synchronize, reopened] | ||
| reaction: "rocket" | ||
| permissions: | ||
| contents: read | ||
| issues: read | ||
| pull-requests: read | ||
| discussions: read | ||
| name: Smoke OpenCode | ||
| engine: opencode | ||
| strict: true | ||
| imports: | ||
| - shared/gh.md | ||
| - shared/reporting.md | ||
| network: | ||
| allowed: | ||
| - defaults | ||
| - github | ||
| tools: | ||
| cache-memory: true | ||
| github: | ||
| toolsets: [repos, pull_requests] | ||
| edit: | ||
| bash: | ||
| - "*" | ||
| safe-outputs: | ||
| threat-detection: | ||
| enabled: false | ||
| add-comment: | ||
| hide-older-comments: true | ||
| max: 2 | ||
| create-issue: | ||
| expires: 2h | ||
| close-older-issues: true | ||
| add-labels: | ||
| allowed: [smoke-opencode] | ||
| hide-comment: | ||
| messages: | ||
| footer: "> 🌐 *Transmitted by [{workflow_name}]({run_url})*" | ||
| run-started: "🌐 [{workflow_name}]({run_url}) is initializing on this {event_type}..." | ||
| run-success: "✅ [{workflow_name}]({run_url}) completed successfully. All systems nominal. 🚀" | ||
| run-failure: "❌ [{workflow_name}]({run_url}) {status}. Investigation required..." | ||
| timeout-minutes: 15 | ||
| post-steps: | ||
| - name: Validate safe outputs were invoked | ||
| run: | | ||
| OUTPUTS_FILE="${GH_AW_SAFE_OUTPUTS:-${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl}" | ||
| if [ ! -s "$OUTPUTS_FILE" ]; then | ||
| echo "::error::No safe outputs were invoked. Smoke tests require the agent to call safe output tools." | ||
| exit 1 | ||
| fi | ||
| echo "Safe output entries found: $(wc -l < "$OUTPUTS_FILE")" | ||
| if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then | ||
| if ! grep -q '"add_comment"' "$OUTPUTS_FILE"; then | ||
| echo "::error::Agent did not call add_comment on a pull_request trigger." | ||
| exit 1 | ||
| fi | ||
| echo "add_comment verified for PR trigger" | ||
| fi | ||
| echo "Safe output validation passed" | ||
| --- | ||
|
|
||
| # Smoke Test: OpenCode Engine Validation | ||
|
|
||
| **IMPORTANT: Keep all outputs extremely short and concise. Use single-line responses where possible. No verbose explanations.** | ||
|
|
||
| ## Test Requirements | ||
|
|
||
| 1. **GitHub MCP Testing**: Review the last 2 merged pull requests in `__GH_AW_GITHUB_REPOSITORY__` | ||
| 2. **File Writing Testing**: Create a test file `/tmp/gh-aw/agent/smoke-test-opencode-${{ github.run_id }}.txt` with content "Smoke test passed for OpenCode at $(date)" (create the directory if it doesn't exist) | ||
| 3. **Bash Tool Testing**: Execute bash commands to verify file creation was successful (use `cat` to read the file back) | ||
| 4. **Build AWF**: Run `npm ci && npm run build` to verify the agent can successfully build the AWF project. If the command fails, mark this test as ❌ and report the failure. | ||
| 5. **Add Comment**: Use the `add_comment` tool to post a brief summary comment on the current pull request | ||
|
|
||
| ## Output | ||
|
|
||
| **REQUIRED**: Call `add_comment` to post a brief comment (max 5-10 lines) on the current pull request (this is validated by the post-step check) containing: | ||
| - PR titles only (no descriptions) | ||
| - ✅ or ❌ for each test result | ||
| - Overall status: PASS or FAIL | ||
|
|
||
| If all tests pass: | ||
| - Use the `add_labels` safe-output tool to add the label `smoke-opencode` to the pull request | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1027,11 +1027,16 @@ if (require.main === module) { | |||||||||||||||
| }); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // OpenCode API proxy (port 10004) — routes to Anthropic (default BYOK provider) | ||||||||||||||||
| // OpenCode gets a separate port from Claude (10001) for per-engine rate limiting, | ||||||||||||||||
| // metrics isolation, and future provider routing (OpenCode is BYOK and may route | ||||||||||||||||
| // to different providers in the future based on model prefix). | ||||||||||||||||
| if (ANTHROPIC_API_KEY) { | ||||||||||||||||
| // OpenCode API proxy (port 10004) — dynamic provider routing | ||||||||||||||||
| // Defaults to Copilot/OpenAI routing (OPENAI_API_KEY), with Anthropic as a BYOK fallback. | ||||||||||||||||
| // OpenCode gets a separate port from Claude (10001) and Codex (10000) for per-engine | ||||||||||||||||
| // rate limiting and metrics isolation. | ||||||||||||||||
| // | ||||||||||||||||
| // Credential priority (first available wins): | ||||||||||||||||
| // 1. OPENAI_API_KEY → OpenAI/Copilot-compatible route (OPENAI_API_TARGET) | ||||||||||||||||
| // 2. ANTHROPIC_API_KEY → Anthropic BYOK route (ANTHROPIC_API_TARGET) | ||||||||||||||||
| // 3. COPILOT_AUTH_TOKEN → Copilot route (COPILOT_API_TARGET) | ||||||||||||||||
| if (OPENAI_API_KEY || ANTHROPIC_API_KEY || COPILOT_AUTH_TOKEN) { | ||||||||||||||||
| const opencodeServer = http.createServer((req, res) => { | ||||||||||||||||
| if (req.url === '/health' && req.method === 'GET') { | ||||||||||||||||
| res.writeHead(200, { 'Content-Type': 'application/json' }); | ||||||||||||||||
|
|
@@ -1046,26 +1051,62 @@ if (require.main === module) { | |||||||||||||||
| method: logMethod, | ||||||||||||||||
| url: logUrl, | ||||||||||||||||
| }); | ||||||||||||||||
| logRequest('info', 'opencode_proxy_header_injection', { | ||||||||||||||||
| message: '[OpenCode Proxy] Injecting x-api-key header with ANTHROPIC_API_KEY', | ||||||||||||||||
| }); | ||||||||||||||||
| const anthropicHeaders = { 'x-api-key': ANTHROPIC_API_KEY }; | ||||||||||||||||
| if (!req.headers['anthropic-version']) { | ||||||||||||||||
| anthropicHeaders['anthropic-version'] = '2023-06-01'; | ||||||||||||||||
|
|
||||||||||||||||
|
||||||||||||||||
| const parsedContentLength = Number(req.headers['content-length']); | |
| const contentLength = Number.isFinite(parsedContentLength) && parsedContentLength > 0 ? parsedContentLength : 0; | |
| if (!checkRateLimit(req, res, 'opencode', contentLength)) { | |
| return; | |
| } |
Copilot
AI
Apr 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New provider-routing behavior for the OpenCode proxy (OPENAI_API_KEY vs ANTHROPIC_API_KEY vs COPILOT_AUTH_TOKEN) isn't covered by tests. Since this repo already has containers/api-proxy/server.test.js, please add unit/integration coverage for the 10004 routing priority and header injection for each credential scenario (and WebSocket upgrade routing if applicable).
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -40,8 +40,8 @@ export const API_PROXY_PORTS = { | |||||
| GEMINI: 10003, | ||||||
|
|
||||||
| /** | ||||||
| * OpenCode API proxy port (routes to Anthropic by default) | ||||||
| * OpenCode is BYOK — defaults to Anthropic as the primary provider | ||||||
| * OpenCode API proxy port (defaults to Copilot/OpenAI routing; falls back to Anthropic) | ||||||
| * OpenCode is BYOK — credential priority: OPENAI_API_KEY > ANTHROPIC_API_KEY > COPILOT_AUTH_TOKEN | ||||||
|
||||||
| * OpenCode is BYOK — credential priority: OPENAI_API_KEY > ANTHROPIC_API_KEY > COPILOT_AUTH_TOKEN | |
| * OpenCode is BYOK — credential priority: OPENAI_API_KEY > ANTHROPIC_API_KEY > COPILOT_GITHUB_TOKEN/COPILOT_API_KEY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This adds a new agentic workflow source file under .github/workflows/, but there is no corresponding compiled
.lock.ymlworkflow checked in (unlike the other smoke workflows, e.g. smoke-copilot.md → smoke-copilot.lock.yml). As-is, this won't run in GitHub Actions and may be easy to overlook; consider either including the compiled lock file once supported, or adding an explicit note in the frontmatter/body that compilation is pending and the workflow is not yet active.