4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
128 lines
4.4 KiB
Python
128 lines
4.4 KiB
Python
"""Core-owned default tool provider for the shared agent harness."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from collections.abc import Callable
|
|
from typing import Any
|
|
|
|
from core.agent_harness.ports import (
|
|
ConfirmFn,
|
|
ToolEventObserver,
|
|
)
|
|
from core.agent_harness.tools.action_tools import get_action_tools_from_integrations_context
|
|
from core.agent_harness.tools.tool_context import (
|
|
ACTION_TOOL_CONTEXT_RESOURCE_KEY,
|
|
ActionToolContext,
|
|
)
|
|
|
|
ActionObserverFactory = Callable[[str], ToolEventObserver]
|
|
# Return value is tools.interactive_shell.subprocess.SubprocessPresenter (surface-injected).
|
|
SubprocessPresenterFactory = Callable[
|
|
[Any, Any, ConfirmFn | None, bool | None, bool],
|
|
Any,
|
|
]
|
|
_TOOL_INPUT_LOG_PREVIEW_LIMIT = 500
|
|
|
|
|
|
def _tool_input_preview(value: Any) -> str:
|
|
preview = repr(value)
|
|
if len(preview) > _TOOL_INPUT_LOG_PREVIEW_LIMIT:
|
|
return f"{preview[: _TOOL_INPUT_LOG_PREVIEW_LIMIT - 3]}..."
|
|
return preview
|
|
|
|
|
|
class DefaultToolProvider:
|
|
""":class:`core.agent_harness.ports.ToolProvider` backed by action tools."""
|
|
|
|
def __init__(
|
|
self,
|
|
session: Any,
|
|
console: Any,
|
|
*,
|
|
request_exit: Callable[[], None] | None = None,
|
|
precomputed_action_tools: list[Any] | None = None,
|
|
observer_factory: ActionObserverFactory | None = None,
|
|
tool_action_logger: logging.Logger | None = None,
|
|
subprocess_presenter_factory: SubprocessPresenterFactory | None = None,
|
|
) -> None:
|
|
self._session = session
|
|
self._console = console
|
|
self._request_exit = request_exit
|
|
self._precomputed_action_tools = precomputed_action_tools
|
|
self._observer_factory = observer_factory
|
|
self._tool_action_logger = tool_action_logger
|
|
self._subprocess_presenter_factory = subprocess_presenter_factory
|
|
self._tool_context: ActionToolContext | None = None
|
|
|
|
def action_tools(
|
|
self,
|
|
*,
|
|
confirm_fn: ConfirmFn | None,
|
|
is_tty: bool | None,
|
|
resolved_integrations: dict[str, Any] | None = None,
|
|
) -> list[Any]:
|
|
subprocess_presenter = None
|
|
if self._subprocess_presenter_factory is not None:
|
|
subprocess_presenter = self._subprocess_presenter_factory(
|
|
self._session,
|
|
self._console,
|
|
confirm_fn,
|
|
is_tty,
|
|
True,
|
|
)
|
|
ctx = ActionToolContext(
|
|
session=self._session,
|
|
console=self._console,
|
|
confirm_fn=confirm_fn,
|
|
is_tty=is_tty,
|
|
request_exit=self._request_exit,
|
|
action_already_listed=True,
|
|
subprocess_presenter=subprocess_presenter,
|
|
)
|
|
self._tool_context = ctx
|
|
if self._precomputed_action_tools is not None:
|
|
return list(self._precomputed_action_tools)
|
|
resolved = (
|
|
resolved_integrations
|
|
if resolved_integrations is not None
|
|
else self._resolved_integrations()
|
|
)
|
|
return get_action_tools_from_integrations_context(ctx, resolved_integrations=resolved)
|
|
|
|
def tool_resources(self) -> dict[str, Any]:
|
|
if self._tool_context is None:
|
|
return {}
|
|
return {ACTION_TOOL_CONTEXT_RESOURCE_KEY: self._tool_context}
|
|
|
|
def observer(self, *, message: str) -> ToolEventObserver:
|
|
if self._observer_factory is not None:
|
|
observer = self._observer_factory(message)
|
|
else:
|
|
|
|
def observer(_kind: str, _data: dict[str, Any]) -> None:
|
|
return None
|
|
|
|
if self._tool_action_logger is None:
|
|
return observer
|
|
logger = self._tool_action_logger
|
|
|
|
def _logging_observer(kind: str, data: dict[str, Any]) -> None:
|
|
if kind == "tool_start":
|
|
tool_name = str(data.get("name") or "tool").strip()
|
|
if tool_name:
|
|
logger.info(
|
|
"tool action name=%s input=%s",
|
|
tool_name,
|
|
_tool_input_preview(data.get("input", {})),
|
|
)
|
|
observer(kind, data)
|
|
|
|
return _logging_observer
|
|
|
|
def _resolved_integrations(self) -> dict[str, Any]:
|
|
from core.agent_harness.session.integration_resolution import resolve_and_cache_integrations
|
|
|
|
# resolve_and_cache_integrations returns a fresh dict.
|
|
return resolve_and_cache_integrations(self._session)
|