fix(session): make message reads effectful (#27291)
This commit is contained in:
@@ -105,7 +105,7 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
|
||||
}
|
||||
|
||||
const page = yield* SessionError.mapStorageNotFound(
|
||||
MessageV2.pageEffect({
|
||||
MessageV2.page({
|
||||
sessionID: ctx.params.sessionID,
|
||||
limit: ctx.query.limit,
|
||||
before: ctx.query.before,
|
||||
@@ -132,7 +132,7 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
|
||||
params: { sessionID: SessionID; messageID: MessageID }
|
||||
}) {
|
||||
return yield* SessionError.mapStorageNotFound(
|
||||
MessageV2.getEffect({ sessionID: ctx.params.sessionID, messageID: ctx.params.messageID }),
|
||||
MessageV2.get({ sessionID: ctx.params.sessionID, messageID: ctx.params.messageID }),
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -919,7 +919,11 @@ export function toModelMessages(
|
||||
return Effect.runPromise(toModelMessagesEffect(input, model, options).pipe(Effect.provide(EffectLogger.layer)))
|
||||
}
|
||||
|
||||
export function page(input: { sessionID: SessionID; limit: number; before?: string }) {
|
||||
export const page = Effect.fn("MessageV2.page")(function* (input: {
|
||||
sessionID: SessionID
|
||||
limit: number
|
||||
before?: string
|
||||
}) {
|
||||
const before = input.before ? cursor.decode(input.before) : undefined
|
||||
const where = before
|
||||
? and(eq(MessageTable.session_id, input.sessionID), older(before))
|
||||
@@ -937,7 +941,7 @@ export function page(input: { sessionID: SessionID; limit: number; before?: stri
|
||||
const row = Database.use((db) =>
|
||||
db.select({ id: SessionTable.id }).from(SessionTable).where(eq(SessionTable.id, input.sessionID)).get(),
|
||||
)
|
||||
if (!row) throw new NotFoundError({ message: `Session not found: ${input.sessionID}` })
|
||||
if (!row) return yield* new NotFoundError({ message: `Session not found: ${input.sessionID}` })
|
||||
return {
|
||||
items: [] as WithParts[],
|
||||
more: false,
|
||||
@@ -954,24 +958,19 @@ export function page(input: { sessionID: SessionID; limit: number; before?: stri
|
||||
more,
|
||||
cursor: more && tail ? cursor.encode({ id: tail.id, time: tail.time_created }) : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
export const pageEffect = Effect.fn("MessageV2.pageEffect")(function* (input: {
|
||||
sessionID: SessionID
|
||||
limit: number
|
||||
before?: string
|
||||
}) {
|
||||
return yield* Effect.try({
|
||||
try: () => page(input),
|
||||
catch: (error) => error,
|
||||
}).pipe(Effect.catch((error) => (NotFoundError.isInstance(error) ? Effect.fail(error) : Effect.die(error))))
|
||||
})
|
||||
|
||||
export function* stream(sessionID: SessionID) {
|
||||
const size = 50
|
||||
let before: string | undefined
|
||||
while (true) {
|
||||
const next = page({ sessionID, limit: size, before })
|
||||
const next = Effect.runSync(
|
||||
page({ sessionID, limit: size, before }).pipe(
|
||||
Effect.catchIf(NotFoundError.isInstance, () =>
|
||||
Effect.succeed({ items: [] as WithParts[], more: false, cursor: undefined }),
|
||||
),
|
||||
),
|
||||
)
|
||||
if (next.items.length === 0) break
|
||||
for (let i = next.items.length - 1; i >= 0; i--) {
|
||||
yield next.items[i]
|
||||
@@ -996,7 +995,7 @@ export function parts(message_id: MessageID) {
|
||||
)
|
||||
}
|
||||
|
||||
export function get(input: { sessionID: SessionID; messageID: MessageID }): WithParts {
|
||||
export const get = Effect.fn("MessageV2.get")(function* (input: { sessionID: SessionID; messageID: MessageID }) {
|
||||
const row = Database.use((db) =>
|
||||
db
|
||||
.select()
|
||||
@@ -1004,21 +1003,11 @@ export function get(input: { sessionID: SessionID; messageID: MessageID }): With
|
||||
.where(and(eq(MessageTable.id, input.messageID), eq(MessageTable.session_id, input.sessionID)))
|
||||
.get(),
|
||||
)
|
||||
if (!row) throw new NotFoundError({ message: `Message not found: ${input.messageID}` })
|
||||
if (!row) return yield* new NotFoundError({ message: `Message not found: ${input.messageID}` })
|
||||
return {
|
||||
info: info(row),
|
||||
parts: parts(input.messageID),
|
||||
}
|
||||
}
|
||||
|
||||
export const getEffect = Effect.fn("MessageV2.getEffect")(function* (input: {
|
||||
sessionID: SessionID
|
||||
messageID: MessageID
|
||||
}) {
|
||||
return yield* Effect.try({
|
||||
try: () => get(input),
|
||||
catch: (error) => error,
|
||||
}).pipe(Effect.catch((error) => (NotFoundError.isInstance(error) ? Effect.fail(error) : Effect.die(error))))
|
||||
})
|
||||
|
||||
export function filterCompacted(msgs: Iterable<WithParts>) {
|
||||
|
||||
@@ -759,14 +759,14 @@ export const layer: Layer.Layer<Service, never, Bus.Service | Storage.Service |
|
||||
|
||||
const messages: Interface["messages"] = Effect.fn("Session.messages")(function* (input) {
|
||||
if (input.limit) {
|
||||
return (yield* MessageV2.pageEffect({ sessionID: input.sessionID, limit: input.limit })).items
|
||||
return (yield* MessageV2.page({ sessionID: input.sessionID, limit: input.limit })).items
|
||||
}
|
||||
|
||||
const size = 50
|
||||
const result = [] as MessageV2.WithParts[]
|
||||
let before: string | undefined
|
||||
while (true) {
|
||||
const page = yield* MessageV2.pageEffect({ sessionID: input.sessionID, limit: size, before })
|
||||
const page = yield* MessageV2.page({ sessionID: input.sessionID, limit: size, before })
|
||||
if (page.items.length === 0) break
|
||||
for (let i = page.items.length - 1; i >= 0; i--) {
|
||||
const item = page.items[i]
|
||||
@@ -817,7 +817,7 @@ export const layer: Layer.Layer<Service, never, Bus.Service | Storage.Service |
|
||||
const size = 50
|
||||
let before: string | undefined
|
||||
while (true) {
|
||||
const page = yield* MessageV2.pageEffect({ sessionID, limit: size, before })
|
||||
const page = yield* MessageV2.page({ sessionID, limit: size, before })
|
||||
if (page.items.length === 0) break
|
||||
for (let i = page.items.length - 1; i >= 0; i--) {
|
||||
const item = page.items[i]
|
||||
|
||||
@@ -86,7 +86,7 @@ export const TaskTool = Tool.define(
|
||||
],
|
||||
}))
|
||||
|
||||
const msg = yield* MessageV2.getEffect({ sessionID: ctx.sessionID, messageID: ctx.messageID }).pipe(Effect.orDie)
|
||||
const msg = yield* MessageV2.get({ sessionID: ctx.sessionID, messageID: ctx.messageID }).pipe(Effect.orDie)
|
||||
if (msg.info.role !== "assistant") return yield* Effect.fail(new Error("Not an assistant message"))
|
||||
|
||||
const model = next.model ?? {
|
||||
|
||||
Reference in New Issue
Block a user