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
@@ -675,22 +675,14 @@ const scenarios: Scenario[] = [
path: route("/api/session/{sessionID}/context", { sessionID: "ses_httpapi_missing" }),
headers: ctx.headers(),
}))
.json(200, array, "none"),
.json(404, object, "status"),
http.protected
.get("/api/session/{sessionID}/message", "v2.session.messages")
.at((ctx) => ({
path: route("/api/session/{sessionID}/message", { sessionID: "ses_httpapi_missing" }),
headers: ctx.headers(),
}))
.json(
200,
(body) => {
object(body)
array(body.items)
object(body.cursor)
},
"none",
),
.json(404, object, "status"),
http.protected
.get("/api/session/{sessionID}/message", "v2.session.messages.params")
.at((ctx) => ({
@@ -700,15 +692,7 @@ const scenarios: Scenario[] = [
})}`,
headers: ctx.headers(),
}))
.json(
200,
(body) => {
object(body)
array(body.items)
object(body.cursor)
},
"none",
),
.json(404, object, "status"),
http.protected
.get("/api/session/{sessionID}/message", "v2.session.messages.cursor")
.at((ctx) => ({
@@ -719,15 +703,7 @@ const scenarios: Scenario[] = [
})}`,
headers: ctx.headers(),
}))
.json(
200,
(body) => {
object(body)
array(body.items)
object(body.cursor)
},
"none",
),
.json(404, object, "status"),
http.protected
.get("/api/session/{sessionID}/message", "v2.session.messages.cursor.invalid")
.at((ctx) => ({
@@ -752,14 +728,14 @@ const scenarios: Scenario[] = [
path: route("/api/session/{sessionID}/compact", { sessionID: "ses_httpapi_missing" }),
headers: ctx.headers(),
}))
.status(204, undefined, "none"),
.status(404, undefined, "status"),
http.protected
.post("/api/session/{sessionID}/wait", "v2.session.wait")
.at((ctx) => ({
path: route("/api/session/{sessionID}/wait", { sessionID: "ses_httpapi_missing" }),
headers: ctx.headers(),
}))
.status(204, undefined, "none"),
.status(404, undefined, "status"),
http.protected
.get("/session", "session.list")
.seeded((ctx) => ctx.session({ title: "List me" }))
@@ -99,4 +99,20 @@ describe("PublicApi OpenAPI v2 errors", () => {
"ServiceUnavailableError",
)
})
test("documents v2 session not-found errors", () => {
const spec = OpenApi.fromApi(PublicApi) as OpenApiSpec
for (const route of [
["post", "/api/session/{sessionID}/prompt"],
["post", "/api/session/{sessionID}/compact"],
["post", "/api/session/{sessionID}/wait"],
["get", "/api/session/{sessionID}/context"],
["get", "/api/session/{sessionID}/message"],
] as const) {
expect(componentName(responseRef(spec.paths[route[1]]?.[route[0]]?.responses?.["404"]) ?? "")).toBe(
"SessionNotFoundError",
)
}
})
})
@@ -402,6 +402,46 @@ describe("session HttpApi", () => {
{ git: true, config: { formatter: false, lsp: false } },
)
it.instance(
"returns v2 public not found errors for missing sessions",
() =>
Effect.gen(function* () {
const test = yield* TestInstance
const headers = { "x-opencode-directory": test.directory }
const missing = SessionID.descending()
const expected = {
_tag: "SessionNotFoundError",
sessionID: missing,
message: `Session not found: ${missing}`,
}
const messages = yield* request(`/api/session/${missing}/message`, { headers })
expect(messages.status).toBe(404)
expect(yield* responseJson(messages)).toEqual(expected)
const context = yield* request(`/api/session/${missing}/context`, { headers })
expect(context.status).toBe(404)
expect(yield* responseJson(context)).toEqual(expected)
const compact = yield* request(`/api/session/${missing}/compact`, { method: "POST", headers })
expect(compact.status).toBe(404)
expect(yield* responseJson(compact)).toEqual(expected)
const wait = yield* request(`/api/session/${missing}/wait`, { method: "POST", headers })
expect(wait.status).toBe(404)
expect(yield* responseJson(wait)).toEqual(expected)
const prompt = yield* request(`/api/session/${missing}/prompt`, {
method: "POST",
headers: { ...headers, "content-type": "application/json" },
body: JSON.stringify({ prompt: { text: "hello" } }),
})
expect(prompt.status).toBe(404)
expect(yield* responseJson(prompt)).toEqual(expected)
}),
{ git: true, config: { formatter: false, lsp: false } },
)
it.instance(
"serves sessions with migrated summary diffs missing file details",
() =>