fix: 完善工具约束与项目文档说明

This commit is contained in:
JOJO 2026-04-10 14:33:41 +08:00
parent 90233690ad
commit 1bda147a6f
7 changed files with 50 additions and 12 deletions

View File

@ -1,6 +1,6 @@
# Repository Guidelines (Code-Verified)
> Last verified against current codebase: 2026-04-06
> Last verified against current codebase: 2026-04-10
> Scope: `/Users/jojo/Desktop/agents/正在修复中/agents`
这份文档基于当前仓库实际代码重写。若与未来代码冲突,以代码为准并及时更新本文档。
@ -12,7 +12,7 @@
- `server/app.py`: 推荐的 Web 服务入口(封装并转发到 `server/app_legacy.py`
- `web_server.py`: 兼容入口,已标记 deprecated但仍可启动
- **后端核心目录**
- `server/`: Flask + Socket.IO 业务主线chat flow、conversation、tasks、status、api_v1 等
- `server/`: Flask 业务主线chat/task 以 REST 任务轮询为主Socket.IO 主要用于兼容与实时辅助通道
- `core/`: 终端与工具编排(`main_terminal.py`、`web_terminal.py`、`main_terminal_parts/*`
- `modules/`: 可复用能力模块terminal/file/memory/sub_agent/upload_security/user 等)
- `config/`: 配置拆分(`api.py`, `limits.py`, `terminal.py`, `paths.py` ...),由 `config/__init__.py` 聚合并加载 `.env`

View File

@ -10,13 +10,13 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
### Entry Points
- **CLI模式**: `python main.py` - 启动命令行交互式 Agent
- **Web模式**: `python web_server.py` - 启动 Flask + Socket.IO Web 服务器 (默认端口 8091)
- **Web模式**: `python web_server.py` - 启动 Flask Web 服务器(主链路为 REST 任务轮询,默认端口 8091
### Key Components
**core/**
- `MainTerminal` - CLI 主终端,处理用户输入和 AI 对话循环
- `WebTerminal` - Web 终端,继承 MainTerminal增加实时推送和对话持久化
- `WebTerminal` - Web 终端,继承 MainTerminal支持轮询任务与实时通道兼容能力
- `tool_config.py` - 定义所有工具的配置和分类
**modules/**
@ -37,7 +37,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- `terminal_factory.py` - 终端类型工厂
**static/**
- Vue + Socket.IO 前端,包含对话流、终端输出、资源监控面板
- Vue 前端(聊天主链路使用 REST 任务轮询,保留 Socket.IO 兼容能力),包含对话流、终端输出、资源监控面板
**docker/**
- `terminal.Dockerfile` - 终端容器镜像构建配置

View File

@ -14,7 +14,7 @@
### 🌐 双端架构
- **Web 模式**: 基于 Flask + Socket.IO + Vue 3 的现代化 Web 界面
- **Web 模式**: 基于 Flask + REST 任务轮询 + Vue 3 的现代化 Web 界面(保留 Socket.IO 兼容通道)
- 实时消息流式传输
- 多对话管理
- 可视化文件管理器
@ -211,7 +211,7 @@ agents/
│ ├── app.py # Flask应用
│ ├── chat_flow_*.py # 对话流程处理
│ ├── conversation.py # 对话管理
│ ├── socket_handlers.py # WebSocket处理
│ ├── socket_handlers.py # Socket.IO 连接与兼容事件处理(聊天主链路已迁移到 REST 任务轮询)
│ └── ...
├── modules/ # 功能模块
│ ├── file_manager.py # 文件管理
@ -261,7 +261,7 @@ static/src/
### 数据流
1. **用户输入**WebSocket/CLI
1. **用户输入**REST APIWeb/CLI
2. **消息处理** → ContextManager 构建上下文
3. **API 调用** → DeepSeekClient 发送请求
4. **流式响应** → 实时解析工具调用

View File

@ -20,7 +20,7 @@
},
"run-command-guide": {
"keywords": [
"run_command", "runcommand", "后台指令", "后台命令", "命令后台运行", "后台执行",
"run_command", "runcommand", "后台指令", "后台命令", "命令后台运行", "后台执行","git","下载","仓库",
"command_id", "wait_runcommand_id", "sleep wait_runcommand_id", "run_in_background",
"超时", "timeout", "终端命令", "shell命令", "执行命令",
"npm run build", "pip install", "brew install", "apt install", "cargo build", "mvn package",

View File

@ -204,6 +204,19 @@ class MainTerminalToolsExecutionMixin:
return False
return normalized in self._get_visited_read_files()
def _mark_file_as_read_visited(self, path: Any) -> None:
normalized = self._normalize_tool_path(path)
if not normalized:
return
visited = self._get_visited_read_files()
if normalized in visited:
return
visited.add(normalized)
self.context_manager._set_meta_flag(
self._file_read_meta_key(),
sorted(visited),
)
def _target_file_exists(self, path: Any) -> bool:
try:
valid, _, full_path = self.file_manager._validate_path(str(path or ""))
@ -267,10 +280,18 @@ class MainTerminalToolsExecutionMixin:
return "sub-agent-guide"
if (
tool_name == "run_command"
and bool(getattr(self, "skill_strict_run_command_background_enabled", False))
and bool((arguments or {}).get("run_in_background", False))
):
return "run-command-guide"
run_in_background = bool((arguments or {}).get("run_in_background", False))
if (
run_in_background
and bool(getattr(self, "skill_strict_run_command_background_enabled", False))
):
return "run-command-guide"
if (
(not run_in_background)
and bool(getattr(self, "skill_strict_run_command_foreground_enabled", False))
):
return "run-command-guide"
return None
def _check_skill_strict_prerequisite(self, tool_name: str, arguments: Optional[Dict[str, Any]] = None) -> Optional[Dict[str, Any]]:
@ -695,6 +716,10 @@ class MainTerminalToolsExecutionMixin:
else:
mode = "a" if append_flag else "w"
result = self.file_manager.write_file(path, content, mode=mode)
if isinstance(result, dict) and result.get("success"):
# write_file 成功后,该文件视作当前会话已“接触”,
# 允许后续继续 write/edit 而不再触发先读拦截。
self._mark_file_as_read_visited(result.get("path") or path)
elif tool_name == "edit_file":
read_guard_error = self._check_read_before_edit_prerequisite(tool_name, arguments)

View File

@ -97,6 +97,9 @@ class MainTerminalToolsPolicyMixin:
# Skill 强约束开关
self.skill_strict_terminal_enabled = bool(effective_config.get("skill_strict_terminal_enabled", False))
self.skill_strict_sub_agent_enabled = bool(effective_config.get("skill_strict_sub_agent_enabled", False))
self.skill_strict_run_command_foreground_enabled = bool(
effective_config.get("skill_strict_run_command_foreground_enabled", False)
)
self.skill_strict_run_command_background_enabled = bool(
effective_config.get("skill_strict_run_command_background_enabled", False)
)

View File

@ -21,6 +21,16 @@ export default defineConfig({
// 统一静态资源基路径,避免动态 import 走到 /assets/* 导致 404
base: '/static/dist/',
plugins: [vue()],
css: {
preprocessorOptions: {
scss: {
silenceDeprecations: ['legacy-js-api']
},
sass: {
silenceDeprecations: ['legacy-js-api']
}
}
},
build: {
outDir: 'static/dist',
emptyOutDir: false,