Settings: move session store path to Debug
This commit is contained in:
@@ -4,7 +4,6 @@ import SwiftUI
|
||||
struct ConfigSettings: View {
|
||||
@State private var configModel: String = ""
|
||||
@State private var customModel: String = ""
|
||||
@State private var configStorePath: String = SessionLoader.defaultStorePath
|
||||
@State private var configSaving = false
|
||||
@State private var hasLoaded = false
|
||||
@State private var models: [ModelChoice] = []
|
||||
@@ -93,15 +92,6 @@ struct ConfigSettings: View {
|
||||
}
|
||||
}
|
||||
|
||||
LabeledContent("Session store") {
|
||||
TextField("Path", text: self.$configStorePath)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.frame(width: 360)
|
||||
.onChange(of: self.configStorePath) { _, _ in
|
||||
self.autosaveConfig()
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
@@ -128,26 +118,13 @@ struct ConfigSettings: View {
|
||||
}
|
||||
|
||||
private func loadConfig() {
|
||||
let url = self.configURL()
|
||||
guard let data = try? Data(contentsOf: url) else {
|
||||
self.configModel = SessionLoader.fallbackModel
|
||||
self.configStorePath = SessionLoader.defaultStorePath
|
||||
return
|
||||
}
|
||||
guard
|
||||
let parsed = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
||||
let inbound = parsed["inbound"] as? [String: Any],
|
||||
let reply = inbound["reply"] as? [String: Any]
|
||||
else {
|
||||
return
|
||||
}
|
||||
let parsed = self.loadConfigDict()
|
||||
let inbound = parsed["inbound"] as? [String: Any]
|
||||
let reply = inbound?["reply"] as? [String: Any]
|
||||
let agent = reply?["agent"] as? [String: Any]
|
||||
let heartbeatMinutes = reply?["heartbeatMinutes"] as? Int
|
||||
let heartbeatBody = reply?["heartbeatBody"] as? String
|
||||
|
||||
let session = reply["session"] as? [String: Any]
|
||||
let agent = reply["agent"] as? [String: Any]
|
||||
let heartbeatMinutes = reply["heartbeatMinutes"] as? Int
|
||||
let heartbeatBody = reply["heartbeatBody"] as? String
|
||||
|
||||
self.configStorePath = (session?["store"] as? String) ?? SessionLoader.defaultStorePath
|
||||
let loadedModel = (agent?["model"] as? String) ?? ""
|
||||
if !loadedModel.isEmpty {
|
||||
self.configModel = loadedModel
|
||||
@@ -171,19 +148,16 @@ struct ConfigSettings: View {
|
||||
self.configSaving = true
|
||||
defer { self.configSaving = false }
|
||||
|
||||
var session: [String: Any] = [:]
|
||||
var agent: [String: Any] = [:]
|
||||
var reply: [String: Any] = [:]
|
||||
|
||||
let trimmedStore = self.configStorePath.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if !trimmedStore.isEmpty { session["store"] = trimmedStore }
|
||||
var root = self.loadConfigDict()
|
||||
var inbound = root["inbound"] as? [String: Any] ?? [:]
|
||||
var reply = inbound["reply"] as? [String: Any] ?? [:]
|
||||
var agent = reply["agent"] as? [String: Any] ?? [:]
|
||||
|
||||
let chosenModel = (self.configModel == "__custom__" ? self.customModel : self.configModel)
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let trimmedModel = chosenModel
|
||||
if !trimmedModel.isEmpty { agent["model"] = trimmedModel }
|
||||
|
||||
reply["session"] = session
|
||||
reply["agent"] = agent
|
||||
|
||||
if let heartbeatMinutes {
|
||||
@@ -195,8 +169,8 @@ struct ConfigSettings: View {
|
||||
reply["heartbeatBody"] = trimmedBody
|
||||
}
|
||||
|
||||
let inbound: [String: Any] = ["reply": reply]
|
||||
let root: [String: Any] = ["inbound": inbound]
|
||||
inbound["reply"] = reply
|
||||
root["inbound"] = inbound
|
||||
|
||||
do {
|
||||
let data = try JSONSerialization.data(withJSONObject: root, options: [.prettyPrinted, .sortedKeys])
|
||||
@@ -208,6 +182,12 @@ struct ConfigSettings: View {
|
||||
} catch {}
|
||||
}
|
||||
|
||||
private func loadConfigDict() -> [String: Any] {
|
||||
let url = self.configURL()
|
||||
guard let data = try? Data(contentsOf: url) else { return [:] }
|
||||
return (try? JSONSerialization.jsonObject(with: data) as? [String: Any]) ?? [:]
|
||||
}
|
||||
|
||||
private func loadModels() async {
|
||||
guard !self.modelsLoading else { return }
|
||||
self.modelsLoading = true
|
||||
|
||||
@@ -10,6 +10,8 @@ struct DebugSettings: View {
|
||||
@State private var modelsError: String?
|
||||
@ObservedObject private var relayManager = RelayProcessManager.shared
|
||||
@State private var relayRootInput: String = RelayProcessManager.shared.projectRootPath()
|
||||
@State private var sessionStorePath: String = SessionLoader.defaultStorePath
|
||||
@State private var sessionStoreSaveError: String?
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
@@ -65,6 +67,27 @@ struct DebugSettings: View {
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
LabeledContent("Session store") {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
HStack(spacing: 8) {
|
||||
TextField("Path", text: self.$sessionStorePath)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.font(.caption.monospaced())
|
||||
.frame(width: 340)
|
||||
Button("Save") { self.saveSessionStorePath() }
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
if let sessionStoreSaveError {
|
||||
Text(sessionStoreSaveError)
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
} else {
|
||||
Text("Used by the CLI session loader; stored in ~/.clawdis/clawdis.json.")
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
LabeledContent("Model catalog") {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
Text(self.modelCatalogPath)
|
||||
@@ -115,7 +138,10 @@ struct DebugSettings: View {
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.horizontal, 12)
|
||||
.task { await self.reloadModels() }
|
||||
.task {
|
||||
await self.reloadModels()
|
||||
self.loadSessionStorePath()
|
||||
}
|
||||
}
|
||||
|
||||
private var pinoLogPath: String {
|
||||
@@ -200,4 +226,56 @@ struct DebugSettings: View {
|
||||
private func saveRelayRoot() {
|
||||
RelayProcessManager.shared.setProjectRoot(path: self.relayRootInput)
|
||||
}
|
||||
|
||||
private func loadSessionStorePath() {
|
||||
let url = self.configURL()
|
||||
guard
|
||||
let data = try? Data(contentsOf: url),
|
||||
let parsed = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
||||
let inbound = parsed["inbound"] as? [String: Any],
|
||||
let reply = inbound["reply"] as? [String: Any],
|
||||
let session = reply["session"] as? [String: Any],
|
||||
let path = session["store"] as? String
|
||||
else {
|
||||
self.sessionStorePath = SessionLoader.defaultStorePath
|
||||
return
|
||||
}
|
||||
self.sessionStorePath = path
|
||||
}
|
||||
|
||||
private func saveSessionStorePath() {
|
||||
let trimmed = self.sessionStorePath.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
var root: [String: Any] = [:]
|
||||
let url = self.configURL()
|
||||
if let data = try? Data(contentsOf: url),
|
||||
let parsed = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
|
||||
{
|
||||
root = parsed
|
||||
}
|
||||
|
||||
var inbound = root["inbound"] as? [String: Any] ?? [:]
|
||||
var reply = inbound["reply"] as? [String: Any] ?? [:]
|
||||
var session = reply["session"] as? [String: Any] ?? [:]
|
||||
session["store"] = trimmed.isEmpty ? SessionLoader.defaultStorePath : trimmed
|
||||
reply["session"] = session
|
||||
inbound["reply"] = reply
|
||||
root["inbound"] = inbound
|
||||
|
||||
do {
|
||||
let data = try JSONSerialization.data(withJSONObject: root, options: [.prettyPrinted, .sortedKeys])
|
||||
try FileManager.default.createDirectory(
|
||||
at: url.deletingLastPathComponent(),
|
||||
withIntermediateDirectories: true)
|
||||
try data.write(to: url, options: [.atomic])
|
||||
self.sessionStoreSaveError = nil
|
||||
} catch {
|
||||
self.sessionStoreSaveError = error.localizedDescription
|
||||
}
|
||||
}
|
||||
|
||||
private func configURL() -> URL {
|
||||
FileManager.default.homeDirectoryForCurrentUser
|
||||
.appendingPathComponent(".clawdis")
|
||||
.appendingPathComponent("clawdis.json")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user