# claude-agent-py-web **Repository Path**: HSKS/claude-agent-py-web ## Basic Information - **Project Name**: claude-agent-py-web - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-08 - **Last Updated**: 2026-10-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # claude-agent-py-web 基于 [claude-agent-sdk](https://pypi.org/project/claude-agent-sdk/) 的编码智能体 Web 应用**基础模板**。FastAPI 后端 + React 前端,PyInstaller 打进**单个可执行文件**(内嵌前端产物、CLI 二进制、`.env`)。后续智能体项目在此模板上二次开发,不动骨架即可长出业务。 ## 技术栈 | 层 | 技术 | |---|---| | 后端 | Python 3.11+ / FastAPI / uvicorn / pydantic-settings,[uv](https://docs.astral.sh/uv/) 管依赖 | | 前端 | Vite / React 19 / TypeScript / Tailwind CSS 4 / zustand / zod / @base-ui/react,[bun](https://bun.sh/) 管依赖 | | 契约 | `frontend/src/contracts/`(FE 线协议)与 `src/backend/contracts/`(BE 校验)**同源对译**,parity 测试守护 | | 打包 | PyInstaller onefile(vite build 产物 + CLI + `.env` 以 datas 内嵌,运行时经 `sys._MEIPASS` 服务) | | 桌面壳 | Tauri(`desktop/`,sidecar 模式拉起 exe) | ## 目录结构 ``` ├── main.py # PyInstaller 打包入口(dev 直接 uv run python -m backend) ├── bootstrap_env.py # 冻结态先播种 exe 同级 .env(须早于 backend.* 任何 import) ├── build.py # 打包器:vite build → pyinstaller → aiagent-{platform}-{arch}-{ver} ├── pyproject.toml # 后端依赖 + ruff/pytest 配置(uv) ├── version.txt # 版本号(打包时内嵌) ├── .env / .env.example # 前后端共用单源配置(vite 与后端读同一份) ├── src/backend/ # FastAPI 应用 │ ├── __main__.py # 服务主入口:argv → 单实例锁 → Job Object → 孤儿清扫 → uvicorn → 优雅停机 │ ├── app.py # 组装:中间件栈 → 路由 → 错误处理(BASE_URL 子路径包装) │ ├── env.py # 环境变量唯一来源(启动即校验,失败退出) │ ├── routes/__init__.py # 路由总表——看一眼即知全部对外入口 │ ├── contracts/ # DTO / SSE 事件 / 加密 / SDK 协议(与前端同源对译) │ ├── core/ # 中间件(requestContext/auth/decryptBody/accessLog/errorHandler)、日志、响应、错误码、前端服务 │ ├── modules/agent/ # 会话注册表、SSE 事件翻译、审批流、查询选项、进程树治理 │ ├── modules/auth/ # JWT 登录、用户档案(scrypt 哈希) │ └── modules/system/ # 单实例锁、自更新、deep-link 拉起、launch 服务 ├── frontend/ # Web UI │ └── src/contracts/ # 前后端线协议契约(与 backend/contracts 对译) ├── desktop/ # Tauri 桌面壳(sidecar 拉起 exe) ├── tests/ # pytest(含 contract parity 守护) └── claude-agent-sdk-guide-new/ # SDK 官方文档中文版(参考) ``` ## 快速开始(dev) 前置:[uv](https://docs.astral.sh/uv/)、[bun](https://bun.sh/)。 ```powershell # 1. 配置:复制模板并填网关信息(ANTHROPIC_BASE_URL / AUTH_TOKEN / MODEL 已迁至前端模型配置弹框) copy .env.example .env # 2. 安装依赖 uv sync bun install --cwd frontend # 3. 启动后端(读 .env,默认端口见 .env 的 PORT;vite dev 代理 /api 到它) uv run python -m backend # 或 uv run python main.py # 4. 启动前端 dev server(另开终端,http://localhost:3001{BASE_URL}) bun run --cwd frontend dev ``` > dev 模式后端不内嵌前端(`has_frontend=False`),页面由 vite dev server 提供;生产形态由 exe 同源服务前端。 > `.env.example` 默认 `PORT=10068`、`BASE_URL=/csmcode`,故 dev 前端访问 `http://localhost:3001/csmcode`。 ## 打包(单 exe) ```powershell uv run python build.py # vite build + pyinstaller onefile(后端 exe) uv run python build.py --skip-ui # 前端已构建时跳过 vite uv run python build.py --no-cli # 不内嵌 CLI(部署机自备并设 AGENT_CLI_PATH) uv run python build.py desktop # 后端 exe 打完后套 Tauri 桌面壳(见下) ``` **后端单 exe**:`dist/aiagent-{platform}-{arch}-{version}[.exe]`,复制一份到 `bin/`。内嵌: - 前端 `dist/`(运行时挂 `BASE_URL`,SPA 回退 index.html) - CLI 二进制(SDK `_bundled`,frozen 下经 cli-cache 解包使用) - `version.txt` + 仓库根 `.env` **Tauri 桌面客户端**(`build.py desktop` 子命令):复制后端 exe 成 `desktop/src-tauri/aiagent-{.exe}`(三元组对齐 `tauri.conf.json` 的 `externalBin: ["aiagent"]`,flat 无 `binaries/` 子目录)→ `desktop/` 跑 `bun install` → `bun run build`(`tauri build`,release,慢)。产物:`desktop/src-tauri/target/release/bundle/`(Windows = NSIS 安装器;`productName: 超级智能体`,`identifier: com.aiagent.desktop`)。 桌面 dev(需先有后端 exe 产物): ```powershell uv run python build.py --skip-ui # 先产 bin/aiagent-* exe(若无) bun run --cwd desktop prepare:sidecar # 复制 exe 成三元组命名(dev 前) bun run --cwd desktop dev # tauri dev(热重载前端 + 拉 sidecar) bun run --cwd desktop icon # 重新生成图标 ``` **跨平台:** PyInstaller 无法交叉编译,Windows / Linux / macOS 需在各自系统执行同一条 `uv run python build.py`。构建脚本已处理平台差异(路径分隔符、venv 结构、产物命名)。 exe 常用参数:`--help` / `--version` / `--update` / `open [--user ]`;deep-link:`csmcode://...`。 ## 配置(.env 单源) 前后端读同一份 `.env`(后端按 CWD / exe 同级解析;vite 读仓库根)。关键项: | 变量 | 说明 | |---|---| | `PORT` | 后端端口(dev vite 代理目标;`.env.example` 默认 10068) | | `BASE_URL` | 子路径部署前缀(如 `/csmcode`),留空为根路径 | | `BODY_ENC_KEY` | 请求体 AES-256-GCM 对称密钥(base64 32 字节;留空关闭加密;进前端 bundle,属混淆级防护) | | `JWT_SECRET` | 生产必配(缺省降级 dev 常量,token 可伪造) | | `AUTH_ADMIN_USERS` | 管理员白名单(逗号分隔用户名) | | `AGENT_CONFIG_ROOT` / `GLOBAL_CONFIG_ROOT` | 每用户 / 全局配置根(会话 JSONL、skills、plugins 按用户隔离) | | `PUBLIC_WORKSPACE_ROOT` / `WORKSPACE_ROOT_NAME` | 公共工作空间根与其下目录名 | | `AGENT_SESSION_IDLE_MINUTES` / `AGENT_SESSION_MAX_LIFE_HOURS` | 空闲回收 / 绝对寿命兜底 | | `AGENT_MAX_SESSIONS_PER_USER` / `AGENT_MAX_TOTAL_SESSIONS` | 活跃会话配额 | | `AGENT_CLI_PATH` | 外置 CLI 路径(`--no-cli` 打包时部署机必配) | | `DEEP_LINK_SCHEME` | deep-link 协议名(默认 `csmcode`) | | `UPDATE_MANIFEST_URL` | 自更新清单地址(不配则自更新不可用) | > LLM 网关(`ANTHROPIC_BASE_URL / AUTH_TOKEN / MODEL / effort / thinking / fallback`)已迁至前端「模型配置」弹框,per-user sidecar 落 `{AGENT_CONFIG_ROOT}/{username}/model-config.json`;`_child_env` 启动子进程时剥离继承的 `ANTHROPIC_*` 并以 sidecar 单源重写。`.env` 的 `ANTHROPIC_*` 不作兜底,会被剥离。 完整项见 `.env.example`。 ## 架构要点 ### 后端分层 ``` routes/ 路由总表(挂载模块 router + 健康探针 + 前端静态) modules// ├ _route.py route 层:handler 只做「入参 → service → ok/created」 └ _service.py service 层:业务逻辑,禁止 import fastapi,可独立单测 core/ 中间件 / 响应 / 错误码 / 日志 / 前端服务 contracts/ DTO / SSE 事件 / 加密 / SDK 协议 utils/ 分页等通用件 ``` - **统一响应信封**:成功 `{data}`(分页时 `data = {list, total, page, pageSize}`);失败 `{error: {code, message, traceId, details?}}`。成功 `return ok(data)` / `created(data)`,失败 `raise AppError(code)`。 - **错误码注册表**:`core/error_codes.py` 单一登记处,业务层只关心 code,HTTP 状态/默认消息由注册表决定。**只允许追加,禁止修改/删除既有条目**。 - **环境变量**:`from backend.env import env` 是唯一合法口径,禁止直接读 `os.environ`。启动即校验,失败直接退出。 - **中间件栈**:`app.py` 反序注册(Starlette 后注册者在外层)。`RequestContextMiddleware` 最先注册(最外层),绑定 `traceId`/`clientIP` 到 contextvar,业务层 `log()` 自动携带。 ### 会话运行时(agent 模块核心) - **SessionContext 单例内存注册表**:主键 `normalized_dir`——每 workspace_dir 全局唯一活跃 claude 进程。`session_registry.py` 是运行时核心。 - **SSE 事件流**:`GET /api/agent/session/events`,每事件带自增 `seq`(`id:` 字段),环形缓冲(500)常驻缓存;EventSource 断线携 `Last-Event-ID` 增量重放;心跳 15s 保活。 - **流式翻译**:`agent_event_translator.py` 把 SDK dataclass 消息翻译成 SSE 事件——partial 流(text/thinking/tool_call_* 增量)+ 完整消息(tool_result 回填、checkpoint、subagent 进度)。 - **审批流**:`can_use_tool` 回调 → 广播 `approval_request` → 前端作答 → `ApprovalDecision`。`updatedInput` 白名单收敛为两类:Bash/PowerShell 仅 `command`,AskUserQuestion 仅 `answers/annotations`。 - **执行模式四档**:`auto`(bypass)/ `standard` / `safe`(敏感工具审批)/ `plan`(只读)。热切换不重启进程,`set_permission_mode` 即时生效。 - **多人安全**:username 一律来自 JWT;历史读写经 per-user `CLAUDE_CONFIG_DIR` 物理隔离;活跃会话操作经 `require_session_ctx` 属主校验,非属主统一 404(不泄露他人会话存在性)。 ### 进程治理(Windows 优先 + POSIX 兜底) - **Windows Job Object**:最先挂,此后 spawn 的 `claude.exe` 后代归入 Job,进程无论怎么死(含 OOM 硬杀)OS 关 Job 句柄即杀光后代,防 orphan。 - **退出扫杀**:`sweep_orphans_on_quit` 扫仍存活的 `claude(.exe)` 直系子树(SDK 2s 宽限未及退出的强杀场景)。 - **启动清扫**:`startup_orphan_sweep` 终止上次崩溃遗留的 SDK 孤儿子进程。 - **优雅停机**:SIGINT/SIGTERM 先关全部 agent 会话(SDK disconnect,2s 优雅窗口)→ 退出扫杀 → 停服。 ### 单实例锁 二次启动解析 argv 帧意图(deep-link / open / 后台自启),冷热转发帧给主实例后退出,不绑 PORT。 ## 前端架构 - React 19 + TS + Tailwind CSS 4 + Vite + zustand(状态)+ zod(校验)。 - **UI 组件体系**:shadcn/ui 模式(`frontend/components.json`),基座是 **Base UI**(`@base-ui/react`,非 Radix);`cva` 管 variant、`cn`(`clsx` + `tailwind-merge`)合并 class;图标 `lucide-react`;`baseColor: neutral`、`cssVariables: true`。新增 UI 组件按 `src/components/ui/` 既有模式:Base UI 原语 + `cva` variant + `cn` 包装。 - **编辑器/渲染**:CodeMirror(`@uiw/react-codemirror` + 各语言包,文件编辑/代码高亮);`react-markdown` + `remark-gfm`(消息 markdown 渲染);`sonner`(toast)。 - `src/contracts/` 与后端 `contracts/` 同源对译:`dto/`(请求/响应)、`sse-events.ts`、`sdk-protocol.ts`、`messages.ts`、`aes-util.ts`。 - `src/hooks/useChatAgent.ts` + `useChatAgentApi.ts`:会话生命周期与 SSE 接入。 - `src/stores/`:zustand store(`auth` / `chat` / `compact-request`)。 - `src/components/chat/`:聊天域组件(消息列表、审批壳、文件树、工具结果渲染);`src/components/ui/`:基础 UI 组件。 - `src/App.tsx`:路由表唯一登记处,受保护页用 `AuthGuard` 包裹。 - Vite `define` 把 `BODY_ENC_KEY` 显式转递为 `import.meta.env.VITE_BODY_ENC_KEY`,`.env` 只留一份;`BASE_URL` 同时驱动 vite `base` 与后端子路径包装,双层同源。 ## 测试与质量检查 **后端:** ```powershell uv run pytest # 全量 uv run pytest tests/test_contract_parity.py # 契约 parity 守护 uv run ruff check src tests # lint(E/F/I/UP/B;B008 忽略) uv run ruff format --check src tests # 格式化检查(本地改 `ruff format` 修) ``` **前端:** ```powershell bun run --cwd frontend build # tsc -b 类型检查 + vite build(类型错误即断) bun run --cwd frontend format # prettier --write bunx --cwd frontend biome check src # biome lint + format(recommended 规则集) ``` - 后端 `asyncio_mode = auto`,service 层不 import fastapi,可独立单测。 - `test_contract_parity.py` 断言后端响应形状、SSE 事件名集合、DTO 字段、错误码注册表完整性——改契约必过此测试。 - 仓库无 CI、无 pre-commit 钩子,质量门禁靠本地自觉:提交前自跑上述命令全绿。 - 完整检查清单与禁忌见 `CLAUDE.md`。 ## 常用命令 ```powershell uv sync # 同步后端依赖 uv add # 加后端依赖 uv run python -m backend # 启后端(dev) uv run pytest # 测试 uv run ruff check src tests # lint uv run ruff format src tests # 格式化 bun install --cwd frontend # 装前端依赖 bun run --cwd frontend dev # 前端 dev server bun run --cwd frontend build # 仅构建前端 uv run python build.py # 全量打包(vite + pyinstaller) ``` ## 二次开发指引 新增业务域的标准步骤(以 `foo` 模块为例): 1. `core/error_codes.py` 追加 `FOO_*` 错误码(**只追加**)。 2. `contracts/dto.py` 加入参/出参 DTO,`frontend/src/contracts/dto/` 同步对译。 3. `modules/foo/` 建 `foo_route.py`(薄封装:`Depends(require_auth)` 取 username,handler 三件事)+ `foo_service.py`(业务,不 import fastapi)。 4. `routes/__init__.py` 挂载:`app.include_router(foo_router, prefix="/api/foo")`。 5. service 层可独立单测;补 `tests/test_foo.py`。 6. `uv run ruff check src tests` 通过。 硬约定与禁忌详见 `CLAUDE.md`。