native macOS codings agent orchestrator prowl.onev.cat
Something went wrong. Try again.
7.6 kB · 261 lines
Swift
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262import Foundationimport Testing
@testable import Prowl
@MainActorstruct MirrorLaunchModelTests { @Test func deduplicatesWorktreesAndUsesOnlyAvailableHostProfiles() async { let model = MirrorLaunchModel { command in switch command { case .agentsInput, .agentsDispatch, .send: throw CancellationError() case .list: return try json(Self.listing) case .profiles: return try json(Self.profiles) case .create: throw CancellationError() } } await model.load() #expect(model.worktrees.count == 1) #expect(model.worktreeID == "worktree-1") #expect(model.profileID == "available-profile") #expect(model.canCreate) model.profileID = "disabled-profile" #expect(!model.canCreate) }
@Test func launchPreservesMultilinePromptAndUsesOrdinaryBackgroundTab() async throws { var requests: [MirrorCommandRequest.Create] = [] let model = MirrorLaunchModel { command in switch command { case .agentsInput, .agentsDispatch, .send: throw CancellationError() case .list: return try json(Self.listing) case .profiles: return try json(Self.profiles) case .create(let create): requests.append(create) return try json(Self.created) } } await model.load() model.prompt = "first\nsecond" let pane = try #require(await model.create()) #expect(pane.title == "Codex") #expect(pane.projectName == "Project") #expect(requests.count == 1) #expect(requests[0].background && requests[0].resource == "tab") #expect(requests[0].launch?.prompt == "first\nsecond") #expect(requests[0].launch?.profile == "available-profile") }
@Test func lostCreationResponseIsNeverAutomaticallyReplayed() async { var calls = 0 let model = MirrorLaunchModel { command in switch command { case .agentsInput, .agentsDispatch, .send: throw CancellationError() case .list: return try json(Self.listing) case .profiles: return try json(Self.profiles) case .create: calls += 1 throw URLError(.networkConnectionLost) } } await model.load() #expect(await model.create() == nil) #expect(model.creationUncertain) #expect(!model.canCreate) let warning = model.error await model.load() #expect(model.error == warning) #expect(await model.create() == nil) #expect(calls == 1) }
@Test func unconfirmedHostResultBlocksAnotherCreation() async { let model = MirrorLaunchModel { command in switch command { case .agentsInput, .agentsDispatch, .send: throw CancellationError() case .list: return try json(Self.listing) case .profiles: return try json(Self.profiles) case .create: return try json( #""" { "ok": false, "error": { "code": "REMOTE_COMMAND_UNCONFIRMED", "message": "Encoding failed" } } """# ) } } await model.load() #expect(await model.create() == nil) #expect(model.creationUncertain) #expect(!model.canCreate) }
@Test func explicitRejectionKeepsTheFormEditable() async { let model = MirrorLaunchModel { command in switch command { case .agentsInput, .agentsDispatch, .send: throw CancellationError() case .list: return try json(Self.listing) case .profiles: return try json(Self.profiles) case .create: return try json(#"{"ok":false,"error":{"message":"Profile removed"}}"#) } } await model.load() #expect(await model.create() == nil) #expect(model.error == "Profile removed") #expect(!model.creationUncertain) #expect(model.canCreate) }
@Test func emptyCatalogAndOversizedPromptCannotLaunch() async { let empty = MirrorLaunchModel { _ in try json(#"{"ok":true,"data":{"items":[],"profiles":[]}}"#) } await empty.load() #expect(!empty.canCreate) let model = MirrorLaunchModel { command in if case .profiles = command { return try json(Self.profiles) } return try json(Self.listing) } await model.load() model.prompt = String(repeating: "你", count: MirrorWire.maximumInput / 3 + 1) #expect(!model.canCreate) }
@Test func shellCreationUsesDormantWorktreesAndNeedsNoProfileOrPrompt() async throws { var captured: MirrorCommandRequest.Create? let model = MirrorLaunchModel(supportsShell: true) { command in switch command { case .list: return try json( #""" { "ok": true, "data": { "items": [], "worktrees": [ { "id": "dormant", "name": "feature", "path": "/Project/feature", "root_path": "/Project" } ] } } """# ) case .profiles: return try json(#"{"ok":true,"data":{"profiles":[]}}"#) case .create(let request): captured = request return try json(Self.created) default: throw CancellationError() } } await model.load() #expect(model.worktreeID == "dormant") #expect(model.canCreate) model.prompt = "Do not send this to the shell" #expect(await model.create() != nil) #expect(captured?.launch == nil) #expect(captured?.background == true) model.kind = .agent #expect(!model.canCreate) }
@Test func catalogFailureClearsStaleLaunchSelections() async { var fails = false let model = MirrorLaunchModel { command in if fails { throw CancellationError() } if case .profiles = command { return try json(Self.profiles) } return try json(Self.listing) } await model.load() #expect(model.canCreate) fails = true await model.load() #expect(!model.canCreate) }
private static let listing = #""" { "ok": true, "data": { "items": [ { "worktree": { "id": "worktree-1", "name": "main", "path": "/Project", "root_path": "/Project" } }, { "worktree": { "id": "worktree-1", "name": "main", "path": "/Project", "root_path": "/Project" } } ] } } """# private static let profiles = #""" { "ok": true, "data": { "profiles": [ { "id": "disabled-profile", "name": "Disabled", "enabled": false, "runtime": "claude", "availability": { "status": "available" } }, { "id": "available-profile", "name": "Codex", "enabled": true, "runtime": "codex", "availability": { "status": "available" } } ] } } """# private static let created = #""" { "ok": true, "data": { "target": { "worktree": { "id": "worktree-1", "name": "main", "path": "/Project", "root_path": "/Project" }, "pane": { "id": "03F5535A-D08C-498C-B70B-C665AC8D02CB", "title": "Codex" } } } } """#}
private func json(_ string: String) throws -> MirrorJSON { try JSONDecoder().decode(MirrorJSON.self, from: Data(string.utf8))}