refactor(agent-core-v2): replace defineOp/Model with Event2 dispatch and replayable states - #2909
refactor(agent-core-v2): replace defineOp/Model with Event2 dispatch and replayable states#2909sailist wants to merge 1 commit into
Conversation
|
commit: |
…and replayable states - replace defineOp/Op/OpDescriptor/toEvent and defineModel/defineCheckpointedModel with Event2 subclasses: durable classes declare static durable + schema, serialize() keeps the wire record shape byte-frozen, transient classes stay off the journal - define states via defineState(...).replayable(...).on(Event2, fold): immer produceWithPatches folds with atomic prepare/commit, .undoable() trait drives prompt-submit checkpoints and context.undo, ephemeral kv keys keep imperative set - degrade IWireService to a journal adapter; the agent event dispatcher owns the pipeline (fold -> set -> appendRecord -> publish) and silent restore - align downstream event surfaces: kap-server WS envelope timestamp from event.time, klient event schemas gain time, node-sdk/acp-server/print wiring updated - rewrite gen-wire-manifest/gen-state-manifest for the unified registry and replace the op-uniqueness lint with event-uniqueness
21b1e9d to
dea38ab
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 21b1e9d584
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| for (const entry of this.queue.splice(0)) { | ||
| entry.resolve(); | ||
| } |
There was a problem hiding this comment.
Reject queued dispatches that were not run
When a dispatch fails after other reentrant dispatches have been queued, this catch resolves every remaining queued promise even though the finally clears the queue and none of those events were folded, published, or persisted. In the reentrant path (dispatching is true, e.g. a bus subscriber calling dispatch()), callers awaiting those returned promises will observe success with their event silently dropped; reject the pending entries or keep them queued for a later drain instead.
Useful? React with 👍 / 👎.
Related Issue
No linked issue — the problem is explained below.
Problem
agent-core-v2 carried two overlapping write models: durable ops defined through
defineOp/defineModelon the wire layer, and transient domain events declared viaDomainEventMapmodule augmentation and published on an event bus. State changes therefore had two disjoint code paths (op apply +toEventprojection vs direct publish), event types were string-keyed maps rather than classes, and undo existed only as whole-snapshot checkpoint copies wired through a bespokeCHECKPOINTED_MODELSregistry. There was no uniform patch history, and the op/event split made it hard to reason about what is persisted, replayed, or observable.What changed
Event2subclasses carryingtype+time. Durable events declare a schema andserialize()into the existing wire.jsonl record shape (byte-for-byte frozen, old v1.0–v1.5 journals still replay); transient events are never persisted.defineOp/Op/OpDescriptor/toEvent/PersistedOpMap/TransientOpMap/DomainEventMapare removed repo-wide.defineState(...).replayable(...)definitions with mutation-style folds (.on(Event, fold)) powered by immerproduceWithPatches. Durable fold results are journaled through the wire AppendLog; restore silently re-folds from the journal without re-publishing events.checkpoint(), andundoToCheckpoint()live on the dispatcher; the former whole-snapshot checkpointed models now ride on the same patch-based undo via an.undoable()trait, withcontext.undosemantics and UX unchanged.defineState/StateKeymechanism and scope state services; the read path isagentState.get(key)and the dispatcher no longer owns state instances. Ephemeral kv state keeps its imperativesetunchanged.gen-wire-manifest/gen-state-manifestscan the new APIs (regenerated manifests), and theop-uniquenesslint becameevent-uniquenesscovering theEVENT2_REGISTRY.event.time), klient/node-sdk/acp-server type alignment, transcript package verified unchanged. Wire journal format, WS envelope shape, SDK flat events, and TUI behavior are intentionally frozen.Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.