Unified Agent + reusable Go agent core.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: Add draft for workspace persona and contacts profile extension

Lyric cc9a7b34 8abcf83b

+367 -1
+340
docs/feat/feat_20260208_workspace_persona_and_contacts_profile.md
··· 1 + --- 2 + date: 2026-02-08 3 + title: Workspace Persona Context + Group Chat Rules + Contacts Profile 扩展方案 4 + status: draft 5 + --- 6 + 7 + # 任务细化稿(2026-02-08) 8 + 9 + 本文将需求拆成 4 条实施流: 10 + 11 + 1. 增加 `TOOLS.md`(本地工具环境笔记) 12 + 2. 增强群聊发言规则(减少“刷屏感”) 13 + 3. 扩展 `contacts` 画像字段(`pronouns` / `timezone` / 长文本偏好上下文) 14 + 4. 增加 `contacts_upsert` 内置 tool(让 agent 可直接录入/更新联系人) 15 + 16 + ## 1) 背景与目标 17 + 18 + 目标不是新增“能力”,而是把现有能力的行为边界更显式、可调、可测试: 19 + 20 + - 通过 `TOOLS.md` 把环境特定知识从 skills/tool schema 中剥离。 21 + - 通过群聊规则把“该说/不该说”落为可执行约束。 22 + - 通过 `contacts` 新字段补齐联系人画像中缺失的人类语境信息。 23 + 24 + ## 2) 范围与非目标 25 + 26 + 范围: 27 + 28 + - `assets/config/` 模板补充 29 + - prompt 组装链路补充 block/rules 30 + - Telegram 群聊策略增强 31 + - contacts 数据结构、CLI、tool、文档、测试补充 32 + 33 + 非目标: 34 + 35 + - 不改 MAEP 协议层 36 + - 不重做 memory 架构 37 + - 不引入新的外部存储(仍基于 markdown/json 文件存储) 38 + 39 + ## 3) 工作流 A: 增加 TOOLS.md 40 + 41 + ### A.1 设计意图 42 + 43 + `TOOLS.md` 是“本地环境映射笔记”,不是工具定义本身。 44 + 它记录 camera 名称、设备别名、SSH 别名、TTS 偏好等,减少 agent 猜测和反复提问。 45 + 46 + ### A.2 任务拆解 47 + 48 + - [ ] 新增模板 `assets/config/TOOLS.md` 49 + - 内容定位:本地环境映射、示例、与 skills 分离原则。 50 + - [ ] 安装流程补充 `TOOLS.md` 51 + - 文件:`cmd/mistermorph/install.go` 52 + - 补充 loader:`loadToolsTemplate()` 53 + - 在 `filePlans` 中新增 `TOOLS.md`(存在则跳过)。 54 + - [ ] prompt 组装链路补充 `TOOLS.md` 注入 55 + - 建议方式:新增 `internal/promptprofile/context.go`(或在现有 `identity.go` 扩展),读取 `TOOLS.md` 后以 `PromptBlock` 注入,而不是覆盖 `spec.Identity`。 56 + - block title 建议:`Local Tool Notes`。 57 + - [ ] 文档更新 58 + - `docs/prompt.md`:增加 “TOOLS.md context block” 的来源与注入时机。 59 + 60 + ### A.3 关键决策点 61 + 62 + - [ ] 决定 `TOOLS.md` 读取路径基准(`file_state_dir` 或 workspace root)并统一到代码和安装行为。 63 + - [ ] 约束最大注入长度(例如 4KB/8KB)避免 prompt 膨胀。 64 + 65 + ### A.4 验收标准 66 + 67 + - 设计合理的 `TOOLS.md` 内容模板 68 + - `TOOLS.md` 存在时能进入系统 prompt block。 69 + - `TOOLS.md` 缺失/空文件不影响主流程。 70 + - 安装命令可初始化该模板,且不覆盖用户已有内容。 71 + 72 + ### A.5 测试清单 73 + 74 + - [ ] `cmd/mistermorph/install_test.go`:新增 `loadToolsTemplate` 相关测试。 75 + - [ ] `internal/promptprofile/*_test.go`:验证 `TOOLS.md` 缺失/空/有效内容注入行为。 76 + 77 + ## 4) 工作流 B: 群聊发言规则增强 78 + 79 + ### B.1 设计意图 80 + 81 + 把“参与但不主导”的群聊行为转成明确规则,避免无价值回复和多次连发。 82 + 83 + ### B.2 任务拆解 84 + 85 + - [ ] 提炼群聊规则并注入 Telegram prompt 86 + - 文件:`cmd/mistermorph/telegramcmd/command.go` 87 + - 注入点:`runTelegramTask(...)` 的群聊分支(现有 `isGroupChat(...)` 附近)。 88 + - 规则覆盖: 89 + - 仅在被点名/被提问/确有增量价值时发文本; 90 + - 无增量价值时优先 emoji reaction; 91 + - 同一条消息不多次碎片化回复(anti triple-tap)。 92 + - [ ] humanlike 应该为 telegram 群聊下的默认策略 93 + - [ ] 触发层与生成层职责分离 94 + - 触发层继续决定“是否进入 agent run”(现有 `groupTriggerDecision`)。 95 + - 生成层决定“文本回复 vs reaction”。 96 + - [ ] 更新文档 97 + - `docs/prompt.md`:补充 Telegram 群聊行为规则来源。 98 + - `docs/feat/feat_20260205_telegram_reactions.md`:补充与 reaction 策略的关系。 99 + 100 + ### B.3 验收标准 101 + 102 + - 群聊中“低价值消息”显著减少文本回复占比。 103 + - 对被明确点名/提问的消息,回复率不下降。 104 + - 不出现同一消息多次连续回复/反应的退化行为。 105 + 106 + ### B.4 测试清单 107 + 108 + - [ ] `groupTriggerDecision` 相关单测补充(点名/回复/普通闲聊路径)。 109 + - [ ] prompt rules 单测:群聊时规则存在,私聊时不注入群聊规则。 110 + - [ ] reaction 相关回归:可 reaction 时不发送冗余文本。 111 + 112 + ## 5) 工作流 C: contacts 画像字段扩展 113 + 114 + > 用户请求中的 `pronous` 统一按 `pronouns` 实现。 115 + 116 + ### C.1 设计意图 117 + 118 + `contacts` 目前偏“互动评分与路由画像”,缺少部分“人类语境字段”。 119 + 新增字段用于提升称呼礼貌、时区相关决策、长期偏好对齐: 120 + 121 + - `pronouns` 122 + - `timezone` 123 + - `preference_context`(长文本偏好上下文) 124 + 125 + ### C.2 数据模型任务 126 + 127 + - [ ] 扩展 `contacts.Contact` 结构 128 + - 文件:`contacts/types.go` 129 + - 新字段建议: 130 + - `Pronouns string \`json:"pronouns,omitempty"\`` 131 + - `Timezone string \`json:"timezone,omitempty"\`` 132 + - `PreferenceContext string \`json:"preference_context,omitempty"\`` 133 + - [ ] 规范化与约束 134 + - 文件:`contacts/file_store.go` 135 + - 在 `normalizeContact(...)` 增加 trim 与长度限制: 136 + - `pronouns`:短文本(建议 <=64 chars) 137 + - `timezone`:IANA 时区校验(非法值保留原值或置空,需明确策略) 138 + - `preference_context`:长文本(建议 <=2000 chars) 139 + 140 + ### C.3 字段填充场景(口径) 141 + 142 + | 字段 | 主要填充入口 | 允许自动提取 | 覆盖策略 | 143 + |---|---|---|---| 144 + | `pronouns` | `contacts upsert`(CLI)/ 后续 `contacts_upsert` tool 明确写入 | 否(默认不猜测) | 仅在明确声明时覆盖 | 145 + | `timezone` | `contacts upsert`(CLI)/ 后续 `contacts_upsert` tool 明确写入 | 否(默认不猜测) | 仅合法 IANA 时区可写入 | 146 + | `preference_context` | `contacts upsert`(CLI 或 tool)+ 会话后画像提取流程 | 是(从会话与记忆提取) | 低频更新,保留人工覆盖优先级 | 147 + 148 + 说明: 149 + 150 + - 自动观察入口(Telegram/MAEP contact observe)默认不写 `pronouns/timezone`,避免猜测性写入。 151 + - `preference_context` 允许来自 LLM 摘要,但需要长度限制与隐私边界。 152 + 153 + ### C.4 CLI 与运维任务 154 + 155 + - [ ] `contacts upsert` 增加参数 156 + - 文件:`cmd/mistermorph/contactscmd/contacts.go` 157 + - 新参数建议: 158 + - `--pronouns` 159 + - `--timezone` 160 + - `--preference-context` 161 + - 可选:`--preference-context-file` 162 + - [ ] `contacts list` 输出优化 163 + - 默认简版保持不变,`--json` 返回完整字段即可。 164 + 165 + ### C.5 新增 `contacts_upsert` tool(agent 可调用) 166 + 167 + - [ ] 新增 tool 实现 168 + - 文件:`tools/builtin/contacts_upsert.go` 169 + - 语义:单联系人 upsert,支持 partial patch(不传字段默认保留旧值)。 170 + - [ ] 注册到默认工具表 171 + - 文件:`cmd/mistermorph/registry.go` 172 + - 在 `tools.contacts.enabled=true` 时注册。 173 + - [ ] 参数 schema 设计 174 + - 必选建议:`contact_id`(或 `subject_id/node_id/peer_id` 至少一个)。 175 + - 可选字段:`kind/status/contact_nickname/persona_brief/persona_traits/pronouns/timezone/preference_context/topic_weights/...`。 176 + - [ ] 日志安全摘要补充 177 + - 文件:`agent/engine_helpers.go` 178 + - 为 `contacts_upsert` 增加参数摘要,避免长文本原文落日志。 179 + - [ ] 文档更新 180 + - 文件:`docs/tools.md` 181 + - 增加 `contacts_upsert` 用途、参数、约束与示例。 182 + 183 + ### C.6 Tool / Prompt 联动任务 184 + 185 + - [ ] `contacts_list` 文档更新 186 + - 文件:`docs/tools.md` 187 + - 明确返回字段包含 `pronouns` / `timezone` / `preference_context`。 188 + - [ ] LLM 特征提取输入补充上下文 189 + - 文件:`contacts/llm_features.go` 190 + - 将 `preference_context` 纳入输入,提升 topic/persona 提取准确性。 191 + - [ ] 隐私边界 192 + - 公共聊天上下文默认不主动暴露长文本 `preference_context` 原文。 193 + - 仅在相关任务中按需最小披露。 194 + 195 + ### C.7 存储兼容性与迁移 196 + 197 + - [ ] 兼容策略确认:使用 `omitempty` + JSON 解码天然前向兼容,默认无需批量迁移。 198 + - [ ] 可选补偿脚本:仅在需要批量填充 timezone/pronouns 时提供。 199 + 200 + ### C.8 验收标准 201 + 202 + - 新字段可通过 CLI 与 `contacts_upsert` tool 写入、通过 `contacts_list` 读取。 203 + - `active.md` / `inactive.md` 旧数据可直接读取,无崩溃/丢字段。 204 + - LLM 特征提取可消费新字段,且不影响旧流程。 205 + - agent 可在会话中调用 `contacts_upsert` 完成联系人画像补录。 206 + 207 + ### C.9 测试清单 208 + 209 + - [ ] `contacts` 存储 roundtrip 测试(含新字段)。 210 + - [ ] `contacts upsert` 参数解析与写入测试。 211 + - [ ] `tools/builtin/contacts_upsert.go` 单测(创建、更新、partial patch、非法参数)。 212 + - [ ] `contacts_list` 输出 JSON 字段回归测试。 213 + - [ ] `llm_features` payload 组装测试。 214 + 215 + ## 6) 推荐实施顺序 216 + 217 + 建议按低风险到高影响顺序分 4 个 PR: 218 + 219 + 1. PR-1: `TOOLS.md` 模板 + 安装 + prompt block 注入 220 + 2. PR-2: 群聊规则注入 + 配置开关 + 回归测试 221 + 3. PR-3: contacts 字段扩展 + CLI + extractor 联动 222 + 4. PR-4: `contacts_upsert` tool + registry + docs + tests 223 + 224 + ## 7) 风险与回滚 225 + 226 + 风险: 227 + 228 + - `TOOLS.md` 注入过长导致 token 消耗上升 229 + - 群聊规则过严导致漏回 230 + - contacts 新字段泄露边界处理不当 231 + 232 + 回滚策略: 233 + 234 + - `TOOLS.md` 注入可通过开关禁用 235 + - 群聊策略可退回 `strict/smart` 旧路径 236 + - contacts 字段为可选字段,回滚可仅停止写入新字段 237 + 238 + ## 8) 开放问题(实现前确认) 239 + 240 + - [ ] `TOOLS.md` 与 `IDENTITY/SOUL` 的统一路径基准最终选哪一个? 241 + - [ ] `timezone` 非法值策略:拒绝写入 vs 容忍写入并打告警? 242 + - [ ] `preference_context` 是否需要单独“摘要字段”供公共场景安全注入? 243 + 244 + ## 9) 执行 TODO 明细(按 PR 顺序) 245 + 246 + ### PR-1: `TOOLS.md` 模板 + 安装 + Prompt 注入 247 + 248 + - [ ] 新增文件 `assets/config/TOOLS.md`,写入本地环境笔记模板(含示例与边界说明)。 249 + - [ ] 更新 `cmd/mistermorph/install.go`: 250 + - [ ] 增加 `loadToolsTemplate()`。 251 + - [ ] 在 `filePlans` 中增加 `TOOLS.md`。 252 + - [ ] 保持“已存在即跳过”行为与现有模板一致。 253 + - [ ] 更新 `cmd/mistermorph/install_test.go`: 254 + - [ ] 增加 `loadToolsTemplate()` 返回非空与标题校验。 255 + - [ ] 更新 prompt 组装逻辑(建议新建 `internal/promptprofile/context.go`): 256 + - [ ] 读取 `TOOLS.md`(与 `IDENTITY/SOUL` 同路径基准)。 257 + - [ ] 当文件非空时注入 `PromptBlock{Title: "Local Tool Notes"}`。 258 + - [ ] 增加注入内容长度上限(避免 prompt 膨胀)。 259 + - [ ] 更新 `docs/prompt.md`: 260 + - [ ] 增加 `TOOLS.md` 注入来源与时机说明。 261 + - [ ] 验证: 262 + - [ ] `go test ./cmd/mistermorph/... ./internal/promptprofile/...` 263 + 264 + ### PR-2: 群聊规则增强(触发层/生成层分离) 265 + 266 + - [ ] 明确触发层职责(只决定是否 run): 267 + - [ ] 在 `cmd/mistermorph/telegramcmd/command.go` 注释/文档化 `groupTriggerDecision(...)`。 268 + - [ ] 禁止触发层承载“文本还是 reaction”的策略。 269 + - [ ] 明确生成层职责(只决定响应形式): 270 + - [ ] 在 `runTelegramTask(...)` 增加群聊规则 prompt 条款: 271 + - [ ] 仅在有增量价值时发文本。 272 + - [ ] 无增量价值优先 reaction。 273 + - [ ] 禁止同消息多次碎片化回复(anti triple-tap)。 274 + - [ ] 增加配置项: 275 + - [ ] `telegram.group.reply_policy`(建议:`strict|humanlike`)。 276 + - [ ] 默认设为 `humanlike`(群聊)。 277 + - [ ] 更新文档: 278 + - [ ] `docs/prompt.md` 补充群聊行为规则注入点。 279 + - [ ] `docs/feat/feat_20260205_telegram_reactions.md` 补充与 reaction 的职责边界。 280 + - [ ] 测试: 281 + - [ ] 补充 `groupTriggerDecision` 触发路径测试。 282 + - [ ] 补充“群聊规则只在群聊注入”的测试。 283 + - [ ] 回归 reaction 场景,确保不发送冗余文本。 284 + - [ ] 验证: 285 + - [ ] `go test ./cmd/mistermorph/telegramcmd/...` 286 + 287 + ### PR-3: `contacts` 字段扩展(`pronouns/timezone/preference_context`) 288 + 289 + - [ ] 扩展模型 `contacts/types.go`: 290 + - [ ] 增加 `Pronouns` 字段。 291 + - [ ] 增加 `Timezone` 字段。 292 + - [ ] 增加 `PreferenceContext` 字段。 293 + - [ ] 更新 `contacts/file_store.go`: 294 + - [ ] 在 `normalizeContact(...)` 中新增字段 trim。 295 + - [ ] 对 `preference_context` 增加长度上限。 296 + - [ ] 对 `timezone` 增加合法性校验策略(按开放问题结论实施)。 297 + - [ ] 更新 CLI `cmd/mistermorph/contactscmd/contacts.go`: 298 + - [ ] `contacts upsert` 增加 `--pronouns`。 299 + - [ ] `contacts upsert` 增加 `--timezone`。 300 + - [ ] `contacts upsert` 增加 `--preference-context`。 301 + - [ ] 可选:增加 `--preference-context-file`。 302 + - [ ] 更新 `contacts/llm_features.go`: 303 + - [ ] 在提取输入 payload 中加入 `preference_context`。 304 + - [ ] 保持输出契约不破坏兼容。 305 + - [ ] 更新文档: 306 + - [ ] `docs/tools.md` 更新 `contacts_list` 返回字段说明。 307 + - [ ] 测试: 308 + - [ ] `contacts` 存储 roundtrip(新字段读写)。 309 + - [ ] CLI 参数解析与写入测试。 310 + - [ ] `llm_features` payload 组装测试。 311 + - [ ] 验证: 312 + - [ ] `go test ./contacts/... ./cmd/mistermorph/contactscmd/...` 313 + 314 + ### PR-4: 新增 `contacts_upsert` 内置 Tool 315 + 316 + - [ ] 新增 `tools/builtin/contacts_upsert.go`: 317 + - [ ] 定义工具名、描述、参数 schema。 318 + - [ ] 实现“partial patch”语义(未提供字段保留旧值)。 319 + - [ ] 至少支持 `contact_id|subject_id|node_id|peer_id` 的最小识别策略。 320 + - [ ] 更新 `cmd/mistermorph/registry.go`: 321 + - [ ] 在 `tools.contacts.enabled=true` 时注册 `contacts_upsert`。 322 + - [ ] 更新 `agent/engine_helpers.go`: 323 + - [ ] 为 `contacts_upsert` 增加安全日志摘要(不输出长文本全文)。 324 + - [ ] 更新文档: 325 + - [ ] `docs/tools.md` 增加 `contacts_upsert` 章节(用途、参数、约束)。 326 + - [ ] 测试: 327 + - [ ] 新增 `tools/builtin/contacts_upsert_test.go`。 328 + - [ ] 场景覆盖:创建、更新、partial patch、非法 kind/status、缺失标识字段。 329 + - [ ] 更新 `agent/engine_helpers_test.go`,覆盖新工具参数摘要。 330 + - [ ] 验证: 331 + - [ ] `go test ./tools/builtin/... ./agent/...` 332 + 333 + ### 收尾(合并前统一检查) 334 + 335 + - [ ] 全量单测:`go test ./...` 336 + - [ ] 静态检查:`go vet ./...` 337 + - [ ] 文档自检: 338 + - [ ] `docs/tools.md` 与实际注册工具一致。 339 + - [ ] `docs/prompt.md` 与实际注入路径一致。 340 + - [ ] 本文档里所有 TODO 的文件路径可直接定位到仓库。
+26
docs/tools.md
··· 12 12 - `url_fetch` 13 13 - `web_search` 14 14 - `memory_recently` 15 + - `contacts_upsert` 15 16 - `contacts_list` 16 17 - `contacts_candidate_rank` 17 18 - `contacts_send` ··· 125 126 | `days` | `integer` | 否 | `3` | 时间窗口(天)。 | 126 127 | `limit` | `integer` | 否 | `tools.memory.recently.max_items` | 返回条数上限。 | 127 128 | `include_body` | `boolean` | 否 | `false` | 是否附带解析后的 body。 | 129 + 130 + ## `contacts_upsert` 131 + 132 + 用途:创建或更新单个联系人画像(支持部分字段更新,未提供字段默认保留原值)。 133 + 134 + 参数: 135 + 136 + | 参数 | 类型 | 必填 | 默认值 | 说明 | 137 + |---|---|---|---|---| 138 + | `contact_id` | `string` | 条件必填 | 无 | 联系人稳定 ID。更新时建议提供。 | 139 + | `status` | `string` | 否 | `active` | `active` / `inactive`。 | 140 + | `contact_nickname` | `string` | 否 | 空 | 联系人昵称。 | 141 + | `persona_brief` | `string` | 否 | 空 | 联系人互动风格摘要。 | 142 + | `persona_traits` | `object<string,number>` | 否 | 空 | 人格特征权重映射。 | 143 + | `subject_id` | `string` | 条件必填 | 空 | 人类联系人的主体 ID。 | 144 + | `understanding_depth` | `number` | 否 | 继承旧值或 `30` | 认知深度,范围 `[0,100]`。 | 145 + | `topic_weights` | `object<string,number>` | 否 | 空 | topic 偏好权重映射。 | 146 + | `reciprocity_norm` | `number` | 否 | 继承旧值或 `0.5` | 互惠分,范围 `[0,1]`。 | 147 + 148 + 约束: 149 + 150 + - `contact_id` / `subject_id` 至少提供一个。 151 + - 当 `contact_id` 缺失时,服务会尝试由 `subject_id` 推导联系人 ID。 152 + - `status` 仅支持 `active|inactive`。 153 + - 数值参数会在存储层被归一化(例如深度裁剪到 `[0,100]`、分值裁剪到 `[0,1]`)。 128 154 129 155 ## `contacts_list` 130 156
+1 -1
internal/promptprofile/identity.go
··· 75 75 76 76 func buildPersonaIdentity(identityDoc string, soulDoc string) string { 77 77 var b strings.Builder 78 - b.WriteString("You are the assistant described by the following local persona files. ") 78 + b.WriteString("You are the person (not an AI assistant) described by the following local persona files. ") 79 79 b.WriteString("Treat them as your primary identity, tone, and behavioral guidance.\n\n") 80 80 if identityDoc != "" { 81 81 b.WriteString("## IDENTITY.md\n")