4.9 KiB
Agent Note: Node PTC 执行模式与内存状态
Status: implemented
English | 中文
问题
交互式自动化需要在模型调用之间保留应用对象、导入模块和辅助函数。如果每次执行都重新创建对象,消费者就无法在观察与操作之间继续使用普通 JavaScript 引用。
决策
现有 @deepseek-ai/dsh-ptc-runtime-node 插件通过 executionMode 选择执行模式。默认的 per-call 模式按配置的文件策略启动新进程。显式启用的 persistent-in-memory 模式为每个以对象身份标识的状态所有者保留一个 Node REPL 进程。两种模式都提供同一个 ctx.ptcRuntime 服务。PTC 使用存活的 Agent 作为所有者,在其上下文销毁时等待释放。修改配置会重载提供方并释放其进程。Node 沙箱决策负责逐次执行的文件约束,PTC 基础决策负责工具分派与模型请求日志。
模式名称描述状态保留方式,不绑定进程实现或代码语法。per-call 只为一次调用保留状态;persistent-in-memory 跨调用保留状态,直到进程或所有者结束。durable 用于命名未来跨重启保存与恢复执行状态的能力。它不是可接受的配置值:实现必须先明确恢复点、可恢复的值以及外部资源的处理方式,才能公开这个模式。常驻进程权限决策负责文件约束、权限切换与临时提权。
一个 npm 包和一个插件入口保持现有安装与加载路径稳定。通信、绑定代理、JSON 编码和输出限制继续作为包内模块复用。Node 提供方将保留进程的所有权交给内部执行对象,该对象不注册额外的 Cordis 服务。逐次执行和内存保留各自管理不同的生命周期。programFormat 描述代码求值形式,与状态保留独立:REPL 不必跨调用保留状态。运行时通过 executionInstructions 负责语法、完成值和状态保留指引;工具层负责调用参数、SDK 声明和图片附加。工作流根据 programFormat 包装程序;所选运行时无法执行受限文件策略时,工作流拒绝执行。
Session 记录提交的程序、嵌套工具调用和返回输出。它不序列化 REPL 堆,也不在重启、恢复或派生后重新执行旧程序,因为重放自动化可能重复外部操作。缺失变量产生普通程序错误,模型指引要求重新创建变量并获取资源。提供方没有引入日志之外的模型输入,因此不需要环境标识或新的持久 Session 事件。
取消、截止时间到期、协议失败、输出超限、所有者销毁和进程退出都会丢弃环境。普通异常保留此前发生的修改。保留的函数使用当前执行的宿主绑定;较早执行中的异步任务不能获取后续执行的工具权限或向其输出。
考虑过的替代方案
将提供方拆成独立 npm 包并增加共享库,可以分别分发,但需要维护额外的包、依赖声明和共享实现的跨包导出。两种 Node 模式目前没有不同发布节奏或独立依赖的需求。第二个插件子路径允许独立加载,但要求部署配置通过替换插件入口来选择执行策略。配置字段直接表达这个选择,并保留已有入口。需要独立分发或出现明显不同的依赖时,可以重新评估拆包。
为公共辅助代码新增 Cordis 服务,会增加注册和注入依赖,却没有提供独立替换的运行能力。内部函数和类已经能够完成复用。共同的执行基类还会把新进程清理与按所有者保留进程的生命周期耦合起来,因此提供方共用处理机制,各自管理生命周期。
序列化任意 JavaScript 对象无法保留原生资源和闭包。重放旧程序可能重复写入和输入操作。这两种做法都会暗示内存保留模式没有提供的恢复保证。
Harness 进程内的独立执行上下文与模型代码共享进程生命周期,无法单独终止同步死循环。托管子进程可以在正常使用时保留导入和变量,同时支持取消与资源清理。仅有进程所有权不能提供文件沙箱或多租户隔离。
影响
选择 persistent-in-memory 会保留执行状态;权限决策定义其文件限制。嵌套工具仍遵循原有授权和日志规则。即使 Harness 没有重启,内存和原生句柄也可能丢失。模型需要从引用或资源错误中恢复,运行时不会自动重试程序。
空闲所有者保留一个没有过期计时器的进程。调用方显式释放所有者,没有所有者的服务调用使用临时进程。程序使用 REPL 语句和末尾表达式,不支持顶层 return;同一保留所有者的调用不能重叠。工具 schema 和程序指引跟随所选模式。