fix(core): commit staged revert before admitting new prompt (#34338)
This commit is contained in:
parent
04c6bed240
commit
42a3cf9645
2 changed files with 56 additions and 2 deletions
|
|
@ -370,7 +370,11 @@ export const layer = Layer.effect(
|
|||
prompt: Effect.fn("V2Session.prompt")((input) =>
|
||||
Effect.uninterruptible(
|
||||
Effect.gen(function* () {
|
||||
yield* result.get(input.sessionID)
|
||||
const session = yield* result.get(input.sessionID)
|
||||
// A staged revert must be committed before admitting new input so the prompt
|
||||
// continues from the reverted boundary rather than stale post-boundary history.
|
||||
if (session.revert)
|
||||
yield* SessionRevert.commit(session).pipe(Effect.provideService(EventV2.Service, events))
|
||||
const prompt = resolvePrompt(input.prompt)
|
||||
const messageID = input.id ?? SessionMessage.ID.create()
|
||||
const delivery = input.delivery ?? "steer"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import { describe, expect } from "bun:test"
|
||||
import { DateTime, Effect, Fiber, Layer, Stream } from "effect"
|
||||
import { DateTime, Effect, Fiber, Layer, Schema, Stream } from "effect"
|
||||
import { eq } from "drizzle-orm"
|
||||
import { Database } from "@opencode-ai/core/database/database"
|
||||
import { EventV2 } from "@opencode-ai/core/event"
|
||||
import { EventTable } from "@opencode-ai/core/event/sql"
|
||||
import { SessionEvent } from "@opencode-ai/core/session/event"
|
||||
import { ModelV2 } from "@opencode-ai/core/model"
|
||||
import { ProviderV2 } from "@opencode-ai/core/provider"
|
||||
import { Project } from "@opencode-ai/core/project"
|
||||
import { ProjectTable } from "@opencode-ai/core/project/sql"
|
||||
import { AbsolutePath } from "@opencode-ai/core/schema"
|
||||
|
|
@ -110,6 +112,21 @@ const eventCount = (type: string) =>
|
|||
),
|
||||
)
|
||||
|
||||
const encodeMessage = Schema.encodeSync(SessionMessage.Message)
|
||||
const assistantRow = (id: SessionMessage.ID, seq: number) => {
|
||||
const { id: _, type, ...data } = encodeMessage(
|
||||
SessionMessage.Assistant.make({
|
||||
id,
|
||||
type: "assistant",
|
||||
agent: "build",
|
||||
model: { id: ModelV2.ID.make("model"), providerID: ProviderV2.ID.make("provider") },
|
||||
content: [],
|
||||
time: { created: DateTime.makeUnsafe(0) },
|
||||
}),
|
||||
)
|
||||
return { id, session_id: sessionID, type, seq, time_created: 0, data }
|
||||
}
|
||||
|
||||
describe("SessionV2.prompt", () => {
|
||||
it.effect("exposes the execution registry", () =>
|
||||
Effect.gen(function* () {
|
||||
|
|
@ -201,6 +218,39 @@ describe("SessionV2.prompt", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
it.effect("commits a staged revert before admitting a new prompt", () =>
|
||||
Effect.gen(function* () {
|
||||
yield* setup
|
||||
const session = yield* SessionV2.Service
|
||||
const events = yield* EventV2.Service
|
||||
const { db } = yield* Database.Service
|
||||
|
||||
const boundary = yield* session.prompt({
|
||||
sessionID,
|
||||
prompt: Prompt.make({ text: "boundary" }),
|
||||
resume: false,
|
||||
})
|
||||
yield* SessionInput.promoteSteers(db, events, sessionID, Number.MAX_SAFE_INTEGER)
|
||||
const stale = SessionMessage.ID.make("msg_stale_assistant")
|
||||
yield* db.insert(SessionMessageTable).values(assistantRow(stale, 100)).run().pipe(Effect.orDie)
|
||||
yield* events.publish(SessionEvent.RevertEvent.Staged, {
|
||||
sessionID,
|
||||
timestamp: yield* DateTime.now,
|
||||
revert: { messageID: boundary.id, files: [] },
|
||||
})
|
||||
expect((yield* session.get(sessionID)).revert?.messageID).toBe(boundary.id)
|
||||
|
||||
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "after revert" }), resume: false })
|
||||
|
||||
expect((yield* session.get(sessionID)).revert).toBeUndefined()
|
||||
expect(
|
||||
(yield* db.select({ id: SessionMessageTable.id }).from(SessionMessageTable).all().pipe(Effect.orDie)).map(
|
||||
(row) => row.id,
|
||||
),
|
||||
).not.toContain(stale)
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("resolves attachment MIME before admission", () =>
|
||||
Effect.gen(function* () {
|
||||
yield* setup
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue