style(macos): tidy settings and CLI

This commit is contained in:
Peter Steinberger
2025-12-13 19:23:41 +00:00
parent 02fe19effa
commit 0b990443de
13 changed files with 116 additions and 89 deletions

View File

@@ -38,4 +38,3 @@ enum ClawdisConfigFile {
self.saveDict(root)
}
}

View File

@@ -203,17 +203,17 @@ struct ConfigSettings: View {
.toggleStyle(.checkbox)
.disabled(!self.browserEnabled)
.onChange(of: self.browserAttachOnly) { _, _ in self.autosaveConfig() }
.help("When enabled, the browser server will only connect if the clawd browser is already running.")
.help(
"When enabled, the browser server will only connect if the clawd browser is already running.")
}
GridRow {
Color.clear
.frame(width: self.labelColumnWidth, height: 1)
Text(
"Clawd uses a separate Chrome profile and ports (default 18791/18792) so it wont interfere with your daily browser."
)
.font(.footnote)
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)
"Clawd uses a separate Chrome profile and ports (default 18791/18792) so it wont interfere with your daily browser.")
.font(.footnote)
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
}

View File

@@ -525,7 +525,8 @@ private struct CronJobEditor: View {
VStack(alignment: .leading, spacing: 6) {
Text(self.job == nil ? "New cron job" : "Edit cron job")
.font(.title3.weight(.semibold))
Text("Create a schedule that wakes clawd via the Gateway. Use an isolated session for agent turns so your main chat stays clean.")
Text(
"Create a schedule that wakes clawd via the Gateway. Use an isolated session for agent turns so your main chat stays clean.")
.font(.callout)
.foregroundStyle(.secondary)
.fixedSize(horizontal: false, vertical: true)
@@ -570,7 +571,8 @@ private struct CronJobEditor: View {
GridRow {
Color.clear
.frame(width: self.labelColumnWidth, height: 1)
Text("Main jobs post a system event into the current main session. Isolated jobs run clawd in a dedicated session and can deliver results (WhatsApp/Telegram/etc).")
Text(
"Main jobs post a system event into the current main session. Isolated jobs run clawd in a dedicated session and can deliver results (WhatsApp/Telegram/etc).")
.font(.footnote)
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)
@@ -594,7 +596,8 @@ private struct CronJobEditor: View {
GridRow {
Color.clear
.frame(width: self.labelColumnWidth, height: 1)
Text("“At” runs once, “Every” repeats with a duration, “Cron” uses a 5-field Unix expression.")
Text(
"“At” runs once, “Every” repeats with a duration, “Cron” uses a 5-field Unix expression.")
.font(.footnote)
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)
@@ -604,7 +607,10 @@ private struct CronJobEditor: View {
case .at:
GridRow {
self.gridLabel("At")
DatePicker("", selection: self.$atDate, displayedComponents: [.date, .hourAndMinute])
DatePicker(
"",
selection: self.$atDate,
displayedComponents: [.date, .hourAndMinute])
.labelsHidden()
.frame(maxWidth: .infinity, alignment: .leading)
}
@@ -635,7 +641,8 @@ private struct CronJobEditor: View {
GroupBox("Payload") {
VStack(alignment: .leading, spacing: 10) {
if self.sessionTarget == .isolated {
Text("Isolated jobs always run an agent turn. The result can be delivered to a surface, and a short summary is posted back to your main chat.")
Text(
"Isolated jobs always run an agent turn. The result can be delivered to a surface, and a short summary is posted back to your main chat.")
.font(.footnote)
.foregroundStyle(.secondary)
.fixedSize(horizontal: false, vertical: true)
@@ -655,7 +662,8 @@ private struct CronJobEditor: View {
GridRow {
Color.clear
.frame(width: self.labelColumnWidth, height: 1)
Text("System events are injected into the current main session. Agent turns require an isolated session target.")
Text(
"System events are injected into the current main session. Agent turns require an isolated session target.")
.font(.footnote)
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)
@@ -687,7 +695,8 @@ private struct CronJobEditor: View {
GridRow {
Color.clear
.frame(width: self.labelColumnWidth, height: 1)
Text("Controls the label used when posting the completion summary back to the main session.")
Text(
"Controls the label used when posting the completion summary back to the main session.")
.font(.footnote)
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)

View File

@@ -45,13 +45,13 @@ struct MenuContent: View {
WebChatManager.shared.show(sessionKey: WebChatManager.shared.preferredSessionKey())
}
}
Toggle(isOn: Binding(
get: { self.browserControlEnabled },
set: { enabled in
self.browserControlEnabled = enabled
ClawdisConfigFile.setBrowserControlEnabled(enabled)
})
) {
Toggle(
isOn: Binding(
get: { self.browserControlEnabled },
set: { enabled in
self.browserControlEnabled = enabled
ClawdisConfigFile.setBrowserControlEnabled(enabled)
})) {
Text("Browser Control")
}
Toggle(isOn: Binding(get: { self.state.canvasEnabled }, set: { self.state.canvasEnabled = $0 })) {
@@ -110,7 +110,9 @@ struct MenuContent: View {
await self.reloadSessionMenu()
}
} label: {
Label(level.capitalized, systemImage: row.thinkingLevel == normalized ? "checkmark" : "")
Label(
level.capitalized,
systemImage: row.thinkingLevel == normalized ? "checkmark" : "")
}
}
}
@@ -126,7 +128,9 @@ struct MenuContent: View {
await self.reloadSessionMenu()
}
} label: {
Label(level.capitalized, systemImage: row.verboseLevel == normalized ? "checkmark" : "")
Label(
level.capitalized,
systemImage: row.verboseLevel == normalized ? "checkmark" : "")
}
}
}

View File

@@ -53,7 +53,8 @@ final class PeekabooBridgeHostCoordinator {
self.host = host
await host.start()
self.logger.info("PeekabooBridge host started at \(PeekabooBridgeConstants.clawdisSocketPath, privacy: .public)")
self.logger
.info("PeekabooBridge host started at \(PeekabooBridgeConstants.clawdisSocketPath, privacy: .public)")
}
}

View File

@@ -28,4 +28,3 @@ extension View {
self.modifier(PointingHandCursorModifier())
}
}

View File

@@ -15,4 +15,3 @@ enum ScreenshotSize {
return Size(width: width, height: height)
}
}

View File

@@ -224,26 +224,26 @@ struct ToolsSettings: View {
EmptyView()
} else {
VStack(alignment: .leading, spacing: 10) {
Text(title)
.font(.callout.weight(.semibold))
.padding(.top, 6)
Text(title)
.font(.callout.weight(.semibold))
.padding(.top, 6)
VStack(spacing: 8) {
ForEach(filtered) { tool in
ToolRow(
tool: tool,
state: self.binding(for: tool),
packageManager: self.packageManager,
refreshState: { await self.refresh(tool: tool) })
.padding(10)
.background(Color(nsColor: .controlBackgroundColor))
.clipShape(RoundedRectangle(cornerRadius: 10))
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.secondary.opacity(0.15), lineWidth: 1))
VStack(spacing: 8) {
ForEach(filtered) { tool in
ToolRow(
tool: tool,
state: self.binding(for: tool),
packageManager: self.packageManager,
refreshState: { await self.refresh(tool: tool) })
.padding(10)
.background(Color(nsColor: .controlBackgroundColor))
.clipShape(RoundedRectangle(cornerRadius: 10))
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.secondary.opacity(0.15), lineWidth: 1))
}
}
}
}
}
}

View File

@@ -639,9 +639,9 @@ enum CommandResolver {
return URL(fileURLWithPath: expanded)
}
#if SWIFT_PACKAGE
#if SWIFT_PACKAGE
static func _testNodeManagerBinPaths(home: URL) -> [String] {
self.nodeManagerBinPaths(home: home)
}
#endif
#endif
}

View File

@@ -36,8 +36,8 @@ struct GatewayChatMessage: Codable, Identifiable {
id: UUID = .init(),
role: String,
content: [GatewayChatMessageContent],
timestamp: Double?
) {
timestamp: Double?)
{
self.id = id
self.role = role
self.content = content
@@ -124,6 +124,7 @@ final class WebChatViewModel: ObservableObject {
private var pendingRuns = Set<String>() {
didSet { self.pendingRunCount = self.pendingRuns.count }
}
private var lastHealthPollAt: Date?
init(sessionKey: String) {
@@ -162,7 +163,8 @@ final class WebChatViewModel: ObservableObject {
do {
let data = try await Task.detached { try Data(contentsOf: url) }.value
guard data.count <= 5_000_000 else {
await MainActor.run { self.errorText = "Attachment \(url.lastPathComponent) exceeds 5 MB limit" }
await MainActor
.run { self.errorText = "Attachment \(url.lastPathComponent) exceeds 5 MB limit" }
continue
}
let uti = UTType(filenameExtension: url.pathExtension) ?? .data
@@ -445,7 +447,8 @@ struct WebChatView: View {
.foregroundStyle(Color.accentColor.opacity(0.9))
Text("Say hi to Clawd")
.font(.headline)
Text(self.viewModel.healthOK ? "This is the native SwiftUI debug chat." : "Connecting to the gateway…")
Text(self.viewModel
.healthOK ? "This is the native SwiftUI debug chat." : "Connecting to the gateway…")
.font(.subheadline)
.foregroundStyle(.secondary)
}
@@ -458,7 +461,9 @@ struct WebChatView: View {
} else {
ForEach(self.viewModel.messages) { msg in
MessageBubble(message: msg)
.frame(maxWidth: .infinity, alignment: msg.role.lowercased() == "user" ? .trailing : .leading)
.frame(
maxWidth: .infinity,
alignment: msg.role.lowercased() == "user" ? .trailing : .leading)
}
}
@@ -673,7 +678,7 @@ private struct ChatMessageBody: View {
switch block.kind {
case .text:
MarkdownTextView(text: block.text)
case .code(let language):
case let .code(language):
CodeBlockView(code: block.text, language: language)
}
}
@@ -747,7 +752,7 @@ private struct AttachmentRow: View {
var body: some View {
HStack(spacing: 8) {
Image(systemName: "paperclip")
Text(att.fileName ?? "Attachment")
Text(self.att.fileName ?? "Attachment")
.font(.footnote)
.lineLimit(1)
Spacer()