132 lines
4.1 KiB
Swift
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")
|
|
}
|
|
}
|
|
}
|