diff --git a/AGENTS.md b/AGENTS.md index d06f76c..4fe7aa8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,9 +15,9 @@ 当用户请求处理仓库内任务时,按以下最小闭环执行: -1. 先检查最相关的文件。 -2. 选择最小的下一步动作。 -3. 只有在减少不确定性或执行动作确有必要时才调用工具。 +1. 先判断运行时状态、已有上下文和当前用户输入是否已经足以决定下一步。 +2. 只有在减少不确定性或执行动作确有必要时,才检查最相关的文件或调用工具。 +3. 选择最小的下一步动作。 4. 使用工具后重新判断结果。 5. 持续循环,直到得到最终答案或出现必须由用户补充的信息。 diff --git a/src/cc_slim/engine.py b/src/cc_slim/engine.py index b5c7682..213a5bc 100644 --- a/src/cc_slim/engine.py +++ b/src/cc_slim/engine.py @@ -113,6 +113,20 @@ class Agent: return for call in result["tool_calls"]: + denied_output = self._check_tool_permission(call["name"], call["input"]) + if denied_output is not None: + yield {"type": "tool_result", "name": call["name"], "output": denied_output} + self.history.append( + { + "role": "tool", + "tool_call_id": call["id"], + "name": call["name"], + "content": denied_output, + } + ) + self._save_message(self.history[-1]) + continue + yield {"type": "tool_call", "name": call["name"], "input": call["input"]} tool_output = self._run_tool(call["name"], call["input"]) yield {"type": "tool_result", "name": call["name"], "output": tool_output} @@ -270,14 +284,19 @@ class Agent: yield {"type": "text", "content": result["text"]} return result - def _run_tool(self, name: str, payload: dict[str, Any]) -> str: - if self.permission_checker and not self.permission_checker.is_allowed(name): + def _check_tool_permission(self, name: str, payload: dict[str, Any]) -> str | None: + if not self.permission_checker: + return None + if not self.permission_checker.is_allowed(name): return self.permission_checker.denial_reason(name) - if self.permission_checker and self.permission_checker.requires_confirmation(name): + if self.permission_checker.requires_confirmation(name): if not self.confirm_tool: return self.permission_checker.denial_reason(name) if not self.confirm_tool(name, payload): return self.permission_checker.denial_reason(name) + return None + + def _run_tool(self, name: str, payload: dict[str, Any]) -> str: tool = self.tools.get(name) if not tool: return f"Tool not found: {name}" diff --git a/src/cc_slim/main.py b/src/cc_slim/main.py index b54f3c6..0d3d273 100644 --- a/src/cc_slim/main.py +++ b/src/cc_slim/main.py @@ -31,7 +31,11 @@ def render_stream(agent: Agent, user_input: str) -> None: printed_text = False console.print(f"[cyan]->[/cyan] {event['name']}({event['input']})") elif event["type"] == "tool_result": - console.print(f"[green]✓[/green] {event['name']} done") + output = str(event.get("output", "")) + if output.startswith("Tool blocked in plan mode:") or output.startswith("Permission denied for tool:"): + console.print(f"[red]{output}[/red]") + else: + console.print(f"[green]✓[/green] {event['name']} done") elif event["type"] == "error": if printed_text: console.print()