Download distinct_tools/__init__.py from User1342/distinct: direct link, hf CLI and curl.
- Browser
- Download file 15 kB
-
https://huggingface.co/spaces/User1342/distinct/resolve/main/distinct_tools/__init__.py
- Command line
-
hf download hf://spaces/User1342/distinct/distinct_tools/__init__.py
-
curl -L -o __init__.py https://huggingface.co/spaces/User1342/distinct/resolve/main/distinct_tools/__init__.py
15 kB
| """Explicit, policy-bounded tools for local inference agents. | |
| **Nothing is approved until an operator approves it, so the default registry is | |
| still empty.** That has not changed, and it is what keeps the runtime's | |
| no-outbound-request claim literally true out of the box. What has changed is | |
| that there is now something to approve. | |
| This package is the tool *framework* and a small, evidence-chosen tool set: | |
| * versioned specs with JSON schemas, exact ``id@version`` references, per-job | |
| policy (allowlist, call quotas, timeouts, byte caps, host permissions) and a | |
| per-job :class:`ToolBroker` that snapshots the registry so a later | |
| registration cannot widen a running job; | |
| * :mod:`distinct_tools.local`, six local tools that open no socket, read no | |
| file and spawn no process: ``calculate``, ``calculate_date``, | |
| ``convert_units``, ``extract_from_text``, ``search_document`` and | |
| ``verify_quote``. Every one answers in a single call, which is the | |
| criterion that decides what is viable below 7B; | |
| * :mod:`distinct_tools.approval`, the operator's own allowlist, which is | |
| checked before the server's and cannot be widened remotely; | |
| * :mod:`distinct_tools.mcp`, which maps Model Context Protocol servers onto the | |
| same specs, brokers and policies rather than beside them; | |
| * :mod:`distinct_tools.trace`, a bounded record of every call attempted, | |
| including every refusal. | |
| Two more sources of library members exist outside this package and reach the | |
| registry through :func:`default_registry`: :mod:`distinct_skills`, a repository | |
| of skills held on disk and digest-pinned, and :mod:`distinct_mcp`, four | |
| in-process MCP servers. Both produce ordinary specs in the ordinary registry. | |
| **The three sources are not approved the same way, and the difference is the | |
| whole safety argument.** ``DISTINCT_APPROVED_TOOLS=local`` is a bundle name, | |
| and :func:`~distinct_tools.approval.load_policy` expands it to "every spec in | |
| the list it was given that declares no host". So the list handed to | |
| ``load_policy`` decides what one word approves, and it is deliberately | |
| :data:`INSTALLABLE_SPECS` and nothing else. A repository skill or an MCP tool | |
| is reachable only by naming its exact ``id@version``: they are filtered with | |
| ``policy.permitted_specs(...)``, which works on refs already approved and never | |
| expands a bundle. Widening the list passed to ``load_policy`` would silently | |
| put ``files.write_file@1``, which reads and writes a directory on a | |
| volunteer's machine, inside a single flag. There is a test that fails if | |
| anybody does. | |
| **The catalogue is small on purpose.** | |
| :data:`~distinct_tools.approval.MAX_APPROVED_TOOLS` caps one operator at 64 | |
| approved refs, because a large menu costs selection accuracy on a small model. | |
| Everything this repository can offer today, the ten library members, the four | |
| repository skills and the eight MCP tools, comes to twenty-two, so the cap is | |
| not currently reachable by approving everything. At the boundary the failure is | |
| closed and loud rather than partial: ``OperatorPolicy`` raises, | |
| ``load_policy`` catches it, and what comes back approves nothing at all with | |
| the reason in ``source``. A truncated approval list would be worse, because the | |
| operator would believe they had approved something they had not. | |
| Three gates stand between a tool existing and a tool running, and all three | |
| must open: | |
| 1. it is **installed** (registered, and for MCP its definition digest still | |
| matches what was approved); | |
| 2. the **operator** approved it, and separately approved network access if it | |
| declares any host; | |
| 3. the **run** selected it, through ``JobSpec.allowed_tools``. | |
| Any tool failing any gate fails closed and the attempt is recorded on | |
| :attr:`ToolBroker.trace`. With nothing approved, gate 2 refuses everything, | |
| no reference resolves, and the agent makes no outbound request. | |
| :mod:`distinct_tools.testing` holds inert fixtures used to keep the framework's | |
| own tests honest. Nothing there is ever auto-registered. | |
| """ | |
| from collections.abc import Mapping | |
| from .approval import ( | |
| APPROVED_EGRESS_ENV_VAR, | |
| APPROVED_TOOLS_ENV_VAR, | |
| DENY_ALL, | |
| LOCAL_BUNDLE, | |
| POLICY_FILE_ENV_VAR, | |
| OperatorPolicy, | |
| ToolPolicyError, | |
| load_policy, | |
| ) | |
| from .core import ( | |
| JobPolicy, | |
| OperatorRefusal, | |
| Registry, | |
| ToolBroker, | |
| ToolCallError, | |
| ToolContext, | |
| ToolInputError, | |
| ToolRef, | |
| ToolResult, | |
| ToolSpec, | |
| normalize_host, | |
| ) | |
| from .local import LOCAL_SPECS, register_local_tools | |
| from .skills import ( | |
| REPOSITORY_SKILLS, | |
| REPOSITORY_SPECS, | |
| REPOSITORY_STATUS, | |
| SKILL_SPECS, | |
| describe_skill_repository, | |
| install_skill_repository, | |
| register_skills, | |
| ) | |
| from .workspace import WORKSPACE_SPECS, register_workspace_tools | |
| from .trace import ToolCallRecord, ToolTrace, describe_for_agent | |
| #: The library members written in this package: the local tools and the local | |
| #: skills. Tools and skills are one library behind one policy; a skill differs | |
| #: only in returning an artifact for the user rather than an in-band answer. | |
| #: | |
| #: This tuple is also the list the ``local`` bundle expands over, which is why | |
| #: the repository skills and the MCP tools are not in it. Both of those are | |
| #: installed by :func:`default_registry` when an operator names them in full, | |
| #: and neither can be reached by the bundle name. | |
| INSTALLABLE_SPECS: tuple[ToolSpec, ...] = LOCAL_SPECS + SKILL_SPECS + WORKSPACE_SPECS | |
| def operator_policy(*, environ: Mapping[str, str] | None = None) -> OperatorPolicy: | |
| """Read the operator's approval policy for the installable tool set.""" | |
| return load_policy(INSTALLABLE_SPECS, environ=environ) | |
| def _install_mcp_catalogue( | |
| registry: Registry, | |
| policy: OperatorPolicy, | |
| environ: Mapping[str, str] | None, | |
| ) -> tuple[frozenset[ToolRef], tuple[str, ...]]: | |
| """Install the MCP tools the operator named, and report what was not. | |
| Returns the refs the catalogue recognised, installed or not, so the caller | |
| can tell an approved ref that this package could not offer apart from one | |
| that nothing anywhere has heard of. | |
| """ | |
| # Nothing was approved that the two local sources do not already cover, so | |
| # there is no MCP work to do. Returning before the import keeps an | |
| # operator who never asked for MCP from being told about it, and it is the | |
| # difference between "you approved an MCP tool and could not have it" and | |
| # a message about a package they were not using. | |
| known = frozenset(spec.ref for spec in INSTALLABLE_SPECS) | |
| known |= frozenset(spec.ref for spec in REPOSITORY_SPECS) | |
| unknown = policy.approved - known | |
| if not unknown: | |
| return frozenset(), () | |
| # Imported here rather than at the top of the module because | |
| # ``distinct_mcp`` imports ``distinct_tools``, and the cycle is the only | |
| # reason for the deferral. It is worth being exact about how it fails, | |
| # because half the time it does not: with the import at module level, | |
| # ``import distinct_tools`` still works, and ``import distinct_mcp`` first | |
| # raises ImportError for a partially initialised module, because this | |
| # module then runs part-way through that one. Anybody who tries the move | |
| # and checks only the first order will conclude it is fine. | |
| try: | |
| from distinct_mcp import install_catalogue | |
| except ImportError as exc: | |
| # Every unresolved ref is counted as accounted for here, even though | |
| # one of them may be a plain typo. Without the package there is no way | |
| # to tell the two apart, and the message below is the true one; adding | |
| # "check the spelling" on top of it would send the operator looking for | |
| # a mistake they did not make. | |
| return unknown, ( | |
| f"MCP tools were approved but distinct_mcp could not be imported ({exc}), " | |
| "so none of them is installed and every call to them fails closed", | |
| ) | |
| result = install_catalogue( | |
| registry, only=policy.approved, egress=policy.egress_approved, environ=environ | |
| ) | |
| return frozenset(result.refs) | frozenset(result.skipped), result.notes | |
| def _build_registry( | |
| environ: Mapping[str, str] | None = None, | |
| ) -> tuple[Registry, tuple[str, ...]]: | |
| """Build the registry and collect anything the operator should be told. | |
| Split from :func:`default_registry` so that the notes have somewhere to go. | |
| A capability an operator approved and did not get is exactly the fact they | |
| need, and returning only a registry leaves nowhere to put it. | |
| """ | |
| registry = Registry() | |
| notes: list[str] = [] | |
| # LOAD-BEARING: the policy is read against INSTALLABLE_SPECS and nothing | |
| # else, because the ``local`` bundle expands over whatever list it is | |
| # given. Adding the repository or the MCP specs here would put a skill | |
| # read off the disk, and a tool that writes files, inside one flag. | |
| policy = load_policy(INSTALLABLE_SPECS, environ=environ) | |
| if not policy.approved: | |
| return registry, () | |
| approved = frozenset(spec.ref for spec in policy.permitted_specs(INSTALLABLE_SPECS)) | |
| if approved: | |
| register_local_tools(registry, only=approved) | |
| register_skills(registry, only=approved) | |
| register_workspace_tools(registry, only=approved) | |
| # permitted_specs filters refs the operator already approved and expands | |
| # nothing, so this cannot widen the bundle however the repository grows. | |
| repository = frozenset(spec.ref for spec in policy.permitted_specs(REPOSITORY_SPECS)) | |
| if repository: | |
| try: | |
| install_skill_repository(registry, only=repository) | |
| except (ValueError, RuntimeError) as exc: | |
| # A duplicate identifier or an unresolvable handler: both are bugs | |
| # in this repository rather than operator error. The worker still | |
| # runs everything else, and says which one it dropped, because a | |
| # worker that refuses every tool over one broken skill is worse. | |
| notes.append(f"the skill repository could not be installed ({exc})") | |
| accounted, mcp_notes = _install_mcp_catalogue(registry, policy, environ) | |
| notes.extend(mcp_notes) | |
| installed = frozenset(spec.ref for spec in registry.specs()) | |
| unmatched = sorted( | |
| policy.approved - installed - accounted, key=lambda ref: (ref.tool_id, ref.version) | |
| ) | |
| for ref in unmatched: | |
| # Almost always a typo. Saying so beats leaving the operator to work | |
| # out why a tool they approved never appears in what the worker offers. | |
| notes.append( | |
| f"{ref.tool_id}@{ref.version} is approved but nothing installs it; check the " | |
| "spelling against the list of approvable refs" | |
| ) | |
| return registry, tuple(notes) | |
| def default_registry(*, environ: Mapping[str, str] | None = None) -> Registry: | |
| """Return the agent's tool registry: only what the operator approved. | |
| There is still no entry-point discovery, import scanning or dynamic module | |
| loading, and no credential-gated registration. A tool appears here only | |
| because a human named it in :data:`~distinct_tools.approval.APPROVED_TOOLS_ENV_VAR` | |
| or a policy file. With neither set, this returns an empty registry and | |
| every tool call fails closed. | |
| Three sources feed it and all three obey the same gate. The library members | |
| in :data:`INSTALLABLE_SPECS` are registered directly; the skills in | |
| :mod:`distinct_skills` are installed from their pinned directories; the MCP | |
| servers in :mod:`distinct_mcp` are built and installed. A server that is | |
| approved but cannot be built is skipped rather than fatal, and the reason | |
| is available from :func:`registry_notes`. | |
| Re-read on each call rather than cached, so an operator who changes their | |
| approvals does not have to restart the worker. A run already in flight is | |
| unaffected: :class:`ToolBroker` snapshots the registry at construction. | |
| Building an MCP server here is still discovery at install time in the sense | |
| :mod:`distinct_tools.mcp` means it: it happens before the job's broker | |
| exists, the broker then snapshots, and no run ever negotiates with a | |
| server. The servers are in-process code from this repository, so the | |
| listing costs no I/O beyond the file server resolving its directory. | |
| """ | |
| return _build_registry(environ)[0] | |
| def registry_notes(*, environ: Mapping[str, str] | None = None) -> tuple[str, ...]: | |
| """Say what the operator approved and did not get, and why. | |
| Empty when everything approved was installed. Anything here is a capability | |
| the worker is not offering despite being told to, which is a fact that has | |
| to reach a person: the alternatives are failing open, or a silence that | |
| reads as success. | |
| """ | |
| return _build_registry(environ)[1] | |
| def approvable_refs() -> tuple[str, ...]: | |
| """Every ``id@version`` an operator could name today, from all three sources. | |
| Not filtered by what is approved: this is the menu, not the order. The MCP | |
| half is derived from the catalogue's manifests rather than by building the | |
| servers, so the file server appears here whether or not a directory has | |
| been nominated for it yet. | |
| """ | |
| refs = {f"{spec.tool_id}@{spec.version}" for spec in INSTALLABLE_SPECS} | |
| refs |= {f"{spec.tool_id}@{spec.version}" for spec in REPOSITORY_SPECS} | |
| try: | |
| from distinct_mcp import catalogue_refs # deferred: see _install_mcp_catalogue | |
| except ImportError: # pragma: no cover - distinct_mcp is part of this repository | |
| return tuple(sorted(refs)) | |
| return tuple(sorted(refs | set(catalogue_refs()))) | |
| def available_tool_refs(*, environ: Mapping[str, str] | None = None) -> tuple[str, ...]: | |
| """Detect approved, installed capabilities as sorted ``id@version`` refs. | |
| This is what the worker advertises. A tool the operator has not approved | |
| is never advertised, so a server cannot select it in the first place; the | |
| broker refuses it again if one tries anyway. | |
| """ | |
| return tuple(sorted(f"{spec.tool_id}@{spec.version}" for spec in default_registry(environ=environ).specs())) | |
| __all__ = [ | |
| "APPROVED_EGRESS_ENV_VAR", | |
| "APPROVED_TOOLS_ENV_VAR", | |
| "DENY_ALL", | |
| "INSTALLABLE_SPECS", | |
| "REPOSITORY_SKILLS", | |
| "REPOSITORY_SPECS", | |
| "REPOSITORY_STATUS", | |
| "describe_skill_repository", | |
| "install_skill_repository", | |
| "LOCAL_BUNDLE", | |
| "LOCAL_SPECS", | |
| "POLICY_FILE_ENV_VAR", | |
| "JobPolicy", | |
| "OperatorPolicy", | |
| "OperatorRefusal", | |
| "Registry", | |
| "ToolBroker", | |
| "ToolCallError", | |
| "ToolCallRecord", | |
| "ToolContext", | |
| "ToolInputError", | |
| "ToolPolicyError", | |
| "ToolRef", | |
| "ToolResult", | |
| "ToolSpec", | |
| "ToolTrace", | |
| "approvable_refs", | |
| "available_tool_refs", | |
| "default_registry", | |
| "describe_for_agent", | |
| "SKILL_SPECS", | |
| "load_policy", | |
| "normalize_host", | |
| "operator_policy", | |
| "register_local_tools", | |
| "register_skills", | |
| "register_workspace_tools", | |
| "registry_notes", | |
| "WORKSPACE_SPECS", | |
| ] | |