refactor(macos): drop duplicate AnyCodable
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import ClawdbotProtocol
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
/// Lightweight `Codable` wrapper that round-trips heterogeneous JSON payloads.
|
|
||||||
/// Marked `@unchecked Sendable` because it can hold reference types.
|
|
||||||
struct AnyCodable: Codable, @unchecked Sendable {
|
|
||||||
let value: Any
|
|
||||||
|
|
||||||
init(_ value: Any) { self.value = value }
|
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
|
||||||
let container = try decoder.singleValueContainer()
|
|
||||||
if let intVal = try? container.decode(Int.self) { self.value = intVal; return }
|
|
||||||
if let doubleVal = try? container.decode(Double.self) { self.value = doubleVal; return }
|
|
||||||
if let boolVal = try? container.decode(Bool.self) { self.value = boolVal; return }
|
|
||||||
if let stringVal = try? container.decode(String.self) { self.value = stringVal; return }
|
|
||||||
if container.decodeNil() { self.value = NSNull(); return }
|
|
||||||
if let dict = try? container.decode([String: AnyCodable].self) { self.value = dict; return }
|
|
||||||
if let array = try? container.decode([AnyCodable].self) { self.value = array; return }
|
|
||||||
throw DecodingError.dataCorruptedError(
|
|
||||||
in: container,
|
|
||||||
debugDescription: "Unsupported type")
|
|
||||||
}
|
|
||||||
|
|
||||||
func encode(to encoder: Encoder) throws {
|
|
||||||
var container = encoder.singleValueContainer()
|
|
||||||
switch self.value {
|
|
||||||
case let intVal as Int: try container.encode(intVal)
|
|
||||||
case let doubleVal as Double: try container.encode(doubleVal)
|
|
||||||
case let boolVal as Bool: try container.encode(boolVal)
|
|
||||||
case let stringVal as String: try container.encode(stringVal)
|
|
||||||
case is NSNull: try container.encodeNil()
|
|
||||||
case let dict as [String: AnyCodable]: try container.encode(dict)
|
|
||||||
case let array as [AnyCodable]: try container.encode(array)
|
|
||||||
case let dict as [String: Any]:
|
|
||||||
try container.encode(dict.mapValues { AnyCodable($0) })
|
|
||||||
case let array as [Any]:
|
|
||||||
try container.encode(array.map { AnyCodable($0) })
|
|
||||||
case let dict as NSDictionary:
|
|
||||||
var converted: [String: AnyCodable] = [:]
|
|
||||||
for (k, v) in dict {
|
|
||||||
guard let key = k as? String else { continue }
|
|
||||||
converted[key] = AnyCodable(v)
|
|
||||||
}
|
|
||||||
try container.encode(converted)
|
|
||||||
case let array as NSArray:
|
|
||||||
try container.encode(array.map { AnyCodable($0) })
|
|
||||||
default:
|
|
||||||
let context = EncodingError.Context(
|
|
||||||
codingPath: encoder.codingPath,
|
|
||||||
debugDescription: "Unsupported type")
|
|
||||||
throw EncodingError.invalidValue(self.value, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -229,7 +229,7 @@ actor BridgeServer {
|
|||||||
error: BridgeRPCError(code: "FORBIDDEN", message: "Method not allowed"))
|
error: BridgeRPCError(code: "FORBIDDEN", message: "Method not allowed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
let params: [String: AnyCodable]?
|
let params: [String: ClawdbotProtocol.AnyCodable]?
|
||||||
if let json = req.paramsJSON?.trimmingCharacters(in: .whitespacesAndNewlines), !json.isEmpty {
|
if let json = req.paramsJSON?.trimmingCharacters(in: .whitespacesAndNewlines), !json.isEmpty {
|
||||||
guard let data = json.data(using: .utf8) else {
|
guard let data = json.data(using: .utf8) else {
|
||||||
return BridgeRPCResponse(
|
return BridgeRPCResponse(
|
||||||
@@ -238,7 +238,7 @@ actor BridgeServer {
|
|||||||
error: BridgeRPCError(code: "INVALID_REQUEST", message: "paramsJSON not UTF-8"))
|
error: BridgeRPCError(code: "INVALID_REQUEST", message: "paramsJSON not UTF-8"))
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
params = try JSONDecoder().decode([String: AnyCodable].self, from: data)
|
params = try JSONDecoder().decode([String: ClawdbotProtocol.AnyCodable].self, from: data)
|
||||||
} catch {
|
} catch {
|
||||||
return BridgeRPCResponse(
|
return BridgeRPCResponse(
|
||||||
id: req.id,
|
id: req.id,
|
||||||
@@ -360,16 +360,16 @@ actor BridgeServer {
|
|||||||
"reason \(reason)",
|
"reason \(reason)",
|
||||||
].compactMap(\.self).joined(separator: " · ")
|
].compactMap(\.self).joined(separator: " · ")
|
||||||
|
|
||||||
var params: [String: AnyCodable] = [
|
var params: [String: ClawdbotProtocol.AnyCodable] = [
|
||||||
"text": AnyCodable(summary),
|
"text": ClawdbotProtocol.AnyCodable(summary),
|
||||||
"instanceId": AnyCodable(nodeId),
|
"instanceId": ClawdbotProtocol.AnyCodable(nodeId),
|
||||||
"host": AnyCodable(host),
|
"host": ClawdbotProtocol.AnyCodable(host),
|
||||||
"mode": AnyCodable("node"),
|
"mode": ClawdbotProtocol.AnyCodable("node"),
|
||||||
"reason": AnyCodable(reason),
|
"reason": ClawdbotProtocol.AnyCodable(reason),
|
||||||
"tags": AnyCodable(tags),
|
"tags": ClawdbotProtocol.AnyCodable(tags),
|
||||||
]
|
]
|
||||||
if let ip { params["ip"] = AnyCodable(ip) }
|
if let ip { params["ip"] = ClawdbotProtocol.AnyCodable(ip) }
|
||||||
if let version { params["version"] = AnyCodable(version) }
|
if let version { params["version"] = ClawdbotProtocol.AnyCodable(version) }
|
||||||
await GatewayConnection.shared.sendSystemEvent(params)
|
await GatewayConnection.shared.sendSystemEvent(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import ClawdbotProtocol
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum ClawdbotConfigFile {
|
enum ClawdbotConfigFile {
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import Foundation
|
|||||||
enum ClawdbotEnv {
|
enum ClawdbotEnv {
|
||||||
static func path(_ key: String) -> String? {
|
static func path(_ key: String) -> String? {
|
||||||
// Normalize env overrides once so UI + file IO stay consistent.
|
// Normalize env overrides once so UI + file IO stay consistent.
|
||||||
guard let value = ProcessInfo.processInfo.environment[key]?
|
guard let raw = getenv(key) else { return nil }
|
||||||
.trimmingCharacters(in: .whitespacesAndNewlines),
|
let value = String(cString: raw).trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
!value.isEmpty
|
guard !value.isEmpty
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import ClawdbotProtocol
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum ConfigStore {
|
enum ConfigStore {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import ClawdbotProtocol
|
||||||
import Foundation
|
import Foundation
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import ClawdbotProtocol
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct CronJobEditor: View {
|
struct CronJobEditor: View {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import ClawdbotProtocol
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
extension CronSettings {
|
extension CronSettings {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import ClawdbotKit
|
import ClawdbotKit
|
||||||
|
import ClawdbotProtocol
|
||||||
import Foundation
|
import Foundation
|
||||||
import Observation
|
import Observation
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
@@ -53,7 +54,7 @@ final class WorkActivityStore {
|
|||||||
phase: String,
|
phase: String,
|
||||||
name: String?,
|
name: String?,
|
||||||
meta: String?,
|
meta: String?,
|
||||||
args: [String: AnyCodable]?)
|
args: [String: ClawdbotProtocol.AnyCodable]?)
|
||||||
{
|
{
|
||||||
let toolKind = Self.mapToolKind(name)
|
let toolKind = Self.mapToolKind(name)
|
||||||
let label = Self.buildLabel(name: name, meta: meta, args: args)
|
let label = Self.buildLabel(name: name, meta: meta, args: args)
|
||||||
@@ -211,7 +212,7 @@ final class WorkActivityStore {
|
|||||||
private static func buildLabel(
|
private static func buildLabel(
|
||||||
name: String?,
|
name: String?,
|
||||||
meta: String?,
|
meta: String?,
|
||||||
args: [String: AnyCodable]?) -> String
|
args: [String: ClawdbotProtocol.AnyCodable]?) -> String
|
||||||
{
|
{
|
||||||
let wrappedArgs = self.wrapToolArgs(args)
|
let wrappedArgs = self.wrapToolArgs(args)
|
||||||
let display = ToolDisplayRegistry.resolve(name: name ?? "tool", args: wrappedArgs, meta: meta)
|
let display = ToolDisplayRegistry.resolve(name: name ?? "tool", args: wrappedArgs, meta: meta)
|
||||||
@@ -221,17 +222,17 @@ final class WorkActivityStore {
|
|||||||
return display.label
|
return display.label
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func wrapToolArgs(_ args: [String: AnyCodable]?) -> ClawdbotKit.AnyCodable? {
|
private static func wrapToolArgs(_ args: [String: ClawdbotProtocol.AnyCodable]?) -> ClawdbotKit.AnyCodable? {
|
||||||
guard let args else { return nil }
|
guard let args else { return nil }
|
||||||
let converted: [String: Any] = args.mapValues { self.unwrapJSONValue($0.value) }
|
let converted: [String: Any] = args.mapValues { self.unwrapJSONValue($0.value) }
|
||||||
return ClawdbotKit.AnyCodable(converted)
|
return ClawdbotKit.AnyCodable(converted)
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func unwrapJSONValue(_ value: Any) -> Any {
|
private static func unwrapJSONValue(_ value: Any) -> Any {
|
||||||
if let dict = value as? [String: AnyCodable] {
|
if let dict = value as? [String: ClawdbotProtocol.AnyCodable] {
|
||||||
return dict.mapValues { self.unwrapJSONValue($0.value) }
|
return dict.mapValues { self.unwrapJSONValue($0.value) }
|
||||||
}
|
}
|
||||||
if let array = value as? [AnyCodable] {
|
if let array = value as? [ClawdbotProtocol.AnyCodable] {
|
||||||
return array.map { self.unwrapJSONValue($0.value) }
|
return array.map { self.unwrapJSONValue($0.value) }
|
||||||
}
|
}
|
||||||
if let dict = value as? [String: Any] {
|
if let dict = value as? [String: Any] {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Testing
|
import Testing
|
||||||
|
import ClawdbotProtocol
|
||||||
@testable import Clawdbot
|
@testable import Clawdbot
|
||||||
|
|
||||||
@Suite
|
@Suite
|
||||||
@@ -15,7 +16,7 @@ struct AgentEventStoreTests {
|
|||||||
seq: 1,
|
seq: 1,
|
||||||
stream: "test",
|
stream: "test",
|
||||||
ts: 0,
|
ts: 0,
|
||||||
data: [:] as [String: AnyCodable],
|
data: [:] as [String: ClawdbotProtocol.AnyCodable],
|
||||||
summary: nil))
|
summary: nil))
|
||||||
#expect(store.events.count == 1)
|
#expect(store.events.count == 1)
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ struct AgentEventStoreTests {
|
|||||||
seq: i,
|
seq: i,
|
||||||
stream: "test",
|
stream: "test",
|
||||||
ts: Double(i),
|
ts: Double(i),
|
||||||
data: [:] as [String: AnyCodable],
|
data: [:] as [String: ClawdbotProtocol.AnyCodable],
|
||||||
summary: nil))
|
summary: nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import Testing
|
|||||||
"null": NSNull(),
|
"null": NSNull(),
|
||||||
]
|
]
|
||||||
|
|
||||||
let data = try JSONEncoder().encode(Clawdbot.AnyCodable(payload))
|
let data = try JSONEncoder().encode(ClawdbotProtocol.AnyCodable(payload))
|
||||||
let obj = try #require(JSONSerialization.jsonObject(with: data) as? [String: Any])
|
let obj = try #require(JSONSerialization.jsonObject(with: data) as? [String: Any])
|
||||||
|
|
||||||
#expect(obj["tags"] as? [String] == ["node", "ios"])
|
#expect(obj["tags"] as? [String] == ["node", "ios"])
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ struct CronJobEditorSmokeTests {
|
|||||||
thinking: "low",
|
thinking: "low",
|
||||||
timeoutSeconds: 120,
|
timeoutSeconds: 120,
|
||||||
deliver: true,
|
deliver: true,
|
||||||
channel: "whatsapp",
|
provider: "whatsapp",
|
||||||
to: "+15551234567",
|
to: "+15551234567",
|
||||||
bestEffortDeliver: true),
|
bestEffortDeliver: true),
|
||||||
isolation: CronIsolation(postToMainPrefix: "Cron"),
|
isolation: CronIsolation(postToMainPrefix: "Cron"),
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ struct CronModelsTests {
|
|||||||
thinking: "low",
|
thinking: "low",
|
||||||
timeoutSeconds: 15,
|
timeoutSeconds: 15,
|
||||||
deliver: true,
|
deliver: true,
|
||||||
channel: "whatsapp",
|
provider: "whatsapp",
|
||||||
to: "+15551234567",
|
to: "+15551234567",
|
||||||
bestEffortDeliver: false)
|
bestEffortDeliver: false)
|
||||||
let data = try JSONEncoder().encode(payload)
|
let data = try JSONEncoder().encode(payload)
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ import Testing
|
|||||||
let url = URL(string: "ws://example.invalid")!
|
let url = URL(string: "ws://example.invalid")!
|
||||||
let cfg = ConfigSource(token: nil)
|
let cfg = ConfigSource(token: nil)
|
||||||
let conn = GatewayConnection(
|
let conn = GatewayConnection(
|
||||||
configProvider: { (url, cfg.snapshotToken()) },
|
configProvider: { (url: url, token: cfg.snapshotToken(), password: nil) },
|
||||||
sessionBox: WebSocketSessionBox(session: session))
|
sessionBox: WebSocketSessionBox(session: session))
|
||||||
|
|
||||||
_ = try await conn.request(method: "status", params: nil)
|
_ = try await conn.request(method: "status", params: nil)
|
||||||
@@ -186,7 +186,7 @@ import Testing
|
|||||||
let url = URL(string: "ws://example.invalid")!
|
let url = URL(string: "ws://example.invalid")!
|
||||||
let cfg = ConfigSource(token: "a")
|
let cfg = ConfigSource(token: "a")
|
||||||
let conn = GatewayConnection(
|
let conn = GatewayConnection(
|
||||||
configProvider: { (url, cfg.snapshotToken()) },
|
configProvider: { (url: url, token: cfg.snapshotToken(), password: nil) },
|
||||||
sessionBox: WebSocketSessionBox(session: session))
|
sessionBox: WebSocketSessionBox(session: session))
|
||||||
|
|
||||||
_ = try await conn.request(method: "status", params: nil)
|
_ = try await conn.request(method: "status", params: nil)
|
||||||
@@ -203,7 +203,7 @@ import Testing
|
|||||||
let url = URL(string: "ws://example.invalid")!
|
let url = URL(string: "ws://example.invalid")!
|
||||||
let cfg = ConfigSource(token: nil)
|
let cfg = ConfigSource(token: nil)
|
||||||
let conn = GatewayConnection(
|
let conn = GatewayConnection(
|
||||||
configProvider: { (url, cfg.snapshotToken()) },
|
configProvider: { (url: url, token: cfg.snapshotToken(), password: nil) },
|
||||||
sessionBox: WebSocketSessionBox(session: session))
|
sessionBox: WebSocketSessionBox(session: session))
|
||||||
|
|
||||||
async let r1: Data = conn.request(method: "status", params: nil)
|
async let r1: Data = conn.request(method: "status", params: nil)
|
||||||
@@ -218,7 +218,7 @@ import Testing
|
|||||||
let url = URL(string: "ws://example.invalid")!
|
let url = URL(string: "ws://example.invalid")!
|
||||||
let cfg = ConfigSource(token: nil)
|
let cfg = ConfigSource(token: nil)
|
||||||
let conn = GatewayConnection(
|
let conn = GatewayConnection(
|
||||||
configProvider: { (url, cfg.snapshotToken()) },
|
configProvider: { (url: url, token: cfg.snapshotToken(), password: nil) },
|
||||||
sessionBox: WebSocketSessionBox(session: session))
|
sessionBox: WebSocketSessionBox(session: session))
|
||||||
|
|
||||||
_ = try await conn.request(method: "status", params: nil)
|
_ = try await conn.request(method: "status", params: nil)
|
||||||
@@ -239,7 +239,7 @@ import Testing
|
|||||||
let url = URL(string: "ws://example.invalid")!
|
let url = URL(string: "ws://example.invalid")!
|
||||||
let cfg = ConfigSource(token: nil)
|
let cfg = ConfigSource(token: nil)
|
||||||
let conn = GatewayConnection(
|
let conn = GatewayConnection(
|
||||||
configProvider: { (url, cfg.snapshotToken()) },
|
configProvider: { (url: url, token: cfg.snapshotToken(), password: nil) },
|
||||||
sessionBox: WebSocketSessionBox(session: session))
|
sessionBox: WebSocketSessionBox(session: session))
|
||||||
|
|
||||||
let stream = await conn.subscribe(bufferingNewest: 10)
|
let stream = await conn.subscribe(bufferingNewest: 10)
|
||||||
|
|||||||
@@ -20,11 +20,27 @@ import Testing
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test func gatewayPortDefaultsAndRespectsOverride() {
|
@Test func gatewayPortDefaultsAndRespectsOverride() {
|
||||||
|
let envKey = "CLAWDBOT_CONFIG_PATH"
|
||||||
|
let previousEnv = getenv(envKey).map { String(cString: $0) }
|
||||||
|
let configPath = FileManager.default.temporaryDirectory
|
||||||
|
.appendingPathComponent("clawdbot-test-config-\(UUID().uuidString).json")
|
||||||
|
.path
|
||||||
|
setenv(envKey, configPath, 1)
|
||||||
|
defer {
|
||||||
|
if let previousEnv {
|
||||||
|
setenv(envKey, previousEnv, 1)
|
||||||
|
} else {
|
||||||
|
unsetenv(envKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UserDefaults.standard.removeObject(forKey: "gatewayPort")
|
||||||
|
defer { UserDefaults.standard.removeObject(forKey: "gatewayPort") }
|
||||||
|
|
||||||
let defaultPort = GatewayEnvironment.gatewayPort()
|
let defaultPort = GatewayEnvironment.gatewayPort()
|
||||||
#expect(defaultPort == 18789)
|
#expect(defaultPort == 18789)
|
||||||
|
|
||||||
UserDefaults.standard.set(19999, forKey: "gatewayPort")
|
UserDefaults.standard.set(19999, forKey: "gatewayPort")
|
||||||
defer { UserDefaults.standard.removeObject(forKey: "gatewayPort") }
|
|
||||||
#expect(GatewayEnvironment.gatewayPort() == 19999)
|
#expect(GatewayEnvironment.gatewayPort() == 19999)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import AppKit
|
import AppKit
|
||||||
import Foundation
|
import Foundation
|
||||||
import Testing
|
import Testing
|
||||||
|
import ClawdbotProtocol
|
||||||
|
|
||||||
@testable import Clawdbot
|
@testable import Clawdbot
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ struct LowCoverageHelperTests {
|
|||||||
#expect(dict["list"]?.arrayValue?.count == 2)
|
#expect(dict["list"]?.arrayValue?.count == 2)
|
||||||
|
|
||||||
let foundation = any.foundationValue as? [String: Any]
|
let foundation = any.foundationValue as? [String: Any]
|
||||||
#expect(foundation?["title"] as? String == "Hello")
|
#expect((foundation?["title"] as? String) == "Hello")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test func attributedStringStripsForegroundColor() {
|
@Test func attributedStringStripsForegroundColor() {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import AppKit
|
import AppKit
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Testing
|
import Testing
|
||||||
|
import ClawdbotProtocol
|
||||||
|
|
||||||
@testable import Clawdbot
|
@testable import Clawdbot
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ struct MenuSessionsInjectorTests {
|
|||||||
key: "main",
|
key: "main",
|
||||||
kind: .direct,
|
kind: .direct,
|
||||||
displayName: nil,
|
displayName: nil,
|
||||||
surface: nil,
|
provider: nil,
|
||||||
subject: nil,
|
subject: nil,
|
||||||
room: nil,
|
room: nil,
|
||||||
space: nil,
|
space: nil,
|
||||||
@@ -47,7 +47,7 @@ struct MenuSessionsInjectorTests {
|
|||||||
key: "discord:group:alpha",
|
key: "discord:group:alpha",
|
||||||
kind: .group,
|
kind: .group,
|
||||||
displayName: nil,
|
displayName: nil,
|
||||||
surface: nil,
|
provider: nil,
|
||||||
subject: nil,
|
subject: nil,
|
||||||
room: nil,
|
room: nil,
|
||||||
space: nil,
|
space: nil,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ struct SessionDataTests {
|
|||||||
key: "user@example.com",
|
key: "user@example.com",
|
||||||
kind: .direct,
|
kind: .direct,
|
||||||
displayName: nil,
|
displayName: nil,
|
||||||
surface: nil,
|
provider: nil,
|
||||||
subject: nil,
|
subject: nil,
|
||||||
room: nil,
|
room: nil,
|
||||||
space: nil,
|
space: nil,
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ struct SettingsViewSmokeTests {
|
|||||||
thinking: "low",
|
thinking: "low",
|
||||||
timeoutSeconds: 30,
|
timeoutSeconds: 30,
|
||||||
deliver: true,
|
deliver: true,
|
||||||
channel: "sms",
|
provider: "sms",
|
||||||
to: "+15551234567",
|
to: "+15551234567",
|
||||||
bestEffortDeliver: true),
|
bestEffortDeliver: true),
|
||||||
isolation: CronIsolation(postToMainPrefix: "[cron] "),
|
isolation: CronIsolation(postToMainPrefix: "[cron] "),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import Testing
|
import Testing
|
||||||
|
import ClawdbotProtocol
|
||||||
@testable import Clawdbot
|
@testable import Clawdbot
|
||||||
|
|
||||||
@Suite(.serialized)
|
@Suite(.serialized)
|
||||||
|
|||||||
@@ -17,6 +17,6 @@ import Testing
|
|||||||
#expect(opts.thinking == "low")
|
#expect(opts.thinking == "low")
|
||||||
#expect(opts.deliver == true)
|
#expect(opts.deliver == true)
|
||||||
#expect(opts.to == nil)
|
#expect(opts.to == nil)
|
||||||
#expect(opts.channel == .last)
|
#expect(opts.provider == .last)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Testing
|
import Testing
|
||||||
|
import ClawdbotProtocol
|
||||||
@testable import Clawdbot
|
@testable import Clawdbot
|
||||||
|
|
||||||
@Suite
|
@Suite
|
||||||
|
|||||||
Reference in New Issue
Block a user