# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

> 和用户交流时默认使用中文。

## Project Overview

多用户 AI Agent 系统，产品暂定名为 **Astrion**（`Astr-` 星星/天体 + `-ion` 粒子后缀，意象为“星之子、星际粒子”）。为每个登录用户提供独立的 Docker 容器环境，支持终端交互、文件操作、对话管理和实时监控。主要用于学习和实验"智能体 + 真实 Dev Workflow"，代码大量由 AI 生成。

## Core Architecture

### Entry Points
- **统一入口**: `python main.py` - 当前实现默认进入 Web 启动流程（thinking_mode=True）
- **推荐 Web 入口**: `python -m server.app` - 封装并转发到 `server/app_legacy.py`，主链路为 REST 任务轮询，默认端口 8091
- **兼容入口**: `python web_server.py` - 已标记 deprecated，但仍可启动

### Key Components

**server/** (Flask 业务主线，chat/task/status 已拆分子包，以 REST 任务轮询为主，Socket.IO 用于兼容与实时辅助通道)
- `app.py` / `app_legacy.py` - Web 服务入口与遗留实现
- `chat/` / `chat_flow*.py` - 对话接口（已拆分为子包）与任务流编排（runner / tool_loop / stream_loop / task_main 等拆分）
- `status/` - 状态/项目/容器/工作区相关接口（已拆分为子包）
- `tasks/` - 任务管理接口（已拆分为子包）
- `goal_flow.py` - 自主目标循环
- `deep_compression.py` - 上下文深度压缩
- `conversation.py` / `files.py` / `auth.py` / `admin.py` / `api_v1.py` / `context.py` - 对话、文件、认证、管理、API v1、请求上下文接口

**core/**
- `MainTerminal` (`main_terminal.py`) - CLI 主终端，处理用户输入和 AI 对话循环；逻辑拆分到 `core/main_terminal_parts/*`（commands / context / tools_definition / tools_execution / tools_policy / tools_read 等）
- `WebTerminal` (`web_terminal.py`) - Web 终端，继承 MainTerminal，支持轮询任务与实时通道兼容能力
- `tool_config.py` - 定义所有工具的配置和分类

**modules/**
- `user_container_manager.py` - 单用户-单容器管理，负责容器生命周期
- `container_file_proxy.py` - 容器内文件代理，通过 `docker exec` 沙箱化文件操作
- `terminal_manager.py` - 管理多个持久化终端会话
- `persistent_terminal/` - 持久化终端核心（已拆分为 base + mixin 子包）
- `terminal_ops/` - 终端命令执行相关能力（已拆分为 base + mixin 子包）
- `mcp_client_manager/` - MCP 客户端管理（已拆分为子包）
- `file_manager/` - 文件 CRUD，包含搜索、替换和 append/modify streaming 功能（已拆分为子包）
- `conversation_manager/` - 对话历史持久化（已拆分为 base + mixin 子包）
- `context_manager/` - 上下文构建、token统计、对话管理（已拆分为 base + mixin 子包）
- `memory_manager.py` - 长期记忆管理
- `todo_manager.py` - 待办事项管理
- `modules/sub_agent/` - 子智能体任务调度与执行（主进程内协程，工具调用复用主 WebTerminal）
- `user_manager.py` - 用户认证和工作区管理
- `upload_security.py` - 上传文件隔离扫描

**utils/**
- `api_client.py` - 兼容入口，实际实现已迁移到 `utils/api_client/` 子包（mixin 组织）
- `tool_result_formatter.py` - 兼容入口，实际实现已迁移到 `utils/tool_result_formatter/` 子包
- `terminal_factory.py` - 终端类型工厂

**static/**
- Vue 3 + TS 前端（`static/src/`，分层为 `app/` `stores/` `components/` `composables/`），聊天主链路使用 REST 任务轮询，保留 Socket.IO 兼容能力，包含对话流、终端输出、资源监控面板
- 监控动画核心文件：`static/src/components/chat/monitor/MonitorDirector.ts`（动画与场景执行）、`static/src/stores/monitor.ts`（事件队列与状态机）

**cli/**
- React 19 + Ink 6 + TypeScript CLI 前端（正在重写中），连接现有本地 Web API（默认 `127.0.0.1:8091`），不是独立 agent runtime
- 关键文件：`cli/src/App.tsx`、`cli/src/components.tsx`、`cli/src/eventMapper.ts`、`cli/src/api.ts`

**docker/**
- `terminal.Dockerfile` - 终端容器镜像构建配置

## Development Commands

### Build & Run
```bash
# === 开箱即用（release / 首次部署，推荐）===
# 首次初始化：建 venv、装依赖、跑配置向导（模式/端口/管理员/密钥/模型）
./setup.sh
# 启动（首次无 .env 会自动跑向导，然后起服务）
./start.sh
# start.sh 透传参数给 server.app，例如：
./start.sh --thinking-mode

# === 手动方式（开发） ===
# 安装 Python 依赖
pip install -r requirements.txt          # 开发用，宽松
pip install -r requirements.lock.txt     # 可复现/打包用，精确版本

# 构建终端镜像
docker build -f docker/terminal.Dockerfile -t my-agent-shell:latest .

# 统一入口（默认进入 Web 启动流程）
python main.py

# 推荐 Web 启动
python -m server.app
# 可选参数
python -m server.app --path ./project --port 8091 --debug --thinking-mode

# 兼容启动方式（deprecated）
python web_server.py
```

### Frontend (根目录 Vue)
```bash
npm install
# 构建（默认只看最后 5 行，减少 Vite 构建资源列表等无关输出）
npm run build --silent 2>&1 | tail -n 5
# 开发监听（当前脚本是 build watch）
npm run dev
# Lint
npm run lint
```

### CLI (React / Ink)
```bash
npm --prefix cli install
# 开发启动
npm run cli            # 或 npm --prefix cli run dev
# 构建
npm run cli:build
# 类型检查
npm run cli:typecheck
# 可执行命令名（构建后）：agents / agents-cli
```

### Testing
```bash
# 主要离线冒烟用例（unittest）
python -m unittest test.test_server_refactor_smoke

# 改动后端接口适配（如 server/chat/、server/status/、server/tasks/）时补充
python3 -m py_compile server/chat/*.py server/status/*.py server/tasks/*.py

# CLI 最小可复现验证
npm --prefix cli run typecheck
npm --prefix cli run build
```
> 仓库未发现 `pytest.ini`/`pyproject.toml`/`tox.ini`，不要默认要求 `pytest` 作为唯一入口。`test/test_system_message.py` 依赖外部 `MOONSHOT_API_KEY` 与网络，不属于离线稳定用例。

### Debugging
```bash
# 查看容器状态
docker ps -a | grep agent-term

# 查看调试日志（运行态日志默认在 ~/.astrion/astrion/<mode>/logs/）
tail -f ~/.astrion/astrion/host/logs/debug_stream.log   # host 模式
tail -f ~/.astrion/astrion/web/logs/debug_stream.log    # web/docker 模式

# 查看容器统计
tail -f ~/.astrion/astrion/web/logs/container_stats.log
```

## Configuration

主要配置文件：`.env`（复制 `.env.example`）

**必填变量**:
- `AGENT_API_BASE_URL` - OpenAI-compatible API 端点
- `AGENT_API_KEY` - API 密钥
- `AGENT_MODEL_ID` - 模型 ID (例如 deepseek-chat)
- `WEB_SECRET_KEY` - Flask session 密钥

**容器配置** (`config/terminal.py`):
- `TERMINAL_SANDBOX_MODE` - docker/host
- `TERMINAL_SANDBOX_IMAGE` - 容器镜像 (默认 python:3.11-slim)
- `TERMINAL_SANDBOX_NETWORK` - 网络模式 (bridge/none/host)
- `TERMINAL_SANDBOX_CPUS` - CPU 限制
- `TERMINAL_SANDBOX_MEMORY` - 内存限制

**资源限制**:
- `PROJECT_MAX_STORAGE_MB` - 单用户磁盘配额 (默认 2048MB)
- `MAX_ACTIVE_USER_CONTAINERS` - 并发容器数量 (默认 8)

**数据目录与路径变量** (`config/paths.py`，2026-06 更新):

运行态数据默认存放在 `~/.astrion/astrion/<mode>`（对齐 `~/.claude`、`~/.codex`），**不落在源码树**。数据根目录（`data_root`）默认为 `~/.astrion/astrion`，可通过 `ASTRION_DATA_ROOT` 整体搬迁；模式由 `TERMINAL_SANDBOX_MODE` 决定：`host` → `~/.astrion/astrion/host`，其它（默认 docker/web）→ `~/.astrion/astrion/web`。数据根目录下还包含 `settings.json`（唯一配置文件）和 `config/`（部署级配置，host/web 共享）。每个模式目录下含 `data/`（对话、用户库、记忆、sub_agents.json、sub_agent_tasks）、`users/`、`api/users/`、`logs/`。

路径解析优先级（高→低）：
1. 具体目录变量 `DATA_DIR` / `LOGS_DIR` / `USER_SPACE_DIR` / `API_USER_SPACE_DIR`（单独覆盖某目录）
2. 数据根目录变量 `ASTRION_DATA_ROOT`（整体搬迁运行态数据根目录，默认 `~/.astrion/astrion`）
3. 兜底 `~/.astrion/astrion/<mode>`

**Host / Web 双路径机制（2026-06）**:
- `paths.py` 新增 `IS_HOST_MODE`、`WEB_DATA_DIR`、`WEB_USER_SPACE_DIR` 三个固定变量
- host 模式下 `UserManager` 同时加载 `host/` 和 `web/` 的用户与工作区（web 用户不覆盖已有）
- 已有 web 工作区直接复用（保持旧数据可访问），新工作区写入 host/
- web 模式：仅读取 web/ 数据，无变化

> `config/*.json` 分两类：**程序能力**（`docker_risk_markers.json`、`skill_hints.json`）与 `prompts/`、`agentskills/` 一样锚定源码树；**部署级配置**（`custom_models`、`host_workspaces`、`auto_approval`、`goal_review`、`forbidden_commands`、`host_sandbox_policy`）外置到 `~/.astrion/astrion/config/`（`DEPLOY_CONFIG_DIR`，host/web 共享），读取走 `config.resolve_deploy_config(name)`，回退链：部署目录 → 源码树 `.json` → 源码树 `.json.example`。含密钥/机器特定的 5 个不进 git，仓库仅留 `.example`。

**日志策略**:
- API 请求体 dump 默认**关闭**，`AGENT_API_DUMP_ENABLED=1` 开启。
- 混合轮转（`utils/log_rotation.py`）：追加型单文件按大小轮转（默认 20MB×3 份），dump 目录按份保留（默认 30 个）。阈值变量：`AGENT_LOG_ROTATE_MAX_BYTES` / `AGENT_LOG_ROTATE_BACKUPS` / `AGENT_DUMP_KEEP`。

**数据迁移**:
- `scripts/migrate_runtime_data.py`：源码树 → `~/.astrion/astrion/<mode>`，复制+备份+可回滚+幂等，`logs/` 丢弃不迁。脚本复用 config 路径解析（模式由 `.env` 决定），执行前先 `--dry-run` 确认目标。

## Important Implementation Details

### File Operations

文件写入统一使用 `write_file`/`edit_file` 工具完成：`write_file` 负责覆盖或追加内容，`edit_file` 负责精确字符串替换，不再依赖历史版本的流式标签标记。

### Container Architecture

每个用户登录时：
1. `UserContainerManager` 创建专属容器
2. 容器挂载 `users/<username>/project/` 到 `/workspace`
3. 所有文件操作通过 `ContainerFileProxy` 在容器内执行
4. 终端会话通过 `docker exec` 运行
5. 空闲超时或登出后自动销毁容器

### Context Management

`ContextManager` 负责：
- 动态构建上下文（系统提示 + 工具 + 对话历史 + 聚焦文件 + 记忆）
- Token 统计和限制检查
- 对话历史保存和加载
- 自动保存机制（每次 API 调用后增量保存）

### Thinking Mode

支持"思考模式"（需配置 `AGENT_THINKING_MODEL_ID`）：
- 首次调用使用 reasoning 模型（如 deepseek-reasoner）
- 后续调用使用快速模型
- 可通过 `THINKING_FAST_INTERVAL` 控制切换频率
- 失败时自动回退到思考模式

### Web Socket Events

主要事件：
- `send_message` - 发送用户消息
- `thinking_start/chunk/end` - 思考过程
- `text_start/chunk/end` - 文本响应
- `tool_preparing/start/update_action` - 工具执行状态
- `conversation_list_update` - 对话列表更新
- `terminal_output` - 终端输出

## Common Patterns

### Adding New Tools

1. 在 `core/main_terminal_parts/tools_execution.py`（及相关 `tools_*.py`）实现执行逻辑
2. 在 `core/tool_config.py` / `core/main_terminal_parts/tools_definition.py` 中注册工具定义
3. 如需在任务流/流式输出中特殊处理，在 `server/chat_flow*.py` 对应环节添加逻辑

### 代码修改约定

- **最小改动原则**：只改与需求直接相关文件，避免顺手重构。
- **文件编辑方式**：优先使用原生文件编辑工具，尽量不要用 `bash`/`python` 脚本批量改文件。
- **后端改动优先级**：先改 `modules/`、`server/` 内对应模块，最后才动入口。
- **前端改动优先级**：按 `static/src` 现有分层改（`app/` `stores/` `components/` `composables/`）。
- **CLI 改动优先级**：优先在 `cli/src/App.tsx`、`cli/src/components.tsx`、`cli/src/eventMapper.ts`、`cli/src/api.ts` 内做最小闭环修改。
- 涉及 monitor 动画/事件联动时，至少同步检查 `MonitorDirector.ts` 与 `stores/monitor.ts`。
- **前端不强制本地构建**：沙箱环境无法成功执行 `npm run build` / `npm run cli:build`，因此改完前端不必每次都跑构建验证。改动后用类型检查（`npm run lint` / `npm --prefix cli run typecheck`）或人工 review 自查即可，构建交由用户在本机或 CI 完成。

### Working with Containers

使用 `ContainerHandle`:
```python
# 文件操作
result = container_handle.execute_file_op("read", path="/workspace/file.txt")

# 执行命令
result = container_handle.run_command("ls -la /workspace")

# 终端会话
result = container_handle.start_terminal(session_name="main", working_dir="/workspace")
```

### Managing Conversations

```python
# 创建新对话
terminal.create_new_conversation(thinking_mode=True)

# 加载对话
terminal.load_conversation(conversation_id)

# 搜索对话
terminal.search_conversations(query="bug fix")

# 删除对话
terminal.delete_conversation(conversation_id)
```

## 前端设计风格统一规范（强制）

> 适用范围：所有前端 UI（以 `static/src` Web 为主；`cli/src` 在视觉可类比处同样适用；以及未来新增的任何界面）。
> 约束级别：写新 UI 或改动 UI 时**必须遵守**；遇到存量违规应在最小改动允许范围内顺手修正。

1. **禁止边缘光晕**：不使用任何 glow / 外发光 / 彩色光晕效果（大范围彩色 `box-shadow` 扩散、用 `filter: drop-shadow` 做光圈、`::before/::after` 模糊光晕等）。已有的要移除。允许的只是中性、克制的投影——沿用 `--claude-shadow` / `--theme-shadow-*` 这类已有 token，不要自造发光阴影。**仅在用户明确允许或要求时才可使用光晕效果。**

2. **禁止原生浏览器组件**：不直接使用浏览器默认外观的 `<select>`、`<input type=checkbox/radio/range/date/color>`、`alert/confirm/prompt`、原生右键菜单、原生 tooltip 等。一律替换为与项目风格统一的自定义组件（下拉、开关、单选、滑块、模态、Toast 等）。

3. **禁止圆角套娃**：不允许「圆角矩形里再套圆角矩形再套圆角矩形」的多层嵌套卡片——这是典型的垃圾审美，且会极大占据有效显示面积。容器层级要扁平：能用分隔线 / 留白 / 底色区分的，就不要再多包一层带边框圆角的盒子。

4. **图标外框对齐**：同一组图标按钮的外框（点击热区 / 容器）必须对齐统一，不能一个居中、一个左对齐、一个右对齐。同组按钮固定相同尺寸与对齐方式。

5. **图标视觉对齐而非理论对齐**：按图标的视觉重心对齐，而不是几何边界盒。对视觉重心偏移的图标（三角形 / 播放键 / 放大镜等）做微调（micro-nudge），让它「看起来居中」而非「数值上居中」。

6. **颜色遵循三模式切换 + 两层 Token**：所有颜色必须走原生三模式（经典 `classic` / 明亮 `light` / 夜间 `dark`），禁止写死颜色字面量（含裸 hex、`rgb()`/`hsl()` 字面色、`var(--x, #hex)` 兜底），一律使用语义 CSS 变量。
   - **三主题定位**（填色基准）：**经典 = 抄 Claude 官网亮色盘**（暖奶油色阶 + 暖橙 primary `#cc785c`）；**浅色 = 抄 ChatGPT 亮色盘**（冷白 + 中性灰 + 近黑 primary `#181818`）；**深色 = 自研中性灰阶**（浅灰/深灰/黑，不硬凑暖调）。
   - **两层结构**：token 定义在 `static/src/styles/base/_tokens.scss`，分原始层 + 语义层；组件只引用**中性语义名**（`--surface-*` / `--text-*` / `--border-*` / `--accent*` / `--state-*` 等）。`--claude-*` / `--theme-*` 是**过时兼容别名**，迁移完成后会删，新代码不要用。
   - **表面层次**（经典）：画布 `--surface-base` `#faf9f5` < 侧栏 `--surface-soft` `#f5f0e8` < 卡片 `--surface-card` `#efe9de` < 嵌套 `--surface-muted` `#e8e0d2` < 纯白浮起 `--surface-raised`。亮色主题不许把所有表面塌成同一个白，必须靠暖/冷灰阶拉开层次。
   - **强调色克制**：primary（`--accent`）是 "CTA-only voltage"，只点在主按钮/logo 等极少数处；hover / 选中 / 运行态一律走中性灰（跟各自主题表面色），不抢镜。
   - **派生色**：需要半透明 tint 时用 `color-mix(in srgb, var(--token) N%, transparent)` 从语义 token 派生，不写死 rgba。
   - **新增颜色**必须在 classic / light / dark 三套主题（及首屏回退 `:root:not([data-theme])`，与经典同值）都补齐。
   - **防回退栏杆**：`.stylelintrc.cjs` 用 `color-no-hex` / `declaration-property-value-disallowed-list` / `media-feature-name-disallowed-list` 三条规则拦截违规，`build` 脚本含 `stylelint` 步骤会拦下裸色。存量未清理文件在 `BASELINE_EXEMPT` 临时豁免，清理一个移除一个，不再回退。切换逻辑见 `static/src/utils/theme.ts`。

7. **带文字容器固定高度**：所有含内部文字的选项 / 按钮 / 标签 / 容器必须固定高度，禁止因文字多少被撑大撑高。文字过长用省略号或内部滚动处理，保持行高与块高稳定。

8. **窗口设最大尺寸 + 内部滚动**：所有弹窗 / 面板 / 列表必须设置 `max-height` / `max-width`，超出时由内部容器滚动，而不是把整个窗口顶大。滚动条要么隐藏，要么做样式适配（贴合整体设计，不暴露原生粗滚动条）。

9. **实体面板禁止半透明**：所有实体 UI 容器（对话区、侧栏、下拉/二级菜单、抽屉、对话框本体、状态条、tooltip 气泡、输入栏等）背景必须**不透明**，且不加 `backdrop-filter` 磨砂。背景一旦不透明，磨砂就失去意义，必须移除。**唯一例外**是遮罩层（弹窗背后压暗的 scrim，用 `--overlay-scrim`，`position:fixed;inset:0`）和刻意的玻璃质感装饰，这类保留半透明。

## Security Considerations

- 所有用户操作在独立容器中执行，与宿主机隔离
- 文件操作路径验证在 `FileManager._validate_path`
- 上传文件经过 `UploadQuarantineManager` 隔离和扫描
- CSRF 保护在 Web 端启用
- 登录失败次数限制和临时锁定

## Known Limitations

- 代码大量由 AI 生成，未达到生产级别
- 容器资源配额依赖 Docker cgroups
- 前端处于改造中，部分功能可能不稳定
- Token 统计基于 tiktoken，可能与实际 API 有偏差

## Directory Structure

```
agents/
├── server/            # Flask 业务主线（chat/task/goal/monitor/auth ...）
├── core/              # 核心终端与工具编排（main_terminal_parts/*）
├── modules/           # 独立功能模块
├── utils/             # 辅助工具（含 log_rotation 日志轮转）
├── config/            # 配置拆分（api/limits/terminal/paths ...，由 __init__ 聚合）
├── static/            # Vue 3 + TS Web 前端
├── cli/               # React + Ink CLI 前端（重写中）
├── modules/sub_agent/ # 子智能体执行逻辑（主进程内协程）
├── easyagent/         # 旧版 Node.js 子智能体实现，暂时保留但已不再使用
├── docker/            # 容器镜像
├── prompts/           # 系统提示词
├── scripts/           # 运维脚本（数据迁移 migrate_runtime_data.py 等）
├── android-webview-app/ # Android WebView 客户端工程
├── test/              # 测试用例
├── docs/ / doc/       # 设计与发布文档
└── _experiments/      # 本地实验残留与历史文档归档（gitignored，不进仓库）

运行态数据（不在源码树）：
~/.astrion/astrion/      # 数据根目录（可通过 ASTRION_DATA_ROOT 覆盖）
├── settings.json      # 唯一配置文件
├── config/            # 部署级配置（host/web 共享）
├── host/              # mode = host，由 TERMINAL_SANDBOX_MODE 决定
│   ├── data/          # 对话、用户库、记忆、sub_agent_tasks（运行态）
│   └── logs/          # 日志文件
└── web/               # mode = web/docker
    ├── data/          # 对话、用户库、记忆、sub_agent_tasks（运行态）
    ├── users/         # web 多用户工作区
    ├── api/users/     # API 用户工作区
    └── logs/          # 日志文件
```

> 历史说明：`data/`、`users/`、`logs/`、`project/` 等过去曾在源码树内，现已默认迁至 `~/.astrion/astrion/<mode>/`。详见 Configuration 节「数据目录与路径变量」。

## Development Tips

- 修改系统提示词：编辑 `prompts/main_system.txt`
- 调整工具限制：修改 `config/limits.py`
- 容器镜像定制：编辑 `docker/terminal.Dockerfile` 并重新构建
- 前端开发：在项目根目录运行 `npm install && npm run dev`（build watch）
- 查看详细执行流程：监控 `logs/debug_stream.log`

## Permission Mode & Sandbox Execution (2026-05)

完整说明文档：`docs/host_sandbox_and_permission_model.md`

系统有两套独立但叠加的控制：

### 权限模式 (Permission Mode)
- `readonly` - `run_command` 在只读沙箱执行；`write_file`/`edit_file` 等写入类工具直接拒绝
- `approval` - `run_command` 先走只读沙箱，权限拒绝（如 `Operation not permitted`/`Permission denied`）时触发前端审批，通过后仅该次命令以可写沙箱重试
- `auto_approval` - 工作区内写入直接执行，工作区外写入进入审批；`run_command` 权限拒绝由后台审批智能体自动审核
- `unrestricted` - 不做权限模式拦截，是否沙箱由执行环境决定

### 执行环境 (Execution Mode)
- `sandbox`（默认）- OS 沙箱执行（macOS: `sandbox-exec`，Linux: `bwrap + seccomp`，Windows: `WSL2`），支持会话级 TTL 自动回退 `direct -> sandbox`
- `direct` - 宿主机直接执行（高风险，仅建议短时使用）

### 路径授权语义
- 前端路径授权分「可读可写」与「仅可读」：可读集合 = 可读可写 + 仅可读，可写集合 = 可读可写

### 自动审批智能体
- 配置文件：`config/auto_approval.json`（`name`/`url`/`key`/`model`/`extra_params`，及 `timeout_seconds`/`max_rounds`/`max_command_timeout`）
- 调试开关：`modules/approval_agent.py` 中 `DEBUG_SAVE_APPROVAL_AGENT_TRANSCRIPT`，开启后写入 `logs/approval_agent/`

## Android Release Notes (Required for frontend update)

当改动前端并准备发 Android WebView 壳版本时，必须同步完成：

1. 更新版本号（`android-webview-app/app/build.gradle.kts`）
   - `versionCode` 递增
   - `versionName` 更新
2. 更新版本说明（`android-webview-app/APP_CHANGELOG.md`）
   - 新版本条目写在顶部
3. 修改完成后提醒用户运行上传脚本：
   - `bash /Users/jojo/Desktop/agents/正在修复中/agents/upload_android_apk.sh`

参考文档：`doc/android_app_release_and_update.md`
