Files
yixiong-claude-marketplace/plugins/huanxi/skills/huanxi-shared/SKILL.md
T
SkyJourneyandClaude Sonnet 5 600c0dd323 feat: 寰汐插件随 v1.0.0 生产切换升级到 v2 技能组,新增独立管理端插件
huanxi 插件的技能内容从 v1 全面替换为 v2(huanxi-org/huanxi-weekly 等
v1 专属技能下线,新增 huanxi-issue/huanxi-lookup/huanxi-meeting),MCP
连接与 Token 获取方式同步更新为个人中心自助生成。

新增独立的 huanxi-admin 插件(管理端 4 个技能,hxa_ Token,普通员工无需
安装),此前一直卡在"v2 未部署到生产域名前不推送"这条约束,今晚寰汐
v1.0.0 生产切换完成后条件满足。

产物由 huanxi-menagement 仓库 skills/sync_marketplace.py 生成,技能源码
单一真相在该仓库的 skills/,本仓库只接收产物、不手工编辑。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018xxRKMuiGR4wYT3QbwCpDc
2026-08-22 02:14:34 +08:00

6.3 KiB
Raw Blame History

name, description
name description
huanxi-shared 寰汐 MCP 共享基础:工具命名约定、本地缓存策略与过期检查、状态两层模型、全局确认约定。所有 huanxi-* 技能必须先读本文件。

寰汐 MCP 共享规则

所有 huanxi-* 技能的必读前置


一条最重要的约定:参数以工具自身的说明为准

本文件与各技能文档都不重画参数表。 每个工具的参数名、必填项、取值范围以它在 MCP 里注册的 docstring 为唯一真相;技能只描述调用顺序、ID 如何传递、哪里必须停下来等用户 确认

这条不是洁癖。上一代技能包重画过参数表,结果字段名、枚举值、必填项四类漂移覆盖了 全部六个技能——用户侧表现为频繁的「参数缺失」报错。工具签名变了而文档没跟上, 是必然发生而非可能发生的事。


工具命名

Claude Code / Claude Desktop 里工具名带前缀:mcp__huanxi__task_query(个人端)、 mcp__huanxi-admin__report_pending(管理端)。其他平台通常是裸名 task_query。 本文档统一写裸名,实际调用时按你所在平台的约定加前缀。

两个端点信任边界不同:

个人端 管理端
Token hxp_ 开头 hxa_ 开头
身份 你本人,权限与网页端一致 Token 创建人的管理员身份
视角 我参与的 全量,不受角色过滤

状态是可配置的两层模型(v2 起)

不要硬编码 "in_progress""done" 这类字面量。 状态由后台配置,分两层:

  • category:四类固定语义 not_started / in_progress / completed / cancelled 用于判断(这条算不算完成)
  • status_option_id:具体状态项的 UUID,用于写入

改任何实体状态前,先 dict_get 取该 entity_typemodule/task/issue/meeting必须选对 下的选项,再传对应的 status_option_id。传旧值或错的 entity_type 会被直接拒绝。


本地缓存

缓存根目录 ~/.claude/huanxi-cache/按通道隔离

~/.claude/huanxi-cache/
├── personal/     hxp_ 视角:me.json / my-modules.json / users.json
├── admin/        hxa_ 视角:all-modules.json
└── dict/         与身份无关的配置字典(两个通道共享)

隔离是必须的:管理端看到的是全量模块,个人端只有我参与的——混用会让你把不该展示的 东西展示给用户。

分层 TTL

类别 文件 策略
身份 personal/me.json 永久(身份不变)
配置字典 dict/*.json 版本戳比对 + 24h 兜底
人员与模块 users.json / my-modules.json 24h
日历 dict/workdays.json 按日期 key 永久(查过的不再查)
业务数据 任务 / 日报 / 会议 / 议题 / 公告 一律不缓存

最后一行是硬规则。业务数据随时在变,缓存它只会让你把过期状态当成现状汇报给用户。

字典为什么要版本戳而不是只靠 TTL

其余缓存过期了最多是显示旧数据;字典不一样——状态选项可能被后台停用,你拿 24 小时前 的 ID 去改状态会直接报错。失败方向从「看到旧数据」变成「操作失败」,值得比对一次。

用字典前:
  1. 调 dict_version()            ← 极轻
  2. 与 dict/versions.json 比对
  3. 一致 → 用缓存;不一致 → 调 dict_get() 重取该类并更新缓存

dict_get 的返回里自带 versions 字段,直接连内容一起存下来即可——不要分两次调用, 那中间字典若被改动,你会把新内容配上旧版本戳缓存起来,之后再也不会刷新。

读缓存伪代码

read(file, ttl):
  1. 读 ~/.claude/huanxi-cache/{file}
  2. 文件不存在 → miss
  3. age = now - cached_at
  4. ttl 为永久 或 age < ttl → 返回 data
  5. 否则 → miss

on_miss(tool, params):
  1. 调用工具
  2. 写入 { "cached_at": <ISO8601>, "data": <返回值> }
  3. 返回 data

workdays.json 特殊:按日期 key 存 { "2026-08-06": true },已查过的日期不再查。


站内消息(M12

寰汐的全部系统通知(任务分配、@提及、报告发布、模块变更…)都落在站内消息中心, notification_query 是它的读入口。

什么时候主动用它:用户问「我错过了什么」「有没有人 @ 我」「最近有什么新任务」时。 不要在每次对话开头都拉一遍——那是噪音,用户没问就别塞。

notification_query(unread_only=True)            # 只看未读
notification_query(scene="comment_mentioned")   # 只看 @提及

返回里的 related 给出关联实体({"type": "task", "id": "..."}),可直接拿去调 对应的 task_get / module_get 看详情——不要把 body 里的名字拿去重新搜索。

标记已读要用户明示notification_mark_read() 不传 id 是全部已读, 这是个不可逆的批量动作,跟提交类操作一样先确认再调。 用户说「都看过了」再全清;只是让你念一遍未读的话,不要顺手清掉。

这里标的是站内已读。用户在飞书点了卡片按钮不算站内已读,两者有意分开—— 「在飞书看了但站内还是未读」与「误触就被标已读」都是要避免的别扭。

全局约定

  1. 提交类操作必须先确认report_submit / leader_report_submit / issue_close 等, 执行前把最终内容展示给用户、等到明确确认(「确认」「提交」「好的」)再调。 不要因为用户说了「帮我写日报」就把提交也一并做了——写和交是两个决定。
  2. 删除与指派同样需要确认task_set_assignees替换语义(传空即清空), 不是追加;覆盖别人的名单前先说清楚会变成什么样。
  3. 非工作日不强行中断workday_check 显示非工作日时告知用户并询问是否仍要填写, 不要直接拒绝——补填、调休上班都是真实场景。
  4. 先解析 ID 再操作:需要 module_id / user_id 的操作,先查缓存,未命中再调 module_query / user_search。不要凭名字猜 ID。
  5. 批量优先:工具的过滤维度基本都收列表,一次查多个比循环调用快得多,也更省上下文。