dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Bridge Claude Code OAuth (Pro/Max/Team) into DeepSeek Harness — reuses ~/.claude/.credentials.json, auto-refreshes, no hardcoding
Bridge your existing Claude Code OAuth session (Pro / Max / Team) into DeepSeek Harness (DSH) — with zero hardcoding.
~/.claude/.credentials.json claudeAiOauth live (same file Claude Code writes)accessToken via https://platform.claude.com/v1/oauth/token when <5 min remainsANTHROPIC_OAUTH_TOKEN (+ CLAUDE_CODE_OAUTH_TOKEN alias) into ~/.dsh/.credentials.yaml — the credential seam dsh-llm-pi-ai already resolvesllm-pi-ai.providers.anthropic (api: anthropic-messages) exists in ~/.dsh/settings.yamlGET /v1/models (id, display name, context window, max output, thinking/effort capabilities) — no hardcoded model list; new Claude releases appear automaticallyclaude-cli impersonation headers) with no real user identifier — cch is a zeroed placeholderBearer + oauth-2025-04-20)anthropic-ratelimit-unified-* headers on a cheap max_tokens:1 probe (these headers ride only on /v1/messages, never /v1/models)This does not embed or persist your tokens beyond the two standard DSH/Claude files.
In the DSH web UI, the plugin's client half docks a themed quota panel in the composer's ambient readout slot (conversation.composer.dock) — non-invasive (touches no shell chrome) and theme-aware (uses --dsw-* tokens, so it adapts to light/dark):
The client half is authored directly in the DSH client-bundle format (window.__ModuleLoader__.load) and served verbatim — no bundler or build step. It reads two JSON endpoints the host half serves:
| Endpoint | Purpose |
|---|---|
GET /api/anthropic-oauth/status | Bridge state + last rateLimit snapshot (folded into lastAuthState) |
GET /api/anthropic-oauth/quota | Live quota (60s TTL); ?force=1 or POST bypasses the cache |
The quota probe spends a negligible amount (Haiku, 1 output token) and is throttled to 60s + manual refresh.
# stable — from npm (once published):
dsh plugin --profile headless add dsh-anthropic-oauth
dsh plugin --profile web add dsh-anthropic-oauth # optional; bridge is headless but harmless in web
# bleeding edge — from GitHub:
dsh plugin --profile headless add github:TrueNix/dsh-anthropic-oauth
Claude Code logged in: claude login or claude setup-token at least once — ~/.claude/.credentials.json must contain claudeAiOauth~0.1.0-rc.6+ (has dsh-llm-pi-ai, credentials, settings, fs)~/.claude/.credentials.json --watch--> dsh-anthropic-oauth Host plugin
claudeAiOauth {accessToken, refreshToken, expiresAt}
│
refreshIfNeeded() if expiry <5m
POST https://platform.claude.com/v1/oauth/token
{grant_type: refresh_token, client_id: 9d1c25…f5e}
│
├─► ~/.claude/.credentials.json (updated expiry)
└─► ~/.dsh/.credentials.yaml
ANTHROPIC_OAUTH_TOKEN: sk-ant-oat01-…
CLAUDE_CODE_OAUTH_TOKEN: sk-ant-oat01-…
└─► GET /v1/models (live catalog)
→ llm-pi-ai.providers.anthropic.models
[{id, name, contextWindow, maxTokens,
reasoning, effortLevels}, …]
~/.dsh/settings.yaml llm-pi-ai.providers.anthropic {apiKeyEnv: ANTHROPIC_OAUTH_TOKEN}
│
└─► pi-ai anthropicMessagesApi — Authorization: Bearer sk-ant-oat01-…
anthropic-beta: oauth-2025-04-20,claude-code-20250219,…
The model catalog is refreshed from GET /v1/models (≤6h TTL, or on demand via
POST /api/anthropic-oauth/sync); if discovery fails the provider keeps a minimal
Sonnet-4.5 seed so it still resolves offline. Quota is probed from
POST /v1/messages (max_tokens:1, Haiku — fractions of a cent, 60s TTL)
and exposed at /api/anthropic-oauth/quota.
# ~/.dsh/settings.yaml
agent-default-model:
provider: anthropic
model: claude-sonnet-4-5
Or pick per-session in Settings → Models after a reload.
# DSH console (bridge + quota probe):
# [anthropic-oauth] pulled N models from /v1/models
# [anthropic-oauth] refreshed, new expiry …
# Force-refresh the model catalog (also syncs quota):
curl -X POST http://127.0.0.1:3080/api/anthropic-oauth/sync
# Live quota (60s TTL; ?force=1 bypasses cache):
curl http://127.0.0.1:3080/api/anthropic-oauth/quota
curl "http://127.0.0.1:3080/api/anthropic-oauth/quota?force=1"
MISSING_CREDENTIAL llm-pi-ai: no credential for provider route "anthropic" — bridge hasn't synced yet; re-login with claude login.claude login again.ok:false with a refresh error — subscription may have changed; re-login, then check /api/anthropic-oauth/quota?force=1.Refreshes are single-flight per plugin and serialized between DSH processes. Missing fields and rejected refresh tokens do not trigger an endless HTTP retry loop. A still-valid access token remains usable while the status endpoint reports that a fresh Claude login is needed. New credentials clear that pause.
The bridge watches the credential directory so atomic replacements from Claude
login are detected. It honors CLAUDE_CONFIG_DIR, validates refresh responses,
and uses atomic owner-only writes. If the source file changes during an HTTP
refresh, the newer credentials are kept instead of overwritten. Claude Code does
not share the plugin lock; avoid logging in during an in-flight refresh when possible.
The bridge never repairs or directly writes DSH's credential YAML. An
unknown top-level key error is a separate malformed-store problem, not an
OAuth grant error.
.gitignore excludes *.oat*, *.credentials.*.0600 files owned by you: ~/.claude/.credentials.json and ~/.dsh/.credentials.yaml.ANTHROPIC_API_KEY for production.MIT