pi-provider-kimi-code 0.6.12 → 0.6.14
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/CHANGELOG.md +21 -0
- package/README.md +25 -7
- package/index.ts +218 -170
- package/package.json +16 -13
- package/src/config.ts +33 -1
- package/src/constants.ts +86 -9
- package/src/errors.ts +31 -0
- package/src/models.ts +95 -13
- package/src/oauth.ts +60 -1
- package/src/payload.ts +266 -1
- package/src/schema-dedup.ts +8 -0
- package/src/settings-ui.ts +28 -0
- package/src/stream.ts +17 -3
- package/src/tools/common.ts +2 -3
- package/src/tools/datasource-catalog.ts +420 -0
- package/src/tools/datasource.ts +54 -68
- package/src/tools/moonshot.ts +7 -7
- package/src/usage.ts +116 -7
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.6.14] - 2026-11-15
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Upgraded `@earendil-works/pi-ai` / `pi-coding-agent` / `pi-tui` to `^1.5.0`. This resolves all npm audit findings (undici, minimatch, brace-expansion advisories) and picks up pi's streaming and rendering performance fixes.
|
|
8
|
+
- Tool parameter schemas (`moonshot_search`, `moonshot_fetch`, `kimi_datasource`) now use `@earendil-works/pi-schema` builders instead of TypeBox, following pi 1.5.0's migration. The generated JSON Schema is unchanged.
|
|
9
|
+
|
|
10
|
+
### Security
|
|
11
|
+
|
|
12
|
+
- Device-code login now rejects verification URLs that are not `http:`/`https:`, mirroring pi 1.5.0's fix for built-in OAuth providers. A malicious or buggy authorization server can no longer hand pi a `file:` or custom-scheme URL to open.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- The `/kimi-coding` settings dialog now reports pi as blocked on user input (OSC 7501 program status) while it is open, so supporting terminals show the correct waiting state.
|
|
17
|
+
- This changelog: pi 1.5.0 shows extension update notes on the next launch after an update.
|
|
18
|
+
- The `/kimi-settings` dialog now exposes **Keep thinking** (`model.thinkingKeep`: `default` / `all` / `last` / `none`), controlling the `thinking.keep` value sent to the Kimi API — i.e. how much reasoning history the server retains across turns. The wire and config plumbing already existed; this makes it adjustable without editing JSON.
|
|
19
|
+
- `kimi_datasource` now syncs its data-source catalog from the official plugin marketplace (`/coding/v1/plugins/marketplace`) with a lazy 24h disk cache (`~/.kimi-code/kimi-datasource-catalog.json`). The bundled snapshot moves from 12 to 35 sources (adds `china_*`, `who`/`fao`/`oecd`/`fred`, `chembl`/`pubchem`/`pdb`/`uniprot` and other science sources, `dongcai`/`cls`/`finance_research`), `data_source_name` is no longer a closed enum so server-side additions are never rejected by a stale client schema, and unknown names trigger one forced catalog refresh before being rejected with the current source list.
|
|
20
|
+
- Model discovery now prefers the unified `/models` schema (`limit.context`, `reasoning.type`/`reasoning.effort.valid`/`default`, `modalities.input`) that the official kimi-code client switched to in #4209, keeping the legacy flat fields (`context_length`, `supports_reasoning`, `think_efforts`, ...) as fallback while the server still sends both.
|
|
21
|
+
- Kimi's hard quota exhaustion (HTTP 429 with `exceeded_current_quota_error`) is now rewritten into actionable guidance — it is not a transient rate limit and retries will keep failing — pointing at `/kimi-settings` for usage, mirroring upstream kimi-code #4477/#4703. Plain transient 429s are untouched.
|
package/README.md
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/pi-provider-kimi-code)
|
|
4
4
|
[](./LICENSE)
|
|
5
5
|
|
|
6
|
-
> **Kimi Code extension for Pi — use K3, K2.
|
|
6
|
+
> **Kimi Code extension for Pi — use K3, K2.8 Code, and HighSpeed models with your Kimi Code Plan.**
|
|
7
|
+
>
|
|
8
|
+
> Why you need it: Pi v0.82.0+ ships a built-in `kimi-coding` provider for model discovery, reasoning controls, and OAuth login, but it does not provide this extension's Kimi Code integrations. Without this extension, Pi and the official `kimi-code` CLI log in separately (a login in one does not authenticate the other), large inline images blow up requests or fail because nothing uploads them through Kimi's Files API, Moonshot's server-side tools (`moonshot_search`, `moonshot_fetch`, `kimi_datasource`) are unavailable, Pi's tool schemas regularly exceed Moonshot's 15 KB per-tool limit and get rejected, and accounts on the wrong side of the mainland-cn / global split (kimi.com vs kimi.ai) fail with 401 because the built-in provider has no region switching. This extension closes those gaps — see [Why this exists](#why-this-exists) below for details.
|
|
7
9
|
|
|
8
10
|
## Why this exists
|
|
9
11
|
|
|
@@ -12,7 +14,8 @@ Use the built-in provider if you only want to chat with Kimi models. Install thi
|
|
|
12
14
|
- **Share a session with the official `kimi-code` CLI.** Reuse an existing `kimi-code` login, or sync Pi's OAuth login back to `kimi-code` so both CLIs stay authenticated.
|
|
13
15
|
- **Send files the Kimi way.** Large inline images go through Kimi's Files API and become `ms://` references instead of huge base64 payloads.
|
|
14
16
|
- **Use Kimi-native tools.** `moonshot_search`, `moonshot_fetch`, and `kimi_datasource` are opt-in tools that call Moonshot's server-side services.
|
|
15
|
-
- **
|
|
17
|
+
- **Meet Kimi's official schema requirements.** Moonshot's API rejects tool schemas over 15 KB — a limit that Pi's extension ecosystem regularly hits ([#16](https://github.com/Leechael/pi-provider-kimi-code/issues/16), [#21](https://github.com/Leechael/pi-provider-kimi-code/issues/21)). This extension adapts Pi's tool schemas to Kimi's requirements by automatically deduplicating them with `$ref`/`$defs` before sending, so subagents and other extensions don't break.
|
|
18
|
+
- **Switch regions.** Kimi runs two managed sides (`mainland-cn` on kimi.com, `global` on kimi.ai). The extension carries the region selection through API endpoints, OAuth, and `/login`, so a kimi.ai account no longer dies with a 401 against the default `.com` endpoints.
|
|
16
19
|
- **Embed in your own build.** The `KimiCode()` factory lets you ship Kimi Code support inside a custom Pi agent with programmatic config overrides — no file-based extension path needed.
|
|
17
20
|
|
|
18
21
|
## What this package adds
|
|
@@ -72,12 +75,25 @@ Pi's built-in `kimi-coding` provider already supports OAuth login via `/login`.
|
|
|
72
75
|
- **Syncs refreshed tokens back to `kimi-code`.** Pi stores credentials at `~/.pi/agent/auth.json`; this extension keeps the official CLI's credential file (`~/.kimi-code/credentials/kimi-code.json`) up to date so both stay authenticated.
|
|
73
76
|
- **Reuses existing `kimi-code` sessions.** If you already use the official CLI, the extension reads its session directly. Set `KIMI_CODE_HOME` if its home directory lives somewhere else.
|
|
74
77
|
- **Supports the legacy `~/.kimi` path.** Read-only. Set `KIMI_SHARE_DIR` to override it.
|
|
78
|
+
- **Follows your region.** Managed endpoints follow the selected region (`mainland-cn` default, `global` for kimi.ai accounts) for API, OAuth, and `/login`. See [Region selection](#region-selection).
|
|
75
79
|
- **`KIMI_API_KEY` fallback.** For CI or key-based access:
|
|
76
80
|
|
|
77
81
|
```bash
|
|
78
82
|
KIMI_API_KEY=sk-... pi
|
|
79
83
|
```
|
|
80
84
|
|
|
85
|
+
### Region selection
|
|
86
|
+
|
|
87
|
+
Kimi runs two managed sides: `api.kimi.com` / `auth.kimi.com` (mainland China, default) and `api.kimi.ai` / `auth.kimi.ai` (global). If your account lives on the kimi.ai side, a global OAuth session or API key against the default `.com` endpoints fails with 401.
|
|
88
|
+
|
|
89
|
+
Precedence, lowest to highest:
|
|
90
|
+
|
|
91
|
+
1. Built-in default (`mainland-cn`)
|
|
92
|
+
2. `KIMI_CODE_REGION` env var (`mainland-cn` or `global`)
|
|
93
|
+
3. `region` in merged home/project `config.json` (`"mainland-cn"` / `"global"` / `null` = auto; project overrides home); the **Region** row in `/kimi-settings` edits this config
|
|
94
|
+
|
|
95
|
+
`KIMI_CODE_BASE_URL` / `KIMI_CODE_OAUTH_HOST` overrides always win, and unknown values fall back to `mainland-cn`. `/login kimi-coding` follows the selected region end to end. See [docs/ENV.md](docs/ENV.md) for details.
|
|
96
|
+
|
|
81
97
|
## Models (legacy provider registration)
|
|
82
98
|
|
|
83
99
|
> **New users:** Use Pi's built-in `kimi-coding` provider for model discovery, reasoning controls, and OAuth login. This extension keeps its own model registration only for backward compatibility with existing sessions.
|
|
@@ -90,9 +106,9 @@ When this extension does register models, the official catalog determines what i
|
|
|
90
106
|
| `kimi-coding/kimi-for-coding-highspeed` | Kimi for Coding High Speed | Official catalog |
|
|
91
107
|
| `kimi-coding/k3` | Kimi K3 | Official catalog |
|
|
92
108
|
|
|
93
|
-
Kimi's official catalog at `https://api.kimi.com/coding/v1/models` is authoritative for model availability and context windows.
|
|
109
|
+
Kimi's official catalog at `https://api.kimi.com/coding/v1/models` is authoritative for model availability and context windows. Since the K2.8 Preview rollout (2026-09-11), the `kimi-for-coding` ID is upgraded in place — same model ID, new engine, no config change needed. K2.8 advertises up to 1M tokens of context across all membership tiers; the catalog reports the exact window for your account.
|
|
94
110
|
|
|
95
|
-
|
|
111
|
+
When discovery is unavailable, the extension uses the fallback models and defaults below (conservative pre-discovery values):
|
|
96
112
|
|
|
97
113
|
- Context window: `256k` tokens
|
|
98
114
|
- Max output: `32k` tokens
|
|
@@ -113,7 +129,7 @@ Inside Pi, run:
|
|
|
113
129
|
/kimi-settings
|
|
114
130
|
```
|
|
115
131
|
|
|
116
|
-
That command shows your signed-in account (via Kimi's `/me` endpoint), the current server-side model name (e.g. "K2.
|
|
132
|
+
That command shows your signed-in account (via Kimi's `/me` endpoint), the current server-side model name (e.g. "K2.8 Code High Speed"), your Kimi quota and Extra Usage balance, the effective region, and lets you edit the home or project config. Changes apply to the active session tool set.
|
|
117
133
|
|
|
118
134
|
Configurable settings include protocol mode, upload threshold, and per-tool enable/collapse.
|
|
119
135
|
|
|
@@ -137,6 +153,7 @@ Project config overrides home config with a deep merge. Missing files or missing
|
|
|
137
153
|
```json
|
|
138
154
|
{
|
|
139
155
|
"protocol": "openai",
|
|
156
|
+
"region": "global",
|
|
140
157
|
"uploads": { "thresholdBytes": 1048576 },
|
|
141
158
|
"tools": {
|
|
142
159
|
"moonshot_search": { "enabled": true, "default_collapsed": true },
|
|
@@ -184,6 +201,7 @@ Most users do not need environment variables. Two are worth knowing:
|
|
|
184
201
|
|
|
185
202
|
- `KIMI_API_KEY` — static API key for CI or key-based access.
|
|
186
203
|
- `KIMI_CODE_PROTOCOL` — `openai` by default; set to `anthropic` for Anthropic-compatible requests, or `responses` for the OpenAI Responses API.
|
|
204
|
+
- `KIMI_CODE_REGION` — `mainland-cn` (default) or `global`; selects the managed API/OAuth endpoints for kimi.com vs kimi.ai accounts.
|
|
187
205
|
|
|
188
206
|
Tools, protocol, and upload threshold are all configurable through `/kimi-settings` or JSON config files.
|
|
189
207
|
|
|
@@ -219,7 +237,7 @@ The login flow always prints a verification URL. Copy it into a browser manually
|
|
|
219
237
|
|
|
220
238
|
### "Access denied" or subscription errors after a successful login
|
|
221
239
|
|
|
222
|
-
Your Moonshot account needs an active Kimi Code Plan. If the same account works in `kimi-code`, re-run `/login kimi-coding` to refresh credentials.
|
|
240
|
+
Your Moonshot account needs an active Kimi Code Plan. If the same account works in `kimi-code`, re-run `/login kimi-coding` to refresh credentials. A 401 right after login can also mean a region mismatch — accounts registered on the kimi.ai side must run with `KIMI_CODE_REGION=global` (or the matching `region` config / `/kimi-settings` row).
|
|
223
241
|
|
|
224
242
|
### Tools do not show up or return errors
|
|
225
243
|
|
|
@@ -227,7 +245,7 @@ Run `/kimi-settings` and check whether the tool is enabled in the home or projec
|
|
|
227
245
|
|
|
228
246
|
### Large images fail with a payload error
|
|
229
247
|
|
|
230
|
-
This extension uploads images over `KIMI_CODE_UPLOAD_THRESHOLD_BYTES` (default 1 MB) to Kimi's Files API and references them as `ms://`. Set `KIMI_CODE_DEBUG=1` to see upload decisions in the provider logs.
|
|
248
|
+
This extension uploads images over `KIMI_CODE_UPLOAD_THRESHOLD_BYTES` (default 1 MB) to Kimi's Files API and references them as `ms://`. Independently of that, a per-request inline media budget (~20 MB of base64 on the wire) drops oversized inline images and videos from the payload and leaves a media-kind-specific placeholder, such as `[image omitted: dropped to fit the request media budget]` or `[video omitted: dropped to fit the request media budget]`, so the model knows content was removed. Set `KIMI_CODE_DEBUG=1` to see upload and budget decisions in the provider logs.
|
|
231
249
|
|
|
232
250
|
### Prompt cache never seems to hit
|
|
233
251
|
|
package/index.ts
CHANGED
|
@@ -46,8 +46,11 @@ import {
|
|
|
46
46
|
KIMI_WIRE_PROTOCOLS,
|
|
47
47
|
PROVIDER_ID,
|
|
48
48
|
PROVIDER_VERSION,
|
|
49
|
+
type KimiRegion,
|
|
50
|
+
applyKimiRegionEnvBridge,
|
|
49
51
|
getBaseUrl,
|
|
50
52
|
getKimiApiType,
|
|
53
|
+
setKimiRegionOverride,
|
|
51
54
|
} from "./src/constants.ts";
|
|
52
55
|
import {
|
|
53
56
|
type KimiOAuthCredentials,
|
|
@@ -74,6 +77,7 @@ import {
|
|
|
74
77
|
type KimiConfigScope,
|
|
75
78
|
buildSettingsTheme,
|
|
76
79
|
formatByteSize,
|
|
80
|
+
formatRegionValue,
|
|
77
81
|
formatScopeDescription,
|
|
78
82
|
parseByteSizeInput,
|
|
79
83
|
} from "./src/settings-ui.ts";
|
|
@@ -139,6 +143,12 @@ function reloadEffectiveKimiRuntimeConfig(
|
|
|
139
143
|
state.cwd = cwd;
|
|
140
144
|
state.config = config;
|
|
141
145
|
state.projectTrusted = projectTrusted;
|
|
146
|
+
// Push the effective region (project/home JSON wins over the env capture;
|
|
147
|
+
// env KIMI_CODE_REGION already sits in the merged config via the env layer)
|
|
148
|
+
// and re-bridge pi core's OAuth host so /login follows settings changes
|
|
149
|
+
// without a restart.
|
|
150
|
+
setKimiRegionOverride(config.region);
|
|
151
|
+
applyKimiRegionEnvBridge();
|
|
142
152
|
setStoreResolvedKimiConfig({
|
|
143
153
|
model: resolveKimiModelConfig(
|
|
144
154
|
config.model,
|
|
@@ -214,190 +224,225 @@ async function openSettingsMenu(
|
|
|
214
224
|
let scope: KimiConfigScope = projectTrusted ? "project" : "home";
|
|
215
225
|
let dirty = false;
|
|
216
226
|
|
|
217
|
-
await ctx.ui.custom<void>(
|
|
218
|
-
|
|
227
|
+
await ctx.ui.custom<void>(
|
|
228
|
+
(tui, theme, _keybindings, done) => {
|
|
229
|
+
const settingsTheme = buildSettingsTheme(theme);
|
|
219
230
|
|
|
220
|
-
|
|
231
|
+
let list: SettingsList;
|
|
221
232
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const formatToolMenuValue = (toolName: KimiToolName) => {
|
|
229
|
-
const tool = drafts[scope].tools[toolName];
|
|
230
|
-
if (!tool.enabled) return "disabled";
|
|
231
|
-
return tool.default_collapsed ? "enabled without preview" : "enabled with preview";
|
|
232
|
-
};
|
|
233
|
+
const toolLabel = (toolName: KimiToolName) => {
|
|
234
|
+
if (toolName === "moonshot_search") return "Search tool";
|
|
235
|
+
if (toolName === "moonshot_fetch") return "Fetch tool";
|
|
236
|
+
return "Real-world data API";
|
|
237
|
+
};
|
|
233
238
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
list.updateValue("protocol", drafts[scope].protocol);
|
|
240
|
-
list.updateValue("uploadThreshold", formatByteSize(drafts[scope].uploads.thresholdBytes));
|
|
241
|
-
};
|
|
239
|
+
const formatToolMenuValue = (toolName: KimiToolName) => {
|
|
240
|
+
const tool = drafts[scope].tools[toolName];
|
|
241
|
+
if (!tool.enabled) return "disabled";
|
|
242
|
+
return tool.default_collapsed ? "enabled without preview" : "enabled with preview";
|
|
243
|
+
};
|
|
242
244
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
const onChange = (id: string, newValue: string) => {
|
|
261
|
-
if (id === "scope") {
|
|
262
|
-
scope = newValue as KimiConfigScope;
|
|
263
|
-
refreshDisplays();
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
if (id === "protocol") {
|
|
267
|
-
drafts[scope].protocol = newValue as KimiCodeConfig["protocol"];
|
|
268
|
-
list.updateValue(id, newValue);
|
|
269
|
-
save();
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
if (id === "uploadThreshold") {
|
|
273
|
-
const bytes = parseByteSizeInput(newValue);
|
|
274
|
-
if (bytes === undefined || bytes <= 0) {
|
|
275
|
-
ctx.ui.notify("Upload threshold must be a positive size, for example 2 MiB", "error");
|
|
245
|
+
const refreshDisplays = () => {
|
|
246
|
+
scopeItem.description = formatScopeDescription(scope, ctx.cwd);
|
|
247
|
+
for (const toolName of KIMI_TOOL_NAMES) {
|
|
248
|
+
list.updateValue(toolName, formatToolMenuValue(toolName));
|
|
249
|
+
}
|
|
250
|
+
list.updateValue("protocol", drafts[scope].protocol);
|
|
251
|
+
list.updateValue("region", formatRegionValue(drafts[scope].region));
|
|
252
|
+
list.updateValue("uploadThreshold", formatByteSize(drafts[scope].uploads.thresholdBytes));
|
|
253
|
+
list.updateValue("thinkingKeep", drafts[scope].model.thinkingKeep ?? "default");
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const save = () => {
|
|
257
|
+
if (scope === "project" && !projectTrusted) {
|
|
258
|
+
ctx.ui.notify("Project config cannot be saved until the project is trusted.", "warning");
|
|
276
259
|
return;
|
|
277
260
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
if (field === "enabled") {
|
|
288
|
-
drafts[scope].tools[toolName].enabled = newValue === "true";
|
|
289
|
-
} else {
|
|
290
|
-
drafts[scope].tools[toolName].default_collapsed = newValue !== "true";
|
|
261
|
+
try {
|
|
262
|
+
saveScopeKimiCodeConfig(scope, ctx.cwd, drafts[scope]);
|
|
263
|
+
applyEffectiveKimiRuntimeConfig(pi, state, ctx.cwd, {
|
|
264
|
+
updateActiveTools: true,
|
|
265
|
+
projectTrusted: scope === "project" ? true : projectTrusted,
|
|
266
|
+
});
|
|
267
|
+
dirty = true;
|
|
268
|
+
} catch (error: unknown) {
|
|
269
|
+
ctx.ui.notify((error as Error).message, "error");
|
|
291
270
|
}
|
|
292
|
-
|
|
293
|
-
save();
|
|
294
|
-
}
|
|
295
|
-
};
|
|
296
|
-
|
|
297
|
-
const scopeItem: SettingItem = {
|
|
298
|
-
id: "scope",
|
|
299
|
-
label: "Config scope",
|
|
300
|
-
description: projectTrusted
|
|
301
|
-
? formatScopeDescription(scope, ctx.cwd)
|
|
302
|
-
: "Project config disabled until the project is trusted; editing home config only",
|
|
303
|
-
currentValue: scope,
|
|
304
|
-
values: projectTrusted ? ["project", "home"] : ["home"],
|
|
305
|
-
};
|
|
271
|
+
};
|
|
306
272
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
description: `Show ${toolName} result previews by default`,
|
|
328
|
-
currentValue: String(!drafts[scope].tools[toolName].default_collapsed),
|
|
329
|
-
values: ["true", "false"],
|
|
330
|
-
},
|
|
331
|
-
],
|
|
332
|
-
2,
|
|
333
|
-
settingsTheme,
|
|
334
|
-
onChange,
|
|
335
|
-
() => submenuDone(),
|
|
336
|
-
),
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
items.push({
|
|
340
|
-
id: "protocol",
|
|
341
|
-
label: "Protocol",
|
|
342
|
-
description: "API protocol for Kimi requests",
|
|
343
|
-
currentValue: drafts[scope].protocol,
|
|
344
|
-
values: ["openai", "anthropic", "responses"],
|
|
345
|
-
});
|
|
346
|
-
items.push({
|
|
347
|
-
id: "uploadThreshold",
|
|
348
|
-
label: "Upload threshold",
|
|
349
|
-
description: "Max size for inline file uploads",
|
|
350
|
-
currentValue: formatByteSize(drafts[scope].uploads.thresholdBytes),
|
|
351
|
-
submenu: (_current, submenuDone) => {
|
|
352
|
-
const input = new Input();
|
|
353
|
-
input.setValue(formatByteSize(drafts[scope].uploads.thresholdBytes));
|
|
354
|
-
input.onSubmit = (value) => {
|
|
355
|
-
const bytes = parseByteSizeInput(value);
|
|
273
|
+
const onChange = (id: string, newValue: string) => {
|
|
274
|
+
if (id === "scope") {
|
|
275
|
+
scope = newValue as KimiConfigScope;
|
|
276
|
+
refreshDisplays();
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (id === "protocol") {
|
|
280
|
+
drafts[scope].protocol = newValue as KimiCodeConfig["protocol"];
|
|
281
|
+
list.updateValue(id, newValue);
|
|
282
|
+
save();
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
if (id === "region") {
|
|
286
|
+
drafts[scope].region = newValue === "auto" ? null : (newValue as KimiRegion);
|
|
287
|
+
list.updateValue(id, newValue);
|
|
288
|
+
save();
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (id === "uploadThreshold") {
|
|
292
|
+
const bytes = parseByteSizeInput(newValue);
|
|
356
293
|
if (bytes === undefined || bytes <= 0) {
|
|
357
294
|
ctx.ui.notify("Upload threshold must be a positive size, for example 2 MiB", "error");
|
|
358
|
-
submenuDone();
|
|
359
295
|
return;
|
|
360
296
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
297
|
+
drafts[scope].uploads.thresholdBytes = bytes;
|
|
298
|
+
list.updateValue(id, formatByteSize(bytes));
|
|
299
|
+
save();
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
if (id === "thinkingKeep") {
|
|
303
|
+
drafts[scope].model.thinkingKeep =
|
|
304
|
+
newValue === "default" ? null : (newValue as KimiCodeConfig["model"]["thinkingKeep"]);
|
|
305
|
+
list.updateValue(id, newValue);
|
|
306
|
+
save();
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const toolMatch = /^(?<tool>.+):(?<field>enabled|collapsed)$/.exec(id);
|
|
310
|
+
if (toolMatch?.groups) {
|
|
311
|
+
const toolName = toolMatch.groups.tool as KimiToolName;
|
|
312
|
+
const field = toolMatch.groups.field as "enabled" | "collapsed";
|
|
313
|
+
if (field === "enabled") {
|
|
314
|
+
drafts[scope].tools[toolName].enabled = newValue === "true";
|
|
315
|
+
} else {
|
|
316
|
+
drafts[scope].tools[toolName].default_collapsed = newValue !== "true";
|
|
317
|
+
}
|
|
318
|
+
list.updateValue(toolName, formatToolMenuValue(toolName));
|
|
319
|
+
save();
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const scopeItem: SettingItem = {
|
|
324
|
+
id: "scope",
|
|
325
|
+
label: "Config scope",
|
|
326
|
+
description: projectTrusted
|
|
327
|
+
? formatScopeDescription(scope, ctx.cwd)
|
|
328
|
+
: "Project config disabled until the project is trusted; editing home config only",
|
|
329
|
+
currentValue: scope,
|
|
330
|
+
values: projectTrusted ? ["project", "home"] : ["home"],
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
const items: SettingItem[] = [scopeItem];
|
|
334
|
+
for (const toolName of KIMI_TOOL_NAMES) {
|
|
335
|
+
items.push({
|
|
336
|
+
id: toolName,
|
|
337
|
+
label: toolLabel(toolName),
|
|
338
|
+
description: `Configure ${toolName} registration and preview defaults`,
|
|
339
|
+
currentValue: formatToolMenuValue(toolName),
|
|
340
|
+
submenu: (_current, submenuDone) =>
|
|
341
|
+
new SettingsList(
|
|
342
|
+
[
|
|
343
|
+
{
|
|
344
|
+
id: `${toolName}:enabled`,
|
|
345
|
+
label: "Enabled",
|
|
346
|
+
description: `Register ${toolName} at session start`,
|
|
347
|
+
currentValue: String(drafts[scope].tools[toolName].enabled),
|
|
348
|
+
values: ["true", "false"],
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
id: `${toolName}:collapsed`,
|
|
352
|
+
label: "Show preview",
|
|
353
|
+
description: `Show ${toolName} result previews by default`,
|
|
354
|
+
currentValue: String(!drafts[scope].tools[toolName].default_collapsed),
|
|
355
|
+
values: ["true", "false"],
|
|
356
|
+
},
|
|
357
|
+
],
|
|
358
|
+
2,
|
|
359
|
+
settingsTheme,
|
|
360
|
+
onChange,
|
|
361
|
+
() => submenuDone(),
|
|
362
|
+
),
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
items.push({
|
|
366
|
+
id: "protocol",
|
|
367
|
+
label: "Protocol",
|
|
368
|
+
description: "API protocol for Kimi requests",
|
|
369
|
+
currentValue: drafts[scope].protocol,
|
|
370
|
+
values: ["openai", "anthropic", "responses"],
|
|
371
|
+
});
|
|
372
|
+
items.push({
|
|
373
|
+
id: "region",
|
|
374
|
+
label: "Region",
|
|
375
|
+
description: "Managed deployment region (auto follows KIMI_CODE_REGION / default)",
|
|
376
|
+
currentValue: formatRegionValue(drafts[scope].region),
|
|
377
|
+
values: ["auto", "mainland-cn", "global"],
|
|
378
|
+
});
|
|
379
|
+
items.push({
|
|
380
|
+
id: "thinkingKeep",
|
|
381
|
+
label: "Keep thinking",
|
|
382
|
+
description:
|
|
383
|
+
"thinking.keep sent to the Kimi API: how much reasoning history the server should retain across turns",
|
|
384
|
+
currentValue: drafts[scope].model.thinkingKeep ?? "default",
|
|
385
|
+
values: ["default", "all", "last", "none"],
|
|
386
|
+
});
|
|
387
|
+
items.push({
|
|
388
|
+
id: "uploadThreshold",
|
|
389
|
+
label: "Upload threshold",
|
|
390
|
+
description: "Max size for inline file uploads",
|
|
391
|
+
currentValue: formatByteSize(drafts[scope].uploads.thresholdBytes),
|
|
392
|
+
submenu: (_current, submenuDone) => {
|
|
393
|
+
const input = new Input();
|
|
394
|
+
input.setValue(formatByteSize(drafts[scope].uploads.thresholdBytes));
|
|
395
|
+
input.onSubmit = (value) => {
|
|
396
|
+
const bytes = parseByteSizeInput(value);
|
|
397
|
+
if (bytes === undefined || bytes <= 0) {
|
|
398
|
+
ctx.ui.notify("Upload threshold must be a positive size, for example 2 MiB", "error");
|
|
399
|
+
submenuDone();
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
submenuDone(formatByteSize(bytes));
|
|
403
|
+
};
|
|
404
|
+
input.onEscape = () => submenuDone();
|
|
405
|
+
return input;
|
|
406
|
+
},
|
|
407
|
+
});
|
|
367
408
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
409
|
+
list = new SettingsList(items, items.length, settingsTheme, onChange, () => done(), {
|
|
410
|
+
enableSearch: true,
|
|
411
|
+
});
|
|
371
412
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
413
|
+
return {
|
|
414
|
+
items,
|
|
415
|
+
onChange,
|
|
416
|
+
render(width: number) {
|
|
417
|
+
const usageLines = usage.split("\n").map((line) => truncateToWidth(` ${line}`, width));
|
|
418
|
+
return [
|
|
419
|
+
truncateToWidth(
|
|
420
|
+
theme.fg("accent", theme.bold(`Kimi settings (provider v${PROVIDER_VERSION})`)),
|
|
421
|
+
width,
|
|
422
|
+
),
|
|
423
|
+
"",
|
|
424
|
+
truncateToWidth(theme.fg("accent", theme.bold("Kimi account")), width),
|
|
425
|
+
truncateToWidth(` ${account}`, width),
|
|
426
|
+
"",
|
|
427
|
+
truncateToWidth(theme.fg("accent", theme.bold("Kimi usage")), width),
|
|
428
|
+
...usageLines,
|
|
429
|
+
"",
|
|
430
|
+
...list.render(width),
|
|
431
|
+
];
|
|
432
|
+
},
|
|
433
|
+
handleInput(data: string) {
|
|
434
|
+
list.handleInput?.(data);
|
|
435
|
+
tui.requestRender();
|
|
436
|
+
},
|
|
437
|
+
invalidate() {
|
|
438
|
+
list.invalidate();
|
|
439
|
+
},
|
|
440
|
+
};
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
blocked: { kind: "question", message: "Kimi settings" },
|
|
444
|
+
},
|
|
445
|
+
);
|
|
401
446
|
|
|
402
447
|
if (dirty) await ctx.reload();
|
|
403
448
|
}
|
|
@@ -654,6 +699,9 @@ function startModelDiscovery(pi: ExtensionAPI, state: KimiRuntimeState): void {
|
|
|
654
699
|
|
|
655
700
|
export function KimiCode(overrides?: KimiCodeConfigPatch): ExtensionFactory {
|
|
656
701
|
return async (pi: ExtensionAPI) => {
|
|
702
|
+
// Region handling (setKimiRegionOverride + the OAuth host bridge) happens
|
|
703
|
+
// in reloadEffectiveKimiRuntimeConfig, which runs just below and on every
|
|
704
|
+
// /kimi-settings save.
|
|
657
705
|
const cwd = process.cwd();
|
|
658
706
|
const config = loadKimiCodeConfig(
|
|
659
707
|
{ cwd, home: os.homedir(), includeProject: false },
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-provider-kimi-code",
|
|
3
|
-
"version": "0.6.
|
|
4
|
-
"description": "Kimi Code models (K3, K2.
|
|
3
|
+
"version": "0.6.14",
|
|
4
|
+
"description": "Kimi Code models (K3, K2.8, HighSpeed) in Pi: OAuth shared login with kimi-code CLI, file uploads, and Kimi-native tools",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-provider",
|
|
7
7
|
"coding-agent",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"kimi-k2.5",
|
|
16
16
|
"kimi-k2.6",
|
|
17
17
|
"kimi-k2.7",
|
|
18
|
+
"kimi-k2.8",
|
|
18
19
|
"kimi-k3",
|
|
19
20
|
"llm",
|
|
20
21
|
"llm-provider",
|
|
@@ -40,7 +41,8 @@
|
|
|
40
41
|
"index.ts",
|
|
41
42
|
"src",
|
|
42
43
|
"package.json",
|
|
43
|
-
"README.md"
|
|
44
|
+
"README.md",
|
|
45
|
+
"CHANGELOG.md"
|
|
44
46
|
],
|
|
45
47
|
"type": "module",
|
|
46
48
|
"scripts": {
|
|
@@ -54,23 +56,24 @@
|
|
|
54
56
|
"pre-commit": "prek run"
|
|
55
57
|
},
|
|
56
58
|
"dependencies": {
|
|
59
|
+
"@earendil-works/pi-schema": "^1.5.0",
|
|
57
60
|
"proper-lockfile": "^4.1.2"
|
|
58
61
|
},
|
|
59
62
|
"devDependencies": {
|
|
60
|
-
"@earendil-works/pi-ai": "^
|
|
61
|
-
"@earendil-works/pi-coding-agent": "^
|
|
62
|
-
"@earendil-works/pi-tui": "^
|
|
63
|
-
"@j178/prek": "^0.5.
|
|
64
|
-
"@types/node": "^24.
|
|
63
|
+
"@earendil-works/pi-ai": "^1.5.0",
|
|
64
|
+
"@earendil-works/pi-coding-agent": "^1.5.0",
|
|
65
|
+
"@earendil-works/pi-tui": "^1.5.0",
|
|
66
|
+
"@j178/prek": "^0.5.10",
|
|
67
|
+
"@types/node": "^24.19.2",
|
|
65
68
|
"@types/proper-lockfile": "^4.1.4",
|
|
66
|
-
"oxfmt": "^0.
|
|
67
|
-
"oxlint": "^1.
|
|
69
|
+
"oxfmt": "^0.77.0",
|
|
70
|
+
"oxlint": "^1.92.0",
|
|
68
71
|
"typescript": "^5.9.0"
|
|
69
72
|
},
|
|
70
73
|
"peerDependencies": {
|
|
71
|
-
"@earendil-works/pi-ai": "
|
|
72
|
-
"@earendil-works/pi-coding-agent": "
|
|
73
|
-
"@earendil-works/pi-tui": "
|
|
74
|
+
"@earendil-works/pi-ai": ">=1.5.0",
|
|
75
|
+
"@earendil-works/pi-coding-agent": ">=1.5.0",
|
|
76
|
+
"@earendil-works/pi-tui": ">=1.5.0"
|
|
74
77
|
},
|
|
75
78
|
"pi": {
|
|
76
79
|
"extensions": [
|