Skip to content

Commit ccf93f3

Browse files
authored
fix(session): make message reads effectful (anomalyco#27291)
1 parent 4b04171 commit ccf93f3

7 files changed

Lines changed: 60 additions & 99 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
105105
}
106106

107107
const page = yield* SessionError.mapStorageNotFound(
108-
MessageV2.pageEffect({
108+
MessageV2.page({
109109
sessionID: ctx.params.sessionID,
110110
limit: ctx.query.limit,
111111
before: ctx.query.before,
@@ -132,7 +132,7 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
132132
params: { sessionID: SessionID; messageID: MessageID }
133133
}) {
134134
return yield* SessionError.mapStorageNotFound(
135-
MessageV2.getEffect({ sessionID: ctx.params.sessionID, messageID: ctx.params.messageID }),
135+
MessageV2.get({ sessionID: ctx.params.sessionID, messageID: ctx.params.messageID }),
136136
)
137137
})
138138

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

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,11 @@ export function toModelMessages(
919919
return Effect.runPromise(toModelMessagesEffect(input, model, options).pipe(Effect.provide(EffectLogger.layer)))
920920
}
921921

922-
export function page(input: { sessionID: SessionID; limit: number; before?: string }) {
922+
export const page = Effect.fn("MessageV2.page")(function* (input: {
923+
sessionID: SessionID
924+
limit: number
925+
before?: string
926+
}) {
923927
const before = input.before ? cursor.decode(input.before) : undefined
924928
const where = before
925929
? and(eq(MessageTable.session_id, input.sessionID), older(before))
@@ -937,7 +941,7 @@ export function page(input: { sessionID: SessionID; limit: number; before?: stri
937941
const row = Database.use((db) =>
938942
db.select({ id: SessionTable.id }).from(SessionTable).where(eq(SessionTable.id, input.sessionID)).get(),
939943
)
940-
if (!row) throw new NotFoundError({ message: `Session not found: ${input.sessionID}` })
944+
if (!row) return yield* new NotFoundError({ message: `Session not found: ${input.sessionID}` })
941945
return {
942946
items: [] as WithParts[],
943947
more: false,
@@ -954,24 +958,19 @@ export function page(input: { sessionID: SessionID; limit: number; before?: stri
954958
more,
955959
cursor: more && tail ? cursor.encode({ id: tail.id, time: tail.time_created }) : undefined,
956960
}
957-
}
958-
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))))
968961
})
969962

970963
export function* stream(sessionID: SessionID) {
971964
const size = 50
972965
let before: string | undefined
973966
while (true) {
974-
const next = page({ sessionID, limit: size, before })
967+
const next = Effect.runSync(
968+
page({ sessionID, limit: size, before }).pipe(
969+
Effect.catchIf(NotFoundError.isInstance, () =>
970+
Effect.succeed({ items: [] as WithParts[], more: false, cursor: undefined }),
971+
),
972+
),
973+
)
975974
if (next.items.length === 0) break
976975
for (let i = next.items.length - 1; i >= 0; i--) {
977976
yield next.items[i]
@@ -996,29 +995,19 @@ export function parts(message_id: MessageID) {
996995
)
997996
}
998997

999-
export function get(input: { sessionID: SessionID; messageID: MessageID }): WithParts {
998+
export const get = Effect.fn("MessageV2.get")(function* (input: { sessionID: SessionID; messageID: MessageID }) {
1000999
const row = Database.use((db) =>
10011000
db
10021001
.select()
10031002
.from(MessageTable)
10041003
.where(and(eq(MessageTable.id, input.messageID), eq(MessageTable.session_id, input.sessionID)))
10051004
.get(),
10061005
)
1007-
if (!row) throw new NotFoundError({ message: `Message not found: ${input.messageID}` })
1006+
if (!row) return yield* new NotFoundError({ message: `Message not found: ${input.messageID}` })
10081007
return {
10091008
info: info(row),
10101009
parts: parts(input.messageID),
10111010
}
1012-
}
1013-
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))))
10221011
})
10231012

10241013
export function filterCompacted(msgs: Iterable<WithParts>) {

packages/opencode/src/session/session.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -759,14 +759,14 @@ export const layer: Layer.Layer<Service, never, Bus.Service | Storage.Service |
759759

760760
const messages: Interface["messages"] = Effect.fn("Session.messages")(function* (input) {
761761
if (input.limit) {
762-
return (yield* MessageV2.pageEffect({ sessionID: input.sessionID, limit: input.limit })).items
762+
return (yield* MessageV2.page({ sessionID: input.sessionID, limit: input.limit })).items
763763
}
764764

765765
const size = 50
766766
const result = [] as MessageV2.WithParts[]
767767
let before: string | undefined
768768
while (true) {
769-
const page = yield* MessageV2.pageEffect({ sessionID: input.sessionID, limit: size, before })
769+
const page = yield* MessageV2.page({ sessionID: input.sessionID, limit: size, before })
770770
if (page.items.length === 0) break
771771
for (let i = page.items.length - 1; i >= 0; i--) {
772772
const item = page.items[i]
@@ -817,7 +817,7 @@ export const layer: Layer.Layer<Service, never, Bus.Service | Storage.Service |
817817
const size = 50
818818
let before: string | undefined
819819
while (true) {
820-
const page = yield* MessageV2.pageEffect({ sessionID, limit: size, before })
820+
const page = yield* MessageV2.page({ sessionID, limit: size, before })
821821
if (page.items.length === 0) break
822822
for (let i = page.items.length - 1; i >= 0; i--) {
823823
const item = page.items[i]

packages/opencode/src/tool/task.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export const TaskTool = Tool.define(
8686
],
8787
}))
8888

89-
const msg = yield* MessageV2.getEffect({ sessionID: ctx.sessionID, messageID: ctx.messageID }).pipe(Effect.orDie)
89+
const msg = yield* MessageV2.get({ sessionID: ctx.sessionID, messageID: ctx.messageID }).pipe(Effect.orDie)
9090
if (msg.info.role !== "assistant") return yield* Effect.fail(new Error("Not an assistant message"))
9191

9292
const model = next.model ?? {

0 commit comments

Comments
 (0)