mirror of
https://github.com/Alishahryar1/free-claude-code.git
synced 2026-07-09 16:00:45 +00:00
762 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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"](
|
||
|
|
d7c54c6dc5
|
Preserve messaging transcript on stop | ||
|
|
a5310f4a0f
|
Fix pre-start stream failures returning HTTP 200 (#1026)
## Problem Provider streams could commit HTTP 200 before an upstream-backed first SSE frame was available. When setup or retry failed before usable stream output, Claude and Codex saw a successful but broken stream instead of a retryable non-200 error. ## Changes | Before | After | | --- | --- | | API egress returned `StreamingResponse` before probing the provider iterator. | API egress waits for the first chunk before committing success headers. | | Pre-start provider failures became synthetic SSE success streams. | Pre-start provider failures raise typed errors and return Anthropic or OpenAI JSON with non-200 status. | | Post-start unexpected stream failures could truncate protocol output. | Post-start failures emit terminal Anthropic error or Responses `response.failed` frames where possible. | | Provider tests expected pre-start final failures as SSE tails. | Provider tests assert typed pre-start errors and preserve midstream and tool-salvage behavior. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR changes streaming responses so HTTP success is not committed before the first protocol chunk. The main changes are: - First-chunk gated streaming helpers for Anthropic and OpenAI Responses egress. - Non-200 JSON error responses for provider failures before stream output starts. - Terminal Anthropic `error` and Responses `response.failed` frames for post-start interruptions. - Provider transport updates that raise typed pre-start errors while preserving retry, recovery, and tool salvage paths. - Targeted API and provider tests plus a patch version and lockfile update. </details> <h3>Confidence Score: 5/5</h3> Safe to merge with low risk. The changed paths keep provider retry and recovery ownership in transports, gate HTTP success before the first chunk, and preserve cancellation behavior. Tests cover the main Anthropic and OpenAI Responses pre-start and post-start failure 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** - Ran the pre-change stream-gating API tests against the previous commit |
||
|
|
98515be55a
|
Fix MiniMax Admin UI API description
Update MiniMax Admin UI copy to describe the OpenAI-compatible Chat Completions endpoint. |
||
|
|
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. |
||
|
|
c9adffffbf
|
Pin managed messaging to Opus tier
Pin managed messaging Claude tasks to the Opus tier so phone sessions route through Admin MODEL_OPUS/MODEL instead of inheriting interactive Claude model picker state. |
||
|
|
dac6d4e88d
|
Request streamed usage for OpenAI-chat providers (#1013)
## Problem
OpenAI-compatible streaming providers could return accurate final usage,
but FCC only requested it for DeepSeek and kept provider prompt tokens
out of final Anthropic usage.
## Changes
| Before | After |
| --- | --- |
| DeepSeek alone requested streamed usage. | The OpenAI-chat transport
requests streamed usage for all OpenAI-compatible providers. |
| Final input usage stayed on the local estimate even when providers
returned `prompt_tokens`. | Final input usage uses provider
`prompt_tokens` when available and falls back to the estimate when
absent. |
| Providers that rejected `stream_options.include_usage` failed the
request. | Providers that reject optional usage metadata retry once
without it. |
| DeepSeek owned duplicated usage extraction logic. | OpenAI-chat usage
extraction is shared, while DeepSeek keeps only cache-token mapping. |
<!-- greptile_comment -->
<details open><summary><h3>Greptile Summary</h3></summary>
This PR moves streamed usage handling into the shared OpenAI-chat
transport. The main changes are:
- Requests `stream_options.include_usage` for OpenAI-compatible
streaming providers.
- Uses provider `prompt_tokens` and `completion_tokens` when streamed
usage is returned.
- Falls back to local token estimates when usage metadata is absent or
rejected.
- Retries once without `include_usage` when an upstream provider rejects
the optional field.
- Keeps DeepSeek-specific cache token mapping in the DeepSeek provider.
</details>
<h3>Confidence Score: 5/5</h3>
Safe to merge with low risk.
The changed logic is localized to the OpenAI-chat streaming path and
includes focused regression coverage for the new usage and retry
behavior.
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 team executed the general contract validation for the non-UI
provider transport using a mocked chat-completion streaming surface.
- Runtime artifacts, including the runtime log and before/after
comparison artifacts, were produced for inspection.
- The after-run summary shows 10 passed in 5.38 seconds with EXIT\_CODE
0.
- Because the test used a mocked streaming surface rather than live
endpoints, no HTTP endpoints or HTTP status messages were observed.
<a
href="https://app.greptile.com/trex/runs/13637854/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 |
|----------|----------|
| core/anthropic/streaming/ledger.py | Allows final `message_delta`
usage to override the ledger's initial estimated input token count. |
| providers/deepseek/client.py | Reuses shared usage extraction for
DeepSeek cache hit and miss token mapping. |
| providers/transports/openai_chat/stream.py | Requests streamed usage
and uses provider prompt and completion tokens when present. |
| providers/transports/openai_chat/transport.py | Adds bounded retry
behavior when upstream providers reject streamed usage metadata. |
| providers/transports/openai_chat/usage.py | Adds shared helpers for
usage requests, usage extraction, and usage rejection detection. |
| tests/providers/test_openai_chat_usage.py | Adds coverage for streamed
usage helpers, provider token usage, and retry fallback behavior. |
</details>
<details open><summary><h3>Sequence Diagram</h3></summary>
<a href="#gh-light-mode-only">
```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Client as Anthropic client
participant Adapter as OpenAIChatStreamAdapter
participant Transport as OpenAIChatTransport
participant Provider as OpenAI-compatible provider
participant Ledger as AnthropicStreamLedger
Client->>Adapter: stream_response(request, input_tokens)
Adapter->>Adapter: build body + request_stream_usage()
Adapter->>Transport: _create_stream(body with include_usage)
Transport->>Provider: "chat.completions.create(stream=True)"
alt provider rejects include_usage
Provider-->>Transport: 400/422 usage option error
Transport->>Transport: clone_without_stream_usage()
Transport->>Provider: retry without include_usage
end
Provider-->>Adapter: streaming chunks + optional final usage
Adapter->>Adapter: usage_int(prompt_tokens/completion_tokens)
Adapter->>Ledger: message_delta(input_tokens, output_tokens, provider usage fields)
Ledger-->>Client: Anthropic SSE usage
```
</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 as Anthropic client
participant Adapter as OpenAIChatStreamAdapter
participant Transport as OpenAIChatTransport
participant Provider as OpenAI-compatible provider
participant Ledger as AnthropicStreamLedger
Client->>Adapter: stream_response(request, input_tokens)
Adapter->>Adapter: build body + request_stream_usage()
Adapter->>Transport: _create_stream(body with include_usage)
Transport->>Provider: "chat.completions.create(stream=True)"
alt provider rejects include_usage
Provider-->>Transport: 400/422 usage option error
Transport->>Transport: clone_without_stream_usage()
Transport->>Provider: retry without include_usage
end
Provider-->>Adapter: streaming chunks + optional final usage
Adapter->>Adapter: usage_int(prompt_tokens/completion_tokens)
Adapter->>Ledger: message_delta(input_tokens, output_tokens, provider usage fields)
Ledger-->>Client: Anthropic SSE usage
```
</a>
</details>
<sub>Reviews (1): Last reviewed commit: ["Request streamed usage for
OpenAI-chat
p..."](
|
||
|
|
befa0ebb93
|
style: modernize admin UI dashboard and improve dropdown alignments (#742) | ||
|
|
ccf46b88cf
|
Retry pre-stream provider transport failures (#1003) | ||
|
|
bd85deb736
|
Fix OpenAI chat reasoning and tool history replay (#1002)
## Problem
OpenAI-chat providers lost explicit empty reasoning state and could
replay invalid tool-call history when unrelated messages appeared before
matching tool results.
## Changes
| Before | After |
| --- | --- |
| Empty `reasoning_content` and empty thinking blocks were treated as
absent. | Empty reasoning is preserved as explicit replay state. |
| OpenAI-chat conversion only deferred post-tool assistant text. |
OpenAI-chat conversion buffers later transcript messages until required
tool results are emitted. |
| Responses prior tool calls and outputs were emitted one item per
message. | Responses prior tool calls and outputs are grouped into valid
Anthropic tool-use/result messages. |
| Empty streamed `reasoning_content` produced no thinking block. | Empty
streamed `reasoning_content` starts thinking state without visible delta
text. |
<!-- greptile_comment -->
<details open><summary><h3>Greptile Summary</h3></summary>
This PR fixes OpenAI chat reasoning replay and tool-history ordering.
The main changes are:
- Preserves explicit empty `reasoning_content` and empty thinking
blocks.
- Reworks OpenAI chat conversion around a ledger that waits for required
tool results before replaying buffered transcript messages.
- Groups prior Responses tool calls and outputs into valid Anthropic
tool-use and tool-result messages.
- Starts streamed thinking state when empty `reasoning_content` is
received.
- Adds focused tests for nested tool turns, out-of-order results,
multi-tool replay, and empty reasoning.
</details>
<h3>Confidence Score: 5/5</h3>
Safe to merge with low risk.
No blocking issues were found in the changed conversion paths. The
updated ledger covers the prior invalid replay cases and the tests
include nested, out-of-order, multi-tool, and empty reasoning scenarios.
The required patch version and lockfile updates are present.
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**
- Ran the focused OpenAI conversion regression suite with Pytest,
capturing the command, working directory, pass count, exit code, and
elapsed time.
- Encountered an external timeout during the initial Pytest run at 98%
progress, then re-ran the same focused suite to completion for
definitive proof.
- Validated code quality with Ruff by executing the lint command and
obtaining a successful output.
<a
href="https://app.greptile.com/trex/runs/13503694/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 |
|----------|----------|
| core/anthropic/conversion.py | Replaces single pending-tool state with
a ledger that buffers transcript segments until required OpenAI chat
tool results can be emitted in valid order. |
| core/openai_responses/input.py | Groups consecutive prior Responses
tool calls/results into Anthropic tool-use/result turns and preserves
explicit empty reasoning. |
| core/openai_responses/reasoning.py | Updates reasoning extraction and
combination helpers so empty strings remain explicit replay state
without adding spurious separators. |
| providers/deepseek/compat.py | Treats empty top-level or block-level
thinking as replayable when detecting DeepSeek tool-history
compatibility. |
| providers/transports/openai_chat/stream.py | Starts an Anthropic
thinking block for empty streamed `reasoning_content` while only
emitting deltas for non-empty text. |
| tests/providers/test_converter.py | Adds OpenAI chat conversion
coverage for buffered tool history, nested pending tool turns, and
explicit empty reasoning. |
| tests/core/openai_responses/test_conversion.py | Adds Responses
conversion tests for grouped prior tool calls/results and empty
reasoning attachment. |
| pyproject.toml | Bumps the package patch version for the production
conversion fixes. |
| uv.lock | Keeps the lockfile package version in sync with
`pyproject.toml`. |
</details>
<details open><summary><h3>Sequence Diagram</h3></summary>
<a href="#gh-light-mode-only">
```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant A as Anthropic transcript
participant L as OpenAI chat ledger
participant O as OpenAI chat history
A->>L: Assistant tool_use segment
L->>O: Emit assistant tool_calls
A->>L: Later plain user/assistant messages
L-->>L: Buffer until required tool_result ids arrive
A->>L: User tool_result blocks
L->>O: Emit matching role: tool results in tool_call order
L->>O: Emit deferred assistant post-tool content
L->>O: Drain buffered plain transcript messages
```
</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 A as Anthropic transcript
participant L as OpenAI chat ledger
participant O as OpenAI chat history
A->>L: Assistant tool_use segment
L->>O: Emit assistant tool_calls
A->>L: Later plain user/assistant messages
L-->>L: Buffer until required tool_result ids arrive
A->>L: User tool_result blocks
L->>O: Emit matching role: tool results in tool_call order
L->>O: Emit deferred assistant post-tool content
L->>O: Drain buffered plain transcript messages
```
</a>
</details>
<sub>Reviews (3): Last reviewed commit: ["Refactor OpenAI chat tool
history
replay"](
|
||
|
|
950aba393d
|
Disable Hugging Face reasoning replay
Disable Hugging Face prior reasoning replay for Chat Completions while preserving streamed reasoning output. |
||
|
|
62c0480eed
|
Add Mistral reasoning fallback | ||
|
|
47ddedcada
|
Fix NIM chat template downgrade (#997)
## Problem
NVIDIA NIM Mistral-tokenizer models can reject chat-template controls
with HTTP 400. FCC only removed `chat_template`, so requests that only
had `chat_template_kwargs` still failed.
## Changes
| Before | After |
| --- | --- |
| NIM retried chat-template errors by stripping only
`extra_body.chat_template`. | NIM retries chat-template errors by
stripping `extra_body.chat_template` and
`extra_body.chat_template_kwargs`. |
| Mistral-tokenizer models could fail after rejecting thinking
chat-template kwargs. | Mistral-tokenizer models retry once without NIM
chat-template controls. |
| Reasoning-budget downgrades preserved thinking flags independently. |
Reasoning-budget downgrades still preserve thinking flags independently.
|
| Package metadata stayed at `3.4.2`. | Package metadata is bumped to
`3.4.3`. |
<!-- greptile_comment -->
<details open><summary><h3>Greptile Summary</h3></summary>
This PR fixes the NVIDIA NIM chat-template retry downgrade. The main
changes are:
- Removes both `extra_body.chat_template` and
`extra_body.chat_template_kwargs` before retrying chat-template 400
errors.
- Adds tests for the full chat-template path and the kwargs-only
regression case.
- Adds helper coverage for unchanged request bodies.
- Bumps package metadata from `3.4.2` to `3.4.3` and keeps `uv.lock`
aligned.
</details>
<h3>Confidence Score: 5/5</h3>
Safe to merge with minimal risk.
The production change is narrow and covered by targeted tests for both
chat-template stripping paths. Version metadata and lockfile updates
follow the repository guidance.
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 initial focused chat-template test run was executed and showed 6
tests passed, while the outer shell wrapper returned nonzero due to a
PIPESTATUS\[0\] substitution issue under /bin/sh after pytest completed.
- A corrected wrapper rerun of the same focused chat-template tests was
performed, and 6 tests passed with exit code 0.
- Focused provider retry tests for chat\_template or reasoning\_budget
were executed, and 4 tests passed with exit code 0.
<a
href="https://app.greptile.com/trex/runs/13364237/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/nvidia_nim/retry.py | Extends NIM chat-template retry
downgrades to remove both `chat_template` and `chat_template_kwargs`
while preserving unchanged-body behavior. |
| tests/providers/test_nvidia_nim.py | Updates streaming retry coverage
to assert the second request strips all chat-template controls,
including the kwargs-only regression case. |
| tests/providers/test_nvidia_nim_request.py | Adds request-body helper
coverage for stripping `chat_template_kwargs` and returning `None` when
no chat-template controls are present. |
| pyproject.toml | Bumps package version from `3.4.2` to `3.4.3` for the
production bug fix. |
| uv.lock | Keeps the editable package version in the lockfile aligned
with `pyproject.toml`. |
</details>
<details open><summary><h3>Sequence Diagram</h3></summary>
<a href="#gh-light-mode-only">
```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Client as Claude request
participant Provider as NvidiaNimProvider
participant NIM as NVIDIA NIM API
Client->>Provider: stream_response(request)
Provider->>NIM: create(extra_body with chat_template controls)
NIM-->>Provider: HTTP 400 chat_template rejection
Provider->>Provider: clone_body_without_chat_template()
Provider->>Provider: remove chat_template and chat_template_kwargs
Provider->>NIM: retry create(extra_body without chat-template controls)
NIM-->>Provider: stream chunks
Provider-->>Client: SSE response 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 Client as Claude request
participant Provider as NvidiaNimProvider
participant NIM as NVIDIA NIM API
Client->>Provider: stream_response(request)
Provider->>NIM: create(extra_body with chat_template controls)
NIM-->>Provider: HTTP 400 chat_template rejection
Provider->>Provider: clone_body_without_chat_template()
Provider->>Provider: remove chat_template and chat_template_kwargs
Provider->>NIM: retry create(extra_body without chat-template controls)
NIM-->>Provider: stream chunks
Provider-->>Client: SSE response events
```
</a>
</details>
<sub>Reviews (1): Last reviewed commit: ["Fix NIM chat template
downgrade"](
|
||
|
|
755a3851f7
|
Use batch delete boundary for messaging (#996)
## Problem
Messaging cleanup had two public queued delete paths. Command code could
loop single-message deletes and bypass Telegram batch deletion.
## Changes
| Before | After |
| --- | --- |
| Workflow code could call `queue_delete_message` or
`queue_delete_messages`. | Workflow code calls only
`queue_delete_messages`. |
| Telegram `/clear` cleanup used one API request per message. | Telegram
`/clear` cleanup uses `deleteMessages` in chunks of 100. |
| The outbox dedupe key used Python process hashing. | The outbox dedupe
key uses a stable SHA-based digest. |
| Voice and smoke cleanup depended on the single-delete queue API. |
Voice and smoke cleanup pass one-item delete lists. |
<!-- greptile_comment -->
<details open><summary><h3>Greptile Summary</h3></summary>
This PR moves messaging cleanup to a list-based delete boundary. The
main changes are:
- `/clear` now sends collected message IDs through
`queue_delete_messages`.
- Telegram deletion uses `deleteMessages` in 100-message chunks with
per-message fallback.
- Discord keeps per-message deletion behind the list-based outbound API.
- Delete-batch dedupe keys now use a stable SHA digest instead of Python
process hashing.
- Voice cleanup, smoke fakes, protocol tests, and messaging tests were
updated for the new delete boundary.
</details>
<h3>Confidence Score: 5/5</h3>
Safe to merge with minimal risk.
The change is well-scoped to the messaging delete boundary, keeps
platform-specific best-effort behavior, addresses the batch-fallback
concern, updates protocol consumers and tests, and includes the required
version and lockfile bump.
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**
- No execution evidence is available for this session; no harness was
created, no tests were run, and no artifacts were produced.
<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 |
|----------|----------|
| messaging/commands.py | Routes `/clear` cleanup through
`queue_delete_messages` once per collected message set while preserving
best-effort state cleanup. |
| messaging/platforms/outbox.py | Removes single-delete queueing,
snapshots delete batches, and uses a stable SHA digest for delete dedupe
keys. |
| messaging/platforms/telegram_io.py | Adds Telegram `deleteMessages`
batching with 100-message chunks and per-message fallback when batch
deletion fails. |
| messaging/platforms/discord_io.py | Removes the public single
queued-delete wrapper and backs queued deletion with the list-based
outbox API. |
| messaging/platforms/voice_flow.py | Changes shared voice cleanup call
sites to submit one-item lists to the delete queue. |
| messaging/platforms/ports.py | Narrows the outbound protocol to the
list-based delete queue method. |
| tests/messaging/test_telegram.py | Adds Telegram batch delete,
chunking, and fallback coverage. |
| tests/messaging/test_platform_outbox.py | Covers stable delete-batch
dedupe keys and snapshotting mutable message ID lists before queueing. |
| pyproject.toml | Bumps the package patch version for the production
messaging changes. |
| uv.lock | Updates the editable package version in the lockfile to
match `pyproject.toml`. |
</details>
<details open><summary><h3>Sequence Diagram</h3></summary>
<a href="#gh-light-mode-only">
```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Command as /clear or voice cleanup
participant Outbound as OutboundMessenger.queue_delete_messages
participant Outbox as PlatformOutbox
participant Telegram as TelegramMessenger
participant Discord as DiscordMessenger
participant API as Platform API
Command->>Outbound: queue_delete_messages(chat_id, message_ids)
Outbound->>Outbox: snapshot IDs and dedupe batch
alt Telegram
Outbox->>Telegram: delete_messages(chat_id, ids)
loop chunks of 100
Telegram->>API: deleteMessages(chat_id, chunk)
alt batch fails
Telegram->>API: deleteMessage(chat_id, each id)
end
end
else Discord
Outbox->>Discord: delete_messages(chat_id, ids)
loop each id
Discord->>API: fetch_message + delete
end
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 Command as /clear or voice cleanup
participant Outbound as OutboundMessenger.queue_delete_messages
participant Outbox as PlatformOutbox
participant Telegram as TelegramMessenger
participant Discord as DiscordMessenger
participant API as Platform API
Command->>Outbound: queue_delete_messages(chat_id, message_ids)
Outbound->>Outbox: snapshot IDs and dedupe batch
alt Telegram
Outbox->>Telegram: delete_messages(chat_id, ids)
loop chunks of 100
Telegram->>API: deleteMessages(chat_id, chunk)
alt batch fails
Telegram->>API: deleteMessage(chat_id, each id)
end
end
else Discord
Outbox->>Discord: delete_messages(chat_id, ids)
loop each id
Discord->>API: fetch_message + delete
end
end
```
</a>
</details>
<sub>Reviews (2): Last reviewed commit: ["Preserve Telegram batch delete
fallback"](
|
||
|
|
28e8996121
|
Make messaging cancellation terminal (#995)
## Problem
Messaging `/clear` and `/stop` could return before cancelled node tasks
finished cleanup. Late cleanup could save stale conversation state after
`/clear` reset FCC state.
## Changes
| Before | After |
| --- | --- |
| Tree cancellation called `task.cancel()` and returned immediately. |
Tree cancellation awaits cancelled task cleanup outside tree locks with
a bounded timeout. |
| Node runners saved snapshots even after their tree was removed or
replaced. | Node runners save only when their node still belongs to the
active tree queue. |
| `/clear` deletion stopped at a batch failure and left tracking vague.
| `/clear` attempts each tracked delete independently and clears
FCC-owned tracking state. |
| Architecture docs did not state terminal cancellation ownership. |
Architecture docs assign terminal cancellation to `messaging/trees` and
guarded cleanup persistence to node runners. |
| Package metadata stayed at `3.4.0`. | Package metadata and lockfile
move to `3.4.1`. |
<!-- greptile_comment -->
<details open><summary><h3>Greptile Summary</h3></summary>
This PR makes messaging cancellation wait for node cleanup before
command cleanup continues. The main changes are:
- Drains cancelled tree tasks with a bounded timeout outside tree locks.
- Guards node-runner snapshot saves so removed or replaced trees are not
restored by late cleanup.
- Changes `/clear` deletion to try each tracked platform message
independently.
- Removes cleared branch message IDs from FCC-owned tracking state.
- Adds cancellation, stale-save, and clear-delete regression tests.
- Bumps package metadata and lockfile version to `3.4.1`.
</details>
<h3>Confidence Score: 5/5</h3>
Safe to merge with minimal risk.
The cancellation paths now drain outside tree locks with a bounded wait,
stale snapshot persistence is guarded, and `/clear` continues through
individual delete failures. Tests cover the key cancellation cleanup,
timeout, stale-save, and clear-delete cases. No blocking correctness or
security issues were found in the changed files.
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**
- Ran the messaging cancellation test suite with verbose output to
capture the command, current working directory, timestamps, and verbose
test names.
- Verified the targeted cancellation tests passed, including
test\_cancel\_tree\_waits\_for\_current\_task\_cleanup,
test\_cancel\_node\_waits\_for\_current\_task\_cleanup,
test\_cancel\_branch\_waits\_for\_current\_task\_cleanup,
test\_cancel\_all\_waits\_for\_current\_task\_cleanup\_across\_trees,
and test\_cancel\_task\_drain\_timeout\_is\_bounded.
- Verified that the coverage tests for /clear handling and stale
persistence guard also passed, including
test\_handle\_message\_clear\_command\_stops\_deletes\_and\_wipes\_state
and
test\_cancelled\_node\_runner\_does\_not\_save\_after\_clear\_replaces\_queue.
<a
href="https://app.greptile.com/trex/runs/13359514/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 |
|----------|----------|
| messaging/trees/manager.py | Makes tree, node, branch, and all-tree
cancellation await cancelled task cleanup outside tree locks with a
bounded drain helper. |
| messaging/node_runner.py | Guards runner-owned snapshot saves by
confirming the node still belongs to the active tree queue. |
| messaging/commands.py | Updates `/clear` deletion to attempt message
deletes individually and forget branch-owned message IDs after branch
clears. |
| messaging/session/message_log.py | Adds targeted removal of tracked
message IDs while keeping the per-chat ID cache synchronized. |
| tests/messaging/test_tree_queue.py | Adds cancellation-drain tests for
tree, node, branch, all-tree, and timeout-bounded cleanup paths. |
| tests/messaging/test_handler.py | Adds coverage for resilient clear
deletion, branch message-log cleanup, and stale cancellation persistence
prevention. |
</details>
<details open><summary><h3>Sequence Diagram</h3></summary>
<a href="#gh-light-mode-only">
```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User
participant Commands as messaging/commands.py
participant Manager as TreeQueueManager
participant Tree as MessageTree
participant Runner as MessagingNodeRunner
participant Store as SessionStore
participant Outbound as OutboundMessenger
User->>Commands: /clear or /stop
Commands->>Manager: cancel_tree/cancel_branch/cancel_all
Manager->>Tree: cancel_current_task()
Tree-->>Manager: cancelled asyncio.Task
Manager->>Tree: mark queued/current nodes ERROR
Manager->>Runner: task cancellation propagates
Manager->>Manager: await _drain_cancelled_tasks(timeout)
Runner->>Runner: cancellation cleanup/update UI
Runner->>Manager: check active tree for node
alt node still belongs to active queue
Runner->>Store: save_tree_snapshot(snapshot)
else tree removed or queue replaced
Runner-->>Store: skip stale save
end
Commands->>Outbound: delete tracked messages individually
Commands->>Store: clear_all or forget_message_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
participant Commands as messaging/commands.py
participant Manager as TreeQueueManager
participant Tree as MessageTree
participant Runner as MessagingNodeRunner
participant Store as SessionStore
participant Outbound as OutboundMessenger
User->>Commands: /clear or /stop
Commands->>Manager: cancel_tree/cancel_branch/cancel_all
Manager->>Tree: cancel_current_task()
Tree-->>Manager: cancelled asyncio.Task
Manager->>Tree: mark queued/current nodes ERROR
Manager->>Runner: task cancellation propagates
Manager->>Manager: await _drain_cancelled_tasks(timeout)
Runner->>Runner: cancellation cleanup/update UI
Runner->>Manager: check active tree for node
alt node still belongs to active queue
Runner->>Store: save_tree_snapshot(snapshot)
else tree removed or queue replaced
Runner-->>Store: skip stale save
end
Commands->>Outbound: delete tracked messages individually
Commands->>Store: clear_all or forget_message_ids
```
</a>
</details>
<sub>Reviews (2): Last reviewed commit: ["Bound messaging cancellation
drain"](
|
||
|
|
05dae97248
|
add telegram proxy support (#988) | ||
|
|
15cab79a43
|
Update GLM 5.2 model references | ||
|
|
770d56708a
|
Add SambaNova Cloud provider (#990) | ||
|
|
418f4963e5
|
Fix HTTP 400 when max_(completion_)tokens exceeds a model's cap (#955) (#991) | ||
|
|
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"](
|
||
|
|
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"](
|
||
|
|
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"](
|
||
|
|
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"](
|
||
|
|
58c40cf24e
|
Remove legacy server.py startup shim (#983)
## Problem The root `server.py` shim kept a second server startup path alive. Local dev, docs, and smoke should exercise the same `fcc-server` entrypoint users run. ## Changes | Before | After | | --- | --- | | Root `server.py` exposed `uvicorn server:app`. | Server startup is owned by `cli.entrypoints:serve`. | | README documented `uv run uvicorn server:app`. | README documents `uv run fcc-server` from a checkout. | | Smoke defaults launched the legacy ASGI shim. | Smoke defaults launch the local CLI server entrypoint. | | Tests covered the deleted shim. | Contracts prevent `server:app` references from returning. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR removes the legacy root `server.py` startup path and routes local startup through the packaged CLI entrypoint. The main changes are: - Deleted the root `server.py` ASGI shim. - Updated README source-run instructions to use `uv run fcc-server`. - Changed smoke server defaults to launch `cli.entrypoints:serve`. - Added contract tests to keep `server:app` references removed. - Bumped package metadata from `2.5.3` to `2.5.4` in `pyproject.toml` and `uv.lock`. </details> <h3>Confidence Score: 5/5</h3> Safe to merge with minimal risk. The changed startup path consistently uses the existing CLI serve entrypoint, smoke defaults were updated, browser launch is disabled for automated smoke runs, and contract tests prevent the deleted `server:app` path from returning. 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** - T-Rex executed the FCC server smoke script to start the service and orchestrate polling, capture, and cleanup. - The health probe logged polling attempts and finally returned a healthy status on the successful /health check. - The focused contract validation suite completed and passed with exit code 0. - The startup log records the FCC server startup, follow-on health probe activity, and shutdown with a termination exit after the probe. <a href="https://app.greptile.com/trex/runs/13305434/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 | Updates source-run documentation and project tree to remove the legacy `server.py` ASGI startup path. | | pyproject.toml | Bumps the package patch version while preserving the existing `fcc-server` and `free-claude-code` CLI entry points. | | server.py | Deletes the root ASGI shim so server startup is no longer exposed through `uvicorn server:app`. | | smoke/lib/child_process.py | Removes the legacy uvicorn command builder and keeps smoke helpers pointed at CLI entrypoint commands. | | smoke/lib/server.py | Changes default smoke server launch to `cmd_free_claude_code_serve()` and disables CLI browser opening for automated smoke runs. | | tests/contracts/test_import_boundaries.py | Adds a contract asserting `server.py` and `server:app` references stay removed and CLI scripts remain registered. | | tests/contracts/test_smoke_child_process.py | Adds contract coverage for the CLI serve command and smoke server environment overrides. | | uv.lock | Updates the editable package version in the lockfile to match `pyproject.toml`. | </details> <details open><summary><h3>Sequence Diagram</h3></summary> <a href="#gh-light-mode-only"> ```mermaid %%{init: {'theme': 'neutral'}}%% sequenceDiagram participant Dev as Developer / Smoke participant Script as fcc-server console script participant CLI as cli.entrypoints:serve participant App as api.app.create_app participant Uvicorn as uvicorn.Server Dev->>Script: uv run fcc-server Script->>CLI: serve() CLI->>CLI: load settings and migrate legacy env if needed CLI->>App: "create_app(lifespan_enabled=False)" App-->>CLI: FastAPI app CLI->>Uvicorn: run GracefulLifespanApp(host, port) Uvicorn-->>Dev: HTTP server on configured host/port ``` </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 Dev as Developer / Smoke participant Script as fcc-server console script participant CLI as cli.entrypoints:serve participant App as api.app.create_app participant Uvicorn as uvicorn.Server Dev->>Script: uv run fcc-server Script->>CLI: serve() CLI->>CLI: load settings and migrate legacy env if needed CLI->>App: "create_app(lifespan_enabled=False)" App-->>CLI: FastAPI app CLI->>Uvicorn: run GracefulLifespanApp(host, port) Uvicorn-->>Dev: HTTP server on configured host/port ``` </a> </details> <!-- greptile_failed_comments --> <h3>Comments Outside Diff (1)</h3> 1. `smoke/lib/server.py`, line 45-53 ([link]( |
||
|
|
85b601884d
|
Remove legacy future annotation imports (#982)
## Problem
Python 3.14 provides native lazy annotations, but the codebase still
relied on legacy future annotation imports. Those imports also made
type-only import cycles easier to hide instead of fixing ownership
boundaries.
## Changes
| Before | After |
| --- | --- |
| Python files used `from __future__ import annotations`. | Python files
rely on Python 3.14 native lazy annotations. |
| Some runtime modules used `TYPE_CHECKING` or local imports for
required dependencies. | Runtime modules use top-level owner-module
imports with explicit boundaries. |
| Local and GitHub guardrails only rejected type ignore suppressions. |
Local and GitHub guardrails reject type ignore suppressions and legacy
future annotation imports. |
| Agent docs only documented the no-type-ignore rule. | Agent docs
document the Python 3.14 annotation and import-boundary rules. |
<!-- greptile_comment -->
<details open><summary><h3>Greptile Summary</h3></summary>
This PR moves the codebase to Python 3.14 native lazy annotations. The
main changes are:
- Removed legacy `from __future__ import annotations` imports across
Python modules.
- Promoted selected runtime dependencies from `TYPE_CHECKING` or local
imports to explicit owner-module imports.
- Added local, GitHub, and contract-test guardrails to reject legacy
future annotation imports.
- Updated agent docs with the annotation and import-boundary rules.
- Bumped the package patch version for production-file changes.
</details>
<h3>Confidence Score: 5/5</h3>
Safe to merge with low risk.
The changes are mostly mechanical annotation cleanup with matching CI
and contract-test guardrails. Reviewed import-boundary updates did not
show a confirmed runtime cycle or dependency break.
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**
- Performed an end-to-end validation of the guardrail contract suite: an
environment check confirmed uv availability, a guardrail pytest run used
CPython 3.14.0 with 5 passing contract tests, 3 focused CI-script tests
passed, and the direct CI suppressions guardrail command (including the
legacy future-annotations grep) also passed.
<a
href="https://app.greptile.com/trex/runs/13303335/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 |
|----------|----------|
| api/runtime.py | Moves messaging, CLI manager, session, limiter, and
tree dependencies from local/type-checking imports to explicit top-level
owner-module imports. |
| messaging/platforms/telegram.py | Removes future annotations and
promotes Telegram SDK type imports into the existing availability guard.
|
| messaging/platforms/telegram_inbound.py | Removes future annotations
and imports Telegram SDK types at module scope for inbound
normalization. |
| tests/contracts/test_import_boundaries.py | Adds an AST contract that
rejects legacy future annotation imports across Python files. |
| scripts/ci.sh | Extends the local suppression check to reject legacy
future annotation imports alongside type-ignore suppressions. |
| scripts/ci.ps1 | Mirrors the local PowerShell CI suppression check for
legacy future annotations. |
| .github/workflows/tests.yml | Renames and broadens the GitHub
guardrail job to reject both type suppressions and legacy future
annotations. |
| pyproject.toml | Bumps the patch version for production-file changes.
|
</details>
<details open><summary><h3>Sequence Diagram</h3></summary>
<a href="#gh-light-mode-only">
```mermaid
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Dev as Developer/CI
participant Guard as Suppression guard
participant AST as Import-boundary contract test
participant Py as Python modules
Dev->>Guard: Run local/GitHub suppression check
Guard->>Py: "Scan *.py for type ignores and future annotations"
Guard-->>Dev: Fail if legacy annotation import remains
Dev->>AST: Run pytest contract tests
AST->>Py: Parse imports with ast
AST-->>Dev: Assert no future annotations/import-boundary violations
Py-->>Dev: Use Python 3.14 native lazy annotations
```
</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 Dev as Developer/CI
participant Guard as Suppression guard
participant AST as Import-boundary contract test
participant Py as Python modules
Dev->>Guard: Run local/GitHub suppression check
Guard->>Py: "Scan *.py for type ignores and future annotations"
Guard-->>Dev: Fail if legacy annotation import remains
Dev->>AST: Run pytest contract tests
AST->>Py: Parse imports with ast
AST-->>Dev: Assert no future annotations/import-boundary violations
Py-->>Dev: Use Python 3.14 native lazy annotations
```
</a>
</details>
<sub>Reviews (2): Last reviewed commit: ["Remove legacy future
annotations
import"](
|
||
|
|
dfbff528c6
|
Fix stream:false requests returning malformed response (matches #917, #868, #771, #497 symptom) (#977) | ||
|
|
2d265c82ee
|
Switch LM Studio to the OpenAI chat transport; add context-budget preflight (fixes silent tool-call text leaks and mid-stream truncation) (#979) | ||
|
|
b5d70bf3e0
|
Prepare CI for merge queue (#981) | ||
|
|
081fcfcda6
|
Add MiniMax provider (#980) | ||
|
|
7633337972
|
build(deps): bump the minor-and-patch group across 1 directory with 3 updates (#972) | ||
|
|
dd6bc93f55
|
build(deps): update fastapi[standard] requirement from >=0.138.1 to >=0.139.0 (#969) | ||
|
|
bd51575430
|
Fix Cloudflare Workers AI transport (#971) | ||
|
|
4601b80a36
|
Fix NIM reasoning budget fallback (#968) | ||
|
|
6a56b18882
|
Fix managed Claude diagnostics and transient retries (#965) | ||
|
|
6a48811a9a
|
build(deps): bump actions/checkout from 6.0.3 to 7.0.0 (#873) | ||
|
|
5803a06c87
|
build(deps): update fastapi[standard] requirement from >=0.136.3 to >=0.138.1 (#876) | ||
|
|
5ecce7df8f
|
build(deps): bump the minor-and-patch group across 1 directory with 5 updates (#919) | ||
|
|
e5c591c0a7 | Fix smoke subprocess text decoding | ||
|
|
bdefb46d16
|
Fix DeepSeek cache usage accounting (#937) | ||
|
|
478e96655c
|
Add Cloudflare provider (#933) | ||
|
|
156a5d55c1
|
Refactor Responses streaming into package (#932) | ||
|
|
002012dfcd
|
Refactor messaging conversation state (#931) | ||
|
|
3afdd98bd1
|
Refactor messaging transcript into package (#930) | ||
|
|
43b3e5e330
|
Refactor provider request policy ownership (#929) | ||
|
|
cdeb1aa9e2
|
Refactor settings schema ownership (#927) | ||
|
|
51157f91bd
|
Refactor admin config into catalog-driven package (#926)
## Problem
Admin config was a single responsibility hub with manually duplicated
provider metadata. Provider labels, fields, template loading,
validation, persistence, and status lived in one place.
## Changes
| Before | After |
| --- | --- |
| Admin config lived in one large `api/admin_config.py` module. | Admin
config lives in package modules for manifest, sources, values,
validation, persistence, and status. |
| Provider admin fields and UI labels were manually duplicated. |
Provider admin fields and display names derive from `PROVIDER_CATALOG`
with admin-only help overrides. |
| `fcc-init` and Admin UI loaded `.env.example` separately. | `fcc-init`
and Admin UI use shared `config.env_template` loading. |
| Architecture docs pointed to the old admin config module. |
Architecture docs describe the package owners and catalog-driven
provider manifest. |
<!-- greptile_comment -->
<details open><summary><h3>Greptile Summary</h3></summary>
This PR refactors admin configuration into a catalog-driven package. The
main changes are:
- Split the former monolithic `api/admin_config.py` into manifest,
source loading, value presentation, validation, persistence, and
provider status modules.
- Generate provider admin fields and display names from
`PROVIDER_CATALOG` with admin-specific help overrides.
- Share `.env.example` loading between `fcc-init` and Admin UI defaults
through `config.env_template`.
- Update admin routes, Admin UI provider labels, architecture docs,
version metadata, and contract/API tests for the new module layout.
</details>
<h3>Confidence Score: 5/5</h3>
The refactor appears merge-safe with no code issues identified in the
reviewed changes.
The package split, catalog-driven provider metadata, shared environment
template loading, route updates, and tests/docs changes are cohesive and
covered by corresponding contract/API/CLI test updates.
<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 manifest validation for catalog provider before and after
routes, capturing base and head responses and catalog-alignment checks,
and confirmed the validation completed successfully.
- T-Rex evaluated the shared-env-template scenarios, observing the
before run with no config.env\_template module and the after run with
the module present, with patched loader values and all consistency
checks passing, and the run exited with code 0.
- T-Rex executed the package-admin-workflow validation, verifying the
base and after import paths, the load/validate/write workflow produced
matching outputs, and the run completed with exit code 0.
<a
href="https://app.greptile.com/trex/runs/12529845/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 admin config into
catalog-drive..."](
|
||
|
|
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"](
|
||
|
|
db60452c0c
|
Split API request handling by product surface (#923) | ||
|
|
c1c8ae1031 | Fix Responses replay of malformed function calls | ||
|
|
60e5797ce4
|
Refactor provider stream engine (#883) |