main
12 次代码提交
| 作者 | SHA1 | 备注 | 提交日期 | |
|---|---|---|---|---|
|
|
2a676cc6d9 |
Make ProviderModelInfo the sole model-catalog contract (#1222)
## Problem Provider model discovery consumes metadata, but providers and the cache still expose a parallel IDs-only contract. The duplicate contract adds adapters and lets tests bypass capability metadata. ## Changes | Before | After | | --- | --- | | `BaseProvider` exposed `list_model_ids()` plus a metadata adapter. | `BaseProvider` exposes only abstract `list_model_infos()` returning application-owned metadata. | | Ordinary providers parsed IDs and converted them later. | Ordinary providers parse OpenAI-compatible catalogs directly into `ProviderModelInfo` values. | | OpenRouter, Cloudflare, and GitHub Models maintained redundant IDs-only wrappers. | Provider-specific filters and capability metadata have one return path. | | Vertex returned paginated IDs for the base adapter to wrap. | Vertex returns metadata after completing the same paginated discovery flow. | | The runtime cache exposed test-only raw-ID write and prefixed-ID read helpers. | The runtime cache accepts and returns metadata while retaining its production admin-status ID projection. | | Provider tests asserted the parallel IDs-only API. | Provider tests enforce the metadata-only contract and preserve provider-specific discovery behavior. | | The package version was `4.11.6`. | The package version is `4.11.7` with an updated lockfile. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR makes provider metadata the only model-catalog contract. The main changes are: - Makes `list_model_infos()` the abstract provider discovery API. - Migrates provider parsers and implementations to `ProviderModelInfo`. - Removes IDs-only cache and parser helpers. - Updates provider tests, architecture documentation, and package metadata. </details> <h3>Confidence Score: 4/5</h3> The catalog migration is consistent, but the release version must reflect the incompatible API removal. Repository provider and cache call paths use the new metadata shape consistently. Existing external consumers of the removed contracts can fail after a patch upgrade. The repository rules classify incompatible API removals as a major release. pyproject.toml and the matching package entry in uv.lock <details><summary><h3><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="20" align="absmiddle"></a> T-Rex Logs</h3></summary> **What T-Rex did** - The external-consumer compatibility probe was run against both revisions, confirming the base still supports the legacy provider contract, while head fails with a TypeError due to the missing list\_model\_infos method, and runtime metadata shows head at version 4.11.7, indicating the removal is a patch transition rather than a major change. - An automated test suite completed successfully with 83 tests passing in 3.31 seconds. <a href="https://app.greptile.com/trex/runs/15207030/artifacts"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img alt="View all artifacts" src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a> <sub><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="14" align="absmiddle"></a> Ran code and verified through T-Rex</sub> </details> <details open><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | src/free_claude_code/providers/base.py | Replaces the IDs-only provider API with an abstract metadata-only contract. | | src/free_claude_code/providers/model_listing.py | Consolidates OpenAI-compatible parsing into ProviderModelInfo results and removes IDs-only helpers. | | src/free_claude_code/providers/runtime/model_cache.py | Removes raw-ID helpers while retaining metadata storage and the admin ID projection. | | src/free_claude_code/providers/openai_chat/provider.py | Provides the metadata discovery implementation inherited by ordinary OpenAI-compatible providers. | | src/free_claude_code/providers/vertex/client.py | Preserves paginated discovery while returning metadata values. | | pyproject.toml | Uses a patch bump for a release that removes callable and importable contracts. | </details> <details open><summary><h3>Flowchart</h3></summary> <a href="#gh-light-mode-only"> ```mermaid %%{init: {'theme': 'neutral'}}%% flowchart LR A[Provider catalog endpoint] --> B[list_model_infos] B --> C[ProviderModelInfo set] C --> D[Provider model discovery] D --> E[ProviderModelCache] E --> F[Metadata-aware catalog] E --> G[Admin ID projection] ``` </a> <a href="#gh-dark-mode-only"> ```mermaid %%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% flowchart LR A[Provider catalog endpoint] --> B[list_model_infos] B --> C[ProviderModelInfo set] C --> D[Provider model discovery] D --> E[ProviderModelCache] E --> F[Metadata-aware catalog] E --> G[Admin ID projection] ``` </a> </details> <a href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22ali%2Fprovider-model-info-contract%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22ali%2Fprovider-model-info-contract%22.%0A%0AFix%20the%20following%201%20code%20review%20issue.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%201%0Apyproject.toml%3A7%0A**Breaking%20Contract%20Ships%20as%20Patch**%0A%0AThis%20release%20removes%20%60BaseProvider.list_model_ids%28%29%60%20and%20cache%2Fparser%20methods%20that%20existing%20integrations%20can%20import%20or%20call.%20Such%20consumers%20will%20fail%20with%20%60TypeError%60%2C%20%60AttributeError%60%2C%20or%20%60ImportError%60%20after%20a%20patch%20upgrade%2C%20so%20this%20incompatible%20API%20change%20requires%20a%20major%20version%20bump%20under%20the%20repository's%20versioning%20rules.%0A%0A%60%60%60suggestion%0Aversion%20%3D%20%225.0.0%22%0A%60%60%60%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1222&platform=github"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodexDark.svg?v=6"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"><img alt="Fix All in Codex" src="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"></picture></a> <sub>Reviews (1): Last reviewed commit: ["Make ProviderModelInfo the sole catalog ..."](https://github.com/alishahryar1/free-claude-code/commit/5c543eadc114201a4085d38885a27ac49153ca29) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=45869248)</sub> > Greptile also left **1 inline comment** on this PR. **Context used:** - Context used - CLAUDE.md ([source](https://app.greptile.com/alishahryar1/github/Alishahryar1/free-claude-code/-/custom-context?memory=d2fd24d8-0dec-4faf-8ee4-e085e215a2f8)) <!-- /greptile_comment --> |
||
|
|
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 --> |
||
|
|
984c4c23b7 |
Fix Auto Mode classifier responses when stream is omitted (#1098)
## Problem Claude Code Auto Mode classifier requests omit `stream`, which means they expect a non-streaming Messages response. FCC treated omission as streaming, returned SSE, and caused Claude to report the classifier model as temporarily unavailable. Fixes #1094. ## Changes | Before | After | | --- | --- | | Omitted `stream` defaulted to streaming SSE. | Omitted `stream` defaults to a complete JSON Message; only `stream: true` selects SSE. | | Classifier side queries received a body without top-level `usage`. | Classifier side queries receive a JSON Message with top-level `usage` while thinking remains disabled. | | Tests encoded FCC's nonstandard streaming default. | Model and HTTP-boundary tests enforce Anthropic's response-mode contract. | | The package version was 4.3.0. | The package version is 4.3.1. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR fixes Messages response mode handling when clients omit `stream`. The main changes are: - Defaulted Anthropic Messages requests to non-streaming JSON. - Returned SSE only when `stream: true` is set. - Updated classifier, handler, web-tool, and model tests for the new contract. - Documented the default response mode and bumped the package version. </details> <h3>Confidence Score: 5/5</h3> This looks safe to merge after deciding whether `stream: null` should remain accepted. The JSON-by-default Messages path is covered in the model, handler, and API tests. Explicit streaming still flows through the SSE path. Clients that send `stream: null` can now get a validation error instead of a response. <details><summary><h3><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="20" align="absmiddle"></a> T-Rex Logs</h3></summary> **What T-Rex did** - Ran the full test suite for the code under test; pytest completed with 132 tests passed in 2.96s and exited with code 0. - Validated the testclient probe non-stream request returned 200 OK with a JSON message. - Validated the testclient probe stream request returned 200 OK with a text/event-stream SSE and routing/behaviors as expected (routed\_stream true, thinking\_enabled\_kwarg false). <a href="https://app.greptile.com/trex/runs/14257681/artifacts"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img alt="View all artifacts" src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a> <sub><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="14" align="absmiddle"></a> Ran code and verified through T-Rex</sub> </details> <details open><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | src/free_claude_code/core/anthropic/models.py | Changes `MessagesRequest.stream` to default to non-streaming JSON and reject null values. | | src/free_claude_code/api/handlers/messages.py | Aggregates internal SSE into JSON unless streaming was explicitly requested. | | src/free_claude_code/api/routes.py | Updates the Messages route description to match the new JSON-by-default behavior. | | src/free_claude_code/core/anthropic/sse_aggregation.py | Updates aggregation documentation for omitted and false stream requests. | | tests/api/test_api.py | Adds coverage for classifier-style requests that omit `stream` and expect JSON. | | tests/api/test_api_handlers.py | Marks streaming handler tests with explicit `stream=True`. | | tests/api/test_web_server_tools.py | Marks the forced web-search streaming test with explicit `stream=True`. | | tests/core/anthropic/test_models.py | Updates model expectations for the new default and adds null-stream rejection coverage. | | pyproject.toml | Bumps the package version to `4.3.1`. | | uv.lock | Keeps the editable package version in sync with `pyproject.toml`. | | ARCHITECTURE.md | Documents that Messages responses are non-streaming unless `stream: true` is provided. | </details> <a href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22ali%2Ffix-auto-mode-omitted-stream%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22ali%2Ffix-auto-mode-omitted-stream%22.%0A%0AFix%20the%20following%201%20code%20review%20issue.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%201%0Asrc%2Ffree_claude_code%2Fcore%2Fanthropic%2Fmodels.py%3A186%0A**Null%20Stream%20Now%20Fails%20Validation**%0A%0AWhen%20a%20client%20serializes%20an%20unspecified%20optional%20stream%20flag%20as%20%60%22stream%22%3A%20null%60%2C%20this%20narrowed%20field%20rejects%20the%20request%20before%20the%20handler%20can%20return%20the%20new%20non-streaming%20JSON%20response.%20The%20old%20model%20accepted%20that%20input%2C%20so%20these%20clients%20now%20receive%20a%20validation%20error%20instead%20of%20a%20Message%20object.%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1098&platform=github"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodexDark.svg?v=6"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"><img alt="Fix All in Codex" src="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"></picture></a> <sub>Reviews (1): Last reviewed commit: ["Fix omitted Messages stream default"](https://github.com/alishahryar1/free-claude-code/commit/ca61e5ad4adf085d5cef1e0e5f3a8ae26d189853) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=43859149)</sub> > Greptile also left **1 inline comment** on this PR. <!-- /greptile_comment --> |
||
|
|
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 --> |
||
|
|
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 --> |
||
|
|
71a78a0c5a |
Move runtime packages under src namespace (#1029)
## Problem Runtime modules were published as generic top-level packages like `api`, `cli`, and `providers`. That shape is fragile for PyPI packaging and weakens explicit ownership boundaries. ## Changes | Before | After | | --- | --- | | Runtime code lived in root-level packages. | Runtime code lives under `src/free_claude_code/`. | | Console scripts targeted top-level modules. | Console scripts target namespaced modules. | | Tests and smoke helpers imported old package roots. | Tests and smoke helpers import `free_claude_code.*`. | | Packaging listed six root packages. | Packaging builds the single namespaced package. | | Contracts allowed old root package directories. | Contracts require the src namespace and reject old root imports. | <!-- greptile_comment --> <details open><summary><h3>Greptile Summary</h3></summary> This PR moves the runtime packages into the `src/free_claude_code` namespace. The main changes are: - Console scripts now point to `free_claude_code.*` entrypoints. - Runtime imports, tests, and smoke helpers now use the namespaced package. - Packaging now builds the single `src/free_claude_code` package. - Contract tests now reject old top-level runtime package roots and imports. </details> <h3>Confidence Score: 5/5</h3> This PR is safe to merge with minimal risk. The changes are a broad but mostly mechanical namespace and package-layout migration with updated packaging, tests, and contract coverage. No files require special attention. <details><summary><h3><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="20" align="absmiddle"></a> T-Rex Logs</h3></summary> **What T-Rex did** - Reviewed the primary contract validation by examining the namespace validation log, which documents the exact commands executed, the working directory, exit codes, pytest output, wheel build output, install output, and import/entrypoint resolution. - Verified the wheel listing by inspecting the wheel listing artifact, confirming the available wheel filenames for the namespace validation. - Ran and inspected the isolated import/entrypoint validation harness saved as package-installed-import-check.py to validate import resolution and entrypoint exposure. - Captured and noted the wheel filename record in package-wheel-filename.txt to enable traceability of the observed artifact. <a href="https://app.greptile.com/trex/runs/13810533/artifacts"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img alt="View all artifacts" src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a> <sub><a href="https://www.greptile.com/trex"><img alt="T-Rex" src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg" height="14" align="absmiddle"></a> Ran code and verified through T-Rex</sub> </details> <details open><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | pyproject.toml | Updates packaging to build the single `src/free_claude_code` package and retargets console scripts to namespaced modules. | | src/free_claude_code/config/env_template.py | Loads `.env.example` from packaged resources with a source-checkout fallback after the runtime package move. | | src/free_claude_code/cli/entrypoints.py | Updates CLI entrypoint imports to `free_claude_code.*` and continues to use the shared env template loader. | | src/free_claude_code/api/routes.py | Retargets API route dependencies and handlers to the namespaced package without changing route behavior. | | src/free_claude_code/api/app.py | Updates app factory imports to the namespaced package while preserving middleware, routers, and exception handling. | | src/free_claude_code/providers/runtime/factory.py | Updates lazy provider factory imports to `free_claude_code.providers.*` under the new package layout. | | tests/contracts/test_import_boundaries.py | Adds contract coverage requiring runtime packages to live under `src/free_claude_code` and rejecting old top-level imports. | | smoke/lib/child_process.py | Updates smoke child-process helpers to import CLI entrypoints from the namespaced package. | | README.md | Updates the project layout and extension guidance to refer to `src/free_claude_code` and importable `free_claude_code.*` modules. | | uv.lock | Reflects the package version bump associated with the runtime packaging move. | </details> <details open><summary><h3>Sequence Diagram</h3></summary> <a href="#gh-light-mode-only"> ```mermaid %%{init: {'theme': 'neutral'}}%% sequenceDiagram participant User as User / CLI participant Script as Console script participant Pkg as free_claude_code package participant API as free_claude_code.api participant Runtime as free_claude_code.providers.runtime participant Provider as Provider adapter User->>Script: run fcc-server / free-claude-code Script->>Pkg: load free_claude_code.cli.entrypoints:serve Pkg->>API: create FastAPI app and routes API->>Runtime: resolve configured provider Runtime->>Provider: instantiate namespaced adapter Provider-->>Runtime: stream/model responses Runtime-->>API: provider result API-->>User: Anthropic/OpenAI-compatible response ``` </a> <a href="#gh-dark-mode-only"> ```mermaid %%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant User as User / CLI participant Script as Console script participant Pkg as free_claude_code package participant API as free_claude_code.api participant Runtime as free_claude_code.providers.runtime participant Provider as Provider adapter User->>Script: run fcc-server / free-claude-code Script->>Pkg: load free_claude_code.cli.entrypoints:serve Pkg->>API: create FastAPI app and routes API->>Runtime: resolve configured provider Runtime->>Provider: instantiate namespaced adapter Provider-->>Runtime: stream/model responses Runtime-->>API: provider result API-->>User: Anthropic/OpenAI-compatible response ``` </a> </details> <sub>Reviews (2): Last reviewed commit: ["Fix documented package import paths"](https://github.com/alishahryar1/free-claude-code/commit/bfa9f2704c45f3684da39657d5e13f3814e5d450) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=42950471)</sub> <!-- /greptile_comment --> |
||
|
|
d7c54c6dc5 | Preserve messaging transcript on stop | ||
|
|
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 --> |
||
|
|
dfbff528c6 | Fix stream:false requests returning malformed response (matches #917, #868, #771, #497 symptom) (#977) | ||
|
|
db60452c0c | Split API request handling by product surface (#923) |