chore(types): mypy strict for locus.rag.* (#34 batch 6 — final)#48
Merged
Conversation
Lifts the last legitimate module group (``locus.rag.*``) out of the mypy ``ignore_errors`` blanket. Covers ~5.7k LOC across the embedding providers, the seven shipped vector stores (Oracle 26ai, OpenSearch, Qdrant, Pinecone, Chroma, pgvector, in-memory), the multimodal processor stack, the retriever, and the tool factories. After this lands, the ``ignore_errors`` block holds **only** ``locus.hooks.builtin.*``, which is held back as a behavioural fix (#45) — the built-in hooks have stale method signatures vs the ``HookProvider`` Protocol and would TypeError at runtime when dispatched through ``HookRegistry``. The mypy migration tracked in #34 is otherwise complete. Notable fixes: - ``rag.tools`` factory functions and ``RAGToolkit`` accessors now return ``Any`` (the ``@tool``-decorated runtime objects don't have a stable user-visible type). - ``rag.retriever``: typed locals on every ``await self.store.*`` delegate so the return annotations are honoured. - ``rag.multimodal.MultimodalProcessor.processors`` declares its value type as ``ContentProcessor`` (the existing Protocol) so the per-type sub-classes share a structural supertype and the ``processor.process(...)`` call type-checks. - ``rag.embeddings.oci``: bind ``oci.config.from_file`` result to a local typed dict before use; ``self._oci_config_dict`` is declared as ``... | None`` for the pre-init state and mypy can't narrow through the field assignment. - ``rag.stores.qdrant``: cast ``query_points`` results to ``list[ScoredPoint]`` (the SDK union shape is wider than what we actually receive at runtime). - ``rag.stores.chroma``: targeted ``# type: ignore[arg-type, unused-ignore]`` at ``Collection.upsert`` / ``query`` boundary calls. Chroma's typed signatures want narrow ``Sequence[float]`` / specific metadata unions; passing the wider ``list[float]`` / ``dict[str, Any]`` we have is structurally compatible at runtime. ``unused-ignore`` is added so the ignore tolerates the dev mypy / pre-commit mypy version drift. - ``mypy.ignore_missing_imports`` gains ``pytesseract``, ``PIL``, ``pypdf``, ``PyPDF2``, ``pdf2image`` (purely-optional deps loaded inside try/except for OCR / PDF / image / audio extraction). This is the final batch of the migration tracked in #34. Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>
fede-kamel
added a commit
that referenced
this pull request
May 19, 2026
``Agent.run_sync`` already shut the model client down inside the asyncio.run loop so the model's TCP / TLS state didn't survive into the next run_sync's loop. The checkpointer carried the same hazard and we hadn't covered it: an OracleBackend pool created during the first run_sync stays bound to the now-closed loop, so the next run_sync's save against the same backend hits ORA-03146 / DPY-4011 when oracledb tries to reuse a connection whose underlying TCP state no longer matches the live loop. The fix is the symmetric cleanup: in the same finally block that closes the model client, look for ``self.config.checkpointer.close`` and ``await`` it. ``StorageBackendAdapter.close`` already delegates to the wrapped backend, so ``OracleBackend.close`` (which drops the pool) fires on the exit path of every ``run_sync`` rather than leaving the pool dangling until the next call notices the dead loop. Note: this alone does not unstick notebook 15 inside the workbench harness — it still surfaces ORA-03146 on Part 2's tight checkpoint loop. Standalone the notebook passes. The remaining issue is a deeper workbench-bootstrap interaction (see follow-up task #48) and needs work in ``workbench/backend/runner.py``, not the Agent runtime. Tests: 768/768 pass. Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lifts the last legitimate module group out of the mypy
ignore_errorsblanket:locus.rag.*(~5.7k LOC across embeddings, seven vector stores, multimodal stack, retriever, and tool factories).After this lands, only
locus.hooks.builtin.*remains onignore_errors— held back as a behavioural fix (tracked in #45). Issue #34 is otherwise complete.Migration summary (#34)
That's roughly 21k LOC moved from
ignore_errorsinto strict mypy across five PRs. Remaining:hooks.builtin.*only (tracked separately in #45 — fixing it requires aligning hook method signatures with the event-basedHookProviderProtocol, which is a behavioural change rather than typing).Notable fixes
rag.toolsfactory functions andRAGToolkitaccessors now returnAny(decorated tool objects).rag.retriever: typed locals on everyawait self.store.*delegate.rag.multimodal.MultimodalProcessor.processorsdeclares its value type asContentProcessor(the existing Protocol).rag.embeddings.oci: bindoci.config.from_fileresult to a local typed dict before use.rag.stores.qdrant: castquery_pointsresults tolist[ScoredPoint].rag.stores.chroma: targeted# type: ignore[arg-type, unused-ignore]atCollection.upsert/queryboundary calls.unused-ignoreis added so the ignore tolerates the dev mypy / pre-commit mypy version drift.mypy.ignore_missing_importsgainspytesseract,PIL,pypdf,PyPDF2,pdf2image(purely-optional deps loaded inside try/except).Test plan
hatch run typecheck— clean (150 source files)hatch run test— 3,246 passed, 1 skippedpre-commit run --all-files— clean