Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/opencode/src/session/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,11 @@ export const layer: Layer.Layer<Service, never, Bus.Service | Storage.Service> =
sessionID: SessionID
messageID: MessageID
}) {
// Surface the route's declared 404 instead of silently succeeding:
// removing a message that does not exist is a not-found, not a no-op.
// MessageV2.get throws NotFoundError for a missing row, which
// ErrorMiddleware maps to 404 (the deleteMessage route already declares it).
yield* Effect.sync(() => MessageV2.get({ sessionID: input.sessionID, messageID: input.messageID }))
yield* Effect.sync(() =>
SyncEvent.run(MessageV2.Event.Removed, {
sessionID: input.sessionID,
Expand Down
30 changes: 30 additions & 0 deletions packages/opencode/test/server/session-messages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,36 @@ describe("session messages endpoint", () => {
)
})

test("deletes a message through the route runtime and 404s a missing one", async () => {
await using tmp = await tmpdir({ git: true })
await withoutWatcher(() =>
Instance.provide({
directory: tmp.path,
fn: async () => {
const session = await svc.create({})
const [messageID] = await fill(session.id, 1)
const app = Server.Default().app

// An existing message still deletes with 200 and is gone afterwards.
const ok = await app.request(`/session/${session.id}/message/${messageID}`, { method: "DELETE" })
expect(ok.status).toBe(200)
expect(await ok.json()).toBe(true)
expect(await svc.messages({ sessionID: session.id })).toHaveLength(0)

// The route's declared 404 is now real: deleting a message that does
// not exist surfaces NotFoundError instead of silently succeeding.
const miss = await app.request(`/session/${session.id}/message/${MessageID.ascending()}`, {
method: "DELETE",
})
expect(miss.status).toBe(404)
expect((await miss.json()).name).toBe("NotFoundError")

await svc.remove(session.id)
},
}),
)
})

test("rejects a part update whose body does not match the path with a 400", async () => {
await using tmp = await tmpdir({ git: true })
await withoutWatcher(() =>
Expand Down
Loading