Something went wrong. Try again.
opencode v2 mirror
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116export type ConfigInvalidError = { name: "ConfigInvalidError" data: { path?: string message?: string issues?: Array<{ message: string; path: string[] }> }}
export type ProviderModelNotFoundError = { name: "ProviderModelNotFoundError" data: { providerID: string modelID: string suggestions?: string[] }}
type Translator = (key: string, vars?: Record<string, string | number>) => string
function tr(translator: Translator | undefined, key: string, text: string, vars?: Record<string, string | number>) { if (!translator) return text const out = translator(key, vars) if (!out || out === key) return text return out}
export function formatServerError(error: unknown, translate?: Translator, fallback?: string) { const unwrapped = unwrapNamedError(error) if (isConfigInvalidErrorLike(unwrapped)) return parseReadableConfigInvalidError(unwrapped, translate) if (isProviderModelNotFoundErrorLike(unwrapped)) return parseReadableProviderModelNotFoundError(unwrapped, translate) if ( typeof unwrapped === "object" && unwrapped !== null && "message" in unwrapped && typeof unwrapped.message === "string" && unwrapped.message ) return unwrapped.message if (error instanceof Error && error.message) return error.message if (typeof error === "string" && error) return error if (fallback) return fallback return tr(translate, "error.chain.unknown", "Unknown error")}
function unwrapNamedError(error: unknown): unknown { if (!(error instanceof Error) || !error.cause || typeof error.cause !== "object") return error if ("body" in error.cause) return (error.cause as Record<string, unknown>).body return error.cause}
// Client-synthesized session not-found errors share one constructor and// predicate so the message contract cannot drift between route session// resolution (session-resolution.ts) and not-found fallback matching (session.tsx).const sessionNotFoundMessage = (sessionID: string) => `Session not found: ${sessionID}`
export function sessionNotFoundError(sessionID: string) { return new Error(sessionNotFoundMessage(sessionID))}
export function isLocalSessionNotFoundError(error: unknown, sessionID: string) { return error instanceof Error && error.message === sessionNotFoundMessage(sessionID)}
export function isSessionNotFoundError(error: unknown, sessionID: string) { const unwrapped = unwrapNamedError(error) if (typeof unwrapped !== "object" || unwrapped === null) return false const value = unwrapped as Record<string, unknown> return value._tag === "SessionNotFoundError" && value.sessionID === sessionID}
function isConfigInvalidErrorLike(error: unknown): error is ConfigInvalidError { if (typeof error !== "object" || error === null) return false const o = error as Record<string, unknown> return o.name === "ConfigInvalidError" && typeof o.data === "object" && o.data !== null}
function isProviderModelNotFoundErrorLike(error: unknown): error is ProviderModelNotFoundError { if (typeof error !== "object" || error === null) return false const o = error as Record<string, unknown> return o.name === "ProviderModelNotFoundError" && typeof o.data === "object" && o.data !== null}
export function parseReadableConfigInvalidError(errorInput: ConfigInvalidError, translator?: Translator) { const file = errorInput.data.path && errorInput.data.path !== "config" ? errorInput.data.path : "config" const detail = errorInput.data.message?.trim() ?? "" const issues = (errorInput.data.issues ?? []) .map((issue) => { const msg = issue.message.trim() if (!issue.path.length) return msg return `${issue.path.join(".")}: ${msg}` }) .filter(Boolean) const msg = issues.length ? issues.join("\n") : detail if (!msg) return tr(translator, "error.chain.configInvalid", `Config file at ${file} is invalid`, { path: file }) return tr(translator, "error.chain.configInvalidWithMessage", `Config file at ${file} is invalid: ${msg}`, { path: file, message: msg, })}
function parseReadableProviderModelNotFoundError(errorInput: ProviderModelNotFoundError, translator?: Translator) { const p = errorInput.data.providerID.trim() const m = errorInput.data.modelID.trim() const list = (errorInput.data.suggestions ?? []).map((v) => v.trim()).filter(Boolean) const body = tr(translator, "error.chain.modelNotFound", `Model not found: ${p}/${m}`, { provider: p, model: m }) const tail = tr(translator, "error.chain.checkConfig", "Check your config (opencode.json) provider/model names") if (list.length) { const suggestions = list.slice(0, 5).join(", ") return [body, tr(translator, "error.chain.didYouMean", `Did you mean: ${suggestions}`, { suggestions }), tail].join( "\n", ) } return [body, tail].join("\n")}