From 55dc8eb99d4e04be1045e0b1640386e7be22d642 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 14 May 2026 09:15:25 +0800 Subject: [PATCH] =?UTF-8?q?design:=20=C2=A77.1=20=E6=94=B9=20task-primary?= =?UTF-8?q?=20+=20dir=20=E5=89=AF=E8=A7=86=E5=9B=BE=E5=BF=83=E6=99=BA?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原"Folder-centric"标题误导,实际产品形态是 task list 扁平视图为主、 dir tree 为辅,两视图正交查同一份数据(dir 不是 task 的父容器)。 - §7.1 重写心智模型,加双视图对照表 + Mac Finder 类比 - §7.1 明写 task_dir 留空 vs 指定的产品语义(一次性对话 vs 项目化) - §7.1 空 dir(只上传素材未开 task)行为 - §7.2 API 顺序调整,tasks 前置,加分组注释 - §7.0/§7.6 task_dir 行同步统一为"留空派生/指定路径"二分 Co-Authored-By: Claude Opus 4.7 (1M context) --- DESIGN.md | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index d9aca43..68310be 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -188,7 +188,7 @@ SaaS 化不是"重写"也不是"取代 CLI",而是**给同一份 core 加一个 |---|---|---| | 入口 | `cli.py chat` 直调 core | HTTP `/v1/...` + SSE | | Storage | **PG**(`ZCBOT_DB_URL` 指 docker compose / 远端 dev PG) | **PG**(指生产 PG) | -| task_dir 根 | `workspace/tasks//`(派生,私有) | `/users///`(用户给,可共享) | +| task_dir 默认值 | `workspace/tasks//`(留空时派生) | `/users//tasks//`(留空时派生);用户指定时走 `/users///` | | Memory | `workspace/memory/`(FS) | `/users//memory/`(仍是 FS) | | Sandbox | subprocess + env 过滤 | per-task docker exec | | Auth | 无(`user_id='local'`) | OIDC + JWT | @@ -197,26 +197,45 @@ SaaS 化不是"重写"也不是"取代 CLI",而是**给同一份 core 加一个 `workspace/` 仅存 skill 产物,state / messages 全在 PG。本地 vs SaaS 差别只在 task_dir 根路径,不在 storage 形态。 -### 7.1 心智模型:Folder-centric,task-as-DB-record +### 7.1 心智模型:Task 一等公民 + Dir 文件副视图 -参考 Claude Code(cwd 是 anchor)+ OpenAI Assistants(stateful agent service)。 +两个并列入口,正交不嵌套: -- **Folder** = 用户的"硬盘",路径 `users///...`,**和本地文件管理器体感一致**。folder 无 ID,**path 即标识**;改名走 prefix cascade。 -- **Task** = DB 一行,带 `task_dir` 指向 folder(相对 user root)。同 folder 允许多 task,但 task 之间**不嵌套**(no-subtask)。 -- **Messages** = DB 表,append-only,`jsonb` 存 LiteLLM 原样 payload。 -- **Skill 产物**全落 cwd,不引入 artifacts 表;SKILL.md 指示 agent 清中间件。 -- **Skill 定义**是项目代码,跟部署走,所有用户共享。 +| 视图 | 入口语义 | 适用场景 | API | +|---|---|---|---| +| **Task list**(主) | "我的对话历史" | 任务驱动:"继续昨天那个 bug fix" | `GET /v1/tasks?status=&task_dir=` | +| **Dir tree**(辅) | "我的文件资产" | 项目驱动:"看汇报项目里所有素材 + 关联对话" | `GET /v1/folders` | -state / messages 两形态都在 PG,FS 只承担 skill 产物。多 task 共享同 folder 时由 §7.8 文件级悲观锁兜底。 +类比:macOS Finder + 最近使用 / Apple Notes 文件夹视图 + 全部备忘录。两个视图查同一份数据的不同切面,**dir 不是 task 的父容器**。 + +- **Task** = DB 一行,一等公民,自带 `task_dir text` 字段: + - **留空 → 默认派生路径**(`workspace/tasks//`),等价"一次性对话"(ChatGPT thread 体验) + - **指定 → 项目化 task**,同 task_dir 多 task 自动共享 `source/` / `sections/` / 终稿(无需建"项目"实体) +- **Dir** = FS 路径,**无 DB 实体,path 即标识**;无父子结构,改名走 prefix cascade(§7.4) +- **No-subtask**:同 task_dir 允许(同项目多对话),前缀嵌套拒 +- **Messages** = DB 表,append-only,`jsonb` 存 LiteLLM 原样 payload +- **Skill 产物**全落 task_dir,不引入 artifacts 表;SKILL.md 指示 agent 清中间件 +- **Skill 定义**是项目代码,跟部署走,所有用户共享 + +**空 dir**(用户上传素材但还没开 task)在 dir tree 视图正常展示 —— 上传本身是有效产品行为;UI 上跟"有 task 的 dir"做轻量区分(如 task 数 badge)。 + +state / messages 两形态都在 PG,FS 只承担 skill 产物。多 task 共享同 task_dir 时由 §7.8 文件级悲观锁兜底。 ### 7.2 资源模型(/v1) +Task 是主视图,排在前面;folder 是文件副视图。 + ``` -POST/GET/PATCH/DELETE /v1/folders[/{path}] 列树 / 创建 / 改名 / hard cascade -GET/POST/DELETE /v1/folders/{path}/files[/{name}] 列 / 上传 / 下载 / 删 -CRUD /v1/tasks[/{id}] {task_dir, mode, desc, model} +# Tasks(主) +CRUD /v1/tasks[/{id}] {task_dir?, mode, desc, model};task_dir 留空默认派生 POST/GET /v1/tasks/{id}/messages 发消息 / 历史(?search= 走 jsonb GIN / tsvector) GET/POST /v1/tasks/{id}/runs/{run_id}/{events,cancel} SSE + +# Folders(文件副视图) +POST/GET/PATCH/DELETE /v1/folders[/{path}] 列树 / 创建 / 改名(cascade)/ hard cascade +GET/POST/DELETE /v1/folders/{path}/files[/{name}] 列 / 上传 / 下载 / 删 + +# 元数据 GET /v1/{skills,models,usage} POST /v1/probe (admin) ``` @@ -285,7 +304,7 @@ usage_events(id, user_id, task_id uuid, run_id uuid, kind, value, ts) |---|---|---| | 1 | ~~事件流化 `loop.py`~~(commit `375bb29`) | done | | 2 | **Storage 落 PG**:`Session` / `TaskState` 改 SQLAlchemy 写 PG;alembic;`cli migrate-from-fs`;`docker-compose.yml` 起本地 PG | 3 天 | -| 3 | **task_dir 双形态**:`TaskState.task_dir` 可显式指定;`tools/fs.py::_resolve` 接 task_dir 注入;system prompt 注入两形态共用 | 1 天 | +| 3 | **task_dir 字段语义**:留空走默认派生(本地 `workspace/tasks//` / SaaS `/users//tasks//`)或显式指定(走用户给路径);`tools/fs.py::_resolve` 接 task_dir 注入;system prompt 注入两形态共用 | 1 天 | | 4 | **Folder API**:list / create / rename(cascade + 锁 running) / delete(hard cascade) / upload / download | 2 天 | | 5 | **No-subtask 校验**:`create_task` 入口跑 §7.4 SQL | 0.5 天 | | 6 | **Executor + sandbox**:`run_python`/`shell` → `Executor.run(...)`;本地保留 subprocess executor,SaaS 走 docker;`api_key_env` → `KeyProvider` 运行时注入 | 2-3 天 |