文件历史

32 次代码提交

作者 SHA1 备注 提交日期
Ali Khokhar 36bb282558 Recover Claude sessions from provider context overflow (#1215)
## Problem
NVIDIA NIM can report context exhaustion as a 400 `BadRequestError`
saying its derived `max_tokens` is negative. FCC treated that as a
generic invalid request, so Claude Code could not recognize the smaller
upstream context window, compact the conversation, and replay the
interrupted turn. LM Studio also encoded Claude's recovery phrase inside
provider code instead of reporting a protocol-neutral failure. Fixes
#1198.

## Changes
- Add one protocol-neutral `context_window_exceeded` execution failure
with a non-retryable 400 contract.
- Narrowly classify only NVIDIA NIM's negative derived-`max_tokens`
signature while preserving the complete redacted provider diagnostic and
request ID.
- Let the Anthropic serializer alone add Claude's `prompt is too long`
compaction trigger; OpenAI Responses keeps a standard invalid-request
envelope.
- Migrate LM Studio's existing context preflight to the same neutral
semantic and document the ownership boundary.
- Add provider, protocol, API, trace, near-miss, and real Claude
compaction/replay coverage; bump FCC to 4.11.4.

| Before | After |
| --- | --- |
| Context overflow appeared as an ordinary provider 400 and ended the
Claude turn. | Claude receives a typed 400 with its recognized
compaction trigger, compacts once, and replays the interrupted turn
without an FCC or SDK retry loop. |

<!-- greptile_comment -->

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

This PR adds protocol-neutral recovery from provider context-window
exhaustion. The main changes are:

- Classify NVIDIA NIM negative derived-`max_tokens` errors as
context-window failures.
- Move Claude's compaction trigger into the Anthropic serializer.
- Migrate LM Studio context preflight to the neutral failure type.
- Preserve the standard OpenAI Responses invalid-request envelope.
- Add provider, protocol, API, trace, and recovery tests.
- Bump the package version to 4.11.4.
</details>

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

This looks safe to merge.

- No blocking issues found in the changed code.
- The new failure kind is covered by both protocol mappings.
- Provider classification remains narrow and non-retryable.
- The protocol-specific compaction phrase stays at the Anthropic
boundary.

<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 narrow pytest command from /home/user/repo without live
provider credentials or services, and observed a clean test run with all
tests passing.

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

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

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

| Filename | Overview |
|----------|----------|
| src/free_claude_code/providers/nvidia_nim/client.py | Adds narrow
context-window classification for nested and top-level NVIDIA NIM error
bodies. |
| src/free_claude_code/providers/lmstudio/client.py | Migrates
context-budget preflight failures to the canonical context-window
failure. |
| src/free_claude_code/core/anthropic/errors.py | Adds Anthropic mapping
and injects Claude's compaction phrase at the wire boundary. |
| src/free_claude_code/core/openai_responses/errors.py | Maps context
exhaustion to the standard OpenAI invalid-request error. |
| src/free_claude_code/providers/failure_policy.py | Adds the canonical
non-retryable status-400 context-window failure factory. |
| src/free_claude_code/core/failures.py | Adds the protocol-neutral
context-window failure category. |

</details>

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

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

```mermaid
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Provider detects context exhaustion] --> B[Context-window ExecutionFailure]
B --> C{Protocol adapter}
C -->|Anthropic Messages| D[400 invalid_request_error]
D --> E[Add prompt is too long trigger]
E --> F[Claude compacts and replays]
C -->|OpenAI Responses| G[400 invalid_request_error]
G --> H[Keep neutral provider message]
```

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

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Provider detects context exhaustion] --> B[Context-window ExecutionFailure]
B --> C{Protocol adapter}
C -->|Anthropic Messages| D[400 invalid_request_error]
D --> E[Add prompt is too long trigger]
E --> F[Claude compacts and replays]
C -->|OpenAI Responses| G[400 invalid_request_error]
G --> H[Keep neutral provider message]
```

</a>
</details>

<sub>Reviews (1): Last reviewed commit: ["Normalize provider context
overflow for
..."](https://github.com/alishahryar1/free-claude-code/commit/29c89a4c1011d986284e9d163855174d1d433293)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=45603631)</sub>

<!-- /greptile_comment -->
2026-07-20 04:23:28 -07:00
Ali Khokhar af12e7b2bb Coordinate provider recovery under concurrent load (#1205)
## Problem

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

## Changes

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

<!-- greptile_comment -->

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

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

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

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

This looks safe to merge.

No blocking issues found in the changed code.

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

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

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

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

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

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

</details>

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

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

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

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

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

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

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

</a>
</details>

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

<!-- /greptile_comment -->
2026-07-19 22:43:29 -07:00
Ali Khokhar ac2ccbdd16 Report output-limit truncation as incomplete Responses (#1180)
## Problem

Responses streams discarded the canonical Anthropic `max_tokens` stop
reason and emitted `response.completed`. Codex therefore treated
truncated provider output as a successful end and could stop midway
without explaining why. Fixes #1178.

## Changes

| Before | After |
| --- | --- |
| The Responses boundary discarded `message_delta.stop_reason`. | The
Responses assembler retains the canonical terminal stop reason. |
| Output-limit streams ended with `response.completed`. | Output-limit
streams end with `response.incomplete` and
`incomplete_details.reason=max_output_tokens`. |
| Truncated output had no dedicated Responses contract coverage. | Core
and API tests cover partial-output and zero-visible-output truncation
while preserving response ID and usage. |
| The package version was `4.8.6`. | The patch release is `4.8.7`. |

<!-- greptile_comment -->

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

This PR reports Anthropic output-limit termination as an incomplete
Responses result. The main changes are:

- Retains the canonical `message_delta.stop_reason` until stream
finalization.
- Emits `response.incomplete` with `max_output_tokens` details for
`max_tokens` termination.
- Preserves partial output, usage, and response identity.
- Adds core and API tests for visible and empty truncated output.
- Updates the package and lockfile version to 4.8.7.
</details>

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

This looks safe to merge.

No blocking issues found in the changed code. Terminal failure handling
still takes precedence over incomplete completion. Tests cover both
partial-output and zero-visible-output truncation.

<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 that after the change, both requests end with
response.incomplete instead of response.completed.
- Observed that partial output remains as 3/4/7 and zero-visible output
remains as 3/64/67, confirming the output retention behavior after the
change.
- Confirmed that created and terminal response IDs match in every
after-change case.
- Reviewed the Python contract-validation artifact to support the
conclusions.

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

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

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

| Filename | Overview |
|----------|----------|
| src/free_claude_code/core/openai_responses/streaming/assembler.py |
Retains the provider stop reason and emits an incomplete terminal
response when output reaches the token limit. |
| src/free_claude_code/core/openai_responses/streaming/event_builders.py
| Adds the Responses SSE envelope for `response.incomplete`. |
| tests/core/openai_responses/test_sse.py | Covers truncated streams
with partial output and no visible output. |
| tests/api/test_openai_responses.py | Covers output-limit reporting
through the public Responses API route. |
| pyproject.toml | Bumps the package patch version to 4.8.7. |
| uv.lock | Synchronizes the locked editable package version. |

</details>

<sub>Reviews (1): Last reviewed commit: ["Fix Responses output-limit
terminal
stat..."](https://github.com/alishahryar1/free-claude-code/commit/d41767572b0820481e3e7555c5b361b184c139c0)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=45277818)</sub>

<!-- /greptile_comment -->
2026-07-17 20:29:58 -07:00
Ali Khokhar 6455c63e1d Make reasoning policy provider-neutral and client-aware (#1148)
## Problem

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

## Changes

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

<!-- greptile_comment -->

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

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

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

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

This looks safe to merge.

No blocking issues found in the changed code.

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

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

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

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

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

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

</details>

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

<!-- /greptile_comment -->
2026-07-16 19:57:12 -07:00
wocessade f77fe8581c Add LOG_LEVEL env var to control log verbosity (#1142)
## Problem

The server always writes DEBUG logs, producing detailed request traces
customers rarely need and allowing rotated files to accumulate without a
retention cap. Supervised restarts also need to apply changed logging
settings consistently. Closes #1141.

## Changes

| Before | After |
| --- | --- |
| The file sink always starts at `DEBUG`. | `LOG_LEVEL` supports
`DEBUG`, `INFO`, `WARNING`, `ERROR`, and `CRITICAL`, with a
customer-friendly `INFO` default. |
| Structured request traces are emitted at `INFO`. | Structured request
traces are emitted at `DEBUG` and remain available for opt-in
diagnostics. |
| Logs rotate at 50 MB without a retention limit. | Logs retain five
rotated files, bounding normal usage to roughly 300 MB including the
active file. |
| Supervised restarts can keep stale sink and third-party logger levels.
| Supervised restarts replace the sink or third-party levels only when
their effective settings change. |
| The package version is `4.7.2`. | The package version is `4.7.3`. |

<!-- greptile_comment -->

<h3>Greptile Summary</h3>

This PR adds configurable file-log verbosity and improves logging
behavior across supervised restarts. The main changes are:

- Adds a validated `LOG_LEVEL` setting with an `INFO` default.
- Moves structured request traces from `INFO` to `DEBUG`.
- Retains five rotated log files.
- Replaces the file sink when its normalized path or level changes.
- Updates third-party logger levels when verbose logging changes.
- Bumps the package version to `4.7.3`.

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

This looks safe to merge.

The supervised restart path now replaces the sink when its normalized
path or level changes. Verbosity-only changes update third-party logger
levels without replacing the file sink. No blocking issues were found in
the changed code.

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

**What T-Rex did**
- T-Rex captured the baseline parent-revision import failure in
runtime-logging-01-before.log.
- T-Rex re-created the virtual environment for the current revision and
captured runtime-logging-02-after.log, which shows the same import
failure after uv reinstallation.
- T-Rex verified the uv-managed Python 3.14 environment exists but
cannot import loguru, as shown in
runtime-logging-environment-blocker.log.
- Artifacts corresponding to the three runtime-logging logs and the
Python artifact were prepared for review.

<a
href="https://app.greptile.com/trex/runs/14767708/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>

<h3>Important Files Changed</h3>

| Filename | Overview |
|----------|----------|
| src/free_claude_code/config/logging_config.py | Tracks the active sink
path, level, verbosity, and identifier so supervised restarts apply
changed logging settings. |
| src/free_claude_code/config/settings.py | Adds and validates the
`LOG_LEVEL` environment setting. |
| src/free_claude_code/runtime/bootstrap.py | Passes the configured log
level and third-party verbosity into logging setup. |
| src/free_claude_code/core/trace.py | Emits structured request traces
at `DEBUG` instead of `INFO`. |
| tests/config/test_logging_config.py | Covers path, level, and
verbosity changes along with default filtering and retention. |

<sub>Reviews (6): Last reviewed commit: ["Make customer logging
configurable and
s..."](https://github.com/alishahryar1/free-claude-code/commit/0cae08607ee8b92a51b5094de9e01cc89478dbfd)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=44854591)</sub>

<!-- /greptile_comment -->

---------

Co-authored-by: Alishahryar1 <alishahryar2@gmail.com>
2026-07-16 16:07:31 -07:00
Ali Khokhar f0b31065ee Preserve mid-conversation system messages through provider conversion (#1125)
## Problem

FCC hoisted inline Anthropic `system` messages into the top-level system
prompt during request validation. Mid-conversation system messages are
position-sensitive, so this applied later instructions retroactively,
changed the existing prompt/cache prefix, and prevented provider
conversion from seeing the original transcript.

## Changes

- Preserve inline `system` messages, content, metadata, and ordering in
Messages and token-count requests while keeping the top-level system
prompt distinct.
- Convert text-only inline system messages to OpenAI Chat `system`
messages at the same transcript position; reject unrepresentable inline
blocks before streaming instead of silently dropping them.
- Remove the lossy normalization path and its unused role enum, and
document protocol-model versus target-conversion ownership in
`ARCHITECTURE.md`.
- Cover API routing, model serialization, cache-prefix stability, text
blocks, tool-result ordering, invalid content, and token counting; bump
the package to `4.6.2`.
- Verify all five local CI checks (2,287 tests) and the ordered
transcript against NVIDIA NIM, OpenRouter, Gemini, DeepSeek, Mistral,
and Hugging Face.

<!-- greptile_comment -->

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

This PR preserves inline Anthropic system messages through provider
conversion. The main changes are:

- Keeps top-level and inline system content separate and ordered.
- Converts text-only inline system messages without moving them.
- Rejects system blocks that OpenAI Chat cannot represent safely.
- Updates request detection to ignore system context when counting user
turns.
- Adds serialization, routing, token-counting, and conversion coverage.
- Updates the package version and architecture documentation.
</details>

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

This looks safe to merge.

The leading-system detection path ignores system entries when counting
user turns. Inline system content remains ordered for provider
conversion. Unsupported system blocks fail explicitly instead of being
dropped. No blocking issues were found in the changed code.

No files require 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 that the transcript roles now follow the order user,
assistant, system, user and that the top-level prompt remains separate.
- Verified that inline system content is no longer counted in message
tokens and that cache\_control metadata survives parsing.
- Confirmed that the converted OpenAI transcript preserves position and
cache prefix.
- Observed that a system message following a tool result is converted as
assistant, tool, system.
- Ran the focused pytest and confirmed 209 passed in 2.82s with exit
code 0.

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

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

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

| Filename | Overview |
|----------|----------|
| src/free_claude_code/core/anthropic/models.py | Preserves system-role
messages in the original transcript instead of hoisting them into the
top-level prompt. |
| src/free_claude_code/core/anthropic/conversion.py | Converts ordered
text-only system messages and rejects unsupported system content before
streaming. |
| src/free_claude_code/api/detection.py | Builds a read-only semantic
view of system context and conversational user turns for local request
detection. |

</details>

<sub>Reviews (2): Last reviewed commit: ["Restore optimizations with
inline
system..."](https://github.com/alishahryar1/free-claude-code/commit/6605ede7f604053381552106489dbd16bcd37987)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=44423885)</sub>

<!-- /greptile_comment -->
2026-07-15 03:37:11 -07:00
Ali Khokhar 984c4c23b7 Fix Auto Mode classifier responses when stream is omitted (#1098)
## Problem

Claude Code Auto Mode classifier requests omit `stream`, which means
they expect a non-streaming Messages response. FCC treated omission as
streaming, returned SSE, and caused Claude to report the classifier
model as temporarily unavailable. Fixes #1094.

## Changes

| Before | After |
| --- | --- |
| Omitted `stream` defaulted to streaming SSE. | Omitted `stream`
defaults to a complete JSON Message; only `stream: true` selects SSE. |
| Classifier side queries received a body without top-level `usage`. |
Classifier side queries receive a JSON Message with top-level `usage`
while thinking remains disabled. |
| Tests encoded FCC's nonstandard streaming default. | Model and
HTTP-boundary tests enforce Anthropic's response-mode contract. |
| The package version was 4.3.0. | The package version is 4.3.1. |

<!-- greptile_comment -->

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

This PR fixes Messages response mode handling when clients omit
`stream`. The main changes are:

- Defaulted Anthropic Messages requests to non-streaming JSON.
- Returned SSE only when `stream: true` is set.
- Updated classifier, handler, web-tool, and model tests for the new
contract.
- Documented the default response mode and bumped the package version.
</details>

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

This looks safe to merge after deciding whether `stream: null` should
remain accepted.

The JSON-by-default Messages path is covered in the model, handler, and
API tests. Explicit streaming still flows through the SSE path.

Clients that send `stream: null` can now get a validation error instead
of a response.

<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 full test suite for the code under test; pytest completed with
132 tests passed in 2.96s and exited with code 0.
- Validated the testclient probe non-stream request returned 200 OK with
a JSON message.
- Validated the testclient probe stream request returned 200 OK with a
text/event-stream SSE and routing/behaviors as expected (routed\_stream
true, thinking\_enabled\_kwarg false).

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

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

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

| Filename | Overview |
|----------|----------|
| src/free_claude_code/core/anthropic/models.py | Changes
`MessagesRequest.stream` to default to non-streaming JSON and reject
null values. |
| src/free_claude_code/api/handlers/messages.py | Aggregates internal
SSE into JSON unless streaming was explicitly requested. |
| src/free_claude_code/api/routes.py | Updates the Messages route
description to match the new JSON-by-default behavior. |
| src/free_claude_code/core/anthropic/sse_aggregation.py | Updates
aggregation documentation for omitted and false stream requests. |
| tests/api/test_api.py | Adds coverage for classifier-style requests
that omit `stream` and expect JSON. |
| tests/api/test_api_handlers.py | Marks streaming handler tests with
explicit `stream=True`. |
| tests/api/test_web_server_tools.py | Marks the forced web-search
streaming test with explicit `stream=True`. |
| tests/core/anthropic/test_models.py | Updates model expectations for
the new default and adds null-stream rejection coverage. |
| pyproject.toml | Bumps the package version to `4.3.1`. |
| uv.lock | Keeps the editable package version in sync with
`pyproject.toml`. |
| ARCHITECTURE.md | Documents that Messages responses are non-streaming
unless `stream: true` is provided. |

</details>

<a
href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22ali%2Ffix-auto-mode-omitted-stream%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22ali%2Ffix-auto-mode-omitted-stream%22.%0A%0AFix%20the%20following%201%20code%20review%20issue.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%201%0Asrc%2Ffree_claude_code%2Fcore%2Fanthropic%2Fmodels.py%3A186%0A**Null%20Stream%20Now%20Fails%20Validation**%0A%0AWhen%20a%20client%20serializes%20an%20unspecified%20optional%20stream%20flag%20as%20%60%22stream%22%3A%20null%60%2C%20this%20narrowed%20field%20rejects%20the%20request%20before%20the%20handler%20can%20return%20the%20new%20non-streaming%20JSON%20response.%20The%20old%20model%20accepted%20that%20input%2C%20so%20these%20clients%20now%20receive%20a%20validation%20error%20instead%20of%20a%20Message%20object.%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1098&platform=github"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodexDark.svg?v=6"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"><img
alt="Fix All in Codex"
src="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"></picture></a>

<sub>Reviews (1): Last reviewed commit: ["Fix omitted Messages stream
default"](https://github.com/alishahryar1/free-claude-code/commit/ca61e5ad4adf085d5cef1e0e5f3a8ae26d189853)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43859149)</sub>

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

<!-- /greptile_comment -->
2026-07-13 09:15:01 -07:00
Ali Khokhar 3a7e0ccf7a Remove the native Anthropic provider transport (#1067)
## Problem

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

## Changes

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

<!-- greptile_comment -->

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

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

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


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

This looks safe to merge.

No blocking issues found in the changed code.

None.

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

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

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

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


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




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

</details>


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

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

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

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

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

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

<!-- /greptile_comment -->
2026-07-11 17:53:42 -07:00
Ali Khokhar 5ffa47fbc3 Make response stream lifetimes explicit (#1060)
## Problem

Client disconnects and response-start send failures could abandon a
prefetched provider stream and its generation lease. Re-yielding
iterators and response-proxy middleware left no owner that closed the
complete body chain before runtime release.

## Changes

| Before | After |
| --- | --- |
| Starlette body iteration indirectly owned stream cleanup and lease
release. | One FCC streaming response surrounds the real ASGI send,
closes the body transitively, then releases the lease exactly once. |
| The prefetched first-frame generator could not close its tail before
replay began. | An explicit closeable replay iterator owns the
prefetched tail in every commit state. |
| Tracing, execution, Responses conversion, and native transport
transforms re-yielded inputs without closing them. | Every retained
transform closes its direct input; redundant transport wrappers are
removed while provider construction failures remain deferred. |
| Function-style correlation middleware proxied and canceled streaming
responses. | Pure ASGI correlation spans the complete stream, preserves
request headers and log context, and keeps the catch-all 500 fallback
correlated. |
| Repeated cancellation could interrupt pre-start and post-start
cleanup. | Shielded completion tasks finish body closure before release
and then restore caller cancellation. |
| The package version was 3.5.5. | The package version is 3.5.6; full CI
passes with 2,162 tests and stable live API/provider/disconnect/client
smoke passes 63 scenarios. |

<!-- greptile_comment -->

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

This PR makes streaming response ownership explicit across the API path.
The main changes are:

- Adds a managed streaming response that closes the body chain before
releasing provider resources.
- Adds a prefetched replay iterator for first-frame commit handling.
- Moves request correlation to pure ASGI middleware for full-stream
context.
- Propagates direct-input closure through execution, tracing, Responses
conversion, and provider transports.
- Bumps the package version and updates tests for stream cleanup
behavior.
</details>

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

This looks safe to merge.

No blocking issues found in the changed code.

None.

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

**What T-Rex did**
- Validated the execution environment by reviewing the environment proof
log, confirming uv 0.11.28, CPython 3.14.0, a repo-local virtual
environment, and exit code 0.
- Verified that the requested test command was executed, based on the
test proof log.
- Confirmed the test run completed successfully with 91 tests passing in
3.63 seconds, as shown in the test proof log.

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

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

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

| Filename | Overview |
|----------|----------|
| src/free_claude_code/api/response_streams.py | Adds the managed
response owner, first-frame replay iterator, and shielded cleanup flow.
|
| src/free_claude_code/api/request_ids.py | Adds pure ASGI request
correlation and response-start header injection. |
| src/free_claude_code/core/trace.py | Adds shared stream input closure
tracing and closes traced inputs on exit. |
| src/free_claude_code/application/execution.py | Closes provider stream
iterators from the executor wrapper when streaming ends. |
|
src/free_claude_code/providers/transports/anthropic_messages/transport.py
| Returns provider runner streams directly and closes layered SSE
iterators explicitly. |

</details>

<sub>Reviews (2): Last reviewed commit: ["Make response stream lifetimes
explicit"](https://github.com/alishahryar1/free-claude-code/commit/cb698c62c08924d5f80a1cea7dbd19c0b8af26a2)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43527620)</sub>

<!-- /greptile_comment -->
2026-07-11 09:33:31 -07:00
Ali Khokhar 23ed6bc87e Make provider backoff admission monotonic (#1053)
## Problem

Concurrent provider requests could miss or shorten a reactive backoff
while waiting for proactive admission. Separate gate commits could also
waste quota or release requests as an expiry burst.

## Changes

| Before | After |
| --- | --- |
| Reactive deadlines were checked once and replaced by later backoffs. |
Reactive deadlines are rechecked until clear and only extended by later
backoffs. |
| Proactive capacity was recorded before the final reactive decision. |
Conditional commit records proactive capacity only while the reactive
deadline is clear. |
| The limiter exposed an ambiguous `set_blocked` callback. | Both
transport families use the explicit `extend_reactive_block` operation. |
| Cross-gate races and wait cancellation lacked deterministic coverage.
| Deterministic tests cover conditional commit, extensions,
non-shortening, and cancellation. |
| The architecture left gate interaction implicit. | The architecture
defines monotonic two-gate admission without wasted quota or expiry
bursts. |

<!-- greptile_comment -->

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

This PR makes provider backoff admission monotonic. The main changes
are:

- Conditional proactive admission before recording quota.
- Reactive waits that recheck extended deadlines.
- Monotonic reactive block extension for retry and stream failure paths.
- Tests for admission retries, deadline extension, non-shortening, and
cancellation.
- Version and architecture updates for the new limiter behavior.
</details>

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

This looks safe to merge.

No blocking issues found in the changed code.

None.

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

**What T-Rex did**
- Ran the provider-rate-limit pytest suite; all 53 tests completed and
passed in 4.02 seconds with EXIT\_CODE: 0.
- Started the transport-backoff pytest run; it advanced through most
tests before xdist workers were terminated and the process exited with
EXIT\_CODE: 143.
- Verified that no live provider credentials, Docker containers, or
external service smoke tests were used.

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

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

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

| Filename | Overview |
|----------|----------|
| src/free_claude_code/core/rate_limit.py | Adds conditional
sliding-window admission without recording quota on rejection. |
| src/free_claude_code/providers/rate_limit.py | Reworks provider
admission to combine reactive waits with final proactive commit checks.
|
| src/free_claude_code/providers/transports/anthropic_messages/stream.py
| Routes stream rate-limit marking through monotonic reactive block
extension. |
| src/free_claude_code/providers/transports/openai_chat/stream.py |
Routes stream rate-limit marking through monotonic reactive block
extension. |
| tests/core/test_strict_sliding_window.py | Covers rejected conditional
admission and commit-time timestamp recording. |
| tests/providers/test_provider_rate_limit.py | Covers reactive
admission retries, extended deadlines, cancellation, and non-shortening
behavior. |

</details>

<sub>Reviews (2): Last reviewed commit: ["Make provider backoff
admission
monotoni..."](https://github.com/alishahryar1/free-claude-code/commit/a5c637393d1996e51c195875636ecb0536522932)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43504969)</sub>

<!-- /greptile_comment -->
2026-07-11 05:07:47 -07:00
Ali Khokhar 26cc73e6ce Use installed metadata as the single package version source (#1051)
## Problem

FCC runtime surfaces reported stale, unrelated versions, and users could
not inspect the installed FCC version without starting the server or
scaffolding configuration.

## Changes

| Before | After |
| --- | --- |
| FastAPI/OpenAPI and the web-tools user agent duplicated stale release
literals. | Every FCC runtime surface reads installed distribution
metadata through one `core.version` owner. |
| FCC-owned commands had no side-effect-free version query. |
`fcc-server`, `free-claude-code`, and `fcc-init` print the installed
version whenever `--version` is present, before any configuration or
process work. |
| Wrapped Claude and Codex argument handling was adjacent to FCC command
behavior. | Claude and Codex launchers remain transparent and pass
`--version` to their wrapped clients unchanged. |
| A source-only checkout had no explicit fallback contract. | Missing
distribution metadata reports `0+unknown`, while malformed installed
metadata still fails visibly. |
| Version behavior lacked end-to-end contract coverage. | API, CLI,
metadata, user-agent, feature-inventory, and live command tests verify
one value and zero CLI side effects; the complete 2,077-test CI gate
passes. |

<!-- greptile_comment -->

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

This PR makes installed package metadata the single source for the FCC
version. The main changes are:

- Adds `core.version.package_version()` with a source-checkout fallback.
- Uses that version in FastAPI/OpenAPI metadata and web-tool User-Agent
headers.
- Adds side-effect-free `--version` handling for FCC-owned CLI
entrypoints.
- Keeps Claude and Codex launchers transparent to wrapped client
arguments.
- Updates tests, smoke coverage, docs, and package metadata to `3.5.0`.
</details>

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

This looks safe to merge.

No blocking issues found in the changed code.

No files need attention.

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

**What T-Rex did**
- The version contract pytest run completed successfully with
EXIT\_CODE: 0, as captured in the version contract pytest log.
- The direct CLI version commands sequence completed with final
EXIT\_CODE: 0, as recorded in the CLI version commands log.

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

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

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

| Filename | Overview |
|----------|----------|
| src/free_claude_code/core/version.py | Adds the canonical
installed-metadata version helper with an explicit missing-metadata
fallback. |
| src/free_claude_code/cli/entrypoints.py | Adds early `--version`
output for FCC-owned server and init commands before startup or config
work. |
| src/free_claude_code/api/app.py | Uses the centralized package version
for FastAPI and OpenAPI metadata. |
| src/free_claude_code/api/web_tools/constants.py | Uses the centralized
package version in the outbound web-tool User-Agent. |

</details>

<sub>Reviews (2): Last reviewed commit: ["Use installed metadata as the
package
ve..."](https://github.com/alishahryar1/free-claude-code/commit/f240f9c363115e63f407d7ac8d5c35833f6b66c8)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43500448)</sub>

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

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

## Changes

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

<!-- greptile_comment -->

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

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

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

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

This looks safe to merge.

No blocking issues found in the changed code.

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

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

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

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

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

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

</details>

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

<!-- /greptile_comment -->
2026-07-11 03:25:01 -07:00
Ali Khokhar e22a38b2c2 Canonicalize provider failure and retry ownership (#1046)
## Problem

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

## Changes

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

<!-- greptile_comment -->

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

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

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

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

This looks safe to merge.

No blocking issues found in the changed code.

No files need attention.

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

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

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

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

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

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

</details>

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

<!-- /greptile_comment -->
2026-07-10 21:33:50 -07:00
Ali Khokhar 4a0a0360de Move protocol models to their protocol owners (#1044)
## Problem

Anthropic Messages and OpenAI Responses wire models lived under the
inbound API adapter. Neutral protocol and provider code therefore
duck-typed requests, obscuring ownership and weakening dependency
boundaries.

## Changes

| Before | After |
| --- | --- |
| The API package owned Anthropic and Responses protocol models. | Each
protocol package owns and publicly exports its wire models. |
| Core and provider request paths accepted `Any` and probed known fields
with `getattr()`. | Core, transports, and providers consume concrete
`MessagesRequest` values. |
| Responses conversion and streaming received a dumped request mapping.
| Responses conversion and streaming receive one concrete
`OpenAIResponsesRequest`. |
| Anthropic request snapshots lived in generic tracing code. | Anthropic
request snapshots live with the protocol while generic tracing stays
protocol-independent. |
| Protocol tests and provider request doubles reflected the old API
ownership. | Protocol tests live under core and provider tests construct
real wire requests. |
| The API model package mixed protocol and model-catalog schemas. | The
API model package is removed, with catalog schemas beside catalog
construction and no compatibility shim. |
| Package version was `3.4.18`. | Package version is `3.4.19` with an
updated lockfile. |

<!-- greptile_comment -->

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

This PR moves protocol request models to their protocol-owned packages.
The main changes are:

- Anthropic Messages models now live under `core.anthropic`.
- OpenAI Responses models now live under `core.openai_responses`.
- API handlers, routes, providers, and tests now use concrete protocol
request types.
- Anthropic request snapshots moved beside the Anthropic protocol
models.
- API model catalog schemas were kept with catalog response
construction.
- The package version and lockfile were updated.
</details>

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

This looks safe to merge.

No blocking issues were found in the changed code. Internal callers were
updated to pass the new concrete protocol models, and no stale internal
imports from the removed API model package were identified.

No files need attention.

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

**What T-Rex did**
- The Pytest run for protocol ownership focused tests completed, showing
71 passed in 6.24s and EXIT\_CODE: 0.
- A protocol import smoke script was generated for the
import/conversion/trace workflow.
- The protocol import smoke run completed successfully, including model
ownership output, adapter payload evidence, and trace snapshot evidence,
with EXIT\_CODE: 0.

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

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

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

| Filename | Overview |
|----------|----------|
| src/free_claude_code/core/anthropic/models.py | Anthropic wire request
and response models moved under the Anthropic protocol package. |
| src/free_claude_code/core/anthropic/native_messages_request.py |
Native Anthropic serialization now expects concrete `MessagesRequest`
instances. |
| src/free_claude_code/core/anthropic/conversion.py | OpenAI chat
conversion now reads fields directly from `MessagesRequest`. |
| src/free_claude_code/core/anthropic/request_snapshot.py | Anthropic
request snapshotting moved from generic tracing into the protocol
package. |
| src/free_claude_code/core/openai_responses/models.py | OpenAI
Responses ingress models moved under the Responses protocol package. |
| src/free_claude_code/core/openai_responses/input.py | Responses
conversion now consumes the concrete request model instead of a dumped
mapping. |
| src/free_claude_code/core/openai_responses/streaming/assembler.py |
Responses stream assembly now reads request attributes from
`OpenAIResponsesRequest`. |
| src/free_claude_code/api/routes.py | Routes now import protocol
request models from their new core owners. |
| src/free_claude_code/api/model_catalog.py | Model-list response
schemas now live with model catalog construction. |

</details>

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

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

```mermaid
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  API[API routes and handlers] --> Anthropic[core.anthropic models and helpers]
  API --> Responses[core.openai_responses models and adapter]
  Responses --> Anthropic
  Providers[Provider clients and transports] --> Anthropic
  Anthropic --> Trace[core.trace sanitization]
  API --> Catalog[api.model_catalog response schemas]
```

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

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart LR
  API[API routes and handlers] --> Anthropic[core.anthropic models and helpers]
  API --> Responses[core.openai_responses models and adapter]
  Responses --> Anthropic
  Providers[Provider clients and transports] --> Anthropic
  Anthropic --> Trace[core.trace sanitization]
  API --> Catalog[api.model_catalog response schemas]
```

</a>
</details>

<sub>Reviews (1): Last reviewed commit: ["Move protocol models to their
protocol
o..."](https://github.com/alishahryar1/free-claude-code/commit/f1be5c1af4a10da710f80b5f9e7f6044a601f6af)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43459428)</sub>

<!-- /greptile_comment -->
2026-07-10 19:26:27 -07:00
Ali Khokhar 1278d00873 Restore protocol-correct provider errors without client retry loops (#1033)
## Problem

Provider failures before streaming were converted to HTTP 200 SSE
errors, masking typed upstream statuses as malformed proxy responses.
This regressed #1026's error visibility while solving client retry
loops; fixes #1031.

## Changes

| Before | After |
| --- | --- |
| Pre-start Messages failures returned HTTP 200 SSE errors. | Pre-start
Messages failures return typed non-2xx JSON with `x-should-retry:
false`. |
| Non-streaming Messages could preserve partial content after an
internal stream error. | Non-streaming Messages discard partial content
and return the mapped Anthropic error. |
| Post-start failures could synthesize a successful stop lifecycle. |
Post-start failures emit protocol-native terminal errors without a fake
success stop. |
| Responses failures lacked consistent retry ownership and correlation.
| Responses failures retain typed envelopes, retry suppression, response
IDs, and request IDs. |
| Request IDs were generated independently across layers. | One
ingress-owned request ID flows through response headers, provider calls,
error bodies, and traces. |
| Provider exceptions owned Anthropic serialization. | Neutral Anthropic
utilities own error envelopes, status mapping, and redacted diagnostics.
|
| Failure-path smoke expected the regressed HTTP 200 shape. |
Failure-path smoke verifies typed JSON and one downstream Claude CLI
request. |
| Package metadata remained at 3.4.15. | Package metadata and the
lockfile advance to 3.4.16. |

<!-- greptile_comment -->

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

This PR restores protocol-correct provider error handling for Messages
and Responses. The main changes are:

- Pre-start provider failures return typed JSON errors with retry
suppression.
- Streaming failures use protocol-native terminal events after commit.
- Request IDs now flow from ingress through headers, traces, provider
calls, and error bodies.
- Shared Anthropic and OpenAI error helpers now shape payloads and
redact diagnostics.
- Provider-error smoke coverage and package metadata were updated.
</details>

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

Committed streaming failure paths still expose exception-derived
messages to clients.

Pre-start provider error handling is more protocol-correct, and the
completed-message lifecycle conflict appears fixed.

Messages and Responses streams still need fixed safe messages after the
HTTP response has committed.

<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**
- I executed a focused uv-run harness against the Anthropic SSE
committed-stream path and reproduced a committed StreamingResponse that
yielded a terminal error SSE frame containing an internal diagnostic
marker.
- I ran a focused uv-run against iter\_responses\_sse\_from\_anthropic
and confirmed the stream was committed, with the later response.failed
SSE event carrying the internal diagnostic string in response.error.
- I completed provider error-handling verification, validating the
deterministic pytest path and running the local /v1/responses probe
script, which reported a 429 status with downstream\_call\_count: 1 and
related metadata, using the exact probe to exercise the failing
provider.

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

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

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

| Filename | Overview |
|----------|----------|
| src/free_claude_code/api/response_streams.py | Pre-start Messages
errors now return typed JSON, but committed terminal SSE errors still
use exception-derived text. |
| src/free_claude_code/core/openai_responses/stream.py | Responses
streams now emit protocol failure events, but committed failures still
use exception-derived text. |
| src/free_claude_code/core/anthropic/streaming/ledger.py | Completed
Anthropic message streams now suppress late terminal errors after
`message_stop`. |
| src/free_claude_code/core/anthropic/errors.py | Shared Anthropic error
payload helpers now add request IDs, status mapping, and diagnostic
redaction. |

</details>

<a
href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22fix%2Fprotocol-correct-provider-errors%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22fix%2Fprotocol-correct-provider-errors%22.%0A%0AFix%20the%20following%202%20code%20review%20issues.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%202%0Asrc%2Ffree_claude_code%2Fapi%2Fresponse_streams.py%3A115-117%0A**Committed%20Stream%20Exception%20Text**%0A%0AWhen%20an%20Anthropic%20stream%20fails%20after%20the%20first%20chunk%20has%20committed%2C%20this%20terminal%20frame%20still%20derives%20the%20public%20SSE%20message%20from%20the%20exception.%20For%20unknown%20SDK%20or%20runtime%20errors%2C%20%60get_user_facing_error_message%28%29%60%20can%20return%20sanitized%20%60str%28exc%29%60%2C%20so%20internal%20URLs%2C%20payload%20fragments%2C%20or%20unsupported%20secret%20formats%20can%20still%20reach%20the%20client.%0A%0A%23%23%23%20Issue%202%20of%202%0Asrc%2Ffree_claude_code%2Fcore%2Fopenai_responses%2Fstream.py%3A49%0A**Failed%20Response%20Exception%20Text**%0A%0AAfter%20a%20Responses%20stream%20has%20emitted%20%60response.created%60%2C%20this%20failure%20event%20still%20uses%20exception-derived%20text%20as%20the%20public%20error%20message.%20If%20an%20unexpected%20provider%20or%20SDK%20exception%20includes%20internal%20diagnostics%20or%20a%20credential%20shape%20outside%20the%20redaction%20patterns%2C%20the%20committed%20%60response.failed%60%20event%20exposes%20it%20to%20the%20client.%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1033&platform=github"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodexDark.svg?v=6"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"><img
alt="Fix All in Codex"
src="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"></picture></a>

<sub>Reviews (2): Last reviewed commit: ["fix(streaming): ignore errors
after
mess..."](https://github.com/alishahryar1/free-claude-code/commit/157eb504e9c8e15f6591bd72391810610be078f7)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=43242122)</sub>

> Greptile also left **2 inline comments** on this PR.

**Context used:**

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

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

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

## Changes

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

<!-- greptile_comment -->

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

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

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

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

This PR is safe to merge with minimal risk.

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

No files require special attention.

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

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

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

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

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

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

</details>

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

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

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

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

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

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

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

</a>
</details>

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

<!-- /greptile_comment -->
2026-07-09 01:19:05 -07:00
Ali Khokhar 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"](https://github.com/alishahryar1/free-claude-code/commit/ae1635d2ce3a232ba7f4c0b9787f7b604b625544)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=42274270)</sub>

<!-- /greptile_comment -->
2026-07-06 23:00:06 -07:00
Ali Khokhar 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"](https://github.com/alishahryar1/free-claude-code/commit/6e6cda69da243bbdb92831207aecb3731ad469f8)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=41875785)</sub>

<!-- /greptile_comment -->
2026-07-04 21:41:51 -07:00
Ali Khokhar 6a56b18882 Fix managed Claude diagnostics and transient retries (#965) 2026-07-03 12:12:54 -07:00
Alishahryar1 c1c8ae1031 Fix Responses replay of malformed function calls 2026-06-27 08:29:35 -07:00
Ali Khokhar 60e5797ce4 Refactor provider stream engine (#883) 2026-06-27 07:24:27 -07:00
Ali Khokhar b3ac9c2e5e Add Responses reasoning usage details (#860)
## Problem

Codex receives reasoning text from the Responses stream, but FCC does
not emit reasoning-token usage details. Codex reports zero reasoning
tokens even when thinking is present.

## Changes

| Before | After |
| --- | --- |
| Responses usage reported only input, output, and total tokens. |
Responses usage reports input, output, total, and reasoning-token
details when reasoning text exists. |
| Reasoning text had no adapter-owned token estimate. | Reasoning text
gets a Responses-owned best-effort token estimate. |
| Reasoning estimates could exceed reported output tokens. | Reasoning
estimates are capped at reported output tokens. |
| Text-only Responses usage kept the base shape. | Text-only Responses
usage keeps the base shape. |
2026-06-18 16:39:27 -07:00
Alishahryar1 c024bf6892 Fix stream cleanup context handling.
Avoid contextvar-based log context in SSE generators and treat GeneratorExit as quiet teardown.
2026-06-17 20:43:38 -07:00
Alishahryar1 da672af337 Skip passive tool_search in Responses conversion.
Codex includes OpenAI tool_search in the tools array; omit it from the Anthropic payload like other passive hosted tools so fcc-codex requests do not fail at conversion.
2026-06-17 20:27:11 -07:00
Ali Khokhar 8d2e5b95f7 Refactor OpenAI Responses into modular adapter facade (#847)
## Summary

- Split monolithic `core/openai_responses/conversion.py` and `sse.py`
into focused protocol modules (input, output, stream, tools, reasoning,
events, etc.) behind an `OpenAIResponsesAdapter` facade.
- Wire `ClaudeProxyService.create_response()` through the adapter
instead of importing conversion helpers directly, tightening the
API/import boundary.
- Add Codex bridging for Responses `custom_tool_call` items and document
the adapter architecture in `ARCHITECTURE.md`.

## Test plan

- [x] `uv run pytest tests/core/openai_responses/
tests/api/test_openai_responses.py tests/cli/test_adapters.py
tests/contracts/test_import_boundaries.py`
- [x] Full CI via `.\scripts\ci.ps1`
2026-06-17 20:19:51 -07:00
Ali Khokhar e2fa4b66d9 Extract shared stream recovery session for provider transports (#835)
## Summary

- Add `StreamRecoverySession` in
`core/anthropic/stream_recovery_session.py` to centralize early-retry
classification, holdback buffering, retry counting, and flush/discard
behavior shared by Anthropic and OpenAI transports.
- Refactor `AnthropicMessagesTransport` and `OpenAIChatTransport` to use
the shared session instead of duplicating recovery holdback and
early-retry logic.
- Update architecture docs and tests for per-delta overlap trim on
midstream recovery; bump version to 2.2.1.

## Test plan

- [x] `uv run pytest tests/core/anthropic/test_stream_recovery.py`
- [x] `uv run pytest tests/providers/test_anthropic_messages.py
tests/providers/test_streaming_errors.py`
2026-06-16 22:01:53 -07:00
Alishahryar1 dcc4b50aae Fix Codex namespace Responses tools 2026-06-16 16:49:59 -07:00
Ali Khokhar 3abe41d270 Add Codex support (#691) 2026-06-16 16:32:43 -07:00
Alishahryar1 e79b430cc2 Raise stream and upstream retry attempts to five total.
Align early transparent, mid-stream recovery, and 429/5xx execute_with_retry
to five attempts; bump version to 1.2.40.
2026-06-02 22:26:07 -07:00
Alishahryar1 0eee1da072 Try mid stream retries 2026-05-31 16:28:44 -07:00
Alishahryar1 29e7714337 feat(logging): structured TRACE events and end-to-end request correlation
Add core/trace.py with trace_event, traced_async_stream, and payload snapshots.
Merge TRACE fields into JSON logs; promote claude_session_id, http path/method.
Instrument API, messaging/CLI, and OpenAI-compat/native provider paths.
Harden log sink with enqueue and stdlib intercept re-entrancy guard.
Document behavior in .env.example and README; extend tests.
2026-05-10 18:24:48 -07:00
Alishahryar1 f3a7528d49 Major refactor: API, providers, messaging, and Anthropic protocol
Consolidates the incremental refactor work into a single change set: modular web tools (api/web_tools), native Anthropic request building and SSE block policy, OpenAI conversion and error handling, provider transports and rate limiting, messaging handler and tree queue, safe logging, smoke tests, and broad test coverage.
2026-04-26 03:01:14 -07:00