0becf7829e
- Package.swift: AI (S2-owned) + DSKit (models/client/fixtures) + DSKitTests, tools 6.2, .swiftLanguageMode(.v6), .macOS(.v26) - JSONValue (Sendable AnyCodable), DSDate (value-type ISO8601FormatStyle cascade, date-only UTC), explicit-CodingKeys decoder - Models: Auth/Document(+Detail flat-compose, MD-first)/Catalog/Search+Ask/Memo/Digest; non-optional limited to id/file_type/created+updated_at/total - DSClient protocol + FixtureDSClient (Bundle.module, zero backend) + DSError + DSConfig + DownloadURL (?token= query) - Tests: 14-fixture contract acceptance (value asserts) + JSONValue number trap + Ask round-trip + AI router fallback/explicit-unavailable swift build + swift test green (19 tests). Sources/AI untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
43 lines
1.8 KiB
Swift
43 lines
1.8 KiB
Swift
import XCTest
|
|
import AI
|
|
|
|
/// Gate 4 (AI flow): proves the S2 AIRouter produces a VISIBLE routingNote on a rule-based fallback,
|
|
/// and that an explicit-provider-unavailable pick throws (no silent fallback). Sources/AI is consumed
|
|
/// read-only; these tests never modify it.
|
|
final class RouterFallbackTests: XCTestCase {
|
|
|
|
func testRuleFallbackIsVisible() async throws {
|
|
let router = AIRouter(providers: [
|
|
.onDevice: MockAIProvider(id: .onDevice, available: false),
|
|
.localMLX: MockAIProvider(id: .localMLX, available: true),
|
|
])
|
|
let resp = try await router.route(AICompletionRequest(task: .quickSummarize, prompt: "x"))
|
|
XCTAssertEqual(resp.providerUsed, .localMLX)
|
|
XCTAssertEqual(resp.routingNote, "fallback from onDevice → localMLX")
|
|
}
|
|
|
|
func testExplicitUnavailableThrowsNoFallback() async throws {
|
|
let router = AIRouter(providers: [
|
|
.onDevice: MockAIProvider(id: .onDevice, available: false),
|
|
.localMLX: MockAIProvider(id: .localMLX, available: true),
|
|
])
|
|
do {
|
|
_ = try await router.route(
|
|
AICompletionRequest(task: .quickSummarize, prompt: "x", explicitProvider: .onDevice)
|
|
)
|
|
XCTFail("expected explicitProviderUnavailable")
|
|
} catch let error as AIRoutingError {
|
|
guard case .explicitProviderUnavailable = error else {
|
|
return XCTFail("wrong error: \(error)")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testCorpusAskRoutesRemoteWithCitation() async throws {
|
|
let router = AIRouter(providers: [.remoteDS: MockAIProvider(id: .remoteDS)])
|
|
let resp = try await router.route(AICompletionRequest(task: .corpusAsk, prompt: "q"))
|
|
XCTAssertEqual(resp.providerUsed, .remoteDS)
|
|
XCTAssertEqual(resp.citations.count, 1)
|
|
}
|
|
}
|