4b6817381b
Benchmark image — build + push to ECR (any adapter) / build + push (push) Waiting to run
CI / quality (ubuntu-latest) (push) Waiting to run
CI / test (tools-runtime) (push) Waiting to run
CI / test (e2e-general) (push) Waiting to run
CI / test (cli-runtime) (push) Waiting to run
CI / test (e2e-provider-and-openclaw) (push) Waiting to run
CI / test (integrations-and-misc) (push) Waiting to run
CI / coverage-report (push) Blocked by required conditions
CI / test-kubernetes (push) Waiting to run
CI / should-run-thorough (push) Waiting to run
CI / test-thorough (cloudwatch-demo) (push) Blocked by required conditions
CI / test-thorough (flink-ecs) (push) Blocked by required conditions
CI / test-thorough (upstream-lambda) (push) Blocked by required conditions
CI / test-thorough (prefect-ecs-fargate) (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Blocked by required conditions
Release / publish-release (push) Blocked by required conditions
Release / publish-main-release (push) Blocked by required conditions
Release / prepare (push) Waiting to run
Release / verify (push) Blocked by required conditions
Release / build-python-dist (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Blocked by required conditions
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Waiting to run
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
13 KiB
13 KiB
Runtime package rules
Human summary
The runtime package holds the focused support modules for the interactive
shell runtime. The top-level bootstrap and controller live one level up in
interactive_shell/.
In simple terms:
../main.pystarts the interactive session and handles process/bootstrap gates.startup/first_launch_github.pyowns the first-launch GitHub sign-in gate.../controller.pyowns theInteractiveShellControllerorchestration class, including prompt input, submitted prompt handling, queued turn consumption, prompt-mediated confirmation waits, one-turn pipeline handoff, background output draining, and shutdown.core/prompt_manager.pyowns prompt-toolkit setup and prompt rendering.input/owns prompt input event conversion: EOF, Ctrl-C, CPR cleanup, and resume hints.utils/input_policy.pyowns prompt stdin/spinner decisions for turns.startup/initial_input.pyowns non-interactive initial-input replay.background/workers.pyowns alert watching, spinner ticking, sampler startup, and turn-start background output drains.background/also owns background investigation records, launchers, and completion notification delivery.core/holds the core runtime engine:state.py— shared runtime state (ReplState,SpinnerState)turn_detection.py— pure text classifiers for cancel, confirm, and correction detection
core.agent_harness.session.tasksowns the cross-session task registry surfaced via/tasksand/cancel.- Reusable per-agent session state (
Session) lives incore.agent_harness.session. Terminal runtime context assembly (ReplRuntimeContext,create_repl_runtime_context) lives ininteractive_shell.runtime.context.
These instructions apply to interactive_shell/runtime/ and all
subdirectories. Parent AGENTS.md files still apply.
Architectural intent (locked)
The runtime package is intentionally split into focused concerns:
core/state.py— runtime state and transition helpers only.core/turn_detection.py— pure prompt text classification only.utils/input_policy.py— terminal stdin/spinner gating decisions only.agent_presentation.py— terminal presentation for the agent prompt only (agent lifecycle events, presentation-state reducer/renderer,ConsoleAgentEventSink).turn_host.py— terminal/runtime host forShellAgentprompts only.../controller.py— stable async entrypoint and async prompt runtime/event loop orchestration, submitted prompt handling, queued-turn consumption, prompt-mediated confirmation waits, turn telemetry, one-turn pipeline handoff, background output draining, and shutdown only.core/prompt_manager.py— prompt-toolkit setup and prompt rendering only.input/— prompt input event conversion and terminal-input cleanup only.background/workers.py— background worker startup and turn-start drain hooks only.core.agent_harness.session.background— background investigation record and preferences only.background/runner.py— session-local background investigation launchers only.background/notifications.py— background RCA completion notification delivery only.../main.py— process/bootstrap boundary only.startup/initial_input.py— scripted initial-input replay only.startup/first_launch_github.py— first-launch GitHub sign-in gate only.core.agent_harness.session.tasks— task registry + persistence only.core.agent_harness.accounting.token_accounting— session-scoped LLM token accounting and run metadata only.
Keep these boundaries strict. If a change crosses concerns, move code to the owner module instead of broadening module responsibilities.
Data flow contract (locked)
The interactive runtime must keep this shape:
interactive_shell.main.run_repl(synchronous entrypoint) sets up process-level concerns and callsrun_repl_async.interactive_shell.main.run_repl_async(async body) createsInteractiveShellController.InteractiveShellController.start_interactive_shellowns prompt lifecycle, submitted input handling, queued-turn consumption, and per-turn task scheduling.runtime.turn_host.run_agent_turn_queueconsumes queued prompts through an injectedrun_turncallable, which in production islambda text: run_agent_turn(self.turn_runtime, text).runtime.turn_host.run_agent_turn(runtime, text)drives one submitted turn.AgentTurnRuntimeis the immutable dependency bundle it operates on (session,state,spinner,invalidate_prompt,request_exit);run_agent_turnowns presentation setup, prompt-mediated confirmation, dispatch state, and per-turn execution.interactive_shell.runtime.shell_turn_execution.execute_shell_turnbinds shell adapters aroundcore.agent_harness.turns.orchestrator.run_turn.core.agent_harnessowns one prompt's action/answer mechanics and accounting finalization. The terminal presentation forAgentEventemissions lives inruntime/agent_presentation.py.
Do not invert this dependency direction.
Architecture diagram
flowchart TD
runRepl["interactive_shell.main.run_repl"] --> replMain["interactive_shell.main.run_repl_async"]
replMain --> controller["interactive_shell.controller.InteractiveShellController"]
controller --> turnHost["runtime.turn_host.run_agent_turn(turn_runtime, text)"]
turnHost --> turnEntry["interactive_shell.runtime.shell_turn_execution.execute_shell_turn"]
turnEntry --> coreHarness["core.agent_harness.turns.orchestrator.run_turn"]
coreHarness --> sideEffects["slash/help/agent/follow-up/investigation side effects"]
controller --> replState["core.state.ReplState"]
controller --> spinnerState["core.state.SpinnerState"]
controller --> inputReader["input.PromptInputReader"]
State ownership rules
ReplStateis the single source of truth for:- active dispatch task
- cancellation event
- confirmation event/response lifecycle
- exit requests
- the explicit turn
phase(TurnPhase:IDLE,DISPATCHING,AWAITING_CONFIRMATION,CANCELLING)
- Mutate turn state through the
ReplStatetransition methods, never by poking raw fields from other modules:start_dispatch/attach_turn_task/attach_cancel_event->DISPATCHINGbegin_confirmation->AWAITING_CONFIRMATION;clear_confirmationreturns toDISPATCHING/IDLE(and never clobbers an in-progressCANCELLING)cancel_current_dispatch->CANCELLING(only when there is something to cancel) then signals the cancel/confirm events andtask.cancelfinish_dispatch/clear_current_task->IDLE
phaseis authoritative for confirmation and cancelling.is_dispatch_running()stays derived from the asyncio task (the runtime truth of the in-flight turn);is_awaiting_confirmation()andis_cancelling()are derived fromphase.- Do not reorder the signaling inside
cancel_current_dispatchor move theconfirm_responsereset after theconfirm_eventpublish inbegin_confirmation; both orderings are load-bearing for cancellation and confirmation race-safety. SpinnerStateowns spinner rendering state only; it must not depend on runtime task management.
Turn execution rules
- Do not reintroduce
dispatch.py, anAgentTurnRunner-style wrapper class, or any compatibility-only forwarding module. - The terminal host lives in
runtime/turn_host.py:run_agent_turn(runtime, text)owns shell presentation (StreamingConsole, spinner, recorder, progress scope), constructs aConsoleAgentEventSink, owns dispatch state, and lazily imports + callsinteractive_shell.runtime.shell_turn_execution.execute_shell_turn.AgentTurnRuntimeis the immutable dependency bundle it operates on; the controller constructs it and passes a boundrun_agent_turncoroutine intorun_agent_turn_queue. - The shell adapter entry lives in
runtime/shell_turn_execution.py:execute_shell_turncomposes the action-turn (runtime/action_turn.py), gather (runtime/integration_tool_gathering.py), and answer (runtime/answer_turn.py) adapters plus accounting aroundcore.agent_harness.turns.orchestrator.run_turn. Each adapter owns its own binding; tests import them from their owning module (notshell_turn_execution). - The reusable per-prompt loop lives in
core.agent_harness: turn snapshots, observation reset, action/response routing, and core result construction stay surface-agnostic. - Keep terminal side effects (spinner, prompt suppression,
console.print, CPR drain) inConsoleAgentEventSink— defined inruntime/agent_presentation.py— not in the turn-entry adapter or the core harness. - Put cancel/confirm/correction text classifiers in
core/turn_detection.py. - Put stdin blocking and spinner decisions in
utils/input_policy.py. - Keep prompt-mediated confirmation waiting in
runtime/core/confirmation.py. - Turn accounting is consolidated behind
ShellTurnAccountingininteractive_shell/runtime/core/turn_accounting.py, invoked frominteractive_shell.runtime.shell_turn_execution.execute_shell_turn. It owns action-agent analytics, terminal-turn aggregate telemetry, prompt-recorder flush, conversational-turn persistence, and the final assistant-intent stamp.interactive_shell.runtime.action_turn.run_action_tool_turnreturns facts only (ToolCallingTurnResultwithaccounting_statusofcompleted/not_run) and emits no analytics itself. Do not re-scatter accounting back intorun_action_tool_turnor standalone_record_*helpers.
Controller rules
../controller.pyowns:InteractiveShellControllerstart_interactive_shellshell lifecycle orchestration- alert listener setup/teardown
AgentTurnRuntimeconstruction and shutdown- queued prompt submission
turn_host.pyowns:run_input_loop(module-level) — read and handle user input until exitrun_agent_turn_queue(module-level) — consume queued prompts until exit (runs an injectedrun_turn)run_agent_turn(runtime, text)(module-level) — presentation, dispatch state, prompt-mediated confirmation, and turn-entry invocation over anAgentTurnRuntimeConsoleAgentEventSink(inruntime/agent_presentation.py) — terminal presentation for agent lifecycle events over_reduce_agent_presentation/_render_agent_presentation_transition- queued turn consumption
- per-turn task lifecycle
- dispatch start/finish state transitions
- prompt-mediated confirmation waiting
- turn telemetry and
execute_shell_turninvocation - current turn cancellation helpers
- coordination between prompt, background, and shutdown helpers
core/prompt_manager.pyowns:- prompt-toolkit wiring
- prompt rendering callbacks
- pending prompt defaults and autosubmit handling
input/owns:- prompt input event types
- terminal EOF and Ctrl-C conversion
- CPR cleanup for submitted prompt text
- session resume hints when prompt input closes
background/workers.pyowns:- alert watcher lifecycle
- spinner ticker lifecycle
- sampler startup
- background notice drains at turn start
- Keep prompt rendering concerns in runtime/prompting modules, not in dispatch/execution.
Main/bootstrap rules
../main.pyowns:- startup sweep
- TTY/non-TTY gate
- banner display for interactive runs
- async boundary (
asyncio.run)
../controller.pyowns alert listener setup/teardown because the inbox is part of the running shell lifecycle.- Do not move per-turn dispatch/runtime logic back into startup bootstrap.
Compatibility surface policy
runtime/__init__.pyshould be a thin export layer.- Do not duplicate business logic in
__init__.py. runtime/__init__.pyexportsSessionfromcore.agent_harness.sessionand runtime-context helpers frominteractive_shell.runtime.context. New shared runtime code should import session names directly fromcore.agent_harness.session.- Do not re-add
_xxxunderscore aliases or wrapper functions for compatibility. Tests and callers should import canonical names from their owning submodule.
Test seam policy
- Prefer patching canonical module seams:
interactive_shell.controller.*for prompt-loop, queued-turn, confirmation behavior, one-turn pipeline execution, and side effectsinteractive_shell.main.*for process/bootstrap behaviorruntime.core.state.*for state-specific behavior
- Avoid adding new tests that monkeypatch package-root internals in
runtime.__init__unless there is no stable canonical seam.
Refactor guardrails
- No behavior changes to action-planning policy should be introduced from
runtime/refactors. - Keep interruption semantics unchanged:
- Esc or bare cancel commands interrupt active dispatch
- cancellation moves the turn to
TurnPhase.CANCELLINGand signals both the cancel event and any pending confirmation event beforetask.cancel - confirmation prompts are cancel-safe and never silently auto-confirm; a
cancel during confirmation must not be downgraded back to
DISPATCHING
- Preserve observability semantics (turn telemetry and turn summaries).