文件历史

3 次代码提交

作者 SHA1 备注 提交日期
Ali Khokhar 2a676cc6d9 Make ProviderModelInfo the sole model-catalog contract (#1222)
## Problem

Provider model discovery consumes metadata, but providers and the cache
still expose a parallel IDs-only contract. The duplicate contract adds
adapters and lets tests bypass capability metadata.

## Changes

| Before | After |
| --- | --- |
| `BaseProvider` exposed `list_model_ids()` plus a metadata adapter. |
`BaseProvider` exposes only abstract `list_model_infos()` returning
application-owned metadata. |
| Ordinary providers parsed IDs and converted them later. | Ordinary
providers parse OpenAI-compatible catalogs directly into
`ProviderModelInfo` values. |
| OpenRouter, Cloudflare, and GitHub Models maintained redundant
IDs-only wrappers. | Provider-specific filters and capability metadata
have one return path. |
| Vertex returned paginated IDs for the base adapter to wrap. | Vertex
returns metadata after completing the same paginated discovery flow. |
| The runtime cache exposed test-only raw-ID write and prefixed-ID read
helpers. | The runtime cache accepts and returns metadata while
retaining its production admin-status ID projection. |
| Provider tests asserted the parallel IDs-only API. | Provider tests
enforce the metadata-only contract and preserve provider-specific
discovery behavior. |
| The package version was `4.11.6`. | The package version is `4.11.7`
with an updated lockfile. |

<!-- greptile_comment -->

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

This PR makes provider metadata the only model-catalog contract. The
main changes are:

- Makes `list_model_infos()` the abstract provider discovery API.
- Migrates provider parsers and implementations to `ProviderModelInfo`.
- Removes IDs-only cache and parser helpers.
- Updates provider tests, architecture documentation, and package
metadata.
</details>

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

The catalog migration is consistent, but the release version must
reflect the incompatible API removal.

Repository provider and cache call paths use the new metadata shape
consistently. Existing external consumers of the removed contracts can
fail after a patch upgrade. The repository rules classify incompatible
API removals as a major release.

pyproject.toml and the matching package entry in uv.lock

<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 external-consumer compatibility probe was run against both
revisions, confirming the base still supports the legacy provider
contract, while head fails with a TypeError due to the missing
list\_model\_infos method, and runtime metadata shows head at version
4.11.7, indicating the removal is a patch transition rather than a major
change.
- An automated test suite completed successfully with 83 tests passing
in 3.31 seconds.

<a
href="https://app.greptile.com/trex/runs/15207030/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/base.py | Replaces the IDs-only
provider API with an abstract metadata-only contract. |
| src/free_claude_code/providers/model_listing.py | Consolidates
OpenAI-compatible parsing into ProviderModelInfo results and removes
IDs-only helpers. |
| src/free_claude_code/providers/runtime/model_cache.py | Removes raw-ID
helpers while retaining metadata storage and the admin ID projection. |
| src/free_claude_code/providers/openai_chat/provider.py | Provides the
metadata discovery implementation inherited by ordinary
OpenAI-compatible providers. |
| src/free_claude_code/providers/vertex/client.py | Preserves paginated
discovery while returning metadata values. |
| pyproject.toml | Uses a patch bump for a release that removes callable
and importable contracts. |

</details>

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

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

```mermaid
%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[Provider catalog endpoint] --> B[list_model_infos]
B --> C[ProviderModelInfo set]
C --> D[Provider model discovery]
D --> E[ProviderModelCache]
E --> F[Metadata-aware catalog]
E --> G[Admin ID projection]
```

</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
A[Provider catalog endpoint] --> B[list_model_infos]
B --> C[ProviderModelInfo set]
C --> D[Provider model discovery]
D --> E[ProviderModelCache]
E --> F[Metadata-aware catalog]
E --> G[Admin ID projection]
```

</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%2Fprovider-model-info-contract%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%2Fprovider-model-info-contract%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%0Apyproject.toml%3A7%0A**Breaking%20Contract%20Ships%20as%20Patch**%0A%0AThis%20release%20removes%20%60BaseProvider.list_model_ids%28%29%60%20and%20cache%2Fparser%20methods%20that%20existing%20integrations%20can%20import%20or%20call.%20Such%20consumers%20will%20fail%20with%20%60TypeError%60%2C%20%60AttributeError%60%2C%20or%20%60ImportError%60%20after%20a%20patch%20upgrade%2C%20so%20this%20incompatible%20API%20change%20requires%20a%20major%20version%20bump%20under%20the%20repository's%20versioning%20rules.%0A%0A%60%60%60suggestion%0Aversion%20%3D%20%225.0.0%22%0A%60%60%60%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1222&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: ["Make ProviderModelInfo the
sole catalog
..."](https://github.com/alishahryar1/free-claude-code/commit/5c543eadc114201a4085d38885a27ac49153ca29)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=45869248)</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-21 00:15:35 -07:00
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 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