refactor(core): dedupe context epoch initialization
Share one insertInitial path between initialize and prepare, and document the runner's ordering constraint: epoch initialization runs before promotion so a blocked System Context leaves prompts pending, while reconciliation runs after promotion so ContextUpdated messages sequence after promoted input.
This commit is contained in:
parent
966dc54e1d
commit
fae51d853d
2 changed files with 15 additions and 8 deletions
|
|
@ -8,7 +8,6 @@ import { SystemContext } from "../system-context/index"
|
|||
import { ContextSnapshotDecodeError } from "./error"
|
||||
import { SessionEvent } from "./event"
|
||||
import { SessionHistory } from "./history"
|
||||
import { SessionInput } from "./input"
|
||||
import { SessionMessage } from "./message"
|
||||
import { SessionSchema } from "./schema"
|
||||
import { SessionContextEpochTable } from "./sql"
|
||||
|
|
@ -47,11 +46,7 @@ const prepareOnce = Effect.fnUntraced(function* (
|
|||
[context, find(db, sessionID), SessionHistory.latestCompaction(db, sessionID)],
|
||||
{ concurrency: "unbounded" },
|
||||
)
|
||||
if (!stored) {
|
||||
const generation = yield* SystemContext.initialize(value)
|
||||
const baselineSeq = yield* insert(db, sessionID, generation)
|
||||
return { baseline: generation.baseline, baselineSeq }
|
||||
}
|
||||
if (!stored) return yield* insertInitial(db, sessionID, value)
|
||||
|
||||
const snapshot = yield* Schema.decodeUnknownEffect(SystemContext.Snapshot)(stored.snapshot).pipe(
|
||||
Effect.mapError((error) => new ContextSnapshotDecodeError({ sessionID, details: String(error) })),
|
||||
|
|
@ -82,8 +77,16 @@ const initializeOnce = Effect.fnUntraced(function* (
|
|||
context: Effect.Effect<SystemContext.SystemContext>,
|
||||
sessionID: SessionSchema.ID,
|
||||
) {
|
||||
if (yield* exists(db, sessionID)) return
|
||||
const generation = yield* context.pipe(Effect.flatMap(SystemContext.initialize))
|
||||
if (yield* exists(db, sessionID)) return undefined
|
||||
return yield* insertInitial(db, sessionID, yield* context)
|
||||
})
|
||||
|
||||
const insertInitial = Effect.fnUntraced(function* (
|
||||
db: DatabaseService,
|
||||
sessionID: SessionSchema.ID,
|
||||
value: SystemContext.SystemContext,
|
||||
) {
|
||||
const generation = yield* SystemContext.initialize(value)
|
||||
const baselineSeq = yield* insert(db, sessionID, generation)
|
||||
return { baseline: generation.baseline, baselineSeq }
|
||||
})
|
||||
|
|
|
|||
|
|
@ -168,6 +168,10 @@ const layer = Layer.effect(
|
|||
if (session.location.directory !== location.directory || session.location.workspaceID !== location.workspaceID)
|
||||
return yield* Effect.interrupt
|
||||
const agent = yield* agents.select(session.agent)
|
||||
// Epoch initialization runs before promotion so a blocked System Context fails the
|
||||
// turn while prompts are still pending in the durable inbox; a retry re-drains them.
|
||||
// Reconciliation (`prepare` below) runs after promotion so ContextUpdated messages
|
||||
// sequence after the promoted user input.
|
||||
const initialized = yield* SessionContextEpoch.initialize(db, loadSystemContext(agent), session.id)
|
||||
const toolFibers = yield* FiberSet.make<void, ToolOutputStore.Error>()
|
||||
let needsContinuation = false
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue