feat(tui): support session deletion

This commit is contained in:
Dax Raad 2026-07-06 19:19:22 -04:00
commit c0ea1a43f9
18 changed files with 563 additions and 273 deletions

View file

@ -153,6 +153,7 @@ export interface Interface {
readonly create: (input: CreateInput) => Effect.Effect<SessionSchema.Info, NotFoundError>
readonly fork: (input: ForkInput) => Effect.Effect<SessionSchema.Info, NotFoundError | MessageNotFoundError>
readonly get: (sessionID: SessionSchema.ID) => Effect.Effect<SessionSchema.Info, NotFoundError>
readonly remove: (sessionID: SessionSchema.ID) => Effect.Effect<void, NotFoundError>
readonly messages: (input: {
sessionID: SessionSchema.ID
limit?: number
@ -363,6 +364,15 @@ const layer = Layer.effect(
if (!session) return yield* new NotFoundError({ sessionID })
return session
}),
remove: Effect.fn("V2Session.remove")(function* (sessionID) {
yield* result.get(sessionID)
yield* execution.interrupt(sessionID)
yield* execution.awaitIdle(sessionID)
const children = yield* result.list({ parentID: sessionID })
yield* Effect.forEach(children.data, (child) => result.remove(child.id), { concurrency: 1, discard: true })
yield* events.publish(SessionEvent.Deleted, { sessionID })
yield* events.remove(sessionID)
}),
list: Effect.fn("V2Session.list")(function* (input = {}) {
const direction = input.anchor?.direction ?? "next"
const requestedOrder = input.order ?? "desc"

View file

@ -152,6 +152,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
},
"session.moved": () => Effect.void,
"session.renamed": () => Effect.void,
"session.deleted": () => Effect.void,
"session.forked": () => Effect.void,
"session.prompt.promoted": () => Effect.void,
"session.prompt.admitted": () => Effect.void,
@ -168,7 +169,6 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
time: { created: event.created },
}),
),
"session.instructions.discovered": () => Effect.void,
"session.synthetic": (event) => {
return adapter.appendMessage(
SessionMessage.Synthetic.make({

View file

@ -26,7 +26,10 @@ import type { DeepMutable } from "../schema"
import { Slug } from "../util/slug"
type DatabaseService = Database.Interface["db"]
type MessageEvent = Exclude<SessionEvent.DurableEvent, typeof SessionEvent.Forked.Type>
type MessageEvent = Exclude<
SessionEvent.DurableEvent,
typeof SessionEvent.Forked.Type | typeof SessionEvent.Deleted.Type
>
const decodeMessage = Schema.decodeUnknownSync(SessionMessage.Message)
const encodeMessage = Schema.encodeSync(SessionMessage.Message)
@ -505,6 +508,9 @@ const layer = Layer.effectDiscard(
yield* events.project(SessionV1.Event.Deleted, (event) =>
db.delete(SessionTable).where(eq(SessionTable.id, event.data.sessionID)).run().pipe(Effect.orDie),
)
yield* events.project(SessionEvent.Deleted, (event) =>
db.delete(SessionTable).where(eq(SessionTable.id, event.data.sessionID)).run().pipe(Effect.orDie),
)
yield* events.project(SessionV1.Event.MessageUpdated, (event) =>
Effect.gen(function* () {
const time_created = event.data.info.time.created