# πŸ“¦ @goodandready/dsh-clinebot

Native ClineBot / ClinePass Provider Companion for DeepSeek Harness

0.6.15 connects multimodal budgeting, exposes model probe/visibility controls, adds the price auto-sync switch and closes the remaining audit hygiene/security findings. Chat runs on the native ctx.llm adapter and requires DSH 0.2.1-rc.2; the legacy llm-pi-ai, loopback proxy and llm/stream path are removed.

npm version license DSH Plugin Node version

GoodAndReady Showcase

πŸ‡¬πŸ‡§ English β€’ πŸ‡·πŸ‡Ί Русский β€’ πŸ‡¨πŸ‡³ δΈ­ζ–‡θ―΄ζ˜Ž

⭐ If you like this plugin, please star it on GitHub β€” it shows me that the plugin is useful to you and motivates me to keep developing it.

πŸ› If you find a bug or would like to request a feature, open a GitHub issue in any language β€” I will review your proposal and implement useful suggestions in a future plugin version.
--- ## ⚑ Overview & The Problem **ClinePass** (`https://cline.bot`) is a subscription service providing developers with 2–5x higher rate limits across premier open-weights coding and reasoning models through a single OpenAI-compatible endpoint (`https://api.cline.bot/api/v1`). Integrating ClinePass into DeepSeek Harness (DSH) natively poses key challenges: 1. **No `/v1/models` Discovery**: `GET /v1/models` on `api.cline.bot` returns `404 Not Found`. Dynamic discovery fails silently or leaves the provider with 0 models. 2. **Model Identifier Formats**: Models require the specific prefix `cline-pass/` (e.g. `cline-pass/deepseek-v4.1-flash`, `cline-pass/kimi-k3`). 3. **Quota Tracking**: Rolling 5-hour and weekly limits need clear in-browser visualization. 4. **Credential Security**: Storing API keys directly in plain settings is insecure. **`@goodandready/dsh-clinebot`** provides a complete solution: * πŸš€ **One-Click In-App Updater**: Upgrade `@goodandready/dsh-clinebot` directly from the DSH UI or trigger secure loopback updates via `/dsh-clinebot/update`. * ⚑ **SWR Quota & Health Caching**: Instantaneous response time (<2ms) on status queries with background revalidation. * πŸ”€ **Smart Quota-Aware Failover**: Automatic multi-account rotation on stream HTTP 429 and exhausted quota (with 30s storm protection; current request is not retried, subsequent chat requests use the next available account). * πŸ–₯️ **Plugin configuration page**: Open the installed ClineBot plugin and choose configure. The page shows the credential name, models, quota, and accounts. It is not a separate sidebar section. * πŸ”„ **Dynamic Subscription Model Sync**: Automatically pulls real models included in your ClinePass plan directly from `GET /api/v1/users/me/plan` with one-click DSH provider sync. Only actual plan models are registered in DSH, while the built-in catalog serves as a rich properties reference and fallback when unsynced. * ⚠️ **Quota Exhaustion Alerts**: Real-time visual warning banners when 5-hour rolling limit reaches 80% (warning) and 95% (exhausted), complete with countdown to reset. * πŸ“ˆ **Session Metrics Telemetry**: Live dashboard tracking real in-flight DSH chat requests through the ClineBot provider, prompt and completion tokens, stream latency, and error counts since process startup. * πŸ“Š **Live Quota Dashboard**: Visual progress bars for 5-hour rolling limits and weekly windows from the official `GET /users/me/plan/usage-limits` API. * πŸ”‘ **In-UI Key Storage**: Paste your API key directly in the UI; it is saved securely via `ctx.credentials.set()` into `~/.dsh/.credentials.yaml`. * 🎯 **Model Picker Management**: Granular checkboxes to choose which models appear in the chat picker. * πŸ’¬ **Slash-Command `/cline`**: Check quota, limits, warnings, session metrics, latency, and active model directly from the DSH chat console. --- ## πŸ›οΈ Architecture ```mermaid graph LR subgraph UI [DSH Web Interface] Settings["Settings -> ClineBot"] Dashboard["Quota / Analytics panel"] Composer["Composer cost read-out"] Picker["Model picker"] end subgraph PluginHost [dsh-clinebot Runtime] Routes["HTTP: /dsh-clinebot/*"] Adapter["lib/adapter.js (ctx.llm LlmAdapter)"] Transport["lib/transport/cline-transport.js"] Pool["account-pool + session-router"] Stats["stats-storage v2 + model-prices"] TUI["dsh-TUI settings section"] end subgraph DSHCore [DeepSeek Harness 0.2.1-rc.2] Llm["ctx.llm"] Credentials["ctx.credentials"] Web["ctx.web / settings / commands"] end subgraph Upstream [ClinePass] Chat["api.cline.bot/api/v1/chat/completions"] Quota["users/me/plan/usage-limits"] Plan["users/me/plan"] end Settings --> Routes Dashboard --> Routes Composer --> Routes Picker --> Llm Llm --> Adapter Adapter --> Pool Adapter --> Transport Transport --> Chat Adapter --> Stats Routes --> Stats Routes --> Credentials TUI --> Routes Adapter --> Quota Adapter --> Plan ``` --- ## ✨ Features & Module Breakdown * **`lib/adapter.js`**: Registers the `ClineBotAdapter` directly on `ctx.llm`: streaming, model catalogue, reasoning effort, pre-first-token account failover, retry policy, usage accounting and provider metadata. * **`lib/transport/cline-transport.js`**: OpenAI-compatible SSE transport with connect/idle timeouts, abort handling and upstream error classification. * **`lib/models.js`**: Dynamic subscription catalogue, curated fallback properties, reasoning efforts, custom models and plan parsing (`parsePlanIncludedModels`, `getAllModels`, `getDynamicModels`). * **`lib/model-prices.js`**: Explicit local cost estimates with per-model overrides. Unknown models stay `unpriced` instead of being reported as $0. When a newly discovered model has no price, the optional `priceAutoSync` setting fetches the public models.dev catalog (at most once per missing set every 6 hours); turn it off in the price card or set `priceAutoSync: false` while keeping the manual Sync button. * **`lib/multimodal-budget.js`**: Offloads images from earlier turns into stable text placeholders and enforces `maxPayloadMb`, reducing prompt-cache churn and oversized ClinePass requests. `offloadedImages` is included in session telemetry. * **Model tools in Settings β†’ ClineBot β†’ Models**: The per-model **Ping** button calls `POST /models/probe` and shows TTFT; **Apply visibility** calls `POST /models/visible` after choosing the visible models and plan-only filter. * **`lib/stats-storage.js`**: Persistent JSON telemetry v2: cache buckets, estimated cost, TTFT/latency, sessions and day/month/model/account aggregates. v1 files upgrade on read. * **`lib/account-pool.js` / `lib/session-router.js`**: Credential discovery, usage-aware least-used and round-robin rotation, sticky sessions and cooldown recovery. * **`lib/cline-client.js`**: `fetchUsageLimits`, credential save, smoke test and the model catalogue cache. * **`lib/index.js`**: Cordis lifecycle: adapter registration, optional HTTP routes, quota warnings, `/cline` command, one-time cleanup of the old provider entry and TUI section registration. * **`lib/tui-settings.js`**: `dsh-TUI` section for key, base URL, model filters, active account, context window and output cap. * **`lib/client.js`**: Native `settings.section` plus provider card, sidebar meter, center-column quota/analytics panel (modal fallback) and composer cost read-out. No emojis, no full-page panel swap. --- ## πŸ“¦ Installation ```bash dsh plugin --profile web add @goodandready/dsh-clinebot ``` Requires **DSH `0.2.1-rc.2`** and Node 22+. ClineBot registers directly with `ctx.llm`; there is no transport switch or loopback proxy. Restart your DeepSeek Harness instance and refresh the browser. ### 0.6.0 endpoints | Endpoint | Purpose | | --- | --- | | `GET /dsh-clinebot/analytics?groupBy=model\|day\|session&from=&to=` | Aggregated requests, tokens, estimated cost, success rate and TTFT | | `GET /dsh-clinebot/prices` | Local price table used by the composer read-out | | `GET /dsh-clinebot/accounts/usage` | Per-account quota snapshot | | `GET /dsh-clinebot/stats/export?detailed=1` | CSV with cache, cost, TTFT and latency columns | --- ## πŸ’¬ Slash-Command `/cline` From any DSH chat session, type `/cline` to inspect quota, warning alerts, and session telemetry: ```text ### πŸ€– ClinePass Status (ClinePass) * Latency: βœ… 210 ms * Active Key: CLINEBOT_API_KEY (credentials) * Default Model: `cline-pass/deepseek-v4.1-flash` ⏱ 5-Hour Window: [β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘] 42% (resets: 18:00) πŸ“… Weekly Window: [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘] 60% (resets: Sep 8) * Account: `developer@example.com` πŸ“ˆ Session Metrics: * Requests: 14 calls * Tokens: ~8,450 (Prompt: 6,100 | Completion: 2,350) * Last Latency: 210 ms ``` --- ## βš™οΈ Configuration Reference (DSH Settings & Web UI) In modern DeepSeek Harness (0.1.7+), settings are managed natively via the DSH Web UI Settings card or `PUT /dsh-clinebot/config`, with API keys persisted securely in DSH Credentials storage (`~/.dsh/.credentials.yaml`). ```yaml dsh-clinebot: enabled: true baseUrl: https://api.cline.bot/api/v1 apiKeyEnv: CLINEBOT_API_KEY defaultModel: your-default-model disabledModels: [] customModels: [] modelReasoningDefaults: your-reasoning-model: high modelContextOverrides: [] statsPath: ~/.dsh/clinebot-stats.json priceCatalogUrl: https://models.dev/api.json priceCatalogPath: ~/.dsh/clinebot-prices.json priceAutoSync: true eventLogPath: ~/.dsh/clinebot-events.json statsRetentionDays: 95 dailyBudgetUsd: 0 monthlyBudgetUsd: 0 timeoutMs: 30000 smokeTimeoutMs: 60000 streamIdleTimeoutMs: 60000 accounts: - label: Team Key apiKeyEnv: CLINEBOT_API_KEY_2 ``` ### Configuration Parameters | Parameter | Type | Default | Description | |:---|:---|:---|:---| | `enabled` | `boolean` | `true` | Enable or disable the ClineBot provider bridge in DSH | | `baseUrl` | `string` | `"https://api.cline.bot/api/v1"` | ClinePass OpenAI-compatible base URL | | `apiKeyEnv` | `string` | `"CLINEBOT_API_KEY"` | Environment variable / credentials key name | | `defaultModel` | `string` | `"cline-pass/deepseek-v4.1-flash"` | Default selected model ID for chat and smoke tests | | `disabledModels` | `array` | `[]` | List of model IDs hidden from the DSH chat picker (new subscription models are auto-enabled) | | `customModels` | `array` | `[]` | User-defined gateway models (`[{ id, name, contextLength, maxTokens, category, isReasoning }]`) | | `modelReasoningDefaults` | `object` | `{}` | Configured default reasoning effort per model (`low`, `medium`, `high`, `max`) | | `modelContextOverrides` | `array` | `[]` | User-defined model context length and max token overrides | | `statsPath` | `string` | `"~/.dsh/clinebot-stats.json"` | Persistent on-disk path for token usage analytics | | `priceCatalogUrl` | `string` | `"https://models.dev/api.json"` | Public price catalog used by the optional sync | | `priceCatalogPath` | `string` | `"~/.dsh/clinebot-prices.json"` | Local cache for the public price catalog | | `priceAutoSync` | `boolean` | `true` | Fetch models.dev for newly discovered models without a price; the manual Sync button remains available when off | | `eventLogPath` | `string` | `"~/.dsh/clinebot-events.json"` | Ring buffer for account cooldown/recovery/routing history | | `statsRetentionDays` | `number` | `95` | Retention for day/hour/session telemetry; 0 keeps everything | | `dailyBudgetUsd` | `number` | `0` | Optional estimated daily spend guard; 0 disables it | | `monthlyBudgetUsd` | `number` | `0` | Optional estimated monthly spend guard; 0 disables it | | `accounts` | `array` | `[]` | Additional accounts for multi-account failover and quota rotation (`[{ label, apiKeyEnv }]`) | | `activeAccount` | `string` | `""` | Manually pinned active account env name (empty for least-used auto routing) | | `timeoutMs` | `number` | `15000` | HTTP probe timeout in milliseconds | | `smokeTimeoutMs` | `number` | `25000` | Timeout for smoke test chat completions in milliseconds | | `streamIdleTimeoutMs` | `number` | `30000` | Idle timeout between SSE stream chunks in milliseconds | | `enabledModels` | `array` | *(deprecated)* | Read-only in public config; rejected on `PUT /config` in favor of `disabledModels` | | `dynamicModels` | `array` | `[]` | Dynamic models automatically synced from the official plan | --- ## 🌐 HTTP API Endpoints All endpoints are registered under `/dsh-clinebot/*` and protected against untrusted cross-site origins (same-origin and loopback allowed). Control endpoints enforce a 256 KiB request payload limit: ### Management & Control Endpoints (Max 256 KiB) * `GET /dsh-clinebot/status` β€” Live status report including provider health, active credential, quota, and session metrics. * `GET /dsh-clinebot/config` β€” Diagnostic endpoint returning public configuration without secret keys. * `PUT /dsh-clinebot/config` β€” Update configuration fields. Accepts only known schema properties (unknown fields or deprecated `enabledModels` return `400 Bad Request`). * `POST /dsh-clinebot/key/verify` β€” Validates a candidate API key against `api.cline.bot` and returns account email and plan name. * `POST /dsh-clinebot/save-key` β€” Saves a key into DSH credentials service under a valid `CLINEBOT_API_KEY*` name. * `POST /dsh-clinebot/models/sync` β€” Synchronizes models with your active subscription plan. * `POST /dsh-clinebot/models/toggle` β€” Toggles models via `disabledModels` (atomic Volatile preservation). * `POST /dsh-clinebot/models/custom` / `DELETE /dsh-clinebot/models/custom` β€” Manage custom user-defined models. * `POST /dsh-clinebot/models/context` / `DELETE /dsh-clinebot/models/context` β€” Manage model context length overrides. * `POST /dsh-clinebot/accounts` β€” Add account to the multi-account pool. * `POST /dsh-clinebot/accounts/delete` β€” Delete account from the pool with atomic credential preservation. * `POST /dsh-clinebot/accounts/active` β€” Switch or pin active account (or empty for auto least-used routing). * `POST /dsh-clinebot/stats/reset` β€” Reset session request and token statistics. * `POST /dsh-clinebot/smoke` β€” Runs a live latency test ping. * `GET /dsh-clinebot/update/status` β€” Query available GitHub releases and plugin updates. * `POST /dsh-clinebot/update/apply` β€” Apply version upgrade with process-group cleanup and lockfile sync. --- ## Visual verification Settings card in DeepSeek Harness, Dark and Light themes side by side: ![dsh-clinebot visual verification](media/visual-verification.png) --- ## πŸ§ͺ Testing Run the automated test suite: ```bash npm test ``` --- ## πŸ“„ License MIT Β© [GooDAnDReaDY](https://github.com/GooDAnDReaDY)