DSH WorkBuddy Connect
corrinehu/dsh-workbuddy-connect将 WorkBuddy 桌面 App 包含的模型自动接入 DeepSeek Harness,在 DSH 对话窗口里零配置使用。
把 ChatGPT(Codex)、Claude、Grok 订阅当作 DeepSeek Harness 的 LLM 提供方:设置页登录、模型目录、用量展示,以及 image_generate、video_generate 与 x_search 工具。
English | 中文
Use your ChatGPT (Codex), Claude, Grok (X Premium), GitHub Copilot, and Google Antigravity subscriptions as LLM providers in DeepSeek Harness — no API keys. Codex, Grok, and Antigravity log in via OAuth in the dsh web UI (Settings → Subscriptions), while Copilot uses the GitHub OAuth device flow; Claude imports credentials from an existing Claude Code session when there is one (macOS Keychain or ~/.claude/.credentials.json) and otherwise falls back to the same browser OAuth flow, so the Claude Code CLI is not required. Tokens live at ~/.dsh/plugins/subscriptions/auth.json (mode 0600) and refresh automatically.
Open Settings → Subscriptions → Manage to set a subscription display name, or edit a model's display name under Edit model list. Both share the existing Save/Cancel actions; clearing a name or choosing Reset to default and saving restores the original name. Names are single-line text of up to 80 characters, stored per provider and model ID in provider-settings.json, and survive restarts and catalog refreshes. They only change presentation: provider IDs, model IDs, reasoning settings, and account routing remain unchanged. Existing account aliases continue to work independently.
Subscription display names also label provider groups in the native model picker. Saving a cleared name restores the provider's default group title.
Settings → Subscriptions: per-provider login/logout, no API keys. Claude imports credentials from Claude Code when available and otherwise uses OAuth, as Codex and Grok always do (settings screenshots use demo accounts and catalog data):
Configure visibility, default reasoning effort, and context together in Edit model list, with shared Save and Cancel actions:
Configure image generation, video generation, and X search per provider. Tool switches apply only to sessions created after saving:
Logged-in providers join the session model picker with their live model catalogs:
Models that advertise reasoning levels get an Effort selector in the same menu — Codex models, Grok 4.6 / 4.5, and Copilot's reasoning models (levels and defaults come from each provider's live catalog, not a hardcoded list; Copilot's capabilities.supports.reasoning_effort array is sent as reasoning_effort on chat completions and reasoning.effort on the Responses wire). Models listing both Copilot endpoints (gpt-5.4, gpt-5-mini) normally speak chat completions but reroute to /responses when a request combines function tools with an effort — Copilot rejects that combination on the chat wire:
Codex models whose catalog advertises the fast tier (the codex CLI's fast mode) get a Speed toggle in the composer's tool row, next to the model selector — Standard or Fast (service_tier: priority), per session. The /fast slash command offers the same choice as a popup; it errors with an explanation when the current model has no fast tier.
Subagents have a separate per-model default: Settings → Subscriptions → ChatGPT (Codex) → Manage → Edit model list → Subagent default speed. Save changes to apply it to subsequent requests, including running subagents. This setting persists across restarts and works regardless of the parent model; main-session Speed choices do not propagate to children. A speed explicitly selected in a child session overrides its model default, including Standard. Explicit session choices reset on restart. Fast still requires catalog support for the actual Codex model. Hosts without live agent origin metadata keep Standard unless the session has an explicit speed choice.
The composer's stats row gains a subscription usage pill showing the used percentage and reset window for the provider of the session's current model (Codex for a Codex model, Grok for a Grok model, and so on). It shows at most one provider: when switching to a non-subscription model, it keeps the most recent subscription selected in the mounted conversation view, or stays hidden if there is none. This recent-model history is not persisted across page reloads. Click the pill to expand every logged-in provider and account — the default account is starred, and the current provider is listed first. Antigravity previews only the current model's windows (at most two per account); the other model windows remain available in a closed disclosure.
Settings → Subscriptions → Status-bar quota display selects Current / most recent subscription only (default) or Hidden. The display preference is saved in the current browser, applies immediately, survives reloads, and synchronizes between tabs of the same origin. It does not hide usage details in Settings, change model selection, or change account routing.
The image_generate tool renders its result inline in the conversation:
Its provider parameter picks the image backend — the same prompt through GPT (gpt-image-2, top) and Grok (grok-imagine-image-2.0, bottom):
The video_generate tool plays the generated clip inline:
Route · Subscription · Models codex · ChatGPT Plus/Pro · live catalog from chatgpt.com/backend-api/codex/models claude · Claude Pro/Max · all models available in your subscription (Opus, Sonnet, Haiku, Fable — static catalog, updated with the plugin) grok · X Premium (xAI) · live catalog from api.x.ai/v1/models (chat models only); reasoning efforts from the Grok CLI catalog (cli-chat-proxy.grok.com/v1/models) copilot · GitHub Copilot · live catalog from api.githubcopilot.com/models (chat models on both wires, with per-model vision flags and reasoning efforts); login uses the OAuth device flow (enter the shown code at github.com/login/device) antigravity · Google Antigravity · live catalog from Antigravity v1internal:fetchAvailableModels; requests use generateContent / streamGenerateContent with text, image, streaming reasoning, and tool-call conversion
Only logged-in providers appear in the session model picker; the lists above refresh on login/logout. Vision-capable models declare ['text', 'image'] input modalities, and image content is translated to each provider's wire format.
Logged-in cards also show subscription usage — per rate-limit window (5-hour session, weekly, and per-model weekly where the plan has one) with the used percentage, a progress bar, and the reset time, plus a Refresh button. Codex usage comes from chatgpt.com/backend-api/wham/usage (also reports the plan), Claude usage from api.anthropic.com/api/oauth/usage, and Grok usage from the Grok Build CLI proxy's cli-chat-proxy.grok.com/v1/billing (the source of the CLI's /usage panel; reports the shared weekly pool and the subscription tier). Antigravity reports plan, credits, and per-model quotas from loadCodeAssist and fetchAvailableModels when those fields are present. Copilot exposes no usage endpoint, so its card shows no usage section.
Also included, registered when the matching provider is enabled:
web seam and does not claim it: with no other search provider mounted DSH auto-selects it, and alongside another one you pick the winner with the host's own web.searchProvider setting. Turning Web search off under Codex's Provider tools withdraws this provider, leaving the host's web_search tool to whatever else is registered.{ answer, citations }.gpt-image-2 via the Codex backend, or grok-imagine-image-2.0 via api.x.ai/v1/images/generations. The provider argument picks the preferred provider (gpt, the default, or grok); when the preferred one is logged out the other serves as fallback. Images are saved under ~/.dsh/plugins/subscriptions/images/ and the paths returned. The size/quality arguments map onto Grok's aspect_ratio/quality on the Grok path.grok-imagine-video-1.5 via api.x.ai/v1/videos (async submit + poll); MP4s are saved under ~/.dsh/plugins/subscriptions/videos/, the path returned, and the clip plays inline in the conversation. Supports duration (1–15 s), aspect ratio, resolution, and image-to-video via image_url.image_generate also supports editing: the model passes optional referenceImages (1–5 complete DSH attachment references) to edit or use existing images as sources; omitting it keeps text-to-image generation. References can come from uploads, read_image, or previous generated images. Read local files with read_image first; paths are not attachment references. Copy references from the image reference text or structured tool results. Their order matches the prompt's image order. Edits save new files and return reusable references, including for subsequent edits with another provider.
Codex edits use /backend-api/codex/images/edits; Grok edits use /v1/images/edits. Existing provider preference, logged-out fallback, and session tool policy still apply. Empty arrays, duplicate or invalid references, and attachment-limit violations fail explicitly instead of generating a new image. Editing requires the DSH attachment service.
Image generation and editing share same-provider account scheduling: try the default account first, then prefer the successful account in that session. Explicit quota, authentication, or image-entitlement rejection tries the remaining accounts; a 401 gets at most one credential refresh and retry first. Image-only cooldowns honor provider reset times and clear on login/logout. Transport failures, timeouts, 5xx responses, and invalid requests do not automatically resend, avoiding duplicate images. Set pool.enabled: false or pool.autoAccounts: false (legacy autoFamilies is accepted) to use only the default account. Image scheduling does not use chat catalogs, chat quota scoring, families, or tiers.
Version 0.9.7 added support for DSH 0.2.0-rc.2; DSH 0.2.1-alpha.2, 0.2.1-alpha.3 and 0.2.1-rc.2 are supported as well, with development dependencies pinned to 0.2.1-rc.2. It handles request-only messages, first-class tool results, preparing tool views, and offloaded image placeholders while retaining legacy history translation. 0.2.1-rc.2 additionally requires tool arguments on every call head and takes the web runtime's provider overrides as Volatile refs. Other 0.2 prereleases are not implicitly allowed.
In DSH 0.2.1-rc.2, the load-time check uses engines.dsh when declared; otherwise, every @deepseek-ai/dsh and @deepseek-ai/dsh-* peer must match the running DSH version. Prereleases participate in this check. This plugin does not declare engines.dsh, so its DSH peer ranges determine whether it can load. The @deepseek-ai/cordis and @deepseek-ai/schemastery peers affect package-manager dependency resolution, not this load-time check. They keep their ^4.0.1 / ^3.18.1 floors and also list the 4.0.5-alpha / 3.18.5-alpha builds bundled with DSH 0.2.1-alpha.2 and 0.2.1-alpha.3, because those caret ranges exclude these prereleases under npm's default semver rules.
The current release supports the published DSH 0.1.1-rc.2, 0.1.2-alpha/rc, 0.1.3-alpha, 0.1.5-alpha/rc, and 0.1.7-rc lines, including 0.1.5-rc.2 and 0.1.7-rc.2. The 0.1.5-alpha.1 peer-range anchor intentionally covers the later 0.1.5-alpha, 0.1.5-rc, and stable 0.1.5 builds under npm semver rules; the 0.1.7-rc.1 anchor likewise covers the later 0.1.7-rc and stable 0.1.7 builds. DSH 0.1.6-alpha and 0.1.7-alpha are not included until they have been separately verified.
Open Settings → Subscriptions → provider → Manage to edit account aliases, automatic-pool participation and model allowlists, and independent account model entries. Existing accounts continue using automatic pooling by default. Independent entries stay bound to one account and never fall back to another account when unavailable. These settings govern LLM routing, not image/video/search tool account policies. See Account and model management.
The model picker uses saved catalogs immediately, including catalogs for non-default accounts, without waiting for network discovery or starting a refresh on each open or selection. The plugin checks catalogs at startup, skips snapshots fetched within the last five minutes, then checks again 60 minutes after the previous check finishes. Failed checks retain saved models and wait for the next scheduled check. An account without any saved catalog still waits for its first discovery.
In Settings → Subscriptions → provider → Edit model list, use Refresh to fetch the current catalog immediately and update the conversation model picker. Successful background updates also invalidate the picker cache. This is separate from subscription-usage and credential refresh, whose behavior is unchanged. If models. is explicitly configured with a non-empty list, that list still overrides discovery.
Codex catalog visibility depends on the client_version request parameter. By default the plugin reads the stable version from the official npm @openai/codex package's public metadata (no CLI installation or subscription credentials sent to npm). Successful lookups are cached in memory for six hours; failures retry after five minutes and retain the last successful version, or the verified 0.153.4 fallback on first use. The lookup has a 5-second deadline, shares in-flight work across accounts, and ignores prerelease or regressed versions. On load the plugin also raises Node's Happy Eyeballs per-address connect attempt timeout to at least 1.5 seconds (never lowering a larger host value), because the 250ms default drops every connection on links where one TCP handshake takes longer than that. Manual model-list refresh also rechecks the version. An explicit plugin configuration field, codexClientVersion: '0.153.4', takes precedence and disables automatic lookup; restart DSH after changing it. Model availability remains account-dependent; see verification notes.
Claude requests present themselves as Claude Code, and the endpoint gates newer models on the Claude Code version (for example, Opus 5.5 requires 2.1.280 or newer). The plugin therefore reads the latest version from the official npm @anthropic-ai/claude-code package's public metadata, with the same caching, deadline, and retry rules as the Codex lookup, and no subscription credentials sent to npm. It never presents a version older than the locally installed claude CLI or the bundled fallback, which is also what it uses while npm is unreachable. Manual model-list refresh also rechecks the version. Settings → Subscriptions shows the version Codex and Claude currently present next to each name, along with its source: the latest on npm, the local CLI, the built-in fallback, or your configured value. A fallback there means the npm lookup is not getting through.
With the dsh CLI available, install from npm (prebuilt artifacts, no build permission needed):
dsh plugin --profile web add dsh-plugin-subscriptionsOr install the sources from GitHub:
dsh plugin --profile web add github:V1ki/dsh-plugin-subscriptionspnpm will ask you to allow this package's build script on first install (git installs fetch sources, not built artifacts); add the printed key to the profile's pnpm-workspace.yaml:
allowBuilds:
dsh-plugin-subscriptions: trueand re-run the add. Only grant this to packages you trust — it runs the package's code at install time.
From a local checkout instead:
git clone https://github.com/V1ki/dsh-plugin-subscriptions.git
cd dsh-plugin-subscriptions && pnpm install && pnpm build
dsh plugin --profile web add ./dsh-plugin-subscriptionsHeadless-only usage without installing into a profile (log in via the web UI first — the token file is shared):
cp overlay.example.yml overlay.yml # then edit the name: to this checkout's absolute lib/index.js path
dsh --profile headless --patch <checkout>/overlay.yml "your task"Installed from npm:
dsh plugin --profile web update --latest dsh-plugin-subscriptionsInstalled from GitHub: re-run the same add github:V1ki/dsh-plugin-subscriptions command — it re-fetches the sources and rebuilds. A linked local checkout just needs git pull && pnpm build in the checkout.
Either way, restart dsh web afterwards so the new version loads.
dsh web, open the printed URL.claude and logged in at least once; without them, Claude authorizes in the browser like the others. For Codex, Grok, and Antigravity, authorize in the opened browser tab; Copilot shows a GitHub device code to enter at github.com/login/device; if a browser flow can't complete (headless host), expand the manual fallback and paste the callback URL or code./model) and choose a model under ChatGPT (Codex) / Claude (Subscription) / Grok (Subscription) / GitHub Copilot / Google Antigravity.Not logged in? The provider stays out of the picker, and requests fail with MISSING_CREDENTIAL pointing at the Settings page; nothing else breaks.
Every provider accepts several accounts: once one is connected, the card grows an Add account button (Claude offers Browser authorization and Import Claude Code separately). Accounts are keyed by their identity (email / login) — re-logging the same account updates it in place, a different account appends. Browser authorization signs in whichever account the browser currently uses, so switch accounts there first (or use an incognito window with the manual code) to add a different one. The ★ default account serves the direct provider routes; pool routes use every account. A Claude account imported from Claude Code stays synced with the CLI's credential store; OAuth-added Claude accounts refresh standalone so several accounts never fight over the Keychain entry.
Open Settings → Subscriptions → provider → Edit model list, search and select models, then Save changes. All discovered models are shown automatically by default. Selecting individual models, selecting all, or clearing the selection saves an explicit list; newly discovered models then stay hidden until selected. Enable automatic display again to restore discovery-driven visibility. Hidden models remain usable by existing sessions, and the editor retains the full catalog so they can be restored. Refreshing discovery preserves preferences. The dialog has one Save changes / Cancel pair: Save submits the model list together with the account settings above it, and Cancel discards both and closes the dialog.
Codex models also accept a context budget in tokens; leave it blank to follow the provider. The plugin reads each account's context_window and max_context_window, caps the requested budget at that account's maximum, and uses the advertised default as the conservative ceiling when no maximum is provided. Account pools resolve each member separately and use the smallest window. This changes DSH's local history budget and compaction timing, without sending an API capacity override. Longer contexts can increase response latency.
The same editor controls Codex Web Search and image generation, plus Grok image generation, video generation, and X search. Changes apply only to sessions created after saving; existing sessions retain their creation-time policy, including after restart. Image generation is shared: it disappears only when neither configured provider enables it, and execution never falls back to a provider disabled for that session. Claude and Copilot currently have no standalone subscription tools to configure.
Preferences and tool-policy history live in ~/.dsh/plugins/subscriptions/provider-settings.json (mode 0600), independently of model-catalog refresh. Existing non-empty models. configuration still defines the base catalog; visibility selections filter that catalog.
Default reasoning effort now lives in Edit model list, beside each model's visibility and context settings. Apply edits with the dialog's Save changes, or discard unsaved edits with Cancel. Hidden models remain editable. Models without reasoning levels have no selector; Follow provider clears an override. Choices come from live capabilities, intersected across account-pool members. Custom pool aliases do not offer ineffective effort overrides.
Existing defaults continue to load from and save to ~/.dsh/plugins/subscriptions/model-defaults.json (mode 0600). If a save fails partway through, unfinished edits remain in the draft; the UI reports any defaults already saved and lets you retry.
- id: llm-subscriptions
name: dsh-plugin-subscriptions
config:
providers: [codex, claude] # subset; default all five
streamIdleTimeoutMs: 300000
claudePromptCacheTtl: 5m # Claude prompt-cache lifetime: 5m (default) or 1h
rateLimit:
wait: true # wait out a closed rate-limit window (default)
maxWaitMs: 21600000 # ceiling on one wait; 6 h, covers a 5-hour session window
models: # override the discovered/built-in catalogs
codex:
- { id: gpt-5.6-sol, name: GPT-5.6 Sol, contextWindow: 272000, inputModalities: [text, image] }
copilot: # manual entries disable Copilot catalog discovery
- { id: gpt-5.6-sol, wire