dsh-qoder-connect 0.2.2 → 0.2.3-alpha.1

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Corrine Hu
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Corrine Hu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.en.md CHANGED
@@ -1,177 +1,177 @@
1
- # DSH Qoder Connect
2
-
3
- **English** | [简体中文](./README.md)
4
-
5
- A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH) plugin that brings your **Qoder subscription** models into DSH through a Personal Access Token (PAT). One plugin serves both Qoder product lines — each with its own settings card, provider id, credential file and saved catalog, never mixed:
6
-
7
- | Variant | Provider id | Card title | Where the PAT is minted |
8
- |---|---|---|---|
9
- | China (国内版) | `qoder` | Qoder | qoder.com.cn |
10
- | International (国际版) | `qoder-global` | Qoder Global | qoder.com |
11
-
12
- Configure only what you use: a variant with no saved PAT shows no model group and never interferes with the other one. Streaming, reasoning content and tool calls ride the plugin's built-in Qoder transport; the conversation loop, compaction and permissions stay Harness-owned.
13
-
14
- ## Features
15
-
16
- - **PAT: save it and it works** — paste a PAT into the card and press *Save*; the token is validated live against that variant's region before anything is written, and the model group appears immediately — no DSH restart. Once signed in, *Replace PAT* (the new token overwrites only after it validates, so a mistyped paste can never strand a working credential) and *Clear PAT* are one click away.
17
- - **Two independent variants** — `qoder` (china) and `qoder-global` (global) keep separate credential files, routes and saved catalogs: a token minted on qoder.com does not work against the China deployment and vice versa.
18
- - **Three-tier model catalog (live → saved → fallback)** — the card states where the list on screen came from: *“Model list updated …”* (fetched now), *“Showing the saved model list from …”* (this account's last successful fetch, restored after a restart or a failed fetch), or *“Showing the built-in model list (not yet updated from Qoder)”* (the roster compiled into the plugin). The reason of the most recent failed fetch is shown too, and a *Refresh model list* button sits right there.
19
- - **One-toggle context window** — each variant card's *Context window* tab lists every model's capacity (the default and the largest declared window) and carries its own *“Use the largest declared context window”* preference (on by default): on, requests declare the maximum (e.g. Qwen3.8-Max at 1M); off, the default (200K). The two variants keep independent toggle state.
20
- - **Model visibility toggles & batch controls** — each variant card provides a dedicated *Model Toggles* tab (between *Context window* and *Credit details*) to freely enable or hide individual models; disabled models are hidden from the DSH model picker, keeping it tidy; includes instant search by name/ID and one-click *Enable all* / *Disable all* batch operations.
21
- - **Daily auto check-in & logs** — claims the daily 100 Credits automatically, **at a time you can set per variant on the card** (10:00 UTC+8 by default, the upstream's reset moment), with independent toggles and startup catch-up protection. The card features a dedicated *Check-in log* panel with audit trails, *Check in now*, *Refresh*, and *Clear logs* quick actions.
22
- - **Sidebar quota card + credit details** — the *“Qoder sidebar display”* card toggles a per-variant sidebar quota widget (off by default; each toggle needs its variant's PAT saved) with one shared refresh interval (default 5 min, minimum 1 min). Clicking the sidebar widget opens the *Qoder quota* panel: one row per credit package — *“Remaining / Total + bar | Expires”* — plus the cycle share and reset time. Click the same widget again to close; click the other to switch variants.
23
- - **Rate display `x<priceFactor>`** — each model name is suffixed with the upstream-reported price multiplier (e.g. `Some Model · x0.79`, free is `x0`), spelled `x<n>` from the catalog's `price_factor`. Display only — it never changes the request; models whose rate the upstream did not report simply show no suffix.
24
-
25
- ## Screenshots
26
-
27
- ### Sidebar quota widgets & credit details
28
-
29
- Once enabled on the *“Qoder sidebar display”* card, a per-variant quota widget sits at the sidebar's foot; clicking it opens the *Qoder quota* panel with one row per credit package, switchable between the two variants at any time.
30
-
31
- **China (after clicking the sidebar widget):**
32
-
33
- ![China sidebar quota details](assets/1.png)
34
-
35
- **International (after clicking the sidebar widget):**
36
-
37
- ![International sidebar quota details](assets/2.png)
38
-
39
- ### Sidebar toggles
40
-
41
- The *“Qoder sidebar display”* card controls both widgets' visibility and the shared refresh interval:
42
-
43
- ![Sidebar display toggles](assets/3.png)
44
-
45
- ### Settings inside the Plugins panel
46
-
47
- The same Qoder settings card has a second home: sidebar → **Plugins** panel → Installed → the *Qoder 连接器* card. Open the card's detail page and the full configuration sits between the description and the component list — PAT, per-variant switches, context windows, model toggles, check-in and sidebar-quota settings, identical to the *Settings → Plugin settings* card (both surfaces share one configuration). On hosts that do not declare the seat (older DSH), only the Settings entry exists and nothing else changes.
48
-
49
- ### Picking a model in a session
50
-
51
- Once a PAT is saved, the model picker gains a Qoder group with per-model rate multipliers (`x0.5`, `x0`, …):
52
-
53
- ![Model picker in a session](assets/4.png)
54
-
55
- ### Context-window settings
56
-
57
- Each variant card's *Context window* tab lists capacities per model under the *“Use the largest declared context window”* preference:
58
-
59
- **China:**
60
-
61
- ![China context-window settings](assets/5.png)
62
-
63
- **International:**
64
-
65
- ![International context-window settings](assets/6.png)
66
-
67
- ### Model toggles & batch controls
68
-
69
- Both variant cards provide a *Model Toggles* tab (located between *Context window* and *Credit details*): search models on the fly, toggle individual models on or off, and use *Enable all* / *Disable all* batch buttons; hidden models will not appear in the session model picker.
70
-
71
- ![Model toggles & batch controls](assets/8.png)
72
-
73
- ### Daily Auto Check-In & Check-In Log
74
-
75
- Enable daily automatic check-in in the settings card and set each variant's own moment (10:00 UTC+8 by default), then inspect check-in history logs, trigger a manual check-in, or clear logs in the *Check-in log* tab:
76
-
77
- ![Daily Auto Check-In & Check-In Log](assets/7.png)
78
-
79
- ## Install
80
-
81
- Prerequisites:
82
-
83
- - DSH core `0.1.7-rc.1` or newer (this plugin peers on the `@deepseek-ai/*` `>=0.1.7-rc.1` line);
84
- - Node.js `^22.19.0 || >=24.0.0` (per `package.json` engines);
85
- - your own Qoder account and at least one Personal Access Token.
86
-
87
- ```sh
88
- # From GitHub (recommended)
89
- dsh plugin --profile web add github:masknull/dsh-qoder-connect
90
- # Or from npm
91
- dsh plugin --profile web add dsh-qoder-connect
92
- ```
93
-
94
- Swap the `--profile` value for the profile you use (`web` / `desktop` / `tui`, e.g. `dsh plugin --profile desktop add dsh-qoder-connect`) — data stays inside that profile, so web / desktop / tui never collide. On a terminal-only profile (TUI) there is no browser card: manage the PAT and check status through the bundled CLI instead; the settings card and sidebar widgets require Web or Desktop.
95
-
96
- > **DSH older than `0.1.7-rc.1`?** Use **[v0.2.0](https://github.com/masknull/dsh-qoder-connect/releases/tag/v0.2.0)** instead — the last release supporting the 0.1.5 line (DSH ≥ `0.1.5-rc.2`):
97
- >
98
- > ```sh
99
- > # From GitHub (recommended, pin the tag)
100
- > dsh plugin --profile web add github:masknull/dsh-qoder-connect#v0.2.0
101
- > # Or from npm
102
- > dsh plugin --profile web add dsh-qoder-connect@0.2.0
103
- > ```
104
- >
105
- > Upgrading from 0.1.5? This release removed the automatic migration of the old host's `settings.yaml`. To carry your old configuration over, migrate through **[v0.1.9](https://github.com/masknull/dsh-qoder-connect/releases/tag/v0.1.9)** (the first release with the data migration) first, then upgrade to this release.
106
-
107
- ## Configuration
108
-
109
- ### Mint a PAT
110
-
111
- - **Qoder (China)**: sign in at qoder.com.cn → account settings → Personal Access Token, then copy it. [Open the page](https://qoder.cn/account/integrations)
112
- - **Qoder Global**: sign in at qoder.com → account settings → Personal Access Token, then copy it. [Open the page](https://qoder.com/account/integrations)
113
-
114
- (The card repeats the same guidance: *“Generate a PAT in your qoder.com account settings (Account → Personal Access Token), then paste it here.”*)
115
-
116
- ### Save it on the card
117
-
118
- DSH → Settings → Plugin Settings (插件设置) → the Qoder card: paste the PAT into the password field and press *Save* (*“Validating and saving…”* while it runs). The token is validated against that variant's region first — a refusal saves nothing and the card says *“That PAT was rejected — generate a new one in your account settings and try again.”*. Do this on both cards to run both groups side by side.
119
-
120
- ### Environment-variable fallback
121
-
122
- For headless setups, the plugin reads an environment fallback **only when no credential file exists**:
123
-
124
- | Variant | Environment variable |
125
- |---|---|
126
- | `qoder` (china) | `QODER_CN_PERSONAL_ACCESS_TOKEN` |
127
- | `qoder-global` | `QODER_PERSONAL_ACCESS_TOKEN` |
128
-
129
- The precedence is **file > env**: as soon as a valid credential file is saved, a stray environment token stops mattering (the saved token always wins). Env-sourced credentials show as *source: environment variable* on the card, with no saved-at time.
130
-
131
- ## Data & privacy
132
-
133
- ### File layout
134
-
135
- Everything the plugin owns lives in one data directory: `<profile>/.dsh-qoder-connect/` — credentials at the root, rebuildable caches under `state/` (so “clear the cache” can never touch a credential):
136
-
137
- ```text
138
- <profile>/.dsh-qoder-connect/
139
- ├── .qoder-auth.json # China PAT ({version:2, pat, region, savedAt})
140
- ├── .qoder-global-auth.json # Global PAT
141
- ├── checkin-status.json # check-in status and history logs
142
- └── state/
143
- ├── .qoder-catalog.json # China per-account saved catalog
144
- ├── .qoder-global-catalog.json
145
- ├── .qoder-probe.json # China reasoning-effort probe records
146
- ├── .qoder-global-probe.json
147
- ├── .qoder-host-heartbeat.json # host heartbeat (doctor uses it)
148
- └── .qoder-machine-id # transport machine-id seed (never written to ~/.qoder)
149
- ```
150
-
151
- The directory follows the profile that declares this plugin (found under `$DSH_HOME/profiles/`), falling back to the Harness home when none can be determined; `DSH_QODER_DATA_DIR` overrides it explicitly.
152
-
153
- ## Development
154
-
155
- ```sh
156
- pnpm install
157
- pnpm run build # tsdown → lib/ (host bundle + client bundle)
158
- pnpm test # vitest run (tests/**/*.spec.ts)
159
- pnpm run test:qoder # node --test (tests/qoder/*.test.ts, the Qoder transport suite)
160
- pnpm run typecheck # tsc across the host and client tsconfigs
161
- pnpm run check # typecheck + test + test:qoder + build in one gate
162
- ```
163
-
164
- The upstream `node:test` suite for the Qoder transport layer now lives in `tests/qoder/` (run it with `pnpm run test:qoder`; the pristine `reference-qoder-tests/` copy has been removed) — `package.json` scripts are the source of truth.
165
-
166
- ## Provenance & license
167
-
168
- - Derived from [masknull/dsh-workbuddy-connect](https://github.com/masknull/dsh-workbuddy-connect) (MIT) — the connect-plugin skeleton this project was refactored from.
169
- - Qoder transport layer ported from [mo-n/dsh-provider-qoder](https://github.com/mo-n/dsh-provider-qoder) (MIT).
170
-
171
- Released under the [MIT](./LICENSE) license; see [NOTICE](./NOTICE) for the upstream attributions. This is a community adapter — not affiliated with, authorized by, or endorsed by Qoder or DeepSeek, and not an official implementation.
172
-
173
- ## Disclaimer
174
-
175
- - Qoder's endpoints come from the upstream repositories: upstream may change, rate-limit or block them at any time, breaking part or all of this plugin with no compatibility window to promise.
176
- - For personal learning and research only; this tool drives **your own** Qoder account. Do not use it commercially or beyond reasonable personal use. You are responsible for complying with Qoder's terms of service and for any consequence — account restriction, quota loss, service interruption — of using this project.
177
- - The authors are not liable for any direct or indirect loss arising from use or misuse of this project. The names Qoder, DeepSeek and related marks belong to their respective owners and appear here only to describe compatibility.
1
+ # DSH Qoder Connect
2
+
3
+ **English** | [简体中文](./README.md)
4
+
5
+ A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH) plugin that brings your **Qoder subscription** models into DSH through a Personal Access Token (PAT). One plugin serves both Qoder product lines — each with its own settings card, provider id, credential file and saved catalog, never mixed:
6
+
7
+ | Variant | Provider id | Card title | Where the PAT is minted |
8
+ |---|---|---|---|
9
+ | China (国内版) | `qoder` | Qoder | qoder.com.cn |
10
+ | International (国际版) | `qoder-global` | Qoder Global | qoder.com |
11
+
12
+ Configure only what you use: a variant with no saved PAT shows no model group and never interferes with the other one. Streaming, reasoning content and tool calls ride the plugin's built-in Qoder transport; the conversation loop, compaction and permissions stay Harness-owned.
13
+
14
+ ## Features
15
+
16
+ - **PAT: save it and it works** — paste a PAT into the card and press *Save*; the token is validated live against that variant's region before anything is written, and the model group appears immediately — no DSH restart. Once signed in, *Replace PAT* (the new token overwrites only after it validates, so a mistyped paste can never strand a working credential) and *Clear PAT* are one click away.
17
+ - **Two independent variants** — `qoder` (china) and `qoder-global` (global) keep separate credential files, routes and saved catalogs: a token minted on qoder.com does not work against the China deployment and vice versa.
18
+ - **Three-tier model catalog (live → saved → fallback)** — the card states where the list on screen came from: *“Model list updated …”* (fetched now), *“Showing the saved model list from …”* (this account's last successful fetch, restored after a restart or a failed fetch), or *“Showing the built-in model list (not yet updated from Qoder)”* (the roster compiled into the plugin). The reason of the most recent failed fetch is shown too, and a *Refresh model list* button sits right there.
19
+ - **One-toggle context window** — each variant card's *Context window* tab lists every model's capacity (the default and the largest declared window) and carries its own *“Use the largest declared context window”* preference (on by default): on, requests declare the maximum (e.g. Qwen3.8-Max at 1M); off, the default (200K). The two variants keep independent toggle state.
20
+ - **Model visibility toggles & batch controls** — each variant card provides a dedicated *Model Toggles* tab (between *Context window* and *Credit details*) to freely enable or hide individual models; disabled models are hidden from the DSH model picker, keeping it tidy; includes instant search by name/ID and one-click *Enable all* / *Disable all* batch operations.
21
+ - **Daily auto check-in & logs** — claims the daily 100 Credits automatically, **at a time you can set per variant on the card** (10:00 UTC+8 by default, the upstream's reset moment), with independent toggles and startup catch-up protection. The card features a dedicated *Check-in log* panel with audit trails, *Check in now*, *Refresh*, and *Clear logs* quick actions.
22
+ - **Sidebar quota card + credit details** — the *“Qoder sidebar display”* card toggles a per-variant sidebar quota widget (off by default; each toggle needs its variant's PAT saved) with one shared refresh interval (default 5 min, minimum 1 min). Clicking the sidebar widget opens the *Qoder quota* panel: one row per credit package — *“Remaining / Total + bar | Expires”* — plus the cycle share and reset time. Click the same widget again to close; click the other to switch variants.
23
+ - **Rate display `x<priceFactor>`** — each model name is suffixed with the upstream-reported price multiplier (e.g. `Some Model · x0.79`, free is `x0`), spelled `x<n>` from the catalog's `price_factor`. Display only — it never changes the request; models whose rate the upstream did not report simply show no suffix.
24
+
25
+ ## Screenshots
26
+
27
+ ### Sidebar quota widgets & credit details
28
+
29
+ Once enabled on the *“Qoder sidebar display”* card, a per-variant quota widget sits at the sidebar's foot; clicking it opens the *Qoder quota* panel with one row per credit package, switchable between the two variants at any time.
30
+
31
+ **China (after clicking the sidebar widget):**
32
+
33
+ ![China sidebar quota details](assets/1.png)
34
+
35
+ **International (after clicking the sidebar widget):**
36
+
37
+ ![International sidebar quota details](assets/2.png)
38
+
39
+ ### Sidebar toggles
40
+
41
+ The *“Qoder sidebar display”* card controls both widgets' visibility and the shared refresh interval:
42
+
43
+ ![Sidebar display toggles](assets/3.png)
44
+
45
+ ### Settings inside the Plugins panel
46
+
47
+ The same Qoder settings card has a second home: sidebar → **Plugins** panel → Installed → the *Qoder 连接器* card. Open the card's detail page and the full configuration sits between the description and the component list — PAT, per-variant switches, context windows, model toggles, check-in and sidebar-quota settings, identical to the *Settings → Plugin settings* card (both surfaces share one configuration). On hosts that do not declare the seat (older DSH), only the Settings entry exists and nothing else changes.
48
+
49
+ ### Picking a model in a session
50
+
51
+ Once a PAT is saved, the model picker gains a Qoder group with per-model rate multipliers (`x0.5`, `x0`, …):
52
+
53
+ ![Model picker in a session](assets/4.png)
54
+
55
+ ### Context-window settings
56
+
57
+ Each variant card's *Context window* tab lists capacities per model under the *“Use the largest declared context window”* preference:
58
+
59
+ **China:**
60
+
61
+ ![China context-window settings](assets/5.png)
62
+
63
+ **International:**
64
+
65
+ ![International context-window settings](assets/6.png)
66
+
67
+ ### Model toggles & batch controls
68
+
69
+ Both variant cards provide a *Model Toggles* tab (located between *Context window* and *Credit details*): search models on the fly, toggle individual models on or off, and use *Enable all* / *Disable all* batch buttons; hidden models will not appear in the session model picker.
70
+
71
+ ![Model toggles & batch controls](assets/8.png)
72
+
73
+ ### Daily Auto Check-In & Check-In Log
74
+
75
+ Enable daily automatic check-in in the settings card and set each variant's own moment (10:00 UTC+8 by default), then inspect check-in history logs, trigger a manual check-in, or clear logs in the *Check-in log* tab:
76
+
77
+ ![Daily Auto Check-In & Check-In Log](assets/7.png)
78
+
79
+ ## Install
80
+
81
+ Prerequisites:
82
+
83
+ - DSH core `0.1.7-rc.1` or newer (this plugin peers on the `@deepseek-ai/*` `>=0.1.7-rc.1` line);
84
+ - Node.js `^22.19.0 || >=24.0.0` (per `package.json` engines);
85
+ - your own Qoder account and at least one Personal Access Token.
86
+
87
+ ```sh
88
+ # From GitHub (recommended)
89
+ dsh plugin --profile web add github:masknull/dsh-qoder-connect
90
+ # Or from npm
91
+ dsh plugin --profile web add dsh-qoder-connect
92
+ ```
93
+
94
+ Swap the `--profile` value for the profile you use (`web` / `desktop` / `tui`, e.g. `dsh plugin --profile desktop add dsh-qoder-connect`) — data stays inside that profile, so web / desktop / tui never collide. On a terminal-only profile (TUI) there is no browser card: manage the PAT and check status through the bundled CLI instead; the settings card and sidebar widgets require Web or Desktop.
95
+
96
+ > **DSH older than `0.1.7-rc.1`?** Use **[v0.2.0](https://github.com/masknull/dsh-qoder-connect/releases/tag/v0.2.0)** instead — the last release supporting the 0.1.5 line (DSH ≥ `0.1.5-rc.2`):
97
+ >
98
+ > ```sh
99
+ > # From GitHub (recommended, pin the tag)
100
+ > dsh plugin --profile web add github:masknull/dsh-qoder-connect#v0.2.0
101
+ > # Or from npm
102
+ > dsh plugin --profile web add dsh-qoder-connect@0.2.0
103
+ > ```
104
+ >
105
+ > Upgrading from 0.1.5? This release removed the automatic migration of the old host's `settings.yaml`. To carry your old configuration over, migrate through **[v0.1.9](https://github.com/masknull/dsh-qoder-connect/releases/tag/v0.1.9)** (the first release with the data migration) first, then upgrade to this release.
106
+
107
+ ## Configuration
108
+
109
+ ### Mint a PAT
110
+
111
+ - **Qoder (China)**: sign in at qoder.com.cn → account settings → Personal Access Token, then copy it. [Open the page](https://qoder.cn/account/integrations)
112
+ - **Qoder Global**: sign in at qoder.com → account settings → Personal Access Token, then copy it. [Open the page](https://qoder.com/account/integrations)
113
+
114
+ (The card repeats the same guidance: *“Generate a PAT in your qoder.com account settings (Account → Personal Access Token), then paste it here.”*)
115
+
116
+ ### Save it on the card
117
+
118
+ DSH → Settings → Plugin Settings (插件设置) → the Qoder card: paste the PAT into the password field and press *Save* (*“Validating and saving…”* while it runs). The token is validated against that variant's region first — a refusal saves nothing and the card says *“That PAT was rejected — generate a new one in your account settings and try again.”*. Do this on both cards to run both groups side by side.
119
+
120
+ ### Environment-variable fallback
121
+
122
+ For headless setups, the plugin reads an environment fallback **only when no credential file exists**:
123
+
124
+ | Variant | Environment variable |
125
+ |---|---|
126
+ | `qoder` (china) | `QODER_CN_PERSONAL_ACCESS_TOKEN` |
127
+ | `qoder-global` | `QODER_PERSONAL_ACCESS_TOKEN` |
128
+
129
+ The precedence is **file > env**: as soon as a valid credential file is saved, a stray environment token stops mattering (the saved token always wins). Env-sourced credentials show as *source: environment variable* on the card, with no saved-at time.
130
+
131
+ ## Data & privacy
132
+
133
+ ### File layout
134
+
135
+ Everything the plugin owns lives in one data directory: `<profile>/.dsh-qoder-connect/` — credentials at the root, rebuildable caches under `state/` (so “clear the cache” can never touch a credential):
136
+
137
+ ```text
138
+ <profile>/.dsh-qoder-connect/
139
+ ├── .qoder-auth.json # China PAT ({version:2, pat, region, savedAt})
140
+ ├── .qoder-global-auth.json # Global PAT
141
+ ├── checkin-status.json # check-in status and history logs
142
+ └── state/
143
+ ├── .qoder-catalog.json # China per-account saved catalog
144
+ ├── .qoder-global-catalog.json
145
+ ├── .qoder-probe.json # China reasoning-effort probe records
146
+ ├── .qoder-global-probe.json
147
+ ├── .qoder-host-heartbeat.json # host heartbeat (doctor uses it)
148
+ └── .qoder-machine-id # transport machine-id seed (never written to ~/.qoder)
149
+ ```
150
+
151
+ The directory follows the profile that declares this plugin (found under `$DSH_HOME/profiles/`), falling back to the Harness home when none can be determined; `DSH_QODER_DATA_DIR` overrides it explicitly.
152
+
153
+ ## Development
154
+
155
+ ```sh
156
+ pnpm install
157
+ pnpm run build # tsdown → lib/ (host bundle + client bundle)
158
+ pnpm test # vitest run (tests/**/*.spec.ts)
159
+ pnpm run test:qoder # node --test (tests/qoder/*.test.ts, the Qoder transport suite)
160
+ pnpm run typecheck # tsc across the host and client tsconfigs
161
+ pnpm run check # typecheck + test + test:qoder + build in one gate
162
+ ```
163
+
164
+ The upstream `node:test` suite for the Qoder transport layer now lives in `tests/qoder/` (run it with `pnpm run test:qoder`; the pristine `reference-qoder-tests/` copy has been removed) — `package.json` scripts are the source of truth.
165
+
166
+ ## Provenance & license
167
+
168
+ - Derived from [masknull/dsh-workbuddy-connect](https://github.com/masknull/dsh-workbuddy-connect) (MIT) — the connect-plugin skeleton this project was refactored from.
169
+ - Qoder transport layer ported from [mo-n/dsh-provider-qoder](https://github.com/mo-n/dsh-provider-qoder) (MIT).
170
+
171
+ Released under the [MIT](./LICENSE) license; see [NOTICE](./NOTICE) for the upstream attributions. This is a community adapter — not affiliated with, authorized by, or endorsed by Qoder or DeepSeek, and not an official implementation.
172
+
173
+ ## Disclaimer
174
+
175
+ - Qoder's endpoints come from the upstream repositories: upstream may change, rate-limit or block them at any time, breaking part or all of this plugin with no compatibility window to promise.
176
+ - For personal learning and research only; this tool drives **your own** Qoder account. Do not use it commercially or beyond reasonable personal use. You are responsible for complying with Qoder's terms of service and for any consequence — account restriction, quota loss, service interruption — of using this project.
177
+ - The authors are not liable for any direct or indirect loss arising from use or misuse of this project. The names Qoder, DeepSeek and related marks belong to their respective owners and appear here only to describe compatibility.