feat: v2.3.0 流式输出 + 日志系统 + 会议室架构全面升级

- 流式输出: SSE 逐 token 接收, \\n\n\ 段落缓冲后 mdprint 彩色渲染
- 日志系统: charmbracelet/log v2 双写(stderr + log.yml), yunshu log 命令
- 会议室架构: dialog(main) + weather/profile/note(sub) 多 Agent 编排
- 泛型工具注册: NewTool[T] 反射推导 JSON Schema, 类型安全
- 安全加固: safeMemoryPath 三段校验(EvalSymlinks+Rel), maxToolCalls=2
- 性能优化: sync.Once 延迟加载, note 一步完成, obs/summary 合并
- Prompt 适配: 流式输出原则(先调工具不说话), 单 Agent 查询跳过 obs+summary
- 文档: AGENTS.md + architecture.md + changelog.md 全部同步至 v2.3.0
This commit is contained in:
titor
2026-05-16 17:21:29 +08:00
parent 0898188086
commit c4a0e3ef53
24 changed files with 2769 additions and 338 deletions

View File

@@ -60,56 +60,114 @@ pkg/
└── termui/ 终端交互(行输入、模式设置)
```
## 当前 tools
## 项目文件
| 工具名 | 作用 | 实现 |
|--------|------|------|
| http-get | HTTP GET 请求 | Go |
| skill | 按需加载知识 | Go |
| geocode | 城市名 → 坐标 | Go调 wttr.in |
| read-file | 读取文件 | Go |
```
main.go CLI 入口onboard/help/version/log 子命令)
types.go 核心类型AgentDef, Schema, ToolDef, Message…
loader.go .md 解析frontmatter + body
catalog.go CatalogAgent 生成 + tools.yml 输出
registry.go AgentRegistryScanAgents, GetMain, GetSub…
llm.go LLM API 封装(豆包/OpenAIsync.Once 延迟加载)
tool.go 工具注册 + safeMemoryPath + ExecuteTool + 7 个工具 handler
toolschema.go 泛型+反射工具注册NewTool[T], structToSchema
runtime.go RunAgent + RunSubAgentmaxToolCalls=2+ cache + session
logger.go charmbracelet/log v2 全局实例(→ stderr
log.go 双写 wrapperwarnLog/errorLog/infoLog+ log.yml + yunshu log 命令
```
## 当前 tools
| 工具名 | 作用 | 实现 |
|--------|------|------|
| http-get | HTTP GET 请求 | Go |
| skill | 按需加载知识 | Go |
| geocode | 城市名 → 坐标 | Go(调 wttr.in |
| read-file | 读取文件 | Go |
| task | 调度子 Agent含缓存管理 | Go阶段一新增 |
| memory.read | 读长期记忆 | Go阶段一新增 |
| memory.write | 写长期记忆 | Go阶段一新增 |
| 工具名 | 作用 | 注册方式 |
|--------|------|---------|
| http-get | HTTP GET 请求 | `NewTool[HTTPGetInput]` |
| skill | 按需加载知识 | `NewTool[SkillInput]` |
| geocode | 城市名 → 坐标(调 wttr.in | `NewTool[GeocodeInput]` |
| read-file | 读取文件 | `NewTool[ReadFileInput]` |
| task | 调度子 Agent含缓存管理 + 多步骤编排) | `NewTool[TaskInput]` |
| memory.read | 读取 config/session/notes 等记忆文件 | `NewTool[MemoryReadInput]` |
| memory.write | 写入记忆文件(.md 按 ## 标题合并,.yml 按 key 合并) | `NewTool[MemoryWriteInput]` |
## 后续演进
所有工具都通过 `NewTool[T]` 泛型函数注册,输入结构体自动反射生成 JSON Schemahandler 内参数为类型安全的结构体字段。
## 核心流程
### 当前(单 Agent
```
yunshu (三层分离+单agent)
└─ weather-agent.md (type: main既是入口也是天气专家)
用户输入
RunAgent → CallLLMStream (SSE 流式,\n\n 段落缓冲 → mdprint 渲染)
├─ 流内容到达 → tryFlushBlocks 检测 \n\n
│ ├─ 完整 block → mdprint.Print 渲染到 stdout
│ └─ 残段 → 留在 blockBuf 继续缓冲
├─ 流结束 → mdprint.Print(blockBuf) 刷残段
├─ 返回 tool_calls累积重建→ 继续循环
│ ├─ task(weather/train/hotel/…) → RunSubAgent → TEXT → 回对话
│ │ ├── maxToolCalls=2 兜底
│ │ └── 每步写 infoLog/warnLog → log.yml
│ ├─ task(profile) → 提取用户画像写入 config/user.md
│ ├─ task(note) → 保存/查询笔记 (notes.md / notes/*.md)
│ ├─ memory.read → 读 config/user.md / session/dialog.yml / soul.md / notes.md
│ ├─ memory.write → 写 config/ session/ notes/ 各文件
│ └─ 其他工具 (http-get, geocode, …)
└─ 返回 text → 流已渲染完毕 → 结束
单 Agent 查询跳过 observation + summary综合查询合并同一轮写
```
### 阶段一(会议室架构基础
## 当前状态2026-05-16 v2.3.0
```
yunshu (会议室架构)
├── dialog-agent.md (type: main入口+调度)
├── weather-sub.md (type: sub天气领域)
├── memory-sub.md (type: sub记忆管理)
── narrator-sub.md (type: sub汇报员,成熟期)
yunshu (会议室架构 — 核心引擎 + 日志 + 画像 + 备忘录)
├── dialog-agent.md (type: main主持者)
├── weather-sub.md (type: sub天气) ✅
├── profile-sub.md (type: sub用户画像) ✅
── note-sub.md (type: sub备忘录) ✅
├── ✨ 日志系统 ✅ charmbracelet/log v2 + log.yml + yunshu log
├── ✨ LLM 延迟加载 ✅ sync.Once--help 不读 config
├── ✨ 路径安全 ✅ EvalSymlinks + filepath.Rel
├── ✨ 热加载 ✅ 交互模式每轮 ScanAgents()
├── ✨ 会话裁剪 ✅ LoadSession 限 40 条
├── ✨ 流式输出 ✅ SSE 流式 + \n\n 段落缓冲 + mdprint
├── ✨ 性能优化 ✅ note 一步完成 + obs/summary 合并 + maxToolCalls=2
├── earthquake-sub.md (type: sub地震) ❌ 待实现
├── train-sub.md (type: sub火车票) ❌ 待实现
├── hotel-sub.md (type: sub住宿) ❌ 待实现
└── narrator-sub.md (type: sub汇报员/成熟期) ❌ 待实现
```
### 阶段二(多领域扩展)→ 河虾 Claw
## 存储结构
```
yunshu / hxclaw (多领域主-从)
├── dialog-agent.md (type: main入口+调度)
├── weather-sub.md (type: sub天气)
├── earthquake-sub.md (type: sub地震)
── volcano-sub.md (type: sub火山)
├── nuclear-sub.md (type: sub核电监测)
├── memory-sub.md (type: sub记忆)
└── narrator-sub.md (type: sub汇报)
~/.config/yunshu/
├── config/
├── config.yml ← LLM 配置(已有)
├── soul.md ← AI 灵魂(用户可编辑)
── user.md ← 用户画像profile-sub 写 ## 画像dialog 写 ## AI观察到
├── session/
├── session.json ← 完整对话历史(直接 POST API
└── dialog.yml ← 对话摘要dialog 每轮写入)
├── notes.md ← 备忘录note-sub 维护,列表格式)
├── notes/ ← 独立笔记文件(复杂内容用)
├── log.yml ← YAML 序列日志yunshu log 命令查看)
├── cache/ ← 子 Agent 缓存
├── agents/ ← Agent 定义
├── skills/ ← 知识技能
└── memory.json ← ❌ 已删除(迁移完毕)
```
## 写入策略
| 文件 | 写入方式 | 说明 |
|------|---------|------|
| `config/user.md` | `##` 标题合并 | 各板块独立更新,互不覆盖 |
| `session/dialog.yml` | key 合并 | 每轮覆写对话摘要 |
| `notes.md` | 全文覆写 | note-sub 全量管理 |
| `notes/` 独立文件 | 全文覆写 | 每个笔记一个文件 |
| `log.yml` | YAML 序列追加 | 读→追加→Marshal→写双写模式 |
```
## 架构文档
详细架构计划见 `docs/会议室架构计划书.md`
- `docs/会议室架构计划书.md` — 完整设计方案
- `docs/AGENTS.md` — 编码规范
- `docs/changelog.md` — 变更日志
- `docs/taolun.md` — 讨论历史