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
+35
View File
@@ -0,0 +1,35 @@
from __future__ import annotations
from app.core.contracts import ToolResult, UserTask
from app.tools.base import BaseTool
from app.tools.sandbox import ToolSandbox
class Tool(BaseTool):
name = "file_read"
description = "Read file contents"
def __init__(self, sandbox: ToolSandbox) -> None:
self._sandbox = sandbox
def execute(self, task: UserTask, args: dict[str, object]) -> ToolResult:
path = args.get("path")
if not path:
return ToolResult(tool=self.name, ok=False, error="Missing path")
try:
resolved = self._sandbox.ensure_path_allowed(str(path))
if not resolved.exists():
return ToolResult(tool=self.name, ok=False, error=f"File not found: {path}")
content = resolved.read_text(encoding="utf-8")
return ToolResult(
tool=self.name,
ok=True,
output=content,
metadata={"path": str(resolved), "size": len(content)},
)
except PermissionError as e:
return ToolResult(tool=self.name, ok=False, error=f"Access denied: {e}")
except FileNotFoundError as e:
return ToolResult(tool=self.name, ok=False, error=f"File not found: {path}")
except Exception as e:
return ToolResult(tool=self.name, ok=False, error=f"Error: {e}")
+10
View File
@@ -0,0 +1,10 @@
{
"name": "file_read",
"version": "1.0",
"entrypoint": "Tool",
"description": "Read file contents from allowed paths",
"args_schema": {
"path": {"type": "string", "required": true, "description": "File path to read"}
},
"requires_permission": false
}
+33
View File
@@ -0,0 +1,33 @@
from __future__ import annotations
from app.core.contracts import ToolResult, UserTask
from app.tools.base import BaseTool
from app.tools.sandbox import ToolSandbox
class Tool(BaseTool):
name = "file_write"
description = "Write content to file"
def __init__(self, sandbox: ToolSandbox) -> None:
self._sandbox = sandbox
def execute(self, task: UserTask, args: dict[str, object]) -> ToolResult:
path = args.get("path")
content = str(args.get("content", ""))
if not path:
return ToolResult(tool=self.name, ok=False, error="Missing path")
try:
resolved = self._sandbox.ensure_path_allowed(str(path))
resolved.parent.mkdir(parents=True, exist_ok=True)
resolved.write_text(content, encoding="utf-8")
return ToolResult(
tool=self.name,
ok=True,
output=f"Wrote {len(content)} bytes",
metadata={"path": str(resolved), "size": len(content)},
)
except PermissionError as e:
return ToolResult(tool=self.name, ok=False, error=f"Access denied: {e}")
except Exception as e:
return ToolResult(tool=self.name, ok=False, error=f"Error: {e}")
@@ -0,0 +1,11 @@
{
"name": "file_write",
"version": "1.0",
"entrypoint": "Tool",
"description": "Write content to file",
"args_schema": {
"path": {"type": "string", "required": true, "description": "File path to write"},
"content": {"type": "string", "required": true, "description": "Content to write"}
},
"requires_permission": true
}
+112
View File
@@ -0,0 +1,112 @@
from __future__ import annotations
import logging
from typing import Any
from app.core.contracts import ToolResult, UserTask
from app.tools.base import BaseTool
logger = logging.getLogger(__name__)
class Tool(BaseTool):
name = "memory"
description = "Memory operations: insert, search, list"
def __init__(self, memory_interface=None) -> None:
self._memory = memory_interface
def execute(self, task: UserTask, args: dict[str, Any]) -> ToolResult:
action = args.get("action", "search")
if action == "insert":
return self._insert(task, args)
elif action == "search":
return self._search(task, args)
elif action == "list":
return self._list(task, args)
else:
return ToolResult(tool=self.name, ok=False, error=f"Unknown action: {action}")
def _insert(self, task: UserTask, args: dict[str, Any]) -> ToolResult:
text = args.get("text", "")
kind = args.get("kind", "fact")
source = args.get("source", "user")
weight = args.get("weight", 0.5)
if not text:
return ToolResult(tool=self.name, ok=False, output="", error="text is required")
if not self._memory:
return ToolResult(tool=self.name, ok=False, output="", error="Memory not available")
try:
entry = self._memory.insert(
text=text,
kind=kind,
source=source,
task_id=task.task_id,
session_id=task.session_id,
weight=weight,
)
return ToolResult(
tool=self.name,
ok=True,
output=f"Stored: {entry.id}",
metadata={"entry_id": entry.id},
)
except Exception as e:
logger.warning(f"Memory insert failed: {e}")
return ToolResult(tool=self.name, ok=False, output="", error=str(e))
def _search(self, task: UserTask, args: dict[str, Any]) -> ToolResult:
query = args.get("query", "")
top_k = args.get("top_k", 5)
if not query:
return ToolResult(tool=self.name, ok=False, output="", error="query is required")
if not self._memory:
return ToolResult(tool=self.name, ok=False, output="", error="Memory not available")
try:
results = self._memory.search(query, top_k=top_k)
if not results:
return ToolResult(tool=self.name, ok=True, output="No results found", metadata={"count": 0})
output_lines = []
for entry, score in results:
output_lines.append(f"[{score:.2f}] {entry.text[:100]}")
return ToolResult(
tool=self.name,
ok=True,
output="\n".join(output_lines),
metadata={"count": len(results)},
)
except Exception as e:
logger.warning(f"Memory search failed: {e}")
return ToolResult(tool=self.name, ok=False, output="", error=str(e))
def _list(self, task: UserTask, args: dict[str, Any]) -> ToolResult:
limit = args.get("limit", 10)
if not self._memory:
return ToolResult(tool=self.name, ok=False, output="", error="Memory not available")
try:
entries = self._memory.get_recent(limit=limit)
if not entries:
return ToolResult(tool=self.name, ok=True, output="No memories", metadata={"count": 0})
output_lines = []
for entry in entries:
output_lines.append(f"{entry.kind}: {entry.text[:80]}")
return ToolResult(
tool=self.name,
ok=True,
output="\n".join(output_lines),
metadata={"count": len(entries)},
)
except Exception as e:
logger.warning(f"Memory list failed: {e}")
return ToolResult(tool=self.name, ok=False, output="", error=str(e))
@@ -0,0 +1,22 @@
{
"name": "memory",
"version": "1.0",
"entrypoint": "Tool",
"description": "Memory operations: insert, search, list",
"args_schema": {
"action": {
"type": "string",
"required": true,
"description": "Action: insert, search, or list",
"enum": ["insert", "search", "list"]
},
"text": {"type": "string", "required": false, "description": "Text to store (insert)"},
"query": {"type": "string", "required": false, "description": "Query string (search)"},
"kind": {"type": "string", "required": false, "description": "Memory kind: fact, command, etc"},
"source": {"type": "string", "required": false, "description": "Source: user, system, etc"},
"weight": {"type": "number", "required": false, "description": "Memory weight 0-1"},
"top_k": {"type": "number", "required": false, "description": "Max results (search)"},
"limit": {"type": "number", "required": false, "description": "Max entries (list)"}
},
"requires_permission": false
}
+33
View File
@@ -0,0 +1,33 @@
from __future__ import annotations
from app.core.contracts import ToolResult, UserTask
from app.tools.base import BaseTool
from app.tools.sandbox import ToolSandbox
class Tool(BaseTool):
name = "shell_exec"
description = "Execute shell commands"
def __init__(self, sandbox: ToolSandbox) -> None:
self._sandbox = sandbox
def execute(self, task: UserTask, args: dict[str, object]) -> ToolResult:
command = str(args.get("command", "")).strip()
if not command:
return ToolResult(tool=self.name, ok=False, error="Missing command", metadata={"exit_code": -1})
cwd = args.get("cwd")
stdin_secret = args.get("stdin_secret")
completed = self._sandbox.run_shell(
command=command,
cwd=str(cwd) if cwd else None,
stdin_data=str(stdin_secret) if stdin_secret is not None else None,
)
output = completed.stdout if completed.returncode == 0 else completed.stderr or completed.stdout
return ToolResult(
tool=self.name,
ok=completed.returncode == 0,
output=output,
error=None if completed.returncode == 0 else f"Command failed with exit code {completed.returncode}",
metadata={"exit_code": completed.returncode},
)
@@ -0,0 +1,12 @@
{
"name": "shell_exec",
"version": "1.0",
"entrypoint": "Tool",
"description": "Execute shell commands in sandboxed environment",
"args_schema": {
"command": {"type": "string", "required": true, "description": "Shell command to execute"},
"cwd": {"type": "string", "required": false, "description": "Working directory"},
"stdin_secret": {"type": "string", "required": false, "description": "Data to pass via stdin"}
},
"requires_permission": true
}