refactor(core): drop AdapterRegistry + BaseAdapter; keep EvaluatorProtocol#1761
refactor(core): drop AdapterRegistry + BaseAdapter; keep EvaluatorProtocol#1761viswa-uipath wants to merge 8 commits into
Conversation
…tocol The adapter-registry plugin-discovery system in uipath-core was a parallel keyed-by-agent-type dispatcher for a fact already known statically: the runtime-factory registry has picked the framework by the time anything needs an "adapter". The two registries existed only to support an open-PR pattern (#125/#126) where the runtime layer sniffed the framework off an opaque agent. With that approach abandoned in favor of framework plugins wiring governance at their native seam (callback handlers, hook lists), the registry, the BaseAdapter abstraction, and their per-package entry-point group are all dead weight. Deletions - src/uipath/core/adapters/base.py — BaseAdapter + GovernedAgentBase. No internal consumers; the only external one (uipath-langchain PR #899) is unmerged and is being reshaped to consume EvaluatorProtocol directly via its factory. - src/uipath/core/adapters/registry.py — AdapterRegistry, get_adapter_registry, reset_adapter_registry, the `uipath.governance.adapters` entry-point group, and the side-effect discovery on first call. - tests/adapters/test_base.py and tests/adapters/test_registry.py. Kept - src/uipath/core/adapters/evaluator.py — EvaluatorProtocol is the one contract framework plugins still consume. Plugin factories accept an evaluator at create_runtime() time and wire it into their own callback seam. - tests/adapters/test_evaluator.py — protocol-conformance unchanged. Net diff: ~960 LOC removed. uipath-core 0.5.22 → 0.5.23. uv.lock files regenerated in uipath-core, uipath-platform, and uipath (workspace editable-path deps, so they pick up 0.5.23 immediately). Verified: ruff clean, mypy clean (45 source files), 230 passed + 1 skipped in uipath-core's test suite. Monorepo grep for AdapterRegistry / BaseAdapter / GovernedAgentBase / get_adapter_registry / reset_adapter_registry returns zero hits outside the deleted files across .py/.toml/.md/.rst/.json. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR removes the adapter-registry plumbing from uipath-core (adapter base class, registry singleton, and related tests) while preserving EvaluatorProtocol as the remaining contract for framework governance integrations. It also bumps uipath-core’s version and refreshes workspace lockfiles to reflect the new core version and updated uv lock metadata.
Changes:
- Deleted
BaseAdapter/AdapterRegistry/ singleton helpers (and their tests), leaving onlyEvaluatorProtocolunderuipath.core.adapters. - Updated
uipath.core.adapterspublic exports/documentation accordingly. - Bumped
uipath-coreto0.5.23and refresheduv.lockfiles across packages.
Reviewed changes
Copilot reviewed 6 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/uipath/uv.lock | Refresh lock metadata and update editable uipath-core version reference to 0.5.23. |
| packages/uipath-platform/uv.lock | Refresh lock metadata and update editable uipath-core version reference to 0.5.23. |
| packages/uipath-core/uv.lock | Update uipath-core package version entry to 0.5.23 in the lock. |
| packages/uipath-core/tests/adapters/test_registry.py | Remove tests for deleted adapter registry behavior. |
| packages/uipath-core/tests/adapters/test_base.py | Remove tests for deleted adapter base/proxy behavior. |
| packages/uipath-core/src/uipath/core/adapters/registry.py | Delete adapter registry + entry-point discovery implementation. |
| packages/uipath-core/src/uipath/core/adapters/base.py | Delete adapter base class and governed proxy base. |
| packages/uipath-core/src/uipath/core/adapters/init.py | Trim exports to only EvaluatorProtocol and update docstring. |
| packages/uipath-core/pyproject.toml | Bump package version from 0.5.22 to 0.5.23. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Closes doc item 1.2 — every ``evaluate_*`` method on ``EvaluatorProtocol`` returned ``-> Any``, forcing callers to downcast to the type they already knew the concrete evaluator was returning. The concrete ``GovernanceEvaluator`` in uipath-runtime-python already declares ``-> AuditRecord`` on each per-hook method, so narrowing the protocol contract is structurally compatible — no behavior change, no downstream code change required. Narrows the six evaluate_* return types (before_agent / after_agent / before_model / after_model / tool_call / after_tool) from Any to AuditRecord, imports the type from uipath.core.governance.models, and refreshes the class docstring (was claiming the protocol is intentionally Any because the audit record "lives in the plugin package" — but AuditRecord lives right here in uipath-core). Verified - ruff clean, mypy clean (45 source files), 230 passed + 1 skipped in uipath-core. - uipath-runtime-python's test suite (357 passed + 1 skipped) keeps green when this version of uipath-core is installed — the protocol- conformance tests in test_evaluator.py still pass because the concrete GovernanceEvaluator was already returning AuditRecord from every evaluate_* method. Rides on the same 0.5.23 version bump as the previous commit — both changes ship together as one public-surface change on uipath-core. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Unblocks architecture-review §2.4 on the uipath-runtime side. The prescription there is to hoist the policy fetch from the runtime-layer ``PolicyLoader`` (which today spins a daemon thread inside an async runtime and blocks on ``threading.Event.wait(timeout=10s)``) up to the async host: the CLI calls ``await provider.get_policy_async(ctx)`` itself, builds the ``PolicyIndex``, and passes the resolved index + mode into ``GovernanceRuntime``. The runtime collapses to a pure, synchronous-to-construct decorator — no thread, no Event, no ``is_conversational`` in the ctor. For that to type-check on the runtime side, the structural ``GovernancePolicyProvider`` Protocol in uipath-core needs to declare ``get_policy_async``. The concrete platform provider (``UiPathPlatformGovernanceProvider``) already implements it; the contract was just lying about what providers expose. Changes - ``GovernancePolicyProvider`` now declares both ``get_policy`` and ``async get_policy_async``. Both required (the platform impl ships both today, and the doc's recommended caller path is the async variant — sync stays for non-event-loop callers like integration tests and CLI tools). - ``_FakePolicyProvider`` in the conformance tests grew the async method and a separate ``async_calls`` recorder. - New ``test_policy_round_trip_async`` exercises the async path via ``@pytest.mark.asyncio`` and pins that the two entry points are independent (calling one doesn't touch the other's recorder). Verified - uipath-core: ruff clean, mypy clean (45 source files), 32 governance tests passed. - uipath-platform: protocol-conformance tests still pass (9 passed) — ``UiPathPlatformGovernanceProvider`` already exposed ``get_policy_async``, so the now-stricter protocol still accepts it structurally. No version bump — rides on the unreleased 0.5.23 that already carries PR #1761's §1.1 (adapter-registry deletion) and §1.2 (typed EvaluatorProtocol returns). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…it empty Lets the runtime layer (uipath-runtime-python) stop carrying ``trace_id`` through ``UiPathGovernedRuntime`` / ``GuardrailCompensator``. The runtime emits compensation requests with ``trace_id=""`` and the platform fills in the canonical agent trace id at HTTP-call time via the existing ``resolve_trace_id()`` helper — same fallback ``track_event`` (PR #1745) already uses. uipath-core - ``GovernRequest.trace_id`` relaxes from required ``str`` to ``str = ""`` default. Docstring documents the platform-side self-resolve contract so wire callers know an empty value is legitimate. uipath-platform - ``GovernanceService._compensate`` / ``_compensate_async`` now call a new ``_resolve_request_trace_id()`` helper before the POST. When ``request.trace_id`` is empty the helper resolves via ``resolve_trace_id()`` (env → LLMOps external span → OTel current span). Caller-supplied values win — the runtime captures live OTel context across its background-pool hop via ``contextvars.copy_context()``, so when the worker calls ``provider.compensate(...)`` the platform-side resolver sees the agent's live span and returns the same canonical id. Caller-supplied non-empty trace ids continue to pass through unchanged. Tests - uipath-core governance suite: 32 passed. - uipath-platform governance service suite: 27 passed. - ruff + mypy clean on ``src/uipath/core/governance`` and ``src/uipath/platform/governance``. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Valentina Bojan <valentina.bojan@uipath.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Ruff format collapses the three-line def to a single line; CI lint runs ruff with --check and failed on the prior commit. No behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2.11.13 is already taken by another PR/publish; bumping to keep the release on this branch publishable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🚨 Heads up:
|


Summary
AdapterRegistry/BaseAdapter/GovernedAgentBaseplumbing fromuipath-core, plus theuipath.governance.adaptersentry-point group andget_adapter_registry/reset_adapter_registryhelpersEvaluatorProtocol— the one contract framework plugins still consumeuipath-coreto0.5.23and refresh the threeuv.lockfilesWhy
The adapter registry was a second plugin-discovery system keyed on the same fact (which framework is active) that
UiPathRuntimeFactoryRegistryalready resolves statically. It existed to support an open-PR pattern where the runtime layer would sniff the framework off an opaque agent — that approach is being abandoned in favor of framework plugins wiring governance at their own native seam (callback handlers / hook lists), so the registry becomes dead weight.The only known external consumer is the unmerged
uipath-langchainPR #899, which is being reshaped to consumeEvaluatorProtocoldirectly through its factory. A grep across the monorepo (.py/.toml/.md/.rst/.json) forAdapterRegistry/BaseAdapter/GovernedAgentBase/get_adapter_registry/reset_adapter_registryreturns zero hits outside the deleted files.Changes
packages/uipath-core/src/uipath/core/adapters/base.pypackages/uipath-core/src/uipath/core/adapters/registry.pypackages/uipath-core/tests/adapters/test_base.pypackages/uipath-core/tests/adapters/test_registry.pypackages/uipath-core/src/uipath/core/adapters/__init__.py— exports trimmed toEvaluatorProtocolpackages/uipath-core/pyproject.toml—0.5.22 → 0.5.23uv.lockfiles for the workspaceNet diff: −962 LOC.
Test plan
uv run ruff check src/ tests/— cleanuv run mypy src/— clean (45 source files)uv run pytest— 230 passed, 1 skipped inuipath-coreuipath/uipath-platformpackagesuipath-langchainPR chore: validate required files on push #899 reshape (see below)Coordination
Downstream
uipath-runtime-pythonanduipath-langchain-pythonare not yet merged, so no shipped consumer breaks. Merge order if this lands first:uipath-runtime-pythonadds optionalevaluatorkwarg to the factory protocol — pendinguipath-langchain-pythonPR chore: validate required files on push #899 reshaped to factory-drivenGovernanceCallbackHandlerwiring (and to subclasslangchain_core.callbacks.BaseCallbackHandlerproperly) — pending🤖 Generated with Claude Code
Development Packages
uipath
uipath-core
uipath-platform