refactor(session): simplify projection state (#43957)

This commit is contained in:
Kit Langton
2026-08-21 14:40:53 -04:00
committed by GitHub
parent b3d6063329
commit 3a1fb5ae65
5 changed files with 16 additions and 31 deletions
+4 -3
View File
@@ -217,13 +217,14 @@ const planContent = (messages: readonly SessionMessage.Info[], tokens: number) =
const selected = select(messages, tokens)
if (!selected) return
const previousSummary = messages.findLast(
(message) => message.type === "compaction" && message.status === "completed",
(message): message is SessionMessage.CompactionCompleted =>
message.type === "compaction" && message.status === "completed",
)
const previousRecent = previousSummary?.type === "compaction" ? previousSummary.recent : ""
const previousRecent = previousSummary?.recent ?? ""
const summarizeRecent = !previousRecent && !selected.head
return {
prompt: buildPrompt({
previousSummary: previousSummary?.type === "compaction" ? previousSummary.summary : undefined,
previousSummary: previousSummary?.summary,
context: summarizeRecent ? [selected.recent] : [previousRecent, selected.head].filter(Boolean),
}),
recent: summarizeRecent ? "" : selected.recent,
+10 -6
View File
@@ -248,19 +248,23 @@ const loadBlobs = Effect.fnUntraced(function* (db: DatabaseService, values: Read
return blobs
})
function dereference(values: Instructions.Values, blobs: ReadonlyMap<Instructions.Hash, Schema.Json>) {
return Object.fromEntries(Object.entries(values).map(([key, hash]) => [key, requireBlob(blobs, hash)])) as Readonly<
Record<string, Schema.Json>
>
function dereference(
values: Instructions.Values,
blobs: ReadonlyMap<Instructions.Hash, Schema.Json>,
): Readonly<Record<string, Schema.Json>> {
return Object.fromEntries(Object.entries(values).map(([key, hash]) => [key, requireBlob(blobs, hash)]))
}
function dereferenceDelta(delta: Instructions.Delta, blobs: ReadonlyMap<Instructions.Hash, Schema.Json>) {
function dereferenceDelta(
delta: Instructions.Delta,
blobs: ReadonlyMap<Instructions.Hash, Schema.Json>,
): Readonly<Record<string, Option.Option<Schema.Json>>> {
return Object.fromEntries(
Object.entries(delta).map(([key, hash]) => [
key,
hash === "removed" ? Option.none() : Option.some(requireBlob(blobs, hash)),
]),
) as Readonly<Record<string, Option.Option<Schema.Json>>>
)
}
function requireBlob(blobs: ReadonlyMap<Instructions.Hash, Schema.Json>, hash: Instructions.Hash) {
+1 -16
View File
@@ -218,8 +218,6 @@ function run(db: DatabaseService, event: MessageEvent) {
const decodeRow = (row: typeof SessionMessageTable.$inferSelect) =>
decodeMessage({ ...row.data, id: row.id, type: row.type })
const updateMessage = (message: SessionMessage.Info) => {
if (event.durable === undefined)
return Effect.die(new Error("Durable Session event is missing aggregate sequence"))
const encoded = encodeMessage(message)
const { id, type, ...data } = encoded
return db
@@ -374,7 +372,6 @@ function run(db: DatabaseService, event: MessageEvent) {
}
function insertMessage(db: DatabaseService, event: SessionEvent.DurableEvent, message: SessionMessage.Info) {
if (event.durable === undefined) return Effect.die(new Error("Durable Session event is missing aggregate sequence"))
const encoded = encodeMessage(message)
const { id, type, ...data } = encoded
return db
@@ -516,8 +513,6 @@ const layer = Layer.effectDiscard(
yield* bus.project(SessionEvent.Forked, (event) => projectFork(db, event))
yield* bus.project(SessionEvent.InboxDelivered, (event) =>
Effect.gen(function* () {
if (event.durable === undefined)
return yield* Effect.die(new Error("Durable Session event is missing aggregate sequence"))
const input = yield* SessionInbox.projectDelivered(db, {
id: event.data.inboxID,
sessionID: event.data.sessionID,
@@ -550,8 +545,6 @@ const layer = Layer.effectDiscard(
)
yield* bus.project(SessionEvent.InboxEnqueued, (event) =>
Effect.gen(function* () {
if (event.durable === undefined)
return yield* Effect.die(new Error("Durable Session event is missing aggregate sequence"))
yield* SessionInbox.projectAdmitted(db, {
enqueuedSeq: event.durable.seq,
id: event.data.inboxID,
@@ -622,17 +615,9 @@ const layer = Layer.effectDiscard(
Effect.gen(function* () {
yield* run(db, event)
yield* InstructionState.advanceEpoch(db, event.data.sessionID, event.durable.seq)
if (event.durable === undefined)
return yield* Effect.die(new Error("Durable Session event is missing aggregate sequence"))
}),
)
yield* bus.project(SessionEvent.Compaction.Failed, (event) =>
Effect.gen(function* () {
yield* run(db, event)
if (event.durable === undefined)
return yield* Effect.die(new Error("Durable Session event is missing aggregate sequence"))
}),
)
yield* bus.project(SessionEvent.Compaction.Failed, (event) => run(db, event))
yield* bus.project(SessionEvent.RevertEvent.Staged, (event) =>
Effect.gen(function* () {
const revert = event.data.revert
@@ -14,9 +14,6 @@ export function make(tools: string[]) {
"- Use the edit tool for targeted changes to existing text files. It replaces the exact text in `oldString` with `newString`, and the values must differ. By default, `oldString` must occur exactly once. If it occurs multiple times, include more surrounding context to make it unique or set `replaceAll` to true to replace every occurrence.",
)
}
// if (tools.includes("patch")) {
// // instructions.push(...)
// }
if (tools.includes("read")) {
instructions.push("- Prefer using the read tool rather than shell commands like `cat`.")
}
+1 -3
View File
@@ -49,8 +49,6 @@ const layer = Layer.effect(
const sessions = yield* Session.Service
const encodeMessage = Schema.encodeSync(SessionMessage.Info)
const persistProject = (project: Project.Resolved) => upsertProject(db, project).pipe(Effect.orDie)
return Service.of({
export: Effect.fn("SessionTransfer.export")(function* (input) {
const data = {
@@ -69,7 +67,7 @@ const layer = Layer.effect(
.pipe(Effect.orDie)
if (recorded) return yield* new ImportConflictError({ sessionID })
const project = yield* projects.resolve(input.location.directory)
yield* persistProject(project)
yield* upsertProject(db, project).pipe(Effect.orDie)
const messages = input.data.messages.map((message, index) => {
const encoded = encodeMessage(message)
const { id: _, type, ...data } = encoded