fix(httpapi): expose v2 session not found (#28511)

This commit is contained in:
Shoubhit Dash
2026-05-21 13:27:20 +05:30
committed by GitHub
parent 4d900b2f46
commit b275b12e90
8 changed files with 142 additions and 48 deletions

View File

@@ -2,7 +2,7 @@ import { SessionID } from "@/session/schema"
import { SessionMessage } from "@opencode-ai/core/session-message"
import { Schema } from "effect"
import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
import { InvalidCursorError } from "../../errors"
import { InvalidCursorError, SessionNotFoundError } from "../../errors"
import { V2Authorization } from "../../middleware/authorization"
import { WorkspaceRoutingQueryFields } from "../../middleware/workspace-routing"
@@ -36,7 +36,7 @@ export const MessageGroup = HttpApiGroup.make("v2.message")
next: Schema.String.pipe(Schema.optional),
}),
}).annotate({ identifier: "V2SessionMessagesResponse" }),
error: InvalidCursorError,
error: [InvalidCursorError, SessionNotFoundError],
}).annotateMerge(
OpenApi.annotations({
identifier: "v2.session.messages",

View File

@@ -4,7 +4,7 @@ import { Prompt } from "@opencode-ai/core/session-prompt"
import { SessionV2 } from "@/v2/session"
import { Schema } from "effect"
import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi"
import { InvalidCursorError, InvalidRequestError } from "../../errors"
import { InvalidCursorError, InvalidRequestError, SessionNotFoundError } from "../../errors"
import { V2Authorization } from "../../middleware/authorization"
import { WorkspaceRoutingQuery, WorkspaceRoutingQueryFields } from "../../middleware/workspace-routing"
import { QueryBoolean } from "../query"
@@ -61,6 +61,7 @@ export const SessionGroup = HttpApiGroup.make("v2.session")
delivery: SessionV2.Delivery.pipe(Schema.optional),
}),
success: SessionMessage.Message,
error: SessionNotFoundError,
}).annotateMerge(
OpenApi.annotations({
identifier: "v2.session.prompt",
@@ -74,6 +75,7 @@ export const SessionGroup = HttpApiGroup.make("v2.session")
params: { sessionID: SessionID },
query: WorkspaceRoutingQuery,
success: HttpApiSchema.NoContent,
error: SessionNotFoundError,
}).annotateMerge(
OpenApi.annotations({
identifier: "v2.session.compact",
@@ -87,6 +89,7 @@ export const SessionGroup = HttpApiGroup.make("v2.session")
params: { sessionID: SessionID },
query: WorkspaceRoutingQuery,
success: HttpApiSchema.NoContent,
error: SessionNotFoundError,
}).annotateMerge(
OpenApi.annotations({
identifier: "v2.session.wait",
@@ -100,6 +103,7 @@ export const SessionGroup = HttpApiGroup.make("v2.session")
params: { sessionID: SessionID },
query: WorkspaceRoutingQuery,
success: Schema.Array(SessionMessage.Message),
error: SessionNotFoundError,
}).annotateMerge(
OpenApi.annotations({
identifier: "v2.session.context",

View File

@@ -4,7 +4,7 @@ import { Effect, Schema } from "effect"
import * as DateTime from "effect/DateTime"
import { HttpApiBuilder } from "effect/unstable/httpapi"
import { InstanceHttpApi } from "../../api"
import { InvalidCursorError } from "../../errors"
import { InvalidCursorError, SessionNotFoundError } from "../../errors"
const DefaultMessagesLimit = 50
@@ -47,7 +47,16 @@ export const messageHandlers = HttpApiBuilder.group(InstanceHttpApi, "v2.message
limit: ctx.query.limit ?? DefaultMessagesLimit,
order,
cursor: decoded ? { id: decoded.id, time: decoded.time, direction: decoded.direction } : undefined,
})
}).pipe(
Effect.catchTag("Session.NotFoundError", (error) =>
Effect.fail(
new SessionNotFoundError({
sessionID: error.sessionID,
message: `Session not found: ${error.sessionID}`,
}),
),
),
)
const first = messages[0]
const last = messages.at(-1)
return {

View File

@@ -3,7 +3,7 @@ import { SessionV2 } from "@/v2/session"
import { DateTime, Effect, Option, Schema } from "effect"
import { HttpApiBuilder, HttpApiSchema } from "effect/unstable/httpapi"
import { InstanceHttpApi } from "../../api"
import { InvalidCursorError, InvalidRequestError } from "../../errors"
import { InvalidCursorError, InvalidRequestError, SessionNotFoundError } from "../../errors"
const DefaultSessionsLimit = 50
@@ -137,27 +137,69 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "v2.session
sessionID: ctx.params.sessionID,
prompt: ctx.payload.prompt,
delivery: ctx.payload.delivery ?? SessionV2.DefaultDelivery,
})
}).pipe(
Effect.catchTag("Session.NotFoundError", (error) =>
Effect.fail(
new SessionNotFoundError({
sessionID: error.sessionID,
message: `Session not found: ${error.sessionID}`,
}),
),
),
)
}),
)
.handle(
"compact",
Effect.fn(function* (ctx) {
yield* session.compact(ctx.params.sessionID)
yield* session
.compact(ctx.params.sessionID)
.pipe(
Effect.catchTag("Session.NotFoundError", (error) =>
Effect.fail(
new SessionNotFoundError({
sessionID: error.sessionID,
message: `Session not found: ${error.sessionID}`,
}),
),
),
)
return HttpApiSchema.NoContent.make()
}),
)
.handle(
"wait",
Effect.fn(function* (ctx) {
yield* session.wait(ctx.params.sessionID)
yield* session
.wait(ctx.params.sessionID)
.pipe(
Effect.catchTag("Session.NotFoundError", (error) =>
Effect.fail(
new SessionNotFoundError({
sessionID: error.sessionID,
message: `Session not found: ${error.sessionID}`,
}),
),
),
)
return HttpApiSchema.NoContent.make()
}),
)
.handle(
"context",
Effect.fn(function* (ctx) {
return yield* session.context(ctx.params.sessionID)
return yield* session
.context(ctx.params.sessionID)
.pipe(
Effect.catchTag("Session.NotFoundError", (error) =>
Effect.fail(
new SessionNotFoundError({
sessionID: error.sessionID,
message: `Session not found: ${error.sessionID}`,
}),
),
),
)
}),
)
}),