Skip to content

feat(providers): support opencode go subscriptions - #684

Open
FradSer wants to merge 11 commits into
langgenius:mainfrom
FradSer:feat/provider-opencode-go
Open

FradSer wants to merge 11 commits into
langgenius:mainfrom
FradSer:feat/provider-opencode-go

Conversation

@FradSer

@FradSer FradSer commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Add OpenCode Go as a distinct subscription provider for OpenCode and Pi. The Host owns the subscription key and forwards requests through the existing expiring proxy grant, with Mosoo deployment identity and a stable Host Session identity.

Admission is limited to five Chat Completions presets: DeepSeek V4.1 Flash, DeepSeek V4 Pro, GLM 5.2, Kimi K2.6 and Kimi K2.7 Code. Messages and Responses presets are withheld until real-provider acceptance is available. Protocol forwarding fixtures remain for historical frozen plans; they do not establish real Go protocol acceptance.

Review changes

  • Merge current main (465d9f26) normally and preserve both OpenCode and Pi directory handling when resolving the conflict with fix(runtime): keep host paths out of opencode acp directories #699. Host cache, HOME and workspace are provisioned independently of the empty optional CLI directory list.
  • Use the landed Driver main commit 49df36e, also pinned by Mosoo main. This PR no longer depends on unmerged Driver feat(public-api): define thread final output client #137 or an unlanded submodule commit.
  • Remove the four Messages/Responses Go presets rather than claiming acceptance from fixtures.
  • Sanitize Go error bodies, status text and headers before returning them to the sandbox. Buffer at most 64 KiB, replace oversized error bodies, remove stale encoding/digest metadata, preserve bodyless responses and leave successful streaming untouched. Strip sandbox-supplied x-opencode-* headers before applying Host identity.
  • Share credential error sanitization with the credential probe. A required inference probe without a model fails explicitly. Existing HTTP 402/429/404 categories are preserved and tested, rather than relabeled as invalid keys. Users can select another admitted model if the default becomes unavailable; there is no unauthenticated model-list fallback for Go.
  • Usage snapshots replace earlier snapshots for the same Run/call, matching the model-call ledger. This applies across runtimes. Thread process events poll the same persisted projection used after reload; the process-feed regression checks independent calls and Runs. The native_step_totals source is emitted by the landed Driver and accepted by the Host.

Verification

Current head: 8da8894c. Hosted Linux PR Check passed, including the full repository gate, all 15 credential-free Preview persistence browser cases and native Host checkpoint recovery. CLA, commit identity and title checks passed. No migration, generated GraphQL/OpenAPI artifact, dependency or lockfile change. The Driver pin equals current main.

  • Local formatting, documentation links, lint and full repository type checking passed during just check. Commit metadata and all commit hooks passed.
  • Runtime catalog package: 25 passed.
  • API package: 1,204 passed / 1 optional native Host checkpoint skipped / 1 failed. The failure is the unchanged native-checkpoint-bundle restore test; its source matches main and a focused rerun reproduced 6 passed / 1 failed on this macOS host.
  • The API run includes 75 proxy cases, including installed OpenCode/Pi streaming and tool execution against local protocol fixtures, plus credential-echo, chunk boundary, oversized-body, header and bodyless-response regressions. The three new body-echo cases failed against unsanitized forwarding before the fix and passed with it. These are deterministic integration checks, not live provider calls.
  • Focused API/Driver boundary: 15 passed. Process replay projection: 16 passed. Credential probe: 27 passed. Public API freshness/backward compatibility and GraphQL freshness passed separately.
  • Local full just check is not green: the unchanged Driver main suite produced 1,658 passed / 71 skipped / 600 failed on macOS, including explicit Linux /proc requirements and native lifecycle failures. The Driver pin was not changed to an unmerged test-fix branch to conceal these failures. Hosted Linux CI is reported separately by the PR checks.

Real-provider evidence and limits

Historical acceptance evidence records two completed real Chat Completions Runs, one each on OpenCode and Pi, with tool output, usage and committed checkpoints. Those Runs used an earlier local candidate, not this head. They do not prove recovery/resume on this head, provider-side billing, or success on the other curated Chat Completions models.

A captured passing credential-Test result is still unavailable. Messages and Responses have no successful real-provider acceptance and are excluded from new preset admission. No credential was read or tested, no real model request or paid Session was created, and no deployment was performed in this review follow-up.

Impact and rollback

Provider/model admission and internal proxy/usage behavior change; the versioned Public API shape is unchanged. No DB migration or stored-data rewrite is included. Go subscription accounting and overage policy remain upstream responsibilities.

Revert the provider/proxy changes if necessary, but retain read compatibility for persisted native_step_totals usage values and already-admitted Session configuration. A deployment rollback must not discard persisted source-enum compatibility. No production deployment is requested here.

Design

N/A: no console layout change.

@Yevanchen

Copy link
Copy Markdown
Collaborator

Hi @FradSer, thanks for putting this together. Could you share screenshots from an acceptance run against a real OpenCode Go subscription? The verification so far uses simulated endpoints, so it would help to see:

  • the Go key added to a Project, with the credential test passing;
  • a Session on a Go model completing a turn that includes a tool call, on OpenCode and on Pi (ideally one model per protocol: Chat Completions, Anthropic Messages, and Responses);
  • the resulting Run with its recorded usage.

Please redact keys and account details.

@FradSer
FradSer marked this pull request as draft October 19, 2026 08:56
@FradSer

FradSer commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor Author

Historical results from 2026-10-19. Later real OpenCode and Pi Runs succeeded. See the current acceptance evidence and updated PR description for the current code and verification status.

Following up on the requested real OpenCode Go acceptance: this PR is now Draft. Acceptance remains incomplete. The latest Pi/Go request reached the real upstream and returned HTTP 401, api_key_expired; testing stopped there.

The Go credential was entered and saved manually in the local Project. The tester reported that Test passed, but its result dialog was not captured. The provider screenshot below proves saved state only.

Four distinct Sessions were submitted once each, within the six-attempt limit:

Harness / Go model Protocol Actual result Run token display
OpenCode / deepseek-v4.1-flash Chat Completions ACP setup rejected unsupported additionalDirectories unavailable (-)
OpenCode / minimax-m3 Anthropic Messages Local directory preparation failed with mkdir: missing operand unavailable (-)
OpenCode / gpt-5.6-luna Responses Local Vite rejected host.docker.internal unavailable (-)
Pi / deepseek-v4.1-flash Chat Completions Real upstream returned 401 api_key_expired 0 total tokens

None produced a successful tool call. The remaining two Pi protocol attempts have not been submitted after the authentication failure, and no failed Session was retried. A valid Go key is needed before continuing. The Run display is not a provider billing or remaining-quota statement; no subscription purchase, upgrade, or balance-setting change was made.

The local candidate is not committed or pushed; this PR's remote head remains 6c3be94. It reconciles main 7cb9866 and includes the Go authenticated credential probe/default-model fixes. It also filters unsupported OpenCode/Pi native directory requests while preserving physical cache, HOME, and workspace preparation. The first local fix missed that shared-helper filesystem use; the corrected regression checks both and passes (15 API/Driver boundary tests, plus 6 Pi admission tests, formatting/docs/API types). The local Vite issue now uses the existing explicit runtime-control origin to reach the API directly, without relaxing Vite's Host guard. Pi version, directories, container-to-API routing and anonymous Go network checks passed before the Pi submission; anonymous metadata is not credential validation.

The Linux native Host checkpoint canary completed successfully with the pinned real Claude CLI and a local model fixture: 3 Host-verified bundles, 2 ready backups, and history restored in a new process. This is checkpoint evidence, not Go subscription acceptance. Full Linux just check is not green: a Driver terminal-settlement deadline test and the DB migration 5-second timeout fail. Both failures were reproduced by actually running clean main in the same Linux image, dependencies and resource limits. The final directory correction has focused regression coverage, not a new full-gate pass.

Actual screenshots below have the complete credential line and account details obscured. No fixture screenshot is included.

Saved provider — Test result not captured

Saved Go provider only; credential line fully redacted

OpenCode / Chat Completions — ACP setup failure

Actual OpenCode Chat Run failure with account details redacted

OpenCode / Anthropic Messages — directory preparation failure

Actual OpenCode Messages Run failure with account details redacted

OpenCode / Responses — local Host guard failure

Actual OpenCode Responses Run failure with account details redacted

Pi / Chat Completions — real upstream key expired, 0 tokens displayed

Actual Pi Go Run showing HTTP401 api_key_expired and 0 total tokens

@FradSer

FradSer commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor Author

Real OpenCode Go acceptance — existing-evidence reconciliation (2026-10-21)

This updates the successful-run evidence captured on 2026-10-20. It uses existing screenshots, the saved seven-attempt manifest, and Run/usage/checkpoint exports only. No model request, credential Test, new Session, or credential read was performed for this update.

Two completed real Runs

Both use opencode-go / deepseek-v4.1-flash over Chat Completions. In each screenshot, the tool result and final reply contain MOSOO_GO_ACCEPTANCE_PROOF. The Run ID in the screenshot matches the saved Run export.

Runtime Run ID Status Input, including cache Cache-read subset Output Total
OpenCode 01M5C8GSQK2Z3ZP45PXMG5TVG3 Completed 16,181 7,936 60 16,241
Pi 01M5C8AQTHRYQD3QPB8F20HFPV Completed 3,788 2,048 77 3,865

Cache reads are a subset of input, so total is input plus output. The saved model-call input excluding cache is 8,245 for OpenCode and 1,740 for Pi. Adding the cache-read subset gives the usage input above. The UI rounds the totals to 16k and 3.9k. These are runtime records, not subscription quota, an invoice, or a provider billing total.

The saved checkpoint exports record acp_session_id for the OpenCode Run and pi_session_path for the Pi Run. Each committed_session_run_id equals its completed Run ID, and each invalidated_at is null. This establishes checkpoint commit, not a new real-Go recovery/resume test.

OpenCode — completed Run, successful tool output, final reply

OpenCode completed Run with tool result and final reply

Pi — completed Run, successful tool output, final reply

Pi completed Run with tool result and final reply

Saved credential and Test evidence

The historical saved-Provider screenshot below shows a Go key entry in the Project. The credential line is fully redacted. It does not show a passing Test and does not identify the later credential used by the successful Runs.

Historical saved Go Provider; credential line redacted; Test result not shown

A passing Test was reported by the user, but no passing dialog or machine-observed success receipt was found in the inspected saved evidence. The retained Test receipt and error-only screenshot instead document the earlier expired key: provider.credential_test at 2026-10-19T15:58:39.934Z, provider.ok=false, HTTP 401, latency 925 ms. This failure is historical; it does not contradict the later successful Runs after the reported credential replacement. It cannot serve as proof that the later UI Test passed. No Test was clicked again.

Complete seven-attempt history

Attempt Runtime / protocol Recorded outcome
1 OpenCode / Chat Completions Failed at unsupported ACP additionalDirectories; no completed tool turn
2 OpenCode / Anthropic Messages (minimax-m3) Failed during local directory preparation (mkdir: missing operand)
3 OpenCode / Responses (gpt-5.6-luna) Failed at the local Vite Host guard
4 Pi / Chat Completions Real upstream rejected the expired key with HTTP 401; no completed tool turn
5 OpenCode / Chat Completions Tool and final reply succeeded, but Host usage-source validation failed the Run; not a completed acceptance Run
6 Pi / Chat Completions Completed; tool, final reply, usage and checkpoint recorded above
7 OpenCode / Chat Completions Completed; tool, final reply, usage and checkpoint recorded above

The two successful Runs used the local candidate recorded in the archived manifest as patch SHA256 251e50c1b57d04fe2a46de2a8f2c24c03f2fda8eeb305414e45497240707d995. Exact source snapshots for the first four attempts were not retained. These historical Runs are not new executions on current head e940702a.

What remains unproven

  • A captured passing credential-Test result.
  • A successful real Anthropic Messages turn: the existing OpenCode attempt failed before model/tool acceptance; Pi was not run.
  • A successful real Responses turn: the existing OpenCode attempt failed locally; Pi was not run.
  • Provider-side subscription accounting or charges.

All seven authorized Sessions were used. The missing success evidence cannot be reconstructed from these records. Acceptance remains partial; no extra paid Session was created to fill the gaps. Simulated protocol tests and the local Claude checkpoint fixture are automated integration evidence, not substitutes for real Go acceptance.

Current-head verification is separate: CI for e940702a passed the full gate and native Host checkpoint recovery. The PR description contains the current source, Driver dependency, and verification details. This evidence update changes no source code.

@FradSer
FradSer marked this pull request as ready for review October 20, 2026 13:29
@Yevanchen

Copy link
Copy Markdown
Collaborator

Adversarial review (Claude, static review of diff + head files; no code executed — points depending on code outside the diff are unverified):

Verdict: merge after fixes. The Go-specific code is careful: the proxy overwrites User-Agent and x-opencode-session with Host values, the raw key stays in the Host, the credential Test can no longer be fooled by Go's public model list, and the new tests fail if their fixes are reverted.

Blocker

Major

  • pkgs/runtime-catalog/src/catalog.ts:447-470: 4 of 9 curated models — minimax-m3, minimax-m2.7, qwen3.7-plus (Messages) and gpt-5.6-luna (Responses) — were only verified against fixtures written in this PR (Bearer-only auth on /messages without x-api-key, driver-route.ts:357; Host-added anthropic-version; ?beta=true passthrough; /zen/go/v1/responses). Scenario: if Go's /messages expects x-api-key or rejects ?beta=true, every call for those models fails, and since the protocol is frozen into the Session plan the only way out is a new Session. Fix: get one real Messages turn, one real Responses turn and a passing credential Test before merge, or ship only the Chat Completions models for now.

Minor

  • apps/api/src/adapters/http/routes/driver-route.ts:396: upstream error bodies are forwarded to the sandbox verbatim; the oc_sk_ redaction (vendor-credential-probe.ts:95) only covers the credential Test. If Go echoes the key in an error (unknown), the subscription key becomes visible in the sandbox/Session. Fix: buffer small non-2xx bodies and replaceAll(target.apiKey, "***") + shared sanitizer; add a key-echo proxy test.
  • vendor-credential-test.ts:256-259, 318-357: Go key Test depends on one hard-coded model; any non-2xx = bad key. Retiring deepseek-v4.1-flash fails every valid key; 429 over-limit shows as a bad key; a null default would fall through to the unauthenticated public model list and report ok: true. Return an error when requiresInferenceProbe && modelId === null; distinct codes for 429/402.
  • runtime-driver-execution-spec.builder.ts:205: every OpenCode and Pi session now gets additionalDirectories: [] regardless of provider, keyed on two hard-coded runtime IDs. Consider a separate PR based on a runtime capability, with a real-CLI test touching home/cache paths.
  • session-process-events.service.ts:98-111 (+ session-event-read.repository.ts:22, 160): usage dedup applies to all runtimes and past sessions, not just Pi; earlier snapshots now return tokens: null; usage_key is optional; the live path still puts tokens on every snapshot (possible 5,781 live vs 3,865 after reload — web client unverified).

Nits: double driver_instance read per Go call and raw internal Session ID sent upstream (runtime-llm-proxy.service.ts:97); other sandbox x-opencode-* headers are still forwarded (driver-route.ts:324-342); rollback by revert isn't clean once native_step_totals is stored (session-live-state-schema.ts:77).

Conflict with #699: #699 changes the same additional-directories logic differently (runtimeId === "acp-fallback" only, renamed helper). Whichever lands second conflicts in 3 files; when resolving, keep this PR's || runtimeId === "pi" check — it would otherwise disappear without a compile error.

Description vs code: local just check numbers are for e940702a, not the current head 95f893e0; "latest Pi usage snapshot" applies to all runtimes; the submodule pin contradicts the stated merge order.

…261029

# Conflicts:
#	apps/api/src/modules/runtime/infrastructure/runtime-sandbox-provisioning/runtime-driver-execution-spec.builder.ts
#	apps/api/tests/api-driver-boundary.test.ts
@FradSer

FradSer commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Updated in 8da8894c, including a normal merge of current main (465d9f26).

  • The Driver pin now uses landed Driver main 49df36e, matching Mosoo main, so this PR no longer depends on unmerged Driver feat(public-api): define thread final output client #137.
  • New Go admission now includes only the five Chat Completions presets. The four Messages/Responses presets are withheld pending real-provider acceptance; forwarding fixtures remain for historical frozen plans.
  • Go failure responses now redact credentials from bodies, headers and status text, enforce a 64 KiB buffer limit, remove stale encoding/digest metadata and preserve bodyless responses. Successful responses keep streaming. Sandbox-supplied x-opencode-* headers are stripped before Host identity is applied.
  • A required credential inference probe without a model fails explicitly. HTTP 402/429/404 classifications are preserved and covered by regressions, so these outcomes are not reported as invalid keys.
  • Conflict resolution preserves both OpenCode and Pi directory handling while keeping Host cache/HOME/workspace provisioning separate. Usage replacement is documented as applying across runtimes; the live process feed polls the same persisted projection used after reload. Rollback notes retain read compatibility for persisted native_step_totals values.

Linux PR Check for this head passed the complete repository gate, all 15 Preview persistence browser cases and native Host checkpoint recovery. Focused checks also passed: 25 catalog cases, 75 proxy cases, 15 API/Driver boundary cases, 16 process-replay cases and 27 credential-probe cases. The credential-echo regressions failed against unsanitized forwarding and pass with the repair. The PR description separately records the local macOS full-gate failures; it does not claim that run passed.

Real-provider acceptance remains limited to the two historical Chat Completions Runs on an earlier candidate. A captured passing credential Test is still missing. This follow-up made no real model request or paid Session, and the fixture and native-checkpoint checks do not establish new Go acceptance on this head.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants