chore: clarify agent record resume contract (#465)

This commit is contained in:
_Kerman 2026-06-05 14:51:58 +08:00 committed by GitHub
parent 4f9977d4dc
commit 95dd0a1f3b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 17 additions and 5 deletions

View file

@ -19,9 +19,16 @@ export type { FileSystemAgentRecordPersistenceOptions } from './persistence';
export { BlobStore, isBlobRef } from './blobref';
export type { BlobStoreOptions } from './blobref';
// Contract: restore MUST NOT emit UI events, call the LLM, execute tools, or
// touch the filesystem in a way that triggers external side effects. Each case
// should reproduce the in-memory state the live handler left behind, nothing more.
// Contract: restore MUST only rebuild in-memory state. It must not emit UI
// events, call the LLM, execute tools, start background work, make network
// requests, or touch the filesystem in a way that triggers external side effects.
//
// Prefer restoring by calling the same method that wrote the record, so live
// execution and resume share one state mutation path. For example,
// permission.set_mode replays through agent.permission.setMode(input.mode),
// not by assigning modeOverride here. records.logRecord, emitEvent, and
// emitStatusUpdated already gate on records.restoring, so those calls are safe
// during resume.
function restoreAgentRecord(agent: Agent, input: AgentRecord): void {
switch (input.type) {
case 'metadata':
@ -95,8 +102,9 @@ function restoreAgentRecord(agent: Agent, input: AgentRecord): void {
case 'tools.update_store':
agent.tools.updateStore(input.key, input.value);
return;
// Goal records are an audit trail only. Goal state is restored from
// `state.json` (metadata.custom.goal), never rebuilt from these records.
// TODO: Move goal state transitions to real resume semantics. These records
// are currently audit-only, while goal state is restored from `state.json`
// (metadata.custom.goal) instead of being rebuilt from ordered records.
case 'goal.create':
case 'goal.update':
case 'goal.account_usage':

View file

@ -10,6 +10,10 @@ import type { PermissionApprovalResultRecord, PermissionMode } from '../permissi
import type { UserToolRegistration } from '../tool';
import type { UsageRecordScope } from '../usage';
// Agent records are the ordered event log used to rebuild agent state on resume.
// Use records, not state.json, when correctness depends on the order in which
// state transitions happened. Each persisted record type must have explicit
// resume semantics in restoreAgentRecord; a write-only record is not persistence.
export interface AgentRecordEvents {
metadata: {
protocol_version: string;