pi-provider-qoder-cn 0.1.0

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.
Files changed (4) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +234 -0
  3. package/dist/index.js +2796 -0
  4. package/package.json +57 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 simonsmh (pi-provider-qoder, https://github.com/simonsmh/pi-provider-qoder)
4
+ Copyright (c) 2025 divingyu (pi-provider-qoder-cn, https://github.com/divingyu/pi-provider-qoder-cn)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,234 @@
1
+ # pi-provider-qoder-cn
2
+
3
+ A [pi](https://shittycodingagent.ai/) provider extension for **Qoder CN** (`qoder.com.cn`),
4
+ with a quota command and enterprise (VPC) endpoint support.
5
+
6
+ This is a focused fork of [`pi-provider-qoder`](https://github.com/simonsmh/pi-provider-qoder)
7
+ (MIT). It registers **only** the CN provider, so it can be installed alongside the
8
+ upstream package without a provider-id collision.
9
+
10
+ ```bash
11
+ pi install npm:pi-provider-qoder-cn
12
+ ```
13
+
14
+ ## What this fork adds
15
+
16
+ | Feature | Upstream | This fork |
17
+ |---|---|---|
18
+ | Qoder CN provider (`qoder-cn`) | ✅ | ✅ |
19
+ | Qoder Global provider (`qoder`) | ✅ | ➖ not registered (see below) |
20
+ | `/qoder-cn.usage` quota command | ❌ | ✅ |
21
+ | `/qoder-endpoint` enterprise (VPC) switching | ❌ | ✅ |
22
+ | Current CN model catalog (`qwen3.8-max` / `qwen3.8-flash`, …) | ❌ | ✅ |
23
+ | Stable CN model ids for `enabledModels` | ❌ | ✅ |
24
+
25
+ > **Why CN only?** Both packages would register a provider named `qoder-cn`, and
26
+ > pi identifies providers by id. Registering only `qoder-cn` here means this
27
+ > package and the upstream one can coexist. If both are installed, whichever is
28
+ > listed last in `settings.json` wins for `qoder-cn` — so put this package last
29
+ > to get the friendly ids and the quota command. Note that the upstream package
30
+ > registers the global `qoder` provider too, but it only appears in
31
+ > `--list-models` once global credentials exist.
32
+ >
33
+ > If you migrated from the upstream package, also remove the old local extension
34
+ > directory if you have one, since a directory at
35
+ > `~/.pi/agent/extensions/pi-provider-qoder/` registers `qoder-cn` as well.
36
+ > Check with `pi list` and inspect `~/.pi/agent/extensions/`.
37
+ >
38
+ > **Migrating from the upstream package:** model ids change from
39
+ > `Qwen3.8-Flash` to `qwen3.8-flash`. Update `enabledModels` entries in
40
+ > `settings.json` and any session pins accordingly. The old ids keep resolving
41
+ > internally, so only the configured names need updating.
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ pi install npm:pi-provider-qoder-cn
47
+ ```
48
+
49
+ Then authenticate once:
50
+
51
+ ```text
52
+ /login qoder-cn
53
+ ```
54
+
55
+ CN supports a Personal Access Token rather than browser OAuth. Create one at
56
+ <https://qoder.com.cn/account/integrations> and paste it when prompted, or export
57
+ it before starting pi:
58
+
59
+ ```bash
60
+ export QODERCN_PERSONAL_ACCESS_TOKEN="<your PAT>"
61
+ ```
62
+
63
+ ## Commands
64
+
65
+ ### `/qoder-cn.usage`
66
+
67
+ Shows the plan allowance and any purchased add-on credits.
68
+
69
+ ```text
70
+ Qoder CN Plan (personal_standard)
71
+ [--------------------] 0% used
72
+ [--------------------] Add-on quota: 0 credits / 700 credits used (0%) · 700 credits left
73
+ Resets: never
74
+ Manage: https://qoder.com.cn/account/usage
75
+ ```
76
+
77
+ Append `json` to print the untouched API payload — useful when a field you need
78
+ is not in the formatted view:
79
+
80
+ ```text
81
+ /qoder-cn.usage json
82
+ ```
83
+
84
+ Notes:
85
+
86
+ - The plan allowance (`Plan quota`) and top-up credits (`Add-on quota`) are
87
+ independent buckets with independent expiry, so both are listed when present.
88
+ - `Resets: never` means the API reported the year-9999 sentinel, i.e. the
89
+ allowance does not reset on a schedule.
90
+ - `(plan quota is prorated)` appears after a mid-cycle plan change.
91
+ - The command uses the same stored token as chat requests, refreshing it first,
92
+ so it reports the same quota the model is actually billed against.
93
+
94
+ ### `/qoder-endpoint`
95
+
96
+ Show or set the CN gateway. Enterprises on a private (VPC) deployment use a
97
+ per-tenant host instead of the public one.
98
+
99
+ ```text
100
+ /qoder-endpoint # show the active endpoint
101
+ /qoder-endpoint acme # enterprise instance "acme"
102
+ /qoder-endpoint acme-gateway.vpc.qoder.com.cn
103
+ /qoder-endpoint https://qoder.internal.example.com
104
+ /qoder-endpoint default # back to the public gateway
105
+ ```
106
+
107
+ A bare instance label `acme` expands to the standard enterprise hostnames:
108
+
109
+ | Role | Host |
110
+ |---|---|
111
+ | Gateway (chat) | `acme-gateway.vpc.qoder.com.cn` |
112
+ | OpenAPI (auth, quota) | `acme-openapi.vpc.qoder.com.cn` |
113
+ | Console | `acme.vpc.qoder.com.cn` |
114
+
115
+ Any other domain is treated as a custom deployment and serves every role from
116
+ that one origin.
117
+
118
+ Setting the endpoint also refreshes the model catalog, because an enterprise
119
+ instance may expose a different model set than the public gateway.
120
+
121
+ The choice is persisted to `~/.pi/agent/qoder-cn-settings.json`. Resolution order
122
+ at startup is:
123
+
124
+ 1. `QODER_VPC_ENDPOINT` / `QODERCN_VPC_ENDPOINT`
125
+ 2. `~/.pi/agent/qoder-cn-settings.json`
126
+ 3. `~/.pi/agent/auth.json` (the `qoder-cn` entry)
127
+ 4. `~/.qoder-cn/settings.json` (the Qoder IDE's own file)
128
+
129
+ > The token and the endpoint must belong to the same instance. Pointing an
130
+ > enterprise endpoint at a public-gateway token fails authentication.
131
+
132
+ ## Models
133
+
134
+ | Model | id | Context | Thinking effort |
135
+ |---|---|---|---|
136
+ | Auto | `auto` | 200K | — |
137
+ | Qwen 3.8-Max | `qwen3.8-max` | 1M | ✅ |
138
+ | Qwen 3.8-Flash | `qwen3.8-flash` | 1M | ✅ |
139
+ | Qwen 3.7-Max | `qwen3.7-max` | 1M | — |
140
+ | Qwen 3.7-Plus | `qwen3.7-plus` | 1M | — |
141
+ | Qwen 3.7-Flash | `qwen3.7-flash` | 1M | — |
142
+ | DeepSeek V4 Pro | `deepseek-v4-pro` | 1M | ✅ |
143
+ | DeepSeek V4 Flash | `deepseek-v4-flash` | 1M | ✅ |
144
+ | GLM-5.3 | `glm-5.3` | 1M | ✅ |
145
+ | GLM-5.3-Flash | `glm-5.3-flash` | 1M | ✅ |
146
+ | GLM 5.2 | `glm-5.2` | 1M | ✅ |
147
+ | Kimi-K3 | `kimi-k3` | 1M | ✅ |
148
+ | Kimi-K2.7-Code | `kimi-k2.7-code` | 256K | — |
149
+ | MiniMax M2.7 | `minimax-m2.7` | 200K | — |
150
+
151
+ ```bash
152
+ pi --provider qoder-cn --model qwen3.8-flash
153
+ ```
154
+
155
+ ```text
156
+ /model qwen3.8-flash
157
+ ```
158
+
159
+ The live catalog is fetched from Qoder and cached for an hour; the table above is
160
+ the offline fallback and the source of model ids.
161
+
162
+ **Ids are stable.** This fork uses lowercase slugs (`qwen3.8-flash`) rather than
163
+ the whitespace-stripped display name, so `enabledModels` entries such as
164
+ `qoder-cn/qwen3.8-flash` keep working across upgrades.
165
+
166
+ ## Development
167
+
168
+ ```bash
169
+ npm install
170
+ npm run check # tsc --noEmit
171
+ npm run lint # biome
172
+ npm test # vitest
173
+ npm run build # esbuild -> dist/index.js
174
+ ```
175
+
176
+ `src/` is TypeScript; `dist/index.js` is the build artifact that
177
+ `pi.extensions` points at. **`dist/` is committed on purpose.**
178
+
179
+ `pi install git:...` runs `npm install --omit=dev`, so devDependencies (esbuild)
180
+ are absent during install and an install-time `prepare` build would fail. The
181
+ committed bundle avoids that; `prepublishOnly` still rebuilds before every npm
182
+ publish, so the published bundle is always current. Run `npm run build` and
183
+ commit `dist/` whenever you change `src/`.
184
+
185
+ ## Publishing
186
+
187
+ The tarball ships `dist/`, `LICENSE`, `README.md` and `package.json` only, as
188
+ controlled by the `files` field.
189
+
190
+ ```bash
191
+ npm login # once, if not already authenticated
192
+ npm run check && npm run lint && npm test && npm run build
193
+ npm publish --access public
194
+ ```
195
+
196
+ `prepublishOnly` re-runs check, lint, test and build, so a broken build cannot
197
+ be published. Verify the tarball before pushing:
198
+
199
+ ```bash
200
+ npm pack --dry-run # confirm exactly 4 files
201
+ ```
202
+
203
+ The `pi-package` keyword makes the package eligible for the
204
+ [Pi package gallery](https://pi.dev/packages); no separate submission is needed.
205
+
206
+ ### Verify an install
207
+
208
+ ```bash
209
+ pi install npm:pi-provider-qoder-cn
210
+ pi --list-models | grep qoder-cn # expect 14 models, including auto
211
+ ```
212
+
213
+ Then in a session, `/qoder-cn.usage` should print the quota, and a prompt that
214
+ needs a tool (for example "run `echo hi` with bash") must execute it rather than
215
+ reply with a `<tool_call>` code block.
216
+
217
+ ## Compatibility
218
+
219
+ Requires pi >= 0.86. Pi hands providers a normalized transcript: the system
220
+ prompt and tool declarations live in transcript system messages and must be read
221
+ with `getCurrentSystemPrompt()` / `getCurrentTools()`. Reading the legacy
222
+ top-level `context.systemPrompt` / `context.tools` yields empty values, which
223
+ sends a request with no tools and makes the model emit tool calls as plain text
224
+ that never execute.
225
+
226
+ ## Credits
227
+
228
+ Forked from [`pi-provider-qoder`](https://github.com/simonsmh/pi-provider-qoder) by
229
+ [simonsmh](https://github.com/simonsmh), MIT licensed. The COSY request signing,
230
+ Qoder wire protocol, and provider scaffolding come from that project.
231
+
232
+ ## License
233
+
234
+ [MIT](./LICENSE)