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>
104 lines
3.3 KiB
Swift
104 lines
3.3 KiB
Swift
import Foundation
|
|
|
|
public struct SearchResult: Codable, Sendable, Identifiable {
|
|
public let id: Int // doc_id
|
|
public let title: String?
|
|
public let aiDomain: String?
|
|
public let aiSummary: String?
|
|
public let fileFormat: String?
|
|
public let score: Double?
|
|
public let snippet: String?
|
|
public let matchReason: String?
|
|
public let chunkId: Int?
|
|
public let chunkIndex: Int?
|
|
public let sectionTitle: String?
|
|
public let rerankScore: Double?
|
|
public let freshnessDebug: JSONValue?
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case id, title, score, snippet
|
|
case aiDomain = "ai_domain"
|
|
case aiSummary = "ai_summary"
|
|
case fileFormat = "file_format"
|
|
case matchReason = "match_reason"
|
|
case chunkId = "chunk_id"
|
|
case chunkIndex = "chunk_index"
|
|
case sectionTitle = "section_title"
|
|
case rerankScore = "rerank_score"
|
|
case freshnessDebug = "freshness_debug"
|
|
}
|
|
}
|
|
|
|
public struct SearchResponse: Codable, Sendable {
|
|
public let results: [SearchResult]
|
|
public let total: Int
|
|
public let query: String
|
|
public let mode: String
|
|
public let debug: JSONValue?
|
|
}
|
|
|
|
/// Ask-response citation. DISTINCT from S2's `AICitation` (Sources/AI) — different field sets;
|
|
/// RemoteDSProvider maps this -> AICitation itself. Do not reuse the S2 type here.
|
|
public struct Citation: Codable, Sendable, Identifiable {
|
|
public let n: Int
|
|
public let chunkId: Int?
|
|
public let docId: Int
|
|
public let title: String?
|
|
public let sectionTitle: String?
|
|
public let spanText: String
|
|
public let fullSnippet: String
|
|
public let relevance: Double
|
|
public let rerankScore: Double
|
|
|
|
public var id: Int { n }
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case n, title, relevance
|
|
case chunkId = "chunk_id"
|
|
case docId = "doc_id"
|
|
case sectionTitle = "section_title"
|
|
case spanText = "span_text"
|
|
case fullSnippet = "full_snippet"
|
|
case rerankScore = "rerank_score"
|
|
}
|
|
}
|
|
|
|
public struct ConfirmedItem: Codable, Sendable {
|
|
public let aspect: String
|
|
public let text: String
|
|
public let citations: [Int]
|
|
}
|
|
|
|
public struct AskResponse: Codable, Sendable {
|
|
public let results: [SearchResult]
|
|
public let aiAnswer: String?
|
|
public let citations: [Citation]
|
|
public let synthesisStatus: String
|
|
public let synthesisMs: Double
|
|
public let confidence: String?
|
|
public let refused: Bool
|
|
public let noResultsReason: String?
|
|
public let query: String
|
|
public let total: Int
|
|
public let completeness: String
|
|
public let coveredAspects: [String]?
|
|
public let missingAspects: [String]?
|
|
public let confirmedItems: [ConfirmedItem]?
|
|
public let backendRequested: String?
|
|
public let backendUsed: String?
|
|
public let debug: JSONValue?
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case results, citations, confidence, refused, query, total, completeness, debug
|
|
case aiAnswer = "ai_answer"
|
|
case synthesisStatus = "synthesis_status"
|
|
case synthesisMs = "synthesis_ms"
|
|
case noResultsReason = "no_results_reason"
|
|
case coveredAspects = "covered_aspects"
|
|
case missingAspects = "missing_aspects"
|
|
case confirmedItems = "confirmed_items"
|
|
case backendRequested = "backend_requested"
|
|
case backendUsed = "backend_used"
|
|
}
|
|
}
|