文件历史

10 次代码提交

作者 SHA1 备注 提交日期
Ali Khokhar a092455b54 Add searchable model selection to the Admin UI (#1121)
## Problem

Admin model routing fields required users to construct provider-prefixed
model slugs. Optional tier overrides represented inheritance as an
unexplained blank value.

## Changes

| Before | After |
| --- | --- |
| Model inputs only gained suggestions after an individual provider
refresh. | Model inputs load configured and discovered canonical slugs
from one Admin catalog. |
| Model routing looked like unrestricted text entry. | Model routing
uses the browser's searchable model dropdown while retaining manual
entry. |
| Tier overrides displayed an empty value for fallback routing. | Tier
overrides display **None** and persist it as an unset override. |
| Model refresh returned provider-shaped cache internals. | Model
refresh returns the same canonical catalog consumed by the Admin UI. |
| Users inferred the provider/model slug format from examples. | The
Admin UI and README define and present complete provider/model slugs. |

<!-- greptile_comment -->

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

This PR adds searchable model selection to the Admin UI. The main
changes are:

- Adds a canonical catalog of configured and discovered model slugs.
- Adds searchable model inputs while preserving manual entry.
- Represents unset tier overrides as **None**.
- Reports provider-specific model refresh failures.
- Reconciles cached models when provider settings change.
- Updates documentation, package metadata, and tests.
</details>

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

This looks safe to merge.

Catalog failures no longer stop the rest of the Admin UI from loading.
Partial provider refreshes now produce a visible warning. Removed
credential-backed providers are pruned from the shared cache, and later
stale writes are rejected. No blocking issues remain 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**
- T-Rex ran the requested verification for the pull request checks.
- The verification completed, but local artifact references were not
uploaded.

<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/api/admin_static/admin.js | Adds searchable model
fields, optional catalog hydration, refresh warnings, and None-to-unset
conversion. |
| src/free_claude_code/api/admin_routes.py | Adds canonical model
catalog endpoints and provider refresh failure metadata. |
| src/free_claude_code/providers/runtime/discovery.py | Tracks provider
refresh outcomes and separates cache eligibility from discovery
eligibility. |
| src/free_claude_code/providers/runtime/model_cache.py | Scopes cached
model metadata to currently available providers and removes stale remote
entries. |
| src/free_claude_code/runtime/provider_manager.py | Reconciles cache
scope during runtime replacement and returns explicit refresh results. |

</details>

<sub>Reviews (2): Last reviewed commit: ["Fix model catalog refresh
lifecycle"](https://github.com/alishahryar1/free-claude-code/commit/d16e170055f5389e538e18dece269a5f7a8c599d)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=44373795)</sub>

<!-- /greptile_comment -->
2026-07-15 01:27:36 -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 f8c21a48f2 Introduce a typed application boundary for provider execution (#1045)
## Problem

The HTTP adapter owned model routing, provider execution, and
runtime-facing contracts, so API handlers depended on provider
implementation types. Provider preflight also discovered private request
builders dynamically, obscuring the boundary that must fail before
streaming begins.

## Changes

| Before | After |
| --- | --- |
| `api/` owned model routing and shared provider execution. |
`application/` owns routing and a settings-independent
`ProviderExecutor`. |
| API handlers accepted `BaseProvider` callbacks. | API handlers consume
the narrow structural `ProviderPort`. |
| `BaseProvider` discovered `_build_request_body` dynamically. | Both
transport families implement explicit abstract preflight, with LM Studio
composing context validation. |
| Request leases, task control, and provider model metadata had
adapter/provider owners. | Application-owned ports and immutable values
define those cross-package contracts. |
| Boundary direction was implicit. | Architecture contracts and
documentation enforce the final dependency direction. |
| Package version was `3.4.19`. | Package version is `3.4.20`, with the
lockfile updated. |
| Coverage followed the old module layout. | Deterministic
boundary/preflight regressions and live Messages/Responses smokes cover
the new shape. |

<!-- greptile_comment -->

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

This PR adds a typed application boundary for provider execution. The
main changes are:

- New `application` package for routing, execution, ports, and model
metadata.
- API handlers now call application-owned routing and provider
execution.
- Provider preflight is now explicit on the transport families.
- Runtime API composition now uses a task-control port for `/stop`.
- Import-boundary tests, smoke references, docs, version, and lockfile
were updated.
</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 a deterministic pytest run for the provider boundary preflight,
which completed with exit code 0 and 102 tests passing in 4.77 seconds.
- Launched the environment presence check as part of the preflight,
which completed with exit code 0 and confirmed
OPENCODE\_API\_KEY=\[REDACTED\] matched.
- Attempted the live provider smoke test, which completed with exit code
0 and 2 tests skipped due to incomplete smoke configuration.

<a
href="https://app.greptile.com/trex/runs/14067905/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/execution.py | Moves shared provider
execution into the application layer and keeps eager preflight before
token counting and streaming. |
| src/free_claude_code/application/ports.py | Adds structural provider,
request-runtime, and task-control protocols used across the new
boundary. |
| src/free_claude_code/api/routes.py | Updates route composition to use
the application provider resolver and task-control stop path. |
| src/free_claude_code/providers/base.py | Makes provider preflight
explicit by requiring subclasses or transport bases to implement it. |
| src/free_claude_code/providers/transports/openai_chat/transport.py |
Adds OpenAI-chat preflight through the same request-body builder used by
streaming. |
|
src/free_claude_code/providers/transports/anthropic_messages/transport.py
| Adds native Messages preflight through the native request-body
builder. |
| src/free_claude_code/providers/model_listing.py | Keeps provider
model-list parsing while moving `ProviderModelInfo` ownership to the
application layer. |
| src/free_claude_code/runtime/bootstrap.py | Passes the runtime object
through the new `tasks` service slot. |
| tests/contracts/test_import_boundaries.py | Extends import-boundary
tests for the new application package. |

</details>

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

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

```mermaid
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  API[api handlers and routes] --> Routing[application.routing]
  API --> Executor[application.execution]
  API --> Ports[application.ports]
  Executor --> ProviderPort[ProviderPort]
  ProviderPort --> Preflight[preflight_stream]
  ProviderPort --> Stream[stream_response]
  Runtime[runtime bootstrap and provider manager] --> Ports
  Providers[providers] --> Metadata[application.model_metadata]
  Executor --> Core[core anthropic and trace]
  Routing --> Config[config settings and model refs]
```

</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
  API[api handlers and routes] --> Routing[application.routing]
  API --> Executor[application.execution]
  API --> Ports[application.ports]
  Executor --> ProviderPort[ProviderPort]
  ProviderPort --> Preflight[preflight_stream]
  ProviderPort --> Stream[stream_response]
  Runtime[runtime bootstrap and provider manager] --> Ports
  Providers[providers] --> Metadata[application.model_metadata]
  Executor --> Core[core anthropic and trace]
  Routing --> Config[config settings and model refs]
```

</a>
</details>

<sub>Reviews (1): Last reviewed commit: ["Introduce typed application
boundary"](https://github.com/alishahryar1/free-claude-code/commit/4cdcf97231c812c6f568ca3d74af7ce759d7f2dc)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43462788)</sub>

<!-- /greptile_comment -->
2026-07-10 20:06:57 -07:00
Ali Khokhar 160d63370b Establish single-owner runtime with stream-safe provider hot swaps (#1036)
## Problem

Provider runtime ownership was split between lifecycle code and mutable
FastAPI state, so Admin replacements could leak the new runtime,
double-close the old runtime, or close providers still serving active
streams. The API package also owned concrete process composition,
obscuring subsystem boundaries.

## Changes

| Before | After |
| --- | --- |
| FastAPI routes inspected several concrete `app.state` resources. |
FastAPI receives one explicit `ApiServices` boundary and stores only
`app.state.services`. |
| Admin Apply persisted config and directly replaced one runtime
reference. | Admin Apply validates a candidate, commits atomically, and
publishes it through the single runtime owner. |
| Provider replacement could close clients used by active streams. |
Generation leases retain old providers until each streaming or
non-streaming response finishes. |
| Provider generations owned discovery state and model metadata. |
`ProviderRuntimeManager` owns one application-lifetime catalog and one
discovery task across replacements. |
| API modules composed provider, messaging, and managed CLI resources. |
`runtime.bootstrap` composes concrete subsystems and
`ApplicationRuntime` owns their lifecycle. |
| Admin config, server URLs, and gateway model IDs lived under the API
package. | Admin config lives under `config`, server URLs live under
`config`, and gateway IDs live under `core`. |
| Messaging restoration and shutdown persistence were coordinated
externally. | `MessagingWorkflow` owns snapshot restoration and final
persistence flushing. |
| Hot-swap behavior lacked a real process-level race scenario. |
Deterministic ownership tests and a credential-free subprocess smoke
hold provider A while new requests switch to provider B. |
| Package version was `3.4.16`. | Package version is `3.4.17` with an
updated lockfile. |

<!-- greptile_comment -->

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

This PR centralizes server runtime ownership and provider hot swaps. The
main changes are:

- Adds `ApplicationRuntime` and `ProviderRuntimeManager` as the process
owners.
- Moves FastAPI to an explicit `ApiServices` boundary.
- Retains provider generations until request and stream responses
finish.
- Moves admin config, server URL, and gateway model ID modules to
neutral package owners.
- Updates admin apply to validate, persist, and publish provider-only
changes through the runtime owner.
- Adds runtime ownership tests and a credential-free smoke scenario.
</details>

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

This looks safe to merge.

No blocking issues found in the changed code. The provider lease path
releases resources on normal completion, stream close, and cancellation.
The admin apply path keeps restart-required changes separate from
provider-only hot swaps, and repository import paths appear updated for
the moved modules.

No files need follow-up 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 T-Rex smoke test command and confirmed it completed with exit
code 0 and pytest passing.
- Monitored runtime ownership activity during the run, including a
provider A stream request on model-a generation 1, an admin publish to
generation 2, a new request on model-b generation 2, and the completion
of the original generation 1 stream.
- Collected smoke result artifacts from the .smoke-results area for
gateway 1, gateway 0, and main, and made them available for review.
- Opened the smoke report JSON artifacts to review the summarized
outcomes for each target environment.

<a
href="https://app.greptile.com/trex/runs/14008910/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/provider_manager.py | Adds provider
generation ownership, request leases, replacement, discovery refresh,
and shutdown cleanup. |
| src/free_claude_code/runtime/application.py | Adds the process-level
owner for startup, shutdown, admin operations, messaging, and session
control. |
| src/free_claude_code/api/routes.py | Routes now acquire provider
generation leases and bind them to response lifetime. |
| src/free_claude_code/api/response_streams.py | Adds response lifetime
binding so retained resources release after stream completion,
cancellation, or close. |
| src/free_claude_code/config/admin/persistence.py | Moves admin config
persistence into `config` and adds prepared validation plus atomic
managed-env commits. |
| src/free_claude_code/runtime/bootstrap.py | Adds the production
composition root for logging, runtime owners, services, and ASGI wiring.
|
| src/free_claude_code/api/__init__.py | Removes package-level API
re-exports as part of the HTTP adapter boundary cleanup. |

</details>

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

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

```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Client
participant API as FastAPI Route
participant Manager as ProviderRuntimeManager
participant Lease as Generation Lease
participant Runtime as Provider Generation
participant Admin as Admin Apply

Client->>API: Request /v1/messages or /v1/responses
API->>Manager: acquire()
Manager-->>API: lease for current generation
API->>Lease: resolve_provider()
Lease->>Runtime: use provider instance
Runtime-->>Client: response body or stream

Admin->>Manager: replace(candidate settings)
Manager->>Manager: publish new generation
Manager->>Manager: retire old generation

Client-->>API: response completes or disconnects
API->>Lease: release()
Lease->>Manager: decrement active leases
Manager->>Runtime: cleanup retired generation when drained
```

</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 Client
participant API as FastAPI Route
participant Manager as ProviderRuntimeManager
participant Lease as Generation Lease
participant Runtime as Provider Generation
participant Admin as Admin Apply

Client->>API: Request /v1/messages or /v1/responses
API->>Manager: acquire()
Manager-->>API: lease for current generation
API->>Lease: resolve_provider()
Lease->>Runtime: use provider instance
Runtime-->>Client: response body or stream

Admin->>Manager: replace(candidate settings)
Manager->>Manager: publish new generation
Manager->>Manager: retire old generation

Client-->>API: response completes or disconnects
API->>Lease: release()
Lease->>Manager: decrement active leases
Manager->>Runtime: cleanup retired generation when drained
```

</a>
</details>

<sub>Reviews (1): Last reviewed commit: ["refactor: establish
single-owner
applica..."](https://github.com/alishahryar1/free-claude-code/commit/92fc06aa733b7acc34ad6ea50de8b6b4ce5cfac1)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43349002)</sub>

<!-- /greptile_comment -->
2026-07-10 10:52:54 -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 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
Alishahryar1 5294661aa4 feat: add Wafer provider 2026-05-08 23:43:16 -07:00
Alishahryar1 d3a3b37e9e Filter OpenRouter model variants by thinking support 2026-04-30 22:01:36 -07:00
Alishahryar1 db3c9521b1 Add no-thinking model picker variants 2026-04-30 21:27:23 -07:00
Alishahryar1 72b34ad57c Added claude-code native model picker 2026-04-30 20:34:35 -07:00