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
127 lines
3.7 KiB
Python
127 lines
3.7 KiB
Python
"""Tests for interactive-shell action rendering."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import io
|
|
from dataclasses import dataclass
|
|
|
|
import pytest
|
|
from rich.console import Console
|
|
|
|
import tools.interactive_shell.actions.slash as slash_tool
|
|
from core.agent_harness.turns.turn_results import ToolCallingTurnResult
|
|
from surfaces.interactive_shell.runtime.action_turn import run_action_tool_turn
|
|
from surfaces.interactive_shell.runtime.shell_turn_execution import execute_shell_turn
|
|
from surfaces.interactive_shell.session import Session
|
|
from surfaces.interactive_shell.ui.action_rendering import ActionRenderObserver
|
|
from surfaces.interactive_shell.ui.input_prompt.rendering import _prompt_turn_number
|
|
from tests.core.agent.orchestration.action_execution_test_harness import (
|
|
ActionExecutionHarness,
|
|
FakeActionLLM,
|
|
no_tool_response,
|
|
)
|
|
|
|
|
|
def test_slash_invoke_tool_start_does_not_record_cli_agent() -> None:
|
|
session = Session()
|
|
buffer = io.StringIO()
|
|
console = Console(file=buffer, force_terminal=False, highlight=False)
|
|
observer = ActionRenderObserver(session=session, console=console, message="/model show")
|
|
|
|
observer(
|
|
"tool_start",
|
|
{"name": "slash_invoke", "input": {"command": "/model", "args": ["show"]}},
|
|
)
|
|
|
|
assert session.history == []
|
|
assert observer.planned_count == 1
|
|
assert buffer.getvalue() == ""
|
|
|
|
|
|
def test_shell_run_tool_start_does_not_record_cli_agent() -> None:
|
|
session = Session()
|
|
console = Console(file=io.StringIO(), force_terminal=False, highlight=False)
|
|
observer = ActionRenderObserver(session=session, console=console, message="!true")
|
|
|
|
observer("tool_start", {"name": "shell_run", "input": {"command": "true"}})
|
|
|
|
assert session.history == []
|
|
assert observer.planned_count == 1
|
|
|
|
|
|
def test_literal_slash_command_records_single_history_entry(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
dispatched: list[str] = []
|
|
|
|
def _fake_dispatch(
|
|
command: str,
|
|
session: Session,
|
|
console: Console,
|
|
**_kwargs: object,
|
|
) -> bool:
|
|
dispatched.append(command)
|
|
session.record("slash", command, ok=True)
|
|
return True
|
|
|
|
monkeypatch.setattr(slash_tool, "dispatch_slash", _fake_dispatch)
|
|
session = Session()
|
|
harness = ActionExecutionHarness(llm=FakeActionLLM([no_tool_response()]))
|
|
|
|
result = run_action_tool_turn(
|
|
"/model show",
|
|
session,
|
|
harness.console,
|
|
deps=harness.deps,
|
|
)
|
|
|
|
assert result.handled is True
|
|
assert dispatched == ["/model show"]
|
|
assert session.history == [{"type": "slash", "text": "/model show", "ok": True}]
|
|
assert _prompt_turn_number(session) == 2
|
|
|
|
|
|
@dataclass
|
|
class _FakeLlmRun:
|
|
response_text: str = "hello back"
|
|
|
|
|
|
def test_chat_turn_records_single_cli_agent_history_entry() -> None:
|
|
session = Session()
|
|
console = Console(file=io.StringIO(), force_terminal=False, highlight=False)
|
|
|
|
def _no_actions(
|
|
_text: str,
|
|
_session: Session,
|
|
_console: Console,
|
|
**kwargs: object,
|
|
) -> ToolCallingTurnResult:
|
|
return ToolCallingTurnResult(
|
|
planned_count=0,
|
|
executed_count=0,
|
|
executed_success_count=0,
|
|
has_unhandled_clause=False,
|
|
handled=False,
|
|
accounting_status="not_run",
|
|
)
|
|
|
|
def _answer(
|
|
_text: str,
|
|
_session: Session,
|
|
_console: Console,
|
|
**kwargs: object,
|
|
) -> _FakeLlmRun:
|
|
return _FakeLlmRun()
|
|
|
|
execute_shell_turn(
|
|
"what broke in prod?",
|
|
session,
|
|
console,
|
|
recorder=None,
|
|
execute_actions=_no_actions,
|
|
answer_agent=_answer,
|
|
)
|
|
|
|
assert session.history == [{"type": "cli_agent", "text": "what broke in prod?", "ok": True}]
|
|
assert _prompt_turn_number(session) == 2
|