文件历史

24 次代码提交

作者 SHA1 备注 提交日期
Ali Khokhar af12e7b2bb Coordinate provider recovery under concurrent load (#1205)
## Problem

Concurrent transient failures could start independent retry, replay,
continuation, and repair loops while holding provider concurrency slots.
This multiplied upstream attempts and could delay or strand terminal
errors under fan-out.

## Changes

| Before | After |
| --- | --- |
| Retry paths owned separate attempt budgets. | One logical-execution
session caps all upstream work at five attempts. |
| Concurrent failures backed off independently. | One provider-owned
recovery episode elects a single half-open probe while followers
coalesce. |
| Backoff occupied stream concurrency. | Concurrency is held only while
an upstream operation or stream is active. |
| Provider catalog calls and stream creation used separate admission
paths. | Every upstream operation uses one provider-generation admission
controller. |
| Cancellation could leave recovery ownership or follower state
unresolved. | Cancellation releases permits, transfers probe ownership,
and unregisters waiting followers. |
| Late in-flight failures could cross an exhausted episode boundary. |
Every coalesced execution retains that generation's terminal outcome. |
| Replay tests allowed loose lifecycle assertions. | Exact SSE contracts
prove retries and continuations emit one unduplicated response. |
| Recovery wrappers could mask final diagnostics. | Final responses and
traces retain the raw provider failure and request ID. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR coordinates provider recovery and retry work under concurrent
load. The main changes are:

- One five-attempt budget for each logical execution.
- Provider-wide recovery episodes with one elected probe.
- Shared admission for streams, catalog calls, rate limits, and
concurrency.
- Concurrency permits held only during active upstream work.
- Cancellation-safe probe ownership and preserved final diagnostics.
</details>

<h3>Confidence Score: 5/5</h3>

This looks safe to merge.

No blocking issues found in the changed code.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- Reviewed the coordinated-recovery-01-before.log to understand how the
exhausted generation outcome was not preserved in a late in-flight
failure.
- Reviewed the coordinated-recovery-02-after.log to confirm that the
updated implementation preserves the exhausted generation outcome for
the same focused contract set.
- Validated that the provider-admission-full-current.log shows the
complete requested test file passed under Python 3.14 with uv run pytest
-n 0.

<a
href="https://app.greptile.com/trex/runs/15050270/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| src/free_claude_code/providers/admission.py | Adds shared admission,
retry budgets, recovery episodes, probe election, and cancellation
handling. |
| src/free_claude_code/providers/openai_chat/provider.py | Moves stream
creation, replay, continuation, and repair onto one admission-owned
retry session. |
| src/free_claude_code/providers/stream_recovery.py | Selects replay,
continuation, repair, or final failure using the remaining shared
attempt budget. |
| src/free_claude_code/providers/failure_policy.py | Adds recovery
exhaustion handling and preserves the underlying provider error for
final classification. |
| src/free_claude_code/providers/runtime/factory.py | Creates one
admission controller per provider generation and passes it through
provider factories. |

</details>

<details open><summary><h3>Sequence Diagram</h3></summary>

<a href="#gh-light-mode-only">

```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant E as Execution
participant A as Admission controller
participant P as Provider
participant F as Concurrent follower

E->>A: Open attempt
A->>P: Send upstream request
P-->>E: Retryable failure
E->>A: Open recovery episode
F->>A: Request admission
A-->>F: Coalesce and wait
E->>A: Claim probe
A->>P: Send half-open probe
alt Probe succeeds
    P-->>E: Valid response
    E->>A: Close recovery episode
    A-->>F: Release waiter
else Probe fails
    P-->>E: Retryable failure
    E->>A: Schedule next probe or finalize error
end
```

</a>
<a href="#gh-dark-mode-only">

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant E as Execution
participant A as Admission controller
participant P as Provider
participant F as Concurrent follower

E->>A: Open attempt
A->>P: Send upstream request
P-->>E: Retryable failure
E->>A: Open recovery episode
F->>A: Request admission
A-->>F: Coalesce and wait
E->>A: Claim probe
A->>P: Send half-open probe
alt Probe succeeds
    P-->>E: Valid response
    E->>A: Close recovery episode
    A-->>F: Release waiter
else Probe fails
    P-->>E: Retryable failure
    E->>A: Schedule next probe or finalize error
end
```

</a>
</details>

<sub>Reviews (2): Last reviewed commit: ["Harden coordinated retry
lifecycle
invar..."](https://github.com/alishahryar1/free-claude-code/commit/2e871c8649d148b5eb71d21f80bf870ae2d11708)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=45554917)</sub>

<!-- /greptile_comment -->
2026-07-19 22:43:29 -07:00
Ali Khokhar a0f62c598c Add Google Vertex AI with renewable ADC (#1193)
## Problem

| Before | After |
| --- | --- |
| FCC supported Google AI Studio API keys but could not route coding
agents through a Google Cloud Vertex AI project. | `vertex/...` routes
through Google's [documented OpenAI-compatible Chat Completions
endpoint](https://cloud.google.com/vertex-ai/generative-ai/docs/start/openai),
using the global endpoint by default or an explicitly configured region.
|
| A pasted Vertex access token would expire, while Application Default
Credentials were not part of provider construction. | FCC loads
[Application Default
Credentials](https://cloud.google.com/docs/authentication/application-default-credentials),
supplies a renewable credential callback to the OpenAI transport,
coalesces concurrent refreshes, and returns typed authentication or
transient failures. |
| Vertex does not expose its model catalog through the compatible OpenAI
`/models` route. | FCC translates its generic discovery operation to
Google's paginated [publisher-model list
API](https://cloud.google.com/vertex-ai/docs/reference/rest/v1beta1/publishers.models/list)
and converts resource names into the model IDs accepted by Chat
Completions. |
| Google thought signatures were owned by the AI Studio adapter even
though Vertex shares the same protocol behavior. | A neutral Google
OpenAI family owns shared thought-signature and request behavior; AI
Studio and Vertex retain separate endpoint and authentication ownership.
|

## Changes

- Added the Vertex provider, `VERTEX_PROJECT_ID`, optional
`VERTEX_LOCATION` and `VERTEX_PROXY`, Admin UI configuration,
model-picker discovery, smoke metadata, and customer setup
documentation.
- Added renewable ADC access tokens with refresh coalescing, proxy-aware
refresh, sanitized failure classification, and project quota headers.
- Added global/regional endpoint composition plus native model-catalog
pagination, strict response validation, response cleanup, and
repeated-page protection.
- Generalized provider readiness around declared configuration fields so
project-based and multi-field providers no longer pretend every remote
provider is configured by one API key.
- Moved shared Google request quirks out of the Gemini adapter,
preserved AI Studio behavior, and bumped the package to `4.11.0`.

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR adds Google Vertex AI as a new provider using Application
Default Credentials. The main changes are:

- New `vertex` provider with project/location endpoint construction.
- Renewable ADC access-token loading with refresh coalescing and
proxy-aware refresh.
- Native Vertex publisher-model discovery with pagination and response
validation.
- Shared Google OpenAI-compatible request behavior for Gemini and
Vertex.
- Admin UI, settings, smoke config, docs, version, lockfile, and tests
for the new provider.
</details>

<h3>Confidence Score: 5/5</h3>

Safe to merge with low risk.

No blocking correctness or security issues were identified. The new
provider follows the existing provider-runtime and Admin configuration
patterns. Endpoint, auth, model parsing, readiness, docs, version,
lockfile, and tests are updated together.

No files require special attention.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- The T-Rex test suite was executed to validate the code-execution
proof-of-work, generating a full verbose pytest log and recording the
run metadata, and the run completed with EXIT\_CODE: 0.

<a
href="https://app.greptile.com/trex/runs/14991235/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| src/free_claude_code/providers/vertex/client.py | Adds the Vertex
provider with OpenAI-compatible chat routing and native paginated model
discovery. |
| src/free_claude_code/providers/vertex/auth.py | Implements renewable
ADC token loading, proxy-aware refresh, coalescing, and sanitized auth
failures. |
| src/free_claude_code/providers/vertex/endpoint.py | Builds validated
Vertex global/regional service, chat, and model-list endpoints. |
| src/free_claude_code/providers/vertex/models.py | Parses Vertex
publisher-model pages into OpenAI-compatible model IDs with
malformed-response checks. |
| src/free_claude_code/providers/google_openai/provider.py | Adds shared
Google thought-signature caching and thinking-budget request body
handling. |
| src/free_claude_code/providers/google_openai/quirks.py | Renames
Gemini-specific quirks to shared Google quirks and exposes model-neutral
thinking config helpers. |
| src/free_claude_code/providers/openai_chat/provider.py | Allows
OpenAI-chat providers to pass an async API-key callback into the OpenAI
SDK. |
| src/free_claude_code/providers/runtime/discovery.py | Uses
descriptor-defined readiness to choose providers eligible for model
cache/discovery. |
| src/free_claude_code/config/provider_catalog.py | Adds the Vertex
descriptor and required settings metadata, and makes Cloudflare
readiness require both token and account ID. |
| src/free_claude_code/config/admin/status.py | Generalizes Admin
provider readiness status to use each descriptor's configuration
attributes. |
| src/free_claude_code/config/admin/provider_manifest.py | Adds Admin UI
fields for Vertex project and location alongside generated provider
fields. |
| tests/providers/test_vertex.py | Adds targeted tests for Vertex
endpoints, ADC token refresh, reasoning mapping, and model discovery
pagination. |

</details>

<details open><summary><h3>Sequence Diagram</h3></summary>

<a href="#gh-light-mode-only">

```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User as User / Admin UI
participant Settings as Settings + Provider Catalog
participant Runtime as Provider Runtime
participant Vertex as VertexProvider
participant ADC as Google ADC
participant OpenAI as OpenAI-compatible Chat Endpoint
participant Models as Vertex Publisher Models API

User->>Settings: Set VERTEX_PROJECT_ID / VERTEX_LOCATION / VERTEX_PROXY
Settings->>Runtime: Descriptor reports vertex configured by project id
Runtime->>Vertex: Construct with project, location, proxy, rate limiter
Vertex->>ADC: Load/refresh Application Default Credentials
ADC-->>Vertex: Renewable access token
Vertex->>OpenAI: Stream chat completion with bearer token + x-goog-user-project
OpenAI-->>Vertex: Streaming chat chunks
Vertex-->>Runtime: Normalized provider stream
Runtime->>Vertex: Refresh model list
Vertex->>Models: GET paginated publishers/google/models
Models-->>Vertex: publisherModels + nextPageToken
Vertex-->>Runtime: Prefixed model IDs for cache/model picker
```

</a>
<a href="#gh-dark-mode-only">

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User as User / Admin UI
participant Settings as Settings + Provider Catalog
participant Runtime as Provider Runtime
participant Vertex as VertexProvider
participant ADC as Google ADC
participant OpenAI as OpenAI-compatible Chat Endpoint
participant Models as Vertex Publisher Models API

User->>Settings: Set VERTEX_PROJECT_ID / VERTEX_LOCATION / VERTEX_PROXY
Settings->>Runtime: Descriptor reports vertex configured by project id
Runtime->>Vertex: Construct with project, location, proxy, rate limiter
Vertex->>ADC: Load/refresh Application Default Credentials
ADC-->>Vertex: Renewable access token
Vertex->>OpenAI: Stream chat completion with bearer token + x-goog-user-project
OpenAI-->>Vertex: Streaming chat chunks
Vertex-->>Runtime: Normalized provider stream
Runtime->>Vertex: Refresh model list
Vertex->>Models: GET paginated publishers/google/models
Models-->>Vertex: publisherModels + nextPageToken
Vertex-->>Runtime: Prefixed model IDs for cache/model picker
```

</a>
</details>

<sub>Reviews (1): Last reviewed commit: ["feat: add Google Vertex AI
provider"](https://github.com/alishahryar1/free-claude-code/commit/97e753f0772e60377865876ca59b2fd8888d922e)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=45405432)</sub>

<!-- /greptile_comment -->
2026-07-18 21:45:07 -07:00
Ali Khokhar af658287bd Add Amazon Bedrock Mantle support (#1192)
## Problem

FCC cannot route coding-agent requests through Amazon Bedrock even
though Bedrock Mantle exposes an OpenAI-compatible streaming Chat
Completions API. Users currently need a separate compatibility layer,
and FCC has no catalog, Admin UI, model-discovery, or smoke-test
contract for Bedrock. Fixes #863.

## Changes

| Before | After |
| --- | --- |
| Amazon Bedrock was absent from provider routing. | `bedrock/` uses the
existing OpenAI Chat provider with AWS's [Bedrock Mantle
endpoint](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-chat-completions-mantle.html).
|
| Bedrock integration would have implied a new AWS-native transport. |
The ordinary profile owns streaming, tools, retries, and `/models`
discovery without boto3, SigV4, Converse, or Invoke machinery. |
| FCC had no Bedrock authentication or regional endpoint configuration.
| `AWS_BEARER_TOKEN_BEDROCK`, `BEDROCK_BASE_URL`, and `BEDROCK_PROXY`
are available through environment and Admin UI configuration, with the
current `us-east-1` Mantle URL as the default. |
| Heterogeneous Bedrock models had no safe provider-wide reasoning
control. | FCC replays prior reasoning through portable think tags and
leaves model-specific reasoning parameters upstream-owned. |
| Smoke configuration duplicated credential checks for every provider. |
Smoke configuration reads primary credentials and configurable endpoints
from the provider catalog, retaining only Cloudflare's two-field
exception. |
| Bedrock behavior had no deterministic coverage or release
documentation. | Provider requests, regional URL normalization, model
discovery, Admin persistence, smoke selection, README usage,
architecture boundaries, and version 4.10.0 cover the new capability. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR adds Amazon Bedrock Mantle as an OpenAI-compatible provider. The
main changes are:

- Bedrock catalog, settings, proxy, and regional base-URL configuration.
- OpenAI Chat routing with portable reasoning replay and model
discovery.
- Admin UI fields and configuration persistence.
- Catalog-driven smoke configuration and Bedrock smoke coverage.
- Provider documentation and a version bump to 4.10.0.
</details>

<h3>Confidence Score: 5/5</h3>

The provider flow looks mergeable after handling an explicitly empty
Bedrock base URL.

Catalog, runtime, Admin, and smoke wiring are consistent. Regional URLs
with or without `/v1` are normalized correctly.

src/free_claude_code/config/settings.py: an empty `BEDROCK_BASE_URL` can
still create a client with an invalid endpoint.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- Before the change, bedrock was rejected as an unknown provider with
exit code 1.
- After the change, the fake service captured the normalized URL, Bearer
trex...oken, portable Chat Completions JSON, one tool, think-tag
history, and no reasoning\_effort, reasoning, or thinking fields; exit
code 0.
- Focused pytest validation completed with 6/6 passing tests.

<a
href="https://app.greptile.com/trex/runs/14988686/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| src/free_claude_code/config/provider_catalog.py | Adds the Bedrock
provider descriptor, regional default endpoint, credential mapping, and
proxy metadata. |
| src/free_claude_code/config/settings.py | Adds Bedrock settings, but
an explicitly empty base URL bypasses the regional default. |
| src/free_claude_code/providers/openai_chat/profiles.py | Registers
Bedrock with URL normalization, think-tag replay, and no provider-wide
reasoning parameter. |
| src/free_claude_code/config/admin/provider_manifest.py | Generalizes
provider base-URL fields and adds Bedrock-specific labels and help text.
|
| smoke/lib/config.py | Adds Bedrock smoke defaults and replaces
provider-specific checks with catalog-driven configuration checks. |
| tests/providers/test_bedrock.py | Covers Bedrock URL normalization,
request fields, reasoning replay, tool calls, and model discovery. |

</details>

<details open><summary><h3>Flowchart</h3></summary>

<a href="#gh-light-mode-only">

```mermaid
%%{init: {'theme': 'neutral'}}%%
flowchart LR
Config[Environment or Admin config] --> Settings[Settings]
Catalog[Provider catalog] --> Runtime[Provider runtime]
Settings --> Runtime
Runtime --> Profile[Bedrock OpenAI Chat profile]
Profile --> Client[AsyncOpenAI client]
Client --> Mantle[Regional Bedrock Mantle endpoint]
Catalog --> Admin[Admin manifest]
Catalog --> Smoke[Smoke selection]
```

</a>
<a href="#gh-dark-mode-only">

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart LR
Config[Environment or Admin config] --> Settings[Settings]
Catalog[Provider catalog] --> Runtime[Provider runtime]
Settings --> Runtime
Runtime --> Profile[Bedrock OpenAI Chat profile]
Profile --> Client[AsyncOpenAI client]
Client --> Mantle[Regional Bedrock Mantle endpoint]
Catalog --> Admin[Admin manifest]
Catalog --> Smoke[Smoke selection]
```

</a>
</details>

<a
href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22ali%2Fadd-bedrock-mantle%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22ali%2Fadd-bedrock-mantle%22.%0A%0AFix%20the%20following%201%20code%20review%20issue.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%201%0Asrc%2Ffree_claude_code%2Fconfig%2Fsettings.py%3A60-63%0A**Empty%20Override%20Bypasses%20Default%20URL**%0A%0AWhen%20%60BEDROCK_BASE_URL%60%20is%20present%20but%20empty%2C%20settings%20keep%20the%20empty%20string%20instead%20of%20using%20%60BEDROCK_DEFAULT_BASE%60.%20Clearing%20this%20field%20through%20environment%20or%20Admin%20configuration%20therefore%20builds%20the%20Bedrock%20client%20with%20an%20invalid%20base%20URL%2C%20and%20Bedrock%20requests%20and%20model%20discovery%20fail%20instead%20of%20using%20the%20documented%20default.%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1192&platform=github"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodexDark.svg?v=6"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"><img
alt="Fix All in Codex"
src="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"></picture></a>

<sub>Reviews (1): Last reviewed commit: ["Add Amazon Bedrock Mantle
provider"](https://github.com/alishahryar1/free-claude-code/commit/f40b539c99c9f6a888762b8da69d5a738a4f4d70)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=45400300)</sub>

> Greptile also left **1 inline comment** on this PR.

<!-- /greptile_comment -->
2026-07-18 20:29:41 -07:00
Ali Khokhar b89e849fff Add Kimi Code subscription support (#1183)
## Problem

FCC's existing `kimi` provider targets Kimi Open Platform credits. Kimi
Code subscription keys use a separate coding-agent endpoint, so
subscribers cannot currently use their plan or select its K3 and coding
models. Fixes #1161.

## Changes

| Before | After |
| --- | --- |
| `KIMI_API_KEY` was the only Kimi contract and routed to the
credit-based API platform. | `KIMI_API_KEY` remains unchanged, while
`KIMI_CODE_API_KEY` routes the separate [Kimi Code
subscription](https://www.kimi.com/code/docs/en/) through
`https://api.kimi.com/coding/v1`. |
| OpenAI-chat profiles could not declare an upstream client identity. |
The Kimi Code profile sends an honest `free-claude-code` user agent as
required by [Kimi's integration
policy](https://www.kimi.com/code/docs/en/kimi-code/community-guidelines.html),
without adding a specialized provider class. |
| FCC's fallback output limit and generic token field would override
Kimi's default when the client omitted a limit. | Explicit client limits
become `max_completion_tokens`; omitted limits remain upstream-owned,
and learned cap recovery still handles model-specific rejections. |
| Kimi Code reasoning and history had no provider contract. | The
profile maps FCC intent to Kimi's documented `low`, `high`, `max`, and
`none` efforts and replays prior thinking through `reasoning_content`,
with no model-name branching. |
| Admin, model discovery, and smoke coverage knew only the credit-based
Kimi provider. | Catalog-derived Admin fields, `/models` discovery,
README setup, smoke configuration, and deterministic provider/runtime
contracts cover `kimi_code`; the release is bumped to 4.9.0. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR adds Kimi Code subscription support as a separate provider. The
main changes are:

- Adds dedicated API key, proxy, endpoint, and Admin settings.
- Adds Kimi-specific reasoning, token-limit, history, and user-agent
behavior.
- Extends model discovery and smoke configuration for `kimi_code`.
- Adds provider contract tests and updates documentation.
- Bumps the package and lockfile version to 4.9.0.
</details>

<h3>Confidence Score: 5/5</h3>

This looks safe to merge.

No blocking issues found in the changed code.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- The contract validation compared the Kimi code HTTP flow before and
after the change and confirmed the after state exits with code 0 and
includes Bearer authentication, User-Agent: free-claude-code, model
discovery, max\_completion\_tokens, Kimi reasoning effort max,
reasoning\_content replay, and omission of token/reasoning fields when
unspecified.
- Focused tests for the Kimi code HTTP flow were run, and 88 tests
passed with exit code 0.
- Artifacts document both the initial failure scenario and the
successful post-change state, along with the focused tests results.

<a
href="https://app.greptile.com/trex/runs/14945625/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| src/free_claude_code/config/provider_catalog.py | Registers Kimi Code
with its dedicated credential, endpoint, and proxy setting. |
| src/free_claude_code/config/settings.py | Adds environment-backed
fields for the Kimi Code subscription key and proxy. |
| src/free_claude_code/providers/openai_chat/__init__.py | Passes an
optional profile user agent into the shared OpenAI-compatible client. |
| src/free_claude_code/providers/openai_chat/profiles.py | Defines Kimi
Code reasoning, token-limit, history replay, extra-body, and user-agent
behavior. |
| smoke/lib/config.py | Adds Kimi Code configuration detection and its
default smoke model. |
| tests/providers/test_kimi_code.py | Covers the new endpoint, headers,
request mapping, reasoning behavior, and model discovery. |

</details>

<sub>Reviews (1): Last reviewed commit: ["Add Kimi Code subscription
provider"](https://github.com/alishahryar1/free-claude-code/commit/dfc66f2755e5885775a77f5c91b4b9a82eb8fd1d)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=45309322)</sub>

<!-- /greptile_comment -->
2026-07-18 04:10:02 -07:00
Ali Khokhar 6455c63e1d Make reasoning policy provider-neutral and client-aware (#1148)
## Problem

FCC reduced reasoning to global and route booleans, mixing client
intent, configuration, provider wire capabilities, output visibility,
and history replay. That discarded named client efforts, encouraged
model-name checks, and made provider behavior inconsistent.

## Changes

| Before | After |
| --- | --- |
| Admin exposed global and route thinking toggles. | Admin exposes
**Off**, **From client**, **Low**, **Medium**, **High**, **X-High**, and
**Max**; Fable, Opus, Sonnet, and Haiku also expose **Inherit**. |
| Request intent was repeatedly reduced to a boolean across routing and
providers. | The application boundary resolves one immutable
`ReasoningPolicy` with independent control, named effort, and exact
positive token budget. |
| Provider adapters could infer reasoning behavior from upstream model
names or versions. | Provider profiles translate only documented
provider-wide wire capabilities; architecture and contributor rules
prohibit model-specific reasoning branches. |
| Gateway reasoning controls were ad hoc. |
[OpenRouter](https://openrouter.ai/docs/guides/best-practices/reasoning-tokens)
and [Vercel AI
Gateway](https://vercel.com/docs/ai-gateway/models-and-providers) use
documented reasoning objects, including exact budgets where
representable. |
| Named effort forwarding was inconsistent or absent. |
[Gemini](https://ai.google.dev/gemini-api/docs/openai),
[Ollama](https://docs.ollama.com/api/openai-compatibility), [LM
Studio](https://lmstudio.ai/changelog/lmstudio-v0.4.8),
[Fireworks](https://docs.fireworks.ai/guides/querying-text-models/reasoning),
[Cohere](https://docs.cohere.com/docs/compatibility-api),
[Wafer](https://docs.wafer.ai/serverless/api-reference),
[Groq](https://console.groq.com/docs/reasoning),
[Cerebras](https://inference-docs.cerebras.ai/capabilities/reasoning),
[SambaNova](https://docs.sambanova.ai/docs/api-reference/chat-completions/create-chat-based-completion),
and
[Mistral](https://docs.mistral.ai/studio-api/conversations/reasoning)
receive their documented named vocabularies with explicit provider-owned
downgrades. |
| Boolean thinking controls were mixed into shared conversion. |
[DeepSeek](https://api-docs.deepseek.com/guides/thinking_mode/),
[Kimi](https://platform.kimi.ai/docs/guide/use-kimi-k2-thinking-model),
[Z.ai](https://docs.z.ai/guides/capabilities/thinking-mode), [Cloudflare
Workers
AI](https://developers.cloudflare.com/changelog/post/2026-04-20-kimi-k2-6-workers-ai/),
and [NVIDIA
NIM](https://docs.nvidia.com/nim/large-language-models/1.15.0/thinking-budget-control.html)
use provider-owned thinking-object or chat-template controls. |
| Effort names and output limits could become fabricated reasoning
budgets. | Exact budgets remain exact and are forwarded only through
documented fields for OpenRouter, Fireworks, LM Studio, NIM, and
[llama.cpp](https://github.com/ggml-org/llama.cpp/blob/master/tools/server/README.md);
named efforts and output limits are never converted into token budgets.
|
| New-turn reasoning and prior-turn replay shared one switch. | Every
profile independently declares native reasoning replay, `<think>` tag
replay, provider-specific replay, or no replay; **Off** suppresses new
reasoning output without corrupting required history. |
| Providers without a stable generic compute control received guessed
controls. |
[MiniMax](https://platform.minimax.io/docs/api-reference/text-openai-api)
requests split output only, while [GitHub
Models](https://docs.github.com/en/rest/models/inference), [Hugging Face
Inference
Providers](https://huggingface.co/docs/inference-providers/en/tasks/chat-completion),
Codestral, and OpenCode keep provider defaults and use only their
explicit replay profile. |
| OpenAI Responses effort became a lossy Anthropic thinking boolean. |
Responses preserves `reasoning.effort` through `output_config`, then
resolves it through the same application policy as Messages without
inventing a budget. |
| Legacy booleans remained the persisted contract. | FCC-owned dotenv
files migrate to typed `REASONING_*` values, explicit env files receive
an actionable warning, documentation describes the ownership boundary,
and the package advances to 4.8.0. |
| Reasoning behavior was covered by scattered boolean assertions. | New
policy, routing, encoder, provider, Admin, migration, Responses, and
smoke contracts pass all five local CI checks: 2,368 tests passed, 40
skipped; 92 smoke tests collect and both live config migration checks
pass. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR makes reasoning policy client-aware and independent of provider
model names. The main changes are:

- Adds one immutable reasoning policy resolved at the application
boundary.
- Adds typed root and route reasoning settings with Admin UI support.
- Moves wire controls and history replay behavior into provider
profiles.
- Migrates owned dotenv files from legacy thinking booleans.
- Expands provider, routing, migration, API, and smoke coverage.
</details>

<h3>Confidence Score: 5/5</h3>

This looks safe to merge.

No blocking issues found in the changed code.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- Ran the contract-validation test suite with the specified test
modules, and the tests reported 78 passed in 1.53s with exit code 0.
- Reviewed the complete captured output artifact
reasoning-contract-02-after.log to verify the final test outcomes and
successful contract validation.

<a
href="https://app.greptile.com/trex/runs/14792858/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| src/free_claude_code/config/env_migrations.py | Migrates legacy
reasoning booleans in owned dotenv files and warns for explicit
environment files. |
| src/free_claude_code/application/reasoning.py | Resolves client
controls and configured preferences into one provider-neutral reasoning
policy. |
| src/free_claude_code/application/routing.py | Carries route-level
reasoning preferences into request-scoped policy resolution. |
| src/free_claude_code/providers/openai_chat/reasoning.py | Provides
shared provider encoders for reasoning controls and replay behavior. |

</details>

<sub>Reviews (2): Last reviewed commit: ["chore: release reasoning
controls as
4.8..."](https://github.com/alishahryar1/free-claude-code/commit/9d4be767f7dbdca5709474012f43dcdc6f4347e3)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=44984039)</sub>

<!-- /greptile_comment -->
2026-07-16 19:57:12 -07:00
Ali Khokhar b1877a4b21 Add Ollama Cloud as a first-class provider (#1106)
## Problem

FCC supports Ollama only through a local daemon, so users cannot
authenticate directly to Ollama Cloud or discover its hosted models from
the Admin UI. Ollama's OpenAI-compatible API also uses the standard
`reasoning` field instead of `reasoning_content`, which would otherwise
drop thinking output and tool-history reasoning.

## Changes

| Before | After |
| --- | --- |
| `ollama/...` requires a local Ollama server. | `ollama_cloud/...`
connects directly to `https://ollama.com/v1` with `OLLAMA_API_KEY`,
while local Ollama remains unchanged. |
| OpenAI-chat reasoning was hard-coded to `reasoning_content`. |
Provider profiles declare their reasoning field, so Ollama streams and
replays `reasoning` without a specialized transport. |
| Ollama Cloud was absent from configuration, model discovery, docs, and
smoke coverage. | The catalog, Admin UI, proxy setting, model picker,
README, smoke matrix, and `4.5.0` release metadata expose the provider
consistently. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR adds Ollama Cloud as a separate OpenAI-compatible provider. The
main changes are:

- New `ollama_cloud` catalog entry, settings, admin fields, proxy
setting, and smoke configuration.
- Provider profiles now choose the streamed and replayed reasoning field
per provider.
- Ollama Cloud uses `reasoning` and `reasoning_effort`, while local
Ollama stays on its separate local configuration.
- Streaming recovery now respects the resolved thinking setting when
collecting reasoning.
- Tests, docs, environment examples, and release metadata were updated
for the new provider.
</details>

<h3>Confidence Score: 5/5</h3>

This looks safe to merge.

No blocking issues found in the changed code.

No files need attention.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- Ran the provider/runtime/converter/streaming tests with full verbose
pytest output and confirmed EXIT\_CODE: 0.
- Ran the config/catalog/contracts/admin tests with full verbose pytest
output and confirmed EXIT\_CODE: 0.
- Generated and ran an introspection script to verify catalog, profile,
settings, and admin manifest values without external API calls, and
recorded the local execution output.

<a
href="https://app.greptile.com/trex/runs/14367965/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| src/free_claude_code/providers/openai_chat/profiles.py | Adds
provider-level reasoning field selection and the Ollama Cloud profile. |
| src/free_claude_code/providers/openai_chat/provider.py | Uses the
profile reasoning field for streaming and passes the thinking setting
into recovery. |
| src/free_claude_code/providers/openai_chat/request_policy.py | Selects
reasoning replay mode from the provider policy only when thinking is
enabled. |
| src/free_claude_code/core/anthropic/conversion.py | Supports replaying
assistant reasoning through either `reasoning_content` or `reasoning`. |
| src/free_claude_code/config/provider_catalog.py | Registers Ollama
Cloud as a remote provider distinct from local Ollama. |
| src/free_claude_code/config/settings.py | Adds the Ollama Cloud API
key and proxy settings. |

</details>

<sub>Reviews (3): Last reviewed commit: ["Keep local Ollama wire
behavior
unchange..."](https://github.com/alishahryar1/free-claude-code/commit/d6f97cdb0074a4cbda140d484fb6dd679a1406df)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=44089262)</sub>

<!-- /greptile_comment -->
2026-07-14 02:48:03 -07:00
Ali Khokhar 4f56a6aa17 Add Fable as a first-class Claude routing tier (#1099)
## Problem

Claude Code now sends `claude-fable-5` for the Fable alias, but FCC
treated it as an unrecognized model and collapsed it into the global
fallback route. Users could not map Fable traffic or reasoning behavior
independently. Fixes #1097.

## Changes

| Before | After |
| --- | --- |
| Fable requests inherited `MODEL` and `ENABLE_MODEL_THINKING`. | Fable
requests use `MODEL_FABLE` and `ENABLE_FABLE_THINKING` when configured,
otherwise inherit the existing defaults. |
| `/v1/models` omitted Claude Fable 5. | `/v1/models` advertises the
canonical `claude-fable-5` identifier. |
| Admin, documentation, validation, and smoke contracts described three
Claude tiers. | Admin, documentation, validation, and smoke contracts
describe Fable alongside Opus, Sonnet, and Haiku. |
| The package version was `4.3.1`. | The package version is `4.4.0`. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR adds Fable as a Claude routing tier. The main changes are:

- `MODEL_FABLE` and `ENABLE_FABLE_THINKING` settings.
- Fable routing and thinking resolution in `ModelRouter`.
- `claude-fable-5` in the model catalog.
- Admin, docs, smoke, and test coverage updates.
- Package version bump to `4.4.0`.
</details>

<h3>Confidence Score: 4/5</h3>

The changed routing path needs a fix for direct provider model ids
containing `fable`.

Fable settings, validation, admin fields, and model listing are
consistent with the existing tier patterns. Blank Fable settings inherit
the existing defaults. Direct provider model ids can receive the Fable
thinking override when their model name contains `fable`.

src/free_claude_code/application/routing.py

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- Reproduced the Fable thinking overmatch by running a focused Python
repro that disables global thinking and enables Fable thinking, then
resolves sambanova/my-fable-ensemble-v2.
- The repro confirmed direct routing preserved provider\_id=sambanova,
provider\_model=my-fable-ensemble-v2, and
provider\_model\_ref=sambanova/my-fable-ensemble-v2, with
resolved\_thinking\_enabled and thinking\_enabled both true.
- Ran the fable-tier validation pytest, which finished with exit code 0
and 177 tests passed.
- Ran the runtime probe to exercise the API model list, Settings env
parsing, and ModelRouter paths, and observed a 200 OK on GET /v1/models,
with the catalog item id claude-fable-5 and the expected Fable vs
global-default routing behavior.
- Generated the probe source file used to exercise the API and Settings
paths, enabling repeatable validation without real provider credentials.

<a
href="https://app.greptile.com/trex/runs/14275379/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| src/free_claude_code/application/routing.py | Adds Fable model and
thinking branches; the thinking branch can also match unrelated direct
provider model ids containing `fable`. |
| src/free_claude_code/config/settings.py | Adds optional Fable model
and thinking settings with blank-env inheritance and provider/model
validation. |
| src/free_claude_code/config/model_refs.py | Includes Fable in
configured chat model reference collection and dedupe. |
| src/free_claude_code/config/admin/manifest.py | Adds Fable model and
thinking controls to the admin manifest. |
| src/free_claude_code/api/model_catalog.py | Adds `claude-fable-5` to
the advertised Claude model aliases. |
| pyproject.toml | Bumps the package version to `4.4.0`. |
| uv.lock | Updates the editable package version to match
`pyproject.toml`. |

</details>

<details open><summary><h3>Flowchart</h3></summary>

<a href="#gh-light-mode-only">

```mermaid
%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Incoming model name] --> B{Direct provider or gateway id?}
  B -- yes --> C[Use provider/model directly]
  C --> D[Resolve thinking from provider model string]
  B -- no --> E{Claude tier match}
  E -- Fable --> F[MODEL_FABLE or MODEL]
  E -- Opus/Sonnet/Haiku --> G[Tier override or MODEL]
  E -- None --> H[MODEL]
  D --> I[Provider request]
  F --> I
  G --> I
  H --> I
```

</a>
<a href="#gh-dark-mode-only">

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
  A[Incoming model name] --> B{Direct provider or gateway id?}
  B -- yes --> C[Use provider/model directly]
  C --> D[Resolve thinking from provider model string]
  B -- no --> E{Claude tier match}
  E -- Fable --> F[MODEL_FABLE or MODEL]
  E -- Opus/Sonnet/Haiku --> G[Tier override or MODEL]
  E -- None --> H[MODEL]
  D --> I[Provider request]
  F --> I
  G --> I
  H --> I
```

</a>
</details>

<a
href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22ali%2Fadd-fable-routing-tier%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22ali%2Fadd-fable-routing-tier%22.%0A%0AFix%20the%20following%201%20code%20review%20issue.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%201%0Asrc%2Ffree_claude_code%2Fapplication%2Frouting.py%3A134-135%0A**Fable%20Thinking%20Overmatches%20Models**%0A%0AWhen%20a%20direct%20provider%20request%20uses%20a%20model%20id%20like%20%60sambanova%2Fmy-fable-ensemble-v2%60%2C%20the%20direct%20route%20bypasses%20tier%20remapping%20but%20still%20calls%20%60_resolve_thinking%28%29%60%20with%20the%20provider%20model%20string.%20With%20%60ENABLE_FABLE_THINKING%60%20set%2C%20this%20substring%20check%20applies%20Fable%20thinking%20behavior%20to%20an%20unrelated%20provider%20model%2C%20changing%20the%20outgoing%20request%20shape%20just%20because%20the%20model%20id%20contains%20%60fable%60.%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1099&platform=github"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodexDark.svg?v=6"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"><img
alt="Fix All in Codex"
src="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"></picture></a>

<sub>Reviews (1): Last reviewed commit: ["Add Fable as a first-class
routing
tier"](https://github.com/alishahryar1/free-claude-code/commit/0705840c65511fd85c74fd2c62ba8ea97afe7c12)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43892323)</sub>

> Greptile also left **1 inline comment** on this PR.

<!-- /greptile_comment -->
2026-07-13 11:56:34 -07:00
Ali Khokhar f3ea35a777 Consolidate OpenAI-compatible provider adapters (#1069)
## Problem

Sixteen OpenAI-compatible providers were represented by
configuration-only subclasses and one factory function each. The sole
provider family also lived under a multi-transport namespace that no
longer described the codebase, while provider defaults, IDs, and
instance caching passed through redundant forwarding layers.

## Changes

| Before | After |
| --- | --- |
| Sixteen provider IDs used configuration-only subclasses. | Immutable
OpenAI-chat profiles configure one concrete provider while preserving
each provider's request policy. |
| Every provider required a dedicated factory function. | Generic
profile construction is the default; only eight adapters with real state
or algorithms retain factories. |
| The sole provider family lived under `providers/transports/`. |
`providers/openai_chat/` directly owns shared request, stream, recovery,
tool, and usage behavior. |
| Provider defaults and IDs passed through forwarding modules, and
constructors repeated fallback resolution. | The neutral catalog
resolves complete immutable provider configuration once. |
| `ProviderRuntime` wrapped a pass-through provider cache. |
`ProviderRuntime` directly owns lazy provider instances and cleanup. |
| Production carried the duplicated adapter structure. | The final shape
removes a net 873 production lines with no compatibility shim or
customer-facing provider change. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR consolidates OpenAI-compatible providers behind shared profiles
and runtime construction. The main changes are:

- OpenAI-chat behavior moved into `providers/openai_chat`.
- Configuration-only provider subclasses replaced by immutable profiles.
- Provider runtime now owns lazy instance caching and cleanup directly.
- Provider defaults and IDs now resolve through the neutral catalog.
- Tests and smoke helpers updated for the new provider shape.
</details>


<h3>Confidence Score: 5/5</h3>

This looks safe to merge.

No blocking issues found in the changed code.

No files need attention.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- T-Rex produced a proof for a posted P1 finding and linked it to the
corresponding review comment for details.
- T-Rex saved contract-validation logs for provider consolidation and
preserved four log files that show the test hanging boundary and the
timeout exit code 124.

<a
href="https://app.greptile.com/trex/runs/14125428/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>


<details open><summary><h3>Important Files Changed</h3></summary>




| Filename | Overview |
|----------|----------|
| src/free_claude_code/providers/runtime/config.py | Builds resolved
provider configuration from catalog descriptors, including static
credentials for local providers. |
| src/free_claude_code/providers/openai_chat/provider.py | Creates
shared OpenAI-chat clients from resolved configuration and immutable
provider profiles. |
| src/free_claude_code/providers/openai_chat/profiles.py | Defines
declarative profiles for formerly configuration-only OpenAI-compatible
adapters. |

</details>


<!-- greptile_failed_comments -->
<h3>Comments Outside Diff (2)</h3>

1. General comment 

<a href="#"><img alt="P1"
src="https://greptile-static-assets.s3.amazonaws.com/badges/p1.svg?v=9"
align="top"></a> **NIM OpenAI-compatible 504 exhausted streaming retry
path hangs instead of completing with the expected user-facing error**

   - **Bug**
- The broader provider consolidation suite failed all parametrized
`test_nim_stream_openai_5xx_exhausted_emits_user_message` cases under
xdist with worker crashes. A serial isolation run narrowed this to the
same OpenAI-compatible NIM exhausted 5xx streaming path: 500, 502, and
503 completed, but the 504 case did not finish before the explicit 120s
timeout, producing exit code 124. This contradicts the expected
streaming retry contract that exhausted transient provider failures
terminate and emit the configured user-facing error.
   - **Cause**
- The OpenAI-compatible streaming retry/exhaustion path for NIM 504
responses appears to wait indefinitely or otherwise fail to terminate
after retries are exhausted. The exact code-level loop/await point was
not isolated within the validation budget, but the failure is anchored
to the provider streaming retry contract exercised by
`tests/providers/test_openai_compat_5xx_retry.py::test_nim_stream_openai_5xx_exhausted_emits_user_message[504-temporarily
unavailable]`.
   - **Fix**
- Inspect the OpenAI-compatible/NIM streaming retry exhaustion handling
for 504 responses and ensure retry limits are enforced, the async stream
is closed/cancelled on exhaustion, and the provider raises/emits the
same terminal user-facing error contract as the 500/502/503 cases. Add
or keep a serial regression test for the 504 exhausted stream path to
prevent hangs.

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>

2. General comment 

<a href="#"><img alt="P1"
src="https://greptile-static-assets.s3.amazonaws.com/badges/p1.svg?v=9"
align="top"></a> **OpenAI-compatible 5xx retry suite hangs on exhausted
502 retry path**

   - **Bug**
- The recommended non-xdist retry validation does not complete. A
verbose rerun with a 60 second timeout shows the suite passes tests
through the exhausted 500 case, then times out while running
`test_nim_stream_openai_5xx_exhausted_emits_user_message[502-temporarily
unavailable]`. This indicates the consolidated OpenAI-compatible
provider retry/error path can hang for at least the 502 exhausted-error
scenario, preventing reliable validation and potentially blocking
callers from receiving the expected `ExecutionFailure`.
   - **Cause**
- The OpenAI-compatible provider's exhausted 502 retry/error handling
path appears not to terminate promptly under the mocked repeated
`openai.InternalServerError` scenario. The exact code location was not
changed during validation, but the failure is isolated to the shared
OpenAI-chat 5xx retry behavior exercised by
`NvidiaNimProvider.stream_response`.
   - **Fix**
- Debug the shared OpenAI-chat retry loop/error classification for 502
responses. Ensure retries are bounded, patched `asyncio.sleep` is
awaited without real backoff during tests, and exhausted 502/503/504
errors consistently raise `ExecutionFailure` with the expected
temporary-unavailable message instead of continuing work indefinitely.

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>

<!-- /greptile_failed_comments -->

<sub>Reviews (2): Last reviewed commit: ["Prove local provider
credential
resoluti..."](https://github.com/alishahryar1/free-claude-code/commit/ba226d97efdae1889bea0372c7bacf268122d65c)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43580983)</sub>

<!-- /greptile_comment -->
2026-07-11 19:55:19 -07:00
Ali Khokhar 3a7e0ccf7a Remove the native Anthropic provider transport (#1067)
## Problem

Ollama and llama.cpp still used a parallel native Anthropic transport
after the other providers moved to OpenAI Chat. That kept duplicate
request, SSE, recovery, model-list, and server-tool policy machinery
alive.

## Changes

| Before | After |
| --- | --- |
| Ollama and llama.cpp streamed through provider-specific Anthropic
`/messages` adapters. | Ollama and llama.cpp use the shared OpenAI Chat
transport. |
| Native request serialization, SSE normalization, error mapping, and
recovery remained beside the OpenAI path. | Native-only machinery is
removed and all providers share one transport lifecycle. |
| Routed models carried a capability object solely to permit native
server-tool passthrough. | Routing carries only route decisions; FCC
handles forced server tools locally and rejects lossy passthrough. |
| Ollama discovery used a separate `/api/tags` parser and rejected `/v1`
configuration. | Ollama discovery uses `/v1/models` and accepts either
root or `/v1` base URLs. |
| Obsolete native tests and a compatibility facade kept deleted
internals represented. | Tests cover the shared transport and real
Ollama product path without compatibility shims. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR removes the native Anthropic transport path for local providers.
The main changes are:

- Ollama and llama.cpp now use the shared OpenAI Chat transport.
- Local provider base URLs are normalized to the OpenAI-compatible `/v1`
API root.
- Ollama discovery now uses the OpenAI-compatible model-listing path.
- Native Anthropic transport code and server-tool passthrough capability
metadata were removed.
- Tests and smoke coverage were updated for the shared transport path.
</details>


<h3>Confidence Score: 5/5</h3>

This looks safe to merge.

No blocking issues found in the changed code.

None.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- Ran the targeted local provider pytest slice and observed exit code 0.
- Executed the generated runtime harness to emulate the provider HTTP
interactions and capture a request trace.
- Validated the request trace showed two GET /v1/models calls authorized
as Bearer ollama for root and /v1 base URL configurations, and a POST
/v1/chat/completions authorized as Bearer llamacpp with streaming OpenAI
chat JSON payload.
- Confirmed the exact generated harness script used for the runtime
proof is the harness file referenced in the artifacts.

<a
href="https://app.greptile.com/trex/runs/14121848/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>


<details open><summary><h3>Important Files Changed</h3></summary>




| Filename | Overview |
|----------|----------|
| src/free_claude_code/providers/transports/openai_chat/base_url.py |
Adds a helper that normalizes local OpenAI-compatible server roots to
`/v1`. |
| src/free_claude_code/providers/llamacpp/client.py | Moves llama.cpp to
the shared OpenAI Chat transport with local base URL normalization. |
| src/free_claude_code/providers/ollama/client.py | Moves Ollama to the
shared OpenAI Chat transport with local base URL normalization. |
| src/free_claude_code/api/handlers/messages.py | Applies server-tool
rejection through the shared request policy instead of provider
passthrough metadata. |
| src/free_claude_code/application/routing.py | Removes provider
capability metadata from routed model results. |

</details>


<!-- greptile_failed_comments -->
<h3>Comments Outside Diff (1)</h3>

1. `src/free_claude_code/api/handlers/messages.py`, line 261-267
([link](https://github.com/alishahryar1/free-claude-code/blob/3c7ff176da46560c4d27b3846dca1ab1c7db561c/src/free_claude_code/api/handlers/messages.py#L261-L267))

<a href="#"><img alt="P2"
src="https://greptile-static-assets.s3.amazonaws.com/badges/p2.svg?v=9"
align="top"></a> **Native Server Tools Always Reject**

With the passthrough capability check removed, Ollama and llama.cpp
requests that previously used their native Anthropic transport for
`web_search` or `web_fetch` are rejected before provider execution. The
default `ENABLE_WEB_SERVER_TOOLS=false` now makes forced server-tool
requests return an invalid-request error instead of reaching the local
provider path that used to support them.

<a
href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22ali%2Fremove-native-anthropic-transport%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22ali%2Fremove-native-anthropic-transport%22.%0A%0AThis%20is%20a%20comment%20left%20during%20a%20code%20review.%0APath%3A%20src%2Ffree_claude_code%2Fapi%2Fhandlers%2Fmessages.py%0ALine%3A%20261-267%0A%0AComment%3A%0A**Native%20Server%20Tools%20Always%20Reject**%0A%0AWith%20the%20passthrough%20capability%20check%20removed%2C%20Ollama%20and%20llama.cpp%20requests%20that%20previously%20used%20their%20native%20Anthropic%20transport%20for%20%60web_search%60%20or%20%60web_fetch%60%20are%20rejected%20before%20provider%20execution.%20The%20default%20%60ENABLE_WEB_SERVER_TOOLS%3Dfalse%60%20now%20makes%20forced%20server-tool%20requests%20return%20an%20invalid-request%20error%20instead%20of%20reaching%20the%20local%20provider%20path%20that%20used%20to%20support%20them.%0A%0AHow%20can%20I%20resolve%20this%3F%20If%20you%20propose%20a%20fix%2C%20please%20make%20it%20concise.&repo=alishahryar1%2Ffree-claude-code&pr=1067&platform=github"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixInCodexDark.svg?v=6"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixInCodex.svg?v=6"><img
alt="Fix in Codex"
src="https://greptile-static-assets.s3.amazonaws.com/badges/FixInCodex.svg?v=6"></picture></a>
<!-- /greptile_failed_comments -->

<sub>Reviews (2): Last reviewed commit: ["Normalize local OpenAI v1 base
URLs"](https://github.com/alishahryar1/free-claude-code/commit/2355eac247a6e411f89a781f46e784636ced98d6)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43572841)</sub>

<!-- /greptile_comment -->
2026-07-11 17:53:42 -07:00
Ali Khokhar d428b5904a Replace historical architecture tests with declarative boundaries (#1050)
## Problem

Architecture contracts mixed real dependency rules with deleted-module
tombstones and exact internal file inventories. Correct refactors
therefore had to preserve history instead of the current ownership
model.

## Changes

| Before | After |
| --- | --- |
| Cross-package rules were duplicated across narrow source and layout
assertions. | One least-privilege matrix and AST scanner enforce every
production package edge. |
| Bare imports, undeclared ownership roots, and module cycles could
escape generic enforcement. | Namespaced imports, initialized owners,
exact exceptions, and an acyclic module graph are enforced. |
| Responses, messaging-tree, and optional dependency ownership relied on
scattered checks. | Facade use and lazy optional dependency owners are
declared and verified centrally. |
| The messaging facade re-exported workflow, persistence, and parsing
internals. | The messaging facade exposes only ingress values, platform
ports, and managed-session protocols. |
| Migration-era tests froze deleted modules and internal filenames. |
Customer contracts remain while obsolete tombstones and layout
inventories are removed. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR replaces historical architecture checks with declarative
import-boundary rules. The main changes are:

- Added a documented package dependency matrix and facade ownership
rules.
- Narrowed the messaging package facade to its supported extension
surface.
- Moved messaging tree consumers to the `messaging.trees` facade.
- Reworked architecture tests around AST scanning, optional dependency
owners, and acyclic imports.
- Bumped the package version and refreshed the lockfile.
</details>

<h3>Confidence Score: 5/5</h3>

This looks safe to merge.

No blocking issues found in the changed code.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- The architecture contracts tests were executed as part of the general
contract validation.
- The test run completed with exit code 0, indicating success.
- The pytest summary shows 26 tests passed in 3.99 seconds.
- An artifact log captures the exact command, working directory,
environment recreation output, and verbose test item names for audit.

<a
href="https://app.greptile.com/trex/runs/14085499/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| src/free_claude_code/messaging/__init__.py | Narrows the top-level
messaging exports to the documented supported extension types. |
| tests/contracts/test_import_boundaries.py | Replaces historical layout
checks with declarative import-boundary enforcement. |
| ARCHITECTURE.md | Documents the current dependency matrix, facade
boundaries, and optional dependency owners. |
| src/free_claude_code/messaging/node_event_pipeline.py | Uses the
messaging tree facade for `NodeClaim`. |
| src/free_claude_code/messaging/node_runner.py | Uses the messaging
tree facade for queue, snapshot, cancellation, and claim types. |

</details>

<sub>Reviews (2): Last reviewed commit: ["Enforce architecture with
declarative
im..."](https://github.com/alishahryar1/free-claude-code/commit/68508f3d2bad19d4d1b8a9ca5d181e1433db4d71)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43498975)</sub>

<!-- /greptile_comment -->
2026-07-11 03:25:01 -07:00
Ali Khokhar 701a394697 Make provider capabilities semantic and typed (#1047)
## Problem

Provider metadata mixed descriptive strings and transport-family names
with product policy. The Messages API had to know provider
implementation details to decide server-tool behavior, while locality
and thinking metadata had ambiguous owners.

## Changes

| Before | After |
| --- | --- |
| Provider descriptors exposed transport names and untyped capability
strings. | Provider descriptors expose an immutable semantic value
containing only locality and server-tool passthrough. |
| The Messages handler derived provider sets from transport families. |
`ResolvedModel` carries catalog capabilities and the handler asks the
resolved semantic policy. |
| Discovery, Admin, and smoke selection inferred locality from
credentials or string membership. | Discovery, Admin, and smoke
selection read the catalog-owned `local` capability. |
| Provider-wide thinking strings competed with discovered model
metadata. | `ProviderModelInfo.supports_thinking` remains the sole
per-model thinking authority. |
| Invalid mapped providers could become raw catalog lookup failures
during the migration. | Routing and provider construction share the
canonical typed unknown-provider error. |
| LM Studio smoke contracts described a native Anthropic transport. | LM
Studio smoke contracts describe its OpenAI-chat-backed Messages path. |
| Tests encoded transport identities as product behavior. | Tests prove
both directions of capability-versus-identity independence while
preserving existing wire behavior and diagnostics. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR moves provider policy from transport names to typed catalog
capabilities. The main changes are:

- Added immutable provider capability values for locality and
server-tool passthrough.
- Routed provider capabilities through `ResolvedModel` for Messages API
policy.
- Updated admin status, discovery, smoke config, docs, and tests to read
semantic capabilities.
- Centralized unknown-provider diagnostics for routing and provider
construction.
- Bumped the package version and lockfile to `3.4.22`.
</details>

<h3>Confidence Score: 5/5</h3>

This looks safe to merge.

No blocking issues found in the changed code.

None.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- The Pytest run for the provider capabilities changes was executed and
completed successfully, as shown by the log's EXIT\_CODE: 0.
- The Ruff linter run for the provider capabilities changes was executed
and completed successfully, as shown by the log's EXIT\_CODE: 0.
- The focused suite exercised the changed code paths via repository
tests rather than relying solely on static inspection.

<a
href="https://app.greptile.com/trex/runs/14074560/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| src/free_claude_code/config/provider_catalog.py | Replaces transport
and string capability metadata with typed immutable provider
capabilities. |
| src/free_claude_code/application/routing.py | Adds catalog
capabilities to resolved models and uses the shared unknown-provider
error. |
| src/free_claude_code/api/handlers/messages.py | Uses resolved semantic
capabilities to decide server-tool passthrough. |
| src/free_claude_code/config/admin/status.py | Classifies local
providers through the new catalog capability. |
| src/free_claude_code/providers/runtime/discovery.py | Uses typed
locality to decide which providers are discovered only when referenced.
|
| src/free_claude_code/application/errors.py | Adds a shared constructor
for canonical unknown-provider messages. |

</details>

<sub>Reviews (1): Last reviewed commit: ["Make provider capabilities
semantic and
..."](https://github.com/alishahryar1/free-claude-code/commit/b2732ef74d61c632ccae332a19aaa655f45a96e7)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43475337)</sub>

<!-- /greptile_comment -->
2026-07-10 22:48:47 -07:00
Ali Khokhar e22a38b2c2 Canonicalize provider failure and retry ownership (#1046)
## Problem

Provider SDK classification, retry policy, canonical failures, and
downstream wire errors shared exception types across layers. That
blurred ownership and let cleanup or provisional Responses tool failures
mask the real provider diagnostic.

## Changes

| Before | After |
| --- | --- |
| Provider failures carried Anthropic wire types and core code
classified OpenAI/httpx errors. | Protocol-neutral `ExecutionFailure`
values cross layers, providers classify SDK errors, and protocol
packages map wire types. |
| Provider adapters could author terminal wire events. | The HTTP commit
boundary selects non-2xx JSON or a protocol terminal event with one
ingress request ID. |
| Retry policy and diagnostic handling were spread across core and
provider modules. | Providers own the unchanged retry budgets while
neutral core utilities own bounded credential redaction. |
| Stream cleanup could replace an already-mapped provider failure. |
Cleanup records safe metadata and preserves the canonical failure,
status, and diagnostic. |
| An incomplete Responses tool could preempt a later provider failure. |
Tool-finalization errors remain provisional so canonical provider
failures take precedence. |
| Readiness failures reused provider exception types. |
Application-owned errors represent deterministic validation and
availability phases without terminal retry headers. |
| Legacy exception and recovery owners remained importable. | Obsolete
modules are deleted without shims, architecture rules enforce the
boundaries, and package version is 3.4.21. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR canonicalizes provider failure handling across the API boundary.
The main changes are:

- Adds protocol-neutral execution failure values and safe diagnostics.
- Moves SDK and HTTP failure classification into provider-owned policy.
- Lets Messages and Responses choose their own wire error payloads.
- Preserves canonical failures across stream cleanup and committed
stream failures.
- Makes incomplete Responses tool errors provisional until finalization.
</details>

<h3>Confidence Score: 5/5</h3>

This looks safe to merge.

No blocking issues found in the changed code.

No files need attention.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- Ran the API failure contract suite and related tests
(tests/api/test\_execution\_failure\_contract.py,
tests/core/test\_failure\_protocol\_mapping.py,
tests/providers/test\_execution\_failure\_boundary.py,
tests/providers/test\_failure\_policy.py); 48 passed in 3.36s.
- Ran the streaming boundaries tests including response streams, stream
recovery, and streaming errors; 70 passed in 5.36s.
- Ran the OpenAI responses tests; 20 passed in 4.42s.

<a
href="https://app.greptile.com/trex/runs/14071383/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| src/free_claude_code/providers/transports/http.py | Adds cleanup-safe
stream closing that preserves established outcomes. |
| src/free_claude_code/core/openai_responses/stream.py | Preserves
canonical execution failures when committed Responses streams fail. |
| src/free_claude_code/core/openai_responses/streaming/assembler.py |
Keeps malformed tool-call errors provisional so later provider failures
can win. |
| src/free_claude_code/core/failures.py | Defines neutral failure kinds
and exception-group lookup for execution failures. |

</details>

<sub>Reviews (2): Last reviewed commit: ["Preserve canonical outcomes in
grouped
a..."](https://github.com/alishahryar1/free-claude-code/commit/f57f21241dbe582985627ed4fb40734b2c656809)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43468297)</sub>

<!-- /greptile_comment -->
2026-07-10 21:33:50 -07:00
Ali Khokhar 4951983b5e Replace global runtime resources with explicit ownership (#1042)
## Problem

Provider, messaging, and transcription resources relied on
process-global state, leaving replacement, cancellation, and shutdown
ownership ambiguous. Separate server lifetimes could share
event-loop-bound resources or retain failed cleanup work.

## Changes

| Before | After |
| --- | --- |
| Provider clients found limiters through global singleton and scoped
registries. | Each provider instance receives and owns one explicitly
constructed limiter. |
| Messaging queues and voice pipelines relied on singleton or
module-global state. | Each platform owns its limiter and outbox, while
the application owns one injected transcriber. |
| Messaging shutdown mixed ingress, active work, delivery, and SDK
cleanup. | Application shutdown quiesces ingress, drains work, closes
delivery, then releases transcription and providers. |
| Cancelled or failed provider cleanup could be forgotten or treated as
complete. | The provider manager retains shielded generation and
unpublished-runtime cleanup until it succeeds. |
| Discord and Telegram startup tasks could outlive or poison runtime
readiness. | Platform runtimes observe long-lived tasks and retry only
independently repeatable lifecycle steps. |
| Constructor-captured security and diagnostic settings appeared
hot-applicable. | Admin marks those settings restart-required so applied
policy matches the running resource graph. |
| Lifecycle races lacked direct ownership coverage. | Deterministic
cancellation, retry, isolation, teardown, and live smoke contracts
protect the final ownership model. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR moves runtime resources from global state into explicitly owned
application objects. The main changes are:

- Provider generations own their rate limiters and cleanup tasks.
- Messaging platforms own their limiter, outbox, ingress, and delivery
lifecycle.
- Application shutdown now runs through ordered cleanup gates.
- Voice transcription is injected as an owned runtime resource.
- Admin config marks constructor-captured settings as restart-required.
</details>

<h3>Confidence Score: 4/5</h3>

The shutdown path needs a bounded cleanup result before merging.

Cleanup steps that hang never reach the retryable incomplete-shutdown
path. ASGI shutdown can remain stuck while waiting for an external SDK,
transcriber, workflow, or provider cleanup. The retry ownership model
works only after cleanup returns or raises.

src/free_claude_code/runtime/application.py

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- T-Rex ran the requested verification, but its local artifact
references were not uploaded.
- The validation run completed successfully with EXIT\_CODE: 0 and 62
tests passed in 3.91 seconds, using the command uv run pytest -vv
tests/runtime/test\_application\_runtime.py
tests/runtime/test\_provider\_manager.py
tests/providers/test\_provider\_runtime.py.

<a
href="https://app.greptile.com/trex/runs/14064214/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| src/free_claude_code/runtime/application.py | Refactors shutdown into
ordered retryable cleanup gates, but cleanup awaitables can still block
shutdown forever. |
| src/free_claude_code/runtime/asgi.py | Reports incomplete runtime
shutdown when `close()` returns false. |
| src/free_claude_code/runtime/provider_manager.py | Adds owned provider
cleanup retry state and shielded generation cleanup. |

</details>

<a
href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22refactor%2Fruntime-owned-resources%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22refactor%2Fruntime-owned-resources%22.%0A%0AFix%20the%20following%201%20code%20review%20issue.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%201%0Asrc%2Ffree_claude_code%2Fruntime%2Fapplication.py%3A59%0A**Cleanup%20Await%20Blocks%20Shutdown**%0A%0AWhen%20a%20platform%20SDK%20stop%2C%20workflow%20drain%2C%20transcriber%20close%2C%20or%20provider%20cleanup%20hangs%2C%20this%20helper%20waits%20forever%20and%20never%20returns%20%60False%60.%20ASGI%20shutdown%20stays%20stuck%20in%20%60runtime.close%28%29%60%20instead%20of%20reporting%20an%20incomplete%20shutdown%2C%20so%20the%20retained%20resource%20graph%20cannot%20be%20retried%20cleanly.%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1042&platform=github"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodexDark.svg?v=6"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"><img
alt="Fix All in Codex"
src="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"></picture></a>

<sub>Reviews (2): Last reviewed commit: ["Report incomplete runtime
shutdown to
AS..."](https://github.com/alishahryar1/free-claude-code/commit/338b2bd179c3875b15bbd52818dd04c780e5d46d)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43454593)</sub>

> Greptile also left **1 inline comment** on this PR.

**Context used:**

- Context used - CLAUDE.md
([source](https://app.greptile.com/alishahryar1/github/Alishahryar1/free-claude-code/-/custom-context?memory=d2fd24d8-0dec-4faf-8ee4-e085e215a2f8))

<!-- /greptile_comment -->
2026-07-10 18:46:50 -07:00
Ali Khokhar 71a78a0c5a Move runtime packages under src namespace (#1029)
## Problem

Runtime modules were published as generic top-level packages like `api`,
`cli`, and `providers`. That shape is fragile for PyPI packaging and
weakens explicit ownership boundaries.

## Changes

| Before | After |
| --- | --- |
| Runtime code lived in root-level packages. | Runtime code lives under
`src/free_claude_code/`. |
| Console scripts targeted top-level modules. | Console scripts target
namespaced modules. |
| Tests and smoke helpers imported old package roots. | Tests and smoke
helpers import `free_claude_code.*`. |
| Packaging listed six root packages. | Packaging builds the single
namespaced package. |
| Contracts allowed old root package directories. | Contracts require
the src namespace and reject old root imports. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR moves the runtime packages into the `src/free_claude_code`
namespace. The main changes are:

- Console scripts now point to `free_claude_code.*` entrypoints.
- Runtime imports, tests, and smoke helpers now use the namespaced
package.
- Packaging now builds the single `src/free_claude_code` package.
- Contract tests now reject old top-level runtime package roots and
imports.
</details>

<h3>Confidence Score: 5/5</h3>

This PR is safe to merge with minimal risk.

The changes are a broad but mostly mechanical namespace and
package-layout migration with updated packaging, tests, and contract
coverage.

No files require special attention.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- Reviewed the primary contract validation by examining the namespace
validation log, which documents the exact commands executed, the working
directory, exit codes, pytest output, wheel build output, install
output, and import/entrypoint resolution.
- Verified the wheel listing by inspecting the wheel listing artifact,
confirming the available wheel filenames for the namespace validation.
- Ran and inspected the isolated import/entrypoint validation harness
saved as package-installed-import-check.py to validate import resolution
and entrypoint exposure.
- Captured and noted the wheel filename record in
package-wheel-filename.txt to enable traceability of the observed
artifact.

<a
href="https://app.greptile.com/trex/runs/13810533/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| pyproject.toml | Updates packaging to build the single
`src/free_claude_code` package and retargets console scripts to
namespaced modules. |
| src/free_claude_code/config/env_template.py | Loads `.env.example`
from packaged resources with a source-checkout fallback after the
runtime package move. |
| src/free_claude_code/cli/entrypoints.py | Updates CLI entrypoint
imports to `free_claude_code.*` and continues to use the shared env
template loader. |
| src/free_claude_code/api/routes.py | Retargets API route dependencies
and handlers to the namespaced package without changing route behavior.
|
| src/free_claude_code/api/app.py | Updates app factory imports to the
namespaced package while preserving middleware, routers, and exception
handling. |
| src/free_claude_code/providers/runtime/factory.py | Updates lazy
provider factory imports to `free_claude_code.providers.*` under the new
package layout. |
| tests/contracts/test_import_boundaries.py | Adds contract coverage
requiring runtime packages to live under `src/free_claude_code` and
rejecting old top-level imports. |
| smoke/lib/child_process.py | Updates smoke child-process helpers to
import CLI entrypoints from the namespaced package. |
| README.md | Updates the project layout and extension guidance to refer
to `src/free_claude_code` and importable `free_claude_code.*` modules. |
| uv.lock | Reflects the package version bump associated with the
runtime packaging move. |

</details>

<details open><summary><h3>Sequence Diagram</h3></summary>

<a href="#gh-light-mode-only">

```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User as User / CLI
participant Script as Console script
participant Pkg as free_claude_code package
participant API as free_claude_code.api
participant Runtime as free_claude_code.providers.runtime
participant Provider as Provider adapter

User->>Script: run fcc-server / free-claude-code
Script->>Pkg: load free_claude_code.cli.entrypoints:serve
Pkg->>API: create FastAPI app and routes
API->>Runtime: resolve configured provider
Runtime->>Provider: instantiate namespaced adapter
Provider-->>Runtime: stream/model responses
Runtime-->>API: provider result
API-->>User: Anthropic/OpenAI-compatible response
```

</a>
<a href="#gh-dark-mode-only">

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User as User / CLI
participant Script as Console script
participant Pkg as free_claude_code package
participant API as free_claude_code.api
participant Runtime as free_claude_code.providers.runtime
participant Provider as Provider adapter

User->>Script: run fcc-server / free-claude-code
Script->>Pkg: load free_claude_code.cli.entrypoints:serve
Pkg->>API: create FastAPI app and routes
API->>Runtime: resolve configured provider
Runtime->>Provider: instantiate namespaced adapter
Provider-->>Runtime: stream/model responses
Runtime-->>API: provider result
API-->>User: Anthropic/OpenAI-compatible response
```

</a>
</details>

<sub>Reviews (2): Last reviewed commit: ["Fix documented package import
paths"](https://github.com/alishahryar1/free-claude-code/commit/bfa9f2704c45f3684da39657d5e13f3814e5d450)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=42950471)</sub>

<!-- /greptile_comment -->
2026-07-09 01:19:05 -07:00
Ali Khokhar 745c38cbbe Move cloud providers to OpenAI-chat transport
Move remote cloud providers onto the OpenAI-chat transport and keep native Anthropic transport local-provider only.
2026-07-07 23:02:31 -07:00
Ali Khokhar 0b86dd4ef8 Add GitHub Models provider (#989)
## Problem

FCC does not expose GitHub Models, so users with GitHub Models access
cannot route Claude, Codex, or messaging prompts through GitHub's hosted
model catalog.

## Changes

| Before | After |
| --- | --- |
| Provider catalog did not include GitHub Models. | Provider catalog
includes `github_models` with token, proxy, admin, smoke, and model
picker wiring. |
| Requests could not target GitHub Models inference. |
`providers/github_models` routes OpenAI-chat requests to
`https://models.github.ai/inference`. |
| Model discovery assumed provider `/models` compatibility. | GitHub
Models discovery uses the catalog API and advertises stream/tool-capable
models. |
| OpenAI-chat transport could not set provider default headers. |
OpenAI-chat transport accepts provider-owned default headers. |
| Docs and templates omitted GitHub Models setup. | README,
`.env.example`, and architecture docs document GitHub Models setup and
ownership. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR adds GitHub Models as a new provider. The main changes are:

- New `github_models` provider runtime, catalog, settings, and admin
wiring.
- OpenAI-chat transport support for provider-owned default headers.
- GitHub Models catalog discovery filtered to streaming and tool-capable
models.
- Smoke configuration, environment template, docs, and tests for the new
provider.
- Package version and lockfile updates for the new feature.
</details>

<h3>Confidence Score: 5/5</h3>

Safe to merge with low risk.

The provider is wired through runtime creation, catalog metadata,
settings, admin fields, smoke config, docs, version metadata, and
focused tests. No blocking correctness or security issues were found in
the changed paths.

No files require special attention.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- Before-change focused pytest run against HEAD^ showed no GitHub Models
provider tests were collected.
- After-change focused pytest run showed all 37 provider/runtime tests
passed.
- After-change harness output captured structured evidence for catalog
discovery and OpenAI-chat request routing, and the harness exited
successfully.
- A temporary harness Python script was generated to capture the mocked
request/response evidence.

<a
href="https://app.greptile.com/trex/runs/13317138/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| providers/github_models/client.py | Implements GitHub Models
OpenAI-chat transport wiring, default GitHub headers, and catalog-based
stream/tool-capable model discovery. |
| providers/transports/openai_chat/transport.py | Allows OpenAI-chat
providers to pass default headers into the shared AsyncOpenAI client. |
| config/provider_catalog.py | Registers GitHub Models provider
metadata, default inference base URL, credential, proxy, and
capabilities. |
| config/settings.py | Adds settings bindings for `GITHUB_MODELS_TOKEN`
and `GITHUB_MODELS_PROXY`. |
| api/admin_config/provider_manifest.py | Adds GitHub Models token
labeling and description for generated admin provider fields. |
| smoke/lib/config.py | Adds GitHub Models smoke defaults and credential
detection. |
| tests/providers/test_github_models.py | Adds focused tests for GitHub
Models initialization, request conversion, catalog filtering, streaming,
tool calls, reasoning, and cleanup. |
| tests/providers/test_provider_runtime.py | Covers GitHub Models
descriptor, provider config construction, and runtime instantiation. |
| README.md | Adds GitHub Models setup documentation and updates
provider counts/numbering. |
| pyproject.toml | Bumps the package version to `3.2.0` for the new
provider feature. |

</details>

<details open><summary><h3>Sequence Diagram</h3></summary>

<a href="#gh-light-mode-only">

```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User as Claude/Codex client
participant FCC as FCC proxy/router
participant Factory as Provider runtime factory
participant GH as GitHubModelsProvider
participant OpenAI as Shared OpenAI-chat transport
participant API as models.github.ai

User->>FCC: Request with model `github_models/...`
FCC->>Factory: create_provider(`github_models`, settings)
Factory->>GH: ProviderConfig(token, base_url, proxy)
GH->>OpenAI: Initialize with GitHub default headers
FCC->>GH: stream_response(MessagesRequest)
GH->>OpenAI: build OpenAI chat body
OpenAI->>API: "POST /inference/chat/completions (stream=true)"
API-->>OpenAI: OpenAI-compatible stream chunks
OpenAI-->>FCC: Anthropic SSE events
FCC-->>User: Streamed Anthropic response

FCC->>GH: list_model_infos()
GH->>API: GET /catalog/models
API-->>GH: Catalog entries with capabilities
GH-->>FCC: stream/tool-capable model ids
```

</a>
<a href="#gh-dark-mode-only">

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User as Claude/Codex client
participant FCC as FCC proxy/router
participant Factory as Provider runtime factory
participant GH as GitHubModelsProvider
participant OpenAI as Shared OpenAI-chat transport
participant API as models.github.ai

User->>FCC: Request with model `github_models/...`
FCC->>Factory: create_provider(`github_models`, settings)
Factory->>GH: ProviderConfig(token, base_url, proxy)
GH->>OpenAI: Initialize with GitHub default headers
FCC->>GH: stream_response(MessagesRequest)
GH->>OpenAI: build OpenAI chat body
OpenAI->>API: "POST /inference/chat/completions (stream=true)"
API-->>OpenAI: OpenAI-compatible stream chunks
OpenAI-->>FCC: Anthropic SSE events
FCC-->>User: Streamed Anthropic response

FCC->>GH: list_model_infos()
GH->>API: GET /catalog/models
API-->>GH: Catalog entries with capabilities
GH-->>FCC: stream/tool-capable model ids
```

</a>
</details>

<sub>Reviews (1): Last reviewed commit: ["Add GitHub Models
provider"](https://github.com/alishahryar1/free-claude-code/commit/736d3f9213f6a8d243d4001c5135b7fac402f143)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=41901295)</sub>

<!-- /greptile_comment -->
2026-07-05 12:11:55 -07:00
Ali Khokhar 9a17d1ed0a Add Cohere provider (#986)
## Problem

FCC does not expose Cohere's OpenAI-compatible chat models, so users
with Cohere keys cannot route Claude, Codex, or messaging prompts
through Cohere.

## Changes

| Before | After |
| --- | --- |
| Provider catalog did not include Cohere. | Provider catalog includes
Cohere with `COHERE_API_KEY`, `COHERE_PROXY`, admin status, and smoke
model wiring. |
| Requests could not target Cohere's compatibility API. |
`providers/cohere` routes OpenAI-chat requests to Cohere's compatibility
API with Cohere-specific request policy. |
| Docs and templates omitted Cohere setup. | README, `.env.example`, and
architecture docs document Cohere setup and ownership. |
| Cohere behavior had no regression coverage. | Provider, runtime,
admin, config, smoke, and catalog tests cover Cohere integration. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR adds Cohere as a new OpenAI-compatible chat provider. The main
changes are:

- Cohere provider metadata in the catalog, settings, Admin UI manifest,
and runtime factory.
- A new `CohereProvider` using the shared OpenAI chat transport with
Cohere-specific request shaping.
- Cohere API key, proxy, smoke model, README, architecture, and
environment template updates.
- Tests for Admin config, settings, provider catalog order, smoke
config, runtime creation, and Cohere request/stream behavior.
- Version and lockfile updates for the new provider feature.
</details>

<h3>Confidence Score: 5/5</h3>

Safe to merge with minimal risk.

No functional, security, or contract issues were identified. Cohere is
consistently wired through settings, catalog metadata, factory creation,
Admin config, smoke defaults, docs, versioning, and targeted tests. The
implemented Cohere `reasoning_effort` values match the Compatibility API
behavior checked during review.

No files require special attention.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- Validated the provider runtime handling of Cohere requests, including
the request body policy, streaming parsing, and default base URL and API
key behavior.
- Verified that the runtime descriptor wiring and provider config
proxy/key behavior pass in the general contract validation.
- Confirmed the admin/config smoke contract artifact shows the Cohere
environment settings, admin config masking, feature/provider catalog
contracts, and smoke configuration passing.
- Compared the initial -01-before.log and the clean -02-after.log
captures to confirm the same scoped commands are present and both exit
with code 0.

<a
href="https://app.greptile.com/trex/runs/13309850/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| providers/cohere/client.py | Implements Cohere request shaping over
shared OpenAI chat transport, including allowed extra body and reasoning
mapping; no issues found. |
| config/provider_catalog.py | Registers Cohere with credential, proxy,
base URL, transport, and capability metadata; no issues found. |
| providers/runtime/factory.py | Wires Cohere into runtime provider
factory dispatch; no issues found. |
| config/settings.py | Adds Cohere API key and proxy settings aliases;
no issues found. |
| api/admin_config/provider_manifest.py | Adds Cohere API key
labeling/description through catalog-derived Admin fields; no issues
found. |
| smoke/lib/config.py | Adds Cohere default smoke model and credential
detection; no issues found. |
| tests/providers/test_cohere.py | Adds request-policy and streaming
adapter tests for the Cohere provider; no issues found. |
| tests/providers/test_provider_runtime.py | Adds Cohere descriptor,
config build, and factory instantiation coverage; no issues found. |
| README.md | Adds Cohere setup instructions and updates provider
counts/order; no issues found. |
| pyproject.toml | Bumps package version for the new provider feature;
no issues found. |
| uv.lock | Updates the lockfile package version to match
`pyproject.toml`; no issues found. |

</details>

<details open><summary><h3>Sequence Diagram</h3></summary>

<a href="#gh-light-mode-only">

```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User as User/Admin config
participant Catalog as Provider catalog/settings
participant Factory as Runtime factory
participant Cohere as CohereProvider
participant Transport as OpenAI chat transport
participant API as Cohere Compatibility API

User->>Catalog: "Configure MODEL=cohere/... and COHERE_API_KEY"
Catalog->>Factory: Build ProviderConfig for provider_id cohere
Factory->>Cohere: Instantiate CohereProvider(config)
Cohere->>Transport: Build chat body with Cohere policy
Transport->>API: "POST /chat/completions stream=true"
API-->>Transport: Streaming OpenAI-compatible chunks
Transport-->>User: Anthropic SSE events
```

</a>
<a href="#gh-dark-mode-only">

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User as User/Admin config
participant Catalog as Provider catalog/settings
participant Factory as Runtime factory
participant Cohere as CohereProvider
participant Transport as OpenAI chat transport
participant API as Cohere Compatibility API

User->>Catalog: "Configure MODEL=cohere/... and COHERE_API_KEY"
Catalog->>Factory: Build ProviderConfig for provider_id cohere
Factory->>Cohere: Instantiate CohereProvider(config)
Cohere->>Transport: Build chat body with Cohere policy
Transport->>API: "POST /chat/completions stream=true"
API-->>Transport: Streaming OpenAI-compatible chunks
Transport-->>User: Anthropic SSE events
```

</a>
</details>

<sub>Reviews (1): Last reviewed commit: ["Add Cohere
provider"](https://github.com/alishahryar1/free-claude-code/commit/7956802968fc6ce63bb71fe6d7503d484df56b79)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=41887611)</sub>

<!-- /greptile_comment -->
2026-07-05 01:01:19 -07:00
Ali Khokhar d4683bf3f6 Add Hugging Face inference provider (#985)
## Problem

FCC did not expose Hugging Face Inference Providers as a selectable
backend. Voice transcription also used the legacy `HF_TOKEN` setting
instead of the canonical Hugging Face API key.

## Changes

| Before | After |
| --- | --- |
| Hugging Face models could not be selected through provider-prefixed
routing. | Hugging Face routes through a thin OpenAI-chat provider using
`huggingface/<model>`. |
| Provider credentials did not include `HUGGINGFACE_API_KEY`. | Admin
config, settings, smoke config, and docs use `HUGGINGFACE_API_KEY`. |
| `HF_TOKEN` remained a voice-only config key. | Owned dotenv files
migrate `HF_TOKEN` to `HUGGINGFACE_API_KEY`, while explicit
`FCC_ENV_FILE` users get a warning. |
| Version metadata stayed on `2.6.0`. | Version metadata moves to
`3.0.0` with a refreshed lockfile. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR adds Hugging Face Inference Providers as a selectable backend.
The main changes are:

- Adds a `huggingface` provider using the shared OpenAI-compatible chat
transport.
- Wires `HUGGINGFACE_API_KEY` and `HUGGINGFACE_PROXY` through settings,
Admin UI, provider catalog, runtime factory, and smoke config.
- Migrates owned dotenv files from `HF_TOKEN` to `HUGGINGFACE_API_KEY`
and warns for explicit `FCC_ENV_FILE` users.
- Updates voice transcription plumbing to use the canonical Hugging Face
key.
- Updates docs, examples, version metadata, lockfile, and related tests.
</details>

<h3>Confidence Score: 5/5</h3>

Safe to merge with minimal risk.

No blocking correctness or security issues were identified. The new
provider reuses the existing OpenAI-chat transport pattern. Provider
wiring, env migration, Admin UI, smoke config, voice plumbing, and tests
are consistent.

No files require special attention.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- The Pytest suite for providers, runtime, env migrations, config, and
contract tests ran and completed with exit code 0 and 198 tests passed.
- The HuggingFace runtime validator script ran and completed
successfully, printing provider\_class=HuggingFaceProvider,
default\_base\_url=https://router.huggingface.co/v1,
credential\_env=HUGGINGFACE\_API\_KEY, and
admin\_field=HUGGINGFACE\_API\_KEY:\[REDACTED\].
- Logs from both runs were captured as artifacts to aid review.

<a
href="https://app.greptile.com/trex/runs/13308618/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| providers/huggingface/client.py | Implements Hugging Face via the
shared OpenAI-chat transport with `extra_body` passthrough. |
| config/provider_catalog.py | Registers Hugging Face metadata, default
router URL, credential, proxy, and capabilities. |
| providers/runtime/factory.py | Wires Hugging Face into runtime
provider construction. |
| config/env_migrations.py | Adds safe `HF_TOKEN` to
`HUGGINGFACE_API_KEY` dotenv migration helpers for owned env files. |
| config/settings.py | Adds Hugging Face API key/proxy settings and
removes the legacy `hf_token` setting. |
| api/admin_config/manifest.py | Removes the voice-only `HF_TOKEN` field
and adds Hugging Face smoke model configuration. |
| api/admin_config/provider_manifest.py | Adds Admin UI labeling and
description for `HUGGINGFACE_API_KEY`. |
| messaging/transcription.py | Renames local Whisper token handling to
use the canonical Hugging Face API key. |
| smoke/lib/config.py | Adds Hugging Face smoke-test default model and
credential detection. |
| tests/providers/test_huggingface.py | Adds provider tests for Hugging
Face base URL, request body policy, streaming, and cleanup. |

</details>

<details open><summary><h3>Sequence Diagram</h3></summary>

<a href="#gh-light-mode-only">

```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User as Admin/User
participant Settings as Settings + dotenv migration
participant Catalog as Provider Catalog
participant Runtime as Provider Runtime Factory
participant HF as HuggingFaceProvider
participant Router as router.huggingface.co/v1

User->>Settings: "Configure MODEL=huggingface/<model> and HUGGINGFACE_API_KEY"
Settings->>Settings: Rename owned HF_TOKEN to HUGGINGFACE_API_KEY when present
Settings->>Catalog: Resolve huggingface descriptor and credential/proxy attrs
Catalog->>Runtime: Build ProviderConfig for huggingface
Runtime->>HF: Create HuggingFaceProvider
HF->>Router: Stream OpenAI-compatible chat completion
Router-->>HF: Streaming chunks
HF-->>User: Anthropic SSE response
```

</a>
<a href="#gh-dark-mode-only">

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User as Admin/User
participant Settings as Settings + dotenv migration
participant Catalog as Provider Catalog
participant Runtime as Provider Runtime Factory
participant HF as HuggingFaceProvider
participant Router as router.huggingface.co/v1

User->>Settings: "Configure MODEL=huggingface/<model> and HUGGINGFACE_API_KEY"
Settings->>Settings: Rename owned HF_TOKEN to HUGGINGFACE_API_KEY when present
Settings->>Catalog: Resolve huggingface descriptor and credential/proxy attrs
Catalog->>Runtime: Build ProviderConfig for huggingface
Runtime->>HF: Create HuggingFaceProvider
HF->>Router: Stream OpenAI-compatible chat completion
Router-->>HF: Streaming chunks
HF-->>User: Anthropic SSE response
```

</a>
</details>

<sub>Reviews (1): Last reviewed commit: ["Add Hugging Face inference
provider"](https://github.com/alishahryar1/free-claude-code/commit/7341d9a923986ac84d5e4fdf858128f913f3e5d3)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=41885587)</sub>

<!-- /greptile_comment -->
2026-07-05 00:26:40 -07:00
Ali Khokhar 020bbef64b Add Vercel AI Gateway provider (#984)
## Problem

FCC did not expose Vercel AI Gateway as a provider, so users with
`AI_GATEWAY_API_KEY` could not route Claude, Codex, or messaging
workflows through Vercel's model gateway.

## Changes

| Before | After |
| --- | --- |
| Provider metadata skipped Vercel AI Gateway. | Provider metadata
includes `vercel` with `AI_GATEWAY_API_KEY`, `VERCEL_AI_GATEWAY_PROXY`,
and OpenAI-chat capabilities. |
| No Vercel provider package or factory existed. | `VercelProvider` uses
the shared OpenAI-chat transport with `max_tokens` and preserved
`extra_body`. |
| Admin, docs, smoke config, and model parsing had no Vercel surface. |
Admin, docs, smoke config, and model parsing include Vercel model refs
such as `vercel/openai/gpt-5.5`. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR adds Vercel AI Gateway as a new OpenAI-compatible provider. The
main changes are:

- Provider catalog, settings, Admin UI metadata, and runtime factory
wiring for `vercel`.
- A thin `VercelProvider` adapter that reuses the shared OpenAI-chat
streaming transport.
- Vercel-specific docs, environment examples, proxy settings, and
smoke-test defaults.
- Config, contract, runtime, and provider tests covering the new
provider path.
- Package version and lockfile updates for the new feature.
</details>

<h3>Confidence Score: 5/5</h3>

This PR is safe to merge with minimal risk.

The new provider follows the existing catalog, settings, factory, and
shared transport patterns. The change includes focused config, runtime,
smoke, and provider tests. The package version and lockfile were updated
with the production changes. No functional or security issues were
identified in the changed paths.

No files require special attention.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- A focused pytest run for the Vercel provider completed successfully
with 187 tests passed in 3.93 seconds and EXIT\_CODE: 0.
- An offline probe script named vercel-provider-offline-probe.py was
generated to exercise the real factory/provider/request construction
code offline.
- The offline probe log vercel-provider-offline-probe.log showed the
expected provider setup and a successful exit, including
catalog\_has\_vercel=True, factory\_has\_vercel=True, provider class
VercelProvider, base URL, synthetic API key propagation, max\_tokens
preserved, max\_completion\_tokens absent, extra\_body preserved, and
EXIT\_CODE: 0.

<a
href="https://app.greptile.com/trex/runs/13307261/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<details open><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| README.md | Adds Vercel AI Gateway setup guidance and renumbers
provider documentation. |
| api/admin_config/provider_manifest.py | Adds Admin UI field metadata
for `AI_GATEWAY_API_KEY` via existing catalog-derived manifest flow. |
| config/provider_catalog.py | Registers `vercel` as an OpenAI-chat
provider with gateway credential, default base URL, proxy, and
capabilities. |
| config/settings.py | Adds settings fields for Vercel gateway API key
and proxy aliases. |
| providers/runtime/factory.py | Wires the new `vercel` provider id to
`VercelProvider` in runtime factory registration. |
| providers/vercel/client.py | Implements a thin Vercel adapter over
shared OpenAI-chat transport with `max_tokens` and `extra_body`
passthrough. |
| pyproject.toml | Bumps the package version to `2.6.0` for the new
provider feature. |
| smoke/lib/config.py | Adds Vercel smoke defaults and credential
detection for provider smoke selection. |
| tests/providers/test_provider_runtime.py | Adds runtime config and
factory instantiation coverage for the Vercel provider. |
| tests/providers/test_vercel.py | Adds unit tests for Vercel base URL
handling, request-body policy, streaming deltas, and cleanup. |
| uv.lock | Synchronizes the lockfile package version with
`pyproject.toml`. |

</details>

<details open><summary><h3>Sequence Diagram</h3></summary>

<a href="#gh-light-mode-only">

```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User as User/Admin config
participant Settings as Settings/env
participant Catalog as Provider catalog
participant Factory as Runtime factory
participant Vercel as VercelProvider
participant Gateway as Vercel AI Gateway

User->>Settings: "Set AI_GATEWAY_API_KEY and MODEL=vercel/..."
Settings->>Catalog: Resolve vercel descriptor
Catalog->>Factory: Build ProviderConfig with key/base/proxy
Factory->>Vercel: Instantiate VercelProvider
Vercel->>Gateway: Stream OpenAI Chat Completions
Gateway-->>Vercel: OpenAI-compatible chunks
Vercel-->>User: Anthropic SSE via shared transport
```

</a>
<a href="#gh-dark-mode-only">

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User as User/Admin config
participant Settings as Settings/env
participant Catalog as Provider catalog
participant Factory as Runtime factory
participant Vercel as VercelProvider
participant Gateway as Vercel AI Gateway

User->>Settings: "Set AI_GATEWAY_API_KEY and MODEL=vercel/..."
Settings->>Catalog: Resolve vercel descriptor
Catalog->>Factory: Build ProviderConfig with key/base/proxy
Factory->>Vercel: Instantiate VercelProvider
Vercel->>Gateway: Stream OpenAI Chat Completions
Gateway-->>Vercel: OpenAI-compatible chunks
Vercel-->>User: Anthropic SSE via shared transport
```

</a>
</details>

<sub>Reviews (1): Last reviewed commit: ["Add Vercel AI Gateway
provider"](https://github.com/alishahryar1/free-claude-code/commit/862ae946b2f7029ce4d3b309178312c9afe2751b)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=41883209)</sub>

<!-- /greptile_comment -->
2026-07-04 23:49:48 -07:00
Ali Khokhar 081fcfcda6 Add MiniMax provider (#980) 2026-07-04 19:28:59 -07:00
Ali Khokhar bd51575430 Fix Cloudflare Workers AI transport (#971) 2026-07-03 23:39:22 -07:00
Ali Khokhar 478e96655c Add Cloudflare provider (#933) 2026-06-28 12:06:14 -07:00
Ali Khokhar cdeb1aa9e2 Refactor settings schema ownership (#927) 2026-06-27 16:21:30 -07:00
Ali Khokhar 58aef0dc8a Refactor provider runtime ownership (#925)
## Problem

Provider construction, model discovery, validation, and cleanup lived in
one registry module. API and admin routes depended on registry-shaped
app state and legacy process-level provider helpers.

## Changes

| Before | After |
| --- | --- |
| `providers.registry` mixed provider factories, config, cache,
discovery, validation, and cleanup. | `providers.runtime` splits
factories, config, cache, model cache, discovery, validation, and
runtime orchestration. |
| API and admin routes read `app.state.provider_registry` and sometimes
created registries ad hoc. | API and admin routes use app-scoped
`ProviderRuntime` through `app.state.provider_runtime`. |
| `api.dependencies` kept process-global provider cache helpers. |
`api.dependencies` resolves providers only through the app-scoped
runtime. |
| Registry-shaped tests preserved old internal boundaries. |
Runtime-shaped tests assert provider config, construction, cache,
discovery, validation, and import boundaries. |

<!-- greptile_comment -->

<details open><summary><h3>Greptile Summary</h3></summary>

This PR moves provider lifecycle ownership from the old registry module
into an app-scoped runtime package. The main changes are:

- Split provider config, factory wiring, instance cache, model cache,
discovery, validation, and cleanup into `providers.runtime` modules.
- Updated API and admin routes to resolve providers and model metadata
through `app.state.provider_runtime`.
- Removed legacy process-global provider helpers and the deleted
`providers.registry` module.
- Updated docs, smoke metadata, import-boundary checks, and tests for
the new runtime ownership model.
- Bumped the package version and lockfile metadata for the production
refactor.
</details>

<h3>Confidence Score: 5/5</h3>

The provider runtime refactor appears merge-safe with no identified
blocking issues.

The changes consistently move provider ownership to app-scoped runtime
modules and update API, admin, docs, smoke metadata, import-boundary
checks, and tests around that architecture.

<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>

**What T-Rex did**
- Ran a baseline and head comparison of provider registry and runtime
states, verifying the after-state shows head
state\_has\_provider\_registry=False and
state\_has\_provider\_runtime=True, that GET /v1/models and admin
endpoints respond with 200, and that provider\_resolver\_called via
runtime, with assertions passing.
- Verified that the four focused provider-runtime contract tests passed
in both the before and after refactor runs, including runtime split
checks, with exit code 0.
- Identified environmental blockers that prevented the smoke-runtime
workflow from running, including uv unavailability, missing pytest for
/usr/local/bin/python, and Python 3.11 being used despite pyproject.toml
requiring \>=3.14.

<a
href="https://app.greptile.com/trex/runs/12528505/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=1"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=1"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=1"
height="32"></picture></a>

<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>

<sub>Reviews (1): Last reviewed commit: ["Refactor provider runtime
ownership"](https://github.com/alishahryar1/free-claude-code/commit/01d589488185c1f85112f1a49c47f04512846161)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=40312173)</sub>

<!-- /greptile_comment -->
2026-06-27 15:04:34 -07:00