refactor: rename bundle identifiers to com.clawdis

This commit is contained in:
Peter Steinberger
2026-01-03 12:26:22 +01:00
parent daa1460502
commit 7165c8a7e5
153 changed files with 282 additions and 242 deletions

View File

@@ -2,6 +2,9 @@
## Unreleased ## Unreleased
### Breaking
- Identifiers: rename bundle IDs and internal domains to `com.clawdis.*` (macOS: `com.clawdis.mac`, iOS: `com.clawdis.ios`, Android: `com.clawdis.android`) and update the gateway LaunchAgent label to `com.clawdis.gateway`.
### Features ### Features
- Gateway: support `gateway.port` + `CLAWDIS_GATEWAY_PORT` across CLI, TUI, and macOS app. - Gateway: support `gateway.port` + `CLAWDIS_GATEWAY_PORT` across CLI, TUI, and macOS app.

View File

@@ -6,7 +6,7 @@ plugins {
} }
android { android {
namespace = "com.steipete.clawdis.node" namespace = "com.clawdis.android"
compileSdk = 36 compileSdk = 36
sourceSets { sourceSets {
@@ -16,7 +16,7 @@ android {
} }
defaultConfig { defaultConfig {
applicationId = "com.steipete.clawdis.node" applicationId = "com.clawdis.android"
minSdk = 31 minSdk = 31
targetSdk = 36 targetSdk = 36
versionCode = 1 versionCode = 1

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node package com.clawdis.android
enum class CameraHudKind { enum class CameraHudKind {
Photo, Photo,

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node package com.clawdis.android
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node package com.clawdis.android
import android.Manifest import android.Manifest
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
@@ -18,8 +18,8 @@ import androidx.core.view.WindowInsetsControllerCompat
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import com.steipete.clawdis.node.ui.RootScreen import com.clawdis.android.ui.RootScreen
import com.steipete.clawdis.node.ui.ClawdisTheme import com.clawdis.android.ui.ClawdisTheme
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {

View File

@@ -1,12 +1,12 @@
package com.steipete.clawdis.node package com.clawdis.android
import android.app.Application import android.app.Application
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import com.steipete.clawdis.node.bridge.BridgeEndpoint import com.clawdis.android.bridge.BridgeEndpoint
import com.steipete.clawdis.node.chat.OutgoingAttachment import com.clawdis.android.chat.OutgoingAttachment
import com.steipete.clawdis.node.node.CameraCaptureManager import com.clawdis.android.node.CameraCaptureManager
import com.steipete.clawdis.node.node.CanvasController import com.clawdis.android.node.CanvasController
import com.steipete.clawdis.node.node.ScreenRecordManager import com.clawdis.android.node.ScreenRecordManager
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
class MainViewModel(app: Application) : AndroidViewModel(app) { class MainViewModel(app: Application) : AndroidViewModel(app) {

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node package com.clawdis.android
import android.app.Application import android.app.Application

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node package com.clawdis.android
import android.app.Notification import android.app.Notification
import android.app.NotificationChannel import android.app.NotificationChannel
@@ -146,7 +146,7 @@ class NodeForegroundService : Service() {
private const val CHANNEL_ID = "connection" private const val CHANNEL_ID = "connection"
private const val NOTIFICATION_ID = 1 private const val NOTIFICATION_ID = 1
private const val ACTION_STOP = "com.steipete.clawdis.node.action.STOP" private const val ACTION_STOP = "com.clawdis.android.action.STOP"
fun start(context: Context) { fun start(context: Context) {
val intent = Intent(context, NodeForegroundService::class.java) val intent = Intent(context, NodeForegroundService::class.java)

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node package com.clawdis.android
import android.Manifest import android.Manifest
import android.content.Context import android.content.Context
@@ -6,27 +6,27 @@ import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import android.os.SystemClock import android.os.SystemClock
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.steipete.clawdis.node.chat.ChatController import com.clawdis.android.chat.ChatController
import com.steipete.clawdis.node.chat.ChatMessage import com.clawdis.android.chat.ChatMessage
import com.steipete.clawdis.node.chat.ChatPendingToolCall import com.clawdis.android.chat.ChatPendingToolCall
import com.steipete.clawdis.node.chat.ChatSessionEntry import com.clawdis.android.chat.ChatSessionEntry
import com.steipete.clawdis.node.chat.OutgoingAttachment import com.clawdis.android.chat.OutgoingAttachment
import com.steipete.clawdis.node.bridge.BridgeDiscovery import com.clawdis.android.bridge.BridgeDiscovery
import com.steipete.clawdis.node.bridge.BridgeEndpoint import com.clawdis.android.bridge.BridgeEndpoint
import com.steipete.clawdis.node.bridge.BridgePairingClient import com.clawdis.android.bridge.BridgePairingClient
import com.steipete.clawdis.node.bridge.BridgeSession import com.clawdis.android.bridge.BridgeSession
import com.steipete.clawdis.node.node.CameraCaptureManager import com.clawdis.android.node.CameraCaptureManager
import com.steipete.clawdis.node.BuildConfig import com.clawdis.android.BuildConfig
import com.steipete.clawdis.node.node.CanvasController import com.clawdis.android.node.CanvasController
import com.steipete.clawdis.node.node.ScreenRecordManager import com.clawdis.android.node.ScreenRecordManager
import com.steipete.clawdis.node.protocol.ClawdisCapability import com.clawdis.android.protocol.ClawdisCapability
import com.steipete.clawdis.node.protocol.ClawdisCameraCommand import com.clawdis.android.protocol.ClawdisCameraCommand
import com.steipete.clawdis.node.protocol.ClawdisCanvasA2UIAction import com.clawdis.android.protocol.ClawdisCanvasA2UIAction
import com.steipete.clawdis.node.protocol.ClawdisCanvasA2UICommand import com.clawdis.android.protocol.ClawdisCanvasA2UICommand
import com.steipete.clawdis.node.protocol.ClawdisCanvasCommand import com.clawdis.android.protocol.ClawdisCanvasCommand
import com.steipete.clawdis.node.protocol.ClawdisScreenCommand import com.clawdis.android.protocol.ClawdisScreenCommand
import com.steipete.clawdis.node.voice.TalkModeManager import com.clawdis.android.voice.TalkModeManager
import com.steipete.clawdis.node.voice.VoiceWakeManager import com.clawdis.android.voice.VoiceWakeManager
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node package com.clawdis.android
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.Intent import android.content.Intent

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node package com.clawdis.android
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context

View File

@@ -1,6 +1,6 @@
@file:Suppress("DEPRECATION") @file:Suppress("DEPRECATION")
package com.steipete.clawdis.node package com.clawdis.android
import android.content.Context import android.content.Context
import androidx.core.content.edit import androidx.core.content.edit

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node package com.clawdis.android
enum class VoiceWakeMode(val rawValue: String) { enum class VoiceWakeMode(val rawValue: String) {
Off("off"), Off("off"),

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node package com.clawdis.android
object WakeWords { object WakeWords {
const val maxWords: Int = 32 const val maxWords: Int = 32

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.bridge package com.clawdis.android.bridge
object BonjourEscapes { object BonjourEscapes {
fun decode(input: String): String { fun decode(input: String): String {

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.bridge package com.clawdis.android.bridge
import android.content.Context import android.content.Context
import android.net.ConnectivityManager import android.net.ConnectivityManager

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.bridge package com.clawdis.android.bridge
data class BridgeEndpoint( data class BridgeEndpoint(
val stableId: String, val stableId: String,

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.bridge package com.clawdis.android.bridge
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.bridge package com.clawdis.android.bridge
import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -11,7 +11,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import com.steipete.clawdis.node.BuildConfig import com.clawdis.android.BuildConfig
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject

View File

@@ -1,6 +1,6 @@
package com.steipete.clawdis.node.chat package com.clawdis.android.chat
import com.steipete.clawdis.node.bridge.BridgeSession import com.clawdis.android.bridge.BridgeSession
import java.util.UUID import java.util.UUID
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.chat package com.clawdis.android.chat
data class ChatMessage( data class ChatMessage(
val id: String, val id: String,

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.node package com.clawdis.android.node
import android.Manifest import android.Manifest
import android.content.Context import android.content.Context
@@ -20,7 +20,7 @@ import androidx.camera.video.VideoRecordEvent
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.checkSelfPermission import androidx.core.content.ContextCompat.checkSelfPermission
import androidx.core.graphics.scale import androidx.core.graphics.scale
import com.steipete.clawdis.node.PermissionRequester import com.clawdis.android.PermissionRequester
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeout import kotlinx.coroutines.withTimeout

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.node package com.clawdis.android.node
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Canvas import android.graphics.Canvas
@@ -17,7 +17,7 @@ import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.JsonPrimitive
import com.steipete.clawdis.node.BuildConfig import com.clawdis.android.BuildConfig
import kotlin.coroutines.resume import kotlin.coroutines.resume
class CanvasController { class CanvasController {

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.node package com.clawdis.android.node
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min

View File

@@ -1,11 +1,11 @@
package com.steipete.clawdis.node.node package com.clawdis.android.node
import android.content.Context import android.content.Context
import android.hardware.display.DisplayManager import android.hardware.display.DisplayManager
import android.media.MediaRecorder import android.media.MediaRecorder
import android.media.projection.MediaProjectionManager import android.media.projection.MediaProjectionManager
import android.util.Base64 import android.util.Base64
import com.steipete.clawdis.node.ScreenCaptureRequester import com.clawdis.android.ScreenCaptureRequester
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@@ -16,13 +16,13 @@ class ScreenRecordManager(private val context: Context) {
data class Payload(val payloadJson: String) data class Payload(val payloadJson: String)
@Volatile private var screenCaptureRequester: ScreenCaptureRequester? = null @Volatile private var screenCaptureRequester: ScreenCaptureRequester? = null
@Volatile private var permissionRequester: com.steipete.clawdis.node.PermissionRequester? = null @Volatile private var permissionRequester: com.clawdis.android.PermissionRequester? = null
fun attachScreenCaptureRequester(requester: ScreenCaptureRequester) { fun attachScreenCaptureRequester(requester: ScreenCaptureRequester) {
screenCaptureRequester = requester screenCaptureRequester = requester
} }
fun attachPermissionRequester(requester: com.steipete.clawdis.node.PermissionRequester) { fun attachPermissionRequester(requester: com.clawdis.android.PermissionRequester) {
permissionRequester = requester permissionRequester = requester
} }

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.protocol package com.clawdis.android.protocol
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.JsonPrimitive

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.protocol package com.clawdis.android.protocol
enum class ClawdisCapability(val rawValue: String) { enum class ClawdisCapability(val rawValue: String) {
Canvas("canvas"), Canvas("canvas"),

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.ui package com.clawdis.android.ui
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box

View File

@@ -1,8 +1,8 @@
package com.steipete.clawdis.node.ui package com.clawdis.android.ui
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import com.steipete.clawdis.node.MainViewModel import com.clawdis.android.MainViewModel
import com.steipete.clawdis.node.ui.chat.ChatSheetContent import com.clawdis.android.ui.chat.ChatSheetContent
@Composable @Composable
fun ChatSheet(viewModel: MainViewModel) { fun ChatSheet(viewModel: MainViewModel) {

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.ui package com.clawdis.android.ui
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.ui package com.clawdis.android.ui
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.Manifest import android.Manifest
@@ -65,8 +65,8 @@ import androidx.compose.ui.viewinterop.AndroidView
import androidx.compose.ui.window.Popup import androidx.compose.ui.window.Popup
import androidx.compose.ui.window.PopupProperties import androidx.compose.ui.window.PopupProperties
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.steipete.clawdis.node.CameraHudKind import com.clawdis.android.CameraHudKind
import com.steipete.clawdis.node.MainViewModel import com.clawdis.android.MainViewModel
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.ui package com.clawdis.android.ui
import android.Manifest import android.Manifest
import android.content.pm.PackageManager import android.content.pm.PackageManager
@@ -47,10 +47,10 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.steipete.clawdis.node.BuildConfig import com.clawdis.android.BuildConfig
import com.steipete.clawdis.node.MainViewModel import com.clawdis.android.MainViewModel
import com.steipete.clawdis.node.NodeForegroundService import com.clawdis.android.NodeForegroundService
import com.steipete.clawdis.node.VoiceWakeMode import com.clawdis.android.VoiceWakeMode
@Composable @Composable
fun SettingsSheet(viewModel: MainViewModel) { fun SettingsSheet(viewModel: MainViewModel) {
@@ -381,7 +381,7 @@ fun SettingsSheet(viewModel: MainViewModel) {
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
Button( Button(
onClick = { onClick = {
val parsed = com.steipete.clawdis.node.WakeWords.parseCommaSeparated(wakeWordsText) val parsed = com.clawdis.android.WakeWords.parseCommaSeparated(wakeWordsText)
viewModel.setWakeWords(parsed) viewModel.setWakeWords(parsed)
}, },
enabled = isConnected, enabled = isConnected,

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.ui package com.clawdis.android.ui
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.ui package com.clawdis.android.ui
import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode import androidx.compose.animation.core.RepeatMode

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.ui.chat package com.clawdis.android.ui.chat
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -38,7 +38,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.steipete.clawdis.node.chat.ChatSessionEntry import com.clawdis.android.chat.ChatSessionEntry
@Composable @Composable
fun ChatComposer( fun ChatComposer(

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.ui.chat package com.clawdis.android.ui.chat
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.util.Base64 import android.util.Base64

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.ui.chat package com.clawdis.android.ui.chat
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -20,8 +20,8 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.alpha
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.steipete.clawdis.node.chat.ChatMessage import com.clawdis.android.chat.ChatMessage
import com.steipete.clawdis.node.chat.ChatPendingToolCall import com.clawdis.android.chat.ChatPendingToolCall
@Composable @Composable
fun ChatMessageListCard( fun ChatMessageListCard(

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.ui.chat package com.clawdis.android.ui.chat
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.util.Base64 import android.util.Base64
@@ -31,9 +31,9 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import com.steipete.clawdis.node.chat.ChatMessage import com.clawdis.android.chat.ChatMessage
import com.steipete.clawdis.node.chat.ChatMessageContent import com.clawdis.android.chat.ChatMessageContent
import com.steipete.clawdis.node.chat.ChatPendingToolCall import com.clawdis.android.chat.ChatPendingToolCall
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.ui.chat package com.clawdis.android.ui.chat
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -20,7 +20,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.steipete.clawdis.node.chat.ChatSessionEntry import com.clawdis.android.chat.ChatSessionEntry
@Composable @Composable
fun ChatSessionsDialog( fun ChatSessionsDialog(

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.ui.chat package com.clawdis.android.ui.chat
import android.content.ContentResolver import android.content.ContentResolver
import android.net.Uri import android.net.Uri
@@ -19,8 +19,8 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.steipete.clawdis.node.MainViewModel import com.clawdis.android.MainViewModel
import com.steipete.clawdis.node.chat.OutgoingAttachment import com.clawdis.android.chat.OutgoingAttachment
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

View File

@@ -1,6 +1,6 @@
package com.steipete.clawdis.node.ui.chat package com.clawdis.android.ui.chat
import com.steipete.clawdis.node.chat.ChatSessionEntry import com.clawdis.android.chat.ChatSessionEntry
private const val MAIN_SESSION_KEY = "main" private const val MAIN_SESSION_KEY = "main"
private const val RECENT_WINDOW_MS = 24 * 60 * 60 * 1000L private const val RECENT_WINDOW_MS = 24 * 60 * 60 * 1000L

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.voice package com.clawdis.android.voice
import android.media.MediaDataSource import android.media.MediaDataSource
import kotlin.math.min import kotlin.math.min

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.voice package com.clawdis.android.voice
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonElement

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.voice package com.clawdis.android.voice
import android.Manifest import android.Manifest
import android.content.Context import android.content.Context
@@ -20,7 +20,7 @@ import android.speech.tts.TextToSpeech
import android.speech.tts.UtteranceProgressListener import android.speech.tts.UtteranceProgressListener
import android.util.Log import android.util.Log
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.steipete.clawdis.node.bridge.BridgeSession import com.clawdis.android.bridge.BridgeSession
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.URL import java.net.URL
import java.util.UUID import java.util.UUID

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.voice package com.clawdis.android.voice
object VoiceWakeCommandExtractor { object VoiceWakeCommandExtractor {
fun extractCommand(text: String, triggerWords: List<String>): String? { fun extractCommand(text: String, triggerWords: List<String>): String? {

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.voice package com.clawdis.android.voice
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node package com.clawdis.android
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.bridge package com.clawdis.android.bridge
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.bridge package com.clawdis.android.bridge
import io.kotest.core.spec.style.StringSpec import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.bridge package com.clawdis.android.bridge
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async import kotlinx.coroutines.async

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.bridge package com.clawdis.android.bridge
import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.node package com.clawdis.android.node
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull import org.junit.Assert.assertNull

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.node package com.clawdis.android.node
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.protocol package com.clawdis.android.protocol
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.protocol package com.clawdis.android.protocol
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test

View File

@@ -1,6 +1,6 @@
package com.steipete.clawdis.node.ui.chat package com.clawdis.android.ui.chat
import com.steipete.clawdis.node.chat.ChatSessionEntry import com.clawdis.android.chat.ChatSessionEntry
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.voice package com.clawdis.android.voice
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull import org.junit.Assert.assertNull

View File

@@ -1,4 +1,4 @@
package com.steipete.clawdis.node.voice package com.clawdis.android.voice
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull import org.junit.Assert.assertNull

View File

@@ -14,7 +14,7 @@ actor BridgeClient {
{ {
self.lineBuffer = Data() self.lineBuffer = Data()
let connection = NWConnection(to: endpoint, using: .tcp) let connection = NWConnection(to: endpoint, using: .tcp)
let queue = DispatchQueue(label: "com.steipete.clawdis.ios.bridge-client") let queue = DispatchQueue(label: "com.clawdis.ios.bridge-client")
defer { connection.cancel() } defer { connection.cancel() }
try await self.withTimeout(seconds: 8, purpose: "connect") { try await self.withTimeout(seconds: 8, purpose: "connect") {
try await self.startAndWaitForReady(connection, queue: queue) try await self.startAndWaitForReady(connection, queue: queue)

View File

@@ -99,7 +99,7 @@ final class BridgeConnectionController {
guard !instanceId.isEmpty else { return } guard !instanceId.isEmpty else { return }
let token = KeychainStore.loadString( let token = KeychainStore.loadString(
service: "com.steipete.clawdis.bridge", service: "com.clawdis.bridge",
account: self.keychainAccount(instanceId: instanceId))? account: self.keychainAccount(instanceId: instanceId))?
.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" .trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
guard !token.isEmpty else { return } guard !token.isEmpty else { return }
@@ -189,7 +189,7 @@ final class BridgeConnectionController {
if !refreshed.isEmpty, refreshed != token { if !refreshed.isEmpty, refreshed != token {
_ = KeychainStore.saveString( _ = KeychainStore.saveString(
refreshed, refreshed,
service: "com.steipete.clawdis.bridge", service: "com.clawdis.bridge",
account: self.keychainAccount(instanceId: instanceId)) account: self.keychainAccount(instanceId: instanceId))
} }
appModel.connectToBridge(endpoint: endpoint, hello: self.makeHello(token: resolvedToken)) appModel.connectToBridge(endpoint: endpoint, hello: self.makeHello(token: resolvedToken))

View File

@@ -102,7 +102,7 @@ final class BridgeDiscoveryModel {
} }
self.browsers[domain] = browser self.browsers[domain] = browser
browser.start(queue: DispatchQueue(label: "com.steipete.clawdis.ios.bridge-discovery.\(domain)")) browser.start(queue: DispatchQueue(label: "com.clawdis.ios.bridge-discovery.\(domain)"))
} }
} }

View File

@@ -78,7 +78,7 @@ actor BridgeSession {
let params = NWParameters.tcp let params = NWParameters.tcp
params.includePeerToPeer = true params.includePeerToPeer = true
let connection = NWConnection(to: endpoint, using: params) let connection = NWConnection(to: endpoint, using: params)
let queue = DispatchQueue(label: "com.steipete.clawdis.ios.bridge-session") let queue = DispatchQueue(label: "com.clawdis.ios.bridge-session")
self.connection = connection self.connection = connection
self.queue = queue self.queue = queue

View File

@@ -1,8 +1,8 @@
import Foundation import Foundation
enum BridgeSettingsStore { enum BridgeSettingsStore {
private static let bridgeService = "com.steipete.clawdis.bridge" private static let bridgeService = "com.clawdis.bridge"
private static let nodeService = "com.steipete.clawdis.node" private static let nodeService = "com.clawdis.node"
private static let instanceIdDefaultsKey = "node.instanceId" private static let instanceIdDefaultsKey = "node.instanceId"
private static let preferredBridgeStableIDDefaultsKey = "bridge.preferredStableID" private static let preferredBridgeStableIDDefaultsKey = "bridge.preferredStableID"

View File

@@ -68,7 +68,7 @@ final class ScreenRecordService: @unchecked Sendable {
try? FileManager.default.removeItem(at: outURL) try? FileManager.default.removeItem(at: outURL)
let state = CaptureState() let state = CaptureState()
let recordQueue = DispatchQueue(label: "com.steipete.clawdis.screenrecord") let recordQueue = DispatchQueue(label: "com.clawdis.screenrecord")
try await withCheckedThrowingContinuation { (cont: CheckedContinuation<Void, Error>) in try await withCheckedThrowingContinuation { (cont: CheckedContinuation<Void, Error>) in
let handler: @Sendable (CMSampleBuffer, RPSampleBufferType, Error?) -> Void = { sample, type, error in let handler: @Sendable (CMSampleBuffer, RPSampleBufferType, Error?) -> Void = { sample, type, error in

View File

@@ -353,7 +353,7 @@ struct SettingsTab: View {
do { do {
let statusStore = self.connectStatus let statusStore = self.connectStatus
let existing = KeychainStore.loadString( let existing = KeychainStore.loadString(
service: "com.steipete.clawdis.bridge", service: "com.clawdis.bridge",
account: self.keychainAccount()) account: self.keychainAccount())
let existingToken = (existing?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false) ? let existingToken = (existing?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false) ?
existing : existing :
@@ -381,7 +381,7 @@ struct SettingsTab: View {
if !token.isEmpty, token != existingToken { if !token.isEmpty, token != existingToken {
_ = KeychainStore.saveString( _ = KeychainStore.saveString(
token, token,
service: "com.steipete.clawdis.bridge", service: "com.clawdis.bridge",
account: self.keychainAccount()) account: self.keychainAccount())
} }
@@ -427,7 +427,7 @@ struct SettingsTab: View {
do { do {
let statusStore = self.connectStatus let statusStore = self.connectStatus
let existing = KeychainStore.loadString( let existing = KeychainStore.loadString(
service: "com.steipete.clawdis.bridge", service: "com.clawdis.bridge",
account: self.keychainAccount()) account: self.keychainAccount())
let existingToken = (existing?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false) ? let existingToken = (existing?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false) ?
existing : existing :
@@ -455,7 +455,7 @@ struct SettingsTab: View {
if !token.isEmpty, token != existingToken { if !token.isEmpty, token != existingToken {
_ = KeychainStore.saveString( _ = KeychainStore.saveString(
token, token,
service: "com.steipete.clawdis.bridge", service: "com.clawdis.bridge",
account: self.keychainAccount()) account: self.keychainAccount())
} }

View File

@@ -47,7 +47,7 @@ final class TalkModeManager: NSObject {
private var chatSubscribedSessionKeys = Set<String>() private var chatSubscribedSessionKeys = Set<String>()
private let logger = Logger(subsystem: "com.steipete.clawdis", category: "TalkMode") private let logger = Logger(subsystem: "com.clawdis", category: "TalkMode")
func attachBridge(_ bridge: BridgeSession) { func attachBridge(_ bridge: BridgeSession) {
self.bridge = bridge self.bridge = bridge

View File

@@ -6,7 +6,7 @@ import Testing
@Suite struct BridgeClientTests { @Suite struct BridgeClientTests {
private final class LineServer: @unchecked Sendable { private final class LineServer: @unchecked Sendable {
private let queue = DispatchQueue(label: "com.steipete.clawdis.tests.bridge-client-server") private let queue = DispatchQueue(label: "com.clawdis.tests.bridge-client-server")
private let listener: NWListener private let listener: NWListener
private var connection: NWConnection? private var connection: NWConnection?
private var buffer = Data() private var buffer = Data()

View File

@@ -10,8 +10,8 @@ private struct KeychainEntry: Hashable {
let account: String let account: String
} }
private let bridgeService = "com.steipete.clawdis.bridge" private let bridgeService = "com.clawdis.bridge"
private let nodeService = "com.steipete.clawdis.node" private let nodeService = "com.clawdis.node"
private let instanceIdEntry = KeychainEntry(service: nodeService, account: "instanceId") private let instanceIdEntry = KeychainEntry(service: nodeService, account: "instanceId")
private let preferredBridgeEntry = KeychainEntry(service: bridgeService, account: "preferredStableID") private let preferredBridgeEntry = KeychainEntry(service: bridgeService, account: "preferredStableID")
private let lastBridgeEntry = KeychainEntry(service: bridgeService, account: "lastDiscoveredStableID") private let lastBridgeEntry = KeychainEntry(service: bridgeService, account: "lastDiscoveredStableID")

View File

@@ -7,8 +7,8 @@ private struct KeychainEntry: Hashable {
let account: String let account: String
} }
private let bridgeService = "com.steipete.clawdis.bridge" private let bridgeService = "com.clawdis.bridge"
private let nodeService = "com.steipete.clawdis.node" private let nodeService = "com.clawdis.node"
private let instanceIdEntry = KeychainEntry(service: nodeService, account: "instanceId") private let instanceIdEntry = KeychainEntry(service: nodeService, account: "instanceId")
private let preferredBridgeEntry = KeychainEntry(service: bridgeService, account: "preferredStableID") private let preferredBridgeEntry = KeychainEntry(service: bridgeService, account: "preferredStableID")
private let lastBridgeEntry = KeychainEntry(service: bridgeService, account: "lastDiscoveredStableID") private let lastBridgeEntry = KeychainEntry(service: bridgeService, account: "lastDiscoveredStableID")

View File

@@ -4,7 +4,7 @@ import Testing
@Suite struct KeychainStoreTests { @Suite struct KeychainStoreTests {
@Test func saveLoadUpdateDeleteRoundTrip() { @Test func saveLoadUpdateDeleteRoundTrip() {
let service = "com.steipete.clawdis.tests.\(UUID().uuidString)" let service = "com.clawdis.tests.\(UUID().uuidString)"
let account = "value" let account = "value"
#expect(KeychainStore.delete(service: service, account: account)) #expect(KeychainStore.delete(service: service, account: account))

View File

@@ -1,4 +1,4 @@
app_identifier("com.steipete.clawdis.ios") app_identifier("com.clawdis.ios")
# Auth is expected via App Store Connect API key. # Auth is expected via App Store Connect API key.
# Provide either: # Provide either:

View File

@@ -1,6 +1,6 @@
name: Clawdis name: Clawdis
options: options:
bundleIdPrefix: com.steipete.clawdis bundleIdPrefix: com.clawdis
deploymentTarget: deploymentTarget:
iOS: "17.0" iOS: "17.0"
xcodeVersion: "16.0" xcodeVersion: "16.0"
@@ -65,8 +65,8 @@ targets:
CODE_SIGN_IDENTITY: "Apple Development" CODE_SIGN_IDENTITY: "Apple Development"
CODE_SIGN_STYLE: Manual CODE_SIGN_STYLE: Manual
DEVELOPMENT_TEAM: Y5PE65HELJ DEVELOPMENT_TEAM: Y5PE65HELJ
PRODUCT_BUNDLE_IDENTIFIER: com.steipete.clawdis.ios PRODUCT_BUNDLE_IDENTIFIER: com.clawdis.ios
PROVISIONING_PROFILE_SPECIFIER: "com.steipete.clawdis.ios Development" PROVISIONING_PROFILE_SPECIFIER: "com.clawdis.ios Development"
SWIFT_VERSION: "6.0" SWIFT_VERSION: "6.0"
info: info:
path: Sources/Info.plist path: Sources/Info.plist
@@ -98,7 +98,7 @@ targets:
product: SwabbleKit product: SwabbleKit
settings: settings:
base: base:
PRODUCT_BUNDLE_IDENTIFIER: com.steipete.clawdis.ios.tests PRODUCT_BUNDLE_IDENTIFIER: com.clawdis.ios.tests
SWIFT_VERSION: "6.0" SWIFT_VERSION: "6.0"
TEST_HOST: "$(BUILT_PRODUCTS_DIR)/Clawdis.app/Clawdis" TEST_HOST: "$(BUILT_PRODUCTS_DIR)/Clawdis.app/Clawdis"
BUNDLE_LOADER: "$(TEST_HOST)" BUNDLE_LOADER: "$(TEST_HOST)"

View File

@@ -2,7 +2,7 @@ import Foundation
import OSLog import OSLog
enum AgentWorkspace { enum AgentWorkspace {
private static let logger = Logger(subsystem: "com.steipete.clawdis", category: "workspace") private static let logger = Logger(subsystem: "com.clawdis", category: "workspace")
static let agentsFilename = "AGENTS.md" static let agentsFilename = "AGENTS.md"
static let soulFilename = "SOUL.md" static let soulFilename = "SOUL.md"
static let identityFilename = "IDENTITY.md" static let identityFilename = "IDENTITY.md"

View File

@@ -58,7 +58,7 @@ enum AnthropicAuthResolver {
} }
enum AnthropicOAuth { enum AnthropicOAuth {
private static let logger = Logger(subsystem: "com.steipete.clawdis", category: "anthropic-oauth") private static let logger = Logger(subsystem: "com.clawdis", category: "anthropic-oauth")
private static let clientId = "9d1c250a-e61b-44d9-88ed-5944d1962f5e" private static let clientId = "9d1c250a-e61b-44d9-88ed-5944d1962f5e"
private static let authorizeURL = URL(string: "https://claude.ai/oauth/authorize")! private static let authorizeURL = URL(string: "https://claude.ai/oauth/authorize")!

View File

@@ -19,7 +19,7 @@ actor BridgeConnectionHandler {
private let logger: Logger private let logger: Logger
private let decoder = JSONDecoder() private let decoder = JSONDecoder()
private let encoder = JSONEncoder() private let encoder = JSONEncoder()
private let queue = DispatchQueue(label: "com.steipete.clawdis.bridge.connection") private let queue = DispatchQueue(label: "com.clawdis.bridge.connection")
private var buffer = Data() private var buffer = Data()
private var isAuthenticated = false private var isAuthenticated = false

View File

@@ -8,7 +8,7 @@ import OSLog
actor BridgeServer { actor BridgeServer {
static let shared = BridgeServer() static let shared = BridgeServer()
private let logger = Logger(subsystem: "com.steipete.clawdis", category: "bridge") private let logger = Logger(subsystem: "com.clawdis", category: "bridge")
private var listener: NWListener? private var listener: NWListener?
private var isRunning = false private var isRunning = false
private var store: PairedNodesStore? private var store: PairedNodesStore?
@@ -42,7 +42,7 @@ actor BridgeServer {
Task { await self.handleListenerState(state) } Task { await self.handleListenerState(state) }
} }
listener.start(queue: DispatchQueue(label: "com.steipete.clawdis.bridge")) listener.start(queue: DispatchQueue(label: "com.clawdis.bridge"))
self.listener = listener self.listener = listener
} catch { } catch {
self.logger.error("bridge start failed: \(error.localizedDescription, privacy: .public)") self.logger.error("bridge start failed: \(error.localizedDescription, privacy: .public)")

View File

@@ -36,7 +36,7 @@ actor CameraCaptureService {
} }
} }
private let logger = Logger(subsystem: "com.steipete.clawdis", category: "camera") private let logger = Logger(subsystem: "com.clawdis", category: "camera")
func listDevices() -> [CameraDeviceInfo] { func listDevices() -> [CameraDeviceInfo] {
Self.availableCameras().map { device in Self.availableCameras().map { device in

View File

@@ -10,7 +10,7 @@ final class CanvasFileWatcher: @unchecked Sendable {
init(url: URL, onChange: @escaping () -> Void) { init(url: URL, onChange: @escaping () -> Void) {
self.url = url self.url = url
self.queue = DispatchQueue(label: "com.steipete.clawdis.canvaswatcher") self.queue = DispatchQueue(label: "com.clawdis.canvaswatcher")
self.onChange = onChange self.onChange = onChange
} }

View File

@@ -7,7 +7,7 @@ import OSLog
final class CanvasManager { final class CanvasManager {
static let shared = CanvasManager() static let shared = CanvasManager()
private static let logger = Logger(subsystem: "com.steipete.clawdis", category: "CanvasManager") private static let logger = Logger(subsystem: "com.clawdis", category: "CanvasManager")
private var panelController: CanvasWindowController? private var panelController: CanvasWindowController?
private var panelSessionKey: String? private var panelSessionKey: String?

View File

@@ -3,7 +3,7 @@ import Foundation
import OSLog import OSLog
import WebKit import WebKit
private let canvasLogger = Logger(subsystem: "com.steipete.clawdis", category: "Canvas") private let canvasLogger = Logger(subsystem: "com.clawdis", category: "Canvas")
final class CanvasSchemeHandler: NSObject, WKURLSchemeHandler { final class CanvasSchemeHandler: NSObject, WKURLSchemeHandler {
private let root: URL private let root: URL

View File

@@ -1,6 +1,6 @@
import AppKit import AppKit
let canvasWindowLogger = Logger(subsystem: "com.steipete.clawdis", category: "Canvas") let canvasWindowLogger = Logger(subsystem: "com.clawdis", category: "Canvas")
enum CanvasLayout { enum CanvasLayout {
static let panelSize = NSSize(width: 520, height: 680) static let panelSize = NSSize(width: 520, height: 680)

View File

@@ -1,7 +1,7 @@
import Foundation import Foundation
enum ClawdisConfigFile { enum ClawdisConfigFile {
private static let logger = Logger(subsystem: "com.steipete.clawdis", category: "config") private static let logger = Logger(subsystem: "com.clawdis", category: "config")
static func url() -> URL { static func url() -> URL {
ClawdisPaths.configURL ClawdisPaths.configURL

View File

@@ -5,7 +5,7 @@ import OSLog
final class ConnectionModeCoordinator { final class ConnectionModeCoordinator {
static let shared = ConnectionModeCoordinator() static let shared = ConnectionModeCoordinator()
private let logger = Logger(subsystem: "com.steipete.clawdis", category: "connection") private let logger = Logger(subsystem: "com.clawdis", category: "connection")
/// Apply the requested connection mode by starting/stopping local gateway, /// Apply the requested connection mode by starting/stopping local gateway,
/// managing the control-channel SSH tunnel, and cleaning up chat windows/panels. /// managing the control-channel SSH tunnel, and cleaning up chat windows/panels.

View File

@@ -1,7 +1,7 @@
import Foundation import Foundation
let launchdLabel = "com.steipete.clawdis" let launchdLabel = "com.clawdis.mac"
let gatewayLaunchdLabel = "com.steipete.clawdis.gateway" let gatewayLaunchdLabel = "com.clawdis.gateway"
let onboardingVersionKey = "clawdis.onboardingVersion" let onboardingVersionKey = "clawdis.onboardingVersion"
let currentOnboardingVersion = 7 let currentOnboardingVersion = 7
let pauseDefaultsKey = "clawdis.pauseEnabled" let pauseDefaultsKey = "clawdis.pauseEnabled"

View File

@@ -73,7 +73,7 @@ final class ControlChannel {
} }
private(set) var lastPingMs: Double? private(set) var lastPingMs: Double?
private let logger = Logger(subsystem: "com.steipete.clawdis", category: "control") private let logger = Logger(subsystem: "com.clawdis", category: "control")
private var eventTask: Task<Void, Never>? private var eventTask: Task<Void, Never>?
private var recoveryTask: Task<Void, Never>? private var recoveryTask: Task<Void, Never>?

View File

@@ -21,7 +21,7 @@ final class CronJobsStore {
var lastError: String? var lastError: String?
var statusMessage: String? var statusMessage: String?
private let logger = Logger(subsystem: "com.steipete.clawdis", category: "cron.ui") private let logger = Logger(subsystem: "com.clawdis", category: "cron.ui")
private var refreshTask: Task<Void, Never>? private var refreshTask: Task<Void, Never>?
private var runsTask: Task<Void, Never>? private var runsTask: Task<Void, Never>?
private var eventTask: Task<Void, Never>? private var eventTask: Task<Void, Never>?

View File

@@ -4,7 +4,7 @@ import Foundation
import OSLog import OSLog
import Security import Security
private let deepLinkLogger = Logger(subsystem: "com.steipete.clawdis", category: "DeepLink") private let deepLinkLogger = Logger(subsystem: "com.clawdis", category: "DeepLink")
@MainActor @MainActor
final class DeepLinkHandler { final class DeepLinkHandler {

View File

@@ -6,7 +6,7 @@ final class DockIconManager: NSObject, @unchecked Sendable {
static let shared = DockIconManager() static let shared = DockIconManager()
private var windowsObservation: NSKeyValueObservation? private var windowsObservation: NSKeyValueObservation?
private let logger = Logger(subsystem: "com.steipete.clawdis", category: "DockIconManager") private let logger = Logger(subsystem: "com.clawdis", category: "DockIconManager")
override private init() { override private init() {
super.init() super.init()

View File

@@ -58,7 +58,7 @@ struct WebSocketSessionBox: @unchecked Sendable {
private typealias ProtoAnyCodable = ClawdisProtocol.AnyCodable private typealias ProtoAnyCodable = ClawdisProtocol.AnyCodable
actor GatewayChannelActor { actor GatewayChannelActor {
private let logger = Logger(subsystem: "com.steipete.clawdis", category: "gateway") private let logger = Logger(subsystem: "com.clawdis", category: "gateway")
private var task: WebSocketTaskBox? private var task: WebSocketTaskBox?
private var pending: [String: CheckedContinuation<GatewayFrame, Error>] = [:] private var pending: [String: CheckedContinuation<GatewayFrame, Error>] = [:]
private var connected = false private var connected = false

View File

@@ -3,7 +3,7 @@ import ClawdisProtocol
import Foundation import Foundation
import OSLog import OSLog
private let gatewayConnectionLogger = Logger(subsystem: "com.steipete.clawdis", category: "gateway.connection") private let gatewayConnectionLogger = Logger(subsystem: "com.clawdis", category: "gateway.connection")
enum GatewayAgentChannel: String, Codable, CaseIterable, Sendable { enum GatewayAgentChannel: String, Codable, CaseIterable, Sendable {
case last case last

View File

@@ -34,7 +34,7 @@ final class GatewayDiscoveryModel {
private var localIdentity: LocalIdentity private var localIdentity: LocalIdentity
private var resolvedTXTByID: [String: [String: String]] = [:] private var resolvedTXTByID: [String: [String: String]] = [:]
private var pendingTXTResolvers: [String: GatewayTXTResolver] = [:] private var pendingTXTResolvers: [String: GatewayTXTResolver] = [:]
private let logger = Logger(subsystem: "com.steipete.clawdis", category: "gateway-discovery") private let logger = Logger(subsystem: "com.clawdis", category: "gateway-discovery")
init() { init() {
self.localIdentity = Self.buildLocalIdentityFast() self.localIdentity = Self.buildLocalIdentityFast()
@@ -69,7 +69,7 @@ final class GatewayDiscoveryModel {
} }
self.browsers[domain] = browser self.browsers[domain] = browser
browser.start(queue: DispatchQueue(label: "com.steipete.clawdis.macos.gateway-discovery.\(domain)")) browser.start(queue: DispatchQueue(label: "com.clawdis.macos.gateway-discovery.\(domain)"))
} }
} }

View File

@@ -72,7 +72,7 @@ actor GatewayEndpointStore {
} }
private let deps: Deps private let deps: Deps
private let logger = Logger(subsystem: "com.steipete.clawdis", category: "gateway-endpoint") private let logger = Logger(subsystem: "com.clawdis", category: "gateway-endpoint")
private var state: GatewayEndpointState private var state: GatewayEndpointState
private var subscribers: [UUID: AsyncStream<GatewayEndpointState>.Continuation] = [:] private var subscribers: [UUID: AsyncStream<GatewayEndpointState>.Continuation] = [:]

View File

@@ -62,7 +62,7 @@ struct GatewayCommandResolution {
} }
enum GatewayEnvironment { enum GatewayEnvironment {
private static let logger = Logger(subsystem: "com.steipete.clawdis", category: "gateway.env") private static let logger = Logger(subsystem: "com.clawdis", category: "gateway.env")
private static let supportedBindModes: Set<String> = ["loopback", "tailnet", "lan", "auto"] private static let supportedBindModes: Set<String> = ["loopback", "tailnet", "lan", "auto"]
static func bundledGatewayExecutable() -> String? { static func bundledGatewayExecutable() -> String? {

View File

@@ -1,14 +1,20 @@
import Foundation import Foundation
enum GatewayLaunchAgentManager { enum GatewayLaunchAgentManager {
private static let logger = Logger(subsystem: "com.steipete.clawdis", category: "gateway.launchd") private static let logger = Logger(subsystem: "com.clawdis", category: "gateway.launchd")
private static let supportedBindModes: Set<String> = ["loopback", "tailnet", "lan", "auto"] private static let supportedBindModes: Set<String> = ["loopback", "tailnet", "lan", "auto"]
private static let legacyGatewayLaunchdLabel = "com.steipete.clawdis.gateway"
private static var plistURL: URL { private static var plistURL: URL {
FileManager.default.homeDirectoryForCurrentUser FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent("Library/LaunchAgents/\(gatewayLaunchdLabel).plist") .appendingPathComponent("Library/LaunchAgents/\(gatewayLaunchdLabel).plist")
} }
private static var legacyPlistURL: URL {
FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent("Library/LaunchAgents/\(legacyGatewayLaunchdLabel).plist")
}
private static func gatewayExecutablePath(bundlePath: String) -> String { private static func gatewayExecutablePath(bundlePath: String) -> String {
"\(bundlePath)/Contents/Resources/Relay/clawdis" "\(bundlePath)/Contents/Resources/Relay/clawdis"
} }
@@ -45,6 +51,8 @@ enum GatewayLaunchAgentManager {
static func set(enabled: Bool, bundlePath: String, port: Int) async -> String? { static func set(enabled: Bool, bundlePath: String, port: Int) async -> String? {
if enabled { if enabled {
_ = await self.runLaunchctl(["bootout", "gui/\(getuid())/\(legacyGatewayLaunchdLabel)"])
try? FileManager.default.removeItem(at: self.legacyPlistURL)
let gatewayBin = self.gatewayExecutablePath(bundlePath: bundlePath) let gatewayBin = self.gatewayExecutablePath(bundlePath: bundlePath)
guard FileManager.default.isExecutableFile(atPath: gatewayBin) else { guard FileManager.default.isExecutableFile(atPath: gatewayBin) else {
self.logger.error("launchd enable failed: gateway missing at \(gatewayBin)") self.logger.error("launchd enable failed: gateway missing at \(gatewayBin)")

View File

@@ -42,7 +42,7 @@ final class GatewayProcessManager {
private var environmentRefreshTask: Task<Void, Never>? private var environmentRefreshTask: Task<Void, Never>?
private var lastEnvironmentRefresh: Date? private var lastEnvironmentRefresh: Date?
private var logRefreshTask: Task<Void, Never>? private var logRefreshTask: Task<Void, Never>?
private let logger = Logger(subsystem: "com.steipete.clawdis", category: "gateway.process") private let logger = Logger(subsystem: "com.clawdis", category: "gateway.process")
private let logLimit = 20000 // characters to keep in-memory private let logLimit = 20000 // characters to keep in-memory
private let environmentRefreshMinInterval: TimeInterval = 30 private let environmentRefreshMinInterval: TimeInterval = 30

View File

@@ -77,7 +77,7 @@ enum HealthState: Equatable {
final class HealthStore { final class HealthStore {
static let shared = HealthStore() static let shared = HealthStore()
private static let logger = Logger(subsystem: "com.steipete.clawdis", category: "health") private static let logger = Logger(subsystem: "com.clawdis", category: "health")
private(set) var snapshot: HealthSnapshot? private(set) var snapshot: HealthSnapshot?
private(set) var lastSuccess: Date? private(set) var lastSuccess: Date?

View File

@@ -2,7 +2,7 @@ import Darwin
import Foundation import Foundation
enum InstanceIdentity { enum InstanceIdentity {
private static let suiteName = "com.steipete.clawdis.shared" private static let suiteName = "com.clawdis.shared"
private static let instanceIdKey = "instanceId" private static let instanceIdKey = "instanceId"
private static var defaults: UserDefaults { private static var defaults: UserDefaults {

View File

@@ -40,7 +40,7 @@ final class InstancesStore {
var statusMessage: String? var statusMessage: String?
var isLoading = false var isLoading = false
private let logger = Logger(subsystem: "com.steipete.clawdis", category: "instances") private let logger = Logger(subsystem: "com.clawdis", category: "instances")
private var task: Task<Void, Never>? private var task: Task<Void, Never>?
private let interval: TimeInterval = 30 private let interval: TimeInterval = 30
private var eventTask: Task<Void, Never>? private var eventTask: Task<Void, Never>?

View File

@@ -1,9 +1,14 @@
import Foundation import Foundation
enum LaunchAgentManager { enum LaunchAgentManager {
private static let legacyLaunchdLabel = "com.steipete.clawdis"
private static var plistURL: URL { private static var plistURL: URL {
FileManager.default.homeDirectoryForCurrentUser FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent("Library/LaunchAgents/com.steipete.clawdis.plist") .appendingPathComponent("Library/LaunchAgents/com.clawdis.mac.plist")
}
private static var legacyPlistURL: URL {
FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent("Library/LaunchAgents/\(legacyLaunchdLabel).plist")
} }
static func status() async -> Bool { static func status() async -> Bool {
@@ -14,6 +19,8 @@ enum LaunchAgentManager {
static func set(enabled: Bool, bundlePath: String) async { static func set(enabled: Bool, bundlePath: String) async {
if enabled { if enabled {
_ = await self.runLaunchctl(["bootout", "gui/\(getuid())/\(legacyLaunchdLabel)"])
try? FileManager.default.removeItem(at: self.legacyPlistURL)
self.writePlist(bundlePath: bundlePath) self.writePlist(bundlePath: bundlePath)
_ = await self.runLaunchctl(["bootout", "gui/\(getuid())/\(launchdLabel)"]) _ = await self.runLaunchctl(["bootout", "gui/\(getuid())/\(launchdLabel)"])
_ = await self.runLaunchctl(["bootstrap", "gui/\(getuid())", self.plistURL.path]) _ = await self.runLaunchctl(["bootstrap", "gui/\(getuid())", self.plistURL.path])
@@ -32,7 +39,7 @@ enum LaunchAgentManager {
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>Label</key> <key>Label</key>
<string>com.steipete.clawdis</string> <string>com.clawdis.mac</string>
<key>ProgramArguments</key> <key>ProgramArguments</key>
<array> <array>
<string>\(bundlePath)/Contents/MacOS/Clawdis</string> <string>\(bundlePath)/Contents/MacOS/Clawdis</string>

View File

@@ -74,7 +74,7 @@ enum ClawdisLogging {
static func parseLabel(_ label: String) -> (String, String) { static func parseLabel(_ label: String) -> (String, String) {
guard let range = label.range(of: Self.labelSeparator) else { guard let range = label.range(of: Self.labelSeparator) else {
return ("com.steipete.clawdis", label) return ("com.clawdis", label)
} }
let subsystem = String(label[..<range.lowerBound]) let subsystem = String(label[..<range.lowerBound])
let category = String(label[range.upperBound...]) let category = String(label[range.upperBound...])

Some files were not shown because too many files have changed in this diff Show More