refactor: simplify cron job editor payloads
This commit is contained in:
@@ -61,19 +61,60 @@ extension CronJobEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildPayload() throws -> [String: AnyCodable] {
|
func buildPayload() throws -> [String: AnyCodable] {
|
||||||
let name = self.name.trimmingCharacters(in: .whitespacesAndNewlines)
|
let name = try self.requireName()
|
||||||
|
let description = self.trimmed(self.description)
|
||||||
|
let agentId = self.trimmed(self.agentId)
|
||||||
|
let schedule = try self.buildSchedule()
|
||||||
|
let payload = try self.buildSelectedPayload()
|
||||||
|
|
||||||
|
try self.validateSessionTarget(payload)
|
||||||
|
try self.validatePayloadRequiredFields(payload)
|
||||||
|
|
||||||
|
var root: [String: Any] = [
|
||||||
|
"name": name,
|
||||||
|
"enabled": self.enabled,
|
||||||
|
"schedule": schedule,
|
||||||
|
"sessionTarget": self.sessionTarget.rawValue,
|
||||||
|
"wakeMode": self.wakeMode.rawValue,
|
||||||
|
"payload": payload,
|
||||||
|
]
|
||||||
|
self.applyDeleteAfterRun(to: &root)
|
||||||
|
if !description.isEmpty { root["description"] = description }
|
||||||
|
if !agentId.isEmpty {
|
||||||
|
root["agentId"] = agentId
|
||||||
|
} else if self.job?.agentId != nil {
|
||||||
|
root["agentId"] = NSNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.sessionTarget == .isolated {
|
||||||
|
let trimmed = self.postPrefix.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
root["isolation"] = [
|
||||||
|
"postToMainPrefix": trimmed.isEmpty ? "Cron" : trimmed,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return root.mapValues { AnyCodable($0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
func trimmed(_ value: String) -> String {
|
||||||
|
value.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireName() throws -> String {
|
||||||
|
let name = self.trimmed(self.name)
|
||||||
if name.isEmpty {
|
if name.isEmpty {
|
||||||
throw NSError(
|
throw NSError(
|
||||||
domain: "Cron",
|
domain: "Cron",
|
||||||
code: 0,
|
code: 0,
|
||||||
userInfo: [NSLocalizedDescriptionKey: "Name is required."])
|
userInfo: [NSLocalizedDescriptionKey: "Name is required."])
|
||||||
}
|
}
|
||||||
let description = self.description.trimmingCharacters(in: .whitespacesAndNewlines)
|
return name
|
||||||
let agentId = self.agentId.trimmingCharacters(in: .whitespacesAndNewlines)
|
}
|
||||||
let schedule: [String: Any]
|
|
||||||
|
func buildSchedule() throws -> [String: Any] {
|
||||||
switch self.scheduleKind {
|
switch self.scheduleKind {
|
||||||
case .at:
|
case .at:
|
||||||
schedule = ["kind": "at", "atMs": Int(self.atDate.timeIntervalSince1970 * 1000)]
|
return ["kind": "at", "atMs": Int(self.atDate.timeIntervalSince1970 * 1000)]
|
||||||
case .every:
|
case .every:
|
||||||
guard let ms = Self.parseDurationMs(self.everyText) else {
|
guard let ms = Self.parseDurationMs(self.everyText) else {
|
||||||
throw NSError(
|
throw NSError(
|
||||||
@@ -81,34 +122,35 @@ extension CronJobEditor {
|
|||||||
code: 0,
|
code: 0,
|
||||||
userInfo: [NSLocalizedDescriptionKey: "Invalid every duration (use 10m, 1h, 1d)."])
|
userInfo: [NSLocalizedDescriptionKey: "Invalid every duration (use 10m, 1h, 1d)."])
|
||||||
}
|
}
|
||||||
schedule = ["kind": "every", "everyMs": ms]
|
return ["kind": "every", "everyMs": ms]
|
||||||
case .cron:
|
case .cron:
|
||||||
let expr = self.cronExpr.trimmingCharacters(in: .whitespacesAndNewlines)
|
let expr = self.trimmed(self.cronExpr)
|
||||||
if expr.isEmpty {
|
if expr.isEmpty {
|
||||||
throw NSError(
|
throw NSError(
|
||||||
domain: "Cron",
|
domain: "Cron",
|
||||||
code: 0,
|
code: 0,
|
||||||
userInfo: [NSLocalizedDescriptionKey: "Cron expression is required."])
|
userInfo: [NSLocalizedDescriptionKey: "Cron expression is required."])
|
||||||
}
|
}
|
||||||
let tz = self.cronTz.trimmingCharacters(in: .whitespacesAndNewlines)
|
let tz = self.trimmed(self.cronTz)
|
||||||
if tz.isEmpty {
|
if tz.isEmpty {
|
||||||
schedule = ["kind": "cron", "expr": expr]
|
return ["kind": "cron", "expr": expr]
|
||||||
} else {
|
|
||||||
schedule = ["kind": "cron", "expr": expr, "tz": tz]
|
|
||||||
}
|
}
|
||||||
|
return ["kind": "cron", "expr": expr, "tz": tz]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let payload: [String: Any] = {
|
func buildSelectedPayload() throws -> [String: Any] {
|
||||||
if self.sessionTarget == .isolated { return self.buildAgentTurnPayload() }
|
if self.sessionTarget == .isolated { return self.buildAgentTurnPayload() }
|
||||||
switch self.payloadKind {
|
switch self.payloadKind {
|
||||||
case .systemEvent:
|
case .systemEvent:
|
||||||
let text = self.systemEventText.trimmingCharacters(in: .whitespacesAndNewlines)
|
let text = self.trimmed(self.systemEventText)
|
||||||
return ["kind": "systemEvent", "text": text]
|
return ["kind": "systemEvent", "text": text]
|
||||||
case .agentTurn:
|
case .agentTurn:
|
||||||
return self.buildAgentTurnPayload()
|
return self.buildAgentTurnPayload()
|
||||||
}
|
}
|
||||||
}()
|
}
|
||||||
|
|
||||||
|
func validateSessionTarget(_ payload: [String: Any]) throws {
|
||||||
if self.sessionTarget == .main, payload["kind"] as? String == "agentTurn" {
|
if self.sessionTarget == .main, payload["kind"] as? String == "agentTurn" {
|
||||||
throw NSError(
|
throw NSError(
|
||||||
domain: "Cron",
|
domain: "Cron",
|
||||||
@@ -125,7 +167,9 @@ extension CronJobEditor {
|
|||||||
code: 0,
|
code: 0,
|
||||||
userInfo: [NSLocalizedDescriptionKey: "Isolated jobs require agentTurn payloads."])
|
userInfo: [NSLocalizedDescriptionKey: "Isolated jobs require agentTurn payloads."])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func validatePayloadRequiredFields(_ payload: [String: Any]) throws {
|
||||||
if payload["kind"] as? String == "systemEvent" {
|
if payload["kind"] as? String == "systemEvent" {
|
||||||
if (payload["text"] as? String ?? "").isEmpty {
|
if (payload["text"] as? String ?? "").isEmpty {
|
||||||
throw NSError(
|
throw NSError(
|
||||||
@@ -133,7 +177,8 @@ extension CronJobEditor {
|
|||||||
code: 0,
|
code: 0,
|
||||||
userInfo: [NSLocalizedDescriptionKey: "System event text is required."])
|
userInfo: [NSLocalizedDescriptionKey: "System event text is required."])
|
||||||
}
|
}
|
||||||
} else if payload["kind"] as? String == "agentTurn" {
|
}
|
||||||
|
if payload["kind"] as? String == "agentTurn" {
|
||||||
if (payload["message"] as? String ?? "").isEmpty {
|
if (payload["message"] as? String ?? "").isEmpty {
|
||||||
throw NSError(
|
throw NSError(
|
||||||
domain: "Cron",
|
domain: "Cron",
|
||||||
@@ -141,35 +186,14 @@ extension CronJobEditor {
|
|||||||
userInfo: [NSLocalizedDescriptionKey: "Agent message is required."])
|
userInfo: [NSLocalizedDescriptionKey: "Agent message is required."])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var root: [String: Any] = [
|
func applyDeleteAfterRun(to root: inout [String: Any]) {
|
||||||
"name": name,
|
|
||||||
"enabled": self.enabled,
|
|
||||||
"schedule": schedule,
|
|
||||||
"sessionTarget": self.sessionTarget.rawValue,
|
|
||||||
"wakeMode": self.wakeMode.rawValue,
|
|
||||||
"payload": payload,
|
|
||||||
]
|
|
||||||
if self.scheduleKind == .at {
|
if self.scheduleKind == .at {
|
||||||
root["deleteAfterRun"] = self.deleteAfterRun
|
root["deleteAfterRun"] = self.deleteAfterRun
|
||||||
} else if self.job?.deleteAfterRun != nil {
|
} else if self.job?.deleteAfterRun != nil {
|
||||||
root["deleteAfterRun"] = false
|
root["deleteAfterRun"] = false
|
||||||
}
|
}
|
||||||
if !description.isEmpty { root["description"] = description }
|
|
||||||
if !agentId.isEmpty {
|
|
||||||
root["agentId"] = agentId
|
|
||||||
} else if self.job?.agentId != nil {
|
|
||||||
root["agentId"] = NSNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.sessionTarget == .isolated {
|
|
||||||
let trimmed = self.postPrefix.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
||||||
root["isolation"] = [
|
|
||||||
"postToMainPrefix": trimmed.isEmpty ? "Cron" : trimmed,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
return root.mapValues { AnyCodable($0) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildAgentTurnPayload() -> [String: Any] {
|
func buildAgentTurnPayload() -> [String: Any] {
|
||||||
|
|||||||
@@ -118,7 +118,8 @@ private func printUsage() {
|
|||||||
clawdbot-mac-wizard
|
clawdbot-mac-wizard
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
clawdbot-mac-wizard [--url <ws://host:port>] [--token <token>] [--password <password>] [--mode <local|remote>] [--workspace <path>] [--json]
|
clawdbot-mac-wizard [--url <ws://host:port>] [--token <token>] [--password <password>]
|
||||||
|
[--mode <local|remote>] [--workspace <path>] [--json]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--url <url> Gateway WebSocket URL (overrides config)
|
--url <url> Gateway WebSocket URL (overrides config)
|
||||||
|
|||||||
Reference in New Issue
Block a user