@goodandready/dsh-subscriptions 0.4.14 → 0.4.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +157 -213
- package/README.ru.md +174 -0
- package/README.zh.md +109 -0
- package/lib/accounts.js +5 -3
- package/lib/adapter.js +3 -1
- package/lib/client.js +150 -0
- package/lib/index.js +294 -9
- package/lib/loopback.js +66 -0
- package/lib/mask.js +21 -0
- package/lib/proxy.js +79 -0
- package/lib/subscriptions.js +4 -1
- package/lib/vendors/codex.js +45 -0
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,233 +1,177 @@
|
|
|
1
|
-
# dsh-subscriptions
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
# 📦 @goodandready/dsh-subscriptions
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
<h3>Personal AI Subscription Bridge, Multi-Account Pool Rotation & Zero-Leak OAuth for DeepSeek Harness</h3>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/@goodandready/dsh-subscriptions"><img src="https://img.shields.io/npm/v/@goodandready/dsh-subscriptions.svg?style=for-the-badge&color=6366f1&labelColor=1e1b4b" alt="npm version"></a>
|
|
9
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-10b981.svg?style=for-the-badge&color=10b981&labelColor=064e3b" alt="license"></a>
|
|
10
|
+
<a href="https://github.com/topics/dsh-plugin"><img src="https://img.shields.io/badge/DSH-Plugin-8b5cf6.svg?style=for-the-badge&labelColor=2e1065" alt="DSH Plugin"></a>
|
|
11
|
+
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node-20%2B-f59e0b.svg?style=for-the-badge&labelColor=451a03" alt="Node version"></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
<a href="https://goodandready.app/"><img src="https://img.shields.io/badge/All_Author_Projects-goodandready.app-ff4500.svg?style=for-the-badge&logo=rocket&logoColor=white&labelColor=1a1a2e" alt="All Author Projects"></a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="README.md"><b>🇬🇧 English</b></a> •
|
|
20
|
+
<a href="README.ru.md"><b>🇷🇺 Русский</b></a> •
|
|
21
|
+
<a href="README.zh.md"><b>🇨🇳 中文说明</b></a>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## ⚡ Overview
|
|
29
|
+
|
|
30
|
+
**`dsh-subscriptions`** bridges your paid personal AI subscriptions directly into **DeepSeek Harness** as first-class LLM providers.
|
|
31
|
+
|
|
32
|
+
Instead of burning expensive pay-as-you-go API credits for everyday agent tasks, `dsh-subscriptions` allows you to authenticate your existing web subscriptions via standard OAuth PKCE. It features **multi-account rotation pools** (automatically switching accounts when a rate limit or cooldown is reached), **preemptive quota switching**, and an **in-process Cordis service (`ctx.subscriptions`)** that safely powers sibling plugins like [`dsh-image-gen`](https://github.com/GooDAnDReaDY/dsh-image-gen) and [`dsh-grok-xsearch`](https://github.com/GooDAnDReaDY/dsh-grok-xsearch) with zero token leakage.
|
|
33
|
+
|
|
34
|
+
```mermaid
|
|
35
|
+
graph LR
|
|
36
|
+
subgraph DSHCore [DeepSeek Harness Session]
|
|
37
|
+
Agent[🤖 DSH Agent Execution] --> Router{Provider Router}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
subgraph SubscriptionsCore [dsh-subscriptions Engine]
|
|
41
|
+
Router --> Pool{Multi-Account Vendor Pool}
|
|
42
|
+
Pool -->|Account #1| Acc1[👤 Primary Account: Active]
|
|
43
|
+
Pool -->|Account #2| Acc2[👤 Secondary Account: Standby]
|
|
44
|
+
Pool -->|Account #3| Acc3[👤 Fallback Account: Cooldown]
|
|
45
|
+
Acc1 -->|HTTP 429 / Quota Limit| Rotate[Smart Quota & Cooldown Rotator]
|
|
46
|
+
Rotate -->|Switches Traffic| Acc2
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
subgraph VendorBridges [4 Upstream Vendor Bridges]
|
|
50
|
+
Acc1 --> B1[ChatGPT / Codex Backend]
|
|
51
|
+
Acc1 --> B2[Claude Pro / Max Protocol]
|
|
52
|
+
Acc1 --> B3[xAI / Grok Subscriptions]
|
|
53
|
+
Acc1 --> B4[Google Cloud Code Assist / Antigravity]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
subgraph EcosystemBridge [In-Process Cordis Service: ctx.subscriptions]
|
|
57
|
+
Pool --> ImgGen[dsh-image-gen: Zero-Cost Image Drawing]
|
|
58
|
+
Pool --> XSearch[dsh-grok-xsearch: Live Twitter Search]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
style DSHCore fill:#1e1e2e,stroke:#89b4fa,stroke-width:2px,color:#cdd6f4
|
|
62
|
+
style SubscriptionsCore fill:#181825,stroke:#cba6f7,stroke-width:2px,color:#cdd6f4
|
|
63
|
+
style VendorBridges fill:#11111b,stroke:#a6e3a1,stroke-width:2px,color:#cdd6f4
|
|
64
|
+
style EcosystemBridge fill:#181825,stroke:#f38ba8,stroke-width:2px,color:#cdd6f4
|
|
21
65
|
```
|
|
22
66
|
|
|
23
|
-
|
|
24
|
-
`lib/` — pnpm reuses the previous copy otherwise.
|
|
25
|
-
|
|
26
|
-
## Settings
|
|
27
|
-
|
|
28
|
-
Settings live on a collapsible card in **Settings → Plugins → Plugin settings**
|
|
29
|
-
(not a sidebar entry). Click **Show** to expand it.
|
|
30
|
-
|
|
31
|
-
1. Pick a provider block and click **Connect**. Complete sign-in in the browser.
|
|
32
|
-
2. **+ Add account** adds another account slot for the same provider; every
|
|
33
|
-
account participates in rotation.
|
|
34
|
-
3. **Disconnect** removes that account's token; **Reconnect** repeats OAuth on
|
|
35
|
-
the same slot. The × button disconnects and drops the slot.
|
|
36
|
-
4. If the provider redirects to a localhost or vendor URL that this host cannot
|
|
37
|
-
receive, paste the full redirected URL (or the `code` value) into the
|
|
38
|
-
account row and click **Submit code**.
|
|
39
|
-
5. Logged-in providers appear in the session model picker.
|
|
40
|
-
|
|
41
|
-
Leave **Use this Web UI origin as OAuth redirect_uri** off unless you registered
|
|
42
|
-
your own OAuth client for this origin. Vendor CLI clients typically require
|
|
43
|
-
their published redirect URI plus the paste step.
|
|
44
|
-
|
|
45
|
-
## Accounts and rotation
|
|
46
|
-
|
|
47
|
-
Each provider holds any number of account slots (`CODEX_OAUTH_1`,
|
|
48
|
-
`CODEX_OAUTH_2`, …). On `RATE_LIMIT`, `QUOTA`, or HTTP 429 the plugin cools the
|
|
49
|
-
account down (`cooldownMs`, default 30 minutes) and retries the same request on
|
|
50
|
-
the next account of the same provider — never a different provider.
|
|
51
|
-
|
|
52
|
-
Beyond error-driven rotation, accounts are proactively skipped when:
|
|
53
|
-
|
|
54
|
-
- usage is at 100% for the current window (vendor-reported), or
|
|
55
|
-
- remaining quota fraction is at or below `switchAtRemaining`
|
|
56
|
-
(default `0.01` = 1%), or
|
|
57
|
-
- the window resets within one minute (no point spending the tail).
|
|
58
|
-
|
|
59
|
-
When every account is below threshold, the request still goes out on the first
|
|
60
|
-
exhausted account — a refusal beats silence.
|
|
61
|
-
|
|
62
|
-
## Quota visibility
|
|
63
|
-
|
|
64
|
-
Vendors that report usage expose named windows (Claude `5h`/`7d apps`,
|
|
65
|
-
Codex primary/secondary, Grok credits). Each window renders as a progress bar
|
|
66
|
-
with percent; colors follow theme variables (normal / warning ≥70% / exhausted
|
|
67
|
-
100%). The last known snapshot persists across harness restarts and refreshes
|
|
68
|
-
on the next successful request.
|
|
69
|
-
|
|
70
|
-
The plugin also estimates remaining requests for the primary window
|
|
71
|
-
(`≈ N (5h)`) once enough request history exists — hidden when data is thin.
|
|
72
|
-
|
|
73
|
-
### Limit notifications
|
|
74
|
-
|
|
75
|
-
When a window crosses 70%, 90%, or 100%, the plugin logs a warning and emits a
|
|
76
|
-
`subscriptions.limit-notice` event (provider, ref, window id, usedPercent,
|
|
77
|
-
threshold). Each threshold fires once per window until it resets. Toggle with
|
|
78
|
-
`notifyLimits` in Config.
|
|
79
|
-
|
|
80
|
-
## Background maintenance
|
|
81
|
-
|
|
82
|
-
Two timers run while the plugin is loaded:
|
|
83
|
-
|
|
84
|
-
- **Token refresh ahead**: expiring tokens are refreshed before they are needed
|
|
85
|
-
(`refreshAheadMs`, default 5 min). Failures back off via `refreshRetryMs`
|
|
86
|
-
(default 10 min) and mark the card as *reconnect required*.
|
|
87
|
-
- **Health probe loop**: every `probeIntervalMin` minutes (default 15, 0
|
|
88
|
-
disables) each connected account gets a cheap vendor check. Dead accounts
|
|
89
|
-
surface in the card; probes never set cooldown.
|
|
90
|
-
|
|
91
|
-
Both timers clean up on plugin dispose.
|
|
92
|
-
|
|
93
|
-
## HTTP proxy
|
|
94
|
-
|
|
95
|
-
`POST|GET /dsh-subscriptions/proxy/{provider}/{path…}` forwards to the vendor
|
|
96
|
-
API on behalf of a logged-in account — through the same allowlist, rotation,
|
|
97
|
-
and quota accounting as model traffic. Same-origin only; no token ever appears
|
|
98
|
-
in a response or log. Paths outside the per-provider allowlist get 403.
|
|
99
|
-
|
|
100
|
-
Example:
|
|
67
|
+
---
|
|
101
68
|
|
|
102
|
-
|
|
103
|
-
curl -X POST https://<host>:3080/dsh-subscriptions/proxy/codex/models \
|
|
104
|
-
-H 'Content-Type: application/json' -d '{}'
|
|
105
|
-
```
|
|
69
|
+
## ✨ Key Features & Capabilities
|
|
106
70
|
|
|
107
|
-
|
|
71
|
+
### 1. 🌐 4 Supported Built-in Subscription Vendors
|
|
108
72
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
73
|
+
| Vendor Key | Subscription Tier | Protocol & Features |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| `codex` | ChatGPT Plus / Pro | Codex streaming responses, tool calling & image drawing (`/backend-api/codex/...`) |
|
|
76
|
+
| `claude` | Claude Pro / Max | Native Claude Messages protocol, usage tracking (`/v1/messages`, `/api/oauth/...`) |
|
|
77
|
+
| `grok` | xAI / X Premium | Real-time reasoning responses, billing checks & social search |
|
|
78
|
+
| `antigravity` | Google Cloud Code Assist | Antigravity engine (`/v1/loadCodeAssist`, `/v1/streamGenerateContent`) |
|
|
79
|
+
|
|
80
|
+
*Custom vendors can also be dynamically registered via the `createVendorFromProfile` factory.*
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
### 2. 🔄 Multi-Account Rotation & Rate-Limit Mitigation (`rotate.js`, `ratelimit.js`)
|
|
85
|
+
* **Multi-Account Pooling**: Attach multiple accounts per vendor (e.g. `CODEX_OAUTH_1`, `CODEX_OAUTH_2`, `CODEX_OAUTH_3`).
|
|
86
|
+
* **Automatic 429 Failover**: When an account encounters a rate limit (`HTTP 429`, `RATE_LIMIT`, `QUOTA_EXCEEDED`), traffic instantly fails over to the next healthy account in the pool.
|
|
87
|
+
* **Preemptive Quota Switching (`switchAtRemaining`)**: Automatically rotates to the next account before hitting zero if the rate-limit window reset is imminent.
|
|
88
|
+
* **Dynamic Cooldown Calculation**: Parses upstream headers (`Retry-After`, `x-ratelimit-reset`, ISO dates, epoch timestamps) and auto-restores cooled-down accounts when their window resets.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
### 3. 🔒 Zero-Leak Credential Security & Headless OAuth
|
|
93
|
+
* **Zero Token Leakage**: OAuth tokens are **never** returned over HTTP API endpoints or rendered in the Web UI. The UI only receives masked account labels, connection health, and quota bars.
|
|
94
|
+
* **Secure Host Storage**: Tokens reside in encrypted `$DSH_HOME/.credentials.yaml` managed by the host credentials service.
|
|
95
|
+
* **Headless / Remote Login Fallback**: If running DSH on a headless server over SSH where browser popups cannot redirect to `localhost`, simply paste the redirected callback URL or authorization code directly into the account card.
|
|
96
|
+
* **Proactive Background Token Refresh**: Access tokens are refreshed automatically before expiration.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### 4. 🧩 In-Process Cordis Service (`ctx.subscriptions`)
|
|
101
|
+
Sibling plugins can tap into subscription capabilities directly in memory via Cordis:
|
|
102
|
+
```javascript
|
|
103
|
+
// Example in dsh-image-gen or custom plugins:
|
|
104
|
+
const res = await ctx.subscriptions.request('codex', '/backend-api/codex/images/generations', {
|
|
105
|
+
method: 'POST',
|
|
106
|
+
body: JSON.stringify({ prompt: 'Cyberpunk landscape', size: '1024x1024' }),
|
|
107
|
+
})
|
|
121
108
|
```
|
|
109
|
+
* **Zero Overhead**: Eliminates intermediate HTTP loops and keeps auth tokens strictly in-memory.
|
|
110
|
+
* **Strict Path Allowlist (`ALLOWLIST`)**: Restricts calls to verified vendor endpoints, preventing SSRF vulnerabilities.
|
|
122
111
|
|
|
123
|
-
|
|
124
|
-
(scrypt). Without the passphrase nothing decrypts; wrong passphrase fails with
|
|
125
|
-
a clear error. Tokens are never logged.
|
|
126
|
-
|
|
127
|
-
## Composer provider switcher
|
|
112
|
+
---
|
|
128
113
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
114
|
+
### 5. 🔐 Login Without a Browser: Loopback & Device Code (`v0.4.9`)
|
|
115
|
+
* **Automatic Loopback Callback (`autoLoopback`, on by default)**: For vendors whose OAuth redirect URI is a loopback address (Codex `:1455`, Grok `:56121`), the plugin spins up a temporary local HTTP server and catches the callback by itself — no URL pasting needed. The paste fallback always stays available.
|
|
116
|
+
* **Device Code Login (Codex)**: On fully headless machines (no browser on any reachable host), use the **Device login** button in the Codex account card. The plugin requests a short user code from `auth.openai.com`, you open `https://auth.openai.com/codex/device` on any device, enter the code, and the plugin completes the standard PKCE exchange automatically.
|
|
117
|
+
* **Classic Fallbacks Intact**: Web-origin redirect (`useWebCallback`) and manual paste of the redirected URL / authorization code remain available for custom OAuth clients.
|
|
132
118
|
|
|
133
|
-
|
|
119
|
+
### 6. 🌍 Per-Account HTTP/SOCKS Proxy (`v0.4.9`)
|
|
120
|
+
* **Individual Proxy per Account (`proxyUrl`)**: Every account slot accepts its own proxy URL (`http://`, `https://`, `socks5://[user:pass@]host:port`). All requests for that account — OAuth token refresh, vendor checks, model requests — are routed through it. Empty = direct connection.
|
|
121
|
+
* **One-Click Proxy Check**: The account card has a **Check proxy** button: it performs a real request to the vendor base URL through the configured proxy and shows the round-trip latency or the failure reason.
|
|
122
|
+
* **Request History Timings**: Every recorded request now carries its duration (`ms`) in the history store, so you can compare direct vs proxied latency over time.
|
|
134
123
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
124
|
+
### 7. 🕶️ Privacy Masking & Diagnostics Report (`v0.4.9`)
|
|
125
|
+
* **Privacy Masking (`privacyMask`)**: One toggle in the settings card masks personal data across the whole UI: emails render as `j***n@example.com` everywhere (account lists, status labels, check results). Designed for screen sharing and streaming. Server-side masking means labels never leak through API responses either; the underlying account data is never overwritten.
|
|
126
|
+
* **Anonymized Diagnostics Report**: The settings card has a **Generate diagnostics report** block: one click fetches an anonymized report (plugin/runtime versions, OS, per-vendor health counters, aggregate HTTP status counts, last ≥400 errors with timings, non-secret settings) and copies it to the clipboard. Tokens, emails, credential refs and proxy URLs are strictly excluded (verified by tests).
|
|
127
|
+
* **Issue-Ready**: The same block links to the project issue tracker, so a bug report is: generate → paste → submit.
|
|
138
128
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
129
|
+
### 8. 🔌 HTTP API (added in `v0.4.9`)
|
|
130
|
+
| Route | Method | Purpose |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| `/dsh-subscriptions/diagnostics` | GET | Anonymized diagnostics report (no secrets, no tokens, no proxy URLs) |
|
|
133
|
+
| `/dsh-subscriptions/proxy-check` | POST | Latency check of a slot's proxy against its vendor base URL |
|
|
134
|
+
| `/dsh-subscriptions/oauth/device/start` | POST | Begin Codex device-code login (returns user code + verification URL) |
|
|
135
|
+
| `/dsh-subscriptions/oauth/device/poll` | POST | Poll device-code authorization status |
|
|
143
136
|
|
|
144
|
-
|
|
137
|
+
---
|
|
145
138
|
|
|
146
|
-
|
|
139
|
+
## 📦 Quick Installation
|
|
147
140
|
|
|
141
|
+
```bash
|
|
142
|
+
dsh plugin --profile web add @goodandready/dsh-subscriptions
|
|
148
143
|
```
|
|
149
|
-
/login <provider> # start OAuth for codex|claude|grok|antigravity (opens the vendor page)
|
|
150
|
-
/login status # insert the connected providers into the composer
|
|
151
|
-
/logout <provider> # disconnect that provider
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## /subscriptions page
|
|
155
|
-
|
|
156
|
-
A localhost-only summary page at `/dsh-subscriptions/subscriptions` lists every account slot,
|
|
157
|
-
connection status, usage percent, remaining quota and reset time across all
|
|
158
|
-
providers. Requests from non-loopback hosts get 403.
|
|
159
|
-
|
|
160
|
-
## Import a token directly
|
|
161
|
-
|
|
162
|
-
In any account card, paste an existing refresh token (or API key) and click
|
|
163
|
-
**Import token** to sign in without the browser OAuth round trip. The token is
|
|
164
|
-
written straight to the host credentials store via
|
|
165
|
-
`POST /dsh-subscriptions/import-token { provider, index, refreshToken }`.
|
|
166
|
-
|
|
167
144
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
145
|
+
> [!IMPORTANT]
|
|
146
|
+
> Restart DSH Web UI after installation (`systemctl --user restart dsh-web`) and navigate to **Settings → Subscriptions** to link your accounts.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## ⚙️ Configuration Reference (`settings.yaml`)
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
dsh-subscriptions:
|
|
154
|
+
switchAtRemaining: 1
|
|
155
|
+
cooldownMs: 60000
|
|
156
|
+
autoLoopback: true # v0.4.9: catch loopback OAuth callbacks automatically
|
|
157
|
+
privacyMask: false # v0.4.9: mask emails and account identifiers in the UI
|
|
158
|
+
# Per-slot fields (v0.4.9): expiresAt (ms epoch), proxyUrl (http/https/socks5://)
|
|
159
|
+
accounts:
|
|
160
|
+
codex:
|
|
161
|
+
- ref: CODEX_OAUTH_1
|
|
162
|
+
label: "Work Pro Account"
|
|
163
|
+
- ref: CODEX_OAUTH_2
|
|
164
|
+
label: "Personal Plus Account"
|
|
165
|
+
claude:
|
|
166
|
+
- ref: CLAUDE_OAUTH_1
|
|
167
|
+
label: "Claude Max"
|
|
168
|
+
grok:
|
|
169
|
+
- ref: GROK_OAUTH_1
|
|
170
|
+
label: "X Premium"
|
|
175
171
|
```
|
|
176
172
|
|
|
177
|
-
|
|
178
|
-
Settings GET never returns access or refresh tokens — only
|
|
179
|
-
`{ configured, label, usagePercent, cooldownUntil, ref }`.
|
|
180
|
-
|
|
181
|
-
## Providers
|
|
182
|
-
|
|
183
|
-
| Key | Subscription | Default OAuth client |
|
|
184
|
-
|---|---|---|
|
|
185
|
-
| `codex` | ChatGPT / Codex | Vendor-public Codex CLI client id |
|
|
186
|
-
| `claude` | Claude Pro/Max | Vendor-public Claude Code client id |
|
|
187
|
-
| `grok` | xAI / SuperGrok | Vendor-public Grok CLI client id |
|
|
188
|
-
| `antigravity` | Google Antigravity | Your OAuth client id + secret in Config |
|
|
189
|
-
|
|
190
|
-
Override `codexClientId`, `claudeClientId`, and the other empty Config fields
|
|
191
|
-
if you register your own OAuth app.
|
|
192
|
-
|
|
193
|
-
Live requests use the vendor subscription surfaces, not API-key hosts:
|
|
194
|
-
Codex `chatgpt.com/backend-api/codex/responses`, Claude Messages with the
|
|
195
|
-
OAuth beta header, Grok `cli-chat-proxy.grok.com` with CLI identity headers,
|
|
196
|
-
and Antigravity Cloud Code Assist (`loadCodeAssist` then
|
|
197
|
-
`streamGenerateContent`). Usage endpoints, when they answer, feed the skip
|
|
198
|
-
logic above. If a live model list fails, the built-in catalog is used.
|
|
199
|
-
|
|
200
|
-
Antigravity uses a confidential Google OAuth client: set `antigravityClientId`
|
|
201
|
-
and `antigravityClientSecret` in plugin Config (Settings) — nothing is baked
|
|
202
|
-
into the repository.
|
|
203
|
-
|
|
204
|
-
Default model catalogs are built-in lists you can replace with
|
|
205
|
-
`codexModels`, `claudeModels`, `grokModels`, `antigravityModels`
|
|
206
|
-
in the plugin Config.
|
|
207
|
-
|
|
208
|
-
### Config reference
|
|
209
|
-
|
|
210
|
-
| Key | Default | Meaning |
|
|
211
|
-
|---|---|---|
|
|
212
|
-
| `cooldownMs` | 1800000 | Cooldown after RATE_LIMIT/QUOTA/429 |
|
|
213
|
-
| `switchAtRemaining` | 0.01 | Skip account when remaining ≤ this (fraction <1 or absolute ≥1); 0 disables |
|
|
214
|
-
| `refreshAheadMs` | 300000 | Refresh tokens expiring within this window |
|
|
215
|
-
| `refreshRetryMs` | 600000 | Backoff after a failed background refresh |
|
|
216
|
-
| `probeIntervalMin` | 15 | Account health-check interval, minutes; 0 disables |
|
|
217
|
-
| `notifyLimits` | true | Emit notices when usage crosses 70/90/100% |
|
|
218
|
-
| `useWebCallback` | false | Use Web UI origin as OAuth redirect_uri |
|
|
219
|
-
| `<vendor>Models` | built-in | Replace default model catalog per vendor |
|
|
220
|
-
|
|
221
|
-
## Identity
|
|
222
|
-
|
|
223
|
-
These three names must match:
|
|
224
|
-
|
|
225
|
-
| Place | Value |
|
|
226
|
-
|---|---|
|
|
227
|
-
| `package.json` `name` | `@goodandready/dsh-subscriptions` |
|
|
228
|
-
| `cordis.patch.yml` `name:` | `@goodandready/dsh-subscriptions` |
|
|
229
|
-
| `lib/client.js` loader `id` | `@goodandready/dsh-subscriptions` |
|
|
173
|
+
---
|
|
230
174
|
|
|
231
|
-
## License
|
|
175
|
+
## 📄 License
|
|
232
176
|
|
|
233
|
-
MIT
|
|
177
|
+
MIT © [GooDAnDReaDY](https://github.com/GooDAnDReaDY)
|
package/README.ru.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# 📦 @goodandready/dsh-subscriptions
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
<h3>Мост персональных подписок на ИИ, ротация пула аккаунтов и безопасный OAuth без утечки токенов для DeepSeek Harness</h3>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/@goodandready/dsh-subscriptions"><img src="https://img.shields.io/npm/v/@goodandready/dsh-subscriptions.svg?style=for-the-badge&color=6366f1&labelColor=1e1b4b" alt="npm version"></a>
|
|
9
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-10b981.svg?style=for-the-badge&color=10b981&labelColor=064e3b" alt="license"></a>
|
|
10
|
+
<a href="https://github.com/topics/dsh-plugin"><img src="https://img.shields.io/badge/DSH-Plugin-8b5cf6.svg?style=for-the-badge&labelColor=2e1065" alt="DSH Plugin"></a>
|
|
11
|
+
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node-20%2B-f59e0b.svg?style=for-the-badge&labelColor=451a03" alt="Node version"></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
<a href="https://goodandready.app/"><img src="https://img.shields.io/badge/Все_проекты_автора-goodandready.app-ff4500.svg?style=for-the-badge&logo=rocket&logoColor=white&labelColor=1a1a2e" alt="Все проекты автора"></a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="README.md"><b>🇬🇧 English</b></a> •
|
|
20
|
+
<a href="README.ru.md"><b>🇷🇺 Русский</b></a> •
|
|
21
|
+
<a href="README.zh.md"><b>🇨🇳 中文说明</b></a>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## ⚡ Обзор
|
|
29
|
+
|
|
30
|
+
**`dsh-subscriptions`** подключает ваши платные персональные подписки на нейросети напрямую в **DeepSeek Harness** в качестве полноценных LLM-провайдеров.
|
|
31
|
+
|
|
32
|
+
Вместо поминутной оплаты дорогих API-ключей для повседневных задач агента, плагин позволяет авторизовать ваши существующие веб-подписки через безопасный протокол OAuth PKCE. Поддерживаются **пулы из нескольких аккаунтов** с автоматической ротацией при исчерпании лимитов, **упреждающее переключение квот** и **внутрипроцессный сервис Cordis (`ctx.subscriptions`)**, который питает соседние плагины (например, [`dsh-image-gen`](https://github.com/GooDAnDReaDY/dsh-image-gen) и [`dsh-grok-xsearch`](https://github.com/GooDAnDReaDY/dsh-grok-xsearch)) без утечки токенов в сеть.
|
|
33
|
+
|
|
34
|
+
```mermaid
|
|
35
|
+
graph LR
|
|
36
|
+
subgraph DSHCore [Сессия диалога DeepSeek Harness]
|
|
37
|
+
Agent[🤖 Выполнение задач агентом] --> Router{Маршрутизатор провайдеров}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
subgraph SubscriptionsCore [Ядро dsh-subscriptions]
|
|
41
|
+
Router --> Pool{Пул аккаунтов вендора}
|
|
42
|
+
Pool -->|Аккаунт 1| Acc1[👤 Основной аккаунт: Активен]
|
|
43
|
+
Pool -->|Аккаунт 2| Acc2[👤 Второй аккаунт: Ожидание]
|
|
44
|
+
Pool -->|Аккаунт 3| Acc3[👤 Запасной аккаунт: Cooldown]
|
|
45
|
+
Acc1 -->|HTTP 429 / Превышение квоты| Rotate[Умный ротатор квот и задержек]
|
|
46
|
+
Rotate -->|Перенаправление трафика| Acc2
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
subgraph VendorBridges [4 Адаптера вендоров]
|
|
50
|
+
Acc1 --> B1[Бэкенд ChatGPT / Codex]
|
|
51
|
+
Acc1 --> B2[Протокол Claude Pro / Max]
|
|
52
|
+
Acc1 --> B3[Подписки xAI / Grok]
|
|
53
|
+
Acc1 --> B4[Google Cloud Code Assist / Antigravity]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
subgraph EcosystemBridge [Сервис Cordis: ctx.subscriptions]
|
|
57
|
+
Pool --> ImgGen[dsh-image-gen: Бесплатная генерация картинок]
|
|
58
|
+
Pool --> XSearch[dsh-grok-xsearch: Поиск в X Twitter]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
style DSHCore fill:#1e1e2e,stroke:#89b4fa,stroke-width:2px,color:#cdd6f4
|
|
62
|
+
style SubscriptionsCore fill:#181825,stroke:#cba6f7,stroke-width:2px,color:#cdd6f4
|
|
63
|
+
style VendorBridges fill:#11111b,stroke:#a6e3a1,stroke-width:2px,color:#cdd6f4
|
|
64
|
+
style EcosystemBridge fill:#181825,stroke:#f38ba8,stroke-width:2px,color:#cdd6f4
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## ✨ Ключевые возможности
|
|
70
|
+
|
|
71
|
+
### 1. 🌐 4 Поддерживаемых встроенных вендора подписок
|
|
72
|
+
|
|
73
|
+
| Ключ вендора | Тариф подписки | Протокол и возможности |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| `codex` | ChatGPT Plus / Pro | Стриминг Codex, вызов инструментов и генерация картинок (`/backend-api/codex/...`) |
|
|
76
|
+
| `claude` | Claude Pro / Max | Нативный протокол Claude Messages, трекинг расхода (`/v1/messages`, `/api/oauth/...`) |
|
|
77
|
+
| `grok` | xAI / X Premium | Ответы с рассуждениями, проверка баланса и поиск в соцсети |
|
|
78
|
+
| `antigravity` | Google Cloud Code Assist | Движок Antigravity (`/v1/loadCodeAssist`, `/v1/streamGenerateContent`) |
|
|
79
|
+
|
|
80
|
+
*Также поддерживается регистрация кастомных вендоров через фабрику профилей `createVendorFromProfile`.*
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
### 2. 🔄 Ротация аккаунтов и защита от лимитов (`rotate.js`, `ratelimit.js`)
|
|
85
|
+
* **Пулы из нескольких аккаунтов**: привязка нескольких аккаунтов на вендора (`CODEX_OAUTH_1`, `CODEX_OAUTH_2`...).
|
|
86
|
+
* **Автоматическое переключение при 429**: при превышении лимита запросов трафик мгновенно переключается на следующий свободный аккаунт.
|
|
87
|
+
* **Упреждающее переключение квот (`switchAtRemaining`)**: смена аккаунта до падения в ошибку, если окно сброса близко.
|
|
88
|
+
* **Динамический расчёт Cooldown**: парсинг заголовков `Retry-After`, `x-ratelimit-reset`, дат ISO и миллисекундных меток с автоматическим возвратом остывших аккаунтов в строй.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
### 3. 🔒 Безопасность и авторизация на headless-серверах
|
|
93
|
+
* **Нулевая утечка токенов**: токен OAuth **никогда** не отдаётся в браузер или через публичный HTTP API. В интерфейсе видны только статус, имя и остаток квоты.
|
|
94
|
+
* **Хранилище хоста**: токены шифруются в `$DSH_HOME/.credentials.yaml`.
|
|
95
|
+
* **Вход без браузера (SSH / Remote)**: если сервер запущен удалённо, авторизацию можно завершить, просто вставив итоговый redirect URL или authorization code в карточку аккаунта.
|
|
96
|
+
* **Фоновое продление токенов**: плагин автоматически обновляет токены до истечения их срока действия.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### 4. 🧩 Внутрипроцессный сервис Cordis (`ctx.subscriptions`)
|
|
101
|
+
Другие плагины могут использовать подключенные подписки напрямую в памяти:
|
|
102
|
+
```javascript
|
|
103
|
+
// Пример вызова из dsh-image-gen:
|
|
104
|
+
const res = await ctx.subscriptions.request('codex', '/backend-api/codex/images/generations', {
|
|
105
|
+
method: 'POST',
|
|
106
|
+
body: JSON.stringify({ prompt: 'Cyberpunk landscape', size: '1024x1024' }),
|
|
107
|
+
})
|
|
108
|
+
```
|
|
109
|
+
* **Нулевой оверхед**: прямое общение без лишних HTTP-запросов.
|
|
110
|
+
* **Белый список путей (`ALLOWLIST`)**: строгий контроль вызываемых эндпоинтов для защиты от SSRF.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### 5. 🔐 Вход без браузера: loopback и device-код (`v0.4.9`)
|
|
115
|
+
* **Автоматический loopback-callback (`autoLoopback`, включён по умолчанию)**: если redirect_uri вендора — loopback-адрес (Codex `:1455`, Grok `:56121`), плагин сам поднимает временный локальный HTTP-сервер и ловит callback без ручной вставки ссылки. Ручная вставка остаётся как запасной путь.
|
|
116
|
+
* **Вход по коду устройства (Codex)**: на полностью headless-машинах нажмите **Device login** в карточке аккаунта Codex: плагин запросит короткий код на `auth.openai.com`, вы открываете `https://auth.openai.com/codex/device` с любого устройства, вводите код — плагин сам завершает стандартный PKCE-обмен.
|
|
117
|
+
* **Классические варианты на месте**: redirect на origin веб-интерфейса (`useWebCallback`) и ручная вставка адреса/кода доступны как раньше.
|
|
118
|
+
|
|
119
|
+
### 6. 🌍 Индивидуальный HTTP/SOCKS-прокси на аккаунт (`v0.4.9`)
|
|
120
|
+
* **Прокси на слот (`proxyUrl`)**: каждый аккаунт принимает свой адрес `http://`, `https://`, `socks5://[user:pass@]host:port`. Через него идут все запросы аккаунта — обновление токенов, проверки вендора, запросы моделей. Пусто = прямое соединение.
|
|
121
|
+
* **Проверка в один клик**: кнопка **Check proxy** в карточке аккаунта делает реальный запрос к базовому URL вендора через прокси и показывает задержку или причину отказа.
|
|
122
|
+
* **Тайминги в истории**: каждая запись истории запросов теперь содержит длительность (`ms`) — удобно сравнивать прямое соединение и прокси.
|
|
123
|
+
|
|
124
|
+
### 7. 🕶️ Режим приватности и диагностический отчёт (`v0.4.9`)
|
|
125
|
+
* **Маскирование (`privacyMask`)**: один тумблер в карточке настроек скрывает персональные данные во всём интерфейсе: email отображается как `j***n@example.com` (списки аккаунтов, статусы, результаты проверок). Маскирование выполняется на сервере — личные данные не утекут и через ответы API; сами данные аккаунтов при этом не перезаписываются. Задумано для демонстраций экрана и стримов.
|
|
126
|
+
* **Анонимизированный диагностический отчёт**: блок **Generate diagnostics report**: один клик — отчёт (версии плагина/рантайма, ОС, счётчики здоровья по вендорам, агрегаты HTTP-статусов, последние ошибки ≥400 с таймингами, не-секретные настройки) скачан и скопирован в буфер. Токены, email, имена учётных записей и адреса прокси исключены (покрыто тестами).
|
|
127
|
+
* **Готово для issue**: рядом ссылка на трекер задач — баг-репорт это «сгенерировать → вставить → отправить».
|
|
128
|
+
|
|
129
|
+
### 8. 🔌 HTTP API (добавлено в `v0.4.9`)
|
|
130
|
+
| Маршрут | Метод | Назначение |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| `/dsh-subscriptions/diagnostics` | GET | Анонимизированный диагностический отчёт (без секретов, токенов и адресов прокси) |
|
|
133
|
+
| `/dsh-subscriptions/proxy-check` | POST | Проверка задержки прокси слота через базовый URL вендора |
|
|
134
|
+
| `/dsh-subscriptions/oauth/device/start` | POST | Начать вход Codex по коду устройства (возвращает код и адрес подтверждения) |
|
|
135
|
+
| `/dsh-subscriptions/oauth/device/poll` | POST | Опрос статуса авторизации по коду устройства |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 📦 Быстрая установка
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
dsh plugin --profile web add @goodandready/dsh-subscriptions
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## ⚙️ Пример конфигурации (`settings.yaml`)
|
|
148
|
+
|
|
149
|
+
```yaml
|
|
150
|
+
dsh-subscriptions:
|
|
151
|
+
switchAtRemaining: 1
|
|
152
|
+
cooldownMs: 60000
|
|
153
|
+
autoLoopback: true # v0.4.9: автоматически ловить loopback-callback
|
|
154
|
+
privacyMask: false # v0.4.9: маскировать email и учётные записи в UI
|
|
155
|
+
# Поля слота (v0.4.9): expiresAt (ms), proxyUrl (http/https/socks5://)
|
|
156
|
+
accounts:
|
|
157
|
+
codex:
|
|
158
|
+
- ref: CODEX_OAUTH_1
|
|
159
|
+
label: "Рабочий Pro-аккаунт"
|
|
160
|
+
- ref: CODEX_OAUTH_2
|
|
161
|
+
label: "Личный Plus-аккаунт"
|
|
162
|
+
claude:
|
|
163
|
+
- ref: CLAUDE_OAUTH_1
|
|
164
|
+
label: "Claude Max"
|
|
165
|
+
grok:
|
|
166
|
+
- ref: GROK_OAUTH_1
|
|
167
|
+
label: "X Premium"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 📄 Лицензия
|
|
173
|
+
|
|
174
|
+
MIT © [GooDAnDReaDY](https://github.com/GooDAnDReaDY)
|