Something went wrong. Try again.
opencode v2 mirror
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146import { isRecord } from "./record"
type ConfigIssue = { message: string; path: string[] }
export function cliErrorMessage(input: unknown): string | undefined { if (input instanceof Error && isRecord(input.cause) && "body" in input.cause) { const formatted = cliErrorMessage(input.cause.body) if (formatted) return formatted }
if (tagged(input, "CliError")) { if (typeof input.exitCode === "number") process.exitCode = input.exitCode return field(input, "message") ?? "" } if (tagged(input, "AccountServiceError") || tagged(input, "AccountTransportError")) { return field(input, "message") ?? "" }
const model = configData(input, "ProviderModelNotFoundError") if (model) { const suggestions = Array.isArray(model.suggestions) ? model.suggestions.filter((item): item is string => typeof item === "string") : [] return [ `Model not found: ${field(model, "providerID")}/${field(model, "modelID")}`, ...(suggestions.length ? ["Did you mean: " + suggestions.join(", ")] : []), "Try: `opencode models` to list available models", "Or check your config (opencode.json) provider/model names", ].join("\n") }
const provider = configData(input, "ProviderInitError") if (provider) return `Failed to initialize provider "${field(provider, "providerID")}". Check credentials and configuration.`
const json = configData(input, "ConfigJsonError") if (json) { const message = field(json, "message") return `Config file at ${field(json, "path")} is not valid JSON(C)` + (message ? `: ${message}` : "") }
const directory = configData(input, "ConfigDirectoryTypoError") if (directory) { return `Directory "${field(directory, "dir")}" in ${field(directory, "path")} is not valid. Rename the directory to "${field(directory, "suggestion")}" or remove it. This is a common typo.` }
const frontmatter = configData(input, "ConfigFrontmatterError") if (frontmatter) return field(frontmatter, "message") ?? ""
const invalid = configData(input, "ConfigInvalidError") if (invalid) { const path = field(invalid, "path") const message = field(invalid, "message") const issues = Array.isArray(invalid.issues) ? invalid.issues.filter((issue): issue is ConfigIssue => { return ( isRecord(issue) && typeof issue.message === "string" && Array.isArray(issue.path) && issue.path.every((item) => typeof item === "string") ) }) : [] return [ `Configuration is invalid${path && path !== "config" ? ` at ${path}` : ""}` + (message ? `: ${message}` : ""), ...issues.map((issue) => "↳ " + issue.message + " " + issue.path.join(".")), ].join("\n") }
if (tagged(input, "UICancelledError") || named(input, "UICancelledError")) return "" if (isRecord(input) && named(input, "MCPFailed")) { const name = isRecord(input.data) ? field(input.data, "name") : undefined return `MCP server "${name}" failed. Note, opencode does not support MCP authentication yet.` } return undefined}
function tagged(input: unknown, tag: string): input is Record<string, unknown> { return isRecord(input) && input._tag === tag}
function named(input: unknown, name: string) { return isRecord(input) && (input.name === name || input._tag === name)}
function configData(input: unknown, tag: string) { if (!isRecord(input)) return undefined if (input.name === tag && isRecord(input.data)) return input.data if (input._tag === tag) return input return undefined}
function field(input: Record<string, unknown>, key: string) { return typeof input[key] === "string" ? input[key] : undefined}
export function errorFormat(error: unknown): string { if (error instanceof Error) { return error.stack ?? `${error.name}: ${error.message}` }
if (typeof error === "object" && error !== null) { try { const json = JSON.stringify(error, null, 2) // Plain objects whose own properties are all non-enumerable (or empty) // serialize to "{}", which prints as a useless bare `{}` on stderr. // Fall back to a custom toString first, then to ctor name + own prop names. if (json === "{}") { const str = String(error) if (str && str !== "[object Object]") return str const ctor = error.constructor?.name const prefix = ctor && ctor !== "Object" ? ctor : "Error" const names = Object.getOwnPropertyNames(error) return names.length === 0 ? `${prefix} (no message)` : `${prefix} { ${names.join(", ")} }` } return json } catch { return "Unexpected error (unserializable)" } }
return String(error)}
export function errorMessage(error: unknown): string { if (error instanceof Error) { if (error.message) return error.message if (error.name) return error.name }
if (isRecord(error) && typeof error.message === "string" && error.message) { return error.message }
if (isRecord(error) && isRecord(error.data) && typeof error.data.message === "string" && error.data.message) { return error.data.message }
const text = String(error) if (text && text !== "[object Object]") return text
const formatted = errorFormat(error) if (formatted) return formatted return "unknown error"}