oh-my-pi /omfg 深度解析:从一句抱怨到 TTSR 流式拦截规则的生成提示词与实现

发布时间:2026/9/12 14:40:11
oh-my-pi /omfg 深度解析:从一句抱怨到 TTSR 流式拦截规则的生成提示词与实现 oh-my-pi /omfg 深度解析从一句抱怨到 TTSR 流式拦截规则的生成提示词与实现【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-piomfg-user.md是 oh-my-pi⌥ Coding agent with the IDE wired in中/omfg斜杠命令背后的用户提示词模板当用户对 agent 反复出现的不良行为例如总是写any、总是在 Ruby 里生成不安全的 eval感到厌烦时只需输入一句抱怨这个模板就会驱动模型把抱怨锻造成一条 Time Traveling Stream RuleTTSR时间旅行流式规则——一条带 YAML frontmatter 的 Markdown 规则文件之后每当 agent 的流式输出再次匹配该规则时流会被中断并注入纠正指导。读完本文你将理解该提示词的 TTSR 机制约束、JSON 输出契约、占位符与再生成路径以及从/omfg命令注册、模型调用、规则解析、历史校验到落盘生效的完整源码链路。提示词定位它是谁、何时被渲染omfg-user.md位于 系统提示词目录全文包裹在omfg.../omfg标签内整体结构为角色设定用户不满于反复出现的 agent 行为→ 任务撰写一条本应更早捕获该行为的 TTSR 规则→TTSR 机制说明→输出契约Output contract→示例形态Example shape→ 用户抱怨占位符{{complaint}}→ 可选的失败反馈/修订区块。从源码看该模板被 OmfgController 以文本方式导入并在每轮生成前渲染import omfgUserPrompt from ../../prompts/system/omfg-user.md with { type: text }; // omfg-controller.ts#L4 ... const promptText prompt.render(omfgUserPrompt, { complaint: request.complaint, feedback: failedAttempts.length 0 ? failedAttempts.join(\n\n) : undefined, previousRule, });即模板中的{{complaint}}被替换为用户输入抱怨而{{#if feedback}} ... {{/if}}区块只在存在失败尝试或用户修订时才展开携带失败尝试记录与最近一次候选 JSON{{previousRule}}要求模型重新生成一条修正后的规则修复列出的校验失败或用户修订绝不重复失败的 scope 或 condition。这是一个典型的带反馈的自修复循环提示词。TTSR 机制提示词教给模型的规则模型提示词 TTSR mechanics一节定义了模型必须遵守的规则模型逐条继承如下这是理解后续所有输出约束的前提规则即文件一条 TTSR 规则是一个带 YAML frontmatter 的 Markdown 文件。condition一个或多个 JavaScript 正则模式用于测试 assistant 的流式输出。scope逗号分隔的允许列表若存在则只检查列出的流。流类型语义text 仅 assistant 散文thinking 隐藏推理摘要tool 所有工具的所有参数。文件级工具 scopetool:name(glob)表示只监控一个工具、且仅当 path 类参数匹配 glob 时。例如tool:write(*.rb)、tool:edit(*.ts)。提示词明确要求针对代码抱怨 SHOULD 使用文件级工具 scope——Ruby 代码通过write生成 → 用tool:write(*.rb)而不是裸的tool或text。JSON 转义容忍工具参数在流式期间可能被序列化因此包含引号的代码的 condition 应当容忍 JSON 转义例如参数里的会出现为\。命中效果当condition在scope内匹配时流被中断Markdown 正文作为纠正指导被注入。仓库文档 docs/ttsr-injection-lifecycle.md 印证了这一机制的运行时事实condition匹配后触发agent.abort()随后按contextMode丢弃或保留部分输出并用ttsr-interrupt.md模板渲染注入内容重试生成默认 scope无显式scope时监控 assistant text 与所有工具参数但不监控 thinking——与提示词中scope 是允许列表的表述一致。输出契约模型必须只输出一个 JSON 对象提示词最核心的部分是Output contract它规定了模型响应必须满足的硬性格式逐条如下只输出恰好一个 JSON 对象不输出任何其他内容JSON 字段name、description、condition、scope、bodyname必须是 kebab-casedescription必须是一行摘要condition必须是字符串或字符串数组JavaScript 正则模式condition必须匹配本会话更早可见的具体不良 assistant 输出正则反斜杠为 JSON只转义一次写\\beval\\s*\\(绝不要写\\\\beval\\\\s*\\(保持condition精确绝不使用宽泛的 catch-allscope必须是字符串或字符串数组scope在抱怨允许的范围内尽量窄绝不使用tool, text——除非同一不良行为同时出现在工具参数和 assistant 散文中body必须是简洁解释正确行为的 Markdown 指导调用方负责组装 YAML frontmatter模型绝不输出 Markdown frontmatter 或用代码围栏包裹 JSON。示例形态提示词原文提示词给出的标准示例如下它同时演示了精确 condition 文件级工具 scope 可执行 body三要素{ name: ts-no-any, description: Never use any in TypeScript — use unknown, a generic, or the real type, condition: : any|as any, scope: [tool:edit(*.ts), tool:edit(*.tsx), tool:write(*.ts), tool:write(*.tsx)], body: Never use : any or as any. Use unknown, a domain type, a generic, or a type guard. }注意condition: : any|as any是一个不带转义符的精确正则as any与: any二选一匹配scope 同时覆盖edit与write两个会产出代码的工具且限定.ts/.tsx后缀——正是mechanics一节要求的文件级工具 scope 写法。从源码看契约为何如此苛刻提示词里的每一条约束都能在 omfg-rule.ts 的解析/校验代码中找到对应的防御点。理解这些代码能解释契约存在的理由1. JSON 提取要抗脏输出extractGeneratedRuleJson()omfg-rule.ts#L29-L37先尝试用正则 (?:json)?\s*([\s\S]*?)从响应中抠出围栏内的 JSON再用extractBalancedJsonObject()#L164-L205一个逐字符跟踪字符串/转义/括号深度的平衡提取器从第一个{ 提取完整对象无围栏时直接对全文做平衡提取。这解释了契约中绝不输出代码围栏——解析器两者都容忍但纯 JSON 是最可靠的形态。2. name 的 kebab-case 要求由 sanitizer 兜底sanitizeRuleName()omfg-rule.ts#L39-L47会把原始 name 转小写、去引号、非[a-z0-9_-]字符折叠为-、压缩连续连字符并去首尾符号。测试证实 Caps Spaces!! →caps-spaces、already_ok-123保持不变见 omfg-rule.test.ts#L105-L109。3. 只转义一次的契约有自动修复兜底针对模型最爱犯的二次转义错误normalizeConditionRegex()#L74-L89先用compileRuleCondition试编译失败则调用unescapeRegexConditionOnce()把\\\\折叠为\\再试编译若修复后仍无法编译才报Invalid condition regex ...错误。parseGeneratedRule()末尾还会用new TtsrManager().addRule(rule)做最终体检规则若无有效 condition 或无可达 scope 则报Rule has no valid condition or reachable scopeomfg-rule.ts#L148-L151。4. frontmatter 由调用方组装assembleRuleMarkdown()omfg-rule.ts#L280-L291把 JSON 五个字段拼装成最终规则文件--- name: name description: JSON 序列化的一行字符串 condition: JSON 字符串或 [a, b] 数组 scope: 同上 --- body 正文CRLF 统一为 LF这正是契约中调用方组装 YAML frontmatter的落实——模型永远不该自己写---块。历史校验condition 必须真的抓得住那次犯案现场契约中conditionMUST match the specific offending assistant output visible earlier in this conversation在代码里对应回放校验validateRuleAgainstAssistantHistory()omfg-rule.ts#L346-L377会用独立的TtsrManager注册候选规则注册失败即判不匹配并给出反馈collectAssistantSurfaces()#L306-L344遍历会话消息把每条 assistant 消息拆成三类校验面surfacetext块、thinking块、toolCall块工具参数经JSON.stringify序列化并抽取path/paths类字段作为文件路径stream key 形如toolcall:id对每个 surface 重置缓冲后调用manager.checkDelta(surface.text, surface.context)任何一次命中即视为 condition 在历史中真实可抓。不匹配时的反馈并非一句没匹配上而是构造了极具指导性的两段反馈文本会原样喂回给模型对应提示词{{feedback}}占位符的内容无匹配反馈buildNoMatchFeedback()#L451-L475列出已检查的 surface 标签与节选最多 5 条超长文本围绕 condition 中的关键词截取 120140 字符窗口并提醒如果可见的坏代码含引号记得工具参数按序列化 JSON 检查引号可能以\形式出现如果 condition 看起来没问题就去修 scope 使其覆盖到犯案的工具与文件 globscope 过宽反馈buildScopeFeedback()#L477-L513当 condition 命中了一个带文件后缀的工具调用、而 scope 却是裸tool/toolcall宽或包含text内容明明在工具参数里时直接给出推荐 scope例如根据犯案路径后缀生成tool:edit(*.ts)并要求不要重复失败的 scope。这条反馈链路正是提示词 mechanics 中SHOULD 使用文件级工具 scope的运行时强制执行者。端到端流程/omfg 命令如何驱动整条链路命令注册与入口/omfg在 builtin-lifecycle.ts#L493-L504 注册{ name: omfg, icon: rule, description: Forge a TTSR rule from a complaint to stop a recurring behavior, inlineHint: complaint, allowArgs: true, handleTui: async (command, runtime) { const complaint command.text.slice(/${command.name}.length).trim(); runtime.ctx.editor.setText(); await runtime.ctx.handleOmfgCommand(complaint); }, },命令后的整段文本可含多词被原样截取为complaint。slash 命令测试验证了三点完整抱怨透传/omfg This guy used any again....、多余空白保留在参数内/omfg stop making unchecked casts...、空参调用不报错而是提示用法。生成—校验—重试循环最多 3 次OmfgController.start()在抱怨为空时提示Usage: /omfg complaint随后挂载一个OmfgPanelComponent面板并异步执行#runRequest()。核心循环在#generateCandidate()omfg-controller.ts#L131-L191const MAX_ATTEMPTS 3; // omfg-controller.ts#L34每一轮用prompt.render(omfgUserPrompt, { complaint, feedback, previousRule })渲染模板——首轮feedback为空、previousRule为空后续轮feedback累积所有失败原因previousRule是上一轮候选的完整文件内容通过session.runEphemeralTurn({ promptText, dedupeReply: false, onTextDelta, signal })发起一个临时ephemeral回合——生成内容流式显示在面板上但不污染主会话历史parseGeneratedRule(replyText)解析提取失败如no object→Missing generated rule JSON object、name 为空、缺 condition/scope/body、正则无法编译都会成为带错误码的失败反馈validateParsedRuleAgainstAssistantHistory()做历史回放校验若校验失败但repairEscapedConditions()把\\\\折叠为\\后重建规则能让规则通过则直接采纳修复后的候选repairedCondition: true校验通过condition 真的命中过历史输出即返回validated: true的候选。3 轮全部失败后返回最后一个未验证候选若历史校验仍不匹配#runRequest()会弹确认框Couldnt confirm this rule matches the conversation. Save anyway?允许用户强制保存——这是一个有意识的人机协作逃逸阀。保存项目级 vs 全局并即时热注册#saveCandidate()omfg-controller.ts#L193-L249提供三个选项选项落盘路径source levelThis project (.omp/rules)cwd/.omp/rules/name.mdCONFIG_DIR_NAME.ompprojectGlobal — all projects (~/.omp/agent/rules)agentDir/rules/name.mduserAmend with feedback…不保存收集用户修订意见进入下一轮生成—目标文件已存在时弹覆盖确认保存后经buildOmfgRuleForPath()构建Rule对象并调用#registerLive()#registerLive(rule: Rule): void { this.ctx.session.ttsrManager?.addRule(rule); }即规则在当前会话内立即生效无需重启。这与 TTSR 生命周期文档描述的注册行为一致TtsrManager.addRule()在ttsr.enabled false、condition 与 astCondition 皆空、同名规则已注册、或 scope 排除所有受监控流时会跳过注册无效正则以警告记日志而不中断会话。与 TTSR 运行时的衔接规则文件保存后即成为标准 TTSR 资源进入 docs/ttsr-injection-lifecycle.md 描述的运行时管线会话创建时loadCapability(rules)发现规则并按rule.name首胜去重bucketRules(...)剔除ttsr.disabledRules列出的规则、在ttsr.builtinRules false时剔除内建默认规则流式期间TtsrCoordinator监控text_delta/thinking_delta/toolcall_delta对命中且interruptMode允许中断的规则立即agent.abort()、延迟 50ms 后按contextMode默认discard处理部分输出并注入纠正。换言之/omfg产出的每一行condition/scope最终都由TtsrManager.checkDelta()/checkSnapshot()逐字执行——提示词中的精确、不宽泛要求直接关系到规则的误报率。测试覆盖契约每条都有断言omfg.test.ts命令路由、多词抱怨透传、空参处理omfg-rule.test.tsJSON 提取含 body 内嵌代码围栏不误伤、fenced JSON 接受、畸形输出错误码缺对象/空 name/缺 condition/缺 scope/非法正则[、内联正则标志(?i)支持、name slug 化、以及edit 工具参数在tool:edit(*.ts)scope 下被历史校验命中等回放断言omfg-controller.test.ts控制器层流程。小结omfg-user.md看似只是一段提示词实则是 oh-my-pi 抱怨 → 规则 → 流式拦截治理闭环的规格说明书它把 TTSR 的规则模型condition/scope/文件级 glob/JSON 转义、严格的单 JSON 输出契约、以及面向失败重试的反馈占位符全部前置编码进模型上下文而 omfg-controller.ts 与 omfg-rule.ts 则用平衡 JSON 提取、正则修复、scope 收窄建议和历史回放校验把这条契约变成了可执行、可验证、可回滚Escape 中止、拒绝保存的工程流程。对希望深入 TTSR 运行时的读者docs/ttsr-injection-lifecycle.md 覆盖了从规则发现、流式监控、触发中断到持久化恢复的完整实现细节。【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考