fix(httpapi): expose v2 catalog errors (#28498)

This commit is contained in:
Shoubhit Dash
2026-05-21 00:53:35 +05:30
committed by GitHub
parent 7690481fc1
commit 4308dd75fb
8 changed files with 82 additions and 14 deletions

View File

@@ -98,12 +98,14 @@ function assistant(id: string) {
} satisfies SdkEvent
}
function feed<T>() {
const StreamClosed = undefined as never
function feed<T, R = never>(returnValue: R = StreamClosed) {
const list: T[] = []
let done = false
let wake: (() => void) | undefined
const wrapped = (async function* () {
const wrapped = (async function* (): AsyncGenerator<T, R, unknown> {
while (!done || list.length > 0) {
if (list.length === 0) {
await new Promise<void>((resolve) => {
@@ -119,6 +121,7 @@ function feed<T>() {
yield next
}
return returnValue as R
})()
return {
@@ -166,10 +169,11 @@ function globalSse(stream: GlobalEventStream) {
}
function wrapGlobalStream(stream: EventStream): GlobalEventStream {
return (async function* () {
return (async function* (): GlobalEventStream {
for await (const event of stream) {
yield globalEvent(event)
}
return StreamClosed
})()
}

View File

@@ -274,6 +274,26 @@ function setEnvScoped(key: string, value: string) {
}
describe("provider HttpApi", () => {
it.instance.skip(
"returns public v2 provider not found errors",
Effect.gen(function* () {
const instance = yield* TestInstance
const response = yield* Effect.promise(() =>
Promise.resolve(
app().request("/api/provider/missing", { headers: { "x-opencode-directory": instance.directory } }),
),
)
expect(response.status).toBe(404)
expect(yield* Effect.promise(() => response.json())).toEqual({
_tag: "ProviderNotFoundError",
providerID: "missing",
message: "Provider not found: missing",
})
}),
projectOptions,
)
it.instance(
"serves OAuth authorize response shapes",
Effect.gen(function* () {

View File

@@ -61,9 +61,9 @@ describe("PublicApi OpenAPI v2 errors", () => {
return ref ? [`${route.method.toUpperCase()} ${route.path} ${status} ${componentName(ref)}`] : []
}),
)
.filter((entry) => entry.includes("BadRequestError") || entry.includes("NotFoundError"))
.filter((entry) => entry.endsWith(" BadRequestError") || entry.endsWith(" NotFoundError"))
expect(refs).toEqual(["GET /api/provider/{providerID} 404 NotFoundError"])
expect(refs).toEqual([])
})
test("new /api endpoint errors cannot use built-in components without an explicit allowlist", () => {
@@ -82,4 +82,21 @@ describe("PublicApi OpenAPI v2 errors", () => {
expect(builtInEndpointErrors).toEqual(allowedV2BuiltInEndpointErrors)
})
test("documents v2 provider and model catalog errors", () => {
const spec = OpenApi.fromApi(PublicApi) as OpenApiSpec
expect(componentName(responseRef(spec.paths["/api/provider"]?.get?.responses?.["503"]) ?? "")).toBe(
"ServiceUnavailableError",
)
expect(componentName(responseRef(spec.paths["/api/model"]?.get?.responses?.["503"]) ?? "")).toBe(
"ServiceUnavailableError",
)
expect(componentName(responseRef(spec.paths["/api/provider/{providerID}"]?.get?.responses?.["404"]) ?? "")).toBe(
"ProviderNotFoundError",
)
expect(componentName(responseRef(spec.paths["/api/provider/{providerID}"]?.get?.responses?.["503"]) ?? "")).toBe(
"ServiceUnavailableError",
)
})
})