main
38 次代码提交
| 作者 | SHA1 | 备注 | 提交日期 | |
|---|---|---|---|---|
|
|
5305bd7e08 |
Remove obsolete init and server alias commands (#1220)
## Problem
FCC still publishes `fcc-init` and the `free-claude-code` server alias
from an obsolete installation flow. Configuration creation now belongs
to the Admin UI, while `fcc-server` owns startup and legacy migration.
## Changes
| Before | After |
| --- | --- |
| The package installs six console commands. | The package installs only
`fcc-server`, `fcc-claude`, `fcc-codex`, and `fcc-pi`. |
| `fcc-init` duplicates configuration creation outside the Admin UI. |
The Admin UI exclusively creates managed configuration, and server
startup retains legacy migration. |
| Smoke contracts and architecture describe the retired commands. |
Smoke contracts and architecture describe the supported command surface.
|
| Installer safety lists contain unexplained retired names. | Installer
safety lists document why retired names remain detectable during updates
and uninstall. |
| The package version is `4.11.4`. | The package version is `4.11.5`. |
<!-- greptile_comment -->
<details open><summary><h3>Greptile Summary</h3></summary>
This PR retires the obsolete initialization command and server alias.
The main changes are:
- Removes `fcc-init` and `free-claude-code` from package scripts.
- Moves fresh configuration creation exclusively to the Admin UI.
- Keeps legacy environment migration in `fcc-server` startup.
- Updates smoke coverage, installer comments, documentation, and package
metadata.
</details>
<h3>Confidence Score: 4/5</h3>
The CLI removal needs a compatible release version or temporary aliases
before merging.
Existing automation can lose `fcc-init` and `free-claude-code` after a
patch upgrade. Fresh installs can still start the server and create
configuration through the Admin UI.
pyproject.toml and uv.lock; legacy configuration migration remains
before settings loading.
<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 reproduced the patch upgrade path by installing base revision
|
||
|
|
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 --> |
||
|
|
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 --> |
||
|
|
4f56a6aa17 |
Add Fable as a first-class Claude routing tier (#1099)
## Problem Claude Code now sends `claude-fable-5` for the Fable alias, but FCC treated it as an unrecognized model and collapsed it into the global fallback route. Users could not map Fable traffic or reasoning behavior independently. Fixes #1097. ## Changes | Before | After | | --- | --- | | Fable requests inherited `MODEL` and `ENABLE_MODEL_THINKING`. | Fable requests use `MODEL_FABLE` and `ENABLE_FABLE_THINKING` when configured, otherwise inherit the existing defaults. | | `/v1/models` omitted Claude Fable 5. | `/v1/models` advertises the canonical `claude-fable-5` identifier. | | Admin, documentation, validation, and smoke contracts described three Claude tiers. | Admin, documentation, validation, and smoke contracts describe Fable alongside Opus, Sonnet, and Haiku. | | The package version was `4.3.1`. | The package version is `4.4.0`. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR adds Fable as a Claude routing tier. The main changes are: - `MODEL_FABLE` and `ENABLE_FABLE_THINKING` settings. - Fable routing and thinking resolution in `ModelRouter`. - `claude-fable-5` in the model catalog. - Admin, docs, smoke, and test coverage updates. - Package version bump to `4.4.0`. </details> <h3>Confidence Score: 4/5</h3> The changed routing path needs a fix for direct provider model ids containing `fable`. Fable settings, validation, admin fields, and model listing are consistent with the existing tier patterns. Blank Fable settings inherit the existing defaults. Direct provider model ids can receive the Fable thinking override when their model name contains `fable`. src/free_claude_code/application/routing.py <details><summary><h3><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="20" align="absmiddle"></a> T-Rex Logs</h3></summary> **What T-Rex did** - Reproduced the Fable thinking overmatch by running a focused Python repro that disables global thinking and enables Fable thinking, then resolves sambanova/my-fable-ensemble-v2. - The repro confirmed direct routing preserved provider\_id=sambanova, provider\_model=my-fable-ensemble-v2, and provider\_model\_ref=sambanova/my-fable-ensemble-v2, with resolved\_thinking\_enabled and thinking\_enabled both true. - Ran the fable-tier validation pytest, which finished with exit code 0 and 177 tests passed. - Ran the runtime probe to exercise the API model list, Settings env parsing, and ModelRouter paths, and observed a 200 OK on GET /v1/models, with the catalog item id claude-fable-5 and the expected Fable vs global-default routing behavior. - Generated the probe source file used to exercise the API and Settings paths, enabling repeatable validation without real provider credentials. <a href="https://app.greptile.com/trex/runs/14275379/artifacts"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img alt="View all artifacts" src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a> <sub><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="14" align="absmiddle"></a> Ran code and verified through T-Rex</sub> </details> <details open><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | src/free_claude_code/application/routing.py | Adds Fable model and thinking branches; the thinking branch can also match unrelated direct provider model ids containing `fable`. | | src/free_claude_code/config/settings.py | Adds optional Fable model and thinking settings with blank-env inheritance and provider/model validation. | | src/free_claude_code/config/model_refs.py | Includes Fable in configured chat model reference collection and dedupe. | | src/free_claude_code/config/admin/manifest.py | Adds Fable model and thinking controls to the admin manifest. | | src/free_claude_code/api/model_catalog.py | Adds `claude-fable-5` to the advertised Claude model aliases. | | pyproject.toml | Bumps the package version to `4.4.0`. | | uv.lock | Updates the editable package version to match `pyproject.toml`. | </details> <details open><summary><h3>Flowchart</h3></summary> <a href="#gh-light-mode-only"> ```mermaid %%{init: {'theme': 'neutral'}}%% flowchart TD A[Incoming model name] --> B{Direct provider or gateway id?} B -- yes --> C[Use provider/model directly] C --> D[Resolve thinking from provider model string] B -- no --> E{Claude tier match} E -- Fable --> F[MODEL_FABLE or MODEL] E -- Opus/Sonnet/Haiku --> G[Tier override or MODEL] E -- None --> H[MODEL] D --> I[Provider request] F --> I G --> I H --> I ``` </a> <a href="#gh-dark-mode-only"> ```mermaid %%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% flowchart TD A[Incoming model name] --> B{Direct provider or gateway id?} B -- yes --> C[Use provider/model directly] C --> D[Resolve thinking from provider model string] B -- no --> E{Claude tier match} E -- Fable --> F[MODEL_FABLE or MODEL] E -- Opus/Sonnet/Haiku --> G[Tier override or MODEL] E -- None --> H[MODEL] D --> I[Provider request] F --> I G --> I H --> I ``` </a> </details> <a href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22ali%2Fadd-fable-routing-tier%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22ali%2Fadd-fable-routing-tier%22.%0A%0AFix%20the%20following%201%20code%20review%20issue.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%201%0Asrc%2Ffree_claude_code%2Fapplication%2Frouting.py%3A134-135%0A**Fable%20Thinking%20Overmatches%20Models**%0A%0AWhen%20a%20direct%20provider%20request%20uses%20a%20model%20id%20like%20%60sambanova%2Fmy-fable-ensemble-v2%60%2C%20the%20direct%20route%20bypasses%20tier%20remapping%20but%20still%20calls%20%60_resolve_thinking%28%29%60%20with%20the%20provider%20model%20string.%20With%20%60ENABLE_FABLE_THINKING%60%20set%2C%20this%20substring%20check%20applies%20Fable%20thinking%20behavior%20to%20an%20unrelated%20provider%20model%2C%20changing%20the%20outgoing%20request%20shape%20just%20because%20the%20model%20id%20contains%20%60fable%60.%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1099&platform=github"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodexDark.svg?v=6"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"><img alt="Fix All in Codex" src="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"></picture></a> <sub>Reviews (1): Last reviewed commit: ["Add Fable as a first-class routing tier"](https://github.com/alishahryar1/free-claude-code/commit/0705840c65511fd85c74fd2c62ba8ea97afe7c12) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43892323)</sub> > Greptile also left **1 inline comment** on this PR. <!-- /greptile_comment --> |
||
|
|
0d5bec3dcd |
Make proxy authentication bearer-only across every client (#1096)
## Problem Proxy authentication selected the first of three credential headers, so a stale `X-API-Key` could mask valid bearer authorization and leave Claude CLI or IDE clients at their login gate. Fixes #902. ## Changes | Before | After | | --- | --- | | FCC accepted three proxy credential headers and stripped legacy model suffixes. | FCC accepts one exact `Authorization: Bearer` token without mutation. | | Conflicting provider credentials could override valid proxy authorization. | Unrelated credential headers are ignored during proxy authentication. | | Codex catalog discovery and Pi catalog or inference paths used API-key authentication. | Every FCC-owned Codex and Pi path uses bearer authorization. | | Authentication failures referred ambiguously to an API key. | Authentication failures identify the proxy authentication token. | | FCC reported version `4.2.0`. | FCC reports version `4.3.0`. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR makes proxy authentication use bearer tokens only. The main changes are: - Replaced multi-header proxy auth with exact `Authorization: Bearer <token>` checks. - Updated protected route dependencies to use the renamed auth dependency. - Switched FCC-owned Codex and Pi catalog requests to bearer authorization. - Added Pi provider `authHeader` registration for inference requests. - Updated smoke tests, API tests, docs, examples, and package metadata for the new auth contract. </details> <h3>Confidence Score: 4/5</h3> The changed auth flow is mostly consistent, but Codex inference can still fail if its generated provider config sends API-key auth. Server-side bearer parsing is direct and covered by updated tests. Route protection appears preserved after the dependency rename. Codex catalog auth was updated, but the inference path still depends on external client header behavior. The version bump may understate a breaking auth-contract change. src/free_claude_code/api/dependencies.py, src/free_claude_code/cli/launchers/codex.py, pyproject.toml <details><summary><h3><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="20" align="absmiddle"></a> T-Rex Logs</h3></summary> **What T-Rex did** - T-Rex executed targeted proxy authentication validation to verify bearer token behavior before and after the change. - T-Rex compared pre-change and post-change test results, confirming 31 passed before and 39 passed after, and validating HTTP 200 for exact bearer with unrelated X-API-Key plus HTTP 401 for missing or invalid tokens. <a href="https://app.greptile.com/trex/runs/14225355/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/dependencies.py | Replaces proxy authentication with exact bearer-token validation and new error details. | | src/free_claude_code/api/routes.py | Updates protected route dependencies to call the renamed auth dependency. | | src/free_claude_code/cli/launchers/codex.py | Changes Codex catalog discovery to send bearer auth while leaving inference auth delegated through Codex config. | | src/free_claude_code/cli/launchers/pi_extension.ts | Changes Pi catalog discovery to bearer auth and registers the provider with `authHeader` enabled. | | smoke/lib/config.py | Updates smoke helper auth headers to emit bearer authorization. | | pyproject.toml | Bumps the package version from 4.2.0 to 4.3.0. | </details> <details open><summary><h3>Sequence Diagram</h3></summary> <a href="#gh-light-mode-only"> ```mermaid %%{init: {'theme': 'neutral'}}%% sequenceDiagram participant Codex participant Launcher as FCC Codex launcher participant API as FCC API Launcher->>API: GET /v1/models with Authorization Bearer token API-->>Launcher: Catalog response Launcher-->>Codex: Raw token in FCC_CODEX_API_KEY Codex->>API: POST /v1/responses with client-built auth alt Client sends bearer authorization API-->>Codex: Accepted else Client sends API-key auth API-->>Codex: 401 proxy auth failure 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 Codex participant Launcher as FCC Codex launcher participant API as FCC API Launcher->>API: GET /v1/models with Authorization Bearer token API-->>Launcher: Catalog response Launcher-->>Codex: Raw token in FCC_CODEX_API_KEY Codex->>API: POST /v1/responses with client-built auth alt Client sends bearer authorization API-->>Codex: Accepted else Client sends API-key auth API-->>Codex: 401 proxy auth failure end ``` </a> </details> <a href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22ali%2Fcanonical-proxy-bearer-auth%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%2Fcanonical-proxy-bearer-auth%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%2Fdependencies.py%3A56%0A**Codex%20Inference%20Still%20Delegates%20Auth**%0A%0AWhen%20Codex%20launches%2C%20FCC%20now%20sends%20bearer%20auth%20only%20for%20its%20own%20%60%2Fv1%2Fmodels%60%20catalog%20request%2C%20but%20inference%20still%20depends%20on%20Codex%20turning%20the%20raw%20%60FCC_CODEX_API_KEY%60%20value%20into%20the%20same%20bearer%20header.%20If%20Codex%20sends%20that%20env%20key%20as%20an%20API-key%20header%2C%20this%20server%20branch%20treats%20the%20request%20as%20missing%20proxy%20auth%20and%20%60%2Fv1%2Fresponses%60%20fails%20with%20401%20even%20though%20catalog%20discovery%20succeeded.%0A%0A%23%23%23%20Issue%202%20of%202%0Apyproject.toml%3A7%0A**Breaking%20Auth%20Contract%20Understated**%0A%0AThis%20change%20removes%20previously%20accepted%20proxy%20credential%20shapes%2C%20including%20%60X-API-Key%60%2C%20%60anthropic-auth-token%60%2C%20and%20suffixed%20bearer%20tokens%2C%20but%20the%20package%20version%20only%20moves%20from%20%604.2.0%60%20to%20%604.3.0%60.%20Existing%20users%20can%20upgrade%20within%20the%20same%20major%20line%20and%20have%20every%20protected%20endpoint%20start%20returning%20401%20until%20their%20clients%20are%20reconfigured%2C%20which%20does%20not%20match%20the%20repository%20guidance%20for%20incompatible%20API%20or%20CLI%20behavior.%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1096&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: make proxy auth bearer-only"](https://github.com/alishahryar1/free-claude-code/commit/c437ee0e23dc8f8411272a8dcfcf1ff69f315857) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43791345)</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 --> |
||
|
|
2fe2ba82d2 |
Add Pi as a first-class FCC client (#1088)
## Problem FCC had no first-class Pi path, so Pi users had to maintain provider configuration themselves. FCC's installers and ownership docs also covered only Claude Code and Codex. ## Changes | Before | After | | --- | --- | | Pi required persistent user-managed provider configuration. | `fcc-pi` registers an ephemeral FCC provider from the live model catalog and leaves Pi-owned state untouched. | | Client launchers normalized blank proxy authentication separately. | Claude, Codex, and Pi share one neutral proxy-auth policy. | | FCC installers and uninstallers did not account for Pi. | Installers delegate missing Pi setup to its official platform installer, while uninstallers remove only `fcc-pi` and preserve native Pi. | | Pi compatibility had no executable FCC contract. | Deterministic launcher and lifecycle coverage plus a real Pi 0.80.6 smoke verify model discovery and `/v1/messages` end to end. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR adds Pi as a supported FCC client. The main changes are: - A new `fcc-pi` launcher and bundled Pi extension. - Shared proxy-auth handling for client launchers. - Pi installation, verification, and uninstall coverage in platform scripts. - Pi-focused tests, smoke coverage, and user documentation. </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 pytest command and confirmed deterministic success with 27 passed in 2.68s and EXIT\_CODE: 0. - Analyzed the blocker log and determined that Pi CLI and live-smoke prerequisites are missing, blocking external Pi execution; uv is available and provider smoke models are discoverable, narrowing the issue to Pi CLI plus live-smoke opt-in. <a href="https://app.greptile.com/trex/runs/14192651/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/cli/launchers/pi.py | Adds the `fcc-pi` launcher, Pi capability checks, passthrough handling, extension loading, and FCC-scoped environment setup. | | src/free_claude_code/cli/launchers/pi_extension.ts | Adds the Pi extension that fetches FCC models and registers a process-local Anthropic Messages provider. | | scripts/install.sh | Adds Pi install, PATH refresh, capability verification, and `fcc-pi` command checks for POSIX installs. | | scripts/install.ps1 | Adds Pi install, PATH refresh, capability verification, and `fcc-pi` command checks for Windows installs. | | pyproject.toml | Registers the `fcc-pi` console script and bumps the package version. | </details> <!-- greptile_failed_comments --> <h3>Comments Outside Diff (1)</h3> 1. General comment <a href="#"><img alt="P1" src="https://greptile-static-assets.s3.amazonaws.com/badges/p1.svg?v=9" align="top"></a> **Pi entrypoint contract test fails due install-hint mismatch** - **Bug** - The narrow Pi launcher/entrypoint test selection fails on current HEAD. `test_launch_pi_rejects_unrelated_pi_binary` expects stderr to include the Windows PowerShell install URL `https://pi.dev/install.ps1`, but the launcher emitted the POSIX install command `curl -fsSL https://pi.dev/install.sh | sh` in this Linux sandbox. - **Cause** - The Pi launcher's incompatible-binary error path and the test contract disagree about which platform-specific install hint should be emitted for this scenario. - **Fix** - Align the Pi launcher contract with the test expectation: either update the launcher to emit the expected platform-specific hint for the mocked scenario, or update the test to assert the correct hint for the active/mocked platform. Then rerun `uv run --frozen pytest -q tests/cli/test_entrypoints.py -k 'pi'`. <sub><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="14" align="absmiddle"></a> Ran code and verified through T-Rex</sub> <!-- /greptile_failed_comments --> <sub>Reviews (3): Last reviewed commit: ["Add first-class Pi client integration"](https://github.com/alishahryar1/free-claude-code/commit/cd5c335f8cf2dee93d927496d7cabbffec86f169) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43721088)</sub> <!-- /greptile_comment --> |
||
|
|
3fba1c6fc3 |
Give messaging clear exact subtree semantics (#1072)
## Problem Messaging `/clear` did not follow the selected platform message boundary. Reply clears preserved the selected user prompt, while standalone clears preserved user-authored messages and could reset FCC state outside the invoking chat. ## Changes | Before | After | | --- | --- | | Reply `/clear` removed a logical conversation branch but retained the selected message. | Reply `/clear` deletes the selected message and its literal reply subtree, including the clear command. | | Standalone `/clear` retained user prompts and voice notes while resetting global messaging state. | Standalone `/clear` deletes every tracked message and resets FCC state only in the invoking platform and chat. | | Trees recorded only logical execution parentage. | Trees separately persist logical execution ancestry and exact prompt/status reply ownership. | | Clear coordination used one global admission boundary. | Per-chat clear generations coordinate admission, voice cancellation, persistence, and best-effort platform deletion. | | Persistence tracked only FCC-authored clearable output. | Persistence tracks managed inbound and outbound messages and migrates legacy entries. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR gives messaging `/clear` exact per-chat and reply-subtree behavior. The main changes are: - Per-chat clear generations for admission and startup-notice cleanup. - Managed inbound and outbound message tracking for deletion. - Exact prompt/status reply ownership in message trees. - Scoped voice cancellation and clear persistence updates. - Updated docs, smoke coverage, and messaging tests. </details> <h3>Confidence Score: 4/5</h3> The clear flow is mostly well-contained, with one upgrade-path issue in legacy tree restoration. Newly created prompt/status subtrees use the new exact reference fields consistently, and legacy snapshots can map old status replies to prompt references. However, reply `/clear` on an upgraded status can miss descendants and leave stale state/messages. src/free_claude_code/messaging/trees/snapshot.py <details><summary><h3><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="20" align="absmiddle"></a> T-Rex Logs</h3></summary> **What T-Rex did** - T-Rex attempted to prepare and run a focused legacy snapshot reproduction harness for legacy status replies detach, but tool access was blocked before execution. - A messaging clear smoke test harness was executed and reported a passing result: 20 items collected and 20 passed in 1.69 seconds, with traces for test\_reply\_clear\_uses\_literal and related paths shown in the log. <a href="https://app.greptile.com/trex/runs/14131337/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/workflow.py | Adds per-chat clear generations, managed inbound recording, scoped clears, and startup-notice invalidation. | | src/free_claude_code/messaging/trees/graph.py | Adds exact prompt/status reference resolution and literal reply-subtree traversal. | | src/free_claude_code/messaging/trees/runtime.py | Adds exact message-subtree removal and status-only clearing behavior. | | src/free_claude_code/messaging/trees/snapshot.py | Adds parent_reference_id persistence and legacy fallback; the fallback can miss legacy status-reply descendants. | | src/free_claude_code/messaging/session/managed_message_log.py | Replaces the clearable output log with managed inbound and outbound message tracking. | | src/free_claude_code/messaging/commands.py | Routes reply and standalone `/clear` through the new exact deletion ID flows. | </details> <details open><summary><h3>Flowchart</h3></summary> <a href="#gh-light-mode-only"> ```mermaid %%{init: {'theme': 'neutral'}}%% flowchart TD A[Incoming message] --> B{Standalone /clear?} B -- yes --> C[Clear invoking chat] C --> D[Cancel scoped voice work] C --> E[Collect managed and tree message IDs] C --> F[Advance chat clear generation] F --> G[Detach scoped trees] G --> H[Clear scoped session store] H --> I[Best-effort platform deletes] B -- no --> J[Record managed inbound message] J --> K[Admit with stop and clear token] K --> L{Reply /clear?} L -- yes --> M[Resolve exact prompt or status reference] M --> N[Remove literal reference subtree] N --> I L -- no --> O[Queue or run tree node] ``` </a> <a href="#gh-dark-mode-only"> ```mermaid %%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% flowchart TD A[Incoming message] --> B{Standalone /clear?} B -- yes --> C[Clear invoking chat] C --> D[Cancel scoped voice work] C --> E[Collect managed and tree message IDs] C --> F[Advance chat clear generation] F --> G[Detach scoped trees] G --> H[Clear scoped session store] H --> I[Best-effort platform deletes] B -- no --> J[Record managed inbound message] J --> K[Admit with stop and clear token] K --> L{Reply /clear?} L -- yes --> M[Resolve exact prompt or status reference] M --> N[Remove literal reference subtree] N --> I L -- no --> O[Queue or run tree node] ``` </a> </details> <a href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22ali%2Fclear-message-subtree%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%2Fclear-message-subtree%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%2Fmessaging%2Ftrees%2Fsnapshot.py%3A192-193%0A**Legacy%20Status%20Replies%20Detach**%0A%0AWhen%20an%20upgraded%20legacy%20snapshot%20contains%20a%20child%20that%20originally%20replied%20to%20its%20parent%20status%2C%20this%20fallback%20rewrites%20the%20missing%20exact%20reference%20to%20the%20parent%20prompt.%20A%20later%20reply%20%60%2Fclear%60%20on%20that%20status%20traverses%20from%20the%20status%20ID%2C%20finds%20no%20migrated%20child%20edge%2C%20and%20leaves%20the%20old%20status-reply%20descendants%20and%20their%20managed%20messages%20behind.%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1072&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: ["Give messaging clear exact subtree seman..."](https://github.com/alishahryar1/free-claude-code/commit/0a3baecf9470da4bb866c864c1d1f01abd517085) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43593126)</sub> > Greptile also left **1 inline comment** on this PR. <!-- /greptile_comment --> |
||
|
|
e37b504636 |
Preserve user messages during messaging clear (#1068)
## Problem Messaging `/clear` used one untyped collection for both internal reply references and platform deletion targets. Clearing a branch or cancelling a voice task could therefore delete the customer's prompt or voice note along with FCC's own status and reply messages. ## Changes | Before | After | | --- | --- | | Tree transitions exposed one message-ID set for repository unindexing and platform deletion. | Tree transitions now separate internal `reference_ids` from FCC-owned `clearable_message_ids`. | | Reply and global clear deleted user prompts and voice notes with FCC output. | Clear removes FCC statuses, replies, notices, and the explicit `/clear` command while preserving user-authored messages. | | The persisted message log accepted ordinary inbound content. | The clearable-message log accepts only FCC output and explicit clear commands, and drops legacy user-content entries when loading. | | Tests treated user-message deletion as successful cleanup. | Deterministic and live messaging coverage enforce preservation across branch, global, and voice clear paths. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR narrows messaging clear behavior so user-authored messages are preserved. The main changes are: - Clearable platform IDs are separated from internal tree reference IDs. - The session message log now tracks FCC-owned output and explicit clear commands. - Branch, global, and voice clear paths now avoid deleting user prompts and voice notes. - Tests, smoke coverage, docs, and the package version were updated. </details> <h3>Confidence Score: 5/5</h3> This looks safe to merge after a small migration cleanup. The clear paths now preserve user-authored messages, and current clearable-log writers use the new shape consistently. src/free_claude_code/messaging/session/clearable_message_log.py needs a migration cleanup for old retained clear-command IDs during session reload. <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 messaging-clear-preservation contract by reviewing the foreground pytest run log, which captured the exact command, working directory, full test output, and exit code, and by examining the artifact note and its capture log that summarize the command, test count, exit code, and scope. <a href="https://app.greptile.com/trex/runs/14123111/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/session/clearable_message_log.py | Replaces the broad message log with a clearable-message log, but the migration filter can drop old retained clear-command IDs. | | src/free_claude_code/messaging/session/store.py | Renames the session-store API around clearable message IDs while keeping the same persisted `message_log` key. | | src/free_claude_code/messaging/trees/runtime.py | Returns internal reference IDs separately from FCC-owned deletion IDs during branch removal and chat-wide enumeration. | | src/free_claude_code/messaging/trees/manager.py | Uses reference IDs for repository cleanup and returns clearable IDs for platform deletion. | | src/free_claude_code/messaging/turn_intake.py | Stops recording ordinary inbound content and records clear commands only when needed for cleanup. | | src/free_claude_code/messaging/commands.py | Deletes clearable IDs plus the invoking clear command instead of deleting all branch reference IDs. | | src/free_claude_code/messaging/workflow.py | Aggregates clearable IDs from tree state, the session log, and voice cancellation results. | | src/free_claude_code/messaging/voice.py | Changes voice cancellation deletion ownership so only FCC-authored status messages are clearable. | </details> <details open><summary><h3>Flowchart</h3></summary> <a href="#gh-light-mode-only"> ```mermaid %%{init: {'theme': 'neutral'}}%% flowchart TD A[Incoming message] --> B{Clear command?} B -- No --> C[Handle normal turn] C --> D[Record FCC outbound status] B -- Reply clear --> E[Record clear command] E --> F[Clear branch or voice task] F --> G[Delete FCC-owned IDs plus clear command] B -- Global clear --> H[Collect clearable IDs] H --> I[Reset conversation state] I --> J[Delete FCC-owned IDs plus clear command] D --> K[Clearable-message log] K --> H ``` </a> <a href="#gh-dark-mode-only"> ```mermaid %%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% flowchart TD A[Incoming message] --> B{Clear command?} B -- No --> C[Handle normal turn] C --> D[Record FCC outbound status] B -- Reply clear --> E[Record clear command] E --> F[Clear branch or voice task] F --> G[Delete FCC-owned IDs plus clear command] B -- Global clear --> H[Collect clearable IDs] H --> I[Reset conversation state] I --> J[Delete FCC-owned IDs plus clear command] D --> K[Clearable-message log] K --> H ``` </a> </details> <a href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22ali%2Fpreserve-user-messages-on-clear%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%2Fpreserve-user-messages-on-clear%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%2Fmessaging%2Fsession%2Fclearable_message_log.py%3A36-37%0A**Legacy%20Clear%20Commands%20Are%20Dropped**%0A%0AWhen%20an%20existing%20session%20file%20contains%20a%20previously%20retained%20clear%20command%20from%20the%20old%20log%2C%20it%20is%20stored%20as%20%60direction%3D%22in%22%60%20and%20%60kind%3D%22command%22%60.%20This%20new%20load%20filter%20drops%20that%20entry%20because%20it%20only%20keeps%20%60kind%3D%22clear_command%22%60%2C%20so%20a%20failed%20or%20cancelled%20%60%2Fclear%60%20command%20recorded%20before%20the%20upgrade%20is%20no%20longer%20retried%20by%20the%20next%20clear%20and%20remains%20on%20the%20platform.%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1068&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: ["Preserve user messages during clear"](https://github.com/alishahryar1/free-claude-code/commit/af7a910facaa29a5ca8f7fb95ec2faae28798e62) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43576921)</sub> > Greptile also left **1 inline comment** on this PR. **Context used:** - Context used - CLAUDE.md ([source](https://app.greptile.com/alishahryar1/github/Alishahryar1/free-claude-code/-/custom-context?memory=d2fd24d8-0dec-4faf-8ee4-e085e215a2f8)) <!-- /greptile_comment --> |
||
|
|
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 --> |
||
|
|
ef76bddd58 |
Make Telegram startup notices clearable (#1066)
## Problem Telegram's online notice was sent directly by the SDK runtime and its message ID was discarded, so `/clear` could not delete it. Moving delivery into the workflow also needs to keep slow sends from blocking commands and prevent acknowledged notices from losing clear ownership. ## Changes | Before | After | | --- | --- | | The Telegram runtime sent a transport-specific startup side effect. | The platform declares a semantic notice intent that the application gives to the workflow after transport readiness. | | Startup delivery bypassed the persisted message log. | The workflow renders and records each acknowledged notice in the same bounded log used by `/clear`. | | Serializing send and record held workflow state across platform I/O. | A dedicated clear generation reserves publication, delivery runs outside the state lock, and a short receipt finalizer commits or compensates. | | Concurrent clear, cancellation, or record failure could leave a delivered notice unowned. | Clear or cancellation deletes a late receipt; record failure deletes it; failed deletion restores tracking for a later `/clear`. | | A standalone `/clear` command could evict an older target at the log cap. | Successful standalone clear owns its command ID directly, while failed or cancelled clear records it for the next attempt. | | Startup ownership races were implicit. | Deterministic race, failure, cap, restart, and product-smoke coverage enforce the final state machine in version 3.5.10. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR makes Telegram startup notices clearable through the messaging workflow. The main changes are: - Moves the Telegram online notice out of the SDK runtime and into workflow-owned publication. - Adds a startup-notice intent to platform composition and publishes it after runtime start and restored-status repair. - Records delivered startup notice IDs for later `/clear` ownership, with delete compensation on interrupted ownership transfer. - Defers standalone `/clear` command ID recording so it cannot evict older deletion targets at the log cap. - Adds tests and smoke coverage for startup notice clearing, cancellation, failures, cap pressure, persistence, and startup ordering. - Bumps the package version and lockfile to 3.5.10. </details> <h3>Confidence Score: 5/5</h3> This looks safe to merge. No blocking issues were 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** - A focused proof run for the telegram startup tests completed, showing 121 tests passed in 2.94 seconds with EXIT\_CODE 0. - A smoke proof run for the same flow completed, showing 18 tests skipped in 0.97 seconds with EXIT\_CODE 0. - The shell wrapper issue was addressed by re-running with bash -lc, producing a clean result with EXIT\_CODE 0 in the final artifact. <a href="https://app.greptile.com/trex/runs/14118230/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/workflow.py | Adds workflow-owned startup notice sending, tracking, compensation, and clear-generation ordering. | | src/free_claude_code/messaging/turn_intake.py | Defers standalone `/clear` command ID recording until failure or cancellation paths need it. | | src/free_claude_code/runtime/application.py | Publishes optional startup notices after messaging runtime start and restored-status repair. | | src/free_claude_code/messaging/platforms/factory.py | Creates a Telegram startup-notice intent when an allowed Telegram user is configured. | | src/free_claude_code/messaging/platforms/telegram.py | Removes the direct Telegram runtime startup-message side effect. | </details> <sub>Reviews (2): Last reviewed commit: ["Make Telegram startup notices clearable"](https://github.com/alishahryar1/free-claude-code/commit/6e779006e0cdaf1df24c27a8d04784e2d7220a66) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43565904)</sub> <!-- /greptile_comment --> |
||
|
|
eda8ea3060 |
Use task status as the sole stop confirmation (#1065)
## Problem Messaging `/stop` edited each affected task status to `Stopped` and also posted a second success message. The duplicate confirmation added noise even though the existing status already represented the terminal result. ## Changes | Before | After | | --- | --- | | Successful active, queued, global, and bound-voice stops posted a second confirmation. | Successful stops use the affected task status as their sole success UI. | | Stop commands returned an ambiguous integer or `None`. | A typed `StopOutcome` carries the cancelled count and terminal status ownership. | | Statusless voice cancellation could become silent if confirmations were removed unconditionally. | Statusless voice cancellation receives one fallback confirmation. | | A global stop could under-report work when any affected status was in another chat. | The invoking chat receives one summary whenever any affected status is outside its scope. | | Zero-work global stops reported that zero requests were cancelled. | No-op global and reply stops report that there was nothing to stop. | | Runtime and product coverage encoded the duplicate message. | Runtime mapping and Discord/Telegram product smokes cover active, queued, voice, no-op, and fallback behavior. | | The package version was 3.5.8. | The package version is 3.5.9 with an updated lockfile. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR changes `/stop` so task statuses become the main success feedback. The main changes are: - Added a typed stop outcome for cancelled counts and status feedback ownership. - Suppressed duplicate stop confirmations when the invoking chat already has complete status feedback. - Kept explicit fallback messages for no-op stops, statusless voice cancellations, and cross-chat stop results. - Updated runtime mapping, docs, product smokes, tests, and the package version. </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 live messaging product smoke test with FCC\_LIVE\_SMOKE=1 and FCC\_SMOKE\_TARGETS=messaging, executing the command uv run pytest under /home/user/repo; the run exited with code 0 and 17 tests passed in 1.34s. - Reviewed the test run log to verify proper shutdown behavior, noting Discord and Telegram stop statuses, a queued trace, and cancellation messages indicating shutdown tasks were being canceled. - Linked the stop-product-smoke-20260711.log artifact for review of the run's stop behavior. <a href="https://app.greptile.com/trex/runs/14115543/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/command_context.py | Adds `StopOutcome` and updates stop command context signatures. | | src/free_claude_code/messaging/commands.py | Routes stop confirmations through the new outcome and fallback rules. | | src/free_claude_code/messaging/workflow.py | Builds stop outcomes from voice cancellations and tree cancellation effects. | | src/free_claude_code/runtime/application.py | Maps the messaging stop outcome back to the runtime stop result count. | | tests/messaging/test_handler.py | Covers same-chat status feedback, cross-chat fallback, no-op stops, and voice fallback behavior. | | smoke/product/test_messaging_product_live.py | Updates product smokes for status-only stop success feedback. | </details> <sub>Reviews (2): Last reviewed commit: ["Use task status as the sole stop confirm..."](https://github.com/alishahryar1/free-claude-code/commit/98f0acb01b3405c2afd918539eff49b9410bf487) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43560341)</sub> <!-- /greptile_comment --> |
||
|
|
df038c2470 |
Retry degraded NVIDIA NIM functions as overloads (#1064)
## Problem NVIDIA NVCF can return HTTP 400 when a deployed function is DEGRADED, even though the failure is transient. FCC treated that response as a deterministic invalid request and never used its provider-owned retry budget. Fixes #1057. ## Changes | Before | After | | --- | --- | | Every NVIDIA HTTP 400 was non-retryable. | The NVIDIA adapter recognizes only the structured NVCF `Function id …: DEGRADED function cannot be invoked` response. | | A degraded function failed after one attempt. | The shared limiter applies its existing five-attempt exponential backoff without mutating the request or adding another retry loop. | | Exhaustion returned `INVALID_REQUEST / 400`. | Exhaustion returns canonical `OVERLOADED / 529` while preserving the redacted upstream HTTP 400 detail and request ID. | | NVIDIA-specific wording could have leaked into shared classification. | The exact marker stays NVIDIA-owned; shared provider policy owns canonical semantics, diagnostics, and scheduling, while API wire mapping remains unchanged. | | The degraded-function boundary had no deterministic coverage. | Tests cover recovery, exact exhaustion, near misses, provider isolation, raw exception preservation, trace metadata, and credential redaction; all five CI gates pass with 2,214 tests passed and 7 skipped. | | Package version was 3.5.7. | Package version is 3.5.8 with an updated lockfile. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR teaches NVIDIA NIM degraded-function failures to use the shared overload retry path. The main changes are: - Adds a provider-specific failure override hook. - Maps the exact NVCF degraded-function HTTP 400 marker to canonical overload semantics. - Threads the override through shared retry and final failure classification. - Adds focused tests for retry, exhaustion, near misses, provider isolation, redaction, and trace metadata. - Updates docs, smoke coverage metadata, package version, and lockfile. </details> <h3>Confidence Score: 5/5</h3> This looks safe to merge after considering the narrow NVIDIA error-body match. The retry and final classification flow preserve the raw upstream error, and non-NVIDIA providers keep the existing 400 behavior. src/free_claude_code/providers/nvidia_nim/client.py should harden the degraded marker lookup for nested SDK error bodies. <details><summary><h3><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="20" align="absmiddle"></a> T-Rex Logs</h3></summary> **What T-Rex did** - T-Rex produced a proof for the posted P1 finding and linked it to the corresponding review comment. - A contract-validation proof was captured showing the full command transcript with timestamps, working directory, commands, pytest verbose output, and exit codes. - The focused Nvidia degraded retry test ran and completed with 8 passed in 2.43s. - A broader test run reported worker crashes, with 3 failed and 70 passed. - A serial test for test\_openai\_compat\_5xx\_retry.py timed out after a hang, exiting at 124. <a href="https://app.greptile.com/trex/runs/14112472/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 NVIDIA-specific degraded-function detection; the match is narrow and only reads a top-level `detail` field. | | src/free_claude_code/providers/rate_limit.py | Uses provider overrides for retry qualification while preserving the raw exception after retry exhaustion. | | src/free_claude_code/providers/failure_policy.py | Adds the shared override type and final classification hook, plus a reusable overloaded-provider failure constructor. | | src/free_claude_code/providers/transports/openai_chat/transport.py | Passes provider-specific failure overrides into stream creation retries and final failure mapping. | | tests/providers/test_nvidia_nim_degraded_retry.py | Adds coverage for NVIDIA degraded-function retry success, retry exhaustion, non-matching 400s, provider isolation, redaction, and traces. | </details> <!-- greptile_failed_comments --> <h3>Comments Outside Diff (1)</h3> 1. General comment <a href="#"><img alt="P1" src="https://greptile-static-assets.s3.amazonaws.com/badges/p1.svg?v=9" align="top"></a> **Adjacent OpenAI-compatible 5xx exhaustion test crashes workers and hangs serially** - **Bug** - The requested adjacent retry/rate-limit coverage is not stable on current head. Under xdist, three parameters of `test_nim_stream_openai_5xx_exhausted_emits_user_message` caused workers to terminate unexpectedly, producing an exit code 1. A follow-up serial rerun passed the 500 parameter but timed out after 60 seconds while running the 502 parameter, indicating the exhausted 5xx path can hang or terminate the worker rather than completing deterministically. - **Cause** - The executed evidence points to the OpenAI-compatible NIM 5xx exhaustion path exercised by `tests/providers/test_openai_compat_5xx_retry.py::test_nim_stream_openai_5xx_exhausted_emits_user_message`. The exact root cause was not isolated within the validation budget, but the affected area overlaps changed retry/transport handling files. - **Fix** - Investigate the OpenAI-compatible streaming 5xx exhaustion path for non-terminating retry/stream cleanup or worker-fatal behavior. Ensure exhausted 5xx cases raise the expected user-facing error promptly for all status parameters, then rerun the adjacent command and the targeted serial parametrized test. <sub><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="14" align="absmiddle"></a> Ran code and verified through T-Rex</sub> <!-- /greptile_failed_comments --> <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%2Fretry-nim-degraded-function%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%2Fretry-nim-degraded-function%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%2Fproviders%2Fnvidia_nim%2Fclient.py%3A126-127%0A**Nested%20Error%20Body%20Misses%20Retry**%0A%0AWhen%20the%20OpenAI%20SDK%20exposes%20a%20400%20response%20as%20the%20common%20nested%20error%20shape%2C%20such%20as%20%60%7B%22error%22%3A%20%7B%22message%22%3A%20%22Function%20id%20...%3A%20DEGRADED%20function%20cannot%20be%20invoked%22%7D%7D%60%2C%20this%20lookup%20never%20sees%20the%20degraded%20marker.%20That%20path%20falls%20back%20to%20the%20shared%20400%20handling%2C%20so%20a%20transient%20degraded%20NVCF%20function%20still%20fails%20after%20one%20attempt%20instead%20of%20using%20the%20provider%20retry%20budget.%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1064&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: ["Retry degraded NVIDIA NIM functions as o..."](https://github.com/alishahryar1/free-claude-code/commit/2cc7f056a73d1baefb1e1395b181d26efc32dc9e) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43555691)</sub> > Greptile also left **1 inline comment** on this PR. <!-- /greptile_comment --> |
||
|
|
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 --> |
||
|
|
2bcaf3ac74 |
Make messaging trees atomic ownership boundaries (#1048)
## Problem Messaging tree state, queue coordination, task ownership, and persistence were jointly mutated across several classes. Raw message IDs were treated as globally unique, allowing cross-chat collisions and unsafe cancellation or clear ordering. ## Changes | Before | After | | --- | --- | | Managers and processors coordinated partial tree mutations through exposed locks and mutable nodes. | MessageTree owns atomic transitions and returns detached effects to task, UI, and persistence owners. | | Raw message IDs and task identities could collide across chats or detached generations. | Scoped tree identities and opaque claim IDs isolate chats and reject stale task writes. | | Session snapshots duplicated graph links and retained ingress payloads. | Lean scoped snapshots rebuild validated indexes and continue reading existing session files. | | Stop, clear, and runner persistence could interleave across commit boundaries. | Admission epochs, cancellation-safe detach, and authoritative writes make committed cleanup durable. | | Tree implementation classes leaked through messaging package exports. | Adapter-facing values and ports remain supported while tree internals stay internal. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR makes messaging trees own their state transitions and scoped identities. The main changes are: - Scoped tree and voice ownership by platform and chat. - Opaque claim IDs for queued task execution. - Manager-owned atomic cancellation, clear, and successor task launch paths. - Lean scoped snapshots with legacy session restore support. - Messaging tree internals removed from the public package surface. </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** - Executed the messaging and contract-boundary test suite with pytest across all specified test modules. - Observed the run completed with 96 tests passing in 4.10 seconds and an exit code of 0. - The exact pytest command used for the run is documented in the proof to enable reproducibility of the test scope. - The run log is available as an artifact for reviewers to inspect test output and details. <a href="https://app.greptile.com/trex/runs/14083891/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/trees/runtime.py | Adds claim-scoped state transitions and cancellation tombstones for late runner writes. | | src/free_claude_code/messaging/trees/manager.py | Centralizes aggregate publication, branch removal, global clear, and successor task launch decisions. | | src/free_claude_code/messaging/trees/processor.py | Runs tasks by opaque claim ID and routes cleanup through manager-owned finish handling. | | src/free_claude_code/messaging/trees/snapshot.py | Serializes scoped tree snapshots and restores supported legacy tree shapes. | | src/free_claude_code/messaging/voice.py | Scopes pending voice registrations by message scope and message ID. | </details> <!-- greptile_failed_comments --> <h3>Comments Outside Diff (1)</h3> 1. `src/free_claude_code/messaging/commands.py`, line 161-164 ([link](https://github.com/alishahryar1/free-claude-code/blob/a4e49f082a9d3ffc1f6cdf3ab6a065b0f22a759d/src/free_claude_code/messaging/commands.py#L161-L164)) <a href="#"><img alt="P1" src="https://greptile-static-assets.s3.amazonaws.com/badges/p1.svg?v=9" align="top"></a> **Voice Cancellation Is Unscoped** The tree reply path is now scoped by `incoming.scope`, but the voice fallback still cancels by only `chat_id` and `reply_id`. If Discord and Telegram both have the same raw chat/message IDs, a reply `/clear` from one platform can cancel a pending voice note from the other platform, crossing the ownership boundary this PR adds for message trees. <details><summary><strong>Artifacts</strong></summary><br /> **[Repro: focused pytest harness that models cross-platform raw ID collision for voice cancellation](https://app.greptile.com/trex/artifacts/0ad480a9-4e20-4b4e-970e-63aebc4577b3)** - Contains supporting evidence from the run (text/x-python; charset=utf-8). **[Repro: verbose pytest output showing unscoped cancel\_pending\_voice call and Discord-owned voice cancellation from Telegram /clear](https://app.greptile.com/trex/artifacts/ead824f3-2f41-4028-a8e3-8359c5f6d3a9)** - Keeps the command output available without making the summary code-heavy. <a href="https://app.greptile.com/trex/runs/14082218/artifacts?artifact=0ad480a9-4e20-4b4e-970e-63aebc4577b3"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewArtifactsDark.svg?v=4"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewArtifacts.svg?v=4"><img alt="View artifacts" src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewArtifacts.svg?v=4"></picture></a> </details> <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> <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%22architecture%2Fmessage-tree-ownership%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22architecture%2Fmessage-tree-ownership%22.%0A%0AThis%20is%20a%20comment%20left%20during%20a%20code%20review.%0APath%3A%20src%2Ffree_claude_code%2Fmessaging%2Fcommands.py%0ALine%3A%20161-164%0A%0AComment%3A%0A**Voice%20Cancellation%20Is%20Unscoped**%0A%0AThe%20tree%20reply%20path%20is%20now%20scoped%20by%20%60incoming.scope%60%2C%20but%20the%20voice%20fallback%20still%20cancels%20by%20only%20%60chat_id%60%20and%20%60reply_id%60.%20If%20Discord%20and%20Telegram%20both%20have%20the%20same%20raw%20chat%2Fmessage%20IDs%2C%20a%20reply%20%60%2Fclear%60%20from%20one%20platform%20can%20cancel%20a%20pending%20voice%20note%20from%20the%20other%20platform%2C%20crossing%20the%20ownership%20boundary%20this%20PR%20adds%20for%20message%20trees.%0A%0AHow%20can%20I%20resolve%20this%3F%20If%20you%20propose%20a%20fix%2C%20please%20make%20it%20concise.&repo=alishahryar1%2Ffree-claude-code&pr=1048&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 (4): Last reviewed commit: ["Serialize successor task publication wit..."](https://github.com/alishahryar1/free-claude-code/commit/ec8744a8882c1ebc38d5dc7e87aaf2e31b08f653) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43492190)</sub> <!-- /greptile_comment --> |
||
|
|
701a394697 |
Make provider capabilities semantic and typed (#1047)
## Problem Provider metadata mixed descriptive strings and transport-family names with product policy. The Messages API had to know provider implementation details to decide server-tool behavior, while locality and thinking metadata had ambiguous owners. ## Changes | Before | After | | --- | --- | | Provider descriptors exposed transport names and untyped capability strings. | Provider descriptors expose an immutable semantic value containing only locality and server-tool passthrough. | | The Messages handler derived provider sets from transport families. | `ResolvedModel` carries catalog capabilities and the handler asks the resolved semantic policy. | | Discovery, Admin, and smoke selection inferred locality from credentials or string membership. | Discovery, Admin, and smoke selection read the catalog-owned `local` capability. | | Provider-wide thinking strings competed with discovered model metadata. | `ProviderModelInfo.supports_thinking` remains the sole per-model thinking authority. | | Invalid mapped providers could become raw catalog lookup failures during the migration. | Routing and provider construction share the canonical typed unknown-provider error. | | LM Studio smoke contracts described a native Anthropic transport. | LM Studio smoke contracts describe its OpenAI-chat-backed Messages path. | | Tests encoded transport identities as product behavior. | Tests prove both directions of capability-versus-identity independence while preserving existing wire behavior and diagnostics. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR moves provider policy from transport names to typed catalog capabilities. The main changes are: - Added immutable provider capability values for locality and server-tool passthrough. - Routed provider capabilities through `ResolvedModel` for Messages API policy. - Updated admin status, discovery, smoke config, docs, and tests to read semantic capabilities. - Centralized unknown-provider diagnostics for routing and provider construction. - Bumped the package version and lockfile to `3.4.22`. </details> <h3>Confidence Score: 5/5</h3> This looks safe to merge. No blocking issues found in the changed code. None. <details><summary><h3><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="20" align="absmiddle"></a> T-Rex Logs</h3></summary> **What T-Rex did** - The Pytest run for the provider capabilities changes was executed and completed successfully, as shown by the log's EXIT\_CODE: 0. - The Ruff linter run for the provider capabilities changes was executed and completed successfully, as shown by the log's EXIT\_CODE: 0. - The focused suite exercised the changed code paths via repository tests rather than relying solely on static inspection. <a href="https://app.greptile.com/trex/runs/14074560/artifacts"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img alt="View all artifacts" src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a> <sub><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="14" align="absmiddle"></a> Ran code and verified through T-Rex</sub> </details> <details open><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | src/free_claude_code/config/provider_catalog.py | Replaces transport and string capability metadata with typed immutable provider capabilities. | | src/free_claude_code/application/routing.py | Adds catalog capabilities to resolved models and uses the shared unknown-provider error. | | src/free_claude_code/api/handlers/messages.py | Uses resolved semantic capabilities to decide server-tool passthrough. | | src/free_claude_code/config/admin/status.py | Classifies local providers through the new catalog capability. | | src/free_claude_code/providers/runtime/discovery.py | Uses typed locality to decide which providers are discovered only when referenced. | | src/free_claude_code/application/errors.py | Adds a shared constructor for canonical unknown-provider messages. | </details> <sub>Reviews (1): Last reviewed commit: ["Make provider capabilities semantic and ..."](https://github.com/alishahryar1/free-claude-code/commit/b2732ef74d61c632ccae332a19aaa655f45a96e7) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43475337)</sub> <!-- /greptile_comment --> |
||
|
|
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 --> |
||
|
|
f8c21a48f2 |
Introduce a typed application boundary for provider execution (#1045)
## Problem The HTTP adapter owned model routing, provider execution, and runtime-facing contracts, so API handlers depended on provider implementation types. Provider preflight also discovered private request builders dynamically, obscuring the boundary that must fail before streaming begins. ## Changes | Before | After | | --- | --- | | `api/` owned model routing and shared provider execution. | `application/` owns routing and a settings-independent `ProviderExecutor`. | | API handlers accepted `BaseProvider` callbacks. | API handlers consume the narrow structural `ProviderPort`. | | `BaseProvider` discovered `_build_request_body` dynamically. | Both transport families implement explicit abstract preflight, with LM Studio composing context validation. | | Request leases, task control, and provider model metadata had adapter/provider owners. | Application-owned ports and immutable values define those cross-package contracts. | | Boundary direction was implicit. | Architecture contracts and documentation enforce the final dependency direction. | | Package version was `3.4.19`. | Package version is `3.4.20`, with the lockfile updated. | | Coverage followed the old module layout. | Deterministic boundary/preflight regressions and live Messages/Responses smokes cover the new shape. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR adds a typed application boundary for provider execution. The main changes are: - New `application` package for routing, execution, ports, and model metadata. - API handlers now call application-owned routing and provider execution. - Provider preflight is now explicit on the transport families. - Runtime API composition now uses a task-control port for `/stop`. - Import-boundary tests, smoke references, docs, version, and lockfile were updated. </details> <h3>Confidence Score: 5/5</h3> This looks safe to merge. No blocking issues found in the changed code. None. <details><summary><h3><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="20" align="absmiddle"></a> T-Rex Logs</h3></summary> **What T-Rex did** - Ran a deterministic pytest run for the provider boundary preflight, which completed with exit code 0 and 102 tests passing in 4.77 seconds. - Launched the environment presence check as part of the preflight, which completed with exit code 0 and confirmed OPENCODE\_API\_KEY=\[REDACTED\] matched. - Attempted the live provider smoke test, which completed with exit code 0 and 2 tests skipped due to incomplete smoke configuration. <a href="https://app.greptile.com/trex/runs/14067905/artifacts"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img alt="View all artifacts" src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a> <sub><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="14" align="absmiddle"></a> Ran code and verified through T-Rex</sub> </details> <details open><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | src/free_claude_code/application/execution.py | Moves shared provider execution into the application layer and keeps eager preflight before token counting and streaming. | | src/free_claude_code/application/ports.py | Adds structural provider, request-runtime, and task-control protocols used across the new boundary. | | src/free_claude_code/api/routes.py | Updates route composition to use the application provider resolver and task-control stop path. | | src/free_claude_code/providers/base.py | Makes provider preflight explicit by requiring subclasses or transport bases to implement it. | | src/free_claude_code/providers/transports/openai_chat/transport.py | Adds OpenAI-chat preflight through the same request-body builder used by streaming. | | src/free_claude_code/providers/transports/anthropic_messages/transport.py | Adds native Messages preflight through the native request-body builder. | | src/free_claude_code/providers/model_listing.py | Keeps provider model-list parsing while moving `ProviderModelInfo` ownership to the application layer. | | src/free_claude_code/runtime/bootstrap.py | Passes the runtime object through the new `tasks` service slot. | | tests/contracts/test_import_boundaries.py | Extends import-boundary tests for the new application package. | </details> <details open><summary><h3>Flowchart</h3></summary> <a href="#gh-light-mode-only"> ```mermaid %%{init: {'theme': 'neutral'}}%% flowchart LR API[api handlers and routes] --> Routing[application.routing] API --> Executor[application.execution] API --> Ports[application.ports] Executor --> ProviderPort[ProviderPort] ProviderPort --> Preflight[preflight_stream] ProviderPort --> Stream[stream_response] Runtime[runtime bootstrap and provider manager] --> Ports Providers[providers] --> Metadata[application.model_metadata] Executor --> Core[core anthropic and trace] Routing --> Config[config settings and model refs] ``` </a> <a href="#gh-dark-mode-only"> ```mermaid %%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% flowchart LR API[api handlers and routes] --> Routing[application.routing] API --> Executor[application.execution] API --> Ports[application.ports] Executor --> ProviderPort[ProviderPort] ProviderPort --> Preflight[preflight_stream] ProviderPort --> Stream[stream_response] Runtime[runtime bootstrap and provider manager] --> Ports Providers[providers] --> Metadata[application.model_metadata] Executor --> Core[core anthropic and trace] Routing --> Config[config settings and model refs] ``` </a> </details> <sub>Reviews (1): Last reviewed commit: ["Introduce typed application boundary"](https://github.com/alishahryar1/free-claude-code/commit/4cdcf97231c812c6f568ca3d74af7ce759d7f2dc) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43462788)</sub> <!-- /greptile_comment --> |
||
|
|
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 --> |
||
|
|
4951983b5e |
Replace global runtime resources with explicit ownership (#1042)
## Problem Provider, messaging, and transcription resources relied on process-global state, leaving replacement, cancellation, and shutdown ownership ambiguous. Separate server lifetimes could share event-loop-bound resources or retain failed cleanup work. ## Changes | Before | After | | --- | --- | | Provider clients found limiters through global singleton and scoped registries. | Each provider instance receives and owns one explicitly constructed limiter. | | Messaging queues and voice pipelines relied on singleton or module-global state. | Each platform owns its limiter and outbox, while the application owns one injected transcriber. | | Messaging shutdown mixed ingress, active work, delivery, and SDK cleanup. | Application shutdown quiesces ingress, drains work, closes delivery, then releases transcription and providers. | | Cancelled or failed provider cleanup could be forgotten or treated as complete. | The provider manager retains shielded generation and unpublished-runtime cleanup until it succeeds. | | Discord and Telegram startup tasks could outlive or poison runtime readiness. | Platform runtimes observe long-lived tasks and retry only independently repeatable lifecycle steps. | | Constructor-captured security and diagnostic settings appeared hot-applicable. | Admin marks those settings restart-required so applied policy matches the running resource graph. | | Lifecycle races lacked direct ownership coverage. | Deterministic cancellation, retry, isolation, teardown, and live smoke contracts protect the final ownership model. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR moves runtime resources from global state into explicitly owned application objects. The main changes are: - Provider generations own their rate limiters and cleanup tasks. - Messaging platforms own their limiter, outbox, ingress, and delivery lifecycle. - Application shutdown now runs through ordered cleanup gates. - Voice transcription is injected as an owned runtime resource. - Admin config marks constructor-captured settings as restart-required. </details> <h3>Confidence Score: 4/5</h3> The shutdown path needs a bounded cleanup result before merging. Cleanup steps that hang never reach the retryable incomplete-shutdown path. ASGI shutdown can remain stuck while waiting for an external SDK, transcriber, workflow, or provider cleanup. The retry ownership model works only after cleanup returns or raises. src/free_claude_code/runtime/application.py <details><summary><h3><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="20" align="absmiddle"></a> T-Rex Logs</h3></summary> **What T-Rex did** - T-Rex ran the requested verification, but its local artifact references were not uploaded. - The validation run completed successfully with EXIT\_CODE: 0 and 62 tests passed in 3.91 seconds, using the command uv run pytest -vv tests/runtime/test\_application\_runtime.py tests/runtime/test\_provider\_manager.py tests/providers/test\_provider\_runtime.py. <a href="https://app.greptile.com/trex/runs/14064214/artifacts"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img alt="View all artifacts" src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a> <sub><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="14" align="absmiddle"></a> Ran code and verified through T-Rex</sub> </details> <details open><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | src/free_claude_code/runtime/application.py | Refactors shutdown into ordered retryable cleanup gates, but cleanup awaitables can still block shutdown forever. | | src/free_claude_code/runtime/asgi.py | Reports incomplete runtime shutdown when `close()` returns false. | | src/free_claude_code/runtime/provider_manager.py | Adds owned provider cleanup retry state and shielded generation cleanup. | </details> <a href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22refactor%2Fruntime-owned-resources%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22refactor%2Fruntime-owned-resources%22.%0A%0AFix%20the%20following%201%20code%20review%20issue.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%201%0Asrc%2Ffree_claude_code%2Fruntime%2Fapplication.py%3A59%0A**Cleanup%20Await%20Blocks%20Shutdown**%0A%0AWhen%20a%20platform%20SDK%20stop%2C%20workflow%20drain%2C%20transcriber%20close%2C%20or%20provider%20cleanup%20hangs%2C%20this%20helper%20waits%20forever%20and%20never%20returns%20%60False%60.%20ASGI%20shutdown%20stays%20stuck%20in%20%60runtime.close%28%29%60%20instead%20of%20reporting%20an%20incomplete%20shutdown%2C%20so%20the%20retained%20resource%20graph%20cannot%20be%20retried%20cleanly.%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1042&platform=github"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodexDark.svg?v=6"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"><img alt="Fix All in Codex" src="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"></picture></a> <sub>Reviews (2): Last reviewed commit: ["Report incomplete runtime shutdown to AS..."](https://github.com/alishahryar1/free-claude-code/commit/338b2bd179c3875b15bbd52818dd04c780e5d46d) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43454593)</sub> > Greptile also left **1 inline comment** on this PR. **Context used:** - Context used - CLAUDE.md ([source](https://app.greptile.com/alishahryar1/github/Alishahryar1/free-claude-code/-/custom-context?memory=d2fd24d8-0dec-4faf-8ee4-e085e215a2f8)) <!-- /greptile_comment --> |
||
|
|
160d63370b |
Establish single-owner runtime with stream-safe provider hot swaps (#1036)
## Problem Provider runtime ownership was split between lifecycle code and mutable FastAPI state, so Admin replacements could leak the new runtime, double-close the old runtime, or close providers still serving active streams. The API package also owned concrete process composition, obscuring subsystem boundaries. ## Changes | Before | After | | --- | --- | | FastAPI routes inspected several concrete `app.state` resources. | FastAPI receives one explicit `ApiServices` boundary and stores only `app.state.services`. | | Admin Apply persisted config and directly replaced one runtime reference. | Admin Apply validates a candidate, commits atomically, and publishes it through the single runtime owner. | | Provider replacement could close clients used by active streams. | Generation leases retain old providers until each streaming or non-streaming response finishes. | | Provider generations owned discovery state and model metadata. | `ProviderRuntimeManager` owns one application-lifetime catalog and one discovery task across replacements. | | API modules composed provider, messaging, and managed CLI resources. | `runtime.bootstrap` composes concrete subsystems and `ApplicationRuntime` owns their lifecycle. | | Admin config, server URLs, and gateway model IDs lived under the API package. | Admin config lives under `config`, server URLs live under `config`, and gateway IDs live under `core`. | | Messaging restoration and shutdown persistence were coordinated externally. | `MessagingWorkflow` owns snapshot restoration and final persistence flushing. | | Hot-swap behavior lacked a real process-level race scenario. | Deterministic ownership tests and a credential-free subprocess smoke hold provider A while new requests switch to provider B. | | Package version was `3.4.16`. | Package version is `3.4.17` with an updated lockfile. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR centralizes server runtime ownership and provider hot swaps. The main changes are: - Adds `ApplicationRuntime` and `ProviderRuntimeManager` as the process owners. - Moves FastAPI to an explicit `ApiServices` boundary. - Retains provider generations until request and stream responses finish. - Moves admin config, server URL, and gateway model ID modules to neutral package owners. - Updates admin apply to validate, persist, and publish provider-only changes through the runtime owner. - Adds runtime ownership tests and a credential-free smoke scenario. </details> <h3>Confidence Score: 5/5</h3> This looks safe to merge. No blocking issues found in the changed code. The provider lease path releases resources on normal completion, stream close, and cancellation. The admin apply path keeps restart-required changes separate from provider-only hot swaps, and repository import paths appear updated for the moved modules. No files need follow-up attention. <details><summary><h3><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="20" align="absmiddle"></a> T-Rex Logs</h3></summary> **What T-Rex did** - Ran the T-Rex smoke test command and confirmed it completed with exit code 0 and pytest passing. - Monitored runtime ownership activity during the run, including a provider A stream request on model-a generation 1, an admin publish to generation 2, a new request on model-b generation 2, and the completion of the original generation 1 stream. - Collected smoke result artifacts from the .smoke-results area for gateway 1, gateway 0, and main, and made them available for review. - Opened the smoke report JSON artifacts to review the summarized outcomes for each target environment. <a href="https://app.greptile.com/trex/runs/14008910/artifacts"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img alt="View all artifacts" src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a> <sub><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="14" align="absmiddle"></a> Ran code and verified through T-Rex</sub> </details> <details open><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | src/free_claude_code/runtime/provider_manager.py | Adds provider generation ownership, request leases, replacement, discovery refresh, and shutdown cleanup. | | src/free_claude_code/runtime/application.py | Adds the process-level owner for startup, shutdown, admin operations, messaging, and session control. | | src/free_claude_code/api/routes.py | Routes now acquire provider generation leases and bind them to response lifetime. | | src/free_claude_code/api/response_streams.py | Adds response lifetime binding so retained resources release after stream completion, cancellation, or close. | | src/free_claude_code/config/admin/persistence.py | Moves admin config persistence into `config` and adds prepared validation plus atomic managed-env commits. | | src/free_claude_code/runtime/bootstrap.py | Adds the production composition root for logging, runtime owners, services, and ASGI wiring. | | src/free_claude_code/api/__init__.py | Removes package-level API re-exports as part of the HTTP adapter boundary cleanup. | </details> <details open><summary><h3>Sequence Diagram</h3></summary> <a href="#gh-light-mode-only"> ```mermaid %%{init: {'theme': 'neutral'}}%% sequenceDiagram participant Client participant API as FastAPI Route participant Manager as ProviderRuntimeManager participant Lease as Generation Lease participant Runtime as Provider Generation participant Admin as Admin Apply Client->>API: Request /v1/messages or /v1/responses API->>Manager: acquire() Manager-->>API: lease for current generation API->>Lease: resolve_provider() Lease->>Runtime: use provider instance Runtime-->>Client: response body or stream Admin->>Manager: replace(candidate settings) Manager->>Manager: publish new generation Manager->>Manager: retire old generation Client-->>API: response completes or disconnects API->>Lease: release() Lease->>Manager: decrement active leases Manager->>Runtime: cleanup retired generation when drained ``` </a> <a href="#gh-dark-mode-only"> ```mermaid %%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant Client participant API as FastAPI Route participant Manager as ProviderRuntimeManager participant Lease as Generation Lease participant Runtime as Provider Generation participant Admin as Admin Apply Client->>API: Request /v1/messages or /v1/responses API->>Manager: acquire() Manager-->>API: lease for current generation API->>Lease: resolve_provider() Lease->>Runtime: use provider instance Runtime-->>Client: response body or stream Admin->>Manager: replace(candidate settings) Manager->>Manager: publish new generation Manager->>Manager: retire old generation Client-->>API: response completes or disconnects API->>Lease: release() Lease->>Manager: decrement active leases Manager->>Runtime: cleanup retired generation when drained ``` </a> </details> <sub>Reviews (1): Last reviewed commit: ["refactor: establish single-owner applica..."](https://github.com/alishahryar1/free-claude-code/commit/92fc06aa733b7acc34ad6ea50de8b6b4ce5cfac1) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43349002)</sub> <!-- /greptile_comment --> |
||
|
|
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 --> |
||
|
|
3c9d0ced76 |
Simplify README around customer usage (#1032)
## Problem The README mixed customer setup with provider internals and contributor guidance, making installation and everyday usage harder to scan. ## Changes | Before | After | | --- | --- | | Customer setup was spread across a 725-line README. | Customer setup follows a clear install, configure, run, connect, and manage flow. | | Providers used long implementation-oriented sections. | All 24 providers use a compact configuration table with essential notes. | | Secondary clients and integrations filled the main scan path. | Secondary clients and integrations use collapsible usage guides. | | Development and contribution guidance lived in the customer README. | Contributor guidance lives in `CONTRIBUTING.md`, with architecture linked separately. | | Internal capabilities were classified as README claims. | Internal capabilities are classified as public-surface coverage and provider documentation is contract-tested. | | README simplification risked removing project identity and social proof. | Existing badges, screenshot gallery, and Star History remain. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR simplifies the customer README and moves contributor guidance into a dedicated file. The main changes are: - Shorter Quick Start, provider, client, integration, and management sections in `README.md`. - New `CONTRIBUTING.md` with setup, checks, standards, and versioning guidance. - Feature coverage reclassified from README claims to public-surface coverage. - A contract test for keeping the README provider table aligned with the provider catalog. </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 Pytest-based docs contract checks and captured a log that records the Pytest command, working directory, output, and exit code 0. - Ran the Ruff-based docs contract validation and captured a log that records the Ruff command, working directory, output, and exit code 0. <a href="https://app.greptile.com/trex/runs/13926440/artifacts"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img alt="View all artifacts" src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a> <sub><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="14" align="absmiddle"></a> Ran code and verified through T-Rex</sub> </details> <details open><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | README.md | Reworked the README into a shorter customer setup and usage guide. | | CONTRIBUTING.md | Added contributor setup, quality checks, project standards, and versioning guidance. | | smoke/features.py | Moved several feature entries from README coverage to public-surface coverage. | | tests/contracts/test_feature_manifest.py | Added a provider table contract test against the provider catalog. | </details> <sub>Reviews (1): Last reviewed commit: ["Simplify README around customer usage"](https://github.com/alishahryar1/free-claude-code/commit/ba0a7a837417b1566f071373d71ae14ecadfe5e7) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43185730)</sub> <!-- /greptile_comment --> |
||
|
|
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 --> |
||
|
|
58aef0dc8a |
Refactor provider runtime ownership (#925)
## Problem Provider construction, model discovery, validation, and cleanup lived in one registry module. API and admin routes depended on registry-shaped app state and legacy process-level provider helpers. ## Changes | Before | After | | --- | --- | | `providers.registry` mixed provider factories, config, cache, discovery, validation, and cleanup. | `providers.runtime` splits factories, config, cache, model cache, discovery, validation, and runtime orchestration. | | API and admin routes read `app.state.provider_registry` and sometimes created registries ad hoc. | API and admin routes use app-scoped `ProviderRuntime` through `app.state.provider_runtime`. | | `api.dependencies` kept process-global provider cache helpers. | `api.dependencies` resolves providers only through the app-scoped runtime. | | Registry-shaped tests preserved old internal boundaries. | Runtime-shaped tests assert provider config, construction, cache, discovery, validation, and import boundaries. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR moves provider lifecycle ownership from the old registry module into an app-scoped runtime package. The main changes are: - Split provider config, factory wiring, instance cache, model cache, discovery, validation, and cleanup into `providers.runtime` modules. - Updated API and admin routes to resolve providers and model metadata through `app.state.provider_runtime`. - Removed legacy process-global provider helpers and the deleted `providers.registry` module. - Updated docs, smoke metadata, import-boundary checks, and tests for the new runtime ownership model. - Bumped the package version and lockfile metadata for the production refactor. </details> <h3>Confidence Score: 5/5</h3> The provider runtime refactor appears merge-safe with no identified blocking issues. The changes consistently move provider ownership to app-scoped runtime modules and update API, admin, docs, smoke metadata, import-boundary checks, and tests around that architecture. <details><summary><h3><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="20" align="absmiddle"></a> T-Rex Logs</h3></summary> **What T-Rex did** - Ran a baseline and head comparison of provider registry and runtime states, verifying the after-state shows head state\_has\_provider\_registry=False and state\_has\_provider\_runtime=True, that GET /v1/models and admin endpoints respond with 200, and that provider\_resolver\_called via runtime, with assertions passing. - Verified that the four focused provider-runtime contract tests passed in both the before and after refactor runs, including runtime split checks, with exit code 0. - Identified environmental blockers that prevented the smoke-runtime workflow from running, including uv unavailability, missing pytest for /usr/local/bin/python, and Python 3.11 being used despite pyproject.toml requiring \>=3.14. <a href="https://app.greptile.com/trex/runs/12528505/artifacts"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=1"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=1"><img alt="View all artifacts" src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=1" height="32"></picture></a> <sub><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="14" align="absmiddle"></a> Ran code and verified through T-Rex</sub> </details> <sub>Reviews (1): Last reviewed commit: ["Refactor provider runtime ownership"](https://github.com/alishahryar1/free-claude-code/commit/01d589488185c1f85112f1a49c47f04512846161) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=40312173)</sub> <!-- /greptile_comment --> |
||
|
|
6bee3104fe |
Refactor CLI surfaces around launchers and managed Claude (#861)
## Problem The CLI package preserved a generic adapter layer and managed Codex parser path that did not match the supported customer workflows. Messaging runs Claude Code sessions, while Codex is supported through `fcc-codex` and extensions. ## Changes | Before | After | | --- | --- | | `fcc-claude` and `fcc-codex` shared generic adapter plumbing. | `fcc-claude` and `fcc-codex` use explicit launcher modules. | | Messaging depended on a generic CLI session abstraction. | Messaging depends on managed Claude Code sessions. | | Codex catalog generation lived as a top-level CLI helper. | Codex catalog generation lives under the Codex launcher owner. | | Tests asserted deleted internal adapter shapes. | Tests assert launcher, managed-Claude, and customer-surface behavior. | |
||
|
|
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` |
||
|
|
b26957faaf | Update README | ||
|
|
3abe41d270 | Add Codex support (#691) | ||
|
|
044a152fb4 | Add Gemini thought signature smoke | ||
|
|
de8e902899 | Add Claude CLI smoke matrices | ||
|
|
07497c7ed8 | Add NVIDIA NIM CLI smoke matrix and tool schema aliasing | ||
|
|
2d2bf3de70 |
fix: replay reasoning_content for DeepSeek/NIM and expand provider smoke
- Add ReasoningReplayMode and top-level reasoning replay in OpenAI conversion - DeepSeek/NIM request bodies use reasoning_content when thinking is enabled - NIM retries without reasoning_content on 400 from upstream - Per-provider smoke models (FCC_SMOKE_MODEL_*) independent of MODEL mapping - Fix smoke model override parsing for owner/model names with slashes - Live smoke: reasoning tool continuation uses synthetic thinking+tool history - Tests and docs updated |
||
|
|
b525217633 |
[feat] ollama method support (#129)
Support use ollama method like LM stuio --------- Co-authored-by: Alishahryar1 <alishahryar2@gmail.com> Co-authored-by: u011436427 <u011436427@noreply.gitcode.com> |
||
|
|
f29e693dc5 | Add per-model thinking toggles | ||
|
|
0e3b2c24b4 |
refactor: remove OpenRouter rollback, shims, and redundant layers
- OpenRouter: native Anthropic only; remove chat_request and OPENROUTER_TRANSPORT - Drop OpenAICompatibleProvider alias, api.request_utils, voice_pipeline facade - Simplify OpenRouter SSE, generic reasoning in conversion, messaging dispatch - Shared markdown table helpers; API optimization response helper; contract guards - Restore PLAN.md; update docs and tests |
||
|
|
66ef23072c | Refactor provider routing and smoke coverage | ||
|
|
751694a5da |
Refactor smoke testing framework and enhance provider configurations
- Updated DEFAULT_TARGETS in config.py to include new targets: clients, llamacpp, and lmstudio, while removing contract and optimizations. - Introduced TARGET_ALIASES for better target management. - Added TARGET_REQUIRED_ENV to specify environment variables needed for each target. - Enhanced SmokeOutcome in report.py to include classification of outcomes for better reporting. - Implemented classify_outcome function to categorize smoke test results. - Added new test for stop endpoint in test_api_live.py to ensure proper error handling. - Updated test_auth_live.py to enforce auth token requirements and utilize environment files. - Changed target from vscode to clients in test_client_shapes_live.py. - Removed obsolete test_feature_manifest.py and test_stream_contracts.py files. - Added new skip helpers in skips.py to manage upstream unavailability scenarios. - Created new tests for local provider endpoints in test_local_provider_endpoints_live.py. - Added comprehensive feature inventory tests in tests/contracts/test_feature_manifest.py. - Implemented stream contract tests in tests/contracts/test_stream_contracts.py. |
||
|
|
462a9430bb |
Add local live smoke test suite (#148)
## Summary - add an opt-in local `smoke/` pytest suite for API, auth, providers, CLI, IDE-shaped requests, messaging, voice, tools, and thinking stream contracts - keep smoke tests out of normal CI collection with `testpaths = ["tests"]` - write sanitized smoke artifacts under `.smoke-results/` ## Verification - `uv run ruff format` - `uv run ruff check` - `uv run ty check` - `uv run ty check smoke` - `FCC_LIVE_SMOKE=1 FCC_SMOKE_TARGETS=all FCC_SMOKE_RUN_VOICE=1 uv run pytest smoke -n 0 -m live -s --tb=short` -> 17 passed, 9 skipped - `uv run pytest` -> 904 passed ## Notes - Skipped live checks require local credentials/tools/services, such as provider models, Telegram/Discord targets, voice backend, or Claude CLI. - `claude-pick` smoke was intentionally removed. |