117 lines
4.3 KiB
Swift
117 lines
4.3 KiB
Swift
import Foundation
|
|
|
|
extension OnboardingView {
|
|
func loadWorkspaceDefaults() async {
|
|
guard self.workspacePath.isEmpty else { return }
|
|
let configured = await self.loadAgentWorkspace()
|
|
let url = AgentWorkspace.resolveWorkspaceURL(from: configured)
|
|
self.workspacePath = AgentWorkspace.displayPath(for: url)
|
|
self.refreshBootstrapStatus()
|
|
}
|
|
|
|
func ensureDefaultWorkspace() async {
|
|
guard self.state.connectionMode == .local else { return }
|
|
let configured = await self.loadAgentWorkspace()
|
|
let url = AgentWorkspace.resolveWorkspaceURL(from: configured)
|
|
switch AgentWorkspace.bootstrapSafety(for: url) {
|
|
case .safe:
|
|
do {
|
|
_ = try AgentWorkspace.bootstrap(workspaceURL: url)
|
|
if (configured ?? "").trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
|
await self.saveAgentWorkspace(AgentWorkspace.displayPath(for: url))
|
|
}
|
|
} catch {
|
|
self.workspaceStatus = "Failed to create workspace: \(error.localizedDescription)"
|
|
}
|
|
case let .unsafe(reason):
|
|
self.workspaceStatus = "Workspace not touched: \(reason)"
|
|
}
|
|
self.refreshBootstrapStatus()
|
|
}
|
|
|
|
func refreshBootstrapStatus() {
|
|
let url = AgentWorkspace.resolveWorkspaceURL(from: self.workspacePath)
|
|
self.needsBootstrap = AgentWorkspace.needsBootstrap(workspaceURL: url)
|
|
if self.needsBootstrap {
|
|
self.didAutoKickoff = false
|
|
}
|
|
}
|
|
|
|
var workspaceBootstrapCommand: String {
|
|
let template = AgentWorkspace.defaultTemplate().trimmingCharacters(in: .whitespacesAndNewlines)
|
|
return """
|
|
mkdir -p ~/.clawdbot/workspace
|
|
cat > ~/.clawdbot/workspace/AGENTS.md <<'EOF'
|
|
\(template)
|
|
EOF
|
|
"""
|
|
}
|
|
|
|
func applyWorkspace() async {
|
|
guard !self.workspaceApplying else { return }
|
|
self.workspaceApplying = true
|
|
defer { self.workspaceApplying = false }
|
|
|
|
do {
|
|
let url = AgentWorkspace.resolveWorkspaceURL(from: self.workspacePath)
|
|
if case let .unsafe(reason) = AgentWorkspace.bootstrapSafety(for: url) {
|
|
self.workspaceStatus = "Workspace not created: \(reason)"
|
|
return
|
|
}
|
|
_ = try AgentWorkspace.bootstrap(workspaceURL: url)
|
|
self.workspacePath = AgentWorkspace.displayPath(for: url)
|
|
self.workspaceStatus = "Workspace ready at \(self.workspacePath)"
|
|
self.refreshBootstrapStatus()
|
|
} catch {
|
|
self.workspaceStatus = "Failed to create workspace: \(error.localizedDescription)"
|
|
}
|
|
}
|
|
|
|
private func loadAgentWorkspace() async -> String? {
|
|
let root = await ConfigStore.load()
|
|
let agents = root["agents"] as? [String: Any]
|
|
let defaults = agents?["defaults"] as? [String: Any]
|
|
return defaults?["workspace"] as? String
|
|
}
|
|
|
|
@discardableResult
|
|
func saveAgentWorkspace(_ workspace: String?) async -> Bool {
|
|
let (success, errorMessage) = await OnboardingView.buildAndSaveWorkspace(workspace)
|
|
|
|
if let errorMessage {
|
|
self.workspaceStatus = errorMessage
|
|
}
|
|
return success
|
|
}
|
|
|
|
@MainActor
|
|
private static func buildAndSaveWorkspace(_ workspace: String?) async -> (Bool, String?) {
|
|
var root = await ConfigStore.load()
|
|
var agents = root["agents"] as? [String: Any] ?? [:]
|
|
var defaults = agents["defaults"] as? [String: Any] ?? [:]
|
|
let trimmed = workspace?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
|
if trimmed.isEmpty {
|
|
defaults.removeValue(forKey: "workspace")
|
|
} else {
|
|
defaults["workspace"] = trimmed
|
|
}
|
|
if defaults.isEmpty {
|
|
agents.removeValue(forKey: "defaults")
|
|
} else {
|
|
agents["defaults"] = defaults
|
|
}
|
|
if agents.isEmpty {
|
|
root.removeValue(forKey: "agents")
|
|
} else {
|
|
root["agents"] = agents
|
|
}
|
|
do {
|
|
try await ConfigStore.save(root)
|
|
return (true, nil)
|
|
} catch {
|
|
let errorMessage = "Failed to save config: \(error.localizedDescription)"
|
|
return (false, errorMessage)
|
|
}
|
|
}
|
|
}
|