Integrate memory policy and reflection runtime

This commit is contained in:
2026-05-21 22:40:11 +08:00
parent 9a8f058008
commit 6f58df82c9
21 changed files with 2014 additions and 60 deletions
+70
View File
@@ -0,0 +1,70 @@
from __future__ import annotations
import logging
from typing import Any
from duck_core.model_client import ModelClient
from duck_core.tools.base import ToolResult
logger = logging.getLogger(__name__)
class CoderTool:
"""Tool that delegates code generation to the coder-role LLM.
The coder model receives the task description and relevant context,
then returns code or technical analysis.
"""
name = "coder"
risk_level = "low"
def __init__(
self,
model_client: ModelClient | None = None,
role: str = "coder",
max_output_tokens: int = 16384,
):
self._model_client = model_client
self._role = role
self._max_output_tokens = max_output_tokens
async def run(self, args: dict[str, Any]) -> ToolResult:
task_description = str(args.get("task_description", "")).strip()
if not task_description:
return ToolResult(ok=False, error="task_description is required for coder tool")
context = str(args.get("context", "")).strip()
language = str(args.get("language", "python")).strip()
prompt_parts = [f"Task: {task_description}"]
if language:
prompt_parts.append(f"Language: {language}")
if context:
prompt_parts.append(f"Context:\n{context}")
messages = [{"role": "user", "content": "\n\n".join(prompt_parts)}]
try:
if self._model_client is None:
return ToolResult(
ok=False,
error="Coder tool has no model client configured",
)
response = await self._model_client.chat(
self._role,
messages,
max_output_tokens=self._max_output_tokens,
)
return ToolResult(
ok=True,
output=response.content,
metadata={
"role": self._role,
"model": response.model,
"latency_ms": response.latency_ms,
},
)
except Exception as exc:
logger.warning("Coder tool failed: %s", exc)
return ToolResult(ok=False, error=f"Coder tool failed: {exc}")
+12 -1
View File
@@ -1,6 +1,7 @@
from typing import Any
from duck_core.tools.base import Tool, ToolResult
from duck_core.tools.coder import CoderTool
from duck_core.tools.file_read import FileReadTool
from duck_core.tools.file_write import FileWriteTool
from duck_core.tools.list_dir import ListDirTool
@@ -13,7 +14,7 @@ class ToolGateway:
self.tools = {tool.name: tool for tool in tools}
@classmethod
def default(cls, workspace: str) -> "ToolGateway":
def default(cls, workspace: str, model_client: Any = None) -> "ToolGateway":
return cls(
[
FileReadTool(workspace),
@@ -21,9 +22,19 @@ class ToolGateway:
ListDirTool(workspace),
SearchFilesTool(workspace),
ShellExecSafeTool(workspace),
CoderTool(model_client=model_client),
]
)
def with_model_client(self, model_client: Any) -> "ToolGateway":
"""Return a new gateway with model-dependent tools configured."""
new_tools = list(self.tools.values())
# Replace coder tool with one that has model_client
new_tools = [
t for t in new_tools if not isinstance(t, CoderTool)
] + [CoderTool(model_client=model_client)]
return self.__class__(new_tools)
async def run_action(
self, action: dict[str, Any], approved: bool = False, password: str | None = None
) -> ToolResult: