Skip to content

Commit fed043a

Browse files
authored
fix(session): add typed message lookup wrappers (anomalyco#27269)
1 parent e9a29e4 commit fed043a

3 files changed

Lines changed: 49 additions & 10 deletions

File tree

packages/opencode/src/server/routes/instance/httpapi/handlers/session.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { SessionStatus } from "@/session/status"
1414
import { SessionSummary } from "@/session/summary"
1515
import { Todo } from "@/session/todo"
1616
import { MessageID, PartID, SessionID } from "@/session/schema"
17-
import { NotFoundError } from "@/storage/storage"
1817
import { NamedError } from "@opencode-ai/core/util/error"
1918
import { Cause, Effect, Option, Schema, Scope } from "effect"
2019
import * as Stream from "effect/Stream"
@@ -105,11 +104,13 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
105104
return yield* session.messages({ sessionID: ctx.params.sessionID })
106105
}
107106

108-
const page = MessageV2.page({
109-
sessionID: ctx.params.sessionID,
110-
limit: ctx.query.limit,
111-
before: ctx.query.before,
112-
})
107+
const page = yield* SessionError.mapStorageNotFound(
108+
MessageV2.pageEffect({
109+
sessionID: ctx.params.sessionID,
110+
limit: ctx.query.limit,
111+
before: ctx.query.before,
112+
}),
113+
)
113114
if (!page.cursor) return page.items
114115

115116
const request = yield* HttpServerRequest.HttpServerRequest
@@ -131,10 +132,7 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
131132
params: { sessionID: SessionID; messageID: MessageID }
132133
}) {
133134
return yield* SessionError.mapStorageNotFound(
134-
Effect.try({
135-
try: () => MessageV2.get({ sessionID: ctx.params.sessionID, messageID: ctx.params.messageID }),
136-
catch: (error) => error,
137-
}).pipe(Effect.catch((error) => (NotFoundError.isInstance(error) ? Effect.fail(error) : Effect.die(error)))),
135+
MessageV2.getEffect({ sessionID: ctx.params.sessionID, messageID: ctx.params.messageID }),
138136
)
139137
})
140138

packages/opencode/src/session/message-v2.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,17 @@ export function page(input: { sessionID: SessionID; limit: number; before?: stri
956956
}
957957
}
958958

959+
export const pageEffect = Effect.fn("MessageV2.pageEffect")(function* (input: {
960+
sessionID: SessionID
961+
limit: number
962+
before?: string
963+
}) {
964+
return yield* Effect.try({
965+
try: () => page(input),
966+
catch: (error) => error,
967+
}).pipe(Effect.catch((error) => (NotFoundError.isInstance(error) ? Effect.fail(error) : Effect.die(error))))
968+
})
969+
959970
export function* stream(sessionID: SessionID) {
960971
const size = 50
961972
let before: string | undefined
@@ -1000,6 +1011,16 @@ export function get(input: { sessionID: SessionID; messageID: MessageID }): With
10001011
}
10011012
}
10021013

1014+
export const getEffect = Effect.fn("MessageV2.getEffect")(function* (input: {
1015+
sessionID: SessionID
1016+
messageID: MessageID
1017+
}) {
1018+
return yield* Effect.try({
1019+
try: () => get(input),
1020+
catch: (error) => error,
1021+
}).pipe(Effect.catch((error) => (NotFoundError.isInstance(error) ? Effect.fail(error) : Effect.die(error))))
1022+
})
1023+
10031024
export function filterCompacted(msgs: Iterable<WithParts>) {
10041025
const result = [] as WithParts[]
10051026
const completed = new Set<string>()

packages/opencode/test/session/messages-pagination.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,15 @@ describe("MessageV2.page", () => {
205205
}),
206206
)
207207

208+
it.instance("fails pageEffect with NotFoundError for non-existent session", () =>
209+
Effect.gen(function* () {
210+
const fake = "non-existent-session" as SessionID
211+
const error = yield* Effect.flip(MessageV2.pageEffect({ sessionID: fake, limit: 10 }))
212+
expect(error).toBeInstanceOf(NotFoundError)
213+
expect(error.message).toBe(`Session not found: ${fake}`)
214+
}),
215+
)
216+
208217
it.instance("handles exact limit boundary", () =>
209218
withSession(({ sessionID }) =>
210219
Effect.gen(function* () {
@@ -492,6 +501,17 @@ describe("MessageV2.get", () => {
492501
),
493502
)
494503

504+
it.instance("fails getEffect with NotFoundError for non-existent message", () =>
505+
withSession(({ sessionID }) =>
506+
Effect.gen(function* () {
507+
const messageID = MessageID.ascending()
508+
const error = yield* Effect.flip(MessageV2.getEffect({ sessionID, messageID }))
509+
expect(error).toBeInstanceOf(NotFoundError)
510+
expect(error.message).toBe(`Message not found: ${messageID}`)
511+
}),
512+
),
513+
)
514+
495515
it.instance("scopes by session id", () =>
496516
Effect.gen(function* () {
497517
const session = yield* SessionNs.Service

0 commit comments

Comments
 (0)