i-have-adhd TypeScript扩展架构深度解析:从loadRules到syncContext的完整调用链

发布时间:2026/8/30 12:54:55
i-have-adhd TypeScript扩展架构深度解析:从loadRules到syncContext的完整调用链 i-have-adhd TypeScript扩展架构深度解析从loadRules到syncContext的完整调用链【免费下载链接】i-have-adhdA skill to stop your coding agent from burying the answer. ADHD-friendly output.项目地址: https://gitcode.com/GitHub_Trending/ih/i-have-adhdi-have-adhd 是一个让 AI 编码助手输出 ADHD 友好内容的技能插件答案先行、步骤编号、零客套。本文以它面向 Pi / OMP 的 TypeScript 扩展为例完整拆解从loadRules读取规则文件、到syncContext把规则注入对话的调用链带你弄清这个扩展如何在整个会话期间让规则常驻在 Agent 上下文中。1️⃣ i-have-adhd 是什么一个 ADHD 友好输出技能普通编码 Agent 回答认证怎么修可能先铺垫三句再给答案。i-have-adhd 做的事情很简单别让 Agent 把答案埋在话里。它的规则集共 10 条全部定义在 skills/i-have-adhd/SKILL.md 中规则一句话说明1. 答案先行第一行就是能执行的命令或路径2. 步骤编号多步任务用编号列表一步一个动作3. 以单一动作收尾结尾只留一个两分钟内能做的下一步4. 抑制跑题当前问题没解决完不谈第二个问题5. 每轮复述状态第 3 步/共 5 步完成不依赖读者记忆6. 具体耗时估计说约 15 分钟不说一点工作量7. 让进展可见明确说出现在能跑通了8. 平静陈述错误位置、原因、修复不用Oh no9. 列表不超过 5 项超出就拆成现在做和以后做10. 无开场、无总结、无客套从答案开始到答案结束规则本体是单一事实来源single source of truth扩展代码只负责把这份规则文件送进模型上下文两者职责分离——这正是理解其 TypeScript 架构的钥匙。核心文件一览文件职责extensions/i-have-adhd.ts扩展入口加载规则、管理状态、订阅事件extensions/context-compat.ts运行时兼容层从 Pi / OMP 读取上下文消息skills/i-have-adhd/SKILL.md10 条规则的权威定义package.json在pi/omp字段中声明扩展入口scripts/check_context_compat.ts兼容性自检脚本2️⃣ 启动第一步loadRules 读取规则文件Pi 或 OMP 启动时会加载 extensions/i-have-adhd.ts 导出的工厂函数iHaveAdhdExtension(pi)它做的第一件事就是调用loadRules()见 extensions/i-have-adhd.ts定位文件模块顶层用自己的文件位置fileURLToPath(import.meta.url)拼出SKILL.md的绝对路径不依赖工作目录。读取全文用readFileSync读文件读不到就抛一个带路径的错误让问题在启动时暴露。剥离 frontmatterstripFrontmatter()用正则删掉文件头部的 YAML 元数据块name、description等只保留规则正文。空内容即失败规则文件是空的会直接抛错避免静默无规则的会话。 关键设计loadRules()每个扩展生命周期只执行一次结果存入闭包变量rules。之后无论注入多少次上下文都不再重复读盘。3️⃣ 三种打开方式启动标志、斜杠命令、自然语言扩展注册了三类用户入口extensions/i-have-adhd.ts启动标志pi --adhd通过pi.registerFlag(adhd, ...)注册让新会话默认开启斜杠命令/i-have-adhd [on|off]会话内切换不带参数则翻转当前状态自然语言input事件监听器拦截stop adhd mode和normal mode两个短语随时关闭。另外还有一个细节/skill:i-have-adhd这个内置技能命令会被扩展接管extensions/i-have-adhd.ts直接等价于开启模式并返回handled防止 Pi 把同一份规则再展开第二遍。状态变更统一走setEnabled()它把开关写入一条会话条目类型为i-have-adhd-state刷新底部状态栏的● ADHD ON标记再调用syncContext()同步上下文。4️⃣ 会话开始restoreState 决定开关初值session_start和session_tree事件都会触发restoreState(ctx)extensions/i-have-adhd.ts它的决策逻辑是查历史getSavedState()扫描当前会话分支的所有条目取最近一条i-have-adhd-state——用户在上一段会话里说过stop adhd mode恢复后仍保持关闭定默认值pi.getFlag(adhd) true即pi --adhd启动或~/.pi/agent/.i-have-adhd-always标志文件存在则默认开启合并enabled savedState ?? enabledByDefault——用户的显式选择永远压过默认值落地先updateStatus()刷新界面状态再syncContext()把规则同步进对话。5️⃣ syncContext 核心规则只注入一次而非每次重写syncContext()extensions/i-have-adhd.ts是整个调用链的心脏决策表非常克制模式 enabled规则已在上下文中动作✅❌注入规则消息隐藏✅✅什么都不做❌✅注入已禁用通知❌❌什么都不做注入用的是pi.sendMessage({ customType: i-have-adhd-rules, display: false }, { triggerTurn: false })——一条不显示、不触发模型回合的隐藏消息安静地留在对话里模型在之后的每个请求中都能看到它。为什么只注入一次代码注释里写得很直白这与 Claude Code 的 SessionStart 钩子行为保持一致——注入一次规则集而不是在每个请求前重写系统提示。省 token也避免规则反复刷新干扰对话节奏。关闭时也不是删消息而是追加一条i-have-adhd-disabled通知忽略之前注入的 ADHD 规则恢复默认风格——用最新的标记覆盖旧规则后文细讲。6️⃣ context-compat 兼容层一份代码跑两种运行时规则还在不在上下文里需要读取会话消息列表但 Pi 和 OMP 的 sessionManager API 并不相同。兼容层 extensions/context-compat.ts 解决了这个问题OMP的 API 是buildSessionContext()返回{ messages }Pi的 API 是buildContextEntries()直接返回条目数组。contextMessages()extensions/context-compat.ts按顺序尝试两个 API并且是故障放行fail open设计sessionManager 缺失、API 不存在、甚至调用抛异常一律返回空数组。后果是调用方认为规则不在上下文于是重新注入一次——重复注入无害见下节而让会话启动崩溃才是真事故。真正裁决规则是否生效的是latestMarkerIsActive()extensions/context-compat.ts它按时间顺序扫描消息只看最后一个标记先注入规则、后追加禁用通知 → 规则失效先禁用、后重新开启再注入规则→ 规则生效普通消息非 custom 标记一律忽略不会误激活规则。这套逻辑有专门的自检脚本 scripts/check_context_compat.ts 验证用bun scripts/check_context_compat.ts运行即可。7️⃣ session_compact压缩之后规则复活Agent 会话过长时会触发压缩compaction被总结掉的旧消息会从上下文里物理移除——之前注入的规则消息也可能就此消失。扩展对session_compact事件的响应只有一行再跑一次syncContext(ctx)。结合第 6 节的判断逻辑规则没了就重新注入还在就什么都不做。配合latestMarkerIsActive只看最新标记的特性整条链对压缩、分支、会话恢复都是安全的。8️⃣ 完整调用链总览把上面的环节串起来整条链是Pi / OMP 启动 └─► iHaveAdhdExtension(pi) ├─► loadRules() ← 读取 SKILL.md剥离 frontmatter一次性 └─► 注册 adhd 标志、/i-have-adhd 命令、input 事件监听 会话开始session_start / session_tree └─► restoreState(ctx) ├─► getSavedState() 从会话条目还原用户上次的开关选择 ├─► updateStatus() 底部状态栏显示 ● ADHD ON └─► syncContext(ctx) └─► rulesAreInContext(ctx) ├─► contextMessages() OMP: buildSessionContext / Pi: buildContextEntriesfail open └─► latestMarkerIsActive() 只看最新标记裁决生效状态 └─► 未注入 → sendMessage(规则, 隐藏, 不触发回合) 用户切换命令 / 自然语言 └─► setEnabled() → appendEntry(持久化) → updateStatus() → syncContext() 会话压缩session_compact └─► syncContext() 规则被压缩掉了重新注入三个值得借鉴的架构要点规则与代码分离——改规则只需编辑 skills/i-have-adhd/SKILL.md扩展代码零改动一次性注入 标记裁决——省 token 且对压缩、分支天然安全故障放行兼容层——运行时 API 变了也不崩最多重复注入一次。 延伸阅读各运行时安装与激活方式见 INSTALL.md仓库整体地图见 AGENTS.mdalways-on 钩子声明在 hooks/hooks.json。【免费下载链接】i-have-adhdA skill to stop your coding agent from burying the answer. ADHD-friendly output.项目地址: https://gitcode.com/GitHub_Trending/ih/i-have-adhd创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考