Files
steipete--codexbar/Sources/CodexBarCLI/CLIErrorReporting.swift
T
2026-07-13 12:22:33 +08:00

132 lines
4.1 KiB
Swift

import CodexBarCore
import Foundation
enum CLIErrorKind: String, Encodable, Sendable {
case args
case config
case provider
case runtime
}
struct ProviderErrorPayload: Encodable, Sendable {
let code: Int32
let message: String
let kind: CLIErrorKind?
}
extension CodexBarCLI {
static func makeErrorPayload(_ error: Error, kind: CLIErrorKind? = nil) -> ProviderErrorPayload {
ProviderErrorPayload(
code: self.mapError(error).rawValue,
message: error.localizedDescription,
kind: kind)
}
static func makeErrorPayload(code: ExitCode, message: String, kind: CLIErrorKind? = nil) -> ProviderErrorPayload {
ProviderErrorPayload(code: code.rawValue, message: message, kind: kind)
}
static func makeCLIErrorPayload(
message: String,
code: ExitCode,
kind: CLIErrorKind,
pretty: Bool) -> String?
{
let payload = ProviderPayload(
providerID: "cli",
account: nil,
version: nil,
source: "cli",
status: nil,
usage: nil,
credits: nil,
antigravityPlanInfo: nil,
openaiDashboard: nil,
error: ProviderErrorPayload(code: code.rawValue, message: message, kind: kind))
return self.encodeJSON([payload], pretty: pretty)
}
static func makeProviderErrorPayload(
provider: UsageProvider,
account: String?,
cacheAccountKey: String? = nil,
source: String,
status: ProviderStatusPayload?,
error: Error,
kind: CLIErrorKind = .provider) -> ProviderPayload
{
ProviderPayload(
provider: provider,
account: account,
cacheAccountKey: cacheAccountKey,
version: nil,
source: source,
status: status,
usage: nil,
credits: nil,
antigravityPlanInfo: nil,
openaiDashboard: nil,
error: self.makeErrorPayload(error, kind: kind))
}
static func encodeJSON(_ payload: some Encodable, pretty: Bool) -> String? {
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
encoder.outputFormatting = pretty ? [.prettyPrinted, .sortedKeys] : []
guard let data = try? encoder.encode(payload) else { return nil }
return String(data: data, encoding: .utf8)
}
static func printJSON(_ payload: some Encodable, pretty: Bool) {
if let output = self.encodeJSON(payload, pretty: pretty) {
print(output)
}
}
static func exit(
code: ExitCode,
message: String? = nil,
output: CLIOutputPreferences? = nil,
kind: CLIErrorKind = .runtime) -> Never
{
if self.shouldPrintExitError(code: code, message: message) {
if let output, output.usesJSONOutput {
let payload = self.makeCLIErrorPayload(
message: message ?? "",
code: code,
kind: kind,
pretty: output.pretty)
if let payload {
print(payload)
}
} else if let message {
self.writeStderr("\(message)\n")
}
}
platformExit(code.rawValue)
}
static func shouldPrintExitError(code: ExitCode, message: String?) -> Bool {
code != .success && message != nil
}
static func printError(_ error: Error, output: CLIOutputPreferences, kind: CLIErrorKind = .runtime) {
if output.usesJSONOutput {
let payload = ProviderPayload(
providerID: "cli",
account: nil,
version: nil,
source: "cli",
status: nil,
usage: nil,
credits: nil,
antigravityPlanInfo: nil,
openaiDashboard: nil,
error: self.makeErrorPayload(error, kind: kind))
self.printJSON([payload], pretty: output.pretty)
} else {
self.writeStderr("Error: \(error.localizedDescription)\n")
}
}
}