# Changelog

## 1.4.2 — 2026-10-28

- Retry a failed Kimi request up to five times instead of two ([#5](https://github.com/BaronCyrus/dsh-kimi-subscription/issues/5)). Kimi answers an overloaded engine with HTTP 429 and `The engine is currently overloaded, please try again later`, which the host retries as a rate limit. With two retries on the host's default backoff, 0.5 s and then 1 s, a request gave up about 1.5 s after the first refusal, so a short overload ended the turn. Five is the host's own default: the waits double from 0.5 s to 8 s, 15.5 s in all, before the original error is shown. The backoff itself is unchanged.
- The limit covers all six retryable codes. A token that expired in flight still recovers on the first retry, but genuinely dead credentials can take up to 14 s longer to report, and a Kimi overload that outlasts the retries still ends the turn. Kimi's own retry hint, if it sends one, does not reach the host: DSH's pi-ai adapter never passes it on.
- Verified offline: all 121 tests pass. A test sends Kimi's 429 overload reply through the real host adapter: pi-ai sends the request once, with no retries of its own, and the failure arrives as `RATE_LIMIT`, which the policy retries, not as an exhausted quota. The retry tests drive the host's real retry executor with the registered policy: each of the six codes is retried five times, after 0.5, 1, 2, 4, and 8 s, and the sixth failure surfaces unchanged. No live model calls and no credential reads.

## 1.4.1 — 2026-10-28

- Calibrate the model list against Kimi's documentation: the [Kimi Code model page](https://www.kimi.com/code/docs/kimi-code/models.html), which gives the IDs this route takes, and the Open Platform [pricing page](https://platform.kimi.com/docs/pricing/chat). The six IDs, their order, and their context windows already matched the Kimi Code page. `kimi-for-coding-highspeed` did not, and a test now pins the whole list.
- `kimi-for-coding-highspeed` is now named **Kimi K2.7 Code Highspeed**, the model version both pages give it. pi-ai's catalog calls it "Kimi For Coding HighSpeed".
- Fix `kimi-for-coding-highspeed` being served as K2.8 Preview without thinking. K2.7 Code Highspeed always thinks and takes no effort level, but pi-ai's catalog gives it no thinking map. With no level chosen, pi-ai therefore sent `"thinking": {"type": "disabled"}`, and Kimi serves a request that disables thinking with K2.8 Preview without thinking. Off did the same, and Minimal through High sent an effort this model does not adjust. The model now offers no effort level (`reasoning: false`, with every level still unmapped): the model picker shows no Effort row for it, and the request carries no thinking field, so Kimi applies the model's own setting and the model still thinks.
- An earlier version of this fix, on `main` after 1.4.0 and never released, marked every level unsupported but still declared that the model takes an effort level. The host adapter then described it with an empty effort list, which DSH's model validator rejects with `INVALID_MODEL_REASONING`, so the model picker showed no Kimi model at all ([#3](https://github.com/BaronCyrus/dsh-kimi-subscription/issues/3)). [@jfb112697](https://github.com/jfb112697) fixed it in [#4](https://github.com/BaronCyrus/dsh-kimi-subscription/pull/4).
- A conversation that picked a level for this model before now fails with `does not support reasoning effort` before any request leaves. The model picker has no Effort row for this model, so pick another model and then K2.7 Code Highspeed again: picking a model in the list sends no effort level.
- The pricing page lists the Open Platform's IDs, `kimi-k3.1-pro`, `kimi-k3.1-pro-highspeed`, `kimi-k3`, `kimi-k2.7-code`, `kimi-k2.7-code-highspeed`, and `kimi-k2.6`, with per-token prices in CNY. The plugin adopts none of them. Kimi Code serves an ID outside its model table with K2.8 Preview without thinking and meters by plan quota, and DSH never reads a model's cost. The page's K2 notice, closed to newly registered Open Platform users from 2026-10-31 and offline at the end of December, is about the Open Platform; the Kimi Code page still lists `kimi-for-coding-highspeed`.
- Kimi's model page gives `high` as the default effort for K3.1 Pro and the K3 series, and `max` for K2.8 Preview. The 1.4.0 notes and both guides said `max` for K3.1 Pro; the guides now say `high`. Requests do not change: with no level chosen they carry no thinking field, and Kimi applies its default.
- Verified offline: all 120 tests pass. A new test registers the host adapter with DSH's own `LlmRuntime` from `@deepseek-ai/dsh-llm` 0.2.1-rc.3 and resolves every listed model through it, the validation the model picker depends on. All six models pass with these names and context windows, `low` / `high` / `max` for the first five, and no effort level for `kimi-for-coding-highspeed`; the same check on the built Host bundle gives the same result. The test fails on the earlier version of this fix with `INVALID_MODEL_REASONING`. This entry first said the six models had been checked through the real host adapter, but that check read only the adapter's own description, an empty effort list for `kimi-for-coding-highspeed`, and never ran DSH's validator, which rejects it. `kimi-for-coding-highspeed`'s request goes to `https://api.kimi.com/coding/v1/messages` with no thinking field; on 1.4.0 the same request carried `"thinking": {"type": "disabled"}`. Desktop was not restarted. No live model calls and no credential reads.
- Add a test that a Kimi request sent through the real host adapter carries the system prompt and the tools. It fails on the previous development baseline, where every request lost both.
- Move the development baseline to the host packages DeepSeek Harness.app 0.2.1-rc.3 ships, read from the app bundle: `@deepseek-ai/dsh-*` 0.2.1-rc.3, Cordis 4.0.5, cordis-plugin-loader 1.0.6, cordis-plugin-include 1.0.10, schemastery 3.18.5, and pi-ai 1.1.0. As in the app, the llm-pi-ai adapter and the plugin now load one pi-ai copy, and a contract test keeps them on it.
- The previous baseline gave the 0.2.0-rc.1 adapter pi-ai 0.85.1, from its own `^0.85.1`, and the plugin pi-ai 0.87.1. pi-ai 0.87.1 expects the system prompt and tools folded into the transcript, and 0.85.1 hands them over unfolded, so both were dropped without an error. The offline suite had run that pairing since 1.3.2, and no test looked at what a request carried. A clean install on DeepSeek Harness.app 0.2.1-rc.3 is not affected: DSH gives the plugin the app's only pi-ai, the same copy its adapter uses.
- A desktop profile whose installed plugin still carries a `node_modules` copied from a local-path install runs the broken pairing: Kimi sees no tools and ends every turn after one reply. Uninstall and reinstall the plugin on the Plugins page, or delete that nested `node_modules`, then quit and reopen DSH. On the maintainer's desktop, the first session afterwards had `k3.1-pro-highspeed` call bash, glob, grep, and read.
- The baseline move changes no published plugin code. `@deepseek-ai/dsh-invariants` leaves the development dependencies: no 0.2.1 package depends on it, and the app does not ship it.

## 1.4.0 — 2026-10-24

- Add Kimi Code's new models **Kimi K3.1 Pro** (`k3.1-pro`) and **Kimi K3.1 Pro Highspeed** (`k3.1-pro-highspeed`) to the Kimi subscription group, ahead of `k3` as on Kimi's model page. No pi-ai release lists them yet, up to and including pi-ai 1.4.0, so the plugin adds them until the upstream catalog catches up, as it already patches K2.8 Preview. A model pi-ai does list is kept as pi-ai ships it.
- The entries follow the [Kimi Code model documentation](https://www.kimi.com/code/docs/kimi-code/models.html): the exact IDs (Kimi answers a mistyped ID with K2.8 Preview without thinking), a 1M context window, and `low` / `high` / `max` thinking. Thinking cannot be turned off on these models, and Kimi rejects a request that disables it with HTTP 400, so the model picker offers no Off level. With no level chosen, the request carries no thinking field and Kimi applies the model default, `max`. The wire protocol, endpoint, and output limit come from the installed catalog's `k3` entry, which every accepted pi-ai version ships with the same Anthropic-compatible settings. The cost field is zero: Kimi Code meters these models by plan quota, and DSH never reads it.
- A plan rejection for either model names the whole ID, for example 「k3.1-pro-highspeed」, and still suggests `kimi-for-coding`. Which plans include each model, and the 1M context, is listed in Kimi's documentation.
- Both READMEs end with a Support the author section holding the maintainer's WeChat and Alipay tip codes, the same images as the PackyCode and Aha Tutor plugins. The package ships both images so the README renders them wherever the package is read, and a release check keeps every local README image in the published files.
- Verified offline: all 114 tests pass on the 0.2.0-rc.1 development baseline with pi-ai 0.87.1. The real host adapter lists both models with their names, a 1M context, and exactly the Low, High, and Max efforts. The request pi-ai builds for `k3.1-pro` names that model and goes to `https://api.kimi.com/coding/v1/messages`, with adaptive thinking and the chosen effort, or with no thinking field when no level is chosen. The same request check passes on pi-ai 1.1.0, the version inside DeepSeek Harness.app 0.2.1-rc.2, and that app's `@deepseek-ai/dsh-llm-pi-ai` 0.2.1-rc.2 derives the offered efforts with the same code as the baseline. Desktop was not restarted. No live model calls and no credential reads.

## 1.3.10 — 2026-10-17

- Fix the update button bypassing pnpm's release-age policy. It ran `pnpm add --save-exact --config.minimumReleaseAge=0 dsh-kimi-subscription@<version>`, which switched the policy off for that one install, so pnpm never recorded the young version as an exception. pnpm 11 checks the profile's lockfile against the policy on every later install, so the next plugin install in that profile failed with `ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION` on the Kimi entry until the version was 24 hours old. PackyCode's update button caused the same failure and dropped the override in its 1.3.3.
- The button now installs the exact version under the profile's own policy. By default pnpm installs it at once and adds `dsh-kimi-subscription@<version>` to the profile's `minimumReleaseAgeExclude`, and later installs pass. Under a stricter policy, an explicit `minimumReleaseAge` or `minimumReleaseAgeStrict: true`, pnpm refuses with `ERR_PNPM_NO_MATURE_MATCHING_VERSION` and exits 1. The update then answers pending, with the time pnpm will accept the version, and the settings card says when to update instead of reporting a failure. The 1.3.1 entry's claim that pnpm ≥ 11 quietly keeps the installed version without the override does not hold for an exact version: pnpm either installs it or refuses.
- Update buttons already shipped, 1.3.9 and earlier, keep the override. Updating with one of them to 1.3.10 within its first 24 hours still installs past the policy, and that profile then refuses every plugin install, including the next update, until 1.3.10 is 24 hours old.
- Verified with DSH's bundled pnpm 11.28.5 in scratch DSH homes, running the plugin's own `update()` from 1.3.8 to 1.3.9 while 1.3.9 was under 20 minutes old. Under the default policy it installed 1.3.9, pnpm added `dsh-kimi-subscription@1.3.9` to `minimumReleaseAgeExclude`, and an unrelated install afterwards passed. Under `minimumReleaseAge: 1440`, and under `minimumReleaseAgeStrict: true`, it installed nothing and returned pending until 2026-10-18T10:35Z. The old override reproduced the failure: after it installed 1.3.9, an unrelated `pnpm add` failed with `ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION`. All 109 offline tests pass. Desktop was not restarted. No live model calls and no credential reads.

## 1.3.9 — 2026-10-17

- Fix DeepSeek Harness `0.2.1-rc.1` failing to start with this plugin installed. The desktop app stopped with `connection (required)  webRuntime` among the plugins waiting for services, and everything that needs Connection waited behind it. DSH 0.2.1 renamed the service the official `connection` row reads `trustedHosts` from, `webRuntime`, to `webStartup`. The bundle patch shipped since 1.2.4 replaced that row's whole inject list (since 1.3.5 with `credentials`, `webRuntime`, and `webServer`), so on 0.2.1 Connection waited for a service no row provides.
- The bundle now patches no official row; it only inserts its own. Every DSH version keeps its `connection` row exactly as shipped, so a later rename there cannot block startup again. The account channel still needs `webServer` on the connection fiber, and the binding 1.3.6 added for hosts where the patch did not land now does that everywhere. The plugin opens the channel once the web server is running and reopens it after a restart, instead of failing when Connection starts first. The channel is still Connection's own route behind its authentication fence, and an unauthenticated request is still rejected.
- Accept `@deepseek-ai/cordis` `4.0.5` and `@earendil-works/pi-ai` `1.1.0`, the versions DeepSeek Harness 0.2.1-rc.1 ships. The Cordis 4.0.5 runtime is byte-identical to 4.0.4, and pi-ai 1.1.0's `kimiCodingProvider` is unchanged. On DSH 0.2.1 the model list shows Kimi models only while the subscription is connected; the host's adapter now asks for a credential before listing any provider's models.
- Verified offline: all 106 tests pass on the 0.2.0-rc.1 development baseline and again against the host packages inside DeepSeek Harness.app 0.2.1-rc.1. `--dump-config` on the app's bundled CLI, with a scratch DSH home, composes the 1.3.8 row as `[credentials, webRuntime, webServer]` and leaves the official `[webStartup]` row untouched with this version. Desktop was not restarted. No live model calls and no credential reads.

## 1.3.8 — 2026-10-09

- Show a readable plugin name on the Plugins page: **Kimi Subscription** in English and **Kimi 订阅** in Chinese, with a matching localized description. DSH reads `meta.title` and `meta.description` from `<package>/locale/<language>.json`; without those files the card fell back to the raw package name `dsh-kimi-subscription`. The package now ships `locale/en.json` and `locale/zh-CN.json`, exports `./locale/*.json`, and includes them in the published files.
- Add a release regression check for the locale export, packaged files, language-id filenames, and the localized titles and descriptions. Pinned installation examples now name 1.3.8.
- No authentication, model-routing, search, quota, icon, or dependency changes. Update the plugin and fully restart DSH to reload the installed package metadata.

## 1.3.7 — 2026-10-09

- Show the existing Kimi mascot on the installed plugin card. The package now declares a top-level `icon` and ships a dedicated 512×512 transparent, lossless WebP (208,698 bytes), below DSH's 256 KiB icon limit. The original 1.6 MiB README PNG exceeds that limit and is retained unchanged.
- Add a release regression check for the icon declaration, exported manifest, packaged asset, WebP signature, and host byte limit. Pinned installation examples now name 1.3.7.
- No authentication, model-routing, search, quota, or dependency changes. Update the plugin and fully restart DSH to reload the installed package metadata.

## 1.3.6 — 2026-10-01

- Fix `dsh web` still failing with `cannot get property "webServer" without inject` after 1.3.5. `connection.rpc.handle` reads `webServer` on the connection fiber. The official row only injects `webRuntime`, and the bundle patch that adds `webServer` is skipped when it is applied before that row exists, so the running fiber never receives it. Reinstalling the package does not change that. Before opening the account channel, the plugin now attaches the already-running web server onto that fiber. The channel is still Connection's own route, and an unauthenticated request is still rejected. The row patch remains for hosts that apply it.
- No live model calls and no credential reads.

## 1.3.5 — 2026-10-01

- Fix `dsh web` failing to activate with `cannot get property "webServer" without inject` after installing the plugin. `@deepseek-ai/dsh-client-connection` declares only `credentials`, while its RPC registration reads `webServer` on that same fiber. DSH `0.2.0-rc.2` `dsh web` and the desktop app load the same `@deepseek-ai/dsh-web-app` row, and that row injects `webRuntime` alone. The compatibility patch replaces the whole row list, so it now names `credentials`, `webRuntime`, and `webServer` together. Dropping the patch (the row already looked complete) removes `webServer` on both surfaces. Dropping `webRuntime` breaks `trustedHosts`. Dropping `credentials` breaks Connection's own `apply` on a host that does not also merge the module inject list.
- Confirmed on the `0.2.0-rc.2` CLI bundled with DeepSeek Harness.app: a scratch web profile composes that inject list, keeps the official `trustedHosts` expression, and starts with no activation warning. Desktop was not restarted. No live model calls and no credential reads.

## 1.3.4 — 2026-09-30

- Publish from GitHub Actions with npm trusted publishing, so the registry stores a provenance attestation. That is the green check beside the version on npm (“Built and signed on GitHub Actions”). `1.3.3` was published from a local machine and cannot gain the mark afterwards; provenance is signed when the version is published.
- No source, peer-range, compatibility, authentication, search, or quota behavior changes. No live model calls and no credential reads.

## 1.3.3 — 2026-09-28

- Document the desktop application as the only supported installation target, and drop the web-profile instructions from both READMEs and both guides. The plugin itself is unchanged and still loads on any conforming DSH profile; what changes is what this project tells users to do.
- Install instructions now describe the desktop application's own **Plugins** page: **Add plugin**, enter `dsh-kimi-subscription` as the package name, pick the official source, then **Install**. The same field accepts a GitHub repository address, an absolute local plugin directory, and a version-qualified name such as `dsh-kimi-subscription@1.3.3`. This replaces the previous `dsh plugin --profile web add …` commands.
- Update and uninstall instructions now lead with **Settings → Kimi subscription → Update plugin** and the Plugins page's **Uninstall**, which is what the desktop application actually exposes. The manual `pnpm add --save-exact …` recovery step for older versions is kept, because `dsh plugin --profile desktop …` is still refused by the CLI with `profile "desktop" is managed exclusively by the Electron application`.
- `dsh plugin --profile <name> …` is documented as a non-desktop-profile path only, so it is not lost for anyone running a scratch profile.
- No source, peer-range, compatibility, authentication, search, or quota behavior changes. No live model calls and no credential reads.

## 1.3.2 — 2026-09-28

- Fix the plugin being disabled outright after the desktop app updated to DeepSeek Harness `0.2.0-rc.1`. Every `@deepseek-ai/dsh-*` peer still stopped at `<0.2.0-0`, so the host's compatibility preflight refused the whole bundle and printed `skipping profile bundle "dsh-kimi-subscription": Error: Plugin dsh-kimi-subscription@1.3.1 is incompatible with dsh 0.2.0-rc.1: peerDependencies {...}`. The row never mounted, so the Kimi models and the settings page both disappeared. The condition was reproduced against a scratch profile on the real desktop runtime before and after the change.
- Widen the declared host peer range to `>=0.1.1-rc.2 <0.3.0-0`, spanning the whole 0.2 line instead of stopping at 0.1. `0.3.0` is still refused, so this stays a claim about a tested line rather than an unbounded promise about any future host. `1.2.14` made the same call for the 0.1 line after an enumerated list broke on a host bump; the 0.1-only upper bound then broke on the next minor line.
- The development baseline, the recorded compatibility data, and the entire offline test suite now target the published `0.2.0-rc.1` host packages, the versions the current desktop app actually carries.
- Accept `@earendil-works/pi-ai` `0.86.0`, `0.86.1`, `0.87.0`, and `0.87.1` in the peer range, and build and test against `0.87.1`. DSH `0.2.0-rc.1` itself depends on `^0.85.1`, so a profile install can resolve any of these and the plugin imports this package directly. `kimiCodingProvider`, the `./providers/*` entry point, and the root `createModels` export are unchanged across `0.85.1` → `0.87.1`.
- `tests/package-contract.test.mjs` now requires every declared host peer range to equal `compatibility.json`'s `acceptedRuntimeRange`, and requires the latest recorded version to be listed as supported and to satisfy that range, so the metadata the gate reads cannot drift from the manifest again.
- No model-routing, authentication, search, quota, or client-UI behavior changes; no source-file changes. No live model calls and no credential reads.

## 1.3.1 — 2026-09-28

- Fix「更新插件」failing on the desktop app. The update action built its command from `process.argv[1]`, which is the entry script of whichever process loaded the plugin — the dsh CLI only when the host *is* the CLI. The desktop app loads plugins inside `@deepseek-ai/dsh-desktop-host`, so that argument was the desktop host entry, and the update re-launched the application with `plugin …` arguments instead of installing anything; the host read those arguments as a profile directory and exited non-zero, so every desktop update attempt failed while「检查更新」kept working.
- The update no longer shells out to `dsh plugin`, which cannot serve the desktop app at all: `dsh plugin --profile desktop` is refused outright with `profile "desktop" is managed exclusively by the Electron application`. It now installs the exact published version into the owning profile with pnpm directly — the same package-manager step `dsh plugin add` performs for a registry spec — using the bundled pnpm entry the desktop host passes in its own arguments, matched by file name rather than by position. The runtime directory carrying the `@deepseek-ai/dsh` package is the fallback, and `PATH` never decides which package manager runs.
- The install is pinned and age-free: `pnpm add --save-exact --config.minimumReleaseAge=0 <name>@<version>`. Without the override, pnpm ≥ 11 quietly keeps the installed version when the target was published less than 24 hours ago — exactly the releases this button exists to install — and with `minimumReleaseAgeStrict: true` that skip becomes a hard failure.
- A zero exit is no longer reported as a successful update on its own. The installed `node_modules/<name>/package.json` is read back and must equal the requested version before the settings page says「已更新」, so a command that installed nothing now fails instead of silently claiming success.
- Verified against the real desktop runtime (`@deepseek-ai/dsh-desktop-host`, DSH `0.1.7-rc.2`, bundled pnpm `11.7.0`) using the shipped bundle and the live host's own launch arguments: the bundled pnpm entry is selected, and `update()` installs the target version into a scratch profile and rewrites its `package.json` dependency while keeping the `dsh.profile.bundles` entry. No live model calls and no credential reads.
- The sibling `dsh-grok-subscription` plugin carries the same `process.argv[1]` pattern through the same code lineage; it is not changed here.

## 1.3.0 — 2026-09-28

- Add the original Moonlight Coder mascot and reorganize the project homepage around features, installation, daily use, screenshots, and maintenance.
- Add an English README and Chinese/English usage guides covering subscription credentials, model access, quota, web-search coexistence, and safe removal.
- Include the mascot, both READMEs, and both guides in the published package so the new documentation assets ship with npm and release archives.
- Refresh pinned installation examples to this release and add a regression check for the documentation packaging contract.
- No model-routing, authentication, search, quota, or peer-dependency behavior changes. This release carries forward the runtime from 1.2.14.

## 1.2.14

- Explain a plan-gated model instead of letting it read as a credential failure. Kimi Code gates models by membership tier and answers a request for a model the plan does not include with HTTP 401; the host classifies any 401 as `AUTH` and its chat surface replaces the text with「API 密钥无效」, so a tier limit looked like a broken key. The stream guard now rewrites that terminal failure into an explicit sentence naming the model and suggesting `kimi-for-coding`. The replacement deliberately carries no status code and none of the words the host matches for quota, rate limits, timeouts, or transport faults, which also keeps the failure out of the `AUTH` retry policy that cannot help it.
- Add the tier table and this failure mode to the README.
- No behavior change for any other failure; no live model calls or credential reads.

## 1.2.13

- The host now performs the Kimi device sign-in and token refresh itself instead of delegating to pi-ai's OAuth, which authenticates with the ambient `fetch`. Both requests ask for an identity-encoded body, and the response is additionally decoded by its magic number (gzip / zstd) when the `Content-Encoding` header did not survive the transport. A token response is about 1.5 KB, so it arrives compressed; a transport that hands back the still-compressed bytes used to turn a successful exchange into `device token request failed (status 200)`, which the settings page showed as「操作失败，请重试。」. This removes the plugin's last dependency on the host's response decoding.
- A failed sign-in now carries the name of the step that failed — `denied`, `expired`, `exchange`, `response`, `network`, or `unreachable` — and the settings page renders it as a specific sentence in Chinese or English instead of one generic line. Provider output still never leaves the Host, because it can quote a token.
- A refresh response that does not rotate the refresh token now keeps the previous one, as RFC 6749 allows, instead of failing the credential.
- No live model calls or credential reads.

## 1.2.12

- Replace the enumerated `@deepseek-ai/dsh-*` peer versions with the range `>=0.1.1-rc.2 <0.2.0-0`. The desktop app auto-updated from `0.1.7-rc.1` to `0.1.7-rc.2` and every enumerated peer stopped matching, so profile startup skipped the bundle and the Kimi models disappeared again with `no adapter registered`. A range keeps the plugin loading across the 0.1 line while still refusing `0.2.0` prereleases.
- The peer gate is now asserted by release semantics rather than by literals: `tests/package-contract.test.mjs` runs the installer's rule (`semver.satisfies(runtime, range, { includePrerelease: true })`) against older releases, the current desktop release, and a rejected `0.2.0` prerelease.
- No source behavior change; no live model calls or credential reads.

## 1.2.11

- Fix “无法检查最新版本” on the desktop app when another plugin replaces undici's global dispatcher with one that does not decompress responses. Registry, usage, and search requests now ask for an identity-encoded body, so `response.json()` no longer fails on gzip bytes.
- No live model calls or credential reads.

## 1.2.10

- Fix the desktop settings page on DeepSeek Harness `0.1.7-rc.1`. That host replaced `settings.register` with volatile plugin Config, so `1.2.9` threw `ctx.settings.register is not a function` while applying and never mounted the account RPC. The settings page then reported that it could not read the Kimi subscription status. The search preference now uses `settings.register` on older hosts and this plugin's volatile Config on `0.1.7`.
- No live model calls or credential reads.

## 1.2.9

- Accept DeepSeek Harness `0.1.7-rc.1`, the version shipped in the desktop app. Its plugin installer rejects a package unless every `@deepseek-ai/dsh-*` peer range satisfies that runtime (prereleases included), which is why `1.2.8` was reported as incompatible. Peer ranges now include the `0.1.5` / `0.1.6` / `0.1.7` releases through `0.1.7-rc.1`, and the development baseline is `0.1.7-rc.1`.
- Drop the `@deepseek-ai/dsh-client-runtime` peer. Its last published release is `0.1.1-rc.2`, and the desktop app no longer ships it. The client inject list now names `@deepseek-ai/dsh-client-ui-conversation`, which owns the composer slot this plugin renders into.
- Widen `@deepseek-ai/cordis` to `4.0.4` and `@deepseek-ai/schemastery` to `^3.18.2`, matching the desktop kernel. The `connection` compatibility patch is unchanged and still activates RPC on both the current and `0.1.2-alpha.5` Connection.
- No live model calls, credential reads, or desktop GUI verification.

## 1.2.8

- Fix [#2](https://github.com/BaronCyrus/dsh-kimi-subscription/issues/2): resolve the Kimi subscription retry policy through the host's public `resolveRetryPolicy` helper before passing it to `PiAiAdapter`. Plugin-supplied profiles already need a resolved policy; missing backoff fields previously produced `NaN` delays and `session event "llm/retry" carries non-JSON-serializable data`, masking the original provider error.
- Preserve normal mode, the two-retry limit, and the existing six retryable codes (including `AUTH` for expired-in-flight OAuth tokens). Use host defaults for initial delay, maximum delay, and jitter. This restores bounded retries; it does not restore exhausted quota or fix genuinely revoked credentials.
- Add offline regression coverage at the actual adapter, host retry executor, and Session event-validation boundary, including finite delays, retry exhaustion, provider-directed delays, and cancellation. Test dependencies are pinned to the existing DSH `0.1.5-alpha.2` baseline; supported host versions are unchanged. No live credentials or model requests are used.

## 1.2.7

- Support Kimi Code's K2.8 Preview upgrade: `kimi-for-coding` was upgraded in place (same model ID) to K2.8 Preview with a 1M context window and `low` / `high` / `max` thinking levels (default `max`). pi-ai's bundled catalog still describes K2.7 Code, so the plugin now patches that model's name, context window, and thinking-level map locally until the upstream catalog catches up. No model ID changes; `k3`, `k3-256k`, and `kimi-for-coding-highspeed` are unchanged.

## 1.2.6

- Fix `Cannot read properties of undefined (reading 'get')` when DeepSeek Harness `0.1.5-alpha.2` resolves the Kimi subscription model catalog: initialize the provider profile's `modelErrors` map required by the host PiAiAdapter.
- Extend peer compatibility to DSH `0.1.5-alpha.2` and update development dependencies and the lockfile to test against that host release, retaining previous peer ranges.
- Add a regression test that first reproduced the exact failure and now resolves every advertised Kimi model and prepares its call through the real host adapter. Catalog verification asserts that credentials are not read and never opens a model stream.
- Validation: 59 automated tests, Host/Client builds, and package creation; no live model calls or full GUI/account-flow verification.

## 1.2.5

- Correct the 1.2.4 Connection compatibility patch to retain the official profile's `webRuntime` injection alongside `webServer`. Entry patches replace the row's inject array; dropping `webRuntime` prevents `trustedHosts: !!js ctx.webRuntime.trustedHosts` from being evaluated during startup.
- Exercise the real profile's entry injection and dynamic trusted-host expression in regression tests, including an explicit reproduction of the 1.2.4 failure.

- Validation: 58 automated tests and real profile configuration checks; the user confirmed successful DSH startup after applying the corrected dependency list.

## 1.2.4

- Fix startup on DeepSeek Harness `0.1.5-alpha.1`: the plugin bundle adds `webServer` to the official `connection` loader entry's injected services. This compensates for Connection RPC registration accessing an undeclared owner dependency, without editing installed DSH code or replacing its transport/authentication logic. The patch is guarded by the official package name and is idempotent on previously supported hosts.
- Extend peer compatibility to DSH `0.1.5-alpha.1` and pi-ai `0.85.1`; update the development baseline while retaining prior peer ranges.
- Add real Cordis Loader/Connection regression coverage: reproduce the unpatched failure, activate the full plugin against current and legacy Connection, verify unauthorized requests are rejected, and verify route cleanup on unload. Validation uses isolated fake host resources and no live credentials or provider calls.

## 1.2.3

- Widen the `@deepseek-ai/cordis` peer range to `4.0.1 || 4.0.2`. DeepSeek Harness 0.1.2 hosts bundle cordis 4.0.2 and their packages require `^4.0.2`, so the previous exact `4.0.1` pin made pnpm print an unmet-peer warning on every `dsh plugin add` (harmless under DSH's `autoInstallPeers: false` profile setup, but noisy). No runtime behavior change.

## 1.2.2

- Refresh compatibility metadata for DeepSeek Harness `0.1.2-alpha.5`: peer ranges now accept `0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3 || 0.1.2-alpha.5` (`@deepseek-ai/dsh-client-runtime` remains `0.1.1-rc.2`, the newest published), development dependencies build and test against `0.1.2-alpha.5`, and `compatibility.json`/README list `0.1.2-alpha.5` as supported. No runtime behavior change.

## 1.2.1

- Refresh compatibility metadata for DeepSeek Harness 0.1.2: peer ranges now accept `0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3` (`@deepseek-ai/dsh-client-runtime` remains `0.1.1-rc.2`, the newest published), development dependencies build and test against `0.1.2-alpha.3`, and `compatibility.json`/README list the 0.1.2 alpha line as supported. No runtime behavior change.

## 1.2.0

- Automatic Codex coexistence for web search: no more manual profile patch. When the Codex subscription plugin manages DSH's search slot, choosing `auto`/`kimi` now writes (and `default` removes) a marked `- id: web` block in the owning profile's `cordis.patch.yml`, which DSH hot-applies without a restart — Codex models use the Codex subscription search, Kimi models use the Kimi subscription search, and other models use the DSH default. The block preserves every other `web` config key (e.g. `fetchProvider`) and every unrelated patch entry verbatim, and the settings card explains the behavior when the Codex plugin is detected. Without the Codex plugin, the previous runtime-slot behavior is unchanged and any stale patch block is cleaned up.

## 1.1.1

- Fix a search-routing race with dsh-codex-subscription. With both plugins set to route web search, the two switchers could contest DSH's single search-provider slot across web-runtime restarts; in practice the Codex plugin's selection won, silently routing Kimi models to the DSH default search instead of the Kimi subscription search. This plugin's switcher now yields whenever the Codex plugin's search providers are registered (the settings page explains this when detected), and the README documents the supported coexistence setup: keep the Codex plugin on its auto route and point the profile `cordis.patch.yml` web `searchProvider` at `kimi-subscription-auto`.
- The auto router now falls through to the built-in `deepseek-official` provider when the DSH base configuration already points at one of this plugin's own providers, avoiding self-delegation for non-subscription models in that patched setup.
- `preferences/status` additionally reports `codexDetected` so the settings card can explain when the selection is inactive.

## 1.1.0

- Add subscription-backed web search. The plugin registers two DSH search providers — `kimi-subscription` (Kimi Code's official `/coding/v1/search` endpoint, authenticated with the host-side subscription credential) and `kimi-subscription-auto` (routes by initiating model: Kimi models use Kimi search, Codex models delegate to the Codex subscription auto provider when installed, everything else uses the DSH default). A new Web search card in Settings selects `default` (passive, never touches DSH's single search-provider slot), `auto`, or `kimi`; switching back to `default` restores the provider this plugin took over from. Credentials and search traffic remain Host-side; the browser only sees the loopback-authorized preference projection.

## 1.0.3

- Fix subscription-usage and plugin-version reads permanently failing (`无法读取订阅余量` / `无法检查最新版本`) on some host startups. Both readers captured the ambient `globalThis.fetch` when the plugin loaded; a sibling plugin that temporarily swaps `globalThis.fetch` with a scoped proxy wrapper during its own startup network work could leave these readers holding a dismantled wrapper whose fallback is nulled on teardown, failing every request for the process lifetime. The ambient fetch is now resolved per call, which stays correct whether or not such a wrapper is installed.

## 1.0.2

- Fix a cancellation race that could make both the subscription-usage and plugin-version cards show permanent errors after page startup or reload. Shared Host requests now survive one browser caller disconnecting, while that caller still cancels promptly and the bounded request can complete for other subscribers and populate the cache.
- Keep the cancellation timeout regression tests alive reliably on the Node.js 22 CI runner.

## 1.0.1

Unpublished. The immutable tag is retained after its Node.js 22 CI run exposed a timeout-test harness issue; the corrected release is 1.0.2.

## 1.0.0

First stable release.

- Show the current and latest plugin versions in the Settings Kimi subscription section. The latest version comes from public npm registry metadata (Host-side, timeout-bounded, redirects refused) and is cached for 5 minutes.
- Add a one-click **Update plugin** button when a newer npm version exists. The update runs `dsh plugin --profile <owning profile> add dsh-kimi-subscription@<version>` on the Host; afterwards the settings page prompts to restart DSH or refresh the page, since the running host process keeps the old code until restarted. Local `link:`/`file:` development checkouts are reported but never updated in place.

## 0.3.3

- Fix sporadic `API key is invalid` (HTTP 401) turn failures with OAuth device sign-in. Kimi Code access tokens live only ~15 minutes and pi-ai refreshed them only at their nominal expiry with zero leeway, so requests dispatched in the final moments of a token's life were rejected and the whole turn failed (AUTH was not retryable). OAuth credentials now refresh 3 minutes early; a pre-chunk 401 marks the access token as upstream-rejected so the next attempt force-refreshes under the serialized lock; and the provider retry policy retries AUTH failures up to 2 times, recovering expired-in-flight tokens transparently. Genuinely revoked credentials still fail after the retries.

## 0.3.2

- Fix the Settings usage reset-time text color: it used the near-invisible `--dsw-alias-label-dimmed` token and now uses `--dsw-alias-label-tertiary`, which stays readable in both light and dark themes.

## 0.3.1

- Publish the plugin as the public npm package `dsh-kimi-subscription`.
- Make npm the primary installation and update path while retaining GitHub Release tarballs.
- Clarify that Kimi Code subscription credentials and Kimi Open Platform API keys are not interchangeable.

## 0.3.0 — 2026-04-02

First public release.

- Register Kimi Code subscription models under the exact `Kimi subscription` group.
- Support subscription API keys and Kimi OAuth device-code login.
- Keep credentials in the DSH Host credential service with OAuth refresh rotation.
- Display weekly, rolling-window, reset-time, and booster-wallet usage in Settings.
- Display `5h 82%　7d 64%`-style quota beside the conversation input for selected Kimi models.
- Keep the subscription route separate from existing `kimi-coding` and Kimi Open Platform configuration.
- Restrict browser RPC to loopback and keep raw credentials and provider usage payloads Host-only.
