From 4d5fb006ad4862be5ef58ab7a07a180f866eaea1 Mon Sep 17 00:00:00 2001 From: Bret Mogilefsky Date: Fri, 30 Oct 2026 16:05:19 -0700 Subject: [PATCH 1/3] feat(kits): add Claude Code gateway kit and shared CI --- .github/claude-code-pr-draft.md | 65 + .github/workflows/ci.yml | 126 +- .gitignore | 5 + Makefile | 35 + README.md | 31 + claude-code/NOTICE | 11 + claude-code/README.md | 255 ++ claude-code/TROUBLESHOOTING.md | 61 + .../decisions/0001-session-local-litellm.md | 101 + claude-code/docs/verification.md | 148 ++ claude-code/files/home/.local/bin/claude | 4 + claude-code/files/home/claude-code/install.py | 137 + claude-code/files/home/claude-code/launch.py | 186 ++ claude-code/files/home/claude-code/models.py | 76 + .../files/home/claude-code/provider.py | 135 + claude-code/files/home/claude-code/proxy.py | 163 ++ .../files/home/claude-code/requirements.in | 6 + .../files/home/claude-code/requirements.lock | 2346 +++++++++++++++++ claude-code/files/home/claude-code/stream.py | 63 + claude-code/scripts/test | 52 + claude-code/scripts/verify | 36 + claude-code/spec.yaml | 69 + claude-code/tests/requirements.in | 2 + claude-code/tests/requirements.lock | 26 + claude-code/tests/test_claude_code.py | 385 +++ claude-code/tests/test_lifecycle.py | 235 ++ pyproject.toml | 18 + requirements-dev.in | 6 + requirements-dev.lock | 159 ++ scripts/run-kit-tests.py | 64 + scripts/tests/test_tooling.py | 227 ++ scripts/validate-kits.py | 149 ++ 32 files changed, 5311 insertions(+), 71 deletions(-) create mode 100644 .github/claude-code-pr-draft.md create mode 100644 Makefile create mode 100644 claude-code/NOTICE create mode 100644 claude-code/README.md create mode 100644 claude-code/TROUBLESHOOTING.md create mode 100644 claude-code/docs/decisions/0001-session-local-litellm.md create mode 100644 claude-code/docs/verification.md create mode 100644 claude-code/files/home/.local/bin/claude create mode 100644 claude-code/files/home/claude-code/install.py create mode 100644 claude-code/files/home/claude-code/launch.py create mode 100644 claude-code/files/home/claude-code/models.py create mode 100644 claude-code/files/home/claude-code/provider.py create mode 100644 claude-code/files/home/claude-code/proxy.py create mode 100644 claude-code/files/home/claude-code/requirements.in create mode 100644 claude-code/files/home/claude-code/requirements.lock create mode 100644 claude-code/files/home/claude-code/stream.py create mode 100644 claude-code/scripts/test create mode 100644 claude-code/scripts/verify create mode 100644 claude-code/spec.yaml create mode 100644 claude-code/tests/requirements.in create mode 100644 claude-code/tests/requirements.lock create mode 100644 claude-code/tests/test_claude_code.py create mode 100644 claude-code/tests/test_lifecycle.py create mode 100644 pyproject.toml create mode 100644 requirements-dev.in create mode 100644 requirements-dev.lock create mode 100644 scripts/run-kit-tests.py create mode 100644 scripts/tests/test_tooling.py create mode 100644 scripts/validate-kits.py diff --git a/.github/claude-code-pr-draft.md b/.github/claude-code-pr-draft.md new file mode 100644 index 0000000..99ade26 --- /dev/null +++ b/.github/claude-code-pr-draft.md @@ -0,0 +1,65 @@ +## Summary + +Add an experimental `claude-code` agent kit that runs Claude inside an acq +microVM using a configured OpenAI-shaped model provider, including USAi. + +- Pinned SHA-256-verified Claude native binaries for Linux x64 and ARM64. +- Private authenticated, session-local LiteLLM bridge from Anthropic Messages + to OpenAI Chat Completions, with hash-locked wheel-only dependencies. +- Unprivileged installation, including pip bootstrap for guests without ensurepip. +- Claude-owned model catalog and explicit canonical-name substitutions; no + separate Paseo catalog projection or global user-config rewrite. +- Host TUI access and optional browser access through the separate Paseo kit. +- README warning: browser picker lists more choices than the configured + OpenAI-shaped model provider supports; tracked at getpaseo/paseo#8321. + +Also consolidate repository CI into a four-kit matrix plus a Claude Python 3.12 +lane, reusing pinned upstream Patterns validators rather than importing the +Patterns skill/index toolchain. Shared checks cover lint/format, ShellCheck, +contracts, local doc links and executable modes, tests, dependency audits, +unsafe-shell patterns, and secrets. CI uses read-only permissions, SHA-pinned +actions and checksum-pinned Gitleaks; no model credentials or VM execution. + +## Verification + +- Local `make check` passed with the pinned Patterns checkout and verified + Gitleaks executable; all four kits validated and the provider bundle validated. +- Claude offline suite: 27 passed / 3 explicitly gated live skips. +- Actual relocated Claude live/unit/lifecycle suite: 30 passed, with four + upstream Pydantic deprecation warnings. +- Actual CLI text, file tool/result continuation and real SDK canonical + Sonnet 5.5 model switch were exercised through USAi. +- Operator observed ARM64 MSB 0.7.7 installation, provider-root presence, + browser access, and Sonnet 5/5.5 calls from the acq Quickstart checkout. +- Independent adversarial review performed; reproducibility findings addressed. + +GitHub Actions execution and local Python 3.12 execution remain unverified in +this session. Native x64 execution, backend mount enforcement, actual browser +permission/disconnect paths, and enterprise CA-specific validation remain live +gates. Offline x64 CI does not prove the native x64 Claude executable works. +See `claude-code/docs/verification.md` for history and limitations. + +## Security and licensing + +No credentials are stored in the kit, generated model settings, or CI. +Model routing comes from acq's backend-owned provider input; the proxy never +accepts client-supplied provider routing. Claude child environments have projected +provider credentials stripped, but this is defense in depth, not same-user +process isolation. The kit publishes no model API port and enables no permission +bypass. Optional Paseo browser exposure retains its separate trust boundary. + +Kit provenance from the local CC0 Patterns worktree is recorded in `NOTICE`; +distribution uses this repository's MIT license. Claude Code remains proprietary, +and downloaded dependencies retain their own licenses. + +## Rollback + +Remove the kit reference and recreate the disposable test sandbox without it. +Existing Claude user settings and transcripts are not overwritten. Revert the +repository change to restore the former CI layout if needed. + +## AI assistance + +Implementation, tests, documentation, and independent reviews were AI-assisted. +The human operator performed the reported macOS/MSB/browser checks. Human review +is required before production use. No compliance or ATO assertion is made. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b24aa9f..ad93e01 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,89 +9,73 @@ permissions: contents: read jobs: - test-and-validate: + kits: runs-on: ubuntu-latest + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + kit: [opencode-go-provider, pi-coding-agent, first-mate-skill, claude-code] + python: ["3.14"] + include: + - kit: claude-code + python: "3.12" steps: - - name: Check out this repository - uses: actions/checkout@v4 - + - name: Check out repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: ${{ matrix.python }} - name: Set up Node.js - uses: actions/setup-node@v4 + if: matrix.kit == 'opencode-go-provider' || matrix.kit == 'pi-coding-agent' + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "22" + - name: Run kit's offline tests + env: + KIT: ${{ matrix.kit }} + run: python scripts/run-kit-tests.py "$KIT" --install - - name: Install kit test dependencies - working-directory: opencode-go-provider - run: npm ci - - - name: Run kit tests - working-directory: opencode-go-provider - run: npm test - - - name: Install pi agent-kit test dependencies - working-directory: pi-coding-agent - run: npm ci - - - name: Run pi agent-kit tests - working-directory: pi-coding-agent - run: npm test - - - name: Run pi agent-kit offline verification - run: bash pi-coding-agent/scripts/verify - - - name: Run first-mate skill-kit offline verification - run: bash first-mate-skill/scripts/verify - - - name: Set up Python - uses: actions/setup-python@v5 + shared: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Check out repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: - python-version: "3.12" - - - name: Install validator dependencies - run: python -m pip install --disable-pip-version-check jsonschema==4.26.0 PyYAML==6.0.3 - - - name: Check out the pinned patterns release - uses: actions/checkout@v4 + persist-credentials: false + fetch-depth: 0 + - name: Check out pinned Patterns validators + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: GSA-TTS/agentic-coding-patterns - # Pinned to the release this kit was authored and validated against. - # Update deliberately together with the validator. ref: a290d5d80737fc739e7ec139da0eeaf438631631 path: .patterns - - - name: Validate agent-kit and skill-kit specs with the patterns validator (when present) - shell: bash + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: "3.14" + - name: Install hash-locked shared tools run: | - set -euo pipefail - validator=".patterns/integrations/isolation/acq-kits/validate-kits.py" - schema=".patterns/schemas/kit-hybrid-v1.schema.json" - if [ ! -f "$validator" ] || [ ! -f "$schema" ]; then - echo "Pinned patterns checkout predates the neutral kit validator;" - echo "the vendored kit-hybrid-v1 schema test in npm test is authoritative." - exit 0 - fi - work="$(mktemp -d)" - mkdir -p "$work/schemas" "$work/integrations/isolation/acq-kits" - cp "$schema" "$work/schemas/" - printf 'schemaVersion: "acq-kits-registry/v1"\nkits:\n' \ - > "$work/integrations/isolation/acq-kits/kits.yaml" - for name in pi-coding-agent first-mate-skill; do - kit="$work/integrations/isolation/acq-kits/$name" - mkdir -p "$kit" - cp "$name/spec.yaml" "$name/README.md" "$kit/" - cp -R "$name/files" "$kit/files" - printf ' %s:\n backends: [sbx, msb]\n parity: CI validation entry.\n' "$name" \ - >> "$work/integrations/isolation/acq-kits/kits.yaml" - done - python "$validator" --root "$work" --strict - - - name: Validate provider input with a patched credential binding + python -m venv .tmp/ci-venv + .tmp/ci-venv/bin/python -m pip install --disable-pip-version-check --require-hashes --only-binary=:all: -r requirements-dev.lock + - name: Lint, format, infrastructure tests, and all kit contracts + run: | + make lint validate + .tmp/ci-venv/bin/python -m pytest scripts/tests -q + - name: Install checksum-pinned Gitleaks (no action token or license) shell: bash run: | set -euo pipefail - mkdir -p .tmp - python -c 'import json; source = ".patterns/integrations/isolation/schemas/provider-credential-bindings.json"; bindings = json.load(open(source, encoding="utf-8")); bindings["providers"]["opencode-go"] = "OPENCODE_GO_API_KEY"; json.dump(bindings, open(".tmp/provider-credential-bindings.json", "w", encoding="utf-8"), indent=2)' - python .patterns/scripts/validate_provider_input_contract.py \ - --schema-dir .patterns/integrations/isolation/schemas \ - --credential-bindings .tmp/provider-credential-bindings.json \ - --bundle opencode-go-provider/provider-input.json + mkdir -p .tmp/gitleaks + curl --fail --silent --show-error --location --proto '=https' --tlsv1.2 --max-time 120 \ + https://github.com/gitleaks/gitleaks/releases/download/v8.24.3/gitleaks_8.24.3_linux_x64.tar.gz \ + -o .tmp/gitleaks/archive.tar.gz + echo '9991e0b2903da4c8f6122b5c3186448b927a5da4deef1fe45271c3793f4ee29c .tmp/gitleaks/archive.tar.gz' | sha256sum --check + tar -xzf .tmp/gitleaks/archive.tar.gz -C .tmp/gitleaks gitleaks + - name: Dependency audit, unsafe shell, and secrets scans + run: make security GITLEAKS="$PWD/.tmp/gitleaks/gitleaks" diff --git a/.gitignore b/.gitignore index 06b86ce..af08881 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,11 @@ tests/output/ .patterns/ .tmp/ +# Python validation artifacts +__pycache__/ +.pytest_cache/ +.ruff_cache/ + # OS noise .DS_Store Thumbs.db diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..06d04ec --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +PYTHON ?= python3 +VENV ?= .tmp/ci-venv +PY := $(VENV)/bin/python +PATTERNS ?= .patterns +LINT_PATHS := scripts/validate-kits.py scripts/run-kit-tests.py scripts/tests claude-code/files claude-code/tests claude-code/scripts/test claude-code/scripts/verify +GITLEAKS ?= gitleaks + +.PHONY: setup check lint test validate security +setup: + @if command -v uv >/dev/null 2>&1; then uv venv --python $(PYTHON) --seed $(VENV); else $(PYTHON) -m venv $(VENV); fi + $(PY) -m pip install --disable-pip-version-check --require-hashes --only-binary=:all: -r requirements-dev.lock + npm --prefix opencode-go-provider ci --ignore-scripts --no-audit --no-fund + npm --prefix pi-coding-agent ci --ignore-scripts --no-audit --no-fund + +check: lint validate test security + +lint: + $(PY) -m ruff check $(LINT_PATHS) + $(PY) -m ruff format --check $(LINT_PATHS) + shellcheck claude-code/files/home/.local/bin/claude + +validate: + $(PY) scripts/validate-kits.py --patterns $(PATTERNS) + +test: + $(PY) -m pytest scripts/tests -q + $(PY) scripts/run-kit-tests.py all + +security: + $(PY) -m pip_audit --strict --require-hashes --disable-pip -r requirements-dev.lock + $(PY) -m pip_audit --strict --require-hashes --disable-pip -r claude-code/files/home/claude-code/requirements.lock + $(PY) $(PATTERNS)/scripts/scan_unsafe_shell.py claude-code + $(GITLEAKS) dir --redact --no-banner --log-level warn claude-code + $(GITLEAKS) dir --redact --no-banner --log-level warn scripts + $(GITLEAKS) git --redact --no-banner --log-level warn . diff --git a/README.md b/README.md index 1276430..dc1a872 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ An agent kit is a `hybrid/v1` mixin that: | Kit | Kind | Provides | Status | | --- | --- | --- | --- | +| [`claude-code/`](claude-code/) | Agent | Pinned Claude Code + private Messages-to-Chat-Completions proxy for a configured OpenAI-shaped model provider | **Experimental** — operator-verified on ARM64 MSB; x64 execution pending; browser model picker overstates availability | | [`opencode-go-provider/`](opencode-go-provider/) | Provider | OpenCode Go (`openai-compatible`) facts and a 19-model neutral catalog | **Preview** — blocked on the acq credential-binding addition | | [`pi-coding-agent/`](pi-coding-agent/) | Agent | Pinned pi CLI + `~/.pi/agent/models.json` renderer | **Preview** — live verification pending acq PR 611 | | [`first-mate-skill/`](first-mate-skill/) | Skill | The `paseo-first-mate` Agent Skill and two helper scripts, dropped into `~/.agents/skills` | Offline-verified; no live sandbox run | @@ -113,6 +114,11 @@ first-mate-skill/ skill kit New kits follow the same directory contract and get a row in the table above. +The Claude Code kit can compose with the separate Patterns Paseo kit for browser +access. It does not include Paseo or write Paseo's model catalog. Its README +explains the [upstream picker limitation](https://github.com/getpaseo/paseo/issues/8321) +and which displayed choices can actually run through the configured provider. + ## Using kits Provider input is materialized **at sandbox create time only**. `acq kit apply` @@ -163,6 +169,31 @@ reads the variable by name. ## Validating a kit +### Shared repository checks + +All root directories containing `spec.yaml` are discovered by shared tooling. +CI runs a matrix over the four kits rather than repeating install/test steps; +Claude also runs on Python 3.12 and 3.14. Tests never receive model credentials +and do not launch VMs. The pinned Patterns checkout supplies contract validation, +not runtime kit configuration. + +For local verification, prepare a checkout of Patterns at +`a290d5d80737fc739e7ec139da0eeaf438631631` in `.patterns` (or set the Make +variable `PATTERNS` to an existing checkout at that commit). Then run: + +```bash +make setup +make check +``` + +`make setup` creates an isolated development environment and installs locked +Python tools and existing Node kit dependencies. `make check` runs scoped lint, +formatting, ShellCheck, all-kit contract validation, local documentation-link +and normalizer-mode checks, each kit's offline tests, dependency audits, +unsafe-shell checks, and secret scans. A missing validator or wrong +Patterns pin fails closed. Gitleaks, ShellCheck, and Node must be available; see the Makefile +for paths and overrides. Opt-in live Claude tests are separate from this command. + Provider kits are validated with the host-time contract validator from `agentic-coding-patterns`: diff --git a/claude-code/NOTICE b/claude-code/NOTICE new file mode 100644 index 0000000..6765a0b --- /dev/null +++ b/claude-code/NOTICE @@ -0,0 +1,11 @@ +Claude Code kit provenance + +This kit was initially developed with AI assistance in a local worktree of +GSA-TTS/agentic-coding-patterns, whose repository dedication is CC0-1.0. +It is distributed here under the repository's MIT license. No proprietary +Claude executable or third-party package source is vendored in this kit. + +Claude Code is downloaded at installation time from Anthropic's distribution +and remains governed by Anthropic's terms. LiteLLM and other downloaded runtime +dependencies retain their respective licenses; the repository license does +not relicense those dependencies. diff --git a/claude-code/README.md b/claude-code/README.md new file mode 100644 index 0000000..5b855d9 --- /dev/null +++ b/claude-code/README.md @@ -0,0 +1,255 @@ +--- +title: "Claude Code acq Agent Kit" +description: "Terminal Claude Code in an acq sandbox using an OpenAI-compatible provider." +status: draft +tier: 2 +last_updated: "2026-10-30" +--- + +# Claude Code (acq agent kit) + +Run Claude Code **inside** an acq-managed microVM, using USAi's Claude models +through its **OpenAI Chat Completions** endpoint. The terminal runs in the +guest; your host terminal supplies the keyboard and display. No desktop app, +Anthropic login, or graphical display server is needed. + +```text +Host terminal → acq guest terminal → claude wrapper → Claude Code + │ │ Messages + SSE + └── private LiteLLM bridge + │ HTTPS Chat Completions + └── USAi / another gateway +``` + +Experimental integration; human review is required before production use. +See [the architecture decision](docs/decisions/0001-session-local-litellm.md). + +## Requirements + +- A released acq with neutral `hybrid/v1` kit support, terminal access, and + [authoritative provider-input materialization](https://github.com/GSA-TTS/agentic-coding-patterns/blob/main/integrations/isolation/docs/provider-input-contract.md). +- A **glibc Linux x64 or ARM64** guest with Python **3.12–3.14**, stdlib `venv`, + system CA certificates, and `~/.local/bin` on the non-interactive PATH. +- A provider kit, such as [`usai-provider`](https://github.com/GSA-TTS/agentic-coding-patterns/tree/main/integrations/isolation/acq-kits/usai-provider), that supplies + `facts.json`, `snapshot.json`, and provider egress. Credentials are injected + through acq's backend secret mechanism, never through `spec.yaml`. +- Sufficient disk/memory: the Claude binary is approximately 300 MB, plus the + Python bridge and its dependencies. No Node runtime is needed by this kit. + +The `agent.name` token is **`claude`**, while this directory is `claude-code`. +That matches Claude's executable and the existing harness readiness declaration. +This does not add a new built-in kit mapping to acq itself. Explicitly apply the +kit if your acq release does not map the `claude` token to this directory. + +## Apply and reach the TUI from the host + +Select the Claude kit and your provider kit through acq's extra-kit mechanism. +For a local checkout (substitute your absolute checkout path): + +```bash +acq --backend msb run shell /path/to/workspace --kit /path/to/agentic-coding-kits/claude-code +``` + +This uses a shell launch target; invoke `claude` inside the attached guest shell. +It avoids assuming this externally distributed kit has an acq built-in mapping. +For a GitHub-distributed kit, authorize `github.com/mogul/` through +`ACQ_EXTRA_KIT_SOURCES` and use a full commit SHA: + +```bash +ACQ_EXTRA_KIT_SOURCES="github.com/mogul/" acq --backend msb run shell /path/to/workspace --kit 'git+https://github.com/mogul/agentic-coding-kits.git#ref=&dir=claude-code' +``` + +This assumes your acq configuration already selects `usai-provider` and injects +its credential. Follow the provider kit's setup instructions. Inspect your +release's `acq run --help` for kit selection if its interface differs. The +startup install is awaited, but the launcher also checks provider readiness at +each invocation: a missing projection fails, it never uses stale global config. + +For an existing sandbox, use its acq interactive terminal/exec interface to run +`claude`. Do not run the host's own Claude executable against a forwarded model +port: that would execute tools on the host rather than inside the microVM. + +## Provider and model selection + +The launcher reads `$ACQ_PROVIDER_INPUT_ROOT/models/providers/`. +One provider is selected automatically; zero or several require an explicit +`ACQ_CLAUDE_PROVIDER`. No backend paths or credential values are hardcoded. + +| Non-secret guest variable | Meaning | +|---|---| +| `ACQ_CLAUDE_PROVIDER` | Selected provider directory ID, for example `usai` | +| `ACQ_CLAUDE_MODEL` | Main and Sonnet-alias model ID | +| `ACQ_CLAUDE_SMALL_MODEL` | Haiku-alias model ID | +| `ACQ_CLAUDE_OPUS_MODEL` | Opus-alias model ID; otherwise the main model | + +Provider recommendations supply `primary` and `small` when overrides are absent. +A single-model catalog needs no recommendation; otherwise choose a main model. +For example, USAi's snapshot recommends `claude-sonnet-5` and +`claude_4_5_haiku`. An Opus choice can be supplied explicitly. Every choice must +exist in the selected snapshot. `/model` or `--model` can select another model +from that same provider; the proxy rejects unknown IDs. Other OpenAI-shaped +providers work through the same contract, but must support **Chat Completions, +streaming, and function tools**. Model-specific capabilities require testing. + +## Browser/port access from outside the VM + +For a browser UI, compose this kit with the existing [`paseo`](https://github.com/GSA-TTS/agentic-coding-patterns/tree/main/integrations/isolation/acq-kits/paseo) kit. +Paseo launches the guest's `claude` executable; that is this kit's wrapper, so +each UI-launched session gets the same provider routing. Select Claude as the +agent in Paseo. Use `acq ports ` to find the **host-loopback** mapping +for guest **6767**, then open that address in your host browser. + +Paseo supplies `publishedPorts` and binds the **guest network interface**, which +MSB's publisher needs; a guest-loopback-only UI would not be reachable via that +publisher. This kit deliberately publishes **no** model-proxy port. Its random +port is authenticated and loopback-only. Port forwarding the proxy provides an +API, not a Claude UI or remote guest tool execution. + +The existing Paseo kit is unauthenticated and intended for a trusted single-user +host. Do not expose its port to a LAN or the Internet. Remote-machine browser +access needs an authenticated, approved access layer; it is not provided here. +Claude's cloud Remote Control is not a local browser server and is not enabled. +Browser access and Sonnet 5/5.5 model calls were confirmed by the operator on +MSB 0.7.7 with the tested acq checkout. This does not establish every browser +feature or model is supported; see the verification record. + +### Known limitation: the browser lists more models than are available + +Paseo 0.13.0 and the examined 0.14.0 source retain native Claude model choices +even when Claude advertises a restricted gateway catalog. **Fewer models are +actually available than the browser picker shows.** Availability is determined +by the **configured OpenAI-shaped model provider**, not by the displayed list. +Only provider model IDs and the kit's explicitly supported equivalent names can +be used; other choices fail rather than silently selecting a different model. +Extended-context variants are not implied supported by a matching base model. + +Tracked upstream: [getpaseo/paseo#8321](https://github.com/getpaseo/paseo/issues/8321). +The Claude kit supplies the restricted SDK catalog and verified substitutions; +the Paseo kit remains a browser-access component, not a second catalog projector. + +### Claude-owned model catalog + +The default Claude picker can show first-party aliases or dated +Anthropic IDs that are absent from USAi. The proxy rejects those IDs; matching +display names are not a routing contract. The wrapper reads the snapshot on each +launch and supplies temporary Claude settings: `availableModels`, +`enforceAvailableModels`, and `modelPicker` with `replaceBuiltInOptions: true`. +The picker contains exact gateway IDs, and Default resolves to the chosen primary +model. This changes the actual Claude SDK `supportedModels()` response, verified +with the pinned CLI, rather than projecting a second catalog into Paseo config. + +No global Claude settings or Paseo settings are rewritten. Existing explicit SDK +`--settings` are composed so hooks and permissions survive; only model catalog +fields are owned by this kit. CLI `--model` still selects an exact gateway ID. +An explicit `modelOverrides` map translates a small set of same-version canonical +Claude names, such as `claude-sonnet-5-5` to `claude-sonnet-5.5`, only when the +target exists in the snapshot and the source is not itself a gateway ID. No fuzzy +matching, extended-context suffix stripping, or unrelated-model substitution. +The real SDK model-switch probe confirms the mapped gateway ID on the wire. The proxy +continues enforcing exact snapshot membership independently of Claude settings. + +Paseo must refresh its Claude discovery after re-applying this kit; a daemon +restart interrupts guest sessions and should be scheduled by the operator. An +installed Paseo release may still merge a curated fallback catalog; the actual +browser list must be checked, not assumed from SDK discovery alone. Non-Anthropic +IDs in the snapshot are listed too, but their behavior is not implied validated. + +## Installation and lifecycle + +- Claude Code **2.1.314**: direct npm **platform tarball**, with independent + SHA-256 pins for x64 and ARM64. Only the regular `package/claude` member is + extracted after verification; no upstream install script is executed. +- LiteLLM **1.100.4** library, MCP import dependency, FastAPI and Uvicorn: + an exact, universal, hash-locked wheel-only dependency set. No LiteLLM + management UI, database, full proxy service, plugins, or callbacks. +- pip **26.2.2** is bootstrapped from a SHA-256-verified universal wheel into a + `venv --without-pip`. No system pip, ensurepip package, sudo, or remote bootstrap + script is needed. This works with the lean Ubuntu guest's split Python packaging. +- Startup installs as the **unprivileged agent**, in + `~/.local/share/acq/claude-code`. The version/lock stamp avoids repeated + downloads. Failed installation is visible and no readiness stamp is written. +- Every session binds its own ephemeral loopback socket before spawning the + proxy, waits for server readiness, then starts Claude. Exit terminates only + that proxy child. No PID files, global process kills, shared port, or daemon. + SIGTERM/SIGHUP cleanup also terminates the invocation's Claude process group + and tool descendants; foreground PTY ownership is handed to Claude and restored. +- User `~/.claude` and project settings are not overwritten. Automatic updates + and nonessential traffic are disabled in the child environment; no permission + bypass is enabled. User hooks/MCP configuration remain the operator's responsibility. + +## Security and compatibility limits + +The backend-owned read-only provider mount is the routing trust boundary. +The kit checks versions, identities, HTTPS hosts, duplicate keys/models, and +symlinked provider entries. It does not implement the backend's mount enforcement. +Provider keys exist only in the injected environment and proxy process memory; +the launcher removes the upstream key and `GITHUB_TOKEN` from Claude's child +environment. This is defense in depth, **not isolation from an agent with shell +access or sudo**. Do not treat same-user processes as a credential boundary. + +The facade accepts only Messages and token-count requests, with a per-session +random authentication token. Client-supplied API URLs, credentials, callbacks, +and provider choices do not reach LiteLLM. Upstream exception bodies and access +logs are suppressed to avoid logging prompts or keys. Provider egress belongs to +the provider kit; installation egress is limited to npm and PyPI hosts. TLS +verification stays enabled; use the CA kit for enterprise trust, never bypass it. + +USAi streaming tool chunks can repeat the same call ID on every argument fragment. +The kit normalizes those translated SSE blocks into one tool call so Claude sees +complete JSON arguments. Distinct IDs remain distinct calls. The live CLI file-read +test covers the resulting tool call and tool-result continuation. + +Supported: ordinary text, streaming text, function-tool calls and results. +Not promised: extended thinking, native server tools/search, prompt-cache +semantics, native compaction, PDF/image/audio behavior, or exact token counts. +Anthropic-only optional fields are not forwarded; thinking/beta/tool-search +features are disabled. The token-count route returns a deliberately conservative +UTF-8-byte estimate, **not Anthropic's tokenizer**. Context utilization may be +overestimated. Do not use the result for billing or capacity guarantees. + +Claude Code is **proprietary**, governed by Anthropic's terms, not this repo's +MIT license. Its npm installer is deprecated upstream; this kit deliberately +uses the still-published native platform artifacts to avoid executing remote +installer scripts. LiteLLM, FastAPI, Uvicorn, and MCP SDK licenses must be +reviewed with the locked dependency inventory. No upstream skill or prompt body +has been copied; these packages are dependencies, not vendored source. + +## Verification + +See the [verification record](docs/verification.md) for observed live results, +review findings addressed, and pending microVM/browser validation gates. + +```bash +make setup +make validate +make test +.tmp/ci-venv/bin/python claude-code/scripts/verify +``` + +The shared checks require a pinned Patterns checkout as described in the +repository README. `scripts/verify --acq /absolute/path/to/acq --sandbox ` +selects the tested host executable rather than an older Homebrew installation. + +`scripts/verify` runs offline checks and returns **3 (unverified)** until required +live checks are confirmed. Supply an existing, configured sandbox via +`--sandbox ` to probe the real wrapper's version and a small live Claude +prompt through `acq exec`. It never creates or deletes a VM. Failures return 1; +successful automated probes still return 3 pending manual interactive PTY +validation. See [troubleshooting](TROUBLESHOOTING.md). + +To refresh the bridge lock, use `uv pip compile requirements.in --python-version +3.12 --universal --generate-hashes --only-binary :all: --output-file +requirements.lock` from the payload directory. Audit and re-test after every +pin change. Claude hashes must be re-derived from both platform artifacts. + +The repository's kit test runner provisions the locked bridge and pytest in an isolated temporary +environment (Python venv/pip, or installed uv), including on clean CI workers. +It makes package-registry requests; it does not add global dependencies. + +## Backend parity + +SBX and MSB use the same neutral files, awaited unprivileged startup command, +agent declaration, and provider-input root. No backend shortcut or published +port is required for the TUI. Both must supply a PTY for interactive operation +and an authoritative read-only provider tree. MicroVM boot, interactive PTY, +and optional Paseo composition remain live-host verification requirements. diff --git a/claude-code/TROUBLESHOOTING.md b/claude-code/TROUBLESHOOTING.md new file mode 100644 index 0000000..43a14ef --- /dev/null +++ b/claude-code/TROUBLESHOOTING.md @@ -0,0 +1,61 @@ +--- +title: "Claude Code Kit Troubleshooting" +description: "Diagnose installation, routing, credentials, and host-access problems." +status: draft +tier: 2 +last_updated: "2026-10-30" +--- + +# Troubleshooting + +## Installation fails + +The guest needs glibc Linux x64/ARM64 and Python 3.12–3.14 with stdlib venv. +The kit seeds pip from a pinned, verified wheel; missing ensurepip is supported. +Missing wheels fail rather than compile remote source. Confirm npm/PyPI egress +and system CA trust; compose the CA kit for enterprise certificates. Never use +`--trusted-host`, disable TLS verification, or bypass a checksum failure. +The install does not use Node or an Anthropic download domain. + +## Claude says the kit is not ready + +Check that startup installation completed and `~/.local/bin` is on PATH. +Check that `ACQ_PROVIDER_INPUT_ROOT` points to acq's materialized read-only tree, +and the selected provider has `facts.json` and `snapshot.json`. Do not fabricate +an empty tree to suppress an error. If several providers exist, set +`ACQ_CLAUDE_PROVIDER` in the guest through a non-secret kit/environment setting. +Choose model IDs from the snapshot, not Anthropic's public API naming scheme. + +Confirm credential **presence**, never print its value. Use acq's approved +secret-injection path and check expiration/authorization. No Anthropic login is +needed. The proxy uses the provider's key, not a Claude subscription token. + +## Upstream request fails + +The bridge always targets `/chat/completions`, not `/responses` or +`/v1/messages` at USAi. Unknown model IDs fail locally. A 502 intentionally hides +upstream errors that might contain sensitive details. Check gateway availability, +credential status and acq egress diagnostics. Do not enable verbose proxy logs +or copy model prompts/credentials into an issue. + +Only ordinary function tools are supported. Server-side Anthropic tools are +rejected; optional thinking/beta/cache fields do not pass through. Validate +specific model capabilities before enabling richer inputs. The count estimate +is conservative and may make the context look fuller than it actually is. + +Claude may warn that a gateway deployment ID is an unrecognized model and use +default context metadata. This is distinct from a routing failure. Do not assume +the native model's context window or feature set from its USAi deployment name. + +## TUI or browser is unreachable + +Use a real interactive PTY through acq, not a host Claude process or a pipe. +For a browser, apply the separate Paseo kit and select Claude in its UI. +`acq ports ` shows the host mapping for guest 6767. The browser must +connect to that host-loopback address, not the microVM's loopback address. +Do not publish the model proxy: it is not a browser UI. + +Paseo's wrapper for OpenCode does not replace the `claude` wrapper. If Paseo +cannot discover Claude, inspect the daemon's non-interactive PATH and confirm +`~/.local/bin/claude` is executable. Browser composition requires live validation +on your sandbox-capable host; this repository's unit tests cannot prove it. diff --git a/claude-code/docs/decisions/0001-session-local-litellm.md b/claude-code/docs/decisions/0001-session-local-litellm.md new file mode 100644 index 0000000..35838d0 --- /dev/null +++ b/claude-code/docs/decisions/0001-session-local-litellm.md @@ -0,0 +1,101 @@ +--- +title: "Use a session-local LiteLLM bridge for Claude Code" +description: "Bridge Anthropic Messages to OpenAI Chat Completions without publishing a model gateway." +status: draft +tier: 2 +date: "2026-10-30" +last_updated: "2026-10-30" +decision_status: proposed +decision_makers: ["Repository maintainers"] +nist_controls: ["AC-6", "SC-7", "SC-8", "SI-10", "SR-3"] +impact_level: "Not assessed" +ato_relevance: "Not assessed" +risk_treatment: mitigate +--- + +# Use a session-local LiteLLM bridge for Claude Code + +## Context and problem statement + +Claude Code speaks Anthropic Messages. USAi exposes Claude models through +OpenAI-shaped endpoints, including Chat Completions but not Responses in the +observed test. A microVM has no desktop display. Model calls and coding tools +must stay in the guest while the human interacts from the host. + +## Decision drivers + +- Reuse existing streaming/tool translation instead of writing a protocol adapter. +- Read provider-neutral inputs and injected credentials, without storing keys. +- Avoid global configuration ownership, shared daemon/port races, and GUI dependencies. +- Pin both supported guest architectures and every bridge dependency. +- Keep user permission prompts and provider egress controls intact. + +## Considered options + +1. Claude Code Router: purpose-built routing, but its current CLI introduces a + management UI, database/native dependency, and larger configuration surface. +2. Full LiteLLM proxy: established Claude integration, but more endpoints and + management/auth/storage features than a single guest session needs. +3. LiteLLM library behind a narrow, session-local facade: reuse translation, + exposing only authenticated Messages and token-count routes. +4. Write a translator: minimal dependencies, but high maintenance and protocol risk. + +## Decision outcome + +Propose option 3. Each wrapper invocation pre-binds a random guest-loopback port, +spawns a ready-gated service, runs Claude and terminates only that service on exit. +Force LiteLLM's `use_chat_completions_url_for_anthropic_messages` setting; the +default Responses path fails on the observed USAi endpoint. Do not publish the +proxy. The host uses acq's TUI/PTY connection; the existing Paseo kit provides +optional browser access via its own published UI port. + +The observed gateway repeats tool IDs across argument chunks; LiteLLM emits +separate incomplete SSE blocks for them. Normalize consecutive same-ID blocks +into a single call without changing tool names or argument bytes. A regression +fixture and live Claude Read/result continuation validate this adapter. + +Pin LiteLLM 1.100.4 with patched filelock 4.2.1. Newer LiteLLM releases currently +cap filelock below 4.0, which conflicts with published filelock advisory fixes. +The chosen locked set was audited without reported vulnerabilities. + +Install Claude's native npm platform artifact after SHA-256 verification, without +an upstream install script. Install bridge dependencies as hash-locked wheels in +a dedicated per-user venv. Installation and session routing fail visibly rather +than fallback to Anthropic or an unpinned dependency. + +## Consequences + +### Distribution and validation ownership + +Distribute the kit in `mogul/agentic-coding-kits`, with no runtime dependency on +the Patterns repository layout. Keep the neutral contract's validation code in +its upstream home and use a pinned Patterns checkout from shared repository +tooling. The kit retains its hash-locked runtime, tests, and operator verification; +the destination CI discovers kits and tests them through a common runner rather +than importing the Patterns skill/routing/index pipeline. Provenance is recorded +in `NOTICE`, and downloaded dependencies retain their own licenses. + +Positive: no database, no desktop, no proxy administrative API, no stored keys, +no global settings replacement, independent concurrent sessions, both Linux architectures. + +Negative: LiteLLM still has a sizable dependency tree; native npm distribution is +deprecated upstream and may disappear. Claude is proprietary and requires human +license/terms review. Ordinary tool use is supported, but Anthropic-specific +thinking/server tools/cache semantics and exact tokenizer behavior are not. +Conservative token counts can overestimate context usage. Browser composition +and actual microVM PTY/lifecycle must be tested on a capable host. + +The facade's input boundary accepts only model IDs from the authoritative +snapshot and ordinary request fields. Provider routing never comes from client +bodies. Same-user environment separation does not prevent a shell-capable agent +from recovering credentials; the microVM/backend egress remains the boundary. +Control tags describe design concerns, not a compliance or ATO assertion. + +## Links + +- [LiteLLM Claude Code integration](https://github.com/BerriAI/litellm/blob/main/cookbook/ai_coding_tool_guides/claude_code_quickstart/guide.md) +- [LiteLLM Messages dispatch implementation](https://github.com/BerriAI/litellm/tree/main/litellm/llms/anthropic/pass_through/messages) +- [Claude Code Router](https://github.com/musistudio/claude-code-router) +- [Claude Code distribution](https://github.com/anthropics/claude-code) +- [Provider contract](https://github.com/GSA-TTS/agentic-coding-patterns/blob/main/integrations/isolation/docs/provider-input-contract.md) +- [Kit README](../../README.md) diff --git a/claude-code/docs/verification.md b/claude-code/docs/verification.md new file mode 100644 index 0000000..63d822a --- /dev/null +++ b/claude-code/docs/verification.md @@ -0,0 +1,148 @@ +--- +title: "Claude Code Kit Verification Record" +description: "Observed test results and unverified microVM gates." +status: draft +tier: 2 +last_updated: "2026-10-30" +--- + +# Verification record + +AI-assisted implementation and independent adversarial reviews, recorded +2026-10-30. Individual commands and observed output are in the session's tool +history. Human review is required before production use. No commit or push was +performed, and no VM was launched. + +## Verification history + +### Relocation check + +After copying this kit into `mogul/agentic-coding-kits`, the actual runtime +payload was exercised again: 30 live/unit/lifecycle tests passed (four upstream +Pydantic deprecation warnings). Offline execution reports 27 passed and three +explicit live skips. Local kit documentation links resolve. No host-global +Claude/Paseo configuration was changed by the relocation. + +### Destination repository transcript + +In `mogul/agentic-coding-kits`, `make check` passed with the pinned Patterns +validator checkout and a checksum-verified local Gitleaks executable. This runs +Ruff lint/format, ShellCheck, all four kit contracts, provider input validation, +shared tooling tests, each kit's offline runner, runtime/development dependency +audits, unsafe-shell checks, and secret scanning. Model credentials and VM +creation are not part of that command. The development and Claude-test locks +are universal hash locks; Python lanes select their requested interpreter. + +GitHub Actions and local Python 3.12 execution were not observed in this session. +CI provides the Python 3.12 and 3.14 lanes; these are planned CI checks, not a +claim of a completed remote run. + +### Historical Patterns repository transcript + +The following table records checks run before relocation in the source Patterns +repository. Its Make targets and 745-test count do not describe this repository. + +| Check | Command | Result | +|---|---|---| +| Repository validation | `make validate` | PASS; existing advisory warnings remain | +| Kit specs/payload wiring | `make validate-kits` | PASS; 12 kits and 2 templates | +| Provider contracts | `make validate-provider-input-contract` | PASS; 3 bundles | +| Index/catalog | `make generate-check` | PASS; unchanged and current | +| Repository tests | `make test` | PASS; 745 tests | +| Clean isolated kit suites | `make test-kits` | PASS; temporary runner provisions bridge dependencies | +| Live/lifecycle kit suite | `RUN_CLAUDE_LIVE=1 python -m pytest /tests -q` with explicit test binary and provider root | PASS; 27 tests | +| Python lint/format | `ruff check `; `ruff format ` | PASS | +| Shell wrapper | `shellcheck /files/home/.local/bin/claude` | PASS | +| Unsafe-shell scan | `make scan-shell` | PASS; 0 errors/warnings | +| Locked dependency audit | `pip-audit -r /files/home/claude-code/requirements.lock --disable-pip --no-deps` | PASS; no known vulnerabilities | +| Python compilation | `python -m compileall -q /files/home/claude-code` | PASS | +| Whitespace | `git diff --check` | PASS | +| Host-side verifier | `python /scripts/verify` | UNVERIFIED; expected exit 3, 24 offline tests passed / 3 live tests skipped | + +The isolated interpreter contains the exact runtime wheel lock plus test tools. +Live credentials stayed in the injected environment; test files contain only +public provider facts, a model snapshot, and synthetic text. Credentials were +not included in prompts, generated configuration, or recorded output. + +## Live observations + +### Operator microVM validation and model catalog follow-up + +The operator's macOS host ran MSB 0.7.7 with the Quickstart checkout at e4feef5. +The older Homebrew acq 4.1.1 lacked provider projection. With the checkout, +the provider validator accepted one USAi bundle, the guest received a generation +root under `/var/lib/acq/provider-input`, and Claude returned `ACQ_OK`. +The pip-wheel bootstrap installed successfully in the actual Python 3.14 guest +without ensurepip. The operator reached Paseo's browser UI and successfully +prompted Sonnet 5. Exact-ID CLI Sonnet 5.5 returned `ACQ_SONNET_55_OK` too. +The native browser model picker exposed incompatible Claude aliases, motivating +the Claude-owned catalog change rather than a second projection into Paseo. + +The updated wrapper's real SDK `supportedModels()` probe returned the exact +snapshot IDs and Default resolved to `claude-sonnet-5`; Fable was absent. +It uses temporary Claude settings without rewriting global config. The updated +live/unit/lifecycle suite passed 29 tests, with four upstream deprecation warnings. +The operator's refreshed browser picker remains a required confirmation. + +The operator subsequently confirmed Paseo 0.13.0 retains curated native entries +after restart. Its Sonnet 5.5 ID is `claude-sonnet-5-5`, not USAi's dotted ID. +A real Claude SDK recorder probe with `modelOverrides` observed the dotted +gateway ID on a `setModel` request. A second real SDK probe through the actual +kit wrapper and USAi successfully switched using the canonical hyphenated name. +The kit now includes only explicit same-version override pairs when the target +exists in the selected snapshot. Fable and extended-context variants stay unmapped. +This fixes equivalent-name routing, not Paseo's hardcoded picker contents. + +- USAi returned `ACQ_OK` through Chat Completions as JSON and Anthropic-shaped SSE. +- Forced function-tool requests returned `tool_use`. +- The actual checksum-verified **ARM64 Claude Code 2.1.314** executable ran + through the private launcher and returned `ACQ_OK`. +- The real CLI used Read on a synthetic file and returned its marker, proving + tool arguments and tool-result continuation through the stream normalization. +- Controlling-PTY regressions performed an immediate stdin read. Targeted + SIGHUP/SIGTERM exited 129/143 and stopped Claude, its real proxy, and a + synthetic SIGTERM-resistant tool child. Two-provider credentials were stripped. +- Both x64 and ARM64 native archives were downloaded and SHA-256 checked. + Only ARM64 execution was possible on this host. + +LiteLLM emitted four Pydantic deprecation warnings in live tests. USAi deployment +names can trigger Claude's unrecognized-model/context-metadata warning. Neither +warning is hidden as proof of complete upstream compatibility. Parallel tools, +extended thinking, and richer modalities were not validated. + +## Review findings addressed + +Independent review found clean-CI dependency wiring, stream concurrency lifetime, +hangup cleanup, unrelated credential forwarding, a session-specific interpreter +path, and a terminal-foreground race. Fixes were reviewed again; the final scoped +recheck found no concrete merge blocker. Live CLI testing also found repeated +tool IDs splitting JSON arguments; a regression and actual Read/result round +trip now pass. + +## Pending host validation gates + +- [x] Real acq MSB ARM64 microVM provisioning/startup installation, operator-observed. +- [ ] Backend provider-root read-only enforcement and startup ordering. +- [ ] Actual interactive permission prompts and host attach/disconnect. +- [ ] x64 guest installation and CLI execution. +- [x] Paseo composition: published host-loopback browser UI and Claude Sonnet 5/5.5 routing, operator-observed. +- [ ] Browser approval prompts and actual backend disconnect behavior. +- [ ] Enterprise CA trust through the actual guest's Python HTTPS client. + +Initial validation was blocked by this environment's inability to launch +microVMs. The operator later confirmed ARM64 MSB installation, generation-root +presence, browser access, and Sonnet 5/5.5 routing as recorded above. Read-only +mount enforcement, permission/disconnect behavior on the actual backend, x64 +execution, and enterprise CA-specific validation remain unverified. The kit +stays experimental and the verifier preserves exit 3 for incomplete live coverage. + +## Rollback and security impact + +Rollback: remove the extra kit selection and recreate the disposable sandbox +without it. Existing user Claude settings and transcripts are not overwritten. + +Adds installation egress, locked dependencies, proprietary Claude software, +and an authenticated guest-loopback facade. This kit adds no host model API port, +Anthropic login, cloud relay, permission bypass, or production infrastructure +change. Optional Paseo exposure follows that kit's separate security boundary. +This record is evidence, not a compliance assertion. diff --git a/claude-code/files/home/.local/bin/claude b/claude-code/files/home/.local/bin/claude new file mode 100644 index 0000000..72ae36d --- /dev/null +++ b/claude-code/files/home/.local/bin/claude @@ -0,0 +1,4 @@ +#!/bin/sh +# The per-user prefix is independent of interactive shell PATH initialization. +set -eu +exec "$HOME/.local/share/acq/claude-code/venv/bin/python" "$HOME/claude-code/launch.py" "$@" diff --git a/claude-code/files/home/claude-code/install.py b/claude-code/files/home/claude-code/install.py new file mode 100644 index 0000000..d47d783 --- /dev/null +++ b/claude-code/files/home/claude-code/install.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +"""Install the pinned CLI and wheel-only, hash-locked bridge as the agent user.""" + +import argparse +import hashlib +import os +import platform +import shutil +import subprocess +import sys +import tarfile +import tempfile +import urllib.request +from pathlib import Path + +VERSION = "2.1.314" +PINS = { + "x86_64": ("x64", "c6b690e52ba2d038c4c8d2566b2ec35acef4995c4321f7d57fa464a7088c2b78"), + "aarch64": ("arm64", "5a8087f6b0df5796326bb8e58c6e89637c58f28a16aea45434a7e914e854b0dc"), +} +PIP_URL = ( + "https://files.pythonhosted.org/packages/3f/06/" + "3e4420302363fbb71be3c7f35ce042f54bfca330e3e66b3a2e3c4cca579f/pip-26.2.2-py3-none-any.whl" +) +PIP_SHA256 = "fd7f4dfa8190e014013b9f08f3e973f4e4c26ffd179a204895533a7254813a70" + + +def bootstrap_venv(prefix, stage): + # Debian/Ubuntu split ensurepip into a separate package. stdlib venv without + # seeding works without it; a verified universal wheel supplies pip instead. + subprocess.run([sys.executable, "-m", "venv", "--without-pip", str(prefix / "venv")], check=True) # noqa: S603 -- fixed interpreter/module argv + wheel = stage / "pip-26.2.2-py3-none-any.whl" + with urllib.request.urlopen(PIP_URL, timeout=120) as response, wheel.open("xb") as target: # noqa: S310 -- fixed HTTPS URL + if response.geturl() != PIP_URL: + raise ValueError("unexpected pip download redirect") + shutil.copyfileobj(response, target) + with wheel.open("rb") as source: + if hashlib.file_digest(source, "sha256").hexdigest() != PIP_SHA256: + raise ValueError("pip wheel SHA-256 mismatch") + env = os.environ.copy() + env["PYTHONPATH"] = str(wheel) + subprocess.run( # noqa: S603 -- verified wheel and fixed pip argv, no shell + [ + str(prefix / "venv/bin/python"), + "-m", + "pip", + "install", + "--isolated", + "--no-index", + "--no-deps", + "--force-reinstall", + str(wheel), + ], + env=env, + check=True, + ) # noqa: S603 -- verified wheel, fixed pip argv + + +def extract_binary(archive, digest, destination): + with archive.open("rb") as source: + if hashlib.file_digest(source, "sha256").hexdigest() != digest: + raise ValueError("Claude archive SHA-256 mismatch") + with tarfile.open(archive, "r:gz") as bundle: + members = [m for m in bundle.getmembers() if m.name == "package/claude"] + if len(members) != 1 or not members[0].isreg(): + raise ValueError("archive must contain one regular package/claude") + if not 1 <= members[0].size <= 500_000_000: + raise ValueError("invalid binary size") + with bundle.extractfile(members[0]) as source, destination.open("xb") as target: + shutil.copyfileobj(source, target) + destination.chmod(0o755) + + +def install(): + if os.geteuid() == 0: + raise ValueError("install must run as the unprivileged agent") + if platform.system() != "Linux" or platform.machine() not in PINS: + raise ValueError("supported guests: glibc Linux x86_64 and aarch64") + if not (3, 12) <= tuple(sys.version_info[:2]) < (3, 15): + raise ValueError("bridge requires Python 3.12–3.14 with stdlib venv") + prefix = Path.home() / ".local/share/acq/claude-code" + prefix.mkdir(parents=True, exist_ok=True) + lock = Path(__file__).with_name("requirements.lock") + stamp = VERSION + ":" + PIP_SHA256 + ":" + hashlib.sha256(lock.read_bytes()).hexdigest() + marker = prefix / "installed" + if ( + marker.is_file() + and marker.read_text() == stamp + and (prefix / "claude").is_file() + and (prefix / "venv/bin/python").is_file() + ): + return + arch, digest = PINS[platform.machine()] + url = f"https://registry.npmjs.org/@anthropic-ai/claude-code-linux-{arch}/-/claude-code-linux-{arch}-{VERSION}.tgz" + with tempfile.TemporaryDirectory(prefix="install-", dir=prefix) as temporary: + stage = Path(temporary) + archive = stage / "claude.tgz" + # URL is constructed exclusively from the fixed HTTPS registry and architecture pins. + with urllib.request.urlopen(url, timeout=120) as response, archive.open("xb") as target: # noqa: S310 + if response.geturl() != url: + raise ValueError("unexpected download redirect") + shutil.copyfileobj(response, target) + extract_binary(archive, digest, stage / "claude") + # Fixed interpreter/module invocations, argv form; no external command strings. + bootstrap_venv(prefix, stage) + subprocess.run( # noqa: S603 -- fixed interpreter and pip argv, hash-locked input + [ + str(prefix / "venv/bin/python"), + "-m", + "pip", + "install", # noqa: S603 + "--isolated", + "--require-hashes", + "--only-binary=:all:", + "--index-url", + "https://pypi.org/simple", + "--timeout", + "60", + "--retries", + "0", + "-r", + str(lock), + ], + check=True, + ) + os.replace(stage / "claude", prefix / "claude") + marker.write_text(stamp) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--apply", action="store_true", help="install; otherwise preview only") + args = parser.parse_args() + if args.apply: + install() + else: + print(f"Would install Claude Code {VERSION} and the locked LiteLLM bridge in the agent home") diff --git a/claude-code/files/home/claude-code/launch.py b/claude-code/files/home/claude-code/launch.py new file mode 100644 index 0000000..52000a0 --- /dev/null +++ b/claude-code/files/home/claude-code/launch.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python3 +"""Run Claude with a private proxy; each invocation owns only its own child.""" + +import json +import multiprocessing +import os +import secrets +import signal +import socket +import subprocess +import sys +import tempfile +from contextlib import suppress +from pathlib import Path + +from models import compose_settings, settings_argv +from provider import credential_names, load_provider + + +def serve(sock, facts, ids, token, ready): + # Use the guest system trust bundle for the Python HTTPS client too. + ca = Path("/etc/ssl/certs/ca-certificates.crt") + if ca.is_file(): + os.environ.setdefault("SSL_CERT_FILE", str(ca)) + os.environ.setdefault("REQUESTS_CA_BUNDLE", str(ca)) + import uvicorn + from proxy import make_app + + config = uvicorn.Config(make_app(facts, ids, token), log_level="critical", access_log=False, lifespan="off") + server = uvicorn.Server(config) + + async def run(): + import asyncio + + task = asyncio.create_task(server.serve(sockets=[sock])) + while not server.started and not task.done(): + await asyncio.sleep(0.02) + if server.started: + ready.send(True) + await task + + import asyncio + + asyncio.run(run()) + + +def claude_environment(facts, roles, port, token, keys=()): + env = os.environ.copy() + # Do not hand the actual upstream credential (or unrelated GitHub token) + # to Claude. The proxy child alone uses the injected provider credential. + for name in ( + *keys, + facts["keyEnv"], + "GITHUB_TOKEN", + "USAI_API_KEY", + "OPENAI_API_KEY", + "ANTHROPIC_API_KEY", + "CLAUDE_CODE_OAUTH_TOKEN", + "CLAUDE_CODE_USE_BEDROCK", + "CLAUDE_CODE_USE_VERTEX", + "CLAUDE_CODE_USE_FOUNDRY", + ): + env.pop(name, None) + env.update( + ANTHROPIC_BASE_URL=f"http://127.0.0.1:{port}", + ANTHROPIC_AUTH_TOKEN=token, + ANTHROPIC_MODEL=roles["primary"], + ANTHROPIC_DEFAULT_SONNET_MODEL=roles["primary"], + ANTHROPIC_DEFAULT_HAIKU_MODEL=roles["small"], + ANTHROPIC_DEFAULT_OPUS_MODEL=roles["opus"], + CLAUDE_CODE_SUBAGENT_MODEL=roles["primary"], + DISABLE_AUTOUPDATER="1", + CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC="1", + DISABLE_TELEMETRY="1", + DISABLE_ERROR_REPORTING="1", + DISABLE_NON_ESSENTIAL_MODEL_CALLS="1", + MAX_THINKING_TOKENS="0", + CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS="1", + ENABLE_TOOL_SEARCH="false", + ) + ca = Path("/etc/ssl/certs/ca-certificates.crt") + if ca.is_file(): + env.setdefault("NODE_EXTRA_CA_CERTS", str(ca)) + return env + + +def run_session(binary, args): + facts, ids, roles = load_provider() + # Temporary settings are kit-owned and contain model metadata only. No + # global Claude or Paseo config writer; discovery invocations use them too. + with tempfile.TemporaryDirectory(prefix="acq-claude-models-") as directory: + args, composed = compose_settings(args, ids, roles) + settings = Path(directory) / "settings.json" + settings.write_text(json.dumps(composed)) + settings.chmod(0o600) + return run_configured_session(binary, settings_argv(args, settings), facts, ids, roles) + + +def run_configured_session(binary, args, facts, ids, roles): + token = secrets.token_urlsafe(32) + context = multiprocessing.get_context("spawn") + receiver, sender = context.Pipe(duplex=False) + with socket.socket() as sock: + sock.bind(("127.0.0.1", 0)) + sock.listen(128) + worker = context.Process(target=serve, args=(sock, facts, ids, token, sender)) + worker.start() + try: + sender.close() + if not receiver.poll(60) or not receiver.recv(): + raise ValueError("proxy did not become ready within 60 seconds") + env = claude_environment(facts, roles, sock.getsockname()[1], token, credential_names(os.environ)) + # Trusted fixed binary; operator's CLI arguments are passed without a shell. + terminal = sys.stdin.isatty() + previous_group = os.tcgetpgrp(sys.stdin.fileno()) if terminal else None + # Main launcher is single-threaded. Claim terminal in the child after + # setpgid and BEFORE exec, eliminating the immediate-read SIGTTIN race. + child = subprocess.Popen( # noqa: S603 -- trusted binary, no shell + [str(binary), *args], + env=env, + process_group=0, + preexec_fn=claim_terminal if terminal else None, + ) + try: + return child.wait() + finally: + stop_group(child) + if previous_group is not None: + foreground(previous_group) + finally: + receiver.close() + worker.terminate() + worker.join(10) + if worker.is_alive(): + worker.kill() + worker.join() + + +def foreground(group): + previous = signal.signal(signal.SIGTTOU, signal.SIG_IGN) + try: + os.tcsetpgrp(sys.stdin.fileno(), group) + finally: + signal.signal(signal.SIGTTOU, previous) + + +def claim_terminal(): + foreground(os.getpgrp()) + + +def stop_group(child): + # Only this Claude invocation's process group, never another agent's tree. + try: + os.killpg(child.pid, signal.SIGTERM) + except ProcessLookupError: + return + with suppress(subprocess.TimeoutExpired): + child.wait(10) + with suppress(ProcessLookupError): + os.killpg(child.pid, signal.SIGKILL) + child.wait() + + +def main(): + binary = Path.home() / ".local/share/acq/claude-code/claude" + args = sys.argv[1:] + if not binary.is_file(): + print("claude-code: installation not ready; check the kit startup install output", file=sys.stderr) + return 1 + if args in (["--help"], ["-h"], ["--version"], ["-v"]): + return subprocess.call([str(binary), *args]) # noqa: S603 -- fixed binary, allowlisted flags + signal.signal(signal.SIGTERM, lambda *_: sys.exit(143)) + signal.signal(signal.SIGHUP, lambda *_: sys.exit(129)) + try: + return run_session(binary, args) + except (ValueError, OSError, EOFError): + print( + "claude-code: not ready; verify installation, provider selection, and credential injection", file=sys.stderr + ) + return 1 + except KeyboardInterrupt: + return 130 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/claude-code/files/home/claude-code/models.py b/claude-code/files/home/claude-code/models.py new file mode 100644 index 0000000..bae6d81 --- /dev/null +++ b/claude-code/files/home/claude-code/models.py @@ -0,0 +1,76 @@ +"""Claude-owned picker and restrictions derived from the selected acq catalog.""" + +from pathlib import Path + +from provider import strict_json + +# Explicit same-version deployment equivalents, not fuzzy name normalization. +# Never add extended-context suffixes or map unavailable Fable to another family. +CANONICAL_EQUIVALENTS = { + "claude-sonnet-5-5": "claude-sonnet-5.5", + "claude-opus-4-8": "claude_4_8_opus", + "claude-opus-4-7": "claude_4_7_opus", + "claude-sonnet-4-6": "claude_4_6_sonnet", + "claude-sonnet-4-5": "claude_4_5_sonnet", + "claude-haiku-4-5": "claude_4_5_haiku", +} + + +def model_overrides(ids): + return {source: target for source, target in CANONICAL_EQUIVALENTS.items() if target in ids and source not in ids} + + +def compose_settings(args, ids, roles): + remaining = [] + settings = {} + index = 0 + while index < len(args): + arg = args[index] + if arg == "--": + remaining.extend(args[index:]) + break + if arg == "--model" or arg.startswith("--model="): + value = args[index + 1] if arg == "--model" and index + 1 < len(args) else arg.partition("=")[2] + if ( + value not in ids + and value not in model_overrides(ids) + and value not in ("default", "sonnet", "opus", "haiku") + ): + raise ValueError("explicit model must be an exact gateway ID or configured role alias") + if arg == "--settings" or arg.startswith("--settings="): + if arg == "--settings": + index += 1 + if index >= len(args): + raise ValueError("missing --settings value") + value = args[index] + else: + value = arg.split("=", 1)[1] + parsed = strict_json(value if value.lstrip().startswith("{") else Path(value).read_text()) + if not isinstance(parsed, dict): + raise ValueError("Claude settings must be an object") + settings.update(parsed) + else: + remaining.append(arg) + index += 1 + # Preserve SDK hooks/permissions/env; own only model selection fields. + settings.update(model_settings(ids, roles)) + return remaining, settings + + +def settings_argv(args, path): + index = args.index("--") if "--" in args else len(args) + return [*args[:index], "--settings", str(path), *args[index:]] + + +def model_settings(ids, roles): + # Exact gateway IDs avoid fuzzy family/version mappings and unavailable aliases. + return { + "model": roles["primary"], + "availableModels": [*ids, *model_overrides(ids)], + "modelOverrides": model_overrides(ids), + "enforceAvailableModels": True, + "modelPicker": { + "replaceBuiltInOptions": True, + "options": [{"model": model, "label": model} for model in ids], + }, + } diff --git a/claude-code/files/home/claude-code/provider.py b/claude-code/files/home/claude-code/provider.py new file mode 100644 index 0000000..cd2e68c --- /dev/null +++ b/claude-code/files/home/claude-code/provider.py @@ -0,0 +1,135 @@ +"""Resolve only backend-owned, provider-neutral facts; never persist credentials.""" + +import json +import os +import re +from pathlib import Path +from urllib.parse import urlsplit + + +def strict_json(text): + def unique(pairs): + result = {} + for key, value in pairs: + if key in result: + raise ValueError("duplicate JSON property") + result[key] = value + return result + + def reject_constant(_): + raise ValueError("non-finite JSON constant") + + return json.loads(text, object_pairs_hook=unique, parse_constant=reject_constant) + + +def credential_names(environ): + """Read credential names for ALL projected providers, never their values.""" + root = Path(environ["ACQ_PROVIDER_INPUT_ROOT"]) / "models/providers" + names = set() + for directory in root.iterdir(): + if directory.is_symlink() or not directory.is_dir(): + raise ValueError("invalid provider directory") + facts = read_input(directory / "facts.json") + validate_facts(facts, directory.name) + names.add(facts["keyEnv"]) + return names + + +def read_input(path): + if path.is_symlink() or not path.is_file(): + raise ValueError("provider input must be a regular, non-symlink file") + if path.stat().st_size > 2_000_000: + raise ValueError("provider input exceeds size limit") + result = strict_json(path.read_text()) + if not isinstance(result, dict): + raise ValueError("provider input must be an object") + return result + + +def validate_facts(facts, provider_id): + if facts.get("schemaVersion") != "acq-provider-facts/v1": + raise ValueError("unsupported provider facts version") + if facts.get("providerId") != provider_id: + raise ValueError("provider directory and identity disagree") + if facts.get("apiProtocol") != "openai-compatible": + raise ValueError("Claude kit requires an OpenAI-compatible provider") + url = urlsplit(facts.get("baseUrl", "")) + if ( + url.scheme != "https" + or not url.hostname + or url.username + or url.password + or url.query + or url.fragment + or url.hostname != facts.get("host") + ): + raise ValueError("provider baseUrl must be HTTPS and agree with host") + key_env = facts.get("keyEnv", "") + if not isinstance(key_env, str) or not re.fullmatch(r"[A-Z][A-Z0-9_]*", key_env): + raise ValueError("invalid credential environment name") + if key_env == "GITHUB_TOKEN": + raise ValueError("GitHub credentials are not model credentials") + + +def model_ids(catalog, provider_id): + if catalog.get("schemaVersion") != "acq-neutral-model-catalog/v1" or catalog.get("providerId") != provider_id: + raise ValueError("catalog version or identity mismatch") + models = catalog.get("models") + if not isinstance(models, list) or len(models) > 500: + raise ValueError("invalid model list") + ids = [] + for model in models: + value = model.get("id") if isinstance(model, dict) else None + if not isinstance(value, str) or not 1 <= len(value) <= 128 or re.search(r"[\x00-\x1f\x7f\u2028\u2029]", value): + raise ValueError("invalid model ID") + if value in ids: + raise ValueError("duplicate model ID") + ids.append(value) + return ids + + +def choose_models(catalog, ids, environ): + recommendations = catalog.get("recommendations", {}) + if not isinstance(recommendations, dict): + raise ValueError("invalid recommendations") + if any(value not in ids for value in recommendations.values()): + raise ValueError("recommendation references an absent model") + primary = environ.get("ACQ_CLAUDE_MODEL") or recommendations.get("primary") + if primary is None and len(ids) == 1: + primary = ids[0] + small = environ.get("ACQ_CLAUDE_SMALL_MODEL") or recommendations.get("small") or primary + opus = environ.get("ACQ_CLAUDE_OPUS_MODEL") or primary + if any(value not in ids for value in (primary, small, opus)): + raise ValueError("select valid ACQ_CLAUDE_MODEL/SMALL_MODEL/OPUS_MODEL values") + return {"primary": primary, "small": small, "opus": opus} + + +def load_provider(environ=None): + environ = os.environ if environ is None else environ + root_value = environ.get("ACQ_PROVIDER_INPUT_ROOT", "") + root = Path(root_value) + if not root_value or not root.is_absolute() or root.is_symlink(): + raise ValueError("ACQ_PROVIDER_INPUT_ROOT is not ready") + providers = root / "models" / "providers" + for location in (root / "models", providers): + if location.is_symlink() or not location.is_dir(): + raise ValueError("authoritative provider directory is not ready") + candidates = sorted(providers.iterdir()) + if any(p.is_symlink() or not p.is_dir() for p in candidates): + raise ValueError("invalid provider directory entry") + selected = environ.get("ACQ_CLAUDE_PROVIDER") + if selected is None and len(candidates) == 1: + selected = candidates[0].name + if not isinstance(selected, str) or not re.fullmatch(r"[a-z0-9](?:[a-z0-9-]{0,30}[a-z0-9])?", selected): + raise ValueError("select ACQ_CLAUDE_PROVIDER when providers are empty or ambiguous") + directory = providers / selected + if directory not in candidates: + raise ValueError("selected provider is absent") + facts = read_input(directory / "facts.json") + validate_facts(facts, selected) + catalog = read_input(directory / "snapshot.json") + ids = model_ids(catalog, selected) + roles = choose_models(catalog, ids, environ) + if not environ.get(facts["keyEnv"]): + raise ValueError("selected provider credential is not injected") + return facts, ids, roles diff --git a/claude-code/files/home/claude-code/proxy.py b/claude-code/files/home/claude-code/proxy.py new file mode 100644 index 0000000..89631d6 --- /dev/null +++ b/claude-code/files/home/claude-code/proxy.py @@ -0,0 +1,163 @@ +"""Authenticated session-local Anthropic Messages facade over LiteLLM.""" + +import asyncio +import hmac +import json +import logging +import os + +os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True" + +import litellm +from fastapi import FastAPI, Request +from fastapi.responses import JSONResponse, StreamingResponse + +litellm.use_chat_completions_url_for_anthropic_messages = True +litellm.suppress_debug_info = True +litellm.set_verbose = False +litellm.turn_off_message_logging = True +logging.getLogger("LiteLLM").setLevel(logging.CRITICAL) + +MAX_BODY = 8 * 1024 * 1024 +FIELDS = { + "messages", + "max_tokens", + "system", + "stop_sequences", + "stream", + "temperature", + "top_p", + "top_k", + "tools", + "tool_choice", +} + + +class RequestValidationError(ValueError): + """Only fixed, kit-authored messages may be returned to the caller.""" + + +def error(status, message): + return JSONResponse( + status_code=status, content={"type": "error", "error": {"type": "api_error", "message": message}} + ) + + +async def body(request, token, ids): + auth = request.headers.get("authorization", "") + candidate = auth.removeprefix("Bearer ") if auth.startswith("Bearer ") else request.headers.get("x-api-key", "") + if not hmac.compare_digest(candidate, token): + raise PermissionError("proxy authentication required") + raw = bytearray() + async for chunk in request.stream(): + raw.extend(chunk) + if len(raw) > MAX_BODY: + raise RequestValidationError("Request body exceeds the proxy size limit") + from provider import strict_json + + data = strict_json(raw) + if not isinstance(data, dict): + raise RequestValidationError("Messages request must be a JSON object") + if not isinstance(data.get("model"), str) or data["model"] not in ids: + raise RequestValidationError( + "Model is not in the selected acq provider snapshot; choose an exact gateway model ID" + ) + if not isinstance(data.get("messages"), list): + raise RequestValidationError("Messages must be an array") + return data + + +def arguments(data, facts): + # Client-supplied routing, credentials, callbacks, MCP gateways, and logging + # options NEVER reach LiteLLM. Only ordinary function tools are supported. + tools = data.get("tools", []) + if not isinstance(tools, list) or any( + not isinstance(t, dict) or t.get("type", "custom") != "custom" for t in tools + ): + raise RequestValidationError("Only ordinary function tools are supported; disable Anthropic server-side tools") + params = {key: data[key] for key in FIELDS if key in data} + params.update( + model="openai/" + data["model"], + api_base=facts["baseUrl"], + api_key=os.environ[facts["keyEnv"]], + timeout=600, + num_retries=0, + drop_params=True, + _skip_mcp_handler=True, + ) + if type(params.get("max_tokens")) is not int or not 1 <= params["max_tokens"] <= 128000: + raise RequestValidationError("max_tokens must be an integer between 1 and 128000") + if "stream" in params and type(params["stream"]) is not bool: + raise RequestValidationError("stream must be boolean") + return params + + +async def sse(response, gate): + from stream import normalize + + try: + async with asyncio.timeout(600): + async for chunk in normalize(response): + yield chunk + except Exception: + yield ( + b'event: error\ndata: {"type":"error","error":{"type":"api_error","message":"Upstream stream failed"}}\n\n' + ) + finally: + try: + close = getattr(response, "aclose", None) + if close: + await close() + finally: + gate.release() + + +def make_app(facts, ids, token): + app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None) + gate = asyncio.Semaphore(4) + + @app.post("/v1/messages") + async def messages(request: Request): + leased = False + try: + data = await body(request, token, ids) + params = arguments(data, facts) + async with asyncio.timeout(600): + await gate.acquire() + leased = True + response = await litellm.anthropic.messages.acreate(**params) + if data.get("stream"): + result = StreamingResponse(sse(response, gate), media_type="text/event-stream") + leased = False # Streaming iterator owns release, including disconnect/cancellation. + return result + return JSONResponse(response) + except PermissionError: + return error(401, "Proxy authentication required") + except RequestValidationError as exc: + return error(400, str(exc)) + except (ValueError, TypeError, json.JSONDecodeError): + return error(400, "Invalid Messages request") + except Exception: + # Upstream exceptions may contain headers, keys, or prompt text. + return error(502, "Upstream request failed; check provider availability and credentials") + finally: + if leased: + gate.release() + + @app.post("/v1/messages/count_tokens") + async def count_tokens(request: Request): + try: + data = await body(request, token, ids) + # Offline estimate, not Anthropic's exact tokenizer. No tokenizer + # downloads, provider calls, or claims of exact context accounting. + payload = {key: data[key] for key in ("messages", "system", "tools") if key in data} + estimate = max(1, len(json.dumps(payload, ensure_ascii=False).encode("utf-8"))) + return JSONResponse({"input_tokens": estimate}) + except PermissionError: + return error(401, "Proxy authentication required") + except RequestValidationError as exc: + return error(400, str(exc)) + except (ValueError, TypeError): + return error(400, "Invalid token-count request") + + return app diff --git a/claude-code/files/home/claude-code/requirements.in b/claude-code/files/home/claude-code/requirements.in new file mode 100644 index 0000000..b201fda --- /dev/null +++ b/claude-code/files/home/claude-code/requirements.in @@ -0,0 +1,6 @@ +litellm==1.100.4 +mcp==2.3.0 +fastapi==0.162.0 +uvicorn==0.54.0 +# Patched transitive dependency; newer LiteLLM releases currently cap it below 4. +filelock==4.2.1 diff --git a/claude-code/files/home/claude-code/requirements.lock b/claude-code/files/home/claude-code/requirements.lock new file mode 100644 index 0000000..20441c3 --- /dev/null +++ b/claude-code/files/home/claude-code/requirements.lock @@ -0,0 +1,2346 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile integrations/isolation/acq-kits/claude-code/files/home/claude-code/requirements.in --python-version 3.12 --universal --generate-hashes --only-binary :all: --output-file integrations/isolation/acq-kits/claude-code/files/home/claude-code/requirements.lock +aiohappyeyeballs==2.7.1 \ + --hash=sha256:065665c041c42a5938ed220bdcd7230f22527fbec085e1853d2402c8a3615d9d \ + --hash=sha256:9243213661e29250eb41368e5daa826fc017156c3b8a11440826b2e3ed376472 + # via aiohttp +aiohttp==3.14.5 \ + --hash=sha256:0133c3c3b54a0bf1e71fa5c1ad95c93f07fd54e24ef1fe182f5122e1573d2bf1 \ + --hash=sha256:038c2c7e8caa26b6c8423779b5eaf1893904048a512c19b32fe841ffa5592b50 \ + --hash=sha256:0684952aeae1f5dbfe02d46039338513b94009baecd15d8e4098a357c4c4a2a6 \ + --hash=sha256:0790ec66fa4013e83c53b9025a45d454723da1a2fce28b3208c9b32d08af162f \ + --hash=sha256:083673c7a94c3ea035caaa5ca04288bdb44887abfe1f5ba23294e6a4b03efd2d \ + --hash=sha256:09e0eb18c7e0c8777e2f9149de63799195b9b3ca1b5c81ba6f32f2c6b8628210 \ + --hash=sha256:09ec102b4b8c9a920275733bbc11fdbb615efe6f9231a06007c0218d336fb77a \ + --hash=sha256:0a8ea271867e360ac985ae607f4a23ad9a38414b9aca1d49ec98839ae660e49f \ + --hash=sha256:0e6f16f5e49c4b8267988c05ab07760d7064cea57d077c3d068d04b0fbb992cb \ + --hash=sha256:1061b364556e8172e8d46b0b183adeeb73e8c42d30ebc745591e1bd89acad52e \ + --hash=sha256:1220353657ad49493551f089ce02f1a348fd57ffd585bfec77f2f3c4fe3a7346 \ + --hash=sha256:137351bf20bbed9a65e839f4a4452ac377389bdb2f2857d2acffef38f5e9f2d1 \ + --hash=sha256:149fb56caf7acb67073126f675d0958d9c4b3125fcd3f6d4877df98aa8a97ce9 \ + --hash=sha256:14f04769cfefe4734016a856a83af36133cd17779cef9ae817f812b8ba9d6d51 \ + --hash=sha256:15a310d3c71398e3d7bfc93a1a73fbe664315cd9e9016b8efc1cff85eeab7155 \ + --hash=sha256:1612fa5857b37bf32e5c1eaeefb96e3b01e9c70679eec81f0934e8a600080863 \ + --hash=sha256:16c8abd5bca220a47efe667d26f8460124c81810787e79ee87b242677563d9dd \ + --hash=sha256:19e2ba471507c34f8252402ab50f5ab512398b9ea8c8f1cb26beb3f75793ba30 \ + --hash=sha256:1aead151c3abbac6b32942e452020cb66d7efc099d253cc6c20f748e926c858b \ + --hash=sha256:1b438b73c38111818d0c9d6a5c2bfed8584c8e503a49ef085d70e874ec846738 \ + --hash=sha256:1b5416552740edf07234cc9437d0706f2acb67b93c198670b1a68e1b2b587dec \ + --hash=sha256:1d2d981b53dd09a319e3570ef8cc3bbc3ef86f5a7abef0f6b2bff3867db3a9e7 \ + --hash=sha256:1eb8167961ec4dfcc8cb9dd50bd0ee72519f7ef496be95203e49e27b01618382 \ + --hash=sha256:1ffa3a523a36d8628f98c06492ae16a31a23d14c0b4ec721757b477319f656d6 \ + --hash=sha256:20064a177a070d789ee64a50b01a9161d3468e989baacfc6c714aa685c4b332f \ + --hash=sha256:20726f9782d5c2744c1c66255842d1d163bb3edcf768b8de25216bf47f7b6ccf \ + --hash=sha256:20f085697d7e911f1f73c43ed03fafbed1e7121797e2eb5428efa80398060584 \ + --hash=sha256:225c579c23b68b343cccea27a7e06e3bd8ec23a09c30b427eb3f1e4ca6239b20 \ + --hash=sha256:24409db442e2fb6e766bc7f3943851a8381dec3098140e43bb2e843b79e31b12 \ + --hash=sha256:248d779ad720b49d4fb355720e60c9e5f444f95887bc16974fea48fc56c41789 \ + --hash=sha256:2528cb4c6b92008c76ac9ac6298624069bb2db91ff4929905512d1d84485f658 \ + --hash=sha256:276a4fc00b1d9ae492b802763a789c5b86328b989c5ea169f2faa447d6a11c7c \ + --hash=sha256:27c2322e03f66101acb09869ce1cf1efc04994ee95e1735b69827bf8c8b9d781 \ + --hash=sha256:293d3ae7c6a0ed176a42e59a1b5fde825ead65c835360f734148e96729f928d2 \ + --hash=sha256:2cc38a4f2b516bef1714e690df87a0e043faf1a7693c82d860091684453d5111 \ + --hash=sha256:3093b72c215bda16ce961a6d073f6e71d46e022962a9d5d457c5d4d421c78b57 \ + --hash=sha256:32e8fa6644e541fcd7e02430588c7fc93b602c1778ea0bc345505db76b61cfb4 \ + --hash=sha256:330900acd0dc4cb8b27f9c127fbaad770964845338493e7906ae3822e82dbf8d \ + --hash=sha256:33f706574e32c6e694f352a856e05caf18f7f2c871b3e87b41c55ea452b409ab \ + --hash=sha256:3ae800a20947e2c2e53088047d021e6bf7d51560cc49f6a0737a1f79d2e3a13c \ + --hash=sha256:3be7dd397d64ca3e1869626fa9318aaebb54b7bf93bc72d7a205448d83e4f748 \ + --hash=sha256:3e0eb43bed3c6801a6cee315195377789e90b2a72c2277a475b578535312488d \ + --hash=sha256:3e51a27980c3788e6e6b3325d694fdd4898087fa8a86b2763af77b39353da41e \ + --hash=sha256:3edbece0379b8b4aaa67619b8aa2399bb66fce372cd5911098a434ea77220aa0 \ + --hash=sha256:3f2dcc00191fd563e9075181a14ec31d7dd63223ced7582cc70a15a499de0c79 \ + --hash=sha256:42b5e616946dbaf505e2bff18c9af2cd4ef9e7ef300ee58a6e951a5b7cf147ae \ + --hash=sha256:42f320d4a5b00b9af0bddcfec5407dc6f2d9816f006b2f79ebbaa31f16895df3 \ + --hash=sha256:43351bdb5e4c3cb7d1772368e988534e869a74db7778079a83782c11c69535c7 \ + --hash=sha256:43e1b7994a8b038125f722bff07492ef501110722c2727c408995d9fb864c421 \ + --hash=sha256:4887d130a7bbfed3a85493bb5a25e5b5b558d40c1d986dd16970d2bb26d63793 \ + --hash=sha256:4f07fe3ac408d8b3f768be471dc3f56d43843c47d97c66120534467a15ead197 \ + --hash=sha256:50343c1757b4b6f6708eeaf24534b32f19dfb99fb1b762c00420867a62fc81e0 \ + --hash=sha256:50983e3be33d8c0942ab88cec3905b10602f64c469b20153c48c5d4e558dd016 \ + --hash=sha256:50a195903119008fe9cc68710535eb37f556ffffd6a7759afe70a2c145587045 \ + --hash=sha256:5558a7f5a05af9ecf744af91e5baefc436f93c9333e656c27ec253f9a6bbe178 \ + --hash=sha256:56572c42e3ecd636de8d2c3dd54cf5fc939cb5c32eb56297f176a0d366fac622 \ + --hash=sha256:56d9828f204331a5ca8850fcfe2bcce95a149f1f223f60cc7216e5524978e480 \ + --hash=sha256:579f97d5120f2971876d2ddca2968135f6944d00c44c3a6590ad7d86ca9b403f \ + --hash=sha256:5af42135fdfebdadbc2bcd9c0842a48ccf0d62794c36a260b21dc4b94d1e0119 \ + --hash=sha256:5ba14a839fbe87cf7c12a6b5661c05f324a296eb8363141edb3944ba63d4c9d3 \ + --hash=sha256:5c76f1802bab718a68ac3cce447160605c734551f95c67ae90fa1132b215cb29 \ + --hash=sha256:5e8f97c0488ffda3082766ac0f2c8150a9a58c4d05788330e479cfd449b37939 \ + --hash=sha256:5f3e96071686755d9cd3600c3880183eb94b012178e92746d68101800f0ed8a3 \ + --hash=sha256:5fb6a6e919bfb703227bc1ce6579281b84b1a2ba57deb9794dfdbec7dcd1e40c \ + --hash=sha256:602c1e9b718a3275c580149f947e7fac65044c0a20e599553fb12e9700da9eca \ + --hash=sha256:657291433bf4dd3142f3abac495764cd47d0c7c92087751e6666c6447e65fcef \ + --hash=sha256:6774814fd5c338e72ee0da5cbb9432816df450e69c019f72b5d29bdec2a1792d \ + --hash=sha256:6da32b5ff3fd78d244e37300463434c7145162bfd2b6e9e915ab164da37f7343 \ + --hash=sha256:6e1d8637cf73eebc92eba2e11d4cfff98a3b562f2505bd75bba766d908926e8d \ + --hash=sha256:6e4251c0ba4624a68a2c11471a1ac54c3306876c21f0ae86de085cc9241c8905 \ + --hash=sha256:6f275c11d1aa6d4c458e05a68be084efe3c55a113d99e3f46a318098e52948fc \ + --hash=sha256:6f967dde489ca6a8c02d093ab245d2cbf50ccb5c36adf0188b17b0ca39d24b67 \ + --hash=sha256:6fdcd6af7e2e51d1ba1b4bea16e97b074bcb7b5dd0246a9d8201341bb28085a0 \ + --hash=sha256:70cb4008ac2ed1e0ca9e824deb4b53d3aa0d939109698ebf1e723a84337bd794 \ + --hash=sha256:7457580535e019e1247ea35d6a02bf081ad30c26d0cbc210c93f6c3ab67a0835 \ + --hash=sha256:74b0a9c8270f9b0a11410e124ff8d4f18bfc1f1837440ec84da5ae7b50927b5d \ + --hash=sha256:74efb69332b85675b1eabd760a8cfc2e2cf42c60607c66f88014c1bdfb40942d \ + --hash=sha256:755933b107ea7a6a9ac916f635a70595a5b1a32fac10a8ff0b9f2ab88555550c \ + --hash=sha256:7779cd97e61ebe583ec2f1c5616cdd038aa08a4453b1848c67842176d054948e \ + --hash=sha256:788ecaa9c10533b786ce5ba70c4f2df78ad41819fd00a6c99d92b66f9a32e1da \ + --hash=sha256:7bd8ac754ebd6733a3e2a0dd1674c4d8ab086196803fd8dcd776f07b4e2607d9 \ + --hash=sha256:81c2b3dfd56c62bee6108e4852d5970b4cf9086390b6983f52b666e878c1f115 \ + --hash=sha256:823c910f046f23f4c713b8d99a2242dc65f591cb45ee86418fa11762a3c2963c \ + --hash=sha256:82c7583cd3dfdc7dcc927835b4f6c7faae7ecc1ba3ca5879321621ae2e6f8e84 \ + --hash=sha256:8966ecac808dd5f473c9c4cefd10cd3ffda71c18a4d3493b7c7d2ae1803bf2cc \ + --hash=sha256:8df7d481654ac96fe1ba9a02a9f67770fdd367823e0d5ef01b922725c4bd2cfa \ + --hash=sha256:8e317e0fb6b16212c881d2205a7d87414c29acd69320b3aa6dce9d9c7b86fe4f \ + --hash=sha256:932ce7e694bbc29b2bf6f64f2343c27d148d4997c771d01bdade4639b6749ff4 \ + --hash=sha256:939042d5cda21d41a6f512e7cc8b8e33a2aebff863352251da495fbd91b673b5 \ + --hash=sha256:94684b879ac1d71e4238850c99b62dc1b28d9086b156a2555f082010b85a865c \ + --hash=sha256:96a2e584f0b9ed8f1fa33211397dcf67bb7069866402cb405d191c2f0defb9a3 \ + --hash=sha256:9ad7e6aa38c20da1be697874349c4c273c8a03b7887169665081706398d0439a \ + --hash=sha256:9b42db919715e91eb76acf3bc492a9a7ccd8bd9adc6745c1412b689735269f14 \ + --hash=sha256:9bab2045550c4fe0f7baf89574db1b455c195750702ba96fef1f16972b146617 \ + --hash=sha256:9bf1d5dcc15204d9ec8b8ea4c18fd66e6b80e5de1f4ecbafb3a2f2740f8039d4 \ + --hash=sha256:9c061aa954daaf57d2a4b8374f9fca621ef0e1b603584431c220c22458c59b6d \ + --hash=sha256:9c428eb2bd8817588d16a0ab898aa4eb5d141f896aa2b394cc79a4cf61d9a8e2 \ + --hash=sha256:9cc882cf8619109583c906b4d4a85d6a111a98afa34b7a450d1e08118d016820 \ + --hash=sha256:9ce66feae6ac65327379460380549bf1b8df8e17c4e25df2a2bcf168272e3bed \ + --hash=sha256:a23fe35d776bc03cb495938b9594450d047e3bc08c5255315a82323e9cb7d2dd \ + --hash=sha256:a2c473a355f9239efcb72c92d5abfd8fcdb0cc78c8e9af607e72ca12dbb36593 \ + --hash=sha256:a63afd1f757de949028387e65a7127b61ad0f775432dbb0e62816ae619fe69ac \ + --hash=sha256:a6d02b4c38de03d9c7617813433e6a0fb6b522797974177d69d9dad431900833 \ + --hash=sha256:a7d470cf7b206e6359fc77b1b860632fde400d5a2ed59cd0181b93a686bc81ee \ + --hash=sha256:a95529a92a446db351675f4aab518feaf5e99842f63f5dd17160c2b74f382db3 \ + --hash=sha256:a9918e58faf62ba2c7147927d06057aec78f42475aff5048047ec47e7265a600 \ + --hash=sha256:a9d3983bd6ab7aa1cfd573544ae98df9b6cb6912a5185a198263e024a636861d \ + --hash=sha256:ab52d8f1fc1b64821c1fbad64a647ed6203627004059a6d1ed4f0858a1499703 \ + --hash=sha256:abfda5cb094a829f7bc25216a32f7db2e85cc65bd59910f8e7b40b3d9b224764 \ + --hash=sha256:adbeee7d6fd4cf5fe0aece2fb3edc4243615d3180430ba8149d01a90670cac99 \ + --hash=sha256:ae53924aa853a7a2ca20ed4142c7c6b56338e4d4cd999e2980075b9efc2e257a \ + --hash=sha256:b032a0023eb41d768ce77d83210ab2a3c389bc0b09313273c7e1eca48c10a755 \ + --hash=sha256:b1b8ece1e71132d2afba4dbc0c3d62c766e25165990b25db1196c04969eb3d84 \ + --hash=sha256:b2966998927d7bed9db12c0a4647b0c7b179755878fc9c357fe1ffd3e3b0c1a5 \ + --hash=sha256:b3cc509327c7b27f6f4727a8830f4004f6df7766e179f2f4b8e54e65c0bec5d3 \ + --hash=sha256:b7806e804889231b0e06469fd4a5c06313d1c0a3377322b6d9237fa5e0fe4167 \ + --hash=sha256:bea559ad70218d230663e4210875735076a9bfea5994cef34a55a25faeaf2544 \ + --hash=sha256:bf163cc701f3d4ac43ba7d97771bf5fd955220ef5500ef3ee847bc0ecfbf4ec1 \ + --hash=sha256:c147451b4a58e7050f7f7394e6c467867c84161560001f9ad4fb2d1446743946 \ + --hash=sha256:c172db893e516e1358e65a95ee20b7ce7173963eefe318b6ab2a2220688b999e \ + --hash=sha256:c1d60eafd9c7e8e74abd03a5b00df44e7febfe6d9b89b559c0a6551eef0699d4 \ + --hash=sha256:c2c30484dd1417ef98b51021ffa2cc0d7f3c78918adaaaab7e70817335ab3e02 \ + --hash=sha256:c32e26310cc10e547f53cd13d39a369034f69dcb7d749d5cb0e5f67bc196b6ba \ + --hash=sha256:c5ed596aedb9c42afd3fe0aae3117725378ac73d2cc5ddc735056fbdb96c5d02 \ + --hash=sha256:c8859a013ae0de1074660992139a1a440df3e6b219b86cf0d3f11c2692bb4fe3 \ + --hash=sha256:c8c4478bef6d57fcfda15dae461ea3c9f06aa7b257c58df3f2300174ccbb185a \ + --hash=sha256:cb11a971a3aea10f9b8373be628f1df932964fc6c6b174516d318a48c3ac4412 \ + --hash=sha256:cb131d775a1573c1aee66656bd78b023577bbdb6cb8349a07773bd4f73e68a6e \ + --hash=sha256:cd88b01f3d37b7a2a34f91d98f14720206f1ea3d540843fab2d649dd5fb91fec \ + --hash=sha256:d05e94cdfe0d15d0206f970722d2554780ce562787b21b218b275447f8751319 \ + --hash=sha256:d079c0a0135c36e7beb6f1c88087c8f108dc5891cdd0b5eafa778421bda70ed2 \ + --hash=sha256:d3112585250b199296c26ca6e0131640b6a8d01bab8b232d2eb3763ed469de11 \ + --hash=sha256:d418ce2af40c6bb685b3f663e9e8de27cb0a22431d8e88a167348d7f01878073 \ + --hash=sha256:d51db97c96384fbfcaf8f4c65922183a68b94f891c3c10c862ef5f6df2adbb1f \ + --hash=sha256:d94e44be379e569758fee8a9a58431cfc3c2598c708b92b1cfe96c66b4c94aef \ + --hash=sha256:dab9ac5a67c8d1f070c00fa8fccb7cbd1b8dcc1a8d6b42f37540df9b3d4cc603 \ + --hash=sha256:dbf53ae2601b7fd5a93c3944deea3a78d40f495226d582c35ef7a433425ce2b2 \ + --hash=sha256:dca3fa8d8a0a26679862eccb0b1a9151b2b9f1cd2c212e7a6335778faaff5833 \ + --hash=sha256:df37b620684e19b5e25724412518ccafc3b1a49cdac706fdbd2f983fad943450 \ + --hash=sha256:e1cc2bfaee8c214f06080a7c7d5772419b8a1108e8e5349236189811823fb02a \ + --hash=sha256:e29347c142cf6e99e0dff5e2995ead1d50fa3b51bf37a7c726a7ccfe5419745a \ + --hash=sha256:e4f5cf4dc72a71c4cfa9751b4950be22f733626670230d46e7d606592aa22d59 \ + --hash=sha256:e724a7b6091f0b1ac064f9d1b15ff9ec52e6033a86cdae649e5f086e32a3c0db \ + --hash=sha256:e87046c8ff77a8decdb6a41d8ab25824b47531b2da933aeab0c1e21c7acff329 \ + --hash=sha256:e95c8def4b81c5d68d5cf1f54c07acd7c0d2577af244e5b6da802120825737c6 \ + --hash=sha256:eb324e2009fb54db30a071dad7caf6998ee2879c4704007efb244514dad1fec1 \ + --hash=sha256:ef60869969180ec2464f1349aff07138ae35ca2200f0946cb3552e49e8f301a8 \ + --hash=sha256:ef692a24087a699c0a4a26af45e746e0c1eae2116f6d8a5ff91d8aae2b867b45 \ + --hash=sha256:efc21a454892828368b11c2c780de0ff8bc991f73f6b99c6b66e56205470929b \ + --hash=sha256:f001b571ead90ca1770f1e616db255351a1703317f20374c361ef22f12c06d09 \ + --hash=sha256:f2a7966bda23dd85051f1661ce0ace38d6890e05ec6c357ecae9d2479cba377e \ + --hash=sha256:f2ebb54b3f932210503072f09974b4fb574d823e497a944adfdcd140a6a00255 \ + --hash=sha256:f2ed8b64dc0c651c0f5a9c926777719770021251b8f336d97c4b80b660836ce1 \ + --hash=sha256:f375db73a39f5cf83696d500e21a67f418dc9a988955756f254be8f03b7b3651 \ + --hash=sha256:f59c7673465908cbe506117176156c127f29f917677afceada34957179221d91 \ + --hash=sha256:f8d40ce41991e9d56fab4f5dc4a51fe59bc3b5c77c27f4b148963064d00232e8 \ + --hash=sha256:f9033b43f511f27547c557dcaba0177649e10a3725336ccd2cce0fdc1dc4850d \ + --hash=sha256:fba47bc2c3d7303c3d027c6cf4d07626c37b1314ac81f5820c31032e0ca1f677 \ + --hash=sha256:fbdc5ec49f9ca3cd24955cf3520b10a4d4c901ba2572094c84274e9e7eb30534 \ + --hash=sha256:fce9523df31cea6284f3e2c479876750d7687cf671d7b25d32b19effc0e86441 \ + --hash=sha256:ff75a7537413a86e7cafe98e0e1d6e3dc4b15c6349896e7d5c6b881bfdb6d550 + # via litellm +aiosignal==1.4.0 \ + --hash=sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e \ + --hash=sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7 + # via aiohttp +annotated-doc==0.0.5 \ + --hash=sha256:117bac03a25ede5df5440e855b32d556049ca169ead221505badf432fed4b101 \ + --hash=sha256:c7e58ce09192557605d8bbd92836d7e1d520ac9580096042c0bfd197efacf1bb + # via fastapi +annotated-types==0.8.0 \ + --hash=sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7 \ + --hash=sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0 + # via pydantic +anyio==4.15.1 \ + --hash=sha256:6152fdbbf9a77fdec97731721bebf7c4c44f7c29b424b0065826173efc7ed101 \ + --hash=sha256:9f28306018cbd6d329e64a36d58256edff76dd996fe423bc957326e578b82a94 + # via + # httpx + # httpx2 + # mcp + # openai + # sse-starlette + # starlette +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 + # via + # aiohttp + # jsonschema + # referencing +boto3==1.43.122 \ + --hash=sha256:c923650d09e4c445564ca14d5ce89466c3083884b6f6c189f0f445fc17f02eb5 \ + --hash=sha256:cca51b3650080594a1df344b8a2e76007eab6d5fa50504a0b622dfdc14cdeaa1 + # via litellm +botocore==1.43.122 \ + --hash=sha256:2fc53b68b35314b1738cad46e6170d0556496863913451428fc3afccb8c7fa95 \ + --hash=sha256:668e608edf8847fc4c3c6b38688e183c3bcf19b8a1f7f58d33c03a6f3039bd49 + # via + # boto3 + # s3transfer +certifi==2026.10.23 \ + --hash=sha256:a9895e6e2758b371e0545e321a3a8fd1fcfd9829ada8824a936dfb16aaaf36cd \ + --hash=sha256:e9b54de76e530bb6cf0ccd036787103acb58fd42ba930ea8bf948ddbaa2f61d1 + # via + # httpcore + # httpx + # requests +cffi==2.1.1 ; platform_python_implementation != 'PyPy' \ + --hash=sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e \ + --hash=sha256:06c72bb76605a4b0cd0aad6930b69d4baf7dd5d806cfc409b824191099700e66 \ + --hash=sha256:0beceaabe56af686895136a2de78db54ecd8e4046b236b8fd6d6cb61389e9bf2 \ + --hash=sha256:154852545011f779917b11c78db2358d095da62a9a172b78ad0a583ee5adc0d0 \ + --hash=sha256:194cffa889098ced9976c3fc6340305e43f6303657d298da55366907c05c22d6 \ + --hash=sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971 \ + --hash=sha256:1a18a57b58cfb21fc28d72e876acf10eaed67a1ed96226f92af4df681d571c4c \ + --hash=sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d \ + --hash=sha256:1dea0e4d7d4f11f619fe8c1d76caf49e24405b4b5743c0e3be16a500ecd930c9 \ + --hash=sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517 \ + --hash=sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735 \ + --hash=sha256:246fa40ce8645a614ff682e0b70f37134e460eaf93a775e0cbe3cca585a67a80 \ + --hash=sha256:25792eac27877609e7bb06d42ff88278a6624fff2ba9bbb523c09616b117e80f \ + --hash=sha256:27350daa11d4f10c540e6e89dada4c54feb7256ad03e9a4dc075ebad7ba360d1 \ + --hash=sha256:28907ab9bfb6aa13184cfc17c6b8e1023c5ab6fd7076d8c20a35e59fe04f8f29 \ + --hash=sha256:2ae64be792b8966f2c69538199728b290e34726562896df1e5dc8ffd8d8188e8 \ + --hash=sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c \ + --hash=sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e \ + --hash=sha256:3222ba5d678f80a030e6afbcc33dc1ae5cb45facabb61cee2c7016b8432fde48 \ + --hash=sha256:3311ed60d36f83378794e1009ac6258bafbf81f7888b4caa7b35a521e3f95813 \ + --hash=sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac \ + --hash=sha256:34e261f78cb6ceaaa36f42f2613f4380d94d9c759a9c73c769ee6e0247364632 \ + --hash=sha256:363e05fa78e15116c3c32c210ee36884fd6b9afa6d440e47112c3bd511d64cb6 \ + --hash=sha256:398aff33cee2767e3e781d2554c54bd0dff386bb437581e0d8011fde1a942ec1 \ + --hash=sha256:3d22a20b1fb1632cc72c22f95f7b0d2961c3e1c235f245ba4c606c4771035659 \ + --hash=sha256:42a494cee34437f05546455144f2b5d9ac09b1face62bcfce597d2e521066688 \ + --hash=sha256:42e2f76b9455f5a9a844f770bf3e200ed3da0e15f5df3db9c31fe80b04b3d004 \ + --hash=sha256:42f6930c31dc7f50732c9ae793c2786c7b6b044195967bbdde40bb9be81c4cc0 \ + --hash=sha256:456a61fa52d579ebf9df2e9552ead5129855dbaff6c1e5a9b1bc408809bdc062 \ + --hash=sha256:471cee653ae88de62096552e6d24ccb4a5adb8c8c9f10b5054d0122c15bf2779 \ + --hash=sha256:49cbc70e6542d4ccccb936558d1064a8012541e78f821f955cff24e357776c94 \ + --hash=sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50 \ + --hash=sha256:4be96343e422f2dfcd12ab5c9f5aebe03f82f737c6bffeca6830b3875cb44aab \ + --hash=sha256:4f42141fc14250de6dde5ee7ea4432be017252d91f19c5ad043c084cea629cac \ + --hash=sha256:507a24c282e0f42f8ed737cf048572cbf580468da5555764a8331735e9c736b6 \ + --hash=sha256:51b31d1c98274844cfd7838ce00bfc27c7423a4dc00fc0772fc3331c2cc90676 \ + --hash=sha256:58acb8ab8e295e6c5ea12f888cbb13cf21511ef2a3303a23f4325c29d17fe5c1 \ + --hash=sha256:5a59cc1c4442bc3d5c703bf720b51138d0bfc173618807c9ee2490a7541dd3d9 \ + --hash=sha256:5bb4e7ea95dcd6a014a6fef62e62467d67d8e582326443f3d68e71d6320a9fcf \ + --hash=sha256:5c58fe613dc5e5336357eff555824a314d8e43282600435c8d1cb6a7a2fedd13 \ + --hash=sha256:5e7cecbaadb83884793e05828cee59b210b24583b9c7425d0ba6a754fe22eb4e \ + --hash=sha256:616f097f2fe415bc92a247f02e11f634e1f9e9a83d327e3c915c15089c87869e \ + --hash=sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973 \ + --hash=sha256:64faea20f4e2613363a1a9b9c7dd73058f3ecd00133a511e72ad7c511658f527 \ + --hash=sha256:661c298b4821edebead0c91edd2b00374d67ad7c5a1f7a91d4442633b79d6a72 \ + --hash=sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890 \ + --hash=sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c \ + --hash=sha256:6e192623c49c94421616a5778fba35cf0d5a8d000650c1967ef4448ee5cdd990 \ + --hash=sha256:7225e4514edb64eb6740324353e0da0711954fd8d7da4576755b1c6e09b697cd \ + --hash=sha256:75f80557d1389eddbd0de2681f6a390a0c5338c31ddaa821381c203fc3fd50d9 \ + --hash=sha256:770de9db11e84213beec501cfcaa013b019820ca881e03344dea5844f7876d94 \ + --hash=sha256:7750c6449dff7864bb9bb27ddfb0267756189201a3afc911d82b3caacd70dfc3 \ + --hash=sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80 \ + --hash=sha256:7ce713ace7c0e4520535b42b77eaa742c16dab813978064913e5a3cf82973b41 \ + --hash=sha256:7da0c5eff80f0197f3b3d1232ec5a682a9325f4ae9016a78f5f5ca35f9ced1f5 \ + --hash=sha256:7dbb61fe3a7699468030f71bbe5f8a0e326a151daa91beb11a6fc1f980c55e1c \ + --hash=sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a \ + --hash=sha256:8ef53b2de9bcb9197d31854256575d59dbac0cba72ac627bb291ef5eceb74be4 \ + --hash=sha256:937c0052c05a31ca1daf18de3158eed4dbfcb9cc107adbea227728d647be701e \ + --hash=sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6 \ + --hash=sha256:9f8d177621de5cb38ee3e731eda45d421db093ec0739f46a5594babda7987a98 \ + --hash=sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b \ + --hash=sha256:a48d62ab9d6f4f98c983223a547af44be6ca3691074c31cecced6facd3ba2dc1 \ + --hash=sha256:a4f00aa42f75d6e4595e8866e748cc1705adc0cddfeb2ca86d0d03993d63ba03 \ + --hash=sha256:a6e721d4b0e45d5b65e87534470e67b18dcd092c83f68fba09f152b9cbc061af \ + --hash=sha256:a730a083190634c65cca36ba5f489531576ebd79bcd5c8e172130f6453127231 \ + --hash=sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2 \ + --hash=sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3 \ + --hash=sha256:ab36d55f9ed2d067327667c2fea18dda018eb628dd6347aa01dda6cf1f5d3836 \ + --hash=sha256:ad2c86c495b899d862ea0f4b42891b8713a3bd45dd4105c7fd51c2a72f39f3a5 \ + --hash=sha256:aeae0e330c9f6acd681f647d46cefd30c29f93e3392882e792e82080c9691399 \ + --hash=sha256:b0431303acaea1089ad4b3e9ce4e6518193def1118d4073ca848635ee4ea2e96 \ + --hash=sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e \ + --hash=sha256:baed1e86cc735622097354b9d1281406caf42ff42a886d29faa8e8d1630333be \ + --hash=sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf \ + --hash=sha256:c26608d2222fb1e94487e4a387d85f13eb55d5ed725cb25a0c589ac4ee60e7bc \ + --hash=sha256:c7659f22557c5a0bc4855cd635f55edec690cc008a40768527762cb9fb263455 \ + --hash=sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0 \ + --hash=sha256:c8d2c9fd1f2d16f780d15127abb050d13d1a76c03a4bd87d7e4980e45e511e12 \ + --hash=sha256:ca82be1a1d406ecfe1d25dc16cb33488e5a16bf4438c9fb590484ea29d92478b \ + --hash=sha256:cc572dace3f60ef98d7b12ff411d20f5362feb31a0439eab0085bbfd349982d7 \ + --hash=sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692 \ + --hash=sha256:d28630f5854ab07ab1fd4aba756de52326c82e6be15d414b12793f1975048b54 \ + --hash=sha256:d9c275eaacd24aa73f94ffd6de08fc3f932424d8b6c376f4bed7cde376fe7bc3 \ + --hash=sha256:da0e573f9f97159390c89d9f1a9e41908b66d408cc5b58d08cf3847d844c531b \ + --hash=sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be \ + --hash=sha256:dddad92b554513a31f272570678ba307fb9f618f05e3d4a5eacafff9eae03e1d \ + --hash=sha256:df423d40ee8654634421812bc3b196da3f9bd7d32929da813f8394c4348a5358 \ + --hash=sha256:df913725b79db7bcf03448f36b7bf8815363417d5b58deecf9305e3e30f0f21a \ + --hash=sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7 \ + --hash=sha256:e2d65b31f36619cda3999b78b2aa9632e76b78448e7a56fc4240824200e7c4fc \ + --hash=sha256:e6e8cff14d6fb0be70a09c0bdc58096f501952d04624ebf867e0e56da2df8960 \ + --hash=sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125 \ + --hash=sha256:f24fb43132a4c6b4cb4eb029492919b2db645be6808d738f244fd146c03c32cb \ + --hash=sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a \ + --hash=sha256:f5cfbc5fe74540d335175b656c725d74d90e3730c626d92575eea35029d9afaa \ + --hash=sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf \ + --hash=sha256:f8ec5e643a9a937f64e1999eb9f75d072263751912dc5cd06d3c85f8f44be7c3 \ + --hash=sha256:fb92203a88b3d3053034db775110081c49d28be6551923805e039924093761e4 \ + --hash=sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264 + # via cryptography +charset-normalizer==3.5.2 \ + --hash=sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e \ + --hash=sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf \ + --hash=sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5 \ + --hash=sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56 \ + --hash=sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26 \ + --hash=sha256:0891b9d3903c5571c03771ca669a4b0ec5618ca722a5c957d3d29cd4e5062848 \ + --hash=sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718 \ + --hash=sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93 \ + --hash=sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640 \ + --hash=sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3 \ + --hash=sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875 \ + --hash=sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e \ + --hash=sha256:1461ac396c4fdb983a675f20aa555624f0ee18ac83d832b9244ffff3d8055275 \ + --hash=sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204 \ + --hash=sha256:15bb4005af6320d259dc7593ca84a38d7fe06a421dbcf7b910ae23979101e787 \ + --hash=sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234 \ + --hash=sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3 \ + --hash=sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98 \ + --hash=sha256:195c26fb65950f8fce54e26349852b7bdd7c5f120aeefbcc440b8a20faaed4a3 \ + --hash=sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187 \ + --hash=sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d \ + --hash=sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f \ + --hash=sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7 \ + --hash=sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011 \ + --hash=sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f \ + --hash=sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869 \ + --hash=sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1 \ + --hash=sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d \ + --hash=sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847 \ + --hash=sha256:28a15fdad492a99b6eccfaaed66ef3f74050680545ea61ec8b2f4c538f1f1320 \ + --hash=sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9 \ + --hash=sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93 \ + --hash=sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd \ + --hash=sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00 \ + --hash=sha256:2cc961b171b3f3440f410489ab3573e86aea8736134ebbb40ea1338b7f0831bc \ + --hash=sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0 \ + --hash=sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09 \ + --hash=sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac \ + --hash=sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621 \ + --hash=sha256:30fcd120b732aa79317f08dee04d7de0847822e4cf7ee0e9f445bb958832252c \ + --hash=sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8 \ + --hash=sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a \ + --hash=sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51 \ + --hash=sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0 \ + --hash=sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef \ + --hash=sha256:3d14b50de6bf4d0edf857a9386836846f982b8f524e188e2e68b96d702bcf4aa \ + --hash=sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6 \ + --hash=sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649 \ + --hash=sha256:3ddacd27458c45bdacd6bd6db644bfb730efbf9e830310186e3045c9c5be8fb2 \ + --hash=sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229 \ + --hash=sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e \ + --hash=sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd \ + --hash=sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115 \ + --hash=sha256:447441e76ec720b15e64418d32e092297340387053047c7c694f579efb0ee1d9 \ + --hash=sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c \ + --hash=sha256:44bd4fbb29dfbeba60e7d2bd000c59e4b21ddb3cc53912b14048d37092706d7c \ + --hash=sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab \ + --hash=sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253 \ + --hash=sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995 \ + --hash=sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438 \ + --hash=sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0 \ + --hash=sha256:50e3adfb96fc189eb27b1cf62d3b598b89b4bb0420d93a3d3e42e137409011be \ + --hash=sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b \ + --hash=sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7 \ + --hash=sha256:55ea99acb17b9325618de155a0cd6a2e8f5d10be008113e1d433bbb58db543b2 \ + --hash=sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a \ + --hash=sha256:588461c2e8384d309bd63e5826019b6977bc66d629b99ac8737bb795d7b2cb5a \ + --hash=sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a \ + --hash=sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c \ + --hash=sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5 \ + --hash=sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37 \ + --hash=sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e \ + --hash=sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4 \ + --hash=sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800 \ + --hash=sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055 \ + --hash=sha256:619799369eeef6366ed3e8755a5670f4f2f0fb6b30a0fd7264dc0fdc2357058e \ + --hash=sha256:62588a277bfb59def052abd940703fa35107152bf479781a878617d60faf8fb5 \ + --hash=sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c \ + --hash=sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b \ + --hash=sha256:68eb192d85ab8e5f6ec69c2bc6ac0179fbf04a5ac1569d12fbef74883fe102d0 \ + --hash=sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80 \ + --hash=sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a \ + --hash=sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4 \ + --hash=sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2 \ + --hash=sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58 \ + --hash=sha256:75a3ceed0724d625d64b86ca20aba182e4df462e04c2414fc941c0f523f06aac \ + --hash=sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc \ + --hash=sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639 \ + --hash=sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf \ + --hash=sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d \ + --hash=sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f \ + --hash=sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c \ + --hash=sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc \ + --hash=sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4 \ + --hash=sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253 \ + --hash=sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade \ + --hash=sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858 \ + --hash=sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26 \ + --hash=sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96 \ + --hash=sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8 \ + --hash=sha256:8a893cc101149f80a653f82062ebc95b34525a2614382e1da5458fe7c6997249 \ + --hash=sha256:8b2bfab86aa71ae13aa41a6a26aab338e0db2b8bc75434b05aea89e011ff35a4 \ + --hash=sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13 \ + --hash=sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1 \ + --hash=sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03 \ + --hash=sha256:93223adc95033dd47133a46ccfc316a0139176fd79085762e27202ec56018f03 \ + --hash=sha256:9373ad13ef0d2c0fb761e04e55bfdee5a08b52cef2c882c8fbe9935b1517152e \ + --hash=sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364 \ + --hash=sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4 \ + --hash=sha256:9bde855991b7e362c146535e3136a50bfaffc0487d38b33ca7e5edefc6e23849 \ + --hash=sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0 \ + --hash=sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a \ + --hash=sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036 \ + --hash=sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3 \ + --hash=sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21 \ + --hash=sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3 \ + --hash=sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e \ + --hash=sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413 \ + --hash=sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21 \ + --hash=sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346 \ + --hash=sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429 \ + --hash=sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685 \ + --hash=sha256:b736353c0a625bbd5fcec108576e2385db3496f4f771f785ff32e108d3c3bc45 \ + --hash=sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f \ + --hash=sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c \ + --hash=sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d \ + --hash=sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad \ + --hash=sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400 \ + --hash=sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb \ + --hash=sha256:c6708715abcf3c73b99508253e961a9967f02fe536532834149574eda6de0d1c \ + --hash=sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc \ + --hash=sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c \ + --hash=sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74 \ + --hash=sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf \ + --hash=sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604 \ + --hash=sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f \ + --hash=sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105 \ + --hash=sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a \ + --hash=sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d \ + --hash=sha256:d4a7319f304a774bed22115bc891618e45f85065ab44ea6acd07d274e750519a \ + --hash=sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1 \ + --hash=sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5 \ + --hash=sha256:d913de495d90407cd859d263bee2e5d1a4ed3eb6573c04e70d9ec619a7cbed7f \ + --hash=sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e \ + --hash=sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709 \ + --hash=sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874 \ + --hash=sha256:ddf19c062bea7a0cc80f519243d2c01dd091be0cf952a0750d4ad576709559f5 \ + --hash=sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc \ + --hash=sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95 \ + --hash=sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd \ + --hash=sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0 \ + --hash=sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d \ + --hash=sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3 \ + --hash=sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c \ + --hash=sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3 \ + --hash=sha256:e80e6c2f55656b4824d72065abb4ddd6a525c74bd78a0aab5d9fc2cf4fb5af50 \ + --hash=sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491 \ + --hash=sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5 \ + --hash=sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5 \ + --hash=sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655 \ + --hash=sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288 \ + --hash=sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd \ + --hash=sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084 \ + --hash=sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d \ + --hash=sha256:f5833ad231be5eb6553de524a70f48d71b2c8563101750531e0b80184e175cd4 \ + --hash=sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915 \ + --hash=sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1 \ + --hash=sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd \ + --hash=sha256:fc14a032f813bf5fe624d991960ea83e9715adc27e4c1830a2361eb1d02ac341 \ + --hash=sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424 \ + --hash=sha256:fd1fbe0f116b6e55da77aca2c6ddcddcfac2186cbf78bdebf40fc156efca389d \ + --hash=sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f + # via requests +click==8.5.0 \ + --hash=sha256:255bc9599cf7748b4b1a446ccc735421bd08a2ae529a8b88597d3de5664ee360 \ + --hash=sha256:ba0d2089de75ea0310e2dde03160e6ca10009947fb95a182f9b54021bb272e34 + # via + # huggingface-hub + # litellm + # uvicorn +colorama==0.4.6 ; sys_platform == 'win32' \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via tqdm +cryptography==50.0.2 \ + --hash=sha256:0ddc924c04591c2811ca024d62ecad4f7f6f08af8939c211438f48a16bd23602 \ + --hash=sha256:0ec5f09541743261e66e291b4a0cbf0fb2997aeaab6d9e9c740b9dba1b58d1c2 \ + --hash=sha256:0ecbc5652bdb6fc9eaf89a7d196e20941adfe812f43bc4ca05d9150496821047 \ + --hash=sha256:1981f1db4630889b9ef7803fadef12b056f428cb6b85c27ba57b774793b6093c \ + --hash=sha256:1ba34f04897fcdaa73f74145c25f3ec146fbd56593853e88adc2e811303c5f42 \ + --hash=sha256:241449bf940a5d27309bd317e6f9a2af6932113818bb2b8f5c59ddc7ef16da18 \ + --hash=sha256:25784ce8b9621c90c643efb9e1e2162ab3b0224cae446ad5e70e7fcb1ce18b51 \ + --hash=sha256:3dc4fd8058cea1644971207d530e1a03a184a805ffc8ebdddf0599d78a331b81 \ + --hash=sha256:4061c0079120205fb760c58acab6443e217307dcf05e3702cf970e0689972856 \ + --hash=sha256:4a20ce1e5cb4284a86692fdcba7cb8754185c6b2e5c56fcef3751cf451d3cdc2 \ + --hash=sha256:4e81d95e5bafc2d6e34e4bed780e53e4d5b9a2f928573428aa4d35fbec1eb0de \ + --hash=sha256:58a0c478eeca76fe5e07993c5a0703def34a6dc6a0cda4f5564639b33112ffe7 \ + --hash=sha256:58ddb5a8e3179d12f19e4ea34d2d32e9d63a4baa142c875c1eb59f41b7243acd \ + --hash=sha256:630ebfea3bf689d075f82316324ff7433dc447fe6bc1bfc76524b74b4a9567d2 \ + --hash=sha256:6f8700550aa1474a91e5dc07049c46f98b423b5b1ddd0483e0b51362eeeaf5be \ + --hash=sha256:78198641e5be9521beea5aa782bb551a58068d10e6eb04c9c680c1b69f2e7d45 \ + --hash=sha256:79def8d059362e7831389ed3be0ecdf58a89386e1271e35dd9f5af84e81bffd0 \ + --hash=sha256:7a8701d6b584d76e909e3d305b7d126b41439876a5aaf76cddc67fc230eafa2e \ + --hash=sha256:7afa5a6602a9f29af1f3a2965f831bae7c9d5d597b7cbb716d41ab3b7d89879c \ + --hash=sha256:7b46165bb56eb4704e2eaaf86f3c940d19154535d9b0ca7d6d590b04060e00d5 \ + --hash=sha256:7b75de3c8b3be1cdb1052747c929440c3eea46c1bc2cb8a6e3a48388e9b7b452 \ + --hash=sha256:7c6d0330c472d96f6a6afe24d80dfdf15176c33096f0a4397ae4c60f3dd3be48 \ + --hash=sha256:828d49b0ff5a0e3975865571c5d91dbbdd0d38d8289b249a163e9425413a5e05 \ + --hash=sha256:84f964e537f916e2cc85199e5a88742e964939b575ac8598b3f9d6cc416cdaf1 \ + --hash=sha256:85d0d9a31b9098e98534226d5686b47264b95e62ce459dc2e62fdfc809f9fe93 \ + --hash=sha256:87e9ce85beb6b328ba370cc6e6aea483c92617b4c95b1d33a49297eb662bfb04 \ + --hash=sha256:8c71ba2cd31fc93748c38e1b613200ff1c2665cbfd5341fe3a61cfde35a1430e \ + --hash=sha256:92e665960f25fcdc73725b9cec7a3824f279ba97a98653afe9ffac2e43668f67 \ + --hash=sha256:94e5e9f108ee10471288214d3d233fbfbb492840a8457eb85178d643ddeb32c7 \ + --hash=sha256:9c8402a82ea0dc4ceeab793db05f0fafa8ca139ca34fcde5df0f596103c74107 \ + --hash=sha256:9dab55f57c74c3cad24c323bacbbd04be4705ba6eb0d92e920b1fc4837ed5079 \ + --hash=sha256:a582ab2ae1d34f67112cadc86702774c9ea4374df6bca6afe672817203c99134 \ + --hash=sha256:a6557e5f38e065ca9fbdaf7cfc7435ecb1d113aa81a022d1b51921ee7432e227 \ + --hash=sha256:a9f7355e6fab51f6c369b86fb7571cffa05edee2c2121e0380a37fb9ac1cd5c1 \ + --hash=sha256:ab50ee449bf968271e820086f10a33d101dd060370abc10bcd22279be2656539 \ + --hash=sha256:ac9ed99d81760c62fe89d5f0815cdfa1ba9a35141cf30f1c2d044f04b4803d2e \ + --hash=sha256:b13478603dcd0a2479ff8e87e2c19a7d525734686fe3c49542472293a204212d \ + --hash=sha256:c423ab384a46c4dff7217b2ea5ba2e11cffdeab6441acd04cf65a369caf0366c \ + --hash=sha256:c5e67125c7dca78d199ec4e116aa93dbb83494808ecbb8211a2cb09b1bf41dbd \ + --hash=sha256:c71be1cbfa5cd9a41ee452acf1eccd82b2c05950358b106ec8ceb83411d1a020 \ + --hash=sha256:cbc8738fd8526d80f35cb3a40d41f41a2e7030bb3b18b09a6778ef63d291c2fd \ + --hash=sha256:ce47f66801c20ec6c6632453bb5960fe38939e9306970b48b3a5a26de7745d94 \ + --hash=sha256:d370b8d1dfcdf7130178137f6fbee6140774a1acc6cacefc4b42643ec11d0a3a \ + --hash=sha256:d38cdff612d06fa6a32840d5e1b1f7a27cee4a349aa9085d94a67789d6bfd408 \ + --hash=sha256:d8947001be83df1394050758ce0e745dd74fb134eef0a4b5124208dfc3a68c37 \ + --hash=sha256:deb9fde5c60e437ee4821bc9bc39ff31b42135c27e1dc61ef0a629389c1de62e \ + --hash=sha256:dfe9763530994147d9af1def057a5b9658b00e8f8fe8743d144d1e0911c2e454 \ + --hash=sha256:e105ab60406787da31fccc883fc0f733af1efd78f0136a4599692c4083a73d0c \ + --hash=sha256:e275096ea1e60cc595cda2836fd4a6c725d1125108b868be17f53684d164e2cc \ + --hash=sha256:edc3342adf8f697fc5f59c887a304356f147b397809440ed64e2fa6af2f50f37 \ + --hash=sha256:ee247f5c245c9a2fe7c8e2214e295918838e44e00a45a6718451e4004219e767 \ + --hash=sha256:eef4c2f3423810b3070ab391f85436d2f8bbfcb286ac15cbc73190b3563b1f1a \ + --hash=sha256:f21e8a22c8605750c7af886bab299a363721264061b4ac0a30efb73cfd58efc5 \ + --hash=sha256:f265528741e048bce55c3463ed721fb0aa45a5888d8add8cfeccb3035451bbdc \ + --hash=sha256:f2f9bd7f90c64fe89253f0a2c05e3c4856072660429ce8831b4235bf29403a67 \ + --hash=sha256:f785f6161f202ab04d8ca194158968798e480ca058943907972da5f12e2881e8 \ + --hash=sha256:f9f6143a8c75945eb960d9eb98905a441394abfa24afaae239d514ffb2586480 \ + --hash=sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb \ + --hash=sha256:fdd28f912fccfec1846a94e2e1e8f9b0012f557f0c46fe4f3eb0d7a87afcf90b + # via pyjwt +distro==1.9.0 \ + --hash=sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed \ + --hash=sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2 + # via openai +fastapi==0.162.0 \ + --hash=sha256:3785963de305dd09912426cb81f2d230fce98ab3521cdfe97265c8d14983128c \ + --hash=sha256:6a22c1e2e6e32e0633ee7e170f00009a29b8228b16feb219ee42f32fd8d88a8f + # via -r integrations/isolation/acq-kits/claude-code/files/home/claude-code/requirements.in +fastuuid==0.14.0 \ + --hash=sha256:05a8dde1f395e0c9b4be515b7a521403d1e8349443e7641761af07c7ad1624b1 \ + --hash=sha256:0737606764b29785566f968bd8005eace73d3666bd0862f33a760796e26d1ede \ + --hash=sha256:089c18018fdbdda88a6dafd7d139f8703a1e7c799618e33ea25eb52503d28a11 \ + --hash=sha256:09098762aad4f8da3a888eb9ae01c84430c907a297b97166b8abc07b640f2995 \ + --hash=sha256:09378a05020e3e4883dfdab438926f31fea15fd17604908f3d39cbeb22a0b4dc \ + --hash=sha256:0c9ec605ace243b6dbe3bd27ebdd5d33b00d8d1d3f580b39fdd15cd96fd71796 \ + --hash=sha256:0df14e92e7ad3276327631c9e7cec09e32572ce82089c55cb1bb8df71cf394ed \ + --hash=sha256:12ac85024637586a5b69645e7ed986f7535106ed3013640a393a03e461740cb7 \ + --hash=sha256:1383fff584fa249b16329a059c68ad45d030d5a4b70fb7c73a08d98fd53bcdab \ + --hash=sha256:139d7ff12bb400b4a0c76be64c28cbe2e2edf60b09826cbfd85f33ed3d0bbe8b \ + --hash=sha256:13ec4f2c3b04271f62be2e1ce7e95ad2dd1cf97e94503a3760db739afbd48f00 \ + --hash=sha256:178947fc2f995b38497a74172adee64fdeb8b7ec18f2a5934d037641ba265d26 \ + --hash=sha256:193ca10ff553cf3cc461572da83b5780fc0e3eea28659c16f89ae5202f3958d4 \ + --hash=sha256:1a771f135ab4523eb786e95493803942a5d1fc1610915f131b363f55af53b219 \ + --hash=sha256:1bf539a7a95f35b419f9ad105d5a8a35036df35fdafae48fb2fd2e5f318f0d75 \ + --hash=sha256:1ca61b592120cf314cfd66e662a5b54a578c5a15b26305e1b8b618a6f22df714 \ + --hash=sha256:1e3cc56742f76cd25ecb98e4b82a25f978ccffba02e4bdce8aba857b6d85d87b \ + --hash=sha256:1e690d48f923c253f28151b3a6b4e335f2b06bf669c68a02665bc150b7839e94 \ + --hash=sha256:2b29e23c97e77c3a9514d70ce343571e469098ac7f5a269320a0f0b3e193ab36 \ + --hash=sha256:2dce5d0756f046fa792a40763f36accd7e466525c5710d2195a038f93ff96346 \ + --hash=sha256:2ec3d94e13712a133137b2805073b65ecef4a47217d5bac15d8ac62376cefdb4 \ + --hash=sha256:2fb3c0d7fef6674bbeacdd6dbd386924a7b60b26de849266d1ff6602937675c8 \ + --hash=sha256:2fc37479517d4d70c08696960fad85494a8a7a0af4e93e9a00af04d74c59f9e3 \ + --hash=sha256:33e678459cf4addaedd9936bbb038e35b3f6b2061330fd8f2f6a1d80414c0f87 \ + --hash=sha256:3964bab460c528692c70ab6b2e469dd7a7b152fbe8c18616c58d34c93a6cf8d4 \ + --hash=sha256:3acdf655684cc09e60fb7e4cf524e8f42ea760031945aa8086c7eae2eeeabeb8 \ + --hash=sha256:448aa6833f7a84bfe37dd47e33df83250f404d591eb83527fa2cac8d1e57d7f3 \ + --hash=sha256:47c821f2dfe95909ead0085d4cb18d5149bca704a2b03e03fb3f81a5202d8cea \ + --hash=sha256:4edc56b877d960b4eda2c4232f953a61490c3134da94f3c28af129fb9c62a4f6 \ + --hash=sha256:5816d41f81782b209843e52fdef757a361b448d782452d96abedc53d545da722 \ + --hash=sha256:6e6243d40f6c793c3e2ee14c13769e341b90be5ef0c23c82fa6515a96145181a \ + --hash=sha256:6fbc49a86173e7f074b1a9ec8cf12ca0d54d8070a85a06ebf0e76c309b84f0d0 \ + --hash=sha256:73657c9f778aba530bc96a943d30e1a7c80edb8278df77894fe9457540df4f85 \ + --hash=sha256:73946cb950c8caf65127d4e9a325e2b6be0442a224fd51ba3b6ac44e1912ce34 \ + --hash=sha256:77a09cb7427e7af74c594e409f7731a0cf887221de2f698e1ca0ebf0f3139021 \ + --hash=sha256:77e94728324b63660ebf8adb27055e92d2e4611645bf12ed9d88d30486471d0a \ + --hash=sha256:7a3c0bca61eacc1843ea97b288d6789fbad7400d16db24e36a66c28c268cfe3d \ + --hash=sha256:7f2f3efade4937fae4e77efae1af571902263de7b78a0aee1a1653795a093b2a \ + --hash=sha256:808527f2407f58a76c916d6aa15d58692a4a019fdf8d4c32ac7ff303b7d7af09 \ + --hash=sha256:83cffc144dc93eb604b87b179837f2ce2af44871a7b323f2bfed40e8acb40ba8 \ + --hash=sha256:84b0779c5abbdec2a9511d5ffbfcd2e53079bf889824b32be170c0d8ef5fc74c \ + --hash=sha256:9579618be6280700ae36ac42c3efd157049fe4dd40ca49b021280481c78c3176 \ + --hash=sha256:9a133bf9cc78fdbd1179cb58a59ad0100aa32d8675508150f3658814aeefeaa4 \ + --hash=sha256:9bd57289daf7b153bfa3e8013446aa144ce5e8c825e9e366d455155ede5ea2dc \ + --hash=sha256:a0809f8cc5731c066c909047f9a314d5f536c871a7a22e815cc4967c110ac9ad \ + --hash=sha256:a6f46790d59ab38c6aa0e35c681c0484b50dc0acf9e2679c005d61e019313c24 \ + --hash=sha256:a8a0dfea3972200f72d4c7df02c8ac70bad1bb4c58d7e0ec1e6f341679073a7f \ + --hash=sha256:aa75b6657ec129d0abded3bec745e6f7ab642e6dba3a5272a68247e85f5f316f \ + --hash=sha256:ab32f74bd56565b186f036e33129da77db8be09178cd2f5206a5d4035fb2a23f \ + --hash=sha256:ab3f5d36e4393e628a4df337c2c039069344db5f4b9d2a3c9cea48284f1dd741 \ + --hash=sha256:ac60fc860cdf3c3f327374db87ab8e064c86566ca8c49d2e30df15eda1b0c2d5 \ + --hash=sha256:ae64ba730d179f439b0736208b4c279b8bc9c089b102aec23f86512ea458c8a4 \ + --hash=sha256:af5967c666b7d6a377098849b07f83462c4fedbafcf8eb8bc8ff05dcbe8aa209 \ + --hash=sha256:b2fdd48b5e4236df145a149d7125badb28e0a383372add3fbaac9a6b7a394470 \ + --hash=sha256:b852a870a61cfc26c884af205d502881a2e59cc07076b60ab4a951cc0c94d1ad \ + --hash=sha256:b9a0ca4f03b7e0b01425281ffd44e99d360e15c895f1907ca105854ed85e2057 \ + --hash=sha256:bbb0c4b15d66b435d2538f3827f05e44e2baafcc003dd7d8472dc67807ab8fd8 \ + --hash=sha256:bcc96ee819c282e7c09b2eed2b9bd13084e3b749fdb2faf58c318d498df2efbe \ + --hash=sha256:c0a94245afae4d7af8c43b3159d5e3934c53f47140be0be624b96acd672ceb73 \ + --hash=sha256:c0eb25f0fd935e376ac4334927a59e7c823b36062080e2e13acbaf2af15db836 \ + --hash=sha256:c3091e63acf42f56a6f74dc65cfdb6f99bfc79b5913c8a9ac498eb7ca09770a8 \ + --hash=sha256:c501561e025b7aea3508719c5801c360c711d5218fc4ad5d77bf1c37c1a75779 \ + --hash=sha256:c7502d6f54cd08024c3ea9b3514e2d6f190feb2f46e6dbcd3747882264bb5f7b \ + --hash=sha256:caa1f14d2102cb8d353096bc6ef6c13b2c81f347e6ab9d6fbd48b9dea41c153d \ + --hash=sha256:cb9a030f609194b679e1660f7e32733b7a0f332d519c5d5a6a0a580991290022 \ + --hash=sha256:cd5a7f648d4365b41dbf0e38fe8da4884e57bed4e77c83598e076ac0c93995e7 \ + --hash=sha256:d23ef06f9e67163be38cece704170486715b177f6baae338110983f99a72c070 \ + --hash=sha256:d31f8c257046b5617fc6af9c69be066d2412bdef1edaa4bdf6a214cf57806105 \ + --hash=sha256:d55b7e96531216fc4f071909e33e35e5bfa47962ae67d9e84b00a04d6e8b7173 \ + --hash=sha256:d9e4332dc4ba054434a9594cbfaf7823b57993d7d8e7267831c3e059857cf397 \ + --hash=sha256:de01280eabcd82f7542828ecd67ebf1551d37203ecdfd7ab1f2e534edb78d505 \ + --hash=sha256:df61342889d0f5e7a32f7284e55ef95103f2110fee433c2ae7c2c0956d76ac8a \ + --hash=sha256:e0976c0dff7e222513d206e06341503f07423aceb1db0b83ff6851c008ceee06 \ + --hash=sha256:e150eab56c95dc9e3fefc234a0eedb342fac433dacc273cd4d150a5b0871e1fa \ + --hash=sha256:e23fc6a83f112de4be0cc1990e5b127c27663ae43f866353166f87df58e73d06 \ + --hash=sha256:ec27778c6ca3393ef662e2762dba8af13f4ec1aaa32d08d77f71f2a70ae9feb8 \ + --hash=sha256:f54d5b36c56a2d5e1a31e73b950b28a0d83eb0c37b91d10408875a5a29494bad \ + --hash=sha256:f74631b8322d2780ebcf2d2d75d58045c3e9378625ec51865fe0b5620800c39d + # via litellm +filelock==4.2.1 \ + --hash=sha256:7be2662e9e826b9bba28afc0f843a123280d799a2ea44bb5d35ccec67905ae44 \ + --hash=sha256:c4c937ccac2a813cee448e662a56366cfb374c0f8702e75f295c412cc1c5d5a3 + # via + # -r integrations/isolation/acq-kits/claude-code/files/home/claude-code/requirements.in + # huggingface-hub +frozenlist==1.8.0 \ + --hash=sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686 \ + --hash=sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0 \ + --hash=sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121 \ + --hash=sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd \ + --hash=sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7 \ + --hash=sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c \ + --hash=sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84 \ + --hash=sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d \ + --hash=sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b \ + --hash=sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79 \ + --hash=sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967 \ + --hash=sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f \ + --hash=sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4 \ + --hash=sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7 \ + --hash=sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef \ + --hash=sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9 \ + --hash=sha256:1a7607e17ad33361677adcd1443edf6f5da0ce5e5377b798fba20fae194825f3 \ + --hash=sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd \ + --hash=sha256:1aa77cb5697069af47472e39612976ed05343ff2e84a3dcf15437b232cbfd087 \ + --hash=sha256:1b9290cf81e95e93fdf90548ce9d3c1211cf574b8e3f4b3b7cb0537cf2227068 \ + --hash=sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7 \ + --hash=sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed \ + --hash=sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b \ + --hash=sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f \ + --hash=sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25 \ + --hash=sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe \ + --hash=sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143 \ + --hash=sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e \ + --hash=sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930 \ + --hash=sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37 \ + --hash=sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128 \ + --hash=sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2 \ + --hash=sha256:332db6b2563333c5671fecacd085141b5800cb866be16d5e3eb15a2086476675 \ + --hash=sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f \ + --hash=sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746 \ + --hash=sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df \ + --hash=sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8 \ + --hash=sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c \ + --hash=sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0 \ + --hash=sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad \ + --hash=sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82 \ + --hash=sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29 \ + --hash=sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c \ + --hash=sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30 \ + --hash=sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf \ + --hash=sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62 \ + --hash=sha256:48e6d3f4ec5c7273dfe83ff27c91083c6c9065af655dc2684d2c200c94308bb5 \ + --hash=sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383 \ + --hash=sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c \ + --hash=sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52 \ + --hash=sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d \ + --hash=sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1 \ + --hash=sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a \ + --hash=sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714 \ + --hash=sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65 \ + --hash=sha256:59a6a5876ca59d1b63af8cd5e7ffffb024c3dc1e9cf9301b21a2e76286505c95 \ + --hash=sha256:5a3a935c3a4e89c733303a2d5a7c257ea44af3a56c8202df486b7f5de40f37e1 \ + --hash=sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506 \ + --hash=sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888 \ + --hash=sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6 \ + --hash=sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41 \ + --hash=sha256:6dc4126390929823e2d2d9dc79ab4046ed74680360fc5f38b585c12c66cdf459 \ + --hash=sha256:7398c222d1d405e796970320036b1b563892b65809d9e5261487bb2c7f7b5c6a \ + --hash=sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608 \ + --hash=sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa \ + --hash=sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8 \ + --hash=sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1 \ + --hash=sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186 \ + --hash=sha256:7bf6cdf8e07c8151fba6fe85735441240ec7f619f935a5205953d58009aef8c6 \ + --hash=sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed \ + --hash=sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e \ + --hash=sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52 \ + --hash=sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231 \ + --hash=sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450 \ + --hash=sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496 \ + --hash=sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a \ + --hash=sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3 \ + --hash=sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24 \ + --hash=sha256:940d4a017dbfed9daf46a3b086e1d2167e7012ee297fef9e1c545c4d022f5178 \ + --hash=sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695 \ + --hash=sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7 \ + --hash=sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4 \ + --hash=sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e \ + --hash=sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e \ + --hash=sha256:9ff15928d62a0b80bb875655c39bf517938c7d589554cbd2669be42d97c2cb61 \ + --hash=sha256:a6483e309ca809f1efd154b4d37dc6d9f61037d6c6a81c2dc7a15cb22c8c5dca \ + --hash=sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad \ + --hash=sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b \ + --hash=sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a \ + --hash=sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8 \ + --hash=sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51 \ + --hash=sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011 \ + --hash=sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8 \ + --hash=sha256:b4f3b365f31c6cd4af24545ca0a244a53688cad8834e32f56831c4923b50a103 \ + --hash=sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b \ + --hash=sha256:b9be22a69a014bc47e78072d0ecae716f5eb56c15238acca0f43d6eb8e4a5bda \ + --hash=sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806 \ + --hash=sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042 \ + --hash=sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e \ + --hash=sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b \ + --hash=sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef \ + --hash=sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d \ + --hash=sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567 \ + --hash=sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a \ + --hash=sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2 \ + --hash=sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0 \ + --hash=sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e \ + --hash=sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b \ + --hash=sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d \ + --hash=sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a \ + --hash=sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52 \ + --hash=sha256:d8b7138e5cd0647e4523d6685b0eac5d4be9a184ae9634492f25c6eb38c12a47 \ + --hash=sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1 \ + --hash=sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94 \ + --hash=sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f \ + --hash=sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff \ + --hash=sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822 \ + --hash=sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a \ + --hash=sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11 \ + --hash=sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581 \ + --hash=sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51 \ + --hash=sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565 \ + --hash=sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40 \ + --hash=sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92 \ + --hash=sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2 \ + --hash=sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5 \ + --hash=sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4 \ + --hash=sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93 \ + --hash=sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027 \ + --hash=sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd + # via + # aiohttp + # aiosignal +fsspec==2026.9.0 \ + --hash=sha256:0f08147951c8cb31d844c3547d631053b127863b60be04cf06e121333ee0e2fe \ + --hash=sha256:8dd6e646e99ea382bd85f97a45e6b526a442d79423a7dc673f1e2756d05fcb5f + # via huggingface-hub +h11==0.16.0 \ + --hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \ + --hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86 + # via + # httpcore + # httpcore2 + # uvicorn +hf-xet==1.8.0 ; platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64' \ + --hash=sha256:07a06d7481702616726c2d8578cfb00052a5b3f21beed6a674592bc837a10330 \ + --hash=sha256:10ed23b51dacf7917d64f335c25048deb470efa755e9989b218fc0531386138e \ + --hash=sha256:1ebaf248c9bef8bb0c9d1d8d71db1fdf0cac14f922cc7a936a81adbf12eb5f01 \ + --hash=sha256:23c262e9f5e137b18dadbce60becfeea84156b0d43119c320bffe260d32cd2fa \ + --hash=sha256:29dab7c904cd1914a0439c6e1306c12c7497c8bd32290fbe563ebf51ca4b6d6d \ + --hash=sha256:3e8934784425781f0f779b91044df441f3a7af4dab47375d7e3aeaecbb8eecb4 \ + --hash=sha256:3ecfe2934448cca55a4c42732b60f985266aecb241905945219b3d388aceb7ba \ + --hash=sha256:42b66fdc688eaa4ff3eb77dc9275e5a0f1258ecc9fdd083ddaf43bb49bec925b \ + --hash=sha256:56735c2d4f416d7473fc986586b26a8756e067832ca4b7fdaad32a0d6f2ce740 \ + --hash=sha256:62b056aedb89ac809f78940baf465fe553b70c8b25ee56890fbab3039fffec1b \ + --hash=sha256:7edeb21c5d381903ee5f4857fc746fa7b52a4b374035e8811ecfb67ee27add0c \ + --hash=sha256:8800e3444770f2c630b361bc6d5c6ebb770b7830646cf632fbb79d0e5bbc9e7f \ + --hash=sha256:92188598dedc1e1f5609bd718d4db8687a6c89915553912571e2f587892eecec \ + --hash=sha256:a584a7b3268da62f23c3187cc7201ca01f7b610985a36b1b6119c66bccb0383c \ + --hash=sha256:c74e3751cbcdae9222c5170e8d788e83201a03dc5e5f4308a20f17a5b6023b56 \ + --hash=sha256:e00d8f60170cd3dd55d98306e41dbaf28b27ff1bcfefbfa84279d197221be83e \ + --hash=sha256:f42940869572dc2b05dfe06f4cc398c6291503e086ddc4eddfb7a6ab9409ad01 + # via huggingface-hub +httpcore==1.0.9 \ + --hash=sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55 \ + --hash=sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8 + # via httpx +httpcore2==2.16.0 ; sys_platform != 'emscripten' \ + --hash=sha256:5c4358319f2602d984ad93182c9fee5160f22e9da7babdda870a5e7c4e2dc34f \ + --hash=sha256:c72cd0413563b17e1cd8354677dff887466f8ec2551679759e93126534428643 + # via httpx2 +httpx==0.28.1 \ + --hash=sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc \ + --hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad + # via + # huggingface-hub + # litellm + # openai +httpx2==2.16.0 \ + --hash=sha256:0d54c98128e8f2ff7fbbde0fca8c359e5f032edeaaaac443cdb7f31f685bcd7f \ + --hash=sha256:fd2c5d7909e8d86fe92d53020c310ca0e4e431b838c207c5754b9bbf0308d49a + # via mcp +httpx2-jsfetch==1.0 ; sys_platform == 'emscripten' \ + --hash=sha256:70a0e3eabfef7cce5ad9c629f7d01ca05e418f586646f4ddf14782e4c1454c60 \ + --hash=sha256:cb916b707601e69a07721aabc8f3f6659be3a6893bc1ff5c6f9e02241df2da32 + # via httpx2 +huggingface-hub==1.33.0 \ + --hash=sha256:04e434b06e100eddbce9a6e817d72693a7884b10a79bd67ab48080d5c07eb899 \ + --hash=sha256:367be21a201db9523eddf8aeac7048f2602c1b308691c97640d5e72ed188007e + # via tokenizers +idna==3.20 \ + --hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \ + --hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c + # via + # anyio + # httpx + # httpx2 + # requests + # yarl +importlib-metadata==8.9.0 \ + --hash=sha256:58850626cef4bd2df100378b0f2aea9724a7b92f10770d547725b047078f99ee \ + --hash=sha256:e0f761b6ea91ced3b0844c14c9d955224d538105921f8e6754c00f6ca79fba7f + # via litellm +jinja2==3.1.6 \ + --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ + --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 + # via litellm +jiter==0.18.0 \ + --hash=sha256:029da1f29852beac2f9001f20209b73b29b4d7bdc748c7f8028895769e2cc0d8 \ + --hash=sha256:0390fa550fcafbf69fb97ccb287bd71192f90410a1c7dd600ca4000aa9aabcf2 \ + --hash=sha256:04a484fce032a8b2c21dec0410a805d7b16573eb34297156a3b4d242c507d2b4 \ + --hash=sha256:04aa358fd3217dedd673e9331febe8cccfa4a00382e5372b39efcafe7447ff63 \ + --hash=sha256:04d67a44b040a6662a35edc9869030f7aa566bf5baaf3549c99d847aa44213e2 \ + --hash=sha256:04e210f5ddcccdbde484821040216a112381e6484abc549c20c38e9698ab07ca \ + --hash=sha256:07ae058bc052ead609b49bbae78c01bf4dee8f5f9d21705cbae9bfe59b33efc9 \ + --hash=sha256:0a41d8ef9f757fd5c11ce2fa56c9c4d008d857e97b6d0edfccbaacbd50830a75 \ + --hash=sha256:0ccf55f6fcdcee82fe40ae617e9d64b8e5f433fa6cb5bf7d2969e584e6df0e5d \ + --hash=sha256:118c1fd995f349f1cad0557f31d6860f336b4aeef7f002dedbc068027f68e2c3 \ + --hash=sha256:1277ac083a58d2f49a24ff9a28fd9876a6443a1992d4467a1db80fb45e354b18 \ + --hash=sha256:131446a60b54ff9d4db62633a74189056387f6b2ad4e5171d3e7ed7977e31eb4 \ + --hash=sha256:1517648b5f6268513dea206241a99d9991d6ffcbdbc406848e77a7f02ed3ccf1 \ + --hash=sha256:163a55e77f8e92d739b1f4ef212f1d445ddc58ecdf0da1feca44ef424b5331f8 \ + --hash=sha256:1b291352b1f7dcf095b2a9d540777d59588c81685cc23f7c53f4356e07385e62 \ + --hash=sha256:1df7b0ce46d869c49c77670ba31db737d96fd1bd4ae44d790d33bb731962c994 \ + --hash=sha256:1f8b3b3d8761dee3cddcb5d3e99eaccc0155bbefc345affcdedcc758a4933a1f \ + --hash=sha256:22d8dd757e603224e46786d63cb7d7bfbddc8f579a02e7b082840468d18c06f3 \ + --hash=sha256:2485807c282b6df64d9135551c2d8e9ac2b098b4c85157979fc7ca8bd884a3b4 \ + --hash=sha256:248e939f67a9f8030e2624260a9f417decfe275af37aa96728d256468a9c4086 \ + --hash=sha256:285cc15ff9ffcd4ce7f0b9ce02fcbc65e22fcf7dfbda1a3d71ccac8d7b73f8a1 \ + --hash=sha256:2ea4f2ed18eba7454182d4ff727444788ae51ad11bf5a25ad892f5f0ad3e754b \ + --hash=sha256:2f7ba518893a4ccef5afb38e41bc3e126bf652354417ec4e75e5a5b000fb1ef6 \ + --hash=sha256:3027e8ec2c86106bfd4b125af27aa6dd5eed2ab63427c35138e039931a98ba7c \ + --hash=sha256:30f8ae18425e0247ffff4e4a5753ec1952e1b81ed4e7949b84e5ecfaf8315833 \ + --hash=sha256:389f5379f7cc5b09f6586db99bf91c5d828fac88f1a52fdeb4fc3b040c1dacc9 \ + --hash=sha256:39ef656cf371971486ec545ca0ae2da8d037d5479bc906121e3e46de86ee73c4 \ + --hash=sha256:3b49071fb7917cdbc6d80c81a491c6ad146c1a8fd6cb3076cd3c1bfeb6e266f6 \ + --hash=sha256:3b77eabfbae1ac47872be0076899e66340bbef39b862971c3d6c9a4b7c91fd10 \ + --hash=sha256:44d0d719cd7845e66b01a0cf346ec9882073e710a05e89a5b6d87be47a9dc69c \ + --hash=sha256:4632f5172800da4cd42fd53f4553c772acd08f1c33dd7ac135e29d735080fa0d \ + --hash=sha256:4654ea93f525ea96adf289afcf1ead32d773b8325ec326862b4f81f5f4570835 \ + --hash=sha256:4656c4b24fd711d6caa61cb2fe895dcc55d0d6944828df23f2fb05504435204b \ + --hash=sha256:4a18ef4fe95685b000d95eca797cc683e0c178a4b364f2e39f6c79ab107a26e6 \ + --hash=sha256:4b81b474e4a8ec745ab20a6762275a360e1147cb70cf08872ec14e1aa5debc37 \ + --hash=sha256:4d1d2dc4d930ebc225f488b6b3790acebb2e51b3a165a4a42cc1d05bb927f83e \ + --hash=sha256:4d5ce30facd564d97aceb49013a02661daef1cf9c34ce322c1afbb841f1e5984 \ + --hash=sha256:4db12daef4a231df528a16f70d5ff7f5e3be21f70e8ad904e4c61442366e8a10 \ + --hash=sha256:552a8714f26ddcb43115c82da6d045b3b9f2fa5997d8b21b2f8ec3721503bebb \ + --hash=sha256:55f808bce951fae459fc916359cc54097d386bef3e72265ddf02b39ba3275118 \ + --hash=sha256:5893dc87a2a5297e271dfc5f8f710c3e61ebeb64c137a0b4b786d5bcd11c8fb7 \ + --hash=sha256:5a3d5397da7ae46c7a9601ef02d2c9ec47a6c3abe15e1ea940eaf93e675ee20e \ + --hash=sha256:5b339f6ae14fe7be92f391cc65cc5c80ff76e8da76d63b18fc14664f09b7cece \ + --hash=sha256:5c2a5dac57aec416140812f6d3824cdaf1da8a4f8f009ece64e50f507b6a709a \ + --hash=sha256:5c7fc8e5357d1ad082bb177be71e398fcd3d458726439255ca5cb0d706060269 \ + --hash=sha256:5cb43336244e063f9cc11e44730e4b92dea70c6eb9b649d268c5ebebc4bc7685 \ + --hash=sha256:5db2cdae6a2f01e8f52ab2154886dcf5bb1844b4f31245440bf623ec91b65b08 \ + --hash=sha256:6133abcd0f332964fbb8145adb1ce775cd0312c9eaf6e4bf26b7a5c9b6f7cca7 \ + --hash=sha256:626d5c9fb8b57babc6ce9d03224846ecb094e1d22ff5bff6080398e7f8aee162 \ + --hash=sha256:67c6662b1b7e5728a507db06ad1b8a7ff8ade04c2a74f092d467209ef744d3a4 \ + --hash=sha256:6e3350b7431f7b8315b925d9ca0f29a44e8fb6ed45c1fe552392cb6297966bb9 \ + --hash=sha256:6ea6d553fe513447a7a8ef6175aeacecd9a6dbb7f68f9215c751389c58e1288c \ + --hash=sha256:6ee49daab0b826279c152ad8d61171ea17f4197f91a5e14251d0d5d4adf51059 \ + --hash=sha256:7161217e2190b9b2c8c79b81699be29d67010f6f77e09a53a3b62261792d5489 \ + --hash=sha256:74b8d31a39b9d22293c75bfdf0e6ab54d9dc16d32b540b2cb8f7c162961769ee \ + --hash=sha256:7779088592f8994e021cd79b9b334f41363cfa10a654af9bd5dd82b99c80497f \ + --hash=sha256:77a01cdf4381a1becbe5b827f682006f47b712581667451c5b1eb259b9ae7041 \ + --hash=sha256:77d61c53ab1732e84ad20f77c44bfc761183ef323eef84a59ffdd9201bd51386 \ + --hash=sha256:79d1fe529bd7065c6f3f50279a08c2ab82eaa0631a6f5dfafa9c65105eeaaafa \ + --hash=sha256:7b41cd64ee6b54db94bea6274e6e37002ed526aa06c114a8be6f36ffe21c184e \ + --hash=sha256:8060a206e290410d3bfc3bd91715f3ec90a499246f8335d48927e0b3b6a6ccc5 \ + --hash=sha256:80a961b1c5c7786bc03b332deb7f7ebe818b7baa6e26685e2bf480548ca128b4 \ + --hash=sha256:860ac97858116bda0ac02ef5f50c541fc1a84ad7b9368cac68d4de5697a9012d \ + --hash=sha256:867a217d4a1857fba97c4cc5dc82a38ea257beee8c2a753b3d9b9310c01d12c0 \ + --hash=sha256:879cf95bb0266643c1e8214be0862f2dd7186c9bb2e279f63d7b5fe099cb9a4b \ + --hash=sha256:89ba6b674d4bd7290f9943bbeba0e1bf35955bbb1e07e41ba94691648cf133d5 \ + --hash=sha256:8ad1a36e3d5ebbff515b85468d8e279b336eaa326953b1b36fa21d5e2b8e8f9d \ + --hash=sha256:8f26198220165eb9627847401fff4d0ca8bebf3ef840a88c6312918d2291c33a \ + --hash=sha256:8f39e7316ee0f16a1e74f23010a058e2bd59481992c7adec0470db4ea57a38e5 \ + --hash=sha256:908f310576554379becf2e8c7730a8962693ebfba9395a54ef3c05c57b1cd9d8 \ + --hash=sha256:91d463858f11ee76ce8e39f391bbcbf1d4c3cc4703a1496fed3a5666dcd5e01d \ + --hash=sha256:92a16933d0fa852133500837d33cd6a4f75e4414d77389c58269e12bafc2ee02 \ + --hash=sha256:93150a3bb0317d8f5a94d4c3ea68db1cb434b94ac819e08c443cea97b7645f2f \ + --hash=sha256:9623fc90f1a4754452a525383ce70476476c16556098944709b8cdbd9ad905f0 \ + --hash=sha256:9656d0e9001f69c4af6523874ff445ab4e5db7b835f59733cc5ff51e73a9aa57 \ + --hash=sha256:97cdff6fffc79d915e3d2691110e014f3f43c7529a73c0bfe8de63530b6efbd9 \ + --hash=sha256:9a70f25f6de76a01e309e109c9bcf2143c5c126b3488dd17a25c7aa404b28f16 \ + --hash=sha256:9b961fedf589ffa182fe302fc4371acf4606d3ed4a6a48a151fbfd724d811f5a \ + --hash=sha256:9de6c9133be12a51ea2d8c270f39a04ed45ee369802bb6270649b952e6cec256 \ + --hash=sha256:a01642d403b8925f2b1e1bb51b4ba49ece8a2bdc9b9560fc8ed0b1f2b35b567a \ + --hash=sha256:a0ca63fd9450a212e4e658d4cfe0ab4977c4f9b0003c68828b843c65e27662ff \ + --hash=sha256:a447ed784b8013b518e0b1effe05424d5dfaa6974fed69aebdd4c1349d82fc54 \ + --hash=sha256:a4ff2d7905b0f3f5c54b29626c7747cd4af3fcddfdedf0cce75fbd06b66e4d40 \ + --hash=sha256:a6bba0404b46157a651d1fe512cf2c59c8e42836a9284c35cdff35310758ba4f \ + --hash=sha256:a9e474da7a9f65d3b460cca93cc8a0f4ec0220d1fa41f1f7a3709195ead60056 \ + --hash=sha256:b066f37dd9ec19fc7931d79dee38f56b6f849217bbe824a7dad4518ef96ee515 \ + --hash=sha256:b2cad787346aa8f458ed6d5ecbbe3b6dd13d6d40fdbaa44980c9e29a8b536048 \ + --hash=sha256:b3c3318cc6ef857b6554b43479c30e8249fc143189d500d4137cde9c58412e6d \ + --hash=sha256:b3c741e6b778c951a6861964ee475118812a33208426c54fb92bf4e318bda834 \ + --hash=sha256:b8b97658b0914e90a352a9a1d515e597bcc89c88514fe4bcb4e37fa2a2fbaa29 \ + --hash=sha256:bd4316df8e2074fcf5173f6001f1fc9596e7c1e8c4bf499b02f9ebe92babdfb1 \ + --hash=sha256:bec676a0dc24d4dabd4bdfb3d1f1bf80d4d3dd892fc5c5b3f8f953e2459dbfce \ + --hash=sha256:bef1fe687dc6af17bef9f644a95d465f15f0efa20b743c858e0b6a14e2c0c73e \ + --hash=sha256:c00b1f8fc1dd06c610305be36778b38148ed1e9a532bdd81189c3c0d9905c888 \ + --hash=sha256:c435e795a7ea4b372166a058a5b49a25caeb9c94e469a1414868b14c83ee5c41 \ + --hash=sha256:c73922e4ff4b1ad2929cd795c98223c6688a43c5fd42e9deb8955e4d43b00abb \ + --hash=sha256:c8f69ef2e28f8c1759bc1522385ab3e4ade0b1056053cecf67449a947c4525a8 \ + --hash=sha256:c938de3832ca88ca879bbf0c24673cbe0176b502eec8d2364f35c9edb9bdf890 \ + --hash=sha256:c9c8a61d6227cdcb0a67c678f30a020837c9f3dd7e0b3f916781defa157e4eb9 \ + --hash=sha256:ca381b4a466023d1fdd04c889c759b46f7d9654f622b28bb01e65abf31d07bba \ + --hash=sha256:ccdc09887b04f50f1761eedcfd19da882d9d834096bc1215049af637023f7db7 \ + --hash=sha256:ccf224d2e706be81d464b59c2bc3f98ba65d12c092c1789e625127e64488944e \ + --hash=sha256:d55acd326db8ecfc94f21951abd20902c7939d35925444e48d94527e287bead7 \ + --hash=sha256:d7424194e68ef44e94290961f59319850d7ce11a329a3957f91709c15ded6618 \ + --hash=sha256:d8013186f2b9a8c27ededa601050392527aa9d27ffd35d49aae424fbd2062f38 \ + --hash=sha256:d9b61af76a3cd90ad9656a331737d97dab8c05facb2d04cb41fb16c9adadc966 \ + --hash=sha256:db7804a8d3a433a3c5e08cd658ea69a6ee9a2ee43b756dd20048dae5a3d7ac67 \ + --hash=sha256:dd7e57efd54a3580620f635c48a3226f910e23649b7eb83ffbc6f0f3386293b8 \ + --hash=sha256:df6d792b41ad90783cf9c3c8f66b02f06025250533b92997913ec600bcb0d075 \ + --hash=sha256:e4d4819398d5330636bc0b91ccc0048dba782076fb99257038257ba6f121c840 \ + --hash=sha256:ea69e23481497c2143775a98d273ccc43de5c92a6387df18c903d2d37bc2b181 \ + --hash=sha256:ebb0c346b6c5d9c033fe9e9b6ed6a1ff6dac0288fe681c3434dde6eb9c264fa1 \ + --hash=sha256:eec2da60423287bd60377b0fad1723560dcc51cfb2b99615be8431ad425c4438 \ + --hash=sha256:f035d01b450ac4e141502f1ce142462cee638198ff5a0237c80e6683798b3b87 \ + --hash=sha256:f1e738b851019d6bb6ff4a42c6319bdede967dec958ef3ec6feb7ab9d12408f7 \ + --hash=sha256:f5e5d58f589412c7774b3a2c4878b8ee54f9804840075822ad2bd2356a5080fd \ + --hash=sha256:f9083a7c2a4ee6358bc0401c46b4d5090f208f6fadfb6275c7b5fe3217e13506 \ + --hash=sha256:fe42726d7fe171cd8fc1966d4457a6aae03bd408d519d2cc5e7726805460b51e \ + --hash=sha256:feadebdfee32c61e91066433f4aa74c891752e26e43032c1feef08dda6d9b6ed + # via openai +jmespath==1.1.0 \ + --hash=sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d \ + --hash=sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64 + # via + # boto3 + # botocore +jsonschema==4.26.0 \ + --hash=sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326 \ + --hash=sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce + # via + # litellm + # mcp +jsonschema-specifications==2025.9.1 \ + --hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \ + --hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d + # via jsonschema +litellm==1.100.4 \ + --hash=sha256:7228d4d12eb332e5e7b7dbfeb41a4182784ad2acf86f6b7eb806565e04912ada \ + --hash=sha256:737c99748f9a37e74d4927ad9fe311e3f531a5379ea423eb0d1412d3310f1643 \ + --hash=sha256:83342175eb948f146f405735b03c1cb1e5c332aeef6a98cfb31f59233d10426a \ + --hash=sha256:aa8e8507678451b18c4369b69506d8948154b2ab4af211454dd062380597c1ce \ + --hash=sha256:c031cbc63848be16403725594f6060fe002dc2e65f0866878285d72923ac27ab \ + --hash=sha256:c86e2e3370674557547022eb9acd8ec842f802bddb2cfa97992332ad56309a53 \ + --hash=sha256:ded14b15466163c76c9a7da0cd091663b4bebbff9aa56724a5905386a9d12532 \ + --hash=sha256:eb12645456c19dd56f1fa5d7e165a2a76effb1501ace5d0a4df18efc0ac5c39a + # via -r integrations/isolation/acq-kits/claude-code/files/home/claude-code/requirements.in +markupsafe==3.0.4 \ + --hash=sha256:007e1ffd9bf65bb6ee96df7b258fc632a4868dd5566037986c64781f35a36e98 \ + --hash=sha256:02fa4acbc6a3fc5c693c34d4dd8c1130b7fe99cc915181b0ddd6f72aeb296002 \ + --hash=sha256:03470d1a8268e692ecf79ecd565593e59d44219377a7ead61f1f1b94c1f7ff6b \ + --hash=sha256:04e7902ba80ee4bac1d50a549606527a1dcf0476cd81403db41099d3b60ec653 \ + --hash=sha256:051417f74bcaaefa316276e0ff723f541616ca51043d070da00249d9bddd3e3c \ + --hash=sha256:05295589e619b9bed252a86b532b8e27350abc372d18ba89b59375325e91ec1e \ + --hash=sha256:06de8ef6331f6e822c28d577dc8bf43fe398800477c49498f38fc38b67ff33fc \ + --hash=sha256:0764a13d34cae40db7bbf3a09b7e9b491bf4603e20b263a7a9d6b8e324975d0a \ + --hash=sha256:077293e425f28ec737dbcad442a71752e28f8ae27cde3d68acd1fb212091cd92 \ + --hash=sha256:0930db9bdc62d22944e10b066448bb65dc9abe9112880c7cab8da54db4284d5f \ + --hash=sha256:0cee7cb0f9a1b6892ea482237d9403b3d1b4603aee057d0ff01f0fac2d019a97 \ + --hash=sha256:0d9c47709875fdb321452056622e930c52afbc07a7d780762fbb8b4d91ce6fa4 \ + --hash=sha256:11935df9bf455ed0c04eb87bcd720f02b1fe5e02128a9430f23aed6f93336fc7 \ + --hash=sha256:12a606a492de952afcb43b59a14aaaaad120e708d3663dd0fdf2d738d427a691 \ + --hash=sha256:14bd2d845d62ab678eaf81da89d7b621b51756c72346745c1a594c09d49207a2 \ + --hash=sha256:15ba9e28640feef770374b116a6f019c21f52404aeabe516aa7f800587b98cfc \ + --hash=sha256:18a801868a884f216e784d7d14db2a4077143ce7610440aee2ce8f734e7cfcde \ + --hash=sha256:1c0df495a977d10460a94941799c72d5b5ab03d3858d949b55b5a66c8f371c99 \ + --hash=sha256:1caa2fa5a6184fb233153b35f654e6687bd555476f6170f29d8ee9be1a8b0af9 \ + --hash=sha256:1e1451fab512d1bcc3dc26988ec1edb0b82c2db909132872cd9356070a6b63df \ + --hash=sha256:1f1f9477e174582b0a1b583d60b66e1f2cf5d3fe12cee985e4aedf44766600e5 \ + --hash=sha256:2628d3a8cb648ecebb3c5d6b0a1052d400e4d8b7ac0fb786be8d285b50040d17 \ + --hash=sha256:26e9867520db70d37f7fb421a7f0d8adb40171011fb84ce869afa1a83370dfa8 \ + --hash=sha256:2a6ef68ae94aed8721934072b27a3b654ea2100b97e4ab864cf1489c90926fbc \ + --hash=sha256:2b2b1e18af909b448bb3cf9e3433366f7a8726271fc214e8b10e0f62a78c724b \ + --hash=sha256:2cb3dd71fc6be918ad4264346a8ed69485f9b7ed7bf35495d8e22807cd6b8bea \ + --hash=sha256:2d1b7d9308288661f56672b1b157d75fc536714d3638487bbea17b6318a78248 \ + --hash=sha256:2dad610540cb2e6272855c178f08ae9a1c7ac258a7fb71660553a5f104b42741 \ + --hash=sha256:2e5a7cd7fdd14fcb1ae5d7d8bf23d24fbd1daefd1fbca2580132e1ea75f098b5 \ + --hash=sha256:2e9ad7dd851bf45fab9f75cbff4cb493fee9979e8d8c7c9c3ee119022518edd6 \ + --hash=sha256:340cbb1957ba99929cbf19a75626d36ba1ae21d1730b287d1cf7f824a20c4fc7 \ + --hash=sha256:34bdde374c5932765d7dc685c4a1d191a3207852d67e8e0a9eb6ea85156181f1 \ + --hash=sha256:353bd63081912ab8cfa6a0c7d185934cdf8426f04c618bba6bc4b394f2069b67 \ + --hash=sha256:387d8cd30e69b3f0a72877b9ae717033396404e19095b17fe89753a981fda44f \ + --hash=sha256:3882fb412298575bae3b9c46868251f15cc69307359f87bb1b382e53d6e5a2c9 \ + --hash=sha256:38fc55594dab834470b6733dead2ee9e3f657fb0608c769dcafa0ba5ab52f45c \ + --hash=sha256:396ec4e65cc889f69786b3b89478b471cee5a3bcf468b9d9bb03e1a30fb291fc \ + --hash=sha256:39dbacefc411633db5b4378b066a9aca70a3d7e2922c9e578d825f844026eeba \ + --hash=sha256:3a93d9616ddecfb393727a0041a562cf0b15a244e20f2bd25efc7949be4c4f17 \ + --hash=sha256:3d23795802fc8bd72534836d64489bbf0f67c088959091bdb22e10735a5107bf \ + --hash=sha256:434139499bb20b502ed3baa1f169e618f924a97e7a777fea1a49446d80106cf6 \ + --hash=sha256:436e3ffc6310d3c41878c601db29098102fe5d8a467c49da4a4125254e0980f2 \ + --hash=sha256:489505b03f692c3f376394e49194fa7a7f9e8558d6e293a7056a0032b0c38163 \ + --hash=sha256:4a540e2d3192792fc84eced57bef37851ccb2b41f73291bb17408eea77bcd278 \ + --hash=sha256:4a7cdc2a420ca01058182da4253329764d4bfa055564d1eced90e6ba1e8b1d3d \ + --hash=sha256:4bced6e2a6dba6a28f7dd3c6ce14df1b2dd495923f16ea484cad03decd463b2b \ + --hash=sha256:4cf3468d5ec187ffffcaca8e61929a37448f215dafc1386a12c750a72fe53634 \ + --hash=sha256:4e2c4809c14559aa7ef426f27fb35afbb38104c349a903bf8f3600456764bb38 \ + --hash=sha256:4ed644d75aa94a2baf7ec3a96eaa160ea58c742eb9d27c6506053c5c40fc84ed \ + --hash=sha256:4f6e0852a0283b1b1fd776eeb7b766a5f440b3e2bd31ab51af3b400585f3965c \ + --hash=sha256:5066b244f576f91afc8ee3ba029a89f99d39c79b1853fe9d39bea9f0afbec148 \ + --hash=sha256:5086f9975abb1ab531ee6afca1761e4b59a19b446f3f6522ed776963228cfe5a \ + --hash=sha256:50b5bedc9ed8a94fc8857a42ef4f84a81ea88f8d4f05dc8705fb23ee6d8dcca7 \ + --hash=sha256:52704c5d36eb6dda8866493decd61111fff86244c9b1ad225ca01b9e91e5970f \ + --hash=sha256:55ffd6ce583d97dc71dc92e930324c8c0d25aea7e3ade6ae54ef77cedb096811 \ + --hash=sha256:569d65055d367e3dcdf30c3f41119467b73d9ee9faf332bdf40402644f5ac08e \ + --hash=sha256:57f9947a7e57a081c1e3e0a2dd0d2dcf290a4531450e6f611e30084c222a7295 \ + --hash=sha256:5989cb26b2e1efc6a42216a9f6b5ee495ce5ace2e5b352a9af489976b32d1ee2 \ + --hash=sha256:5c22873ad1f0532ba40fa1727f3c0fc1bbbaab6d373d4cbe3f0dc74b2e2521c7 \ + --hash=sha256:5e8b3d0b18fd623afa12ecb2ce8d8becef69f9b5440c6330c7972200e0bb84b0 \ + --hash=sha256:61631e08084be9e21a8967ec3139c7616ed7c5e9368e05c86d1b39562c8a57b6 \ + --hash=sha256:64511c54db4e4987aef4c41923235927428729e8174c5dba488429be70a998ed \ + --hash=sha256:6669c1bf34080161ce49c589cc512ef24d4c704ac9d2b2d3667f519c60418378 \ + --hash=sha256:672d207103e6b16ca098611b0f9efad6bc00afd47c03d6ef62186495ca677dc0 \ + --hash=sha256:6768d67d1bce64270e0fdc2e69309d68b9b18ae56ddf6c711d168e9d051c2cac \ + --hash=sha256:6a45c3d514f2436064db00d7fc8778d888f0236ebfed649b53d13a59e69ad51b \ + --hash=sha256:6bd9e1788e15bfcf6a9082de42e30387e7b85d211ab21e57a939bb8cfaaf8d96 \ + --hash=sha256:6d2a9efe686f9de00d0d1ea32a4a5a86d558a2277501bd78d964214eab625e59 \ + --hash=sha256:6da83a088f8ef93b2d483a8232a4dbf4d69d3d8496b568a03c56becac43e1808 \ + --hash=sha256:7018d4af1cd272e847aa5917983ab5e83e4f6579f9dbfecd4a79c0ca80b144c2 \ + --hash=sha256:71f88e749ea29f67f21f3b36433c1dc54c7729ed2a6d9e2da2e0d9e0d7b224eb \ + --hash=sha256:737c9c3981998eba27f11786f84fddcbabc74068b72a4a1f454ea02094b57b65 \ + --hash=sha256:73e77980c7207854f00fc4e71fb1626868d5740ab4012623d55c7a99ad122a72 \ + --hash=sha256:799c39bdf5e2f1292fedd3009f7b3c9e760f10b2420cb9638d56920840ff6db8 \ + --hash=sha256:7a83aa6e4805df46fed18e989d3d16f86ef60cb50bbc8d9ce3a6be89165fbf6e \ + --hash=sha256:7d3391b2188d18737cb2fa147028b1096236eaa7e156446c650a489fa2cadc91 \ + --hash=sha256:7e1636da3d8dfc220b6dd10264db5f2b165e4888c4518594898fbe381049af8a \ + --hash=sha256:805c8b84534fa10891890f0e4be39f3a99e94615d93e8836bf9fa1fdca2feeb2 \ + --hash=sha256:811d02d5122171c1941357efd8f9bf4ffe907b7f0a1a4e729a880e4be3f46e3e \ + --hash=sha256:8138eb83940ec7299024d92d4dee45f601b9e6c5ffde9d25f4e35e326203c707 \ + --hash=sha256:83b3944fea42a8400edf92fd1770fb8d0d4f7de651353bd2d8525a92dba69a21 \ + --hash=sha256:849dd2bb0e5e4ab2b71c7191726a4a8d5aa8a610daa584728cbee0b710ddc4ef \ + --hash=sha256:8698d70a8081ee8c090dbb394768b5789a1da8b131b5499f89d071dd3cfaf6be \ + --hash=sha256:8781a792a070cf2bd1b86d3aa943894115faaba6e88122a7bf32d62072742453 \ + --hash=sha256:88d59b473bfb03259722600839af9bbd7fa13a2eb514beefeedb95997882f69a \ + --hash=sha256:8909c2f1c6dd65e054ac4b573a91c8384d1492281e55d82d159d653f7a13adf6 \ + --hash=sha256:8965520ac587c94a4ac48b729be3d8b8de00af39699b17585dfb599babe77977 \ + --hash=sha256:8b5d563170ff8ba3181caa967c99a3c804d1dedb702c7cb93a6a7c32247da978 \ + --hash=sha256:8e124f974786f831d6043728e38296969d3579db8896fe004682f5758e613581 \ + --hash=sha256:8f0fac8b13d14bb06c68195f849371924ae53dd7b1c00fed24650f704383b692 \ + --hash=sha256:9240187afb63d2f9ddc3e032c670356fe941f6e20662ea168a5dc3f1f317e1b3 \ + --hash=sha256:925f929d6b59a8b3f8b8c6ac363cd0af7eecc81efb3071770b3c6717c450a369 \ + --hash=sha256:9348cbb300d224fe3b89793262cb093504d4ae927004468463f745188a193e4a \ + --hash=sha256:9388003072b95f2f1e3fd908604194d653ba21330d811961a78b7da1a77e9e36 \ + --hash=sha256:9438a2648b2195980cb2dd8e53ed7b8df91319e2d0b70ae61a9e1d1bc8d3bec9 \ + --hash=sha256:94e4c421742086aeee4c32a506eec8859d7634aad943f7e6aacf70f813478768 \ + --hash=sha256:94f5407f7bc64fa6463906b896f9904beeeb7dd8dc116ee8e9056c8714ff9916 \ + --hash=sha256:971a3bbb75d97ae4e2e8f7d4834236f86f85f0c85e04ab2e191db1123b04f80b \ + --hash=sha256:9e227f3dbe6bde7491cf0a9965d00b88c6b1a4a95d11480ddf88bb96d397c19f \ + --hash=sha256:9e25feb9e330b63edb0278a0acdf85e50d0cb0fbf49c3084abbe4e24ae195346 \ + --hash=sha256:9f098115c247e11d138ab83a28fa0323c77015007ea2df73ba5fd714dfefd67c \ + --hash=sha256:a18f38cafc329bac5e3c2b96c765b4c96d3d103421ed22ab7988c1e3fce27464 \ + --hash=sha256:a4bbd2d87dd233b9fc5812160c3d0ffbe42edc22a26ce0469f58479ede633fe9 \ + --hash=sha256:a5fcffb37e602b0b3c1638a97746b9b96125caa9bcf6fa41d337a9261de231ee \ + --hash=sha256:a8e9f292fcda89b324f2f5c91d13f1424a153e40fc2756f38ee23b15835ff300 \ + --hash=sha256:a9f54054101545a9a9cccefddf54316aa6e4491611fcbef9e91b3b6bebec04f6 \ + --hash=sha256:aa2c838cc024642cc04c6854232f32b43e5e22833dd11119c1766c7873b8370d \ + --hash=sha256:ac0c7c9f1609b0c4c114feb1d7a3409564c7fb77e360bed9e97e5d25dfeaf868 \ + --hash=sha256:add96447a86d205ab616665d53b2950ee81083757f56e6ea833c8b2917646b46 \ + --hash=sha256:ae9dcb8fbe244cb82f8a6458b455b927a03685e383d9bacf1ea5ce180b96dc97 \ + --hash=sha256:b4a635a0487774f841cb1fb62e907e7195cc95bc761e053184b8acc3ceb20733 \ + --hash=sha256:b4d12837e0203bbace818ff4a7461afdcd78bcd782351cea148139180d7bcffe \ + --hash=sha256:b61687d0828e72bf5cda24a2690188f37170bd31c9359ac97e4e66569f120a16 \ + --hash=sha256:b807e598953730f82e4eae3bd30f6a122cf6b31c398c6b504c0e04c13c170429 \ + --hash=sha256:b8cd1f918b26fd7b1832ece557cc18f2d8747309ff8b3f0ef9d4250c5ad67a39 \ + --hash=sha256:b91cc9d336957239ff200f30097e6fea2dc6d6fb3c81e853eaa09eac904fd894 \ + --hash=sha256:bd3ce56ae2cbae3ba82b683bc425cd7e48d2ed8b10f3e818186b6f5646d9271c \ + --hash=sha256:be6cb0c799abb0e2ba3e618e6d28ddddf7e485f6c2ce938dfa237daf3905072c \ + --hash=sha256:befb4158af32106b9a93db8d6d1d1cbbd418c0d5aca0cabb7b1780abf0c89169 \ + --hash=sha256:bf053da3c97a4bc5ecfbb218cdd2983febd91c617be8367d139882aa11e490aa \ + --hash=sha256:c02e8f18bdedba082cef725942ac823b9b60656db07f7e265cb31618dfd00d77 \ + --hash=sha256:c1bc67752d5f21013cfe430df4062441714eab79f65a6a05e01505957e9c35fe \ + --hash=sha256:c61750fadcd119d0825bcb7d7d675dd264dcc89cc05292aab5be68ebdbb374ad \ + --hash=sha256:c90d5b3d4e944e065a301d741b3c1d784f6bd1f503aa68b4967e32b2ba313d85 \ + --hash=sha256:c9a7f43c0b202b334cc9184af09bb8f21d3a209e038efaf106936fb69e6b026e \ + --hash=sha256:cb96e6e088d6cf71c1ea977510948320234824cf226e32f6f6e044f7a9c82b34 \ + --hash=sha256:cf63c214fe879a65e69a386f915e36104fc84254ab141240f8854602d8e0be2a \ + --hash=sha256:d1aca03ede943eb80ab3d63bb082c84b7aab85ea83bd0fd0c200260945fb49d9 \ + --hash=sha256:d2e56fd3b00222722abfb3f5f0759ddbae4b90811b5ad4343c64030ad1bde70c \ + --hash=sha256:d5f93ebbeb8032d47e349328ec8662d973d9b05a70b3c35df1f91fe419b84749 \ + --hash=sha256:d882a373d8093c2941e01291b7ced96e9cbe4781da9a7751ca7e6c70385e5214 \ + --hash=sha256:d920abdfa61279ba1a2ef9484aab07bf03331f8c08a10120fa332353d06e6932 \ + --hash=sha256:da2af0d7aebfc2074080d72efa6ab8317c62481ef1f896f65d9999c1c01f4494 \ + --hash=sha256:dd8ea6ebee7aedbf7c749fa80521d9ccf1ba473e0d1e14805caafbaad281c889 \ + --hash=sha256:de8b364c423ef0a4bad9069657d617f9a5d2b2062457a89b1fa16ee199c399c1 \ + --hash=sha256:df1ae86ff54725a01fa1a0510b914ca53a161b7050be74f6204e24aded5971d0 \ + --hash=sha256:dff05cb7016dff1e9fd68f4122c127b65dfc59de5306cfb7ad92f956f230bee2 \ + --hash=sha256:e1a622f13970d81f95d0c72f9dc090dce9085fccfa4c9f2174377ee32bd15786 \ + --hash=sha256:e49fb0d1ce92cfa0cb198cc5b1b11cdf9d0638658e2a2db2687e39db7c87fc78 \ + --hash=sha256:e5c802729725bd07e2bc3ab7b76dc7e0bbfc53129d8f1eb1c002c24cf774717e \ + --hash=sha256:e841068dc0be4cb6dfb5c890eb88cbdcff2f4a332393c7ec94e8e618bd32c1a8 \ + --hash=sha256:e916035e3e9930cbdfdd10abf48861340221857f45509565898e012263f7b289 \ + --hash=sha256:eba154571c16e032112afac0dc2dfe9e63c2ceb7aedd07bb7eecf2ce26d4dd4c \ + --hash=sha256:f03460ff076f70ab595bb45a0205ccea1971443575b6920c52e755dec2b3fbfe \ + --hash=sha256:f0ec3b750b59375eab5b0fb2b9254810c00a3375be6d789899f1055a1d556237 \ + --hash=sha256:f291bcf42ae98eb5107edb162c3c998b4a89648fd8e99ed4cbd12705292788cd \ + --hash=sha256:f61efe1d2fe0de16158a5fe1d1cf3c14bdb6aecd54d8938fd26512c525c1f624 \ + --hash=sha256:f68edfc67aabac33708941f26f22a7b8e9f81429bc0cf249fcf7d66b23af8d19 \ + --hash=sha256:fa95848c929b6a75f6848d3c9793e59db365ee436776e57db835cdbfa79ba977 \ + --hash=sha256:fd9f8797427910198f95bced71ddfed61130d7e349213bfb8466c9c99e2c46a8 \ + --hash=sha256:fdb4ca07ab75ffadab4a8b135ad59cdbb3156b99310f3d565370da74a15d6bd3 + # via jinja2 +mcp==2.3.0 \ + --hash=sha256:8b147a50441cf059dc88c684e0aeed3687f0aa0f39c6cde7b90330effd2b34d8 \ + --hash=sha256:dd0c44c089d16453e8ae31a3877a0054d7a2314caaa81f5e0541b9b1734b2377 + # via -r integrations/isolation/acq-kits/claude-code/files/home/claude-code/requirements.in +mcp-types==2.3.0 \ + --hash=sha256:968efdbdaedfab06adae40d378a34395f1090c5921d4be3c9cde283aaf76d91d \ + --hash=sha256:d1e46549edb35ee19a94940fcee6d1addd7e589ab7ea92dda83f5d84781fc362 + # via mcp +multidict==7.2.1 \ + --hash=sha256:02009b402129a73e1f3da68f48eb999afbacd29f25aef0d5052b84ff5c2786a2 \ + --hash=sha256:02d9c04d395a36eeebe89e45f2269614a4675b8e83fddcba15bba2be903971e5 \ + --hash=sha256:03846be88267369908fcd9a91159358a3b142d740991c96e4f696d362fce516c \ + --hash=sha256:08ea94663d9e7c25d14d78222f7aee906c472d4837766bec62477c38f6e419dc \ + --hash=sha256:0c454b677214fa604e9c4a38952c685dc88a62c96f5576a7ce550f213d1dc318 \ + --hash=sha256:0c52fdd8cb8194fcb6969a417149aa1d09d6e48b69fb1b34ee1b1e4cb51ec183 \ + --hash=sha256:0c7b4d8cc9e6ae7070b8129bdb840215552d4e2689ca765d37eb208a24919209 \ + --hash=sha256:0d852d3d9638f852158d7de7200dd77f7ff8d77fc8f3d396032f3d847883f631 \ + --hash=sha256:0eb7fa012ab47b13e96bffc1369642f520adcc4e3d3e170d7f1a2b39fb953bce \ + --hash=sha256:0ec95a02f9f08246cc7f1d85ac425e4d5c233fd3f098f5be1b2cca16aa690186 \ + --hash=sha256:0f30d6eaf3cb309b6c21096c6c2b4cf3800f195a78b1babae85f481ce851bdc2 \ + --hash=sha256:12bbab225ce7f69df75409ab8005b11b4e9309fae863821e019e81b32e53a2a8 \ + --hash=sha256:13268013a3db11a214ccb6920f778d175b765f69a40509610b92e43602272718 \ + --hash=sha256:15da10cf11fd8d8716720c95b93180e94c8317405d89d08524c579ef360128ac \ + --hash=sha256:1d369ed297e79b417766327ece16bb7e89306c588df63c364a85d90d4aeac843 \ + --hash=sha256:1fb8c1a3480c130c3a6422d5f16f3cad6552bf08c2089dd288ba7134649183b5 \ + --hash=sha256:2022bd3194968a027f64ed16f9779e62e71a823a9df3971a7328c1d45dfeb9ab \ + --hash=sha256:21d86f2aa58aa428fb9909d6b8587b75eea827287e3515b8506dca86b55e2c7d \ + --hash=sha256:223427392fdf993e198644ec40c404fd93f1cd2a61328d18842ecbf154d02c82 \ + --hash=sha256:2529873a3bf68c372532a9f8058bcf4199e78387e92cd6a01b73334bfe6a7e3f \ + --hash=sha256:2592fb6c335d67f1912bf72788c02fd5dab305fc3c8c7eab078a5bec1aaa0f88 \ + --hash=sha256:25ebc4208d9098f77caeb16df895a0e56eb6c3b22870ac4e3ec43e0a9d6a33b6 \ + --hash=sha256:27166b6ec73eac37696d66b2c6efbd44b6d04b597d655070959df54dc7c71c0b \ + --hash=sha256:27cc258247b13008742f0e239933ad01dec5ed4e6dfc63849e30e04e1aa5bc82 \ + --hash=sha256:295a15ccb8cfde9351dd6062b80af4e839460636b3c46813b4aa443905ded86a \ + --hash=sha256:2b4d0c4e13d329ffee73d46128e32dd3b4aeb2f9c6ac9c8a89eb28d3b82dcea8 \ + --hash=sha256:2bac371da2c3554a99ba126f545e79ab8e8d9426a3e41df81d00ad725c1e2cbf \ + --hash=sha256:2c4e6a97f79699f33e6dc13bddb5631781ee79a4a94c1822116d100e7d5c136c \ + --hash=sha256:2d4cfbbb1023f0f6795b5395c400752fb23a5a09ba756aa9003886bbc47b3e12 \ + --hash=sha256:2e279ad5a6e9347bc9e043fdbee180a0480c8fd52618c3258e983dd93d98ed49 \ + --hash=sha256:2f3cf710144b1859f4128051cc27ea86eee83caac5648cf2ca0c1b835261cbbe \ + --hash=sha256:30572b61c7932e4d3c2ad1e580de7db1f35b7a35d36db38f89397ce3f2e69096 \ + --hash=sha256:335f715f8c111654f29e4bf19086bdf0245579d2b4f4f59ca8dd9b3003b859c1 \ + --hash=sha256:363e5db93fc3f65f3218a79fe108d217b9d264181a4e993c77552bfe275d0393 \ + --hash=sha256:36b868758fb11cfa748c788b793994e73660abec90f83c780a678539c2c468bf \ + --hash=sha256:37b161535e92776788957a165fcf38a80b33c1efde7b18cab287db4e4574df78 \ + --hash=sha256:3b7542fad2706595c1b1853b46f2c3c4ae5cc5a6252b7225f294d607a29e1bdf \ + --hash=sha256:3ca4e2e9102d0788b94894a30a5e3561fd4818a0605d8748d8fe780f890aa069 \ + --hash=sha256:3ca60708f0ca9d994f46790c5a5c774771e2f1dcb75b12c70a5582f915d0e721 \ + --hash=sha256:3d22ebb716ac79bf32c2a1d15250f017faef719114af4376e8dd814d6633cf0a \ + --hash=sha256:3d6fce7cc4ef63d9a7633cbae43e737798412805a4c3ba876cdf472dc6ff9c51 \ + --hash=sha256:4b338b45dc26ca4bac702e1278754f78613d4d0081e14e94e44fe8e261bf1750 \ + --hash=sha256:4bebc9587cc29359e3b045518a7a09264fa882a7d165b0d143fdac8eeb7ea948 \ + --hash=sha256:4d61be3725016ef5db3543c95f1f062d7d150ba776582d959a982af88e75fa55 \ + --hash=sha256:4eb2650aa240b62ab0c6d87238bee5d14aa4d411c0d69ad61be53e026e0785ba \ + --hash=sha256:4f31ddf9c00e0e7db848b0236c717acbe8a51954d0d31b4d908c538ab3f0f5bc \ + --hash=sha256:522f7d2351743804cdf5c5a304bc45f9d55e935dd87706fae2dbeafe0fed0b49 \ + --hash=sha256:5324411117bdb67cfaeb3d1d28fb783710fcca3d88b855696af99044d7219e4b \ + --hash=sha256:554ee1d2e71fb5b4059c0c4ee35d8cbc8af2a3147036d65a454c53fea07ff4eb \ + --hash=sha256:57ac987ec5d26d89bbc48c03e486f659e1367d425c465552ac2e4c4af8219def \ + --hash=sha256:57b5d0df4c60ab8b1159687610a1c3ae069ad2380d390a79dedff5c82318e714 \ + --hash=sha256:584ebfa26c9dcf3e465637a5a9afa2647bebb3022b50b1ff384834ba8e0380d1 \ + --hash=sha256:5a7df927c7999d1d3196176a8d4139d3a0e1765936f5de8c768097275b2d617a \ + --hash=sha256:5b944091cfa7da4f7a9bd2587569cd90c94b89ec4721f8e87fe62504f2432b67 \ + --hash=sha256:5deadf03fb4a7842696d551f9f9a06dd4445bb43ca06b5f9736e4e1885561333 \ + --hash=sha256:5efddcdbcb73f5485dca2b6624edc8ee063604b77bd3a3eb772826063965819f \ + --hash=sha256:65e4448dadc7c94a8643bb41361e45f3a73d46e36a008a9bc03e9b525f4d7c80 \ + --hash=sha256:66af55b07e4593790157e85f897f06983ded8a8692cb2fb048f3049c1d3fa172 \ + --hash=sha256:678ac791b5820d9346eb13c8515fe0c9383659335e5cfc544bf6f54714ca1939 \ + --hash=sha256:68b97b721d95b77d75e718d1b62a227fa4b3e647bd2a9fb39552d1a79ffb67c0 \ + --hash=sha256:6966806cf917cbbeb9a8b5c581db52e19c9af0ef5fe009db54c1f5799a6e003f \ + --hash=sha256:69befda4b1ef57027ea95dc6ed733568642f330fb3203a3e5c5ef107d41e0a1f \ + --hash=sha256:6e22756c6e2d4f57ead0d2e6be179d8a16d661bee424b81de0c6c0c1305ec39f \ + --hash=sha256:6efdeed2723431999cf3bcbc84c72dbe0f65d16bb1f84e15a657f5b60ff18ca6 \ + --hash=sha256:714fe5f3eabd153b1b6911d0b5d31cfc2b808ae6b9e59a32fab17a4e6cdad5a6 \ + --hash=sha256:7238f7135481926d52a94c18a8cca633a9e72c1cbfccd5796548298a479b0656 \ + --hash=sha256:74d3e015c28b43b6c1a108eec324ea2efb185c359c459216cabd4cb98f7f02f6 \ + --hash=sha256:76a4f5132b8dc29eb3c768ee9b47e132a1d24fbc2e9259854c01af9beaff1d49 \ + --hash=sha256:7726c53b1d59eb57b009a9e8759d4f71049ebdacf30642a198a197f80cea451c \ + --hash=sha256:781ca5dfc2f1d58e47f52216a0c1c7e1ba91ce8aa235459e20de2d402af77fb3 \ + --hash=sha256:785ef2f3e372dabc131f228a275f97eca92ad17cfab1ab138790e330d99abe3e \ + --hash=sha256:7cb1a6bb70edcc06ea65cb9a35654f268ee39d9fc3a52240e6ba074db4d9c99e \ + --hash=sha256:7fb3bc8d58e1b7c1d9fa1d995e30a4ce9dbe49f4c63c755a1ffdecdfbd026ccb \ + --hash=sha256:8148c2aaaf4b85d7872f024c8bb0c9b9797cc76b10588e3594a69cb01057472a \ + --hash=sha256:81a5f84a76401c4330e6db4e170dddd58860b30c4e8a44a181e5c2809c7f9c9d \ + --hash=sha256:81c6fc88ac9bf6920a0cdf22d3c383964167f12d35eb630463fc6d5ac89e460d \ + --hash=sha256:822a7fcd33f6922b650e1b26594f09d53c5d011fe655fea7ded27b2728ce2a1b \ + --hash=sha256:83fbd7cfaca614975efdbdcd9e2df45f3e987e819216468fb73e1db6f0365b98 \ + --hash=sha256:846b17193f1c373d6f05ada894fadf56bce2473067caea0aab51828849894b31 \ + --hash=sha256:8648dd5dc4d5db32b5936dc5e85e9a4d79db1135513d40d1f54ca15503750324 \ + --hash=sha256:873d35366cc115be02a1c858f9b22a1a9f6182b99aab2171ee5276af02a153e3 \ + --hash=sha256:8c3ff4f5c376df7126695a52af61e6084b69c9e52dcb9f4713e71ce9819e1bfd \ + --hash=sha256:90efd90a0f9b7ae3844a4fb3ae614321832d364ae19567b7cd312315fac4ec39 \ + --hash=sha256:9306e0c5595f91874e685be0a9eb743d48ba069c888eea051bec3c67c08b5b8d \ + --hash=sha256:987f65f6c9321402bc7012f6c6d09ba501b88ddb1640f5b0b4a19f2caafe24a5 \ + --hash=sha256:9a53776adc1ba923c9e345fdea7b61553c44c17a9af5eba8d8def8c5dcac4dec \ + --hash=sha256:9c44bd978adddf39df5834c6a1efd7d075c84769a7a084168d035a2a276d9008 \ + --hash=sha256:9c9f285f788acf2448a57c9b93d31103ac69bd03f92907e2ffbb23c4e2b42eb6 \ + --hash=sha256:9df532dd12c59a7a4d381646fc1bf5ccb4bcdbd01c0887d07ec769fae965ea9a \ + --hash=sha256:a0f999155c22c8929cc492949c08c6fe7ec8079a5e1bfdeb34b9a3e4991959d0 \ + --hash=sha256:a2a322c8a6ca82a5a67ae6542e9c6a13ded9045cfd171dcccc5c213ac4fe0eab \ + --hash=sha256:a3d28ac22fe658ad7486d1532b3a9084fbf65b428db31f47212c5b0b6da826f1 \ + --hash=sha256:a3d9a59bcdf8531d46b56bcd512017533510c25e955c2c546efd0743bd840940 \ + --hash=sha256:a789e3d27fc5665cc0477f10a35a89383313e4c9cf8b5e6af7ea71f039cdcc0e \ + --hash=sha256:a7d120bdde5b213e67ed7dc80ea3adf4f014453fbc20195d619ba2ceb34084f3 \ + --hash=sha256:a878fef2797a7c082aa47559af68299372edebc7367bd5128dff2d36e6d820e1 \ + --hash=sha256:a92e3080d8889b0f7a80ea0c4a72181b4d4d5d3918a03136b4a459f51f5f59da \ + --hash=sha256:a9cc121b5ee2c8b4bd4b6b526d5a26bb782f4d620463f73707691b2004b8c349 \ + --hash=sha256:b4821bd30b38144d8ab75df56af0b07e9d71327c9cf94c0c7a1965f865bb9615 \ + --hash=sha256:b5fb6b048931ea925b484f0c7c01b007981415a00a6c62ee74bbf8d229d39c08 \ + --hash=sha256:b63acdf4df5a78a15223bbb510bb3e0f8234dfa807610ccb8796d0842db2c801 \ + --hash=sha256:b81ff0f2d375988152614eaea4d5023c98ecb08f77df4bb1d96762504bb86fca \ + --hash=sha256:b97bffa5772b7e853303de094829fcd3a9bd49fddd70534651ee4933691f6587 \ + --hash=sha256:ba5e8d9310a794b853fb0e327d46a827b5b015576341219a591f88ed9d799c27 \ + --hash=sha256:bc9decb36abd00ed5d123db9df70eb9a0da45d6376d86d64f4a94bfd5a1b83fe \ + --hash=sha256:c10ac5e3e76837180656079008f71add8339b00c3c26314092bcd1e8e449049f \ + --hash=sha256:c753b820738cddc097892fee95e7cd716fbdfc9640414c5e9ce9463ad125321b \ + --hash=sha256:c85a0a54a19429a17ef449e967baffe7b5089cb4f6ef2894c9168a69fa024d05 \ + --hash=sha256:cadd02ca804d6ebe799a7af19197d9730094fe2cc74b70eb4f374f4b8c1886c1 \ + --hash=sha256:cb43bb34346155d479acdc5423afccdff79ce1fc66adfcc9de995cbec8a13acf \ + --hash=sha256:cb7fc8820b206932ec6d8f8985aeba6edfd2932e13b6c4bf2434d6bcbbeef3e1 \ + --hash=sha256:cba29f12cd717f1cbbe220edf005666f8df0453347217748331a0c2f7522eca4 \ + --hash=sha256:cd69c99affd1b4debc1f9a53058ea6e3a9b34f2e733840bb45891666cd8ede0a \ + --hash=sha256:ce0f884408938fbd72e764031d0e23a8f5e438a7bf73641089c7a6465cb84456 \ + --hash=sha256:cecb2c778f00a65c6ca01410dd194d0e797a9eebb7c6dea0db87718719f293c7 \ + --hash=sha256:cff7657e79224dea46f2f2e58eb99186656ca63ebe356212210c5c00e9beb814 \ + --hash=sha256:d0381074dc21225951278d7e4a7a2241f7fb86a4d8b94154dfee1411f49cf851 \ + --hash=sha256:d094951489bb7836342c005e790bd005e60b669aaf5c936b96dd5d68cbd2e23b \ + --hash=sha256:d10e49b940e70e2a4e91f44098007dda0bacb78c3f8e31ba7a37ee2ce52269e6 \ + --hash=sha256:d37773029ba034a2cc970b6eeb67dad3bff9d894393c51f6bb1c6b4f563a032c \ + --hash=sha256:d4af0d863e72f3ea48e85d3aa1d1b426fd81e9544fd7976fc6d6753584a25b03 \ + --hash=sha256:d5738cd929f2af8651ebb284467acb58b1ec0f2f4d42489cd0597172bc82e15b \ + --hash=sha256:d615377a8e7bfc4f1983ede3f411c2ac2b0f7c3053f262d0437b7d8bcc4485e3 \ + --hash=sha256:dbda2baafe08f8431fd3333be02c261023fd454607e3bde5e7dc00565f7bebcb \ + --hash=sha256:dc6f3dcb08c4b41e64f2d6cf272b5686d9144db585b2e138a8b1664376ab3921 \ + --hash=sha256:e0f2b33a6ae233f4da38c77ea32f90aab2cb82ba819d7b6c4f1b68cd33d871b6 \ + --hash=sha256:e47d058c2db95010f5d2e1f6037acebdfb0e2fa4507650e1041437985c91db38 \ + --hash=sha256:e64b86d16158954825d12799271979c6944c1fd1d03575b2f22e869c3f7d00dc \ + --hash=sha256:e8af3e6f1bdbc31fd762b094133b478b89988eaebc63cbe82b1d9e3bbd15cede \ + --hash=sha256:eb5c4a5b1281985271b6c29be53f2c1a9decf11e30a0e2733439c4d9d61b9ebb \ + --hash=sha256:ec4ee5d2d624088775e61cada87bbe7629bfd936bfbd57f122a106970d8ab1ee \ + --hash=sha256:ed6c107642a9acaa7ede32dcd428a6c87e302c5d555ecd3ec132ffa8c6155b4b \ + --hash=sha256:edffdb3950d3a8b769ddaec3a0962fb7b76b3c96f317f6b88500455a537dded2 \ + --hash=sha256:efe695cc2081633b02fcb95bc1b13070f6647c9ad52d42a8beeb3c2a7ea062dc \ + --hash=sha256:f07f06db2e333b68dd52560b8b0b12b6f8bf6053cedebf9af4aecfecd2dc1b32 \ + --hash=sha256:f15205c67d4c45250fcff5da077f0ae54102b5bc39e9ee8bab90d99e09a728c5 \ + --hash=sha256:f2087ee23a18d1d618a135eedcafba7dfc40c6be4e8e52d7f29a1c8a2344cfcc \ + --hash=sha256:f278f118f9fdb5faba5a6792be397fbda094d1568efa4dfe8c3595ce4ce89eea \ + --hash=sha256:f29885fef157a602d1816439e5da964c70ebcdbbcd4bb9d2d21b7e8bb5636604 \ + --hash=sha256:f2cc27ec6a53b1d39bab44d2b9dd21cc31e796d01b5e18a76d569721282bb264 \ + --hash=sha256:f332b16911ffc668baec6aaf8f08a09e1af34a8ee87ccac26bd722589e264645 \ + --hash=sha256:f5812cfcf7daf3ace5fedf6e2ef8d4b342c92fb8ea3a87c1aed2b50453271093 \ + --hash=sha256:f62172cf387e92f4928b60e5936b02c06e3c8449ed7fb440978d6c9bcbfc85df \ + --hash=sha256:f9c118e866164ce05498d9106a4bd01e745321403cd6f0b77a0b2587768f8c06 \ + --hash=sha256:f9e78d98a29e969a001e953eb09167a48bbc71249e804dae5db987ee7e6531c9 \ + --hash=sha256:fa0ecd064b0ae18d235283abb5adbc4e07304dba8f2aa7c0d61f28bebcc70d4c \ + --hash=sha256:fa949c81e3865c10f981dea72fd8d418b59edd13a047a0aee89ae64790113d53 \ + --hash=sha256:fba33e264cdd2ec43b762b9960d1648478eecfc1ce6e8159e7573510f0412c0a \ + --hash=sha256:fc45ff19520bc5321dcd9c6dd7df6f35ddd894eed35e5be65d1828a9c3f5e7fb \ + --hash=sha256:fcfebcb537f419e415b6e2bfc77ddbd33abe3c036f0105410a25a14741df9c31 \ + --hash=sha256:fd24c4425fdb8e822601335602375c6d0cb020f7a368e1d5842eb7925a9c8748 + # via + # aiohttp + # yarl +openai==2.54.0 \ + --hash=sha256:89089789197ccdb87f173a03145ed1598d00795220c93e96cf712b1cbf5e5f2b \ + --hash=sha256:e3e6f8bc1ba30ddf381ace1a14340eed381cb984a1a59bd0f34b5be3b5d49cfa + # via litellm +opentelemetry-api==1.45.2 \ + --hash=sha256:2cbd737377e710ee740d261c94e93fa0f08e6d037c18f17513cc0a2d94479a34 \ + --hash=sha256:d7b0008e21e5fd61cbe7a7f34ca3b6905a78ab677d9bc395e299359c75cda6b4 + # via + # fastapi + # mcp +packaging==26.3 \ + --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ + --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c + # via huggingface-hub +propcache==0.5.4 \ + --hash=sha256:004e685b315646c410771836e72a44f143bbe624f29653a42687815069a303d5 \ + --hash=sha256:02c0a34f16889cf800f10f0247a564d8ce6eeab6ffcd7c87198f769067eb8432 \ + --hash=sha256:03969626faf0783a592dfa17e28eac06018bd0b44dafae6943d53b92421a7f72 \ + --hash=sha256:03b229037d25b801e7af53fd52b9fc49d9439b036fca1e087e02780631adfa97 \ + --hash=sha256:0951315a6b3142ee2167404d707743f0157c110091342b1aa0accac5cf0e4acf \ + --hash=sha256:0a095db8e15a6020db149ecbed6461939fe74f6acaa3ae8b702a1fe8c38cd983 \ + --hash=sha256:0c889f6fa84957bc7e8b4eab71fd16a0455068d5045e3aa40c733071d2b2fd77 \ + --hash=sha256:0d21d0d2c82bbfeb1677a9711f38df968f9837576102bb4add1bd449d28d88f1 \ + --hash=sha256:10ef33a68a61ce317e095fd2e202a592ea92392b90944a78c993f0d9a73ab06c \ + --hash=sha256:12682126712ddc19b70ff819debbd279e58adf1f0c8f8f8138c18ade2044b284 \ + --hash=sha256:135036c5cfc93864affb0f9af9a27e5d7a71cb7bd745e7b6dbfc2d56cc30e827 \ + --hash=sha256:13e52b6e0bde97dee98ab66552dbff2931649c96f1ac432eac299fe689ec373b \ + --hash=sha256:141fdbd73748db0cf7636035030aaac383d2efde8f34e7bc24594cc776d225b8 \ + --hash=sha256:146f48a9e4812611a7581003b1a39de56c34967046310c4171a68ef908c9a745 \ + --hash=sha256:174507f82d3594622acb1dd2dafecf2d899d6d506335494e7107767bf05f3aae \ + --hash=sha256:1783582065a1f07f9d9ee1e992e13f15d7dc8fb1eb3a7476d43eb3f2e69d26bb \ + --hash=sha256:17a7400cec0256f0a71ae71f9da398f9894c956ff6668a1c9d317b3367316320 \ + --hash=sha256:1b2f3bec4261a94019575481c726c29850f72e27907773c75b1de421e20e9f9d \ + --hash=sha256:1d759d05634f1b038fb625a66662a8c85e5a8fec912da381b5149ddac107482b \ + --hash=sha256:1df8d8561b21465c5dd56110a01caf897e026d065b4b84e98a488209094272ec \ + --hash=sha256:213bb68d9ced5cf2bf717b1071bf2b09b4b04c426256f9fe6d054c60318424c4 \ + --hash=sha256:23278f808cd81d5ada7184a76606b925fb3389c60e1077b2cd7da7b1fcf0553c \ + --hash=sha256:251c63dd46a0659bb875cb254dc4c1e79ee91a847c737cd62373295afc2235dc \ + --hash=sha256:279655a16973f1ee2bd2fe79973137681642fd9ae0d89215bba263726eb0dc3a \ + --hash=sha256:2814ecd8e818f487bee4b0f921bc4d1c176cc5fc71ac0f072d0fa67eda4ac14b \ + --hash=sha256:286867fb156488c251a3721766e380ac4495e4fd6b51aaa1403d89ce7f4359d9 \ + --hash=sha256:2dba2f02d2d5c09ef8a0e6c1a42aeaa451f4be9898cb00b04fe98717da2eb23b \ + --hash=sha256:30cc1cebaf9aef49db06357a50398323ae04d70460c0491837d026ab7d6452ea \ + --hash=sha256:31eb43ba2edc704ab2ec27815315dd8a19def0fb16215be4cfe8d32fe78ffd51 \ + --hash=sha256:350b272b2279f4135a64fc0c304a5d08e28a137c9573442c606152446638a831 \ + --hash=sha256:36c0d9db44b523ef93d03341b1c42d69ff01d673c053d1b1c6c3a363bcaa39ba \ + --hash=sha256:3af0c8642b2da4815d86e631232ac8286e17644fad907c19508aa8e7cb4ba8ad \ + --hash=sha256:3cd3a7edb6b95b9b33998135ebfa18d709da82290fb8f27c858970b5a12c8b56 \ + --hash=sha256:3d605bb239b796e82a81c6709548b2bd460ab73b4590cb0c83de8a2dd9694d0f \ + --hash=sha256:3e413d7a4a9b4866b7a761d6060d434b64d23cd35122eda3b026a0bbe8196b25 \ + --hash=sha256:3eb2e820e8e2101407da93f17c57cbb7d225461955fc60105daaba14cd421ee2 \ + --hash=sha256:3fa15757fea1dfcd5b7745cad9f4638929605531bd4018ab2adff7955f1a403d \ + --hash=sha256:3fc24f209c1b7f7f688b66b98293954f5504279760999b58920ee12dd8471c1d \ + --hash=sha256:4054acf80d40456a0537f2913b349718649d8d6458a14ab7f48d0ce28c30869d \ + --hash=sha256:40e94adb1e7d39ff28a8bd8d8b8fbd1df6b9f40976dbe379134f1ce058e532dd \ + --hash=sha256:420162a77f94eb1cf5ef7893f500016dabd548e73de956785a1dd899cc73006a \ + --hash=sha256:425f8cc86ab5018b4b8d4a23bc8e74d964bd3d757c3702e301aa79be76c53f6c \ + --hash=sha256:44149f46500a0a41b95b4d99c2e586a77319539730607b9892974a092788b111 \ + --hash=sha256:445ee3bfb46e85838387fb3c536a73cc0b994dc192b004e40e170adc54aa2a7e \ + --hash=sha256:45488d1a5f9ab5bd90aaa1ca20f50fe1922b8ffad71a2009d2adf41355897aac \ + --hash=sha256:45bebbe252550fec975ba3b62bc6f931643cfd3b5464ef47619cf3fef154e01c \ + --hash=sha256:45bf2e730ab8905d0527fe05a86500f406e64305c34cc81ebe64b4617cab9760 \ + --hash=sha256:48cb48c5346a97de792254af77715aa2529c2a1ebc5f586aa0aae44a02f1fe57 \ + --hash=sha256:4a1f4f5ffa55dce6307631f3cb2948e117e665966ea512e0d502b16c24f567e7 \ + --hash=sha256:4cfe0a92ae30151869e67a4b5f5e105e4e03ad30b3f38e5211b5bf77d0881993 \ + --hash=sha256:4d86476a935c88963d9b8e1a9a0d38188790e9622169bfbafa173046846709d3 \ + --hash=sha256:4e985382be6d15da8d0c2710a6fa7b9070fc9ecdeefb7f580e88373984ec8be3 \ + --hash=sha256:4f2d880ff60f45898f4acfa152aac8d04e3ee627d90ff4003491bf92239d5757 \ + --hash=sha256:4fbc1a15dc8cd1689508758d626b372b1f09d28d9577667feaf9e6bfcd8efcbc \ + --hash=sha256:50e337653721d20ead710da33bf44487fbe8a0db8782714b60306481e9f95b51 \ + --hash=sha256:53eaa697c4d0422ff4cb714d00231b43352064d97b944033b30c1d57cc506ec0 \ + --hash=sha256:56fc3f7599528db40b1efa0889a620116e2704144495273d66066e8164e45838 \ + --hash=sha256:58134228927cee6c047d626c08e60a81be604a20578a12ce752cc5c9a84d4826 \ + --hash=sha256:594eb4c6ec35e7179b058481f4e9f02521b56de16fa577c4b85c76fb1bf8a9f8 \ + --hash=sha256:5cacf3c9efd09df409dc33654dd077e1c245ba8fb747b0f0236ef41b7c49b589 \ + --hash=sha256:60a64cbccaa11b7760ce705a14ada17ba459e7ca9f23ba587eb013821032d7ef \ + --hash=sha256:62530ca89187827e4a4fe733f971abe81a7542eeea48ff61995f19b64d7199c8 \ + --hash=sha256:62c60aec739ed00124573cce1178138fd690c7676352d67a37328c1cf51d7468 \ + --hash=sha256:69fc35c0779522da366c563e5faf203ffc1f8ff0021d5b1337fa4efa5be73177 \ + --hash=sha256:6af4693716bfb03f1752ef1b30faa593db2c01d5272e9b8564a1549452a979ab \ + --hash=sha256:6c7599df2b57ebeea8de011b5f2f7b85de95e76037d43d34b95e328430275487 \ + --hash=sha256:6e9368e87a3efc285e559131092c5db643eb8e56de4ee42064d5baec22ef2bb5 \ + --hash=sha256:6f0093ac3e9daada202c2082439d414a625c57184727a46e112a3fb2a81cb788 \ + --hash=sha256:7177c43eddf10a0893c4fec52ebb408fdcd7f7d63962caace9180d8f81b14ece \ + --hash=sha256:720cf832eb2d0b0dfee129cb3335a26f6ce3cc45ee1187e8f0731758caa16792 \ + --hash=sha256:770e8209d018175fc0063936fa9583b6d27e88c5ad31543f3383d66080efdd62 \ + --hash=sha256:7a8d5ff04eb1f85698a78d20c62a14676e7b960dcafde09a388d60ad377d355d \ + --hash=sha256:7b9100a93b372418d8688f3f2a3e5b45c64d70ca4d6176e121aca1e3bfc1e32f \ + --hash=sha256:7cc528e760a8af06f2b13e9b9f362cd90c7c718ea61228a96dbd31ba16ed7f47 \ + --hash=sha256:7ffafcbfc7b549ab940047e505c831eabac5e67de53e1bc174adbc5285c55944 \ + --hash=sha256:87a3caecf8095e48dc72f84bfa42e23a848cf410cc9cc13031fba4869b706a21 \ + --hash=sha256:886b59c4d28ca97dd23b025fdfc50a0356be934efbbbca89ad26230067f86fe5 \ + --hash=sha256:8876b39961e33d912afe3c1bee18ee564fdad0206f873cc15d522756b7f50737 \ + --hash=sha256:897d1ddf6716e8f47200f7aad9a0efa6cc7586df66c6defa572f9eab379c078e \ + --hash=sha256:8a1fc236528c457cd739c88abe823da851b7ab645d72792f88658114cc340c12 \ + --hash=sha256:8a235f73d6e020855dc29dff012d920c02ee0feab8d73a24185a7569f4be1161 \ + --hash=sha256:8f911c395cef73c510bac566da9507bb6a43e7763d0c79138dc60ee53f11207e \ + --hash=sha256:96f7c5c15656040ddcbc51e56dc59b58aa25999d743c126abd425b9766ab43e9 \ + --hash=sha256:978f28401afbc76cdc3df9e1717b4229a06b626a1dcc75db4e1f2beb3884c3e9 \ + --hash=sha256:98914de2c4d7f0f9f4a8c6ea4bf05841f4175796941e3ef7d47eb718f22311fb \ + --hash=sha256:9a2a8a50a93dee0268a860a07fa3b4bd968f8ce4dbd794957da772f395368526 \ + --hash=sha256:9cbfff4423eef4cc6cafc021469641a2b835f610b2647a6c5281903e21b8670d \ + --hash=sha256:9e9ab13760aa8b6d0881ae7cb04fd891d8d490cd2554ea8e79bb278399169bcc \ + --hash=sha256:9f3551b8a35c1df3e7ea4d2d86edee15f0dde1bddd434a71744048683544d0ef \ + --hash=sha256:9f86f7259efe2c951f43e57d471c9b41daa5bfc7db9f67189059cf1ae6d77fd9 \ + --hash=sha256:9fb0a5be8d9aa213150e8d8148a42aca4984b285bcad1e69587dc4298edd929b \ + --hash=sha256:a219f0ac59817a9114dd2aa57c13180f993e819ba658c7ddab4b66ed1ee0d370 \ + --hash=sha256:a419ee85e654927baabda3929c03c0cc1112bf472ff0dfd6142f4e3a81ca4162 \ + --hash=sha256:a4d7a54719b67338a305dca2ce6aafe366817df94ddfd4b5514374356f5ca546 \ + --hash=sha256:a5793c7698a53f56f4a1889a4737c7eeb1b7ad0842fa6b1abca22913ff79c8c1 \ + --hash=sha256:a5e8ef588c109725dc713ba69aadcac00a1ef90c2ce9c0a8c7075128f569f47f \ + --hash=sha256:a74bfa37147cc08fb29df10bd9c16f40fa7f860cd3a6d2fff853323a94f6e17f \ + --hash=sha256:ada748108a43d29b7c328ba7db3755327cd94f028bcc1a7ee3f0addcfacd9c38 \ + --hash=sha256:ae58f361bd5dae942717c65d3413b478c70aea9c462599e7b9adad3731db3894 \ + --hash=sha256:b28f41fa3b8c6900457f858ec5b03998f3a6d535fbc1bb2edec5961ea05ec429 \ + --hash=sha256:b3083bfe87f95c756e610bd8025f26cbd1cd4aaa03a422f2d65efb7a97cd53d8 \ + --hash=sha256:b61805357d966680acf68b3b6d49772631ed9df44ebece10ff1460e117a7da8a \ + --hash=sha256:b77c313314524ca9c38fbd70f73515d04597ac58c40c939bc0e71eeb4abff680 \ + --hash=sha256:bee7d3aed13d56f54e681df38c3a23031bc9e3863f687d9d598825c9146acd7d \ + --hash=sha256:c02c0e570c5c7e077b0181a9f3cdb7d4c3617d1cda6b5c95bd5d34022923d82c \ + --hash=sha256:c174bfd1c48a1b51a3078e95586dde718374bac79719ab3541ec9e74aec40574 \ + --hash=sha256:c2ba30a89035b57b73e00475de948521602f543d79ce01db10b04b36c4c76fc8 \ + --hash=sha256:c3e98c55bde2bcf7db3c70d1aed7ae9aa8aebbf19a250c66645cde44cdb8b867 \ + --hash=sha256:c3ef2818d63bc86071e9d2989ae75a1bc32b8f7059cfd9f5abbbee70c32e2ed6 \ + --hash=sha256:c83acbce9f2b5e3f5f5eda9e53d2001fed22fcdfef81274a9e02d8fd53b70a30 \ + --hash=sha256:c9281e922c072158c91974d4589f1dbe0fee6d467f284c28e463f9f5a4d933f4 \ + --hash=sha256:cc07876cfb079b6f6f36d21ce75784ad6c2c6b563eeac0ed26c2fa2669b85df9 \ + --hash=sha256:ccf4f7a79e26bb7efb06ecd50c177833b71df05cbc748701372325e6bcc17f6f \ + --hash=sha256:cdee8205a44d0be91bbac4c41b95d86641b72dfc7aef1279400e4fda3f26a937 \ + --hash=sha256:ceb3e879afac028f93d272c957814695dc5569e4904262dbee92f6c41bd5e4a3 \ + --hash=sha256:d1f5a500bfcbb2c0ab85e98a0dcd70f5899d34efe365a0187700369a79603031 \ + --hash=sha256:d42a9a856a4a6e2f6c10f1318c07e7daa498d6593abe745c71dae4521a26ca39 \ + --hash=sha256:d83b12902eb8bce151259c86c03ba746600b2d994543de46e370cecf96c452f2 \ + --hash=sha256:d8e017eeb7482bed34cdb0d61cf2bcfc88d104bbab296a17cd16a6af8aabc70e \ + --hash=sha256:db3ae52ccc150dbc84704e9d642743897f3e1c54742ff34cacb661e52e3818a9 \ + --hash=sha256:dbab5f5ff6897c81f355d079010cdae85b02e5a0b518b5251523b8ad8ae9ac3c \ + --hash=sha256:dc4242ca653c9b30ab51c5f8193323e7bc0928f897ee9103201e59a43abcb72e \ + --hash=sha256:dcbf346a318a5e30063f547630b02bb787ce2f45b6368d5da143660b6a3835d8 \ + --hash=sha256:dd2ac8f5b643454c2cc6b6118b13da16e88f4a6434fc3ba61aca384029f04f36 \ + --hash=sha256:e1d52a05dc417279f7e5c7618c5dfbbc29923aaf9bc0a5c1802ddcebf54c61a0 \ + --hash=sha256:e6720ba44ad7e72174314d0e1fb0172494cff5c73a3a8a2159c3d2402ff15565 \ + --hash=sha256:e738ab81179510ce79b2eac9a6ecf47feffd9e76d1c72e403005dddb6e36c06c \ + --hash=sha256:e904d4d01f36bd6e197590be1533c44e06058771e0746dd073a8ebb3ef880858 \ + --hash=sha256:e9f165403b81fea7e89c932d89046a1e3d9a3a60e8d7ef2f249dccdcb0982bf5 \ + --hash=sha256:ec6a85f424afa8d23e0d9a094e5dbb6eda01da91c92b9183cd433768247ffc97 \ + --hash=sha256:ee19113bce2f3acd46432050688b70f61acd6857d75abb9ec96341b7e9ced123 \ + --hash=sha256:ef3b928d9c984322b5c44e6964d8dbc653da87d2d8ee1647fa6da43072e650a9 \ + --hash=sha256:f273dcf7149a50527c4fd1f55cfe9eac0f60753f5af544b4c9352578e20c0874 \ + --hash=sha256:f5470694918830da62fac9e69133b53d23b736d7070e587b27a4a2be37e08e68 \ + --hash=sha256:f574e460d1c8a08384a016fdb09ccf3543433263ed6b2f97104f979e64ea57c2 \ + --hash=sha256:f85915e00dcb1cd9f2f890ead064ed40a27df06f0db65be427b29482ae357572 \ + --hash=sha256:fc2461ecc45f17893f8207e73b46ea8ba93e33630e51cf4af3fbc21d47462b1a \ + --hash=sha256:ff6b113f50bc066a698db5d944d2c6dc7507168dd3341e255a8892fd0715a558 + # via + # aiohttp + # yarl +pycparser==3.12 ; implementation_name != 'PyPy' and platform_python_implementation != 'PyPy' \ + --hash=sha256:a076f3f489b39b43ed13563a1dafe42447445bec2e294154ec5c57fcdda4c85e \ + --hash=sha256:f03387877eab82ce01bbdfd0ba7252ee55a90b1c708d5129e2ce915475cf1db6 + # via cffi +pydantic==2.14.2 \ + --hash=sha256:7efbf7507b937931cd32a5755acb00ea1cf5ccb1d4e8067a5850d5069e382118 \ + --hash=sha256:fb7b2db6cefe8414dd612edeede49c4c433acb0432b0f92b95024e45f66c505d + # via + # fastapi + # litellm + # mcp + # mcp-types + # openai + # pydantic-settings +pydantic-core==2.50.2 \ + --hash=sha256:01eb0282d0b3a065d55956d1be9ce398c46db3dd6d277a6cb2358c8aa8c53179 \ + --hash=sha256:04cf672960b8c4fc28bb159c8cdd101fbd311c520237a5c0360448b851adfb41 \ + --hash=sha256:0b94a515f44f1ebcb25395bcdba506c4cdaf6d3fcb0466b9658521b41e5ff057 \ + --hash=sha256:0d090ae76d5b09c003600c7779b3adcf3d1b49268f616c5c51d844e54c8e318d \ + --hash=sha256:126f158474346f457c0759c29c1a6334acd5f7f99dd272bb27d19314f3d81b4d \ + --hash=sha256:150f6e101f575c21a4ecfed1be1c05bb89a0ad49cb9c846ed377583bd71b32c2 \ + --hash=sha256:16ec8e07c37f02dcf68939cc7f202ba9a148cc155ee2acf22d337e10b24c2cb7 \ + --hash=sha256:18f008ef58cd30782f81b6e0119e20b7e884edcefbc2d370162ebe033f6e5c99 \ + --hash=sha256:196b87b48b2695426920e8470d20f9e99f019ebd86f15808aa018b68086840cd \ + --hash=sha256:1a5e859f5a8a6d834b0a13acaa0eaddf1a9b4b015fcda13bab7b471e18299d32 \ + --hash=sha256:1ac5b99bc7b0a68ec64f5f75a6828a7bab5535c8df0cdc07901deb50e0815910 \ + --hash=sha256:1b0e8dc3932cf4e9ed5727570325cacc716b9409ffc794a221c0ccc72e8eb775 \ + --hash=sha256:1b9f652e17a13bbc09b45f74c3c326cca72059ce4dcdef687fcb04389db413a9 \ + --hash=sha256:1db9cab6197e797824f0479dd2ae5fd2e272aa61c61b7faa5a6e450ca7a0d3b7 \ + --hash=sha256:1fdf5b52ed22f1404c2433d0b46df2d86d9befb742d0b9b4042a2325c43cdb97 \ + --hash=sha256:2115d7ca6d58554af8a14da3dd32d361a4fe999fae52f115a6155679b5b00e72 \ + --hash=sha256:21a902e546032c82b7275552345a2342d862e0541aea7226c91067c396e68b3f \ + --hash=sha256:21ea3b00f1e87c66f3f9e92f9f6fec20495ac0e60d7d2e68ba1fc49739d7cf40 \ + --hash=sha256:23385c4626f8b5a7792aa381ea573d9432cfbf4c21375a0a5eed2a4fb64e0e58 \ + --hash=sha256:240fec32a74af0979f7253532859b3fd209ad5eea822416bb010929dba445c3d \ + --hash=sha256:24120c644322a35b5eb765416ac8442214c45689e255f5fc6e761e7e7c743c8b \ + --hash=sha256:26b778d4ebb75f181d36220ff0f54a513fc46f053d9b09ce79993c2f00bc45cc \ + --hash=sha256:2d4a043c820363359e40ac96270e1915e5376e116be1f59cee0701775de3e376 \ + --hash=sha256:31a1fb3ffbd1195b24490f671d12623dd4c9bfa56d6af0a299fa43b516134f5b \ + --hash=sha256:33c6800ab9563adaa0d7893e9cd8f5b972ef1e6a23df70498e05c24f3fcec5e1 \ + --hash=sha256:3435c443da7510a6de1a30c68beae338852a11f0440cc8320ea756a162f38dbe \ + --hash=sha256:36917e29c0b815d6b940bc91560fcf453b5b85d55c579796373f0ea11d1c111a \ + --hash=sha256:36d8b9725684ca3bf658b90a101d335fc8cae405bb22196b7b5ef41344913756 \ + --hash=sha256:3939538e640c94ab779a05f2d45dafedd01d65d93e1290797f3ac5b59fcb6455 \ + --hash=sha256:3b1bb3950e0794a795c9344d818d5b476189b0c9c9755e8eb8fde87c3acee17a \ + --hash=sha256:3bfe12243b3ded517c6734d91f127489e2f51bf95cb533b53130fe360333db80 \ + --hash=sha256:3fbcd402e4b607d4b8de5d4591215f31f042af03f9d09e58f693a6221e32833f \ + --hash=sha256:41ed8abeffda6a880207fdc0cd1343a448cec3cc6b38b53f730c0745f745292d \ + --hash=sha256:43a8fd56f3c681f3cda2d5c842ad28e88241df742dfcbe8fd1dd437a3056e1f6 \ + --hash=sha256:48e944091b7bff233920bed8a60b0ed6c96c73d3c5836bf51c4b9a4bfb58e4ca \ + --hash=sha256:4ac996e42a93d80122a23edce44e02c6b9c4913f5c6198a077da31475341a39a \ + --hash=sha256:4e9392ddf67fe97ab9889f796d468c9908a8754b8b6c7520eb03a65012b9a1e7 \ + --hash=sha256:4ea01f30e119f1ec7a2034e85c40f491d469896aef02cd6436fd9292fe1be3fb \ + --hash=sha256:4eb54c25e3463d73e1e4ed439ffc45d1d7e590df40bc7bb06f11a906afd996c3 \ + --hash=sha256:4ee64baeab403b9de9c92846c5c1abec28ffb046cbc023bfae059897841f88af \ + --hash=sha256:523fe6574aea50f456cbc301c1cdddcbf237939f7657f9af99b4f0f71942b59c \ + --hash=sha256:5299296ff5cafcb69851fd652de8f9268a0bb036bcbedbfcaa94cf743baf3986 \ + --hash=sha256:53bd25e8ab54c02bb4c55d4848c1d36f75f3b9a7356e83179fe27794d9e9e6c4 \ + --hash=sha256:57bccd3e1128736c792094da1feac6da46ec3feb1957ef649a9b3e4f8de6fa04 \ + --hash=sha256:596921489390a002d6a5e303384a0f1f98384f8bb550fbf38a1aafa6093da0f9 \ + --hash=sha256:5ab5738c39b25b5dc5a721270e2269a2f5e86e614375e6c07ee6caab8cbc0f2f \ + --hash=sha256:5c12a5a080570a91bbcbf6d10db008b80e3f5dea015ef2f0137bbec70f24f3f3 \ + --hash=sha256:5d3cd8be71c4da3c9b42cc92f17e5e3036bdca98bf18555a0e072c3fe87abbb4 \ + --hash=sha256:61e13100b30d8d25fc0d1f0297014b32941bf0975a3584bd08f3adebb68d1ead \ + --hash=sha256:6258754c473b3045a7aa30b833a8a331a1ab36c6147cb230789861d80bb26f83 \ + --hash=sha256:6a438cb8a3f87f2c49e82e43fb19511d4d5043f53e0787dc4df937ccb904373a \ + --hash=sha256:6c25b8826be85714b27dafe908d3461e1b09e3e31c0279a7029040c832c781ef \ + --hash=sha256:6d47b2d0e00e030e0ebdb08115a37da7294e7a6d196d134a77ed7ee6c142284b \ + --hash=sha256:6e731bf5a5e8e25398544d7709e39068ec4230b0177e4db7fa955692fd415ba3 \ + --hash=sha256:6eb6ff07964f39e33c6f57fefe939514e76b8c0d4a694e5663e2e04e80cc1798 \ + --hash=sha256:6f5a432c6c1ef18a1a02a04b3616b8d3f2f88b13faa46caae1ac6559ab202234 \ + --hash=sha256:6ffb4dce3ecb2cd563aa30f9eb5088a1cf1f4f688b90cbb374fa96e49fc50b02 \ + --hash=sha256:701bc55d08c22f981973ca4f6fdf4ea102ee1ee3a21b818b66fdb161ea711a4a \ + --hash=sha256:713d7c33c0e231e3786eb0ec95885814dd65d5f3a09754399b6acbf5e9365f11 \ + --hash=sha256:71615edeaf1ae70f5f3f558426072eede0168b7e5190fd9633878e29a0b85732 \ + --hash=sha256:783abdfac21247d33bec40aa683d26bba30d61655c40de38b2decc4797aabf92 \ + --hash=sha256:7c539d452cba22f250103c7d1c00cbe9038eb705e657476e701c43374efd9f2e \ + --hash=sha256:7c6e1bd6cadae13958e52897ef020e85c9916a95917149fca463bb0c0421a7c6 \ + --hash=sha256:7f9821dfc0c473c96ad55ce4189c7cb4f9c94e7d4f563afb874173243dec1162 \ + --hash=sha256:823b222c4fc861a82c650998a6117ecbd150cc71bf8b78f9a31bf3f48c456108 \ + --hash=sha256:83d6f42ae6eba44548a1a3d4f900a5b1500fdd14f09f04754a8800ab0d544432 \ + --hash=sha256:8431ecb131489cbdaf6f51f7ade47475f73aff4f1912552f75ba19a6cfe233a8 \ + --hash=sha256:848984e231190ae49bc8b5229e64d2a6fba4231dc6046e1b6b28ddc060bc7601 \ + --hash=sha256:86e7abd24a67f61a4bfe8df059b67a2bdd8bf33705178e98463195d140bd3780 \ + --hash=sha256:8772c2c0091e6fc2d0499151793d31bf811826986b0727052935a95104845544 \ + --hash=sha256:8835566b3e94026da3ce2249f9ee35c9d2ebe4cd131f6a39bfc82708d3010a46 \ + --hash=sha256:89213368eef163350af37127939ace099010e8102757905c3e329f1175950ed8 \ + --hash=sha256:91238117cd296352f54f24117ff5a227bdea428865dba1244aa0cdd1424c0bc2 \ + --hash=sha256:91315aea7adb51821d4a3378ede953bfdd76e3bf71551de4a82d7638cef7dc02 \ + --hash=sha256:91c92856b846aa690ea6239ffd6c5003c5e3e296a69095570bf4efee5bfa0bdc \ + --hash=sha256:928a44ad1e21a7e923eb924d601605f0694cd187d2ce5d40bf7ad76650f4627d \ + --hash=sha256:92acf02c770b9d5c4e9a3e8d64e9d95ae26456a86ebb7b7cf64a97f899e5871b \ + --hash=sha256:92ada606285dab054e40848a951f583c537cde1e54701ea1305ec0096877012d \ + --hash=sha256:93bedc68c4138088ea3c042189c01d2945f530f0dcc36e1ea02df8418bd4f1cd \ + --hash=sha256:93eb41d626d9a2749a678823c70bba8c25033cef474ae8001fd7621adbbd8437 \ + --hash=sha256:95838be125133fa314753f8cc5168f7c41e3a9dd5eef5383dbbbeed511bd4853 \ + --hash=sha256:9667637665acba166a7dbbc786f14c50512d3a01f7199e0e1a13b929e92d7c7a \ + --hash=sha256:98722314e12a8e4fa346e0afd3fff2098b5732875ff45592b450a7b589b43c4f \ + --hash=sha256:99e1d482138a71902415ba375bb4627679a5fefd3bd07803c3a8f37632f4981d \ + --hash=sha256:9a87744e683d9a13f60b7fa5242c17f8d283ffa94ad727cb19063b48c3d34960 \ + --hash=sha256:9a8a62281fd9c6a373b3fd3d473685e6838d43341eecde5f47729748e2c11ee3 \ + --hash=sha256:9b01a092955c1c7530196ad526755cff4f2d11f37ca9a6fc9ebe37ca49a48977 \ + --hash=sha256:9b2383933b1dd7a8c93e02f99ebfd305f1286057172483b8e6898bed3fef69d3 \ + --hash=sha256:9e7460abce637f90e37f8c443559fbd687c38884d05cb69ef265e634945f4324 \ + --hash=sha256:9eff570402175c7d5fff8497d5a9c05580664a79bb66c07b8f205d17f69e580b \ + --hash=sha256:9fcde11462e0faab4c2a2ae8cd4516f7dd8239eec583bd88c5524d8064ad2d0c \ + --hash=sha256:a1b4d60bad57d6e0e7cd30cc4d1dc646d258dd6dfb7935ce76c7dd72dd1e98b0 \ + --hash=sha256:a3317630e2791f56071b82f89bb71624146125e4311e6643f708c6ba744b5ac5 \ + --hash=sha256:a53d5f11cd6d15569ba3e53f3498077f0d5e633f6ec604d2ea613e895017ebee \ + --hash=sha256:a55c1163e829a08707b4a92c8ee02a5a3a3847ced74aa4da94e3e975ffe1ec63 \ + --hash=sha256:a59db03b80a156a6fbeae41096866d1cb89cdf31031ba44c768a804538880636 \ + --hash=sha256:a786cf782ebb2e45a43c7118d75d452aac982b79577dfe804d8dbf2878f0b589 \ + --hash=sha256:a88851e8e332588cb8cced8b5318d1163c7d0bb87830aa8dcafbc4ae9602b73c \ + --hash=sha256:adec010c824290d4ca87047e8d8bfa4f85ac29f545f326cd5321696805d311ed \ + --hash=sha256:aff31602e8518594e6f6bc670cdb27e37cb7dbeb2d5d0b76a7707b70fe951ddf \ + --hash=sha256:b0b25d647036972c2951059046cb498f72b7af5a2def27bf8e5f44c3067ab7dd \ + --hash=sha256:b0e6a2152706d84f7da8b9d34dcecc7e9bde678af32c40bd5b405f427ae0fbdb \ + --hash=sha256:b1adf2f37521b578c438f6ec61d1c1d0c20b076863ddd5d8b6f3ab658857db3f \ + --hash=sha256:b29b7c5adf4b2be7c941f7f76432aa3269cd5052ff8610376b8ece24d7b02c51 \ + --hash=sha256:b2dd65864aad38dbcc57c3d0e2c978d4286e063378137d8fc0c9fcd558943285 \ + --hash=sha256:b381574614245f18fdb2d6d1aa8f149e225869c47b5ee7f81812de8977817314 \ + --hash=sha256:b3e681208e2d39fde13fbea449ef2736a85ec1ea2afa41e9193a8c536e71dafe \ + --hash=sha256:b5675a12a7b67063fe3ca187e735b0463cf13fabc10166ae4d4b2f775fd0632d \ + --hash=sha256:b583ddeee6a6bb5bbc04462167c68034913221139d52d9f155ca6d1637a2fdcf \ + --hash=sha256:b62c89545d21d930c333208fd548e7b4f262228ba3a322fd75c987a75ab11f31 \ + --hash=sha256:b7abcfaf66c1dc14c5ed928c349614f223c972a8b021b4be9548dbea6c817371 \ + --hash=sha256:b958c217c6e56bef261f516e4caf5d490b079ad6a428752afada5a764cca6c71 \ + --hash=sha256:bb6d49f00e2babd40af4889d6b9f4bf50879f522dd4e2e22cb705cac5e0c5e8e \ + --hash=sha256:bd1fe69056a19c377a6c6de2c1240fb8676ba0512a969965efb486510c5e0f1f \ + --hash=sha256:bd6ecae08c0d871cf93b6f0d4ee76b06c65be44ea22311981a022b2f1948cf9d \ + --hash=sha256:bf7f99a0e6616cea754e2334d129091f3260d011369d9b8c658522bfb2427619 \ + --hash=sha256:c1b65a42afc73b39e6ae908ec7b9c3b9898676a7b15ce4c66d4965f7071007c8 \ + --hash=sha256:c324a7e0c0012e3974053f81a270d8f1aa23227571f4ddd3254c911bb356459b \ + --hash=sha256:cb8d2d7b07cbe2d7488de7e53671f836c4f4a8032dcda079df33dc1b7e2397c0 \ + --hash=sha256:cc488daac19e6f5292180fac5e0ef7efffabeef4e096af9a17a75a7d3d6781f6 \ + --hash=sha256:d18d56c1ec63b304f4bb3c7db7e0d311e61cca1b1c944590a4b13ac39b2ca92b \ + --hash=sha256:d3d049b557875f9d15230eec8a731749a7a873d8ed6a051903b05bdf46e0e65f \ + --hash=sha256:d684ff87d00de2f6abcbbfa9b0fdce8b513dd799a900809dcfa7eb62ad69832a \ + --hash=sha256:d71a9a9352acbcb5c73d39dd003383599428067b6eda5cf7c5d335a7a0da37e1 \ + --hash=sha256:d79aaa468193c1bed6b0560d3c5c9f9e369e3efb0b128b38a2537e2d51d42773 \ + --hash=sha256:d93c066a38f83376b5bc020e563666784d1b680a70d6ceb625fdb541af7a312e \ + --hash=sha256:e2e6240a0a5ad847017b3d65187877fdb7a11d5a58d43c30736f9f523478913b \ + --hash=sha256:e3d824b6152e1c0fd58dc6266f2de470eb7b2286135294f5f7cd26a0f0693738 \ + --hash=sha256:e5c801bdf3cc92274b8fc2c7023c8751e5ae81260c009ac558ff55ce712a2d45 \ + --hash=sha256:e80c47314c7233e7105a7efcfffd89d56e479e558189d1959eeeaf2639a27680 \ + --hash=sha256:ea71b94a2eb5d2fc102926321f56d2ee8eddfad2673eadb1d23e9f287a492715 \ + --hash=sha256:eec187d2876abb6a74203efbe2aa796455c1809334acf4e739dde35da8cfb69f \ + --hash=sha256:efad0bdc67d3b119c3bab6b94d341a27333c2bb89ed75dfa182a4a06cd0ea329 \ + --hash=sha256:f078e276848bc23d1f92f46fc88d5b9cbb824b9acc60d9e07116620e502e16a9 \ + --hash=sha256:f07c965a8aa6d62145f122641f292129984f39a3e3697585b19298a1488287db \ + --hash=sha256:f142cd663d1148ed32993ed9a58e5c67ea312f446a01a6c13a956945aafc9f23 \ + --hash=sha256:f47c1349c3b4274aeb18459d54244881a5c0dee0fdccedffca45704ba5c9e0a0 \ + --hash=sha256:f5ba7ef10ce82737e173fa95cafa1c8210918f7e653715b2c7a7a31877a74848 \ + --hash=sha256:f73930dacad5e611fe019e18df6f53c30629b1843d038d303b8dec86a32493bd \ + --hash=sha256:f81df206b937d0dca5efb38c25fc99037d82dbcd3740e34c3f81997d2322ac1c \ + --hash=sha256:fd9aa71a800c87c0f7ab53fa38009169a23a82c685989626ca74a4bd483e1b67 + # via pydantic +pydantic-settings==2.16.2 \ + --hash=sha256:3dc08ffabed2bbd5dc2dd55ead7b78b4e4c5cd776aecd04310db5f1224caaf46 \ + --hash=sha256:8d523e5c129b097686bde019bd6109bff53f4c8c3f63f1ddf9933ffa42e5ab4f + # via litellm +pyjwt==2.15.1 \ + --hash=sha256:42d59d631f7768a1028a64c7ff581a9bf7519804daf91fc5b6c56e30eec5e193 \ + --hash=sha256:4f259e80cdfb6b3fc18a7de51fd1ef9ec79652f25019bae68975ca2468a34df8 + # via mcp +python-dateutil==2.9.0.post0 \ + --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ + --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 + # via botocore +python-dotenv==1.2.4 \ + --hash=sha256:42269a8a5b3fd54ffa6f3d84b18abed50064717576b4ecf03dc4a55d8aa04fdc \ + --hash=sha256:f0d53e69935a851c0dcc78f3ab7aaccd8cabef0b92382b576b824212902873c0 + # via + # litellm + # pydantic-settings +python-multipart==0.0.32 \ + --hash=sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e \ + --hash=sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23 + # via mcp +pywin32==312 ; sys_platform == 'win32' \ + --hash=sha256:02ebca0f0242b75292e218065004310d6a477407c09fa449bfe4f6022bc0c0fc \ + --hash=sha256:17948aeadbdb091f0ced6ef0841620794e68327b94ee415571c1203594b7215c \ + --hash=sha256:3020656e34f1cf7faeb7bccd2b84653a607c6ff0c55ada85e6487d61716deabd \ + --hash=sha256:59aba5d5940842075343a5ddc6b11f1cdf0d1567fe745290359dfbcc7c2eb831 \ + --hash=sha256:5c1fbe4a937a73ae9297384a3da38518cbc694c68ad8a809b2e19acd350f03ed \ + --hash=sha256:5dbc35d2b5320dc07f25fa31269cfb767471002b17de5eb067d03da68c7cb2db \ + --hash=sha256:6017c58e12f6809fbb0555b75df144c2922a9ffd18e4b9b5afa863b6c1a9d950 \ + --hash=sha256:772235332b5d1024c696f11cea1ae4be7930f0a8b894bb43db14e3f435f1ff7e \ + --hash=sha256:7a27df850933d16a8eabfbaeb73d52b273e2da667f80d70b01a89d1f6828d02c \ + --hash=sha256:9fce94568364e0155e6dfb781ac5d95903be8baf28670632beab1b523f300daa \ + --hash=sha256:a4dd3a848290ef724347b19f301045831d8e802fa4464f491b98b1e0a081432e \ + --hash=sha256:a77a90fbb6881238d2ca9c6fd797b25817f3768fe78d214a90137ff055a75f5b \ + --hash=sha256:a8597d28f267b39074aef51fa593530082b39cbe5a074226096857b1fed2dfb9 \ + --hash=sha256:b2200a054ca6d6625c4842fc56a4976a4b47f96b73dbe5538c3f813a80359f47 \ + --hash=sha256:b457f6d628a47e8a7346ce22acb7e1a46a4a78b52e1d17e1af56871bd19a93bc \ + --hash=sha256:c2f03a0f73f804a13c2735b99392b0cd426bb4f2c4d0178e5ac966a0f21618d5 \ + --hash=sha256:c53e878d15a1c44788082bfe712a905433473aa38f86375b7cf8b45e3acbaaf9 \ + --hash=sha256:d11417d84412f859b722fad0841b3614459ed0047f7542d8362e77884f6b6e8a \ + --hash=sha256:d620900033cc7531e50727c3c8333091df5dd3ffe6d68cdca38c03f5821408d5 \ + --hash=sha256:dab4f65ac9c4e48400a2a0530c46c3c579cd5905ecd11b80692373915269208b \ + --hash=sha256:dc90147579a905b8635e1b0ec6514967dcb07e6e0d9c42f1477feef14cac23bb + # via mcp +pyyaml==6.0.3 \ + --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \ + --hash=sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a \ + --hash=sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3 \ + --hash=sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956 \ + --hash=sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6 \ + --hash=sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c \ + --hash=sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65 \ + --hash=sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a \ + --hash=sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0 \ + --hash=sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b \ + --hash=sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1 \ + --hash=sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6 \ + --hash=sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7 \ + --hash=sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e \ + --hash=sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007 \ + --hash=sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310 \ + --hash=sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4 \ + --hash=sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9 \ + --hash=sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295 \ + --hash=sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea \ + --hash=sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0 \ + --hash=sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e \ + --hash=sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac \ + --hash=sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9 \ + --hash=sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7 \ + --hash=sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35 \ + --hash=sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb \ + --hash=sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b \ + --hash=sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69 \ + --hash=sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5 \ + --hash=sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b \ + --hash=sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c \ + --hash=sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369 \ + --hash=sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd \ + --hash=sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824 \ + --hash=sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198 \ + --hash=sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065 \ + --hash=sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c \ + --hash=sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c \ + --hash=sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764 \ + --hash=sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196 \ + --hash=sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b \ + --hash=sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00 \ + --hash=sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac \ + --hash=sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8 \ + --hash=sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e \ + --hash=sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28 \ + --hash=sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3 \ + --hash=sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5 \ + --hash=sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4 \ + --hash=sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b \ + --hash=sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf \ + --hash=sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5 \ + --hash=sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702 \ + --hash=sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8 \ + --hash=sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788 \ + --hash=sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da \ + --hash=sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d \ + --hash=sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc \ + --hash=sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c \ + --hash=sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba \ + --hash=sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f \ + --hash=sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917 \ + --hash=sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5 \ + --hash=sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26 \ + --hash=sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f \ + --hash=sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b \ + --hash=sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be \ + --hash=sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c \ + --hash=sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3 \ + --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ + --hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \ + --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 + # via huggingface-hub +referencing==0.37.0 \ + --hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \ + --hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8 + # via + # jsonschema + # jsonschema-specifications +regex==2026.9.29 \ + --hash=sha256:01000ddf0e3ffef97f2413ceb514f6313040106b6d18a03ee00a4fe35c1eb1db \ + --hash=sha256:0166844493626c5015c6088ee15c9ca2fd060ca15b7641d1657da6a58432ae33 \ + --hash=sha256:044265d77d94f5e3cb2fd72c76723807c429cb8c533e9d4672d0334a6f14f588 \ + --hash=sha256:0476e5bcbe6e1ba3d1c4cc7bbb1c3ba78e3b979b5c8a88d0a6a8cdd4992b8c84 \ + --hash=sha256:066d0e3dbfdd739bce2bf8c2a41dd16f73e3d8adc2eb06dd803a36a307f56075 \ + --hash=sha256:0b65c72739f981377c9c22e0c5c3cd7f42da7bd8a3c9209330fac772c7d893ed \ + --hash=sha256:0c992c19cd45058a4b92f68f139c93db168b48fb1f322c9a7cd620806afb6b51 \ + --hash=sha256:0cc63b5e47c12a48d90c7e9d7de6a035dd14f62868aaedbb4e0ff8ba2b8bfe7b \ + --hash=sha256:0dd8af32e9f7b56b7f95cc1fd79b23054c3bdc172392ae560acc24d57b7ffe71 \ + --hash=sha256:0def9fb6abac55492d6d51cddb7225d07d6f279e774e0adc08569a54a5fc8d46 \ + --hash=sha256:0fd2c901cc307a745ad4bc87f20060d7a0825a3371d1e93488af22e7a387f78f \ + --hash=sha256:1043aedf5917caa861bcb25a9c11460049656bdf0017a90a309fa8f255467725 \ + --hash=sha256:121a76a0985db80ceae9e171c337f8c927868e37d01b54e3ce87bc87f9c6a208 \ + --hash=sha256:143533cc4b6fbc5b95aca0a5b8d541088d374831593def000ec89322c220221d \ + --hash=sha256:14e953ff3607c92d7675bf79c4d4509ef6782aa8c08509f179f9b3d6d0679e86 \ + --hash=sha256:18ae8eed4526e35bdb754d61562b90bf5c00a67fdcf3cc1380dd59597486631b \ + --hash=sha256:19959129885356df0e97556856f77eb2888380dac18bed075a7c05c5128c618d \ + --hash=sha256:1ba8c6a416569ce0d37e83e28a254a61dc99a419084dfb6476cea02d997f74fa \ + --hash=sha256:1c2a0026062abcc321a53db4a185ceba0b59a66b5d37b0808917a88b55a5257f \ + --hash=sha256:1d9fe8091b2e89d470df68a9331111ed008ae8aae6bf1e8e1fba4086a495c84e \ + --hash=sha256:2089fe39c406784d90101c726755ffa1497bb74638fd434300d2b88006186de8 \ + --hash=sha256:23ae6fdad9e63e54038f5ef78aba2933faca61e24d432786589e737bc5522ebb \ + --hash=sha256:26ec4ccce55aa533fbd603d08911b01101a8fcfec987845ac3ae2c7087b2bde3 \ + --hash=sha256:2f7f7aa47b229f2b39a2ae2596d2ad5625d77b5eb9856fac2dab3eb506cdd0a0 \ + --hash=sha256:31b003f9a070335e2a8233ee9b14a3ca8e6d792012ae011f741bf0aaf11744c5 \ + --hash=sha256:32ab11df9677ca80bcbb5fe4eb1da9109a5019239a054836efc6fa1c64e683cf \ + --hash=sha256:33026515aebc0e70d1c89978e53e8d695d35d9e472f8d5b34465ba3c74028650 \ + --hash=sha256:34b6925af9853bf461950e6508910f179fd6e9b1a7ec8548e069606b7e51a26b \ + --hash=sha256:352cf115a810b357caa35193ab656ecf5ef41056855e82f292c99e8514f8d954 \ + --hash=sha256:39ab5894d971f9ac68baa6eca5c50387db579cfcacf36ae8df3feceb1815e6d0 \ + --hash=sha256:3a21a9509d0ee88e7a70e1ad228cd2f0e0fd1e187458db132e8a8d18c97daf9d \ + --hash=sha256:3c5c2ef13797466aa64170cbb66ad98a32351dd4127694cea7199f80f213750d \ + --hash=sha256:3e778bfccd63075167709136afbc251c1f683758d5bf49c803c60ac3f894ce6b \ + --hash=sha256:3f1e6cb402a89457582cd696f982559217d13484a193202c394015297968c86d \ + --hash=sha256:42e82e578c904445d4c8a35b8f28052cf567593215fa5db06266fbc6f77aaa2e \ + --hash=sha256:4408b2b27a95ca8cc48b7411945753773353b5c93b307754781086c99d3a576f \ + --hash=sha256:446654b29bfaa30500d80947eda42cef1449dc8a87f4e3cf061cc8485d3a1f0b \ + --hash=sha256:45010bcfe66df41522d56c9b6114e87ecc597a08970ff6a2ced24415c141ae5f \ + --hash=sha256:49ee178ca31c94621294bf9b8b676a92a2e6bba8af0529591753719e57edb621 \ + --hash=sha256:4d7d93613b01b0199961330e49cfc52d479b3d5776c56c691db31130c0a07d91 \ + --hash=sha256:4fb41211d2333eb930a51e0546a65999761cf1f572a4da56ef9b8a62966c06f2 \ + --hash=sha256:4fe97894d1b306c919b4e50def1e6f6c522f4d03a7283811f4d108f1ce5d3ac2 \ + --hash=sha256:554bffadcbcb6d5f4e5fb10a61cc52084b9a63d1dab5f10bcd2c4343972e8e2c \ + --hash=sha256:59b49507f47479e299a9e1bc41b5cb83a7afda0540625f1dbae886615978acbf \ + --hash=sha256:5eeb8edc6110d9194a4d0d54610f64c37a31c605b5dbb7e407fc6ec7fa34a4a1 \ + --hash=sha256:612b709381c0355b70d89cdb51b7f670591ed5cbbc0e3b5337488019dc667b65 \ + --hash=sha256:61956f074ecd123f55adca68ee3eab46e6a07ad3f8e64e6db95dfacb444f55c4 \ + --hash=sha256:6398d5145689503412cc1748895242598d8846b8967b851133b20dc2ed1e21e8 \ + --hash=sha256:65b408d8fcb273e3499e7ef2ce796810da1becd208c7fb4373692a242d79d461 \ + --hash=sha256:686ac5350fceae63830bb98805fcb8039325bf4c06d9f6f048ff65229d5bffa5 \ + --hash=sha256:6a1a824fbed817e0a891103886b68f063b1e83cc51bc97192a90a60195a9291f \ + --hash=sha256:6abb75ab16bc3281714a5b99548a2225db70dba1f995f6d7f7419b76eb5a8fbe \ + --hash=sha256:6f7121a8914ed13fcfe2099f895341bfb789f004d4c5a0bdece8fa667da10849 \ + --hash=sha256:7020ed44df30b3aa492c00ee3b52d0548c1f30c2c6c5bb13ae897680900d3413 \ + --hash=sha256:720537c7ea6f80dc61913184edb0ce2497a306b39ef19f28505b322553d52bdb \ + --hash=sha256:724184b4aafed865e4f13ca313fdcb43024300c028ec67319cfa16847d84685e \ + --hash=sha256:7c03031610e3e6ed1768a2b7a8fc84637c1257b50c5eacaf094c6e17a84fc563 \ + --hash=sha256:80a5ea3b4fd9d6a5b9a44f7976a9acaaab35aa3c1f6b29e5bd857dfabaded223 \ + --hash=sha256:80c7cadd3fd2bfde5df8aa0787e315812cad0c313a753095d02f4c2b6c01677b \ + --hash=sha256:80ea96f5c1a30bf09007d48466521d9c294bebe197c708c3359096e3e3691632 \ + --hash=sha256:864e9b87ac33c3fb9fb4ad48166d4fdb579c351d5c77deb0d34bccb36a775cd9 \ + --hash=sha256:87fb80cbe3557e27e7b28b995c2b2eedf689b8886f941ab93e0e288f0976518a \ + --hash=sha256:8873c4a11c50b9989168881aeb3f08859f469d809941866aa1feefd8be5431f6 \ + --hash=sha256:888d60953908dcf761aa320c3e390ab8556efbdb551ace63921de90f6ae0848d \ + --hash=sha256:8b5fcc4771732191b2b7d1dd68d8f0353f47f8d90b6150f6dce58bf1112442cb \ + --hash=sha256:8f39588af4731c8923c26810eb3b33f76f17633985e40f59c3cd45a33805a895 \ + --hash=sha256:9173db3be74a35cb6731701094b98120f7ee4876a287882a59cdea1fa7da342f \ + --hash=sha256:92f05c9c42bde5785dc48770bc2194d9f7442544156f951e19cd31b096cec562 \ + --hash=sha256:951733b1bbdb71e377cec567b409f1a7881b47cfcad84121aa74cb575fa425ea \ + --hash=sha256:957bb708e8057ab1649ba566456429d691ec9b90d1c9ad1af1ba7ffbbeaf05f2 \ + --hash=sha256:9916fda742cd4eede63b286f58c06718324265d727ce0856eb1aac86d0d150d6 \ + --hash=sha256:9e1d3a4cb7993b708f0ada8d0c84590efd853f169e7147d2202c9da503180242 \ + --hash=sha256:9e4482589065c8ecd761cff522dcd85f2d39e62f551e37e025d1c7d54772def3 \ + --hash=sha256:a5300757f8a68f5b6cc33f57338d72a0e3589c5cc9ad5f8504ea06f028be582a \ + --hash=sha256:a540abfab208e1b7ef2df231c40ef3b6cbb30a0aad6204e9b6a81c10a6794628 \ + --hash=sha256:a5758353650079898dc1b2b0e95aa51fa23a30d020e06f62c430dd08ee56cdd8 \ + --hash=sha256:a64b85a4760337cfefdb27d42da6ed8b58e8cde3f2d57b6ef43e76ef6ea9ef47 \ + --hash=sha256:a655d34b2a6943af32401f3d94f72e9d731f6ad16285815550bf2b4ee69d420a \ + --hash=sha256:a714befaacbd10092ffe4cea0d3c5f008fb9efe9bc322c715bcdfdee414b9a3d \ + --hash=sha256:a760da040b47767b4b873adfb7c3b691e9ba2fc60f113f9d0b88f1a62f323e85 \ + --hash=sha256:addd736a0547d553283adaf4e05d7104e7f2c7b0b092e9b4d28756825f14531f \ + --hash=sha256:ae4613d7d9dda60fcba95f846cc6f808017f1843f392cf9daad14a6534493d71 \ + --hash=sha256:b11b589e00095ec69cf79841a76360f9b079e95b0368a25b5ebb951ab0c157ff \ + --hash=sha256:b3e445b66c80b4eb4234e855ce94d9adc183eedbd632816228d89930b91b2c5b \ + --hash=sha256:b7b893976e7fe42053da64f2aa27239c24252fd2ec6df471e1be197c0addc3b1 \ + --hash=sha256:b84f186a7f0536fe4ff9a9fa12d06d007b9b71d4b5352ddcc41f59ad6522a312 \ + --hash=sha256:b89efc38431793d28b7cd91227e2f952ad7c48df19132b17f43a5fec3c14143b \ + --hash=sha256:b97a38fb4c732b6832db6bf108963adbcd82ef1268ba2025dce390f45af75efa \ + --hash=sha256:b9d74e4eee9ddb64c2e92d5d61472c59c21684c059eb7b68767be9628e977859 \ + --hash=sha256:bb90e7177944b6684738c1fc36aabd2dd00d1de3be7dbe09f91e196f1bc0dc81 \ + --hash=sha256:bec37990e3d6121f29ecfb594bd8f1bf009e9f7926daba2e50e3b27d3892a783 \ + --hash=sha256:bf3c49863c23a1ad6da9c30351aed6cff8d5ddbeb63c5c8420ae54e98c7d0138 \ + --hash=sha256:bf48516e35cf848390ea68850aba53e7c333720d2945b4d2c25b69fc5171723f \ + --hash=sha256:bfc71e6d970419c1309b3640305298643e2a734cad3f7cfb6d2ddee4175ab53d \ + --hash=sha256:c0094897d7d01f184b2d7fe8c56c66d64efe01b31f4b7d34205b391387df1111 \ + --hash=sha256:c03c6eb6ece86dfdcbb34799efaa339b093132e1aceed491ba5e08fe06cdf699 \ + --hash=sha256:c1a9a6651197fbed6f0212591418b9def774fc3f8324f78d1bf0e6a63e5f8aa1 \ + --hash=sha256:c3589f40749acce747510bf5d589d54e376cb0930ea58b35effac97e5312b0c1 \ + --hash=sha256:c4e38dd8f39c43a91d2410ad2b85610701b0979342c3df1d69eaf8e838c757d8 \ + --hash=sha256:c6c8fabf1dafc1f1ddcbb67896d3f93efb092e8c4b6322d7389b944e76a484e5 \ + --hash=sha256:c90fcf7804ea0a54b896ce0f2b9565350220b8d4890fd0db461a476a4c687963 \ + --hash=sha256:c9b602fae1e00b7c035d661ce85575365719192a7b46784bd71cf64c68053aa0 \ + --hash=sha256:ccb64d887a9db1cd76dbc0f92051a1a478a2a67e7f56c62d915cb881d7734704 \ + --hash=sha256:d06fcdecc10fc7954d7c8f27a03c96055fe525274dc84a7b0dbdc3d6b9e03dab \ + --hash=sha256:d0c3082bf79bcd6a614d55916590ad4b8f93200e10b97f463ea5d9d07c9b5f23 \ + --hash=sha256:d49c18f1ea294cf4adde2e5ac256e98c82ea9d708462ce4bf799dffa7cfe8a2c \ + --hash=sha256:d60030baaa7bfbb02d650c126cdcddcb6e33dbff14d819434c8fa2fdcaeeeba5 \ + --hash=sha256:d7cab119d0df0b9413f106b4d7fc34f2872d3574ed3806fb48959c830b1537da \ + --hash=sha256:d9b77b25b4f395f92de6099ab08e8ae2bc7e51dfe157f22900902243a5cc90c7 \ + --hash=sha256:dabee8f4935e731fb46b2a3091bdda0d3d94b3bbfb907d2b4f12eefce4009619 \ + --hash=sha256:db5e82ba15c142425b8406690032df89e39cca4a2e8afbbb9a3d84edc2373ac3 \ + --hash=sha256:dc79d36d0618752265f0d575915bdc5c5130ecb9c9f6b3bcefeae32e4bdfafcf \ + --hash=sha256:ddfa987262763c3c22a8367d2a49c244b018a74c3a8e3ab1a864119ad45c5633 \ + --hash=sha256:e1172147d28d8fbcf8cb8d26c41506169f5ad8fe9ec969cb116835a19d4d8eca \ + --hash=sha256:e11edba5bc344a32b029a7af9d4b3173982dd79eeafa0b9dbd787364414b0509 \ + --hash=sha256:e2c89e9b762c57f59d5e99ee8b20202adb892e35f8d3485741340999ca55058e \ + --hash=sha256:e31f72490b7c12f7790e1e25c3afffd20503ee1bfb43461d7838b871ff244b19 \ + --hash=sha256:e8c65ef3862a8ad6e86492b6ed9327805dd66904c012bd3649dc67d822ed6c34 \ + --hash=sha256:ebb8912f565b8cdbbf27debfe00df04202c20e2f651b9e32767930c5eace3621 \ + --hash=sha256:ed511a0708e2297e1d6431e7fb217e3402791e491e02da800658ace4973df1bb \ + --hash=sha256:edf06545875f3efa31560d94121e95c7fd70d98b1dfedc0157097d79b13b52ea \ + --hash=sha256:f0fe9834e5aeccaf19a0d8feb296d66a24be1a7c9922002f842a682cd5abb787 \ + --hash=sha256:f1a0d5117230dd46b399a30a38afa44f79c99f3168988fdc4f425c3f928b39df \ + --hash=sha256:f37964e4a5e993d2fd45147741e9dff7f34a2d8c00ab94c4ea0514a4677f959e \ + --hash=sha256:f57dc6b8fef170f105d2cf5cdce254f47b137d7755086cf7050f47e16582abba \ + --hash=sha256:f93bc1c3486ef3747e07c9d7c1d0a147b8fbaab975f80e348aed6f71309dfaca \ + --hash=sha256:fb00027a09a8f9f08028b40dce4c933cf73e4833240ed356583fdc9cfa721566 \ + --hash=sha256:fb99cc9d45f48895d9d67f6a0b8a57f08d39c174d9f25ad97a313e0470267b1c \ + --hash=sha256:fdd88ed5e20b1bcdd234421e454962c971aa44b653bdb7f1ea9ef683e90fb649 \ + --hash=sha256:fe3fa1dd453ed5c7f5ea23a26218329790ed7197a99b90e94330e313959a7f52 + # via tiktoken +requests==2.34.2 \ + --hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \ + --hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed + # via tiktoken +rpds-py==2026.9.1 \ + --hash=sha256:00ba2d8c7dd4ee537978ddf4b3fbd712bef2d8751603f7f3146b3f4287768e25 \ + --hash=sha256:01445c8d194aa032a08e944f16567672da1c62dbdbefd8b6d0693032e290cf68 \ + --hash=sha256:028ad274ea951dac64491b5d1e65712a4aeabfdbdb9fccf797b57bd899b0c495 \ + --hash=sha256:0483515261947e4e8b8e1375bf7463e7eb6ccfb3d86e7b554d90cd5285f20f32 \ + --hash=sha256:068c37bba854ec2fe42f7365c640af11dd9895890ccbf2df5070d0c059bd7f96 \ + --hash=sha256:074a4d198bc34d9a8ea425114fc3ded6d11ec01f6a314a8db67454a5152d8834 \ + --hash=sha256:07deecbfce94c78473018bc7d10b337cc651d12df87a1eb2cb3e4024bc9c33d0 \ + --hash=sha256:08dae4a4095150a7c4545a1fb40b98e1ab1744fbc2770d92c977b9dadaa49ab6 \ + --hash=sha256:0da298fb372dc192610a4b9ecbc68a0cd8b675bbbd1fc519d01b41cfd658333e \ + --hash=sha256:0f045bb053c9057720d72c56dffe30dffdc05997b2897a827b9325f0ab6623fa \ + --hash=sha256:10e208f2425d973938afcd56e28a7c4be32e27b6a60b5d381f49fb9d8acf9759 \ + --hash=sha256:136a1c3fe4402b7008bc81cb62ee538481795b61a7e83df88dff3b3f02b726ff \ + --hash=sha256:159a7aab5c5e8b112c8830f54717ce56da1252ebdbb526f5be2df2309280b9e7 \ + --hash=sha256:172e47169583f46ce118cbec68e6795d0da0f4606b488b6434f8276bca0a058c \ + --hash=sha256:1c2d1f6da5128eabf34e963d7163a818846075a52568250d006c4c953b40f903 \ + --hash=sha256:1d55198263bb51f557550c6ed2e6d1cb6a6fed6eb5c9120b741c5926bef8a45d \ + --hash=sha256:1d77b649e6f7cdf12ca5c2a98dad0ad37f9ea9b6f960408a92f0cb12bb3d04d9 \ + --hash=sha256:1e8d4d79d828299bf44a55db22a9388ab967b49d17132c88eab0f4360b48da8e \ + --hash=sha256:22ffd29a63d71fb1b81552c21f2c2b734949b7ac751a9be70675a939a900839b \ + --hash=sha256:2693b2728bbcc48d09a981a356954b0c47c53ff25b545856f28a889ea619f69a \ + --hash=sha256:270bdcdaac5d5b6f73c5e22e7e135c7f2a50e789f71d9e241d5be8d90026e19a \ + --hash=sha256:2711d29b653b3bce48a63d18b9c6b53274669e6d6c4094dddeb4d9a0e45128b2 \ + --hash=sha256:2c16ab111bc27c646ba8aa005d0527754edc538ebb636f0b1bf8e244b48d1945 \ + --hash=sha256:306ee1850d8105b5baf977e78d45fcadd12c1a54678d614c9baf217708446e91 \ + --hash=sha256:3231c4c0e521dafa5be0c9f114ee2c2ad46650836f2d72caa86801950c3e7044 \ + --hash=sha256:3890a6aa36e6baa53d5258a2a25d3ef8b37ad165a6ab27a892d7c3e3a432cd69 \ + --hash=sha256:3a72c11530d71abfb66c8d7696a2f86c43e63fca8b948f1a784ac490f4ec688e \ + --hash=sha256:3b5a6f40f0a1486b4b36c888123afc67acdbd9f33235927acf5ff295429a0ba3 \ + --hash=sha256:3c91c210ae7645626c608400e3519b4a642f837cce09ca830db3beb2e9f274d4 \ + --hash=sha256:3cd182d7291d29b92c521a0069d9c01ba6193628a9a105531d11b40a6d731a33 \ + --hash=sha256:3e524c7874ac72884d28e16dd5b8d839fd09e0fe76b020d3fbca23212a7b8c52 \ + --hash=sha256:3e93b2cd69a9830be33e03945cd7cda940a0a8bfcfbff41d6144f0cb0d3d8bd9 \ + --hash=sha256:3edae8c5ddfdb6985d49ae9d150516e5076888879022f91a26c2de9276ce0bdb \ + --hash=sha256:3f0e9ac28fc067d4d34b88ae43c48e9489455c97fee9633d851f7eeed5a05d35 \ + --hash=sha256:42e75466f83cd43f6026c81eab74246efb2bdadafb307b85700632d06c68f299 \ + --hash=sha256:44b32a7c4f0da3d28af31c259e38ddcff096f855e205ed0671d02fcf44f1ea1c \ + --hash=sha256:457866b85daf5034296666168b84a69e0b2e89dc4f1af102b46f6448a60b9063 \ + --hash=sha256:45bc6bccf78b20fd834237d18db64965d7ee68ba7f60440a26c7ab71e7b8d51a \ + --hash=sha256:46d80bc76b51a6c24f9944368c28d38b8bcbcea1da4f2f8d3ebc31a67e8c6ec6 \ + --hash=sha256:4793ef7f78268b124b73fa933440f01d258bbae01de9fa53e9080c9ab0425a12 \ + --hash=sha256:492e5e428cbe126221611f47e068f01660352feec4ad18bc0f5ea9b2ae88fb14 \ + --hash=sha256:4b26b03d9d2658ee2fa234f8f4f19f38a09773fe5261028025032e26d4d35af0 \ + --hash=sha256:4c0d2cb595a420b34d5086db0add011e26e2c09d6a024afbac4228bf8f863a30 \ + --hash=sha256:4cfaf02209061880210819934de2f4f6aa83dc04dafe6770276acc240a56da31 \ + --hash=sha256:501909f2e4a1e2dee528ef766fe3c469060ebc17e54a8383d404ba07a81a6f02 \ + --hash=sha256:50906f5aea24b5a865cbd0a589698288631d9f3a54c3a937c83aefa95a0d14af \ + --hash=sha256:54ac2158a6f96cfbabff0b2eedaf94b90c5ec7ca8317fcadc61e1c2b2e0ff6ef \ + --hash=sha256:56c6952a9b15047466d0c2347c446a761d4527f89976156341e68f0ce5cc08b0 \ + --hash=sha256:56cd8b3f77d7b6812f533b662186a1f28316931166ddc00fb893b1b0db7e9888 \ + --hash=sha256:57492a550a1d88d29d003247e5f78dd8cf04a701fac0e4c8db8745a6d2504e0a \ + --hash=sha256:5943980471829f6de242a20b109de3111ba6b77e3af0ffc587028ac854b05e6c \ + --hash=sha256:5c6ee90dee3e85e055ddfd502d611643d9b0fd94c818220bda84ec3dacd9b27b \ + --hash=sha256:5c90e7fa02e8f5de0d10c17595c568ada48c5302e749462c0ea1a4c362111a86 \ + --hash=sha256:5ce8943f79c2210f7abcc28e86367b03b28d95027fd01c46d2472373ae70c86f \ + --hash=sha256:617f59cde379b4f648a09797b7f683d04b90a46344cddab85639da5aff0f5531 \ + --hash=sha256:6307a0da524939decb8ca4a3933b8ab62525794411d6984fca6726e732804af6 \ + --hash=sha256:684fd492fff4fead00587544e059be2bbcb6f93454f21fa2a91b66fc7508be82 \ + --hash=sha256:6b5b393eda5ea42cca1c1a6665f2a4882b4fd5d1777e41ce0545a107fb008c9d \ + --hash=sha256:6b723eb406dec5bc9ec516c73ab9c3239a3284e017f7eb89ee2b3258bd504fb7 \ + --hash=sha256:6b9bf3135b4ad5981df9a73d71a35272d650a2985ae9c2746357b24d59de2448 \ + --hash=sha256:6beb738155fe8ab8091afdfa5a3226b21c2b1593f1e50ebb90eb25b44dbc0391 \ + --hash=sha256:6c0dbbcc19735fe5f8b0a54c07659d154a9e69f47e15d0a6ab7299215daf62cb \ + --hash=sha256:6cdc537c8633d7fd92a82e2e0d2ab74320a3f63d5e59fb9cf08711e08fe151c4 \ + --hash=sha256:6eae33003518fd4cb4f83a218d5371469dd3001aa3b87128c005b07762f7fe5e \ + --hash=sha256:740d0a99cf9de0b17a3943388e9294a59becf75e7c43421f387bd3c7a9901f7c \ + --hash=sha256:75c38c50ab9aca840225d9a9a3810bf11d04bd5c1f186cabbb8aee56db3e9b15 \ + --hash=sha256:761fdae6728ceb99ab182fad2f0cc1e262f610834dc891aea1d1a2a2e634776f \ + --hash=sha256:7664419f27db41d4f1c43a78dccda7dd6e8ef2428df3ee01d0c2a07a6b071297 \ + --hash=sha256:76d3af9732d2dab69f28179b40ba2d87e2f1d5824b4a694780aa787d685e8f36 \ + --hash=sha256:78326f4cb4427a56ba4996c0762b63be45f06b85f086526420d2b3a66e40f84d \ + --hash=sha256:7868b85224291c6cb6759f9b5adb9745f486d226f62b16a614dd5a2a5ab2b35b \ + --hash=sha256:815d26356930846a40c7bc1366e7b1b0320ab8a063e66c11298a208bed0fd237 \ + --hash=sha256:8171b44a054e5c67fd748ada04187f1250bf35b95f85e52ab64bcf3331a923bb \ + --hash=sha256:821b2755db9194409254012f429c56643416fb96ef9be090be82ec8826b7f477 \ + --hash=sha256:837c6b305e26fe0f75b15c92cf3b2ba29e0ae19dc40b1c557b026cb426347d0c \ + --hash=sha256:839dde845559254f34885267c6878f60d61d5205180226d976fe488d45fa128e \ + --hash=sha256:84a6ecc0c940169190d2c23bd969debd48c94dbc855acd60188a68d71d421608 \ + --hash=sha256:8601470267d938bcb7f3ab1a336100af51a4fd5b6ed030ef52461bb3ef5e7e07 \ + --hash=sha256:88b5268892fde430d5531f95bc560b6efbbd67c929662c586afd729a96e7461c \ + --hash=sha256:8aa5dda18d39b6143eb24809d158f9252c88f402749b6f1b62a506cc7d96cc35 \ + --hash=sha256:926bdd3e3b5998ddf70cc64bc8cf57209571f9044542913afb673799fec77dd0 \ + --hash=sha256:96beca19ec79de272e8668585380ff9092c47077c1d7a1e098e00bbd921f4785 \ + --hash=sha256:9a0460d43603d1fd9ef59c30278531e15d78581721ddb538fa560aa7817ea4ad \ + --hash=sha256:a03d57b86d2a51d0a66c92177e2be154ad015f357791d306e714569999cdb4cc \ + --hash=sha256:a36b70596407634ca82d4b989a3729074a008537a0522e4c8046a67c729103e9 \ + --hash=sha256:a3a52a3ba86436ab3aef510fbe21512abc2ddd1993005dfe50514bd2284ef025 \ + --hash=sha256:a3dbc5ed9514908d5046107d7b1346bde71eea61de6e0e4919c19354f97e769f \ + --hash=sha256:a431156bb41865fc14cd5d79bb9d7bbed83110b0159e34e62ae30951f96c0009 \ + --hash=sha256:a575404ebc9cf2e91edd32eaf570ec1430eb900d4f56724ba7dd4bc1fc9c176d \ + --hash=sha256:a5cf77eb04f20b720be95265a3e00eb2a14814074255cc27069c551b2db53118 \ + --hash=sha256:a8763f20692da7df39b0afdd1ba3042b004c50a45994f76c2d9a25641f7673db \ + --hash=sha256:ab4b2fda7c2b542f7f9d886cc6a838c5079d2b76f72e6081411faba11adde2c9 \ + --hash=sha256:addeda51556dac7c1a2f14cda62db8b621cd12afba3091d03a96c72932387eab \ + --hash=sha256:b242c27c8f836305a4a72df9cdd564386ac57b807bd252a063223331c9316b37 \ + --hash=sha256:b4f062343e7ad3fa94f2c66e5ae667dee47ee74dd41a9057c4fbe163236a123d \ + --hash=sha256:b5b8b0753718d258fd454283fbd57e14545d3b40583fa672e27cb4f987626bcc \ + --hash=sha256:be3e47e2d91aa3942ff9bf4077a505226005abfc39b6f7554a91c1b9393986b9 \ + --hash=sha256:befc2d6a953e563f8a7bfd87a42c22ebf8a3e980dcb7b6a4d17b70b0e914e8a3 \ + --hash=sha256:bf35d0568abda97233239ce32896d3ad53fccc537832c104e30c94aa5fb93569 \ + --hash=sha256:c933c6678c6f116ff8af47a4c6db0868b8ace74af0343016c0ef00f00272ea69 \ + --hash=sha256:c9d1aca01f49170fdcf5c92761b1fafe97f554b721ca4570c5949fff778f0d4b \ + --hash=sha256:cdeaa99ce822dca76cfb1b993e9120c5ea212f2eb66d48950ad63c349668a018 \ + --hash=sha256:ce4d4f52e2a4324396caddbd45a97d8d7be5f42edd25d2355282a9c34f9b2f7f \ + --hash=sha256:d1028417bb44037eb3069c1009bd7b7277212876cda22fbe565b0bca9fab6d2c \ + --hash=sha256:d151e148117294133bf8af7eeace085e7e87432db15ab6adf640330298a47f6f \ + --hash=sha256:d7841166b7fa64c9c56404617ae4341448847482d45933b13135d26c130519e5 \ + --hash=sha256:d7fca4eb6df565e2a928f1c7dad92d27db8f9df0f449e76423ed5d7e713ed445 \ + --hash=sha256:d95a354e02393eada6d7351184671aced9d4cce109dabf927cb7aa99624352a1 \ + --hash=sha256:d9edf30457d74eebfd76b045535e36f1cd89062566a128a0db2145ca042d787e \ + --hash=sha256:dbc2673f9223d420c91145599b3ba45a8a50c207d1976908e5fb5ddb0c9b9429 \ + --hash=sha256:e01b3c878c8641913e688edd1b3f08658c6783d29cf6b826bd3c0d1ae7a1ffaa \ + --hash=sha256:e21c1429e205828ea886a2293a4a2c8e01f4c25d9893ca330e97a6cf73f52e7b \ + --hash=sha256:e43d4a1f673e8a1cbd8533e809e02b4bf9d4f2280269bb640436556312121250 \ + --hash=sha256:e6d198bad4e49dd6732fbd636e2fc5c082f45c8cad0b4acb756b00c82c76072e \ + --hash=sha256:e6ea1cda8d8c688278430e4268a42f5e5da3bdd74578dfadc0820c3f1766ce83 \ + --hash=sha256:ea394a937f17a54c51239348bdbe2e3518124c8d4a8951ba04a311d3095bd18f \ + --hash=sha256:eac2f5dbafd585dfe31f86a23ebf0d3ba480a9d49ebc87947267b5608d4ea0cd \ + --hash=sha256:eb61be926bb81567c1f48bdc8aa22b9855048dc2efd53871f9f7e6e9a5632346 \ + --hash=sha256:eba5d173f7d5708b22a93815017a4611873ed54db9f268077c0dd1ed99cfc858 \ + --hash=sha256:ec450527cbf485e13c8d3602a54f428ab0432fdade0ede75efd74b735421c871 \ + --hash=sha256:eef6a03b0b6d08d0835ccfa8ec8d1bc70525e3801387567137b50c557695e6da \ + --hash=sha256:ef0d8c843e2827d6c120ab4687e9423fb1d893db1df27b7c1506615bcb9734a0 \ + --hash=sha256:ef6b65b03247c54692ad4fd9ee97cb772781927db72e3cb05e70b3db6d1ff14f \ + --hash=sha256:f3d6ed6a98cfd19155996605474982cc470d7601746a6439078f1a5a3fa8b050 \ + --hash=sha256:fce4b85234a0cbad67bf8e6e1201ee815d172c9aebad75f25645bc4d834f8e31 \ + --hash=sha256:fda1d96e542c37b6c804547dbf489c129fe7c97183a76a5ec275909ba1a063df \ + --hash=sha256:fdcd198979b4ecffcc1beba366a7fbcf4eb41243691a82fe52ceb0b902f09c12 \ + --hash=sha256:fe5ad0664ec772b02c45859041aa17655709cced7a31005817fbbbd988c25567 + # via + # jsonschema + # referencing +s3transfer==0.19.3 \ + --hash=sha256:24eb7535804306355e31c952a90022bf5b2f9d760f9a11062c7493a217c08553 \ + --hash=sha256:8326acc3d056d7f7b8a37110c7d2aea41f67e83f6ae79cd3b5fbcca34c726406 + # via boto3 +six==1.17.0 \ + --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ + --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 + # via python-dateutil +sniffio==1.3.1 \ + --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \ + --hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc + # via openai +sse-starlette==3.6.0 \ + --hash=sha256:623151d6c20dc0eebf1b3379c27faae91fff883bac7ab6665f16f46440a88b3a \ + --hash=sha256:e4dfa4d237d2712cb2b4d4918eda9b457cd6b44bbecdc838af75de836565bafd + # via mcp +starlette==1.10.0 \ + --hash=sha256:478c0ab3b4ced6e82719849c118fa406f0278a3499c1a898cd15cd31bdc38ce4 \ + --hash=sha256:b8399098d4c1e3522734f7235dc79b1fc967f96cf139c81e0fa30479e0685f9b + # via + # fastapi + # mcp + # sse-starlette +tiktoken==0.14.0 \ + --hash=sha256:087538c080e5ff421abd3a0785ed63c5111d06af98e6cd0d374dbe5969147ca3 \ + --hash=sha256:10f31e63e40313f2e518d87f7086cfa44e45f64cc14d8ae14103b41220c30a14 \ + --hash=sha256:11d8211b290855d2721334ff17dd9b3a17bfb26872be01f25d73612ef7ece890 \ + --hash=sha256:144a3fc369f92b7d548995217c5d6e84038d3572157a0f6f34080d65291d0f78 \ + --hash=sha256:149d97453c4c98c04b081d64a85e635921269b532710d6faf81e9e82b790e7d3 \ + --hash=sha256:14b47e3674f2624803a8acc8fb367b7e24fc53055f9df3296482fe9a3a34a232 \ + --hash=sha256:151d37a150c8f3dfc5f4345597b10e101876bd1bd13494e0185af6b508758d2e \ + --hash=sha256:18a1b651c4b032004bf7b4f1713391a54b2a341a52c6e8a2b59acae9d16e13c7 \ + --hash=sha256:19d643d701fdaa70e5b9c7f8f96abcaffe77ca5e482a3a1a7dde46feb4284695 \ + --hash=sha256:1b6e4adcfd285c44502aed51df98aaaca4f0fea028165dbf8a9e857b9f98d8ea \ + --hash=sha256:1f83081065ee5833d35b49e9180f3d8d15622a603dd1c435da0da6cc12b3662f \ + --hash=sha256:2157f52e4b4d7ac5ecc7457b3716834706e7ef9a46f5144029bfeb7cf71f4e06 \ + --hash=sha256:231dec90efcdccf1b565a1416107736f1e09b1a08fe736ef9d6363e626d03874 \ + --hash=sha256:26cc4b4840fa0e9f4b72ed489883e12f57e00d1021ca794720e3c29a12f0edef \ + --hash=sha256:26e60f6a956ee171ab728b37b8439905d7ea1db435c30f9822f291e9861c861d \ + --hash=sha256:2cc19ac87b41c9493c9778ff5847f0c8bbcf5bd0ec6b87ce06c1c802adc8a771 \ + --hash=sha256:2ea70afba6b9eddbf22c165142e5f0a2ad7aa36a452873c48b57bb2aeb8492ae \ + --hash=sha256:2ec16eb585332c55d022d86354e209ddf27326b1ea3477585ab248e7776d3b1f \ + --hash=sha256:2fc834fbe3f6a0736905c36ab709537e6840dbd63b982dc9e0216ae7d305ba1a \ + --hash=sha256:380873f330b741c4435574f37edb20813d04603ace2d53e0a63560e1fec83010 \ + --hash=sha256:3b12e54f8bec91433e41aff65d8d1f209a4f678081163747079806e5361f6c91 \ + --hash=sha256:3c5349c9f916283bba32bec8af69b763e4faa304dc004d0eaaea66a3cf004c1f \ + --hash=sha256:3de75343041a1c57333b1e707ac8a9769738241d7d6a55d39e12cf84548337c6 \ + --hash=sha256:3fd7c14b1cb45b486c39fc9b3443bb341f3e2fc7e6f31247f3435a5836651632 \ + --hash=sha256:447ada49af4898b5e992f0b5799d2f3af385921102c211947ce3fe960dd919da \ + --hash=sha256:4d8d91d68353bd167fdf26467e5ff9e56aaa5f87d6410c0238608629e4dc0d33 \ + --hash=sha256:50a7e5646cbac2a8f7c3e8c0934ffda1a4357ee9c44b652434b23c3ed54d0900 \ + --hash=sha256:561e7580f84a79859af1ef6f676968e9030fcc3fe195700b15235bca64f009c9 \ + --hash=sha256:60c47ca69ddda0dea8256fffd12e1b86f4b59734a20e4a70c61f63cc5f021df4 \ + --hash=sha256:6eb94895c45f26bb8f5546e5fd8a069efcf6e3f108ea9d5cbe3bf6f7f3983438 \ + --hash=sha256:728303a072163130c5b477b1f20d6211895569c1d5302c24ffc93a3009160871 \ + --hash=sha256:78571efc311c30b73f31eb949a921d6dac39a5d9dc42d1cfa8f8db157b3447b1 \ + --hash=sha256:7896eea257fe497a2b7134474d909156c6744ce8da35bce88011a960e008aa0d \ + --hash=sha256:7aab286a020660a039097912a088236b985d18a3090d73f136c4413d29d37ca0 \ + --hash=sha256:7b7acbb7a4b8383707bce22ad3c162006478c27b56368acd3e1fcb1658a80425 \ + --hash=sha256:7db45b98e94adf4173a5cd7422b150999a7ee11ff847783a14f6e1b80cc38cb6 \ + --hash=sha256:86951a971c53979ec857bd8c4a32dc227ab0fd33f6c12a3bd62d3fbf5f0bfcaa \ + --hash=sha256:86f66c85e796f5d05d5c4a60ec1d40cbfebc47a32464053528c797163fa9ab89 \ + --hash=sha256:8e947aefe98ef74cce94923f90e48c98fe34eb1ec0a6bfdfadfc5a96359bfc36 \ + --hash=sha256:90a762670c7f968184723769a06ed51f5cf5ce5dcd1e30164f25c72d85c2d1f1 \ + --hash=sha256:94f77b60a8ab23580db19ae822744c9716c1720020d2179ca5605112d12326f1 \ + --hash=sha256:979c1524f753b662b0f3cd261b135afe6659cce33caaa7a5ea00dd1756b3055c \ + --hash=sha256:a140e83317fef02faeeb78d9a8efac623887f2feaf0055c55dcdb2b17f0226ad \ + --hash=sha256:aa428a559d5fd02ae619aacaace86c7474a1f2702d2c01fc828908dd60f20f7a \ + --hash=sha256:b950248272f1b303dc32986396e2dccfa10cf6d1e83ec8f0bba1776660305482 \ + --hash=sha256:c2edf09b381fafbc014ae8e018ed25087abb9a3dafa8465a0ea63c6558c47a79 \ + --hash=sha256:c3093001ddce822b4587e6e94bf6de36a5f97b3f31de1c9fc8d4fda144c59ff4 \ + --hash=sha256:c6cb9896a82b9ee44e15ba0b5c8044072f2e4d48acaa704c8d3feeef5ad9487c \ + --hash=sha256:c77d4a3e1deb2707819df92046b89aad1ac81d27e07616b797cbff3f62c037da \ + --hash=sha256:ca4db6ff5c5bf600f9b7761a0070ed44dfe5797a76bd432fb978bc480ef40c58 \ + --hash=sha256:cbe2cc3bba939bcdaf103e03df9d5039d33887080b315624be28ec69059e5f94 \ + --hash=sha256:cd8ca1305c1c902fe42c486165f2e4808d9997625c98ffb05b9e0366d99d3948 \ + --hash=sha256:d0781223705199b289faa59601bb9c2441712d4c600dd13c43d8fd6a33d22cd5 \ + --hash=sha256:d6cebe67765569df3dafac8474e4eccf5c19d24140492567a5e58a11445732a4 \ + --hash=sha256:e067f4cbcc5d036e8aff7fe7a6b530a8f4de2e4616ad9005a24a1879e24e6450 \ + --hash=sha256:e2eca764c53490f8930dbce329e0769f11108d87d908282a80c5c130e26e7037 \ + --hash=sha256:e3442bbb2f0c588cec876061e37ae67b455b9df9978b003c8fe30e45f2ef5b42 \ + --hash=sha256:e4ddf863b59347deaa92302dcd90e5eb003cdc9be06ec2b692c38d1bdd9efd49 \ + --hash=sha256:e9c5fe393aab56469f04e432ff851216d3def3436cf5f07e442a240164bf500f \ + --hash=sha256:eceeff0c62419bc78d4b6e70a4762a4d25df3ae8f2d5946e3853ce93e7a57098 \ + --hash=sha256:f2af4a336ea56d6c14f27741a0e1d8294a35dd0b038bcf990d232ebb54eb994b \ + --hash=sha256:f3d6cf93fbe2e7117eb7bedca684216fbe328a41f0843ce34245451d8eb2df1c \ + --hash=sha256:f5e7665f6624e052e5e7f6a36919ab69279decdc976d7b16b4fa15e1897d0513 \ + --hash=sha256:f702e0aeeb6506e57687e881c59e844ebe8f0a6a097ddafe20e3ab25f387be4e + # via litellm +tokenizers==0.23.3 \ + --hash=sha256:114e2b55ed177179d59f4ab98200a4471e11e78f9e4b5a922d146740f96fcf52 \ + --hash=sha256:1554a6eed34d9d6a78d23360f4e06df8dffab1ae08c7e8488e0b3e3b36cc266f \ + --hash=sha256:1ebf28794e7e4954e20a7f70fbea410b2d1f0418f7dbbca97ca384fcfef38c25 \ + --hash=sha256:1f0823bb00c5fdc98e487354d54dd55a03848d61a1a0bf29a68c77f24f3b26c3 \ + --hash=sha256:2a89614730d7b80940a5d2ed9320e1ec8add5a745c6151d8d05071b7215505b6 \ + --hash=sha256:376851d22bcf9d650a5c3090bb83e6cf9e895fbf0595369fa4cd43c1f69b5f87 \ + --hash=sha256:5cc24bb457dd4a8af89c8fcb40074d570129ec473df2a866c276ee55db4749d7 \ + --hash=sha256:68649e97d5b43c44c031d8d848874a6eecae8f8fe40ea989aa777a5a83aca716 \ + --hash=sha256:7e48734d2de9260d86f03ab056d2cfeeff3869f61dbd49aaa15a2793b5f3458b \ + --hash=sha256:82eb480f6f1c21cea3349dec32cf1a6384c6c1e775f00f83b0d51197bc013687 \ + --hash=sha256:84513ef0aeb8bf8f4ea11a2e8a7ac163ec5288aa115e649a59b470ac5c3107df \ + --hash=sha256:9d2b5c97daf61688c2ad1803ca851800feaba50fb68d5821779e9ea5880d968c \ + --hash=sha256:a4fbb3662f9f59d199d61338e54b4bcc11d07ebbb1aeb3540dacb2be9c521cb7 \ + --hash=sha256:acd5c57b4bd3e56e246e2731a3a3a6825a7a7d89b7e3b761ba80bc521710f04b \ + --hash=sha256:bf501c40b72d2d5c8623620210430e9cac1ce47a46e45b34107b70a1557d46b0 \ + --hash=sha256:c64a0713180ff16829d4e7f39a658b77ea11443af4e1aa46523692943c9b1414 \ + --hash=sha256:cded33237c77caeef62944d32aa9a7ef42bdce2b3497e18d137e072a8c4be438 \ + --hash=sha256:d3407fb7b9c4d75dd68850ffd7180bc0a5d2dbaf0762d888e612f31fec3f9c6b \ + --hash=sha256:ddedfd4b3b4be6be24ff6ca645c4a37fddfd305f6f3e354c54cf10b715c48215 \ + --hash=sha256:de536665495cb4b409d25bade41963f801aff4225c19a6b804b048f7d14e34c7 \ + --hash=sha256:e05ab7baf7f47b406a95fea6f3b0a484b2ddcd9e1d14b68844c457eb755085a3 \ + --hash=sha256:e88646b8580c5ad7f4361477f1298e9cc01771a1ee9aecfe32c47b8ff614cc38 \ + --hash=sha256:ec82e80e65a862275b97c3d90b7a523df8d9519ee48aeb4e9625b2cc909274e0 \ + --hash=sha256:efa3d7318406b4d115dce61ad5061953f1f44b128e79c020ce4615d763e23b6e + # via litellm +tqdm==4.70.1 \ + --hash=sha256:c293e525e6fef9c20e8728fd4612df02a0aa31bb5fe91ecd93e123b1b7bffa73 \ + --hash=sha256:cefd0eca11b2a37a3aee776544d4f4ae913f02688135b5556b8788dfa474afc4 + # via + # huggingface-hub + # openai +truststore==0.10.5 ; sys_platform != 'emscripten' \ + --hash=sha256:30d36967ccaded5cbb38d602c433f53600036c79d502f4533a49b60a03bbefcd \ + --hash=sha256:9aaaedaefaf06d8b206278cf8b5012bc897f485a874503501e12d776df78951c + # via + # httpcore2 + # httpx2 +typing-extensions==4.16.0 \ + --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ + --hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5 + # via + # aiohttp + # aiosignal + # anyio + # fastapi + # httpx2 + # huggingface-hub + # mcp + # mcp-types + # openai + # opentelemetry-api + # pydantic + # pydantic-core + # pydantic-settings + # referencing + # starlette + # typing-inspection +typing-inspection==0.4.4 \ + --hash=sha256:547274fa6b0a561ccf549cc9524b999a578e737d015d8709d021f9d0d13bea47 \ + --hash=sha256:65b8397ba37ccbce054456aaccddfc91e6e3083c92824df348d96ca832f3f147 + # via + # fastapi + # mcp + # pydantic + # pydantic-settings +urllib3==2.8.0 \ + --hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3 \ + --hash=sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63 + # via + # botocore + # requests +uvicorn==0.54.0 \ + --hash=sha256:505bdb0f318731d45f1f712071fc781a8981f6847a31c902c9f5e652d4f67faf \ + --hash=sha256:a2e33cbfaa0306f8e6b0c13e0cb89d7d7a2da3e62b90c66e18c33d9807b28620 + # via + # -r integrations/isolation/acq-kits/claude-code/files/home/claude-code/requirements.in + # mcp +yarl==1.25.1 \ + --hash=sha256:0136d640dfa9b0523853e411430a99f8a91eca85774c6420285a33b755bc6de3 \ + --hash=sha256:03dd38de09bc213e9a8b29761eec33ee1d5318dac0e49d8af36e4d27830e23a7 \ + --hash=sha256:0a191bfdb30a79b98e5d175d75285f9fcb78bf0e46ba5efda042e1c72071a0de \ + --hash=sha256:0a66db89ea473abeac4b70523cafd94db3772380e565f9d28af7a179b7af71fa \ + --hash=sha256:0ae12ff2b805fa02c4dab838005caef735e39986322698c48588d3beacb65c62 \ + --hash=sha256:0f12afda4eea8c8994a76d4df1875c765194f5fbe8a9d197929ea303caee29ec \ + --hash=sha256:10b2fd95332f0d716d5eee3c9fb2ce8eada19082de7fee83d32e37992fd75c26 \ + --hash=sha256:126a2533570c554719ca40a1288fdee1700b6bc82e7131aa69fa85252d92e651 \ + --hash=sha256:12b6bc4906e11f5e1a1cdcb12296e7afbd366c783cc8073403cd2fb74334e453 \ + --hash=sha256:142c06c4d6a35ee3ec5da08499805e879cb3ca7c1fbfbecb0140fe72403818d6 \ + --hash=sha256:14b79a30a93a3ce2e8832603fd0ab780ada281b0ba5110b519a634f2d7d7d1fc \ + --hash=sha256:17c9877a89fb6e2bca6f9087eb24cd7fb434653946ef5075e470d23d49b52287 \ + --hash=sha256:192a866877a49993949ef1975864ad8728bea28ee810f6abe1a0729c2b500426 \ + --hash=sha256:1ab7618921a93767387a4b83776f751588f5b5ae9bb5bc96620e2e2e00bca868 \ + --hash=sha256:1e80dcf1446e1b080b1932b0d103c464a04112f5bc31f0f983ad418172063cde \ + --hash=sha256:1f51020b2eb8a003c84925638ec63c21a750a4bddd3a22ec8eac6a742dadf1b9 \ + --hash=sha256:1fb2a01ba8cd9c5d2c5dc1ec35e0fc951d04b4f037541d4ac090c993ce58b3d7 \ + --hash=sha256:2239a02249d9326655419e0168a28ca9008938eaab31dc29fc875c217927a6c0 \ + --hash=sha256:23bf5b403c879a54964e0feac7285688e04bb220074878d737d331522da0a5bf \ + --hash=sha256:24ce942011a61953e7d313438038f4d32ff21387b775f58a957f7a07dd55ef95 \ + --hash=sha256:25868beca8b6765f8f7d0e11fe6dd7c66dd4b0793b9500286d20cc92352126a5 \ + --hash=sha256:287e99ff5aa4dc1c7630bfc683ded6f106d756c99dec432a2d7f197a784f51c6 \ + --hash=sha256:29273edf1530e397bd07cb784db1fbe0d2590b77569f2e24679a9c0a2d763b94 \ + --hash=sha256:2b49375d22299b0a834c2bca72f39aaecc270d96fb24c30424899676f487b22a \ + --hash=sha256:30eec96e8a91bd588ce897c9543f6d5d8d34b28fbcba28a4dedf20ebeae9fe57 \ + --hash=sha256:319e070a01db9920fb63761843f96a104c8e2b9427266731810dc1e22595b17c \ + --hash=sha256:35dcbea443fafb3eece757ad4e514560ddeb6c34cfae1582c620d7b293d7feee \ + --hash=sha256:3f4d48a6112712973e676bd792121fee470e432d749177162d9949d5c9460a1b \ + --hash=sha256:3feb99222553a8cbedfa52c2f59dd84c3f50d5b582c728d522caf8d72769a54b \ + --hash=sha256:419f392a1da624877975709e3864dfe833af6cc7671b39318086d456e288380c \ + --hash=sha256:42a66563d8cc056ee32e6191e05097a7b2b3bc302e0bc3133daf8710eb18bd26 \ + --hash=sha256:48796ea00a303961507dc6c8437c4b325a6fc3f95f7c36c71b91ea9a8150963c \ + --hash=sha256:4bd6340d20ae2c7ca719b87b426e808e90743b676d05d4c26c4fb5ca71f41184 \ + --hash=sha256:4ca89e4e21854ed27ec753297dde84b16c9f8e53b14a4866fb44457d643c19f8 \ + --hash=sha256:4d781294bb815ecb5ea57ff6bbf8038e0a31a95fdf3e1788f66e0dc100d64b58 \ + --hash=sha256:4f1c91f5a5980a937ff8e238e98e6897e1ad74a4b1e2c0d68c73b5ffbb3f5c0b \ + --hash=sha256:564fdc7085d2245ab84f88882fdb1d6ac0723124bff6ded35bfb1c00f812630d \ + --hash=sha256:59ba3a6e1aa8cfe5adf4bd270fd965db21955401b7ca6f1696010c55ed4daec2 \ + --hash=sha256:5df89f769cc8ff94c3d7e7603386fba309d25ce5240132d26c15baa8d0e96c4c \ + --hash=sha256:632da579b2d879f6bad20f2cfa35ded1efe2f4f77f8abb26a6234a5b236acd2f \ + --hash=sha256:65b5b2066651b7432d389e9799d979c703bcc6ef44266bb8153ef54e91e4aab3 \ + --hash=sha256:664ec6a520b74a1df2810666eb67695fcb77fa663e6ea0a25aaf2e529cb24dfa \ + --hash=sha256:681c758b0490f9e96b78e5fa8e8dc6e648e9185bb6eaebe73183c33ea0c445f3 \ + --hash=sha256:683e362b8ba453080f7489c66f4ea794e751c35b72e7eab3575ef784c2fbc7fb \ + --hash=sha256:68782fdb4027b8d1eee25ec35e9a6db05e863b899eb0310b3a33b6c3fef55707 \ + --hash=sha256:6efaf45df6a849cef613a03a94c845647456662f85438c886bb67a9c027c8c2c \ + --hash=sha256:71f42c5b9a948c113bbdebfa544598321431d064ff959d32e99b1feb61d68345 \ + --hash=sha256:72849d892954be4d09e569b8b831ac39ce58417fedc767d4308a0fe542018a40 \ + --hash=sha256:72c34ac7ad4314c19362d5ce27626dcc8429bd30bbf8c179f4234078851f9492 \ + --hash=sha256:734f6e5400352ac4254456003d462866c684703570929cff7a7bde015d0cb371 \ + --hash=sha256:75baa6cf9b6d1c52f3e111a130e202fd8cf0a5b3a066c3f73d615e885092e4ec \ + --hash=sha256:77716e245c90f058466a05e6a465bb8600f767a8f4b18b4d40f3aff958e5f73c \ + --hash=sha256:77e5099b99b37f3cf79c246998ca9f7313a78054cd1809ec46bc1afad47e1c4c \ + --hash=sha256:783dd1467083f4d3f7722ad6a313f24c173e7571372738fcb7a6e6d1ba48df25 \ + --hash=sha256:7a5c3115595995779ee21f2567035793911c3802a43c74f3fbb0314929ec67ac \ + --hash=sha256:7c88edaec8c349ad4c5ad4c486a3defcc4b80ceb2f074436ffa0a87caf5e76a6 \ + --hash=sha256:7cb414a73e21a7ab58254926073f2930cb22f5b4314ea4260a687e2b3fd4dce3 \ + --hash=sha256:7d42e7e3ca399555578b4d617e3a6ecf13371b3743a115995fa010c7bf341459 \ + --hash=sha256:7d575b54cb3863ef9bc290ea4b009999d55dc237326131e4853cf33e888fee03 \ + --hash=sha256:7e4de3ac4adbad3d0bc7c6f4360a7dbff5de2f15e3b723be3198074e17fd9c40 \ + --hash=sha256:7efc9f082dfed77c316edffa9deb52888e1bc6789171887cc1f68e06d65465c8 \ + --hash=sha256:80a063f8297fc796296f00f100be520f209b23dc98f93ce8eba6ee7122598209 \ + --hash=sha256:80e47012e730da131c9f059c80936783f9659aae22dc31c03c0595590d11ed54 \ + --hash=sha256:83d4a37e4b95da4d8bda930d6d35b75b4cdadbacbb4980cae290ea3100b5d51d \ + --hash=sha256:83e9f4a25085bd4b7214701a0794ff1f50fc633ffb8bdfebf07abdd81c2db126 \ + --hash=sha256:85a18376073f8a39aa07be34f9fc77e2869aa72c55c441efdd2cf79a0407504d \ + --hash=sha256:87796fedc3ba97ec14fab55acb48584276e6c1e4c1e89c422bda62c838e754a9 \ + --hash=sha256:882569ff613758cac762a457a5d72d6e211b28d4bcfea89d1d71ea942b02eac0 \ + --hash=sha256:8ce4d6ccafb33d39bd78444612d14938ead674c25702ded2ee9c54a47735d225 \ + --hash=sha256:8e7d98cdbb6d71e726f7d525952867096053d1f290dd4e3c50d7d313a136f414 \ + --hash=sha256:8ee202350cf57abf0e9502a41601841019c25d3db7ff52d980aaf31446254059 \ + --hash=sha256:8fb0eb4955adf0579001581f2f71a126e8781ba61bcd120f127b0401163c6c2d \ + --hash=sha256:90c30ed53546da833c700115c0064c22120d1b1560f474699fd31f22dd668233 \ + --hash=sha256:9489e6abf47ba37f332075a91444c7cfedb03e6ce99fbb2f116bfe1ce810da3b \ + --hash=sha256:94d7aa6debf92a1dd14cb5280b083a764169a13cfb23a452111160274ed989f4 \ + --hash=sha256:98d370568f393215d605304cdb77b3d5539bd192c75b623c7304c42c8d6d8273 \ + --hash=sha256:9b1bdaae98bc016825dd3c9d8ee1832f829b3341f9cc6ebd1a1b0a7fef7367cc \ + --hash=sha256:9d693bf4bf534e9ba3ae2780cfd577f5135629f7b5ac653490859d0b77864865 \ + --hash=sha256:9d6ed3d17bccce4c05343e1ca8da13bc5c02c812a4e7282ddd05e8769322d3fc \ + --hash=sha256:9e23c82b63cd7652fc24d33ed6cc17099d607aa3b4fc4ddc75e95062f3d82df4 \ + --hash=sha256:a1daf47cd95a7c3a63456336bc5aaa8c86dd3a47d07ed3d0e76132ae4666a5a1 \ + --hash=sha256:a1e32763e641a1566507d90a8d3b19bfc3cc04a9d4e5ae3e32189874ed4b58a3 \ + --hash=sha256:a2059a2d891bd156bc5184e7ab7a56e78a84dfcfdeac8c501b552533ad1c36ee \ + --hash=sha256:a2ed0ba415ccdf08f14bf544cb78346d0f76086707ffee24921a2c84dbf1305a \ + --hash=sha256:a3faadac7d812ddac258feb57b9846b60c1b437c4f4b9ad42595c6f6fe4390df \ + --hash=sha256:a5877f2255aab518ebe528289037699201d5dc5f045f2396cb30aa02db22f57f \ + --hash=sha256:a78b50b4f7918a3de71105d5c0b93bbc57bb8339a4d03a9dfd449f9068e76f3d \ + --hash=sha256:a8c2b841478068440d8b733005d13a5ef535b9928cbc05f17182d410f32ba449 \ + --hash=sha256:a9ca696eb02e5c02a8afd872ada510eba9b7fe6e68b9572c2e9a9b1941e31e2e \ + --hash=sha256:aa4ed3dd308548f9e707d9caaf005d2d7f8c1e7868f858dfeb47fe76e16b391d \ + --hash=sha256:ab2054c5531af2a9ba7b69b8ec91e4f884420e83a8c5e579b013084cb57e5e5d \ + --hash=sha256:abb1384477f5901d436b5d2e5465954de46ea6098f59163d243660b5c4461d35 \ + --hash=sha256:acae6b45d1ace09b6ba3876da43b88366ef368f73b988c7f57e14231753d4420 \ + --hash=sha256:acfa7e22aa6c6e7a5996a41d275bfa01efa7ea56ab890590280e9063e2cf5c1b \ + --hash=sha256:af4ea5b37403ef4e30f3927eaed540db942bde01d8d3ff083527c0704d1c9c68 \ + --hash=sha256:b10dd0557ba422715b5206b3743192135a6022acca8baec51aa127d0a75db8fe \ + --hash=sha256:b13b88747769537f3d32e89e3a735da10c0a9e35d7322928c701b5f93d3afffd \ + --hash=sha256:b51c159a9794633f5e0db7ecec7b2b6e3734eca1f5d17dc989ff3552a43ff78b \ + --hash=sha256:b5402a340723fa7da00b5cff987ddab61276be6d11251ea71ae02bcac54890d8 \ + --hash=sha256:b7abffdf37af1cec6a2ad69b827aa84320db5894791bc8ed932dc93fb274b7e9 \ + --hash=sha256:b8075fe90bc08e40b8b8a1874fab42ee4c7b56af05c5886e9cc841397f916908 \ + --hash=sha256:bc3ac7bf569f6b64dad04dd7808c7872dae8a97df657856eac05e9b7e3614a85 \ + --hash=sha256:bd0912757081f89b107d6c00b2ff8a194401b0b87eadcf4481de2b865a8fd44f \ + --hash=sha256:bdc8d8b8c22e9e43ac68316b5e6cf083dec537f4ec213cb4aa967b583bc3fa64 \ + --hash=sha256:be80550d9bfe83d9b62398a37081a90434e6df2d978ec345c3d2820de6beddab \ + --hash=sha256:c6f117789d22dce188e5754e8bc65b7e6ebf8cb73963b9fa761f672a5883769d \ + --hash=sha256:ca32926d7d77bcc8838425c4c95e040a3ace1cb7dfdae599013458dcda2607ca \ + --hash=sha256:cce0727fd5ac04d372fa9bbfde9febc2bcf209aadfcf0468e45dec72719895d1 \ + --hash=sha256:d0f1489233a254bb3643d2f05de7d59019254d81daeca6b9162fe9edef57e0c7 \ + --hash=sha256:d1c557dfd5e3db046053a0bdc72261ade790ebe8e2c7a41b36b0ca1f14cb95f3 \ + --hash=sha256:d21f0fa80a02d05299207eeaafef345d812ace96d5306e4ef265e1d419a615fa \ + --hash=sha256:d45673badd08456d0340e9364eddafe1c53a9d2896424294de4d7dd71ad3ee57 \ + --hash=sha256:d5add7b4ca7afeea91d52e4d4e4db3b1fe9885b71f07054560d8c4296b7441a2 \ + --hash=sha256:d5f90e44653c4e0f78501ed9bb7d3fce835a8d62b7c6ed0cb16557534087e743 \ + --hash=sha256:d7306dee25b8a0e737363f347362b875094b4dc4e367311470656ae420fdbf8e \ + --hash=sha256:dbcef5a9119ef653653132cccaf999b30a0af6f33bb0a4ba80bec30056868487 \ + --hash=sha256:def538065f9e4d4cf1ae164bd59aba00dfa84f03923e0de4c3788f252d6bcd17 \ + --hash=sha256:df23df54b5114a17c2d0ef192433e2e5a9f0c5178c32375e90b7cfc965f349d0 \ + --hash=sha256:dfbf531053a0935f2e871bcd4753f90313688772ff8c017f5ea402e315a78c1f \ + --hash=sha256:e029648f9c951db30e98a7d7ec90835db88ec4b32820efe2a9bdc2287e032eb6 \ + --hash=sha256:e07595c7d6f4db270ceede356a1bd1c07a34f1c26f958d1ed0cd7b48e0d2bba3 \ + --hash=sha256:e12c538e00e7c1b286a07061046b90e8124e6a9793efae2c70db6a4aad07faad \ + --hash=sha256:e546fe1d4a93ebc2910f0d768baff19faa09843ab3f2036a67ed6e69fae4419d \ + --hash=sha256:e5637ca8d0bd7fb72648a6c7934af4baaccb697657f7438c9d264fc2abb8b0b1 \ + --hash=sha256:e636b64d24fd9c38053c5e389a1174c66361fa49dcfd220f4dd35b4abde7cb89 \ + --hash=sha256:e7011b8fb8c4054bf0c12e5edc6cd83778b0028e99ce59b18586ed036f92cfdc \ + --hash=sha256:e80f557716fd765439577131e526b8942ffc2c07bdbc5e39fa62f660ba1e963f \ + --hash=sha256:e92b6bcc741b86d67606c40d3cb9c7cc8e6c737f81e31f4a94efc204456c92e3 \ + --hash=sha256:eb96ed1ae6c7d072d60840c0434aef07a2df611812810807fbc54263a6053e9a \ + --hash=sha256:eda19ea5ee88742f47a2340816e6f2d40b53bed3ab5b69794769f36af9f35bb4 \ + --hash=sha256:ef74070ac553c59eb4f04258722066d6c6135b7baa03b2e9f2da65c096e96d98 \ + --hash=sha256:efb01a106f971cb3752856bca2318bbdf7f01bd8823779c461586cbe5ffd5258 \ + --hash=sha256:f074e8d4aa0a5798920ddb6de3d08b228c614ff3724c3e8bd7577f4bafea867b \ + --hash=sha256:f38a70074041d3b7e138e452799f5174198bae5bd5ab2000917badf403908c5f \ + --hash=sha256:f41753a76f4f63927d03a0d8ba8f5ce0f2083bec29a8cfaccc55371b1564b96b \ + --hash=sha256:f53dcd26694f148f738edc052b5a69234833e739f10f4c3287bdfd8ec0f7b326 \ + --hash=sha256:f61964f235a43738bfac50da46fc4254943a7eea3051aeb0b6fc7c992c29fadc \ + --hash=sha256:fe01645169a2112aa1d4ebc3e4c5f029c5c8f97adfc32e5d37c993b39a994d75 + # via aiohttp +zipp==4.1.2 \ + --hash=sha256:b30cb6cd253122169c47de245ca24a86bac2a5d3802ba15bf7ba6414eb9e144d \ + --hash=sha256:cf474b90b07ea932637e17c6b9479de2b2882900b0d311bdaf4f5c000a15a97f + # via importlib-metadata diff --git a/claude-code/files/home/claude-code/stream.py b/claude-code/files/home/claude-code/stream.py new file mode 100644 index 0000000..ea59c60 --- /dev/null +++ b/claude-code/files/home/claude-code/stream.py @@ -0,0 +1,63 @@ +"""Normalize repeated tool IDs from gateways that restamp every argument chunk.""" + +import json + + +def encode(event): + return f"event: {event['type']}\ndata: {json.dumps(event)}\n\n".encode() + + +async def normalize(response): + active = None + next_index = 0 + pending_stop = False + source_index = None + buffer = b"" + async for chunk in response: + buffer += chunk if isinstance(chunk, bytes) else chunk.encode() + while b"\n\n" in buffer: + frame, buffer = buffer.split(b"\n\n", 1) + data = b"\n".join(line[6:] for line in frame.splitlines() if line.startswith(b"data: ")) + event = json.loads(data) + kind = event["type"] + if kind == "content_block_start": + block = event["content_block"] + source_index = event["index"] + repeated = ( + active is not None + and block.get("type") == "tool_use" + and active["block"].get("type") == "tool_use" + and block.get("id") == active["block"].get("id") + ) + if repeated: + if block.get("name") != active["block"].get("name"): + raise ValueError("tool ID changed name") + pending_stop = False + continue + if active is not None: + if not pending_stop: + raise ValueError("overlapping content blocks") + yield encode({"type": "content_block_stop", "index": active["index"]}) + active = {"index": next_index, "block": block} + next_index += 1 + pending_stop = False + event["index"] = active["index"] + elif kind == "content_block_delta": + if active is None or pending_stop or event["index"] != source_index: + raise ValueError("delta outside active content block") + event["index"] = active["index"] + elif kind == "content_block_stop": + if active is None or event["index"] != source_index: + raise ValueError("stop outside active content block") + pending_stop = True + continue + elif kind in ("message_delta", "message_stop", "error"): + if active is not None: + if not pending_stop and kind != "error": + raise ValueError("unfinished content block") + yield encode({"type": "content_block_stop", "index": active["index"]}) + active = None + pending_stop = False + yield encode(event) + if buffer.strip() or active is not None: + raise ValueError("incomplete SSE stream") diff --git a/claude-code/scripts/test b/claude-code/scripts/test new file mode 100644 index 0000000..6ce9d4a --- /dev/null +++ b/claude-code/scripts/test @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +"""Provision an isolated temporary test environment; no CI/global dependency changes.""" + +import os +import shutil +import subprocess +import sys +import tempfile +from pathlib import Path + +kit = Path(__file__).resolve().parents[1] +if os.environ.get("RUN_CLAUDE_LIVE") == "1": + raise SystemExit("scripts/test is offline-only; run opt-in live tests explicitly from the configured environment") +with tempfile.TemporaryDirectory(prefix="claude-kit-test-") as work: + python = Path(work) / "venv/bin/python" + if shutil.which("uv"): + subprocess.run(["uv", "venv", "--python", sys.executable, "--seed", str(python.parents[1])], check=True) + else: + subprocess.run([sys.executable, "-m", "venv", str(python.parents[1])], check=True) + subprocess.run( + [ + str(python), + "-m", + "pip", + "install", + "--isolated", + "--require-hashes", + "--only-binary=:all:", + "--index-url", + "https://pypi.org/simple", + "-r", + str(kit / "files/home/claude-code/requirements.lock"), + ], + check=True, + ) + subprocess.run( + [ + str(python), + "-m", + "pip", + "install", + "--isolated", + "--only-binary=:all:", + "--index-url", + "https://pypi.org/simple", + "--require-hashes", + "-r", + str(kit / "tests/requirements.lock"), + ], + check=True, + ) + sys.exit(subprocess.run([str(python), "-m", "pytest", str(kit / "tests"), "-q"]).returncode) diff --git a/claude-code/scripts/verify b/claude-code/scripts/verify new file mode 100644 index 0000000..a6f278a --- /dev/null +++ b/claude-code/scripts/verify @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +"""Offline kit check plus opt-in real wrapper probe in an existing sandbox.""" + +import argparse +import shutil +import subprocess +import sys +from pathlib import Path + +KIT = Path(__file__).resolve().parents[1] + +parser = argparse.ArgumentParser(description=__doc__) +parser.add_argument("--sandbox", help="existing configured sandbox; never creates/deletes a VM") +parser.add_argument("--acq", default="acq", help="acq executable; use the absolute tested checkout path") +args = parser.parse_args() +commands = [ + [sys.executable, str(KIT.parent / "scripts/validate-kits.py")], + [sys.executable, str(KIT / "scripts/test")], +] +for command in commands: + if subprocess.run(command).returncode: + sys.exit(1) +if not args.sandbox or not shutil.which(args.acq): + print("UNVERIFIED: live microVM/PTY/provider checks require acq and --sandbox") + sys.exit(3) +for command in (["claude", "--version"], ["claude", "-p", "--tools", "", "Reply exactly ACQ_OK"]): + result = subprocess.run( + [args.acq, "exec", args.sandbox, "--", *command], capture_output=True, text=True, timeout=180 + ) + expected = "2.1.314" if "--version" in command else "ACQ_OK" + if result.returncode or expected not in result.stdout: + print("FAIL: guest Claude wrapper/version/provider probe failed; sensitive output withheld") + sys.exit(1) +print("PASS: offline checks and real guest wrapper/provider probes") +print("UNVERIFIED: human interactive PTY and optional browser composition require manual checks") +sys.exit(3) diff --git a/claude-code/spec.yaml b/claude-code/spec.yaml new file mode 100644 index 0000000..5e6f04b --- /dev/null +++ b/claude-code/spec.yaml @@ -0,0 +1,69 @@ +schemaVersion: "hybrid/v1" +kind: mixin +name: claude-code +displayName: Claude Code (OpenAI-compatible gateway) +description: > + Installs pinned Claude Code for Linux x64 or ARM64 and a hash-locked LiteLLM + Messages-to-Chat-Completions bridge. The host reaches Claude's TUI through + acq's terminal connection. Each invocation owns an authenticated guest-loopback + proxy, with no published model API or desktop requirement. Provider facts, + model snapshots, and credentials come from acq, not this kit. +agent: + name: claude + entrypoint: claude +caps: + network: + allow: + - registry.npmjs.org + - pypi.org + - files.pythonhosted.org +files: + - path: /home/agent/claude-code/install.py + mode: "0755" + source: files/home/claude-code/install.py + - path: /home/agent/claude-code/provider.py + mode: "0644" + source: files/home/claude-code/provider.py + - path: /home/agent/claude-code/proxy.py + mode: "0644" + source: files/home/claude-code/proxy.py + - path: /home/agent/claude-code/launch.py + mode: "0755" + source: files/home/claude-code/launch.py + - path: /home/agent/claude-code/stream.py + mode: "0644" + source: files/home/claude-code/stream.py + - path: /home/agent/claude-code/models.py + mode: "0644" + source: files/home/claude-code/models.py + - path: /home/agent/claude-code/requirements.lock + mode: "0644" + source: files/home/claude-code/requirements.lock + - path: /home/agent/.local/bin/claude + mode: "0755" + source: files/home/.local/bin/claude +commands: + - phase: startup + user: "1000" + description: Install pinned Claude Code and its locked translation bridge as the agent user + command: + - python3 + - /home/agent/claude-code/install.py + - --apply +agentContext: | + ## Claude Code through an OpenAI-compatible gateway + + Run `claude` in the host-attached guest terminal. It starts a private + authenticated proxy and routes Claude's Messages API to the selected + provider's OpenAI Chat Completions API. No Anthropic subscription login, + display, or published proxy port is needed. Permission prompts remain active. + + ACQ_PROVIDER_INPUT_ROOT must be materialized before launch; model credentials + must be injected by acq. With several providers, set ACQ_CLAUDE_PROVIDER. + ACQ_CLAUDE_MODEL, ACQ_CLAUDE_SMALL_MODEL and ACQ_CLAUDE_OPUS_MODEL override + the provider catalog's recommendations. Models must exist in that snapshot. + + This bridge supports text and ordinary function tools, not Anthropic-native + server tools, extended thinking, prompt caching, or exact token counting. + The separate Paseo kit can publish its agent browser UI on guest port 6767; + the model proxy must remain private. See this kit's README for composition. diff --git a/claude-code/tests/requirements.in b/claude-code/tests/requirements.in new file mode 100644 index 0000000..7dbc533 --- /dev/null +++ b/claude-code/tests/requirements.in @@ -0,0 +1,2 @@ +# Test framework only; runtime packages remain in the payload's separate lock. +pytest==9.1.1 diff --git a/claude-code/tests/requirements.lock b/claude-code/tests/requirements.lock new file mode 100644 index 0000000..816934c --- /dev/null +++ b/claude-code/tests/requirements.lock @@ -0,0 +1,26 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile claude-code/tests/requirements.in --python-version 3.12 --universal --generate-hashes --only-binary :all: --output-file claude-code/tests/requirements.lock +colorama==0.4.6 ; sys_platform == 'win32' \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via pytest +iniconfig==2.3.1 \ + --hash=sha256:67f4b9c50da0dedf52af349e7749a80a9057a5031199791b906c3bb3ae878960 \ + --hash=sha256:9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7 + # via pytest +packaging==26.3 \ + --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ + --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c + # via pytest +pluggy==1.7.0 \ + --hash=sha256:7dd7b0d8832ba3cb632c306926ded123429211b83641b35dc5c41ad2d34f9bec \ + --hash=sha256:d1eaa46ebb595891b860ab086b4d09c8588af65ebd4361b8e8f4bb8920b90ba8 + # via pytest +pygments==2.21.0 \ + --hash=sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9 \ + --hash=sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c + # via pytest +pytest==9.1.1 \ + --hash=sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313 \ + --hash=sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c + # via -r claude-code/tests/requirements.in diff --git a/claude-code/tests/test_claude_code.py b/claude-code/tests/test_claude_code.py new file mode 100644 index 0000000..b88cbee --- /dev/null +++ b/claude-code/tests/test_claude_code.py @@ -0,0 +1,385 @@ +"""Offline boundaries and live opt-in checks for the Claude kit.""" + +import asyncio +import hashlib +import io +import json +import os +import sys +import tarfile +from pathlib import Path +from unittest.mock import AsyncMock + +import pytest +from fastapi.testclient import TestClient + +PAYLOAD = Path(__file__).resolve().parents[1] / "files/home/claude-code" +sys.path.insert(0, str(PAYLOAD)) +from install import PINS, PIP_SHA256, bootstrap_venv, extract_binary # noqa: E402 -- standalone kit payload +from launch import claude_environment, run_session # noqa: E402 +from provider import load_provider, strict_json # noqa: E402 +from proxy import arguments, make_app, sse # noqa: E402 +from stream import encode, normalize # noqa: E402 + + +@pytest.fixture +def inputs(tmp_path): + directory = tmp_path / "models/providers/example" + directory.mkdir(parents=True) + facts = { + "schemaVersion": "acq-provider-facts/v1", + "providerId": "example", + "apiProtocol": "openai-compatible", + "host": "example.invalid", + "baseUrl": "https://example.invalid/v1", + "keyEnv": "EXAMPLE_MODEL_KEY", + } + catalog = { + "schemaVersion": "acq-neutral-model-catalog/v1", + "providerId": "example", + "models": [{"id": "model-a"}, {"id": "model-b"}], + "recommendations": {"primary": "model-a", "small": "model-b"}, + } + (directory / "facts.json").write_text(json.dumps(facts)) + (directory / "snapshot.json").write_text(json.dumps(catalog)) + return tmp_path, directory, facts, catalog + + +def test_provider_recommendations_and_overrides(inputs): + root, _, _, _ = inputs + env = {"ACQ_PROVIDER_INPUT_ROOT": str(root), "EXAMPLE_MODEL_KEY": "synthetic"} + facts, ids, roles = load_provider(env) + assert facts["providerId"] == "example" + assert ids == ["model-a", "model-b"] + assert roles == {"primary": "model-a", "small": "model-b", "opus": "model-a"} + env["ACQ_CLAUDE_MODEL"] = "model-b" + assert load_provider(env)[2]["primary"] == "model-b" + + +@pytest.mark.parametrize("change", ["missing-key", "unknown-model", "symlink", "http", "identity", "duplicate"]) +def test_provider_rejects_invalid_input(inputs, change): + root, directory, facts, catalog = inputs + env = {"ACQ_PROVIDER_INPUT_ROOT": str(root), "EXAMPLE_MODEL_KEY": "synthetic"} + if change == "missing-key": + env.pop("EXAMPLE_MODEL_KEY") + elif change == "unknown-model": + env["ACQ_CLAUDE_MODEL"] = "absent" + elif change == "symlink": + (directory / "facts.json").rename(directory / "original.json") + (directory / "facts.json").symlink_to("original.json") + elif change == "http": + facts["baseUrl"] = "http://example.invalid/v1" + (directory / "facts.json").write_text(json.dumps(facts)) + elif change == "identity": + catalog["providerId"] = "other" + (directory / "snapshot.json").write_text(json.dumps(catalog)) + else: + (directory / "facts.json").write_text('{"schemaVersion":"x","schemaVersion":"y"}') + with pytest.raises(ValueError): + load_provider(env) + + +def test_missing_empty_and_ambiguous_providers(inputs): + root, _, _, _ = inputs + with pytest.raises(ValueError): + load_provider({}) + (root / "models/providers/second").mkdir() + with pytest.raises(ValueError): + load_provider({"ACQ_PROVIDER_INPUT_ROOT": str(root)}) + + +def test_child_environment_removes_credentials(inputs, monkeypatch): + _, _, facts, _ = inputs + monkeypatch.setenv("EXAMPLE_MODEL_KEY", "synthetic-provider") + monkeypatch.setenv("GITHUB_TOKEN", "synthetic-github") + env = claude_environment( + facts, {"primary": "model-a", "small": "model-b", "opus": "model-a"}, 1234, "synthetic-local" + ) + assert "EXAMPLE_MODEL_KEY" not in env and "GITHUB_TOKEN" not in env + assert env["ANTHROPIC_AUTH_TOKEN"] == "synthetic-local" # noqa: S105 -- synthetic test token + assert env["ANTHROPIC_BASE_URL"] == "http://127.0.0.1:1234" + assert env["MAX_THINKING_TOKENS"] == "0" + + +def test_proxy_routes_auth_validation_and_redaction(inputs, monkeypatch): + _, _, facts, _ = inputs + monkeypatch.setenv("EXAMPLE_MODEL_KEY", "synthetic-provider") + mock = AsyncMock(return_value={"content": [{"type": "text", "text": "OK"}]}) + monkeypatch.setattr("proxy.litellm.anthropic.messages.acreate", mock) + client = TestClient(make_app(facts, ["model-a"], "synthetic-local")) + data = {"model": "model-a", "max_tokens": 32, "messages": [{"role": "user", "content": "hello"}]} + headers = {"Authorization": "Bearer synthetic-local"} + assert client.post("/v1/messages", json=data).status_code == 401 + assert client.post("/v1/messages", json={**data, "model": "unknown"}, headers=headers).status_code == 400 + rejected = client.post("/v1/messages", json={**data, "model": "unknown"}, headers=headers) + assert "exact gateway model ID" in rejected.text + assert "unknown" not in rejected.text + data.update(api_base="https://attacker.invalid", api_key="untrusted", callbacks=["untrusted"]) + assert client.post("/v1/messages", json=data, headers=headers).status_code == 200 + assert mock.call_args.kwargs["api_base"] == facts["baseUrl"] + assert "callbacks" not in mock.call_args.kwargs + mock.side_effect = RuntimeError("synthetic-provider private prompt") + result = client.post("/v1/messages", json=data, headers=headers) + assert result.status_code == 502 and "private prompt" not in result.text + assert client.get("/docs").status_code == 404 + assert client.post("/v1/messages/count_tokens", json=data, headers=headers).json()["input_tokens"] > 0 + + +def test_server_tools_rejected(inputs, monkeypatch): + _, _, facts, _ = inputs + monkeypatch.setenv("EXAMPLE_MODEL_KEY", "synthetic") + with pytest.raises(ValueError): + arguments({"model": "a", "max_tokens": 1, "tools": [{"type": "web_search_20250305"}]}, facts) + + +@pytest.mark.parametrize("kind", ["regular", "symlink", "duplicate", "wrong-hash"]) +def test_archive_validation(tmp_path, kind): + archive = tmp_path / "archive.tgz" + with tarfile.open(archive, "w:gz") as bundle: + member = tarfile.TarInfo("package/claude") + member.size = 4 + if kind == "symlink": + member.type = tarfile.SYMTYPE + member.linkname = "/etc/passwd" + bundle.addfile(member, io.BytesIO(b"test") if member.isreg() else None) + if kind == "duplicate": + bundle.addfile(member, io.BytesIO(b"test")) + digest = hashlib.sha256(archive.read_bytes()).hexdigest() + destination = tmp_path / "claude" + if kind == "regular": + extract_binary(archive, digest, destination) + assert destination.read_bytes() == b"test" + else: + with pytest.raises(ValueError): + extract_binary(archive, "0" * 64 if kind == "wrong-hash" else digest, destination) + assert not destination.exists() + + +def test_both_architectures_have_independent_pins(): + assert set(PINS) == {"x86_64", "aarch64"} + assert PINS["x86_64"][0] == "x64" + assert PINS["aarch64"][0] == "arm64" + assert PINS["x86_64"][1] != PINS["aarch64"][1] + + +def test_bootstrap_without_ensurepip_rejects_wrong_wheel(tmp_path, monkeypatch): + calls = [] + monkeypatch.setattr("install.subprocess.run", lambda argv, **kwargs: calls.append(argv)) + + class Response(io.BytesIO): + def geturl(self): + from install import PIP_URL + + return PIP_URL + + monkeypatch.setattr("install.urllib.request.urlopen", lambda *a, **kw: Response(b"wrong wheel")) + with pytest.raises(ValueError, match="pip wheel SHA-256 mismatch"): + bootstrap_venv(tmp_path, tmp_path) + assert len(calls) == 1 + assert "--without-pip" in calls[0] + assert len(PIP_SHA256) == 64 + + +def test_duplicate_json_rejected(): + with pytest.raises(ValueError): + strict_json('{"a":1,"a":2}') + + +def test_claude_model_settings_preserve_sdk_hooks(): + from models import compose_settings + + ids = ["claude-sonnet-5.5", "claude_4_5_haiku"] + roles = {"primary": ids[0]} + args, settings = compose_settings(["-p", "ping", "--settings", '{"hooks":{"test":[]},"model":"fable"}'], ids, roles) + assert args == ["-p", "ping"] + assert settings["hooks"] == {"test": []} + assert settings["model"] == ids[0] + assert all(model in settings["availableModels"] for model in ids) + assert settings["modelOverrides"]["claude-sonnet-5-5"] == "claude-sonnet-5.5" + assert "fable" not in settings["availableModels"] + assert settings["modelPicker"]["replaceBuiltInOptions"] + with pytest.raises(ValueError, match="exact gateway ID"): + compose_settings(["--model", "fable", "-p", "ping"], ids, roles) + assert compose_settings(["--model", ids[0], "-p", "ping"], ids, roles)[0][1] == ids[0] + assert compose_settings(["--model", "claude-sonnet-5-5"], ids, roles)[0][1] == "claude-sonnet-5-5" + from models import settings_argv + + original = ["-p", "--", "--settings", '{"hooks":{"untrusted":[]}}'] + remaining, composed = compose_settings(original, ids, roles) + assert remaining == original + assert "hooks" not in composed + assert settings_argv(remaining, "owned.json") == ["-p", "--settings", "owned.json", *original[1:]] + + +def test_canonical_mappings_never_replace_gateway_ids_or_missing_models(): + from models import model_overrides + + assert model_overrides([]) == {} + assert model_overrides(["claude-sonnet-5.5"]) == {"claude-sonnet-5-5": "claude-sonnet-5.5"} + assert model_overrides(["claude-sonnet-5.5", "claude-sonnet-5-5"]) == {} + overrides = model_overrides(["claude_4_8_opus", "claude_4_5_haiku"]) + assert overrides == {"claude-opus-4-8": "claude_4_8_opus", "claude-haiku-4-5": "claude_4_5_haiku"} + assert not any("fable" in key or "[1m]" in key for key in overrides) + + +def test_stream_holds_slot_until_close(): + async def run(): + gate = asyncio.Semaphore(4) + closed = [] + + class Stream: + def __aiter__(self): + return self + + async def __anext__(self): + raise StopAsyncIteration + + async def aclose(self): + closed.append(True) + + for _ in range(4): + await gate.acquire() + waiter = asyncio.create_task(gate.acquire()) + await asyncio.sleep(0) + assert not waiter.done() + async for _ in sse(Stream(), gate): + pass + await asyncio.wait_for(waiter, 1) + assert closed == [True] + + asyncio.run(run()) + + +def test_repeated_tool_id_fragments_form_one_call(): + async def source(): + for index, fragment in enumerate(['{"file_', 'path":"/tmp/probe.txt"}']): + yield encode( + { + "type": "content_block_start", + "index": index, + "content_block": {"type": "tool_use", "id": "same-call", "name": "Read", "input": {}}, + } + ) + yield encode( + { + "type": "content_block_delta", + "index": index, + "delta": {"type": "input_json_delta", "partial_json": fragment}, + } + ) + yield encode({"type": "content_block_stop", "index": index}) + yield encode({"type": "message_delta", "delta": {"stop_reason": "tool_use"}}) + yield encode({"type": "message_stop"}) + + async def run(): + frames = [frame async for frame in normalize(source())] + events = [json.loads(frame.split(b"data: ", 1)[1]) for frame in frames] + assert sum(e["type"] == "content_block_start" for e in events) == 1 + assert sum(e["type"] == "content_block_stop" for e in events) == 1 + fragments = [e["delta"]["partial_json"] for e in events if e["type"] == "content_block_delta"] + assert json.loads("".join(fragments)) == {"file_path": "/tmp/probe.txt"} # noqa: S108 -- data only, no file IO + assert all(e.get("index", 0) == 0 for e in events) + + asyncio.run(run()) + + +@pytest.mark.skipif(os.environ.get("RUN_CLAUDE_LIVE") != "1", reason="explicit live opt-in required") +def test_live_translation(): + import litellm + + facts, ids, roles = load_provider() + client = TestClient(make_app(facts, ids, "synthetic-local")) + data = { + "model": roles["small"], + "max_tokens": 64, + "messages": [{"role": "user", "content": "Reply exactly ACQ_OK"}], + } + headers = {"Authorization": "Bearer synthetic-local"} + result = client.post("/v1/messages", json=data, headers=headers) + assert result.status_code == 200, result.text + assert "ACQ_OK" in result.text + result = client.post("/v1/messages", json={**data, "stream": True}, headers=headers) + assert "event: message_stop" in result.text and "event: error" not in result.text + assert litellm.use_chat_completions_url_for_anthropic_messages + + async def tools(): + args = arguments( + { + **data, + "messages": [{"role": "user", "content": "Call check with value ACQ_OK"}], + "tools": [ + { + "name": "check", + "description": "Return the value", + "input_schema": { + "type": "object", + "properties": {"value": {"type": "string"}}, + "required": ["value"], + }, + } + ], + "tool_choice": {"type": "tool", "name": "check"}, + }, + facts, + ) + result = await litellm.anthropic.messages.acreate(**args) + assert result["stop_reason"] == "tool_use" + assert any(block["type"] == "tool_use" for block in result["content"]) + + asyncio.run(tools()) + + +@pytest.mark.skipif( + os.environ.get("RUN_CLAUDE_LIVE") != "1" or not os.environ.get("ACQ_CLAUDE_TEST_BINARY"), + reason="explicit live CLI opt-in required", +) +def test_live_claude_session(tmp_path, monkeypatch, capfd): + import multiprocessing + + monkeypatch.setenv("ACQ_CLAUDE_MODEL", "claude_4_5_haiku") + monkeypatch.chdir(tmp_path) + code = run_session( + Path(os.environ["ACQ_CLAUDE_TEST_BINARY"]), + [ + "-p", + "--tools", + "", + "--setting-sources", + "", + "--strict-mcp-config", + "--no-session-persistence", + "Reply exactly ACQ_OK", + ], + ) + output = capfd.readouterr() + assert code == 0, output.out + output.err + assert "ACQ_OK" in output.out + assert not multiprocessing.active_children() + + +@pytest.mark.skipif( + os.environ.get("RUN_CLAUDE_LIVE") != "1" or not os.environ.get("ACQ_CLAUDE_TEST_BINARY"), + reason="explicit live CLI tool opt-in required", +) +def test_live_claude_reads_tool_result(tmp_path, monkeypatch, capfd): + monkeypatch.setenv("ACQ_CLAUDE_MODEL", "claude_4_5_haiku") + monkeypatch.chdir(tmp_path) + (tmp_path / "probe.txt").write_text("ACQ_TOOL_RESULT_7391") + code = run_session( + Path(os.environ["ACQ_CLAUDE_TEST_BINARY"]), + [ + "-p", + "--tools", + "Read", + "--allowedTools", + "Read", + "--setting-sources", + "", + "--strict-mcp-config", + "--no-session-persistence", + f"Use the Read tool to read {tmp_path / 'probe.txt'}. Reply exactly with the file contents.", + ], + ) + output = capfd.readouterr() + assert code == 0, output.out + output.err + assert "ACQ_TOOL_RESULT_7391" in output.out diff --git a/claude-code/tests/test_lifecycle.py b/claude-code/tests/test_lifecycle.py new file mode 100644 index 0000000..831023a --- /dev/null +++ b/claude-code/tests/test_lifecycle.py @@ -0,0 +1,235 @@ +"""Real launcher lifecycle checks with synthetic credentials and no upstream calls.""" + +import json +import os +import signal +import subprocess +import sys +import time +from contextlib import suppress +from pathlib import Path + +import pytest + +PAYLOAD = Path(__file__).resolve().parents[1] / "files/home/claude-code" +PYTHON = Path(sys.executable) +pytestmark = pytest.mark.skipif(not Path("/proc/self/stat").exists(), reason="Linux process inspection required") + +FAKE_CLAUDE = """import json +import os +import subprocess +import sys +import time +from pathlib import Path + +# An ordinary tool descendant, deliberately requiring process-group escalation. +tool = subprocess.Popen([ + sys.executable, "-c", + "import signal, time; signal.signal(signal.SIGTERM, signal.SIG_IGN); print('ready', flush=True); time.sleep(300)", +], stdout=subprocess.PIPE, text=True) +assert tool.stdout.readline().strip() == "ready" +if sys.stdin.isatty(): + # Immediate read must not stop on SIGTTIN before foreground handoff. + assert sys.stdin.readline().strip() == "terminal-ready" +names = ( + "FIRST_MODEL_KEY", "SECOND_MODEL_KEY", "GITHUB_TOKEN", "USAI_API_KEY", + "OPENAI_API_KEY", "ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN", + "ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_BASE_URL", "ANTHROPIC_MODEL", +) +record = { + "claude": os.getpid(), "tool": tool.pid, "group": os.getpgrp(), + "foreground": os.tcgetpgrp(0) if sys.stdin.isatty() else None, + "environment": {name: os.environ[name] for name in names if name in os.environ}, +} +target = Path(os.environ["TEST_CLAUDE_RECORD"]) +pending = target.with_suffix(".pending") +pending.write_text(json.dumps(record)) +pending.replace(target) +tool.wait() +""" + + +def running(pid): + """Zombies have exited; PID existence alone does not mean a leaked process.""" + try: + stat = Path(f"/proc/{pid}/stat").read_text() + except FileNotFoundError: + return False + return stat.rsplit(")", 1)[1].split()[0] not in {"Z", "X"} + + +def wait_until(predicate, timeout=15): + deadline = time.monotonic() + timeout + while time.monotonic() < deadline: + if predicate(): + return True + time.sleep(0.05) + return False + + +def direct_children(pid): + return {int(value) for value in Path(f"/proc/{pid}/task/{pid}/children").read_text().split()} + + +def provider_inputs(root, provider_id, key): + directory = root / "models/providers" / provider_id + directory.mkdir(parents=True) + facts = { + "schemaVersion": "acq-provider-facts/v1", + "providerId": provider_id, + "apiProtocol": "openai-compatible", + "host": "example.invalid", + "baseUrl": "https://example.invalid/v1", + "keyEnv": key, + } + snapshot = { + "schemaVersion": "acq-neutral-model-catalog/v1", + "providerId": provider_id, + "models": [{"id": "model-a"}], + "recommendations": {"primary": "model-a"}, + } + for name, data in (("facts.json", facts), ("snapshot.json", snapshot)): + path = directory / name + path.write_text(json.dumps(data)) + path.chmod(0o444) + + +def controlling_terminal(): + """Give the wrapper a real controlling terminal without changing the runner.""" + import fcntl + import termios + + os.setsid() + fcntl.ioctl(0, termios.TIOCSCTTY, 0) + + +@pytest.fixture +def session(tmp_path): + assert PYTHON.is_file(), f"provisioned kit interpreter required: {PYTHON}" + home = tmp_path / "home" + binary = home / ".local/share/acq/claude-code/claude" + binary.parent.mkdir(parents=True) + binary.write_text(f"#!{PYTHON}\n" + FAKE_CLAUDE) + binary.chmod(0o755) + root = tmp_path / "inputs" + provider_inputs(root, "first", "FIRST_MODEL_KEY") + provider_inputs(root, "second", "SECOND_MODEL_KEY") + record = tmp_path / "claude.json" + env = { + "HOME": str(home), + "PATH": f"{PYTHON.parent}:/usr/bin:/bin", + "LC_ALL": "C.UTF-8", + "PYTHONUNBUFFERED": "1", + "ACQ_PROVIDER_INPUT_ROOT": str(root), + "ACQ_CLAUDE_PROVIDER": "first", + "TEST_CLAUDE_RECORD": str(record), + **{ + name: "synthetic-" + name.lower() + for name in ( + "FIRST_MODEL_KEY", + "SECOND_MODEL_KEY", + "GITHUB_TOKEN", + "USAI_API_KEY", + "OPENAI_API_KEY", + "ANTHROPIC_API_KEY", + "CLAUDE_CODE_OAUTH_TOKEN", + ) + }, + } + # Only explicit synthetic entries reach either the wrapper or its proxy. + yield tmp_path, record, env + + +@pytest.fixture +def launched(session, request): + import pty + + tmp_path, record, env = session + terminal = getattr(request, "param", False) + master, slave = pty.openpty() if terminal else (None, None) + descendants = set() + with (tmp_path / "launcher.log").open("w+") as output: + wrapper = subprocess.Popen( # noqa: S603 -- fixed local interpreter and launcher + [str(PYTHON), str(PAYLOAD / "launch.py")], + cwd=tmp_path, + env=env, + stdin=slave if terminal else subprocess.DEVNULL, + stdout=output, + stderr=output, + start_new_session=not terminal, + preexec_fn=controlling_terminal if terminal else None, + ) + try: + if master is not None: + os.write(master, b"terminal-ready\n") + assert wait_until(lambda: record.exists() or wrapper.poll() is not None, 75) + output.seek(0) + assert record.exists(), output.read() + data = json.loads(record.read_text()) + descendants = direct_children(wrapper.pid) | {data["claude"], data["tool"]} + proxies = [ + pid + for pid in descendants + if pid != data["tool"] and b"spawn_main" in Path(f"/proc/{pid}/cmdline").read_bytes() + ] + assert len(proxies) == 1, "real multiprocessing proxy must be running" + assert all(running(pid) for pid in descendants) + yield wrapper, data, descendants, output + finally: + # Failure cleanup is scoped to this wrapper and the PIDs it created. + if record.exists(): + data = json.loads(record.read_text()) + with suppress(ProcessLookupError): + os.killpg(data["group"], signal.SIGKILL) + if wrapper.poll() is None: + descendants.update(direct_children(wrapper.pid)) + wrapper.kill() + wrapper.wait(timeout=15) + for pid in descendants: + if running(pid): + with suppress(ProcessLookupError): + os.kill(pid, signal.SIGKILL) + for fd in (master, slave): + if fd is not None: + os.close(fd) + + +@pytest.mark.parametrize("launched", [False, True], indirect=True, ids=["pipe", "terminal"]) +@pytest.mark.parametrize("signum, expected", [(signal.SIGHUP, 129), (signal.SIGTERM, 143)]) +def test_targeted_signal_reaps_claude_proxy_and_tool(launched, signum, expected): + wrapper, data, descendants, output = launched + assert data["group"] == data["claude"] + assert data["group"] != wrapper.pid + if data["foreground"] is not None: + assert data["foreground"] == data["group"] + # Signal only main, not the wrapper's group or any of its descendants. + os.kill(wrapper.pid, signum) + code = wrapper.wait(timeout=25) + output.seek(0) + assert code == expected, output.read() + assert wait_until(lambda: not any(running(pid) for pid in descendants)), ( + f"launcher leaked descendants: {[pid for pid in descendants if running(pid)]}" + ) + + +def test_two_provider_credentials_are_not_inherited_by_claude(launched): + wrapper, data, descendants, output = launched + env = data["environment"] + assert not set(env).intersection( + { + "FIRST_MODEL_KEY", + "SECOND_MODEL_KEY", + "GITHUB_TOKEN", + "USAI_API_KEY", + "OPENAI_API_KEY", + "ANTHROPIC_API_KEY", + "CLAUDE_CODE_OAUTH_TOKEN", + } + ) + assert env["ANTHROPIC_AUTH_TOKEN"] and not env["ANTHROPIC_AUTH_TOKEN"].startswith("synthetic-") + assert env["ANTHROPIC_BASE_URL"].startswith("http://127.0.0.1:") + assert env["ANTHROPIC_MODEL"] == "model-a" + os.kill(wrapper.pid, signal.SIGTERM) + output.seek(0) + assert wrapper.wait(timeout=25) == 143, output.read() + assert wait_until(lambda: not any(running(pid) for pid in descendants)) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..7d2e576 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,18 @@ +[tool.ruff] +line-length = 120 +target-version = "py312" + +[tool.ruff.lint] +select = ["E", "F", "I", "UP", "B", "SIM", "S"] + +[tool.ruff.lint.per-file-ignores] +"scripts/tests/*" = ["S101", "S603", "S607"] +# argv-only calls use an allowlisted kit and resolved executables, never a shell. +"scripts/run-kit-tests.py" = ["S603"] +"scripts/validate-kits.py" = ["S603"] +"claude-code/tests/*" = ["S101", "S603", "S607"] +"claude-code/scripts/test" = ["S603", "S607"] +"claude-code/scripts/verify" = ["S603", "S607"] + +[tool.pytest.ini_options] +testpaths = ["scripts/tests"] diff --git a/requirements-dev.in b/requirements-dev.in new file mode 100644 index 0000000..80280d1 --- /dev/null +++ b/requirements-dev.in @@ -0,0 +1,6 @@ +# Shared CI tools; regenerate with uv pip compile --generate-hashes. +jsonschema==4.26.0 +PyYAML==6.0.3 +pytest==9.1.1 +ruff==0.17.0 +pip-audit==2.10.1 diff --git a/requirements-dev.lock b/requirements-dev.lock new file mode 100644 index 0000000..34f3bdc --- /dev/null +++ b/requirements-dev.lock @@ -0,0 +1,159 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile requirements-dev.in --python-version 3.12 --universal --generate-hashes --only-binary :all: --output-file requirements-dev.lock +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 + # via + # jsonschema + # referencing +boolean-py==5.0 \ + --hash=sha256:ef28a70bd43115208441b53a045d1549e2f0ec6e3d08a9d142cbc41c1938e8d9 + # via license-expression +cachecontrol==0.14.4 \ + --hash=sha256:b7ac014ff72ee199b5f8af1de29d60239954f223e948196fa3d84adaffc71d2b + # via pip-audit +certifi==2026.10.23 \ + --hash=sha256:e9b54de76e530bb6cf0ccd036787103acb58fd42ba930ea8bf948ddbaa2f61d1 + # via requests +charset-normalizer==3.5.2 \ + --hash=sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a \ + --hash=sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649 \ + --hash=sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80 \ + --hash=sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685 + # via requests +colorama==0.4.6 ; sys_platform == 'win32' \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via pytest +cyclonedx-python-lib==11.12.0 \ + --hash=sha256:0e807521a921a5c3cb8ce1153f8a61d29eedfe76a46aac2796b7c6b573391a54 + # via pip-audit +defusedxml==0.7.1 \ + --hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 + # via py-serializable +filelock==4.2.5 \ + --hash=sha256:46ce42d27e5cdde09ee7197349663e97cb106679bd9e75db3a09679fbc7aa1a8 + # via cachecontrol +idna==3.20 \ + --hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c + # via requests +iniconfig==2.3.1 \ + --hash=sha256:9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7 + # via pytest +jsonschema==4.26.0 \ + --hash=sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce + # via -r requirements-dev.in +jsonschema-specifications==2025.9.1 \ + --hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe + # via jsonschema +license-expression==30.4.4 \ + --hash=sha256:421788fdcadb41f049d2dc934ce666626265aeccefddd25e162a26f23bcbf8a4 + # via cyclonedx-python-lib +markdown-it-py==4.2.0 \ + --hash=sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a + # via rich +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 + # via markdown-it-py +msgpack==1.2.4 \ + --hash=sha256:2444a4e04f924630d059ae6eae8f91fdfcd28ed9fd17b21bacf4e74550a091f7 \ + --hash=sha256:9ca1e78106675f2aed07dc37b842ce19be70010ab22c5c5c04688f0840d48539 \ + --hash=sha256:55e6106d2d085af42b2de72efeb38ed255241a24b32295ca889707c1d679c442 \ + --hash=sha256:5d65b791ce4283e02b6267742ad540899155e1b32887b9cbdda47f38f5a076b5 \ + --hash=sha256:c4d5bbdbea8f5669b3a734d6c226772804fb120848f99cbe63a0ddee63b049c9 + # via cachecontrol +packageurl-python==0.17.6 \ + --hash=sha256:31a85c2717bc41dd818f3c62908685ff9eebcb68588213745b14a6ee9e7df7c9 + # via cyclonedx-python-lib +packaging==26.3 \ + --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c + # via + # pip-audit + # pip-requirements-parser + # pytest +pip==26.2.2 \ + --hash=sha256:fd7f4dfa8190e014013b9f08f3e973f4e4c26ffd179a204895533a7254813a70 + # via pip-api +pip-api==0.0.35 \ + --hash=sha256:66990d0da25378555cbb538db79384bab92d4617c6350dfd7a2126ba2a3a9894 + # via pip-audit +pip-audit==2.10.1 \ + --hash=sha256:99ef3f600a317c1945f1e89e227ef26e1c2d618429b8bd3fa6f4f7c440c4611a + # via -r requirements-dev.in +pip-requirements-parser==32.0.1 \ + --hash=sha256:4659bc2a667783e7a15d190f6fccf8b2486685b6dba4c19c3876314769c57526 + # via pip-audit +platformdirs==4.14.0 \ + --hash=sha256:1dadfc59a8a5d7565b3d9270ae8fa71c065595352c4277b41c11ee6c222c4b91 + # via pip-audit +pluggy==1.7.0 \ + --hash=sha256:7dd7b0d8832ba3cb632c306926ded123429211b83641b35dc5c41ad2d34f9bec + # via pytest +py-serializable==2.1.0 \ + --hash=sha256:b56d5d686b5a03ba4f4db5e769dc32336e142fc3bd4d68a8c25579ebb0a67304 + # via cyclonedx-python-lib +pygments==2.21.0 \ + --hash=sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9 + # via + # pytest + # rich +pyparsing==3.3.3 \ + --hash=sha256:ece8c00a69cf01b45d0b1dedabb469c90d8caf996d4fda40f147627a122849a4 + # via pip-requirements-parser +pytest==9.1.1 \ + --hash=sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c + # via -r requirements-dev.in +pyyaml==6.0.3 \ + --hash=sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28 \ + --hash=sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7 \ + --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \ + --hash=sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc \ + --hash=sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5 + # via -r requirements-dev.in +referencing==0.37.0 \ + --hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 + # via + # jsonschema + # jsonschema-specifications +requests==2.34.2 \ + --hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 + # via + # cachecontrol + # pip-audit +rich==15.0.0 \ + --hash=sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb + # via pip-audit +rpds-py==2026.9.1 \ + --hash=sha256:2693b2728bbcc48d09a981a356954b0c47c53ff25b545856f28a889ea619f69a \ + --hash=sha256:07deecbfce94c78473018bc7d10b337cc651d12df87a1eb2cb3e4024bc9c33d0 \ + --hash=sha256:0da298fb372dc192610a4b9ecbc68a0cd8b675bbbd1fc519d01b41cfd658333e \ + --hash=sha256:addeda51556dac7c1a2f14cda62db8b621cd12afba3091d03a96c72932387eab \ + --hash=sha256:eac2f5dbafd585dfe31f86a23ebf0d3ba480a9d49ebc87947267b5608d4ea0cd + # via + # jsonschema + # referencing +ruff==0.17.0 \ + --hash=sha256:13ee90156522998c3037059d8f66885c8adeeaf7643bdce2caceee196ecd23e0 \ + --hash=sha256:bc73e7c133e82d55b5f15897b2a442d72c0cb4a0c886c46801ce3c247150b60c + # via -r requirements-dev.in +sortedcontainers==2.4.0 \ + --hash=sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0 + # via cyclonedx-python-lib +tomli==2.5.0 \ + --hash=sha256:bf0b5e8e0f68ebb494356e577c06c139161efd8d3b9050f93b39b7c26cc54ff0 \ + --hash=sha256:6e95c7614e705bfe2b04b27aa124adec59752d15813df37e2156747cab3a006b \ + --hash=sha256:22185fad8a1e622f064e78008018a0dd3323550dcb479cb7a1d296888d74024f \ + --hash=sha256:32a7b79ac57a2e83670ce329ccf675798bc5a2094783a63676866b70503f2e2b \ + --hash=sha256:6cf74416bdc94ae458b14e37286c1073081850ac8459a00d0c5efef5d44294c6 \ + --hash=sha256:7ac2027d37c3afbdf4bdd377f2676f6f1d2122a5be1f1137b49dced590b37e75 + # via pip-audit +tomli-w==1.2.0 \ + --hash=sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90 + # via pip-audit +typing-extensions==4.16.0 ; python_full_version < '3.13' \ + --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 + # via + # cyclonedx-python-lib + # referencing +urllib3==2.8.0 \ + --hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3 + # via requests diff --git a/scripts/run-kit-tests.py b/scripts/run-kit-tests.py new file mode 100644 index 0000000..6b49330 --- /dev/null +++ b/scripts/run-kit-tests.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +"""Dispatch a named root kit's tests; sandbox/live verification is always disabled.""" + +from __future__ import annotations + +import argparse +import os +import shutil +import subprocess +import sys +from pathlib import Path + +KIT_NAMES = ("opencode-go-provider", "pi-coding-agent", "first-mate-skill", "claude-code") + + +def test_commands(root: Path, name: str, *, install: bool = False) -> tuple[Path, list[list[str]]]: + if name not in KIT_NAMES: + raise ValueError(f"unknown kit: {name}") + kit = root / name + if not kit.is_dir() or kit.is_symlink() or not (kit / "spec.yaml").is_file(): + raise ValueError(f"kit must be an actual root directory with spec.yaml: {kit}") + if name in ("opencode-go-provider", "pi-coding-agent"): + commands = [["npm", "test"]] + if install: + commands.insert(0, ["npm", "ci", "--ignore-scripts", "--no-audit", "--no-fund"]) + if name == "pi-coding-agent": + commands.append(["bash", "scripts/verify"]) + elif name == "first-mate-skill": + commands = [["bash", "scripts/verify"]] + else: + # The kit owns its isolated, hash-locked runtime test environment. + commands = [[sys.executable, "scripts/test"]] + return kit, commands + + +def run_tests(root: Path, name: str, *, install: bool = False) -> None: + kit, commands = test_commands(root, name, install=install) + environment = dict(os.environ, RUN_ACQ="0", RUN_LIVE="0", RUN_CLAUDE_LIVE="0", PYTHON_BIN=sys.executable) + for command in commands: + executable = shutil.which(command[0]) + if executable is None: + raise ValueError(f"required test executable not found: {command[0]}") + subprocess.run([executable, *command[1:]], cwd=kit, env=environment, check=True) + + +def main(argv: list[str] | None = None) -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("kit", choices=(*KIT_NAMES, "all")) + parser.add_argument("--root", type=Path, default=Path(__file__).resolve().parents[1]) + parser.add_argument( + "--install", action="store_true", help="install Node dependencies with lifecycle scripts disabled" + ) + args = parser.parse_args(argv) + try: + for name in KIT_NAMES if args.kit == "all" else (args.kit,): + run_tests(args.root.resolve(), name, install=args.install) + except (ValueError, OSError, subprocess.CalledProcessError) as error: + print(f"kit tests failed: {error}", file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/tests/test_tooling.py b/scripts/tests/test_tooling.py new file mode 100644 index 0000000..f602655 --- /dev/null +++ b/scripts/tests/test_tooling.py @@ -0,0 +1,227 @@ +"""Regression tests for shared dispatch, staging, and fail-closed validation.""" + +import importlib.util +import json +import runpy +import subprocess +import sys +from pathlib import Path + +import pytest +import yaml + +ROOT = Path(__file__).resolve().parents[2] + + +def load_script(name): + spec = importlib.util.spec_from_file_location(name.replace("-", "_"), ROOT / "scripts" / f"{name}.py") + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +validator = load_script("validate-kits") +runner = load_script("run-kit-tests") + + +@pytest.fixture +def kits(tmp_path): + root = tmp_path / "repo" + root.mkdir() + for name in runner.KIT_NAMES: + kit = root / name + kit.mkdir() + (kit / "spec.yaml").write_text(yaml.safe_dump({"name": name}), encoding="utf-8") + (kit / "files/.hidden").mkdir(parents=True) + (kit / "files/.hidden/payload").write_text("payload", encoding="utf-8") + return root + + +def test_stages_every_root_kit_and_hidden_payload(kits, tmp_path): + extra = kits / "another-kit" + extra.mkdir() + (extra / "spec.yaml").write_text("name: another-kit\n", encoding="utf-8") + patterns = tmp_path / "patterns" + (patterns / "schemas").mkdir(parents=True) + (patterns / "schemas/kit-hybrid-v1.schema.json").write_text("{}", encoding="utf-8") + work = tmp_path / "stage" + validator.stage_kits(kits, patterns, work) + staged = work / "integrations/isolation/acq-kits" + registry = yaml.safe_load((staged / "kits.yaml").read_text()) + assert set(registry["kits"]) == {*runner.KIT_NAMES, "another-kit"} + assert (staged / "claude-code/files/.hidden/payload").read_text() == "payload" + + +def test_missing_required_kit_fails(kits): + (kits / "claude-code/spec.yaml").unlink() + with pytest.raises(ValueError, match="claude-code"): + validator.discover_kits(kits) + + +def test_broken_local_doc_link_fails(kits): + kit = kits / "claude-code" + (kit / "README.md").write_text("[Missing](missing.md)\n", encoding="utf-8") + with pytest.raises(ValueError, match="broken local link"): + validator.validate_local_docs_and_modes(kit) + + +def test_provider_normalizer_requires_executable_mode(kits): + kit = kits / "opencode-go-provider" + (kit / "provider-input.json").write_text('{"normalizerPath":"normalizer"}', encoding="utf-8") + normalizer = kit / "normalizer" + normalizer.write_text("test", encoding="utf-8") + normalizer.chmod(0o644) + with pytest.raises(ValueError, match="executable on disk"): + validator.validate_local_docs_and_modes(kit) + normalizer.chmod(0o755) + validator.validate_local_docs_and_modes(kit) + + +def test_spec_name_mismatch_fails(kits, tmp_path): + (kits / "claude-code/spec.yaml").write_text("name: wrong\n", encoding="utf-8") + patterns = tmp_path / "patterns" + (patterns / "schemas").mkdir(parents=True) + (patterns / "schemas/kit-hybrid-v1.schema.json").write_text("{}", encoding="utf-8") + with pytest.raises(ValueError, match="spec name"): + validator.stage_kits(kits, patterns, tmp_path / "stage") + + +@pytest.mark.parametrize("name", runner.KIT_NAMES) +def test_dispatch_commands(kits, name): + cwd, commands = runner.test_commands(kits, name, install=True) + assert cwd == kits / name + if name in ("opencode-go-provider", "pi-coding-agent"): + assert commands[:2] == [["npm", "ci", "--ignore-scripts", "--no-audit", "--no-fund"], ["npm", "test"]] + elif name == "claude-code": + assert commands == [[sys.executable, "scripts/test"]] + else: + assert commands == [["bash", "scripts/verify"]] + + +def test_ci_matrix_and_dispatch_cover_every_repository_kit(): + actual = {kit.name for kit in validator.discover_kits(ROOT)} + workflow = yaml.safe_load((ROOT / ".github/workflows/ci.yml").read_text(encoding="utf-8")) + matrix = workflow["jobs"]["kits"]["strategy"]["matrix"] + assert set(matrix["kit"]) == set(runner.KIT_NAMES) == actual + assert actual == validator.REQUIRED_KITS + assert {"kit": "claude-code", "python": "3.12"} in matrix["include"] + + +@pytest.mark.parametrize("name", ["../claude-code", "/outside-project", "unknown", "claude-code;echo bad"]) +def test_rejects_unrecognized_kit(kits, name): + with pytest.raises(ValueError, match="unknown kit"): + runner.test_commands(kits, name) + + +def test_rejects_symlinked_kit(kits, tmp_path): + target = tmp_path / "linked" + (kits / "claude-code").rename(target) + (kits / "claude-code").symlink_to(target, target_is_directory=True) + with pytest.raises(ValueError, match="actual root directory"): + runner.test_commands(kits, "claude-code") + + +def test_live_checks_disabled_and_failure_propagates(kits, monkeypatch): + monkeypatch.setenv("RUN_ACQ", "1") + monkeypatch.setenv("RUN_CLAUDE_LIVE", "1") + calls = [] + monkeypatch.setattr(runner.shutil, "which", lambda name: f"/usr/bin/{name}") + + def failed(command, **kwargs): + calls.append(kwargs) + raise subprocess.CalledProcessError(7, command) + + monkeypatch.setattr(runner.subprocess, "run", failed) + assert runner.main(["pi-coding-agent", "--root", str(kits)]) == 1 + assert calls[0]["env"]["RUN_ACQ"] == "0" + assert calls[0]["env"]["RUN_LIVE"] == "0" + assert calls[0]["env"]["RUN_CLAUDE_LIVE"] == "0" + assert calls[0]["check"] is True + + +def test_claude_test_bootstrap_uses_requested_python_and_locked_tools(monkeypatch): + monkeypatch.delenv("RUN_CLAUDE_LIVE", raising=False) + monkeypatch.setattr("shutil.which", lambda name: "/usr/bin/uv" if name == "uv" else None) + commands = [] + monkeypatch.setattr( + subprocess, "run", lambda command, **kwargs: commands.append(command) or subprocess.CompletedProcess(command, 0) + ) + with pytest.raises(SystemExit) as result: + runpy.run_path(str(ROOT / "claude-code/scripts/test"), run_name="__main__") + assert result.value.code == 0 + assert commands[0][commands[0].index("--python") + 1] == sys.executable + assert all("--require-hashes" in command for command in commands[1:3]) + assert commands[2][-1].endswith("tests/requirements.lock") + + +def test_missing_patterns_fails_without_fetch(kits, capsys): + assert validator.main(["--root", str(kits)]) == 1 + assert "kit validation failed" in capsys.readouterr().err + + +def test_wrong_patterns_pin_fails(kits, monkeypatch): + monkeypatch.setattr( + validator.subprocess, "run", lambda *args, **kwargs: subprocess.CompletedProcess(args, 0, "wrong\n") + ) + with pytest.raises(ValueError, match="must be pinned"): + validator.validate(kits, kits / ".patterns") + + +@pytest.mark.parametrize("missing", ["validator", "schema", "provider"]) +def test_missing_upstream_inputs_fail(kits, tmp_path, monkeypatch, missing): + patterns = tmp_path / "patterns" + paths = { + "validator": "integrations/isolation/acq-kits/validate-kits.py", + "schema": "schemas/kit-hybrid-v1.schema.json", + "provider": "scripts/validate_provider_input_contract.py", + "bindings": "integrations/isolation/schemas/provider-credential-bindings.json", + } + for key, path in paths.items(): + if key != missing: + target = patterns / path + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text('{"providers": {}}', encoding="utf-8") + monkeypatch.setattr( + validator.subprocess, + "run", + lambda *args, **kwargs: subprocess.CompletedProcess(args, 0, validator.PATTERNS_REF + "\n"), + ) + with pytest.raises(ValueError, match="required validation input missing"): + validator.validate(kits, patterns) + + +def test_provider_binding_patch_is_local_and_upstream_validation_is_strict(kits, tmp_path, monkeypatch): + patterns = tmp_path / "patterns" + inputs = [ + "integrations/isolation/acq-kits/validate-kits.py", + "scripts/validate_provider_input_contract.py", + "schemas/kit-hybrid-v1.schema.json", + ] + for path in inputs: + target = patterns / path + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text("{}", encoding="utf-8") + binding = patterns / "integrations/isolation/schemas/provider-credential-bindings.json" + binding.parent.mkdir(parents=True) + binding.write_text('{"providers": {"usai": "USAI_API_KEY"}}', encoding="utf-8") + (kits / "opencode-go-provider/provider-input.json").write_text('{"normalizerPath":"normalizer"}', encoding="utf-8") + normalizer = kits / "opencode-go-provider/normalizer" + normalizer.write_text("test", encoding="utf-8") + normalizer.chmod(0o755) + calls = [] + + def capture(command, **kwargs): + calls.append(command) + if "--credential-bindings" in command: + patched = Path(command[command.index("--credential-bindings") + 1]) + assert json.loads(patched.read_text())["providers"] == { + "usai": "USAI_API_KEY", + "opencode-go": "OPENCODE_GO_API_KEY", + } + return subprocess.CompletedProcess(command, 0, validator.PATTERNS_REF + "\n") + + monkeypatch.setattr(validator.subprocess, "run", capture) + validator.validate(kits, patterns) + assert "--strict" in calls[1] + assert calls[2][-2:] == ["--bundle", str(kits / "opencode-go-provider/provider-input.json")] + assert json.loads(binding.read_text()) == {"providers": {"usai": "USAI_API_KEY"}} diff --git a/scripts/validate-kits.py b/scripts/validate-kits.py new file mode 100644 index 0000000..3c25b7c --- /dev/null +++ b/scripts/validate-kits.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 +"""Validate every root kit using the locally checked-out, pinned Patterns release. + +No network access: provision .patterns separately. Synthetic layout adapts this +repository's root directories to the upstream validator without changing specs. +""" + +from __future__ import annotations + +import argparse +import json +import re +import shutil +import subprocess +import sys +import tempfile +from pathlib import Path + +import yaml + +PATTERNS_REF = "a290d5d80737fc739e7ec139da0eeaf438631631" +REQUIRED_KITS = {"opencode-go-provider", "pi-coding-agent", "first-mate-skill", "claude-code"} + + +def require_file(path: Path) -> Path: + if not path.is_file(): + raise ValueError(f"required validation input missing: {path}") + return path + + +def discover_kits(root: Path) -> list[Path]: + kits = sorted(path for path in root.iterdir() if path.is_dir() and (path / "spec.yaml").is_file()) + missing = REQUIRED_KITS - {path.name for path in kits} + if missing: + raise ValueError(f"required kit directories missing: {', '.join(sorted(missing))}") + return kits + + +def validate_local_docs_and_modes(kit: Path) -> None: + for document in kit.rglob("*.md"): + if any(part in {"node_modules", "__pycache__", ".pytest_cache"} for part in document.parts): + continue + for target in re.findall(r"\]\(([^)\s]+)\)", document.read_text(encoding="utf-8")): + if "://" in target or target.startswith(("#", "mailto:")): + continue + if not (document.parent / target.split("#", 1)[0]).exists(): + raise ValueError(f"{document}: broken local link {target}") + # Check source permissions as well as declared guest permissions. Modes on + # host-side normalizers matter before kit materialization begins. + manifest = kit / "provider-input.json" + if manifest.exists(): + bundle = json.loads(manifest.read_text(encoding="utf-8")) + if not isinstance(bundle, dict) or not isinstance(bundle.get("normalizerPath"), str): + raise ValueError(f"{kit.name}: provider manifest requires normalizerPath") + normalizer = kit / bundle["normalizerPath"] + if not normalizer.is_file() or not normalizer.stat().st_mode & 0o111: + raise ValueError(f"{kit.name}: normalizer must be executable on disk") + spec = yaml.safe_load((kit / "spec.yaml").read_text(encoding="utf-8")) + if isinstance(spec, dict): + for entry in spec.get("files", []): + if not isinstance(entry, dict): + continue + try: + executable = int(str(entry.get("mode", "0")), 8) & 0o111 + except ValueError: + raise ValueError(f"{kit.name}: invalid payload mode") from None + if "source" in entry and executable: + source = kit / entry["source"] + if source.is_file() and not source.stat().st_mode & 0o111: + raise ValueError(f"{kit.name}: executable payload lacks host execute permission: {entry['source']}") + + +def stage_kits(root: Path, patterns: Path, work: Path) -> Path: + kits_dir = work / "integrations/isolation/acq-kits" + kits_dir.mkdir(parents=True) + (work / "schemas").mkdir() + shutil.copy2(require_file(patterns / "schemas/kit-hybrid-v1.schema.json"), work / "schemas") + registry = {} + for kit in discover_kits(root): + validate_local_docs_and_modes(kit) + spec = yaml.safe_load((kit / "spec.yaml").read_text(encoding="utf-8")) + if not isinstance(spec, dict) or spec.get("name") != kit.name: + raise ValueError(f"{kit.name}: spec name must match its root directory") + # Symlinks retain all payload paths, including hidden files, with no copies + # of node_modules/ or virtual environments into the temporary tree. + (kits_dir / kit.name).symlink_to(kit.resolve(), target_is_directory=True) + registry[kit.name] = {"backends": ["sbx", "msb"], "parity": "CI validation entry."} + (kits_dir / "kits.yaml").write_text( + yaml.safe_dump({"schemaVersion": "acq-kits-registry/v1", "kits": registry}), encoding="utf-8" + ) + return work + + +def validate(root: Path, patterns: Path) -> None: + git = shutil.which("git") + if git is None: + raise ValueError("git is required to verify the Patterns checkout") + actual = subprocess.run( + [git, "-C", str(patterns), "rev-parse", "HEAD"], check=True, capture_output=True, text=True + ).stdout.strip() + if actual != PATTERNS_REF: + raise ValueError(f"Patterns checkout must be pinned to {PATTERNS_REF}, got {actual}") + validator = require_file(patterns / "integrations/isolation/acq-kits/validate-kits.py") + provider_validator = require_file(patterns / "scripts/validate_provider_input_contract.py") + schema_dir = patterns / "integrations/isolation/schemas" + bindings_source = require_file(schema_dir / "provider-credential-bindings.json") + with tempfile.TemporaryDirectory(prefix="kit-validation-") as temporary: + work = Path(temporary) + stage_kits(root, patterns, work) + subprocess.run([sys.executable, str(validator), "--root", str(work), "--strict"], check=True) + # Preserve the preview provider's binding patch, not a relaxed validator. + bindings = json.loads(bindings_source.read_text(encoding="utf-8")) + bindings["providers"]["opencode-go"] = "OPENCODE_GO_API_KEY" + bindings_path = work / "provider-credential-bindings.json" + bindings_path.write_text(json.dumps(bindings, indent=2) + "\n", encoding="utf-8") + bundles = [ + kit / "provider-input.json" for kit in discover_kits(root) if (kit / "provider-input.json").is_file() + ] + if not bundles: + raise ValueError("no provider input bundles found") + command = [ + sys.executable, + str(provider_validator), + "--schema-dir", + str(schema_dir), + "--credential-bindings", + str(bindings_path), + ] + for bundle in bundles: + command.extend(["--bundle", str(bundle)]) + subprocess.run(command, check=True) + + +def main(argv: list[str] | None = None) -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--root", type=Path, default=Path(__file__).resolve().parents[1]) + parser.add_argument("--patterns", type=Path, help="local pinned checkout (default: ROOT/.patterns)") + args = parser.parse_args(argv) + root = args.root.resolve() + try: + validate(root, args.patterns.resolve() if args.patterns else root / ".patterns") + except (ValueError, OSError, subprocess.CalledProcessError, yaml.YAMLError) as error: + print(f"kit validation failed: {error}", file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) From a0743cd51da8ddbe91d806c4fad4329a4c5bbe9b Mon Sep 17 00:00:00 2001 From: Bret Mogilefsky Date: Fri, 30 Oct 2026 21:20:46 -0700 Subject: [PATCH 2/3] fix(kits): record executable script modes --- claude-code/files/home/.local/bin/claude | 0 claude-code/files/home/claude-code/install.py | 0 claude-code/files/home/claude-code/launch.py | 0 claude-code/scripts/test | 0 claude-code/scripts/verify | 0 scripts/run-kit-tests.py | 0 scripts/validate-kits.py | 0 7 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 claude-code/files/home/.local/bin/claude mode change 100644 => 100755 claude-code/files/home/claude-code/install.py mode change 100644 => 100755 claude-code/files/home/claude-code/launch.py mode change 100644 => 100755 claude-code/scripts/test mode change 100644 => 100755 claude-code/scripts/verify mode change 100644 => 100755 scripts/run-kit-tests.py mode change 100644 => 100755 scripts/validate-kits.py diff --git a/claude-code/files/home/.local/bin/claude b/claude-code/files/home/.local/bin/claude old mode 100644 new mode 100755 diff --git a/claude-code/files/home/claude-code/install.py b/claude-code/files/home/claude-code/install.py old mode 100644 new mode 100755 diff --git a/claude-code/files/home/claude-code/launch.py b/claude-code/files/home/claude-code/launch.py old mode 100644 new mode 100755 diff --git a/claude-code/scripts/test b/claude-code/scripts/test old mode 100644 new mode 100755 diff --git a/claude-code/scripts/verify b/claude-code/scripts/verify old mode 100644 new mode 100755 diff --git a/scripts/run-kit-tests.py b/scripts/run-kit-tests.py old mode 100644 new mode 100755 diff --git a/scripts/validate-kits.py b/scripts/validate-kits.py old mode 100644 new mode 100755 From 185ba1f954994d1a9426a72dabba0c6c0168c97d Mon Sep 17 00:00:00 2001 From: Bret Mogilefsky Date: Fri, 30 Oct 2026 21:26:12 -0700 Subject: [PATCH 3/3] fix(ci): validate Git-recorded executable modes --- README.md | 12 +++++++++ scripts/tests/test_tooling.py | 37 +++++++++++++++++++++++++ scripts/validate-kits.py | 51 +++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) diff --git a/README.md b/README.md index dc1a872..e56694c 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,18 @@ first-mate-skill/ skill kit New kits follow the same directory contract and get a row in the table above. +### Executable scripts on shared mounts + +Shared host/microVM mounts can report filesystem permissions differently from +Git's recorded modes. Validation checks both declared executable payloads and +Git index entries for executable scripts, including normalizers and test/verify +entrypoints. An executable script must be staged with mode `100755`; checking +only `test -x` locally does not prove a fresh CI checkout will be executable. +For an intended executable, stage it and run +`git update-index --chmod=+x