From 807f733a1cee4f8e67462ae2042af577e1c1e121 Mon Sep 17 00:00:00 2001 From: --git_token Date: Fri, 8 May 2026 08:10:01 +0800 Subject: [PATCH] auto backup 2026-05-08 08:10:01 --- .vala_skill_hashes | 2 +- memory/.dreams/events.jsonl | 4 + memory/.dreams/short-term-recall.json | 136 ++++-- memory/2026-05-07-2032.md | 12 + memory/2026-05-07-2049.md | 44 ++ memory/2026-05-07-2051.md | 29 ++ memory/2026-05-07-feishu-group-test.md | 43 ++ memory/2026-05-07-greeting-hi.md | 18 + memory/2026-05-07.md | 208 +++++++++ .../飞书反馈_2026-05-06.xlsx | Bin 0 -> 6918 bytes .../飞书反馈_2026-05-07.xlsx | Bin 0 -> 7072 bytes scripts/export_lark_feedback_to_wiki.py | 28 +- scripts/run_export_lark_feedback.sh | 6 +- scripts/sync_feishu_feedback_dispatch_p0.sh | 21 + scripts/sync_feishu_feedback_realtime.sh | 21 + scripts/sync_feishu_feedback_summary.sh | 21 + scripts/sync_feishu_feedback_wrapper.sh | 10 +- skills/feishu-feedback-sync/SKILL.md | 302 +++++++++---- .../scripts/sync_feishu_feedback.py | 407 ++++++++++++++++-- skills/lark_wiki_operate_as_bot.vala/SKILL.md | 75 ---- 20 files changed, 1129 insertions(+), 258 deletions(-) create mode 100644 memory/2026-05-07-2032.md create mode 100644 memory/2026-05-07-2049.md create mode 100644 memory/2026-05-07-2051.md create mode 100644 memory/2026-05-07-feishu-group-test.md create mode 100644 memory/2026-05-07-greeting-hi.md create mode 100644 memory/2026-05-07.md create mode 100644 output/daily_feedback/飞书反馈_2026-05-06.xlsx create mode 100644 output/daily_feedback/飞书反馈_2026-05-07.xlsx create mode 100755 scripts/sync_feishu_feedback_dispatch_p0.sh create mode 100755 scripts/sync_feishu_feedback_realtime.sh create mode 100755 scripts/sync_feishu_feedback_summary.sh delete mode 100644 skills/lark_wiki_operate_as_bot.vala/SKILL.md diff --git a/.vala_skill_hashes b/.vala_skill_hashes index e7b2ae7..5b29689 100644 --- a/.vala_skill_hashes +++ b/.vala_skill_hashes @@ -14,4 +14,4 @@ user-feedback-collector c0320451bf7ea0ce3d8ceaa603ae0a7b55c373c048363a5142258a4c user-feedback-data-source a95eb9142f3019fd193c46f89147dc7e0bf01dfe250202565a86f8bc52f37b13 feishu-group-msg-sync 085f95a5b89fec3b6a627da25d66ffeeb0be430098387739a64f7903f0ee88d4 user-feedback-processor 61783a8e9f03a973c187b359a87749ad1993dc71f8364b0a853d8b3ff64c75e8 -feishu-feedback-sync 1fe2d72586096fc49cb39f5aa1d3f3e364664d8c7578a27ae49ef1be8f7a9896 +feishu-feedback-sync b046dd9f252ba6672acfac66aa732442cded924f0cd3c70e46cba5c6e300af6d diff --git a/memory/.dreams/events.jsonl b/memory/.dreams/events.jsonl index 758e45b..13cc865 100644 --- a/memory/.dreams/events.jsonl +++ b/memory/.dreams/events.jsonl @@ -2,3 +2,7 @@ {"type":"memory.recall.recorded","timestamp":"2026-04-30T06:52:35.560Z","query":"用户反馈数据源 飞书群 微信群 数据库表","resultCount":1,"results":[{"path":"memory/2026-04-18.md","startLine":1,"endLine":5,"score":1}]} {"type":"memory.recall.recorded","timestamp":"2026-04-30T08:11:39.116Z","query":"飞书群反馈表格 token E8vFsCmPBhT4SCtNmnJchqeJnJe 内容测试问题反馈","resultCount":1,"results":[{"path":"memory/2026-04-18.md","startLine":1,"endLine":5,"score":1}]} {"type":"memory.recall.recorded","timestamp":"2026-05-06T13:30:08.593Z","query":"内容测试反馈群 群聊规则 GroupSystemPrompt","resultCount":5,"results":[{"path":"memory/2026-04-30.md","startLine":198,"endLine":224,"score":1},{"path":"memory/2026-04-30.md","startLine":116,"endLine":142,"score":1},{"path":"memory/2026-04-30.md","startLine":134,"endLine":166,"score":1},{"path":"memory/2026-04-30.md","startLine":177,"endLine":205,"score":1},{"path":"memory/2026-04-18.md","startLine":1,"endLine":5,"score":1}]} +{"type":"memory.recall.recorded","timestamp":"2026-05-07T02:22:47.713Z","query":"用户反馈问题汇总 文档 写入逻辑 覆盖 overwrite","resultCount":6,"results":[{"path":"memory/2026-05-06.md","startLine":61,"endLine":86,"score":1},{"path":"memory/2026-04-30.md","startLine":116,"endLine":142,"score":1},{"path":"memory/2026-04-30.md","startLine":177,"endLine":205,"score":1},{"path":"memory/2026-04-30.md","startLine":198,"endLine":224,"score":1},{"path":"memory/2026-04-30.md","startLine":134,"endLine":166,"score":1},{"path":"memory/2026-04-30.md","startLine":73,"endLine":102,"score":1}]} +{"type":"memory.recall.recorded","timestamp":"2026-05-07T02:22:52.564Z","query":"用户反馈问题汇总 写入知识库 append overwrite 文档模式 feishu-feedback-sync","resultCount":6,"results":[{"path":"memory/2026-05-06.md","startLine":61,"endLine":86,"score":1},{"path":"memory/2026-04-30.md","startLine":116,"endLine":142,"score":1},{"path":"memory/2026-04-30.md","startLine":177,"endLine":205,"score":1},{"path":"memory/2026-04-30.md","startLine":198,"endLine":224,"score":1},{"path":"memory/2026-04-30.md","startLine":134,"endLine":166,"score":1},{"path":"memory/2026-04-30.md","startLine":73,"endLine":102,"score":1}]} +{"type":"memory.recall.recorded","timestamp":"2026-05-07T02:55:43.649Z","query":"问题分类 分类规则 版本更新 声音音频 UI显示 启动运行 语音识别 关卡内容 priority_classifier","resultCount":6,"results":[{"path":"memory/2026-05-06.md","startLine":61,"endLine":86,"score":1},{"path":"memory/2026-04-30.md","startLine":116,"endLine":142,"score":1},{"path":"memory/2026-04-30.md","startLine":177,"endLine":205,"score":1},{"path":"memory/2026-04-30.md","startLine":198,"endLine":224,"score":1},{"path":"memory/2026-04-30.md","startLine":134,"endLine":166,"score":1},{"path":"memory/2026-04-30.md","startLine":73,"endLine":102,"score":1}]} +{"type":"memory.recall.recorded","timestamp":"2026-05-07T03:19:39.321Z","query":"小葵小葵群 chat_id 发消息 bot","resultCount":1,"results":[{"path":"memory/2026-04-18.md","startLine":1,"endLine":5,"score":1}]} diff --git a/memory/.dreams/short-term-recall.json b/memory/.dreams/short-term-recall.json index b2a26d0..0863336 100644 --- a/memory/.dreams/short-term-recall.json +++ b/memory/.dreams/short-term-recall.json @@ -1,6 +1,6 @@ { "version": 1, - "updatedAt": "2026-05-06T13:30:08.593Z", + "updatedAt": "2026-05-07T03:19:39.321Z", "entries": { "memory:memory/2026-04-18.md:1:5": { "key": "memory:memory/2026-04-18.md:1:5", @@ -9,22 +9,24 @@ "endLine": 5, "source": "memory", "snippet": "# 2026-04-18 工作日志 ## 术语共识 [李若松确认] 术语「飞书反馈消息数据库」默认指代用户反馈收集技能中的飞书内部测试反馈MySQL数据表 `vala_test.lark_group_message`,存储「内容测试问题反馈」群(oc_fabff7672e62a9ced7b326ee4a286c26)的同步消息数据。", - "recallCount": 4, + "recallCount": 5, "dailyCount": 0, "groundedCount": 0, - "totalScore": 4, + "totalScore": 5, "maxScore": 1, "firstRecalledAt": "2026-04-30T03:47:21.989Z", - "lastRecalledAt": "2026-05-06T13:30:08.593Z", + "lastRecalledAt": "2026-05-07T03:19:39.321Z", "queryHashes": [ "353f9765c086", "a6b740c99377", "9625ed0029fd", - "f865295b9ac7" + "f865295b9ac7", + "42fe8210f22c" ], "recallDays": [ "2026-04-30", - "2026-05-06" + "2026-05-06", + "2026-05-07" ], "conceptTags": [ "vala-test.lark-group-message", @@ -44,18 +46,22 @@ "endLine": 224, "source": "memory", "snippet": "3. 问题描述留 `[AI归纳]` 占位符 - 运行时 AI(即助手本身)根据元数据 + 对话上下文,生成精炼的问题描述 #### AI 归纳的最终输出格式(固定模板) ```markdown ### 问题 N > **在{端}端{环节}内({课程}),{角色/组件}出现了{现象}** | 发言人 | 要点 | |--------|------| | ... | ... | **当前问题排查结论:** ... ``` #### 结论提取规则增强 - 解释性关键词:上云/预下载/加载/原因是/改为了/首次 → 标记为分析性发言 - 分析性发言 + 日志上传 → 输出「疑似{原因},已上传日志,排查中」 - 分析性发言 + 无日志 → 输出「{原因},待确认」 - 无分析 + 无日志 → 改为「暂未排查到问题」(刘新玉确认,比「暂未排查到根因」更准确) #### 4/28 最终归纳结果(AI 生成) 1. **NPC HUD 显示**:在移动端关卡内(11-2),NPC 头上的 HUD 偶尔变成一小条 → 暂未排查到问题 2. **iOS Loading 慢**:在 iOS 端关卡内(L1 3-2),Loading 耗时约 10 秒(正常 3 秒),导致组件数据丢失/无音频 → 疑似关卡内容上云加载导致,已上传日志,排查中 #### 结论提取的边界 - 刘新玉指出:\"暂未排查到问题\" vs \"暂未排查到根因\" → 前者更准确(问题被描述了但可能没被排查)", - "recallCount": 1, + "recallCount": 4, "dailyCount": 0, "groundedCount": 0, - "totalScore": 1, + "totalScore": 4, "maxScore": 1, "firstRecalledAt": "2026-05-06T13:30:08.593Z", - "lastRecalledAt": "2026-05-06T13:30:08.593Z", + "lastRecalledAt": "2026-05-07T02:55:43.649Z", "queryHashes": [ - "f865295b9ac7" + "f865295b9ac7", + "cd9c89262c30", + "ac7fd0b52a4e", + "49c0959dc960" ], "recallDays": [ - "2026-05-06" + "2026-05-06", + "2026-05-07" ], "conceptTags": [ "角色/组件", @@ -75,18 +81,22 @@ "endLine": 142, "source": "memory", "snippet": "问题:很多消息有关联但没有 `quote_message_id`(飞书 API 的 `root_id`/`parent_id` 未采集) **推断规则(按优先级)**: 1. **@提及匹配**:消息中 @了某人 → 关联到被@者最近一条消息 2. **同发送者聚类**:同一人在 2 分钟窗口内连续发多条 → 认为是对同一目标消息的回复 3. **最近不同发送者**:关联到最近一条不同发送者的消息(30 分钟内) 已测试效果:上午 NPC HUD 问题链成功串联,下午 iOS 问题链准确分组。部分跨话题误判仍需 AI 语义辅助(策略3,待后续评估)。 #### 触发方式 - 手动:「同步飞书反馈」「整理反馈对话链」 - 定时:每天 10:00 crontab 自动执行 ## 步骤4:问题归纳功能开发 [刘新玉] - 2026-04-30 18:38 完成 ### 步骤4 包含两部分 1. **问题描述**:在{端}{环节}内({课程}),{角色/组件}出现了{现象} 2. **当前问题排查结论**:从对话最后 1-2 条提取,匹配规则: - \"日志上传/排查/查\" → \"日志已上传,排查中\" - \"确认/确实\" → \"已确认,待修复\" - \"已修复/已解决\" → \"已修复\" - \"不是 bug/设计如此\" → \"非问题,设计如此\" - 无明确结论 → \"暂未排查到根因\" ### 归纳格式 ```markdown ### 问题 N", - "recallCount": 1, + "recallCount": 4, "dailyCount": 0, "groundedCount": 0, - "totalScore": 1, + "totalScore": 4, "maxScore": 1, "firstRecalledAt": "2026-05-06T13:30:08.593Z", - "lastRecalledAt": "2026-05-06T13:30:08.593Z", + "lastRecalledAt": "2026-05-07T02:55:43.649Z", "queryHashes": [ - "f865295b9ac7" + "f865295b9ac7", + "cd9c89262c30", + "ac7fd0b52a4e", + "49c0959dc960" ], "recallDays": [ - "2026-05-06" + "2026-05-06", + "2026-05-07" ], "conceptTags": [ "quote-message-id", @@ -106,18 +116,22 @@ "endLine": 166, "source": "memory", "snippet": "- \"日志上传/排查/查\" → \"日志已上传,排查中\" - \"确认/确实\" → \"已确认,待修复\" - \"已修复/已解决\" → \"已修复\" - \"不是 bug/设计如此\" → \"非问题,设计如此\" - 无明确结论 → \"暂未排查到根因\" ### 归纳格式 ```markdown ### 问题 N > **在{端}端{环节}内({课程}),{角色/组件}出现了{现象}** | 发言人 | 要点 | |--------|------| | 报告人 | 🚩 报告:... | | ... | ... | | 最终人 | ✅ 结论/待排查 | ``` ### 维度提取规则 | 维度 | 优先级/来源 | |------|------------| | 端 | iOS > iPad > pad端 > Android > 移动端 > PC(正则匹配,忽略大小写) | | 环节 | 关卡内/知识巩固/单元挑战/听力挑战/阅读挑战/口语挑战/写作挑战/单元强化/瓦拉学院/报告(从消息文本匹配) | | 课程 | 匹配数字编号(如 11-2、L1 3-2) | | 角色/组件 | NPC/HUD/音频/组件/数据/Loading/加载/日志(从消息文本匹配) | | 现象 | 从消息中提取要害描述,截断在 35 字符以内 | ### 现象提取逻辑 1. 优先从包含 \"Bug的表现是这样的:\"、\"问题是\"、\"发现\"、\"出现\" 等关键词的消息中截取描述句 2. 提取的句子去除 URL、图片标记、疑问句 3. 截断到 35 字符防止过长 ### Bug 修复记录", - "recallCount": 1, + "recallCount": 4, "dailyCount": 0, "groundedCount": 0, - "totalScore": 1, + "totalScore": 4, "maxScore": 1, "firstRecalledAt": "2026-05-06T13:30:08.593Z", - "lastRecalledAt": "2026-05-06T13:30:08.593Z", + "lastRecalledAt": "2026-05-07T02:55:43.649Z", "queryHashes": [ - "f865295b9ac7" + "f865295b9ac7", + "cd9c89262c30", + "ac7fd0b52a4e", + "49c0959dc960" ], "recallDays": [ - "2026-05-06" + "2026-05-06", + "2026-05-07" ], "conceptTags": [ "日志上传/排查/查", @@ -137,18 +151,22 @@ "endLine": 205, "source": "memory", "snippet": "- iOS 的两个相关话题(组件无音频 / Loading 慢)因无引用关系而分成两个簇(需策略3语义聚类解决) - 单消息簇被跳过(需至少 2 条消息才能形成问题) ### Skill 文件最终状态 - `skills/feishu-feedback-sync/SKILL.md`:已包含完整步骤1-4的文档 - `skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py`:已集成 `summarize_cluster()`、`extract_location_elements()`、`generate_summary()` 函数 - crontab 每日 10:00 执行(与步骤3一起) ### 步骤4 架构调整:AI 归纳取代规则生成 [刘新玉] - 2026-04-30 19:07 #### 问题 脚本规则匹配生成的问题描述质量差: - 组件匹配失败(NPC/HUD → \"未知组件\") - 现象摘取了完整原始消息(含 @、无关词) - 端识别不稳定 #### 决策 **脚本输出结构化元数据 + 对话表,AI 负责归纳描述。** - 脚本 `summarize_cluster` 改为输出: 1. 位置元数据(端/环节/课程/组件)— 由 `extract_location_elements` 提取 2. 发言人-要点表格(规则生成) 3. 问题描述留 `[AI归纳]` 占位符 - 运行时 AI(即助手本身)根据元数据 + 对话上下文,生成精炼的问题描述 #### AI 归纳的最终输出格式(固", - "recallCount": 1, + "recallCount": 4, "dailyCount": 0, "groundedCount": 0, - "totalScore": 1, + "totalScore": 4, "maxScore": 1, "firstRecalledAt": "2026-05-06T13:30:08.593Z", - "lastRecalledAt": "2026-05-06T13:30:08.593Z", + "lastRecalledAt": "2026-05-07T02:55:43.649Z", "queryHashes": [ - "f865295b9ac7" + "f865295b9ac7", + "cd9c89262c30", + "ac7fd0b52a4e", + "49c0959dc960" ], "recallDays": [ - "2026-05-06" + "2026-05-06", + "2026-05-07" ], "conceptTags": [ "已包含完整步骤1-4的文档", @@ -160,6 +178,72 @@ "发言人-要点表格", "ios" ] + }, + "memory:memory/2026-05-06.md:61:86": { + "key": "memory:memory/2026-05-06.md:61:86", + "path": "memory/2026-05-06.md", + "startLine": 61, + "endLine": 86, + "source": "memory", + "snippet": "- `generate_summary()` 调用 `compute_final_priority()` + `sort_by_priority()` 排序 - 新增 `--skip-priority` CLI 参数 - 修复了推断引用算法的孤立簇问题:在 sort_threads Union-Find 后增加合并单条孤立消息到有发送者重叠的大簇的逻辑 #### 3. 更新 SKILL.md 文档 - 增加了步骤5的完整文档说明 - 增加了优先级判定规则速查表 #### 4. 真实数据验证结果 - 2026-04-28 数据:2个问题 - P0:iOS端Loading超时致数据丢失/无音频(15条) - P1:移动端NPC HUD偶尔变成一小条(8条) #### 5. 刘新玉要求简化文档格式(~11:46) - 反馈文档太繁琐,只要在原有格式把\"问题 1\"改成\"P0-问题 1\" - 去掉了优先级分布汇总、额外信息行,只保留标题前缀 + 一行判定依据 - 最终格式:`### P0-问题 1` + `**优先级判定:** 规则...` - 知识库文档已更新为简洁版 #### 6. 修复推断引用算法 Bug - 策略2的 else 分支(同发送者无引用时往前找不同发送者)缺少时间限制 - 导致胡陈辰 20:45 的媒体消息被推断引用到徐思清 12:29(跨8小时) - 修复:加了 `GAP_THRESHOLD_MIN` 检查 #### 7. 文档写入方式改进 - 从 `insert_before` + `replace_range` 改为 `append` 模式", + "recallCount": 3, + "dailyCount": 0, + "groundedCount": 0, + "totalScore": 3, + "maxScore": 1, + "firstRecalledAt": "2026-05-07T02:22:47.713Z", + "lastRecalledAt": "2026-05-07T02:55:43.649Z", + "queryHashes": [ + "cd9c89262c30", + "ac7fd0b52a4e", + "49c0959dc960" + ], + "recallDays": [ + "2026-05-07" + ], + "conceptTags": [ + "generate-summary", + "compute-final-priority", + "sort-by-priority", + "skip-priority", + "sort-threads", + "union-find", + "skill.md", + "ios端loading超时致数据丢失/无音频" + ] + }, + "memory:memory/2026-04-30.md:73:102": { + "key": "memory:memory/2026-04-30.md:73:102", + "path": "memory/2026-04-30.md", + "startLine": 73, + "endLine": 102, + "source": "memory", + "snippet": "### 飞书问题反馈按引用关系重新排序 [刘新玉] 要求按问题完整解决过程排序——通过 `quote_message_id` 串联同一问题的讨论链。 #### 排序逻辑 1. 从数据库读取全部消息及引用关系 2. 构建引用图:每个消息的 `quote_message_id` 指向其父消息 3. 聚合问题链(cluster):同一引用链的消息归为一组,连续排列 4. 同 cluster 内按时间排序,子回复紧跟父消息 5. Cluster 间按最早时间排序 6. 无引用关系的独立消息按时间线补充 #### 处理过程 - 写入前先通过 `lark-cli sheets +write` 清空 sheet(`--raw-data=\"[]\"`) - 4/28 23条 → 生成完整引用链排序,写入 - 4/29 2条 → 无引用关系,直接写入 #### 4/28 问题链总结 | 问题 | 涉及人 | 消息数 | |------|--------|--------| | NPC HUD显示bug(仅移动端) | 徐思清→王胤鑫 | 3 | | 关卡出现规律 | 王胤鑫→庞鸿潇→梁晨 | 4 | | Playtesting数据记录 | 孙时敏 | 1 | | iOS组件无音频+Loading慢/数据丢失 | 胡陈辰→安君仪/毋益飞/王胤鑫 | 11 | | 网络问题(4/29) | Ann | 2 | ### 飞书群 4/25-4/27 数据查询结果 - 查询 MySQL `lark_group_message` 2026-04-25 ~ 2026-04-27 数据 - 结果:0 条,", + "recallCount": 3, + "dailyCount": 0, + "groundedCount": 0, + "totalScore": 3, + "maxScore": 1, + "firstRecalledAt": "2026-05-07T02:22:47.713Z", + "lastRecalledAt": "2026-05-07T02:55:43.649Z", + "queryHashes": [ + "cd9c89262c30", + "ac7fd0b52a4e", + "49c0959dc960" + ], + "recallDays": [ + "2026-05-07" + ], + "conceptTags": [ + "网络", + "quote-message-id", + "lark-cli", + "raw-data", + "4/28", + "4/29", + "loading慢/数据丢失", + "安君仪/毋益飞/王胤鑫" + ] } } } diff --git a/memory/2026-05-07-2032.md b/memory/2026-05-07-2032.md new file mode 100644 index 0000000..2081902 --- /dev/null +++ b/memory/2026-05-07-2032.md @@ -0,0 +1,12 @@ +# Session: 2026-05-07 20:32:56 GMT+8 + +- **Session Key**: agent:xiaokui:feishu:direct:ou_088ee79216826be4a24af44f7268f880 +- **Session ID**: 4d87bbc1-5d38-4c8c-bf62-555c32351d24 +- **Source**: feishu + +## Conversation Summary + +user: (continue) +assistant: 最新一期看完了。最近几期都挺有意思的,Gemini 3 的 agent 能力确实让人印象深刻,那个"自己开浏览器去购物"的演示挺震撼。Claude 被 Gemini 压得有点狠,不过 Opus 4.6 如果能按时出应该能扳回一局。你对哪块最感兴趣? +user: 你好 +assistant: 若松好。今天的工作日志里记录了不少刘新玉那边的变更——反馈文档结构调整、问题分类规则、消息分发到「小葵小葵」群都落地了。有什么需要处理的? diff --git a/memory/2026-05-07-2049.md b/memory/2026-05-07-2049.md new file mode 100644 index 0000000..2dea937 --- /dev/null +++ b/memory/2026-05-07-2049.md @@ -0,0 +1,44 @@ +# Session: 2026-05-07 20:49:03 GMT+8 + +- **Session Key**: agent:xiaokui:feishu:direct:ou_088ee79216826be4a24af44f7268f880 +- **Session ID**: 7ab6e9db-9453-4c3b-8667-87b587bfe6a3 +- **Source**: feishu + +## Conversation Summary + +assistant: 创建成功,让我验证一下文档是否在正确的位置。 +assistant: 已在「小葵」节点下成功创建子文档 **研发调试**。 + +- **父节点:** 小葵 (`Ih0VwOhd4io22Pkm3fGcTHb6nRg`) +- **新文档:** 研发调试 +- **链接:** https://makee-interactive.feishu.cn/wiki/RnUPwsSYKiQjYAkLQqyciI81nLc +- **空间:** `7612229802338045122` +user: 好的 现在在文档中 再追加一句话 "你好明天" +assistant: 已追加。文档链接:https://makee-interactive.feishu.cn/wiki/RnUPwsSYKiQjYAkLQqyciI81nLc +user: 好的 现在尝试 删除刚才追加的这句话 +assistant: 验证一下: +assistant: 已删除"你好明天",文档恢复为只保留标题和入口说明。链接不变:https://makee-interactive.feishu.cn/wiki/RnUPwsSYKiQjYAkLQqyciI81nLc +user: 好的 现在尝试删除这个文档 +assistant: Bot 应用缺少 `wiki:node:create` 权限,无法删除知识库节点。需要在飞书开发者后台给小葵应用开通此权限: + +**操作步骤:** +1. 打开:https://open.feishu.cn/app/cli_a9311791083adcc1/auth?q=wiki:node:create +2. 开通 `wiki:node:create` 权限 +3. 开通后告诉我,我继续执行删除 + +这是飞书知识库 API 的设计,删除节点需要 `wiki:node:create` 这个 scope。 +user: 已开通 再次尝试 +assistant: `obj_type=wiki` 成功了!删除是异步任务。让我验证一下结果。 +assistant: 已删除。「研发调试」文档已从知识库中移除,验证结果: + +- 节点查询返回 `not found` ✅ +- 父节点「小葵」下只剩原来的两个文档 ✅ + +关键发现:删除知识库节点时,`obj_type` 需传 `wiki`(而非 `docx`),这是一个异步任务,飞书返回了 `task_id` 确认已处理。 +user: 删除知识库节点时,obj_type 需传 wiki(而非 docx),这是一个异步任务 这个信息 是否已经记录在 /root/.openclaw/skills/lark_wiki_operate_as_bot 中? +assistant: 没有记录。该技能目前只覆盖了**读取/遍历**操作,未涉及创建和删除。我现在把删除操作的关键发现补充进去。 +assistant: 已补充。更新内容: + +- **适用场景** 增加了"删除知识库节点"和"创建知识库文档" +- **新增步骤5:删除知识库节点** — 记录了完整命令、`obj_type` 必须传 `wiki` 的关键发现、异步任务机制、以及验证方法 +- **权限表** 增加了 `wiki:node:create` 读写权限 diff --git a/memory/2026-05-07-2051.md b/memory/2026-05-07-2051.md new file mode 100644 index 0000000..6c359c2 --- /dev/null +++ b/memory/2026-05-07-2051.md @@ -0,0 +1,29 @@ +# Session: 2026-05-07 20:51:44 GMT+8 + +- **Session Key**: agent:xiaokui:feishu:direct:ou_088ee79216826be4a24af44f7268f880 +- **Session ID**: fbadd4ba-035c-4aaa-a673-e7ab49d2b411 +- **Source**: feishu + +## Conversation Summary + +user: 测试下 https://makee-interactive.feishu.cn/wiki/Ih0VwOhd4io22Pkm3fGcTHb6nRg?fromScene=spaceOverview 在这个节点下 新建一个 子文档 "研发调试" +assistant: 好的,我先获取该节点信息,然后在其下创建子文档"研发调试"。 +assistant: 需要先绑定配置。让我查一下绑定方式。 +assistant: 需要先绑定 OpenClaw 上下文。让我查看绑定方式后执行。 +assistant: 需要先绑定 lark-cli 到 OpenClaw 上下文。我取一下 app-id: +assistant: `lark-cli` 尚未绑定 OpenClaw 上下文,需要先做一次性绑定。绑定后所有 Wiki 操作将以 Bot 身份执行(`bot-only`,不触发用户授权),符合我们的安全规范。 + +确认绑定吗? +user: 好‘ +assistant: 绑定成功。现在获取目标节点信息,然后创建子文档。 +assistant: 节点信息已获取。在「小葵」目录下创建子文档「研发调试」: +assistant: ✅ 创建成功! + +**「研发调试」** 文档已创建在「小葵」节点下: + +| 项目 | 值 | +|------|-----| +| 文档标题 | 研发调试 | +| Wiki 链接 | https://makee-interactive.feishu.cn/wiki/KSUpwNEMKiyjbiklSsIc2YC2n2D | +| obj_token | `SrCTdxan4oBad4xoQiXcdIKHnNh` | +| 父节点 | 小葵 | diff --git a/memory/2026-05-07-feishu-group-test.md b/memory/2026-05-07-feishu-group-test.md new file mode 100644 index 0000000..ad1afe7 --- /dev/null +++ b/memory/2026-05-07-feishu-group-test.md @@ -0,0 +1,43 @@ +# Session: 2026-05-07 18:25:53 GMT+8 + +- **Session Key**: agent:xiaokui:feishu:direct:ou_088ee79216826be4a24af44f7268f880 +- **Session ID**: 76c1e3aa-0a11-45dc-8eaa-bf12193fa334 +- **Source**: feishu + +## Conversation Summary + +assistant: 我来查一下之前的对话记录,看看发生了什么。 +assistant: 让我进一步搜索关于"小葵小葵"群的具体对话记录,以及和刘新玉关于群的沟通。 +assistant: 没有找到关于"小葵小葵"这个具体群名的记录。让我搜索最近的日记忆文件和刘新玉相关的对话。 +assistant: 我没有找到和刘新玉关于"小葵小葵"这个群的直接对话。让我看看最近的记忆,以及查一下刘新玉最近和我的对话记录。 +assistant: 我在最近的记忆中没有发现和刘新玉关于"小葵小葵"群的对话记录。让我直接通过飞书 API 来确认当前 Bot 是否在"小葵小葵"群里。 +assistant: 这走的是用户身份授权。让我用 Bot 身份来查询。 +assistant: 好,让我用 Bot 身份来搜索"小葵小葵"群。 +assistant: 结果很清楚:**小葵Bot确实已经在"小葵小葵"群里**,`chat_id` 为 `oc_4171a2188f2554522a4309f2d7c27753`。 + +你说得对,这是我的问题。回顾一下: + +**事实上**"小葵小葵"群(`oc_4171a2188f2554522a4309f2d7c27753`)一直在小葵Bot的群列表中,Bot确实可以往这个群里发消息。 + +**我之前和刘新玉说的"Bot 不在群里"**,那指的是「内容测试问题反馈」群(`oc_fabff7672e62a9ced7b326ee4a286c26`)——当时(4月10日-20日期间)那个群 Bot 确实没加入,后来应该已经加上了。但我在表述时可能没有区分清楚,让刘新玉误以为我在所有群都不在,包括"小葵小葵"群。 + +这是我的疏忽——我应该明确说明"不在**特定群**"而不是笼统说"不在群里"。同一个 Bot 在不同群的加入状态是不同的,不能混为一谈。 + +已经验证确认:小葵Bot 在"小葵小葵"群(`oc_4171a2188f2554522a4309f2d7c27753`)中,完全可以往里面发消息。需要我现在往这个群发什么吗? +user: 好 现在发送一个 "测试信息" +assistant: 已发送。✅ 「测试信息」已成功发到"小葵小葵"群(`oc_4171a2188f2554522a4309f2d7c27753`),message_id: `om_x100b50f41db41c3cb2b8bb5619e89cd`。 +user: 记住 这个群,以后相关负责人需要你往这个群里发消息时,请准确执行。 +assistant: 已记录。「小葵小葵」群 `chat_id: oc_4171a2188f2554522a4309f2d7c27753`,以后相关负责人要求往这个群发消息时,直接执行即可。 +assistant: 🔧 Bot 权限申请 + +以下两个应用需要开通 wiki:node:create 权限: + +小研 (cli_a931175d41799cc7) +https://open.feishu.cn/app/cli_a931175d41799cc7/auth?q=wiki:node:create + +小葵 (cli_a9311791083adcc1) +https://open.feishu.cn/app/cli_a9311791083adcc1/auth?q=wiki:node:create + +原因:用户反馈问题汇总下出现重复子文档,需通过 API 删除多余节点。 +user: hi +assistant: hi 若松,有什么需要处理的? diff --git a/memory/2026-05-07-greeting-hi.md b/memory/2026-05-07-greeting-hi.md new file mode 100644 index 0000000..b197919 --- /dev/null +++ b/memory/2026-05-07-greeting-hi.md @@ -0,0 +1,18 @@ +# Session: 2026-05-07 19:38:30 GMT+8 + +- **Session Key**: agent:xiaokui:feishu:direct:ou_088ee79216826be4a24af44f7268f880 +- **Session ID**: 650e0d77-aad3-48d3-ad3b-1bef33d439a2 +- **Source**: feishu + +## Conversation Summary + +assistant: 下午好😊,我是你的数字员工小葵,有什么需要协助处理的工作可以随时告诉我。 +user: hi +assistant: 你好若松,下午好😊 有什么需要我处理的直接说~ +user: hi +assistant: 嗨,若松~ 在呢,随时吩咐 😄 +user: hi +user: [Thu 2026-05-07 19:28 GMT+8] [System] Your previous turn was interrupted by a gateway restart while OpenClaw was waiting on tool/model work. Continue from the existing transcript and finish the interrupted response. +assistant: 嗨若松,我在~ 有什么需要帮忙的吗? +user: hi +assistant: 若松,我在呢~ 看起来你连着发了几次消息但都被打断了,有什么需要直接说就好 😄 diff --git a/memory/2026-05-07.md b/memory/2026-05-07.md new file mode 100644 index 0000000..462e200 --- /dev/null +++ b/memory/2026-05-07.md @@ -0,0 +1,208 @@ + +## 用户反馈问题汇总文档结构调整 [刘新玉] - 2026-05-07 10:45 + +### 变更内容 +1. 「用户反馈问题汇总」文档改为按日期创建独立子文档,每天一个 +2. 子文档标题格式:`YYYY-MM-DD 问题反馈` +3. 父文档(RaL6whoYMijyYHkSlWrc7OLLnBy)改为索引说明页 +4. 子文档 obj_token: + - 2026-05-06: ISpQdgf6QoIKIyxdZjPcTAa4nEe + - 2026-04-28: UusFdRBEioSs4ox9JhPcXGfCnzf + +### 脚本修改 +- `sync_feishu_feedback.py` 中新增 `update_summary_doc_as_children()` 函数 +- 逻辑:先 `list_child_nodes()` 查已有子文档 → 存在则更新、不存在才创建 +- **核心规则:每天只新增一个对应日期的子文档,绝不重复创建** + +### 同步清理 +- 数据库中 sender_name='未知' 的3条无效记录已删除 +- 「内容测试问题反馈」电子表格中也清理了"未知"发送者的行 +- 该电子表格已从"飞书问题反馈-近3天"重命名为"内容测试问题反馈" + +### 飞书群信息 [李若松确认] - 2026-05-07 11:23 +- 「小葵小葵」群 chat_id: `oc_4171a2188f2554522a4309f2d7c27753`,小葵Bot已在该群中 +- 相关负责人需要往此群发消息时,直接用 Bot 身份向该 chat_id 发送 + +### 知识空间信息 +- space_id: 7612229802338045122 +- 父节点 node_token: RaL6whoYMijyYHkSlWrc7OLLnBy +- 父节点 obj_token: J8bKd4dbYoofZixxVsCc06bhnFc (docx) + +## 用户反馈问题汇总文档结构调整 [刘新玉] - 2026-05-07 10:45 + +### 变更内容 +1. 「用户反馈问题汇总」文档改为按日期创建独立子文档,每天一个 +2. 子文档标题格式:`YYYY-MM-DD 问题反馈` +3. 父文档(RaL6whoYMijyYHkSlWrc7OLLnBy)改为索引说明页 +4. 子文档 obj_token: + - 2026-05-06: ISpQdgf6QoIKIyxdZjPcTAa4nEe + - 2026-04-28: UusFdRBEioSs4ox9JhPcXGfCnzf + +### 脚本修改 +- `sync_feishu_feedback.py` 中新增 `update_summary_doc_as_children()` 函数 +- 逻辑:先 `list_child_nodes()` 查已有子文档 → 存在则更新、不存在才创建 +- **核心规则:每天只新增一个对应日期的子文档,绝不重复创建** + +### 同步清理 +- 数据库中 sender_name='未知' 的3条无效记录已删除 +- 「内容测试问题反馈」电子表格中也清理了"未知"发送者的行 +- 该电子表格已从"飞书问题反馈-近3天"重命名为"内容测试问题反馈" + +### 飞书群信息 [李若松确认] - 2026-05-07 11:23 +- 「小葵小葵」群 chat_id: `oc_4171a2188f2554522a4309f2d7c27753`,小葵Bot已在该群中 +- 相关负责人需要往此群发消息时,直接用 Bot 身份向该 chat_id 发送 + +### 知识空间信息 +- space_id: 7612229802338045122 +- 父节点 node_token: RaL6whoYMijyYHkSlWrc7OLLnBy +- 父节点 obj_token: J8bKd4dbYoofZixxVsCc06bhnFc (docx) + +--- + +## 今日问题归纳增加问题分类 [刘新玉] - 2026-05-07 10:55 + +### 新增步骤6:问题分类 +在优先级判定之后,对每个问题添加分类标签。输出格式: +``` +**⚠️ P0级核心问题(需优先处理)** +1. **Loading/加载类** + - 问题描述... +**⚡ P1级重要问题** +1. **关卡/内容类** + - 问题描述... +``` + +### 问题分类规则(按匹配优先级从上到下) +| 优先级 | 分类 | 匹配关键词 | +|--------|------|-----------| +| 1 | 启动/运行异常 | 闪退、崩溃、crash、进不去、卡死、黑屏、重启、服务器宕机、服务器挂了 | +| 2 | 版本/更新类 | 更新、升级、新版、版本、安装失败、OTA、热更新、无法更新、下载更新 | +| 3 | Loading/加载类 | 加载、loading、loading卡死、转星星、加载慢、加载超时、loading超时、一直加载 | +| 4 | 数据/进度类 | 数据丢失、数据异常、进度丢失、数据错误、分数异常、进度不对、记录丢失、数据对不上 | +| 5 | 声音/音频类 | 无声、声音、音频、没声音、音效 | +| 6 | 语音识别/判分类 | 判分、识别、语音识别、发音、评分、打分、AI判分 | +| 7 | 关卡/内容类 | 关卡、题目、答案、内容 | +| 8 | UI显示类 | 显示、界面、UI、HUD、动画、层级、图层、渲染 | +| 9 | 用户反馈问题 | 建议、反馈、体验、优化 | +| 10 | 其他问题 | (默认兜底) | + +### 脚本修改 +- `priority_classifier.py` 新增 `proble m_category(keyword)` 函数和 `CATEGORY_KEYWORDS` 规则 +- `sync_feishu_feedback.py` 中 `summarize_cluster()` 新增 `category` 字段 +- `generate_summary()` 输出格式改为按优先级+分类分组 + +--- + +## 新增步骤7:问题分发 [刘新玉] - 2026-05-07 11:09 + +### 需求 +将每日问题归纳同步到「小葵小葵」群,P0问题@相关负责人跟进。 + +### 分发规则 +1. 将"今日问题归纳"内容发送到指定群(格式:标题+归纳正文+文档链接) +2. P0问题 @相关负责人的 @列表(从 `summarize_cluster` 的 `operators` 字段提取发言人) + +### Bot身份问题 +- Bot应用名:**小研**(App ID: `cli_a931175d41799cc7`) +- Bot发消息需要已经加入目标群 +- 小葵Bot在「小葵小葵」群中发消息报 500 "chat does not exist" → 可能是不同应用 +- **待解决**:需要确认"小葵小葵"群里加的是哪个应用,或者把小研Bot加进去 + +### 脚本修改 +- `sync_feishu_feedback.py` 新增 `dispatch_to_group()` 函数 +- 新增 `--dispatch` 参数控制是否执行步骤7 +- 新增 `--dispatch-chat-id` 参数指定目标群(默认 oc_4171a2188f2554522a4309f2d7c27753) + +### 关键配置 +- 目标群 chat_id: `oc_4171a2188f2554522a4309f2d7c27753` +- 毋益飞 user_id: `eggbg21g` +- SKILL.md 已从"五步流程"更新为"七步流程" + +--- + +## 当日待跟进事项 +1. 「小葵小葵」群Bot发消息报错问题 → 需确认群内有哪个Bot应用,或引入小研Bot + +--- + +## 步骤7格式调整 [刘新玉] - 2026-05-07 11:40 + +### 最终消息格式(已确认并更新到脚本和SKILL.md) +``` +📋 2026-04-28 用户反馈问题归纳 + +**⚠️ P0级核心问题(需优先处理)** @毋益飞 +1. **Loading/加载类** + - 在iOS 端关卡内(3-2),Loading 耗时约 10 秒... + +**⚡ P1级重要问题** +1. **关卡/内容类** + - 【偶现】在移动端关卡内(11-2),NPC 头上的 HUD... + +📄 详细反馈文档:https://makee-interactive.feishu.cn/wiki/CQ0UwjRTZijvvEk6tSecEUTXnFg +``` +- @逻辑:P0标题行后面直接@发言人,@列表从 `summarize_cluster` 的 `operators` 提取 +- 非P0问题不@ + +### H5链接 +- 尝试生成公开H5链接失败,Bot无 `drive:permission` 权限 +- 当前使用飞书wiki链接,飞书App内可直接打开 +- 若需外部浏览器访问,需在知识空间设置"互联网上可查看" + +### 小葵Bot身份确认 +- xiaokui 凭证目录:`/root/.openclaw/credentials/xiaokui` +- xiaoyan 凭证目录:`/root/.openclaw/credentials/xiaoyan` +- 发「小葵小葵」群消息用 xiaokui 身份成功 + +--- + +## 当前定时任务清单 [刘新玉] - 2026-05-07 14:59 + +| 时间 | 任务 | +|------|------| +| 每天 02:00 | vala_skill_auto_push.sh(技能推送) | +| 每天 08:00-22:00 每2小时 | run_lark_group_sync.sh(反馈群消息同步到数据库) | +| 每天 08:10 | backup.sh(工作区Git备份) | +| 每分钟 | sync_wechat_feedback_minutely.py(微信用户反馈实时同步) | +| 每天 09:30 | daily_feedback_report.sh(每日反馈报告) | +| 每天 09:00 | run_export_lark_feedback.sh(飞书反馈数据导出) | +| **每天 10:00** | **sync_feishu_feedback_wrapper.sh(飞书问题反馈同步,含7步+分发到群)** | + +--- + +## 定时任务演化记录 [刘新玉] - 2026-05-07 15:03~15:56 + +### 已移除的任务 +- `sync_wechat_feedback_minutely.py`(微信用户反馈实时同步)— 已删除 +- `daily_feedback_report.sh`(每日反馈报告)— 已删除 + +### 最终定时任务清单(2026-05-07 15:56) + +| 频率 | 脚本 | 步骤 | 说明 | +|------|------|------|------| +| 每天 02:00 | `vala_skill_auto_push.sh` | — | 技能推送到 SkillHub | +| 每分钟 | `run_lark_group_sync.sh` | — | 群消息同步到数据库 | +| 每天 08:10 | `backup.sh` | — | Git 工作区备份 | +| 每分钟 | `run_export_lark_feedback.sh` | — | 当天数据实时导出 Excel | +| 每分钟 | `sync_feishu_feedback_realtime.sh` | 1-3 | 实时写入电子表格 | +| 每分钟 | `sync_feishu_feedback_summary.sh` | 4-6 | 归纳+分类 → 子文档 | +| 每分钟 | `sync_feishu_feedback_dispatch_p0.sh` | 7(仅P0) | P0问题实时分发到群 | +| 每天 10:00 | `sync_feishu_feedback_wrapper.sh` | 7(全部) | 全量分发到群 | + +### 完整数据流 +``` +群消息 → 每1分钟入MySQL → 每1分钟刷新表格 → 每1分钟归纳+分类 → P0实时发群 / 每天10:00全量发群 +``` + +### 关键技术细节 +- **拆分方式**:`sync_feishu_feedback.py` 新增 `--steps` 参数(如 `--steps 1-3`、`--steps 4-6`、`--steps 7`) +- **分发模式**:新增 `--dispatch-mode` 参数,`p0` 只发P0级,`all` 发全部 +- **电子表格**:`TVivwmzqXiW3YakDUzucFMRenvf`("内容测试问题反馈") +- **归纳子文档父节点**:`RaL6whoYMijyYHkSlWrc7OLLnBy`(space_id: 7612229802338045122) +- **分发目标群**:`oc_4171a2188f2554522a4309f2d7c27753`(「小葵小葵」群) +- **分发Bot**:xiaokui(`/root/.openclaw/credentials/xiaokui`) +- **新 wrapper 脚本**: + - `scripts/sync_feishu_feedback_realtime.sh`(步骤1-3) + - `scripts/sync_feishu_feedback_summary.sh`(步骤4-6) + - `scripts/sync_feishu_feedback_dispatch_p0.sh`(步骤7 P0) + - `scripts/sync_feishu_feedback_wrapper.sh`(步骤7 全量,每天10:00) diff --git a/output/daily_feedback/飞书反馈_2026-05-06.xlsx b/output/daily_feedback/飞书反馈_2026-05-06.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a80eded0383282a2988ce22b60f5ed0dc45e525a GIT binary patch literal 6918 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 "$LOG_FILE" +} + +log "=== P0 实时分发开始 ===" + +cd /root/.openclaw/workspace-xiaokui +python3 skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py --days 1 --steps 7 --dispatch-mode p0 >> "$LOG_FILE" 2>&1 + +log "=== P0 实时分发结束 ===" +exit 0 diff --git a/scripts/sync_feishu_feedback_realtime.sh b/scripts/sync_feishu_feedback_realtime.sh new file mode 100755 index 0000000..1272056 --- /dev/null +++ b/scripts/sync_feishu_feedback_realtime.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# 任务名称:飞书问题反馈实时同步(步骤1-3:写入电子表格) +# 执行时间:每 5 分钟 +# 归属 Agent:小葵 xiaokui + +set -e + +export PATH=/root/.nvm/versions/node/v24.14.0/bin:$PATH +LOG_FILE="/var/log/xiaokui_feedback_realtime.log" + +log() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" +} + +log "=== 实时同步开始 ===" + +cd /root/.openclaw/workspace-xiaokui +python3 skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py --days 3 --steps 1-3 >> "$LOG_FILE" 2>&1 + +log "=== 实时同步结束 ===" +exit 0 diff --git a/scripts/sync_feishu_feedback_summary.sh b/scripts/sync_feishu_feedback_summary.sh new file mode 100755 index 0000000..43f22d3 --- /dev/null +++ b/scripts/sync_feishu_feedback_summary.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# 任务名称:飞书问题反馈归纳与分类(步骤4-6) +# 执行时间:每分钟 +# 归属 Agent:小葵 xiaokui + +set -e + +export PATH=/root/.nvm/versions/node/v24.14.0/bin:$PATH +LOG_FILE="/var/log/xiaokui_feedback_summary.log" + +log() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" +} + +log "=== 归纳与分类开始 ===" + +cd /root/.openclaw/workspace-xiaokui +python3 skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py --days 1 --steps 4-6 --skip-dispatch >> "$LOG_FILE" 2>&1 + +log "=== 归纳与分类结束 ===" +exit 0 diff --git a/scripts/sync_feishu_feedback_wrapper.sh b/scripts/sync_feishu_feedback_wrapper.sh index 058e9f1..f6c3730 100755 --- a/scripts/sync_feishu_feedback_wrapper.sh +++ b/scripts/sync_feishu_feedback_wrapper.sh @@ -1,21 +1,21 @@ #!/bin/bash -# 任务名称:飞书问题反馈同步与对话链排序 +# 任务名称:飞书问题反馈每日全量分发(步骤7,全部问题) # 执行时间:每天 10:00 # 归属 Agent:小葵 xiaokui set -e export PATH=/root/.nvm/versions/node/v24.14.0/bin:$PATH -LOG_FILE="/var/log/xiaokui_feedback_sync.log" +LOG_FILE="/var/log/xiaokui_feedback_dispatch_daily.log" log() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" } -log "=== 飞书问题反馈同步开始 ===" +log "=== 每日全量分发开始 ===" cd /root/.openclaw/workspace-xiaokui -python3 skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py --days 3 >> "$LOG_FILE" 2>&1 +python3 skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py --days 1 --steps 7 --dispatch-mode all >> "$LOG_FILE" 2>&1 -log "=== 同步完成 ===" +log "=== 每日全量分发结束 ===" exit 0 diff --git a/skills/feishu-feedback-sync/SKILL.md b/skills/feishu-feedback-sync/SKILL.md index fcdb945..68a881d 100644 --- a/skills/feishu-feedback-sync/SKILL.md +++ b/skills/feishu-feedback-sync/SKILL.md @@ -1,39 +1,41 @@ --- name: feishu-feedback-sync -description: 同步飞书「内容测试问题反馈」群消息到知识库电子表格并执行对话链排序。用于:(1) 刘新玉说"同步飞书反馈"、"更新飞书问题反馈表格"、"整理反馈对话链"时触发;(2) 定时任务每日自动同步。数据源为 MySQL vala_test.lark_group_message,目标为知识库飞书问题反馈-近3天表格。含五步完整流程:数据同步 → 写入表格 → 对话链排序 → 问题归纳 → 优先级判定排序。 +description: 同步飞书「内容测试问题反馈」群消息到知识库电子表格并执行对话链排序。用于:(1) 刘新玉说"同步飞书反馈"、"更新飞书问题反馈表格"、"整理反馈对话链"时触发;(2) 定时任务每日自动同步。数据源为 MySQL vala_test.lark_group_message,目标为知识库内容测试问题反馈表格。含七步完整流程:数据同步 → 写入表格 → 对话链排序 → 问题归纳 → 优先级判定排序 → 问题分类 → 问题分发。 --- -# 飞书问题反馈同步(五步完整流程) +# 飞书问题反馈同步(七步完整流程) ## 概述 -从 MySQL `vala_test.lark_group_message` 读取飞书群消息,执行五步完整处理流程。 +从 MySQL `vala_test.lark_group_message` 读取飞书群消息,执行七步完整处理流程。 -### 五步流程总览 +### 七步流程总览 -| 步骤 | 名称 | 目标文档 | 产出 | +| 步骤 | 名称 | 目标文档/群 | 产出 | |------|------|---------|------| | 步骤 1 | 查询数据库 | — | 原始消息数据 | | 步骤 2 | 写入飞书表格 | `AHtnsehwShUVyDtjasSciIvgn7b` | 按天分 sheet 的原始数据 | | 步骤 3 | 反馈对话链排序 | `AHtnsehwShUVyDtjasSciIvgn7b` | 已排序的问题簇 | -| 步骤 4 | 问题归纳 | `RaL6whoYMijyYHkSlWrc7OLLnBy` | 结构化问题描述+对话表格+结论 | -| 步骤 5 | 优先级判定与排序 | `RaL6whoYMijyYHkSlWrc7OLLnBy` | 按 P0>P1>P2>P3 排序的问题列表 | +| 步骤 4 | 问题归纳 | `RaL6whoYMijyYHkSlWrc7OLLnBy`(子文档) | 结构化问题描述+对话表格+结论 | +| 步骤 5 | 优先级判定与排序 | `RaL6whoYMijyYHkSlWrc7OLLnBy`(子文档) | 按 P0>P1>P2>P3 排序的问题列表 | +| 步骤 6 | 问题分类 | `RaL6whoYMijyYHkSlWrc7OLLnBy`(子文档) | 按优先级+分类展示的问题列表 | +| 步骤 7 | 问题分发 | 「小葵小葵」群 `oc_4171a2188f2554522a4309f2d7c27753` | P0问题@通知到群 | ## 关键标识 | 项目 | 值 | |------|-----| -| 数据库 | MySQL `bj-cdb-8frbdwju.sql.tencentcdb.com:25413`,user `chatbot`,密码 `xhuBx7d@uT2gUVv`,database `vala_test` | +| 数据库 | MySQL `bj-cdb-8frbdwju.sql.tencentcdb.com:25413`,user `chatbot`,密码 `xhuBx7d@uT2gUVv`,database `vala_test` | | 源表 | `lark_group_message` | -| 目标表格 token | `AHtnsehwShUVyDtjasSciIvgn7b`(步骤1-3:原始数据整理) | -| 目标归纳文档 token | `RaL6whoYMijyYHkSlWrc7OLLnBy`(步骤4:问题归纳输出) | +| 目标表格 token | `AHtnsehwShUVyDtjasSciIvgn7b`(步骤1-3:原始数据整理) | +| 目标归纳文档 token | `RaL6whoYMijyYHkSlWrc7OLLnBy`(步骤4:问题归纳输出) | | 目标知识库节点 | `TVivwmzqXiW3YakDUzucFMRenvf` | | 知识空间 space_id | `7612229802338045122` | | 群 chat_id | `oc_fabff7672e62a9ced7b326ee4a286c26` | | Bot App ID | `cli_a9311791083adcc1` | | Bot App Secret | `ThhLL1I0F2AIKnSbpozKnhm40LTPfyap` | -## 表格字段(与数据库一致) +## 表格字段(与数据库一致) | 列 | 数据库字段 | |----|-----------| @@ -48,7 +50,7 @@ description: 同步飞书「内容测试问题反馈」群消息到知识库电 ## 执行流程 -### 步骤 1:查询数据库 +### 步骤 1:查询数据库 ```sql SELECT message_id, sender_name, msg_type, content, media_url, quote_message_id, @@ -58,23 +60,23 @@ WHERE msg_time >= '{date} 00:00:00' AND msg_time < '{next_date} 00:00:00' ORDER BY msg_time ASC ``` -默认同步最近 3 天的数据。如果表格已有当天 sheet,则追加新数据(去重写入,按 message_id 去重);如无则创建新 sheet。 +默认同步最近 3 天的数据。如果表格已有当天 sheet,则追加新数据(去重写入,按 message_id 去重);如无则创建新 sheet。 -### 步骤 2:写入飞书表格 +### 步骤 2:写入飞书表格 -使用 `lark-cli sheets +write`(Bot 身份)批量写入: -- 按天分 sheet(sheet 名为日期,如 `2026-04-28`) +使用 `lark-cli sheets +write`(Bot 身份)批量写入: +- 按天分 sheet(sheet 名为日期,如 `2026-04-28`) - 表头固定为 8 列 -- 每 sheet 最多一次写入(或分批,不超过 500 行/批) +- 每 sheet 最多一次写入(或分批,不超过 500 行/批) -**凭证环境:** +**凭证环境:** ```bash export PATH=/root/.nvm/versions/node/v24.14.0/bin:$PATH export LARKSUITE_CLI_CONFIG_DIR=/root/.openclaw/credentials/xiaokui export HOME=/root ``` -**写入命令格式:** +**写入命令格式:** ```bash lark-cli sheets +write \ --spreadsheet-token AHtnsehwShUVyDtjasSciIvgn7b \ @@ -83,51 +85,51 @@ lark-cli sheets +write \ --as bot ``` -### 步骤 3:反馈对话链排序 +### 步骤 3:反馈对话链排序 -对每个 sheet 中的数据执行引用链排序(详见下文排序逻辑),使每个问题的完整讨论过程在表格中连续呈现。 +对每个 sheet 中的数据执行引用链排序(详见下文排序逻辑),使每个问题的完整讨论过程在表格中连续呈现。 ## 反馈对话链排序逻辑 ### 两阶段排序 -#### 阶段 A:推断缺失引用(策略2) +#### 阶段 A:推断缺失引用(策略2) -由于飞书群消息同步时仅采集了 `quote_message_id`(显式引用),大量通过飞书「直接回复」功能产生的消息没有引用关系。策略2通过启发式规则补全: +由于飞书群消息同步时仅采集了 `quote_message_id`(显式引用),大量通过飞书「直接回复」功能产生的消息没有引用关系。策略2通过启发式规则补全: -1. **@提及匹配**(最高优先级):消息中 `@某人` → 关联到被@者最近一条消息 -2. **同发送者聚类**:同一发送者在 2 分钟窗口内连续发多条消息 → 认为是对同一目标的回复 -3. **最近不同发送者**(fallback):关联到最近一条不同发送者的消息(需在 30 分钟内,防止跨话题误关联) +1. **@提及匹配**(最高优先级):消息中 `@某人` → 关联到被@者最近一条消息 +2. **同发送者聚类**:同一发送者在 2 分钟窗口内连续发多条消息 → 认为是对同一目标的回复 +3. **最近不同发送者**(fallback):关联到最近一条不同发送者的消息(需在 30 分钟内,防止跨话题误关联) ``` -示例: +示例: 12:18 徐思清: NPC HUD 报告 (无引用) -12:19 王胤鑫: o3 分支? (无引用 → 推断关联12:18,因为12:18是最近不同发送者) -12:19 王胤鑫: 有固定关卡吗 (无引用 → 推断关联12:18,因为同发送者2分钟窗口内) +12:19 王胤鑫: o3 分支? (无引用 → 推断关联12:18,因为12:18是最近不同发送者) +12:19 王胤鑫: 有固定关卡吗 (无引用 → 推断关联12:18,因为同发送者2分钟窗口内) ``` -#### 阶段 B:引用链排序 +#### 阶段 B:引用链排序 -1. **Union-Find 聚类**:将有引用关系的消息(含推断引用)合并为同一「问题簇」 -2. **簇内递归展开**:从根消息开始,子回复紧跟父消息(子节点按时间排序) -3. **簇间排序**:按每个簇最早消息的时间排序 +1. **Union-Find 聚类**:将有引用关系的消息(含推断引用)合并为同一「问题簇」 +2. **簇内递归展开**:从根消息开始,子回复紧跟父消息(子节点按时间排序) +3. **簇间排序**:按每个簇最早消息的时间排序 ### 排序效果对比 -排序前(时间平铺): +排序前(时间平铺): ``` 12:18 徐思清: NPC HUD 报告 -12:19 王胤鑫: o3 分支? +12:19 王胤鑫: o3 分支? 12:19 王胤鑫: 有固定关卡出现吗 12:20 庞鸿潇: @王胤鑫 11-2 (引用"有固定关卡") 12:22 梁晨: @王胤鑫 没啥规律 (引用"有固定关卡") 12:28 王胤鑫: 是否只在移动端 (引用NPC HUD) ``` -排序后(问题链聚合): +排序后(问题链聚合): ``` 12:18 徐思清: NPC HUD 报告 - 12:19 王胤鑫: o3 分支? (推断引用12:18) + 12:19 王胤鑫: o3 分支? (推断引用12:18) 12:19 王胤鑫: 有固定关卡吗 (推断引用12:18) 12:20 庞鸿潇: 11-2 (引用"有固定关卡") 12:22 梁晨: 没啥规律 (引用"有固定关卡") @@ -135,18 +137,18 @@ lark-cli sheets +write \ 12:26 孙时敏: Playtesting有数据 (推断引用12:22) ``` -> 缩进行为对该根消息的直接或间接回复,形成完整的「问题 → 追问 → 诊断 → 结论」链路。 +> 缩进行为对该根消息的直接或间接回复,形成完整的「问题 → 追问 → 诊断 → 结论」链路。 -### 步骤 4:问题归纳 +### 步骤 4:问题归纳 -对每个问题簇生成结构化归纳,分两个部分: -1. **问题描述**:按固定格式描述问题 -2. **当前问题排查结论**:从对话最后几条消息中提取排查状态 +对每个问题簇生成结构化归纳,分两个部分: +1. **问题描述**:按固定格式描述问题 +2. **当前问题排查结论**:从对话最后几条消息中提取排查状态 #### 4.1 问题描述格式 ``` -> **在{端}端{环节}内({课程}),{角色/组件}出现了{现象}** +> **在{端}端{环节}内({课程}),{角色/组件}出现了{现象}** ``` #### 位置要素提取维度 @@ -161,82 +163,82 @@ lark-cli sheets +write \ #### 4.2 归纳输出格式 -每个问题簇输出一个结构化块(结论在表格上方,表格放原始对话): +每个问题簇输出一个结构化块(结论在表格上方,表格放原始对话): ```markdown ### 问题 N -**问题描述:** {AI 归纳后的精炼描述} +**问题描述:** {AI 归纳后的精炼描述} -**当前问题排查结论:** {结论} +**当前问题排查结论:** {结论} | 发言人 | 对话信息 | |--------|---------| -| 报告人 | 🚩 报告:原始对话内容 | -| ... | 原始对话内容(含媒体 URL) | +| 报告人 | 🚩 报告:原始对话内容 | +| ... | 原始对话内容(含媒体 URL) | | 最终人 | ✅ 原始对话内容 | ``` ``` #### 4.3 排查结论提取规则 -脚本从**全部消息**(而非仅最后 1-2 条)中提取结论。优先匹配以下模式: +脚本从**全部消息**(而非仅最后 1-2 条)中提取结论。优先匹配以下模式: | 优先级 | 匹配模式 | 结论 | |--------|---------|------| | 1 | 已修复/已解决/修好了 | 已修复 | -| 2 | 确认是bug/确实是问题 | 已确认,待修复 | -| 3 | 不是bug/设计如此/非问题 | 非问题,设计如此 | -| 4 | 有解释性分析 + 日志已上传 + 排查中 | 疑似{原因},已上传日志,排查中 | -| 5 | 日志已上传 + 排查中 | 已上传日志,排查中 | +| 2 | 确认是bug/确实是问题 | 已确认,待修复 | +| 3 | 不是bug/设计如此/非问题 | 非问题,设计如此 | +| 4 | 有解释性分析 + 日志已上传 + 排查中 | 疑似{原因},已上传日志,排查中 | +| 5 | 日志已上传 + 排查中 | 已上传日志,排查中 | | 6 | 暂未/没复现/未复现 | 暂未排查到问题 | -| 7 | 其他(无明确结论) | 暂未排查到问题 | +| 7 | 其他(无明确结论) | 暂未排查到问题 | -**解释性分析** 的来源:消息中匹配 "因为/原因是/应该是/改为了/导致/预下载/上云/首次/正常情况" 等关键词,提取对应发言人的判断句作为疑似原因。 +**解释性分析** 的来源:消息中匹配 "因为/原因是/应该是/改为了/导致/预下载/上云/首次/正常情况" 等关键词,提取对应发言人的判断句作为疑似原因。 -> 注意:脚本的规则匹配是辅助手段。运行时的 AI 可以根据完整对话上下文,修正或补全结论。 +> 注意:脚本的规则匹配是辅助手段。运行时的 AI 可以根据完整对话上下文,修正或补全结论。 #### 4.4 归纳示例 ```markdown ### 问题一 -> **在移动端关卡内(11-2 等),NPC 头上的 HUD 偶尔变成一小条** +> **在移动端关卡内(11-2 等),NPC 头上的 HUD 偶尔变成一小条** | 发言人 | 要点 | |--------|------| -| 徐思清 | 🚩 报告:最近经常出现,无明显规律 | -| 王胤鑫 | 追问:o3 分支?只在手机包出现,unity 里正常? | -| 庞鸿潇 | 确认:11-2 出现了 | -| 梁晨 | 补充:只在 APP 里发现过 | -| 徐思清 | ✅ 确认:确实只在移动端出现 | +| 徐思清 | 🚩 报告:最近经常出现,无明显规律 | +| 王胤鑫 | 追问:o3 分支?只在手机包出现,unity 里正常? | +| 庞鸿潇 | 确认:11-2 出现了 | +| 梁晨 | 补充:只在 APP 里发现过 | +| 徐思清 | ✅ 确认:确实只在移动端出现 | -**当前问题排查结论:** 暂未排查到问题 +**当前问题排查结论:** 暂未排查到问题 ``` ```markdown ### 问题二 -> **在 iOS 端关卡内(L1 3-2),组件数据丢失,无音频,Loading 耗时约 10 秒** +> **在 iOS 端关卡内(L1 3-2),组件数据丢失,无音频,Loading 耗时约 10 秒** | 发言人 | 要点 | |--------|------| -| 胡陈辰 | 🚩 报告:iOS 线上 L1 3-2 组件无音频 | -| 安君仪 | 询问:哪个组件? | -| 胡陈辰 | 复现:Loading 约 10 秒,组件数据丢失,杀 APP 重进恢复正常 | -| 毋益飞 | 解释:Loading 慢因内容上云加载;要求上传日志 | -| 胡陈辰 | ✅ 日志已上传,待明天排查 | +| 胡陈辰 | 🚩 报告:iOS 线上 L1 3-2 组件无音频 | +| 安君仪 | 询问:哪个组件? | +| 胡陈辰 | 复现:Loading 约 10 秒,组件数据丢失,杀 APP 重进恢复正常 | +| 毋益飞 | 解释:Loading 慢因内容上云加载;要求上传日志 | +| 胡陈辰 | ✅ 日志已上传,待明天排查 | -**当前问题排查结论:** 日志已上传,排查中 +**当前问题排查结论:** 日志已上传,排查中 ``` -### 步骤 5:优先级判定与排序 +### 步骤 5:优先级判定与排序 -基于《用户反馈问题优先级判断文档》,对步骤4归纳的问题自动评定优先级(P0-P3),并按优先级从高到低排序输出。 +基于《用户反馈问题优先级判断文档》,对步骤4归纳的问题自动评定优先级(P0-P3),并按优先级从高到低排序输出。 #### 5.1 判定维度 | 维度 | 说明 | 来源 | |------|------|------| -| 基础优先级 | 根据问题严重程度(崩溃/功能异常/体验瑕疵/细节优化) | 关键词规则匹配 | +| 基础优先级 | 根据问题严重程度(崩溃/功能异常/体验瑕疵/细节优化) | 关键词规则匹配 | | 出现概率 | 必现/高概率/中概率/低概率/偶现 | 消息内容关键词 | | 影响范围 | 全部用户/大部分用户/部分用户/极少数用户 | 消息内容关键词 | @@ -244,8 +246,8 @@ lark-cli sheets +write \ | 规则 | 条件 | 效果 | |------|------|------| -| 必现升级 | 出现概率为必现/高概率 | 原有优先级 +1 级(P1→P0, P2→P1) | -| 偶现降级 | 出现概率为低概率/偶现 | 原有优先级 -1 级(最多降一级,P1→P2) | +| 必现升级 | 出现概率为必现/高概率 | 原有优先级 +1 级(P1→P0, P2→P1) | +| 偶现降级 | 出现概率为低概率/偶现 | 原有优先级 -1 级(最多降一级,P1→P2) | | 范围升级 | 影响全部用户 | 原有优先级 +1 级 | | 范围降级 | 仅影响极少数用户 | 原有优先级 -1 级 | @@ -253,31 +255,31 @@ lark-cli sheets +write \ | 级别 | 定义 | 修复时限 | 典型关键词 | |------|------|----------|-----------| -| 🔴 **P0** | 孩子完全上不了课 / 核心功能崩溃 | 2小时内处理,当天解决 | 闪退、崩溃、进不去、数据丢失、服务器宕机 | +| 🔴 **P0** | 孩子完全上不了课 / 核心功能崩溃 | 2小时内处理,当天解决 | 闪退、崩溃、进不去、数据丢失、服务器宕机 | | 🟠 **P1** | 功能能用但不对劲 / 学习效果打折扣 | 3天内修复上线 | 音频异常、判分错误、进度保存失败、奖励未发放 | | 🟡 **P2** | 偶尔小毛病 / 界面瑕疵 / 刷新就好 | 当周修复 | UI显示异常、偶尔不显示、拖拽不流畅、刷新恢复 | | 🟢 **P3** | 几乎不影响使用 / 追求完美细节 | 不单独排期 | 分辨率略低、错别字、背景音不统一 | #### 5.4 输出格式 -在步骤4归纳结果的基础上,每个问题标题追加优先级标签,并新增优先级信息行: +在步骤4归纳结果的基础上,每个问题标题追加优先级标签,并新增优先级信息行: ```markdown ### 问题 1 🔴 P0 -**优先级:** 🔴 P0 | 基础优先级: P1(匹配P1规则:learning_func);出现频率: 必现;动态调整: 升级 1 级 -**修复时限:** 2小时内处理,当天解决 +**优先级:** 🔴 P0 | 基础优先级: P1(匹配P1规则:learning_func);出现频率: 必现;动态调整: 升级 1 级 +**修复时限:** 2小时内处理,当天解决 > **[AI归纳: 问题描述]** ... ``` -问题在文档中按 **P0 → P1 → P2 → P3** 排列,同优先级内按最早消息时间排序。 +问题在文档中按 **P0 → P1 → P2 → P3** 排列,同优先级内按最早消息时间排序。 -在归纳开头先输出优先级分布汇总: +在归纳开头先输出优先级分布汇总: ```markdown -**优先级分布:** P0:1个 | P1:3个 | P2:5个 | P3:2个 +**优先级分布:** P0:1个 | P1:3个 | P2:5个 | P3:2个 ``` #### 5.5 执行方式 @@ -286,23 +288,147 @@ lark-cli sheets +write \ # 默认启用步骤5 python3 sync_feishu_feedback.py --days 3 -# 跳过步骤5(仅执行步骤1-4) +# 跳过步骤5(仅执行步骤1-4) python3 sync_feishu_feedback.py --days 3 --skip-priority ``` -优先级判定函数位于独立模块 `scripts/priority_classifier.py`,可单独测试: +优先级判定函数位于独立模块 `scripts/priority_classifier.py`,可单独测试: ```bash python3 priority_classifier.py ``` -## 定时任务 +### 步骤 6:问题分类 -建议每日执行一次,在飞书群消息同步完毕后(`feishu-group-msg-sync` 之后)运行。 +对每个问题簇自动判定问题类别,在"今日问题归纳"部分按 **优先级 + 分类** 分组展示。 -### 创建定时任务(crontab) +#### 6.1 问题分类规则 + +按匹配优先级从上到下执行,命中第一个即返回: + +| 分类名称 | 匹配关键词场景 | +|---------|----------------| +| 启动/运行异常 | 闪退、崩溃、卡死、无法启动、进不去、服务器宕机 | +| 版本/更新类 | 更新失败、版本异常、升级后无法使用 | +| Loading/加载类 | 加载慢、加载超时、转星星、Loading 耗时异常 | +| 数据/进度类 | 数据丢失、进度不对、白学、保存失败 | +| 声音/音频类 | 无声、音频异常、播放问题、听不到 | +| 语音识别/判分类 | 判分不对、识别错误、评测异常 | +| 关卡/内容类 | 关卡异常、课程问题、层级问题、题目错误 | +| UI显示类 | 界面异常、HUD显示、动画、错位、截断 | +| 用户反馈问题 | 反馈、建议 | +| 其他问题 | 默认兆底 | + +#### 6.2 "今日问题归纳"输出格式 + +```markdown +## 今日问题归纳 + +**⚠️ P0级核心问题(需优先处理)** +1. **Loading/加载类** + - 在iOS 端关卡内(3-2),Loading 耗时约 10 秒... + +**⚡ P1级重要问题** +1. **关卡/内容类** + - 【偶现】在移动端关卡内,NPC 头上的 HUD 偶尔变成一小条 + +**📌 P2级一般问题** +1. **UI显示类** + - ... + +**📝 P3级低优先级** +1. **其他问题** + - ... +``` + +#### 6.3 优先级标题映射 + +| 优先级 | 标题格式 | +|--------|----------| +| P0 | ⚠️ P0级核心问题(需优先处理) | +| P1 | ⚡ P1级重要问题 | +| P2 | 📌 P2级一般问题 | +| P3 | 📝 P3级低优先级 | + +#### 6.4 分类函数 + +位于 `sync_feishu_feedback.py` 中的 `classify_problem(cluster_msgs)` 函数,基于 `CATEGORY_PATTERNS` 列表顺序匹配。 + +### 文档输出结构(子文档模式) + +「用户反馈问题汇总」采用子文档模式,每个日期独立一个子文档: + +``` +📂 用户反馈问题汇总 (node: RaL6whoYMijyYHkSlWrc7OLLnBy) + ├── 2026-05-06 问题反馈 + ├── 2026-04-28 问题反馈 + └── ...更多日期 +``` + +**规则:** +- 每天只新增一个对应日期的子文档,绝不重复创建 +- 子文档标题格式:`YYYY-MM-DD 问题反馈` +- 已有同日期子文档则覆盖更新内容 +- 实现函数:`update_summary_doc_as_children(day_sections)` +- 依赖:`list_child_nodes()` 查询已有子文档,`create_child_doc()` 创建新节点 + +### 步骤 7:问题分发 + +将每日问题归纳同步到「小葵小葵」问题反馈群(chat_id: `oc_4171a2188f2554522a4309f2d7c27753`),P0问题 @相关负责人及时跟进。 + +#### 7.1 分发规则 + +| 规则 | 说明 | +|------|------| +| 内容 | 仅发送"今日问题归纳"部分(不含"今日问题拆解"详细表格) | +| 格式 | 富文本 post 消息,含标题 + 归纳正文 + 文档链接 | +| P0 @通知 | 自动 @配置列表中的负责人(当前:毋益飞 eggbg21g) | +| 身份 | 使用小葵Bot(凭证目录 `DIS PATCH_CRED_DIR`)直接调用 API | +| 频率 | 每天每条汇总发送一次 | + +#### 7.2 消息格式示例 + +``` +📋 2026-04-28 用户反馈问题归纳 + +⚠️ P0级核心问题(需优先处理) @毋益飞 +1. Loading/加载类 + - 在iOS 端关卡内(3-2),Loading 耗时约 10 秒... + +⚡ P1级重要问题 +1. 关卡/内容类 + - 【偶现】在移动端关卡内(11-2),NPC 头上的 HUD 偶尔变成一小条 + +📄 详细文档:2026-04-28 问题反馈 [链接] +``` + +#### 7.3 配置 + +位于 `sync_feishu_feedback.py`: + +| 配置项 | 值 | 说明 | +|--------|-----|------| +| DISPATCH_CHAT_ID | `oc_4171a2188f2554522a4309f2d7c27753` | 目标群 | +| P0_NOTIFY_USERS | `["eggbg21g"]` | P0问题 @列表 | +| DISPATCH_CRED_DIR | `/root/.openclaw/credentials/xiaokui` | Bot身份凭证 | + +#### 7.4 执行方式 ```bash -# 每天 10:00 执行(确保消息已同步入库) +# 默认执行步骤7 +python3 sync_feishu_feedback.py --days 3 + +# 跳过步骤7 +python3 sync_feishu_feedback.py --days 3 --skip-dispatch +``` + +## 定时任务 + +建议每日执行一次,在飞书群消息同步完毕后(`feishu-group-msg-sync` 之后)运行。 + +### 创建定时任务(crontab) + +```bash +# 每天 10:00 执行(确保消息已同步入库) 0 10 * * * /bin/bash /root/.openclaw/workspace-xiaokui/scripts/sync_feishu_feedback_wrapper.sh >> /var/log/xiaokui_feedback_sync.log 2>&1 ``` diff --git a/skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py b/skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py index e86981a..46e7470 100755 --- a/skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py +++ b/skills/feishu-feedback-sync/scripts/sync_feishu_feedback.py @@ -531,6 +531,38 @@ def generate_problem_description(cluster_msgs, location, root_text): return result +# ============================================================ +# 问题分类(用于“今日问题归纳”部分的分类展示) +# ============================================================ + +CATEGORY_PATTERNS = [ + ("启动/运行异常", r'闪退|崩溃|卡死|无法启动|打不开|进不去|登不上|无法.*进入|无法.*连接|服务器.*挂|宕机'), + ("版本/更新类", r'(更新|版本|升级).*(失败|无法|出问题|异常|后.*(无法|不能|收不到))'), + ("Loading/加载类", r'loading|加载.*(慢|长|卡|超时|失败)|进入.*慢|转星星'), + ("数据/进度类", r'数据.*(丢失|没记录|白学|全没|消失|不对|错误)|进度.*(显示|记录|保存).*(错|不对|失败)'), + ("声音/音频类", r'音频|声音|播放|没声音|无声|听不到|没音|没声|无音频|音量'), + ("语音识别/判分类", r'判分|打分|识别|评测|跟读.*(异常|不对|错误)|明明.*对.*系统.*(说|判断).*不对'), + ("关卡/内容类", r'关卡|课程|单元|知识巩固|题目|选项|内容.*(异常|有问题|错误)|层级|墙.*层级'), + ("UI显示类", r'界面|UI|显示|排版|文案|图标|动画|动效|截断|错位|HUD|不显示'), + ("用户反馈问题", r'反馈|建议'), + ("其他问题", r'.*'), # 默认分类 +] + + +def classify_problem(cluster_msgs) -> str: + """ + 根据问题簇的消息内容判定问题分类。 + 返回分类名称字符串。 + """ + all_text = " ".join(str(m[3]) or "" for m in cluster_msgs) + all_text = re.sub(r'\[Image:[^\]]+\]', '', all_text) + + for category_name, pattern in CATEGORY_PATTERNS: + if re.search(pattern, all_text, re.IGNORECASE): + return category_name + return "其他问题" + + def summarize_cluster(cluster_msgs, idx, priority_info=None): """ 生成单个问题簇的结构化归纳。 @@ -707,23 +739,39 @@ def generate_summary(clusters, cluster_order, skip_priority=False): # 按优先级排序:P0 > P1 > P2 > P3,同优先级按时间 valid_clusters = sort_by_priority(valid_clusters) - # 生成层汇总索引 + # 生成层汇总索引(按优先级 + 分类) grouped = defaultdict(list) for vc in valid_clusters: p = vc.get("priority_info", {}).get("priority", "P2") if not skip_priority else "P2" + vc["category"] = classify_problem(vc["msgs"]) grouped[p].append(vc) + priority_headers = { + "P0": "⚠️ P0级核心问题(需优先处理)", + "P1": "⚡ P1级重要问题", + "P2": "📌 P2级一般问题", + "P3": "📝 P3级低优先级", + } + for p_level in ["P0", "P1", "P2", "P3"]: items = grouped.get(p_level, []) if not items: continue - lines.append(f"**【{p_level}问题】**") - item_idx = 0 + lines.append(f"**{priority_headers[p_level]}**") + + # 按分类分组 + by_category = defaultdict(list) for vc in items: - item_idx += 1 - desc = generate_problem_description(vc["msgs"], - extract_location_elements(vc["msgs"]), "") - lines.append(f"{item_idx},{desc}") + by_category[vc["category"]].append(vc) + + cat_idx = 0 + for cat_name, cat_items in by_category.items(): + cat_idx += 1 + lines.append(f"{cat_idx}. **{cat_name}**") + for vc in cat_items: + desc = generate_problem_description(vc["msgs"], + extract_location_elements(vc["msgs"]), "") + lines.append(f" - {desc}") lines.append("") # 问题拆解 @@ -740,31 +788,129 @@ def generate_summary(clusters, cluster_order, skip_priority=False): # === 步骤5写入目标文档配置 === -SUMMARY_DOC_TOKEN = "J8bKd4dbYoofZixxVsCc06bhnFc" # 用户反馈问题汇总.docx obj_token +SUMMARY_PARENT_NODE = "RaL6whoYMijyYHkSlWrc7OLLnBy" # 用户反馈问题汇总 wiki node_token +SUMMARY_SPACE_ID = "7612229802338045122" # 知识空间 ID -def update_summary_doc(markdown_content, day_label, mode="overwrite"): + +def get_tenant_token(cred_dir=None): + """获取 Bot 的 tenant_access_token。cred_dir 可选指定凭证目录。""" + import urllib.request + if cred_dir is None: + cred_dir = os.environ.get("LARKSUITE_CLI_CONFIG_DIR", "/root/.openclaw/credentials/xiaoyan") + config = json.load(open(os.path.join(cred_dir, "config.json"))) + app_id = config["apps"][0]["appId"] + app_secret = config["apps"][0]["appSecret"] + + req = urllib.request.Request( + "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal", + data=json.dumps({"app_id": app_id, "app_secret": app_secret}).encode(), + headers={"Content-Type": "application/json"}, + method="POST" + ) + resp = urllib.request.urlopen(req, timeout=10) + return json.loads(resp.read())["tenant_access_token"] + + +def list_child_nodes(): + """列出「用户反馈问题汇总」下的所有子节点,返回 {title: {node_token, obj_token}}。同名节点取 obj_edit_time 最新的。""" + import urllib.request + token = get_tenant_token() + url = f"https://open.feishu.cn/open-apis/wiki/v2/spaces/{SUMMARY_SPACE_ID}/nodes?parent_node_token={SUMMARY_PARENT_NODE}" + req = urllib.request.Request(url, headers={"Authorization": f"Bearer {token}"}) + resp = urllib.request.urlopen(req, timeout=10) + data = json.loads(resp.read()) + + nodes = {} + for item in data.get("data", {}).get("items", []): + title = item["title"] + edit_time = item.get("obj_edit_time", "0") + # 同名取更新时间最近的 + if title not in nodes or edit_time > nodes[title].get("_edit_time", "0"): + nodes[title] = { + "node_token": item["node_token"], + "obj_token": item["obj_token"], + "_edit_time": edit_time + } + return nodes + + +def create_child_doc(title): + """在「用户反馈问题汇总」下创建子文档,返回 obj_token""" + import urllib.request + token = get_tenant_token() + url = f"https://open.feishu.cn/open-apis/wiki/v2/spaces/{SUMMARY_SPACE_ID}/nodes" + body = json.dumps({ + "obj_type": "docx", + "node_type": "origin", + "parent_node_token": SUMMARY_PARENT_NODE, + "title": title + }).encode() + req = urllib.request.Request(url, data=body, headers={ + "Authorization": f"Bearer {token}", + "Content-Type": "application/json" + }, method="POST") + resp = urllib.request.urlopen(req, timeout=10) + data = json.loads(resp.read()) + if data.get("code") == 0: + return data["data"]["node"]["obj_token"] + print(f" ⚠️ 创建子文档失败: {data}") + return None + + +def update_summary_doc_as_children(day_sections): """ - 将当日归纳结果写入「用户反馈问题汇总」文档。 - mode: 'overwrite'(覆盖,默认,第一天使用) / 'append'(追加,多天时后续天使用) + 将各日期的归纳结果写入「用户反馈问题汇总」的子文档中。 + day_sections: dict, key=日期字符串(如'2026-05-06'), value=该日的归纳 markdown + + 逻辑: + 1. 列出已有子文档 + 2. 对每个日期:已有则覆盖更新,无则创建新子文档 + 3. 写入内容 """ env = get_env() + existing_nodes = list_child_nodes() - full_md = f"## {day_label} 飞书问题反馈归纳\n\n" + markdown_content + for day in sorted(day_sections.keys(), reverse=True): + title = f"{day} 问题反馈" + content = day_sections[day] + + # 双重检查:重新列一次子节点,避免并发创建重复 + existing_nodes = list_child_nodes() + if title in existing_nodes: + obj_token = existing_nodes[title]["obj_token"] + print(f" 📝 更新子文档: {title}") + else: + obj_token = create_child_doc(title) + if not obj_token: + # 创建失败可能是并发冲突,再查一次 + existing_nodes = list_child_nodes() + if title in existing_nodes: + obj_token = existing_nodes[title]["obj_token"] + print(f" 📝 已存在,使用已有子文档: {title}") + else: + continue + else: + print(f" ➕ 创建子文档: {title}") + + # 写入内容 + result = subprocess.run( + [CLI, "docs", "+update", "--doc", obj_token, "--as", "bot", + "--mode", "overwrite", + "--markdown", content], + env=env, capture_output=True, text=True, timeout=15 + ) + + try: + d = json.loads(result.stdout) + if d.get("ok"): + print(f" ✅ {title} 写入成功") + else: + print(f" ⚠️ {title} 写入失败: {result.stdout[:100]}") + except Exception: + print(f" ⚠️ {title} 写入异常: {result.stderr[:100]}") - result = subprocess.run( - [CLI, "docs", "+update", "--doc", SUMMARY_DOC_TOKEN, "--as", "bot", - "--mode", mode, - "--markdown", full_md], - env=env, capture_output=True, text=True, timeout=15 - ) - - d = json.loads(result.stdout) - if d.get("ok"): - print(f" ✅ 归纳结果已{'覆盖写入' if mode == 'overwrite' else '追加'}到「用户反馈问题汇总」文档") - return True - else: - print(f" ⚠️ 文档写入失败: {result.stdout[:200]}") - return False + print(f" 📂 共处理 {len(day_sections)} 个日期的子文档") + return True def main(): @@ -772,6 +918,9 @@ def main(): parser.add_argument("--days", type=int, default=3, help="同步最近 N 天(默认 3)") parser.add_argument("--dry-run", action="store_true", help="仅预览不写入") parser.add_argument("--skip-priority", action="store_true", help="跳过步骤5优先级判定") + parser.add_argument("--skip-dispatch", action="store_true", help="跳过步骤7问题分发") + parser.add_argument("--dispatch-mode", type=str, default="all", choices=["all", "p0"], help="分发模式:all=发全部, p0=仅发P0级问题(默认 all)") + parser.add_argument("--steps", type=str, default="1-7", help="执行步骤范围,如 '1-3'(仅写入表格)或 '4-7'(归纳+分类+分发)") args = parser.parse_args() end_date = date.today() @@ -806,7 +955,7 @@ def main(): print(f"📑 现有 sheet:{list(existing.keys())}") total_written = 0 - first_day_written = False + day_summaries = {} # 收集所有天的归纳结果 for day in sorted(groups.keys()): msgs = groups[day] @@ -823,26 +972,26 @@ def main(): sorted_msgs, clusters, cluster_order = sort_threads(msgs) print(f" 排序完成:{len(sorted_msgs)} 条") - # 步骤 4:问题归纳 - # 步骤 5:优先级判定(默认启用,--skip-priority 可跳过) - summary, has_content = generate_summary(clusters, cluster_order, skip_priority=args.skip_priority) - if has_content: - priority_count = summary.count('优先级:') if not args.skip_priority else 0 - print(f" 归纳完成:{summary.count('### 问题')} 个问题") - if not args.skip_priority: - print(f" 步骤5 优先级判定完成:{priority_count} 个问题已评定优先级并排序") - print(f" (归纳内容见下方)") - print(summary) - - # 写入「用户反馈问题汇总」文档 - # 第一个有内容的天用 overwrite,后续用 append - doc_mode = "overwrite" if not first_day_written else "append" - update_summary_doc(summary, day, mode=doc_mode) - first_day_written = True - else: - print(" ⚠️ 无有效问题簇可归纳") + # 根据 --steps 参数决定是否执行步骤4-6 + run_steps = args.steps + do_summary = "4" in run_steps or "5" in run_steps or "6" in run_steps or "7" in run_steps + + if do_summary: + # 步骤 4:问题归纳 + # 步骤 5:优先级判定(默认启用,--skip-priority 可跳过) + summary, has_content = generate_summary(clusters, cluster_order, skip_priority=args.skip_priority) + if has_content: + priority_count = summary.count('优先级:') if not args.skip_priority else 0 + print(f" 归纳完成:{summary.count('### 问题')} 个问题") + if not args.skip_priority: + print(f" 步骤5 优先级判定完成:{priority_count} 个问题已评定优先级并排序") + print(f" (归纳内容见下方)") + print(summary) + day_summaries[day] = summary + else: + print(" ⚠️ 无有效问题簇可归纳") - # 写入 + # 写入表格(步骤2) success = write_sheet(sheet_id, sorted_msgs) if success: total_written += len(sorted_msgs) @@ -850,8 +999,174 @@ def main(): else: print(f" ❌ 写入失败") + # 统一写入「用户反馈问题汇总」文档(增量更新,保留已有日期内容)— 步骤4-6 + if day_summaries and do_summary: + update_summary_doc_as_children(day_summaries) + + # 步骤7:问题分发(发送到群聊 + @相关人) + if do_summary and not args.skip_dispatch: + dispatch_mode = args.dispatch_mode + print(f"\n📨 步骤7:问题分发(模式: {dispatch_mode})...") + for day, info in day_summaries.items(): + # 检查当天归纳中是否有 P0 问题 + has_p0 = "⚠️ P0级" in info["summary"] + if dispatch_mode == "p0" and not has_p0: + print(f" [{day}] 无P0问题,跳过分发") + continue + dispatch_summary_to_chat(day, info["summary"], p0_only=(dispatch_mode == "p0")) + print(f"\n🎉 同步完成,总计写入 {total_written} 条") if __name__ == "__main__": main() + + +# ============================================================ +# 步骤 7:问题分发(发送到群聊 + @相关人) +# ============================================================ + +# 分发目标群配置 +DISPATCH_CHAT_ID = "oc_4171a2188f2554522a4309f2d7c27753" # 「小葵小葵」问题反馈群 + +# P0问题默认@的人(user_id) +P0_NOTIFY_USERS = [ + "eggbg21g", # 毋益飞 +] + +# Bot身份: 使用 xiaokui(小葵)的凭证发消息 +DISPATCH_CRED_DIR = "/root/.openclaw/credentials/xiaokui" + + +def dispatch_summary_to_chat(day_label, summary_text, p0_only=False): + """ + 将「今日问题归纳」部分发送到指定群聊。 + P0问题会 @指定人员。 + + 参数: + day_label: 日期标签,如 '2026-04-28' + summary_text: 今日问题归纳的 markdown 文本 + p0_only: True=仅发送 P0 部分,False=发送全部 + """ + if not DISPATCH_CHAT_ID: + print(" ⚠️ 未配置分发群 chat_id,跳过步骤7") + return False + + # 构建消息内容 + # 提取「今日问题归纳」部分(到「今日问题拆解」之前) + lines = summary_text.split("\n") + 归纳_lines = [] + in_归纳 = False + for line in lines: + if "今日问题归纳" in line: + in_归纳 = True + continue + if "今日问题拆解" in line: + break + if in_归纳: + 归纳_lines.append(line) + + 归纳_content = "\n".join(归纳_lines).strip() + if not 归纳_content: + print(" ⚠️ 无归纳内容可分发") + return False + + # 检查是否有 P0 问题 + has_p0 = "⚠️ P0级" in 归纳_content + + # 如果 p0_only 模式,裁剪掉非 P0 部分 + if p0_only and has_p0: + # 保留 P0 部分,去掉后面的 P1/P2/P3 + # 找到下一个优先级标题的位置 + for marker in ["⚡ P1级", "📌 P2级", "📝 P3级"]: + idx = 归纳_content.find(marker) + if idx > 0: + 归纳_content = 归纳_content[:idx].strip() + break + + # 构建富文本消息(post 格式) + # P0 @跟在标题行后面,不放单独段落 + title = f"📋 {day_label} 用户反馈问题归纳" + + # 将归纳内容中的 P0 标题行注入 @人 + # 格式:⚠️ P0级核心问题(需优先处理) → ⚠️ P0级核心问题(需优先处理) @某某 + if has_p0 and P0_NOTIFY_USERS: + at_str = "".join(f"" for uid in P0_NOTIFY_USERS) + # 在 P0 标题行后面插入 @ + 归纳_content = re.sub( + r'(⚠️ P0级核心问题(需优先处理))', + rf'\1 {at_str}', + 归纳_content + ) + + # 飞书 post 消息不支持 HTML 标签的 at,需要用富文本 tag + # 所以改为:把归纳内容按 P0/P1/P2/P3 段落拆分,P0 段落后追加 at tag + content_parts = [] + + if has_p0 and P0_NOTIFY_USERS: + # 找到 P0 标题行并插入 @ + p0_header = "⚠️ P0级核心问题(需优先处理)" + if p0_header in 归纳_content: + parts_before = 归纳_content.split(p0_header, 1) + before_p0 = parts_before[0].strip() + after_p0 = parts_before[1].lstrip() + + if before_p0: + content_parts.append([{"tag": "text", "text": before_p0 + "\n"}]) + + # P0 标题行 + @ + 后续内容 + p0_line = [{"tag": "text", "text": p0_header + " "}] + for uid in P0_NOTIFY_USERS: + p0_line.append({"tag": "at", "user_id": uid}) + p0_line.append({"tag": "text", "text": " "}) + p0_line.append({"tag": "text", "text": "\n" + after_p0}) + content_parts.append(p0_line) + else: + content_parts.append([{"tag": "text", "text": 归纳_content}]) + else: + content_parts.append([{"tag": "text", "text": 归纳_content}]) + + # 追加文档链接 + content_parts.append([ + {"tag": "text", "text": "\n📄 详细文档:"}, + {"tag": "a", "text": f"{day_label} 问题反馈", "href": f"https://makee-interactive.feishu.cn/wiki/RaL6whoYMijyYHkSlWrc7OLLnBy"} + ]) + + post_content = json.dumps({ + "zh_cn": { + "title": title, + "content": content_parts + } + }, ensure_ascii=False) + + # 使用小葵(xiaokui)Bot 身份直接调用飞书 API 发送 + try: + import urllib.request + token = get_tenant_token(cred_dir=DISPATCH_CRED_DIR) + + body = json.dumps({ + "receive_id": DISPATCH_CHAT_ID, + "msg_type": "post", + "content": post_content + }, ensure_ascii=False).encode() + + req = urllib.request.Request( + "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id", + data=body, + headers={ + "Authorization": f"Bearer {token}", + "Content-Type": "application/json" + }, + method="POST" + ) + resp = urllib.request.urlopen(req, timeout=10) + d = json.loads(resp.read()) + if d.get("code") == 0: + print(f" ✅ 问题归纳已分发到群聊" + (" (含P0 @通知)" if has_p0 else "")) + return True + else: + print(f" ⚠️ 分发失败: {d.get('msg', '')[:100]}") + except Exception as e: + print(f" ⚠️ 分发异常: {e}") + + return False diff --git a/skills/lark_wiki_operate_as_bot.vala/SKILL.md b/skills/lark_wiki_operate_as_bot.vala/SKILL.md deleted file mode 100644 index 679ea45..0000000 --- a/skills/lark_wiki_operate_as_bot.vala/SKILL.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -name: lark_wiki_operate_as_bot -version: 1.0.0 -description: "飞书知识库Bot身份操作专用技能,统一使用Bot身份遍历目录、读取知识库文档内容,禁止触发用户身份授权" -metadata: - requires: - permissions: ["wiki:node:retrieve", "docx:document:readonly"] ---- - -# lark_wiki_operate_as_bot 技能规范 - -## 核心规则(强制执行) -1. **身份限制**:所有知识库操作**永远使用Bot身份**执行,绝对不触发任何用户身份授权弹窗 -2. **文档范围限制**:仅支持读取飞书知识库(`/wiki/`开头的链接)文档,**不支持读取用户私有个人文档**(`/doc/`/`/sheet/`等非wiki开头的个人路径) -3. **权限告知规则**: - - 收到非知识库文档链接:直接回复「我仅支持读取飞书知识库(Wiki)文档,暂不支持读取个人私有文档,请提供知识库链接」 - - Bot无权限访问目标知识空间:回复「当前Bot无访问该知识空间权限,请将Bot应用添加为该知识空间成员并授予查看权限后重试」 - -## 适用场景 -- 遍历知识库目录下的子文档/子目录 -- 读取知识库文档内容 -- 批量导出知识库文档 -- 所有知识库相关的查询、读取操作 - -## 完整执行链路 - -### 步骤1:链接解析 -- 从用户提供的链接中提取`wiki_token`:例如链接`https://xxx.feishu.cn/wiki/XXXXXXX`中的`XXXXXXX`即为`wiki_token` -- 若链接不含`/wiki/`路径,直接按非知识库文档规则回复 - -### 步骤2:获取节点基础信息 -```bash -LARKSUITE_CLI_CONFIG_DIR=/root/.openclaw/credentials/xiaoyan lark-cli wiki spaces get_node --params '{"token":""}' --as bot -``` -返回结果中提取关键信息: -- `space_id`:知识空间ID -- `obj_token`:文档真实ID(若节点为文档) -- `has_child`:是否为目录(含子节点) -- `obj_type`:节点类型(docx/sheet/bitable等) - -### 步骤3:遍历目录子节点(仅当has_child=true时) -#### 3.1 获取Bot租户访问凭证 -```bash -curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \ - -H "Content-Type: application/json" \ - -d '{"app_id":"cli_xxx","app_secret":"xxx"}' \ - | jq -r '.tenant_access_token' -``` -得到`tenant_access_token`(有效期2小时) - -#### 3.2 调用Wiki V2接口获取子节点列表 -```bash -curl -s -X GET "https://open.feishu.cn/open-apis/wiki/v2/spaces//nodes?parent_node_token=" \ - -H "Authorization: Bearer " -``` -返回子节点完整列表(名称、链接、类型等) - -### 步骤4:读取文档内容(仅当节点为文档时) -```bash -LARKSUITE_CLI_CONFIG_DIR=/root/.openclaw/credentials/xiaoyan lark-cli docs +fetch --doc --as bot -``` - -## 权限要求 -### 1. 应用权限(飞书开发者后台配置) -| 权限名称 | Scope | 类型 | -|---------|-------|------| -| 获取知识空间节点信息 | `wiki:node:retrieve` | 只读 | -| 查看文档内容 | `docx:document:readonly` | 只读 | - -### 2. 知识空间配置 -需要将Bot应用添加到目标知识空间的成员列表,授予至少「可查看」权限 - -## 异常处理 -- 接口返回`99991401`(无权限):按权限不足规则回复用户 -- 接口返回`404`:检查`wiki_token`/`space_id`是否正确,确认链接为有效知识库链接