Bug gixes, features added, GUI updates and more
This commit is contained in:
@@ -40,6 +40,14 @@ struct SettingRecord: Codable, FetchableRecord, PersistableRecord, Sendable {
|
||||
var value: String
|
||||
}
|
||||
|
||||
struct HistoryRecord: Codable, FetchableRecord, PersistableRecord, Sendable {
|
||||
static let databaseTableName = "command_history"
|
||||
|
||||
var id: String
|
||||
var input: String
|
||||
var timestamp: String
|
||||
}
|
||||
|
||||
// MARK: - DatabaseService
|
||||
|
||||
final class DatabaseService: Sendable {
|
||||
@@ -48,6 +56,9 @@ final class DatabaseService: Sendable {
|
||||
private let dbQueue: DatabaseQueue
|
||||
private let isoFormatter: ISO8601DateFormatter
|
||||
|
||||
// Command history limit - keep most recent 5000 entries
|
||||
private static let maxHistoryEntries = 5000
|
||||
|
||||
nonisolated private init() {
|
||||
isoFormatter = ISO8601DateFormatter()
|
||||
isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
|
||||
@@ -102,6 +113,20 @@ final class DatabaseService: Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
migrator.registerMigration("v3") { db in
|
||||
try db.create(table: "command_history") { t in
|
||||
t.primaryKey("id", .text)
|
||||
t.column("input", .text).notNull()
|
||||
t.column("timestamp", .text).notNull()
|
||||
}
|
||||
|
||||
try db.create(
|
||||
index: "command_history_on_timestamp",
|
||||
on: "command_history",
|
||||
columns: ["timestamp"]
|
||||
)
|
||||
}
|
||||
|
||||
return migrator
|
||||
}
|
||||
|
||||
@@ -315,4 +340,68 @@ final class DatabaseService: Sendable {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Command History Operations
|
||||
|
||||
nonisolated func saveCommandHistory(input: String) {
|
||||
let now = Date()
|
||||
let record = HistoryRecord(
|
||||
id: UUID().uuidString,
|
||||
input: input,
|
||||
timestamp: isoFormatter.string(from: now)
|
||||
)
|
||||
|
||||
try? dbQueue.write { db in
|
||||
try record.insert(db)
|
||||
|
||||
// Clean up old entries if we exceed the limit
|
||||
let count = try HistoryRecord.fetchCount(db)
|
||||
if count > Self.maxHistoryEntries {
|
||||
// Delete oldest entries to get back to limit
|
||||
let excess = count - Self.maxHistoryEntries
|
||||
try db.execute(
|
||||
sql: """
|
||||
DELETE FROM command_history
|
||||
WHERE id IN (
|
||||
SELECT id FROM command_history
|
||||
ORDER BY timestamp ASC
|
||||
LIMIT ?
|
||||
)
|
||||
""",
|
||||
arguments: [excess]
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nonisolated func loadCommandHistory() throws -> [(input: String, timestamp: Date)] {
|
||||
try dbQueue.read { db in
|
||||
let records = try HistoryRecord
|
||||
.order(Column("timestamp").desc)
|
||||
.fetchAll(db)
|
||||
|
||||
return records.compactMap { record in
|
||||
guard let date = isoFormatter.date(from: record.timestamp) else {
|
||||
return nil
|
||||
}
|
||||
return (input: record.input, timestamp: date)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nonisolated func searchCommandHistory(query: String) throws -> [(input: String, timestamp: Date)] {
|
||||
try dbQueue.read { db in
|
||||
let records = try HistoryRecord
|
||||
.filter(Column("input").like("%\(query)%"))
|
||||
.order(Column("timestamp").desc)
|
||||
.fetchAll(db)
|
||||
|
||||
return records.compactMap { record in
|
||||
guard let date = isoFormatter.date(from: record.timestamp) else {
|
||||
return nil
|
||||
}
|
||||
return (input: record.input, timestamp: date)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,19 @@ class SettingsService {
|
||||
}
|
||||
}
|
||||
|
||||
var systemPrompt: String? {
|
||||
get { cache["systemPrompt"] }
|
||||
set {
|
||||
if let value = newValue, !value.isEmpty {
|
||||
cache["systemPrompt"] = value
|
||||
DatabaseService.shared.setSetting(key: "systemPrompt", value: value)
|
||||
} else {
|
||||
cache.removeValue(forKey: "systemPrompt")
|
||||
DatabaseService.shared.deleteSetting(key: "systemPrompt")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Feature Settings
|
||||
|
||||
var onlineMode: Bool {
|
||||
|
||||
Reference in New Issue
Block a user