# Changelog

## 5.1.0 — 2026-07-12

### Changed

- **`@x12i/ai-profiles` ^4.4.0:** Profile registry refresh — `cheap/default` resolves to `deepseek/deepseek-v4-flash` (was Gemma). Cost/docs tests aligned with the new mapping.

## 5.0.0 — 2026-07-10

### Breaking

- **`@x12i/ai-profiles` ^4.2.1** is the **single source of truth** for profiles and the models catalog (including OpenRouter). Bundled `src/data/models-catalog.json` / `openrouter-models-catalog.json` and dual open-assets loaders are removed.
- **Resolve order:** known profile input is resolved via ai-profiles **`resolveInput` / `isKnownProfileInput`** before catalog fuzzy match. Vendor identity no longer invents a provider from arbitrary `prefix/rest` strings (fixes `cheap/default` being treated as vendor `cheap`).
- Catalog load goes through `loadModelsCatalog` / unified `models-catalog.v2.json`. `DEFAULT_MODELS_CATALOG_URL` replaces the dual URL pair (legacy `DEFAULT_DIRECT_CATALOG_URL` / `DEFAULT_OPENROUTER_CATALOG_URL` still exported as aliases).
- Removed `npm run catalog:refresh` / `catalog:verify` scripts that seeded ai-tools-owned JSON (use `ai-tools catalog refresh|verify` CLI or ai-profiles catalog tooling).

### Changed

- `AiModelsCatalogClient` maps ai-profiles `CatalogModelEntry` (`direct` + `openrouter` slices) into `AiModelRecord` maps.
- `AiModelsService.listModels` / `countModels` delegate attribute filters to `listAICatalogModels` (provider, status, modalities, tools, reasoning, search).
- `matchModelInAiProfiles` is a thin adapter over `resolveInput` (no local profile-index workaround).
- Re-exports: `isKnownProfileInput`, `resolveInput`, `listAICatalogModels`.
- `ModelNameResolver` remains as a fuzzy layer over the ai-profiles-loaded catalog only.

## 4.0.0 — 2026-07-08

### Breaking

- **`@x12i/ai-profiles` ^4.0.0:** Profile registry refresh — `cheap/default` and related tiers resolve to Gemma models (e.g. `google/gemma-3-4b-it`) instead of `google/gemini-2.5-flash-lite`. Bare `gemini-2.5-flash-lite` is no longer indexed in profile choices; use catalog pricing or a current profile-choice model id. `deepseekv32` resolves via ai-profiles registry alias to `deepseek-v3.2`.

### Changed

- Tests and docs aligned with ai-profiles v4 registry and `resolveModelIdentity` behavior.

## 3.3.5 — 2026-06-08

### Changed

- **README:** Document `@x12i/logxer@5.1.0` ESM/CJS dual export fix, consumer import boundaries (`package-levels` vs main entry), and upgrade path for Vite/ESM hosts.

## 3.3.4 — 2026-06-08

### Changed

- **`@x12i/ai-profiles` ^3.4.1**, **`@x12i/env` ^4.0.3:** Dependency bumps; ai-profiles pulls **`@x12i/logxer@^5.1.0`** (dual ESM/CJS named exports — fixes Vite `import { createLogxer }` interop failures from logxer 4.x).

### Notes

- ai-tools does not import `@x12i/logxer` directly. See README § [`@x12i/logxer@5.1.0`](#x12ilogxer510--esmcjs-and-import-boundaries) for consumer import boundaries (`package-levels` in browser; main entry Node-only).

## 3.3.0 — 2026-06-08

### Breaking

- **OpenRouter routing:** `PREFER_OPENROUTER` env (default `true`; accepts `true`/`false`/`1`/`0` and ai-profiles aliases like `yes`/`on`) and `preferOpenRouter` invoke option, aligned with `@x12i/ai-profiles`. Exports: `resolvePreferOpenRouter`, `readPreferOpenRouterFromEnv`, `resolvePreferOpenRouterPreference`, `PreferOpenRouterOptions`.
- **Catalog routing default:** When both `OPENROUTER_API_KEY` and a vendor key are set, unset `PREFER_OPENROUTER` defaults to OpenRouter (aligned with invoke path).
- **Toolbox:** Export `DEFAULT_TOOLBOX_MODEL` (`cheap/default`).

### Changed

- **`@x12i/ai-profiles` ^3.3.0:** Dependency aligned with `PREFER_OPENROUTER` env parsing.

## 3.1.0 — 2026-06-05

### Breaking

- **`@x12i/ai-profiles` v3.0.0:** Only `profile/choice` keys or concrete model ids are accepted. Shortcuts (`standard`, `cheapest`, …), bare profiles (`cheap`), and profile aliases are rejected.
- **Removed project-local aliases:** `@x12i/ai-tools/aliases` export, `AliasRegistry`, `AliasResolver`, `ai-tools alias` CLI, and all `ALIAS_*` error codes.
- **Removed legacy model shorthands:** `SHORTHAND_MAP` / `shorthand-expansion` (`deepseekv32`, `claude-sonnet`, …). Use catalog ids (`deepseek-v3.2`, `deepseek/deepseek-v3.2`).
- **Removed ai-profiles shortcut resolution:** `listAIShortcuts`, `ai-profiles-shortcut` strategy, shortcut branches in `profileResolveKey` / `aiProfilesMatch`.
- **Renamed invoke routing:** `applyOpenRouterInvokePolicy` → `applyOpenRouterInvokeRouting`; `ApplyOpenRouterInvokePolicyOptions` → `ApplyOpenRouterInvokeRoutingOptions`.
- **Invoke diagnostics:** `diagnostics.profileAlias` → `profileKey`; `ModelProfileUnroutableError.profileAlias` → `profileKey`.
- **Removed `ModelResolverOptions`:** `aliasRegistry`, `additionalShorthands`.

### Added

- Re-exports from `@x12i/ai-profiles` v3: `ensureConcreteModel`, `resolveBundledInput`, `resolveModelIdentity`, `listAIProfileChoices`, `resolveAIProfileByTags`, `isKnownProfileChoiceInput`, `listRegistryProfileChoiceKeys`.

### Notes

- See README § [v3.0 breaking changes](#v30-breaking-changes) for migration table.

## 2.5.0 — 2026-06-03

### Added

- **`resolveInvokeModel()`** — host-agnostic invoke-time model resolution orchestrator (catalog + profiles + vendor mapping + OpenRouter invoke policy).
- Supporting exports: `buildInvokeModelResolverOptions`, `mapResolutionToRouterConfig`, `applyOpenRouterInvokePolicy`, `enrichModelResolutionError`, `resolvePreferOpenRouter`, `readPreferOpenRouterFromEnv`, `resolveOpenRouterApiKey`, `createAiToolsInvokeClient`, `getAiToolsInvokeClient`.
- **`ModelProfileUnroutableError`**, **`ModelProfileInputRejectedError`**, **`INVALID_INVOKE_INPUT`** error code.
- **`@x12i/ai-tools/invoke`** subpath export.
- Env **`PREFER_OPENROUTER`** for invoke-time OpenRouter preference (`resolvePreferOpenRouter` defaults to `true` when unset).

### Notes

- Engines (`@x12i/ai-gateway`, graph-engine, ai-skills) can delegate model resolution to ai-tools instead of duplicating gateway glue.
- See README § [Invoke model resolution](#invoke-model-resolution-v25).

## 2.4.0 — 2026-06-02

### Breaking

- **`@x12i/ai-profiles` ≥ 2.1.0:** Profile resolution requires `profile/choice` (e.g. `cheap/default`), a shortcut (`standard`), or explicit `profile` + `choice` on `resolveProfileForAsk`. Bare profile names (`cheap`) are rejected.
- Removed `isKnownProfileOrShortcut` → use `isKnownProfileChoice` from ai-profiles.

### Added

- `requireProfileResolveKey`, `profileResolveKey`, `ProfileResolveKeyRequiredError`.
- `@x12i/ai-tools/profiles` export path; profile helpers enforce the same contract as ai-profiles for external configs.

### Notes

- Concrete model SKUs (`gemini-2.5-flash-lite`, `deepseek/deepseek-v3.2`) still resolve via catalog / registry index without a profile key.
- See README § [AI profiles (v2.4)](#ai-profiles-v24-x12iai-profiles-21) for caller guidance.

## 2.0.0 — 2026-05-27

### Breaking

- Removed Catalox/Firestore catalog sync (`ensureAiModelsCatalog`, `runAiModelsCatalogSync`, `ai-tools sync`).
- Pricing catalogs load from [open-assets.x12i.com](https://open-assets.x12i.com/) JSON with bundled `src/data` fallbacks.
- Default catalog cache TTL is **24 hours** (was 1 hour in earlier CLI defaults).

### Added

- `AiModelsCatalogClient` with dual catalogs (direct vendor + OpenRouter pricing).
- `loadCatalogSources`, `loadCatalogSourcesCached`, `refreshAiModelsCatalog`, `verifyAiModelsCatalog`.
- `CostCalculator.calculateFromRecord()` for activity/gateway JSON.
- Smart usage extraction (`extractUsageInput`) with model/token field priorities.
- Versioned runtime model id resolution (`gpt-5.5-2026-04-23` → `openai/gpt-5.5`) with `VERSION_SUFFIX_PRICING` warning.
- CLI: `catalog refresh`, `catalog verify`.

### Notes

- Catalog JSON `version` / `schema` fields are informational; the library does not validate or compare them.
- Remote catalogs are always treated as the latest pricing source when the network is available.
