## Summary
Adds **Granite**, a new OpenAI-compatible (chat completions) stealth
provider, and serves two models through it.
### Provider
- New provider `granite` in `packages/models/src/providers.ts`,
configured via `LLM_GRANITE_API_KEY` and `LLM_GRANITE_BASE_URL`.
- Base-URL resolution wired in
`packages/actions/src/get-provider-endpoint.ts`; requests resolve to
`<baseUrl>/v1/chat/completions` via the default OpenAI-compatible path,
with `Authorization: Bearer` auth via the default header case.
- Registered in the OpenAI-compatible streaming transform
(`transform-streaming-to-openai.ts`) so responses don't hit the "unknown
provider" fallback.
- Provider icon entries added in `provider-icons.tsx` and
`provider-logo.ts`.
### Models (Granite mappings added to existing models)
- **glm-5.2** (`packages/models/src/models/zai.ts`) — Granite mapping
with reasoning + tools + json. Web search is intentionally **not**
advertised: it is wired only in the provider-specific `zai` branch, and
the Granite upstream does not perform a search (verified `webSearchCost:
0`).
- **qwen3.7-max** (`packages/models/src/models/alibaba.ts`) — Granite
mapping added to the existing `qwen3.7-max` model, reusing its pricing
and the existing `supportedParameters` set (which drops `tool_choice`,
since this thinking-mode model rejects forced `tool_choice`). Added
`granite/qwen3.7-max` to the Responses-API tool-call
`TOOL_CALL_DENYLIST` in `responses.e2e.ts`, because under forced
`tool_choice` the upstream returns reasoning text instead of a
structured tool call (the existing `alibaba`/`novita` mappings handle
this path; granite's upstream does not).
### Docs
- `AGENTS.md`: documented scoping the full e2e suite to a single mapping
via `TEST_MODELS` instead of running individual `*.e2e.ts` files one by
one.
## Testing
Full e2e suite scoped per mapping:
- `TEST_MODELS="granite/glm-5.2" FULL_MODE=true pnpm test:e2e` → all
pass.
- `TEST_MODELS="granite/qwen3.7-max" FULL_MODE=true pnpm test:e2e` → all
pass.
- Web search verified non-functional for Granite
(`TEST_WEB_SEARCH=true`, `webSearchCost: 0`), so the params were
removed.
- `pnpm build` passes; `pnpm format` clean; `packages/models` specs pass
(36 tests, no duplicate model ids).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added support for a new provider across the app, including display
icons, endpoint handling, and model availability.
* Expanded model support so additional chat and reasoning capabilities
are available for compatible models.
* **Bug Fixes**
* Improved streaming event handling and finish-status normalization for
the new provider.
* Refined test coverage exclusions for models with incompatible
tool-call behavior, reducing flaky failures.
* **Documentation**
* Clarified testing guidance to recommend running the end-to-end suite
once with scoped model selection.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>