mirror of
https://github.com/hanzoai/bot.git
synced 2026-10-30 17:24:26 +00:00
Squash merge of 1,462 upstream commits with openclaw→hanzo-bot naming transforms applied. Conflicts resolved favoring our main branch to preserve existing customizations. Key upstream additions: - iOS Security Stack (concurrency locks, runtime guards, TTS fallback) - Discord CDN hostname allowlisting for SSRF protection - Discord mention handling improvements - Various bug fixes and stability improvements
98 lines
3.6 KiB
Swift
98 lines
3.6 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 ~/.hanzo-bot/workspace
|
|
cat > ~/.hanzo-bot/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()
|
|
return AgentWorkspaceConfig.workspace(from: root)
|
|
}
|
|
|
|
@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()
|
|
AgentWorkspaceConfig.setWorkspace(in: &root, workspace: workspace)
|
|
do {
|
|
try await ConfigStore.save(root)
|
|
return (true, nil)
|
|
} catch {
|
|
let errorMessage = "Failed to save config: \(error.localizedDescription)"
|
|
return (false, errorMessage)
|
|
}
|
|
}
|
|
}
|