opencode-svip-proxy
v0.3.0
Published
OpenCode plugin that injects metadata.user_id into svip-relay Claude/DeepSeek request bodies so the relay pins requests to one account (prompt-cache stickiness) — replaces a local request-rewriting proxy
Maintainers
Readme
opencode-svip-proxy
An OpenCode plugin that injects metadata.user_id into
every model request body (/v1/messages and /v1/chat/completions).
A relay that routes by metadata.user_id can then pin all of a session's
requests to one upstream account, keeping the prompt-cache hit rate high — so
you get the caching benefit without running a separate request-rewriting
proxy in front of OpenCode.
It wraps globalThis.fetch inside the plugin server() hook (the same
mechanism @lucentia/opencode-trace uses), so it composes with other plugins.
Install
Add it to the plugin array in ~/.config/opencode/opencode.json:
{
"plugin": ["opencode-svip-proxy"],
"provider": {
"svip": {
"npm": "@ai-sdk/anthropic",
"options": {
"baseURL": "https://svip.xty.app/v1",
"apiKey": "{env:LLM_API_KEY}"
},
"models": { "claude-opus-4-8": {} }
}
}
}OpenCode fetches and caches the plugin from npm. Because the metadata is added
in-process, the provider baseURL points straight at the remote relay — no
local proxy needed.
Configure
export OPENCODE_METADATA_USER_ID=your-stable-user-or-session-idFalls back to a built-in constant if unset.
Behaviour
Injection happens only when both hold (otherwise the request is passed through untouched — other providers/models see no change):
- the request host is the svip relay (
OPENCODE_SVIP_HOST, defaultsvip.xty.app) — i.e. it came through thesvipprovider; and - the target
modelis a Claude or DeepSeek model (/claude|deepseek/i) — both are cache-routed byuser_idon svip (claude via/v1/messages, deepseek via/v1/chat/completions).
Additionally:
- only POSTs to
…/messagesor…/chat/completionsare touched; - an existing
metadataobject is merged, not overwritten; - all other request fields are preserved.
Run the tests: npm test.
License
MIT
