mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-28 08:52:45 +00:00
refactor: rename clawdbot to moltbot with legacy compat
This commit is contained in:
@@ -6,8 +6,8 @@
|
||||
{
|
||||
"layers" : [
|
||||
{
|
||||
"image-name" : "clawdbot-mac.png",
|
||||
"name" : "clawdbot-mac",
|
||||
"image-name" : "moltbot-mac.png",
|
||||
"name" : "moltbot-mac",
|
||||
"position" : {
|
||||
"scale" : 1.07,
|
||||
"translation-in-points" : [
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// swift-tools-version: 6.2
|
||||
// Package manifest for the Clawdbot macOS companion (menu bar app + IPC library).
|
||||
// Package manifest for the Moltbot macOS companion (menu bar app + IPC library).
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "Clawdbot",
|
||||
name: "Moltbot",
|
||||
platforms: [
|
||||
.macOS(.v15),
|
||||
],
|
||||
products: [
|
||||
.library(name: "ClawdbotIPC", targets: ["ClawdbotIPC"]),
|
||||
.library(name: "ClawdbotDiscovery", targets: ["ClawdbotDiscovery"]),
|
||||
.executable(name: "Clawdbot", targets: ["Clawdbot"]),
|
||||
.executable(name: "clawdbot-mac", targets: ["ClawdbotMacCLI"]),
|
||||
.library(name: "MoltbotIPC", targets: ["MoltbotIPC"]),
|
||||
.library(name: "MoltbotDiscovery", targets: ["MoltbotDiscovery"]),
|
||||
.executable(name: "Moltbot", targets: ["Moltbot"]),
|
||||
.executable(name: "moltbot-mac", targets: ["MoltbotMacCLI"]),
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/orchetect/MenuBarExtraAccess", exact: "1.2.2"),
|
||||
@@ -25,28 +25,28 @@ let package = Package(
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "ClawdbotIPC",
|
||||
name: "MoltbotIPC",
|
||||
dependencies: [],
|
||||
swiftSettings: [
|
||||
.enableUpcomingFeature("StrictConcurrency"),
|
||||
]),
|
||||
.target(
|
||||
name: "ClawdbotDiscovery",
|
||||
name: "MoltbotDiscovery",
|
||||
dependencies: [
|
||||
.product(name: "ClawdbotKit", package: "ClawdbotKit"),
|
||||
.product(name: "MoltbotKit", package: "MoltbotKit"),
|
||||
],
|
||||
path: "Sources/ClawdbotDiscovery",
|
||||
path: "Sources/MoltbotDiscovery",
|
||||
swiftSettings: [
|
||||
.enableUpcomingFeature("StrictConcurrency"),
|
||||
]),
|
||||
.executableTarget(
|
||||
name: "Clawdbot",
|
||||
name: "Moltbot",
|
||||
dependencies: [
|
||||
"ClawdbotIPC",
|
||||
"ClawdbotDiscovery",
|
||||
.product(name: "ClawdbotKit", package: "ClawdbotKit"),
|
||||
.product(name: "ClawdbotChatUI", package: "ClawdbotKit"),
|
||||
.product(name: "ClawdbotProtocol", package: "ClawdbotKit"),
|
||||
"MoltbotIPC",
|
||||
"MoltbotDiscovery",
|
||||
.product(name: "MoltbotKit", package: "MoltbotKit"),
|
||||
.product(name: "MoltbotChatUI", package: "MoltbotKit"),
|
||||
.product(name: "MoltbotProtocol", package: "MoltbotKit"),
|
||||
.product(name: "SwabbleKit", package: "swabble"),
|
||||
.product(name: "MenuBarExtraAccess", package: "MenuBarExtraAccess"),
|
||||
.product(name: "Subprocess", package: "swift-subprocess"),
|
||||
@@ -59,30 +59,30 @@ let package = Package(
|
||||
"Resources/Info.plist",
|
||||
],
|
||||
resources: [
|
||||
.copy("Resources/Clawdbot.icns"),
|
||||
.copy("Resources/Moltbot.icns"),
|
||||
.copy("Resources/DeviceModels"),
|
||||
],
|
||||
swiftSettings: [
|
||||
.enableUpcomingFeature("StrictConcurrency"),
|
||||
]),
|
||||
.executableTarget(
|
||||
name: "ClawdbotMacCLI",
|
||||
name: "MoltbotMacCLI",
|
||||
dependencies: [
|
||||
"ClawdbotDiscovery",
|
||||
.product(name: "ClawdbotKit", package: "ClawdbotKit"),
|
||||
.product(name: "ClawdbotProtocol", package: "ClawdbotKit"),
|
||||
"MoltbotDiscovery",
|
||||
.product(name: "MoltbotKit", package: "MoltbotKit"),
|
||||
.product(name: "MoltbotProtocol", package: "MoltbotKit"),
|
||||
],
|
||||
path: "Sources/ClawdbotMacCLI",
|
||||
path: "Sources/MoltbotMacCLI",
|
||||
swiftSettings: [
|
||||
.enableUpcomingFeature("StrictConcurrency"),
|
||||
]),
|
||||
.testTarget(
|
||||
name: "ClawdbotIPCTests",
|
||||
name: "MoltbotIPCTests",
|
||||
dependencies: [
|
||||
"ClawdbotIPC",
|
||||
"Clawdbot",
|
||||
"ClawdbotDiscovery",
|
||||
.product(name: "ClawdbotProtocol", package: "ClawdbotKit"),
|
||||
"MoltbotIPC",
|
||||
"Moltbot",
|
||||
"MoltbotDiscovery",
|
||||
.product(name: "MoltbotProtocol", package: "MoltbotKit"),
|
||||
.product(name: "SwabbleKit", package: "swabble"),
|
||||
],
|
||||
swiftSettings: [
|
||||
|
||||
@@ -10,7 +10,7 @@ struct AboutSettings: View {
|
||||
VStack(spacing: 8) {
|
||||
let appIcon = NSApplication.shared.applicationIconImage ?? CritterIconRenderer.makeIcon(blink: 0)
|
||||
Button {
|
||||
if let url = URL(string: "https://github.com/clawdbot/clawdbot") {
|
||||
if let url = URL(string: "https://github.com/moltbot/moltbot") {
|
||||
NSWorkspace.shared.open(url)
|
||||
}
|
||||
} label: {
|
||||
@@ -29,7 +29,7 @@ struct AboutSettings: View {
|
||||
}
|
||||
|
||||
VStack(spacing: 3) {
|
||||
Text("Clawdbot")
|
||||
Text("Moltbot")
|
||||
.font(.title3.bold())
|
||||
Text("Version \(self.versionString)")
|
||||
.foregroundStyle(.secondary)
|
||||
@@ -49,7 +49,7 @@ struct AboutSettings: View {
|
||||
AboutLinkRow(
|
||||
icon: "chevron.left.slash.chevron.right",
|
||||
title: "GitHub",
|
||||
url: "https://github.com/clawdbot/clawdbot")
|
||||
url: "https://github.com/moltbot/moltbot")
|
||||
AboutLinkRow(icon: "globe", title: "Website", url: "https://steipete.me")
|
||||
AboutLinkRow(icon: "bird", title: "Twitter", url: "https://twitter.com/steipete")
|
||||
AboutLinkRow(icon: "envelope", title: "Email", url: "mailto:peter@steipete.me")
|
||||
@@ -108,7 +108,7 @@ struct AboutSettings: View {
|
||||
}
|
||||
|
||||
private var buildTimestamp: String? {
|
||||
guard let raw = Bundle.main.object(forInfoDictionaryKey: "ClawdbotBuildTimestamp") as? String
|
||||
guard let raw = Bundle.main.object(forInfoDictionaryKey: "MoltbotBuildTimestamp") as? String
|
||||
else { return nil }
|
||||
let parser = ISO8601DateFormatter()
|
||||
parser.formatOptions = [.withInternetDateTime]
|
||||
@@ -122,7 +122,7 @@ struct AboutSettings: View {
|
||||
}
|
||||
|
||||
private var gitCommit: String {
|
||||
Bundle.main.object(forInfoDictionaryKey: "ClawdbotGitCommit") as? String ?? "unknown"
|
||||
Bundle.main.object(forInfoDictionaryKey: "MoltbotGitCommit") as? String ?? "unknown"
|
||||
}
|
||||
|
||||
private var bundleID: String {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
@@ -81,7 +81,7 @@ private struct EventRow: View {
|
||||
return f.string(from: date)
|
||||
}
|
||||
|
||||
private func prettyJSON(_ dict: [String: ClawdbotProtocol.AnyCodable]) -> String? {
|
||||
private func prettyJSON(_ dict: [String: MoltbotProtocol.AnyCodable]) -> String? {
|
||||
let normalized = dict.mapValues { $0.value }
|
||||
guard JSONSerialization.isValidJSONObject(normalized),
|
||||
let data = try? JSONSerialization.data(withJSONObject: normalized, options: [.prettyPrinted]),
|
||||
@@ -99,8 +99,8 @@ struct AgentEventsWindow_Previews: PreviewProvider {
|
||||
stream: "tool",
|
||||
ts: Date().timeIntervalSince1970 * 1000,
|
||||
data: [
|
||||
"phase": ClawdbotProtocol.AnyCodable("start"),
|
||||
"name": ClawdbotProtocol.AnyCodable("bash"),
|
||||
"phase": MoltbotProtocol.AnyCodable("start"),
|
||||
"name": MoltbotProtocol.AnyCodable("bash"),
|
||||
],
|
||||
summary: nil)
|
||||
AgentEventStore.shared.append(sample)
|
||||
|
||||
@@ -34,7 +34,7 @@ enum AgentWorkspace {
|
||||
|
||||
static func resolveWorkspaceURL(from userInput: String?) -> URL {
|
||||
let trimmed = userInput?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
if trimmed.isEmpty { return ClawdbotConfigFile.defaultWorkspaceURL() }
|
||||
if trimmed.isEmpty { return MoltbotConfigFile.defaultWorkspaceURL() }
|
||||
let expanded = (trimmed as NSString).expandingTildeInPath
|
||||
return URL(fileURLWithPath: expanded, isDirectory: true)
|
||||
}
|
||||
@@ -154,7 +154,7 @@ enum AgentWorkspace {
|
||||
|
||||
static func defaultTemplate() -> String {
|
||||
let fallback = """
|
||||
# AGENTS.md - Clawdbot Workspace
|
||||
# AGENTS.md - Moltbot Workspace
|
||||
|
||||
This folder is the assistant's working directory.
|
||||
|
||||
@@ -265,7 +265,7 @@ enum AgentWorkspace {
|
||||
- Timezone (optional)
|
||||
- Notes
|
||||
|
||||
3) ~/.clawdbot/clawdbot.json
|
||||
3) ~/.clawdbot/moltbot.json
|
||||
Set identity.name, identity.theme, identity.emoji to match IDENTITY.md.
|
||||
|
||||
## Cleanup
|
||||
|
||||
@@ -6,7 +6,7 @@ import SwiftUI
|
||||
struct AnthropicAuthControls: View {
|
||||
let connectionMode: AppState.ConnectionMode
|
||||
|
||||
@State private var oauthStatus: ClawdbotOAuthStore.AnthropicOAuthStatus = ClawdbotOAuthStore.anthropicOAuthStatus()
|
||||
@State private var oauthStatus: MoltbotOAuthStore.AnthropicOAuthStatus = MoltbotOAuthStore.anthropicOAuthStatus()
|
||||
@State private var pkce: AnthropicOAuth.PKCE?
|
||||
@State private var code: String = ""
|
||||
@State private var busy = false
|
||||
@@ -42,10 +42,10 @@ struct AnthropicAuthControls: View {
|
||||
.foregroundStyle(.secondary)
|
||||
Spacer()
|
||||
Button("Reveal") {
|
||||
NSWorkspace.shared.activateFileViewerSelecting([ClawdbotOAuthStore.oauthURL()])
|
||||
NSWorkspace.shared.activateFileViewerSelecting([MoltbotOAuthStore.oauthURL()])
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.disabled(!FileManager().fileExists(atPath: ClawdbotOAuthStore.oauthURL().path))
|
||||
.disabled(!FileManager().fileExists(atPath: MoltbotOAuthStore.oauthURL().path))
|
||||
|
||||
Button("Refresh") {
|
||||
self.refresh()
|
||||
@@ -53,7 +53,7 @@ struct AnthropicAuthControls: View {
|
||||
.buttonStyle(.bordered)
|
||||
}
|
||||
|
||||
Text(ClawdbotOAuthStore.oauthURL().path)
|
||||
Text(MoltbotOAuthStore.oauthURL().path)
|
||||
.font(.caption.monospaced())
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(1)
|
||||
@@ -130,8 +130,8 @@ struct AnthropicAuthControls: View {
|
||||
}
|
||||
|
||||
private func refresh() {
|
||||
let imported = ClawdbotOAuthStore.importLegacyAnthropicOAuthIfNeeded()
|
||||
self.oauthStatus = ClawdbotOAuthStore.anthropicOAuthStatus()
|
||||
let imported = MoltbotOAuthStore.importLegacyAnthropicOAuthIfNeeded()
|
||||
self.oauthStatus = MoltbotOAuthStore.anthropicOAuthStatus()
|
||||
if imported != nil {
|
||||
self.statusText = "Imported existing OAuth credentials."
|
||||
}
|
||||
@@ -172,11 +172,11 @@ struct AnthropicAuthControls: View {
|
||||
code: parsed.code,
|
||||
state: parsed.state,
|
||||
verifier: pkce.verifier)
|
||||
try ClawdbotOAuthStore.saveAnthropicOAuth(creds)
|
||||
try MoltbotOAuthStore.saveAnthropicOAuth(creds)
|
||||
self.refresh()
|
||||
self.pkce = nil
|
||||
self.code = ""
|
||||
self.statusText = "Connected. Clawdbot can now use Claude via OAuth."
|
||||
self.statusText = "Connected. Moltbot can now use Claude via OAuth."
|
||||
} catch {
|
||||
self.statusText = "OAuth failed: \(error.localizedDescription)"
|
||||
}
|
||||
@@ -212,7 +212,7 @@ struct AnthropicAuthControls: View {
|
||||
extension AnthropicAuthControls {
|
||||
init(
|
||||
connectionMode: AppState.ConnectionMode,
|
||||
oauthStatus: ClawdbotOAuthStore.AnthropicOAuthStatus,
|
||||
oauthStatus: MoltbotOAuthStore.AnthropicOAuthStatus,
|
||||
pkce: AnthropicOAuth.PKCE? = nil,
|
||||
code: String = "",
|
||||
busy: Bool = false,
|
||||
|
||||
@@ -18,7 +18,7 @@ enum AnthropicAuthMode: Equatable {
|
||||
|
||||
var shortLabel: String {
|
||||
switch self {
|
||||
case .oauthFile: "OAuth (Clawdbot token file)"
|
||||
case .oauthFile: "OAuth (Moltbot token file)"
|
||||
case .oauthEnv: "OAuth (env var)"
|
||||
case .apiKeyEnv: "API key (env var)"
|
||||
case .missing: "Missing credentials"
|
||||
@@ -36,7 +36,7 @@ enum AnthropicAuthMode: Equatable {
|
||||
enum AnthropicAuthResolver {
|
||||
static func resolve(
|
||||
environment: [String: String] = ProcessInfo.processInfo.environment,
|
||||
oauthStatus: ClawdbotOAuthStore.AnthropicOAuthStatus = ClawdbotOAuthStore
|
||||
oauthStatus: MoltbotOAuthStore.AnthropicOAuthStatus = MoltbotOAuthStore
|
||||
.anthropicOAuthStatus()) -> AnthropicAuthMode
|
||||
{
|
||||
if oauthStatus.isConnected { return .oauthFile }
|
||||
@@ -194,10 +194,10 @@ enum AnthropicOAuth {
|
||||
}
|
||||
}
|
||||
|
||||
enum ClawdbotOAuthStore {
|
||||
enum MoltbotOAuthStore {
|
||||
static let oauthFilename = "oauth.json"
|
||||
private static let providerKey = "anthropic"
|
||||
private static let clawdbotOAuthDirEnv = "CLAWDBOT_OAUTH_DIR"
|
||||
private static let moltbotOAuthDirEnv = "CLAWDBOT_OAUTH_DIR"
|
||||
private static let legacyPiDirEnv = "PI_CODING_AGENT_DIR"
|
||||
|
||||
enum AnthropicOAuthStatus: Equatable {
|
||||
@@ -215,12 +215,12 @@ enum ClawdbotOAuthStore {
|
||||
|
||||
var shortDescription: String {
|
||||
switch self {
|
||||
case .missingFile: "Clawdbot OAuth token file not found"
|
||||
case .unreadableFile: "Clawdbot OAuth token file not readable"
|
||||
case .invalidJSON: "Clawdbot OAuth token file invalid"
|
||||
case .missingProviderEntry: "No Anthropic entry in Clawdbot OAuth token file"
|
||||
case .missingFile: "Moltbot OAuth token file not found"
|
||||
case .unreadableFile: "Moltbot OAuth token file not readable"
|
||||
case .invalidJSON: "Moltbot OAuth token file invalid"
|
||||
case .missingProviderEntry: "No Anthropic entry in Moltbot OAuth token file"
|
||||
case .missingTokens: "Anthropic entry missing tokens"
|
||||
case .connected: "Clawdbot OAuth credentials found"
|
||||
case .connected: "Moltbot OAuth credentials found"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import ClawdbotKit
|
||||
import ClawdbotProtocol
|
||||
import MoltbotKit
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
|
||||
// Prefer the ClawdbotKit wrapper to keep gateway request payloads consistent.
|
||||
typealias AnyCodable = ClawdbotKit.AnyCodable
|
||||
typealias InstanceIdentity = ClawdbotKit.InstanceIdentity
|
||||
// Prefer the MoltbotKit wrapper to keep gateway request payloads consistent.
|
||||
typealias AnyCodable = MoltbotKit.AnyCodable
|
||||
typealias InstanceIdentity = MoltbotKit.InstanceIdentity
|
||||
|
||||
extension AnyCodable {
|
||||
var stringValue: String? { self.value as? String }
|
||||
@@ -26,19 +26,19 @@ extension AnyCodable {
|
||||
}
|
||||
}
|
||||
|
||||
extension ClawdbotProtocol.AnyCodable {
|
||||
extension MoltbotProtocol.AnyCodable {
|
||||
var stringValue: String? { self.value as? String }
|
||||
var boolValue: Bool? { self.value as? Bool }
|
||||
var intValue: Int? { self.value as? Int }
|
||||
var doubleValue: Double? { self.value as? Double }
|
||||
var dictionaryValue: [String: ClawdbotProtocol.AnyCodable]? { self.value as? [String: ClawdbotProtocol.AnyCodable] }
|
||||
var arrayValue: [ClawdbotProtocol.AnyCodable]? { self.value as? [ClawdbotProtocol.AnyCodable] }
|
||||
var dictionaryValue: [String: MoltbotProtocol.AnyCodable]? { self.value as? [String: MoltbotProtocol.AnyCodable] }
|
||||
var arrayValue: [MoltbotProtocol.AnyCodable]? { self.value as? [MoltbotProtocol.AnyCodable] }
|
||||
|
||||
var foundationValue: Any {
|
||||
switch self.value {
|
||||
case let dict as [String: ClawdbotProtocol.AnyCodable]:
|
||||
case let dict as [String: MoltbotProtocol.AnyCodable]:
|
||||
dict.mapValues { $0.foundationValue }
|
||||
case let array as [ClawdbotProtocol.AnyCodable]:
|
||||
case let array as [MoltbotProtocol.AnyCodable]:
|
||||
array.map(\.foundationValue)
|
||||
default:
|
||||
self.value
|
||||
|
||||
@@ -41,13 +41,13 @@ final class AppState {
|
||||
}
|
||||
|
||||
var onboardingSeen: Bool {
|
||||
didSet { self.ifNotPreview { UserDefaults.standard.set(self.onboardingSeen, forKey: "clawdbot.onboardingSeen") }
|
||||
didSet { self.ifNotPreview { UserDefaults.standard.set(self.onboardingSeen, forKey: "moltbot.onboardingSeen") }
|
||||
}
|
||||
}
|
||||
|
||||
var debugPaneEnabled: Bool {
|
||||
didSet {
|
||||
self.ifNotPreview { UserDefaults.standard.set(self.debugPaneEnabled, forKey: "clawdbot.debugPaneEnabled") }
|
||||
self.ifNotPreview { UserDefaults.standard.set(self.debugPaneEnabled, forKey: "moltbot.debugPaneEnabled") }
|
||||
CanvasManager.shared.refreshDebugStatus()
|
||||
}
|
||||
}
|
||||
@@ -229,11 +229,11 @@ final class AppState {
|
||||
|
||||
init(preview: Bool = false) {
|
||||
self.isPreview = preview || ProcessInfo.processInfo.isRunningTests
|
||||
let onboardingSeen = UserDefaults.standard.bool(forKey: "clawdbot.onboardingSeen")
|
||||
let onboardingSeen = UserDefaults.standard.bool(forKey: "moltbot.onboardingSeen")
|
||||
self.isPaused = UserDefaults.standard.bool(forKey: pauseDefaultsKey)
|
||||
self.launchAtLogin = false
|
||||
self.onboardingSeen = onboardingSeen
|
||||
self.debugPaneEnabled = UserDefaults.standard.bool(forKey: "clawdbot.debugPaneEnabled")
|
||||
self.debugPaneEnabled = UserDefaults.standard.bool(forKey: "moltbot.debugPaneEnabled")
|
||||
let savedVoiceWake = UserDefaults.standard.bool(forKey: swabbleEnabledKey)
|
||||
self.swabbleEnabled = voiceWakeSupported ? savedVoiceWake : false
|
||||
self.swabbleTriggerWords = UserDefaults.standard
|
||||
@@ -275,7 +275,7 @@ final class AppState {
|
||||
UserDefaults.standard.set(IconOverrideSelection.system.rawValue, forKey: iconOverrideKey)
|
||||
}
|
||||
|
||||
let configRoot = ClawdbotConfigFile.loadDict()
|
||||
let configRoot = MoltbotConfigFile.loadDict()
|
||||
let configRemoteUrl = GatewayRemoteConfig.resolveUrlString(root: configRoot)
|
||||
let configRemoteTransport = GatewayRemoteConfig.resolveTransport(root: configRoot)
|
||||
let resolvedConnectionMode = ConnectionModeResolver.resolve(root: configRoot).mode
|
||||
@@ -353,7 +353,7 @@ final class AppState {
|
||||
}
|
||||
|
||||
private func startConfigWatcher() {
|
||||
let configUrl = ClawdbotConfigFile.url()
|
||||
let configUrl = MoltbotConfigFile.url()
|
||||
self.configWatcher = ConfigFileWatcher(url: configUrl) { [weak self] in
|
||||
Task { @MainActor in
|
||||
self?.applyConfigFromDisk()
|
||||
@@ -363,7 +363,7 @@ final class AppState {
|
||||
}
|
||||
|
||||
private func applyConfigFromDisk() {
|
||||
let root = ClawdbotConfigFile.loadDict()
|
||||
let root = MoltbotConfigFile.loadDict()
|
||||
self.applyConfigOverrides(root)
|
||||
}
|
||||
|
||||
@@ -451,7 +451,7 @@ final class AppState {
|
||||
|
||||
Task { @MainActor in
|
||||
// Keep app-only connection settings local to avoid overwriting remote gateway config.
|
||||
var root = ClawdbotConfigFile.loadDict()
|
||||
var root = MoltbotConfigFile.loadDict()
|
||||
var gateway = root["gateway"] as? [String: Any] ?? [:]
|
||||
var changed = false
|
||||
|
||||
@@ -541,7 +541,7 @@ final class AppState {
|
||||
} else {
|
||||
root["gateway"] = gateway
|
||||
}
|
||||
ClawdbotConfigFile.saveDict(root)
|
||||
MoltbotConfigFile.saveDict(root)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -685,7 +685,7 @@ extension AppState {
|
||||
state.remoteTarget = "user@example.com"
|
||||
state.remoteUrl = "wss://gateway.example.ts.net"
|
||||
state.remoteIdentity = "~/.ssh/id_ed25519"
|
||||
state.remoteProjectRoot = "~/Projects/clawdbot"
|
||||
state.remoteProjectRoot = "~/Projects/moltbot"
|
||||
state.remoteCliPath = ""
|
||||
return state
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ final class CLIInstallPrompter {
|
||||
UserDefaults.standard.set(version, forKey: cliInstallPromptedVersionKey)
|
||||
|
||||
let alert = NSAlert()
|
||||
alert.messageText = "Install Clawdbot CLI?"
|
||||
alert.messageText = "Install Moltbot CLI?"
|
||||
alert.informativeText = "Local mode needs the CLI so launchd can run the gateway."
|
||||
alert.addButton(withTitle: "Install CLI")
|
||||
alert.addButton(withTitle: "Not now")
|
||||
|
||||
@@ -13,7 +13,7 @@ enum CLIInstaller {
|
||||
fileManager: FileManager) -> String?
|
||||
{
|
||||
for basePath in searchPaths {
|
||||
let candidate = URL(fileURLWithPath: basePath).appendingPathComponent("clawdbot").path
|
||||
let candidate = URL(fileURLWithPath: basePath).appendingPathComponent("moltbot").path
|
||||
var isDirectory: ObjCBool = false
|
||||
|
||||
guard fileManager.fileExists(atPath: candidate, isDirectory: &isDirectory),
|
||||
@@ -37,14 +37,14 @@ enum CLIInstaller {
|
||||
static func install(statusHandler: @escaping @MainActor @Sendable (String) async -> Void) async {
|
||||
let expected = GatewayEnvironment.expectedGatewayVersionString() ?? "latest"
|
||||
let prefix = Self.installPrefix()
|
||||
await statusHandler("Installing clawdbot CLI…")
|
||||
await statusHandler("Installing moltbot CLI…")
|
||||
let cmd = self.installScriptCommand(version: expected, prefix: prefix)
|
||||
let response = await ShellExecutor.runDetailed(command: cmd, cwd: nil, env: nil, timeout: 900)
|
||||
|
||||
if response.success {
|
||||
let parsed = self.parseInstallEvents(response.stdout)
|
||||
let installedVersion = parsed.last { $0.event == "done" }?.version
|
||||
let summary = installedVersion.map { "Installed clawdbot \($0)." } ?? "Installed clawdbot."
|
||||
let summary = installedVersion.map { "Installed moltbot \($0)." } ?? "Installed moltbot."
|
||||
await statusHandler(summary)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import AVFoundation
|
||||
import ClawdbotIPC
|
||||
import ClawdbotKit
|
||||
import MoltbotIPC
|
||||
import MoltbotKit
|
||||
import CoreGraphics
|
||||
import Foundation
|
||||
import OSLog
|
||||
@@ -168,7 +168,7 @@ actor CameraCaptureService {
|
||||
await Self.warmUpCaptureSession()
|
||||
|
||||
let tmpMovURL = FileManager().temporaryDirectory
|
||||
.appendingPathComponent("clawdbot-camera-\(UUID().uuidString).mov")
|
||||
.appendingPathComponent("moltbot-camera-\(UUID().uuidString).mov")
|
||||
defer { try? FileManager().removeItem(at: tmpMovURL) }
|
||||
|
||||
let outputURL: URL = {
|
||||
@@ -176,7 +176,7 @@ actor CameraCaptureService {
|
||||
return URL(fileURLWithPath: outPath)
|
||||
}
|
||||
return FileManager().temporaryDirectory
|
||||
.appendingPathComponent("clawdbot-camera-\(UUID().uuidString).mp4")
|
||||
.appendingPathComponent("moltbot-camera-\(UUID().uuidString).mp4")
|
||||
}()
|
||||
|
||||
// Ensure we don't fail exporting due to an existing file.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import AppKit
|
||||
import ClawdbotIPC
|
||||
import ClawdbotKit
|
||||
import MoltbotIPC
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import WebKit
|
||||
|
||||
final class CanvasA2UIActionMessageHandler: NSObject, WKScriptMessageHandler {
|
||||
static let messageName = "clawdbotCanvasA2UIAction"
|
||||
static let messageName = "moltbotCanvasA2UIAction"
|
||||
|
||||
private let sessionKey: String
|
||||
|
||||
@@ -52,7 +52,7 @@ final class CanvasA2UIActionMessageHandler: NSObject, WKScriptMessageHandler {
|
||||
}()
|
||||
guard !userAction.isEmpty else { return }
|
||||
|
||||
guard let name = ClawdbotCanvasA2UIAction.extractActionName(userAction) else { return }
|
||||
guard let name = MoltbotCanvasA2UIAction.extractActionName(userAction) else { return }
|
||||
let actionId =
|
||||
(userAction["id"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty
|
||||
?? UUID().uuidString
|
||||
@@ -64,15 +64,15 @@ final class CanvasA2UIActionMessageHandler: NSObject, WKScriptMessageHandler {
|
||||
let sourceComponentId = (userAction["sourceComponentId"] as? String)?
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty ?? "-"
|
||||
let instanceId = InstanceIdentity.instanceId.lowercased()
|
||||
let contextJSON = ClawdbotCanvasA2UIAction.compactJSON(userAction["context"])
|
||||
let contextJSON = MoltbotCanvasA2UIAction.compactJSON(userAction["context"])
|
||||
|
||||
// Token-efficient and unambiguous. The agent should treat this as a UI event and (by default) update Canvas.
|
||||
let messageContext = ClawdbotCanvasA2UIAction.AgentMessageContext(
|
||||
let messageContext = MoltbotCanvasA2UIAction.AgentMessageContext(
|
||||
actionName: name,
|
||||
session: .init(key: self.sessionKey, surfaceId: surfaceId),
|
||||
component: .init(id: sourceComponentId, host: InstanceIdentity.displayName, instanceId: instanceId),
|
||||
contextJSON: contextJSON)
|
||||
let text = ClawdbotCanvasA2UIAction.formatAgentMessage(messageContext)
|
||||
let text = MoltbotCanvasA2UIAction.formatAgentMessage(messageContext)
|
||||
|
||||
Task { [weak webView] in
|
||||
if AppStateStore.shared.connectionMode == .local {
|
||||
@@ -91,7 +91,7 @@ final class CanvasA2UIActionMessageHandler: NSObject, WKScriptMessageHandler {
|
||||
|
||||
await MainActor.run {
|
||||
guard let webView else { return }
|
||||
let js = ClawdbotCanvasA2UIAction.jsDispatchA2UIActionStatus(
|
||||
let js = MoltbotCanvasA2UIAction.jsDispatchA2UIActionStatus(
|
||||
actionId: actionId,
|
||||
ok: result.ok,
|
||||
error: result.error)
|
||||
@@ -144,5 +144,5 @@ final class CanvasA2UIActionMessageHandler: NSObject, WKScriptMessageHandler {
|
||||
return false
|
||||
}
|
||||
|
||||
// Formatting helpers live in ClawdbotKit (`ClawdbotCanvasA2UIAction`).
|
||||
// Formatting helpers live in MoltbotKit (`MoltbotCanvasA2UIAction`).
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import AppKit
|
||||
import ClawdbotIPC
|
||||
import ClawdbotKit
|
||||
import MoltbotIPC
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import OSLog
|
||||
|
||||
@@ -26,7 +26,7 @@ final class CanvasManager {
|
||||
|
||||
private nonisolated static let canvasRoot: URL = {
|
||||
let base = FileManager().urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
|
||||
return base.appendingPathComponent("Clawdbot/canvas", isDirectory: true)
|
||||
return base.appendingPathComponent("Moltbot/canvas", isDirectory: true)
|
||||
}()
|
||||
|
||||
func show(sessionKey: String, path: String? = nil, placement: CanvasPlacement? = nil) throws -> String {
|
||||
@@ -231,7 +231,7 @@ final class CanvasManager {
|
||||
private static func resolveA2UIHostUrl(from raw: String?) -> String? {
|
||||
let trimmed = raw?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
guard !trimmed.isEmpty, let base = URL(string: trimmed) else { return nil }
|
||||
return base.appendingPathComponent("__clawdbot__/a2ui/").absoluteString + "?platform=macos"
|
||||
return base.appendingPathComponent("__moltbot__/a2ui/").absoluteString + "?platform=macos"
|
||||
}
|
||||
|
||||
// MARK: - Anchoring
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Foundation
|
||||
|
||||
enum CanvasScheme {
|
||||
static let scheme = "clawdbot-canvas"
|
||||
static let scheme = "moltbot-canvas"
|
||||
|
||||
static func makeURL(session: String, path: String? = nil) -> URL? {
|
||||
var comps = URLComponents()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import OSLog
|
||||
import WebKit
|
||||
@@ -222,7 +222,7 @@ final class CanvasSchemeHandler: NSObject, WKURLSchemeHandler {
|
||||
let name = fileURL.deletingPathExtension().lastPathComponent
|
||||
guard !name.isEmpty, !ext.isEmpty else { return nil }
|
||||
|
||||
let bundle = ClawdbotKitResources.bundle
|
||||
let bundle = MoltbotKitResources.bundle
|
||||
let resourceURL =
|
||||
bundle.url(forResource: name, withExtension: ext, subdirectory: subdirectory)
|
||||
?? bundle.url(forResource: name, withExtension: ext)
|
||||
|
||||
@@ -23,7 +23,7 @@ extension CanvasWindowController {
|
||||
}
|
||||
|
||||
static func storedFrameDefaultsKey(sessionKey: String) -> String {
|
||||
"clawdbot.canvas.frame.\(self.sanitizeSessionKey(sessionKey))"
|
||||
"moltbot.canvas.frame.\(self.sanitizeSessionKey(sessionKey))"
|
||||
}
|
||||
|
||||
static func loadRestoredFrame(sessionKey: String) -> NSRect? {
|
||||
|
||||
@@ -17,7 +17,7 @@ extension CanvasWindowController {
|
||||
let scheme = url.scheme?.lowercased()
|
||||
|
||||
// Deep links: allow local Canvas content to invoke the agent without bouncing through NSWorkspace.
|
||||
if scheme == "clawdbot" {
|
||||
if scheme == "moltbot" {
|
||||
if self.webView.url?.scheme == CanvasScheme.scheme {
|
||||
Task { await DeepLinkHandler.shared.handle(url: url) }
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import AppKit
|
||||
import ClawdbotIPC
|
||||
import MoltbotIPC
|
||||
|
||||
extension CanvasWindowController {
|
||||
// MARK: - Window
|
||||
@@ -12,7 +12,7 @@ extension CanvasWindowController {
|
||||
styleMask: [.titled, .closable, .resizable, .miniaturizable],
|
||||
backing: .buffered,
|
||||
defer: false)
|
||||
window.title = "Clawdbot Canvas"
|
||||
window.title = "Moltbot Canvas"
|
||||
window.isReleasedWhenClosed = false
|
||||
window.contentView = contentView
|
||||
window.center()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import AppKit
|
||||
import ClawdbotIPC
|
||||
import ClawdbotKit
|
||||
import MoltbotIPC
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import WebKit
|
||||
|
||||
@@ -57,8 +57,8 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
|
||||
(() => {
|
||||
try {
|
||||
if (location.protocol !== '\(CanvasScheme.scheme):') return;
|
||||
if (globalThis.__clawdbotA2UIBridgeInstalled) return;
|
||||
globalThis.__clawdbotA2UIBridgeInstalled = true;
|
||||
if (globalThis.__moltbotA2UIBridgeInstalled) return;
|
||||
globalThis.__moltbotA2UIBridgeInstalled = true;
|
||||
|
||||
const deepLinkKey = \(Self.jsStringLiteral(deepLinkKey));
|
||||
const sessionKey = \(Self.jsStringLiteral(injectedSessionKey));
|
||||
@@ -89,7 +89,7 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
|
||||
|
||||
// If the bundled A2UI shell is present, let it forward actions so we keep its richer
|
||||
// context resolution (data model path lookups, surface detection, etc.).
|
||||
const hasBundledA2UIHost = !!globalThis.clawdbotA2UI || !!document.querySelector('clawdbot-a2ui-host');
|
||||
const hasBundledA2UIHost = !!globalThis.clawdbotA2UI || !!document.querySelector('moltbot-a2ui-host');
|
||||
if (hasBundledA2UIHost && handler?.postMessage) return;
|
||||
|
||||
// Otherwise, forward directly when possible.
|
||||
@@ -115,7 +115,7 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
|
||||
params.set('deliver', 'false');
|
||||
params.set('channel', 'last');
|
||||
params.set('key', deepLinkKey);
|
||||
location.href = 'clawdbot://agent?' + params.toString();
|
||||
location.href = 'moltbot://agent?' + params.toString();
|
||||
} catch {}
|
||||
}, true);
|
||||
} catch {}
|
||||
@@ -268,7 +268,7 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
|
||||
let js = """
|
||||
(() => {
|
||||
try {
|
||||
const api = globalThis.__clawdbot;
|
||||
const api = globalThis.__moltbot;
|
||||
if (!api) return;
|
||||
if (typeof api.setDebugStatusEnabled === 'function') {
|
||||
api.setDebugStatusEnabled(\(enabled ? "true" : "false"));
|
||||
@@ -336,7 +336,7 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
|
||||
path = outPath
|
||||
} else {
|
||||
let ts = Int(Date().timeIntervalSince1970)
|
||||
path = "/tmp/clawdbot-canvas-\(CanvasWindowController.sanitizeSessionKey(self.sessionKey))-\(ts).png"
|
||||
path = "/tmp/moltbot-canvas-\(CanvasWindowController.sanitizeSessionKey(self.sessionKey))-\(ts).png"
|
||||
}
|
||||
|
||||
try png.write(to: URL(fileURLWithPath: path), options: [.atomic])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import SwiftUI
|
||||
|
||||
extension ChannelsSettings {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
|
||||
extension ChannelsStore {
|
||||
@@ -28,7 +28,7 @@ extension ChannelsStore {
|
||||
params: nil,
|
||||
timeoutMs: 10000)
|
||||
self.configStatus = snap.valid == false
|
||||
? "Config invalid; fix it in ~/.clawdbot/clawdbot.json."
|
||||
? "Config invalid; fix it in ~/.clawdbot/moltbot.json."
|
||||
: nil
|
||||
self.configRoot = snap.config?.mapValues { $0.foundationValue } ?? [:]
|
||||
self.configDraft = cloneConfigValue(self.configRoot) as? [String: Any] ?? self.configRoot
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
|
||||
extension ChannelsStore {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
import Observation
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
|
||||
enum ClawdbotConfigFile {
|
||||
enum MoltbotConfigFile {
|
||||
private static let logger = Logger(subsystem: "com.clawdbot", category: "config")
|
||||
|
||||
static func url() -> URL {
|
||||
ClawdbotPaths.configURL
|
||||
MoltbotPaths.configURL
|
||||
}
|
||||
|
||||
static func stateDirURL() -> URL {
|
||||
ClawdbotPaths.stateDirURL
|
||||
MoltbotPaths.stateDirURL
|
||||
}
|
||||
|
||||
static func defaultWorkspaceURL() -> URL {
|
||||
ClawdbotPaths.workspaceURL
|
||||
MoltbotPaths.workspaceURL
|
||||
}
|
||||
|
||||
static func loadDict() -> [String: Any] {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
enum ClawdbotEnv {
|
||||
enum MoltbotEnv {
|
||||
static func path(_ key: String) -> String? {
|
||||
// Normalize env overrides once so UI + file IO stay consistent.
|
||||
guard let raw = getenv(key) else { return nil }
|
||||
@@ -13,12 +13,12 @@ enum ClawdbotEnv {
|
||||
}
|
||||
}
|
||||
|
||||
enum ClawdbotPaths {
|
||||
enum MoltbotPaths {
|
||||
private static let configPathEnv = "CLAWDBOT_CONFIG_PATH"
|
||||
private static let stateDirEnv = "CLAWDBOT_STATE_DIR"
|
||||
|
||||
static var stateDirURL: URL {
|
||||
if let override = ClawdbotEnv.path(self.stateDirEnv) {
|
||||
if let override = MoltbotEnv.path(self.stateDirEnv) {
|
||||
return URL(fileURLWithPath: override, isDirectory: true)
|
||||
}
|
||||
return FileManager().homeDirectoryForCurrentUser
|
||||
@@ -26,10 +26,10 @@ enum ClawdbotPaths {
|
||||
}
|
||||
|
||||
static var configURL: URL {
|
||||
if let override = ClawdbotEnv.path(self.configPathEnv) {
|
||||
if let override = MoltbotEnv.path(self.configPathEnv) {
|
||||
return URL(fileURLWithPath: override)
|
||||
}
|
||||
return self.stateDirURL.appendingPathComponent("clawdbot.json")
|
||||
return self.stateDirURL.appendingPathComponent("moltbot.json")
|
||||
}
|
||||
|
||||
static var workspaceURL: URL {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import Foundation
|
||||
|
||||
enum CommandResolver {
|
||||
private static let projectRootDefaultsKey = "clawdbot.gatewayProjectRootPath"
|
||||
private static let helperName = "clawdbot"
|
||||
private static let projectRootDefaultsKey = "moltbot.gatewayProjectRootPath"
|
||||
private static let helperName = "moltbot"
|
||||
|
||||
static func gatewayEntrypoint(in root: URL) -> String? {
|
||||
let distEntry = root.appendingPathComponent("dist/index.js").path
|
||||
if FileManager().isReadableFile(atPath: distEntry) { return distEntry }
|
||||
let binEntry = root.appendingPathComponent("bin/clawdbot.js").path
|
||||
let binEntry = root.appendingPathComponent("bin/moltbot.js").path
|
||||
if FileManager().isReadableFile(atPath: binEntry) { return binEntry }
|
||||
return nil
|
||||
}
|
||||
@@ -52,7 +52,7 @@ enum CommandResolver {
|
||||
return url
|
||||
}
|
||||
let fallback = FileManager().homeDirectoryForCurrentUser
|
||||
.appendingPathComponent("Projects/clawdbot")
|
||||
.appendingPathComponent("Projects/moltbot")
|
||||
if FileManager().fileExists(atPath: fallback.path) {
|
||||
return fallback
|
||||
}
|
||||
@@ -87,17 +87,17 @@ enum CommandResolver {
|
||||
// Dev-only convenience. Avoid project-local PATH hijacking in release builds.
|
||||
extras.insert(projectRoot.appendingPathComponent("node_modules/.bin").path, at: 0)
|
||||
#endif
|
||||
let clawdbotPaths = self.clawdbotManagedPaths(home: home)
|
||||
if !clawdbotPaths.isEmpty {
|
||||
extras.insert(contentsOf: clawdbotPaths, at: 1)
|
||||
let moltbotPaths = self.clawdbotManagedPaths(home: home)
|
||||
if !moltbotPaths.isEmpty {
|
||||
extras.insert(contentsOf: moltbotPaths, at: 1)
|
||||
}
|
||||
extras.insert(contentsOf: self.nodeManagerBinPaths(home: home), at: 1 + clawdbotPaths.count)
|
||||
extras.insert(contentsOf: self.nodeManagerBinPaths(home: home), at: 1 + moltbotPaths.count)
|
||||
var seen = Set<String>()
|
||||
// Preserve order while stripping duplicates so PATH lookups remain deterministic.
|
||||
return (extras + current).filter { seen.insert($0).inserted }
|
||||
}
|
||||
|
||||
private static func clawdbotManagedPaths(home: URL) -> [String] {
|
||||
private static func moltbotManagedPaths(home: URL) -> [String] {
|
||||
let base = home.appendingPathComponent(".clawdbot")
|
||||
let bin = base.appendingPathComponent("bin")
|
||||
let nodeBin = base.appendingPathComponent("tools/node/bin")
|
||||
@@ -187,11 +187,11 @@ enum CommandResolver {
|
||||
return nil
|
||||
}
|
||||
|
||||
static func clawdbotExecutable(searchPaths: [String]? = nil) -> String? {
|
||||
static func moltbotExecutable(searchPaths: [String]? = nil) -> String? {
|
||||
self.findExecutable(named: self.helperName, searchPaths: searchPaths)
|
||||
}
|
||||
|
||||
static func projectClawdbotExecutable(projectRoot: URL? = nil) -> String? {
|
||||
static func projectMoltbotExecutable(projectRoot: URL? = nil) -> String? {
|
||||
#if DEBUG
|
||||
let root = projectRoot ?? self.projectRoot()
|
||||
let candidate = root.appendingPathComponent("node_modules/.bin").appendingPathComponent(self.helperName).path
|
||||
@@ -202,11 +202,11 @@ enum CommandResolver {
|
||||
}
|
||||
|
||||
static func nodeCliPath() -> String? {
|
||||
let candidate = self.projectRoot().appendingPathComponent("bin/clawdbot.js").path
|
||||
let candidate = self.projectRoot().appendingPathComponent("bin/moltbot.js").path
|
||||
return FileManager().isReadableFile(atPath: candidate) ? candidate : nil
|
||||
}
|
||||
|
||||
static func hasAnyClawdbotInvoker(searchPaths: [String]? = nil) -> Bool {
|
||||
static func hasAnyMoltbotInvoker(searchPaths: [String]? = nil) -> Bool {
|
||||
if self.clawdbotExecutable(searchPaths: searchPaths) != nil { return true }
|
||||
if self.findExecutable(named: "pnpm", searchPaths: searchPaths) != nil { return true }
|
||||
if self.findExecutable(named: "node", searchPaths: searchPaths) != nil,
|
||||
@@ -217,7 +217,7 @@ enum CommandResolver {
|
||||
return false
|
||||
}
|
||||
|
||||
static func clawdbotNodeCommand(
|
||||
static func moltbotNodeCommand(
|
||||
subcommand: String,
|
||||
extraArgs: [String] = [],
|
||||
defaults: UserDefaults = .standard,
|
||||
@@ -238,8 +238,8 @@ enum CommandResolver {
|
||||
switch runtimeResult {
|
||||
case let .success(runtime):
|
||||
let root = self.projectRoot()
|
||||
if let clawdbotPath = self.projectClawdbotExecutable(projectRoot: root) {
|
||||
return [clawdbotPath, subcommand] + extraArgs
|
||||
if let moltbotPath = self.projectMoltbotExecutable(projectRoot: root) {
|
||||
return [moltbotPath, subcommand] + extraArgs
|
||||
}
|
||||
|
||||
if let entry = self.gatewayEntrypoint(in: root) {
|
||||
@@ -251,14 +251,14 @@ enum CommandResolver {
|
||||
}
|
||||
if let pnpm = self.findExecutable(named: "pnpm", searchPaths: searchPaths) {
|
||||
// Use --silent to avoid pnpm lifecycle banners that would corrupt JSON outputs.
|
||||
return [pnpm, "--silent", "clawdbot", subcommand] + extraArgs
|
||||
return [pnpm, "--silent", "moltbot", subcommand] + extraArgs
|
||||
}
|
||||
if let clawdbotPath = self.clawdbotExecutable(searchPaths: searchPaths) {
|
||||
return [clawdbotPath, subcommand] + extraArgs
|
||||
if let moltbotPath = self.clawdbotExecutable(searchPaths: searchPaths) {
|
||||
return [moltbotPath, subcommand] + extraArgs
|
||||
}
|
||||
|
||||
let missingEntry = """
|
||||
clawdbot entrypoint missing (looked for dist/index.js or bin/clawdbot.js); run pnpm build.
|
||||
moltbot entrypoint missing (looked for dist/index.js or bin/moltbot.js); run pnpm build.
|
||||
"""
|
||||
return self.errorCommand(with: missingEntry)
|
||||
|
||||
@@ -267,8 +267,8 @@ enum CommandResolver {
|
||||
}
|
||||
}
|
||||
|
||||
// Existing callers still refer to clawdbotCommand; keep it as node alias.
|
||||
static func clawdbotCommand(
|
||||
// Existing callers still refer to moltbotCommand; keep it as node alias.
|
||||
static func moltbotCommand(
|
||||
subcommand: String,
|
||||
extraArgs: [String] = [],
|
||||
defaults: UserDefaults = .standard,
|
||||
@@ -289,7 +289,7 @@ enum CommandResolver {
|
||||
guard !settings.target.isEmpty else { return nil }
|
||||
guard let parsed = self.parseSSHTarget(settings.target) else { return nil }
|
||||
|
||||
// Run the real clawdbot CLI on the remote host.
|
||||
// Run the real moltbot CLI on the remote host.
|
||||
let exportedPath = [
|
||||
"/opt/homebrew/bin",
|
||||
"/usr/local/bin",
|
||||
@@ -306,7 +306,7 @@ enum CommandResolver {
|
||||
|
||||
let projectSection = if userPRJ.isEmpty {
|
||||
"""
|
||||
DEFAULT_PRJ="$HOME/Projects/clawdbot"
|
||||
DEFAULT_PRJ="$HOME/Projects/moltbot"
|
||||
if [ -d "$DEFAULT_PRJ" ]; then
|
||||
PRJ="$DEFAULT_PRJ"
|
||||
cd "$PRJ" || { echo "Project root not found: $PRJ"; exit 127; }
|
||||
@@ -345,9 +345,9 @@ enum CommandResolver {
|
||||
CLI="";
|
||||
\(cliSection)
|
||||
\(projectSection)
|
||||
if command -v clawdbot >/dev/null 2>&1; then
|
||||
CLI="$(command -v clawdbot)"
|
||||
clawdbot \(quotedArgs);
|
||||
if command -v moltbot >/dev/null 2>&1; then
|
||||
CLI="$(command -v moltbot)"
|
||||
moltbot \(quotedArgs);
|
||||
elif [ -n "${PRJ:-}" ] && [ -f "$PRJ/dist/index.js" ]; then
|
||||
if command -v node >/dev/null 2>&1; then
|
||||
CLI="node $PRJ/dist/index.js"
|
||||
@@ -355,18 +355,18 @@ enum CommandResolver {
|
||||
else
|
||||
echo "Node >=22 required on remote host"; exit 127;
|
||||
fi
|
||||
elif [ -n "${PRJ:-}" ] && [ -f "$PRJ/bin/clawdbot.js" ]; then
|
||||
elif [ -n "${PRJ:-}" ] && [ -f "$PRJ/bin/moltbot.js" ]; then
|
||||
if command -v node >/dev/null 2>&1; then
|
||||
CLI="node $PRJ/bin/clawdbot.js"
|
||||
node "$PRJ/bin/clawdbot.js" \(quotedArgs);
|
||||
CLI="node $PRJ/bin/moltbot.js"
|
||||
node "$PRJ/bin/moltbot.js" \(quotedArgs);
|
||||
else
|
||||
echo "Node >=22 required on remote host"; exit 127;
|
||||
fi
|
||||
elif command -v pnpm >/dev/null 2>&1; then
|
||||
CLI="pnpm --silent clawdbot"
|
||||
pnpm --silent clawdbot \(quotedArgs);
|
||||
CLI="pnpm --silent moltbot"
|
||||
pnpm --silent moltbot \(quotedArgs);
|
||||
else
|
||||
echo "clawdbot CLI missing on remote host"; exit 127;
|
||||
echo "moltbot CLI missing on remote host"; exit 127;
|
||||
fi
|
||||
"""
|
||||
let options: [String] = [
|
||||
@@ -394,7 +394,7 @@ enum CommandResolver {
|
||||
defaults: UserDefaults = .standard,
|
||||
configRoot: [String: Any]? = nil) -> RemoteSettings
|
||||
{
|
||||
let root = configRoot ?? ClawdbotConfigFile.loadDict()
|
||||
let root = configRoot ?? MoltbotConfigFile.loadDict()
|
||||
let mode = ConnectionModeResolver.resolve(root: root, defaults: defaults).mode
|
||||
let target = defaults.string(forKey: remoteTargetKey) ?? ""
|
||||
let identity = defaults.string(forKey: remoteIdentityKey) ?? ""
|
||||
|
||||
@@ -153,7 +153,7 @@ extension ConfigSettings {
|
||||
.font(.title3.weight(.semibold))
|
||||
Text(self.isNixMode
|
||||
? "This tab is read-only in Nix mode. Edit config via Nix and rebuild."
|
||||
: "Edit ~/.clawdbot/clawdbot.json using the schema-driven form.")
|
||||
: "Edit ~/.clawdbot/moltbot.json using the schema-driven form.")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
|
||||
enum ConfigStore {
|
||||
@@ -44,7 +44,7 @@ enum ConfigStore {
|
||||
if let gateway = await self.loadFromGateway() {
|
||||
return gateway
|
||||
}
|
||||
return ClawdbotConfigFile.loadDict()
|
||||
return MoltbotConfigFile.loadDict()
|
||||
}
|
||||
|
||||
@MainActor
|
||||
@@ -63,7 +63,7 @@ enum ConfigStore {
|
||||
do {
|
||||
try await self.saveToGateway(root)
|
||||
} catch {
|
||||
ClawdbotConfigFile.saveDict(root)
|
||||
MoltbotConfigFile.saveDict(root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ enum ConnectionModeResolver {
|
||||
return EffectiveConnectionMode(mode: storedMode, source: .userDefaults)
|
||||
}
|
||||
|
||||
let seen = defaults.bool(forKey: "clawdbot.onboardingSeen")
|
||||
let seen = defaults.bool(forKey: "moltbot.onboardingSeen")
|
||||
return EffectiveConnectionMode(mode: seen ? .local : .unconfigured, source: .onboarding)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,43 +2,43 @@ import Foundation
|
||||
|
||||
let launchdLabel = "com.clawdbot.mac"
|
||||
let gatewayLaunchdLabel = "com.clawdbot.gateway"
|
||||
let onboardingVersionKey = "clawdbot.onboardingVersion"
|
||||
let onboardingVersionKey = "moltbot.onboardingVersion"
|
||||
let currentOnboardingVersion = 7
|
||||
let pauseDefaultsKey = "clawdbot.pauseEnabled"
|
||||
let iconAnimationsEnabledKey = "clawdbot.iconAnimationsEnabled"
|
||||
let swabbleEnabledKey = "clawdbot.swabbleEnabled"
|
||||
let swabbleTriggersKey = "clawdbot.swabbleTriggers"
|
||||
let voiceWakeTriggerChimeKey = "clawdbot.voiceWakeTriggerChime"
|
||||
let voiceWakeSendChimeKey = "clawdbot.voiceWakeSendChime"
|
||||
let showDockIconKey = "clawdbot.showDockIcon"
|
||||
let pauseDefaultsKey = "moltbot.pauseEnabled"
|
||||
let iconAnimationsEnabledKey = "moltbot.iconAnimationsEnabled"
|
||||
let swabbleEnabledKey = "moltbot.swabbleEnabled"
|
||||
let swabbleTriggersKey = "moltbot.swabbleTriggers"
|
||||
let voiceWakeTriggerChimeKey = "moltbot.voiceWakeTriggerChime"
|
||||
let voiceWakeSendChimeKey = "moltbot.voiceWakeSendChime"
|
||||
let showDockIconKey = "moltbot.showDockIcon"
|
||||
let defaultVoiceWakeTriggers = ["clawd", "claude"]
|
||||
let voiceWakeMaxWords = 32
|
||||
let voiceWakeMaxWordLength = 64
|
||||
let voiceWakeMicKey = "clawdbot.voiceWakeMicID"
|
||||
let voiceWakeMicNameKey = "clawdbot.voiceWakeMicName"
|
||||
let voiceWakeLocaleKey = "clawdbot.voiceWakeLocaleID"
|
||||
let voiceWakeAdditionalLocalesKey = "clawdbot.voiceWakeAdditionalLocaleIDs"
|
||||
let voicePushToTalkEnabledKey = "clawdbot.voicePushToTalkEnabled"
|
||||
let talkEnabledKey = "clawdbot.talkEnabled"
|
||||
let iconOverrideKey = "clawdbot.iconOverride"
|
||||
let connectionModeKey = "clawdbot.connectionMode"
|
||||
let remoteTargetKey = "clawdbot.remoteTarget"
|
||||
let remoteIdentityKey = "clawdbot.remoteIdentity"
|
||||
let remoteProjectRootKey = "clawdbot.remoteProjectRoot"
|
||||
let remoteCliPathKey = "clawdbot.remoteCliPath"
|
||||
let canvasEnabledKey = "clawdbot.canvasEnabled"
|
||||
let cameraEnabledKey = "clawdbot.cameraEnabled"
|
||||
let systemRunPolicyKey = "clawdbot.systemRunPolicy"
|
||||
let systemRunAllowlistKey = "clawdbot.systemRunAllowlist"
|
||||
let systemRunEnabledKey = "clawdbot.systemRunEnabled"
|
||||
let locationModeKey = "clawdbot.locationMode"
|
||||
let locationPreciseKey = "clawdbot.locationPreciseEnabled"
|
||||
let peekabooBridgeEnabledKey = "clawdbot.peekabooBridgeEnabled"
|
||||
let deepLinkKeyKey = "clawdbot.deepLinkKey"
|
||||
let modelCatalogPathKey = "clawdbot.modelCatalogPath"
|
||||
let modelCatalogReloadKey = "clawdbot.modelCatalogReload"
|
||||
let cliInstallPromptedVersionKey = "clawdbot.cliInstallPromptedVersion"
|
||||
let heartbeatsEnabledKey = "clawdbot.heartbeatsEnabled"
|
||||
let debugFileLogEnabledKey = "clawdbot.debug.fileLogEnabled"
|
||||
let appLogLevelKey = "clawdbot.debug.appLogLevel"
|
||||
let voiceWakeMicKey = "moltbot.voiceWakeMicID"
|
||||
let voiceWakeMicNameKey = "moltbot.voiceWakeMicName"
|
||||
let voiceWakeLocaleKey = "moltbot.voiceWakeLocaleID"
|
||||
let voiceWakeAdditionalLocalesKey = "moltbot.voiceWakeAdditionalLocaleIDs"
|
||||
let voicePushToTalkEnabledKey = "moltbot.voicePushToTalkEnabled"
|
||||
let talkEnabledKey = "moltbot.talkEnabled"
|
||||
let iconOverrideKey = "moltbot.iconOverride"
|
||||
let connectionModeKey = "moltbot.connectionMode"
|
||||
let remoteTargetKey = "moltbot.remoteTarget"
|
||||
let remoteIdentityKey = "moltbot.remoteIdentity"
|
||||
let remoteProjectRootKey = "moltbot.remoteProjectRoot"
|
||||
let remoteCliPathKey = "moltbot.remoteCliPath"
|
||||
let canvasEnabledKey = "moltbot.canvasEnabled"
|
||||
let cameraEnabledKey = "moltbot.cameraEnabled"
|
||||
let systemRunPolicyKey = "moltbot.systemRunPolicy"
|
||||
let systemRunAllowlistKey = "moltbot.systemRunAllowlist"
|
||||
let systemRunEnabledKey = "moltbot.systemRunEnabled"
|
||||
let locationModeKey = "moltbot.locationMode"
|
||||
let locationPreciseKey = "moltbot.locationPreciseEnabled"
|
||||
let peekabooBridgeEnabledKey = "moltbot.peekabooBridgeEnabled"
|
||||
let deepLinkKeyKey = "moltbot.deepLinkKey"
|
||||
let modelCatalogPathKey = "moltbot.modelCatalogPath"
|
||||
let modelCatalogReloadKey = "moltbot.modelCatalogReload"
|
||||
let cliInstallPromptedVersionKey = "moltbot.cliInstallPromptedVersion"
|
||||
let heartbeatsEnabledKey = "moltbot.heartbeatsEnabled"
|
||||
let debugFileLogEnabledKey = "moltbot.debug.fileLogEnabled"
|
||||
let appLogLevelKey = "moltbot.debug.appLogLevel"
|
||||
let voiceWakeSupported: Bool = ProcessInfo.processInfo.operatingSystemVersion.majorVersion >= 26
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ClawdbotKit
|
||||
import ClawdbotProtocol
|
||||
import MoltbotKit
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
import Observation
|
||||
import SwiftUI
|
||||
@@ -20,7 +20,7 @@ struct ControlAgentEvent: Codable, Sendable, Identifiable {
|
||||
let seq: Int
|
||||
let stream: String
|
||||
let ts: Double
|
||||
let data: [String: ClawdbotProtocol.AnyCodable]
|
||||
let data: [String: MoltbotProtocol.AnyCodable]
|
||||
let summary: String?
|
||||
}
|
||||
|
||||
@@ -163,8 +163,8 @@ final class ControlChannel {
|
||||
timeoutMs: Double? = nil) async throws -> Data
|
||||
{
|
||||
do {
|
||||
let rawParams = params?.reduce(into: [String: ClawdbotKit.AnyCodable]()) {
|
||||
$0[$1.key] = ClawdbotKit.AnyCodable($1.value.base)
|
||||
let rawParams = params?.reduce(into: [String: MoltbotKit.AnyCodable]()) {
|
||||
$0[$1.key] = MoltbotKit.AnyCodable($1.value.base)
|
||||
}
|
||||
let data = try await GatewayConnection.shared.request(
|
||||
method: method,
|
||||
@@ -400,20 +400,20 @@ final class ControlChannel {
|
||||
}
|
||||
|
||||
private static func bridgeToProtocolArgs(
|
||||
_ value: ClawdbotProtocol.AnyCodable?) -> [String: ClawdbotProtocol.AnyCodable]?
|
||||
_ value: MoltbotProtocol.AnyCodable?) -> [String: MoltbotProtocol.AnyCodable]?
|
||||
{
|
||||
guard let value else { return nil }
|
||||
if let dict = value.value as? [String: ClawdbotProtocol.AnyCodable] {
|
||||
if let dict = value.value as? [String: MoltbotProtocol.AnyCodable] {
|
||||
return dict
|
||||
}
|
||||
if let dict = value.value as? [String: ClawdbotKit.AnyCodable],
|
||||
if let dict = value.value as? [String: MoltbotKit.AnyCodable],
|
||||
let data = try? JSONEncoder().encode(dict),
|
||||
let decoded = try? JSONDecoder().decode([String: ClawdbotProtocol.AnyCodable].self, from: data)
|
||||
let decoded = try? JSONDecoder().decode([String: MoltbotProtocol.AnyCodable].self, from: data)
|
||||
{
|
||||
return decoded
|
||||
}
|
||||
if let data = try? JSONEncoder().encode(value),
|
||||
let decoded = try? JSONDecoder().decode([String: ClawdbotProtocol.AnyCodable].self, from: data)
|
||||
let decoded = try? JSONDecoder().decode([String: MoltbotProtocol.AnyCodable].self, from: data)
|
||||
{
|
||||
return decoded
|
||||
}
|
||||
@@ -422,6 +422,6 @@ final class ControlChannel {
|
||||
}
|
||||
|
||||
extension Notification.Name {
|
||||
static let controlHeartbeat = Notification.Name("clawdbot.control.heartbeat")
|
||||
static let controlAgentEvent = Notification.Name("clawdbot.control.agent")
|
||||
static let controlHeartbeat = Notification.Name("moltbot.control.heartbeat")
|
||||
static let controlAgentEvent = Notification.Name("moltbot.control.agent")
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Observation
|
||||
import SwiftUI
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ClawdbotKit
|
||||
import ClawdbotProtocol
|
||||
import MoltbotKit
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
import Observation
|
||||
import OSLog
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
|
||||
extension CronSettings {
|
||||
|
||||
@@ -57,7 +57,7 @@ extension CronSettings {
|
||||
static func exerciseForTesting() {
|
||||
let store = CronJobsStore(isPreview: true)
|
||||
store.schedulerEnabled = false
|
||||
store.schedulerStorePath = "/tmp/clawdbot-cron-store.json"
|
||||
store.schedulerStorePath = "/tmp/moltbot-cron-store.json"
|
||||
|
||||
let job = CronJob(
|
||||
id: "job-1",
|
||||
|
||||
@@ -3,9 +3,9 @@ import Foundation
|
||||
import SwiftUI
|
||||
|
||||
enum DebugActions {
|
||||
private static let verboseDefaultsKey = "clawdbot.debug.verboseMain"
|
||||
private static let verboseDefaultsKey = "moltbot.debug.verboseMain"
|
||||
private static let sessionMenuLimit = 12
|
||||
private static let onboardingSeenKey = "clawdbot.onboardingSeen"
|
||||
private static let onboardingSeenKey = "moltbot.onboardingSeen"
|
||||
|
||||
@MainActor
|
||||
static func openAgentEventsWindow() {
|
||||
@@ -63,7 +63,7 @@ enum DebugActions {
|
||||
}
|
||||
|
||||
static func sendTestNotification() async {
|
||||
_ = await NotificationManager().send(title: "Clawdbot", body: "Test notification", sound: nil)
|
||||
_ = await NotificationManager().send(title: "Moltbot", body: "Test notification", sound: nil)
|
||||
}
|
||||
|
||||
static func sendDebugVoice() async -> Result<String, DebugActionError> {
|
||||
@@ -196,7 +196,7 @@ enum DebugActions {
|
||||
private static func resolveSessionStorePath() -> String {
|
||||
let defaultPath = SessionLoader.defaultStorePath
|
||||
let configURL = FileManager().homeDirectoryForCurrentUser
|
||||
.appendingPathComponent(".clawdbot/clawdbot.json")
|
||||
.appendingPathComponent(".clawdbot/moltbot.json")
|
||||
guard
|
||||
let data = try? Data(contentsOf: configURL),
|
||||
let parsed = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
||||
|
||||
@@ -103,7 +103,7 @@ struct DebugSettings: View {
|
||||
}
|
||||
|
||||
Text(
|
||||
"When enabled, Clawdbot won't install or manage \(gatewayLaunchdLabel). " +
|
||||
"When enabled, Moltbot won't install or manage \(gatewayLaunchdLabel). " +
|
||||
"It will only attach to an existing Gateway.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
@@ -203,7 +203,7 @@ struct DebugSettings: View {
|
||||
Button("Copy sample URL") {
|
||||
let msg = "Hello from deep link"
|
||||
let encoded = msg.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? msg
|
||||
let url = "clawdbot://agent?message=\(encoded)&key=\(key)"
|
||||
let url = "moltbot://agent?message=\(encoded)&key=\(key)"
|
||||
NSPasteboard.general.clearContents()
|
||||
NSPasteboard.general.setString(url, forType: .string)
|
||||
}
|
||||
@@ -211,7 +211,7 @@ struct DebugSettings: View {
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
|
||||
Text("Deep links (clawdbot://…) are always enabled; the key controls unattended runs.")
|
||||
Text("Deep links (moltbot://…) are always enabled; the key controls unattended runs.")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
@@ -274,7 +274,7 @@ struct DebugSettings: View {
|
||||
Toggle("Write rolling diagnostics log (JSONL)", isOn: self.$diagnosticsFileLogEnabled)
|
||||
.toggleStyle(.checkbox)
|
||||
.help(
|
||||
"Writes a rotating, local-only log under ~/Library/Logs/Clawdbot/. " +
|
||||
"Writes a rotating, local-only log under ~/Library/Logs/Moltbot/. " +
|
||||
"Enable only while actively debugging.")
|
||||
|
||||
HStack(spacing: 8) {
|
||||
@@ -382,10 +382,10 @@ struct DebugSettings: View {
|
||||
GroupBox("Paths") {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
Text("Clawdbot project root")
|
||||
Text("Moltbot project root")
|
||||
.font(.caption.weight(.semibold))
|
||||
HStack(spacing: 8) {
|
||||
TextField("Path to clawdbot repo", text: self.$gatewayRootInput)
|
||||
TextField("Path to moltbot repo", text: self.$gatewayRootInput)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.font(.caption.monospaced())
|
||||
.onSubmit { self.saveRelayRoot() }
|
||||
@@ -393,7 +393,7 @@ struct DebugSettings: View {
|
||||
.buttonStyle(.borderedProminent)
|
||||
Button("Reset") {
|
||||
let def = FileManager().homeDirectoryForCurrentUser
|
||||
.appendingPathComponent("Projects/clawdbot").path
|
||||
.appendingPathComponent("Projects/moltbot").path
|
||||
self.gatewayRootInput = def
|
||||
self.saveRelayRoot()
|
||||
}
|
||||
@@ -423,7 +423,7 @@ struct DebugSettings: View {
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
} else {
|
||||
Text("Used by the CLI session loader; stored in ~/.clawdbot/clawdbot.json.")
|
||||
Text("Used by the CLI session loader; stored in ~/.clawdbot/moltbot.json.")
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
@@ -524,15 +524,15 @@ struct DebugSettings: View {
|
||||
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
Text(
|
||||
"Note: macOS may require restarting Clawdbot after enabling Accessibility or Screen Recording.")
|
||||
"Note: macOS may require restarting Moltbot after enabling Accessibility or Screen Recording.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
|
||||
Button {
|
||||
LaunchdManager.startClawdbot()
|
||||
LaunchdManager.startMoltbot()
|
||||
} label: {
|
||||
Label("Restart Clawdbot", systemImage: "arrow.counterclockwise")
|
||||
Label("Restart Moltbot", systemImage: "arrow.counterclockwise")
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.controlSize(.small)
|
||||
@@ -832,7 +832,7 @@ struct DebugSettings: View {
|
||||
private func configURL() -> URL {
|
||||
FileManager().homeDirectoryForCurrentUser
|
||||
.appendingPathComponent(".clawdbot")
|
||||
.appendingPathComponent("clawdbot.json")
|
||||
.appendingPathComponent("moltbot.json")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -981,7 +981,7 @@ extension DebugSettings {
|
||||
view.modelsCount = 3
|
||||
view.modelsLoading = false
|
||||
view.modelsError = "Failed to load models"
|
||||
view.gatewayRootInput = "/tmp/clawdbot"
|
||||
view.gatewayRootInput = "/tmp/moltbot"
|
||||
view.sessionStorePath = "/tmp/sessions.json"
|
||||
view.sessionStoreSaveError = "Save failed"
|
||||
view.debugSendInFlight = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import AppKit
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import OSLog
|
||||
import Security
|
||||
@@ -23,7 +23,7 @@ final class DeepLinkHandler {
|
||||
return
|
||||
}
|
||||
guard !AppStateStore.shared.isPaused else {
|
||||
self.presentAlert(title: "Clawdbot is paused", message: "Unpause Clawdbot to run agent actions.")
|
||||
self.presentAlert(title: "Moltbot is paused", message: "Unpause Moltbot to run agent actions.")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ final class DeepLinkHandler {
|
||||
let trimmed = messagePreview.count > 240 ? "\(messagePreview.prefix(240))…" : messagePreview
|
||||
let body =
|
||||
"Run the agent with this message?\n\n\(trimmed)\n\nURL:\n\(originalURL.absoluteString)"
|
||||
guard self.confirm(title: "Run Clawdbot agent?", message: body) else { return }
|
||||
guard self.confirm(title: "Run Moltbot agent?", message: body) else { return }
|
||||
}
|
||||
|
||||
if AppStateStore.shared.connectionMode == .local {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import AppKit
|
||||
import ClawdbotKit
|
||||
import ClawdbotProtocol
|
||||
import MoltbotKit
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
import Observation
|
||||
import OSLog
|
||||
|
||||
@@ -24,7 +24,7 @@ actor DiagnosticsFileLog {
|
||||
?? FileManager().homeDirectoryForCurrentUser.appendingPathComponent("Library", isDirectory: true)
|
||||
return library
|
||||
.appendingPathComponent("Logs", isDirectory: true)
|
||||
.appendingPathComponent("Clawdbot", isDirectory: true)
|
||||
.appendingPathComponent("Moltbot", isDirectory: true)
|
||||
}
|
||||
|
||||
nonisolated static func logFileURL() -> URL {
|
||||
|
||||
@@ -197,11 +197,11 @@ enum ExecApprovalsStore {
|
||||
private static let defaultAutoAllowSkills = false
|
||||
|
||||
static func fileURL() -> URL {
|
||||
ClawdbotPaths.stateDirURL.appendingPathComponent("exec-approvals.json")
|
||||
MoltbotPaths.stateDirURL.appendingPathComponent("exec-approvals.json")
|
||||
}
|
||||
|
||||
static func socketPath() -> String {
|
||||
ClawdbotPaths.stateDirURL.appendingPathComponent("exec-approvals.sock").path
|
||||
MoltbotPaths.stateDirURL.appendingPathComponent("exec-approvals.sock").path
|
||||
}
|
||||
|
||||
static func normalizeIncoming(_ file: ExecApprovalsFile) -> ExecApprovalsFile {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ClawdbotKit
|
||||
import ClawdbotProtocol
|
||||
import MoltbotKit
|
||||
import MoltbotProtocol
|
||||
import CoreGraphics
|
||||
import Foundation
|
||||
import OSLog
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import AppKit
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import CryptoKit
|
||||
import Darwin
|
||||
import Foundation
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import ClawdbotChatUI
|
||||
import ClawdbotKit
|
||||
import ClawdbotProtocol
|
||||
import MoltbotChatUI
|
||||
import MoltbotKit
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
import OSLog
|
||||
|
||||
@@ -272,7 +272,7 @@ actor GatewayConnection {
|
||||
return trimmed.isEmpty ? nil : trimmed
|
||||
}
|
||||
|
||||
private func sessionDefaultString(_ defaults: [String: ClawdbotProtocol.AnyCodable]?, key: String) -> String {
|
||||
private func sessionDefaultString(_ defaults: [String: MoltbotProtocol.AnyCodable]?, key: String) -> String {
|
||||
let raw = defaults?[key]?.value as? String
|
||||
return (raw ?? "").trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
||||
}
|
||||
@@ -503,7 +503,7 @@ extension GatewayConnection {
|
||||
|
||||
func healthOK(timeoutMs: Int = 8000) async throws -> Bool {
|
||||
let data = try await self.requestRaw(method: .health, timeoutMs: Double(timeoutMs))
|
||||
return (try? self.decoder.decode(ClawdbotGatewayHealthOK.self, from: data))?.ok ?? true
|
||||
return (try? self.decoder.decode(MoltbotGatewayHealthOK.self, from: data))?.ok ?? true
|
||||
}
|
||||
|
||||
// MARK: - Skills
|
||||
@@ -548,13 +548,13 @@ extension GatewayConnection {
|
||||
keys: [String],
|
||||
limit: Int? = nil,
|
||||
maxChars: Int? = nil,
|
||||
timeoutMs: Int? = nil) async throws -> ClawdbotSessionsPreviewPayload
|
||||
timeoutMs: Int? = nil) async throws -> MoltbotSessionsPreviewPayload
|
||||
{
|
||||
let resolvedKeys = keys
|
||||
.map { self.canonicalizeSessionKey($0) }
|
||||
.filter { !$0.isEmpty }
|
||||
if resolvedKeys.isEmpty {
|
||||
return ClawdbotSessionsPreviewPayload(ts: 0, previews: [])
|
||||
return MoltbotSessionsPreviewPayload(ts: 0, previews: [])
|
||||
}
|
||||
var params: [String: AnyCodable] = ["keys": AnyCodable(resolvedKeys)]
|
||||
if let limit { params["limit"] = AnyCodable(limit) }
|
||||
@@ -571,7 +571,7 @@ extension GatewayConnection {
|
||||
func chatHistory(
|
||||
sessionKey: String,
|
||||
limit: Int? = nil,
|
||||
timeoutMs: Int? = nil) async throws -> ClawdbotChatHistoryPayload
|
||||
timeoutMs: Int? = nil) async throws -> MoltbotChatHistoryPayload
|
||||
{
|
||||
let resolvedKey = self.canonicalizeSessionKey(sessionKey)
|
||||
var params: [String: AnyCodable] = ["sessionKey": AnyCodable(resolvedKey)]
|
||||
@@ -588,8 +588,8 @@ extension GatewayConnection {
|
||||
message: String,
|
||||
thinking: String,
|
||||
idempotencyKey: String,
|
||||
attachments: [ClawdbotChatAttachmentPayload],
|
||||
timeoutMs: Int = 30000) async throws -> ClawdbotChatSendResponse
|
||||
attachments: [MoltbotChatAttachmentPayload],
|
||||
timeoutMs: Int = 30000) async throws -> MoltbotChatSendResponse
|
||||
{
|
||||
let resolvedKey = self.canonicalizeSessionKey(sessionKey)
|
||||
var params: [String: AnyCodable] = [
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotDiscovery
|
||||
import MoltbotDiscovery
|
||||
import Foundation
|
||||
|
||||
enum GatewayDiscoveryHelpers {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotDiscovery
|
||||
import MoltbotDiscovery
|
||||
import SwiftUI
|
||||
|
||||
struct GatewayDiscoveryInlineList: View {
|
||||
@@ -134,6 +134,6 @@ struct GatewayDiscoveryMenu: View {
|
||||
} label: {
|
||||
Image(systemName: "dot.radiowaves.left.and.right")
|
||||
}
|
||||
.help("Discover Clawdbot gateways on your LAN")
|
||||
.help("Discover Moltbot gateways on your LAN")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ actor GatewayEndpointStore {
|
||||
static let live = Deps(
|
||||
mode: { await MainActor.run { AppStateStore.shared.connectionMode } },
|
||||
token: {
|
||||
let root = ClawdbotConfigFile.loadDict()
|
||||
let root = MoltbotConfigFile.loadDict()
|
||||
let isRemote = ConnectionModeResolver.resolve(root: root).mode == .remote
|
||||
return GatewayEndpointStore.resolveGatewayToken(
|
||||
isRemote: isRemote,
|
||||
@@ -52,7 +52,7 @@ actor GatewayEndpointStore {
|
||||
launchdSnapshot: GatewayLaunchAgentManager.launchdConfigSnapshot())
|
||||
},
|
||||
password: {
|
||||
let root = ClawdbotConfigFile.loadDict()
|
||||
let root = MoltbotConfigFile.loadDict()
|
||||
let isRemote = ConnectionModeResolver.resolve(root: root).mode == .remote
|
||||
return GatewayEndpointStore.resolveGatewayPassword(
|
||||
isRemote: isRemote,
|
||||
@@ -62,7 +62,7 @@ actor GatewayEndpointStore {
|
||||
},
|
||||
localPort: { GatewayEnvironment.gatewayPort() },
|
||||
localHost: {
|
||||
let root = ClawdbotConfigFile.loadDict()
|
||||
let root = MoltbotConfigFile.loadDict()
|
||||
let bind = GatewayEndpointStore.resolveGatewayBindMode(
|
||||
root: root,
|
||||
env: ProcessInfo.processInfo.environment)
|
||||
@@ -243,17 +243,17 @@ actor GatewayEndpointStore {
|
||||
if let modeRaw {
|
||||
initialMode = AppState.ConnectionMode(rawValue: modeRaw) ?? .local
|
||||
} else {
|
||||
let seen = UserDefaults.standard.bool(forKey: "clawdbot.onboardingSeen")
|
||||
let seen = UserDefaults.standard.bool(forKey: "moltbot.onboardingSeen")
|
||||
initialMode = seen ? .local : .unconfigured
|
||||
}
|
||||
|
||||
let port = deps.localPort()
|
||||
let bind = GatewayEndpointStore.resolveGatewayBindMode(
|
||||
root: ClawdbotConfigFile.loadDict(),
|
||||
root: MoltbotConfigFile.loadDict(),
|
||||
env: ProcessInfo.processInfo.environment)
|
||||
let customBindHost = GatewayEndpointStore.resolveGatewayCustomBindHost(root: ClawdbotConfigFile.loadDict())
|
||||
let customBindHost = GatewayEndpointStore.resolveGatewayCustomBindHost(root: MoltbotConfigFile.loadDict())
|
||||
let scheme = GatewayEndpointStore.resolveGatewayScheme(
|
||||
root: ClawdbotConfigFile.loadDict(),
|
||||
root: MoltbotConfigFile.loadDict(),
|
||||
env: ProcessInfo.processInfo.environment)
|
||||
let host = GatewayEndpointStore.resolveLocalGatewayHost(
|
||||
bindMode: bind,
|
||||
@@ -303,7 +303,7 @@ actor GatewayEndpointStore {
|
||||
let port = self.deps.localPort()
|
||||
let host = await self.deps.localHost()
|
||||
let scheme = GatewayEndpointStore.resolveGatewayScheme(
|
||||
root: ClawdbotConfigFile.loadDict(),
|
||||
root: MoltbotConfigFile.loadDict(),
|
||||
env: ProcessInfo.processInfo.environment)
|
||||
self.setState(.ready(
|
||||
mode: .local,
|
||||
@@ -311,7 +311,7 @@ actor GatewayEndpointStore {
|
||||
token: token,
|
||||
password: password))
|
||||
case .remote:
|
||||
let root = ClawdbotConfigFile.loadDict()
|
||||
let root = MoltbotConfigFile.loadDict()
|
||||
if GatewayRemoteConfig.resolveTransport(root: root) == .direct {
|
||||
guard let url = GatewayRemoteConfig.resolveGatewayUrl(root: root) else {
|
||||
self.cancelRemoteEnsure()
|
||||
@@ -332,7 +332,7 @@ actor GatewayEndpointStore {
|
||||
}
|
||||
self.cancelRemoteEnsure()
|
||||
let scheme = GatewayEndpointStore.resolveGatewayScheme(
|
||||
root: ClawdbotConfigFile.loadDict(),
|
||||
root: MoltbotConfigFile.loadDict(),
|
||||
env: ProcessInfo.processInfo.environment)
|
||||
self.setState(.ready(
|
||||
mode: .remote,
|
||||
@@ -354,7 +354,7 @@ actor GatewayEndpointStore {
|
||||
code: 1,
|
||||
userInfo: [NSLocalizedDescriptionKey: "Remote mode is not enabled"])
|
||||
}
|
||||
let root = ClawdbotConfigFile.loadDict()
|
||||
let root = MoltbotConfigFile.loadDict()
|
||||
if GatewayRemoteConfig.resolveTransport(root: root) == .direct {
|
||||
guard let url = GatewayRemoteConfig.resolveGatewayUrl(root: root) else {
|
||||
throw NSError(
|
||||
@@ -433,7 +433,7 @@ actor GatewayEndpointStore {
|
||||
userInfo: [NSLocalizedDescriptionKey: "Remote mode is not enabled"])
|
||||
}
|
||||
|
||||
let root = ClawdbotConfigFile.loadDict()
|
||||
let root = MoltbotConfigFile.loadDict()
|
||||
if GatewayRemoteConfig.resolveTransport(root: root) == .direct {
|
||||
guard let url = GatewayRemoteConfig.resolveGatewayUrl(root: root) else {
|
||||
throw NSError(
|
||||
@@ -470,7 +470,7 @@ actor GatewayEndpointStore {
|
||||
let token = self.deps.token()
|
||||
let password = self.deps.password()
|
||||
let scheme = GatewayEndpointStore.resolveGatewayScheme(
|
||||
root: ClawdbotConfigFile.loadDict(),
|
||||
root: MoltbotConfigFile.loadDict(),
|
||||
env: ProcessInfo.processInfo.environment)
|
||||
let url = URL(string: "\(scheme)://127.0.0.1:\(Int(forwarded))")!
|
||||
self.setState(.ready(mode: .remote, url: url, token: token, password: password))
|
||||
@@ -525,7 +525,7 @@ actor GatewayEndpointStore {
|
||||
let mode = await self.deps.mode()
|
||||
guard mode == .local else { return nil }
|
||||
|
||||
let root = ClawdbotConfigFile.loadDict()
|
||||
let root = MoltbotConfigFile.loadDict()
|
||||
let bind = GatewayEndpointStore.resolveGatewayBindMode(
|
||||
root: root,
|
||||
env: ProcessInfo.processInfo.environment)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotIPC
|
||||
import MoltbotIPC
|
||||
import Foundation
|
||||
import OSLog
|
||||
|
||||
@@ -76,7 +76,7 @@ enum GatewayEnvironment {
|
||||
let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if let parsed = Int(trimmed), parsed > 0 { return parsed }
|
||||
}
|
||||
if let configPort = ClawdbotConfigFile.gatewayPort(), configPort > 0 {
|
||||
if let configPort = MoltbotConfigFile.gatewayPort(), configPort > 0 {
|
||||
return configPort
|
||||
}
|
||||
let stored = UserDefaults.standard.integer(forKey: "gatewayPort")
|
||||
@@ -131,7 +131,7 @@ enum GatewayEnvironment {
|
||||
nodeVersion: runtime.version.description,
|
||||
gatewayVersion: nil,
|
||||
requiredGateway: expectedString,
|
||||
message: "clawdbot CLI not found in PATH; install the CLI.")
|
||||
message: "moltbot CLI not found in PATH; install the CLI.")
|
||||
}
|
||||
|
||||
let installed = gatewayBin.flatMap { self.readGatewayVersion(binary: $0) }
|
||||
@@ -217,7 +217,7 @@ enum GatewayEnvironment {
|
||||
}
|
||||
}
|
||||
|
||||
let root = ClawdbotConfigFile.loadDict()
|
||||
let root = MoltbotConfigFile.loadDict()
|
||||
if let gateway = root["gateway"] as? [String: Any],
|
||||
let bind = gateway["bind"] as? String
|
||||
{
|
||||
@@ -247,16 +247,16 @@ enum GatewayEnvironment {
|
||||
let bun = CommandResolver.findExecutable(named: "bun")
|
||||
let (label, cmd): (String, [String]) =
|
||||
if let npm {
|
||||
("npm", [npm, "install", "-g", "clawdbot@\(target)"])
|
||||
("npm", [npm, "install", "-g", "moltbot@\(target)"])
|
||||
} else if let pnpm {
|
||||
("pnpm", [pnpm, "add", "-g", "clawdbot@\(target)"])
|
||||
("pnpm", [pnpm, "add", "-g", "moltbot@\(target)"])
|
||||
} else if let bun {
|
||||
("bun", [bun, "add", "-g", "clawdbot@\(target)"])
|
||||
("bun", [bun, "add", "-g", "moltbot@\(target)"])
|
||||
} else {
|
||||
("npm", ["npm", "install", "-g", "clawdbot@\(target)"])
|
||||
("npm", ["npm", "install", "-g", "moltbot@\(target)"])
|
||||
}
|
||||
|
||||
statusHandler("Installing clawdbot@\(target) via \(label)…")
|
||||
statusHandler("Installing moltbot@\(target) via \(label)…")
|
||||
|
||||
func summarize(_ text: String) -> String? {
|
||||
let lines = text
|
||||
@@ -270,7 +270,7 @@ enum GatewayEnvironment {
|
||||
|
||||
let response = await ShellExecutor.runDetailed(command: cmd, cwd: nil, env: ["PATH": preferred], timeout: 300)
|
||||
if response.success {
|
||||
statusHandler("Installed clawdbot@\(target)")
|
||||
statusHandler("Installed moltbot@\(target)")
|
||||
} else {
|
||||
if response.timedOut {
|
||||
statusHandler("Install failed: timed out. Check your internet connection and try again.")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import AppKit
|
||||
import ClawdbotDiscovery
|
||||
import ClawdbotIPC
|
||||
import ClawdbotKit
|
||||
import MoltbotDiscovery
|
||||
import MoltbotIPC
|
||||
import MoltbotKit
|
||||
import Observation
|
||||
import SwiftUI
|
||||
|
||||
@@ -24,8 +24,8 @@ struct GeneralSettings: View {
|
||||
VStack(alignment: .leading, spacing: 18) {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
SettingsToggleRow(
|
||||
title: "Clawdbot active",
|
||||
subtitle: "Pause to stop the Clawdbot gateway; no messages will be processed.",
|
||||
title: "Moltbot active",
|
||||
subtitle: "Pause to stop the Moltbot gateway; no messages will be processed.",
|
||||
binding: self.activeBinding)
|
||||
|
||||
self.connectionSection
|
||||
@@ -34,12 +34,12 @@ struct GeneralSettings: View {
|
||||
|
||||
SettingsToggleRow(
|
||||
title: "Launch at login",
|
||||
subtitle: "Automatically start Clawdbot after you sign in.",
|
||||
subtitle: "Automatically start Moltbot after you sign in.",
|
||||
binding: self.$state.launchAtLogin)
|
||||
|
||||
SettingsToggleRow(
|
||||
title: "Show Dock icon",
|
||||
subtitle: "Keep Clawdbot visible in the Dock instead of menu-bar-only mode.",
|
||||
subtitle: "Keep Moltbot visible in the Dock instead of menu-bar-only mode.",
|
||||
binding: self.$state.showDockIcon)
|
||||
|
||||
SettingsToggleRow(
|
||||
@@ -71,7 +71,7 @@ struct GeneralSettings: View {
|
||||
Spacer(minLength: 12)
|
||||
HStack {
|
||||
Spacer()
|
||||
Button("Quit Clawdbot") { NSApp.terminate(nil) }
|
||||
Button("Quit Moltbot") { NSApp.terminate(nil) }
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
}
|
||||
@@ -98,7 +98,7 @@ struct GeneralSettings: View {
|
||||
|
||||
private var connectionSection: some View {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
Text("Clawdbot runs")
|
||||
Text("Moltbot runs")
|
||||
.font(.title3.weight(.semibold))
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
@@ -167,12 +167,12 @@ struct GeneralSettings: View {
|
||||
.frame(width: 280)
|
||||
}
|
||||
LabeledContent("Project root") {
|
||||
TextField("/home/you/Projects/clawdbot", text: self.$state.remoteProjectRoot)
|
||||
TextField("/home/you/Projects/moltbot", text: self.$state.remoteProjectRoot)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.frame(width: 280)
|
||||
}
|
||||
LabeledContent("CLI path") {
|
||||
TextField("/Applications/Clawdbot.app/.../clawdbot", text: self.$state.remoteCliPath)
|
||||
TextField("/Applications/Moltbot.app/.../moltbot", text: self.$state.remoteCliPath)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.frame(width: 280)
|
||||
}
|
||||
@@ -659,7 +659,7 @@ extension GeneralSettings {
|
||||
let alert = NSAlert()
|
||||
alert.messageText = "Log file not found"
|
||||
alert.informativeText = """
|
||||
Looked for clawdbot logs in /tmp/clawdbot/.
|
||||
Looked for moltbot logs in /tmp/moltbot/.
|
||||
Run a health check or send a message to generate activity, then try again.
|
||||
"""
|
||||
alert.alertStyle = .informational
|
||||
@@ -683,7 +683,7 @@ extension GeneralSettings {
|
||||
host: host,
|
||||
port: gateway.sshPort)
|
||||
self.state.remoteCliPath = gateway.cliPath ?? ""
|
||||
ClawdbotConfigFile.setRemoteGatewayUrl(host: host, port: gateway.gatewayPort)
|
||||
MoltbotConfigFile.setRemoteGatewayUrl(host: host, port: gateway.gatewayPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -711,8 +711,8 @@ extension GeneralSettings {
|
||||
state.remoteTarget = "user@host:2222"
|
||||
state.remoteUrl = "wss://gateway.example.ts.net"
|
||||
state.remoteIdentity = "/tmp/id_ed25519"
|
||||
state.remoteProjectRoot = "/tmp/clawdbot"
|
||||
state.remoteCliPath = "/tmp/clawdbot"
|
||||
state.remoteProjectRoot = "/tmp/moltbot"
|
||||
state.remoteCliPath = "/tmp/moltbot"
|
||||
|
||||
let view = GeneralSettings(state: state)
|
||||
view.gatewayStatus = GatewayEnvironmentStatus(
|
||||
|
||||
@@ -221,9 +221,9 @@ final class HealthStore {
|
||||
if let fallback = self.resolveFallbackChannel(snap, excluding: link.id) {
|
||||
let fallbackLabel = snap.channelLabels?[fallback.id] ?? fallback.id.capitalized
|
||||
let fallbackState = (fallback.summary.probe?.ok ?? true) ? "ok" : "degraded"
|
||||
return "\(fallbackLabel) \(fallbackState) · Not linked — run clawdbot login"
|
||||
return "\(fallbackLabel) \(fallbackState) · Not linked — run moltbot login"
|
||||
}
|
||||
return "Not linked — run clawdbot login"
|
||||
return "Not linked — run moltbot login"
|
||||
}
|
||||
let auth = link.summary.authAgeMs.map { msToAge($0) } ?? "unknown"
|
||||
if let probe = link.summary.probe, probe.ok == false {
|
||||
@@ -241,7 +241,7 @@ final class HealthStore {
|
||||
if lower.contains("connection refused") {
|
||||
let port = GatewayEnvironment.gatewayPort()
|
||||
let host = GatewayConnectivityCoordinator.shared.localEndpointHostLabel ?? "127.0.0.1:\(port)"
|
||||
return "The gateway control port (\(host)) isn’t listening — restart Clawdbot to bring it back."
|
||||
return "The gateway control port (\(host)) isn’t listening — restart Moltbot to bring it back."
|
||||
}
|
||||
if lower.contains("timeout") {
|
||||
return "Timed out waiting for the control server; the gateway may be crashed or still starting."
|
||||
@@ -253,7 +253,7 @@ final class HealthStore {
|
||||
|
||||
func describeFailure(from snap: HealthSnapshot, fallback: String?) -> String {
|
||||
if let link = self.resolveLinkChannel(snap), link.summary.linked != true {
|
||||
return "Not linked — run clawdbot login"
|
||||
return "Not linked — run moltbot login"
|
||||
}
|
||||
if let link = self.resolveLinkChannel(snap), let probe = link.summary.probe, probe.ok == false {
|
||||
return Self.describeProbeFailure(probe)
|
||||
|
||||
@@ -38,7 +38,7 @@ struct InstancesSettings: View {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text("Connected Instances")
|
||||
.font(.headline)
|
||||
Text("Latest presence beacons from Clawdbot nodes. Updated periodically.")
|
||||
Text("Latest presence beacons from Moltbot nodes. Updated periodically.")
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ClawdbotKit
|
||||
import ClawdbotProtocol
|
||||
import MoltbotKit
|
||||
import MoltbotProtocol
|
||||
import Cocoa
|
||||
import Foundation
|
||||
import Observation
|
||||
@@ -293,7 +293,7 @@ final class InstancesStore {
|
||||
}
|
||||
}
|
||||
|
||||
func handlePresenceEventPayload(_ payload: ClawdbotProtocol.AnyCodable) {
|
||||
func handlePresenceEventPayload(_ payload: MoltbotProtocol.AnyCodable) {
|
||||
do {
|
||||
let wrapper = try GatewayPayloadDecoding.decode(payload, as: PresenceEventPayload.self)
|
||||
self.applyPresence(wrapper.presence)
|
||||
|
||||
@@ -43,7 +43,7 @@ enum LaunchAgentManager {
|
||||
<string>com.clawdbot.mac</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>\(bundlePath)/Contents/MacOS/Clawdbot</string>
|
||||
<string>\(bundlePath)/Contents/MacOS/Moltbot</string>
|
||||
</array>
|
||||
<key>WorkingDirectory</key>
|
||||
<string>\(FileManager().homeDirectoryForCurrentUser.path)</string>
|
||||
|
||||
@@ -8,12 +8,12 @@ enum LaunchdManager {
|
||||
try? process.run()
|
||||
}
|
||||
|
||||
static func startClawdbot() {
|
||||
static func startMoltbot() {
|
||||
let userTarget = "gui/\(getuid())/\(launchdLabel)"
|
||||
self.runLaunchctl(["kickstart", "-k", userTarget])
|
||||
}
|
||||
|
||||
static func stopClawdbot() {
|
||||
static func stopMoltbot() {
|
||||
let userTarget = "gui/\(getuid())/\(launchdLabel)"
|
||||
self.runLaunchctl(["stop", userTarget])
|
||||
}
|
||||
|
||||
@@ -6,15 +6,15 @@ enum LogLocator {
|
||||
return URL(fileURLWithPath: override)
|
||||
}
|
||||
|
||||
return URL(fileURLWithPath: "/tmp/clawdbot")
|
||||
return URL(fileURLWithPath: "/tmp/moltbot")
|
||||
}
|
||||
|
||||
private static var stdoutLog: URL {
|
||||
logDir.appendingPathComponent("clawdbot-stdout.log")
|
||||
logDir.appendingPathComponent("moltbot-stdout.log")
|
||||
}
|
||||
|
||||
private static var gatewayLog: URL {
|
||||
logDir.appendingPathComponent("clawdbot-gateway.log")
|
||||
logDir.appendingPathComponent("moltbot-gateway.log")
|
||||
}
|
||||
|
||||
private static func ensureLogDirExists() {
|
||||
@@ -25,7 +25,7 @@ enum LogLocator {
|
||||
(try? url.resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate) ?? .distantPast
|
||||
}
|
||||
|
||||
/// Returns the newest log file under /tmp/clawdbot/ (rolling or stdout), or nil if none exist.
|
||||
/// Returns the newest log file under /tmp/moltbot/ (rolling or stdout), or nil if none exist.
|
||||
static func bestLogFile() -> URL? {
|
||||
self.ensureLogDirExists()
|
||||
let fm = FileManager()
|
||||
@@ -35,7 +35,7 @@ enum LogLocator {
|
||||
options: [.skipsHiddenFiles])) ?? []
|
||||
|
||||
return files
|
||||
.filter { $0.lastPathComponent.hasPrefix("clawdbot") && $0.pathExtension == "log" }
|
||||
.filter { $0.lastPathComponent.hasPrefix("moltbot") && $0.pathExtension == "log" }
|
||||
.max { lhs, rhs in
|
||||
self.modificationDate(for: lhs) < self.modificationDate(for: rhs)
|
||||
}
|
||||
|
||||
@@ -52,14 +52,14 @@ enum AppLogLevel: String, CaseIterable, Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
enum ClawdbotLogging {
|
||||
enum MoltbotLogging {
|
||||
private static let labelSeparator = "::"
|
||||
|
||||
private static let didBootstrap: Void = {
|
||||
LoggingSystem.bootstrap { label in
|
||||
let (subsystem, category) = Self.parseLabel(label)
|
||||
let osHandler = ClawdbotOSLogHandler(subsystem: subsystem, category: category)
|
||||
let fileHandler = ClawdbotFileLogHandler(label: label)
|
||||
let osHandler = MoltbotOSLogHandler(subsystem: subsystem, category: category)
|
||||
let fileHandler = MoltbotFileLogHandler(label: label)
|
||||
return MultiplexLogHandler([osHandler, fileHandler])
|
||||
}
|
||||
}()
|
||||
@@ -84,8 +84,8 @@ enum ClawdbotLogging {
|
||||
|
||||
extension Logging.Logger {
|
||||
init(subsystem: String, category: String) {
|
||||
ClawdbotLogging.bootstrapIfNeeded()
|
||||
let label = ClawdbotLogging.makeLabel(subsystem: subsystem, category: category)
|
||||
MoltbotLogging.bootstrapIfNeeded()
|
||||
let label = MoltbotLogging.makeLabel(subsystem: subsystem, category: category)
|
||||
self.init(label: label)
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,7 @@ extension Logger.Message.StringInterpolation {
|
||||
}
|
||||
}
|
||||
|
||||
struct ClawdbotOSLogHandler: LogHandler {
|
||||
struct MoltbotOSLogHandler: LogHandler {
|
||||
private let osLogger: os.Logger
|
||||
var metadata: Logger.Metadata = [:]
|
||||
|
||||
@@ -174,7 +174,7 @@ struct ClawdbotOSLogHandler: LogHandler {
|
||||
}
|
||||
}
|
||||
|
||||
struct ClawdbotFileLogHandler: LogHandler {
|
||||
struct MoltbotFileLogHandler: LogHandler {
|
||||
let label: String
|
||||
var metadata: Logger.Metadata = [:]
|
||||
|
||||
@@ -198,7 +198,7 @@ struct ClawdbotFileLogHandler: LogHandler {
|
||||
line: UInt)
|
||||
{
|
||||
guard AppLogSettings.fileLoggingEnabled() else { return }
|
||||
let (subsystem, category) = ClawdbotLogging.parseLabel(self.label)
|
||||
let (subsystem, category) = MoltbotLogging.parseLabel(self.label)
|
||||
var fields: [String: String] = [
|
||||
"subsystem": subsystem,
|
||||
"category": category,
|
||||
|
||||
@@ -8,7 +8,7 @@ import Security
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct ClawdbotApp: App {
|
||||
struct MoltbotApp: App {
|
||||
@NSApplicationDelegateAdaptor(AppDelegate.self) private var delegate
|
||||
@State private var state: AppState
|
||||
private static let logger = Logger(subsystem: "com.clawdbot", category: "app")
|
||||
@@ -32,7 +32,7 @@ struct ClawdbotApp: App {
|
||||
}
|
||||
|
||||
init() {
|
||||
ClawdbotLogging.bootstrapIfNeeded()
|
||||
MoltbotLogging.bootstrapIfNeeded()
|
||||
Self.applyAttachOnlyOverrideIfNeeded()
|
||||
_state = State(initialValue: AppStateStore.shared)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import Foundation
|
||||
import Observation
|
||||
import SwiftUI
|
||||
|
||||
/// Menu contents for the Clawdbot menu bar extra.
|
||||
/// Menu contents for the Moltbot menu bar extra.
|
||||
struct MenuContent: View {
|
||||
@Bindable var state: AppState
|
||||
let updater: UpdaterProviding?
|
||||
@@ -149,7 +149,7 @@ struct MenuContent: View {
|
||||
Button("Settings…") { self.open(tab: .general) }
|
||||
.keyboardShortcut(",", modifiers: [.command])
|
||||
self.debugMenu
|
||||
Button("About Clawdbot") { self.open(tab: .about) }
|
||||
Button("About Moltbot") { self.open(tab: .about) }
|
||||
if let updater, updater.isAvailable, self.updateStatus.isUpdateReady {
|
||||
Button("Update ready, restart now?") { updater.checkForUpdates(nil) }
|
||||
}
|
||||
@@ -185,11 +185,11 @@ struct MenuContent: View {
|
||||
private var connectionLabel: String {
|
||||
switch self.state.connectionMode {
|
||||
case .unconfigured:
|
||||
"Clawdbot Not Configured"
|
||||
"Moltbot Not Configured"
|
||||
case .remote:
|
||||
"Remote Clawdbot Active"
|
||||
"Remote Moltbot Active"
|
||||
case .local:
|
||||
"Clawdbot Active"
|
||||
"Moltbot Active"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ enum ModelCatalogLoader {
|
||||
private static let logger = Logger(subsystem: "com.clawdbot", category: "models")
|
||||
private nonisolated static let appSupportDir: URL = {
|
||||
let base = FileManager().urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
|
||||
return base.appendingPathComponent("Clawdbot", isDirectory: true)
|
||||
return base.appendingPathComponent("Moltbot", isDirectory: true)
|
||||
}()
|
||||
|
||||
private static var cachePath: URL {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import CoreLocation
|
||||
import Foundation
|
||||
|
||||
@@ -30,7 +30,7 @@ final class MacNodeLocationService: NSObject, CLLocationManagerDelegate {
|
||||
}
|
||||
|
||||
func currentLocation(
|
||||
desiredAccuracy: ClawdbotLocationAccuracy,
|
||||
desiredAccuracy: MoltbotLocationAccuracy,
|
||||
maxAgeMs: Int?,
|
||||
timeoutMs: Int?) async throws -> CLLocation
|
||||
{
|
||||
@@ -103,7 +103,7 @@ final class MacNodeLocationService: NSObject, CLLocationManagerDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
private static func accuracyValue(_ accuracy: ClawdbotLocationAccuracy) -> CLLocationAccuracy {
|
||||
private static func accuracyValue(_ accuracy: MoltbotLocationAccuracy) -> CLLocationAccuracy {
|
||||
switch accuracy {
|
||||
case .coarse:
|
||||
kCLLocationAccuracyKilometer
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import OSLog
|
||||
|
||||
@@ -60,7 +60,7 @@ final class MacNodeModeCoordinator {
|
||||
caps: caps,
|
||||
commands: commands,
|
||||
permissions: permissions,
|
||||
clientId: "clawdbot-macos",
|
||||
clientId: "moltbot-macos",
|
||||
clientMode: "node",
|
||||
clientDisplayName: InstanceIdentity.displayName)
|
||||
let sessionBox = self.buildSessionBox(url: config.url)
|
||||
@@ -91,7 +91,7 @@ final class MacNodeModeCoordinator {
|
||||
return BridgeInvokeResponse(
|
||||
id: req.id,
|
||||
ok: false,
|
||||
error: ClawdbotNodeError(code: .unavailable, message: "UNAVAILABLE: node not ready"))
|
||||
error: MoltbotNodeError(code: .unavailable, message: "UNAVAILABLE: node not ready"))
|
||||
}
|
||||
return await self.runtime.handleInvoke(req)
|
||||
})
|
||||
@@ -107,13 +107,13 @@ final class MacNodeModeCoordinator {
|
||||
}
|
||||
|
||||
private func currentCaps() -> [String] {
|
||||
var caps: [String] = [ClawdbotCapability.canvas.rawValue, ClawdbotCapability.screen.rawValue]
|
||||
var caps: [String] = [MoltbotCapability.canvas.rawValue, MoltbotCapability.screen.rawValue]
|
||||
if UserDefaults.standard.object(forKey: cameraEnabledKey) as? Bool ?? false {
|
||||
caps.append(ClawdbotCapability.camera.rawValue)
|
||||
caps.append(MoltbotCapability.camera.rawValue)
|
||||
}
|
||||
let rawLocationMode = UserDefaults.standard.string(forKey: locationModeKey) ?? "off"
|
||||
if ClawdbotLocationMode(rawValue: rawLocationMode) != .off {
|
||||
caps.append(ClawdbotCapability.location.rawValue)
|
||||
if MoltbotLocationMode(rawValue: rawLocationMode) != .off {
|
||||
caps.append(MoltbotCapability.location.rawValue)
|
||||
}
|
||||
return caps
|
||||
}
|
||||
@@ -125,30 +125,30 @@ final class MacNodeModeCoordinator {
|
||||
|
||||
private func currentCommands(caps: [String]) -> [String] {
|
||||
var commands: [String] = [
|
||||
ClawdbotCanvasCommand.present.rawValue,
|
||||
ClawdbotCanvasCommand.hide.rawValue,
|
||||
ClawdbotCanvasCommand.navigate.rawValue,
|
||||
ClawdbotCanvasCommand.evalJS.rawValue,
|
||||
ClawdbotCanvasCommand.snapshot.rawValue,
|
||||
ClawdbotCanvasA2UICommand.push.rawValue,
|
||||
ClawdbotCanvasA2UICommand.pushJSONL.rawValue,
|
||||
ClawdbotCanvasA2UICommand.reset.rawValue,
|
||||
MoltbotCanvasCommand.present.rawValue,
|
||||
MoltbotCanvasCommand.hide.rawValue,
|
||||
MoltbotCanvasCommand.navigate.rawValue,
|
||||
MoltbotCanvasCommand.evalJS.rawValue,
|
||||
MoltbotCanvasCommand.snapshot.rawValue,
|
||||
MoltbotCanvasA2UICommand.push.rawValue,
|
||||
MoltbotCanvasA2UICommand.pushJSONL.rawValue,
|
||||
MoltbotCanvasA2UICommand.reset.rawValue,
|
||||
MacNodeScreenCommand.record.rawValue,
|
||||
ClawdbotSystemCommand.notify.rawValue,
|
||||
ClawdbotSystemCommand.which.rawValue,
|
||||
ClawdbotSystemCommand.run.rawValue,
|
||||
ClawdbotSystemCommand.execApprovalsGet.rawValue,
|
||||
ClawdbotSystemCommand.execApprovalsSet.rawValue,
|
||||
MoltbotSystemCommand.notify.rawValue,
|
||||
MoltbotSystemCommand.which.rawValue,
|
||||
MoltbotSystemCommand.run.rawValue,
|
||||
MoltbotSystemCommand.execApprovalsGet.rawValue,
|
||||
MoltbotSystemCommand.execApprovalsSet.rawValue,
|
||||
]
|
||||
|
||||
let capsSet = Set(caps)
|
||||
if capsSet.contains(ClawdbotCapability.camera.rawValue) {
|
||||
commands.append(ClawdbotCameraCommand.list.rawValue)
|
||||
commands.append(ClawdbotCameraCommand.snap.rawValue)
|
||||
commands.append(ClawdbotCameraCommand.clip.rawValue)
|
||||
if capsSet.contains(MoltbotCapability.camera.rawValue) {
|
||||
commands.append(MoltbotCameraCommand.list.rawValue)
|
||||
commands.append(MoltbotCameraCommand.snap.rawValue)
|
||||
commands.append(MoltbotCameraCommand.clip.rawValue)
|
||||
}
|
||||
if capsSet.contains(ClawdbotCapability.location.rawValue) {
|
||||
commands.append(ClawdbotLocationCommand.get.rawValue)
|
||||
if capsSet.contains(MoltbotCapability.location.rawValue) {
|
||||
commands.append(MoltbotLocationCommand.get.rawValue)
|
||||
}
|
||||
|
||||
return commands
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import AppKit
|
||||
import ClawdbotIPC
|
||||
import ClawdbotKit
|
||||
import MoltbotIPC
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
|
||||
actor MacNodeRuntime {
|
||||
@@ -34,39 +34,39 @@ actor MacNodeRuntime {
|
||||
return BridgeInvokeResponse(
|
||||
id: req.id,
|
||||
ok: false,
|
||||
error: ClawdbotNodeError(
|
||||
error: MoltbotNodeError(
|
||||
code: .unavailable,
|
||||
message: "CANVAS_DISABLED: enable Canvas in Settings"))
|
||||
}
|
||||
do {
|
||||
switch command {
|
||||
case ClawdbotCanvasCommand.present.rawValue,
|
||||
ClawdbotCanvasCommand.hide.rawValue,
|
||||
ClawdbotCanvasCommand.navigate.rawValue,
|
||||
ClawdbotCanvasCommand.evalJS.rawValue,
|
||||
ClawdbotCanvasCommand.snapshot.rawValue:
|
||||
case MoltbotCanvasCommand.present.rawValue,
|
||||
MoltbotCanvasCommand.hide.rawValue,
|
||||
MoltbotCanvasCommand.navigate.rawValue,
|
||||
MoltbotCanvasCommand.evalJS.rawValue,
|
||||
MoltbotCanvasCommand.snapshot.rawValue:
|
||||
return try await self.handleCanvasInvoke(req)
|
||||
case ClawdbotCanvasA2UICommand.reset.rawValue,
|
||||
ClawdbotCanvasA2UICommand.push.rawValue,
|
||||
ClawdbotCanvasA2UICommand.pushJSONL.rawValue:
|
||||
case MoltbotCanvasA2UICommand.reset.rawValue,
|
||||
MoltbotCanvasA2UICommand.push.rawValue,
|
||||
MoltbotCanvasA2UICommand.pushJSONL.rawValue:
|
||||
return try await self.handleA2UIInvoke(req)
|
||||
case ClawdbotCameraCommand.snap.rawValue,
|
||||
ClawdbotCameraCommand.clip.rawValue,
|
||||
ClawdbotCameraCommand.list.rawValue:
|
||||
case MoltbotCameraCommand.snap.rawValue,
|
||||
MoltbotCameraCommand.clip.rawValue,
|
||||
MoltbotCameraCommand.list.rawValue:
|
||||
return try await self.handleCameraInvoke(req)
|
||||
case ClawdbotLocationCommand.get.rawValue:
|
||||
case MoltbotLocationCommand.get.rawValue:
|
||||
return try await self.handleLocationInvoke(req)
|
||||
case MacNodeScreenCommand.record.rawValue:
|
||||
return try await self.handleScreenRecordInvoke(req)
|
||||
case ClawdbotSystemCommand.run.rawValue:
|
||||
case MoltbotSystemCommand.run.rawValue:
|
||||
return try await self.handleSystemRun(req)
|
||||
case ClawdbotSystemCommand.which.rawValue:
|
||||
case MoltbotSystemCommand.which.rawValue:
|
||||
return try await self.handleSystemWhich(req)
|
||||
case ClawdbotSystemCommand.notify.rawValue:
|
||||
case MoltbotSystemCommand.notify.rawValue:
|
||||
return try await self.handleSystemNotify(req)
|
||||
case ClawdbotSystemCommand.execApprovalsGet.rawValue:
|
||||
case MoltbotSystemCommand.execApprovalsGet.rawValue:
|
||||
return try await self.handleSystemExecApprovalsGet(req)
|
||||
case ClawdbotSystemCommand.execApprovalsSet.rawValue:
|
||||
case MoltbotSystemCommand.execApprovalsSet.rawValue:
|
||||
return try await self.handleSystemExecApprovalsSet(req)
|
||||
default:
|
||||
return Self.errorResponse(req, code: .invalidRequest, message: "INVALID_REQUEST: unknown command")
|
||||
@@ -82,9 +82,9 @@ actor MacNodeRuntime {
|
||||
|
||||
private func handleCanvasInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse {
|
||||
switch req.command {
|
||||
case ClawdbotCanvasCommand.present.rawValue:
|
||||
let params = (try? Self.decodeParams(ClawdbotCanvasPresentParams.self, from: req.paramsJSON)) ??
|
||||
ClawdbotCanvasPresentParams()
|
||||
case MoltbotCanvasCommand.present.rawValue:
|
||||
let params = (try? Self.decodeParams(MoltbotCanvasPresentParams.self, from: req.paramsJSON)) ??
|
||||
MoltbotCanvasPresentParams()
|
||||
let urlTrimmed = params.url?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
let url = urlTrimmed.isEmpty ? nil : urlTrimmed
|
||||
let placement = params.placement.map {
|
||||
@@ -98,29 +98,29 @@ actor MacNodeRuntime {
|
||||
placement: placement)
|
||||
}
|
||||
return BridgeInvokeResponse(id: req.id, ok: true)
|
||||
case ClawdbotCanvasCommand.hide.rawValue:
|
||||
case MoltbotCanvasCommand.hide.rawValue:
|
||||
let sessionKey = self.mainSessionKey
|
||||
await MainActor.run {
|
||||
CanvasManager.shared.hide(sessionKey: sessionKey)
|
||||
}
|
||||
return BridgeInvokeResponse(id: req.id, ok: true)
|
||||
case ClawdbotCanvasCommand.navigate.rawValue:
|
||||
let params = try Self.decodeParams(ClawdbotCanvasNavigateParams.self, from: req.paramsJSON)
|
||||
case MoltbotCanvasCommand.navigate.rawValue:
|
||||
let params = try Self.decodeParams(MoltbotCanvasNavigateParams.self, from: req.paramsJSON)
|
||||
let sessionKey = self.mainSessionKey
|
||||
try await MainActor.run {
|
||||
_ = try CanvasManager.shared.show(sessionKey: sessionKey, path: params.url)
|
||||
}
|
||||
return BridgeInvokeResponse(id: req.id, ok: true)
|
||||
case ClawdbotCanvasCommand.evalJS.rawValue:
|
||||
let params = try Self.decodeParams(ClawdbotCanvasEvalParams.self, from: req.paramsJSON)
|
||||
case MoltbotCanvasCommand.evalJS.rawValue:
|
||||
let params = try Self.decodeParams(MoltbotCanvasEvalParams.self, from: req.paramsJSON)
|
||||
let sessionKey = self.mainSessionKey
|
||||
let result = try await CanvasManager.shared.eval(
|
||||
sessionKey: sessionKey,
|
||||
javaScript: params.javaScript)
|
||||
let payload = try Self.encodePayload(["result": result] as [String: String])
|
||||
return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload)
|
||||
case ClawdbotCanvasCommand.snapshot.rawValue:
|
||||
let params = try? Self.decodeParams(ClawdbotCanvasSnapshotParams.self, from: req.paramsJSON)
|
||||
case MoltbotCanvasCommand.snapshot.rawValue:
|
||||
let params = try? Self.decodeParams(MoltbotCanvasSnapshotParams.self, from: req.paramsJSON)
|
||||
let format = params?.format ?? .jpeg
|
||||
let maxWidth: Int? = {
|
||||
if let raw = params?.maxWidth, raw > 0 { return raw }
|
||||
@@ -155,10 +155,10 @@ actor MacNodeRuntime {
|
||||
|
||||
private func handleA2UIInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse {
|
||||
switch req.command {
|
||||
case ClawdbotCanvasA2UICommand.reset.rawValue:
|
||||
case MoltbotCanvasA2UICommand.reset.rawValue:
|
||||
try await self.handleA2UIReset(req)
|
||||
case ClawdbotCanvasA2UICommand.push.rawValue,
|
||||
ClawdbotCanvasA2UICommand.pushJSONL.rawValue:
|
||||
case MoltbotCanvasA2UICommand.push.rawValue,
|
||||
MoltbotCanvasA2UICommand.pushJSONL.rawValue:
|
||||
try await self.handleA2UIPush(req)
|
||||
default:
|
||||
Self.errorResponse(req, code: .invalidRequest, message: "INVALID_REQUEST: unknown command")
|
||||
@@ -170,14 +170,14 @@ actor MacNodeRuntime {
|
||||
return BridgeInvokeResponse(
|
||||
id: req.id,
|
||||
ok: false,
|
||||
error: ClawdbotNodeError(
|
||||
error: MoltbotNodeError(
|
||||
code: .unavailable,
|
||||
message: "CAMERA_DISABLED: enable Camera in Settings"))
|
||||
}
|
||||
switch req.command {
|
||||
case ClawdbotCameraCommand.snap.rawValue:
|
||||
let params = (try? Self.decodeParams(ClawdbotCameraSnapParams.self, from: req.paramsJSON)) ??
|
||||
ClawdbotCameraSnapParams()
|
||||
case MoltbotCameraCommand.snap.rawValue:
|
||||
let params = (try? Self.decodeParams(MoltbotCameraSnapParams.self, from: req.paramsJSON)) ??
|
||||
MoltbotCameraSnapParams()
|
||||
let delayMs = min(10000, max(0, params.delayMs ?? 2000))
|
||||
let res = try await self.cameraCapture.snap(
|
||||
facing: CameraFacing(rawValue: params.facing?.rawValue ?? "") ?? .front,
|
||||
@@ -197,9 +197,9 @@ actor MacNodeRuntime {
|
||||
width: Int(res.size.width),
|
||||
height: Int(res.size.height)))
|
||||
return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload)
|
||||
case ClawdbotCameraCommand.clip.rawValue:
|
||||
let params = (try? Self.decodeParams(ClawdbotCameraClipParams.self, from: req.paramsJSON)) ??
|
||||
ClawdbotCameraClipParams()
|
||||
case MoltbotCameraCommand.clip.rawValue:
|
||||
let params = (try? Self.decodeParams(MoltbotCameraClipParams.self, from: req.paramsJSON)) ??
|
||||
MoltbotCameraClipParams()
|
||||
let res = try await self.cameraCapture.clip(
|
||||
facing: CameraFacing(rawValue: params.facing?.rawValue ?? "") ?? .front,
|
||||
durationMs: params.durationMs,
|
||||
@@ -220,7 +220,7 @@ actor MacNodeRuntime {
|
||||
durationMs: res.durationMs,
|
||||
hasAudio: res.hasAudio))
|
||||
return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload)
|
||||
case ClawdbotCameraCommand.list.rawValue:
|
||||
case MoltbotCameraCommand.list.rawValue:
|
||||
let devices = await self.cameraCapture.listDevices()
|
||||
let payload = try Self.encodePayload(["devices": devices])
|
||||
return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload)
|
||||
@@ -235,12 +235,12 @@ actor MacNodeRuntime {
|
||||
return BridgeInvokeResponse(
|
||||
id: req.id,
|
||||
ok: false,
|
||||
error: ClawdbotNodeError(
|
||||
error: MoltbotNodeError(
|
||||
code: .unavailable,
|
||||
message: "LOCATION_DISABLED: enable Location in Settings"))
|
||||
}
|
||||
let params = (try? Self.decodeParams(ClawdbotLocationGetParams.self, from: req.paramsJSON)) ??
|
||||
ClawdbotLocationGetParams()
|
||||
let params = (try? Self.decodeParams(MoltbotLocationGetParams.self, from: req.paramsJSON)) ??
|
||||
MoltbotLocationGetParams()
|
||||
let desired = params.desiredAccuracy ??
|
||||
(Self.locationPreciseEnabled() ? .precise : .balanced)
|
||||
let services = await self.mainActorServices()
|
||||
@@ -257,7 +257,7 @@ actor MacNodeRuntime {
|
||||
return BridgeInvokeResponse(
|
||||
id: req.id,
|
||||
ok: false,
|
||||
error: ClawdbotNodeError(
|
||||
error: MoltbotNodeError(
|
||||
code: .unavailable,
|
||||
message: "LOCATION_PERMISSION_REQUIRED: grant Location permission"))
|
||||
}
|
||||
@@ -267,7 +267,7 @@ actor MacNodeRuntime {
|
||||
maxAgeMs: params.maxAgeMs,
|
||||
timeoutMs: params.timeoutMs)
|
||||
let isPrecise = await services.locationAccuracyAuthorization() == .fullAccuracy
|
||||
let payload = ClawdbotLocationPayload(
|
||||
let payload = MoltbotLocationPayload(
|
||||
lat: location.coordinate.latitude,
|
||||
lon: location.coordinate.longitude,
|
||||
accuracyMeters: location.horizontalAccuracy,
|
||||
@@ -283,14 +283,14 @@ actor MacNodeRuntime {
|
||||
return BridgeInvokeResponse(
|
||||
id: req.id,
|
||||
ok: false,
|
||||
error: ClawdbotNodeError(
|
||||
error: MoltbotNodeError(
|
||||
code: .unavailable,
|
||||
message: "LOCATION_TIMEOUT: no fix in time"))
|
||||
} catch {
|
||||
return BridgeInvokeResponse(
|
||||
id: req.id,
|
||||
ok: false,
|
||||
error: ClawdbotNodeError(
|
||||
error: MoltbotNodeError(
|
||||
code: .unavailable,
|
||||
message: "LOCATION_UNAVAILABLE: \(error.localizedDescription)"))
|
||||
}
|
||||
@@ -345,7 +345,7 @@ actor MacNodeRuntime {
|
||||
let sessionKey = self.mainSessionKey
|
||||
let json = try await CanvasManager.shared.eval(sessionKey: sessionKey, javaScript: """
|
||||
(() => {
|
||||
if (!globalThis.clawdbotA2UI) return JSON.stringify({ ok: false, error: "missing clawdbotA2UI" });
|
||||
if (!globalThis.clawdbotA2UI) return JSON.stringify({ ok: false, error: "missing moltbotA2UI" });
|
||||
return JSON.stringify(globalThis.clawdbotA2UI.reset());
|
||||
})()
|
||||
""")
|
||||
@@ -354,27 +354,27 @@ actor MacNodeRuntime {
|
||||
|
||||
private func handleA2UIPush(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse {
|
||||
let command = req.command
|
||||
let messages: [ClawdbotKit.AnyCodable]
|
||||
if command == ClawdbotCanvasA2UICommand.pushJSONL.rawValue {
|
||||
let params = try Self.decodeParams(ClawdbotCanvasA2UIPushJSONLParams.self, from: req.paramsJSON)
|
||||
messages = try ClawdbotCanvasA2UIJSONL.decodeMessagesFromJSONL(params.jsonl)
|
||||
let messages: [MoltbotKit.AnyCodable]
|
||||
if command == MoltbotCanvasA2UICommand.pushJSONL.rawValue {
|
||||
let params = try Self.decodeParams(MoltbotCanvasA2UIPushJSONLParams.self, from: req.paramsJSON)
|
||||
messages = try MoltbotCanvasA2UIJSONL.decodeMessagesFromJSONL(params.jsonl)
|
||||
} else {
|
||||
do {
|
||||
let params = try Self.decodeParams(ClawdbotCanvasA2UIPushParams.self, from: req.paramsJSON)
|
||||
let params = try Self.decodeParams(MoltbotCanvasA2UIPushParams.self, from: req.paramsJSON)
|
||||
messages = params.messages
|
||||
} catch {
|
||||
let params = try Self.decodeParams(ClawdbotCanvasA2UIPushJSONLParams.self, from: req.paramsJSON)
|
||||
messages = try ClawdbotCanvasA2UIJSONL.decodeMessagesFromJSONL(params.jsonl)
|
||||
let params = try Self.decodeParams(MoltbotCanvasA2UIPushJSONLParams.self, from: req.paramsJSON)
|
||||
messages = try MoltbotCanvasA2UIJSONL.decodeMessagesFromJSONL(params.jsonl)
|
||||
}
|
||||
}
|
||||
|
||||
try await self.ensureA2UIHost()
|
||||
|
||||
let messagesJSON = try ClawdbotCanvasA2UIJSONL.encodeMessagesJSONArray(messages)
|
||||
let messagesJSON = try MoltbotCanvasA2UIJSONL.encodeMessagesJSONArray(messages)
|
||||
let js = """
|
||||
(() => {
|
||||
try {
|
||||
if (!globalThis.clawdbotA2UI) return JSON.stringify({ ok: false, error: "missing clawdbotA2UI" });
|
||||
if (!globalThis.clawdbotA2UI) return JSON.stringify({ ok: false, error: "missing moltbotA2UI" });
|
||||
const messages = \(messagesJSON);
|
||||
return JSON.stringify(globalThis.clawdbotA2UI.applyMessages(messages));
|
||||
} catch (e) {
|
||||
@@ -408,7 +408,7 @@ actor MacNodeRuntime {
|
||||
guard let raw = await GatewayConnection.shared.canvasHostUrl() else { return nil }
|
||||
let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !trimmed.isEmpty, let baseUrl = URL(string: trimmed) else { return nil }
|
||||
return baseUrl.appendingPathComponent("__clawdbot__/a2ui/").absoluteString + "?platform=macos"
|
||||
return baseUrl.appendingPathComponent("__moltbot__/a2ui/").absoluteString + "?platform=macos"
|
||||
}
|
||||
|
||||
private func isA2UIReady(poll: Bool = false) async -> Bool {
|
||||
@@ -431,7 +431,7 @@ actor MacNodeRuntime {
|
||||
}
|
||||
|
||||
private func handleSystemRun(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse {
|
||||
let params = try Self.decodeParams(ClawdbotSystemRunParams.self, from: req.paramsJSON)
|
||||
let params = try Self.decodeParams(MoltbotSystemRunParams.self, from: req.paramsJSON)
|
||||
let command = params.command
|
||||
guard !command.isEmpty else {
|
||||
return Self.errorResponse(req, code: .invalidRequest, message: "INVALID_REQUEST: command required")
|
||||
@@ -593,7 +593,7 @@ actor MacNodeRuntime {
|
||||
}
|
||||
|
||||
private func handleSystemWhich(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse {
|
||||
let params = try Self.decodeParams(ClawdbotSystemWhichParams.self, from: req.paramsJSON)
|
||||
let params = try Self.decodeParams(MoltbotSystemWhichParams.self, from: req.paramsJSON)
|
||||
let bins = params.bins
|
||||
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
|
||||
.filter { !$0.isEmpty }
|
||||
@@ -639,7 +639,7 @@ actor MacNodeRuntime {
|
||||
|
||||
private func resolveSystemRunApproval(
|
||||
req: BridgeInvokeRequest,
|
||||
params: ClawdbotSystemRunParams,
|
||||
params: MoltbotSystemRunParams,
|
||||
context: ExecRunContext) async -> ExecApprovalOutcome
|
||||
{
|
||||
let requiresAsk = ExecApprovalHelpers.requiresAsk(
|
||||
@@ -790,7 +790,7 @@ actor MacNodeRuntime {
|
||||
}
|
||||
|
||||
private func handleSystemNotify(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse {
|
||||
let params = try Self.decodeParams(ClawdbotSystemNotifyParams.self, from: req.paramsJSON)
|
||||
let params = try Self.decodeParams(MoltbotSystemNotifyParams.self, from: req.paramsJSON)
|
||||
let title = params.title.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let body = params.body.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if title.isEmpty, body.isEmpty {
|
||||
@@ -886,9 +886,9 @@ extension MacNodeRuntime {
|
||||
return merged
|
||||
}
|
||||
|
||||
private nonisolated static func locationMode() -> ClawdbotLocationMode {
|
||||
private nonisolated static func locationMode() -> MoltbotLocationMode {
|
||||
let raw = UserDefaults.standard.string(forKey: locationModeKey) ?? "off"
|
||||
return ClawdbotLocationMode(rawValue: raw) ?? .off
|
||||
return MoltbotLocationMode(rawValue: raw) ?? .off
|
||||
}
|
||||
|
||||
private nonisolated static func locationPreciseEnabled() -> Bool {
|
||||
@@ -898,18 +898,18 @@ extension MacNodeRuntime {
|
||||
|
||||
private static func errorResponse(
|
||||
_ req: BridgeInvokeRequest,
|
||||
code: ClawdbotNodeErrorCode,
|
||||
code: MoltbotNodeErrorCode,
|
||||
message: String) -> BridgeInvokeResponse
|
||||
{
|
||||
BridgeInvokeResponse(
|
||||
id: req.id,
|
||||
ok: false,
|
||||
error: ClawdbotNodeError(code: code, message: message))
|
||||
error: MoltbotNodeError(code: code, message: message))
|
||||
}
|
||||
|
||||
private static func encodeCanvasSnapshot(
|
||||
image: NSImage,
|
||||
format: ClawdbotCanvasSnapshotFormat,
|
||||
format: MoltbotCanvasSnapshotFormat,
|
||||
maxWidth: Int?,
|
||||
quality: Double) throws -> Data
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import CoreLocation
|
||||
import Foundation
|
||||
|
||||
@@ -14,7 +14,7 @@ protocol MacNodeRuntimeMainActorServices: Sendable {
|
||||
func locationAuthorizationStatus() -> CLAuthorizationStatus
|
||||
func locationAccuracyAuthorization() -> CLAccuracyAuthorization
|
||||
func currentLocation(
|
||||
desiredAccuracy: ClawdbotLocationAccuracy,
|
||||
desiredAccuracy: MoltbotLocationAccuracy,
|
||||
maxAgeMs: Int?,
|
||||
timeoutMs: Int?) async throws -> CLLocation
|
||||
}
|
||||
@@ -48,7 +48,7 @@ final class LiveMacNodeRuntimeMainActorServices: MacNodeRuntimeMainActorServices
|
||||
}
|
||||
|
||||
func currentLocation(
|
||||
desiredAccuracy: ClawdbotLocationAccuracy,
|
||||
desiredAccuracy: MoltbotLocationAccuracy,
|
||||
maxAgeMs: Int?,
|
||||
timeoutMs: Int?) async throws -> CLLocation
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import AppKit
|
||||
import ClawdbotDiscovery
|
||||
import ClawdbotIPC
|
||||
import ClawdbotKit
|
||||
import ClawdbotProtocol
|
||||
import MoltbotDiscovery
|
||||
import MoltbotIPC
|
||||
import MoltbotKit
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
import Observation
|
||||
import OSLog
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotIPC
|
||||
import MoltbotIPC
|
||||
import Foundation
|
||||
import Security
|
||||
import UserNotifications
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import AppKit
|
||||
import ClawdbotChatUI
|
||||
import ClawdbotDiscovery
|
||||
import ClawdbotIPC
|
||||
import MoltbotChatUI
|
||||
import MoltbotDiscovery
|
||||
import MoltbotIPC
|
||||
import Combine
|
||||
import Observation
|
||||
import SwiftUI
|
||||
|
||||
enum UIStrings {
|
||||
static let welcomeTitle = "Welcome to Clawdbot"
|
||||
static let welcomeTitle = "Welcome to Moltbot"
|
||||
}
|
||||
|
||||
@MainActor
|
||||
@@ -18,7 +18,7 @@ final class OnboardingController {
|
||||
func show() {
|
||||
if ProcessInfo.processInfo.isNixMode {
|
||||
// Nix mode is fully declarative; onboarding would suggest interactive setup that doesn't apply.
|
||||
UserDefaults.standard.set(true, forKey: "clawdbot.onboardingSeen")
|
||||
UserDefaults.standard.set(true, forKey: "moltbot.onboardingSeen")
|
||||
UserDefaults.standard.set(currentOnboardingVersion, forKey: onboardingVersionKey)
|
||||
AppStateStore.shared.onboardingSeen = true
|
||||
return
|
||||
@@ -79,7 +79,7 @@ struct OnboardingView: View {
|
||||
@State var anthropicAuthVerificationAttempted = false
|
||||
@State var anthropicAuthVerificationFailed = false
|
||||
@State var anthropicAuthVerifiedAt: Date?
|
||||
@State var anthropicAuthDetectedStatus: ClawdbotOAuthStore.AnthropicOAuthStatus = .missingFile
|
||||
@State var anthropicAuthDetectedStatus: MoltbotOAuthStore.AnthropicOAuthStatus = .missingFile
|
||||
@State var anthropicAuthAutoDetectClipboard = true
|
||||
@State var anthropicAuthAutoConnectClipboard = true
|
||||
@State var anthropicAuthLastPasteboardChangeCount = NSPasteboard.general.changeCount
|
||||
@@ -90,7 +90,7 @@ struct OnboardingView: View {
|
||||
@State var showAdvancedConnection = false
|
||||
@State var preferredGatewayID: String?
|
||||
@State var gatewayDiscovery: GatewayDiscoveryModel
|
||||
@State var onboardingChatModel: ClawdbotChatViewModel
|
||||
@State var onboardingChatModel: MoltbotChatViewModel
|
||||
@State var onboardingSkillsModel = SkillsSettingsModel()
|
||||
@State var onboardingWizard = OnboardingWizardModel()
|
||||
@State var didLoadOnboardingSkills = false
|
||||
@@ -156,7 +156,7 @@ struct OnboardingView: View {
|
||||
var canAdvance: Bool { !self.isWizardBlocking }
|
||||
var devLinkCommand: String {
|
||||
let version = GatewayEnvironment.expectedGatewayVersionString() ?? "latest"
|
||||
return "npm install -g clawdbot@\(version)"
|
||||
return "npm install -g moltbot@\(version)"
|
||||
}
|
||||
|
||||
struct LocalGatewayProbe: Equatable {
|
||||
@@ -177,7 +177,7 @@ struct OnboardingView: View {
|
||||
self.permissionMonitor = permissionMonitor
|
||||
self._gatewayDiscovery = State(initialValue: discoveryModel)
|
||||
self._onboardingChatModel = State(
|
||||
initialValue: ClawdbotChatViewModel(
|
||||
initialValue: MoltbotChatViewModel(
|
||||
sessionKey: "onboarding",
|
||||
transport: MacGatewayChatTransport()))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import AppKit
|
||||
import ClawdbotDiscovery
|
||||
import ClawdbotIPC
|
||||
import MoltbotDiscovery
|
||||
import MoltbotIPC
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
@@ -35,7 +35,7 @@ extension OnboardingView {
|
||||
user: user,
|
||||
host: host,
|
||||
port: gateway.sshPort)
|
||||
ClawdbotConfigFile.setRemoteGatewayUrl(host: host, port: gateway.gatewayPort)
|
||||
MoltbotConfigFile.setRemoteGatewayUrl(host: host, port: gateway.gatewayPort)
|
||||
}
|
||||
self.state.remoteCliPath = gateway.cliPath ?? ""
|
||||
|
||||
@@ -67,7 +67,7 @@ extension OnboardingView {
|
||||
}
|
||||
|
||||
func finish() {
|
||||
UserDefaults.standard.set(true, forKey: "clawdbot.onboardingSeen")
|
||||
UserDefaults.standard.set(true, forKey: "moltbot.onboardingSeen")
|
||||
UserDefaults.standard.set(currentOnboardingVersion, forKey: onboardingVersionKey)
|
||||
OnboardingController.shared.close()
|
||||
}
|
||||
@@ -113,9 +113,9 @@ extension OnboardingView {
|
||||
code: parsed.code,
|
||||
state: parsed.state,
|
||||
verifier: pkce.verifier)
|
||||
try ClawdbotOAuthStore.saveAnthropicOAuth(creds)
|
||||
try MoltbotOAuthStore.saveAnthropicOAuth(creds)
|
||||
self.refreshAnthropicOAuthStatus()
|
||||
self.anthropicAuthStatus = "Connected. Clawdbot can now use Claude."
|
||||
self.anthropicAuthStatus = "Connected. Moltbot can now use Claude."
|
||||
} catch {
|
||||
self.anthropicAuthStatus = "OAuth failed: \(error.localizedDescription)"
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ extension OnboardingView {
|
||||
}
|
||||
guard self.onboardingChatModel.messages.isEmpty else { return }
|
||||
let kickoff =
|
||||
"Hi! I just installed Clawdbot and you’re my brand‑new agent. " +
|
||||
"Hi! I just installed Moltbot and you’re my brand‑new agent. " +
|
||||
"Please start the first‑run ritual from BOOTSTRAP.md, ask one question at a time, " +
|
||||
"and before we talk about WhatsApp/Telegram, visit soul.md with me to craft SOUL.md: " +
|
||||
"ask what matters to me and how you should be. Then guide me through choosing " +
|
||||
|
||||
@@ -4,7 +4,7 @@ import SwiftUI
|
||||
extension OnboardingView {
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
GlowingClawdbotIcon(size: 130, glowIntensity: 0.28)
|
||||
GlowingMoltbotIcon(size: 130, glowIntensity: 0.28)
|
||||
.offset(y: 10)
|
||||
.frame(height: 145)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotIPC
|
||||
import MoltbotIPC
|
||||
import Foundation
|
||||
|
||||
extension OnboardingView {
|
||||
@@ -115,7 +115,7 @@ extension OnboardingView {
|
||||
return
|
||||
}
|
||||
let command = desc.command.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let expectedTokens = ["node", "clawdbot", "tsx", "pnpm", "bun"]
|
||||
let expectedTokens = ["node", "moltbot", "tsx", "pnpm", "bun"]
|
||||
let lower = command.lowercased()
|
||||
let expected = expectedTokens.contains { lower.contains($0) }
|
||||
self.localGatewayProbe = LocalGatewayProbe(
|
||||
@@ -127,9 +127,9 @@ extension OnboardingView {
|
||||
}
|
||||
|
||||
func refreshAnthropicOAuthStatus() {
|
||||
_ = ClawdbotOAuthStore.importLegacyAnthropicOAuthIfNeeded()
|
||||
_ = MoltbotOAuthStore.importLegacyAnthropicOAuthIfNeeded()
|
||||
let previous = self.anthropicAuthDetectedStatus
|
||||
let status = ClawdbotOAuthStore.anthropicOAuthStatus()
|
||||
let status = MoltbotOAuthStore.anthropicOAuthStatus()
|
||||
self.anthropicAuthDetectedStatus = status
|
||||
self.anthropicAuthConnected = status.isConnected
|
||||
|
||||
@@ -154,7 +154,7 @@ extension OnboardingView {
|
||||
self.anthropicAuthVerificationFailed = false
|
||||
defer { self.anthropicAuthVerifying = false }
|
||||
|
||||
guard let refresh = ClawdbotOAuthStore.loadAnthropicOAuthRefreshToken(), !refresh.isEmpty else {
|
||||
guard let refresh = MoltbotOAuthStore.loadAnthropicOAuthRefreshToken(), !refresh.isEmpty else {
|
||||
self.anthropicAuthStatus = "OAuth verification failed: missing refresh token."
|
||||
self.anthropicAuthVerificationFailed = true
|
||||
return
|
||||
@@ -162,7 +162,7 @@ extension OnboardingView {
|
||||
|
||||
do {
|
||||
let updated = try await AnthropicOAuth.refresh(refreshToken: refresh)
|
||||
try ClawdbotOAuthStore.saveAnthropicOAuth(updated)
|
||||
try MoltbotOAuthStore.saveAnthropicOAuth(updated)
|
||||
self.refreshAnthropicOAuthStatus()
|
||||
self.anthropicAuthVerified = true
|
||||
self.anthropicAuthVerifiedAt = Date()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import AppKit
|
||||
import ClawdbotChatUI
|
||||
import ClawdbotDiscovery
|
||||
import ClawdbotIPC
|
||||
import MoltbotChatUI
|
||||
import MoltbotDiscovery
|
||||
import MoltbotIPC
|
||||
import SwiftUI
|
||||
|
||||
extension OnboardingView {
|
||||
@@ -32,9 +32,9 @@ extension OnboardingView {
|
||||
func welcomePage() -> some View {
|
||||
self.onboardingPage {
|
||||
VStack(spacing: 22) {
|
||||
Text("Welcome to Clawdbot")
|
||||
Text("Welcome to Moltbot")
|
||||
.font(.largeTitle.weight(.semibold))
|
||||
Text("Clawdbot is a powerful personal AI assistant that can connect to WhatsApp or Telegram.")
|
||||
Text("Moltbot is a powerful personal AI assistant that can connect to WhatsApp or Telegram.")
|
||||
.font(.body)
|
||||
.foregroundStyle(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
@@ -57,7 +57,7 @@ extension OnboardingView {
|
||||
"The connected AI agent (e.g. Claude) can trigger powerful actions on your Mac, " +
|
||||
"including running commands, reading/writing files, and capturing screenshots — " +
|
||||
"depending on the permissions you grant.\n\n" +
|
||||
"Only enable Clawdbot if you understand the risks and trust the prompts and " +
|
||||
"Only enable Moltbot if you understand the risks and trust the prompts and " +
|
||||
"integrations you use.")
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
@@ -76,7 +76,7 @@ extension OnboardingView {
|
||||
Text("Choose your Gateway")
|
||||
.font(.largeTitle.weight(.semibold))
|
||||
Text(
|
||||
"Clawdbot uses a single Gateway that stays running. Pick this Mac, " +
|
||||
"Moltbot uses a single Gateway that stays running. Pick this Mac, " +
|
||||
"connect to a discovered gateway nearby, or configure later.")
|
||||
.font(.body)
|
||||
.foregroundStyle(.secondary)
|
||||
@@ -228,7 +228,7 @@ extension OnboardingView {
|
||||
Text("Project root")
|
||||
.font(.callout.weight(.semibold))
|
||||
.frame(width: labelWidth, alignment: .leading)
|
||||
TextField("/home/you/Projects/clawdbot", text: self.$state.remoteProjectRoot)
|
||||
TextField("/home/you/Projects/moltbot", text: self.$state.remoteProjectRoot)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.frame(width: fieldWidth)
|
||||
}
|
||||
@@ -237,7 +237,7 @@ extension OnboardingView {
|
||||
.font(.callout.weight(.semibold))
|
||||
.frame(width: labelWidth, alignment: .leading)
|
||||
TextField(
|
||||
"/Applications/Clawdbot.app/.../clawdbot",
|
||||
"/Applications/Moltbot.app/.../moltbot",
|
||||
text: self.$state.remoteCliPath)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.frame(width: fieldWidth)
|
||||
@@ -335,7 +335,7 @@ extension OnboardingView {
|
||||
.multilineTextAlignment(.center)
|
||||
.frame(maxWidth: 540)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
Text("Clawdbot supports any model — we strongly recommend Opus 4.5 for the best experience.")
|
||||
Text("Moltbot supports any model — we strongly recommend Opus 4.5 for the best experience.")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
@@ -375,14 +375,14 @@ extension OnboardingView {
|
||||
}
|
||||
|
||||
Text(
|
||||
"This lets Clawdbot use Claude immediately. Credentials are stored at " +
|
||||
"This lets Moltbot use Claude immediately. Credentials are stored at " +
|
||||
"`~/.clawdbot/credentials/oauth.json` (owner-only).")
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
|
||||
HStack(spacing: 12) {
|
||||
Text(ClawdbotOAuthStore.oauthURL().path)
|
||||
Text(MoltbotOAuthStore.oauthURL().path)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(1)
|
||||
@@ -391,7 +391,7 @@ extension OnboardingView {
|
||||
Spacer()
|
||||
|
||||
Button("Reveal") {
|
||||
NSWorkspace.shared.activateFileViewerSelecting([ClawdbotOAuthStore.oauthURL()])
|
||||
NSWorkspace.shared.activateFileViewerSelecting([MoltbotOAuthStore.oauthURL()])
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
|
||||
@@ -493,7 +493,7 @@ extension OnboardingView {
|
||||
self.onboardingPage {
|
||||
Text("Grant permissions")
|
||||
.font(.largeTitle.weight(.semibold))
|
||||
Text("These macOS permissions let Clawdbot automate apps and capture context on this Mac.")
|
||||
Text("These macOS permissions let Moltbot automate apps and capture context on this Mac.")
|
||||
.font(.body)
|
||||
.foregroundStyle(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
@@ -534,7 +534,7 @@ extension OnboardingView {
|
||||
self.onboardingPage {
|
||||
Text("Install the CLI")
|
||||
.font(.largeTitle.weight(.semibold))
|
||||
Text("Required for local mode: installs `clawdbot` so launchd can run the gateway.")
|
||||
Text("Required for local mode: installs `moltbot` so launchd can run the gateway.")
|
||||
.font(.body)
|
||||
.foregroundStyle(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
@@ -594,7 +594,7 @@ extension OnboardingView {
|
||||
Text("Agent workspace")
|
||||
.font(.largeTitle.weight(.semibold))
|
||||
Text(
|
||||
"Clawdbot runs the agent from a dedicated workspace so it can load `AGENTS.md` " +
|
||||
"Moltbot runs the agent from a dedicated workspace so it can load `AGENTS.md` " +
|
||||
"and write files there without mixing into your other projects.")
|
||||
.font(.body)
|
||||
.foregroundStyle(.secondary)
|
||||
@@ -621,7 +621,7 @@ extension OnboardingView {
|
||||
Text("Workspace folder")
|
||||
.font(.headline)
|
||||
TextField(
|
||||
AgentWorkspace.displayPath(for: ClawdbotConfigFile.defaultWorkspaceURL()),
|
||||
AgentWorkspace.displayPath(for: MoltbotConfigFile.defaultWorkspaceURL()),
|
||||
text: self.$workspacePath)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
|
||||
@@ -651,7 +651,7 @@ extension OnboardingView {
|
||||
let saved = await self.saveAgentWorkspace(AgentWorkspace.displayPath(for: url))
|
||||
if saved {
|
||||
self.workspaceStatus =
|
||||
"Saved to ~/.clawdbot/clawdbot.json (agents.defaults.workspace)"
|
||||
"Saved to ~/.clawdbot/moltbot.json (agents.defaults.workspace)"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -693,7 +693,7 @@ extension OnboardingView {
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
|
||||
self.onboardingGlassCard(padding: 8) {
|
||||
ClawdbotChatView(viewModel: self.onboardingChatModel, style: .onboarding)
|
||||
MoltbotChatView(viewModel: self.onboardingChatModel, style: .onboarding)
|
||||
.frame(maxHeight: .infinity)
|
||||
}
|
||||
.frame(maxHeight: .infinity)
|
||||
@@ -719,7 +719,7 @@ extension OnboardingView {
|
||||
self.featureRow(
|
||||
title: "Remote gateway checklist",
|
||||
subtitle: """
|
||||
On your gateway host: install/update the `clawdbot` package and make sure credentials exist
|
||||
On your gateway host: install/update the `moltbot` package and make sure credentials exist
|
||||
(typically `~/.clawdbot/credentials/oauth.json`). Then connect again if needed.
|
||||
""",
|
||||
systemImage: "network")
|
||||
@@ -728,7 +728,7 @@ extension OnboardingView {
|
||||
}
|
||||
self.featureRow(
|
||||
title: "Open the menu bar panel",
|
||||
subtitle: "Click the Clawdbot menu bar icon for quick chat and status.",
|
||||
subtitle: "Click the Moltbot menu bar icon for quick chat and status.",
|
||||
systemImage: "bubble.left.and.bubble.right")
|
||||
self.featureActionRow(
|
||||
title: "Connect WhatsApp or Telegram",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotDiscovery
|
||||
import MoltbotDiscovery
|
||||
import SwiftUI
|
||||
|
||||
#if DEBUG
|
||||
@@ -14,7 +14,7 @@ extension OnboardingView {
|
||||
tailnetDns: "gateway.ts.net",
|
||||
sshPort: 2222,
|
||||
gatewayPort: 18789,
|
||||
cliPath: "/usr/local/bin/clawdbot",
|
||||
cliPath: "/usr/local/bin/moltbot",
|
||||
stableID: "gateway-1",
|
||||
debugID: "gateway-1",
|
||||
isLocal: false)
|
||||
@@ -28,14 +28,14 @@ extension OnboardingView {
|
||||
view.localGatewayProbe = LocalGatewayProbe(
|
||||
port: GatewayEnvironment.gatewayPort(),
|
||||
pid: 123,
|
||||
command: "clawdbot-gateway",
|
||||
command: "moltbot-gateway",
|
||||
expected: true)
|
||||
view.showAdvancedConnection = true
|
||||
view.preferredGatewayID = gateway.stableID
|
||||
view.cliInstalled = true
|
||||
view.cliInstallLocation = "/usr/local/bin/clawdbot"
|
||||
view.cliInstallLocation = "/usr/local/bin/moltbot"
|
||||
view.cliStatus = "Installed"
|
||||
view.workspacePath = "/tmp/clawdbot"
|
||||
view.workspacePath = "/tmp/moltbot"
|
||||
view.workspaceStatus = "Saved workspace"
|
||||
view.anthropicAuthPKCE = AnthropicOAuth.PKCE(verifier: "verifier", challenge: "challenge")
|
||||
view.anthropicAuthCode = "code#state"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Observation
|
||||
import SwiftUI
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import AppKit
|
||||
import SwiftUI
|
||||
|
||||
struct GlowingClawdbotIcon: View {
|
||||
struct GlowingMoltbotIcon: View {
|
||||
@Environment(\.scenePhase) private var scenePhase
|
||||
|
||||
let size: CGFloat
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ClawdbotKit
|
||||
import ClawdbotProtocol
|
||||
import MoltbotKit
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
import Observation
|
||||
import OSLog
|
||||
@@ -9,10 +9,10 @@ private let onboardingWizardLogger = Logger(subsystem: "com.clawdbot", category:
|
||||
|
||||
// MARK: - Swift 6 AnyCodable Bridging Helpers
|
||||
|
||||
// Bridge between ClawdbotProtocol.AnyCodable and the local module to avoid
|
||||
// Bridge between MoltbotProtocol.AnyCodable and the local module to avoid
|
||||
// Swift 6 strict concurrency type conflicts.
|
||||
|
||||
private typealias ProtocolAnyCodable = ClawdbotProtocol.AnyCodable
|
||||
private typealias ProtocolAnyCodable = MoltbotProtocol.AnyCodable
|
||||
|
||||
private func bridgeToLocal(_ value: ProtocolAnyCodable) -> AnyCodable {
|
||||
if let data = try? JSONEncoder().encode(value),
|
||||
@@ -187,7 +187,7 @@ final class OnboardingWizardModel {
|
||||
}
|
||||
|
||||
private func shouldSkipWizard() -> Bool {
|
||||
let root = ClawdbotConfigFile.loadDict()
|
||||
let root = MoltbotConfigFile.loadDict()
|
||||
if let wizard = root["wizard"] as? [String: Any], !wizard.isEmpty {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ final class PeekabooBridgeHostCoordinator {
|
||||
private let logger = Logger(subsystem: "com.clawdbot", category: "PeekabooBridge")
|
||||
|
||||
private var host: PeekabooBridgeHost?
|
||||
private var services: ClawdbotPeekabooBridgeServices?
|
||||
private var services: MoltbotPeekabooBridgeServices?
|
||||
|
||||
func setEnabled(_ enabled: Bool) async {
|
||||
if enabled {
|
||||
@@ -39,7 +39,7 @@ final class PeekabooBridgeHostCoordinator {
|
||||
}
|
||||
let allowlistedBundles: Set<String> = []
|
||||
|
||||
let services = ClawdbotPeekabooBridgeServices()
|
||||
let services = MoltbotPeekabooBridgeServices()
|
||||
let server = PeekabooBridgeServer(
|
||||
services: services,
|
||||
hostKind: .gui,
|
||||
@@ -90,7 +90,7 @@ final class PeekabooBridgeHostCoordinator {
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private final class ClawdbotPeekabooBridgeServices: PeekabooBridgeServiceProviding {
|
||||
private final class MoltbotPeekabooBridgeServices: PeekabooBridgeServiceProviding {
|
||||
let permissions: PermissionsService
|
||||
let screenCapture: any ScreenCaptureServiceProtocol
|
||||
let automation: any UIAutomationServiceProtocol
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import AppKit
|
||||
import ApplicationServices
|
||||
import AVFoundation
|
||||
import ClawdbotIPC
|
||||
import MoltbotIPC
|
||||
import CoreGraphics
|
||||
import CoreLocation
|
||||
import Foundation
|
||||
@@ -380,7 +380,7 @@ enum AppleScriptPermission {
|
||||
static func isAuthorized() -> Bool {
|
||||
let script = """
|
||||
tell application "Terminal"
|
||||
return "clawdbot-ok"
|
||||
return "moltbot-ok"
|
||||
end tell
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ClawdbotIPC
|
||||
import ClawdbotKit
|
||||
import MoltbotIPC
|
||||
import MoltbotKit
|
||||
import CoreLocation
|
||||
import SwiftUI
|
||||
|
||||
@@ -12,7 +12,7 @@ struct PermissionsSettings: View {
|
||||
VStack(alignment: .leading, spacing: 14) {
|
||||
SystemRunSettingsView()
|
||||
|
||||
Text("Allow these so Clawdbot can notify and capture when needed.")
|
||||
Text("Allow these so Moltbot can notify and capture when needed.")
|
||||
.padding(.top, 4)
|
||||
|
||||
PermissionStatusList(status: self.status, refresh: self.refresh)
|
||||
@@ -31,9 +31,9 @@ struct PermissionsSettings: View {
|
||||
}
|
||||
|
||||
private struct LocationAccessSettings: View {
|
||||
@AppStorage(locationModeKey) private var locationModeRaw: String = ClawdbotLocationMode.off.rawValue
|
||||
@AppStorage(locationModeKey) private var locationModeRaw: String = MoltbotLocationMode.off.rawValue
|
||||
@AppStorage(locationPreciseKey) private var locationPreciseEnabled: Bool = true
|
||||
@State private var lastLocationModeRaw: String = ClawdbotLocationMode.off.rawValue
|
||||
@State private var lastLocationModeRaw: String = MoltbotLocationMode.off.rawValue
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
@@ -41,9 +41,9 @@ private struct LocationAccessSettings: View {
|
||||
.font(.body)
|
||||
|
||||
Picker("", selection: self.$locationModeRaw) {
|
||||
Text("Off").tag(ClawdbotLocationMode.off.rawValue)
|
||||
Text("While Using").tag(ClawdbotLocationMode.whileUsing.rawValue)
|
||||
Text("Always").tag(ClawdbotLocationMode.always.rawValue)
|
||||
Text("Off").tag(MoltbotLocationMode.off.rawValue)
|
||||
Text("While Using").tag(MoltbotLocationMode.whileUsing.rawValue)
|
||||
Text("Always").tag(MoltbotLocationMode.always.rawValue)
|
||||
}
|
||||
.labelsHidden()
|
||||
.pickerStyle(.menu)
|
||||
@@ -62,7 +62,7 @@ private struct LocationAccessSettings: View {
|
||||
.onChange(of: self.locationModeRaw) { _, newValue in
|
||||
let previous = self.lastLocationModeRaw
|
||||
self.lastLocationModeRaw = newValue
|
||||
guard let mode = ClawdbotLocationMode(rawValue: newValue) else { return }
|
||||
guard let mode = MoltbotLocationMode(rawValue: newValue) else { return }
|
||||
Task {
|
||||
let granted = await self.requestLocationAuthorization(mode: mode)
|
||||
if !granted {
|
||||
@@ -75,11 +75,11 @@ private struct LocationAccessSettings: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var locationMode: ClawdbotLocationMode {
|
||||
ClawdbotLocationMode(rawValue: self.locationModeRaw) ?? .off
|
||||
private var locationMode: MoltbotLocationMode {
|
||||
MoltbotLocationMode(rawValue: self.locationModeRaw) ?? .off
|
||||
}
|
||||
|
||||
private func requestLocationAuthorization(mode: ClawdbotLocationMode) async -> Bool {
|
||||
private func requestLocationAuthorization(mode: MoltbotLocationMode) async -> Bool {
|
||||
guard mode != .off else { return true }
|
||||
guard CLLocationManager.locationServicesEnabled() else {
|
||||
await MainActor.run { LocationPermissionHelper.openSettings() }
|
||||
|
||||
@@ -25,7 +25,7 @@ actor PortGuardian {
|
||||
private let logger = Logger(subsystem: "com.clawdbot", category: "portguard")
|
||||
private nonisolated static let appSupportDir: URL = {
|
||||
let base = FileManager().urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
|
||||
return base.appendingPathComponent("Clawdbot", isDirectory: true)
|
||||
return base.appendingPathComponent("Moltbot", isDirectory: true)
|
||||
}()
|
||||
|
||||
private nonisolated static var recordPath: URL {
|
||||
@@ -263,7 +263,7 @@ actor PortGuardian {
|
||||
{
|
||||
let expectedDesc: String
|
||||
let okPredicate: (Listener) -> Bool
|
||||
let expectedCommands = ["node", "clawdbot", "tsx", "pnpm", "bun"]
|
||||
let expectedCommands = ["node", "moltbot", "tsx", "pnpm", "bun"]
|
||||
|
||||
switch mode {
|
||||
case .remote:
|
||||
@@ -357,10 +357,10 @@ actor PortGuardian {
|
||||
if port == GatewayEnvironment.gatewayPort() { return cmd.contains("ssh") }
|
||||
return false
|
||||
case .local:
|
||||
// The gateway daemon may listen as `clawdbot` or as its runtime (`node`, `bun`, etc).
|
||||
// The gateway daemon may listen as `moltbot` or as its runtime (`node`, `bun`, etc).
|
||||
if full.contains("gateway-daemon") { return true }
|
||||
// If args are unavailable, treat a clawdbot listener as expected.
|
||||
if cmd.contains("clawdbot"), full == cmd { return true }
|
||||
// If args are unavailable, treat a moltbot listener as expected.
|
||||
if cmd.contains("moltbot"), full == cmd { return true }
|
||||
return false
|
||||
case .unconfigured:
|
||||
return false
|
||||
|
||||
@@ -8,7 +8,7 @@ extension ProcessInfo {
|
||||
|
||||
var isNixMode: Bool {
|
||||
if let raw = getenv("CLAWDBOT_NIX_MODE"), String(cString: raw) == "1" { return true }
|
||||
return UserDefaults.standard.bool(forKey: "clawdbot.nixMode")
|
||||
return UserDefaults.standard.bool(forKey: "moltbot.nixMode")
|
||||
}
|
||||
|
||||
var isRunningTests: Bool {
|
||||
|
||||
@@ -136,7 +136,7 @@ final class RemotePortTunnel {
|
||||
}
|
||||
|
||||
private static func resolveRemotePortOverride(for sshHost: String) -> Int? {
|
||||
let root = ClawdbotConfigFile.loadDict()
|
||||
let root = MoltbotConfigFile.loadDict()
|
||||
guard let gateway = root["gateway"] as? [String: Any],
|
||||
let remote = gateway["remote"] as? [String: Any],
|
||||
let urlRaw = remote["url"] as? String
|
||||
|
||||
@@ -31,7 +31,7 @@ actor RemoteTunnelManager {
|
||||
tunnel.terminate()
|
||||
self.controlTunnel = nil
|
||||
}
|
||||
// If a previous Clawdbot run already has an SSH listener on the expected port (common after restarts),
|
||||
// If a previous Moltbot run already has an SSH listener on the expected port (common after restarts),
|
||||
// reuse it instead of spawning new ssh processes that immediately fail with "Address already in use".
|
||||
let desiredPort = UInt16(GatewayEnvironment.gatewayPort())
|
||||
if let desc = await PortGuardian.shared.describe(port: Int(desiredPort)),
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Clawdbot</string>
|
||||
<string>Moltbot</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.clawdbot.mac</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Clawdbot</string>
|
||||
<string>Moltbot</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
@@ -19,7 +19,7 @@
|
||||
<key>CFBundleVersion</key>
|
||||
<string>202601260</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>Clawdbot</string>
|
||||
<string>Moltbot</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
@@ -27,7 +27,7 @@
|
||||
<string>com.clawdbot.mac.deeplink</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>clawdbot</string>
|
||||
<string>moltbot</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
@@ -36,29 +36,29 @@
|
||||
<key>LSUIElement</key>
|
||||
<true/>
|
||||
|
||||
<key>ClawdbotBuildTimestamp</key>
|
||||
<key>MoltbotBuildTimestamp</key>
|
||||
<string></string>
|
||||
<key>ClawdbotGitCommit</key>
|
||||
<key>MoltbotGitCommit</key>
|
||||
<string></string>
|
||||
|
||||
<key>NSUserNotificationUsageDescription</key>
|
||||
<string>Clawdbot needs notification permission to show alerts for agent actions.</string>
|
||||
<string>Moltbot needs notification permission to show alerts for agent actions.</string>
|
||||
<key>NSScreenCaptureDescription</key>
|
||||
<string>Clawdbot captures the screen when the agent needs screenshots for context.</string>
|
||||
<string>Moltbot captures the screen when the agent needs screenshots for context.</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Clawdbot can capture photos or short video clips when requested by the agent.</string>
|
||||
<string>Moltbot can capture photos or short video clips when requested by the agent.</string>
|
||||
<key>NSLocationUsageDescription</key>
|
||||
<string>Clawdbot can share your location when requested by the agent.</string>
|
||||
<string>Moltbot can share your location when requested by the agent.</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>Clawdbot can share your location when requested by the agent.</string>
|
||||
<string>Moltbot can share your location when requested by the agent.</string>
|
||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||
<string>Clawdbot can share your location when requested by the agent.</string>
|
||||
<string>Moltbot can share your location when requested by the agent.</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Clawdbot needs the mic for Voice Wake tests and agent audio capture.</string>
|
||||
<string>Moltbot needs the mic for Voice Wake tests and agent audio capture.</string>
|
||||
<key>NSSpeechRecognitionUsageDescription</key>
|
||||
<string>Clawdbot uses speech recognition to detect your Voice Wake trigger phrase.</string>
|
||||
<string>Moltbot uses speech recognition to detect your Voice Wake trigger phrase.</string>
|
||||
<key>NSAppleEventsUsageDescription</key>
|
||||
<string>Clawdbot needs Automation (AppleScript) permission to drive Terminal and other apps for agent actions.</string>
|
||||
<string>Moltbot needs Automation (AppleScript) permission to drive Terminal and other apps for agent actions.</string>
|
||||
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
|
||||
@@ -89,7 +89,7 @@ enum RuntimeLocator {
|
||||
switch error {
|
||||
case let .notFound(searchPaths):
|
||||
[
|
||||
"clawdbot needs Node >=22.0.0 but found no runtime.",
|
||||
"moltbot needs Node >=22.0.0 but found no runtime.",
|
||||
"PATH searched: \(searchPaths.joined(separator: ":"))",
|
||||
"Install Node: https://nodejs.org/en/download",
|
||||
].joined(separator: "\n")
|
||||
@@ -97,7 +97,7 @@ enum RuntimeLocator {
|
||||
[
|
||||
"Found \(kind.rawValue) \(found) at \(path) but need >= \(required).",
|
||||
"PATH searched: \(searchPaths.joined(separator: ":"))",
|
||||
"Upgrade Node and rerun clawdbot.",
|
||||
"Upgrade Node and rerun moltbot.",
|
||||
].joined(separator: "\n")
|
||||
case let .versionParse(kind, raw, path, searchPaths):
|
||||
[
|
||||
|
||||
@@ -43,7 +43,7 @@ final class ScreenRecordService {
|
||||
return URL(fileURLWithPath: outPath)
|
||||
}
|
||||
return FileManager().temporaryDirectory
|
||||
.appendingPathComponent("clawdbot-screen-record-\(UUID().uuidString).mp4")
|
||||
.appendingPathComponent("moltbot-screen-record-\(UUID().uuidString).mp4")
|
||||
}()
|
||||
try? FileManager().removeItem(at: outURL)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import ClawdbotChatUI
|
||||
import ClawdbotKit
|
||||
import ClawdbotProtocol
|
||||
import MoltbotChatUI
|
||||
import MoltbotKit
|
||||
import MoltbotProtocol
|
||||
import OSLog
|
||||
import SwiftUI
|
||||
|
||||
@@ -288,7 +288,7 @@ enum SessionMenuPreviewLoader {
|
||||
|
||||
private static func requestPreview(
|
||||
keys: [String],
|
||||
maxItems: Int) async throws -> ClawdbotSessionsPreviewPayload
|
||||
maxItems: Int) async throws -> MoltbotSessionsPreviewPayload
|
||||
{
|
||||
let boundedItems = self.normalizeMaxItems(maxItems)
|
||||
let timeoutMs = Int(self.previewTimeoutSeconds * 1000)
|
||||
@@ -331,7 +331,7 @@ enum SessionMenuPreviewLoader {
|
||||
}
|
||||
|
||||
private static func snapshot(
|
||||
from entry: ClawdbotSessionPreviewEntry,
|
||||
from entry: MoltbotSessionPreviewEntry,
|
||||
maxItems: Int) -> SessionMenuPreviewSnapshot
|
||||
{
|
||||
let items = self.previewItems(from: entry, maxItems: maxItems)
|
||||
@@ -348,7 +348,7 @@ enum SessionMenuPreviewLoader {
|
||||
}
|
||||
}
|
||||
|
||||
private static func cache(payload: ClawdbotSessionsPreviewPayload, maxItems: Int) async {
|
||||
private static func cache(payload: MoltbotSessionsPreviewPayload, maxItems: Int) async {
|
||||
for entry in payload.previews {
|
||||
let snapshot = self.snapshot(from: entry, maxItems: maxItems)
|
||||
await SessionPreviewCache.shared.store(snapshot: snapshot, for: entry.key)
|
||||
@@ -365,7 +365,7 @@ enum SessionMenuPreviewLoader {
|
||||
}
|
||||
|
||||
private static func previewItems(
|
||||
from entry: ClawdbotSessionPreviewEntry,
|
||||
from entry: MoltbotSessionPreviewEntry,
|
||||
maxItems: Int) -> [SessionPreviewItem]
|
||||
{
|
||||
let boundedItems = self.normalizeMaxItems(maxItems)
|
||||
@@ -381,11 +381,11 @@ enum SessionMenuPreviewLoader {
|
||||
}
|
||||
|
||||
private static func previewItems(
|
||||
from payload: ClawdbotChatHistoryPayload,
|
||||
from payload: MoltbotChatHistoryPayload,
|
||||
maxItems: Int) -> [SessionPreviewItem]
|
||||
{
|
||||
let boundedItems = self.normalizeMaxItems(maxItems)
|
||||
let raw: [ClawdbotKit.AnyCodable] = payload.messages ?? []
|
||||
let raw: [MoltbotKit.AnyCodable] = payload.messages ?? []
|
||||
let messages = self.decodeMessages(raw)
|
||||
let built = messages.compactMap { message -> SessionPreviewItem? in
|
||||
guard let text = self.previewText(for: message) else { return nil }
|
||||
@@ -399,10 +399,10 @@ enum SessionMenuPreviewLoader {
|
||||
return Array(trimmed.reversed())
|
||||
}
|
||||
|
||||
private static func decodeMessages(_ raw: [ClawdbotKit.AnyCodable]) -> [ClawdbotChatMessage] {
|
||||
private static func decodeMessages(_ raw: [MoltbotKit.AnyCodable]) -> [MoltbotChatMessage] {
|
||||
raw.compactMap { item in
|
||||
guard let data = try? JSONEncoder().encode(item) else { return nil }
|
||||
return try? JSONDecoder().decode(ClawdbotChatMessage.self, from: data)
|
||||
return try? JSONDecoder().decode(MoltbotChatMessage.self, from: data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ enum SessionMenuPreviewLoader {
|
||||
}
|
||||
}
|
||||
|
||||
private static func previewText(for message: ClawdbotChatMessage) -> String? {
|
||||
private static func previewText(for message: MoltbotChatMessage) -> String? {
|
||||
let text = message.content.compactMap(\.text).joined(separator: "\n")
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if !text.isEmpty { return text }
|
||||
@@ -442,12 +442,12 @@ enum SessionMenuPreviewLoader {
|
||||
return nil
|
||||
}
|
||||
|
||||
private static func isToolCall(_ message: ClawdbotChatMessage) -> Bool {
|
||||
private static func isToolCall(_ message: MoltbotChatMessage) -> Bool {
|
||||
if message.toolName?.nonEmpty != nil { return true }
|
||||
return message.content.contains { $0.name?.nonEmpty != nil || $0.type?.lowercased() == "toolcall" }
|
||||
}
|
||||
|
||||
private static func toolNames(for message: ClawdbotChatMessage) -> [String] {
|
||||
private static func toolNames(for message: MoltbotChatMessage) -> [String] {
|
||||
var names: [String] = []
|
||||
for content in message.content {
|
||||
if let name = content.name?.nonEmpty {
|
||||
@@ -460,7 +460,7 @@ enum SessionMenuPreviewLoader {
|
||||
return Self.dedupePreservingOrder(names)
|
||||
}
|
||||
|
||||
private static func mediaSummary(for message: ClawdbotChatMessage) -> String? {
|
||||
private static func mediaSummary(for message: MoltbotChatMessage) -> String? {
|
||||
let types = message.content.compactMap { content -> String? in
|
||||
let raw = content.type?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
|
||||
guard let raw, !raw.isEmpty else { return nil }
|
||||
|
||||
@@ -111,8 +111,8 @@ struct SettingsRootView: View {
|
||||
|
||||
private var nixManagedBanner: some View {
|
||||
// Prefer gateway-resolved paths; fall back to local env defaults if disconnected.
|
||||
let configPath = self.snapshotPaths.configPath ?? ClawdbotPaths.configURL.path
|
||||
let stateDir = self.snapshotPaths.stateDir ?? ClawdbotPaths.stateDirURL.path
|
||||
let configPath = self.snapshotPaths.configPath ?? MoltbotPaths.configURL.path
|
||||
let stateDir = self.snapshotPaths.stateDir ?? MoltbotPaths.stateDirURL.path
|
||||
|
||||
return VStack(alignment: .leading, spacing: 6) {
|
||||
HStack(spacing: 8) {
|
||||
@@ -227,7 +227,7 @@ enum SettingsTabRouter {
|
||||
}
|
||||
|
||||
extension Notification.Name {
|
||||
static let clawdbotSelectSettingsTab = Notification.Name("clawdbotSelectSettingsTab")
|
||||
static let moltbotSelectSettingsTab = Notification.Name("moltbotSelectSettingsTab")
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotIPC
|
||||
import MoltbotIPC
|
||||
import Foundation
|
||||
|
||||
enum ShellExecutor {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
|
||||
struct SkillsStatusReport: Codable {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Observation
|
||||
import SwiftUI
|
||||
|
||||
@@ -231,13 +231,13 @@ private struct SkillRow: View {
|
||||
|
||||
private var sourceLabel: String {
|
||||
switch self.skill.source {
|
||||
case "clawdbot-bundled":
|
||||
case "moltbot-bundled":
|
||||
"Bundled"
|
||||
case "clawdbot-managed":
|
||||
case "moltbot-managed":
|
||||
"Managed"
|
||||
case "clawdbot-workspace":
|
||||
case "moltbot-workspace":
|
||||
"Workspace"
|
||||
case "clawdbot-extra":
|
||||
case "moltbot-extra":
|
||||
"Extra"
|
||||
default:
|
||||
self.skill.source
|
||||
@@ -578,7 +578,7 @@ extension SkillsSettings {
|
||||
let skill = SkillStatus(
|
||||
name: "Test Skill",
|
||||
description: "Test description",
|
||||
source: "clawdbot-bundled",
|
||||
source: "moltbot-bundled",
|
||||
filePath: "/tmp/skills/test",
|
||||
baseDir: "/tmp/skills",
|
||||
skillKey: "test",
|
||||
|
||||
@@ -234,7 +234,7 @@ struct TailscaleIntegrationSection: View {
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.frame(maxWidth: 240)
|
||||
.onSubmit { Task { await self.applySettings() } }
|
||||
Text("Stored in ~/.clawdbot/clawdbot.json. Prefer CLAWDBOT_GATEWAY_PASSWORD for production.")
|
||||
Text("Stored in ~/.clawdbot/moltbot.json. Prefer CLAWDBOT_GATEWAY_PASSWORD for production.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
Button("Update password") { Task { await self.applySettings() } }
|
||||
@@ -293,9 +293,9 @@ struct TailscaleIntegrationSection: View {
|
||||
}
|
||||
|
||||
if self.connectionMode == .local, !self.isPaused {
|
||||
self.statusMessage = "Saved to ~/.clawdbot/clawdbot.json. Restarting gateway…"
|
||||
self.statusMessage = "Saved to ~/.clawdbot/moltbot.json. Restarting gateway…"
|
||||
} else {
|
||||
self.statusMessage = "Saved to ~/.clawdbot/clawdbot.json. Restart the gateway to apply."
|
||||
self.statusMessage = "Saved to ~/.clawdbot/moltbot.json. Restart the gateway to apply."
|
||||
}
|
||||
self.restartGatewayIfNeeded()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import AVFoundation
|
||||
import ClawdbotChatUI
|
||||
import ClawdbotKit
|
||||
import MoltbotChatUI
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import OSLog
|
||||
import Speech
|
||||
@@ -416,9 +416,9 @@ actor TalkModeRuntime {
|
||||
do {
|
||||
let history = try await GatewayConnection.shared.chatHistory(sessionKey: sessionKey)
|
||||
let messages = history.messages ?? []
|
||||
let decoded: [ClawdbotChatMessage] = messages.compactMap { item in
|
||||
let decoded: [MoltbotChatMessage] = messages.compactMap { item in
|
||||
guard let data = try? JSONEncoder().encode(item) else { return nil }
|
||||
return try? JSONDecoder().decode(ClawdbotChatMessage.self, from: data)
|
||||
return try? JSONDecoder().decode(MoltbotChatMessage.self, from: data)
|
||||
}
|
||||
let assistant = decoded.last { message in
|
||||
guard message.role == "assistant" else { return false }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import OSLog
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ final class VoiceWakeOverlayController {
|
||||
let logger = Logger(subsystem: "com.clawdbot", category: "voicewake.overlay")
|
||||
let enableUI: Bool
|
||||
|
||||
/// Keep the voice wake overlay above any other Clawdbot windows, but below the system’s pop-up menus.
|
||||
/// Keep the voice wake overlay above any other Moltbot windows, but below the system’s pop-up menus.
|
||||
/// (Menu bar menus typically live at `.popUpMenu`.)
|
||||
static let preferredWindowLevel = NSWindow.Level(rawValue: NSWindow.Level.popUpMenu.rawValue - 4)
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ struct VoiceWakeSettings: View {
|
||||
.stroke(Color.secondary.opacity(0.25), lineWidth: 1))
|
||||
|
||||
Text(
|
||||
"Clawdbot reacts when any trigger appears in a transcription. "
|
||||
"Moltbot reacts when any trigger appears in a transcription. "
|
||||
+ "Keep them short to avoid false positives.")
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import AppKit
|
||||
import ClawdbotChatUI
|
||||
import ClawdbotKit
|
||||
import ClawdbotProtocol
|
||||
import MoltbotChatUI
|
||||
import MoltbotKit
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
import OSLog
|
||||
import QuartzCore
|
||||
@@ -16,8 +16,8 @@ private enum WebChatSwiftUILayout {
|
||||
static let anchorPadding: CGFloat = 8
|
||||
}
|
||||
|
||||
struct MacGatewayChatTransport: ClawdbotChatTransport, Sendable {
|
||||
func requestHistory(sessionKey: String) async throws -> ClawdbotChatHistoryPayload {
|
||||
struct MacGatewayChatTransport: MoltbotChatTransport, Sendable {
|
||||
func requestHistory(sessionKey: String) async throws -> MoltbotChatHistoryPayload {
|
||||
try await GatewayConnection.shared.chatHistory(sessionKey: sessionKey)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ struct MacGatewayChatTransport: ClawdbotChatTransport, Sendable {
|
||||
timeoutMs: 10000)
|
||||
}
|
||||
|
||||
func listSessions(limit: Int?) async throws -> ClawdbotChatSessionsListResponse {
|
||||
func listSessions(limit: Int?) async throws -> MoltbotChatSessionsListResponse {
|
||||
var params: [String: AnyCodable] = [
|
||||
"includeGlobal": AnyCodable(true),
|
||||
"includeUnknown": AnyCodable(false),
|
||||
@@ -43,7 +43,7 @@ struct MacGatewayChatTransport: ClawdbotChatTransport, Sendable {
|
||||
method: "sessions.list",
|
||||
params: params,
|
||||
timeoutMs: 15000)
|
||||
return try JSONDecoder().decode(ClawdbotChatSessionsListResponse.self, from: data)
|
||||
return try JSONDecoder().decode(MoltbotChatSessionsListResponse.self, from: data)
|
||||
}
|
||||
|
||||
func sendMessage(
|
||||
@@ -51,7 +51,7 @@ struct MacGatewayChatTransport: ClawdbotChatTransport, Sendable {
|
||||
message: String,
|
||||
thinking: String,
|
||||
idempotencyKey: String,
|
||||
attachments: [ClawdbotChatAttachmentPayload]) async throws -> ClawdbotChatSendResponse
|
||||
attachments: [MoltbotChatAttachmentPayload]) async throws -> MoltbotChatSendResponse
|
||||
{
|
||||
try await GatewayConnection.shared.chatSend(
|
||||
sessionKey: sessionKey,
|
||||
@@ -65,7 +65,7 @@ struct MacGatewayChatTransport: ClawdbotChatTransport, Sendable {
|
||||
try await GatewayConnection.shared.healthOK(timeoutMs: timeoutMs)
|
||||
}
|
||||
|
||||
func events() -> AsyncStream<ClawdbotChatTransportEvent> {
|
||||
func events() -> AsyncStream<MoltbotChatTransportEvent> {
|
||||
AsyncStream { continuation in
|
||||
let task = Task {
|
||||
do {
|
||||
@@ -89,11 +89,11 @@ struct MacGatewayChatTransport: ClawdbotChatTransport, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
static func mapPushToTransportEvent(_ push: GatewayPush) -> ClawdbotChatTransportEvent? {
|
||||
static func mapPushToTransportEvent(_ push: GatewayPush) -> MoltbotChatTransportEvent? {
|
||||
switch push {
|
||||
case let .snapshot(hello):
|
||||
let ok = (try? JSONDecoder().decode(
|
||||
ClawdbotGatewayHealthOK.self,
|
||||
MoltbotGatewayHealthOK.self,
|
||||
from: JSONEncoder().encode(hello.snapshot.health)))?.ok ?? true
|
||||
return .health(ok: ok)
|
||||
|
||||
@@ -102,7 +102,7 @@ struct MacGatewayChatTransport: ClawdbotChatTransport, Sendable {
|
||||
case "health":
|
||||
guard let payload = evt.payload else { return nil }
|
||||
let ok = (try? JSONDecoder().decode(
|
||||
ClawdbotGatewayHealthOK.self,
|
||||
MoltbotGatewayHealthOK.self,
|
||||
from: JSONEncoder().encode(payload)))?.ok ?? true
|
||||
return .health(ok: ok)
|
||||
case "tick":
|
||||
@@ -110,7 +110,7 @@ struct MacGatewayChatTransport: ClawdbotChatTransport, Sendable {
|
||||
case "chat":
|
||||
guard let payload = evt.payload else { return nil }
|
||||
guard let chat = try? JSONDecoder().decode(
|
||||
ClawdbotChatEventPayload.self,
|
||||
MoltbotChatEventPayload.self,
|
||||
from: JSONEncoder().encode(payload))
|
||||
else {
|
||||
return nil
|
||||
@@ -119,7 +119,7 @@ struct MacGatewayChatTransport: ClawdbotChatTransport, Sendable {
|
||||
case "agent":
|
||||
guard let payload = evt.payload else { return nil }
|
||||
guard let agent = try? JSONDecoder().decode(
|
||||
ClawdbotAgentEventPayload.self,
|
||||
MoltbotAgentEventPayload.self,
|
||||
from: JSONEncoder().encode(payload))
|
||||
else {
|
||||
return nil
|
||||
@@ -141,7 +141,7 @@ struct MacGatewayChatTransport: ClawdbotChatTransport, Sendable {
|
||||
final class WebChatSwiftUIWindowController {
|
||||
private let presentation: WebChatPresentation
|
||||
private let sessionKey: String
|
||||
private let hosting: NSHostingController<ClawdbotChatView>
|
||||
private let hosting: NSHostingController<MoltbotChatView>
|
||||
private let contentController: NSViewController
|
||||
private var window: NSWindow?
|
||||
private var dismissMonitor: Any?
|
||||
@@ -152,12 +152,12 @@ final class WebChatSwiftUIWindowController {
|
||||
self.init(sessionKey: sessionKey, presentation: presentation, transport: MacGatewayChatTransport())
|
||||
}
|
||||
|
||||
init(sessionKey: String, presentation: WebChatPresentation, transport: any ClawdbotChatTransport) {
|
||||
init(sessionKey: String, presentation: WebChatPresentation, transport: any MoltbotChatTransport) {
|
||||
self.sessionKey = sessionKey
|
||||
self.presentation = presentation
|
||||
let vm = ClawdbotChatViewModel(sessionKey: sessionKey, transport: transport)
|
||||
let vm = MoltbotChatViewModel(sessionKey: sessionKey, transport: transport)
|
||||
let accent = Self.color(fromHex: AppStateStore.shared.seamColorHex)
|
||||
self.hosting = NSHostingController(rootView: ClawdbotChatView(
|
||||
self.hosting = NSHostingController(rootView: MoltbotChatView(
|
||||
viewModel: vm,
|
||||
showsSessionSwitcher: true,
|
||||
userAccent: accent))
|
||||
@@ -268,7 +268,7 @@ final class WebChatSwiftUIWindowController {
|
||||
styleMask: [.titled, .closable, .resizable, .miniaturizable],
|
||||
backing: .buffered,
|
||||
defer: false)
|
||||
window.title = "Clawdbot Chat"
|
||||
window.title = "Moltbot Chat"
|
||||
window.contentViewController = contentViewController
|
||||
window.isReleasedWhenClosed = false
|
||||
window.titleVisibility = .visible
|
||||
@@ -311,7 +311,7 @@ final class WebChatSwiftUIWindowController {
|
||||
|
||||
private static func makeContentController(
|
||||
for presentation: WebChatPresentation,
|
||||
hosting: NSHostingController<ClawdbotChatView>) -> NSViewController
|
||||
hosting: NSHostingController<MoltbotChatView>) -> NSViewController
|
||||
{
|
||||
let controller = NSViewController()
|
||||
let effectView = NSVisualEffectView()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ClawdbotKit
|
||||
import ClawdbotProtocol
|
||||
import MoltbotKit
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
import Observation
|
||||
import SwiftUI
|
||||
@@ -56,7 +56,7 @@ final class WorkActivityStore {
|
||||
phase: String,
|
||||
name: String?,
|
||||
meta: String?,
|
||||
args: [String: ClawdbotProtocol.AnyCodable]?)
|
||||
args: [String: MoltbotProtocol.AnyCodable]?)
|
||||
{
|
||||
let toolKind = Self.mapToolKind(name)
|
||||
let label = Self.buildLabel(name: name, meta: meta, args: args)
|
||||
@@ -225,7 +225,7 @@ final class WorkActivityStore {
|
||||
private static func buildLabel(
|
||||
name: String?,
|
||||
meta: String?,
|
||||
args: [String: ClawdbotProtocol.AnyCodable]?) -> String
|
||||
args: [String: MoltbotProtocol.AnyCodable]?) -> String
|
||||
{
|
||||
let wrappedArgs = self.wrapToolArgs(args)
|
||||
let display = ToolDisplayRegistry.resolve(name: name ?? "tool", args: wrappedArgs, meta: meta)
|
||||
@@ -236,17 +236,17 @@ final class WorkActivityStore {
|
||||
return display.label
|
||||
}
|
||||
|
||||
private static func wrapToolArgs(_ args: [String: ClawdbotProtocol.AnyCodable]?) -> ClawdbotKit.AnyCodable? {
|
||||
private static func wrapToolArgs(_ args: [String: MoltbotProtocol.AnyCodable]?) -> MoltbotKit.AnyCodable? {
|
||||
guard let args else { return nil }
|
||||
let converted: [String: Any] = args.mapValues { self.unwrapJSONValue($0.value) }
|
||||
return ClawdbotKit.AnyCodable(converted)
|
||||
return MoltbotKit.AnyCodable(converted)
|
||||
}
|
||||
|
||||
private static func unwrapJSONValue(_ value: Any) -> Any {
|
||||
if let dict = value as? [String: ClawdbotProtocol.AnyCodable] {
|
||||
if let dict = value as? [String: MoltbotProtocol.AnyCodable] {
|
||||
return dict.mapValues { self.unwrapJSONValue($0.value) }
|
||||
}
|
||||
if let array = value as? [ClawdbotProtocol.AnyCodable] {
|
||||
if let array = value as? [MoltbotProtocol.AnyCodable] {
|
||||
return array.map { self.unwrapJSONValue($0.value) }
|
||||
}
|
||||
if let dict = value as? [String: Any] {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import Network
|
||||
import Observation
|
||||
@@ -81,11 +81,11 @@ public final class GatewayDiscoveryModel {
|
||||
public func start() {
|
||||
if !self.browsers.isEmpty { return }
|
||||
|
||||
for domain in ClawdbotBonjour.gatewayServiceDomains {
|
||||
for domain in MoltbotBonjour.gatewayServiceDomains {
|
||||
let params = NWParameters.tcp
|
||||
params.includePeerToPeer = true
|
||||
let browser = NWBrowser(
|
||||
for: .bonjour(type: ClawdbotBonjour.gatewayServiceType, domain: domain),
|
||||
for: .bonjour(type: MoltbotBonjour.gatewayServiceType, domain: domain),
|
||||
using: params)
|
||||
|
||||
browser.stateUpdateHandler = { [weak self] state in
|
||||
@@ -113,7 +113,7 @@ public final class GatewayDiscoveryModel {
|
||||
}
|
||||
|
||||
public func refreshWideAreaFallbackNow(timeoutSeconds: TimeInterval = 5.0) {
|
||||
let domain = ClawdbotBonjour.wideAreaGatewayServiceDomain
|
||||
let domain = MoltbotBonjour.wideAreaGatewayServiceDomain
|
||||
Task.detached(priority: .utility) { [weak self] in
|
||||
guard let self else { return }
|
||||
let beacons = WideAreaGatewayDiscovery.discover(timeoutSeconds: timeoutSeconds)
|
||||
@@ -235,7 +235,7 @@ public final class GatewayDiscoveryModel {
|
||||
}
|
||||
.sorted { $0.displayName.localizedCaseInsensitiveCompare($1.displayName) == .orderedAscending }
|
||||
|
||||
if domain == ClawdbotBonjour.wideAreaGatewayServiceDomain,
|
||||
if domain == MoltbotBonjour.wideAreaGatewayServiceDomain,
|
||||
self.hasUsableWideAreaResults
|
||||
{
|
||||
self.wideAreaFallbackGateways = []
|
||||
@@ -243,7 +243,7 @@ public final class GatewayDiscoveryModel {
|
||||
}
|
||||
|
||||
private func scheduleWideAreaFallback() {
|
||||
let domain = ClawdbotBonjour.wideAreaGatewayServiceDomain
|
||||
let domain = MoltbotBonjour.wideAreaGatewayServiceDomain
|
||||
if Self.isRunningTests { return }
|
||||
guard self.wideAreaFallbackTask == nil else { return }
|
||||
self.wideAreaFallbackTask = Task.detached(priority: .utility) { [weak self] in
|
||||
@@ -276,7 +276,7 @@ public final class GatewayDiscoveryModel {
|
||||
}
|
||||
|
||||
private var hasUsableWideAreaResults: Bool {
|
||||
let domain = ClawdbotBonjour.wideAreaGatewayServiceDomain
|
||||
let domain = MoltbotBonjour.wideAreaGatewayServiceDomain
|
||||
guard let gateways = self.gatewaysByDomain[domain], !gateways.isEmpty else { return false }
|
||||
if !self.filterLocalGateways { return true }
|
||||
return gateways.contains(where: { !$0.isLocal })
|
||||
@@ -455,7 +455,7 @@ public final class GatewayDiscoveryModel {
|
||||
|
||||
private nonisolated static func prettifyInstanceName(_ decodedName: String) -> String {
|
||||
let normalized = decodedName.split(whereSeparator: \.isWhitespace).joined(separator: " ")
|
||||
let stripped = normalized.replacingOccurrences(of: " (Clawdbot)", with: "")
|
||||
let stripped = normalized.replacingOccurrences(of: " (Moltbot)", with: "")
|
||||
.replacingOccurrences(of: #"\s+\(\d+\)$"#, with: "", options: .regularExpression)
|
||||
return stripped.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user