refactor agent pre-step inbox lifecycle

This commit is contained in:
_Kerman
2026-07-31 19:21:16 +08:00
parent c2ff9ddec8
commit fcc2b5e282
267 changed files with 2052 additions and 1546 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-07-21-semantic-session-checkpoints.md
2026-07-21-semantic-session-checkpoints.md: 927a4c5d6d2aad5dea460ea29f97c1686e9d5398
2026-07-21-semantic-session-checkpoints.zh.md: 6454b496aa8c03c172d6a4bc969e43e8dbca2430
2026-07-21-semantic-session-checkpoints.md: 697d878dccbfab1ded9f73e134d594ba6f0665e1
2026-07-21-semantic-session-checkpoints.zh.md: 48bd97001d04fa4a4f6037ef9d7936278003df26

View File

@@ -10,9 +10,9 @@ Persistence buffered every synchronous `session/event` until the loop's final tu
## Decision
`dsh-session-checkpoint-policy` owns semantic durability barriers as a zero-config plugin beside a persistence backend. At `agent/step`, it flushes pending prompt input or the preceding response/result batch before the next request is derived. It wraps `llm/stream` lazily and flushes the live session after `request/header` is logged but before the adapter stream is constructed. It wraps top-level `tools/execute` after ordered pre-execute policy and flushes the recorded `tool/call` before the tool body; nested dispatches reuse the outer model-visible call. The loop's final `turn/end` checkpoint remains the closing boundary and settles before another queued turn or idle observation.
`dsh-session-checkpoint-policy` owns semantic durability barriers as a zero-config plugin beside a persistence backend. At `agent/pre-step`, it flushes pending prompt input or the preceding response/result batch before the next request is derived. It wraps `llm/stream` lazily and flushes the live session after `request/header` is logged but before the adapter stream is constructed. It wraps top-level `tools/execute` after ordered pre-execute policy and flushes the recorded `tool/call` before the tool body; nested dispatches reuse the outer model-visible call. The loop's final `turn/end` checkpoint remains the closing boundary and settles before another queued turn or idle observation.
Persistence and checkpoint scheduling remain separate Cordis plugins. A backend makes requested `session/flush` boundaries durable but does not choose them; loading it without this policy is valid and retains the loop's coarser checkpoints. First-party persisted apps and runtimes explicitly mount both, while a specialized deployment may intentionally omit or replace the policy. Registration order governs whether events appended by other `agent/step` listeners precede this checkpoint; prompt input and the preceding loop-owned assistant message and ordered results are already in the log.
Persistence and checkpoint scheduling remain separate Cordis plugins. A backend makes requested `session/flush` boundaries durable but does not choose them; loading it without this policy is valid and retains the loop's coarser checkpoints. First-party persisted apps and runtimes explicitly mount both, while a specialized deployment may intentionally omit or replace the policy. Registration order governs whether events appended by other `agent/pre-step` listeners precede this checkpoint; prompt input and the preceding loop-owned assistant message and ordered results are already in the log.
Checkpoint failure and cancellation are fail-closed at effect boundaries. A rejected request checkpoint prevents adapter dispatch; a rejected tool checkpoint becomes an error result without invoking the tool body. If cancellation lands while the tool checkpoint is pending, the policy rechecks the signal and returns the canonical `ABORTED_BEFORE_DISPATCH` result. A rejected between-step checkpoint closes the turn before another model request. A rejected final turn checkpoint is reported live and does not prevent later queued work. Persistence serialization continues to belong to the coordinator, so concurrent tool checkpoints cannot duplicate event sequences.

View File

@@ -10,9 +10,9 @@ Status: implemented
## 决策
`dsh-session-checkpoint-policy` 以零配置插件的形式与持久化后端共同加载,并负责语义持久性屏障。在 `agent/step` 时,该插件会在推导下一个请求前刷新待持久化的提示词输入或前一批响应/结果。该插件惰性包装 `llm/stream`,在记录 `request/header` 之后、构造适配器流之前,刷新活动会话。该插件还在有序的执行前策略之后包装顶层 `tools/execute`,在进入工具主体前刷新已记录的 `tool/call`;嵌套分发则复用外层模型可见调用。循环的最终 `turn/end` 检查点仍是轮次的收尾边界,并会在处理另一个已排队轮次或观察到空闲状态之前完成。
`dsh-session-checkpoint-policy` 以零配置插件的形式与持久化后端共同加载,并负责语义持久性屏障。在 `agent/pre-step` 时,该插件会在推导下一个请求前刷新待持久化的提示词输入或前一批响应/结果。该插件惰性包装 `llm/stream`,在记录 `request/header` 之后、构造适配器流之前,刷新活动会话。该插件还在有序的执行前策略之后包装顶层 `tools/execute`,在进入工具主体前刷新已记录的 `tool/call`;嵌套分发则复用外层模型可见调用。循环的最终 `turn/end` 检查点仍是轮次的收尾边界,并会在处理另一个已排队轮次或观察到空闲状态之前完成。
持久化与检查点调度仍是相互独立的 Cordis 插件。后端使请求的 `session/flush` 边界持久化,但不选择边界;只加载后端而不加载本策略仍是有效组合,并保留循环提供的较粗检查点。第一方持久化应用与运行时会显式加载两者,专用部署则可以有意省略或替换本策略。注册顺序决定其他 `agent/step` 监听器追加的事件是否先于本检查点;提示词输入以及前一批由循环自身记录的助手消息与有序结果都已在日志中。
持久化与检查点调度仍是相互独立的 Cordis 插件。后端使请求的 `session/flush` 边界持久化,但不选择边界;只加载后端而不加载本策略仍是有效组合,并保留循环提供的较粗检查点。第一方持久化应用与运行时会显式加载两者,专用部署则可以有意省略或替换本策略。注册顺序决定其他 `agent/pre-step` 监听器追加的事件是否先于本检查点;提示词输入以及前一批由循环自身记录的助手消息与有序结果都已在日志中。
检查点失败与取消在副作用边界上采取失败关闭策略。请求检查点被拒绝时,系统不会分发给适配器;工具检查点被拒绝时,系统会返回错误结果,不调用工具主体。如果在工具检查点等待期间收到取消,策略会重新检查信号,并返回标准的 `ABORTED_BEFORE_DISPATCH` 结果。步骤间检查点被拒绝时,系统会在发起下一个模型请求前结束该轮次。轮次的最终检查点被拒绝时,系统会实时报告该失败,但不会阻止后续排队工作。持久化写入的串行化仍由协调器负责,因此并发的工具检查点不会产生重复的事件序号。