DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

1624318455 /

1624318455/dsh-plugin-adapter

Verified

DSH adapter for OpenCode Zen free models (maintained fork with gateway-compat fixes)

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: master@fbf31a83

dsh-plugin-adapter

Free OpenCode Zen models, natively inside DSH (DeepSeek Harness).

No API key. No registration. No extra process.

DeepSeek Harness

license Awesome node tests stars last commit

English | 简体中文


dsh-plugin-adapter registers a native DSH LlmAdapter that streams directly from OpenCode Zen's anonymous free lane — the same models OpenCode's own CLI uses without an account, served to your DSH model picker as a regular provider called opencode2dsh.

Requests leave your machine looking exactly like traffic from the OpenCode CLI (same user agent, same correlation headers), and the model catalog stays fresh through a three-tier fallback chain. There is nothing to log into and nothing to host.

Features

  • Zero credential, zero setup — the anonymous lane needs no key; install, restart, chat
  • Native adapter, no sidecar — one npm package, no child process, no binary, no local port (the legacy Go sidecar is not part of the published package; see legacy/)
  • CLI-identical disguise — requests carry the OpenCode CLI user agent and its session/request/project header set, derived per conversation
  • Gateway-compat tracking — Responses-only models auto-route to /responses, and a synced live session keeps the free lane open while Zen only serves known sessions
  • Live catalog with a fallback chain — live upstream list ∩ free-by-metadata, falling back to offline cache and a verified static list
  • Self-healing — fast startup retries, periodic refresh, and a written health snapshot for diagnostics
  • Proper error surfaces — upstream failures (rate limit, auth, timeout, transport) arrive in DSH as classified finish reasons, and retries stay owned by DSH

Requirements

DSH (DeepSeek Harness) with a web profile; Node.js ≥ 20 (already present if DSH runs); outbound HTTPS to opencode.ai and models.dev.

Install

From the plugin market (recommended, once listed): in DSH open Settings → Plugin Market, search dsh-plugin-adapter, one-click install.

From GitHub:

dsh plugin --profile web add github:1624318455/dsh-plugin-adapter

From npm:

dsh plugin --profile web add @memef1f1y/dsh-plugin-adapter

From source (build the tarball yourself):

git clone https://github.com/1624318455/dsh-plugin-adapter.git
cd dsh-plugin-adapter/packages/plugin
pnpm install && pnpm pack
dsh plugin --profile web add ./memef1f1y-dsh-plugin-adapter-<version>.tgz

Verify: restart dsh web, open the model picker, and pick a model from the opencode2dsh group.

Configuration

Defaults work out of the box. Override via the profile's cordis.patch.yml:

- id: opencode2dsh
  name: '@memef1f1y/dsh-plugin-adapter'
  config:
    mode: adapter        # adapter (default) | sidecar
    providerId: opencode2dsh
    refreshSeconds: 300  # catalog refresh cadence
Option Default Description
mode adapter adapter: native LlmAdapter streaming straight from Zen. sidecar: legacy local-agent mode, not bundled — build the agent from legacy/agent and pass agentPath.
providerId opencode2dsh Provider name shown in DSH.
refreshSeconds 300 Live catalog refresh interval. Pricing metadata refreshes every 24 h.
gatewaySession — A live CLI session id sent as x-opencode-session (Zen only serves known sessions). Takes precedence over gatewaySessionFile.
gatewaySessionFile — File holding the session id, re-read every turn so an external helper can rotate it without a restart.
agentPath auto-resolved Sidecar only: path to the agent binary.
agentArgs — Sidecar only: extra CLI args for the agent.
restartDelayMs / restartMaxDelayMs / maxConsecutiveCrashes 1000 / 60000 / 5 Sidecar only: restart backoff and circuit breaker.

How it works

DSH session
   │  harness chunks (block-start / text-delta / usage / finish …)
   ▼
ZenAdapter (registered LlmAdapter)
   │  pi-ai openai-completions stream (chat models)
   │  pi-ai openai-responses stream (Responses-only models)
   ▼
https://opencode.ai/zen/v1        ← Authorization: Bearer public
   with CLI-identical headers:
     user-agent: opencode/… (CLI-identical, runtime values)
     x-opencode-client, x-opencode-session, x-session-affinity,
     X-Session-Id, x-opencode-request, x-opencode-project
  • Session correlation — by default session/project ids are SHA-256 derived from the conversation's first user turn (stable per conversation, non-reversible), and each request gets a fresh random id, mirroring the CLI. When gatewaySession/gatewaySessionFile is set, the synced live session id is sent instead (Zen only serves sessions it has seen from a genuine CLI flow).
  • Catalog fallback chain — S1: live GET /v1/models; S2: models.dev pricing metadata decides "free"; S3: a compile-time verified static list. A disk cache (~7-day TTL) covers upstream outages.
  • Resilience — the adapter registers immediately at startup; if the first catalog fetch races your network (VPN/TUN reconnects, DNS), the plugin retries on a short cadence (~1 min) before settling into the periodic refresh. Responses models get a wider 300 s body-idle watchdog for bursty reasoning; chat models keep the 120 s default.
  • Sidecar mode (mode: sidecar, legacy) — spawns a local Go agent (a single-tenant port of opencode2api) on 127.0.0.1:<random>, token-authenticated, and registers a standard llm-pi-ai route. Not part of the published package; build it from legacy/agent (go build ./cmd/agent) and point agentPath at the binary.

Edge cases handled

  • Responses-only models (muse-spark-*): chat returns a bare 500 while /responses returns 200 — auto-routed, no config needed.
  • Unknown sessions: unknown x-opencode-session ids get 403 FreeTierError — sync a live CLI session via gatewaySessionFile. (Note: non-streaming probes always 403 — diagnose with stream:true.)

Settings persistence

Adapter config lives in the profile's cordis.patch.yml (static per install). The synced session file is plain text (one line) re-read every turn. The IP-pool card (settings UI) owns the live routing section; catalog health persists to ~/.opencode2dsh/adapter-status.json.

Health & troubleshooting

The plugin writes a health snapshot after every refresh round:

~/.opencode2dsh/adapter-status.json
{
  "status": "ready",
  "total": 64,
  "exposed": 9,
  "lastError": "",
  "writtenAt": "2026-08-29T07:01:54.915Z"
}
Symptom Likely cause & fix
Boot screen shows Failed to load plugins … list slot "settings.plugin.item" requires options.id Your DSH is too old (≤ 0.1.0-rc.6): upgrade DSH to ≥ 0.1.0-rc.7 (latest recommended). Model routing is unaffected.
Only 3 models Startup fetch raced your network; retries land within ~1 min. Check adapter-status.json for lastError.
lastError: "fetch failed" persisting Outbound HTTPS to opencode.ai blocked; check proxy/VPN rules.
Rate-limit errors in chat The anonymous lane is quota-per-IP; switch network node or wait.
500 on muse-spark-* via chat Responses-only model; routed to /responses automatically.
403 FreeTierError: free tier can only be used from within OpenCode Zen only serves gateway-known sessions: sync a live CLI session via gatewaySessionFile (re-run the sync helper when it recurs).
stream body idle timeout on reasoning models Bursty chain-of-thought tripped the watchdog; Responses models use 300 s. If it persists, the exit node may be killing long SSE — switch nodes.
Connection error to 127.0.0.1:* A stale sidecar route shadows the adapter; plugin ≥ 0.2.1 removes it at startup.
Install fails with ERR_PNPM_IGNORED_BUILDS A transitive dependency of pi-ai (@google/genai, protobufjs) has build scripts that are not needed at runtime. Approve-or-decline them via the plugin market, or set both to false under allowBuilds: in the profile's pnpm-workspace.yaml.

FAQ

  • Do I need an API key? No. The anonymous lane's key is the literal string public; quotas are per exit IP.
  • Why did a working model suddenly 403/500? Zen moves models between APIs and tightens fingerprinting without notice — update the plugin first, then check the table above.
  • muse-spark is slow? It reasons with high effort before answering; the first tokens can take ~30 s. That is the model, not the plugin.

Development

git clone https://github.com/1624318455/dsh-plugin-adapter.git
cd dsh-plugin-adapter/packages/plugin
pnpm install
pnpm typecheck && pnpm test
pnpm build                    # bundle to lib/

The legacy Go sidecar lives in legacy/agent (go test ./...). Architecture notes and the porting record live in docs/.

Releasing: pnpm pack in packages/plugin (prepack builds and syncs docs).

Test status: full suite 162 passed; 3 environment-sensitive groups (watchdog timing, live-subscription, airport fixture) fail without a built bundle/network/slack and pre-date this fork.

Known limits

  • Free models may train on your data during the free period (Zen policy) — use privacy models or local runners for sensitive code.
  • Responses models need a live synced session; a stale file yields 403 until refreshed.

Acknowledgments

  • opencode2dsh by FishBottle7 — the adapter, catalog and IP-pool design originate there; this project maintains that core with gateway-compatibility fixes.
  • opencode2api by @jasonxu114514 — the legacy Go sidecar in legacy/agent is a port of its anonymous-lane implementation.
  • OpenCode — for running the free anonymous Zen lane.
  • @earendil-works/pi-ai — the wire layer used by adapter mode.
  • DeepSeek Harness and the dsh-market community.

Friends

LinuxDo — 新的理想型社区 / a new ideal community

License

MIT © FishBottle7, © 1624318455

—/ 5

No ratings yet

Verified DSH bundle

Commit fbf31a83154b

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout