mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 10:30:01 +08:00
fix(client): include the detail in client error messages (#50929)
This commit is contained in:
@@ -221,7 +221,7 @@ describe("mini command", () => {
|
||||
expect(JSON.parse(result.stdout)).toMatchObject({
|
||||
type: "error",
|
||||
sessionID: "",
|
||||
error: { type: "unknown", message: "UnexpectedStatus" },
|
||||
error: { type: "unknown", message: "UnexpectedStatus: 500" },
|
||||
})
|
||||
} finally {
|
||||
server.stop(true)
|
||||
|
||||
@@ -9,8 +9,9 @@ export class ClientError extends Error {
|
||||
override readonly name = "ClientError"
|
||||
constructor(
|
||||
readonly reason: ClientErrorReason,
|
||||
options?: ErrorOptions,
|
||||
options?: ErrorOptions & { readonly detail?: string | null },
|
||||
) {
|
||||
super(reason, options)
|
||||
const detail = options?.detail ?? (options?.cause instanceof Error ? options.cause.message : undefined)
|
||||
super(detail ? `${reason}: ${detail}` : reason, options)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +335,7 @@ export function make(options: ClientOptions) {
|
||||
try {
|
||||
await response.body?.cancel()
|
||||
} catch {}
|
||||
throw new ClientError("UnexpectedStatus", { cause: { status: response.status } })
|
||||
throw new ClientError("UnexpectedStatus", { cause: { status: response.status }, detail: String(response.status) })
|
||||
}
|
||||
|
||||
const request = async <A>(descriptor: RequestDescriptor, requestOptions?: RequestOptions): Promise<A> => {
|
||||
@@ -359,7 +359,7 @@ export function make(options: ClientOptions) {
|
||||
try {
|
||||
await response.body?.cancel()
|
||||
} catch {}
|
||||
throw new ClientError("UnsupportedContentType")
|
||||
throw new ClientError("UnsupportedContentType", { detail: response.headers.get("content-type") })
|
||||
}
|
||||
if (response.body === null) throw new ClientError("MalformedResponse")
|
||||
const reader = response.body.getReader()
|
||||
@@ -2185,7 +2185,7 @@ async function json(response: Response): Promise<unknown> {
|
||||
try {
|
||||
await response.body?.cancel()
|
||||
} catch {}
|
||||
throw new ClientError("UnsupportedContentType")
|
||||
throw new ClientError("UnsupportedContentType", { detail: response.headers.get("content-type") })
|
||||
}
|
||||
let text: string
|
||||
try {
|
||||
|
||||
@@ -191,6 +191,27 @@ test("declared errors with a data envelope read the nested message", async () =>
|
||||
expect(error).toMatchObject({ name: "WorktreeError", data: { message: "Worktree directory unavailable" } })
|
||||
})
|
||||
|
||||
test("client errors keep the reason and describe the failure in the message", async () => {
|
||||
const failure = (fetch: () => Promise<Response>) =>
|
||||
OpenCode.make({ baseUrl: "http://localhost:3000", fetch })
|
||||
.session.list()
|
||||
.catch((cause: unknown) => cause)
|
||||
expect(await failure(() => Promise.reject(new TypeError("Unable to connect")))).toMatchObject({
|
||||
reason: "Transport",
|
||||
message: "Transport: Unable to connect",
|
||||
})
|
||||
expect(await failure(async () => new Response("", { status: 500 }))).toMatchObject({
|
||||
reason: "UnexpectedStatus",
|
||||
message: "UnexpectedStatus: 500",
|
||||
})
|
||||
expect(await failure(async () => new Response("<html>", { headers: { "content-type": "text/html" } }))).toMatchObject(
|
||||
{
|
||||
reason: "UnsupportedContentType",
|
||||
message: "UnsupportedContentType: text/html",
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
test("project.update uses the global project contract", async () => {
|
||||
let request: Request | undefined
|
||||
const project = {
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user