fix(core): harden compaction admission
This commit is contained in:
@@ -600,7 +600,6 @@ export type SessionPromptInput = {
|
||||
|
||||
export type SessionPromptOutput = {
|
||||
readonly data: {
|
||||
readonly type: "prompt"
|
||||
readonly admittedSeq: number
|
||||
readonly id: string
|
||||
readonly sessionID: string
|
||||
@@ -801,7 +800,6 @@ export type SessionCommandInput = {
|
||||
|
||||
export type SessionCommandOutput = {
|
||||
readonly data: {
|
||||
readonly type: "prompt"
|
||||
readonly admittedSeq: number
|
||||
readonly id: string
|
||||
readonly sessionID: string
|
||||
|
||||
@@ -212,7 +212,6 @@ const session = {
|
||||
|
||||
const admission = {
|
||||
data: {
|
||||
type: "prompt",
|
||||
admittedSeq: 0,
|
||||
id: "msg_test",
|
||||
sessionID: "ses_test",
|
||||
|
||||
@@ -309,7 +309,6 @@ const session = {
|
||||
|
||||
const admission = {
|
||||
data: {
|
||||
type: "prompt",
|
||||
admittedSeq: 0,
|
||||
id: "msg_test",
|
||||
sessionID: "ses_test",
|
||||
|
||||
@@ -2,7 +2,7 @@ export * as SessionInput from "./input"
|
||||
|
||||
import { and, asc, eq, isNull } from "drizzle-orm"
|
||||
import { DateTime, Effect, Schema } from "effect"
|
||||
import { Admitted, Compaction, Delivery, Entry } from "@opencode-ai/schema/session-input"
|
||||
import { Admitted, Compaction, Delivery, Entry, PromptEntry } from "@opencode-ai/schema/session-input"
|
||||
import type { Database } from "../database/database"
|
||||
import type { EventV2 } from "../event"
|
||||
import { KeyedMutex } from "../effect/keyed-mutex"
|
||||
@@ -14,7 +14,7 @@ import { SessionInputTable, SessionMessageTable } from "./sql"
|
||||
|
||||
type DatabaseService = Database.Interface["db"]
|
||||
|
||||
export { Admitted, Compaction, Delivery, Entry }
|
||||
export { Admitted, Compaction, Delivery, Entry, PromptEntry }
|
||||
|
||||
const decodePrompt = Schema.decodeUnknownSync(Prompt)
|
||||
const encodePrompt = Schema.encodeSync(Prompt)
|
||||
@@ -38,7 +38,7 @@ const fromRow = (row: typeof SessionInputTable.$inferSelect): Entry => {
|
||||
...(row.promoted_seq === null ? {} : { handledSeq: row.promoted_seq }),
|
||||
})
|
||||
if (!row.prompt || !row.delivery) throw new LifecycleConflict({ id: base.id })
|
||||
return Admitted.make({
|
||||
return PromptEntry.make({
|
||||
...base,
|
||||
type: "prompt",
|
||||
prompt: decodePrompt(row.prompt),
|
||||
@@ -47,6 +47,17 @@ const fromRow = (row: typeof SessionInputTable.$inferSelect): Entry => {
|
||||
})
|
||||
}
|
||||
|
||||
const toAdmitted = (entry: PromptEntry): Admitted =>
|
||||
Admitted.make({
|
||||
admittedSeq: entry.admittedSeq,
|
||||
id: entry.id,
|
||||
sessionID: entry.sessionID,
|
||||
prompt: entry.prompt,
|
||||
delivery: entry.delivery,
|
||||
timeCreated: entry.timeCreated,
|
||||
...(entry.promotedSeq === undefined ? {} : { promotedSeq: entry.promotedSeq }),
|
||||
})
|
||||
|
||||
export const find = Effect.fn("SessionInput.find")(function* (db: DatabaseService, id: SessionMessage.ID) {
|
||||
const row = yield* db.select().from(SessionInputTable).where(eq(SessionInputTable.id, id)).get().pipe(Effect.orDie)
|
||||
return row === undefined ? undefined : fromRow(row)
|
||||
@@ -88,7 +99,7 @@ export const admit = Effect.fn("SessionInput.admit")(function* (
|
||||
const existing = yield* find(db, input.id)
|
||||
if (existing !== undefined) {
|
||||
if (existing.type !== "prompt") return yield* Effect.die(new LifecycleConflict({ id: input.id }))
|
||||
return existing
|
||||
return toAdmitted(existing)
|
||||
}
|
||||
return yield* events
|
||||
.publish(SessionEvent.PromptAdmitted, {
|
||||
@@ -103,7 +114,6 @@ export const admit = Effect.fn("SessionInput.admit")(function* (
|
||||
? Effect.die(new Error("Prompt admission event is missing aggregate sequence"))
|
||||
: Effect.succeed(
|
||||
Admitted.make({
|
||||
type: "prompt",
|
||||
admittedSeq: event.durable.seq,
|
||||
id: input.id,
|
||||
sessionID: input.sessionID,
|
||||
@@ -115,7 +125,9 @@ export const admit = Effect.fn("SessionInput.admit")(function* (
|
||||
),
|
||||
Effect.catchDefect((defect) =>
|
||||
find(db, input.id).pipe(
|
||||
Effect.flatMap((stored) => (stored?.type === "prompt" ? Effect.succeed(stored) : Effect.die(defect))),
|
||||
Effect.flatMap((stored) =>
|
||||
stored?.type === "prompt" ? Effect.succeed(toAdmitted(stored)) : Effect.die(defect),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -13,7 +13,6 @@ export type Delivery = SessionDelivery.Delivery
|
||||
|
||||
export interface Admitted extends Schema.Schema.Type<typeof Admitted> {}
|
||||
export const Admitted = Schema.Struct({
|
||||
type: Schema.Literal("prompt"),
|
||||
admittedSeq: NonNegativeInt,
|
||||
id: SessionMessage.ID,
|
||||
sessionID: SessionID,
|
||||
@@ -23,6 +22,12 @@ export const Admitted = Schema.Struct({
|
||||
promotedSeq: NonNegativeInt.pipe(optional),
|
||||
}).annotate({ identifier: "SessionInput.Admitted" })
|
||||
|
||||
export interface PromptEntry extends Schema.Schema.Type<typeof PromptEntry> {}
|
||||
export const PromptEntry = Schema.Struct({
|
||||
type: Schema.Literal("prompt"),
|
||||
...Admitted.fields,
|
||||
}).annotate({ identifier: "SessionInput.PromptEntry" })
|
||||
|
||||
export interface Compaction extends Schema.Schema.Type<typeof Compaction> {}
|
||||
export const Compaction = Schema.Struct({
|
||||
type: Schema.Literal("compaction"),
|
||||
@@ -33,5 +38,5 @@ export const Compaction = Schema.Struct({
|
||||
handledSeq: NonNegativeInt.pipe(optional),
|
||||
}).annotate({ identifier: "SessionInput.Compaction" })
|
||||
|
||||
export const Entry = Schema.Union([Admitted, Compaction]).pipe(Schema.toTaggedUnion("type"))
|
||||
export const Entry = Schema.Union([PromptEntry, Compaction]).pipe(Schema.toTaggedUnion("type"))
|
||||
export type Entry = typeof Entry.Type
|
||||
|
||||
@@ -4399,7 +4399,6 @@ export type PromptInputFileAttachment = {
|
||||
}
|
||||
|
||||
export type SessionInputAdmitted = {
|
||||
type: "prompt"
|
||||
admittedSeq: number
|
||||
id: string
|
||||
sessionID: string
|
||||
@@ -8697,7 +8696,6 @@ export type SessionV2InfoV2 = {
|
||||
}
|
||||
|
||||
export type SessionInputAdmittedV2 = {
|
||||
type: "prompt"
|
||||
admittedSeq: number
|
||||
id: string
|
||||
sessionID: string
|
||||
|
||||
Reference in New Issue
Block a user