Skip to content

Commit 4be2e20

Browse files
okuyam2yYoshiaki Okuyama
authored andcommitted
fix: replace as-any casts with ErrorWithStatus interface
Define a file-local ErrorWithStatus interface matching upstream's pattern (FetchDecompressionError) to eliminate all as-any casts. Separate direct property extraction from JSON message fallback to avoid double-parsing.
1 parent 6489b3f commit 4be2e20

1 file changed

Lines changed: 28 additions & 22 deletions

File tree

packages/opencode/src/session/message-v2.ts

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ interface FetchDecompressionError extends Error {
2222
path: string
2323
}
2424

25+
/** Common shapes for non-APICallError provider errors carrying HTTP status */
26+
interface ErrorWithStatus {
27+
status?: number
28+
statusCode?: number
29+
response?: { status?: number; statusCode?: number }
30+
message?: string
31+
}
32+
2533
export namespace MessageV2 {
2634
export function isMedia(mime: string) {
2735
return mime.startsWith("image/") || mime === "application/pdf"
@@ -991,28 +999,27 @@ export namespace MessageV2 {
991999
).toObject()
9921000
case e instanceof Error: {
9931001
// Non-APICallError with HTTP status — treat 5xx as retryable.
1002+
const typed = e as Error & ErrorWithStatus
9941003
const code =
995-
(e as any).status ?? (e as any).statusCode ??
996-
(e as any).response?.status ?? (e as any).response?.statusCode ??
997-
(() => {
998-
try {
999-
const obj = JSON.parse(e.message)
1000-
return obj?.status ?? obj?.statusCode
1001-
} catch {
1002-
return undefined
1003-
}
1004-
})()
1005-
if (typeof code === "number" && code >= 500) {
1006-
let msg = e.message
1007-
try {
1008-
const obj = JSON.parse(msg)
1009-
if (typeof obj?.message === "string") msg = obj.message
1010-
} catch {}
1004+
typed.status ?? typed.statusCode ??
1005+
typed.response?.status ?? typed.response?.statusCode
1006+
if (typeof code === "number" && code >= 500)
10111007
return new MessageV2.APIError(
1012-
{ message: msg, statusCode: code, isRetryable: true },
1008+
{ message: e.message, statusCode: code, isRetryable: true },
10131009
{ cause: e },
10141010
).toObject()
1015-
}
1011+
// Fallback: status may be embedded in a JSON error message.
1012+
try {
1013+
const obj = JSON.parse(e.message) as ErrorWithStatus
1014+
const jsonCode = obj?.status ?? obj?.statusCode
1015+
if (typeof jsonCode === "number" && jsonCode >= 500) {
1016+
const msg = typeof obj?.message === "string" ? obj.message : e.message
1017+
return new MessageV2.APIError(
1018+
{ message: msg, statusCode: jsonCode, isRetryable: true },
1019+
{ cause: e },
1020+
).toObject()
1021+
}
1022+
} catch {}
10161023
return new NamedError.Unknown({ message: e.message }, { cause: e }).toObject()
10171024
}
10181025
default:
@@ -1042,13 +1049,12 @@ export namespace MessageV2 {
10421049
} catch {}
10431050
// Plain-object 5xx — treat as retryable.
10441051
if (typeof e === "object" && e !== null) {
1045-
const code =
1046-
(e as any).status ?? (e as any).statusCode ??
1047-
(e as any).response?.status ?? (e as any).response?.statusCode
1052+
const typed = e as ErrorWithStatus
1053+
const code = typed.status ?? typed.statusCode ?? typed.response?.status ?? typed.response?.statusCode
10481054
if (typeof code === "number" && code >= 500)
10491055
return new MessageV2.APIError(
10501056
{
1051-
message: typeof (e as any).message === "string" ? (e as any).message : JSON.stringify(e),
1057+
message: typeof typed.message === "string" ? typed.message : JSON.stringify(e),
10521058
statusCode: code,
10531059
isRetryable: true,
10541060
},

0 commit comments

Comments
 (0)