steerable-agent-runtime 0.6.61__tar.gz → 0.6.63__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/PKG-INFO +1 -1
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/pyproject.toml +1 -1
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/approval.py +47 -10
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/history.py +1 -2
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/llm/parts.py +1 -1
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/mcp.py +1 -1
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/recording.py +3 -4
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/tool_search.py +2 -2
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime.egg-info/PKG-INFO +1 -1
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_approval.py +72 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/README.md +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/setup.cfg +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/__init__.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/antihallucination.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/approval_policy.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/ask_user.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/branch.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/cache_control.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/calibration.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/compaction.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/compaction_policy.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/config.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/default.harness.json +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/default.harness.yaml +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/delegation_gate.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/errors.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/gateway_catalog.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/handoff.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/harness.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/harness_spec.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/hooks.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/llm/__init__.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/llm/anthropic_native.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/llm/compat.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/llm/errors.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/llm/google_genai.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/llm/openai_compat.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/llm/openai_responses.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/llm/presets.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/llm/system_proxy.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/loop.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/maintenance.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/mcp_server.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/model_catalog.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/model_info.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/model_resolve.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/native_bridge.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/observation_aging.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/orchestration.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/otel.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/plugins.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/pool.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/pricing.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/pseudo.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/reminders.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/replay.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/resume.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/retry.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/sandboxed.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/skills.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/spill.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/storage/__init__.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/storage/in_memory.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/storage/sqlalchemy_store.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/storage/sqlite_store.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/storage/write_lease.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/subagent.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/todo.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/tokens.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/tool_presentation.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/tool_schema.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/tools.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/tracing.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/transport/__init__.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/transport/fastapi_sse.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/transport/stdio_jsonrpc.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/world_state.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime.egg-info/SOURCES.txt +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime.egg-info/dependency_links.txt +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime.egg-info/requires.txt +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime.egg-info/top_level.txt +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_antihallucination.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_approval_policy.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_ask_user.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_branch.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_cache_control.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_cache_instrumentation.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_calibration.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_compaction.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_compaction_policy.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_compaction_strategy.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_config.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_content_parts.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_delegation_gate.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_error_taxonomy.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_fragment_bounds.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_gateway_catalog.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_golden.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_handoff.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_harness.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_harness_spec.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_history.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_history_persistence.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_hooks.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_in_memory_storage.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_llm_gemini_wire.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_llm_responses_wire.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_llm_stream_e2e.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_llm_wire_helpers.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_long_session.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_loop.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_loop_cancellation.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_loop_replay.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_loop_sandbox_event.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_loop_terminal.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_maintenance.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_mcp.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_mcp_server.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_model_catalog.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_model_equivalence.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_model_info.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_model_resolve.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_native_default.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_observation_aging.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_orchestration.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_otel.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_parallel_tools.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_plugins.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_provider_compat.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_provider_presets.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_pseudo.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_pyo3_api_surface.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_recording.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_reminders.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_replay_crosslang.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_resume.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_retry_hooks.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_safety_gate.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_sandboxed.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_skills.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_soft_timeout.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_spill.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_sqlite_storage.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_steer.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_storage_contract.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_stream_strip.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_subagent.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_system_proxy.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_todo.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_todo_gate.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_tokens.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_tool_exposure.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_tool_hygiene.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_tool_presentation.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_tool_router.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_tool_schema.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_tool_timeout.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_trace_recorder.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_transport_jsonrpc.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_transport_sse.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_usage_attribution.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_world_state.py +0 -0
- {steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_write_lease.py +0 -0
|
@@ -38,6 +38,7 @@ from steerable_agent_harness.policy import ToolMode, decide_tool_mode
|
|
|
38
38
|
from steerable_agent_protocol.generated import ToolCall, ToolResult
|
|
39
39
|
|
|
40
40
|
from .errors import ApprovalAborted
|
|
41
|
+
from .sandboxed import DEFAULT_SHELL_TOOLS
|
|
41
42
|
|
|
42
43
|
if TYPE_CHECKING:
|
|
43
44
|
from .loop import LoopContext, ToolExecutor
|
|
@@ -142,9 +143,9 @@ _PATH_ARG_TOOLS = {
|
|
|
142
143
|
def declared_target_paths(request: ApprovalRequest) -> list[str] | None:
|
|
143
144
|
"""Filesystem targets of a path-scoped tool, or None when the call is not one.
|
|
144
145
|
|
|
145
|
-
``None`` means
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
``None`` means this approver cannot prove the call from its path
|
|
147
|
+
arguments. Shell commands are judged separately, from the sandbox and
|
|
148
|
+
the working directory, not from the command text.
|
|
148
149
|
"""
|
|
149
150
|
if request.tool_name == "present_files":
|
|
150
151
|
files = request.arguments.get("files")
|
|
@@ -192,20 +193,54 @@ def path_inside_writable_roots(raw: str, roots: list[str]) -> bool:
|
|
|
192
193
|
return False
|
|
193
194
|
|
|
194
195
|
|
|
195
|
-
|
|
196
|
-
"""
|
|
196
|
+
def shell_stays_in_workspace(request: ApprovalRequest, roots: list[str]) -> bool:
|
|
197
|
+
"""True when a shell call's working directory is inside a writable root.
|
|
198
|
+
|
|
199
|
+
The command text is not parsed. Confinement is the OS sandbox's job:
|
|
200
|
+
writes outside the roots fail there. An omitted cwd uses the host's
|
|
201
|
+
project directory. An explicit cwd outside the roots, or one that
|
|
202
|
+
climbs out with ``..``, still needs a prompt.
|
|
203
|
+
"""
|
|
204
|
+
if request.tool_name not in DEFAULT_SHELL_TOOLS or not roots:
|
|
205
|
+
return False
|
|
206
|
+
cwd = request.arguments.get("cwd")
|
|
207
|
+
if cwd is None:
|
|
208
|
+
return True
|
|
209
|
+
if not isinstance(cwd, str) or not cwd.strip():
|
|
210
|
+
return True
|
|
211
|
+
return path_inside_writable_roots(cwd, roots)
|
|
197
212
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
213
|
+
|
|
214
|
+
class WorkspaceAutoApprover:
|
|
215
|
+
"""Skip the host prompt for work the workspace sandbox already confines.
|
|
216
|
+
|
|
217
|
+
Embedders may also name host-owned control tools whose effects are limited
|
|
218
|
+
to internal session state and therefore need no interactive consent.
|
|
219
|
+
Path-scoped tools (``local_write_file``, ``local_edit_file``, reads,
|
|
220
|
+
``present_files``) skip when every declared path is inside a writable
|
|
221
|
+
root. Shell tools skip only when the OS exec sandbox is on and the
|
|
222
|
+
working directory is inside those roots — the same split Codex uses
|
|
223
|
+
between ``workspace-write`` and ``on-request``. The allow is
|
|
224
|
+
request-scoped. The next call is judged again. Anything else falls
|
|
225
|
+
through to the inner approver.
|
|
202
226
|
"""
|
|
203
227
|
|
|
204
|
-
def __init__(
|
|
228
|
+
def __init__(
|
|
229
|
+
self,
|
|
230
|
+
inner: Approver,
|
|
231
|
+
writable_roots: list[str],
|
|
232
|
+
*,
|
|
233
|
+
sandbox_enforced: bool = False,
|
|
234
|
+
auto_allow_tools: tuple[str, ...] = (),
|
|
235
|
+
) -> None:
|
|
205
236
|
self._inner = inner
|
|
206
237
|
self._roots = [root for root in writable_roots if isinstance(root, str) and root.strip()]
|
|
238
|
+
self._sandbox_enforced = sandbox_enforced
|
|
239
|
+
self._auto_allow_tools = frozenset(auto_allow_tools)
|
|
207
240
|
|
|
208
241
|
async def approve(self, request: ApprovalRequest) -> ApprovalDecision:
|
|
242
|
+
if request.tool_name in self._auto_allow_tools:
|
|
243
|
+
return ApprovalDecision("allow_once", "trusted host control tool")
|
|
209
244
|
paths = declared_target_paths(request)
|
|
210
245
|
if (
|
|
211
246
|
self._roots
|
|
@@ -213,6 +248,8 @@ class WorkspaceAutoApprover:
|
|
|
213
248
|
and all(path_inside_writable_roots(path, self._roots) for path in paths)
|
|
214
249
|
):
|
|
215
250
|
return ApprovalDecision("allow_once", "path is inside a writable project root")
|
|
251
|
+
if self._sandbox_enforced and shell_stays_in_workspace(request, self._roots):
|
|
252
|
+
return ApprovalDecision("allow_once", "command stays inside the workspace sandbox")
|
|
216
253
|
return await self._inner.approve(request)
|
|
217
254
|
|
|
218
255
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""Typed append-only history — the model-visible record and its projection.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
model-visible transcript becomes a *projection* of a typed, append-only
|
|
3
|
+
The model-visible transcript is a *projection* of a typed, append-only
|
|
5
4
|
record instead of a mutable ``list[LLMMessage]`` that hooks rewrite in
|
|
6
5
|
place.
|
|
7
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Content parts — the structured form of ``LLMMessage.content``.
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Message content is a
|
|
4
4
|
list of typed parts instead of a bare string, unblocking multimodal input,
|
|
5
5
|
structured output, and (Wave 2) per-block cache annotations.
|
|
6
6
|
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/src/steerable_agent_runtime/mcp.py
RENAMED
|
@@ -19,7 +19,7 @@ caps.
|
|
|
19
19
|
finds them through the ``tool_search`` seam instead of paying for every
|
|
20
20
|
schema in every request. Hosts pin favorites with ``exposure="direct"``.
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
In the desktop product, MCP
|
|
23
23
|
servers are launched host-side (Electron main) and reached through
|
|
24
24
|
`ToolRouter.register_remote` — a Seatbelt-confined sidecar never spawns
|
|
25
25
|
them. `McpStdioClient` and `McpStreamableHttpClient` exist for hosts that
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"""RecordingProvider — capture every outbound LLM request, plus the
|
|
2
2
|
prompt-invariant assertions built on the recording.
|
|
3
3
|
|
|
4
|
-
Wave
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
that gap:
|
|
4
|
+
Wave 1 rewrites history into typed append-only envelopes. Without a
|
|
5
|
+
recording of what the model actually saw, a correct rewrite can silently
|
|
6
|
+
regress. This module closes that gap:
|
|
8
7
|
|
|
9
8
|
- ``RecordingProvider`` wraps any ``LLMProvider`` and snapshots every outbound
|
|
10
9
|
request (messages + params) into a sink *before* delegating, so a failed
|
|
@@ -26,8 +26,8 @@ from .tools import RegisteredTool, ToolRouter
|
|
|
26
26
|
|
|
27
27
|
TOOL_SEARCH_NAME = "tool_search"
|
|
28
28
|
|
|
29
|
-
#: Default matches per call. 8 matches codex's tool_discovery cap
|
|
30
|
-
#:
|
|
29
|
+
#: Default matches per call. 8 matches codex's tool_discovery cap.
|
|
30
|
+
#: The per-call ceiling below bounds
|
|
31
31
|
#: the schema payload regardless of what a call requests.
|
|
32
32
|
DEFAULT_MAX_RESULTS = 8
|
|
33
33
|
#: Hard ceiling per call: every match carries a full schema, so an
|
|
@@ -512,6 +512,25 @@ async def test_workspace_auto_approver_allows_paths_inside_writable_roots(tmp_pa
|
|
|
512
512
|
assert inner.requests == []
|
|
513
513
|
|
|
514
514
|
|
|
515
|
+
@pytest.mark.asyncio
|
|
516
|
+
async def test_workspace_auto_approver_allows_named_host_control_tools() -> None:
|
|
517
|
+
from steerable_agent_runtime.approval import WorkspaceAutoApprover
|
|
518
|
+
|
|
519
|
+
inner = _ScriptedApprover([ApprovalDecision("deny_once", "should not ask")])
|
|
520
|
+
approver = WorkspaceAutoApprover(
|
|
521
|
+
inner,
|
|
522
|
+
[],
|
|
523
|
+
auto_allow_tools=("update_goal", "loop_stop"),
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
goal = await approver.approve(_request("update_goal", {"action": "complete"}))
|
|
527
|
+
loop = await approver.approve(_request("loop_stop", {"id": "loop-1"}))
|
|
528
|
+
|
|
529
|
+
assert goal.kind == "allow_once"
|
|
530
|
+
assert loop.kind == "allow_once"
|
|
531
|
+
assert inner.requests == []
|
|
532
|
+
|
|
533
|
+
|
|
515
534
|
@pytest.mark.asyncio
|
|
516
535
|
async def test_workspace_auto_approver_asks_when_a_path_leaves_the_project(tmp_path) -> None:
|
|
517
536
|
from steerable_agent_runtime.approval import WorkspaceAutoApprover
|
|
@@ -569,3 +588,56 @@ async def test_workspace_auto_approver_does_not_cache_the_tool_name(tmp_path) ->
|
|
|
569
588
|
assert inside.kind == "allow_once"
|
|
570
589
|
assert outside.kind == "deny_once"
|
|
571
590
|
assert len(inner.requests) == 1
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
@pytest.mark.asyncio
|
|
594
|
+
async def test_workspace_auto_approver_allows_sandboxed_shell_inside_writable_roots(tmp_path) -> None:
|
|
595
|
+
from steerable_agent_runtime.approval import WorkspaceAutoApprover
|
|
596
|
+
|
|
597
|
+
project = tmp_path / "111-2"
|
|
598
|
+
project.mkdir()
|
|
599
|
+
source = tmp_path / "sources"
|
|
600
|
+
source.mkdir()
|
|
601
|
+
inner = _ScriptedApprover([ApprovalDecision("deny_once", "should not ask")])
|
|
602
|
+
approver = WorkspaceAutoApprover(inner, [str(project), str(source)], sandbox_enforced=True)
|
|
603
|
+
|
|
604
|
+
omitted = await approver.approve(_request("local_exec_shell", {"command": "mkdir notes"}))
|
|
605
|
+
nested = await approver.approve(
|
|
606
|
+
_request("local_exec_shell", {"command": "touch a.md", "cwd": str(project / "notes")})
|
|
607
|
+
)
|
|
608
|
+
linked = await approver.approve(
|
|
609
|
+
_request("bash", {"command": "ls", "cwd": str(source / "raw")})
|
|
610
|
+
)
|
|
611
|
+
relative = await approver.approve(
|
|
612
|
+
_request("shell", {"command": "pwd", "cwd": "subdir"})
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
assert omitted.kind == "allow_once"
|
|
616
|
+
assert nested.kind == "allow_once"
|
|
617
|
+
assert linked.kind == "allow_once"
|
|
618
|
+
assert relative.kind == "allow_once"
|
|
619
|
+
assert inner.requests == []
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
@pytest.mark.asyncio
|
|
623
|
+
async def test_workspace_auto_approver_asks_for_shell_that_leaves_the_sandbox(tmp_path) -> None:
|
|
624
|
+
from steerable_agent_runtime.approval import WorkspaceAutoApprover
|
|
625
|
+
|
|
626
|
+
project = tmp_path / "111-2"
|
|
627
|
+
project.mkdir()
|
|
628
|
+
inner = _ScriptedApprover([ApprovalDecision("allow_once", "user allowed")] * 3)
|
|
629
|
+
confined = WorkspaceAutoApprover(inner, [str(project)], sandbox_enforced=True)
|
|
630
|
+
open_sandbox = WorkspaceAutoApprover(inner, [str(project)], sandbox_enforced=False)
|
|
631
|
+
|
|
632
|
+
outside = await confined.approve(
|
|
633
|
+
_request("local_exec_shell", {"command": "ls", "cwd": str(tmp_path / "other")})
|
|
634
|
+
)
|
|
635
|
+
climbed = await confined.approve(
|
|
636
|
+
_request("local_exec_shell", {"command": "ls", "cwd": "../outside"})
|
|
637
|
+
)
|
|
638
|
+
unsandboxed = await open_sandbox.approve(
|
|
639
|
+
_request("local_exec_shell", {"command": "ls", "cwd": str(project)})
|
|
640
|
+
)
|
|
641
|
+
|
|
642
|
+
assert [item.kind for item in (outside, climbed, unsandboxed)] == ["allow_once"] * 3
|
|
643
|
+
assert [item.tool_name for item in inner.requests] == ["local_exec_shell"] * 3
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_antihallucination.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_approval_policy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_cache_control.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_compaction_policy.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_compaction_strategy.py
RENAMED
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_content_parts.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_delegation_gate.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_error_taxonomy.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_fragment_bounds.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_gateway_catalog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_harness_spec.py
RENAMED
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_history_persistence.py
RENAMED
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_in_memory_storage.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_llm_gemini_wire.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_llm_responses_wire.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_llm_stream_e2e.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_llm_wire_helpers.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_long_session.py
RENAMED
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_loop_cancellation.py
RENAMED
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_loop_sandbox_event.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_loop_terminal.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_model_catalog.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_model_equivalence.py
RENAMED
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_model_resolve.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_native_default.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_observation_aging.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_orchestration.py
RENAMED
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_parallel_tools.py
RENAMED
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_provider_compat.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_provider_presets.py
RENAMED
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_pyo3_api_surface.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_replay_crosslang.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_soft_timeout.py
RENAMED
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_sqlite_storage.py
RENAMED
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_storage_contract.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_stream_strip.py
RENAMED
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_system_proxy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_tool_exposure.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_tool_hygiene.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_tool_presentation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_tool_timeout.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_trace_recorder.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_transport_jsonrpc.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_transport_sse.py
RENAMED
|
File without changes
|
{steerable_agent_runtime-0.6.61 → steerable_agent_runtime-0.6.63}/tests/test_usage_attribution.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|