prompt(skill 机制): 永远 load → 可选辅助,通用任务不必硬套

skill 字段在新建任务时已可留空(本轮 /v1/skills 下拉落地),原"永远 load 一下"
对简单问答 / 改 bug / 文件操作等通用任务过激;改为"Skill 是可选辅助",明确通用
任务直接用通用工具,匹配到 skill 领域再 load。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
caoqianming 2026-05-18 16:27:30 +08:00
parent b057c3bd06
commit 952a377017
2 changed files with 7 additions and 4 deletions

View File

@ -2,7 +2,7 @@
> 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。
最后更新:2026-05-18(`GET /v1/skills` 路由 + dev SPA 新建任务弹窗 skill 字段改下拉选择,数据源自 SkillRegistry)
最后更新:2026-05-18(system prompt skill 机制改"可选辅助",通用任务不必硬套 skill)
---
@ -21,6 +21,7 @@
## 已完成关键能力
- **05-18 / system prompt skill 机制改"可选辅助"**:接 `GET /v1/skills` + 下拉选择落地后,task 创建时 skill 字段允许留空成为常态。原 `prompts/system/general_v1.md` 第 14 行 `"永远 load 一下。skill 数有限,加载成本很低"` 在新形态下变得过激 —— 简单问答 / 通用编码 / 文件操作不该被强行匹配到 coding 等 skill。改为"Skill 是**可选辅助**"+ 明确列出"简单问答、读代码、改 bug、文件操作这类通用任务,直接用通用工具就够,不必为每个任务硬套 skill"。一旦决定要用仍要求 load 完整指引(原则不变)。**未动**:skill discovery block 内容(name + description 注入仍按 registry 顺序)、`load_skill` 工具协议、SKILL.md 内容。**tradeoff**:边缘场景(用户提"整理大纲"可能落 proposal 也可能不用)agent 现在会偏向不 load,可能漏掉好的模板;但比原来"什么都套 coding"的噪音更可接受。
- **05-18 / `GET /v1/skills` + dev SPA skill 字段改下拉**:原 `nt-skill` 是自由输入(用户得记住 `coding / ppt / proposal` 拼写),用户反馈"加 skill 接口给前端选"。后端 `web/app.py` lifespan 启动时 `SkillRegistry(ROOT / cfg["skills_dir"])` 扫一次挂到 `app.state.skill_registry`(文件系统静态,运行中不变);新增 `GET /v1/skills``require_user` JWT 鉴权,返 `{skills:[{name,description}]}` 按 name 升序(registry 已 sorted)。dev SPA(`web/static/dev.html`):`<input id=nt-skill>` 换 `<select>`,首项固定 `(默认 · 不限定)` 空值;`hd-new` 打开 modal 时 `loadSkillOptions()``loadFolderSuggestions()` 并发(`Promise.all`),首次拉到的列表缓存到 `state.skills`,失败时静默退化为只剩"默认"项不阻塞。option 文案 `name — description`,`title` 也带 description 鼠标悬停看长文。Smoke:`TestClient` 起 app → `/v1/auth/login` 拿 token → `/v1/skills` 返 3 项(coding/ppt/proposal)+ 描述;无 token 401。**未动**:`_build_system_prompt` 注入的 skill discovery block(name + description)和这里渲染的下拉项是同源 registry,改一处不影响另一处;`POST /v1/tasks` body 不校验 `skill ∈ registry`(留空 / 任意串都允许,与 schema 一致 — 真要拦在 UI 层早就拦了)。
- **05-18 / dev SPA 全套 UI 中文化**:用户反馈"web 页面菜单按钮啥的改为中文"。`web/static/dev.html` 静态部分(login overlay / header / 三栏 pane-head label / chat 操作按钮 / new task modal)+ JS 动态部分(状态文案 / role 标签 / confirm/alert 文案 / 状态 badge / SSE 流式提示)全面本地化。**静态文案**:`zcbot dev login → zcbot 登录` / `+ new task → + 新建任务` / `logout → 退出登录` / `tasks/chat/files → 任务/对话/文件` / 状态 select `(all)/active/completed/abandoned → (全部)/进行中/已完成/已废弃` / `export .docx/done/abandon/delete → 导出 docx/完成/废弃/删除` / `stop/send → 停止/发送` / `ready/sending/streaming/cancelling → 就绪/发送中/接收中/停止中` / `(no task selected) → (未选中任务)` / `select a task on the left → 请在左侧选一个任务` / `loading… → 加载中…` / `load failed → 加载失败` / `(no tasks) → (暂无任务)` / `(no messages yet) → (暂无消息 · 在下方输入开始对话)` / `(unnamed) → (未命名)` / `(user root) → (根目录)`。**动态文案**:`renderTaskList` / `renderChatMeta``statusLabels` map(`active→进行中`等),task list 计数 `msg → 条`;消息卡 role 标签 `user/assistant/error → 我/助手/错误`,`tool · name → 工具调用 · name`,`result (N chars) → 结果(N 字符)`,SSE 流式 `tool_call:/tool_result → 工具调用:/工具结果`;`cancelled` badge `已停止(stopped by user) → 已停止`(更简洁)。**弹窗 / 错文案**:`确认置为 status? → 确认置为「中文 label」?` / `delete failed → 删除失败:` / `download failed → 下载失败:` / `upload failed → 上传失败:` / `export failed → 导出失败:` / 删 task confirm 文案改"任务「项目名」(N 条消息)" / `任务名 必填 → 任务名为必填项`。**modal**:`新建 task → 新建任务` / 各 label "必填"/"可选" 加括号统一 / `留空 fallback 用任务名 → 留空则用任务名` / `N 个 task → N 个任务`。**Smoke**(in-process TestClient 拉 `/static/dev.html`):assert 13 个中文标签全在 + 8 个原英文按钮文案全无残留。**没动**:技术字段(`user_id` / `platform_key` / `UUID` / `tok` token 简称)、CSS class(`badge active` 等仍是英文 class,但显示文本走 statusLabels)、SSE event 名(`text/tool_call/tool_result/done/error/cancelled`)、API 字段名 — 都是 schema 层,不影响 UI 中文。
- **05-18 / 入口归位:`cli.py` 改名 `main.py`、原 `main.py` 挪 `core/agent_builder.py`,删 CLI REPL `chat/tasks/export`,§7 E 双模式路线撤**:接 0004 schema 大瘦身后又一轮架构清理。用户复盘"§7 E `--remote` 是不是可以移除""有 dev SPA 后 CLI REPL 还需要吗""统一到 main.py 是否合理"——一连串问题指向同一个底层:`cli.py`(CLI 入口)+ `main.py`(装配 lib)+ `chat / tasks / export` REPL 子命令是历史多形态共存遗留,在"UI 由 platform 实现 + dev SPA 是开发主路径"的新形态下都是冗余。**架构判断**:`main.py` 此前混三角色(装配 lib + 路径/验证 utility + 被 cli+web 共同 import 的事实入口),按 §5 Less Scaffolding + SoC 应该拆;直接答案是 `cli.py` 改名 `main.py`(入口),原 `main.py``core/agent_builder.py`(装配 lib),单一职责对齐 Python 社区惯例(入口叫 main.py,lib 在子模块)。**改动**:① `git mv main.py core/agent_builder.py`;② `git mv cli.py main.py`(覆盖);③ 5 处 `web/app.py::from main import xxx``from core.agent_builder import xxx`(`build_agent / sync_task_tokens / working_dir_from_name / resolve_workspace / user_root / InvalidTaskName / validate_task_name`);④ 新 `main.py` 自指 `from main import``from core.agent_builder import`;⑤ 删 `chat / tasks / export` 三个 click 命令 + REPL 内部 helpers(`_cleanup_if_empty / _delete_task_db_row / _task_has_messages / _list_task_rows` 共 ~110 行)+ REPL 主循环(`/exit /reset /new /resume /id /status /done /abandon /desc /export` 共 ~200 行)+ `--name --working-dir --skill --desc --resume --model` CLI 选项 + `tasks` 列表渲染 + `export` 命令 — 共 ~400 行;新 `main.py` ~180 行(`db {upgrade,downgrade,current}` + `probe` + `web` 三命令组);⑥ `core/agent_builder.py` 顺手清:删 `_resolve_uuid_or_prefix` 函数(web 端只传完整 UUID,前缀匹配无 caller)+ `resolve_task_id``task_id_arg in (None, "", "last")` 分支(web 不传 "last"),resume 直接 `UUID(task_id_arg)`;模块 docstring "本地 CLI user_id = SENTINEL" → "所有入口走 web `/v1` + JWT;dev SPA 默认填 SENTINEL 走同一条路径"。**Smoke 6 case 全绿**(in-process TestClient + 子进程跑 `python main.py db current`):① `/healthz` 200 ② POST /v1/tasks → GET → POST messages(返 `events_url` 无 run_id)→ cancel → DELETE 全链路 ③ `/v1/folders``core.agent_builder.user_root` 路径 ④ `/v1/files``_load_user_root``resolve_task_id` 完整 UUID resume(去前缀匹配后用 `UUID(...)` 直接解析;非 UUID 字符串 ValueError;ghost UUID `empty working_dir` ValueError)⑥ `subprocess.run([sys.executable, "main.py", "db", "current"])` 子进程跑通 + stdout 含 `0004 (head)`(验证 click 入口、alembic config 路径、ROOT 解析都没坏)。**文档同步**:DESIGN §1 形态兼容(删 `--remote`,讲"无 CLI / in-process 分叉")/ §2 目录树(`{main.py, cli.py}` → `core/agent_builder.py + main.py`)/ §3.3 `cli.py probe``main.py probe` / §3.6 "REPL 内 task 切换"段改"Task 切换 / 软删 走 dev SPA + /v1" + "入口"段讲 `python main.py web` / §7.0 共享差别表入口列改 `python main.py web` + auth 行讲"dev SPA 填 sentinel + 本地 key" / §7.6 #8 标"已撤" / §7.7 E 阶段标"撤" / §7.8 风险表"CLI 双模式分叉"行融合进"过早抽象" / §7.9 新增"CLI REPL 撤,入口统一 main.py"取舍说明 + 删原"CLI 双模式共存"段;RUN 顶 / 一次性初始化 / 日常命令 / 故障兜底 / 关键路径全部 `cli.py``main.py`,且日常命令段重写"只剩 `web / db / probe` + 所有 task 交互走 main.py web 后浏览器或 /v1`";PROGRESS 文件清单 / 状态表 / 下一步候选同步(去掉 E 路线)。**净效果**:总代码 -360 行(`cli.py` 558 行删 → `main.py` 180 行 + `core/agent_builder.py` ~320 行 = ~500;原 `main.py` 337 + `cli.py` 558 = 895;净减 -395);入口文件数 2 → 1;维护面 -1 套 task 切换语义(REPL `/new /resume /done /abandon` 全归到 `/v1/tasks*`);测试面 -1 套(原 cli build_agent 调用链 smoke 全归到 web TestClient)。

View File

@ -8,10 +8,12 @@
- `load_skill` —— 加载某个 skill 的完整指引
## Skill 机制
你启动时只看到下方 skill 的"名字 + 描述"。当用户的任务匹配某个 skill 的领域,
**先 `load_skill(name)`** 拿到完整指引(工作流、模板、原则),再开始干活。
你启动时只看到下方 skill 的"名字 + 描述"。Skill 是**可选辅助** —— 任务明确落在
某个 skill 领域(用户要做 PPT、写申报书等)时,先 `load_skill(name)` 拿完整指引
(工作流、模板、原则)再干。
不要凭印象推测一个 skill 怎么用 —— 永远 load 一下。skill 数有限,加载成本很低。
简单问答、读代码、改 bug、文件操作这类通用任务,直接用通用工具就够,不必为每个
任务硬套 skill。一旦决定要用,**不要凭印象推测**怎么用 —— load 一下。
## 工作原则
- 动手前先看: 用 read/grep/glob 摸清现状,再 edit