mcpField
P
pi-durable-dev-rules

pi-durable-dev-rules

github.com/agents365-ai开发9760 次安装2 周前更新
代码仓库

关于 pi-durable-dev-rules

pi-durable-dev-rules 是面向使用 @earendil-works/pi-durable 及相关包构建应用的开发者的参考技能。它涵盖持久化执行、API、运行时行为和实现范例;该 API 仍处于实验阶段。

主要功能

  1. 01Harness 设置与存储选择
  2. 02对话和任务生命周期指南
  3. 03工具架构与执行模式
  4. 04崩溃恢复与重放安全
  5. 05API、运行时及范例参考

适用场景

  1. 01搭建 Agent 应用 Harness
  2. 02审查持久化任务和工具代码
  3. 03诊断恢复或任务阻塞问题
  4. 04实现前核对包的 API

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agents365-ai/365-skills --skill pi-durable-dev-rules

安装后在 Claude Code 中输入/pi-durable-dev-rules确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

.skillspector-baseline.yaml
assets/
workflow-en.drawio
workflow-zh.drawio
references/
codemode-sandbox.md
durable-api.md
durable-guide.md
durable-recipes.md
durable-runtime.md
durable-spec.md
pi-ai-models.md
scripts/
build-references.py
README.md
refresh.sh

详细介绍

Pi 持久化开发规则

@earendil-works/pi-durable 是一个持久化 Agent 框架:对话、模型轮次、工具调用、任务以及你自己的文档,都会先提交到存储中,再显示出来,因此即使进程在某轮中途退出,也能从中断处继续。它与 @earendil-works/pi-ai(模型访问、工具、消息)和 @earendil-works/chord(受追踪的 JSON 状态)一同发布在 pi monorepo 中。

有两点会决定大多数设计选择:

  • API 处于实验阶段。 1.2.0 版与 monorepo 同步;每次发布都可能引入破坏性变更。请依据你安装的版本引用并编写代码,并将签名差异视为版本差异,而非错误。
  • 这是一个用于构建 Agent 应用的库,而非编码 Agent 命令行工具。 如需使用 Pi CLI、它的扩展、技能、MCP 和 SDK,请使用同级技能 pi-dev-rules。

何时使用此技能

  • 编写或审查导入 @earendil-works/pi-durable 或 @earendil-works/pi-ai 的代码。
  • 组装框架:选择存储后端、配置 HarnessOptions、设置、注册表和执行环境。
  • 对话:提交 / 等待、忙碌收件箱(引导、跟进、写入)、重置和交接、分叉、按对话更改 Agent。
  • 工具:TypeBox 模式、三种输出通道、使用 executeTool() 进行嵌套调用、callers、deferred 工具和工具搜索、重放安全、输出限制、图像处理。
  • 持久化任务:阶段和检查点、所有权、等待和 failFast、中止、恢复、迁移。
  • 子 Agent 和子任务、前台与后台、汇报答案。
  • 文档:作用域、历史记录和分叉语义、迁移、检查点、观察。
  • 代码模式(在对话的工具上运行的 QuickJS 脚本)、钩子和守卫、压缩、用量。
  • 运行时问题:崩溃后哪些内容会保留、为什么输入仍在排队、任务为何被阻塞或成为孤儿、中止如何级联、部分答案为何可见或缺失。
  • 扩展框架:通过一致性测试套件验证的存储后端和执行环境、自定义任务和提示词章节。

参考索引:按需加载文件

文件内容
references/durable-guide.md软件包自带的指南,原样打包:快速入门、概念、持久化与恢复、扩展、工具(包括嵌套调用和 callers)、代码模式、系统提示词、按对话配置 Agent、设置、环境、重新加载、监视、繁忙对话、重置与移交、压缩、Agent 事件、钩子、更多对话与分支、中止与子 Agent、子任务、任务图、自有状态、用量与成本、存储、错误和可运行示例。从这里开始。
references/durable-api.md精确的公开接口:入口映射、Context、Harness/Session/Conversation/ConversationHandle、提交、Tx 事务接口、文档、条目、扩展与分区、钩子、工具与 ToolExecutionApi、任务与 TaskRuntime、环境、存储、测试、观察、错误类,以及各子路径的导出清单
references/durable-runtime.md工作的实际执行方式:提交线及其规则、一次输入的完整流程、任务检查点、所有权树、按情况恢复、压缩、收件箱边界、实时状态与进度节奏、故障模型、改变行为的参数,以及刻意不包含的目标
references/durable-recipes.md项目设置、全部 32 个可运行示例的目录,以及包含代码的 19 个示例方案:最简聊天、持久化与输入恰好处理一次、实时 UI、Agent 事件、结构化输出工具、工具调用工具、前台与后台子 Agent、具有持久等待的子任务、编码 Agent、计划模式、按对话配置沙箱、工具覆盖与包装器、扩展状态与迁移、钩子、压缩、代码模式、工具搜索、一致性测试,以及陷阱检查清单
references/durable-spec.md原样打包的规范性 Pico5 规范(5340 行):记录与生命周期、文档与变更所有权、事务与存储所有权、任务与效果夹层、结构化并发、提交与收件箱、扩展/钩子/工具、内置任务、文档观察、存储契约与故障模型、后端、API 易错点和非目标。发布前请阅读第 12 节
references/pi-ai-models.md原样打包的模型层:createModels()/builtinModels()、提供方工厂与身份验证、查询模型目录、环境变量、使用 TypeBox 定义工具、约束采样、事件参考、图像输入、用量与成本、重试,以及最终写入条目的消息类型
references/codemode-sandbox.md原样打包的 @earendil-works/pi-codemode:脚本可以调用的内容、注入的全局变量、沙箱模块接口、确定性与内存限制,以及本地与远程沙箱

速查表

npm install @earendil-works/pi-durable @earendil-works/pi-ai @earendil-works/chord
node --conditions=source --experimental-strip-types app.ts     # run TS directly against the source
import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
import { builtinModels } from "@earendil-works/pi-ai/providers/all";
import { createRegistry, Harness, AssistantEntry } from "@earendil-works/pi-durable";
import { openNodeSqliteStorage } from "@earendil-works/pi-durable/storage/sqlite/node";

const context = BACKGROUND_CONTEXT;
const harness = await Harness.open(await openNodeSqliteStorage("./session.sqlite"), {
	models: builtinModels(), registry: createRegistry(), env: (target) => new NodeExecutionEnv({ cwd: target.cwd ?? process.cwd() }),
}, context);
const root = await harness.root(context, { agent: { model: { provider: "openai", modelId: "gpt-6-sol" } } });

harness.resume();                                              // continue unfinished work from a previous process
const submission = await root.submit({ type: "input", content: "Hello", requestId: "greeting-1" }, context);
const settled = await submission.wait(context);                // "done" | "unanswered"
if (settled.status === "done" && settled.type === "input") {
	const answer = await root.commit((tx) => tx.entry(AssistantEntry, settled.answer), context);
}
await harness.close(context);

存储:MemoryStorage(不持久化任何内容)、openNodeSqliteStorage(path)(长期运行时的默认选择;使用 WAL,提交在进程崩溃后仍能保留)、openNodeJsonlStorage(directory, context)(仅追加,整个历史记录保留在内存中)、openDurableObjectSqliteStorage(ctx.storage)。 每次只能由一个进程拥有某个存储。

硬性规则

  • 写入都必须经过同一条提交路径,且提交存储前不会显示任何内容。 在提交回调中,只能通过 tx 读取;在首次写入表之前,先读取所需的每一行表数据(ReadAfterWrite),且绝不要在其中等待耗时操作:模型、工具、进程、网络、人类、嵌套提交或会话等待者。
  • 每个异步调用都要传入一个 Context。 取消它只会取消该调用或等待,不会取消持久化工作。无需取消时使用 BACKGROUND_CONTEXT,在宿主边界使用 withCancel()。withoutAbortSignal() 用于 close() 等必须完成的清理操作。
  • 只有提交后才能报告已完成的操作。 任务步骤的模式是:提交意图、执行操作、提交结果。如果操作完成后、提交前发生崩溃,该步骤会重新运行,因此要让步骤具备幂等性,使用 runtime.memo() 实现首个写入者胜出,并且只有在重新运行确实安全时,才为工具设置 replay: "safe"。不安全的工具若被中断,会向模型返回 interrupted 错误结果,其中包含截至目前已提交的输出。
  • 工具有三个输出通道。 output 是模型读取的内容,structuredOutput 是调用该工具的程序读取的内容(会根据 structuredOutputSchema 验证;除非结果是错误,否则必须提供),details 用于宿主 UI。只有 output 和 details 会进入对话记录。
  • 每次工具调用都是由其调用方拥有的独立持久化任务。 使用 api.executeTool() 发起的嵌套调用会将结果返回给调用方,而不会写入对话记录;重新运行时会复用同一个键。取消上下文只会停止等待。嵌套结果的 usage 已计入其自身工具,再次转发会导致重复计数。
  • 所有权决定生命周期。 每项任务创建时都要指定所有者;每段对话要么没有所有者,要么归某项任务所有。中止会向下传播;只有普通的所属工作全部完成后,任务才会结束(在此之前会存储为 completing);background: true 的任务是一个边界,普通中止和空闲等待都会跳过它。绝不要在中止处理程序中创建所属工作(此时任务已标记为中止):应在原处补偿,或使用由对话拥有的后台任务,并调用 runtime.waitForTask()。
  • 运行会话拥有自己的写入。 不要向有活动运行会话的对话追加原始条目:应使用写入提交,因为原始 tx.appendEntry() 无法替代它,也不会执行过期检查。
  • 以 pi. 为前缀的名称属于内置项,适用于任务名称、文档类型和条目类型(pi.user、pi.assistant、pi.system、pi.tool-result、pi.reset、pi.compaction、pi.agent、pi.provider、pi.live、pi.inbox、pi.usage、pi.generation、pi.tool)。没有任何机制强制遵守此规则,重用这些名称会与框架行为冲突。
  • 存储错误会终止框架。 出错的调用会被拒绝;之后的每个调用和待处理的等待都会以 SessionFailed 被拒绝;监视会以 session_failed 结束;onReport 会收到一次错误通知。不会重试;要恢复,请重新打开并使用相同的 requestId 重新提交。无效请求只会导致该次调用失败(StorageRequestError),你自己的代码出错则只会导致其自身单元失败。
  • 文档按类型寻址,而非按对象寻址。 类型和可见名称是持久化协议的一部分:值迁移不能重命名类型(应复制并停用旧类型);存储的版本高于代码版本,或低于代码版本但没有 migrate,都会导致访问失败。只有带类型的 tx.doc() 才会创建不存在的文档。
  • snapshot()、文档状态和监视返回的值都是受跟踪的容器。 绝不要修改它们;先复制。监视最多保留 100 个未交付帧,之后会合并为一个完整值替换帧,因此必须看到每次状态转换的消费者需要自行记录日志。
  • 扩展是整体选择的。 Hook 和包装器仅在选中相应扩展时才会生效,因此,如果某个对话将工具指定为显式数组且未包含某个防护扩展,该对话运行时就不会启用它。包装器必须是纯函数;卸载扩展会停止后续使用,但不会释放正在运行的调用所占用的资源。
  • 提示词章节必须保持稳定。 如果章节文本在内容没有实际变化时仍会变化(例如受时钟或随机值影响),每次请求都会追加一条 pi.system 条目,并破坏提供方提示词缓存。设置可以是 getter:每次使用时都会读取,且绝不会存储。
  • 该 API 仍处于实验阶段,Pico5 规范是一份设计文档。 有关行为,请阅读 references/durable-guide.md;规则的重要性不明确时,请阅读 references/durable-spec.md;发布前请阅读规范的第 12 节(API 易错点)。

评论

支持 Markdown