Files
YunShu/docs/AGENTS.md
titor 0898188086 docs: 会议室架构规划 + MSN hourlyforecast 端点更新
- 新增 docs/会议室架构计划书.md 完整架构方案(主持者+子Agent+task+cache+记忆)
- 更新 taolun.md 追加 2026-05-11 讨论历史
- 更新 AGENTS.md 规范(type, cache 字段)
- 更新 architecture.md 后续演进章节
- 更新 changelog.md 架构规划里程碑
- 修复 MSN 天气接口文档:新增 hourlyforecast,标记 weathertrends 已失效
- 更新 skills/msn-weather-api/SKILL.md 新增 hourlyforecast 端点
- 更新 agents/weather-agent.md 支持逐小时查询
2026-05-11 08:32:30 +08:00

178 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 编码规范
## 通用规范
- 全程使用中文书写注释、文档、沟通以及内部思考过程
- 所有代码必须包含详细的中文注释,说明函数功能、参数含义、关键逻辑
- Markdown 文件使用 `#` 标题层级,保持结构清晰
- 变量命名采用驼峰式,类型和函数首字母大写导出
- 同一个问题连续工作 3 次没有结论,立即退出并询问用户接下来怎么做
## Go 代码规范
- 使用 `package main` 扁平结构MVP 阶段),后续可拆分子包
- 错误处理:所有可能失败的操作必须检查 error
- 错误信息使用中文描述
- 导出函数(首字母大写)供包外调用,非导出函数(首字母小写)为内部实现
- HTTP 客户端设置超时(默认 15s避免资源泄漏
- JSON 序列化/反序列化使用 `encoding/json` 标准库
- 终端颜色输出优先使用 `pkg/style` 包:
- 8 色用 `Fg(ColorXxx)` / `Bg(ColorXxx)`
- 真彩色用 `FgHex("#RRGGBB")` / `BgHex("#RRGGBB")`
- 所有通配 `.Render(text)` 生成 ANSI 转义序列
## Agent 定义规范(.md 文件)
- 必须包含 YAML frontmatter`---` 包裹)
- frontmatter 必需字段:`name`, `description`, `type`, `tools`
- `type` 可选值:`main`(主持者/对话 Agent唯一入口`sub`(领域专家,被 task 调)
- `cache` 可选字段:`ttl`(过期秒数)、`keys`(从 args 中提取的缓存 key 字段列表)
- tools 为数组,声明 agent 需要的工具名(在 tool.go 中注册)
- body 为 system prompt**只定义行为逻辑**(角色、工作流程、输出规范)
- **关键技术细节URL、apiKey、请求头、JSON 路径等)不要 inline 在 agent skill 中**,改为:
- 放到 `skills/*/SKILL.md` 中,由 agent 调用 `skill("name")` 按需加载
- 或注册为 tool确定性操作由 agent 声明 tools 即可调用
- session 文件存在 `~/.config/yunshu/session.json`,不污染项目目录
### 主持者示例type: main
```markdown
---
name: dialog
type: main
description: 个人助理,负责闲聊和调度
tools:
- task
- memory.read
- memory.write
---
# 对话助理
你是用户的私人助理...
你可以调度以下子 Agent
- weather: 天气查询
- earthquake: 地震信息
用 task("agent_name", {args}) 调度。
不自己回答领域问题。
```
### 子 Agent 示例type: sub
```markdown
---
name: weather
type: sub
description: 天气查询专家
cache:
ttl: 7200
keys: ["city", "forecast_type"]
tools:
- http-get
- geocode
- skill
---
# 天气专家
你是天气领域的专家。被调时才回答。
被调时你会收到:
- args: 查询参数
- cache_data: 上次缓存的原始数据(有时)
有 cache_data 且未过期 → 直接回答,不调 API。
无 cache_data → 调 http-get 获取新数据。
返回格式:
你的回答文本
---CACHE---(只有数据更新时带)
{原始 JSON 数据}
```
## Session 规范
- 文件路径:`~/.config/yunshu/session.json`
- 格式JSON 数组,元素为 Message 对象(兼容 OpenAI Chat Completion messages 格式)
- 角色类型:`system`, `user`, `assistant`, `tool`
- 启动时清空,每轮对话追加
- 消息顺序即对话顺序
- 放在用户配置目录而非项目目录,确保不同目录下运行时上下文连贯
## 工具注册规范
- 工具在 `tool.go``init()` 中通过 `RegisterTool()` 注册
- 每个工具定义Name, Description, ParametersJSON Schema, Execute 函数
- 工具名与 `.md` 文件中声明的 tools 列表对应
- Execute 函数接收 `map[string]interface{}` 参数,返回 string 和 error
## 环境变量
| 变量名 | 必需 | 说明 |
|--------|------|------|
| `LLM_API_KEY` | 否* | API Key覆盖配置文件 |
| `LLM_ENDPOINT` | 否 | API 端点,覆盖配置文件 |
| `LLM_MODEL` | 否 | 模型名,覆盖配置文件 |
| `OPENAI_API_KEY` | 否 | 兼容旧名,当 `LLM_API_KEY` 未设置时生效 |
> *注:可在 `~/.config/yunshu/config.yaml` 中配置,无需环境变量。
> 首次使用请运行 `yunshu onboard` 交互式初始化。
---
## 【认知修正】
> 本字段存放开发过程中验证后的知识点、踩坑记录。以陈述句形式记录。
### 2026-05-07
1. **MSN 天气 API 属于非公开内部接口**apiKey 固定为 `j5i4gDqHL6nGYwx5wi5kRhXjtf2c5qgFX9fzfk0TOo`,修改任意字符即 401。必须携带 `User-Agent``Referer` 请求头,否则返回 401。响应数据在 `value[0].responses[0].weather[0]` 路径下。
2. **Go 的 `syscall` 包是标准库,无需额外依赖**。在 Windows 上可通过 `kernel32.SetConsoleOutputCP(65001)` 设置控制台 UTF-8 编码,但 PowerShell 5.1 有独立的 `[Console]::OutputEncoding` 覆盖此设置,需要额外 `[Console]::OutputEncoding = [Text.Encoding]::UTF8`
3. **豆包火山引擎API 兼容 OpenAI Chat Completion 格式**,包括 function callingtool_calls。修改 `endpoint``model` 即可切换,无需改动代码逻辑。实测 `doubao-seed-2-0-pro-260215` 支持工具调用正常。
4. **非流式调用更简单可靠**。对于 CLI 工具,等待完整响应再输出比流式逐 token 输出实现更简单,且用户能一次获取完整信息。
5. **Session 文件的关键设计**session 存储的是完整的对话消息列表(不含 system prompt格式与 OpenAI Chat Completion API 的 messages 数组一致。这意味着 runtime 不需要做任何格式转换,读 session → 直接 POST 给 LLM → 拿到回复 → 追加到 session。
6. **Go 的 `gopkg.in/yaml.v3` 依赖可能遇到 GOSUMDB 问题**。在中国网络环境下,需要设置 `GONOSUMCHECK='*'``GONOSUMDB='*'` 环境变量来绕过 checksum 数据库验证。
7. **工具定义要提供清晰的 JSON Schema 参数描述**。LLM 通过参数描述来理解如何调用工具。描述越清晰LLM 生成正确参数的概率越高。`http-get` 工具的 `headers` 参数设计为 JSON 字符串格式,比结构化对象更灵活。
8. **Go 中处理 OpenAI 响应的 Content 字段要使用指针类型**。当 LLM 返回 tool_calls 时content 字段为 nullJSON 中的 null而非空字符串。使用 `*string` 才能区分"内容为空"和"无内容"两种情况。
9. **配置文件放在 `~/.config/yunshu/config.yaml` 而非 .env/.secret**。YAML 格式与 agent 定义风格一致统一管理。API Key 用 `0600` 权限保护。优先顺序:环境变量 > 配置文件 > 默认值。`onboard` 子命令提供交互式初始化体验。
10. **双路径搜索机制**:项目目录优先,`~/.config/yunshu/` 后备。这使得开发时用项目本地文件,部署后自动切换到全局配置。`SearchFile()``LoadAgent()/LoadSkill()` 都遵循此规则。
11. **用户配置目录固定为 `~/.config/yunshu/`**,所有系统统一。存放 config.yaml、session.json、以及用户自定义的 agents/skills/data。不能改到其他路径。
12. **Agent skill、普通 skill、tool 必须严格分离,不能混淆**。Agent skill`agents/*.md`)只放行为逻辑(角色、工作流程、输出风格),不 inline 任何技术细节。技术细节URL、apiKey、请求头、JSON 解析路径)放在 `skills/*/SKILL.md` 作为纯知识,由 LLM 按需调用 `skill("name")` 加载。确定性操作(如 geocode注册为 tool保证 100% 可靠执行。这解决了 picoclaw 单 agent 架构下 skill 污染上下文的问题。
13. **wttr.in `?format=j1` 返回的 JSON 包含地理编码信息**`nearest_area[0]` 中有 `latitude``longitude``areaName``country``population` 字段。可作为免费的地理编码服务使用,无需 API Key。
14. **geocode 工具用 Go 代码实现比让 LLM 自己调 http-get 解析 JSON 更可靠**。LLM 在构造 URL 和解析嵌套 JSON 时容易出错(尤其是中文编码问题)。注册为 tool 后LLM 只需提供城市名参数Go 代码处理所有细节。
15. **项目正式命名为云枢·AgentYunShu / yunshu**,配置目录从 `~/.config/weather-cli/` 迁移到 `~/.config/yunshu/`。旧目录在首次运行时会自动迁移并删除。二进制名称改为 `yunshu`。如果迁移失败,用户可手动复制旧目录内容后重新运行。
### 2026-05-09
1. **Windows raw mode + bufio.Reader 冲突**:在禁用 `ENABLE_LINE_INPUT` 的 raw mode 下,`bufio.NewReader(os.Stdin).ReadRune()` 会因内部预读缓冲(默认 4KB导致读取阻塞。后续尝试用 `ReadConsoleInputW` + 手动回显也因光标位置计算不一致而放弃。**最终决定放弃自实现 Tab 补全**,后续如需补全功能,引入第三方库(如 `go-prompt` / `readline`)。
2. **ANSI 光标移动需要启用输出 VT 处理**`\033[A`(光标上移)/ `\033[J`(清屏)等输出序列需要输出句柄设置 `ENABLE_VIRTUAL_TERMINAL_PROCESSING`0x0004才能生效。只设置输入句柄的 mode 不够,输入输出句柄是两个独立的控制台句柄。
3. **ReadLineWithCompletion / Completer 类型已移除**`completer.go` 清空,`main.go` 回到 `termui.ReadLine()``cmdCompleter``commonPrefix`、相关测试一并移除。`input.go``ReadConsoleInputW` 相关的 `keyEventRecord`/`inputRecord` 结构和 proc 也一并清理。
### 2026-05-11
1. **MSN 天气存在 `hourlyforecast` 端点**`https://assets.msn.cn/service/weather/hourlyforecast`,返回未来 10 天逐小时预报数据,参数和 dailyforecast 一致。之前文档遗漏了该端点。`weathertrends` 端点已失效500 Internal Server Error
2. **MSN 的 `assets.msn.cn` 国内城市接口正常**:用经纬度查询 `assets.msn.cn/service/weather/current` 对国内城市返回正确数据。之前 Agent 误报"返回也门数据"是因为用了 `api.msn.cn` 的城市名接口(该接口本就有文档标注的问题:城市名匹配不可靠)。**用 `assets.msn.cn` + 经纬度即可正常获取国内城市数据,不需要切换到 wttr.in。**
3. **会议室架构决策**:确定从单 Agent 升级为 1 主持dialog, type:main+ N 领域专家type:sub+ 共享黑板memory的架构。主持者保持极薄只有人格 + 调度规则 + `task` + `memory` 工具),子 Agent 只做领域工作,用完即毁。详见 `docs/会议室架构计划书.md`
4. **Cache 设计原则**Frontmatter 声明 `cache.keys``cache.ttl``task` 工具机械化从 args 取值拼 key、查/写缓存。子 Agent 不感知缓存存在,只需在回答末尾可选带 `---CACHE---` + JSON 供 task 存储。一个 Agent 一个缓存 JSON 文件MD5 hash 做 key。
5. **记忆系统规则**:共享黑板模式,所有 Agent 可读,仅 memory Agent 可写。dialog-agent 是最小写入者(只写 `dialog_context`memory Agent 负责从对话中提取用户画像写入长期记忆。