# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [1.7.0] — 2026-11-02

### Added

- **November ClinePass lineup** — adds Kimi K3.1 Pro, DeepSeek V4.1 Flash 1017, MiMo V2.6 Flash and Pro, and MiniMax M3.1 Flash. MiMo V2.6 Flash exposes a 1M context window. Update saved selections from `cline-pass/mimo-v2.5` to `cline-pass/mimo-v2.6-flash` and from `cline-pass/mimo-v2.5-pro` to `cline-pass/mimo-v2.6-pro`; the retired IDs have no aliases ([#100](https://github.com/jellydn/pi-clinepass-provider/pull/100)).
- **Release-time catalog verification** — `npm run check:catalog` (requires Bun) compares every curated ID with the exact `clinePass` bucket in Cline's first-party lineup feed. It fails on differences or unavailable/malformed data and never changes runtime registration.

### Changed

- **Explicit static registration** — removes ineffective startup discovery through `/api/v1/models`, discovery-only parsers, and generic unknown-model defaults. The provider always registers the reviewed catalog without a catalog request or credential-store read for listing. No vendor-ID inference or automatic registration; model additions, retirements, and metadata changes require a package update ([#103](https://github.com/jellydn/pi-clinepass-provider/pull/103), [#101](https://github.com/jellydn/pi-clinepass-provider/issues/101)).
- **Development compatibility** — lockfile pi dependencies move to 1.5.0 together; manifest and peer ranges are unchanged. Typecheck still covers minimum pi 0.80.2. Other development dependency and CI updates are included; there is still no build step ([#104](https://github.com/jellydn/pi-clinepass-provider/pull/104)).

### Fixed

- **Reference-price drift** — DeepSeek V4 Pro uses ClinePass peak estimates of $1.32 input / $3.96 output / $0.044 cached read per million tokens. Qwen3.8 Max cached read is $0.17. These bundled estimates are not bills or exact quota measurements.
- **Documentation and regressions** — clarify static pricing/modalities and the eight-model image-smoke scope, preserve known metadata, reject malformed lineup feeds, and assert that registration makes no catalog request.

### Release verification and limits

- Unit tests, typecheck, lint, formatting, shell syntax, package contents, and all 15 lineup IDs were checked. CI covers lockfile pi on Node 22/24 and minimum pi 0.80.2 on Node 22. Pi 1.5.0 lists all 15 curated models with a registration-only placeholder key.
- **Owner-approved waiver:** live authenticated E2E tests were explicitly waived for this release. Chat completions, image understanding, reasoning behavior, and live login/refresh remain unverified. The image smoke script covers eight of twelve configured image-capable models; Kimi K3.1 Pro, DeepSeek V4.1 Flash 1017, MiMo V2.6 Pro, and MiniMax M3.1 Flash are not in its image loop. Passing unit tests, accepting image payloads, or appearing in the lineup feed does not establish those routes or account entitlement.

## [1.6.0] — 2026-10-07

### Added

- **Image input for multimodal models** — eight catalog models now declare `input: ["text", "image"]`: GLM-5.3-Flash, Kimi K3, Muse Spark 1.3 Contributor, DeepSeek V4.1 Flash, MiMo-V2.5, MiniMax M3, Qwen3.7 Plus, and Qwen3.8 Max. GLM-5.3, DeepSeek V4 Pro, MiMo-V2.5-Pro, and Qwen3.7 Max stay text-only. Previously every model was hard-declared text-only, so pi stripped pasted images before the request reached Cline. Dynamic discovery reads `architecture.input_modalities` and falls back to the static catalog. Images are sent as base64 `image_url` content through pi's built-in `openai-completions` streaming.

### Changed

- **pi 1.0.4 dev range** — `@earendil-works/pi-ai` and `@earendil-works/pi-coding-agent` devDependencies are `^1.0.4`. Peer ranges stay `*` (any installed pi). This removes the lockfile split where typecheck used top-level `pi-ai@0.86.0` while `pi-coding-agent@1.0.4` nested `pi-ai@1.0.4`. `OAuthCredentials` is still `{ access, refresh, expires }`. `registerProvider(name, { api: "openai-completions", oauth, models })` is unchanged. CI still typechecks the minimum pin `0.80.2`. Tooling already on main since 1.5.0: `oxfmt` 0.72.0, `oxlint` 1.87.0, `vitest` 5.0.3, `@types/node` 26.6.4.

### Fixed

- **Release scripts** — `release:patch`, `release:minor`, and `release:major` pass `--release` to bumpp 12. The old form put `patch` / `minor` / `major` after `--tag`, so bumpp treated that word as the tag name and still prompted for the version.

## [1.5.0] — 2026-09-20

### Added

- **GLM-5.3 model** — registered `cline-pass/glm-5.3` (Z.ai) in the static catalog with 1M context / 128K output. GLM-5.3 always reasons and cannot be disabled; its `reasoning_effort` enum is `low`/`high`/`max` (default `max`) with no `medium` or `xhigh` tier, so pi's `off`/`minimal`/`medium` map to `null` and `xhigh` maps to `max` (every offered level distinct and increasing). Pricing mirrors GLM-5.2 per the ClinePass docs ($1.40/$4.40/$0.26).
- **GLM-5.3-Flash model** — registered `cline-pass/glm-5.3-flash` (Z.ai's first natively multimodal GLM-5 model) with 1M context / 128K output. Text parameters are consistent with GLM-5.3 (low/high/max, thinking always on); pricing is Z.ai's published $0.15/$0.50/$0.03.
- **Muse Spark 1.3 Contributor model** — registered `cline-pass/muse-spark-1.3-contributor` (Meta) with 1M context / ~944K output and upstream contributor-tier reference pricing ($0.10/$0.20/$0.002 input/output/cached input). Muse Spark is hosted, not open-weight. Meta's Contributor tier permits training on prompts/completions; check Cline's applicable terms before sending private code. Muse Spark always reasons (`reasoning_effort: "none"` returns HTTP 400), so pi's `off` maps to `null`; minimal/low/medium/high/xhigh map 1:1. The upstream `max` tier is Standard-only.
- **DeepSeek V4.1 Flash model** — registered `cline-pass/deepseek-v4.1-flash` (1M context / 384K output) replacing `cline-pass/deepseek-v4-flash`. Uses upstream peak reference rates ($0.30/$1.20/$0.006 input/output/cached input); upstream off-peak rates are half. ClinePass rates for all three new models remain unconfirmed. Discovery overrides prices only for exact `cline-pass/` IDs with pricing metadata; the public endpoint currently returns upstream IDs without that metadata.

### Removed

- **Deprecated models ([#79](https://github.com/jellydn/pi-clinepass-provider/issues/79))** — removes `cline-pass/glm-5.2` (→ GLM-5.3), `cline-pass/kimi-k2.7-code` and `cline-pass/kimi-k2.6` (→ Kimi K3), and `cline-pass/deepseek-v4-flash` (→ DeepSeek V4.1 Flash) from both static and dynamic catalogs immediately, ahead of Cline's announced 2026-09-21 cutoff. Update saved selections and scripts; no aliases are provided. Runtime TypeScript contracts are unchanged, but removed model selections are not backward-compatible.

### Changed

- **pi 0.86.0 dev range** — bump `@earendil-works/pi-ai` and `@earendil-works/pi-coding-agent` to `^0.86.0`. Peer ranges stay `*` (any installed pi). No custom `streamSimple` migration: ClinePass still uses built-in `openai-completions`. Tooling patches in the same release: `pi-ai` 0.84.4, `@types/node` 26.6.2, `vitest` 5.0.1, `oxlint` 1.83.0, `oxfmt` 0.68.0.

### Docs

- **Thinking levels usage guide** — added Reasoning column to Supported Models table showing per-model thinking level capabilities (off/minimal/low/medium/high/xhigh), plus `--thinking` flag examples in Usage section ([#17](https://github.com/jellydn/pi-clinepass-provider/issues/17))
- **Modular architecture** — documented 8 source modules (`env`, `auth`, `models`, `workos`, `oauth`, `error-handler`, `errors`, `utils`) + entry point in Features
- **Unsupported level wording fix** — clarified that unsupported thinking levels are not sent to the API (model runs with its default reasoning behavior), not "without reasoning"
- **GLM-5.2 reasoning matrix fix** — corrected table to exclude unsupported `minimal` level

## [1.1.1] — 2026-07-15

### Fixed

- **Developer role rejected by ClinePass API** — set `compat.supportsDeveloperRole: false` on all models so pi sends `system` instead of `developer`, fixing 400 errors on GLM-5.2 and other ClinePass models ([#31](https://github.com/jellydn/pi-clinepass-provider/issues/31))

## [1.0.6] — 2026-07-06

### Fixed

- **Thinking level `off` mapping** — map pi's `off` thinking level to ClinePass `reasoning.effort: "none"` instead of `"off"`, fixing 400 errors on GLM 5.2 and other models when thinking is disabled ([#17](https://github.com/jellydn/pi-clinepass-provider/issues/17))

## [1.0.2] — 2026-06-30

### Added

- **`walkClineProviderSettings` helper** — shared traversal extracted from `auth.ts` and `workos.ts` to eliminate duplicated `providers["cline-pass"|"cline"].settings` iteration with `isRecord` chains (~25 lines of duplication eliminated)
- **JSDoc to `buildEndpointUrl`** — was the only exported function without a doc comment; now consistent with all other exports
- **Module-level JSDoc restoration** — `@module clinepass-error-handler` re-added to `error-handler.ts` describing the three pipeline stages (Filter → Classify → Deliver)
- **npm publishing setup** — `.npmignore` excluding source maps, build artifacts, editor files, test fixtures, and doc internals; `CHANGELOG.md` added to package `files`
- **npm badges** — version and downloads badges in README
- **Codemap refresh** — all 7 `.planning/codebase/` documents updated to reflect current architecture (9 modules, 132 tests, DI patterns, auth paths)

### Changed

- **README refinement** — deduplicated install section, added 📦 Installation with pi + npm commands, linked CHANGELOG from footer
- **`sanitizeApiKey` control character filtering** — simplified from `.split("").filter(charCodeCheck).join("")` approach; regex alternatives blocked by oxlint `no-control-regex` even via `new RegExp()`

### Fixed

- **WorkOS token leak in `resolveApiKey`** — pi `auth.json` path now skips `workos:`-prefixed access values (short-lived OAuth tokens should not be returned as static API keys); mirrors existing guard in `resolveClineProvidersKey`

### Tests

- **132 unit tests across 8 files** (up from 124 across 9, consolidated test files)
- New test: WorkOS token skipping in pi `auth.json` path (`tests/unit/auth.test.ts`)

## [1.0.1] — 2026-06-30

### Added

- **Refresh timeout** — `AbortSignal.timeout(15s)` on WorkOS token refresh fetch, with user-friendly `AbortError` message
- **expiresAt validation** — `Number.isFinite` guard alongside `typeof === "number"` in `resolveClineAuthCredentials` to reject `NaN`/`Infinity`
- **`toMicroPerToken` helper** — eliminates redundant `numberValue()` calls in `parseRemoteModel` pricing parsing
- **`fetchRemoteModels` optimization** — combined `filter → map → filter` into single `reduce()` pass
- **Display name fallback** — remote model name prefers `fallback?.name` before raw `id`
- **`resolveApiBase` normalization** — trimming, empty-string fallback, trailing-slash removal
- **403 guidance expansion** — mentions org-level ClinePass admin contact
- **Defensive null guard** — `if (!event.message) return;` in `handleClinePassError`
- **CI hardening** — `persist-credentials: false` on all `actions/checkout` steps
- **Documentation** — ADR-0006 (module split + WorkOS adapter extraction), codebase map updates, npm badges + install instructions in README

### Changed

- **`src/env.ts`** — `sanitizeApiKey` simplified from `Array.from().filter().join()` to regex `.replace()`
- **Architecture** — codebase map documents updated to reflect module-split architecture (9 source modules, 9 test files)

### Fixed

- **TypeScript error** — `makeCallbacks` `onPrompt` return type fixed from `string` to `Promise<string>` in oauth tests

### Tests

- **124 unit tests across 9 files** (up from 96 across 8)
- **`tests/unit/utils.test.ts`** — 19 tests for `isRecord`, `stringValue`, `numberValue`, `booleanValue`
- **`tests/unit/oauth.test.ts`** — 9 new `login()` tests: WorkOS auto-login (valid/expired/margin), manual paste (dashboard URL, empty key, trimming, short-key warning, paste wrapper removal)
- **`tests/unit/env.test.ts`** — 7 new `resolveApiBase` normalization tests (trailing slash, trim, empty string)

## [1.0.0] — 2026-06-29

### Added

- Initial release — ClinePass provider for pi
- 10 curated open-weight models: GLM-5.2, Kimi K2.7 Code, Kimi K2.6, DeepSeek V4 Pro, DeepSeek V4 Flash, MiMo-V2.5, MiMo-V2.5-Pro, MiniMax M3, Qwen3.7 Max, Qwen3.7 Plus
- OpenAI-compatible Chat Completions streaming via pi's built-in `openai-completions` provider
- WorkOS OAuth token refresh — reuses Cline CLI `cline auth` login with automatic token refresh via `POST /api/v1/auth/refresh`
- Static API key authentication with auto-discovery from `CLINE_API_KEY` env var, `~/.cline/data/settings/providers.json`, or `~/.pi/agent/auth.json`
- Dynamic model discovery from Cline's `/models` endpoint, falling back to static list on error
- `/login` integration — automatic WorkOS OAuth detection or browser-assisted manual paste
- Error classification — user-friendly messages for 403 (subscription), 401 (auth), 429 (rate limit) errors
- Error surface via `message_end` event handler with filter → classify → deliver pipeline
- Injection-testable I/O via options objects (`AuthKeyOptions`, `RemoteModelsOptions`)
- 96 unit tests across 8 files
- E2E smoke tests (manual trigger with `CLINE_API_KEY`)
- CI matrix: Node 22 + Node 24, with minimum pi version pinning

[Unreleased]: https://github.com/jellydn/pi-clinepass-provider/compare/v1.7.0...HEAD
[1.7.0]: https://github.com/jellydn/pi-clinepass-provider/compare/v1.6.0...v1.7.0
[1.0.2]: https://github.com/jellydn/pi-clinepass-provider/compare/v1.0.1...v1.0.2
[1.0.1]: https://github.com/jellydn/pi-clinepass-provider/compare/v1.0.0...v1.0.1
[1.0.0]: https://github.com/jellydn/pi-clinepass-provider/releases/tag/v1.0.0
