Import ducklm runtime

This commit is contained in:
2026-05-10 23:37:56 +08:00
parent fd1a045488
commit dc8267880a
90 changed files with 9171 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
from app.api.server import chat, health, resolve_permission, resolve_secret
from app.core.permission_resolution import PermissionResolutionRequest, SecretResolutionRequest
from app.core.contracts import UserTask
def test_health_handler() -> None:
assert health() == {"status": "ok"}
def test_chat_handler_returns_runtime_events() -> None:
body = chat(UserTask(input="hello from handler test"))
assert body["status"] == "completed"
assert body["events"][0]["type"] == "task_received"
def test_resolve_permission_handler_allows_completion() -> None:
initial = chat(UserTask(input="запусти pwd"))
if initial["status"] == "awaiting_permission":
body = resolve_permission(
PermissionResolutionRequest(task_id=initial["task_id"], decision="allow_once")
)
assert body["status"] in {"completed", "failed"}
def test_resolve_secret_handler_requires_pending_request() -> None:
body = resolve_secret(SecretResolutionRequest(task_id="missing", secret="x"))
assert body["status"] == "failed"
+37
View File
@@ -0,0 +1,37 @@
from app.core.contracts import CriticScore, ExecutionDirective, PlanStep, UserTask
def test_user_task_defaults() -> None:
task = UserTask(input="hello")
assert task.task_id
assert task.session_id
def test_plan_step_supports_dependencies() -> None:
step = PlanStep(
id="step-1",
kind="tool",
tool="shell_exec",
description="run command",
depends_on=[],
)
assert step.tool == "shell_exec"
def test_critic_score_bounds() -> None:
score = CriticScore(
correctness=1.0,
usefulness=0.5,
safety=0.0,
memory_store=False,
weight=0.2,
explanation="ok",
)
assert score.weight == 0.2
def test_execution_directive_defaults() -> None:
directive = ExecutionDirective(type="noop")
assert directive.payload == {}
assert directive.confidence == 0.0
+25
View File
@@ -0,0 +1,25 @@
from app.core.contracts import UserTask
from app.runtime.runtime_controller import RuntimeController
def test_runtime_loop_emits_basic_events() -> None:
controller = RuntimeController()
result = controller.handle_task(UserTask(input="hello runtime"))
event_types = [event["type"] for event in result["events"]]
assert result["status"] == "completed"
assert "message" in result["result"]
assert "task_received" in event_types
assert "context_built" in event_types
assert "task_completed" in event_types
def test_runtime_loop_routes_natural_language_shell_request_to_permission_flow() -> None:
controller = RuntimeController()
result = controller.handle_task(UserTask(input="запусти sudo apt update"))
event_types = [event["type"] for event in result["events"]]
assert result["status"] == "awaiting_permission"
assert result["directive"]["type"] == "tool"
assert result["directive"]["payload"]["tool"] == "shell_exec"
assert "permission_requested" in event_types
assert "task_awaiting_permission" in event_types
assert result["result"]["error"] == "Permission required before execution."
+147
View File
@@ -0,0 +1,147 @@
import json
from pathlib import Path
from app.core.contracts import UserTask
from app.runtime.runtime_controller import RuntimeController
def _write_config_tree(base_dir: Path) -> None:
(base_dir / "config").mkdir()
(base_dir / "data" / "events").mkdir(parents=True, exist_ok=True)
(base_dir / "data" / "state").mkdir(parents=True, exist_ok=True)
(base_dir / "data" / "permissions").mkdir(parents=True, exist_ok=True)
(base_dir / "models").mkdir(exist_ok=True)
configs = {
"models.json": {
"orchestrator_path": "models/llama.gguf",
"coder_path": "models/xcoder.gguf",
"critic_path": "models/gemma.gguf",
"embeddings_path": "models/all-MiniLM-L6-v2",
"inference": {},
},
"prompts.json": {
"orchestration_prompt": "",
"planning_prompt": "",
"coder_prompt": "",
"critic_prompt": "",
},
"permissions.json": {
"dangerous_commands": {"rm": "ask_always", "sudo": "ask_always"},
"sensitive_paths": ["/etc", "/usr", "/var"],
"default_approval_behavior": "ask_always",
},
"runtime.json": {
"step_timeout_ms": 5000,
"task_timeout_ms": 30000,
"planner_retry_limit": 1,
"tool_retry_limit": 0,
"replan_limit": 0,
"max_execution_steps": 5,
"retrieval_top_k": 3,
"memory_thresholds": {},
"critic_fallback_policy": "continue_without_critic",
"checkpoint_policy": {"save_on_transition": True},
"event_retention_policy": {"keep_all": True},
"streaming_settings": {"enabled": True},
},
}
for name, payload in configs.items():
(base_dir / "config" / name).write_text(json.dumps(payload), encoding="utf-8")
def test_file_write_and_read_tool_flow(tmp_path: Path) -> None:
_write_config_tree(tmp_path)
controller = RuntimeController(base_dir=tmp_path)
target = tmp_path / "notes" / "test.txt"
write_result = controller.handle_task(
UserTask(
input="write a file",
context={
"requested_tool": "file_write",
"tool_args": {"path": str(target), "content": "hello from ducklm"},
},
)
)
assert write_result["status"] == "completed"
assert target.read_text(encoding="utf-8") == "hello from ducklm"
read_result = controller.handle_task(
UserTask(
input="read the file",
context={
"requested_tool": "file_read",
"tool_args": {"path": str(target)},
},
)
)
assert read_result["status"] == "completed"
assert read_result["result"]["output"] == "hello from ducklm"
def test_shell_exec_requires_permission_for_dangerous_command(tmp_path: Path) -> None:
_write_config_tree(tmp_path)
controller = RuntimeController(base_dir=tmp_path)
result = controller.handle_task(
UserTask(
input="run dangerous shell command",
context={
"requested_tool": "shell_exec",
"tool_args": {"command": "rm -rf /tmp/nonexistent"},
},
)
)
assert result["status"] == "awaiting_permission"
assert "permission_request" in result["result"]
def test_shell_exec_allows_safe_command(tmp_path: Path) -> None:
_write_config_tree(tmp_path)
controller = RuntimeController(base_dir=tmp_path)
result = controller.handle_task(
UserTask(
input="run safe shell command",
context={
"requested_tool": "shell_exec",
"tool_args": {"command": "pwd"},
},
)
)
assert result["status"] == "completed"
assert str(tmp_path) in result["result"]["output"]
def test_permission_resolution_can_resume_task(tmp_path: Path) -> None:
_write_config_tree(tmp_path)
controller = RuntimeController(base_dir=tmp_path)
initial = controller.handle_task(
UserTask(
input="запусти sudo apt update",
)
)
assert initial["status"] == "awaiting_permission"
resumed = controller.resolve_permission(task_id=initial["task_id"], decision="deny")
assert resumed["status"] == "failed"
assert resumed["result"]["error"] == "Permission denied by user."
def test_sudo_permission_resolution_requests_secret_input(tmp_path: Path) -> None:
_write_config_tree(tmp_path)
controller = RuntimeController(base_dir=tmp_path)
initial = controller.handle_task(UserTask(input="запусти sudo apt update"))
assert initial["status"] == "awaiting_permission"
resumed = controller.resolve_permission(task_id=initial["task_id"], decision="allow_once")
assert resumed["status"] == "awaiting_input"
assert resumed["result"]["secret_request"]["kind"] == "sudo_password"
def test_secret_resolution_continues_after_pending_secret_saved(tmp_path: Path) -> None:
_write_config_tree(tmp_path)
controller = RuntimeController(base_dir=tmp_path)
initial = controller.handle_task(UserTask(input="запусти sudo apt update"))
resumed = controller.resolve_permission(task_id=initial["task_id"], decision="allow_once")
assert resumed["status"] == "awaiting_input"
final = controller.resolve_secret(task_id=initial["task_id"], secret="wrongpass")
assert final["status"] in {"completed", "failed"}
assert "error" in final["result"] or "output" in final["result"]