diff --git a/.github/actionlint.yml b/.github/actionlint.yml index 138f61b35..feb35f292 100644 --- a/.github/actionlint.yml +++ b/.github/actionlint.yml @@ -6,4 +6,4 @@ paths: .github/actions/setup-uv-env/action.yml: ignore: - - '.*is not defined in object type.*' \ No newline at end of file + - .*is not defined in object type.* diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index d913a282d..cdea36e99 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -5,24 +5,23 @@ name: Setup Mise Environment description: Complete Python development environment setup with mise and UV caching - inputs: python-version: description: Python version to install required: false - default: '3.12' + default: "3.12" fetch-depth: description: Git fetch depth for checkout required: false - default: '1' + default: "1" skip-checkout: description: Skip checkout step (if already checked out by calling workflow) required: false - default: 'false' + default: "false" github-token: description: GitHub token for mise installation (to avoid rate limits) required: false - default: '' + default: "" profile: description: Task profile to use for mise setup one of 'minimal', 'reviewer', 'dev' required: true diff --git a/.github/actions/setup-python-env/action.yml b/.github/actions/setup-python-env/action.yml index 8ad9b8db6..5baece786 100644 --- a/.github/actions/setup-python-env/action.yml +++ b/.github/actions/setup-python-env/action.yml @@ -5,20 +5,19 @@ name: Setup Python Environment description: Minimal Python environment setup - inputs: python-version: description: Python version to install required: false - default: '3.12' + default: "3.12" fetch-depth: description: Git fetch depth for checkout required: false - default: '0' + default: "0" skip-checkout: description: Skip checkout step (if already checked out by calling workflow) required: false - default: 'false' + default: "false" github-token: description: GitHub token for mise installation (to avoid rate limits) required: false @@ -40,11 +39,9 @@ runs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 with: fetch-depth: ${{ inputs.fetch-depth }} - - name: Free up disk space shell: bash run: ./scripts/dev-env/ci-free-disk-space.sh - - name: Set up Python ${{ inputs.python-version }} uses: actions/setup-python@9b03c627221f32cb88b299427119da30671cf9cc # v5 with: diff --git a/.github/actions/setup-uv-env/action.yml b/.github/actions/setup-uv-env/action.yml index 077e44b26..f795a7a5f 100644 --- a/.github/actions/setup-uv-env/action.yml +++ b/.github/actions/setup-uv-env/action.yml @@ -5,24 +5,23 @@ name: Setup UV Environment description: Minimal UV environment setup with caching - inputs: fetch-depth: description: Git fetch depth for checkout required: false - default: '1' + default: "1" skip-checkout: description: Skip checkout step (if already checked out by calling workflow) required: false - default: 'false' + default: "false" github-token: description: GitHub token for mise installation (to avoid rate limits) required: false - default: '' + default: "" python-version: description: Python version to install required: false - default: '3.12' + default: "3.12" activate-venv: description: Whether to activate the Python virtual environment required: false @@ -44,11 +43,10 @@ runs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 with: fetch-depth: ${{ inputs.fetch-depth }} - - name: Setup UV and build uses: astral-sh/setup-uv@9c12baee9699f1b4f4318d7175fab8635c2b8e45 with: - resolution-strategy: "highest" + resolution-strategy: highest python-version: ${{ inputs.python-version }} activate-environment: ${{ inputs.activate-venv }} github-token: ${{ inputs.github-token }} @@ -56,7 +54,7 @@ runs: cache-dependency-glob: | **/pyproject.toml **/uv.lock - cache-suffix: "highest" + cache-suffix: highest restore-cache: "true" save-cache: "true" prune-cache: "true" diff --git a/.github/workflows/_reusable-build.yml b/.github/workflows/_reusable-build.yml index b59641359..568ae6dbb 100644 --- a/.github/workflows/_reusable-build.yml +++ b/.github/workflows/_reusable-build.yml @@ -4,31 +4,29 @@ # SPDX-License-Identifier: MIT OR Apache-2.0 name: Reusable Build Workflow - on: workflow_call: inputs: artifact-name: - description: "Name for the build artifacts" + description: Name for the build artifacts required: false type: string - default: "python-package-distributions" + default: python-package-distributions python-version: - description: "Python version for building" + description: Python version for building required: false type: string default: "3.12" upload-artifacts: - description: "Upload build artifacts" + description: Upload build artifacts required: false type: boolean default: true clean-build: - description: "Run clean build (uv build --clear)" + description: Run clean build (uv build --clear) required: false type: boolean default: false - jobs: build: name: Build Package @@ -62,21 +60,13 @@ jobs: else "$UV_PATH" build fi - - name: Check build artifacts - run: | - ls -la dist/ - echo "Built packages:" - for file in dist/*; do - echo "📦 $(basename "$file")" - done - + run: "ls -la dist/\necho \"Built packages:\"\nfor file in dist/*; do\n echo \"\U0001F4E6 $(basename \"$file\")\"\ndone\n" - name: Verify package integrity with twine env: UVX_PATH: ${{ steps.setup-uv.outputs.uvx-path }} run: | "$UVX_PATH" twine check dist/* - - name: Upload build artifacts if: inputs.upload-artifacts uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 diff --git a/.github/workflows/_reusable-lint.yml b/.github/workflows/_reusable-lint.yml index e4a061416..1ddeb2c51 100644 --- a/.github/workflows/_reusable-lint.yml +++ b/.github/workflows/_reusable-lint.yml @@ -6,17 +6,16 @@ name: Reusable Lint Workflow permissions: contents: read - on: workflow_call: inputs: python-version: - description: "Python version for linting" + description: Python version for linting required: false type: string default: "3.12" run-format-check: - description: "Run format/license checks" + description: Run format/license checks required: false type: boolean default: true @@ -31,7 +30,6 @@ jobs: permissions: contents: read name: Lint and Format - runs-on: ubuntu-latest env: MISE_PYTHON_VERSION: ${{ inputs.python-version }} UV_PYTHON: ${{ inputs.python-version }} @@ -40,11 +38,10 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 with: fetch-depth: 1 - - name: Setup Python environment uses: ./.github/actions/setup-mise-env with: - python-version: ${{ inputs.python-version }} + python-version: ${{ env.python-version }} github-token: ${{ secrets.GITHUB_TOKEN }} profile: "${{ env.PROFILE }}" skip-checkout: true @@ -55,7 +52,6 @@ jobs: MISE_PYTHON_VERSION: ${{ steps.mise-setup.outputs.MISE_PYTHON_VERSION }} run: mise run lint || echo "::warning::Lint checks failed but allowing workflow to continue" continue-on-error: true - - name: Check formatting and licenses if: inputs.run-format-check env: diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index ea90d0176..fb353a0af 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -6,27 +6,26 @@ name: Reusable Test Workflow permissions: contents: read - on: workflow_call: inputs: python-versions: - description: 'JSON array of Python versions to test (e.g., ["3.12", "3.13"]). Experimental versions (3.13t, 3.14t) are always included via matrix.include.' + description: JSON array of Python versions to test (e.g., ["3.12", "3.13"]). Experimental versions (3.13t, 3.14t) are always included via matrix.include. required: false type: string default: '["3.12", "3.13", "3.14"]' test-markers: - description: "Pytest markers for test filtering" + description: Pytest markers for test filtering required: false type: string - default: "not docker and not qdrant and not dev_only and not skip_ci and not network and not external_api" + default: not docker and not qdrant and not dev_only and not skip_ci and not network and not external_api upload-coverage: - description: "Upload coverage to Codecov" + description: Upload coverage to Codecov required: false type: boolean default: true run-quality-checks: - description: "Run quality checks before tests" + description: Run quality checks before tests required: false type: boolean default: true @@ -61,12 +60,13 @@ jobs: fail-fast: false matrix: python-version: ${{ fromJSON(inputs.python-versions) }} - experimental: [false] + experimental: + - false include: # Experimental free-threaded Python versions (no-GIL) - - python-version: "3.13t" + - python-version: 3.13t experimental: true - - python-version: "3.14t" + - python-version: 3.14t experimental: true env: MISE_PYTHON_VERSION: ${{ matrix.python-version }} @@ -82,7 +82,7 @@ jobs: with: python-version: ${{ matrix.python-version }} github-token: ${{ secrets.GITHUB_TOKEN }} - profile: "dev" + profile: dev skip-checkout: true mise-debug: true id: setup-mise @@ -107,7 +107,6 @@ jobs: files: ./coverage.xml fail_ci_if_error: false token: ${{ secrets.CODECOV_TOKEN }} - - name: Upload test results uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 if: always() diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 055f48130..ad67e3bad 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -4,23 +4,20 @@ # SPDX-License-Identifier: MIT OR Apache-2.0 name: Generate Changelog - on: workflow_dispatch: inputs: tag: - description: "Generate changelog for specific tag (e.g., v0.1.0). Leave empty for unreleased changes." + description: Generate changelog for specific tag (e.g., v0.1.0). Leave empty for unreleased changes. required: false type: string commit: - description: "Commit and push the generated CHANGELOG.md" + description: Commit and push the generated CHANGELOG.md required: false type: boolean default: false - permissions: contents: write - jobs: generate-changelog: name: Generate Changelog @@ -30,12 +27,10 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 with: fetch-depth: 0 # Fetch all history for changelog generation - - name: Install git-cliff uses: taiki-e/install-action@331a600f1b10a3fed8dc56f925012bede91ae51f with: tool: git-cliff@2.10.0 - - name: Generate changelog id: changelog run: | @@ -49,12 +44,10 @@ jobs: echo "Generating changelog for unreleased changes" git-cliff --unreleased --prepend --output CHANGELOG.md fi - - name: Display changelog run: | echo "Generated CHANGELOG.md:" cat CHANGELOG.md - - name: Commit and push if: github.event.inputs.commit == 'true' run: | @@ -71,7 +64,6 @@ jobs: fi git push fi - - name: Upload changelog artifact uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2cdf8834..d0a9a34f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,42 +6,39 @@ name: CI permissions: contents: read - on: push: branches: - main - staging paths: - - "src/**" - - "tests/**" - - "pyproject.toml" - - "uv.lock" - - "**/mise.*.toml" - - "**/mise.toml" - - ".github/workflows/ci.yml" - - ".github/workflows/_reusable-*.yml" - - ".github/actions/**" + - src/** + - tests/** + - pyproject.toml + - uv.lock + - '**/mise.*.toml' + - '**/mise.toml' + - .github/workflows/ci.yml + - .github/workflows/_reusable-*.yml + - .github/actions/** pull_request: branches: - main - staging paths: - - "src/**" - - "tests/**" - - "pyproject.toml" - - "uv.lock" - - "mise.toml" - - "mise.ci.toml" - - ".github/workflows/ci.yml" - - ".github/workflows/_reusable-*.yml" - - ".github/actions/**" + - src/** + - tests/** + - pyproject.toml + - uv.lock + - mise.toml + - mise.ci.toml + - .github/workflows/ci.yml + - .github/workflows/_reusable-*.yml + - .github/actions/** workflow_dispatch: - concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true - jobs: test: name: Test @@ -60,7 +57,6 @@ jobs: name: Lint uses: ./.github/workflows/_reusable-lint.yml secrets: inherit - build: name: Build needs: diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 291e5c30b..97bc38c29 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -5,7 +5,6 @@ # ! GitHub Action to check CLA signatures for Knitli repositories # ! This action is triggered on issue comments and pull request events. name: CLA Assistant - on: issue_comment: types: @@ -20,11 +19,10 @@ permissions: contents: read pull-requests: write statuses: write - jobs: cla-check: uses: knitli/.github/.github/workflows/cla-check.yml@main with: - repo_name: "codeweaver" - cla_document_url: "https://github.com/knitli/codeweaver/blob/main/CONTRIBUTORS_LICENSE_AGREEMENT.md" + repo_name: codeweaver + cla_document_url: https://github.com/knitli/codeweaver/blob/main/CONTRIBUTORS_LICENSE_AGREEMENT.md secrets: inherit diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 05db17a6d..643bf81f3 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -59,7 +59,7 @@ jobs: with: python-version: "3.13" github-token: ${{ secrets.GITHUB_TOKEN }} - profile: "reviewer" + profile: reviewer skip-checkout: "true" - name: PR Review @@ -68,8 +68,8 @@ jobs: with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }} - allowed_non_write_users: "Copilot" - trigger_phrase: "@claude" + allowed_non_write_users: Copilot + trigger_phrase: '@claude' assignee_trigger: claude label_trigger: claude base_branch: main @@ -95,7 +95,7 @@ jobs: with: python-version: "3.13" github-token: ${{ secrets.GITHUB_TOKEN }} - profile: "dev" + profile: dev skip-checkout: "true" - name: Issue Opened if: github.event_name == 'issues' && github.event.action == 'opened' @@ -103,7 +103,7 @@ jobs: with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }} - trigger_phrase: "@claude" + trigger_phrase: '@claude' assignee_trigger: claude label_trigger: claude track_progress: true @@ -130,7 +130,7 @@ jobs: with: python-version: "3.13" github-token: ${{ secrets.GITHUB_TOKEN }} - profile: "minimal" + profile: minimal skip-checkout: "true" - name: PR Review Comment if: github.event_name == 'pull_request_review_comment' @@ -138,7 +138,7 @@ jobs: with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }} - trigger_phrase: "@claude" + trigger_phrase: '@claude' assignee_trigger: claude label_trigger: claude use_commit_signing: true @@ -166,7 +166,7 @@ jobs: with: python-version: "3.13" github-token: ${{ secrets.GITHUB_TOKEN }} - profile: "dev" + profile: dev skip-checkout: "true" - name: Issue Assigned or Labeled Claude if: | @@ -175,7 +175,7 @@ jobs: with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }} - trigger_phrase: "@claude" + trigger_phrase: '@claude' assignee_trigger: claude label_trigger: claude track_progress: true diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 3e96fff14..a5e92aa3e 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -18,6 +18,8 @@ on: jobs: # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot. copilot-setup-steps: + outputs: + MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} env: CODEWEAVER_VECTOR_STORE_URL: ${{ secrets.CODEWEAVER_VECTOR_STORE_URL }} QDRANT__SERVICE__API_KEY: ${{ secrets.QDRANT__SERVICE__API_KEY }} @@ -49,7 +51,7 @@ jobs: with: python-version: "3.13" github-token: ${{ secrets.GITHUB_TOKEN }} - profile: "dev" + profile: dev skip-checkout: "true" - name: Make scripts executable diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index b8b26fb91..6300d4d2d 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -34,7 +34,7 @@ on: workflow_dispatch: inputs: update_description_only: - description: "Only update Docker Hub description (no build)" + description: Only update Docker Hub description (no build) required: false type: boolean default: false @@ -61,10 +61,9 @@ jobs: password: ${{ secrets.DOCKERHUB_TOKEN }} repository: ${{ env.IMAGE_NAME }} readme-filepath: ./DOCKER.md - short-description: "The missing abstraction layer between AI and your code - deep, structural understanding for better AI results" + short-description: The missing abstraction layer between AI and your code - deep, structural understanding for better AI results - name: Confirmation run: echo "✅ Docker Hub description updated successfully!" - # Build and test Docker image build: name: Build Docker Image @@ -304,7 +303,7 @@ jobs: password: ${{ secrets.DOCKERHUB_TOKEN }} repository: ${{ env.IMAGE_NAME }} readme-filepath: ./DOCKER.md - short-description: "The missing abstraction layer between AI and your code - deep, structural understanding for better AI results" + short-description: The missing abstraction layer between AI and your code - deep, structural understanding for better AI results - name: Generate image summary run: | { diff --git a/.github/workflows/mcp-registry-submit.yml b/.github/workflows/mcp-registry-submit.yml index 47a68234c..90144084e 100644 --- a/.github/workflows/mcp-registry-submit.yml +++ b/.github/workflows/mcp-registry-submit.yml @@ -5,7 +5,6 @@ # Triggers on release publication after PyPI package is available name: Submit to MCP Registry - on: release: types: @@ -14,18 +13,15 @@ on: workflow_dispatch: inputs: version: - description: "Version to submit (leave empty to use latest release)" + description: Version to submit (leave empty to use latest release) required: false type: string - permissions: contents: read - jobs: validate-and-submit: name: Validate and Submit to MCP Registry runs-on: ubuntu-latest - steps: - name: Checkout repository uses: actions/checkout@b3498302c5c423fa896b97a26bb183df735d08f8 @@ -55,7 +51,6 @@ jobs: echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "Detected version: ${VERSION}" - - name: Regenerate server.json from code run: | VERSION="${{ steps.version.outputs.version }}" diff --git a/.github/workflows/publish-test.yml b/.github/workflows/publish-test.yml index 710910bb4..d83cd2852 100644 --- a/.github/workflows/publish-test.yml +++ b/.github/workflows/publish-test.yml @@ -22,11 +22,10 @@ jobs: uses: ./.github/workflows/_reusable-test.yml with: python-versions: '["3.12", "3.13"]' - test-markers: "not docker and not qdrant and not dev_only and not skip_ci" + test-markers: not docker and not qdrant and not dev_only and not skip_ci upload-coverage: false run-quality-checks: true secrets: inherit - build: name: Build Distribution needs: tests @@ -37,7 +36,6 @@ jobs: python-version: "3.12" upload-artifacts: true clean-build: true - publish-to-testpypi: name: Publish to TestPyPI needs: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5bdf2c626..fe4be8bc3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,6 +6,9 @@ name: Release on: push: + branches: + - main + - staging tags: - v* workflow_dispatch: @@ -38,19 +41,17 @@ jobs: upload-coverage: false run-quality-checks: true secrets: inherit - build: name: Build Distribution needs: tests if: always() && (needs.tests.result == 'success' || needs.tests.result == 'skipped') uses: ./.github/workflows/_reusable-build.yml with: - artifact-name: "python-package-distributions" + artifact-name: python-package-distributions python-version: "3.12" upload-artifacts: true clean-build: true secrets: inherit - github-release: name: Create GitHub Release needs: @@ -82,84 +83,13 @@ jobs: fi echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "tag=v$VERSION" >> "$GITHUB_OUTPUT" - - name: Install git-cliff uses: taiki-e/install-action@331a600f1b10a3fed8dc56f925012bede91ae51f with: tool: git-cliff@2.10.0 - - name: Generate release notes id: release_notes - run: | - # Get the latest release tag (before current) - PREVIOUS_TAG="$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+([ab]|rc|-alpha|-beta)?[0-9]*(\.[0-9]+)?$' | head -2 | tail -1 || echo "")" - CURRENT_TAG="${{ steps.version.outputs.tag }}" - VERSION="${{ steps.version.outputs.version }}" - - echo "Previous tag: $PREVIOUS_TAG" - echo "Current tag: $CURRENT_TAG" - - # Generate changelog using git-cliff. - # Note: We use '--strip header' to intentionally remove the changelog header (as defined in cliff.toml), - # so that only the changes section is extracted for embedding in the release notes. - if [ -n "$PREVIOUS_TAG" ] && [ "$PREVIOUS_TAG" != "$CURRENT_TAG" ]; then - # Generate changelog for the range between previous and current tag - git-cliff --strip header --tag "$CURRENT_TAG" "$PREVIOUS_TAG..$CURRENT_TAG" > changelog_section.md - else - # First release - get all commits - git-cliff --strip header --tag "$CURRENT_TAG" > changelog_section.md - fi - - # Build complete release notes with installation instructions - cat > release_notes.md << 'EOF' - ## What's Changed - - EOF - - cat changelog_section.md >> release_notes.md - - cat >> release_notes.md << 'EOF' - - ## Installation - - EOF - - # Add pre-release specific installation instructions - if [[ "$VERSION" == *"a"* ]] || [[ "$VERSION" == *"b"* ]] || [[ "$VERSION" == *"rc"* ]]; then - cat >> release_notes.md << EOF - **This is a pre-release version.** Install with: - \`\`\`bash - pip install --pre code-weaver - # Or specific version: - pip install code-weaver==$VERSION - \`\`\` - EOF - else - cat >> release_notes.md << 'EOF' - Install from PyPI: - ```bash - pip install code-weaver - ``` - EOF - fi - - cat >> release_notes.md << 'EOF' - - Or download the wheel/source distribution from the assets below. - - ## Verification - - All release artifacts are built from source and include: - - 📦 Wheel distribution (.whl) - - 📦 Source distribution (.tar.gz) - - EOF - - if [ -n "$PREVIOUS_TAG" ]; then - echo "**Full Changelog**: https://github.com/knitli/codeweaver/compare/$PREVIOUS_TAG...$CURRENT_TAG" >> release_notes.md - else - echo "**Full Changelog**: https://github.com/knitli/codeweaver/commits/$CURRENT_TAG" >> release_notes.md - fi + run: "# Get the latest release tag (before current)\nPREVIOUS_TAG=\"$(git tag --sort=-version:refname | grep -E '^v[0-9]+\\.[0-9]+\\.[0-9]+([ab]|rc|-alpha|-beta)?[0-9]*(\\.[0-9]+)?$' | head -2 | tail -1 || echo \"\")\"\nCURRENT_TAG=\"${{ steps.version.outputs.tag }}\"\nVERSION=\"${{ steps.version.outputs.version }}\"\n\necho \"Previous tag: $PREVIOUS_TAG\"\necho \"Current tag: $CURRENT_TAG\"\n\n# Generate changelog using git-cliff.\n# Note: We use '--strip header' to intentionally remove the changelog header (as defined in cliff.toml),\n# so that only the changes section is extracted for embedding in the release notes.\nif [ -n \"$PREVIOUS_TAG\" ] && [ \"$PREVIOUS_TAG\" != \"$CURRENT_TAG\" ]; then\n # Generate changelog for the range between previous and current tag\n git-cliff --strip header --tag \"$CURRENT_TAG\" \"$PREVIOUS_TAG..$CURRENT_TAG\" > changelog_section.md\nelse\n # First release - get all commits\n git-cliff --strip header --tag \"$CURRENT_TAG\" > changelog_section.md\nfi\n\n# Build complete release notes with installation instructions\ncat > release_notes.md << 'EOF'\n## What's Changed\n\nEOF\n\ncat changelog_section.md >> release_notes.md\n\ncat >> release_notes.md << 'EOF'\n\n## Installation\n\nEOF\n\n# Add pre-release specific installation instructions\nif [[ \"$VERSION\" == *\"a\"* ]] || [[ \"$VERSION\" == *\"b\"* ]] || [[ \"$VERSION\" == *\"rc\"* ]]; then\n cat >> release_notes.md << EOF\n**This is a pre-release version.** Install with:\n\\`\\`\\`bash\npip install --pre code-weaver\n# Or specific version:\npip install code-weaver==$VERSION\n\\`\\`\\`\nEOF\nelse\n cat >> release_notes.md << 'EOF'\nInstall from PyPI:\n```bash\npip install code-weaver\n```\nEOF\nfi\n\ncat >> release_notes.md << 'EOF'\n\nOr download the wheel/source distribution from the assets below.\n\n## Verification\n\nAll release artifacts are built from source and include:\n- \U0001F4E6 Wheel distribution (.whl)\n- \U0001F4E6 Source distribution (.tar.gz)\n\nEOF\n\nif [ -n \"$PREVIOUS_TAG\" ]; then\n echo \"**Full Changelog**: https://github.com/knitli/codeweaver/compare/$PREVIOUS_TAG...$CURRENT_TAG\" >> release_notes.md\nelse\n echo \"**Full Changelog**: https://github.com/knitli/codeweaver/commits/$CURRENT_TAG\" >> release_notes.md\nfi\n" - name: Create GitHub Release uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe with: @@ -183,7 +113,6 @@ jobs: environment: name: production url: https://pypi.org/p/codeweaver - permissions: id-token: write contents: read diff --git a/.mcp.json b/.mcp.json index a9c745d5c..f54caf66c 100644 --- a/.mcp.json +++ b/.mcp.json @@ -58,4 +58,4 @@ "type": "stdio" } } -} \ No newline at end of file +} diff --git a/.vscode/mcp.json b/.vscode/mcp.json index 07526fa34..213f0db27 100644 --- a/.vscode/mcp.json +++ b/.vscode/mcp.json @@ -45,4 +45,4 @@ } } } -} \ No newline at end of file +} diff --git a/context7.json b/context7.json index bb1dc4546..bf553d9d9 100644 --- a/context7.json +++ b/context7.json @@ -35,4 +35,4 @@ "CodeWeaver supports multiple AI Agents and vector models, allowing you to choose the best fit for your use case.", "Focus on types. CodeWeaver has a strong type system that ensures all components are type-safe and can be easily extended." ] -} \ No newline at end of file +} diff --git a/data/node_types/hcl-node-types.json b/data/node_types/hcl-node-types.json index 1443092c1..908719129 100644 --- a/data/node_types/hcl-node-types.json +++ b/data/node_types/hcl-node-types.json @@ -1286,4 +1286,4 @@ "type": "}", "named": false } -] \ No newline at end of file +] diff --git a/docker-compose.yml b/docker-compose.yml index bc801cacf..ffb345b70 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,7 +25,6 @@ services: restart: unless-stopped networks: - codeweaver-network - # CodeWeaver MCP Server # Semantic code search and context delivery for AI agents codeweaver: @@ -34,21 +33,26 @@ services: dockerfile: Dockerfile container_name: codeweaver-server # Use HTTP transport for persistent service mode (daemon not needed in Docker) - command: ["codeweaver", "server", "--host", "0.0.0.0", "--port", "9328", "--transport", "streamable-http"] + command: + - codeweaver + - server + - --host + - 0.0.0.0 + - --port + - "9328" + - --transport + - streamable-http ports: - ${CODEWEAVER_PORT:-9328}:9328 volumes: # Mount your codebase to be indexed (read-only) # Changes on host are immediately visible in container - ${PROJECT_PATH:-.}:/workspace:ro - # Persistent storage for checkpoints, config, and secrets # CRITICAL: This must persist between restarts for index checkpoints - codeweaver_config:/app/config - # Application data and cache - codeweaver_data:/app/data - # Note: Config auto-discovery # CodeWeaver finds codeweaver.toml in your project root automatically. # Just add it to PROJECT_PATH - no explicit mount needed. @@ -62,7 +66,6 @@ services: # - quickstart: FastEmbed/Sentence Transformers (free, local) # - backup: Lightest local models + in-memory vectors - CODEWEAVER_PROFILE=${CODEWEAVER_PROFILE:-quickstart} - # Vector store deployment type - CODEWEAVER_VECTOR_DEPLOYMENT=${VECTOR_DEPLOYMENT:-local} # For cloud deployment, set CODEWEAVER_VECTOR_URL @@ -74,19 +77,15 @@ services: - CODEWEAVER_PROJECT_PATH=/workspace - CODEWEAVER_TOKEN_LIMIT=${TOKEN_LIMIT:-30000} - CODEWEAVER_PROJECT_NAME=${PROJECT_NAME} - # Redirect user config to mounted volume for checkpoint persistence - XDG_CONFIG_HOME=/app/config - # ================================================================= # API Keys (Pass through to providers) # ================================================================= # Required for 'recommended' profile - VOYAGE_API_KEY=${VOYAGE_API_KEY:-} - # Required for agent functionality (future feature) - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-} - # Optional: Alternative providers # - OPENAI_API_KEY=${OPENAI_API_KEY:-} # - COHERE_API_KEY=${COHERE_API_KEY:-} @@ -119,7 +118,6 @@ services: memory: 4G reservations: memory: 2G - volumes: # Persistent storage for Qdrant vector database qdrant_storage: @@ -130,7 +128,6 @@ volumes: # CodeWeaver application data codeweaver_data: driver: local - networks: codeweaver-network: driver: bridge diff --git a/docs-site/.vscode/extensions.json b/docs-site/.vscode/extensions.json index 22a15055d..2d7e89370 100644 --- a/docs-site/.vscode/extensions.json +++ b/docs-site/.vscode/extensions.json @@ -1,4 +1,6 @@ { - "recommendations": ["astro-build.astro-vscode"], + "recommendations": [ + "astro-build.astro-vscode" + ], "unwantedRecommendations": [] } diff --git a/docs-site/package.json b/docs-site/package.json index c9e56b0e5..a08508672 100644 --- a/docs-site/package.json +++ b/docs-site/package.json @@ -31,4 +31,4 @@ }, "type": "module", "version": "0.0.1" -} \ No newline at end of file +} diff --git a/docs-site/src/content/docs/index.mdx b/docs-site/src/content/docs/index.mdx index bb8378de4..6c46f8a2f 100644 --- a/docs-site/src/content/docs/index.mdx +++ b/docs-site/src/content/docs/index.mdx @@ -40,7 +40,7 @@ import { Card, CardGrid } from '@astrojs/starlight/components'; ```bash # Install CodeWeaver -uv pip install codeweaver +uv pip install code-weaver # Start the daemon cw start --project /path/to/your/codebase diff --git a/docs-site/tsconfig.json b/docs-site/tsconfig.json index 9202d199e..f36744a58 100644 --- a/docs-site/tsconfig.json +++ b/docs-site/tsconfig.json @@ -15,4 +15,4 @@ ] } } -} \ No newline at end of file +} diff --git a/mise-tasks/validate-lazy-imports.py b/mise-tasks/validate-lazy-imports.py index 22cf0b44d..1306046be 100755 --- a/mise-tasks/validate-lazy-imports.py +++ b/mise-tasks/validate-lazy-imports.py @@ -75,6 +75,8 @@ "codeweaver.mcp.middleware.McpMiddleware", "codeweaver.providers.agent.AgentProfile", "codeweaver.providers.agent.AgentProfileSpec", + "providers.reranking.providers.sentence_transformers", + "providers.embedding.providers.sentence_transformers", "codeweaver.providers.reranking.KnownRerankModelName", "codeweaver.providers.reranking.capabilities.dependency_map", "codeweaver.providers.reranking.capabilities.load_default_capabilities", @@ -85,7 +87,15 @@ "codeweaver.providers.embedding.capabilities.load_sparse_capabilities", ) -PROBLEM_CHILDREN = ("codeweaver.providers.embedding.providers.bedrock", "BedrockEmbeddingProvider") +PROBLEM_CHILDREN = ( + "codeweaver.providers.embedding.providers.bedrock", + "BedrockEmbeddingProvider", + "codeweaver.providers.embedding.providers.sentence_transformers", + "SentenceTransformersEmbeddingProvider", + "SentenceTransformersSparseProvider", + "codeweaver.providers.reranking.providers.sentence_transformers", + "SentenceTransformersRerankingProvider", +) """Tuple of modules and types with known problematic lazy imports to skip during validation.""" diff --git a/mise.dev.toml b/mise.dev.toml index 81a13eaee..7208d9d99 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -41,7 +41,7 @@ case "$python_path" in ;; *) # Not in venv or python not found, source it - source .venv/bin/activate 2>/dev/null || true + . .venv/bin/activate 2>/dev/null || true ;; esac ''' diff --git a/mise.toml b/mise.toml index cef3a6423..b3a6e8408 100644 --- a/mise.toml +++ b/mise.toml @@ -137,6 +137,45 @@ ACTIVE_SHELL = '''{{ exec(command='basename "$SHELL" 2>/dev/null || echo zsh') } [tasks.setup.tools] uv = "latest" +[tasks.cloud-setup] +run = [ + "echo \"[codeweaver] Setting up cloud development environment...\"", + "ln -sf AGENTS.md CLAUDE.md", + '''if ! command -v mise &>/dev/null; then + if [ -d "$HOME/.local/share/mise" ] || [ -d "$HOME/.mise" ] || [ -f "$HOME/.local/bin/mise" ]; then + export PATH="$HOME/.local/bin:$HOME/.mise/bin:$HOME/.local/share/mise/bin:$PATH" + if ! grep -q "mise activate" "$HOME/.bashrc"; then + echo "eval \"$(mise activate \"${ACTIVE_SHELL:-bash}\")\" 2>&1 || true" >> "$HOME/.bashrc" + fi + else + chmod +x scripts/dev-env/install-mise.sh 2>&1 || true + ./scripts/dev-env/install-mise.sh 2>&1 || true + fi + fi''', + "mise -y trust --all 2>&1 || true", + "mise install 2>&1 || true", + "hk install --mise 2>&1 || mise x hk@latest -- hk install --mise 2>&1 || true", + "mise x uv@latest -- uv venv --allow-existing --seed --keyring-provider subprocess --python {{ get_env(name='MISE_PYTHON', default='3.13') }} .venv 2>&1", + "source .venv/bin/activate 2>&1 || true", + "mise x uv@latest -- uv sync --group dev --group test 2>&1", + "git config include.path .gitconfig 2>&1 || true", + ''' + ignore_files=('src/codeweaver/_version.py' 'coverage.xml' 'test-results.xml') + for file in "${ignore_files[@]}"; do + if ! grep -qx "$file" .git/info/exclude; then + echo "$file" >> .git/info/exclude 2>&1 + fi + done + ''', + "echo \"[codeweaver] Cloud development environment setup complete!\"", +] + +[tasks.cloud-setup.env] +ACTIVE_SHELL = '''{{ exec(command='basename "$SHELL" 2>/dev/null || echo bash') }}''' +MISE_EXPERIMENTAL = "1" +MISE_ENV = "dev" +MISE_YES = "1" + [tasks.fix-python] tools.uv = "latest" tools.ast-grep = "latest" diff --git a/pyproject.toml b/pyproject.toml index eb55ff631..e17197baf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -107,8 +107,8 @@ dependencies = [ "ast-grep-py>=0.40.0", "blake3>=1.0.8", # CLI framework and output - "cyclopts>=4.2.4", - "fastembed>=0.7.3", + "cyclopts>=4.3.0", + "fastembed>=0.7.4", # MCP server framework "fastmcp>=2.13.3", "httpx[http2]>=0.28.1", @@ -153,6 +153,8 @@ codeweaver = "codeweaver.cli.__main__:main" cw = "codeweaver.cli.__main__:main" [project.optional-dependencies] +# ==== Providers ==== +anthropic = ["pydantic-ai-slim[anthropic]"] # eunomia middleware - see https://gofastmcp.com/integrations/eunomia-authorization auth-eunomia = ["eunomia-mcp"] # ==== Authentication and Authorization Middleware ==== @@ -166,6 +168,16 @@ auth-permitio = ["permit-fastmcp"] # Settings/Config Secrets aws-secrets-manager = ["pydantic-settings[yaml,toml,aws-secrets-manager]"] azure-key-vault = ["pydantic-settings[yaml,toml,azure-key-vault]"] +bedrock = [ + "pydantic-ai-slim[bedrock]", + "types-boto3-custom", +] +cohere = ["pydantic-ai-slim[cohere]"] +# ==== Data Sources ==== +duckduckgo = ["pydantic-ai-slim[duckduckgo]"] +fastembed = ["fastembed", "py-cpuinfo"] +# Requires additional setup, see https://qdrant.github.io/fastembed/examples/FastEmbed_GPU/ +fastembed-gpu = ["fastembed-gpu", "py-cpuinfo"] # workos AuthKit middleware - see https://gofastmcp.com/integrations/authkit # No additional dependencies required, it's purely REST-based. # Enable with environment variables: @@ -178,6 +190,7 @@ azure-key-vault = ["pydantic-settings[yaml,toml,azure-key-vault]"] full = [ "permit-fastmcp", "eunomia-mcp", + "pydantic-ai-slim[openai,cohere,google,anthropic,groq,mistral,bedrock,huggingface,duckduckgo,tavily,retries]", "pydantic-settings[yaml,toml,aws-secrets-manager,azure-key-vault,gcp-secret-manager]", "permit-fastmcp", "sentence-transformers>=5.1.2", @@ -194,38 +207,34 @@ full-gpu = [ # "sentence-transformers[onnx-gpu]; python_version>='3.12' and python_version<'3.14'", ] gcp-secret-manager = ["pydantic-settings[yaml,toml,gcp-secret-manager]"] +google = ["pydantic-ai-slim[google]"] gpu-support = [ "fastembed-gpu", # see note below about why this is commented out # "sentence-transformers[onnx-gpu]; python_version>='3.12' and python_version<'3.14'", ] -# ==== Providers ==== -provider-anthropic = ["pydantic-ai-slim[anthropic]"] -provider-bedrock = [ - "pydantic-ai-slim[bedrock]", - "types-boto3-custom", -] -provider-cohere = ["pydantic-ai-slim[cohere]"] -provider-fastembed = ["fastembed", "py-cpuinfo"] -# Requires additional setup, see https://qdrant.github.io/fastembed/examples/FastEmbed_GPU/ -provider-fastembed-gpu = ["fastembed-gpu", "py-cpuinfo"] -provider-google = ["pydantic-ai-slim[google]"] -provider-groq = ["pydantic-ai-slim[groq]"] +groq = ["pydantic-ai-slim[groq]"] # --- Embedding and Agent Providers --- (no rerank) -provider-huggingface = ["pydantic-ai-slim[huggingface]"] +huggingface = ["pydantic-ai-slim[huggingface]"] # ==== Vector Stores ==== -provider-in-memory = ["qdrant-client", "tokenizers"] -provider-mistral = ["pydantic-ai-slim[mistral]"] +in-memory = ["qdrant-client", "tokenizers"] +mistral = ["pydantic-ai-slim[mistral]"] # OpenAI includes support for: # Cerebras, DeekSeek, Ollama, OpenRouter, Vercel, Perplexity, Moonshot, FireworksAI, # TogetherAI, Azure AI Foundry, Heroku, and Github Models, X-AI # which all use the OpenAI API -provider-openai = ["pydantic-ai-slim[openai]"] -provider-qdrant = ["qdrant-client"] -provider-sentence-transformers = [ +openai = ["pydantic-ai-slim[openai]"] +qdrant = ["qdrant-client"] +recommended-local-only = [ + "fastembed", + "sentence-transformers", + "tokenizers", +] +sentence-transformers = [ "sentence-transformers", "py-cpuinfo", ] +tavily = ["pydantic-ai-slim[tavily]"] # NOTE: Why not GPU or OpenVino support for sentence-transformers? # The underlying runtimes for these packages, when resolved against our other dependencies, # essentially require us to choose between support for Python 3.14 and these packages. @@ -234,23 +243,15 @@ provider-sentence-transformers = [ # We think the sparse-encoding use case is much broader than GPU or OpenVino acceleration for most users, # so we are leaving these out of the official optional dependencies for now. # If you need GPU or OpenVino support, you can install these packages manually in your environment. -# provider-sentence-transformers-gpu = [ +# sentence-transformers-gpu = [ # GPU requires additional setup # "sentence-transformers[onnx-gpu]; python_version>='3.12' and python_version<'3.14'", # ] -# provider-sentence-transformers-openvino = [ +# sentence-transformers-openvino = [ # "sentence-transformers[openvino]", # "py-cpuinfo", # ] -provider-voyageai = ["voyageai"] -recommended-local-only = [ - "fastembed", - "sentence-transformers", - "tokenizers", -] -# ==== Data Sources ==== -source-duckduckgo = ["pydantic-ai-slim[duckduckgo]"] -source-tavily = ["pydantic-ai-slim[tavily]"] +voyageai = ["voyageai"] [dependency-groups] dev = [ diff --git a/schema/v1.0.0/codeweaver.schema.json b/schema/v1.0.0/codeweaver.schema.json index e858f0d4e..b4bc64cb4 100644 --- a/schema/v1.0.0/codeweaver.schema.json +++ b/schema/v1.0.0/codeweaver.schema.json @@ -2518,4 +2518,4 @@ }, "title": "CodeWeaver Settings", "type": "object" -} \ No newline at end of file +} diff --git a/scripts/build/generate-docker-server-yaml.py b/scripts/build/generate-docker-server-yaml.py index 6ae2991fa..2dc94c30d 100755 --- a/scripts/build/generate-docker-server-yaml.py +++ b/scripts/build/generate-docker-server-yaml.py @@ -163,7 +163,11 @@ def generate_server_yaml() -> dict: }, "about": { "title": "CodeWeaver - Code Search for AI Agents", - "description": f"Semantic code search built for AI agents. Hybrid AST-aware context for {len(_languages())} languages with intelligent chunking, intent detection, and multi-provider support.", + "description": f"""Semantic code search for AI agents. Hybrid search across {len(_languages())} languages with {len(embedding_providers())} embedding providers. + + Works offline with local models or cloud providers (Voyage, OpenAI, Cohere, etc.). AST-aware parsing, intelligent chunking, automatic failover. + + One simple MCP tool for any client.""", "icon": "https://github.com/knitli/codeweaver/raw/refs/heads/main/docs/assets/codeweaver-favico.png", }, "source": { diff --git a/scripts/build/generate-mcp-server-json.py b/scripts/build/generate-mcp-server-json.py index 24d48ceca..a7ca95832 100755 --- a/scripts/build/generate-mcp-server-json.py +++ b/scripts/build/generate-mcp-server-json.py @@ -848,7 +848,7 @@ def generate_server_detail() -> ServerDetail: return ServerDetail( field_schema=AnyUrl("https://static.modelcontextprotocol.io/schemas/2025-10-17/server.schema.json"), name="com.knitli/codeweaver", - description=f"Semantic code search built for AI agents. Hybrid, AST-aware, context for {len(_languages())} languages.", + description=f"Semantic code search for AI agents. Hybrid search, {len(_languages())} languages, {len([provider for provider in Provider if provider != Provider.NOT_SET])} providers.", title="CodeWeaver - Code Search for AI Agents", version=__version__, repository=REPOSITORY, diff --git a/server.yaml b/server.yaml index 27cbd612b..a67ab5425 100644 --- a/server.yaml +++ b/server.yaml @@ -7,31 +7,31 @@ name: codeweaver image: mcp/codeweaver type: server meta: - category: devops - tags: - - devops + category: devops + tags: + - devops about: - title: Codeweaver - Code Search for AI Agents - description: Semantic code search built for AI agents. Advanced hybrid, AST-aware context curation for 166 languages with intelligent chunking, intent detection, and multi-provider support. Deploy CodeWeaver locally or as a service, in the cloud or completely local. Use with any IDE or AI client. CodeWeaver gives your AI agents one great tool to get the information they need. - icon: https://github.com/knitli/codeweaver/raw/refs/heads/main/docs/assets/codeweaver-favico.png + title: Codeweaver - Code Search for AI Agents + description: Semantic code search built for AI agents. Advanced hybrid, AST-aware context curation for 166 languages with intelligent chunking, intent detection, and multi-provider support. Deploy CodeWeaver locally or as a service, in the cloud or completely local. Use with any IDE or AI client. CodeWeaver gives your AI agents one great tool to get the information they need. + icon: https://github.com/knitli/codeweaver/raw/refs/heads/main/docs/assets/codeweaver-favico.png source: - project: https://github.com/knitli/codeweaver - commit: b2809e688507c84d20867de1199d00d037ca859a + project: https://github.com/knitli/codeweaver + commit: b2809e688507c84d20867de1199d00d037ca859a run: - volumes: - - /data:{{codeweaver.data}} + volumes: + - /data:{{codeweaver.data}} config: - description: Configure the connection to Codeweaver - Code Search for AI Agents - secrets: - - name: codeweaver.foo - env: bar - example: - env: - - name: foo - example: value - value: '{{value}}' - parameters: - type: object - properties: - foo: - type: string + description: Configure the connection to Codeweaver - Code Search for AI Agents + secrets: + - name: codeweaver.foo + env: bar + example: + env: + - name: foo + example: value + value: '{{value}}' + parameters: + type: object + properties: + foo: + type: string diff --git a/specs/004-we-re-preparing/quickstart.md b/specs/004-we-re-preparing/quickstart.md index 89a5a62ba..e5b2a7c28 100644 --- a/specs/004-we-re-preparing/quickstart.md +++ b/specs/004-we-re-preparing/quickstart.md @@ -199,7 +199,7 @@ gh run list --workflow=publish.yml --limit=1 python -m venv /tmp/test-pypi source /tmp/test-pypi/bin/activate -pip install codeweaver==0.1.0 +pip install code-weaver==0.1.0 python -c "import codeweaver; print(codeweaver.__version__)" @@ -214,7 +214,7 @@ rm -rf /tmp/test-pypi **Success Criteria**: - ✅ GitHub Actions workflow succeeds - ✅ Package published to PyPI -- ✅ Package installable via `pip install codeweaver` +- ✅ Package installable via `pip install code-weaver` - ✅ Smoke tests pass - ✅ Version matches tag (e.g., `0.1.0`) diff --git a/src/codeweaver/common/http_pool.py b/src/codeweaver/common/http_pool.py index 7acbb4949..ded2c4bf6 100644 --- a/src/codeweaver/common/http_pool.py +++ b/src/codeweaver/common/http_pool.py @@ -34,8 +34,9 @@ import asyncio import logging import threading + from dataclasses import dataclass, field -from typing import Any, ClassVar +from typing import Any, ClassVar, Self import httpx @@ -112,9 +113,7 @@ class HttpClientPool: @classmethod def get_instance( - cls, - limits: PoolLimits | None = None, - timeouts: PoolTimeouts | None = None, + cls, limits: PoolLimits | None = None, timeouts: PoolTimeouts | None = None ) -> HttpClientPool: """Get or create the singleton HttpClientPool instance. @@ -135,8 +134,7 @@ def get_instance( with _instance_lock: if cls._instance is None: cls._instance = cls( - limits=limits or PoolLimits(), - timeouts=timeouts or PoolTimeouts(), + limits=limits or PoolLimits(), timeouts=timeouts or PoolTimeouts() ) logger.debug( "Created HttpClientPool singleton with limits=%s, timeouts=%s", @@ -205,8 +203,7 @@ async def get_client(self, name: str, **overrides: Any) -> httpx.AsyncClient: limits = httpx.Limits( max_connections=overrides.get("max_connections", self.limits.max_connections), max_keepalive_connections=overrides.get( - "max_keepalive_connections", - self.limits.max_keepalive_connections, + "max_keepalive_connections", self.limits.max_keepalive_connections ), keepalive_expiry=overrides.get("keepalive_expiry", self.limits.keepalive_expiry), ) @@ -275,10 +272,11 @@ def get_client_sync(self, name: str, **overrides: Any) -> httpx.AsyncClient: limits = httpx.Limits( max_connections=overrides.get("max_connections", self.limits.max_connections), max_keepalive_connections=overrides.get( - "max_keepalive_connections", - self.limits.max_keepalive_connections, + "max_keepalive_connections", self.limits.max_keepalive_connections + ), + keepalive_expiry=overrides.get( + "keepalive_expiry", self.limits.keepalive_expiry ), - keepalive_expiry=overrides.get("keepalive_expiry", self.limits.keepalive_expiry), ) timeout = httpx.Timeout( @@ -289,9 +287,7 @@ def get_client_sync(self, name: str, **overrides: Any) -> httpx.AsyncClient: ) self._clients[name] = httpx.AsyncClient( - limits=limits, - timeout=timeout, - http2=overrides.get("http2", True), + limits=limits, timeout=timeout, http2=overrides.get("http2", True) ) logger.debug( @@ -341,10 +337,11 @@ async def close_client(self, name: str) -> bool: try: await client.aclose() logger.debug("Closed HTTP client pool for %s", name) - return True except (httpx.HTTPError, OSError) as e: logger.warning("Error closing HTTP client pool for %s: %s", name, e) # Client already removed from dict above + else: + return True return False async def close_all(self) -> None: @@ -372,11 +369,11 @@ async def close_all(self) -> None: if client_names: logger.debug("Closed %d HTTP client pool(s)", len(client_names)) - async def __aenter__(self) -> HttpClientPool: + async def __aenter__(self) -> Self: """Async context manager entry.""" return self - async def __aexit__(self, *args: Any) -> None: + async def __aexit__(self, *args: object) -> None: """Async context manager exit - closes all clients.""" await self.close_all() diff --git a/src/codeweaver/config/profiles.py b/src/codeweaver/config/profiles.py index 9df495833..e76096c5f 100644 --- a/src/codeweaver/config/profiles.py +++ b/src/codeweaver/config/profiles.py @@ -11,8 +11,8 @@ The recommended flag gives you access to: - All current vector, agent and data providers - All embedding and reranking providers except for Sentence Transformers (because these install paths are aligned with pydantic-ai's default dependencies, and Sentence Transformers is not a default dependency of pydantic-ai). -- A-la-Carte installations: You can also use the `required-core` install flag (`pip install code-weaver[required-core]`) to install only the core dependencies of CodeWeaver, and then add individual providers using their own install flags (all prefixed with `provider-`), like: - `pip install code-weaver[required-core,provider-openai,provider-qdrant]` +- A-la-Carte installations: You can also use the `required-core` install flag (`pip install code-weaver[required-core]`) to install only the core dependencies of CodeWeaver, and then add individual providers using their own install flags, like: + `pip install code-weaver[required-core,openai,qdrant]` """ diff --git a/src/codeweaver/config/settings.py b/src/codeweaver/config/settings.py index a106098b9..e078912db 100644 --- a/src/codeweaver/config/settings.py +++ b/src/codeweaver/config/settings.py @@ -521,12 +521,12 @@ class CodeWeaverSettings(BaseSettings): pattern=r"\d{1,2}\.\d{1,3}\.\d{1,3}", alias="schema_version", ), - ] = "1.1.0" + ] = "1.1.1" schema_: HttpUrl = Field( description="URL to the CodeWeaver settings schema", default_factory=lambda data: HttpUrl( - f"https://raw.githubusercontent.com/knitli/codeweaver/main/schema/v{data.get('__version__', data.get('schema_version')) or '1.1.0'}/codeweaver.schema.json" + f"https://raw.githubusercontent.com/knitli/codeweaver/main/schema/v{data.get('__version__', data.get('schema_version')) or '1.1.1'}/codeweaver.schema.json" ), ) diff --git a/src/codeweaver/config/telemetry.py b/src/codeweaver/config/telemetry.py index 78c840605..51665f7eb 100644 --- a/src/codeweaver/config/telemetry.py +++ b/src/codeweaver/config/telemetry.py @@ -73,7 +73,7 @@ class TelemetrySettings(BasedModel): If you want to disable telemetry, you have several options: 1. set this setting to False in your codeweaver.toml/yaml/json file, 2. set the environment variable `CODEWEAVER_ENABLE_TELEMETRY` to `false` - 3. install CodeWeaver with the `codeweaver[recommended-no-telemetry]` extra, or use the a-la-carte install with `codeweaver[required-core]` and your choice of providers (like, `codeweaver[required-core,cli,provider-anthropic,provider-fastembed,provider-azure]`) to install without telemetry + 3. install CodeWeaver with the `codeweaver[recommended-no-telemetry]` extra, or use the a-la-carte install with `codeweaver[required-core]` and your choice of providers (like, `codeweaver[anthropic,fastembed,azure]`) to install without telemetry 4. Point the `CODEWEAVER__TELEMETRY__POSTHOG_PROJECT_KEY` environment variable to your own Posthog project (if you're a data nerd, or want to collect internal telemetry for your organization). If you disable telemetry, we won't collect any data at all.""" ), ] = _set_bool_env_var("CODEWEAVER__TELEMETRY__DISABLE_TELEMETRY") diff --git a/src/codeweaver/core/discovery.py b/src/codeweaver/core/discovery.py index 6a366e2a5..bb4349dff 100644 --- a/src/codeweaver/core/discovery.py +++ b/src/codeweaver/core/discovery.py @@ -159,6 +159,7 @@ def size(self) -> NonNegativeInt: return 0 # Return 0 for non-existent files (e.g., test fixtures) @computed_field + @property def file_hash(self) -> BlakeHashKey: """Return the blake3 hash of the file contents, if available.""" if self._file_hash is not None: @@ -181,7 +182,7 @@ def is_same(self, other_path: Path) -> bool: """ if other_path.is_file() and other_path.exists(): file = type(self).from_path(other_path) - return bool(file and file.file_hash() == self.file_hash()) + return bool(file and file.file_hash == self.file_hash) return False @computed_field diff --git a/src/codeweaver/core/types/aliases.py b/src/codeweaver/core/types/aliases.py index 7f6c84538..9023ce550 100644 --- a/src/codeweaver/core/types/aliases.py +++ b/src/codeweaver/core/types/aliases.py @@ -127,7 +127,8 @@ description="""A file extension string as the `FileExt` NewType, including the leading dot. E.g. '.txt'. May also be an exact filename like 'Makefile' that has no extension.""", pattern=r"""^(\.[^<>:;,?*|\\]+|[^<>:;,?*|\\]+)$""", min_length=2, - max_length=20, + # this may seem long but sometimes extensions are actually filenames, so we allow longer ones within reason + max_length=50, ), ] diff --git a/src/codeweaver/engine/failover_tracker.py b/src/codeweaver/engine/failover_tracker.py index a7bd17e6f..5a2278b5f 100644 --- a/src/codeweaver/engine/failover_tracker.py +++ b/src/codeweaver/engine/failover_tracker.py @@ -137,7 +137,7 @@ def record_file_indexed(self, discovered_file: DiscoveredFile) -> None: serialized_rel_path = str(rel_path) old_hash = self.file_hashes.get(serialized_rel_path) - new_hash = discovered_file.file_hash() + new_hash = discovered_file.file_hash if old_hash != new_hash: self.pending_changes.add(serialized_rel_path) diff --git a/src/codeweaver/engine/indexer/indexer.py b/src/codeweaver/engine/indexer/indexer.py index ed8e56620..7e487aa1f 100644 --- a/src/codeweaver/engine/indexer/indexer.py +++ b/src/codeweaver/engine/indexer/indexer.py @@ -496,7 +496,7 @@ async def _index_file(self, path: Path, context: Any = None) -> None: logger.debug("Skipping non-text file: %s", path) return - self._store.set(discovered_file.file_hash(), discovered_file) + self._store.set(discovered_file.file_hash, discovered_file) self._stats.files_discovered += 1 # Track file discovery in session statistics @@ -667,7 +667,7 @@ async def _index_file(self, path: Path, context: Any = None) -> None: async with self._manifest_lock: self._file_manifest.add_file( path=relative_path, - content_hash=discovered_file.file_hash(), + content_hash=discovered_file.file_hash, chunk_ids=chunk_ids, dense_embedding_provider=model_info["dense_provider"], dense_embedding_model=model_info["dense_model"], @@ -975,7 +975,7 @@ async def _update_manifest_for_batch( async with self._manifest_lock: self._file_manifest.add_file( path=relative_path, - content_hash=discovered_file.file_hash(), + content_hash=discovered_file.file_hash, chunk_ids=chunk_ids, dense_embedding_provider=model_info["dense_provider"], dense_embedding_model=model_info["dense_model"], @@ -1518,7 +1518,7 @@ def _discover_files_for_batch(self, files: list[Path]) -> list[DiscoveredFile]: discovered_file = DiscoveredFile.from_path(path) if discovered_file and discovered_file.is_text: discovered_files.append(discovered_file) - self._store.set(discovered_file.file_hash(), discovered_file) + self._store.set(discovered_file.file_hash, discovered_file) except Exception: logger.warning("Failed to discover file %s", path, exc_info=True) self._stats.files_with_errors.append(path) diff --git a/src/codeweaver/providers/embedding/providers/bedrock.py b/src/codeweaver/providers/embedding/providers/bedrock.py index 71c996229..a8914cb9b 100644 --- a/src/codeweaver/providers/embedding/providers/bedrock.py +++ b/src/codeweaver/providers/embedding/providers/bedrock.py @@ -434,7 +434,7 @@ def from_boto3_response(cls, response: Any) -> BedrockInvokeEmbeddingResponse: exc_info=True, ) raise ConfigurationError( - "Failed to import boto3. You need to install the boto3 package, you can do this by running 'pip install code-weaver[bedrock]'" + r"Failed to import boto3. You need to install the boto3 package, you can do this by running 'pip install code-weaver\[bedrock]'" ) from e diff --git a/src/codeweaver/providers/embedding/providers/cohere.py b/src/codeweaver/providers/embedding/providers/cohere.py index de36a177a..ca247656c 100644 --- a/src/codeweaver/providers/embedding/providers/cohere.py +++ b/src/codeweaver/providers/embedding/providers/cohere.py @@ -89,7 +89,7 @@ def try_for_azure_endpoint(kwargs: Any) -> str: except ImportError as e: raise ConfigurationError( - 'Please install the `cohere` package to use the Cohere provider, \nyou can use the `cohere` optional group -- `pip install "code-weaver[cohere]"`' + r'Please install the `cohere` package to use the Cohere provider, \nyou can use the `cohere` optional group -- `pip install "code-weaver\[cohere]"`' ) from e diff --git a/src/codeweaver/providers/embedding/providers/fastembed.py b/src/codeweaver/providers/embedding/providers/fastembed.py index 681d420bc..a693abf74 100644 --- a/src/codeweaver/providers/embedding/providers/fastembed.py +++ b/src/codeweaver/providers/embedding/providers/fastembed.py @@ -49,7 +49,7 @@ ) except ImportError as e: raise ConfigurationError( - "FastEmbed is not installed. Please install it with `pip install code-weaver[fastembed]` or `codeweaver[fastembed-gpu]`." + r"FastEmbed is not installed. Please install it with `pip install code-weaver\[fastembed]` or `code-weaver\[fastembed-gpu]`." ) from e _TextEmbedding = get_text_embedder() diff --git a/src/codeweaver/providers/embedding/providers/google.py b/src/codeweaver/providers/embedding/providers/google.py index d911926a7..2e4c8ccb6 100644 --- a/src/codeweaver/providers/embedding/providers/google.py +++ b/src/codeweaver/providers/embedding/providers/google.py @@ -83,7 +83,7 @@ def __str__( except ImportError as e: raise ConfigurationError( - "The 'google-genai' package is required to use the Google embedding provider. Please install it with 'pip install code-weaver[google]'." + r"The 'google-genai' package is required to use the Google embedding provider. Please install it with 'pip install code-weaver\[google]'." ) from e diff --git a/src/codeweaver/providers/embedding/providers/huggingface.py b/src/codeweaver/providers/embedding/providers/huggingface.py index 6fa303ca9..266f257cb 100644 --- a/src/codeweaver/providers/embedding/providers/huggingface.py +++ b/src/codeweaver/providers/embedding/providers/huggingface.py @@ -63,7 +63,7 @@ def huggingface_hub_query_kwargs(**kwargs: Any) -> dict[str, Any]: except ImportError as e: logger.debug("HuggingFace Hub is not installed.") raise ConfigurationError( - 'Please install the `huggingface_hub` package to use the HuggingFace provider, you can use the `huggingface` optional group -- `pip install "code-weaver[huggingface]"`' + r'Please install the `huggingface_hub` package to use the HuggingFace provider, you can use the `huggingface` optional group -- `pip install "code-weaver\[huggingface]"`' ) from e diff --git a/src/codeweaver/providers/embedding/providers/mistral.py b/src/codeweaver/providers/embedding/providers/mistral.py index 37f0e5cf2..47307aa37 100644 --- a/src/codeweaver/providers/embedding/providers/mistral.py +++ b/src/codeweaver/providers/embedding/providers/mistral.py @@ -26,7 +26,7 @@ from mistralai.models import EmbeddingDtype except ImportError as e: raise ConfigurationError( - 'Please install the `mistralai` package to use the Mistral provider, \nyou can use the `mistral` optional group -- `pip install "code-weaver[mistral]"`' + r'Please install the `mistralai` package to use the Mistral provider, \nyou can use the `mistral` optional group -- `pip install "code-weaver\[mistral]"`' ) from e diff --git a/src/codeweaver/providers/embedding/providers/openai_factory.py b/src/codeweaver/providers/embedding/providers/openai_factory.py index 5d71f94a8..099223544 100644 --- a/src/codeweaver/providers/embedding/providers/openai_factory.py +++ b/src/codeweaver/providers/embedding/providers/openai_factory.py @@ -90,7 +90,7 @@ def try_for_azure_endpoint(kwargs: Any) -> str: from openai.types.create_embedding_response import CreateEmbeddingResponse except ImportError as _import_error: raise ConfigurationError( - 'Please install the `openai` package to use the OpenAI provider, \nyou can use the `openai` optional group -- `pip install "code-weaver[openai]"`' + r'Please install the `openai` package to use the OpenAI provider, \nyou can use the `openai` optional group -- `pip install "code-weaver\[openai]"`' ) from _import_error diff --git a/src/codeweaver/providers/embedding/providers/sentence_transformers.py b/src/codeweaver/providers/embedding/providers/sentence_transformers.py index 3029cdd17..c4248c04c 100644 --- a/src/codeweaver/providers/embedding/providers/sentence_transformers.py +++ b/src/codeweaver/providers/embedding/providers/sentence_transformers.py @@ -34,7 +34,7 @@ from sentence_transformers import SentenceTransformer except ImportError as e: raise ConfigurationError( - 'Please install the `sentence-transformers` package to use the Sentence Transformers provider, \nyou can use the `sentence-transformers` optional group -- `pip install "codeweaver[sentence-transformers]"` or `codeweaver[sentence-transformers-gpu]`' + r'Please install the `sentence-transformers` package to use the Sentence Transformers provider, \nyou can use the `sentence-transformers` optional group -- `pip install "code-weaver\[sentence-transformers]"` or `code-weaver\[sentence-transformers-gpu]`' ) from e # SparseEncoder is not available in all versions of sentence-transformers @@ -129,8 +129,6 @@ def __init__( model_name_or_path=capabilities.name, **doc_kwargs.get("client_options", {}) ) - # Call super().__init__() FIRST which handles all Pydantic initialization - # The base class will set doc_kwargs, query_kwargs, and call _initialize() super().__init__(client=client, caps=capabilities, kwargs=kwargs) @property @@ -164,10 +162,6 @@ def _initialize(self, caps: EmbeddingModelCapabilities) -> None: self.query_kwargs.pop("model_name", None) self.query_kwargs.pop("model_name_or_path", None) - # Note: _client is already set by __init__ when client is provided - # The old code here (self.client = self.client(name, ...)) was incorrect - # as it tried to call an instance as if it were a class - if ( (other := caps.other) and (model := other.get("model_kwargs", {})) @@ -347,10 +341,6 @@ def _initialize(self, caps: EmbeddingModelCapabilities) -> None: self.query_kwargs.pop("model_name", None) self.query_kwargs.pop("model_name_or_path", None) - # Note: _client is already set by __init__ when client is provided - # The old code here (self.client = SparseEncoder(name, ...)) was incorrect - # as it tried to re-initialize an already-initialized client - def _to_sparse_format(self, embedding: Any) -> SparseEmbedding: """Convert embedding to sparse format with indices and values.""" from codeweaver.providers.embedding.types import SparseEmbedding diff --git a/src/codeweaver/providers/embedding/providers/voyage.py b/src/codeweaver/providers/embedding/providers/voyage.py index a32df76ad..258a6207e 100644 --- a/src/codeweaver/providers/embedding/providers/voyage.py +++ b/src/codeweaver/providers/embedding/providers/voyage.py @@ -26,7 +26,7 @@ except ImportError as _import_error: raise ConfigurationError( - 'Please install the `voyageai` package to use the Voyage provider, you can use the `voyage` optional group -- `pip install "code-weaver[voyage]"`' + r'Please install the `voyageai` package to use the Voyage provider, you can use the `voyage` optional group -- `pip install "code-weaver\[voyage]"`' ) from _import_error diff --git a/src/codeweaver/providers/reranking/providers/bedrock.py b/src/codeweaver/providers/reranking/providers/bedrock.py index 2f33f05ce..0ac1f09cf 100644 --- a/src/codeweaver/providers/reranking/providers/bedrock.py +++ b/src/codeweaver/providers/reranking/providers/bedrock.py @@ -22,6 +22,7 @@ from codeweaver.config.providers import AWSProviderSettings from codeweaver.core.types.models import BasedModel +from codeweaver.exceptions import ConfigurationError from codeweaver.exceptions import ValidationError as CodeWeaverValidationError from codeweaver.providers.provider import Provider from codeweaver.providers.reranking.capabilities.amazon import get_amazon_reranking_capabilities @@ -222,7 +223,9 @@ class BedrockRerankingResult(BaseBedrockModel): except ImportError as e: logger.warning("Failed to import boto3", exc_info=True) - raise ImportError("boto3 is not installed. Please install it with `pip install boto3`.") from e + raise ConfigurationError( + r"boto3 is not installed. Please enable it with `pip install code-weaver\[bedrock]`." + ) from e def _to_doc_sources(documents: list[DocumentSource]) -> list[BedrockInlineDocumentSource]: diff --git a/src/codeweaver/providers/reranking/providers/cohere.py b/src/codeweaver/providers/reranking/providers/cohere.py index ddfccc464..23773efef 100644 --- a/src/codeweaver/providers/reranking/providers/cohere.py +++ b/src/codeweaver/providers/reranking/providers/cohere.py @@ -33,7 +33,7 @@ from codeweaver.exceptions import ConfigurationError raise ConfigurationError( - 'Please install the `cohere` package to use the Cohere provider, \nyou can use the `cohere` optional group -- `pip install "code-weaver[cohere]"`' + r'Please install the `cohere` package to use the Cohere provider, \nyou can use the `cohere` optional group -- `pip install "code-weaver\[cohere]"`' ) from e diff --git a/src/codeweaver/providers/reranking/providers/fastembed.py b/src/codeweaver/providers/reranking/providers/fastembed.py index c3807c735..f868bc88b 100644 --- a/src/codeweaver/providers/reranking/providers/fastembed.py +++ b/src/codeweaver/providers/reranking/providers/fastembed.py @@ -31,7 +31,7 @@ from codeweaver.exceptions import ConfigurationError raise ConfigurationError( - "FastEmbed is not installed. Please install it with `pip install code-weaver[fastembed]` or `codeweaver[fastembed-gpu]`." + r"FastEmbed is not installed. Please install it with `pip install code-weaver\[fastembed]` or `codeweaver\[fastembed-gpu]`." ) from e diff --git a/src/codeweaver/providers/reranking/providers/sentence_transformers.py b/src/codeweaver/providers/reranking/providers/sentence_transformers.py index 909d821c3..50e126b61 100644 --- a/src/codeweaver/providers/reranking/providers/sentence_transformers.py +++ b/src/codeweaver/providers/reranking/providers/sentence_transformers.py @@ -33,7 +33,7 @@ from codeweaver.exceptions import ConfigurationError raise ConfigurationError( - "SentenceTransformers is not installed. Please install it with `pip install code-weaver[sentence-transformers]` or `codeweaver[sentence-transformers-gpu]`." + r"SentenceTransformers is not installed. Please install it with `pip install code-weaver\[sentence-transformers]` or `code-weaver\[sentence-transformers-gpu]`." ) from e diff --git a/src/codeweaver/providers/reranking/providers/voyage.py b/src/codeweaver/providers/reranking/providers/voyage.py index 0942864b4..418abd2cd 100644 --- a/src/codeweaver/providers/reranking/providers/voyage.py +++ b/src/codeweaver/providers/reranking/providers/voyage.py @@ -38,7 +38,7 @@ from codeweaver.exceptions import ConfigurationError raise ConfigurationError( - "Voyage AI SDK is not installed. Please install it with `pip install code-weaver[voyage]`." + r"Voyage AI SDK is not installed. Please install it with `pip install code-weaver\[voyage]`." ) from e diff --git a/src/codeweaver/server/server.py b/src/codeweaver/server/server.py index 648a68e48..b41c31a94 100644 --- a/src/codeweaver/server/server.py +++ b/src/codeweaver/server/server.py @@ -155,7 +155,7 @@ class CodeWeaverState(DataclassSerializationMixin): telemetry: Annotated[PostHogClient | None, PrivateAttr(default=None)] http_pool: Annotated[ - "HttpClientPool | None", + HttpClientPool | None, Field( default=None, description="Shared HTTP client pool for provider connections (Voyage, Cohere, etc.)", diff --git a/tests/unit/test_indexer_remove_path.py b/tests/unit/test_indexer_remove_path.py index 30f44bb20..bcf33c35d 100644 --- a/tests/unit/test_indexer_remove_path.py +++ b/tests/unit/test_indexer_remove_path.py @@ -107,7 +107,7 @@ def test_remove_with_multiple_files_in_store( discovered = DiscoveredFile( path=discovered.path, ext_kind=discovered.ext_kind, - file_hash=discovered.file_hash(), + file_hash=discovered.file_hash, git_branch=resolved_branch, source_id=unique_id, ) diff --git a/uv.lock b/uv.lock index 4e86b8268..93d2df59b 100644 --- a/uv.lock +++ b/uv.lock @@ -15,18 +15,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e3/52/6ad8f63ec8da1bf40f96996d25d5b650fdd38f5975f8c813732c47388f18/aenum-3.1.16-py3-none-any.whl", hash = "sha256:9035092855a98e41b66e3d0998bd7b96280e85ceb3a04cc035636138a1943eaf", size = 165627, upload-time = "2025-04-25T03:17:58.89Z" }, ] -[[package]] -name = "ag-ui-protocol" -version = "0.1.10" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pydantic" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/67/bb/5a5ec893eea5805fb9a3db76a9888c3429710dfb6f24bbb37568f2cf7320/ag_ui_protocol-0.1.10.tar.gz", hash = "sha256:3213991c6b2eb24bb1a8c362ee270c16705a07a4c5962267a083d0959ed894f4", size = 6945, upload-time = "2025-11-06T15:17:17.068Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/78/eb55fabaab41abc53f52c0918a9a8c0f747807e5306273f51120fd695957/ag_ui_protocol-0.1.10-py3-none-any.whl", hash = "sha256:c81e6981f30aabdf97a7ee312bfd4df0cd38e718d9fc10019c7d438128b93ab5", size = 7889, upload-time = "2025-11-06T15:17:15.325Z" }, -] - [[package]] name = "aiohappyeyeballs" version = "2.6.1" @@ -185,15 +173,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/15/b3/9b1a8074496371342ec1e796a96f99c82c945a339cd81a8e73de28b4cf9e/anyio-4.11.0-py3-none-any.whl", hash = "sha256:0287e96f4d26d4149305414d4e3bc32f0dcd0862365a4bddea19d7a1ec38c4fc", size = 109097, upload-time = "2025-09-23T09:19:10.601Z" }, ] -[[package]] -name = "argcomplete" -version = "3.6.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/38/61/0b9ae6399dd4a58d8c1b1dc5a27d6f2808023d0b5dd3104bb99f45a33ff6/argcomplete-3.6.3.tar.gz", hash = "sha256:62e8ed4fd6a45864acc8235409461b72c9a28ee785a2011cc5eb78318786c89c", size = 73754, upload-time = "2025-10-20T03:33:34.741Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/74/f5/9373290775639cb67a2fce7f629a1c240dce9f12fe927bc32b2736e16dfc/argcomplete-3.6.3-py3-none-any.whl", hash = "sha256:f5007b3a600ccac5d25bbce33089211dfd49eab4a7718da3f10e3082525a92ce", size = 43846, upload-time = "2025-10-20T03:33:33.021Z" }, -] - [[package]] name = "ast-grep-py" version = "0.40.0" @@ -682,7 +661,7 @@ dependencies = [ { name = "psutil" }, { name = "py-cpuinfo" }, { name = "pydantic" }, - { name = "pydantic-ai" }, + { name = "pydantic-ai-slim" }, { name = "pydantic-graph" }, { name = "pydantic-settings", extra = ["toml", "yaml"] }, { name = "qdrant-client" }, @@ -702,6 +681,9 @@ dependencies = [ ] [package.optional-dependencies] +anthropic = [ + { name = "pydantic-ai-slim", extra = ["anthropic"] }, +] auth-eunomia = [ { name = "eunomia-mcp" }, ] @@ -714,9 +696,28 @@ aws-secrets-manager = [ azure-key-vault = [ { name = "pydantic-settings", extra = ["azure-key-vault", "toml", "yaml"] }, ] +bedrock = [ + { name = "pydantic-ai-slim", extra = ["bedrock"] }, + { name = "types-boto3-custom" }, +] +cohere = [ + { name = "pydantic-ai-slim", extra = ["cohere"] }, +] +duckduckgo = [ + { name = "pydantic-ai-slim", extra = ["duckduckgo"] }, +] +fastembed = [ + { name = "fastembed" }, + { name = "py-cpuinfo" }, +] +fastembed-gpu = [ + { name = "fastembed-gpu" }, + { name = "py-cpuinfo" }, +] full = [ { name = "eunomia-mcp" }, { name = "permit-fastmcp" }, + { name = "pydantic-ai-slim", extra = ["anthropic", "bedrock", "cohere", "duckduckgo", "google", "groq", "huggingface", "mistral", "openai", "retries", "tavily"] }, { name = "pydantic-settings", extra = ["aws-secrets-manager", "azure-key-vault", "gcp-secret-manager", "toml", "yaml"] }, { name = "sentence-transformers" }, { name = "types-boto3-custom" }, @@ -731,67 +732,46 @@ full-gpu = [ gcp-secret-manager = [ { name = "pydantic-settings", extra = ["gcp-secret-manager", "toml", "yaml"] }, ] -gpu-support = [ - { name = "fastembed-gpu" }, -] -provider-anthropic = [ - { name = "pydantic-ai-slim", extra = ["anthropic"] }, -] -provider-bedrock = [ - { name = "pydantic-ai-slim", extra = ["bedrock"] }, - { name = "types-boto3-custom" }, -] -provider-cohere = [ - { name = "pydantic-ai-slim", extra = ["cohere"] }, -] -provider-fastembed = [ - { name = "fastembed" }, - { name = "py-cpuinfo" }, +google = [ + { name = "pydantic-ai-slim", extra = ["google"] }, ] -provider-fastembed-gpu = [ +gpu-support = [ { name = "fastembed-gpu" }, - { name = "py-cpuinfo" }, ] -provider-google = [ - { name = "pydantic-ai-slim", extra = ["google"] }, -] -provider-groq = [ +groq = [ { name = "pydantic-ai-slim", extra = ["groq"] }, ] -provider-huggingface = [ +huggingface = [ { name = "pydantic-ai-slim", extra = ["huggingface"] }, ] -provider-in-memory = [ +in-memory = [ { name = "qdrant-client" }, { name = "tokenizers" }, ] -provider-mistral = [ +mistral = [ { name = "pydantic-ai-slim", extra = ["mistral"] }, ] -provider-openai = [ +openai = [ { name = "pydantic-ai-slim", extra = ["openai"] }, ] -provider-qdrant = [ +qdrant = [ { name = "qdrant-client" }, ] -provider-sentence-transformers = [ - { name = "py-cpuinfo" }, - { name = "sentence-transformers" }, -] -provider-voyageai = [ - { name = "voyageai" }, -] recommended-local-only = [ { name = "fastembed" }, { name = "sentence-transformers" }, { name = "tokenizers" }, ] -source-duckduckgo = [ - { name = "pydantic-ai-slim", extra = ["duckduckgo"] }, +sentence-transformers = [ + { name = "py-cpuinfo" }, + { name = "sentence-transformers" }, ] -source-tavily = [ +tavily = [ { name = "pydantic-ai-slim", extra = ["tavily"] }, ] +voyageai = [ + { name = "voyageai" }, +] [package.dev-dependencies] build = [ @@ -835,16 +815,16 @@ requires-dist = [ { name = "aenum", specifier = ">=3.1.16" }, { name = "ast-grep-py", specifier = ">=0.40.0" }, { name = "blake3", specifier = ">=1.0.8" }, - { name = "cyclopts", specifier = ">=4.2.4" }, + { name = "cyclopts", specifier = ">=4.3.0" }, { name = "eunomia-mcp", marker = "extra == 'auth-eunomia'" }, { name = "eunomia-mcp", marker = "extra == 'full'" }, { name = "eunomia-mcp", marker = "extra == 'full-gpu'" }, - { name = "fastembed", specifier = ">=0.7.3" }, - { name = "fastembed", marker = "extra == 'provider-fastembed'" }, + { name = "fastembed", specifier = ">=0.7.4" }, + { name = "fastembed", marker = "extra == 'fastembed'" }, { name = "fastembed", marker = "extra == 'recommended-local-only'" }, + { name = "fastembed-gpu", marker = "extra == 'fastembed-gpu'" }, { name = "fastembed-gpu", marker = "extra == 'full-gpu'" }, { name = "fastembed-gpu", marker = "extra == 'gpu-support'" }, - { name = "fastembed-gpu", marker = "extra == 'provider-fastembed-gpu'" }, { name = "fastmcp", specifier = ">=2.13.3" }, { name = "httpx", extras = ["http2"], specifier = ">=0.28.1" }, { name = "mcp", specifier = ">=1.19.0" }, @@ -878,32 +858,32 @@ requires-dist = [ { name = "pydantic-settings", extras = ["gcp-secret-manager", "toml", "yaml"], marker = "extra == 'gcp-secret-manager'" }, { name = "pydantic-settings", extras = ["toml", "yaml"], specifier = ">=2.12.0" }, { name = "qdrant-client", specifier = ">=1.16.1" }, - { name = "qdrant-client", marker = "extra == 'provider-in-memory'" }, - { name = "qdrant-client", marker = "extra == 'provider-qdrant'" }, + { name = "qdrant-client", marker = "extra == 'in-memory'" }, + { name = "qdrant-client", marker = "extra == 'qdrant'" }, { name = "rich", specifier = ">=14.2.0" }, { name = "rignore", specifier = ">=0.7.6" }, { name = "sentence-transformers", marker = "extra == 'full'", specifier = ">=5.1.2" }, { name = "sentence-transformers", marker = "extra == 'full-gpu'" }, - { name = "sentence-transformers", marker = "extra == 'provider-sentence-transformers'" }, { name = "sentence-transformers", marker = "extra == 'recommended-local-only'" }, + { name = "sentence-transformers", marker = "extra == 'sentence-transformers'" }, { name = "tenacity", specifier = ">=9.1.2" }, { name = "textcase", specifier = ">=0.4.5" }, { name = "tiktoken", specifier = ">=0.12.0" }, { name = "tokenizers", specifier = ">=0.22.1" }, - { name = "tokenizers", marker = "extra == 'provider-in-memory'" }, + { name = "tokenizers", marker = "extra == 'in-memory'" }, { name = "tokenizers", marker = "extra == 'recommended-local-only'" }, { name = "tomli-w", specifier = ">=1.2.0" }, + { name = "types-boto3-custom", marker = "extra == 'bedrock'", path = "vendored/types_boto3_custom-1.41.2-py3-none-any.whl" }, { name = "types-boto3-custom", marker = "extra == 'full'", path = "vendored/types_boto3_custom-1.41.2-py3-none-any.whl" }, - { name = "types-boto3-custom", marker = "extra == 'provider-bedrock'", path = "vendored/types_boto3_custom-1.41.2-py3-none-any.whl" }, { name = "typing-extensions", specifier = ">=4.15.0" }, { name = "uuid7", marker = "python_full_version < '3.14'", specifier = ">=0.1.0" }, { name = "uvicorn", extras = ["standard"], specifier = ">=0.38.0" }, { name = "uvloop", marker = "platform_python_implementation == 'CPython' and sys_platform != 'win32'", specifier = ">=0.22.1" }, { name = "voyageai", specifier = ">=0.3.5" }, - { name = "voyageai", marker = "extra == 'provider-voyageai'" }, + { name = "voyageai", marker = "extra == 'voyageai'" }, { name = "watchfiles", specifier = ">=1.1.1" }, ] -provides-extras = ["auth-eunomia", "auth-permitio", "aws-secrets-manager", "azure-key-vault", "full", "full-gpu", "gcp-secret-manager", "gpu-support", "provider-anthropic", "provider-bedrock", "provider-cohere", "provider-fastembed", "provider-fastembed-gpu", "provider-google", "provider-groq", "provider-huggingface", "provider-in-memory", "provider-mistral", "provider-openai", "provider-qdrant", "provider-sentence-transformers", "provider-voyageai", "recommended-local-only", "source-duckduckgo", "source-tavily"] +provides-extras = ["anthropic", "auth-eunomia", "auth-permitio", "aws-secrets-manager", "azure-key-vault", "bedrock", "cohere", "duckduckgo", "fastembed", "fastembed-gpu", "full", "full-gpu", "gcp-secret-manager", "google", "gpu-support", "groq", "huggingface", "in-memory", "mistral", "openai", "qdrant", "recommended-local-only", "sentence-transformers", "tavily", "voyageai"] [package.metadata.requires-dev] build = [ @@ -1113,7 +1093,7 @@ wheels = [ [[package]] name = "cyclopts" -version = "4.2.4" +version = "4.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -1121,9 +1101,9 @@ dependencies = [ { name = "rich" }, { name = "rich-rst" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/eb/08/f20fe40a5db9cd1c42316de5a26209dd008f30d38eea297f94e744dea463/cyclopts-4.2.4.tar.gz", hash = "sha256:27e1d175df2889aba72cd960c4e34c8b0a501c5b0161e849c72d9fee5903ecbb", size = 149362, upload-time = "2025-11-14T21:38:46.722Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/0f/fe026df2ab8301e30a2b0bd425ff1462ad858fd4f991c1ac0389c2059c24/cyclopts-4.3.0.tar.gz", hash = "sha256:e95179cd0a959ce250ecfb2f0262a5996a92c1f9467bccad2f3d829e6833cef5", size = 151411, upload-time = "2025-11-25T02:59:33.572Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/b2/fabcd6020b63b9d9f7a79cfc61b9c03c4e08ccb54f9cf9db9791be5669ef/cyclopts-4.2.4-py3-none-any.whl", hash = "sha256:41054f5e921a4f2b8ab9c839f12a274dec06a19560dc4898ce37cb775ca68ca4", size = 185023, upload-time = "2025-11-14T21:38:45.659Z" }, + { url = "https://files.pythonhosted.org/packages/7a/e8/77a231ae531cf38765b75ddf27dae28bb5f70b41d8bb4f15ce1650e93f57/cyclopts-4.3.0-py3-none-any.whl", hash = "sha256:91a30b69faf128ada7cfeaefd7d9649dc222e8b2a8697f1fc99e4ee7b7ca44f3", size = 187184, upload-time = "2025-11-25T02:59:32.21Z" }, ] [[package]] @@ -1359,7 +1339,7 @@ wheels = [ [[package]] name = "fastembed" -version = "0.7.3" +version = "0.7.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "huggingface-hub" }, @@ -1373,9 +1353,9 @@ dependencies = [ { name = "tokenizers" }, { name = "tqdm" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/65/f6/e8d3d9d487f95b698c9ff0d04d4e050d8fca9fa4cba58cff60fd519d1976/fastembed-0.7.3.tar.gz", hash = "sha256:04e95eb5ccc706513166c23bf8e5429ed160c5783b7b11514431a77624d480a5", size = 66561, upload-time = "2025-08-29T11:19:46.521Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/c2/9c708680de1b54480161e0505f9d6d3d8eb47a1dc1a1f7f3c5106ba355d2/fastembed-0.7.4.tar.gz", hash = "sha256:8b8a4ea860ca295002f4754e8f5820a636e1065a9444959e18d5988d7f27093b", size = 68807, upload-time = "2025-12-05T12:08:10.447Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/19/38/447aabefddda026c3b65b3b9f1fec48ab78b648441e3e530bf8d78b26bdf/fastembed-0.7.3-py3-none-any.whl", hash = "sha256:a377b57843abd773318042960be39f1aef29827530acb98b035a554742a85cdf", size = 105322, upload-time = "2025-08-29T11:19:45.4Z" }, + { url = "https://files.pythonhosted.org/packages/10/3b/8da01492bc8b69184257d0c951bf0e77aec8ce110f06d8ce16c6ed9084f7/fastembed-0.7.4-py3-none-any.whl", hash = "sha256:79250a775f70bd6addb0e054204df042b5029ecae501e40e5bbd08e75844ad83", size = 108491, upload-time = "2025-12-05T12:08:09.059Z" }, ] [[package]] @@ -2324,29 +2304,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/5c/521a3d8295e2e7caea67032e65554866293b6dc8e934bd86be8cc1f7b955/langsmith-0.4.43-py3-none-any.whl", hash = "sha256:c97846a0b15061bc15844aac32fd1ce4a8e50983905f80a0d6079bb41b112ae3", size = 410232, upload-time = "2025-11-15T00:32:10.557Z" }, ] -[[package]] -name = "logfire" -version = "4.14.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "executing" }, - { name = "opentelemetry-exporter-otlp-proto-http" }, - { name = "opentelemetry-instrumentation" }, - { name = "opentelemetry-sdk" }, - { name = "protobuf" }, - { name = "rich" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5c/89/d26951b6b21790641720c12cfd6dca0cf7ead0f5ddd7de4299837b90b8b1/logfire-4.14.2.tar.gz", hash = "sha256:8dcedbd59c3d06a8794a93bbf09add788de3b74c45afa821750992f0c822c628", size = 548291, upload-time = "2025-10-24T20:14:39.115Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/92/4fba7b8f4f56f721ad279cb0c08164bffa14e93cfd184d1a4cc7151c52a2/logfire-4.14.2-py3-none-any.whl", hash = "sha256:caa8111b20f263f4ebb0ae380a62f2a214aeb07d5e2f03c9300fa096d0a8e692", size = 228364, upload-time = "2025-10-24T20:14:34.495Z" }, -] - -[package.optional-dependencies] -httpx = [ - { name = "opentelemetry-instrumentation-httpx" }, -] - [[package]] name = "logfire-api" version = "4.14.2" @@ -2848,18 +2805,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/eb/8d/776adee7bbf76365fdd7f2552710282c79a4ead5d2a46408c9043a2b70ba/networkx-3.5-py3-none-any.whl", hash = "sha256:0030d386a9a06dee3565298b4a734b68589749a544acbb6c412dc9e2489ec6ec", size = 2034406, upload-time = "2025-05-29T11:35:04.961Z" }, ] -[[package]] -name = "nexus-rpc" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ef/66/540687556bd28cf1ec370cc6881456203dfddb9dab047b8979c6865b5984/nexus_rpc-1.1.0.tar.gz", hash = "sha256:d65ad6a2f54f14e53ebe39ee30555eaeb894102437125733fb13034a04a44553", size = 77383, upload-time = "2025-07-07T19:03:58.368Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/2f/9e9d0dcaa4c6ffa22b7aa31069a8a264c753ff8027b36af602cce038c92f/nexus_rpc-1.1.0-py3-none-any.whl", hash = "sha256:d1b007af2aba186a27e736f8eaae39c03aed05b488084ff6c3d1785c9ba2ad38", size = 27743, upload-time = "2025-07-07T19:03:57.556Z" }, -] - [[package]] name = "nh3" version = "0.3.2" @@ -3181,115 +3126,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ae/a2/d86e01c28300bd41bab8f18afd613676e2bd63515417b77636fc1add426f/opentelemetry_api-1.38.0-py3-none-any.whl", hash = "sha256:2891b0197f47124454ab9f0cf58f3be33faca394457ac3e09daba13ff50aa582", size = 65947, upload-time = "2025-10-16T08:35:30.23Z" }, ] -[[package]] -name = "opentelemetry-exporter-otlp-proto-common" -version = "1.38.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "opentelemetry-proto" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/19/83/dd4660f2956ff88ed071e9e0e36e830df14b8c5dc06722dbde1841accbe8/opentelemetry_exporter_otlp_proto_common-1.38.0.tar.gz", hash = "sha256:e333278afab4695aa8114eeb7bf4e44e65c6607d54968271a249c180b2cb605c", size = 20431, upload-time = "2025-10-16T08:35:53.285Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/9e/55a41c9601191e8cd8eb626b54ee6827b9c9d4a46d736f32abc80d8039fc/opentelemetry_exporter_otlp_proto_common-1.38.0-py3-none-any.whl", hash = "sha256:03cb76ab213300fe4f4c62b7d8f17d97fcfd21b89f0b5ce38ea156327ddda74a", size = 18359, upload-time = "2025-10-16T08:35:34.099Z" }, -] - -[[package]] -name = "opentelemetry-exporter-otlp-proto-http" -version = "1.38.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "googleapis-common-protos" }, - { name = "opentelemetry-api" }, - { name = "opentelemetry-exporter-otlp-proto-common" }, - { name = "opentelemetry-proto" }, - { name = "opentelemetry-sdk" }, - { name = "requests" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/81/0a/debcdfb029fbd1ccd1563f7c287b89a6f7bef3b2902ade56797bfd020854/opentelemetry_exporter_otlp_proto_http-1.38.0.tar.gz", hash = "sha256:f16bd44baf15cbe07633c5112ffc68229d0edbeac7b37610be0b2def4e21e90b", size = 17282, upload-time = "2025-10-16T08:35:54.422Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/77/154004c99fb9f291f74aa0822a2f5bbf565a72d8126b3a1b63ed8e5f83c7/opentelemetry_exporter_otlp_proto_http-1.38.0-py3-none-any.whl", hash = "sha256:84b937305edfc563f08ec69b9cb2298be8188371217e867c1854d77198d0825b", size = 19579, upload-time = "2025-10-16T08:35:36.269Z" }, -] - -[[package]] -name = "opentelemetry-instrumentation" -version = "0.59b0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "opentelemetry-api" }, - { name = "opentelemetry-semantic-conventions" }, - { name = "packaging" }, - { name = "wrapt" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/04/ed/9c65cd209407fd807fa05be03ee30f159bdac8d59e7ea16a8fe5a1601222/opentelemetry_instrumentation-0.59b0.tar.gz", hash = "sha256:6010f0faaacdaf7c4dff8aac84e226d23437b331dcda7e70367f6d73a7db1adc", size = 31544, upload-time = "2025-10-16T08:39:31.959Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/10/f5/7a40ff3f62bfe715dad2f633d7f1174ba1a7dd74254c15b2558b3401262a/opentelemetry_instrumentation-0.59b0-py3-none-any.whl", hash = "sha256:44082cc8fe56b0186e87ee8f7c17c327c4c2ce93bdbe86496e600985d74368ee", size = 33020, upload-time = "2025-10-16T08:38:31.463Z" }, -] - -[[package]] -name = "opentelemetry-instrumentation-httpx" -version = "0.59b0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "opentelemetry-api" }, - { name = "opentelemetry-instrumentation" }, - { name = "opentelemetry-semantic-conventions" }, - { name = "opentelemetry-util-http" }, - { name = "wrapt" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/18/6b/1bdf36b68cace9b4eae3cbbade4150c71c90aa392b127dda5bb5c2a49307/opentelemetry_instrumentation_httpx-0.59b0.tar.gz", hash = "sha256:a1cb9b89d9f05a82701cc9ab9cfa3db54fd76932489449778b350bc1b9f0e872", size = 19886, upload-time = "2025-10-16T08:39:48.428Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/58/16/c1e0745d20af392ec9060693531d7f01239deb2d81e460d0c379719691b8/opentelemetry_instrumentation_httpx-0.59b0-py3-none-any.whl", hash = "sha256:7dc9f66aef4ca3904d877f459a70c78eafd06131dc64d713b9b1b5a7d0a48f05", size = 15197, upload-time = "2025-10-16T08:38:55.507Z" }, -] - -[[package]] -name = "opentelemetry-proto" -version = "1.38.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/51/14/f0c4f0f6371b9cb7f9fa9ee8918bfd59ac7040c7791f1e6da32a1839780d/opentelemetry_proto-1.38.0.tar.gz", hash = "sha256:88b161e89d9d372ce723da289b7da74c3a8354a8e5359992be813942969ed468", size = 46152, upload-time = "2025-10-16T08:36:01.612Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b6/6a/82b68b14efca5150b2632f3692d627afa76b77378c4999f2648979409528/opentelemetry_proto-1.38.0-py3-none-any.whl", hash = "sha256:b6ebe54d3217c42e45462e2a1ae28c3e2bf2ec5a5645236a490f55f45f1a0a18", size = 72535, upload-time = "2025-10-16T08:35:45.749Z" }, -] - -[[package]] -name = "opentelemetry-sdk" -version = "1.38.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "opentelemetry-api" }, - { name = "opentelemetry-semantic-conventions" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/85/cb/f0eee1445161faf4c9af3ba7b848cc22a50a3d3e2515051ad8628c35ff80/opentelemetry_sdk-1.38.0.tar.gz", hash = "sha256:93df5d4d871ed09cb4272305be4d996236eedb232253e3ab864c8620f051cebe", size = 171942, upload-time = "2025-10-16T08:36:02.257Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/2e/e93777a95d7d9c40d270a371392b6d6f1ff170c2a3cb32d6176741b5b723/opentelemetry_sdk-1.38.0-py3-none-any.whl", hash = "sha256:1c66af6564ecc1553d72d811a01df063ff097cdc82ce188da9951f93b8d10f6b", size = 132349, upload-time = "2025-10-16T08:35:46.995Z" }, -] - -[[package]] -name = "opentelemetry-semantic-conventions" -version = "0.59b0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "opentelemetry-api" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/40/bc/8b9ad3802cd8ac6583a4eb7de7e5d7db004e89cb7efe7008f9c8a537ee75/opentelemetry_semantic_conventions-0.59b0.tar.gz", hash = "sha256:7a6db3f30d70202d5bf9fa4b69bc866ca6a30437287de6c510fb594878aed6b0", size = 129861, upload-time = "2025-10-16T08:36:03.346Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/24/7d/c88d7b15ba8fe5c6b8f93be50fc11795e9fc05386c44afaf6b76fe191f9b/opentelemetry_semantic_conventions-0.59b0-py3-none-any.whl", hash = "sha256:35d3b8833ef97d614136e253c1da9342b4c3c083bbaf29ce31d572a1c3825eed", size = 207954, upload-time = "2025-10-16T08:35:48.054Z" }, -] - -[[package]] -name = "opentelemetry-util-http" -version = "0.59b0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/34/f7/13cd081e7851c42520ab0e96efb17ffbd901111a50b8252ec1e240664020/opentelemetry_util_http-0.59b0.tar.gz", hash = "sha256:ae66ee91be31938d832f3b4bc4eb8a911f6eddd38969c4a871b1230db2a0a560", size = 9412, upload-time = "2025-10-16T08:40:11.335Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/20/56/62282d1d4482061360449dacc990c89cad0fc810a2ed937b636300f55023/opentelemetry_util_http-0.59b0-py3-none-any.whl", hash = "sha256:6d036a07563bce87bf521839c0671b507a02a0d39d7ea61b88efa14c6e25355d", size = 7648, upload-time = "2025-10-16T08:39:25.706Z" }, -] - [[package]] name = "orjson" version = "3.11.4" @@ -3865,18 +3701,6 @@ email = [ { name = "email-validator" }, ] -[[package]] -name = "pydantic-ai" -version = "1.27.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pydantic-ai-slim", extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "fastmcp", "google", "groq", "huggingface", "logfire", "mcp", "mistral", "openai", "retries", "temporal", "ui", "vertexai"] }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e3/7f/c56413e9dd3a1f4330981bc4f261f2edb22d3c19480102fdf50e590a5fd7/pydantic_ai-1.27.0.tar.gz", hash = "sha256:6741111d0be19c0fb5f9612beab5af12b945ce715780b19e861fe104e656d61d", size = 11862, upload-time = "2025-12-05T03:23:03.818Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/39/6f/dfa4a1895b5011b0daff684198226d6a16be1f1104a4e7e9f8b1377c4ab0/pydantic_ai-1.27.0-py3-none-any.whl", hash = "sha256:cdb77c1a1f6569c42483ba05b1da99aa3b5f7f9042ad3492b5dac741f45d5450", size = 7167, upload-time = "2025-12-05T03:22:54.825Z" }, -] - [[package]] name = "pydantic-ai-slim" version = "1.27.0" @@ -3896,34 +3720,18 @@ wheels = [ ] [package.optional-dependencies] -ag-ui = [ - { name = "ag-ui-protocol" }, - { name = "starlette" }, -] anthropic = [ { name = "anthropic" }, ] bedrock = [ { name = "boto3" }, ] -cli = [ - { name = "argcomplete" }, - { name = "prompt-toolkit" }, - { name = "pyperclip" }, - { name = "rich" }, -] cohere = [ { name = "cohere", marker = "sys_platform != 'emscripten'" }, ] duckduckgo = [ { name = "ddgs" }, ] -evals = [ - { name = "pydantic-evals" }, -] -fastmcp = [ - { name = "fastmcp" }, -] google = [ { name = "google-genai" }, ] @@ -3933,12 +3741,6 @@ groq = [ huggingface = [ { name = "huggingface-hub", extra = ["inference"] }, ] -logfire = [ - { name = "logfire", extra = ["httpx"] }, -] -mcp = [ - { name = "mcp" }, -] mistral = [ { name = "mistralai" }, ] @@ -3951,16 +3753,6 @@ retries = [ tavily = [ { name = "tavily-python" }, ] -temporal = [ - { name = "temporalio" }, -] -ui = [ - { name = "starlette" }, -] -vertexai = [ - { name = "google-auth" }, - { name = "requests" }, -] [[package]] name = "pydantic-core" @@ -4033,23 +3825,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, ] -[[package]] -name = "pydantic-evals" -version = "1.27.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "logfire-api" }, - { name = "pydantic" }, - { name = "pydantic-ai-slim" }, - { name = "pyyaml" }, - { name = "rich" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b6/75/f668b4d83e3c6d6806b37f97b84397ca1667a559147d8d4133a3665db55d/pydantic_evals-1.27.0.tar.gz", hash = "sha256:d8f08c4a61c7adea8cabd84368d3acde88f196162ab37ca1f99ffbbac6872f8f", size = 47078, upload-time = "2025-12-05T03:23:08.792Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/b0/1fcde1b8263ec681a46e1af1a6a01850ed25ae856db52c477b127d12947e/pydantic_evals-1.27.0-py3-none-any.whl", hash = "sha256:086b3264c6602dceddaeb66ee18df7f9a3d5def2acd27d5251018bc95430c47e", size = 56225, upload-time = "2025-12-05T03:22:59.876Z" }, -] - [[package]] name = "pydantic-graph" version = "1.27.0" @@ -5030,24 +4805,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/55/4d/e5e4c65cd66144ac3d0d5a6a2bbfba22eb6a63e6e450beba10ee8413b86d/tavily_python-0.7.13-py3-none-any.whl", hash = "sha256:911825467f2bb19b8162b4766d3e81081160a7c0fb8a15c7c716b2bef73e6296", size = 15484, upload-time = "2025-11-13T18:53:02.821Z" }, ] -[[package]] -name = "temporalio" -version = "1.19.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "nexus-rpc" }, - { name = "protobuf" }, - { name = "types-protobuf" }, - { name = "typing-extensions" }, -] -wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/92/0775d831fa245d61b74db2059d5a24a04cef0532ed2c48310a5ab007de9c/temporalio-1.19.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c2d6d5cad8aec56e048705aa4f0bab83fec15343757ea7acf8504f2e0c289b60", size = 13175255, upload-time = "2025-11-13T22:35:54.22Z" }, - { url = "https://files.pythonhosted.org/packages/e2/e1/2a818fefc0023eb132bfff1a03440bcaff154d4d97445ef88a40c23c20c8/temporalio-1.19.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:d85c89018cba9471ce529d90c9cee5bcc31790fd64176b9ada32cc76440f8d73", size = 12854549, upload-time = "2025-11-13T22:35:57.217Z" }, - { url = "https://files.pythonhosted.org/packages/ff/78/fe5c8c9b112b38e01aba845335df17a8bbfd60a434ffe3c1c4737ced40a0/temporalio-1.19.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f772f0698d60f808bc3c4a055fb53e40d757fa646411845b911863eebbf0549d", size = 13237772, upload-time = "2025-11-13T22:36:00.511Z" }, - { url = "https://files.pythonhosted.org/packages/d9/82/be0fd31119651f518f8db8685fd61976d9d5bbecf3b562d51f13a6442a17/temporalio-1.19.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f706c8f49771daf342ac8daa8ed07f4124fae943177f9feef458a1255aee717c", size = 13374621, upload-time = "2025-11-13T22:36:03.431Z" }, - { url = "https://files.pythonhosted.org/packages/d8/94/18f6ae06ffd91507ded9111af1041146a5ba4b56e9256520c5ce82629fc4/temporalio-1.19.0-cp310-abi3-win_amd64.whl", hash = "sha256:162459c293553be39994f20c635a132f7332ae71bd7ba4042f8473701fcf1c7c", size = 14256891, upload-time = "2025-11-13T22:36:06.778Z" }, -] - [[package]] name = "tenacity" version = "9.1.2" @@ -5409,15 +5166,6 @@ requires-dist = [ { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] -[[package]] -name = "types-protobuf" -version = "6.32.1.20251105" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f3/ab/0dce6a9841b5ebf3e37401879bb8cc20724ad9c770a7649bee997696cc75/types_protobuf-6.32.1.20251105.tar.gz", hash = "sha256:641002611ff87dd9fedc38a39a29cacb9907ae5ce61489b53e99ca2074bef764", size = 63846, upload-time = "2025-11-05T03:04:43.456Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/57/3a0d89b33b7485b7ffd99ec7cf53b0c5c89194c481f0bd673fd67e5f273f/types_protobuf-6.32.1.20251105-py3-none-any.whl", hash = "sha256:a15109d38f7cfefd2539ef86d3f93a6a41c7cad53924f8aa1a51eaddbb72a660", size = 77890, upload-time = "2025-11-05T03:04:42.067Z" }, -] - [[package]] name = "types-requests" version = "2.32.4.20250913" @@ -5714,55 +5462,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e1/07/c6fe3ad3e685340704d314d765b7912993bcb8dc198f0e7a89382d37974b/win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390", size = 4083, upload-time = "2024-12-07T15:28:26.465Z" }, ] -[[package]] -name = "wrapt" -version = "1.17.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0", size = 55547, upload-time = "2025-08-12T05:53:21.714Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9f/41/cad1aba93e752f1f9268c77270da3c469883d56e2798e7df6240dcb2287b/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0", size = 53998, upload-time = "2025-08-12T05:51:47.138Z" }, - { url = "https://files.pythonhosted.org/packages/60/f8/096a7cc13097a1869fe44efe68dace40d2a16ecb853141394047f0780b96/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba", size = 39020, upload-time = "2025-08-12T05:51:35.906Z" }, - { url = "https://files.pythonhosted.org/packages/33/df/bdf864b8997aab4febb96a9ae5c124f700a5abd9b5e13d2a3214ec4be705/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd", size = 39098, upload-time = "2025-08-12T05:51:57.474Z" }, - { url = "https://files.pythonhosted.org/packages/9f/81/5d931d78d0eb732b95dc3ddaeeb71c8bb572fb01356e9133916cd729ecdd/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828", size = 88036, upload-time = "2025-08-12T05:52:34.784Z" }, - { url = "https://files.pythonhosted.org/packages/ca/38/2e1785df03b3d72d34fc6252d91d9d12dc27a5c89caef3335a1bbb8908ca/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9", size = 88156, upload-time = "2025-08-12T05:52:13.599Z" }, - { url = "https://files.pythonhosted.org/packages/b3/8b/48cdb60fe0603e34e05cffda0b2a4adab81fd43718e11111a4b0100fd7c1/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396", size = 87102, upload-time = "2025-08-12T05:52:14.56Z" }, - { url = "https://files.pythonhosted.org/packages/3c/51/d81abca783b58f40a154f1b2c56db1d2d9e0d04fa2d4224e357529f57a57/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc", size = 87732, upload-time = "2025-08-12T05:52:36.165Z" }, - { url = "https://files.pythonhosted.org/packages/9e/b1/43b286ca1392a006d5336412d41663eeef1ad57485f3e52c767376ba7e5a/wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe", size = 36705, upload-time = "2025-08-12T05:53:07.123Z" }, - { url = "https://files.pythonhosted.org/packages/28/de/49493f962bd3c586ab4b88066e967aa2e0703d6ef2c43aa28cb83bf7b507/wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c", size = 38877, upload-time = "2025-08-12T05:53:05.436Z" }, - { url = "https://files.pythonhosted.org/packages/f1/48/0f7102fe9cb1e8a5a77f80d4f0956d62d97034bbe88d33e94699f99d181d/wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6", size = 36885, upload-time = "2025-08-12T05:52:54.367Z" }, - { url = "https://files.pythonhosted.org/packages/fc/f6/759ece88472157acb55fc195e5b116e06730f1b651b5b314c66291729193/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0", size = 54003, upload-time = "2025-08-12T05:51:48.627Z" }, - { url = "https://files.pythonhosted.org/packages/4f/a9/49940b9dc6d47027dc850c116d79b4155f15c08547d04db0f07121499347/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77", size = 39025, upload-time = "2025-08-12T05:51:37.156Z" }, - { url = "https://files.pythonhosted.org/packages/45/35/6a08de0f2c96dcdd7fe464d7420ddb9a7655a6561150e5fc4da9356aeaab/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7", size = 39108, upload-time = "2025-08-12T05:51:58.425Z" }, - { url = "https://files.pythonhosted.org/packages/0c/37/6faf15cfa41bf1f3dba80cd3f5ccc6622dfccb660ab26ed79f0178c7497f/wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277", size = 88072, upload-time = "2025-08-12T05:52:37.53Z" }, - { url = "https://files.pythonhosted.org/packages/78/f2/efe19ada4a38e4e15b6dff39c3e3f3f73f5decf901f66e6f72fe79623a06/wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d", size = 88214, upload-time = "2025-08-12T05:52:15.886Z" }, - { url = "https://files.pythonhosted.org/packages/40/90/ca86701e9de1622b16e09689fc24b76f69b06bb0150990f6f4e8b0eeb576/wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa", size = 87105, upload-time = "2025-08-12T05:52:17.914Z" }, - { url = "https://files.pythonhosted.org/packages/fd/e0/d10bd257c9a3e15cbf5523025252cc14d77468e8ed644aafb2d6f54cb95d/wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050", size = 87766, upload-time = "2025-08-12T05:52:39.243Z" }, - { url = "https://files.pythonhosted.org/packages/e8/cf/7d848740203c7b4b27eb55dbfede11aca974a51c3d894f6cc4b865f42f58/wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8", size = 36711, upload-time = "2025-08-12T05:53:10.074Z" }, - { url = "https://files.pythonhosted.org/packages/57/54/35a84d0a4d23ea675994104e667ceff49227ce473ba6a59ba2c84f250b74/wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb", size = 38885, upload-time = "2025-08-12T05:53:08.695Z" }, - { url = "https://files.pythonhosted.org/packages/01/77/66e54407c59d7b02a3c4e0af3783168fff8e5d61def52cda8728439d86bc/wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16", size = 36896, upload-time = "2025-08-12T05:52:55.34Z" }, - { url = "https://files.pythonhosted.org/packages/02/a2/cd864b2a14f20d14f4c496fab97802001560f9f41554eef6df201cd7f76c/wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39", size = 54132, upload-time = "2025-08-12T05:51:49.864Z" }, - { url = "https://files.pythonhosted.org/packages/d5/46/d011725b0c89e853dc44cceb738a307cde5d240d023d6d40a82d1b4e1182/wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235", size = 39091, upload-time = "2025-08-12T05:51:38.935Z" }, - { url = "https://files.pythonhosted.org/packages/2e/9e/3ad852d77c35aae7ddebdbc3b6d35ec8013af7d7dddad0ad911f3d891dae/wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c", size = 39172, upload-time = "2025-08-12T05:51:59.365Z" }, - { url = "https://files.pythonhosted.org/packages/c3/f7/c983d2762bcce2326c317c26a6a1e7016f7eb039c27cdf5c4e30f4160f31/wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b", size = 87163, upload-time = "2025-08-12T05:52:40.965Z" }, - { url = "https://files.pythonhosted.org/packages/e4/0f/f673f75d489c7f22d17fe0193e84b41540d962f75fce579cf6873167c29b/wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa", size = 87963, upload-time = "2025-08-12T05:52:20.326Z" }, - { url = "https://files.pythonhosted.org/packages/df/61/515ad6caca68995da2fac7a6af97faab8f78ebe3bf4f761e1b77efbc47b5/wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7", size = 86945, upload-time = "2025-08-12T05:52:21.581Z" }, - { url = "https://files.pythonhosted.org/packages/d3/bd/4e70162ce398462a467bc09e768bee112f1412e563620adc353de9055d33/wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4", size = 86857, upload-time = "2025-08-12T05:52:43.043Z" }, - { url = "https://files.pythonhosted.org/packages/2b/b8/da8560695e9284810b8d3df8a19396a6e40e7518059584a1a394a2b35e0a/wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10", size = 37178, upload-time = "2025-08-12T05:53:12.605Z" }, - { url = "https://files.pythonhosted.org/packages/db/c8/b71eeb192c440d67a5a0449aaee2310a1a1e8eca41676046f99ed2487e9f/wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6", size = 39310, upload-time = "2025-08-12T05:53:11.106Z" }, - { url = "https://files.pythonhosted.org/packages/45/20/2cda20fd4865fa40f86f6c46ed37a2a8356a7a2fde0773269311f2af56c7/wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58", size = 37266, upload-time = "2025-08-12T05:52:56.531Z" }, - { url = "https://files.pythonhosted.org/packages/77/ed/dd5cf21aec36c80443c6f900449260b80e2a65cf963668eaef3b9accce36/wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a", size = 56544, upload-time = "2025-08-12T05:51:51.109Z" }, - { url = "https://files.pythonhosted.org/packages/8d/96/450c651cc753877ad100c7949ab4d2e2ecc4d97157e00fa8f45df682456a/wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067", size = 40283, upload-time = "2025-08-12T05:51:39.912Z" }, - { url = "https://files.pythonhosted.org/packages/d1/86/2fcad95994d9b572db57632acb6f900695a648c3e063f2cd344b3f5c5a37/wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454", size = 40366, upload-time = "2025-08-12T05:52:00.693Z" }, - { url = "https://files.pythonhosted.org/packages/64/0e/f4472f2fdde2d4617975144311f8800ef73677a159be7fe61fa50997d6c0/wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e", size = 108571, upload-time = "2025-08-12T05:52:44.521Z" }, - { url = "https://files.pythonhosted.org/packages/cc/01/9b85a99996b0a97c8a17484684f206cbb6ba73c1ce6890ac668bcf3838fb/wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f", size = 113094, upload-time = "2025-08-12T05:52:22.618Z" }, - { url = "https://files.pythonhosted.org/packages/25/02/78926c1efddcc7b3aa0bc3d6b33a822f7d898059f7cd9ace8c8318e559ef/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056", size = 110659, upload-time = "2025-08-12T05:52:24.057Z" }, - { url = "https://files.pythonhosted.org/packages/dc/ee/c414501ad518ac3e6fe184753632fe5e5ecacdcf0effc23f31c1e4f7bfcf/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804", size = 106946, upload-time = "2025-08-12T05:52:45.976Z" }, - { url = "https://files.pythonhosted.org/packages/be/44/a1bd64b723d13bb151d6cc91b986146a1952385e0392a78567e12149c7b4/wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977", size = 38717, upload-time = "2025-08-12T05:53:15.214Z" }, - { url = "https://files.pythonhosted.org/packages/79/d9/7cfd5a312760ac4dd8bf0184a6ee9e43c33e47f3dadc303032ce012b8fa3/wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116", size = 41334, upload-time = "2025-08-12T05:53:14.178Z" }, - { url = "https://files.pythonhosted.org/packages/46/78/10ad9781128ed2f99dbc474f43283b13fea8ba58723e98844367531c18e9/wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6", size = 38471, upload-time = "2025-08-12T05:52:57.784Z" }, - { url = "https://files.pythonhosted.org/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22", size = 23591, upload-time = "2025-08-12T05:53:20.674Z" }, -] - [[package]] name = "yarl" version = "1.22.0"