Remove legacy future annotation imports (#982)
Some checks are pending
CI / Ban suppressions and legacy annotations (push) Waiting to run
CI / pytest (push) Waiting to run
CI / ruff-check (push) Waiting to run
CI / ruff-format (push) Waiting to run
CI / ty (push) Waiting to run

## 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"](6e6cda69da)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=41875785)</sub>

<!-- /greptile_comment -->
This commit is contained in:
Ali Khokhar 2026-07-04 21:41:51 -07:00 committed by GitHub
parent dfbff528c6
commit 85b601884d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
214 changed files with 87 additions and 492 deletions

View file

@ -1,5 +1,5 @@
# Branch protection: require every status check this workflow reports, for example:
# Ban type ignore suppressions
# Ban suppressions and legacy annotations
# ruff-format, ruff-check, ty, pytest
# GitHub may prefix with the workflow name (e.g. "CI / ruff-format"); use the names the branch protection UI offers after a run.
@ -17,8 +17,8 @@ concurrency:
cancel-in-progress: true
jobs:
no-type-ignore-suppressions:
name: Ban type ignore suppressions
no-suppressions-or-legacy-annotations:
name: Ban suppressions and legacy annotations
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
@ -30,10 +30,10 @@ jobs:
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
fetch-depth: 1
- name: "Fail on type: ignore (no suppressions allowed)"
- name: "Fail on type ignores and legacy future annotations"
run: |
if grep -rE '# type: ignore|# ty: ignore' --include='*.py' . --exclude-dir=.venv --exclude-dir=.git; then
echo "::error::type: ignore / ty: ignore comments are not allowed. Fix the underlying type errors instead."
if grep -rE '# type: ignore|# ty: ignore|from __future__ import annotations' --include='*.py' . --exclude-dir=.venv --exclude-dir=.git; then
echo "::error::type: ignore / ty: ignore comments and legacy future annotations are not allowed. Fix the underlying type/import issue instead."
exit 1
fi
exit 0

View file

@ -16,10 +16,11 @@
- GitHub CI remains check-only for Ruff (`ruff format --check`, `ruff check`) so branch protection verifies committed code.
- Fall back to individual repair commands when debugging local failures: `uv run ruff format`, `uv run ruff check --fix`, `uv run ty check`, `uv run pytest -v --tb=short`. Use GitHub-style checks only when verifying enforcement locally: `uv run ruff format --check`, `uv run ruff check`.
- Do not add `# type: ignore` or `# ty: ignore`; fix the underlying type issue.
- Do not add `from __future__ import annotations`; Python 3.14 native lazy annotations are the project standard.
- All 5 check IDs are represented in `scripts/ci.sh` / `scripts/ci.ps1` and enforced in `tests.yml` on push/merge (parallel jobs: suppression grep, ruff-format, ruff-check, ty, pytest).
- GitHub CI runs on `push`, `pull_request`, and `merge_group` so required checks validate merge queue candidates before they land.
- Repository protection should use rulesets: a non-bypassable main integrity ruleset requires pull requests, merge queue, required checks, and blocks direct/force pushes to `main`; a separate review ruleset may allow `Alishahryar1`/admins to bypass review only.
- Required status checks: set **required status checks** to **all** of those statuses (e.g. **Ban type ignore suppressions**, **ruff-format**, **ruff-check**, **ty**, **pytest**—use the exact labels GitHub shows, which may be prefixed with **CI /**). Remove **ci** from required checks if it was previously added for the old gate job.
- Required status checks: set **required status checks** to **all** of those statuses (e.g. **Ban suppressions and legacy annotations**, **ruff-format**, **ruff-check**, **ty**, **pytest**—use the exact labels GitHub shows, which may be prefixed with **CI /**). Remove **ci** from required checks if it was previously added for the old gate job.
## IDENTITY & CONTEXT
@ -37,6 +38,8 @@
- **Performance**: Use list accumulation for strings (not `+=` in loops), cache env vars at init, prefer iterative over recursive when stack depth matters.
- **Platform-agnostic naming**: Use generic names (e.g. `PLATFORM_EDIT`) not platform-specific ones (e.g. `TELEGRAM_EDIT`) in shared code.
- **No type ignores**: Do not add `# type: ignore` or `# ty: ignore`. Fix the underlying type issue.
- **Python 3.14 annotations**: Do not use `from __future__ import annotations`; rely on native lazy annotations and fix circular import boundaries instead of hiding them with annotation stringization.
- **Imports**: Prefer top-level imports. Avoid `TYPE_CHECKING` and local imports for first-party or required dependencies; if a top-level import creates a cycle, move shared types/protocols to a neutral owner.
- **Complete migrations**: When moving modules, update imports to the new owner and remove old compatibility shims in the same change unless preserving a published interface is explicitly required.
- **Maximum Test Coverage**: There should be maximum test coverage for everything, preferably live smoke test coverage to catch bugs early

View file

@ -16,10 +16,11 @@
- GitHub CI remains check-only for Ruff (`ruff format --check`, `ruff check`) so branch protection verifies committed code.
- Fall back to individual repair commands when debugging local failures: `uv run ruff format`, `uv run ruff check --fix`, `uv run ty check`, `uv run pytest -v --tb=short`. Use GitHub-style checks only when verifying enforcement locally: `uv run ruff format --check`, `uv run ruff check`.
- Do not add `# type: ignore` or `# ty: ignore`; fix the underlying type issue.
- Do not add `from __future__ import annotations`; Python 3.14 native lazy annotations are the project standard.
- All 5 check IDs are represented in `scripts/ci.sh` / `scripts/ci.ps1` and enforced in `tests.yml` on push/merge (parallel jobs: suppression grep, ruff-format, ruff-check, ty, pytest).
- GitHub CI runs on `push`, `pull_request`, and `merge_group` so required checks validate merge queue candidates before they land.
- Repository protection should use rulesets: a non-bypassable main integrity ruleset requires pull requests, merge queue, required checks, and blocks direct/force pushes to `main`; a separate review ruleset may allow `Alishahryar1`/admins to bypass review only.
- Required status checks: set **required status checks** to **all** of those statuses (e.g. **Ban type ignore suppressions**, **ruff-format**, **ruff-check**, **ty**, **pytest**—use the exact labels GitHub shows, which may be prefixed with **CI /**). Remove **ci** from required checks if it was previously added for the old gate job.
- Required status checks: set **required status checks** to **all** of those statuses (e.g. **Ban suppressions and legacy annotations**, **ruff-format**, **ruff-check**, **ty**, **pytest**—use the exact labels GitHub shows, which may be prefixed with **CI /**). Remove **ci** from required checks if it was previously added for the old gate job.
## IDENTITY & CONTEXT
@ -37,6 +38,8 @@
- **Performance**: Use list accumulation for strings (not `+=` in loops), cache env vars at init, prefer iterative over recursive when stack depth matters.
- **Platform-agnostic naming**: Use generic names (e.g. `PLATFORM_EDIT`) not platform-specific ones (e.g. `TELEGRAM_EDIT`) in shared code.
- **No type ignores**: Do not add `# type: ignore` or `# ty: ignore`. Fix the underlying type issue.
- **Python 3.14 annotations**: Do not use `from __future__ import annotations`; rely on native lazy annotations and fix circular import boundaries instead of hiding them with annotation stringization.
- **Imports**: Prefer top-level imports. Avoid `TYPE_CHECKING` and local imports for first-party or required dependencies; if a top-level import creates a cycle, move shared types/protocols to a neutral owner.
- **Complete migrations**: When moving modules, update imports to the new owner and remove old compatibility shims in the same change unless preserving a published interface is explicitly required.
- **Maximum Test Coverage**: There should be maximum test coverage for everything, preferably live smoke test coverage to catch bugs early

View file

@ -1,7 +1,5 @@
"""Admin UI configuration manifest."""
from __future__ import annotations
from collections.abc import Iterable
from dataclasses import dataclass
from typing import Literal

View file

@ -1,7 +1,5 @@
"""Managed env persistence, validation preview, and rendering."""
from __future__ import annotations
import os
from collections.abc import Mapping
from typing import Any

View file

@ -1,7 +1,5 @@
"""Catalog-derived Admin UI provider fields."""
from __future__ import annotations
from typing import Any
from config.provider_catalog import PROVIDER_CATALOG

View file

@ -1,7 +1,5 @@
"""Admin config source loading and source precedence."""
from __future__ import annotations
import os
from io import StringIO
from pathlib import Path

View file

@ -1,7 +1,5 @@
"""Provider configuration status for the Admin UI."""
from __future__ import annotations
from collections.abc import Mapping
from typing import Any

View file

@ -1,7 +1,5 @@
"""Settings-backed Admin UI config validation."""
from __future__ import annotations
from collections.abc import Mapping
from typing import Any

View file

@ -1,7 +1,5 @@
"""Admin config value state and API response assembly."""
from __future__ import annotations
import os
from typing import Any

View file

@ -1,7 +1,5 @@
"""Local admin UI routes and APIs."""
from __future__ import annotations
import inspect
import ipaddress
from pathlib import Path

View file

@ -1,7 +1,5 @@
"""Helpers for presenting local admin URLs."""
from __future__ import annotations
from config.settings import Settings

View file

@ -1,7 +1,5 @@
"""Gateway-safe model id encoding for Claude Code model discovery."""
from __future__ import annotations
from dataclasses import dataclass
GATEWAY_MODEL_ID_PREFIX = "anthropic"

View file

@ -1,7 +1,5 @@
"""Claude Messages API product flow."""
from __future__ import annotations
from collections.abc import AsyncIterator, Callable
from dataclasses import dataclass, replace

View file

@ -1,7 +1,5 @@
"""OpenAI Responses API product flow for Codex clients."""
from __future__ import annotations
from collections.abc import Callable
from fastapi.responses import JSONResponse

View file

@ -1,7 +1,5 @@
"""Anthropic token-count API product flow."""
from __future__ import annotations
import uuid
from fastapi import HTTPException

View file

@ -1,7 +1,5 @@
"""Model-list response construction for Claude-compatible clients."""
from __future__ import annotations
from config.model_refs import configured_chat_model_refs
from config.settings import Settings
from providers.runtime import ProviderRuntime

View file

@ -1,7 +1,5 @@
"""Model routing for Claude-compatible requests."""
from __future__ import annotations
from dataclasses import dataclass
from loguru import logger

View file

@ -1,7 +1,5 @@
"""Pydantic models for OpenAI Responses-compatible ingress."""
from __future__ import annotations
from typing import Any
from pydantic import BaseModel, ConfigDict

View file

@ -1,7 +1,5 @@
"""Shared provider execution primitive for API product handlers."""
from __future__ import annotations
import uuid
from collections.abc import AsyncIterator, Callable
from typing import Any

View file

@ -1,7 +1,5 @@
"""Shared API request validation and safe error logging."""
from __future__ import annotations
import traceback
from typing import Any

View file

@ -1,7 +1,5 @@
"""FastAPI streaming response wrappers for public API wire formats."""
from __future__ import annotations
from collections.abc import AsyncIterator, Mapping
from fastapi.responses import StreamingResponse

View file

@ -1,29 +1,30 @@
"""Application runtime composition and lifecycle ownership."""
from __future__ import annotations
import asyncio
import logging
import os
import traceback
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any
from typing import Any
from fastapi import FastAPI
from loguru import logger
import cli.managed as cli_managed
import messaging.limiter as messaging_limiter
import messaging.session as messaging_session
import messaging.trees as messaging_trees
import messaging.workflow as messaging_workflow_module
from api.admin_urls import local_admin_url
from config.env_files import ANTHROPIC_AUTH_TOKEN_ENV, process_env_key_is_effective
from config.paths import default_claude_workspace_path
from config.settings import Settings, get_settings
from messaging.platforms import factory as messaging_platform_factory
from messaging.platforms.factory import MessagingPlatformOptions
from messaging.platforms.ports import MessagingPlatformComponents, MessagingRuntime
from providers.exceptions import ServiceUnavailableError
from providers.runtime import ProviderRuntime
if TYPE_CHECKING:
from cli.managed import ManagedClaudeSessionManager
from messaging.platforms.ports import MessagingPlatformComponents, MessagingRuntime
from messaging.session import SessionStore
from messaging.workflow import MessagingWorkflow
_SHUTDOWN_TIMEOUT_S = 5.0
@ -92,8 +93,8 @@ class AppRuntime:
settings: Settings
_provider_runtime: ProviderRuntime | None = field(default=None, init=False)
messaging_runtime: MessagingRuntime | None = None
messaging_workflow: MessagingWorkflow | None = None
cli_manager: ManagedClaudeSessionManager | None = None
messaging_workflow: messaging_workflow_module.MessagingWorkflow | None = None
cli_manager: cli_managed.ManagedClaudeSessionManager | None = None
@classmethod
def for_app(
@ -179,12 +180,7 @@ class AppRuntime:
async def _start_messaging_if_configured(self) -> None:
try:
from messaging.platforms.factory import (
MessagingPlatformOptions,
create_messaging_components,
)
components = create_messaging_components(
components = messaging_platform_factory.create_messaging_components(
self.settings.messaging_platform,
MessagingPlatformOptions(
telegram_bot_token=self.settings.telegram_bot_token,
@ -217,8 +213,6 @@ class AppRuntime:
except Exception as e:
if self.settings.log_api_error_tracebacks:
logger.error("Failed to start messaging platform: {}", e)
import traceback
logger.error(traceback.format_exc())
else:
logger.error(
@ -229,10 +223,6 @@ class AppRuntime:
async def _start_messaging_workflow(
self, components: MessagingPlatformComponents
) -> None:
from cli.managed import ManagedClaudeSessionManager
from messaging.session import SessionStore
from messaging.workflow import MessagingWorkflow
workspace = (
os.path.abspath(self.settings.allowed_dir)
if self.settings.allowed_dir
@ -247,7 +237,7 @@ class AppRuntime:
allowed_dirs = [workspace] if self.settings.allowed_dir else []
plans_dir_abs = os.path.abspath(os.path.join(data_path, "plans"))
plans_directory = os.path.relpath(plans_dir_abs, workspace)
self.cli_manager = ManagedClaudeSessionManager(
self.cli_manager = cli_managed.ManagedClaudeSessionManager(
workspace_path=workspace,
api_url=api_url,
allowed_dirs=allowed_dirs,
@ -257,12 +247,12 @@ class AppRuntime:
log_messaging_error_details=self.settings.log_messaging_error_details,
)
session_store = SessionStore(
session_store = messaging_session.SessionStore(
storage_path=os.path.join(data_path, "sessions.json"),
message_log_cap=self.settings.max_message_log_entries_per_chat,
)
self.messaging_runtime = components.runtime
self.messaging_workflow = MessagingWorkflow(
self.messaging_workflow = messaging_workflow_module.MessagingWorkflow(
platform_name=components.name,
outbound=components.outbound,
voice_cancellation=components.voice_cancellation,
@ -280,7 +270,9 @@ class AppRuntime:
await components.runtime.start()
logger.info("{} platform started with messaging workflow", components.name)
def _restore_tree_state(self, session_store: SessionStore) -> None:
def _restore_tree_state(
self, session_store: messaging_session.SessionStore
) -> None:
conversation_snapshot = session_store.load_conversation_snapshot()
if conversation_snapshot.is_empty:
return
@ -291,10 +283,9 @@ class AppRuntime:
"Restoring {} conversation trees...",
len(conversation_snapshot.trees),
)
from messaging.trees import TreeQueueManager
self.messaging_workflow.replace_tree_queue(
TreeQueueManager.from_snapshot(
messaging_trees.TreeQueueManager.from_snapshot(
conversation_snapshot,
queue_update_callback=self.messaging_workflow.update_queue_positions,
node_started_callback=self.messaging_workflow.mark_node_processing,
@ -313,24 +304,18 @@ class AppRuntime:
async def _shutdown_limiter(self) -> None:
verbose = self.settings.log_api_error_tracebacks
try:
from messaging.limiter import MessagingRateLimiter
await best_effort(
"MessagingRateLimiter.shutdown_instance",
messaging_limiter.MessagingRateLimiter.shutdown_instance(),
timeout_s=2.0,
log_verbose_errors=verbose,
)
except Exception as e:
if verbose:
logger.debug(
"Rate limiter shutdown skipped (import failed): {}: {}",
type(e).__name__,
e,
"Rate limiter shutdown skipped: {}: {}", type(e).__name__, e
)
else:
logger.debug(
"Rate limiter shutdown skipped (import failed): exc_type={}",
type(e).__name__,
"Rate limiter shutdown skipped: exc_type={}", type(e).__name__
)
return
await best_effort(
"MessagingRateLimiter.shutdown_instance",
MessagingRateLimiter.shutdown_instance(),
timeout_s=2.0,
log_verbose_errors=verbose,
)

View file

@ -1,7 +1,5 @@
"""Safe metadata summaries for HTTP 422 validation logging (no raw text content)."""
from __future__ import annotations
from typing import Any

View file

@ -1,7 +1,5 @@
"""Compatibility re-exports for :mod:`api.web_tools` (web_search / web_fetch)."""
from __future__ import annotations
import httpx
from api.web_tools.egress import (

View file

@ -1,7 +1,5 @@
"""Egress policy for user-controlled web_fetch URLs (SSRF guard)."""
from __future__ import annotations
import ipaddress
import socket
from dataclasses import dataclass

View file

@ -1,7 +1,5 @@
"""Outbound HTTP for web_search / web_fetch (client, body caps, logging)."""
from __future__ import annotations
import asyncio
import socket
from collections.abc import AsyncIterator

View file

@ -1,7 +1,5 @@
"""HTML parsing for web_search / web_fetch."""
from __future__ import annotations
import html
import re
from html.parser import HTMLParser

View file

@ -1,7 +1,5 @@
"""Detect forced Anthropic web server tool requests."""
from __future__ import annotations
from api.models.anthropic import MessagesRequest, Tool

View file

@ -1,7 +1,5 @@
"""SSE streaming for local web_search / web_fetch server tool results."""
from __future__ import annotations
import uuid
from collections.abc import AsyncIterator
from datetime import UTC, datetime

View file

@ -1,7 +1,5 @@
"""Shared Claude Code environment policy for FCC client surfaces."""
from __future__ import annotations
CLAUDE_CODE_AUTO_COMPACT_WINDOW = "190000"
CLAUDE_BINARY_NAME = "claude"
CLAUDE_NO_AUTH_SENTINEL = "fcc-no-auth"

View file

@ -1,7 +1,5 @@
"""CLI entry points for the installed package."""
from __future__ import annotations
import os
import shutil
import threading

View file

@ -1,7 +1,5 @@
"""Installed `fcc-claude` launcher."""
from __future__ import annotations
import os
import sys
from collections.abc import Mapping, Sequence

View file

@ -1,7 +1,5 @@
"""Installed `fcc-codex` launcher."""
from __future__ import annotations
import json
import os
import sys

View file

@ -1,7 +1,5 @@
"""Build Codex model catalogs from the FCC model-list route."""
from __future__ import annotations
import json
import uuid
from collections.abc import Mapping

View file

@ -1,7 +1,5 @@
"""Shared process helpers for installed client CLI launchers."""
from __future__ import annotations
import shutil
import subprocess
import sys

View file

@ -1,7 +1,5 @@
"""Managed Claude Code task command, environment, and stdout parsing."""
from __future__ import annotations
import json
from collections.abc import Iterable, Mapping
from dataclasses import dataclass, field

View file

@ -1,7 +1,5 @@
"""Managed Claude Code diagnostic classification."""
from __future__ import annotations
from dataclasses import dataclass
_BENIGN_STDERR_MARKERS = ("claude.ai connectors are disabled",)

View file

@ -5,8 +5,6 @@ FastAPI lifespan cleanup doesn't run to completion. We only track processes we
spawn so we don't accidentally kill unrelated system processes.
"""
from __future__ import annotations
import atexit
import os
import signal

View file

@ -1,7 +1,5 @@
"""Dotenv file discovery and explicit dotenv override helpers."""
from __future__ import annotations
import os
from collections.abc import Mapping
from pathlib import Path

View file

@ -1,7 +1,5 @@
"""Canonical env template loading for init and Admin UI defaults."""
from __future__ import annotations
import importlib.resources
from pathlib import Path

View file

@ -1,7 +1,5 @@
"""Provider-prefixed model reference helpers."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Protocol

View file

@ -4,8 +4,6 @@ Adapter factories live in :mod:`providers.runtime.factory`; this module stays fr
provider implementation imports (see contract tests).
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Literal

View file

@ -1,7 +1,5 @@
"""Canonical provider id tuple (re-exported from the provider catalog)."""
from __future__ import annotations
from .provider_catalog import SUPPORTED_PROVIDER_IDS
__all__ = ("SUPPORTED_PROVIDER_IDS",)

View file

@ -3,8 +3,6 @@
Provider adapters supply policy via parameters (defaults, OpenRouter post-steps).
"""
from __future__ import annotations
from collections.abc import Sequence
from typing import Any

View file

@ -4,8 +4,6 @@ Used by :class:`OpenRouterProvider` and line-mode
:class:`providers.transports.anthropic_messages.AnthropicMessagesTransport` providers.
"""
from __future__ import annotations
import copy
import json
from dataclasses import dataclass, field

View file

@ -1,7 +1,5 @@
"""Canonical Anthropic-style SSE sequence for provider-side streaming errors."""
from __future__ import annotations
import uuid
from collections.abc import Iterator
from typing import Any

View file

@ -1,7 +1,5 @@
"""Shared Anthropic request serialization helpers."""
from __future__ import annotations
import json
from typing import Any

View file

@ -3,8 +3,6 @@
Shared by :mod:`api.web_tools` and stream contract tests to avoid drift.
"""
from __future__ import annotations
from typing import Final
SERVER_TOOL_USE: Final = "server_tool_use"

View file

@ -7,8 +7,6 @@ back the same shape the real Anthropic API returns for a non-streaming
``messages.create()`` call.
"""
from __future__ import annotations
import json
import uuid
from collections.abc import AsyncIterator

View file

@ -3,8 +3,6 @@
Used by default CI contract tests and by opt-in live smoke scenarios.
"""
from __future__ import annotations
import json
from collections.abc import Iterable
from dataclasses import dataclass

View file

@ -1,7 +1,5 @@
"""Anthropic SSE serialization helpers."""
from __future__ import annotations
import json
from typing import Any

View file

@ -1,7 +1,5 @@
"""Anthropic stream state ledger."""
from __future__ import annotations
import hashlib
import json
import uuid

View file

@ -1,7 +1,5 @@
"""Shared retry and recovery policy for Anthropic streams."""
from __future__ import annotations
import json
import time
from collections.abc import Callable

View file

@ -1,7 +1,5 @@
"""Provider-neutral transient upstream error classification."""
from __future__ import annotations
import json
from collections.abc import Mapping
from contextlib import suppress

View file

@ -1,7 +1,5 @@
"""Facade for OpenAI Responses protocol adaptation."""
from __future__ import annotations
from collections.abc import AsyncIterable, AsyncIterator, Mapping
from typing import Any, ClassVar

View file

@ -1,7 +1,5 @@
"""Anthropic SSE parsing used by the Responses stream adapter."""
from __future__ import annotations
import json
from collections.abc import AsyncIterable, AsyncIterator
from dataclasses import dataclass

View file

@ -1,7 +1,5 @@
"""Errors and error envelopes for OpenAI Responses compatibility."""
from __future__ import annotations
from typing import Any

View file

@ -1,7 +1,5 @@
"""OpenAI Responses SSE event formatting."""
from __future__ import annotations
import json
from collections.abc import Mapping
from typing import Any

View file

@ -1,7 +1,5 @@
"""Identifier helpers for OpenAI Responses payloads."""
from __future__ import annotations
import uuid

View file

@ -1,7 +1,5 @@
"""Convert OpenAI Responses requests into Anthropic Messages payloads."""
from __future__ import annotations
from collections.abc import Mapping
from typing import Any

View file

@ -1,7 +1,5 @@
"""Responses object and output item builders."""
from __future__ import annotations
from typing import Any

View file

@ -1,7 +1,5 @@
"""Reasoning and thinking conversion helpers for OpenAI Responses."""
from __future__ import annotations
from collections.abc import Mapping
from typing import Any

View file

@ -1,7 +1,5 @@
"""Translate Anthropic SSE streams into OpenAI Responses SSE streams."""
from __future__ import annotations
from collections.abc import AsyncIterable, AsyncIterator, Mapping
from typing import Any

View file

@ -1,7 +1,5 @@
"""Anthropic SSE to OpenAI Responses stream assembly."""
from __future__ import annotations
import json
import time
import uuid

View file

@ -1,7 +1,5 @@
"""Block state for OpenAI Responses streaming assembly."""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Literal

View file

@ -1,7 +1,5 @@
"""Block finalization for OpenAI Responses streams."""
from __future__ import annotations
from collections.abc import Callable
from ..errors import ResponsesConversionError

View file

@ -1,7 +1,5 @@
"""Responses stream error mapping."""
from __future__ import annotations
from collections.abc import Mapping
from typing import Any

View file

@ -1,7 +1,5 @@
"""OpenAI Responses SSE event builders."""
from __future__ import annotations
from typing import Any
from ..events import format_response_sse_event

View file

@ -1,7 +1,5 @@
"""Output ledger for OpenAI Responses streaming assembly."""
from __future__ import annotations
from collections.abc import Mapping
from typing import Any

View file

@ -1,7 +1,5 @@
"""Tool conversion helpers for the OpenAI Responses adapter."""
from __future__ import annotations
import hashlib
import json
import re

View file

@ -1,7 +1,5 @@
"""Usage helpers for OpenAI Responses payloads."""
from __future__ import annotations
from typing import Protocol
_DISALLOWED_SPECIAL: tuple[str, ...] = ()

View file

@ -1,7 +1,5 @@
"""Shared strict sliding-window rate limiting primitives."""
from __future__ import annotations
import asyncio
import time
from collections import deque

View file

@ -5,8 +5,6 @@ Conversation and Claude Code prompts are logged verbatim unless values live unde
sanitized credential keys (e.g. ``api_key``, ``authorization``).
"""
from __future__ import annotations
import asyncio
from collections.abc import AsyncGenerator, AsyncIterator, Mapping
from typing import Any

View file

@ -1,7 +1,5 @@
"""Typed dependency surface for messaging slash commands."""
from __future__ import annotations
from typing import Protocol
from .managed_protocols import ManagedClaudeSessionManagerProtocol

View file

@ -1,7 +1,5 @@
"""Command parsing and dispatch for messaging handlers."""
from __future__ import annotations
from .command_context import MessagingCommandContext
from .commands import handle_clear_command, handle_stats_command, handle_stop_command
from .models import IncomingMessage

View file

@ -3,16 +3,10 @@
Commands depend on MessagingCommandContext instead of the concrete workflow.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
from loguru import logger
from .command_context import MessagingCommandContext
if TYPE_CHECKING:
from messaging.models import IncomingMessage
from .models import IncomingMessage
async def handle_stop_command(

View file

@ -1,7 +1,5 @@
"""Protocols for messaging-owned managed Claude sessions."""
from __future__ import annotations
from collections.abc import AsyncGenerator
from typing import Any, Protocol, runtime_checkable

View file

@ -1,7 +1,5 @@
"""CLI event handling for a single queued node (transcript + session + errors)."""
from __future__ import annotations
from collections.abc import Awaitable, Callable
from typing import Any

View file

@ -1,7 +1,5 @@
"""Run queued messaging nodes through a managed CLI session."""
from __future__ import annotations
import asyncio
from collections.abc import Callable

View file

@ -1,7 +1,5 @@
"""Discord messaging runtime."""
from __future__ import annotations
import asyncio
import contextlib
from collections.abc import Awaitable, Callable

View file

@ -1,7 +1,5 @@
"""Discord inbound event normalization."""
from __future__ import annotations
from typing import Any
from loguru import logger

View file

@ -1,7 +1,5 @@
"""Discord outbound delivery."""
from __future__ import annotations
from collections.abc import Awaitable, Callable
from typing import Any, cast

View file

@ -1,7 +1,5 @@
"""Messaging platform component factory."""
from __future__ import annotations
from dataclasses import dataclass
from loguru import logger

View file

@ -1,7 +1,5 @@
"""Shared queued delivery helper for messaging platforms."""
from __future__ import annotations
import asyncio
from collections.abc import Awaitable, Callable
from typing import Any, cast

View file

@ -1,7 +1,5 @@
"""Messaging platform ports used by the customer-facing workflow."""
from __future__ import annotations
from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from typing import Any, Protocol, runtime_checkable

View file

@ -1,12 +1,10 @@
"""Telegram messaging runtime."""
from __future__ import annotations
import asyncio
import contextlib
import os
from collections.abc import Awaitable, Callable
from typing import TYPE_CHECKING, Any
from typing import Any
# Opt-in to future behavior for python-telegram-bot (retry_after as timedelta).
os.environ["PTB_TIMEDELTA"] = "1"
@ -25,11 +23,8 @@ from .telegram_inbound import (
from .telegram_io import TelegramMessenger
from .voice_flow import VoiceNoteFlow
if TYPE_CHECKING:
from telegram import Update
from telegram.ext import ContextTypes
try:
from telegram import Update
from telegram.ext import (
Application,
CommandHandler,

View file

@ -1,19 +1,13 @@
"""Telegram inbound event normalization."""
from __future__ import annotations
from typing import TYPE_CHECKING
from loguru import logger
from telegram import Update
from telegram.ext import ContextTypes
from ..models import IncomingMessage
from ..rendering.telegram_markdown import format_status
from .voice_flow import VoiceNoteRequest, audio_suffix_from_metadata
if TYPE_CHECKING:
from telegram import Update
from telegram.ext import ContextTypes
def telegram_text_message_from_update(
update: Update,

View file

@ -1,7 +1,5 @@
"""Telegram outbound delivery."""
from __future__ import annotations
import asyncio
from collections.abc import Awaitable, Callable
from datetime import timedelta

View file

@ -1,7 +1,5 @@
"""Shared voice-note flow for messaging platform adapters."""
from __future__ import annotations
import contextlib
import tempfile
from collections.abc import Awaitable, Callable

View file

@ -1,7 +1,5 @@
"""Shared Markdown table pre-normalization for platform renderers."""
from __future__ import annotations
import re
_TABLE_SEP_RE = re.compile(r"^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?\s*$")

View file

@ -1,7 +1,5 @@
"""Platform rendering profiles for messaging transcripts and status text."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass

View file

@ -1,7 +1,5 @@
"""Helpers for redacting user-derived content from log lines."""
from __future__ import annotations
def format_exception_for_log(exc: BaseException, *, log_full_message: bool) -> str:
"""Return exception type and optionally ``str(exc)`` for operator diagnostics."""

View file

@ -1,7 +1,5 @@
"""Per-chat message ID log used by messaging clear commands."""
from __future__ import annotations
from datetime import UTC, datetime
from typing import Any

View file

@ -1,7 +1,5 @@
"""Atomic JSON persistence for messaging session state."""
from __future__ import annotations
import contextlib
import json
import os

View file

@ -1,7 +1,5 @@
"""Persistent messaging conversation state store."""
from __future__ import annotations
import threading
from loguru import logger

View file

@ -1,7 +1,5 @@
"""Transcript event application and open-block tracking."""
from __future__ import annotations
from typing import Any
from .context import RenderCtx

View file

@ -1,7 +1,5 @@
"""Rendering context used by transcript segments."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass

View file

@ -1,7 +1,5 @@
"""Render and truncate ordered transcript segments."""
from __future__ import annotations
from collections import deque
from collections.abc import Iterable

View file

@ -1,7 +1,5 @@
"""Transcript segment types for messaging UI output."""
from __future__ import annotations
import json
from abc import ABC, abstractmethod
from dataclasses import dataclass, field

Some files were not shown because too many files have changed in this diff Show more