From 286d0fdb48d7165293c8eee1fa214726b50dcbde Mon Sep 17 00:00:00 2001 From: kumarabhirup Date: Wed, 4 Mar 2026 16:34:45 -0800 Subject: [PATCH] delete em all --- .agent/workflows/update_clawdbot.md | 380 - .agents/maintainers.md | 1 - .detect-secrets.cfg | 30 - .dockerignore | 60 - .env.example | 80 - .gitattributes | 1 - .github/FUNDING.yml | 1 - .github/ISSUE_TEMPLATE/bug_report.yml | 95 - .github/ISSUE_TEMPLATE/config.yml | 8 - .github/ISSUE_TEMPLATE/feature_request.yml | 70 - .github/actionlint.yaml | 22 - .../actions/detect-docs-changes/action.yml | 53 - .github/actions/setup-node-env/action.yml | 98 - .../actions/setup-pnpm-store-cache/action.yml | 47 - .github/dependabot.yml | 65 - .github/instructions/copilot.instructions.md | 64 - .github/labeler.yml | 258 - .github/pull_request_template.md | 108 - .github/workflows/ci.yml | 65 - .github/workflows/workflow-sanity.yml | 67 - .gitignore | 3 + .markdownlint-cli2.jsonc | 52 - .pi/extensions/diff.ts | 195 - .pi/extensions/files.ts | 194 - .pi/extensions/prompt-url-widget.ts | 193 - .pi/extensions/redraws.ts | 26 - .pi/git/.gitignore | 2 - .pi/prompts/cl.md | 58 - .pi/prompts/is.md | 22 - .pi/prompts/landpr.md | 73 - .pi/prompts/reviewpr.md | 105 - .pre-commit-config.yaml | 105 - .secrets.baseline | 13104 -------------- .shellcheckrc | 25 - .swiftformat | 51 - .swiftlint.yml | 148 - .vscode/extensions.json | 3 - .vscode/settings.json | 22 - AGENTS.md | 240 - CHANGELOG.md | 2585 --- CLAUDE.md | 1 - CONTRIBUTING.md | 147 - Dockerfile | 65 - Dockerfile.sandbox | 20 - Dockerfile.sandbox-browser | 32 - Dockerfile.sandbox-common | 45 - README.md | 2 +- SECURITY.md | 137 - Swabble/.github/workflows/ci.yml | 54 - Swabble/.gitignore | 33 - Swabble/.swiftformat | 8 - Swabble/.swiftlint.yml | 43 - Swabble/CHANGELOG.md | 11 - Swabble/LICENSE | 21 - Swabble/Package.resolved | 69 - Swabble/Package.swift | 55 - Swabble/README.md | 111 - .../Sources/SwabbleCore/Config/Config.swift | 77 - .../SwabbleCore/Hooks/HookExecutor.swift | 75 - .../SwabbleCore/Speech/BufferConverter.swift | 50 - .../SwabbleCore/Speech/SpeechPipeline.swift | 114 - .../Support/AttributedString+Sentences.swift | 62 - .../Sources/SwabbleCore/Support/Logging.swift | 41 - .../SwabbleCore/Support/OutputFormat.swift | 45 - .../Support/TranscriptsStore.swift | 45 - Swabble/Sources/SwabbleKit/WakeWordGate.swift | 197 - Swabble/Sources/swabble/CLI/CLIRegistry.swift | 71 - .../swabble/Commands/DoctorCommand.swift | 37 - .../swabble/Commands/HealthCommand.swift | 16 - .../swabble/Commands/MicCommands.swift | 62 - .../swabble/Commands/ServeCommand.swift | 81 - .../swabble/Commands/ServiceCommands.swift | 77 - .../swabble/Commands/SetupCommand.swift | 26 - .../swabble/Commands/StartStopCommands.swift | 35 - .../swabble/Commands/StatusCommand.swift | 34 - .../swabble/Commands/TailLogCommand.swift | 20 - .../swabble/Commands/TestHookCommand.swift | 30 - .../swabble/Commands/TranscribeCommand.swift | 61 - Swabble/Sources/swabble/main.swift | 151 - .../SwabbleKitTests/WakeWordGateTests.swift | 63 - Swabble/Tests/swabbleTests/ConfigTests.swift | 23 - Swabble/docs/spec.md | 33 - Swabble/scripts/format.sh | 5 - Swabble/scripts/lint.sh | 9 - VISION.md | 110 - appcast.xml | 363 - apps/android/.gitignore | 5 - apps/android/README.md | 51 - apps/android/app/build.gradle.kts | 150 - apps/android/app/proguard-rules.pro | 28 - apps/android/app/src/main/AndroidManifest.xml | 64 - .../ai/openclaw/android/CameraHudState.kt | 14 - .../java/ai/openclaw/android/DeviceNames.kt | 26 - .../openclaw/android/InstallResultReceiver.kt | 33 - .../java/ai/openclaw/android/LocationMode.kt | 15 - .../java/ai/openclaw/android/MainActivity.kt | 130 - .../java/ai/openclaw/android/MainViewModel.kt | 188 - .../main/java/ai/openclaw/android/NodeApp.kt | 37 - .../openclaw/android/NodeForegroundService.kt | 180 - .../java/ai/openclaw/android/NodeRuntime.kt | 753 - .../openclaw/android/PermissionRequester.kt | 133 - .../android/ScreenCaptureRequester.kt | 65 - .../java/ai/openclaw/android/SecurePrefs.kt | 285 - .../java/ai/openclaw/android/SessionKey.kt | 13 - .../java/ai/openclaw/android/VoiceWakeMode.kt | 14 - .../java/ai/openclaw/android/WakeWords.kt | 21 - .../openclaw/android/chat/ChatController.kt | 524 - .../ai/openclaw/android/chat/ChatModels.kt | 44 - .../android/gateway/BonjourEscapes.kt | 35 - .../android/gateway/DeviceAuthStore.kt | 26 - .../android/gateway/DeviceIdentityStore.kt | 182 - .../android/gateway/GatewayDiscovery.kt | 521 - .../android/gateway/GatewayEndpoint.kt | 26 - .../android/gateway/GatewayProtocol.kt | 3 - .../android/gateway/GatewaySession.kt | 704 - .../ai/openclaw/android/gateway/GatewayTls.kt | 159 - .../ai/openclaw/android/node/A2UIHandler.kt | 146 - .../openclaw/android/node/AppUpdateHandler.kt | 295 - .../android/node/CameraCaptureManager.kt | 364 - .../ai/openclaw/android/node/CameraHandler.kt | 157 - .../openclaw/android/node/CanvasController.kt | 264 - .../android/node/ConnectionManager.kt | 188 - .../ai/openclaw/android/node/DebugHandler.kt | 117 - .../android/node/GatewayEventHandler.kt | 71 - .../openclaw/android/node/InvokeDispatcher.kt | 176 - .../openclaw/android/node/JpegSizeLimiter.kt | 61 - .../android/node/LocationCaptureManager.kt | 117 - .../openclaw/android/node/LocationHandler.kt | 116 - .../ai/openclaw/android/node/NodeUtils.kt | 57 - .../ai/openclaw/android/node/ScreenHandler.kt | 25 - .../android/node/ScreenRecordManager.kt | 199 - .../ai/openclaw/android/node/SmsHandler.kt | 19 - .../ai/openclaw/android/node/SmsManager.kt | 230 - .../protocol/OpenClawCanvasA2UIAction.kt | 66 - .../protocol/OpenClawProtocolConstants.kt | 71 - .../ai/openclaw/android/tools/ToolDisplay.kt | 222 - .../openclaw/android/ui/CameraHudOverlay.kt | 44 - .../java/ai/openclaw/android/ui/ChatSheet.kt | 10 - .../ai/openclaw/android/ui/OpenClawTheme.kt | 32 - .../java/ai/openclaw/android/ui/RootScreen.kt | 429 - .../ai/openclaw/android/ui/SettingsSheet.kt | 723 - .../java/ai/openclaw/android/ui/StatusPill.kt | 114 - .../ai/openclaw/android/ui/TalkOrbOverlay.kt | 134 - .../openclaw/android/ui/chat/ChatComposer.kt | 285 - .../openclaw/android/ui/chat/ChatMarkdown.kt | 215 - .../android/ui/chat/ChatMessageListCard.kt | 110 - .../android/ui/chat/ChatMessageViews.kt | 263 - .../android/ui/chat/ChatSessionsDialog.kt | 92 - .../android/ui/chat/ChatSheetContent.kt | 147 - .../android/ui/chat/SessionFilters.kt | 73 - .../android/voice/StreamingMediaDataSource.kt | 98 - .../android/voice/TalkDirectiveParser.kt | 191 - .../openclaw/android/voice/TalkModeManager.kt | 1257 -- .../voice/VoiceWakeCommandExtractor.kt | 40 - .../android/voice/VoiceWakeManager.kt | 173 - .../main/res/mipmap-anydpi/ic_launcher.xml | 6 - .../res/mipmap-anydpi/ic_launcher_round.xml | 6 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 10928 -> 0 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 44702 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 5655 -> 0 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 21883 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 17855 -> 0 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 75167 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 36404 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 158927 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 60935 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 276047 -> 0 bytes .../app/src/main/res/values/colors.xml | 3 - .../app/src/main/res/values/strings.xml | 3 - .../app/src/main/res/values/themes.xml | 7 - .../app/src/main/res/xml/backup_rules.xml | 4 - .../main/res/xml/data_extraction_rules.xml | 9 - .../app/src/main/res/xml/file_paths.xml | 4 - .../main/res/xml/network_security_config.xml | 12 - .../android/NodeForegroundServiceTest.kt | 43 - .../java/ai/openclaw/android/WakeWordsTest.kt | 50 - .../android/gateway/BonjourEscapesTest.kt | 19 - .../android/node/AppUpdateHandlerTest.kt | 65 - .../CanvasControllerSnapshotParamsTest.kt | 43 - .../android/node/ConnectionManagerTest.kt | 76 - .../android/node/JpegSizeLimiterTest.kt | 47 - .../openclaw/android/node/SmsManagerTest.kt | 91 - .../protocol/OpenClawCanvasA2UIActionTest.kt | 49 - .../protocol/OpenClawProtocolConstantsTest.kt | 35 - .../android/ui/chat/SessionFiltersTest.kt | 35 - .../android/voice/TalkDirectiveParserTest.kt | 55 - .../voice/VoiceWakeCommandExtractorTest.kt | 25 - apps/android/build.gradle.kts | 6 - apps/android/gradle.properties | 5 - .../android/gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 - apps/android/gradlew | 249 - apps/android/gradlew.bat | 92 - apps/android/settings.gradle.kts | 18 - apps/ios/.swiftlint.yml | 9 - apps/ios/Config/Signing.xcconfig | 18 - apps/ios/LocalSigning.xcconfig.example | 14 - apps/ios/README.md | 141 - apps/ios/ShareExtension/Info.plist | 45 - .../ShareExtension/ShareViewController.swift | 548 - apps/ios/Signing.xcconfig | 17 - .../AppIcon.appiconset/100.png | Bin 9725 -> 0 bytes .../AppIcon.appiconset/102.png | Bin 9525 -> 0 bytes .../AppIcon.appiconset/1024.png | Bin 348539 -> 0 bytes .../AppIcon.appiconset/108.png | Bin 10564 -> 0 bytes .../AppIcon.appiconset/114.png | Bin 11312 -> 0 bytes .../AppIcon.appiconset/120.png | Bin 11620 -> 0 bytes .../AppIcon.appiconset/172.png | Bin 20674 -> 0 bytes .../AppIcon.appiconset/180.png | Bin 22378 -> 0 bytes .../AppIcon.appiconset/196.png | Bin 25563 -> 0 bytes .../AppIcon.appiconset/216.png | Bin 29020 -> 0 bytes .../AppIcon.appiconset/234.png | Bin 33325 -> 0 bytes .../AppIcon.appiconset/258.png | Bin 39552 -> 0 bytes .../Assets.xcassets/AppIcon.appiconset/29.png | Bin 2357 -> 0 bytes .../Assets.xcassets/AppIcon.appiconset/40.png | Bin 2865 -> 0 bytes .../Assets.xcassets/AppIcon.appiconset/48.png | Bin 3729 -> 0 bytes .../Assets.xcassets/AppIcon.appiconset/55.png | Bin 4137 -> 0 bytes .../Assets.xcassets/AppIcon.appiconset/57.png | Bin 4498 -> 0 bytes .../Assets.xcassets/AppIcon.appiconset/58.png | Bin 4727 -> 0 bytes .../Assets.xcassets/AppIcon.appiconset/60.png | Bin 4750 -> 0 bytes .../Assets.xcassets/AppIcon.appiconset/66.png | Bin 5512 -> 0 bytes .../Assets.xcassets/AppIcon.appiconset/80.png | Bin 6923 -> 0 bytes .../Assets.xcassets/AppIcon.appiconset/87.png | Bin 7963 -> 0 bytes .../Assets.xcassets/AppIcon.appiconset/88.png | Bin 7800 -> 0 bytes .../Assets.xcassets/AppIcon.appiconset/92.png | Bin 8539 -> 0 bytes .../AppIcon.appiconset/Contents.json | 1 - .../Sources/Calendar/CalendarService.swift | 135 - .../ios/Sources/Camera/CameraController.swift | 402 - .../Capabilities/NodeCapabilityRouter.swift | 25 - apps/ios/Sources/Chat/ChatSheet.swift | 47 - .../Chat/IOSGatewayChatTransport.swift | 137 - .../Sources/Contacts/ContactsService.swift | 212 - .../Sources/Device/DeviceStatusService.swift | 87 - .../Sources/Device/NetworkStatusService.swift | 69 - apps/ios/Sources/Device/NodeDisplayName.swift | 48 - .../EventKit/EventKitAuthorization.swift | 34 - .../Gateway/GatewayConnectConfig.swift | 27 - .../Gateway/GatewayConnectionController.swift | 1093 -- .../Gateway/GatewayConnectionIssue.swift | 71 - .../GatewayDiscoveryDebugLogView.swift | 68 - .../Gateway/GatewayDiscoveryModel.swift | 190 - .../Gateway/GatewayHealthMonitor.swift | 85 - .../Gateway/GatewayQuickSetupSheet.swift | 113 - .../Gateway/GatewayServiceResolver.swift | 55 - .../Gateway/GatewaySettingsStore.swift | 438 - .../Sources/Gateway/GatewaySetupCode.swift | 42 - .../Gateway/GatewayTrustPromptAlert.swift | 41 - apps/ios/Sources/Gateway/KeychainStore.swift | 48 - apps/ios/Sources/Gateway/TCPProbe.swift | 43 - apps/ios/Sources/Info.plist | 88 - .../Sources/Location/LocationService.swift | 202 - .../Location/SignificantLocationMonitor.swift | 42 - .../Sources/Media/PhotoLibraryService.swift | 164 - .../Sources/Model/NodeAppModel+Canvas.swift | 70 - apps/ios/Sources/Model/NodeAppModel.swift | 2611 --- apps/ios/Sources/Motion/MotionService.swift | 100 - .../Onboarding/GatewayOnboardingView.swift | 354 - .../Onboarding/OnboardingStateStore.swift | 52 - .../Onboarding/OnboardingWizardView.swift | 890 - .../Sources/Onboarding/QRScannerView.swift | 96 - apps/ios/Sources/OpenClaw.entitlements | 9 - apps/ios/Sources/OpenClawApp.swift | 499 - .../Sources/Reminders/RemindersService.swift | 133 - apps/ios/Sources/RootCanvas.swift | 505 - apps/ios/Sources/RootTabs.swift | 114 - apps/ios/Sources/RootView.swift | 7 - .../ios/Sources/Screen/ScreenController.swift | 373 - .../Sources/Screen/ScreenRecordService.swift | 360 - apps/ios/Sources/Screen/ScreenTab.swift | 27 - apps/ios/Sources/Screen/ScreenWebView.swift | 193 - .../Services/NodeServiceProtocols.swift | 103 - .../Services/NotificationService.swift | 58 - .../Services/WatchMessagingService.swift | 280 - apps/ios/Sources/SessionKey.swift | 23 - .../Settings/SettingsNetworkingHelpers.swift | 40 - apps/ios/Sources/Settings/SettingsTab.swift | 1042 -- .../Settings/VoiceWakeWordsSettingsView.swift | 98 - .../Status/StatusActivityBuilder.swift | 71 - apps/ios/Sources/Status/StatusPill.swift | 136 - apps/ios/Sources/Status/VoiceWakeToast.swift | 38 - apps/ios/Sources/Voice/TalkModeManager.swift | 2089 --- apps/ios/Sources/Voice/TalkOrbOverlay.swift | 87 - apps/ios/Sources/Voice/VoiceTab.swift | 46 - apps/ios/Sources/Voice/VoiceWakeManager.swift | 495 - .../Sources/Voice/VoiceWakePreferences.swift | 44 - apps/ios/SwiftSources.input.xcfilelist | 61 - apps/ios/Tests/AppCoverageTests.swift | 31 - .../Tests/CameraControllerClampTests.swift | 24 - .../Tests/CameraControllerErrorTests.swift | 14 - apps/ios/Tests/DeepLinkParserTests.swift | 181 - .../GatewayConnectionControllerTests.swift | 122 - .../Tests/GatewayConnectionIssueTests.swift | 33 - .../GatewayConnectionSecurityTests.swift | 131 - .../Tests/GatewayDiscoveryModelTests.swift | 22 - apps/ios/Tests/GatewayEndpointIDTests.swift | 33 - .../ios/Tests/GatewaySettingsStoreTests.swift | 199 - .../Tests/IOSGatewayChatTransportTests.swift | 30 - apps/ios/Tests/Info.plist | 24 - apps/ios/Tests/KeychainStoreTests.swift | 22 - apps/ios/Tests/NodeAppModelInvokeTests.swift | 351 - .../ios/Tests/OnboardingStateStoreTests.swift | 57 - apps/ios/Tests/ScreenControllerTests.swift | 87 - apps/ios/Tests/ScreenRecordServiceTests.swift | 32 - .../SettingsNetworkingHelpersTests.swift | 50 - .../ios/Tests/ShareToAgentDeepLinkTests.swift | 51 - apps/ios/Tests/SwiftUIRenderSmokeTests.swift | 81 - .../ios/Tests/VoiceWakeGatewaySyncTests.swift | 22 - .../VoiceWakeManagerExtractCommandTests.swift | 90 - .../Tests/VoiceWakeManagerStateTests.swift | 65 - .../ios/Tests/VoiceWakePreferencesTests.swift | 38 - .../AppIcon.appiconset/Contents.json | 116 - .../AppIcon.appiconset/watch-app-38@2x.png | Bin 7845 -> 0 bytes .../AppIcon.appiconset/watch-app-40@2x.png | Bin 8759 -> 0 bytes .../AppIcon.appiconset/watch-app-41@2x.png | Bin 9281 -> 0 bytes .../AppIcon.appiconset/watch-app-44@2x.png | Bin 10297 -> 0 bytes .../AppIcon.appiconset/watch-app-45@2x.png | Bin 10544 -> 0 bytes .../watch-companion-29@2x.png | Bin 5032 -> 0 bytes .../watch-companion-29@3x.png | Bin 8650 -> 0 bytes .../watch-marketing-1024.png | Bin 206341 -> 0 bytes .../watch-notification-38@2x.png | Bin 3893 -> 0 bytes .../watch-notification-42@2x.png | Bin 4673 -> 0 bytes .../watch-quicklook-38@2x.png | Bin 19776 -> 0 bytes .../watch-quicklook-42@2x.png | Bin 23404 -> 0 bytes .../watch-quicklook-44@2x.png | Bin 26236 -> 0 bytes .../watch-quicklook-45@2x.png | Bin 28860 -> 0 bytes .../WatchApp/Assets.xcassets/Contents.json | 6 - apps/ios/WatchApp/Info.plist | 28 - apps/ios/WatchExtension/Info.plist | 32 - .../Sources/OpenClawWatchApp.swift | 28 - .../Sources/WatchConnectivityReceiver.swift | 236 - .../Sources/WatchInboxStore.swift | 230 - .../Sources/WatchInboxView.swift | 64 - apps/ios/fastlane/.env.example | 21 - apps/ios/fastlane/Appfile | 7 - apps/ios/fastlane/Fastfile | 104 - apps/ios/fastlane/SETUP.md | 32 - apps/ios/project.yml | 232 - apps/macos/Icon.icon/Assets/openclaw-mac.png | Bin 1393705 -> 0 bytes apps/macos/Icon.icon/icon.json | 36 - apps/macos/Package.resolved | 132 - apps/macos/Package.swift | 92 - apps/macos/README.md | 64 - .../Sources/OpenClaw/AboutSettings.swift | 199 - .../Sources/OpenClaw/AgeFormatting.swift | 17 - .../Sources/OpenClaw/AgentEventStore.swift | 22 - .../Sources/OpenClaw/AgentEventsWindow.swift | 109 - .../Sources/OpenClaw/AgentWorkspace.swift | 340 - .../OpenClaw/AnthropicAuthControls.swift | 234 - .../Sources/OpenClaw/AnthropicOAuth.swift | 383 - .../OpenClaw/AnthropicOAuthCodeState.swift | 59 - .../Sources/OpenClaw/AnyCodable+Helpers.swift | 43 - apps/macos/Sources/OpenClaw/AppState.swift | 720 - .../OpenClaw/AudioInputDeviceObserver.swift | 216 - .../Sources/OpenClaw/CLIInstallPrompter.swift | 84 - .../macos/Sources/OpenClaw/CLIInstaller.swift | 103 - .../OpenClaw/CameraCaptureService.swift | 427 - .../CanvasA2UIActionMessageHandler.swift | 149 - .../OpenClaw/CanvasChromeContainerView.swift | 235 - .../Sources/OpenClaw/CanvasFileWatcher.swift | 24 - .../Sources/OpenClaw/CanvasManager.swift | 342 - .../macos/Sources/OpenClaw/CanvasScheme.swift | 42 - .../OpenClaw/CanvasSchemeHandler.swift | 259 - .../macos/Sources/OpenClaw/CanvasWindow.swift | 31 - .../CanvasWindowController+Helpers.swift | 43 - .../CanvasWindowController+Navigation.swift | 64 - .../CanvasWindowController+Testing.swift | 39 - .../CanvasWindowController+Window.swift | 166 - .../OpenClaw/CanvasWindowController.swift | 373 - .../Sources/OpenClaw/ChannelConfigForm.swift | 363 - .../ChannelsSettings+ChannelSections.swift | 137 - .../ChannelsSettings+ChannelState.swift | 508 - .../OpenClaw/ChannelsSettings+Helpers.swift | 17 - .../OpenClaw/ChannelsSettings+View.swift | 167 - .../Sources/OpenClaw/ChannelsSettings.swift | 19 - .../OpenClaw/ChannelsStore+Config.swift | 154 - .../OpenClaw/ChannelsStore+Lifecycle.swift | 163 - .../Sources/OpenClaw/ChannelsStore.swift | 296 - .../OpenClaw/CoalescingFSEventsWatcher.swift | 110 - .../Sources/OpenClaw/CommandResolver.swift | 574 - .../Sources/OpenClaw/ConfigFileWatcher.swift | 45 - .../OpenClaw/ConfigSchemaSupport.swift | 219 - .../Sources/OpenClaw/ConfigSettings.swift | 395 - apps/macos/Sources/OpenClaw/ConfigStore.swift | 117 - .../OpenClaw/ConnectionModeCoordinator.swift | 79 - .../OpenClaw/ConnectionModeResolver.swift | 49 - apps/macos/Sources/OpenClaw/Constants.swift | 48 - .../OpenClaw/ContextMenuCardView.swift | 120 - .../Sources/OpenClaw/ContextUsageBar.swift | 93 - .../Sources/OpenClaw/ControlChannel.swift | 428 - .../Sources/OpenClaw/CostUsageMenuView.swift | 99 - .../OpenClaw/CritterIconRenderer.swift | 387 - .../CritterStatusLabel+Behavior.swift | 305 - .../Sources/OpenClaw/CritterStatusLabel.swift | 23 - .../OpenClaw/CronJobEditor+Helpers.swift | 271 - .../OpenClaw/CronJobEditor+Testing.swift | 28 - .../Sources/OpenClaw/CronJobEditor.swift | 362 - .../Sources/OpenClaw/CronJobsStore.swift | 200 - apps/macos/Sources/OpenClaw/CronModels.swift | 271 - .../OpenClaw/CronSettings+Actions.swift | 23 - .../OpenClaw/CronSettings+Helpers.swift | 56 - .../OpenClaw/CronSettings+Layout.swift | 179 - .../Sources/OpenClaw/CronSettings+Rows.swift | 246 - .../OpenClaw/CronSettings+Testing.swift | 121 - .../macos/Sources/OpenClaw/CronSettings.swift | 17 - .../macos/Sources/OpenClaw/DebugActions.swift | 265 - .../Sources/OpenClaw/DebugSettings.swift | 1026 -- apps/macos/Sources/OpenClaw/DeepLinks.swift | 199 - .../Sources/OpenClaw/DeviceModelCatalog.swift | 188 - .../DevicePairingApprovalPrompter.swift | 307 - .../Sources/OpenClaw/DiagnosticsFileLog.swift | 133 - .../Sources/OpenClaw/DockIconManager.swift | 116 - .../OpenClaw/ExecAllowlistMatcher.swift | 79 - .../OpenClaw/ExecApprovalEvaluation.swift | 67 - .../Sources/OpenClaw/ExecApprovals.swift | 794 - .../ExecApprovalsGatewayPrompter.swift | 123 - .../OpenClaw/ExecApprovalsSocket.swift | 780 - .../OpenClaw/ExecCommandResolution.swift | 305 - .../OpenClaw/FileHandle+SafeRead.swift | 28 - .../OpenClaw/GatewayAutostartPolicy.swift | 14 - .../Sources/OpenClaw/GatewayConnection.swift | 742 - .../GatewayConnectivityCoordinator.swift | 63 - .../OpenClaw/GatewayDiscoveryHelpers.swift | 77 - .../OpenClaw/GatewayDiscoveryMenu.swift | 139 - .../GatewayDiscoveryPreferences.swift | 25 - .../OpenClaw/GatewayEndpointStore.swift | 728 - .../Sources/OpenClaw/GatewayEnvironment.swift | 344 - .../OpenClaw/GatewayLaunchAgentManager.swift | 204 - .../OpenClaw/GatewayProcessManager.swift | 432 - .../OpenClaw/GatewayRemoteConfig.swift | 102 - .../Sources/OpenClaw/GeneralSettings.swift | 743 - apps/macos/Sources/OpenClaw/HealthStore.swift | 301 - .../Sources/OpenClaw/HeartbeatStore.swift | 39 - .../Sources/OpenClaw/HostEnvSanitizer.swift | 57 - apps/macos/Sources/OpenClaw/HoverHUD.swift | 311 - apps/macos/Sources/OpenClaw/IconState.swift | 113 - .../Sources/OpenClaw/InstancesSettings.swift | 479 - .../Sources/OpenClaw/InstancesStore.swift | 349 - .../Sources/OpenClaw/LaunchAgentManager.swift | 78 - apps/macos/Sources/OpenClaw/Launchctl.swift | 87 - .../Sources/OpenClaw/LaunchdManager.swift | 20 - apps/macos/Sources/OpenClaw/LogLocator.swift | 59 - .../OpenClaw/Logging/OpenClawLogging.swift | 232 - apps/macos/Sources/OpenClaw/MenuBar.swift | 474 - .../Sources/OpenClaw/MenuContentView.swift | 596 - .../OpenClaw/MenuContextCardInjector.swift | 228 - .../OpenClaw/MenuHighlightedHostView.swift | 104 - .../Sources/OpenClaw/MenuHostedItem.swift | 29 - .../OpenClaw/MenuSessionsHeaderView.swift | 44 - .../OpenClaw/MenuSessionsInjector.swift | 1233 -- .../OpenClaw/MenuUsageHeaderView.swift | 35 - .../Sources/OpenClaw/MicLevelMonitor.swift | 96 - .../Sources/OpenClaw/ModelCatalogLoader.swift | 159 - .../NSAttributedString+VoiceWake.swift | 9 - .../NodeMode/MacNodeLocationService.swift | 139 - .../NodeMode/MacNodeModeCoordinator.swift | 171 - .../OpenClaw/NodeMode/MacNodeRuntime.swift | 1002 -- .../MacNodeRuntimeMainActorServices.swift | 60 - .../NodeMode/MacNodeScreenCommands.swift | 13 - .../NodePairingApprovalPrompter.swift | 682 - .../Sources/OpenClaw/NodeServiceManager.swift | 150 - apps/macos/Sources/OpenClaw/NodesMenu.swift | 333 - apps/macos/Sources/OpenClaw/NodesStore.swift | 110 - .../OpenClaw/NotificationManager.swift | 66 - .../Sources/OpenClaw/NotifyOverlay.swift | 192 - apps/macos/Sources/OpenClaw/Onboarding.swift | 196 - .../OpenClaw/OnboardingView+Actions.swift | 147 - .../OpenClaw/OnboardingView+Chat.swift | 26 - .../OpenClaw/OnboardingView+Layout.swift | 234 - .../OpenClaw/OnboardingView+Monitoring.swift | 178 - .../OpenClaw/OnboardingView+Pages.swift | 847 - .../OpenClaw/OnboardingView+Testing.swift | 87 - .../OpenClaw/OnboardingView+Wizard.swift | 94 - .../OpenClaw/OnboardingView+Workspace.swift | 116 - .../Sources/OpenClaw/OnboardingWidgets.swift | 65 - .../Sources/OpenClaw/OnboardingWizard.swift | 419 - .../Sources/OpenClaw/OpenClawConfigFile.swift | 373 - .../Sources/OpenClaw/OpenClawPaths.swift | 53 - .../OpenClaw/PairingAlertSupport.swift | 46 - .../PeekabooBridgeHostCoordinator.swift | 137 - .../Sources/OpenClaw/PermissionManager.swift | 506 - .../OpenClaw/PermissionsSettings.swift | 229 - .../Sources/OpenClaw/PointingHandCursor.swift | 30 - .../macos/Sources/OpenClaw/PortGuardian.swift | 422 - .../Sources/OpenClaw/PresenceReporter.swift | 114 - .../Sources/OpenClaw/Process+PipeRead.swift | 11 - .../OpenClaw/ProcessInfo+OpenClaw.swift | 48 - .../Sources/OpenClaw/RemotePortTunnel.swift | 317 - .../OpenClaw/RemoteTunnelManager.swift | 122 - .../LICENSE.apple-device-identifiers.txt | 21 - .../OpenClaw/Resources/DeviceModels/NOTICE.md | 9 - .../DeviceModels/ios-device-identifiers.json | 176 - .../DeviceModels/mac-device-identifiers.json | 214 - .../Sources/OpenClaw/Resources/Info.plist | 79 - .../Sources/OpenClaw/Resources/OpenClaw.icns | Bin 1884490 -> 0 bytes .../Sources/OpenClaw/RuntimeLocator.swift | 171 - .../OpenClaw/ScreenRecordService.swift | 266 - .../Sources/OpenClaw/ScreenshotSize.swift | 17 - .../Sources/OpenClaw/SessionActions.swift | 91 - apps/macos/Sources/OpenClaw/SessionData.swift | 346 - .../OpenClaw/SessionMenuLabelView.swift | 58 - .../OpenClaw/SessionMenuPreviewView.swift | 495 - .../Sources/OpenClaw/SessionsSettings.swift | 212 - .../Sources/OpenClaw/SettingsComponents.swift | 24 - .../Sources/OpenClaw/SettingsRootView.swift | 243 - .../OpenClaw/SettingsWindowOpener.swift | 36 - .../Sources/OpenClaw/ShellExecutor.swift | 101 - .../macos/Sources/OpenClaw/SkillsModels.swift | 74 - .../Sources/OpenClaw/SkillsSettings.swift | 621 - .../macos/Sources/OpenClaw/SoundEffects.swift | 109 - apps/macos/Sources/OpenClaw/StatusPill.swift | 16 - .../Sources/OpenClaw/String+NonEmpty.swift | 8 - .../Sources/OpenClaw/SystemPresenceInfo.swift | 16 - .../OpenClaw/SystemRunSettingsView.swift | 449 - .../TailscaleIntegrationSection.swift | 401 - .../Sources/OpenClaw/TailscaleService.swift | 182 - .../Sources/OpenClaw/TalkAudioPlayer.swift | 158 - .../Sources/OpenClaw/TalkModeController.swift | 69 - .../Sources/OpenClaw/TalkModeRuntime.swift | 953 -- .../Sources/OpenClaw/TalkModeTypes.swift | 8 - apps/macos/Sources/OpenClaw/TalkOverlay.swift | 146 - .../Sources/OpenClaw/TalkOverlayView.swift | 225 - .../OpenClaw/TerminationSignalWatcher.swift | 53 - .../Sources/OpenClaw/UsageCostData.swift | 60 - apps/macos/Sources/OpenClaw/UsageData.swift | 103 - .../Sources/OpenClaw/UsageMenuLabelView.swift | 59 - .../OpenClaw/UserDefaultsMigration.swift | 16 - apps/macos/Sources/OpenClaw/ViewMetrics.swift | 29 - .../Sources/OpenClaw/VisualEffectView.swift | 37 - .../Sources/OpenClaw/VoicePushToTalk.swift | 421 - .../OpenClaw/VoiceSessionCoordinator.swift | 134 - .../Sources/OpenClaw/VoiceWakeChime.swift | 76 - .../Sources/OpenClaw/VoiceWakeForwarder.swift | 73 - .../VoiceWakeGlobalSettingsSync.swift | 66 - .../Sources/OpenClaw/VoiceWakeHelpers.swift | 24 - .../Sources/OpenClaw/VoiceWakeOverlay.swift | 62 - .../VoiceWakeOverlayController+Session.swift | 281 - .../VoiceWakeOverlayController+Testing.swift | 49 - .../VoiceWakeOverlayController+Window.swift | 141 - .../OpenClaw/VoiceWakeOverlayTextViews.swift | 202 - .../OpenClaw/VoiceWakeOverlayView.swift | 188 - .../Sources/OpenClaw/VoiceWakeRuntime.swift | 805 - .../Sources/OpenClaw/VoiceWakeSettings.swift | 675 - .../Sources/OpenClaw/VoiceWakeTestCard.swift | 95 - .../Sources/OpenClaw/VoiceWakeTester.swift | 473 - .../Sources/OpenClaw/VoiceWakeTextUtils.swift | 48 - .../Sources/OpenClaw/WebChatManager.swift | 127 - .../Sources/OpenClaw/WebChatSwiftUI.swift | 374 - .../Sources/OpenClaw/WindowPlacement.swift | 84 - .../Sources/OpenClaw/WorkActivityStore.swift | 262 - .../GatewayDiscoveryModel.swift | 682 - .../OpenClawDiscovery/TailscaleNetwork.swift | 46 - .../WideAreaGatewayDiscovery.swift | 375 - apps/macos/Sources/OpenClawIPC/IPC.swift | 416 - .../OpenClawMacCLI/ConnectCommand.swift | 309 - .../OpenClawMacCLI/DiscoverCommand.swift | 149 - .../Sources/OpenClawMacCLI/EntryPoint.swift | 56 - .../OpenClawMacCLI/GatewayConfig.swift | 62 - .../Sources/OpenClawMacCLI/TypeAliases.swift | 5 - .../OpenClawMacCLI/WizardCommand.swift | 548 - .../OpenClawProtocol/GatewayModels.swift | 3053 ---- .../AgentEventStoreTests.swift | 44 - .../AgentWorkspaceTests.swift | 123 - .../AnthropicAuthControlsSmokeTests.swift | 29 - .../AnthropicAuthResolverTests.swift | 52 - .../AnthropicOAuthCodeStateTests.swift | 31 - .../AnyCodableEncodingTests.swift | 38 - .../OpenClawIPCTests/CLIInstallerTests.swift | 34 - .../CameraCaptureServiceTests.swift | 21 - .../OpenClawIPCTests/CameraIPCTests.swift | 61 - .../CanvasFileWatcherTests.swift | 78 - .../OpenClawIPCTests/CanvasIPCTests.swift | 41 - .../CanvasWindowSmokeTests.swift | 49 - .../ChannelsSettingsSmokeTests.swift | 164 - .../CommandResolverTests.swift | 171 - .../OpenClawIPCTests/ConfigStoreTests.swift | 68 - .../OpenClawIPCTests/CoverageDumpTests.swift | 24 - .../CritterIconRendererTests.swift | 37 - .../CronJobEditorSmokeTests.swift | 93 - .../OpenClawIPCTests/CronModelsTests.swift | 141 - .../DeepLinkAgentPolicyTests.swift | 77 - .../DeviceModelCatalogTests.swift | 41 - .../OpenClawIPCTests/ExecAllowlistTests.swift | 197 - .../ExecApprovalHelpersTests.swift | 78 - .../ExecApprovalsGatewayPrompterTests.swift | 56 - .../ExecApprovalsStoreRefactorTests.swift | 75 - .../FileHandleLegacyAPIGuardTests.swift | 155 - .../FileHandleSafeReadTests.swift | 47 - .../GatewayAgentChannelTests.swift | 27 - .../GatewayAutostartPolicyTests.swift | 24 - .../GatewayChannelConfigureTests.swift | 246 - .../GatewayChannelConnectTests.swift | 127 - .../GatewayChannelRequestTests.swift | 101 - .../GatewayChannelShutdownTests.swift | 96 - .../GatewayConnectionControlTests.swift | 59 - .../GatewayDiscoveryHelpersTests.swift | 98 - .../GatewayDiscoveryModelTests.swift | 124 - .../GatewayEndpointStoreTests.swift | 236 - .../GatewayEnvironmentTests.swift | 57 - .../GatewayFrameDecodeTests.swift | 98 - .../GatewayLaunchAgentManagerTests.swift | 41 - .../GatewayProcessManagerTests.swift | 107 - .../GatewayWebSocketTestSupport.swift | 63 - .../OpenClawIPCTests/HealthDecodeTests.swift | 32 - .../HealthStoreStateTests.swift | 42 - .../HoverHUDControllerTests.swift | 26 - .../InstancesSettingsSmokeTests.swift | 59 - .../InstancesStoreTests.swift | 36 - .../OpenClawIPCTests/LogLocatorTests.swift | 24 - .../LowCoverageHelperTests.swift | 215 - .../LowCoverageViewSmokeTests.swift | 99 - .../MacGatewayChatTransportMappingTests.swift | 101 - .../MacNodeRuntimeTests.swift | 97 - .../MasterDiscoveryMenuSmokeTests.swift | 78 - .../MenuContentSmokeTests.swift | 41 - .../MenuSessionsInjectorTests.swift | 96 - .../ModelCatalogLoaderTests.swift | 53 - .../NixModeStableSuiteTests.swift | 46 - .../NodeManagerPathsTests.swift | 45 - .../NodePairingApprovalPrompterTests.swift | 10 - .../NodePairingReconcilePolicyTests.swift | 14 - .../OnboardingCoverageTests.swift | 10 - .../OnboardingViewSmokeTests.swift | 61 - .../OnboardingWizardStepViewTests.swift | 44 - .../OpenClawConfigFileTests.swift | 143 - .../OpenClawOAuthStoreTests.swift | 97 - .../PermissionManagerLocationTests.swift | 20 - .../PermissionManagerTests.swift | 38 - .../Tests/OpenClawIPCTests/Placeholder.swift | 7 - .../RemotePortTunnelTests.swift | 74 - .../RuntimeLocatorTests.swift | 71 - .../ScreenshotSizeTests.swift | 21 - .../Tests/OpenClawIPCTests/SemverTests.swift | 21 - .../OpenClawIPCTests/SessionDataTests.swift | 48 - .../SessionMenuPreviewTests.swift | 28 - .../SettingsViewSmokeTests.swift | 165 - .../SkillsSettingsSmokeTests.swift | 119 - .../TailscaleIntegrationSectionTests.swift | 48 - .../TalkAudioPlayerTests.swift | 97 - .../OpenClawIPCTests/TestIsolation.swift | 116 - .../OpenClawIPCTests/UtilitiesTests.swift | 83 - .../VoicePushToTalkHotkeyTests.swift | 37 - .../VoicePushToTalkTests.swift | 24 - .../VoiceWakeForwarderTests.swift | 22 - .../VoiceWakeGlobalSettingsSyncTests.swift | 56 - .../VoiceWakeHelpersTests.swift | 35 - .../VoiceWakeOverlayControllerTests.swift | 68 - .../VoiceWakeOverlayTests.swift | 21 - .../VoiceWakeOverlayViewSmokeTests.swift | 28 - .../VoiceWakeRuntimeTests.swift | 91 - .../VoiceWakeTesterTests.swift | 47 - .../WebChatMainSessionKeyTests.swift | 67 - .../WebChatManagerTests.swift | 11 - .../WebChatSwiftUISmokeTests.swift | 60 - .../WideAreaGatewayDiscoveryTests.swift | 51 - .../WindowPlacementTests.swift | 85 - .../WorkActivityStoreTests.swift | 99 - apps/shared/OpenClawKit/Package.swift | 61 - .../OpenClawChatUI/AssistantTextParser.swift | 139 - .../Sources/OpenClawChatUI/ChatComposer.swift | 499 - .../ChatMarkdownPreprocessor.swift | 123 - .../OpenClawChatUI/ChatMarkdownRenderer.swift | 90 - .../OpenClawChatUI/ChatMessageViews.swift | 620 - .../Sources/OpenClawChatUI/ChatModels.swift | 332 - .../OpenClawChatUI/ChatPayloadDecoding.swift | 9 - .../Sources/OpenClawChatUI/ChatSessions.swift | 40 - .../Sources/OpenClawChatUI/ChatSheets.swift | 69 - .../Sources/OpenClawChatUI/ChatTheme.swift | 174 - .../OpenClawChatUI/ChatTransport.swift | 45 - .../Sources/OpenClawChatUI/ChatView.swift | 527 - .../OpenClawChatUI/ChatViewModel.swift | 685 - .../ToolResultTextFormatter.swift | 157 - .../Sources/OpenClawKit/AnyCodable.swift | 4 - .../Sources/OpenClawKit/AsyncTimeout.swift | 36 - .../OpenClawKit/AudioStreamingProtocols.swift | 16 - .../Sources/OpenClawKit/BonjourEscapes.swift | 33 - .../Sources/OpenClawKit/BonjourTypes.swift | 40 - .../Sources/OpenClawKit/BridgeFrames.swift | 261 - .../OpenClawKit/CalendarCommands.swift | 93 - .../Sources/OpenClawKit/CameraCommands.swift | 68 - .../OpenClawKit/CanvasA2UIAction.swift | 104 - .../OpenClawKit/CanvasA2UICommands.swift | 26 - .../Sources/OpenClawKit/CanvasA2UIJSONL.swift | 81 - .../OpenClawKit/CanvasCommandParams.swift | 76 - .../Sources/OpenClawKit/CanvasCommands.swift | 9 - .../Sources/OpenClawKit/Capabilities.swift | 16 - .../Sources/OpenClawKit/ChatCommands.swift | 23 - .../OpenClawKit/ContactsCommands.swift | 85 - .../Sources/OpenClawKit/DeepLinks.swift | 185 - .../Sources/OpenClawKit/DeviceAuthStore.swift | 107 - .../Sources/OpenClawKit/DeviceCommands.swift | 134 - .../Sources/OpenClawKit/DeviceIdentity.swift | 112 - .../OpenClawKit/ElevenLabsKitShim.swift | 9 - .../Sources/OpenClawKit/GatewayChannel.swift | 795 - .../GatewayDiscoveryStatusText.swift | 39 - .../OpenClawKit/GatewayEndpointID.swift | 25 - .../Sources/OpenClawKit/GatewayErrors.swift | 38 - .../OpenClawKit/GatewayNodeSession.swift | 442 - .../OpenClawKit/GatewayPayloadDecoding.swift | 20 - .../Sources/OpenClawKit/GatewayPush.swift | 13 - .../OpenClawKit/GatewayTLSPinning.swift | 119 - .../OpenClawKit/InstanceIdentity.swift | 108 - .../Sources/OpenClawKit/JPEGTranscoder.swift | 135 - .../OpenClawKit/LocationCommands.swift | 57 - .../OpenClawKit/LocationSettings.swift | 7 - .../Sources/OpenClawKit/MotionCommands.swift | 95 - .../OpenClawKit/NetworkInterfaces.swift | 43 - .../Sources/OpenClawKit/NodeError.swift | 28 - .../OpenClawKit/OpenClawKitResources.swift | 83 - .../Sources/OpenClawKit/PhotoCapture.swift | 19 - .../Sources/OpenClawKit/PhotosCommands.swift | 41 - .../OpenClawKit/RemindersCommands.swift | 82 - .../Resources/CanvasScaffold/scaffold.html | 225 - .../OpenClawKit/Resources/tool-display.json | 197 - .../Sources/OpenClawKit/ScreenCommands.swift | 27 - .../ShareGatewayRelaySettings.swift | 62 - .../OpenClawKit/ShareToAgentDeepLink.swift | 62 - .../OpenClawKit/ShareToAgentSettings.swift | 29 - .../Sources/OpenClawKit/StoragePaths.swift | 37 - .../Sources/OpenClawKit/SystemCommands.swift | 88 - .../Sources/OpenClawKit/TalkCommands.swift | 28 - .../Sources/OpenClawKit/TalkDirective.swift | 201 - .../OpenClawKit/TalkHistoryTimestamp.swift | 12 - .../OpenClawKit/TalkPromptBuilder.swift | 26 - .../TalkSystemSpeechSynthesizer.swift | 116 - .../Sources/OpenClawKit/ToolDisplay.swift | 265 - .../Sources/OpenClawKit/WatchCommands.swift | 95 - .../Sources/OpenClawProtocol/AnyCodable.swift | 104 - .../OpenClawProtocol/GatewayModels.swift | 3053 ---- .../OpenClawProtocol/WizardHelpers.swift | 106 - .../OpenClawKitTests/AnyCodableTests.swift | 40 - .../AssistantTextParserTests.swift | 37 - .../BonjourEscapesTests.swift | 26 - .../CanvasA2UIActionTests.swift | 36 - .../OpenClawKitTests/CanvasA2UITests.swift | 42 - .../CanvasSnapshotFormatTests.swift | 15 - .../ChatMarkdownPreprocessorTests.swift | 107 - .../OpenClawKitTests/ChatThemeTests.swift | 29 - .../OpenClawKitTests/ChatViewModelTests.swift | 720 - .../DeepLinksSecurityTests.swift | 61 - .../ElevenLabsTTSValidationTests.swift | 19 - .../GatewayNodeSessionTests.swift | 284 - .../JPEGTranscoderTests.swift | 129 - .../OpenClawKitTests/TalkDirectiveTests.swift | 74 - .../TalkHistoryTimestampTests.swift | 16 - .../TalkPromptBuilderTests.swift | 29 - .../ToolDisplayRegistryTests.swift | 16 - .../ToolResultTextFormatterTests.swift | 54 - .../OpenClawKit/Tools/CanvasA2UI/bootstrap.js | 489 - .../Tools/CanvasA2UI/rolldown.config.mjs | 67 - apps/web/app/api/workspace/init/route.test.ts | 6 +- apps/web/app/api/workspace/init/route.ts | 43 +- .../workspace/workspace-sidebar.tsx | 4 +- apps/web/lib/workspace-bootstrap-templates.ts | 14 + apps/web/lib/workspace-seed.ts | 4 + apps/web/package.json | 6 +- apps/web/tsconfig.json | 3 +- apps/web/vitest.config.ts | 1 - assets/avatar-placeholder.svg | 19 - assets/chrome-extension/README.md | 23 - assets/chrome-extension/background.js | 453 - assets/chrome-extension/icons/icon128.png | Bin 614 -> 0 bytes assets/chrome-extension/icons/icon16.png | Bin 265 -> 0 bytes assets/chrome-extension/icons/icon32.png | Bin 318 -> 0 bytes assets/chrome-extension/icons/icon48.png | Bin 370 -> 0 bytes assets/chrome-extension/manifest.json | 25 - assets/chrome-extension/options.html | 200 - assets/chrome-extension/options.js | 83 - assets/dmg-background-small.png | Bin 224752 -> 0 bytes assets/dmg-background.png | Bin 1013735 -> 0 bytes assets/openclaw-ai-sdk-banner.png | Bin 94984 -> 0 bytes openclaw.mjs => denchclaw.mjs | 0 docker-compose.yml | 46 - docker-setup.sh | 288 - docs.acp.md | 197 - docs/.i18n/README.md | 31 - docs/.i18n/glossary.ja-JP.json | 14 - docs/.i18n/glossary.zh-CN.json | 210 - docs/.i18n/ja-JP.tm.jsonl | 0 docs/.i18n/zh-CN.tm.jsonl | 1329 -- docs/CNAME | 1 - docs/assets/install-script.svg | 1 - .../macos-onboarding/01-macos-warning.jpeg | Bin 159086 -> 0 bytes .../macos-onboarding/02-local-networks.jpeg | Bin 166205 -> 0 bytes .../macos-onboarding/03-security-notice.png | Bin 319426 -> 0 bytes .../macos-onboarding/04-choose-gateway.png | Bin 319685 -> 0 bytes .../macos-onboarding/05-permissions.png | Bin 370923 -> 0 bytes docs/assets/openclaw-logo-text-dark.png | Bin 133422 -> 0 bytes docs/assets/openclaw-logo-text.png | Bin 92131 -> 0 bytes docs/assets/pixel-lobster.svg | 60 - docs/assets/showcase/agents-ui.jpg | Bin 133623 -> 0 bytes docs/assets/showcase/bambu-cli.png | Bin 149260 -> 0 bytes docs/assets/showcase/codexmonitor.png | Bin 137961 -> 0 bytes docs/assets/showcase/gohome-grafana.png | Bin 388314 -> 0 bytes docs/assets/showcase/ios-testflight.jpg | Bin 170208 -> 0 bytes docs/assets/showcase/oura-health.png | Bin 1254626 -> 0 bytes docs/assets/showcase/padel-cli.svg | 11 - docs/assets/showcase/padel-screenshot.jpg | Bin 46496 -> 0 bytes docs/assets/showcase/papla-tts.jpg | Bin 71193 -> 0 bytes docs/assets/showcase/pr-review-telegram.jpg | Bin 259648 -> 0 bytes docs/assets/showcase/roborock-screenshot.jpg | Bin 77439 -> 0 bytes docs/assets/showcase/roborock-status.svg | 13 - docs/assets/showcase/roof-camera-sky.jpg | Bin 126380 -> 0 bytes docs/assets/showcase/snag.png | Bin 817148 -> 0 bytes docs/assets/showcase/tesco-shop.jpg | Bin 94600 -> 0 bytes docs/assets/showcase/wienerlinien.png | Bin 136918 -> 0 bytes docs/assets/showcase/wine-cellar-skill.jpg | Bin 80572 -> 0 bytes docs/assets/showcase/winix-air-purifier.jpg | Bin 202240 -> 0 bytes docs/assets/showcase/xuezh-pronunciation.jpeg | Bin 94947 -> 0 bytes docs/assets/sponsors/blacksmith.svg | 14 - docs/assets/sponsors/openai.svg | 3 - docs/automation/auth-monitoring.md | 44 - docs/automation/cron-jobs.md | 542 - docs/automation/cron-vs-heartbeat.md | 286 - docs/automation/gmail-pubsub.md | 256 - docs/automation/hooks.md | 1001 -- docs/automation/poll.md | 69 - docs/automation/troubleshooting.md | 122 - docs/automation/webhook.md | 215 - docs/brave-search.md | 41 - docs/channels/bluebubbles.md | 346 - docs/channels/broadcast-groups.md | 442 - docs/channels/channel-routing.md | 118 - docs/channels/discord.md | 1044 -- docs/channels/feishu.md | 586 - docs/channels/googlechat.md | 253 - docs/channels/grammy.md | 31 - docs/channels/group-messages.md | 84 - docs/channels/groups.md | 374 - docs/channels/imessage.md | 366 - docs/channels/index.md | 47 - docs/channels/irc.md | 234 - docs/channels/line.md | 186 - docs/channels/location.md | 56 - docs/channels/matrix.md | 302 - docs/channels/mattermost.md | 158 - docs/channels/msteams.md | 771 - docs/channels/nextcloud-talk.md | 138 - docs/channels/nostr.md | 233 - docs/channels/pairing.md | 103 - docs/channels/signal.md | 324 - docs/channels/slack.md | 525 - docs/channels/telegram.md | 749 - docs/channels/tlon.md | 148 - docs/channels/troubleshooting.md | 117 - docs/channels/twitch.md | 379 - docs/channels/whatsapp.md | 444 - docs/channels/zalo.md | 192 - docs/channels/zalouser.md | 140 - docs/ci.md | 50 - docs/cli/acp.md | 182 - docs/cli/agent.md | 24 - docs/cli/agents.md | 75 - docs/cli/approvals.md | 50 - docs/cli/browser.md | 107 - docs/cli/channels.md | 79 - docs/cli/config.md | 50 - docs/cli/configure.md | 33 - docs/cli/cron.md | 44 - docs/cli/dashboard.md | 16 - docs/cli/devices.md | 73 - docs/cli/directory.md | 63 - docs/cli/dns.md | 23 - docs/cli/docs.md | 15 - docs/cli/doctor.md | 41 - docs/cli/gateway.md | 202 - docs/cli/health.md | 21 - docs/cli/hooks.md | 313 - docs/cli/index.md | 1036 -- docs/cli/logs.md | 28 - docs/cli/memory.md | 45 - docs/cli/message.md | 260 - docs/cli/models.md | 79 - docs/cli/node.md | 112 - docs/cli/nodes.md | 73 - docs/cli/onboard.md | 76 - docs/cli/pairing.md | 21 - docs/cli/plugins.md | 92 - docs/cli/reset.md | 17 - docs/cli/sandbox.md | 152 - docs/cli/security.md | 65 - docs/cli/sessions.md | 16 - docs/cli/setup.md | 29 - docs/cli/skills.md | 26 - docs/cli/status.md | 26 - docs/cli/system.md | 60 - docs/cli/tui.md | 23 - docs/cli/uninstall.md | 17 - docs/cli/update.md | 98 - docs/cli/voicecall.md | 34 - docs/cli/webhooks.md | 25 - docs/concepts/agent-loop.md | 148 - docs/concepts/agent-workspace.md | 234 - docs/concepts/agent.md | 123 - docs/concepts/architecture.md | 136 - docs/concepts/compaction.md | 61 - docs/concepts/context.md | 161 - docs/concepts/features.md | 53 - docs/concepts/markdown-formatting.md | 130 - docs/concepts/memory.md | 733 - docs/concepts/messages.md | 154 - docs/concepts/model-failover.md | 149 - docs/concepts/model-providers.md | 424 - docs/concepts/models.md | 209 - docs/concepts/multi-agent.md | 536 - docs/concepts/oauth.md | 145 - docs/concepts/presence.md | 102 - docs/concepts/queue.md | 89 - docs/concepts/retry.md | 69 - docs/concepts/session-pruning.md | 123 - docs/concepts/session-tool.md | 219 - docs/concepts/session.md | 206 - docs/concepts/sessions.md | 10 - docs/concepts/streaming.md | 155 - docs/concepts/system-prompt.md | 129 - docs/concepts/timezone.md | 91 - docs/concepts/typebox.md | 289 - docs/concepts/typing-indicators.md | 68 - docs/concepts/usage-tracking.md | 35 - docs/date-time.md | 128 - docs/debug/node-issue.md | 85 - docs/diagnostics/flags.md | 91 - docs/docs.json | 1858 -- docs/experiments/.DS_Store | Bin 6148 -> 0 bytes .../experiments/onboarding-config-protocol.md | 40 - .../plans/browser-evaluate-cdp-refactor.md | 229 - docs/experiments/plans/cron-add-hardening.md | 63 - .../plans/group-policy-hardening.md | 40 - .../plans/openresponses-gateway.md | 123 - .../plans/pty-process-supervision.md | 192 - .../plans/session-binding-channel-agnostic.md | 223 - docs/experiments/proposals/model-config.md | 36 - docs/experiments/research/memory.md | 228 - docs/gateway/authentication.md | 162 - docs/gateway/background-process.md | 96 - docs/gateway/bonjour.md | 177 - docs/gateway/bridge-protocol.md | 91 - docs/gateway/cli-backends.md | 225 - docs/gateway/configuration-examples.md | 620 - docs/gateway/configuration-reference.md | 2511 --- docs/gateway/configuration.md | 496 - docs/gateway/discovery.md | 123 - docs/gateway/doctor.md | 282 - docs/gateway/gateway-lock.md | 34 - docs/gateway/health.md | 35 - docs/gateway/heartbeat.md | 376 - docs/gateway/index.md | 254 - docs/gateway/local-models.md | 150 - docs/gateway/logging.md | 113 - docs/gateway/multiple-gateways.md | 112 - docs/gateway/network-model.md | 20 - docs/gateway/openai-http-api.md | 119 - docs/gateway/openresponses-http-api.md | 333 - docs/gateway/pairing.md | 99 - docs/gateway/protocol.md | 221 - docs/gateway/remote-gateway-readme.md | 158 - docs/gateway/remote.md | 131 - .../sandbox-vs-tool-policy-vs-elevated.md | 128 - docs/gateway/sandboxing.md | 203 - docs/gateway/security/index.md | 936 - docs/gateway/tailscale.md | 132 - docs/gateway/tools-invoke-http-api.md | 110 - docs/gateway/troubleshooting.md | 318 - docs/gateway/trusted-proxy-auth.md | 270 - docs/help/debugging.md | 162 - docs/help/environment.md | 107 - docs/help/faq.md | 2879 ---- docs/help/index.md | 21 - docs/help/scripts.md | 28 - docs/help/testing.md | 385 - docs/help/troubleshooting.md | 265 - .../configure-model-picker-unsearchable.png | Bin 672731 -> 0 bytes docs/images/feishu-step2-create-app.png | Bin 461999 -> 0 bytes docs/images/feishu-step3-credentials.png | Bin 229747 -> 0 bytes docs/images/feishu-step4-permissions.png | Bin 413354 -> 0 bytes docs/images/feishu-step5-bot-capability.png | Bin 383469 -> 0 bytes .../feishu-step6-event-subscription.png | Bin 364996 -> 0 bytes docs/images/groups-flow.svg | 52 - docs/images/mobile-ui-screenshot.png | Bin 107288 -> 0 bytes docs/index.md | 192 - docs/install/ansible.md | 208 - docs/install/bun.md | 59 - docs/install/development-channels.md | 75 - docs/install/docker.md | 590 - docs/install/exe-dev.md | 126 - docs/install/fly.md | 486 - docs/install/gcp.md | 500 - docs/install/hetzner.md | 348 - docs/install/index.md | 218 - docs/install/installer.md | 405 - docs/install/macos-vm.md | 281 - docs/install/migrating.md | 192 - docs/install/nix.md | 98 - docs/install/node.md | 138 - docs/install/northflank.mdx | 53 - docs/install/podman.md | 108 - docs/install/railway.mdx | 99 - docs/install/render.mdx | 159 - docs/install/uninstall.md | 128 - docs/install/updating.md | 233 - docs/ja-JP/AGENTS.md | 37 - docs/ja-JP/index.md | 186 - docs/ja-JP/start/getting-started.md | 125 - docs/ja-JP/start/wizard.md | 77 - docs/logging.md | 350 - docs/nav-tabs-underline.js | 100 - docs/network.md | 54 - docs/nodes/audio.md | 133 - docs/nodes/camera.md | 156 - docs/nodes/images.md | 72 - docs/nodes/index.md | 342 - docs/nodes/location-command.md | 113 - docs/nodes/media-understanding.md | 379 - docs/nodes/talk.md | 90 - docs/nodes/troubleshooting.md | 112 - docs/nodes/voicewake.md | 65 - docs/perplexity.md | 80 - docs/pi-dev.md | 70 - docs/pi.md | 612 - docs/platforms/android.md | 151 - docs/platforms/digitalocean.md | 266 - docs/platforms/index.md | 53 - docs/platforms/ios.md | 108 - docs/platforms/linux.md | 94 - docs/platforms/mac/bundled-gateway.md | 73 - docs/platforms/mac/canvas.md | 125 - docs/platforms/mac/child-process.md | 69 - docs/platforms/mac/dev-setup.md | 104 - docs/platforms/mac/health.md | 34 - docs/platforms/mac/icon.md | 31 - docs/platforms/mac/logging.md | 57 - docs/platforms/mac/menu-bar.md | 81 - docs/platforms/mac/peekaboo.md | 65 - docs/platforms/mac/permissions.md | 50 - docs/platforms/mac/release.md | 85 - docs/platforms/mac/remote.md | 84 - docs/platforms/mac/signing.md | 47 - docs/platforms/mac/skills.md | 33 - docs/platforms/mac/voice-overlay.md | 60 - docs/platforms/mac/voicewake.md | 67 - docs/platforms/mac/webchat.md | 43 - docs/platforms/mac/xpc.md | 61 - docs/platforms/macos.md | 205 - docs/platforms/oracle.md | 303 - docs/platforms/raspberry-pi.md | 358 - docs/platforms/windows.md | 159 - docs/plugins/agent-tools.md | 99 - docs/plugins/community.md | 44 - docs/plugins/manifest.md | 71 - docs/plugins/voice-call.md | 322 - docs/plugins/zalouser.md | 81 - docs/prose.md | 134 - docs/providers/anthropic.md | 174 - docs/providers/bedrock.md | 176 - docs/providers/claude-max-api-proxy.md | 148 - docs/providers/cloudflare-ai-gateway.md | 71 - docs/providers/deepgram.md | 93 - docs/providers/github-copilot.md | 72 - docs/providers/glm.md | 33 - docs/providers/huggingface.md | 209 - docs/providers/index.md | 69 - docs/providers/litellm.md | 153 - docs/providers/minimax.md | 208 - docs/providers/models.md | 52 - docs/providers/moonshot.md | 142 - docs/providers/nvidia.md | 55 - docs/providers/ollama.md | 250 - docs/providers/openai.md | 62 - docs/providers/opencode.md | 36 - docs/providers/openrouter.md | 37 - docs/providers/qianfan.md | 38 - docs/providers/qwen.md | 53 - docs/providers/synthetic.md | 99 - docs/providers/together.md | 65 - docs/providers/venice.md | 267 - docs/providers/vercel-ai-gateway.md | 50 - docs/providers/vllm.md | 92 - docs/providers/xiaomi.md | 64 - docs/providers/zai.md | 38 - docs/refactor/clawnet.md | 417 - docs/refactor/exec-host.md | 316 - docs/refactor/outbound-session-mirroring.md | 85 - docs/refactor/plugin-sdk.md | 214 - docs/refactor/strict-config.md | 93 - docs/reference/AGENTS.default.md | 124 - docs/reference/RELEASING.md | 121 - docs/reference/api-usage-costs.md | 138 - docs/reference/credits.md | 28 - docs/reference/device-models.md | 47 - docs/reference/rpc.md | 43 - .../session-management-compaction.md | 285 - docs/reference/templates/AGENTS.dev.md | 83 - docs/reference/templates/AGENTS.md | 219 - docs/reference/templates/BOOT.md | 11 - docs/reference/templates/BOOTSTRAP.md | 62 - docs/reference/templates/HEARTBEAT.md | 12 - docs/reference/templates/IDENTITY.dev.md | 47 - docs/reference/templates/IDENTITY.md | 29 - docs/reference/templates/SOUL.dev.md | 76 - docs/reference/templates/SOUL.md | 43 - docs/reference/templates/TOOLS.dev.md | 24 - docs/reference/templates/TOOLS.md | 47 - docs/reference/templates/USER.dev.md | 18 - docs/reference/templates/USER.md | 23 - docs/reference/test.md | 51 - docs/reference/token-use.md | 136 - docs/reference/transcript-hygiene.md | 151 - docs/reference/wizard.md | 269 - docs/security/CONTRIBUTING-THREAT-MODEL.md | 90 - docs/security/README.md | 17 - docs/security/THREAT-MODEL-ATLAS.md | 603 - docs/security/formal-verification.md | 164 - docs/start/bootstrapping.md | 41 - docs/start/docs-directory.md | 64 - docs/start/getting-started.md | 135 - docs/start/hubs.md | 197 - docs/start/lore.md | 219 - docs/start/onboarding-overview.md | 51 - docs/start/onboarding.md | 81 - docs/start/openclaw.md | 215 - docs/start/quickstart.md | 22 - docs/start/setup.md | 162 - docs/start/showcase.md | 416 - docs/start/wizard-cli-automation.md | 158 - docs/start/wizard-cli-reference.md | 259 - docs/start/wizard.md | 110 - docs/style.css | 37 - docs/tools/agent-send.md | 53 - docs/tools/apply-patch.md | 51 - docs/tools/browser-linux-troubleshooting.md | 139 - docs/tools/browser-login.md | 67 - docs/tools/browser.md | 587 - docs/tools/chrome-extension.md | 183 - docs/tools/clawhub.md | 257 - docs/tools/creating-skills.md | 54 - docs/tools/elevated.md | 57 - docs/tools/exec-approvals.md | 276 - docs/tools/exec.md | 184 - docs/tools/firecrawl.md | 61 - docs/tools/index.md | 551 - docs/tools/llm-task.md | 115 - docs/tools/lobster.md | 340 - docs/tools/loop-detection.md | 98 - docs/tools/multi-agent-sandbox-tools.md | 397 - docs/tools/plugin.md | 687 - docs/tools/reactions.md | 22 - docs/tools/skills-config.md | 76 - docs/tools/skills.md | 300 - docs/tools/slash-commands.md | 217 - docs/tools/subagents.md | 273 - docs/tools/thinking.md | 74 - docs/tools/web.md | 265 - docs/tts.md | 399 - docs/vps.md | 43 - docs/web/control-ui.md | 248 - docs/web/dashboard.md | 46 - docs/web/index.md | 118 - docs/web/tui.md | 162 - docs/web/webchat.md | 53 - docs/whatsapp-openclaw-ai-zh.jpg | Bin 249947 -> 0 bytes docs/whatsapp-openclaw.jpg | Bin 91771 -> 0 bytes docs/zh-CN/AGENTS.md | 59 - docs/zh-CN/automation/auth-monitoring.md | 47 - docs/zh-CN/automation/cron-jobs.md | 424 - docs/zh-CN/automation/cron-vs-heartbeat.md | 286 - docs/zh-CN/automation/gmail-pubsub.md | 249 - docs/zh-CN/automation/hooks.md | 882 - docs/zh-CN/automation/poll.md | 76 - docs/zh-CN/automation/troubleshooting.md | 8 - docs/zh-CN/automation/webhook.md | 163 - docs/zh-CN/brave-search.md | 48 - docs/zh-CN/channels/bluebubbles.md | 271 - docs/zh-CN/channels/broadcast-groups.md | 449 - docs/zh-CN/channels/channel-routing.md | 117 - docs/zh-CN/channels/discord.md | 468 - docs/zh-CN/channels/feishu.md | 629 - docs/zh-CN/channels/googlechat.md | 257 - docs/zh-CN/channels/grammy.md | 38 - docs/zh-CN/channels/group-messages.md | 91 - docs/zh-CN/channels/groups.md | 379 - docs/zh-CN/channels/imessage.md | 302 - docs/zh-CN/channels/index.md | 53 - docs/zh-CN/channels/line.md | 180 - docs/zh-CN/channels/location.md | 63 - docs/zh-CN/channels/matrix.md | 221 - docs/zh-CN/channels/mattermost.md | 144 - docs/zh-CN/channels/msteams.md | 775 - docs/zh-CN/channels/nextcloud-talk.md | 142 - docs/zh-CN/channels/nostr.md | 240 - docs/zh-CN/channels/pairing.md | 89 - docs/zh-CN/channels/signal.md | 209 - docs/zh-CN/channels/slack.md | 531 - docs/zh-CN/channels/telegram.md | 751 - docs/zh-CN/channels/tlon.md | 136 - docs/zh-CN/channels/troubleshooting.md | 36 - docs/zh-CN/channels/twitch.md | 385 - docs/zh-CN/channels/whatsapp.md | 411 - docs/zh-CN/channels/zalo.md | 196 - docs/zh-CN/channels/zalouser.md | 147 - docs/zh-CN/cli/acp.md | 173 - docs/zh-CN/cli/agent.md | 30 - docs/zh-CN/cli/agents.md | 82 - docs/zh-CN/cli/approvals.md | 57 - docs/zh-CN/cli/browser.md | 114 - docs/zh-CN/cli/channels.md | 86 - docs/zh-CN/cli/config.md | 57 - docs/zh-CN/cli/configure.md | 38 - docs/zh-CN/cli/cron.md | 43 - docs/zh-CN/cli/dashboard.md | 23 - docs/zh-CN/cli/devices.md | 74 - docs/zh-CN/cli/directory.md | 70 - docs/zh-CN/cli/dns.md | 30 - docs/zh-CN/cli/docs.md | 22 - docs/zh-CN/cli/doctor.md | 48 - docs/zh-CN/cli/gateway.md | 206 - docs/zh-CN/cli/health.md | 28 - docs/zh-CN/cli/hooks.md | 298 - docs/zh-CN/cli/index.md | 1032 -- docs/zh-CN/cli/logs.md | 31 - docs/zh-CN/cli/memory.md | 52 - docs/zh-CN/cli/message.md | 246 - docs/zh-CN/cli/models.md | 85 - docs/zh-CN/cli/node.md | 115 - docs/zh-CN/cli/nodes.md | 80 - docs/zh-CN/cli/onboard.md | 36 - docs/zh-CN/cli/pairing.md | 28 - docs/zh-CN/cli/plugins.md | 66 - docs/zh-CN/cli/reset.md | 24 - docs/zh-CN/cli/sandbox.md | 158 - docs/zh-CN/cli/security.md | 33 - docs/zh-CN/cli/sessions.md | 23 - docs/zh-CN/cli/setup.md | 36 - docs/zh-CN/cli/skills.md | 33 - docs/zh-CN/cli/status.md | 33 - docs/zh-CN/cli/system.md | 63 - docs/zh-CN/cli/tui.md | 30 - docs/zh-CN/cli/uninstall.md | 24 - docs/zh-CN/cli/update.md | 101 - docs/zh-CN/cli/voicecall.md | 41 - docs/zh-CN/cli/webhooks.md | 32 - docs/zh-CN/concepts/agent-loop.md | 146 - docs/zh-CN/concepts/agent-workspace.md | 219 - docs/zh-CN/concepts/agent.md | 115 - docs/zh-CN/concepts/architecture.md | 123 - docs/zh-CN/concepts/compaction.md | 67 - docs/zh-CN/concepts/context.md | 168 - docs/zh-CN/concepts/features.md | 59 - docs/zh-CN/concepts/markdown-formatting.md | 117 - docs/zh-CN/concepts/memory.md | 412 - docs/zh-CN/concepts/messages.md | 141 - docs/zh-CN/concepts/model-failover.md | 145 - docs/zh-CN/concepts/model-providers.md | 320 - docs/zh-CN/concepts/models.md | 196 - docs/zh-CN/concepts/multi-agent.md | 372 - docs/zh-CN/concepts/oauth.md | 151 - docs/zh-CN/concepts/presence.md | 99 - docs/zh-CN/concepts/queue.md | 94 - docs/zh-CN/concepts/retry.md | 76 - docs/zh-CN/concepts/session-pruning.md | 129 - docs/zh-CN/concepts/session-tool.md | 200 - docs/zh-CN/concepts/session.md | 166 - docs/zh-CN/concepts/sessions.md | 17 - docs/zh-CN/concepts/streaming.md | 133 - docs/zh-CN/concepts/system-prompt.md | 101 - docs/zh-CN/concepts/timezone.md | 96 - docs/zh-CN/concepts/typebox.md | 284 - docs/zh-CN/concepts/typing-indicators.md | 74 - docs/zh-CN/concepts/usage-tracking.md | 42 - docs/zh-CN/date-time.md | 129 - docs/zh-CN/debug/node-issue.md | 90 - docs/zh-CN/diagnostics/flags.md | 98 - .../experiments/onboarding-config-protocol.md | 47 - .../experiments/plans/cron-add-hardening.md | 70 - .../plans/group-policy-hardening.md | 45 - .../plans/openresponses-gateway.md | 121 - .../experiments/proposals/model-config.md | 42 - docs/zh-CN/experiments/research/memory.md | 235 - docs/zh-CN/gateway/authentication.md | 142 - docs/zh-CN/gateway/background-process.md | 100 - docs/zh-CN/gateway/bonjour.md | 174 - docs/zh-CN/gateway/bridge-protocol.md | 86 - docs/zh-CN/gateway/cli-backends.md | 213 - docs/zh-CN/gateway/configuration-examples.md | 587 - docs/zh-CN/gateway/configuration.md | 3332 ---- docs/zh-CN/gateway/discovery.md | 123 - docs/zh-CN/gateway/doctor.md | 238 - docs/zh-CN/gateway/gateway-lock.md | 41 - docs/zh-CN/gateway/health.md | 42 - docs/zh-CN/gateway/heartbeat.md | 274 - docs/zh-CN/gateway/index.md | 335 - docs/zh-CN/gateway/local-models.md | 157 - docs/zh-CN/gateway/logging.md | 114 - docs/zh-CN/gateway/multiple-gateways.md | 119 - docs/zh-CN/gateway/network-model.md | 23 - docs/zh-CN/gateway/openai-http-api.md | 125 - docs/zh-CN/gateway/openresponses-http-api.md | 317 - docs/zh-CN/gateway/pairing.md | 99 - docs/zh-CN/gateway/protocol.md | 220 - docs/zh-CN/gateway/remote-gateway-readme.md | 164 - docs/zh-CN/gateway/remote.md | 133 - .../sandbox-vs-tool-policy-vs-elevated.md | 135 - docs/zh-CN/gateway/sandboxing.md | 188 - docs/zh-CN/gateway/security/index.md | 777 - docs/zh-CN/gateway/tailscale.md | 124 - docs/zh-CN/gateway/tools-invoke-http-api.md | 92 - docs/zh-CN/gateway/troubleshooting.md | 771 - docs/zh-CN/help/debugging.md | 160 - docs/zh-CN/help/environment.md | 88 - docs/zh-CN/help/faq.md | 2628 --- docs/zh-CN/help/index.md | 28 - docs/zh-CN/help/scripts.md | 35 - docs/zh-CN/help/testing.md | 375 - docs/zh-CN/help/troubleshooting.md | 104 - docs/zh-CN/index.md | 186 - docs/zh-CN/install/ansible.md | 215 - docs/zh-CN/install/bun.md | 65 - docs/zh-CN/install/development-channels.md | 81 - docs/zh-CN/install/docker.md | 532 - docs/zh-CN/install/exe-dev.md | 127 - docs/zh-CN/install/fly.md | 490 - docs/zh-CN/install/gcp.md | 510 - docs/zh-CN/install/hetzner.md | 337 - docs/zh-CN/install/index.md | 193 - docs/zh-CN/install/installer.md | 128 - docs/zh-CN/install/macos-vm.md | 288 - docs/zh-CN/install/migrating.md | 199 - docs/zh-CN/install/nix.md | 99 - docs/zh-CN/install/node.md | 8 - docs/zh-CN/install/northflank.mdx | 60 - docs/zh-CN/install/railway.mdx | 106 - docs/zh-CN/install/render.mdx | 169 - docs/zh-CN/install/uninstall.md | 135 - docs/zh-CN/install/updating.md | 233 - docs/zh-CN/logging.md | 329 - docs/zh-CN/network.md | 59 - docs/zh-CN/nodes/audio.md | 120 - docs/zh-CN/nodes/camera.md | 162 - docs/zh-CN/nodes/images.md | 79 - docs/zh-CN/nodes/index.md | 348 - docs/zh-CN/nodes/location-command.md | 120 - docs/zh-CN/nodes/media-understanding.md | 380 - docs/zh-CN/nodes/talk.md | 97 - docs/zh-CN/nodes/troubleshooting.md | 8 - docs/zh-CN/nodes/voicewake.md | 72 - docs/zh-CN/perplexity.md | 84 - docs/zh-CN/pi-dev.md | 77 - docs/zh-CN/pi.md | 619 - docs/zh-CN/platforms/android.md | 155 - docs/zh-CN/platforms/digitalocean.md | 269 - docs/zh-CN/platforms/index.md | 60 - docs/zh-CN/platforms/ios.md | 114 - docs/zh-CN/platforms/linux.md | 101 - docs/zh-CN/platforms/mac/bundled-gateway.md | 75 - docs/zh-CN/platforms/mac/canvas.md | 128 - docs/zh-CN/platforms/mac/child-process.md | 73 - docs/zh-CN/platforms/mac/dev-setup.md | 109 - docs/zh-CN/platforms/mac/health.md | 41 - docs/zh-CN/platforms/mac/icon.md | 38 - docs/zh-CN/platforms/mac/logging.md | 64 - docs/zh-CN/platforms/mac/menu-bar.md | 88 - docs/zh-CN/platforms/mac/peekaboo.md | 62 - docs/zh-CN/platforms/mac/permissions.md | 46 - docs/zh-CN/platforms/mac/release.md | 92 - docs/zh-CN/platforms/mac/remote.md | 90 - docs/zh-CN/platforms/mac/signing.md | 54 - docs/zh-CN/platforms/mac/skills.md | 40 - docs/zh-CN/platforms/mac/voice-overlay.md | 67 - docs/zh-CN/platforms/mac/voicewake.md | 74 - docs/zh-CN/platforms/mac/webchat.md | 43 - docs/zh-CN/platforms/mac/xpc.md | 68 - docs/zh-CN/platforms/macos.md | 193 - docs/zh-CN/platforms/oracle.md | 310 - docs/zh-CN/platforms/raspberry-pi.md | 365 - docs/zh-CN/platforms/windows.md | 156 - docs/zh-CN/plugins/agent-tools.md | 99 - docs/zh-CN/plugins/manifest.md | 68 - docs/zh-CN/plugins/voice-call.md | 250 - docs/zh-CN/plugins/zalouser.md | 88 - docs/zh-CN/prose.md | 141 - docs/zh-CN/providers/anthropic.md | 159 - docs/zh-CN/providers/bedrock.md | 170 - docs/zh-CN/providers/claude-max-api-proxy.md | 155 - docs/zh-CN/providers/deepgram.md | 97 - docs/zh-CN/providers/github-copilot.md | 67 - docs/zh-CN/providers/glm.md | 39 - docs/zh-CN/providers/index.md | 68 - docs/zh-CN/providers/minimax.md | 206 - docs/zh-CN/providers/models.md | 55 - docs/zh-CN/providers/moonshot.md | 145 - docs/zh-CN/providers/ollama.md | 230 - docs/zh-CN/providers/openai.md | 68 - docs/zh-CN/providers/opencode.md | 41 - docs/zh-CN/providers/openrouter.md | 43 - docs/zh-CN/providers/qianfan.md | 8 - docs/zh-CN/providers/qwen.md | 55 - docs/zh-CN/providers/synthetic.md | 102 - docs/zh-CN/providers/venice.md | 274 - docs/zh-CN/providers/vercel-ai-gateway.md | 57 - docs/zh-CN/providers/xiaomi.md | 68 - docs/zh-CN/providers/zai.md | 41 - docs/zh-CN/refactor/clawnet.md | 424 - docs/zh-CN/refactor/exec-host.md | 323 - .../refactor/outbound-session-mirroring.md | 92 - docs/zh-CN/refactor/plugin-sdk.md | 221 - docs/zh-CN/refactor/strict-config.md | 100 - docs/zh-CN/reference/AGENTS.default.md | 131 - docs/zh-CN/reference/RELEASING.md | 123 - docs/zh-CN/reference/api-usage-costs.md | 136 - docs/zh-CN/reference/credits.md | 34 - docs/zh-CN/reference/device-models.md | 54 - docs/zh-CN/reference/rpc.md | 48 - .../session-management-compaction.md | 287 - docs/zh-CN/reference/templates/AGENTS.dev.md | 89 - docs/zh-CN/reference/templates/AGENTS.md | 225 - docs/zh-CN/reference/templates/BOOT.md | 17 - docs/zh-CN/reference/templates/BOOTSTRAP.md | 68 - docs/zh-CN/reference/templates/HEARTBEAT.md | 18 - .../zh-CN/reference/templates/IDENTITY.dev.md | 54 - docs/zh-CN/reference/templates/IDENTITY.md | 36 - docs/zh-CN/reference/templates/SOUL.dev.md | 83 - docs/zh-CN/reference/templates/SOUL.md | 49 - docs/zh-CN/reference/templates/TOOLS.dev.md | 31 - docs/zh-CN/reference/templates/TOOLS.md | 53 - docs/zh-CN/reference/templates/USER.dev.md | 25 - docs/zh-CN/reference/templates/USER.md | 30 - docs/zh-CN/reference/test.md | 57 - docs/zh-CN/reference/token-use.md | 119 - docs/zh-CN/reference/transcript-hygiene.md | 109 - docs/zh-CN/reference/wizard.md | 9 - docs/zh-CN/security/formal-verification.md | 171 - docs/zh-CN/start/bootstrapping.md | 9 - docs/zh-CN/start/docs-directory.md | 70 - docs/zh-CN/start/getting-started.md | 206 - docs/zh-CN/start/hubs.md | 200 - docs/zh-CN/start/lore.md | 226 - docs/zh-CN/start/onboarding.md | 105 - docs/zh-CN/start/openclaw.md | 248 - docs/zh-CN/start/quickstart.md | 88 - docs/zh-CN/start/setup.md | 153 - docs/zh-CN/start/showcase.md | 423 - docs/zh-CN/start/wizard.md | 331 - docs/zh-CN/tools/agent-send.md | 59 - docs/zh-CN/tools/apply-patch.md | 57 - .../tools/browser-linux-troubleshooting.md | 144 - docs/zh-CN/tools/browser-login.md | 75 - docs/zh-CN/tools/browser.md | 553 - docs/zh-CN/tools/chrome-extension.md | 183 - docs/zh-CN/tools/clawhub.md | 209 - docs/zh-CN/tools/creating-skills.md | 61 - docs/zh-CN/tools/elevated.md | 64 - docs/zh-CN/tools/exec-approvals.md | 234 - docs/zh-CN/tools/exec.md | 169 - docs/zh-CN/tools/firecrawl.md | 68 - docs/zh-CN/tools/index.md | 515 - docs/zh-CN/tools/llm-task.md | 117 - docs/zh-CN/tools/lobster.md | 349 - docs/zh-CN/tools/multi-agent-sandbox-tools.md | 401 - docs/zh-CN/tools/plugin.md | 639 - docs/zh-CN/tools/reactions.md | 29 - docs/zh-CN/tools/skills-config.md | 78 - docs/zh-CN/tools/skills.md | 279 - docs/zh-CN/tools/slash-commands.md | 205 - docs/zh-CN/tools/subagents.md | 167 - docs/zh-CN/tools/thinking.md | 80 - docs/zh-CN/tools/web.md | 257 - docs/zh-CN/tts.md | 375 - docs/zh-CN/vps.md | 47 - docs/zh-CN/web/control-ui.md | 191 - docs/zh-CN/web/dashboard.md | 53 - docs/zh-CN/web/index.md | 118 - docs/zh-CN/web/tui.md | 166 - docs/zh-CN/web/webchat.md | 56 - extensions/bluebubbles/README.md | 45 - extensions/bluebubbles/index.ts | 19 - extensions/bluebubbles/openclaw.plugin.json | 9 - extensions/bluebubbles/package.json | 36 - extensions/bluebubbles/src/account-resolve.ts | 29 - extensions/bluebubbles/src/accounts.ts | 88 - extensions/bluebubbles/src/actions.test.ts | 709 - extensions/bluebubbles/src/actions.ts | 471 - .../bluebubbles/src/attachments.test.ts | 405 - extensions/bluebubbles/src/attachments.ts | 259 - extensions/bluebubbles/src/channel.ts | 414 - extensions/bluebubbles/src/chat.test.ts | 432 - extensions/bluebubbles/src/chat.ts | 379 - .../bluebubbles/src/config-schema.test.ts | 55 - extensions/bluebubbles/src/config-schema.ts | 64 - extensions/bluebubbles/src/history.ts | 177 - extensions/bluebubbles/src/media-send.test.ts | 256 - extensions/bluebubbles/src/media-send.ts | 317 - .../bluebubbles/src/monitor-normalize.ts | 796 - .../bluebubbles/src/monitor-processing.ts | 1448 -- .../bluebubbles/src/monitor-reply-cache.ts | 185 - extensions/bluebubbles/src/monitor-shared.ts | 51 - extensions/bluebubbles/src/monitor.test.ts | 3310 ---- extensions/bluebubbles/src/monitor.ts | 534 - extensions/bluebubbles/src/multipart.ts | 32 - extensions/bluebubbles/src/onboarding.ts | 353 - extensions/bluebubbles/src/probe.ts | 155 - extensions/bluebubbles/src/reactions.test.ts | 392 - extensions/bluebubbles/src/reactions.ts | 182 - extensions/bluebubbles/src/request-url.ts | 12 - extensions/bluebubbles/src/runtime.ts | 14 - extensions/bluebubbles/src/send-helpers.ts | 53 - extensions/bluebubbles/src/send.test.ts | 719 - extensions/bluebubbles/src/send.ts | 430 - extensions/bluebubbles/src/targets.test.ts | 202 - extensions/bluebubbles/src/targets.ts | 361 - extensions/bluebubbles/src/test-harness.ts | 50 - extensions/bluebubbles/src/test-mocks.ts | 11 - extensions/bluebubbles/src/types.ts | 133 - extensions/copilot-proxy/README.md | 24 - extensions/copilot-proxy/index.ts | 154 - extensions/copilot-proxy/openclaw.plugin.json | 9 - extensions/copilot-proxy/package.json | 15 - extensions/denchclaw-auth/README.md | 39 - extensions/denchclaw-auth/index.ts | 258 - extensions/denchclaw-auth/oauth.ts | 354 - .../denchclaw-auth/openclaw.plugin.json | 9 - extensions/device-pair/index.ts | 644 - extensions/device-pair/openclaw.plugin.json | 20 - extensions/diagnostics-otel/index.ts | 15 - .../diagnostics-otel/openclaw.plugin.json | 8 - extensions/diagnostics-otel/package.json | 27 - .../diagnostics-otel/src/service.test.ts | 296 - extensions/diagnostics-otel/src/service.ts | 666 - extensions/discord/index.ts | 19 - extensions/discord/openclaw.plugin.json | 9 - extensions/discord/package.json | 14 - extensions/discord/src/channel.ts | 442 - extensions/discord/src/runtime.ts | 14 - extensions/discord/src/subagent-hooks.test.ts | 430 - extensions/discord/src/subagent-hooks.ts | 152 - extensions/feishu/index.ts | 63 - extensions/feishu/openclaw.plugin.json | 10 - extensions/feishu/package.json | 37 - extensions/feishu/skills/feishu-doc/SKILL.md | 105 - .../feishu-doc/references/block-types.md | 103 - .../feishu/skills/feishu-drive/SKILL.md | 97 - extensions/feishu/skills/feishu-perm/SKILL.md | 119 - extensions/feishu/skills/feishu-wiki/SKILL.md | 111 - extensions/feishu/src/accounts.ts | 144 - extensions/feishu/src/bitable.ts | 739 - .../feishu/src/bot.checkBotMentioned.test.ts | 149 - .../feishu/src/bot.stripBotMention.test.ts | 38 - extensions/feishu/src/bot.test.ts | 289 - extensions/feishu/src/bot.ts | 978 -- extensions/feishu/src/channel.test.ts | 48 - extensions/feishu/src/channel.ts | 355 - extensions/feishu/src/client.ts | 118 - extensions/feishu/src/config-schema.test.ts | 66 - extensions/feishu/src/config-schema.ts | 240 - extensions/feishu/src/dedup.ts | 33 - extensions/feishu/src/directory.ts | 177 - extensions/feishu/src/doc-schema.ts | 47 - extensions/feishu/src/docx.test.ts | 123 - extensions/feishu/src/docx.ts | 536 - extensions/feishu/src/drive-schema.ts | 46 - extensions/feishu/src/drive.ts | 227 - extensions/feishu/src/dynamic-agent.ts | 132 - extensions/feishu/src/external-keys.test.ts | 20 - extensions/feishu/src/external-keys.ts | 19 - extensions/feishu/src/media.test.ts | 281 - extensions/feishu/src/media.ts | 455 - extensions/feishu/src/mention.ts | 133 - extensions/feishu/src/monitor.ts | 397 - .../src/monitor.webhook-security.test.ts | 174 - extensions/feishu/src/onboarding.ts | 359 - extensions/feishu/src/outbound.ts | 55 - extensions/feishu/src/perm-schema.ts | 52 - extensions/feishu/src/perm.ts | 173 - extensions/feishu/src/policy.ts | 84 - extensions/feishu/src/probe.ts | 44 - extensions/feishu/src/reactions.ts | 160 - .../feishu/src/reply-dispatcher.test.ts | 116 - extensions/feishu/src/reply-dispatcher.ts | 239 - extensions/feishu/src/runtime.ts | 14 - extensions/feishu/src/send-result.ts | 29 - extensions/feishu/src/send.ts | 335 - extensions/feishu/src/streaming-card.ts | 223 - extensions/feishu/src/targets.test.ts | 16 - extensions/feishu/src/targets.ts | 78 - extensions/feishu/src/tools-config.ts | 21 - extensions/feishu/src/types.ts | 81 - extensions/feishu/src/typing.ts | 80 - extensions/feishu/src/wiki-schema.ts | 55 - extensions/feishu/src/wiki.ts | 232 - extensions/google-antigravity-auth/README.md | 24 - extensions/google-antigravity-auth/index.ts | 424 - .../openclaw.plugin.json | 9 - .../google-antigravity-auth/package.json | 15 - extensions/google-gemini-cli-auth/README.md | 35 - extensions/google-gemini-cli-auth/index.ts | 75 - .../google-gemini-cli-auth/oauth.test.ts | 162 - extensions/google-gemini-cli-auth/oauth.ts | 639 - .../openclaw.plugin.json | 9 - .../google-gemini-cli-auth/package.json | 15 - extensions/googlechat/index.ts | 19 - extensions/googlechat/openclaw.plugin.json | 9 - extensions/googlechat/package.json | 40 - extensions/googlechat/src/accounts.ts | 147 - extensions/googlechat/src/actions.ts | 173 - extensions/googlechat/src/api.test.ts | 61 - extensions/googlechat/src/api.ts | 282 - extensions/googlechat/src/auth.ts | 137 - extensions/googlechat/src/channel.ts | 570 - extensions/googlechat/src/monitor.test.ts | 22 - extensions/googlechat/src/monitor.ts | 940 - .../src/monitor.webhook-routing.test.ts | 138 - extensions/googlechat/src/onboarding.ts | 270 - .../googlechat/src/resolve-target.test.ts | 106 - extensions/googlechat/src/runtime.ts | 14 - extensions/googlechat/src/targets.test.ts | 32 - extensions/googlechat/src/targets.ts | 65 - extensions/googlechat/src/types.config.ts | 3 - extensions/googlechat/src/types.ts | 73 - extensions/imessage/index.ts | 17 - extensions/imessage/openclaw.plugin.json | 9 - extensions/imessage/package.json | 15 - .../imessage/src/channel.outbound.test.ts | 66 - extensions/imessage/src/channel.ts | 298 - extensions/imessage/src/runtime.ts | 14 - extensions/irc/index.ts | 17 - extensions/irc/openclaw.plugin.json | 9 - extensions/irc/package.json | 14 - extensions/irc/src/accounts.ts | 268 - extensions/irc/src/channel.ts | 370 - extensions/irc/src/client.test.ts | 43 - extensions/irc/src/client.ts | 439 - extensions/irc/src/config-schema.test.ts | 27 - extensions/irc/src/config-schema.ts | 97 - extensions/irc/src/connect-options.ts | 30 - extensions/irc/src/control-chars.ts | 22 - extensions/irc/src/inbound.ts | 337 - extensions/irc/src/monitor.test.ts | 43 - extensions/irc/src/monitor.ts | 147 - extensions/irc/src/normalize.test.ts | 46 - extensions/irc/src/normalize.ts | 117 - extensions/irc/src/onboarding.test.ts | 128 - extensions/irc/src/onboarding.ts | 479 - extensions/irc/src/policy.test.ts | 132 - extensions/irc/src/policy.ts | 157 - extensions/irc/src/probe.ts | 53 - extensions/irc/src/protocol.test.ts | 44 - extensions/irc/src/protocol.ts | 169 - extensions/irc/src/runtime.ts | 14 - extensions/irc/src/send.ts | 88 - extensions/irc/src/types.ts | 94 - extensions/line/index.ts | 19 - extensions/line/openclaw.plugin.json | 9 - extensions/line/package.json | 30 - extensions/line/src/card-command.ts | 344 - extensions/line/src/channel.logout.test.ts | 138 - .../line/src/channel.sendPayload.test.ts | 312 - extensions/line/src/channel.startup.test.ts | 133 - extensions/line/src/channel.ts | 801 - extensions/line/src/runtime.ts | 14 - extensions/llm-task/README.md | 97 - extensions/llm-task/index.ts | 6 - extensions/llm-task/openclaw.plugin.json | 21 - extensions/llm-task/package.json | 15 - extensions/llm-task/src/llm-task-tool.test.ts | 138 - extensions/llm-task/src/llm-task-tool.ts | 249 - extensions/lobster/README.md | 75 - extensions/lobster/SKILL.md | 97 - extensions/lobster/index.ts | 18 - extensions/lobster/openclaw.plugin.json | 10 - extensions/lobster/package.json | 14 - extensions/lobster/src/lobster-tool.test.ts | 345 - extensions/lobster/src/lobster-tool.ts | 266 - extensions/lobster/src/windows-spawn.test.ts | 148 - extensions/lobster/src/windows-spawn.ts | 193 - extensions/matrix/CHANGELOG.md | 20 - extensions/matrix/index.ts | 17 - extensions/matrix/openclaw.plugin.json | 9 - extensions/matrix/package.json | 36 - extensions/matrix/src/actions.ts | 195 - .../matrix/src/channel.directory.test.ts | 154 - extensions/matrix/src/channel.ts | 480 - extensions/matrix/src/config-schema.ts | 63 - extensions/matrix/src/directory-live.test.ts | 74 - extensions/matrix/src/directory-live.ts | 208 - extensions/matrix/src/group-mentions.ts | 52 - extensions/matrix/src/matrix/accounts.test.ts | 82 - extensions/matrix/src/matrix/accounts.ts | 137 - extensions/matrix/src/matrix/actions.ts | 15 - .../matrix/src/matrix/actions/client.ts | 47 - .../matrix/src/matrix/actions/limits.test.ts | 15 - .../matrix/src/matrix/actions/limits.ts | 6 - .../matrix/src/matrix/actions/messages.ts | 126 - .../matrix/src/matrix/actions/pins.test.ts | 74 - extensions/matrix/src/matrix/actions/pins.ts | 84 - .../src/matrix/actions/reactions.test.ts | 109 - .../matrix/src/matrix/actions/reactions.ts | 102 - extensions/matrix/src/matrix/actions/room.ts | 85 - .../matrix/src/matrix/actions/summary.ts | 75 - extensions/matrix/src/matrix/actions/types.ts | 85 - extensions/matrix/src/matrix/active-client.ts | 32 - .../matrix/src/matrix/client-bootstrap.ts | 39 - extensions/matrix/src/matrix/client.test.ts | 56 - extensions/matrix/src/matrix/client.ts | 14 - extensions/matrix/src/matrix/client/config.ts | 219 - .../matrix/src/matrix/client/create-client.ts | 123 - .../matrix/src/matrix/client/logging.ts | 36 - .../matrix/src/matrix/client/runtime.ts | 4 - extensions/matrix/src/matrix/client/shared.ts | 201 - .../matrix/src/matrix/client/storage.ts | 131 - extensions/matrix/src/matrix/client/types.ts | 34 - extensions/matrix/src/matrix/credentials.ts | 125 - extensions/matrix/src/matrix/deps.ts | 140 - extensions/matrix/src/matrix/format.test.ts | 33 - extensions/matrix/src/matrix/format.ts | 22 - extensions/matrix/src/matrix/index.ts | 11 - .../src/matrix/monitor/allowlist.test.ts | 45 - .../matrix/src/matrix/monitor/allowlist.ts | 103 - .../matrix/src/matrix/monitor/auto-join.ts | 71 - .../matrix/src/matrix/monitor/direct.ts | 104 - .../matrix/src/matrix/monitor/events.ts | 102 - .../matrix/src/matrix/monitor/handler.ts | 702 - extensions/matrix/src/matrix/monitor/index.ts | 345 - .../matrix/src/matrix/monitor/location.ts | 100 - .../matrix/src/matrix/monitor/media.test.ts | 86 - extensions/matrix/src/matrix/monitor/media.ts | 118 - .../src/matrix/monitor/mentions.test.ts | 154 - .../matrix/src/matrix/monitor/mentions.ts | 62 - .../matrix/src/matrix/monitor/replies.test.ts | 132 - .../matrix/src/matrix/monitor/replies.ts | 100 - .../matrix/src/matrix/monitor/room-info.ts | 55 - .../matrix/src/matrix/monitor/rooms.test.ts | 39 - extensions/matrix/src/matrix/monitor/rooms.ts | 47 - .../matrix/src/matrix/monitor/threads.ts | 68 - extensions/matrix/src/matrix/monitor/types.ts | 39 - .../matrix/src/matrix/poll-types.test.ts | 21 - extensions/matrix/src/matrix/poll-types.ts | 167 - extensions/matrix/src/matrix/probe.ts | 69 - extensions/matrix/src/matrix/send.test.ts | 238 - extensions/matrix/src/matrix/send.ts | 262 - extensions/matrix/src/matrix/send/client.ts | 97 - .../matrix/src/matrix/send/formatting.ts | 93 - extensions/matrix/src/matrix/send/media.ts | 230 - .../matrix/src/matrix/send/targets.test.ts | 98 - extensions/matrix/src/matrix/send/targets.ts | 150 - extensions/matrix/src/matrix/send/types.ts | 109 - extensions/matrix/src/onboarding.ts | 446 - extensions/matrix/src/outbound.ts | 55 - extensions/matrix/src/resolve-targets.test.ts | 67 - extensions/matrix/src/resolve-targets.ts | 126 - extensions/matrix/src/runtime.ts | 14 - extensions/matrix/src/tool-actions.ts | 164 - extensions/matrix/src/types.ts | 116 - extensions/mattermost/index.ts | 17 - extensions/mattermost/openclaw.plugin.json | 9 - extensions/mattermost/package.json | 28 - extensions/mattermost/src/channel.test.ts | 235 - extensions/mattermost/src/channel.ts | 433 - extensions/mattermost/src/config-schema.ts | 61 - extensions/mattermost/src/group-mentions.ts | 15 - .../mattermost/src/mattermost/accounts.ts | 128 - .../mattermost/src/mattermost/client.test.ts | 19 - .../mattermost/src/mattermost/client.ts | 230 - extensions/mattermost/src/mattermost/index.ts | 9 - .../src/mattermost/monitor-helpers.ts | 93 - .../src/mattermost/monitor-onchar.ts | 25 - .../src/mattermost/monitor-websocket.test.ts | 232 - .../src/mattermost/monitor-websocket.ts | 221 - .../mattermost/src/mattermost/monitor.ts | 1037 -- extensions/mattermost/src/mattermost/probe.ts | 73 - .../src/mattermost/reactions.test-helpers.ts | 83 - .../src/mattermost/reactions.test.ts | 103 - .../mattermost/src/mattermost/reactions.ts | 124 - .../src/mattermost/reconnect.test.ts | 192 - .../mattermost/src/mattermost/reconnect.ts | 103 - extensions/mattermost/src/mattermost/send.ts | 231 - extensions/mattermost/src/normalize.ts | 46 - .../mattermost/src/onboarding-helpers.ts | 1 - extensions/mattermost/src/onboarding.ts | 186 - extensions/mattermost/src/runtime.ts | 14 - extensions/mattermost/src/types.ts | 57 - extensions/memory-core/index.ts | 38 - extensions/memory-core/openclaw.plugin.json | 9 - extensions/memory-core/package.json | 18 - extensions/memory-lancedb/config.ts | 161 - extensions/memory-lancedb/index.test.ts | 330 - extensions/memory-lancedb/index.ts | 670 - .../memory-lancedb/openclaw.plugin.json | 71 - extensions/memory-lancedb/package.json | 20 - extensions/minimax-portal-auth/README.md | 33 - extensions/minimax-portal-auth/index.ts | 161 - extensions/minimax-portal-auth/oauth.ts | 247 - .../minimax-portal-auth/openclaw.plugin.json | 9 - extensions/minimax-portal-auth/package.json | 15 - extensions/msteams/CHANGELOG.md | 23 - extensions/msteams/index.ts | 17 - extensions/msteams/openclaw.plugin.json | 9 - extensions/msteams/package.json | 35 - extensions/msteams/src/attachments.test.ts | 560 - extensions/msteams/src/attachments.ts | 18 - .../msteams/src/attachments/download.ts | 278 - extensions/msteams/src/attachments/graph.ts | 374 - extensions/msteams/src/attachments/html.ts | 90 - extensions/msteams/src/attachments/payload.ts | 22 - .../msteams/src/attachments/remote-media.ts | 42 - extensions/msteams/src/attachments/shared.ts | 304 - extensions/msteams/src/attachments/types.ts | 37 - .../msteams/src/channel.directory.test.ts | 66 - extensions/msteams/src/channel.ts | 454 - .../msteams/src/conversation-store-fs.test.ts | 75 - .../msteams/src/conversation-store-fs.ts | 165 - .../msteams/src/conversation-store-memory.ts | 47 - extensions/msteams/src/conversation-store.ts | 41 - extensions/msteams/src/directory-live.ts | 126 - extensions/msteams/src/errors.test.ts | 45 - extensions/msteams/src/errors.ts | 190 - .../msteams/src/file-consent-helpers.test.ts | 243 - .../msteams/src/file-consent-helpers.ts | 73 - extensions/msteams/src/file-consent.ts | 126 - extensions/msteams/src/file-lock.ts | 1 - extensions/msteams/src/graph-chat.ts | 53 - extensions/msteams/src/graph-upload.ts | 452 - extensions/msteams/src/graph.ts | 92 - extensions/msteams/src/inbound.test.ts | 66 - extensions/msteams/src/inbound.ts | 48 - extensions/msteams/src/index.ts | 4 - extensions/msteams/src/media-helpers.test.ts | 202 - extensions/msteams/src/media-helpers.ts | 105 - extensions/msteams/src/mentions.test.ts | 235 - extensions/msteams/src/mentions.ts | 114 - extensions/msteams/src/messenger.test.ts | 335 - extensions/msteams/src/messenger.ts | 495 - extensions/msteams/src/monitor-handler.ts | 162 - .../src/monitor-handler/inbound-media.ts | 128 - .../src/monitor-handler/message-handler.ts | 653 - extensions/msteams/src/monitor-types.ts | 5 - extensions/msteams/src/monitor.ts | 305 - extensions/msteams/src/onboarding.ts | 406 - extensions/msteams/src/outbound.ts | 46 - extensions/msteams/src/pending-uploads.ts | 89 - extensions/msteams/src/policy.test.ts | 209 - extensions/msteams/src/policy.ts | 257 - extensions/msteams/src/polls-store-memory.ts | 32 - extensions/msteams/src/polls-store.test.ts | 38 - extensions/msteams/src/polls.test.ts | 59 - extensions/msteams/src/polls.ts | 315 - extensions/msteams/src/probe.test.ts | 58 - extensions/msteams/src/probe.ts | 105 - extensions/msteams/src/reply-dispatcher.ts | 132 - extensions/msteams/src/resolve-allowlist.ts | 216 - extensions/msteams/src/runtime.ts | 14 - extensions/msteams/src/sdk-types.ts | 19 - extensions/msteams/src/sdk.ts | 33 - extensions/msteams/src/send-context.ts | 164 - extensions/msteams/src/send.ts | 530 - .../msteams/src/sent-message-cache.test.ts | 15 - extensions/msteams/src/sent-message-cache.ts | 44 - extensions/msteams/src/storage.ts | 25 - extensions/msteams/src/store-fs.ts | 44 - extensions/msteams/src/test-runtime.ts | 16 - extensions/msteams/src/token.ts | 19 - extensions/nextcloud-talk/index.ts | 17 - .../nextcloud-talk/openclaw.plugin.json | 9 - extensions/nextcloud-talk/package.json | 33 - extensions/nextcloud-talk/src/accounts.ts | 170 - extensions/nextcloud-talk/src/channel.ts | 409 - .../nextcloud-talk/src/config-schema.ts | 79 - extensions/nextcloud-talk/src/format.ts | 79 - extensions/nextcloud-talk/src/inbound.ts | 339 - .../src/monitor.read-body.test.ts | 16 - extensions/nextcloud-talk/src/monitor.ts | 274 - extensions/nextcloud-talk/src/normalize.ts | 39 - extensions/nextcloud-talk/src/onboarding.ts | 349 - extensions/nextcloud-talk/src/policy.test.ts | 33 - extensions/nextcloud-talk/src/policy.ts | 180 - extensions/nextcloud-talk/src/room-info.ts | 125 - extensions/nextcloud-talk/src/runtime.ts | 14 - extensions/nextcloud-talk/src/send.ts | 215 - extensions/nextcloud-talk/src/signature.ts | 72 - extensions/nextcloud-talk/src/types.ts | 184 - extensions/nostr/CHANGELOG.md | 32 - extensions/nostr/README.md | 136 - extensions/nostr/index.ts | 68 - extensions/nostr/openclaw.plugin.json | 9 - extensions/nostr/package.json | 33 - extensions/nostr/src/channel.test.ts | 151 - extensions/nostr/src/channel.ts | 345 - extensions/nostr/src/config-schema.ts | 90 - extensions/nostr/src/metrics.ts | 458 - extensions/nostr/src/nostr-bus.fuzz.test.ts | 533 - .../nostr/src/nostr-bus.integration.test.ts | 448 - extensions/nostr/src/nostr-bus.test.ts | 199 - extensions/nostr/src/nostr-bus.ts | 719 - .../nostr/src/nostr-profile-http.test.ts | 455 - extensions/nostr/src/nostr-profile-http.ts | 519 - .../nostr/src/nostr-profile-import.test.ts | 119 - extensions/nostr/src/nostr-profile-import.ts | 262 - .../nostr/src/nostr-profile.fuzz.test.ts | 480 - extensions/nostr/src/nostr-profile.test.ts | 410 - extensions/nostr/src/nostr-profile.ts | 277 - .../nostr/src/nostr-state-store.test.ts | 133 - extensions/nostr/src/nostr-state-store.ts | 226 - extensions/nostr/src/runtime.ts | 14 - extensions/nostr/src/seen-tracker.ts | 289 - extensions/nostr/src/types.test.ts | 157 - extensions/nostr/src/types.ts | 101 - extensions/nostr/test/setup.ts | 5 - extensions/open-prose/README.md | 25 - extensions/open-prose/index.ts | 5 - extensions/open-prose/openclaw.plugin.json | 11 - extensions/open-prose/package.json | 15 - extensions/open-prose/skills/prose/LICENSE | 21 - extensions/open-prose/skills/prose/SKILL.md | 323 - .../open-prose/skills/prose/alt-borges.md | 141 - .../skills/prose/alts/arabian-nights.md | 358 - .../open-prose/skills/prose/alts/borges.md | 360 - .../open-prose/skills/prose/alts/folk.md | 322 - .../open-prose/skills/prose/alts/homer.md | 346 - .../open-prose/skills/prose/alts/kafka.md | 373 - .../open-prose/skills/prose/compiler.md | 2971 ---- .../prose/examples/01-hello-world.prose | 4 - .../examples/02-research-and-summarize.prose | 6 - .../prose/examples/03-code-review.prose | 17 - .../prose/examples/04-write-and-refine.prose | 14 - .../prose/examples/05-debug-issue.prose | 20 - .../prose/examples/06-explain-codebase.prose | 17 - .../skills/prose/examples/07-refactor.prose | 20 - .../skills/prose/examples/08-blog-post.prose | 20 - .../examples/09-research-with-agents.prose | 25 - .../examples/10-code-review-agents.prose | 32 - .../examples/11-skills-and-imports.prose | 27 - .../12-secure-agent-permissions.prose | 43 - .../examples/13-variables-and-context.prose | 51 - .../examples/14-composition-blocks.prose | 48 - .../prose/examples/15-inline-sequences.prose | 23 - .../prose/examples/16-parallel-reviews.prose | 19 - .../prose/examples/17-parallel-research.prose | 19 - .../18-mixed-parallel-sequential.prose | 36 - .../prose/examples/19-advanced-parallel.prose | 71 - .../prose/examples/20-fixed-loops.prose | 20 - .../examples/21-pipeline-operations.prose | 35 - .../prose/examples/22-error-handling.prose | 51 - .../examples/23-retry-with-backoff.prose | 63 - .../prose/examples/24-choice-blocks.prose | 86 - .../prose/examples/25-conditionals.prose | 114 - .../examples/26-parameterized-blocks.prose | 100 - .../examples/27-string-interpolation.prose | 105 - .../examples/28-automated-pr-review.prose | 37 - .../skills/prose/examples/28-gas-town.prose | 1572 -- .../prose/examples/29-captains-chair.prose | 218 - .../examples/30-captains-chair-simple.prose | 42 - .../31-captains-chair-with-memory.prose | 145 - .../prose/examples/33-pr-review-autofix.prose | 168 - .../prose/examples/34-content-pipeline.prose | 204 - .../prose/examples/35-feature-factory.prose | 296 - .../skills/prose/examples/36-bug-hunter.prose | 237 - .../skills/prose/examples/37-the-forge.prose | 1474 -- .../skills/prose/examples/38-skill-scan.prose | 455 - .../examples/39-architect-by-simulation.prose | 277 - .../prose/examples/40-rlm-self-refine.prose | 32 - .../examples/41-rlm-divide-conquer.prose | 38 - .../examples/42-rlm-filter-recurse.prose | 46 - .../prose/examples/43-rlm-pairwise.prose | 50 - .../examples/44-run-endpoint-ux-test.prose | 261 - .../prose/examples/45-plugin-release.prose | 159 - ...un-endpoint-ux-test-with-remediation.prose | 637 - .../46-run-endpoint-ux-test-fast.prose | 148 - .../examples/46-workflow-crystallizer.prose | 225 - .../47-language-self-improvement.prose | 356 - .../prose/examples/48-habit-miner.prose | 445 - .../examples/49-prose-run-retrospective.prose | 210 - .../skills/prose/examples/README.md | 391 - .../skills/prose/examples/roadmap/README.md | 22 - .../roadmap/iterative-refinement.prose | 20 - .../examples/roadmap/parallel-review.prose | 18 - .../examples/roadmap/simple-pipeline.prose | 17 - .../roadmap/syntax/open-prose-syntax.prose | 223 - .../skills/prose/guidance/antipatterns.md | 951 -- .../skills/prose/guidance/patterns.md | 700 - .../skills/prose/guidance/system-prompt.md | 180 - extensions/open-prose/skills/prose/help.md | 144 - .../open-prose/skills/prose/lib/README.md | 108 - .../skills/prose/lib/calibrator.prose | 215 - .../skills/prose/lib/cost-analyzer.prose | 174 - .../skills/prose/lib/error-forensics.prose | 250 - .../skills/prose/lib/inspector.prose | 196 - .../skills/prose/lib/profiler.prose | 460 - .../skills/prose/lib/program-improver.prose | 275 - .../skills/prose/lib/project-memory.prose | 118 - .../skills/prose/lib/user-memory.prose | 93 - .../skills/prose/lib/vm-improver.prose | 243 - .../skills/prose/primitives/session.md | 593 - extensions/open-prose/skills/prose/prose.md | 1237 -- .../skills/prose/state/filesystem.md | 498 - .../skills/prose/state/in-context.md | 384 - .../open-prose/skills/prose/state/postgres.md | 880 - .../open-prose/skills/prose/state/sqlite.md | 574 - extensions/phone-control/index.ts | 421 - extensions/phone-control/openclaw.plugin.json | 10 - extensions/qwen-portal-auth/README.md | 24 - extensions/qwen-portal-auth/index.ts | 134 - extensions/qwen-portal-auth/oauth.ts | 190 - .../qwen-portal-auth/openclaw.plugin.json | 9 - .../shared/resolve-target-test-helpers.ts | 66 - extensions/signal/index.ts | 17 - extensions/signal/openclaw.plugin.json | 9 - extensions/signal/package.json | 15 - extensions/signal/src/channel.ts | 302 - extensions/signal/src/runtime.ts | 14 - extensions/slack/index.ts | 17 - extensions/slack/openclaw.plugin.json | 9 - extensions/slack/package.json | 15 - extensions/slack/src/channel.ts | 412 - extensions/slack/src/runtime.ts | 14 - extensions/synology-chat/index.ts | 17 - extensions/synology-chat/openclaw.plugin.json | 9 - extensions/synology-chat/package.json | 29 - extensions/synology-chat/src/accounts.test.ts | 133 - extensions/synology-chat/src/accounts.ts | 87 - extensions/synology-chat/src/channel.test.ts | 339 - extensions/synology-chat/src/channel.ts | 323 - extensions/synology-chat/src/client.test.ts | 104 - extensions/synology-chat/src/client.ts | 142 - extensions/synology-chat/src/runtime.ts | 20 - extensions/synology-chat/src/security.test.ts | 98 - extensions/synology-chat/src/security.ts | 112 - extensions/synology-chat/src/types.ts | 60 - .../synology-chat/src/webhook-handler.test.ts | 263 - .../synology-chat/src/webhook-handler.ts | 217 - extensions/talk-voice/index.ts | 150 - extensions/talk-voice/openclaw.plugin.json | 10 - extensions/telegram/index.ts | 17 - extensions/telegram/openclaw.plugin.json | 9 - extensions/telegram/package.json | 15 - extensions/telegram/src/channel.test.ts | 125 - extensions/telegram/src/channel.ts | 560 - extensions/telegram/src/runtime.ts | 14 - extensions/thread-ownership/index.test.ts | 180 - extensions/thread-ownership/index.ts | 133 - .../thread-ownership/openclaw.plugin.json | 28 - extensions/tlon/README.md | 5 - extensions/tlon/index.ts | 17 - extensions/tlon/openclaw.plugin.json | 9 - extensions/tlon/package.json | 32 - extensions/tlon/src/account-fields.ts | 25 - extensions/tlon/src/channel.ts | 384 - extensions/tlon/src/config-schema.test.ts | 31 - extensions/tlon/src/config-schema.ts | 47 - extensions/tlon/src/monitor/discovery.ts | 78 - extensions/tlon/src/monitor/history.ts | 92 - extensions/tlon/src/monitor/index.ts | 603 - .../src/monitor/processed-messages.test.ts | 23 - .../tlon/src/monitor/processed-messages.ts | 46 - extensions/tlon/src/monitor/utils.ts | 106 - extensions/tlon/src/onboarding.ts | 229 - extensions/tlon/src/runtime.ts | 14 - extensions/tlon/src/targets.ts | 89 - extensions/tlon/src/types.ts | 99 - extensions/tlon/src/urbit/auth.ssrf.test.ts | 44 - extensions/tlon/src/urbit/auth.ts | 48 - extensions/tlon/src/urbit/base-url.test.ts | 41 - extensions/tlon/src/urbit/base-url.ts | 57 - extensions/tlon/src/urbit/channel-client.ts | 157 - extensions/tlon/src/urbit/channel-ops.ts | 164 - extensions/tlon/src/urbit/context.ts | 47 - extensions/tlon/src/urbit/errors.ts | 51 - extensions/tlon/src/urbit/fetch.ts | 39 - extensions/tlon/src/urbit/send.test.ts | 38 - extensions/tlon/src/urbit/send.ts | 131 - extensions/tlon/src/urbit/sse-client.test.ts | 44 - extensions/tlon/src/urbit/sse-client.ts | 430 - extensions/twitch/CHANGELOG.md | 27 - extensions/twitch/README.md | 89 - extensions/twitch/index.ts | 20 - extensions/twitch/openclaw.plugin.json | 9 - extensions/twitch/package.json | 20 - extensions/twitch/src/access-control.test.ts | 491 - extensions/twitch/src/access-control.ts | 166 - extensions/twitch/src/actions.ts | 174 - .../twitch/src/client-manager-registry.ts | 115 - extensions/twitch/src/config-schema.ts | 84 - extensions/twitch/src/config.test.ts | 87 - extensions/twitch/src/config.ts | 116 - extensions/twitch/src/monitor.ts | 273 - extensions/twitch/src/onboarding.test.ts | 316 - extensions/twitch/src/onboarding.ts | 417 - extensions/twitch/src/outbound.test.ts | 403 - extensions/twitch/src/outbound.ts | 187 - extensions/twitch/src/plugin.test.ts | 39 - extensions/twitch/src/plugin.ts | 274 - extensions/twitch/src/probe.test.ts | 196 - extensions/twitch/src/probe.ts | 119 - extensions/twitch/src/resolver.ts | 137 - extensions/twitch/src/runtime.ts | 14 - extensions/twitch/src/send.test.ts | 276 - extensions/twitch/src/send.ts | 136 - extensions/twitch/src/status.test.ts | 270 - extensions/twitch/src/status.ts | 179 - extensions/twitch/src/test-fixtures.ts | 30 - extensions/twitch/src/token.test.ts | 171 - extensions/twitch/src/token.ts | 91 - extensions/twitch/src/twitch-client.test.ts | 589 - extensions/twitch/src/twitch-client.ts | 277 - extensions/twitch/src/types.ts | 143 - extensions/twitch/src/utils/markdown.ts | 98 - extensions/twitch/src/utils/twitch.ts | 78 - extensions/twitch/test/setup.ts | 7 - extensions/voice-call/CHANGELOG.md | 37 - extensions/voice-call/README.md | 168 - extensions/voice-call/index.ts | 512 - extensions/voice-call/openclaw.plugin.json | 559 - extensions/voice-call/package.json | 19 - extensions/voice-call/src/allowlist.ts | 19 - extensions/voice-call/src/cli.ts | 367 - extensions/voice-call/src/config.test.ts | 204 - extensions/voice-call/src/config.ts | 462 - extensions/voice-call/src/core-bridge.ts | 159 - extensions/voice-call/src/manager.test.ts | 485 - extensions/voice-call/src/manager.ts | 209 - extensions/voice-call/src/manager/context.ts | 40 - .../voice-call/src/manager/events.test.ts | 253 - extensions/voice-call/src/manager/events.ts | 229 - extensions/voice-call/src/manager/lookup.ts | 35 - extensions/voice-call/src/manager/outbound.ts | 340 - extensions/voice-call/src/manager/state.ts | 48 - extensions/voice-call/src/manager/store.ts | 94 - extensions/voice-call/src/manager/timers.ts | 103 - extensions/voice-call/src/manager/twiml.ts | 9 - .../voice-call/src/media-stream.test.ts | 96 - extensions/voice-call/src/media-stream.ts | 417 - extensions/voice-call/src/providers/base.ts | 67 - extensions/voice-call/src/providers/index.ts | 10 - extensions/voice-call/src/providers/mock.ts | 165 - .../voice-call/src/providers/plivo.test.ts | 27 - extensions/voice-call/src/providers/plivo.ts | 515 - .../src/providers/stt-openai-realtime.ts | 311 - .../voice-call/src/providers/telnyx.test.ts | 106 - extensions/voice-call/src/providers/telnyx.ts | 318 - .../voice-call/src/providers/tts-openai.ts | 259 - .../voice-call/src/providers/twilio.test.ts | 62 - extensions/voice-call/src/providers/twilio.ts | 637 - .../voice-call/src/providers/twilio/api.ts | 42 - .../src/providers/twilio/webhook.ts | 32 - .../voice-call/src/response-generator.ts | 158 - extensions/voice-call/src/runtime.ts | 217 - extensions/voice-call/src/telephony-audio.ts | 90 - .../voice-call/src/telephony-tts.test.ts | 75 - extensions/voice-call/src/telephony-tts.ts | 106 - extensions/voice-call/src/tunnel.ts | 314 - extensions/voice-call/src/types.ts | 272 - extensions/voice-call/src/utils.ts | 14 - extensions/voice-call/src/voice-mapping.ts | 67 - .../voice-call/src/webhook-security.test.ts | 409 - extensions/voice-call/src/webhook-security.ts | 788 - extensions/voice-call/src/webhook.test.ts | 118 - extensions/voice-call/src/webhook.ts | 540 - extensions/whatsapp/index.ts | 17 - extensions/whatsapp/openclaw.plugin.json | 9 - extensions/whatsapp/package.json | 15 - extensions/whatsapp/src/channel.ts | 465 - .../whatsapp/src/resolve-target.test.ts | 170 - extensions/whatsapp/src/runtime.ts | 14 - extensions/zalo/CHANGELOG.md | 17 - extensions/zalo/README.md | 50 - extensions/zalo/index.ts | 19 - extensions/zalo/openclaw.plugin.json | 9 - extensions/zalo/package.json | 35 - extensions/zalo/src/accounts.ts | 82 - extensions/zalo/src/actions.ts | 67 - extensions/zalo/src/api.ts | 208 - extensions/zalo/src/channel.directory.test.ts | 53 - extensions/zalo/src/channel.ts | 380 - extensions/zalo/src/config-schema.ts | 25 - extensions/zalo/src/monitor.ts | 835 - extensions/zalo/src/monitor.webhook.test.ts | 307 - extensions/zalo/src/onboarding.ts | 398 - extensions/zalo/src/probe.ts | 45 - extensions/zalo/src/proxy.ts | 24 - extensions/zalo/src/runtime.ts | 14 - extensions/zalo/src/send.ts | 124 - extensions/zalo/src/status-issues.ts | 53 - extensions/zalo/src/token.ts | 62 - extensions/zalo/src/types.ts | 44 - extensions/zalouser/CHANGELOG.md | 19 - extensions/zalouser/README.md | 225 - extensions/zalouser/index.ts | 31 - extensions/zalouser/openclaw.plugin.json | 9 - extensions/zalouser/package.json | 35 - extensions/zalouser/src/accounts.ts | 135 - extensions/zalouser/src/channel.test.ts | 18 - extensions/zalouser/src/channel.ts | 652 - extensions/zalouser/src/config-schema.ts | 28 - extensions/zalouser/src/monitor.ts | 605 - extensions/zalouser/src/onboarding.ts | 501 - extensions/zalouser/src/probe.ts | 27 - extensions/zalouser/src/runtime.ts | 14 - extensions/zalouser/src/send.ts | 160 - extensions/zalouser/src/status-issues.test.ts | 57 - extensions/zalouser/src/status-issues.ts | 89 - extensions/zalouser/src/tool.ts | 166 - extensions/zalouser/src/types.ts | 110 - extensions/zalouser/src/zca.ts | 198 - fly.private.toml | 39 - fly.toml | 34 - git-hooks/pre-commit | 55 - openclaw.podman.env | 24 - packages/clawdbot/index.js | 1 - packages/clawdbot/package.json | 16 - packages/clawdbot/scripts/postinstall.js | 1 - packages/moltbot/index.js | 1 - packages/moltbot/package.json | 16 - packages/moltbot/scripts/postinstall.js | 1 - patches/.gitkeep | 0 pnpm-lock.yaml | 3352 +--- pnpm-workspace.yaml | 3 - render.yaml | 21 - scripts/auth-monitor.sh | 89 - scripts/bench-model.ts | 146 - scripts/build-and-run-mac.sh | 18 - scripts/build-docs-list.mjs | 14 - scripts/build_icon.sh | 59 - scripts/bundle-a2ui.sh | 95 - scripts/changelog-to-html.sh | 91 - ...ck-composite-action-input-interpolation.py | 81 - scripts/check-ts-max-loc.ts | 80 - scripts/claude-auth-status.sh | 280 - scripts/clawlog.sh | 309 - scripts/clawtributors-map.json | 40 - scripts/codesign-mac-app.sh | 289 - scripts/codespell-dictionary.txt | 3 - scripts/codespell-ignore.txt | 9 - scripts/committer | 117 - scripts/create-dmg.sh | 176 - scripts/cron_usage_report.ts | 273 - scripts/debug-claude-usage.ts | 391 - scripts/dev/gateway-smoke.ts | 75 - scripts/dev/gateway-ws-client.ts | 132 - scripts/dev/ios-node-e2e.ts | 283 - scripts/dev/ios-pull-gateway-log.sh | 17 - scripts/dev/test-device-pair-telegram.ts | 62 - scripts/docker/cleanup-smoke/Dockerfile | 19 - scripts/docker/cleanup-smoke/run.sh | 35 - scripts/docker/install-sh-e2e/Dockerfile | 17 - scripts/docker/install-sh-e2e/run.sh | 535 - scripts/docker/install-sh-nonroot/Dockerfile | 32 - scripts/docker/install-sh-nonroot/run.sh | 66 - scripts/docker/install-sh-smoke/Dockerfile | 24 - scripts/docker/install-sh-smoke/run.sh | 92 - scripts/docs-i18n/doc_mode.go | 272 - scripts/docs-i18n/glossary.go | 29 - scripts/docs-i18n/go.mod | 10 - scripts/docs-i18n/go.sum | 10 - scripts/docs-i18n/html_translate.go | 160 - scripts/docs-i18n/main.go | 273 - scripts/docs-i18n/markdown_segments.go | 131 - scripts/docs-i18n/masking.go | 89 - scripts/docs-i18n/order.go | 37 - scripts/docs-i18n/placeholders.go | 30 - scripts/docs-i18n/process.go | 202 - scripts/docs-i18n/prompt.go | 146 - scripts/docs-i18n/segment.go | 11 - scripts/docs-i18n/tm.go | 132 - scripts/docs-i18n/translator.go | 247 - scripts/docs-i18n/util.go | 81 - scripts/docs-link-audit.mjs | 233 - scripts/docs-list.js | 173 - scripts/docs-spellcheck.sh | 44 - scripts/e2e/Dockerfile | 29 - scripts/e2e/Dockerfile.qr-import | 13 - scripts/e2e/doctor-install-switch-docker.sh | 158 - scripts/e2e/gateway-network-docker.sh | 138 - scripts/e2e/onboard-docker.sh | 564 - scripts/e2e/plugins-docker.sh | 224 - scripts/e2e/qr-import-docker.sh | 11 - scripts/firecrawl-compare.ts | 139 - scripts/ios-configure-signing.sh | 100 - scripts/ios-team-id.sh | 134 - scripts/label-open-issues.ts | 912 - scripts/make_appcast.sh | 69 - scripts/mobile-reauth.sh | 84 - scripts/notarize-mac-artifact.sh | 65 - scripts/package-mac-app.sh | 261 - scripts/package-mac-dist.sh | 93 - scripts/podman/openclaw.container.in | 26 - scripts/pr | 1168 -- scripts/pr-merge | 44 - scripts/pr-prepare | 40 - scripts/pr-review | 13 - scripts/pre-commit/filter-staged-files.mjs | 39 - scripts/pre-commit/run-node-tool.sh | 31 - scripts/protocol-gen-swift.ts | 247 - scripts/protocol-gen.ts | 51 - scripts/readability-basic-compare.ts | 66 - scripts/recover-orphaned-processes.sh | 191 - scripts/release-check.ts | 56 - scripts/repro/tsx-name-repro.ts | 3 - scripts/restart-mac.sh | 269 - scripts/run-node.d.mts | 22 - scripts/run-node.mjs | 263 - scripts/run-openclaw-podman.sh | 211 - scripts/sandbox-browser-entrypoint.sh | 88 - scripts/sandbox-browser-setup.sh | 7 - scripts/sandbox-common-setup.sh | 40 - scripts/sandbox-setup.sh | 7 - scripts/setup-auth-system.sh | 119 - scripts/shell-helpers/README.md | 226 - scripts/shell-helpers/clawdock-helpers.sh | 417 - scripts/sqlite-vec-smoke.mjs | 38 - scripts/standalone-hoist-pnpm.sh | 49 - scripts/sync-labels.ts | 100 - scripts/sync-moonshot-docs.ts | 125 - scripts/sync-plugin-versions.ts | 76 - scripts/systemd/openclaw-auth-monitor.service | 14 - scripts/systemd/openclaw-auth-monitor.timer | 10 - scripts/termux-auth-widget.sh | 81 - scripts/termux-quick-auth.sh | 30 - scripts/termux-sync-widget.sh | 25 - scripts/test-cleanup-docker.sh | 14 - scripts/test-force.ts | 59 - scripts/test-install-sh-docker.sh | 75 - scripts/test-install-sh-e2e-docker.sh | 29 - scripts/test-live-gateway-models-docker.sh | 32 - scripts/test-live-models-docker.sh | 33 - scripts/test-parallel.mjs | 392 - scripts/test-shell-completion.ts | 223 - scripts/ui.js | 203 - scripts/update-clawtributors.ts | 504 - scripts/update-clawtributors.types.ts | 32 - scripts/vitest-slowest.mjs | 160 - scripts/watch-node.d.mts | 14 - scripts/watch-node.mjs | 92 - scripts/write-build-info.ts | 47 - scripts/zai-fallback-repro.ts | 168 - setup-podman.sh | 251 - skills/1password/SKILL.md | 70 - skills/1password/references/cli-examples.md | 29 - skills/1password/references/get-started.md | 17 - skills/apple-notes/SKILL.md | 77 - skills/apple-reminders/SKILL.md | 118 - skills/bear-notes/SKILL.md | 107 - skills/blogwatcher/SKILL.md | 69 - skills/blucli/SKILL.md | 47 - skills/bluebubbles/SKILL.md | 131 - skills/camsnap/SKILL.md | 45 - skills/canvas/SKILL.md | 198 - skills/clawhub/SKILL.md | 77 - skills/coding-agent/SKILL.md | 284 - skills/discord/SKILL.md | 197 - skills/eightctl/SKILL.md | 50 - skills/food-order/SKILL.md | 48 - skills/gemini/SKILL.md | 43 - skills/gh-issues/SKILL.md | 865 - skills/gifgrep/SKILL.md | 79 - skills/github/SKILL.md | 163 - skills/gog/SKILL.md | 116 - skills/goplaces/SKILL.md | 52 - skills/healthcheck/SKILL.md | 245 - skills/himalaya/SKILL.md | 257 - skills/himalaya/references/configuration.md | 184 - .../references/message-composition.md | 199 - skills/imsg/SKILL.md | 122 - skills/mcporter/SKILL.md | 61 - skills/model-usage/SKILL.md | 69 - skills/model-usage/references/codexbar-cli.md | 33 - skills/model-usage/scripts/model_usage.py | 310 - skills/nano-banana-pro/SKILL.md | 58 - .../nano-banana-pro/scripts/generate_image.py | 184 - skills/nano-pdf/SKILL.md | 38 - skills/notion/SKILL.md | 172 - skills/obsidian/SKILL.md | 81 - skills/openai-image-gen/SKILL.md | 89 - skills/openai-image-gen/scripts/gen.py | 240 - skills/openai-whisper-api/SKILL.md | 52 - .../openai-whisper-api/scripts/transcribe.sh | 85 - skills/openai-whisper/SKILL.md | 38 - skills/openhue/SKILL.md | 112 - skills/oracle/SKILL.md | 125 - skills/ordercli/SKILL.md | 78 - skills/peekaboo/SKILL.md | 190 - skills/sag/SKILL.md | 87 - skills/session-logs/SKILL.md | 115 - skills/sherpa-onnx-tts/SKILL.md | 103 - skills/sherpa-onnx-tts/bin/sherpa-onnx-tts | 178 - skills/skill-creator/SKILL.md | 372 - skills/skill-creator/license.txt | 202 - skills/skill-creator/scripts/init_skill.py | 378 - skills/skill-creator/scripts/package_skill.py | 118 - .../skill-creator/scripts/quick_validate.py | 101 - .../scripts/test_package_skill.py | 104 - skills/slack/SKILL.md | 144 - skills/software-engineering/SKILL.md | 96 - skills/songsee/SKILL.md | 49 - skills/sonoscli/SKILL.md | 65 - skills/spotify-player/SKILL.md | 64 - skills/summarize/SKILL.md | 87 - skills/things-mac/SKILL.md | 86 - skills/tmux/SKILL.md | 153 - skills/tmux/scripts/find-sessions.sh | 112 - skills/tmux/scripts/wait-for-text.sh | 83 - skills/trello/SKILL.md | 95 - skills/video-frames/SKILL.md | 46 - skills/video-frames/scripts/frame.sh | 81 - skills/voice-call/SKILL.md | 45 - skills/wacli/SKILL.md | 72 - skills/weather/SKILL.md | 112 - skills/xurl/SKILL.md | 461 - src/channels/chat-type.ts | 18 - src/cli/windows-argv.test.ts | 8 +- src/cli/workspace-seed.ts | 2 +- src/config/paths.ts | 7 +- src/config/types.agent-defaults.ts | 312 - src/config/types.agents.ts | 97 - src/config/types.approvals.ts | 29 - src/config/types.auth.ts | 29 - src/config/types.base.ts | 208 - src/config/types.browser.ts | 63 - src/config/types.channels.ts | 60 - src/config/types.cron.ts | 18 - src/config/types.discord.ts | 289 - src/config/types.gateway.ts | 341 - src/config/types.googlechat.ts | 6 - src/config/types.hooks.ts | 153 - src/config/types.imessage.ts | 87 - src/config/types.irc.ts | 108 - src/config/types.memory.ts | 67 - src/config/types.messages.ts | 176 - src/config/types.models.ts | 67 - src/config/types.msteams.ts | 113 - src/config/types.node-host.ts | 11 - src/config/types.openclaw.ts | 129 - src/config/types.plugins.ts | 42 - src/config/types.queue.ts | 22 - src/config/types.sandbox.ts | 81 - src/config/types.signal.ts | 96 - src/config/types.skills.ts | 45 - src/config/types.slack.ts | 190 - src/config/types.telegram.ts | 202 - src/config/types.tools.ts | 533 - src/config/types.tts.ts | 82 - src/config/types.whatsapp.ts | 156 - src/discord/pluralkit.ts | 7 - src/logging/config.ts | 10 +- src/logging/console.ts | 3 +- src/logging/logger.ts | 3 +- src/logging/redact.ts | 2 +- src/plugins/runtime.ts | 10 - src/test-utils/channel-plugins.ts | 10 - test/appcast.test.ts | 27 - test/evals/README.md | 26 - test/evals/REGRESSION_VERIFICATION_REPORT.md | 72 - test/evals/dataset.ts | 140 - test/evals/graders.test.ts | 43 - test/evals/graders.ts | 203 - test/evals/run-evals.ts | 81 - test/evals/types.ts | 46 - test/evals/vitest.config.ts | 9 - test/fixtures/child-process-bridge/child.js | 11 - .../exec-allowlist-shell-parser-parity.json | 82 - .../fixtures/hooks-install/npm-pack-hooks.tgz | Bin 421 -> 0 bytes test/fixtures/hooks-install/tar-evil-id.tar | Bin 5632 -> 0 bytes test/fixtures/hooks-install/tar-hooks.tar | Bin 5632 -> 0 bytes .../hooks-install/tar-reserved-id.tar | Bin 5632 -> 0 bytes test/fixtures/hooks-install/tar-traversal.tar | Bin 2048 -> 0 bytes test/fixtures/hooks-install/zip-hooks.zip | Bin 961 -> 0 bytes test/fixtures/hooks-install/zip-traversal.zip | Bin 209 -> 0 bytes test/gateway.multi.e2e.test.ts | 398 - test/git-hooks-pre-commit.e2e.test.ts | 48 - test/global-setup.ts | 6 - test/helpers/dispatch-inbound-capture.ts | 18 - test/helpers/envelope-timestamp.ts | 43 - test/helpers/inbound-contract-capture.ts | 31 - test/helpers/inbound-contract.ts | 19 - test/helpers/mock-incoming-request.ts | 27 - test/helpers/normalize-text.ts | 9 - test/helpers/paths.ts | 16 - test/helpers/poll.ts | 25 - test/helpers/temp-home.ts | 129 - test/media-understanding.auto.e2e.test.ts | 197 - test/mocks/baileys.ts | 76 - test/provider-timeout.e2e.test.ts | 230 - test/scripts/ui.test.ts | 35 - test/setup.ts | 226 - test/test-env.ts | 147 - tsconfig.json | 2 +- ui/index.html | 16 - ui/package-lock.json | 441 - ui/package.json | 27 - ui/public/apple-touch-icon.png | Bin 5920 -> 0 bytes ui/public/favicon-32.png | Bin 1015 -> 0 bytes ui/public/favicon.ico | Bin 96542 -> 0 bytes ui/public/favicon.svg | 22 - ui/src/i18n/index.ts | 3 - ui/src/i18n/lib/lit-controller.ts | 22 - ui/src/i18n/lib/translate.ts | 123 - ui/src/i18n/lib/types.ts | 9 - ui/src/i18n/locales/en.ts | 116 - ui/src/i18n/locales/pt-BR.ts | 118 - ui/src/i18n/locales/zh-CN.ts | 115 - ui/src/i18n/locales/zh-TW.ts | 115 - ui/src/i18n/test/translate.test.ts | 31 - ui/src/main.ts | 2 - ui/src/styles.css | 5 - ui/src/styles/base.css | 388 - ui/src/styles/chat.css | 5 - ui/src/styles/chat/grouped.css | 300 - ui/src/styles/chat/layout.css | 456 - ui/src/styles/chat/sidebar.css | 117 - ui/src/styles/chat/text.css | 144 - ui/src/styles/chat/tool-cards.css | 202 - ui/src/styles/components.css | 2151 --- ui/src/styles/config.css | 1446 -- ui/src/styles/layout.css | 621 - ui/src/styles/layout.mobile.css | 374 - ...rm-renderer-flags-unsupported-unions-1.png | Bin 2081 -> 0 bytes ...er-renders-inputs-and-patches-values-1.png | Bin 2081 -> 0 bytes ...ers-union-literals-as-select-options-1.png | Bin 2081 -> 0 bytes ...s-chat-history-to-the-latest-message-1.png | Bin 35014 -> 0 bytes ui/src/ui/app-channels.ts | 279 - ui/src/ui/app-chat.ts | 267 - ui/src/ui/app-defaults.ts | 32 - ui/src/ui/app-events.ts | 5 - ui/src/ui/app-gateway.node.test.ts | 180 - ui/src/ui/app-gateway.ts | 311 - ui/src/ui/app-lifecycle.ts | 104 - ui/src/ui/app-polling.ts | 69 - ui/src/ui/app-render-usage-tab.ts | 273 - ui/src/ui/app-render.helpers.node.test.ts | 216 - ui/src/ui/app-render.helpers.ts | 481 - ui/src/ui/app-render.ts | 967 -- ui/src/ui/app-scroll.test.ts | 251 - ui/src/ui/app-scroll.ts | 179 - ui/src/ui/app-settings.test.ts | 70 - ui/src/ui/app-settings.ts | 429 - ui/src/ui/app-tool-stream.node.test.ts | 139 - ui/src/ui/app-tool-stream.ts | 455 - ui/src/ui/app-view-state.ts | 289 - ui/src/ui/app.ts | 585 - ui/src/ui/assistant-identity.ts | 35 - ui/src/ui/chat-markdown.browser.test.ts | 37 - ui/src/ui/chat/constants.ts | 12 - ui/src/ui/chat/copy-as-markdown.ts | 97 - ui/src/ui/chat/grouped-render.ts | 282 - ui/src/ui/chat/message-extract.test.ts | 45 - ui/src/ui/chat/message-extract.ts | 149 - ui/src/ui/chat/message-normalizer.test.ts | 179 - ui/src/ui/chat/message-normalizer.ts | 101 - ui/src/ui/chat/tool-cards.ts | 156 - ui/src/ui/chat/tool-helpers.test.ts | 141 - ui/src/ui/chat/tool-helpers.ts | 37 - ui/src/ui/components/resizable-divider.ts | 110 - ui/src/ui/config-form.browser.test.ts | 259 - ui/src/ui/contracts/chat-envelope.ts | 49 - ui/src/ui/contracts/control-ui-contract.ts | 8 - ui/src/ui/contracts/device-auth.ts | 30 - ui/src/ui/contracts/format-duration.ts | 55 - ui/src/ui/contracts/format-relative.ts | 49 - ui/src/ui/contracts/gateway-client-info.ts | 85 - ui/src/ui/contracts/gateway-device-auth.ts | 31 - ui/src/ui/contracts/gateway-events.ts | 7 - ui/src/ui/contracts/reasoning-tags.ts | 123 - ui/src/ui/contracts/session-key.ts | 23 - ui/src/ui/contracts/strip-inbound-meta.ts | 134 - ui/src/ui/contracts/tool-display-common.ts | 324 - ui/src/ui/contracts/tool-policy.ts | 112 - ui/src/ui/contracts/update.ts | 5 - ui/src/ui/contracts/usage-aggregates.ts | 63 - ui/src/ui/controllers/agent-files.ts | 126 - ui/src/ui/controllers/agent-identity.ts | 59 - ui/src/ui/controllers/agent-skills.ts | 33 - ui/src/ui/controllers/agents.ts | 37 - ui/src/ui/controllers/assistant-identity.ts | 34 - ui/src/ui/controllers/channels.ts | 94 - ui/src/ui/controllers/channels.types.ts | 15 - ui/src/ui/controllers/chat.test.ts | 216 - ui/src/ui/controllers/chat.ts | 241 - ui/src/ui/controllers/config.test.ts | 295 - ui/src/ui/controllers/config.ts | 219 - ui/src/ui/controllers/config/form-coerce.ts | 160 - .../config/form-utils.node.test.ts | 471 - ui/src/ui/controllers/config/form-utils.ts | 90 - .../controllers/control-ui-bootstrap.test.ts | 82 - ui/src/ui/controllers/control-ui-bootstrap.ts | 49 - ui/src/ui/controllers/cron.test.ts | 130 - ui/src/ui/controllers/cron.ts | 244 - ui/src/ui/controllers/debug.ts | 60 - ui/src/ui/controllers/devices.ts | 159 - ui/src/ui/controllers/exec-approval.ts | 100 - ui/src/ui/controllers/exec-approvals.ts | 170 - ui/src/ui/controllers/logs.ts | 147 - ui/src/ui/controllers/nodes.ts | 32 - ui/src/ui/controllers/presence.ts | 37 - ui/src/ui/controllers/sessions.test.ts | 104 - ui/src/ui/controllers/sessions.ts | 127 - ui/src/ui/controllers/skills.ts | 157 - ui/src/ui/controllers/usage.node.test.ts | 190 - ui/src/ui/controllers/usage.ts | 315 - ui/src/ui/data/moonshot-kimi-k2.ts | 39 - ui/src/ui/device-auth.ts | 95 - ui/src/ui/device-identity.ts | 112 - ui/src/ui/focus-mode.browser.test.ts | 39 - ui/src/ui/format.test.ts | 76 - ui/src/ui/format.ts | 60 - ui/src/ui/gateway.ts | 312 - ui/src/ui/icons.ts | 256 - ui/src/ui/markdown.test.ts | 51 - ui/src/ui/markdown.ts | 142 - ui/src/ui/navigation.browser.test.ts | 188 - ui/src/ui/navigation.test.ts | 187 - ui/src/ui/navigation.ts | 165 - ui/src/ui/presenter.ts | 84 - ui/src/ui/storage.ts | 91 - ui/src/ui/test-helpers/app-mount.ts | 26 - ui/src/ui/text-direction.test.ts | 24 - ui/src/ui/text-direction.ts | 30 - ui/src/ui/theme-transition.ts | 109 - ui/src/ui/theme.ts | 16 - ui/src/ui/tool-display.json | 236 - ui/src/ui/tool-display.ts | 149 - ui/src/ui/types.ts | 568 - ui/src/ui/types/chat-types.ts | 44 - ui/src/ui/ui-types.ts | 36 - ui/src/ui/usage-helpers.node.test.ts | 43 - ui/src/ui/usage-helpers.ts | 321 - ui/src/ui/usage-types.ts | 216 - ui/src/ui/uuid.test.ts | 41 - ui/src/ui/uuid.ts | 57 - ui/src/ui/views/agents-panels-status-files.ts | 505 - ui/src/ui/views/agents-panels-tools-skills.ts | 477 - ui/src/ui/views/agents-utils.ts | 470 - ui/src/ui/views/agents.ts | 489 - ui/src/ui/views/channels.config.ts | 176 - ui/src/ui/views/channels.discord.ts | 65 - ui/src/ui/views/channels.googlechat.ts | 79 - ui/src/ui/views/channels.imessage.ts | 65 - .../ui/views/channels.nostr-profile-form.ts | 321 - ui/src/ui/views/channels.nostr.ts | 237 - ui/src/ui/views/channels.shared.ts | 38 - ui/src/ui/views/channels.signal.ts | 69 - ui/src/ui/views/channels.slack.ts | 65 - ui/src/ui/views/channels.telegram.ts | 120 - ui/src/ui/views/channels.ts | 325 - ui/src/ui/views/channels.types.ts | 62 - ui/src/ui/views/channels.whatsapp.ts | 118 - ui/src/ui/views/chat.test.ts | 205 - ui/src/ui/views/chat.ts | 616 - ui/src/ui/views/config-form.analyze.ts | 208 - ui/src/ui/views/config-form.node.ts | 782 - ui/src/ui/views/config-form.render.ts | 502 - ui/src/ui/views/config-form.shared.ts | 94 - ui/src/ui/views/config-form.ts | 4 - ui/src/ui/views/config.browser.test.ts | 201 - ui/src/ui/views/config.ts | 744 - ui/src/ui/views/cron.test.ts | 225 - ui/src/ui/views/cron.ts | 582 - ui/src/ui/views/debug.ts | 149 - ui/src/ui/views/exec-approval.ts | 89 - ui/src/ui/views/gateway-url-confirmation.ts | 40 - ui/src/ui/views/instances.ts | 89 - ui/src/ui/views/logs.ts | 155 - ui/src/ui/views/markdown-sidebar.ts | 40 - ui/src/ui/views/nodes-exec-approvals.ts | 651 - ui/src/ui/views/nodes.ts | 520 - ui/src/ui/views/overview.ts | 297 - ui/src/ui/views/sessions.test.ts | 81 - ui/src/ui/views/sessions.ts | 321 - ui/src/ui/views/skills-grouping.ts | 40 - ui/src/ui/views/skills-shared.ts | 52 - ui/src/ui/views/skills.ts | 192 - ui/src/ui/views/usage-metrics.ts | 598 - ui/src/ui/views/usage-query.ts | 277 - ui/src/ui/views/usage-render-details.test.ts | 132 - ui/src/ui/views/usage-render-details.ts | 1083 -- ui/src/ui/views/usage-render-overview.ts | 796 - .../views/usage-styles/usageStyles-part1.ts | 701 - .../views/usage-styles/usageStyles-part2.ts | 702 - .../views/usage-styles/usageStyles-part3.ts | 551 - ui/src/ui/views/usage.ts | 844 - ui/src/ui/views/usageStyles.ts | 5 - ui/src/ui/views/usageTypes.ts | 105 - ui/vite.config.ts | 41 - ui/vitest.config.ts | 15 - ui/vitest.node.config.ts | 10 - vendor/a2ui/.gemini/GEMINI.md | 94 - vendor/a2ui/.github/workflows/docs.yml | 79 - .../a2ui/.github/workflows/editor_build.yml | 55 - .../.github/workflows/inspector_build.yml | 56 - .../.github/workflows/java_build_and_test.yml | 48 - .../.github/workflows/lit_samples_build.yml | 54 - .../.github/workflows/ng_build_and_test.yml | 72 - .../workflows/python_samples_build.yml | 62 - .../.github/workflows/web_build_and_test.yml | 50 - vendor/a2ui/.gitignore | 16 - vendor/a2ui/CONTRIBUTING.md | 49 - vendor/a2ui/LICENSE | 203 - vendor/a2ui/README.md | 162 - vendor/a2ui/mkdocs.yaml | 184 - vendor/a2ui/renderers/angular/.npmrc | 2 - vendor/a2ui/renderers/angular/README.md | 9 - vendor/a2ui/renderers/angular/angular.json | 35 - vendor/a2ui/renderers/angular/ng-package.json | 8 - .../a2ui/renderers/angular/package-lock.json | 14264 ---------------- vendor/a2ui/renderers/angular/package.json | 59 - .../angular/src/lib/catalog/audio.ts | 50 - .../angular/src/lib/catalog/button.ts | 56 - .../renderers/angular/src/lib/catalog/card.ts | 57 - .../angular/src/lib/catalog/checkbox.ts | 73 - .../angular/src/lib/catalog/column.ts | 96 - .../angular/src/lib/catalog/datetime-input.ts | 127 - .../angular/src/lib/catalog/default.ts | 185 - .../angular/src/lib/catalog/divider.ts | 37 - .../renderers/angular/src/lib/catalog/icon.ts | 44 - .../angular/src/lib/catalog/image.ts | 62 - .../renderers/angular/src/lib/catalog/list.ts | 63 - .../angular/src/lib/catalog/modal.ts | 113 - .../src/lib/catalog/multiple-choice.ts | 77 - .../renderers/angular/src/lib/catalog/row.ts | 100 - .../angular/src/lib/catalog/slider.ts | 73 - .../angular/src/lib/catalog/surface.ts | 99 - .../renderers/angular/src/lib/catalog/tabs.ts | 72 - .../angular/src/lib/catalog/text-field.ts | 86 - .../renderers/angular/src/lib/catalog/text.ts | 137 - .../angular/src/lib/catalog/video.ts | 50 - .../a2ui/renderers/angular/src/lib/config.ts | 25 - .../renderers/angular/src/lib/data/index.ts | 18 - .../angular/src/lib/data/markdown.ts | 114 - .../angular/src/lib/data/processor.ts | 47 - .../renderers/angular/src/lib/data/types.ts | 29 - .../angular/src/lib/rendering/catalog.ts | 36 - .../src/lib/rendering/dynamic-component.ts | 100 - .../angular/src/lib/rendering/index.ts | 20 - .../angular/src/lib/rendering/renderer.ts | 109 - .../angular/src/lib/rendering/theming.ts | 22 - .../a2ui/renderers/angular/src/public-api.ts | 21 - vendor/a2ui/renderers/angular/tsconfig.json | 23 - .../a2ui/renderers/angular/tsconfig.lib.json | 16 - .../renderers/angular/tsconfig.lib.prod.json | 9 - .../a2ui/renderers/angular/tsconfig.spec.json | 12 - vendor/a2ui/renderers/lit/.npmrc | 2 - vendor/a2ui/renderers/lit/README | 9 - vendor/a2ui/renderers/lit/README.md | 9 - vendor/a2ui/renderers/lit/package-lock.json | 1196 -- vendor/a2ui/renderers/lit/package.json | 108 - vendor/a2ui/renderers/lit/src/0.8/core.ts | 35 - .../a2ui/renderers/lit/src/0.8/data/guards.ts | 236 - .../lit/src/0.8/data/model-processor.ts | 867 - .../src/0.8/data/signal-model-processor.ts | 31 - .../a2ui/renderers/lit/src/0.8/events/a2ui.ts | 28 - .../a2ui/renderers/lit/src/0.8/events/base.ts | 19 - .../renderers/lit/src/0.8/events/events.ts | 53 - vendor/a2ui/renderers/lit/src/0.8/index.ts | 18 - .../a2ui/renderers/lit/src/0.8/model.test.ts | 1376 -- .../renderers/lit/src/0.8/schemas/.gitignore | 4 - ...erver_to_client_with_standard_catalog.json | 827 - .../renderers/lit/src/0.8/styles/behavior.ts | 55 - .../renderers/lit/src/0.8/styles/border.ts | 42 - .../renderers/lit/src/0.8/styles/colors.ts | 100 - .../renderers/lit/src/0.8/styles/icons.ts | 60 - .../renderers/lit/src/0.8/styles/index.ts | 37 - .../renderers/lit/src/0.8/styles/layout.ts | 235 - .../renderers/lit/src/0.8/styles/opacity.ts | 24 - .../renderers/lit/src/0.8/styles/shared.ts | 17 - .../a2ui/renderers/lit/src/0.8/styles/type.ts | 156 - .../renderers/lit/src/0.8/styles/utils.ts | 104 - .../lit/src/0.8/types/client-event.ts | 80 - .../renderers/lit/src/0.8/types/colors.ts | 66 - .../renderers/lit/src/0.8/types/components.ts | 211 - .../renderers/lit/src/0.8/types/primitives.ts | 60 - .../a2ui/renderers/lit/src/0.8/types/types.ts | 474 - vendor/a2ui/renderers/lit/src/0.8/ui/audio.ts | 96 - .../a2ui/renderers/lit/src/0.8/ui/button.ts | 65 - vendor/a2ui/renderers/lit/src/0.8/ui/card.ts | 64 - .../a2ui/renderers/lit/src/0.8/ui/checkbox.ts | 139 - .../a2ui/renderers/lit/src/0.8/ui/column.ts | 104 - .../lit/src/0.8/ui/component-registry.ts | 58 - .../renderers/lit/src/0.8/ui/context/theme.ts | 20 - .../lit/src/0.8/ui/custom-components/index.ts | 22 - .../lit/src/0.8/ui/datetime-input.ts | 197 - .../lit/src/0.8/ui/directives/directives.ts | 17 - .../lit/src/0.8/ui/directives/markdown.ts | 152 - .../lit/src/0.8/ui/directives/sanitizer.ts | 40 - .../a2ui/renderers/lit/src/0.8/ui/divider.ts | 51 - vendor/a2ui/renderers/lit/src/0.8/ui/icon.ts | 98 - vendor/a2ui/renderers/lit/src/0.8/ui/image.ts | 118 - vendor/a2ui/renderers/lit/src/0.8/ui/list.ts | 72 - vendor/a2ui/renderers/lit/src/0.8/ui/modal.ts | 131 - .../lit/src/0.8/ui/multiple-choice.ts | 142 - vendor/a2ui/renderers/lit/src/0.8/ui/root.ts | 475 - vendor/a2ui/renderers/lit/src/0.8/ui/row.ts | 104 - .../a2ui/renderers/lit/src/0.8/ui/slider.ts | 159 - .../a2ui/renderers/lit/src/0.8/ui/styles.ts | 20 - .../a2ui/renderers/lit/src/0.8/ui/surface.ts | 134 - vendor/a2ui/renderers/lit/src/0.8/ui/tabs.ts | 132 - .../renderers/lit/src/0.8/ui/text-field.ts | 131 - vendor/a2ui/renderers/lit/src/0.8/ui/text.ts | 164 - vendor/a2ui/renderers/lit/src/0.8/ui/ui.ts | 119 - .../renderers/lit/src/0.8/ui/utils/utils.ts | 92 - .../renderers/lit/src/0.8/ui/utils/youtube.ts | 77 - vendor/a2ui/renderers/lit/src/0.8/ui/video.ts | 96 - vendor/a2ui/renderers/lit/src/index.ts | 17 - vendor/a2ui/renderers/lit/tsconfig.json | 35 - vendor/a2ui/requirements-docs.txt | 9 - vendor/a2ui/specification/0.8/eval/.gitignore | 26 - vendor/a2ui/specification/0.8/eval/GEMINI.md | 76 - vendor/a2ui/specification/0.8/eval/README.md | 61 - .../specification/0.8/eval/genkit.conf.js | 24 - .../a2ui/specification/0.8/eval/package.json | 36 - .../specification/0.8/eval/pnpm-lock.yaml | 4885 ------ .../0.8/eval/pnpm-workspace.yaml | 18 - .../0.8/eval/src/basic_schema_matcher.ts | 65 - vendor/a2ui/specification/0.8/eval/src/dev.ts | 17 - .../a2ui/specification/0.8/eval/src/flows.ts | 71 - .../a2ui/specification/0.8/eval/src/index.ts | 363 - .../0.8/eval/src/message_type_matcher.ts | 50 - .../a2ui/specification/0.8/eval/src/models.ts | 68 - .../specification/0.8/eval/src/prompts.ts | 493 - .../0.8/eval/src/schema_matcher.ts | 24 - .../eval/src/surface_update_schema_matcher.ts | 207 - .../specification/0.8/eval/src/validator.ts | 496 - .../a2ui/specification/0.8/eval/tsconfig.json | 12 - vendor/a2ui/specification/0.8/json/README.md | 15 - .../json/a2ui_client_capabilities_schema.json | 23 - .../0.8/json/catalog_description_schema.json | 34 - .../0.8/json/client_to_server.json | 53 - .../0.8/json/server_to_client.json | 148 - ...erver_to_client_with_standard_catalog.json | 827 - .../0.8/json/standard_catalog_definition.json | 685 - vendor/a2ui/specification/0.9/eval/.gitignore | 26 - vendor/a2ui/specification/0.9/eval/README.md | 79 - .../specification/0.9/eval/genkit.conf.js | 24 - .../a2ui/specification/0.9/eval/package.json | 47 - .../specification/0.9/eval/pnpm-lock.yaml | 4727 ----- .../0.9/eval/pnpm-workspace.yaml | 18 - vendor/a2ui/specification/0.9/eval/src/ai.ts | 46 - .../0.9/eval/src/analysis_flow.ts | 118 - vendor/a2ui/specification/0.9/eval/src/dev.ts | 18 - .../0.9/eval/src/evaluation_flow.ts | 193 - .../specification/0.9/eval/src/evaluator.ts | 205 - .../0.9/eval/src/generation_flow.ts | 148 - .../specification/0.9/eval/src/generator.ts | 211 - .../a2ui/specification/0.9/eval/src/index.ts | 493 - .../a2ui/specification/0.9/eval/src/logger.ts | 70 - .../a2ui/specification/0.9/eval/src/models.ts | 93 - .../specification/0.9/eval/src/prompts.ts | 373 - .../specification/0.9/eval/src/rateLimiter.ts | 205 - .../a2ui/specification/0.9/eval/src/types.ts | 47 - .../a2ui/specification/0.9/eval/src/utils.ts | 44 - .../specification/0.9/eval/src/validator.ts | 365 - .../a2ui/specification/0.9/eval/tsconfig.json | 12 - .../0.9/json/client_to_server.json | 97 - .../specification/0.9/json/common_types.json | 120 - .../0.9/json/contact_form_example.jsonl | 3 - .../0.9/json/server_to_client.json | 114 - .../0.9/json/standard_catalog_definition.json | 638 - .../0.9/json/standard_catalog_rules.txt | 5 - vendor/a2ui/specification/0.9/validate.sh | 38 - vitest.config.ts | 9 +- vitest.e2e.config.ts | 31 - vitest.extensions.config.ts | 15 - vitest.gateway.config.ts | 15 - vitest.live.config.ts | 16 - vitest.unit.config.ts | 4 +- zizmor.yml | 17 - 2858 files changed, 253 insertions(+), 491991 deletions(-) delete mode 100644 .agent/workflows/update_clawdbot.md delete mode 100644 .agents/maintainers.md delete mode 100644 .detect-secrets.cfg delete mode 100644 .dockerignore delete mode 100644 .env.example delete mode 100644 .gitattributes delete mode 100644 .github/FUNDING.yml delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml delete mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml delete mode 100644 .github/actionlint.yaml delete mode 100644 .github/actions/detect-docs-changes/action.yml delete mode 100644 .github/actions/setup-node-env/action.yml delete mode 100644 .github/actions/setup-pnpm-store-cache/action.yml delete mode 100644 .github/dependabot.yml delete mode 100644 .github/instructions/copilot.instructions.md delete mode 100644 .github/labeler.yml delete mode 100644 .github/pull_request_template.md delete mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/workflow-sanity.yml delete mode 100644 .markdownlint-cli2.jsonc delete mode 100644 .pi/extensions/diff.ts delete mode 100644 .pi/extensions/files.ts delete mode 100644 .pi/extensions/prompt-url-widget.ts delete mode 100644 .pi/extensions/redraws.ts delete mode 100644 .pi/git/.gitignore delete mode 100644 .pi/prompts/cl.md delete mode 100644 .pi/prompts/is.md delete mode 100644 .pi/prompts/landpr.md delete mode 100644 .pi/prompts/reviewpr.md delete mode 100644 .pre-commit-config.yaml delete mode 100644 .secrets.baseline delete mode 100644 .shellcheckrc delete mode 100644 .swiftformat delete mode 100644 .swiftlint.yml delete mode 100644 .vscode/extensions.json delete mode 100644 .vscode/settings.json delete mode 100644 AGENTS.md delete mode 100644 CHANGELOG.md delete mode 120000 CLAUDE.md delete mode 100644 CONTRIBUTING.md delete mode 100644 Dockerfile delete mode 100644 Dockerfile.sandbox delete mode 100644 Dockerfile.sandbox-browser delete mode 100644 Dockerfile.sandbox-common delete mode 100644 SECURITY.md delete mode 100644 Swabble/.github/workflows/ci.yml delete mode 100644 Swabble/.gitignore delete mode 100644 Swabble/.swiftformat delete mode 100644 Swabble/.swiftlint.yml delete mode 100644 Swabble/CHANGELOG.md delete mode 100644 Swabble/LICENSE delete mode 100644 Swabble/Package.resolved delete mode 100644 Swabble/Package.swift delete mode 100644 Swabble/README.md delete mode 100644 Swabble/Sources/SwabbleCore/Config/Config.swift delete mode 100644 Swabble/Sources/SwabbleCore/Hooks/HookExecutor.swift delete mode 100644 Swabble/Sources/SwabbleCore/Speech/BufferConverter.swift delete mode 100644 Swabble/Sources/SwabbleCore/Speech/SpeechPipeline.swift delete mode 100644 Swabble/Sources/SwabbleCore/Support/AttributedString+Sentences.swift delete mode 100644 Swabble/Sources/SwabbleCore/Support/Logging.swift delete mode 100644 Swabble/Sources/SwabbleCore/Support/OutputFormat.swift delete mode 100644 Swabble/Sources/SwabbleCore/Support/TranscriptsStore.swift delete mode 100644 Swabble/Sources/SwabbleKit/WakeWordGate.swift delete mode 100644 Swabble/Sources/swabble/CLI/CLIRegistry.swift delete mode 100644 Swabble/Sources/swabble/Commands/DoctorCommand.swift delete mode 100644 Swabble/Sources/swabble/Commands/HealthCommand.swift delete mode 100644 Swabble/Sources/swabble/Commands/MicCommands.swift delete mode 100644 Swabble/Sources/swabble/Commands/ServeCommand.swift delete mode 100644 Swabble/Sources/swabble/Commands/ServiceCommands.swift delete mode 100644 Swabble/Sources/swabble/Commands/SetupCommand.swift delete mode 100644 Swabble/Sources/swabble/Commands/StartStopCommands.swift delete mode 100644 Swabble/Sources/swabble/Commands/StatusCommand.swift delete mode 100644 Swabble/Sources/swabble/Commands/TailLogCommand.swift delete mode 100644 Swabble/Sources/swabble/Commands/TestHookCommand.swift delete mode 100644 Swabble/Sources/swabble/Commands/TranscribeCommand.swift delete mode 100644 Swabble/Sources/swabble/main.swift delete mode 100644 Swabble/Tests/SwabbleKitTests/WakeWordGateTests.swift delete mode 100644 Swabble/Tests/swabbleTests/ConfigTests.swift delete mode 100644 Swabble/docs/spec.md delete mode 100755 Swabble/scripts/format.sh delete mode 100755 Swabble/scripts/lint.sh delete mode 100644 VISION.md delete mode 100644 appcast.xml delete mode 100644 apps/android/.gitignore delete mode 100644 apps/android/README.md delete mode 100644 apps/android/app/build.gradle.kts delete mode 100644 apps/android/app/proguard-rules.pro delete mode 100644 apps/android/app/src/main/AndroidManifest.xml delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/CameraHudState.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/DeviceNames.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/InstallResultReceiver.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/LocationMode.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/MainActivity.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/MainViewModel.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/NodeApp.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/NodeForegroundService.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/NodeRuntime.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/PermissionRequester.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ScreenCaptureRequester.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/SecurePrefs.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/SessionKey.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/VoiceWakeMode.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/WakeWords.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/chat/ChatController.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/chat/ChatModels.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/gateway/BonjourEscapes.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/gateway/DeviceAuthStore.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/gateway/DeviceIdentityStore.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayDiscovery.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayEndpoint.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayProtocol.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewaySession.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayTls.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/A2UIHandler.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/AppUpdateHandler.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/CameraCaptureManager.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/CameraHandler.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/CanvasController.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/ConnectionManager.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/DebugHandler.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/GatewayEventHandler.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/InvokeDispatcher.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/JpegSizeLimiter.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/LocationCaptureManager.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/LocationHandler.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/NodeUtils.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/ScreenHandler.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/ScreenRecordManager.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/SmsHandler.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/node/SmsManager.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/protocol/OpenClawCanvasA2UIAction.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/protocol/OpenClawProtocolConstants.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/tools/ToolDisplay.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/CameraHudOverlay.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/ChatSheet.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/OpenClawTheme.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/RootScreen.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/SettingsSheet.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/StatusPill.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/TalkOrbOverlay.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatComposer.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatMarkdown.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatMessageListCard.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatMessageViews.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatSessionsDialog.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatSheetContent.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/ui/chat/SessionFilters.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/voice/StreamingMediaDataSource.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/voice/TalkDirectiveParser.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/voice/TalkModeManager.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/voice/VoiceWakeCommandExtractor.kt delete mode 100644 apps/android/app/src/main/java/ai/openclaw/android/voice/VoiceWakeManager.kt delete mode 100644 apps/android/app/src/main/res/mipmap-anydpi/ic_launcher.xml delete mode 100644 apps/android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml delete mode 100644 apps/android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 apps/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png delete mode 100644 apps/android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 apps/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png delete mode 100644 apps/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 apps/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png delete mode 100644 apps/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 apps/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png delete mode 100644 apps/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 apps/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png delete mode 100644 apps/android/app/src/main/res/values/colors.xml delete mode 100644 apps/android/app/src/main/res/values/strings.xml delete mode 100644 apps/android/app/src/main/res/values/themes.xml delete mode 100644 apps/android/app/src/main/res/xml/backup_rules.xml delete mode 100644 apps/android/app/src/main/res/xml/data_extraction_rules.xml delete mode 100644 apps/android/app/src/main/res/xml/file_paths.xml delete mode 100644 apps/android/app/src/main/res/xml/network_security_config.xml delete mode 100644 apps/android/app/src/test/java/ai/openclaw/android/NodeForegroundServiceTest.kt delete mode 100644 apps/android/app/src/test/java/ai/openclaw/android/WakeWordsTest.kt delete mode 100644 apps/android/app/src/test/java/ai/openclaw/android/gateway/BonjourEscapesTest.kt delete mode 100644 apps/android/app/src/test/java/ai/openclaw/android/node/AppUpdateHandlerTest.kt delete mode 100644 apps/android/app/src/test/java/ai/openclaw/android/node/CanvasControllerSnapshotParamsTest.kt delete mode 100644 apps/android/app/src/test/java/ai/openclaw/android/node/ConnectionManagerTest.kt delete mode 100644 apps/android/app/src/test/java/ai/openclaw/android/node/JpegSizeLimiterTest.kt delete mode 100644 apps/android/app/src/test/java/ai/openclaw/android/node/SmsManagerTest.kt delete mode 100644 apps/android/app/src/test/java/ai/openclaw/android/protocol/OpenClawCanvasA2UIActionTest.kt delete mode 100644 apps/android/app/src/test/java/ai/openclaw/android/protocol/OpenClawProtocolConstantsTest.kt delete mode 100644 apps/android/app/src/test/java/ai/openclaw/android/ui/chat/SessionFiltersTest.kt delete mode 100644 apps/android/app/src/test/java/ai/openclaw/android/voice/TalkDirectiveParserTest.kt delete mode 100644 apps/android/app/src/test/java/ai/openclaw/android/voice/VoiceWakeCommandExtractorTest.kt delete mode 100644 apps/android/build.gradle.kts delete mode 100644 apps/android/gradle.properties delete mode 100644 apps/android/gradle/wrapper/gradle-wrapper.jar delete mode 100644 apps/android/gradle/wrapper/gradle-wrapper.properties delete mode 100755 apps/android/gradlew delete mode 100644 apps/android/gradlew.bat delete mode 100644 apps/android/settings.gradle.kts delete mode 100644 apps/ios/.swiftlint.yml delete mode 100644 apps/ios/Config/Signing.xcconfig delete mode 100644 apps/ios/LocalSigning.xcconfig.example delete mode 100644 apps/ios/README.md delete mode 100644 apps/ios/ShareExtension/Info.plist delete mode 100644 apps/ios/ShareExtension/ShareViewController.swift delete mode 100644 apps/ios/Signing.xcconfig delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/100.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/102.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/1024.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/108.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/114.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/120.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/172.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/180.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/196.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/216.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/234.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/258.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/29.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/40.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/48.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/55.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/57.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/58.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/60.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/66.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/80.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/87.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/88.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/92.png delete mode 100644 apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 apps/ios/Sources/Calendar/CalendarService.swift delete mode 100644 apps/ios/Sources/Camera/CameraController.swift delete mode 100644 apps/ios/Sources/Capabilities/NodeCapabilityRouter.swift delete mode 100644 apps/ios/Sources/Chat/ChatSheet.swift delete mode 100644 apps/ios/Sources/Chat/IOSGatewayChatTransport.swift delete mode 100644 apps/ios/Sources/Contacts/ContactsService.swift delete mode 100644 apps/ios/Sources/Device/DeviceStatusService.swift delete mode 100644 apps/ios/Sources/Device/NetworkStatusService.swift delete mode 100644 apps/ios/Sources/Device/NodeDisplayName.swift delete mode 100644 apps/ios/Sources/EventKit/EventKitAuthorization.swift delete mode 100644 apps/ios/Sources/Gateway/GatewayConnectConfig.swift delete mode 100644 apps/ios/Sources/Gateway/GatewayConnectionController.swift delete mode 100644 apps/ios/Sources/Gateway/GatewayConnectionIssue.swift delete mode 100644 apps/ios/Sources/Gateway/GatewayDiscoveryDebugLogView.swift delete mode 100644 apps/ios/Sources/Gateway/GatewayDiscoveryModel.swift delete mode 100644 apps/ios/Sources/Gateway/GatewayHealthMonitor.swift delete mode 100644 apps/ios/Sources/Gateway/GatewayQuickSetupSheet.swift delete mode 100644 apps/ios/Sources/Gateway/GatewayServiceResolver.swift delete mode 100644 apps/ios/Sources/Gateway/GatewaySettingsStore.swift delete mode 100644 apps/ios/Sources/Gateway/GatewaySetupCode.swift delete mode 100644 apps/ios/Sources/Gateway/GatewayTrustPromptAlert.swift delete mode 100644 apps/ios/Sources/Gateway/KeychainStore.swift delete mode 100644 apps/ios/Sources/Gateway/TCPProbe.swift delete mode 100644 apps/ios/Sources/Info.plist delete mode 100644 apps/ios/Sources/Location/LocationService.swift delete mode 100644 apps/ios/Sources/Location/SignificantLocationMonitor.swift delete mode 100644 apps/ios/Sources/Media/PhotoLibraryService.swift delete mode 100644 apps/ios/Sources/Model/NodeAppModel+Canvas.swift delete mode 100644 apps/ios/Sources/Model/NodeAppModel.swift delete mode 100644 apps/ios/Sources/Motion/MotionService.swift delete mode 100644 apps/ios/Sources/Onboarding/GatewayOnboardingView.swift delete mode 100644 apps/ios/Sources/Onboarding/OnboardingStateStore.swift delete mode 100644 apps/ios/Sources/Onboarding/OnboardingWizardView.swift delete mode 100644 apps/ios/Sources/Onboarding/QRScannerView.swift delete mode 100644 apps/ios/Sources/OpenClaw.entitlements delete mode 100644 apps/ios/Sources/OpenClawApp.swift delete mode 100644 apps/ios/Sources/Reminders/RemindersService.swift delete mode 100644 apps/ios/Sources/RootCanvas.swift delete mode 100644 apps/ios/Sources/RootTabs.swift delete mode 100644 apps/ios/Sources/RootView.swift delete mode 100644 apps/ios/Sources/Screen/ScreenController.swift delete mode 100644 apps/ios/Sources/Screen/ScreenRecordService.swift delete mode 100644 apps/ios/Sources/Screen/ScreenTab.swift delete mode 100644 apps/ios/Sources/Screen/ScreenWebView.swift delete mode 100644 apps/ios/Sources/Services/NodeServiceProtocols.swift delete mode 100644 apps/ios/Sources/Services/NotificationService.swift delete mode 100644 apps/ios/Sources/Services/WatchMessagingService.swift delete mode 100644 apps/ios/Sources/SessionKey.swift delete mode 100644 apps/ios/Sources/Settings/SettingsNetworkingHelpers.swift delete mode 100644 apps/ios/Sources/Settings/SettingsTab.swift delete mode 100644 apps/ios/Sources/Settings/VoiceWakeWordsSettingsView.swift delete mode 100644 apps/ios/Sources/Status/StatusActivityBuilder.swift delete mode 100644 apps/ios/Sources/Status/StatusPill.swift delete mode 100644 apps/ios/Sources/Status/VoiceWakeToast.swift delete mode 100644 apps/ios/Sources/Voice/TalkModeManager.swift delete mode 100644 apps/ios/Sources/Voice/TalkOrbOverlay.swift delete mode 100644 apps/ios/Sources/Voice/VoiceTab.swift delete mode 100644 apps/ios/Sources/Voice/VoiceWakeManager.swift delete mode 100644 apps/ios/Sources/Voice/VoiceWakePreferences.swift delete mode 100644 apps/ios/SwiftSources.input.xcfilelist delete mode 100644 apps/ios/Tests/AppCoverageTests.swift delete mode 100644 apps/ios/Tests/CameraControllerClampTests.swift delete mode 100644 apps/ios/Tests/CameraControllerErrorTests.swift delete mode 100644 apps/ios/Tests/DeepLinkParserTests.swift delete mode 100644 apps/ios/Tests/GatewayConnectionControllerTests.swift delete mode 100644 apps/ios/Tests/GatewayConnectionIssueTests.swift delete mode 100644 apps/ios/Tests/GatewayConnectionSecurityTests.swift delete mode 100644 apps/ios/Tests/GatewayDiscoveryModelTests.swift delete mode 100644 apps/ios/Tests/GatewayEndpointIDTests.swift delete mode 100644 apps/ios/Tests/GatewaySettingsStoreTests.swift delete mode 100644 apps/ios/Tests/IOSGatewayChatTransportTests.swift delete mode 100644 apps/ios/Tests/Info.plist delete mode 100644 apps/ios/Tests/KeychainStoreTests.swift delete mode 100644 apps/ios/Tests/NodeAppModelInvokeTests.swift delete mode 100644 apps/ios/Tests/OnboardingStateStoreTests.swift delete mode 100644 apps/ios/Tests/ScreenControllerTests.swift delete mode 100644 apps/ios/Tests/ScreenRecordServiceTests.swift delete mode 100644 apps/ios/Tests/SettingsNetworkingHelpersTests.swift delete mode 100644 apps/ios/Tests/ShareToAgentDeepLinkTests.swift delete mode 100644 apps/ios/Tests/SwiftUIRenderSmokeTests.swift delete mode 100644 apps/ios/Tests/VoiceWakeGatewaySyncTests.swift delete mode 100644 apps/ios/Tests/VoiceWakeManagerExtractCommandTests.swift delete mode 100644 apps/ios/Tests/VoiceWakeManagerStateTests.swift delete mode 100644 apps/ios/Tests/VoiceWakePreferencesTests.swift delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-app-38@2x.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-app-40@2x.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-app-41@2x.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-app-44@2x.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-app-45@2x.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-companion-29@2x.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-companion-29@3x.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-marketing-1024.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-notification-38@2x.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-notification-42@2x.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-quicklook-38@2x.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-quicklook-42@2x.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-quicklook-44@2x.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-quicklook-45@2x.png delete mode 100644 apps/ios/WatchApp/Assets.xcassets/Contents.json delete mode 100644 apps/ios/WatchApp/Info.plist delete mode 100644 apps/ios/WatchExtension/Info.plist delete mode 100644 apps/ios/WatchExtension/Sources/OpenClawWatchApp.swift delete mode 100644 apps/ios/WatchExtension/Sources/WatchConnectivityReceiver.swift delete mode 100644 apps/ios/WatchExtension/Sources/WatchInboxStore.swift delete mode 100644 apps/ios/WatchExtension/Sources/WatchInboxView.swift delete mode 100644 apps/ios/fastlane/.env.example delete mode 100644 apps/ios/fastlane/Appfile delete mode 100644 apps/ios/fastlane/Fastfile delete mode 100644 apps/ios/fastlane/SETUP.md delete mode 100644 apps/ios/project.yml delete mode 100644 apps/macos/Icon.icon/Assets/openclaw-mac.png delete mode 100644 apps/macos/Icon.icon/icon.json delete mode 100644 apps/macos/Package.resolved delete mode 100644 apps/macos/Package.swift delete mode 100644 apps/macos/README.md delete mode 100644 apps/macos/Sources/OpenClaw/AboutSettings.swift delete mode 100644 apps/macos/Sources/OpenClaw/AgeFormatting.swift delete mode 100644 apps/macos/Sources/OpenClaw/AgentEventStore.swift delete mode 100644 apps/macos/Sources/OpenClaw/AgentEventsWindow.swift delete mode 100644 apps/macos/Sources/OpenClaw/AgentWorkspace.swift delete mode 100644 apps/macos/Sources/OpenClaw/AnthropicAuthControls.swift delete mode 100644 apps/macos/Sources/OpenClaw/AnthropicOAuth.swift delete mode 100644 apps/macos/Sources/OpenClaw/AnthropicOAuthCodeState.swift delete mode 100644 apps/macos/Sources/OpenClaw/AnyCodable+Helpers.swift delete mode 100644 apps/macos/Sources/OpenClaw/AppState.swift delete mode 100644 apps/macos/Sources/OpenClaw/AudioInputDeviceObserver.swift delete mode 100644 apps/macos/Sources/OpenClaw/CLIInstallPrompter.swift delete mode 100644 apps/macos/Sources/OpenClaw/CLIInstaller.swift delete mode 100644 apps/macos/Sources/OpenClaw/CameraCaptureService.swift delete mode 100644 apps/macos/Sources/OpenClaw/CanvasA2UIActionMessageHandler.swift delete mode 100644 apps/macos/Sources/OpenClaw/CanvasChromeContainerView.swift delete mode 100644 apps/macos/Sources/OpenClaw/CanvasFileWatcher.swift delete mode 100644 apps/macos/Sources/OpenClaw/CanvasManager.swift delete mode 100644 apps/macos/Sources/OpenClaw/CanvasScheme.swift delete mode 100644 apps/macos/Sources/OpenClaw/CanvasSchemeHandler.swift delete mode 100644 apps/macos/Sources/OpenClaw/CanvasWindow.swift delete mode 100644 apps/macos/Sources/OpenClaw/CanvasWindowController+Helpers.swift delete mode 100644 apps/macos/Sources/OpenClaw/CanvasWindowController+Navigation.swift delete mode 100644 apps/macos/Sources/OpenClaw/CanvasWindowController+Testing.swift delete mode 100644 apps/macos/Sources/OpenClaw/CanvasWindowController+Window.swift delete mode 100644 apps/macos/Sources/OpenClaw/CanvasWindowController.swift delete mode 100644 apps/macos/Sources/OpenClaw/ChannelConfigForm.swift delete mode 100644 apps/macos/Sources/OpenClaw/ChannelsSettings+ChannelSections.swift delete mode 100644 apps/macos/Sources/OpenClaw/ChannelsSettings+ChannelState.swift delete mode 100644 apps/macos/Sources/OpenClaw/ChannelsSettings+Helpers.swift delete mode 100644 apps/macos/Sources/OpenClaw/ChannelsSettings+View.swift delete mode 100644 apps/macos/Sources/OpenClaw/ChannelsSettings.swift delete mode 100644 apps/macos/Sources/OpenClaw/ChannelsStore+Config.swift delete mode 100644 apps/macos/Sources/OpenClaw/ChannelsStore+Lifecycle.swift delete mode 100644 apps/macos/Sources/OpenClaw/ChannelsStore.swift delete mode 100644 apps/macos/Sources/OpenClaw/CoalescingFSEventsWatcher.swift delete mode 100644 apps/macos/Sources/OpenClaw/CommandResolver.swift delete mode 100644 apps/macos/Sources/OpenClaw/ConfigFileWatcher.swift delete mode 100644 apps/macos/Sources/OpenClaw/ConfigSchemaSupport.swift delete mode 100644 apps/macos/Sources/OpenClaw/ConfigSettings.swift delete mode 100644 apps/macos/Sources/OpenClaw/ConfigStore.swift delete mode 100644 apps/macos/Sources/OpenClaw/ConnectionModeCoordinator.swift delete mode 100644 apps/macos/Sources/OpenClaw/ConnectionModeResolver.swift delete mode 100644 apps/macos/Sources/OpenClaw/Constants.swift delete mode 100644 apps/macos/Sources/OpenClaw/ContextMenuCardView.swift delete mode 100644 apps/macos/Sources/OpenClaw/ContextUsageBar.swift delete mode 100644 apps/macos/Sources/OpenClaw/ControlChannel.swift delete mode 100644 apps/macos/Sources/OpenClaw/CostUsageMenuView.swift delete mode 100644 apps/macos/Sources/OpenClaw/CritterIconRenderer.swift delete mode 100644 apps/macos/Sources/OpenClaw/CritterStatusLabel+Behavior.swift delete mode 100644 apps/macos/Sources/OpenClaw/CritterStatusLabel.swift delete mode 100644 apps/macos/Sources/OpenClaw/CronJobEditor+Helpers.swift delete mode 100644 apps/macos/Sources/OpenClaw/CronJobEditor+Testing.swift delete mode 100644 apps/macos/Sources/OpenClaw/CronJobEditor.swift delete mode 100644 apps/macos/Sources/OpenClaw/CronJobsStore.swift delete mode 100644 apps/macos/Sources/OpenClaw/CronModels.swift delete mode 100644 apps/macos/Sources/OpenClaw/CronSettings+Actions.swift delete mode 100644 apps/macos/Sources/OpenClaw/CronSettings+Helpers.swift delete mode 100644 apps/macos/Sources/OpenClaw/CronSettings+Layout.swift delete mode 100644 apps/macos/Sources/OpenClaw/CronSettings+Rows.swift delete mode 100644 apps/macos/Sources/OpenClaw/CronSettings+Testing.swift delete mode 100644 apps/macos/Sources/OpenClaw/CronSettings.swift delete mode 100644 apps/macos/Sources/OpenClaw/DebugActions.swift delete mode 100644 apps/macos/Sources/OpenClaw/DebugSettings.swift delete mode 100644 apps/macos/Sources/OpenClaw/DeepLinks.swift delete mode 100644 apps/macos/Sources/OpenClaw/DeviceModelCatalog.swift delete mode 100644 apps/macos/Sources/OpenClaw/DevicePairingApprovalPrompter.swift delete mode 100644 apps/macos/Sources/OpenClaw/DiagnosticsFileLog.swift delete mode 100644 apps/macos/Sources/OpenClaw/DockIconManager.swift delete mode 100644 apps/macos/Sources/OpenClaw/ExecAllowlistMatcher.swift delete mode 100644 apps/macos/Sources/OpenClaw/ExecApprovalEvaluation.swift delete mode 100644 apps/macos/Sources/OpenClaw/ExecApprovals.swift delete mode 100644 apps/macos/Sources/OpenClaw/ExecApprovalsGatewayPrompter.swift delete mode 100644 apps/macos/Sources/OpenClaw/ExecApprovalsSocket.swift delete mode 100644 apps/macos/Sources/OpenClaw/ExecCommandResolution.swift delete mode 100644 apps/macos/Sources/OpenClaw/FileHandle+SafeRead.swift delete mode 100644 apps/macos/Sources/OpenClaw/GatewayAutostartPolicy.swift delete mode 100644 apps/macos/Sources/OpenClaw/GatewayConnection.swift delete mode 100644 apps/macos/Sources/OpenClaw/GatewayConnectivityCoordinator.swift delete mode 100644 apps/macos/Sources/OpenClaw/GatewayDiscoveryHelpers.swift delete mode 100644 apps/macos/Sources/OpenClaw/GatewayDiscoveryMenu.swift delete mode 100644 apps/macos/Sources/OpenClaw/GatewayDiscoveryPreferences.swift delete mode 100644 apps/macos/Sources/OpenClaw/GatewayEndpointStore.swift delete mode 100644 apps/macos/Sources/OpenClaw/GatewayEnvironment.swift delete mode 100644 apps/macos/Sources/OpenClaw/GatewayLaunchAgentManager.swift delete mode 100644 apps/macos/Sources/OpenClaw/GatewayProcessManager.swift delete mode 100644 apps/macos/Sources/OpenClaw/GatewayRemoteConfig.swift delete mode 100644 apps/macos/Sources/OpenClaw/GeneralSettings.swift delete mode 100644 apps/macos/Sources/OpenClaw/HealthStore.swift delete mode 100644 apps/macos/Sources/OpenClaw/HeartbeatStore.swift delete mode 100644 apps/macos/Sources/OpenClaw/HostEnvSanitizer.swift delete mode 100644 apps/macos/Sources/OpenClaw/HoverHUD.swift delete mode 100644 apps/macos/Sources/OpenClaw/IconState.swift delete mode 100644 apps/macos/Sources/OpenClaw/InstancesSettings.swift delete mode 100644 apps/macos/Sources/OpenClaw/InstancesStore.swift delete mode 100644 apps/macos/Sources/OpenClaw/LaunchAgentManager.swift delete mode 100644 apps/macos/Sources/OpenClaw/Launchctl.swift delete mode 100644 apps/macos/Sources/OpenClaw/LaunchdManager.swift delete mode 100644 apps/macos/Sources/OpenClaw/LogLocator.swift delete mode 100644 apps/macos/Sources/OpenClaw/Logging/OpenClawLogging.swift delete mode 100644 apps/macos/Sources/OpenClaw/MenuBar.swift delete mode 100644 apps/macos/Sources/OpenClaw/MenuContentView.swift delete mode 100644 apps/macos/Sources/OpenClaw/MenuContextCardInjector.swift delete mode 100644 apps/macos/Sources/OpenClaw/MenuHighlightedHostView.swift delete mode 100644 apps/macos/Sources/OpenClaw/MenuHostedItem.swift delete mode 100644 apps/macos/Sources/OpenClaw/MenuSessionsHeaderView.swift delete mode 100644 apps/macos/Sources/OpenClaw/MenuSessionsInjector.swift delete mode 100644 apps/macos/Sources/OpenClaw/MenuUsageHeaderView.swift delete mode 100644 apps/macos/Sources/OpenClaw/MicLevelMonitor.swift delete mode 100644 apps/macos/Sources/OpenClaw/ModelCatalogLoader.swift delete mode 100644 apps/macos/Sources/OpenClaw/NSAttributedString+VoiceWake.swift delete mode 100644 apps/macos/Sources/OpenClaw/NodeMode/MacNodeLocationService.swift delete mode 100644 apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swift delete mode 100644 apps/macos/Sources/OpenClaw/NodeMode/MacNodeRuntime.swift delete mode 100644 apps/macos/Sources/OpenClaw/NodeMode/MacNodeRuntimeMainActorServices.swift delete mode 100644 apps/macos/Sources/OpenClaw/NodeMode/MacNodeScreenCommands.swift delete mode 100644 apps/macos/Sources/OpenClaw/NodePairingApprovalPrompter.swift delete mode 100644 apps/macos/Sources/OpenClaw/NodeServiceManager.swift delete mode 100644 apps/macos/Sources/OpenClaw/NodesMenu.swift delete mode 100644 apps/macos/Sources/OpenClaw/NodesStore.swift delete mode 100644 apps/macos/Sources/OpenClaw/NotificationManager.swift delete mode 100644 apps/macos/Sources/OpenClaw/NotifyOverlay.swift delete mode 100644 apps/macos/Sources/OpenClaw/Onboarding.swift delete mode 100644 apps/macos/Sources/OpenClaw/OnboardingView+Actions.swift delete mode 100644 apps/macos/Sources/OpenClaw/OnboardingView+Chat.swift delete mode 100644 apps/macos/Sources/OpenClaw/OnboardingView+Layout.swift delete mode 100644 apps/macos/Sources/OpenClaw/OnboardingView+Monitoring.swift delete mode 100644 apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift delete mode 100644 apps/macos/Sources/OpenClaw/OnboardingView+Testing.swift delete mode 100644 apps/macos/Sources/OpenClaw/OnboardingView+Wizard.swift delete mode 100644 apps/macos/Sources/OpenClaw/OnboardingView+Workspace.swift delete mode 100644 apps/macos/Sources/OpenClaw/OnboardingWidgets.swift delete mode 100644 apps/macos/Sources/OpenClaw/OnboardingWizard.swift delete mode 100644 apps/macos/Sources/OpenClaw/OpenClawConfigFile.swift delete mode 100644 apps/macos/Sources/OpenClaw/OpenClawPaths.swift delete mode 100644 apps/macos/Sources/OpenClaw/PairingAlertSupport.swift delete mode 100644 apps/macos/Sources/OpenClaw/PeekabooBridgeHostCoordinator.swift delete mode 100644 apps/macos/Sources/OpenClaw/PermissionManager.swift delete mode 100644 apps/macos/Sources/OpenClaw/PermissionsSettings.swift delete mode 100644 apps/macos/Sources/OpenClaw/PointingHandCursor.swift delete mode 100644 apps/macos/Sources/OpenClaw/PortGuardian.swift delete mode 100644 apps/macos/Sources/OpenClaw/PresenceReporter.swift delete mode 100644 apps/macos/Sources/OpenClaw/Process+PipeRead.swift delete mode 100644 apps/macos/Sources/OpenClaw/ProcessInfo+OpenClaw.swift delete mode 100644 apps/macos/Sources/OpenClaw/RemotePortTunnel.swift delete mode 100644 apps/macos/Sources/OpenClaw/RemoteTunnelManager.swift delete mode 100644 apps/macos/Sources/OpenClaw/Resources/DeviceModels/LICENSE.apple-device-identifiers.txt delete mode 100644 apps/macos/Sources/OpenClaw/Resources/DeviceModels/NOTICE.md delete mode 100644 apps/macos/Sources/OpenClaw/Resources/DeviceModels/ios-device-identifiers.json delete mode 100644 apps/macos/Sources/OpenClaw/Resources/DeviceModels/mac-device-identifiers.json delete mode 100644 apps/macos/Sources/OpenClaw/Resources/Info.plist delete mode 100644 apps/macos/Sources/OpenClaw/Resources/OpenClaw.icns delete mode 100644 apps/macos/Sources/OpenClaw/RuntimeLocator.swift delete mode 100644 apps/macos/Sources/OpenClaw/ScreenRecordService.swift delete mode 100644 apps/macos/Sources/OpenClaw/ScreenshotSize.swift delete mode 100644 apps/macos/Sources/OpenClaw/SessionActions.swift delete mode 100644 apps/macos/Sources/OpenClaw/SessionData.swift delete mode 100644 apps/macos/Sources/OpenClaw/SessionMenuLabelView.swift delete mode 100644 apps/macos/Sources/OpenClaw/SessionMenuPreviewView.swift delete mode 100644 apps/macos/Sources/OpenClaw/SessionsSettings.swift delete mode 100644 apps/macos/Sources/OpenClaw/SettingsComponents.swift delete mode 100644 apps/macos/Sources/OpenClaw/SettingsRootView.swift delete mode 100644 apps/macos/Sources/OpenClaw/SettingsWindowOpener.swift delete mode 100644 apps/macos/Sources/OpenClaw/ShellExecutor.swift delete mode 100644 apps/macos/Sources/OpenClaw/SkillsModels.swift delete mode 100644 apps/macos/Sources/OpenClaw/SkillsSettings.swift delete mode 100644 apps/macos/Sources/OpenClaw/SoundEffects.swift delete mode 100644 apps/macos/Sources/OpenClaw/StatusPill.swift delete mode 100644 apps/macos/Sources/OpenClaw/String+NonEmpty.swift delete mode 100644 apps/macos/Sources/OpenClaw/SystemPresenceInfo.swift delete mode 100644 apps/macos/Sources/OpenClaw/SystemRunSettingsView.swift delete mode 100644 apps/macos/Sources/OpenClaw/TailscaleIntegrationSection.swift delete mode 100644 apps/macos/Sources/OpenClaw/TailscaleService.swift delete mode 100644 apps/macos/Sources/OpenClaw/TalkAudioPlayer.swift delete mode 100644 apps/macos/Sources/OpenClaw/TalkModeController.swift delete mode 100644 apps/macos/Sources/OpenClaw/TalkModeRuntime.swift delete mode 100644 apps/macos/Sources/OpenClaw/TalkModeTypes.swift delete mode 100644 apps/macos/Sources/OpenClaw/TalkOverlay.swift delete mode 100644 apps/macos/Sources/OpenClaw/TalkOverlayView.swift delete mode 100644 apps/macos/Sources/OpenClaw/TerminationSignalWatcher.swift delete mode 100644 apps/macos/Sources/OpenClaw/UsageCostData.swift delete mode 100644 apps/macos/Sources/OpenClaw/UsageData.swift delete mode 100644 apps/macos/Sources/OpenClaw/UsageMenuLabelView.swift delete mode 100644 apps/macos/Sources/OpenClaw/UserDefaultsMigration.swift delete mode 100644 apps/macos/Sources/OpenClaw/ViewMetrics.swift delete mode 100644 apps/macos/Sources/OpenClaw/VisualEffectView.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoicePushToTalk.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceSessionCoordinator.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeChime.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeForwarder.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeGlobalSettingsSync.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeHelpers.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeOverlay.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeOverlayController+Session.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeOverlayController+Testing.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeOverlayController+Window.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeOverlayTextViews.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeOverlayView.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeRuntime.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeSettings.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeTestCard.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeTester.swift delete mode 100644 apps/macos/Sources/OpenClaw/VoiceWakeTextUtils.swift delete mode 100644 apps/macos/Sources/OpenClaw/WebChatManager.swift delete mode 100644 apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift delete mode 100644 apps/macos/Sources/OpenClaw/WindowPlacement.swift delete mode 100644 apps/macos/Sources/OpenClaw/WorkActivityStore.swift delete mode 100644 apps/macos/Sources/OpenClawDiscovery/GatewayDiscoveryModel.swift delete mode 100644 apps/macos/Sources/OpenClawDiscovery/TailscaleNetwork.swift delete mode 100644 apps/macos/Sources/OpenClawDiscovery/WideAreaGatewayDiscovery.swift delete mode 100644 apps/macos/Sources/OpenClawIPC/IPC.swift delete mode 100644 apps/macos/Sources/OpenClawMacCLI/ConnectCommand.swift delete mode 100644 apps/macos/Sources/OpenClawMacCLI/DiscoverCommand.swift delete mode 100644 apps/macos/Sources/OpenClawMacCLI/EntryPoint.swift delete mode 100644 apps/macos/Sources/OpenClawMacCLI/GatewayConfig.swift delete mode 100644 apps/macos/Sources/OpenClawMacCLI/TypeAliases.swift delete mode 100644 apps/macos/Sources/OpenClawMacCLI/WizardCommand.swift delete mode 100644 apps/macos/Sources/OpenClawProtocol/GatewayModels.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/AgentEventStoreTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/AgentWorkspaceTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/AnthropicAuthControlsSmokeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/AnthropicAuthResolverTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/AnthropicOAuthCodeStateTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/AnyCodableEncodingTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/CLIInstallerTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/CameraCaptureServiceTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/CameraIPCTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/CanvasFileWatcherTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/CanvasIPCTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/CanvasWindowSmokeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/ChannelsSettingsSmokeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/CommandResolverTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/ConfigStoreTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/CoverageDumpTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/CritterIconRendererTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/CronJobEditorSmokeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/CronModelsTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/DeepLinkAgentPolicyTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/DeviceModelCatalogTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/ExecAllowlistTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/ExecApprovalHelpersTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/ExecApprovalsGatewayPrompterTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/ExecApprovalsStoreRefactorTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/FileHandleLegacyAPIGuardTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/FileHandleSafeReadTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayAgentChannelTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayAutostartPolicyTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayChannelConfigureTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayChannelConnectTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayChannelRequestTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayChannelShutdownTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayConnectionControlTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayDiscoveryHelpersTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayDiscoveryModelTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayEndpointStoreTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayEnvironmentTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayFrameDecodeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayLaunchAgentManagerTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayProcessManagerTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/GatewayWebSocketTestSupport.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/HealthDecodeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/HealthStoreStateTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/HoverHUDControllerTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/InstancesSettingsSmokeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/InstancesStoreTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/LogLocatorTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/LowCoverageHelperTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/LowCoverageViewSmokeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/MacGatewayChatTransportMappingTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/MacNodeRuntimeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/MasterDiscoveryMenuSmokeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/MenuContentSmokeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/MenuSessionsInjectorTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/ModelCatalogLoaderTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/NixModeStableSuiteTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/NodeManagerPathsTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/NodePairingApprovalPrompterTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/NodePairingReconcilePolicyTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/OnboardingCoverageTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/OnboardingViewSmokeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/OnboardingWizardStepViewTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/OpenClawConfigFileTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/OpenClawOAuthStoreTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/PermissionManagerLocationTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/PermissionManagerTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/Placeholder.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/RemotePortTunnelTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/RuntimeLocatorTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/ScreenshotSizeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/SemverTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/SessionDataTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/SessionMenuPreviewTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/SettingsViewSmokeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/SkillsSettingsSmokeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/TailscaleIntegrationSectionTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/TalkAudioPlayerTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/TestIsolation.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/UtilitiesTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/VoicePushToTalkHotkeyTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/VoicePushToTalkTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/VoiceWakeForwarderTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/VoiceWakeGlobalSettingsSyncTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/VoiceWakeHelpersTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/VoiceWakeOverlayControllerTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/VoiceWakeOverlayTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/VoiceWakeOverlayViewSmokeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/VoiceWakeRuntimeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/VoiceWakeTesterTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/WebChatMainSessionKeyTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/WebChatManagerTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/WebChatSwiftUISmokeTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/WideAreaGatewayDiscoveryTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/WindowPlacementTests.swift delete mode 100644 apps/macos/Tests/OpenClawIPCTests/WorkActivityStoreTests.swift delete mode 100644 apps/shared/OpenClawKit/Package.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/AssistantTextParser.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMarkdownPreprocessor.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMarkdownRenderer.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageViews.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatModels.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatPayloadDecoding.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatSessions.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatSheets.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatTheme.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatTransport.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ToolResultTextFormatter.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/AnyCodable.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/AsyncTimeout.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/AudioStreamingProtocols.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/BonjourEscapes.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/BonjourTypes.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/BridgeFrames.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/CalendarCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/CameraCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/CanvasA2UIAction.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/CanvasA2UICommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/CanvasA2UIJSONL.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/CanvasCommandParams.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/CanvasCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/Capabilities.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/ChatCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/ContactsCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/DeepLinks.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/DeviceAuthStore.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/DeviceCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/DeviceIdentity.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/ElevenLabsKitShim.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayChannel.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayDiscoveryStatusText.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayEndpointID.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayErrors.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayNodeSession.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayPayloadDecoding.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayPush.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayTLSPinning.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/InstanceIdentity.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/JPEGTranscoder.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/LocationCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/LocationSettings.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/MotionCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/NetworkInterfaces.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/NodeError.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/OpenClawKitResources.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/PhotoCapture.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/PhotosCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/RemindersCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/Resources/CanvasScaffold/scaffold.html delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/Resources/tool-display.json delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/ScreenCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/ShareGatewayRelaySettings.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/ShareToAgentDeepLink.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/ShareToAgentSettings.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/StoragePaths.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/SystemCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/TalkCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/TalkDirective.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/TalkHistoryTimestamp.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/TalkPromptBuilder.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/TalkSystemSpeechSynthesizer.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/ToolDisplay.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawKit/WatchCommands.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawProtocol/AnyCodable.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift delete mode 100644 apps/shared/OpenClawKit/Sources/OpenClawProtocol/WizardHelpers.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/AnyCodableTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/AssistantTextParserTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/BonjourEscapesTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/CanvasA2UIActionTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/CanvasA2UITests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/CanvasSnapshotFormatTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatMarkdownPreprocessorTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatThemeTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatViewModelTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/DeepLinksSecurityTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/ElevenLabsTTSValidationTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/GatewayNodeSessionTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/JPEGTranscoderTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/TalkDirectiveTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/TalkHistoryTimestampTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/TalkPromptBuilderTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/ToolDisplayRegistryTests.swift delete mode 100644 apps/shared/OpenClawKit/Tests/OpenClawKitTests/ToolResultTextFormatterTests.swift delete mode 100644 apps/shared/OpenClawKit/Tools/CanvasA2UI/bootstrap.js delete mode 100644 apps/shared/OpenClawKit/Tools/CanvasA2UI/rolldown.config.mjs create mode 100644 apps/web/lib/workspace-bootstrap-templates.ts create mode 100644 apps/web/lib/workspace-seed.ts delete mode 100644 assets/avatar-placeholder.svg delete mode 100644 assets/chrome-extension/README.md delete mode 100644 assets/chrome-extension/background.js delete mode 100644 assets/chrome-extension/icons/icon128.png delete mode 100644 assets/chrome-extension/icons/icon16.png delete mode 100644 assets/chrome-extension/icons/icon32.png delete mode 100644 assets/chrome-extension/icons/icon48.png delete mode 100644 assets/chrome-extension/manifest.json delete mode 100644 assets/chrome-extension/options.html delete mode 100644 assets/chrome-extension/options.js delete mode 100644 assets/dmg-background-small.png delete mode 100644 assets/dmg-background.png delete mode 100644 assets/openclaw-ai-sdk-banner.png rename openclaw.mjs => denchclaw.mjs (100%) delete mode 100644 docker-compose.yml delete mode 100755 docker-setup.sh delete mode 100644 docs.acp.md delete mode 100644 docs/.i18n/README.md delete mode 100644 docs/.i18n/glossary.ja-JP.json delete mode 100644 docs/.i18n/glossary.zh-CN.json delete mode 100644 docs/.i18n/ja-JP.tm.jsonl delete mode 100644 docs/.i18n/zh-CN.tm.jsonl delete mode 100644 docs/CNAME delete mode 100644 docs/assets/install-script.svg delete mode 100644 docs/assets/macos-onboarding/01-macos-warning.jpeg delete mode 100644 docs/assets/macos-onboarding/02-local-networks.jpeg delete mode 100644 docs/assets/macos-onboarding/03-security-notice.png delete mode 100644 docs/assets/macos-onboarding/04-choose-gateway.png delete mode 100644 docs/assets/macos-onboarding/05-permissions.png delete mode 100644 docs/assets/openclaw-logo-text-dark.png delete mode 100644 docs/assets/openclaw-logo-text.png delete mode 100644 docs/assets/pixel-lobster.svg delete mode 100644 docs/assets/showcase/agents-ui.jpg delete mode 100644 docs/assets/showcase/bambu-cli.png delete mode 100644 docs/assets/showcase/codexmonitor.png delete mode 100644 docs/assets/showcase/gohome-grafana.png delete mode 100644 docs/assets/showcase/ios-testflight.jpg delete mode 100644 docs/assets/showcase/oura-health.png delete mode 100644 docs/assets/showcase/padel-cli.svg delete mode 100644 docs/assets/showcase/padel-screenshot.jpg delete mode 100644 docs/assets/showcase/papla-tts.jpg delete mode 100644 docs/assets/showcase/pr-review-telegram.jpg delete mode 100644 docs/assets/showcase/roborock-screenshot.jpg delete mode 100644 docs/assets/showcase/roborock-status.svg delete mode 100644 docs/assets/showcase/roof-camera-sky.jpg delete mode 100644 docs/assets/showcase/snag.png delete mode 100644 docs/assets/showcase/tesco-shop.jpg delete mode 100644 docs/assets/showcase/wienerlinien.png delete mode 100644 docs/assets/showcase/wine-cellar-skill.jpg delete mode 100644 docs/assets/showcase/winix-air-purifier.jpg delete mode 100644 docs/assets/showcase/xuezh-pronunciation.jpeg delete mode 100644 docs/assets/sponsors/blacksmith.svg delete mode 100644 docs/assets/sponsors/openai.svg delete mode 100644 docs/automation/auth-monitoring.md delete mode 100644 docs/automation/cron-jobs.md delete mode 100644 docs/automation/cron-vs-heartbeat.md delete mode 100644 docs/automation/gmail-pubsub.md delete mode 100644 docs/automation/hooks.md delete mode 100644 docs/automation/poll.md delete mode 100644 docs/automation/troubleshooting.md delete mode 100644 docs/automation/webhook.md delete mode 100644 docs/brave-search.md delete mode 100644 docs/channels/bluebubbles.md delete mode 100644 docs/channels/broadcast-groups.md delete mode 100644 docs/channels/channel-routing.md delete mode 100644 docs/channels/discord.md delete mode 100644 docs/channels/feishu.md delete mode 100644 docs/channels/googlechat.md delete mode 100644 docs/channels/grammy.md delete mode 100644 docs/channels/group-messages.md delete mode 100644 docs/channels/groups.md delete mode 100644 docs/channels/imessage.md delete mode 100644 docs/channels/index.md delete mode 100644 docs/channels/irc.md delete mode 100644 docs/channels/line.md delete mode 100644 docs/channels/location.md delete mode 100644 docs/channels/matrix.md delete mode 100644 docs/channels/mattermost.md delete mode 100644 docs/channels/msteams.md delete mode 100644 docs/channels/nextcloud-talk.md delete mode 100644 docs/channels/nostr.md delete mode 100644 docs/channels/pairing.md delete mode 100644 docs/channels/signal.md delete mode 100644 docs/channels/slack.md delete mode 100644 docs/channels/telegram.md delete mode 100644 docs/channels/tlon.md delete mode 100644 docs/channels/troubleshooting.md delete mode 100644 docs/channels/twitch.md delete mode 100644 docs/channels/whatsapp.md delete mode 100644 docs/channels/zalo.md delete mode 100644 docs/channels/zalouser.md delete mode 100644 docs/ci.md delete mode 100644 docs/cli/acp.md delete mode 100644 docs/cli/agent.md delete mode 100644 docs/cli/agents.md delete mode 100644 docs/cli/approvals.md delete mode 100644 docs/cli/browser.md delete mode 100644 docs/cli/channels.md delete mode 100644 docs/cli/config.md delete mode 100644 docs/cli/configure.md delete mode 100644 docs/cli/cron.md delete mode 100644 docs/cli/dashboard.md delete mode 100644 docs/cli/devices.md delete mode 100644 docs/cli/directory.md delete mode 100644 docs/cli/dns.md delete mode 100644 docs/cli/docs.md delete mode 100644 docs/cli/doctor.md delete mode 100644 docs/cli/gateway.md delete mode 100644 docs/cli/health.md delete mode 100644 docs/cli/hooks.md delete mode 100644 docs/cli/index.md delete mode 100644 docs/cli/logs.md delete mode 100644 docs/cli/memory.md delete mode 100644 docs/cli/message.md delete mode 100644 docs/cli/models.md delete mode 100644 docs/cli/node.md delete mode 100644 docs/cli/nodes.md delete mode 100644 docs/cli/onboard.md delete mode 100644 docs/cli/pairing.md delete mode 100644 docs/cli/plugins.md delete mode 100644 docs/cli/reset.md delete mode 100644 docs/cli/sandbox.md delete mode 100644 docs/cli/security.md delete mode 100644 docs/cli/sessions.md delete mode 100644 docs/cli/setup.md delete mode 100644 docs/cli/skills.md delete mode 100644 docs/cli/status.md delete mode 100644 docs/cli/system.md delete mode 100644 docs/cli/tui.md delete mode 100644 docs/cli/uninstall.md delete mode 100644 docs/cli/update.md delete mode 100644 docs/cli/voicecall.md delete mode 100644 docs/cli/webhooks.md delete mode 100644 docs/concepts/agent-loop.md delete mode 100644 docs/concepts/agent-workspace.md delete mode 100644 docs/concepts/agent.md delete mode 100644 docs/concepts/architecture.md delete mode 100644 docs/concepts/compaction.md delete mode 100644 docs/concepts/context.md delete mode 100644 docs/concepts/features.md delete mode 100644 docs/concepts/markdown-formatting.md delete mode 100644 docs/concepts/memory.md delete mode 100644 docs/concepts/messages.md delete mode 100644 docs/concepts/model-failover.md delete mode 100644 docs/concepts/model-providers.md delete mode 100644 docs/concepts/models.md delete mode 100644 docs/concepts/multi-agent.md delete mode 100644 docs/concepts/oauth.md delete mode 100644 docs/concepts/presence.md delete mode 100644 docs/concepts/queue.md delete mode 100644 docs/concepts/retry.md delete mode 100644 docs/concepts/session-pruning.md delete mode 100644 docs/concepts/session-tool.md delete mode 100644 docs/concepts/session.md delete mode 100644 docs/concepts/sessions.md delete mode 100644 docs/concepts/streaming.md delete mode 100644 docs/concepts/system-prompt.md delete mode 100644 docs/concepts/timezone.md delete mode 100644 docs/concepts/typebox.md delete mode 100644 docs/concepts/typing-indicators.md delete mode 100644 docs/concepts/usage-tracking.md delete mode 100644 docs/date-time.md delete mode 100644 docs/debug/node-issue.md delete mode 100644 docs/diagnostics/flags.md delete mode 100644 docs/docs.json delete mode 100644 docs/experiments/.DS_Store delete mode 100644 docs/experiments/onboarding-config-protocol.md delete mode 100644 docs/experiments/plans/browser-evaluate-cdp-refactor.md delete mode 100644 docs/experiments/plans/cron-add-hardening.md delete mode 100644 docs/experiments/plans/group-policy-hardening.md delete mode 100644 docs/experiments/plans/openresponses-gateway.md delete mode 100644 docs/experiments/plans/pty-process-supervision.md delete mode 100644 docs/experiments/plans/session-binding-channel-agnostic.md delete mode 100644 docs/experiments/proposals/model-config.md delete mode 100644 docs/experiments/research/memory.md delete mode 100644 docs/gateway/authentication.md delete mode 100644 docs/gateway/background-process.md delete mode 100644 docs/gateway/bonjour.md delete mode 100644 docs/gateway/bridge-protocol.md delete mode 100644 docs/gateway/cli-backends.md delete mode 100644 docs/gateway/configuration-examples.md delete mode 100644 docs/gateway/configuration-reference.md delete mode 100644 docs/gateway/configuration.md delete mode 100644 docs/gateway/discovery.md delete mode 100644 docs/gateway/doctor.md delete mode 100644 docs/gateway/gateway-lock.md delete mode 100644 docs/gateway/health.md delete mode 100644 docs/gateway/heartbeat.md delete mode 100644 docs/gateway/index.md delete mode 100644 docs/gateway/local-models.md delete mode 100644 docs/gateway/logging.md delete mode 100644 docs/gateway/multiple-gateways.md delete mode 100644 docs/gateway/network-model.md delete mode 100644 docs/gateway/openai-http-api.md delete mode 100644 docs/gateway/openresponses-http-api.md delete mode 100644 docs/gateway/pairing.md delete mode 100644 docs/gateway/protocol.md delete mode 100644 docs/gateway/remote-gateway-readme.md delete mode 100644 docs/gateway/remote.md delete mode 100644 docs/gateway/sandbox-vs-tool-policy-vs-elevated.md delete mode 100644 docs/gateway/sandboxing.md delete mode 100644 docs/gateway/security/index.md delete mode 100644 docs/gateway/tailscale.md delete mode 100644 docs/gateway/tools-invoke-http-api.md delete mode 100644 docs/gateway/troubleshooting.md delete mode 100644 docs/gateway/trusted-proxy-auth.md delete mode 100644 docs/help/debugging.md delete mode 100644 docs/help/environment.md delete mode 100644 docs/help/faq.md delete mode 100644 docs/help/index.md delete mode 100644 docs/help/scripts.md delete mode 100644 docs/help/testing.md delete mode 100644 docs/help/troubleshooting.md delete mode 100644 docs/images/configure-model-picker-unsearchable.png delete mode 100644 docs/images/feishu-step2-create-app.png delete mode 100644 docs/images/feishu-step3-credentials.png delete mode 100644 docs/images/feishu-step4-permissions.png delete mode 100644 docs/images/feishu-step5-bot-capability.png delete mode 100644 docs/images/feishu-step6-event-subscription.png delete mode 100644 docs/images/groups-flow.svg delete mode 100644 docs/images/mobile-ui-screenshot.png delete mode 100644 docs/index.md delete mode 100644 docs/install/ansible.md delete mode 100644 docs/install/bun.md delete mode 100644 docs/install/development-channels.md delete mode 100644 docs/install/docker.md delete mode 100644 docs/install/exe-dev.md delete mode 100644 docs/install/fly.md delete mode 100644 docs/install/gcp.md delete mode 100644 docs/install/hetzner.md delete mode 100644 docs/install/index.md delete mode 100644 docs/install/installer.md delete mode 100644 docs/install/macos-vm.md delete mode 100644 docs/install/migrating.md delete mode 100644 docs/install/nix.md delete mode 100644 docs/install/node.md delete mode 100644 docs/install/northflank.mdx delete mode 100644 docs/install/podman.md delete mode 100644 docs/install/railway.mdx delete mode 100644 docs/install/render.mdx delete mode 100644 docs/install/uninstall.md delete mode 100644 docs/install/updating.md delete mode 100644 docs/ja-JP/AGENTS.md delete mode 100644 docs/ja-JP/index.md delete mode 100644 docs/ja-JP/start/getting-started.md delete mode 100644 docs/ja-JP/start/wizard.md delete mode 100644 docs/logging.md delete mode 100644 docs/nav-tabs-underline.js delete mode 100644 docs/network.md delete mode 100644 docs/nodes/audio.md delete mode 100644 docs/nodes/camera.md delete mode 100644 docs/nodes/images.md delete mode 100644 docs/nodes/index.md delete mode 100644 docs/nodes/location-command.md delete mode 100644 docs/nodes/media-understanding.md delete mode 100644 docs/nodes/talk.md delete mode 100644 docs/nodes/troubleshooting.md delete mode 100644 docs/nodes/voicewake.md delete mode 100644 docs/perplexity.md delete mode 100644 docs/pi-dev.md delete mode 100644 docs/pi.md delete mode 100644 docs/platforms/android.md delete mode 100644 docs/platforms/digitalocean.md delete mode 100644 docs/platforms/index.md delete mode 100644 docs/platforms/ios.md delete mode 100644 docs/platforms/linux.md delete mode 100644 docs/platforms/mac/bundled-gateway.md delete mode 100644 docs/platforms/mac/canvas.md delete mode 100644 docs/platforms/mac/child-process.md delete mode 100644 docs/platforms/mac/dev-setup.md delete mode 100644 docs/platforms/mac/health.md delete mode 100644 docs/platforms/mac/icon.md delete mode 100644 docs/platforms/mac/logging.md delete mode 100644 docs/platforms/mac/menu-bar.md delete mode 100644 docs/platforms/mac/peekaboo.md delete mode 100644 docs/platforms/mac/permissions.md delete mode 100644 docs/platforms/mac/release.md delete mode 100644 docs/platforms/mac/remote.md delete mode 100644 docs/platforms/mac/signing.md delete mode 100644 docs/platforms/mac/skills.md delete mode 100644 docs/platforms/mac/voice-overlay.md delete mode 100644 docs/platforms/mac/voicewake.md delete mode 100644 docs/platforms/mac/webchat.md delete mode 100644 docs/platforms/mac/xpc.md delete mode 100644 docs/platforms/macos.md delete mode 100644 docs/platforms/oracle.md delete mode 100644 docs/platforms/raspberry-pi.md delete mode 100644 docs/platforms/windows.md delete mode 100644 docs/plugins/agent-tools.md delete mode 100644 docs/plugins/community.md delete mode 100644 docs/plugins/manifest.md delete mode 100644 docs/plugins/voice-call.md delete mode 100644 docs/plugins/zalouser.md delete mode 100644 docs/prose.md delete mode 100644 docs/providers/anthropic.md delete mode 100644 docs/providers/bedrock.md delete mode 100644 docs/providers/claude-max-api-proxy.md delete mode 100644 docs/providers/cloudflare-ai-gateway.md delete mode 100644 docs/providers/deepgram.md delete mode 100644 docs/providers/github-copilot.md delete mode 100644 docs/providers/glm.md delete mode 100644 docs/providers/huggingface.md delete mode 100644 docs/providers/index.md delete mode 100644 docs/providers/litellm.md delete mode 100644 docs/providers/minimax.md delete mode 100644 docs/providers/models.md delete mode 100644 docs/providers/moonshot.md delete mode 100644 docs/providers/nvidia.md delete mode 100644 docs/providers/ollama.md delete mode 100644 docs/providers/openai.md delete mode 100644 docs/providers/opencode.md delete mode 100644 docs/providers/openrouter.md delete mode 100644 docs/providers/qianfan.md delete mode 100644 docs/providers/qwen.md delete mode 100644 docs/providers/synthetic.md delete mode 100644 docs/providers/together.md delete mode 100644 docs/providers/venice.md delete mode 100644 docs/providers/vercel-ai-gateway.md delete mode 100644 docs/providers/vllm.md delete mode 100644 docs/providers/xiaomi.md delete mode 100644 docs/providers/zai.md delete mode 100644 docs/refactor/clawnet.md delete mode 100644 docs/refactor/exec-host.md delete mode 100644 docs/refactor/outbound-session-mirroring.md delete mode 100644 docs/refactor/plugin-sdk.md delete mode 100644 docs/refactor/strict-config.md delete mode 100644 docs/reference/AGENTS.default.md delete mode 100644 docs/reference/RELEASING.md delete mode 100644 docs/reference/api-usage-costs.md delete mode 100644 docs/reference/credits.md delete mode 100644 docs/reference/device-models.md delete mode 100644 docs/reference/rpc.md delete mode 100644 docs/reference/session-management-compaction.md delete mode 100644 docs/reference/templates/AGENTS.dev.md delete mode 100644 docs/reference/templates/AGENTS.md delete mode 100644 docs/reference/templates/BOOT.md delete mode 100644 docs/reference/templates/BOOTSTRAP.md delete mode 100644 docs/reference/templates/HEARTBEAT.md delete mode 100644 docs/reference/templates/IDENTITY.dev.md delete mode 100644 docs/reference/templates/IDENTITY.md delete mode 100644 docs/reference/templates/SOUL.dev.md delete mode 100644 docs/reference/templates/SOUL.md delete mode 100644 docs/reference/templates/TOOLS.dev.md delete mode 100644 docs/reference/templates/TOOLS.md delete mode 100644 docs/reference/templates/USER.dev.md delete mode 100644 docs/reference/templates/USER.md delete mode 100644 docs/reference/test.md delete mode 100644 docs/reference/token-use.md delete mode 100644 docs/reference/transcript-hygiene.md delete mode 100644 docs/reference/wizard.md delete mode 100644 docs/security/CONTRIBUTING-THREAT-MODEL.md delete mode 100644 docs/security/README.md delete mode 100644 docs/security/THREAT-MODEL-ATLAS.md delete mode 100644 docs/security/formal-verification.md delete mode 100644 docs/start/bootstrapping.md delete mode 100644 docs/start/docs-directory.md delete mode 100644 docs/start/getting-started.md delete mode 100644 docs/start/hubs.md delete mode 100644 docs/start/lore.md delete mode 100644 docs/start/onboarding-overview.md delete mode 100644 docs/start/onboarding.md delete mode 100644 docs/start/openclaw.md delete mode 100644 docs/start/quickstart.md delete mode 100644 docs/start/setup.md delete mode 100644 docs/start/showcase.md delete mode 100644 docs/start/wizard-cli-automation.md delete mode 100644 docs/start/wizard-cli-reference.md delete mode 100644 docs/start/wizard.md delete mode 100644 docs/style.css delete mode 100644 docs/tools/agent-send.md delete mode 100644 docs/tools/apply-patch.md delete mode 100644 docs/tools/browser-linux-troubleshooting.md delete mode 100644 docs/tools/browser-login.md delete mode 100644 docs/tools/browser.md delete mode 100644 docs/tools/chrome-extension.md delete mode 100644 docs/tools/clawhub.md delete mode 100644 docs/tools/creating-skills.md delete mode 100644 docs/tools/elevated.md delete mode 100644 docs/tools/exec-approvals.md delete mode 100644 docs/tools/exec.md delete mode 100644 docs/tools/firecrawl.md delete mode 100644 docs/tools/index.md delete mode 100644 docs/tools/llm-task.md delete mode 100644 docs/tools/lobster.md delete mode 100644 docs/tools/loop-detection.md delete mode 100644 docs/tools/multi-agent-sandbox-tools.md delete mode 100644 docs/tools/plugin.md delete mode 100644 docs/tools/reactions.md delete mode 100644 docs/tools/skills-config.md delete mode 100644 docs/tools/skills.md delete mode 100644 docs/tools/slash-commands.md delete mode 100644 docs/tools/subagents.md delete mode 100644 docs/tools/thinking.md delete mode 100644 docs/tools/web.md delete mode 100644 docs/tts.md delete mode 100644 docs/vps.md delete mode 100644 docs/web/control-ui.md delete mode 100644 docs/web/dashboard.md delete mode 100644 docs/web/index.md delete mode 100644 docs/web/tui.md delete mode 100644 docs/web/webchat.md delete mode 100644 docs/whatsapp-openclaw-ai-zh.jpg delete mode 100644 docs/whatsapp-openclaw.jpg delete mode 100644 docs/zh-CN/AGENTS.md delete mode 100644 docs/zh-CN/automation/auth-monitoring.md delete mode 100644 docs/zh-CN/automation/cron-jobs.md delete mode 100644 docs/zh-CN/automation/cron-vs-heartbeat.md delete mode 100644 docs/zh-CN/automation/gmail-pubsub.md delete mode 100644 docs/zh-CN/automation/hooks.md delete mode 100644 docs/zh-CN/automation/poll.md delete mode 100644 docs/zh-CN/automation/troubleshooting.md delete mode 100644 docs/zh-CN/automation/webhook.md delete mode 100644 docs/zh-CN/brave-search.md delete mode 100644 docs/zh-CN/channels/bluebubbles.md delete mode 100644 docs/zh-CN/channels/broadcast-groups.md delete mode 100644 docs/zh-CN/channels/channel-routing.md delete mode 100644 docs/zh-CN/channels/discord.md delete mode 100644 docs/zh-CN/channels/feishu.md delete mode 100644 docs/zh-CN/channels/googlechat.md delete mode 100644 docs/zh-CN/channels/grammy.md delete mode 100644 docs/zh-CN/channels/group-messages.md delete mode 100644 docs/zh-CN/channels/groups.md delete mode 100644 docs/zh-CN/channels/imessage.md delete mode 100644 docs/zh-CN/channels/index.md delete mode 100644 docs/zh-CN/channels/line.md delete mode 100644 docs/zh-CN/channels/location.md delete mode 100644 docs/zh-CN/channels/matrix.md delete mode 100644 docs/zh-CN/channels/mattermost.md delete mode 100644 docs/zh-CN/channels/msteams.md delete mode 100644 docs/zh-CN/channels/nextcloud-talk.md delete mode 100644 docs/zh-CN/channels/nostr.md delete mode 100644 docs/zh-CN/channels/pairing.md delete mode 100644 docs/zh-CN/channels/signal.md delete mode 100644 docs/zh-CN/channels/slack.md delete mode 100644 docs/zh-CN/channels/telegram.md delete mode 100644 docs/zh-CN/channels/tlon.md delete mode 100644 docs/zh-CN/channels/troubleshooting.md delete mode 100644 docs/zh-CN/channels/twitch.md delete mode 100644 docs/zh-CN/channels/whatsapp.md delete mode 100644 docs/zh-CN/channels/zalo.md delete mode 100644 docs/zh-CN/channels/zalouser.md delete mode 100644 docs/zh-CN/cli/acp.md delete mode 100644 docs/zh-CN/cli/agent.md delete mode 100644 docs/zh-CN/cli/agents.md delete mode 100644 docs/zh-CN/cli/approvals.md delete mode 100644 docs/zh-CN/cli/browser.md delete mode 100644 docs/zh-CN/cli/channels.md delete mode 100644 docs/zh-CN/cli/config.md delete mode 100644 docs/zh-CN/cli/configure.md delete mode 100644 docs/zh-CN/cli/cron.md delete mode 100644 docs/zh-CN/cli/dashboard.md delete mode 100644 docs/zh-CN/cli/devices.md delete mode 100644 docs/zh-CN/cli/directory.md delete mode 100644 docs/zh-CN/cli/dns.md delete mode 100644 docs/zh-CN/cli/docs.md delete mode 100644 docs/zh-CN/cli/doctor.md delete mode 100644 docs/zh-CN/cli/gateway.md delete mode 100644 docs/zh-CN/cli/health.md delete mode 100644 docs/zh-CN/cli/hooks.md delete mode 100644 docs/zh-CN/cli/index.md delete mode 100644 docs/zh-CN/cli/logs.md delete mode 100644 docs/zh-CN/cli/memory.md delete mode 100644 docs/zh-CN/cli/message.md delete mode 100644 docs/zh-CN/cli/models.md delete mode 100644 docs/zh-CN/cli/node.md delete mode 100644 docs/zh-CN/cli/nodes.md delete mode 100644 docs/zh-CN/cli/onboard.md delete mode 100644 docs/zh-CN/cli/pairing.md delete mode 100644 docs/zh-CN/cli/plugins.md delete mode 100644 docs/zh-CN/cli/reset.md delete mode 100644 docs/zh-CN/cli/sandbox.md delete mode 100644 docs/zh-CN/cli/security.md delete mode 100644 docs/zh-CN/cli/sessions.md delete mode 100644 docs/zh-CN/cli/setup.md delete mode 100644 docs/zh-CN/cli/skills.md delete mode 100644 docs/zh-CN/cli/status.md delete mode 100644 docs/zh-CN/cli/system.md delete mode 100644 docs/zh-CN/cli/tui.md delete mode 100644 docs/zh-CN/cli/uninstall.md delete mode 100644 docs/zh-CN/cli/update.md delete mode 100644 docs/zh-CN/cli/voicecall.md delete mode 100644 docs/zh-CN/cli/webhooks.md delete mode 100644 docs/zh-CN/concepts/agent-loop.md delete mode 100644 docs/zh-CN/concepts/agent-workspace.md delete mode 100644 docs/zh-CN/concepts/agent.md delete mode 100644 docs/zh-CN/concepts/architecture.md delete mode 100644 docs/zh-CN/concepts/compaction.md delete mode 100644 docs/zh-CN/concepts/context.md delete mode 100644 docs/zh-CN/concepts/features.md delete mode 100644 docs/zh-CN/concepts/markdown-formatting.md delete mode 100644 docs/zh-CN/concepts/memory.md delete mode 100644 docs/zh-CN/concepts/messages.md delete mode 100644 docs/zh-CN/concepts/model-failover.md delete mode 100644 docs/zh-CN/concepts/model-providers.md delete mode 100644 docs/zh-CN/concepts/models.md delete mode 100644 docs/zh-CN/concepts/multi-agent.md delete mode 100644 docs/zh-CN/concepts/oauth.md delete mode 100644 docs/zh-CN/concepts/presence.md delete mode 100644 docs/zh-CN/concepts/queue.md delete mode 100644 docs/zh-CN/concepts/retry.md delete mode 100644 docs/zh-CN/concepts/session-pruning.md delete mode 100644 docs/zh-CN/concepts/session-tool.md delete mode 100644 docs/zh-CN/concepts/session.md delete mode 100644 docs/zh-CN/concepts/sessions.md delete mode 100644 docs/zh-CN/concepts/streaming.md delete mode 100644 docs/zh-CN/concepts/system-prompt.md delete mode 100644 docs/zh-CN/concepts/timezone.md delete mode 100644 docs/zh-CN/concepts/typebox.md delete mode 100644 docs/zh-CN/concepts/typing-indicators.md delete mode 100644 docs/zh-CN/concepts/usage-tracking.md delete mode 100644 docs/zh-CN/date-time.md delete mode 100644 docs/zh-CN/debug/node-issue.md delete mode 100644 docs/zh-CN/diagnostics/flags.md delete mode 100644 docs/zh-CN/experiments/onboarding-config-protocol.md delete mode 100644 docs/zh-CN/experiments/plans/cron-add-hardening.md delete mode 100644 docs/zh-CN/experiments/plans/group-policy-hardening.md delete mode 100644 docs/zh-CN/experiments/plans/openresponses-gateway.md delete mode 100644 docs/zh-CN/experiments/proposals/model-config.md delete mode 100644 docs/zh-CN/experiments/research/memory.md delete mode 100644 docs/zh-CN/gateway/authentication.md delete mode 100644 docs/zh-CN/gateway/background-process.md delete mode 100644 docs/zh-CN/gateway/bonjour.md delete mode 100644 docs/zh-CN/gateway/bridge-protocol.md delete mode 100644 docs/zh-CN/gateway/cli-backends.md delete mode 100644 docs/zh-CN/gateway/configuration-examples.md delete mode 100644 docs/zh-CN/gateway/configuration.md delete mode 100644 docs/zh-CN/gateway/discovery.md delete mode 100644 docs/zh-CN/gateway/doctor.md delete mode 100644 docs/zh-CN/gateway/gateway-lock.md delete mode 100644 docs/zh-CN/gateway/health.md delete mode 100644 docs/zh-CN/gateway/heartbeat.md delete mode 100644 docs/zh-CN/gateway/index.md delete mode 100644 docs/zh-CN/gateway/local-models.md delete mode 100644 docs/zh-CN/gateway/logging.md delete mode 100644 docs/zh-CN/gateway/multiple-gateways.md delete mode 100644 docs/zh-CN/gateway/network-model.md delete mode 100644 docs/zh-CN/gateway/openai-http-api.md delete mode 100644 docs/zh-CN/gateway/openresponses-http-api.md delete mode 100644 docs/zh-CN/gateway/pairing.md delete mode 100644 docs/zh-CN/gateway/protocol.md delete mode 100644 docs/zh-CN/gateway/remote-gateway-readme.md delete mode 100644 docs/zh-CN/gateway/remote.md delete mode 100644 docs/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated.md delete mode 100644 docs/zh-CN/gateway/sandboxing.md delete mode 100644 docs/zh-CN/gateway/security/index.md delete mode 100644 docs/zh-CN/gateway/tailscale.md delete mode 100644 docs/zh-CN/gateway/tools-invoke-http-api.md delete mode 100644 docs/zh-CN/gateway/troubleshooting.md delete mode 100644 docs/zh-CN/help/debugging.md delete mode 100644 docs/zh-CN/help/environment.md delete mode 100644 docs/zh-CN/help/faq.md delete mode 100644 docs/zh-CN/help/index.md delete mode 100644 docs/zh-CN/help/scripts.md delete mode 100644 docs/zh-CN/help/testing.md delete mode 100644 docs/zh-CN/help/troubleshooting.md delete mode 100644 docs/zh-CN/index.md delete mode 100644 docs/zh-CN/install/ansible.md delete mode 100644 docs/zh-CN/install/bun.md delete mode 100644 docs/zh-CN/install/development-channels.md delete mode 100644 docs/zh-CN/install/docker.md delete mode 100644 docs/zh-CN/install/exe-dev.md delete mode 100644 docs/zh-CN/install/fly.md delete mode 100644 docs/zh-CN/install/gcp.md delete mode 100644 docs/zh-CN/install/hetzner.md delete mode 100644 docs/zh-CN/install/index.md delete mode 100644 docs/zh-CN/install/installer.md delete mode 100644 docs/zh-CN/install/macos-vm.md delete mode 100644 docs/zh-CN/install/migrating.md delete mode 100644 docs/zh-CN/install/nix.md delete mode 100644 docs/zh-CN/install/node.md delete mode 100644 docs/zh-CN/install/northflank.mdx delete mode 100644 docs/zh-CN/install/railway.mdx delete mode 100644 docs/zh-CN/install/render.mdx delete mode 100644 docs/zh-CN/install/uninstall.md delete mode 100644 docs/zh-CN/install/updating.md delete mode 100644 docs/zh-CN/logging.md delete mode 100644 docs/zh-CN/network.md delete mode 100644 docs/zh-CN/nodes/audio.md delete mode 100644 docs/zh-CN/nodes/camera.md delete mode 100644 docs/zh-CN/nodes/images.md delete mode 100644 docs/zh-CN/nodes/index.md delete mode 100644 docs/zh-CN/nodes/location-command.md delete mode 100644 docs/zh-CN/nodes/media-understanding.md delete mode 100644 docs/zh-CN/nodes/talk.md delete mode 100644 docs/zh-CN/nodes/troubleshooting.md delete mode 100644 docs/zh-CN/nodes/voicewake.md delete mode 100644 docs/zh-CN/perplexity.md delete mode 100644 docs/zh-CN/pi-dev.md delete mode 100644 docs/zh-CN/pi.md delete mode 100644 docs/zh-CN/platforms/android.md delete mode 100644 docs/zh-CN/platforms/digitalocean.md delete mode 100644 docs/zh-CN/platforms/index.md delete mode 100644 docs/zh-CN/platforms/ios.md delete mode 100644 docs/zh-CN/platforms/linux.md delete mode 100644 docs/zh-CN/platforms/mac/bundled-gateway.md delete mode 100644 docs/zh-CN/platforms/mac/canvas.md delete mode 100644 docs/zh-CN/platforms/mac/child-process.md delete mode 100644 docs/zh-CN/platforms/mac/dev-setup.md delete mode 100644 docs/zh-CN/platforms/mac/health.md delete mode 100644 docs/zh-CN/platforms/mac/icon.md delete mode 100644 docs/zh-CN/platforms/mac/logging.md delete mode 100644 docs/zh-CN/platforms/mac/menu-bar.md delete mode 100644 docs/zh-CN/platforms/mac/peekaboo.md delete mode 100644 docs/zh-CN/platforms/mac/permissions.md delete mode 100644 docs/zh-CN/platforms/mac/release.md delete mode 100644 docs/zh-CN/platforms/mac/remote.md delete mode 100644 docs/zh-CN/platforms/mac/signing.md delete mode 100644 docs/zh-CN/platforms/mac/skills.md delete mode 100644 docs/zh-CN/platforms/mac/voice-overlay.md delete mode 100644 docs/zh-CN/platforms/mac/voicewake.md delete mode 100644 docs/zh-CN/platforms/mac/webchat.md delete mode 100644 docs/zh-CN/platforms/mac/xpc.md delete mode 100644 docs/zh-CN/platforms/macos.md delete mode 100644 docs/zh-CN/platforms/oracle.md delete mode 100644 docs/zh-CN/platforms/raspberry-pi.md delete mode 100644 docs/zh-CN/platforms/windows.md delete mode 100644 docs/zh-CN/plugins/agent-tools.md delete mode 100644 docs/zh-CN/plugins/manifest.md delete mode 100644 docs/zh-CN/plugins/voice-call.md delete mode 100644 docs/zh-CN/plugins/zalouser.md delete mode 100644 docs/zh-CN/prose.md delete mode 100644 docs/zh-CN/providers/anthropic.md delete mode 100644 docs/zh-CN/providers/bedrock.md delete mode 100644 docs/zh-CN/providers/claude-max-api-proxy.md delete mode 100644 docs/zh-CN/providers/deepgram.md delete mode 100644 docs/zh-CN/providers/github-copilot.md delete mode 100644 docs/zh-CN/providers/glm.md delete mode 100644 docs/zh-CN/providers/index.md delete mode 100644 docs/zh-CN/providers/minimax.md delete mode 100644 docs/zh-CN/providers/models.md delete mode 100644 docs/zh-CN/providers/moonshot.md delete mode 100644 docs/zh-CN/providers/ollama.md delete mode 100644 docs/zh-CN/providers/openai.md delete mode 100644 docs/zh-CN/providers/opencode.md delete mode 100644 docs/zh-CN/providers/openrouter.md delete mode 100644 docs/zh-CN/providers/qianfan.md delete mode 100644 docs/zh-CN/providers/qwen.md delete mode 100644 docs/zh-CN/providers/synthetic.md delete mode 100644 docs/zh-CN/providers/venice.md delete mode 100644 docs/zh-CN/providers/vercel-ai-gateway.md delete mode 100644 docs/zh-CN/providers/xiaomi.md delete mode 100644 docs/zh-CN/providers/zai.md delete mode 100644 docs/zh-CN/refactor/clawnet.md delete mode 100644 docs/zh-CN/refactor/exec-host.md delete mode 100644 docs/zh-CN/refactor/outbound-session-mirroring.md delete mode 100644 docs/zh-CN/refactor/plugin-sdk.md delete mode 100644 docs/zh-CN/refactor/strict-config.md delete mode 100644 docs/zh-CN/reference/AGENTS.default.md delete mode 100644 docs/zh-CN/reference/RELEASING.md delete mode 100644 docs/zh-CN/reference/api-usage-costs.md delete mode 100644 docs/zh-CN/reference/credits.md delete mode 100644 docs/zh-CN/reference/device-models.md delete mode 100644 docs/zh-CN/reference/rpc.md delete mode 100644 docs/zh-CN/reference/session-management-compaction.md delete mode 100644 docs/zh-CN/reference/templates/AGENTS.dev.md delete mode 100644 docs/zh-CN/reference/templates/AGENTS.md delete mode 100644 docs/zh-CN/reference/templates/BOOT.md delete mode 100644 docs/zh-CN/reference/templates/BOOTSTRAP.md delete mode 100644 docs/zh-CN/reference/templates/HEARTBEAT.md delete mode 100644 docs/zh-CN/reference/templates/IDENTITY.dev.md delete mode 100644 docs/zh-CN/reference/templates/IDENTITY.md delete mode 100644 docs/zh-CN/reference/templates/SOUL.dev.md delete mode 100644 docs/zh-CN/reference/templates/SOUL.md delete mode 100644 docs/zh-CN/reference/templates/TOOLS.dev.md delete mode 100644 docs/zh-CN/reference/templates/TOOLS.md delete mode 100644 docs/zh-CN/reference/templates/USER.dev.md delete mode 100644 docs/zh-CN/reference/templates/USER.md delete mode 100644 docs/zh-CN/reference/test.md delete mode 100644 docs/zh-CN/reference/token-use.md delete mode 100644 docs/zh-CN/reference/transcript-hygiene.md delete mode 100644 docs/zh-CN/reference/wizard.md delete mode 100644 docs/zh-CN/security/formal-verification.md delete mode 100644 docs/zh-CN/start/bootstrapping.md delete mode 100644 docs/zh-CN/start/docs-directory.md delete mode 100644 docs/zh-CN/start/getting-started.md delete mode 100644 docs/zh-CN/start/hubs.md delete mode 100644 docs/zh-CN/start/lore.md delete mode 100644 docs/zh-CN/start/onboarding.md delete mode 100644 docs/zh-CN/start/openclaw.md delete mode 100644 docs/zh-CN/start/quickstart.md delete mode 100644 docs/zh-CN/start/setup.md delete mode 100644 docs/zh-CN/start/showcase.md delete mode 100644 docs/zh-CN/start/wizard.md delete mode 100644 docs/zh-CN/tools/agent-send.md delete mode 100644 docs/zh-CN/tools/apply-patch.md delete mode 100644 docs/zh-CN/tools/browser-linux-troubleshooting.md delete mode 100644 docs/zh-CN/tools/browser-login.md delete mode 100644 docs/zh-CN/tools/browser.md delete mode 100644 docs/zh-CN/tools/chrome-extension.md delete mode 100644 docs/zh-CN/tools/clawhub.md delete mode 100644 docs/zh-CN/tools/creating-skills.md delete mode 100644 docs/zh-CN/tools/elevated.md delete mode 100644 docs/zh-CN/tools/exec-approvals.md delete mode 100644 docs/zh-CN/tools/exec.md delete mode 100644 docs/zh-CN/tools/firecrawl.md delete mode 100644 docs/zh-CN/tools/index.md delete mode 100644 docs/zh-CN/tools/llm-task.md delete mode 100644 docs/zh-CN/tools/lobster.md delete mode 100644 docs/zh-CN/tools/multi-agent-sandbox-tools.md delete mode 100644 docs/zh-CN/tools/plugin.md delete mode 100644 docs/zh-CN/tools/reactions.md delete mode 100644 docs/zh-CN/tools/skills-config.md delete mode 100644 docs/zh-CN/tools/skills.md delete mode 100644 docs/zh-CN/tools/slash-commands.md delete mode 100644 docs/zh-CN/tools/subagents.md delete mode 100644 docs/zh-CN/tools/thinking.md delete mode 100644 docs/zh-CN/tools/web.md delete mode 100644 docs/zh-CN/tts.md delete mode 100644 docs/zh-CN/vps.md delete mode 100644 docs/zh-CN/web/control-ui.md delete mode 100644 docs/zh-CN/web/dashboard.md delete mode 100644 docs/zh-CN/web/index.md delete mode 100644 docs/zh-CN/web/tui.md delete mode 100644 docs/zh-CN/web/webchat.md delete mode 100644 extensions/bluebubbles/README.md delete mode 100644 extensions/bluebubbles/index.ts delete mode 100644 extensions/bluebubbles/openclaw.plugin.json delete mode 100644 extensions/bluebubbles/package.json delete mode 100644 extensions/bluebubbles/src/account-resolve.ts delete mode 100644 extensions/bluebubbles/src/accounts.ts delete mode 100644 extensions/bluebubbles/src/actions.test.ts delete mode 100644 extensions/bluebubbles/src/actions.ts delete mode 100644 extensions/bluebubbles/src/attachments.test.ts delete mode 100644 extensions/bluebubbles/src/attachments.ts delete mode 100644 extensions/bluebubbles/src/channel.ts delete mode 100644 extensions/bluebubbles/src/chat.test.ts delete mode 100644 extensions/bluebubbles/src/chat.ts delete mode 100644 extensions/bluebubbles/src/config-schema.test.ts delete mode 100644 extensions/bluebubbles/src/config-schema.ts delete mode 100644 extensions/bluebubbles/src/history.ts delete mode 100644 extensions/bluebubbles/src/media-send.test.ts delete mode 100644 extensions/bluebubbles/src/media-send.ts delete mode 100644 extensions/bluebubbles/src/monitor-normalize.ts delete mode 100644 extensions/bluebubbles/src/monitor-processing.ts delete mode 100644 extensions/bluebubbles/src/monitor-reply-cache.ts delete mode 100644 extensions/bluebubbles/src/monitor-shared.ts delete mode 100644 extensions/bluebubbles/src/monitor.test.ts delete mode 100644 extensions/bluebubbles/src/monitor.ts delete mode 100644 extensions/bluebubbles/src/multipart.ts delete mode 100644 extensions/bluebubbles/src/onboarding.ts delete mode 100644 extensions/bluebubbles/src/probe.ts delete mode 100644 extensions/bluebubbles/src/reactions.test.ts delete mode 100644 extensions/bluebubbles/src/reactions.ts delete mode 100644 extensions/bluebubbles/src/request-url.ts delete mode 100644 extensions/bluebubbles/src/runtime.ts delete mode 100644 extensions/bluebubbles/src/send-helpers.ts delete mode 100644 extensions/bluebubbles/src/send.test.ts delete mode 100644 extensions/bluebubbles/src/send.ts delete mode 100644 extensions/bluebubbles/src/targets.test.ts delete mode 100644 extensions/bluebubbles/src/targets.ts delete mode 100644 extensions/bluebubbles/src/test-harness.ts delete mode 100644 extensions/bluebubbles/src/test-mocks.ts delete mode 100644 extensions/bluebubbles/src/types.ts delete mode 100644 extensions/copilot-proxy/README.md delete mode 100644 extensions/copilot-proxy/index.ts delete mode 100644 extensions/copilot-proxy/openclaw.plugin.json delete mode 100644 extensions/copilot-proxy/package.json delete mode 100644 extensions/denchclaw-auth/README.md delete mode 100644 extensions/denchclaw-auth/index.ts delete mode 100644 extensions/denchclaw-auth/oauth.ts delete mode 100644 extensions/denchclaw-auth/openclaw.plugin.json delete mode 100644 extensions/device-pair/index.ts delete mode 100644 extensions/device-pair/openclaw.plugin.json delete mode 100644 extensions/diagnostics-otel/index.ts delete mode 100644 extensions/diagnostics-otel/openclaw.plugin.json delete mode 100644 extensions/diagnostics-otel/package.json delete mode 100644 extensions/diagnostics-otel/src/service.test.ts delete mode 100644 extensions/diagnostics-otel/src/service.ts delete mode 100644 extensions/discord/index.ts delete mode 100644 extensions/discord/openclaw.plugin.json delete mode 100644 extensions/discord/package.json delete mode 100644 extensions/discord/src/channel.ts delete mode 100644 extensions/discord/src/runtime.ts delete mode 100644 extensions/discord/src/subagent-hooks.test.ts delete mode 100644 extensions/discord/src/subagent-hooks.ts delete mode 100644 extensions/feishu/index.ts delete mode 100644 extensions/feishu/openclaw.plugin.json delete mode 100644 extensions/feishu/package.json delete mode 100644 extensions/feishu/skills/feishu-doc/SKILL.md delete mode 100644 extensions/feishu/skills/feishu-doc/references/block-types.md delete mode 100644 extensions/feishu/skills/feishu-drive/SKILL.md delete mode 100644 extensions/feishu/skills/feishu-perm/SKILL.md delete mode 100644 extensions/feishu/skills/feishu-wiki/SKILL.md delete mode 100644 extensions/feishu/src/accounts.ts delete mode 100644 extensions/feishu/src/bitable.ts delete mode 100644 extensions/feishu/src/bot.checkBotMentioned.test.ts delete mode 100644 extensions/feishu/src/bot.stripBotMention.test.ts delete mode 100644 extensions/feishu/src/bot.test.ts delete mode 100644 extensions/feishu/src/bot.ts delete mode 100644 extensions/feishu/src/channel.test.ts delete mode 100644 extensions/feishu/src/channel.ts delete mode 100644 extensions/feishu/src/client.ts delete mode 100644 extensions/feishu/src/config-schema.test.ts delete mode 100644 extensions/feishu/src/config-schema.ts delete mode 100644 extensions/feishu/src/dedup.ts delete mode 100644 extensions/feishu/src/directory.ts delete mode 100644 extensions/feishu/src/doc-schema.ts delete mode 100644 extensions/feishu/src/docx.test.ts delete mode 100644 extensions/feishu/src/docx.ts delete mode 100644 extensions/feishu/src/drive-schema.ts delete mode 100644 extensions/feishu/src/drive.ts delete mode 100644 extensions/feishu/src/dynamic-agent.ts delete mode 100644 extensions/feishu/src/external-keys.test.ts delete mode 100644 extensions/feishu/src/external-keys.ts delete mode 100644 extensions/feishu/src/media.test.ts delete mode 100644 extensions/feishu/src/media.ts delete mode 100644 extensions/feishu/src/mention.ts delete mode 100644 extensions/feishu/src/monitor.ts delete mode 100644 extensions/feishu/src/monitor.webhook-security.test.ts delete mode 100644 extensions/feishu/src/onboarding.ts delete mode 100644 extensions/feishu/src/outbound.ts delete mode 100644 extensions/feishu/src/perm-schema.ts delete mode 100644 extensions/feishu/src/perm.ts delete mode 100644 extensions/feishu/src/policy.ts delete mode 100644 extensions/feishu/src/probe.ts delete mode 100644 extensions/feishu/src/reactions.ts delete mode 100644 extensions/feishu/src/reply-dispatcher.test.ts delete mode 100644 extensions/feishu/src/reply-dispatcher.ts delete mode 100644 extensions/feishu/src/runtime.ts delete mode 100644 extensions/feishu/src/send-result.ts delete mode 100644 extensions/feishu/src/send.ts delete mode 100644 extensions/feishu/src/streaming-card.ts delete mode 100644 extensions/feishu/src/targets.test.ts delete mode 100644 extensions/feishu/src/targets.ts delete mode 100644 extensions/feishu/src/tools-config.ts delete mode 100644 extensions/feishu/src/types.ts delete mode 100644 extensions/feishu/src/typing.ts delete mode 100644 extensions/feishu/src/wiki-schema.ts delete mode 100644 extensions/feishu/src/wiki.ts delete mode 100644 extensions/google-antigravity-auth/README.md delete mode 100644 extensions/google-antigravity-auth/index.ts delete mode 100644 extensions/google-antigravity-auth/openclaw.plugin.json delete mode 100644 extensions/google-antigravity-auth/package.json delete mode 100644 extensions/google-gemini-cli-auth/README.md delete mode 100644 extensions/google-gemini-cli-auth/index.ts delete mode 100644 extensions/google-gemini-cli-auth/oauth.test.ts delete mode 100644 extensions/google-gemini-cli-auth/oauth.ts delete mode 100644 extensions/google-gemini-cli-auth/openclaw.plugin.json delete mode 100644 extensions/google-gemini-cli-auth/package.json delete mode 100644 extensions/googlechat/index.ts delete mode 100644 extensions/googlechat/openclaw.plugin.json delete mode 100644 extensions/googlechat/package.json delete mode 100644 extensions/googlechat/src/accounts.ts delete mode 100644 extensions/googlechat/src/actions.ts delete mode 100644 extensions/googlechat/src/api.test.ts delete mode 100644 extensions/googlechat/src/api.ts delete mode 100644 extensions/googlechat/src/auth.ts delete mode 100644 extensions/googlechat/src/channel.ts delete mode 100644 extensions/googlechat/src/monitor.test.ts delete mode 100644 extensions/googlechat/src/monitor.ts delete mode 100644 extensions/googlechat/src/monitor.webhook-routing.test.ts delete mode 100644 extensions/googlechat/src/onboarding.ts delete mode 100644 extensions/googlechat/src/resolve-target.test.ts delete mode 100644 extensions/googlechat/src/runtime.ts delete mode 100644 extensions/googlechat/src/targets.test.ts delete mode 100644 extensions/googlechat/src/targets.ts delete mode 100644 extensions/googlechat/src/types.config.ts delete mode 100644 extensions/googlechat/src/types.ts delete mode 100644 extensions/imessage/index.ts delete mode 100644 extensions/imessage/openclaw.plugin.json delete mode 100644 extensions/imessage/package.json delete mode 100644 extensions/imessage/src/channel.outbound.test.ts delete mode 100644 extensions/imessage/src/channel.ts delete mode 100644 extensions/imessage/src/runtime.ts delete mode 100644 extensions/irc/index.ts delete mode 100644 extensions/irc/openclaw.plugin.json delete mode 100644 extensions/irc/package.json delete mode 100644 extensions/irc/src/accounts.ts delete mode 100644 extensions/irc/src/channel.ts delete mode 100644 extensions/irc/src/client.test.ts delete mode 100644 extensions/irc/src/client.ts delete mode 100644 extensions/irc/src/config-schema.test.ts delete mode 100644 extensions/irc/src/config-schema.ts delete mode 100644 extensions/irc/src/connect-options.ts delete mode 100644 extensions/irc/src/control-chars.ts delete mode 100644 extensions/irc/src/inbound.ts delete mode 100644 extensions/irc/src/monitor.test.ts delete mode 100644 extensions/irc/src/monitor.ts delete mode 100644 extensions/irc/src/normalize.test.ts delete mode 100644 extensions/irc/src/normalize.ts delete mode 100644 extensions/irc/src/onboarding.test.ts delete mode 100644 extensions/irc/src/onboarding.ts delete mode 100644 extensions/irc/src/policy.test.ts delete mode 100644 extensions/irc/src/policy.ts delete mode 100644 extensions/irc/src/probe.ts delete mode 100644 extensions/irc/src/protocol.test.ts delete mode 100644 extensions/irc/src/protocol.ts delete mode 100644 extensions/irc/src/runtime.ts delete mode 100644 extensions/irc/src/send.ts delete mode 100644 extensions/irc/src/types.ts delete mode 100644 extensions/line/index.ts delete mode 100644 extensions/line/openclaw.plugin.json delete mode 100644 extensions/line/package.json delete mode 100644 extensions/line/src/card-command.ts delete mode 100644 extensions/line/src/channel.logout.test.ts delete mode 100644 extensions/line/src/channel.sendPayload.test.ts delete mode 100644 extensions/line/src/channel.startup.test.ts delete mode 100644 extensions/line/src/channel.ts delete mode 100644 extensions/line/src/runtime.ts delete mode 100644 extensions/llm-task/README.md delete mode 100644 extensions/llm-task/index.ts delete mode 100644 extensions/llm-task/openclaw.plugin.json delete mode 100644 extensions/llm-task/package.json delete mode 100644 extensions/llm-task/src/llm-task-tool.test.ts delete mode 100644 extensions/llm-task/src/llm-task-tool.ts delete mode 100644 extensions/lobster/README.md delete mode 100644 extensions/lobster/SKILL.md delete mode 100644 extensions/lobster/index.ts delete mode 100644 extensions/lobster/openclaw.plugin.json delete mode 100644 extensions/lobster/package.json delete mode 100644 extensions/lobster/src/lobster-tool.test.ts delete mode 100644 extensions/lobster/src/lobster-tool.ts delete mode 100644 extensions/lobster/src/windows-spawn.test.ts delete mode 100644 extensions/lobster/src/windows-spawn.ts delete mode 100644 extensions/matrix/CHANGELOG.md delete mode 100644 extensions/matrix/index.ts delete mode 100644 extensions/matrix/openclaw.plugin.json delete mode 100644 extensions/matrix/package.json delete mode 100644 extensions/matrix/src/actions.ts delete mode 100644 extensions/matrix/src/channel.directory.test.ts delete mode 100644 extensions/matrix/src/channel.ts delete mode 100644 extensions/matrix/src/config-schema.ts delete mode 100644 extensions/matrix/src/directory-live.test.ts delete mode 100644 extensions/matrix/src/directory-live.ts delete mode 100644 extensions/matrix/src/group-mentions.ts delete mode 100644 extensions/matrix/src/matrix/accounts.test.ts delete mode 100644 extensions/matrix/src/matrix/accounts.ts delete mode 100644 extensions/matrix/src/matrix/actions.ts delete mode 100644 extensions/matrix/src/matrix/actions/client.ts delete mode 100644 extensions/matrix/src/matrix/actions/limits.test.ts delete mode 100644 extensions/matrix/src/matrix/actions/limits.ts delete mode 100644 extensions/matrix/src/matrix/actions/messages.ts delete mode 100644 extensions/matrix/src/matrix/actions/pins.test.ts delete mode 100644 extensions/matrix/src/matrix/actions/pins.ts delete mode 100644 extensions/matrix/src/matrix/actions/reactions.test.ts delete mode 100644 extensions/matrix/src/matrix/actions/reactions.ts delete mode 100644 extensions/matrix/src/matrix/actions/room.ts delete mode 100644 extensions/matrix/src/matrix/actions/summary.ts delete mode 100644 extensions/matrix/src/matrix/actions/types.ts delete mode 100644 extensions/matrix/src/matrix/active-client.ts delete mode 100644 extensions/matrix/src/matrix/client-bootstrap.ts delete mode 100644 extensions/matrix/src/matrix/client.test.ts delete mode 100644 extensions/matrix/src/matrix/client.ts delete mode 100644 extensions/matrix/src/matrix/client/config.ts delete mode 100644 extensions/matrix/src/matrix/client/create-client.ts delete mode 100644 extensions/matrix/src/matrix/client/logging.ts delete mode 100644 extensions/matrix/src/matrix/client/runtime.ts delete mode 100644 extensions/matrix/src/matrix/client/shared.ts delete mode 100644 extensions/matrix/src/matrix/client/storage.ts delete mode 100644 extensions/matrix/src/matrix/client/types.ts delete mode 100644 extensions/matrix/src/matrix/credentials.ts delete mode 100644 extensions/matrix/src/matrix/deps.ts delete mode 100644 extensions/matrix/src/matrix/format.test.ts delete mode 100644 extensions/matrix/src/matrix/format.ts delete mode 100644 extensions/matrix/src/matrix/index.ts delete mode 100644 extensions/matrix/src/matrix/monitor/allowlist.test.ts delete mode 100644 extensions/matrix/src/matrix/monitor/allowlist.ts delete mode 100644 extensions/matrix/src/matrix/monitor/auto-join.ts delete mode 100644 extensions/matrix/src/matrix/monitor/direct.ts delete mode 100644 extensions/matrix/src/matrix/monitor/events.ts delete mode 100644 extensions/matrix/src/matrix/monitor/handler.ts delete mode 100644 extensions/matrix/src/matrix/monitor/index.ts delete mode 100644 extensions/matrix/src/matrix/monitor/location.ts delete mode 100644 extensions/matrix/src/matrix/monitor/media.test.ts delete mode 100644 extensions/matrix/src/matrix/monitor/media.ts delete mode 100644 extensions/matrix/src/matrix/monitor/mentions.test.ts delete mode 100644 extensions/matrix/src/matrix/monitor/mentions.ts delete mode 100644 extensions/matrix/src/matrix/monitor/replies.test.ts delete mode 100644 extensions/matrix/src/matrix/monitor/replies.ts delete mode 100644 extensions/matrix/src/matrix/monitor/room-info.ts delete mode 100644 extensions/matrix/src/matrix/monitor/rooms.test.ts delete mode 100644 extensions/matrix/src/matrix/monitor/rooms.ts delete mode 100644 extensions/matrix/src/matrix/monitor/threads.ts delete mode 100644 extensions/matrix/src/matrix/monitor/types.ts delete mode 100644 extensions/matrix/src/matrix/poll-types.test.ts delete mode 100644 extensions/matrix/src/matrix/poll-types.ts delete mode 100644 extensions/matrix/src/matrix/probe.ts delete mode 100644 extensions/matrix/src/matrix/send.test.ts delete mode 100644 extensions/matrix/src/matrix/send.ts delete mode 100644 extensions/matrix/src/matrix/send/client.ts delete mode 100644 extensions/matrix/src/matrix/send/formatting.ts delete mode 100644 extensions/matrix/src/matrix/send/media.ts delete mode 100644 extensions/matrix/src/matrix/send/targets.test.ts delete mode 100644 extensions/matrix/src/matrix/send/targets.ts delete mode 100644 extensions/matrix/src/matrix/send/types.ts delete mode 100644 extensions/matrix/src/onboarding.ts delete mode 100644 extensions/matrix/src/outbound.ts delete mode 100644 extensions/matrix/src/resolve-targets.test.ts delete mode 100644 extensions/matrix/src/resolve-targets.ts delete mode 100644 extensions/matrix/src/runtime.ts delete mode 100644 extensions/matrix/src/tool-actions.ts delete mode 100644 extensions/matrix/src/types.ts delete mode 100644 extensions/mattermost/index.ts delete mode 100644 extensions/mattermost/openclaw.plugin.json delete mode 100644 extensions/mattermost/package.json delete mode 100644 extensions/mattermost/src/channel.test.ts delete mode 100644 extensions/mattermost/src/channel.ts delete mode 100644 extensions/mattermost/src/config-schema.ts delete mode 100644 extensions/mattermost/src/group-mentions.ts delete mode 100644 extensions/mattermost/src/mattermost/accounts.ts delete mode 100644 extensions/mattermost/src/mattermost/client.test.ts delete mode 100644 extensions/mattermost/src/mattermost/client.ts delete mode 100644 extensions/mattermost/src/mattermost/index.ts delete mode 100644 extensions/mattermost/src/mattermost/monitor-helpers.ts delete mode 100644 extensions/mattermost/src/mattermost/monitor-onchar.ts delete mode 100644 extensions/mattermost/src/mattermost/monitor-websocket.test.ts delete mode 100644 extensions/mattermost/src/mattermost/monitor-websocket.ts delete mode 100644 extensions/mattermost/src/mattermost/monitor.ts delete mode 100644 extensions/mattermost/src/mattermost/probe.ts delete mode 100644 extensions/mattermost/src/mattermost/reactions.test-helpers.ts delete mode 100644 extensions/mattermost/src/mattermost/reactions.test.ts delete mode 100644 extensions/mattermost/src/mattermost/reactions.ts delete mode 100644 extensions/mattermost/src/mattermost/reconnect.test.ts delete mode 100644 extensions/mattermost/src/mattermost/reconnect.ts delete mode 100644 extensions/mattermost/src/mattermost/send.ts delete mode 100644 extensions/mattermost/src/normalize.ts delete mode 100644 extensions/mattermost/src/onboarding-helpers.ts delete mode 100644 extensions/mattermost/src/onboarding.ts delete mode 100644 extensions/mattermost/src/runtime.ts delete mode 100644 extensions/mattermost/src/types.ts delete mode 100644 extensions/memory-core/index.ts delete mode 100644 extensions/memory-core/openclaw.plugin.json delete mode 100644 extensions/memory-core/package.json delete mode 100644 extensions/memory-lancedb/config.ts delete mode 100644 extensions/memory-lancedb/index.test.ts delete mode 100644 extensions/memory-lancedb/index.ts delete mode 100644 extensions/memory-lancedb/openclaw.plugin.json delete mode 100644 extensions/memory-lancedb/package.json delete mode 100644 extensions/minimax-portal-auth/README.md delete mode 100644 extensions/minimax-portal-auth/index.ts delete mode 100644 extensions/minimax-portal-auth/oauth.ts delete mode 100644 extensions/minimax-portal-auth/openclaw.plugin.json delete mode 100644 extensions/minimax-portal-auth/package.json delete mode 100644 extensions/msteams/CHANGELOG.md delete mode 100644 extensions/msteams/index.ts delete mode 100644 extensions/msteams/openclaw.plugin.json delete mode 100644 extensions/msteams/package.json delete mode 100644 extensions/msteams/src/attachments.test.ts delete mode 100644 extensions/msteams/src/attachments.ts delete mode 100644 extensions/msteams/src/attachments/download.ts delete mode 100644 extensions/msteams/src/attachments/graph.ts delete mode 100644 extensions/msteams/src/attachments/html.ts delete mode 100644 extensions/msteams/src/attachments/payload.ts delete mode 100644 extensions/msteams/src/attachments/remote-media.ts delete mode 100644 extensions/msteams/src/attachments/shared.ts delete mode 100644 extensions/msteams/src/attachments/types.ts delete mode 100644 extensions/msteams/src/channel.directory.test.ts delete mode 100644 extensions/msteams/src/channel.ts delete mode 100644 extensions/msteams/src/conversation-store-fs.test.ts delete mode 100644 extensions/msteams/src/conversation-store-fs.ts delete mode 100644 extensions/msteams/src/conversation-store-memory.ts delete mode 100644 extensions/msteams/src/conversation-store.ts delete mode 100644 extensions/msteams/src/directory-live.ts delete mode 100644 extensions/msteams/src/errors.test.ts delete mode 100644 extensions/msteams/src/errors.ts delete mode 100644 extensions/msteams/src/file-consent-helpers.test.ts delete mode 100644 extensions/msteams/src/file-consent-helpers.ts delete mode 100644 extensions/msteams/src/file-consent.ts delete mode 100644 extensions/msteams/src/file-lock.ts delete mode 100644 extensions/msteams/src/graph-chat.ts delete mode 100644 extensions/msteams/src/graph-upload.ts delete mode 100644 extensions/msteams/src/graph.ts delete mode 100644 extensions/msteams/src/inbound.test.ts delete mode 100644 extensions/msteams/src/inbound.ts delete mode 100644 extensions/msteams/src/index.ts delete mode 100644 extensions/msteams/src/media-helpers.test.ts delete mode 100644 extensions/msteams/src/media-helpers.ts delete mode 100644 extensions/msteams/src/mentions.test.ts delete mode 100644 extensions/msteams/src/mentions.ts delete mode 100644 extensions/msteams/src/messenger.test.ts delete mode 100644 extensions/msteams/src/messenger.ts delete mode 100644 extensions/msteams/src/monitor-handler.ts delete mode 100644 extensions/msteams/src/monitor-handler/inbound-media.ts delete mode 100644 extensions/msteams/src/monitor-handler/message-handler.ts delete mode 100644 extensions/msteams/src/monitor-types.ts delete mode 100644 extensions/msteams/src/monitor.ts delete mode 100644 extensions/msteams/src/onboarding.ts delete mode 100644 extensions/msteams/src/outbound.ts delete mode 100644 extensions/msteams/src/pending-uploads.ts delete mode 100644 extensions/msteams/src/policy.test.ts delete mode 100644 extensions/msteams/src/policy.ts delete mode 100644 extensions/msteams/src/polls-store-memory.ts delete mode 100644 extensions/msteams/src/polls-store.test.ts delete mode 100644 extensions/msteams/src/polls.test.ts delete mode 100644 extensions/msteams/src/polls.ts delete mode 100644 extensions/msteams/src/probe.test.ts delete mode 100644 extensions/msteams/src/probe.ts delete mode 100644 extensions/msteams/src/reply-dispatcher.ts delete mode 100644 extensions/msteams/src/resolve-allowlist.ts delete mode 100644 extensions/msteams/src/runtime.ts delete mode 100644 extensions/msteams/src/sdk-types.ts delete mode 100644 extensions/msteams/src/sdk.ts delete mode 100644 extensions/msteams/src/send-context.ts delete mode 100644 extensions/msteams/src/send.ts delete mode 100644 extensions/msteams/src/sent-message-cache.test.ts delete mode 100644 extensions/msteams/src/sent-message-cache.ts delete mode 100644 extensions/msteams/src/storage.ts delete mode 100644 extensions/msteams/src/store-fs.ts delete mode 100644 extensions/msteams/src/test-runtime.ts delete mode 100644 extensions/msteams/src/token.ts delete mode 100644 extensions/nextcloud-talk/index.ts delete mode 100644 extensions/nextcloud-talk/openclaw.plugin.json delete mode 100644 extensions/nextcloud-talk/package.json delete mode 100644 extensions/nextcloud-talk/src/accounts.ts delete mode 100644 extensions/nextcloud-talk/src/channel.ts delete mode 100644 extensions/nextcloud-talk/src/config-schema.ts delete mode 100644 extensions/nextcloud-talk/src/format.ts delete mode 100644 extensions/nextcloud-talk/src/inbound.ts delete mode 100644 extensions/nextcloud-talk/src/monitor.read-body.test.ts delete mode 100644 extensions/nextcloud-talk/src/monitor.ts delete mode 100644 extensions/nextcloud-talk/src/normalize.ts delete mode 100644 extensions/nextcloud-talk/src/onboarding.ts delete mode 100644 extensions/nextcloud-talk/src/policy.test.ts delete mode 100644 extensions/nextcloud-talk/src/policy.ts delete mode 100644 extensions/nextcloud-talk/src/room-info.ts delete mode 100644 extensions/nextcloud-talk/src/runtime.ts delete mode 100644 extensions/nextcloud-talk/src/send.ts delete mode 100644 extensions/nextcloud-talk/src/signature.ts delete mode 100644 extensions/nextcloud-talk/src/types.ts delete mode 100644 extensions/nostr/CHANGELOG.md delete mode 100644 extensions/nostr/README.md delete mode 100644 extensions/nostr/index.ts delete mode 100644 extensions/nostr/openclaw.plugin.json delete mode 100644 extensions/nostr/package.json delete mode 100644 extensions/nostr/src/channel.test.ts delete mode 100644 extensions/nostr/src/channel.ts delete mode 100644 extensions/nostr/src/config-schema.ts delete mode 100644 extensions/nostr/src/metrics.ts delete mode 100644 extensions/nostr/src/nostr-bus.fuzz.test.ts delete mode 100644 extensions/nostr/src/nostr-bus.integration.test.ts delete mode 100644 extensions/nostr/src/nostr-bus.test.ts delete mode 100644 extensions/nostr/src/nostr-bus.ts delete mode 100644 extensions/nostr/src/nostr-profile-http.test.ts delete mode 100644 extensions/nostr/src/nostr-profile-http.ts delete mode 100644 extensions/nostr/src/nostr-profile-import.test.ts delete mode 100644 extensions/nostr/src/nostr-profile-import.ts delete mode 100644 extensions/nostr/src/nostr-profile.fuzz.test.ts delete mode 100644 extensions/nostr/src/nostr-profile.test.ts delete mode 100644 extensions/nostr/src/nostr-profile.ts delete mode 100644 extensions/nostr/src/nostr-state-store.test.ts delete mode 100644 extensions/nostr/src/nostr-state-store.ts delete mode 100644 extensions/nostr/src/runtime.ts delete mode 100644 extensions/nostr/src/seen-tracker.ts delete mode 100644 extensions/nostr/src/types.test.ts delete mode 100644 extensions/nostr/src/types.ts delete mode 100644 extensions/nostr/test/setup.ts delete mode 100644 extensions/open-prose/README.md delete mode 100644 extensions/open-prose/index.ts delete mode 100644 extensions/open-prose/openclaw.plugin.json delete mode 100644 extensions/open-prose/package.json delete mode 100644 extensions/open-prose/skills/prose/LICENSE delete mode 100644 extensions/open-prose/skills/prose/SKILL.md delete mode 100644 extensions/open-prose/skills/prose/alt-borges.md delete mode 100644 extensions/open-prose/skills/prose/alts/arabian-nights.md delete mode 100644 extensions/open-prose/skills/prose/alts/borges.md delete mode 100644 extensions/open-prose/skills/prose/alts/folk.md delete mode 100644 extensions/open-prose/skills/prose/alts/homer.md delete mode 100644 extensions/open-prose/skills/prose/alts/kafka.md delete mode 100644 extensions/open-prose/skills/prose/compiler.md delete mode 100644 extensions/open-prose/skills/prose/examples/01-hello-world.prose delete mode 100644 extensions/open-prose/skills/prose/examples/02-research-and-summarize.prose delete mode 100644 extensions/open-prose/skills/prose/examples/03-code-review.prose delete mode 100644 extensions/open-prose/skills/prose/examples/04-write-and-refine.prose delete mode 100644 extensions/open-prose/skills/prose/examples/05-debug-issue.prose delete mode 100644 extensions/open-prose/skills/prose/examples/06-explain-codebase.prose delete mode 100644 extensions/open-prose/skills/prose/examples/07-refactor.prose delete mode 100644 extensions/open-prose/skills/prose/examples/08-blog-post.prose delete mode 100644 extensions/open-prose/skills/prose/examples/09-research-with-agents.prose delete mode 100644 extensions/open-prose/skills/prose/examples/10-code-review-agents.prose delete mode 100644 extensions/open-prose/skills/prose/examples/11-skills-and-imports.prose delete mode 100644 extensions/open-prose/skills/prose/examples/12-secure-agent-permissions.prose delete mode 100644 extensions/open-prose/skills/prose/examples/13-variables-and-context.prose delete mode 100644 extensions/open-prose/skills/prose/examples/14-composition-blocks.prose delete mode 100644 extensions/open-prose/skills/prose/examples/15-inline-sequences.prose delete mode 100644 extensions/open-prose/skills/prose/examples/16-parallel-reviews.prose delete mode 100644 extensions/open-prose/skills/prose/examples/17-parallel-research.prose delete mode 100644 extensions/open-prose/skills/prose/examples/18-mixed-parallel-sequential.prose delete mode 100644 extensions/open-prose/skills/prose/examples/19-advanced-parallel.prose delete mode 100644 extensions/open-prose/skills/prose/examples/20-fixed-loops.prose delete mode 100644 extensions/open-prose/skills/prose/examples/21-pipeline-operations.prose delete mode 100644 extensions/open-prose/skills/prose/examples/22-error-handling.prose delete mode 100644 extensions/open-prose/skills/prose/examples/23-retry-with-backoff.prose delete mode 100644 extensions/open-prose/skills/prose/examples/24-choice-blocks.prose delete mode 100644 extensions/open-prose/skills/prose/examples/25-conditionals.prose delete mode 100644 extensions/open-prose/skills/prose/examples/26-parameterized-blocks.prose delete mode 100644 extensions/open-prose/skills/prose/examples/27-string-interpolation.prose delete mode 100644 extensions/open-prose/skills/prose/examples/28-automated-pr-review.prose delete mode 100644 extensions/open-prose/skills/prose/examples/28-gas-town.prose delete mode 100644 extensions/open-prose/skills/prose/examples/29-captains-chair.prose delete mode 100644 extensions/open-prose/skills/prose/examples/30-captains-chair-simple.prose delete mode 100644 extensions/open-prose/skills/prose/examples/31-captains-chair-with-memory.prose delete mode 100644 extensions/open-prose/skills/prose/examples/33-pr-review-autofix.prose delete mode 100644 extensions/open-prose/skills/prose/examples/34-content-pipeline.prose delete mode 100644 extensions/open-prose/skills/prose/examples/35-feature-factory.prose delete mode 100644 extensions/open-prose/skills/prose/examples/36-bug-hunter.prose delete mode 100644 extensions/open-prose/skills/prose/examples/37-the-forge.prose delete mode 100644 extensions/open-prose/skills/prose/examples/38-skill-scan.prose delete mode 100644 extensions/open-prose/skills/prose/examples/39-architect-by-simulation.prose delete mode 100644 extensions/open-prose/skills/prose/examples/40-rlm-self-refine.prose delete mode 100644 extensions/open-prose/skills/prose/examples/41-rlm-divide-conquer.prose delete mode 100644 extensions/open-prose/skills/prose/examples/42-rlm-filter-recurse.prose delete mode 100644 extensions/open-prose/skills/prose/examples/43-rlm-pairwise.prose delete mode 100644 extensions/open-prose/skills/prose/examples/44-run-endpoint-ux-test.prose delete mode 100644 extensions/open-prose/skills/prose/examples/45-plugin-release.prose delete mode 100644 extensions/open-prose/skills/prose/examples/45-run-endpoint-ux-test-with-remediation.prose delete mode 100644 extensions/open-prose/skills/prose/examples/46-run-endpoint-ux-test-fast.prose delete mode 100644 extensions/open-prose/skills/prose/examples/46-workflow-crystallizer.prose delete mode 100644 extensions/open-prose/skills/prose/examples/47-language-self-improvement.prose delete mode 100644 extensions/open-prose/skills/prose/examples/48-habit-miner.prose delete mode 100644 extensions/open-prose/skills/prose/examples/49-prose-run-retrospective.prose delete mode 100644 extensions/open-prose/skills/prose/examples/README.md delete mode 100644 extensions/open-prose/skills/prose/examples/roadmap/README.md delete mode 100644 extensions/open-prose/skills/prose/examples/roadmap/iterative-refinement.prose delete mode 100644 extensions/open-prose/skills/prose/examples/roadmap/parallel-review.prose delete mode 100644 extensions/open-prose/skills/prose/examples/roadmap/simple-pipeline.prose delete mode 100644 extensions/open-prose/skills/prose/examples/roadmap/syntax/open-prose-syntax.prose delete mode 100644 extensions/open-prose/skills/prose/guidance/antipatterns.md delete mode 100644 extensions/open-prose/skills/prose/guidance/patterns.md delete mode 100644 extensions/open-prose/skills/prose/guidance/system-prompt.md delete mode 100644 extensions/open-prose/skills/prose/help.md delete mode 100644 extensions/open-prose/skills/prose/lib/README.md delete mode 100644 extensions/open-prose/skills/prose/lib/calibrator.prose delete mode 100644 extensions/open-prose/skills/prose/lib/cost-analyzer.prose delete mode 100644 extensions/open-prose/skills/prose/lib/error-forensics.prose delete mode 100644 extensions/open-prose/skills/prose/lib/inspector.prose delete mode 100644 extensions/open-prose/skills/prose/lib/profiler.prose delete mode 100644 extensions/open-prose/skills/prose/lib/program-improver.prose delete mode 100644 extensions/open-prose/skills/prose/lib/project-memory.prose delete mode 100644 extensions/open-prose/skills/prose/lib/user-memory.prose delete mode 100644 extensions/open-prose/skills/prose/lib/vm-improver.prose delete mode 100644 extensions/open-prose/skills/prose/primitives/session.md delete mode 100644 extensions/open-prose/skills/prose/prose.md delete mode 100644 extensions/open-prose/skills/prose/state/filesystem.md delete mode 100644 extensions/open-prose/skills/prose/state/in-context.md delete mode 100644 extensions/open-prose/skills/prose/state/postgres.md delete mode 100644 extensions/open-prose/skills/prose/state/sqlite.md delete mode 100644 extensions/phone-control/index.ts delete mode 100644 extensions/phone-control/openclaw.plugin.json delete mode 100644 extensions/qwen-portal-auth/README.md delete mode 100644 extensions/qwen-portal-auth/index.ts delete mode 100644 extensions/qwen-portal-auth/oauth.ts delete mode 100644 extensions/qwen-portal-auth/openclaw.plugin.json delete mode 100644 extensions/shared/resolve-target-test-helpers.ts delete mode 100644 extensions/signal/index.ts delete mode 100644 extensions/signal/openclaw.plugin.json delete mode 100644 extensions/signal/package.json delete mode 100644 extensions/signal/src/channel.ts delete mode 100644 extensions/signal/src/runtime.ts delete mode 100644 extensions/slack/index.ts delete mode 100644 extensions/slack/openclaw.plugin.json delete mode 100644 extensions/slack/package.json delete mode 100644 extensions/slack/src/channel.ts delete mode 100644 extensions/slack/src/runtime.ts delete mode 100644 extensions/synology-chat/index.ts delete mode 100644 extensions/synology-chat/openclaw.plugin.json delete mode 100644 extensions/synology-chat/package.json delete mode 100644 extensions/synology-chat/src/accounts.test.ts delete mode 100644 extensions/synology-chat/src/accounts.ts delete mode 100644 extensions/synology-chat/src/channel.test.ts delete mode 100644 extensions/synology-chat/src/channel.ts delete mode 100644 extensions/synology-chat/src/client.test.ts delete mode 100644 extensions/synology-chat/src/client.ts delete mode 100644 extensions/synology-chat/src/runtime.ts delete mode 100644 extensions/synology-chat/src/security.test.ts delete mode 100644 extensions/synology-chat/src/security.ts delete mode 100644 extensions/synology-chat/src/types.ts delete mode 100644 extensions/synology-chat/src/webhook-handler.test.ts delete mode 100644 extensions/synology-chat/src/webhook-handler.ts delete mode 100644 extensions/talk-voice/index.ts delete mode 100644 extensions/talk-voice/openclaw.plugin.json delete mode 100644 extensions/telegram/index.ts delete mode 100644 extensions/telegram/openclaw.plugin.json delete mode 100644 extensions/telegram/package.json delete mode 100644 extensions/telegram/src/channel.test.ts delete mode 100644 extensions/telegram/src/channel.ts delete mode 100644 extensions/telegram/src/runtime.ts delete mode 100644 extensions/thread-ownership/index.test.ts delete mode 100644 extensions/thread-ownership/index.ts delete mode 100644 extensions/thread-ownership/openclaw.plugin.json delete mode 100644 extensions/tlon/README.md delete mode 100644 extensions/tlon/index.ts delete mode 100644 extensions/tlon/openclaw.plugin.json delete mode 100644 extensions/tlon/package.json delete mode 100644 extensions/tlon/src/account-fields.ts delete mode 100644 extensions/tlon/src/channel.ts delete mode 100644 extensions/tlon/src/config-schema.test.ts delete mode 100644 extensions/tlon/src/config-schema.ts delete mode 100644 extensions/tlon/src/monitor/discovery.ts delete mode 100644 extensions/tlon/src/monitor/history.ts delete mode 100644 extensions/tlon/src/monitor/index.ts delete mode 100644 extensions/tlon/src/monitor/processed-messages.test.ts delete mode 100644 extensions/tlon/src/monitor/processed-messages.ts delete mode 100644 extensions/tlon/src/monitor/utils.ts delete mode 100644 extensions/tlon/src/onboarding.ts delete mode 100644 extensions/tlon/src/runtime.ts delete mode 100644 extensions/tlon/src/targets.ts delete mode 100644 extensions/tlon/src/types.ts delete mode 100644 extensions/tlon/src/urbit/auth.ssrf.test.ts delete mode 100644 extensions/tlon/src/urbit/auth.ts delete mode 100644 extensions/tlon/src/urbit/base-url.test.ts delete mode 100644 extensions/tlon/src/urbit/base-url.ts delete mode 100644 extensions/tlon/src/urbit/channel-client.ts delete mode 100644 extensions/tlon/src/urbit/channel-ops.ts delete mode 100644 extensions/tlon/src/urbit/context.ts delete mode 100644 extensions/tlon/src/urbit/errors.ts delete mode 100644 extensions/tlon/src/urbit/fetch.ts delete mode 100644 extensions/tlon/src/urbit/send.test.ts delete mode 100644 extensions/tlon/src/urbit/send.ts delete mode 100644 extensions/tlon/src/urbit/sse-client.test.ts delete mode 100644 extensions/tlon/src/urbit/sse-client.ts delete mode 100644 extensions/twitch/CHANGELOG.md delete mode 100644 extensions/twitch/README.md delete mode 100644 extensions/twitch/index.ts delete mode 100644 extensions/twitch/openclaw.plugin.json delete mode 100644 extensions/twitch/package.json delete mode 100644 extensions/twitch/src/access-control.test.ts delete mode 100644 extensions/twitch/src/access-control.ts delete mode 100644 extensions/twitch/src/actions.ts delete mode 100644 extensions/twitch/src/client-manager-registry.ts delete mode 100644 extensions/twitch/src/config-schema.ts delete mode 100644 extensions/twitch/src/config.test.ts delete mode 100644 extensions/twitch/src/config.ts delete mode 100644 extensions/twitch/src/monitor.ts delete mode 100644 extensions/twitch/src/onboarding.test.ts delete mode 100644 extensions/twitch/src/onboarding.ts delete mode 100644 extensions/twitch/src/outbound.test.ts delete mode 100644 extensions/twitch/src/outbound.ts delete mode 100644 extensions/twitch/src/plugin.test.ts delete mode 100644 extensions/twitch/src/plugin.ts delete mode 100644 extensions/twitch/src/probe.test.ts delete mode 100644 extensions/twitch/src/probe.ts delete mode 100644 extensions/twitch/src/resolver.ts delete mode 100644 extensions/twitch/src/runtime.ts delete mode 100644 extensions/twitch/src/send.test.ts delete mode 100644 extensions/twitch/src/send.ts delete mode 100644 extensions/twitch/src/status.test.ts delete mode 100644 extensions/twitch/src/status.ts delete mode 100644 extensions/twitch/src/test-fixtures.ts delete mode 100644 extensions/twitch/src/token.test.ts delete mode 100644 extensions/twitch/src/token.ts delete mode 100644 extensions/twitch/src/twitch-client.test.ts delete mode 100644 extensions/twitch/src/twitch-client.ts delete mode 100644 extensions/twitch/src/types.ts delete mode 100644 extensions/twitch/src/utils/markdown.ts delete mode 100644 extensions/twitch/src/utils/twitch.ts delete mode 100644 extensions/twitch/test/setup.ts delete mode 100644 extensions/voice-call/CHANGELOG.md delete mode 100644 extensions/voice-call/README.md delete mode 100644 extensions/voice-call/index.ts delete mode 100644 extensions/voice-call/openclaw.plugin.json delete mode 100644 extensions/voice-call/package.json delete mode 100644 extensions/voice-call/src/allowlist.ts delete mode 100644 extensions/voice-call/src/cli.ts delete mode 100644 extensions/voice-call/src/config.test.ts delete mode 100644 extensions/voice-call/src/config.ts delete mode 100644 extensions/voice-call/src/core-bridge.ts delete mode 100644 extensions/voice-call/src/manager.test.ts delete mode 100644 extensions/voice-call/src/manager.ts delete mode 100644 extensions/voice-call/src/manager/context.ts delete mode 100644 extensions/voice-call/src/manager/events.test.ts delete mode 100644 extensions/voice-call/src/manager/events.ts delete mode 100644 extensions/voice-call/src/manager/lookup.ts delete mode 100644 extensions/voice-call/src/manager/outbound.ts delete mode 100644 extensions/voice-call/src/manager/state.ts delete mode 100644 extensions/voice-call/src/manager/store.ts delete mode 100644 extensions/voice-call/src/manager/timers.ts delete mode 100644 extensions/voice-call/src/manager/twiml.ts delete mode 100644 extensions/voice-call/src/media-stream.test.ts delete mode 100644 extensions/voice-call/src/media-stream.ts delete mode 100644 extensions/voice-call/src/providers/base.ts delete mode 100644 extensions/voice-call/src/providers/index.ts delete mode 100644 extensions/voice-call/src/providers/mock.ts delete mode 100644 extensions/voice-call/src/providers/plivo.test.ts delete mode 100644 extensions/voice-call/src/providers/plivo.ts delete mode 100644 extensions/voice-call/src/providers/stt-openai-realtime.ts delete mode 100644 extensions/voice-call/src/providers/telnyx.test.ts delete mode 100644 extensions/voice-call/src/providers/telnyx.ts delete mode 100644 extensions/voice-call/src/providers/tts-openai.ts delete mode 100644 extensions/voice-call/src/providers/twilio.test.ts delete mode 100644 extensions/voice-call/src/providers/twilio.ts delete mode 100644 extensions/voice-call/src/providers/twilio/api.ts delete mode 100644 extensions/voice-call/src/providers/twilio/webhook.ts delete mode 100644 extensions/voice-call/src/response-generator.ts delete mode 100644 extensions/voice-call/src/runtime.ts delete mode 100644 extensions/voice-call/src/telephony-audio.ts delete mode 100644 extensions/voice-call/src/telephony-tts.test.ts delete mode 100644 extensions/voice-call/src/telephony-tts.ts delete mode 100644 extensions/voice-call/src/tunnel.ts delete mode 100644 extensions/voice-call/src/types.ts delete mode 100644 extensions/voice-call/src/utils.ts delete mode 100644 extensions/voice-call/src/voice-mapping.ts delete mode 100644 extensions/voice-call/src/webhook-security.test.ts delete mode 100644 extensions/voice-call/src/webhook-security.ts delete mode 100644 extensions/voice-call/src/webhook.test.ts delete mode 100644 extensions/voice-call/src/webhook.ts delete mode 100644 extensions/whatsapp/index.ts delete mode 100644 extensions/whatsapp/openclaw.plugin.json delete mode 100644 extensions/whatsapp/package.json delete mode 100644 extensions/whatsapp/src/channel.ts delete mode 100644 extensions/whatsapp/src/resolve-target.test.ts delete mode 100644 extensions/whatsapp/src/runtime.ts delete mode 100644 extensions/zalo/CHANGELOG.md delete mode 100644 extensions/zalo/README.md delete mode 100644 extensions/zalo/index.ts delete mode 100644 extensions/zalo/openclaw.plugin.json delete mode 100644 extensions/zalo/package.json delete mode 100644 extensions/zalo/src/accounts.ts delete mode 100644 extensions/zalo/src/actions.ts delete mode 100644 extensions/zalo/src/api.ts delete mode 100644 extensions/zalo/src/channel.directory.test.ts delete mode 100644 extensions/zalo/src/channel.ts delete mode 100644 extensions/zalo/src/config-schema.ts delete mode 100644 extensions/zalo/src/monitor.ts delete mode 100644 extensions/zalo/src/monitor.webhook.test.ts delete mode 100644 extensions/zalo/src/onboarding.ts delete mode 100644 extensions/zalo/src/probe.ts delete mode 100644 extensions/zalo/src/proxy.ts delete mode 100644 extensions/zalo/src/runtime.ts delete mode 100644 extensions/zalo/src/send.ts delete mode 100644 extensions/zalo/src/status-issues.ts delete mode 100644 extensions/zalo/src/token.ts delete mode 100644 extensions/zalo/src/types.ts delete mode 100644 extensions/zalouser/CHANGELOG.md delete mode 100644 extensions/zalouser/README.md delete mode 100644 extensions/zalouser/index.ts delete mode 100644 extensions/zalouser/openclaw.plugin.json delete mode 100644 extensions/zalouser/package.json delete mode 100644 extensions/zalouser/src/accounts.ts delete mode 100644 extensions/zalouser/src/channel.test.ts delete mode 100644 extensions/zalouser/src/channel.ts delete mode 100644 extensions/zalouser/src/config-schema.ts delete mode 100644 extensions/zalouser/src/monitor.ts delete mode 100644 extensions/zalouser/src/onboarding.ts delete mode 100644 extensions/zalouser/src/probe.ts delete mode 100644 extensions/zalouser/src/runtime.ts delete mode 100644 extensions/zalouser/src/send.ts delete mode 100644 extensions/zalouser/src/status-issues.test.ts delete mode 100644 extensions/zalouser/src/status-issues.ts delete mode 100644 extensions/zalouser/src/tool.ts delete mode 100644 extensions/zalouser/src/types.ts delete mode 100644 extensions/zalouser/src/zca.ts delete mode 100644 fly.private.toml delete mode 100644 fly.toml delete mode 100755 git-hooks/pre-commit delete mode 100644 openclaw.podman.env delete mode 100644 packages/clawdbot/index.js delete mode 100644 packages/clawdbot/package.json delete mode 100644 packages/clawdbot/scripts/postinstall.js delete mode 100644 packages/moltbot/index.js delete mode 100644 packages/moltbot/package.json delete mode 100644 packages/moltbot/scripts/postinstall.js delete mode 100644 patches/.gitkeep delete mode 100644 render.yaml delete mode 100755 scripts/auth-monitor.sh delete mode 100644 scripts/bench-model.ts delete mode 100755 scripts/build-and-run-mac.sh delete mode 100644 scripts/build-docs-list.mjs delete mode 100755 scripts/build_icon.sh delete mode 100755 scripts/bundle-a2ui.sh delete mode 100755 scripts/changelog-to-html.sh delete mode 100644 scripts/check-composite-action-input-interpolation.py delete mode 100644 scripts/check-ts-max-loc.ts delete mode 100755 scripts/claude-auth-status.sh delete mode 100755 scripts/clawlog.sh delete mode 100644 scripts/clawtributors-map.json delete mode 100755 scripts/codesign-mac-app.sh delete mode 100644 scripts/codespell-dictionary.txt delete mode 100644 scripts/codespell-ignore.txt delete mode 100755 scripts/committer delete mode 100755 scripts/create-dmg.sh delete mode 100644 scripts/cron_usage_report.ts delete mode 100644 scripts/debug-claude-usage.ts delete mode 100644 scripts/dev/gateway-smoke.ts delete mode 100644 scripts/dev/gateway-ws-client.ts delete mode 100644 scripts/dev/ios-node-e2e.ts delete mode 100755 scripts/dev/ios-pull-gateway-log.sh delete mode 100644 scripts/dev/test-device-pair-telegram.ts delete mode 100644 scripts/docker/cleanup-smoke/Dockerfile delete mode 100755 scripts/docker/cleanup-smoke/run.sh delete mode 100644 scripts/docker/install-sh-e2e/Dockerfile delete mode 100755 scripts/docker/install-sh-e2e/run.sh delete mode 100644 scripts/docker/install-sh-nonroot/Dockerfile delete mode 100644 scripts/docker/install-sh-nonroot/run.sh delete mode 100644 scripts/docker/install-sh-smoke/Dockerfile delete mode 100755 scripts/docker/install-sh-smoke/run.sh delete mode 100644 scripts/docs-i18n/doc_mode.go delete mode 100644 scripts/docs-i18n/glossary.go delete mode 100644 scripts/docs-i18n/go.mod delete mode 100644 scripts/docs-i18n/go.sum delete mode 100644 scripts/docs-i18n/html_translate.go delete mode 100644 scripts/docs-i18n/main.go delete mode 100644 scripts/docs-i18n/markdown_segments.go delete mode 100644 scripts/docs-i18n/masking.go delete mode 100644 scripts/docs-i18n/order.go delete mode 100644 scripts/docs-i18n/placeholders.go delete mode 100644 scripts/docs-i18n/process.go delete mode 100644 scripts/docs-i18n/prompt.go delete mode 100644 scripts/docs-i18n/segment.go delete mode 100644 scripts/docs-i18n/tm.go delete mode 100644 scripts/docs-i18n/translator.go delete mode 100644 scripts/docs-i18n/util.go delete mode 100644 scripts/docs-link-audit.mjs delete mode 100755 scripts/docs-list.js delete mode 100644 scripts/docs-spellcheck.sh delete mode 100644 scripts/e2e/Dockerfile delete mode 100644 scripts/e2e/Dockerfile.qr-import delete mode 100755 scripts/e2e/doctor-install-switch-docker.sh delete mode 100644 scripts/e2e/gateway-network-docker.sh delete mode 100755 scripts/e2e/onboard-docker.sh delete mode 100755 scripts/e2e/plugins-docker.sh delete mode 100755 scripts/e2e/qr-import-docker.sh delete mode 100644 scripts/firecrawl-compare.ts delete mode 100755 scripts/ios-configure-signing.sh delete mode 100755 scripts/ios-team-id.sh delete mode 100644 scripts/label-open-issues.ts delete mode 100755 scripts/make_appcast.sh delete mode 100755 scripts/mobile-reauth.sh delete mode 100755 scripts/notarize-mac-artifact.sh delete mode 100755 scripts/package-mac-app.sh delete mode 100755 scripts/package-mac-dist.sh delete mode 100644 scripts/podman/openclaw.container.in delete mode 100755 scripts/pr delete mode 100755 scripts/pr-merge delete mode 100755 scripts/pr-prepare delete mode 100755 scripts/pr-review delete mode 100644 scripts/pre-commit/filter-staged-files.mjs delete mode 100755 scripts/pre-commit/run-node-tool.sh delete mode 100644 scripts/protocol-gen-swift.ts delete mode 100644 scripts/protocol-gen.ts delete mode 100644 scripts/readability-basic-compare.ts delete mode 100755 scripts/recover-orphaned-processes.sh delete mode 100755 scripts/release-check.ts delete mode 100644 scripts/repro/tsx-name-repro.ts delete mode 100755 scripts/restart-mac.sh delete mode 100644 scripts/run-node.d.mts delete mode 100644 scripts/run-node.mjs delete mode 100755 scripts/run-openclaw-podman.sh delete mode 100755 scripts/sandbox-browser-entrypoint.sh delete mode 100755 scripts/sandbox-browser-setup.sh delete mode 100755 scripts/sandbox-common-setup.sh delete mode 100755 scripts/sandbox-setup.sh delete mode 100755 scripts/setup-auth-system.sh delete mode 100644 scripts/shell-helpers/README.md delete mode 100755 scripts/shell-helpers/clawdock-helpers.sh delete mode 100644 scripts/sqlite-vec-smoke.mjs delete mode 100755 scripts/standalone-hoist-pnpm.sh delete mode 100644 scripts/sync-labels.ts delete mode 100644 scripts/sync-moonshot-docs.ts delete mode 100644 scripts/sync-plugin-versions.ts delete mode 100644 scripts/systemd/openclaw-auth-monitor.service delete mode 100644 scripts/systemd/openclaw-auth-monitor.timer delete mode 100644 scripts/termux-auth-widget.sh delete mode 100644 scripts/termux-quick-auth.sh delete mode 100644 scripts/termux-sync-widget.sh delete mode 100755 scripts/test-cleanup-docker.sh delete mode 100755 scripts/test-force.ts delete mode 100755 scripts/test-install-sh-docker.sh delete mode 100755 scripts/test-install-sh-e2e-docker.sh delete mode 100755 scripts/test-live-gateway-models-docker.sh delete mode 100755 scripts/test-live-models-docker.sh delete mode 100644 scripts/test-parallel.mjs delete mode 100644 scripts/test-shell-completion.ts delete mode 100644 scripts/ui.js delete mode 100644 scripts/update-clawtributors.ts delete mode 100644 scripts/update-clawtributors.types.ts delete mode 100644 scripts/vitest-slowest.mjs delete mode 100644 scripts/watch-node.d.mts delete mode 100644 scripts/watch-node.mjs delete mode 100644 scripts/write-build-info.ts delete mode 100644 scripts/zai-fallback-repro.ts delete mode 100755 setup-podman.sh delete mode 100644 skills/1password/SKILL.md delete mode 100644 skills/1password/references/cli-examples.md delete mode 100644 skills/1password/references/get-started.md delete mode 100644 skills/apple-notes/SKILL.md delete mode 100644 skills/apple-reminders/SKILL.md delete mode 100644 skills/bear-notes/SKILL.md delete mode 100644 skills/blogwatcher/SKILL.md delete mode 100644 skills/blucli/SKILL.md delete mode 100644 skills/bluebubbles/SKILL.md delete mode 100644 skills/camsnap/SKILL.md delete mode 100644 skills/canvas/SKILL.md delete mode 100644 skills/clawhub/SKILL.md delete mode 100644 skills/coding-agent/SKILL.md delete mode 100644 skills/discord/SKILL.md delete mode 100644 skills/eightctl/SKILL.md delete mode 100644 skills/food-order/SKILL.md delete mode 100644 skills/gemini/SKILL.md delete mode 100644 skills/gh-issues/SKILL.md delete mode 100644 skills/gifgrep/SKILL.md delete mode 100644 skills/github/SKILL.md delete mode 100644 skills/gog/SKILL.md delete mode 100644 skills/goplaces/SKILL.md delete mode 100644 skills/healthcheck/SKILL.md delete mode 100644 skills/himalaya/SKILL.md delete mode 100644 skills/himalaya/references/configuration.md delete mode 100644 skills/himalaya/references/message-composition.md delete mode 100644 skills/imsg/SKILL.md delete mode 100644 skills/mcporter/SKILL.md delete mode 100644 skills/model-usage/SKILL.md delete mode 100644 skills/model-usage/references/codexbar-cli.md delete mode 100644 skills/model-usage/scripts/model_usage.py delete mode 100644 skills/nano-banana-pro/SKILL.md delete mode 100755 skills/nano-banana-pro/scripts/generate_image.py delete mode 100644 skills/nano-pdf/SKILL.md delete mode 100644 skills/notion/SKILL.md delete mode 100644 skills/obsidian/SKILL.md delete mode 100644 skills/openai-image-gen/SKILL.md delete mode 100644 skills/openai-image-gen/scripts/gen.py delete mode 100644 skills/openai-whisper-api/SKILL.md delete mode 100644 skills/openai-whisper-api/scripts/transcribe.sh delete mode 100644 skills/openai-whisper/SKILL.md delete mode 100644 skills/openhue/SKILL.md delete mode 100644 skills/oracle/SKILL.md delete mode 100644 skills/ordercli/SKILL.md delete mode 100644 skills/peekaboo/SKILL.md delete mode 100644 skills/sag/SKILL.md delete mode 100644 skills/session-logs/SKILL.md delete mode 100644 skills/sherpa-onnx-tts/SKILL.md delete mode 100755 skills/sherpa-onnx-tts/bin/sherpa-onnx-tts delete mode 100644 skills/skill-creator/SKILL.md delete mode 100644 skills/skill-creator/license.txt delete mode 100644 skills/skill-creator/scripts/init_skill.py delete mode 100644 skills/skill-creator/scripts/package_skill.py delete mode 100644 skills/skill-creator/scripts/quick_validate.py delete mode 100644 skills/skill-creator/scripts/test_package_skill.py delete mode 100644 skills/slack/SKILL.md delete mode 100644 skills/software-engineering/SKILL.md delete mode 100644 skills/songsee/SKILL.md delete mode 100644 skills/sonoscli/SKILL.md delete mode 100644 skills/spotify-player/SKILL.md delete mode 100644 skills/summarize/SKILL.md delete mode 100644 skills/things-mac/SKILL.md delete mode 100644 skills/tmux/SKILL.md delete mode 100755 skills/tmux/scripts/find-sessions.sh delete mode 100755 skills/tmux/scripts/wait-for-text.sh delete mode 100644 skills/trello/SKILL.md delete mode 100644 skills/video-frames/SKILL.md delete mode 100644 skills/video-frames/scripts/frame.sh delete mode 100644 skills/voice-call/SKILL.md delete mode 100644 skills/wacli/SKILL.md delete mode 100644 skills/weather/SKILL.md delete mode 100644 skills/xurl/SKILL.md delete mode 100644 src/channels/chat-type.ts delete mode 100644 src/config/types.agent-defaults.ts delete mode 100644 src/config/types.agents.ts delete mode 100644 src/config/types.approvals.ts delete mode 100644 src/config/types.auth.ts delete mode 100644 src/config/types.base.ts delete mode 100644 src/config/types.browser.ts delete mode 100644 src/config/types.channels.ts delete mode 100644 src/config/types.cron.ts delete mode 100644 src/config/types.discord.ts delete mode 100644 src/config/types.gateway.ts delete mode 100644 src/config/types.googlechat.ts delete mode 100644 src/config/types.hooks.ts delete mode 100644 src/config/types.imessage.ts delete mode 100644 src/config/types.irc.ts delete mode 100644 src/config/types.memory.ts delete mode 100644 src/config/types.messages.ts delete mode 100644 src/config/types.models.ts delete mode 100644 src/config/types.msteams.ts delete mode 100644 src/config/types.node-host.ts delete mode 100644 src/config/types.openclaw.ts delete mode 100644 src/config/types.plugins.ts delete mode 100644 src/config/types.queue.ts delete mode 100644 src/config/types.sandbox.ts delete mode 100644 src/config/types.signal.ts delete mode 100644 src/config/types.skills.ts delete mode 100644 src/config/types.slack.ts delete mode 100644 src/config/types.telegram.ts delete mode 100644 src/config/types.tools.ts delete mode 100644 src/config/types.tts.ts delete mode 100644 src/config/types.whatsapp.ts delete mode 100644 src/discord/pluralkit.ts delete mode 100644 src/plugins/runtime.ts delete mode 100644 src/test-utils/channel-plugins.ts delete mode 100644 test/appcast.test.ts delete mode 100644 test/evals/README.md delete mode 100644 test/evals/REGRESSION_VERIFICATION_REPORT.md delete mode 100644 test/evals/dataset.ts delete mode 100644 test/evals/graders.test.ts delete mode 100644 test/evals/graders.ts delete mode 100644 test/evals/run-evals.ts delete mode 100644 test/evals/types.ts delete mode 100644 test/evals/vitest.config.ts delete mode 100644 test/fixtures/child-process-bridge/child.js delete mode 100644 test/fixtures/exec-allowlist-shell-parser-parity.json delete mode 100644 test/fixtures/hooks-install/npm-pack-hooks.tgz delete mode 100644 test/fixtures/hooks-install/tar-evil-id.tar delete mode 100644 test/fixtures/hooks-install/tar-hooks.tar delete mode 100644 test/fixtures/hooks-install/tar-reserved-id.tar delete mode 100644 test/fixtures/hooks-install/tar-traversal.tar delete mode 100644 test/fixtures/hooks-install/zip-hooks.zip delete mode 100644 test/fixtures/hooks-install/zip-traversal.zip delete mode 100644 test/gateway.multi.e2e.test.ts delete mode 100644 test/git-hooks-pre-commit.e2e.test.ts delete mode 100644 test/global-setup.ts delete mode 100644 test/helpers/dispatch-inbound-capture.ts delete mode 100644 test/helpers/envelope-timestamp.ts delete mode 100644 test/helpers/inbound-contract-capture.ts delete mode 100644 test/helpers/inbound-contract.ts delete mode 100644 test/helpers/mock-incoming-request.ts delete mode 100644 test/helpers/normalize-text.ts delete mode 100644 test/helpers/paths.ts delete mode 100644 test/helpers/poll.ts delete mode 100644 test/helpers/temp-home.ts delete mode 100644 test/media-understanding.auto.e2e.test.ts delete mode 100644 test/mocks/baileys.ts delete mode 100644 test/provider-timeout.e2e.test.ts delete mode 100644 test/scripts/ui.test.ts delete mode 100644 test/setup.ts delete mode 100644 test/test-env.ts delete mode 100644 ui/index.html delete mode 100644 ui/package-lock.json delete mode 100644 ui/package.json delete mode 100644 ui/public/apple-touch-icon.png delete mode 100644 ui/public/favicon-32.png delete mode 100644 ui/public/favicon.ico delete mode 100644 ui/public/favicon.svg delete mode 100644 ui/src/i18n/index.ts delete mode 100644 ui/src/i18n/lib/lit-controller.ts delete mode 100644 ui/src/i18n/lib/translate.ts delete mode 100644 ui/src/i18n/lib/types.ts delete mode 100644 ui/src/i18n/locales/en.ts delete mode 100644 ui/src/i18n/locales/pt-BR.ts delete mode 100644 ui/src/i18n/locales/zh-CN.ts delete mode 100644 ui/src/i18n/locales/zh-TW.ts delete mode 100644 ui/src/i18n/test/translate.test.ts delete mode 100644 ui/src/main.ts delete mode 100644 ui/src/styles.css delete mode 100644 ui/src/styles/base.css delete mode 100644 ui/src/styles/chat.css delete mode 100644 ui/src/styles/chat/grouped.css delete mode 100644 ui/src/styles/chat/layout.css delete mode 100644 ui/src/styles/chat/sidebar.css delete mode 100644 ui/src/styles/chat/text.css delete mode 100644 ui/src/styles/chat/tool-cards.css delete mode 100644 ui/src/styles/components.css delete mode 100644 ui/src/styles/config.css delete mode 100644 ui/src/styles/layout.css delete mode 100644 ui/src/styles/layout.mobile.css delete mode 100644 ui/src/ui/__screenshots__/config-form.browser.test.ts/config-form-renderer-flags-unsupported-unions-1.png delete mode 100644 ui/src/ui/__screenshots__/config-form.browser.test.ts/config-form-renderer-renders-inputs-and-patches-values-1.png delete mode 100644 ui/src/ui/__screenshots__/config-form.browser.test.ts/config-form-renderer-renders-union-literals-as-select-options-1.png delete mode 100644 ui/src/ui/__screenshots__/navigation.browser.test.ts/control-UI-routing-auto-scrolls-chat-history-to-the-latest-message-1.png delete mode 100644 ui/src/ui/app-channels.ts delete mode 100644 ui/src/ui/app-chat.ts delete mode 100644 ui/src/ui/app-defaults.ts delete mode 100644 ui/src/ui/app-events.ts delete mode 100644 ui/src/ui/app-gateway.node.test.ts delete mode 100644 ui/src/ui/app-gateway.ts delete mode 100644 ui/src/ui/app-lifecycle.ts delete mode 100644 ui/src/ui/app-polling.ts delete mode 100644 ui/src/ui/app-render-usage-tab.ts delete mode 100644 ui/src/ui/app-render.helpers.node.test.ts delete mode 100644 ui/src/ui/app-render.helpers.ts delete mode 100644 ui/src/ui/app-render.ts delete mode 100644 ui/src/ui/app-scroll.test.ts delete mode 100644 ui/src/ui/app-scroll.ts delete mode 100644 ui/src/ui/app-settings.test.ts delete mode 100644 ui/src/ui/app-settings.ts delete mode 100644 ui/src/ui/app-tool-stream.node.test.ts delete mode 100644 ui/src/ui/app-tool-stream.ts delete mode 100644 ui/src/ui/app-view-state.ts delete mode 100644 ui/src/ui/app.ts delete mode 100644 ui/src/ui/assistant-identity.ts delete mode 100644 ui/src/ui/chat-markdown.browser.test.ts delete mode 100644 ui/src/ui/chat/constants.ts delete mode 100644 ui/src/ui/chat/copy-as-markdown.ts delete mode 100644 ui/src/ui/chat/grouped-render.ts delete mode 100644 ui/src/ui/chat/message-extract.test.ts delete mode 100644 ui/src/ui/chat/message-extract.ts delete mode 100644 ui/src/ui/chat/message-normalizer.test.ts delete mode 100644 ui/src/ui/chat/message-normalizer.ts delete mode 100644 ui/src/ui/chat/tool-cards.ts delete mode 100644 ui/src/ui/chat/tool-helpers.test.ts delete mode 100644 ui/src/ui/chat/tool-helpers.ts delete mode 100644 ui/src/ui/components/resizable-divider.ts delete mode 100644 ui/src/ui/config-form.browser.test.ts delete mode 100644 ui/src/ui/contracts/chat-envelope.ts delete mode 100644 ui/src/ui/contracts/control-ui-contract.ts delete mode 100644 ui/src/ui/contracts/device-auth.ts delete mode 100644 ui/src/ui/contracts/format-duration.ts delete mode 100644 ui/src/ui/contracts/format-relative.ts delete mode 100644 ui/src/ui/contracts/gateway-client-info.ts delete mode 100644 ui/src/ui/contracts/gateway-device-auth.ts delete mode 100644 ui/src/ui/contracts/gateway-events.ts delete mode 100644 ui/src/ui/contracts/reasoning-tags.ts delete mode 100644 ui/src/ui/contracts/session-key.ts delete mode 100644 ui/src/ui/contracts/strip-inbound-meta.ts delete mode 100644 ui/src/ui/contracts/tool-display-common.ts delete mode 100644 ui/src/ui/contracts/tool-policy.ts delete mode 100644 ui/src/ui/contracts/update.ts delete mode 100644 ui/src/ui/contracts/usage-aggregates.ts delete mode 100644 ui/src/ui/controllers/agent-files.ts delete mode 100644 ui/src/ui/controllers/agent-identity.ts delete mode 100644 ui/src/ui/controllers/agent-skills.ts delete mode 100644 ui/src/ui/controllers/agents.ts delete mode 100644 ui/src/ui/controllers/assistant-identity.ts delete mode 100644 ui/src/ui/controllers/channels.ts delete mode 100644 ui/src/ui/controllers/channels.types.ts delete mode 100644 ui/src/ui/controllers/chat.test.ts delete mode 100644 ui/src/ui/controllers/chat.ts delete mode 100644 ui/src/ui/controllers/config.test.ts delete mode 100644 ui/src/ui/controllers/config.ts delete mode 100644 ui/src/ui/controllers/config/form-coerce.ts delete mode 100644 ui/src/ui/controllers/config/form-utils.node.test.ts delete mode 100644 ui/src/ui/controllers/config/form-utils.ts delete mode 100644 ui/src/ui/controllers/control-ui-bootstrap.test.ts delete mode 100644 ui/src/ui/controllers/control-ui-bootstrap.ts delete mode 100644 ui/src/ui/controllers/cron.test.ts delete mode 100644 ui/src/ui/controllers/cron.ts delete mode 100644 ui/src/ui/controllers/debug.ts delete mode 100644 ui/src/ui/controllers/devices.ts delete mode 100644 ui/src/ui/controllers/exec-approval.ts delete mode 100644 ui/src/ui/controllers/exec-approvals.ts delete mode 100644 ui/src/ui/controllers/logs.ts delete mode 100644 ui/src/ui/controllers/nodes.ts delete mode 100644 ui/src/ui/controllers/presence.ts delete mode 100644 ui/src/ui/controllers/sessions.test.ts delete mode 100644 ui/src/ui/controllers/sessions.ts delete mode 100644 ui/src/ui/controllers/skills.ts delete mode 100644 ui/src/ui/controllers/usage.node.test.ts delete mode 100644 ui/src/ui/controllers/usage.ts delete mode 100644 ui/src/ui/data/moonshot-kimi-k2.ts delete mode 100644 ui/src/ui/device-auth.ts delete mode 100644 ui/src/ui/device-identity.ts delete mode 100644 ui/src/ui/focus-mode.browser.test.ts delete mode 100644 ui/src/ui/format.test.ts delete mode 100644 ui/src/ui/format.ts delete mode 100644 ui/src/ui/gateway.ts delete mode 100644 ui/src/ui/icons.ts delete mode 100644 ui/src/ui/markdown.test.ts delete mode 100644 ui/src/ui/markdown.ts delete mode 100644 ui/src/ui/navigation.browser.test.ts delete mode 100644 ui/src/ui/navigation.test.ts delete mode 100644 ui/src/ui/navigation.ts delete mode 100644 ui/src/ui/presenter.ts delete mode 100644 ui/src/ui/storage.ts delete mode 100644 ui/src/ui/test-helpers/app-mount.ts delete mode 100644 ui/src/ui/text-direction.test.ts delete mode 100644 ui/src/ui/text-direction.ts delete mode 100644 ui/src/ui/theme-transition.ts delete mode 100644 ui/src/ui/theme.ts delete mode 100644 ui/src/ui/tool-display.json delete mode 100644 ui/src/ui/tool-display.ts delete mode 100644 ui/src/ui/types.ts delete mode 100644 ui/src/ui/types/chat-types.ts delete mode 100644 ui/src/ui/ui-types.ts delete mode 100644 ui/src/ui/usage-helpers.node.test.ts delete mode 100644 ui/src/ui/usage-helpers.ts delete mode 100644 ui/src/ui/usage-types.ts delete mode 100644 ui/src/ui/uuid.test.ts delete mode 100644 ui/src/ui/uuid.ts delete mode 100644 ui/src/ui/views/agents-panels-status-files.ts delete mode 100644 ui/src/ui/views/agents-panels-tools-skills.ts delete mode 100644 ui/src/ui/views/agents-utils.ts delete mode 100644 ui/src/ui/views/agents.ts delete mode 100644 ui/src/ui/views/channels.config.ts delete mode 100644 ui/src/ui/views/channels.discord.ts delete mode 100644 ui/src/ui/views/channels.googlechat.ts delete mode 100644 ui/src/ui/views/channels.imessage.ts delete mode 100644 ui/src/ui/views/channels.nostr-profile-form.ts delete mode 100644 ui/src/ui/views/channels.nostr.ts delete mode 100644 ui/src/ui/views/channels.shared.ts delete mode 100644 ui/src/ui/views/channels.signal.ts delete mode 100644 ui/src/ui/views/channels.slack.ts delete mode 100644 ui/src/ui/views/channels.telegram.ts delete mode 100644 ui/src/ui/views/channels.ts delete mode 100644 ui/src/ui/views/channels.types.ts delete mode 100644 ui/src/ui/views/channels.whatsapp.ts delete mode 100644 ui/src/ui/views/chat.test.ts delete mode 100644 ui/src/ui/views/chat.ts delete mode 100644 ui/src/ui/views/config-form.analyze.ts delete mode 100644 ui/src/ui/views/config-form.node.ts delete mode 100644 ui/src/ui/views/config-form.render.ts delete mode 100644 ui/src/ui/views/config-form.shared.ts delete mode 100644 ui/src/ui/views/config-form.ts delete mode 100644 ui/src/ui/views/config.browser.test.ts delete mode 100644 ui/src/ui/views/config.ts delete mode 100644 ui/src/ui/views/cron.test.ts delete mode 100644 ui/src/ui/views/cron.ts delete mode 100644 ui/src/ui/views/debug.ts delete mode 100644 ui/src/ui/views/exec-approval.ts delete mode 100644 ui/src/ui/views/gateway-url-confirmation.ts delete mode 100644 ui/src/ui/views/instances.ts delete mode 100644 ui/src/ui/views/logs.ts delete mode 100644 ui/src/ui/views/markdown-sidebar.ts delete mode 100644 ui/src/ui/views/nodes-exec-approvals.ts delete mode 100644 ui/src/ui/views/nodes.ts delete mode 100644 ui/src/ui/views/overview.ts delete mode 100644 ui/src/ui/views/sessions.test.ts delete mode 100644 ui/src/ui/views/sessions.ts delete mode 100644 ui/src/ui/views/skills-grouping.ts delete mode 100644 ui/src/ui/views/skills-shared.ts delete mode 100644 ui/src/ui/views/skills.ts delete mode 100644 ui/src/ui/views/usage-metrics.ts delete mode 100644 ui/src/ui/views/usage-query.ts delete mode 100644 ui/src/ui/views/usage-render-details.test.ts delete mode 100644 ui/src/ui/views/usage-render-details.ts delete mode 100644 ui/src/ui/views/usage-render-overview.ts delete mode 100644 ui/src/ui/views/usage-styles/usageStyles-part1.ts delete mode 100644 ui/src/ui/views/usage-styles/usageStyles-part2.ts delete mode 100644 ui/src/ui/views/usage-styles/usageStyles-part3.ts delete mode 100644 ui/src/ui/views/usage.ts delete mode 100644 ui/src/ui/views/usageStyles.ts delete mode 100644 ui/src/ui/views/usageTypes.ts delete mode 100644 ui/vite.config.ts delete mode 100644 ui/vitest.config.ts delete mode 100644 ui/vitest.node.config.ts delete mode 100644 vendor/a2ui/.gemini/GEMINI.md delete mode 100644 vendor/a2ui/.github/workflows/docs.yml delete mode 100644 vendor/a2ui/.github/workflows/editor_build.yml delete mode 100644 vendor/a2ui/.github/workflows/inspector_build.yml delete mode 100644 vendor/a2ui/.github/workflows/java_build_and_test.yml delete mode 100644 vendor/a2ui/.github/workflows/lit_samples_build.yml delete mode 100644 vendor/a2ui/.github/workflows/ng_build_and_test.yml delete mode 100644 vendor/a2ui/.github/workflows/python_samples_build.yml delete mode 100644 vendor/a2ui/.github/workflows/web_build_and_test.yml delete mode 100644 vendor/a2ui/.gitignore delete mode 100644 vendor/a2ui/CONTRIBUTING.md delete mode 100644 vendor/a2ui/LICENSE delete mode 100644 vendor/a2ui/README.md delete mode 100644 vendor/a2ui/mkdocs.yaml delete mode 100644 vendor/a2ui/renderers/angular/.npmrc delete mode 100644 vendor/a2ui/renderers/angular/README.md delete mode 100644 vendor/a2ui/renderers/angular/angular.json delete mode 100644 vendor/a2ui/renderers/angular/ng-package.json delete mode 100644 vendor/a2ui/renderers/angular/package-lock.json delete mode 100644 vendor/a2ui/renderers/angular/package.json delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/audio.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/button.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/card.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/checkbox.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/column.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/datetime-input.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/default.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/divider.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/icon.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/image.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/list.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/modal.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/multiple-choice.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/row.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/slider.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/surface.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/tabs.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/text-field.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/text.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/catalog/video.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/config.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/data/index.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/data/markdown.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/data/processor.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/data/types.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/rendering/catalog.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/rendering/dynamic-component.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/rendering/index.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/rendering/renderer.ts delete mode 100644 vendor/a2ui/renderers/angular/src/lib/rendering/theming.ts delete mode 100644 vendor/a2ui/renderers/angular/src/public-api.ts delete mode 100644 vendor/a2ui/renderers/angular/tsconfig.json delete mode 100644 vendor/a2ui/renderers/angular/tsconfig.lib.json delete mode 100644 vendor/a2ui/renderers/angular/tsconfig.lib.prod.json delete mode 100644 vendor/a2ui/renderers/angular/tsconfig.spec.json delete mode 100644 vendor/a2ui/renderers/lit/.npmrc delete mode 100644 vendor/a2ui/renderers/lit/README delete mode 100644 vendor/a2ui/renderers/lit/README.md delete mode 100644 vendor/a2ui/renderers/lit/package-lock.json delete mode 100644 vendor/a2ui/renderers/lit/package.json delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/core.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/data/guards.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/data/model-processor.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/data/signal-model-processor.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/events/a2ui.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/events/base.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/events/events.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/index.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/model.test.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/schemas/.gitignore delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/schemas/server_to_client_with_standard_catalog.json delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/styles/behavior.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/styles/border.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/styles/colors.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/styles/icons.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/styles/index.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/styles/layout.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/styles/opacity.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/styles/shared.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/styles/type.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/styles/utils.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/types/client-event.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/types/colors.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/types/components.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/types/primitives.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/types/types.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/audio.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/button.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/card.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/checkbox.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/column.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/component-registry.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/context/theme.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/custom-components/index.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/datetime-input.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/directives/directives.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/directives/markdown.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/directives/sanitizer.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/divider.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/icon.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/image.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/list.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/modal.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/multiple-choice.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/root.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/row.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/slider.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/styles.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/surface.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/tabs.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/text-field.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/text.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/ui.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/utils/utils.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/utils/youtube.ts delete mode 100644 vendor/a2ui/renderers/lit/src/0.8/ui/video.ts delete mode 100644 vendor/a2ui/renderers/lit/src/index.ts delete mode 100644 vendor/a2ui/renderers/lit/tsconfig.json delete mode 100644 vendor/a2ui/requirements-docs.txt delete mode 100644 vendor/a2ui/specification/0.8/eval/.gitignore delete mode 100644 vendor/a2ui/specification/0.8/eval/GEMINI.md delete mode 100644 vendor/a2ui/specification/0.8/eval/README.md delete mode 100644 vendor/a2ui/specification/0.8/eval/genkit.conf.js delete mode 100644 vendor/a2ui/specification/0.8/eval/package.json delete mode 100644 vendor/a2ui/specification/0.8/eval/pnpm-lock.yaml delete mode 100644 vendor/a2ui/specification/0.8/eval/pnpm-workspace.yaml delete mode 100644 vendor/a2ui/specification/0.8/eval/src/basic_schema_matcher.ts delete mode 100644 vendor/a2ui/specification/0.8/eval/src/dev.ts delete mode 100644 vendor/a2ui/specification/0.8/eval/src/flows.ts delete mode 100644 vendor/a2ui/specification/0.8/eval/src/index.ts delete mode 100644 vendor/a2ui/specification/0.8/eval/src/message_type_matcher.ts delete mode 100644 vendor/a2ui/specification/0.8/eval/src/models.ts delete mode 100644 vendor/a2ui/specification/0.8/eval/src/prompts.ts delete mode 100644 vendor/a2ui/specification/0.8/eval/src/schema_matcher.ts delete mode 100644 vendor/a2ui/specification/0.8/eval/src/surface_update_schema_matcher.ts delete mode 100644 vendor/a2ui/specification/0.8/eval/src/validator.ts delete mode 100644 vendor/a2ui/specification/0.8/eval/tsconfig.json delete mode 100644 vendor/a2ui/specification/0.8/json/README.md delete mode 100644 vendor/a2ui/specification/0.8/json/a2ui_client_capabilities_schema.json delete mode 100644 vendor/a2ui/specification/0.8/json/catalog_description_schema.json delete mode 100644 vendor/a2ui/specification/0.8/json/client_to_server.json delete mode 100644 vendor/a2ui/specification/0.8/json/server_to_client.json delete mode 100644 vendor/a2ui/specification/0.8/json/server_to_client_with_standard_catalog.json delete mode 100644 vendor/a2ui/specification/0.8/json/standard_catalog_definition.json delete mode 100644 vendor/a2ui/specification/0.9/eval/.gitignore delete mode 100644 vendor/a2ui/specification/0.9/eval/README.md delete mode 100644 vendor/a2ui/specification/0.9/eval/genkit.conf.js delete mode 100644 vendor/a2ui/specification/0.9/eval/package.json delete mode 100644 vendor/a2ui/specification/0.9/eval/pnpm-lock.yaml delete mode 100644 vendor/a2ui/specification/0.9/eval/pnpm-workspace.yaml delete mode 100644 vendor/a2ui/specification/0.9/eval/src/ai.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/analysis_flow.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/dev.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/evaluation_flow.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/evaluator.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/generation_flow.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/generator.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/index.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/logger.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/models.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/prompts.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/rateLimiter.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/types.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/utils.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/src/validator.ts delete mode 100644 vendor/a2ui/specification/0.9/eval/tsconfig.json delete mode 100644 vendor/a2ui/specification/0.9/json/client_to_server.json delete mode 100644 vendor/a2ui/specification/0.9/json/common_types.json delete mode 100644 vendor/a2ui/specification/0.9/json/contact_form_example.jsonl delete mode 100644 vendor/a2ui/specification/0.9/json/server_to_client.json delete mode 100644 vendor/a2ui/specification/0.9/json/standard_catalog_definition.json delete mode 100644 vendor/a2ui/specification/0.9/json/standard_catalog_rules.txt delete mode 100755 vendor/a2ui/specification/0.9/validate.sh delete mode 100644 vitest.e2e.config.ts delete mode 100644 vitest.extensions.config.ts delete mode 100644 vitest.gateway.config.ts delete mode 100644 vitest.live.config.ts delete mode 100644 zizmor.yml diff --git a/.agent/workflows/update_clawdbot.md b/.agent/workflows/update_clawdbot.md deleted file mode 100644 index 04a079aab41..00000000000 --- a/.agent/workflows/update_clawdbot.md +++ /dev/null @@ -1,380 +0,0 @@ ---- -description: Update Clawdbot from upstream when branch has diverged (ahead/behind) ---- - -# Clawdbot Upstream Sync Workflow - -Use this workflow when your fork has diverged from upstream (e.g., "18 commits ahead, 29 commits behind"). - -## Quick Reference - -```bash -# Check divergence status -git fetch upstream && git rev-list --left-right --count main...upstream/main - -# Full sync (rebase preferred) -git fetch upstream && git rebase upstream/main && pnpm install && pnpm build && ./scripts/restart-mac.sh - -# Check for Swift 6.2 issues after sync -grep -r "FileManager\.default\|Thread\.isMainThread" src/ apps/ --include="*.swift" -``` - ---- - -## Step 1: Assess Divergence - -```bash -git fetch upstream -git log --oneline --left-right main...upstream/main | head -20 -``` - -This shows: - -- `<` = your local commits (ahead) -- `>` = upstream commits you're missing (behind) - -**Decision point:** - -- Few local commits, many upstream → **Rebase** (cleaner history) -- Many local commits or shared branch → **Merge** (preserves history) - ---- - -## Step 2A: Rebase Strategy (Preferred) - -Replays your commits on top of upstream. Results in linear history. - -```bash -# Ensure working tree is clean -git status - -# Rebase onto upstream -git rebase upstream/main -``` - -### Handling Rebase Conflicts - -```bash -# When conflicts occur: -# 1. Fix conflicts in the listed files -# 2. Stage resolved files -git add - -# 3. Continue rebase -git rebase --continue - -# If a commit is no longer needed (already in upstream): -git rebase --skip - -# To abort and return to original state: -git rebase --abort -``` - -### Common Conflict Patterns - -| File | Resolution | -| ---------------- | ------------------------------------------------ | -| `package.json` | Take upstream deps, keep local scripts if needed | -| `pnpm-lock.yaml` | Accept upstream, regenerate with `pnpm install` | -| `*.patch` files | Usually take upstream version | -| Source files | Merge logic carefully, prefer upstream structure | - ---- - -## Step 2B: Merge Strategy (Alternative) - -Preserves all history with a merge commit. - -```bash -git merge upstream/main --no-edit -``` - -Resolve conflicts same as rebase, then: - -```bash -git add -git commit -``` - ---- - -## Step 3: Rebuild Everything - -After sync completes: - -```bash -# Install dependencies (regenerates lock if needed) -pnpm install - -# Build TypeScript -pnpm build - -# Build UI assets -pnpm ui:build - -# Run diagnostics -pnpm clawdbot doctor -``` - ---- - -## Step 4: Rebuild macOS App - -```bash -# Full rebuild, sign, and launch -./scripts/restart-mac.sh - -# Or just package without restart -pnpm mac:package -``` - -### Install to /Applications - -```bash -# Kill running app -pkill -x "Clawdbot" || true - -# Move old version -mv /Applications/Clawdbot.app /tmp/Clawdbot-backup.app - -# Install new build -cp -R dist/Clawdbot.app /Applications/ - -# Launch -open /Applications/Clawdbot.app -``` - ---- - -## Step 4A: Verify macOS App & Agent - -After rebuilding the macOS app, always verify it works correctly: - -```bash -# Check gateway health -pnpm clawdbot health - -# Verify no zombie processes -ps aux | grep -E "(clawdbot|gateway)" | grep -v grep - -# Test agent functionality by sending a verification message -pnpm clawdbot agent --message "Verification: macOS app rebuild successful - agent is responding." --session-id YOUR_TELEGRAM_SESSION_ID - -# Confirm the message was received on Telegram -# (Check your Telegram chat with the bot) -``` - -**Important:** Always wait for the Telegram verification message before proceeding. If the agent doesn't respond, troubleshoot the gateway or model configuration before pushing. - ---- - -## Step 5: Handle Swift/macOS Build Issues (Common After Upstream Sync) - -Upstream updates may introduce Swift 6.2 / macOS 26 SDK incompatibilities. Use analyze-mode for systematic debugging: - -### Analyze-Mode Investigation - -```bash -# Gather context with parallel agents -morph-mcp_warpgrep_codebase_search search_string="Find deprecated FileManager.default and Thread.isMainThread usages in Swift files" repo_path="/Volumes/Main SSD/Developer/clawdis" -morph-mcp_warpgrep_codebase_search search_string="Locate Peekaboo submodule and macOS app Swift files with concurrency issues" repo_path="/Volumes/Main SSD/Developer/clawdis" -``` - -### Common Swift 6.2 Fixes - -**FileManager.default Deprecation:** - -```bash -# Search for deprecated usage -grep -r "FileManager\.default" src/ apps/ --include="*.swift" - -# Replace with proper initialization -# OLD: FileManager.default -# NEW: FileManager() -``` - -**Thread.isMainThread Deprecation:** - -```bash -# Search for deprecated usage -grep -r "Thread\.isMainThread" src/ apps/ --include="*.swift" - -# Replace with modern concurrency check -# OLD: Thread.isMainThread -# NEW: await MainActor.run { ... } or DispatchQueue.main.sync { ... } -``` - -### Peekaboo Submodule Fixes - -```bash -# Check Peekaboo for concurrency issues -cd src/canvas-host/a2ui -grep -r "Thread\.isMainThread\|FileManager\.default" . --include="*.swift" - -# Fix and rebuild submodule -cd /Volumes/Main SSD/Developer/clawdis -pnpm canvas:a2ui:bundle -``` - -### macOS App Concurrency Fixes - -```bash -# Check macOS app for issues -grep -r "Thread\.isMainThread\|FileManager\.default" apps/macos/ --include="*.swift" - -# Clean and rebuild after fixes -cd apps/macos && rm -rf .build .swiftpm -./scripts/restart-mac.sh -``` - -### Model Configuration Updates - -If upstream introduced new model configurations: - -```bash -# Check for OpenRouter API key requirements -grep -r "openrouter\|OPENROUTER" src/ --include="*.ts" --include="*.js" - -# Update clawdbot.json with fallback chains -# Add model fallback configurations as needed -``` - ---- - -## Step 6: Verify & Push - -```bash -# Verify everything works -pnpm clawdbot health -pnpm test - -# Push (force required after rebase) -git push origin main --force-with-lease - -# Or regular push after merge -git push origin main -``` - ---- - -## Troubleshooting - -### Build Fails After Sync - -```bash -# Clean and rebuild -rm -rf node_modules dist -pnpm install -pnpm build -``` - -### Type Errors (Bun/Node Incompatibility) - -Common issue: `fetch.preconnect` type mismatch. Fix by using `FetchLike` type instead of `typeof fetch`. - -### macOS App Crashes on Launch - -Usually resource bundle mismatch. Full rebuild required: - -```bash -cd apps/macos && rm -rf .build .swiftpm -./scripts/restart-mac.sh -``` - -### Patch Failures - -```bash -# Check patch status -pnpm install 2>&1 | grep -i patch - -# If patches fail, they may need updating for new dep versions -# Check patches/ directory against package.json patchedDependencies -``` - -### Swift 6.2 / macOS 26 SDK Build Failures - -**Symptoms:** Build fails with deprecation warnings about `FileManager.default` or `Thread.isMainThread` - -**Search-Mode Investigation:** - -```bash -# Exhaustive search for deprecated APIs -morph-mcp_warpgrep_codebase_search search_string="Find all Swift files using deprecated FileManager.default or Thread.isMainThread" repo_path="/Volumes/Main SSD/Developer/clawdis" -``` - -**Quick Fix Commands:** - -```bash -# Find all affected files -find . -name "*.swift" -exec grep -l "FileManager\.default\|Thread\.isMainThread" {} \; - -# Replace FileManager.default with FileManager() -find . -name "*.swift" -exec sed -i '' 's/FileManager\.default/FileManager()/g' {} \; - -# For Thread.isMainThread, need manual review of each usage -grep -rn "Thread\.isMainThread" --include="*.swift" . -``` - -**Rebuild After Fixes:** - -```bash -# Clean all build artifacts -rm -rf apps/macos/.build apps/macos/.swiftpm -rm -rf src/canvas-host/a2ui/.build - -# Rebuild Peekaboo bundle -pnpm canvas:a2ui:bundle - -# Full macOS rebuild -./scripts/restart-mac.sh -``` - ---- - -## Automation Script - -Save as `scripts/sync-upstream.sh`: - -```bash -#!/usr/bin/env bash -set -euo pipefail - -echo "==> Fetching upstream..." -git fetch upstream - -echo "==> Current divergence:" -git rev-list --left-right --count main...upstream/main - -echo "==> Rebasing onto upstream/main..." -git rebase upstream/main - -echo "==> Installing dependencies..." -pnpm install - -echo "==> Building..." -pnpm build -pnpm ui:build - -echo "==> Running doctor..." -pnpm clawdbot doctor - -echo "==> Rebuilding macOS app..." -./scripts/restart-mac.sh - -echo "==> Verifying gateway health..." -pnpm clawdbot health - -echo "==> Checking for Swift 6.2 compatibility issues..." -if grep -r "FileManager\.default\|Thread\.isMainThread" src/ apps/ --include="*.swift" --quiet; then - echo "⚠️ Found potential Swift 6.2 deprecated API usage" - echo " Run manual fixes or use analyze-mode investigation" -else - echo "✅ No obvious Swift deprecation issues found" -fi - -echo "==> Testing agent functionality..." -# Note: Update YOUR_TELEGRAM_SESSION_ID with actual session ID -pnpm clawdbot agent --message "Verification: Upstream sync and macOS rebuild completed successfully." --session-id YOUR_TELEGRAM_SESSION_ID || echo "Warning: Agent test failed - check Telegram for verification message" - -echo "==> Done! Check Telegram for verification message, then run 'git push --force-with-lease' when ready." -``` diff --git a/.agents/maintainers.md b/.agents/maintainers.md deleted file mode 100644 index 2bbb9c6203e..00000000000 --- a/.agents/maintainers.md +++ /dev/null @@ -1 +0,0 @@ -Maintainer skills now live in [`openclaw/maintainers`](https://github.com/openclaw/maintainers/). diff --git a/.detect-secrets.cfg b/.detect-secrets.cfg deleted file mode 100644 index 38912567c9b..00000000000 --- a/.detect-secrets.cfg +++ /dev/null @@ -1,30 +0,0 @@ -# detect-secrets exclusion patterns (regex) -# -# Note: detect-secrets does not read this file by default. If you want these -# applied, wire them into your scan command (e.g. translate to --exclude-files -# / --exclude-lines) or into a baseline's filters_used. - -[exclude-files] -# pnpm lockfiles contain lots of high-entropy package integrity blobs. -pattern = (^|/)pnpm-lock\.yaml$ -# Generated output and vendored assets. -pattern = (^|/)(dist|vendor)/ -# Local config file with allowlist patterns. -pattern = (^|/)\.detect-secrets\.cfg$ - -[exclude-lines] -# Fastlane checks for private key marker; not a real key. -pattern = key_content\.include\?\("BEGIN PRIVATE KEY"\) -# UI label string for Anthropic auth mode. -pattern = case \.apiKeyEnv: "API key \(env var\)" -# CodingKeys mapping uses apiKey literal. -pattern = case apikey = "apiKey" -# Schema labels referencing password fields (not actual secrets). -pattern = "gateway\.remote\.password" -pattern = "gateway\.auth\.password" -# Schema label for talk API key (label text only). -pattern = "talk\.apiKey" -# checking for typeof is not something we care about. -pattern = === "string" -# specific optional-chaining password check that didn't match the line above. -pattern = typeof remote\?\.password === "string" diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 73d00fff147..00000000000 --- a/.dockerignore +++ /dev/null @@ -1,60 +0,0 @@ -.git -.worktrees -.bun-cache -.bun -.tmp -**/.tmp -.DS_Store -**/.DS_Store -*.png -*.jpg -*.jpeg -*.webp -*.gif -*.mp4 -*.mov -*.wav -*.mp3 -node_modules -**/node_modules -.pnpm-store -**/.pnpm-store -.turbo -**/.turbo -.cache -**/.cache -.next -**/.next -coverage -**/coverage -*.log -tmp -**/tmp - -# build artifacts -dist -**/dist -apps/macos/.build -apps/ios/build -**/*.trace - -# large app trees not needed for CLI build -apps/ -assets/ -Peekaboo/ -Swabble/ -Core/ -Users/ -vendor/ - -# Needed for building the Canvas A2UI bundle during Docker image builds. -# Keep the rest of apps/ and vendor/ excluded to avoid a large build context. -!apps/shared/ -!apps/shared/OpenClawKit/ -!apps/shared/OpenClawKit/Tools/ -!apps/shared/OpenClawKit/Tools/CanvasA2UI/ -!apps/shared/OpenClawKit/Tools/CanvasA2UI/** -!vendor/a2ui/ -!vendor/a2ui/renderers/ -!vendor/a2ui/renderers/lit/ -!vendor/a2ui/renderers/lit/** diff --git a/.env.example b/.env.example deleted file mode 100644 index 41df435b8f9..00000000000 --- a/.env.example +++ /dev/null @@ -1,80 +0,0 @@ -# OpenClaw .env example -# -# Quick start: -# 1) Copy this file to `.env` (for local runs from this repo), OR to `~/.openclaw/.env` (for launchd/systemd daemons). -# 2) Fill only the values you use. -# 3) Keep real secrets out of git. -# -# Env-source precedence for environment variables (highest -> lowest): -# process env, ./.env, ~/.openclaw/.env, then openclaw.json `env` block. -# Existing non-empty process env vars are not overridden by dotenv/config env loading. -# Note: direct config keys (for example `gateway.auth.token` or channel tokens in openclaw.json) -# are resolved separately from env loading and often take precedence over env fallbacks. - -# ----------------------------------------------------------------------------- -# Gateway auth + paths -# ----------------------------------------------------------------------------- -# Recommended if the gateway binds beyond loopback. -OPENCLAW_GATEWAY_TOKEN=change-me-to-a-long-random-token -# Example generator: openssl rand -hex 32 - -# Optional alternative auth mode (use token OR password). -# OPENCLAW_GATEWAY_PASSWORD=change-me-to-a-strong-password - -# Optional path overrides (defaults shown for reference). -# OPENCLAW_STATE_DIR=~/.openclaw -# OPENCLAW_CONFIG_PATH=~/.openclaw/openclaw.json -# OPENCLAW_HOME=~ - -# Optional: import missing keys from your login shell profile. -# OPENCLAW_LOAD_SHELL_ENV=1 -# OPENCLAW_SHELL_ENV_TIMEOUT_MS=15000 - -# ----------------------------------------------------------------------------- -# Model provider API keys (set at least one) -# ----------------------------------------------------------------------------- -# OPENAI_API_KEY=sk-... -# ANTHROPIC_API_KEY=sk-ant-... -# GEMINI_API_KEY=... -# OPENROUTER_API_KEY=sk-or-... -# OPENCLAW_LIVE_OPENAI_KEY=sk-... -# OPENCLAW_LIVE_ANTHROPIC_KEY=sk-ant-... -# OPENCLAW_LIVE_GEMINI_KEY=... -# OPENAI_API_KEY_1=... -# ANTHROPIC_API_KEY_1=... -# GEMINI_API_KEY_1=... -# GOOGLE_API_KEY=... -# OPENAI_API_KEYS=sk-1,sk-2 -# ANTHROPIC_API_KEYS=sk-ant-1,sk-ant-2 -# GEMINI_API_KEYS=key-1,key-2 - -# Optional additional providers -# ZAI_API_KEY=... -# AI_GATEWAY_API_KEY=... -# MINIMAX_API_KEY=... -# SYNTHETIC_API_KEY=... - -# ----------------------------------------------------------------------------- -# Channels (only set what you enable) -# ----------------------------------------------------------------------------- -# TELEGRAM_BOT_TOKEN=123456:ABCDEF... -# DISCORD_BOT_TOKEN=... -# SLACK_BOT_TOKEN=xoxb-... -# SLACK_APP_TOKEN=xapp-... - -# Optional channel env fallbacks -# MATTERMOST_BOT_TOKEN=... -# MATTERMOST_URL=https://chat.example.com -# ZALO_BOT_TOKEN=... -# OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:... - -# ----------------------------------------------------------------------------- -# Tools + voice/media (optional) -# ----------------------------------------------------------------------------- -# BRAVE_API_KEY=... -# PERPLEXITY_API_KEY=pplx-... -# FIRECRAWL_API_KEY=... - -# ELEVENLABS_API_KEY=... -# XI_API_KEY=... # alias for ElevenLabs -# DEEPGRAM_API_KEY=... diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 6313b56c578..00000000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto eol=lf diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 082086ea079..00000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -custom: ["https://github.com/sponsors/steipete"] diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml deleted file mode 100644 index 927aa7079cf..00000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ /dev/null @@ -1,95 +0,0 @@ -name: Bug report -description: Report a defect or unexpected behavior in OpenClaw. -title: "[Bug]: " -labels: - - bug -body: - - type: markdown - attributes: - value: | - Thanks for filing this report. Keep it concise, reproducible, and evidence-based. - - type: textarea - id: summary - attributes: - label: Summary - description: One-sentence statement of what is broken. - placeholder: After upgrading to , behavior regressed from . - validations: - required: true - - type: textarea - id: repro - attributes: - label: Steps to reproduce - description: Provide the shortest deterministic repro path. - placeholder: | - 1. Configure channel X. - 2. Send message Y. - 3. Run command Z. - validations: - required: true - - type: textarea - id: expected - attributes: - label: Expected behavior - description: What should happen if the bug does not exist. - placeholder: Agent posts a reply in the same thread. - validations: - required: true - - type: textarea - id: actual - attributes: - label: Actual behavior - description: What happened instead, including user-visible errors. - placeholder: No reply is posted; gateway logs "reply target not found". - validations: - required: true - - type: input - id: version - attributes: - label: OpenClaw version - description: Exact version/build tested. - placeholder: - validations: - required: true - - type: input - id: os - attributes: - label: Operating system - description: OS and version where this occurs. - placeholder: macOS 15.4 / Ubuntu 24.04 / Windows 11 - validations: - required: true - - type: input - id: install_method - attributes: - label: Install method - description: How OpenClaw was installed or launched. - placeholder: npm global / pnpm dev / docker / mac app - - type: textarea - id: logs - attributes: - label: Logs, screenshots, and evidence - description: Include redacted logs/screenshots/recordings that prove the behavior. - render: shell - - type: textarea - id: impact - attributes: - label: Impact and severity - description: | - Explain who is affected, how severe it is, how often it happens, and the practical consequence. - Include: - - Affected users/systems/channels - - Severity (annoying, blocks workflow, data risk, etc.) - - Frequency (always/intermittent/edge case) - - Consequence (missed messages, failed onboarding, extra cost, etc.) - placeholder: | - Affected: Telegram group users on - Severity: High (blocks replies) - Frequency: 100% repro - Consequence: Agents cannot respond in threads - - type: textarea - id: additional_information - attributes: - label: Additional information - description: Add any context that helps triage but does not fit above. - placeholder: Regression started after upgrade from ; temporary workaround is ... diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 4c1b9775597..00000000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,8 +0,0 @@ -blank_issues_enabled: false -contact_links: - - name: Onboarding - url: https://discord.gg/clawd - about: "New to OpenClaw? Join Discord for setup guidance in #help." - - name: Support - url: https://discord.gg/clawd - about: "Get help from the OpenClaw community on Discord in #help." diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml deleted file mode 100644 index a08b456786e..00000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: Feature request -description: Propose a new capability or product improvement. -title: "[Feature]: " -labels: - - enhancement -body: - - type: markdown - attributes: - value: | - Help us evaluate this request with concrete use cases and tradeoffs. - - type: textarea - id: summary - attributes: - label: Summary - description: One-line statement of the requested capability. - placeholder: Add per-channel default response prefix. - validations: - required: true - - type: textarea - id: problem - attributes: - label: Problem to solve - description: What user pain this solves and why current behavior is insufficient. - placeholder: Agents cannot distinguish persona context in mixed channels, causing misrouted follow-ups. - validations: - required: true - - type: textarea - id: proposed_solution - attributes: - label: Proposed solution - description: Desired behavior/API/UX with as much specificity as possible. - placeholder: Support channels..responsePrefix with default fallback and account-level override. - validations: - required: true - - type: textarea - id: alternatives - attributes: - label: Alternatives considered - description: Other approaches considered and why they are weaker. - placeholder: Manual prefixing in prompts is inconsistent and hard to enforce. - - type: textarea - id: impact - attributes: - label: Impact - description: | - Explain who is affected, severity/urgency, how often this pain occurs, and practical consequences. - Include: - - Affected users/systems/channels - - Severity (annoying, blocks workflow, etc.) - - Frequency (always/intermittent/edge case) - - Consequence (delays, errors, extra manual work, etc.) - placeholder: | - Affected: Multi-team shared channels - Severity: Medium - Frequency: Daily - Consequence: +20 minutes/day/operator and delayed alerts - validations: - required: true - - type: textarea - id: evidence - attributes: - label: Evidence/examples - description: Prior art, links, screenshots, logs, or metrics. - placeholder: Comparable behavior in X, sample config, and screenshot of current limitation. - - type: textarea - id: additional_information - attributes: - label: Additional information - description: Extra context, constraints, or references not covered above. - placeholder: Must remain backward-compatible with existing config keys. diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml deleted file mode 100644 index f02fbddb3e8..00000000000 --- a/.github/actionlint.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# actionlint configuration -# https://github.com/rhysd/actionlint/blob/main/docs/config.md - -self-hosted-runner: - labels: - # Blacksmith CI runners - - blacksmith-8vcpu-ubuntu-2404 - - blacksmith-8vcpu-windows-2025 - - blacksmith-16vcpu-ubuntu-2404 - - blacksmith-16vcpu-windows-2025 - - blacksmith-16vcpu-ubuntu-2404-arm - -# Ignore patterns for known issues -paths: - .github/workflows/**/*.yml: - ignore: - # Ignore shellcheck warnings (we run shellcheck separately) - - "shellcheck reported issue.+" - # Ignore intentional if: false for disabled jobs - - 'constant expression "false" in condition' - # actionlint's built-in runner label allowlist lags Blacksmith additions. - - 'label "blacksmith-16vcpu-[^"]+" is unknown\.' diff --git a/.github/actions/detect-docs-changes/action.yml b/.github/actions/detect-docs-changes/action.yml deleted file mode 100644 index 853442a7783..00000000000 --- a/.github/actions/detect-docs-changes/action.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Detect docs-only changes -description: > - Outputs docs_only=true when all changed files are under docs/ or are - markdown (.md/.mdx). Fail-safe: if detection fails, outputs false (run - everything). Uses git diff — no API calls, no extra permissions needed. - -outputs: - docs_only: - description: "'true' if all changes are docs/markdown, 'false' otherwise" - value: ${{ steps.check.outputs.docs_only }} - docs_changed: - description: "'true' if any changed file is under docs/ or is markdown" - value: ${{ steps.check.outputs.docs_changed }} - -runs: - using: composite - steps: - - name: Detect docs-only changes - id: check - shell: bash - run: | - if [ "${{ github.event_name }}" = "push" ]; then - BASE="${{ github.event.before }}" - else - # Use the exact base SHA from the event payload — stable regardless - # of base branch movement (avoids origin/ drift). - BASE="${{ github.event.pull_request.base.sha }}" - fi - - # Fail-safe: if we can't diff, assume non-docs (run everything) - CHANGED=$(git diff --name-only "$BASE" HEAD 2>/dev/null || echo "UNKNOWN") - if [ "$CHANGED" = "UNKNOWN" ] || [ -z "$CHANGED" ]; then - echo "docs_only=false" >> "$GITHUB_OUTPUT" - echo "docs_changed=false" >> "$GITHUB_OUTPUT" - exit 0 - fi - - # Check if any changed file is a doc - DOCS=$(echo "$CHANGED" | grep -E '^docs/|\.md$|\.mdx$' || true) - if [ -n "$DOCS" ]; then - echo "docs_changed=true" >> "$GITHUB_OUTPUT" - else - echo "docs_changed=false" >> "$GITHUB_OUTPUT" - fi - - # Check if all changed files are docs or markdown - NON_DOCS=$(echo "$CHANGED" | grep -vE '^docs/|\.md$|\.mdx$' || true) - if [ -z "$NON_DOCS" ]; then - echo "docs_only=true" >> "$GITHUB_OUTPUT" - echo "Docs-only change detected — skipping heavy jobs" - else - echo "docs_only=false" >> "$GITHUB_OUTPUT" - fi diff --git a/.github/actions/setup-node-env/action.yml b/.github/actions/setup-node-env/action.yml deleted file mode 100644 index 334cd3c24fb..00000000000 --- a/.github/actions/setup-node-env/action.yml +++ /dev/null @@ -1,98 +0,0 @@ -name: Setup Node environment -description: > - Initialize submodules with retry, install Node 22, pnpm, optionally Bun, - and run pnpm install. Requires actions/checkout to run first. -inputs: - node-version: - description: Node.js version to install. - required: false - default: "22.x" - pnpm-version: - description: pnpm version for corepack. - required: false - default: "10.23.0" - install-bun: - description: Whether to install Bun alongside Node. - required: false - default: "true" - frozen-lockfile: - description: Whether to use --frozen-lockfile for install. - required: false - default: "true" -runs: - using: composite - steps: - - name: Checkout submodules (retry) - shell: bash - run: | - set -euo pipefail - git submodule sync --recursive - for attempt in 1 2 3 4 5; do - if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then - exit 0 - fi - echo "Submodule update failed (attempt $attempt/5). Retrying…" - sleep $((attempt * 10)) - done - exit 1 - - - name: Setup Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version: ${{ inputs.node-version }} - check-latest: true - - - name: Setup pnpm + cache store - uses: ./.github/actions/setup-pnpm-store-cache - with: - pnpm-version: ${{ inputs.pnpm-version }} - cache-key-suffix: "node22" - - - name: Setup Bun - if: inputs.install-bun == 'true' - uses: oven-sh/setup-bun@v2 - with: - bun-version: "1.3.9+cf6cdbbba" - - - name: Runtime versions - shell: bash - run: | - node -v - npm -v - pnpm -v - if command -v bun &>/dev/null; then bun -v; fi - - - name: Capture node path - shell: bash - run: echo "NODE_BIN=$(dirname "$(node -p "process.execPath")")" >> "$GITHUB_ENV" - - - name: Install dependencies - shell: bash - env: - CI: "true" - FROZEN_LOCKFILE: ${{ inputs.frozen-lockfile }} - run: | - set -euo pipefail - export PATH="$NODE_BIN:$PATH" - which node - node -v - pnpm -v - case "$FROZEN_LOCKFILE" in - true) LOCKFILE_FLAG="--frozen-lockfile" ;; - false) LOCKFILE_FLAG="" ;; - *) - echo "::error::Invalid frozen-lockfile input: '$FROZEN_LOCKFILE' (expected true or false)" - exit 2 - ;; - esac - - install_args=( - install - --ignore-scripts=false - --config.engine-strict=false - --config.enable-pre-post-scripts=true - ) - if [ -n "$LOCKFILE_FLAG" ]; then - install_args+=("$LOCKFILE_FLAG") - fi - pnpm "${install_args[@]}" || pnpm "${install_args[@]}" diff --git a/.github/actions/setup-pnpm-store-cache/action.yml b/.github/actions/setup-pnpm-store-cache/action.yml deleted file mode 100644 index 8e25492ac92..00000000000 --- a/.github/actions/setup-pnpm-store-cache/action.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Setup pnpm + store cache -description: Prepare pnpm via corepack and restore pnpm store cache. -inputs: - pnpm-version: - description: pnpm version to activate via corepack. - required: false - default: "10.23.0" - cache-key-suffix: - description: Suffix appended to the cache key. - required: false - default: "node22" -runs: - using: composite - steps: - - name: Setup pnpm (corepack retry) - shell: bash - env: - PNPM_VERSION: ${{ inputs.pnpm-version }} - run: | - set -euo pipefail - if [[ ! "$PNPM_VERSION" =~ ^[0-9]+(\.[0-9]+){1,2}([.-][0-9A-Za-z.-]+)?$ ]]; then - echo "::error::Invalid pnpm-version input: '$PNPM_VERSION'" - exit 2 - fi - corepack enable - for attempt in 1 2 3; do - if corepack prepare "pnpm@$PNPM_VERSION" --activate; then - pnpm -v - exit 0 - fi - echo "corepack prepare failed (attempt $attempt/3). Retrying..." - sleep $((attempt * 10)) - done - exit 1 - - - name: Resolve pnpm store path - id: pnpm-store - shell: bash - run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT" - - - name: Restore pnpm store cache - uses: actions/cache@v4 - with: - path: ${{ steps.pnpm-store.outputs.path }} - key: ${{ runner.os }}-pnpm-store-${{ inputs.cache-key-suffix }}-${{ hashFiles('pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store-${{ inputs.cache-key-suffix }}- diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index bfdac1a9c3f..00000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,65 +0,0 @@ -# Dependabot configuration -# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file - -version: 2 - -registries: - npm-npmjs: - type: npm-registry - url: https://registry.npmjs.org - replaces-base: true - -updates: - # npm dependencies (root) - - package-ecosystem: npm - directory: / - schedule: - interval: weekly - cooldown: - default-days: 7 - groups: - production: - dependency-type: production - update-types: - - minor - - patch - development: - dependency-type: development - update-types: - - minor - - patch - open-pull-requests-limit: 10 - registries: - - npm-npmjs - - # GitHub Actions - - package-ecosystem: github-actions - directory: / - schedule: - interval: weekly - cooldown: - default-days: 7 - groups: - actions: - patterns: - - "*" - update-types: - - minor - - patch - open-pull-requests-limit: 5 - - # Docker base images (root Dockerfiles) - - package-ecosystem: docker - directory: / - schedule: - interval: weekly - cooldown: - default-days: 7 - groups: - docker-images: - patterns: - - "*" - update-types: - - minor - - patch - open-pull-requests-limit: 5 diff --git a/.github/instructions/copilot.instructions.md b/.github/instructions/copilot.instructions.md deleted file mode 100644 index 8686521cfc7..00000000000 --- a/.github/instructions/copilot.instructions.md +++ /dev/null @@ -1,64 +0,0 @@ -# OpenClaw Codebase Patterns - -**Always reuse existing code - no redundancy!** - -## Tech Stack - -- **Runtime**: Node 22+ (Bun also supported for dev/scripts) -- **Language**: TypeScript (ESM, strict mode) -- **Package Manager**: pnpm (keep `pnpm-lock.yaml` in sync) -- **Lint/Format**: Oxlint, Oxfmt (`pnpm check`) -- **Tests**: Vitest with V8 coverage -- **CLI Framework**: Commander + clack/prompts -- **Build**: tsdown (outputs to `dist/`) - -## Anti-Redundancy Rules - -- Avoid files that just re-export from another file. Import directly from the original source. -- If a function already exists, import it - do NOT create a duplicate in another file. -- Before creating any formatter, utility, or helper, search for existing implementations first. - -## Source of Truth Locations - -### Formatting Utilities (`src/infra/`) - -- **Time formatting**: `src\infra\format-time` - -**NEVER create local `formatAge`, `formatDuration`, `formatElapsedTime` functions - import from centralized modules.** - -### Terminal Output (`src/terminal/`) - -- Tables: `src/terminal/table.ts` (`renderTable`) -- Themes/colors: `src/terminal/theme.ts` (`theme.success`, `theme.muted`, etc.) -- Progress: `src/cli/progress.ts` (spinners, progress bars) - -### CLI Patterns - -- CLI option wiring: `src/cli/` -- Commands: `src/commands/` -- Dependency injection via `createDefaultDeps` - -## Import Conventions - -- Use `.js` extension for cross-package imports (ESM) -- Direct imports only - no re-export wrapper files -- Types: `import type { X }` for type-only imports - -## Code Quality - -- TypeScript (ESM), strict typing, avoid `any` -- Keep files under ~700 LOC - extract helpers when larger -- Colocated tests: `*.test.ts` next to source files -- Run `pnpm check` before commits (lint + format) -- Run `pnpm tsgo` for type checking - -## Stack & Commands - -- **Package manager**: pnpm (`pnpm install`) -- **Dev**: `pnpm openclaw ...` or `pnpm dev` -- **Type-check**: `pnpm tsgo` -- **Lint/format**: `pnpm check` -- **Tests**: `pnpm test` -- **Build**: `pnpm build` - -If you are coding together with a human, do NOT use scripts/committer, but git directly and run the above commands manually to ensure quality. diff --git a/.github/labeler.yml b/.github/labeler.yml deleted file mode 100644 index 329e34e4f14..00000000000 --- a/.github/labeler.yml +++ /dev/null @@ -1,258 +0,0 @@ -"channel: bluebubbles": - - changed-files: - - any-glob-to-any-file: - - "extensions/bluebubbles/**" - - "docs/channels/bluebubbles.md" -"channel: discord": - - changed-files: - - any-glob-to-any-file: - - "src/discord/**" - - "extensions/discord/**" - - "docs/channels/discord.md" -"channel: irc": - - changed-files: - - any-glob-to-any-file: - - "extensions/irc/**" - - "docs/channels/irc.md" -"channel: feishu": - - changed-files: - - any-glob-to-any-file: - - "src/feishu/**" - - "extensions/feishu/**" - - "docs/channels/feishu.md" -"channel: googlechat": - - changed-files: - - any-glob-to-any-file: - - "extensions/googlechat/**" - - "docs/channels/googlechat.md" -"channel: imessage": - - changed-files: - - any-glob-to-any-file: - - "src/imessage/**" - - "extensions/imessage/**" - - "docs/channels/imessage.md" -"channel: line": - - changed-files: - - any-glob-to-any-file: - - "extensions/line/**" - - "docs/channels/line.md" -"channel: matrix": - - changed-files: - - any-glob-to-any-file: - - "extensions/matrix/**" - - "docs/channels/matrix.md" -"channel: mattermost": - - changed-files: - - any-glob-to-any-file: - - "extensions/mattermost/**" - - "docs/channels/mattermost.md" -"channel: msteams": - - changed-files: - - any-glob-to-any-file: - - "extensions/msteams/**" - - "docs/channels/msteams.md" -"channel: nextcloud-talk": - - changed-files: - - any-glob-to-any-file: - - "extensions/nextcloud-talk/**" - - "docs/channels/nextcloud-talk.md" -"channel: nostr": - - changed-files: - - any-glob-to-any-file: - - "extensions/nostr/**" - - "docs/channels/nostr.md" -"channel: signal": - - changed-files: - - any-glob-to-any-file: - - "src/signal/**" - - "extensions/signal/**" - - "docs/channels/signal.md" -"channel: slack": - - changed-files: - - any-glob-to-any-file: - - "src/slack/**" - - "extensions/slack/**" - - "docs/channels/slack.md" -"channel: telegram": - - changed-files: - - any-glob-to-any-file: - - "src/telegram/**" - - "extensions/telegram/**" - - "docs/channels/telegram.md" -"channel: tlon": - - changed-files: - - any-glob-to-any-file: - - "extensions/tlon/**" - - "docs/channels/tlon.md" -"channel: twitch": - - changed-files: - - any-glob-to-any-file: - - "extensions/twitch/**" - - "docs/channels/twitch.md" -"channel: voice-call": - - changed-files: - - any-glob-to-any-file: - - "extensions/voice-call/**" -"channel: whatsapp-web": - - changed-files: - - any-glob-to-any-file: - - "src/web/**" - - "extensions/whatsapp/**" - - "docs/channels/whatsapp.md" -"channel: zalo": - - changed-files: - - any-glob-to-any-file: - - "extensions/zalo/**" - - "docs/channels/zalo.md" -"channel: zalouser": - - changed-files: - - any-glob-to-any-file: - - "extensions/zalouser/**" - - "docs/channels/zalouser.md" - -"app: android": - - changed-files: - - any-glob-to-any-file: - - "apps/android/**" - - "docs/platforms/android.md" -"app: ios": - - changed-files: - - any-glob-to-any-file: - - "apps/ios/**" - - "docs/platforms/ios.md" -"app: macos": - - changed-files: - - any-glob-to-any-file: - - "apps/macos/**" - - "docs/platforms/macos.md" - - "docs/platforms/mac/**" -"app: web-ui": - - changed-files: - - any-glob-to-any-file: - - "ui/**" - - "src/gateway/control-ui.ts" - - "src/gateway/control-ui-shared.ts" - - "src/gateway/protocol/**" - - "src/gateway/server-methods/chat.ts" - - "src/infra/control-ui-assets.ts" - -"gateway": - - changed-files: - - any-glob-to-any-file: - - "src/gateway/**" - - "src/daemon/**" - - "docs/gateway/**" - -"docs": - - changed-files: - - any-glob-to-any-file: - - "docs/**" - - "docs.acp.md" - -"cli": - - changed-files: - - any-glob-to-any-file: - - "src/cli/**" - -"commands": - - changed-files: - - any-glob-to-any-file: - - "src/commands/**" - -"scripts": - - changed-files: - - any-glob-to-any-file: - - "scripts/**" - -"docker": - - changed-files: - - any-glob-to-any-file: - - "Dockerfile" - - "Dockerfile.*" - - "docker-compose.yml" - - "docker-setup.sh" - - ".dockerignore" - - "scripts/**/*docker*" - - "scripts/**/Dockerfile*" - - "scripts/sandbox-*.sh" - - "src/agents/sandbox*.ts" - - "src/commands/sandbox*.ts" - - "src/cli/sandbox-cli.ts" - - "src/docker-setup.test.ts" - - "src/config/**/*sandbox*" - - "docs/cli/sandbox.md" - - "docs/gateway/sandbox*.md" - - "docs/install/docker.md" - - "docs/multi-agent-sandbox-tools.md" - -"agents": - - changed-files: - - any-glob-to-any-file: - - "src/agents/**" - -"security": - - changed-files: - - any-glob-to-any-file: - - "docs/cli/security.md" - - "docs/gateway/security.md" - -"extensions: copilot-proxy": - - changed-files: - - any-glob-to-any-file: - - "extensions/copilot-proxy/**" -"extensions: diagnostics-otel": - - changed-files: - - any-glob-to-any-file: - - "extensions/diagnostics-otel/**" -"extensions: google-antigravity-auth": - - changed-files: - - any-glob-to-any-file: - - "extensions/google-antigravity-auth/**" -"extensions: google-gemini-cli-auth": - - changed-files: - - any-glob-to-any-file: - - "extensions/google-gemini-cli-auth/**" -"extensions: denchclaw-auth": - - changed-files: - - any-glob-to-any-file: - - "extensions/denchclaw-auth/**" -"extensions: llm-task": - - changed-files: - - any-glob-to-any-file: - - "extensions/llm-task/**" -"extensions: lobster": - - changed-files: - - any-glob-to-any-file: - - "extensions/lobster/**" -"extensions: memory-core": - - changed-files: - - any-glob-to-any-file: - - "extensions/memory-core/**" -"extensions: memory-lancedb": - - changed-files: - - any-glob-to-any-file: - - "extensions/memory-lancedb/**" -"extensions: open-prose": - - changed-files: - - any-glob-to-any-file: - - "extensions/open-prose/**" -"extensions: qwen-portal-auth": - - changed-files: - - any-glob-to-any-file: - - "extensions/qwen-portal-auth/**" -"extensions: device-pair": - - changed-files: - - any-glob-to-any-file: - - "extensions/device-pair/**" -"extensions: minimax-portal-auth": - - changed-files: - - any-glob-to-any-file: - - "extensions/minimax-portal-auth/**" -"extensions: phone-control": - - changed-files: - - any-glob-to-any-file: - - "extensions/phone-control/**" -"extensions: talk-voice": - - changed-files: - - any-glob-to-any-file: - - "extensions/talk-voice/**" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index 9b0e7f8dc4b..00000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,108 +0,0 @@ -## Summary - -Describe the problem and fix in 2–5 bullets: - -- Problem: -- Why it matters: -- What changed: -- What did NOT change (scope boundary): - -## Change Type (select all) - -- [ ] Bug fix -- [ ] Feature -- [ ] Refactor -- [ ] Docs -- [ ] Security hardening -- [ ] Chore/infra - -## Scope (select all touched areas) - -- [ ] Gateway / orchestration -- [ ] Skills / tool execution -- [ ] Auth / tokens -- [ ] Memory / storage -- [ ] Integrations -- [ ] API / contracts -- [ ] UI / DX -- [ ] CI/CD / infra - -## Linked Issue/PR - -- Closes # -- Related # - -## User-visible / Behavior Changes - -List user-visible changes (including defaults/config). -If none, write `None`. - -## Security Impact (required) - -- New permissions/capabilities? (`Yes/No`) -- Secrets/tokens handling changed? (`Yes/No`) -- New/changed network calls? (`Yes/No`) -- Command/tool execution surface changed? (`Yes/No`) -- Data access scope changed? (`Yes/No`) -- If any `Yes`, explain risk + mitigation: - -## Repro + Verification - -### Environment - -- OS: -- Runtime/container: -- Model/provider: -- Integration/channel (if any): -- Relevant config (redacted): - -### Steps - -1. -2. -3. - -### Expected - -- - -### Actual - -- - -## Evidence - -Attach at least one: - -- [ ] Failing test/log before + passing after -- [ ] Trace/log snippets -- [ ] Screenshot/recording -- [ ] Perf numbers (if relevant) - -## Human Verification (required) - -What you personally verified (not just CI), and how: - -- Verified scenarios: -- Edge cases checked: -- What you did **not** verify: - -## Compatibility / Migration - -- Backward compatible? (`Yes/No`) -- Config/env changes? (`Yes/No`) -- Migration needed? (`Yes/No`) -- If yes, exact upgrade steps: - -## Failure Recovery (if this breaks) - -- How to disable/revert this change quickly: -- Files/config to restore: -- Known bad symptoms reviewers should watch for: - -## Risks and Mitigations - -List only real risks for this PR. Add/remove entries as needed. If none, write `None`. - -- Risk: - - Mitigation: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 4f20ec2242a..00000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: CI - -on: - push: - branches: [main] - pull_request: - -concurrency: - group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -jobs: - # check: - # name: "check" - # runs-on: ubuntu-latest - # steps: - # - name: Checkout - # uses: actions/checkout@v4 - # with: - # submodules: false - # - # - name: Setup Node environment - # uses: ./.github/actions/setup-node-env - # - # - name: Check types and lint and oxfmt - # run: pnpm check - - test: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - include: - - runtime: node - command: pnpm canvas:a2ui:bundle && pnpm test - - runtime: bootstrap - command: pnpm vitest run --config src/cli/vitest.config.ts src/cli/profile.test.ts src/cli/bootstrap-external.test.ts src/cli/bootstrap-external.bootstrap-command.test.ts - - runtime: bun - command: pnpm canvas:a2ui:bundle && bunx vitest run --config vitest.unit.config.ts - steps: - - name: Skip bun lane on push - if: github.event_name == 'push' && matrix.runtime == 'bun' - run: echo "Skipping bun test lane on push events." - - - name: Checkout - if: github.event_name != 'push' || matrix.runtime != 'bun' - uses: actions/checkout@v4 - with: - submodules: false - - - name: Setup Node environment - if: matrix.runtime != 'bun' || github.event_name != 'push' - uses: ./.github/actions/setup-node-env - with: - install-bun: "${{ matrix.runtime == 'bun' }}" - - - name: Configure Node test resources - if: matrix.runtime == 'node' - run: | - echo "OPENCLAW_TEST_WORKERS=2" >> "$GITHUB_ENV" - echo "OPENCLAW_TEST_MAX_OLD_SPACE_SIZE_MB=8192" >> "$GITHUB_ENV" - - - name: Run tests (${{ matrix.runtime }}) - if: github.event_name != 'push' || matrix.runtime != 'bun' - run: ${{ matrix.command }} diff --git a/.github/workflows/workflow-sanity.yml b/.github/workflows/workflow-sanity.yml deleted file mode 100644 index 19668e697ad..00000000000 --- a/.github/workflows/workflow-sanity.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: Workflow Sanity - -on: - pull_request: - push: - branches: [main] - -concurrency: - group: workflow-sanity-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -jobs: - no-tabs: - runs-on: blacksmith-16vcpu-ubuntu-2404 - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Fail on tabs in workflow files - run: | - python - <<'PY' - from __future__ import annotations - - import pathlib - import sys - - root = pathlib.Path(".github/workflows") - bad: list[str] = [] - for path in sorted(root.rglob("*.yml")): - if b"\t" in path.read_bytes(): - bad.append(str(path)) - - for path in sorted(root.rglob("*.yaml")): - if b"\t" in path.read_bytes(): - bad.append(str(path)) - - if bad: - print("Tabs found in workflow file(s):") - for path in bad: - print(f"- {path}") - sys.exit(1) - PY - - actionlint: - runs-on: blacksmith-16vcpu-ubuntu-2404 - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Install actionlint - shell: bash - run: | - set -euo pipefail - ACTIONLINT_VERSION="1.7.11" - archive="actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" - base_url="https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}" - curl -sSfL -o "${archive}" "${base_url}/${archive}" - curl -sSfL -o checksums.txt "${base_url}/actionlint_${ACTIONLINT_VERSION}_checksums.txt" - grep " ${archive}\$" checksums.txt | sha256sum -c - - tar -xzf "${archive}" actionlint - sudo install -m 0755 actionlint /usr/local/bin/actionlint - - - name: Lint workflows - run: actionlint - - - name: Disallow direct inputs interpolation in composite run blocks - run: python3 scripts/check-composite-action-input-interpolation.py diff --git a/.gitignore b/.gitignore index 3323db84fe6..9c23dc593b2 100644 --- a/.gitignore +++ b/.gitignore @@ -103,7 +103,10 @@ package-lock.json # Local iOS signing overrides apps/ios/LocalSigning.xcconfig + # Generated protocol schema (produced via pnpm protocol:gen) dist/protocol.schema.json .cursor/skills/ + +.npmrc.deploy diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc deleted file mode 100644 index 94035711053..00000000000 --- a/.markdownlint-cli2.jsonc +++ /dev/null @@ -1,52 +0,0 @@ -{ - "globs": ["docs/**/*.md", "docs/**/*.mdx", "README.md"], - "ignores": ["docs/zh-CN/**", "docs/.i18n/**", "docs/reference/templates/**", "**/.local/**"], - "config": { - "default": true, - - "MD013": false, - "MD025": false, - "MD029": false, - - "MD033": { - "allowed_elements": [ - "Note", - "Info", - "Tip", - "Warning", - "Card", - "CardGroup", - "Columns", - "Steps", - "Step", - "Tabs", - "Tab", - "Accordion", - "AccordionGroup", - "CodeGroup", - "Frame", - "Callout", - "ParamField", - "ResponseField", - "RequestExample", - "ResponseExample", - "img", - "a", - "br", - "details", - "summary", - "p", - "strong", - "picture", - "source", - "Tooltip", - "Check", - ], - }, - - "MD036": false, - "MD040": false, - "MD041": false, - "MD046": false, - }, -} diff --git a/.pi/extensions/diff.ts b/.pi/extensions/diff.ts deleted file mode 100644 index 037fa240afb..00000000000 --- a/.pi/extensions/diff.ts +++ /dev/null @@ -1,195 +0,0 @@ -/** - * Diff Extension - * - * /diff command shows modified/deleted/new files from git status and opens - * the selected file in VS Code's diff view. - */ - -import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; -import { DynamicBorder } from "@mariozechner/pi-coding-agent"; -import { - Container, - Key, - matchesKey, - type SelectItem, - SelectList, - Text, -} from "@mariozechner/pi-tui"; - -interface FileInfo { - status: string; - statusLabel: string; - file: string; -} - -export default function (pi: ExtensionAPI) { - pi.registerCommand("diff", { - description: "Show git changes and open in VS Code diff view", - handler: async (_args, ctx) => { - if (!ctx.hasUI) { - ctx.ui.notify("No UI available", "error"); - return; - } - - // Get changed files from git status - const result = await pi.exec("git", ["status", "--porcelain"], { cwd: ctx.cwd }); - - if (result.code !== 0) { - ctx.ui.notify(`git status failed: ${result.stderr}`, "error"); - return; - } - - if (!result.stdout || !result.stdout.trim()) { - ctx.ui.notify("No changes in working tree", "info"); - return; - } - - // Parse git status output - // Format: XY filename (where XY is two-letter status, then space, then filename) - const lines = result.stdout.split("\n"); - const files: FileInfo[] = []; - - for (const line of lines) { - if (line.length < 4) { - continue; - } // Need at least "XY f" - - const status = line.slice(0, 2); - const file = line.slice(2).trimStart(); - - // Translate status codes to short labels - let statusLabel: string; - if (status.includes("M")) { - statusLabel = "M"; - } else if (status.includes("A")) { - statusLabel = "A"; - } else if (status.includes("D")) { - statusLabel = "D"; - } else if (status.includes("?")) { - statusLabel = "?"; - } else if (status.includes("R")) { - statusLabel = "R"; - } else if (status.includes("C")) { - statusLabel = "C"; - } else { - statusLabel = status.trim() || "~"; - } - - files.push({ status: statusLabel, statusLabel, file }); - } - - if (files.length === 0) { - ctx.ui.notify("No changes found", "info"); - return; - } - - const openSelected = async (fileInfo: FileInfo): Promise => { - try { - // Open in VS Code diff view. - // For untracked files, git difftool won't work, so fall back to just opening the file. - if (fileInfo.status === "?") { - await pi.exec("code", ["-g", fileInfo.file], { cwd: ctx.cwd }); - return; - } - - const diffResult = await pi.exec( - "git", - ["difftool", "-y", "--tool=vscode", fileInfo.file], - { - cwd: ctx.cwd, - }, - ); - if (diffResult.code !== 0) { - await pi.exec("code", ["-g", fileInfo.file], { cwd: ctx.cwd }); - } - } catch (error) { - const message = error instanceof Error ? error.message : String(error); - ctx.ui.notify(`Failed to open ${fileInfo.file}: ${message}`, "error"); - } - }; - - // Show file picker with SelectList - await ctx.ui.custom((tui, theme, _kb, done) => { - const container = new Container(); - - // Top border - container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s))); - - // Title - container.addChild(new Text(theme.fg("accent", theme.bold(" Select file to diff")), 0, 0)); - - // Build select items with colored status - const items: SelectItem[] = files.map((f) => { - let statusColor: string; - switch (f.status) { - case "M": - statusColor = theme.fg("warning", f.status); - break; - case "A": - statusColor = theme.fg("success", f.status); - break; - case "D": - statusColor = theme.fg("error", f.status); - break; - case "?": - statusColor = theme.fg("muted", f.status); - break; - default: - statusColor = theme.fg("dim", f.status); - } - return { - value: f, - label: `${statusColor} ${f.file}`, - }; - }); - - const visibleRows = Math.min(files.length, 15); - let currentIndex = 0; - - const selectList = new SelectList(items, visibleRows, { - selectedPrefix: (t) => theme.fg("accent", t), - selectedText: (t) => t, // Keep existing colors - description: (t) => theme.fg("muted", t), - scrollInfo: (t) => theme.fg("dim", t), - noMatch: (t) => theme.fg("warning", t), - }); - selectList.onSelect = (item) => { - void openSelected(item.value as FileInfo); - }; - selectList.onCancel = () => done(); - selectList.onSelectionChange = (item) => { - currentIndex = items.indexOf(item); - }; - container.addChild(selectList); - - // Help text - container.addChild( - new Text(theme.fg("dim", " ↑↓ navigate • ←→ page • enter open • esc close"), 0, 0), - ); - - // Bottom border - container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s))); - - return { - render: (w) => container.render(w), - invalidate: () => container.invalidate(), - handleInput: (data) => { - // Add paging with left/right - if (matchesKey(data, Key.left)) { - // Page up - clamp to 0 - currentIndex = Math.max(0, currentIndex - visibleRows); - selectList.setSelectedIndex(currentIndex); - } else if (matchesKey(data, Key.right)) { - // Page down - clamp to last - currentIndex = Math.min(items.length - 1, currentIndex + visibleRows); - selectList.setSelectedIndex(currentIndex); - } else { - selectList.handleInput(data); - } - tui.requestRender(); - }, - }; - }); - }, - }); -} diff --git a/.pi/extensions/files.ts b/.pi/extensions/files.ts deleted file mode 100644 index bba2760d032..00000000000 --- a/.pi/extensions/files.ts +++ /dev/null @@ -1,194 +0,0 @@ -/** - * Files Extension - * - * /files command lists all files the model has read/written/edited in the active session branch, - * coalesced by path and sorted newest first. Selecting a file opens it in VS Code. - */ - -import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; -import { DynamicBorder } from "@mariozechner/pi-coding-agent"; -import { - Container, - Key, - matchesKey, - type SelectItem, - SelectList, - Text, -} from "@mariozechner/pi-tui"; - -interface FileEntry { - path: string; - operations: Set<"read" | "write" | "edit">; - lastTimestamp: number; -} - -type FileToolName = "read" | "write" | "edit"; - -export default function (pi: ExtensionAPI) { - pi.registerCommand("files", { - description: "Show files read/written/edited in this session", - handler: async (_args, ctx) => { - if (!ctx.hasUI) { - ctx.ui.notify("No UI available", "error"); - return; - } - - // Get the current branch (path from leaf to root) - const branch = ctx.sessionManager.getBranch(); - - // First pass: collect tool calls (id -> {path, name}) from assistant messages - const toolCalls = new Map(); - - for (const entry of branch) { - if (entry.type !== "message") { - continue; - } - const msg = entry.message; - - if (msg.role === "assistant" && Array.isArray(msg.content)) { - for (const block of msg.content) { - if (block.type === "toolCall") { - const name = block.name; - if (name === "read" || name === "write" || name === "edit") { - const path = block.arguments?.path; - if (path && typeof path === "string") { - toolCalls.set(block.id, { path, name, timestamp: msg.timestamp }); - } - } - } - } - } - } - - // Second pass: match tool results to get the actual execution timestamp - const fileMap = new Map(); - - for (const entry of branch) { - if (entry.type !== "message") { - continue; - } - const msg = entry.message; - - if (msg.role === "toolResult") { - const toolCall = toolCalls.get(msg.toolCallId); - if (!toolCall) { - continue; - } - - const { path, name } = toolCall; - const timestamp = msg.timestamp; - - const existing = fileMap.get(path); - if (existing) { - existing.operations.add(name); - if (timestamp > existing.lastTimestamp) { - existing.lastTimestamp = timestamp; - } - } else { - fileMap.set(path, { - path, - operations: new Set([name]), - lastTimestamp: timestamp, - }); - } - } - } - - if (fileMap.size === 0) { - ctx.ui.notify("No files read/written/edited in this session", "info"); - return; - } - - // Sort by most recent first - const files = Array.from(fileMap.values()).toSorted( - (a, b) => b.lastTimestamp - a.lastTimestamp, - ); - - const openSelected = async (file: FileEntry): Promise => { - try { - await pi.exec("code", ["-g", file.path], { cwd: ctx.cwd }); - } catch (error) { - const message = error instanceof Error ? error.message : String(error); - ctx.ui.notify(`Failed to open ${file.path}: ${message}`, "error"); - } - }; - - // Show file picker with SelectList - await ctx.ui.custom((tui, theme, _kb, done) => { - const container = new Container(); - - // Top border - container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s))); - - // Title - container.addChild(new Text(theme.fg("accent", theme.bold(" Select file to open")), 0, 0)); - - // Build select items with colored operations - const items: SelectItem[] = files.map((f) => { - const ops: string[] = []; - if (f.operations.has("read")) { - ops.push(theme.fg("muted", "R")); - } - if (f.operations.has("write")) { - ops.push(theme.fg("success", "W")); - } - if (f.operations.has("edit")) { - ops.push(theme.fg("warning", "E")); - } - const opsLabel = ops.join(""); - return { - value: f, - label: `${opsLabel} ${f.path}`, - }; - }); - - const visibleRows = Math.min(files.length, 15); - let currentIndex = 0; - - const selectList = new SelectList(items, visibleRows, { - selectedPrefix: (t) => theme.fg("accent", t), - selectedText: (t) => t, // Keep existing colors - description: (t) => theme.fg("muted", t), - scrollInfo: (t) => theme.fg("dim", t), - noMatch: (t) => theme.fg("warning", t), - }); - selectList.onSelect = (item) => { - void openSelected(item.value as FileEntry); - }; - selectList.onCancel = () => done(); - selectList.onSelectionChange = (item) => { - currentIndex = items.indexOf(item); - }; - container.addChild(selectList); - - // Help text - container.addChild( - new Text(theme.fg("dim", " ↑↓ navigate • ←→ page • enter open • esc close"), 0, 0), - ); - - // Bottom border - container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s))); - - return { - render: (w) => container.render(w), - invalidate: () => container.invalidate(), - handleInput: (data) => { - // Add paging with left/right - if (matchesKey(data, Key.left)) { - // Page up - clamp to 0 - currentIndex = Math.max(0, currentIndex - visibleRows); - selectList.setSelectedIndex(currentIndex); - } else if (matchesKey(data, Key.right)) { - // Page down - clamp to last - currentIndex = Math.min(items.length - 1, currentIndex + visibleRows); - selectList.setSelectedIndex(currentIndex); - } else { - selectList.handleInput(data); - } - tui.requestRender(); - }, - }; - }); - }, - }); -} diff --git a/.pi/extensions/prompt-url-widget.ts b/.pi/extensions/prompt-url-widget.ts deleted file mode 100644 index 2bb56b104ea..00000000000 --- a/.pi/extensions/prompt-url-widget.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { - DynamicBorder, - type ExtensionAPI, - type ExtensionContext, -} from "@mariozechner/pi-coding-agent"; -import { Container, Text } from "@mariozechner/pi-tui"; - -const PR_PROMPT_PATTERN = /^\s*You are given one or more GitHub PR URLs:\s*(\S+)/im; -const ISSUE_PROMPT_PATTERN = /^\s*Analyze GitHub issue\(s\):\s*(\S+)/im; - -type PromptMatch = { - kind: "pr" | "issue"; - url: string; -}; - -type GhMetadata = { - title?: string; - author?: { - login?: string; - name?: string | null; - }; -}; - -function extractPromptMatch(prompt: string): PromptMatch | undefined { - const prMatch = prompt.match(PR_PROMPT_PATTERN); - if (prMatch?.[1]) { - return { kind: "pr", url: prMatch[1].trim() }; - } - - const issueMatch = prompt.match(ISSUE_PROMPT_PATTERN); - if (issueMatch?.[1]) { - return { kind: "issue", url: issueMatch[1].trim() }; - } - - return undefined; -} - -async function fetchGhMetadata( - pi: ExtensionAPI, - kind: PromptMatch["kind"], - url: string, -): Promise { - const args = - kind === "pr" - ? ["pr", "view", url, "--json", "title,author"] - : ["issue", "view", url, "--json", "title,author"]; - - try { - const result = await pi.exec("gh", args); - if (result.code !== 0 || !result.stdout) { - return undefined; - } - return JSON.parse(result.stdout) as GhMetadata; - } catch { - return undefined; - } -} - -function formatAuthor(author?: GhMetadata["author"]): string | undefined { - if (!author) { - return undefined; - } - const name = author.name?.trim(); - const login = author.login?.trim(); - if (name && login) { - return `${name} (@${login})`; - } - if (login) { - return `@${login}`; - } - if (name) { - return name; - } - return undefined; -} - -export default function promptUrlWidgetExtension(pi: ExtensionAPI) { - const setWidget = ( - ctx: ExtensionContext, - match: PromptMatch, - title?: string, - authorText?: string, - ) => { - ctx.ui.setWidget("prompt-url", (_tui, thm) => { - const titleText = title ? thm.fg("accent", title) : thm.fg("accent", match.url); - const authorLine = authorText ? thm.fg("muted", authorText) : undefined; - const urlLine = thm.fg("dim", match.url); - - const lines = [titleText]; - if (authorLine) { - lines.push(authorLine); - } - lines.push(urlLine); - - const container = new Container(); - container.addChild(new DynamicBorder((s: string) => thm.fg("muted", s))); - container.addChild(new Text(lines.join("\n"), 1, 0)); - return container; - }); - }; - - const applySessionName = (ctx: ExtensionContext, match: PromptMatch, title?: string) => { - const label = match.kind === "pr" ? "PR" : "Issue"; - const trimmedTitle = title?.trim(); - const fallbackName = `${label}: ${match.url}`; - const desiredName = trimmedTitle ? `${label}: ${trimmedTitle} (${match.url})` : fallbackName; - const currentName = pi.getSessionName()?.trim(); - if (!currentName) { - pi.setSessionName(desiredName); - return; - } - if (currentName === match.url || currentName === fallbackName) { - pi.setSessionName(desiredName); - } - }; - - pi.on("before_agent_start", async (event, ctx) => { - if (!ctx.hasUI) { - return; - } - const match = extractPromptMatch(event.prompt); - if (!match) { - return; - } - - setWidget(ctx, match); - applySessionName(ctx, match); - void fetchGhMetadata(pi, match.kind, match.url).then((meta) => { - const title = meta?.title?.trim(); - const authorText = formatAuthor(meta?.author); - setWidget(ctx, match, title, authorText); - applySessionName(ctx, match, title); - }); - }); - - pi.on("session_switch", async (_event, ctx) => { - rebuildFromSession(ctx); - }); - - const getUserText = (content: string | { type: string; text?: string }[] | undefined): string => { - if (!content) { - return ""; - } - if (typeof content === "string") { - return content; - } - return ( - content - .filter((block): block is { type: "text"; text: string } => block.type === "text") - .map((block) => block.text) - .join("\n") ?? "" - ); - }; - - const rebuildFromSession = (ctx: ExtensionContext) => { - if (!ctx.hasUI) { - return; - } - - const entries = ctx.sessionManager.getEntries(); - const lastMatch = [...entries].toReversed().find((entry) => { - if (entry.type !== "message" || entry.message.role !== "user") { - return false; - } - const text = getUserText(entry.message.content); - return !!extractPromptMatch(text); - }); - - const content = - lastMatch?.type === "message" && lastMatch.message.role === "user" - ? lastMatch.message.content - : undefined; - const text = getUserText(content); - const match = text ? extractPromptMatch(text) : undefined; - if (!match) { - ctx.ui.setWidget("prompt-url", undefined); - return; - } - - setWidget(ctx, match); - applySessionName(ctx, match); - void fetchGhMetadata(pi, match.kind, match.url).then((meta) => { - const title = meta?.title?.trim(); - const authorText = formatAuthor(meta?.author); - setWidget(ctx, match, title, authorText); - applySessionName(ctx, match, title); - }); - }; - - pi.on("session_start", async (_event, ctx) => { - rebuildFromSession(ctx); - }); -} diff --git a/.pi/extensions/redraws.ts b/.pi/extensions/redraws.ts deleted file mode 100644 index 6331f5eaba6..00000000000 --- a/.pi/extensions/redraws.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Redraws Extension - * - * Exposes /tui to show TUI redraw stats. - */ - -import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; -import { Text } from "@mariozechner/pi-tui"; - -export default function (pi: ExtensionAPI) { - pi.registerCommand("tui", { - description: "Show TUI stats", - handler: async (_args, ctx) => { - if (!ctx.hasUI) { - return; - } - let redraws = 0; - await ctx.ui.custom((tui, _theme, _keybindings, done) => { - redraws = tui.fullRedraws; - done(undefined); - return new Text("", 0, 0); - }); - ctx.ui.notify(`TUI full redraws: ${redraws}`, "info"); - }, - }); -} diff --git a/.pi/git/.gitignore b/.pi/git/.gitignore deleted file mode 100644 index d6b7ef32c84..00000000000 --- a/.pi/git/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/.pi/prompts/cl.md b/.pi/prompts/cl.md deleted file mode 100644 index 6d79ecda66e..00000000000 --- a/.pi/prompts/cl.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -description: Audit changelog entries before release ---- - -Audit changelog entries for all commits since the last release. - -## Process - -1. **Find the last release tag:** - - ```bash - git tag --sort=-version:refname | head -1 - ``` - -2. **List all commits since that tag:** - - ```bash - git log ..HEAD --oneline - ``` - -3. **Read each package's [Unreleased] section:** - - packages/ai/CHANGELOG.md - - packages/tui/CHANGELOG.md - - packages/coding-agent/CHANGELOG.md - -4. **For each commit, check:** - - Skip: changelog updates, doc-only changes, release housekeeping - - Determine which package(s) the commit affects (use `git show --stat`) - - Verify a changelog entry exists in the affected package(s) - - For external contributions (PRs), verify format: `Description ([#N](url) by [@user](url))` - -5. **Cross-package duplication rule:** - Changes in `ai`, `agent` or `tui` that affect end users should be duplicated to `coding-agent` changelog, since coding-agent is the user-facing package that depends on them. - -6. **Add New Features section after changelog fixes:** - - Insert a `### New Features` section at the start of `## [Unreleased]` in `packages/coding-agent/CHANGELOG.md`. - - Propose the top new features to the user for confirmation before writing them. - - Link to relevant docs and sections whenever possible. - -7. **Report:** - - List commits with missing entries - - List entries that need cross-package duplication - - Add any missing entries directly - -## Changelog Format Reference - -Sections (in order): - -- `### Breaking Changes` - API changes requiring migration -- `### Added` - New features -- `### Changed` - Changes to existing functionality -- `### Fixed` - Bug fixes -- `### Removed` - Removed features - -Attribution: - -- Internal: `Fixed foo ([#123](https://github.com/badlogic/pi-mono/issues/123))` -- External: `Added bar ([#456](https://github.com/badlogic/pi-mono/pull/456) by [@user](https://github.com/user))` diff --git a/.pi/prompts/is.md b/.pi/prompts/is.md deleted file mode 100644 index cc8f603adc0..00000000000 --- a/.pi/prompts/is.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -description: Analyze GitHub issues (bugs or feature requests) ---- - -Analyze GitHub issue(s): $ARGUMENTS - -For each issue: - -1. Read the issue in full, including all comments and linked issues/PRs. - -2. **For bugs**: - - Ignore any root cause analysis in the issue (likely wrong) - - Read all related code files in full (no truncation) - - Trace the code path and identify the actual root cause - - Propose a fix - -3. **For feature requests**: - - Read all related code files in full (no truncation) - - Propose the most concise implementation approach - - List affected files and changes needed - -Do NOT implement unless explicitly asked. Analyze and propose only. diff --git a/.pi/prompts/landpr.md b/.pi/prompts/landpr.md deleted file mode 100644 index 95e4692f3e5..00000000000 --- a/.pi/prompts/landpr.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -description: Land a PR (merge with proper workflow) ---- - -Input - -- PR: $1 - - If missing: use the most recent PR mentioned in the conversation. - - If ambiguous: ask. - -Do (end-to-end) -Goal: PR must end in GitHub state = MERGED (never CLOSED). Use `gh pr merge` with `--rebase` or `--squash`. - -1. Assign PR to self: - - `gh pr edit --add-assignee @me` -2. Repo clean: `git status`. -3. Identify PR meta (author + head branch): - - ```sh - gh pr view --json number,title,author,headRefName,baseRefName,headRepository --jq '{number,title,author:.author.login,head:.headRefName,base:.baseRefName,headRepo:.headRepository.nameWithOwner}' - contrib=$(gh pr view --json author --jq .author.login) - head=$(gh pr view --json headRefName --jq .headRefName) - head_repo_url=$(gh pr view --json headRepository --jq .headRepository.url) - ``` - -4. Fast-forward base: - - `git checkout main` - - `git pull --ff-only` -5. Create temp base branch from main: - - `git checkout -b temp/landpr-` -6. Check out PR branch locally: - - `gh pr checkout ` -7. Rebase PR branch onto temp base: - - `git rebase temp/landpr-` - - Fix conflicts; keep history tidy. -8. Fix + tests + changelog: - - Implement fixes + add/adjust tests - - Update `CHANGELOG.md` and mention `#` + `@$contrib` -9. Decide merge strategy: - - Rebase if we want to preserve commit history - - Squash if we want a single clean commit - - If unclear, ask -10. Full gate (BEFORE commit): - - `pnpm lint && pnpm build && pnpm test` -11. Commit via committer (final merge commit only includes PR # + thanks): - - For the final merge-ready commit: `committer "fix: (#) (thanks @$contrib)" CHANGELOG.md ` - - If you need intermediate fix commits before the final merge commit, keep those messages concise and **omit** PR number/thanks. - - `land_sha=$(git rev-parse HEAD)` -12. Push updated PR branch (rebase => usually needs force): - - ```sh - git remote add prhead "$head_repo_url.git" 2>/dev/null || git remote set-url prhead "$head_repo_url.git" - git push --force-with-lease prhead HEAD:$head - ``` - -13. Merge PR (must show MERGED on GitHub): - - Rebase: `gh pr merge --rebase` - - Squash: `gh pr merge --squash` - - Never `gh pr close` (closing is wrong) -14. Sync main: - - `git checkout main` - - `git pull --ff-only` -15. Comment on PR with what we did + SHAs + thanks: - - ```sh - merge_sha=$(gh pr view --json mergeCommit --jq '.mergeCommit.oid') - gh pr comment --body "Landed via temp rebase onto main.\n\n- Gate: pnpm lint && pnpm build && pnpm test\n- Land commit: $land_sha\n- Merge commit: $merge_sha\n\nThanks @$contrib!" - ``` - -16. Verify PR state == MERGED: - - `gh pr view --json state --jq .state` -17. Delete temp branch: - - `git branch -D temp/landpr-` diff --git a/.pi/prompts/reviewpr.md b/.pi/prompts/reviewpr.md deleted file mode 100644 index 835be806dd5..00000000000 --- a/.pi/prompts/reviewpr.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -description: Review a PR thoroughly without merging ---- - -Input - -- PR: $1 - - If missing: use the most recent PR mentioned in the conversation. - - If ambiguous: ask. - -Do (review-only) -Goal: produce a thorough review and a clear recommendation (READY for /landpr vs NEEDS WORK). Do NOT merge, do NOT push, do NOT make changes in the repo as part of this command. - -1. Identify PR meta + context - - ```sh - gh pr view --json number,title,state,isDraft,author,baseRefName,headRefName,headRepository,url,body,labels,assignees,reviewRequests,files,additions,deletions --jq '{number,title,url,state,isDraft,author:.author.login,base:.baseRefName,head:.headRefName,headRepo:.headRepository.nameWithOwner,additions,deletions,files:.files|length}' - ``` - -2. Read the PR description carefully - - Summarize the stated goal, scope, and any "why now?" rationale. - - Call out any missing context: motivation, alternatives considered, rollout/compat notes, risk. - -3. Read the diff thoroughly (prefer full diff) - - ```sh - gh pr diff - # If you need more surrounding context for files: - gh pr checkout # optional; still review-only - git show --stat - ``` - -4. Validate the change is needed / valuable - - What user/customer/dev pain does this solve? - - Is this change the smallest reasonable fix? - - Are we introducing complexity for marginal benefit? - - Are we changing behavior/contract in a way that needs docs or a release note? - -5. Evaluate implementation quality + optimality - - Correctness: edge cases, error handling, null/undefined, concurrency, ordering. - - Design: is the abstraction/architecture appropriate or over/under-engineered? - - Performance: hot paths, allocations, queries, network, N+1s, caching. - - Security/privacy: authz/authn, input validation, secrets, logging PII. - - Backwards compatibility: public APIs, config, migrations. - - Style consistency: formatting, naming, patterns used elsewhere. - -6. Tests & verification - - Identify what's covered by tests (unit/integration/e2e). - - Are there regression tests for the bug fixed / scenario added? - - Missing tests? Call out exact cases that should be added. - - If tests are present, do they actually assert the important behavior (not just snapshots / happy path)? - -7. Follow-up refactors / cleanup suggestions - - Any code that should be simplified before merge? - - Any TODOs that should be tickets vs addressed now? - - Any deprecations, docs, types, or lint rules we should adjust? - -8. Key questions to answer explicitly - - Can we fix everything ourselves in a follow-up, or does the contributor need to update this PR? - - Any blocking concerns (must-fix before merge)? - - Is this PR ready to land, or does it need work? - -9. Output (structured) - Produce a review with these sections: - -A) TL;DR recommendation - -- One of: READY FOR /landpr | NEEDS WORK | NEEDS DISCUSSION -- 1–3 sentence rationale. - -B) What changed - -- Brief bullet summary of the diff/behavioral changes. - -C) What's good - -- Bullets: correctness, simplicity, tests, docs, ergonomics, etc. - -D) Concerns / questions (actionable) - -- Numbered list. -- Mark each item as: - - BLOCKER (must fix before merge) - - IMPORTANT (should fix before merge) - - NIT (optional) -- For each: point to the file/area and propose a concrete fix or alternative. - -E) Tests - -- What exists. -- What's missing (specific scenarios). - -F) Follow-ups (optional) - -- Non-blocking refactors/tickets to open later. - -G) Suggested PR comment (optional) - -- Offer: "Want me to draft a PR comment to the author?" -- If yes, provide a ready-to-paste comment summarizing the above, with clear asks. - -Rules / Guardrails - -- Review only: do not merge (`gh pr merge`), do not push branches, do not edit code. -- If you need clarification, ask questions rather than guessing. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index e946d18c112..00000000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,105 +0,0 @@ -# Pre-commit hooks for openclaw -# Install: prek install -# Run manually: prek run --all-files -# -# See https://pre-commit.com for more information - -repos: - # Basic file hygiene - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 - hooks: - - id: trailing-whitespace - exclude: '^(docs/|dist/|vendor/|.*\.snap$)' - - id: end-of-file-fixer - exclude: '^(docs/|dist/|vendor/|.*\.snap$)' - - id: check-yaml - args: [--allow-multiple-documents] - - id: check-added-large-files - args: [--maxkb=500] - - id: check-merge-conflict - - # Secret detection (same as CI) - - repo: https://github.com/Yelp/detect-secrets - rev: v1.5.0 - hooks: - - id: detect-secrets - args: - - --baseline - - .secrets.baseline - - --exclude-files - - '(^|/)(dist/|vendor/|pnpm-lock\.yaml$|\.detect-secrets\.cfg$)' - - --exclude-lines - - 'key_content\.include\?\("BEGIN PRIVATE KEY"\)' - - --exclude-lines - - 'case \.apiKeyEnv: "API key \(env var\)"' - - --exclude-lines - - 'case apikey = "apiKey"' - - --exclude-lines - - '"gateway\.remote\.password"' - - --exclude-lines - - '"gateway\.auth\.password"' - - --exclude-lines - - '"talk\.apiKey"' - - --exclude-lines - - '=== "string"' - - --exclude-lines - - 'typeof remote\?\.password === "string"' - - # Shell script linting - - repo: https://github.com/koalaman/shellcheck-precommit - rev: v0.11.0 - hooks: - - id: shellcheck - args: [--severity=error] # Only fail on errors, not warnings/info - # Exclude vendor and scripts with embedded code or known issues - exclude: "^(vendor/|scripts/e2e/)" - - # GitHub Actions linting - - repo: https://github.com/rhysd/actionlint - rev: v1.7.10 - hooks: - - id: actionlint - - # GitHub Actions security audit - - repo: https://github.com/zizmorcore/zizmor-pre-commit - rev: v1.22.0 - hooks: - - id: zizmor - args: [--persona=regular, --min-severity=medium, --min-confidence=medium] - exclude: "^(vendor/|Swabble/)" - - # Project checks (same commands as CI) - - repo: local - hooks: - # oxlint --type-aware src test - - id: oxlint - name: oxlint - entry: scripts/pre-commit/run-node-tool.sh oxlint --type-aware src test - language: system - pass_filenames: false - types_or: [javascript, jsx, ts, tsx] - - # oxfmt --check src test - - id: oxfmt - name: oxfmt - entry: scripts/pre-commit/run-node-tool.sh oxfmt --check src test - language: system - pass_filenames: false - types_or: [javascript, jsx, ts, tsx] - - # swiftlint (same as CI) - - id: swiftlint - name: swiftlint - entry: swiftlint --config .swiftlint.yml - language: system - pass_filenames: false - types: [swift] - - # swiftformat --lint (same as CI) - - id: swiftformat - name: swiftformat - entry: swiftformat --lint apps/macos/Sources --config .swiftformat - language: system - pass_filenames: false - types: [swift] diff --git a/.secrets.baseline b/.secrets.baseline deleted file mode 100644 index 089515fe250..00000000000 --- a/.secrets.baseline +++ /dev/null @@ -1,13104 +0,0 @@ -{ - "version": "1.5.0", - "plugins_used": [ - { - "name": "ArtifactoryDetector" - }, - { - "name": "AWSKeyDetector" - }, - { - "name": "AzureStorageKeyDetector" - }, - { - "name": "Base64HighEntropyString", - "limit": 4.5 - }, - { - "name": "BasicAuthDetector" - }, - { - "name": "CloudantDetector" - }, - { - "name": "DiscordBotTokenDetector" - }, - { - "name": "GitHubTokenDetector" - }, - { - "name": "GitLabTokenDetector" - }, - { - "name": "HexHighEntropyString", - "limit": 3.0 - }, - { - "name": "IbmCloudIamDetector" - }, - { - "name": "IbmCosHmacDetector" - }, - { - "name": "IPPublicDetector" - }, - { - "name": "JwtTokenDetector" - }, - { - "name": "KeywordDetector", - "keyword_exclude": "" - }, - { - "name": "MailchimpDetector" - }, - { - "name": "NpmDetector" - }, - { - "name": "OpenAIDetector" - }, - { - "name": "PrivateKeyDetector" - }, - { - "name": "PypiTokenDetector" - }, - { - "name": "SendGridDetector" - }, - { - "name": "SlackDetector" - }, - { - "name": "SoftlayerDetector" - }, - { - "name": "SquareOAuthDetector" - }, - { - "name": "StripeDetector" - }, - { - "name": "TelegramBotTokenDetector" - }, - { - "name": "TwilioKeyDetector" - } - ], - "filters_used": [ - { - "path": "detect_secrets.filters.allowlist.is_line_allowlisted" - }, - { - "path": "detect_secrets.filters.common.is_baseline_file", - "filename": ".secrets.baseline" - }, - { - "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies", - "min_level": 2 - }, - { - "path": "detect_secrets.filters.heuristic.is_indirect_reference" - }, - { - "path": "detect_secrets.filters.heuristic.is_likely_id_string" - }, - { - "path": "detect_secrets.filters.heuristic.is_lock_file" - }, - { - "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string" - }, - { - "path": "detect_secrets.filters.heuristic.is_potential_uuid" - }, - { - "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign" - }, - { - "path": "detect_secrets.filters.heuristic.is_sequential_string" - }, - { - "path": "detect_secrets.filters.heuristic.is_swagger_file" - }, - { - "path": "detect_secrets.filters.heuristic.is_templated_secret" - }, - { - "path": "detect_secrets.filters.regex.should_exclude_file", - "pattern": [ - "(^|/)pnpm-lock\\.yaml$" - ] - }, - { - "path": "detect_secrets.filters.regex.should_exclude_line", - "pattern": [ - "key_content\\.include\\?\\(\"BEGIN PRIVATE KEY\"\\)", - "case \\.apiKeyEnv: \"API key \\(env var\\)\"", - "case apikey = \"apiKey\"", - "\"gateway\\.remote\\.password\"", - "\"gateway\\.auth\\.password\"", - "\"talk\\.apiKey\"", - "=== \"string\"", - "typeof remote\\?\\.password === \"string\"" - ] - } - ], - "results": { - ".detect-secrets.cfg": [ - { - "type": "Private Key", - "filename": ".detect-secrets.cfg", - "hashed_secret": "1348b145fa1a555461c1b790a2f66614781091e9", - "is_verified": false, - "line_number": 17 - }, - { - "type": "Secret Keyword", - "filename": ".detect-secrets.cfg", - "hashed_secret": "fe88fceb47e040ba1bfafa4ac639366188df2f6d", - "is_verified": false, - "line_number": 19 - } - ], - "appcast.xml": [ - { - "type": "Base64 High Entropy String", - "filename": "appcast.xml", - "hashed_secret": "2bc43713edb8f775582c6314953b7c020d691aba", - "is_verified": false, - "line_number": 141 - }, - { - "type": "Base64 High Entropy String", - "filename": "appcast.xml", - "hashed_secret": "2fcd83b35235522978c19dbbab2884a09aa64f35", - "is_verified": false, - "line_number": 209 - }, - { - "type": "Base64 High Entropy String", - "filename": "appcast.xml", - "hashed_secret": "78b65f0952ed8a557e0f67b2364ff67cb6863bc8", - "is_verified": false, - "line_number": 310 - } - ], - "apps/android/app/src/test/java/ai/openclaw/android/node/AppUpdateHandlerTest.kt": [ - { - "type": "Hex High Entropy String", - "filename": "apps/android/app/src/test/java/ai/openclaw/android/node/AppUpdateHandlerTest.kt", - "hashed_secret": "ee662f2bc691daa48d074542722d8e1b0587673c", - "is_verified": false, - "line_number": 58 - } - ], - "apps/ios/Sources/Gateway/GatewaySettingsStore.swift": [ - { - "type": "Secret Keyword", - "filename": "apps/ios/Sources/Gateway/GatewaySettingsStore.swift", - "hashed_secret": "5f7c0c35e552780b67fe1c0ee186764354793be3", - "is_verified": false, - "line_number": 28 - } - ], - "apps/ios/Tests/DeepLinkParserTests.swift": [ - { - "type": "Secret Keyword", - "filename": "apps/ios/Tests/DeepLinkParserTests.swift", - "hashed_secret": "1a91d62f7ca67399625a4368a6ab5d4a3baa6073", - "is_verified": false, - "line_number": 89 - } - ], - "apps/macos/Sources/OpenClawProtocol/GatewayModels.swift": [ - { - "type": "Secret Keyword", - "filename": "apps/macos/Sources/OpenClawProtocol/GatewayModels.swift", - "hashed_secret": "7990585255d25249fb1e6eac3d2bd6c37429b2cd", - "is_verified": false, - "line_number": 1492 - } - ], - "apps/macos/Tests/OpenClawIPCTests/AnthropicAuthResolverTests.swift": [ - { - "type": "Secret Keyword", - "filename": "apps/macos/Tests/OpenClawIPCTests/AnthropicAuthResolverTests.swift", - "hashed_secret": "e761624445731fcb8b15da94343c6b92e507d190", - "is_verified": false, - "line_number": 26 - }, - { - "type": "Secret Keyword", - "filename": "apps/macos/Tests/OpenClawIPCTests/AnthropicAuthResolverTests.swift", - "hashed_secret": "a23c8630c8a5fbaa21f095e0269c135c20d21689", - "is_verified": false, - "line_number": 42 - } - ], - "apps/macos/Tests/OpenClawIPCTests/GatewayEndpointStoreTests.swift": [ - { - "type": "Secret Keyword", - "filename": "apps/macos/Tests/OpenClawIPCTests/GatewayEndpointStoreTests.swift", - "hashed_secret": "19dad5cecb110281417d1db56b60e1b006d55bb4", - "is_verified": false, - "line_number": 61 - } - ], - "apps/macos/Tests/OpenClawIPCTests/GatewayLaunchAgentManagerTests.swift": [ - { - "type": "Secret Keyword", - "filename": "apps/macos/Tests/OpenClawIPCTests/GatewayLaunchAgentManagerTests.swift", - "hashed_secret": "1a91d62f7ca67399625a4368a6ab5d4a3baa6073", - "is_verified": false, - "line_number": 13 - } - ], - "apps/macos/Tests/OpenClawIPCTests/TailscaleIntegrationSectionTests.swift": [ - { - "type": "Secret Keyword", - "filename": "apps/macos/Tests/OpenClawIPCTests/TailscaleIntegrationSectionTests.swift", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 27 - } - ], - "apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayChannel.swift": [ - { - "type": "Secret Keyword", - "filename": "apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayChannel.swift", - "hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", - "is_verified": false, - "line_number": 106 - } - ], - "apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift": [ - { - "type": "Secret Keyword", - "filename": "apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift", - "hashed_secret": "7990585255d25249fb1e6eac3d2bd6c37429b2cd", - "is_verified": false, - "line_number": 1492 - } - ], - "docs/.i18n/zh-CN.tm.jsonl": [ - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6ba7bb7047f44b28279fbb11350e1a7bf4e7de59", - "is_verified": false, - "line_number": 1 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e83ec66165edcee8f2b408b5e6bafe4844071f8f", - "is_verified": false, - "line_number": 2 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8793597fb80169cbcefe08a1b0151138b7ab78bd", - "is_verified": false, - "line_number": 3 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "af6b2a2ef841b637288e2eb2726e20ed9c3974c0", - "is_verified": false, - "line_number": 4 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "db1f9e54942e872f3a7b29aa174c70a3167d76f2", - "is_verified": false, - "line_number": 5 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f66de1a7ae418bd55115d4fac319824deb0d88cb", - "is_verified": false, - "line_number": 6 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "98510d5b8050a30514bc7fa147af6f66e5e34804", - "is_verified": false, - "line_number": 7 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b03e1a8bbe1b422cb64d7aea071d94088b6c1768", - "is_verified": false, - "line_number": 8 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6f72b03efde2d701a7e882dcaed1e935484a8e67", - "is_verified": false, - "line_number": 9 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "57d35c7411cff6f679c4a437d3251c0532fbe3cb", - "is_verified": false, - "line_number": 10 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fbffe72a354d73fad191eec6605543d3e8e5f549", - "is_verified": false, - "line_number": 11 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ceb3b4e53c22f7e28ab7006c9e1931bd31d534e1", - "is_verified": false, - "line_number": 12 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3eb65eb5d24ab5bd58a57bcd1a1894c1d05ad7f6", - "is_verified": false, - "line_number": 13 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "88e065467489c885d4d80d8f582707f3ca6284e6", - "is_verified": false, - "line_number": 14 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fd9e2dd936c475429f6d461056c5d97d1635de2e", - "is_verified": false, - "line_number": 15 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b7a629ae866eda49b01fe2eccbf842b52594442a", - "is_verified": false, - "line_number": 16 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "67c615ed823ff022c807fcb65d52bd454a52bc1f", - "is_verified": false, - "line_number": 17 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "121e6974c091fafcc6e493892b7e7ffe3c81e7eb", - "is_verified": false, - "line_number": 18 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2be720cb8d166c422e71de2c43dbb5832c952df5", - "is_verified": false, - "line_number": 19 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e44ba9d2b09e8923191b76eb9f58127ad9980cae", - "is_verified": false, - "line_number": 20 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ff53d507245282f09d082321e8ef511a3e2af5ff", - "is_verified": false, - "line_number": 21 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7ecbf8a10b1e8bc096b49c27d3b70812778205eb", - "is_verified": false, - "line_number": 22 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5628e70d1f7717c328418619beb0ae164fb5075c", - "is_verified": false, - "line_number": 23 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b0b8efbb45c2854a57241d51c2b556838eaebc00", - "is_verified": false, - "line_number": 24 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "686c14971a01fa1737cc2c00790933213b688e52", - "is_verified": false, - "line_number": 25 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6311a112d1ef120acc3247c79a07721b9dc52f5b", - "is_verified": false, - "line_number": 26 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0765cbc88514c95526bffd2e5b5144e050969aae", - "is_verified": false, - "line_number": 27 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8d4d995d95dae479362773b1fe5ff943f735dd97", - "is_verified": false, - "line_number": 28 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6da60e76ffee6f074c22f89fbfe1969b9b5bbbe2", - "is_verified": false, - "line_number": 29 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "40efc129489cfc37e7f114be79db3843adfd6549", - "is_verified": false, - "line_number": 30 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "976e548e417838885ab177817cf2b04f9c390571", - "is_verified": false, - "line_number": 31 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "26ad87428b833b4d5d569c10ec5bd7cc32019a0a", - "is_verified": false, - "line_number": 32 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "45f8de688074faa92a647dcf9f67b670de68a2b0", - "is_verified": false, - "line_number": 33 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "24d6fb4ef117d39c5f9c45a205faf1c85f356fa0", - "is_verified": false, - "line_number": 34 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "172a6875ed57d321409cb9c27d425b0b41eacb29", - "is_verified": false, - "line_number": 35 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bf13e4219d558c0deff114eb6b6098dd12d30e90", - "is_verified": false, - "line_number": 36 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1c91d3756008237ba0540b5831e88763e45a4fa9", - "is_verified": false, - "line_number": 37 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "63f55dcafa051c764eebfc72939788ec777fa3b5", - "is_verified": false, - "line_number": 38 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2fec58745fb43cefe32e523ca60285baa33825c3", - "is_verified": false, - "line_number": 39 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7dc4fc41a5c1ba307be067570a0e458f3b139696", - "is_verified": false, - "line_number": 40 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "26e2d413623e29e208ee2e71dd8aa02db3f0daa5", - "is_verified": false, - "line_number": 41 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "816184e85b856e06b4d70967ce713e72b22292e5", - "is_verified": false, - "line_number": 42 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "874b4362c636af8f5b4aebe013ae321ab0b83fd9", - "is_verified": false, - "line_number": 43 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8e89a4e4945335d905762eb2dc5e8510abc9716d", - "is_verified": false, - "line_number": 44 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7d4eb519b7fa3bce189b20609de596db82b56fae", - "is_verified": false, - "line_number": 45 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "22f878f965c38ebecdfd6ba0229e118cbfc80b00", - "is_verified": false, - "line_number": 46 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2b2b5ced0fb09d74ab6fba9f058139ef47ad6bda", - "is_verified": false, - "line_number": 47 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ff5c4ac7b55661c8bb699005b3ba9e0299b66ec9", - "is_verified": false, - "line_number": 48 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "541344e343f0f02cb1548729b073161d0b44c373", - "is_verified": false, - "line_number": 49 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "886979ee264082f1daebc1a2c95e9376281869fa", - "is_verified": false, - "line_number": 50 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d1c7b012097938e3b75365359d49aa134768f64f", - "is_verified": false, - "line_number": 51 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9c6a58787264a4fb0a823f9e20fd2c9abf82b96d", - "is_verified": false, - "line_number": 52 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "79e2c2821ed6a8b47486b4ddea90be8c7d4ad5b8", - "is_verified": false, - "line_number": 53 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ae8e49c80ed43d16eef9f633c28879b3166318ab", - "is_verified": false, - "line_number": 54 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f96db0197e1d67eab1197a03c107b07a71cd0ce7", - "is_verified": false, - "line_number": 55 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cf799fdab5d19a32f25735f5b6a1265b6e30c33d", - "is_verified": false, - "line_number": 56 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9d2165cc2b208ca555fb00ddaa1768455c89c4d0", - "is_verified": false, - "line_number": 57 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9139a8402a3454c747b23df0d7c8e957312dd6d2", - "is_verified": false, - "line_number": 58 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "00bb66a6c79ba6cfebbf1018a83af7129a29a479", - "is_verified": false, - "line_number": 59 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5b43b45627cffb5959d10386ec63025d28dbeec4", - "is_verified": false, - "line_number": 60 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c99e2f9d7726da2ea48cb07e71a33a757cb12118", - "is_verified": false, - "line_number": 61 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1880416d744d0693237d330f6ca744b59e7e12b4", - "is_verified": false, - "line_number": 62 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2ed0dc836758d77d6a96c6b96d054697a59d64f0", - "is_verified": false, - "line_number": 63 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8f34c522fe85146a367d92efe27488718791707e", - "is_verified": false, - "line_number": 64 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5bc1ce83e698af25ed3427553c8a3fcf8aaefdc9", - "is_verified": false, - "line_number": 65 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "05e16bf4e66e22a4a83defe89f6e746becf049b8", - "is_verified": false, - "line_number": 66 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "97b2b3d469cde6e5e88ac0089433c772d2d86b0d", - "is_verified": false, - "line_number": 67 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "149e7eb26c3598e6fa620c61de9e7562d7995e01", - "is_verified": false, - "line_number": 68 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5ec42634100091a94f71a2fd14820cb535df481e", - "is_verified": false, - "line_number": 69 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8d6ef196daa5e81bda9ac982bcb40a6f07d4f50c", - "is_verified": false, - "line_number": 70 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2d5c79b7d58642498f734dbe2c1245159a277a1e", - "is_verified": false, - "line_number": 71 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7efd41240b058195c11e1ea621060bc8c82df8fc", - "is_verified": false, - "line_number": 72 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "47f6371bd5fe1746bcade2fea59cb8d93ff5c4e0", - "is_verified": false, - "line_number": 73 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c67ce872a65c537d8748b302f45479714a04c420", - "is_verified": false, - "line_number": 74 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fc32724374d238112dd530743e85af73f1c8eb8e", - "is_verified": false, - "line_number": 75 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a01d187f1b0f38159c62f32405796de21548be31", - "is_verified": false, - "line_number": 76 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a39ae2ab785dc2d4aab7856b0a7c6e4e5875b215", - "is_verified": false, - "line_number": 77 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4ad4b170f1617e562f07cba453b69c8bc53cb5cd", - "is_verified": false, - "line_number": 78 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b0e551f8b6fbe0147169202fbc141c1a0478dfb2", - "is_verified": false, - "line_number": 79 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "02593ce120c7398316c65894a5fa4be694ea3cee", - "is_verified": false, - "line_number": 80 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "789bc546ba1936b86999373fca6d6a6a4899a787", - "is_verified": false, - "line_number": 81 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ee29461a81f3e898f4376d270ac84b8567f9b68c", - "is_verified": false, - "line_number": 82 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "235f549d4c65ec31307e0887204c428441d6229f", - "is_verified": false, - "line_number": 83 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "87b2376e9f5457bad56b7fb363c6a5f86d8f119a", - "is_verified": false, - "line_number": 84 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c3b3424f5845769977ccb309a3c2b70117989e3c", - "is_verified": false, - "line_number": 85 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "88ddc980ca5f609c2806df08e2e1b9b206153817", - "is_verified": false, - "line_number": 86 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "af48a18326858bfcef8e5f3a850fba0f9d462549", - "is_verified": false, - "line_number": 87 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c22217254346f8d551183caac2f73ec8284953b3", - "is_verified": false, - "line_number": 88 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2de7388be37ebdde032f5e169940da7c9d38ac8b", - "is_verified": false, - "line_number": 89 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "98facee0b1bf74672bacb855a27972851929dd78", - "is_verified": false, - "line_number": 90 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0a5cae7f96ade77892c5caa993b6d19cd41232fb", - "is_verified": false, - "line_number": 91 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fe0da76f124e112f6702f2e9c62514238398ba8d", - "is_verified": false, - "line_number": 92 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d5ce761d7b87445aa65b1734ad36c5d3d1d71c2a", - "is_verified": false, - "line_number": 93 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f5b70c708f3034bd837835329603a499207c4fb5", - "is_verified": false, - "line_number": 94 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "50d6381367811dd8a0ad61bf1dd2c3619ece8a44", - "is_verified": false, - "line_number": 95 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fe061e35aafc5841544633d917f55357813c0906", - "is_verified": false, - "line_number": 96 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "dc8722d30a33248ccc5dd9012fba71eefd3a44ac", - "is_verified": false, - "line_number": 97 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2fb43da561bbb79d7cf89e5d6c5102c1436f6f49", - "is_verified": false, - "line_number": 98 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cf61d12e9d98f6ba507bf40285d05f37fe158a01", - "is_verified": false, - "line_number": 99 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "dfeb7563bafd2d89888b8b440dee49d089daeb78", - "is_verified": false, - "line_number": 100 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fea45d453b5b8650cda0b2b9db6b85b60c503d6c", - "is_verified": false, - "line_number": 101 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bb7538d46b4fde60dc88be303de19d35fe89019d", - "is_verified": false, - "line_number": 102 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "08e0674faf444c6dc671036d900e3decce98d1eb", - "is_verified": false, - "line_number": 103 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e261897f1d1a99aafec462606b65228331e30583", - "is_verified": false, - "line_number": 104 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ffe19721c941dfb929b30707c8513e2f0c8c4dc7", - "is_verified": false, - "line_number": 105 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fe1fc5b0e4ca6aa0189f77a9d78b852201366b81", - "is_verified": false, - "line_number": 106 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "590787fa67e0d75346ed1a3850f98741b6a49506", - "is_verified": false, - "line_number": 107 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "eccb56a947e4d36b8e9d51d0e071caf1a978c6f2", - "is_verified": false, - "line_number": 108 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c301ee23c9e41d15d5c58c7cd5939e41e7d1eb99", - "is_verified": false, - "line_number": 109 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9f8607273e42be64e9779e59455706923081cd80", - "is_verified": false, - "line_number": 110 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "72d31fe5a3e5b6e818f5fd3ec97a9ac0042acec7", - "is_verified": false, - "line_number": 111 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bb9158c9b6e8a0a1007b93b92ec531bdd9ffd32e", - "is_verified": false, - "line_number": 112 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c2ca44d18bd79c0f1b663d8bc3dfcfb02a7e02df", - "is_verified": false, - "line_number": 113 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "eac2c4cc6263495036a0ef8d8aaf2d8075167249", - "is_verified": false, - "line_number": 114 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f55341301796552621f367fff6ea9a2bd076df29", - "is_verified": false, - "line_number": 115 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "21967ac89d793aa883840d7a71308514e9e1dc4e", - "is_verified": false, - "line_number": 116 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "679dc9deb86fd7375692381ae784de604a552ae3", - "is_verified": false, - "line_number": 117 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "dd90f8337c050490f6e9b191fb603c9ad402d8c0", - "is_verified": false, - "line_number": 118 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3c8bfe5a9f458f3884e67768465ac1c17ff80e0f", - "is_verified": false, - "line_number": 119 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3f01eb8d14a37b6e087592d109baf01e603417eb", - "is_verified": false, - "line_number": 120 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "021709695261ffbc463f12b726d9dd6c27abb6f0", - "is_verified": false, - "line_number": 121 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a09a21e3684c15de00769686d906f72dd664f663", - "is_verified": false, - "line_number": 122 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "15a62195ff8e8694bfd7045af4391df383b990ed", - "is_verified": false, - "line_number": 123 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "010fa027e45282a3941133bf3403ab98cacc9edd", - "is_verified": false, - "line_number": 124 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e19fd3f99a05ccf60d1083f5601dea6817b1ac03", - "is_verified": false, - "line_number": 125 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d17a8e92d9f18e17c7477d375dcac30af8c34ff5", - "is_verified": false, - "line_number": 126 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c33ae1092a63f763487a4e0d84720b06a2523880", - "is_verified": false, - "line_number": 127 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9486a607ef0dcb94ce9ac75a85f0a76230defd1d", - "is_verified": false, - "line_number": 128 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1d850e2d57c74a691b52e3e2526c2767865fb798", - "is_verified": false, - "line_number": 129 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "60a0c030c7e8a5beddd199d1061825b5684ab4ae", - "is_verified": false, - "line_number": 130 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2986a818d44589ee322b0d05a751b9184b74ebac", - "is_verified": false, - "line_number": 131 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "440aad6aaad76b0dab4c53eb8a9c511d38f5ee1c", - "is_verified": false, - "line_number": 132 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "372c99f2afefff2b07dd4611b07c6830ec1014f3", - "is_verified": false, - "line_number": 133 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "99678a4cbb8d20741f35f04235ee808686a5ee52", - "is_verified": false, - "line_number": 134 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3486b5c6f177ac543d846a9195d3291a0d3bd724", - "is_verified": false, - "line_number": 135 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2902179aba6cb39f2c7b774649301a368a39b969", - "is_verified": false, - "line_number": 136 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4108ee51d5c321b98393b68a262b74d6377cec76", - "is_verified": false, - "line_number": 137 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8abe8434123396924dc964759bc7823d59b31283", - "is_verified": false, - "line_number": 138 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a2a8363585b5988aeff2a2c8c878c15445322a52", - "is_verified": false, - "line_number": 139 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bbbcc1630c23a709000e6da74ca22fe18b78b919", - "is_verified": false, - "line_number": 140 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "be582fadd937879b93b46e404049076080faed08", - "is_verified": false, - "line_number": 141 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "15320eb2e8d97720f682f8dc5105cb86a539a452", - "is_verified": false, - "line_number": 142 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "611278690506b584ecc5d4c88b334dbe7e9b8c54", - "is_verified": false, - "line_number": 143 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8a08069ce7a3702f245f8c50ac49a529092384be", - "is_verified": false, - "line_number": 144 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8cf1444399ca01a1bf569233106065b30c103cd2", - "is_verified": false, - "line_number": 145 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4a5a11832d16a4c2c6914d05397ce3e6f457572f", - "is_verified": false, - "line_number": 146 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "80490973b1980ad3740d42426c7c0f2986cbe462", - "is_verified": false, - "line_number": 147 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "495d2b2d95ba56eded4e4d738b229dd5caaeea67", - "is_verified": false, - "line_number": 148 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2264d1d1a69546223eb2754465a1b40ce20ab936", - "is_verified": false, - "line_number": 149 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6e9e9f0b269aacbf7358498c088c226a9296de14", - "is_verified": false, - "line_number": 150 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1cb9e17cefe3759cb8fd0de893e8a12531c4375b", - "is_verified": false, - "line_number": 151 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ddc15a0e8c7caca06cf93d15768533595b8ba232", - "is_verified": false, - "line_number": 152 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7dbafb9953c44da0cc46c003d3dacd14a32a4438", - "is_verified": false, - "line_number": 153 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "be61d29ac11ba55400fcaf405a1b404e269e528e", - "is_verified": false, - "line_number": 154 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2e65dec5c2802e2bb8102d3cd8d0a7e031a6b130", - "is_verified": false, - "line_number": 155 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c43e69c82865cf66a55df2d00a9e842df3525669", - "is_verified": false, - "line_number": 156 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "084448bff84b39813fc1efe3ff5840807d7da8f9", - "is_verified": false, - "line_number": 157 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e175aaf2f1a6929f95138b56d92ae7b84b831ffe", - "is_verified": false, - "line_number": 158 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9d6deadf9c4eb8ea0240ecca10258afb9b39e0a2", - "is_verified": false, - "line_number": 159 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4bf318f05592507a55a872cdb1a5739ad4477293", - "is_verified": false, - "line_number": 160 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b71cc2bafb860b166886bb522c191f45d405cc76", - "is_verified": false, - "line_number": 161 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a723b7af4e7b4ede705855c03e4d3ac8b17a17a0", - "is_verified": false, - "line_number": 162 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "595c5493c18960b81043b1aaa0ada4a86a493f2b", - "is_verified": false, - "line_number": 163 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "dee9b3f8262451274b6451ead384675a75700188", - "is_verified": false, - "line_number": 164 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b300397e68cfcee9898e8e00f7395a27f8280070", - "is_verified": false, - "line_number": 165 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "44973e389b0e5b25d51439d6a9b6c9d43fdd6ee0", - "is_verified": false, - "line_number": 166 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "93ebcb14fec5ae9ae41b0bdce7d6aa2971298e47", - "is_verified": false, - "line_number": 167 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c5b1332b11dd3ba639ce2fdaaa025bad034207e9", - "is_verified": false, - "line_number": 168 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4927a4f45fa60e6d8deb3d42ca896410d791f3db", - "is_verified": false, - "line_number": 169 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "081e263d2c8f882eb19692648f71ac03a8731c09", - "is_verified": false, - "line_number": 170 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ef5eba4fd8203b259dd839628ddc0d9a3ed6f97f", - "is_verified": false, - "line_number": 171 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c90d7323630daddb2824cd0d9e637521237e2454", - "is_verified": false, - "line_number": 172 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "99e13b6a3b2c3c60603df94711c67938be98e776", - "is_verified": false, - "line_number": 173 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2c55757167c8ecf90790ad052900e790f269619e", - "is_verified": false, - "line_number": 174 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f3e5c54b01b6e69be585cd9142ed7abe5d4056e5", - "is_verified": false, - "line_number": 175 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b0dd1c28e143d597218a174dbe0274598c59b9c8", - "is_verified": false, - "line_number": 176 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9a1fe8341b21243d6116f6b3375877b7fa9b34d7", - "is_verified": false, - "line_number": 177 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e6b9bc000db030828a117a2d31a0598a84120186", - "is_verified": false, - "line_number": 178 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8e40eebcfe379882ecbfb761bb470c208826ebf8", - "is_verified": false, - "line_number": 179 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "afd7a7532b580be96e7cc3c0e368a89f31ef621c", - "is_verified": false, - "line_number": 180 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bfd20c7315b569fab2449be3018de404ed0d6fc3", - "is_verified": false, - "line_number": 181 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ccba0997cbb3cea20186ca1d3d3b170044e78f27", - "is_verified": false, - "line_number": 182 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "43cd2dcd4adf33ef138634454d93153671a58357", - "is_verified": false, - "line_number": 183 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7244b34d4c1c0014497a432c580eeea0498b7996", - "is_verified": false, - "line_number": 184 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ec96512c56ade3837920de713f54fa81e6463a5b", - "is_verified": false, - "line_number": 185 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f9ab8ac96faef103a825c131a9f6aa18aaf5c496", - "is_verified": false, - "line_number": 186 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "988b02f25fa7b8124ad9d5e3127ec7690bd7f568", - "is_verified": false, - "line_number": 187 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "71d4e0487a5ed7f3f82b2256bed1efb3797c99e2", - "is_verified": false, - "line_number": 188 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4dad8db6d2449abd1800ac11f64dd362f579a823", - "is_verified": false, - "line_number": 189 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d079b5fbe50b0b84ad69a0d061b4307a3a0a6688", - "is_verified": false, - "line_number": 190 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c2672b9214bb9991530f943c1a5a0d05977c0f0a", - "is_verified": false, - "line_number": 191 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f3a8f4566cd7f256979933da8536f6dafb05d447", - "is_verified": false, - "line_number": 192 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e3b44891d5e5ec135f1e977ec5fd79c74ca11d9c", - "is_verified": false, - "line_number": 193 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8542da23c2d0a4b0bcab3939f096b31e3131d85f", - "is_verified": false, - "line_number": 194 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fb281df2d7a6793a43236092a3fcc1b038db56c9", - "is_verified": false, - "line_number": 195 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "727686c68fa10c5edecbf37cdfec2d44f3a5f669", - "is_verified": false, - "line_number": 196 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e7957179705dafeab8797bb8f90fcaf5ad0a61ee", - "is_verified": false, - "line_number": 197 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7424aea64d7c75511030d719e479517e8bef9d25", - "is_verified": false, - "line_number": 198 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3ad22266e9a3214addc49722b44d9559eb7cbedc", - "is_verified": false, - "line_number": 199 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8b00c700bf0f6c74820e1ad93d812f961989d69e", - "is_verified": false, - "line_number": 200 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2eef664e5193da7dde51adccd6d726a988701aaf", - "is_verified": false, - "line_number": 201 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9186e0986b4b7967aa03cfe311149d508d22e6aa", - "is_verified": false, - "line_number": 202 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1a639bb9895dc305d6db698183635c1f8b173c5c", - "is_verified": false, - "line_number": 203 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b5fbec5f1451e2d940c70945a01323eda82984bd", - "is_verified": false, - "line_number": 204 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ebb046a7ba8464ce615d215edb8b1fd82a1357b6", - "is_verified": false, - "line_number": 205 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "719e3976a5a00a7473cd38f81f712ca8c6e522e1", - "is_verified": false, - "line_number": 206 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "12cde4d54e7136273e8aa76d161b6f143469ef6d", - "is_verified": false, - "line_number": 207 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e04ec69eef9a4325231986801ebd42d3159ccca7", - "is_verified": false, - "line_number": 208 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "07c8e9accb3cfcc748b91d0369629fa1ee90576f", - "is_verified": false, - "line_number": 209 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3b00038548a6119fba962ca93f6bd24035d5571e", - "is_verified": false, - "line_number": 210 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2914f579938a910fb510898044063bec779e5ad5", - "is_verified": false, - "line_number": 211 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "868cf20bb88168a03fa29c7261762c97430ea0fc", - "is_verified": false, - "line_number": 212 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0475a43ad50f08c4a7012c4a87f15eeee3762ff9", - "is_verified": false, - "line_number": 213 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5ebe715bd56f0448d0374adae8568a6d86856442", - "is_verified": false, - "line_number": 214 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9c6dff479fd398382a289dc8f60cabf06fa60a26", - "is_verified": false, - "line_number": 215 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0102959abc9fee55edba97642bb1bcc546ce07dc", - "is_verified": false, - "line_number": 216 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "45459296596dbed9d7fbf7eab7a9645eb4fa107a", - "is_verified": false, - "line_number": 217 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5a5a491d064e789e785a8b080d38d9d1cc7d207f", - "is_verified": false, - "line_number": 218 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f3005c052e76c7e804c10403bdfcd9265a9de2ea", - "is_verified": false, - "line_number": 219 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "73aaaaf5bcab49cc1b1f47b45eae9b31db783a66", - "is_verified": false, - "line_number": 220 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "13aae30474af34fdede678dc5e8c00c075612707", - "is_verified": false, - "line_number": 221 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "336edbc017f4dadc0bf047e0f6d1889679fc3b48", - "is_verified": false, - "line_number": 222 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7bff3213c39d3873551698ec233998613e6b69dc", - "is_verified": false, - "line_number": 223 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9f1a6484627a58c233e1ec3f0aeffe4ff2d8a440", - "is_verified": false, - "line_number": 224 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d7c80e31311e912fb766bb2348b02785c28d878b", - "is_verified": false, - "line_number": 225 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2c75cc7344d810bb26cb768be82e843af623001a", - "is_verified": false, - "line_number": 226 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "607df6be12ab20f70a64076c372b178d6c10bc00", - "is_verified": false, - "line_number": 227 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9b7fed64d1f0682953011eb4702467dee8cd1174", - "is_verified": false, - "line_number": 228 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e982d9359554bc4a5c58d9d8d4387843e6e5cbb4", - "is_verified": false, - "line_number": 229 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c2f3985aed2da033a083cb330fb006239b2a1c8e", - "is_verified": false, - "line_number": 230 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "23d658cf19e1e76efbfa3498d2c2ed091c60b1f4", - "is_verified": false, - "line_number": 231 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a58be87cd80825e211c567b3c5397e122f702019", - "is_verified": false, - "line_number": 232 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f96f43b99c2f249a03a2e57e097c236561a1162c", - "is_verified": false, - "line_number": 233 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2fc8f0d1c9fadfb9cc384af21c8d3716c99a40f6", - "is_verified": false, - "line_number": 234 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f229dfc403d5b25f3362e73c4a7dc05233ecd4b6", - "is_verified": false, - "line_number": 235 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cf79e1dd8ff4c91b3346f5153780ba52438830be", - "is_verified": false, - "line_number": 236 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "20a1e643e857f0f63923b810289ab4b6c848252e", - "is_verified": false, - "line_number": 237 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9754246ca2c82802cc557d5958175d94ae5c760b", - "is_verified": false, - "line_number": 238 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ca0abe4a600e610c1bbbb25de89390251811ed1c", - "is_verified": false, - "line_number": 239 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b9c7402f138d31bea12092e7243ac7050a693146", - "is_verified": false, - "line_number": 240 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "07e9e0d4ea04d51535c0ec78454f32830dcfe8da", - "is_verified": false, - "line_number": 241 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9872435a00467574f08579e551e3900c65f2b36e", - "is_verified": false, - "line_number": 242 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "eec328050797cfffad3dc2dd6dd16d8ec33675f6", - "is_verified": false, - "line_number": 243 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b3b084478fcaec50b9f7e39dfef8bda422d48d91", - "is_verified": false, - "line_number": 244 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2093470fb2ffad170981ec4b030b0292929f3022", - "is_verified": false, - "line_number": 245 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b920a9ef2ec94e4e4edac20163e006425a391da4", - "is_verified": false, - "line_number": 246 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "06455554c00ce5845d49ebef199c0021b208d5df", - "is_verified": false, - "line_number": 247 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a077b13877b651822b80de2903f4b6acdbac3433", - "is_verified": false, - "line_number": 248 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "78fd658f1b01b01b25be00348caeced0e3ad0b29", - "is_verified": false, - "line_number": 249 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "79f7d6f792cc4e4ba79e3bf7cd3538fb65e4399a", - "is_verified": false, - "line_number": 250 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8280b950e62db218766e1087ec5771ec93de3b36", - "is_verified": false, - "line_number": 251 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "11fffafcae5d1e1aacf6f3c3a0235bbed17cacb2", - "is_verified": false, - "line_number": 252 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f0aebb371b0356a2e803f625a1274299544e0472", - "is_verified": false, - "line_number": 253 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bce9139737d07f1759822ac6e458eff6c06c1dae", - "is_verified": false, - "line_number": 254 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a61bed5d464a3dd53f1814dc44da919124e2c72b", - "is_verified": false, - "line_number": 255 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9c553b7e8c46273c6e1841f82032a11f697cafe1", - "is_verified": false, - "line_number": 256 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "24535adb56bd8d682e42561ded0eaab8a1a18475", - "is_verified": false, - "line_number": 257 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7f16429d5dba0340ae2ec02921abbe054ad4d9fd", - "is_verified": false, - "line_number": 258 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "61bac3ad8d011d3db96793f70a9fdaf5def37244", - "is_verified": false, - "line_number": 259 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "413654967fff8eae5dd1fece27756c957721d131", - "is_verified": false, - "line_number": 260 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c42fd06a8e9c5ad8b9b3624c1732347dd992f665", - "is_verified": false, - "line_number": 261 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "53fbf2125f17fd346dba810d394774c191c05241", - "is_verified": false, - "line_number": 262 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "312ebc5348c48d940a08737cc70b257c7ba67358", - "is_verified": false, - "line_number": 263 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3c072673c95b839b4c75a59ffcb4e7de11df227c", - "is_verified": false, - "line_number": 264 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "67dcac03bb680bd7400daff1125821df29119a57", - "is_verified": false, - "line_number": 265 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "74ceb07916759595af8144a74de06f4622295fab", - "is_verified": false, - "line_number": 266 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "becd47f7a933263c4029eb3298bdf67e64166b72", - "is_verified": false, - "line_number": 267 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "62cbb7af58e6841cb33ae8aa20b188904e88400b", - "is_verified": false, - "line_number": 268 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1240f6fbe789e15d2488a1f63a38913ace848063", - "is_verified": false, - "line_number": 269 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b313e2c9b9b7a229486000525bd2bfd909c739c3", - "is_verified": false, - "line_number": 270 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9ccd84180f08a811fc82fc6c2baa43b92b0c6d4c", - "is_verified": false, - "line_number": 271 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fec498a62202037efd0ff28ff270b1d65600ee21", - "is_verified": false, - "line_number": 272 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5e5991defd9bf4c9cd7ad44bfc3499b021f9b306", - "is_verified": false, - "line_number": 273 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3ac80ba9980be6af93aa361f71cc0b24ebb9a80d", - "is_verified": false, - "line_number": 274 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3e58a970f8a2580b7929b87623a05bcfd18ff5d0", - "is_verified": false, - "line_number": 275 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4e95912a938c4a5d793d6147f17b1a4f4564f521", - "is_verified": false, - "line_number": 276 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b9c19621f11904336bb1c83271b6e66392139adf", - "is_verified": false, - "line_number": 277 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ea26c6b69a1fbd9d19136131f1a4904190cdc910", - "is_verified": false, - "line_number": 278 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "88806d10d6a88e386d7bffe5ed9d13a01aa30188", - "is_verified": false, - "line_number": 279 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "92c4052a065855d439918461deb8ab1d85b8dec4", - "is_verified": false, - "line_number": 280 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5a801127b30267b3143bcd1879b09ce966f4e4db", - "is_verified": false, - "line_number": 281 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "03c0a54929a02a84158ffbab6a79ba8a31bbea5e", - "is_verified": false, - "line_number": 282 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9adc71007b98c2f47eb094b8c771d0a2c81e8584", - "is_verified": false, - "line_number": 283 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "19cc3f05c05fc6ff92f9a56656d3903fb6e05af1", - "is_verified": false, - "line_number": 284 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "901c70145ec0a76f9705743bc180ac505301db81", - "is_verified": false, - "line_number": 285 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e264698710238eada7824909e03b11a1d5b94d01", - "is_verified": false, - "line_number": 286 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e74cd3a559f33f9541ef286068dee5338b7c2f5d", - "is_verified": false, - "line_number": 287 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a0b7170416566ab964d395d0cf138ecd3c65fe2c", - "is_verified": false, - "line_number": 288 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c9c183b3a85dec6b215a6a18a1f0ce82381c12a6", - "is_verified": false, - "line_number": 289 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "06b739bfeff8deb1f44a03424e08ab08f1280851", - "is_verified": false, - "line_number": 290 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "25dc7c4a6b8bfdcb8bc41e815d05dac7fa905711", - "is_verified": false, - "line_number": 291 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1b298510f55fd15ee6110b2a9250263dbc9f4fc9", - "is_verified": false, - "line_number": 292 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6403b53b45d57554b17c4388178cd5250aa7587a", - "is_verified": false, - "line_number": 293 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f944cf9178e33e14fddf0ac6149cbb69e993d05c", - "is_verified": false, - "line_number": 294 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "61b4fee247e19961be2d760ed745da4e39d8bf4e", - "is_verified": false, - "line_number": 295 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d25d1f3178dd3a9485d590ce68bd38b3029d0806", - "is_verified": false, - "line_number": 296 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9fdfeae6046b80e2ae85322799cdc6da4842f991", - "is_verified": false, - "line_number": 297 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f7143b0c85044b4b76ef20cd58177815daf7407e", - "is_verified": false, - "line_number": 298 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5e605f0950f7c24e192224fa469889b9c83c80ac", - "is_verified": false, - "line_number": 299 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "329c29edf1fb8e3427b1d79a30e77a700c01ff5c", - "is_verified": false, - "line_number": 300 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "74a03233311d2f477a3dd7ffa81c7343586b1f8e", - "is_verified": false, - "line_number": 301 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3b1df47dbd920bfaf1de8a7b957d21d552d78a76", - "is_verified": false, - "line_number": 302 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "929a23cdbe2b28de6dac28454d1e7478a4a14fea", - "is_verified": false, - "line_number": 303 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a6436a4a36cd90e5d03b33f562213dfc3d038455", - "is_verified": false, - "line_number": 304 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a010833ccd24af9e70339bac73664fb47b6ac727", - "is_verified": false, - "line_number": 305 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "53be5a9c1c894e77c4fcdfbbb3b003405252ed79", - "is_verified": false, - "line_number": 306 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "61b289fe5c2eb0d8b8bc5b1cc5e9855472daabd9", - "is_verified": false, - "line_number": 307 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "773307c58ca81fd42a4734bbc4b3c7eb8bcfd774", - "is_verified": false, - "line_number": 308 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "35f607d2769173d1672e30f60b9276d01b8250d7", - "is_verified": false, - "line_number": 309 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e602d5d9691c09f57a628600014aaae749d38489", - "is_verified": false, - "line_number": 310 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "625238f7e6c9febfca3878a385daa7b8646a2439", - "is_verified": false, - "line_number": 311 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e6ba52cd1f2f9a30963834fd94aafc869bf05b82", - "is_verified": false, - "line_number": 312 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d629b569233f71690b6e6eaed9001e44b88c50bf", - "is_verified": false, - "line_number": 313 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a001d4059055a1c86b9ec62774d044b54ddb3376", - "is_verified": false, - "line_number": 314 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bce06d4b0177a2d06399e21e0b26bc99e44d6e9b", - "is_verified": false, - "line_number": 315 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cb6af31518d65e6dcb92fb01b9f31556c3a70c5e", - "is_verified": false, - "line_number": 316 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c2a95352f382fdbe53bd8b729a718c38eacfbf73", - "is_verified": false, - "line_number": 317 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f9b16dccab1e453362789df2fc682f2ba2c9ee2a", - "is_verified": false, - "line_number": 318 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1bb4e4fd05b7c33cfab0dad062c54a16278d3423", - "is_verified": false, - "line_number": 319 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9dcc6dc6f20a71fd6880951ceb63262d34de8334", - "is_verified": false, - "line_number": 320 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "666382b579258537d6cf5e7094dbaa0684b78707", - "is_verified": false, - "line_number": 321 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "072c49f046dfdce12c1553a67756e2f5ee4d7e49", - "is_verified": false, - "line_number": 322 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "47b792bdebbbf305d87092f12c0afcd8810e054d", - "is_verified": false, - "line_number": 323 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "41d3b22a387fa43c1491d62310faf50c4ab7956a", - "is_verified": false, - "line_number": 324 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bcdc3859e08c518f75cfe65b69f3adb9f489400b", - "is_verified": false, - "line_number": 325 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fc2b22e2d43816acf209af822877aff7e82fa4d0", - "is_verified": false, - "line_number": 326 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f63542bc2eb9de2caa3bfaeafd53d7bf65485889", - "is_verified": false, - "line_number": 327 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7ab01f0f438a3d21b529df89fbde67234aa49d89", - "is_verified": false, - "line_number": 328 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fed608fe9221f0e45c84b68a80a0c065a9a2b7f1", - "is_verified": false, - "line_number": 329 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7a6394c70b925009c3e708ec195a17ee40cae8f4", - "is_verified": false, - "line_number": 330 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5d615bd2adf567fe7403c51814ff76c694b1c8d3", - "is_verified": false, - "line_number": 331 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "77f3c695d15ee63db41dabcecce126a246b266e6", - "is_verified": false, - "line_number": 332 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "78138e46003e12617c75a8011fddbe2868ff5650", - "is_verified": false, - "line_number": 333 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "89c905852505ac6168e4132b5ee29241a64b2654", - "is_verified": false, - "line_number": 334 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3d55f361c5d2bf2c1ec7d2c2551d7bec67b3cc35", - "is_verified": false, - "line_number": 335 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "89f1aec19abc18d22541dc01270e0fee325a878b", - "is_verified": false, - "line_number": 336 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "23ed3413498b5fe9fe2d6d3ae4040a0e2571c9df", - "is_verified": false, - "line_number": 337 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e7f990c94d57f6880b1e2cf856ab0646636bc46a", - "is_verified": false, - "line_number": 338 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "87dccf8b7123c723b5c35c45533d7471a19c9c22", - "is_verified": false, - "line_number": 339 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "14a222dcf6b592c1178fae0babbb73d809102462", - "is_verified": false, - "line_number": 340 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "161b87029fb1fe5f37573770659140c254b6f26d", - "is_verified": false, - "line_number": 341 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e01ccf01c8ae560637e1fba1396ec9d27a48943e", - "is_verified": false, - "line_number": 342 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0d45bd0e0858d416488ca24b5e277430fdbc29a2", - "is_verified": false, - "line_number": 343 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bd6b3d87fee3f95d7bbe77782404507c7d6d23ba", - "is_verified": false, - "line_number": 344 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "297eface47da40362e6c34af977185a96ecd4503", - "is_verified": false, - "line_number": 345 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1d908d54bd47e7b762cf149a00428daf8ab41535", - "is_verified": false, - "line_number": 346 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e0404cb2e3feaba3e7bdc52c798b9bce57f546d3", - "is_verified": false, - "line_number": 347 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8dc5b0bbc5b3c3f93405daac036e950013ae6e83", - "is_verified": false, - "line_number": 348 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c914f94ead99fe6e6b262f63f419aba9f1f65cc9", - "is_verified": false, - "line_number": 349 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5d2559e8fbde4bdf604babb1a00a92f547e9c305", - "is_verified": false, - "line_number": 350 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b28706495d2c7f4e44a064279570ec409025bce8", - "is_verified": false, - "line_number": 351 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ce77aa4f51f5ee1a1f56ba0999a3873e07bdec29", - "is_verified": false, - "line_number": 352 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c828435ec3655b9b44974c212f94811121d3183c", - "is_verified": false, - "line_number": 353 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0361b85a6a04d362a8704e834cd633a76d7c8531", - "is_verified": false, - "line_number": 354 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e8b43fe4aa4ece98317775e13e359f784187c9ea", - "is_verified": false, - "line_number": 355 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ec00a6364212bbc187bc15f3a22ec56eb7d5d201", - "is_verified": false, - "line_number": 356 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5599c260b57d92c0f8bd7613fa1233ad9f599db3", - "is_verified": false, - "line_number": 357 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d11065d4dd0b6fd8e29dd99b53bfbe17e1447ab3", - "is_verified": false, - "line_number": 358 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c8c47349a7991ac9cb1df02c20e18dde2ec48b9c", - "is_verified": false, - "line_number": 359 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e5302dc80bfbd04a37e52099a936c74b38d022ec", - "is_verified": false, - "line_number": 360 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4a4e17621d292bddf3604bcc712ed17fdd28aca2", - "is_verified": false, - "line_number": 361 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a43a1929d714363194cc42b3477dfe9b4c679036", - "is_verified": false, - "line_number": 362 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "645e56a2836118de395a78586b710ac24c6d1b9d", - "is_verified": false, - "line_number": 363 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c0f20d875c6d2d8e99539de46a245a5a30e757d0", - "is_verified": false, - "line_number": 364 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fb552bf2f6ea4da1a8d0203ac4c6b4ecb1bbea56", - "is_verified": false, - "line_number": 365 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "53c6b8e08eeb37812e6e40071ac16916c372b60f", - "is_verified": false, - "line_number": 366 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c64cf6bc4ec02fa8b2bf2f5de1c04f0a0c8ec77d", - "is_verified": false, - "line_number": 367 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e7dc30b59854ec80d81edc89378c880df83697c4", - "is_verified": false, - "line_number": 368 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e60404864ae5ddda3612f7ece72537ab2a97abf7", - "is_verified": false, - "line_number": 369 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a84bea5c674feff72b4542a20373b69d25a47b89", - "is_verified": false, - "line_number": 370 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "47cbc18c75b60b6e0ed4d8b6a56b705a918e814b", - "is_verified": false, - "line_number": 371 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cd8bc0fe19677ebb0187995618c3fa78d994bbb2", - "is_verified": false, - "line_number": 372 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "887786ac035ae25cc86bd2205542f8a1936e04d2", - "is_verified": false, - "line_number": 373 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3ef2e1c199d211d5f1805b7116cb0314d7180a5c", - "is_verified": false, - "line_number": 374 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f89746f236eab3882d16c8ff8668ed874692cde3", - "is_verified": false, - "line_number": 375 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2b3db4dc1799edfee973978b339357881c73d3ab", - "is_verified": false, - "line_number": 376 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b7254fda5baf4f83d6081229d10c2734763d58b4", - "is_verified": false, - "line_number": 377 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9af3e435c37c257b5e652e38a2dfd776ab01726e", - "is_verified": false, - "line_number": 378 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "833be77b754d40e1f889b7eda5c192ae9e3a63fe", - "is_verified": false, - "line_number": 379 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a153d9446771953d3e571c86725da1572899c284", - "is_verified": false, - "line_number": 380 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "68d2128a64a2b421d62bc4a5afeeb20649efe317", - "is_verified": false, - "line_number": 381 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "92490f06bfafdb12118f5494f08821c771abafff", - "is_verified": false, - "line_number": 382 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "84a479485dd167e8dc97cce221767e68cbe14793", - "is_verified": false, - "line_number": 383 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ca9c140d7b9b6dbf874d9124b3de861939eb834e", - "is_verified": false, - "line_number": 384 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d293b3b1e9c7e4b8adde8f2a8d68159c72582f71", - "is_verified": false, - "line_number": 385 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "120db881813bc074d8abb7a52909f1ffc4acf08b", - "is_verified": false, - "line_number": 386 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6be68465c1bce11d46731c083c86cc39b4ca4b26", - "is_verified": false, - "line_number": 387 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ec613f94f9c8e0a7c9a412e1405a0d1862888d44", - "is_verified": false, - "line_number": 388 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "53300289cf9589a5e08bfa702e1f3a09d2d088b1", - "is_verified": false, - "line_number": 389 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "aac8dac3f68993b049bcc04acbb83ee491921fa8", - "is_verified": false, - "line_number": 390 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b309b1a5cda603c764ed884401105a00c1a1b760", - "is_verified": false, - "line_number": 391 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c1d9acf0ca3757e6861a2c8eab08f6bf39f8f1a3", - "is_verified": false, - "line_number": 392 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "39860c432a27f5bcbcd30b58cdd4b2f8e6daf65f", - "is_verified": false, - "line_number": 393 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f28f8289110a85b1b99cd2089e9dfa14901a6bbe", - "is_verified": false, - "line_number": 394 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7c51dd968d2ae5ffad1bc290812c0d6d3f79b28a", - "is_verified": false, - "line_number": 395 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "19e03888ea02a1788b3e7aacdb982a5f29c67816", - "is_verified": false, - "line_number": 396 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "936e0dfc9fa79e90eabe1640e4808232112d6def", - "is_verified": false, - "line_number": 397 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "66b03fc6f79763108c0e0ebced61830ce609d769", - "is_verified": false, - "line_number": 398 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b4615dacf79e97a732e205acd45e29c655a422cb", - "is_verified": false, - "line_number": 399 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4e9cab1ac24cee599dc609b69273255207fb9703", - "is_verified": false, - "line_number": 400 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7c2d628057af1a5f9cdc10e1a94d61fa2f43671c", - "is_verified": false, - "line_number": 401 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1f76628414c76162638c6cdd002f50d35c0030df", - "is_verified": false, - "line_number": 402 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "656cd81676438907b67dc35f1dcbc7f65fb44eae", - "is_verified": false, - "line_number": 403 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2b7c94fe6035b5e6d98a65122fd66d9fbc0710f6", - "is_verified": false, - "line_number": 404 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d55f6f2d0aff7554ed2c85a4f534c421ba83601a", - "is_verified": false, - "line_number": 405 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "742a9e62c813d9b6326e2540f1f9f97dfca8542c", - "is_verified": false, - "line_number": 406 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8b446fd2f0b22dc0fdfee36b5b370643b669bd2d", - "is_verified": false, - "line_number": 407 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ce38475ba93df187a8dd9972a02437ffef9e849c", - "is_verified": false, - "line_number": 408 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e5581573b5114490af9bdc16bad95dca6177f4ba", - "is_verified": false, - "line_number": 409 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2f005879125b38683f71c8a64bd232cd11591e08", - "is_verified": false, - "line_number": 410 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7e1581a6326b6fb0d8f18d69631ee8ee2a2b3d50", - "is_verified": false, - "line_number": 411 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e5814a47cd07ed2435b048b8b97f41be6cd2c9eb", - "is_verified": false, - "line_number": 412 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "72a7b76523b4eda36ffdd63ac1bcd4f52063e387", - "is_verified": false, - "line_number": 413 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3d2aeb7f6499d336ff54871823348b2bf58e7c89", - "is_verified": false, - "line_number": 414 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ca1473b861759dfa5fb912c2a7c49316897cafa5", - "is_verified": false, - "line_number": 415 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5bc665714e4b5b73c47d7e066567db6fde6ff539", - "is_verified": false, - "line_number": 416 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8f2f91164826d44904bc522f6680822bfd758342", - "is_verified": false, - "line_number": 417 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c9c956b3f172ca5ed76808abd98502a3499268f1", - "is_verified": false, - "line_number": 418 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b0c287a3b80addbf5fe7eb56f10dd251368ba491", - "is_verified": false, - "line_number": 419 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5da8ed9d858656f49131055a4b632defccffd4dd", - "is_verified": false, - "line_number": 420 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "23dd6031c249baabd4b92e8596f896bbc407eb7e", - "is_verified": false, - "line_number": 421 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c58b01cfd3befe531fdad283418fa7ac558cea5f", - "is_verified": false, - "line_number": 422 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "32a9671da53c8e3572ffd9303171adf6ae95a919", - "is_verified": false, - "line_number": 423 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "60789728174b9ee630b33b2af057e0c6a0180947", - "is_verified": false, - "line_number": 424 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "073252599d795b92b38cbad3ed849f1c5fd5368b", - "is_verified": false, - "line_number": 425 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "761bcb628d3c585abebaa8a64b04ab193f5a559e", - "is_verified": false, - "line_number": 426 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "dd230524f2606a207b426444142d01d518781aef", - "is_verified": false, - "line_number": 427 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3b459c62a8c9fe3401808103493996348ef70870", - "is_verified": false, - "line_number": 428 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "70dbcfd2a8a038e265a0d3d6379284b679226101", - "is_verified": false, - "line_number": 429 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "29398aafd66a1c4f181e540ec90a2b76dcdfe2cc", - "is_verified": false, - "line_number": 430 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4698c1c5c6daf3f88ec2768de0693d543e81c8b5", - "is_verified": false, - "line_number": 431 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cd333285b1ef33582b502f72b4a153a16a4678a9", - "is_verified": false, - "line_number": 432 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b2c2475773928e727fd3ba3969aaae40ab2b99b2", - "is_verified": false, - "line_number": 433 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c28676c2076efac73f3d01195ed463c6d7a6f442", - "is_verified": false, - "line_number": 434 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c520370cf0e7b1bcc405af46775963a7df856b9d", - "is_verified": false, - "line_number": 435 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fcd376b4fd7ecf2299b1ad018e66732a5e74ee08", - "is_verified": false, - "line_number": 436 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f9a69a2290885d929addfd83a6c1570dc7c76646", - "is_verified": false, - "line_number": 437 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5fdb5ce747a93d7048f4fd3a428653520b3efb50", - "is_verified": false, - "line_number": 438 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4ca9129303ac0d5e4e1b810e7abf90ea11a16833", - "is_verified": false, - "line_number": 439 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f83fb00877111e23db5ceb8b74255963d17c84e9", - "is_verified": false, - "line_number": 440 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "17e35c47564c0e6fefa2946f24d71618053bcfb7", - "is_verified": false, - "line_number": 441 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fab7d05454c71ae59bade022116124571421e4c4", - "is_verified": false, - "line_number": 442 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7820b9feb8912aee44c524eedf37df78b8d90200", - "is_verified": false, - "line_number": 443 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ea2a0f7323961fd704b1bad39ae54e02c9345d2a", - "is_verified": false, - "line_number": 444 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "353fcf93df94d7081d2bd21eab903cf8e492f614", - "is_verified": false, - "line_number": 445 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7149d4db2de10af66a4390042173958d5fa1cbde", - "is_verified": false, - "line_number": 446 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "85b4428454e38494e03e227d224ae58a586ab768", - "is_verified": false, - "line_number": 447 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "df83530e6fb8ccd7f380c5dc82bc8c314b82436a", - "is_verified": false, - "line_number": 448 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "106157744da44adeb38c39220b1db267c26deb77", - "is_verified": false, - "line_number": 449 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c5e67d1eed731314ac68f5e67cb7b7dba68225f5", - "is_verified": false, - "line_number": 450 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d9737cec69cbdedea1a2d9a70d7961ff76592696", - "is_verified": false, - "line_number": 451 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7aab6c9118166720f0f0e3a9db46fd59e3ed647d", - "is_verified": false, - "line_number": 452 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "500a58b74d63b4c10c8c098743d63e51a477c9cd", - "is_verified": false, - "line_number": 453 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "69a150ffbef689cc7a14cfc019e9c808b19afd4a", - "is_verified": false, - "line_number": 454 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "49d3801a82b82e48cbcc596af60be9d4b72bbd76", - "is_verified": false, - "line_number": 455 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5f3e17df79af2812cc6b5dbc211224595f8299a8", - "is_verified": false, - "line_number": 456 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5f21f46cef784459cbac4d4dc83015d760f37bcf", - "is_verified": false, - "line_number": 457 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4a91f36506d85a30ddc1a32f9ed41545eeb1320f", - "is_verified": false, - "line_number": 458 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b99666bc5cc4bf48a44f4f7265633ebc8af6d4b7", - "is_verified": false, - "line_number": 459 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c061353e73ac0a46b366b0de2325b728e3d75c5b", - "is_verified": false, - "line_number": 460 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d17d588edde018a01f319f5f235e2d3bcbbe8879", - "is_verified": false, - "line_number": 461 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "63567656706221b839b2545375a8ba06cd8d99ae", - "is_verified": false, - "line_number": 462 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "976e5ce3af12f576a37ce83ccf034fd223616033", - "is_verified": false, - "line_number": 463 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "626b3f10041c9e9a173ca99252424b49e3377345", - "is_verified": false, - "line_number": 464 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f8ba93d3a155b11bb1f2ef51b2e3c48c2723ef8e", - "is_verified": false, - "line_number": 465 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8b4879aed0c0368438de972c19849b7835adb762", - "is_verified": false, - "line_number": 466 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d35dbaf2ea5ec4fc587bed878582bba8599f31c0", - "is_verified": false, - "line_number": 467 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c09d7037f9b01473f6d2980d71c2f9a1a666411c", - "is_verified": false, - "line_number": 468 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d53d7f86659a0602cd1eb8068a5ad80a85e16234", - "is_verified": false, - "line_number": 469 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "aa9442f71f2747b5bb2a190454e511a7c62263d8", - "is_verified": false, - "line_number": 470 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f800b1fed08ed55a8e2a9223fc3939c96f3e11e5", - "is_verified": false, - "line_number": 471 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e46a4855198ba0f803471fb44a70ae5fbd2dd58f", - "is_verified": false, - "line_number": 472 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f47b48b6b7c2847fbe206253667d1eda00880758", - "is_verified": false, - "line_number": 473 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a9d98ab785981fe0f13a721e7fe2094a6e644b5d", - "is_verified": false, - "line_number": 474 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fe151aabb001edb57e3fed654d3a96e00bc58c81", - "is_verified": false, - "line_number": 475 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "77c40b5a173e170886069d57178c0074dfe71514", - "is_verified": false, - "line_number": 476 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "04e04736dcf54eb8a8ef78638b0b0412cab69e96", - "is_verified": false, - "line_number": 477 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b13a34e3be842da54436ed8ab8f2a9758b2cc38e", - "is_verified": false, - "line_number": 478 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3971f1dcb845e4eaedcb04a6505fd69e27b60982", - "is_verified": false, - "line_number": 479 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1b8ae7b1c309866e28fe66e07927675ce0e24514", - "is_verified": false, - "line_number": 480 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4c3f6543b234d2db27b1a347b3768028dd60bc77", - "is_verified": false, - "line_number": 481 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ca4ac68931f7c54308050c1b6ac9657c4ff0d399", - "is_verified": false, - "line_number": 482 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "02cca5fc17dc903feb5088abec3d2262f604402e", - "is_verified": false, - "line_number": 483 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d864c37f23cab8cff54e9977a41676319c040928", - "is_verified": false, - "line_number": 484 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e67a5309737b99b0ac9ba746ca33d6682975cea1", - "is_verified": false, - "line_number": 485 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "aef65112b27cc0ecbcfbd3ae95847e9e0fbee0b7", - "is_verified": false, - "line_number": 486 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "40d73861d177d9e22d977dd62b8a111bbf8ee0b7", - "is_verified": false, - "line_number": 487 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "71e44d4a353467958cd9be3a7e6942385e883568", - "is_verified": false, - "line_number": 488 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e1f00f9205b689ba1d025f88e948f03a4ac77a59", - "is_verified": false, - "line_number": 489 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6a9f1470e772a7f4176e8c24b7ab0e307847b92b", - "is_verified": false, - "line_number": 490 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5959a3a8554f9ce7987b60e5e915b9e357af0d99", - "is_verified": false, - "line_number": 491 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b0a791edf8675bd6a65fc9de9ba5bcb8336d1fc0", - "is_verified": false, - "line_number": 492 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "557bcf89f60a98f72b336e21f56521a4c30a2f0c", - "is_verified": false, - "line_number": 493 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "80e8a78fd29c2ac00817f37e03d9208f8fd59441", - "is_verified": false, - "line_number": 494 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "351dded8c590b80cc8dc498021fccadc972c1d00", - "is_verified": false, - "line_number": 495 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4f55ad2c0e5a697defde047e6a388c14b3423cda", - "is_verified": false, - "line_number": 496 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "20412c530d4b4c38510d9924cbfb259126c2568c", - "is_verified": false, - "line_number": 497 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "05e66772d14918a72d1b6f45872428a35c424347", - "is_verified": false, - "line_number": 498 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c61a40f7ae13f5e26ea16a6266491d58e78f6f1f", - "is_verified": false, - "line_number": 499 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b4d93dd6c2e36056d55ce3844610991eec962277", - "is_verified": false, - "line_number": 500 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c7088e4ff6e5a3bc44ca3fdf1b06847711f3e95c", - "is_verified": false, - "line_number": 501 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5e5168774b473fb9fcc31c8f5c1518eb0f9771c1", - "is_verified": false, - "line_number": 502 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a1f86c50a6626bcab082286bec7f5474e7c8b293", - "is_verified": false, - "line_number": 503 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a9fac6e3490672c5dccd35d5e6fc1cb7b1b5931b", - "is_verified": false, - "line_number": 504 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b48c69b346d712e3df1728014956ac0397c659ea", - "is_verified": false, - "line_number": 505 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8367e351d57fa775f22fc1132dd170c458799542", - "is_verified": false, - "line_number": 506 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "972953c33baa3303c488360576bdd3bae95e79a3", - "is_verified": false, - "line_number": 507 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2ef2d21dde1d6ef435fbf1b6a049f7e94a2d5588", - "is_verified": false, - "line_number": 508 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "76bf193e8f7b54ab5f0007ee41b768ee1e3ce24d", - "is_verified": false, - "line_number": 509 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e8e93efe226e4bf62b880c14bdef1507dc67c4fe", - "is_verified": false, - "line_number": 510 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "71cd9e3eb02ec34d305a55df09540b95549f8342", - "is_verified": false, - "line_number": 511 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "34c2c4351cc369f306886089967adc3fd23202b5", - "is_verified": false, - "line_number": 512 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "95a9e6645670ef390609e97a9a94ab1af8ecb5e5", - "is_verified": false, - "line_number": 513 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7a773ead4f5cbee039dd9c90bcbd2157ff9dfe98", - "is_verified": false, - "line_number": 514 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c8974d5459c5318a865674227914120b61ee7ca8", - "is_verified": false, - "line_number": 515 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9aa53dd7b54460ca4058dc1b993c61c85016c3a5", - "is_verified": false, - "line_number": 516 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5cf42e6632ac13c10b1709348bda0d36d4cc8fe2", - "is_verified": false, - "line_number": 517 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "22368f64933f9d4b20751ed12db25bdb937f4288", - "is_verified": false, - "line_number": 518 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "558145b7f5778e24056c8de59bd9d54190950f14", - "is_verified": false, - "line_number": 519 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2068d5b68ddc59653056d96e1283951282b22267", - "is_verified": false, - "line_number": 520 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4d807498a9a96f89bb538a8308d6056a2a303a0d", - "is_verified": false, - "line_number": 521 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3457741ed34d5ad7b9d04fa9cc677a72e8c47b4d", - "is_verified": false, - "line_number": 522 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "59556e4aa33301c95feb9c58d99d10a080179646", - "is_verified": false, - "line_number": 523 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2d49954101a3bd1dd5da50b8a1847f00bf4ec16b", - "is_verified": false, - "line_number": 524 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c2f14cff186baad8445fb7997c3dc863eff10ef6", - "is_verified": false, - "line_number": 525 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "dd317a7973e49de529850041e8c1ce51b0d378df", - "is_verified": false, - "line_number": 526 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9cbaaf4ff0453e81aaac598e05d8c973991c77b3", - "is_verified": false, - "line_number": 527 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "576dd6a98701c267f16a5e568f8b6a748665713d", - "is_verified": false, - "line_number": 528 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c5ce7f45e2ddbd43d244e473e165b1400ba86dd9", - "is_verified": false, - "line_number": 529 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "04a10a70b498263467ef1968fabfb90e012fd101", - "is_verified": false, - "line_number": 530 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "482928d9b3b49339bc5f96e54f970e98f84970b7", - "is_verified": false, - "line_number": 531 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "24d25f3a906f38241bd1d3dfa750631cd4b2f91f", - "is_verified": false, - "line_number": 532 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8cc46e3c020e63d10457e32b2e5d28b5c7ce0960", - "is_verified": false, - "line_number": 533 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "da272306205373082db86bc6bc2577ab85ed9e31", - "is_verified": false, - "line_number": 534 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b03284305e4d5012e7c3cf243b2942a6dab309cc", - "is_verified": false, - "line_number": 535 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f7c91578b688a0054f2c1e18082541d6ecc6b865", - "is_verified": false, - "line_number": 536 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1f009c80b8504a856a276e8d2c66210b59e8bf2e", - "is_verified": false, - "line_number": 537 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "54490e77b2c296149b58ae26c414fea75c6b34ec", - "is_verified": false, - "line_number": 538 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d5bd68de7769dde988f99eab3781025297a7212d", - "is_verified": false, - "line_number": 539 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b6161808b7485264957a2f88c822f0929047f39a", - "is_verified": false, - "line_number": 540 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1ff88fb1bf83bca472ab129466e257c9cc412821", - "is_verified": false, - "line_number": 541 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "002e1405d3a8ea0f2241832ea5480b0bf374c4c6", - "is_verified": false, - "line_number": 542 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1058c455a959a189a2d87806d15edeff48e32077", - "is_verified": false, - "line_number": 543 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cbcf1915e42c132c29771ceea1ba465602f4907c", - "is_verified": false, - "line_number": 544 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "23738e07a26a79ab81f4d2f72dc46d89f411e234", - "is_verified": false, - "line_number": 545 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "270492f5701f4895695b3491000112ddc2c1427d", - "is_verified": false, - "line_number": 546 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "88aec41eb1eedc51148e0e36361361a6d2ecc84f", - "is_verified": false, - "line_number": 547 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7b7d73969b405098122cd3d32d75689cd37ee505", - "is_verified": false, - "line_number": 548 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "79b731de4a4426370b701ad4274d52a3dc1fc6c1", - "is_verified": false, - "line_number": 549 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5b328e2a87876ae0b6b37b90ef8637e04822a81b", - "is_verified": false, - "line_number": 550 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8638f4b78c1059177cbfccd236d764224c3cad5c", - "is_verified": false, - "line_number": 551 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ef285f61357b53010f004c1d4435b6bb9eeaff09", - "is_verified": false, - "line_number": 552 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ddd64557778a6d44ac631e92ed64691335cf80df", - "is_verified": false, - "line_number": 553 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "de486a7abd16c23dfdf2da477534329520c0c5ec", - "is_verified": false, - "line_number": 554 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0618c0886736acb309b0ad209de20783b224caa6", - "is_verified": false, - "line_number": 555 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "521ee58b56f589a8f3b116e6ef2e0d31efd4da1d", - "is_verified": false, - "line_number": 556 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5b916ff5502800f5113b33ba3a8d88671346e3b3", - "is_verified": false, - "line_number": 557 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7582e85dc9e4a416aa1e2a4ce9e38854f02e8a56", - "is_verified": false, - "line_number": 558 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b24c1e8ac697a8ff152decc54d028e08dd482e4f", - "is_verified": false, - "line_number": 559 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "923eb19912270d9a7c2614d35594711272bc33c0", - "is_verified": false, - "line_number": 560 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e0331901bcbebd698248f7ba932083b13144da42", - "is_verified": false, - "line_number": 561 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f49cc7570d7e3331425d2c1cca13e437c6eb0c86", - "is_verified": false, - "line_number": 562 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6adbf5db8ff386502f09c1dbb9fa2b37600491a6", - "is_verified": false, - "line_number": 563 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "03060c922cbe09ed17fe632cbf93ed32eb018577", - "is_verified": false, - "line_number": 564 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "71cfee01fe9f254c01da3a00f2b752cf39cbe95d", - "is_verified": false, - "line_number": 565 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "542ef00d5b90d5b9935d54e3c2ebd84c59b7e7ba", - "is_verified": false, - "line_number": 566 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4073dc551871d96e2b647f18924989272ea88177", - "is_verified": false, - "line_number": 567 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0a4afe0870fdff9777720cab41c253d7a2a1b318", - "is_verified": false, - "line_number": 568 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ef7992a75c33f682c8382997f7f93d370996ee7d", - "is_verified": false, - "line_number": 569 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a265ebf662a7b28aeacc7f61bdb9ba819782fc24", - "is_verified": false, - "line_number": 570 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2bc27f59373f1a1091eef59a7d9d23c720506614", - "is_verified": false, - "line_number": 571 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e17be476c0805f05b4445d528ae5b03fa7a13366", - "is_verified": false, - "line_number": 572 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6b8281ade6ee972b53eb2e5e173068a482250005", - "is_verified": false, - "line_number": 573 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "931c912c0da827ad7895c4e6d901dc2924ef23e4", - "is_verified": false, - "line_number": 574 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ecf0566d6b6ce6c44f7f8fb56af4a8608e72f5e4", - "is_verified": false, - "line_number": 575 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "947323679dbee5d60736f14258621626565ea1c6", - "is_verified": false, - "line_number": 576 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "05d0d9d4a4e53fa7d7f3f7f8317bec618b1bfe15", - "is_verified": false, - "line_number": 577 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6b7871d101c02971f1b9f6f95f5a969c36a8483c", - "is_verified": false, - "line_number": 578 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "05441b75c971d39d04a13b168a1b0f2c4aeb2114", - "is_verified": false, - "line_number": 579 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c9d8088c151b2a7c09676ed3fd9de0fddc490b30", - "is_verified": false, - "line_number": 580 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "07eb4a0a546de02a324550e1e1b66e306bd3f706", - "is_verified": false, - "line_number": 581 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "baa791026849604561c1dd00787a9caa598abae1", - "is_verified": false, - "line_number": 582 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8d49f6f1c3e27bdfe580816e609cab2c9ca00cc6", - "is_verified": false, - "line_number": 583 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "926d8707e359f80554585f4eca9f90b6021d3327", - "is_verified": false, - "line_number": 584 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "68982f7b9ff005fdd9d27fdf5ef5d37c9c611f58", - "is_verified": false, - "line_number": 585 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cc95ebd65aeae6dd8e774a1e90798079211554f3", - "is_verified": false, - "line_number": 586 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a76b151ddad3198ad11b962ff59170a761baf0c6", - "is_verified": false, - "line_number": 587 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8a59e160326a76b11b5fc26cfa592cfdf158fd49", - "is_verified": false, - "line_number": 588 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "784d839853e3c0966a262a542b36e259aa00e8df", - "is_verified": false, - "line_number": 589 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fbba9f2d7a916915d9535d71c785ba4491a3b733", - "is_verified": false, - "line_number": 590 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f290b3c4f8aacf898285d68358fcdffe6baf1e2e", - "is_verified": false, - "line_number": 591 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "14f10baeacada2cc41047108f58b200c6026bca3", - "is_verified": false, - "line_number": 592 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e583513a87e1f5b242e81fe86427da78faa63ede", - "is_verified": false, - "line_number": 593 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "391f7646f98c7bf123453c90b372ac45f4ea35fc", - "is_verified": false, - "line_number": 594 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "da2e4b9e552f03c36dcf672072f1d6cda917672d", - "is_verified": false, - "line_number": 595 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9c4a1dc6277cda2374666e447dceb663ac39c62a", - "is_verified": false, - "line_number": 596 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "469b9dfc4d3851edbd0c27f80b4b36c04ec52f5e", - "is_verified": false, - "line_number": 597 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c09b72b36f9e813bdfcf32f58e070a4fe98f4092", - "is_verified": false, - "line_number": 598 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6ee9dd6fd0333921cb607f274d3bfc04187bfac5", - "is_verified": false, - "line_number": 599 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9ccd2b0b5ae426a9c581621270630389e40d08e0", - "is_verified": false, - "line_number": 600 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "881f2e047f571e1ea937638ea2598581e92e4900", - "is_verified": false, - "line_number": 601 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1e5acdb5b4e970fd7be282ae31e3195d24aa98b9", - "is_verified": false, - "line_number": 602 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8b1564bd262285220c1f4cc7ba034b14836d3496", - "is_verified": false, - "line_number": 603 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2f79127d99b576c55a920ce8195d9c871296dd79", - "is_verified": false, - "line_number": 604 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0aa38b942875102db24b7ce22856fbce4dd8bca5", - "is_verified": false, - "line_number": 605 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "62f537c1449b850f2f3b66c200a85fff4e4ce6c3", - "is_verified": false, - "line_number": 606 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2f83b93fddaa24f65acbea08be3fc0b2456f3ea5", - "is_verified": false, - "line_number": 607 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0d3a416a9b47316629342cf32e4535bd5de367bd", - "is_verified": false, - "line_number": 608 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9d018c03a51c7405ca8de9dafde5fb12bf198544", - "is_verified": false, - "line_number": 609 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0e20193d744f60ef0bcd425ce45d19c73f5ff504", - "is_verified": false, - "line_number": 610 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a2ad69c925092acbbffb97ea70f2c87985fccc8e", - "is_verified": false, - "line_number": 611 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "997ad02ee3779b7ffcd11b8e19df0afe052b66f6", - "is_verified": false, - "line_number": 612 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "46bc2f629e8b64d43d23cc3429346583a7319bae", - "is_verified": false, - "line_number": 613 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "10e4c7043154dc91c0a002d88fe23f356370b80b", - "is_verified": false, - "line_number": 614 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b002194b0535528d6a24fa7502e7f76b935afc8d", - "is_verified": false, - "line_number": 615 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "43728be0f14a9413b4bebd1d22562002cbd07c2d", - "is_verified": false, - "line_number": 616 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "172cb154f89a4168cbbcc48186b6f5a2b113e893", - "is_verified": false, - "line_number": 617 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1df3a86d99563dd6124a197f28a21f1412fd438b", - "is_verified": false, - "line_number": 618 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d44276da69dfa1c411354e75dcda7d75ea6d605a", - "is_verified": false, - "line_number": 619 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "39c326b627e45a8ae4192ac750d38cda7fa55d79", - "is_verified": false, - "line_number": 620 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3c24ec7ee3be457039f1e46a4b437065ba4c4130", - "is_verified": false, - "line_number": 621 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "98b18d68b753e89b1b0c8b4ce575011326b0d2c6", - "is_verified": false, - "line_number": 622 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "95dc0c323f31332cea1b74ce77fe4af9fd0d5c5c", - "is_verified": false, - "line_number": 623 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cb0763f8b448f29101b230bf3ace6a9fc200be9b", - "is_verified": false, - "line_number": 624 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f746e396467de57bda19eb1fe555bc43b8773bf2", - "is_verified": false, - "line_number": 625 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d0878fed2da5ef58888639234936d2df27aa1380", - "is_verified": false, - "line_number": 626 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3010d3905af38cd8156a527f4d531f34c46c39a7", - "is_verified": false, - "line_number": 627 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4da40200c07f4e433a8fafc73d0567d024606752", - "is_verified": false, - "line_number": 628 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5415afc22a2c5f94eabfdadbccbe688b42341335", - "is_verified": false, - "line_number": 629 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "86f3350f28fa5af153e0021bd0f95610f50f0aa6", - "is_verified": false, - "line_number": 630 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "84541393133a5662b9b265024ec3edc3545c3802", - "is_verified": false, - "line_number": 631 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "05830a12efa0b065e55a209e1de1b7721546f2a1", - "is_verified": false, - "line_number": 632 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9e7dabf3cda36b3ab3b57fefca047d5271cb674e", - "is_verified": false, - "line_number": 633 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ef05a15dcbe9f43b719bec0f2dc74d6870cab938", - "is_verified": false, - "line_number": 634 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "35c2e8c0d488a1e0e7f4a721cb9fc5af4f91423b", - "is_verified": false, - "line_number": 635 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e4ad4eb707a0dd2b2ef876c8001f966f51f524d9", - "is_verified": false, - "line_number": 636 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f99b3161abeffa11c6be076150cccd8221fcd703", - "is_verified": false, - "line_number": 637 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4b1647cf6264941baa9ba28fb792cd82e06217cd", - "is_verified": false, - "line_number": 638 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a62b12a0505128c7094f73376a7b32b6896a8602", - "is_verified": false, - "line_number": 639 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8ac29efbb3b877bfdebdcba31d3528f2cd0809ea", - "is_verified": false, - "line_number": 640 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1aa7fb76951a195b27333fc8580b44a57e98fa9e", - "is_verified": false, - "line_number": 641 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3a29474a5fbc845f27b5bafd16ddbb4d7defa2d8", - "is_verified": false, - "line_number": 642 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b1c3e50ce69aa2cc899da1df5a55338242567ab4", - "is_verified": false, - "line_number": 643 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "841f3550b43d66f5f3138d26990ffbb161a3b827", - "is_verified": false, - "line_number": 644 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "80cfd7fb194ed700b9c0e4970bf4e47cc75257a9", - "is_verified": false, - "line_number": 645 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bc4508d089cc2186f7bc5bb14ccddeb772a04244", - "is_verified": false, - "line_number": 646 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "01b35bc3e5deb295f2dd6c43f2abae453ed7a20f", - "is_verified": false, - "line_number": 647 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fa3e9c6424f3bc18eb13d341ed64c132b4f8c929", - "is_verified": false, - "line_number": 648 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b13663ab4e5621994f9bb7909a69c769c343e542", - "is_verified": false, - "line_number": 649 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c06f704f3a0cefec9a28623bda60f64f8c038bdd", - "is_verified": false, - "line_number": 650 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a2eadafda305962f6b553a99abf919d450cc4df2", - "is_verified": false, - "line_number": 651 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "43c8cab46cbb8319ee64234130771cb99a47e034", - "is_verified": false, - "line_number": 652 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1cc137a3c9d41ba4b30464890ae6a6f08c7ba92d", - "is_verified": false, - "line_number": 653 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b43d13f2dcc835cd55d4a40733b22d07fd882167", - "is_verified": false, - "line_number": 654 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "78d7945d58ea7aaaf4861131b57b5fd4c308437f", - "is_verified": false, - "line_number": 655 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6b2f6f1c7b573efc39d8bd013cef20e89e011276", - "is_verified": false, - "line_number": 656 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d92bdf2e2be4bfe8acb991a3cf2b0f23da624825", - "is_verified": false, - "line_number": 657 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e8b7c1a13d23facf8589088b2de85f851ad53a82", - "is_verified": false, - "line_number": 658 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6d3e58158529f32b5ead6e3b94c7ca491ef27ed3", - "is_verified": false, - "line_number": 659 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "800ea2592a27f8b38f0a18253dd49f97b65a3aad", - "is_verified": false, - "line_number": 660 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0b13798c29f5879b119c807ab7490d35a0342cef", - "is_verified": false, - "line_number": 661 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0a9a21ca4e9aa08b2b5fbe769bf6afb1deb8da91", - "is_verified": false, - "line_number": 662 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "183877effc366e532c7937f2f62f7f67f299bd36", - "is_verified": false, - "line_number": 663 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e245782b2f99805ed35dab1350ac78781ae882eb", - "is_verified": false, - "line_number": 664 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9b619bf6db9561f29c4cc75e26244017cc97d305", - "is_verified": false, - "line_number": 665 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "377469b721f5e247f1ad0fee41cca960c49a1fe9", - "is_verified": false, - "line_number": 666 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f2cb896b3defe96fd6a885f608e528704b40728c", - "is_verified": false, - "line_number": 667 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7643925d0ad2652497482352b404604985b0f41e", - "is_verified": false, - "line_number": 668 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ce5594ef11357e35de0d439687defce446dd0f66", - "is_verified": false, - "line_number": 669 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "65dde318bca6689643335f831444daf0156cc4e5", - "is_verified": false, - "line_number": 670 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "143c3d69803143aa5d40372c0863df82b176b41c", - "is_verified": false, - "line_number": 671 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c32dcbc4225f3183d5f5a5df78ec5ae9afb38968", - "is_verified": false, - "line_number": 672 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cfa29e11ebef38d8e08fb599491372f6404e6b6f", - "is_verified": false, - "line_number": 673 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3d91d5f1054fc768cf87c6b19d005e6d3ccbc2f3", - "is_verified": false, - "line_number": 674 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2d6bffd0f0c9cc4790eebc50b6a56155c3789663", - "is_verified": false, - "line_number": 675 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "64110bdd2bf084ec47040ce8b25fc13add2318e7", - "is_verified": false, - "line_number": 676 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7f6bf6522a85f71bf4b93350ec369683759735f9", - "is_verified": false, - "line_number": 677 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3d53588bd3f314ef6e7bf9806e69872aa2ce1aff", - "is_verified": false, - "line_number": 678 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d5efc1772557e4bff709c55a59904928b70ffe1c", - "is_verified": false, - "line_number": 679 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b8e46dd05b23c4127cca0009514527e49b6c400f", - "is_verified": false, - "line_number": 680 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "58d30b123d121316480c37ae6222d755dc9144ca", - "is_verified": false, - "line_number": 681 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "66a2abf99d8a4a38e6d64192d347850840a580bf", - "is_verified": false, - "line_number": 682 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d434fa5b419700a92dc830da1c3d135e8ad0b3e2", - "is_verified": false, - "line_number": 683 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ee251356a77d3ec7b7134156818fac73a2972077", - "is_verified": false, - "line_number": 684 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "239cb830c56b6d22115d2905399f8518bd1a5657", - "is_verified": false, - "line_number": 685 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2e6143570c020503a4e1455ec190038b82bedc19", - "is_verified": false, - "line_number": 686 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9107d00af85969940a45efb9eccad5e87f8a87f2", - "is_verified": false, - "line_number": 687 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5a5d1ac75eb4c31c7e9650ac70bdc363a9b612c5", - "is_verified": false, - "line_number": 688 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "05a99938fdc58951b4a6a756c8317050e3f5d665", - "is_verified": false, - "line_number": 689 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "67ccbdebe626ab7af430920c1d0d6ec524bdc4f9", - "is_verified": false, - "line_number": 690 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "71fd81160a50c9d47b12b4522c5c60f2fca72b6a", - "is_verified": false, - "line_number": 691 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f150f2f043f66a564ed3b3fb2f29c0636fd2921a", - "is_verified": false, - "line_number": 692 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a1140dfe90f9a5da45451945b56877c45cb36881", - "is_verified": false, - "line_number": 693 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7533bea169a68e900d67a401cac35a7aade18d92", - "is_verified": false, - "line_number": 694 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f0dd83a2a8d653ad8b30fefcde5603b98bf1ca66", - "is_verified": false, - "line_number": 695 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "21334df57a3a5c6629c12f451eeb819a2b37b42c", - "is_verified": false, - "line_number": 696 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "99f04da5b8530b3eb79e3740fece370654d3c271", - "is_verified": false, - "line_number": 697 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c2dfd7c77cafb9193a0e77a45d14ccc1498816fb", - "is_verified": false, - "line_number": 698 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5351e6405ba12ea193b349e8b2273201bb568404", - "is_verified": false, - "line_number": 699 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cc215cb1a47a674d2b0c1fb09df87db836ce8505", - "is_verified": false, - "line_number": 700 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3078af7fa82e149420b97ff56fff9f824387b35b", - "is_verified": false, - "line_number": 701 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ac0e1537926b5bbd543ad3e731959a0bad451c73", - "is_verified": false, - "line_number": 702 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a6da4e82d314f4ca0bf7262a78875b0b6edc30aa", - "is_verified": false, - "line_number": 703 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e08c74c3fbf412c2d4f330b0414f1275679cb818", - "is_verified": false, - "line_number": 704 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7bf9ae1b766cb0b9a5aa335a0103518d7be00daf", - "is_verified": false, - "line_number": 705 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ec844560c5f208fa8723c1700f6e86b8e7ffed04", - "is_verified": false, - "line_number": 706 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6c133b025f53327eb652d2a1ca576dfe58eef1b4", - "is_verified": false, - "line_number": 707 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3dc21b9f6f63b73a241d900e379a3c7094341f8b", - "is_verified": false, - "line_number": 708 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1a012b2bf61ee9874d5af73df474051c0d235ecf", - "is_verified": false, - "line_number": 709 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b0ebf0b521ec6e6e696f9be2fe4e1845876d57ab", - "is_verified": false, - "line_number": 710 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f0a5d3ac0705186e25effb02649df87361b8c67e", - "is_verified": false, - "line_number": 711 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "385ecb845a1d5d43766d568b466d1dd237a81980", - "is_verified": false, - "line_number": 712 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "18d0416b8ea44ce305b214380de978cef27e8603", - "is_verified": false, - "line_number": 713 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "89dca45aa9146b8a31236fd77001c02769dceb60", - "is_verified": false, - "line_number": 714 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "30acd4c1f4a878883c654846b8f3c5a6ab807285", - "is_verified": false, - "line_number": 715 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7d3229ff5e754c72a8b2072d3d7a5e00749ece9b", - "is_verified": false, - "line_number": 716 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e6da9d65dc0cfb42b86ae8f9b7c1d5fe79b4a763", - "is_verified": false, - "line_number": 717 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9c85908a1bfd5f2a7337f812c68f2ce8dfbfd65e", - "is_verified": false, - "line_number": 718 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4000341e5c04854eeca9fe7537dfddfdbb7c785a", - "is_verified": false, - "line_number": 719 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ef23e2969a46edf410fab2c69d1b29b2a65f57f9", - "is_verified": false, - "line_number": 720 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4902863163e24fa9f172e61808385de2b9ee3099", - "is_verified": false, - "line_number": 721 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "31efc8d3bba9c8f66b3f54bc146443732ac15c2c", - "is_verified": false, - "line_number": 722 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "263deaf83b359554fc9dafca8e6622ece44cf75d", - "is_verified": false, - "line_number": 723 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ead7409fe5b86813e3609f7fe6e13b8fc4b0b9d6", - "is_verified": false, - "line_number": 724 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7b0d884d6cdc64a613cf3e887395d875ff738c3e", - "is_verified": false, - "line_number": 725 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fa0a0a999cb067eee81673f3d2de8bfd96a0d14c", - "is_verified": false, - "line_number": 726 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0db684d862dfc8427e8f66adb62f33fcdc9f3de8", - "is_verified": false, - "line_number": 727 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8794a8121832fd31b1871d2c5d4b00af07779b0c", - "is_verified": false, - "line_number": 728 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d6070805e7a6c25dbe13a540cbc0f16a89055e7e", - "is_verified": false, - "line_number": 729 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "56b3e8e6d14b9b459bf055900784e8aa31c306c2", - "is_verified": false, - "line_number": 730 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a4d6976637c19991da48707bf35b3cf2ded4c2fb", - "is_verified": false, - "line_number": 731 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f714e448a86a46baf2128d81014e554874f0d4f6", - "is_verified": false, - "line_number": 732 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2b03a5eb51085de41df415881ef1d425f20f9e05", - "is_verified": false, - "line_number": 733 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "99fa7285e15d91ac3047b95ddb475d339c7afc7b", - "is_verified": false, - "line_number": 734 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4a9880aa478dba526c2d311ae17578711d0f9426", - "is_verified": false, - "line_number": 735 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0cd512ccf176189c7bf36765b520d8ec2ddeade0", - "is_verified": false, - "line_number": 736 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2eb8822459b9db479752d12f62dec094ab68fc55", - "is_verified": false, - "line_number": 737 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1aab694ebb334a12ccd22baa0044a3b058db67f9", - "is_verified": false, - "line_number": 738 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ce29f8616e1c62e54a8f0b39b829d9bd7df5721c", - "is_verified": false, - "line_number": 739 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c099a1c5f639e647bda5961d9c51cc158790ff3e", - "is_verified": false, - "line_number": 740 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "78dc2b71e3614e4e802c4f578a66132ea1ae0be8", - "is_verified": false, - "line_number": 741 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0befb6d3255080ce4d051a531fc1fedb33801389", - "is_verified": false, - "line_number": 742 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "087447f269677e0947da157a5bc0bb535c6c7759", - "is_verified": false, - "line_number": 743 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8911e3aef563e1481305a379a083f7616d57cd08", - "is_verified": false, - "line_number": 744 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2846a4bb4af2826a787fb0d8a0e7342c404a1cd1", - "is_verified": false, - "line_number": 745 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3364317b783250007fcee5bcddf07b2006752ad3", - "is_verified": false, - "line_number": 746 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e1a4444540434bc0ba51a8b5e6540e82d4b17f4f", - "is_verified": false, - "line_number": 747 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f453d1221dfbe308b5c71029f5cc2fba020f2c6a", - "is_verified": false, - "line_number": 748 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3e4231678403aa61b0f4f6719081016d579fa3e4", - "is_verified": false, - "line_number": 749 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a64b90a0dd1a214d6c65a4078437eab4ada65a32", - "is_verified": false, - "line_number": 750 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0433fe0f97f7a354a3ed06d6a8a77c2f1983f947", - "is_verified": false, - "line_number": 751 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a21195a2dde808b7cff35695396ecf7699125a53", - "is_verified": false, - "line_number": 752 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6547a05519f26198981f500b703d36443958ad14", - "is_verified": false, - "line_number": 753 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fbb8441f5e8e9b911cc42a025c856470784d89d1", - "is_verified": false, - "line_number": 754 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6378293ead806f554612c82fddf04ea8fb1ab2cc", - "is_verified": false, - "line_number": 755 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3272309f5c986a45cd892d943c5bd5af5165ad70", - "is_verified": false, - "line_number": 756 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1c79d15ecac42472241726cbae8d19bb820f478b", - "is_verified": false, - "line_number": 757 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a868da324435f3b1f32bc12bbd3171e9d62fcdca", - "is_verified": false, - "line_number": 758 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c56de5d2c763355c7a508dec8c7318e0c985dfec", - "is_verified": false, - "line_number": 759 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "258e19436174463d0e1b8066eb8adfbf79f78b32", - "is_verified": false, - "line_number": 760 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "112d96e04bf661b672adc373f32126696e9c06fe", - "is_verified": false, - "line_number": 761 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bdeaea4ca3484db9e8b0769382e1ba65b62362b3", - "is_verified": false, - "line_number": 762 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fff367064d95bace4262a1b712aa5b6fb2a821d6", - "is_verified": false, - "line_number": 763 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e16dcae490d17a842f5acd262ca51eae385fb6af", - "is_verified": false, - "line_number": 764 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bad941c81722b152629cebce1794a7fd01b85ebc", - "is_verified": false, - "line_number": 765 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "65e6aaaad1727c35328c05dd79fb718d5b1f01ce", - "is_verified": false, - "line_number": 766 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b7ea9b9d7d8c84eeeb12423e69f8d4f228e37add", - "is_verified": false, - "line_number": 767 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "42bea72c021eedb1af58f249bdae3a2e948c03fa", - "is_verified": false, - "line_number": 768 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1ddcb2cad21af53ad5dd2483478f91f3c884cea0", - "is_verified": false, - "line_number": 769 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e72ad6e31d1a19d6b69a1a316486290cb2c61eab", - "is_verified": false, - "line_number": 770 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8ca884c8fb24ecd61300231b81d1d575611cda07", - "is_verified": false, - "line_number": 771 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5754688edbb69be88b9c0ea821cc97eada724c14", - "is_verified": false, - "line_number": 772 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a267e65960056589647f075496fd3a6067618928", - "is_verified": false, - "line_number": 773 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ad3424f420bf25442aa9df96533852d29eac12a9", - "is_verified": false, - "line_number": 774 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8a5a26db2b7bda6268a9250808256e08d2a62262", - "is_verified": false, - "line_number": 775 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ff90aa934268bd629b33708b7db9a10b5f0bf822", - "is_verified": false, - "line_number": 776 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9294697fb9b36decacc26c3c33c3d186fc128f82", - "is_verified": false, - "line_number": 777 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8dfc552d4f52ed53ccb13c958117ceba6c8038d8", - "is_verified": false, - "line_number": 778 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "49c6467fa09d3052faaa1a369ebd226234db892d", - "is_verified": false, - "line_number": 779 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f2a450ffba5b1fdb7f016e4add7035ef6ba2df77", - "is_verified": false, - "line_number": 780 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "79a4f5a8804b9a94b5c4801700f08a2cdef54662", - "is_verified": false, - "line_number": 781 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1baf161ffff392357bbfb8e38d95c8c2f79ef6a2", - "is_verified": false, - "line_number": 782 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "840365ccbf5f23b939e8ee15571bdb838a862cb3", - "is_verified": false, - "line_number": 783 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0e50db71a57f0d0016b2abeaf299294c3bb4fedb", - "is_verified": false, - "line_number": 784 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b108976e96b8ce856b59b4f73cc6caa2555310cf", - "is_verified": false, - "line_number": 785 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "474f1a83c946ec223093d46f5010ff081f433765", - "is_verified": false, - "line_number": 786 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3740691aa3a788e71b7b74806dbcae3009b4f7fb", - "is_verified": false, - "line_number": 787 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c11bddda98ea121b857aabafbcdf75307a18bc45", - "is_verified": false, - "line_number": 788 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3445e70b7f8f3d381c21f6ed88c28c0db545662e", - "is_verified": false, - "line_number": 789 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c368482da3144e79d4f4f8063bdcfc85b1318ca1", - "is_verified": false, - "line_number": 790 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "470e734260c3e67dd19fca5ef32dbc6ce863dcbc", - "is_verified": false, - "line_number": 791 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0dc9bbedd1b90674d2d0c81563b1b59e82f901b6", - "is_verified": false, - "line_number": 792 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "49bbe143a0a5d2d81eaa04b0ae5f02b89b2e60ce", - "is_verified": false, - "line_number": 793 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9e009fcc53e8ae16ac2cd1c31945812a8b3cb1f8", - "is_verified": false, - "line_number": 794 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fda8ab7b8d8d0e3d995648f21cb97fb6a4371008", - "is_verified": false, - "line_number": 795 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "15ca6383ad968b3f606e5600e0ee5765cc61a223", - "is_verified": false, - "line_number": 796 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c901600adaae1fae9b24fe869cc11364e07651c1", - "is_verified": false, - "line_number": 797 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2a6968448cc0520a44b0fc8eac395ef9047a0ba9", - "is_verified": false, - "line_number": 798 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e58e1397cdedc8cedfc10472af62b0e24b7d90bd", - "is_verified": false, - "line_number": 799 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3f1a00fc8f814e6e5bfbb1b38a44318af25c0149", - "is_verified": false, - "line_number": 800 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "23887318ac83e9f3953825ada42ec746364c362a", - "is_verified": false, - "line_number": 801 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c5ebf6b1cd6af76112bb20fb2ef8482bd95088fe", - "is_verified": false, - "line_number": 802 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7f2b7465a347061ef449ed6410a3fccb7805775a", - "is_verified": false, - "line_number": 803 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "35c7486eb3aab3d324e34c9f2e4149c0833e7368", - "is_verified": false, - "line_number": 804 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6bafab58fdb0248c4e31eb58b8b99d326a5fec77", - "is_verified": false, - "line_number": 805 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b5b8f84bebc143026521dd3dec400fc319c8f07f", - "is_verified": false, - "line_number": 806 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "dc663ea73f635724beef79b22fe7c40bf812907f", - "is_verified": false, - "line_number": 807 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a5f5ebcab108b702af3122c9dec85e4aed492ba1", - "is_verified": false, - "line_number": 808 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "24826ebb519bed6f61af4c6dc3008fea3ca87c62", - "is_verified": false, - "line_number": 809 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f5e2d1ee2fc9d16703269c4942a406effa9208ae", - "is_verified": false, - "line_number": 810 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f28e36af3d92643a5ca738f66b0f9b0f0906a02a", - "is_verified": false, - "line_number": 811 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "19c8b107d6fdc4b807d831334b433ba0f051ee3d", - "is_verified": false, - "line_number": 812 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fd640c778ecdae75e71f490588436bad8551dc0c", - "is_verified": false, - "line_number": 813 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b93f3e5a8f7937290e368015ec63b9faa148a091", - "is_verified": false, - "line_number": 814 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b665cd0e94b8b690e5edb8446039bc20bd4edf8f", - "is_verified": false, - "line_number": 815 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e3482306ec339930b1f4d60e13c4006b9ac9949d", - "is_verified": false, - "line_number": 816 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a2c8590320283074b40e9c0f05af26ac1671580f", - "is_verified": false, - "line_number": 817 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e30ee01ef2baf677c7592e2a339d1d4c5f3b3053", - "is_verified": false, - "line_number": 818 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b8495b9cd806dbee2e7679dc94c9ca6b675107af", - "is_verified": false, - "line_number": 819 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b175eb842c0cb4c4d2b816c80b2cfea2b81eca04", - "is_verified": false, - "line_number": 820 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7cca142d68498553dd9cd10129b64f8f6b1d130d", - "is_verified": false, - "line_number": 821 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "62709b572d8c7952674f5ca8c807aa12346d8219", - "is_verified": false, - "line_number": 822 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "260d9d5da81fc235a36890dc1df9b0b93e620051", - "is_verified": false, - "line_number": 823 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f45c83b63c8fb4ee062a5649950ed25963f72269", - "is_verified": false, - "line_number": 824 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "94ab5caccdc141879f89dff48b17d633cce7c6ae", - "is_verified": false, - "line_number": 825 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8a67f56357e2ab075ec362aa17de81e09829dd1e", - "is_verified": false, - "line_number": 826 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e47ea7fc498253e920531b2f9440df22b65b4bfb", - "is_verified": false, - "line_number": 827 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "608bda7f1c9bbb04cbcd94fbef60907b34e5107c", - "is_verified": false, - "line_number": 828 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0ef4f672781b0c8008104b4833da99758a37c2d5", - "is_verified": false, - "line_number": 829 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b84c442c7f733ee0416ab3e451b3acd4fe708d11", - "is_verified": false, - "line_number": 830 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "af40c42cfab503d271744c98fa2d912f75fe1192", - "is_verified": false, - "line_number": 831 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "088fb0ba102fd16911bc92ecad1e96d6b9d7c6e1", - "is_verified": false, - "line_number": 832 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0205ce524bdf9689abb764ade3daff0a75a9680b", - "is_verified": false, - "line_number": 833 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ffb06eac178944f7cd519dffee1bce92b7b39de0", - "is_verified": false, - "line_number": 834 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1f4fec8780ce70e3b189b9ef478d52cb508ab225", - "is_verified": false, - "line_number": 835 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2084a2c1c5c015caab2036e77747bc1bc8da1b5b", - "is_verified": false, - "line_number": 836 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6d61e0dc6e9e3786a038ce41b2645ffa55ad34dd", - "is_verified": false, - "line_number": 837 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c2eedfdfb494f1da2837db4fe02a349f6b83e34b", - "is_verified": false, - "line_number": 838 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cb90f645f60eb596ccd816c2c9cad6df1da2f7af", - "is_verified": false, - "line_number": 839 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3714fb2f7dd6cc5392456fa413a7a6ba3cceca16", - "is_verified": false, - "line_number": 840 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a2b9353093261900009e92216ad07fb712d3aeef", - "is_verified": false, - "line_number": 841 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "38abeae07fcc9d78f57c915f7ec1ef448928c8d7", - "is_verified": false, - "line_number": 842 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4aab4807666815ca001aecb2c98150fa4e998a4e", - "is_verified": false, - "line_number": 843 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a3c2b5f078ce6bd677972296a39a9b6f476ad8fb", - "is_verified": false, - "line_number": 844 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "76cb76a7b46fbebf5a3d38b4f7507f5f6f966bbb", - "is_verified": false, - "line_number": 845 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6216237ea7f4271573ad9257b04f29624b32d067", - "is_verified": false, - "line_number": 846 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c46a24ae59ed9570cd0eaaf744cbdac682131822", - "is_verified": false, - "line_number": 847 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c7f4bfd365cfeda78938b48c174e84c476e0b121", - "is_verified": false, - "line_number": 848 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "95306491cf2bf602d32f153877fa3668188e89e5", - "is_verified": false, - "line_number": 849 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0a86977039aca715fef41f075a006d08913e2f9e", - "is_verified": false, - "line_number": 850 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "98ab4de33fb607da8c4bd3e6dcde7fc48be461cb", - "is_verified": false, - "line_number": 851 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c8a681b8468ceb7be04c81c9531fc1b76a73a979", - "is_verified": false, - "line_number": 852 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c1f2b4dc85c69f47bab7f0c95934abeb21241dfe", - "is_verified": false, - "line_number": 853 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d2c65d95022c1689e545f27bdb9125abfa65014a", - "is_verified": false, - "line_number": 854 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5334888b103ace2ac1628b453dfba0374aa21563", - "is_verified": false, - "line_number": 855 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "db870d53e2dbee8610b39a18017bf2e95d9b6a1d", - "is_verified": false, - "line_number": 856 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a874dd47f5e9d721212644df27395f9d0455bc7b", - "is_verified": false, - "line_number": 857 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "24304e79b441e1689f7db990cf1380e8ea172237", - "is_verified": false, - "line_number": 858 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ed52cda8715ae3d4b24fdea5e451cf0610003eb6", - "is_verified": false, - "line_number": 859 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8b5757852d0c36e7217daf8504004e6c85212d7a", - "is_verified": false, - "line_number": 860 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "85d089a4858f5681d1828bc1d67eb3f19bbeba6f", - "is_verified": false, - "line_number": 861 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "80dbb757c0b7fb948816886168d397b09b317e0b", - "is_verified": false, - "line_number": 862 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a45b519f89630194e67ed91782425b2095083fcb", - "is_verified": false, - "line_number": 863 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "297a0f9e38f85884d7d6beb518b33f8f35349004", - "is_verified": false, - "line_number": 864 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2200c973aaaaa2f1201604176787152091904d25", - "is_verified": false, - "line_number": 865 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "07d4fef177f006578f4d37289137d90727a5fa86", - "is_verified": false, - "line_number": 866 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d68f0a891f53a354bff2a9002ce0e3c60236d0fa", - "is_verified": false, - "line_number": 867 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d101c2cdae39ce8adcf30a777effd4be14b07713", - "is_verified": false, - "line_number": 868 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7e5670956a5ca012cbfe2ec89841595ada7ffc4a", - "is_verified": false, - "line_number": 869 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d58782068176eeb0987b1850ec9b1e54764c5947", - "is_verified": false, - "line_number": 870 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d779f72f04dbb76344f4c264d19bba7242e25e90", - "is_verified": false, - "line_number": 871 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "99c57a64facfebfb9e41dfae591af95633715986", - "is_verified": false, - "line_number": 872 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a7a97bb3f0508c2ed46ad81ed8cc53ff7469edc5", - "is_verified": false, - "line_number": 873 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c8b289fb0554107bbd07c43f462a87e7b929a529", - "is_verified": false, - "line_number": 874 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3c092d1639246d4ce9167319e729dc39d1bb3793", - "is_verified": false, - "line_number": 875 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c34cc18e2fb77269d8f33529c23d4ae2a55b873e", - "is_verified": false, - "line_number": 876 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "57562f3034b2895272567bccdb4476ff4ffb387f", - "is_verified": false, - "line_number": 877 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e75aa06fcf9eb16ce4f765009f73bff5998b4d82", - "is_verified": false, - "line_number": 878 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "561dd2c1798724b1f7730df97cf07b16f27db369", - "is_verified": false, - "line_number": 879 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "548d01127e6414ebc307a1da07e1814eb28d9c43", - "is_verified": false, - "line_number": 880 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d356fdfdeab6a77435a395a60e99e988f3c7e85e", - "is_verified": false, - "line_number": 881 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7d850865aadf5851746b420805c2d1a859af11fe", - "is_verified": false, - "line_number": 882 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a2221c705b602dee5ab23632133b47700d5a1dd2", - "is_verified": false, - "line_number": 883 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0d4e54941ee10299f1064634fffb86e4b7bfd005", - "is_verified": false, - "line_number": 884 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "589f88e962e41fc2e6691090dc335a20c7520348", - "is_verified": false, - "line_number": 885 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0d9ea7340e4afb03c7564f911883428d4d0e5e01", - "is_verified": false, - "line_number": 886 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "86525dece15cc1ed811c029ebae7ce496af598aa", - "is_verified": false, - "line_number": 887 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f3add200e410ee751ec2e65f4c00d5fe546a2b46", - "is_verified": false, - "line_number": 888 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "89588ee266a0fee04980b989461d344c91f917cf", - "is_verified": false, - "line_number": 889 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c02f12006740778cceb3e14d10eef033650f0905", - "is_verified": false, - "line_number": 890 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "16d1c52b661852a0a2d801d14e5153cd2245854a", - "is_verified": false, - "line_number": 891 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bd48b759e75395bd491df6811d82ada954b1a8f8", - "is_verified": false, - "line_number": 892 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f9d8d2bcc1f978b39c12409b8bd5c35e1fd3caef", - "is_verified": false, - "line_number": 893 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bd7006183d8fc08da5a29edc7dce2833b7d67c29", - "is_verified": false, - "line_number": 894 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b4f7d597cf8d0e4a8bdd47b462ffaf7f753906f6", - "is_verified": false, - "line_number": 895 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "10d3f4cb2e16143374e3db5c6828184d97cef711", - "is_verified": false, - "line_number": 896 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6045891b6aed86c8d19a6aecd12b2df1a32e3921", - "is_verified": false, - "line_number": 897 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f09ecd7a19945614bd73b5be04331b691d2bc030", - "is_verified": false, - "line_number": 898 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f0cf1445d72e773713d17ed9ecbf6f805206cc80", - "is_verified": false, - "line_number": 899 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "34cba93b5c522de558e25672a78a5d75028a02fc", - "is_verified": false, - "line_number": 900 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b08833d65be532022a038652bffe2445f840479f", - "is_verified": false, - "line_number": 901 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ed24a43ca6ed9df8d933b25418889701bdf1492d", - "is_verified": false, - "line_number": 902 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f081d33d1093e834b3fe9e678720c07c7dfbaef7", - "is_verified": false, - "line_number": 903 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fbd0b56627efce28202a4ebc927ed09fb338cf24", - "is_verified": false, - "line_number": 904 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8f79ecdca6ff2d1240ab55db0395f3babd8e0cd7", - "is_verified": false, - "line_number": 905 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0d42925b4018649775d5543b6e5ccd1096eea954", - "is_verified": false, - "line_number": 906 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5564f26e8a7f58c2e525d04261557b54ccb3eeae", - "is_verified": false, - "line_number": 907 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7e61f7e6fbbccc54b49c5932dfee56e4d05d8bb6", - "is_verified": false, - "line_number": 908 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d28c82f5235be5773d7b556004493d197863e47e", - "is_verified": false, - "line_number": 909 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ead7a2d8ba1098da1203103338f6077d384ec789", - "is_verified": false, - "line_number": 910 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "57b73b00541a671b1c0f9b49b1a5b9b6d43e386f", - "is_verified": false, - "line_number": 911 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "00d3ba478bd4e0005ba325c0fa3bbb80969a4072", - "is_verified": false, - "line_number": 912 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "63497e9fab38614d05946c0b9dd1338983132696", - "is_verified": false, - "line_number": 913 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bf7915a186cac89cbf27b479b4318af45d334f3e", - "is_verified": false, - "line_number": 914 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9e5791210452015df2676f6a7706415ad7c8149e", - "is_verified": false, - "line_number": 915 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "149a819c93748d871763fdd157fbf2c93fcff33d", - "is_verified": false, - "line_number": 916 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5c0e33a6cdc2bcfa911e665929ae524093e8d4a8", - "is_verified": false, - "line_number": 917 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0a04734c82ec76181682c537a590934fbe46fe44", - "is_verified": false, - "line_number": 918 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fb96412139d649dc332fc596841dc2d7543a09d3", - "is_verified": false, - "line_number": 919 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c48b721469472686b78de0db8d34ccfbe5113804", - "is_verified": false, - "line_number": 920 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7c832e5288c3cd8f714e3b57d31c7fe05ad0b98b", - "is_verified": false, - "line_number": 921 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "58383e090cd1cdfdbd494f46d533d7be96c3d16f", - "is_verified": false, - "line_number": 922 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "964063ef09c1114c0b89c4a8bdc6fb9a5238b75b", - "is_verified": false, - "line_number": 923 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0f70be8ee00fb5491a86ff2b185e193bed8147d2", - "is_verified": false, - "line_number": 924 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "eade9c861e70446d1a4057306ea14bcbb105515a", - "is_verified": false, - "line_number": 925 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "645a4a4787c20dbf7d23af52b6b66e963a79701d", - "is_verified": false, - "line_number": 926 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "952b79bc3f47f661ffd882f2cac342d761c7ee89", - "is_verified": false, - "line_number": 927 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "325ae8750d58cb76ba5b471c776b575c6dd8f7de", - "is_verified": false, - "line_number": 928 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c848e0ebbd67aadd99f498bf457fe74377e2dee9", - "is_verified": false, - "line_number": 929 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "938a394aacb5f28860f2a21dc11c2143dfda6609", - "is_verified": false, - "line_number": 930 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6f7cc320c863e5e4d854df9f1d9343408b316152", - "is_verified": false, - "line_number": 931 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bca601976f824d572c9829820d04ef78f0aa89f2", - "is_verified": false, - "line_number": 932 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8f436a87f64990bcc5bba342e4614ba240cb4001", - "is_verified": false, - "line_number": 933 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3c41d19e585a5d6932fbedfe9a9970b2be5be662", - "is_verified": false, - "line_number": 934 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "11c444922d1367a8d844b4f265dd34234145b4e1", - "is_verified": false, - "line_number": 935 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4b5b8766a87bdfe9e72b205635cf3202579c294e", - "is_verified": false, - "line_number": 936 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a8c32045952ca987aa668c54161b8313d4e27d06", - "is_verified": false, - "line_number": 937 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7280d2d3abaeaa0b8c09b30184cfa8e9d96f16f9", - "is_verified": false, - "line_number": 938 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d353aeb68a062440b13bc25906bc19450808c33f", - "is_verified": false, - "line_number": 939 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c06ff020b6c003435cd543d7c094df946d5cee8a", - "is_verified": false, - "line_number": 940 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6c846e552b2bae1eb5fb1ee603bd35dbcf43f8e1", - "is_verified": false, - "line_number": 941 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9526db9835d636a82d4c7843dcb4b1a97f0cd41a", - "is_verified": false, - "line_number": 942 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c0d1d341758862cd2d243425d7e0e638ccde2be9", - "is_verified": false, - "line_number": 943 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "168f03ae12ec1b265302c9be39275b3ff886f0ba", - "is_verified": false, - "line_number": 944 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d4431e65831239ecb46c60b109b3cdf3d90413e4", - "is_verified": false, - "line_number": 945 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6065a318efbc35fa8bfa8179ea00d139aa8ac5f8", - "is_verified": false, - "line_number": 946 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ca8eb4ab2a13fd9c8009f64e9a57a9698da2af08", - "is_verified": false, - "line_number": 947 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "076d36e09e412d1baffcfe20e235b32e766d9d37", - "is_verified": false, - "line_number": 948 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8a96b1bb17e8fc8048721963a8944f194e0d6383", - "is_verified": false, - "line_number": 949 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "036334bc532f791df9f17a922a6b282468e3a32d", - "is_verified": false, - "line_number": 950 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2e9e4798ee11ce742834d80c2103c846b8a7daa8", - "is_verified": false, - "line_number": 951 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b34309d4e552ffa204cbf7632dd06376f7cfe925", - "is_verified": false, - "line_number": 952 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "eb323c2dabc2fe8fe9d73e355e24554f45a097ef", - "is_verified": false, - "line_number": 953 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "eeb750c5480e76e5b075a1cc415007182d5a84a5", - "is_verified": false, - "line_number": 954 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "baa82df8fe62f21e4a9bd056515d279b5f4bf296", - "is_verified": false, - "line_number": 955 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7ed197e47d75c92a2bb9fa469ce2584338ae7978", - "is_verified": false, - "line_number": 956 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "eacb84eb412e97afee8329c534ea5822025d2f34", - "is_verified": false, - "line_number": 957 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1a7e7d49835c298874d24cf9434a7c249f71811c", - "is_verified": false, - "line_number": 958 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "71124a16113f0bfca8f71090445ea96115e92c3b", - "is_verified": false, - "line_number": 959 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "eb6fed65dc17090a731ba790be1c1e913ed43696", - "is_verified": false, - "line_number": 960 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ff488edfba52bda0a9d4ef548f4e848e1bc407c1", - "is_verified": false, - "line_number": 961 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d58ebcc9017888fd12d9eee6a1dbb7a1e5d8bf72", - "is_verified": false, - "line_number": 962 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4db9b98c3dc42567e08ac91e4658c7774eacfddd", - "is_verified": false, - "line_number": 963 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e91ea43a53d83fb4b47e5769b7db51e4f1c0a333", - "is_verified": false, - "line_number": 964 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b8768444a059004aa7d50c73da0c7665e774c8b7", - "is_verified": false, - "line_number": 965 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "52af7be744b7e8e3c9d75db11b3de31693313573", - "is_verified": false, - "line_number": 966 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "169a53ab3aa86b11c6a4fb5064b2cab7b64d260d", - "is_verified": false, - "line_number": 967 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6c29925cd018548844c1b174a4fad45f39ca4d3b", - "is_verified": false, - "line_number": 968 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "793d9bb0e0d7f5e031e367587ecb877881cdd56b", - "is_verified": false, - "line_number": 969 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "709969f024af92b318a5dc3a0315a66c2a024820", - "is_verified": false, - "line_number": 970 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6c66657d4bd785b7c16df241260cd51f8d7e7702", - "is_verified": false, - "line_number": 971 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "54330bf419e7174ab210ac03a0b26bdbb50832e3", - "is_verified": false, - "line_number": 972 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "02bbbfc42d316c59297fe15109e17447512bc76c", - "is_verified": false, - "line_number": 973 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "446f08aead8d20df9ee177b4ee290303cbbfc348", - "is_verified": false, - "line_number": 974 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9b47bd9a70c30307c89348cf7044e66b8eeb604b", - "is_verified": false, - "line_number": 975 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "16799c910c44755b0c3ffa38c27e420439938bb8", - "is_verified": false, - "line_number": 976 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cfba338d2d1c6c8ee47fd7297eae9e346ef33d2c", - "is_verified": false, - "line_number": 977 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "42f730799ccc5f4e3f522abf901ce4a7872f4353", - "is_verified": false, - "line_number": 978 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5669611e63657e7b6d5f10aee1fe08837577dc99", - "is_verified": false, - "line_number": 979 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8b8a1180371e560308a4b3bcbf7d135e4fdce66e", - "is_verified": false, - "line_number": 980 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b5b25fad7a60d76bb8612fe1fe7f4114134b7fe1", - "is_verified": false, - "line_number": 981 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7268358632fc15cc97395c23ac937631427a06da", - "is_verified": false, - "line_number": 982 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "77b14302acab126de73e1960951b4d8862f8996b", - "is_verified": false, - "line_number": 983 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a9f98d55aa73cddda74d878887f9cf7c91ed9622", - "is_verified": false, - "line_number": 984 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7c0abf324bb40af2772baa72ec9eb002674b972d", - "is_verified": false, - "line_number": 985 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ecd7751d16ed66ffbccbc3bc0cdc6767e85c9737", - "is_verified": false, - "line_number": 986 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1829e0ea8aa97dd1c07f83877af61079a0420f0a", - "is_verified": false, - "line_number": 987 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "246e88cdb42b377333a3fb259ca89b8f2927c9f6", - "is_verified": false, - "line_number": 988 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "70c184cc1ba36cc336edff03d3180e16a7b6a8c8", - "is_verified": false, - "line_number": 989 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f3e0f3c62ed74ee4c701d70dbfbf5825e9b153e3", - "is_verified": false, - "line_number": 990 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fceabb5893c16c83a2f75e44a2c969cb6bff4c70", - "is_verified": false, - "line_number": 991 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "dd14309feb249e827dba5ced8ac68b654e7db8cf", - "is_verified": false, - "line_number": 992 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9f675a535ed79052f233c3b6f844eb96368d2d4f", - "is_verified": false, - "line_number": 993 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0e0d26feae012efa3585e895b6fa672005c3434e", - "is_verified": false, - "line_number": 994 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "42a18905f6b1ba2fa6cda2c3b08b43059503926d", - "is_verified": false, - "line_number": 995 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "960330eaa639a3374f20fb3bb1d33c3cb926f9cc", - "is_verified": false, - "line_number": 996 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c676ae0d67843480085f4544a475ccec95b1c942", - "is_verified": false, - "line_number": 997 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "05a62b604c1187eb336526d03642a7c46e6727c3", - "is_verified": false, - "line_number": 998 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cde1211319f593ead3f23c0fac4f0ab48866f5da", - "is_verified": false, - "line_number": 999 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7d12d1e4865212b188c6aefd69096d4f6df8d113", - "is_verified": false, - "line_number": 1000 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "58c2087994575f810e6fb07f476718ac01436189", - "is_verified": false, - "line_number": 1001 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b9b320c5cd52c63f2c7d8df9f7eb8d7ae97ea0c9", - "is_verified": false, - "line_number": 1002 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "94ade2ea50c865df9827f975b66b0ed87f6196b3", - "is_verified": false, - "line_number": 1003 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "399c06fffa9278491e56e25312b94398408888b6", - "is_verified": false, - "line_number": 1004 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f20cde564b4b5821671912b7c6a87f2955fa42e8", - "is_verified": false, - "line_number": 1005 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6f320defd3068726e899c9764628473dfd3552bf", - "is_verified": false, - "line_number": 1006 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2e1374c55dbeb0c445b7cebbcf13b2258776c08b", - "is_verified": false, - "line_number": 1007 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "60d220a965d81b4d93238d90e5f9f6a8cfe4ee1a", - "is_verified": false, - "line_number": 1008 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b6b4a1a8971608d6c5f4612efb7b811612fab847", - "is_verified": false, - "line_number": 1009 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "54d103be76f6e12ddfb2d277d367ce2e78d41c5b", - "is_verified": false, - "line_number": 1010 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "65de6ec76c0fb7685c47bc8c136b9f8e35187a14", - "is_verified": false, - "line_number": 1011 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3e507308114a34a5709c1796bc43132539ecc410", - "is_verified": false, - "line_number": 1012 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6b2d7139a0eb9228a3ee9cce0808e1f8a8790e82", - "is_verified": false, - "line_number": 1013 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7a6e781d3ddf14c6314ee3329b8fec94fb15c29c", - "is_verified": false, - "line_number": 1014 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fee4d49183e2b79df72990acf34d147d86b65df3", - "is_verified": false, - "line_number": 1015 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6f0633cbd3640e2b979a8a1516c9bd394da76fe5", - "is_verified": false, - "line_number": 1016 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "711980892808cca786860a2790796417f526d762", - "is_verified": false, - "line_number": 1017 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "25756983273f8f4a48bb032b07c85104e4fc98cd", - "is_verified": false, - "line_number": 1018 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5726a0328e5579f407bbf03fc3caa06062205ca8", - "is_verified": false, - "line_number": 1019 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e8c6a788cf042a2a2ea8989b33826f1d6423eb29", - "is_verified": false, - "line_number": 1020 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "755577452cdccb63d3e7f1d3176316fe5ef084c8", - "is_verified": false, - "line_number": 1021 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0ec16170fcd97d28c0f5fa919e3c635358935c04", - "is_verified": false, - "line_number": 1022 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0f91ef272eab7567d0f2db99dffc6dbaae2cc084", - "is_verified": false, - "line_number": 1023 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "35e6dad6c44367b5bb860ff5afeb54c8c92cef58", - "is_verified": false, - "line_number": 1024 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "73dcdb9d800fe9776667edb8cde8312a0a768ada", - "is_verified": false, - "line_number": 1025 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b56ea4486eded8635f63a8622a012fb3ee81a3bb", - "is_verified": false, - "line_number": 1026 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b0f4a8c4f6255ea5f66fdb118eba5eeb0829307d", - "is_verified": false, - "line_number": 1027 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "88d9c65e3ce55ba286c8faf8cb105ea6ac39a19b", - "is_verified": false, - "line_number": 1028 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "adc51f3f9a4c42b861f0da4fcc29392bafe2d98e", - "is_verified": false, - "line_number": 1029 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "96b4ea6fc588c3413700405f4d169504240aa637", - "is_verified": false, - "line_number": 1030 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f119079e796b8f2b9d29804daa90877f525cee3a", - "is_verified": false, - "line_number": 1031 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fbf43f6ca18c68df0a478acd09bb465453c9358b", - "is_verified": false, - "line_number": 1032 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d437b203233fd78ffc8630e42a0655f58d2e9f4e", - "is_verified": false, - "line_number": 1033 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6b7f8512ed9b6046476383c6515fc080c63ca508", - "is_verified": false, - "line_number": 1034 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d9f3006796ec72e11dba105176761e360fcf2a3d", - "is_verified": false, - "line_number": 1035 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ad59895b47e8ab566d17c2ef7121c98d469e0559", - "is_verified": false, - "line_number": 1036 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "132f531444b23991fdf797454d8f949e5426ff45", - "is_verified": false, - "line_number": 1037 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "406f3373f38a62e52e8caa4458dfaa68eca20780", - "is_verified": false, - "line_number": 1038 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ce605737729ff998492c8760553bd54393097aac", - "is_verified": false, - "line_number": 1039 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fc42bf79fd0d8179e9f4f9f0190faad588388004", - "is_verified": false, - "line_number": 1040 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "efc0f56dded17fa0c00b58a820fbe74a1e368b63", - "is_verified": false, - "line_number": 1041 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9d450e49c3cbcffcfb559a51d6ab4531f2a645bf", - "is_verified": false, - "line_number": 1042 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8437e864bc114188554fd79b98cfd43f4c588df7", - "is_verified": false, - "line_number": 1043 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "de462d8851d3dc92579a62f39fadecf6b9d6bc22", - "is_verified": false, - "line_number": 1044 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "508fdca9918030fb0b8a8739ba791f611b793112", - "is_verified": false, - "line_number": 1045 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4933bc7d4edeb7116d71e7f1947e5d6ed29760ec", - "is_verified": false, - "line_number": 1046 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4a8bfde12d39966ecc92cc667695767bbdf7366b", - "is_verified": false, - "line_number": 1047 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3dbc1c47b263483e20fa69941a4274cc19f85bc2", - "is_verified": false, - "line_number": 1048 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d1287d92f048a817c6bb27b0993a87aa9560996b", - "is_verified": false, - "line_number": 1049 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "10cb9bc401ea5975fd15188a2b9cc592e513647a", - "is_verified": false, - "line_number": 1050 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f18de35aa597b41bb9d73890f35c8f7704c72ea1", - "is_verified": false, - "line_number": 1051 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "dfe7e4f70a85c9d4d9e5e43b38e6c4afb6af9858", - "is_verified": false, - "line_number": 1052 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d39edd8dd598dfb8918b748d29c25259509675dd", - "is_verified": false, - "line_number": 1053 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5d2721a37cabecbb784a5e45ff9d869e7c90d7f5", - "is_verified": false, - "line_number": 1054 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "60d52adbbee54411db221581b7d93960b772f691", - "is_verified": false, - "line_number": 1055 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "af1320e386741990cf1c7201101f2ae194fc72ca", - "is_verified": false, - "line_number": 1056 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4bbc199707b0d38feb6244d4069391cf4af4b8bb", - "is_verified": false, - "line_number": 1057 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "22023f99a0e352116a61bf566f8af2ab60b5d9c1", - "is_verified": false, - "line_number": 1058 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3f664164c66bb49689d9931436c3d4f57f316eb6", - "is_verified": false, - "line_number": 1059 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9a4a988167abb6a3816d472d4be97cd105a69baf", - "is_verified": false, - "line_number": 1060 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7edf4402503eaf501e23c31ef1306392d5ecacd0", - "is_verified": false, - "line_number": 1061 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "508b4ed03f5a2f09fb22e2641580065ee4c8a372", - "is_verified": false, - "line_number": 1062 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b02f44c26e7091096fa6fcafb832b62869af42a2", - "is_verified": false, - "line_number": 1063 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0f9174e85538561b056727e432773bb69e128278", - "is_verified": false, - "line_number": 1064 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cabc1f10dc737ef7e110172b814966cdad11b159", - "is_verified": false, - "line_number": 1065 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ee5288a3e32b3b55b342ef18051c78ffff012231", - "is_verified": false, - "line_number": 1066 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0a25e259c157bcc1a99d7e001e52b35d0a4ae2b8", - "is_verified": false, - "line_number": 1067 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3c7bdd0b20d6f7c299da33dbb32d99105489f1c4", - "is_verified": false, - "line_number": 1068 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "19b40ca81ef322c1c0028ad1a005654faa9cfe93", - "is_verified": false, - "line_number": 1069 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fc4ff73da4fb03231a38728acf285f405b1b3ce5", - "is_verified": false, - "line_number": 1070 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c4e603285dc95917f8836283bebce03ff4bc11ba", - "is_verified": false, - "line_number": 1071 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e9e498abd308db923d58b1c35ad83467e58a60b3", - "is_verified": false, - "line_number": 1072 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "954161d814c5c2ccf3ce8c3609ebb4157c08b6f7", - "is_verified": false, - "line_number": 1073 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9bcf9c2a4de2db297ac881231955ad39f19a9df1", - "is_verified": false, - "line_number": 1074 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8eafb590298e1d35ed72d88625bd344a427ccc8b", - "is_verified": false, - "line_number": 1075 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "32a3705a4ce42eecec3c45b0bb0a2c36142b6d08", - "is_verified": false, - "line_number": 1076 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5e8a991485e2080c429eab8a5049b3c3bf7c0ba8", - "is_verified": false, - "line_number": 1077 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d9fbae4d79a44395e6eca487062df13d46954053", - "is_verified": false, - "line_number": 1078 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f62a4f64d930b746fbefdad6c48b0d2a2dc07130", - "is_verified": false, - "line_number": 1079 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f7af30387bf7c4ac2cc0b48eef09f350ec43dae8", - "is_verified": false, - "line_number": 1080 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "afb00100d9ca02672c09acc78c7e13b56b049f63", - "is_verified": false, - "line_number": 1081 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "428e0f17cb680f5fc2b3cdc648ef8739b0fc1d87", - "is_verified": false, - "line_number": 1082 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a7846f258d908bca9bdf9120db6b9b370a4143bd", - "is_verified": false, - "line_number": 1083 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "38c581282a5c2d07745c008443cdc545acbf5aca", - "is_verified": false, - "line_number": 1084 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "63f97716fc1f282d6718710c230006611b86be04", - "is_verified": false, - "line_number": 1085 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "57600ce03478249d79dd13c009f7f64b7ae6211c", - "is_verified": false, - "line_number": 1086 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8e96ee931397b82b3f2c330bcfb3cfea3093d5a7", - "is_verified": false, - "line_number": 1087 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c85653058313f125a2438e1cf446cb90bbedd8ed", - "is_verified": false, - "line_number": 1088 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1a54794f5e3a4dd2036cfd120e294e6401f6d227", - "is_verified": false, - "line_number": 1089 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "60f2b36dcf992c96fe61ea001441417f314064ff", - "is_verified": false, - "line_number": 1090 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "939ca981ece9656aebd5b02d02ed33deadb8923b", - "is_verified": false, - "line_number": 1091 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c28c0ae6268f5e6e813f9fe3b119e211473071e6", - "is_verified": false, - "line_number": 1092 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fa66a89cdd91b75a640282d832886514fe6456a1", - "is_verified": false, - "line_number": 1093 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e464c2a1ba37ae51b0f7ff8b3fba06a8ed7108dc", - "is_verified": false, - "line_number": 1094 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8fb023d4933c56bfeb403311ffc3752d2fbc975e", - "is_verified": false, - "line_number": 1095 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8f066fc1693da2a9cfa30bc540bb35f884c62a30", - "is_verified": false, - "line_number": 1096 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "63a7db4c42e5b728324ad5d2c92e6514ab23364a", - "is_verified": false, - "line_number": 1097 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d4b9ba68b048c4c52c65e192dd281c1c203463c0", - "is_verified": false, - "line_number": 1098 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "33e4d896c6a8b4d14cb836f616f03eaafa43018b", - "is_verified": false, - "line_number": 1099 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1a5b72368ecddce420d879781be813c19475c1be", - "is_verified": false, - "line_number": 1100 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0106004ab89b24991e5e01849276a2ed348d1194", - "is_verified": false, - "line_number": 1101 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "54ede800e24d999c54ce14b80d8c56f834d1a570", - "is_verified": false, - "line_number": 1102 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ff58b7f59920c5d3484985e53a686b91d7b183cd", - "is_verified": false, - "line_number": 1103 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "255ac9b7f9fa6a2376b2fc2219ff38f80dc8c655", - "is_verified": false, - "line_number": 1104 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b0b7694dff36d2e9337b1012073d9ab41aec18c6", - "is_verified": false, - "line_number": 1105 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3d675b3354c15f5088cf1581fc9fa052360c8ecf", - "is_verified": false, - "line_number": 1106 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6e11485ed9e411128ab20a54b6d52e4e879e289f", - "is_verified": false, - "line_number": 1107 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "200a78aa828ba2d7cca00e420a85bef9dde6c841", - "is_verified": false, - "line_number": 1108 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "936a30deb66f624c112527914bbe2f09fb1c2ea2", - "is_verified": false, - "line_number": 1109 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "430e0786d83a62119d1ed6bdc8b87efbf7afbc9d", - "is_verified": false, - "line_number": 1110 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f3fd7614d07e21dc15fa385fc2042847610f8259", - "is_verified": false, - "line_number": 1111 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "dddf43eddf77d768ace4901fc5d506ae2c85ec2d", - "is_verified": false, - "line_number": 1112 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ae367707142233fce304a364467337f943952845", - "is_verified": false, - "line_number": 1113 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6b16b9ea707df813fc90c54d7a531cf0f6b754d0", - "is_verified": false, - "line_number": 1114 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cd1dc83b5bd180fb9f5e72361ff34526b2227197", - "is_verified": false, - "line_number": 1115 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2f4400f3ba736cab5d0bf75f249c030724c8d0b7", - "is_verified": false, - "line_number": 1116 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "43d51f653e0a59b1f5988c8b6732b71dc2492bde", - "is_verified": false, - "line_number": 1117 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "32336fe7d0a6638edadafcef1f7355ff5a5043d1", - "is_verified": false, - "line_number": 1118 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4915df89c72bb9de93ba1cf88de251db9ebb05ec", - "is_verified": false, - "line_number": 1119 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3f1343a17f1e3d24a58df03d29a1330994239874", - "is_verified": false, - "line_number": 1120 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a240e2ccfb08d02d3d54ce913d120af2b4a68a19", - "is_verified": false, - "line_number": 1121 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ac1f2ad12e871b6e5818be4e7f23f90f0b655c65", - "is_verified": false, - "line_number": 1122 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3b792af94a90899b8cfb1cc44605d4de5c0eab7a", - "is_verified": false, - "line_number": 1123 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d6d3294546ce3a4df35269a80497b35d3d97851c", - "is_verified": false, - "line_number": 1124 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "04992ccff77891f14f3dca8bb59cc30534ae31f3", - "is_verified": false, - "line_number": 1125 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bbb54a9a3169f76822f3c8de4c5c33c12138a8ed", - "is_verified": false, - "line_number": 1126 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "64419f894e06d7b0ab1236d60034a5410006f422", - "is_verified": false, - "line_number": 1127 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f58a6063b0ce4ccf2630215d7ab442eb3a6cc154", - "is_verified": false, - "line_number": 1128 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "80fa5cbedc3d970f28652338cbd1da179a4b24f5", - "is_verified": false, - "line_number": 1129 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "904d8f8daa11159afe547828d6da112ec785fc9e", - "is_verified": false, - "line_number": 1130 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "62e23442e30718968242cf6397ceaf835e2b6758", - "is_verified": false, - "line_number": 1131 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8ce675cce57b21a3cf664029ff539107da67583b", - "is_verified": false, - "line_number": 1132 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "64098f0a9449c43a8f071d2052c6066940e75ee8", - "is_verified": false, - "line_number": 1133 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "876250d35eaa0e8f788304e6f47bfb9ecf4aa1f4", - "is_verified": false, - "line_number": 1134 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7aac80369e7b76f53ae0de0d94dfbaa21a130d32", - "is_verified": false, - "line_number": 1135 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "65df2537b97ebdb84c0dc6afa37f140811294e57", - "is_verified": false, - "line_number": 1136 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f6ed524b021390fe734f26cac66fcf1e6a6c455e", - "is_verified": false, - "line_number": 1137 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8fdc365a4e50f09aa482d72bba1974df3b6c9859", - "is_verified": false, - "line_number": 1138 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "36890040b0afedd15fdd9eb87459a4165fcbe2a3", - "is_verified": false, - "line_number": 1139 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9df5cbdfba97fabe10d94f771bcd7ca889c87b2d", - "is_verified": false, - "line_number": 1140 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "de65594f00e0098e7ab3312414faf191bbc3e3c1", - "is_verified": false, - "line_number": 1141 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "37247ab05766ecc1ac7fae19a77b31f7116cce38", - "is_verified": false, - "line_number": 1142 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "13d8923244df4b3025c5d2dd405a22a757628f8d", - "is_verified": false, - "line_number": 1143 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9eef15e4a145e31f7c74235731b69dba5207b237", - "is_verified": false, - "line_number": 1144 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "746b63eabaddeed7ab5dbe3b1fe4e41f89e9f21e", - "is_verified": false, - "line_number": 1145 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f9512226d4044bb241d77988dac046b05effb4f3", - "is_verified": false, - "line_number": 1146 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "de168aa5d99ff80498b7552c850db5d42cb425f9", - "is_verified": false, - "line_number": 1147 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2367ab77f144da2b2349cdbfdc4500d429754353", - "is_verified": false, - "line_number": 1148 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d6a619ebb4b2766bce83fa5bfb6118a9d8ba3212", - "is_verified": false, - "line_number": 1149 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "35fe8489533c677b657cfee61474bab7f268a495", - "is_verified": false, - "line_number": 1150 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e58be566894c228cb922e434d34416a473f0dc28", - "is_verified": false, - "line_number": 1151 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "18f33c6db138875913acb6ad887ed80ca3dc317f", - "is_verified": false, - "line_number": 1152 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1e8a66cfa6671b1771e5874f29bfd96e47b4ad76", - "is_verified": false, - "line_number": 1153 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "284301d7ef66a6721a4b76a02c274419de91a437", - "is_verified": false, - "line_number": 1154 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6694d586f66b50c0162e1cff4b1f133e2c8a9423", - "is_verified": false, - "line_number": 1155 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c712802905f08891cac2e68e6d8f5f6d85e4cf60", - "is_verified": false, - "line_number": 1156 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cd5f0c85968b392a77596cb5143de81f6f109bcd", - "is_verified": false, - "line_number": 1157 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e158eb64d577c9904690ff67584f2b0090792139", - "is_verified": false, - "line_number": 1158 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "62cef2983d23c372ffd1175683e2cf0489a0a93c", - "is_verified": false, - "line_number": 1159 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0039a393f63d3b522516a90354354b6477765b06", - "is_verified": false, - "line_number": 1160 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5c91012c71d492f7e5bc5607f71e1d3337562f9b", - "is_verified": false, - "line_number": 1161 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "83fd266255474e467fcc3f1ca61b0371bf6933eb", - "is_verified": false, - "line_number": 1162 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "44dc9bc4f3a32681036d3328bf2e2c298c94c5b3", - "is_verified": false, - "line_number": 1163 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c077db4aab559fcc23cecde6c8dce6f58a86c7ba", - "is_verified": false, - "line_number": 1164 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f2e728ed22184e3a7bf3b34308c53815d811687d", - "is_verified": false, - "line_number": 1165 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9d653c4cd2f63ba627e1f7eb557b793e7eb50f3a", - "is_verified": false, - "line_number": 1166 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "33e0029ea6c1f2989bf2b5b86f6c4acc03fd7b10", - "is_verified": false, - "line_number": 1167 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "139c8a653e6827e2b29b75c31d27eba181977579", - "is_verified": false, - "line_number": 1168 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e34424070b48aeaee9eeeb88a1a928d2ce1f5517", - "is_verified": false, - "line_number": 1169 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c4db39ccd7c06e68ada50b294aa53f947559a99a", - "is_verified": false, - "line_number": 1170 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0636d970e79e781a5159068c6fe7f0411698b596", - "is_verified": false, - "line_number": 1171 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0bc38af13c57dafb7f18b33b86e5bcbe1292bc2e", - "is_verified": false, - "line_number": 1172 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "02d9eabf8b61d1e62425eac9c7b39385e602ddad", - "is_verified": false, - "line_number": 1173 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3ba33420b436dd34da6f45fdbdbb26a87c99e811", - "is_verified": false, - "line_number": 1174 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2965a6a5b73c3edfdc11d9a979bb085546d63d1f", - "is_verified": false, - "line_number": 1175 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8b15da0afbed8313d1daec67d4bca7958949484d", - "is_verified": false, - "line_number": 1176 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4bf0c8b08ddcb81f5ac2457580003197ff4782dd", - "is_verified": false, - "line_number": 1177 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9e3822884cf25511703c4fbfce1ddacc0d19d021", - "is_verified": false, - "line_number": 1178 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "26fd6e63721168b064c7825415fda7da4c17cd36", - "is_verified": false, - "line_number": 1179 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "82db110822969249eff39d4b7e6830ee919c4b8e", - "is_verified": false, - "line_number": 1180 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e81523785f6e5efeb372a665059ab959c7911c37", - "is_verified": false, - "line_number": 1181 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4c8056fa1e16e63e4da13f329a0f0ba8c3d875eb", - "is_verified": false, - "line_number": 1182 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "63a9faac8e9440b425905da27052de51aa69b937", - "is_verified": false, - "line_number": 1183 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e0ad9315e82b5f80b7b02ce12ba3e686c9a637a5", - "is_verified": false, - "line_number": 1184 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "176ca3d77737c23c86a524235e4281df3a64a573", - "is_verified": false, - "line_number": 1185 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e8b4a7abb0c1178809eb5f5703ed43d558083a2d", - "is_verified": false, - "line_number": 1186 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7e0ad9ba810350bcd8da9180615fd964827c14ef", - "is_verified": false, - "line_number": 1187 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "39c3357766171faf88e70eea0dccb00239f273c5", - "is_verified": false, - "line_number": 1188 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d17aa49aceeaf925527404fa57a4e17668de8596", - "is_verified": false, - "line_number": 1189 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2a6b75b5576df53c3219112e7daff1dc142702d1", - "is_verified": false, - "line_number": 1190 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b75fa52e7d8ecfb8e7e9ff3dc2c37b73abcf7e2c", - "is_verified": false, - "line_number": 1191 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c551bfc4af7eb1fd5daa4f05fd58a2d4d65b85fe", - "is_verified": false, - "line_number": 1192 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a8d858cd02dcd5038dc3e76ac76b2da91f8dbccd", - "is_verified": false, - "line_number": 1193 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1bf631baf29fc48072c20ebfdd321964066f9f08", - "is_verified": false, - "line_number": 1194 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c6eb53905cd7e0253f4e69f34295cb6a50f58e08", - "is_verified": false, - "line_number": 1195 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7bbb8b2539588d170a6c26e9f61ae0800f9d8f2d", - "is_verified": false, - "line_number": 1196 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "26caefb3dca46d7afafdcf0010c67b9e9fccc92b", - "is_verified": false, - "line_number": 1197 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2cb19ac1427a96db3d380729bf039e5349ef63be", - "is_verified": false, - "line_number": 1198 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9e2aa480ce341383cbca0c207198d483e20322bd", - "is_verified": false, - "line_number": 1199 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "be742ba9f651b96a51823045433f3a1948d7eced", - "is_verified": false, - "line_number": 1200 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "317bd6bc5bcc732a1db7e57d0371aa9257f8df00", - "is_verified": false, - "line_number": 1201 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7c80c0ebf44179e49cf0e5a3d0408cc76aee83de", - "is_verified": false, - "line_number": 1202 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7858b77e2046951eadc43758c07104d777668eb7", - "is_verified": false, - "line_number": 1203 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "85a09b9fd03c47f1b036cf44c4909bc73ddd6cad", - "is_verified": false, - "line_number": 1204 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1718e46e064b47cec903bad3b0e9d6ef1da2f11b", - "is_verified": false, - "line_number": 1205 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0c1ee8a96d538ba8b4fa8b05db03563fd7ef8973", - "is_verified": false, - "line_number": 1206 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2017b3f2be44d213be17940140c168a5fba7561d", - "is_verified": false, - "line_number": 1207 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b083a5002d8fe4f2a66696aa0814e03ffa6d1837", - "is_verified": false, - "line_number": 1208 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ff42555f72300b656e47db4ed191f5df0ac07560", - "is_verified": false, - "line_number": 1209 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2ef2cf7195a65a890efa0632dd212ef8220aa1c6", - "is_verified": false, - "line_number": 1210 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "69cb36505922753131885b4a08c707f81ac66a47", - "is_verified": false, - "line_number": 1211 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "069b86c3a9114bd673eef998e22656df1fcaddd8", - "is_verified": false, - "line_number": 1212 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "70c8686a1be4b67a602a59a873ddbede2cd4da7e", - "is_verified": false, - "line_number": 1213 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "523d5a3e6d4fbf64c23594663c7e4687ae9c2be3", - "is_verified": false, - "line_number": 1214 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "16e86f176fd3cd4f7a58f0ffb8dc5791f3f95a86", - "is_verified": false, - "line_number": 1215 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ed84afa53dc05329a7991f5bf5cd2cae1fd77ffc", - "is_verified": false, - "line_number": 1216 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f1289b7119566377ed28ab9dd62af0fd09ed9fe2", - "is_verified": false, - "line_number": 1217 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a4f904b0556d1681ef00ea1813f2f94e28b797eb", - "is_verified": false, - "line_number": 1218 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0949c112813b58b0da6912740cf8bcbb85226c34", - "is_verified": false, - "line_number": 1219 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1bbf17622cda5702d35e14ba66df075a7bb57913", - "is_verified": false, - "line_number": 1220 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8e3a03cec08874a64bccc6d6d425f0afe79533a1", - "is_verified": false, - "line_number": 1221 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1aafc9018c54c7198cf74db22feb0319707898b6", - "is_verified": false, - "line_number": 1222 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e7b49f254a6e2de711e659bd28ad158691e30fce", - "is_verified": false, - "line_number": 1223 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fbc11861a047faba2041e2b6c715d8ca60803c8e", - "is_verified": false, - "line_number": 1224 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "44c990c1ce572f1e8f1ab851427e3a42ce71242a", - "is_verified": false, - "line_number": 1225 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4d3640532de6af408ed943d63ed3e3c2689e9c5f", - "is_verified": false, - "line_number": 1226 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a523fffc0ede19e1deeda09652de2b7a018cf8b4", - "is_verified": false, - "line_number": 1227 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4a995d1758da7e7154ba4acbec5b5b403742b7e1", - "is_verified": false, - "line_number": 1228 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "de4be8856b30e21fc713dc10f8988539feea7023", - "is_verified": false, - "line_number": 1229 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "fb1c0866f73c66412d08391f3ce4878af73aa639", - "is_verified": false, - "line_number": 1230 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a702fefff9cdbe1f95ab8827ddec5ba8efc30892", - "is_verified": false, - "line_number": 1231 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "724b47ffa7a9db1bbaf712b3d9d2b76898db0ea5", - "is_verified": false, - "line_number": 1232 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e0f16906358b6b058b6d986929a05521b6901f68", - "is_verified": false, - "line_number": 1233 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4332f528fff4a967c90c89db64aa58e23393bfed", - "is_verified": false, - "line_number": 1234 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "451a10712041218c61b0cc3787311943dab42dc6", - "is_verified": false, - "line_number": 1235 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "6a1be9deb76862f934fd8a9197069f4609ef70b5", - "is_verified": false, - "line_number": 1236 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2b1256a86a2fb02c20dc58e47774d30baed60f62", - "is_verified": false, - "line_number": 1237 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "74d000f3ede09a41df362d509537a2ac5f1fa07b", - "is_verified": false, - "line_number": 1238 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "43f8293d7eda52b663063cd56e5a3e394f193642", - "is_verified": false, - "line_number": 1239 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "51352b84bafc3573024540c543cc95922a764ef0", - "is_verified": false, - "line_number": 1240 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0ece3e42bfed9840f907fa700d5d29f0087985db", - "is_verified": false, - "line_number": 1241 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3b91d6d99ae8c482392adc042654bd076573cd8a", - "is_verified": false, - "line_number": 1242 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ab529305822e1642ed7c7d3acd9ba80dabc55108", - "is_verified": false, - "line_number": 1243 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3cf4744d88fd85b0fcb0fbf0425c5b50eae93b3e", - "is_verified": false, - "line_number": 1244 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "228fe53a555785f979a20a0159c96ef7d8d057c7", - "is_verified": false, - "line_number": 1245 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8d21215aa0a8f29d068ff316fc09ea6ae9e766c7", - "is_verified": false, - "line_number": 1246 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d63d3d63396c5e88f1fd8cdab9116331080cd2e2", - "is_verified": false, - "line_number": 1247 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d4fe6d5f06c2860ed38ebb02079bb2ebfcbfb093", - "is_verified": false, - "line_number": 1248 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5e1d352485a30350ac108f66da7ac3ce62b1ea4f", - "is_verified": false, - "line_number": 1249 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c682e7af6638379e4edf52c36995c3454ea1b149", - "is_verified": false, - "line_number": 1250 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "bb193ef1c9bcbc39ed64689f474af29719df489e", - "is_verified": false, - "line_number": 1251 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "01c34073e2e61552f4fd0ba64139be0ccabcdb8a", - "is_verified": false, - "line_number": 1252 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "cc47b8620102a6216f098eb7f9ea841c3c2a5f22", - "is_verified": false, - "line_number": 1253 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8f070c859fe84c5502e45b84a274308bbc0a7744", - "is_verified": false, - "line_number": 1254 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5f3061dc64135be12c1eaef23ab8e02f1826f24d", - "is_verified": false, - "line_number": 1255 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "9238be5963618c3501e919ebd4c13992a4bea3b4", - "is_verified": false, - "line_number": 1256 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "68c1365f209fa103e65c4da375b42d5656575940", - "is_verified": false, - "line_number": 1257 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "384be6402a8d31d62cb35fefaec77b06c8211f59", - "is_verified": false, - "line_number": 1258 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "360329c0a8cb6053168e61758688b85104fc86ff", - "is_verified": false, - "line_number": 1259 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7cd87f59db950306302a74b81e8f926df1577397", - "is_verified": false, - "line_number": 1260 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "553b2380d863621a9e4ab7c7a97fdec425ebab25", - "is_verified": false, - "line_number": 1261 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "43562265e7cf90c28221c2b7dbfcafa8f62843dc", - "is_verified": false, - "line_number": 1262 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ed7e495370ef7882b13866c332dff00ef7c361a6", - "is_verified": false, - "line_number": 1263 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7123453c9f62fc6c33951aa2595f1714b23d583a", - "is_verified": false, - "line_number": 1264 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e941c0eb1694570c999ca3fe548f76f6daaca83c", - "is_verified": false, - "line_number": 1265 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "85018e48b287ca7323192ff38ebe9411e61b38e2", - "is_verified": false, - "line_number": 1266 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "814d7edca30e0262ab0b07c6baf47d20738c823b", - "is_verified": false, - "line_number": 1267 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5dca59fe14f949e763116aef3968af2662926895", - "is_verified": false, - "line_number": 1268 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "ee86abd29ecfab79519c1efc033546d2c477477f", - "is_verified": false, - "line_number": 1269 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5878ed0ebded462f8d2461fe18061aa18d1000fd", - "is_verified": false, - "line_number": 1270 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4dd683cc3993e43d00b1b5f9e4e57895bb56e8e5", - "is_verified": false, - "line_number": 1271 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "a8a20da925fd5126d24df7d8baf68ac1fa23a184", - "is_verified": false, - "line_number": 1272 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "137f68b2d3f03ddd81ed8602ff19218c71df55fb", - "is_verified": false, - "line_number": 1273 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b32f2f31a868ddf0e3f013465c72527f62057e44", - "is_verified": false, - "line_number": 1274 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f5425542a9e9183a33dd16d559c92182f35f44a8", - "is_verified": false, - "line_number": 1275 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "77e8234c8ff852ec820384cd8f9284cde00e34a9", - "is_verified": false, - "line_number": 1276 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "be6e0ac8ab7d8ac8d7f7a4fc86b123392c09374e", - "is_verified": false, - "line_number": 1277 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3063130919857912b6373c6182853095d60ca18b", - "is_verified": false, - "line_number": 1278 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "607c9f8efafb2de11157fefd103f9f1cda4f347b", - "is_verified": false, - "line_number": 1279 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "2c301b0126a15e8150d92a84d8a49ab1eb9b4282", - "is_verified": false, - "line_number": 1280 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "84737ddb75ed5806c645ba66e122402be971389a", - "is_verified": false, - "line_number": 1281 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5a9adaee2ecb6e99992aa263eda966061c9acac0", - "is_verified": false, - "line_number": 1282 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0c09b49e14a5a35d3f26420994f8b786035166e6", - "is_verified": false, - "line_number": 1283 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0ef06e9fe84d92197ae053067b3f3d5051070690", - "is_verified": false, - "line_number": 1284 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b249743c201079e983e03d0afeb3c140342fc9d0", - "is_verified": false, - "line_number": 1285 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "82d624e2d36bf5346e60dd14806ff782bb2a4334", - "is_verified": false, - "line_number": 1286 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "88850db69d81a7ece67fb1d9b286c2d951b70819", - "is_verified": false, - "line_number": 1287 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "e49afb46bf458312000f8f9660ae81ff47bdc199", - "is_verified": false, - "line_number": 1288 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1cbdad16e84903fc3b9b6388a089a067dea2a3d2", - "is_verified": false, - "line_number": 1289 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "82feda736f248ac86d376891de516d9d1824a27c", - "is_verified": false, - "line_number": 1290 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "4a71f468c1364aff801b9120b1f5d529078048e9", - "is_verified": false, - "line_number": 1291 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f091998ff0fee46909f88aa7fd4f3cc73a3d3c9a", - "is_verified": false, - "line_number": 1292 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "29eaffa6f6f8a37758a5f7b32907b3dc5b691896", - "is_verified": false, - "line_number": 1293 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "44f681b1a58ce0c6df53676cc0808013e97ea9f4", - "is_verified": false, - "line_number": 1294 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "962dfd74b7253ac6cd612a6e748f2e95efb79f51", - "is_verified": false, - "line_number": 1295 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c86ef7132a2306cf87224e55cb204e6d2e8e7828", - "is_verified": false, - "line_number": 1296 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c4eb42c72ecfdf7810202a43d54548f7d2bff62d", - "is_verified": false, - "line_number": 1297 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "19383a628b845b1cbb1c0444832b0afbe8ab5064", - "is_verified": false, - "line_number": 1298 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b34bf28a1f7465a72772787a147d434d923c8d1b", - "is_verified": false, - "line_number": 1299 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "288ba78781c2ed007a423cb65cb1bf2306c3fd95", - "is_verified": false, - "line_number": 1300 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f3ceb3cc25a1228a6c53b4e215d7568d36e757a6", - "is_verified": false, - "line_number": 1301 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "87996bb1e32b4a0ecc22ac1d13cea8e0190b350b", - "is_verified": false, - "line_number": 1302 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "790704b8f93fe5aca8ac2ecfcb68f1584dad2647", - "is_verified": false, - "line_number": 1303 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "86223a1c42e86aae0a1ed4fa7d40eb2d059c4dd5", - "is_verified": false, - "line_number": 1304 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1673e79621b9dddf3b29a9b1ddf8d2ec0aad4bdc", - "is_verified": false, - "line_number": 1305 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "35b29b6e62d70ae4822318a19d0a46658eddd34f", - "is_verified": false, - "line_number": 1306 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b3cb65216294e3c0b3981e2db721954bafc3b23a", - "is_verified": false, - "line_number": 1307 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5dbca02e62ce0d208d12a1da12ba317344d8c6cc", - "is_verified": false, - "line_number": 1308 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "83acef9b2863c05447dea16c378025f007bc8c34", - "is_verified": false, - "line_number": 1309 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "524ef34b587ca7240673b9607b4314f3f37cd2a8", - "is_verified": false, - "line_number": 1310 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c76948814be7ef0455d6d9ff65aeae688b7bec24", - "is_verified": false, - "line_number": 1311 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5604fd630dabf095466a6c854750348059dbb1aa", - "is_verified": false, - "line_number": 1312 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "0b5772a512bb087fa1d6e34a062c7eec75f6e744", - "is_verified": false, - "line_number": 1313 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "7d3fa248843c7c76c909ee18b0dd773bbb5741e7", - "is_verified": false, - "line_number": 1314 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d7d16ac0dbd0bb5e98c6cb1d8508ff0132bbcbb0", - "is_verified": false, - "line_number": 1315 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d33b30cdcf982839a7cb6ae4e04b74deb2bd8f28", - "is_verified": false, - "line_number": 1316 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "281ca8a981dae1cebcb05b90cde4c895f3c59525", - "is_verified": false, - "line_number": 1317 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "712b5a91ad8f25eaaae3afccd7b41c6215102f70", - "is_verified": false, - "line_number": 1318 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "5fbc83376379b2201ae51f28039f87cb1ca14649", - "is_verified": false, - "line_number": 1319 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "d7497697fc350ef28cc0682526233a7846bfbf7f", - "is_verified": false, - "line_number": 1320 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "3f3d0b8308dfa23ce4c75abcfdd3840cab33de8b", - "is_verified": false, - "line_number": 1321 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "71a4936bbf172bf22c55b532a505a2c33f04ef2a", - "is_verified": false, - "line_number": 1322 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "f76a3c0087070143222761d33c9496d10ec5645a", - "is_verified": false, - "line_number": 1323 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "b8e837e18bc28489da6d38ac38370bd4a7757770", - "is_verified": false, - "line_number": 1324 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "af90bf5453dacd36dd205811a40eda42d5496cb5", - "is_verified": false, - "line_number": 1325 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "1fd5a47605b1192ee40beb9203beaafe8e53e13c", - "is_verified": false, - "line_number": 1326 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "c286938c2542589cd0fbed6acb6326d3c9efeb77", - "is_verified": false, - "line_number": 1327 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "73cfd5a17466838726c63386a3e5cccdf722a9d8", - "is_verified": false, - "line_number": 1328 - }, - { - "type": "Hex High Entropy String", - "filename": "docs/.i18n/zh-CN.tm.jsonl", - "hashed_secret": "8bb0680522ae015a5b71c1e7d24ec4641960c322", - "is_verified": false, - "line_number": 1329 - } - ], - "docs/brave-search.md": [ - { - "type": "Secret Keyword", - "filename": "docs/brave-search.md", - "hashed_secret": "491d458f895b9213facb2ee9375b1b044eaea3ac", - "is_verified": false, - "line_number": 27 - } - ], - "docs/channels/bluebubbles.md": [ - { - "type": "Secret Keyword", - "filename": "docs/channels/bluebubbles.md", - "hashed_secret": "555da20df20d4172e00f1b73d7c3943802055270", - "is_verified": false, - "line_number": 37 - } - ], - "docs/channels/feishu.md": [ - { - "type": "Secret Keyword", - "filename": "docs/channels/feishu.md", - "hashed_secret": "b60d121b438a380c343d5ec3c2037564b82ffef3", - "is_verified": false, - "line_number": 187 - }, - { - "type": "Secret Keyword", - "filename": "docs/channels/feishu.md", - "hashed_secret": "186154712b2d5f6791d85b9a0987b98fa231779c", - "is_verified": false, - "line_number": 435 - } - ], - "docs/channels/irc.md": [ - { - "type": "Secret Keyword", - "filename": "docs/channels/irc.md", - "hashed_secret": "d54831b8e4b461d85e32ea82156d2fb5ce5cb624", - "is_verified": false, - "line_number": 191 - } - ], - "docs/channels/line.md": [ - { - "type": "Secret Keyword", - "filename": "docs/channels/line.md", - "hashed_secret": "83661b43df128631f891767fbfc5b049af3dce86", - "is_verified": false, - "line_number": 61 - } - ], - "docs/channels/matrix.md": [ - { - "type": "Secret Keyword", - "filename": "docs/channels/matrix.md", - "hashed_secret": "45d676e7c6ab44cf4b8fa366ef2d8fccd3e6d6e6", - "is_verified": false, - "line_number": 60 - } - ], - "docs/channels/nextcloud-talk.md": [ - { - "type": "Secret Keyword", - "filename": "docs/channels/nextcloud-talk.md", - "hashed_secret": "76ed0a056aa77060de25754586440cff390791d0", - "is_verified": false, - "line_number": 56 - } - ], - "docs/channels/nostr.md": [ - { - "type": "Secret Keyword", - "filename": "docs/channels/nostr.md", - "hashed_secret": "edeb23e25a619c434d22bb7f1c3ca4841166b4e8", - "is_verified": false, - "line_number": 67 - } - ], - "docs/channels/slack.md": [ - { - "type": "Secret Keyword", - "filename": "docs/channels/slack.md", - "hashed_secret": "3f4800fb7c1fb79a9a48bfd562d90bc6b2e2b718", - "is_verified": false, - "line_number": 104 - } - ], - "docs/channels/twitch.md": [ - { - "type": "Secret Keyword", - "filename": "docs/channels/twitch.md", - "hashed_secret": "0d1ba0da3e84e54f29846c93c43182eede365858", - "is_verified": false, - "line_number": 138 - }, - { - "type": "Secret Keyword", - "filename": "docs/channels/twitch.md", - "hashed_secret": "7cb4c5b8b81e266d08d4f106799af98d748bceb9", - "is_verified": false, - "line_number": 324 - } - ], - "docs/concepts/memory.md": [ - { - "type": "Secret Keyword", - "filename": "docs/concepts/memory.md", - "hashed_secret": "39d711243bfcee9fec8299b204e1aa9c3430fa12", - "is_verified": false, - "line_number": 281 - }, - { - "type": "Secret Keyword", - "filename": "docs/concepts/memory.md", - "hashed_secret": "1a8abbf465c52363ab4c9c6ad945b8e857cbea55", - "is_verified": false, - "line_number": 305 - }, - { - "type": "Secret Keyword", - "filename": "docs/concepts/memory.md", - "hashed_secret": "b9f640d6095b9f6b5a65983f7b76dbbb254e0044", - "is_verified": false, - "line_number": 706 - } - ], - "docs/concepts/model-providers.md": [ - { - "type": "Secret Keyword", - "filename": "docs/concepts/model-providers.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 178 - }, - { - "type": "Secret Keyword", - "filename": "docs/concepts/model-providers.md", - "hashed_secret": "6a4a6c8f2406f4f0843a0a1aae6a320f92f9d6ae", - "is_verified": false, - "line_number": 274 - }, - { - "type": "Secret Keyword", - "filename": "docs/concepts/model-providers.md", - "hashed_secret": "ef83ad68b9b66e008727b7c417c6a8f618b5177e", - "is_verified": false, - "line_number": 305 - } - ], - "docs/gateway/configuration-examples.md": [ - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-examples.md", - "hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281", - "is_verified": false, - "line_number": 57 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-examples.md", - "hashed_secret": "b6f56e5e92078ed7c078c46fbfeedcbe5719bc25", - "is_verified": false, - "line_number": 59 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-examples.md", - "hashed_secret": "22af290a1a3d5e941193a41a3d3a9e4ca8da5e27", - "is_verified": false, - "line_number": 332 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-examples.md", - "hashed_secret": "c1e6ee547fd492df1441ac492e8bb294974712bd", - "is_verified": false, - "line_number": 431 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-examples.md", - "hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209", - "is_verified": false, - "line_number": 596 - } - ], - "docs/gateway/configuration-reference.md": [ - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-reference.md", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 149 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-reference.md", - "hashed_secret": "1188d5a8ed7edcff5144a9472af960243eacf12e", - "is_verified": false, - "line_number": 1267 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-reference.md", - "hashed_secret": "bde4db9b4c3be4049adc3b9a69851d7c35119770", - "is_verified": false, - "line_number": 1283 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-reference.md", - "hashed_secret": "7f8aaf142ce0552c260f2e546dda43ddd7c9aef3", - "is_verified": false, - "line_number": 1461 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-reference.md", - "hashed_secret": "22af290a1a3d5e941193a41a3d3a9e4ca8da5e27", - "is_verified": false, - "line_number": 1603 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-reference.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 1631 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-reference.md", - "hashed_secret": "c1e6ee547fd492df1441ac492e8bb294974712bd", - "is_verified": false, - "line_number": 1862 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-reference.md", - "hashed_secret": "45d676e7c6ab44cf4b8fa366ef2d8fccd3e6d6e6", - "is_verified": false, - "line_number": 1966 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-reference.md", - "hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281", - "is_verified": false, - "line_number": 2202 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration-reference.md", - "hashed_secret": "b6f56e5e92078ed7c078c46fbfeedcbe5719bc25", - "is_verified": false, - "line_number": 2204 - } - ], - "docs/gateway/configuration.md": [ - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration.md", - "hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281", - "is_verified": false, - "line_number": 434 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/configuration.md", - "hashed_secret": "b6f56e5e92078ed7c078c46fbfeedcbe5719bc25", - "is_verified": false, - "line_number": 435 - } - ], - "docs/gateway/local-models.md": [ - { - "type": "Secret Keyword", - "filename": "docs/gateway/local-models.md", - "hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209", - "is_verified": false, - "line_number": 34 - }, - { - "type": "Secret Keyword", - "filename": "docs/gateway/local-models.md", - "hashed_secret": "49fd535e63175a827aab3eff9ac58a9e82460ac9", - "is_verified": false, - "line_number": 124 - } - ], - "docs/gateway/tailscale.md": [ - { - "type": "Secret Keyword", - "filename": "docs/gateway/tailscale.md", - "hashed_secret": "9cb0dc5383312aa15b9dc6745645bde18ff5ade9", - "is_verified": false, - "line_number": 81 - } - ], - "docs/help/environment.md": [ - { - "type": "Secret Keyword", - "filename": "docs/help/environment.md", - "hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281", - "is_verified": false, - "line_number": 31 - }, - { - "type": "Secret Keyword", - "filename": "docs/help/environment.md", - "hashed_secret": "b6f56e5e92078ed7c078c46fbfeedcbe5719bc25", - "is_verified": false, - "line_number": 33 - } - ], - "docs/help/faq.md": [ - { - "type": "Secret Keyword", - "filename": "docs/help/faq.md", - "hashed_secret": "491d458f895b9213facb2ee9375b1b044eaea3ac", - "is_verified": false, - "line_number": 1412 - }, - { - "type": "Secret Keyword", - "filename": "docs/help/faq.md", - "hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281", - "is_verified": false, - "line_number": 1689 - }, - { - "type": "Secret Keyword", - "filename": "docs/help/faq.md", - "hashed_secret": "b6f56e5e92078ed7c078c46fbfeedcbe5719bc25", - "is_verified": false, - "line_number": 1690 - }, - { - "type": "Secret Keyword", - "filename": "docs/help/faq.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 2118 - }, - { - "type": "Secret Keyword", - "filename": "docs/help/faq.md", - "hashed_secret": "45d676e7c6ab44cf4b8fa366ef2d8fccd3e6d6e6", - "is_verified": false, - "line_number": 2398 - } - ], - "docs/install/macos-vm.md": [ - { - "type": "Secret Keyword", - "filename": "docs/install/macos-vm.md", - "hashed_secret": "8dd3bcd07c9ee927e6921c98b4dc6e94e2cc10a9", - "is_verified": false, - "line_number": 217 - } - ], - "docs/nodes/talk.md": [ - { - "type": "Secret Keyword", - "filename": "docs/nodes/talk.md", - "hashed_secret": "1188d5a8ed7edcff5144a9472af960243eacf12e", - "is_verified": false, - "line_number": 58 - } - ], - "docs/perplexity.md": [ - { - "type": "Secret Keyword", - "filename": "docs/perplexity.md", - "hashed_secret": "6b26c117c66a0c030e239eef595c1e18865132a8", - "is_verified": false, - "line_number": 36 - } - ], - "docs/plugins/voice-call.md": [ - { - "type": "Secret Keyword", - "filename": "docs/plugins/voice-call.md", - "hashed_secret": "cb46980ce5532f18440dff4bbbe097896a8c08c8", - "is_verified": false, - "line_number": 239 - } - ], - "docs/providers/anthropic.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/anthropic.md", - "hashed_secret": "c7a8c334eef5d1749fface7d42c66f9ae5e8cf36", - "is_verified": false, - "line_number": 33 - } - ], - "docs/providers/claude-max-api-proxy.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/claude-max-api-proxy.md", - "hashed_secret": "b5c2827eb65bf13b87130e7e3c424ba9ff07cd67", - "is_verified": false, - "line_number": 80 - } - ], - "docs/providers/glm.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/glm.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 24 - } - ], - "docs/providers/litellm.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/litellm.md", - "hashed_secret": "b907cadbe5a060ca6c6b78fee4c1953f34c64c32", - "is_verified": false, - "line_number": 40 - }, - { - "type": "Secret Keyword", - "filename": "docs/providers/litellm.md", - "hashed_secret": "651702a4fa521c0c493a3171cfba79c3c49eeaec", - "is_verified": false, - "line_number": 52 - } - ], - "docs/providers/minimax.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/minimax.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 71 - }, - { - "type": "Secret Keyword", - "filename": "docs/providers/minimax.md", - "hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209", - "is_verified": false, - "line_number": 140 - } - ], - "docs/providers/moonshot.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/moonshot.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 43 - } - ], - "docs/providers/nvidia.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/nvidia.md", - "hashed_secret": "2083c49ad8d63838a4d18f1de0c419f06eb464db", - "is_verified": false, - "line_number": 18 - } - ], - "docs/providers/ollama.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/ollama.md", - "hashed_secret": "e774aaeac31c6272107ba89080295e277050fa7c", - "is_verified": false, - "line_number": 33 - } - ], - "docs/providers/openai.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/openai.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 31 - } - ], - "docs/providers/opencode.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/opencode.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 27 - } - ], - "docs/providers/openrouter.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/openrouter.md", - "hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281", - "is_verified": false, - "line_number": 24 - } - ], - "docs/providers/synthetic.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/synthetic.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 33 - } - ], - "docs/providers/venice.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/venice.md", - "hashed_secret": "0b1b9301d9cd541620de4e3865d4a8f54f42fa89", - "is_verified": false, - "line_number": 55 - }, - { - "type": "Secret Keyword", - "filename": "docs/providers/venice.md", - "hashed_secret": "c179fe46776696372a90218532dc0d67267f2f04", - "is_verified": false, - "line_number": 236 - } - ], - "docs/providers/vllm.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/vllm.md", - "hashed_secret": "6a4a6c8f2406f4f0843a0a1aae6a320f92f9d6ae", - "is_verified": false, - "line_number": 26 - } - ], - "docs/providers/xiaomi.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/xiaomi.md", - "hashed_secret": "6d9c68c603e465077bdd49c62347fe54717f83a3", - "is_verified": false, - "line_number": 34 - }, - { - "type": "Secret Keyword", - "filename": "docs/providers/xiaomi.md", - "hashed_secret": "2369ac9988d706e53899168280d126c81c33bcd2", - "is_verified": false, - "line_number": 42 - } - ], - "docs/providers/zai.md": [ - { - "type": "Secret Keyword", - "filename": "docs/providers/zai.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 27 - } - ], - "docs/tools/browser.md": [ - { - "type": "Basic Auth Credentials", - "filename": "docs/tools/browser.md", - "hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684", - "is_verified": false, - "line_number": 140 - } - ], - "docs/tools/firecrawl.md": [ - { - "type": "Secret Keyword", - "filename": "docs/tools/firecrawl.md", - "hashed_secret": "674397e2c0c2faaa85961c708d2a96a7cc7af217", - "is_verified": false, - "line_number": 29 - } - ], - "docs/tools/skills-config.md": [ - { - "type": "Secret Keyword", - "filename": "docs/tools/skills-config.md", - "hashed_secret": "c1e6ee547fd492df1441ac492e8bb294974712bd", - "is_verified": false, - "line_number": 29 - } - ], - "docs/tools/skills.md": [ - { - "type": "Secret Keyword", - "filename": "docs/tools/skills.md", - "hashed_secret": "c1e6ee547fd492df1441ac492e8bb294974712bd", - "is_verified": false, - "line_number": 198 - } - ], - "docs/tools/web.md": [ - { - "type": "Secret Keyword", - "filename": "docs/tools/web.md", - "hashed_secret": "6b26c117c66a0c030e239eef595c1e18865132a8", - "is_verified": false, - "line_number": 62 - }, - { - "type": "Secret Keyword", - "filename": "docs/tools/web.md", - "hashed_secret": "96c682c88ed551f22fe76d206c2dfb7df9221ad9", - "is_verified": false, - "line_number": 113 - }, - { - "type": "Secret Keyword", - "filename": "docs/tools/web.md", - "hashed_secret": "491d458f895b9213facb2ee9375b1b044eaea3ac", - "is_verified": false, - "line_number": 161 - }, - { - "type": "Secret Keyword", - "filename": "docs/tools/web.md", - "hashed_secret": "674397e2c0c2faaa85961c708d2a96a7cc7af217", - "is_verified": false, - "line_number": 235 - } - ], - "docs/tts.md": [ - { - "type": "Secret Keyword", - "filename": "docs/tts.md", - "hashed_secret": "bde4db9b4c3be4049adc3b9a69851d7c35119770", - "is_verified": false, - "line_number": 95 - }, - { - "type": "Secret Keyword", - "filename": "docs/tts.md", - "hashed_secret": "1188d5a8ed7edcff5144a9472af960243eacf12e", - "is_verified": false, - "line_number": 100 - } - ], - "docs/zh-CN/brave-search.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/brave-search.md", - "hashed_secret": "491d458f895b9213facb2ee9375b1b044eaea3ac", - "is_verified": false, - "line_number": 34 - } - ], - "docs/zh-CN/channels/bluebubbles.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/channels/bluebubbles.md", - "hashed_secret": "555da20df20d4172e00f1b73d7c3943802055270", - "is_verified": false, - "line_number": 43 - } - ], - "docs/zh-CN/channels/feishu.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/channels/feishu.md", - "hashed_secret": "b60d121b438a380c343d5ec3c2037564b82ffef3", - "is_verified": false, - "line_number": 195 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/channels/feishu.md", - "hashed_secret": "186154712b2d5f6791d85b9a0987b98fa231779c", - "is_verified": false, - "line_number": 445 - } - ], - "docs/zh-CN/channels/line.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/channels/line.md", - "hashed_secret": "83661b43df128631f891767fbfc5b049af3dce86", - "is_verified": false, - "line_number": 62 - } - ], - "docs/zh-CN/channels/matrix.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/channels/matrix.md", - "hashed_secret": "45d676e7c6ab44cf4b8fa366ef2d8fccd3e6d6e6", - "is_verified": false, - "line_number": 62 - } - ], - "docs/zh-CN/channels/nextcloud-talk.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/channels/nextcloud-talk.md", - "hashed_secret": "76ed0a056aa77060de25754586440cff390791d0", - "is_verified": false, - "line_number": 61 - } - ], - "docs/zh-CN/channels/nostr.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/channels/nostr.md", - "hashed_secret": "edeb23e25a619c434d22bb7f1c3ca4841166b4e8", - "is_verified": false, - "line_number": 74 - } - ], - "docs/zh-CN/channels/slack.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/channels/slack.md", - "hashed_secret": "3f4800fb7c1fb79a9a48bfd562d90bc6b2e2b718", - "is_verified": false, - "line_number": 153 - } - ], - "docs/zh-CN/channels/twitch.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/channels/twitch.md", - "hashed_secret": "0d1ba0da3e84e54f29846c93c43182eede365858", - "is_verified": false, - "line_number": 145 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/channels/twitch.md", - "hashed_secret": "7cb4c5b8b81e266d08d4f106799af98d748bceb9", - "is_verified": false, - "line_number": 330 - } - ], - "docs/zh-CN/concepts/memory.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/concepts/memory.md", - "hashed_secret": "39d711243bfcee9fec8299b204e1aa9c3430fa12", - "is_verified": false, - "line_number": 127 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/concepts/memory.md", - "hashed_secret": "1a8abbf465c52363ab4c9c6ad945b8e857cbea55", - "is_verified": false, - "line_number": 150 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/concepts/memory.md", - "hashed_secret": "b9f640d6095b9f6b5a65983f7b76dbbb254e0044", - "is_verified": false, - "line_number": 398 - } - ], - "docs/zh-CN/concepts/model-providers.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/concepts/model-providers.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 181 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/concepts/model-providers.md", - "hashed_secret": "ef83ad68b9b66e008727b7c417c6a8f618b5177e", - "is_verified": false, - "line_number": 282 - } - ], - "docs/zh-CN/gateway/configuration-examples.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration-examples.md", - "hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281", - "is_verified": false, - "line_number": 64 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration-examples.md", - "hashed_secret": "b6f56e5e92078ed7c078c46fbfeedcbe5719bc25", - "is_verified": false, - "line_number": 66 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration-examples.md", - "hashed_secret": "22af290a1a3d5e941193a41a3d3a9e4ca8da5e27", - "is_verified": false, - "line_number": 329 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration-examples.md", - "hashed_secret": "c1e6ee547fd492df1441ac492e8bb294974712bd", - "is_verified": false, - "line_number": 424 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration-examples.md", - "hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209", - "is_verified": false, - "line_number": 563 - } - ], - "docs/zh-CN/gateway/configuration.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration.md", - "hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281", - "is_verified": false, - "line_number": 289 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration.md", - "hashed_secret": "b6f56e5e92078ed7c078c46fbfeedcbe5719bc25", - "is_verified": false, - "line_number": 291 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration.md", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 1092 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration.md", - "hashed_secret": "1188d5a8ed7edcff5144a9472af960243eacf12e", - "is_verified": false, - "line_number": 1570 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration.md", - "hashed_secret": "bde4db9b4c3be4049adc3b9a69851d7c35119770", - "is_verified": false, - "line_number": 1586 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration.md", - "hashed_secret": "22af290a1a3d5e941193a41a3d3a9e4ca8da5e27", - "is_verified": false, - "line_number": 2398 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 2476 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration.md", - "hashed_secret": "c1e6ee547fd492df1441ac492e8bb294974712bd", - "is_verified": false, - "line_number": 2768 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/configuration.md", - "hashed_secret": "45d676e7c6ab44cf4b8fa366ef2d8fccd3e6d6e6", - "is_verified": false, - "line_number": 2967 - } - ], - "docs/zh-CN/gateway/local-models.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/local-models.md", - "hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209", - "is_verified": false, - "line_number": 41 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/local-models.md", - "hashed_secret": "49fd535e63175a827aab3eff9ac58a9e82460ac9", - "is_verified": false, - "line_number": 131 - } - ], - "docs/zh-CN/gateway/tailscale.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/gateway/tailscale.md", - "hashed_secret": "9cb0dc5383312aa15b9dc6745645bde18ff5ade9", - "is_verified": false, - "line_number": 80 - } - ], - "docs/zh-CN/help/environment.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/help/environment.md", - "hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281", - "is_verified": false, - "line_number": 38 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/help/environment.md", - "hashed_secret": "b6f56e5e92078ed7c078c46fbfeedcbe5719bc25", - "is_verified": false, - "line_number": 40 - } - ], - "docs/zh-CN/help/faq.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/help/faq.md", - "hashed_secret": "491d458f895b9213facb2ee9375b1b044eaea3ac", - "is_verified": false, - "line_number": 1277 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/help/faq.md", - "hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281", - "is_verified": false, - "line_number": 1524 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/help/faq.md", - "hashed_secret": "b6f56e5e92078ed7c078c46fbfeedcbe5719bc25", - "is_verified": false, - "line_number": 1525 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/help/faq.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 1916 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/help/faq.md", - "hashed_secret": "45d676e7c6ab44cf4b8fa366ef2d8fccd3e6d6e6", - "is_verified": false, - "line_number": 2191 - } - ], - "docs/zh-CN/install/macos-vm.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/install/macos-vm.md", - "hashed_secret": "8dd3bcd07c9ee927e6921c98b4dc6e94e2cc10a9", - "is_verified": false, - "line_number": 224 - } - ], - "docs/zh-CN/nodes/talk.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/nodes/talk.md", - "hashed_secret": "1188d5a8ed7edcff5144a9472af960243eacf12e", - "is_verified": false, - "line_number": 65 - } - ], - "docs/zh-CN/perplexity.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/perplexity.md", - "hashed_secret": "6b26c117c66a0c030e239eef595c1e18865132a8", - "is_verified": false, - "line_number": 42 - } - ], - "docs/zh-CN/plugins/voice-call.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/plugins/voice-call.md", - "hashed_secret": "cb46980ce5532f18440dff4bbbe097896a8c08c8", - "is_verified": false, - "line_number": 167 - } - ], - "docs/zh-CN/providers/anthropic.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/anthropic.md", - "hashed_secret": "c7a8c334eef5d1749fface7d42c66f9ae5e8cf36", - "is_verified": false, - "line_number": 40 - } - ], - "docs/zh-CN/providers/claude-max-api-proxy.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/claude-max-api-proxy.md", - "hashed_secret": "b5c2827eb65bf13b87130e7e3c424ba9ff07cd67", - "is_verified": false, - "line_number": 87 - } - ], - "docs/zh-CN/providers/glm.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/glm.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 30 - } - ], - "docs/zh-CN/providers/minimax.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/minimax.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 72 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/minimax.md", - "hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209", - "is_verified": false, - "line_number": 140 - } - ], - "docs/zh-CN/providers/moonshot.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/moonshot.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 47 - } - ], - "docs/zh-CN/providers/ollama.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/ollama.md", - "hashed_secret": "e774aaeac31c6272107ba89080295e277050fa7c", - "is_verified": false, - "line_number": 38 - } - ], - "docs/zh-CN/providers/openai.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/openai.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 37 - } - ], - "docs/zh-CN/providers/opencode.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/opencode.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 32 - } - ], - "docs/zh-CN/providers/openrouter.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/openrouter.md", - "hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281", - "is_verified": false, - "line_number": 30 - } - ], - "docs/zh-CN/providers/synthetic.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/synthetic.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 39 - } - ], - "docs/zh-CN/providers/venice.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/venice.md", - "hashed_secret": "0b1b9301d9cd541620de4e3865d4a8f54f42fa89", - "is_verified": false, - "line_number": 62 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/venice.md", - "hashed_secret": "c179fe46776696372a90218532dc0d67267f2f04", - "is_verified": false, - "line_number": 243 - } - ], - "docs/zh-CN/providers/xiaomi.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/xiaomi.md", - "hashed_secret": "6d9c68c603e465077bdd49c62347fe54717f83a3", - "is_verified": false, - "line_number": 38 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/xiaomi.md", - "hashed_secret": "2369ac9988d706e53899168280d126c81c33bcd2", - "is_verified": false, - "line_number": 46 - } - ], - "docs/zh-CN/providers/zai.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/providers/zai.md", - "hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0", - "is_verified": false, - "line_number": 32 - } - ], - "docs/zh-CN/tools/browser.md": [ - { - "type": "Basic Auth Credentials", - "filename": "docs/zh-CN/tools/browser.md", - "hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684", - "is_verified": false, - "line_number": 137 - } - ], - "docs/zh-CN/tools/firecrawl.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/tools/firecrawl.md", - "hashed_secret": "674397e2c0c2faaa85961c708d2a96a7cc7af217", - "is_verified": false, - "line_number": 36 - } - ], - "docs/zh-CN/tools/skills-config.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/tools/skills-config.md", - "hashed_secret": "c1e6ee547fd492df1441ac492e8bb294974712bd", - "is_verified": false, - "line_number": 36 - } - ], - "docs/zh-CN/tools/skills.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/tools/skills.md", - "hashed_secret": "c1e6ee547fd492df1441ac492e8bb294974712bd", - "is_verified": false, - "line_number": 183 - } - ], - "docs/zh-CN/tools/web.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/tools/web.md", - "hashed_secret": "6b26c117c66a0c030e239eef595c1e18865132a8", - "is_verified": false, - "line_number": 67 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/tools/web.md", - "hashed_secret": "96c682c88ed551f22fe76d206c2dfb7df9221ad9", - "is_verified": false, - "line_number": 112 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/tools/web.md", - "hashed_secret": "491d458f895b9213facb2ee9375b1b044eaea3ac", - "is_verified": false, - "line_number": 159 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/tools/web.md", - "hashed_secret": "674397e2c0c2faaa85961c708d2a96a7cc7af217", - "is_verified": false, - "line_number": 229 - } - ], - "docs/zh-CN/tts.md": [ - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/tts.md", - "hashed_secret": "bde4db9b4c3be4049adc3b9a69851d7c35119770", - "is_verified": false, - "line_number": 89 - }, - { - "type": "Secret Keyword", - "filename": "docs/zh-CN/tts.md", - "hashed_secret": "1188d5a8ed7edcff5144a9472af960243eacf12e", - "is_verified": false, - "line_number": 94 - } - ], - "extensions/bluebubbles/src/actions.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/actions.test.ts", - "hashed_secret": "789cbe0407840b1c2041cb33452ff60f19bf58cc", - "is_verified": false, - "line_number": 86 - } - ], - "extensions/bluebubbles/src/attachments.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/attachments.test.ts", - "hashed_secret": "789cbe0407840b1c2041cb33452ff60f19bf58cc", - "is_verified": false, - "line_number": 21 - }, - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/attachments.test.ts", - "hashed_secret": "db1530e1ea43af094d3d75b8dbaf19a4a182a318", - "is_verified": false, - "line_number": 85 - }, - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/attachments.test.ts", - "hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", - "is_verified": false, - "line_number": 103 - }, - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/attachments.test.ts", - "hashed_secret": "052f076c732648ab32d2fcde9fe255319bfa0c7b", - "is_verified": false, - "line_number": 215 - } - ], - "extensions/bluebubbles/src/chat.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/chat.test.ts", - "hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", - "is_verified": false, - "line_number": 19 - }, - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/chat.test.ts", - "hashed_secret": "789cbe0407840b1c2041cb33452ff60f19bf58cc", - "is_verified": false, - "line_number": 54 - }, - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/chat.test.ts", - "hashed_secret": "5c5a15a8b0b3e154d77746945e563ba40100681b", - "is_verified": false, - "line_number": 82 - }, - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/chat.test.ts", - "hashed_secret": "faacad0ce4ea1c19b46e128fd79679d37d3d331d", - "is_verified": false, - "line_number": 131 - }, - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/chat.test.ts", - "hashed_secret": "4dcc26a1d99532846fedf1265df4f40f4e0005b8", - "is_verified": false, - "line_number": 227 - }, - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/chat.test.ts", - "hashed_secret": "fd2a721f7be1ee3d691a011affcdb11d0ca365a8", - "is_verified": false, - "line_number": 290 - } - ], - "extensions/bluebubbles/src/monitor.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/monitor.test.ts", - "hashed_secret": "789cbe0407840b1c2041cb33452ff60f19bf58cc", - "is_verified": false, - "line_number": 278 - }, - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/monitor.test.ts", - "hashed_secret": "1ae0af3fe72b3ba394f9fa95a6cffc090d726c23", - "is_verified": false, - "line_number": 552 - } - ], - "extensions/bluebubbles/src/reactions.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/reactions.test.ts", - "hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", - "is_verified": false, - "line_number": 37 - }, - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/reactions.test.ts", - "hashed_secret": "789cbe0407840b1c2041cb33452ff60f19bf58cc", - "is_verified": false, - "line_number": 178 - }, - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/reactions.test.ts", - "hashed_secret": "a4a05c9a6449eb9d6cdac81dd7edc49230e327e6", - "is_verified": false, - "line_number": 209 - }, - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/reactions.test.ts", - "hashed_secret": "a2833da9f0a16f09994754d0a31749cecf8c8c77", - "is_verified": false, - "line_number": 315 - } - ], - "extensions/bluebubbles/src/send.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/send.test.ts", - "hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", - "is_verified": false, - "line_number": 55 - }, - { - "type": "Secret Keyword", - "filename": "extensions/bluebubbles/src/send.test.ts", - "hashed_secret": "faacad0ce4ea1c19b46e128fd79679d37d3d331d", - "is_verified": false, - "line_number": 692 - } - ], - "extensions/bluebubbles/src/targets.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "extensions/bluebubbles/src/targets.test.ts", - "hashed_secret": "a3af2fb0c1e2a30bb038049e1e4b401593af6225", - "is_verified": false, - "line_number": 61 - } - ], - "extensions/bluebubbles/src/targets.ts": [ - { - "type": "Hex High Entropy String", - "filename": "extensions/bluebubbles/src/targets.ts", - "hashed_secret": "a3af2fb0c1e2a30bb038049e1e4b401593af6225", - "is_verified": false, - "line_number": 265 - } - ], - "extensions/copilot-proxy/index.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/copilot-proxy/index.ts", - "hashed_secret": "50f013532a9770a2c2cfdc38b7581dd01df69b70", - "is_verified": false, - "line_number": 9 - } - ], - "extensions/feishu/skills/feishu-doc/SKILL.md": [ - { - "type": "Hex High Entropy String", - "filename": "extensions/feishu/skills/feishu-doc/SKILL.md", - "hashed_secret": "8a2256bca273bb01a4e09ae6555b1e6652d9ff8c", - "is_verified": false, - "line_number": 20 - } - ], - "extensions/feishu/skills/feishu-wiki/SKILL.md": [ - { - "type": "Hex High Entropy String", - "filename": "extensions/feishu/skills/feishu-wiki/SKILL.md", - "hashed_secret": "8a2256bca273bb01a4e09ae6555b1e6652d9ff8c", - "is_verified": false, - "line_number": 40 - } - ], - "extensions/feishu/src/channel.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/feishu/src/channel.test.ts", - "hashed_secret": "8437d84cae482d10a2b9fd3f555d45006979e4be", - "is_verified": false, - "line_number": 21 - } - ], - "extensions/feishu/src/docx.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/feishu/src/docx.test.ts", - "hashed_secret": "f49922d511d666848f250663c4fca84074b856a8", - "is_verified": false, - "line_number": 97 - } - ], - "extensions/feishu/src/media.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/feishu/src/media.test.ts", - "hashed_secret": "f49922d511d666848f250663c4fca84074b856a8", - "is_verified": false, - "line_number": 45 - } - ], - "extensions/feishu/src/reply-dispatcher.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/feishu/src/reply-dispatcher.test.ts", - "hashed_secret": "f49922d511d666848f250663c4fca84074b856a8", - "is_verified": false, - "line_number": 48 - } - ], - "extensions/google-antigravity-auth/index.ts": [ - { - "type": "Base64 High Entropy String", - "filename": "extensions/google-antigravity-auth/index.ts", - "hashed_secret": "709d0f232b6ac4f8d24dec3e4fabfdb14257174f", - "is_verified": false, - "line_number": 14 - } - ], - "extensions/google-gemini-cli-auth/oauth.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/google-gemini-cli-auth/oauth.test.ts", - "hashed_secret": "021343c1f561d7bcbc3b513df45cc3a6baf67b43", - "is_verified": false, - "line_number": 30 - } - ], - "extensions/irc/src/accounts.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/irc/src/accounts.ts", - "hashed_secret": "920f8f5815b381ea692e9e7c2f7119f2b1aa620a", - "is_verified": false, - "line_number": 19 - } - ], - "extensions/irc/src/client.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/irc/src/client.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 8 - }, - { - "type": "Secret Keyword", - "filename": "extensions/irc/src/client.test.ts", - "hashed_secret": "b1cc3814a07fc3d7094f4cc181df7b57b51d165b", - "is_verified": false, - "line_number": 39 - } - ], - "extensions/line/src/channel.startup.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/line/src/channel.startup.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 103 - } - ], - "extensions/matrix/src/matrix/accounts.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/matrix/src/matrix/accounts.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 74 - } - ], - "extensions/matrix/src/matrix/client.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/matrix/src/matrix/client.test.ts", - "hashed_secret": "fe7fcdaea49ece14677acd32374d2f1225819d5c", - "is_verified": false, - "line_number": 13 - }, - { - "type": "Secret Keyword", - "filename": "extensions/matrix/src/matrix/client.test.ts", - "hashed_secret": "3dc927d80543dc0f643940b70d066bd4b4c4b78e", - "is_verified": false, - "line_number": 23 - } - ], - "extensions/matrix/src/matrix/client/storage.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/matrix/src/matrix/client/storage.ts", - "hashed_secret": "7505d64a54e061b7acd54ccd58b49dc43500b635", - "is_verified": false, - "line_number": 8 - } - ], - "extensions/memory-lancedb/config.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/memory-lancedb/config.ts", - "hashed_secret": "ecb252044b5ea0f679ee78ec1a12904739e2904d", - "is_verified": false, - "line_number": 101 - } - ], - "extensions/memory-lancedb/index.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/memory-lancedb/index.test.ts", - "hashed_secret": "ed65c049bb2f78ee4f703b2158ba9cc6ea31fb7e", - "is_verified": false, - "line_number": 71 - } - ], - "extensions/msteams/src/probe.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/msteams/src/probe.test.ts", - "hashed_secret": "1a91d62f7ca67399625a4368a6ab5d4a3baa6073", - "is_verified": false, - "line_number": 35 - } - ], - "extensions/nextcloud-talk/src/accounts.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/nextcloud-talk/src/accounts.ts", - "hashed_secret": "920f8f5815b381ea692e9e7c2f7119f2b1aa620a", - "is_verified": false, - "line_number": 22 - }, - { - "type": "Secret Keyword", - "filename": "extensions/nextcloud-talk/src/accounts.ts", - "hashed_secret": "71f8e7976e4cbc4561c9d62fb283e7f788202acb", - "is_verified": false, - "line_number": 151 - } - ], - "extensions/nextcloud-talk/src/channel.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/nextcloud-talk/src/channel.ts", - "hashed_secret": "71f8e7976e4cbc4561c9d62fb283e7f788202acb", - "is_verified": false, - "line_number": 396 - } - ], - "extensions/nostr/README.md": [ - { - "type": "Secret Keyword", - "filename": "extensions/nostr/README.md", - "hashed_secret": "edeb23e25a619c434d22bb7f1c3ca4841166b4e8", - "is_verified": false, - "line_number": 46 - } - ], - "extensions/nostr/src/channel.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "extensions/nostr/src/channel.test.ts", - "hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13", - "is_verified": false, - "line_number": 48 - }, - { - "type": "Secret Keyword", - "filename": "extensions/nostr/src/channel.test.ts", - "hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13", - "is_verified": false, - "line_number": 48 - } - ], - "extensions/nostr/src/nostr-bus.fuzz.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "extensions/nostr/src/nostr-bus.fuzz.test.ts", - "hashed_secret": "2b4489606a23fb31fcdc849fa7e577ba90f6d39a", - "is_verified": false, - "line_number": 193 - }, - { - "type": "Hex High Entropy String", - "filename": "extensions/nostr/src/nostr-bus.fuzz.test.ts", - "hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13", - "is_verified": false, - "line_number": 194 - }, - { - "type": "Hex High Entropy String", - "filename": "extensions/nostr/src/nostr-bus.fuzz.test.ts", - "hashed_secret": "b84cb0c3925d34496e6c8b0e55b8c1664a438035", - "is_verified": false, - "line_number": 199 - } - ], - "extensions/nostr/src/nostr-bus.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "extensions/nostr/src/nostr-bus.test.ts", - "hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13", - "is_verified": false, - "line_number": 11 - }, - { - "type": "Hex High Entropy String", - "filename": "extensions/nostr/src/nostr-bus.test.ts", - "hashed_secret": "7258e28563f03fb4c5994e8402e6f610d1f0f110", - "is_verified": false, - "line_number": 33 - }, - { - "type": "Hex High Entropy String", - "filename": "extensions/nostr/src/nostr-bus.test.ts", - "hashed_secret": "2b4489606a23fb31fcdc849fa7e577ba90f6d39a", - "is_verified": false, - "line_number": 101 - }, - { - "type": "Hex High Entropy String", - "filename": "extensions/nostr/src/nostr-bus.test.ts", - "hashed_secret": "ef717286343f6da3f4e6f68c6de02a5148a801c4", - "is_verified": false, - "line_number": 106 - }, - { - "type": "Hex High Entropy String", - "filename": "extensions/nostr/src/nostr-bus.test.ts", - "hashed_secret": "98b35fe4c45011220f509ebb5546d3889b55a891", - "is_verified": false, - "line_number": 111 - } - ], - "extensions/nostr/src/nostr-profile.fuzz.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "extensions/nostr/src/nostr-profile.fuzz.test.ts", - "hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13", - "is_verified": false, - "line_number": 11 - } - ], - "extensions/nostr/src/nostr-profile.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "extensions/nostr/src/nostr-profile.test.ts", - "hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13", - "is_verified": false, - "line_number": 14 - } - ], - "extensions/nostr/src/types.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "extensions/nostr/src/types.test.ts", - "hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13", - "is_verified": false, - "line_number": 4 - }, - { - "type": "Secret Keyword", - "filename": "extensions/nostr/src/types.test.ts", - "hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13", - "is_verified": false, - "line_number": 4 - }, - { - "type": "Secret Keyword", - "filename": "extensions/nostr/src/types.test.ts", - "hashed_secret": "3bee216ebc256d692260fc3adc765050508fef5e", - "is_verified": false, - "line_number": 123 - } - ], - "extensions/open-prose/skills/prose/SKILL.md": [ - { - "type": "Basic Auth Credentials", - "filename": "extensions/open-prose/skills/prose/SKILL.md", - "hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684", - "is_verified": false, - "line_number": 204 - } - ], - "extensions/open-prose/skills/prose/state/postgres.md": [ - { - "type": "Secret Keyword", - "filename": "extensions/open-prose/skills/prose/state/postgres.md", - "hashed_secret": "fa9beb99e4029ad5a6615399e7bbae21356086b3", - "is_verified": false, - "line_number": 77 - }, - { - "type": "Basic Auth Credentials", - "filename": "extensions/open-prose/skills/prose/state/postgres.md", - "hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684", - "is_verified": false, - "line_number": 200 - } - ], - "extensions/twitch/src/onboarding.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/twitch/src/onboarding.test.ts", - "hashed_secret": "f2b14f68eb995facb3a1c35287b778d5bd785511", - "is_verified": false, - "line_number": 239 - }, - { - "type": "Secret Keyword", - "filename": "extensions/twitch/src/onboarding.test.ts", - "hashed_secret": "c8d8f8140951794fa875ea2c2d010c4382f36566", - "is_verified": false, - "line_number": 249 - } - ], - "extensions/twitch/src/status.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/twitch/src/status.test.ts", - "hashed_secret": "f2b14f68eb995facb3a1c35287b778d5bd785511", - "is_verified": false, - "line_number": 122 - } - ], - "extensions/voice-call/README.md": [ - { - "type": "Secret Keyword", - "filename": "extensions/voice-call/README.md", - "hashed_secret": "48004f85d79e636cfd408c3baddcb1f0bbdd611a", - "is_verified": false, - "line_number": 49 - } - ], - "extensions/voice-call/src/config.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/voice-call/src/config.test.ts", - "hashed_secret": "62207a469ec2fdcfc7d66b04c2980ac1501acbf0", - "is_verified": false, - "line_number": 129 - } - ], - "extensions/voice-call/src/providers/telnyx.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/voice-call/src/providers/telnyx.test.ts", - "hashed_secret": "62207a469ec2fdcfc7d66b04c2980ac1501acbf0", - "is_verified": false, - "line_number": 30 - } - ], - "extensions/zalo/README.md": [ - { - "type": "Secret Keyword", - "filename": "extensions/zalo/README.md", - "hashed_secret": "f51aaee16a4a756d287f126b99c081b73cba7f15", - "is_verified": false, - "line_number": 41 - } - ], - "extensions/zalo/src/monitor.webhook.test.ts": [ - { - "type": "Secret Keyword", - "filename": "extensions/zalo/src/monitor.webhook.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 40 - } - ], - "skills/1password/references/cli-examples.md": [ - { - "type": "Secret Keyword", - "filename": "skills/1password/references/cli-examples.md", - "hashed_secret": "9dda0987cc3054773a2df97e352d4f64d233ef10", - "is_verified": false, - "line_number": 17 - } - ], - "skills/openai-whisper-api/SKILL.md": [ - { - "type": "Secret Keyword", - "filename": "skills/openai-whisper-api/SKILL.md", - "hashed_secret": "1077361f94d70e1ddcc7c6dc581a489532a81d03", - "is_verified": false, - "line_number": 48 - } - ], - "skills/trello/SKILL.md": [ - { - "type": "Secret Keyword", - "filename": "skills/trello/SKILL.md", - "hashed_secret": "11fa7c37d697f30e6aee828b4426a10f83ab2380", - "is_verified": false, - "line_number": 22 - } - ], - "src/agents/compaction.tool-result-details.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/compaction.tool-result-details.e2e.test.ts", - "hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", - "is_verified": false, - "line_number": 50 - } - ], - "src/agents/memory-search.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/memory-search.e2e.test.ts", - "hashed_secret": "a1b49d68a91fdf9c9217773f3fac988d77fa0f50", - "is_verified": false, - "line_number": 189 - } - ], - "src/agents/minimax-vlm.normalizes-api-key.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/minimax-vlm.normalizes-api-key.e2e.test.ts", - "hashed_secret": "8a8461b67e3fe515f248ac2610fd7b1f4fc3b412", - "is_verified": false, - "line_number": 28 - } - ], - "src/agents/model-auth.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/model-auth.e2e.test.ts", - "hashed_secret": "07a6b9cec637c806195e8aa7e5c0851ab03dc35e", - "is_verified": false, - "line_number": 228 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/model-auth.e2e.test.ts", - "hashed_secret": "21f296583ccd80c5ab9b3330a8b0d47e4a409fb9", - "is_verified": false, - "line_number": 254 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/model-auth.e2e.test.ts", - "hashed_secret": "b65888424ecafcc98bfd803b24817e4dadf821f8", - "is_verified": false, - "line_number": 275 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/model-auth.e2e.test.ts", - "hashed_secret": "77e991e9f56e6fa4ed1a908208048421f1214c07", - "is_verified": false, - "line_number": 296 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/model-auth.e2e.test.ts", - "hashed_secret": "dff6d4ff5dc357cf451d1855ab9cbda562645c9f", - "is_verified": false, - "line_number": 319 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/model-auth.e2e.test.ts", - "hashed_secret": "b43be360db55d89ec6afd74d6ed8f82002fe4982", - "is_verified": false, - "line_number": 374 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/model-auth.e2e.test.ts", - "hashed_secret": "5b850e9dc678446137ff6d905ebd78634d687fdd", - "is_verified": false, - "line_number": 395 - } - ], - "src/agents/model-auth.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/model-auth.ts", - "hashed_secret": "8956265d216d474a080edaa97880d37fc1386f33", - "is_verified": false, - "line_number": 25 - } - ], - "src/agents/models-config.e2e-harness.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/models-config.e2e-harness.ts", - "hashed_secret": "7cf31e8b6cda49f70c31f1f25af05d46f924142d", - "is_verified": false, - "line_number": 110 - } - ], - "src/agents/models-config.fills-missing-provider-apikey-from-env-var.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/models-config.fills-missing-provider-apikey-from-env-var.e2e.test.ts", - "hashed_secret": "fcdd655b11f33ba4327695084a347b2ba192976c", - "is_verified": false, - "line_number": 19 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/models-config.fills-missing-provider-apikey-from-env-var.e2e.test.ts", - "hashed_secret": "3a81eb091f80c845232225be5663d270e90dacb7", - "is_verified": false, - "line_number": 73 - } - ], - "src/agents/models-config.normalizes-gemini-3-ids-preview-google-providers.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/models-config.normalizes-gemini-3-ids-preview-google-providers.e2e.test.ts", - "hashed_secret": "980d02eb9335ae7c9e9984f6c8ad432352a0d2ac", - "is_verified": false, - "line_number": 20 - } - ], - "src/agents/models-config.providers.nvidia.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/models-config.providers.nvidia.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 13 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/models-config.providers.nvidia.test.ts", - "hashed_secret": "be1a7be9d4d5af417882b267f4db6dddc08507bd", - "is_verified": false, - "line_number": 27 - } - ], - "src/agents/models-config.providers.ollama.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/models-config.providers.ollama.e2e.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 37 - } - ], - "src/agents/models-config.providers.qianfan.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/models-config.providers.qianfan.e2e.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 12 - } - ], - "src/agents/models-config.skips-writing-models-json-no-env-token.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/models-config.skips-writing-models-json-no-env-token.e2e.test.ts", - "hashed_secret": "4c7bac93427c83bcc3beeceebfa54f16f801b78f", - "is_verified": false, - "line_number": 100 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/models-config.skips-writing-models-json-no-env-token.e2e.test.ts", - "hashed_secret": "4f2b3ddc953da005a97d825652080fe6eff21520", - "is_verified": false, - "line_number": 113 - } - ], - "src/agents/openai-responses.reasoning-replay.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/openai-responses.reasoning-replay.test.ts", - "hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", - "is_verified": false, - "line_number": 55 - } - ], - "src/agents/pi-embedded-runner.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/pi-embedded-runner.e2e.test.ts", - "hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd", - "is_verified": false, - "line_number": 127 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/pi-embedded-runner.e2e.test.ts", - "hashed_secret": "fcdd655b11f33ba4327695084a347b2ba192976c", - "is_verified": false, - "line_number": 238 - } - ], - "src/agents/pi-embedded-runner/model.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/pi-embedded-runner/model.ts", - "hashed_secret": "e774aaeac31c6272107ba89080295e277050fa7c", - "is_verified": false, - "line_number": 118 - } - ], - "src/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 86 - } - ], - "src/agents/pi-tools.safe-bins.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/pi-tools.safe-bins.e2e.test.ts", - "hashed_secret": "3ea88a727641fd5571b5e126ce87032377be1e7f", - "is_verified": false, - "line_number": 126 - } - ], - "src/agents/sanitize-for-prompt.test.ts": [ - { - "type": "Base64 High Entropy String", - "filename": "src/agents/sanitize-for-prompt.test.ts", - "hashed_secret": "9c62d3aa77c19e170c44b18129f967e2041fda41", - "is_verified": false, - "line_number": 28 - } - ], - "src/agents/skills.build-workspace-skills-prompt.prefers-workspace-skills-managed-skills.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/skills.build-workspace-skills-prompt.prefers-workspace-skills-managed-skills.e2e.test.ts", - "hashed_secret": "7a85f4764bbd6daf1c3545efbbf0f279a6dc0beb", - "is_verified": false, - "line_number": 103 - } - ], - "src/agents/skills.build-workspace-skills-prompt.syncs-merged-skills-into-target-workspace.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/skills.build-workspace-skills-prompt.syncs-merged-skills-into-target-workspace.e2e.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 147 - } - ], - "src/agents/skills.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/skills.e2e.test.ts", - "hashed_secret": "5df3a673d724e8a1eb673a8baf623e183940804d", - "is_verified": false, - "line_number": 250 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/skills.e2e.test.ts", - "hashed_secret": "8921daaa546693e52bc1f9c40bdcf15e816e0448", - "is_verified": false, - "line_number": 277 - } - ], - "src/agents/tools/web-fetch.firecrawl-api-key-normalization.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/tools/web-fetch.firecrawl-api-key-normalization.e2e.test.ts", - "hashed_secret": "9da08ab1e27fe0ae2ba6101aea30edcec02d21a4", - "is_verified": false, - "line_number": 45 - } - ], - "src/agents/tools/web-fetch.ssrf.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/tools/web-fetch.ssrf.e2e.test.ts", - "hashed_secret": "5ce8e9d54c77266fff990194d2219a708c59b76c", - "is_verified": false, - "line_number": 73 - } - ], - "src/agents/tools/web-search.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/tools/web-search.e2e.test.ts", - "hashed_secret": "c8d313eac6d38274ccfc0fa7935c68bd61d5bc2f", - "is_verified": false, - "line_number": 129 - } - ], - "src/agents/tools/web-search.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/tools/web-search.ts", - "hashed_secret": "dfba7aade0868074c2861c98e2a9a92f3178a51b", - "is_verified": false, - "line_number": 97 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/tools/web-search.ts", - "hashed_secret": "71f8e7976e4cbc4561c9d62fb283e7f788202acb", - "is_verified": false, - "line_number": 285 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/tools/web-search.ts", - "hashed_secret": "c4865ff9250aca23b0d98eb079dad70ebec1cced", - "is_verified": false, - "line_number": 295 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/tools/web-search.ts", - "hashed_secret": "527ee41f36386e85fa932ef09471ca017f3c95c8", - "is_verified": false, - "line_number": 298 - } - ], - "src/agents/tools/web-tools.enabled-defaults.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/tools/web-tools.enabled-defaults.e2e.test.ts", - "hashed_secret": "47b249a75ca78fdb578d0f28c33685e27ea82684", - "is_verified": false, - "line_number": 181 - }, - { - "type": "Secret Keyword", - "filename": "src/agents/tools/web-tools.enabled-defaults.e2e.test.ts", - "hashed_secret": "d0ffd81d6d7ad1bc3c365660fe8882480c9a986e", - "is_verified": false, - "line_number": 187 - } - ], - "src/agents/tools/web-tools.fetch.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/agents/tools/web-tools.fetch.e2e.test.ts", - "hashed_secret": "5ce8e9d54c77266fff990194d2219a708c59b76c", - "is_verified": false, - "line_number": 246 - } - ], - "src/auto-reply/reply.directive.directive-behavior.prefers-alias-matches-fuzzy-selection-is-ambiguous.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/auto-reply/reply.directive.directive-behavior.prefers-alias-matches-fuzzy-selection-is-ambiguous.e2e.test.ts", - "hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd", - "is_verified": false, - "line_number": 56 - }, - { - "type": "Secret Keyword", - "filename": "src/auto-reply/reply.directive.directive-behavior.prefers-alias-matches-fuzzy-selection-is-ambiguous.e2e.test.ts", - "hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209", - "is_verified": false, - "line_number": 62 - } - ], - "src/auto-reply/reply.directive.directive-behavior.supports-fuzzy-model-matches-model-directive.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/auto-reply/reply.directive.directive-behavior.supports-fuzzy-model-matches-model-directive.e2e.test.ts", - "hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd", - "is_verified": false, - "line_number": 42 - }, - { - "type": "Secret Keyword", - "filename": "src/auto-reply/reply.directive.directive-behavior.supports-fuzzy-model-matches-model-directive.e2e.test.ts", - "hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209", - "is_verified": false, - "line_number": 149 - } - ], - "src/auto-reply/status.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/auto-reply/status.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 36 - } - ], - "src/browser/bridge-server.auth.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/browser/bridge-server.auth.test.ts", - "hashed_secret": "6af3c121ed4a752936c297cddfb7b00394eabf10", - "is_verified": false, - "line_number": 66 - } - ], - "src/browser/browser-utils.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "src/browser/browser-utils.test.ts", - "hashed_secret": "4e126c049580d66ca1549fa534d95a7263f27f46", - "is_verified": false, - "line_number": 38 - }, - { - "type": "Basic Auth Credentials", - "filename": "src/browser/browser-utils.test.ts", - "hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684", - "is_verified": false, - "line_number": 159 - } - ], - "src/browser/cdp.test.ts": [ - { - "type": "Basic Auth Credentials", - "filename": "src/browser/cdp.test.ts", - "hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684", - "is_verified": false, - "line_number": 186 - } - ], - "src/channels/plugins/plugins-channel.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "src/channels/plugins/plugins-channel.test.ts", - "hashed_secret": "99c962e8c62296bdc9a17f5caf91ce9bb4c7e0e6", - "is_verified": false, - "line_number": 46 - } - ], - "src/cli/program.smoke.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/cli/program.smoke.e2e.test.ts", - "hashed_secret": "8689a958b58e4a6f7da6211e666da8e17651697c", - "is_verified": false, - "line_number": 215 - } - ], - "src/cli/update-cli.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "src/cli/update-cli.test.ts", - "hashed_secret": "e4f91dd323bac5bfc4f60a6e433787671dc2421d", - "is_verified": false, - "line_number": 239 - } - ], - "src/commands/auth-choice.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/commands/auth-choice.e2e.test.ts", - "hashed_secret": "2480500ff391183070fe22ba8665a8be19350833", - "is_verified": false, - "line_number": 454 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/auth-choice.e2e.test.ts", - "hashed_secret": "844ae5308654406d80db6f2b3d0beb07d616f9e1", - "is_verified": false, - "line_number": 487 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/auth-choice.e2e.test.ts", - "hashed_secret": "77e991e9f56e6fa4ed1a908208048421f1214c07", - "is_verified": false, - "line_number": 549 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/auth-choice.e2e.test.ts", - "hashed_secret": "266e955b27b5fc2c2f532e446f2e71c3667a4cd9", - "is_verified": false, - "line_number": 584 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/auth-choice.e2e.test.ts", - "hashed_secret": "1b4d8423b11d32dd0c466428ac81de84a4a9442b", - "is_verified": false, - "line_number": 726 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/auth-choice.e2e.test.ts", - "hashed_secret": "c24e00b94c972ed497d5961212ac96f0dffb4f7a", - "is_verified": false, - "line_number": 798 - } - ], - "src/commands/auth-choice.preferred-provider.ts": [ - { - "type": "Secret Keyword", - "filename": "src/commands/auth-choice.preferred-provider.ts", - "hashed_secret": "c03a8d10174dd7eb2b3288b570a5a74fdd9ae05d", - "is_verified": false, - "line_number": 8 - } - ], - "src/commands/configure.gateway-auth.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/commands/configure.gateway-auth.e2e.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 21 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/configure.gateway-auth.e2e.test.ts", - "hashed_secret": "d5d4cd07616a542891b7ec2d0257b3a24b69856e", - "is_verified": false, - "line_number": 62 - } - ], - "src/commands/daemon-install-helpers.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/commands/daemon-install-helpers.e2e.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 128 - } - ], - "src/commands/doctor-memory-search.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/commands/doctor-memory-search.test.ts", - "hashed_secret": "2e07956ffc9bc4fd624064c40b7495c85d5f1467", - "is_verified": false, - "line_number": 38 - } - ], - "src/commands/model-picker.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/commands/model-picker.e2e.test.ts", - "hashed_secret": "5b924ca5330ede58702a5b0e414207b90fb1aef3", - "is_verified": false, - "line_number": 127 - } - ], - "src/commands/models/list.status.e2e.test.ts": [ - { - "type": "Base64 High Entropy String", - "filename": "src/commands/models/list.status.e2e.test.ts", - "hashed_secret": "d6ae2508a78a232d5378ef24b85ce40cbb4d7ff0", - "is_verified": false, - "line_number": 12 - }, - { - "type": "Base64 High Entropy String", - "filename": "src/commands/models/list.status.e2e.test.ts", - "hashed_secret": "2d8012102440ea97852b3152239218f00579bafa", - "is_verified": false, - "line_number": 19 - }, - { - "type": "Base64 High Entropy String", - "filename": "src/commands/models/list.status.e2e.test.ts", - "hashed_secret": "51848e2be4b461a549218d3167f19c01be6b98b8", - "is_verified": false, - "line_number": 51 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/models/list.status.e2e.test.ts", - "hashed_secret": "51848e2be4b461a549218d3167f19c01be6b98b8", - "is_verified": false, - "line_number": 51 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/models/list.status.e2e.test.ts", - "hashed_secret": "1c1e381bfb72d3b7bfca9437053d9875356680f0", - "is_verified": false, - "line_number": 57 - } - ], - "src/commands/onboard-auth.config-minimax.ts": [ - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-auth.config-minimax.ts", - "hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209", - "is_verified": false, - "line_number": 36 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-auth.config-minimax.ts", - "hashed_secret": "ddcb713196b974770575a9bea5a4e7d46361f8e9", - "is_verified": false, - "line_number": 78 - } - ], - "src/commands/onboard-auth.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-auth.e2e.test.ts", - "hashed_secret": "e184b402822abc549b37689c84e8e0e33c39a1f1", - "is_verified": false, - "line_number": 272 - } - ], - "src/commands/onboard-custom.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-custom.e2e.test.ts", - "hashed_secret": "62e6748c6bb4c4a0f785a28cdd7d41ef212c0091", - "is_verified": false, - "line_number": 238 - } - ], - "src/commands/onboard-non-interactive.provider-auth.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-non-interactive.provider-auth.e2e.test.ts", - "hashed_secret": "fcdd655b11f33ba4327695084a347b2ba192976c", - "is_verified": false, - "line_number": 153 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-non-interactive.provider-auth.e2e.test.ts", - "hashed_secret": "07a6b9cec637c806195e8aa7e5c0851ab03dc35e", - "is_verified": false, - "line_number": 191 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-non-interactive.provider-auth.e2e.test.ts", - "hashed_secret": "77e991e9f56e6fa4ed1a908208048421f1214c07", - "is_verified": false, - "line_number": 234 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-non-interactive.provider-auth.e2e.test.ts", - "hashed_secret": "65547299f940eca3dc839f3eac85e8a78a6deb05", - "is_verified": false, - "line_number": 282 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-non-interactive.provider-auth.e2e.test.ts", - "hashed_secret": "2833d098c110602e4c8d577fbfdb423a9ffd58e9", - "is_verified": false, - "line_number": 304 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-non-interactive.provider-auth.e2e.test.ts", - "hashed_secret": "266e955b27b5fc2c2f532e446f2e71c3667a4cd9", - "is_verified": false, - "line_number": 338 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-non-interactive.provider-auth.e2e.test.ts", - "hashed_secret": "995b80728ee01edb90ddfed07870bbab405df19f", - "is_verified": false, - "line_number": 366 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-non-interactive.provider-auth.e2e.test.ts", - "hashed_secret": "b65888424ecafcc98bfd803b24817e4dadf821f8", - "is_verified": false, - "line_number": 383 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-non-interactive.provider-auth.e2e.test.ts", - "hashed_secret": "62e6748c6bb4c4a0f785a28cdd7d41ef212c0091", - "is_verified": false, - "line_number": 402 - }, - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-non-interactive.provider-auth.e2e.test.ts", - "hashed_secret": "8818d3b7c102fd6775af9e1390e5ed3a128473fb", - "is_verified": false, - "line_number": 447 - } - ], - "src/commands/onboard-non-interactive/api-keys.ts": [ - { - "type": "Secret Keyword", - "filename": "src/commands/onboard-non-interactive/api-keys.ts", - "hashed_secret": "112f3a99b283a4e1788dedd8e0e5d35375c33747", - "is_verified": false, - "line_number": 11 - } - ], - "src/commands/status.update.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "src/commands/status.update.test.ts", - "hashed_secret": "33c76f70af66754ca47d19b17da8dc232e125253", - "is_verified": false, - "line_number": 74 - } - ], - "src/commands/vllm-setup.ts": [ - { - "type": "Secret Keyword", - "filename": "src/commands/vllm-setup.ts", - "hashed_secret": "5b924ca5330ede58702a5b0e414207b90fb1aef3", - "is_verified": false, - "line_number": 60 - } - ], - "src/commands/zai-endpoint-detect.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/commands/zai-endpoint-detect.e2e.test.ts", - "hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd", - "is_verified": false, - "line_number": 24 - } - ], - "src/config/config-misc.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/config-misc.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 62 - } - ], - "src/config/config.env-vars.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/config.env-vars.test.ts", - "hashed_secret": "a24ef9c1a27cac44823571ceef2e8262718eee36", - "is_verified": false, - "line_number": 13 - }, - { - "type": "Secret Keyword", - "filename": "src/config/config.env-vars.test.ts", - "hashed_secret": "29d5f92e9ee44d4854d6dfaeefc3dc27d779fdf3", - "is_verified": false, - "line_number": 19 - }, - { - "type": "Secret Keyword", - "filename": "src/config/config.env-vars.test.ts", - "hashed_secret": "1672b6a1e7956c6a70f45d699aa42a351b1f8b80", - "is_verified": false, - "line_number": 27 - } - ], - "src/config/config.irc.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/config.irc.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 92 - } - ], - "src/config/config.talk-api-key-fallback.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/config.talk-api-key-fallback.test.ts", - "hashed_secret": "bea2f7b64fab8d1d414d0449530b1e088d36d5b1", - "is_verified": false, - "line_number": 33 - } - ], - "src/config/env-preserve-io.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/env-preserve-io.test.ts", - "hashed_secret": "85639f0560fd9bf8704f52e01c5e764c9ed5a6aa", - "is_verified": false, - "line_number": 59 - }, - { - "type": "Secret Keyword", - "filename": "src/config/env-preserve-io.test.ts", - "hashed_secret": "996650087ab48bdb1ca80f0842c97d4fbb6f1c71", - "is_verified": false, - "line_number": 86 - } - ], - "src/config/env-preserve.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/env-preserve.test.ts", - "hashed_secret": "f6067ac4599b1cd5176f34897bb556a1a1eaf049", - "is_verified": false, - "line_number": 6 - }, - { - "type": "Secret Keyword", - "filename": "src/config/env-preserve.test.ts", - "hashed_secret": "5a41c5061e7279cec0566b3ef52cbe042e831192", - "is_verified": false, - "line_number": 7 - }, - { - "type": "Secret Keyword", - "filename": "src/config/env-preserve.test.ts", - "hashed_secret": "53d407242b91f07138abcf30ee0e6b71f304b87f", - "is_verified": false, - "line_number": 19 - }, - { - "type": "Secret Keyword", - "filename": "src/config/env-preserve.test.ts", - "hashed_secret": "c1b24294f00e281605f9dd6a298612e3060062b4", - "is_verified": false, - "line_number": 82 - } - ], - "src/config/env-substitution.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/env-substitution.test.ts", - "hashed_secret": "f2b14f68eb995facb3a1c35287b778d5bd785511", - "is_verified": false, - "line_number": 37 - }, - { - "type": "Secret Keyword", - "filename": "src/config/env-substitution.test.ts", - "hashed_secret": "ec417f567082612f8fd6afafe1abcab831fca840", - "is_verified": false, - "line_number": 68 - }, - { - "type": "Secret Keyword", - "filename": "src/config/env-substitution.test.ts", - "hashed_secret": "520bd69c3eb1646d9a78181ecb4c90c51fdf428d", - "is_verified": false, - "line_number": 69 - }, - { - "type": "Secret Keyword", - "filename": "src/config/env-substitution.test.ts", - "hashed_secret": "f136444bf9b3d01a9f9b772b80ac6bf7b6a43ef0", - "is_verified": false, - "line_number": 227 - } - ], - "src/config/io.write-config.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/io.write-config.test.ts", - "hashed_secret": "13951588fd3325e25ed1e3b116d7009fb221c85e", - "is_verified": false, - "line_number": 65 - } - ], - "src/config/model-alias-defaults.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/model-alias-defaults.test.ts", - "hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd", - "is_verified": false, - "line_number": 66 - } - ], - "src/config/redact-snapshot.test.ts": [ - { - "type": "Base64 High Entropy String", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "3732e17b2d11ed6c64fef02c341958007af154e7", - "is_verified": false, - "line_number": 77 - }, - { - "type": "Secret Keyword", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "3732e17b2d11ed6c64fef02c341958007af154e7", - "is_verified": false, - "line_number": 77 - }, - { - "type": "Secret Keyword", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "7f413afd37447cd321d79286be0f58d7a9875d9b", - "is_verified": false, - "line_number": 89 - }, - { - "type": "Secret Keyword", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "c21afa950dee2a70f3e0f6ffdfbc87f8edb90262", - "is_verified": false, - "line_number": 99 - }, - { - "type": "Secret Keyword", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "83a9937c6de261ffda22304834f30fe6c8f97926", - "is_verified": false, - "line_number": 110 - }, - { - "type": "Secret Keyword", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "87ac76dfc9cba93bead43c191e31bd099a97cc11", - "is_verified": false, - "line_number": 198 - }, - { - "type": "Secret Keyword", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "abb1aabcd0e49019c2873944a40671a80ccd64c7", - "is_verified": false, - "line_number": 309 - }, - { - "type": "Base64 High Entropy String", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "8e22880b4e96bab354e1da6c91d2f58dabde3555", - "is_verified": false, - "line_number": 321 - }, - { - "type": "Secret Keyword", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "8e22880b4e96bab354e1da6c91d2f58dabde3555", - "is_verified": false, - "line_number": 321 - }, - { - "type": "Secret Keyword", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "a9c732e05044a08c760cce7f6d142cd0d35a19e5", - "is_verified": false, - "line_number": 375 - }, - { - "type": "Secret Keyword", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "50843dd5651cfafbe7c5611c1eed195c63e6e3fd", - "is_verified": false, - "line_number": 691 - }, - { - "type": "Secret Keyword", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "927e7cdedcb8f71af399a49fb90a381df8b8df28", - "is_verified": false, - "line_number": 808 - }, - { - "type": "Secret Keyword", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "1996cc327bd39dad69cd8feb24250dafd51e7c08", - "is_verified": false, - "line_number": 814 - }, - { - "type": "Secret Keyword", - "filename": "src/config/redact-snapshot.test.ts", - "hashed_secret": "a5c0a65a4fa8874a486aa5072671927ceba82a90", - "is_verified": false, - "line_number": 838 - } - ], - "src/config/schema.help.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/schema.help.ts", - "hashed_secret": "9f4cda226d3868676ac7f86f59e4190eb94bd208", - "is_verified": false, - "line_number": 109 - }, - { - "type": "Secret Keyword", - "filename": "src/config/schema.help.ts", - "hashed_secret": "01822c8bbf6a8b136944b14182cb885100ec2eae", - "is_verified": false, - "line_number": 130 - }, - { - "type": "Secret Keyword", - "filename": "src/config/schema.help.ts", - "hashed_secret": "bb7dfd9746e660e4a4374951ec5938ef0e343255", - "is_verified": false, - "line_number": 187 - } - ], - "src/config/schema.irc.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/schema.irc.ts", - "hashed_secret": "de18cf01737148de8ff7cb33fd38dd4d3e226384", - "is_verified": false, - "line_number": 6 - }, - { - "type": "Secret Keyword", - "filename": "src/config/schema.irc.ts", - "hashed_secret": "b362522192a2259c5d10ecb89fe728a66d6015e9", - "is_verified": false, - "line_number": 7 - }, - { - "type": "Secret Keyword", - "filename": "src/config/schema.irc.ts", - "hashed_secret": "383088054f9b38c21ec29db239e3fccb7eb0a485", - "is_verified": false, - "line_number": 20 - }, - { - "type": "Secret Keyword", - "filename": "src/config/schema.irc.ts", - "hashed_secret": "a3484eea8ccb96dd79f50edc14b8fbf2867a9180", - "is_verified": false, - "line_number": 21 - } - ], - "src/config/schema.labels.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/schema.labels.ts", - "hashed_secret": "e73c9fcad85cd4eecc74181ec4bdb31064d68439", - "is_verified": false, - "line_number": 104 - }, - { - "type": "Secret Keyword", - "filename": "src/config/schema.labels.ts", - "hashed_secret": "2eda7cd978f39eebec3bf03e4410a40e14167fff", - "is_verified": false, - "line_number": 145 - } - ], - "src/config/slack-http-config.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/slack-http-config.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 10 - } - ], - "src/config/telegram-webhook-secret.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/config/telegram-webhook-secret.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 10 - } - ], - "src/docker-setup.test.ts": [ - { - "type": "Base64 High Entropy String", - "filename": "src/docker-setup.test.ts", - "hashed_secret": "32ac33b537769e97787f70ef85576cc243fab934", - "is_verified": false, - "line_number": 131 - } - ], - "src/gateway/auth-rate-limit.ts": [ - { - "type": "Secret Keyword", - "filename": "src/gateway/auth-rate-limit.ts", - "hashed_secret": "76ed0a056aa77060de25754586440cff390791d0", - "is_verified": false, - "line_number": 37 - } - ], - "src/gateway/auth.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/gateway/auth.test.ts", - "hashed_secret": "db5543cd7440bbdc4c5aaf8aa363715c31dd5a27", - "is_verified": false, - "line_number": 32 - }, - { - "type": "Secret Keyword", - "filename": "src/gateway/auth.test.ts", - "hashed_secret": "d51f846285cbc6d1dd76677a0fd588c8df44e506", - "is_verified": false, - "line_number": 48 - }, - { - "type": "Secret Keyword", - "filename": "src/gateway/auth.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 95 - }, - { - "type": "Secret Keyword", - "filename": "src/gateway/auth.test.ts", - "hashed_secret": "a4b48a81cdab1e1a5dd37907d6c85ca1c61ddc7c", - "is_verified": false, - "line_number": 103 - } - ], - "src/gateway/call.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/gateway/call.test.ts", - "hashed_secret": "db5543cd7440bbdc4c5aaf8aa363715c31dd5a27", - "is_verified": false, - "line_number": 357 - }, - { - "type": "Secret Keyword", - "filename": "src/gateway/call.test.ts", - "hashed_secret": "de1c41e8ece73f5d5c259bb37eccb59a542b91dc", - "is_verified": false, - "line_number": 361 - }, - { - "type": "Secret Keyword", - "filename": "src/gateway/call.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 398 - }, - { - "type": "Secret Keyword", - "filename": "src/gateway/call.test.ts", - "hashed_secret": "e493f561d90c6638c1f51c5a8a069c3b129b79ed", - "is_verified": false, - "line_number": 408 - }, - { - "type": "Secret Keyword", - "filename": "src/gateway/call.test.ts", - "hashed_secret": "2e07956ffc9bc4fd624064c40b7495c85d5f1467", - "is_verified": false, - "line_number": 413 - }, - { - "type": "Secret Keyword", - "filename": "src/gateway/call.test.ts", - "hashed_secret": "bddc29032de580fb53b3a9a0357dd409086db800", - "is_verified": false, - "line_number": 426 - }, - { - "type": "Secret Keyword", - "filename": "src/gateway/call.test.ts", - "hashed_secret": "6255675480f681df08c1704b7b3cd2c49917f0e2", - "is_verified": false, - "line_number": 463 - } - ], - "src/gateway/client.e2e.test.ts": [ - { - "type": "Private Key", - "filename": "src/gateway/client.e2e.test.ts", - "hashed_secret": "1348b145fa1a555461c1b790a2f66614781091e9", - "is_verified": false, - "line_number": 85 - } - ], - "src/gateway/gateway-cli-backend.live.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "src/gateway/gateway-cli-backend.live.test.ts", - "hashed_secret": "3e2fd4a90d5afbd27974730c4d6a9592fe300825", - "is_verified": false, - "line_number": 38 - } - ], - "src/gateway/gateway-models.profiles.live.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "src/gateway/gateway-models.profiles.live.test.ts", - "hashed_secret": "3e2fd4a90d5afbd27974730c4d6a9592fe300825", - "is_verified": false, - "line_number": 242 - } - ], - "src/gateway/server-methods/skills.update.normalizes-api-key.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/gateway/server-methods/skills.update.normalizes-api-key.test.ts", - "hashed_secret": "c17b6f497b392e2efc655e8b646b3455f4b28e58", - "is_verified": false, - "line_number": 29 - } - ], - "src/gateway/server-methods/talk.ts": [ - { - "type": "Secret Keyword", - "filename": "src/gateway/server-methods/talk.ts", - "hashed_secret": "e478a5eeba4907d2f12a68761996b9de745d826d", - "is_verified": false, - "line_number": 13 - } - ], - "src/gateway/server.auth.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/gateway/server.auth.e2e.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 460 - }, - { - "type": "Secret Keyword", - "filename": "src/gateway/server.auth.e2e.test.ts", - "hashed_secret": "a4b48a81cdab1e1a5dd37907d6c85ca1c61ddc7c", - "is_verified": false, - "line_number": 478 - } - ], - "src/gateway/server.skills-status.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/gateway/server.skills-status.e2e.test.ts", - "hashed_secret": "1cc6bff0f84efb2d3ff4fa1347f3b2bc173aaff0", - "is_verified": false, - "line_number": 13 - } - ], - "src/gateway/server.talk-config.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/gateway/server.talk-config.e2e.test.ts", - "hashed_secret": "3c310634864babb081f0b617c14bc34823d7e369", - "is_verified": false, - "line_number": 13 - } - ], - "src/gateway/session-utils.test.ts": [ - { - "type": "Base64 High Entropy String", - "filename": "src/gateway/session-utils.test.ts", - "hashed_secret": "bb9a5d9483409d2c60b28268a0efcb93324d4cda", - "is_verified": false, - "line_number": 280 - } - ], - "src/gateway/test-openai-responses-model.ts": [ - { - "type": "Secret Keyword", - "filename": "src/gateway/test-openai-responses-model.ts", - "hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", - "is_verified": false, - "line_number": 17 - } - ], - "src/gateway/ws-log.test.ts": [ - { - "type": "Base64 High Entropy String", - "filename": "src/gateway/ws-log.test.ts", - "hashed_secret": "edd2e7ac4f61d0c606e80a0919d727540842a307", - "is_verified": false, - "line_number": 22 - } - ], - "src/infra/env.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/infra/env.test.ts", - "hashed_secret": "df98a117ddabf85991b9fe0e268214dc0e1254dc", - "is_verified": false, - "line_number": 9 - }, - { - "type": "Secret Keyword", - "filename": "src/infra/env.test.ts", - "hashed_secret": "6d811dc1f59a55ca1a3d38b5042a062b9f79e8ec", - "is_verified": false, - "line_number": 30 - } - ], - "src/infra/outbound/message-action-runner.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "src/infra/outbound/message-action-runner.test.ts", - "hashed_secret": "804ec071803318791b835cffd6e509c8d32239db", - "is_verified": false, - "line_number": 129 - }, - { - "type": "Secret Keyword", - "filename": "src/infra/outbound/message-action-runner.test.ts", - "hashed_secret": "789cbe0407840b1c2041cb33452ff60f19bf58cc", - "is_verified": false, - "line_number": 435 - } - ], - "src/infra/outbound/outbound.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "src/infra/outbound/outbound.test.ts", - "hashed_secret": "804ec071803318791b835cffd6e509c8d32239db", - "is_verified": false, - "line_number": 631 - } - ], - "src/infra/provider-usage.auth.normalizes-keys.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/infra/provider-usage.auth.normalizes-keys.test.ts", - "hashed_secret": "45c7365e3b542cdb4fae6ec10c2ff149224d7656", - "is_verified": false, - "line_number": 80 - }, - { - "type": "Secret Keyword", - "filename": "src/infra/provider-usage.auth.normalizes-keys.test.ts", - "hashed_secret": "b67074884ab7ef7c7a8cd6a3da9565d96c792248", - "is_verified": false, - "line_number": 81 - }, - { - "type": "Secret Keyword", - "filename": "src/infra/provider-usage.auth.normalizes-keys.test.ts", - "hashed_secret": "d4d8027e64f9cf4180d3aecfe31ea409368022ee", - "is_verified": false, - "line_number": 82 - } - ], - "src/infra/shell-env.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/infra/shell-env.test.ts", - "hashed_secret": "65c10dc3549fe07424148a8a4790a3341ecbc253", - "is_verified": false, - "line_number": 26 - }, - { - "type": "Secret Keyword", - "filename": "src/infra/shell-env.test.ts", - "hashed_secret": "e013ffda590d2178607c16d11b1ea42f75ceb0e7", - "is_verified": false, - "line_number": 58 - }, - { - "type": "Base64 High Entropy String", - "filename": "src/infra/shell-env.test.ts", - "hashed_secret": "be6ee9a6bf9f2dad84a5a67d6c0576a5bacc391e", - "is_verified": false, - "line_number": 60 - } - ], - "src/line/accounts.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/line/accounts.test.ts", - "hashed_secret": "fe1bae27cb7c1fb823f496f286e78f1d2ae87734", - "is_verified": false, - "line_number": 30 - }, - { - "type": "Secret Keyword", - "filename": "src/line/accounts.test.ts", - "hashed_secret": "8a8281cec699f5e51330e21dd7fab3531af6ef0c", - "is_verified": false, - "line_number": 48 - }, - { - "type": "Secret Keyword", - "filename": "src/line/accounts.test.ts", - "hashed_secret": "b4924d9834a1126714643ac231fb6623c14c3449", - "is_verified": false, - "line_number": 74 - } - ], - "src/line/bot-handlers.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/line/bot-handlers.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 106 - } - ], - "src/line/bot-message-context.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/line/bot-message-context.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 18 - } - ], - "src/line/monitor.fail-closed.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/line/monitor.fail-closed.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 22 - } - ], - "src/line/webhook-node.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/line/webhook-node.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 28 - } - ], - "src/line/webhook.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/line/webhook.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 23 - } - ], - "src/logging/redact.test.ts": [ - { - "type": "Base64 High Entropy String", - "filename": "src/logging/redact.test.ts", - "hashed_secret": "dd7754662b89333191ff45e8257a3e6d3fcd3990", - "is_verified": false, - "line_number": 8 - }, - { - "type": "Private Key", - "filename": "src/logging/redact.test.ts", - "hashed_secret": "1348b145fa1a555461c1b790a2f66614781091e9", - "is_verified": false, - "line_number": 73 - }, - { - "type": "Hex High Entropy String", - "filename": "src/logging/redact.test.ts", - "hashed_secret": "7992945213f7d76889fa83ff0f2be352409c837e", - "is_verified": false, - "line_number": 74 - }, - { - "type": "Base64 High Entropy String", - "filename": "src/logging/redact.test.ts", - "hashed_secret": "063995ecb4fa5afe2460397d322925cd867b7d74", - "is_verified": false, - "line_number": 88 - } - ], - "src/media-understanding/apply.e2e.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/media-understanding/apply.e2e.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 12 - } - ], - "src/media-understanding/providers/deepgram/audio.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/media-understanding/providers/deepgram/audio.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 27 - } - ], - "src/media-understanding/providers/google/video.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/media-understanding/providers/google/video.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 64 - } - ], - "src/media-understanding/providers/openai/audio.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/media-understanding/providers/openai/audio.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 22 - } - ], - "src/media-understanding/runner.auto-audio.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/media-understanding/runner.auto-audio.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 40 - } - ], - "src/media-understanding/runner.deepgram.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/media-understanding/runner.deepgram.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 44 - } - ], - "src/memory/embeddings-voyage.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/memory/embeddings-voyage.test.ts", - "hashed_secret": "7c2020578bbe5e2e3f78d7f954eb2ad8ab5b0403", - "is_verified": false, - "line_number": 33 - }, - { - "type": "Secret Keyword", - "filename": "src/memory/embeddings-voyage.test.ts", - "hashed_secret": "8afdb3da9b79c8957ae35978ea8f33fbc3bfdf60", - "is_verified": false, - "line_number": 77 - } - ], - "src/memory/embeddings.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/memory/embeddings.test.ts", - "hashed_secret": "a47110e348a3063541fb1f1f640d635d457181a0", - "is_verified": false, - "line_number": 45 - }, - { - "type": "Secret Keyword", - "filename": "src/memory/embeddings.test.ts", - "hashed_secret": "c734e47630dda71619c696d88381f06f7511bd78", - "is_verified": false, - "line_number": 160 - }, - { - "type": "Secret Keyword", - "filename": "src/memory/embeddings.test.ts", - "hashed_secret": "56e1d57b8db262b08bc73c60ed08d8c92e59503f", - "is_verified": false, - "line_number": 189 - } - ], - "src/pairing/pairing-store.ts": [ - { - "type": "Base64 High Entropy String", - "filename": "src/pairing/pairing-store.ts", - "hashed_secret": "f8c6f1ff98c5ee78c27d34a3ca68f35ad79847af", - "is_verified": false, - "line_number": 13 - } - ], - "src/pairing/setup-code.test.ts": [ - { - "type": "Base64 High Entropy String", - "filename": "src/pairing/setup-code.test.ts", - "hashed_secret": "4914c103484773b5a8e18448b11919bb349cbff8", - "is_verified": false, - "line_number": 22 - }, - { - "type": "Secret Keyword", - "filename": "src/pairing/setup-code.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 96 - } - ], - "src/security/audit.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/security/audit.test.ts", - "hashed_secret": "21f688ab56f76a99e5c6ed342291422f4e57e47f", - "is_verified": false, - "line_number": 2063 - }, - { - "type": "Secret Keyword", - "filename": "src/security/audit.test.ts", - "hashed_secret": "3dc927d80543dc0f643940b70d066bd4b4c4b78e", - "is_verified": false, - "line_number": 2094 - } - ], - "src/telegram/monitor.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/telegram/monitor.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 205 - }, - { - "type": "Secret Keyword", - "filename": "src/telegram/monitor.test.ts", - "hashed_secret": "5934c4d4a4fa5d66ddb3d3fc0bba84996c17a5b7", - "is_verified": false, - "line_number": 233 - } - ], - "src/telegram/webhook.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/telegram/webhook.test.ts", - "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", - "is_verified": false, - "line_number": 42 - } - ], - "src/tts/tts.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/tts/tts.test.ts", - "hashed_secret": "2e7a7ee14caebf378fc32d6cf6f557f347c96773", - "is_verified": false, - "line_number": 36 - }, - { - "type": "Hex High Entropy String", - "filename": "src/tts/tts.test.ts", - "hashed_secret": "b214f706bb602c1cc2adc5c6165e73622305f4bb", - "is_verified": false, - "line_number": 98 - }, - { - "type": "Secret Keyword", - "filename": "src/tts/tts.test.ts", - "hashed_secret": "75ddfb45216fe09680dfe70eda4f559a910c832c", - "is_verified": false, - "line_number": 397 - }, - { - "type": "Secret Keyword", - "filename": "src/tts/tts.test.ts", - "hashed_secret": "e29af93630aa18cc3457cb5b13937b7ab7c99c9b", - "is_verified": false, - "line_number": 413 - }, - { - "type": "Secret Keyword", - "filename": "src/tts/tts.test.ts", - "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", - "is_verified": false, - "line_number": 447 - } - ], - "src/tui/gateway-chat.test.ts": [ - { - "type": "Secret Keyword", - "filename": "src/tui/gateway-chat.test.ts", - "hashed_secret": "6255675480f681df08c1704b7b3cd2c49917f0e2", - "is_verified": false, - "line_number": 85 - } - ], - "src/web/login.test.ts": [ - { - "type": "Hex High Entropy String", - "filename": "src/web/login.test.ts", - "hashed_secret": "564666dc1ca6e7318b2d5feeb1ce7b5bf717411e", - "is_verified": false, - "line_number": 60 - } - ], - "ui/src/i18n/locales/en.ts": [ - { - "type": "Secret Keyword", - "filename": "ui/src/i18n/locales/en.ts", - "hashed_secret": "de0ff6b974d6910aca8d6b830e1b761f076d8fe6", - "is_verified": false, - "line_number": 60 - } - ], - "ui/src/i18n/locales/pt-BR.ts": [ - { - "type": "Secret Keyword", - "filename": "ui/src/i18n/locales/pt-BR.ts", - "hashed_secret": "ef7b6f95faca2d7d3a5aa5a6434c89530c6dd243", - "is_verified": false, - "line_number": 60 - } - ], - "vendor/a2ui/README.md": [ - { - "type": "Secret Keyword", - "filename": "vendor/a2ui/README.md", - "hashed_secret": "2619a5397a5d054dab3fe24e6a8da1fbd76ec3a6", - "is_verified": false, - "line_number": 123 - } - ] - }, - "generated_at": "2026-02-17T13:34:38Z" -} diff --git a/.shellcheckrc b/.shellcheckrc deleted file mode 100644 index 515f25a5f1e..00000000000 --- a/.shellcheckrc +++ /dev/null @@ -1,25 +0,0 @@ -# ShellCheck configuration -# https://www.shellcheck.net/wiki/ - -# Disable common false positives and style suggestions - -# SC2034: Variable appears unused (often exported or used indirectly) -disable=SC2034 - -# SC2155: Declare and assign separately (common idiom, rarely causes issues) -disable=SC2155 - -# SC2295: Expansions inside ${..} need quoting (info-level, rarely causes issues) -disable=SC2295 - -# SC1012: \r is literal (tr -d '\r' works as intended on most systems) -disable=SC1012 - -# SC2026: Word outside quotes (info-level, often intentional) -disable=SC2026 - -# SC2016: Expressions don't expand in single quotes (often intentional in sed/awk) -disable=SC2016 - -# SC2129: Consider using { cmd1; cmd2; } >> file (style preference) -disable=SC2129 diff --git a/.swiftformat b/.swiftformat deleted file mode 100644 index fd8c0e6315c..00000000000 --- a/.swiftformat +++ /dev/null @@ -1,51 +0,0 @@ -# SwiftFormat configuration adapted from Peekaboo defaults (Swift 6 friendly) - ---swiftversion 6.2 - -# Self handling ---self insert ---selfrequired - -# Imports / extensions ---importgrouping testable-bottom ---extensionacl on-declarations - -# Indentation ---indent 4 ---indentcase false ---ifdef no-indent ---xcodeindentation enabled - -# Line breaks ---linebreaks lf ---maxwidth 120 - -# Whitespace ---trimwhitespace always ---emptybraces no-space ---nospaceoperators ...,..< ---ranges no-space ---someAny true ---voidtype void - -# Wrapping ---wraparguments before-first ---wrapparameters before-first ---wrapcollections before-first ---closingparen same-line - -# Organization ---organizetypes class,struct,enum,extension ---extensionmark "MARK: - %t + %p" ---marktypes always ---markextensions always ---structthreshold 0 ---enumthreshold 0 - -# Other ---stripunusedargs closure-only ---header ignore ---allman false - -# Exclusions ---exclude .build,.swiftpm,DerivedData,node_modules,dist,coverage,xcuserdata,Peekaboo,Swabble,apps/android,apps/ios,apps/shared,apps/macos/Sources/MoltbotProtocol diff --git a/.swiftlint.yml b/.swiftlint.yml deleted file mode 100644 index b5622880111..00000000000 --- a/.swiftlint.yml +++ /dev/null @@ -1,148 +0,0 @@ -# SwiftLint configuration adapted from Peekaboo defaults (Swift 6 friendly) - -included: - - apps/macos/Sources - -excluded: - - .build - - DerivedData - - "**/.build" - - "**/.swiftpm" - - "**/DerivedData" - - "**/Generated" - - "**/Resources" - - "**/Package.swift" - - "**/Tests/Resources" - - node_modules - - dist - - coverage - - "*.playground" - # Generated (protocol-gen-swift.ts) - - apps/macos/Sources/MoltbotProtocol/GatewayModels.swift - -analyzer_rules: - - unused_declaration - - unused_import - -opt_in_rules: - - array_init - - closure_spacing - - contains_over_first_not_nil - - empty_count - - empty_string - - explicit_init - - fallthrough - - fatal_error_message - - first_where - - joined_default_parameter - - last_where - - literal_expression_end_indentation - - multiline_arguments - - multiline_parameters - - operator_usage_whitespace - - overridden_super_call - - pattern_matching_keywords - - private_outlet - - prohibited_super_call - - redundant_nil_coalescing - - sorted_first_last - - switch_case_alignment - - unneeded_parentheses_in_closure_argument - - vertical_parameter_alignment_on_call - -disabled_rules: - # SwiftFormat handles these - - trailing_whitespace - - trailing_newline - - trailing_comma - - vertical_whitespace - - indentation_width - - # Style exclusions - - explicit_self - - identifier_name - - file_header - - explicit_top_level_acl - - explicit_acl - - explicit_type_interface - - missing_docs - - required_deinit - - prefer_nimble - - quick_discouraged_call - - quick_discouraged_focused_test - - quick_discouraged_pending_test - - anonymous_argument_in_multiline_closure - - no_extension_access_modifier - - no_grouping_extension - - switch_case_on_newline - - strict_fileprivate - - extension_access_modifier - - convenience_type - - no_magic_numbers - - one_declaration_per_file - - vertical_whitespace_between_cases - - vertical_whitespace_closing_braces - - superfluous_else - - number_separator - - prefixed_toplevel_constant - - opening_brace - - trailing_closure - - contrasted_opening_brace - - sorted_imports - - redundant_type_annotation - - shorthand_optional_binding - - untyped_error_in_catch - - file_name - - todo - -force_cast: warning -force_try: warning - -type_name: - min_length: - warning: 2 - error: 1 - max_length: - warning: 60 - error: 80 - -function_body_length: - warning: 150 - error: 300 - -function_parameter_count: - warning: 7 - error: 10 - -file_length: - warning: 1500 - error: 2500 - ignore_comment_only_lines: true - -type_body_length: - warning: 800 - error: 1200 - -cyclomatic_complexity: - warning: 20 - error: 120 - -large_tuple: - warning: 4 - error: 5 - -nesting: - type_level: - warning: 4 - error: 6 - function_level: - warning: 5 - error: 7 - -line_length: - warning: 120 - error: 250 - ignores_comments: true - ignores_urls: true - -reporter: "xcode" diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 99e2f7ddf76..00000000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "recommendations": ["oxc.oxc-vscode"] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index e291954cfc3..00000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "editor.formatOnSave": true, - "files.insertFinalNewline": true, - "files.trimFinalNewlines": true, - "[javascript]": { - "editor.defaultFormatter": "oxc.oxc-vscode" - }, - "[typescriptreact]": { - "editor.defaultFormatter": "oxc.oxc-vscode" - }, - "[typescript]": { - "editor.defaultFormatter": "oxc.oxc-vscode" - }, - "[json]": { - "editor.defaultFormatter": "oxc.oxc-vscode" - }, - "typescript.preferences.importModuleSpecifierEnding": "js", - "typescript.reportStyleChecksAsWarnings": false, - "typescript.updateImportsOnFileMove.enabled": "always", - "typescript.tsdk": "node_modules/typescript/lib", - "typescript.experimental.useTsgo": true -} diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index 3555ef17936..00000000000 --- a/AGENTS.md +++ /dev/null @@ -1,240 +0,0 @@ -# Repository Guidelines - -- Repo: https://github.com/openclaw/openclaw -- GitHub issues/comments/PR comments: use literal multiline strings or `-F - <<'EOF'` (or $'...') for real newlines; never embed "\\n". - -## Project Structure & Module Organization - -- Source code: `src/` (CLI wiring in `src/cli`, commands in `src/commands`, web provider in `src/provider-web.ts`, infra in `src/infra`, media pipeline in `src/media`). -- Tests: colocated `*.test.ts`. -- Docs: `docs/` (images, queue, Pi config). Built output lives in `dist/`. -- Plugins/extensions: live under `extensions/*` (workspace packages). Keep plugin-only deps in the extension `package.json`; do not add them to the root `package.json` unless core uses them. -- Plugins: install runs `npm install --omit=dev` in plugin dir; runtime deps must live in `dependencies`. Avoid `workspace:*` in `dependencies` (npm install breaks); put `openclaw` in `devDependencies` or `peerDependencies` instead (runtime resolves `openclaw/plugin-sdk` via jiti alias). -- Installers served from `https://openclaw.ai/*`: live in the sibling repo `../openclaw.ai` (`public/install.sh`, `public/install-cli.sh`, `public/install.ps1`). -- Messaging channels: always consider **all** built-in + extension channels when refactoring shared logic (routing, allowlists, pairing, command gating, onboarding, docs). - - Core channel docs: `docs/channels/` - - Core channel code: `src/telegram`, `src/discord`, `src/slack`, `src/signal`, `src/imessage`, `src/web` (WhatsApp web), `src/channels`, `src/routing` - - Extensions (channel plugins): `extensions/*` (e.g. `extensions/msteams`, `extensions/matrix`, `extensions/zalo`, `extensions/zalouser`, `extensions/voice-call`) -- When adding channels/extensions/apps/docs, update `.github/labeler.yml` and create matching GitHub labels (use existing channel/extension label colors). - -## Docs Linking (Mintlify) - -- Docs are hosted on Mintlify (docs.openclaw.ai). -- Internal doc links in `docs/**/*.md`: root-relative, no `.md`/`.mdx` (example: `[Config](/configuration)`). -- When working with documentation, read the mintlify skill. -- Section cross-references: use anchors on root-relative paths (example: `[Hooks](/configuration#hooks)`). -- Doc headings and anchors: avoid em dashes and apostrophes in headings because they break Mintlify anchor links. -- When Peter asks for links, reply with full `https://docs.openclaw.ai/...` URLs (not root-relative). -- When you touch docs, end the reply with the `https://docs.openclaw.ai/...` URLs you referenced. -- README (GitHub): keep absolute docs URLs (`https://docs.openclaw.ai/...`) so links work on GitHub. -- Docs content must be generic: no personal device names/hostnames/paths; use placeholders like `user@gateway-host` and “gateway host”. - -## Docs i18n (zh-CN) - -- `docs/zh-CN/**` is generated; do not edit unless the user explicitly asks. -- Pipeline: update English docs → adjust glossary (`docs/.i18n/glossary.zh-CN.json`) → run `scripts/docs-i18n` → apply targeted fixes only if instructed. -- Translation memory: `docs/.i18n/zh-CN.tm.jsonl` (generated). -- See `docs/.i18n/README.md`. -- The pipeline can be slow/inefficient; if it’s dragging, ping @jospalmbier on Discord instead of hacking around it. - -## exe.dev VM ops (general) - -- Access: stable path is `ssh exe.dev` then `ssh vm-name` (assume SSH key already set). -- SSH flaky: use exe.dev web terminal or Shelley (web agent); keep a tmux session for long ops. -- Update: `sudo npm i -g openclaw@latest` (global install needs root on `/usr/lib/node_modules`). -- Config: use `openclaw config set ...`; ensure `gateway.mode=local` is set. -- Discord: store raw token only (no `DISCORD_BOT_TOKEN=` prefix). -- Restart: stop old gateway and run: - `pkill -9 -f openclaw-gateway || true; nohup openclaw gateway run --bind loopback --port 18789 --force > /tmp/openclaw-gateway.log 2>&1 &` -- Verify: `openclaw channels status --probe`, `ss -ltnp | rg 18789`, `tail -n 120 /tmp/openclaw-gateway.log`. - -## Build, Test, and Development Commands - -- Runtime baseline: Node **22+** (keep Node + Bun paths working). -- Install deps: `pnpm install` -- If deps are missing (for example `node_modules` missing, `vitest not found`, or `command not found`), run the repo’s package-manager install command (prefer lockfile/README-defined PM), then rerun the exact requested command once. Apply this to test/build/lint/typecheck/dev commands; if retry still fails, report the command and first actionable error. -- Pre-commit hooks: `prek install` (runs same checks as CI) -- Also supported: `bun install` (keep `pnpm-lock.yaml` + Bun patching in sync when touching deps/patches). -- Prefer Bun for TypeScript execution (scripts, dev, tests): `bun ` / `bunx `. -- Run CLI in dev: `pnpm openclaw ...` (bun) or `pnpm dev`. -- Node remains supported for running built output (`dist/*`) and production installs. -- Mac packaging (dev): `scripts/package-mac-app.sh` defaults to current arch. Release checklist: `docs/platforms/mac/release.md`. -- Type-check/build: `pnpm build` -- TypeScript checks: `pnpm tsgo` -- Lint/format: `pnpm check` -- Format check: `pnpm format` (oxfmt --check) -- Format fix: `pnpm format:fix` (oxfmt --write) -- Tests: `pnpm test` (vitest); coverage: `pnpm test:coverage` - -## Coding Style & Naming Conventions - -- Language: TypeScript (ESM). Prefer strict typing; avoid `any`. -- Formatting/linting via Oxlint and Oxfmt; run `pnpm check` before commits. -- Never add `@ts-nocheck` and do not disable `no-explicit-any`; fix root causes and update Oxlint/Oxfmt config only when required. -- Never share class behavior via prototype mutation (`applyPrototypeMixins`, `Object.defineProperty` on `.prototype`, or exporting `Class.prototype` for merges). Use explicit inheritance/composition (`A extends B extends C`) or helper composition so TypeScript can typecheck. -- If this pattern is needed, stop and get explicit approval before shipping; default behavior is to split/refactor into an explicit class hierarchy and keep members strongly typed. -- In tests, prefer per-instance stubs over prototype mutation (`SomeClass.prototype.method = ...`) unless a test explicitly documents why prototype-level patching is required. -- Add brief code comments for tricky or non-obvious logic. -- Keep files concise; extract helpers instead of “V2” copies. Use existing patterns for CLI options and dependency injection via `createDefaultDeps`. -- Aim to keep files under ~700 LOC; guideline only (not a hard guardrail). Split/refactor when it improves clarity or testability. -- Naming: use **OpenClaw** for product/app/docs headings; use `openclaw` for CLI command, package/binary, paths, and config keys. - -## Release Channels (Naming) - -- stable: tagged releases only (e.g. `vYYYY.M.D`), npm dist-tag `latest`. -- beta: prerelease tags `vYYYY.M.D-beta.N`, npm dist-tag `beta` (may ship without macOS app). -- dev: moving head on `main` (no tag; git checkout main). - -## Testing Guidelines - -- Framework: Vitest with V8 coverage thresholds (70% lines/branches/functions/statements). -- Naming: match source names with `*.test.ts`; e2e in `*.e2e.test.ts`. -- Run `pnpm test` (or `pnpm test:coverage`) before pushing when you touch logic. -- Do not set test workers above 16; tried already. -- Live tests (real keys): `CLAWDBOT_LIVE_TEST=1 pnpm test:live` (OpenClaw-only) or `LIVE=1 pnpm test:live` (includes provider live tests). Docker: `pnpm test:docker:live-models`, `pnpm test:docker:live-gateway`. Onboarding Docker E2E: `pnpm test:docker:onboard`. -- Full kit + what’s covered: `docs/testing.md`. -- Changelog: user-facing changes only; no internal/meta notes (version alignment, appcast reminders, release process). -- Pure test additions/fixes generally do **not** need a changelog entry unless they alter user-facing behavior or the user asks for one. -- Mobile: before using a simulator, check for connected real devices (iOS + Android) and prefer them when available. - -## Commit & Pull Request Guidelines - -**Full maintainer PR workflow (optional):** If you want the repo's end-to-end maintainer workflow (triage order, quality bar, rebase rules, commit/changelog conventions, co-contributor policy, and the `review-pr` > `prepare-pr` > `merge-pr` pipeline), see `.agents/skills/PR_WORKFLOW.md`. Maintainers may use other workflows; when a maintainer specifies a workflow, follow that. If no workflow is specified, default to PR_WORKFLOW. - -- Create commits with `scripts/committer "" `; avoid manual `git add`/`git commit` so staging stays scoped. -- Follow concise, action-oriented commit messages (e.g., `CLI: add verbose flag to send`). -- Group related changes; avoid bundling unrelated refactors. -- PR submission template (canonical): `.github/pull_request_template.md` -- Issue submission templates (canonical): `.github/ISSUE_TEMPLATE/` - -## Shorthand Commands - -- `sync`: if working tree is dirty, commit all changes (pick a sensible Conventional Commit message), then `git pull --rebase`; if rebase conflicts and cannot resolve, stop; otherwise `git push`. - -## Git Notes - -- If `git branch -d/-D ` is policy-blocked, delete the local ref directly: `git update-ref -d refs/heads/`. -- Bulk PR close/reopen safety: if a close action would affect more than 5 PRs, first ask for explicit user confirmation with the exact PR count and target scope/query. - -## Security & Configuration Tips - -- Web provider stores creds at `~/.openclaw/credentials/`; rerun `openclaw login` if logged out. -- Pi sessions live under `~/.openclaw/sessions/` by default; the base directory is not configurable. -- Environment variables: see `~/.profile`. -- Never commit or publish real phone numbers, videos, or live configuration values. Use obviously fake placeholders in docs, tests, and examples. -- Release flow: always read `docs/reference/RELEASING.md` and `docs/platforms/mac/release.md` before any release work; do not ask routine questions once those docs answer them. - -## GHSA (Repo Advisory) Patch/Publish - -- Before reviewing security advisories, read `SECURITY.md`. -- Fetch: `gh api /repos/openclaw/openclaw/security-advisories/` -- Latest npm: `npm view openclaw version --userconfig "$(mktemp)"` -- Private fork PRs must be closed: - `fork=$(gh api /repos/openclaw/openclaw/security-advisories/ | jq -r .private_fork.full_name)` - `gh pr list -R "$fork" --state open` (must be empty) -- Description newline footgun: write Markdown via heredoc to `/tmp/ghsa.desc.md` (no `"\\n"` strings) -- Build patch JSON via jq: `jq -n --rawfile desc /tmp/ghsa.desc.md '{summary,severity,description:$desc,vulnerabilities:[...]}' > /tmp/ghsa.patch.json` -- GHSA API footgun: cannot set `severity` and `cvss_vector_string` in the same PATCH; do separate calls. -- Patch + publish: `gh api -X PATCH /repos/openclaw/openclaw/security-advisories/ --input /tmp/ghsa.patch.json` (publish = include `"state":"published"`; no `/publish` endpoint) -- If publish fails (HTTP 422): missing `severity`/`description`/`vulnerabilities[]`, or private fork has open PRs -- Verify: re-fetch; ensure `state=published`, `published_at` set; `jq -r .description | rg '\\\\n'` returns nothing - -## Troubleshooting - -- Rebrand/migration issues or legacy config/service warnings: run `openclaw doctor` (see `docs/gateway/doctor.md`). - -## Agent-Specific Notes - -- Vocabulary: "makeup" = "mac app". -- Never edit `node_modules` (global/Homebrew/npm/git installs too). Updates overwrite. Skill notes go in `tools.md` or `AGENTS.md`. -- When adding a new `AGENTS.md` anywhere in the repo, also add a `CLAUDE.md` symlink pointing to it (example: `ln -s AGENTS.md CLAUDE.md`). -- Signal: "update fly" => `fly ssh console -a flawd-bot -C "bash -lc 'cd /data/clawd/openclaw && git pull --rebase origin main'"` then `fly machines restart e825232f34d058 -a flawd-bot`. -- When working on a GitHub Issue or PR, print the full URL at the end of the task. -- When answering questions, respond with high-confidence answers only: verify in code; do not guess. -- Never update the Carbon dependency. -- Any dependency with `pnpm.patchedDependencies` must use an exact version (no `^`/`~`). -- Patching dependencies (pnpm patches, overrides, or vendored changes) requires explicit approval; do not do this by default. -- CLI progress: use `src/cli/progress.ts` (`osc-progress` + `@clack/prompts` spinner); don’t hand-roll spinners/bars. -- Status output: keep tables + ANSI-safe wrapping (`src/terminal/table.ts`); `status --all` = read-only/pasteable, `status --deep` = probes. -- Gateway currently runs only as the menubar app; there is no separate LaunchAgent/helper label installed. Restart via the OpenClaw Mac app or `scripts/restart-mac.sh`; to verify/kill use `launchctl print gui/$UID | grep openclaw` rather than assuming a fixed label. **When debugging on macOS, start/stop the gateway via the app, not ad-hoc tmux sessions; kill any temporary tunnels before handoff.** -- macOS logs: use `./scripts/clawlog.sh` to query unified logs for the OpenClaw subsystem; it supports follow/tail/category filters and expects passwordless sudo for `/usr/bin/log`. -- If shared guardrails are available locally, review them; otherwise follow this repo's guidance. -- SwiftUI state management (iOS/macOS): prefer the `Observation` framework (`@Observable`, `@Bindable`) over `ObservableObject`/`@StateObject`; don’t introduce new `ObservableObject` unless required for compatibility, and migrate existing usages when touching related code. -- Connection providers: when adding a new connection, update every UI surface and docs (macOS app, web UI, mobile if applicable, onboarding/overview docs) and add matching status + configuration forms so provider lists and settings stay in sync. -- Version locations: `package.json` (CLI), `apps/android/app/build.gradle.kts` (versionName/versionCode), `apps/ios/Sources/Info.plist` + `apps/ios/Tests/Info.plist` (CFBundleShortVersionString/CFBundleVersion), `apps/macos/Sources/OpenClaw/Resources/Info.plist` (CFBundleShortVersionString/CFBundleVersion), `docs/install/updating.md` (pinned npm version), `docs/platforms/mac/release.md` (APP_VERSION/APP_BUILD examples), Peekaboo Xcode projects/Info.plists (MARKETING_VERSION/CURRENT_PROJECT_VERSION). -- "Bump version everywhere" means all version locations above **except** `appcast.xml` (only touch appcast when cutting a new macOS Sparkle release). -- **Restart apps:** “restart iOS/Android apps” means rebuild (recompile/install) and relaunch, not just kill/launch. -- **Device checks:** before testing, verify connected real devices (iOS/Android) before reaching for simulators/emulators. -- iOS Team ID lookup: `security find-identity -p codesigning -v` → use Apple Development (…) TEAMID. Fallback: `defaults read com.apple.dt.Xcode IDEProvisioningTeamIdentifiers`. -- A2UI bundle hash: `src/canvas-host/a2ui/.bundle.hash` is auto-generated; ignore unexpected changes, and only regenerate via `pnpm canvas:a2ui:bundle` (or `scripts/bundle-a2ui.sh`) when needed. Commit the hash as a separate commit. -- Release signing/notary keys are managed outside the repo; follow internal release docs. -- Notary auth env vars (`APP_STORE_CONNECT_ISSUER_ID`, `APP_STORE_CONNECT_KEY_ID`, `APP_STORE_CONNECT_API_KEY_P8`) are expected in your environment (per internal release docs). -- **Multi-agent safety:** do **not** create/apply/drop `git stash` entries unless explicitly requested (this includes `git pull --rebase --autostash`). Assume other agents may be working; keep unrelated WIP untouched and avoid cross-cutting state changes. -- **Multi-agent safety:** when the user says "push", you may `git pull --rebase` to integrate latest changes (never discard other agents' work). When the user says "commit", scope to your changes only. When the user says "commit all", commit everything in grouped chunks. -- **Multi-agent safety:** do **not** create/remove/modify `git worktree` checkouts (or edit `.worktrees/*`) unless explicitly requested. -- **Multi-agent safety:** do **not** switch branches / check out a different branch unless explicitly requested. -- **Multi-agent safety:** running multiple agents is OK as long as each agent has its own session. -- **Multi-agent safety:** when you see unrecognized files, keep going; focus on your changes and commit only those. -- Lint/format churn: - - If staged+unstaged diffs are formatting-only, auto-resolve without asking. - - If commit/push already requested, auto-stage and include formatting-only follow-ups in the same commit (or a tiny follow-up commit if needed), no extra confirmation. - - Only ask when changes are semantic (logic/data/behavior). -- Lobster seam: use the shared CLI palette in `src/terminal/palette.ts` (no hardcoded colors); apply palette to onboarding/config prompts and other TTY UI output as needed. -- **Multi-agent safety:** focus reports on your edits; avoid guard-rail disclaimers unless truly blocked; when multiple agents touch the same file, continue if safe; end with a brief “other files present” note only if relevant. -- Bug investigations: read source code of relevant npm dependencies and all related local code before concluding; aim for high-confidence root cause. -- Code style: add brief comments for tricky logic; keep files under ~500 LOC when feasible (split/refactor as needed). -- Tool schema guardrails (google-antigravity): avoid `Type.Union` in tool input schemas; no `anyOf`/`oneOf`/`allOf`. Use `stringEnum`/`optionalStringEnum` (Type.Unsafe enum) for string lists, and `Type.Optional(...)` instead of `... | null`. Keep top-level tool schema as `type: "object"` with `properties`. -- Tool schema guardrails: avoid raw `format` property names in tool schemas; some validators treat `format` as a reserved keyword and reject the schema. -- When asked to open a “session” file, open the Pi session logs under `~/.openclaw/agents//sessions/*.jsonl` (use the `agent=` value in the Runtime line of the system prompt; newest unless a specific ID is given), not the default `sessions.json`. If logs are needed from another machine, SSH via Tailscale and read the same path there. -- Do not rebuild the macOS app over SSH; rebuilds must be run directly on the Mac. -- Never send streaming/partial replies to external messaging surfaces (WhatsApp, Telegram); only final replies should be delivered there. Streaming/tool events may still go to internal UIs/control channel. -- Voice wake forwarding tips: - - Command template should stay `openclaw-mac agent --message "${text}" --thinking low`; `VoiceWakeForwarder` already shell-escapes `${text}`. Don’t add extra quotes. - - launchd PATH is minimal; ensure the app’s launch agent PATH includes standard system paths plus your pnpm bin (typically `$HOME/Library/pnpm`) so `pnpm`/`openclaw` binaries resolve when invoked via `openclaw-mac`. -- For manual `openclaw message send` messages that include `!`, use the heredoc pattern noted below to avoid the Bash tool’s escaping. -- Release guardrails: do not change version numbers without operator’s explicit consent; always ask permission before running any npm publish/release step. - -## NPM + 1Password (publish/verify) - -- Use the 1password skill; all `op` commands must run inside a fresh tmux session. -- Sign in: `eval "$(op signin --account my.1password.com)"` (app unlocked + integration on). -- OTP: `op read 'op://Private/Npmjs/one-time password?attribute=otp'`. -- Publish: `npm publish --access public --otp=""` (run from the package dir). -- Verify without local npmrc side effects: `npm view version --userconfig "$(mktemp)"`. -- Kill the tmux session after publish. - -## Plugin Release Fast Path (no core `openclaw` publish) - -- Release only already-on-npm plugins. Source list is in `docs/reference/RELEASING.md` under "Current npm plugin list". -- Run all CLI `op` calls and `npm publish` inside tmux to avoid hangs/interruption: - - `tmux new -d -s release-plugins-$(date +%Y%m%d-%H%M%S)` - - `eval "$(op signin --account my.1password.com)"` -- 1Password helpers: - - password used by `npm login`: - `op item get Npmjs --format=json | jq -r '.fields[] | select(.id=="password").value'` - - OTP: - `op read 'op://Private/Npmjs/one-time password?attribute=otp'` -- Fast publish loop (local helper script in `/tmp` is fine; keep repo clean): - - compare local plugin `version` to `npm view version` - - only run `npm publish --access public --otp=""` when versions differ - - skip if package is missing on npm or version already matches. -- Keep `openclaw` untouched: never run publish from repo root unless explicitly requested. -- Post-check for each release: - - per-plugin: `npm view @openclaw/ version --userconfig "$(mktemp)"` should be `2026.2.17` - - core guard: `npm view openclaw version --userconfig "$(mktemp)"` should stay at previous version unless explicitly requested. - -## Changelog Release Notes - -- When cutting a mac release with beta GitHub prerelease: - - Tag `vYYYY.M.D-beta.N` from the release commit (example: `v2026.2.15-beta.1`). - - Create prerelease with title `openclaw YYYY.M.D-beta.N`. - - Use release notes from `CHANGELOG.md` version section (`Changes` + `Fixes`, no title duplicate). - - Attach at least `OpenClaw-YYYY.M.D.zip` and `OpenClaw-YYYY.M.D.dSYM.zip`; include `.dmg` if available. - -- Keep top version entries in `CHANGELOG.md` sorted by impact: - - `### Changes` first. - - `### Fixes` deduped and ranked with user-facing fixes first. -- Before tagging/publishing, run: - - `node --import tsx scripts/release-check.ts` - - `pnpm release:check` - - `pnpm test:install:smoke` or `OPENCLAW_INSTALL_SMOKE_SKIP_NONROOT=1 pnpm test:install:smoke` for non-root smoke path. diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index c29a34c9bd4..00000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,2585 +0,0 @@ -# Changelog - -Docs: https://docs.openclaw.ai - -## 2026.2.22 (Unreleased) - -### Changes - -- Channels/Config: unify channel preview streaming config handling with a shared resolver and canonical migration path. -- Discord/Allowlist: canonicalize resolved Discord allowlist names to IDs and split resolution flow for clearer fail-closed behavior. -- Memory/FTS: add Korean stop-word filtering and particle-aware keyword extraction (including mixed Korean/English stems) for query expansion in FTS-only search mode. (#18899) Thanks @ruypang. -- iOS/Talk: prefetch TTS segments and suppress expected speech-cancellation errors for smoother talk playback. (#22833) Thanks @ngutman. - -### Breaking - -- **BREAKING:** unify channel preview-streaming config to `channels..streaming` with enum values `off | partial | block | progress`, and move Slack native stream toggle to `channels.slack.nativeStreaming`. Legacy keys (`streamMode`, Slack boolean `streaming`) are still read and migrated by `openclaw doctor --fix`, but canonical saved config/docs now use the unified names. - -### Fixes - -- Telegram/WSL2: disable `autoSelectFamily` by default on WSL2 and memoize WSL2 detection in Telegram network decision logic to avoid repeated sync `/proc/version` probes on fetch/send paths. (#21916) Thanks @MizukiMachine. -- Telegram/Streaming: preserve archived draft preview mapping after flush and clean superseded reasoning preview bubbles so multi-message preview finals no longer cross-edit or orphan stale messages under send/rotation races. (#23202) Thanks @obviyus. -- Slack/Slash commands: preserve the Bolt app receiver when registering external select options handlers so monitor startup does not crash on runtimes that require bound `app.options` calls. (#23209) Thanks @0xgaia. -- Slack/Telegram slash sessions: await session metadata persistence before dispatch so first-turn native slash runs do not race session-origin metadata updates. (#23065) thanks @hydro13. -- Agents/Ollama: preserve unsafe integer tool-call arguments as exact strings during NDJSON parsing, preventing large numeric IDs from being rounded before tool execution. (#23170) Thanks @BestJoester. -- Cron/Gateway: keep `cron.list` and `cron.status` responsive during startup catch-up by avoiding a long-held cron lock while missed jobs execute. (#23106) Thanks @jayleekr. -- Gateway/Config reload: compare array-valued config paths structurally during diffing so unchanged `memory.qmd.paths` and `memory.qmd.scope.rules` no longer trigger false restart-required reloads. (#23185) Thanks @rex05ai. -- Cron/Scheduling: validate runtime cron expressions before schedule/stagger evaluation so malformed persisted jobs report a clear `invalid cron schedule: expr is required` error instead of crashing with `undefined.trim` failures and auto-disable churn. (#23223) Thanks @asimons81. -- Memory/QMD: migrate legacy unscoped collection bindings (for example `memory-root`) to per-agent scoped names (for example `memory-root-main`) during startup when safe, so QMD-backed `memory_search` no longer fails with `Collection not found` after upgrades. (#23228, #20727) Thanks @JLDynamics and @AaronFaby. -- TUI/Input: enable multiline-paste burst coalescing on macOS Terminal.app and iTerm so pasted blocks no longer submit line-by-line as separate messages. (#18809) Thanks @fwends. -- TUI/Status: request immediate renders after setting `sending`/`waiting` activity states so in-flight runs always show visible progress indicators instead of appearing idle until completion. (#21549) Thanks @13Guinness. -- Agents/Fallbacks: treat JSON payloads with `type: "api_error"` + `"Internal server error"` as transient failover errors so Anthropic 500-style failures trigger model fallback. (#23193) Thanks @jarvis-lane. -- Agents/Diagnostics: include resolved lifecycle error text in `embedded run agent end` warnings so UI/TUI “Connection error” runs expose actionable provider failure reasons in gateway logs. (#23054) Thanks @Raize. -- Gateway/Pairing: treat operator.admin pairing tokens as satisfying operator.write requests so legacy devices stop looping through scope-upgrade prompts introduced in 2026.2.19. (#23125, #23006) Thanks @vignesh07. -- Gateway/Pairing: treat `operator.admin` as satisfying other `operator.*` scope checks during device-auth verification so local CLI/TUI sessions stop entering pairing-required loops for pairing/approval-scoped commands. (#22062, #22193, #21191) Thanks @Botaccess, @jhartshorn, and @ctbritt. -- Gateway/Pairing: preserve existing approved token scopes when processing repair pairings that omit `scopes`, preventing empty-scope token regressions on reconnecting clients. (#21906) Thanks @paki81. -- Plugins/CLI: make `openclaw plugins enable` and plugin install/link flows update allowlists via shared plugin-enable policy so enabled plugins are not left disabled by allowlist mismatch. (#23190) Thanks @downwind7clawd-ctrl. -- Memory/QMD: add optional `memory.qmd.mcporter` search routing so QMD `query/search/vsearch` can run through mcporter keep-alive flows (including multi-collection paths) to reduce cold starts, while keeping searches on agent-scoped QMD state for consistent recall. (#19617) Thanks @nicole-luxe and @vignesh07. -- Chat/UI: strip inline reply/audio directive tags (`[[reply_to_current]]`, `[[reply_to:]]`, `[[audio_as_voice]]`) from displayed chat history, live chat event output, and session preview snippets so control tags no longer leak into user-visible surfaces. -- BlueBubbles/DM history: restore DM backfill context with account-scoped rolling history, bounded backfill retries, and safer history payload limits. (#20302) Thanks @Ryan-Haines. -- Security/Config: block prototype-key traversal during config merge patch and legacy migration merge helpers (`__proto__`, `constructor`, `prototype`) to prevent prototype pollution during config mutation flows. (#22968) Thanks @Clawborn. -- Security/Shell env: validate login-shell executable paths for shell-env fallback (`/etc/shells` + trusted prefixes) and block `SHELL` in dangerous env override policy paths so untrusted shell-path injection falls back safely to `/bin/sh`. Thanks @athuljayaram for reporting. -- Security/Config: make parsed chat allowlist checks fail closed when `allowFrom` is empty, restoring expected DM/pairing gating. -- Security/Exec: in non-default setups that manually add `sort` to `tools.exec.safeBins`, block `sort --compress-program` so allowlist-mode safe-bin checks cannot bypass approval. Thanks @tdjackey for reporting. -- Security/Exec approvals: when users choose `allow-always` for shell-wrapper commands (for example `/bin/zsh -lc ...`), persist allowlist patterns for the inner executable(s) instead of the wrapper shell binary, preventing accidental broad shell allowlisting in moderate mode. (#23276) Thanks @xrom2863. -- Security/macOS app beta: enforce path-only `system.run` allowlist matching (drop basename matches like `echo`), migrate legacy basename entries to last resolved paths when available, and harden shell-chain handling to fail closed on unsafe parse/control syntax (including quoted command substitution/backticks). This is an optional allowlist-mode feature; default installs remain deny-by-default. This ships in the next npm release. Thanks @tdjackey for reporting. -- Security/SSRF: expand IPv4 fetch guard blocking to include RFC special-use/non-global ranges (including benchmarking, TEST-NET, multicast, and reserved/broadcast blocks), and centralize range checks into a single CIDR policy table to reduce classifier drift. -- Security/Archive: block zip symlink escapes during archive extraction. -- Security/Media sandbox: keep tmp media allowance for absolute tmp paths only and enforce symlink-escape checks before sandbox-validated reads, preventing tmp symlink exfiltration and relative `../` sandbox escapes when sandboxes live under tmp. (#17892) Thanks @dashed. -- Security/Discord: add `openclaw security audit` warnings for name/tag-based Discord allowlist entries (DM allowlists, guild/channel `users`, and pairing-store entries), highlighting slug-collision risk while keeping name-based matching supported, and canonicalize resolved Discord allowlist names to IDs at runtime without rewriting config files. Thanks @tdjackey for reporting. -- Security/Gateway: block node-role connections when device identity metadata is missing. -- Security/Media: enforce inbound media byte limits during download/read across Discord, Telegram, Zalo, Microsoft Teams, and BlueBubbles to prevent oversized payload memory spikes before rejection. This ships in the next npm release. Thanks @tdjackey for reporting. -- Media/Understanding: preserve `application/pdf` MIME classification during text-like file heuristics so PDF uploads use PDF extraction paths instead of being inlined as raw text. (#23191) Thanks @claudeplay2026-byte. -- Security/Control UI: block symlink-based out-of-root static file reads by enforcing realpath containment and file-identity checks when serving Control UI assets and SPA fallback `index.html`. This ships in the next npm release. Thanks @tdjackey for reporting. -- Security/MSTeams media: enforce allowlist checks for SharePoint reference attachment URLs and redirect targets during Graph-backed media fetches so redirect chains cannot escape configured media host boundaries. This ships in the next npm release. Thanks @tdjackey for reporting. -- Security/macOS discovery: fail closed for unresolved discovery endpoints by clearing stale remote selection values, use resolved service host only for SSH target derivation, and keep remote URL config aligned with resolved endpoint availability. (#21618) Thanks @bmendonca3. -- Chat/Usage/TUI: strip synthetic inbound metadata blocks (including `Conversation info` and trailing `Untrusted context` channel metadata wrappers) from displayed conversation history so internal prompt context no longer leaks into user-visible logs. -- CI/Tests: fix TypeScript case-table typing and lint assertion regressions so `pnpm check` passes again after Synology Chat landing. (#23012) Thanks @druide67. -- Security/Browser relay: harden extension relay auth token handling for `/extension` and `/cdp` pathways. -- Cron: persist `delivered` state in cron job records so delivery failures remain visible in status and logs. (#19174) Thanks @simonemacario. -- Config/Doctor: only repair the OAuth credentials directory when affected channels are configured, avoiding fresh-install noise. -- Usage/Pricing: correct MiniMax M2.5 pricing defaults to fix inflated cost reporting. (#22755) Thanks @miloudbelarebia. -- Gateway/Daemon: verify gateway health after daemon restart. -- Agents/UI text: stop rewriting normal assistant billing/payment language outside explicit error contexts. (#17834) Thanks @niceysam. - -## 2026.2.21 - -### Changes - -- Models/Google: add Gemini 3.1 support (`google/gemini-3.1-pro-preview`). -- Providers/Onboarding: add Volcano Engine (Doubao) and BytePlus providers/models (including coding variants), wire onboarding auth choices for interactive + non-interactive flows, and align docs to `volcengine-api-key`. (#7967) Thanks @funmore123. -- Channels/CLI: add per-account/channel `defaultTo` outbound routing fallback so `openclaw agent --deliver` can send without explicit `--reply-to` when a default target is configured. (#16985) Thanks @KirillShchetinin. -- Channels: allow per-channel model overrides via `channels.modelByChannel` and note them in /status. Thanks @thewilloftheshadow. -- Telegram/Streaming: simplify preview streaming config to `channels.telegram.streaming` (boolean), auto-map legacy `streamMode` values, and remove block-vs-partial preview branching. (#22012) thanks @obviyus. -- Discord/Streaming: add stream preview mode for live draft replies with partial/block options and configurable chunking. Thanks @thewilloftheshadow. Inspiration @neoagentic-ship-it. -- Discord/Telegram: add configurable lifecycle status reactions for queued/thinking/tool/done/error phases with a shared controller and emoji/timing overrides. Thanks @wolly-tundracube and @thewilloftheshadow. -- Discord/Voice: add voice channel join/leave/status via `/vc`, plus auto-join configuration for realtime voice conversations. Thanks @thewilloftheshadow. -- Discord: add configurable ephemeral defaults for slash-command responses. (#16563) Thanks @wei. -- Discord: support updating forum `available_tags` via channel edit actions for forum tag management. (#12070) Thanks @xiaoyaner0201. -- Discord: include channel topics in trusted inbound metadata on new sessions. Thanks @thewilloftheshadow. -- Discord/Subagents: add thread-bound subagent sessions on Discord with per-thread focus/list controls and thread-bound continuation routing for spawned helper agents. (#21805) Thanks @onutc. -- iOS/Chat: clean chat UI noise by stripping inbound untrusted metadata/timestamp prefixes, formatting tool outputs into concise summaries/errors, compacting the composer while typing, and supporting tap-to-dismiss keyboard in chat view. (#22122) thanks @mbelinky. -- iOS/Watch: bridge mirrored watch prompt notification actions into iOS quick-reply handling, including queued action handoff until app model initialization. (#22123) thanks @mbelinky. -- iOS/Gateway: stabilize background wake and reconnect behavior with background reconnect suppression/lease windows, BGAppRefresh wake fallback, location wake hook throttling, and APNs wake retry+nudge instrumentation. (#21226) thanks @mbelinky. -- Auto-reply/UI: add model fallback lifecycle visibility in verbose logs, /status active-model context with fallback reason, and cohesive WebUI fallback indicators. (#20704) Thanks @joshavant. -- MSTeams: dedupe sent-message cache storage by removing duplicate per-message Set storage and using timestamps Map keys as the single membership source. (#22514) Thanks @TaKO8Ki. -- Agents/Subagents: default subagent spawn depth now uses shared `maxSpawnDepth=2`, enabling depth-1 orchestrator spawning by default while keeping depth policy checks consistent across spawn and prompt paths. (#22223) Thanks @tyler6204. -- Security/Agents: make owner-ID obfuscation use a dedicated HMAC secret from configuration (`ownerDisplaySecret`) and update hashing behavior so obfuscation is decoupled from gateway token handling for improved control. (#7343) Thanks @vincentkoc. -- Security/Infra: switch gateway lock and tool-call synthetic IDs from SHA-1 to SHA-256 with unchanged truncation length to strengthen hash basis while keeping deterministic behavior and lock key format. (#7343) Thanks @vincentkoc. -- Dependencies/Tooling: add non-blocking dead-code scans in CI via Knip/ts-prune/ts-unused-exports to surface unused dependencies and exports earlier. (#22468) Thanks @vincentkoc. -- Dependencies/Unused Dependencies: remove or scope unused root and extension deps (`@larksuiteoapi/node-sdk`, `signal-utils`, `ollama`, `lit`, `@lit/context`, `@lit-labs/signals`, `@microsoft/agents-hosting-express`, `@microsoft/agents-hosting-extensions-teams`, and plugin-local `openclaw` devDeps in `extensions/open-prose`, `extensions/lobster`, and `extensions/llm-task`). (#22471, #22495) Thanks @vincentkoc. -- Dependencies/A2UI: harden dependency resolution after root cleanup (resolve `lit`, `@lit/context`, `@lit-labs/signals`, and `signal-utils` from workspace/root) and simplify bundling fallback behavior, including `pnpm dlx rolldown` compatibility. (#22481, #22507) Thanks @vincentkoc. - -### Fixes - -- Security/Agents: cap embedded Pi runner outer retry loop with a higher profile-aware dynamic limit (32-160 attempts) and return an explicit `retry_limit` error payload when retries never converge, preventing unbounded internal retry cycles (`GHSA-76m6-pj3w-v7mf`). -- Telegram: detect duplicate bot-token ownership across Telegram accounts at startup/status time, mark secondary accounts as not configured with an explicit fix message, and block duplicate account startup before polling to avoid endless `getUpdates` conflict loops. -- Agents/Tool images: include source filenames in `agents/tool-images` resize logs so compression events can be traced back to specific files. -- Providers/OAuth: harden Qwen and Chutes refresh handling by validating refresh response expiry values and preserving prior refresh tokens when providers return empty refresh token fields, with regression coverage for empty-token responses. -- Models/Kimi-Coding: add missing implicit provider template for `kimi-coding` with correct `anthropic-messages` API type and base URL, fixing 403 errors when using Kimi for Coding. (#22409) -- Auto-reply/Tools: forward `senderIsOwner` through embedded queued/followup runner params so owner-only tools remain available for authorized senders. (#22296) thanks @hcoj. -- Discord: restore model picker back navigation when a provider is missing and document the Discord picker flow. (#21458) Thanks @pejmanjohn and @thewilloftheshadow. -- Memory/QMD: respect per-agent `memorySearch.enabled=false` during gateway QMD startup initialization, split multi-collection QMD searches into per-collection queries (`search`/`vsearch`/`query`) to avoid sparse-term drops, prefer collection-hinted doc resolution to avoid stale-hash collisions, retry boot updates on transient lock/timeout failures, skip `qmd embed` in BM25-only `search` mode (including `memory index --force`), and serialize embed runs globally with failure backoff to prevent CPU storms on multi-agent hosts. (#20581, #21590, #20513, #20001, #21266, #21583, #20346, #19493) Thanks @danielrevivo, @zanderkrause, @sunyan034-cmd, @tilleulenspiegel, @dae-oss, @adamlongcreativellc, @jonathanadams96, and @kiliansitel. -- Memory/Builtin: prevent automatic sync races with manager shutdown by skipping post-close sync starts and waiting for in-flight sync before closing SQLite, so `onSearch`/`onSessionStart` no longer fail with `database is not open` in ephemeral CLI flows. (#20556, #7464) Thanks @FuzzyTG and @henrybottter. -- Providers/Copilot: drop persisted assistant `thinking` blocks for Claude models (while preserving turn structure/tool blocks) so follow-up requests no longer fail on invalid `thinkingSignature` payloads. (#19459) Thanks @jackheuberger. -- Providers/Copilot: add `claude-sonnet-4.6` and `claude-sonnet-4.5` to the default GitHub Copilot model catalog and add coverage for model-list/definition helpers. (#20270, fixes #20091) Thanks @Clawborn. -- Auto-reply/WebChat: avoid defaulting inbound runtime channel labels to unrelated providers (for example `whatsapp`) for webchat sessions so channel-specific formatting guidance stays accurate. (#21534) Thanks @lbo728. -- Status: include persisted `cacheRead`/`cacheWrite` in session summaries so compact `/status` output consistently shows cache hit percentages from real session data. -- Heartbeat/Cron: restore interval heartbeat behavior so missing `HEARTBEAT.md` no longer suppresses runs (only effectively empty files skip), preserving prompt-driven and tagged-cron execution paths. -- WhatsApp/Cron/Heartbeat: enforce allowlisted routing for implicit scheduled/system delivery by merging pairing-store + configured `allowFrom` recipients, selecting authorized recipients when last-route context points to a non-allowlisted chat, and preventing heartbeat fan-out to recent unauthorized chats. -- Heartbeat/Active hours: constrain active-hours `24` sentinel parsing to `24:00` in time validation so invalid values like `24:30` are rejected early. (#21410) thanks @adhitShet. -- Heartbeat: treat `activeHours` windows with identical `start`/`end` times as zero-width (always outside the window) instead of always-active. (#21408) thanks @adhitShet. -- CLI/Pairing: default `pairing list` and `pairing approve` to the sole available pairing channel when omitted, so TUI-only setups can recover from `pairing required` without guessing channel arguments. (#21527) Thanks @losts1. -- TUI/Pairing: show explicit pairing-required recovery guidance after gateway disconnects that return `pairing required`, including approval steps to unblock quickstart TUI hatching on fresh installs. (#21841) Thanks @nicolinux. -- TUI/Input: suppress duplicate backspace events arriving in the same input burst window so SSH sessions no longer delete two characters per backspace press in the composer. (#19318) Thanks @eheimer. -- TUI/Models: scope `models.list` to the configured model allowlist (`agents.defaults.models`) so `/model` picker no longer floods with unrelated catalog entries by default. (#18816) Thanks @fwends. -- TUI/Heartbeat: suppress heartbeat ACK/prompt noise in chat streaming when `showOk` is disabled, while still preserving non-ACK heartbeat alerts in final output. (#20228) Thanks @bhalliburton. -- TUI/History: cap chat-log component growth and prune stale render nodes/references so large default history loads no longer overflow render recursion with `RangeError: Maximum call stack size exceeded`. (#18068) Thanks @JaniJegoroff. -- Memory/QMD: diversify mixed-source search ranking when both session and memory collections are present so session transcript hits no longer crowd out durable memory-file matches in top results. (#19913) Thanks @alextempr. -- Memory/Tools: return explicit `unavailable` warnings/actions from `memory_search` when embedding/provider failures occur (including quota exhaustion), so disabled memory does not look like an empty recall result. (#21894) Thanks @XBS9. -- Session/Startup: require the `/new` and `/reset` greeting path to run Session Startup file-reading instructions before responding, so daily memory startup context is not skipped on fresh-session greetings. (#22338) Thanks @armstrong-pv. -- Auth/Onboarding: align OAuth profile-id config mapping with stored credential IDs for OpenAI Codex and Chutes flows, preventing `provider:default` mismatches when OAuth returns email-scoped credentials. (#12692) thanks @mudrii. -- Provider/HTTP: treat HTTP 503 as failover-eligible for LLM provider errors. (#21086) Thanks @Protocol-zero-0. -- Slack: pass `recipient_team_id` / `recipient_user_id` through Slack native streaming calls so `chat.startStream`/`appendStream`/`stopStream` work reliably across DMs and Slack Connect setups, and disable block streaming when native streaming is active. (#20988) Thanks @Dithilli. Earlier recipient-ID groundwork was contributed in #20377 by @AsserAl1012. -- CLI/Config: add canonical `--strict-json` parsing for `config set` and keep `--json` as a legacy alias to reduce help/behavior drift. (#21332) thanks @adhitShet. -- CLI/Config: preserve explicitly unset config paths in persisted JSON after writes so `openclaw config unset ` no longer re-introduces defaulted keys (for example `commands.ownerDisplay`) through schema normalization. (#22984) Thanks @aronchick. -- CLI: keep `openclaw -v` as a root-only version alias so subcommand `-v, --verbose` flags (for example ACP/hooks/skills) are no longer intercepted globally. (#21303) thanks @adhitShet. -- Memory: return empty snippets when `memory_get`/QMD read files that have not been created yet, and harden memory indexing/session helpers against ENOENT races so missing Markdown no longer crashes tools. (#20680) Thanks @pahdo. -- Telegram/Streaming: always clean up draft previews even when dispatch throws before fallback handling, preventing orphaned preview messages during failed runs. (#19041) thanks @mudrii. -- Telegram/Streaming: split reasoning and answer draft preview lanes to prevent cross-lane overwrites, and ignore literal `` tags inside inline/fenced code snippets so sample markup is not misrouted as reasoning. (#20774) Thanks @obviyus. -- Telegram/Streaming: restore 30-char first-preview debounce and scope `NO_REPLY` prefix suppression to partial sentinel fragments so normal `No...` text is not filtered. (#22613) thanks @obviyus. -- Telegram/Status reactions: refresh stall timers on repeated phase updates and honor ack-reaction scope when lifecycle reactions are enabled, preventing false stall emojis and unwanted group reactions. Thanks @wolly-tundracube and @thewilloftheshadow. -- Telegram/Status reactions: keep lifecycle reactions active when available-reactions lookup fails by falling back to unrestricted variant selection instead of suppressing reaction updates. (#22380) thanks @obviyus. -- Discord/Events: await `DiscordMessageListener` message handlers so regular `MESSAGE_CREATE` traffic is processed through queue ordering/timeout flow instead of fire-and-forget drops. (#22396) Thanks @sIlENtbuffER. -- Discord/Streaming: apply `replyToMode: first` only to the first Discord chunk so block-streamed replies do not spam mention pings. (#20726) Thanks @thewilloftheshadow for the report. -- Discord/Components: map DM channel targets back to user-scoped component sessions so button/select interactions stay in the main DM session. Thanks @thewilloftheshadow. -- Discord/Allowlist: lazy-load guild lists when resolving Discord user allowlists so ID-only entries resolve even if guild fetch fails. (#20208) Thanks @zhangjunmengyang. -- Discord/Gateway: handle close code 4014 (missing privileged gateway intents) without crashing the gateway. Thanks @thewilloftheshadow. -- Discord: ingest inbound stickers as media so sticker-only messages and forwarded stickers are visible to agents. Thanks @thewilloftheshadow. -- Auto-reply/Runner: emit `onAgentRunStart` only after agent lifecycle or tool activity begins (and only once per run), so fallback preflight errors no longer mark runs as started. (#21165) Thanks @shakkernerd. -- Auto-reply/Tool results: serialize tool-result delivery and keep the delivery chain progressing after individual failures so concurrent tool outputs preserve user-visible ordering. (#21231) thanks @ahdernasr. -- Auto-reply/Prompt caching: restore prefix-cache stability by keeping inbound system metadata session-stable and moving per-message IDs (`message_id`, `message_id_full`, `reply_to_id`, `sender_id`) into untrusted conversation context. (#20597) Thanks @anisoptera. -- iOS/Watch: add actionable watch approval/reject controls and quick-reply actions so watch-originated approvals and responses can be sent directly from notification flows. (#21996) Thanks @mbelinky. -- iOS/Watch: refresh iOS and watch app icon assets with the lobster icon set to keep phone/watch branding aligned. (#21997) Thanks @mbelinky. -- CLI/Onboarding: fix Anthropic-compatible custom provider verification by normalizing base URLs to avoid duplicate `/v1` paths during setup checks. (#21336) Thanks @17jmumford. -- iOS/Gateway/Tools: prefer uniquely connected node matches when duplicate display names exist, surface actionable `nodes invoke` pairing-required guidance with request IDs, and refresh active iOS gateway registration after location-capability setting changes so capability updates apply immediately. (#22120) thanks @mbelinky. -- Gateway/Auth: require `gateway.trustedProxies` to include a loopback proxy address when `auth.mode="trusted-proxy"` and `bind="loopback"`, preventing same-host proxy misconfiguration from silently blocking auth. (#22082, follow-up to #20097) thanks @mbelinky. -- Gateway/Auth: allow trusted-proxy mode with loopback bind for same-host reverse-proxy deployments, while still requiring configured `gateway.trustedProxies`. (#20097) thanks @xinhuagu. -- Gateway/Auth: allow authenticated clients across roles/scopes to call `health` while preserving role and scope enforcement for non-health methods. (#19699) thanks @Nachx639. -- Gateway/Hooks: include transform export name in hook-transform cache keys so distinct exports from the same module do not reuse the wrong cached transform function. (#13855) thanks @mcaxtr. -- Gateway/Control UI: return 404 for missing static-asset paths instead of serving SPA fallback HTML, while preserving client-route fallback behavior for extensionless and non-asset dotted paths. (#12060) thanks @mcaxtr. -- Gateway/Pairing: prevent device-token rotate scope escalation by enforcing an approved-scope baseline, preserving approved scopes across metadata updates, and rejecting rotate requests that exceed approved role scope implications. (#20703) thanks @coygeek. -- Gateway/Pairing: clear persisted paired-device state when the gateway client closes with `device token mismatch` (`1008`) so reconnect flows can cleanly re-enter pairing. (#22071) Thanks @mbelinky. -- Gateway/Config: allow `gateway.customBindHost` in strict config validation when `gateway.bind="custom"` so valid custom bind-host configurations no longer fail startup. (#20318, fixes #20289) Thanks @MisterGuy420. -- Gateway/Pairing: tolerate legacy paired devices missing `roles`/`scopes` metadata in websocket upgrade checks and backfill metadata on reconnect. (#21447, fixes #21236) Thanks @joshavant. -- Gateway/Pairing/CLI: align read-scope compatibility in pairing/device-token checks and add local `openclaw devices` fallback recovery for loopback `pairing required` deadlocks, with explicit fallback notice to unblock approval bootstrap flows. (#21616) Thanks @shakkernerd. -- Cron: honor `cron.maxConcurrentRuns` in the timer loop so due jobs can execute up to the configured parallelism instead of always running serially. (#11595) Thanks @Takhoffman. -- Agents/Compaction: restore embedded compaction safeguard/context-pruning extension loading in production by wiring bundled extension factories into the resource loader instead of runtime file-path resolution. (#22349) Thanks @Glucksberg. -- Agents/Subagents: restore announce-chain delivery to agent injection, defer nested announce output until descendant follow-up content is ready, and prevent descendant deferrals from consuming announce retry budget so deep chains do not drop final completions. (#22223) Thanks @tyler6204. -- Agents/System Prompt: label allowlisted senders as authorized senders to avoid implying ownership. Thanks @thewilloftheshadow. -- Agents/Tool display: fix exec cwd suffix inference so `pushd ... && popd ... && ` does not keep stale `(in )` context in summaries. (#21925) Thanks @Lukavyi. -- Agents/Google: flatten residual nested `anyOf`/`oneOf` unions in Gemini tool-schema cleanup so Cloud Code Assist no longer rejects unsupported union keywords that survive earlier simplification. (#22825) Thanks @Oceanswave. -- Tools/web_search: handle xAI Responses API payloads that emit top-level `output_text` blocks (without a `message` wrapper) so Grok web_search no longer returns `No response` for those results. (#20508) Thanks @echoVic. -- Agents/Failover: treat non-default override runs as direct fallback-to-configured-primary (skip configured fallback chain), normalize default-model detection for provider casing/whitespace, and add regression coverage for override/auth error paths. (#18820) Thanks @Glucksberg. -- Docker/Build: include `ownerDisplay` in `CommandsSchema` object-level defaults so Docker `pnpm build` no longer fails with `TS2769` during plugin SDK d.ts generation. (#22558) Thanks @obviyus. -- Docker/Browser: install Playwright Chromium into `/home/node/.cache/ms-playwright` and set `node:node` ownership so browser binaries are available to the runtime user in browser-enabled images. (#22585) thanks @obviyus. -- Hooks/Session memory: trigger bundled `session-memory` persistence on both `/new` and `/reset` so reset flows no longer skip markdown transcript capture before archival. (#21382) Thanks @mofesolapaul. -- Dependencies/Agents: bump embedded Pi SDK packages (`@mariozechner/pi-agent-core`, `@mariozechner/pi-ai`, `@mariozechner/pi-coding-agent`, `@mariozechner/pi-tui`) to `0.54.0`. (#21578) Thanks @Takhoffman. -- Config/Agents: expose Pi compaction tuning values `agents.defaults.compaction.reserveTokens` and `agents.defaults.compaction.keepRecentTokens` in config schema/types and apply them in embedded Pi runner settings overrides with floor enforcement via `reserveTokensFloor`. (#21568) Thanks @Takhoffman. -- Docker: pin base images to SHA256 digests in Docker builds to prevent mutable tag drift. (#7734) Thanks @coygeek. -- Docker: run build steps as the `node` user and use `COPY --chown` to avoid recursive ownership changes, trimming image size and layer churn. Thanks @huntharo. -- Config/Memory: restore schema help/label metadata for hybrid `mmr` and `temporalDecay` settings so configuration surfaces show correct names and guidance. (#18786) Thanks @rodrigouroz. -- Skills/SonosCLI: add troubleshooting guidance for `sonos discover` failures on macOS direct mode (`sendto: no route to host`) and sandbox network restrictions (`bind: operation not permitted`). (#21316) Thanks @huntharo. -- macOS/Build: default release packaging to `BUNDLE_ID=ai.openclaw.mac` in `scripts/package-mac-dist.sh`, so Sparkle feed URL is retained and auto-update no longer fails with an empty appcast feed. (#19750) thanks @loganprit. -- Signal/Outbound: preserve case for Base64 group IDs during outbound target normalization so cross-context routing and policy checks no longer break when group IDs include uppercase characters. (#5578) Thanks @heyhudson. -- Anthropic/Agents: preserve required pi-ai default OAuth beta headers when `context1m` injects `anthropic-beta`, preventing 401 auth failures for `sk-ant-oat-*` tokens. (#19789, fixes #19769) Thanks @minupla. -- Security/Exec: block unquoted heredoc body expansion tokens in shell allowlist analysis, reject unterminated heredocs, and require explicit approval for allowlisted heredoc execution on gateway hosts to prevent heredoc substitution allowlist bypass. Thanks @torturado for reporting. -- macOS/Security: evaluate `system.run` allowlists per shell segment in macOS node runtime and companion exec host (including chained shell operators), fail closed on shell/process substitution parsing, and require explicit approval on unsafe parse cases to prevent allowlist bypass via `rawCommand` chaining. Thanks @tdjackey for reporting. -- WhatsApp/Security: enforce allowlist JID authorization for reaction actions so authenticated callers cannot target non-allowlisted chats by forging `chatJid` + valid `messageId` pairs. Thanks @aether-ai-agent for reporting. -- ACP/Security: escape control and delimiter characters in ACP `resource_link` title/URI metadata before prompt interpolation to prevent metadata-driven prompt injection through resource links. Thanks @aether-ai-agent for reporting. -- TTS/Security: make model-driven provider switching opt-in by default (`messages.tts.modelOverrides.allowProvider=false` unless explicitly enabled), while keeping voice/style overrides available, to reduce prompt-injection-driven provider hops and unexpected TTS cost escalation. Thanks @aether-ai-agent for reporting. -- Security/Agents: keep overflow compaction retry budgeting global across tool-result truncation recovery so successful truncation cannot reset the overflow retry counter and amplify retry/cost cycles. Thanks @aether-ai-agent for reporting. -- BlueBubbles/Security: require webhook token authentication for all BlueBubbles webhook requests (including loopback/proxied setups), removing passwordless webhook fallback behavior. Thanks @zpbrent. -- iOS/Security: force `https://` for non-loopback manual gateway hosts during iOS onboarding to block insecure remote transport URLs. (#21969) Thanks @mbelinky. -- Gateway/Security: remove shared-IP fallback for canvas endpoints and require token or session capability for canvas access. Thanks @thewilloftheshadow. -- Gateway/Security: require secure context and paired-device checks for Control UI auth even when `gateway.controlUi.allowInsecureAuth` is set, and align audit messaging with the hardened behavior. (#20684) Thanks @coygeek and @Vasco0x4 for reporting. -- Gateway/Security: scope tokenless Tailscale forwarded-header auth to Control UI websocket auth only, so HTTP gateway routes still require token/password even on trusted hosts. Thanks @zpbrent for reporting. -- Docker/Security: run E2E and install-sh test images as non-root by adding appuser directives. Thanks @thewilloftheshadow. -- Skills/Security: sanitize skill env overrides to block unsafe runtime injection variables and only allow sensitive keys when declared in skill metadata, with warnings for suspicious values. Thanks @thewilloftheshadow. -- Security/Commands: block prototype-key injection in runtime `/debug` overrides and require own-property checks for gated command flags (`bash`, `config`, `debug`) so inherited prototype values cannot enable privileged commands. Thanks @tdjackey for reporting. -- Security/Browser: block non-network browser navigation protocols (including `file:`, `data:`, and `javascript:`) while preserving `about:blank`, preventing local file reads via browser tool navigation. Thanks @q1uf3ng for reporting. -- Security/Exec: block shell startup-file env injection (`BASH_ENV`, `ENV`, `BASH_FUNC_*`, `LD_*`, `DYLD_*`) across config env ingestion, node-host inherited environment sanitization, and macOS exec host runtime to prevent pre-command execution from attacker-controlled environment variables. Thanks @tdjackey. -- Security/Exec (Windows): canonicalize `cmd.exe /c` command text across validation, approval binding, and audit/event rendering to prevent trailing-argument approval mismatches in `system.run`. Thanks @tdjackey for reporting. -- Security/Gateway/Hooks: block `__proto__`, `constructor`, and `prototype` traversal in webhook template path resolution to prevent prototype-chain payload data leakage in `messageTemplate` rendering. (#22213) Thanks @SleuthCo. -- Security/OpenClawKit/UI: prevent injected inbound user context metadata blocks from leaking into chat history in TUI, webchat, and macOS surfaces by stripping all untrusted metadata prefixes at display boundaries. (#22142) Thanks @Mellowambience, @vincentkoc. -- Security/OpenClawKit/UI: strip inbound metadata blocks from user messages in TUI rendering while preserving user-authored content. (#22345) Thanks @kansodata, @vincentkoc. -- Security/OpenClawKit/UI: prevent inbound metadata leaks and reply-tag streaming artifacts in TUI rendering by stripping untrusted metadata prefixes at display boundaries. (#22346) Thanks @akramcodez, @vincentkoc. -- Security/Agents: restrict local MEDIA tool attachments to core tools and the OpenClaw temp root to prevent untrusted MCP tool file exfiltration. Thanks @NucleiAv and @thewilloftheshadow. -- Security/Net: strip sensitive headers (`Authorization`, `Proxy-Authorization`, `Cookie`, `Cookie2`) on cross-origin redirects in `fetchWithSsrFGuard` to prevent credential forwarding across origin boundaries. (#20313) Thanks @afurm. -- Security/Systemd: reject CR/LF in systemd unit environment values and fix argument escaping so generated units cannot be injected with extra directives. Thanks @thewilloftheshadow. -- Security/Tools: add per-wrapper random IDs to untrusted-content markers from `wrapExternalContent`/`wrapWebContent`, preventing marker spoofing from escaping content boundaries. (#19009) Thanks @Whoaa512. -- Shared/Security: reject insecure deep links that use `ws://` non-loopback gateway URLs to prevent plaintext remote websocket configuration. (#21970) Thanks @mbelinky. -- macOS/Security: reject non-loopback `ws://` remote gateway URLs in macOS remote config to block insecure plaintext websocket endpoints. (#21971) Thanks @mbelinky. -- Browser/Security: block upload path symlink escapes so browser upload sources cannot traverse outside the allowed workspace via symlinked paths. (#21972) Thanks @mbelinky. -- Security/Dependencies: bump transitive `hono` usage to `4.11.10` to incorporate timing-safe authentication comparison hardening for `basicAuth`/`bearerAuth` (`GHSA-gq3j-xvxp-8hrf`). Thanks @vincentkoc. -- Security/Gateway: parse `X-Forwarded-For` with trust-preserving semantics when requests come from configured trusted proxies, preventing proxy-chain spoofing from influencing client IP classification and rate-limit identity. Thanks @AnthonyDiSanti and @vincentkoc. -- Security/Sandbox: remove default `--no-sandbox` for the browser container entrypoint, add explicit opt-in via `OPENCLAW_BROWSER_NO_SANDBOX` / `CLAWDBOT_BROWSER_NO_SANDBOX`, and add security-audit checks for stale/missing sandbox browser Docker hash labels. Thanks @TerminalsandCoffee and @vincentkoc. -- Security/Sandbox Browser: require VNC password auth for noVNC observer sessions in the sandbox browser entrypoint, plumb per-container noVNC passwords from runtime, and emit short-lived noVNC observer token URLs while keeping loopback-only host port publishing. Thanks @TerminalsandCoffee for reporting. -- Security/Sandbox Browser: default browser sandbox containers to a dedicated Docker network (`openclaw-sandbox-browser`), add optional CDP ingress source-range restrictions, auto-create missing dedicated networks, and warn in `openclaw security --audit` when browser sandboxing runs on bridge without source-range limits. Thanks @TerminalsandCoffee for reporting. - -## 2026.2.19 - -### Changes - -- iOS/Watch: add an Apple Watch companion MVP with watch inbox UI, watch notification relay handling, and gateway command surfaces for watch status/send flows. (#20054) Thanks @mbelinky. -- iOS/Gateway: wake disconnected iOS nodes via APNs before `nodes.invoke` and auto-reconnect gateway sessions on silent push wake to reduce invoke failures while the app is backgrounded. (#20332) Thanks @mbelinky. -- Gateway/CLI: add paired-device hygiene flows with `device.pair.remove`, plus `openclaw devices remove` and guarded `openclaw devices clear --yes [--pending]` commands for removing paired entries and optionally rejecting pending requests. (#20057) Thanks @mbelinky. -- iOS/APNs: add push registration and notification-signing configuration for node delivery. (#20308) Thanks @mbelinky. -- Gateway/APNs: add a push-test pipeline for APNs delivery validation in gateway flows. (#20307) Thanks @mbelinky. -- Security/Audit: add `gateway.http.no_auth` findings when `gateway.auth.mode="none"` leaves Gateway HTTP APIs reachable, with loopback warning and remote-exposure critical severity, plus regression coverage and docs updates. -- Skills: harden coding-agent skill guidance by removing shell-command examples that interpolate untrusted issue text directly into command strings. -- Dev tooling: align `oxfmt` local/CI formatting behavior. (#12579) Thanks @vincentkoc. - -### Fixes - -- Agents/Streaming: keep assistant partial streaming active during reasoning streams, handle native `thinking_*` stream events consistently, dedupe mixed reasoning-end signals, and clear stale mutating tool errors after same-target retry success. (#20635) Thanks @obviyus. -- iOS/Chat: use a dedicated iOS chat session key for ChatSheet routing to avoid cross-client session collisions with main-session traffic. (#21139) thanks @mbelinky. -- iOS/Chat: auto-resync chat history after reconnect sequence gaps, clear stale pending runs, and avoid dead-end manual refresh errors after transient disconnects. (#21135) thanks @mbelinky. -- UI/Usage: reload usage data immediately when timezone changes so Local/UTC toggles apply the selected date range without requiring a manual refresh. (#17774) -- iOS/Screen: move `WKWebView` lifecycle ownership into `ScreenWebView` coordinator and explicit attach/detach flow to reduce gesture/lifecycle crash risk (`__NSArrayM insertObject:atIndex:` paths) during screen tab updates. (#20366) Thanks @ngutman. -- iOS/Onboarding: prevent pairing-status flicker during auto-resume by keeping resumed state transitions stable. (#20310) Thanks @mbelinky. -- iOS/Onboarding: stabilize pairing and reconnect behavior by resetting stale pairing request state on manual retry, disconnecting both operator and node gateways on operator failure, and avoiding duplicate pairing loops from operator transport identity attachment. (#20056) Thanks @mbelinky. -- iOS/Signing: restore local auto-selected signing-team overrides during iOS project generation by wiring `.local-signing.xcconfig` into the active signing config and emitting `OPENCLAW_DEVELOPMENT_TEAM` in local signing setup. (#19993) Thanks @ngutman. -- Telegram: unify message-like inbound handling so `message` and `channel_post` share the same dedupe/access/media pipeline and remain behaviorally consistent. (#20591) Thanks @obviyus. -- Telegram/Agents: gate exec/bash tool-failure warnings behind verbose mode so default Telegram replies stay clean while verbose sessions still surface diagnostics. (#20560) Thanks @obviyus. -- Telegram/Cron/Heartbeat: honor explicit Telegram topic targets in cron and heartbeat delivery (`:topic:`) so scheduled sends land in the configured topic instead of the last active thread. (#19367) Thanks @Lukavyi. -- Gateway/Daemon: forward `TMPDIR` into installed service environments so macOS LaunchAgent gateway runs can open SQLite temp/journal files reliably instead of failing with `SQLITE_CANTOPEN`. (#20512) Thanks @Clawborn. -- Agents/Billing: include the active model that produced a billing error in user-facing billing messages (for example, `OpenAI (gpt-5.3)`) across payload, failover, and lifecycle error paths, so users can identify exactly which key needs credits. (#20510) Thanks @echoVic. -- Gateway/TUI: honor `agents.defaults.blockStreamingDefault` for `chat.send` by removing the hardcoded block-streaming disable override, so replies can use configured block-mode delivery. (#19693) Thanks @neipor. -- UI/Sessions: accept the canonical main session-key alias in Chat UI flows so main-session routing stays consistent. (#20311) Thanks @mbelinky. -- OpenClawKit/Protocol: preserve JSON boolean literals (`true`/`false`) when bridging through `AnyCodable` so Apple client RPC params no longer re-encode booleans as `1`/`0`. Thanks @mbelinky. -- Commands/Doctor: skip embedding-provider warnings when `memory.backend` is `qmd`, because QMD manages embeddings internally and does not require `memorySearch` providers. (#17263) Thanks @miloudbelarebia. -- Canvas/A2UI: improve bundled-asset resolution and empty-state handling so UI fallbacks render reliably. (#20312) Thanks @mbelinky. -- Commands/Doctor: avoid rewriting invalid configs with new `gateway.auth.token` defaults during repair and only write when real config changes are detected, preventing accidental token duplication and backup churn. -- Gateway/Auth: default unresolved gateway auth to token mode with startup auto-generation/persistence of `gateway.auth.token`, while allowing explicit `gateway.auth.mode: "none"` for intentional open loopback setups. (#20686) thanks @gumadeiras. -- Channels/Matrix: fix mention detection for `formatted_body` Matrix-to links by handling matrix.to mention formats consistently. (#16941) Thanks @zerone0x. -- Heartbeat/Cron: skip interval heartbeats when `HEARTBEAT.md` is missing or empty and no tagged cron events are queued, while preserving cron-event fallback for queued tagged reminders. (#20461) thanks @vikpos. -- Browser/Relay: reuse an already-running extension relay when the relay port is occupied by another OpenClaw process, while still failing on non-relay port collisions to avoid masking unrelated listeners. (#20035) Thanks @mbelinky. -- Scripts: update clawdock helper command support to include `docker-compose.extra.yml` where available. (#17094) Thanks @zerone0x. -- Lobster/Config: remove Lobster executable-path overrides (`lobsterPath`), require PATH-based execution, and add focused Windows wrapper-resolution tests to keep shell-free behavior stable. -- Gateway/WebChat: block `sessions.patch` and `sessions.delete` for WebChat clients so session-store mutations stay restricted to non-WebChat operator flows. Thanks @allsmog for reporting. -- Gateway: clarify launchctl GUI domain bootstrap failure on macOS. (#13795) Thanks @vincentkoc. -- Lobster/CI: fix flaky test Windows cmd shim script resolution. (#20833) Thanks @vincentkoc. -- Browser/Relay: require gateway-token auth on both `/extension` and `/cdp`, and align Chrome extension setup to use a single `gateway.auth.token` input for relay authentication. Thanks @tdjackey for reporting. -- Gateway/Hooks: run BOOT.md startup checks per configured agent scope, including per-agent session-key resolution, startup-hook regression coverage, and non-success boot outcome logging for diagnosability. (#20569) thanks @mcaxtr. -- Protocol/Apple: regenerate Swift gateway models for `push.test` so `pnpm protocol:check` stays green on main. Thanks @mbelinky. -- Sandbox/Registry: serialize container and browser registry writes with shared file locks and atomic replacement to prevent lost updates and delete rollback races from desyncing `sandbox list`, `prune`, and `recreate --all`. Thanks @kexinoh. -- OTEL/diagnostics-otel: complete OpenTelemetry v2 API migration. (#12897) Thanks @vincentkoc. -- Cron/Webhooks: protect cron webhook POST delivery with SSRF-guarded outbound fetch (`fetchWithSsrFGuard`) to block private/metadata destinations before request dispatch. Thanks @Adam55A-code. -- Security/Voice Call: harden `voice-call` telephony TTS override merging by blocking unsafe deep-merge keys (`__proto__`, `prototype`, `constructor`) and add regression coverage for top-level and nested prototype-pollution payloads. -- Security/Windows Daemon: harden Scheduled Task `gateway.cmd` generation by quoting cmd metacharacter arguments, escaping `%`/`!` expansions, and rejecting CR/LF in arguments, descriptions, and environment assignments (`set "KEY=VALUE"`), preventing command injection in Windows daemon startup scripts. Thanks @tdjackey for reporting. -- Security/Gateway/Canvas: replace shared-IP fallback auth with node-scoped session capability URLs for `/__openclaw__/canvas/*` and `/__openclaw__/a2ui/*`, fail closed when trusted-proxy requests omit forwarded client headers, and add IPv6/proxy-header regression coverage. Thanks @aether-ai-agent for reporting. -- Security/Net: enforce strict dotted-decimal IPv4 literals in SSRF checks and fail closed on unsupported legacy forms (octal/hex/short/packed, for example `0177.0.0.1`, `127.1`, `2130706433`) before DNS lookup. -- Security/Discord: enforce trusted-sender guild permission checks for moderation actions (`timeout`, `kick`, `ban`) and ignore untrusted `senderUserId` params to prevent privilege escalation in tool-driven flows. Thanks @aether-ai-agent for reporting. -- Security/ACP+Exec: add `openclaw acp --token-file/--password-file` secret-file support (with inline secret flag warnings), redact ACP working-directory prefixes to `~` home-relative paths, constrain exec script preflight file inspection to the effective `workdir` boundary, and add security-audit warnings when `tools.exec.host="sandbox"` is configured while sandbox mode is off. -- Security/Plugins/Hooks: enforce runtime/package path containment with realpath checks so `openclaw.extensions`, `openclaw.hooks`, and hook handler modules cannot escape their trusted roots via traversal or symlinks. -- Security/Discord: centralize trusted sender checks for moderation actions in message-action dispatch, share moderation command parsing across handlers, and clarify permission helpers with explicit any/all semantics. -- Security/ACP: harden ACP bridge session management with duplicate-session refresh, idle-session reaping, oldest-idle soft-cap eviction, and burst rate limiting on session creation to reduce local DoS risk without disrupting normal IDE usage. -- Security/ACP: bound ACP prompt text payloads to 2 MiB before gateway forwarding, account for join separator bytes during pre-concatenation size checks, and avoid stale active-run session state when oversized prompts are rejected. Thanks @aether-ai-agent for reporting. -- Security/Plugins/Hooks: add optional `--pin` for npm plugin/hook installs, persist resolved npm metadata (`name`, `version`, `spec`, integrity, shasum, timestamp), warn/confirm on integrity drift during updates, and extend `openclaw security audit` to flag unpinned specs, missing integrity metadata, and install-record version drift. -- Security/Plugins: harden plugin discovery by blocking unsafe candidates (root escapes, world-writable paths, suspicious ownership), add startup warnings when `plugins.allow` is empty with discoverable non-bundled plugins, and warn on loaded plugins without install/load-path provenance. -- Security/Gateway: rate-limit control-plane write RPCs (`config.apply`, `config.patch`, `update.run`) to 3 requests per minute per `deviceId+clientIp`, add restart single-flight coalescing plus a 30-second restart cooldown, and log actor/device/ip with changed-path audit details for config/update-triggered restarts. -- Security/Webhooks: harden Feishu and Zalo webhook ingress with webhook-mode token preconditions, loopback-default Feishu bind host, JSON content-type enforcement, per-path rate limiting, replay dedupe for Zalo events, constant-time Zalo secret comparison, and anomaly status counters. -- Security/Plugins: for the next npm release, clarify plugin trust boundary and keep `runtime.system.runCommandWithTimeout` available by default for trusted in-process plugins. Thanks @markmusson for reporting. -- Security/Skills: for the next npm release, reject symlinks during skill packaging to prevent external file inclusion in distributed `.skill` archives. Thanks @aether-ai-agent for reporting. -- Security/Gateway: fail startup when `hooks.token` matches `gateway.auth.token` so hooks and gateway token reuse is rejected at boot. (#20813) Thanks @coygeek. -- Security/Network: block plaintext `ws://` connections to non-loopback hosts and require secure websocket transport elsewhere. (#20803) Thanks @jscaldwell55. -- Security/Config: parse frontmatter YAML using the YAML 1.2 core schema to avoid implicit coercion of `on`/`off`-style values. (#20857) Thanks @davidrudduck. -- Security/Discord: escape backticks in exec-approval embed content to prevent markdown formatting injection via command text. (#20854) Thanks @davidrudduck. -- Security/Agents: replace shell-based `execSync` usage with `execFileSync` in command lookup helpers to eliminate shell argument interpolation risk. (#20655) Thanks @mahanandhi. -- Security/Media: use `crypto.randomBytes()` for temp file names and set owner-only permissions for TTS temp files. (#20654) Thanks @mahanandhi. -- Security/Gateway: set baseline security headers (`X-Content-Type-Options: nosniff`, `Referrer-Policy: no-referrer`) on gateway HTTP responses. (#10526) Thanks @abdelsfane. -- Security/iMessage: harden remote attachment SSH/SCP handling by requiring strict host-key verification, validating `channels.imessage.remoteHost` as `host`/`user@host`, and rejecting unsafe host tokens from config or auto-detection. Thanks @allsmog for reporting. -- Security/Feishu: prevent path traversal in Feishu inbound media temp-file writes by replacing key-derived temp filenames with UUID-based names. Thanks @allsmog for reporting. -- Security/Feishu: escape mention regex metacharacters in `stripBotMention` so crafted mention metadata cannot trigger regex injection or ReDoS during inbound message parsing. (#20916) Thanks @orlyjamie for the fix and @allsmog for reporting. -- LINE/Security: harden inbound media temp-file naming by using UUID-based temp paths for downloaded media instead of external message IDs. (#20792) Thanks @mbelinky. -- Security/Media: harden local media ingestion against TOCTOU/symlink swap attacks by pinning reads to a single file descriptor with symlink rejection and inode/device verification in `saveMediaSource`. Thanks @dorjoos for reporting. -- Security/Lobster (Windows): for the next npm release, remove shell-based fallback when launching Lobster wrappers (`.cmd`/`.bat`) and switch to explicit argv execution with wrapper entrypoint resolution, preventing command injection while preserving Windows wrapper compatibility. Thanks @allsmog for reporting. -- Security/Exec: require `tools.exec.safeBins` binaries to resolve from trusted bin directories (system defaults plus gateway startup `PATH`) so PATH-hijacked trojan binaries cannot bypass allowlist checks. Thanks @jackhax for reporting. -- Security/Exec: remove file-existence oracle behavior from `tools.exec.safeBins` by using deterministic argv-only stdin-safe validation and blocking file-oriented flags (for example `sort -o`, `jq -f`, `grep -f`) so allow/deny results no longer disclose host file presence. Thanks @nedlir for reporting. -- Security/Browser: route browser URL navigation through one SSRF-guarded validation path for tab-open/CDP-target/Playwright navigation flows and block private/metadata destinations by default (configurable via `browser.ssrfPolicy`). Thanks @dorjoos for reporting. -- Security/Exec: for the next npm release, harden safe-bin stdin-only enforcement by blocking output/recursive flags (`sort -o/--output`, grep recursion) and tightening default safe bins to remove `sort`/`grep`, preventing safe-bin allowlist bypass for file writes/recursive reads. Thanks @nedlir for reporting. -- Security/Exec: block grep safe-bin positional operand bypass by setting grep positional budget to zero, so `-e/--regexp` cannot smuggle bare filename reads (for example `.env`) via ambiguous positionals; safe-bin grep patterns must come from `-e/--regexp`. Thanks @athuljayaram for reporting. -- Security/Gateway/Agents: remove implicit admin scopes from agent tool gateway calls by classifying methods to least-privilege operator scopes, and enforce owner-only tooling (`cron`, `gateway`, `whatsapp_login`) through centralized tool-policy wrappers plus tool metadata to prevent non-owner DM privilege escalation. Ships in the next npm release. Thanks @Adam55A-code for reporting. -- Security/Gateway: centralize gateway method-scope authorization and default non-CLI gateway callers to least-privilege method scopes, with explicit CLI scope handling, full core-handler scope classification coverage, and regression guards to prevent scope drift. -- Security/Net: block SSRF bypass via NAT64 (`64:ff9b::/96`, `64:ff9b:1::/48`), 6to4 (`2002::/16`), and Teredo (`2001:0000::/32`) IPv6 transition addresses, and fail closed on IPv6 parse errors. Thanks @jackhax. -- Security/OTEL: sanitize OTLP endpoint URL resolution. (#13791) Thanks @vincentkoc. -- Security: patch Dependabot security issues in pnpm lock. (#20832) Thanks @vincentkoc. -- Security: migrate request dependencies to `@cypress/request`. (#20836) Thanks @vincentkoc. - -## 2026.2.17 - -### Changes - -- Agents/Anthropic: add opt-in 1M context beta header support for Opus/Sonnet via model `params.context1m: true` (maps to `anthropic-beta: context-1m-2025-08-07`). -- Agents/Models: support Anthropic Sonnet 4.6 (`anthropic/claude-sonnet-4-6`) across aliases/defaults with forward-compat fallback when upstream catalogs still only expose Sonnet 4.5. -- Commands/Subagents: add `/subagents spawn` for deterministic subagent activation from chat commands. (#18218) Thanks @JoshuaLelon. -- Agents/Subagents: add an accepted response note for `sessions_spawn` explaining polling subagents are disabled for one-off calls. Thanks @tyler6204. -- Agents/Subagents: prefix spawned subagent task messages with context to preserve source information in downstream handling. Thanks @tyler6204. -- iOS/Share: add an iOS share extension that forwards shared URL/text/image content directly to gateway `agent.request`, with delivery-route fallback and optional receipt acknowledgements. (#19424) Thanks @mbelinky. -- iOS/Talk: add a `Background Listening` toggle that keeps Talk Mode active while the app is backgrounded (off by default for battery safety). Thanks @zeulewan. -- iOS/Talk: add a `Voice Directive Hint` toggle for Talk Mode prompts so users can disable ElevenLabs voice-switching instructions to save tokens when not needed. (#18250) Thanks @zeulewan. -- iOS/Talk: harden barge-in behavior by disabling interrupt-on-speech when output route is built-in speaker/receiver, reducing false interruptions from local TTS bleed-through. Thanks @zeulewan. -- Slack: add native single-message text streaming with Slack `chat.startStream`/`appendStream`/`stopStream`; keep reply threading aligned with `replyToMode`, default streaming to enabled, and fall back to normal delivery when streaming fails. (#9972) Thanks @natedenh. -- Slack: add configurable streaming modes for draft previews. (#18555) Thanks @Solvely-Colin. -- Telegram/Agents: add inline button `style` support (`primary|success|danger`) across message tool schema, Telegram action parsing, send pipeline, and runtime prompt guidance. (#18241) Thanks @obviyus. -- Telegram: surface user message reactions as system events, with configurable `channels.telegram.reactionNotifications` scope. (#10075) Thanks @Glucksberg. -- iMessage: support `replyToId` on outbound text/media sends and normalize leading `[[reply_to:]]` tags so replies target the intended iMessage. Thanks @tyler6204. -- Tool Display/Web UI: add intent-first tool detail views and exec summaries. (#18592) Thanks @xdLawless2. -- Discord: expose native `/exec` command options (host/security/ask/node) so Discord slash commands get autocomplete and structured inputs. Thanks @thewilloftheshadow. -- Discord: allow reusable interactive components with `components.reusable=true` so buttons, selects, and forms can be used multiple times before expiring. Thanks @thewilloftheshadow. -- Discord: add per-button `allowedUsers` allowlist for interactive components to restrict who can click buttons. Thanks @thewilloftheshadow. -- Cron/Gateway: separate per-job webhook delivery (`delivery.mode = "webhook"`) from announce delivery, enforce valid HTTP(S) webhook URLs, and keep a temporary legacy `notify + cron.webhook` fallback for stored jobs. (#17901) Thanks @advaitpaliwal. -- Cron/CLI: add deterministic default stagger for recurring top-of-hour cron schedules (including 6-field seconds cron), auto-migrate existing jobs to persisted `schedule.staggerMs`, and add `openclaw cron add/edit --stagger ` plus `--exact` overrides for per-job timing control. -- Cron: log per-run model/provider usage telemetry in cron run logs/webhooks and add a local usage report script for aggregating token usage by job. (#18172) Thanks @HankAndTheCrew. -- Tools/Web: add URL allowlists for `web_search` and `web_fetch`. (#18584) Thanks @smartprogrammer93. -- Browser: add `extraArgs` config for custom Chrome launch arguments. (#18443) Thanks @JayMishra-source. -- Voice Call: pre-cache inbound greeting TTS for faster first playback. (#18447) Thanks @JayMishra-source. -- Skills: compact skill file `` paths in the system prompt by replacing home-directory prefixes with `~`, and add targeted compaction tests for prompt serialization behavior. (#14776) Thanks @bitfish3. -- Skills: refine skill-description routing boundaries with explicit "Use when"/"NOT for" guidance for coding-agent/github/weather, and clarify PTY/browser fallback wording. (#14577) Thanks @DylanWoodAkers. -- Auto-reply/Prompts: include trusted inbound `message_id` in conversation metadata payloads for downstream targeting workflows. Thanks @tyler6204. -- Auto-reply: include `sender_id` in trusted inbound metadata so moderation workflows can target the sender without relying on untrusted text. (#18303) Thanks @crimeacs. -- UI/Sessions: avoid duplicating typed session prefixes in display names (for example `Subagent Subagent ...`). Thanks @tyler6204. -- Agents/Z.AI: enable `tool_stream` by default for real-time tool call streaming, with opt-out via `params.tool_stream: false`. (#18173) Thanks @tianxiao1430-jpg. -- Plugins: add `before_agent_start` model/provider overrides before resolution. (#18568) Thanks @natefikru. -- Mattermost: add emoji reaction actions plus reaction event notifications, including an explicit boolean `remove` flag to avoid accidental removals. (#18608) Thanks @echo931. -- Memory/Search: add FTS fallback plus query expansion for memory search. (#18304) Thanks @irchelper. -- Agents/Models: support per-model `thinkingDefault` overrides in model config. (#18152) Thanks @wu-tian807. -- Agents: enable `llms.txt` discovery in default behavior. (#18158) Thanks @yolo-maxi. -- Extensions/Auth: add OpenAI Codex CLI auth provider integration. (#18009) Thanks @jiteshdhamaniya. -- Feishu: add Bitable create-app/create-field tools for automation workflows. (#17963) Thanks @gaowanqi08141999. -- Docker: add optional `OPENCLAW_INSTALL_BROWSER` build arg to preinstall Chromium + Xvfb in the Docker image, avoiding runtime Playwright installs. (#18449) - -### Fixes - -- Agents/Antigravity: preserve unsigned Claude thinking blocks as plain text instead of dropping them during transcript sanitization, preventing reasoning context loss while avoiding `thinking.signature` request rejections. -- Agents/Google: clean tool JSON Schemas for `google-antigravity` the same as `google-gemini-cli` before Cloud Code Assist requests, preventing Claude tool calls from failing with `patternProperties` 400 errors. (#19860) -- Tests/Telegram: add regression coverage for command-menu sync that asserts all `setMyCommands` entries are Telegram-safe and hyphen-normalized across native/custom/plugin command sources. (#19703) Thanks @obviyus. -- Agents/Image: collapse resize diagnostics to one line per image and include visible pixel/byte size details in the log message for faster triage. -- Auth/Cooldowns: clear all usage stats fields (`disabledUntil`, `disabledReason`, `failureCounts`) in `clearAuthProfileCooldown` so manual cooldown resets fully recover billing-disabled profiles without requiring direct file edits. (#19211) Thanks @nabbilkhan. -- Agents/Subagents: preemptively guard accumulated tool-result context before model calls by truncating oversized outputs and compacting oldest tool-result messages to avoid context-window overflow crashes. Thanks @tyler6204. -- Agents/Subagents/CLI: fail `sessions_spawn` when subagent model patching is rejected, allow subagent model patch defaults from `subagents.model`, and keep `sessions list`/`status` model reporting aligned to runtime model resolution. (#18660) Thanks @robbyczgw-cla. -- Agents/Subagents: add explicit subagent guidance to recover from `[compacted: tool output removed to free context]` / `[truncated: output exceeded context limit]` markers by re-reading with smaller chunks instead of full-file `cat`. Thanks @tyler6204. -- Agents/Tools: make `read` auto-page across chunks (when no explicit `limit` is provided) and scale its per-call output budget from model `contextWindow`, so larger contexts can read more before context guards kick in. Thanks @tyler6204. -- Agents/Tools: strip duplicated `read` truncation payloads from tool-result `details` and make pre-call context guarding account for heavy tool-result metadata, so repeated `read` calls no longer bypass compaction and overflow model context windows. Thanks @tyler6204. -- Reply threading: keep reply context sticky across streamed/split chunks and preserve `replyToId` on all chunk sends across shared and channel-specific delivery paths (including iMessage, BlueBubbles, Telegram, Discord, and Matrix), so follow-up bubbles stay attached to the same referenced message. Thanks @tyler6204. -- Gateway/Agent: defer transient lifecycle `error` snapshots with a short grace window so `agent.wait` does not resolve early during retry/failover. Thanks @tyler6204. -- Gateway/Presence: centralize presence snapshot broadcasts and unify runtime version precedence (`OPENCLAW_VERSION` > `OPENCLAW_SERVICE_VERSION` > `npm_package_version`) so self-presence and websocket `hello-ok` report consistent versions. -- Hooks/Automation: bridge outbound/inbound message lifecycle into internal hook events (`message:received`, `message:sent`) with session-key correlation guards, while keeping per-payload success/error reporting accurate for chunked and best-effort deliveries. (PR #9387) -- Media understanding: honor `agents.defaults.imageModel` during auto-discovery so implicit image analysis uses configured primary/fallback image models. (PR #7607) -- iOS/Onboarding: stop auth Step 3 retry-loop churn by pausing reconnect attempts on unauthorized/missing-token gateway errors and keeping auth/pairing issue state sticky during manual retry. (#19153) Thanks @mbelinky. -- Voice-call: auto-end calls when media streams disconnect to prevent stuck active calls. (#18435) Thanks @JayMishra-source. -- Voice call/Gateway: prevent overlapping closed-loop turn races with per-call turn locking, route transcript dedupe via source-aware fingerprints with strict cache eviction bounds, and harden `voicecall latency` stats for large logs without spread-operator stack overflow. (#19140) Thanks @mbelinky. -- iOS/Chat: route ChatSheet RPCs through the operator session instead of the node session to avoid node-role authorization failures for `chat.history`, `chat.send`, and `sessions.list`. (#19320) Thanks @mbelinky. -- macOS/Update: correct the Sparkle appcast version for 2026.2.15 so updates are offered again. (#18201) -- Gateway/Auth: clear stale device-auth tokens after device token mismatch errors so re-paired clients can re-auth. (#18201) -- Telegram: enable DM voice-note transcription with CLI fallback handling. (#18564) Thanks @thhuang. -- Telegram/Polls: restore Telegram poll action wiring in channel handlers. (#18122) Thanks @akyourowngames. -- WebChat: strip reply/audio directive tags from rendered chat output. (#18093) Thanks @aldoeliacim. -- Discord: honor configured HTTP proxy for app-id and allowlist REST resolution. (#17958) Thanks @k2009. -- BlueBubbles: add fallback path to recover outbound `message_id` from `fromMe` webhooks when platform message IDs are missing. Thanks @tyler6204. -- BlueBubbles: match outbound message-id fallback recovery by chat identifier as well as account context. Thanks @tyler6204. -- BlueBubbles: include sender identifier in untrusted conversation metadata for conversation info payloads. Thanks @tyler6204. -- Security/Exec: fix the OC-09 credential-theft path via environment-variable injection. (#18048) Thanks @aether-ai-agent. -- Security/Config: confine `$include` resolution to the top-level config directory, harden traversal/symlink checks with cross-platform-safe path containment, and add doctor hints for invalid escaped include paths. (#18652) Thanks @aether-ai-agent. -- Security/Net: block SSRF bypass via ISATAP embedded IPv4 transition addresses and centralize hostname/IP blocking checks across URL safety validators. Thanks @zpbrent for reporting. -- Providers: improve error messaging for unconfigured local `ollama`/`vllm` providers. (#18183) Thanks @arosstale. -- TTS: surface all provider errors instead of only the last error in aggregated failures. (#17964) Thanks @ikari-pl. -- CLI/Doctor/Configure: skip gateway auth checks for loopback-only setups. (#18407) Thanks @sggolakiya. -- CLI/Doctor: reconcile gateway service-token drift after re-pair flows. (#18525) Thanks @norunners. -- Process/Windows: disable detached spawn in exec runs to prevent empty command output. (#18067) Thanks @arosstale. -- Process: gracefully terminate process trees with SIGTERM before SIGKILL. (#18626) Thanks @sauerdaniel. -- Sessions/Windows: use atomic session-store writes to prevent context loss on Windows. (#18347) Thanks @twcwinston. -- Agents/Image: validate base64 image payloads before provider submission. (#18263) Thanks @sriram369. -- Models CLI: validate catalog entries in `openclaw models set`. (#18129) Thanks @carrotRakko. -- Usage: isolate last-turn totals in token usage reporting to avoid mixed-turn totals. (#18052) Thanks @arosstale. -- Cron: resolve `accountId` from agent bindings in isolated sessions. (#17996) Thanks @simonemacario. -- Gateway/HTTP: preserve unbracketed IPv6 `Host` headers when normalizing requests. (#18061) Thanks @Clawborn. -- Sandbox: fix workspace-directory orphaning during SHA-1 -> SHA-256 slug migration. (#18523) Thanks @yinghaosang. -- Ollama/Qwen: handle Qwen 3 reasoning field format in Ollama responses. (#18631) Thanks @mr-sk. -- OpenAI/Transcripts: always drop orphaned reasoning blocks from transcript repair. (#18632) Thanks @TySabs. -- Fix types in all tests. Typecheck the whole repository. -- Gateway/Channels: wire `gateway.channelHealthCheckMinutes` into strict config validation, treat implicit account status as managed for health checks, and harden channel auto-restart flow (preserve restart-attempt caps across crash loops, propagate enabled/configured runtime flags, and stop pending restart backoff after manual stop). Thanks @steipete. -- Gateway/WebChat: hard-cap `chat.history` oversized payloads by truncating high-cost fields and replacing over-budget entries with placeholders, so history fetches stay within configured byte limits and avoid chat UI freezes. (#18505) -- UI/Usage: replace lingering undefined `var(--text-muted)` usage with `var(--muted)` in usage date-range and chart styles to keep muted text visible across themes. (#17975) Thanks @jogelin. -- UI/Usage: preserve selected-range totals when timeline data is downsampled by bucket-aggregating timeseries points (instead of dropping intermediate points), so filtered tokens/cost stay accurate. (#17959) Thanks @jogelin. -- UI/Sessions: refresh the sessions table only after successful deletes and preserve delete errors on cancel/failure paths, so deleted sessions disappear automatically without masking delete failures. (#18507) -- Scripts/UI/Windows: fix `pnpm ui:*` spawn `EINVAL` failures by restoring shell-backed launch for `.cmd`/`.bat` runners, narrowing shell usage to launcher types that require it, and rejecting unsafe forwarded shell metacharacters in UI script args. (#18594) -- Hooks/Session-memory: recover `/new` conversation summaries when session pointers are reset-path or missing `sessionFile`, and consistently prefer the newest `.jsonl.reset.*` transcript candidate for fallback extraction. (#18088) -- Auto-reply/Sessions: prevent stale thread ID leakage into non-thread sessions so replies stay in the main DM after topic interactions. (#18528) Thanks @j2h4u. -- Slack: restrict forwarded-attachment ingestion to explicit shared-message attachments and skip non-Slack forwarded `image_url` fetches, preventing non-forward attachment unfurls from polluting inbound agent context while preserving forwarded message handling. -- Feishu: detect bot mentions in post messages with embedded docs when `message.mentions` is empty. (#18074) Thanks @popomore. -- Agents/Sessions: align session lock watchdog hold windows with run and compaction timeout budgets (plus grace), preventing valid long-running turns from being force-unlocked mid-run while still recovering hung lock owners. (#18060) -- Cron: preserve default model fallbacks for cron agent runs when only `model.primary` is overridden, so failover still follows configured fallbacks unless explicitly cleared with `fallbacks: []`. (#18210) Thanks @mahsumaktas. -- Cron: route text-only announce output through the main session announce flow via runSubagentAnnounceFlow so cron text-only output remains visible to the initiating session. Thanks @tyler6204. -- Cron: treat `timeoutSeconds: 0` as no-timeout (not clamped to 1), ensuring long-running cron runs are not prematurely terminated. Thanks @tyler6204. -- Cron announce injection now targets the session determined by delivery config (`to` + channel) instead of defaulting to the current session. Thanks @tyler6204. -- Cron/Heartbeat: canonicalize session-scoped reminder `sessionKey` routing and preserve explicit flat `sessionKey` cron tool inputs, preventing enqueue/wake namespace drift for session-targeted reminders. (#18637) Thanks @vignesh07. -- Cron/Webhooks: reuse existing session IDs for webhook/cron runs when the session key is stable and still fresh, preserving conversation history. (#18031) Thanks @Operative-001. -- Cron: prevent spin loops when cron jobs complete within the scheduled second by advancing the next run and enforcing a minimum refire gap. (#18073) Thanks @widingmarcus-cyber. -- OpenClawKit/iOS ChatUI: accept canonical session-key completion events for local pending runs and preserve message IDs across history refreshes, preventing stuck "thinking" state and message flicker after gateway replies. (#18165) Thanks @mbelinky. -- iOS/Onboarding: add QR-first onboarding wizard with setup-code deep link support, pairing/auth issue guidance, and device-pair QR generation improvements for Telegram/Web/TUI fallback flows. (#18162) Thanks @mbelinky and @Marvae. -- iOS/Gateway: stabilize connect/discovery state handling, add onboarding reset recovery in Settings, and fix iOS gateway-controller coverage for command-surface and last-connection persistence behavior. (#18164) Thanks @mbelinky. -- iOS/Talk: harden mobile talk config handling by ignoring redacted/env-placeholder API keys, support secure local keychain override, improve accessibility motion/contrast behavior in status UI, and tighten ATS to local-network allowance. (#18163) Thanks @mbelinky. -- iOS/Location: restore the significant location monitor implementation (service hooks + protocol surface + ATS key alignment) after merge drift so iOS builds compile again. (#18260) Thanks @ngutman. -- iOS/Signing: auto-select local Apple Development team during iOS project generation/build, prefer the canonical OpenClaw team when available, and support local per-machine signing overrides without committing team IDs. (#18421) Thanks @ngutman. -- Discord/Telegram: make per-account message action gates effective for both action listing and execution, and preserve top-level gate restrictions when account overrides only specify a subset of `actions` keys (account key -> base key -> default fallback). (#18494) -- Telegram: keep DM-topic replies and draft previews in the originating private-chat topic by preserving positive `message_thread_id` values for DM threads. (#18586) Thanks @sebslight. -- Telegram: preserve private-chat topic `message_thread_id` on outbound sends (message/sticker/poll), keep thread-not-found retry fallback, and avoid masking `chat not found` routing errors. (#18993) Thanks @obviyus. -- Discord: prevent duplicate media delivery when the model uses the `message send` tool with media, by skipping media extraction from messaging tool results since the tool already sent the message directly. (#18270) -- Discord: route `audioAsVoice` auto-replies through the voice message API so opt-in audio renders as voice messages. (#18041) Thanks @zerone0x. -- Discord: skip auto-thread creation in forum/media/voice/stage channels and keep group session last-route metadata fresh to avoid invalid thread API errors and lost follow-up sends. (#18098) Thanks @Clawborn. -- Discord/Commands: normalize `commands.allowFrom` entries with `user:`/`discord:`/`pk:` prefixes and `<@id>` mentions so command authorization matches Discord allowlist behavior. (#18042) -- Telegram: keep draft-stream preview replies attached to the user message for `replyToMode: "all"` in groups and DMs, preserving threaded reply context from preview through finalization. (#17880) Thanks @yinghaosang. -- Telegram: prevent streaming final replies from being overwritten by later final/error payloads, and suppress fallback tool-error warnings when a recovered assistant answer already exists after tool calls. (#17883) Thanks @Marvae and @obviyus. -- Telegram: debounce the first draft-stream preview update (30-char threshold) and finalize short responses by editing the stop-time preview message, improving first push notifications and avoiding duplicate final sends. (#18148) Thanks @Marvae. -- Telegram: disable block streaming when `channels.telegram.streamMode` is `off`, preventing newline/content-block replies from splitting into multiple messages. (#17679) Thanks @saivarunk. -- Telegram: keep `streamMode: "partial"` draft previews in a single message across assistant-message/reasoning boundaries, preventing duplicate preview bubbles during partial-mode tool-call turns. (#18956) Thanks @obviyus. -- Telegram: normalize native command names for Telegram menu registration (`-` -> `_`) to avoid `BOT_COMMAND_INVALID` command-menu wipeouts, and log failed command syncs instead of silently swallowing them. (#19257) Thanks @akramcodez. -- Telegram: route non-abort slash commands on the normal chat/topic sequential lane while keeping true abort requests (`/stop`, `stop`) on the control lane, preventing command/reply race conditions from control-lane bypass. (#17899) Thanks @obviyus. -- Telegram: ignore `` placeholder lines when extracting `MEDIA:` tool-result paths, preventing false local-file reads and dropped replies. (#18510) Thanks @yinghaosang. -- Telegram: skip retries when inbound media `getFile` fails with Telegram's 20MB limit and continue processing message text, avoiding dropped messages for oversized attachments. (#18531) Thanks @brandonwise. -- Telegram: clear stored polling offsets when bot tokens change or accounts are deleted, preventing stale offsets after token rotations. (#18233) -- Telegram: enable `autoSelectFamily` by default on Node.js 22+ so IPv4 fallback works on broken IPv6 networks. (#18272) Thanks @nacho9900. -- Auto-reply/TTS: keep tool-result media delivery enabled in group chats and native command sessions (while still suppressing tool summary text) so `NO_REPLY` follow-ups do not drop successful TTS audio. (#17991) Thanks @zerone0x. -- Agents/Tools: deliver tool-result media even when verbose tool output is off so media attachments are not dropped. (#16679) -- Discord: optimize reaction notification handling to skip unnecessary message fetches in `off`/`all`/`allowlist` modes, streamline reaction routing, and improve reaction emoji formatting. (#18248) Thanks @thewilloftheshadow and @victorGPT. -- CLI/Pairing: make `openclaw qr --remote` prefer `gateway.remote.url` over tailscale/public URL resolution and register the `openclaw clawbot qr` legacy alias path. (#18091) -- CLI/QR: restore fail-fast validation for `openclaw qr --remote` when neither `gateway.remote.url` nor tailscale `serve`/`funnel` is configured, preventing unusable remote pairing QR flows. (#18166) Thanks @mbelinky. -- CLI: fix parent/subcommand option collisions across gateway, daemon, update, ACP, and browser command flows, while preserving legacy `browser set headers --json ` compatibility. -- CLI/Doctor: ensure `openclaw doctor --fix --non-interactive --yes` exits promptly after completion so one-shot automation no longer hangs. (#18502) -- CLI/Doctor: auto-repair `dmPolicy="open"` configs missing wildcard allowlists and write channel-correct repair paths (including `channels.googlechat.dm.allowFrom`) so `openclaw doctor --fix` no longer leaves Google Chat configs invalid after attempted repair. (#18544) -- CLI/Doctor: detect gateway service token drift when the gateway token is only provided via environment variables, keeping service repairs aligned after token rotation. -- Gateway/Update: prevent restart crash loops after failed self-updates by restarting only on successful updates, stopping early on failed install/build steps, and running `openclaw doctor --fix` during updates to sanitize config. (#18131) Thanks @RamiNoodle733. -- Gateway/Update: preserve update.run restart delivery context so post-update status replies route back to the initiating channel/thread. (#18267) Thanks @yinghaosang. -- CLI/Update: run a standalone restart helper after updates, honoring service-name overrides and reporting restart initiation separately from confirmed restarts. (#18050) -- CLI/Daemon: warn when a gateway restart sees a stale service token so users can reinstall with `openclaw gateway install --force`, and skip drift warnings for non-gateway service restarts. (#18018) -- CLI/Daemon: prefer the active version-manager Node when installing daemons and include macOS version-manager bin directories in the service PATH so launchd services resolve user-managed runtimes. -- CLI/Status: fix `openclaw status --all` token summaries for bot-token-only channels so Mattermost/Zalo no longer show a bot+app warning. (#18527) Thanks @echo931. -- CLI/Configure: make the `/model picker` allowlist prompt searchable with tokenized matching in `openclaw configure` so users can filter huge model lists by typing terms like `gpt-5.2 openai/`. (#19010) Thanks @bjesuiter. -- CLI/Message: preserve `--components` JSON payloads in `openclaw message send` so Discord component payloads are no longer dropped. (#18222) Thanks @saurabhchopade. -- Voice Call: add an optional stale call reaper (`staleCallReaperSeconds`) to end stuck calls when enabled. (#18437) -- Auto-reply/Subagents: propagate group context (`groupId`, `groupChannel`, `space`) when spawning via `/subagents spawn`, matching tool-triggered subagent spawn behavior. -- Subagents: route nested announce results back to the parent session after the parent run ends, falling back only when the parent session is deleted. (#18043) Thanks @tyler6204. -- Subagents: cap announce retry loops with max attempts and expiry to prevent infinite retry spam after deferred announces. (#18444) -- Agents/Tools/exec: add a preflight guard that detects likely shell env var injection (e.g. `$DM_JSON`, `$TMPDIR`) in Python/Node scripts before execution, preventing recurring cron failures and wasted tokens when models emit mixed shell+language source. (#12836) -- Agents/Tools/exec: treat normal non-zero exit codes as completed and append the exit code to tool output to avoid false tool-failure warnings. (#18425) -- Agents/Tools: make loop detection progress-aware and phased by hard-blocking known `process(action=poll|log)` no-progress loops, warning on generic identical-call repeats, warning + no-progress-blocking ping-pong alternation loops (10/20), coalescing repeated warning spam into threshold buckets (including canonical ping-pong pairs), adding a global circuit breaker at 30 no-progress repeats, and emitting structured diagnostic `tool.loop` warning/error events for loop actions. (#16808) Thanks @akramcodez and @beca-oc. -- Agents/Hooks: preserve the `before_tool_call` wrapped-marker across abort-signal tool wrapping so the hook runs once per tool call in normal agent sessions. (#16852) Thanks @sreuter. -- Agents/Tests: add `before_message_write` persistence regression coverage for block/mutate behavior (including synthetic tool-result flushes) and thrown-hook fallback persistence. (#18197) Thanks @shakkernerd -- Agents/Tools: scope the `message` tool schema to the active channel so Telegram uses `buttons` and Discord uses `components`. (#18215) Thanks @obviyus. -- Agents/Image tool: replace Anthropic-incompatible union schema with explicit `image` (single) and `images` (multi) parameters, keeping tool schemas `anyOf`/`oneOf`/`allOf`-free while preserving multi-image analysis support. (#18551, #18566) Thanks @aldoeliacim. -- Agents/Models: probe the primary model when its auth-profile cooldown is near expiry (with per-provider throttling), so runs recover from temporary rate limits without staying on fallback models until restart. (#17478) Thanks @PlayerGhost. -- Agents/Failover: classify provider abort stop-reason errors (`Unhandled stop reason: abort`, `stop reason: abort`, `reason: abort`) as timeout-class failures so configured model fallback chains trigger instead of surfacing raw abort failures. (#18618) Thanks @sauerdaniel. -- Models/CLI: sync auth-profiles credentials into agent `auth.json` before registry availability checks so `openclaw models list --all` reports auth correctly for API-key/token providers, normalize provider-id aliases when bridging credentials, and skip expired token mirrors. (#18610, #18615) -- Agents/Context: raise default total bootstrap prompt cap from `24000` to `150000` chars (keeping `bootstrapMaxChars` at `20000`), include total-cap visibility in `/context`, and mark truncation from injected-vs-raw sizes so total-cap clipping is reflected accurately. -- Memory/QMD: scope managed collection names per agent and precreate glob-backed collection directories before registration, preventing cross-agent collection clobbering and startup ENOENT failures in fresh workspaces. (#17194) Thanks @jonathanadams96. -- Cron: preserve per-job schedule-error isolation in post-run maintenance recompute so malformed sibling jobs no longer abort persistence of successful runs. (#17852) Thanks @pierreeurope. -- Gateway/Config: prevent `config.patch` object-array merges from falling back to full-array replacement when some patch entries lack `id`, so partial `agents.list` updates no longer drop unrelated agents. (#17989) Thanks @stakeswky. -- Gateway/Auth: trim whitespace around trusted proxy entries before matching so configured proxies with stray spaces still authorize. (#18084) Thanks @Clawborn. -- Config/Discord: require string IDs in Discord allowlists, keep onboarding inputs string-only, and add doctor repair for numeric entries. (#18220) Thanks @thewilloftheshadow. -- Security/Sessions: create new session transcript JSONL files with user-only (`0o600`) permissions and extend `openclaw security audit --fix` to remediate existing transcript file permissions. -- Sessions/Maintenance: archive transcripts when pruning stale sessions, clean expired media in subdirectories, and purge `.deleted` transcript archives after the prune window to prevent disk leaks. (#18538) -- Infra/Fetch: ensure foreign abort-signal listener cleanup never masks original fetch successes/failures, while still preventing detached-finally unhandled rejection noise in `wrapFetchWithAbortSignal`. Thanks @Jackten. -- Heartbeat: allow suppressing tool error warning payloads during heartbeat runs via a new heartbeat config flag. (#18497) Thanks @thewilloftheshadow. -- Heartbeat: include sender metadata (From/To/Provider) in heartbeat prompts so model context matches the delivery target. (#18532) Thanks @dinakars777. -- Heartbeat/Telegram: strip configured `responsePrefix` before heartbeat ack detection (with boundary-safe matching) so prefixed `HEARTBEAT_OK` replies are correctly suppressed instead of leaking into DMs. (#18602) - -## 2026.2.15 - -### Changes - -- Discord: unlock rich interactive agent prompts with Components v2 (buttons, selects, modals, and attachment-backed file blocks) so for native interaction through Discord. Thanks @thewilloftheshadow. -- Discord: components v2 UI + embeds passthrough + exec approval UX refinements (CV2 containers, button layout, Discord-forwarding skip). Thanks @thewilloftheshadow. -- Plugins: expose `llm_input` and `llm_output` hook payloads so extensions can observe prompt/input context and model output usage details. (#16724) Thanks @SecondThread. -- Subagents: nested sub-agents (sub-sub-agents) with configurable depth. Set `agents.defaults.subagents.maxSpawnDepth: 2` to allow sub-agents to spawn their own children. Includes `maxChildrenPerAgent` limit (default 5), depth-aware tool policy, and proper announce chain routing. (#14447) Thanks @tyler6204. -- Slack/Discord/Telegram: add per-channel ack reaction overrides (account/channel-level) to support platform-specific emoji formats. (#17092) Thanks @zerone0x. -- Telegram: add `channel_post` inbound support for channel-based bot-to-bot wake/trigger flows, with channel allowlist gating and message/media batching parity. -- Cron/Gateway: add finished-run webhook delivery toggle (`notify`) and dedicated webhook auth token support (`cron.webhookToken`) for outbound cron webhook posts. (#14535) Thanks @advaitpaliwal. -- Channels: deduplicate probe/token resolution base types across core + extensions while preserving per-channel error typing. (#16986) Thanks @iyoda and @thewilloftheshadow. -- Memory: add MMR (Maximal Marginal Relevance) re-ranking for hybrid search diversity. Configurable via `memorySearch.query.hybrid.mmr`. Thanks @rodrigouroz. -- Memory: add opt-in temporal decay for hybrid search scoring, with configurable half-life via `memorySearch.query.hybrid.temporalDecay`. Thanks @rodrigouroz. - -### Fixes - -- Discord: send initial content when creating non-forum threads so `thread-create` content is delivered. (#18117) Thanks @zerone0x. -- Security: replace deprecated SHA-1 sandbox configuration hashing with SHA-256 for deterministic sandbox cache identity and recreation checks. Thanks @kexinoh. -- Security/Logging: redact Telegram bot tokens from error messages and uncaught stack traces to prevent accidental secret leakage into logs. Thanks @aether-ai-agent. -- Sandbox/Security: block dangerous sandbox Docker config (bind mounts, host networking, unconfined seccomp/apparmor) to prevent container escape via config injection. Thanks @aether-ai-agent. -- Sandbox: preserve array order in config hashing so order-sensitive Docker/browser settings trigger container recreation correctly. Thanks @kexinoh. -- Gateway/Security: redact sensitive session/path details from `status` responses for non-admin clients; full details remain available to `operator.admin`. (#8590) Thanks @fr33d3m0n. -- Gateway/Control UI: preserve requested operator scopes for Control UI bypass modes (`allowInsecureAuth` / `dangerouslyDisableDeviceAuth`) when device identity is unavailable, preventing false `missing scope` failures on authenticated LAN/HTTP operator sessions. (#17682) Thanks @leafbird. -- LINE/Security: fail closed on webhook startup when channel token or channel secret is missing, and treat LINE accounts as configured only when both are present. (#17587) Thanks @davidahmann. -- Skills/Security: restrict `download` installer `targetDir` to the per-skill tools directory to prevent arbitrary file writes. Thanks @Adam55A-code. -- Skills/Linux: harden go installer fallback on apt-based systems by handling root/no-sudo environments safely, doing best-effort apt index refresh, and returning actionable errors instead of failing with spawn errors. (#17687) Thanks @mcrolly. -- Web Fetch/Security: cap downloaded response body size before HTML parsing to prevent memory exhaustion from oversized or deeply nested pages. Thanks @xuemian168. -- Config/Gateway: make sensitive-key whitelist suffix matching case-insensitive while preserving `passwordFile` path exemptions, preventing accidental redaction of non-secret config values like `maxTokens` and IRC password-file paths. (#16042) Thanks @akramcodez. -- Dev tooling: harden git `pre-commit` hook against option injection from malicious filenames (for example `--force`), preventing accidental staging of ignored files. Thanks @mrthankyou. -- Gateway/Agent: reject malformed `agent:`-prefixed session keys (for example, `agent:main`) in `agent` and `agent.identity.get` instead of silently resolving them to the default agent, preventing accidental cross-session routing. (#15707) Thanks @rodrigouroz. -- Gateway/Chat: harden `chat.send` inbound message handling by rejecting null bytes, stripping unsafe control characters, and normalizing Unicode to NFC before dispatch. (#8593) Thanks @fr33d3m0n. -- Gateway/Send: return an actionable error when `send` targets internal-only `webchat`, guiding callers to use `chat.send` or a deliverable channel. (#15703) Thanks @rodrigouroz. -- Gateway/Commands: keep webchat command authorization on the internal `webchat` context instead of inferring another provider from channel allowlists, fixing dropped `/new`/`/status` commands in Control UI when channel allowlists are configured. (#7189) Thanks @karlisbergmanis-lv. -- Control UI: prevent stored XSS via assistant name/avatar by removing inline script injection, serving bootstrap config as JSON, and enforcing `script-src 'self'`. Thanks @Adam55A-code. -- Agents/Security: sanitize workspace paths before embedding into LLM prompts (strip Unicode control/format chars) to prevent instruction injection via malicious directory names. Thanks @aether-ai-agent. -- Agents/Sandbox: clarify system prompt path guidance so sandbox `bash/exec` uses container paths (for example `/workspace`) while file tools keep host-bridge mapping, avoiding first-attempt path misses from host-only absolute paths in sandbox command execution. (#17693) Thanks @app/juniordevbot. -- Agents/Context: apply configured model `contextWindow` overrides after provider discovery so `lookupContextTokens()` honors operator config values (including discovery-failure paths). (#17404) Thanks @michaelbship and @vignesh07. -- Agents/Context: derive `lookupContextTokens()` from auth-available model metadata and keep the smallest discovered context window for duplicate model ids, preventing cross-provider cache collisions from overestimating session context limits. (#17586) Thanks @githabideri and @vignesh07. -- Agents/OpenAI: force `store=true` for direct OpenAI Responses/Codex runs to preserve multi-turn server-side conversation state, while leaving proxy/non-OpenAI endpoints unchanged. (#16803) Thanks @mark9232 and @vignesh07. -- Memory/FTS: make `buildFtsQuery` Unicode-aware so non-ASCII queries (including CJK) produce keyword tokens instead of falling back to vector-only search. (#17672) Thanks @KinGP5471. -- Auto-reply/Compaction: resolve `memory/YYYY-MM-DD.md` placeholders with timezone-aware runtime dates and append a `Current time:` line to memory-flush turns, preventing wrong-year memory filenames without making the system prompt time-variant. (#17603, #17633) Thanks @nicholaspapadam-wq and @vignesh07. -- Auth/Cooldowns: auto-expire stale auth profile cooldowns when `cooldownUntil` or `disabledUntil` timestamps have passed, and reset `errorCount` so the next transient failure does not immediately escalate to a disproportionately long cooldown. Handles `cooldownUntil` and `disabledUntil` independently. (#3604) Thanks @nabbilkhan. -- Agents: return an explicit timeout error reply when an embedded run times out before producing any payloads, preventing silent dropped turns during slow cache-refresh transitions. (#16659) Thanks @liaosvcaf and @vignesh07. -- Group chats: always inject group chat context (name, participants, reply guidance) into the system prompt on every turn, not just the first. Prevents the model from losing awareness of which group it's in and incorrectly using the message tool to send to the same group. (#14447) Thanks @tyler6204. -- Browser/Agents: when browser control service is unavailable, return explicit non-retry guidance (instead of "try again") so models do not loop on repeated browser tool calls until timeout. (#17673) Thanks @austenstone. -- Subagents: use child-run-based deterministic announce idempotency keys across direct and queued delivery paths (with legacy queued-item fallback) to prevent duplicate announce retries without collapsing distinct same-millisecond announces. (#17150) Thanks @widingmarcus-cyber. -- Subagents/Models: preserve `agents.defaults.model.fallbacks` when subagent sessions carry a model override, so subagent runs fail over to configured fallback models instead of retrying only the overridden primary model. -- Agents/Tools: scope the `message` tool schema to the active channel so Telegram uses `buttons` and Discord uses `components`. (#18215) Thanks @obviyus. -- Telegram: omit `message_thread_id` for DM sends/draft previews and keep forum-topic handling (`id=1` general omitted, non-general kept), preventing DM failures with `400 Bad Request: message thread not found`. (#10942) Thanks @garnetlyx. -- Telegram: replace inbound `` placeholder with successful preflight voice transcript in message body context, preventing placeholder-only prompt bodies for mention-gated voice messages. (#16789) Thanks @Limitless2023. -- Telegram: retry inbound media `getFile` calls (3 attempts with backoff) and gracefully fall back to placeholder-only processing when retries fail, preventing dropped voice/media messages on transient Telegram network errors. (#16154) Thanks @yinghaosang. -- Telegram: finalize streaming preview replies in place instead of sending a second final message, preventing duplicate Telegram assistant outputs at stream completion. (#17218) Thanks @obviyus. -- Discord: preserve channel session continuity when runtime payloads omit `message.channelId` by falling back to event/raw `channel_id` values for routing/session keys, so same-channel messages keep history across turns/restarts. Also align diagnostics so active Discord runs no longer appear as `sessionKey=unknown`. (#17622) Thanks @shakkernerd. -- Discord: dedupe native skill commands by skill name in multi-agent setups to prevent duplicated slash commands with `_2` suffixes. (#17365) Thanks @seewhyme. -- Discord: ensure role allowlist matching uses raw role IDs for message routing authorization. Thanks @xinhuagu. -- Discord: skip text-based exec approval forwarding in favor of Discord's component-based approval UI. Thanks @thewilloftheshadow. -- Web UI/Agents: hide `BOOTSTRAP.md` in the Agents Files list after onboarding is completed, avoiding confusing missing-file warnings for completed workspaces. (#17491) Thanks @gumadeiras. -- Memory/QMD: scope managed collection names per agent and precreate glob-backed collection directories before registration, preventing cross-agent collection clobbering and startup ENOENT failures in fresh workspaces. (#17194) Thanks @jonathanadams96. -- Gateway/Memory: initialize QMD startup sync for every configured agent (not just the default agent), so `memory.qmd.update.onBoot` is effective across multi-agent setups. (#17663) Thanks @HenryLoenwind. -- Auto-reply/WhatsApp/TUI/Web: when a final assistant message is `NO_REPLY` and a messaging tool send succeeded, mirror the delivered messaging-tool text into session-visible assistant output so TUI/Web no longer show `NO_REPLY` placeholders. (#7010) Thanks @Morrowind-Xie. -- Cron: infer `payload.kind="agentTurn"` for model-only `cron.update` payload patches, so partial agent-turn updates do not fail validation when `kind` is omitted. (#15664) Thanks @rodrigouroz. -- TUI: make searchable-select filtering and highlight rendering ANSI-aware so queries ignore hidden escape codes and no longer corrupt ANSI styling sequences during match highlighting. (#4519) Thanks @bee4come. -- TUI/Windows: coalesce rapid single-line submit bursts in Git Bash into one multiline message as a fallback when bracketed paste is unavailable, preventing pasted multiline text from being split into multiple sends. (#4986) Thanks @adamkane. -- TUI: suppress false `(no output)` placeholders for non-local empty final events during concurrent runs, preventing external-channel replies from showing empty assistant bubbles while a local run is still streaming. (#5782) Thanks @LagWizard and @vignesh07. -- TUI: preserve copy-sensitive long tokens (URLs/paths/file-like identifiers) during wrapping and overflow sanitization so wrapped output no longer inserts spaces that corrupt copy/paste values. (#17515, #17466, #17505) Thanks @abe238, @trevorpan, and @JasonCry. -- CLI/Build: make legacy daemon CLI compatibility shim generation tolerant of minimal tsdown daemon export sets, while preserving restart/register compatibility aliases and surfacing explicit errors for unavailable legacy daemon commands. Thanks @vignesh07. - -## 2026.2.14 - -### Changes - -- Telegram: add poll sending via `openclaw message poll` (duration seconds, silent delivery, anonymity controls). (#16209) Thanks @robbyczgw-cla. -- Slack/Discord: add `dmPolicy` + `allowFrom` config aliases for DM access control; legacy `dm.policy` + `dm.allowFrom` keys remain supported and `openclaw doctor --fix` can migrate them. -- Discord: allow exec approval prompts to target channels or both DM+channel via `channels.discord.execApprovals.target`. (#16051) Thanks @leonnardo. -- Sandbox: add `sandbox.browser.binds` to configure browser-container bind mounts separately from exec containers. (#16230) Thanks @seheepeak. -- Discord: add debug logging for message routing decisions to improve `--debug` tracing. (#16202) Thanks @jayleekr. -- Agents: add optional `messages.suppressToolErrors` config to hide non-mutating tool-failure warnings from user-facing chat while still surfacing mutating failures. (#16620) Thanks @vai-oro. - -### Fixes - -- CLI/Installation: fix Docker installation hangs on macOS. (#12972) Thanks @vincentkoc. -- Models: fix antigravity opus 4.6 availability follow-up. (#12845) Thanks @vincentkoc. -- Security/Sessions/Telegram: restrict session tool targeting by default to the current session tree (`tools.sessions.visibility`, default `tree`) with sandbox clamping, and pass configured per-account Telegram webhook secrets in webhook mode when no explicit override is provided. Thanks @aether-ai-agent. -- CLI/Plugins: ensure `openclaw message send` exits after successful delivery across plugin-backed channels so one-shot sends do not hang. (#16491) Thanks @yinghaosang. -- CLI/Plugins: run registered plugin `gateway_stop` hooks before `openclaw message` exits (success and failure paths), so plugin-backed channels can clean up one-shot CLI resources. (#16580) Thanks @gumadeiras. -- WhatsApp: honor per-account `dmPolicy` overrides (account-level settings now take precedence over channel defaults for inbound DMs). (#10082) Thanks @mcaxtr. -- Telegram: when `channels.telegram.commands.native` is `false`, exclude plugin commands from `setMyCommands` menu registration while keeping plugin slash handlers callable. (#15132) Thanks @Glucksberg. -- LINE: return 200 OK for Developers Console "Verify" requests (`{"events":[]}`) without `X-Line-Signature`, while still requiring signatures for real deliveries. (#16582) Thanks @arosstale. -- Cron: deliver text-only output directly when `delivery.to` is set so cron recipients get full output instead of summaries. (#16360) Thanks @thewilloftheshadow. -- Cron/Slack: preserve agent identity (name and icon) when cron jobs deliver outbound messages. (#16242) Thanks @robbyczgw-cla. -- Media: accept `MEDIA:`-prefixed paths (lenient whitespace) when loading outbound media to prevent `ENOENT` for tool-returned local media paths. (#13107) Thanks @mcaxtr. -- Media understanding: treat binary `application/vnd.*`/zip/octet-stream attachments as non-text (while keeping vendor `+json`/`+xml` text-eligible) so Office/ZIP files are not inlined into prompt body text. (#16513) Thanks @rmramsey32. -- Agents: deliver tool result media (screenshots, images, audio) to channels regardless of verbose level. (#11735) Thanks @strelov1. -- Auto-reply/Block streaming: strip leading whitespace from streamed block replies so messages starting with blank lines no longer deliver visible leading empty lines. (#16422) Thanks @mcinteerj. -- Auto-reply/Queue: keep queued followups and overflow summaries when drain attempts fail, then retry delivery instead of dropping messages on transient errors. (#16771) Thanks @mmhzlrj. -- Agents/Image tool: allow workspace-local image paths by including the active workspace directory in local media allowlists, and trust sandbox-validated paths in image loaders to prevent false "not under an allowed directory" rejections. (#15541) -- Agents/Image tool: propagate the effective workspace root into tool wiring so workspace-local image paths are accepted by default when running without an explicit `workspaceDir`. (#16722) -- BlueBubbles: include sender identity in group chat envelopes and pass clean message text to the agent prompt, aligning with iMessage/Signal formatting. (#16210) Thanks @zerone0x. -- CLI: fix lazy core command registration so top-level maintenance commands (`doctor`, `dashboard`, `reset`, `uninstall`) resolve correctly instead of exposing a non-functional `maintenance` placeholder command. -- CLI/Dashboard: when `gateway.bind=lan`, generate localhost dashboard URLs to satisfy browser secure-context requirements while preserving non-LAN bind behavior. (#16434) Thanks @BinHPdev. -- TUI/Gateway: resolve local gateway target URL from `gateway.bind` mode (tailnet/lan) instead of hardcoded localhost so `openclaw tui` connects when gateway is non-loopback. (#16299) Thanks @cortexuvula. -- TUI: honor explicit `--session ` in `openclaw tui` even when `session.scope` is `global`, so named sessions no longer collapse into shared global history. (#16575) Thanks @cinqu. -- TUI: use available terminal width for session name display in searchable select lists. (#16238) Thanks @robbyczgw-cla. -- TUI: preserve in-flight streaming replies when a different run finalizes concurrently (avoid clearing active run or reloading history mid-stream). (#10704) Thanks @axschr73. -- TUI: keep pre-tool streamed text visible when later tool-boundary deltas temporarily omit earlier text blocks. (#6958) Thanks @KrisKind75. -- TUI: sanitize ANSI/control-heavy history text, redact binary-like lines, and split pathological long unbroken tokens before rendering to prevent startup crashes on binary attachment history. (#13007) Thanks @wilkinspoe. -- TUI: harden render-time sanitizer for narrow terminals by chunking moderately long unbroken tokens and adding fast-path sanitization guards to reduce overhead on normal text. (#5355) Thanks @tingxueren. -- TUI: render assistant body text in terminal default foreground (instead of fixed light ANSI color) so contrast remains readable on light themes such as Solarized Light. (#16750) Thanks @paymog. -- TUI/Hooks: pass explicit reset reason (`new` vs `reset`) through `sessions.reset` and emit internal command hooks for gateway-triggered resets so `/new` hook workflows fire in TUI/webchat. -- Gateway/Agent: route bare `/new` and `/reset` through `sessions.reset` before running the fresh-session greeting prompt, so reset commands clear the current session in-place instead of falling through to normal agent runs. (#16732) Thanks @kdotndot and @vignesh07. -- Cron: prevent `cron list`/`cron status` from silently skipping past-due recurring jobs by using maintenance recompute semantics. (#16156) Thanks @zerone0x. -- Cron: repair missing/corrupt `nextRunAtMs` for the updated job without globally recomputing unrelated due jobs during `cron update`. (#15750) -- Cron: treat persisted jobs with missing `enabled` as enabled by default across update/list/timer due-path checks, and add regression coverage for missing-`enabled` store records. (#15433) Thanks @eternauta1337. -- Cron: skip missed-job replay on startup for jobs interrupted mid-run (stale `runningAtMs` markers), preventing restart loops for self-restarting jobs such as update tasks. (#16694) Thanks @sbmilburn. -- Heartbeat/Cron: treat cron-tagged queued system events as cron reminders even on interval wakes, so isolated cron announce summaries no longer run under the default heartbeat prompt. (#14947) Thanks @archedark-ada and @vignesh07. -- Discord: prefer gateway guild id when logging inbound messages so cached-miss guilds do not appear as `guild=dm`. Thanks @thewilloftheshadow. -- Discord: treat empty per-guild `channels: {}` config maps as no channel allowlist (not deny-all), so `groupPolicy: "open"` guilds without explicit channel entries continue to receive messages. (#16714) Thanks @xqliu. -- Models/CLI: guard `models status` string trimming paths to prevent crashes from malformed non-string config values. (#16395) Thanks @BinHPdev. -- Gateway/Subagents: preserve queued announce items and summary state on delivery errors, retry failed announce drains, and avoid dropping unsent announcements on timeout/failure. (#16729) Thanks @Clawdette-Workspace. -- Gateway/Config: make `config.patch` merge object arrays by `id` (for example `agents.list`) instead of replacing the whole array, so partial agent updates do not silently delete unrelated agents. (#6766) Thanks @lightclient. -- Webchat/Prompts: stop injecting direct-chat `conversation_label` into inbound untrusted metadata context blocks, preventing internal label noise from leaking into visible chat replies. (#16556) Thanks @nberardi. -- Auto-reply/Prompts: include trusted inbound `message_id`, `chat_id`, `reply_to_id`, and optional `message_id_full` metadata fields so action tools (for example reactions) can target the triggering message without relying on user text. (#17662) Thanks @MaikiMolto. -- Gateway/Sessions: abort active embedded runs and clear queued session work before `sessions.reset`, returning unavailable if the run does not stop in time. (#16576) Thanks @Grynn. -- Sessions/Agents: harden transcript path resolution for mismatched agent context by preserving explicit store roots and adding safe absolute-path fallback to the correct agent sessions directory. (#16288) Thanks @robbyczgw-cla. -- Agents: add a safety timeout around embedded `session.compact()` to ensure stalled compaction runs settle and release blocked session lanes. (#16331) Thanks @BinHPdev. -- Agents/Tools: make required-parameter validation errors list missing fields and instruct: "Supply correct parameters before retrying," reducing repeated invalid tool-call loops (for example `read({})`). (#14729) -- Agents: keep unresolved mutating tool failures visible until the same action retry succeeds, scope mutation-error surfacing to mutating calls (including `session_status` model changes), and dedupe duplicate failure warnings in outbound replies. (#16131) Thanks @Swader. -- Agents/Process/Bootstrap: preserve unbounded `process log` offset-only pagination (default tail applies only when both `offset` and `limit` are omitted) and enforce strict `bootstrapTotalMaxChars` budgeting across injected bootstrap content (including markers), skipping additional injection when remaining budget is too small. (#16539) Thanks @CharlieGreenman. -- Agents/Workspace: persist bootstrap onboarding state so partially initialized workspaces recover missing `BOOTSTRAP.md` once, while completed onboarding keeps BOOTSTRAP deleted even if runtime files are later recreated. Thanks @gumadeiras. -- Agents/Workspace: create `BOOTSTRAP.md` when core workspace files are seeded in partially initialized workspaces, while keeping BOOTSTRAP one-shot after onboarding deletion. (#16457) Thanks @robbyczgw-cla. -- Agents: classify external timeout aborts during compaction the same as internal timeouts, preventing unnecessary auth-profile rotation and preserving compaction-timeout snapshot fallback behavior. (#9855) Thanks @mverrilli. -- Agents: treat empty-stream provider failures (`request ended without sending any chunks`) as timeout-class failover signals, enabling auth-profile rotation/fallback and showing a friendly timeout message instead of raw provider errors. (#10210) Thanks @zenchantlive. -- Agents: treat `read` tool `file_path` arguments as valid in tool-start diagnostics to avoid false “read tool called without path” warnings when alias parameters are used. (#16717) Thanks @Stache73. -- Agents/Transcript: drop malformed tool-call blocks with blank required fields (`id`/`name` or missing `input`/`arguments`) during session transcript repair to prevent persistent tool-call corruption on future turns. (#15485) Thanks @mike-zachariades. -- Tools/Write/Edit: normalize structured text-block arguments for `content`/`oldText`/`newText` before filesystem edits, preventing JSON-like file corruption and false “exact text not found” misses from block-form params. (#16778) Thanks @danielpipernz. -- Ollama/Agents: avoid forcing `` tag enforcement for Ollama models, which could suppress all output as `(no output)`. (#16191) Thanks @Glucksberg. -- Plugins: suppress false duplicate plugin id warnings when the same extension is discovered via multiple paths (config/workspace/global vs bundled), while still warning on genuine duplicates. (#16222) Thanks @shadril238. -- Agents/Process: supervise PTY/child process lifecycles with explicit ownership, cancellation, timeouts, and deterministic cleanup, preventing Codex/Pi PTY sessions from dying or stalling on resume. (#14257) Thanks @onutc. -- Skills: watch `SKILL.md` only when refreshing skills snapshot to avoid file-descriptor exhaustion in large data trees. (#11325) Thanks @household-bard. -- Memory/QMD: make `memory status` read-only by skipping QMD boot update/embed side effects for status-only manager checks. -- Memory/QMD: keep original QMD failures when builtin fallback initialization fails (for example missing embedding API keys), instead of replacing them with fallback init errors. -- Memory/Builtin: keep `memory status` dirty reporting stable across invocations by deriving status-only manager dirty state from persisted index metadata instead of process-start defaults. (#10863) Thanks @BarryYangi. -- Memory/QMD: cap QMD command output buffering to prevent memory exhaustion from pathological `qmd` command output. -- Memory/QMD: parse qmd scope keys once per request to avoid repeated parsing in scope checks. -- Memory/QMD: query QMD index using exact docid matches before falling back to prefix lookup for better recall correctness and index efficiency. -- Memory/QMD: pass result limits to `search`/`vsearch` commands so QMD can cap results earlier. -- Memory/QMD: avoid reading full markdown files when a `from/lines` window is requested in QMD reads. -- Memory/QMD: skip rewriting unchanged session export markdown files during sync to reduce disk churn. -- Memory/QMD: make QMD result JSON parsing resilient to noisy command output by extracting the first JSON array from noisy `stdout`. -- Memory/QMD: treat prefixed `no results found` marker output as an empty result set in qmd JSON parsing. (#11302) Thanks @blazerui. -- Memory/QMD: avoid multi-collection `query` ranking corruption by running one `qmd query -c ` per managed collection and merging by best score (also used for `search`/`vsearch` fallback-to-query). (#16740) Thanks @volarian-vai. -- Memory/QMD: rebind managed collections when existing collection metadata drifts (including sessions name-only listings), preventing non-default agents from reusing another agent's `sessions` collection path. (#17194) Thanks @jonathanadams96. -- Memory/QMD: make `openclaw memory index` verify and print the active QMD index file path/size, and fail when QMD leaves a missing or zero-byte index artifact after an update. (#16775) Thanks @Shunamxiao. -- Memory/QMD: detect null-byte `ENOTDIR` update failures, rebuild managed collections once, and retry update to self-heal corrupted collection metadata. (#12919) Thanks @jorgejhms. -- Memory/QMD/Security: add `rawKeyPrefix` support for QMD scope rules and preserve legacy `keyPrefix: "agent:..."` matching, preventing scoped deny bypass when operators match agent-prefixed session keys. -- Memory/Builtin: narrow memory watcher targets to markdown globs and ignore dependency/venv directories to reduce file-descriptor pressure during memory sync startup. (#11721) Thanks @rex05ai. -- Security/Memory-LanceDB: treat recalled memories as untrusted context (escape injected memory text + explicit non-instruction framing), skip likely prompt-injection payloads during auto-capture, and restrict auto-capture to user messages to reduce memory-poisoning risk. (#12524) Thanks @davidschmid24. -- Security/Memory-LanceDB: require explicit `autoCapture: true` opt-in (default is now disabled) to prevent automatic PII capture unless operators intentionally enable it. (#12552) Thanks @fr33d3m0n. -- Diagnostics/Memory: prune stale diagnostic session state entries and cap tracked session states to prevent unbounded in-memory growth on long-running gateways. (#5136) Thanks @coygeek and @vignesh07. -- Gateway/Memory: clean up `agentRunSeq` tracking on run completion/abort and enforce maintenance-time cap pruning to prevent unbounded sequence-map growth over long uptimes. (#6036) Thanks @coygeek and @vignesh07. -- Auto-reply/Memory: bound `ABORT_MEMORY` growth by evicting oldest entries and deleting reset (`false`) flags so abort state tracking cannot grow unbounded over long uptimes. (#6629) Thanks @coygeek and @vignesh07. -- Slack/Memory: bound thread-starter cache growth with TTL + max-size pruning to prevent long-running Slack gateways from accumulating unbounded thread cache state. (#5258) Thanks @coygeek and @vignesh07. -- Outbound/Memory: bound directory cache growth with max-size eviction and proactive TTL pruning to prevent long-running gateways from accumulating unbounded directory entries. (#5140) Thanks @coygeek and @vignesh07. -- Skills/Memory: remove disconnected nodes from remote-skills cache to prevent stale node metadata from accumulating over long uptimes. (#6760) Thanks @coygeek. -- Sandbox/Tools: make sandbox file tools bind-mount aware (including absolute container paths) and enforce read-only bind semantics for writes. (#16379) Thanks @tasaankaeris. -- Sandbox/Prompts: show the sandbox container workdir as the prompt working directory and clarify host-path usage for file tools, preventing host-path `exec` failures in sandbox sessions. (#16790) Thanks @carrotRakko. -- Media/Security: allow local media reads from OpenClaw state `workspace/` and `sandboxes/` roots by default so generated workspace media can be delivered without unsafe global path bypasses. (#15541) Thanks @lanceji. -- Media/Security: harden local media allowlist bypasses by requiring an explicit `readFile` override when callers mark paths as validated, and reject filesystem-root `localRoots` entries. (#16739) -- Media/Security: allow outbound local media reads from the active agent workspace (including `workspace-`) via agent-scoped local roots, avoiding broad global allowlisting of all per-agent workspaces. (#17136) Thanks @MisterGuy420. -- Outbound/Media: thread explicit `agentId` through core `sendMessage` direct-delivery path so agent-scoped local media roots apply even when mirror metadata is absent. (#17268) Thanks @gumadeiras. -- Discord/Security: harden voice message media loading (SSRF + allowed-local-root checks) so tool-supplied paths/URLs cannot be used to probe internal URLs or read arbitrary local files. -- Security/BlueBubbles: require explicit `mediaLocalRoots` allowlists for local outbound media path reads to prevent local file disclosure. (#16322) Thanks @mbelinky. -- Security/BlueBubbles: reject ambiguous shared-path webhook routing when multiple webhook targets match the same guid/password. -- Security/BlueBubbles: harden BlueBubbles webhook auth behind reverse proxies by only accepting passwordless webhooks for direct localhost loopback requests (forwarded/proxied requests now require a password). Thanks @simecek. -- Feishu/Security: harden media URL fetching against SSRF and local file disclosure. (#16285) Thanks @mbelinky. -- Security/Zalo: reject ambiguous shared-path webhook routing when multiple webhook targets match the same secret. -- Security/Nostr: require loopback source and block cross-origin profile mutation/import attempts. Thanks @vincentkoc. -- Security/Signal: harden signal-cli archive extraction during install to prevent path traversal outside the install root. -- Security/Hooks: restrict hook transform modules to `~/.openclaw/hooks/transforms` (prevents path traversal/escape module loads via config). Config note: `hooks.transformsDir` must now be within that directory. Thanks @akhmittra. -- Security/Hooks: ignore hook package manifest entries that point outside the package directory (prevents out-of-tree handler loads during hook discovery). -- Security/Archive: enforce archive extraction entry/size limits to prevent resource exhaustion from high-expansion ZIP/TAR archives. Thanks @vincentkoc. -- Security/Media: reject oversized base64-backed input media before decoding to avoid large allocations. Thanks @vincentkoc. -- Security/Media: stream and bound URL-backed input media fetches to prevent memory exhaustion from oversized responses. Thanks @vincentkoc. -- Security/Skills: harden archive extraction for download-installed skills to prevent path traversal outside the target directory. Thanks @markmusson. -- Security/Slack: compute command authorization for DM slash commands even when `dmPolicy=open`, preventing unauthorized users from running privileged commands via DM. Thanks @christos-eth. -- Security/Pairing: scope pairing allowlist writes/reads to channel accounts (for example `telegram:yy`), and propagate account-aware pairing approvals so multi-account channels do not share a single per-channel pairing allowFrom store. (#17631) Thanks @crazytan. -- Security/iMessage: keep DM pairing-store identities out of group allowlist authorization (prevents cross-context command authorization). Thanks @vincentkoc. -- Security/Google Chat: deprecate `users/` allowlists (treat `users/...` as immutable user id only); keep raw email allowlists for usability. Thanks @vincentkoc. -- Security/Google Chat: reject ambiguous shared-path webhook routing when multiple webhook targets verify successfully (prevents cross-account policy-context misrouting). Thanks @vincentkoc. -- Telegram/Security: require numeric Telegram sender IDs for allowlist authorization (reject `@username` principals), auto-resolve `@username` to IDs in `openclaw doctor --fix` (when possible), and warn in `openclaw security audit` when legacy configs contain usernames. Thanks @vincentkoc. -- Telegram/Security: reject Telegram webhook startup when `webhookSecret` is missing or empty (prevents unauthenticated webhook request forgery). Thanks @yueyueL. -- Security/Windows: avoid shell invocation when spawning child processes to prevent cmd.exe metacharacter injection via untrusted CLI arguments (e.g. agent prompt text). -- Telegram: set webhook callback timeout handling to `onTimeout: "return"` (10s) so long-running update processing no longer emits webhook 500s and retry storms. (#16763) Thanks @chansearrington. -- Signal: preserve case-sensitive `group:` target IDs during normalization so mixed-case group IDs no longer fail with `Group not found`. (#16748) Thanks @repfigit. -- Security/Agents: scope CLI process cleanup to owned child PIDs to avoid killing unrelated processes on shared hosts. Thanks @aether-ai-agent. -- Security/Agents: enforce workspace-root path bounds for `apply_patch` in non-sandbox mode to block traversal and symlink escape writes. Thanks @p80n-sec. -- Security/Agents: enforce symlink-escape checks for `apply_patch` delete hunks under `workspaceOnly`, while still allowing deleting the symlink itself. Thanks @p80n-sec. -- Security/Agents (macOS): prevent shell injection when writing Claude CLI keychain credentials. (#15924) Thanks @aether-ai-agent. -- macOS: hard-limit unkeyed `openclaw://agent` deep links and ignore `deliver` / `to` / `channel` unless a valid unattended key is provided. Thanks @Cillian-Collins. -- Scripts/Security: validate GitHub logins and avoid shell invocation in `scripts/update-clawtributors.ts` to prevent command injection via malicious commit records. Thanks @scanleale. -- Security: fix Chutes manual OAuth login state validation by requiring the full redirect URL (reject code-only pastes) (thanks @aether-ai-agent). -- Security/Gateway: harden tool-supplied `gatewayUrl` overrides by restricting them to loopback or the configured `gateway.remote.url`. Thanks @p80n-sec. -- Security/Gateway: block `system.execApprovals.*` via `node.invoke` (use `exec.approvals.node.*` instead). Thanks @christos-eth. -- Security/Gateway: reject oversized base64 chat attachments before decoding to avoid large allocations. Thanks @vincentkoc. -- Security/Gateway: stop returning raw resolved config values in `skills.status` requirement checks (prevents operator.read clients from reading secrets). Thanks @simecek. -- Security/Net: fix SSRF guard bypass via full-form IPv4-mapped IPv6 literals (blocks loopback/private/metadata access). Thanks @yueyueL. -- Security/Browser: harden browser control file upload + download helpers to prevent path traversal / local file disclosure. Thanks @1seal. -- Security/Browser: block cross-origin mutating requests to loopback browser control routes (CSRF hardening). Thanks @vincentkoc. -- Security/Node Host: enforce `system.run` rawCommand/argv consistency to prevent allowlist/approval bypass. Thanks @christos-eth. -- Security/Exec approvals: prevent safeBins allowlist bypass via shell expansion (host exec allowlist mode only; not enabled by default). Thanks @christos-eth. -- Security/Exec: harden PATH handling by disabling project-local `node_modules/.bin` bootstrapping by default, disallowing node-host `PATH` overrides, and spawning ACP servers via the current executable by default. Thanks @akhmittra. -- Security/Tlon: harden Urbit URL fetching against SSRF by blocking private/internal hosts by default (opt-in: `channels.tlon.allowPrivateNetwork`). Thanks @p80n-sec. -- Security/Voice Call (Telnyx): require webhook signature verification when receiving inbound events; configs without `telnyx.publicKey` are now rejected unless `skipSignatureVerification` is enabled. Thanks @p80n-sec. -- Security/Voice Call: require valid Twilio webhook signatures even when ngrok free tier loopback compatibility mode is enabled. Thanks @p80n-sec. -- Security/Discovery: stop treating Bonjour TXT records as authoritative routing (prefer resolved service endpoints) and prevent discovery from overriding stored TLS pins; autoconnect now requires a previously trusted gateway. Thanks @simecek. - -## 2026.2.13 - -### Changes - -- Install: add optional Podman-based setup: `setup-podman.sh` for one-time host setup (openclaw user, image, launch script, systemd quadlet), `run-openclaw-podman.sh launch` / `launch setup`; systemd Quadlet unit for openclaw user service; docs for rootless container, openclaw user (subuid/subgid), and quadlet (troubleshooting). (#16273) Thanks @DarwinsBuddy. -- Discord: send voice messages with waveform previews from local audio files (including silent delivery). (#7253) Thanks @nyanjou. -- Discord: add configurable presence status/activity/type/url (custom status defaults to activity text). (#10855) Thanks @h0tp-ftw. -- Slack/Plugins: add thread-ownership outbound gating via `message_sending` hooks, including @-mention bypass tracking and Slack outbound hook wiring for cancel/modify behavior. (#15775) Thanks @DarlingtonDeveloper. -- Agents: add synthetic catalog support for `hf:zai-org/GLM-5`. (#15867) Thanks @battman21. -- Skills: remove duplicate `local-places` Google Places skill/proxy and keep `goplaces` as the single supported Google Places path. -- Agents: add pre-prompt context diagnostics (`messages`, `systemPromptChars`, `promptChars`, provider/model, session file) before embedded runner prompt calls to improve overflow debugging. (#8930) Thanks @Glucksberg. -- Onboarding/Providers: add first-class Hugging Face Inference provider support (provider wiring, onboarding auth choice/API key flow, and default-model selection), and preserve Hugging Face auth intent in auth-choice remapping (`tokenProvider=huggingface` with `authChoice=apiKey`) while skipping env-override prompts when an explicit token is provided. (#13472) Thanks @Josephrp. -- Onboarding/Providers: add `minimax-api-key-cn` auth choice for the MiniMax China API endpoint. (#15191) Thanks @liuy. - -### Breaking - -- Config/State: removed legacy `.moltbot` auto-detection/migration and `moltbot.json` config candidates. If you still have state/config under `~/.moltbot`, move it to `~/.openclaw` (recommended) or set `OPENCLAW_STATE_DIR` / `OPENCLAW_CONFIG_PATH` explicitly. - -### Fixes - -- Gateway/Auth: add trusted-proxy mode hardening follow-ups by keeping `OPENCLAW_GATEWAY_*` env compatibility, auto-normalizing invalid setup combinations in interactive `gateway configure` (trusted-proxy forces `bind=lan` and disables Tailscale serve/funnel), and suppressing shared-secret/rate-limit audit findings that do not apply to trusted-proxy deployments. (#15940) Thanks @nickytonline. -- Docs/Hooks: update hooks documentation URLs to the new `/automation/hooks` location. (#16165) Thanks @nicholascyh. -- Security/Audit: warn when `gateway.tools.allow` re-enables default-denied tools over HTTP `POST /tools/invoke`, since this can increase RCE blast radius if the gateway is reachable. -- Security/Plugins/Hooks: harden npm-based installs by restricting specs to registry packages only, passing `--ignore-scripts` to `npm pack`, and cleaning up temp install directories. -- Security/Sessions: preserve inter-session input provenance for routed prompts so delegated/internal sessions are not treated as direct external user instructions. Thanks @anbecker. -- Feishu: stop persistent Typing reaction on NO_REPLY/suppressed runs by wiring reply-dispatcher cleanup to remove typing indicators. (#15464) Thanks @arosstale. -- Agents: strip leading empty lines from `sanitizeUserFacingText` output and normalize whitespace-only outputs to empty text. (#16158) Thanks @mcinteerj. -- BlueBubbles: gracefully degrade when Private API is disabled by filtering private-only actions, skipping private-only reactions/reply effects, and avoiding private reply markers so non-private flows remain usable. (#16002) Thanks @L-U-C-K-Y. -- Outbound: add a write-ahead delivery queue with crash-recovery retries to prevent lost outbound messages after gateway restarts. (#15636) Thanks @nabbilkhan, @thewilloftheshadow. -- Auto-reply/Threading: auto-inject implicit reply threading so `replyToMode` works without requiring model-emitted `[[reply_to_current]]`, while preserving `replyToMode: "off"` behavior for implicit Slack replies and keeping block-streaming chunk coalescing stable under `replyToMode: "first"`. (#14976) Thanks @Diaspar4u. -- Auto-reply/Threading: honor explicit `[[reply_to_*]]` tags even when `replyToMode` is `off`. (#16174) Thanks @aldoeliacim. -- Plugins/Threading: rename `allowTagsWhenOff` to `allowExplicitReplyTagsWhenOff` and keep the old key as a deprecated alias for compatibility. (#16189) -- Outbound/Threading: pass `replyTo` and `threadId` from `message send` tool actions through the core outbound send path to channel adapters, preserving thread/reply routing. (#14948) Thanks @mcaxtr. -- Auto-reply/Media: allow image-only inbound messages (no caption) to reach the agent instead of short-circuiting as empty text, and preserve thread context in queued/followup prompt bodies for media-only runs. (#11916) Thanks @arosstale. -- Discord: route autoThread replies to existing threads instead of the root channel. (#8302) Thanks @gavinbmoore, @thewilloftheshadow. -- Web UI: add `img` to DOMPurify allowed tags and `src`/`alt` to allowed attributes so markdown images render in webchat instead of being stripped. (#15437) Thanks @lailoo. -- Telegram/Matrix: treat MP3 and M4A (including `audio/mp4`) as voice-compatible for `asVoice` routing, and keep WAV/AAC falling back to regular audio sends. (#15438) Thanks @azade-c. -- WhatsApp: preserve outbound document filenames for web-session document sends instead of always sending `"file"`. (#15594) Thanks @TsekaLuk. -- Telegram: cap bot menu registration to Telegram's 100-command limit with an overflow warning while keeping typed hidden commands available. (#15844) Thanks @battman21. -- Telegram: scope skill commands to the resolved agent for default accounts so `setMyCommands` no longer triggers `BOT_COMMANDS_TOO_MUCH` when multiple agents are configured. (#15599) -- Discord: avoid misrouting numeric guild allowlist entries to `/channels/` by prefixing guild-only inputs with `guild:` during resolution. (#12326) Thanks @headswim. -- Memory/QMD: default `memory.qmd.searchMode` to `search` for faster CPU-only recall and always scope `search`/`vsearch` requests to managed collections (auto-falling back to `query` when required). (#16047) Thanks @togotago. -- Memory/LanceDB: add configurable `captureMaxChars` for auto-capture while keeping the legacy 500-char default. (#16641) Thanks @ciberponk. -- MS Teams: preserve parsed mention entities/text when appending OneDrive fallback file links, and accept broader real-world Teams mention ID formats (`29:...`, `8:orgid:...`) while still rejecting placeholder patterns. (#15436) Thanks @hyojin. -- Media: classify `text/*` MIME types as documents in media-kind routing so text attachments are no longer treated as unknown. (#12237) Thanks @arosstale. -- Inbound/Web UI: preserve literal `\n` sequences when normalizing inbound text so Windows paths like `C:\\Work\\nxxx\\README.md` are not corrupted. (#11547) Thanks @mcaxtr. -- TUI/Streaming: preserve richer streamed assistant text when final payload drops pre-tool-call text blocks, while keeping non-empty final payload authoritative for plain-text updates. (#15452) Thanks @TsekaLuk. -- Providers/MiniMax: switch implicit MiniMax API-key provider from `openai-completions` to `anthropic-messages` with the correct Anthropic-compatible base URL, fixing `invalid role: developer (2013)` errors on MiniMax M2.5. (#15275) Thanks @lailoo. -- Ollama/Agents: use resolved model/provider base URLs for native `/api/chat` streaming (including aliased providers), normalize `/v1` endpoints, and forward abort + `maxTokens` stream options for reliable cancellation and token caps. (#11853) Thanks @BrokenFinger98. -- OpenAI Codex/Spark: implement end-to-end `gpt-5.3-codex-spark` support across fallback/thinking/model resolution and `models list` forward-compat visibility. (#14990, #15174) Thanks @L-U-C-K-Y, @loiie45e. -- Agents/Codex: allow `gpt-5.3-codex-spark` in forward-compat fallback, live model filtering, and thinking presets, and fix model-picker recognition for spark. (#14990) Thanks @L-U-C-K-Y. -- Models/Codex: resolve configured `openai-codex/gpt-5.3-codex-spark` through forward-compat fallback during `models list`, so it is not incorrectly tagged as missing when runtime resolution succeeds. (#15174) Thanks @loiie45e. -- OpenAI Codex/Auth: bridge OpenClaw OAuth profiles into `pi` `auth.json` so model discovery and models-list registry resolution can use Codex OAuth credentials. (#15184) Thanks @loiie45e. -- Auth/OpenAI Codex: share OAuth login handling across onboarding and `models auth login --provider openai-codex`, keep onboarding alive when OAuth fails, and surface a direct OAuth help note instead of terminating the wizard. (#15406, follow-up to #14552) Thanks @zhiluo20. -- Onboarding/Providers: add vLLM as an onboarding provider with model discovery, auth profile wiring, and non-interactive auth-choice validation. (#12577) Thanks @gejifeng. -- Onboarding/CLI: restore terminal state without resuming paused `stdin`, so onboarding exits cleanly (including Docker TTY installs that would otherwise hang). (#12972) Thanks @vincentkoc. -- Signal/Install: auto-install `signal-cli` via Homebrew on non-x64 Linux architectures, avoiding x86_64 native binary `Exec format error` failures on arm64/arm hosts. (#15443) Thanks @jogvan-k. -- macOS Voice Wake: fix a crash in trigger trimming for CJK/Unicode transcripts by matching and slicing on original-string ranges instead of transformed-string indices. (#11052) Thanks @Flash-LHR. -- Mattermost (plugin): retry websocket monitor connections with exponential backoff and abort-aware teardown so transient connect failures no longer permanently stop monitoring. (#14962) Thanks @mcaxtr. -- Discord/Agents: apply channel/group `historyLimit` during embedded-runner history compaction to prevent long-running channel sessions from bypassing truncation and overflowing context windows. (#11224) Thanks @shadril238. -- Outbound targets: fail closed for WhatsApp/Twitch/Google Chat fallback paths so invalid or missing targets are dropped instead of rerouted, and align resolver hints with strict target requirements. (#13578) Thanks @mcaxtr. -- Gateway/Restart: clear stale command-queue and heartbeat wake runtime state after SIGUSR1 in-process restarts to prevent zombie gateway behavior where queued work stops draining. (#15195) Thanks @joeykrug. -- Heartbeat: prevent scheduler silent-death races during runner reloads, preserve retry cooldown backoff under wake bursts, and prioritize user/action wake causes over interval/retry reasons when coalescing. (#15108) Thanks @joeykrug. -- Heartbeat: allow explicit wake (`wake`) and hook wake (`hook:*`) reasons to run even when `HEARTBEAT.md` is effectively empty so queued system events are processed. (#14527) Thanks @arosstale. -- Auto-reply/Heartbeat: strip sentence-ending `HEARTBEAT_OK` tokens even when followed by up to 4 punctuation characters, while preserving surrounding sentence punctuation. (#15847) Thanks @Spacefish. -- Sessions/Agents: pass `agentId` when resolving existing transcript paths in reply runs so non-default agents and heartbeat/chat handlers no longer fail with `Session file path must be within sessions directory`. (#15141) Thanks @Goldenmonstew. -- Sessions/Agents: pass `agentId` through status and usage transcript-resolution paths (auto-reply, gateway usage APIs, and session cost/log loaders) so non-default agents can resolve absolute session files without path-validation failures. (#15103) Thanks @jalehman. -- Sessions: archive previous transcript files on `/new` and `/reset` session resets (including gateway `sessions.reset`) so stale transcripts do not accumulate on disk. (#14869) Thanks @mcaxtr. -- Status/Sessions: stop clamping derived `totalTokens` to context-window size, keep prompt-token snapshots wired through session accounting, and surface context usage as unknown when fresh snapshot data is missing to avoid false 100% reports. (#15114) Thanks @echoVic. -- Gateway/Routing: speed up hot paths for session listing (derived titles + previews), WS broadcast, and binding resolution. -- Gateway/Sessions: cache derived title + last-message transcript reads to speed up repeated sessions list refreshes. -- CLI/Completion: route plugin-load logs to stderr and write generated completion scripts directly to stdout to avoid `source <(openclaw completion ...)` corruption. (#15481) Thanks @arosstale. -- CLI: lazily load outbound provider dependencies and remove forced success-path exits so commands terminate naturally without killing intentional long-running foreground actions. (#12906) Thanks @DrCrinkle. -- CLI: speed up startup by lazily registering core commands (keeps rich `--help` while reducing cold-start overhead). -- Security/Gateway + ACP: block high-risk tools (`sessions_spawn`, `sessions_send`, `gateway`, `whatsapp_login`) from HTTP `/tools/invoke` by default with `gateway.tools.{allow,deny}` overrides, and harden ACP permission selection to fail closed when tool identity/options are ambiguous while supporting `allow_always`/`reject_always`. (#15390) Thanks @aether-ai-agent. -- Security/ACP: prompt for non-read/search permission requests in ACP clients (reduces silent tool approval risk). Thanks @aether-ai-agent. -- Security/Gateway: breaking default-behavior change - canvas IP-based auth fallback now only accepts machine-scoped addresses (RFC1918, link-local, ULA IPv6, CGNAT); public-source IP matches now require bearer token auth. (#14661) Thanks @sumleo. -- Security/Link understanding: block loopback/internal host patterns and private/mapped IPv6 addresses in extracted URL handling to close SSRF bypasses in link CLI flows. (#15604) Thanks @AI-Reviewer-QS. -- Security/Browser: constrain `POST /trace/stop`, `POST /wait/download`, and `POST /download` output paths to OpenClaw temp roots and reject traversal/escape paths. -- Security/Browser: sanitize download `suggestedFilename` to keep implicit `wait/download` paths within the downloads root. Thanks @1seal. -- Security/Browser: confine `POST /hooks/file-chooser` upload paths to an OpenClaw temp uploads root and reject traversal/escape paths. Thanks @1seal. -- Security/Browser: require auth for the sandbox browser bridge server (protects `/profiles`, `/tabs`, CDP URLs, and other control endpoints). Thanks @jackhax. -- Security: bind local helper servers to loopback and fail closed on non-loopback OAuth callback hosts (reduces localhost/LAN attack surface). -- Security/Canvas: serve A2UI assets via the shared safe-open path (`openFileWithinRoot`) to close traversal/TOCTOU gaps, with traversal and symlink regression coverage. (#10525) Thanks @abdelsfane. -- Security/WhatsApp: enforce `0o600` on `creds.json` and `creds.json.bak` on save/backup/restore paths to reduce credential file exposure. (#10529) Thanks @abdelsfane. -- Security/Gateway: sanitize and truncate untrusted WebSocket header values in pre-handshake close logs to reduce log-poisoning risk. Thanks @thewilloftheshadow. -- Security/Audit: add misconfiguration checks for sandbox Docker config with sandbox mode off, ineffective `gateway.nodes.denyCommands` entries, global minimal tool-profile overrides by agent profiles, and permissive extension-plugin tool reachability. -- Security/Audit: distinguish external webhooks (`hooks.enabled`) from internal hooks (`hooks.internal.enabled`) in attack-surface summaries to avoid false exposure signals when only internal hooks are enabled. (#13474) Thanks @mcaxtr. -- Security/Onboarding: clarify multi-user DM isolation remediation with explicit `openclaw config set session.dmScope ...` commands in security audit, doctor security, and channel onboarding guidance. (#13129) Thanks @VintLin. -- Security/Gateway: bind node `system.run` approval overrides to gateway exec-approval records (runId-bound), preventing approval-bypass via `node.invoke` param injection. Thanks @222n5. -- Agents/Nodes: harden node exec approval decision handling in the `nodes` tool run path by failing closed on unexpected approval decisions, and add regression coverage for approval-required retry/deny/timeout flows. (#4726) Thanks @rmorse. -- Android/Nodes: harden `app.update` by requiring HTTPS and gateway-host URL matching plus SHA-256 verification, stream URL camera downloads to disk with size guards to avoid memory spikes, and stop signing release builds with debug keys. (#13541) Thanks @smartprogrammer93. -- Routing: enforce strict binding-scope matching across peer/guild/team/roles so peer-scoped Discord/Slack bindings no longer match unrelated guild/team contexts or fallback tiers. (#15274) Thanks @lailoo. -- Exec/Allowlist: allow multiline heredoc bodies (`<<`, `<<-`) while keeping multiline non-heredoc shell commands blocked, so exec approval parsing permits heredoc input safely without allowing general newline command chaining. (#13811) Thanks @mcaxtr. -- Config: preserve `${VAR}` env references when writing config files so `openclaw config set/apply/patch` does not persist secrets to disk. Thanks @thewilloftheshadow. -- Config: remove a cross-request env-snapshot race in config writes by carrying read-time env context into write calls per request, preserving `${VAR}` refs safely under concurrent gateway config mutations. (#11560) Thanks @akoscz. -- Config: log overwrite audit entries (path, backup target, and hash transition) whenever an existing config file is replaced, improving traceability for unexpected config clobbers. -- Config: keep legacy audio transcription migration strict by rejecting non-string/unsafe command tokens while still migrating valid custom script executables. (#5042) Thanks @shayan919293. -- Config: accept `$schema` key in config file so JSON Schema editor tooling works without validation errors. (#14998) -- Gateway/Tools Invoke: sanitize `/tools/invoke` execution failures while preserving `400` for tool input errors and returning `500` for unexpected runtime failures, with regression coverage and docs updates. (#13185) Thanks @davidrudduck. -- Gateway/Hooks: preserve `408` for hook request-body timeout responses while keeping bounded auth-failure cache eviction behavior, with timeout-status regression coverage. (#15848) Thanks @AI-Reviewer-QS. -- Plugins/Hooks: fire `before_tool_call` hook exactly once per tool invocation in embedded runs by removing duplicate dispatch paths while preserving parameter mutation semantics. (#15635) Thanks @lailoo. -- Agents/Transcript policy: sanitize OpenAI/Codex tool-call ids during transcript policy normalization to prevent invalid tool-call identifiers from propagating into session history. (#15279) Thanks @divisonofficer. -- Agents/Image tool: cap image-analysis completion `maxTokens` by model capability (`min(4096, model.maxTokens)`) to avoid over-limit provider failures while still preventing truncation. (#11770) Thanks @detecti1. -- Agents/Compaction: centralize exec default resolution in the shared tool factory so per-agent `tools.exec` overrides (host/security/ask/node and related defaults) persist across compaction retries. (#15833) Thanks @napetrov. -- Gateway/Agents: stop injecting a phantom `main` agent into gateway agent listings when `agents.list` explicitly excludes it. (#11450) Thanks @arosstale. -- Process/Exec: avoid shell execution for `.exe` commands on Windows so env overrides work reliably in `runCommandWithTimeout`. Thanks @thewilloftheshadow. -- Daemon/Windows: preserve literal backslashes in `gateway.cmd` command parsing so drive and UNC paths are not corrupted in runtime checks and doctor entrypoint comparisons. (#15642) Thanks @arosstale. -- Sandbox: pass configured `sandbox.docker.env` variables to sandbox containers at `docker create` time. (#15138) Thanks @stevebot-alive. -- Voice Call: route webhook runtime event handling through shared manager event logic so rejected inbound hangups are idempotent in production, with regression tests for duplicate reject events and provider-call-ID remapping parity. (#15892) Thanks @dcantu96. -- Cron: add regression coverage for announce-mode isolated jobs so runs that already report `delivered: true` do not enqueue duplicate main-session relays, including delivery configs where `mode` is omitted and defaults to announce. (#15737) Thanks @brandonwise. -- Cron: honor `deleteAfterRun` in isolated announce delivery by mapping it to subagent announce cleanup mode, so cron run sessions configured for deletion are removed after completion. (#15368) Thanks @arosstale. -- Web tools/web_fetch: prefer `text/markdown` responses for Cloudflare Markdown for Agents, add `cf-markdown` extraction for markdown bodies, and redact fetched URLs in `x-markdown-tokens` debug logs to avoid leaking raw paths/query params. (#15376) Thanks @Yaxuan42. -- Tools/web_search: support `freshness` for the Perplexity provider by mapping `pd`/`pw`/`pm`/`py` to Perplexity `search_recency_filter` values and including freshness in the Perplexity cache key. (#15343) Thanks @echoVic. -- Clawdock: avoid Zsh readonly variable collisions in helper scripts. (#15501) Thanks @nkelner. -- Memory: switch default local embedding model to the QAT `embeddinggemma-300m-qat-Q8_0` variant for better quality at the same footprint. (#15429) Thanks @azade-c. -- Docs/Discord: expand quick setup and clarify guild workspace guidance. (#20088) Thanks @pejmanjohn, @thewilloftheshadow. -- Docs/Mermaid: remove hardcoded Mermaid init theme blocks from four docs diagrams so dark mode inherits readable theme defaults. (#15157) Thanks @heytulsiprasad. -- Security/Pairing: generate 256-bit base64url device and node pairing tokens and use byte-safe constant-time verification to avoid token-compare edge-case failures. (#16535) Thanks @FaizanKolega, @gumadeiras. - -## 2026.2.12 - -### Changes - -- CLI/Plugins: add `openclaw plugins uninstall ` with `--dry-run`, `--force`, and `--keep-files` options, including safe uninstall path handling and plugin uninstall docs. (#5985) Thanks @JustasMonkev. -- CLI: add `openclaw logs --local-time` to display log timestamps in local timezone. (#13818) Thanks @xialonglee. -- Telegram: render blockquotes as native `
` tags instead of stripping them. (#14608) -- Telegram: expose `/compact` in the native command menu. (#10352) Thanks @akramcodez. -- Discord: add role-based allowlists and role-based agent routing. (#10650) Thanks @Minidoracat. -- Config: avoid redacting `maxTokens`-like fields during config snapshot redaction, preventing round-trip validation failures in `/config`. (#14006) Thanks @constansino. - -### Breaking - -- Hooks: `POST /hooks/agent` now rejects payload `sessionKey` overrides by default. To keep fixed hook context, set `hooks.defaultSessionKey` (recommended with `hooks.allowedSessionKeyPrefixes: ["hook:"]`). If you need legacy behavior, explicitly set `hooks.allowRequestSessionKey: true`. Thanks @alpernae for reporting. - -### Fixes - -- Gateway/OpenResponses: harden URL-based `input_file`/`input_image` handling with explicit SSRF deny policy, hostname allowlists (`files.urlAllowlist` / `images.urlAllowlist`), per-request URL input caps (`maxUrlParts`), blocked-fetch audit logging, and regression coverage/docs updates. -- Sessions: guard `withSessionStoreLock` against undefined `storePath` to prevent `path.dirname` crash. (#14717) -- Security: fix unauthenticated Nostr profile API remote config tampering. (#13719) Thanks @coygeek. -- Security: remove bundled soul-evil hook. (#14757) Thanks @Imccccc. -- Security/Audit: add hook session-routing hardening checks (`hooks.defaultSessionKey`, `hooks.allowRequestSessionKey`, and prefix allowlists), and warn when HTTP API endpoints allow explicit session-key routing. -- Security/Sandbox: confine mirrored skill sync destinations to the sandbox `skills/` root and stop using frontmatter-controlled skill names as filesystem destination paths. Thanks @1seal. -- Security/Web tools: treat browser/web content as untrusted by default (wrapped outputs for browser snapshot/tabs/console and structured external-content metadata for web tools), and strip `toolResult.details` from model-facing transcript/compaction inputs to reduce prompt-injection replay risk. -- Security/Hooks: harden webhook and device token verification with shared constant-time secret comparison, and add per-client auth-failure throttling for hook endpoints (`429` + `Retry-After`). Thanks @akhmittra. -- Security/Browser: require auth for loopback browser control HTTP routes, auto-generate `gateway.auth.token` when browser control starts without auth, and add a security-audit check for unauthenticated browser control. Thanks @tcusolle. -- Sessions/Gateway: harden transcript path resolution and reject unsafe session IDs/file paths so session operations stay within agent sessions directories. Thanks @akhmittra. -- Sessions: preserve `verboseLevel`, `thinkingLevel`/`reasoningLevel`, and `ttsAuto` overrides across `/new` and `/reset` session resets. (#10787) Thanks @mcaxtr. -- Gateway: raise WS payload/buffer limits so 5,000,000-byte image attachments work reliably. (#14486) Thanks @0xRaini. -- Logging/CLI: use local timezone timestamps for console prefixing, and include `±HH:MM` offsets when using `openclaw logs --local-time` to avoid ambiguity. (#14771) Thanks @0xRaini. -- Gateway: drain active turns before restart to prevent message loss. (#13931) Thanks @0xRaini. -- Gateway: auto-generate auth token during install to prevent launchd restart loops. (#13813) Thanks @cathrynlavery. -- Gateway: prevent `undefined`/missing token in auth config. (#13809) Thanks @asklee-klawd. -- Configure/Gateway: reject literal `"undefined"`/`"null"` token input and validate gateway password prompt values to avoid invalid password-mode configs. (#13767) Thanks @omair445. -- Gateway: handle async `EPIPE` on stdout/stderr during shutdown. (#13414) Thanks @keshav55. -- Gateway/Control UI: resolve missing dashboard assets when `openclaw` is installed globally via symlink-based Node managers (nvm/fnm/n/Homebrew). (#14919) Thanks @aynorica. -- Gateway/Control UI: keep partial assistant output visible when runs are aborted, and persist aborted partials to session transcripts for follow-up context. -- Cron: use requested `agentId` for isolated job auth resolution. (#13983) Thanks @0xRaini. -- Cron: prevent cron jobs from skipping execution when `nextRunAtMs` advances. (#14068) Thanks @WalterSumbon. -- Cron: pass `agentId` to `runHeartbeatOnce` for main-session jobs. (#14140) Thanks @ishikawa-pro. -- Cron: re-arm timers when `onTimer` fires while a job is still executing. (#14233) Thanks @tomron87. -- Cron: prevent duplicate fires when multiple jobs trigger simultaneously. (#14256) Thanks @xinhuagu. -- Cron: prevent duplicate announce-mode isolated cron deliveries, and keep main-session fallback active when best-effort structured delivery attempts fail to send any message. (#15739) Thanks @widingmarcus-cyber. -- Cron: isolate scheduler errors so one bad job does not break all jobs. (#14385) Thanks @MarvinDontPanic. -- Cron: prevent one-shot `at` jobs from re-firing on restart after skipped/errored runs. (#13878) Thanks @lailoo. -- Heartbeat: prevent scheduler stalls on unexpected run errors and avoid immediate rerun loops after `requests-in-flight` skips. (#14901) Thanks @joeykrug. -- Cron: honor stored session model overrides for isolated-agent runs while preserving `hooks.gmail.model` precedence for Gmail hook sessions. (#14983) Thanks @shtse8. -- Logging/Browser: fall back to `os.tmpdir()/openclaw` for default log, browser trace, and browser download temp paths when `/tmp/openclaw` is unavailable. -- WhatsApp: convert Markdown bold/strikethrough to WhatsApp formatting. (#14285) Thanks @Raikan10. -- WhatsApp: allow media-only sends and normalize leading blank payloads. (#14408) Thanks @karimnaguib. -- WhatsApp: default MIME type for voice messages when Baileys omits it. (#14444) Thanks @mcaxtr. -- Telegram: handle no-text message in model picker editMessageText. (#14397) Thanks @0xRaini. -- Telegram: surface REACTION_INVALID as non-fatal warning. (#14340) Thanks @0xRaini. -- BlueBubbles: fix webhook auth bypass via loopback proxy trust. (#13787) Thanks @coygeek. -- Slack: change default replyToMode from "off" to "all". (#14364) Thanks @nm-de. -- Slack: honor `limit` for `emoji-list` actions across core and extension adapters, with capped emoji-list responses in the Slack action handler. (#4293) Thanks @mcaxtr. -- Slack: detect control commands when channel messages start with bot mention prefixes (for example, `@Bot /new`). (#14142) Thanks @beefiker. -- Slack: include thread reply metadata in inbound message footer context (`thread_ts`, `parent_user_id`) while keeping top-level `thread_ts == ts` events unthreaded. (#14625) Thanks @bennewton999. -- Signal: enforce E.164 validation for the Signal bot account prompt so mistyped numbers are caught early. (#15063) Thanks @Duartemartins. -- Discord: process DM reactions instead of silently dropping them. (#10418) Thanks @mcaxtr. -- Discord: treat Administrator as full permissions in channel permission checks. Thanks @thewilloftheshadow. -- Discord: respect replyToMode in threads. (#11062) Thanks @cordx56. -- Discord: add optional gateway proxy support for WebSocket connections via `channels.discord.proxy`. (#10400) Thanks @winter-loo, @thewilloftheshadow. -- Browser: add Chrome launch flag `--disable-blink-features=AutomationControlled` to reduce `navigator.webdriver` automation detection issues on reCAPTCHA-protected sites. (#10735) Thanks @Milofax. -- Heartbeat: filter noise-only system events so scheduled reminder notifications do not fire when cron runs carry only heartbeat markers. (#13317) Thanks @pvtclawn. -- Signal: render mention placeholders as `@uuid`/`@phone` so mention gating and Clawdbot targeting work. (#2013) Thanks @alexgleason. -- Agents/Reminders: guard reminder promises by appending a note when no `cron.add` succeeded in the turn, so users know nothing was scheduled. (#18588) Thanks @vignesh07. -- Discord: omit empty content fields for media-only messages while preserving caption whitespace. (#9507) Thanks @leszekszpunar. -- Onboarding/Providers: add Z.AI endpoint-specific auth choices (`zai-coding-global`, `zai-coding-cn`, `zai-global`, `zai-cn`) and expand default Z.AI model wiring. (#13456) Thanks @tomsun28. -- Onboarding/Providers: update MiniMax API default/recommended models from M2.1 to M2.5, add M2.5/M2.5-Lightning model entries, and include `minimax-m2.5` in modern model filtering. (#14865) Thanks @adao-max. -- Ollama: use configured `models.providers.ollama.baseUrl` for model discovery and normalize `/v1` endpoints to the native Ollama API root. (#14131) Thanks @shtse8. -- Voice Call: pass Twilio stream auth token via `` instead of query string. (#14029) Thanks @mcwigglesmcgee. -- Config/Models: allow full `models.providers.*.models[*].compat` keys used by `openai-completions` (`thinkingFormat`, `supportsStrictMode`, and streaming/tool-result compatibility flags) so valid provider overrides no longer fail strict config validation. (#11063) Thanks @ikari-pl. -- Feishu: pass `Buffer` directly to the Feishu SDK upload APIs instead of `Readable.from(...)` to avoid form-data upload failures. (#10345) Thanks @youngerstyle. -- Feishu: trigger mention-gated group handling only when the bot itself is mentioned (not just any mention). (#11088) Thanks @openperf. -- Feishu: probe status uses the resolved account context for multi-account credential checks. (#11233) Thanks @onevcat. -- Feishu: add streaming card replies via Card Kit API and preserve `renderMode=auto` fallback behavior for plain-text responses. (#10379) Thanks @xzq-xu. -- Feishu DocX: preserve top-level converted block order using `firstLevelBlockIds` when writing/appending documents. (#13994) Thanks @Cynosure159. -- Feishu plugin packaging: remove `workspace:*` `openclaw` dependency from `extensions/feishu` and sync lockfile for install compatibility. (#14423) Thanks @jackcooper2015. -- CLI/Wizard: exit with code 1 when `configure`, `agents add`, or interactive `onboard` wizards are canceled, so `set -e` automation stops correctly. (#14156) Thanks @0xRaini. -- Media: strip `MEDIA:` lines with local paths instead of leaking as visible text. (#14399) Thanks @0xRaini. -- Config/Cron: exclude `maxTokens` from config redaction and honor `deleteAfterRun` on skipped cron jobs. (#13342) Thanks @niceysam. -- Config: ignore `meta` field changes in config file watcher. (#13460) Thanks @brandonwise. -- Daemon: suppress `EPIPE` error when restarting LaunchAgent. (#14343) Thanks @0xRaini. -- Antigravity: add opus 4.6 forward-compat model and bypass thinking signature sanitization. (#14218) Thanks @jg-noncelogic. -- Agents: prevent file descriptor leaks in child process cleanup. (#13565) Thanks @KyleChen26. -- Agents: prevent double compaction caused by cache TTL bypassing guard. (#13514) Thanks @taw0002. -- Agents: use last API call's cache tokens for context display instead of accumulated sum. (#13805) Thanks @akari-musubi. -- Agents: keep followup-runner session `totalTokens` aligned with post-compaction context by using last-call usage and shared token-accounting logic. (#14979) Thanks @shtse8. -- Hooks/Plugins: wire 9 previously unwired plugin lifecycle hooks into core runtime paths (session, compaction, gateway, and outbound message hooks). (#14882) Thanks @shtse8. -- Hooks/Tools: dispatch `before_tool_call` and `after_tool_call` hooks from both tool execution paths with rebased conflict fixes. (#15012) Thanks @Patrick-Barletta, @Takhoffman. -- Hooks: replace loader `console.*` output with subsystem logger messages so hook loading errors/warnings route through standard logging. (#11029) Thanks @shadril238. -- Discord: allow channel-edit to archive/lock threads and set auto-archive duration. (#5542) Thanks @stumct. -- Discord tests: use a partial @buape/carbon mock in slash command coverage. (#13262) Thanks @arosstale. -- Tests: update thread ID handling in Slack message collection tests. (#14108) Thanks @swizzmagik. -- Update/Daemon: fix post-update restart compatibility by generating `dist/cli/daemon-cli.js` with alias-aware exports from hashed daemon bundles, preventing `registerDaemonCli` import failures during `openclaw update`. - -## 2026.2.9 - -### Added - -- Commands: add `commands.allowFrom` config for separate command authorization, allowing operators to restrict slash commands to specific users while keeping chat open to others. (#12430) Thanks @thewilloftheshadow. -- Docker: add ClawDock shell helpers for Docker workflows. (#12817) Thanks @Olshansk. -- Gateway: periodic channel health monitor auto-restarts stuck, crashed, or silently-stopped channels. Configurable via `gateway.channelHealthCheckMinutes` (default: 5, set to 0 to disable). (#7053, #4302) -- iOS: alpha node app + setup-code onboarding. (#11756) Thanks @mbelinky. -- Channels: comprehensive BlueBubbles and channel cleanup. (#11093) Thanks @tyler6204. -- Channels: IRC first-class channel support. (#11482) Thanks @vignesh07. -- Plugins: device pairing + phone control plugins (Telegram `/pair`, iOS/Android node controls). (#11755) Thanks @mbelinky. -- Tools: add Grok (xAI) as a `web_search` provider. (#12419) Thanks @tmchow. -- Gateway: add agent management RPC methods for the web UI (`agents.create`, `agents.update`, `agents.delete`). (#11045) Thanks @advaitpaliwal. -- Gateway: stream thinking events to WS clients and broadcast tool events independent of verbose level. (#10568) Thanks @nk1tz. -- Web UI: show a Compaction divider in chat history. (#11341) Thanks @Takhoffman. -- Agents: include runtime shell in agent envelopes. (#1835) Thanks @Takhoffman. -- Agents: auto-select `zai/glm-4.6v` for image understanding when ZAI is primary provider. (#10267) Thanks @liuy. -- Paths: add `OPENCLAW_HOME` for overriding the home directory used by internal path resolution. (#12091) Thanks @sebslight. -- Onboarding: add Custom Provider flow for OpenAI and Anthropic-compatible endpoints. (#11106) Thanks @MackDing. -- Hooks: route webhook agent runs to specific `agentId`s, add `hooks.allowedAgentIds` controls, and fall back to default agent when unknown IDs are provided. (#13672) Thanks @BillChirico. - -### Fixes - -- Cron: prevent one-shot `at` jobs from re-firing on gateway restart when previously skipped or errored. (#13845) -- Discord: add exec approval cleanup option to delete DMs after approval/denial/timeout. (#13205) Thanks @thewilloftheshadow. -- Sessions: prune stale entries, cap session store size, rotate large stores, accept duration/size thresholds, default to warn-only maintenance, and prune cron run sessions after retention windows. (#13083) Thanks @skyfallsin, @Glucksberg, @gumadeiras. -- CI: Implement pipeline and workflow order. Thanks @quotentiroler. -- WhatsApp: preserve original filenames for inbound documents. (#12691) Thanks @akramcodez. -- Telegram: harden quote parsing; preserve quote context; avoid QUOTE_TEXT_INVALID; avoid nested reply quote misclassification. (#12156) Thanks @rybnikov. -- Security/Telegram: breaking default-behavior change — standalone canvas host + Telegram webhook listeners now bind loopback (`127.0.0.1`) instead of `0.0.0.0`; set `channels.telegram.webhookHost` when external ingress is required. (#13184) Thanks @davidrudduck. -- Telegram: recover proactive sends when stale topic thread IDs are used by retrying without `message_thread_id`. (#11620) -- Discord: auto-create forum/media thread posts on send, with chunked follow-up replies and media handling for forum sends. (#12380) Thanks @magendary, @thewilloftheshadow. -- Discord: cap gateway reconnect attempts to avoid infinite retry loops. (#12230) Thanks @Yida-Dev. -- Telegram: render markdown spoilers with `` HTML tags. (#11543) Thanks @ezhikkk. -- Telegram: truncate command registration to 100 entries to avoid `BOT_COMMANDS_TOO_MUCH` failures on startup. (#12356) Thanks @arosstale. -- Telegram: match DM `allowFrom` against sender user id (fallback to chat id) and clarify pairing logs. (#12779) Thanks @liuxiaopai-ai. -- Pairing/Telegram: include the actual pairing code in approve commands, route Telegram pairing replies through the shared pairing message builder, and add regression checks to prevent `` placeholder drift. -- Onboarding: QuickStart now auto-installs shell completion (prompt only in Manual). -- Onboarding/Providers: add LiteLLM provider onboarding and preserve custom LiteLLM proxy base URLs while enforcing API-key auth mode. (#12823) Thanks @ryan-crabbe. -- Docker: make `docker-setup.sh` compatible with macOS Bash 3.2 and empty extra mounts. (#9441) Thanks @mateusz-michalik. -- Auth: strip embedded line breaks from pasted API keys and tokens before storing/resolving credentials. -- Agents: strip reasoning tags and downgraded tool markers from messaging tool and streaming output to prevent leakage. (#11053, #13453) Thanks @liebertar, @meaadore1221-afk, @gumadeiras. -- Browser: prevent stuck `act:evaluate` from wedging the browser tool, and make cancellation stop waiting promptly. (#13498) Thanks @onutc. -- Security/Gateway: default-deny missing connect `scopes` (no implicit `operator.admin`). -- Web UI: make chat refresh smoothly scroll to the latest messages and suppress new-messages badge flash during manual refresh. -- Web UI: coerce Form Editor values to schema types before `config.set` and `config.apply`, preventing numeric and boolean fields from being serialized as strings. (#13468) Thanks @mcaxtr. -- Tools/web_search: include provider-specific settings in the web search cache key, and pass `inlineCitations` for Grok. (#12419) Thanks @tmchow. -- Tools/web_search: fix Grok response parsing for xAI Responses API output blocks. (#13049) Thanks @ereid7. -- Tools/web_search: normalize direct Perplexity model IDs while keeping OpenRouter model IDs unchanged. (#12795) Thanks @cdorsey. -- Model failover: treat HTTP 400 errors as failover-eligible, enabling automatic model fallback. (#1879) Thanks @orenyomtov. -- Errors: prevent false positive context overflow detection when conversation mentions "context overflow" topic. (#2078) Thanks @sbking. -- Errors: avoid rewriting/swallowing normal assistant replies that mention error keywords by scoping `sanitizeUserFacingText` rewrites to error-context. (#12988) Thanks @Takhoffman. -- Config: re-hydrate state-dir `.env` during runtime config loads so `${VAR}` substitutions remain resolvable. (#12748) Thanks @rodrigouroz. -- Gateway: no more post-compaction amnesia; injected transcript writes now preserve Pi session `parentId` chain so agents can remember again. (#12283) Thanks @Takhoffman. -- Gateway: fix multi-agent sessions.usage discovery. (#11523) Thanks @Takhoffman. -- Agents: recover from context overflow caused by oversized tool results (pre-emptive capping + fallback truncation). (#11579) Thanks @tyler6204. -- Subagents/compaction: stabilize announce timing and preserve compaction metrics across retries. (#11664) Thanks @tyler6204. -- Subagents: report timeout-aborted runs as timed out instead of completed successfully in parent-session announcements. (#13996) Thanks @dario-github. -- Cron: share isolated announce flow and harden scheduling/delivery reliability. (#11641) Thanks @tyler6204. -- Cron tool: recover flat params when LLM omits the `job` wrapper for add requests. (#12124) Thanks @tyler6204. -- Gateway/CLI: when `gateway.bind=lan`, use a LAN IP for probe URLs and Control UI links. (#11448) Thanks @AnonO6. -- CLI: make `openclaw plugins list` output scannable by hoisting source roots and shortening bundled/global/workspace plugin paths. -- Hooks: fix bundled hooks broken since 2026.2.2 (tsdown migration). (#9295) Thanks @patrickshao. -- Security/Plugins: install plugin and hook dependencies with `--ignore-scripts` to prevent lifecycle script execution. -- Routing: refresh bindings per message by loading config at route resolution so binding changes apply without restart. (#11372) Thanks @juanpablodlc. -- Exec approvals: render forwarded commands in monospace for safer approval scanning. (#11937) Thanks @sebslight. -- Config: clamp `maxTokens` to `contextWindow` to prevent invalid model configs. (#5516) Thanks @lailoo. -- Thinking: allow xhigh for `github-copilot/gpt-5.2-codex` and `github-copilot/gpt-5.2`. (#11646) Thanks @LatencyTDH. -- Thinking: honor `/think off` for reasoning-capable models. (#9564) Thanks @liuy. -- Discord: support forum/media thread-create starter messages, wire `message thread create --message`, and harden routing. (#10062) Thanks @jarvis89757. -- Discord: download attachments from forwarded messages. (#17049) Thanks @pip-nomel, @thewilloftheshadow. -- Paths: structurally resolve `OPENCLAW_HOME`-derived home paths and fix Windows drive-letter handling in tool meta shortening. (#12125) Thanks @mcaxtr. -- Memory: set Voyage embeddings `input_type` for improved retrieval. (#10818) Thanks @mcinteerj. -- Memory: disable async batch embeddings by default for memory indexing (opt-in via `agents.defaults.memorySearch.remote.batch.enabled`). (#13069) Thanks @mcinteerj. -- Memory/QMD: reuse default model cache across agents instead of re-downloading per agent. (#12114) Thanks @tyler6204. -- Memory/QMD: run boot refresh in background by default, add configurable QMD maintenance timeouts, retry QMD after fallback failures, and scope QMD queries to OpenClaw-managed collections. (#9690, #9705, #10042) Thanks @vignesh07. -- Memory/QMD: initialize QMD backend on gateway startup so background update timers restart after process reloads. (#10797) Thanks @vignesh07. -- Config/Memory: auto-migrate legacy top-level `memorySearch` settings into `agents.defaults.memorySearch`. (#11278, #9143) Thanks @vignesh07. -- Memory/QMD: treat plain-text `No results found` output from QMD as an empty result instead of throwing invalid JSON errors. (#9824) -- Memory/QMD: add `memory.qmd.searchMode` to choose `query`, `search`, or `vsearch` recall mode. (#9967, #10084) -- Media understanding: recognize `.caf` audio attachments for transcription. (#10982) Thanks @succ985. -- State dir: honor `OPENCLAW_STATE_DIR` for default device identity and canvas storage paths. (#4824) Thanks @kossoy. -- Doctor/State dir: suppress repeated legacy migration warnings only for valid symlink mirrors, while keeping warnings for empty or invalid legacy trees. (#11709) Thanks @gumadeiras. -- Tests: harden flaky hotspots by removing timer sleeps, consolidating onboarding provider-auth coverage, and improving memory test realism. (#11598) Thanks @gumadeiras. -- macOS: honor Nix-managed defaults suite (`ai.openclaw.mac`) for nixMode to prevent onboarding from reappearing after bundle-id churn. (#12205) Thanks @joshp123. -- Matrix: add multi-account support via `channels.matrix.accounts`; use per-account config for dm policy, allowFrom, groups, and other settings; serialize account startup to avoid race condition. (#7286, #3165, #3085) Thanks @emonty. - -## 2026.2.6 - -### Changes - -- Cron: default `wakeMode` is now `"now"` for new jobs (was `"next-heartbeat"`). (#10776) Thanks @tyler6204. -- Cron: `cron run` defaults to force execution; use `--due` to restrict to due-only. (#10776) Thanks @tyler6204. -- Models: support Anthropic Opus 4.6 and OpenAI Codex gpt-5.3-codex (forward-compat fallbacks). (#9853, #10720, #9995) Thanks @TinyTb, @calvin-hpnet, @tyler6204. -- Providers: add xAI (Grok) support. (#9885) Thanks @grp06. -- Providers: add Baidu Qianfan support. (#8868) Thanks @ide-rea. -- Web UI: add token usage dashboard. (#10072) Thanks @Takhoffman. -- Web UI: add RTL auto-direction support for Hebrew/Arabic text in chat composer and rendered messages. (#11498) Thanks @dirbalak. -- Memory: native Voyage AI support. (#7078) Thanks @mcinteerj. -- Sessions: cap sessions_history payloads to reduce context overflow. (#10000) Thanks @gut-puncture. -- CLI: sort commands alphabetically in help output. (#8068) Thanks @deepsoumya617. -- CI: optimize pipeline throughput (macOS consolidation, Windows perf, workflow concurrency). (#10784) Thanks @mcaxtr. -- Agents: bump pi-mono to 0.52.7; add embedded forward-compat fallback for Opus 4.6 model ids. - -### Added - -- Cron: run history deep-links to session chat from the dashboard. (#10776) Thanks @tyler6204. -- Cron: per-run session keys in run log entries and default labels for cron sessions. (#10776) Thanks @tyler6204. -- Cron: legacy payload field compatibility (`deliver`, `channel`, `to`, `bestEffortDeliver`) in schema. (#10776) Thanks @tyler6204. - -### Fixes - -- TTS: add missing OpenAI voices (ballad, cedar, juniper, marin, verse) to the allowlist so they are recognized instead of silently falling back to Edge TTS. (#2393) -- Cron: scheduler reliability (timer drift, restart catch-up, lock contention, stale running markers). (#10776) Thanks @tyler6204. -- Cron: store migration hardening (legacy field migration, parse error handling, explicit delivery mode persistence). (#10776) Thanks @tyler6204. -- Memory: set Voyage embeddings `input_type` for improved retrieval. (#10818) Thanks @mcinteerj. -- Memory/QMD: run boot refresh in background by default, add configurable QMD maintenance timeouts, retry QMD after fallback failures, and scope QMD queries to OpenClaw-managed collections. (#9690, #9705, #10042) Thanks @vignesh07. -- Media understanding: recognize `.caf` audio attachments for transcription. (#10982) Thanks @succ985. -- Telegram: auto-inject DM topic threadId in message tool + subagent announce. (#7235) Thanks @Lukavyi. -- Security: require auth for Gateway canvas host and A2UI assets. (#9518) Thanks @coygeek. -- Cron: fix scheduling and reminder delivery regressions; harden next-run recompute + timer re-arming + legacy schedule fields. (#9733, #9823, #9948, #9932) Thanks @tyler6204, @pycckuu, @j2h4u, @fujiwara-tofu-shop. -- Update: harden Control UI asset handling in update flow. (#10146) Thanks @gumadeiras. -- Security: add skill/plugin code safety scanner; redact credentials from config.get gateway responses. (#9806, #9858) Thanks @abdelsfane. -- Exec approvals: coerce bare string allowlist entries to objects. (#9903) Thanks @mcaxtr. -- Slack: add mention stripPatterns for /new and /reset. (#9971) Thanks @ironbyte-rgb. -- Chrome extension: fix bundled path resolution. (#8914) Thanks @kelvinCB. -- Compaction/errors: allow multiple compaction retries on context overflow; show clear billing errors. (#8928, #8391) Thanks @Glucksberg. - -## 2026.2.3 - -### Changes - -- Telegram: remove last `@ts-nocheck` from `bot-handlers.ts`, use Grammy types directly, deduplicate `StickerMetadata`. Zero `@ts-nocheck` remaining in `src/telegram/`. (#9206) -- Telegram: remove `@ts-nocheck` from `bot-message.ts`, type deps via `Omit`, widen `allMedia` to `TelegramMediaRef[]`. (#9180) -- Telegram: remove `@ts-nocheck` from `bot.ts`, fix duplicate `bot.catch` error handler (Grammy overrides), remove dead reaction `message_thread_id` routing, harden sticker cache guard. (#9077) -- Onboarding: add Cloudflare AI Gateway provider setup and docs. (#7914) Thanks @roerohan. -- Onboarding: add Moonshot (.cn) auth choice and keep the China base URL when preserving defaults. (#7180) Thanks @waynelwz. -- Docs: clarify tmux send-keys for TUI by splitting text and Enter. (#7737) Thanks @Wangnov. -- Docs: mirror the landing page revamp for zh-CN (features, quickstart, docs directory, network model, credits). (#8994) Thanks @joshp123. -- Messages: add per-channel and per-account responsePrefix overrides across channels. (#9001) Thanks @mudrii. -- Cron: add announce delivery mode for isolated jobs (CLI + Control UI) and delivery mode config. -- Cron: default isolated jobs to announce delivery; accept ISO 8601 `schedule.at` in tool inputs. -- Cron: hard-migrate isolated jobs to announce/none delivery; drop legacy post-to-main/payload delivery fields and `atMs` inputs. -- Cron: delete one-shot jobs after success by default; add `--keep-after-run` for CLI. -- Cron: suppress messaging tools during announce delivery so summaries post consistently. -- Cron: avoid duplicate deliveries when isolated runs send messages directly. - -### Fixes - -- Control UI: add hardened fallback for asset resolution in global npm installs. (#4855) Thanks @anapivirtua. -- Update: remove dead restore control-ui step that failed on gitignored dist/ output. -- Update: avoid wiping prebuilt Control UI assets during dev auto-builds (`tsdown --no-clean`), run update doctor via `openclaw.mjs`, and auto-restore missing UI assets after doctor. (#10146) Thanks @gumadeiras. -- Models: add forward-compat fallback for `openai-codex/gpt-5.3-codex` when model registry hasn't discovered it yet. (#9989) Thanks @w1kke. -- Auto-reply/Docs: normalize `extra-high` (and spaced variants) to `xhigh` for Codex thinking levels, and align Codex 5.3 FAQ examples. (#9976) Thanks @slonce70. -- Compaction: remove orphaned `tool_result` messages during history pruning to prevent session corruption from aborted tool calls. (#9868, fixes #9769, #9724, #9672) -- Telegram: pass `parentPeer` for forum topic binding inheritance so group-level bindings apply to all topics within the group. (#9789, fixes #9545, #9351) -- CLI: pass `--disable-warning=ExperimentalWarning` as a Node CLI option when respawning (avoid disallowed `NODE_OPTIONS` usage; fixes npm pack). (#9691) Thanks @18-RAJAT. -- CLI: resolve bundled Chrome extension assets by walking up to the nearest assets directory; add resolver and clipboard tests. (#8914) Thanks @kelvinCB. -- Tests: stabilize Windows ACL coverage with deterministic os.userInfo mocking. (#9335) Thanks @M00N7682. -- Exec approvals: coerce bare string allowlist entries to objects to prevent allowlist corruption. (#9903, fixes #9790) Thanks @mcaxtr. -- Exec approvals: ensure two-phase approval registration/decision flow works reliably by validating `twoPhase` requests and exposing `waitDecision` as an approvals-scoped gateway method. (#3357, fixes #2402) Thanks @ramin-shirali. -- Heartbeat: allow explicit accountId routing for multi-account channels. (#8702) Thanks @lsh411. -- TUI/Gateway: handle non-streaming finals, refresh history for non-local chat runs, and avoid event gap warnings for targeted tool streams. (#8432) Thanks @gumadeiras. -- Shell completion: auto-detect and migrate slow dynamic patterns to cached files for faster terminal startup; add completion health checks to doctor/update/onboard. -- Telegram: honor session model overrides in inline model selection. (#8193) Thanks @gildo. -- Web UI: fix agent model selection saves for default/non-default agents and wrap long workspace paths. Thanks @Takhoffman. -- Web UI: resolve header logo path when `gateway.controlUi.basePath` is set. (#7178) Thanks @Yeom-JinHo. -- Web UI: apply button styling to the new-messages indicator. -- Onboarding: infer auth choice from non-interactive API key flags. (#8484) Thanks @f-trycua. -- Security: keep untrusted channel metadata out of system prompts (Slack/Discord). Thanks @KonstantinMirin. -- Security: enforce sandboxed media paths for message tool attachments. (#9182) Thanks @victormier. -- Security: require explicit credentials for gateway URL overrides to prevent credential leakage. (#8113) Thanks @victormier. -- Security: gate `whatsapp_login` tool to owner senders and default-deny non-owner contexts. (#8768) Thanks @victormier. -- Voice call: harden webhook verification with host allowlists/proxy trust and keep ngrok loopback bypass. -- Voice call: add regression coverage for anonymous inbound caller IDs with allowlist policy. (#8104) Thanks @victormier. -- Cron: accept epoch timestamps and 0ms durations in CLI `--at` parsing. -- Cron: reload store data when the store file is recreated or mtime changes. -- Cron: deliver announce runs directly, honor delivery mode, and respect wakeMode for summaries. (#8540) Thanks @tyler6204. -- Telegram: include forward_from_chat metadata in forwarded messages and harden cron delivery target checks. (#8392) Thanks @Glucksberg. -- macOS: fix cron payload summary rendering and ISO 8601 formatter concurrency safety. -- Discord: enforce DM allowlists for agent components (buttons/select menus), honoring pairing store approvals and tag matches. (#11254) Thanks @thedudeabidesai. - -## 2026.2.2-3 - -### Fixes - -- Update: ship legacy daemon-cli shim for pre-tsdown update imports (fixes daemon restart after npm update). - -## 2026.2.2-2 - -### Changes - -- Docs: promote BlueBubbles as the recommended iMessage integration; mark imsg channel as legacy. (#8415) Thanks @tyler6204. - -### Fixes - -- CLI status: resolve build-info from bundled dist output (fixes "unknown" commit in npm builds). - -## 2026.2.2-1 - -### Fixes - -- CLI status: fall back to build-info for version detection (fixes "unknown" in beta builds). Thanks @gumadeira. - -## 2026.2.2 - -### Changes - -- Feishu: add Feishu/Lark plugin support + docs. (#7313) Thanks @jiulingyun (openclaw-cn). -- Web UI: add Agents dashboard for managing agent files, tools, skills, models, channels, and cron jobs. -- Subagents: discourage direct messaging tool use unless a specific external recipient is requested. -- Memory: implement the opt-in QMD backend for workspace memory. (#3160) Thanks @vignesh07. -- Security: add healthcheck skill and bootstrap audit guidance. (#7641) Thanks @Takhoffman. -- Config: allow setting a default subagent thinking level via `agents.defaults.subagents.thinking` (and per-agent `agents.list[].subagents.thinking`). (#7372) Thanks @tyler6204. -- Docs: zh-CN translations seed + polish, pipeline guidance, nav/landing updates, and typo fixes. (#8202, #6995, #6619, #7242, #7303, #7415) Thanks @AaronWander, @taiyi747, @Explorer1092, @rendaoyuan, @joshp123, @lailoo. -- Docs: add zh-CN i18n guardrails to avoid editing generated translations. (#8416) Thanks @joshp123. - -### Fixes - -- Docs: finish renaming the QMD memory docs to reference the OpenClaw state dir. -- Onboarding: keep TUI flow exclusive (skip completion prompt + background Web UI seed). -- Onboarding: drop completion prompt now handled by install/update. -- TUI: block onboarding output while TUI is active and restore terminal state on exit. -- CLI: cache shell completion scripts in state dir and source cached files in profiles. -- Zsh completion: escape option descriptions to avoid invalid option errors. -- Agents: repair malformed tool calls and session transcripts. (#7473) Thanks @justinhuangcode. -- fix(agents): validate AbortSignal instances before calling AbortSignal.any() (#7277) (thanks @Elarwei001) -- fix(webchat): respect user scroll position during streaming and refresh (#7226) (thanks @marcomarandiz) -- Telegram: recover from grammY long-poll timed out errors. (#7466) Thanks @macmimi23. -- Media understanding: skip binary media from file text extraction. (#7475) Thanks @AlexZhangji. -- Security: enforce access-group gating for Slack slash commands when channel type lookup fails. -- Security: require validated shared-secret auth before skipping device identity on gateway connect. Thanks @simecek. -- Security: guard skill installer downloads with SSRF checks (block private/localhost URLs). -- Security/Gateway: require `operator.approvals` for in-chat `/approve` when invoked from gateway clients. Thanks @yueyueL. -- Security: harden Windows exec allowlist; block cmd.exe bypass via single &. Thanks @simecek. -- Discord: route autoThread replies to existing threads instead of the root channel. (#8302) Thanks @gavinbmoore, @thewilloftheshadow. -- Media understanding: apply SSRF guardrails to provider fetches; allow private baseUrl overrides explicitly. -- fix(voice-call): harden inbound allowlist; reject anonymous callers; require Telnyx publicKey for allowlist; token-gate Twilio media streams; cap webhook body size (thanks @simecek) -- Onboarding: keep TUI flow exclusive (skip completion prompt + background Web UI seed); completion prompt now handled by install/update. -- CLI/Zsh completion: cache scripts in state dir and escape option descriptions to avoid invalid option errors. -- fix(ui): resolve Control UI asset path correctly. -- fix(ui): refresh agent files after external edits. -- Tests: stub SSRF DNS pinning in web auto-reply + Gemini video coverage. (#6619) Thanks @joshp123. - -## 2026.2.1 - -### Changes - -- Docs: onboarding/install/i18n/exec-approvals/Control UI/exe.dev/cacheRetention updates + misc nav/typos. (#3050, #3461, #4064, #4675, #4729, #4763, #5003, #5402, #5446, #5474, #5663, #5689, #5694, #5967, #6270, #6300, #6311, #6416, #6487, #6550, #6789) -- Telegram: use shared pairing store. (#6127) Thanks @obviyus. -- Agents: add OpenRouter app attribution headers. Thanks @alexanderatallah. -- Agents: add system prompt safety guardrails. (#5445) Thanks @joshp123. -- Agents: update pi-ai to 0.50.9 and rename cacheControlTtl -> cacheRetention (with back-compat mapping). -- Agents: extend CreateAgentSessionOptions with systemPrompt/skills/contextFiles. -- Agents: add tool policy conformance snapshot (no runtime behavior change). (#6011) -- Auth: update MiniMax OAuth hint + portal auth note copy. -- Discord: inherit thread parent bindings for routing. (#3892) Thanks @aerolalit. -- Gateway: inject timestamps into agent and chat.send messages. (#3705) Thanks @conroywhitney, @CashWilliams. -- Gateway: require TLS 1.3 minimum for TLS listeners. (#5970) Thanks @loganaden. -- Web UI: refine chat layout + extend session active duration. -- CI: add formal conformance + alias consistency checks. (#5723, #5807) - -### Fixes - -- Security: guard remote media fetches with SSRF protections (block private/localhost, DNS pinning). -- Updates: clean stale global install rename dirs and extend gateway update timeouts to avoid npm ENOTEMPTY failures. -- Security/Plugins/Hooks: validate install paths and reject traversal-like names (prevents path traversal outside the state dir). Thanks @logicx24. -- Telegram: add download timeouts for file fetches. (#6914) Thanks @hclsys. -- Telegram: enforce thread specs for DM vs forum sends. (#6833) Thanks @obviyus. -- Streaming: flush block streaming on paragraph boundaries for newline chunking. (#7014) -- Streaming: stabilize partial streaming filters. -- Auto-reply: avoid referencing workspace files in /new greeting prompt. (#5706) Thanks @bravostation. -- Tools: align tool execute adapters/signatures (legacy + parameter order + arg normalization). -- Tools: treat "\*" tool allowlist entries as valid to avoid spurious unknown-entry warnings. -- Skills: update session-logs paths from .clawdbot to .openclaw. (#4502) -- Slack: harden media fetch limits and Slack file URL validation. (#6639) Thanks @davidiach. -- Lint: satisfy curly rule after import sorting. (#6310) -- Process: resolve Windows `spawn()` failures for npm-family CLIs by appending `.cmd` when needed. (#5815) Thanks @thejhinvirtuoso. -- Discord: resolve PluralKit proxied senders for allowlists and labels. (#5838) Thanks @thewilloftheshadow. -- Tlon: add timeout to SSE client fetch calls (CWE-400). (#5926) -- Memory search: L2-normalize local embedding vectors to fix semantic search. (#5332) -- Agents: align embedded runner + typings with pi-coding-agent API updates (pi 0.51.0). -- Agents: ensure OpenRouter attribution headers apply in the embedded runner. -- Agents: cap context window resolution for compaction safeguard. (#6187) Thanks @iamEvanYT. -- System prompt: resolve overrides and hint using session_status for current date/time. (#1897, #1928, #2108, #3677) -- Agents: fix Pi prompt template argument syntax. (#6543) -- Subagents: fix announce failover race (always emit lifecycle end; timeout=0 means no-timeout). (#6621) -- Teams: gate media auth retries. -- Telegram: restore draft streaming partials. (#5543) Thanks @obviyus. -- Onboarding: friendlier Windows onboarding message. (#6242) Thanks @shanselman. -- TUI: prevent crash when searching with digits in the model selector. -- Agents: wire before_tool_call plugin hook into tool execution. (#6570, #6660) Thanks @ryancnelson. -- Browser: secure Chrome extension relay CDP sessions. -- Docker: use container port for gateway command instead of host port. (#5110) Thanks @mise42. -- Docker: start gateway CMD by default for container deployments. (#6635) Thanks @kaizen403. -- fix(lobster): block arbitrary exec via lobsterPath/cwd injection (GHSA-4mhr-g7xj-cg8j). (#5335) Thanks @vignesh07. -- Security: sanitize WhatsApp accountId to prevent path traversal. (#4610) -- Security: restrict MEDIA path extraction to prevent LFI. (#4930) -- Security: validate message-tool filePath/path against sandbox root. (#6398) -- Security: block LD*/DYLD* env overrides for host exec. (#4896) Thanks @HassanFleyah. -- Security: harden web tool content wrapping + file parsing safeguards. (#4058) Thanks @VACInc. -- Security: enforce Twitch `allowFrom` allowlist gating (deny non-allowlisted senders). Thanks @MegaManSec. - -## 2026.1.31 - -### Changes - -- Docs: onboarding/install/i18n/exec-approvals/Control UI/exe.dev/cacheRetention updates + misc nav/typos. (#3050, #3461, #4064, #4675, #4729, #4763, #5003, #5402, #5446, #5474, #5663, #5689, #5694, #5967, #6270, #6300, #6311, #6416, #6487, #6550, #6789) -- Telegram: use shared pairing store. (#6127) Thanks @obviyus. -- Agents: add OpenRouter app attribution headers. Thanks @alexanderatallah. -- Agents: add system prompt safety guardrails. (#5445) Thanks @joshp123. -- Agents: update pi-ai to 0.50.9 and rename cacheControlTtl -> cacheRetention (with back-compat mapping). -- Agents: extend CreateAgentSessionOptions with systemPrompt/skills/contextFiles. -- Agents: add tool policy conformance snapshot (no runtime behavior change). (#6011) -- Auth: update MiniMax OAuth hint + portal auth note copy. -- Discord: inherit thread parent bindings for routing. (#3892) Thanks @aerolalit. -- Gateway: inject timestamps into agent and chat.send messages. (#3705) Thanks @conroywhitney, @CashWilliams. -- Gateway: require TLS 1.3 minimum for TLS listeners. (#5970) Thanks @loganaden. -- Web UI: refine chat layout + extend session active duration. -- CI: add formal conformance + alias consistency checks. (#5723, #5807) - -### Fixes - -- Security: guard remote media fetches with SSRF protections (block private/localhost, DNS pinning). -- Updates: clean stale global install rename dirs and extend gateway update timeouts to avoid npm ENOTEMPTY failures. -- Plugins: validate plugin/hook install paths and reject traversal-like names. -- Telegram: add download timeouts for file fetches. (#6914) Thanks @hclsys. -- Telegram: enforce thread specs for DM vs forum sends. (#6833) Thanks @obviyus. -- Streaming: flush block streaming on paragraph boundaries for newline chunking. (#7014) -- Streaming: stabilize partial streaming filters. -- Auto-reply: avoid referencing workspace files in /new greeting prompt. (#5706) Thanks @bravostation. -- Tools: align tool execute adapters/signatures (legacy + parameter order + arg normalization). -- Tools: treat `"*"` tool allowlist entries as valid to avoid spurious unknown-entry warnings. -- Skills: update session-logs paths from .clawdbot to .openclaw. (#4502) -- Slack: harden media fetch limits and Slack file URL validation. (#6639) Thanks @davidiach. -- Lint: satisfy curly rule after import sorting. (#6310) -- Process: resolve Windows `spawn()` failures for npm-family CLIs by appending `.cmd` when needed. (#5815) Thanks @thejhinvirtuoso. -- Discord: resolve PluralKit proxied senders for allowlists and labels. (#5838) Thanks @thewilloftheshadow. -- Tlon: add timeout to SSE client fetch calls (CWE-400). (#5926) -- Memory search: L2-normalize local embedding vectors to fix semantic search. (#5332) -- Agents: align embedded runner + typings with pi-coding-agent API updates (pi 0.51.0). -- Agents: ensure OpenRouter attribution headers apply in the embedded runner. -- Agents: cap context window resolution for compaction safeguard. (#6187) Thanks @iamEvanYT. -- System prompt: resolve overrides and hint using session_status for current date/time. (#1897, #1928, #2108, #3677) -- Agents: fix Pi prompt template argument syntax. (#6543) -- Subagents: fix announce failover race (always emit lifecycle end; timeout=0 means no-timeout). (#6621) -- Teams: gate media auth retries. -- Telegram: restore draft streaming partials. (#5543) Thanks @obviyus. -- Onboarding: friendlier Windows onboarding message. (#6242) Thanks @shanselman. -- TUI: prevent crash when searching with digits in the model selector. -- Agents: wire before_tool_call plugin hook into tool execution. (#6570, #6660) Thanks @ryancnelson. -- Browser: secure Chrome extension relay CDP sessions. -- Docker: use container port for gateway command instead of host port. (#5110) Thanks @mise42. -- Docker: start gateway CMD by default for container deployments. (#6635) Thanks @kaizen403. -- fix(lobster): block arbitrary exec via lobsterPath/cwd injection (GHSA-4mhr-g7xj-cg8j). (#5335) Thanks @vignesh07. -- Security: sanitize WhatsApp accountId to prevent path traversal. (#4610) -- Security: restrict MEDIA path extraction to prevent LFI. (#4930) -- Security: validate message-tool filePath/path against sandbox root. (#6398) -- Security: block LD*/DYLD* env overrides for host exec. (#4896) Thanks @HassanFleyah. -- Security: harden web tool content wrapping + file parsing safeguards. (#4058) Thanks @VACInc. -- Security: enforce Twitch `allowFrom` allowlist gating (deny non-allowlisted senders). Thanks @MegaManSec. - -## 2026.1.30 - -### Changes - -- CLI: add `completion` command (Zsh/Bash/PowerShell/Fish) and auto-setup during postinstall/onboarding. -- CLI: add per-agent `models status` (`--agent` filter). (#4780) Thanks @jlowin. -- Agents: add Kimi K2.5 to the synthetic model catalog. (#4407) Thanks @manikv12. -- Auth: switch Kimi Coding to built-in provider; normalize OAuth profile email. -- Auth: add MiniMax OAuth plugin + onboarding option. (#4521) Thanks @Maosghoul. -- Agents: update pi SDK/API usage and dependencies. -- Web UI: refresh sessions after chat commands and improve session display names. -- Build: move TypeScript builds to `tsdown` + `tsgo` (faster builds, CI typechecks), update tsconfig target, and clean up lint rules. -- Build: align npm tar override and bin metadata so the `openclaw` CLI entrypoint is preserved in npm publishes. -- Docs: add pi/pi-dev docs and update OpenClaw branding + install links. -- Docker E2E: stabilize gateway readiness, plugin installs/manifests, and cleanup/doctor switch entrypoint checks. - -### Fixes - -- Security: restrict local path extraction in media parser to prevent LFI. (#4880) -- Gateway: prevent token defaults from becoming the literal "undefined". (#4873) Thanks @Hisleren. -- Control UI: fix assets resolution for npm global installs. (#4909) Thanks @YuriNachos. -- macOS: avoid stderr pipe backpressure in gateway discovery. (#3304) Thanks @abhijeet117. -- Telegram: normalize account token lookup for non-normalized IDs. (#5055) Thanks @jasonsschin. -- Telegram: preserve delivery thread fallback and fix threadId handling in delivery context. -- Telegram: fix HTML nesting for overlapping styles/links. (#4578) Thanks @ThanhNguyxn. -- Telegram: accept numeric messageId/chatId in react actions. (#4533) Thanks @Ayush10. -- Telegram: honor per-account proxy dispatcher via undici fetch. (#4456) Thanks @spiceoogway. -- Telegram: scope skill commands to bound agent per bot. (#4360) Thanks @robhparker. -- BlueBubbles: debounce by messageId to preserve attachments in text+image messages. (#4984) -- Routing: prefer requesterOrigin over stale session entries for sub-agent announce delivery. (#4957) -- Extensions: restore embedded extension discovery typings. -- CLI: fix `tui:dev` port resolution. -- LINE: fix status command TypeError. (#4651) -- OAuth: skip expired-token warnings when refresh tokens are still valid. (#4593) -- Build: skip redundant UI install step in Dockerfile. (#4584) Thanks @obviyus. - -## 2026.1.29 - -### Changes - -- Rebrand: rename the npm package/CLI to `openclaw`, add a `openclaw` compatibility shim, and move extensions to the `@openclaw/*` scope. -- Onboarding: strengthen security warning copy for beta + access control expectations. -- Onboarding: add Venice API key to non-interactive flow. (#1893) Thanks @jonisjongithub. -- Config: auto-migrate legacy state/config paths and keep config resolution consistent across legacy filenames. -- Gateway: warn on hook tokens via query params; document header auth preference. (#2200) Thanks @YuriNachos. -- Gateway: add dangerous Control UI device auth bypass flag + audit warnings. (#2248) -- Doctor: warn on gateway exposure without auth. (#2016) Thanks @Alex-Alaniz. -- Web UI: keep sub-agent announce replies visible in WebChat. (#1977) Thanks @andrescardonas7. -- Browser: route browser control via gateway/node; remove standalone browser control command and control URL config. -- Browser: route `browser.request` via node proxies when available; honor proxy timeouts; derive browser ports from `gateway.port`. -- Browser: fall back to URL matching for extension relay target resolution. (#1999) Thanks @jonit-dev. -- Telegram: allow caption param for media sends. (#1888) Thanks @mguellsegarra. -- Telegram: support plugin sendPayload channelData (media/buttons) and validate plugin commands. (#1917) Thanks @JoshuaLelon. -- Telegram: avoid block replies when streaming is disabled. (#1885) Thanks @ivancasco. -- Telegram: add optional silent send flag (disable notifications). (#2382) Thanks @Suksham-sharma. -- Telegram: support editing sent messages via message(action="edit"). (#2394) Thanks @marcelomar21. -- Telegram: support quote replies for message tool and inbound context. (#2900) Thanks @aduk059. -- Telegram: add sticker receive/send with vision caching. (#2629) Thanks @longjos. -- Telegram: send sticker pixels to vision models. (#2650) -- Telegram: keep topic IDs in restart sentinel notifications. (#1807) Thanks @hsrvc. -- Discord: add configurable privileged gateway intents for presences/members. (#2266) Thanks @kentaro. -- Slack: clear ack reaction after streamed replies. (#2044) Thanks @fancyboi999. -- Matrix: switch plugin SDK to @vector-im/matrix-bot-sdk. -- Tlon: format thread reply IDs as @ud. (#1837) Thanks @wca4a. -- Tools: add per-sender group tool policies and fix precedence. (#1757) Thanks @adam91holt. -- Agents: summarize dropped messages during compaction safeguard pruning. (#2509) Thanks @jogi47. -- Agents: expand cron tool description with full schema docs. (#1988) Thanks @tomascupr. -- Agents: honor tools.exec.safeBins in exec allowlist checks. (#2281) -- Memory Search: allow extra paths for memory indexing (ignores symlinks). (#3600) Thanks @kira-ariaki. -- Skills: add multi-image input support to Nano Banana Pro skill. (#1958) Thanks @tyler6204. -- Skills: add missing dependency metadata for GitHub, Notion, Slack, Discord. (#1995) Thanks @jackheuberger. -- Commands: group /help and /commands output with Telegram paging. (#2504) Thanks @hougangdev. -- Routing: add per-account DM session scope and document multi-account isolation. (#3095) Thanks @jarvis-sam. -- Routing: precompile session key regexes. (#1697) Thanks @Ray0907. -- CLI: use Node's module compile cache for faster startup. (#2808) Thanks @pi0. -- Auth: show copyable Google auth URL after ASCII prompt. (#1787) Thanks @robbyczgw-cla. -- TUI: avoid width overflow when rendering selection lists. (#1686) Thanks @mossein. -- macOS: finish OpenClaw app rename for macOS sources, bundle identifiers, and shared kit paths. (#2844) Thanks @fal3. -- Branding: update launchd labels, mobile bundle IDs, and logging subsystems to bot.molt (legacy bundle ID migrations). Thanks @thewilloftheshadow. -- macOS: limit project-local `node_modules/.bin` PATH preference to debug builds (reduce PATH hijacking risk). -- macOS: keep custom SSH usernames in remote target. (#2046) Thanks @algal. -- macOS: avoid crash when rendering code blocks by bumping Textual to 0.3.1. (#2033) Thanks @garricn. -- Update: ignore dist/control-ui for dirty checks and restore after ui builds. (#1976) Thanks @Glucksberg. -- Build: bundle A2UI assets during build and stop tracking generated bundles. (#2455) Thanks @0oAstro. -- CI: increase Node heap size for macOS checks. (#1890) Thanks @realZachi. -- Config: apply config.env before ${VAR} substitution. (#1813) Thanks @spanishflu-est1918. -- Gateway: prefer newest session metadata when combining stores. (#1823) Thanks @emanuelst. -- Docs: tighten Fly private deployment steps. (#2289) Thanks @dguido. -- Docs: add migration guide for moving to a new machine. (#2381) -- Docs: add Northflank one-click deployment guide. (#2167) Thanks @AdeboyeDN. -- Docs: add Vercel AI Gateway to providers sidebar. (#1901) Thanks @jerilynzheng. -- Docs: add Render deployment guide. (#1975) Thanks @anurag. -- Docs: add Claude Max API Proxy guide. (#1875) Thanks @atalovesyou. -- Docs: add DigitalOcean deployment guide. (#1870) Thanks @0xJonHoldsCrypto. -- Docs: add Oracle Cloud (OCI) platform guide + cross-links. (#2333) Thanks @hirefrank. -- Docs: add Raspberry Pi install guide. (#1871) Thanks @0xJonHoldsCrypto. -- Docs: add GCP Compute Engine deployment guide. (#1848) Thanks @hougangdev. -- Docs: add LINE channel guide. Thanks @thewilloftheshadow. -- Docs: credit both contributors for Control UI refresh. (#1852) Thanks @EnzeD. -- Docs: keep docs header sticky so navbar stays visible while scrolling. (#2445) Thanks @chenyuan99. -- Docs: update exe.dev install instructions. (#https://github.com/openclaw/openclaw/pull/3047) Thanks @zackerthescar. - -### Breaking - -- **BREAKING:** Gateway auth mode "none" is removed; gateway now requires token/password (Tailscale Serve identity still allowed). - -### Fixes - -- Skills: update session-logs paths to use ~/.openclaw. (#4502) Thanks @bonald. -- Telegram: avoid silent empty replies by tracking normalization skips before fallback. (#3796) -- Mentions: honor mentionPatterns even when explicit mentions are present. (#3303) Thanks @HirokiKobayashi-R. -- Discord: restore username directory lookup in target resolution. (#3131) Thanks @bonald. -- Agents: align MiniMax base URL test expectation with default provider config. (#3131) Thanks @bonald. -- Agents: prevent retries on oversized image errors and surface size limits. (#2871) Thanks @Suksham-sharma. -- Agents: inherit provider baseUrl/api for inline models. (#2740) Thanks @lploc94. -- Memory Search: keep auto provider model defaults and only include remote when configured. (#2576) Thanks @papago2355. -- Telegram: include AccountId in native command context for multi-agent routing. (#2942) Thanks @Chloe-VP. -- Telegram: handle video note attachments in media extraction. (#2905) Thanks @mylukin. -- TTS: read OPENAI_TTS_BASE_URL at runtime instead of module load to honor config.env. (#3341) Thanks @hclsys. -- macOS: auto-scroll to bottom when sending a new message while scrolled up. (#2471) Thanks @kennyklee. -- Web UI: auto-expand the chat compose textarea while typing (with sensible max height). (#2950) Thanks @shivamraut101. -- Gateway: prevent crashes on transient network errors (fetch failures, timeouts, DNS). Added fatal error detection to only exit on truly critical errors. Fixes #2895, #2879, #2873. (#2980) Thanks @elliotsecops. -- Agents: guard channel tool listActions to avoid plugin crashes. (#2859) Thanks @mbelinky. -- Discord: stop resolveDiscordTarget from passing directory params into messaging target parsers. Fixes #3167. Thanks @thewilloftheshadow. -- Discord: avoid resolving bare channel names to user DMs when a username matches. Thanks @thewilloftheshadow. -- Discord: fix directory config type import for target resolution. Thanks @thewilloftheshadow. -- Providers: update MiniMax API endpoint and compatibility mode. (#3064) Thanks @hlbbbbbbb. -- Telegram: treat more network errors as recoverable in polling. (#3013) Thanks @ryancontent. -- Discord: resolve usernames to user IDs for outbound messages. (#2649) Thanks @nonggialiang. -- Providers: update Moonshot Kimi model references to kimi-k2.5. (#2762) Thanks @MarvinCui. -- Gateway: suppress AbortError and transient network errors in unhandled rejections. (#2451) Thanks @Glucksberg. -- TTS: keep /tts status replies on text-only commands and avoid duplicate block-stream audio. (#2451) Thanks @Glucksberg. -- Security: pin npm overrides to keep tar@7.5.4 for install toolchains. -- Security: properly test Windows ACL audit for config includes. (#2403) Thanks @dominicnunez. -- CLI: recognize versioned Node executables when parsing argv. (#2490) Thanks @David-Marsh-Photo. -- CLI: avoid prompting for gateway runtime under the spinner. (#2874) -- BlueBubbles: coalesce inbound URL link preview messages. (#1981) Thanks @tyler6204. -- Cron: allow payloads containing "heartbeat" in event filter. (#2219) Thanks @dwfinkelstein. -- CLI: avoid loading config for global help/version while registering plugin commands. (#2212) Thanks @dial481. -- Agents: include memory.md when bootstrapping memory context. (#2318) Thanks @czekaj. -- Agents: release session locks on process termination and cover more signals. (#2483) Thanks @janeexai. -- Agents: skip cooldowned providers during model failover. (#2143) Thanks @YiWang24. -- Telegram: harden polling + retry behavior for transient network errors and Node 22 transport issues. (#2420) Thanks @techboss. -- Telegram: ignore non-forum group message_thread_id while preserving DM thread sessions. (#2731) Thanks @dylanneve1. -- Telegram: wrap reasoning italics per line to avoid raw underscores. (#2181) Thanks @YuriNachos. -- Telegram: centralize API error logging for delivery and bot calls. (#2492) Thanks @altryne. -- Voice Call: enforce Twilio webhook signature verification for ngrok URLs; disable ngrok free tier bypass by default. -- Security: harden Tailscale Serve auth by validating identity via local tailscaled before trusting headers. -- Media: fix text attachment MIME misclassification with CSV/TSV inference and UTF-16 detection; add XML attribute escaping for file output. (#3628) Thanks @frankekn. -- Build: align memory-core peer dependency with lockfile. -- Security: add mDNS discovery mode with minimal default to reduce information disclosure. (#1882) Thanks @orlyjamie. -- Security: harden URL fetches with DNS pinning to reduce rebinding risk. Thanks Chris Zheng. -- Web UI: improve WebChat image paste previews and allow image-only sends. (#1925) Thanks @smartprogrammer93. -- Security: wrap external hook content by default with a per-hook opt-out. (#1827) Thanks @mertcicekci0. -- Gateway: default auth now fail-closed (token/password required; Tailscale Serve identity remains allowed). -- Gateway: treat loopback + non-local Host connections as remote unless trusted proxy headers are present. -- Onboarding: remove unsupported gateway auth "off" choice from onboarding/configure flows and CLI flags. - -## 2026.1.24-3 - -### Fixes - -- Slack: fix image downloads failing due to missing Authorization header on cross-origin redirects. (#1936) Thanks @sanderhelgesen. -- Gateway: harden reverse proxy handling for local-client detection and unauthenticated proxied connects. (#1795) Thanks @orlyjamie. -- Security audit: flag loopback Control UI with auth disabled as critical. (#1795) Thanks @orlyjamie. -- CLI: resume claude-cli sessions and stream CLI replies to TUI clients. (#1921) Thanks @rmorse. - -## 2026.1.24-2 - -### Fixes - -- Packaging: include dist/link-understanding output in npm tarball (fixes missing apply.js import on install). - -## 2026.1.24-1 - -### Fixes - -- Packaging: include dist/shared output in npm tarball (fixes missing reasoning-tags import on install). - -## 2026.1.24 - -### Highlights - -- Providers: Ollama discovery + docs; Venice guide upgrades + cross-links. (#1606) Thanks @abhaymundhara. https://docs.openclaw.ai/providers/ollama https://docs.openclaw.ai/providers/venice -- Channels: LINE plugin (Messaging API) with rich replies + quick replies. (#1630) Thanks @plum-dawg. -- TTS: Edge fallback (keyless) + `/tts` auto modes. (#1668, #1667) Thanks @steipete, @sebslight. https://docs.openclaw.ai/tts -- Exec approvals: approve in-chat via `/approve` across all channels (including plugins). (#1621) Thanks @czekaj. https://docs.openclaw.ai/tools/exec-approvals https://docs.openclaw.ai/tools/slash-commands -- Telegram: DM topics as separate sessions + outbound link preview toggle. (#1597, #1700) Thanks @rohannagpal, @zerone0x. https://docs.openclaw.ai/channels/telegram - -### Changes - -- Channels: add LINE plugin (Messaging API) with rich replies, quick replies, and plugin HTTP registry. (#1630) Thanks @plum-dawg. -- TTS: add Edge TTS provider fallback, defaulting to keyless Edge with MP3 retry on format failures. (#1668) Thanks @steipete. https://docs.openclaw.ai/tts -- TTS: add auto mode enum (off/always/inbound/tagged) with per-session `/tts` override. (#1667) Thanks @sebslight. https://docs.openclaw.ai/tts -- Telegram: treat DM topics as separate sessions and keep DM history limits stable with thread suffixes. (#1597) Thanks @rohannagpal. -- Telegram: add `channels.telegram.linkPreview` to toggle outbound link previews. (#1700) Thanks @zerone0x. https://docs.openclaw.ai/channels/telegram -- Web search: add Brave freshness filter parameter for time-scoped results. (#1688) Thanks @JonUleis. https://docs.openclaw.ai/tools/web -- UI: refresh Control UI dashboard design system (colors, icons, typography). (#1745, #1786) Thanks @EnzeD, @mousberg. -- Exec approvals: forward approval prompts to chat with `/approve` for all channels (including plugins). (#1621) Thanks @czekaj. https://docs.openclaw.ai/tools/exec-approvals https://docs.openclaw.ai/tools/slash-commands -- Gateway: expose config.patch in the gateway tool with safe partial updates + restart sentinel. (#1653) Thanks @Glucksberg. -- Diagnostics: add diagnostic flags for targeted debug logs (config + env override). https://docs.openclaw.ai/diagnostics/flags -- Docs: expand FAQ (migration, scheduling, concurrency, model recommendations, OpenAI subscription auth, Pi sizing, hackable install, docs SSL workaround). -- Docs: add verbose installer troubleshooting guidance. -- Docs: add macOS VM guide with local/hosted options + VPS/nodes guidance. (#1693) Thanks @f-trycua. -- Docs: add Bedrock EC2 instance role setup + IAM steps. (#1625) Thanks @sergical. https://docs.openclaw.ai/bedrock -- Docs: update Fly.io guide notes. -- Dev: add prek pre-commit hooks + dependabot config for weekly updates. (#1720) Thanks @dguido. - -### Fixes - -- Web UI: fix config/debug layout overflow, scrolling, and code block sizing. (#1715) Thanks @saipreetham589. -- Web UI: show Stop button during active runs, swap back to New session when idle. (#1664) Thanks @ndbroadbent. -- Web UI: clear stale disconnect banners on reconnect; allow form saves with unsupported schema paths but block missing schema. (#1707) Thanks @Glucksberg. -- Web UI: hide internal `message_id` hints in chat bubbles. -- Gateway: allow Control UI token-only auth to skip device pairing even when device identity is present (`gateway.controlUi.allowInsecureAuth`). (#1679) Thanks @steipete. -- Matrix: decrypt E2EE media attachments with preflight size guard. (#1744) Thanks @araa47. -- BlueBubbles: route phone-number targets to DMs, avoid leaking routing IDs, and auto-create missing DMs (Private API required). (#1751) Thanks @tyler6204. https://docs.openclaw.ai/channels/bluebubbles -- BlueBubbles: keep part-index GUIDs in reply tags when short IDs are missing. -- iMessage: normalize chat_id/chat_guid/chat_identifier prefixes case-insensitively and keep service-prefixed handles stable. (#1708) Thanks @aaronn. -- Signal: repair reaction sends (group/UUID targets + CLI author flags). (#1651) Thanks @vilkasdev. -- Signal: add configurable signal-cli startup timeout + external daemon mode docs. (#1677) https://docs.openclaw.ai/channels/signal -- Telegram: set fetch duplex="half" for uploads on Node 22 to avoid sendPhoto failures. (#1684) Thanks @commdata2338. -- Telegram: use wrapped fetch for long-polling on Node to normalize AbortSignal handling. (#1639) -- Telegram: honor per-account proxy for outbound API calls. (#1774) Thanks @radek-paclt. -- Telegram: fall back to text when voice notes are blocked by privacy settings. (#1725) Thanks @foeken. -- Voice Call: return stream TwiML for outbound conversation calls on initial Twilio webhook. (#1634) -- Voice Call: serialize Twilio TTS playback and cancel on barge-in to prevent overlap. (#1713) Thanks @dguido. -- Google Chat: tighten email allowlist matching, typing cleanup, media caps, and onboarding/docs/tests. (#1635) Thanks @iHildy. -- Google Chat: normalize space targets without double `spaces/` prefix. -- Agents: auto-compact on context overflow prompt errors before failing. (#1627) Thanks @rodrigouroz. -- Agents: use the active auth profile for auto-compaction recovery. -- Media understanding: skip image understanding when the primary model already supports vision. (#1747) Thanks @tyler6204. -- Models: default missing custom provider fields so minimal configs are accepted. -- Messaging: keep newline chunking safe for fenced markdown blocks across channels. -- Messaging: treat newline chunking as paragraph-aware (blank-line splits) to keep lists and headings together. (#1726) Thanks @tyler6204. -- TUI: reload history after gateway reconnect to restore session state. (#1663) -- Heartbeat: normalize target identifiers for consistent routing. -- Exec: keep approvals for elevated ask unless full mode. (#1616) Thanks @ivancasco. -- Exec: treat Windows platform labels as Windows for node shell selection. (#1760) Thanks @ymat19. -- Gateway: include inline config env vars in service install environments. (#1735) Thanks @Seredeep. -- Gateway: skip Tailscale DNS probing when tailscale.mode is off. (#1671) -- Gateway: reduce log noise for late invokes + remote node probes; debounce skills refresh. (#1607) Thanks @petter-b. -- Gateway: clarify Control UI/WebChat auth error hints for missing tokens. (#1690) -- Gateway: listen on IPv6 loopback when bound to 127.0.0.1 so localhost webhooks work. -- Gateway: store lock files in the temp directory to avoid stale locks on persistent volumes. (#1676) -- macOS: default direct-transport `ws://` URLs to port 18789; document `gateway.remote.transport`. (#1603) Thanks @ngutman. -- Tests: cap Vitest workers on CI macOS to reduce timeouts. (#1597) Thanks @rohannagpal. -- Tests: avoid fake-timer dependency in embedded runner stream mock to reduce CI flakes. (#1597) Thanks @rohannagpal. -- Tests: increase embedded runner ordering test timeout to reduce CI flakes. (#1597) Thanks @rohannagpal. - -## 2026.1.23-1 - -### Fixes - -- Packaging: include dist/tts output in npm tarball (fixes missing dist/tts/tts.js). - -## 2026.1.23 - -### Highlights - -- TTS: move Telegram TTS into core + enable model-driven TTS tags by default for expressive audio replies. (#1559) Thanks @Glucksberg. https://docs.openclaw.ai/tts -- Gateway: add `/tools/invoke` HTTP endpoint for direct tool calls (auth + tool policy enforced). (#1575) Thanks @vignesh07. https://docs.openclaw.ai/gateway/tools-invoke-http-api -- Heartbeat: per-channel visibility controls (OK/alerts/indicator). (#1452) Thanks @dlauer. https://docs.openclaw.ai/gateway/heartbeat -- Deploy: add Fly.io deployment support + guide. (#1570) https://docs.openclaw.ai/platforms/fly -- Channels: add Tlon/Urbit channel plugin (DMs, group mentions, thread replies). (#1544) Thanks @wca4a. https://docs.openclaw.ai/channels/tlon - -### Changes - -- Channels: allow per-group tool allow/deny policies across built-in + plugin channels. (#1546) Thanks @adam91holt. https://docs.openclaw.ai/multi-agent-sandbox-tools -- Agents: add Bedrock auto-discovery defaults + config overrides. (#1553) Thanks @fal3. https://docs.openclaw.ai/bedrock -- CLI: add `openclaw system` for system events + heartbeat controls; remove standalone `wake`. (commit 71203829d) https://docs.openclaw.ai/cli/system -- CLI: add live auth probes to `openclaw models status` for per-profile verification. (commit 40181afde) https://docs.openclaw.ai/cli/models -- CLI: restart the gateway by default after `openclaw update`; add `--no-restart` to skip it. (commit 2c85b1b40) -- Browser: add node-host proxy auto-routing for remote gateways (configurable per gateway/node). (commit c3cb26f7c) -- Plugins: add optional `llm-task` JSON-only tool for workflows. (#1498) Thanks @vignesh07. https://docs.openclaw.ai/tools/llm-task -- Markdown: add per-channel table conversion (bullets for Signal/WhatsApp, code blocks elsewhere). (#1495) Thanks @odysseus0. -- Agents: keep system prompt time zone-only and move current time to `session_status` for better cache hits. (commit 66eec295b) -- Agents: remove redundant bash tool alias from tool registration/display. (#1571) Thanks @Takhoffman. -- Docs: add cron vs heartbeat decision guide (with Lobster workflow notes). (#1533) Thanks @JustYannicc. https://docs.openclaw.ai/automation/cron-vs-heartbeat -- Docs: clarify HEARTBEAT.md empty file skips heartbeats, missing file still runs. (#1535) Thanks @JustYannicc. https://docs.openclaw.ai/gateway/heartbeat - -### Fixes - -- Sessions: accept non-UUID sessionIds for history/send/status while preserving agent scoping. (#1518) -- Heartbeat: accept plugin channel ids for heartbeat target validation + UI hints. -- Messaging/Sessions: mirror outbound sends into target session keys (threads + dmScope), create session entries on send, and normalize session key casing. (#1520, commit 4b6cdd1d3) -- Sessions: reject array-backed session stores to prevent silent wipes. (#1469) -- Gateway: compare Linux process start time to avoid PID recycling lock loops; keep locks unless stale. (#1572) Thanks @steipete. -- Gateway: accept null optional fields in exec approval requests. (#1511) Thanks @pvoo. -- Exec approvals: persist allowlist entry ids to keep macOS allowlist rows stable. (#1521) Thanks @ngutman. -- Exec: honor tools.exec ask/security defaults for elevated approvals (avoid unwanted prompts). (commit 5662a9cdf) -- Daemon: use platform PATH delimiters when building minimal service paths. (commit a4e57d3ac) -- Linux: include env-configured user bin roots in systemd PATH and align PATH audits. (#1512) Thanks @robbyczgw-cla. -- Tailscale: retry serve/funnel with sudo only for permission errors and keep original failure details. (#1551) Thanks @sweepies. -- Docker: update gateway command in docker-compose and Hetzner guide. (#1514) -- Agents: show tool error fallback when the last assistant turn only invoked tools (prevents silent stops). (commit 8ea8801d0) -- Agents: ignore IDENTITY.md template placeholders when parsing identity. (#1556) -- Agents: drop orphaned OpenAI Responses reasoning blocks on model switches. (#1562) Thanks @roshanasingh4. -- Agents: add CLI log hint to "agent failed before reply" messages. (#1550) Thanks @sweepies. -- Agents: warn and ignore tool allowlists that only reference unknown or unloaded plugin tools. (#1566) -- Agents: treat plugin-only tool allowlists as opt-ins; keep core tools enabled. (#1467) -- Agents: honor enqueue overrides for embedded runs to avoid queue deadlocks in tests. (commit 084002998) -- Slack: honor open groupPolicy for unlisted channels in message + slash gating. (#1563) Thanks @itsjaydesu. -- Discord: limit autoThread mention bypass to bot-owned threads; keep ack reactions mention-gated. (#1511) Thanks @pvoo. -- Discord: retry rate-limited allowlist resolution + command deploy to avoid gateway crashes. (commit f70ac0c7c) -- Mentions: ignore mentionPattern matches when another explicit mention is present in group chats (Slack/Discord/Telegram/WhatsApp). (commit d905ca0e0) -- Telegram: render markdown in media captions. (#1478) -- MS Teams: remove `.default` suffix from Graph scopes and Bot Framework probe scopes. (#1507, #1574) Thanks @Evizero. -- Browser: keep extension relay tabs controllable when the extension reuses a session id after switching tabs. (#1160) -- Voice wake: auto-save wake words on blur/submit across iOS/Android and align limits with macOS. (commit 69f645c66) -- UI: keep the Control UI sidebar visible while scrolling long pages. (#1515) Thanks @pookNast. -- UI: cache Control UI markdown rendering + memoize chat text extraction to reduce Safari typing jank. (commit d57cb2e1a) -- TUI: forward unknown slash commands, include Gateway commands in autocomplete, and render slash replies as system output. (commit 1af227b61, commit 8195497ce, commit 6fba598ea) -- CLI: auth probe output polish (table output, inline errors, reduced noise, and wrap fixes in `openclaw models status`). (commit da3f2b489, commit 00ae21bed, commit 31e59cd58, commit f7dc27f2d, commit 438e782f8, commit 886752217, commit aabe0bed3, commit 81535d512, commit c63144ab1) -- Media: only parse `MEDIA:` tags when they start the line to avoid stripping prose mentions. (#1206) -- Media: preserve PNG alpha when possible; fall back to JPEG when still over size cap. (#1491) Thanks @robbyczgw-cla. -- Skills: gate bird Homebrew install to macOS. (#1569) Thanks @bradleypriest. - -## 2026.1.22 - -### Changes - -- Highlight: Compaction safeguard now uses adaptive chunking, progressive fallback, and UI status + retries. (#1466) Thanks @dlauer. -- Providers: add Antigravity usage tracking to status output. (#1490) Thanks @patelhiren. -- Slack: add chat-type reply threading overrides via `replyToModeByChatType`. (#1442) Thanks @stefangalescu. -- BlueBubbles: add `asVoice` support for MP3/CAF voice memos in sendAttachment. (#1477, #1482) Thanks @Nicell. -- Onboarding: add hatch choice (TUI/Web/Later), token explainer, background dashboard seed on macOS, and showcase link. - -### Fixes - -- BlueBubbles: stop typing indicator on idle/no-reply. (#1439) Thanks @Nicell. -- Message tool: keep path/filePath as-is for send; hydrate buffers only for sendAttachment. (#1444) Thanks @hopyky. -- Auto-reply: only report a model switch when session state is available. (#1465) Thanks @robbyczgw-cla. -- Control UI: resolve local avatar URLs with basePath across injection + identity RPC. (#1457) Thanks @dlauer. -- Agents: sanitize assistant history text to strip tool-call markers. (#1456) Thanks @zerone0x. -- Discord: clarify Message Content Intent onboarding hint. (#1487) Thanks @kyleok. -- Gateway: stop the service before uninstalling and fail if it remains loaded. -- Agents: surface concrete API error details instead of generic AI service errors. -- Exec: fall back to non-PTY when PTY spawn fails (EBADF). (#1484) -- Exec approvals: allow per-segment allowlists for chained shell commands on gateway + node hosts. (#1458) Thanks @czekaj. -- Agents: make OpenAI sessions image-sanitize-only; gate tool-id/repair sanitization by provider. -- Doctor: honor CLAWDBOT_GATEWAY_TOKEN for auth checks and security audit token reuse. (#1448) Thanks @azade-c. -- Agents: make tool summaries more readable and only show optional params when set. -- Agents: honor SOUL.md guidance even when the file is nested or path-qualified. (#1434) Thanks @neooriginal. -- Matrix (plugin): persist m.direct for resolved DMs and harden room fallback. (#1436, #1486) Thanks @sibbl. -- CLI: prefer `~` for home paths in output. -- Mattermost (plugin): enforce pairing/allowlist gating, keep @username targets, and clarify plugin-only docs. (#1428) Thanks @damoahdominic. -- Agents: centralize transcript sanitization in the runner; keep tags and error turns intact. -- Auth: skip auth profiles in cooldown during initial selection and rotation. (#1316) Thanks @odrobnik. -- Agents/TUI: honor user-pinned auth profiles during cooldown and preserve search picker ranking. (#1432) Thanks @tobiasbischoff. -- Docs: fix gog auth services example to include docs scope. (#1454) Thanks @zerone0x. -- Slack: reduce WebClient retries to avoid duplicate sends. (#1481) -- Slack: read thread replies for message reads when threadId is provided (replies-only). (#1450) Thanks @rodrigouroz. -- Discord: honor accountId across message actions and cron deliveries. (#1492) Thanks @svkozak. -- macOS: prefer linked channels in gateway summary to avoid false “not linked” status. -- macOS/tests: fix gateway summary lookup after guard unwrap; prevent browser opens during tests. (ECID-1483) - -## 2026.1.21-2 - -### Fixes - -- Control UI: ignore bootstrap identity placeholder text for avatar values and fall back to the default avatar. https://docs.openclaw.ai/cli/agents https://docs.openclaw.ai/web/control-ui -- Slack: remove deprecated `filetype` field from `files.uploadV2` to eliminate API warnings. (#1447) - -## 2026.1.21 - -### Changes - -- Highlight: Lobster optional plugin tool for typed workflows + approval gates. https://docs.openclaw.ai/tools/lobster -- Lobster: allow workflow file args via `argsJson` in the plugin tool. https://docs.openclaw.ai/tools/lobster -- Heartbeat: allow running heartbeats in an explicit session key. (#1256) Thanks @zknicker. -- CLI: default exec approvals to the local host, add gateway/node targeting flags, and show target details in allowlist output. -- CLI: exec approvals mutations render tables instead of raw JSON. -- Exec approvals: support wildcard agent allowlists (`*`) across all agents. -- Exec approvals: allowlist matches resolved binary paths only, add safe stdin-only bins, and tighten allowlist shell parsing. -- Nodes: expose node PATH in status/describe and bootstrap PATH for node-host execution. -- CLI: flatten node service commands under `openclaw node` and remove `service node` docs. -- CLI: move gateway service commands under `openclaw gateway` and add `gateway probe` for reachability. -- Sessions: add per-channel reset overrides via `session.resetByChannel`. (#1353) Thanks @cash-echo-bot. -- Agents: add identity avatar config support and Control UI avatar rendering. (#1329, #1424) Thanks @dlauer. -- UI: show per-session assistant identity in the Control UI. (#1420) Thanks @robbyczgw-cla. -- CLI: add `openclaw update wizard` for interactive channel selection and restart prompts. https://docs.openclaw.ai/cli/update -- Signal: add typing indicators and DM read receipts via signal-cli. -- MSTeams: add file uploads, adaptive cards, and attachment handling improvements. (#1410) Thanks @Evizero. -- Onboarding: remove the run setup-token auth option (paste setup-token or reuse CLI creds instead). -- Docs: add troubleshooting entry for gateway.mode blocking gateway start. https://docs.openclaw.ai/gateway/troubleshooting -- Docs: add /model allowlist troubleshooting note. (#1405) -- Docs: add per-message Gmail search example for gog. (#1220) Thanks @mbelinky. - -### Breaking - -- **BREAKING:** Control UI now rejects insecure HTTP without device identity by default. Use HTTPS (Tailscale Serve) or set `gateway.controlUi.allowInsecureAuth: true` to allow token-only auth. https://docs.openclaw.ai/web/control-ui#insecure-http -- **BREAKING:** Envelope and system event timestamps now default to host-local time (was UTC) so agents don’t have to constantly convert. - -### Fixes - -- Nodes/macOS: prompt on allowlist miss for node exec approvals, persist allowlist decisions, and flatten node invoke errors. (#1394) Thanks @ngutman. -- Gateway: keep auto bind loopback-first and add explicit tailnet binding to avoid Tailscale taking over local UI. (#1380) -- Memory: prevent CLI hangs by deferring vector probes, adding sqlite-vec/embedding timeouts, and showing sync progress early. -- Agents: enforce 9-char alphanumeric tool call ids for Mistral providers. (#1372) Thanks @zerone0x. -- Embedded runner: persist injected history images so attachments aren’t reloaded each turn. (#1374) Thanks @Nicell. -- Nodes tool: include agent/node/gateway context in tool failure logs to speed approval debugging. -- macOS: exec approvals now respect wildcard agent allowlists (`*`). -- macOS: allow SSH agent auth when no identity file is set. (#1384) Thanks @ameno-. -- Gateway: prevent multiple gateways from sharing the same config/state at once (singleton lock). -- UI: remove the chat stop button and keep the composer aligned to the bottom edge. -- Typing: start instant typing indicators at run start so DMs and mentions show immediately. -- Configure: restrict the model allowlist picker to OAuth-compatible Anthropic models and preselect Opus 4.5. -- Configure: seed model fallbacks from the allowlist selection when multiple models are chosen. -- Model picker: list the full catalog when no model allowlist is configured. -- Discord: honor wildcard channel configs via shared match helpers. (#1334) Thanks @pvoo. -- BlueBubbles: resolve short message IDs safely and expose full IDs in templates. (#1387) Thanks @tyler6204. -- Infra: preserve fetch helper methods when wrapping abort signals. (#1387) -- macOS: default distribution packaging to universal binaries. (#1396) Thanks @JustYannicc. - -## 2026.1.20 - -### Changes - -- Control UI: add copy-as-markdown with error feedback. (#1345) https://docs.openclaw.ai/web/control-ui -- Control UI: drop the legacy list view. (#1345) https://docs.openclaw.ai/web/control-ui -- TUI: add syntax highlighting for code blocks. (#1200) https://docs.openclaw.ai/tui -- TUI: session picker shows derived titles, fuzzy search, relative times, and last message preview. (#1271) https://docs.openclaw.ai/tui -- TUI: add a searchable model picker for quicker model selection. (#1198) https://docs.openclaw.ai/tui -- TUI: add input history (up/down) for submitted messages. (#1348) https://docs.openclaw.ai/tui -- ACP: add `openclaw acp` for IDE integrations. https://docs.openclaw.ai/cli/acp -- ACP: add `openclaw acp client` interactive harness for debugging. https://docs.openclaw.ai/cli/acp -- Skills: add download installs with OS-filtered options. https://docs.openclaw.ai/tools/skills -- Skills: add the local sherpa-onnx-tts skill. https://docs.openclaw.ai/tools/skills -- Memory: add hybrid BM25 + vector search (FTS5) with weighted merging and fallback. https://docs.openclaw.ai/concepts/memory -- Memory: add SQLite embedding cache to speed up reindexing and frequent updates. https://docs.openclaw.ai/concepts/memory -- Memory: add OpenAI batch indexing for embeddings when configured. https://docs.openclaw.ai/concepts/memory -- Memory: enable OpenAI batch indexing by default for OpenAI embeddings. https://docs.openclaw.ai/concepts/memory -- Memory: allow parallel OpenAI batch indexing jobs (default concurrency: 2). https://docs.openclaw.ai/concepts/memory -- Memory: render progress immediately, color batch statuses in verbose logs, and poll OpenAI batch status every 2s by default. https://docs.openclaw.ai/concepts/memory -- Memory: add `--verbose` logging for memory status + batch indexing details. https://docs.openclaw.ai/concepts/memory -- Memory: add native Gemini embeddings provider for memory search. (#1151) https://docs.openclaw.ai/concepts/memory -- Browser: allow config defaults for efficient snapshots in the tool/CLI. (#1336) https://docs.openclaw.ai/tools/browser -- Nostr: add the Nostr channel plugin with profile management + onboarding defaults. (#1323) https://docs.openclaw.ai/channels/nostr -- Matrix: migrate to matrix-bot-sdk with E2EE support, location handling, and group allowlist upgrades. (#1298) https://docs.openclaw.ai/channels/matrix -- Slack: add HTTP webhook mode via Bolt HTTP receiver. (#1143) https://docs.openclaw.ai/channels/slack -- Telegram: enrich forwarded-message context with normalized origin details + legacy fallback. (#1090) https://docs.openclaw.ai/channels/telegram -- Discord: fall back to `/skill` when native command limits are exceeded. (#1287) -- Discord: expose `/skill` globally. (#1287) -- Zalouser: add channel dock metadata, config schema, setup wiring, probe, and status issues. (#1219) https://docs.openclaw.ai/plugins/zalouser -- Plugins: require manifest-embedded config schemas with preflight validation warnings. (#1272) https://docs.openclaw.ai/plugins/manifest -- Plugins: move channel catalog metadata into plugin manifests. (#1290) https://docs.openclaw.ai/plugins/manifest -- Plugins: align Nextcloud Talk policy helpers with core patterns. (#1290) https://docs.openclaw.ai/plugins/manifest -- Plugins/UI: let channel plugin metadata drive UI labels/icons and cron channel options. (#1306) https://docs.openclaw.ai/web/control-ui -- Agents/UI: add agent avatar support in identity config, IDENTITY.md, and the Control UI. (#1329) https://docs.openclaw.ai/gateway/configuration -- Plugins: add plugin slots with a dedicated memory slot selector. https://docs.openclaw.ai/plugins/agent-tools -- Plugins: ship the bundled BlueBubbles channel plugin (disabled by default). https://docs.openclaw.ai/channels/bluebubbles -- Plugins: migrate bundled messaging extensions to the plugin SDK and resolve plugin-sdk imports in the loader. -- Plugins: migrate the Zalo plugin to the shared plugin SDK runtime. https://docs.openclaw.ai/channels/zalo -- Plugins: migrate the Zalo Personal plugin to the shared plugin SDK runtime. https://docs.openclaw.ai/plugins/zalouser -- Plugins: allow optional agent tools with explicit allowlists and add the plugin tool authoring guide. https://docs.openclaw.ai/plugins/agent-tools -- Plugins: auto-enable bundled channel/provider plugins when configuration is present. -- Plugins: sync plugin sources on channel switches and update npm-installed plugins during `openclaw update`. -- Plugins: share npm plugin update logic between `openclaw update` and `openclaw plugins update`. - -- Gateway/API: add `/v1/responses` (OpenResponses) with item-based input + semantic streaming events. (#1229) -- Gateway/API: expand `/v1/responses` to support file/image inputs, tool_choice, usage, and output limits. (#1229) -- Usage: add `/usage cost` summaries and macOS menu cost charts. https://docs.openclaw.ai/reference/api-usage-costs -- Security: warn when <=300B models run without sandboxing while web tools are enabled. https://docs.openclaw.ai/cli/security -- Exec: add host/security/ask routing for gateway + node exec. https://docs.openclaw.ai/tools/exec -- Exec: add `/exec` directive for per-session exec defaults (host/security/ask/node). https://docs.openclaw.ai/tools/exec -- Exec approvals: migrate approvals to `~/.openclaw/exec-approvals.json` with per-agent allowlists + skill auto-allow toggle, and add approvals UI + node exec lifecycle events. https://docs.openclaw.ai/tools/exec-approvals -- Nodes: add headless node host (`openclaw node start`) for `system.run`/`system.which`. https://docs.openclaw.ai/cli/node -- Nodes: add node daemon service install/status/start/stop/restart. https://docs.openclaw.ai/cli/node -- Bridge: add `skills.bins` RPC to support node host auto-allow skill bins. -- Sessions: add daily reset policy with per-type overrides and idle windows (default 4am local), preserving legacy idle-only configs. (#1146) https://docs.openclaw.ai/concepts/session -- Sessions: allow `sessions_spawn` to override thinking level for sub-agent runs. https://docs.openclaw.ai/tools/subagents -- Channels: unify thread/topic allowlist matching + command/mention gating helpers across core providers. https://docs.openclaw.ai/concepts/groups -- Models: add Qwen Portal OAuth provider support. (#1120) https://docs.openclaw.ai/providers/qwen -- Onboarding: add allowlist prompts and username-to-id resolution across core and extension channels. https://docs.openclaw.ai/start/onboarding -- Docs: clarify allowlist input types and onboarding behavior for messaging channels. https://docs.openclaw.ai/start/onboarding -- Docs: refresh Android node discovery docs for the Gateway WS service type. https://docs.openclaw.ai/platforms/android -- Docs: surface Amazon Bedrock in provider lists and clarify Bedrock auth env vars. (#1289) https://docs.openclaw.ai/bedrock -- Docs: clarify WhatsApp voice notes. https://docs.openclaw.ai/channels/whatsapp -- Docs: clarify Windows WSL portproxy LAN access notes. https://docs.openclaw.ai/platforms/windows -- Docs: refresh bird skill install metadata and usage notes. (#1302) https://docs.openclaw.ai/tools/browser-login -- Agents: add local docs path resolution and include docs/mirror/source/community pointers in the system prompt. -- Agents: clarify node_modules read-only guidance in agent instructions. -- Config: stamp last-touched metadata on write and warn if the config is newer than the running build. -- macOS: hide usage section when usage is unavailable instead of showing provider errors. -- Android: migrate node transport to the Gateway WebSocket protocol with TLS pinning support + gateway discovery naming. -- Android: send structured payloads in node events/invokes and include user-agent metadata in gateway connects. -- Android: remove legacy bridge transport code now that nodes use the gateway protocol. -- Android: bump okhttp + dnsjava to satisfy lint dependency checks. -- Build: update workspace + core/plugin deps. -- Build: use tsgo for dev/watch builds by default (opt out with `OPENCLAW_TS_COMPILER=tsc`). -- Repo: remove the Peekaboo git submodule now that the SPM release is used. -- macOS: switch PeekabooBridge integration to the tagged Swift Package Manager release. -- macOS: stop syncing Peekaboo in postinstall. -- Swabble: use the tagged Commander Swift package release. - -### Breaking - -- **BREAKING:** Reject invalid/unknown config entries and refuse to start the gateway for safety. Run `openclaw doctor --fix` to repair, then update plugins (`openclaw plugins update`) if you use any. - -### Fixes - -- Discovery: shorten Bonjour DNS-SD service type to `_moltbot-gw._tcp` and update discovery clients/docs. -- Diagnostics: export OTLP logs, correct queue depth tracking, and document message-flow telemetry. -- Diagnostics: emit message-flow diagnostics across channels via shared dispatch. (#1244) -- Diagnostics: gate heartbeat/webhook logging. (#1244) -- Gateway: strip inbound envelope headers from chat history messages to keep clients clean. -- Gateway: clarify unauthorized handshake responses with token/password mismatch guidance. -- Gateway: allow mobile node client ids for iOS + Android handshake validation. (#1354) -- Gateway: clarify connect/validation errors for gateway params. (#1347) -- Gateway: preserve restart wake routing + thread replies across restarts. (#1337) -- Gateway: reschedule per-agent heartbeats on config hot reload without restarting the runner. -- Gateway: require authorized restarts for SIGUSR1 (restart/apply/update) so config gating can't be bypassed. -- Cron: auto-deliver isolated agent output to explicit targets without tool calls. (#1285) -- Agents: preserve subagent announce thread/topic routing + queued replies across channels. (#1241) -- Agents: propagate accountId into embedded runs so sub-agent announce routing honors the originating account. (#1058) -- Agents: avoid treating timeout errors with "aborted" messages as user aborts, so model fallback still runs. (#1137) -- Agents: sanitize oversized image payloads before send and surface image-dimension errors. -- Sessions: fall back to session labels when listing display names. (#1124) -- Compaction: include tool failure summaries in safeguard compaction to prevent retry loops. (#1084) -- Config: log invalid config issues once per run and keep invalid-config errors stackless. -- Config: allow Perplexity as a web_search provider in config validation. (#1230) -- Config: allow custom fields under `skills.entries..config` for skill credentials/config. (#1226) -- Doctor: clarify plugin auto-enable hint text in the startup banner. -- Doctor: canonicalize legacy session keys in session stores to prevent stale metadata. (#1169) -- Docs: make docs:list fail fast with a clear error if the docs directory is missing. -- Plugins: add Nextcloud Talk manifest for plugin config validation. (#1297) -- Plugins: surface plugin load/register/config errors in gateway logs with plugin/source context. -- CLI: preserve cron delivery settings when editing message payloads. (#1322) -- CLI: keep `openclaw logs` output resilient to broken pipes while preserving progress output. -- CLI: avoid duplicating --profile/--dev flags when formatting commands. -- CLI: centralize CLI command registration to keep fast-path routing and program wiring in sync. (#1207) -- CLI: keep banners on routed commands, restore config guarding outside fast-path routing, and tighten fast-path flag parsing while skipping console capture for extra speed. (#1195) -- CLI: skip runner rebuilds when dist is fresh. (#1231) -- CLI: add WSL2/systemd unavailable hints in daemon status/doctor output. -- Status: route native `/status` to the active agent so model selection reflects the correct profile. (#1301) -- Status: show both usage windows with reset hints when usage data is available. (#1101) -- UI: keep config form enums typed, preserve empty strings, protect sensitive defaults, and deepen config search. (#1315) -- UI: preserve ordered list numbering in chat markdown. (#1341) -- UI: allow Control UI to read gatewayUrl from URL params for remote WebSocket targets. (#1342) -- UI: prevent double-scroll in Control UI chat by locking chat layout to the viewport. (#1283) -- UI: enable shell mode for sync Windows spawns to avoid `pnpm ui:build` EINVAL. (#1212) -- TUI: keep thinking blocks ordered before content during streaming and isolate per-run assembly. (#1202) -- TUI: align custom editor initialization with the latest pi-tui API. (#1298) -- TUI: show generic empty-state text for searchable pickers. (#1201) -- TUI: highlight model search matches and stabilize search ordering. -- Configure: hide OpenRouter auto routing model from the model picker. (#1182) -- Memory: show total file counts + scan issues in `openclaw memory status`. -- Memory: fall back to non-batch embeddings after repeated batch failures. -- Memory: apply OpenAI batch defaults even without explicit remote config. -- Memory: index atomically so failed reindex preserves the previous memory database. (#1151) -- Memory: avoid sqlite-vec unique constraint failures when reindexing duplicate chunk ids. (#1151) -- Memory: retry transient 5xx errors (Cloudflare) during embedding indexing. -- Memory: parallelize embedding indexing with rate-limit retries. -- Memory: split overly long lines to keep embeddings under token limits. -- Memory: skip empty chunks to avoid invalid embedding inputs. -- Memory: split embedding batches to avoid OpenAI token limits during indexing. -- Memory: probe sqlite-vec availability in `openclaw memory status`. -- Exec approvals: enforce allowlist when ask is off. -- Exec approvals: prefer raw command for node approvals/events. -- Tools: show exec elevated flag before the command and keep it outside markdown in tool summaries. -- Tools: return a companion-app-required message when node exec is requested with no paired node. -- Tools: return a companion-app-required message when `system.run` is requested without a supporting node. -- Exec: default gateway/node exec security to allowlist when unset (sandbox stays deny). -- Exec: prefer bash when fish is default shell, falling back to sh if bash is missing. (#1297) -- Exec: merge login-shell PATH for host=gateway exec while keeping daemon PATH minimal. (#1304) -- Streaming: emit assistant deltas for OpenAI-compatible SSE chunks. (#1147) -- Discord: make resolve warnings avoid raw JSON payloads on rate limits. -- Discord: process message handlers in parallel across sessions to avoid event queue blocking. (#1295) -- Discord: stop reconnecting the gateway after aborts to prevent duplicate listeners. -- Discord: only emit slow listener warnings after 30s. -- Discord: inherit parent channel allowlists for thread slash commands and reactions. (#1123) -- Telegram: honor pairing allowlists for native slash commands. -- Telegram: preserve hidden text_link URLs by expanding entities in inbound text. (#1118) -- Slack: resolve Bolt import interop for Bun + Node. (#1191) -- Web search: infer Perplexity base URL from API key source (direct vs OpenRouter). -- Web fetch: harden SSRF protection with shared hostname checks and redirect limits. (#1346) -- Browser: register AI snapshot refs for act commands. (#1282) -- Voice call: include request query in Twilio webhook verification when publicUrl is set. (#864) -- Anthropic: default API prompt caching to 1h with configurable TTL override. -- Anthropic: ignore TTL for OAuth. -- Auth profiles: keep auto-pinned preference while allowing rotation on failover. (#1138) -- Auth profiles: user pins stay locked. (#1138) -- Model catalog: avoid caching import failures, log transient discovery errors, and keep partial results. (#1332) -- Tests: stabilize Windows gateway/CLI tests by skipping sidecars, normalizing argv, and extending timeouts. -- Tests: stabilize plugin SDK resolution and embedded agent timeouts. -- Windows: install gateway scheduled task as the current user. -- Windows: show friendly guidance instead of failing on access denied. -- macOS: load menu session previews asynchronously so items populate while the menu is open. -- macOS: use label colors for session preview text so previews render in menu subviews. -- macOS: suppress usage error text in the menubar cost view. -- macOS: Doctor repairs LaunchAgent bootstrap issues for Gateway + Node when listed but not loaded. (#1166) -- macOS: avoid touching launchd in Remote over SSH so quitting the app no longer disables the remote gateway. (#1105) -- macOS: bundle Textual resources in packaged app builds to avoid code block crashes. (#1006) -- Daemon: include HOME in service environments to avoid missing HOME errors. (#1214) - -Thanks @AlexMikhalev, @CoreyH, @John-Rood, @KrauseFx, @MaudeBot, @Nachx639, @NicholaiVogel, @RyanLisse, @ThePickle31, @VACInc, @Whoaa512, @YuriNachos, @aaronveklabs, @abdaraxus, @alauppe, @ameno-, @artuskg, @austinm911, @bradleypriest, @cheeeee, @dougvk, @fogboots, @gnarco, @gumadeiras, @jdrhyne, @joelklabo, @longmaba, @mukhtharcm, @odysseus0, @oscargavin, @rhjoh, @sebslight, @sibbl, @sleontenko, @steipete, @suminhthanh, @thewilloftheshadow, @tyler6204, @vignesh07, @visionik, @ysqander, @zerone0x. - -## 2026.1.16-2 - -### Changes - -- CLI: stamp build commit into dist metadata so banners show the commit in npm installs. -- CLI: close memory manager after memory commands to avoid hanging processes. (#1127) — thanks @NicholasSpisak. - -## 2026.1.16-1 - -### Highlights - -- Hooks: add hooks system with bundled hooks, CLI tooling, and docs. (#1028) — thanks @ThomsenDrake. https://docs.openclaw.ai/hooks -- Media: add inbound media understanding (image/audio/video) with provider + CLI fallbacks. https://docs.openclaw.ai/nodes/media-understanding -- Plugins: add Zalo Personal plugin (`@openclaw/zalouser`) and unify channel directory for plugins. (#1032) — thanks @suminhthanh. https://docs.openclaw.ai/plugins/zalouser -- Models: add Vercel AI Gateway auth choice + onboarding updates. (#1016) — thanks @timolins. https://docs.openclaw.ai/providers/vercel-ai-gateway -- Sessions: add `session.identityLinks` for cross-platform DM session li nking. (#1033) — thanks @thewilloftheshadow. https://docs.openclaw.ai/concepts/session -- Web search: add `country`/`language` parameters (schema + Brave API) and docs. (#1046) — thanks @YuriNachos. https://docs.openclaw.ai/tools/web - -### Breaking - -- **BREAKING:** `openclaw message` and message tool now require `target` (dropping `to`/`channelId` for destinations). (#1034) — thanks @tobalsan. -- **BREAKING:** Channel auth now prefers config over env for Discord/Telegram/Matrix (env is fallback only). (#1040) — thanks @thewilloftheshadow. -- **BREAKING:** Drop legacy `chatType: "room"` support; use `chatType: "channel"`. -- **BREAKING:** remove legacy provider-specific target resolution fallbacks; target resolution is centralized with plugin hints + directory lookups. -- **BREAKING:** `openclaw hooks` is now `openclaw webhooks`; hooks live under `openclaw hooks`. https://docs.openclaw.ai/cli/webhooks -- **BREAKING:** `openclaw plugins install ` now copies into `~/.openclaw/extensions` (use `--link` to keep path-based loading). - -### Changes - -- Plugins: ship bundled plugins disabled by default and allow overrides by installed versions. (#1066) — thanks @ItzR3NO. -- Plugins: add bundled Antigravity + Gemini CLI OAuth + Copilot Proxy provider plugins. (#1066) — thanks @ItzR3NO. -- Tools: improve `web_fetch` extraction using Readability (with fallback). -- Tools: add Firecrawl fallback for `web_fetch` when configured. -- Tools: send Chrome-like headers by default for `web_fetch` to improve extraction on bot-sensitive sites. -- Tools: Firecrawl fallback now uses bot-circumvention + cache by default; remove basic HTML fallback when extraction fails. -- Tools: default `exec` exit notifications and auto-migrate legacy `tools.bash` to `tools.exec`. -- Tools: add `exec` PTY support for interactive sessions. https://docs.openclaw.ai/tools/exec -- Tools: add tmux-style `process send-keys` and bracketed paste helpers for PTY sessions. -- Tools: add `process submit` helper to send CR for PTY sessions. -- Tools: respond to PTY cursor position queries to unblock interactive TUIs. -- Tools: include tool outputs in verbose mode and expand verbose tool feedback. -- Skills: update coding-agent guidance to prefer PTY-enabled exec runs and simplify tmux usage. -- TUI: refresh session token counts after runs complete or fail. (#1079) — thanks @d-ploutarchos. -- Status: trim `/status` to current-provider usage only and drop the OAuth/token block. -- Directory: unify `openclaw directory` across channels and plugin channels. -- UI: allow deleting sessions from the Control UI. -- Memory: add sqlite-vec vector acceleration with CLI status details. -- Memory: add experimental session transcript indexing for memory_search (opt-in via memorySearch.experimental.sessionMemory + sources). -- Skills: add user-invocable skill commands and expanded skill command registration. -- Telegram: default reaction level to minimal and enable reaction notifications by default. -- Telegram: allow reply-chain messages to bypass mention gating in groups. (#1038) — thanks @adityashaw2. -- iMessage: add remote attachment support for VM/SSH deployments. -- Messages: refresh live directory cache results when resolving targets. -- Messages: mirror delivered outbound text/media into session transcripts. (#1031) — thanks @TSavo. -- Messages: avoid redundant sender envelopes for iMessage + Signal group chats. (#1080) — thanks @tyler6204. -- Media: normalize Deepgram audio upload bytes for fetch compatibility. -- Cron: isolated cron jobs now start a fresh session id on every run to prevent context buildup. -- Docs: add `/help` hub, Node/npm PATH guide, and expand directory CLI docs. -- Config: support env var substitution in config values. (#1044) — thanks @sebslight. -- Health: add per-agent session summaries and account-level health details, and allow selective probes. (#1047) — thanks @gumadeiras. -- Hooks: add hook pack installs (npm/path/zip/tar) with `openclaw.hooks` manifests and `openclaw hooks install/update`. -- Plugins: add zip installs and `--link` to avoid copying local paths. - -### Fixes - -- macOS: drain subprocess pipes before waiting to avoid deadlocks. (#1081) — thanks @thesash. -- Verbose: wrap tool summaries/output in markdown only for markdown-capable channels. -- Tools: include provider/session context in elevated exec denial errors. -- Tools: normalize exec tool alias naming in tool error logs. -- Logging: reuse shared ANSI stripping to keep console capture lint-clean. -- Logging: prefix nested agent output with session/run/channel context. -- Telegram: accept tg/group/telegram prefixes + topic targets for inline button validation. (#1072) — thanks @danielz1z. -- Telegram: split long captions into follow-up messages. -- Config: block startup on invalid config, preserve best-effort doctor config, and keep rolling config backups. (#1083) — thanks @mukhtharcm. -- Sub-agents: normalize announce delivery origin + queue bucketing by accountId to keep multi-account routing stable. (#1061, #1058) — thanks @adam91holt. -- Sessions: include deliveryContext in sessions.list and reuse normalized delivery routing for announce/restart fallbacks. (#1058) -- Sessions: propagate deliveryContext into last-route updates to keep account/channel routing stable. (#1058) -- Sessions: preserve overrides on `/new` reset. -- Memory: prevent unhandled rejections when watch/interval sync fails. (#1076) — thanks @roshanasingh4. -- Memory: avoid gateway crash when embeddings return 429/insufficient_quota (disable tool + surface error). (#1004) -- Gateway: honor explicit delivery targets without implicit accountId fallback; preserve lastAccountId for implicit routing. -- Gateway: avoid reusing last-to/accountId when the requested channel differs; sync deliveryContext with last route fields. -- Build: allow `@lydell/node-pty` builds on supported platforms. -- Repo: fix oxlint config filename and move ignore pattern into config. (#1064) — thanks @connorshea. -- Messages: `/stop` now hard-aborts queued followups and sub-agent runs; suppress zero-count stop notes. -- Messages: honor message tool channel when deduping sends. -- Messages: include sender labels for live group messages across channels, matching queued/history formatting. (#1059) -- Sessions: reset `compactionCount` on `/new` and `/reset`, and preserve `sessions.json` file mode (0600). -- Sessions: repair orphaned user turns before embedded prompts. -- Sessions: hard-stop `sessions.delete` cleanup. -- Channels: treat replies to the bot as implicit mentions across supported channels. -- Channels: normalize object-format capabilities in channel capability parsing. -- Security: default-deny slash/control commands unless a channel computed `CommandAuthorized` (fixes accidental “open” behavior), and ensure WhatsApp + Zalo plugin channels gate inline `/…` tokens correctly. https://docs.openclaw.ai/gateway/security -- Security: redact sensitive text in gateway WS logs. -- Tools: cap pending `exec` process output to avoid unbounded buffers. -- CLI: speed up `openclaw sandbox-explain` by avoiding heavy plugin imports when normalizing channel ids. -- Browser: remote profile tab operations prefer persistent Playwright and avoid silent HTTP fallbacks. (#1057) — thanks @mukhtharcm. -- Browser: remote profile tab ops follow-up: shared Playwright loader, Playwright-based focus, and more coverage (incl. opt-in live Browserless test). (follow-up to #1057) — thanks @mukhtharcm. -- Browser: refresh extension relay tab metadata after navigation so `/json/list` stays current. (#1073) — thanks @roshanasingh4. -- WhatsApp: scope self-chat response prefix; inject pending-only group history and clear after any processed message. -- WhatsApp: include `linked` field in `describeAccount`. -- Agents: drop unsigned Gemini tool calls and avoid JSON Schema `format` keyword collisions. -- Agents: hide the image tool when the primary model already supports images. -- Agents: avoid duplicate sends by replying with `NO_REPLY` after `message` tool sends. -- Auth: inherit/merge sub-agent auth profiles from the main agent. -- Gateway: resolve local auth for security probe and validate gateway token/password file modes. (#1011, #1022) — thanks @ivanrvpereira, @kkarimi. -- Signal/iMessage: bound transport readiness waits to 30s with periodic logging. (#1014) — thanks @Szpadel. -- iMessage: avoid RPC restart loops. -- OpenAI image-gen: handle URL + `b64_json` responses and remove deprecated `response_format` (use URL downloads). -- CLI: auto-update global installs when installed via a package manager. -- Routing: migrate legacy `accountID` bindings to `accountId` and remove legacy fallback lookups. (#1047) — thanks @gumadeiras. -- Discord: truncate skill command descriptions to 100 chars for slash command limits. (#1018) — thanks @evalexpr. -- Security: bump `tar` to 7.5.3. -- Models: align ZAI thinking toggles. -- iMessage/Signal: include sender metadata for non-queued group messages. (#1059) -- Discord: preserve whitespace when chunking long lines so message splits keep spacing intact. -- Skills: fix skills watcher ignored list typing (tsc). - -## 2026.1.15 - -### Highlights - -- Plugins: add provider auth registry + `openclaw models auth login` for plugin-driven OAuth/API key flows. -- Browser: improve remote CDP/Browserless support (auth passthrough, `wss` upgrade, timeouts, clearer errors). -- Heartbeat: per-agent configuration + 24h duplicate suppression. (#980) — thanks @voidserf. -- Security: audit warns on weak model tiers; app nodes store auth tokens encrypted (Keychain/SecurePrefs). - -### Breaking - -- **BREAKING:** iOS minimum version is now 18.0 to support Textual markdown rendering in native chat. (#702) -- **BREAKING:** Microsoft Teams is now a plugin; install `@openclaw/msteams` via `openclaw plugins install @openclaw/msteams`. -- **BREAKING:** Channel auth now prefers config over env for Discord/Telegram/Matrix (env is fallback only). (#1040) — thanks @thewilloftheshadow. - -### Changes - -- UI/Apps: move channel/config settings to schema-driven forms and rename Connections → Channels. (#1040) — thanks @thewilloftheshadow. -- CLI: set process titles to `openclaw-` for clearer process listings. -- CLI/macOS: sync remote SSH target/identity to config and let `gateway status` auto-infer SSH targets (ssh-config aware). -- Telegram: scope inline buttons with allowlist default + callback gating in DMs/groups. -- Telegram: default reaction notifications to own. -- Tools: improve `web_fetch` extraction using Readability (with fallback). -- Heartbeat: tighten prompt guidance + suppress duplicate alerts for 24h. (#980) — thanks @voidserf. -- Repo: ignore local identity files to avoid accidental commits. (#1001) — thanks @gerardward2007. -- Sessions/Security: add `session.dmScope` for multi-user DM isolation and audit warnings. (#948) — thanks @Alphonse-arianee. -- Onboarding: switch channels setup to a single-select loop with per-channel actions and disabled hints in the picker. -- TUI: show provider/model labels for the active session and default model. -- Heartbeat: add per-agent heartbeat configuration and multi-agent docs example. -- UI: show gateway auth guidance + doc link on unauthorized Control UI connections. -- UI: add session deletion action in Control UI sessions list. (#1017) — thanks @Szpadel. -- Security: warn on weak model tiers (Haiku, below GPT-5, below Claude 4.5) in `openclaw security audit`. -- Apps: store node auth tokens encrypted (Keychain/SecurePrefs). -- Daemon: share profile/state-dir resolution across service helpers and honor `CLAWDBOT_STATE_DIR` for Windows task scripts. -- Docs: clarify multi-gateway rescue bot guidance. (#969) — thanks @bjesuiter. -- Agents: add Current Date & Time system prompt section with configurable time format (auto/12/24). -- Tools: normalize Slack/Discord message timestamps with `timestampMs`/`timestampUtc` while keeping raw provider fields. -- macOS: add `system.which` for prompt-free remote skill discovery (with gateway fallback to `system.run`). -- Docs: add Date & Time guide and update prompt/timezone configuration docs. -- Messages: debounce rapid inbound messages across channels with per-connector overrides. (#971) — thanks @juanpablodlc. -- Messages: allow media-only sends (CLI/tool) and show Telegram voice recording status for voice notes. (#957) — thanks @rdev. -- Auth/Status: keep auth profiles sticky per session (rotate on compaction/new), surface provider usage headers in `/status` and `openclaw models status`, and update docs. -- CLI: add `--json` output for `openclaw daemon` lifecycle/install commands. -- Memory: make `node-llama-cpp` an optional dependency (avoid Node 25 install failures) and improve local-embeddings fallback/errors. -- Browser: add `snapshot refs=aria` (Playwright aria-ref ids) for self-resolving refs across `snapshot` → `act`. -- Browser: `profile="chrome"` now defaults to host control and returns clearer “attach a tab” errors. -- Browser: prefer stable Chrome for auto-detect, with Brave/Edge fallbacks and updated docs. (#983) — thanks @cpojer. -- Browser: increase remote CDP reachability timeouts + add `remoteCdpTimeoutMs`/`remoteCdpHandshakeTimeoutMs`. -- Browser: preserve auth/query tokens for remote CDP endpoints and pass Basic auth for CDP HTTP/WS. (#895) — thanks @mukhtharcm. -- Telegram: add bidirectional reaction support with configurable notifications and agent guidance. (#964) — thanks @bohdanpodvirnyi. -- Telegram: allow custom commands in the bot menu (merged with native; conflicts ignored). (#860) — thanks @nachoiacovino. -- Discord: allow allowlisted guilds without channel lists to receive messages when `groupPolicy="allowlist"`. — thanks @thewilloftheshadow. -- Discord: allow emoji/sticker uploads + channel actions in config defaults. (#870) — thanks @JDIVE. - -### Fixes - -- Messages: make `/stop` clear queued followups and pending session lane work for a hard abort. -- Messages: make `/stop` abort active sub-agent runs spawned from the requester session and report how many were stopped. -- WhatsApp: report linked status consistently in channel status. (#1050) — thanks @YuriNachos. -- Sessions: keep per-session overrides when `/new` resets compaction counters. (#1050) — thanks @YuriNachos. -- Skills: allow OpenAI image-gen helper to handle URL or base64 responses. (#1050) — thanks @YuriNachos. -- WhatsApp: default response prefix only for self-chat, using identity name when set. -- Signal/iMessage: bound transport readiness waits to 30s with periodic logging. (#1014) — thanks @Szpadel. -- iMessage: treat missing `imsg rpc` support as fatal to avoid restart loops. -- Auth: merge main auth profiles into per-agent stores for sub-agents and document inheritance. (#1013) — thanks @marcmarg. -- Agents: avoid JSON Schema `format` collisions in tool params by renaming snapshot format fields. (#1013) — thanks @marcmarg. -- Fix: make `openclaw update` auto-update global installs when installed via a package manager. -- Fix: list model picker entries as provider/model pairs for explicit selection. (#970) — thanks @mcinteerj. -- Fix: align OpenAI image-gen defaults with DALL-E 3 standard quality and document output formats. (#880) — thanks @mkbehr. -- Fix: persist `gateway.mode=local` after selecting Local run mode in `openclaw configure`, even if no other sections are chosen. -- Daemon: fix profile-aware service label resolution (env-driven) and add coverage for launchd/systemd/schtasks. (#969) — thanks @bjesuiter. -- Agents: avoid false positives when logging unsupported Google tool schema keywords. -- Agents: skip Gemini history downgrades for google-antigravity to preserve tool calls. (#894) — thanks @mukhtharcm. -- Status: restore usage summary line for current provider when no OAuth profiles exist. -- Fix: guard model fallback against undefined provider/model values. (#954) — thanks @roshanasingh4. -- Fix: refactor session store updates, add chat.inject, and harden subagent cleanup flow. (#944) — thanks @tyler6204. -- Fix: clean up suspended CLI processes across backends. (#978) — thanks @Nachx639. -- Fix: support MiniMax coding plan usage responses with `model_remains`/`current_interval_*` payloads. -- Fix: honor message tool channel for duplicate suppression (prefer `NO_REPLY` after `message` tool sends). (#1053) — thanks @sashcatanzarite. -- Fix: suppress WhatsApp pairing replies for historical catch-up DMs on initial link. (#904) -- Browser: extension mode recovers when only one tab is attached (stale targetId fallback). -- Browser: fix `tab not found` for extension relay snapshots/actions when Playwright blocks `newCDPSession` (use the single available Page). -- Browser: upgrade `ws` → `wss` when remote CDP uses `https` (fixes Browserless handshake). -- Telegram: skip `message_thread_id=1` for General topic sends while keeping typing indicators. (#848) — thanks @azade-c. -- Fix: sanitize user-facing error text + strip `` tags across reply pipelines. (#975) — thanks @ThomsenDrake. -- Fix: normalize pairing CLI aliases, allow extension channels, and harden Zalo webhook payload parsing. (#991) — thanks @longmaba. -- Fix: allow local Tailscale Serve hostnames without treating tailnet clients as direct. (#885) — thanks @oswalpalash. -- Fix: reset sessions after role-ordering conflicts to recover from consecutive user turns. (#998) - -## 2026.1.14-1 - -### Highlights - -- Web search: `web_search`/`web_fetch` tools (Brave API) + first-time setup in onboarding/configure. -- Browser control: Chrome extension relay takeover mode + remote browser control support. -- Plugins: channel plugins (gateway HTTP hooks) + Zalo plugin + onboarding install flow. (#854) — thanks @longmaba. -- Security: expanded `openclaw security audit` (+ `--fix`), detect-secrets CI scan, and a `SECURITY.md` reporting policy. - -### Changes - -- Docs: clarify per-agent auth stores, sandboxed skill binaries, and elevated semantics. -- Docs: add FAQ entries for missing provider auth after adding agents and Gemini thinking signature errors. -- Agents: add optional auth-profile copy prompt on `agents add` and improve auth error messaging. -- Security: expand `openclaw security audit` checks (model hygiene, config includes, plugin allowlists, exposure matrix) and extend `--fix` to tighten more sensitive state paths. -- Security: add `SECURITY.md` reporting policy. -- Channels: add Matrix plugin (external) with docs + onboarding hooks. -- Plugins: add Zalo channel plugin with gateway HTTP hooks and onboarding install prompt. (#854) — thanks @longmaba. -- Onboarding: add a security checkpoint prompt (docs link + sandboxing hint); require `--accept-risk` for `--non-interactive`. -- Docs: expand gateway security hardening guidance and incident response checklist. -- Docs: document DM history limits for channel DMs. (#883) — thanks @pkrmf. -- Security: add detect-secrets CI scan and baseline guidance. (#227) — thanks @Hyaxia. -- Tools: add `web_search`/`web_fetch` (Brave API), auto-enable `web_fetch` for sandboxed sessions, and remove the `brave-search` skill. -- CLI/Docs: add a web tools configure section for storing Brave API keys and update onboarding tips. -- Browser: add Chrome extension relay takeover mode (toolbar button), plus `openclaw browser extension install/path` and remote browser control (standalone server + token auth). - -### Fixes - -- Sessions: refactor session store updates to lock + mutate per-entry, add chat.inject, and harden subagent cleanup flow. (#944) — thanks @tyler6204. -- Browser: add tests for snapshot labels/efficient query params and labeled image responses. -- Google: downgrade unsigned thinking blocks before send to avoid missing signature errors. -- Doctor: avoid re-adding WhatsApp config when only legacy ack reactions are set. (#927, fixes #900) — thanks @grp06. -- Agents: scrub tuple `items` schemas for Gemini tool calls. (#926, fixes #746) — thanks @grp06. -- Agents: harden Antigravity Claude history/tool-call sanitization. (#968) — thanks @rdev. -- Agents: stabilize sub-agent announce status from runtime outcomes and normalize Result/Notes. (#835) — thanks @roshanasingh4. -- Embedded runner: suppress raw API error payloads from replies. (#924) — thanks @grp06. -- Auth: normalize Claude Code CLI profile mode to oauth and auto-migrate config. (#855) — thanks @sebslight. -- Daemon: clear persisted launchd disabled state before bootstrap (fixes `daemon install` after uninstall). (#849) — thanks @ndraiman. -- Logging: tolerate `EIO` from console writes to avoid gateway crashes. (#925, fixes #878) — thanks @grp06. -- Sandbox: restore `docker.binds` config validation for custom bind mounts. (#873) — thanks @akonyer. -- Sandbox: preserve configured PATH for `docker exec` so custom tools remain available. (#873) — thanks @akonyer. -- Slack: respect `channels.slack.requireMention` default when resolving channel mention gating. (#850) — thanks @evalexpr. -- Telegram: aggregate split inbound messages into one prompt (reduces “one reply per fragment”). -- Auto-reply: treat trailing `NO_REPLY` tokens as silent replies. -- Config: prevent partial config writes from clobbering unrelated settings (base hash guard + merge patch for connection saves). - -## 2026.1.14 - -### Changes - -- Usage: add MiniMax coding plan usage tracking. -- Auth: label Claude Code CLI auth options. (#915) — thanks @SeanZoR. -- Docs: standardize Claude Code CLI naming across docs and prompts. (follow-up to #915) -- Telegram: add message delete action in the message tool. (#903) — thanks @sleontenko. -- Config: add `channels..configWrites` gating for channel-initiated config writes; migrate Slack channel IDs. - -### Fixes - -- Mac: pass auth token/password to dashboard URL for authenticated access. (#918) — thanks @rahthakor. -- UI: use application-defined WebSocket close code (browser compatibility). (#918) — thanks @rahthakor. -- TUI: render picker overlays via the overlay stack so /models and /settings display. (#921) — thanks @grizzdank. -- TUI: add a bright spinner + elapsed time in the status line for send/stream/run states. -- TUI: show LLM error messages (rate limits, auth, etc.) instead of `(no output)`. -- Gateway/Dev: ensure `pnpm gateway:dev` always uses the dev profile config + state (`~/.openclaw-dev`). - -#### Agents / Auth / Tools / Sandbox - -- Agents: make user time zone and 24-hour time explicit in the system prompt. (#859) — thanks @CashWilliams. -- Agents: strip downgraded tool call text without eating adjacent replies and filter thinking-tag leaks. (#905) — thanks @erikpr1994. -- Agents: cap tool call IDs for OpenAI/OpenRouter to avoid request rejections. (#875) — thanks @j1philli. -- Agents: scrub tuple `items` schemas for Gemini tool calls. (#926, fixes #746) — thanks @grp06. -- Agents: stabilize sub-agent announce status from runtime outcomes and normalize Result/Notes. (#835) — thanks @roshanasingh4. -- Auth: normalize Claude Code CLI profile mode to oauth and auto-migrate config. (#855) — thanks @sebslight. -- Embedded runner: suppress raw API error payloads from replies. (#924) — thanks @grp06. -- Logging: tolerate `EIO` from console writes to avoid gateway crashes. (#925, fixes #878) — thanks @grp06. -- Sandbox: restore `docker.binds` config validation and preserve configured PATH for `docker exec`. (#873) — thanks @akonyer. -- Google: downgrade unsigned thinking blocks before send to avoid missing signature errors. - -#### macOS / Apps - -- macOS: ensure launchd log directory exists with a test-only override. (#909) — thanks @roshanasingh4. -- macOS: format ConnectionsStore config to satisfy SwiftFormat lint. (#852) — thanks @mneves75. -- macOS: pass auth token/password to dashboard URL for authenticated access. (#918) — thanks @rahthakor. -- macOS: reuse launchd gateway auth and skip wizard when gateway config already exists. (#917) -- macOS: prefer the default bridge tunnel port in remote mode for node bridge connectivity; document macOS remote control + bridge tunnels. (#960, fixes #865) — thanks @kkarimi. -- Apps: use canonical main session keys from gateway defaults across macOS/iOS/Android to avoid creating bare `main` sessions. -- macOS: fix cron preview/testing payload to use `channel` key. (#867) — thanks @wes-davis. -- Telegram: honor `channels.telegram.timeoutSeconds` for grammY API requests. (#863) — thanks @Snaver. -- Telegram: split long captions into media + follow-up text messages. (#907) - thanks @jalehman. -- Telegram: migrate group config when supergroups change chat IDs. (#906) — thanks @sleontenko. -- Messaging: unify markdown formatting + format-first chunking for Slack/Telegram/Signal. (#920) — thanks @TheSethRose. -- Slack: drop Socket Mode events with mismatched `api_app_id`/`team_id`. (#889) — thanks @roshanasingh4. -- Discord: isolate autoThread thread context. (#856) — thanks @davidguttman. -- WhatsApp: fix context isolation using wrong ID (was bot's number, now conversation ID). (#911) — thanks @tristanmanchester. -- WhatsApp: normalize user JIDs with device suffix for allowlist checks in groups. (#838) — thanks @peschee. - -## 2026.1.13 - -### Fixes - -- Postinstall: treat already-applied pnpm patches as no-ops to avoid npm/bun install failures. -- Packaging: pin `@mariozechner/pi-ai` to 0.45.7 and refresh patched dependency to match npm resolution. - -## 2026.1.12-2 - -### Fixes - -- Packaging: include `dist/memory/**` in the npm tarball (fixes `ERR_MODULE_NOT_FOUND` for `dist/memory/index.js`). -- Agents: persist sub-agent registry across gateway restarts and resume announce flow safely. (#831) — thanks @roshanasingh4. -- Agents: strip invalid Gemini thought signatures from OpenRouter history to avoid 400s. (#841, #845) — thanks @MatthieuBizien. - -## 2026.1.12-1 - -### Fixes - -- Packaging: include `dist/channels/**` in the npm tarball (fixes `ERR_MODULE_NOT_FOUND` for `dist/channels/registry.js`). - -## 2026.1.12 - -### Highlights - -- **BREAKING:** rename chat “providers” (Slack/Telegram/WhatsApp/…) to **channels** across CLI/RPC/config; legacy config keys auto-migrate on load (and are written back as `channels.*`). -- Memory: add vector search for agent memories (Markdown-only) with SQLite index, chunking, lazy sync + file watch, and per-agent enablement/fallback. -- Plugins: restore full voice-call plugin parity (Telnyx/Twilio, streaming, inbound policies, tools/CLI). -- Models: add Synthetic provider plus Moonshot Kimi K2 0905 + turbo/thinking variants (with docs). (#811) — thanks @siraht; (#818) — thanks @mickahouan. -- Cron: one-shot schedules accept ISO timestamps (UTC) with optional delete-after-run; cron jobs can target a specific agent (CLI + macOS/Control UI). -- Agents: add compaction mode config with optional safeguard summarization and per-agent model fallbacks. (#700) — thanks @thewilloftheshadow; (#583) — thanks @mitschabaude-bot. - -### New & Improved - -- Memory: add custom OpenAI-compatible embedding endpoints; support OpenAI/local `node-llama-cpp` embeddings with per-agent overrides and provider metadata in tools/CLI. (#819) — thanks @mukhtharcm. -- Memory: new `openclaw memory` CLI plus `memory_search`/`memory_get` tools with snippets + line ranges; index stored under `~/.openclaw/memory/{agentId}.sqlite` with watch-on-by-default. -- Agents: strengthen memory recall guidance; make workspace bootstrap truncation configurable (default 20k) with warnings; add default sub-agent model config. -- Tools/Sandbox: add tool profiles + group shorthands; support tool-policy groups in `tools.sandbox.tools`; drop legacy `memory` shorthand; allow Docker bind mounts via `docker.binds`. (#790) — thanks @akonyer. -- Tools: add provider/model-specific tool policy overrides (`tools.byProvider`) to trim tool exposure per provider. -- Tools: add browser `scrollintoview` action; allow Claude/Gemini tool param aliases; allow thinking `xhigh` for GPT-5.2/Codex with safe downgrades. (#793) — thanks @hsrvc; (#444) — thanks @grp06. -- Gateway/CLI: add Tailscale binary discovery, custom bind mode, and probe auth retry; add `openclaw dashboard` auto-open flow; default native slash commands to `"auto"` with per-provider overrides. (#740) — thanks @jeffersonwarrior. -- Auth/Onboarding: add Chutes OAuth (PKCE + refresh + onboarding choice); normalize API key inputs; default TUI onboarding to `deliver: false`. (#726) — thanks @FrieSei; (#791) — thanks @roshanasingh4. -- Providers: add `discord.allowBots`; trim legacy MiniMax M2 from default catalogs; route MiniMax vision to the Coding Plan VLM endpoint (also accepts `@/path/to/file.png` inputs). (#802) — thanks @zknicker. -- Gateway: allow Tailscale Serve identity headers to satisfy token auth; rebuild Control UI assets when protocol schema is newer. (#823) — thanks @roshanasingh4; (#786) — thanks @meaningfool. -- Heartbeat: default `ackMaxChars` to 300 so short `HEARTBEAT_OK` replies stay internal. - -### Installer - -- Install: run `openclaw doctor --non-interactive` after git installs/updates and nudge daemon restarts when detected. - -### Fixes - -- Doctor: warn on pnpm workspace mismatches, missing Control UI assets, and missing tsx binaries; offer UI rebuilds. -- Tools: apply global tool allow/deny even when agent-specific tool policy is set. -- Models/Providers: treat credential validation failures as auth errors to trigger fallback; normalize `${ENV_VAR}` apiKey values and auto-fill missing provider keys; preserve explicit GitHub Copilot provider config + agent-dir auth profiles. (#822) — thanks @sebslight; (#705) — thanks @TAGOOZ. -- Auth: drop invalid auth profiles from ordering so environment keys can still be used for providers like MiniMax. -- Gemini: normalize Gemini 3 ids to preview variants; strip Gemini CLI tool call/response ids; downgrade missing `thought_signature`; strip Claude `msg_*` thought_signature fields to avoid base64 decode errors. (#795) — thanks @thewilloftheshadow; (#783) — thanks @ananth-vardhan-cn; (#793) — thanks @hsrvc; (#805) — thanks @marcmarg. -- Agents: auto-recover from compaction context overflow by resetting the session and retrying; propagate overflow details from embedded runs so callers can recover. -- MiniMax: strip malformed tool invocation XML; include `MiniMax-VL-01` in implicit provider for image pairing. (#809) — thanks @latitudeki5223. -- Onboarding/Auth: honor `CLAWDBOT_AGENT_DIR` / `PI_CODING_AGENT_DIR` when writing auth profiles (MiniMax). (#829) — thanks @roshanasingh4. -- Anthropic: handle `overloaded_error` with a friendly message and failover classification. (#832) — thanks @danielz1z. -- Anthropic: merge consecutive user turns (preserve newest metadata) before validation to avoid incorrect role errors. (#804) — thanks @ThomsenDrake. -- Messaging: enforce context isolation for message tool sends; keep typing indicators alive during tool execution. (#793) — thanks @hsrvc; (#450, #447) — thanks @thewilloftheshadow. -- Auto-reply: `/status` allowlist behavior, reasoning-tag enforcement on fallback, and system-event enqueueing for elevated/reasoning toggles. (#810) — thanks @mcinteerj. -- System events: include local timestamps when events are injected into prompts. (#245) — thanks @thewilloftheshadow. -- Auto-reply: resolve ambiguous `/model` matches; fix streaming block reply media handling; keep >300 char heartbeat replies instead of dropping. -- Discord/Slack: centralize reply-thread planning; fix autoThread routing + add per-channel autoThread; avoid duplicate listeners; keep reasoning italics intact; allow clearing channel parents via message tool. (#800, #807) — thanks @davidguttman; (#744) — thanks @thewilloftheshadow. -- Telegram: preserve forum topic thread ids, persist polling offsets, respect account bindings in webhook mode, and show typing indicator in General topics. (#727, #739) — thanks @thewilloftheshadow; (#821) — thanks @gumadeiras; (#779) — thanks @azade-c. -- Slack: accept slash commands with or without leading `/` for custom command configs. (#798) — thanks @thewilloftheshadow. -- Cron: persist disabled jobs correctly; accept `jobId` aliases for update/run/remove params. (#205, #252) — thanks @thewilloftheshadow. -- Gateway/CLI: honor `CLAWDBOT_LAUNCHD_LABEL` / `CLAWDBOT_SYSTEMD_UNIT` overrides; `agents.list` respects explicit config; reduce noisy loopback WS logs during tests; run `openclaw doctor --non-interactive` during updates. (#781) — thanks @ronyrus. -- Onboarding/Control UI: refuse invalid configs (run doctor first); quote Windows browser URLs for OAuth; keep chat scroll position unless the user is near the bottom. (#764) — thanks @mukhtharcm; (#794) — thanks @roshanasingh4; (#217) — thanks @thewilloftheshadow. -- Tools/UI: harden tool input schemas for strict providers; drop null-only union variants for Gemini schema cleanup; treat `maxChars: 0` as unlimited; keep TUI last streamed response instead of "(no output)". (#782) — thanks @AbhisekBasu1; (#796) — thanks @gabriel-trigo; (#747) — thanks @thewilloftheshadow. -- Connections UI: polish multi-account account cards. (#816) — thanks @steipete. - -### Maintenance - -- Dependencies: bump Pi packages to 0.45.3 and refresh patched pi-ai. -- Testing: update Vitest + browser-playwright to 4.0.17. -- Docs: add Amazon Bedrock provider notes and link from models/FAQ. - -## 2026.1.11 - -### Highlights - -- Plugins are now first-class: loader + CLI management, plus the new Voice Call plugin. -- Config: modular `$include` support for split config files. (#731) — thanks @pasogott. -- Agents/Pi: reserve compaction headroom so pre-compaction memory writes can run before auto-compaction. -- Agents: automatic pre-compaction memory flush turn to store durable memories before compaction. - -### Changes - -- CLI/Onboarding: simplify MiniMax auth choice to a single M2.1 option. -- CLI: configure section selection now loops until Continue. -- Docs: explain MiniMax vs MiniMax Lightning (speed vs cost) and restore LM Studio example. -- Docs: add Cerebras GLM 4.6/4.7 config example (OpenAI-compatible endpoint). -- Onboarding/CLI: group model/auth choice by provider and label Z.AI as GLM 4.7. -- Onboarding/Docs: add Moonshot AI (Kimi K2) auth choice + config example. -- CLI/Onboarding: prompt to reuse detected API keys for Moonshot/MiniMax/Z.AI/Gemini/Anthropic/OpenCode. -- Auto-reply: add compact `/model` picker (models + available providers) and show provider endpoints in `/model status`. -- Control UI: add Config tab model presets (MiniMax M2.1, GLM 4.7, Kimi) for one-click setup. -- Plugins: add extension loader (tools/RPC/CLI/services), discovery paths, and config schema + Control UI labels (uiHints). -- Plugins: add `openclaw plugins install` (path/tgz/npm), plus `list|info|enable|disable|doctor` UX. -- Plugins: voice-call plugin now real (Twilio/log), adds start/status RPC/CLI/tool + tests. -- Docs: add plugins doc + cross-links from tools/skills/gateway config. -- Docs: add beginner-friendly plugin quick start + expand Voice Call plugin docs. -- Tests: add Docker plugin loader + tgz-install smoke test. -- Tests: extend Docker plugin E2E to cover installing from local folders (`plugins.load.paths`) and `file:` npm specs. -- Tests: add coverage for pre-compaction memory flush settings. -- Tests: modernize live model smoke selection for current releases and enforce tools/images/thinking-high coverage. (#769) — thanks @steipete. -- Agents/Tools: add `apply_patch` tool for multi-file edits (experimental; gated by tools.exec.applyPatch; OpenAI-only). -- Agents/Tools: rename the bash tool to exec (config alias maintained). (#748) — thanks @myfunc. -- Agents: add pre-compaction memory flush config (`agents.defaults.compaction.*`) with a soft threshold + system prompt. -- Config: add `$include` directive for modular config files. (#731) — thanks @pasogott. -- Build: set pnpm minimum release age to 2880 minutes (2 days). (#718) — thanks @dan-dr. -- macOS: prompt to install the global `openclaw` CLI when missing in local mode; install via `openclaw.ai/install-cli.sh` (no onboarding) and use external launchd/CLI instead of the embedded gateway runtime. -- Docs: add gog calendar event color IDs from `gog calendar colors`. (#715) — thanks @mjrussell. -- Cron/CLI: add `--model` flag to cron add/edit commands. (#711) — thanks @mjrussell. -- Cron/CLI: trim model overrides on cron edits and document main-session guidance. (#711) — thanks @mjrussell. -- Skills: bundle `skill-creator` to guide creating and packaging skills. -- Providers: add per-DM history limit overrides (`dmHistoryLimit`) with provider-level config. (#728) — thanks @pkrmf. -- Discord: expose channel/category management actions in the message tool. (#730) — thanks @NicholasSpisak. -- Docs: rename README “macOS app” section to “Apps”. (#733) — thanks @AbhisekBasu1. -- Gateway: require `client.id` in WebSocket connect params; use `client.instanceId` for presence de-dupe; update docs/tests. -- macOS: remove the attach-only gateway setting; local mode now always manages launchd while still attaching to an existing gateway if present. - -### Installer - -- Postinstall: replace `git apply` with builtin JS patcher (works npm/pnpm/bun; no git dependency) plus regression tests. -- Postinstall: skip pnpm patch fallback when the new patcher is active. -- Installer tests: add root+non-root docker smokes, CI workflow to fetch openclaw.ai scripts and run install sh/cli with onboarding skipped. -- Installer UX: support `CLAWDBOT_NO_ONBOARD=1` for non-interactive installs; fix npm prefix on Linux and auto-install git. -- Installer UX: add `install.sh --help` with flags/env and git install hint. -- Installer UX: add `--install-method git|npm` and auto-detect source checkouts (prompt to update git checkout vs migrate to npm). - -### Fixes - -- Models/Onboarding: configure MiniMax (minimax.io) via Anthropic-compatible `/anthropic` endpoint by default (keep `minimax-api` as a legacy alias). -- Models: normalize Gemini 3 Pro/Flash IDs to preview names for live model lookups. (#769) — thanks @steipete. -- CLI: fix guardCancel typing for configure prompts. (#769) — thanks @steipete. -- Gateway/WebChat: include handshake validation details in the WebSocket close reason for easier debugging; preserve close codes. -- Gateway/Auth: send invalid connect responses before closing the handshake; stabilize invalid-connect auth test. -- Gateway: tighten gateway listener detection. -- Control UI: hide onboarding chat when configured and guard the mobile chat sidebar overlay. -- Auth: read Codex keychain credentials and make the lookup platform-aware. -- macOS/Release: avoid bundling dist artifacts in relay builds and generate appcasts from zip-only sources. -- Doctor: surface plugin diagnostics in the report. -- Plugins: treat `plugins.load.paths` directory entries as package roots when they contain `package.json` + `openclaw.extensions`; load plugin packages from config dirs; extract archives without system tar. -- Config: expand `~` in `CLAWDBOT_CONFIG_PATH` and common path-like config fields (including `plugins.load.paths`); guard invalid `$include` paths. (#731) — thanks @pasogott. -- Agents: stop pre-creating session transcripts so first user messages persist in JSONL history. -- Agents: skip pre-compaction memory flush when the session workspace is read-only. -- Auto-reply: ignore inline `/status` directives unless the message is directive-only. -- Auto-reply: align `/think` default display with model reasoning defaults. (#751) — thanks @gabriel-trigo. -- Auto-reply: flush block reply buffers on tool boundaries. (#750) — thanks @sebslight. -- Auto-reply: allow sender fallback for command authorization when `SenderId` is empty (WhatsApp self-chat). (#755) — thanks @juanpablodlc. -- Auto-reply: treat whitespace-only sender ids as missing for command authorization (WhatsApp self-chat). (#766) — thanks @steipete. -- Heartbeat: refresh prompt text for updated defaults. -- Agents/Tools: use PowerShell on Windows to capture system utility output. (#748) — thanks @myfunc. -- Docker: tolerate unset optional env vars in docker-setup.sh under strict mode. (#725) — thanks @petradonka. -- CLI/Update: preserve base environment when passing overrides to update subprocesses. (#713) — thanks @danielz1z. -- Agents: treat message tool errors as failures so fallback replies still send; require `to` + `message` for `action=send`. (#717) — thanks @theglove44. -- Agents: preserve reasoning items on tool-only turns. -- Agents/Subagents: wait for completion before announcing, align wait timeout with run timeout, and make announce prompts more emphatic. -- Agents: route subagent transcripts to the target agent sessions directory and add regression coverage. (#708) — thanks @xMikeMickelson. -- Agents/Tools: preserve action enums when flattening tool schemas. (#708) — thanks @xMikeMickelson. -- Gateway/Agents: canonicalize main session aliases for store writes and add regression coverage. (#709) — thanks @xMikeMickelson. -- Agents: reset sessions and retry when auto-compaction overflows instead of crashing the gateway. -- Providers/Telegram: normalize command mentions for consistent parsing. (#729) — thanks @obviyus. -- Providers: skip DM history limit handling for non-DM sessions. (#728) — thanks @pkrmf. -- Sandbox: fix non-main mode incorrectly sandboxing the main DM session and align `/status` runtime reporting with effective sandbox state. -- Sandbox/Gateway: treat `agent::main` as a main-session alias when `session.mainKey` is customized (backwards compatible). -- Auto-reply: fast-path allowlisted slash commands (inline `/help`/`/commands`/`/status`/`/whoami` stripped before model). - -## 2026.1.10 - -### Highlights - -- CLI: `openclaw status` now table-based + shows OS/update/gateway/daemon/agents/sessions; `status --all` adds a full read-only debug report (tables, log tails, Tailscale summary, and scan progress via OSC-9 + spinner). -- CLI Backends: add Codex CLI fallback with resume support (text output) and JSONL parsing for new runs, plus a live CLI resume probe. -- CLI: add `openclaw update` (safe-ish git checkout update) + `--update` shorthand. (#673) — thanks @fm1randa. -- Gateway: add OpenAI-compatible `/v1/chat/completions` HTTP endpoint (auth, SSE streaming, per-agent routing). (#680). - -### Changes - -- Onboarding/Models: add first-class Z.AI (GLM) auth choice (`zai-api-key`) + `--zai-api-key` flag. -- CLI/Onboarding: add OpenRouter API key auth option in configure/onboard. (#703) — thanks @mteam88. -- Agents: add human-delay pacing between block replies (modes: off/natural/custom, per-agent configurable). (#446) — thanks @tony-freedomology. -- Agents/Browser: add `browser.target` (sandbox/host/custom) with sandbox host-control gating via `agents.defaults.sandbox.browser.allowHostControl`, allowlists for custom control URLs/hosts/ports, and expand browser tool docs (remote control, profiles, internals). -- Onboarding/Models: add catalog-backed default model picker to onboarding + configure. (#611) — thanks @jonasjancarik. -- Agents/OpenCode Zen: update fallback models + defaults, keep legacy alias mappings. (#669) — thanks @magimetal. -- CLI: add `openclaw reset` and `openclaw uninstall` flows (interactive + non-interactive) plus docker cleanup smoke test. -- Providers: move provider wiring to a plugin architecture. (#661). -- Providers: unify group history context wrappers across providers with per-provider/per-account `historyLimit` overrides (fallback to `messages.groupChat.historyLimit`). Set `0` to disable. (#672). -- Gateway/Heartbeat: optionally deliver heartbeat `Reasoning:` output (`agents.defaults.heartbeat.includeReasoning`). (#690) -- Docker: allow optional home volume + extra bind mounts in `docker-setup.sh`. (#679) — thanks @gabriel-trigo. - -### Fixes - -- Auto-reply: suppress draft/typing streaming for `NO_REPLY` (silent system ops) so it doesn’t leak partial output. -- CLI/Status: expand tables to full terminal width; clarify provider setup vs runtime warnings; richer per-provider detail; token previews in `status` while keeping `status --all` redacted; add troubleshooting link footer; keep log tails pasteable; show gateway auth used when reachable; surface provider runtime errors (Signal/iMessage/Slack); harden `tailscale status --json` parsing; make `status --all` scan progress determinate; and replace the footer with a 3-line “Next steps” recommendation (share/debug/probe). -- CLI/Gateway: clarify that `openclaw gateway status` reports RPC health (connect + RPC) and shows RPC failures separately from connect failures. -- CLI/Update: gate progress spinner on stdout TTY and align clean-check step label. (#701) — thanks @bjesuiter. -- Telegram: add `/whoami` + `/id` commands to reveal sender id for allowlists; allow `@username` and prefixed ids in `allowFrom` prompts (with stability warning). -- Heartbeat: strip markup-wrapped `HEARTBEAT_OK` so acks don’t leak to external providers (e.g., Telegram). -- Control UI: stop auto-writing `telegram.groups["*"]` and warn/confirm before enabling wildcard groups. -- WhatsApp: send ack reactions only for handled messages and ignore legacy `messages.ackReaction` (doctor copies to `whatsapp.ackReaction`). (#629) — thanks @pasogott. -- Sandbox/Skills: mirror skills into sandbox workspaces for read-only mounts so SKILL.md stays accessible. -- Terminal/Table: ANSI-safe wrapping to prevent table clipping/color loss; add regression coverage. -- Docker: allow optional apt packages during image build and document the build arg. (#697) — thanks @gabriel-trigo. -- Gateway/Heartbeat: deliver reasoning even when the main heartbeat reply is `HEARTBEAT_OK`. (#694) — thanks @antons. -- Agents/Pi: inject config `temperature`/`maxTokens` into streaming without replacing the session streamFn; cover with live maxTokens probe. (#732) — thanks @peschee. -- macOS: clear unsigned launchd overrides on signed restarts and warn via doctor when attach-only/disable markers are set. (#695) — thanks @jeffersonwarrior. -- Agents: enforce single-writer session locks and drop orphan tool results to prevent tool-call ID failures (MiniMax/Anthropic-compatible APIs). -- Docs: make `openclaw status` the first diagnostic step, clarify `status --deep` behavior, and document `/whoami` + `/id`. -- Docs/Testing: clarify live tool+image probes and how to list your testable `provider/model` ids. -- Tests/Live: make gateway bash+read probes resilient to provider formatting while still validating real tool calls. -- WhatsApp: detect @lid mentions in groups using authDir reverse mapping + resolve self JID E.164 for mention gating. (#692) — thanks @peschee. -- Gateway/Auth: default to token auth on loopback during onboarding, add doctor token generation flow, and tighten audio transcription config to Whisper-only. -- Providers: dedupe inbound messages across providers to avoid duplicate LLM runs on redeliveries/reconnects. (#689) — thanks @adam91holt. -- Agents: strip ``/`` tags from hidden reasoning output and cover tag variants in tests. (#688) — thanks @theglove44. -- macOS: save model picker selections as normalized provider/model IDs and keep manual entries aligned. (#683) — thanks @benithors. -- Agents: recognize "usage limit" errors as rate limits for failover. (#687) — thanks @evalexpr. -- CLI: avoid success message when daemon restart is skipped. (#685) — thanks @carlulsoe. -- Commands: disable `/config` + `/debug` by default; gate via `commands.config`/`commands.debug` and hide from native registration/help output. -- Agents/System: clarify that sub-agents remain sandboxed and cannot use elevated host access. -- Gateway: disable the OpenAI-compatible `/v1/chat/completions` endpoint by default; enable via `gateway.http.endpoints.chatCompletions.enabled=true`. -- macOS: stabilize bridge tunnels, guard invoke senders on disconnect, and drain stdout/stderr to avoid deadlocks. (#676) — thanks @ngutman. -- Agents/System: clarify sandboxed runtime in system prompt and surface elevated availability when sandboxed. -- Auto-reply: prefer `RawBody` for command/directive parsing (WhatsApp + Discord) and prevent fallback runs from clobbering concurrent session updates. (#643) — thanks @mcinteerj. -- WhatsApp: fix group reactions by preserving message IDs and sender JIDs in history; normalize participant phone numbers to JIDs in outbound reactions. (#640) — thanks @mcinteerj. -- WhatsApp: expose group participant IDs to the model so reactions can target the right sender. -- Cron: `wakeMode: "now"` waits for heartbeat completion (and retries when the main lane is busy). (#666) — thanks @roshanasingh4. -- Agents/OpenAI: fix Responses tool-only → follow-up turn handling (avoid standalone `reasoning` items that trigger 400 “required following item”) and replay reasoning items in Responses/Codex Responses history for tool-call-only turns. -- Sandbox: add `openclaw sandbox explain` (effective policy inspector + fix-it keys); improve “sandbox jail” tool-policy/elevated errors with actionable config key paths; link to docs. -- Hooks/Gmail: keep Tailscale serve path at `/` while preserving the public path. (#668) — thanks @antons. -- Hooks/Gmail: allow Tailscale target URLs to preserve internal serve paths. -- Auth: update Claude Code keychain credentials in-place during refresh sync; share JSON file helpers; add CLI fallback coverage. -- Auth: throttle external CLI credential syncs (Claude/Codex), reduce Keychain reads, and skip sync when cached credentials are still fresh. -- CLI: respect `CLAWDBOT_STATE_DIR` for node pairing + voice wake settings storage. (#664) — thanks @azade-c. -- Onboarding/Gateway: persist non-interactive gateway token auth in config; add WS wizard + gateway tool-calling regression coverage. -- Gateway/Control UI: make `chat.send` non-blocking, wire Stop to `chat.abort`, and treat `/stop` as an out-of-band abort. (#653) -- Gateway/Control UI: allow `chat.abort` without `runId` (abort active runs), suppress post-abort chat streaming, and prune stuck chat runs. (#653) -- Gateway/Control UI: sniff image attachments for chat.send, drop non-images, and log mismatches. (#670) — thanks @cristip73. -- macOS: force `restart-mac.sh --sign` to require identities and keep bundled Node signed for relay verification. (#580) — thanks @jeffersonwarrior. -- Gateway/Agent: accept image attachments on `agent` (multimodal message) and add live gateway image probe (`CLAWDBOT_LIVE_GATEWAY_IMAGE_PROBE=1`). -- CLI: `openclaw sessions` now includes `elev:*` + `usage:*` flags in the table output. -- CLI/Pairing: accept positional provider for `pairing list|approve` (npm-run compatible); update docs/bot hints. -- Branding: normalize legacy casing/branding to “OpenClaw” (CLI, status, docs). -- Auto-reply: fix native `/model` not updating the actual chat session (Telegram/Slack/Discord). (#646) -- Doctor: offer to run `openclaw update` first on git installs (keeps doctor output aligned with latest). -- Doctor: avoid false legacy workspace warning when install dir is `~/openclaw`. (#660) -- iMessage: fix reasoning persistence across DMs; avoid partial/duplicate replies when reasoning is enabled. (#655) — thanks @antons. -- Models/Auth: allow MiniMax API configs without `models.providers.minimax.apiKey` (auth profiles / `MINIMAX_API_KEY`). (#656) — thanks @mneves75. -- Agents: avoid duplicate replies when the message tool sends. (#659) — thanks @mickahouan. -- Agents: harden Cloud Code Assist tool ID sanitization (toolUse/toolCall/toolResult) and scrub extra JSON Schema constraints. (#665) — thanks @sebslight. -- Agents: sanitize tool results + Cloud Code Assist tool IDs at context-build time (prevents mid-run strict-provider request rejects). -- Agents/Tools: resolve workspace-relative Read/Write/Edit paths; align bash default cwd. (#642) — thanks @mukhtharcm. -- Discord: include forwarded message snapshots in agent session context. (#667) — thanks @rubyrunsstuff. -- Telegram: add `telegram.draftChunk` to tune draft streaming chunking for `streamMode: "block"`. (#667) — thanks @rubyrunsstuff. -- Tests/Agents: add regression coverage for workspace tool path resolution and bash cwd defaults. -- iOS/Android: enable stricter concurrency/lint checks; fix Swift 6 strict concurrency issues + Android lint errors (ExifInterface, obsolete SDK check). (#662) — thanks @KristijanJovanovski. -- Auth: read Codex CLI keychain tokens on macOS before falling back to `~/.codex/auth.json`, preventing stale refresh tokens from breaking gateway live tests. -- Security/Exec approvals: reject shell command substitution (`$()` and backticks) inside double quotes to prevent exec allowlist bypass when exec allowlist mode is explicitly enabled (the default configuration does not use this mode). Thanks @simecek. -- iOS/macOS: share `AsyncTimeout`, require explicit `bridgeStableID` on connect, and harden tool display defaults (avoids missing-resource label fallbacks). -- Telegram: serialize media-group processing to avoid missed albums under load. -- Signal: handle `dataMessage.reaction` events (signal-cli SSE) to avoid broken attachment errors. (#637) — thanks @neist. -- Docs: showcase entries for ParentPay, R2 Upload, iOS TestFlight, and Oura Health. (#650) — thanks @henrino3. -- Agents: repair session transcripts by dropping duplicate tool results across the whole history (unblocks Anthropic-compatible APIs after retries). -- Tests/Live: reset the gateway session between model runs to avoid cross-provider transcript incompatibilities (notably OpenAI Responses reasoning replay rules). - -## 2026.1.9 - -### Highlights - -- Microsoft Teams provider: polling, attachments, outbound CLI send, per-channel policy. -- Models/Auth expansion: OpenCode Zen + MiniMax API onboarding; token auth profiles + auth order; OAuth health in doctor/status. -- CLI/Gateway UX: message subcommands, gateway discover/status/SSH, /config + /debug, sandbox CLI. -- Provider reliability sweep: WhatsApp contact cards/targets, Telegram audio-as-voice + streaming, Signal reactions, Slack threading, Discord stability. -- Auto-reply + status: block-streaming controls, reasoning handling, usage/cost reporting. -- Control UI/TUI: queued messages, session links, reasoning view, mobile polish, logs UX. - -### Breaking - -- CLI: `openclaw message` now subcommands (`message send|poll|...`) and requires `--provider` unless only one provider configured. -- Commands/Tools: `/restart` and gateway restart tool disabled by default; enable with `commands.restart=true`. - -### New Features and Changes - -- Models/Auth: OpenCode Zen onboarding (#623) — thanks @magimetal; MiniMax Anthropic-compatible API + hosted onboarding (#590, #495) — thanks @mneves75, @tobiasbischoff. -- Models/Auth: setup-token + token auth profiles; `openclaw models auth order {get,set,clear}`; per-agent auth candidates in `/model status`; OAuth expiry checks in doctor/status. -- Agent/System: claude-cli runner; `session_status` tool (and sandbox allow); adaptive context pruning default; system prompt messaging guidance + no auto self-update; eligible skills list injection; sub-agent context trimmed. -- Commands: `/commands` list; `/models` alias; `/usage` alias; `/debug` runtime overrides + effective config view; `/config` chat updates + `/config get`; `config --section`. -- CLI/Gateway: unified message tool + message subcommands; gateway discover (local + wide-area DNS-SD) with JSON/timeout; gateway status human-readable + JSON + SSH loopback; wide-area records include gatewayPort/sshPort/cliPath + tailnet DNS fallback. -- CLI UX: logs output modes (pretty/plain/JSONL) + colorized health/daemon output; global `--no-color`; lobster palette in onboarding/config. -- Dev ergonomics: gateway `--dev/--reset` + dev profile auto-config; C-3PO dev templates; dev gateway/TUI helper scripts. -- Sandbox/Workspace: sandbox list/recreate commands; sync skills into sandbox workspace; sandbox browser auto-start. -- Config/Onboarding: inline env vars; OpenAI API key flow to shared `~/.openclaw/.env`; Opus 4.5 default prompt for Anthropic auth; QuickStart auto-install gateway (Node-only) + provider picker tweaks + skip-systemd flags; TUI bootstrap prompt (`tui --message`); remove Bun runtime choice. -- Providers: Microsoft Teams provider (polling, attachments, outbound sends, requireMention, config reload/DM policy). (#404) — thanks @onutc -- Providers: WhatsApp broadcast groups for multi-agent replies (#547) — thanks @pasogott; inbound media size cap configurable (#505) — thanks @koala73; identity-based message prefixes (#578) — thanks @p6l-richard. -- Providers: Telegram inline keyboard buttons + callback payload routing (#491) — thanks @azade-c; cron topic delivery targets (#474/#478) — thanks @mitschabaude-bot, @nachoiacovino; `[[audio_as_voice]]` tag support (#490) — thanks @jarvis-medmatic. -- Providers: Signal reactions + notifications with allowlist support. -- Status/Usage: /status cost reporting + `/cost` lines; auth profile snippet; provider usage windows. -- Control UI: mobile responsiveness (#558) — thanks @carlulsoe; queued messages + Enter-to-send (#527) — thanks @YuriNachos; session links (#471) — thanks @HazAT; reasoning view; skill install feedback (#445) — thanks @pkrmf; chat layout refresh (#475) — thanks @rahthakor; docs link + new session button; drop explicit `ui:install`. -- TUI: agent picker + agents list RPC; improved status line. -- Doctor/Daemon: audit/repair flows, permissions checks, supervisor config audits; provider status probes + warnings for Discord intents and Telegram privacy; last activity timestamps; gateway restart guidance. -- Docs: Hetzner Docker VPS guide + cross-links (#556/#592) — thanks @Iamadig; Ansible guide (#545) — thanks @pasogott; provider troubleshooting index; hook parameter expansion (#532) — thanks @mcinteerj; model allowlist notes; OAuth deep dive; showcase refresh. -- Apps/Branding: refreshed iOS/Android/macOS icons (#521) — thanks @fishfisher. - -### Fixes - -- Packaging: include MS Teams send module in npm tarball. -- Sandbox/Browser: auto-start CDP endpoint; proxy CDP out of container for attachOnly; relax Bun fetch typing; align sandbox list output with config images. -- Agents/Runtime: gate heartbeat prompt to default sessions; /stop aborts between tool calls; require explicit system-event session keys; guard small context windows; fix model fallback stringification; sessions_spawn inherits provider; failover on billing/credits; respect auth cooldown ordering; restore Anthropic OAuth tool dispatch + tool-name bypass; avoid OpenAI invalid reasoning replay; harden Gmail hook model defaults. -- Agent history/schema: strip/skip empty assistant/error blocks to prevent session corruption/Claude 400s; scrub unsupported JSON Schema keywords + sanitize tool call IDs for Cloud Code Assist; simplify Gemini-compatible tool/session schemas; require raw for config.apply. -- Auto-reply/Streaming: default audioAsVoice false; preserve audio_as_voice propagation + buffer audio blocks + guard voice notes; block reply ordering (timeout) + forced-block fence-safe; avoid chunk splits inside parentheses + fence-close breaks + invalid UTF-16 truncation; preserve inline directive spacing + allow whitespace in reply tags; filter NO_REPLY prefixes + normalize routed replies; suppress leakage with separate Reasoning; block streaming defaults (off by default, minChars/idle tuning) + coalesced blocks; dedupe followup queue; restore explicit responsePrefix default. -- Status/Commands: provider prefix in /status model display; usage filtering + provider mapping; auth label + usage snapshots (claude-cli fallback + optional claude.ai); show Verbose/Elevated only when enabled; compact usage/cost line + restore emoji-rich status; /status in directive-only + multi-directive handling; mention-bypass elevated handling; surface provider usage errors; wire /usage to /status; restore hidden gateway-daemon alias; fallback /model list when catalog unavailable. -- WhatsApp: vCard/contact cards (prefer FN, include numbers, show all contacts, keep summary counts, better empty summaries); preserve group JIDs + normalize targets; resolve @lid mappings/JIDs (Baileys/auth-dir) + inbound mapping; route queued replies to sender; improve web listener errors + remove provider name from errors; record outbound activity account id; fix web media fetch errors; broadcast group history consistency. -- Telegram: keep streamMode draft-only; long-poll conflict retries + update dedupe; grammY fetch mismatch fixes + restrict native fetch to Bun; suppress getUpdates stack traces; include user id in pairing; audio_as_voice handling fixes. -- Discord/Slack: thread context helpers + forum thread starters; avoid category parent overrides; gateway reconnect logs + HELLO timeout + stop provider after reconnect exhaustion; DM recipient parsing for numeric IDs; remove incorrect limited warning; reply threading + mrkdwn edge cases; remove ack reactions after reply; gateway debug event visibility. -- Signal: reaction handling safety; own-reaction matching (uuid+phone); UUID-only senders accepted; ignore reaction-only messages. -- MS Teams: download image attachments reliably; fix top-level replies; stop on shutdown + honor chunk limits; normalize poll providers/deps; pairing label fixes. -- iMessage: isolate group-ish threads by chat_id. -- Gateway/Daemon/Doctor: atomic config writes; repair gateway service entrypoint + install switches; non-interactive legacy migrations; systemd unit alignment + KillMode=process; node bridge keepalive/pings; Launch at Login persistence; bundle MoltbotKit resources + Swift 6.2 compat dylib; relay version check + remove smoke test; regen Swift GatewayModels + keep agent provider string; cron jobId alias + channel alias migration + main session key normalization; heartbeat Telegram accountId resolution; avoid WhatsApp fallback for internal runs; gateway listener error wording; serveBaseUrl param; honor gateway --dev; fix wide-area discovery updates; align agents.defaults schema; provider account metadata in daemon status; refresh Carbon patch for gateway fixes; restore doctor prompter initialValue handling. -- Control UI/TUI: persist per-session verbose off + hide tool cards; logs tab opens at bottom; relative asset paths + landing cleanup; session labels lookup/persistence; stop pinning main session in recents; start logs at bottom; TUI status bar refresh + timeout handling + hide reasoning label when off. -- Onboarding/Configure: QuickStart single-select provider picker; avoid Codex CLI false-expiry warnings; clarify WhatsApp owner prompt; fix Minimax hosted onboarding (agents.defaults + msteams heartbeat target); remove configure Control UI prompt; honor gateway --dev flag. - -### Maintenance - -- Dependencies: bump pi-\* stack to 0.42.2. -- Dependencies: Pi 0.40.0 bump (#543) — thanks @mcinteerj. -- Build: Docker build cache layer (#605) — thanks @zknicker. - -- Auth: enable OAuth token refresh for Claude Code CLI credentials (`anthropic:claude-cli`) with bidirectional sync back to Claude Code storage (file on Linux/Windows, Keychain on macOS). This allows long-running agents to operate autonomously without manual re-authentication (#654 — thanks @radek-paclt). - -## 2026.1.8 - -### Highlights - -- Security: DMs locked down by default across providers; pairing-first + allowlist guidance. -- Sandbox: per-agent scope defaults + workspace access controls; tool/session isolation tuned. -- Agent loop: compaction, pruning, streaming, and error handling hardened. -- Providers: Telegram/WhatsApp/Discord/Slack reliability, threading, reactions, media, and retries improved. -- Control UI: logs tab, streaming stability, focus mode, and large-output rendering fixes. -- CLI/Gateway/Doctor: daemon/logs/status, auth migration, and diagnostics significantly expanded. - -### Breaking - -- **SECURITY (update ASAP):** inbound DMs are now **locked down by default** on Telegram/WhatsApp/Signal/iMessage/Discord/Slack. - - Previously, if you didn’t configure an allowlist, your bot could be **open to anyone** (especially discoverable Telegram bots). - - New default: DM pairing (`dmPolicy="pairing"` / `discord.dm.policy="pairing"` / `slack.dm.policy="pairing"`). - - To keep old “open to everyone” behavior: set `dmPolicy="open"` and include `"*"` in the relevant `allowFrom` (Discord/Slack: `discord.dm.allowFrom` / `slack.dm.allowFrom`). - - Approve requests via `openclaw pairing list ` + `openclaw pairing approve `. -- Sandbox: default `agent.sandbox.scope` to `"agent"` (one container/workspace per agent). Use `"session"` for per-session isolation; `"shared"` disables cross-session isolation. -- Timestamps in agent envelopes are now UTC (compact `YYYY-MM-DDTHH:mmZ`); removed `messages.timestampPrefix`. Add `agent.userTimezone` to tell the model the user’s local time (system prompt only). -- Model config schema changes (auth profiles + model lists); doctor auto-migrates and the gateway rewrites legacy configs on startup. -- Commands: gate all slash commands to authorized senders; add `/compact` to manually compact session context. -- Groups: `whatsapp.groups`, `telegram.groups`, and `imessage.groups` now act as allowlists when set. Add `"*"` to keep allow-all behavior. -- Auto-reply: removed `autoReply` from Discord/Slack/Telegram channel configs; use `requireMention` instead (Telegram topics now support `requireMention` overrides). -- CLI: remove `update`, `gateway-daemon`, `gateway {install|uninstall|start|stop|restart|daemon status|wake|send|agent}`, and `telegram` commands; move `login/logout` to `providers login/logout` (top-level aliases hidden); use `daemon` for service control, `send`/`agent`/`wake` for RPC, and `nodes canvas` for canvas ops. - -### Fixes - -- **CLI/Gateway/Doctor:** daemon runtime selection + improved logs/status/health/errors; auth/password handling for local CLI; richer close/timeout details; auto-migrate legacy config/sessions/state; integrity checks + repair prompts; `--yes`/`--non-interactive`; `--deep` gateway scans; better restart/service hints. -- **Agent loop + compaction:** compaction/pruning tuning, overflow handling, safer bootstrap context, and per-provider threading/confirmations; opt-in tool-result pruning + compact tracking. -- **Sandbox + tools:** per-agent sandbox overrides, workspaceAccess controls, session tool visibility, tool policy overrides, process isolation, and tool schema/timeout/reaction unification. -- **Providers (Telegram/WhatsApp/Discord/Slack/Signal/iMessage):** retry/backoff, threading, reactions, media groups/attachments, mention gating, typing behavior, and error/log stability; long polling + forum topic isolation for Telegram. -- **Gateway/CLI UX:** `openclaw logs`, cron list colors/aliases, docs search, agents list/add/delete flows, status usage snapshots, runtime/auth source display, and `/status`/commands auth unification. -- **Control UI/Web:** logs tab, focus mode polish, config form resilience, streaming stability, tool output caps, windowed chat history, and reconnect/password URL auth. -- **macOS/Android/TUI/Build:** macOS gateway races, QR bundling, JSON5 config safety, Voice Wake hardening; Android EXIF rotation + APK naming/versioning; TUI key handling; tooling/bundling fixes. -- **Packaging/compat:** npm dist folder coverage, Node 25 qrcode-terminal import fixes, Bun/Playwright/WebSocket patches, and Docker Bun install. -- **Docs:** new FAQ/ClawHub/config examples/showcase entries and clarified auth, sandbox, and systemd docs. - -### Maintenance - -- Skills additions (Himalaya email, CodexBar, 1Password). -- Dependency refreshes (pi-\* stack, Slack SDK, discord-api-types, file-type, zod, Biome, Vite). - -## 2026.1.5 - -### Highlights - -- Models: add image-specific model config (`agent.imageModel` + fallbacks) and scan support. -- Agent tools: new `image` tool routed to the image model (when configured). -- Config: default model shorthands (`opus`, `sonnet`, `gpt`, `gpt-mini`, `gemini`, `gemini-flash`). -- Docs: document built-in model shorthands + precedence (user config wins). -- Bun: optional local install/build workflow without maintaining a Bun lockfile (see `docs/bun.md`). - -### Fixes - -- Control UI: render Markdown in tool result cards. -- Control UI: prevent overlapping action buttons in Discord guild rules on narrow layouts. -- Android: tapping the foreground service notification brings the app to the front. (#179) — thanks @Syhids -- Cron tool uses `id` for update/remove/run/runs (aligns with gateway params). (#180) — thanks @adamgall -- Control UI: chat view uses page scroll with sticky header/sidebar and fixed composer (no inner scroll frame). -- macOS: treat location permission as always-only to avoid iOS-only enums. (#165) — thanks @Nachx639 -- macOS: make generated gateway protocol models `Sendable` for Swift 6 strict concurrency. (#195) — thanks @andranik-sahakyan -- macOS: bundle QR code renderer modules so DMG gateway boot doesn't crash on missing qrcode-terminal vendor files. -- macOS: parse JSON5 config safely to avoid wiping user settings when comments are present. -- WhatsApp: suppress typing indicator during heartbeat background tasks. (#190) — thanks @mcinteerj -- WhatsApp: mark offline history sync messages as read without auto-reply. (#193) — thanks @mcinteerj -- Discord: avoid duplicate replies when a provider emits late streaming `text_end` events (OpenAI/GPT). -- CLI: use tailnet IP for local gateway calls when bind is tailnet/auto (fixes #176). -- Env: load global `$OPENCLAW_STATE_DIR/.env` (`~/.openclaw/.env`) as a fallback after CWD `.env`. -- Env: optional login-shell env fallback (opt-in; imports expected keys without overriding existing env). -- Agent tools: OpenAI-compatible tool JSON Schemas (fix `browser`, normalize union schemas). -- Onboarding: when running from source, auto-build missing Control UI assets (`bun run ui:build`). -- Discord/Slack: route reaction + system notifications to the correct session (no main-session bleed). -- Agent tools: honor `agent.tools` allow/deny policy even when sandbox is off. -- Discord: avoid duplicate replies when OpenAI emits repeated `message_end` events. -- Commands: unify /status (inline) and command auth across providers; group bypass for authorized control commands; remove Discord /clawd slash handler. -- CLI: run `openclaw agent` via the Gateway by default; use `--local` to force embedded mode. diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 120000 index c3170642553..00000000000 --- a/CLAUDE.md +++ /dev/null @@ -1 +0,0 @@ -AGENTS.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 2beaeeba290..00000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,147 +0,0 @@ -# Contributing to OpenClaw - -Welcome to the lobster tank! 🦞 - -## Quick Links - -- **GitHub:** https://github.com/openclaw/openclaw -- **Vision:** [`VISION.md`](VISION.md) -- **Discord:** https://discord.gg/qkhbAGHRBT -- **X/Twitter:** [@steipete](https://x.com/steipete) / [@openclaw](https://x.com/openclaw) - -## Maintainers - -- **Peter Steinberger** - Benevolent Dictator - - GitHub: [@steipete](https://github.com/steipete) · X: [@steipete](https://x.com/steipete) - -- **Shadow** - Discord subsystem, Discord admin, Clawhub, all community moderation - - GitHub: [@thewilloftheshadow](https://github.com/thewilloftheshadow) · X: [@4shad0wed](https://x.com/4shad0wed) - -- **Vignesh** - Memory (QMD), formal modeling, TUI, IRC, and Lobster - - GitHub: [@vignesh07](https://github.com/vignesh07) · X: [@\_vgnsh](https://x.com/_vgnsh) - -- **Jos** - Telegram, API, Nix mode - - GitHub: [@joshp123](https://github.com/joshp123) · X: [@jjpcodes](https://x.com/jjpcodes) - -- **Ayaan Zaidi** - Telegram subsystem, iOS app - - GitHub: [@obviyus](https://github.com/obviyus) · X: [@0bviyus](https://x.com/0bviyus) - -- **Tyler Yust** - Agents/subagents, cron, BlueBubbles, macOS app - - GitHub: [@tyler6204](https://github.com/tyler6204) · X: [@tyleryust](https://x.com/tyleryust) - -- **Mariano Belinky** - iOS app, Security - - GitHub: [@mbelinky](https://github.com/mbelinky) · X: [@belimad](https://x.com/belimad) - -- **Vincent Koc** - Agents, Telemetry, Hooks, Security - - GitHub: [@vincentkoc](https://github.com/vincentkoc) · X: [@vincent_koc](https://x.com/vincent_koc) - -- **Seb Slight** - Docs, Agent Reliability, Runtime Hardening - - GitHub: [@sebslight](https://github.com/sebslight) · X: [@sebslig](https://x.com/sebslig) - -- **Christoph Nakazawa** - JS Infra - - GitHub: [@cpojer](https://github.com/cpojer) · X: [@cnakazawa](https://x.com/cnakazawa) - -- **Gustavo Madeira Santana** - Multi-agents, CLI, web UI - - GitHub: [@gumadeiras](https://github.com/gumadeiras) · X: [@gumadeiras](https://x.com/gumadeiras) - -- **Onur Solmaz** - Agents, dev workflows, ACP integrations, MS Teams - - GitHub: [@onutc](https://github.com/onutc), [@osolmaz](https://github.com/osolmaz) · X: [@onusoz](https://x.com/onusoz) - -## How to Contribute - -1. **Bugs & small fixes** → Open a PR! -2. **New features / architecture** → Start a [GitHub Discussion](https://github.com/openclaw/openclaw/discussions) or ask in Discord first -3. **Questions** → Discord #setup-help - -## Before You PR - -- Test locally with your OpenClaw instance -- Run tests: `pnpm build && pnpm check && pnpm test` -- Ensure CI checks pass -- Keep PRs focused (one thing per PR; do not mix unrelated concerns) -- Describe what & why - -## Control UI Decorators - -The Control UI uses Lit with **legacy** decorators (current Rollup parsing does not support -`accessor` fields required for standard decorators). When adding reactive fields, keep the -legacy style: - -```ts -@state() foo = "bar"; -@property({ type: Number }) count = 0; -``` - -The root `tsconfig.json` is configured for legacy decorators (`experimentalDecorators: true`) -with `useDefineForClassFields: false`. Avoid flipping these unless you are also updating the UI -build tooling to support standard decorators. - -## AI/Vibe-Coded PRs Welcome! 🤖 - -Built with Codex, Claude, or other AI tools? **Awesome - just mark it!** - -Please include in your PR: - -- [ ] Mark as AI-assisted in the PR title or description -- [ ] Note the degree of testing (untested / lightly tested / fully tested) -- [ ] Include prompts or session logs if possible (super helpful!) -- [ ] Confirm you understand what the code does - -AI PRs are first-class citizens here. We just want transparency so reviewers know what to look for. - -## Current Focus & Roadmap 🗺 - -We are currently prioritizing: - -- **Stability**: Fixing edge cases in channel connections (WhatsApp/Telegram). -- **UX**: Improving the onboarding wizard and error messages. -- **Skills**: For skill contributions, head to [ClawHub](https://clawhub.ai/) — the community hub for OpenClaw skills. -- **Performance**: Optimizing token usage and compaction logic. - -Check the [GitHub Issues](https://github.com/openclaw/openclaw/issues) for "good first issue" labels! - -## Maintainers - -We're selectively expanding the maintainer team. -If you're an experienced contributor who wants to help shape OpenClaw's direction — whether through code, docs, or community — we'd like to hear from you. - -Being a maintainer is a responsibility, not an honorary title. We expect active, consistent involvement — triaging issues, reviewing PRs, and helping move the project forward. - -Still interested? Email contributing@openclaw.ai with: - -- Links to your PRs on OpenClaw (if you don't have any, start there first) -- Links to open source projects you maintain or actively contribute to -- Your GitHub, Discord, and X/Twitter handles -- A brief intro: background, experience, and areas of interest -- Languages you speak and where you're based -- How much time you can realistically commit - -We welcome people across all skill sets — engineering, documentation, community management, and more. -We review every human-only-written application carefully and add maintainers slowly and deliberately. -Please allow a few weeks for a response. - -## Report a Vulnerability - -We take security reports seriously. Report vulnerabilities directly to the repository where the issue lives: - -- **Core CLI and gateway** — [openclaw/openclaw](https://github.com/openclaw/openclaw) -- **macOS desktop app** — [openclaw/openclaw](https://github.com/openclaw/openclaw) (apps/macos) -- **iOS app** — [openclaw/openclaw](https://github.com/openclaw/openclaw) (apps/ios) -- **Android app** — [openclaw/openclaw](https://github.com/openclaw/openclaw) (apps/android) -- **ClawHub** — [openclaw/clawhub](https://github.com/openclaw/clawhub) -- **Trust and threat model** — [openclaw/trust](https://github.com/openclaw/trust) - -For issues that don't fit a specific repo, or if you're unsure, email **security@openclaw.ai** and we'll route it. - -### Required in Reports - -1. **Title** -2. **Severity Assessment** -3. **Impact** -4. **Affected Component** -5. **Technical Reproduction** -6. **Demonstrated Impact** -7. **Environment** -8. **Remediation Advice** - -Reports without reproduction steps, demonstrated impact, and remediation advice will be deprioritized. Given the volume of AI-generated scanner findings, we must ensure we're receiving vetted reports from researchers who understand the issues. diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 255340cb02b..00000000000 --- a/Dockerfile +++ /dev/null @@ -1,65 +0,0 @@ -FROM node:22-bookworm@sha256:cd7bcd2e7a1e6f72052feb023c7f6b722205d3fcab7bbcbd2d1bfdab10b1e935 - -# Install Bun (required for build scripts) -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:${PATH}" - -RUN corepack enable - -WORKDIR /app -RUN chown node:node /app - -ARG OPENCLAW_DOCKER_APT_PACKAGES="" -RUN if [ -n "$OPENCLAW_DOCKER_APT_PACKAGES" ]; then \ - apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $OPENCLAW_DOCKER_APT_PACKAGES && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \ - fi - -COPY --chown=node:node package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./ -COPY --chown=node:node ui/package.json ./ui/package.json -COPY --chown=node:node patches ./patches -COPY --chown=node:node scripts ./scripts - -USER node -RUN pnpm install --frozen-lockfile - -# Optionally install Chromium and Xvfb for browser automation. -# Build with: docker build --build-arg OPENCLAW_INSTALL_BROWSER=1 ... -# Adds ~300MB but eliminates the 60-90s Playwright install on every container start. -# Must run after pnpm install so playwright-core is available in node_modules. -USER root -ARG OPENCLAW_INSTALL_BROWSER="" -RUN if [ -n "$OPENCLAW_INSTALL_BROWSER" ]; then \ - apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xvfb && \ - mkdir -p /home/node/.cache/ms-playwright && \ - PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright \ - node /app/node_modules/playwright-core/cli.js install --with-deps chromium && \ - chown -R node:node /home/node/.cache/ms-playwright && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \ - fi - -USER node -COPY --chown=node:node . . -RUN pnpm build -# Force pnpm for UI build (Bun may fail on ARM/Synology architectures) -ENV OPENCLAW_PREFER_PNPM=1 -RUN pnpm ui:build - -ENV NODE_ENV=production - -# Security hardening: Run as non-root user -# The node:22-bookworm image includes a 'node' user (uid 1000) -# This reduces the attack surface by preventing container escape via root privileges -USER node - -# Start gateway server with default config. -# Binds to loopback (127.0.0.1) by default for security. -# -# For container platforms requiring external health checks: -# 1. Set OPENCLAW_GATEWAY_TOKEN or OPENCLAW_GATEWAY_PASSWORD env var -# 2. Override CMD: ["node","openclaw.mjs","gateway","--allow-unconfigured","--bind","lan"] -CMD ["node", "openclaw.mjs", "gateway", "--allow-unconfigured"] diff --git a/Dockerfile.sandbox b/Dockerfile.sandbox deleted file mode 100644 index a463d4a1020..00000000000 --- a/Dockerfile.sandbox +++ /dev/null @@ -1,20 +0,0 @@ -FROM debian:bookworm-slim@sha256:98f4b71de414932439ac6ac690d7060df1f27161073c5036a7553723881bffbe - -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - bash \ - ca-certificates \ - curl \ - git \ - jq \ - python3 \ - ripgrep \ - && rm -rf /var/lib/apt/lists/* - -RUN useradd --create-home --shell /bin/bash sandbox -USER sandbox -WORKDIR /home/sandbox - -CMD ["sleep", "infinity"] diff --git a/Dockerfile.sandbox-browser b/Dockerfile.sandbox-browser deleted file mode 100644 index ec9faf71113..00000000000 --- a/Dockerfile.sandbox-browser +++ /dev/null @@ -1,32 +0,0 @@ -FROM debian:bookworm-slim@sha256:98f4b71de414932439ac6ac690d7060df1f27161073c5036a7553723881bffbe - -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - bash \ - ca-certificates \ - chromium \ - curl \ - fonts-liberation \ - fonts-noto-color-emoji \ - git \ - jq \ - novnc \ - python3 \ - socat \ - websockify \ - x11vnc \ - xvfb \ - && rm -rf /var/lib/apt/lists/* - -COPY scripts/sandbox-browser-entrypoint.sh /usr/local/bin/openclaw-sandbox-browser -RUN chmod +x /usr/local/bin/openclaw-sandbox-browser - -RUN useradd --create-home --shell /bin/bash sandbox -USER sandbox -WORKDIR /home/sandbox - -EXPOSE 9222 5900 6080 - -CMD ["openclaw-sandbox-browser"] diff --git a/Dockerfile.sandbox-common b/Dockerfile.sandbox-common deleted file mode 100644 index 71f80070adf..00000000000 --- a/Dockerfile.sandbox-common +++ /dev/null @@ -1,45 +0,0 @@ -ARG BASE_IMAGE=openclaw-sandbox:bookworm-slim -FROM ${BASE_IMAGE} - -USER root - -ENV DEBIAN_FRONTEND=noninteractive - -ARG PACKAGES="curl wget jq coreutils grep nodejs npm python3 git ca-certificates golang-go rustc cargo unzip pkg-config libasound2-dev build-essential file" -ARG INSTALL_PNPM=1 -ARG INSTALL_BUN=1 -ARG BUN_INSTALL_DIR=/opt/bun -ARG INSTALL_BREW=1 -ARG BREW_INSTALL_DIR=/home/linuxbrew/.linuxbrew -ARG FINAL_USER=sandbox - -ENV BUN_INSTALL=${BUN_INSTALL_DIR} -ENV HOMEBREW_PREFIX=${BREW_INSTALL_DIR} -ENV HOMEBREW_CELLAR=${BREW_INSTALL_DIR}/Cellar -ENV HOMEBREW_REPOSITORY=${BREW_INSTALL_DIR}/Homebrew -ENV PATH=${BUN_INSTALL_DIR}/bin:${BREW_INSTALL_DIR}/bin:${BREW_INSTALL_DIR}/sbin:${PATH} - -RUN apt-get update \ - && apt-get install -y --no-install-recommends ${PACKAGES} \ - && rm -rf /var/lib/apt/lists/* - -RUN if [ "${INSTALL_PNPM}" = "1" ]; then npm install -g pnpm; fi - -RUN if [ "${INSTALL_BUN}" = "1" ]; then \ - curl -fsSL https://bun.sh/install | bash; \ - ln -sf "${BUN_INSTALL_DIR}/bin/bun" /usr/local/bin/bun; \ -fi - -RUN if [ "${INSTALL_BREW}" = "1" ]; then \ - if ! id -u linuxbrew >/dev/null 2>&1; then useradd -m -s /bin/bash linuxbrew; fi; \ - mkdir -p "${BREW_INSTALL_DIR}"; \ - chown -R linuxbrew:linuxbrew "$(dirname "${BREW_INSTALL_DIR}")"; \ - su - linuxbrew -c "NONINTERACTIVE=1 CI=1 /bin/bash -c '$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)'"; \ - if [ ! -e "${BREW_INSTALL_DIR}/Library" ]; then ln -s "${BREW_INSTALL_DIR}/Homebrew/Library" "${BREW_INSTALL_DIR}/Library"; fi; \ - if [ ! -x "${BREW_INSTALL_DIR}/bin/brew" ]; then echo \"brew install failed\"; exit 1; fi; \ - ln -sf "${BREW_INSTALL_DIR}/bin/brew" /usr/local/bin/brew; \ -fi - -# Default is sandbox, but allow BASE_IMAGE overrides to select another final user. -USER ${FINAL_USER} - diff --git a/README.md b/README.md index b1419f42fa4..86a83591633 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@

- Website · Docs · OpenClaw Framework · Discord · Skills Store + Website · Docs · OpenClaw Framework · Discord · Skills Store

--- diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 4b51daeaa73..00000000000 --- a/SECURITY.md +++ /dev/null @@ -1,137 +0,0 @@ -# Security Policy - -If you believe you've found a security issue in OpenClaw, please report it privately. - -## Reporting - -Report vulnerabilities directly to the repository where the issue lives: - -- **Core CLI and gateway** — [openclaw/openclaw](https://github.com/openclaw/openclaw) -- **macOS desktop app** — [openclaw/openclaw](https://github.com/openclaw/openclaw) (apps/macos) -- **iOS app** — [openclaw/openclaw](https://github.com/openclaw/openclaw) (apps/ios) -- **Android app** — [openclaw/openclaw](https://github.com/openclaw/openclaw) (apps/android) -- **ClawHub** — [openclaw/clawhub](https://github.com/openclaw/clawhub) -- **Trust and threat model** — [openclaw/trust](https://github.com/openclaw/trust) - -For issues that don't fit a specific repo, or if you're unsure, email **security@openclaw.ai** and we'll route it. - -For full reporting instructions see our [Trust page](https://trust.openclaw.ai). - -### Required in Reports - -1. **Title** -2. **Severity Assessment** -3. **Impact** -4. **Affected Component** -5. **Technical Reproduction** -6. **Demonstrated Impact** -7. **Environment** -8. **Remediation Advice** - -Reports without reproduction steps, demonstrated impact, and remediation advice will be deprioritized. Given the volume of AI-generated scanner findings, we must ensure we're receiving vetted reports from researchers who understand the issues. - -## Security & Trust - -**Jamieson O'Reilly** ([@theonejvo](https://twitter.com/theonejvo)) is Security & Trust at OpenClaw. Jamieson is the founder of [Dvuln](https://dvuln.com) and brings extensive experience in offensive security, penetration testing, and security program development. - -## Bug Bounties - -OpenClaw is a labor of love. There is no bug bounty program and no budget for paid reports. Please still disclose responsibly so we can fix issues quickly. -The best way to help the project right now is by sending PRs. - -## Maintainers: GHSA Updates via CLI - -When patching a GHSA via `gh api`, include `X-GitHub-Api-Version: 2022-11-28` (or newer). Without it, some fields (notably CVSS) may not persist even if the request returns 200. - -## Out of Scope - -- Public Internet Exposure -- Using OpenClaw in ways that the docs recommend not to -- Deployments where mutually untrusted/adversarial operators share one gateway host and config -- Prompt injection attacks - -## Deployment Assumptions - -OpenClaw security guidance assumes: - -- The host where OpenClaw runs is within a trusted OS/admin boundary. -- Anyone who can modify `~/.openclaw` state/config (including `openclaw.json`) is effectively a trusted operator. -- A single Gateway shared by mutually untrusted people is **not a recommended setup**. Use separate gateways (or at minimum separate OS users/hosts) per trust boundary. - -## Plugin Trust Boundary - -Plugins/extensions are loaded **in-process** with the Gateway and are treated as trusted code. - -- Plugins can execute with the same OS privileges as the OpenClaw process. -- Runtime helpers (for example `runtime.system.runCommandWithTimeout`) are convenience APIs, not a sandbox boundary. -- Only install plugins you trust, and prefer `plugins.allow` to pin explicit trusted plugin ids. - -## Operational Guidance - -For threat model + hardening guidance (including `openclaw security audit --deep` and `--fix`), see: - -- `https://docs.openclaw.ai/gateway/security` - -### Tool filesystem hardening - -- `tools.exec.applyPatch.workspaceOnly: true` (recommended): keeps `apply_patch` writes/deletes within the configured workspace directory. -- `tools.fs.workspaceOnly: true` (optional): restricts `read`/`write`/`edit`/`apply_patch` paths to the workspace directory. -- Avoid setting `tools.exec.applyPatch.workspaceOnly: false` unless you fully trust who can trigger tool execution. - -### Web Interface Safety - -OpenClaw's web interface (Gateway Control UI + HTTP endpoints) is intended for **local use only**. - -- Recommended: keep the Gateway **loopback-only** (`127.0.0.1` / `::1`). - - Config: `gateway.bind="loopback"` (default). - - CLI: `openclaw gateway run --bind loopback`. -- Canvas host note: network-visible canvas is **intentional** for trusted node scenarios (LAN/tailnet). - - Expected setup: non-loopback bind + Gateway auth (token/password/trusted-proxy) + firewall/tailnet controls. - - Expected routes: `/__openclaw__/canvas/`, `/__openclaw__/a2ui/`. - - This deployment model alone is not a security vulnerability. -- Do **not** expose it to the public internet (no direct bind to `0.0.0.0`, no public reverse proxy). It is not hardened for public exposure. -- If you need remote access, prefer an SSH tunnel or Tailscale serve/funnel (so the Gateway still binds to loopback), plus strong Gateway auth. -- The Gateway HTTP surface includes the canvas host (`/__openclaw__/canvas/`, `/__openclaw__/a2ui/`). Treat canvas content as sensitive/untrusted and avoid exposing it beyond loopback unless you understand the risk. - -## Runtime Requirements - -### Node.js Version - -OpenClaw requires **Node.js 22.12.0 or later** (LTS). This version includes important security patches: - -- CVE-2025-59466: async_hooks DoS vulnerability -- CVE-2026-21636: Permission model bypass vulnerability - -Verify your Node.js version: - -```bash -node --version # Should be v22.12.0 or later -``` - -### Docker Security - -When running OpenClaw in Docker: - -1. The official image runs as a non-root user (`node`) for reduced attack surface -2. Use `--read-only` flag when possible for additional filesystem protection -3. Limit container capabilities with `--cap-drop=ALL` - -Example secure Docker run: - -```bash -docker run --read-only --cap-drop=ALL \ - -v openclaw-data:/app/data \ - openclaw/openclaw:latest -``` - -## Security Scanning - -This project uses `detect-secrets` for automated secret detection in CI/CD. -See `.detect-secrets.cfg` for configuration and `.secrets.baseline` for the baseline. - -Run locally: - -```bash -pip install detect-secrets==1.5.0 -detect-secrets scan --baseline .secrets.baseline -``` diff --git a/Swabble/.github/workflows/ci.yml b/Swabble/.github/workflows/ci.yml deleted file mode 100644 index aff600f6df0..00000000000 --- a/Swabble/.github/workflows/ci.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: CI - -on: - push: - branches: [main] - pull_request: - -jobs: - build-and-test: - runs-on: macos-latest - defaults: - run: - shell: bash - working-directory: swabble - steps: - - name: Checkout swabble - uses: actions/checkout@v4 - with: - path: swabble - - - name: Select Xcode 26.1 (prefer 26.1.1) - run: | - set -euo pipefail - # pick the newest installed 26.1.x, fallback to newest 26.x - CANDIDATE="$(ls -d /Applications/Xcode_26.1*.app 2>/dev/null | sort -V | tail -1 || true)" - if [[ -z "$CANDIDATE" ]]; then - CANDIDATE="$(ls -d /Applications/Xcode_26*.app 2>/dev/null | sort -V | tail -1 || true)" - fi - if [[ -z "$CANDIDATE" ]]; then - echo "No Xcode 26.x found on runner" >&2 - exit 1 - fi - echo "Selecting $CANDIDATE" - sudo xcode-select -s "$CANDIDATE" - xcodebuild -version - - - name: Show Swift version - run: swift --version - - - name: Install tooling - run: | - brew update - brew install swiftlint swiftformat - - - name: Format check - run: | - ./scripts/format.sh - git diff --exit-code - - - name: Lint - run: ./scripts/lint.sh - - - name: Test - run: swift test --parallel diff --git a/Swabble/.gitignore b/Swabble/.gitignore deleted file mode 100644 index e988a5b232b..00000000000 --- a/Swabble/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -# macOS -.DS_Store - -# SwiftPM / Build -/.build -/.swiftpm -/DerivedData -xcuserdata/ -*.xcuserstate - -# Editors -/.vscode -.idea/ - -# Xcode artifacts -*.hmap -*.ipa -*.dSYM.zip -*.dSYM - -# Playgrounds -*.xcplayground -playground.xcworkspace -timeline.xctimeline - -# Carthage -Carthage/Build/ - -# fastlane -fastlane/report.xml -fastlane/Preview.html -fastlane/screenshots/**/*.png -fastlane/test_output diff --git a/Swabble/.swiftformat b/Swabble/.swiftformat deleted file mode 100644 index 2686269a272..00000000000 --- a/Swabble/.swiftformat +++ /dev/null @@ -1,8 +0,0 @@ ---swiftversion 6.2 ---indent 4 ---maxwidth 120 ---wraparguments before-first ---wrapcollections before-first ---stripunusedargs closure-only ---self remove ---header "" diff --git a/Swabble/.swiftlint.yml b/Swabble/.swiftlint.yml deleted file mode 100644 index f63ff5dbb18..00000000000 --- a/Swabble/.swiftlint.yml +++ /dev/null @@ -1,43 +0,0 @@ -# SwiftLint for swabble -included: - - Sources -excluded: - - .build - - DerivedData - - "**/.swiftpm" - - "**/.build" - - "**/DerivedData" - - "**/.DS_Store" -opt_in_rules: - - array_init - - closure_spacing - - explicit_init - - fatal_error_message - - first_where - - joined_default_parameter - - last_where - - literal_expression_end_indentation - - multiline_arguments - - multiline_parameters - - operator_usage_whitespace - - redundant_nil_coalescing - - sorted_first_last - - switch_case_alignment - - vertical_parameter_alignment_on_call - - vertical_whitespace_opening_braces - - vertical_whitespace_closing_braces - -disabled_rules: - - trailing_whitespace - - trailing_newline - - indentation_width - - identifier_name - - explicit_self - - file_header - - todo - -line_length: - warning: 140 - error: 180 - -reporter: "xcode" diff --git a/Swabble/CHANGELOG.md b/Swabble/CHANGELOG.md deleted file mode 100644 index e8f2ad60d85..00000000000 --- a/Swabble/CHANGELOG.md +++ /dev/null @@ -1,11 +0,0 @@ -# Changelog - -## 0.2.0 — 2025-12-23 - -### Highlights -- Added `SwabbleKit` (multi-platform wake-word gate utilities with segment-aware gap detection). -- Swabble package now supports iOS + macOS consumers; CLI remains macOS 26-only. - -### Changes -- CLI wake-word matching/stripping routed through `SwabbleKit` helpers. -- Speech pipeline types now explicitly gated to macOS 26 / iOS 26 availability. diff --git a/Swabble/LICENSE b/Swabble/LICENSE deleted file mode 100644 index f7b526698bb..00000000000 --- a/Swabble/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 Peter Steinberger - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Swabble/Package.resolved b/Swabble/Package.resolved deleted file mode 100644 index f52a51fbe53..00000000000 --- a/Swabble/Package.resolved +++ /dev/null @@ -1,69 +0,0 @@ -{ - "originHash" : "24a723309d7a0039d3df3051106f77ac1ed7068a02508e3a6804e41d757e6c72", - "pins" : [ - { - "identity" : "commander", - "kind" : "remoteSourceControl", - "location" : "https://github.com/steipete/Commander.git", - "state" : { - "revision" : "9e349575c8e3c6745e81fe19e5bb5efa01b078ce", - "version" : "0.2.1" - } - }, - { - "identity" : "elevenlabskit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/steipete/ElevenLabsKit", - "state" : { - "revision" : "7e3c948d8340abe3977014f3de020edf221e9269", - "version" : "0.1.0" - } - }, - { - "identity" : "swift-concurrency-extras", - "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-concurrency-extras", - "state" : { - "revision" : "5a3825302b1a0d744183200915a47b508c828e6f", - "version" : "1.3.2" - } - }, - { - "identity" : "swift-syntax", - "kind" : "remoteSourceControl", - "location" : "https://github.com/swiftlang/swift-syntax.git", - "state" : { - "revision" : "0687f71944021d616d34d922343dcef086855920", - "version" : "600.0.1" - } - }, - { - "identity" : "swift-testing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-testing", - "state" : { - "revision" : "399f76dcd91e4c688ca2301fa24a8cc6d9927211", - "version" : "0.99.0" - } - }, - { - "identity" : "swiftui-math", - "kind" : "remoteSourceControl", - "location" : "https://github.com/gonzalezreal/swiftui-math", - "state" : { - "revision" : "0b5c2cfaaec8d6193db206f675048eeb5ce95f71", - "version" : "0.1.0" - } - }, - { - "identity" : "textual", - "kind" : "remoteSourceControl", - "location" : "https://github.com/gonzalezreal/textual", - "state" : { - "revision" : "5b06b811c0f5313b6b84bbef98c635a630638c38", - "version" : "0.3.1" - } - } - ], - "version" : 3 -} diff --git a/Swabble/Package.swift b/Swabble/Package.swift deleted file mode 100644 index 9f5a0003619..00000000000 --- a/Swabble/Package.swift +++ /dev/null @@ -1,55 +0,0 @@ -// swift-tools-version: 6.2 -import PackageDescription - -let package = Package( - name: "swabble", - platforms: [ - .macOS(.v15), - .iOS(.v17), - ], - products: [ - .library(name: "Swabble", targets: ["Swabble"]), - .library(name: "SwabbleKit", targets: ["SwabbleKit"]), - .executable(name: "swabble", targets: ["SwabbleCLI"]), - ], - dependencies: [ - .package(url: "https://github.com/steipete/Commander.git", exact: "0.2.1"), - .package(url: "https://github.com/apple/swift-testing", from: "0.99.0"), - ], - targets: [ - .target( - name: "Swabble", - path: "Sources/SwabbleCore", - swiftSettings: []), - .target( - name: "SwabbleKit", - path: "Sources/SwabbleKit", - swiftSettings: [ - .enableUpcomingFeature("StrictConcurrency"), - ]), - .executableTarget( - name: "SwabbleCLI", - dependencies: [ - "Swabble", - "SwabbleKit", - .product(name: "Commander", package: "Commander"), - ], - path: "Sources/swabble"), - .testTarget( - name: "SwabbleKitTests", - dependencies: [ - "SwabbleKit", - .product(name: "Testing", package: "swift-testing"), - ], - swiftSettings: [ - .enableUpcomingFeature("StrictConcurrency"), - .enableExperimentalFeature("SwiftTesting"), - ]), - .testTarget( - name: "swabbleTests", - dependencies: [ - "Swabble", - .product(name: "Testing", package: "swift-testing"), - ]), - ], - swiftLanguageModes: [.v6]) diff --git a/Swabble/README.md b/Swabble/README.md deleted file mode 100644 index bf6dc3dc8bd..00000000000 --- a/Swabble/README.md +++ /dev/null @@ -1,111 +0,0 @@ -# 🎙️ swabble — Speech.framework wake-word hook daemon (macOS 26) - -swabble is a Swift 6.2 wake-word hook daemon. The CLI targets macOS 26 (SpeechAnalyzer + SpeechTranscriber). The shared `SwabbleKit` target is multi-platform and exposes wake-word gating utilities for iOS/macOS apps. - -- **Local-only**: Speech.framework on-device models; zero network usage. -- **Wake word**: Default `clawd` (aliases `claude`), optional `--no-wake` bypass. -- **SwabbleKit**: Shared wake gate utilities (gap-based gating when you provide speech segments). -- **Hooks**: Run any command with prefix/env, cooldown, min_chars, timeout. -- **Services**: launchd helper stubs for start/stop/install. -- **File transcribe**: TXT or SRT with time ranges (using AttributedString splits). - -## Quick start -```bash -# Install deps -brew install swiftformat swiftlint - -# Build -swift build - -# Write default config (~/.config/swabble/config.json) -swift run swabble setup - -# Run foreground daemon -swift run swabble serve - -# Test your hook -swift run swabble test-hook "hello world" - -# Transcribe a file to SRT -swift run swabble transcribe /path/to/audio.m4a --format srt --output out.srt -``` - -## Use as a library -Add swabble as a SwiftPM dependency and import the `Swabble` or `SwabbleKit` product: - -```swift -// Package.swift -dependencies: [ - .package(url: "https://github.com/steipete/swabble.git", branch: "main"), -], -targets: [ - .target(name: "MyApp", dependencies: [ - .product(name: "Swabble", package: "swabble"), // Speech pipeline (macOS 26+ / iOS 26+) - .product(name: "SwabbleKit", package: "swabble"), // Wake-word gate utilities (iOS 17+ / macOS 15+) - ]), -] -``` - -## CLI -- `serve` — foreground loop (mic → wake → hook) -- `transcribe ` — offline transcription (txt|srt) -- `test-hook "text"` — invoke configured hook -- `mic list|set ` — enumerate/select input device -- `setup` — write default config JSON -- `doctor` — check Speech auth & device availability -- `health` — prints `ok` -- `tail-log` — last 10 transcripts -- `status` — show wake state + recent transcripts -- `service install|uninstall|status` — user launchd plist (stub: prints launchctl commands) -- `start|stop|restart` — placeholders until full launchd wiring - -All commands accept Commander runtime flags (`-v/--verbose`, `--json-output`, `--log-level`), plus `--config` where applicable. - -## Config -`~/.config/swabble/config.json` (auto-created by `setup`): -```json -{ - "audio": {"deviceName": "", "deviceIndex": -1, "sampleRate": 16000, "channels": 1}, - "wake": {"enabled": true, "word": "clawd", "aliases": ["claude"]}, - "hook": { - "command": "", - "args": [], - "prefix": "Voice swabble from ${hostname}: ", - "cooldownSeconds": 1, - "minCharacters": 24, - "timeoutSeconds": 5, - "env": {} - }, - "logging": {"level": "info", "format": "text"}, - "transcripts": {"enabled": true, "maxEntries": 50}, - "speech": {"localeIdentifier": "en_US", "etiquetteReplacements": false} -} -``` - -- Config path override: `--config /path/to/config.json` on relevant commands. -- Transcripts persist to `~/Library/Application Support/swabble/transcripts.log`. - -## Hook protocol -When a wake-gated transcript passes min_chars & cooldown, swabble runs: -``` - "" -``` -Environment variables: -- `SWABBLE_TEXT` — stripped transcript (wake word removed) -- `SWABBLE_PREFIX` — rendered prefix (hostname substituted) -- plus any `hook.env` key/values - -## Speech pipeline -- `AVAudioEngine` tap → `BufferConverter` → `AnalyzerInput` → `SpeechAnalyzer` with a `SpeechTranscriber` module. -- Requests volatile + final results; the CLI uses text-only wake gating today. -- Authorization requested at first start; requires macOS 26 + new Speech.framework APIs. - -## Development -- Format: `./scripts/format.sh` (uses local `.swiftformat`) -- Lint: `./scripts/lint.sh` (uses local `.swiftlint.yml`) -- Tests: `swift test` (uses swift-testing package) - -## Roadmap -- launchd control (load/bootout, PID + status socket) -- JSON logging + PII redaction toggle -- Stronger wake-word detection and control socket status/health diff --git a/Swabble/Sources/SwabbleCore/Config/Config.swift b/Swabble/Sources/SwabbleCore/Config/Config.swift deleted file mode 100644 index 4dc9d4668c0..00000000000 --- a/Swabble/Sources/SwabbleCore/Config/Config.swift +++ /dev/null @@ -1,77 +0,0 @@ -import Foundation - -public struct SwabbleConfig: Codable, Sendable { - public struct Audio: Codable, Sendable { - public var deviceName: String = "" - public var deviceIndex: Int = -1 - public var sampleRate: Double = 16000 - public var channels: Int = 1 - } - - public struct Wake: Codable, Sendable { - public var enabled: Bool = true - public var word: String = "clawd" - public var aliases: [String] = ["claude"] - } - - public struct Hook: Codable, Sendable { - public var command: String = "" - public var args: [String] = [] - public var prefix: String = "Voice swabble from ${hostname}: " - public var cooldownSeconds: Double = 1 - public var minCharacters: Int = 24 - public var timeoutSeconds: Double = 5 - public var env: [String: String] = [:] - } - - public struct Logging: Codable, Sendable { - public var level: String = "info" - public var format: String = "text" // text|json placeholder - } - - public struct Transcripts: Codable, Sendable { - public var enabled: Bool = true - public var maxEntries: Int = 50 - } - - public struct Speech: Codable, Sendable { - public var localeIdentifier: String = Locale.current.identifier - public var etiquetteReplacements: Bool = false - } - - public var audio = Audio() - public var wake = Wake() - public var hook = Hook() - public var logging = Logging() - public var transcripts = Transcripts() - public var speech = Speech() - - public static let defaultPath = FileManager.default - .homeDirectoryForCurrentUser - .appendingPathComponent(".config/swabble/config.json") - - public init() {} -} - -public enum ConfigError: Error { - case missingConfig -} - -public enum ConfigLoader { - public static func load(at path: URL?) throws -> SwabbleConfig { - let url = path ?? SwabbleConfig.defaultPath - if !FileManager.default.fileExists(atPath: url.path) { - throw ConfigError.missingConfig - } - let data = try Data(contentsOf: url) - return try JSONDecoder().decode(SwabbleConfig.self, from: data) - } - - public static func save(_ config: SwabbleConfig, at path: URL?) throws { - let url = path ?? SwabbleConfig.defaultPath - let dir = url.deletingLastPathComponent() - try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) - let data = try JSONEncoder().encode(config) - try data.write(to: url) - } -} diff --git a/Swabble/Sources/SwabbleCore/Hooks/HookExecutor.swift b/Swabble/Sources/SwabbleCore/Hooks/HookExecutor.swift deleted file mode 100644 index dd59c43bb58..00000000000 --- a/Swabble/Sources/SwabbleCore/Hooks/HookExecutor.swift +++ /dev/null @@ -1,75 +0,0 @@ -import Foundation - -public struct HookJob: Sendable { - public let text: String - public let timestamp: Date - - public init(text: String, timestamp: Date) { - self.text = text - self.timestamp = timestamp - } -} - -public actor HookExecutor { - private let config: SwabbleConfig - private var lastRun: Date? - private let hostname: String - - public init(config: SwabbleConfig) { - self.config = config - hostname = Host.current().localizedName ?? "host" - } - - public func shouldRun() -> Bool { - guard config.hook.cooldownSeconds > 0 else { return true } - if let lastRun, Date().timeIntervalSince(lastRun) < config.hook.cooldownSeconds { - return false - } - return true - } - - public func run(job: HookJob) async throws { - guard shouldRun() else { return } - guard !config.hook.command.isEmpty else { throw NSError( - domain: "Hook", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "hook command not set"]) } - - let prefix = config.hook.prefix.replacingOccurrences(of: "${hostname}", with: hostname) - let payload = prefix + job.text - - let process = Process() - process.executableURL = URL(fileURLWithPath: config.hook.command) - process.arguments = config.hook.args + [payload] - - var env = ProcessInfo.processInfo.environment - env["SWABBLE_TEXT"] = job.text - env["SWABBLE_PREFIX"] = prefix - for (k, v) in config.hook.env { - env[k] = v - } - process.environment = env - - let pipe = Pipe() - process.standardOutput = pipe - process.standardError = pipe - - try process.run() - - let timeoutNanos = UInt64(max(config.hook.timeoutSeconds, 0.1) * 1_000_000_000) - try await withThrowingTaskGroup(of: Void.self) { group in - group.addTask { - process.waitUntilExit() - } - group.addTask { - try await Task.sleep(nanoseconds: timeoutNanos) - if process.isRunning { - process.terminate() - } - } - try await group.next() - group.cancelAll() - } - lastRun = Date() - } -} diff --git a/Swabble/Sources/SwabbleCore/Speech/BufferConverter.swift b/Swabble/Sources/SwabbleCore/Speech/BufferConverter.swift deleted file mode 100644 index e6d7dc993ba..00000000000 --- a/Swabble/Sources/SwabbleCore/Speech/BufferConverter.swift +++ /dev/null @@ -1,50 +0,0 @@ -@preconcurrency import AVFoundation -import Foundation - -final class BufferConverter { - private final class Box: @unchecked Sendable { var value: T; init(_ value: T) { self.value = value } } - enum ConverterError: Swift.Error { - case failedToCreateConverter - case failedToCreateConversionBuffer - case conversionFailed(NSError?) - } - - private var converter: AVAudioConverter? - - func convert(_ buffer: AVAudioPCMBuffer, to format: AVAudioFormat) throws -> AVAudioPCMBuffer { - let inputFormat = buffer.format - if inputFormat == format { - return buffer - } - if converter == nil || converter?.outputFormat != format { - converter = AVAudioConverter(from: inputFormat, to: format) - converter?.primeMethod = .none - } - guard let converter else { throw ConverterError.failedToCreateConverter } - - let sampleRateRatio = converter.outputFormat.sampleRate / converter.inputFormat.sampleRate - let scaledInputFrameLength = Double(buffer.frameLength) * sampleRateRatio - let frameCapacity = AVAudioFrameCount(scaledInputFrameLength.rounded(.up)) - guard let conversionBuffer = AVAudioPCMBuffer(pcmFormat: converter.outputFormat, frameCapacity: frameCapacity) - else { - throw ConverterError.failedToCreateConversionBuffer - } - - var nsError: NSError? - let consumed = Box(false) - let inputBuffer = buffer - let status = converter.convert(to: conversionBuffer, error: &nsError) { _, statusPtr in - if consumed.value { - statusPtr.pointee = .noDataNow - return nil - } - consumed.value = true - statusPtr.pointee = .haveData - return inputBuffer - } - if status == .error { - throw ConverterError.conversionFailed(nsError) - } - return conversionBuffer - } -} diff --git a/Swabble/Sources/SwabbleCore/Speech/SpeechPipeline.swift b/Swabble/Sources/SwabbleCore/Speech/SpeechPipeline.swift deleted file mode 100644 index 014b174da7b..00000000000 --- a/Swabble/Sources/SwabbleCore/Speech/SpeechPipeline.swift +++ /dev/null @@ -1,114 +0,0 @@ -import AVFoundation -import Foundation -import Speech - -@available(macOS 26.0, iOS 26.0, *) -public struct SpeechSegment: Sendable { - public let text: String - public let isFinal: Bool -} - -@available(macOS 26.0, iOS 26.0, *) -public enum SpeechPipelineError: Error { - case authorizationDenied - case analyzerFormatUnavailable - case transcriberUnavailable -} - -/// Live microphone → SpeechAnalyzer → SpeechTranscriber pipeline. -@available(macOS 26.0, iOS 26.0, *) -public actor SpeechPipeline { - private struct UnsafeBuffer: @unchecked Sendable { let buffer: AVAudioPCMBuffer } - - private var engine = AVAudioEngine() - private var transcriber: SpeechTranscriber? - private var analyzer: SpeechAnalyzer? - private var inputContinuation: AsyncStream.Continuation? - private var resultTask: Task? - private let converter = BufferConverter() - - public init() {} - - public func start(localeIdentifier: String, etiquette: Bool) async throws -> AsyncStream { - let auth = await requestAuthorizationIfNeeded() - guard auth == .authorized else { throw SpeechPipelineError.authorizationDenied } - - let transcriberModule = SpeechTranscriber( - locale: Locale(identifier: localeIdentifier), - transcriptionOptions: etiquette ? [.etiquetteReplacements] : [], - reportingOptions: [.volatileResults], - attributeOptions: []) - transcriber = transcriberModule - - guard let analyzerFormat = await SpeechAnalyzer.bestAvailableAudioFormat(compatibleWith: [transcriberModule]) - else { - throw SpeechPipelineError.analyzerFormatUnavailable - } - - analyzer = SpeechAnalyzer(modules: [transcriberModule]) - let (stream, continuation) = AsyncStream.makeStream() - inputContinuation = continuation - - let inputNode = engine.inputNode - let inputFormat = inputNode.outputFormat(forBus: 0) - inputNode.removeTap(onBus: 0) - inputNode.installTap(onBus: 0, bufferSize: 2048, format: inputFormat) { [weak self] buffer, _ in - guard let self else { return } - let boxed = UnsafeBuffer(buffer: buffer) - Task { await self.handleBuffer(boxed.buffer, targetFormat: analyzerFormat) } - } - - engine.prepare() - try engine.start() - try await analyzer?.start(inputSequence: stream) - - guard let transcriberForStream = transcriber else { - throw SpeechPipelineError.transcriberUnavailable - } - - return AsyncStream { continuation in - self.resultTask = Task { - do { - for try await result in transcriberForStream.results { - let seg = SpeechSegment(text: String(result.text.characters), isFinal: result.isFinal) - continuation.yield(seg) - } - } catch { - // swallow errors and finish - } - continuation.finish() - } - continuation.onTermination = { _ in - Task { await self.stop() } - } - } - } - - public func stop() async { - resultTask?.cancel() - inputContinuation?.finish() - engine.inputNode.removeTap(onBus: 0) - engine.stop() - try? await analyzer?.finalizeAndFinishThroughEndOfInput() - } - - private func handleBuffer(_ buffer: AVAudioPCMBuffer, targetFormat: AVAudioFormat) async { - do { - let converted = try converter.convert(buffer, to: targetFormat) - let input = AnalyzerInput(buffer: converted) - inputContinuation?.yield(input) - } catch { - // drop on conversion failure - } - } - - private func requestAuthorizationIfNeeded() async -> SFSpeechRecognizerAuthorizationStatus { - let current = SFSpeechRecognizer.authorizationStatus() - guard current == .notDetermined else { return current } - return await withCheckedContinuation { continuation in - SFSpeechRecognizer.requestAuthorization { status in - continuation.resume(returning: status) - } - } - } -} diff --git a/Swabble/Sources/SwabbleCore/Support/AttributedString+Sentences.swift b/Swabble/Sources/SwabbleCore/Support/AttributedString+Sentences.swift deleted file mode 100644 index e2de6fdfce5..00000000000 --- a/Swabble/Sources/SwabbleCore/Support/AttributedString+Sentences.swift +++ /dev/null @@ -1,62 +0,0 @@ -import CoreMedia -import Foundation -import NaturalLanguage - -extension AttributedString { - public func sentences(maxLength: Int? = nil) -> [AttributedString] { - let tokenizer = NLTokenizer(unit: .sentence) - let string = String(characters) - tokenizer.string = string - let sentenceRanges = tokenizer.tokens(for: string.startIndex.. maxLength else { - return [sentenceRange] - } - - let wordTokenizer = NLTokenizer(unit: .word) - wordTokenizer.string = string - var wordRanges = wordTokenizer.tokens(for: sentenceStringRange).map { - AttributedString.Index($0.lowerBound, within: self)! - ..< - AttributedString.Index($0.upperBound, within: self)! - } - guard !wordRanges.isEmpty else { return [sentenceRange] } - wordRanges[0] = sentenceRange.lowerBound..] = [] - for wordRange in wordRanges { - if let lastRange = ranges.last, - self[lastRange].characters.count + self[wordRange].characters.count <= maxLength { - ranges[ranges.count - 1] = lastRange.lowerBound.. Bool { lhs.rank < rhs.rank } -} - -public struct Logger: Sendable { - public let level: LogLevel - - public init(level: LogLevel) { self.level = level } - - public func log(_ level: LogLevel, _ message: String) { - guard level >= self.level else { return } - let ts = ISO8601DateFormatter().string(from: Date()) - print("[\(level.rawValue.uppercased())] \(ts) | \(message)") - } - - public func trace(_ msg: String) { log(.trace, msg) } - public func debug(_ msg: String) { log(.debug, msg) } - public func info(_ msg: String) { log(.info, msg) } - public func warn(_ msg: String) { log(.warn, msg) } - public func error(_ msg: String) { log(.error, msg) } -} - -extension LogLevel { - public init?(configValue: String) { - self.init(rawValue: configValue.lowercased()) - } -} diff --git a/Swabble/Sources/SwabbleCore/Support/OutputFormat.swift b/Swabble/Sources/SwabbleCore/Support/OutputFormat.swift deleted file mode 100644 index 84047c7284b..00000000000 --- a/Swabble/Sources/SwabbleCore/Support/OutputFormat.swift +++ /dev/null @@ -1,45 +0,0 @@ -import CoreMedia -import Foundation - -public enum OutputFormat: String { - case txt - case srt - - public var needsAudioTimeRange: Bool { - switch self { - case .srt: true - default: false - } - } - - public func text(for transcript: AttributedString, maxLength: Int) -> String { - switch self { - case .txt: - return String(transcript.characters) - case .srt: - func format(_ timeInterval: TimeInterval) -> String { - let ms = Int(timeInterval.truncatingRemainder(dividingBy: 1) * 1000) - let s = Int(timeInterval) % 60 - let m = (Int(timeInterval) / 60) % 60 - let h = Int(timeInterval) / 60 / 60 - return String(format: "%0.2d:%0.2d:%0.2d,%0.3d", h, m, s, ms) - } - - return transcript.sentences(maxLength: maxLength).compactMap { (sentence: AttributedString) -> ( - CMTimeRange, - String)? in - guard let timeRange = sentence.audioTimeRange else { return nil } - return (timeRange, String(sentence.characters)) - }.enumerated().map { index, run in - let (timeRange, text) = run - return """ - - \(index + 1) - \(format(timeRange.start.seconds)) --> \(format(timeRange.end.seconds)) - \(text.trimmingCharacters(in: .whitespacesAndNewlines)) - - """ - }.joined().trimmingCharacters(in: .whitespacesAndNewlines) - } - } -} diff --git a/Swabble/Sources/SwabbleCore/Support/TranscriptsStore.swift b/Swabble/Sources/SwabbleCore/Support/TranscriptsStore.swift deleted file mode 100644 index 4f91d052e6a..00000000000 --- a/Swabble/Sources/SwabbleCore/Support/TranscriptsStore.swift +++ /dev/null @@ -1,45 +0,0 @@ -import Foundation - -public actor TranscriptsStore { - public static let shared = TranscriptsStore() - - private var entries: [String] = [] - private let limit = 100 - private let fileURL: URL - - public init() { - let dir = FileManager.default.homeDirectoryForCurrentUser - .appendingPathComponent("Library/Application Support/swabble", isDirectory: true) - try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) - fileURL = dir.appendingPathComponent("transcripts.log") - if let data = try? Data(contentsOf: fileURL), - let text = String(data: data, encoding: .utf8) { - entries = text.split(separator: "\n").map(String.init).suffix(limit) - } - } - - public func append(text: String) { - entries.append(text) - if entries.count > limit { - entries.removeFirst(entries.count - limit) - } - let body = entries.joined(separator: "\n") - try? body.write(to: fileURL, atomically: false, encoding: .utf8) - } - - public func latest() -> [String] { entries } -} - -extension String { - private func appendLine(to url: URL) throws { - let data = (self + "\n").data(using: .utf8) ?? Data() - if FileManager.default.fileExists(atPath: url.path) { - let handle = try FileHandle(forWritingTo: url) - try handle.seekToEnd() - try handle.write(contentsOf: data) - try handle.close() - } else { - try data.write(to: url) - } - } -} diff --git a/Swabble/Sources/SwabbleKit/WakeWordGate.swift b/Swabble/Sources/SwabbleKit/WakeWordGate.swift deleted file mode 100644 index 27c952a8d1b..00000000000 --- a/Swabble/Sources/SwabbleKit/WakeWordGate.swift +++ /dev/null @@ -1,197 +0,0 @@ -import Foundation - -public struct WakeWordSegment: Sendable, Equatable { - public let text: String - public let start: TimeInterval - public let duration: TimeInterval - public let range: Range? - - public init(text: String, start: TimeInterval, duration: TimeInterval, range: Range? = nil) { - self.text = text - self.start = start - self.duration = duration - self.range = range - } - - public var end: TimeInterval { start + duration } -} - -public struct WakeWordGateConfig: Sendable, Equatable { - public var triggers: [String] - public var minPostTriggerGap: TimeInterval - public var minCommandLength: Int - - public init( - triggers: [String], - minPostTriggerGap: TimeInterval = 0.45, - minCommandLength: Int = 1) { - self.triggers = triggers - self.minPostTriggerGap = minPostTriggerGap - self.minCommandLength = minCommandLength - } -} - -public struct WakeWordGateMatch: Sendable, Equatable { - public let triggerEndTime: TimeInterval - public let postGap: TimeInterval - public let command: String - - public init(triggerEndTime: TimeInterval, postGap: TimeInterval, command: String) { - self.triggerEndTime = triggerEndTime - self.postGap = postGap - self.command = command - } -} - -public enum WakeWordGate { - private struct Token { - let normalized: String - let start: TimeInterval - let end: TimeInterval - let range: Range? - let text: String - } - - private struct TriggerTokens { - let tokens: [String] - } - - private struct MatchCandidate { - let index: Int - let triggerEnd: TimeInterval - let gap: TimeInterval - } - - public static func match( - transcript: String, - segments: [WakeWordSegment], - config: WakeWordGateConfig) - -> WakeWordGateMatch? { - let triggerTokens = normalizeTriggers(config.triggers) - guard !triggerTokens.isEmpty else { return nil } - - let tokens = normalizeSegments(segments) - guard !tokens.isEmpty else { return nil } - - var best: MatchCandidate? - - for trigger in triggerTokens { - let count = trigger.tokens.count - guard count > 0, tokens.count > count else { continue } - for i in 0...(tokens.count - count - 1) { - let matched = (0..= config.minCommandLength else { return nil } - return WakeWordGateMatch(triggerEndTime: best.triggerEnd, postGap: best.gap, command: command) - } - - public static func commandText( - transcript: String, - segments: [WakeWordSegment], - triggerEndTime: TimeInterval) - -> String { - let threshold = triggerEndTime + 0.001 - for segment in segments where segment.start >= threshold { - if normalizeToken(segment.text).isEmpty { continue } - if let range = segment.range { - let slice = transcript[range.lowerBound...] - return String(slice).trimmingCharacters(in: Self.whitespaceAndPunctuation) - } - break - } - - let text = segments - .filter { $0.start >= threshold && !normalizeToken($0.text).isEmpty } - .map(\.text) - .joined(separator: " ") - return text.trimmingCharacters(in: Self.whitespaceAndPunctuation) - } - - public static func matchesTextOnly(text: String, triggers: [String]) -> Bool { - guard !text.isEmpty else { return false } - let normalized = text.lowercased() - for trigger in triggers { - let token = trigger.trimmingCharacters(in: whitespaceAndPunctuation).lowercased() - if token.isEmpty { continue } - if normalized.contains(token) { return true } - } - return false - } - - public static func stripWake(text: String, triggers: [String]) -> String { - var out = text - for trigger in triggers { - let token = trigger.trimmingCharacters(in: whitespaceAndPunctuation) - guard !token.isEmpty else { continue } - out = out.replacingOccurrences(of: token, with: "", options: [.caseInsensitive]) - } - return out.trimmingCharacters(in: whitespaceAndPunctuation) - } - - private static func normalizeTriggers(_ triggers: [String]) -> [TriggerTokens] { - var output: [TriggerTokens] = [] - for trigger in triggers { - let tokens = trigger - .split(whereSeparator: { $0.isWhitespace }) - .map { normalizeToken(String($0)) } - .filter { !$0.isEmpty } - if tokens.isEmpty { continue } - output.append(TriggerTokens(tokens: tokens)) - } - return output - } - - private static func normalizeSegments(_ segments: [WakeWordSegment]) -> [Token] { - segments.compactMap { segment in - let normalized = normalizeToken(segment.text) - guard !normalized.isEmpty else { return nil } - return Token( - normalized: normalized, - start: segment.start, - end: segment.end, - range: segment.range, - text: segment.text) - } - } - - private static func normalizeToken(_ token: String) -> String { - token - .trimmingCharacters(in: whitespaceAndPunctuation) - .lowercased() - } - - private static let whitespaceAndPunctuation = CharacterSet.whitespacesAndNewlines - .union(.punctuationCharacters) -} - -#if canImport(Speech) -import Speech - -public enum WakeWordSpeechSegments { - public static func from(transcription: SFTranscription, transcript: String) -> [WakeWordSegment] { - transcription.segments.map { segment in - let range = Range(segment.substringRange, in: transcript) - return WakeWordSegment( - text: segment.substring, - start: segment.timestamp, - duration: segment.duration, - range: range) - } - } -} -#endif diff --git a/Swabble/Sources/swabble/CLI/CLIRegistry.swift b/Swabble/Sources/swabble/CLI/CLIRegistry.swift deleted file mode 100644 index c47a9864f9a..00000000000 --- a/Swabble/Sources/swabble/CLI/CLIRegistry.swift +++ /dev/null @@ -1,71 +0,0 @@ -import Commander -import Foundation - -@available(macOS 26.0, *) -@MainActor -enum CLIRegistry { - static var descriptors: [CommandDescriptor] { - let serveDesc = descriptor(for: ServeCommand.self) - let transcribeDesc = descriptor(for: TranscribeCommand.self) - let testHookDesc = descriptor(for: TestHookCommand.self) - let micList = descriptor(for: MicList.self) - let micSet = descriptor(for: MicSet.self) - let micRoot = CommandDescriptor( - name: "mic", - abstract: "Microphone management", - discussion: nil, - signature: CommandSignature(), - subcommands: [micList, micSet]) - let serviceRoot = CommandDescriptor( - name: "service", - abstract: "launchd helper", - discussion: nil, - signature: CommandSignature(), - subcommands: [ - descriptor(for: ServiceInstall.self), - descriptor(for: ServiceUninstall.self), - descriptor(for: ServiceStatus.self) - ]) - let doctorDesc = descriptor(for: DoctorCommand.self) - let setupDesc = descriptor(for: SetupCommand.self) - let healthDesc = descriptor(for: HealthCommand.self) - let tailLogDesc = descriptor(for: TailLogCommand.self) - let startDesc = descriptor(for: StartCommand.self) - let stopDesc = descriptor(for: StopCommand.self) - let restartDesc = descriptor(for: RestartCommand.self) - let statusDesc = descriptor(for: StatusCommand.self) - - let rootSignature = CommandSignature().withStandardRuntimeFlags() - let root = CommandDescriptor( - name: "swabble", - abstract: "Speech hook daemon", - discussion: "Local wake-word → SpeechTranscriber → hook", - signature: rootSignature, - subcommands: [ - serveDesc, - transcribeDesc, - testHookDesc, - micRoot, - serviceRoot, - doctorDesc, - setupDesc, - healthDesc, - tailLogDesc, - startDesc, - stopDesc, - restartDesc, - statusDesc - ]) - return [root] - } - - private static func descriptor(for type: any ParsableCommand.Type) -> CommandDescriptor { - let sig = CommandSignature.describe(type.init()).withStandardRuntimeFlags() - return CommandDescriptor( - name: type.commandDescription.commandName ?? "", - abstract: type.commandDescription.abstract, - discussion: type.commandDescription.discussion, - signature: sig, - subcommands: []) - } -} diff --git a/Swabble/Sources/swabble/Commands/DoctorCommand.swift b/Swabble/Sources/swabble/Commands/DoctorCommand.swift deleted file mode 100644 index ec6c84ad44a..00000000000 --- a/Swabble/Sources/swabble/Commands/DoctorCommand.swift +++ /dev/null @@ -1,37 +0,0 @@ -import Commander -import Foundation -import Speech -import Swabble - -@MainActor -struct DoctorCommand: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription(commandName: "doctor", abstract: "Check Speech permission and config") - } - - @Option(name: .long("config"), help: "Path to config JSON") var configPath: String? - - init() {} - init(parsed: ParsedValues) { - self.init() - if let cfg = parsed.options["config"]?.last { configPath = cfg } - } - - mutating func run() async throws { - let auth = await SFSpeechRecognizer.authorizationStatus() - print("Speech auth: \(auth)") - do { - _ = try ConfigLoader.load(at: configURL) - print("Config: OK") - } catch { - print("Config missing or invalid; run setup") - } - let session = AVCaptureDevice.DiscoverySession( - deviceTypes: [.microphone, .external], - mediaType: .audio, - position: .unspecified) - print("Mics found: \(session.devices.count)") - } - - private var configURL: URL? { configPath.map { URL(fileURLWithPath: $0) } } -} diff --git a/Swabble/Sources/swabble/Commands/HealthCommand.swift b/Swabble/Sources/swabble/Commands/HealthCommand.swift deleted file mode 100644 index b3db452868d..00000000000 --- a/Swabble/Sources/swabble/Commands/HealthCommand.swift +++ /dev/null @@ -1,16 +0,0 @@ -import Commander -import Foundation - -@MainActor -struct HealthCommand: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription(commandName: "health", abstract: "Health probe") - } - - init() {} - init(parsed: ParsedValues) {} - - mutating func run() async throws { - print("ok") - } -} diff --git a/Swabble/Sources/swabble/Commands/MicCommands.swift b/Swabble/Sources/swabble/Commands/MicCommands.swift deleted file mode 100644 index 6430c86d529..00000000000 --- a/Swabble/Sources/swabble/Commands/MicCommands.swift +++ /dev/null @@ -1,62 +0,0 @@ -import AVFoundation -import Commander -import Foundation -import Swabble - -@MainActor -struct MicCommand: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription( - commandName: "mic", - abstract: "Microphone management", - subcommands: [MicList.self, MicSet.self]) - } -} - -@MainActor -struct MicList: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription(commandName: "list", abstract: "List input devices") - } - - init() {} - init(parsed: ParsedValues) {} - - mutating func run() async throws { - let session = AVCaptureDevice.DiscoverySession( - deviceTypes: [.microphone, .external], - mediaType: .audio, - position: .unspecified) - let devices = session.devices - if devices.isEmpty { print("no audio inputs found"); return } - for (idx, device) in devices.enumerated() { - print("[\(idx)] \(device.localizedName)") - } - } -} - -@MainActor -struct MicSet: ParsableCommand { - @Argument(help: "Device index from list") var index: Int = 0 - @Option(name: .long("config"), help: "Path to config JSON") var configPath: String? - - static var commandDescription: CommandDescription { - CommandDescription(commandName: "set", abstract: "Set default input device index") - } - - init() {} - init(parsed: ParsedValues) { - self.init() - if let value = parsed.positional.first, let intVal = Int(value) { index = intVal } - if let cfg = parsed.options["config"]?.last { configPath = cfg } - } - - mutating func run() async throws { - var cfg = try ConfigLoader.load(at: configURL) - cfg.audio.deviceIndex = index - try ConfigLoader.save(cfg, at: configURL) - print("saved device index \(index)") - } - - private var configURL: URL? { configPath.map { URL(fileURLWithPath: $0) } } -} diff --git a/Swabble/Sources/swabble/Commands/ServeCommand.swift b/Swabble/Sources/swabble/Commands/ServeCommand.swift deleted file mode 100644 index 705ecf41a65..00000000000 --- a/Swabble/Sources/swabble/Commands/ServeCommand.swift +++ /dev/null @@ -1,81 +0,0 @@ -import Commander -import Foundation -import Swabble -import SwabbleKit - -@available(macOS 26.0, *) -@MainActor -struct ServeCommand: ParsableCommand { - @Option(name: .long("config"), help: "Path to config JSON") var configPath: String? - @Flag(name: .long("no-wake"), help: "Disable wake word") var noWake: Bool = false - - static var commandDescription: CommandDescription { - CommandDescription( - commandName: "serve", - abstract: "Run swabble in the foreground") - } - - init() {} - - init(parsed: ParsedValues) { - self.init() - if parsed.flags.contains("noWake") { noWake = true } - if let cfg = parsed.options["config"]?.last { configPath = cfg } - } - - mutating func run() async throws { - var cfg: SwabbleConfig - do { - cfg = try ConfigLoader.load(at: configURL) - } catch { - cfg = SwabbleConfig() - try ConfigLoader.save(cfg, at: configURL) - } - if noWake { - cfg.wake.enabled = false - } - - let logger = Logger(level: LogLevel(configValue: cfg.logging.level) ?? .info) - logger.info("swabble serve starting (wake: \(cfg.wake.enabled ? cfg.wake.word : "disabled"))") - let pipeline = SpeechPipeline() - do { - let stream = try await pipeline.start( - localeIdentifier: cfg.speech.localeIdentifier, - etiquette: cfg.speech.etiquetteReplacements) - for await seg in stream { - if cfg.wake.enabled { - guard Self.matchesWake(text: seg.text, cfg: cfg) else { continue } - } - let stripped = Self.stripWake(text: seg.text, cfg: cfg) - let job = HookJob(text: stripped, timestamp: Date()) - let executor = HookExecutor(config: cfg) - try await executor.run(job: job) - if cfg.transcripts.enabled { - await TranscriptsStore.shared.append(text: stripped) - } - if seg.isFinal { - logger.info("final: \(stripped)") - } else { - logger.debug("partial: \(stripped)") - } - } - } catch { - logger.error("serve error: \(error)") - throw error - } - } - - private var configURL: URL? { - configPath.map { URL(fileURLWithPath: $0) } - } - - private static func matchesWake(text: String, cfg: SwabbleConfig) -> Bool { - let triggers = [cfg.wake.word] + cfg.wake.aliases - return WakeWordGate.matchesTextOnly(text: text, triggers: triggers) - } - - private static func stripWake(text: String, cfg: SwabbleConfig) -> String { - let triggers = [cfg.wake.word] + cfg.wake.aliases - return WakeWordGate.stripWake(text: text, triggers: triggers) - } -} diff --git a/Swabble/Sources/swabble/Commands/ServiceCommands.swift b/Swabble/Sources/swabble/Commands/ServiceCommands.swift deleted file mode 100644 index 8690e95628d..00000000000 --- a/Swabble/Sources/swabble/Commands/ServiceCommands.swift +++ /dev/null @@ -1,77 +0,0 @@ -import Commander -import Foundation - -@MainActor -struct ServiceRootCommand: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription( - commandName: "service", - abstract: "Manage launchd agent", - subcommands: [ServiceInstall.self, ServiceUninstall.self, ServiceStatus.self]) - } -} - -private enum LaunchdHelper { - static let label = "com.swabble.agent" - - static var plistURL: URL { - FileManager.default - .homeDirectoryForCurrentUser - .appendingPathComponent("Library/LaunchAgents/\(label).plist") - } - - static func writePlist(executable: String) throws { - let plist: [String: Any] = [ - "Label": label, - "ProgramArguments": [executable, "serve"], - "RunAtLoad": true, - "KeepAlive": true - ] - let data = try PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0) - try data.write(to: plistURL) - } - - static func removePlist() throws { - try? FileManager.default.removeItem(at: plistURL) - } -} - -@MainActor -struct ServiceInstall: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription(commandName: "install", abstract: "Install user launch agent") - } - - mutating func run() async throws { - let exe = CommandLine.arguments.first ?? "/usr/local/bin/swabble" - try LaunchdHelper.writePlist(executable: exe) - print("launchctl load -w \(LaunchdHelper.plistURL.path)") - } -} - -@MainActor -struct ServiceUninstall: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription(commandName: "uninstall", abstract: "Remove launch agent") - } - - mutating func run() async throws { - try LaunchdHelper.removePlist() - print("launchctl bootout gui/$(id -u)/\(LaunchdHelper.label)") - } -} - -@MainActor -struct ServiceStatus: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription(commandName: "status", abstract: "Show launch agent status") - } - - mutating func run() async throws { - if FileManager.default.fileExists(atPath: LaunchdHelper.plistURL.path) { - print("plist present at \(LaunchdHelper.plistURL.path)") - } else { - print("launchd plist not installed") - } - } -} diff --git a/Swabble/Sources/swabble/Commands/SetupCommand.swift b/Swabble/Sources/swabble/Commands/SetupCommand.swift deleted file mode 100644 index 469de233d11..00000000000 --- a/Swabble/Sources/swabble/Commands/SetupCommand.swift +++ /dev/null @@ -1,26 +0,0 @@ -import Commander -import Foundation -import Swabble - -@MainActor -struct SetupCommand: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription(commandName: "setup", abstract: "Write default config") - } - - @Option(name: .long("config"), help: "Path to config JSON") var configPath: String? - - init() {} - init(parsed: ParsedValues) { - self.init() - if let cfg = parsed.options["config"]?.last { configPath = cfg } - } - - mutating func run() async throws { - let cfg = SwabbleConfig() - try ConfigLoader.save(cfg, at: configURL) - print("wrote config to \(configURL?.path ?? SwabbleConfig.defaultPath.path)") - } - - private var configURL: URL? { configPath.map { URL(fileURLWithPath: $0) } } -} diff --git a/Swabble/Sources/swabble/Commands/StartStopCommands.swift b/Swabble/Sources/swabble/Commands/StartStopCommands.swift deleted file mode 100644 index 641cd923a0d..00000000000 --- a/Swabble/Sources/swabble/Commands/StartStopCommands.swift +++ /dev/null @@ -1,35 +0,0 @@ -import Commander -import Foundation - -@MainActor -struct StartCommand: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription(commandName: "start", abstract: "Start swabble (foreground placeholder)") - } - - mutating func run() async throws { - print("start: launchd helper not implemented; run 'swabble serve' instead") - } -} - -@MainActor -struct StopCommand: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription(commandName: "stop", abstract: "Stop swabble (placeholder)") - } - - mutating func run() async throws { - print("stop: launchd helper not implemented yet") - } -} - -@MainActor -struct RestartCommand: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription(commandName: "restart", abstract: "Restart swabble (placeholder)") - } - - mutating func run() async throws { - print("restart: launchd helper not implemented yet") - } -} diff --git a/Swabble/Sources/swabble/Commands/StatusCommand.swift b/Swabble/Sources/swabble/Commands/StatusCommand.swift deleted file mode 100644 index 19db16117ab..00000000000 --- a/Swabble/Sources/swabble/Commands/StatusCommand.swift +++ /dev/null @@ -1,34 +0,0 @@ -import Commander -import Foundation -import Swabble - -@MainActor -struct StatusCommand: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription(commandName: "status", abstract: "Show daemon state") - } - - @Option(name: .long("config"), help: "Path to config JSON") var configPath: String? - - init() {} - init(parsed: ParsedValues) { - self.init() - if let cfg = parsed.options["config"]?.last { configPath = cfg } - } - - mutating func run() async throws { - let cfg = try? ConfigLoader.load(at: configURL) - let wake = cfg?.wake.word ?? "clawd" - let wakeEnabled = cfg?.wake.enabled ?? false - let latest = await TranscriptsStore.shared.latest().suffix(3) - print("wake: \(wakeEnabled ? wake : "disabled")") - if latest.isEmpty { - print("transcripts: (none yet)") - } else { - print("last transcripts:") - latest.forEach { print("- \($0)") } - } - } - - private var configURL: URL? { configPath.map { URL(fileURLWithPath: $0) } } -} diff --git a/Swabble/Sources/swabble/Commands/TailLogCommand.swift b/Swabble/Sources/swabble/Commands/TailLogCommand.swift deleted file mode 100644 index 451ed37de41..00000000000 --- a/Swabble/Sources/swabble/Commands/TailLogCommand.swift +++ /dev/null @@ -1,20 +0,0 @@ -import Commander -import Foundation -import Swabble - -@MainActor -struct TailLogCommand: ParsableCommand { - static var commandDescription: CommandDescription { - CommandDescription(commandName: "tail-log", abstract: "Tail recent transcripts") - } - - init() {} - init(parsed: ParsedValues) {} - - mutating func run() async throws { - let latest = await TranscriptsStore.shared.latest() - for line in latest.suffix(10) { - print(line) - } - } -} diff --git a/Swabble/Sources/swabble/Commands/TestHookCommand.swift b/Swabble/Sources/swabble/Commands/TestHookCommand.swift deleted file mode 100644 index 226776ceb89..00000000000 --- a/Swabble/Sources/swabble/Commands/TestHookCommand.swift +++ /dev/null @@ -1,30 +0,0 @@ -import Commander -import Foundation -import Swabble - -@MainActor -struct TestHookCommand: ParsableCommand { - @Argument(help: "Text to send to hook") var text: String - @Option(name: .long("config"), help: "Path to config JSON") var configPath: String? - - static var commandDescription: CommandDescription { - CommandDescription(commandName: "test-hook", abstract: "Invoke the configured hook with text") - } - - init() {} - - init(parsed: ParsedValues) { - self.init() - if let positional = parsed.positional.first { text = positional } - if let cfg = parsed.options["config"]?.last { configPath = cfg } - } - - mutating func run() async throws { - let cfg = try ConfigLoader.load(at: configURL) - let executor = HookExecutor(config: cfg) - try await executor.run(job: HookJob(text: text, timestamp: Date())) - print("hook invoked") - } - - private var configURL: URL? { configPath.map { URL(fileURLWithPath: $0) } } -} diff --git a/Swabble/Sources/swabble/Commands/TranscribeCommand.swift b/Swabble/Sources/swabble/Commands/TranscribeCommand.swift deleted file mode 100644 index 1bedca3fc0a..00000000000 --- a/Swabble/Sources/swabble/Commands/TranscribeCommand.swift +++ /dev/null @@ -1,61 +0,0 @@ -import AVFoundation -import Commander -import Foundation -import Speech -import Swabble - -@MainActor -struct TranscribeCommand: ParsableCommand { - @Argument(help: "Path to audio/video file") var inputFile: String = "" - @Option(name: .long("locale"), help: "Locale identifier", parsing: .singleValue) var locale: String = Locale.current - .identifier - @Flag(help: "Censor etiquette-sensitive content") var censor: Bool = false - @Option(name: .long("output"), help: "Output file path") var outputFile: String? - @Option(name: .long("format"), help: "Output format txt|srt") var format: String = "txt" - @Option(name: .long("max-length"), help: "Max sentence length for srt") var maxLength: Int = 40 - - static var commandDescription: CommandDescription { - CommandDescription( - commandName: "transcribe", - abstract: "Transcribe a media file locally") - } - - init() {} - - init(parsed: ParsedValues) { - self.init() - if let positional = parsed.positional.first { inputFile = positional } - if let loc = parsed.options["locale"]?.last { locale = loc } - if parsed.flags.contains("censor") { censor = true } - if let out = parsed.options["output"]?.last { outputFile = out } - if let fmt = parsed.options["format"]?.last { format = fmt } - if let len = parsed.options["maxLength"]?.last, let intVal = Int(len) { maxLength = intVal } - } - - mutating func run() async throws { - let fileURL = URL(fileURLWithPath: inputFile) - let audioFile = try AVAudioFile(forReading: fileURL) - - let outputFormat = OutputFormat(rawValue: format) ?? .txt - - let transcriber = SpeechTranscriber( - locale: Locale(identifier: locale), - transcriptionOptions: censor ? [.etiquetteReplacements] : [], - reportingOptions: [], - attributeOptions: outputFormat.needsAudioTimeRange ? [.audioTimeRange] : []) - let analyzer = SpeechAnalyzer(modules: [transcriber]) - try await analyzer.start(inputAudioFile: audioFile, finishAfterFile: true) - - var transcript: AttributedString = "" - for try await result in transcriber.results { - transcript += result.text - } - - let output = outputFormat.text(for: transcript, maxLength: maxLength) - if let path = outputFile { - try output.write(to: URL(fileURLWithPath: path), atomically: false, encoding: .utf8) - } else { - print(output) - } - } -} diff --git a/Swabble/Sources/swabble/main.swift b/Swabble/Sources/swabble/main.swift deleted file mode 100644 index a534c68d969..00000000000 --- a/Swabble/Sources/swabble/main.swift +++ /dev/null @@ -1,151 +0,0 @@ -import Commander -import Foundation - -@available(macOS 26.0, *) -@MainActor -private func runCLI() async -> Int32 { - do { - let descriptors = CLIRegistry.descriptors - let program = Program(descriptors: descriptors) - let invocation = try program.resolve(argv: CommandLine.arguments) - try await dispatch(invocation: invocation) - return 0 - } catch { - fputs("error: \(error)\n", stderr) - return 1 - } -} - -@available(macOS 26.0, *) -@MainActor -private func dispatch(invocation: CommandInvocation) async throws { - let parsed = invocation.parsedValues - let path = invocation.path - guard let first = path.first else { throw CommanderProgramError.missingCommand } - - switch first { - case "swabble": - try await dispatchSwabble(parsed: parsed, path: path) - default: - throw CommanderProgramError.unknownCommand(first) - } -} - -@available(macOS 26.0, *) -@MainActor -private func dispatchSwabble(parsed: ParsedValues, path: [String]) async throws { - let sub = try subcommand(path, index: 1, command: "swabble") - switch sub { - case "mic": - try await dispatchMic(parsed: parsed, path: path) - case "service": - try await dispatchService(path: path) - default: - let handlers = swabbleHandlers(parsed: parsed) - guard let handler = handlers[sub] else { - throw CommanderProgramError.unknownSubcommand(command: "swabble", name: sub) - } - try await handler() - } -} - -@available(macOS 26.0, *) -@MainActor -private func swabbleHandlers(parsed: ParsedValues) -> [String: () async throws -> Void] { - [ - "serve": { - var cmd = ServeCommand(parsed: parsed) - try await cmd.run() - }, - "transcribe": { - var cmd = TranscribeCommand(parsed: parsed) - try await cmd.run() - }, - "test-hook": { - var cmd = TestHookCommand(parsed: parsed) - try await cmd.run() - }, - "doctor": { - var cmd = DoctorCommand(parsed: parsed) - try await cmd.run() - }, - "setup": { - var cmd = SetupCommand(parsed: parsed) - try await cmd.run() - }, - "health": { - var cmd = HealthCommand(parsed: parsed) - try await cmd.run() - }, - "tail-log": { - var cmd = TailLogCommand(parsed: parsed) - try await cmd.run() - }, - "start": { - var cmd = StartCommand() - try await cmd.run() - }, - "stop": { - var cmd = StopCommand() - try await cmd.run() - }, - "restart": { - var cmd = RestartCommand() - try await cmd.run() - }, - "status": { - var cmd = StatusCommand() - try await cmd.run() - } - ] -} - -@available(macOS 26.0, *) -@MainActor -private func dispatchMic(parsed: ParsedValues, path: [String]) async throws { - let micSub = try subcommand(path, index: 2, command: "mic") - switch micSub { - case "list": - var cmd = MicList(parsed: parsed) - try await cmd.run() - case "set": - var cmd = MicSet(parsed: parsed) - try await cmd.run() - default: - throw CommanderProgramError.unknownSubcommand(command: "mic", name: micSub) - } -} - -@available(macOS 26.0, *) -@MainActor -private func dispatchService(path: [String]) async throws { - let svcSub = try subcommand(path, index: 2, command: "service") - switch svcSub { - case "install": - var cmd = ServiceInstall() - try await cmd.run() - case "uninstall": - var cmd = ServiceUninstall() - try await cmd.run() - case "status": - var cmd = ServiceStatus() - try await cmd.run() - default: - throw CommanderProgramError.unknownSubcommand(command: "service", name: svcSub) - } -} - -private func subcommand(_ path: [String], index: Int, command: String) throws -> String { - guard path.count > index else { - throw CommanderProgramError.missingSubcommand(command: command) - } - return path[index] -} - -if #available(macOS 26.0, *) { - let exitCode = await runCLI() - exit(exitCode) -} else { - fputs("error: swabble requires macOS 26 or newer\n", stderr) - exit(1) -} diff --git a/Swabble/Tests/SwabbleKitTests/WakeWordGateTests.swift b/Swabble/Tests/SwabbleKitTests/WakeWordGateTests.swift deleted file mode 100644 index 5cc283c35ae..00000000000 --- a/Swabble/Tests/SwabbleKitTests/WakeWordGateTests.swift +++ /dev/null @@ -1,63 +0,0 @@ -import Foundation -import SwabbleKit -import Testing - -@Suite struct WakeWordGateTests { - @Test func matchRequiresGapAfterTrigger() { - let transcript = "hey clawd do thing" - let segments = makeSegments( - transcript: transcript, - words: [ - ("hey", 0.0, 0.1), - ("clawd", 0.2, 0.1), - ("do", 0.35, 0.1), - ("thing", 0.5, 0.1), - ]) - let config = WakeWordGateConfig(triggers: ["clawd"], minPostTriggerGap: 0.3) - #expect(WakeWordGate.match(transcript: transcript, segments: segments, config: config) == nil) - } - - @Test func matchAllowsGapAndExtractsCommand() { - let transcript = "hey clawd do thing" - let segments = makeSegments( - transcript: transcript, - words: [ - ("hey", 0.0, 0.1), - ("clawd", 0.2, 0.1), - ("do", 0.9, 0.1), - ("thing", 1.1, 0.1), - ]) - let config = WakeWordGateConfig(triggers: ["clawd"], minPostTriggerGap: 0.3) - let match = WakeWordGate.match(transcript: transcript, segments: segments, config: config) - #expect(match?.command == "do thing") - } - - @Test func matchHandlesMultiWordTriggers() { - let transcript = "hey clawd do it" - let segments = makeSegments( - transcript: transcript, - words: [ - ("hey", 0.0, 0.1), - ("clawd", 0.2, 0.1), - ("do", 0.8, 0.1), - ("it", 1.0, 0.1), - ]) - let config = WakeWordGateConfig(triggers: ["hey clawd"], minPostTriggerGap: 0.3) - let match = WakeWordGate.match(transcript: transcript, segments: segments, config: config) - #expect(match?.command == "do it") - } -} - -private func makeSegments( - transcript: String, - words: [(String, TimeInterval, TimeInterval)]) --> [WakeWordSegment] { - var searchStart = transcript.startIndex - var output: [WakeWordSegment] = [] - for (word, start, duration) in words { - let range = transcript.range(of: word, range: searchStart../dev/null; then - echo "swiftlint not installed" >&2 - exit 1 -fi -swiftlint --config "$CONFIG" diff --git a/VISION.md b/VISION.md deleted file mode 100644 index 4ff70189ab8..00000000000 --- a/VISION.md +++ /dev/null @@ -1,110 +0,0 @@ -## OpenClaw Vision - -OpenClaw is the AI that actually does things. -It runs on your devices, in your channels, with your rules. - -This document explains the current state and direction of the project. -We are still early, so iteration is fast. -Project overview and developer docs: [`README.md`](README.md) -Contribution guide: [`CONTRIBUTING.md`](CONTRIBUTING.md) - -OpenClaw started as a personal playground to learn AI and build something genuinely useful: -an assistant that can run real tasks on a real computer. -It evolved through several names and shells: Warelay -> Clawdbot -> Moltbot -> OpenClaw. - -The goal: a personal assistant that is easy to use, supports a wide range of platforms, and respects privacy and security. - -The current focus is: - -Priority: - -- Security and safe defaults -- Bug fixes and stability -- Setup reliability and first-run UX - -Next priorities: - -- Supporting all major model providers -- Improving support for major messaging channels (and adding a few high-demand ones) -- Performance and test infrastructure -- Better computer-use and agent harness capabilities -- Ergonomics across CLI and web frontend -- Companion apps on macOS, iOS, Android, Windows, and Linux - -Contribution rules: - -- One PR = one issue/topic. Do not bundle multiple unrelated fixes/features. -- PRs over ~5,000 changed lines are reviewed only in exceptional circumstances. -- Do not open large batches of tiny PRs at once; each PR has review cost. -- For very small related fixes, grouping into one focused PR is encouraged. - -## Security - -Security in OpenClaw is a deliberate tradeoff: strong defaults without killing capability. -The goal is to stay powerful for real work while making risky paths explicit and operator-controlled. - -Canonical security policy and reporting: - -- [`SECURITY.md`](SECURITY.md) - -We prioritize secure defaults, but also expose clear knobs for trusted high-power workflows. - -## Plugins & Memory - -OpenClaw has an extensive plugin API. -Core stays lean; optional capability should usually ship as plugins. - -Preferred plugin path is npm package distribution plus local extension loading for development. -If you build a plugin, host and maintain it in your own repository. -The bar for adding optional plugins to core is intentionally high. -Plugin docs: [`docs/tools/plugin.md`](docs/tools/plugin.md) -Community plugin listing + PR bar: https://docs.openclaw.ai/plugins/community - -Memory is a special plugin slot where only one memory plugin can be active at a time. -Today we ship multiple memory options; over time we plan to converge on one recommended default path. - -### Skills - -We still ship some bundled skills for baseline UX. -New skills should be published to ClawHub first (`clawhub.ai`), not added to core by default. -Core skill additions should be rare and require a strong product or security reason. - -### MCP Support - -OpenClaw supports MCP through `mcporter`: https://github.com/steipete/mcporter - -This keeps MCP integration flexible and decoupled from core runtime: - -- add or change MCP servers without restarting the gateway -- keep core tool/context surface lean -- reduce MCP churn impact on core stability and security - -For now, we prefer this bridge model over building first-class MCP runtime into core. -If there is an MCP server or feature `mcporter` does not support yet, please open an issue there. - -### Setup - -OpenClaw is currently terminal-first by design. -This keeps setup explicit: users see docs, auth, permissions, and security posture up front. - -Long term, we want easier onboarding flows as hardening matures. -We do not want convenience wrappers that hide critical security decisions from users. - -### Why TypeScript? - -OpenClaw is primarily an orchestration system: prompts, tools, protocols, and integrations. -TypeScript was chosen to keep OpenClaw hackable by default. -It is widely known, fast to iterate in, and easy to read, modify, and extend. - -## What We Will Not Merge (For Now) - -- New core skills when they can live on ClawHub -- Full-doc translation sets for all docs (deferred; we plan AI-generated translations later) -- Commercial service integrations that do not clearly fit the model-provider category -- Wrapper channels around already supported channels without a clear capability or security gap -- First-class MCP runtime in core when `mcporter` already provides the integration path -- Agent-hierarchy frameworks (manager-of-managers / nested planner trees) as a default architecture -- Heavy orchestration layers that duplicate existing agent and tool infrastructure - -This list is a roadmap guardrail, not a law of physics. -Strong user demand and strong technical rationale can change it. diff --git a/appcast.xml b/appcast.xml deleted file mode 100644 index ac9369da007..00000000000 --- a/appcast.xml +++ /dev/null @@ -1,363 +0,0 @@ - - - - OpenClaw - - 2026.2.14 - Sun, 15 Feb 2026 04:24:34 +0100 - https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml - 202602140 - 2026.2.14 - 15.0 - OpenClaw 2026.2.14 -

Changes

-
    -
  • Telegram: add poll sending via openclaw message poll (duration seconds, silent delivery, anonymity controls). (#16209) Thanks @robbyczgw-cla.
  • -
  • Slack/Discord: add dmPolicy + allowFrom config aliases for DM access control; legacy dm.policy + dm.allowFrom keys remain supported and openclaw doctor --fix can migrate them.
  • -
  • Discord: allow exec approval prompts to target channels or both DM+channel via channels.discord.execApprovals.target. (#16051) Thanks @leonnardo.
  • -
  • Sandbox: add sandbox.browser.binds to configure browser-container bind mounts separately from exec containers. (#16230) Thanks @seheepeak.
  • -
  • Discord: add debug logging for message routing decisions to improve --debug tracing. (#16202) Thanks @jayleekr.
  • -
-

Fixes

-
    -
  • CLI/Plugins: ensure openclaw message send exits after successful delivery across plugin-backed channels so one-shot sends do not hang. (#16491) Thanks @yinghaosang.
  • -
  • CLI/Plugins: run registered plugin gateway_stop hooks before openclaw message exits (success and failure paths), so plugin-backed channels can clean up one-shot CLI resources. (#16580) Thanks @gumadeiras.
  • -
  • WhatsApp: honor per-account dmPolicy overrides (account-level settings now take precedence over channel defaults for inbound DMs). (#10082) Thanks @mcaxtr.
  • -
  • Telegram: when channels.telegram.commands.native is false, exclude plugin commands from setMyCommands menu registration while keeping plugin slash handlers callable. (#15132) Thanks @Glucksberg.
  • -
  • LINE: return 200 OK for Developers Console "Verify" requests ({"events":[]}) without X-Line-Signature, while still requiring signatures for real deliveries. (#16582) Thanks @arosstale.
  • -
  • Cron: deliver text-only output directly when delivery.to is set so cron recipients get full output instead of summaries. (#16360) Thanks @thewilloftheshadow.
  • -
  • Cron/Slack: preserve agent identity (name and icon) when cron jobs deliver outbound messages. (#16242) Thanks @robbyczgw-cla.
  • -
  • Media: accept MEDIA:-prefixed paths (lenient whitespace) when loading outbound media to prevent ENOENT for tool-returned local media paths. (#13107) Thanks @mcaxtr.
  • -
  • Agents: deliver tool result media (screenshots, images, audio) to channels regardless of verbose level. (#11735) Thanks @strelov1.
  • -
  • Agents/Image tool: allow workspace-local image paths by including the active workspace directory in local media allowlists, and trust sandbox-validated paths in image loaders to prevent false "not under an allowed directory" rejections. (#15541)
  • -
  • Agents/Image tool: propagate the effective workspace root into tool wiring so workspace-local image paths are accepted by default when running without an explicit workspaceDir. (#16722)
  • -
  • BlueBubbles: include sender identity in group chat envelopes and pass clean message text to the agent prompt, aligning with iMessage/Signal formatting. (#16210) Thanks @zerone0x.
  • -
  • CLI: fix lazy core command registration so top-level maintenance commands (doctor, dashboard, reset, uninstall) resolve correctly instead of exposing a non-functional maintenance placeholder command.
  • -
  • CLI/Dashboard: when gateway.bind=lan, generate localhost dashboard URLs to satisfy browser secure-context requirements while preserving non-LAN bind behavior. (#16434) Thanks @BinHPdev.
  • -
  • TUI/Gateway: resolve local gateway target URL from gateway.bind mode (tailnet/lan) instead of hardcoded localhost so openclaw tui connects when gateway is non-loopback. (#16299) Thanks @cortexuvula.
  • -
  • TUI: honor explicit --session in openclaw tui even when session.scope is global, so named sessions no longer collapse into shared global history. (#16575) Thanks @cinqu.
  • -
  • TUI: use available terminal width for session name display in searchable select lists. (#16238) Thanks @robbyczgw-cla.
  • -
  • TUI: refactor searchable select list description layout and add regression coverage for ANSI-highlight width bounds.
  • -
  • TUI: preserve in-flight streaming replies when a different run finalizes concurrently (avoid clearing active run or reloading history mid-stream). (#10704) Thanks @axschr73.
  • -
  • TUI: keep pre-tool streamed text visible when later tool-boundary deltas temporarily omit earlier text blocks. (#6958) Thanks @KrisKind75.
  • -
  • TUI: sanitize ANSI/control-heavy history text, redact binary-like lines, and split pathological long unbroken tokens before rendering to prevent startup crashes on binary attachment history. (#13007) Thanks @wilkinspoe.
  • -
  • TUI: harden render-time sanitizer for narrow terminals by chunking moderately long unbroken tokens and adding fast-path sanitization guards to reduce overhead on normal text. (#5355) Thanks @tingxueren.
  • -
  • TUI: render assistant body text in terminal default foreground (instead of fixed light ANSI color) so contrast remains readable on light themes such as Solarized Light. (#16750) Thanks @paymog.
  • -
  • TUI/Hooks: pass explicit reset reason (new vs reset) through sessions.reset and emit internal command hooks for gateway-triggered resets so /new hook workflows fire in TUI/webchat.
  • -
  • Cron: prevent cron list/cron status from silently skipping past-due recurring jobs by using maintenance recompute semantics. (#16156) Thanks @zerone0x.
  • -
  • Cron: repair missing/corrupt nextRunAtMs for the updated job without globally recomputing unrelated due jobs during cron update. (#15750)
  • -
  • Cron: skip missed-job replay on startup for jobs interrupted mid-run (stale runningAtMs markers), preventing restart loops for self-restarting jobs such as update tasks. (#16694) Thanks @sbmilburn.
  • -
  • Discord: prefer gateway guild id when logging inbound messages so cached-miss guilds do not appear as guild=dm. Thanks @thewilloftheshadow.
  • -
  • Discord: treat empty per-guild channels: {} config maps as no channel allowlist (not deny-all), so groupPolicy: "open" guilds without explicit channel entries continue to receive messages. (#16714) Thanks @xqliu.
  • -
  • Models/CLI: guard models status string trimming paths to prevent crashes from malformed non-string config values. (#16395) Thanks @BinHPdev.
  • -
  • Gateway/Subagents: preserve queued announce items and summary state on delivery errors, retry failed announce drains, and avoid dropping unsent announcements on timeout/failure. (#16729) Thanks @Clawdette-Workspace.
  • -
  • Gateway/Sessions: abort active embedded runs and clear queued session work before sessions.reset, returning unavailable if the run does not stop in time. (#16576) Thanks @Grynn.
  • -
  • Sessions/Agents: harden transcript path resolution for mismatched agent context by preserving explicit store roots and adding safe absolute-path fallback to the correct agent sessions directory. (#16288) Thanks @robbyczgw-cla.
  • -
  • Agents: add a safety timeout around embedded session.compact() to ensure stalled compaction runs settle and release blocked session lanes. (#16331) Thanks @BinHPdev.
  • -
  • Agents: keep unresolved mutating tool failures visible until the same action retry succeeds, scope mutation-error surfacing to mutating calls (including session_status model changes), and dedupe duplicate failure warnings in outbound replies. (#16131) Thanks @Swader.
  • -
  • Agents/Process/Bootstrap: preserve unbounded process log offset-only pagination (default tail applies only when both offset and limit are omitted) and enforce strict bootstrapTotalMaxChars budgeting across injected bootstrap content (including markers), skipping additional injection when remaining budget is too small. (#16539) Thanks @CharlieGreenman.
  • -
  • Agents/Workspace: persist bootstrap onboarding state so partially initialized workspaces recover missing BOOTSTRAP.md once, while completed onboarding keeps BOOTSTRAP deleted even if runtime files are later recreated. Thanks @gumadeiras.
  • -
  • Agents/Workspace: create BOOTSTRAP.md when core workspace files are seeded in partially initialized workspaces, while keeping BOOTSTRAP one-shot after onboarding deletion. (#16457) Thanks @robbyczgw-cla.
  • -
  • Agents: classify external timeout aborts during compaction the same as internal timeouts, preventing unnecessary auth-profile rotation and preserving compaction-timeout snapshot fallback behavior. (#9855) Thanks @mverrilli.
  • -
  • Agents: treat empty-stream provider failures (request ended without sending any chunks) as timeout-class failover signals, enabling auth-profile rotation/fallback and showing a friendly timeout message instead of raw provider errors. (#10210) Thanks @zenchantlive.
  • -
  • Agents: treat read tool file_path arguments as valid in tool-start diagnostics to avoid false “read tool called without path” warnings when alias parameters are used. (#16717) Thanks @Stache73.
  • -
  • Ollama/Agents: avoid forcing tag enforcement for Ollama models, which could suppress all output as (no output). (#16191) Thanks @Glucksberg.
  • -
  • Plugins: suppress false duplicate plugin id warnings when the same extension is discovered via multiple paths (config/workspace/global vs bundled), while still warning on genuine duplicates. (#16222) Thanks @shadril238.
  • -
  • Skills: watch SKILL.md only when refreshing skills snapshot to avoid file-descriptor exhaustion in large data trees. (#11325) Thanks @household-bard.
  • -
  • Memory/QMD: make memory status read-only by skipping QMD boot update/embed side effects for status-only manager checks.
  • -
  • Memory/QMD: keep original QMD failures when builtin fallback initialization fails (for example missing embedding API keys), instead of replacing them with fallback init errors.
  • -
  • Memory/Builtin: keep memory status dirty reporting stable across invocations by deriving status-only manager dirty state from persisted index metadata instead of process-start defaults. (#10863) Thanks @BarryYangi.
  • -
  • Memory/QMD: cap QMD command output buffering to prevent memory exhaustion from pathological qmd command output.
  • -
  • Memory/QMD: parse qmd scope keys once per request to avoid repeated parsing in scope checks.
  • -
  • Memory/QMD: query QMD index using exact docid matches before falling back to prefix lookup for better recall correctness and index efficiency.
  • -
  • Memory/QMD: pass result limits to search/vsearch commands so QMD can cap results earlier.
  • -
  • Memory/QMD: avoid reading full markdown files when a from/lines window is requested in QMD reads.
  • -
  • Memory/QMD: skip rewriting unchanged session export markdown files during sync to reduce disk churn.
  • -
  • Memory/QMD: make QMD result JSON parsing resilient to noisy command output by extracting the first JSON array from noisy stdout.
  • -
  • Memory/QMD: treat prefixed no results found marker output as an empty result set in qmd JSON parsing. (#11302) Thanks @blazerui.
  • -
  • Memory/QMD: avoid multi-collection query ranking corruption by running one qmd query -c per managed collection and merging by best score (also used for search/vsearch fallback-to-query). (#16740) Thanks @volarian-vai.
  • -
  • Memory/QMD: detect null-byte ENOTDIR update failures, rebuild managed collections once, and retry update to self-heal corrupted collection metadata. (#12919) Thanks @jorgejhms.
  • -
  • Memory/QMD/Security: add rawKeyPrefix support for QMD scope rules and preserve legacy keyPrefix: "agent:..." matching, preventing scoped deny bypass when operators match agent-prefixed session keys.
  • -
  • Memory/Builtin: narrow memory watcher targets to markdown globs and ignore dependency/venv directories to reduce file-descriptor pressure during memory sync startup. (#11721) Thanks @rex05ai.
  • -
  • Security/Memory-LanceDB: treat recalled memories as untrusted context (escape injected memory text + explicit non-instruction framing), skip likely prompt-injection payloads during auto-capture, and restrict auto-capture to user messages to reduce memory-poisoning risk. (#12524) Thanks @davidschmid24.
  • -
  • Security/Memory-LanceDB: require explicit autoCapture: true opt-in (default is now disabled) to prevent automatic PII capture unless operators intentionally enable it. (#12552) Thanks @fr33d3m0n.
  • -
  • Diagnostics/Memory: prune stale diagnostic session state entries and cap tracked session states to prevent unbounded in-memory growth on long-running gateways. (#5136) Thanks @coygeek and @vignesh07.
  • -
  • Gateway/Memory: clean up agentRunSeq tracking on run completion/abort and enforce maintenance-time cap pruning to prevent unbounded sequence-map growth over long uptimes. (#6036) Thanks @coygeek and @vignesh07.
  • -
  • Auto-reply/Memory: bound ABORT_MEMORY growth by evicting oldest entries and deleting reset (false) flags so abort state tracking cannot grow unbounded over long uptimes. (#6629) Thanks @coygeek and @vignesh07.
  • -
  • Slack/Memory: bound thread-starter cache growth with TTL + max-size pruning to prevent long-running Slack gateways from accumulating unbounded thread cache state. (#5258) Thanks @coygeek and @vignesh07.
  • -
  • Outbound/Memory: bound directory cache growth with max-size eviction and proactive TTL pruning to prevent long-running gateways from accumulating unbounded directory entries. (#5140) Thanks @coygeek and @vignesh07.
  • -
  • Skills/Memory: remove disconnected nodes from remote-skills cache to prevent stale node metadata from accumulating over long uptimes. (#6760) Thanks @coygeek.
  • -
  • Sandbox/Tools: make sandbox file tools bind-mount aware (including absolute container paths) and enforce read-only bind semantics for writes. (#16379) Thanks @tasaankaeris.
  • -
  • Media/Security: allow local media reads from OpenClaw state workspace/ and sandboxes/ roots by default so generated workspace media can be delivered without unsafe global path bypasses. (#15541) Thanks @lanceji.
  • -
  • Media/Security: harden local media allowlist bypasses by requiring an explicit readFile override when callers mark paths as validated, and reject filesystem-root localRoots entries. (#16739)
  • -
  • Discord/Security: harden voice message media loading (SSRF + allowed-local-root checks) so tool-supplied paths/URLs cannot be used to probe internal URLs or read arbitrary local files.
  • -
  • Security/BlueBubbles: require explicit mediaLocalRoots allowlists for local outbound media path reads to prevent local file disclosure. (#16322) Thanks @mbelinky.
  • -
  • Security/BlueBubbles: reject ambiguous shared-path webhook routing when multiple webhook targets match the same guid/password.
  • -
  • Security/BlueBubbles: harden BlueBubbles webhook auth behind reverse proxies by only accepting passwordless webhooks for direct localhost loopback requests (forwarded/proxied requests now require a password). Thanks @simecek.
  • -
  • Feishu/Security: harden media URL fetching against SSRF and local file disclosure. (#16285) Thanks @mbelinky.
  • -
  • Security/Zalo: reject ambiguous shared-path webhook routing when multiple webhook targets match the same secret.
  • -
  • Security/Nostr: require loopback source and block cross-origin profile mutation/import attempts. Thanks @vincentkoc.
  • -
  • Security/Signal: harden signal-cli archive extraction during install to prevent path traversal outside the install root.
  • -
  • Security/Hooks: restrict hook transform modules to ~/.openclaw/hooks/transforms (prevents path traversal/escape module loads via config). Config note: hooks.transformsDir must now be within that directory. Thanks @akhmittra.
  • -
  • Security/Hooks: ignore hook package manifest entries that point outside the package directory (prevents out-of-tree handler loads during hook discovery).
  • -
  • Security/Archive: enforce archive extraction entry/size limits to prevent resource exhaustion from high-expansion ZIP/TAR archives. Thanks @vincentkoc.
  • -
  • Security/Media: reject oversized base64-backed input media before decoding to avoid large allocations. Thanks @vincentkoc.
  • -
  • Security/Media: stream and bound URL-backed input media fetches to prevent memory exhaustion from oversized responses. Thanks @vincentkoc.
  • -
  • Security/Skills: harden archive extraction for download-installed skills to prevent path traversal outside the target directory. Thanks @markmusson.
  • -
  • Security/Slack: compute command authorization for DM slash commands even when dmPolicy=open, preventing unauthorized users from running privileged commands via DM. Thanks @christos-eth.
  • -
  • Security/iMessage: keep DM pairing-store identities out of group allowlist authorization (prevents cross-context command authorization). Thanks @vincentkoc.
  • -
  • Security/Google Chat: deprecate users/ allowlists (treat users/... as immutable user id only); keep raw email allowlists for usability. Thanks @vincentkoc.
  • -
  • Security/Google Chat: reject ambiguous shared-path webhook routing when multiple webhook targets verify successfully (prevents cross-account policy-context misrouting). Thanks @vincentkoc.
  • -
  • Telegram/Security: require numeric Telegram sender IDs for allowlist authorization (reject @username principals), auto-resolve @username to IDs in openclaw doctor --fix (when possible), and warn in openclaw security audit when legacy configs contain usernames. Thanks @vincentkoc.
  • -
  • Telegram/Security: reject Telegram webhook startup when webhookSecret is missing or empty (prevents unauthenticated webhook request forgery). Thanks @yueyueL.
  • -
  • Security/Windows: avoid shell invocation when spawning child processes to prevent cmd.exe metacharacter injection via untrusted CLI arguments (e.g. agent prompt text).
  • -
  • Telegram: set webhook callback timeout handling to onTimeout: "return" (10s) so long-running update processing no longer emits webhook 500s and retry storms. (#16763) Thanks @chansearrington.
  • -
  • Signal: preserve case-sensitive group: target IDs during normalization so mixed-case group IDs no longer fail with Group not found. (#16748) Thanks @repfigit.
  • -
  • Feishu/Security: harden media URL fetching against SSRF and local file disclosure. (#16285) Thanks @mbelinky.
  • -
  • Security/Agents: scope CLI process cleanup to owned child PIDs to avoid killing unrelated processes on shared hosts. Thanks @aether-ai-agent.
  • -
  • Security/Agents: enforce workspace-root path bounds for apply_patch in non-sandbox mode to block traversal and symlink escape writes. Thanks @p80n-sec.
  • -
  • Security/Agents: enforce symlink-escape checks for apply_patch delete hunks under workspaceOnly, while still allowing deleting the symlink itself. Thanks @p80n-sec.
  • -
  • Security/Agents (macOS): prevent shell injection when writing Claude CLI keychain credentials. (#15924) Thanks @aether-ai-agent.
  • -
  • macOS: hard-limit unkeyed openclaw://agent deep links and ignore deliver / to / channel unless a valid unattended key is provided. Thanks @Cillian-Collins.
  • -
  • Scripts/Security: validate GitHub logins and avoid shell invocation in scripts/update-clawtributors.ts to prevent command injection via malicious commit records. Thanks @scanleale.
  • -
  • Security: fix Chutes manual OAuth login state validation by requiring the full redirect URL (reject code-only pastes) (thanks @aether-ai-agent).
  • -
  • Security/Gateway: harden tool-supplied gatewayUrl overrides by restricting them to loopback or the configured gateway.remote.url. Thanks @p80n-sec.
  • -
  • Security/Gateway: block system.execApprovals.* via node.invoke (use exec.approvals.node.* instead). Thanks @christos-eth.
  • -
  • Security/Gateway: reject oversized base64 chat attachments before decoding to avoid large allocations. Thanks @vincentkoc.
  • -
  • Security/Gateway: stop returning raw resolved config values in skills.status requirement checks (prevents operator.read clients from reading secrets). Thanks @simecek.
  • -
  • Security/Net: fix SSRF guard bypass via full-form IPv4-mapped IPv6 literals (blocks loopback/private/metadata access). Thanks @yueyueL.
  • -
  • Security/Browser: harden browser control file upload + download helpers to prevent path traversal / local file disclosure. Thanks @1seal.
  • -
  • Security/Browser: block cross-origin mutating requests to loopback browser control routes (CSRF hardening). Thanks @vincentkoc.
  • -
  • Security/Node Host: enforce system.run rawCommand/argv consistency to prevent allowlist/approval bypass. Thanks @christos-eth.
  • -
  • Security/Exec approvals: prevent safeBins allowlist bypass via shell expansion (host exec allowlist mode only; not enabled by default). Thanks @christos-eth.
  • -
  • Security/Exec: harden PATH handling by disabling project-local node_modules/.bin bootstrapping by default, disallowing node-host PATH overrides, and spawning ACP servers via the current executable by default. Thanks @akhmittra.
  • -
  • Security/Tlon: harden Urbit URL fetching against SSRF by blocking private/internal hosts by default (opt-in: channels.tlon.allowPrivateNetwork). Thanks @p80n-sec.
  • -
  • Security/Voice Call (Telnyx): require webhook signature verification when receiving inbound events; configs without telnyx.publicKey are now rejected unless skipSignatureVerification is enabled. Thanks @p80n-sec.
  • -
  • Security/Voice Call: require valid Twilio webhook signatures even when ngrok free tier loopback compatibility mode is enabled. Thanks @p80n-sec.
  • -
  • Security/Discovery: stop treating Bonjour TXT records as authoritative routing (prefer resolved service endpoints) and prevent discovery from overriding stored TLS pins; autoconnect now requires a previously trusted gateway. Thanks @simecek.
  • -
-

View full changelog

-]]>
- -
- - 2026.2.15 - Mon, 16 Feb 2026 05:04:34 +0100 - https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml - 202602150 - 2026.2.15 - 15.0 - OpenClaw 2026.2.15 -

Changes

-
    -
  • Discord: unlock rich interactive agent prompts with Components v2 (buttons, selects, modals, and attachment-backed file blocks) so for native interaction through Discord. Thanks @thewilloftheshadow.
  • -
  • Discord: components v2 UI + embeds passthrough + exec approval UX refinements (CV2 containers, button layout, Discord-forwarding skip). Thanks @thewilloftheshadow.
  • -
  • Plugins: expose llm_input and llm_output hook payloads so extensions can observe prompt/input context and model output usage details. (#16724) Thanks @SecondThread.
  • -
  • Subagents: nested sub-agents (sub-sub-agents) with configurable depth. Set agents.defaults.subagents.maxSpawnDepth: 2 to allow sub-agents to spawn their own children. Includes maxChildrenPerAgent limit (default 5), depth-aware tool policy, and proper announce chain routing. (#14447) Thanks @tyler6204.
  • -
  • Slack/Discord/Telegram: add per-channel ack reaction overrides (account/channel-level) to support platform-specific emoji formats. (#17092) Thanks @zerone0x.
  • -
  • Cron/Gateway: add finished-run webhook delivery toggle (notify) and dedicated webhook auth token support (cron.webhookToken) for outbound cron webhook posts. (#14535) Thanks @advaitpaliwal.
  • -
  • Channels: deduplicate probe/token resolution base types across core + extensions while preserving per-channel error typing. (#16986) Thanks @iyoda and @thewilloftheshadow.
  • -
-

Fixes

-
    -
  • Security: replace deprecated SHA-1 sandbox configuration hashing with SHA-256 for deterministic sandbox cache identity and recreation checks. Thanks @kexinoh.
  • -
  • Security/Logging: redact Telegram bot tokens from error messages and uncaught stack traces to prevent accidental secret leakage into logs. Thanks @aether-ai-agent.
  • -
  • Sandbox/Security: block dangerous sandbox Docker config (bind mounts, host networking, unconfined seccomp/apparmor) to prevent container escape via config injection. Thanks @aether-ai-agent.
  • -
  • Sandbox: preserve array order in config hashing so order-sensitive Docker/browser settings trigger container recreation correctly. Thanks @kexinoh.
  • -
  • Gateway/Security: redact sensitive session/path details from status responses for non-admin clients; full details remain available to operator.admin. (#8590) Thanks @fr33d3m0n.
  • -
  • Gateway/Control UI: preserve requested operator scopes for Control UI bypass modes (allowInsecureAuth / dangerouslyDisableDeviceAuth) when device identity is unavailable, preventing false missing scope failures on authenticated LAN/HTTP operator sessions. (#17682) Thanks @leafbird.
  • -
  • LINE/Security: fail closed on webhook startup when channel token or channel secret is missing, and treat LINE accounts as configured only when both are present. (#17587) Thanks @davidahmann.
  • -
  • Skills/Security: restrict download installer targetDir to the per-skill tools directory to prevent arbitrary file writes. Thanks @Adam55A-code.
  • -
  • Skills/Linux: harden go installer fallback on apt-based systems by handling root/no-sudo environments safely, doing best-effort apt index refresh, and returning actionable errors instead of failing with spawn errors. (#17687) Thanks @mcrolly.
  • -
  • Web Fetch/Security: cap downloaded response body size before HTML parsing to prevent memory exhaustion from oversized or deeply nested pages. Thanks @xuemian168.
  • -
  • Config/Gateway: make sensitive-key whitelist suffix matching case-insensitive while preserving passwordFile path exemptions, preventing accidental redaction of non-secret config values like maxTokens and IRC password-file paths. (#16042) Thanks @akramcodez.
  • -
  • Dev tooling: harden git pre-commit hook against option injection from malicious filenames (for example --force), preventing accidental staging of ignored files. Thanks @mrthankyou.
  • -
  • Gateway/Agent: reject malformed agent:-prefixed session keys (for example, agent:main) in agent and agent.identity.get instead of silently resolving them to the default agent, preventing accidental cross-session routing. (#15707) Thanks @rodrigouroz.
  • -
  • Gateway/Chat: harden chat.send inbound message handling by rejecting null bytes, stripping unsafe control characters, and normalizing Unicode to NFC before dispatch. (#8593) Thanks @fr33d3m0n.
  • -
  • Gateway/Send: return an actionable error when send targets internal-only webchat, guiding callers to use chat.send or a deliverable channel. (#15703) Thanks @rodrigouroz.
  • -
  • Control UI: prevent stored XSS via assistant name/avatar by removing inline script injection, serving bootstrap config as JSON, and enforcing script-src 'self'. Thanks @Adam55A-code.
  • -
  • Agents/Security: sanitize workspace paths before embedding into LLM prompts (strip Unicode control/format chars) to prevent instruction injection via malicious directory names. Thanks @aether-ai-agent.
  • -
  • Agents/Sandbox: clarify system prompt path guidance so sandbox bash/exec uses container paths (for example /workspace) while file tools keep host-bridge mapping, avoiding first-attempt path misses from host-only absolute paths in sandbox command execution. (#17693) Thanks @app/juniordevbot.
  • -
  • Agents/Context: apply configured model contextWindow overrides after provider discovery so lookupContextTokens() honors operator config values (including discovery-failure paths). (#17404) Thanks @michaelbship and @vignesh07.
  • -
  • Agents/Context: derive lookupContextTokens() from auth-available model metadata and keep the smallest discovered context window for duplicate model ids, preventing cross-provider cache collisions from overestimating session context limits. (#17586) Thanks @githabideri and @vignesh07.
  • -
  • Agents/OpenAI: force store=true for direct OpenAI Responses/Codex runs to preserve multi-turn server-side conversation state, while leaving proxy/non-OpenAI endpoints unchanged. (#16803) Thanks @mark9232 and @vignesh07.
  • -
  • Memory/FTS: make buildFtsQuery Unicode-aware so non-ASCII queries (including CJK) produce keyword tokens instead of falling back to vector-only search. (#17672) Thanks @KinGP5471.
  • -
  • Auto-reply/Compaction: resolve memory/YYYY-MM-DD.md placeholders with timezone-aware runtime dates and append a Current time: line to memory-flush turns, preventing wrong-year memory filenames without making the system prompt time-variant. (#17603, #17633) Thanks @nicholaspapadam-wq and @vignesh07.
  • -
  • Agents: return an explicit timeout error reply when an embedded run times out before producing any payloads, preventing silent dropped turns during slow cache-refresh transitions. (#16659) Thanks @liaosvcaf and @vignesh07.
  • -
  • Group chats: always inject group chat context (name, participants, reply guidance) into the system prompt on every turn, not just the first. Prevents the model from losing awareness of which group it's in and incorrectly using the message tool to send to the same group. (#14447) Thanks @tyler6204.
  • -
  • Browser/Agents: when browser control service is unavailable, return explicit non-retry guidance (instead of "try again") so models do not loop on repeated browser tool calls until timeout. (#17673) Thanks @austenstone.
  • -
  • Subagents: use child-run-based deterministic announce idempotency keys across direct and queued delivery paths (with legacy queued-item fallback) to prevent duplicate announce retries without collapsing distinct same-millisecond announces. (#17150) Thanks @widingmarcus-cyber.
  • -
  • Subagents/Models: preserve agents.defaults.model.fallbacks when subagent sessions carry a model override, so subagent runs fail over to configured fallback models instead of retrying only the overridden primary model.
  • -
  • Telegram: omit message_thread_id for DM sends/draft previews and keep forum-topic handling (id=1 general omitted, non-general kept), preventing DM failures with 400 Bad Request: message thread not found. (#10942) Thanks @garnetlyx.
  • -
  • Telegram: replace inbound placeholder with successful preflight voice transcript in message body context, preventing placeholder-only prompt bodies for mention-gated voice messages. (#16789) Thanks @Limitless2023.
  • -
  • Telegram: retry inbound media getFile calls (3 attempts with backoff) and gracefully fall back to placeholder-only processing when retries fail, preventing dropped voice/media messages on transient Telegram network errors. (#16154) Thanks @yinghaosang.
  • -
  • Telegram: finalize streaming preview replies in place instead of sending a second final message, preventing duplicate Telegram assistant outputs at stream completion. (#17218) Thanks @obviyus.
  • -
  • Discord: preserve channel session continuity when runtime payloads omit message.channelId by falling back to event/raw channel_id values for routing/session keys, so same-channel messages keep history across turns/restarts. Also align diagnostics so active Discord runs no longer appear as sessionKey=unknown. (#17622) Thanks @shakkernerd.
  • -
  • Discord: dedupe native skill commands by skill name in multi-agent setups to prevent duplicated slash commands with _2 suffixes. (#17365) Thanks @seewhyme.
  • -
  • Discord: ensure role allowlist matching uses raw role IDs for message routing authorization. Thanks @xinhuagu.
  • -
  • Web UI/Agents: hide BOOTSTRAP.md in the Agents Files list after onboarding is completed, avoiding confusing missing-file warnings for completed workspaces. (#17491) Thanks @gumadeiras.
  • -
  • Auto-reply/WhatsApp/TUI/Web: when a final assistant message is NO_REPLY and a messaging tool send succeeded, mirror the delivered messaging-tool text into session-visible assistant output so TUI/Web no longer show NO_REPLY placeholders. (#7010) Thanks @Morrowind-Xie.
  • -
  • Cron: infer payload.kind="agentTurn" for model-only cron.update payload patches, so partial agent-turn updates do not fail validation when kind is omitted. (#15664) Thanks @rodrigouroz.
  • -
  • TUI: make searchable-select filtering and highlight rendering ANSI-aware so queries ignore hidden escape codes and no longer corrupt ANSI styling sequences during match highlighting. (#4519) Thanks @bee4come.
  • -
  • TUI/Windows: coalesce rapid single-line submit bursts in Git Bash into one multiline message as a fallback when bracketed paste is unavailable, preventing pasted multiline text from being split into multiple sends. (#4986) Thanks @adamkane.
  • -
  • TUI: suppress false (no output) placeholders for non-local empty final events during concurrent runs, preventing external-channel replies from showing empty assistant bubbles while a local run is still streaming. (#5782) Thanks @LagWizard and @vignesh07.
  • -
  • TUI: preserve copy-sensitive long tokens (URLs/paths/file-like identifiers) during wrapping and overflow sanitization so wrapped output no longer inserts spaces that corrupt copy/paste values. (#17515, #17466, #17505) Thanks @abe238, @trevorpan, and @JasonCry.
  • -
  • CLI/Build: make legacy daemon CLI compatibility shim generation tolerant of minimal tsdown daemon export sets, while preserving restart/register compatibility aliases and surfacing explicit errors for unavailable legacy daemon commands. Thanks @vignesh07.
  • -
-

View full changelog

-]]>
- -
- - 2026.2.21 - Sat, 21 Feb 2026 17:55:48 +0100 - https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml - 13056 - 2026.2.21 - 15.0 - OpenClaw 2026.2.21 -

Changes

-
    -
  • Models/Google: add Gemini 3.1 support (google/gemini-3.1-pro-preview).
  • -
  • Providers/Onboarding: add Volcano Engine (Doubao) and BytePlus providers/models (including coding variants), wire onboarding auth choices for interactive + non-interactive flows, and align docs to volcengine-api-key. (#7967) Thanks @funmore123.
  • -
  • Channels/CLI: add per-account/channel defaultTo outbound routing fallback so openclaw agent --deliver can send without explicit --reply-to when a default target is configured. (#16985) Thanks @KirillShchetinin.
  • -
  • Channels: allow per-channel model overrides via channels.modelByChannel and note them in /status. Thanks @thewilloftheshadow.
  • -
  • Telegram/Streaming: simplify preview streaming config to channels.telegram.streaming (boolean), auto-map legacy streamMode values, and remove block-vs-partial preview branching. (#22012) thanks @obviyus.
  • -
  • Discord/Streaming: add stream preview mode for live draft replies with partial/block options and configurable chunking. Thanks @thewilloftheshadow. Inspiration @neoagentic-ship-it.
  • -
  • Discord/Telegram: add configurable lifecycle status reactions for queued/thinking/tool/done/error phases with a shared controller and emoji/timing overrides. Thanks @wolly-tundracube and @thewilloftheshadow.
  • -
  • Discord/Voice: add voice channel join/leave/status via /vc, plus auto-join configuration for realtime voice conversations. Thanks @thewilloftheshadow.
  • -
  • Discord: add configurable ephemeral defaults for slash-command responses. (#16563) Thanks @wei.
  • -
  • Discord: support updating forum available_tags via channel edit actions for forum tag management. (#12070) Thanks @xiaoyaner0201.
  • -
  • Discord: include channel topics in trusted inbound metadata on new sessions. Thanks @thewilloftheshadow.
  • -
  • Discord/Subagents: add thread-bound subagent sessions on Discord with per-thread focus/list controls and thread-bound continuation routing for spawned helper agents. (#21805) Thanks @onutc.
  • -
  • iOS/Chat: clean chat UI noise by stripping inbound untrusted metadata/timestamp prefixes, formatting tool outputs into concise summaries/errors, compacting the composer while typing, and supporting tap-to-dismiss keyboard in chat view. (#22122) thanks @mbelinky.
  • -
  • iOS/Watch: bridge mirrored watch prompt notification actions into iOS quick-reply handling, including queued action handoff until app model initialization. (#22123) thanks @mbelinky.
  • -
  • iOS/Gateway: stabilize background wake and reconnect behavior with background reconnect suppression/lease windows, BGAppRefresh wake fallback, location wake hook throttling, and APNs wake retry+nudge instrumentation. (#21226) thanks @mbelinky.
  • -
  • Auto-reply/UI: add model fallback lifecycle visibility in verbose logs, /status active-model context with fallback reason, and cohesive WebUI fallback indicators. (#20704) Thanks @joshavant.
  • -
  • MSTeams: dedupe sent-message cache storage by removing duplicate per-message Set storage and using timestamps Map keys as the single membership source. (#22514) Thanks @TaKO8Ki.
  • -
  • Agents/Subagents: default subagent spawn depth now uses shared maxSpawnDepth=2, enabling depth-1 orchestrator spawning by default while keeping depth policy checks consistent across spawn and prompt paths. (#22223) Thanks @tyler6204.
  • -
  • Security/Agents: make owner-ID obfuscation use a dedicated HMAC secret from configuration (ownerDisplaySecret) and update hashing behavior so obfuscation is decoupled from gateway token handling for improved control. (#7343) Thanks @vincentkoc.
  • -
  • Security/Infra: switch gateway lock and tool-call synthetic IDs from SHA-1 to SHA-256 with unchanged truncation length to strengthen hash basis while keeping deterministic behavior and lock key format. (#7343) Thanks @vincentkoc.
  • -
  • Dependencies/Tooling: add non-blocking dead-code scans in CI via Knip/ts-prune/ts-unused-exports to surface unused dependencies and exports earlier. (#22468) Thanks @vincentkoc.
  • -
  • Dependencies/Unused Dependencies: remove or scope unused root and extension deps (@larksuiteoapi/node-sdk, signal-utils, ollama, lit, @lit/context, @lit-labs/signals, @microsoft/agents-hosting-express, @microsoft/agents-hosting-extensions-teams, and plugin-local openclaw devDeps in extensions/open-prose, extensions/lobster, and extensions/llm-task). (#22471, #22495) Thanks @vincentkoc.
  • -
  • Dependencies/A2UI: harden dependency resolution after root cleanup (resolve lit, @lit/context, @lit-labs/signals, and signal-utils from workspace/root) and simplify bundling fallback behavior, including pnpm dlx rolldown compatibility. (#22481, #22507) Thanks @vincentkoc.
  • -
-

Fixes

-
    -
  • Security/Agents: cap embedded Pi runner outer retry loop with a higher profile-aware dynamic limit (32-160 attempts) and return an explicit retry_limit error payload when retries never converge, preventing unbounded internal retry cycles (GHSA-76m6-pj3w-v7mf).
  • -
  • Telegram: detect duplicate bot-token ownership across Telegram accounts at startup/status time, mark secondary accounts as not configured with an explicit fix message, and block duplicate account startup before polling to avoid endless getUpdates conflict loops.
  • -
  • Agents/Tool images: include source filenames in agents/tool-images resize logs so compression events can be traced back to specific files.
  • -
  • Providers/OAuth: harden Qwen and Chutes refresh handling by validating refresh response expiry values and preserving prior refresh tokens when providers return empty refresh token fields, with regression coverage for empty-token responses.
  • -
  • Models/Kimi-Coding: add missing implicit provider template for kimi-coding with correct anthropic-messages API type and base URL, fixing 403 errors when using Kimi for Coding. (#22409)
  • -
  • Auto-reply/Tools: forward senderIsOwner through embedded queued/followup runner params so owner-only tools remain available for authorized senders. (#22296) thanks @hcoj.
  • -
  • Discord: restore model picker back navigation when a provider is missing and document the Discord picker flow. (#21458) Thanks @pejmanjohn and @thewilloftheshadow.
  • -
  • Memory/QMD: respect per-agent memorySearch.enabled=false during gateway QMD startup initialization, split multi-collection QMD searches into per-collection queries (search/vsearch/query) to avoid sparse-term drops, prefer collection-hinted doc resolution to avoid stale-hash collisions, retry boot updates on transient lock/timeout failures, skip qmd embed in BM25-only search mode (including memory index --force), and serialize embed runs globally with failure backoff to prevent CPU storms on multi-agent hosts. (#20581, #21590, #20513, #20001, #21266, #21583, #20346, #19493) Thanks @danielrevivo, @zanderkrause, @sunyan034-cmd, @tilleulenspiegel, @dae-oss, @adamlongcreativellc, @jonathanadams96, and @kiliansitel.
  • -
  • Memory/Builtin: prevent automatic sync races with manager shutdown by skipping post-close sync starts and waiting for in-flight sync before closing SQLite, so onSearch/onSessionStart no longer fail with database is not open in ephemeral CLI flows. (#20556, #7464) Thanks @FuzzyTG and @henrybottter.
  • -
  • Providers/Copilot: drop persisted assistant thinking blocks for Claude models (while preserving turn structure/tool blocks) so follow-up requests no longer fail on invalid thinkingSignature payloads. (#19459) Thanks @jackheuberger.
  • -
  • Providers/Copilot: add claude-sonnet-4.6 and claude-sonnet-4.5 to the default GitHub Copilot model catalog and add coverage for model-list/definition helpers. (#20270, fixes #20091) Thanks @Clawborn.
  • -
  • Auto-reply/WebChat: avoid defaulting inbound runtime channel labels to unrelated providers (for example whatsapp) for webchat sessions so channel-specific formatting guidance stays accurate. (#21534) Thanks @lbo728.
  • -
  • Status: include persisted cacheRead/cacheWrite in session summaries so compact /status output consistently shows cache hit percentages from real session data.
  • -
  • Heartbeat/Cron: restore interval heartbeat behavior so missing HEARTBEAT.md no longer suppresses runs (only effectively empty files skip), preserving prompt-driven and tagged-cron execution paths.
  • -
  • WhatsApp/Cron/Heartbeat: enforce allowlisted routing for implicit scheduled/system delivery by merging pairing-store + configured allowFrom recipients, selecting authorized recipients when last-route context points to a non-allowlisted chat, and preventing heartbeat fan-out to recent unauthorized chats.
  • -
  • Heartbeat/Active hours: constrain active-hours 24 sentinel parsing to 24:00 in time validation so invalid values like 24:30 are rejected early. (#21410) thanks @adhitShet.
  • -
  • Heartbeat: treat activeHours windows with identical start/end times as zero-width (always outside the window) instead of always-active. (#21408) thanks @adhitShet.
  • -
  • CLI/Pairing: default pairing list and pairing approve to the sole available pairing channel when omitted, so TUI-only setups can recover from pairing required without guessing channel arguments. (#21527) Thanks @losts1.
  • -
  • TUI/Pairing: show explicit pairing-required recovery guidance after gateway disconnects that return pairing required, including approval steps to unblock quickstart TUI hatching on fresh installs. (#21841) Thanks @nicolinux.
  • -
  • TUI/Input: suppress duplicate backspace events arriving in the same input burst window so SSH sessions no longer delete two characters per backspace press in the composer. (#19318) Thanks @eheimer.
  • -
  • TUI/Heartbeat: suppress heartbeat ACK/prompt noise in chat streaming when showOk is disabled, while still preserving non-ACK heartbeat alerts in final output. (#20228) Thanks @bhalliburton.
  • -
  • TUI/History: cap chat-log component growth and prune stale render nodes/references so large default history loads no longer overflow render recursion with RangeError: Maximum call stack size exceeded. (#18068) Thanks @JaniJegoroff.
  • -
  • Memory/QMD: diversify mixed-source search ranking when both session and memory collections are present so session transcript hits no longer crowd out durable memory-file matches in top results. (#19913) Thanks @alextempr.
  • -
  • Memory/Tools: return explicit unavailable warnings/actions from memory_search when embedding/provider failures occur (including quota exhaustion), so disabled memory does not look like an empty recall result. (#21894) Thanks @XBS9.
  • -
  • Session/Startup: require the /new and /reset greeting path to run Session Startup file-reading instructions before responding, so daily memory startup context is not skipped on fresh-session greetings. (#22338) Thanks @armstrong-pv.
  • -
  • Auth/Onboarding: align OAuth profile-id config mapping with stored credential IDs for OpenAI Codex and Chutes flows, preventing provider:default mismatches when OAuth returns email-scoped credentials. (#12692) thanks @mudrii.
  • -
  • Provider/HTTP: treat HTTP 503 as failover-eligible for LLM provider errors. (#21086) Thanks @Protocol-zero-0.
  • -
  • Slack: pass recipient_team_id / recipient_user_id through Slack native streaming calls so chat.startStream/appendStream/stopStream work reliably across DMs and Slack Connect setups, and disable block streaming when native streaming is active. (#20988) Thanks @Dithilli. Earlier recipient-ID groundwork was contributed in #20377 by @AsserAl1012.
  • -
  • CLI/Config: add canonical --strict-json parsing for config set and keep --json as a legacy alias to reduce help/behavior drift. (#21332) thanks @adhitShet.
  • -
  • CLI: keep openclaw -v as a root-only version alias so subcommand -v, --verbose flags (for example ACP/hooks/skills) are no longer intercepted globally. (#21303) thanks @adhitShet.
  • -
  • Memory: return empty snippets when memory_get/QMD read files that have not been created yet, and harden memory indexing/session helpers against ENOENT races so missing Markdown no longer crashes tools. (#20680) Thanks @pahdo.
  • -
  • Telegram/Streaming: always clean up draft previews even when dispatch throws before fallback handling, preventing orphaned preview messages during failed runs. (#19041) thanks @mudrii.
  • -
  • Telegram/Streaming: split reasoning and answer draft preview lanes to prevent cross-lane overwrites, and ignore literal tags inside inline/fenced code snippets so sample markup is not misrouted as reasoning. (#20774) Thanks @obviyus.
  • -
  • Telegram/Streaming: restore 30-char first-preview debounce and scope NO_REPLY prefix suppression to partial sentinel fragments so normal No... text is not filtered. (#22613) thanks @obviyus.
  • -
  • Telegram/Status reactions: refresh stall timers on repeated phase updates and honor ack-reaction scope when lifecycle reactions are enabled, preventing false stall emojis and unwanted group reactions. Thanks @wolly-tundracube and @thewilloftheshadow.
  • -
  • Telegram/Status reactions: keep lifecycle reactions active when available-reactions lookup fails by falling back to unrestricted variant selection instead of suppressing reaction updates. (#22380) thanks @obviyus.
  • -
  • Discord/Streaming: apply replyToMode: first only to the first Discord chunk so block-streamed replies do not spam mention pings. (#20726) Thanks @thewilloftheshadow for the report.
  • -
  • Discord/Components: map DM channel targets back to user-scoped component sessions so button/select interactions stay in the main DM session. Thanks @thewilloftheshadow.
  • -
  • Discord/Allowlist: lazy-load guild lists when resolving Discord user allowlists so ID-only entries resolve even if guild fetch fails. (#20208) Thanks @zhangjunmengyang.
  • -
  • Discord/Gateway: handle close code 4014 (missing privileged gateway intents) without crashing the gateway. Thanks @thewilloftheshadow.
  • -
  • Discord: ingest inbound stickers as media so sticker-only messages and forwarded stickers are visible to agents. Thanks @thewilloftheshadow.
  • -
  • Auto-reply/Runner: emit onAgentRunStart only after agent lifecycle or tool activity begins (and only once per run), so fallback preflight errors no longer mark runs as started. (#21165) Thanks @shakkernerd.
  • -
  • Auto-reply/Tool results: serialize tool-result delivery and keep the delivery chain progressing after individual failures so concurrent tool outputs preserve user-visible ordering. (#21231) thanks @ahdernasr.
  • -
  • Auto-reply/Prompt caching: restore prefix-cache stability by keeping inbound system metadata session-stable and moving per-message IDs (message_id, message_id_full, reply_to_id, sender_id) into untrusted conversation context. (#20597) Thanks @anisoptera.
  • -
  • iOS/Watch: add actionable watch approval/reject controls and quick-reply actions so watch-originated approvals and responses can be sent directly from notification flows. (#21996) Thanks @mbelinky.
  • -
  • iOS/Watch: refresh iOS and watch app icon assets with the lobster icon set to keep phone/watch branding aligned. (#21997) Thanks @mbelinky.
  • -
  • CLI/Onboarding: fix Anthropic-compatible custom provider verification by normalizing base URLs to avoid duplicate /v1 paths during setup checks. (#21336) Thanks @17jmumford.
  • -
  • iOS/Gateway/Tools: prefer uniquely connected node matches when duplicate display names exist, surface actionable nodes invoke pairing-required guidance with request IDs, and refresh active iOS gateway registration after location-capability setting changes so capability updates apply immediately. (#22120) thanks @mbelinky.
  • -
  • Gateway/Auth: require gateway.trustedProxies to include a loopback proxy address when auth.mode="trusted-proxy" and bind="loopback", preventing same-host proxy misconfiguration from silently blocking auth. (#22082, follow-up to #20097) thanks @mbelinky.
  • -
  • Gateway/Auth: allow trusted-proxy mode with loopback bind for same-host reverse-proxy deployments, while still requiring configured gateway.trustedProxies. (#20097) thanks @xinhuagu.
  • -
  • Gateway/Auth: allow authenticated clients across roles/scopes to call health while preserving role and scope enforcement for non-health methods. (#19699) thanks @Nachx639.
  • -
  • Gateway/Hooks: include transform export name in hook-transform cache keys so distinct exports from the same module do not reuse the wrong cached transform function. (#13855) thanks @mcaxtr.
  • -
  • Gateway/Control UI: return 404 for missing static-asset paths instead of serving SPA fallback HTML, while preserving client-route fallback behavior for extensionless and non-asset dotted paths. (#12060) thanks @mcaxtr.
  • -
  • Gateway/Pairing: prevent device-token rotate scope escalation by enforcing an approved-scope baseline, preserving approved scopes across metadata updates, and rejecting rotate requests that exceed approved role scope implications. (#20703) thanks @coygeek.
  • -
  • Gateway/Pairing: clear persisted paired-device state when the gateway client closes with device token mismatch (1008) so reconnect flows can cleanly re-enter pairing. (#22071) Thanks @mbelinky.
  • -
  • Gateway/Config: allow gateway.customBindHost in strict config validation when gateway.bind="custom" so valid custom bind-host configurations no longer fail startup. (#20318, fixes #20289) Thanks @MisterGuy420.
  • -
  • Gateway/Pairing: tolerate legacy paired devices missing roles/scopes metadata in websocket upgrade checks and backfill metadata on reconnect. (#21447, fixes #21236) Thanks @joshavant.
  • -
  • Gateway/Pairing/CLI: align read-scope compatibility in pairing/device-token checks and add local openclaw devices fallback recovery for loopback pairing required deadlocks, with explicit fallback notice to unblock approval bootstrap flows. (#21616) Thanks @shakkernerd.
  • -
  • Cron: honor cron.maxConcurrentRuns in the timer loop so due jobs can execute up to the configured parallelism instead of always running serially. (#11595) Thanks @Takhoffman.
  • -
  • Agents/Compaction: restore embedded compaction safeguard/context-pruning extension loading in production by wiring bundled extension factories into the resource loader instead of runtime file-path resolution. (#22349) Thanks @Glucksberg.
  • -
  • Agents/Subagents: restore announce-chain delivery to agent injection, defer nested announce output until descendant follow-up content is ready, and prevent descendant deferrals from consuming announce retry budget so deep chains do not drop final completions. (#22223) Thanks @tyler6204.
  • -
  • Agents/System Prompt: label allowlisted senders as authorized senders to avoid implying ownership. Thanks @thewilloftheshadow.
  • -
  • Agents/Tool display: fix exec cwd suffix inference so pushd ... && popd ... && does not keep stale (in ) context in summaries. (#21925) Thanks @Lukavyi.
  • -
  • Tools/web_search: handle xAI Responses API payloads that emit top-level output_text blocks (without a message wrapper) so Grok web_search no longer returns No response for those results. (#20508) Thanks @echoVic.
  • -
  • Agents/Failover: treat non-default override runs as direct fallback-to-configured-primary (skip configured fallback chain), normalize default-model detection for provider casing/whitespace, and add regression coverage for override/auth error paths. (#18820) Thanks @Glucksberg.
  • -
  • Docker/Build: include ownerDisplay in CommandsSchema object-level defaults so Docker pnpm build no longer fails with TS2769 during plugin SDK d.ts generation. (#22558) Thanks @obviyus.
  • -
  • Docker/Browser: install Playwright Chromium into /home/node/.cache/ms-playwright and set node:node ownership so browser binaries are available to the runtime user in browser-enabled images. (#22585) thanks @obviyus.
  • -
  • Hooks/Session memory: trigger bundled session-memory persistence on both /new and /reset so reset flows no longer skip markdown transcript capture before archival. (#21382) Thanks @mofesolapaul.
  • -
  • Dependencies/Agents: bump embedded Pi SDK packages (@mariozechner/pi-agent-core, @mariozechner/pi-ai, @mariozechner/pi-coding-agent, @mariozechner/pi-tui) to 0.54.0. (#21578) Thanks @Takhoffman.
  • -
  • Config/Agents: expose Pi compaction tuning values agents.defaults.compaction.reserveTokens and agents.defaults.compaction.keepRecentTokens in config schema/types and apply them in embedded Pi runner settings overrides with floor enforcement via reserveTokensFloor. (#21568) Thanks @Takhoffman.
  • -
  • Docker: pin base images to SHA256 digests in Docker builds to prevent mutable tag drift. (#7734) Thanks @coygeek.
  • -
  • Docker: run build steps as the node user and use COPY --chown to avoid recursive ownership changes, trimming image size and layer churn. Thanks @huntharo.
  • -
  • Config/Memory: restore schema help/label metadata for hybrid mmr and temporalDecay settings so configuration surfaces show correct names and guidance. (#18786) Thanks @rodrigouroz.
  • -
  • Skills/SonosCLI: add troubleshooting guidance for sonos discover failures on macOS direct mode (sendto: no route to host) and sandbox network restrictions (bind: operation not permitted). (#21316) Thanks @huntharo.
  • -
  • macOS/Build: default release packaging to BUNDLE_ID=ai.openclaw.mac in scripts/package-mac-dist.sh, so Sparkle feed URL is retained and auto-update no longer fails with an empty appcast feed. (#19750) thanks @loganprit.
  • -
  • Signal/Outbound: preserve case for Base64 group IDs during outbound target normalization so cross-context routing and policy checks no longer break when group IDs include uppercase characters. (#5578) Thanks @heyhudson.
  • -
  • Anthropic/Agents: preserve required pi-ai default OAuth beta headers when context1m injects anthropic-beta, preventing 401 auth failures for sk-ant-oat-* tokens. (#19789, fixes #19769) Thanks @minupla.
  • -
  • Security/Exec: block unquoted heredoc body expansion tokens in shell allowlist analysis, reject unterminated heredocs, and require explicit approval for allowlisted heredoc execution on gateway hosts to prevent heredoc substitution allowlist bypass. Thanks @torturado for reporting.
  • -
  • macOS/Security: evaluate system.run allowlists per shell segment in macOS node runtime and companion exec host (including chained shell operators), fail closed on shell/process substitution parsing, and require explicit approval on unsafe parse cases to prevent allowlist bypass via rawCommand chaining. Thanks @tdjackey for reporting.
  • -
  • WhatsApp/Security: enforce allowlist JID authorization for reaction actions so authenticated callers cannot target non-allowlisted chats by forging chatJid + valid messageId pairs. Thanks @aether-ai-agent for reporting.
  • -
  • ACP/Security: escape control and delimiter characters in ACP resource_link title/URI metadata before prompt interpolation to prevent metadata-driven prompt injection through resource links. Thanks @aether-ai-agent for reporting.
  • -
  • TTS/Security: make model-driven provider switching opt-in by default (messages.tts.modelOverrides.allowProvider=false unless explicitly enabled), while keeping voice/style overrides available, to reduce prompt-injection-driven provider hops and unexpected TTS cost escalation. Thanks @aether-ai-agent for reporting.
  • -
  • Security/Agents: keep overflow compaction retry budgeting global across tool-result truncation recovery so successful truncation cannot reset the overflow retry counter and amplify retry/cost cycles. Thanks @aether-ai-agent for reporting.
  • -
  • BlueBubbles/Security: require webhook token authentication for all BlueBubbles webhook requests (including loopback/proxied setups), removing passwordless webhook fallback behavior. Thanks @zpbrent.
  • -
  • iOS/Security: force https:// for non-loopback manual gateway hosts during iOS onboarding to block insecure remote transport URLs. (#21969) Thanks @mbelinky.
  • -
  • Gateway/Security: remove shared-IP fallback for canvas endpoints and require token or session capability for canvas access. Thanks @thewilloftheshadow.
  • -
  • Gateway/Security: require secure context and paired-device checks for Control UI auth even when gateway.controlUi.allowInsecureAuth is set, and align audit messaging with the hardened behavior. (#20684) Thanks @coygeek and @Vasco0x4 for reporting.
  • -
  • Gateway/Security: scope tokenless Tailscale forwarded-header auth to Control UI websocket auth only, so HTTP gateway routes still require token/password even on trusted hosts. Thanks @zpbrent for reporting.
  • -
  • Docker/Security: run E2E and install-sh test images as non-root by adding appuser directives. Thanks @thewilloftheshadow.
  • -
  • Skills/Security: sanitize skill env overrides to block unsafe runtime injection variables and only allow sensitive keys when declared in skill metadata, with warnings for suspicious values. Thanks @thewilloftheshadow.
  • -
  • Security/Commands: block prototype-key injection in runtime /debug overrides and require own-property checks for gated command flags (bash, config, debug) so inherited prototype values cannot enable privileged commands. Thanks @tdjackey for reporting.
  • -
  • Security/Browser: block non-network browser navigation protocols (including file:, data:, and javascript:) while preserving about:blank, preventing local file reads via browser tool navigation. Thanks @q1uf3ng for reporting.
  • -
  • Security/Exec: block shell startup-file env injection (BASH_ENV, ENV, BASH_FUNC_*, LD_*, DYLD_*) across config env ingestion, node-host inherited environment sanitization, and macOS exec host runtime to prevent pre-command execution from attacker-controlled environment variables. Thanks @tdjackey.
  • -
  • Security/Exec (Windows): canonicalize cmd.exe /c command text across validation, approval binding, and audit/event rendering to prevent trailing-argument approval mismatches in system.run. Thanks @tdjackey for reporting.
  • -
  • Security/Gateway/Hooks: block __proto__, constructor, and prototype traversal in webhook template path resolution to prevent prototype-chain payload data leakage in messageTemplate rendering. (#22213) Thanks @SleuthCo.
  • -
  • Security/OpenClawKit/UI: prevent injected inbound user context metadata blocks from leaking into chat history in TUI, webchat, and macOS surfaces by stripping all untrusted metadata prefixes at display boundaries. (#22142) Thanks @Mellowambience, @vincentkoc.
  • -
  • Security/OpenClawKit/UI: strip inbound metadata blocks from user messages in TUI rendering while preserving user-authored content. (#22345) Thanks @kansodata, @vincentkoc.
  • -
  • Security/OpenClawKit/UI: prevent inbound metadata leaks and reply-tag streaming artifacts in TUI rendering by stripping untrusted metadata prefixes at display boundaries. (#22346) Thanks @akramcodez, @vincentkoc.
  • -
  • Security/Agents: restrict local MEDIA tool attachments to core tools and the OpenClaw temp root to prevent untrusted MCP tool file exfiltration. Thanks @NucleiAv and @thewilloftheshadow.
  • -
  • Security/Net: strip sensitive headers (Authorization, Proxy-Authorization, Cookie, Cookie2) on cross-origin redirects in fetchWithSsrFGuard to prevent credential forwarding across origin boundaries. (#20313) Thanks @afurm.
  • -
  • Security/Systemd: reject CR/LF in systemd unit environment values and fix argument escaping so generated units cannot be injected with extra directives. Thanks @thewilloftheshadow.
  • -
  • Security/Tools: add per-wrapper random IDs to untrusted-content markers from wrapExternalContent/wrapWebContent, preventing marker spoofing from escaping content boundaries. (#19009) Thanks @Whoaa512.
  • -
  • Shared/Security: reject insecure deep links that use ws:// non-loopback gateway URLs to prevent plaintext remote websocket configuration. (#21970) Thanks @mbelinky.
  • -
  • macOS/Security: reject non-loopback ws:// remote gateway URLs in macOS remote config to block insecure plaintext websocket endpoints. (#21971) Thanks @mbelinky.
  • -
  • Browser/Security: block upload path symlink escapes so browser upload sources cannot traverse outside the allowed workspace via symlinked paths. (#21972) Thanks @mbelinky.
  • -
  • Security/Dependencies: bump transitive hono usage to 4.11.10 to incorporate timing-safe authentication comparison hardening for basicAuth/bearerAuth (GHSA-gq3j-xvxp-8hrf). Thanks @vincentkoc.
  • -
  • Security/Gateway: parse X-Forwarded-For with trust-preserving semantics when requests come from configured trusted proxies, preventing proxy-chain spoofing from influencing client IP classification and rate-limit identity. Thanks @AnthonyDiSanti and @vincentkoc.
  • -
  • Security/Sandbox: remove default --no-sandbox for the browser container entrypoint, add explicit opt-in via OPENCLAW_BROWSER_NO_SANDBOX / CLAWDBOT_BROWSER_NO_SANDBOX, and add security-audit checks for stale/missing sandbox browser Docker hash labels. Thanks @TerminalsandCoffee and @vincentkoc.
  • -
  • Security/Sandbox Browser: require VNC password auth for noVNC observer sessions in the sandbox browser entrypoint, plumb per-container noVNC passwords from runtime, and emit short-lived noVNC observer token URLs while keeping loopback-only host port publishing. Thanks @TerminalsandCoffee for reporting.
  • -
  • Security/Sandbox Browser: default browser sandbox containers to a dedicated Docker network (openclaw-sandbox-browser), add optional CDP ingress source-range restrictions, auto-create missing dedicated networks, and warn in openclaw security --audit when browser sandboxing runs on bridge without source-range limits. Thanks @TerminalsandCoffee for reporting.
  • -
-

View full changelog

-]]>
- -
-
-
\ No newline at end of file diff --git a/apps/android/.gitignore b/apps/android/.gitignore deleted file mode 100644 index 68bfc099e36..00000000000 --- a/apps/android/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.gradle/ -**/build/ -local.properties -.idea/ -**/*.iml diff --git a/apps/android/README.md b/apps/android/README.md deleted file mode 100644 index c2ae5a2179b..00000000000 --- a/apps/android/README.md +++ /dev/null @@ -1,51 +0,0 @@ -## OpenClaw Node (Android) (internal) - -Modern Android node app: connects to the **Gateway WebSocket** (`_openclaw-gw._tcp`) and exposes **Canvas + Chat + Camera**. - -Notes: -- The node keeps the connection alive via a **foreground service** (persistent notification with a Disconnect action). -- Chat always uses the shared session key **`main`** (same session across iOS/macOS/WebChat/Android). -- Supports modern Android only (`minSdk 31`, Kotlin + Jetpack Compose). - -## Open in Android Studio -- Open the folder `apps/android`. - -## Build / Run - -```bash -cd apps/android -./gradlew :app:assembleDebug -./gradlew :app:installDebug -./gradlew :app:testDebugUnitTest -``` - -`gradlew` auto-detects the Android SDK at `~/Library/Android/sdk` (macOS default) if `ANDROID_SDK_ROOT` / `ANDROID_HOME` are unset. - -## Connect / Pair - -1) Start the gateway (on your “master” machine): -```bash -pnpm openclaw gateway --port 18789 --verbose -``` - -2) In the Android app: -- Open **Settings** -- Either select a discovered gateway under **Discovered Gateways**, or use **Advanced → Manual Gateway** (host + port). - -3) Approve pairing (on the gateway machine): -```bash -openclaw nodes pending -openclaw nodes approve -``` - -More details: `docs/platforms/android.md`. - -## Permissions - -- Discovery: - - Android 13+ (`API 33+`): `NEARBY_WIFI_DEVICES` - - Android 12 and below: `ACCESS_FINE_LOCATION` (required for NSD scanning) -- Foreground service notification (Android 13+): `POST_NOTIFICATIONS` -- Camera: - - `CAMERA` for `camera.snap` and `camera.clip` - - `RECORD_AUDIO` for `camera.clip` when `includeAudio=true` diff --git a/apps/android/app/build.gradle.kts b/apps/android/app/build.gradle.kts deleted file mode 100644 index b91b1e21537..00000000000 --- a/apps/android/app/build.gradle.kts +++ /dev/null @@ -1,150 +0,0 @@ -import com.android.build.api.variant.impl.VariantOutputImpl - -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") - id("org.jetbrains.kotlin.plugin.compose") - id("org.jetbrains.kotlin.plugin.serialization") -} - -android { - namespace = "ai.openclaw.android" - compileSdk = 36 - - sourceSets { - getByName("main") { - assets.srcDir(file("../../shared/OpenClawKit/Sources/OpenClawKit/Resources")) - } - } - - defaultConfig { - applicationId = "ai.openclaw.android" - minSdk = 31 - targetSdk = 36 - versionCode = 202602210 - versionName = "2026.2.21" - ndk { - // Support all major ABIs — native libs are tiny (~47 KB per ABI) - abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64") - } - } - - buildTypes { - release { - isMinifyEnabled = true - isShrinkResources = true - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") - } - debug { - isMinifyEnabled = false - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - packaging { - resources { - excludes += setOf( - "/META-INF/{AL2.0,LGPL2.1}", - "/META-INF/*.version", - "/META-INF/LICENSE*.txt", - "DebugProbesKt.bin", - "kotlin-tooling-metadata.json", - ) - } - } - - lint { - disable += setOf( - "GradleDependency", - "IconLauncherShape", - "NewerVersionAvailable", - ) - warningsAsErrors = true - } - - testOptions { - unitTests.isIncludeAndroidResources = true - } -} - -androidComponents { - onVariants { variant -> - variant.outputs - .filterIsInstance() - .forEach { output -> - val versionName = output.versionName.orNull ?: "0" - val buildType = variant.buildType - - val outputFileName = "openclaw-${versionName}-${buildType}.apk" - output.outputFileName = outputFileName - } - } -} -kotlin { - compilerOptions { - jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) - allWarningsAsErrors.set(true) - } -} - -dependencies { - val composeBom = platform("androidx.compose:compose-bom:2025.12.00") - implementation(composeBom) - androidTestImplementation(composeBom) - - implementation("androidx.core:core-ktx:1.17.0") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.10.0") - implementation("androidx.activity:activity-compose:1.12.2") - implementation("androidx.webkit:webkit:1.15.0") - - implementation("androidx.compose.ui:ui") - implementation("androidx.compose.ui:ui-tooling-preview") - implementation("androidx.compose.material3:material3") - // material-icons-extended pulled in full icon set (~20 MB DEX). Only ~18 icons used. - // R8 will tree-shake unused icons when minify is enabled on release builds. - implementation("androidx.compose.material:material-icons-extended") - implementation("androidx.navigation:navigation-compose:2.9.6") - - debugImplementation("androidx.compose.ui:ui-tooling") - - // Material Components (XML theme + resources) - implementation("com.google.android.material:material:1.13.0") - - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0") - - implementation("androidx.security:security-crypto:1.1.0") - implementation("androidx.exifinterface:exifinterface:1.4.2") - implementation("com.squareup.okhttp3:okhttp:5.3.2") - implementation("org.bouncycastle:bcprov-jdk18on:1.83") - - // CameraX (for node.invoke camera.* parity) - implementation("androidx.camera:camera-core:1.5.2") - implementation("androidx.camera:camera-camera2:1.5.2") - implementation("androidx.camera:camera-lifecycle:1.5.2") - implementation("androidx.camera:camera-video:1.5.2") - implementation("androidx.camera:camera-view:1.5.2") - - // Unicast DNS-SD (Wide-Area Bonjour) for tailnet discovery domains. - implementation("dnsjava:dnsjava:3.6.4") - - testImplementation("junit:junit:4.13.2") - testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.2") - testImplementation("io.kotest:kotest-runner-junit5-jvm:6.0.7") - testImplementation("io.kotest:kotest-assertions-core-jvm:6.0.7") - testImplementation("org.robolectric:robolectric:4.16") - testRuntimeOnly("org.junit.vintage:junit-vintage-engine:6.0.2") -} - -tasks.withType().configureEach { - useJUnitPlatform() -} diff --git a/apps/android/app/proguard-rules.pro b/apps/android/app/proguard-rules.pro deleted file mode 100644 index d73c79711d6..00000000000 --- a/apps/android/app/proguard-rules.pro +++ /dev/null @@ -1,28 +0,0 @@ -# ── App classes ─────────────────────────────────────────────────── --keep class ai.openclaw.android.** { *; } - -# ── Bouncy Castle ───────────────────────────────────────────────── --keep class org.bouncycastle.** { *; } --dontwarn org.bouncycastle.** - -# ── CameraX ─────────────────────────────────────────────────────── --keep class androidx.camera.** { *; } - -# ── kotlinx.serialization ──────────────────────────────────────── --keep class kotlinx.serialization.** { *; } --keepclassmembers class * { - @kotlinx.serialization.Serializable *; -} --keepattributes *Annotation*, InnerClasses - -# ── OkHttp ──────────────────────────────────────────────────────── --dontwarn okhttp3.** --dontwarn okio.** --keep class okhttp3.internal.platform.** { *; } - -# ── Misc suppressions ──────────────────────────────────────────── --dontwarn com.sun.jna.** --dontwarn javax.naming.** --dontwarn lombok.Generated --dontwarn org.slf4j.impl.StaticLoggerBinder --dontwarn sun.net.spi.nameservice.NameServiceDescriptor diff --git a/apps/android/app/src/main/AndroidManifest.xml b/apps/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index facdbf301b4..00000000000 --- a/apps/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/android/app/src/main/java/ai/openclaw/android/CameraHudState.kt b/apps/android/app/src/main/java/ai/openclaw/android/CameraHudState.kt deleted file mode 100644 index 636c31bdd3c..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/CameraHudState.kt +++ /dev/null @@ -1,14 +0,0 @@ -package ai.openclaw.android - -enum class CameraHudKind { - Photo, - Recording, - Success, - Error, -} - -data class CameraHudState( - val token: Long, - val kind: CameraHudKind, - val message: String, -) diff --git a/apps/android/app/src/main/java/ai/openclaw/android/DeviceNames.kt b/apps/android/app/src/main/java/ai/openclaw/android/DeviceNames.kt deleted file mode 100644 index 3c44a3bb4f7..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/DeviceNames.kt +++ /dev/null @@ -1,26 +0,0 @@ -package ai.openclaw.android - -import android.content.Context -import android.os.Build -import android.provider.Settings - -object DeviceNames { - fun bestDefaultNodeName(context: Context): String { - val deviceName = - runCatching { - Settings.Global.getString(context.contentResolver, "device_name") - } - .getOrNull() - ?.trim() - .orEmpty() - - if (deviceName.isNotEmpty()) return deviceName - - val model = - listOfNotNull(Build.MANUFACTURER?.takeIf { it.isNotBlank() }, Build.MODEL?.takeIf { it.isNotBlank() }) - .joinToString(" ") - .trim() - - return model.ifEmpty { "Android Node" } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/InstallResultReceiver.kt b/apps/android/app/src/main/java/ai/openclaw/android/InstallResultReceiver.kt deleted file mode 100644 index ffb21258c1c..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/InstallResultReceiver.kt +++ /dev/null @@ -1,33 +0,0 @@ -package ai.openclaw.android - -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.pm.PackageInstaller -import android.util.Log - -class InstallResultReceiver : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE) - val message = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) - - when (status) { - PackageInstaller.STATUS_PENDING_USER_ACTION -> { - // System needs user confirmation — launch the confirmation activity - @Suppress("DEPRECATION") - val confirmIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT) - if (confirmIntent != null) { - confirmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - context.startActivity(confirmIntent) - Log.w("openclaw", "app.update: user confirmation requested, launching install dialog") - } - } - PackageInstaller.STATUS_SUCCESS -> { - Log.w("openclaw", "app.update: install SUCCESS") - } - else -> { - Log.e("openclaw", "app.update: install FAILED status=$status message=$message") - } - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/LocationMode.kt b/apps/android/app/src/main/java/ai/openclaw/android/LocationMode.kt deleted file mode 100644 index eb9c84428e0..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/LocationMode.kt +++ /dev/null @@ -1,15 +0,0 @@ -package ai.openclaw.android - -enum class LocationMode(val rawValue: String) { - Off("off"), - WhileUsing("whileUsing"), - Always("always"), - ; - - companion object { - fun fromRawValue(raw: String?): LocationMode { - val normalized = raw?.trim()?.lowercase() - return entries.firstOrNull { it.rawValue.lowercase() == normalized } ?: Off - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/MainActivity.kt b/apps/android/app/src/main/java/ai/openclaw/android/MainActivity.kt deleted file mode 100644 index 2bbfd8712f9..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/MainActivity.kt +++ /dev/null @@ -1,130 +0,0 @@ -package ai.openclaw.android - -import android.Manifest -import android.content.pm.ApplicationInfo -import android.os.Bundle -import android.os.Build -import android.view.WindowManager -import android.webkit.WebView -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.viewModels -import androidx.compose.material3.Surface -import androidx.compose.ui.Modifier -import androidx.core.content.ContextCompat -import androidx.core.view.WindowCompat -import androidx.core.view.WindowInsetsCompat -import androidx.core.view.WindowInsetsControllerCompat -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.repeatOnLifecycle -import ai.openclaw.android.ui.RootScreen -import ai.openclaw.android.ui.OpenClawTheme -import kotlinx.coroutines.launch - -class MainActivity : ComponentActivity() { - private val viewModel: MainViewModel by viewModels() - private lateinit var permissionRequester: PermissionRequester - private lateinit var screenCaptureRequester: ScreenCaptureRequester - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val isDebuggable = (applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE) != 0 - WebView.setWebContentsDebuggingEnabled(isDebuggable) - applyImmersiveMode() - requestDiscoveryPermissionsIfNeeded() - requestNotificationPermissionIfNeeded() - NodeForegroundService.start(this) - permissionRequester = PermissionRequester(this) - screenCaptureRequester = ScreenCaptureRequester(this) - viewModel.camera.attachLifecycleOwner(this) - viewModel.camera.attachPermissionRequester(permissionRequester) - viewModel.sms.attachPermissionRequester(permissionRequester) - viewModel.screenRecorder.attachScreenCaptureRequester(screenCaptureRequester) - viewModel.screenRecorder.attachPermissionRequester(permissionRequester) - - lifecycleScope.launch { - repeatOnLifecycle(Lifecycle.State.STARTED) { - viewModel.preventSleep.collect { enabled -> - if (enabled) { - window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) - } else { - window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) - } - } - } - } - - setContent { - OpenClawTheme { - Surface(modifier = Modifier) { - RootScreen(viewModel = viewModel) - } - } - } - } - - override fun onResume() { - super.onResume() - applyImmersiveMode() - } - - override fun onWindowFocusChanged(hasFocus: Boolean) { - super.onWindowFocusChanged(hasFocus) - if (hasFocus) { - applyImmersiveMode() - } - } - - override fun onStart() { - super.onStart() - viewModel.setForeground(true) - } - - override fun onStop() { - viewModel.setForeground(false) - super.onStop() - } - - private fun applyImmersiveMode() { - WindowCompat.setDecorFitsSystemWindows(window, false) - val controller = WindowInsetsControllerCompat(window, window.decorView) - controller.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - controller.hide(WindowInsetsCompat.Type.systemBars()) - } - - private fun requestDiscoveryPermissionsIfNeeded() { - if (Build.VERSION.SDK_INT >= 33) { - val ok = - ContextCompat.checkSelfPermission( - this, - Manifest.permission.NEARBY_WIFI_DEVICES, - ) == android.content.pm.PackageManager.PERMISSION_GRANTED - if (!ok) { - requestPermissions(arrayOf(Manifest.permission.NEARBY_WIFI_DEVICES), 100) - } - } else { - val ok = - ContextCompat.checkSelfPermission( - this, - Manifest.permission.ACCESS_FINE_LOCATION, - ) == android.content.pm.PackageManager.PERMISSION_GRANTED - if (!ok) { - requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 101) - } - } - } - - private fun requestNotificationPermissionIfNeeded() { - if (Build.VERSION.SDK_INT < 33) return - val ok = - ContextCompat.checkSelfPermission( - this, - Manifest.permission.POST_NOTIFICATIONS, - ) == android.content.pm.PackageManager.PERMISSION_GRANTED - if (!ok) { - requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 102) - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/MainViewModel.kt b/apps/android/app/src/main/java/ai/openclaw/android/MainViewModel.kt deleted file mode 100644 index d9123d10293..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/MainViewModel.kt +++ /dev/null @@ -1,188 +0,0 @@ -package ai.openclaw.android - -import android.app.Application -import androidx.lifecycle.AndroidViewModel -import ai.openclaw.android.gateway.GatewayEndpoint -import ai.openclaw.android.chat.OutgoingAttachment -import ai.openclaw.android.node.CameraCaptureManager -import ai.openclaw.android.node.CanvasController -import ai.openclaw.android.node.ScreenRecordManager -import ai.openclaw.android.node.SmsManager -import kotlinx.coroutines.flow.StateFlow - -class MainViewModel(app: Application) : AndroidViewModel(app) { - private val runtime: NodeRuntime = (app as NodeApp).runtime - - val canvas: CanvasController = runtime.canvas - val camera: CameraCaptureManager = runtime.camera - val screenRecorder: ScreenRecordManager = runtime.screenRecorder - val sms: SmsManager = runtime.sms - - val gateways: StateFlow> = runtime.gateways - val discoveryStatusText: StateFlow = runtime.discoveryStatusText - - val isConnected: StateFlow = runtime.isConnected - val statusText: StateFlow = runtime.statusText - val serverName: StateFlow = runtime.serverName - val remoteAddress: StateFlow = runtime.remoteAddress - val pendingGatewayTrust: StateFlow = runtime.pendingGatewayTrust - val isForeground: StateFlow = runtime.isForeground - val seamColorArgb: StateFlow = runtime.seamColorArgb - val mainSessionKey: StateFlow = runtime.mainSessionKey - - val cameraHud: StateFlow = runtime.cameraHud - val cameraFlashToken: StateFlow = runtime.cameraFlashToken - val screenRecordActive: StateFlow = runtime.screenRecordActive - - val instanceId: StateFlow = runtime.instanceId - val displayName: StateFlow = runtime.displayName - val cameraEnabled: StateFlow = runtime.cameraEnabled - val locationMode: StateFlow = runtime.locationMode - val locationPreciseEnabled: StateFlow = runtime.locationPreciseEnabled - val preventSleep: StateFlow = runtime.preventSleep - val wakeWords: StateFlow> = runtime.wakeWords - val voiceWakeMode: StateFlow = runtime.voiceWakeMode - val voiceWakeStatusText: StateFlow = runtime.voiceWakeStatusText - val voiceWakeIsListening: StateFlow = runtime.voiceWakeIsListening - val talkEnabled: StateFlow = runtime.talkEnabled - val talkStatusText: StateFlow = runtime.talkStatusText - val talkIsListening: StateFlow = runtime.talkIsListening - val talkIsSpeaking: StateFlow = runtime.talkIsSpeaking - val manualEnabled: StateFlow = runtime.manualEnabled - val manualHost: StateFlow = runtime.manualHost - val manualPort: StateFlow = runtime.manualPort - val manualTls: StateFlow = runtime.manualTls - val gatewayToken: StateFlow = runtime.gatewayToken - val canvasDebugStatusEnabled: StateFlow = runtime.canvasDebugStatusEnabled - - val chatSessionKey: StateFlow = runtime.chatSessionKey - val chatSessionId: StateFlow = runtime.chatSessionId - val chatMessages = runtime.chatMessages - val chatError: StateFlow = runtime.chatError - val chatHealthOk: StateFlow = runtime.chatHealthOk - val chatThinkingLevel: StateFlow = runtime.chatThinkingLevel - val chatStreamingAssistantText: StateFlow = runtime.chatStreamingAssistantText - val chatPendingToolCalls = runtime.chatPendingToolCalls - val chatSessions = runtime.chatSessions - val pendingRunCount: StateFlow = runtime.pendingRunCount - - fun setForeground(value: Boolean) { - runtime.setForeground(value) - } - - fun setDisplayName(value: String) { - runtime.setDisplayName(value) - } - - fun setCameraEnabled(value: Boolean) { - runtime.setCameraEnabled(value) - } - - fun setLocationMode(mode: LocationMode) { - runtime.setLocationMode(mode) - } - - fun setLocationPreciseEnabled(value: Boolean) { - runtime.setLocationPreciseEnabled(value) - } - - fun setPreventSleep(value: Boolean) { - runtime.setPreventSleep(value) - } - - fun setManualEnabled(value: Boolean) { - runtime.setManualEnabled(value) - } - - fun setManualHost(value: String) { - runtime.setManualHost(value) - } - - fun setManualPort(value: Int) { - runtime.setManualPort(value) - } - - fun setManualTls(value: Boolean) { - runtime.setManualTls(value) - } - - fun setGatewayToken(value: String) { - runtime.setGatewayToken(value) - } - - fun setCanvasDebugStatusEnabled(value: Boolean) { - runtime.setCanvasDebugStatusEnabled(value) - } - - fun setWakeWords(words: List) { - runtime.setWakeWords(words) - } - - fun resetWakeWordsDefaults() { - runtime.resetWakeWordsDefaults() - } - - fun setVoiceWakeMode(mode: VoiceWakeMode) { - runtime.setVoiceWakeMode(mode) - } - - fun setTalkEnabled(enabled: Boolean) { - runtime.setTalkEnabled(enabled) - } - - fun refreshGatewayConnection() { - runtime.refreshGatewayConnection() - } - - fun connect(endpoint: GatewayEndpoint) { - runtime.connect(endpoint) - } - - fun connectManual() { - runtime.connectManual() - } - - fun disconnect() { - runtime.disconnect() - } - - fun acceptGatewayTrustPrompt() { - runtime.acceptGatewayTrustPrompt() - } - - fun declineGatewayTrustPrompt() { - runtime.declineGatewayTrustPrompt() - } - - fun handleCanvasA2UIActionFromWebView(payloadJson: String) { - runtime.handleCanvasA2UIActionFromWebView(payloadJson) - } - - fun loadChat(sessionKey: String) { - runtime.loadChat(sessionKey) - } - - fun refreshChat() { - runtime.refreshChat() - } - - fun refreshChatSessions(limit: Int? = null) { - runtime.refreshChatSessions(limit = limit) - } - - fun setChatThinkingLevel(level: String) { - runtime.setChatThinkingLevel(level) - } - - fun switchChatSession(sessionKey: String) { - runtime.switchChatSession(sessionKey) - } - - fun abortChat() { - runtime.abortChat() - } - - fun sendChat(message: String, thinking: String, attachments: List) { - runtime.sendChat(message = message, thinking = thinking, attachments = attachments) - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/NodeApp.kt b/apps/android/app/src/main/java/ai/openclaw/android/NodeApp.kt deleted file mode 100644 index 2be9ee71a2c..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/NodeApp.kt +++ /dev/null @@ -1,37 +0,0 @@ -package ai.openclaw.android - -import android.app.Application -import android.os.StrictMode -import android.util.Log -import java.security.Security - -class NodeApp : Application() { - val runtime: NodeRuntime by lazy { NodeRuntime(this) } - - override fun onCreate() { - super.onCreate() - // Register Bouncy Castle as highest-priority provider for Ed25519 support - try { - val bcProvider = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider") - .getDeclaredConstructor().newInstance() as java.security.Provider - Security.removeProvider("BC") - Security.insertProviderAt(bcProvider, 1) - } catch (it: Throwable) { - Log.e("NodeApp", "Failed to register Bouncy Castle provider", it) - } - if (BuildConfig.DEBUG) { - StrictMode.setThreadPolicy( - StrictMode.ThreadPolicy.Builder() - .detectAll() - .penaltyLog() - .build(), - ) - StrictMode.setVmPolicy( - StrictMode.VmPolicy.Builder() - .detectAll() - .penaltyLog() - .build(), - ) - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/NodeForegroundService.kt b/apps/android/app/src/main/java/ai/openclaw/android/NodeForegroundService.kt deleted file mode 100644 index ee7c8e00674..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/NodeForegroundService.kt +++ /dev/null @@ -1,180 +0,0 @@ -package ai.openclaw.android - -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.app.Service -import android.app.PendingIntent -import android.Manifest -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.content.pm.ServiceInfo -import androidx.core.app.NotificationCompat -import androidx.core.content.ContextCompat -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.cancel -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.launch - -class NodeForegroundService : Service() { - private val scope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) - private var notificationJob: Job? = null - private var lastRequiresMic = false - private var didStartForeground = false - - override fun onCreate() { - super.onCreate() - ensureChannel() - val initial = buildNotification(title = "OpenClaw Node", text = "Starting…") - startForegroundWithTypes(notification = initial, requiresMic = false) - - val runtime = (application as NodeApp).runtime - notificationJob = - scope.launch { - combine( - runtime.statusText, - runtime.serverName, - runtime.isConnected, - runtime.voiceWakeMode, - runtime.voiceWakeIsListening, - ) { status, server, connected, voiceMode, voiceListening -> - Quint(status, server, connected, voiceMode, voiceListening) - }.collect { (status, server, connected, voiceMode, voiceListening) -> - val title = if (connected) "OpenClaw Node · Connected" else "OpenClaw Node" - val voiceSuffix = - if (voiceMode == VoiceWakeMode.Always) { - if (voiceListening) " · Voice Wake: Listening" else " · Voice Wake: Paused" - } else { - "" - } - val text = (server?.let { "$status · $it" } ?: status) + voiceSuffix - - val requiresMic = - voiceMode == VoiceWakeMode.Always && hasRecordAudioPermission() - startForegroundWithTypes( - notification = buildNotification(title = title, text = text), - requiresMic = requiresMic, - ) - } - } - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - when (intent?.action) { - ACTION_STOP -> { - (application as NodeApp).runtime.disconnect() - stopSelf() - return START_NOT_STICKY - } - } - // Keep running; connection is managed by NodeRuntime (auto-reconnect + manual). - return START_STICKY - } - - override fun onDestroy() { - notificationJob?.cancel() - scope.cancel() - super.onDestroy() - } - - override fun onBind(intent: Intent?) = null - - private fun ensureChannel() { - val mgr = getSystemService(NotificationManager::class.java) - val channel = - NotificationChannel( - CHANNEL_ID, - "Connection", - NotificationManager.IMPORTANCE_LOW, - ).apply { - description = "OpenClaw node connection status" - setShowBadge(false) - } - mgr.createNotificationChannel(channel) - } - - private fun buildNotification(title: String, text: String): Notification { - val launchIntent = Intent(this, MainActivity::class.java).apply { - flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP - } - val launchPending = - PendingIntent.getActivity( - this, - 1, - launchIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, - ) - - val stopIntent = Intent(this, NodeForegroundService::class.java).setAction(ACTION_STOP) - val stopPending = - PendingIntent.getService( - this, - 2, - stopIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, - ) - - return NotificationCompat.Builder(this, CHANNEL_ID) - .setSmallIcon(R.mipmap.ic_launcher) - .setContentTitle(title) - .setContentText(text) - .setContentIntent(launchPending) - .setOngoing(true) - .setOnlyAlertOnce(true) - .setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE) - .addAction(0, "Disconnect", stopPending) - .build() - } - - private fun updateNotification(notification: Notification) { - val mgr = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - mgr.notify(NOTIFICATION_ID, notification) - } - - private fun startForegroundWithTypes(notification: Notification, requiresMic: Boolean) { - if (didStartForeground && requiresMic == lastRequiresMic) { - updateNotification(notification) - return - } - - lastRequiresMic = requiresMic - val types = - if (requiresMic) { - ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC or ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE - } else { - ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC - } - startForeground(NOTIFICATION_ID, notification, types) - didStartForeground = true - } - - private fun hasRecordAudioPermission(): Boolean { - return ( - ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == - PackageManager.PERMISSION_GRANTED - ) - } - - companion object { - private const val CHANNEL_ID = "connection" - private const val NOTIFICATION_ID = 1 - - private const val ACTION_STOP = "ai.openclaw.android.action.STOP" - - fun start(context: Context) { - val intent = Intent(context, NodeForegroundService::class.java) - context.startForegroundService(intent) - } - - fun stop(context: Context) { - val intent = Intent(context, NodeForegroundService::class.java).setAction(ACTION_STOP) - context.startService(intent) - } - } -} - -private data class Quint(val first: A, val second: B, val third: C, val fourth: D, val fifth: E) diff --git a/apps/android/app/src/main/java/ai/openclaw/android/NodeRuntime.kt b/apps/android/app/src/main/java/ai/openclaw/android/NodeRuntime.kt deleted file mode 100644 index aec192c25bb..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/NodeRuntime.kt +++ /dev/null @@ -1,753 +0,0 @@ -package ai.openclaw.android - -import android.Manifest -import android.content.Context -import android.content.pm.PackageManager -import android.os.SystemClock -import androidx.core.content.ContextCompat -import ai.openclaw.android.chat.ChatController -import ai.openclaw.android.chat.ChatMessage -import ai.openclaw.android.chat.ChatPendingToolCall -import ai.openclaw.android.chat.ChatSessionEntry -import ai.openclaw.android.chat.OutgoingAttachment -import ai.openclaw.android.gateway.DeviceAuthStore -import ai.openclaw.android.gateway.DeviceIdentityStore -import ai.openclaw.android.gateway.GatewayDiscovery -import ai.openclaw.android.gateway.GatewayEndpoint -import ai.openclaw.android.gateway.GatewaySession -import ai.openclaw.android.gateway.probeGatewayTlsFingerprint -import ai.openclaw.android.node.* -import ai.openclaw.android.protocol.OpenClawCanvasA2UIAction -import ai.openclaw.android.voice.TalkModeManager -import ai.openclaw.android.voice.VoiceWakeManager -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.launch -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonArray -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import kotlinx.serialization.json.buildJsonObject -import java.util.concurrent.atomic.AtomicLong - -class NodeRuntime(context: Context) { - private val appContext = context.applicationContext - private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) - - val prefs = SecurePrefs(appContext) - private val deviceAuthStore = DeviceAuthStore(prefs) - val canvas = CanvasController() - val camera = CameraCaptureManager(appContext) - val location = LocationCaptureManager(appContext) - val screenRecorder = ScreenRecordManager(appContext) - val sms = SmsManager(appContext) - private val json = Json { ignoreUnknownKeys = true } - - private val externalAudioCaptureActive = MutableStateFlow(false) - - private val voiceWake: VoiceWakeManager by lazy { - VoiceWakeManager( - context = appContext, - scope = scope, - onCommand = { command -> - nodeSession.sendNodeEvent( - event = "agent.request", - payloadJson = - buildJsonObject { - put("message", JsonPrimitive(command)) - put("sessionKey", JsonPrimitive(resolveMainSessionKey())) - put("thinking", JsonPrimitive(chatThinkingLevel.value)) - put("deliver", JsonPrimitive(false)) - }.toString(), - ) - }, - ) - } - - val voiceWakeIsListening: StateFlow - get() = voiceWake.isListening - - val voiceWakeStatusText: StateFlow - get() = voiceWake.statusText - - val talkStatusText: StateFlow - get() = talkMode.statusText - - val talkIsListening: StateFlow - get() = talkMode.isListening - - val talkIsSpeaking: StateFlow - get() = talkMode.isSpeaking - - private val discovery = GatewayDiscovery(appContext, scope = scope) - val gateways: StateFlow> = discovery.gateways - val discoveryStatusText: StateFlow = discovery.statusText - - private val identityStore = DeviceIdentityStore(appContext) - private var connectedEndpoint: GatewayEndpoint? = null - - private val cameraHandler: CameraHandler = CameraHandler( - appContext = appContext, - camera = camera, - prefs = prefs, - connectedEndpoint = { connectedEndpoint }, - externalAudioCaptureActive = externalAudioCaptureActive, - showCameraHud = ::showCameraHud, - triggerCameraFlash = ::triggerCameraFlash, - invokeErrorFromThrowable = { invokeErrorFromThrowable(it) }, - ) - - private val debugHandler: DebugHandler = DebugHandler( - appContext = appContext, - identityStore = identityStore, - ) - - private val appUpdateHandler: AppUpdateHandler = AppUpdateHandler( - appContext = appContext, - connectedEndpoint = { connectedEndpoint }, - ) - - private val locationHandler: LocationHandler = LocationHandler( - appContext = appContext, - location = location, - json = json, - isForeground = { _isForeground.value }, - locationMode = { locationMode.value }, - locationPreciseEnabled = { locationPreciseEnabled.value }, - ) - - private val screenHandler: ScreenHandler = ScreenHandler( - screenRecorder = screenRecorder, - setScreenRecordActive = { _screenRecordActive.value = it }, - invokeErrorFromThrowable = { invokeErrorFromThrowable(it) }, - ) - - private val smsHandlerImpl: SmsHandler = SmsHandler( - sms = sms, - ) - - private val a2uiHandler: A2UIHandler = A2UIHandler( - canvas = canvas, - json = json, - getNodeCanvasHostUrl = { nodeSession.currentCanvasHostUrl() }, - getOperatorCanvasHostUrl = { operatorSession.currentCanvasHostUrl() }, - ) - - private val connectionManager: ConnectionManager = ConnectionManager( - prefs = prefs, - cameraEnabled = { cameraEnabled.value }, - locationMode = { locationMode.value }, - voiceWakeMode = { voiceWakeMode.value }, - smsAvailable = { sms.canSendSms() }, - hasRecordAudioPermission = { hasRecordAudioPermission() }, - manualTls = { manualTls.value }, - ) - - private val invokeDispatcher: InvokeDispatcher = InvokeDispatcher( - canvas = canvas, - cameraHandler = cameraHandler, - locationHandler = locationHandler, - screenHandler = screenHandler, - smsHandler = smsHandlerImpl, - a2uiHandler = a2uiHandler, - debugHandler = debugHandler, - appUpdateHandler = appUpdateHandler, - isForeground = { _isForeground.value }, - cameraEnabled = { cameraEnabled.value }, - locationEnabled = { locationMode.value != LocationMode.Off }, - ) - - private lateinit var gatewayEventHandler: GatewayEventHandler - - data class GatewayTrustPrompt( - val endpoint: GatewayEndpoint, - val fingerprintSha256: String, - ) - - private val _isConnected = MutableStateFlow(false) - val isConnected: StateFlow = _isConnected.asStateFlow() - - private val _statusText = MutableStateFlow("Offline") - val statusText: StateFlow = _statusText.asStateFlow() - - private val _pendingGatewayTrust = MutableStateFlow(null) - val pendingGatewayTrust: StateFlow = _pendingGatewayTrust.asStateFlow() - - private val _mainSessionKey = MutableStateFlow("main") - val mainSessionKey: StateFlow = _mainSessionKey.asStateFlow() - - private val cameraHudSeq = AtomicLong(0) - private val _cameraHud = MutableStateFlow(null) - val cameraHud: StateFlow = _cameraHud.asStateFlow() - - private val _cameraFlashToken = MutableStateFlow(0L) - val cameraFlashToken: StateFlow = _cameraFlashToken.asStateFlow() - - private val _screenRecordActive = MutableStateFlow(false) - val screenRecordActive: StateFlow = _screenRecordActive.asStateFlow() - - private val _serverName = MutableStateFlow(null) - val serverName: StateFlow = _serverName.asStateFlow() - - private val _remoteAddress = MutableStateFlow(null) - val remoteAddress: StateFlow = _remoteAddress.asStateFlow() - - private val _seamColorArgb = MutableStateFlow(DEFAULT_SEAM_COLOR_ARGB) - val seamColorArgb: StateFlow = _seamColorArgb.asStateFlow() - - private val _isForeground = MutableStateFlow(true) - val isForeground: StateFlow = _isForeground.asStateFlow() - - private var lastAutoA2uiUrl: String? = null - private var operatorConnected = false - private var nodeConnected = false - private var operatorStatusText: String = "Offline" - private var nodeStatusText: String = "Offline" - - private val operatorSession = - GatewaySession( - scope = scope, - identityStore = identityStore, - deviceAuthStore = deviceAuthStore, - onConnected = { name, remote, mainSessionKey -> - operatorConnected = true - operatorStatusText = "Connected" - _serverName.value = name - _remoteAddress.value = remote - _seamColorArgb.value = DEFAULT_SEAM_COLOR_ARGB - applyMainSessionKey(mainSessionKey) - updateStatus() - scope.launch { refreshBrandingFromGateway() } - scope.launch { gatewayEventHandler.refreshWakeWordsFromGateway() } - }, - onDisconnected = { message -> - operatorConnected = false - operatorStatusText = message - _serverName.value = null - _remoteAddress.value = null - _seamColorArgb.value = DEFAULT_SEAM_COLOR_ARGB - if (!isCanonicalMainSessionKey(_mainSessionKey.value)) { - _mainSessionKey.value = "main" - } - val mainKey = resolveMainSessionKey() - talkMode.setMainSessionKey(mainKey) - chat.applyMainSessionKey(mainKey) - chat.onDisconnected(message) - updateStatus() - }, - onEvent = { event, payloadJson -> - handleGatewayEvent(event, payloadJson) - }, - ) - - private val nodeSession = - GatewaySession( - scope = scope, - identityStore = identityStore, - deviceAuthStore = deviceAuthStore, - onConnected = { _, _, _ -> - nodeConnected = true - nodeStatusText = "Connected" - updateStatus() - maybeNavigateToA2uiOnConnect() - }, - onDisconnected = { message -> - nodeConnected = false - nodeStatusText = message - updateStatus() - showLocalCanvasOnDisconnect() - }, - onEvent = { _, _ -> }, - onInvoke = { req -> - invokeDispatcher.handleInvoke(req.command, req.paramsJson) - }, - onTlsFingerprint = { stableId, fingerprint -> - prefs.saveGatewayTlsFingerprint(stableId, fingerprint) - }, - ) - - private val chat: ChatController = - ChatController( - scope = scope, - session = operatorSession, - json = json, - supportsChatSubscribe = false, - ) - private val talkMode: TalkModeManager by lazy { - TalkModeManager( - context = appContext, - scope = scope, - session = operatorSession, - supportsChatSubscribe = false, - isConnected = { operatorConnected }, - ) - } - - private fun applyMainSessionKey(candidate: String?) { - val trimmed = normalizeMainKey(candidate) ?: return - if (isCanonicalMainSessionKey(_mainSessionKey.value)) return - if (_mainSessionKey.value == trimmed) return - _mainSessionKey.value = trimmed - talkMode.setMainSessionKey(trimmed) - chat.applyMainSessionKey(trimmed) - } - - private fun updateStatus() { - _isConnected.value = operatorConnected - _statusText.value = - when { - operatorConnected && nodeConnected -> "Connected" - operatorConnected && !nodeConnected -> "Connected (node offline)" - !operatorConnected && nodeConnected -> "Connected (operator offline)" - operatorStatusText.isNotBlank() && operatorStatusText != "Offline" -> operatorStatusText - else -> nodeStatusText - } - } - - private fun resolveMainSessionKey(): String { - val trimmed = _mainSessionKey.value.trim() - return if (trimmed.isEmpty()) "main" else trimmed - } - - private fun maybeNavigateToA2uiOnConnect() { - val a2uiUrl = a2uiHandler.resolveA2uiHostUrl() ?: return - val current = canvas.currentUrl()?.trim().orEmpty() - if (current.isEmpty() || current == lastAutoA2uiUrl) { - lastAutoA2uiUrl = a2uiUrl - canvas.navigate(a2uiUrl) - } - } - - private fun showLocalCanvasOnDisconnect() { - lastAutoA2uiUrl = null - canvas.navigate("") - } - - val instanceId: StateFlow = prefs.instanceId - val displayName: StateFlow = prefs.displayName - val cameraEnabled: StateFlow = prefs.cameraEnabled - val locationMode: StateFlow = prefs.locationMode - val locationPreciseEnabled: StateFlow = prefs.locationPreciseEnabled - val preventSleep: StateFlow = prefs.preventSleep - val wakeWords: StateFlow> = prefs.wakeWords - val voiceWakeMode: StateFlow = prefs.voiceWakeMode - val talkEnabled: StateFlow = prefs.talkEnabled - val manualEnabled: StateFlow = prefs.manualEnabled - val manualHost: StateFlow = prefs.manualHost - val manualPort: StateFlow = prefs.manualPort - val manualTls: StateFlow = prefs.manualTls - val gatewayToken: StateFlow = prefs.gatewayToken - fun setGatewayToken(value: String) = prefs.setGatewayToken(value) - val lastDiscoveredStableId: StateFlow = prefs.lastDiscoveredStableId - val canvasDebugStatusEnabled: StateFlow = prefs.canvasDebugStatusEnabled - - private var didAutoConnect = false - - val chatSessionKey: StateFlow = chat.sessionKey - val chatSessionId: StateFlow = chat.sessionId - val chatMessages: StateFlow> = chat.messages - val chatError: StateFlow = chat.errorText - val chatHealthOk: StateFlow = chat.healthOk - val chatThinkingLevel: StateFlow = chat.thinkingLevel - val chatStreamingAssistantText: StateFlow = chat.streamingAssistantText - val chatPendingToolCalls: StateFlow> = chat.pendingToolCalls - val chatSessions: StateFlow> = chat.sessions - val pendingRunCount: StateFlow = chat.pendingRunCount - - init { - gatewayEventHandler = GatewayEventHandler( - scope = scope, - prefs = prefs, - json = json, - operatorSession = operatorSession, - isConnected = { _isConnected.value }, - ) - - scope.launch { - combine( - voiceWakeMode, - isForeground, - externalAudioCaptureActive, - wakeWords, - ) { mode, foreground, externalAudio, words -> - Quad(mode, foreground, externalAudio, words) - }.distinctUntilChanged() - .collect { (mode, foreground, externalAudio, words) -> - voiceWake.setTriggerWords(words) - - val shouldListen = - when (mode) { - VoiceWakeMode.Off -> false - VoiceWakeMode.Foreground -> foreground - VoiceWakeMode.Always -> true - } && !externalAudio - - if (!shouldListen) { - voiceWake.stop(statusText = if (mode == VoiceWakeMode.Off) "Off" else "Paused") - return@collect - } - - if (!hasRecordAudioPermission()) { - voiceWake.stop(statusText = "Microphone permission required") - return@collect - } - - voiceWake.start() - } - } - - scope.launch { - talkEnabled.collect { enabled -> - talkMode.setEnabled(enabled) - externalAudioCaptureActive.value = enabled - } - } - - scope.launch(Dispatchers.Default) { - gateways.collect { list -> - if (list.isNotEmpty()) { - // Security: don't let an unauthenticated discovery feed continuously steer autoconnect. - // UX parity with iOS: only set once when unset. - if (lastDiscoveredStableId.value.trim().isEmpty()) { - prefs.setLastDiscoveredStableId(list.first().stableId) - } - } - - if (didAutoConnect) return@collect - if (_isConnected.value) return@collect - - if (manualEnabled.value) { - val host = manualHost.value.trim() - val port = manualPort.value - if (host.isNotEmpty() && port in 1..65535) { - // Security: autoconnect only to previously trusted gateways (stored TLS pin). - if (!manualTls.value) return@collect - val stableId = GatewayEndpoint.manual(host = host, port = port).stableId - val storedFingerprint = prefs.loadGatewayTlsFingerprint(stableId)?.trim().orEmpty() - if (storedFingerprint.isEmpty()) return@collect - - didAutoConnect = true - connect(GatewayEndpoint.manual(host = host, port = port)) - } - return@collect - } - - val targetStableId = lastDiscoveredStableId.value.trim() - if (targetStableId.isEmpty()) return@collect - val target = list.firstOrNull { it.stableId == targetStableId } ?: return@collect - - // Security: autoconnect only to previously trusted gateways (stored TLS pin). - val storedFingerprint = prefs.loadGatewayTlsFingerprint(target.stableId)?.trim().orEmpty() - if (storedFingerprint.isEmpty()) return@collect - - didAutoConnect = true - connect(target) - } - } - - scope.launch { - combine( - canvasDebugStatusEnabled, - statusText, - serverName, - remoteAddress, - ) { debugEnabled, status, server, remote -> - Quad(debugEnabled, status, server, remote) - }.distinctUntilChanged() - .collect { (debugEnabled, status, server, remote) -> - canvas.setDebugStatusEnabled(debugEnabled) - if (!debugEnabled) return@collect - canvas.setDebugStatus(status, server ?: remote) - } - } - } - - fun setForeground(value: Boolean) { - _isForeground.value = value - } - - fun setDisplayName(value: String) { - prefs.setDisplayName(value) - } - - fun setCameraEnabled(value: Boolean) { - prefs.setCameraEnabled(value) - } - - fun setLocationMode(mode: LocationMode) { - prefs.setLocationMode(mode) - } - - fun setLocationPreciseEnabled(value: Boolean) { - prefs.setLocationPreciseEnabled(value) - } - - fun setPreventSleep(value: Boolean) { - prefs.setPreventSleep(value) - } - - fun setManualEnabled(value: Boolean) { - prefs.setManualEnabled(value) - } - - fun setManualHost(value: String) { - prefs.setManualHost(value) - } - - fun setManualPort(value: Int) { - prefs.setManualPort(value) - } - - fun setManualTls(value: Boolean) { - prefs.setManualTls(value) - } - - fun setCanvasDebugStatusEnabled(value: Boolean) { - prefs.setCanvasDebugStatusEnabled(value) - } - - fun setWakeWords(words: List) { - prefs.setWakeWords(words) - gatewayEventHandler.scheduleWakeWordsSyncIfNeeded() - } - - fun resetWakeWordsDefaults() { - setWakeWords(SecurePrefs.defaultWakeWords) - } - - fun setVoiceWakeMode(mode: VoiceWakeMode) { - prefs.setVoiceWakeMode(mode) - } - - fun setTalkEnabled(value: Boolean) { - prefs.setTalkEnabled(value) - } - - fun refreshGatewayConnection() { - val endpoint = connectedEndpoint ?: return - val token = prefs.loadGatewayToken() - val password = prefs.loadGatewayPassword() - val tls = connectionManager.resolveTlsParams(endpoint) - operatorSession.connect(endpoint, token, password, connectionManager.buildOperatorConnectOptions(), tls) - nodeSession.connect(endpoint, token, password, connectionManager.buildNodeConnectOptions(), tls) - operatorSession.reconnect() - nodeSession.reconnect() - } - - fun connect(endpoint: GatewayEndpoint) { - val tls = connectionManager.resolveTlsParams(endpoint) - if (tls?.required == true && tls.expectedFingerprint.isNullOrBlank()) { - // First-time TLS: capture fingerprint, ask user to verify out-of-band, then store and connect. - _statusText.value = "Verify gateway TLS fingerprint…" - scope.launch { - val fp = probeGatewayTlsFingerprint(endpoint.host, endpoint.port) ?: run { - _statusText.value = "Failed: can't read TLS fingerprint" - return@launch - } - _pendingGatewayTrust.value = GatewayTrustPrompt(endpoint = endpoint, fingerprintSha256 = fp) - } - return - } - - connectedEndpoint = endpoint - operatorStatusText = "Connecting…" - nodeStatusText = "Connecting…" - updateStatus() - val token = prefs.loadGatewayToken() - val password = prefs.loadGatewayPassword() - operatorSession.connect(endpoint, token, password, connectionManager.buildOperatorConnectOptions(), tls) - nodeSession.connect(endpoint, token, password, connectionManager.buildNodeConnectOptions(), tls) - } - - fun acceptGatewayTrustPrompt() { - val prompt = _pendingGatewayTrust.value ?: return - _pendingGatewayTrust.value = null - prefs.saveGatewayTlsFingerprint(prompt.endpoint.stableId, prompt.fingerprintSha256) - connect(prompt.endpoint) - } - - fun declineGatewayTrustPrompt() { - _pendingGatewayTrust.value = null - _statusText.value = "Offline" - } - - private fun hasRecordAudioPermission(): Boolean { - return ( - ContextCompat.checkSelfPermission(appContext, Manifest.permission.RECORD_AUDIO) == - PackageManager.PERMISSION_GRANTED - ) - } - - fun connectManual() { - val host = manualHost.value.trim() - val port = manualPort.value - if (host.isEmpty() || port <= 0 || port > 65535) { - _statusText.value = "Failed: invalid manual host/port" - return - } - connect(GatewayEndpoint.manual(host = host, port = port)) - } - - fun disconnect() { - connectedEndpoint = null - _pendingGatewayTrust.value = null - operatorSession.disconnect() - nodeSession.disconnect() - } - - fun handleCanvasA2UIActionFromWebView(payloadJson: String) { - scope.launch { - val trimmed = payloadJson.trim() - if (trimmed.isEmpty()) return@launch - - val root = - try { - json.parseToJsonElement(trimmed).asObjectOrNull() ?: return@launch - } catch (_: Throwable) { - return@launch - } - - val userActionObj = (root["userAction"] as? JsonObject) ?: root - val actionId = (userActionObj["id"] as? JsonPrimitive)?.content?.trim().orEmpty().ifEmpty { - java.util.UUID.randomUUID().toString() - } - val name = OpenClawCanvasA2UIAction.extractActionName(userActionObj) ?: return@launch - - val surfaceId = - (userActionObj["surfaceId"] as? JsonPrimitive)?.content?.trim().orEmpty().ifEmpty { "main" } - val sourceComponentId = - (userActionObj["sourceComponentId"] as? JsonPrimitive)?.content?.trim().orEmpty().ifEmpty { "-" } - val contextJson = (userActionObj["context"] as? JsonObject)?.toString() - - val sessionKey = resolveMainSessionKey() - val message = - OpenClawCanvasA2UIAction.formatAgentMessage( - actionName = name, - sessionKey = sessionKey, - surfaceId = surfaceId, - sourceComponentId = sourceComponentId, - host = displayName.value, - instanceId = instanceId.value.lowercase(), - contextJson = contextJson, - ) - - val connected = nodeConnected - var error: String? = null - if (connected) { - try { - nodeSession.sendNodeEvent( - event = "agent.request", - payloadJson = - buildJsonObject { - put("message", JsonPrimitive(message)) - put("sessionKey", JsonPrimitive(sessionKey)) - put("thinking", JsonPrimitive("low")) - put("deliver", JsonPrimitive(false)) - put("key", JsonPrimitive(actionId)) - }.toString(), - ) - } catch (e: Throwable) { - error = e.message ?: "send failed" - } - } else { - error = "gateway not connected" - } - - try { - canvas.eval( - OpenClawCanvasA2UIAction.jsDispatchA2UIActionStatus( - actionId = actionId, - ok = connected && error == null, - error = error, - ), - ) - } catch (_: Throwable) { - // ignore - } - } - } - - fun loadChat(sessionKey: String) { - val key = sessionKey.trim().ifEmpty { resolveMainSessionKey() } - chat.load(key) - } - - fun refreshChat() { - chat.refresh() - } - - fun refreshChatSessions(limit: Int? = null) { - chat.refreshSessions(limit = limit) - } - - fun setChatThinkingLevel(level: String) { - chat.setThinkingLevel(level) - } - - fun switchChatSession(sessionKey: String) { - chat.switchSession(sessionKey) - } - - fun abortChat() { - chat.abort() - } - - fun sendChat(message: String, thinking: String, attachments: List) { - chat.sendMessage(message = message, thinkingLevel = thinking, attachments = attachments) - } - - private fun handleGatewayEvent(event: String, payloadJson: String?) { - if (event == "voicewake.changed") { - gatewayEventHandler.handleVoiceWakeChangedEvent(payloadJson) - return - } - - talkMode.handleGatewayEvent(event, payloadJson) - chat.handleGatewayEvent(event, payloadJson) - } - - private suspend fun refreshBrandingFromGateway() { - if (!_isConnected.value) return - try { - val res = operatorSession.request("config.get", "{}") - val root = json.parseToJsonElement(res).asObjectOrNull() - val config = root?.get("config").asObjectOrNull() - val ui = config?.get("ui").asObjectOrNull() - val raw = ui?.get("seamColor").asStringOrNull()?.trim() - val sessionCfg = config?.get("session").asObjectOrNull() - val mainKey = normalizeMainKey(sessionCfg?.get("mainKey").asStringOrNull()) - applyMainSessionKey(mainKey) - - val parsed = parseHexColorArgb(raw) - _seamColorArgb.value = parsed ?: DEFAULT_SEAM_COLOR_ARGB - } catch (_: Throwable) { - // ignore - } - } - - private fun triggerCameraFlash() { - // Token is used as a pulse trigger; value doesn't matter as long as it changes. - _cameraFlashToken.value = SystemClock.elapsedRealtimeNanos() - } - - private fun showCameraHud(message: String, kind: CameraHudKind, autoHideMs: Long? = null) { - val token = cameraHudSeq.incrementAndGet() - _cameraHud.value = CameraHudState(token = token, kind = kind, message = message) - - if (autoHideMs != null && autoHideMs > 0) { - scope.launch { - delay(autoHideMs) - if (_cameraHud.value?.token == token) _cameraHud.value = null - } - } - } - -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/PermissionRequester.kt b/apps/android/app/src/main/java/ai/openclaw/android/PermissionRequester.kt deleted file mode 100644 index 0ee267b5588..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/PermissionRequester.kt +++ /dev/null @@ -1,133 +0,0 @@ -package ai.openclaw.android - -import android.content.pm.PackageManager -import android.content.Intent -import android.Manifest -import android.net.Uri -import android.provider.Settings -import androidx.appcompat.app.AlertDialog -import androidx.activity.ComponentActivity -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts -import androidx.core.content.ContextCompat -import androidx.core.app.ActivityCompat -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import kotlinx.coroutines.withContext -import kotlinx.coroutines.suspendCancellableCoroutine -import kotlin.coroutines.resume - -class PermissionRequester(private val activity: ComponentActivity) { - private val mutex = Mutex() - private var pending: CompletableDeferred>? = null - - private val launcher: ActivityResultLauncher> = - activity.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result -> - val p = pending - pending = null - p?.complete(result) - } - - suspend fun requestIfMissing( - permissions: List, - timeoutMs: Long = 20_000, - ): Map = - mutex.withLock { - val missing = - permissions.filter { perm -> - ContextCompat.checkSelfPermission(activity, perm) != PackageManager.PERMISSION_GRANTED - } - if (missing.isEmpty()) { - return permissions.associateWith { true } - } - - val needsRationale = - missing.any { ActivityCompat.shouldShowRequestPermissionRationale(activity, it) } - if (needsRationale) { - val proceed = showRationaleDialog(missing) - if (!proceed) { - return permissions.associateWith { perm -> - ContextCompat.checkSelfPermission(activity, perm) == PackageManager.PERMISSION_GRANTED - } - } - } - - val deferred = CompletableDeferred>() - pending = deferred - withContext(Dispatchers.Main) { - launcher.launch(missing.toTypedArray()) - } - - val result = - withContext(Dispatchers.Default) { - kotlinx.coroutines.withTimeout(timeoutMs) { deferred.await() } - } - - // Merge: if something was already granted, treat it as granted even if launcher omitted it. - val merged = - permissions.associateWith { perm -> - val nowGranted = - ContextCompat.checkSelfPermission(activity, perm) == PackageManager.PERMISSION_GRANTED - result[perm] == true || nowGranted - } - - val denied = - merged.filterValues { !it }.keys.filter { - !ActivityCompat.shouldShowRequestPermissionRationale(activity, it) - } - if (denied.isNotEmpty()) { - showSettingsDialog(denied) - } - - return merged - } - - private suspend fun showRationaleDialog(permissions: List): Boolean = - withContext(Dispatchers.Main) { - suspendCancellableCoroutine { cont -> - AlertDialog.Builder(activity) - .setTitle("Permission required") - .setMessage(buildRationaleMessage(permissions)) - .setPositiveButton("Continue") { _, _ -> cont.resume(true) } - .setNegativeButton("Not now") { _, _ -> cont.resume(false) } - .setOnCancelListener { cont.resume(false) } - .show() - } - } - - private fun showSettingsDialog(permissions: List) { - AlertDialog.Builder(activity) - .setTitle("Enable permission in Settings") - .setMessage(buildSettingsMessage(permissions)) - .setPositiveButton("Open Settings") { _, _ -> - val intent = - Intent( - Settings.ACTION_APPLICATION_DETAILS_SETTINGS, - Uri.fromParts("package", activity.packageName, null), - ) - activity.startActivity(intent) - } - .setNegativeButton("Cancel", null) - .show() - } - - private fun buildRationaleMessage(permissions: List): String { - val labels = permissions.map { permissionLabel(it) } - return "OpenClaw needs ${labels.joinToString(", ")} permissions to continue." - } - - private fun buildSettingsMessage(permissions: List): String { - val labels = permissions.map { permissionLabel(it) } - return "Please enable ${labels.joinToString(", ")} in Android Settings to continue." - } - - private fun permissionLabel(permission: String): String = - when (permission) { - Manifest.permission.CAMERA -> "Camera" - Manifest.permission.RECORD_AUDIO -> "Microphone" - Manifest.permission.SEND_SMS -> "SMS" - else -> permission - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ScreenCaptureRequester.kt b/apps/android/app/src/main/java/ai/openclaw/android/ScreenCaptureRequester.kt deleted file mode 100644 index c215103b54d..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ScreenCaptureRequester.kt +++ /dev/null @@ -1,65 +0,0 @@ -package ai.openclaw.android - -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.media.projection.MediaProjectionManager -import androidx.activity.ComponentActivity -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts -import androidx.appcompat.app.AlertDialog -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import kotlinx.coroutines.withContext -import kotlinx.coroutines.withTimeout -import kotlinx.coroutines.suspendCancellableCoroutine -import kotlin.coroutines.resume - -class ScreenCaptureRequester(private val activity: ComponentActivity) { - data class CaptureResult(val resultCode: Int, val data: Intent) - - private val mutex = Mutex() - private var pending: CompletableDeferred? = null - - private val launcher: ActivityResultLauncher = - activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - val p = pending - pending = null - val data = result.data - if (result.resultCode == Activity.RESULT_OK && data != null) { - p?.complete(CaptureResult(result.resultCode, data)) - } else { - p?.complete(null) - } - } - - suspend fun requestCapture(timeoutMs: Long = 20_000): CaptureResult? = - mutex.withLock { - val proceed = showRationaleDialog() - if (!proceed) return null - - val mgr = activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager - val intent = mgr.createScreenCaptureIntent() - - val deferred = CompletableDeferred() - pending = deferred - withContext(Dispatchers.Main) { launcher.launch(intent) } - - withContext(Dispatchers.Default) { withTimeout(timeoutMs) { deferred.await() } } - } - - private suspend fun showRationaleDialog(): Boolean = - withContext(Dispatchers.Main) { - suspendCancellableCoroutine { cont -> - AlertDialog.Builder(activity) - .setTitle("Screen recording required") - .setMessage("OpenClaw needs to record the screen for this command.") - .setPositiveButton("Continue") { _, _ -> cont.resume(true) } - .setNegativeButton("Not now") { _, _ -> cont.resume(false) } - .setOnCancelListener { cont.resume(false) } - .show() - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/SecurePrefs.kt b/apps/android/app/src/main/java/ai/openclaw/android/SecurePrefs.kt deleted file mode 100644 index 29ef4a3eaae..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/SecurePrefs.kt +++ /dev/null @@ -1,285 +0,0 @@ -@file:Suppress("DEPRECATION") - -package ai.openclaw.android - -import android.content.Context -import android.content.SharedPreferences -import androidx.core.content.edit -import androidx.security.crypto.EncryptedSharedPreferences -import androidx.security.crypto.MasterKey -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonArray -import kotlinx.serialization.json.JsonNull -import kotlinx.serialization.json.JsonPrimitive -import java.util.UUID - -class SecurePrefs(context: Context) { - companion object { - val defaultWakeWords: List = listOf("openclaw", "claude") - private const val displayNameKey = "node.displayName" - private const val voiceWakeModeKey = "voiceWake.mode" - } - - private val appContext = context.applicationContext - private val json = Json { ignoreUnknownKeys = true } - - private val masterKey = - MasterKey.Builder(context) - .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) - .build() - - private val prefs: SharedPreferences by lazy { - createPrefs(appContext, "openclaw.node.secure") - } - - private val _instanceId = MutableStateFlow(loadOrCreateInstanceId()) - val instanceId: StateFlow = _instanceId - - private val _displayName = - MutableStateFlow(loadOrMigrateDisplayName(context = context)) - val displayName: StateFlow = _displayName - - private val _cameraEnabled = MutableStateFlow(prefs.getBoolean("camera.enabled", true)) - val cameraEnabled: StateFlow = _cameraEnabled - - private val _locationMode = - MutableStateFlow(LocationMode.fromRawValue(prefs.getString("location.enabledMode", "off"))) - val locationMode: StateFlow = _locationMode - - private val _locationPreciseEnabled = - MutableStateFlow(prefs.getBoolean("location.preciseEnabled", true)) - val locationPreciseEnabled: StateFlow = _locationPreciseEnabled - - private val _preventSleep = MutableStateFlow(prefs.getBoolean("screen.preventSleep", true)) - val preventSleep: StateFlow = _preventSleep - - private val _manualEnabled = - MutableStateFlow(prefs.getBoolean("gateway.manual.enabled", false)) - val manualEnabled: StateFlow = _manualEnabled - - private val _manualHost = - MutableStateFlow(prefs.getString("gateway.manual.host", "") ?: "") - val manualHost: StateFlow = _manualHost - - private val _manualPort = - MutableStateFlow(prefs.getInt("gateway.manual.port", 18789)) - val manualPort: StateFlow = _manualPort - - private val _manualTls = - MutableStateFlow(prefs.getBoolean("gateway.manual.tls", true)) - val manualTls: StateFlow = _manualTls - - private val _gatewayToken = - MutableStateFlow(prefs.getString("gateway.manual.token", "") ?: "") - val gatewayToken: StateFlow = _gatewayToken - - private val _lastDiscoveredStableId = - MutableStateFlow( - prefs.getString("gateway.lastDiscoveredStableID", "") ?: "", - ) - val lastDiscoveredStableId: StateFlow = _lastDiscoveredStableId - - private val _canvasDebugStatusEnabled = - MutableStateFlow(prefs.getBoolean("canvas.debugStatusEnabled", false)) - val canvasDebugStatusEnabled: StateFlow = _canvasDebugStatusEnabled - - private val _wakeWords = MutableStateFlow(loadWakeWords()) - val wakeWords: StateFlow> = _wakeWords - - private val _voiceWakeMode = MutableStateFlow(loadVoiceWakeMode()) - val voiceWakeMode: StateFlow = _voiceWakeMode - - private val _talkEnabled = MutableStateFlow(prefs.getBoolean("talk.enabled", false)) - val talkEnabled: StateFlow = _talkEnabled - - fun setLastDiscoveredStableId(value: String) { - val trimmed = value.trim() - prefs.edit { putString("gateway.lastDiscoveredStableID", trimmed) } - _lastDiscoveredStableId.value = trimmed - } - - fun setDisplayName(value: String) { - val trimmed = value.trim() - prefs.edit { putString(displayNameKey, trimmed) } - _displayName.value = trimmed - } - - fun setCameraEnabled(value: Boolean) { - prefs.edit { putBoolean("camera.enabled", value) } - _cameraEnabled.value = value - } - - fun setLocationMode(mode: LocationMode) { - prefs.edit { putString("location.enabledMode", mode.rawValue) } - _locationMode.value = mode - } - - fun setLocationPreciseEnabled(value: Boolean) { - prefs.edit { putBoolean("location.preciseEnabled", value) } - _locationPreciseEnabled.value = value - } - - fun setPreventSleep(value: Boolean) { - prefs.edit { putBoolean("screen.preventSleep", value) } - _preventSleep.value = value - } - - fun setManualEnabled(value: Boolean) { - prefs.edit { putBoolean("gateway.manual.enabled", value) } - _manualEnabled.value = value - } - - fun setManualHost(value: String) { - val trimmed = value.trim() - prefs.edit { putString("gateway.manual.host", trimmed) } - _manualHost.value = trimmed - } - - fun setManualPort(value: Int) { - prefs.edit { putInt("gateway.manual.port", value) } - _manualPort.value = value - } - - fun setManualTls(value: Boolean) { - prefs.edit { putBoolean("gateway.manual.tls", value) } - _manualTls.value = value - } - - fun setGatewayToken(value: String) { - prefs.edit { putString("gateway.manual.token", value) } - _gatewayToken.value = value - } - - fun setCanvasDebugStatusEnabled(value: Boolean) { - prefs.edit { putBoolean("canvas.debugStatusEnabled", value) } - _canvasDebugStatusEnabled.value = value - } - - fun loadGatewayToken(): String? { - val manual = _gatewayToken.value.trim() - if (manual.isNotEmpty()) return manual - val key = "gateway.token.${_instanceId.value}" - val stored = prefs.getString(key, null)?.trim() - return stored?.takeIf { it.isNotEmpty() } - } - - fun saveGatewayToken(token: String) { - val key = "gateway.token.${_instanceId.value}" - prefs.edit { putString(key, token.trim()) } - } - - fun loadGatewayPassword(): String? { - val key = "gateway.password.${_instanceId.value}" - val stored = prefs.getString(key, null)?.trim() - return stored?.takeIf { it.isNotEmpty() } - } - - fun saveGatewayPassword(password: String) { - val key = "gateway.password.${_instanceId.value}" - prefs.edit { putString(key, password.trim()) } - } - - fun loadGatewayTlsFingerprint(stableId: String): String? { - val key = "gateway.tls.$stableId" - return prefs.getString(key, null)?.trim()?.takeIf { it.isNotEmpty() } - } - - fun saveGatewayTlsFingerprint(stableId: String, fingerprint: String) { - val key = "gateway.tls.$stableId" - prefs.edit { putString(key, fingerprint.trim()) } - } - - fun getString(key: String): String? { - return prefs.getString(key, null) - } - - fun putString(key: String, value: String) { - prefs.edit { putString(key, value) } - } - - fun remove(key: String) { - prefs.edit { remove(key) } - } - - private fun createPrefs(context: Context, name: String): SharedPreferences { - return EncryptedSharedPreferences.create( - context, - name, - masterKey, - EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, - EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM, - ) - } - - private fun loadOrCreateInstanceId(): String { - val existing = prefs.getString("node.instanceId", null)?.trim() - if (!existing.isNullOrBlank()) return existing - val fresh = UUID.randomUUID().toString() - prefs.edit { putString("node.instanceId", fresh) } - return fresh - } - - private fun loadOrMigrateDisplayName(context: Context): String { - val existing = prefs.getString(displayNameKey, null)?.trim().orEmpty() - if (existing.isNotEmpty() && existing != "Android Node") return existing - - val candidate = DeviceNames.bestDefaultNodeName(context).trim() - val resolved = candidate.ifEmpty { "Android Node" } - - prefs.edit { putString(displayNameKey, resolved) } - return resolved - } - - fun setWakeWords(words: List) { - val sanitized = WakeWords.sanitize(words, defaultWakeWords) - val encoded = - JsonArray(sanitized.map { JsonPrimitive(it) }).toString() - prefs.edit { putString("voiceWake.triggerWords", encoded) } - _wakeWords.value = sanitized - } - - fun setVoiceWakeMode(mode: VoiceWakeMode) { - prefs.edit { putString(voiceWakeModeKey, mode.rawValue) } - _voiceWakeMode.value = mode - } - - fun setTalkEnabled(value: Boolean) { - prefs.edit { putBoolean("talk.enabled", value) } - _talkEnabled.value = value - } - - private fun loadVoiceWakeMode(): VoiceWakeMode { - val raw = prefs.getString(voiceWakeModeKey, null) - val resolved = VoiceWakeMode.fromRawValue(raw) - - // Default ON (foreground) when unset. - if (raw.isNullOrBlank()) { - prefs.edit { putString(voiceWakeModeKey, resolved.rawValue) } - } - - return resolved - } - - private fun loadWakeWords(): List { - val raw = prefs.getString("voiceWake.triggerWords", null)?.trim() - if (raw.isNullOrEmpty()) return defaultWakeWords - return try { - val element = json.parseToJsonElement(raw) - val array = element as? JsonArray ?: return defaultWakeWords - val decoded = - array.mapNotNull { item -> - when (item) { - is JsonNull -> null - is JsonPrimitive -> item.content.trim().takeIf { it.isNotEmpty() } - else -> null - } - } - WakeWords.sanitize(decoded, defaultWakeWords) - } catch (_: Throwable) { - defaultWakeWords - } - } - -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/SessionKey.kt b/apps/android/app/src/main/java/ai/openclaw/android/SessionKey.kt deleted file mode 100644 index 8148a17029e..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/SessionKey.kt +++ /dev/null @@ -1,13 +0,0 @@ -package ai.openclaw.android - -internal fun normalizeMainKey(raw: String?): String { - val trimmed = raw?.trim() - return if (!trimmed.isNullOrEmpty()) trimmed else "main" -} - -internal fun isCanonicalMainSessionKey(raw: String?): Boolean { - val trimmed = raw?.trim().orEmpty() - if (trimmed.isEmpty()) return false - if (trimmed == "global") return true - return trimmed.startsWith("agent:") -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/VoiceWakeMode.kt b/apps/android/app/src/main/java/ai/openclaw/android/VoiceWakeMode.kt deleted file mode 100644 index 75c2fe34468..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/VoiceWakeMode.kt +++ /dev/null @@ -1,14 +0,0 @@ -package ai.openclaw.android - -enum class VoiceWakeMode(val rawValue: String) { - Off("off"), - Foreground("foreground"), - Always("always"), - ; - - companion object { - fun fromRawValue(raw: String?): VoiceWakeMode { - return entries.firstOrNull { it.rawValue == raw?.trim()?.lowercase() } ?: Foreground - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/WakeWords.kt b/apps/android/app/src/main/java/ai/openclaw/android/WakeWords.kt deleted file mode 100644 index b64cb1dd749..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/WakeWords.kt +++ /dev/null @@ -1,21 +0,0 @@ -package ai.openclaw.android - -object WakeWords { - const val maxWords: Int = 32 - const val maxWordLength: Int = 64 - - fun parseCommaSeparated(input: String): List { - return input.split(",").map { it.trim() }.filter { it.isNotEmpty() } - } - - fun parseIfChanged(input: String, current: List): List? { - val parsed = parseCommaSeparated(input) - return if (parsed == current) null else parsed - } - - fun sanitize(words: List, defaults: List): List { - val cleaned = - words.map { it.trim() }.filter { it.isNotEmpty() }.take(maxWords).map { it.take(maxWordLength) } - return cleaned.ifEmpty { defaults } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/chat/ChatController.kt b/apps/android/app/src/main/java/ai/openclaw/android/chat/ChatController.kt deleted file mode 100644 index 3ed69ee5b24..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/chat/ChatController.kt +++ /dev/null @@ -1,524 +0,0 @@ -package ai.openclaw.android.chat - -import ai.openclaw.android.gateway.GatewaySession -import java.util.UUID -import java.util.concurrent.ConcurrentHashMap -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonArray -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.JsonNull -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import kotlinx.serialization.json.buildJsonObject - -class ChatController( - private val scope: CoroutineScope, - private val session: GatewaySession, - private val json: Json, - private val supportsChatSubscribe: Boolean, -) { - private val _sessionKey = MutableStateFlow("main") - val sessionKey: StateFlow = _sessionKey.asStateFlow() - - private val _sessionId = MutableStateFlow(null) - val sessionId: StateFlow = _sessionId.asStateFlow() - - private val _messages = MutableStateFlow>(emptyList()) - val messages: StateFlow> = _messages.asStateFlow() - - private val _errorText = MutableStateFlow(null) - val errorText: StateFlow = _errorText.asStateFlow() - - private val _healthOk = MutableStateFlow(false) - val healthOk: StateFlow = _healthOk.asStateFlow() - - private val _thinkingLevel = MutableStateFlow("off") - val thinkingLevel: StateFlow = _thinkingLevel.asStateFlow() - - private val _pendingRunCount = MutableStateFlow(0) - val pendingRunCount: StateFlow = _pendingRunCount.asStateFlow() - - private val _streamingAssistantText = MutableStateFlow(null) - val streamingAssistantText: StateFlow = _streamingAssistantText.asStateFlow() - - private val pendingToolCallsById = ConcurrentHashMap() - private val _pendingToolCalls = MutableStateFlow>(emptyList()) - val pendingToolCalls: StateFlow> = _pendingToolCalls.asStateFlow() - - private val _sessions = MutableStateFlow>(emptyList()) - val sessions: StateFlow> = _sessions.asStateFlow() - - private val pendingRuns = mutableSetOf() - private val pendingRunTimeoutJobs = ConcurrentHashMap() - private val pendingRunTimeoutMs = 120_000L - - private var lastHealthPollAtMs: Long? = null - - fun onDisconnected(message: String) { - _healthOk.value = false - // Not an error; keep connection status in the UI pill. - _errorText.value = null - clearPendingRuns() - pendingToolCallsById.clear() - publishPendingToolCalls() - _streamingAssistantText.value = null - _sessionId.value = null - } - - fun load(sessionKey: String) { - val key = sessionKey.trim().ifEmpty { "main" } - _sessionKey.value = key - scope.launch { bootstrap(forceHealth = true) } - } - - fun applyMainSessionKey(mainSessionKey: String) { - val trimmed = mainSessionKey.trim() - if (trimmed.isEmpty()) return - if (_sessionKey.value == trimmed) return - if (_sessionKey.value != "main") return - _sessionKey.value = trimmed - scope.launch { bootstrap(forceHealth = true) } - } - - fun refresh() { - scope.launch { bootstrap(forceHealth = true) } - } - - fun refreshSessions(limit: Int? = null) { - scope.launch { fetchSessions(limit = limit) } - } - - fun setThinkingLevel(thinkingLevel: String) { - val normalized = normalizeThinking(thinkingLevel) - if (normalized == _thinkingLevel.value) return - _thinkingLevel.value = normalized - } - - fun switchSession(sessionKey: String) { - val key = sessionKey.trim() - if (key.isEmpty()) return - if (key == _sessionKey.value) return - _sessionKey.value = key - scope.launch { bootstrap(forceHealth = true) } - } - - fun sendMessage( - message: String, - thinkingLevel: String, - attachments: List, - ) { - val trimmed = message.trim() - if (trimmed.isEmpty() && attachments.isEmpty()) return - if (!_healthOk.value) { - _errorText.value = "Gateway health not OK; cannot send" - return - } - - val runId = UUID.randomUUID().toString() - val text = if (trimmed.isEmpty() && attachments.isNotEmpty()) "See attached." else trimmed - val sessionKey = _sessionKey.value - val thinking = normalizeThinking(thinkingLevel) - - // Optimistic user message. - val userContent = - buildList { - add(ChatMessageContent(type = "text", text = text)) - for (att in attachments) { - add( - ChatMessageContent( - type = att.type, - mimeType = att.mimeType, - fileName = att.fileName, - base64 = att.base64, - ), - ) - } - } - _messages.value = - _messages.value + - ChatMessage( - id = UUID.randomUUID().toString(), - role = "user", - content = userContent, - timestampMs = System.currentTimeMillis(), - ) - - armPendingRunTimeout(runId) - synchronized(pendingRuns) { - pendingRuns.add(runId) - _pendingRunCount.value = pendingRuns.size - } - - _errorText.value = null - _streamingAssistantText.value = null - pendingToolCallsById.clear() - publishPendingToolCalls() - - scope.launch { - try { - val params = - buildJsonObject { - put("sessionKey", JsonPrimitive(sessionKey)) - put("message", JsonPrimitive(text)) - put("thinking", JsonPrimitive(thinking)) - put("timeoutMs", JsonPrimitive(30_000)) - put("idempotencyKey", JsonPrimitive(runId)) - if (attachments.isNotEmpty()) { - put( - "attachments", - JsonArray( - attachments.map { att -> - buildJsonObject { - put("type", JsonPrimitive(att.type)) - put("mimeType", JsonPrimitive(att.mimeType)) - put("fileName", JsonPrimitive(att.fileName)) - put("content", JsonPrimitive(att.base64)) - } - }, - ), - ) - } - } - val res = session.request("chat.send", params.toString()) - val actualRunId = parseRunId(res) ?: runId - if (actualRunId != runId) { - clearPendingRun(runId) - armPendingRunTimeout(actualRunId) - synchronized(pendingRuns) { - pendingRuns.add(actualRunId) - _pendingRunCount.value = pendingRuns.size - } - } - } catch (err: Throwable) { - clearPendingRun(runId) - _errorText.value = err.message - } - } - } - - fun abort() { - val runIds = - synchronized(pendingRuns) { - pendingRuns.toList() - } - if (runIds.isEmpty()) return - scope.launch { - for (runId in runIds) { - try { - val params = - buildJsonObject { - put("sessionKey", JsonPrimitive(_sessionKey.value)) - put("runId", JsonPrimitive(runId)) - } - session.request("chat.abort", params.toString()) - } catch (_: Throwable) { - // best-effort - } - } - } - } - - fun handleGatewayEvent(event: String, payloadJson: String?) { - when (event) { - "tick" -> { - scope.launch { pollHealthIfNeeded(force = false) } - } - "health" -> { - // If we receive a health snapshot, the gateway is reachable. - _healthOk.value = true - } - "seqGap" -> { - _errorText.value = "Event stream interrupted; try refreshing." - clearPendingRuns() - } - "chat" -> { - if (payloadJson.isNullOrBlank()) return - handleChatEvent(payloadJson) - } - "agent" -> { - if (payloadJson.isNullOrBlank()) return - handleAgentEvent(payloadJson) - } - } - } - - private suspend fun bootstrap(forceHealth: Boolean) { - _errorText.value = null - _healthOk.value = false - clearPendingRuns() - pendingToolCallsById.clear() - publishPendingToolCalls() - _streamingAssistantText.value = null - _sessionId.value = null - - val key = _sessionKey.value - try { - if (supportsChatSubscribe) { - try { - session.sendNodeEvent("chat.subscribe", """{"sessionKey":"$key"}""") - } catch (_: Throwable) { - // best-effort - } - } - - val historyJson = session.request("chat.history", """{"sessionKey":"$key"}""") - val history = parseHistory(historyJson, sessionKey = key) - _messages.value = history.messages - _sessionId.value = history.sessionId - history.thinkingLevel?.trim()?.takeIf { it.isNotEmpty() }?.let { _thinkingLevel.value = it } - - pollHealthIfNeeded(force = forceHealth) - fetchSessions(limit = 50) - } catch (err: Throwable) { - _errorText.value = err.message - } - } - - private suspend fun fetchSessions(limit: Int?) { - try { - val params = - buildJsonObject { - put("includeGlobal", JsonPrimitive(true)) - put("includeUnknown", JsonPrimitive(false)) - if (limit != null && limit > 0) put("limit", JsonPrimitive(limit)) - } - val res = session.request("sessions.list", params.toString()) - _sessions.value = parseSessions(res) - } catch (_: Throwable) { - // best-effort - } - } - - private suspend fun pollHealthIfNeeded(force: Boolean) { - val now = System.currentTimeMillis() - val last = lastHealthPollAtMs - if (!force && last != null && now - last < 10_000) return - lastHealthPollAtMs = now - try { - session.request("health", null) - _healthOk.value = true - } catch (_: Throwable) { - _healthOk.value = false - } - } - - private fun handleChatEvent(payloadJson: String) { - val payload = json.parseToJsonElement(payloadJson).asObjectOrNull() ?: return - val sessionKey = payload["sessionKey"].asStringOrNull()?.trim() - if (!sessionKey.isNullOrEmpty() && sessionKey != _sessionKey.value) return - - val runId = payload["runId"].asStringOrNull() - if (runId != null) { - val isPending = - synchronized(pendingRuns) { - pendingRuns.contains(runId) - } - if (!isPending) return - } - - val state = payload["state"].asStringOrNull() - when (state) { - "final", "aborted", "error" -> { - if (state == "error") { - _errorText.value = payload["errorMessage"].asStringOrNull() ?: "Chat failed" - } - if (runId != null) clearPendingRun(runId) else clearPendingRuns() - pendingToolCallsById.clear() - publishPendingToolCalls() - _streamingAssistantText.value = null - scope.launch { - try { - val historyJson = - session.request("chat.history", """{"sessionKey":"${_sessionKey.value}"}""") - val history = parseHistory(historyJson, sessionKey = _sessionKey.value) - _messages.value = history.messages - _sessionId.value = history.sessionId - history.thinkingLevel?.trim()?.takeIf { it.isNotEmpty() }?.let { _thinkingLevel.value = it } - } catch (_: Throwable) { - // best-effort - } - } - } - } - } - - private fun handleAgentEvent(payloadJson: String) { - val payload = json.parseToJsonElement(payloadJson).asObjectOrNull() ?: return - val runId = payload["runId"].asStringOrNull() - val sessionId = _sessionId.value - if (sessionId != null && runId != sessionId) return - - val stream = payload["stream"].asStringOrNull() - val data = payload["data"].asObjectOrNull() - - when (stream) { - "assistant" -> { - val text = data?.get("text")?.asStringOrNull() - if (!text.isNullOrEmpty()) { - _streamingAssistantText.value = text - } - } - "tool" -> { - val phase = data?.get("phase")?.asStringOrNull() - val name = data?.get("name")?.asStringOrNull() - val toolCallId = data?.get("toolCallId")?.asStringOrNull() - if (phase.isNullOrEmpty() || name.isNullOrEmpty() || toolCallId.isNullOrEmpty()) return - - val ts = payload["ts"].asLongOrNull() ?: System.currentTimeMillis() - if (phase == "start") { - val args = data?.get("args").asObjectOrNull() - pendingToolCallsById[toolCallId] = - ChatPendingToolCall( - toolCallId = toolCallId, - name = name, - args = args, - startedAtMs = ts, - isError = null, - ) - publishPendingToolCalls() - } else if (phase == "result") { - pendingToolCallsById.remove(toolCallId) - publishPendingToolCalls() - } - } - "error" -> { - _errorText.value = "Event stream interrupted; try refreshing." - clearPendingRuns() - pendingToolCallsById.clear() - publishPendingToolCalls() - _streamingAssistantText.value = null - } - } - } - - private fun publishPendingToolCalls() { - _pendingToolCalls.value = - pendingToolCallsById.values.sortedBy { it.startedAtMs } - } - - private fun armPendingRunTimeout(runId: String) { - pendingRunTimeoutJobs[runId]?.cancel() - pendingRunTimeoutJobs[runId] = - scope.launch { - delay(pendingRunTimeoutMs) - val stillPending = - synchronized(pendingRuns) { - pendingRuns.contains(runId) - } - if (!stillPending) return@launch - clearPendingRun(runId) - _errorText.value = "Timed out waiting for a reply; try again or refresh." - } - } - - private fun clearPendingRun(runId: String) { - pendingRunTimeoutJobs.remove(runId)?.cancel() - synchronized(pendingRuns) { - pendingRuns.remove(runId) - _pendingRunCount.value = pendingRuns.size - } - } - - private fun clearPendingRuns() { - for ((_, job) in pendingRunTimeoutJobs) { - job.cancel() - } - pendingRunTimeoutJobs.clear() - synchronized(pendingRuns) { - pendingRuns.clear() - _pendingRunCount.value = 0 - } - } - - private fun parseHistory(historyJson: String, sessionKey: String): ChatHistory { - val root = json.parseToJsonElement(historyJson).asObjectOrNull() ?: return ChatHistory(sessionKey, null, null, emptyList()) - val sid = root["sessionId"].asStringOrNull() - val thinkingLevel = root["thinkingLevel"].asStringOrNull() - val array = root["messages"].asArrayOrNull() ?: JsonArray(emptyList()) - - val messages = - array.mapNotNull { item -> - val obj = item.asObjectOrNull() ?: return@mapNotNull null - val role = obj["role"].asStringOrNull() ?: return@mapNotNull null - val content = obj["content"].asArrayOrNull()?.mapNotNull(::parseMessageContent) ?: emptyList() - val ts = obj["timestamp"].asLongOrNull() - ChatMessage( - id = UUID.randomUUID().toString(), - role = role, - content = content, - timestampMs = ts, - ) - } - - return ChatHistory(sessionKey = sessionKey, sessionId = sid, thinkingLevel = thinkingLevel, messages = messages) - } - - private fun parseMessageContent(el: JsonElement): ChatMessageContent? { - val obj = el.asObjectOrNull() ?: return null - val type = obj["type"].asStringOrNull() ?: "text" - return if (type == "text") { - ChatMessageContent(type = "text", text = obj["text"].asStringOrNull()) - } else { - ChatMessageContent( - type = type, - mimeType = obj["mimeType"].asStringOrNull(), - fileName = obj["fileName"].asStringOrNull(), - base64 = obj["content"].asStringOrNull(), - ) - } - } - - private fun parseSessions(jsonString: String): List { - val root = json.parseToJsonElement(jsonString).asObjectOrNull() ?: return emptyList() - val sessions = root["sessions"].asArrayOrNull() ?: return emptyList() - return sessions.mapNotNull { item -> - val obj = item.asObjectOrNull() ?: return@mapNotNull null - val key = obj["key"].asStringOrNull()?.trim().orEmpty() - if (key.isEmpty()) return@mapNotNull null - val updatedAt = obj["updatedAt"].asLongOrNull() - val displayName = obj["displayName"].asStringOrNull()?.trim() - ChatSessionEntry(key = key, updatedAtMs = updatedAt, displayName = displayName) - } - } - - private fun parseRunId(resJson: String): String? { - return try { - json.parseToJsonElement(resJson).asObjectOrNull()?.get("runId").asStringOrNull() - } catch (_: Throwable) { - null - } - } - - private fun normalizeThinking(raw: String): String { - return when (raw.trim().lowercase()) { - "low" -> "low" - "medium" -> "medium" - "high" -> "high" - else -> "off" - } - } -} - -private fun JsonElement?.asObjectOrNull(): JsonObject? = this as? JsonObject - -private fun JsonElement?.asArrayOrNull(): JsonArray? = this as? JsonArray - -private fun JsonElement?.asStringOrNull(): String? = - when (this) { - is JsonNull -> null - is JsonPrimitive -> content - else -> null - } - -private fun JsonElement?.asLongOrNull(): Long? = - when (this) { - is JsonPrimitive -> content.toLongOrNull() - else -> null - } diff --git a/apps/android/app/src/main/java/ai/openclaw/android/chat/ChatModels.kt b/apps/android/app/src/main/java/ai/openclaw/android/chat/ChatModels.kt deleted file mode 100644 index dd17a8c1ae5..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/chat/ChatModels.kt +++ /dev/null @@ -1,44 +0,0 @@ -package ai.openclaw.android.chat - -data class ChatMessage( - val id: String, - val role: String, - val content: List, - val timestampMs: Long?, -) - -data class ChatMessageContent( - val type: String = "text", - val text: String? = null, - val mimeType: String? = null, - val fileName: String? = null, - val base64: String? = null, -) - -data class ChatPendingToolCall( - val toolCallId: String, - val name: String, - val args: kotlinx.serialization.json.JsonObject? = null, - val startedAtMs: Long, - val isError: Boolean? = null, -) - -data class ChatSessionEntry( - val key: String, - val updatedAtMs: Long?, - val displayName: String? = null, -) - -data class ChatHistory( - val sessionKey: String, - val sessionId: String?, - val thinkingLevel: String?, - val messages: List, -) - -data class OutgoingAttachment( - val type: String, - val mimeType: String, - val fileName: String, - val base64: String, -) diff --git a/apps/android/app/src/main/java/ai/openclaw/android/gateway/BonjourEscapes.kt b/apps/android/app/src/main/java/ai/openclaw/android/gateway/BonjourEscapes.kt deleted file mode 100644 index 1606df79ec6..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/gateway/BonjourEscapes.kt +++ /dev/null @@ -1,35 +0,0 @@ -package ai.openclaw.android.gateway - -object BonjourEscapes { - fun decode(input: String): String { - if (input.isEmpty()) return input - - val bytes = mutableListOf() - var i = 0 - while (i < input.length) { - if (input[i] == '\\' && i + 3 < input.length) { - val d0 = input[i + 1] - val d1 = input[i + 2] - val d2 = input[i + 3] - if (d0.isDigit() && d1.isDigit() && d2.isDigit()) { - val value = - ((d0.code - '0'.code) * 100) + ((d1.code - '0'.code) * 10) + (d2.code - '0'.code) - if (value in 0..255) { - bytes.add(value.toByte()) - i += 4 - continue - } - } - } - - val codePoint = Character.codePointAt(input, i) - val charBytes = String(Character.toChars(codePoint)).toByteArray(Charsets.UTF_8) - for (b in charBytes) { - bytes.add(b) - } - i += Character.charCount(codePoint) - } - - return String(bytes.toByteArray(), Charsets.UTF_8) - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/gateway/DeviceAuthStore.kt b/apps/android/app/src/main/java/ai/openclaw/android/gateway/DeviceAuthStore.kt deleted file mode 100644 index 810e029fba8..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/gateway/DeviceAuthStore.kt +++ /dev/null @@ -1,26 +0,0 @@ -package ai.openclaw.android.gateway - -import ai.openclaw.android.SecurePrefs - -class DeviceAuthStore(private val prefs: SecurePrefs) { - fun loadToken(deviceId: String, role: String): String? { - val key = tokenKey(deviceId, role) - return prefs.getString(key)?.trim()?.takeIf { it.isNotEmpty() } - } - - fun saveToken(deviceId: String, role: String, token: String) { - val key = tokenKey(deviceId, role) - prefs.putString(key, token.trim()) - } - - fun clearToken(deviceId: String, role: String) { - val key = tokenKey(deviceId, role) - prefs.remove(key) - } - - private fun tokenKey(deviceId: String, role: String): String { - val normalizedDevice = deviceId.trim().lowercase() - val normalizedRole = role.trim().lowercase() - return "gateway.deviceToken.$normalizedDevice.$normalizedRole" - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/gateway/DeviceIdentityStore.kt b/apps/android/app/src/main/java/ai/openclaw/android/gateway/DeviceIdentityStore.kt deleted file mode 100644 index ff651c6c17b..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/gateway/DeviceIdentityStore.kt +++ /dev/null @@ -1,182 +0,0 @@ -package ai.openclaw.android.gateway - -import android.content.Context -import android.util.Base64 -import java.io.File -import java.security.KeyFactory -import java.security.KeyPairGenerator -import java.security.MessageDigest -import java.security.Signature -import java.security.spec.PKCS8EncodedKeySpec -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json - -@Serializable -data class DeviceIdentity( - val deviceId: String, - val publicKeyRawBase64: String, - val privateKeyPkcs8Base64: String, - val createdAtMs: Long, -) - -class DeviceIdentityStore(context: Context) { - private val json = Json { ignoreUnknownKeys = true } - private val identityFile = File(context.filesDir, "openclaw/identity/device.json") - - @Synchronized - fun loadOrCreate(): DeviceIdentity { - val existing = load() - if (existing != null) { - val derived = deriveDeviceId(existing.publicKeyRawBase64) - if (derived != null && derived != existing.deviceId) { - val updated = existing.copy(deviceId = derived) - save(updated) - return updated - } - return existing - } - val fresh = generate() - save(fresh) - return fresh - } - - fun signPayload(payload: String, identity: DeviceIdentity): String? { - return try { - // Use BC lightweight API directly — JCA provider registration is broken by R8 - val privateKeyBytes = Base64.decode(identity.privateKeyPkcs8Base64, Base64.DEFAULT) - val pkInfo = org.bouncycastle.asn1.pkcs.PrivateKeyInfo.getInstance(privateKeyBytes) - val parsed = pkInfo.parsePrivateKey() - val rawPrivate = org.bouncycastle.asn1.DEROctetString.getInstance(parsed).octets - val privateKey = org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters(rawPrivate, 0) - val signer = org.bouncycastle.crypto.signers.Ed25519Signer() - signer.init(true, privateKey) - val payloadBytes = payload.toByteArray(Charsets.UTF_8) - signer.update(payloadBytes, 0, payloadBytes.size) - base64UrlEncode(signer.generateSignature()) - } catch (e: Throwable) { - android.util.Log.e("DeviceAuth", "signPayload FAILED: ${e.javaClass.simpleName}: ${e.message}", e) - null - } - } - - fun verifySelfSignature(payload: String, signatureBase64Url: String, identity: DeviceIdentity): Boolean { - return try { - val rawPublicKey = Base64.decode(identity.publicKeyRawBase64, Base64.DEFAULT) - val pubKey = org.bouncycastle.crypto.params.Ed25519PublicKeyParameters(rawPublicKey, 0) - val sigBytes = base64UrlDecode(signatureBase64Url) - val verifier = org.bouncycastle.crypto.signers.Ed25519Signer() - verifier.init(false, pubKey) - val payloadBytes = payload.toByteArray(Charsets.UTF_8) - verifier.update(payloadBytes, 0, payloadBytes.size) - verifier.verifySignature(sigBytes) - } catch (e: Throwable) { - android.util.Log.e("DeviceAuth", "self-verify exception: ${e.message}", e) - false - } - } - - private fun base64UrlDecode(input: String): ByteArray { - val normalized = input.replace('-', '+').replace('_', '/') - val padded = normalized + "=".repeat((4 - normalized.length % 4) % 4) - return Base64.decode(padded, Base64.DEFAULT) - } - - fun publicKeyBase64Url(identity: DeviceIdentity): String? { - return try { - val raw = Base64.decode(identity.publicKeyRawBase64, Base64.DEFAULT) - base64UrlEncode(raw) - } catch (_: Throwable) { - null - } - } - - private fun load(): DeviceIdentity? { - return readIdentity(identityFile) - } - - private fun readIdentity(file: File): DeviceIdentity? { - return try { - if (!file.exists()) return null - val raw = file.readText(Charsets.UTF_8) - val decoded = json.decodeFromString(DeviceIdentity.serializer(), raw) - if (decoded.deviceId.isBlank() || - decoded.publicKeyRawBase64.isBlank() || - decoded.privateKeyPkcs8Base64.isBlank() - ) { - null - } else { - decoded - } - } catch (_: Throwable) { - null - } - } - - private fun save(identity: DeviceIdentity) { - try { - identityFile.parentFile?.mkdirs() - val encoded = json.encodeToString(DeviceIdentity.serializer(), identity) - identityFile.writeText(encoded, Charsets.UTF_8) - } catch (_: Throwable) { - // best-effort only - } - } - - private fun generate(): DeviceIdentity { - // Use BC lightweight API directly to avoid JCA provider issues with R8 - val kpGen = org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator() - kpGen.init(org.bouncycastle.crypto.params.Ed25519KeyGenerationParameters(java.security.SecureRandom())) - val kp = kpGen.generateKeyPair() - val pubKey = kp.public as org.bouncycastle.crypto.params.Ed25519PublicKeyParameters - val privKey = kp.private as org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters - val rawPublic = pubKey.encoded // 32 bytes - val deviceId = sha256Hex(rawPublic) - // Encode private key as PKCS8 for storage - val privKeyInfo = org.bouncycastle.crypto.util.PrivateKeyInfoFactory.createPrivateKeyInfo(privKey) - val pkcs8Bytes = privKeyInfo.encoded - return DeviceIdentity( - deviceId = deviceId, - publicKeyRawBase64 = Base64.encodeToString(rawPublic, Base64.NO_WRAP), - privateKeyPkcs8Base64 = Base64.encodeToString(pkcs8Bytes, Base64.NO_WRAP), - createdAtMs = System.currentTimeMillis(), - ) - } - - private fun deriveDeviceId(publicKeyRawBase64: String): String? { - return try { - val raw = Base64.decode(publicKeyRawBase64, Base64.DEFAULT) - sha256Hex(raw) - } catch (_: Throwable) { - null - } - } - - private fun stripSpkiPrefix(spki: ByteArray): ByteArray { - if (spki.size == ED25519_SPKI_PREFIX.size + 32 && - spki.copyOfRange(0, ED25519_SPKI_PREFIX.size).contentEquals(ED25519_SPKI_PREFIX) - ) { - return spki.copyOfRange(ED25519_SPKI_PREFIX.size, spki.size) - } - return spki - } - - private fun sha256Hex(data: ByteArray): String { - val digest = MessageDigest.getInstance("SHA-256").digest(data) - val out = StringBuilder(digest.size * 2) - for (byte in digest) { - out.append(String.format("%02x", byte)) - } - return out.toString() - } - - private fun base64UrlEncode(data: ByteArray): String { - return Base64.encodeToString(data, Base64.URL_SAFE or Base64.NO_WRAP or Base64.NO_PADDING) - } - - companion object { - private val ED25519_SPKI_PREFIX = - byteArrayOf( - 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, - ) - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayDiscovery.kt b/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayDiscovery.kt deleted file mode 100644 index 2ad8ec0cb19..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayDiscovery.kt +++ /dev/null @@ -1,521 +0,0 @@ -package ai.openclaw.android.gateway - -import android.content.Context -import android.net.ConnectivityManager -import android.net.DnsResolver -import android.net.NetworkCapabilities -import android.net.nsd.NsdManager -import android.net.nsd.NsdServiceInfo -import android.os.CancellationSignal -import android.util.Log -import java.io.IOException -import java.net.InetSocketAddress -import java.nio.ByteBuffer -import java.nio.charset.CodingErrorAction -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.Executor -import java.util.concurrent.Executors -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch -import kotlinx.coroutines.suspendCancellableCoroutine -import org.xbill.DNS.AAAARecord -import org.xbill.DNS.ARecord -import org.xbill.DNS.DClass -import org.xbill.DNS.ExtendedResolver -import org.xbill.DNS.Message -import org.xbill.DNS.Name -import org.xbill.DNS.PTRRecord -import org.xbill.DNS.Record -import org.xbill.DNS.Rcode -import org.xbill.DNS.Resolver -import org.xbill.DNS.SRVRecord -import org.xbill.DNS.Section -import org.xbill.DNS.SimpleResolver -import org.xbill.DNS.TextParseException -import org.xbill.DNS.TXTRecord -import org.xbill.DNS.Type -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException - -@Suppress("DEPRECATION") -class GatewayDiscovery( - context: Context, - private val scope: CoroutineScope, -) { - private val nsd = context.getSystemService(NsdManager::class.java) - private val connectivity = context.getSystemService(ConnectivityManager::class.java) - private val dns = DnsResolver.getInstance() - private val serviceType = "_openclaw-gw._tcp." - private val wideAreaDomain = System.getenv("OPENCLAW_WIDE_AREA_DOMAIN") - private val logTag = "OpenClaw/GatewayDiscovery" - - private val localById = ConcurrentHashMap() - private val unicastById = ConcurrentHashMap() - private val _gateways = MutableStateFlow>(emptyList()) - val gateways: StateFlow> = _gateways.asStateFlow() - - private val _statusText = MutableStateFlow("Searching…") - val statusText: StateFlow = _statusText.asStateFlow() - - private var unicastJob: Job? = null - private val dnsExecutor: Executor = Executors.newCachedThreadPool() - - @Volatile private var lastWideAreaRcode: Int? = null - @Volatile private var lastWideAreaCount: Int = 0 - - private val discoveryListener = - object : NsdManager.DiscoveryListener { - override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) {} - override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) {} - override fun onDiscoveryStarted(serviceType: String) {} - override fun onDiscoveryStopped(serviceType: String) {} - - override fun onServiceFound(serviceInfo: NsdServiceInfo) { - if (serviceInfo.serviceType != this@GatewayDiscovery.serviceType) return - resolve(serviceInfo) - } - - override fun onServiceLost(serviceInfo: NsdServiceInfo) { - val serviceName = BonjourEscapes.decode(serviceInfo.serviceName) - val id = stableId(serviceName, "local.") - localById.remove(id) - publish() - } - } - - init { - startLocalDiscovery() - if (!wideAreaDomain.isNullOrBlank()) { - startUnicastDiscovery(wideAreaDomain) - } - } - - private fun startLocalDiscovery() { - try { - nsd.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, discoveryListener) - } catch (_: Throwable) { - // ignore (best-effort) - } - } - - private fun stopLocalDiscovery() { - try { - nsd.stopServiceDiscovery(discoveryListener) - } catch (_: Throwable) { - // ignore (best-effort) - } - } - - private fun startUnicastDiscovery(domain: String) { - unicastJob = - scope.launch(Dispatchers.IO) { - while (true) { - try { - refreshUnicast(domain) - } catch (_: Throwable) { - // ignore (best-effort) - } - delay(5000) - } - } - } - - private fun resolve(serviceInfo: NsdServiceInfo) { - nsd.resolveService( - serviceInfo, - object : NsdManager.ResolveListener { - override fun onResolveFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {} - - override fun onServiceResolved(resolved: NsdServiceInfo) { - val host = resolved.host?.hostAddress ?: return - val port = resolved.port - if (port <= 0) return - - val rawServiceName = resolved.serviceName - val serviceName = BonjourEscapes.decode(rawServiceName) - val displayName = BonjourEscapes.decode(txt(resolved, "displayName") ?: serviceName) - val lanHost = txt(resolved, "lanHost") - val tailnetDns = txt(resolved, "tailnetDns") - val gatewayPort = txtInt(resolved, "gatewayPort") - val canvasPort = txtInt(resolved, "canvasPort") - val tlsEnabled = txtBool(resolved, "gatewayTls") - val tlsFingerprint = txt(resolved, "gatewayTlsSha256") - val id = stableId(serviceName, "local.") - localById[id] = - GatewayEndpoint( - stableId = id, - name = displayName, - host = host, - port = port, - lanHost = lanHost, - tailnetDns = tailnetDns, - gatewayPort = gatewayPort, - canvasPort = canvasPort, - tlsEnabled = tlsEnabled, - tlsFingerprintSha256 = tlsFingerprint, - ) - publish() - } - }, - ) - } - - private fun publish() { - _gateways.value = - (localById.values + unicastById.values).sortedBy { it.name.lowercase() } - _statusText.value = buildStatusText() - } - - private fun buildStatusText(): String { - val localCount = localById.size - val wideRcode = lastWideAreaRcode - val wideCount = lastWideAreaCount - - val wide = - when (wideRcode) { - null -> "Wide: ?" - Rcode.NOERROR -> "Wide: $wideCount" - Rcode.NXDOMAIN -> "Wide: NXDOMAIN" - else -> "Wide: ${Rcode.string(wideRcode)}" - } - - return when { - localCount == 0 && wideRcode == null -> "Searching for gateways…" - localCount == 0 -> "$wide" - else -> "Local: $localCount • $wide" - } - } - - private fun stableId(serviceName: String, domain: String): String { - return "${serviceType}|${domain}|${normalizeName(serviceName)}" - } - - private fun normalizeName(raw: String): String { - return raw.trim().split(Regex("\\s+")).joinToString(" ") - } - - private fun txt(info: NsdServiceInfo, key: String): String? { - val bytes = info.attributes[key] ?: return null - return try { - String(bytes, Charsets.UTF_8).trim().ifEmpty { null } - } catch (_: Throwable) { - null - } - } - - private fun txtInt(info: NsdServiceInfo, key: String): Int? { - return txt(info, key)?.toIntOrNull() - } - - private fun txtBool(info: NsdServiceInfo, key: String): Boolean { - val raw = txt(info, key)?.trim()?.lowercase() ?: return false - return raw == "1" || raw == "true" || raw == "yes" - } - - private suspend fun refreshUnicast(domain: String) { - val ptrName = "${serviceType}${domain}" - val ptrMsg = lookupUnicastMessage(ptrName, Type.PTR) ?: return - val ptrRecords = records(ptrMsg, Section.ANSWER).mapNotNull { it as? PTRRecord } - - val next = LinkedHashMap() - for (ptr in ptrRecords) { - val instanceFqdn = ptr.target.toString() - val srv = - recordByName(ptrMsg, instanceFqdn, Type.SRV) as? SRVRecord - ?: run { - val msg = lookupUnicastMessage(instanceFqdn, Type.SRV) ?: return@run null - recordByName(msg, instanceFqdn, Type.SRV) as? SRVRecord - } - ?: continue - val port = srv.port - if (port <= 0) continue - - val targetFqdn = srv.target.toString() - val host = - resolveHostFromMessage(ptrMsg, targetFqdn) - ?: resolveHostFromMessage(lookupUnicastMessage(instanceFqdn, Type.SRV), targetFqdn) - ?: resolveHostUnicast(targetFqdn) - ?: continue - - val txtFromPtr = - recordsByName(ptrMsg, Section.ADDITIONAL)[keyName(instanceFqdn)] - .orEmpty() - .mapNotNull { it as? TXTRecord } - val txt = - if (txtFromPtr.isNotEmpty()) { - txtFromPtr - } else { - val msg = lookupUnicastMessage(instanceFqdn, Type.TXT) - records(msg, Section.ANSWER).mapNotNull { it as? TXTRecord } - } - val instanceName = BonjourEscapes.decode(decodeInstanceName(instanceFqdn, domain)) - val displayName = BonjourEscapes.decode(txtValue(txt, "displayName") ?: instanceName) - val lanHost = txtValue(txt, "lanHost") - val tailnetDns = txtValue(txt, "tailnetDns") - val gatewayPort = txtIntValue(txt, "gatewayPort") - val canvasPort = txtIntValue(txt, "canvasPort") - val tlsEnabled = txtBoolValue(txt, "gatewayTls") - val tlsFingerprint = txtValue(txt, "gatewayTlsSha256") - val id = stableId(instanceName, domain) - next[id] = - GatewayEndpoint( - stableId = id, - name = displayName, - host = host, - port = port, - lanHost = lanHost, - tailnetDns = tailnetDns, - gatewayPort = gatewayPort, - canvasPort = canvasPort, - tlsEnabled = tlsEnabled, - tlsFingerprintSha256 = tlsFingerprint, - ) - } - - unicastById.clear() - unicastById.putAll(next) - lastWideAreaRcode = ptrMsg.header.rcode - lastWideAreaCount = next.size - publish() - - if (next.isEmpty()) { - Log.d( - logTag, - "wide-area discovery: 0 results for $ptrName (rcode=${Rcode.string(ptrMsg.header.rcode)})", - ) - } - } - - private fun decodeInstanceName(instanceFqdn: String, domain: String): String { - val suffix = "${serviceType}${domain}" - val withoutSuffix = - if (instanceFqdn.endsWith(suffix)) { - instanceFqdn.removeSuffix(suffix) - } else { - instanceFqdn.substringBefore(serviceType) - } - return normalizeName(stripTrailingDot(withoutSuffix)) - } - - private fun stripTrailingDot(raw: String): String { - return raw.removeSuffix(".") - } - - private suspend fun lookupUnicastMessage(name: String, type: Int): Message? { - val query = - try { - Message.newQuery( - org.xbill.DNS.Record.newRecord( - Name.fromString(name), - type, - DClass.IN, - ), - ) - } catch (_: TextParseException) { - return null - } - - val system = queryViaSystemDns(query) - if (records(system, Section.ANSWER).any { it.type == type }) return system - - val direct = createDirectResolver() ?: return system - return try { - val msg = direct.send(query) - if (records(msg, Section.ANSWER).any { it.type == type }) msg else system - } catch (_: Throwable) { - system - } - } - - private suspend fun queryViaSystemDns(query: Message): Message? { - val network = preferredDnsNetwork() - val bytes = - try { - rawQuery(network, query.toWire()) - } catch (_: Throwable) { - return null - } - - return try { - Message(bytes) - } catch (_: IOException) { - null - } - } - - private fun records(msg: Message?, section: Int): List { - return msg?.getSectionArray(section)?.toList() ?: emptyList() - } - - private fun keyName(raw: String): String { - return raw.trim().lowercase() - } - - private fun recordsByName(msg: Message, section: Int): Map> { - val next = LinkedHashMap>() - for (r in records(msg, section)) { - val name = r.name?.toString() ?: continue - next.getOrPut(keyName(name)) { mutableListOf() }.add(r) - } - return next - } - - private fun recordByName(msg: Message, fqdn: String, type: Int): Record? { - val key = keyName(fqdn) - val byNameAnswer = recordsByName(msg, Section.ANSWER) - val fromAnswer = byNameAnswer[key].orEmpty().firstOrNull { it.type == type } - if (fromAnswer != null) return fromAnswer - - val byNameAdditional = recordsByName(msg, Section.ADDITIONAL) - return byNameAdditional[key].orEmpty().firstOrNull { it.type == type } - } - - private fun resolveHostFromMessage(msg: Message?, hostname: String): String? { - val m = msg ?: return null - val key = keyName(hostname) - val additional = recordsByName(m, Section.ADDITIONAL)[key].orEmpty() - val a = additional.mapNotNull { it as? ARecord }.mapNotNull { it.address?.hostAddress } - val aaaa = additional.mapNotNull { it as? AAAARecord }.mapNotNull { it.address?.hostAddress } - return a.firstOrNull() ?: aaaa.firstOrNull() - } - - private fun preferredDnsNetwork(): android.net.Network? { - val cm = connectivity ?: return null - - // Prefer VPN (Tailscale) when present; otherwise use the active network. - cm.allNetworks.firstOrNull { n -> - val caps = cm.getNetworkCapabilities(n) ?: return@firstOrNull false - caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN) - }?.let { return it } - - return cm.activeNetwork - } - - private fun createDirectResolver(): Resolver? { - val cm = connectivity ?: return null - - val candidateNetworks = - buildList { - cm.allNetworks - .firstOrNull { n -> - val caps = cm.getNetworkCapabilities(n) ?: return@firstOrNull false - caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN) - }?.let(::add) - cm.activeNetwork?.let(::add) - }.distinct() - - val servers = - candidateNetworks - .asSequence() - .flatMap { n -> - cm.getLinkProperties(n)?.dnsServers?.asSequence() ?: emptySequence() - } - .distinctBy { it.hostAddress ?: it.toString() } - .toList() - if (servers.isEmpty()) return null - - return try { - val resolvers = - servers.mapNotNull { addr -> - try { - SimpleResolver().apply { - setAddress(InetSocketAddress(addr, 53)) - setTimeout(3) - } - } catch (_: Throwable) { - null - } - } - if (resolvers.isEmpty()) return null - ExtendedResolver(resolvers.toTypedArray()).apply { setTimeout(3) } - } catch (_: Throwable) { - null - } - } - - private suspend fun rawQuery(network: android.net.Network?, wireQuery: ByteArray): ByteArray = - suspendCancellableCoroutine { cont -> - val signal = CancellationSignal() - cont.invokeOnCancellation { signal.cancel() } - - dns.rawQuery( - network, - wireQuery, - DnsResolver.FLAG_EMPTY, - dnsExecutor, - signal, - object : DnsResolver.Callback { - override fun onAnswer(answer: ByteArray, rcode: Int) { - cont.resume(answer) - } - - override fun onError(error: DnsResolver.DnsException) { - cont.resumeWithException(error) - } - }, - ) - } - - private fun txtValue(records: List, key: String): String? { - val prefix = "$key=" - for (r in records) { - val strings: List = - try { - r.strings.mapNotNull { it as? String } - } catch (_: Throwable) { - emptyList() - } - for (s in strings) { - val trimmed = decodeDnsTxtString(s).trim() - if (trimmed.startsWith(prefix)) { - return trimmed.removePrefix(prefix).trim().ifEmpty { null } - } - } - } - return null - } - - private fun txtIntValue(records: List, key: String): Int? { - return txtValue(records, key)?.toIntOrNull() - } - - private fun txtBoolValue(records: List, key: String): Boolean { - val raw = txtValue(records, key)?.trim()?.lowercase() ?: return false - return raw == "1" || raw == "true" || raw == "yes" - } - - private fun decodeDnsTxtString(raw: String): String { - // dnsjava treats TXT as opaque bytes and decodes as ISO-8859-1 to preserve bytes. - // Our TXT payload is UTF-8 (written by the gateway), so re-decode when possible. - val bytes = raw.toByteArray(Charsets.ISO_8859_1) - val decoder = - Charsets.UTF_8 - .newDecoder() - .onMalformedInput(CodingErrorAction.REPORT) - .onUnmappableCharacter(CodingErrorAction.REPORT) - return try { - decoder.decode(ByteBuffer.wrap(bytes)).toString() - } catch (_: Throwable) { - raw - } - } - - private suspend fun resolveHostUnicast(hostname: String): String? { - val a = - records(lookupUnicastMessage(hostname, Type.A), Section.ANSWER) - .mapNotNull { it as? ARecord } - .mapNotNull { it.address?.hostAddress } - val aaaa = - records(lookupUnicastMessage(hostname, Type.AAAA), Section.ANSWER) - .mapNotNull { it as? AAAARecord } - .mapNotNull { it.address?.hostAddress } - - return a.firstOrNull() ?: aaaa.firstOrNull() - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayEndpoint.kt b/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayEndpoint.kt deleted file mode 100644 index 9a301060282..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayEndpoint.kt +++ /dev/null @@ -1,26 +0,0 @@ -package ai.openclaw.android.gateway - -data class GatewayEndpoint( - val stableId: String, - val name: String, - val host: String, - val port: Int, - val lanHost: String? = null, - val tailnetDns: String? = null, - val gatewayPort: Int? = null, - val canvasPort: Int? = null, - val tlsEnabled: Boolean = false, - val tlsFingerprintSha256: String? = null, -) { - companion object { - fun manual(host: String, port: Int): GatewayEndpoint = - GatewayEndpoint( - stableId = "manual|${host.lowercase()}|$port", - name = "$host:$port", - host = host, - port = port, - tlsEnabled = false, - tlsFingerprintSha256 = null, - ) - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayProtocol.kt b/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayProtocol.kt deleted file mode 100644 index da8fa4c6933..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayProtocol.kt +++ /dev/null @@ -1,3 +0,0 @@ -package ai.openclaw.android.gateway - -const val GATEWAY_PROTOCOL_VERSION = 3 diff --git a/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewaySession.kt b/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewaySession.kt deleted file mode 100644 index 091e735530d..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewaySession.kt +++ /dev/null @@ -1,704 +0,0 @@ -package ai.openclaw.android.gateway - -import android.util.Log -import java.util.Locale -import java.util.UUID -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.atomic.AtomicBoolean -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.TimeoutCancellationException -import kotlinx.coroutines.cancelAndJoin -import kotlinx.coroutines.delay -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import kotlinx.coroutines.withContext -import kotlinx.coroutines.withTimeout -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonArray -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.JsonNull -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import kotlinx.serialization.json.buildJsonObject -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import okhttp3.WebSocket -import okhttp3.WebSocketListener - -data class GatewayClientInfo( - val id: String, - val displayName: String?, - val version: String, - val platform: String, - val mode: String, - val instanceId: String?, - val deviceFamily: String?, - val modelIdentifier: String?, -) - -data class GatewayConnectOptions( - val role: String, - val scopes: List, - val caps: List, - val commands: List, - val permissions: Map, - val client: GatewayClientInfo, - val userAgent: String? = null, -) - -class GatewaySession( - private val scope: CoroutineScope, - private val identityStore: DeviceIdentityStore, - private val deviceAuthStore: DeviceAuthStore, - private val onConnected: (serverName: String?, remoteAddress: String?, mainSessionKey: String?) -> Unit, - private val onDisconnected: (message: String) -> Unit, - private val onEvent: (event: String, payloadJson: String?) -> Unit, - private val onInvoke: (suspend (InvokeRequest) -> InvokeResult)? = null, - private val onTlsFingerprint: ((stableId: String, fingerprint: String) -> Unit)? = null, -) { - data class InvokeRequest( - val id: String, - val nodeId: String, - val command: String, - val paramsJson: String?, - val timeoutMs: Long?, - ) - - data class InvokeResult(val ok: Boolean, val payloadJson: String?, val error: ErrorShape?) { - companion object { - fun ok(payloadJson: String?) = InvokeResult(ok = true, payloadJson = payloadJson, error = null) - fun error(code: String, message: String) = - InvokeResult(ok = false, payloadJson = null, error = ErrorShape(code = code, message = message)) - } - } - - data class ErrorShape(val code: String, val message: String) - - private val json = Json { ignoreUnknownKeys = true } - private val writeLock = Mutex() - private val pending = ConcurrentHashMap>() - - @Volatile private var canvasHostUrl: String? = null - @Volatile private var mainSessionKey: String? = null - - private data class DesiredConnection( - val endpoint: GatewayEndpoint, - val token: String?, - val password: String?, - val options: GatewayConnectOptions, - val tls: GatewayTlsParams?, - ) - - private var desired: DesiredConnection? = null - private var job: Job? = null - @Volatile private var currentConnection: Connection? = null - - fun connect( - endpoint: GatewayEndpoint, - token: String?, - password: String?, - options: GatewayConnectOptions, - tls: GatewayTlsParams? = null, - ) { - desired = DesiredConnection(endpoint, token, password, options, tls) - if (job == null) { - job = scope.launch(Dispatchers.IO) { runLoop() } - } - } - - fun disconnect() { - desired = null - currentConnection?.closeQuietly() - scope.launch(Dispatchers.IO) { - job?.cancelAndJoin() - job = null - canvasHostUrl = null - mainSessionKey = null - onDisconnected("Offline") - } - } - - fun reconnect() { - currentConnection?.closeQuietly() - } - - fun currentCanvasHostUrl(): String? = canvasHostUrl - fun currentMainSessionKey(): String? = mainSessionKey - - suspend fun sendNodeEvent(event: String, payloadJson: String?) { - val conn = currentConnection ?: return - val parsedPayload = payloadJson?.let { parseJsonOrNull(it) } - val params = - buildJsonObject { - put("event", JsonPrimitive(event)) - if (parsedPayload != null) { - put("payload", parsedPayload) - } else if (payloadJson != null) { - put("payloadJSON", JsonPrimitive(payloadJson)) - } else { - put("payloadJSON", JsonNull) - } - } - try { - conn.request("node.event", params, timeoutMs = 8_000) - } catch (err: Throwable) { - Log.w("OpenClawGateway", "node.event failed: ${err.message ?: err::class.java.simpleName}") - } - } - - suspend fun request(method: String, paramsJson: String?, timeoutMs: Long = 15_000): String { - val conn = currentConnection ?: throw IllegalStateException("not connected") - val params = - if (paramsJson.isNullOrBlank()) { - null - } else { - json.parseToJsonElement(paramsJson) - } - val res = conn.request(method, params, timeoutMs) - if (res.ok) return res.payloadJson ?: "" - val err = res.error - throw IllegalStateException("${err?.code ?: "UNAVAILABLE"}: ${err?.message ?: "request failed"}") - } - - private data class RpcResponse(val id: String, val ok: Boolean, val payloadJson: String?, val error: ErrorShape?) - - private inner class Connection( - private val endpoint: GatewayEndpoint, - private val token: String?, - private val password: String?, - private val options: GatewayConnectOptions, - private val tls: GatewayTlsParams?, - ) { - private val connectDeferred = CompletableDeferred() - private val closedDeferred = CompletableDeferred() - private val isClosed = AtomicBoolean(false) - private val connectNonceDeferred = CompletableDeferred() - private val client: OkHttpClient = buildClient() - private var socket: WebSocket? = null - private val loggerTag = "OpenClawGateway" - - val remoteAddress: String = - if (endpoint.host.contains(":")) { - "[${endpoint.host}]:${endpoint.port}" - } else { - "${endpoint.host}:${endpoint.port}" - } - - suspend fun connect() { - val scheme = if (tls != null) "wss" else "ws" - val url = "$scheme://${endpoint.host}:${endpoint.port}" - val httpScheme = if (tls != null) "https" else "http" - val origin = "$httpScheme://${endpoint.host}:${endpoint.port}" - val request = Request.Builder().url(url).header("Origin", origin).build() - socket = client.newWebSocket(request, Listener()) - try { - connectDeferred.await() - } catch (err: Throwable) { - throw err - } - } - - suspend fun request(method: String, params: JsonElement?, timeoutMs: Long): RpcResponse { - val id = UUID.randomUUID().toString() - val deferred = CompletableDeferred() - pending[id] = deferred - val frame = - buildJsonObject { - put("type", JsonPrimitive("req")) - put("id", JsonPrimitive(id)) - put("method", JsonPrimitive(method)) - if (params != null) put("params", params) - } - sendJson(frame) - return try { - withTimeout(timeoutMs) { deferred.await() } - } catch (err: TimeoutCancellationException) { - pending.remove(id) - throw IllegalStateException("request timeout") - } - } - - suspend fun sendJson(obj: JsonObject) { - val jsonString = obj.toString() - writeLock.withLock { - socket?.send(jsonString) - } - } - - suspend fun awaitClose() = closedDeferred.await() - - fun closeQuietly() { - if (isClosed.compareAndSet(false, true)) { - socket?.close(1000, "bye") - socket = null - closedDeferred.complete(Unit) - } - } - - private fun buildClient(): OkHttpClient { - val builder = OkHttpClient.Builder() - .writeTimeout(60, java.util.concurrent.TimeUnit.SECONDS) - .readTimeout(0, java.util.concurrent.TimeUnit.SECONDS) - .pingInterval(30, java.util.concurrent.TimeUnit.SECONDS) - val tlsConfig = buildGatewayTlsConfig(tls) { fingerprint -> - onTlsFingerprint?.invoke(tls?.stableId ?: endpoint.stableId, fingerprint) - } - if (tlsConfig != null) { - builder.sslSocketFactory(tlsConfig.sslSocketFactory, tlsConfig.trustManager) - builder.hostnameVerifier(tlsConfig.hostnameVerifier) - } - return builder.build() - } - - private inner class Listener : WebSocketListener() { - override fun onOpen(webSocket: WebSocket, response: Response) { - scope.launch { - try { - val nonce = awaitConnectNonce() - sendConnect(nonce) - } catch (err: Throwable) { - connectDeferred.completeExceptionally(err) - closeQuietly() - } - } - } - - override fun onMessage(webSocket: WebSocket, text: String) { - scope.launch { handleMessage(text) } - } - - override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { - if (!connectDeferred.isCompleted) { - connectDeferred.completeExceptionally(t) - } - if (isClosed.compareAndSet(false, true)) { - failPending() - closedDeferred.complete(Unit) - onDisconnected("Gateway error: ${t.message ?: t::class.java.simpleName}") - } - } - - override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { - if (!connectDeferred.isCompleted) { - connectDeferred.completeExceptionally(IllegalStateException("Gateway closed: $reason")) - } - if (isClosed.compareAndSet(false, true)) { - failPending() - closedDeferred.complete(Unit) - onDisconnected("Gateway closed: $reason") - } - } - } - - private suspend fun sendConnect(connectNonce: String?) { - val identity = identityStore.loadOrCreate() - val storedToken = deviceAuthStore.loadToken(identity.deviceId, options.role) - val trimmedToken = token?.trim().orEmpty() - val authToken = if (storedToken.isNullOrBlank()) trimmedToken else storedToken - val canFallbackToShared = !storedToken.isNullOrBlank() && trimmedToken.isNotBlank() - val payload = buildConnectParams(identity, connectNonce, authToken, password?.trim()) - val res = request("connect", payload, timeoutMs = 8_000) - if (!res.ok) { - val msg = res.error?.message ?: "connect failed" - if (canFallbackToShared) { - deviceAuthStore.clearToken(identity.deviceId, options.role) - } - throw IllegalStateException(msg) - } - val payloadJson = res.payloadJson ?: throw IllegalStateException("connect failed: missing payload") - val obj = json.parseToJsonElement(payloadJson).asObjectOrNull() ?: throw IllegalStateException("connect failed") - val serverName = obj["server"].asObjectOrNull()?.get("host").asStringOrNull() - val authObj = obj["auth"].asObjectOrNull() - val deviceToken = authObj?.get("deviceToken").asStringOrNull() - val authRole = authObj?.get("role").asStringOrNull() ?: options.role - if (!deviceToken.isNullOrBlank()) { - deviceAuthStore.saveToken(identity.deviceId, authRole, deviceToken) - } - val rawCanvas = obj["canvasHostUrl"].asStringOrNull() - canvasHostUrl = normalizeCanvasHostUrl(rawCanvas, endpoint) - val sessionDefaults = - obj["snapshot"].asObjectOrNull() - ?.get("sessionDefaults").asObjectOrNull() - mainSessionKey = sessionDefaults?.get("mainSessionKey").asStringOrNull() - onConnected(serverName, remoteAddress, mainSessionKey) - connectDeferred.complete(Unit) - } - - private fun buildConnectParams( - identity: DeviceIdentity, - connectNonce: String?, - authToken: String, - authPassword: String?, - ): JsonObject { - val client = options.client - val locale = Locale.getDefault().toLanguageTag() - val clientObj = - buildJsonObject { - put("id", JsonPrimitive(client.id)) - client.displayName?.let { put("displayName", JsonPrimitive(it)) } - put("version", JsonPrimitive(client.version)) - put("platform", JsonPrimitive(client.platform)) - put("mode", JsonPrimitive(client.mode)) - client.instanceId?.let { put("instanceId", JsonPrimitive(it)) } - client.deviceFamily?.let { put("deviceFamily", JsonPrimitive(it)) } - client.modelIdentifier?.let { put("modelIdentifier", JsonPrimitive(it)) } - } - - val password = authPassword?.trim().orEmpty() - val authJson = - when { - authToken.isNotEmpty() -> - buildJsonObject { - put("token", JsonPrimitive(authToken)) - } - password.isNotEmpty() -> - buildJsonObject { - put("password", JsonPrimitive(password)) - } - else -> null - } - - val signedAtMs = System.currentTimeMillis() - val payload = - buildDeviceAuthPayload( - deviceId = identity.deviceId, - clientId = client.id, - clientMode = client.mode, - role = options.role, - scopes = options.scopes, - signedAtMs = signedAtMs, - token = if (authToken.isNotEmpty()) authToken else null, - nonce = connectNonce, - ) - val signature = identityStore.signPayload(payload, identity) - val publicKey = identityStore.publicKeyBase64Url(identity) - val deviceJson = - if (!signature.isNullOrBlank() && !publicKey.isNullOrBlank()) { - buildJsonObject { - put("id", JsonPrimitive(identity.deviceId)) - put("publicKey", JsonPrimitive(publicKey)) - put("signature", JsonPrimitive(signature)) - put("signedAt", JsonPrimitive(signedAtMs)) - if (!connectNonce.isNullOrBlank()) { - put("nonce", JsonPrimitive(connectNonce)) - } - } - } else { - null - } - - return buildJsonObject { - put("minProtocol", JsonPrimitive(GATEWAY_PROTOCOL_VERSION)) - put("maxProtocol", JsonPrimitive(GATEWAY_PROTOCOL_VERSION)) - put("client", clientObj) - if (options.caps.isNotEmpty()) put("caps", JsonArray(options.caps.map(::JsonPrimitive))) - if (options.commands.isNotEmpty()) put("commands", JsonArray(options.commands.map(::JsonPrimitive))) - if (options.permissions.isNotEmpty()) { - put( - "permissions", - buildJsonObject { - options.permissions.forEach { (key, value) -> - put(key, JsonPrimitive(value)) - } - }, - ) - } - put("role", JsonPrimitive(options.role)) - if (options.scopes.isNotEmpty()) put("scopes", JsonArray(options.scopes.map(::JsonPrimitive))) - authJson?.let { put("auth", it) } - deviceJson?.let { put("device", it) } - put("locale", JsonPrimitive(locale)) - options.userAgent?.trim()?.takeIf { it.isNotEmpty() }?.let { - put("userAgent", JsonPrimitive(it)) - } - } - } - - private suspend fun handleMessage(text: String) { - val frame = json.parseToJsonElement(text).asObjectOrNull() ?: return - when (frame["type"].asStringOrNull()) { - "res" -> handleResponse(frame) - "event" -> handleEvent(frame) - } - } - - private fun handleResponse(frame: JsonObject) { - val id = frame["id"].asStringOrNull() ?: return - val ok = frame["ok"].asBooleanOrNull() ?: false - val payloadJson = frame["payload"]?.let { payload -> payload.toString() } - val error = - frame["error"]?.asObjectOrNull()?.let { obj -> - val code = obj["code"].asStringOrNull() ?: "UNAVAILABLE" - val msg = obj["message"].asStringOrNull() ?: "request failed" - ErrorShape(code, msg) - } - pending.remove(id)?.complete(RpcResponse(id, ok, payloadJson, error)) - } - - private fun handleEvent(frame: JsonObject) { - val event = frame["event"].asStringOrNull() ?: return - val payloadJson = - frame["payload"]?.let { it.toString() } ?: frame["payloadJSON"].asStringOrNull() - if (event == "connect.challenge") { - val nonce = extractConnectNonce(payloadJson) - if (!connectNonceDeferred.isCompleted) { - connectNonceDeferred.complete(nonce) - } - return - } - if (event == "node.invoke.request" && payloadJson != null && onInvoke != null) { - handleInvokeEvent(payloadJson) - return - } - onEvent(event, payloadJson) - } - - private suspend fun awaitConnectNonce(): String? { - if (isLoopbackHost(endpoint.host)) return null - return try { - withTimeout(2_000) { connectNonceDeferred.await() } - } catch (_: Throwable) { - null - } - } - - private fun extractConnectNonce(payloadJson: String?): String? { - if (payloadJson.isNullOrBlank()) return null - val obj = parseJsonOrNull(payloadJson)?.asObjectOrNull() ?: return null - return obj["nonce"].asStringOrNull() - } - - private fun handleInvokeEvent(payloadJson: String) { - val payload = - try { - json.parseToJsonElement(payloadJson).asObjectOrNull() - } catch (_: Throwable) { - null - } ?: return - val id = payload["id"].asStringOrNull() ?: return - val nodeId = payload["nodeId"].asStringOrNull() ?: return - val command = payload["command"].asStringOrNull() ?: return - val params = - payload["paramsJSON"].asStringOrNull() - ?: payload["params"]?.let { value -> if (value is JsonNull) null else value.toString() } - val timeoutMs = payload["timeoutMs"].asLongOrNull() - scope.launch { - val result = - try { - onInvoke?.invoke(InvokeRequest(id, nodeId, command, params, timeoutMs)) - ?: InvokeResult.error("UNAVAILABLE", "invoke handler missing") - } catch (err: Throwable) { - invokeErrorFromThrowable(err) - } - sendInvokeResult(id, nodeId, result) - } - } - - private suspend fun sendInvokeResult(id: String, nodeId: String, result: InvokeResult) { - val parsedPayload = result.payloadJson?.let { parseJsonOrNull(it) } - val params = - buildJsonObject { - put("id", JsonPrimitive(id)) - put("nodeId", JsonPrimitive(nodeId)) - put("ok", JsonPrimitive(result.ok)) - if (parsedPayload != null) { - put("payload", parsedPayload) - } else if (result.payloadJson != null) { - put("payloadJSON", JsonPrimitive(result.payloadJson)) - } - result.error?.let { err -> - put( - "error", - buildJsonObject { - put("code", JsonPrimitive(err.code)) - put("message", JsonPrimitive(err.message)) - }, - ) - } - } - try { - request("node.invoke.result", params, timeoutMs = 15_000) - } catch (err: Throwable) { - Log.w(loggerTag, "node.invoke.result failed: ${err.message ?: err::class.java.simpleName}") - } - } - - private fun invokeErrorFromThrowable(err: Throwable): InvokeResult { - val msg = err.message?.trim().takeIf { !it.isNullOrEmpty() } ?: err::class.java.simpleName - val parts = msg.split(":", limit = 2) - if (parts.size == 2) { - val code = parts[0].trim() - val rest = parts[1].trim() - if (code.isNotEmpty() && code.all { it.isUpperCase() || it == '_' }) { - return InvokeResult.error(code = code, message = rest.ifEmpty { msg }) - } - } - return InvokeResult.error(code = "UNAVAILABLE", message = msg) - } - - private fun failPending() { - for ((_, waiter) in pending) { - waiter.cancel() - } - pending.clear() - } - } - - private suspend fun runLoop() { - var attempt = 0 - while (scope.isActive) { - val target = desired - if (target == null) { - currentConnection?.closeQuietly() - currentConnection = null - delay(250) - continue - } - - try { - onDisconnected(if (attempt == 0) "Connecting…" else "Reconnecting…") - connectOnce(target) - attempt = 0 - } catch (err: Throwable) { - attempt += 1 - onDisconnected("Gateway error: ${err.message ?: err::class.java.simpleName}") - val sleepMs = minOf(8_000L, (350.0 * Math.pow(1.7, attempt.toDouble())).toLong()) - delay(sleepMs) - } - } - } - - private suspend fun connectOnce(target: DesiredConnection) = withContext(Dispatchers.IO) { - val conn = Connection(target.endpoint, target.token, target.password, target.options, target.tls) - currentConnection = conn - try { - conn.connect() - conn.awaitClose() - } finally { - currentConnection = null - canvasHostUrl = null - mainSessionKey = null - } - } - - private fun buildDeviceAuthPayload( - deviceId: String, - clientId: String, - clientMode: String, - role: String, - scopes: List, - signedAtMs: Long, - token: String?, - nonce: String?, - ): String { - val scopeString = scopes.joinToString(",") - val authToken = token.orEmpty() - val version = if (nonce.isNullOrBlank()) "v1" else "v2" - val parts = - mutableListOf( - version, - deviceId, - clientId, - clientMode, - role, - scopeString, - signedAtMs.toString(), - authToken, - ) - if (!nonce.isNullOrBlank()) { - parts.add(nonce) - } - return parts.joinToString("|") - } - - private fun normalizeCanvasHostUrl(raw: String?, endpoint: GatewayEndpoint): String? { - val trimmed = raw?.trim().orEmpty() - val parsed = trimmed.takeIf { it.isNotBlank() }?.let { runCatching { java.net.URI(it) }.getOrNull() } - val host = parsed?.host?.trim().orEmpty() - val port = parsed?.port ?: -1 - val scheme = parsed?.scheme?.trim().orEmpty().ifBlank { "http" } - - // Detect TLS reverse proxy: endpoint on port 443, or domain-based host - val tls = endpoint.port == 443 || endpoint.host.contains(".") - - // If raw URL is a non-loopback address AND we're behind TLS reverse proxy, - // fix the port (gateway sends its internal port like 18789, but we need 443 via Caddy) - if (trimmed.isNotBlank() && !isLoopbackHost(host)) { - if (tls && port > 0 && port != 443) { - // Rewrite the URL to use the reverse proxy port instead of the raw gateway port - val fixedScheme = "https" - val formattedHost = if (host.contains(":")) "[${host}]" else host - return "$fixedScheme://$formattedHost" - } - return trimmed - } - - val fallbackHost = - endpoint.tailnetDns?.trim().takeIf { !it.isNullOrEmpty() } - ?: endpoint.lanHost?.trim().takeIf { !it.isNullOrEmpty() } - ?: endpoint.host.trim() - if (fallbackHost.isEmpty()) return trimmed.ifBlank { null } - - // When connecting through a reverse proxy (TLS on standard port), use the - // connection endpoint's scheme and port instead of the raw canvas port. - val fallbackScheme = if (tls) "https" else scheme - // Behind reverse proxy, always use the proxy port (443), not the raw canvas port - val fallbackPort = if (tls) endpoint.port else (endpoint.canvasPort ?: endpoint.port) - val formattedHost = if (fallbackHost.contains(":")) "[${fallbackHost}]" else fallbackHost - val portSuffix = if ((fallbackScheme == "https" && fallbackPort == 443) || (fallbackScheme == "http" && fallbackPort == 80)) "" else ":$fallbackPort" - return "$fallbackScheme://$formattedHost$portSuffix" - } - - private fun isLoopbackHost(raw: String?): Boolean { - val host = raw?.trim()?.lowercase().orEmpty() - if (host.isEmpty()) return false - if (host == "localhost") return true - if (host == "::1") return true - if (host == "0.0.0.0" || host == "::") return true - return host.startsWith("127.") - } -} - -private fun JsonElement?.asObjectOrNull(): JsonObject? = this as? JsonObject - -private fun JsonElement?.asStringOrNull(): String? = - when (this) { - is JsonNull -> null - is JsonPrimitive -> content - else -> null - } - -private fun JsonElement?.asBooleanOrNull(): Boolean? = - when (this) { - is JsonPrimitive -> { - val c = content.trim() - when { - c.equals("true", ignoreCase = true) -> true - c.equals("false", ignoreCase = true) -> false - else -> null - } - } - else -> null - } - -private fun JsonElement?.asLongOrNull(): Long? = - when (this) { - is JsonPrimitive -> content.toLongOrNull() - else -> null - } - -private fun parseJsonOrNull(payload: String): JsonElement? { - val trimmed = payload.trim() - if (trimmed.isEmpty()) return null - return try { - Json.parseToJsonElement(trimmed) - } catch (_: Throwable) { - null - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayTls.kt b/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayTls.kt deleted file mode 100644 index 0726c94fc97..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/gateway/GatewayTls.kt +++ /dev/null @@ -1,159 +0,0 @@ -package ai.openclaw.android.gateway - -import android.annotation.SuppressLint -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import java.net.InetSocketAddress -import java.security.MessageDigest -import java.security.SecureRandom -import java.security.cert.CertificateException -import java.security.cert.X509Certificate -import java.util.Locale -import javax.net.ssl.HttpsURLConnection -import javax.net.ssl.HostnameVerifier -import javax.net.ssl.SSLContext -import javax.net.ssl.SSLParameters -import javax.net.ssl.SSLSocketFactory -import javax.net.ssl.SNIHostName -import javax.net.ssl.SSLSocket -import javax.net.ssl.TrustManagerFactory -import javax.net.ssl.X509TrustManager - -data class GatewayTlsParams( - val required: Boolean, - val expectedFingerprint: String?, - val allowTOFU: Boolean, - val stableId: String, -) - -data class GatewayTlsConfig( - val sslSocketFactory: SSLSocketFactory, - val trustManager: X509TrustManager, - val hostnameVerifier: HostnameVerifier, -) - -fun buildGatewayTlsConfig( - params: GatewayTlsParams?, - onStore: ((String) -> Unit)? = null, -): GatewayTlsConfig? { - if (params == null) return null - val expected = params.expectedFingerprint?.let(::normalizeFingerprint) - val defaultTrust = defaultTrustManager() - @SuppressLint("CustomX509TrustManager") - val trustManager = - object : X509TrustManager { - override fun checkClientTrusted(chain: Array, authType: String) { - defaultTrust.checkClientTrusted(chain, authType) - } - - override fun checkServerTrusted(chain: Array, authType: String) { - if (chain.isEmpty()) throw CertificateException("empty certificate chain") - val fingerprint = sha256Hex(chain[0].encoded) - if (expected != null) { - if (fingerprint != expected) { - throw CertificateException("gateway TLS fingerprint mismatch") - } - return - } - if (params.allowTOFU) { - onStore?.invoke(fingerprint) - return - } - defaultTrust.checkServerTrusted(chain, authType) - } - - override fun getAcceptedIssuers(): Array = defaultTrust.acceptedIssuers - } - - val context = SSLContext.getInstance("TLS") - context.init(null, arrayOf(trustManager), SecureRandom()) - val verifier = - if (expected != null || params.allowTOFU) { - // When pinning, we intentionally ignore hostname mismatch (service discovery often yields IPs). - HostnameVerifier { _, _ -> true } - } else { - HttpsURLConnection.getDefaultHostnameVerifier() - } - return GatewayTlsConfig( - sslSocketFactory = context.socketFactory, - trustManager = trustManager, - hostnameVerifier = verifier, - ) -} - -suspend fun probeGatewayTlsFingerprint( - host: String, - port: Int, - timeoutMs: Int = 3_000, -): String? { - val trimmedHost = host.trim() - if (trimmedHost.isEmpty()) return null - if (port !in 1..65535) return null - - return withContext(Dispatchers.IO) { - val trustAll = - @SuppressLint("CustomX509TrustManager", "TrustAllX509TrustManager") - object : X509TrustManager { - @SuppressLint("TrustAllX509TrustManager") - override fun checkClientTrusted(chain: Array, authType: String) {} - @SuppressLint("TrustAllX509TrustManager") - override fun checkServerTrusted(chain: Array, authType: String) {} - override fun getAcceptedIssuers(): Array = emptyArray() - } - - val context = SSLContext.getInstance("TLS") - context.init(null, arrayOf(trustAll), SecureRandom()) - - val socket = (context.socketFactory.createSocket() as SSLSocket) - try { - socket.soTimeout = timeoutMs - socket.connect(InetSocketAddress(trimmedHost, port), timeoutMs) - - // Best-effort SNI for hostnames (avoid crashing on IP literals). - try { - if (trimmedHost.any { it.isLetter() }) { - val params = SSLParameters() - params.serverNames = listOf(SNIHostName(trimmedHost)) - socket.sslParameters = params - } - } catch (_: Throwable) { - // ignore - } - - socket.startHandshake() - val cert = socket.session.peerCertificates.firstOrNull() as? X509Certificate ?: return@withContext null - sha256Hex(cert.encoded) - } catch (_: Throwable) { - null - } finally { - try { - socket.close() - } catch (_: Throwable) { - // ignore - } - } - } -} - -private fun defaultTrustManager(): X509TrustManager { - val factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) - factory.init(null as java.security.KeyStore?) - val trust = - factory.trustManagers.firstOrNull { it is X509TrustManager } as? X509TrustManager - return trust ?: throw IllegalStateException("No default X509TrustManager found") -} - -private fun sha256Hex(data: ByteArray): String { - val digest = MessageDigest.getInstance("SHA-256").digest(data) - val out = StringBuilder(digest.size * 2) - for (byte in digest) { - out.append(String.format(Locale.US, "%02x", byte)) - } - return out.toString() -} - -private fun normalizeFingerprint(raw: String): String { - val stripped = raw.trim() - .replace(Regex("^sha-?256\\s*:?\\s*", RegexOption.IGNORE_CASE), "") - return stripped.lowercase(Locale.US).filter { it in '0'..'9' || it in 'a'..'f' } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/A2UIHandler.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/A2UIHandler.kt deleted file mode 100644 index 4e7ee32b996..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/A2UIHandler.kt +++ /dev/null @@ -1,146 +0,0 @@ -package ai.openclaw.android.node - -import ai.openclaw.android.gateway.GatewaySession -import kotlinx.coroutines.delay -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonArray -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive - -class A2UIHandler( - private val canvas: CanvasController, - private val json: Json, - private val getNodeCanvasHostUrl: () -> String?, - private val getOperatorCanvasHostUrl: () -> String?, -) { - fun resolveA2uiHostUrl(): String? { - val nodeRaw = getNodeCanvasHostUrl()?.trim().orEmpty() - val operatorRaw = getOperatorCanvasHostUrl()?.trim().orEmpty() - val raw = if (nodeRaw.isNotBlank()) nodeRaw else operatorRaw - if (raw.isBlank()) return null - val base = raw.trimEnd('/') - return "${base}/__openclaw__/a2ui/?platform=android" - } - - suspend fun ensureA2uiReady(a2uiUrl: String): Boolean { - try { - val already = canvas.eval(a2uiReadyCheckJS) - if (already == "true") return true - } catch (_: Throwable) { - // ignore - } - - canvas.navigate(a2uiUrl) - repeat(50) { - try { - val ready = canvas.eval(a2uiReadyCheckJS) - if (ready == "true") return true - } catch (_: Throwable) { - // ignore - } - delay(120) - } - return false - } - - fun decodeA2uiMessages(command: String, paramsJson: String?): String { - val raw = paramsJson?.trim().orEmpty() - if (raw.isBlank()) throw IllegalArgumentException("INVALID_REQUEST: paramsJSON required") - - val obj = - json.parseToJsonElement(raw) as? JsonObject - ?: throw IllegalArgumentException("INVALID_REQUEST: expected object params") - - val jsonlField = (obj["jsonl"] as? JsonPrimitive)?.content?.trim().orEmpty() - val hasMessagesArray = obj["messages"] is JsonArray - - if (command == "canvas.a2ui.pushJSONL" || (!hasMessagesArray && jsonlField.isNotBlank())) { - val jsonl = jsonlField - if (jsonl.isBlank()) throw IllegalArgumentException("INVALID_REQUEST: jsonl required") - val messages = - jsonl - .lineSequence() - .map { it.trim() } - .filter { it.isNotBlank() } - .mapIndexed { idx, line -> - val el = json.parseToJsonElement(line) - val msg = - el as? JsonObject - ?: throw IllegalArgumentException("A2UI JSONL line ${idx + 1}: expected a JSON object") - validateA2uiV0_8(msg, idx + 1) - msg - } - .toList() - return JsonArray(messages).toString() - } - - val arr = obj["messages"] as? JsonArray ?: throw IllegalArgumentException("INVALID_REQUEST: messages[] required") - val out = - arr.mapIndexed { idx, el -> - val msg = - el as? JsonObject - ?: throw IllegalArgumentException("A2UI messages[${idx}]: expected a JSON object") - validateA2uiV0_8(msg, idx + 1) - msg - } - return JsonArray(out).toString() - } - - private fun validateA2uiV0_8(msg: JsonObject, lineNumber: Int) { - if (msg.containsKey("createSurface")) { - throw IllegalArgumentException( - "A2UI JSONL line $lineNumber: looks like A2UI v0.9 (`createSurface`). Canvas supports v0.8 messages only.", - ) - } - val allowed = setOf("beginRendering", "surfaceUpdate", "dataModelUpdate", "deleteSurface") - val matched = msg.keys.filter { allowed.contains(it) } - if (matched.size != 1) { - val found = msg.keys.sorted().joinToString(", ") - throw IllegalArgumentException( - "A2UI JSONL line $lineNumber: expected exactly one of ${allowed.sorted().joinToString(", ")}; found: $found", - ) - } - } - - companion object { - const val a2uiReadyCheckJS: String = - """ - (() => { - try { - const host = globalThis.openclawA2UI; - return !!host && typeof host.applyMessages === 'function'; - } catch (_) { - return false; - } - })() - """ - - const val a2uiResetJS: String = - """ - (() => { - try { - const host = globalThis.openclawA2UI; - if (!host) return { ok: false, error: "missing openclawA2UI" }; - return host.reset(); - } catch (e) { - return { ok: false, error: String(e?.message ?? e) }; - } - })() - """ - - fun a2uiApplyMessagesJS(messagesJson: String): String { - return """ - (() => { - try { - const host = globalThis.openclawA2UI; - if (!host) return { ok: false, error: "missing openclawA2UI" }; - const messages = $messagesJson; - return host.applyMessages(messages); - } catch (e) { - return { ok: false, error: String(e?.message ?? e) }; - } - })() - """.trimIndent() - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/AppUpdateHandler.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/AppUpdateHandler.kt deleted file mode 100644 index e54c846c0fb..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/AppUpdateHandler.kt +++ /dev/null @@ -1,295 +0,0 @@ -package ai.openclaw.android.node - -import android.app.PendingIntent -import android.content.Context -import android.content.Intent -import ai.openclaw.android.InstallResultReceiver -import ai.openclaw.android.MainActivity -import ai.openclaw.android.gateway.GatewayEndpoint -import ai.openclaw.android.gateway.GatewaySession -import java.io.File -import java.net.URI -import java.security.MessageDigest -import java.util.Locale -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.buildJsonObject -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.json.jsonPrimitive -import kotlinx.serialization.json.put - -private val SHA256_HEX = Regex("^[a-fA-F0-9]{64}$") - -internal data class AppUpdateRequest( - val url: String, - val expectedSha256: String, -) - -internal fun parseAppUpdateRequest(paramsJson: String?, connectedHost: String?): AppUpdateRequest { - val params = - try { - paramsJson?.let { Json.parseToJsonElement(it).jsonObject } - } catch (_: Throwable) { - throw IllegalArgumentException("params must be valid JSON") - } ?: throw IllegalArgumentException("missing 'url' parameter") - - val urlRaw = - params["url"]?.jsonPrimitive?.content?.trim().orEmpty() - .ifEmpty { throw IllegalArgumentException("missing 'url' parameter") } - val sha256Raw = - params["sha256"]?.jsonPrimitive?.content?.trim().orEmpty() - .ifEmpty { throw IllegalArgumentException("missing 'sha256' parameter") } - if (!SHA256_HEX.matches(sha256Raw)) { - throw IllegalArgumentException("invalid 'sha256' parameter (expected 64 hex chars)") - } - - val uri = - try { - URI(urlRaw) - } catch (_: Throwable) { - throw IllegalArgumentException("invalid 'url' parameter") - } - val scheme = uri.scheme?.lowercase(Locale.US).orEmpty() - if (scheme != "https") { - throw IllegalArgumentException("url must use https") - } - if (!uri.userInfo.isNullOrBlank()) { - throw IllegalArgumentException("url must not include credentials") - } - val host = uri.host?.lowercase(Locale.US) ?: throw IllegalArgumentException("url host required") - val connectedHostNormalized = connectedHost?.trim()?.lowercase(Locale.US).orEmpty() - if (connectedHostNormalized.isNotEmpty() && host != connectedHostNormalized) { - throw IllegalArgumentException("url host must match connected gateway host") - } - - return AppUpdateRequest( - url = uri.toASCIIString(), - expectedSha256 = sha256Raw.lowercase(Locale.US), - ) -} - -internal fun sha256Hex(file: File): String { - val digest = MessageDigest.getInstance("SHA-256") - file.inputStream().use { input -> - val buffer = ByteArray(DEFAULT_BUFFER_SIZE) - while (true) { - val read = input.read(buffer) - if (read < 0) break - if (read == 0) continue - digest.update(buffer, 0, read) - } - } - val out = StringBuilder(64) - for (byte in digest.digest()) { - out.append(String.format(Locale.US, "%02x", byte)) - } - return out.toString() -} - -class AppUpdateHandler( - private val appContext: Context, - private val connectedEndpoint: () -> GatewayEndpoint?, -) { - - fun handleUpdate(paramsJson: String?): GatewaySession.InvokeResult { - try { - val updateRequest = - try { - parseAppUpdateRequest(paramsJson, connectedEndpoint()?.host) - } catch (err: IllegalArgumentException) { - return GatewaySession.InvokeResult.error( - code = "INVALID_REQUEST", - message = "INVALID_REQUEST: ${err.message ?: "invalid app.update params"}", - ) - } - val url = updateRequest.url - val expectedSha256 = updateRequest.expectedSha256 - - android.util.Log.w("openclaw", "app.update: downloading from $url") - - val notifId = 9001 - val channelId = "app_update" - val notifManager = appContext.getSystemService(android.content.Context.NOTIFICATION_SERVICE) as android.app.NotificationManager - - // Create notification channel (required for Android 8+) - val channel = android.app.NotificationChannel(channelId, "App Updates", android.app.NotificationManager.IMPORTANCE_LOW) - notifManager.createNotificationChannel(channel) - - // PendingIntent to open the app when notification is tapped - val launchIntent = Intent(appContext, MainActivity::class.java).apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP - } - val launchPi = PendingIntent.getActivity(appContext, 0, launchIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) - - // Launch download async so the invoke returns immediately - CoroutineScope(Dispatchers.IO).launch { - try { - val cacheDir = java.io.File(appContext.cacheDir, "updates") - cacheDir.mkdirs() - val file = java.io.File(cacheDir, "update.apk") - if (file.exists()) file.delete() - - // Show initial progress notification - fun buildProgressNotif(progress: Int, max: Int, text: String): android.app.Notification { - return android.app.Notification.Builder(appContext, channelId) - .setSmallIcon(android.R.drawable.stat_sys_download) - .setContentTitle("OpenClaw Update") - .setContentText(text) - .setProgress(max, progress, max == 0) - - .setContentIntent(launchPi) - .setOngoing(true) - .build() - } - notifManager.notify(notifId, buildProgressNotif(0, 0, "Connecting...")) - - val client = okhttp3.OkHttpClient.Builder() - .connectTimeout(30, java.util.concurrent.TimeUnit.SECONDS) - .readTimeout(300, java.util.concurrent.TimeUnit.SECONDS) - .build() - val request = okhttp3.Request.Builder().url(url).build() - val response = client.newCall(request).execute() - if (!response.isSuccessful) { - notifManager.cancel(notifId) - notifManager.notify(notifId, android.app.Notification.Builder(appContext, channelId) - .setSmallIcon(android.R.drawable.stat_notify_error) - .setContentTitle("Update Failed") - - .setContentIntent(launchPi) - .setContentText("HTTP ${response.code}") - .build()) - return@launch - } - - val contentLength = response.body?.contentLength() ?: -1L - val body = response.body ?: run { - notifManager.cancel(notifId) - return@launch - } - - // Download with progress tracking - var totalBytes = 0L - var lastNotifUpdate = 0L - body.byteStream().use { input -> - file.outputStream().use { output -> - val buffer = ByteArray(8192) - while (true) { - val bytesRead = input.read(buffer) - if (bytesRead == -1) break - output.write(buffer, 0, bytesRead) - totalBytes += bytesRead - - // Update notification at most every 500ms - val now = System.currentTimeMillis() - if (now - lastNotifUpdate > 500) { - lastNotifUpdate = now - if (contentLength > 0) { - val pct = ((totalBytes * 100) / contentLength).toInt() - val mb = String.format(Locale.US, "%.1f", totalBytes / 1048576.0) - val totalMb = String.format(Locale.US, "%.1f", contentLength / 1048576.0) - notifManager.notify(notifId, buildProgressNotif(pct, 100, "$mb / $totalMb MB ($pct%)")) - } else { - val mb = String.format(Locale.US, "%.1f", totalBytes / 1048576.0) - notifManager.notify(notifId, buildProgressNotif(0, 0, "${mb} MB downloaded")) - } - } - } - } - } - - android.util.Log.w("openclaw", "app.update: downloaded ${file.length()} bytes") - val actualSha256 = sha256Hex(file) - if (actualSha256 != expectedSha256) { - android.util.Log.e( - "openclaw", - "app.update: sha256 mismatch expected=$expectedSha256 actual=$actualSha256", - ) - file.delete() - notifManager.cancel(notifId) - notifManager.notify( - notifId, - android.app.Notification.Builder(appContext, channelId) - .setSmallIcon(android.R.drawable.stat_notify_error) - .setContentTitle("Update Failed") - .setContentIntent(launchPi) - .setContentText("SHA-256 mismatch") - .build(), - ) - return@launch - } - - // Verify file is a valid APK (basic check: ZIP magic bytes) - val magic = file.inputStream().use { it.read().toByte() to it.read().toByte() } - if (magic.first != 0x50.toByte() || magic.second != 0x4B.toByte()) { - android.util.Log.e("openclaw", "app.update: invalid APK (bad magic: ${magic.first}, ${magic.second})") - file.delete() - notifManager.cancel(notifId) - notifManager.notify(notifId, android.app.Notification.Builder(appContext, channelId) - .setSmallIcon(android.R.drawable.stat_notify_error) - .setContentTitle("Update Failed") - - .setContentIntent(launchPi) - .setContentText("Downloaded file is not a valid APK") - .build()) - return@launch - } - - // Use PackageInstaller session API — works from background on API 34+ - // The system handles showing the install confirmation dialog - notifManager.cancel(notifId) - notifManager.notify( - notifId, - android.app.Notification.Builder(appContext, channelId) - .setSmallIcon(android.R.drawable.stat_sys_download_done) - .setContentTitle("Installing Update...") - .setContentIntent(launchPi) - .setContentText("${String.format(Locale.US, "%.1f", totalBytes / 1048576.0)} MB downloaded") - .build(), - ) - - val installer = appContext.packageManager.packageInstaller - val params = android.content.pm.PackageInstaller.SessionParams( - android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL - ) - params.setSize(file.length()) - val sessionId = installer.createSession(params) - val session = installer.openSession(sessionId) - session.openWrite("openclaw-update.apk", 0, file.length()).use { out -> - file.inputStream().use { inp -> inp.copyTo(out) } - session.fsync(out) - } - // Commit with FLAG_MUTABLE PendingIntent — system requires mutable for PackageInstaller status - val callbackIntent = android.content.Intent(appContext, InstallResultReceiver::class.java) - val pi = android.app.PendingIntent.getBroadcast( - appContext, sessionId, callbackIntent, - android.app.PendingIntent.FLAG_UPDATE_CURRENT or android.app.PendingIntent.FLAG_MUTABLE - ) - session.commit(pi.intentSender) - android.util.Log.w("openclaw", "app.update: PackageInstaller session committed, waiting for user confirmation") - } catch (err: Throwable) { - android.util.Log.e("openclaw", "app.update: async error", err) - notifManager.cancel(notifId) - notifManager.notify(notifId, android.app.Notification.Builder(appContext, channelId) - .setSmallIcon(android.R.drawable.stat_notify_error) - .setContentTitle("Update Failed") - - .setContentIntent(launchPi) - .setContentText(err.message ?: "Unknown error") - .build()) - } - } - - // Return immediately — download happens in background - return GatewaySession.InvokeResult.ok(buildJsonObject { - put("status", "downloading") - put("url", url) - put("sha256", expectedSha256) - }.toString()) - } catch (err: Throwable) { - android.util.Log.e("openclaw", "app.update: error", err) - return GatewaySession.InvokeResult.error(code = "UNAVAILABLE", message = err.message ?: "update failed") - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/CameraCaptureManager.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/CameraCaptureManager.kt deleted file mode 100644 index 65bac915eff..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/CameraCaptureManager.kt +++ /dev/null @@ -1,364 +0,0 @@ -package ai.openclaw.android.node - -import android.Manifest -import android.content.Context -import android.annotation.SuppressLint -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import android.graphics.Matrix -import android.util.Base64 -import android.content.pm.PackageManager -import androidx.exifinterface.media.ExifInterface -import androidx.lifecycle.LifecycleOwner -import androidx.camera.core.CameraSelector -import androidx.camera.core.ImageCapture -import androidx.camera.core.ImageCaptureException -import androidx.camera.lifecycle.ProcessCameraProvider -import androidx.camera.video.FileOutputOptions -import androidx.camera.video.FallbackStrategy -import androidx.camera.video.Quality -import androidx.camera.video.QualitySelector -import androidx.camera.video.Recorder -import androidx.camera.video.Recording -import androidx.camera.video.VideoCapture -import androidx.camera.video.VideoRecordEvent -import androidx.core.content.ContextCompat -import androidx.core.content.ContextCompat.checkSelfPermission -import androidx.core.graphics.scale -import ai.openclaw.android.PermissionRequester -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.suspendCancellableCoroutine -import kotlinx.coroutines.withTimeout -import kotlinx.coroutines.withContext -import java.io.ByteArrayOutputStream -import java.io.File -import java.util.concurrent.Executor -import kotlin.math.roundToInt -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException - -class CameraCaptureManager(private val context: Context) { - data class Payload(val payloadJson: String) - data class FilePayload(val file: File, val durationMs: Long, val hasAudio: Boolean) - - @Volatile private var lifecycleOwner: LifecycleOwner? = null - @Volatile private var permissionRequester: PermissionRequester? = null - - fun attachLifecycleOwner(owner: LifecycleOwner) { - lifecycleOwner = owner - } - - fun attachPermissionRequester(requester: PermissionRequester) { - permissionRequester = requester - } - - private suspend fun ensureCameraPermission() { - val granted = checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED - if (granted) return - - val requester = permissionRequester - ?: throw IllegalStateException("CAMERA_PERMISSION_REQUIRED: grant Camera permission") - val results = requester.requestIfMissing(listOf(Manifest.permission.CAMERA)) - if (results[Manifest.permission.CAMERA] != true) { - throw IllegalStateException("CAMERA_PERMISSION_REQUIRED: grant Camera permission") - } - } - - private suspend fun ensureMicPermission() { - val granted = checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED - if (granted) return - - val requester = permissionRequester - ?: throw IllegalStateException("MIC_PERMISSION_REQUIRED: grant Microphone permission") - val results = requester.requestIfMissing(listOf(Manifest.permission.RECORD_AUDIO)) - if (results[Manifest.permission.RECORD_AUDIO] != true) { - throw IllegalStateException("MIC_PERMISSION_REQUIRED: grant Microphone permission") - } - } - - suspend fun snap(paramsJson: String?): Payload = - withContext(Dispatchers.Main) { - ensureCameraPermission() - val owner = lifecycleOwner ?: throw IllegalStateException("UNAVAILABLE: camera not ready") - val facing = parseFacing(paramsJson) ?: "front" - val quality = (parseQuality(paramsJson) ?: 0.5).coerceIn(0.1, 1.0) - val maxWidth = parseMaxWidth(paramsJson) ?: 800 - - val provider = context.cameraProvider() - val capture = ImageCapture.Builder().build() - val selector = - if (facing == "front") CameraSelector.DEFAULT_FRONT_CAMERA else CameraSelector.DEFAULT_BACK_CAMERA - - provider.unbindAll() - provider.bindToLifecycle(owner, selector, capture) - - val (bytes, orientation) = capture.takeJpegWithExif(context.mainExecutor()) - val decoded = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) - ?: throw IllegalStateException("UNAVAILABLE: failed to decode captured image") - val rotated = rotateBitmapByExif(decoded, orientation) - val scaled = - if (maxWidth > 0 && rotated.width > maxWidth) { - val h = - (rotated.height.toDouble() * (maxWidth.toDouble() / rotated.width.toDouble())) - .toInt() - .coerceAtLeast(1) - rotated.scale(maxWidth, h) - } else { - rotated - } - - val maxPayloadBytes = 5 * 1024 * 1024 - // Base64 inflates payloads by ~4/3; cap encoded bytes so the payload stays under 5MB (API limit). - val maxEncodedBytes = (maxPayloadBytes / 4) * 3 - val result = - JpegSizeLimiter.compressToLimit( - initialWidth = scaled.width, - initialHeight = scaled.height, - startQuality = (quality * 100.0).roundToInt().coerceIn(10, 100), - maxBytes = maxEncodedBytes, - encode = { width, height, q -> - val bitmap = - if (width == scaled.width && height == scaled.height) { - scaled - } else { - scaled.scale(width, height) - } - val out = ByteArrayOutputStream() - if (!bitmap.compress(Bitmap.CompressFormat.JPEG, q, out)) { - if (bitmap !== scaled) bitmap.recycle() - throw IllegalStateException("UNAVAILABLE: failed to encode JPEG") - } - if (bitmap !== scaled) { - bitmap.recycle() - } - out.toByteArray() - }, - ) - val base64 = Base64.encodeToString(result.bytes, Base64.NO_WRAP) - Payload( - """{"format":"jpg","base64":"$base64","width":${result.width},"height":${result.height}}""", - ) - } - - @SuppressLint("MissingPermission") - suspend fun clip(paramsJson: String?): FilePayload = - withContext(Dispatchers.Main) { - ensureCameraPermission() - val owner = lifecycleOwner ?: throw IllegalStateException("UNAVAILABLE: camera not ready") - val facing = parseFacing(paramsJson) ?: "front" - val durationMs = (parseDurationMs(paramsJson) ?: 3_000).coerceIn(200, 60_000) - val includeAudio = parseIncludeAudio(paramsJson) ?: true - if (includeAudio) ensureMicPermission() - - android.util.Log.w("CameraCaptureManager", "clip: start facing=$facing duration=$durationMs audio=$includeAudio") - - val provider = context.cameraProvider() - android.util.Log.w("CameraCaptureManager", "clip: got camera provider") - - // Use LOWEST quality for smallest files over WebSocket - val recorder = Recorder.Builder() - .setQualitySelector( - QualitySelector.from(Quality.LOWEST, FallbackStrategy.lowerQualityOrHigherThan(Quality.LOWEST)) - ) - .build() - val videoCapture = VideoCapture.withOutput(recorder) - val selector = - if (facing == "front") CameraSelector.DEFAULT_FRONT_CAMERA else CameraSelector.DEFAULT_BACK_CAMERA - - // CameraX requires a Preview use case for the camera to start producing frames; - // without it, the encoder may get no data (ERROR_NO_VALID_DATA). - val preview = androidx.camera.core.Preview.Builder().build() - // Provide a dummy SurfaceTexture so the preview pipeline activates - val surfaceTexture = android.graphics.SurfaceTexture(0) - surfaceTexture.setDefaultBufferSize(640, 480) - preview.setSurfaceProvider { request -> - val surface = android.view.Surface(surfaceTexture) - request.provideSurface(surface, context.mainExecutor()) { result -> - surface.release() - surfaceTexture.release() - } - } - - provider.unbindAll() - android.util.Log.w("CameraCaptureManager", "clip: binding preview + videoCapture to lifecycle") - val camera = provider.bindToLifecycle(owner, selector, preview, videoCapture) - android.util.Log.w("CameraCaptureManager", "clip: bound, cameraInfo=${camera.cameraInfo}") - - // Give camera pipeline time to initialize before recording - android.util.Log.w("CameraCaptureManager", "clip: warming up camera 1.5s...") - kotlinx.coroutines.delay(1_500) - - val file = File.createTempFile("openclaw-clip-", ".mp4") - val outputOptions = FileOutputOptions.Builder(file).build() - - val finalized = kotlinx.coroutines.CompletableDeferred() - android.util.Log.w("CameraCaptureManager", "clip: starting recording to ${file.absolutePath}") - val recording: Recording = - videoCapture.output - .prepareRecording(context, outputOptions) - .apply { - if (includeAudio) withAudioEnabled() - } - .start(context.mainExecutor()) { event -> - android.util.Log.w("CameraCaptureManager", "clip: event ${event.javaClass.simpleName}") - if (event is VideoRecordEvent.Status) { - android.util.Log.w("CameraCaptureManager", "clip: recording status update") - } - if (event is VideoRecordEvent.Finalize) { - android.util.Log.w("CameraCaptureManager", "clip: finalize hasError=${event.hasError()} error=${event.error} cause=${event.cause}") - finalized.complete(event) - } - } - - android.util.Log.w("CameraCaptureManager", "clip: recording started, delaying ${durationMs}ms") - try { - kotlinx.coroutines.delay(durationMs.toLong()) - } finally { - android.util.Log.w("CameraCaptureManager", "clip: stopping recording") - recording.stop() - } - - val finalizeEvent = - try { - withTimeout(15_000) { finalized.await() } - } catch (err: Throwable) { - android.util.Log.e("CameraCaptureManager", "clip: finalize timed out", err) - withContext(Dispatchers.IO) { file.delete() } - provider.unbindAll() - throw IllegalStateException("UNAVAILABLE: camera clip finalize timed out") - } - if (finalizeEvent.hasError()) { - android.util.Log.e("CameraCaptureManager", "clip: FAILED error=${finalizeEvent.error}, cause=${finalizeEvent.cause}", finalizeEvent.cause) - // Check file size for debugging - val fileSize = withContext(Dispatchers.IO) { if (file.exists()) file.length() else -1 } - android.util.Log.e("CameraCaptureManager", "clip: file exists=${file.exists()} size=$fileSize") - withContext(Dispatchers.IO) { file.delete() } - provider.unbindAll() - throw IllegalStateException("UNAVAILABLE: camera clip failed (error=${finalizeEvent.error})") - } - - val fileSize = withContext(Dispatchers.IO) { file.length() } - android.util.Log.w("CameraCaptureManager", "clip: SUCCESS file size=$fileSize") - - provider.unbindAll() - - FilePayload(file = file, durationMs = durationMs.toLong(), hasAudio = includeAudio) - } - - private fun rotateBitmapByExif(bitmap: Bitmap, orientation: Int): Bitmap { - val matrix = Matrix() - when (orientation) { - ExifInterface.ORIENTATION_ROTATE_90 -> matrix.postRotate(90f) - ExifInterface.ORIENTATION_ROTATE_180 -> matrix.postRotate(180f) - ExifInterface.ORIENTATION_ROTATE_270 -> matrix.postRotate(270f) - ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> matrix.postScale(-1f, 1f) - ExifInterface.ORIENTATION_FLIP_VERTICAL -> matrix.postScale(1f, -1f) - ExifInterface.ORIENTATION_TRANSPOSE -> { - matrix.postRotate(90f) - matrix.postScale(-1f, 1f) - } - ExifInterface.ORIENTATION_TRANSVERSE -> { - matrix.postRotate(-90f) - matrix.postScale(-1f, 1f) - } - else -> return bitmap - } - val rotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true) - if (rotated !== bitmap) { - bitmap.recycle() - } - return rotated - } - - private fun parseFacing(paramsJson: String?): String? = - when { - paramsJson?.contains("\"front\"") == true -> "front" - paramsJson?.contains("\"back\"") == true -> "back" - else -> null - } - - private fun parseQuality(paramsJson: String?): Double? = - parseNumber(paramsJson, key = "quality")?.toDoubleOrNull() - - private fun parseMaxWidth(paramsJson: String?): Int? = - parseNumber(paramsJson, key = "maxWidth")?.toIntOrNull() - - private fun parseDurationMs(paramsJson: String?): Int? = - parseNumber(paramsJson, key = "durationMs")?.toIntOrNull() - - private fun parseIncludeAudio(paramsJson: String?): Boolean? { - val raw = paramsJson ?: return null - val key = "\"includeAudio\"" - val idx = raw.indexOf(key) - if (idx < 0) return null - val colon = raw.indexOf(':', idx + key.length) - if (colon < 0) return null - val tail = raw.substring(colon + 1).trimStart() - return when { - tail.startsWith("true") -> true - tail.startsWith("false") -> false - else -> null - } - } - - private fun parseNumber(paramsJson: String?, key: String): String? { - val raw = paramsJson ?: return null - val needle = "\"$key\"" - val idx = raw.indexOf(needle) - if (idx < 0) return null - val colon = raw.indexOf(':', idx + needle.length) - if (colon < 0) return null - val tail = raw.substring(colon + 1).trimStart() - return tail.takeWhile { it.isDigit() || it == '.' } - } - - private fun Context.mainExecutor(): Executor = ContextCompat.getMainExecutor(this) -} - -private suspend fun Context.cameraProvider(): ProcessCameraProvider = - suspendCancellableCoroutine { cont -> - val future = ProcessCameraProvider.getInstance(this) - future.addListener( - { - try { - cont.resume(future.get()) - } catch (e: Exception) { - cont.resumeWithException(e) - } - }, - ContextCompat.getMainExecutor(this), - ) - } - -/** Returns (jpegBytes, exifOrientation) so caller can rotate the decoded bitmap. */ -private suspend fun ImageCapture.takeJpegWithExif(executor: Executor): Pair = - suspendCancellableCoroutine { cont -> - val file = File.createTempFile("openclaw-snap-", ".jpg") - val options = ImageCapture.OutputFileOptions.Builder(file).build() - takePicture( - options, - executor, - object : ImageCapture.OnImageSavedCallback { - override fun onError(exception: ImageCaptureException) { - file.delete() - cont.resumeWithException(exception) - } - - override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { - try { - val exif = ExifInterface(file.absolutePath) - val orientation = exif.getAttributeInt( - ExifInterface.TAG_ORIENTATION, - ExifInterface.ORIENTATION_NORMAL, - ) - val bytes = file.readBytes() - cont.resume(Pair(bytes, orientation)) - } catch (e: Exception) { - cont.resumeWithException(e) - } finally { - file.delete() - } - } - }, - ) - } diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/CameraHandler.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/CameraHandler.kt deleted file mode 100644 index 658c117ff31..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/CameraHandler.kt +++ /dev/null @@ -1,157 +0,0 @@ -package ai.openclaw.android.node - -import android.content.Context -import ai.openclaw.android.CameraHudKind -import ai.openclaw.android.BuildConfig -import ai.openclaw.android.SecurePrefs -import ai.openclaw.android.gateway.GatewayEndpoint -import ai.openclaw.android.gateway.GatewaySession -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.withContext -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.RequestBody.Companion.asRequestBody - -class CameraHandler( - private val appContext: Context, - private val camera: CameraCaptureManager, - private val prefs: SecurePrefs, - private val connectedEndpoint: () -> GatewayEndpoint?, - private val externalAudioCaptureActive: MutableStateFlow, - private val showCameraHud: (message: String, kind: CameraHudKind, autoHideMs: Long?) -> Unit, - private val triggerCameraFlash: () -> Unit, - private val invokeErrorFromThrowable: (err: Throwable) -> Pair, -) { - - suspend fun handleSnap(paramsJson: String?): GatewaySession.InvokeResult { - val logFile = if (BuildConfig.DEBUG) java.io.File(appContext.cacheDir, "camera_debug.log") else null - fun camLog(msg: String) { - if (!BuildConfig.DEBUG) return - val ts = java.text.SimpleDateFormat("HH:mm:ss.SSS", java.util.Locale.US).format(java.util.Date()) - logFile?.appendText("[$ts] $msg\n") - android.util.Log.w("openclaw", "camera.snap: $msg") - } - try { - logFile?.writeText("") // clear - camLog("starting, params=$paramsJson") - camLog("calling showCameraHud") - showCameraHud("Taking photo…", CameraHudKind.Photo, null) - camLog("calling triggerCameraFlash") - triggerCameraFlash() - val res = - try { - camLog("calling camera.snap()") - val r = camera.snap(paramsJson) - camLog("success, payload size=${r.payloadJson.length}") - r - } catch (err: Throwable) { - camLog("inner error: ${err::class.java.simpleName}: ${err.message}") - camLog("stack: ${err.stackTraceToString().take(2000)}") - val (code, message) = invokeErrorFromThrowable(err) - showCameraHud(message, CameraHudKind.Error, 2200) - return GatewaySession.InvokeResult.error(code = code, message = message) - } - camLog("returning result") - showCameraHud("Photo captured", CameraHudKind.Success, 1600) - return GatewaySession.InvokeResult.ok(res.payloadJson) - } catch (err: Throwable) { - camLog("outer error: ${err::class.java.simpleName}: ${err.message}") - camLog("stack: ${err.stackTraceToString().take(2000)}") - return GatewaySession.InvokeResult.error(code = "UNAVAILABLE", message = err.message ?: "camera snap failed") - } - } - - suspend fun handleClip(paramsJson: String?): GatewaySession.InvokeResult { - val clipLogFile = if (BuildConfig.DEBUG) java.io.File(appContext.cacheDir, "camera_debug.log") else null - fun clipLog(msg: String) { - if (!BuildConfig.DEBUG) return - val ts = java.text.SimpleDateFormat("HH:mm:ss.SSS", java.util.Locale.US).format(java.util.Date()) - clipLogFile?.appendText("[CLIP $ts] $msg\n") - android.util.Log.w("openclaw", "camera.clip: $msg") - } - val includeAudio = paramsJson?.contains("\"includeAudio\":true") != false - if (includeAudio) externalAudioCaptureActive.value = true - try { - clipLogFile?.writeText("") // clear - clipLog("starting, params=$paramsJson includeAudio=$includeAudio") - clipLog("calling showCameraHud") - showCameraHud("Recording…", CameraHudKind.Recording, null) - val filePayload = - try { - clipLog("calling camera.clip()") - val r = camera.clip(paramsJson) - clipLog("success, file size=${r.file.length()}") - r - } catch (err: Throwable) { - clipLog("inner error: ${err::class.java.simpleName}: ${err.message}") - clipLog("stack: ${err.stackTraceToString().take(2000)}") - val (code, message) = invokeErrorFromThrowable(err) - showCameraHud(message, CameraHudKind.Error, 2400) - return GatewaySession.InvokeResult.error(code = code, message = message) - } - // Upload file via HTTP instead of base64 through WebSocket - clipLog("uploading via HTTP...") - val uploadUrl = try { - withContext(Dispatchers.IO) { - val ep = connectedEndpoint() - val gatewayHost = if (ep != null) { - val isHttps = ep.tlsEnabled || ep.port == 443 - if (!isHttps) { - clipLog("refusing to upload over plain HTTP — bearer token would be exposed; falling back to base64") - throw Exception("HTTPS required for upload (bearer token protection)") - } - if (ep.port == 443) "https://${ep.host}" else "https://${ep.host}:${ep.port}" - } else { - clipLog("error: no gateway endpoint connected, cannot upload") - throw Exception("no gateway endpoint connected") - } - val token = prefs.loadGatewayToken() ?: "" - val client = okhttp3.OkHttpClient.Builder() - .connectTimeout(10, java.util.concurrent.TimeUnit.SECONDS) - .writeTimeout(120, java.util.concurrent.TimeUnit.SECONDS) - .readTimeout(30, java.util.concurrent.TimeUnit.SECONDS) - .build() - val body = filePayload.file.asRequestBody("video/mp4".toMediaType()) - val req = okhttp3.Request.Builder() - .url("$gatewayHost/upload/clip.mp4") - .put(body) - .header("Authorization", "Bearer $token") - .build() - clipLog("uploading ${filePayload.file.length()} bytes to $gatewayHost/upload/clip.mp4") - val resp = client.newCall(req).execute() - val respBody = resp.body?.string() ?: "" - clipLog("upload response: ${resp.code} $respBody") - filePayload.file.delete() - if (!resp.isSuccessful) throw Exception("upload failed: HTTP ${resp.code}") - // Parse URL from response - val urlMatch = Regex("\"url\":\"([^\"]+)\"").find(respBody) - urlMatch?.groupValues?.get(1) ?: throw Exception("no url in response: $respBody") - } - } catch (err: Throwable) { - clipLog("upload failed: ${err.message}, falling back to base64") - // Fallback to base64 if upload fails - val bytes = withContext(Dispatchers.IO) { - val b = filePayload.file.readBytes() - filePayload.file.delete() - b - } - val base64 = android.util.Base64.encodeToString(bytes, android.util.Base64.NO_WRAP) - showCameraHud("Clip captured", CameraHudKind.Success, 1800) - return GatewaySession.InvokeResult.ok( - """{"format":"mp4","base64":"$base64","durationMs":${filePayload.durationMs},"hasAudio":${filePayload.hasAudio}}""" - ) - } - clipLog("returning URL result: $uploadUrl") - showCameraHud("Clip captured", CameraHudKind.Success, 1800) - return GatewaySession.InvokeResult.ok( - """{"format":"mp4","url":"$uploadUrl","durationMs":${filePayload.durationMs},"hasAudio":${filePayload.hasAudio}}""" - ) - } catch (err: Throwable) { - clipLog("outer error: ${err::class.java.simpleName}: ${err.message}") - clipLog("stack: ${err.stackTraceToString().take(2000)}") - return GatewaySession.InvokeResult.error(code = "UNAVAILABLE", message = err.message ?: "camera clip failed") - } finally { - if (includeAudio) externalAudioCaptureActive.value = false - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/CanvasController.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/CanvasController.kt deleted file mode 100644 index c46770a6367..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/CanvasController.kt +++ /dev/null @@ -1,264 +0,0 @@ -package ai.openclaw.android.node - -import android.graphics.Bitmap -import android.graphics.Canvas -import android.os.Looper -import android.util.Log -import android.webkit.WebView -import androidx.core.graphics.createBitmap -import androidx.core.graphics.scale -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.suspendCancellableCoroutine -import kotlinx.coroutines.withContext -import java.io.ByteArrayOutputStream -import android.util.Base64 -import org.json.JSONObject -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import ai.openclaw.android.BuildConfig -import kotlin.coroutines.resume - -class CanvasController { - enum class SnapshotFormat(val rawValue: String) { - Png("png"), - Jpeg("jpeg"), - } - - @Volatile private var webView: WebView? = null - @Volatile private var url: String? = null - @Volatile private var debugStatusEnabled: Boolean = false - @Volatile private var debugStatusTitle: String? = null - @Volatile private var debugStatusSubtitle: String? = null - - private val scaffoldAssetUrl = "file:///android_asset/CanvasScaffold/scaffold.html" - - private fun clampJpegQuality(quality: Double?): Int { - val q = (quality ?: 0.82).coerceIn(0.1, 1.0) - return (q * 100.0).toInt().coerceIn(1, 100) - } - - fun attach(webView: WebView) { - this.webView = webView - reload() - applyDebugStatus() - } - - fun navigate(url: String) { - val trimmed = url.trim() - this.url = if (trimmed.isBlank() || trimmed == "/") null else trimmed - reload() - } - - fun currentUrl(): String? = url - - fun isDefaultCanvas(): Boolean = url == null - - fun setDebugStatusEnabled(enabled: Boolean) { - debugStatusEnabled = enabled - applyDebugStatus() - } - - fun setDebugStatus(title: String?, subtitle: String?) { - debugStatusTitle = title - debugStatusSubtitle = subtitle - applyDebugStatus() - } - - fun onPageFinished() { - applyDebugStatus() - } - - private inline fun withWebViewOnMain(crossinline block: (WebView) -> Unit) { - val wv = webView ?: return - if (Looper.myLooper() == Looper.getMainLooper()) { - block(wv) - } else { - wv.post { block(wv) } - } - } - - private fun reload() { - val currentUrl = url - withWebViewOnMain { wv -> - if (currentUrl == null) { - if (BuildConfig.DEBUG) { - Log.d("OpenClawCanvas", "load scaffold: $scaffoldAssetUrl") - } - wv.loadUrl(scaffoldAssetUrl) - } else { - if (BuildConfig.DEBUG) { - Log.d("OpenClawCanvas", "load url: $currentUrl") - } - wv.loadUrl(currentUrl) - } - } - } - - private fun applyDebugStatus() { - val enabled = debugStatusEnabled - val title = debugStatusTitle - val subtitle = debugStatusSubtitle - withWebViewOnMain { wv -> - val titleJs = title?.let { JSONObject.quote(it) } ?: "null" - val subtitleJs = subtitle?.let { JSONObject.quote(it) } ?: "null" - val js = """ - (() => { - try { - const api = globalThis.__openclaw; - if (!api) return; - if (typeof api.setDebugStatusEnabled === 'function') { - api.setDebugStatusEnabled(${if (enabled) "true" else "false"}); - } - if (!${if (enabled) "true" else "false"}) return; - if (typeof api.setStatus === 'function') { - api.setStatus($titleJs, $subtitleJs); - } - } catch (_) {} - })(); - """.trimIndent() - wv.evaluateJavascript(js, null) - } - } - - suspend fun eval(javaScript: String): String = - withContext(Dispatchers.Main) { - val wv = webView ?: throw IllegalStateException("no webview") - suspendCancellableCoroutine { cont -> - wv.evaluateJavascript(javaScript) { result -> - cont.resume(result ?: "") - } - } - } - - suspend fun snapshotPngBase64(maxWidth: Int?): String = - withContext(Dispatchers.Main) { - val wv = webView ?: throw IllegalStateException("no webview") - val bmp = wv.captureBitmap() - val scaled = - if (maxWidth != null && maxWidth > 0 && bmp.width > maxWidth) { - val h = (bmp.height.toDouble() * (maxWidth.toDouble() / bmp.width.toDouble())).toInt().coerceAtLeast(1) - bmp.scale(maxWidth, h) - } else { - bmp - } - - val out = ByteArrayOutputStream() - scaled.compress(Bitmap.CompressFormat.PNG, 100, out) - Base64.encodeToString(out.toByteArray(), Base64.NO_WRAP) - } - - suspend fun snapshotBase64(format: SnapshotFormat, quality: Double?, maxWidth: Int?): String = - withContext(Dispatchers.Main) { - val wv = webView ?: throw IllegalStateException("no webview") - val bmp = wv.captureBitmap() - val scaled = - if (maxWidth != null && maxWidth > 0 && bmp.width > maxWidth) { - val h = (bmp.height.toDouble() * (maxWidth.toDouble() / bmp.width.toDouble())).toInt().coerceAtLeast(1) - bmp.scale(maxWidth, h) - } else { - bmp - } - - val out = ByteArrayOutputStream() - val (compressFormat, compressQuality) = - when (format) { - SnapshotFormat.Png -> Bitmap.CompressFormat.PNG to 100 - SnapshotFormat.Jpeg -> Bitmap.CompressFormat.JPEG to clampJpegQuality(quality) - } - scaled.compress(compressFormat, compressQuality, out) - Base64.encodeToString(out.toByteArray(), Base64.NO_WRAP) - } - - private suspend fun WebView.captureBitmap(): Bitmap = - suspendCancellableCoroutine { cont -> - val width = width.coerceAtLeast(1) - val height = height.coerceAtLeast(1) - val bitmap = createBitmap(width, height, Bitmap.Config.ARGB_8888) - - // WebView isn't supported by PixelCopy.request(...) directly; draw() is the most reliable - // cross-version snapshot for this lightweight "canvas" use-case. - draw(Canvas(bitmap)) - cont.resume(bitmap) - } - - companion object { - data class SnapshotParams(val format: SnapshotFormat, val quality: Double?, val maxWidth: Int?) - - fun parseNavigateUrl(paramsJson: String?): String { - val obj = parseParamsObject(paramsJson) ?: return "" - return obj.string("url").trim() - } - - fun parseEvalJs(paramsJson: String?): String? { - val obj = parseParamsObject(paramsJson) ?: return null - val js = obj.string("javaScript").trim() - return js.takeIf { it.isNotBlank() } - } - - fun parseSnapshotMaxWidth(paramsJson: String?): Int? { - val obj = parseParamsObject(paramsJson) ?: return null - if (!obj.containsKey("maxWidth")) return null - val width = obj.int("maxWidth") ?: 0 - return width.takeIf { it > 0 } - } - - fun parseSnapshotFormat(paramsJson: String?): SnapshotFormat { - val obj = parseParamsObject(paramsJson) ?: return SnapshotFormat.Jpeg - val raw = obj.string("format").trim().lowercase() - return when (raw) { - "png" -> SnapshotFormat.Png - "jpeg", "jpg" -> SnapshotFormat.Jpeg - "" -> SnapshotFormat.Jpeg - else -> SnapshotFormat.Jpeg - } - } - - fun parseSnapshotQuality(paramsJson: String?): Double? { - val obj = parseParamsObject(paramsJson) ?: return null - if (!obj.containsKey("quality")) return null - val q = obj.double("quality") ?: Double.NaN - if (!q.isFinite()) return null - return q.coerceIn(0.1, 1.0) - } - - fun parseSnapshotParams(paramsJson: String?): SnapshotParams { - return SnapshotParams( - format = parseSnapshotFormat(paramsJson), - quality = parseSnapshotQuality(paramsJson), - maxWidth = parseSnapshotMaxWidth(paramsJson), - ) - } - - private val json = Json { ignoreUnknownKeys = true } - - private fun parseParamsObject(paramsJson: String?): JsonObject? { - val raw = paramsJson?.trim().orEmpty() - if (raw.isEmpty()) return null - return try { - json.parseToJsonElement(raw).asObjectOrNull() - } catch (_: Throwable) { - null - } - } - - private fun JsonElement?.asObjectOrNull(): JsonObject? = this as? JsonObject - - private fun JsonObject.string(key: String): String { - val prim = this[key] as? JsonPrimitive ?: return "" - val raw = prim.content - return raw.takeIf { it != "null" }.orEmpty() - } - - private fun JsonObject.int(key: String): Int? { - val prim = this[key] as? JsonPrimitive ?: return null - return prim.content.toIntOrNull() - } - - private fun JsonObject.double(key: String): Double? { - val prim = this[key] as? JsonPrimitive ?: return null - return prim.content.toDoubleOrNull() - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/ConnectionManager.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/ConnectionManager.kt deleted file mode 100644 index d15d928e0a4..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/ConnectionManager.kt +++ /dev/null @@ -1,188 +0,0 @@ -package ai.openclaw.android.node - -import android.os.Build -import ai.openclaw.android.BuildConfig -import ai.openclaw.android.SecurePrefs -import ai.openclaw.android.gateway.GatewayClientInfo -import ai.openclaw.android.gateway.GatewayConnectOptions -import ai.openclaw.android.gateway.GatewayEndpoint -import ai.openclaw.android.gateway.GatewayTlsParams -import ai.openclaw.android.protocol.OpenClawCanvasA2UICommand -import ai.openclaw.android.protocol.OpenClawCanvasCommand -import ai.openclaw.android.protocol.OpenClawCameraCommand -import ai.openclaw.android.protocol.OpenClawLocationCommand -import ai.openclaw.android.protocol.OpenClawScreenCommand -import ai.openclaw.android.protocol.OpenClawSmsCommand -import ai.openclaw.android.protocol.OpenClawCapability -import ai.openclaw.android.LocationMode -import ai.openclaw.android.VoiceWakeMode - -class ConnectionManager( - private val prefs: SecurePrefs, - private val cameraEnabled: () -> Boolean, - private val locationMode: () -> LocationMode, - private val voiceWakeMode: () -> VoiceWakeMode, - private val smsAvailable: () -> Boolean, - private val hasRecordAudioPermission: () -> Boolean, - private val manualTls: () -> Boolean, -) { - companion object { - internal fun resolveTlsParamsForEndpoint( - endpoint: GatewayEndpoint, - storedFingerprint: String?, - manualTlsEnabled: Boolean, - ): GatewayTlsParams? { - val stableId = endpoint.stableId - val stored = storedFingerprint?.trim().takeIf { !it.isNullOrEmpty() } - val isManual = stableId.startsWith("manual|") - - if (isManual) { - if (!manualTlsEnabled) return null - if (!stored.isNullOrBlank()) { - return GatewayTlsParams( - required = true, - expectedFingerprint = stored, - allowTOFU = false, - stableId = stableId, - ) - } - return GatewayTlsParams( - required = true, - expectedFingerprint = null, - allowTOFU = false, - stableId = stableId, - ) - } - - // Prefer stored pins. Never let discovery-provided TXT override a stored fingerprint. - if (!stored.isNullOrBlank()) { - return GatewayTlsParams( - required = true, - expectedFingerprint = stored, - allowTOFU = false, - stableId = stableId, - ) - } - - val hinted = endpoint.tlsEnabled || !endpoint.tlsFingerprintSha256.isNullOrBlank() - if (hinted) { - // TXT is unauthenticated. Do not treat the advertised fingerprint as authoritative. - return GatewayTlsParams( - required = true, - expectedFingerprint = null, - allowTOFU = false, - stableId = stableId, - ) - } - - return null - } - } - - fun buildInvokeCommands(): List = - buildList { - add(OpenClawCanvasCommand.Present.rawValue) - add(OpenClawCanvasCommand.Hide.rawValue) - add(OpenClawCanvasCommand.Navigate.rawValue) - add(OpenClawCanvasCommand.Eval.rawValue) - add(OpenClawCanvasCommand.Snapshot.rawValue) - add(OpenClawCanvasA2UICommand.Push.rawValue) - add(OpenClawCanvasA2UICommand.PushJSONL.rawValue) - add(OpenClawCanvasA2UICommand.Reset.rawValue) - add(OpenClawScreenCommand.Record.rawValue) - if (cameraEnabled()) { - add(OpenClawCameraCommand.Snap.rawValue) - add(OpenClawCameraCommand.Clip.rawValue) - } - if (locationMode() != LocationMode.Off) { - add(OpenClawLocationCommand.Get.rawValue) - } - if (smsAvailable()) { - add(OpenClawSmsCommand.Send.rawValue) - } - if (BuildConfig.DEBUG) { - add("debug.logs") - add("debug.ed25519") - } - add("app.update") - } - - fun buildCapabilities(): List = - buildList { - add(OpenClawCapability.Canvas.rawValue) - add(OpenClawCapability.Screen.rawValue) - if (cameraEnabled()) add(OpenClawCapability.Camera.rawValue) - if (smsAvailable()) add(OpenClawCapability.Sms.rawValue) - if (voiceWakeMode() != VoiceWakeMode.Off && hasRecordAudioPermission()) { - add(OpenClawCapability.VoiceWake.rawValue) - } - if (locationMode() != LocationMode.Off) { - add(OpenClawCapability.Location.rawValue) - } - } - - fun resolvedVersionName(): String { - val versionName = BuildConfig.VERSION_NAME.trim().ifEmpty { "dev" } - return if (BuildConfig.DEBUG && !versionName.contains("dev", ignoreCase = true)) { - "$versionName-dev" - } else { - versionName - } - } - - fun resolveModelIdentifier(): String? { - return listOfNotNull(Build.MANUFACTURER, Build.MODEL) - .joinToString(" ") - .trim() - .ifEmpty { null } - } - - fun buildUserAgent(): String { - val version = resolvedVersionName() - val release = Build.VERSION.RELEASE?.trim().orEmpty() - val releaseLabel = if (release.isEmpty()) "unknown" else release - return "OpenClawAndroid/$version (Android $releaseLabel; SDK ${Build.VERSION.SDK_INT})" - } - - fun buildClientInfo(clientId: String, clientMode: String): GatewayClientInfo { - return GatewayClientInfo( - id = clientId, - displayName = prefs.displayName.value, - version = resolvedVersionName(), - platform = "android", - mode = clientMode, - instanceId = prefs.instanceId.value, - deviceFamily = "Android", - modelIdentifier = resolveModelIdentifier(), - ) - } - - fun buildNodeConnectOptions(): GatewayConnectOptions { - return GatewayConnectOptions( - role = "node", - scopes = emptyList(), - caps = buildCapabilities(), - commands = buildInvokeCommands(), - permissions = emptyMap(), - client = buildClientInfo(clientId = "openclaw-android", clientMode = "node"), - userAgent = buildUserAgent(), - ) - } - - fun buildOperatorConnectOptions(): GatewayConnectOptions { - return GatewayConnectOptions( - role = "operator", - scopes = listOf("operator.read", "operator.write", "operator.talk.secrets"), - caps = emptyList(), - commands = emptyList(), - permissions = emptyMap(), - client = buildClientInfo(clientId = "openclaw-control-ui", clientMode = "ui"), - userAgent = buildUserAgent(), - ) - } - - fun resolveTlsParams(endpoint: GatewayEndpoint): GatewayTlsParams? { - val stored = prefs.loadGatewayTlsFingerprint(endpoint.stableId) - return resolveTlsParamsForEndpoint(endpoint, storedFingerprint = stored, manualTlsEnabled = manualTls()) - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/DebugHandler.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/DebugHandler.kt deleted file mode 100644 index 49502bd3631..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/DebugHandler.kt +++ /dev/null @@ -1,117 +0,0 @@ -package ai.openclaw.android.node - -import android.content.Context -import ai.openclaw.android.BuildConfig -import ai.openclaw.android.gateway.DeviceIdentityStore -import ai.openclaw.android.gateway.GatewaySession -import kotlinx.serialization.json.JsonPrimitive - -class DebugHandler( - private val appContext: Context, - private val identityStore: DeviceIdentityStore, -) { - - fun handleEd25519(): GatewaySession.InvokeResult { - if (!BuildConfig.DEBUG) { - return GatewaySession.InvokeResult.error(code = "UNAVAILABLE", message = "debug commands are disabled in release builds") - } - // Self-test Ed25519 signing and return diagnostic info - try { - val identity = identityStore.loadOrCreate() - val testPayload = "test|${identity.deviceId}|${System.currentTimeMillis()}" - val results = mutableListOf() - results.add("deviceId: ${identity.deviceId}") - results.add("publicKeyRawBase64: ${identity.publicKeyRawBase64.take(20)}...") - results.add("privateKeyPkcs8Base64: ${identity.privateKeyPkcs8Base64.take(20)}...") - - // Test publicKeyBase64Url - val pubKeyUrl = identityStore.publicKeyBase64Url(identity) - results.add("publicKeyBase64Url: ${pubKeyUrl ?: "NULL (FAILED)"}") - - // Test signing - val signature = identityStore.signPayload(testPayload, identity) - results.add("signPayload: ${if (signature != null) "${signature.take(20)}... (OK)" else "NULL (FAILED)"}") - - // Test self-verify - if (signature != null) { - val verifyOk = identityStore.verifySelfSignature(testPayload, signature, identity) - results.add("verifySelfSignature: $verifyOk") - } - - // Check available providers - val providers = java.security.Security.getProviders() - val ed25519Providers = providers.filter { p -> - p.services.any { s -> s.algorithm.contains("Ed25519", ignoreCase = true) } - } - results.add("Ed25519 providers: ${ed25519Providers.map { "${it.name} v${it.version}" }}") - results.add("Provider order: ${providers.take(5).map { it.name }}") - - // Test KeyFactory directly - try { - val kf = java.security.KeyFactory.getInstance("Ed25519") - results.add("KeyFactory.Ed25519: ${kf.provider.name} (OK)") - } catch (e: Throwable) { - results.add("KeyFactory.Ed25519: FAILED - ${e.javaClass.simpleName}: ${e.message}") - } - - // Test Signature directly - try { - val sig = java.security.Signature.getInstance("Ed25519") - results.add("Signature.Ed25519: ${sig.provider.name} (OK)") - } catch (e: Throwable) { - results.add("Signature.Ed25519: FAILED - ${e.javaClass.simpleName}: ${e.message}") - } - - return GatewaySession.InvokeResult.ok("""{"diagnostics":"${results.joinToString("\\n").replace("\"", "\\\"")}"}"""") - } catch (e: Throwable) { - return GatewaySession.InvokeResult.error(code = "ED25519_TEST_FAILED", message = "${e.javaClass.simpleName}: ${e.message}\n${e.stackTraceToString().take(500)}") - } - } - - fun handleLogs(): GatewaySession.InvokeResult { - if (!BuildConfig.DEBUG) { - return GatewaySession.InvokeResult.error(code = "UNAVAILABLE", message = "debug commands are disabled in release builds") - } - val pid = android.os.Process.myPid() - val rt = Runtime.getRuntime() - val info = "v6 pid=$pid thread=${Thread.currentThread().name} free=${rt.freeMemory()/1024}K total=${rt.totalMemory()/1024}K max=${rt.maxMemory()/1024}K uptime=${android.os.SystemClock.elapsedRealtime()/1000}s sdk=${android.os.Build.VERSION.SDK_INT} device=${android.os.Build.MODEL}\n" - // Run logcat on current dispatcher thread (no withContext) with file redirect - val logResult = try { - val tmpFile = java.io.File(appContext.cacheDir, "debug_logs.txt") - if (tmpFile.exists()) tmpFile.delete() - val pb = ProcessBuilder("logcat", "-d", "-t", "200", "--pid=$pid") - pb.redirectOutput(tmpFile) - pb.redirectErrorStream(true) - val proc = pb.start() - val finished = proc.waitFor(4, java.util.concurrent.TimeUnit.SECONDS) - if (!finished) proc.destroyForcibly() - val raw = if (tmpFile.exists() && tmpFile.length() > 0) { - tmpFile.readText().take(128000) - } else { - "(no output, finished=$finished, exists=${tmpFile.exists()})" - } - tmpFile.delete() - val spamPatterns = listOf("setRequestedFrameRate", "I View :", "BLASTBufferQueue", "VRI[Pop-Up", - "InsetsController:", "VRI[MainActivity", "InsetsSource:", "handleResized", "ProfileInstaller", - "I VRI[", "onStateChanged: host=", "D StrictMode:", "E StrictMode:", "ImeFocusController", - "InputTransport", "IncorrectContextUseViolation") - val sb = StringBuilder() - for (line in raw.lineSequence()) { - if (line.isBlank()) continue - if (spamPatterns.any { line.contains(it) }) continue - if (sb.length + line.length > 16000) { sb.append("\n(truncated)"); break } - if (sb.isNotEmpty()) sb.append('\n') - sb.append(line) - } - sb.toString().ifEmpty { "(all ${raw.lines().size} lines filtered as spam)" } - } catch (e: Throwable) { - "(logcat error: ${e::class.java.simpleName}: ${e.message})" - } - // Also include camera debug log if it exists - val camLogFile = java.io.File(appContext.cacheDir, "camera_debug.log") - val camLog = if (camLogFile.exists() && camLogFile.length() > 0) { - "\n--- camera_debug.log ---\n" + camLogFile.readText().take(4000) - } else "" - return GatewaySession.InvokeResult.ok("""{"logs":${JsonPrimitive(info + logResult + camLog)}}""") - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/GatewayEventHandler.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/GatewayEventHandler.kt deleted file mode 100644 index 9c0514d8635..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/GatewayEventHandler.kt +++ /dev/null @@ -1,71 +0,0 @@ -package ai.openclaw.android.node - -import ai.openclaw.android.SecurePrefs -import ai.openclaw.android.gateway.GatewaySession -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonArray - -class GatewayEventHandler( - private val scope: CoroutineScope, - private val prefs: SecurePrefs, - private val json: Json, - private val operatorSession: GatewaySession, - private val isConnected: () -> Boolean, -) { - private var suppressWakeWordsSync = false - private var wakeWordsSyncJob: Job? = null - - fun applyWakeWordsFromGateway(words: List) { - suppressWakeWordsSync = true - prefs.setWakeWords(words) - suppressWakeWordsSync = false - } - - fun scheduleWakeWordsSyncIfNeeded() { - if (suppressWakeWordsSync) return - if (!isConnected()) return - - val snapshot = prefs.wakeWords.value - wakeWordsSyncJob?.cancel() - wakeWordsSyncJob = - scope.launch { - delay(650) - val jsonList = snapshot.joinToString(separator = ",") { it.toJsonString() } - val params = """{"triggers":[$jsonList]}""" - try { - operatorSession.request("voicewake.set", params) - } catch (_: Throwable) { - // ignore - } - } - } - - suspend fun refreshWakeWordsFromGateway() { - if (!isConnected()) return - try { - val res = operatorSession.request("voicewake.get", "{}") - val payload = json.parseToJsonElement(res).asObjectOrNull() ?: return - val array = payload["triggers"] as? JsonArray ?: return - val triggers = array.mapNotNull { it.asStringOrNull() } - applyWakeWordsFromGateway(triggers) - } catch (_: Throwable) { - // ignore - } - } - - fun handleVoiceWakeChangedEvent(payloadJson: String?) { - if (payloadJson.isNullOrBlank()) return - try { - val payload = json.parseToJsonElement(payloadJson).asObjectOrNull() ?: return - val array = payload["triggers"] as? JsonArray ?: return - val triggers = array.mapNotNull { it.asStringOrNull() } - applyWakeWordsFromGateway(triggers) - } catch (_: Throwable) { - // ignore - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/InvokeDispatcher.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/InvokeDispatcher.kt deleted file mode 100644 index e44896db0fa..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/InvokeDispatcher.kt +++ /dev/null @@ -1,176 +0,0 @@ -package ai.openclaw.android.node - -import ai.openclaw.android.gateway.GatewaySession -import ai.openclaw.android.protocol.OpenClawCanvasA2UICommand -import ai.openclaw.android.protocol.OpenClawCanvasCommand -import ai.openclaw.android.protocol.OpenClawCameraCommand -import ai.openclaw.android.protocol.OpenClawLocationCommand -import ai.openclaw.android.protocol.OpenClawScreenCommand -import ai.openclaw.android.protocol.OpenClawSmsCommand - -class InvokeDispatcher( - private val canvas: CanvasController, - private val cameraHandler: CameraHandler, - private val locationHandler: LocationHandler, - private val screenHandler: ScreenHandler, - private val smsHandler: SmsHandler, - private val a2uiHandler: A2UIHandler, - private val debugHandler: DebugHandler, - private val appUpdateHandler: AppUpdateHandler, - private val isForeground: () -> Boolean, - private val cameraEnabled: () -> Boolean, - private val locationEnabled: () -> Boolean, -) { - suspend fun handleInvoke(command: String, paramsJson: String?): GatewaySession.InvokeResult { - // Check foreground requirement for canvas/camera/screen commands - if ( - command.startsWith(OpenClawCanvasCommand.NamespacePrefix) || - command.startsWith(OpenClawCanvasA2UICommand.NamespacePrefix) || - command.startsWith(OpenClawCameraCommand.NamespacePrefix) || - command.startsWith(OpenClawScreenCommand.NamespacePrefix) - ) { - if (!isForeground()) { - return GatewaySession.InvokeResult.error( - code = "NODE_BACKGROUND_UNAVAILABLE", - message = "NODE_BACKGROUND_UNAVAILABLE: canvas/camera/screen commands require foreground", - ) - } - } - - // Check camera enabled - if (command.startsWith(OpenClawCameraCommand.NamespacePrefix) && !cameraEnabled()) { - return GatewaySession.InvokeResult.error( - code = "CAMERA_DISABLED", - message = "CAMERA_DISABLED: enable Camera in Settings", - ) - } - - // Check location enabled - if (command.startsWith(OpenClawLocationCommand.NamespacePrefix) && !locationEnabled()) { - return GatewaySession.InvokeResult.error( - code = "LOCATION_DISABLED", - message = "LOCATION_DISABLED: enable Location in Settings", - ) - } - - return when (command) { - // Canvas commands - OpenClawCanvasCommand.Present.rawValue -> { - val url = CanvasController.parseNavigateUrl(paramsJson) - canvas.navigate(url) - GatewaySession.InvokeResult.ok(null) - } - OpenClawCanvasCommand.Hide.rawValue -> GatewaySession.InvokeResult.ok(null) - OpenClawCanvasCommand.Navigate.rawValue -> { - val url = CanvasController.parseNavigateUrl(paramsJson) - canvas.navigate(url) - GatewaySession.InvokeResult.ok(null) - } - OpenClawCanvasCommand.Eval.rawValue -> { - val js = - CanvasController.parseEvalJs(paramsJson) - ?: return GatewaySession.InvokeResult.error( - code = "INVALID_REQUEST", - message = "INVALID_REQUEST: javaScript required", - ) - val result = - try { - canvas.eval(js) - } catch (err: Throwable) { - return GatewaySession.InvokeResult.error( - code = "NODE_BACKGROUND_UNAVAILABLE", - message = "NODE_BACKGROUND_UNAVAILABLE: canvas unavailable", - ) - } - GatewaySession.InvokeResult.ok("""{"result":${result.toJsonString()}}""") - } - OpenClawCanvasCommand.Snapshot.rawValue -> { - val snapshotParams = CanvasController.parseSnapshotParams(paramsJson) - val base64 = - try { - canvas.snapshotBase64( - format = snapshotParams.format, - quality = snapshotParams.quality, - maxWidth = snapshotParams.maxWidth, - ) - } catch (err: Throwable) { - return GatewaySession.InvokeResult.error( - code = "NODE_BACKGROUND_UNAVAILABLE", - message = "NODE_BACKGROUND_UNAVAILABLE: canvas unavailable", - ) - } - GatewaySession.InvokeResult.ok("""{"format":"${snapshotParams.format.rawValue}","base64":"$base64"}""") - } - - // A2UI commands - OpenClawCanvasA2UICommand.Reset.rawValue -> { - val a2uiUrl = a2uiHandler.resolveA2uiHostUrl() - ?: return GatewaySession.InvokeResult.error( - code = "A2UI_HOST_NOT_CONFIGURED", - message = "A2UI_HOST_NOT_CONFIGURED: gateway did not advertise canvas host", - ) - val ready = a2uiHandler.ensureA2uiReady(a2uiUrl) - if (!ready) { - return GatewaySession.InvokeResult.error( - code = "A2UI_HOST_UNAVAILABLE", - message = "A2UI host not reachable", - ) - } - val res = canvas.eval(A2UIHandler.a2uiResetJS) - GatewaySession.InvokeResult.ok(res) - } - OpenClawCanvasA2UICommand.Push.rawValue, OpenClawCanvasA2UICommand.PushJSONL.rawValue -> { - val messages = - try { - a2uiHandler.decodeA2uiMessages(command, paramsJson) - } catch (err: Throwable) { - return GatewaySession.InvokeResult.error( - code = "INVALID_REQUEST", - message = err.message ?: "invalid A2UI payload" - ) - } - val a2uiUrl = a2uiHandler.resolveA2uiHostUrl() - ?: return GatewaySession.InvokeResult.error( - code = "A2UI_HOST_NOT_CONFIGURED", - message = "A2UI_HOST_NOT_CONFIGURED: gateway did not advertise canvas host", - ) - val ready = a2uiHandler.ensureA2uiReady(a2uiUrl) - if (!ready) { - return GatewaySession.InvokeResult.error( - code = "A2UI_HOST_UNAVAILABLE", - message = "A2UI host not reachable", - ) - } - val js = A2UIHandler.a2uiApplyMessagesJS(messages) - val res = canvas.eval(js) - GatewaySession.InvokeResult.ok(res) - } - - // Camera commands - OpenClawCameraCommand.Snap.rawValue -> cameraHandler.handleSnap(paramsJson) - OpenClawCameraCommand.Clip.rawValue -> cameraHandler.handleClip(paramsJson) - - // Location command - OpenClawLocationCommand.Get.rawValue -> locationHandler.handleLocationGet(paramsJson) - - // Screen command - OpenClawScreenCommand.Record.rawValue -> screenHandler.handleScreenRecord(paramsJson) - - // SMS command - OpenClawSmsCommand.Send.rawValue -> smsHandler.handleSmsSend(paramsJson) - - // Debug commands - "debug.ed25519" -> debugHandler.handleEd25519() - "debug.logs" -> debugHandler.handleLogs() - - // App update - "app.update" -> appUpdateHandler.handleUpdate(paramsJson) - - else -> - GatewaySession.InvokeResult.error( - code = "INVALID_REQUEST", - message = "INVALID_REQUEST: unknown command", - ) - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/JpegSizeLimiter.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/JpegSizeLimiter.kt deleted file mode 100644 index d6018467e66..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/JpegSizeLimiter.kt +++ /dev/null @@ -1,61 +0,0 @@ -package ai.openclaw.android.node - -import kotlin.math.max -import kotlin.math.min -import kotlin.math.roundToInt - -internal data class JpegSizeLimiterResult( - val bytes: ByteArray, - val width: Int, - val height: Int, - val quality: Int, -) - -internal object JpegSizeLimiter { - fun compressToLimit( - initialWidth: Int, - initialHeight: Int, - startQuality: Int, - maxBytes: Int, - minQuality: Int = 20, - minSize: Int = 256, - scaleStep: Double = 0.85, - maxScaleAttempts: Int = 6, - maxQualityAttempts: Int = 6, - encode: (width: Int, height: Int, quality: Int) -> ByteArray, - ): JpegSizeLimiterResult { - require(initialWidth > 0 && initialHeight > 0) { "Invalid image size" } - require(maxBytes > 0) { "Invalid maxBytes" } - - var width = initialWidth - var height = initialHeight - val clampedStartQuality = startQuality.coerceIn(minQuality, 100) - var best = JpegSizeLimiterResult(bytes = encode(width, height, clampedStartQuality), width = width, height = height, quality = clampedStartQuality) - if (best.bytes.size <= maxBytes) return best - - repeat(maxScaleAttempts) { - var quality = clampedStartQuality - repeat(maxQualityAttempts) { - val bytes = encode(width, height, quality) - best = JpegSizeLimiterResult(bytes = bytes, width = width, height = height, quality = quality) - if (bytes.size <= maxBytes) return best - if (quality <= minQuality) return@repeat - quality = max(minQuality, (quality * 0.75).roundToInt()) - } - - val minScale = (minSize.toDouble() / min(width, height).toDouble()).coerceAtMost(1.0) - val nextScale = max(scaleStep, minScale) - val nextWidth = max(minSize, (width * nextScale).roundToInt()) - val nextHeight = max(minSize, (height * nextScale).roundToInt()) - if (nextWidth == width && nextHeight == height) return@repeat - width = min(nextWidth, width) - height = min(nextHeight, height) - } - - if (best.bytes.size > maxBytes) { - throw IllegalStateException("CAMERA_TOO_LARGE: ${best.bytes.size} bytes > $maxBytes bytes") - } - - return best - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/LocationCaptureManager.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/LocationCaptureManager.kt deleted file mode 100644 index 87762e87fa9..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/LocationCaptureManager.kt +++ /dev/null @@ -1,117 +0,0 @@ -package ai.openclaw.android.node - -import android.Manifest -import android.content.Context -import android.content.pm.PackageManager -import android.location.Location -import android.location.LocationManager -import android.os.CancellationSignal -import androidx.core.content.ContextCompat -import java.time.Instant -import java.time.format.DateTimeFormatter -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import kotlinx.coroutines.withTimeout -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException -import kotlinx.coroutines.suspendCancellableCoroutine - -class LocationCaptureManager(private val context: Context) { - data class Payload(val payloadJson: String) - - suspend fun getLocation( - desiredProviders: List, - maxAgeMs: Long?, - timeoutMs: Long, - isPrecise: Boolean, - ): Payload = - withContext(Dispatchers.Main) { - val manager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager - if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && - !manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) - ) { - throw IllegalStateException("LOCATION_UNAVAILABLE: no location providers enabled") - } - - val cached = bestLastKnown(manager, desiredProviders, maxAgeMs) - val location = - cached ?: requestCurrent(manager, desiredProviders, timeoutMs) - - val timestamp = DateTimeFormatter.ISO_INSTANT.format(Instant.ofEpochMilli(location.time)) - val source = location.provider - val altitudeMeters = if (location.hasAltitude()) location.altitude else null - val speedMps = if (location.hasSpeed()) location.speed.toDouble() else null - val headingDeg = if (location.hasBearing()) location.bearing.toDouble() else null - Payload( - buildString { - append("{\"lat\":") - append(location.latitude) - append(",\"lon\":") - append(location.longitude) - append(",\"accuracyMeters\":") - append(location.accuracy.toDouble()) - if (altitudeMeters != null) append(",\"altitudeMeters\":").append(altitudeMeters) - if (speedMps != null) append(",\"speedMps\":").append(speedMps) - if (headingDeg != null) append(",\"headingDeg\":").append(headingDeg) - append(",\"timestamp\":\"").append(timestamp).append('"') - append(",\"isPrecise\":").append(isPrecise) - append(",\"source\":\"").append(source).append('"') - append('}') - }, - ) - } - - private fun bestLastKnown( - manager: LocationManager, - providers: List, - maxAgeMs: Long?, - ): Location? { - val fineOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == - PackageManager.PERMISSION_GRANTED - val coarseOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == - PackageManager.PERMISSION_GRANTED - if (!fineOk && !coarseOk) { - throw IllegalStateException("LOCATION_PERMISSION_REQUIRED: grant Location permission") - } - val now = System.currentTimeMillis() - val candidates = - providers.mapNotNull { provider -> manager.getLastKnownLocation(provider) } - val freshest = candidates.maxByOrNull { it.time } ?: return null - if (maxAgeMs != null && now - freshest.time > maxAgeMs) return null - return freshest - } - - private suspend fun requestCurrent( - manager: LocationManager, - providers: List, - timeoutMs: Long, - ): Location { - val fineOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == - PackageManager.PERMISSION_GRANTED - val coarseOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == - PackageManager.PERMISSION_GRANTED - if (!fineOk && !coarseOk) { - throw IllegalStateException("LOCATION_PERMISSION_REQUIRED: grant Location permission") - } - val resolved = - providers.firstOrNull { manager.isProviderEnabled(it) } - ?: throw IllegalStateException("LOCATION_UNAVAILABLE: no providers available") - return withTimeout(timeoutMs.coerceAtLeast(1)) { - suspendCancellableCoroutine { cont -> - val signal = CancellationSignal() - cont.invokeOnCancellation { signal.cancel() } - manager.getCurrentLocation(resolved, signal, context.mainExecutor) { location -> - if (location != null) { - cont.resume(location) - } else { - cont.resumeWithException(IllegalStateException("LOCATION_UNAVAILABLE: no fix")) - } - } - } - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/LocationHandler.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/LocationHandler.kt deleted file mode 100644 index c3f292f97a5..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/LocationHandler.kt +++ /dev/null @@ -1,116 +0,0 @@ -package ai.openclaw.android.node - -import android.Manifest -import android.content.Context -import android.content.pm.PackageManager -import android.location.LocationManager -import androidx.core.content.ContextCompat -import ai.openclaw.android.LocationMode -import ai.openclaw.android.gateway.GatewaySession -import kotlinx.coroutines.TimeoutCancellationException -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive - -class LocationHandler( - private val appContext: Context, - private val location: LocationCaptureManager, - private val json: Json, - private val isForeground: () -> Boolean, - private val locationMode: () -> LocationMode, - private val locationPreciseEnabled: () -> Boolean, -) { - fun hasFineLocationPermission(): Boolean { - return ( - ContextCompat.checkSelfPermission(appContext, Manifest.permission.ACCESS_FINE_LOCATION) == - PackageManager.PERMISSION_GRANTED - ) - } - - fun hasCoarseLocationPermission(): Boolean { - return ( - ContextCompat.checkSelfPermission(appContext, Manifest.permission.ACCESS_COARSE_LOCATION) == - PackageManager.PERMISSION_GRANTED - ) - } - - fun hasBackgroundLocationPermission(): Boolean { - return ( - ContextCompat.checkSelfPermission(appContext, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == - PackageManager.PERMISSION_GRANTED - ) - } - - suspend fun handleLocationGet(paramsJson: String?): GatewaySession.InvokeResult { - val mode = locationMode() - if (!isForeground() && mode != LocationMode.Always) { - return GatewaySession.InvokeResult.error( - code = "LOCATION_BACKGROUND_UNAVAILABLE", - message = "LOCATION_BACKGROUND_UNAVAILABLE: background location requires Always", - ) - } - if (!hasFineLocationPermission() && !hasCoarseLocationPermission()) { - return GatewaySession.InvokeResult.error( - code = "LOCATION_PERMISSION_REQUIRED", - message = "LOCATION_PERMISSION_REQUIRED: grant Location permission", - ) - } - if (!isForeground() && mode == LocationMode.Always && !hasBackgroundLocationPermission()) { - return GatewaySession.InvokeResult.error( - code = "LOCATION_PERMISSION_REQUIRED", - message = "LOCATION_PERMISSION_REQUIRED: enable Always in system Settings", - ) - } - val (maxAgeMs, timeoutMs, desiredAccuracy) = parseLocationParams(paramsJson) - val preciseEnabled = locationPreciseEnabled() - val accuracy = - when (desiredAccuracy) { - "precise" -> if (preciseEnabled && hasFineLocationPermission()) "precise" else "balanced" - "coarse" -> "coarse" - else -> if (preciseEnabled && hasFineLocationPermission()) "precise" else "balanced" - } - val providers = - when (accuracy) { - "precise" -> listOf(LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER) - "coarse" -> listOf(LocationManager.NETWORK_PROVIDER, LocationManager.GPS_PROVIDER) - else -> listOf(LocationManager.NETWORK_PROVIDER, LocationManager.GPS_PROVIDER) - } - try { - val payload = - location.getLocation( - desiredProviders = providers, - maxAgeMs = maxAgeMs, - timeoutMs = timeoutMs, - isPrecise = accuracy == "precise", - ) - return GatewaySession.InvokeResult.ok(payload.payloadJson) - } catch (err: TimeoutCancellationException) { - return GatewaySession.InvokeResult.error( - code = "LOCATION_TIMEOUT", - message = "LOCATION_TIMEOUT: no fix in time", - ) - } catch (err: Throwable) { - val message = err.message ?: "LOCATION_UNAVAILABLE: no fix" - return GatewaySession.InvokeResult.error(code = "LOCATION_UNAVAILABLE", message = message) - } - } - - private fun parseLocationParams(paramsJson: String?): Triple { - if (paramsJson.isNullOrBlank()) { - return Triple(null, 10_000L, null) - } - val root = - try { - json.parseToJsonElement(paramsJson).asObjectOrNull() - } catch (_: Throwable) { - null - } - val maxAgeMs = (root?.get("maxAgeMs") as? JsonPrimitive)?.content?.toLongOrNull() - val timeoutMs = - (root?.get("timeoutMs") as? JsonPrimitive)?.content?.toLongOrNull()?.coerceIn(1_000L, 60_000L) - ?: 10_000L - val desiredAccuracy = - (root?.get("desiredAccuracy") as? JsonPrimitive)?.content?.trim()?.lowercase() - return Triple(maxAgeMs, timeoutMs, desiredAccuracy) - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/NodeUtils.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/NodeUtils.kt deleted file mode 100644 index 8ba5ad276d5..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/NodeUtils.kt +++ /dev/null @@ -1,57 +0,0 @@ -package ai.openclaw.android.node - -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.JsonNull -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive - -const val DEFAULT_SEAM_COLOR_ARGB: Long = 0xFF4F7A9A - -data class Quad(val first: A, val second: B, val third: C, val fourth: D) - -fun String.toJsonString(): String { - val escaped = - this.replace("\\", "\\\\") - .replace("\"", "\\\"") - .replace("\n", "\\n") - .replace("\r", "\\r") - return "\"$escaped\"" -} - -fun JsonElement?.asObjectOrNull(): JsonObject? = this as? JsonObject - -fun JsonElement?.asStringOrNull(): String? = - when (this) { - is JsonNull -> null - is JsonPrimitive -> content - else -> null - } - -fun parseHexColorArgb(raw: String?): Long? { - val trimmed = raw?.trim().orEmpty() - if (trimmed.isEmpty()) return null - val hex = if (trimmed.startsWith("#")) trimmed.drop(1) else trimmed - if (hex.length != 6) return null - val rgb = hex.toLongOrNull(16) ?: return null - return 0xFF000000L or rgb -} - -fun invokeErrorFromThrowable(err: Throwable): Pair { - val raw = (err.message ?: "").trim() - if (raw.isEmpty()) return "UNAVAILABLE" to "UNAVAILABLE: error" - - val idx = raw.indexOf(':') - if (idx <= 0) return "UNAVAILABLE" to raw - val code = raw.substring(0, idx).trim().ifEmpty { "UNAVAILABLE" } - val message = raw.substring(idx + 1).trim().ifEmpty { raw } - return code to "$code: $message" -} - -fun normalizeMainKey(raw: String?): String? { - val trimmed = raw?.trim().orEmpty() - return if (trimmed.isEmpty()) null else trimmed -} - -fun isCanonicalMainSessionKey(key: String): Boolean { - return key == "main" -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/ScreenHandler.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/ScreenHandler.kt deleted file mode 100644 index c63d73f5e52..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/ScreenHandler.kt +++ /dev/null @@ -1,25 +0,0 @@ -package ai.openclaw.android.node - -import ai.openclaw.android.gateway.GatewaySession - -class ScreenHandler( - private val screenRecorder: ScreenRecordManager, - private val setScreenRecordActive: (Boolean) -> Unit, - private val invokeErrorFromThrowable: (Throwable) -> Pair, -) { - suspend fun handleScreenRecord(paramsJson: String?): GatewaySession.InvokeResult { - setScreenRecordActive(true) - try { - val res = - try { - screenRecorder.record(paramsJson) - } catch (err: Throwable) { - val (code, message) = invokeErrorFromThrowable(err) - return GatewaySession.InvokeResult.error(code = code, message = message) - } - return GatewaySession.InvokeResult.ok(res.payloadJson) - } finally { - setScreenRecordActive(false) - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/ScreenRecordManager.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/ScreenRecordManager.kt deleted file mode 100644 index 337a953866a..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/ScreenRecordManager.kt +++ /dev/null @@ -1,199 +0,0 @@ -package ai.openclaw.android.node - -import android.content.Context -import android.hardware.display.DisplayManager -import android.media.MediaRecorder -import android.media.projection.MediaProjectionManager -import android.os.Build -import android.util.Base64 -import ai.openclaw.android.ScreenCaptureRequester -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay -import kotlinx.coroutines.withContext -import java.io.File -import kotlin.math.roundToInt - -class ScreenRecordManager(private val context: Context) { - data class Payload(val payloadJson: String) - - @Volatile private var screenCaptureRequester: ScreenCaptureRequester? = null - @Volatile private var permissionRequester: ai.openclaw.android.PermissionRequester? = null - - fun attachScreenCaptureRequester(requester: ScreenCaptureRequester) { - screenCaptureRequester = requester - } - - fun attachPermissionRequester(requester: ai.openclaw.android.PermissionRequester) { - permissionRequester = requester - } - - suspend fun record(paramsJson: String?): Payload = - withContext(Dispatchers.Default) { - val requester = - screenCaptureRequester - ?: throw IllegalStateException( - "SCREEN_PERMISSION_REQUIRED: grant Screen Recording permission", - ) - - val durationMs = (parseDurationMs(paramsJson) ?: 10_000).coerceIn(250, 60_000) - val fps = (parseFps(paramsJson) ?: 10.0).coerceIn(1.0, 60.0) - val fpsInt = fps.roundToInt().coerceIn(1, 60) - val screenIndex = parseScreenIndex(paramsJson) - val includeAudio = parseIncludeAudio(paramsJson) ?: true - val format = parseString(paramsJson, key = "format") - if (format != null && format.lowercase() != "mp4") { - throw IllegalArgumentException("INVALID_REQUEST: screen format must be mp4") - } - if (screenIndex != null && screenIndex != 0) { - throw IllegalArgumentException("INVALID_REQUEST: screenIndex must be 0 on Android") - } - - val capture = requester.requestCapture() - ?: throw IllegalStateException( - "SCREEN_PERMISSION_REQUIRED: grant Screen Recording permission", - ) - - val mgr = - context.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager - val projection = mgr.getMediaProjection(capture.resultCode, capture.data) - ?: throw IllegalStateException("UNAVAILABLE: screen capture unavailable") - - val metrics = context.resources.displayMetrics - val width = metrics.widthPixels - val height = metrics.heightPixels - val densityDpi = metrics.densityDpi - - val file = File.createTempFile("openclaw-screen-", ".mp4") - if (includeAudio) ensureMicPermission() - - val recorder = createMediaRecorder() - var virtualDisplay: android.hardware.display.VirtualDisplay? = null - try { - if (includeAudio) { - recorder.setAudioSource(MediaRecorder.AudioSource.MIC) - } - recorder.setVideoSource(MediaRecorder.VideoSource.SURFACE) - recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) - recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264) - if (includeAudio) { - recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC) - recorder.setAudioChannels(1) - recorder.setAudioSamplingRate(44_100) - recorder.setAudioEncodingBitRate(96_000) - } - recorder.setVideoSize(width, height) - recorder.setVideoFrameRate(fpsInt) - recorder.setVideoEncodingBitRate(estimateBitrate(width, height, fpsInt)) - recorder.setOutputFile(file.absolutePath) - recorder.prepare() - - val surface = recorder.surface - virtualDisplay = - projection.createVirtualDisplay( - "openclaw-screen", - width, - height, - densityDpi, - DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, - surface, - null, - null, - ) - - recorder.start() - delay(durationMs.toLong()) - } finally { - try { - recorder.stop() - } catch (_: Throwable) { - // ignore - } - recorder.reset() - recorder.release() - virtualDisplay?.release() - projection.stop() - } - - val bytes = withContext(Dispatchers.IO) { file.readBytes() } - file.delete() - val base64 = Base64.encodeToString(bytes, Base64.NO_WRAP) - Payload( - """{"format":"mp4","base64":"$base64","durationMs":$durationMs,"fps":$fpsInt,"screenIndex":0,"hasAudio":$includeAudio}""", - ) - } - - private fun createMediaRecorder(): MediaRecorder = MediaRecorder(context) - - private suspend fun ensureMicPermission() { - val granted = - androidx.core.content.ContextCompat.checkSelfPermission( - context, - android.Manifest.permission.RECORD_AUDIO, - ) == android.content.pm.PackageManager.PERMISSION_GRANTED - if (granted) return - - val requester = - permissionRequester - ?: throw IllegalStateException("MIC_PERMISSION_REQUIRED: grant Microphone permission") - val results = requester.requestIfMissing(listOf(android.Manifest.permission.RECORD_AUDIO)) - if (results[android.Manifest.permission.RECORD_AUDIO] != true) { - throw IllegalStateException("MIC_PERMISSION_REQUIRED: grant Microphone permission") - } - } - - private fun parseDurationMs(paramsJson: String?): Int? = - parseNumber(paramsJson, key = "durationMs")?.toIntOrNull() - - private fun parseFps(paramsJson: String?): Double? = - parseNumber(paramsJson, key = "fps")?.toDoubleOrNull() - - private fun parseScreenIndex(paramsJson: String?): Int? = - parseNumber(paramsJson, key = "screenIndex")?.toIntOrNull() - - private fun parseIncludeAudio(paramsJson: String?): Boolean? { - val raw = paramsJson ?: return null - val key = "\"includeAudio\"" - val idx = raw.indexOf(key) - if (idx < 0) return null - val colon = raw.indexOf(':', idx + key.length) - if (colon < 0) return null - val tail = raw.substring(colon + 1).trimStart() - return when { - tail.startsWith("true") -> true - tail.startsWith("false") -> false - else -> null - } - } - - private fun parseNumber(paramsJson: String?, key: String): String? { - val raw = paramsJson ?: return null - val needle = "\"$key\"" - val idx = raw.indexOf(needle) - if (idx < 0) return null - val colon = raw.indexOf(':', idx + needle.length) - if (colon < 0) return null - val tail = raw.substring(colon + 1).trimStart() - return tail.takeWhile { it.isDigit() || it == '.' || it == '-' } - } - - private fun parseString(paramsJson: String?, key: String): String? { - val raw = paramsJson ?: return null - val needle = "\"$key\"" - val idx = raw.indexOf(needle) - if (idx < 0) return null - val colon = raw.indexOf(':', idx + needle.length) - if (colon < 0) return null - val tail = raw.substring(colon + 1).trimStart() - if (!tail.startsWith('\"')) return null - val rest = tail.drop(1) - val end = rest.indexOf('\"') - if (end < 0) return null - return rest.substring(0, end) - } - - private fun estimateBitrate(width: Int, height: Int, fps: Int): Int { - val pixels = width.toLong() * height.toLong() - val raw = (pixels * fps.toLong() * 2L).toInt() - return raw.coerceIn(1_000_000, 12_000_000) - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/SmsHandler.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/SmsHandler.kt deleted file mode 100644 index 30b7781009d..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/SmsHandler.kt +++ /dev/null @@ -1,19 +0,0 @@ -package ai.openclaw.android.node - -import ai.openclaw.android.gateway.GatewaySession - -class SmsHandler( - private val sms: SmsManager, -) { - suspend fun handleSmsSend(paramsJson: String?): GatewaySession.InvokeResult { - val res = sms.send(paramsJson) - if (res.ok) { - return GatewaySession.InvokeResult.ok(res.payloadJson) - } else { - val error = res.error ?: "SMS_SEND_FAILED" - val idx = error.indexOf(':') - val code = if (idx > 0) error.substring(0, idx).trim() else "SMS_SEND_FAILED" - return GatewaySession.InvokeResult.error(code = code, message = error) - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/node/SmsManager.kt b/apps/android/app/src/main/java/ai/openclaw/android/node/SmsManager.kt deleted file mode 100644 index d727bfd2763..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/node/SmsManager.kt +++ /dev/null @@ -1,230 +0,0 @@ -package ai.openclaw.android.node - -import android.Manifest -import android.content.Context -import android.content.pm.PackageManager -import android.telephony.SmsManager as AndroidSmsManager -import androidx.core.content.ContextCompat -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.encodeToString -import ai.openclaw.android.PermissionRequester - -/** - * Sends SMS messages via the Android SMS API. - * Requires SEND_SMS permission to be granted. - */ -class SmsManager(private val context: Context) { - - private val json = JsonConfig - @Volatile private var permissionRequester: PermissionRequester? = null - - data class SendResult( - val ok: Boolean, - val to: String, - val message: String?, - val error: String? = null, - val payloadJson: String, - ) - - internal data class ParsedParams( - val to: String, - val message: String, - ) - - internal sealed class ParseResult { - data class Ok(val params: ParsedParams) : ParseResult() - data class Error( - val error: String, - val to: String = "", - val message: String? = null, - ) : ParseResult() - } - - internal data class SendPlan( - val parts: List, - val useMultipart: Boolean, - ) - - companion object { - internal val JsonConfig = Json { ignoreUnknownKeys = true } - - internal fun parseParams(paramsJson: String?, json: Json = JsonConfig): ParseResult { - val params = paramsJson?.trim().orEmpty() - if (params.isEmpty()) { - return ParseResult.Error(error = "INVALID_REQUEST: paramsJSON required") - } - - val obj = try { - json.parseToJsonElement(params).jsonObject - } catch (_: Throwable) { - null - } - - if (obj == null) { - return ParseResult.Error(error = "INVALID_REQUEST: expected JSON object") - } - - val to = (obj["to"] as? JsonPrimitive)?.content?.trim().orEmpty() - val message = (obj["message"] as? JsonPrimitive)?.content.orEmpty() - - if (to.isEmpty()) { - return ParseResult.Error( - error = "INVALID_REQUEST: 'to' phone number required", - message = message, - ) - } - - if (message.isEmpty()) { - return ParseResult.Error( - error = "INVALID_REQUEST: 'message' text required", - to = to, - ) - } - - return ParseResult.Ok(ParsedParams(to = to, message = message)) - } - - internal fun buildSendPlan( - message: String, - divider: (String) -> List, - ): SendPlan { - val parts = divider(message).ifEmpty { listOf(message) } - return SendPlan(parts = parts, useMultipart = parts.size > 1) - } - - internal fun buildPayloadJson( - json: Json = JsonConfig, - ok: Boolean, - to: String, - error: String?, - ): String { - val payload = - mutableMapOf( - "ok" to JsonPrimitive(ok), - "to" to JsonPrimitive(to), - ) - if (!ok) { - payload["error"] = JsonPrimitive(error ?: "SMS_SEND_FAILED") - } - return json.encodeToString(JsonObject.serializer(), JsonObject(payload)) - } - } - - fun hasSmsPermission(): Boolean { - return ContextCompat.checkSelfPermission( - context, - Manifest.permission.SEND_SMS - ) == PackageManager.PERMISSION_GRANTED - } - - fun canSendSms(): Boolean { - return hasSmsPermission() && hasTelephonyFeature() - } - - fun hasTelephonyFeature(): Boolean { - return context.packageManager?.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) == true - } - - fun attachPermissionRequester(requester: PermissionRequester) { - permissionRequester = requester - } - - /** - * Send an SMS message. - * - * @param paramsJson JSON with "to" (phone number) and "message" (text) fields - * @return SendResult indicating success or failure - */ - suspend fun send(paramsJson: String?): SendResult { - if (!hasTelephonyFeature()) { - return errorResult( - error = "SMS_UNAVAILABLE: telephony not available", - ) - } - - if (!ensureSmsPermission()) { - return errorResult( - error = "SMS_PERMISSION_REQUIRED: grant SMS permission", - ) - } - - val parseResult = parseParams(paramsJson, json) - if (parseResult is ParseResult.Error) { - return errorResult( - error = parseResult.error, - to = parseResult.to, - message = parseResult.message, - ) - } - val params = (parseResult as ParseResult.Ok).params - - return try { - val smsManager = context.getSystemService(AndroidSmsManager::class.java) - ?: throw IllegalStateException("SMS_UNAVAILABLE: SmsManager not available") - - val plan = buildSendPlan(params.message) { smsManager.divideMessage(it) } - if (plan.useMultipart) { - smsManager.sendMultipartTextMessage( - params.to, // destination - null, // service center (null = default) - ArrayList(plan.parts), // message parts - null, // sent intents - null, // delivery intents - ) - } else { - smsManager.sendTextMessage( - params.to, // destination - null, // service center (null = default) - params.message,// message - null, // sent intent - null, // delivery intent - ) - } - - okResult(to = params.to, message = params.message) - } catch (e: SecurityException) { - errorResult( - error = "SMS_PERMISSION_REQUIRED: ${e.message}", - to = params.to, - message = params.message, - ) - } catch (e: Throwable) { - errorResult( - error = "SMS_SEND_FAILED: ${e.message ?: "unknown error"}", - to = params.to, - message = params.message, - ) - } - } - - private suspend fun ensureSmsPermission(): Boolean { - if (hasSmsPermission()) return true - val requester = permissionRequester ?: return false - val results = requester.requestIfMissing(listOf(Manifest.permission.SEND_SMS)) - return results[Manifest.permission.SEND_SMS] == true - } - - private fun okResult(to: String, message: String): SendResult { - return SendResult( - ok = true, - to = to, - message = message, - error = null, - payloadJson = buildPayloadJson(json = json, ok = true, to = to, error = null), - ) - } - - private fun errorResult(error: String, to: String = "", message: String? = null): SendResult { - return SendResult( - ok = false, - to = to, - message = message, - error = error, - payloadJson = buildPayloadJson(json = json, ok = false, to = to, error = error), - ) - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/protocol/OpenClawCanvasA2UIAction.kt b/apps/android/app/src/main/java/ai/openclaw/android/protocol/OpenClawCanvasA2UIAction.kt deleted file mode 100644 index 7e1a5bf127e..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/protocol/OpenClawCanvasA2UIAction.kt +++ /dev/null @@ -1,66 +0,0 @@ -package ai.openclaw.android.protocol - -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive - -object OpenClawCanvasA2UIAction { - fun extractActionName(userAction: JsonObject): String? { - val name = - (userAction["name"] as? JsonPrimitive) - ?.content - ?.trim() - .orEmpty() - if (name.isNotEmpty()) return name - val action = - (userAction["action"] as? JsonPrimitive) - ?.content - ?.trim() - .orEmpty() - return action.ifEmpty { null } - } - - fun sanitizeTagValue(value: String): String { - val trimmed = value.trim().ifEmpty { "-" } - val normalized = trimmed.replace(" ", "_") - val out = StringBuilder(normalized.length) - for (c in normalized) { - val ok = - c.isLetterOrDigit() || - c == '_' || - c == '-' || - c == '.' || - c == ':' - out.append(if (ok) c else '_') - } - return out.toString() - } - - fun formatAgentMessage( - actionName: String, - sessionKey: String, - surfaceId: String, - sourceComponentId: String, - host: String, - instanceId: String, - contextJson: String?, - ): String { - val ctxSuffix = contextJson?.takeIf { it.isNotBlank() }?.let { " ctx=$it" }.orEmpty() - return listOf( - "CANVAS_A2UI", - "action=${sanitizeTagValue(actionName)}", - "session=${sanitizeTagValue(sessionKey)}", - "surface=${sanitizeTagValue(surfaceId)}", - "component=${sanitizeTagValue(sourceComponentId)}", - "host=${sanitizeTagValue(host)}", - "instance=${sanitizeTagValue(instanceId)}$ctxSuffix", - "default=update_canvas", - ).joinToString(separator = " ") - } - - fun jsDispatchA2UIActionStatus(actionId: String, ok: Boolean, error: String?): String { - val err = (error ?: "").replace("\\", "\\\\").replace("\"", "\\\"") - val okLiteral = if (ok) "true" else "false" - val idEscaped = actionId.replace("\\", "\\\\").replace("\"", "\\\"") - return "window.dispatchEvent(new CustomEvent('openclaw:a2ui-action-status', { detail: { id: \"${idEscaped}\", ok: ${okLiteral}, error: \"${err}\" } }));" - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/protocol/OpenClawProtocolConstants.kt b/apps/android/app/src/main/java/ai/openclaw/android/protocol/OpenClawProtocolConstants.kt deleted file mode 100644 index ccca40c4c35..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/protocol/OpenClawProtocolConstants.kt +++ /dev/null @@ -1,71 +0,0 @@ -package ai.openclaw.android.protocol - -enum class OpenClawCapability(val rawValue: String) { - Canvas("canvas"), - Camera("camera"), - Screen("screen"), - Sms("sms"), - VoiceWake("voiceWake"), - Location("location"), -} - -enum class OpenClawCanvasCommand(val rawValue: String) { - Present("canvas.present"), - Hide("canvas.hide"), - Navigate("canvas.navigate"), - Eval("canvas.eval"), - Snapshot("canvas.snapshot"), - ; - - companion object { - const val NamespacePrefix: String = "canvas." - } -} - -enum class OpenClawCanvasA2UICommand(val rawValue: String) { - Push("canvas.a2ui.push"), - PushJSONL("canvas.a2ui.pushJSONL"), - Reset("canvas.a2ui.reset"), - ; - - companion object { - const val NamespacePrefix: String = "canvas.a2ui." - } -} - -enum class OpenClawCameraCommand(val rawValue: String) { - Snap("camera.snap"), - Clip("camera.clip"), - ; - - companion object { - const val NamespacePrefix: String = "camera." - } -} - -enum class OpenClawScreenCommand(val rawValue: String) { - Record("screen.record"), - ; - - companion object { - const val NamespacePrefix: String = "screen." - } -} - -enum class OpenClawSmsCommand(val rawValue: String) { - Send("sms.send"), - ; - - companion object { - const val NamespacePrefix: String = "sms." - } -} - -enum class OpenClawLocationCommand(val rawValue: String) { - Get("location.get"), - ; - - companion object { - const val NamespacePrefix: String = "location." - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/tools/ToolDisplay.kt b/apps/android/app/src/main/java/ai/openclaw/android/tools/ToolDisplay.kt deleted file mode 100644 index 1c5561767e6..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/tools/ToolDisplay.kt +++ /dev/null @@ -1,222 +0,0 @@ -package ai.openclaw.android.tools - -import android.content.Context -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonArray -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import kotlinx.serialization.json.contentOrNull - -@Serializable -private data class ToolDisplayActionSpec( - val label: String? = null, - val detailKeys: List? = null, -) - -@Serializable -private data class ToolDisplaySpec( - val emoji: String? = null, - val title: String? = null, - val label: String? = null, - val detailKeys: List? = null, - val actions: Map? = null, -) - -@Serializable -private data class ToolDisplayConfig( - val version: Int? = null, - val fallback: ToolDisplaySpec? = null, - val tools: Map? = null, -) - -data class ToolDisplaySummary( - val name: String, - val emoji: String, - val title: String, - val label: String, - val verb: String?, - val detail: String?, -) { - val detailLine: String? - get() { - val parts = mutableListOf() - if (!verb.isNullOrBlank()) parts.add(verb) - if (!detail.isNullOrBlank()) parts.add(detail) - return if (parts.isEmpty()) null else parts.joinToString(" · ") - } - - val summaryLine: String - get() = if (detailLine != null) "${emoji} ${label}: ${detailLine}" else "${emoji} ${label}" -} - -object ToolDisplayRegistry { - private const val CONFIG_ASSET = "tool-display.json" - - private val json = Json { ignoreUnknownKeys = true } - @Volatile private var cachedConfig: ToolDisplayConfig? = null - - fun resolve( - context: Context, - name: String?, - args: JsonObject?, - meta: String? = null, - ): ToolDisplaySummary { - val trimmedName = name?.trim().orEmpty().ifEmpty { "tool" } - val key = trimmedName.lowercase() - val config = loadConfig(context) - val spec = config.tools?.get(key) - val fallback = config.fallback - - val emoji = spec?.emoji ?: fallback?.emoji ?: "🧩" - val title = spec?.title ?: titleFromName(trimmedName) - val label = spec?.label ?: trimmedName - - val actionRaw = args?.get("action")?.asStringOrNull()?.trim() - val action = actionRaw?.takeIf { it.isNotEmpty() } - val actionSpec = action?.let { spec?.actions?.get(it) } - val verb = normalizeVerb(actionSpec?.label ?: action) - - var detail: String? = null - if (key == "read") { - detail = readDetail(args) - } else if (key == "write" || key == "edit" || key == "attach") { - detail = pathDetail(args) - } - - val detailKeys = actionSpec?.detailKeys ?: spec?.detailKeys ?: fallback?.detailKeys ?: emptyList() - if (detail == null) { - detail = firstValue(args, detailKeys) - } - - if (detail == null) { - detail = meta - } - - if (detail != null) { - detail = shortenHomeInString(detail) - } - - return ToolDisplaySummary( - name = trimmedName, - emoji = emoji, - title = title, - label = label, - verb = verb, - detail = detail, - ) - } - - private fun loadConfig(context: Context): ToolDisplayConfig { - val existing = cachedConfig - if (existing != null) return existing - return try { - val jsonString = context.assets.open(CONFIG_ASSET).bufferedReader().use { it.readText() } - val decoded = json.decodeFromString(ToolDisplayConfig.serializer(), jsonString) - cachedConfig = decoded - decoded - } catch (_: Throwable) { - val fallback = ToolDisplayConfig() - cachedConfig = fallback - fallback - } - } - - private fun titleFromName(name: String): String { - val cleaned = name.replace("_", " ").trim() - if (cleaned.isEmpty()) return "Tool" - return cleaned - .split(Regex("\\s+")) - .joinToString(" ") { part -> - val upper = part.uppercase() - if (part.length <= 2 && part == upper) part - else upper.firstOrNull()?.toString().orEmpty() + part.lowercase().drop(1) - } - } - - private fun normalizeVerb(value: String?): String? { - val trimmed = value?.trim().orEmpty() - if (trimmed.isEmpty()) return null - return trimmed.replace("_", " ") - } - - private fun readDetail(args: JsonObject?): String? { - val path = args?.get("path")?.asStringOrNull() ?: return null - val offset = args["offset"].asNumberOrNull() - val limit = args["limit"].asNumberOrNull() - return if (offset != null && limit != null) { - val end = offset + limit - "${path}:${offset.toInt()}-${end.toInt()}" - } else { - path - } - } - - private fun pathDetail(args: JsonObject?): String? { - return args?.get("path")?.asStringOrNull() - } - - private fun firstValue(args: JsonObject?, keys: List): String? { - for (key in keys) { - val value = valueForPath(args, key) - val rendered = renderValue(value) - if (!rendered.isNullOrBlank()) return rendered - } - return null - } - - private fun valueForPath(args: JsonObject?, path: String): JsonElement? { - var current: JsonElement? = args - for (segment in path.split(".")) { - if (segment.isBlank()) return null - val obj = current as? JsonObject ?: return null - current = obj[segment] - } - return current - } - - private fun renderValue(value: JsonElement?): String? { - if (value == null) return null - if (value is JsonPrimitive) { - if (value.isString) { - val trimmed = value.contentOrNull?.trim().orEmpty() - if (trimmed.isEmpty()) return null - val firstLine = trimmed.lineSequence().firstOrNull()?.trim().orEmpty() - if (firstLine.isEmpty()) return null - return if (firstLine.length > 160) "${firstLine.take(157)}…" else firstLine - } - val raw = value.contentOrNull?.trim().orEmpty() - raw.toBooleanStrictOrNull()?.let { return it.toString() } - raw.toLongOrNull()?.let { return it.toString() } - raw.toDoubleOrNull()?.let { return it.toString() } - } - if (value is JsonArray) { - val items = value.mapNotNull { renderValue(it) } - if (items.isEmpty()) return null - val preview = items.take(3).joinToString(", ") - return if (items.size > 3) "${preview}…" else preview - } - return null - } - - private fun shortenHomeInString(value: String): String { - val home = System.getProperty("user.home")?.takeIf { it.isNotBlank() } - ?: System.getenv("HOME")?.takeIf { it.isNotBlank() } - if (home.isNullOrEmpty()) return value - return value.replace(home, "~") - .replace(Regex("/Users/[^/]+"), "~") - .replace(Regex("/home/[^/]+"), "~") - } - - private fun JsonElement?.asStringOrNull(): String? { - val primitive = this as? JsonPrimitive ?: return null - return if (primitive.isString) primitive.contentOrNull else primitive.toString() - } - - private fun JsonElement?.asNumberOrNull(): Double? { - val primitive = this as? JsonPrimitive ?: return null - val raw = primitive.contentOrNull ?: return null - return raw.toDoubleOrNull() - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/CameraHudOverlay.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/CameraHudOverlay.kt deleted file mode 100644 index 21043d739b0..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/CameraHudOverlay.kt +++ /dev/null @@ -1,44 +0,0 @@ -package ai.openclaw.android.ui - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableFloatStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.graphics.Color -import kotlinx.coroutines.delay - -@Composable -fun CameraFlashOverlay( - token: Long, - modifier: Modifier = Modifier, -) { - Box(modifier = modifier.fillMaxSize()) { - CameraFlash(token = token) - } -} - -@Composable -private fun CameraFlash(token: Long) { - var alpha by remember { mutableFloatStateOf(0f) } - LaunchedEffect(token) { - if (token == 0L) return@LaunchedEffect - alpha = 0.85f - delay(110) - alpha = 0f - } - - Box( - modifier = - Modifier - .fillMaxSize() - .alpha(alpha) - .background(Color.White), - ) -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/ChatSheet.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/ChatSheet.kt deleted file mode 100644 index 85f20364c61..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/ChatSheet.kt +++ /dev/null @@ -1,10 +0,0 @@ -package ai.openclaw.android.ui - -import androidx.compose.runtime.Composable -import ai.openclaw.android.MainViewModel -import ai.openclaw.android.ui.chat.ChatSheetContent - -@Composable -fun ChatSheet(viewModel: MainViewModel) { - ChatSheetContent(viewModel = viewModel) -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/OpenClawTheme.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/OpenClawTheme.kt deleted file mode 100644 index aad743a6d7d..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/OpenClawTheme.kt +++ /dev/null @@ -1,32 +0,0 @@ -package ai.openclaw.android.ui - -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.dynamicDarkColorScheme -import androidx.compose.material3.dynamicLightColorScheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext - -@Composable -fun OpenClawTheme(content: @Composable () -> Unit) { - val context = LocalContext.current - val isDark = isSystemInDarkTheme() - val colorScheme = if (isDark) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) - - MaterialTheme(colorScheme = colorScheme, content = content) -} - -@Composable -fun overlayContainerColor(): Color { - val scheme = MaterialTheme.colorScheme - val isDark = isSystemInDarkTheme() - val base = if (isDark) scheme.surfaceContainerLow else scheme.surfaceContainerHigh - // Light mode: background stays dark (canvas), so clamp overlays away from pure-white glare. - return if (isDark) base else base.copy(alpha = 0.88f) -} - -@Composable -fun overlayIconColor(): Color { - return MaterialTheme.colorScheme.onSurfaceVariant -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/RootScreen.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/RootScreen.kt deleted file mode 100644 index af0cfe628ac..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/RootScreen.kt +++ /dev/null @@ -1,429 +0,0 @@ -package ai.openclaw.android.ui - -import android.annotation.SuppressLint -import android.Manifest -import android.content.pm.PackageManager -import android.graphics.Color -import android.util.Log -import android.view.View -import android.webkit.JavascriptInterface -import android.webkit.ConsoleMessage -import android.webkit.WebChromeClient -import android.webkit.WebView -import android.webkit.WebSettings -import android.webkit.WebResourceError -import android.webkit.WebResourceRequest -import android.webkit.WebResourceResponse -import android.webkit.WebViewClient -import androidx.activity.compose.rememberLauncherForActivityResult -import androidx.activity.result.contract.ActivityResultContracts -import androidx.webkit.WebSettingsCompat -import androidx.webkit.WebViewFeature -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.WindowInsetsSides -import androidx.compose.foundation.layout.only -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.safeDrawing -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.windowInsetsPadding -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.FilledTonalIconButton -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButtonDefaults -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.rememberModalBottomSheetState -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ScreenShare -import androidx.compose.material.icons.filled.ChatBubble -import androidx.compose.material.icons.filled.CheckCircle -import androidx.compose.material.icons.filled.Error -import androidx.compose.material.icons.filled.FiberManualRecord -import androidx.compose.material.icons.filled.PhotoCamera -import androidx.compose.material.icons.filled.RecordVoiceOver -import androidx.compose.material.icons.filled.Refresh -import androidx.compose.material.icons.filled.Report -import androidx.compose.material.icons.filled.Settings -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color as ComposeColor -import androidx.compose.ui.graphics.lerp -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.unit.dp -import androidx.compose.ui.viewinterop.AndroidView -import androidx.compose.ui.window.Popup -import androidx.compose.ui.window.PopupProperties -import androidx.core.content.ContextCompat -import ai.openclaw.android.CameraHudKind -import ai.openclaw.android.MainViewModel - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun RootScreen(viewModel: MainViewModel) { - var sheet by remember { mutableStateOf(null) } - val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) - val safeOverlayInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal) - val context = LocalContext.current - val serverName by viewModel.serverName.collectAsState() - val statusText by viewModel.statusText.collectAsState() - val cameraHud by viewModel.cameraHud.collectAsState() - val cameraFlashToken by viewModel.cameraFlashToken.collectAsState() - val screenRecordActive by viewModel.screenRecordActive.collectAsState() - val isForeground by viewModel.isForeground.collectAsState() - val voiceWakeStatusText by viewModel.voiceWakeStatusText.collectAsState() - val talkEnabled by viewModel.talkEnabled.collectAsState() - val talkStatusText by viewModel.talkStatusText.collectAsState() - val talkIsListening by viewModel.talkIsListening.collectAsState() - val talkIsSpeaking by viewModel.talkIsSpeaking.collectAsState() - val seamColorArgb by viewModel.seamColorArgb.collectAsState() - val seamColor = remember(seamColorArgb) { ComposeColor(seamColorArgb) } - val audioPermissionLauncher = - rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { granted -> - if (granted) viewModel.setTalkEnabled(true) - } - val activity = - remember(cameraHud, screenRecordActive, isForeground, statusText, voiceWakeStatusText) { - // Status pill owns transient activity state so it doesn't overlap the connection indicator. - if (!isForeground) { - return@remember StatusActivity( - title = "Foreground required", - icon = Icons.Default.Report, - contentDescription = "Foreground required", - ) - } - - val lowerStatus = statusText.lowercase() - if (lowerStatus.contains("repair")) { - return@remember StatusActivity( - title = "Repairing…", - icon = Icons.Default.Refresh, - contentDescription = "Repairing", - ) - } - if (lowerStatus.contains("pairing") || lowerStatus.contains("approval")) { - return@remember StatusActivity( - title = "Approval pending", - icon = Icons.Default.RecordVoiceOver, - contentDescription = "Approval pending", - ) - } - // Avoid duplicating the primary gateway status ("Connecting…") in the activity slot. - - if (screenRecordActive) { - return@remember StatusActivity( - title = "Recording screen…", - icon = Icons.AutoMirrored.Filled.ScreenShare, - contentDescription = "Recording screen", - tint = androidx.compose.ui.graphics.Color.Red, - ) - } - - cameraHud?.let { hud -> - return@remember when (hud.kind) { - CameraHudKind.Photo -> - StatusActivity( - title = hud.message, - icon = Icons.Default.PhotoCamera, - contentDescription = "Taking photo", - ) - CameraHudKind.Recording -> - StatusActivity( - title = hud.message, - icon = Icons.Default.FiberManualRecord, - contentDescription = "Recording", - tint = androidx.compose.ui.graphics.Color.Red, - ) - CameraHudKind.Success -> - StatusActivity( - title = hud.message, - icon = Icons.Default.CheckCircle, - contentDescription = "Capture finished", - ) - CameraHudKind.Error -> - StatusActivity( - title = hud.message, - icon = Icons.Default.Error, - contentDescription = "Capture failed", - tint = androidx.compose.ui.graphics.Color.Red, - ) - } - } - - if (voiceWakeStatusText.contains("Microphone permission", ignoreCase = true)) { - return@remember StatusActivity( - title = "Mic permission", - icon = Icons.Default.Error, - contentDescription = "Mic permission required", - ) - } - if (voiceWakeStatusText == "Paused") { - val suffix = if (!isForeground) " (background)" else "" - return@remember StatusActivity( - title = "Voice Wake paused$suffix", - icon = Icons.Default.RecordVoiceOver, - contentDescription = "Voice Wake paused", - ) - } - - null - } - - val gatewayState = - remember(serverName, statusText) { - when { - serverName != null -> GatewayState.Connected - statusText.contains("connecting", ignoreCase = true) || - statusText.contains("reconnecting", ignoreCase = true) -> GatewayState.Connecting - statusText.contains("error", ignoreCase = true) -> GatewayState.Error - else -> GatewayState.Disconnected - } - } - - val voiceEnabled = - ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == - PackageManager.PERMISSION_GRANTED - - Box(modifier = Modifier.fillMaxSize()) { - CanvasView(viewModel = viewModel, modifier = Modifier.fillMaxSize()) - } - - // Camera flash must be in a Popup to render above the WebView. - Popup(alignment = Alignment.Center, properties = PopupProperties(focusable = false)) { - CameraFlashOverlay(token = cameraFlashToken, modifier = Modifier.fillMaxSize()) - } - - // Keep the overlay buttons above the WebView canvas (AndroidView), otherwise they may not receive touches. - Popup(alignment = Alignment.TopStart, properties = PopupProperties(focusable = false)) { - StatusPill( - gateway = gatewayState, - voiceEnabled = voiceEnabled, - activity = activity, - onClick = { sheet = Sheet.Settings }, - modifier = Modifier.windowInsetsPadding(safeOverlayInsets).padding(start = 12.dp, top = 12.dp), - ) - } - - Popup(alignment = Alignment.TopEnd, properties = PopupProperties(focusable = false)) { - Column( - modifier = Modifier.windowInsetsPadding(safeOverlayInsets).padding(end = 12.dp, top = 12.dp), - verticalArrangement = Arrangement.spacedBy(10.dp), - horizontalAlignment = Alignment.End, - ) { - OverlayIconButton( - onClick = { sheet = Sheet.Chat }, - icon = { Icon(Icons.Default.ChatBubble, contentDescription = "Chat") }, - ) - - // Talk mode gets a dedicated side bubble instead of burying it in settings. - val baseOverlay = overlayContainerColor() - val talkContainer = - lerp( - baseOverlay, - seamColor.copy(alpha = baseOverlay.alpha), - if (talkEnabled) 0.35f else 0.22f, - ) - val talkContent = if (talkEnabled) seamColor else overlayIconColor() - OverlayIconButton( - onClick = { - val next = !talkEnabled - if (next) { - val micOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == - PackageManager.PERMISSION_GRANTED - if (!micOk) audioPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO) - viewModel.setTalkEnabled(true) - } else { - viewModel.setTalkEnabled(false) - } - }, - containerColor = talkContainer, - contentColor = talkContent, - icon = { - Icon( - Icons.Default.RecordVoiceOver, - contentDescription = "Talk Mode", - ) - }, - ) - - OverlayIconButton( - onClick = { sheet = Sheet.Settings }, - icon = { Icon(Icons.Default.Settings, contentDescription = "Settings") }, - ) - } - } - - if (talkEnabled) { - Popup(alignment = Alignment.Center, properties = PopupProperties(focusable = false)) { - TalkOrbOverlay( - seamColor = seamColor, - statusText = talkStatusText, - isListening = talkIsListening, - isSpeaking = talkIsSpeaking, - ) - } - } - - val currentSheet = sheet - if (currentSheet != null) { - ModalBottomSheet( - onDismissRequest = { sheet = null }, - sheetState = sheetState, - ) { - when (currentSheet) { - Sheet.Chat -> ChatSheet(viewModel = viewModel) - Sheet.Settings -> SettingsSheet(viewModel = viewModel) - } - } - } -} - -private enum class Sheet { - Chat, - Settings, -} - -@Composable -private fun OverlayIconButton( - onClick: () -> Unit, - icon: @Composable () -> Unit, - containerColor: ComposeColor? = null, - contentColor: ComposeColor? = null, -) { - FilledTonalIconButton( - onClick = onClick, - modifier = Modifier.size(44.dp), - colors = - IconButtonDefaults.filledTonalIconButtonColors( - containerColor = containerColor ?: overlayContainerColor(), - contentColor = contentColor ?: overlayIconColor(), - ), - ) { - icon() - } -} - -@SuppressLint("SetJavaScriptEnabled") -@Composable -private fun CanvasView(viewModel: MainViewModel, modifier: Modifier = Modifier) { - val context = LocalContext.current - val isDebuggable = (context.applicationInfo.flags and android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE) != 0 - AndroidView( - modifier = modifier, - factory = { - WebView(context).apply { - settings.javaScriptEnabled = true - // Some embedded web UIs (incl. the "background website") use localStorage/sessionStorage. - settings.domStorageEnabled = true - settings.mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE - if (WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING)) { - WebSettingsCompat.setAlgorithmicDarkeningAllowed(settings, false) - } else { - disableForceDarkIfSupported(settings) - } - if (isDebuggable) { - Log.d("OpenClawWebView", "userAgent: ${settings.userAgentString}") - } - isScrollContainer = true - overScrollMode = View.OVER_SCROLL_IF_CONTENT_SCROLLS - isVerticalScrollBarEnabled = true - isHorizontalScrollBarEnabled = true - webViewClient = - object : WebViewClient() { - override fun onReceivedError( - view: WebView, - request: WebResourceRequest, - error: WebResourceError, - ) { - if (!isDebuggable) return - if (!request.isForMainFrame) return - Log.e("OpenClawWebView", "onReceivedError: ${error.errorCode} ${error.description} ${request.url}") - } - - override fun onReceivedHttpError( - view: WebView, - request: WebResourceRequest, - errorResponse: WebResourceResponse, - ) { - if (!isDebuggable) return - if (!request.isForMainFrame) return - Log.e( - "OpenClawWebView", - "onReceivedHttpError: ${errorResponse.statusCode} ${errorResponse.reasonPhrase} ${request.url}", - ) - } - - override fun onPageFinished(view: WebView, url: String?) { - if (isDebuggable) { - Log.d("OpenClawWebView", "onPageFinished: $url") - } - viewModel.canvas.onPageFinished() - } - - override fun onRenderProcessGone( - view: WebView, - detail: android.webkit.RenderProcessGoneDetail, - ): Boolean { - if (isDebuggable) { - Log.e( - "OpenClawWebView", - "onRenderProcessGone didCrash=${detail.didCrash()} priorityAtExit=${detail.rendererPriorityAtExit()}", - ) - } - return true - } - } - webChromeClient = - object : WebChromeClient() { - override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean { - if (!isDebuggable) return false - val msg = consoleMessage ?: return false - Log.d( - "OpenClawWebView", - "console ${msg.messageLevel()} @ ${msg.sourceId()}:${msg.lineNumber()} ${msg.message()}", - ) - return false - } - } - // Use default layer/background; avoid forcing a black fill over WebView content. - - val a2uiBridge = - CanvasA2UIActionBridge { payload -> - viewModel.handleCanvasA2UIActionFromWebView(payload) - } - addJavascriptInterface(a2uiBridge, CanvasA2UIActionBridge.interfaceName) - viewModel.canvas.attach(this) - } - }, - ) -} - -private fun disableForceDarkIfSupported(settings: WebSettings) { - if (!WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) return - @Suppress("DEPRECATION") - WebSettingsCompat.setForceDark(settings, WebSettingsCompat.FORCE_DARK_OFF) -} - -private class CanvasA2UIActionBridge(private val onMessage: (String) -> Unit) { - @JavascriptInterface - fun postMessage(payload: String?) { - val msg = payload?.trim().orEmpty() - if (msg.isEmpty()) return - onMessage(msg) - } - - companion object { - const val interfaceName: String = "openclawCanvasA2UIAction" - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/SettingsSheet.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/SettingsSheet.kt deleted file mode 100644 index bb04c30108c..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/SettingsSheet.kt +++ /dev/null @@ -1,723 +0,0 @@ -package ai.openclaw.android.ui - -import android.Manifest -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.net.Uri -import android.os.Build -import android.provider.Settings -import androidx.activity.compose.rememberLauncherForActivityResult -import androidx.activity.result.contract.ActivityResultContracts -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.WindowInsetsSides -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.only -import androidx.compose.foundation.layout.safeDrawing -import androidx.compose.foundation.layout.windowInsetsPadding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.text.KeyboardActions -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ExpandLess -import androidx.compose.material.icons.filled.ExpandMore -import androidx.compose.material3.Button -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.ListItem -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.RadioButton -import androidx.compose.material3.Switch -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.focus.onFocusChanged -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.text.input.ImeAction -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.core.content.ContextCompat -import ai.openclaw.android.BuildConfig -import ai.openclaw.android.LocationMode -import ai.openclaw.android.MainViewModel -import ai.openclaw.android.NodeForegroundService -import ai.openclaw.android.VoiceWakeMode -import ai.openclaw.android.WakeWords - -@Composable -fun SettingsSheet(viewModel: MainViewModel) { - val context = LocalContext.current - val instanceId by viewModel.instanceId.collectAsState() - val displayName by viewModel.displayName.collectAsState() - val cameraEnabled by viewModel.cameraEnabled.collectAsState() - val locationMode by viewModel.locationMode.collectAsState() - val locationPreciseEnabled by viewModel.locationPreciseEnabled.collectAsState() - val preventSleep by viewModel.preventSleep.collectAsState() - val wakeWords by viewModel.wakeWords.collectAsState() - val voiceWakeMode by viewModel.voiceWakeMode.collectAsState() - val voiceWakeStatusText by viewModel.voiceWakeStatusText.collectAsState() - val isConnected by viewModel.isConnected.collectAsState() - val manualEnabled by viewModel.manualEnabled.collectAsState() - val manualHost by viewModel.manualHost.collectAsState() - val manualPort by viewModel.manualPort.collectAsState() - val manualTls by viewModel.manualTls.collectAsState() - val gatewayToken by viewModel.gatewayToken.collectAsState() - val canvasDebugStatusEnabled by viewModel.canvasDebugStatusEnabled.collectAsState() - val statusText by viewModel.statusText.collectAsState() - val serverName by viewModel.serverName.collectAsState() - val remoteAddress by viewModel.remoteAddress.collectAsState() - val gateways by viewModel.gateways.collectAsState() - val discoveryStatusText by viewModel.discoveryStatusText.collectAsState() - val pendingTrust by viewModel.pendingGatewayTrust.collectAsState() - - val listState = rememberLazyListState() - val (wakeWordsText, setWakeWordsText) = remember { mutableStateOf("") } - val (advancedExpanded, setAdvancedExpanded) = remember { mutableStateOf(false) } - val focusManager = LocalFocusManager.current - var wakeWordsHadFocus by remember { mutableStateOf(false) } - val deviceModel = - remember { - listOfNotNull(Build.MANUFACTURER, Build.MODEL) - .joinToString(" ") - .trim() - .ifEmpty { "Android" } - } - val appVersion = - remember { - val versionName = BuildConfig.VERSION_NAME.trim().ifEmpty { "dev" } - if (BuildConfig.DEBUG && !versionName.contains("dev", ignoreCase = true)) { - "$versionName-dev" - } else { - versionName - } - } - - if (pendingTrust != null) { - val prompt = pendingTrust!! - AlertDialog( - onDismissRequest = { viewModel.declineGatewayTrustPrompt() }, - title = { Text("Trust this gateway?") }, - text = { - Text( - "First-time TLS connection.\n\n" + - "Verify this SHA-256 fingerprint out-of-band before trusting:\n" + - prompt.fingerprintSha256, - ) - }, - confirmButton = { - TextButton(onClick = { viewModel.acceptGatewayTrustPrompt() }) { - Text("Trust and connect") - } - }, - dismissButton = { - TextButton(onClick = { viewModel.declineGatewayTrustPrompt() }) { - Text("Cancel") - } - }, - ) - } - - LaunchedEffect(wakeWords) { setWakeWordsText(wakeWords.joinToString(", ")) } - val commitWakeWords = { - val parsed = WakeWords.parseIfChanged(wakeWordsText, wakeWords) - if (parsed != null) { - viewModel.setWakeWords(parsed) - } - } - - val permissionLauncher = - rememberLauncherForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { perms -> - val cameraOk = perms[Manifest.permission.CAMERA] == true - viewModel.setCameraEnabled(cameraOk) - } - - var pendingLocationMode by remember { mutableStateOf(null) } - var pendingPreciseToggle by remember { mutableStateOf(false) } - - val locationPermissionLauncher = - rememberLauncherForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { perms -> - val fineOk = perms[Manifest.permission.ACCESS_FINE_LOCATION] == true - val coarseOk = perms[Manifest.permission.ACCESS_COARSE_LOCATION] == true - val granted = fineOk || coarseOk - val requestedMode = pendingLocationMode - pendingLocationMode = null - - if (pendingPreciseToggle) { - pendingPreciseToggle = false - viewModel.setLocationPreciseEnabled(fineOk) - return@rememberLauncherForActivityResult - } - - if (!granted) { - viewModel.setLocationMode(LocationMode.Off) - return@rememberLauncherForActivityResult - } - - if (requestedMode != null) { - viewModel.setLocationMode(requestedMode) - if (requestedMode == LocationMode.Always) { - val backgroundOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == - PackageManager.PERMISSION_GRANTED - if (!backgroundOk) { - openAppSettings(context) - } - } - } - } - - val audioPermissionLauncher = - rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { _ -> - // Status text is handled by NodeRuntime. - } - - val smsPermissionAvailable = - remember { - context.packageManager?.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) == true - } - var smsPermissionGranted by - remember { - mutableStateOf( - ContextCompat.checkSelfPermission(context, Manifest.permission.SEND_SMS) == - PackageManager.PERMISSION_GRANTED, - ) - } - val smsPermissionLauncher = - rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { granted -> - smsPermissionGranted = granted - viewModel.refreshGatewayConnection() - } - - fun setCameraEnabledChecked(checked: Boolean) { - if (!checked) { - viewModel.setCameraEnabled(false) - return - } - - val cameraOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == - PackageManager.PERMISSION_GRANTED - if (cameraOk) { - viewModel.setCameraEnabled(true) - } else { - permissionLauncher.launch(arrayOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)) - } - } - - fun requestLocationPermissions(targetMode: LocationMode) { - val fineOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == - PackageManager.PERMISSION_GRANTED - val coarseOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == - PackageManager.PERMISSION_GRANTED - if (fineOk || coarseOk) { - viewModel.setLocationMode(targetMode) - if (targetMode == LocationMode.Always) { - val backgroundOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == - PackageManager.PERMISSION_GRANTED - if (!backgroundOk) { - openAppSettings(context) - } - } - } else { - pendingLocationMode = targetMode - locationPermissionLauncher.launch( - arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), - ) - } - } - - fun setPreciseLocationChecked(checked: Boolean) { - if (!checked) { - viewModel.setLocationPreciseEnabled(false) - return - } - val fineOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == - PackageManager.PERMISSION_GRANTED - if (fineOk) { - viewModel.setLocationPreciseEnabled(true) - } else { - pendingPreciseToggle = true - locationPermissionLauncher.launch(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)) - } - } - - val visibleGateways = - if (isConnected && remoteAddress != null) { - gateways.filterNot { "${it.host}:${it.port}" == remoteAddress } - } else { - gateways - } - - val gatewayDiscoveryFooterText = - if (visibleGateways.isEmpty()) { - discoveryStatusText - } else if (isConnected) { - "Discovery active • ${visibleGateways.size} other gateway${if (visibleGateways.size == 1) "" else "s"} found" - } else { - "Discovery active • ${visibleGateways.size} gateway${if (visibleGateways.size == 1) "" else "s"} found" - } - - LazyColumn( - state = listState, - modifier = - Modifier - .fillMaxWidth() - .fillMaxHeight() - .imePadding() - .windowInsetsPadding(WindowInsets.safeDrawing.only(WindowInsetsSides.Bottom)), - contentPadding = PaddingValues(16.dp), - verticalArrangement = Arrangement.spacedBy(6.dp), - ) { - // Order parity: Node → Gateway → Voice → Camera → Messaging → Location → Screen. - item { Text("Node", style = MaterialTheme.typography.titleSmall) } - item { - OutlinedTextField( - value = displayName, - onValueChange = viewModel::setDisplayName, - label = { Text("Name") }, - modifier = Modifier.fillMaxWidth(), - ) - } - item { Text("Instance ID: $instanceId", color = MaterialTheme.colorScheme.onSurfaceVariant) } - item { Text("Device: $deviceModel", color = MaterialTheme.colorScheme.onSurfaceVariant) } - item { Text("Version: $appVersion", color = MaterialTheme.colorScheme.onSurfaceVariant) } - - item { HorizontalDivider() } - - // Gateway - item { Text("Gateway", style = MaterialTheme.typography.titleSmall) } - item { ListItem(headlineContent = { Text("Status") }, supportingContent = { Text(statusText) }) } - if (serverName != null) { - item { ListItem(headlineContent = { Text("Server") }, supportingContent = { Text(serverName!!) }) } - } - if (remoteAddress != null) { - item { ListItem(headlineContent = { Text("Address") }, supportingContent = { Text(remoteAddress!!) }) } - } - item { - // UI sanity: "Disconnect" only when we have an active remote. - if (isConnected && remoteAddress != null) { - Button( - onClick = { - viewModel.disconnect() - NodeForegroundService.stop(context) - }, - ) { - Text("Disconnect") - } - } - } - - item { HorizontalDivider() } - - if (!isConnected || visibleGateways.isNotEmpty()) { - item { - Text( - if (isConnected) "Other Gateways" else "Discovered Gateways", - style = MaterialTheme.typography.titleSmall, - ) - } - if (!isConnected && visibleGateways.isEmpty()) { - item { Text("No gateways found yet.", color = MaterialTheme.colorScheme.onSurfaceVariant) } - } else { - items(items = visibleGateways, key = { it.stableId }) { gateway -> - val detailLines = - buildList { - add("IP: ${gateway.host}:${gateway.port}") - gateway.lanHost?.let { add("LAN: $it") } - gateway.tailnetDns?.let { add("Tailnet: $it") } - if (gateway.gatewayPort != null || gateway.canvasPort != null) { - val gw = (gateway.gatewayPort ?: gateway.port).toString() - val canvas = gateway.canvasPort?.toString() ?: "—" - add("Ports: gw $gw · canvas $canvas") - } - } - ListItem( - headlineContent = { Text(gateway.name) }, - supportingContent = { - Column(verticalArrangement = Arrangement.spacedBy(2.dp)) { - detailLines.forEach { line -> - Text(line, color = MaterialTheme.colorScheme.onSurfaceVariant) - } - } - }, - trailingContent = { - Button( - onClick = { - NodeForegroundService.start(context) - viewModel.connect(gateway) - }, - ) { - Text("Connect") - } - }, - ) - } - } - item { - Text( - gatewayDiscoveryFooterText, - modifier = Modifier.fillMaxWidth(), - textAlign = TextAlign.Center, - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - } - - item { HorizontalDivider() } - - item { - ListItem( - headlineContent = { Text("Advanced") }, - supportingContent = { Text("Manual gateway connection") }, - trailingContent = { - Icon( - imageVector = if (advancedExpanded) Icons.Filled.ExpandLess else Icons.Filled.ExpandMore, - contentDescription = if (advancedExpanded) "Collapse" else "Expand", - ) - }, - modifier = - Modifier.clickable { - setAdvancedExpanded(!advancedExpanded) - }, - ) - } - item { - AnimatedVisibility(visible = advancedExpanded) { - Column(verticalArrangement = Arrangement.spacedBy(10.dp), modifier = Modifier.fillMaxWidth()) { - ListItem( - headlineContent = { Text("Use Manual Gateway") }, - supportingContent = { Text("Use this when discovery is blocked.") }, - trailingContent = { Switch(checked = manualEnabled, onCheckedChange = viewModel::setManualEnabled) }, - ) - - OutlinedTextField( - value = manualHost, - onValueChange = viewModel::setManualHost, - label = { Text("Host") }, - modifier = Modifier.fillMaxWidth(), - enabled = manualEnabled, - ) - OutlinedTextField( - value = manualPort.toString(), - onValueChange = { v -> viewModel.setManualPort(v.toIntOrNull() ?: 0) }, - label = { Text("Port") }, - modifier = Modifier.fillMaxWidth(), - enabled = manualEnabled, - ) - OutlinedTextField( - value = gatewayToken, - onValueChange = viewModel::setGatewayToken, - label = { Text("Gateway Token") }, - modifier = Modifier.fillMaxWidth(), - enabled = manualEnabled, - singleLine = true, - ) - ListItem( - headlineContent = { Text("Require TLS") }, - supportingContent = { Text("Pin the gateway certificate on first connect.") }, - trailingContent = { Switch(checked = manualTls, onCheckedChange = viewModel::setManualTls, enabled = manualEnabled) }, - modifier = Modifier.alpha(if (manualEnabled) 1f else 0.5f), - ) - - val hostOk = manualHost.trim().isNotEmpty() - val portOk = manualPort in 1..65535 - Button( - onClick = { - NodeForegroundService.start(context) - viewModel.connectManual() - }, - enabled = manualEnabled && hostOk && portOk, - ) { - Text("Connect (Manual)") - } - } - } - } - - item { HorizontalDivider() } - - // Voice - item { Text("Voice", style = MaterialTheme.typography.titleSmall) } - item { - val enabled = voiceWakeMode != VoiceWakeMode.Off - ListItem( - headlineContent = { Text("Voice Wake") }, - supportingContent = { Text(voiceWakeStatusText) }, - trailingContent = { - Switch( - checked = enabled, - onCheckedChange = { on -> - if (on) { - val micOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == - PackageManager.PERMISSION_GRANTED - if (!micOk) audioPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO) - viewModel.setVoiceWakeMode(VoiceWakeMode.Foreground) - } else { - viewModel.setVoiceWakeMode(VoiceWakeMode.Off) - } - }, - ) - }, - ) - } - item { - AnimatedVisibility(visible = voiceWakeMode != VoiceWakeMode.Off) { - Column(verticalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier.fillMaxWidth()) { - ListItem( - headlineContent = { Text("Foreground Only") }, - supportingContent = { Text("Listens only while OpenClaw is open.") }, - trailingContent = { - RadioButton( - selected = voiceWakeMode == VoiceWakeMode.Foreground, - onClick = { - val micOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == - PackageManager.PERMISSION_GRANTED - if (!micOk) audioPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO) - viewModel.setVoiceWakeMode(VoiceWakeMode.Foreground) - }, - ) - }, - ) - ListItem( - headlineContent = { Text("Always") }, - supportingContent = { Text("Keeps listening in the background (shows a persistent notification).") }, - trailingContent = { - RadioButton( - selected = voiceWakeMode == VoiceWakeMode.Always, - onClick = { - val micOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == - PackageManager.PERMISSION_GRANTED - if (!micOk) audioPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO) - viewModel.setVoiceWakeMode(VoiceWakeMode.Always) - }, - ) - }, - ) - } - } - } - item { - OutlinedTextField( - value = wakeWordsText, - onValueChange = setWakeWordsText, - label = { Text("Wake Words (comma-separated)") }, - modifier = - Modifier.fillMaxWidth().onFocusChanged { focusState -> - if (focusState.isFocused) { - wakeWordsHadFocus = true - } else if (wakeWordsHadFocus) { - wakeWordsHadFocus = false - commitWakeWords() - } - }, - singleLine = true, - keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), - keyboardActions = - KeyboardActions( - onDone = { - commitWakeWords() - focusManager.clearFocus() - }, - ), - ) - } - item { Button(onClick = viewModel::resetWakeWordsDefaults) { Text("Reset defaults") } } - item { - Text( - if (isConnected) { - "Any node can edit wake words. Changes sync via the gateway." - } else { - "Connect to a gateway to sync wake words globally." - }, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - - item { HorizontalDivider() } - - // Camera - item { Text("Camera", style = MaterialTheme.typography.titleSmall) } - item { - ListItem( - headlineContent = { Text("Allow Camera") }, - supportingContent = { Text("Allows the gateway to request photos or short video clips (foreground only).") }, - trailingContent = { Switch(checked = cameraEnabled, onCheckedChange = ::setCameraEnabledChecked) }, - ) - } - item { - Text( - "Tip: grant Microphone permission for video clips with audio.", - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - - item { HorizontalDivider() } - - // Messaging - item { Text("Messaging", style = MaterialTheme.typography.titleSmall) } - item { - val buttonLabel = - when { - !smsPermissionAvailable -> "Unavailable" - smsPermissionGranted -> "Manage" - else -> "Grant" - } - ListItem( - headlineContent = { Text("SMS Permission") }, - supportingContent = { - Text( - if (smsPermissionAvailable) { - "Allow the gateway to send SMS from this device." - } else { - "SMS requires a device with telephony hardware." - }, - ) - }, - trailingContent = { - Button( - onClick = { - if (!smsPermissionAvailable) return@Button - if (smsPermissionGranted) { - openAppSettings(context) - } else { - smsPermissionLauncher.launch(Manifest.permission.SEND_SMS) - } - }, - enabled = smsPermissionAvailable, - ) { - Text(buttonLabel) - } - }, - ) - } - - item { HorizontalDivider() } - - // Location - item { Text("Location", style = MaterialTheme.typography.titleSmall) } - item { - Column(verticalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier.fillMaxWidth()) { - ListItem( - headlineContent = { Text("Off") }, - supportingContent = { Text("Disable location sharing.") }, - trailingContent = { - RadioButton( - selected = locationMode == LocationMode.Off, - onClick = { viewModel.setLocationMode(LocationMode.Off) }, - ) - }, - ) - ListItem( - headlineContent = { Text("While Using") }, - supportingContent = { Text("Only while OpenClaw is open.") }, - trailingContent = { - RadioButton( - selected = locationMode == LocationMode.WhileUsing, - onClick = { requestLocationPermissions(LocationMode.WhileUsing) }, - ) - }, - ) - ListItem( - headlineContent = { Text("Always") }, - supportingContent = { Text("Allow background location (requires system permission).") }, - trailingContent = { - RadioButton( - selected = locationMode == LocationMode.Always, - onClick = { requestLocationPermissions(LocationMode.Always) }, - ) - }, - ) - } - } - item { - ListItem( - headlineContent = { Text("Precise Location") }, - supportingContent = { Text("Use precise GPS when available.") }, - trailingContent = { - Switch( - checked = locationPreciseEnabled, - onCheckedChange = ::setPreciseLocationChecked, - enabled = locationMode != LocationMode.Off, - ) - }, - ) - } - item { - Text( - "Always may require Android Settings to allow background location.", - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - - item { HorizontalDivider() } - - // Screen - item { Text("Screen", style = MaterialTheme.typography.titleSmall) } - item { - ListItem( - headlineContent = { Text("Prevent Sleep") }, - supportingContent = { Text("Keeps the screen awake while OpenClaw is open.") }, - trailingContent = { Switch(checked = preventSleep, onCheckedChange = viewModel::setPreventSleep) }, - ) - } - - item { HorizontalDivider() } - - // Debug - item { Text("Debug", style = MaterialTheme.typography.titleSmall) } - item { - ListItem( - headlineContent = { Text("Debug Canvas Status") }, - supportingContent = { Text("Show status text in the canvas when debug is enabled.") }, - trailingContent = { - Switch( - checked = canvasDebugStatusEnabled, - onCheckedChange = viewModel::setCanvasDebugStatusEnabled, - ) - }, - ) - } - - item { Spacer(modifier = Modifier.height(20.dp)) } - } -} - -private fun openAppSettings(context: Context) { - val intent = - Intent( - Settings.ACTION_APPLICATION_DETAILS_SETTINGS, - Uri.fromParts("package", context.packageName, null), - ) - context.startActivity(intent) -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/StatusPill.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/StatusPill.kt deleted file mode 100644 index d608fc38a7b..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/StatusPill.kt +++ /dev/null @@ -1,114 +0,0 @@ -package ai.openclaw.android.ui - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Mic -import androidx.compose.material.icons.filled.MicOff -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.material3.VerticalDivider -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.dp - -@Composable -fun StatusPill( - gateway: GatewayState, - voiceEnabled: Boolean, - onClick: () -> Unit, - modifier: Modifier = Modifier, - activity: StatusActivity? = null, -) { - Surface( - onClick = onClick, - modifier = modifier, - shape = RoundedCornerShape(14.dp), - color = overlayContainerColor(), - tonalElevation = 3.dp, - shadowElevation = 0.dp, - ) { - Row( - modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp), - horizontalArrangement = Arrangement.spacedBy(10.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Row(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically) { - Surface( - modifier = Modifier.size(9.dp), - shape = CircleShape, - color = gateway.color, - ) {} - - Text( - text = gateway.title, - style = MaterialTheme.typography.labelLarge, - ) - } - - VerticalDivider( - modifier = Modifier.height(14.dp).alpha(0.35f), - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - - if (activity != null) { - Row( - horizontalArrangement = Arrangement.spacedBy(6.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Icon( - imageVector = activity.icon, - contentDescription = activity.contentDescription, - tint = activity.tint ?: overlayIconColor(), - modifier = Modifier.size(18.dp), - ) - Text( - text = activity.title, - style = MaterialTheme.typography.labelLarge, - maxLines = 1, - ) - } - } else { - Icon( - imageVector = if (voiceEnabled) Icons.Default.Mic else Icons.Default.MicOff, - contentDescription = if (voiceEnabled) "Voice enabled" else "Voice disabled", - tint = - if (voiceEnabled) { - overlayIconColor() - } else { - MaterialTheme.colorScheme.onSurfaceVariant - }, - modifier = Modifier.size(18.dp), - ) - } - - Spacer(modifier = Modifier.width(2.dp)) - } - } -} - -data class StatusActivity( - val title: String, - val icon: androidx.compose.ui.graphics.vector.ImageVector, - val contentDescription: String, - val tint: Color? = null, -) - -enum class GatewayState(val title: String, val color: Color) { - Connected("Connected", Color(0xFF2ECC71)), - Connecting("Connecting…", Color(0xFFF1C40F)), - Error("Error", Color(0xFFE74C3C)), - Disconnected("Offline", Color(0xFF9E9E9E)), -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/TalkOrbOverlay.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/TalkOrbOverlay.kt deleted file mode 100644 index f89b298d1f7..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/TalkOrbOverlay.kt +++ /dev/null @@ -1,134 +0,0 @@ -package ai.openclaw.android.ui - -import androidx.compose.animation.core.LinearEasing -import androidx.compose.animation.core.RepeatMode -import androidx.compose.animation.core.animateFloat -import androidx.compose.animation.core.infiniteRepeatable -import androidx.compose.animation.core.rememberInfiniteTransition -import androidx.compose.animation.core.tween -import androidx.compose.foundation.Canvas -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.drawscope.Stroke -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp - -@Composable -fun TalkOrbOverlay( - seamColor: Color, - statusText: String, - isListening: Boolean, - isSpeaking: Boolean, - modifier: Modifier = Modifier, -) { - val transition = rememberInfiniteTransition(label = "talk-orb") - val t by - transition.animateFloat( - initialValue = 0f, - targetValue = 1f, - animationSpec = - infiniteRepeatable( - animation = tween(durationMillis = 1500, easing = LinearEasing), - repeatMode = RepeatMode.Restart, - ), - label = "pulse", - ) - - val trimmed = statusText.trim() - val showStatus = trimmed.isNotEmpty() && trimmed != "Off" - val phase = - when { - isSpeaking -> "Speaking" - isListening -> "Listening" - else -> "Thinking" - } - - Column( - modifier = modifier.padding(24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(12.dp), - ) { - Box(contentAlignment = Alignment.Center) { - Canvas(modifier = Modifier.size(360.dp)) { - val center = this.center - val baseRadius = size.minDimension * 0.30f - - val ring1 = 1.05f + (t * 0.25f) - val ring2 = 1.20f + (t * 0.55f) - val ringAlpha1 = (1f - t) * 0.34f - val ringAlpha2 = (1f - t) * 0.22f - - drawCircle( - color = seamColor.copy(alpha = ringAlpha1), - radius = baseRadius * ring1, - center = center, - style = Stroke(width = 3.dp.toPx()), - ) - drawCircle( - color = seamColor.copy(alpha = ringAlpha2), - radius = baseRadius * ring2, - center = center, - style = Stroke(width = 3.dp.toPx()), - ) - - drawCircle( - brush = - Brush.radialGradient( - colors = - listOf( - seamColor.copy(alpha = 0.92f), - seamColor.copy(alpha = 0.40f), - Color.Black.copy(alpha = 0.56f), - ), - center = center, - radius = baseRadius * 1.35f, - ), - radius = baseRadius, - center = center, - ) - - drawCircle( - color = seamColor.copy(alpha = 0.34f), - radius = baseRadius, - center = center, - style = Stroke(width = 1.dp.toPx()), - ) - } - } - - if (showStatus) { - Surface( - color = Color.Black.copy(alpha = 0.40f), - shape = CircleShape, - ) { - Text( - text = trimmed, - modifier = Modifier.padding(horizontal = 14.dp, vertical = 8.dp), - color = Color.White.copy(alpha = 0.92f), - style = MaterialTheme.typography.labelLarge, - fontWeight = FontWeight.SemiBold, - ) - } - } else { - Text( - text = phase, - color = Color.White.copy(alpha = 0.80f), - style = MaterialTheme.typography.labelLarge, - fontWeight = FontWeight.SemiBold, - ) - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatComposer.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatComposer.kt deleted file mode 100644 index 07ba769697d..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatComposer.kt +++ /dev/null @@ -1,285 +0,0 @@ -package ai.openclaw.android.ui.chat - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.horizontalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowUpward -import androidx.compose.material.icons.filled.AttachFile -import androidx.compose.material.icons.filled.Refresh -import androidx.compose.material.icons.filled.Stop -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.DropdownMenu -import androidx.compose.material3.DropdownMenuItem -import androidx.compose.material3.FilledTonalButton -import androidx.compose.material3.FilledTonalIconButton -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButtonDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import ai.openclaw.android.chat.ChatSessionEntry - -@Composable -fun ChatComposer( - sessionKey: String, - sessions: List, - mainSessionKey: String, - healthOk: Boolean, - thinkingLevel: String, - pendingRunCount: Int, - errorText: String?, - attachments: List, - onPickImages: () -> Unit, - onRemoveAttachment: (id: String) -> Unit, - onSetThinkingLevel: (level: String) -> Unit, - onSelectSession: (sessionKey: String) -> Unit, - onRefresh: () -> Unit, - onAbort: () -> Unit, - onSend: (text: String) -> Unit, -) { - var input by rememberSaveable { mutableStateOf("") } - var showThinkingMenu by remember { mutableStateOf(false) } - var showSessionMenu by remember { mutableStateOf(false) } - - val sessionOptions = resolveSessionChoices(sessionKey, sessions, mainSessionKey = mainSessionKey) - val currentSessionLabel = friendlySessionName( - sessionOptions.firstOrNull { it.key == sessionKey }?.displayName ?: sessionKey - ) - - val canSend = pendingRunCount == 0 && (input.trim().isNotEmpty() || attachments.isNotEmpty()) && healthOk - - Surface( - shape = MaterialTheme.shapes.large, - color = MaterialTheme.colorScheme.surfaceContainer, - tonalElevation = 0.dp, - shadowElevation = 0.dp, - ) { - Column(modifier = Modifier.padding(10.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) { - Row( - modifier = Modifier.fillMaxWidth().horizontalScroll(rememberScrollState()), - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Box { - FilledTonalButton( - onClick = { showSessionMenu = true }, - contentPadding = ButtonDefaults.ContentPadding, - ) { - Text(currentSessionLabel, maxLines = 1, overflow = TextOverflow.Ellipsis) - } - - DropdownMenu(expanded = showSessionMenu, onDismissRequest = { showSessionMenu = false }) { - for (entry in sessionOptions) { - DropdownMenuItem( - text = { Text(friendlySessionName(entry.displayName ?: entry.key)) }, - onClick = { - onSelectSession(entry.key) - showSessionMenu = false - }, - trailingIcon = { - if (entry.key == sessionKey) { - Text("✓") - } else { - Spacer(modifier = Modifier.width(10.dp)) - } - }, - ) - } - } - } - - Box { - FilledTonalButton( - onClick = { showThinkingMenu = true }, - contentPadding = ButtonDefaults.ContentPadding, - ) { - Text("🧠 ${thinkingLabel(thinkingLevel)}", maxLines = 1) - } - - DropdownMenu(expanded = showThinkingMenu, onDismissRequest = { showThinkingMenu = false }) { - ThinkingMenuItem("off", thinkingLevel, onSetThinkingLevel) { showThinkingMenu = false } - ThinkingMenuItem("low", thinkingLevel, onSetThinkingLevel) { showThinkingMenu = false } - ThinkingMenuItem("medium", thinkingLevel, onSetThinkingLevel) { showThinkingMenu = false } - ThinkingMenuItem("high", thinkingLevel, onSetThinkingLevel) { showThinkingMenu = false } - } - } - - FilledTonalIconButton(onClick = onRefresh, modifier = Modifier.size(42.dp)) { - Icon(Icons.Default.Refresh, contentDescription = "Refresh") - } - - FilledTonalIconButton(onClick = onPickImages, modifier = Modifier.size(42.dp)) { - Icon(Icons.Default.AttachFile, contentDescription = "Add image") - } - } - - if (attachments.isNotEmpty()) { - AttachmentsStrip(attachments = attachments, onRemoveAttachment = onRemoveAttachment) - } - - OutlinedTextField( - value = input, - onValueChange = { input = it }, - modifier = Modifier.fillMaxWidth(), - placeholder = { Text("Message OpenClaw…") }, - minLines = 2, - maxLines = 6, - ) - - Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { - ConnectionPill(sessionLabel = currentSessionLabel, healthOk = healthOk) - Spacer(modifier = Modifier.weight(1f)) - - if (pendingRunCount > 0) { - FilledTonalIconButton( - onClick = onAbort, - colors = - IconButtonDefaults.filledTonalIconButtonColors( - containerColor = Color(0x33E74C3C), - contentColor = Color(0xFFE74C3C), - ), - ) { - Icon(Icons.Default.Stop, contentDescription = "Abort") - } - } else { - FilledTonalIconButton(onClick = { - val text = input - input = "" - onSend(text) - }, enabled = canSend) { - Icon(Icons.Default.ArrowUpward, contentDescription = "Send") - } - } - } - - if (!errorText.isNullOrBlank()) { - Text( - text = errorText, - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.error, - maxLines = 2, - ) - } - } - } -} - -@Composable -private fun ConnectionPill(sessionLabel: String, healthOk: Boolean) { - Surface( - shape = RoundedCornerShape(999.dp), - color = MaterialTheme.colorScheme.surfaceContainerHighest, - ) { - Row( - modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Surface( - modifier = Modifier.size(7.dp), - shape = androidx.compose.foundation.shape.CircleShape, - color = if (healthOk) Color(0xFF2ECC71) else Color(0xFFF39C12), - ) {} - Text(sessionLabel, style = MaterialTheme.typography.labelSmall) - Text( - if (healthOk) "Connected" else "Connecting…", - style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - } -} - -@Composable -private fun ThinkingMenuItem( - value: String, - current: String, - onSet: (String) -> Unit, - onDismiss: () -> Unit, -) { - DropdownMenuItem( - text = { Text(thinkingLabel(value)) }, - onClick = { - onSet(value) - onDismiss() - }, - trailingIcon = { - if (value == current.trim().lowercase()) { - Text("✓") - } else { - Spacer(modifier = Modifier.width(10.dp)) - } - }, - ) -} - -private fun thinkingLabel(raw: String): String { - return when (raw.trim().lowercase()) { - "low" -> "Low" - "medium" -> "Medium" - "high" -> "High" - else -> "Off" - } -} - -@Composable -private fun AttachmentsStrip( - attachments: List, - onRemoveAttachment: (id: String) -> Unit, -) { - Row( - modifier = Modifier.fillMaxWidth().horizontalScroll(rememberScrollState()), - horizontalArrangement = Arrangement.spacedBy(8.dp), - ) { - for (att in attachments) { - AttachmentChip( - fileName = att.fileName, - onRemove = { onRemoveAttachment(att.id) }, - ) - } - } -} - -@Composable -private fun AttachmentChip(fileName: String, onRemove: () -> Unit) { - Surface( - shape = RoundedCornerShape(999.dp), - color = MaterialTheme.colorScheme.primary.copy(alpha = 0.10f), - ) { - Row( - modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp), - ) { - Text(text = fileName, style = MaterialTheme.typography.bodySmall, maxLines = 1) - FilledTonalIconButton( - onClick = onRemove, - modifier = Modifier.size(30.dp), - ) { - Text("×") - } - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatMarkdown.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatMarkdown.kt deleted file mode 100644 index 77dba2275a4..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatMarkdown.kt +++ /dev/null @@ -1,215 +0,0 @@ -package ai.openclaw.android.ui.chat - -import android.graphics.BitmapFactory -import android.util.Base64 -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.text.selection.SelectionContainer -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.asImageBitmap -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.withStyle -import androidx.compose.ui.unit.dp -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext - -@Composable -fun ChatMarkdown(text: String, textColor: Color) { - val blocks = remember(text) { splitMarkdown(text) } - val inlineCodeBg = MaterialTheme.colorScheme.surfaceContainerLow - - Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { - for (b in blocks) { - when (b) { - is ChatMarkdownBlock.Text -> { - val trimmed = b.text.trimEnd() - if (trimmed.isEmpty()) continue - Text( - text = parseInlineMarkdown(trimmed, inlineCodeBg = inlineCodeBg), - style = MaterialTheme.typography.bodyMedium, - color = textColor, - ) - } - is ChatMarkdownBlock.Code -> { - SelectionContainer(modifier = Modifier.fillMaxWidth()) { - ChatCodeBlock(code = b.code, language = b.language) - } - } - is ChatMarkdownBlock.InlineImage -> { - InlineBase64Image(base64 = b.base64, mimeType = b.mimeType) - } - } - } - } -} - -private sealed interface ChatMarkdownBlock { - data class Text(val text: String) : ChatMarkdownBlock - data class Code(val code: String, val language: String?) : ChatMarkdownBlock - data class InlineImage(val mimeType: String?, val base64: String) : ChatMarkdownBlock -} - -private fun splitMarkdown(raw: String): List { - if (raw.isEmpty()) return emptyList() - - val out = ArrayList() - var idx = 0 - while (idx < raw.length) { - val fenceStart = raw.indexOf("```", startIndex = idx) - if (fenceStart < 0) { - out.addAll(splitInlineImages(raw.substring(idx))) - break - } - - if (fenceStart > idx) { - out.addAll(splitInlineImages(raw.substring(idx, fenceStart))) - } - - val langLineStart = fenceStart + 3 - val langLineEnd = raw.indexOf('\n', startIndex = langLineStart).let { if (it < 0) raw.length else it } - val language = raw.substring(langLineStart, langLineEnd).trim().ifEmpty { null } - - val codeStart = if (langLineEnd < raw.length && raw[langLineEnd] == '\n') langLineEnd + 1 else langLineEnd - val fenceEnd = raw.indexOf("```", startIndex = codeStart) - if (fenceEnd < 0) { - out.addAll(splitInlineImages(raw.substring(fenceStart))) - break - } - val code = raw.substring(codeStart, fenceEnd) - out.add(ChatMarkdownBlock.Code(code = code, language = language)) - - idx = fenceEnd + 3 - } - - return out -} - -private fun splitInlineImages(text: String): List { - if (text.isEmpty()) return emptyList() - val regex = Regex("data:image/([a-zA-Z0-9+.-]+);base64,([A-Za-z0-9+/=\\n\\r]+)") - val out = ArrayList() - - var idx = 0 - while (idx < text.length) { - val m = regex.find(text, startIndex = idx) ?: break - val start = m.range.first - val end = m.range.last + 1 - if (start > idx) out.add(ChatMarkdownBlock.Text(text.substring(idx, start))) - - val mime = "image/" + (m.groupValues.getOrNull(1)?.trim()?.ifEmpty { "png" } ?: "png") - val b64 = m.groupValues.getOrNull(2)?.replace("\n", "")?.replace("\r", "")?.trim().orEmpty() - if (b64.isNotEmpty()) { - out.add(ChatMarkdownBlock.InlineImage(mimeType = mime, base64 = b64)) - } - idx = end - } - - if (idx < text.length) out.add(ChatMarkdownBlock.Text(text.substring(idx))) - return out -} - -private fun parseInlineMarkdown(text: String, inlineCodeBg: androidx.compose.ui.graphics.Color): AnnotatedString { - if (text.isEmpty()) return AnnotatedString("") - - val out = buildAnnotatedString { - var i = 0 - while (i < text.length) { - if (text.startsWith("**", startIndex = i)) { - val end = text.indexOf("**", startIndex = i + 2) - if (end > i + 2) { - withStyle(SpanStyle(fontWeight = FontWeight.SemiBold)) { - append(text.substring(i + 2, end)) - } - i = end + 2 - continue - } - } - - if (text[i] == '`') { - val end = text.indexOf('`', startIndex = i + 1) - if (end > i + 1) { - withStyle( - SpanStyle( - fontFamily = FontFamily.Monospace, - background = inlineCodeBg, - ), - ) { - append(text.substring(i + 1, end)) - } - i = end + 1 - continue - } - } - - if (text[i] == '*' && (i + 1 < text.length && text[i + 1] != '*')) { - val end = text.indexOf('*', startIndex = i + 1) - if (end > i + 1) { - withStyle(SpanStyle(fontStyle = FontStyle.Italic)) { - append(text.substring(i + 1, end)) - } - i = end + 1 - continue - } - } - - append(text[i]) - i += 1 - } - } - return out -} - -@Composable -private fun InlineBase64Image(base64: String, mimeType: String?) { - var image by remember(base64) { mutableStateOf(null) } - var failed by remember(base64) { mutableStateOf(false) } - - LaunchedEffect(base64) { - failed = false - image = - withContext(Dispatchers.Default) { - try { - val bytes = Base64.decode(base64, Base64.DEFAULT) - val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) ?: return@withContext null - bitmap.asImageBitmap() - } catch (_: Throwable) { - null - } - } - if (image == null) failed = true - } - - if (image != null) { - Image( - bitmap = image!!, - contentDescription = mimeType ?: "image", - contentScale = ContentScale.Fit, - modifier = Modifier.fillMaxWidth(), - ) - } else if (failed) { - Text( - text = "Image unavailable", - modifier = Modifier.padding(vertical = 2.dp), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatMessageListCard.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatMessageListCard.kt deleted file mode 100644 index bcec19a5fa2..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatMessageListCard.kt +++ /dev/null @@ -1,110 +0,0 @@ -package ai.openclaw.android.ui.chat - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowCircleDown -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.unit.dp -import ai.openclaw.android.chat.ChatMessage -import ai.openclaw.android.chat.ChatPendingToolCall - -@Composable -fun ChatMessageListCard( - messages: List, - pendingRunCount: Int, - pendingToolCalls: List, - streamingAssistantText: String?, - modifier: Modifier = Modifier, -) { - val listState = rememberLazyListState() - - // With reverseLayout the newest item is at index 0 (bottom of screen). - LaunchedEffect(messages.size, pendingRunCount, pendingToolCalls.size, streamingAssistantText) { - listState.animateScrollToItem(index = 0) - } - - Card( - modifier = modifier.fillMaxWidth(), - shape = MaterialTheme.shapes.large, - colors = - CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceContainer, - ), - elevation = CardDefaults.cardElevation(defaultElevation = 0.dp), - ) { - Box(modifier = Modifier.fillMaxSize()) { - LazyColumn( - modifier = Modifier.fillMaxSize(), - state = listState, - reverseLayout = true, - verticalArrangement = Arrangement.spacedBy(14.dp), - contentPadding = androidx.compose.foundation.layout.PaddingValues(top = 12.dp, bottom = 12.dp, start = 12.dp, end = 12.dp), - ) { - // With reverseLayout = true, index 0 renders at the BOTTOM. - // So we emit newest items first: streaming → tools → typing → messages (newest→oldest). - - val stream = streamingAssistantText?.trim() - if (!stream.isNullOrEmpty()) { - item(key = "stream") { - ChatStreamingAssistantBubble(text = stream) - } - } - - if (pendingToolCalls.isNotEmpty()) { - item(key = "tools") { - ChatPendingToolsBubble(toolCalls = pendingToolCalls) - } - } - - if (pendingRunCount > 0) { - item(key = "typing") { - ChatTypingIndicatorBubble() - } - } - - items(count = messages.size, key = { idx -> messages[messages.size - 1 - idx].id }) { idx -> - ChatMessageBubble(message = messages[messages.size - 1 - idx]) - } - } - - if (messages.isEmpty() && pendingRunCount == 0 && pendingToolCalls.isEmpty() && streamingAssistantText.isNullOrBlank()) { - EmptyChatHint(modifier = Modifier.align(Alignment.Center)) - } - } - } -} - -@Composable -private fun EmptyChatHint(modifier: Modifier = Modifier) { - Row( - modifier = modifier.alpha(0.7f), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp), - ) { - Icon( - imageVector = Icons.Default.ArrowCircleDown, - contentDescription = null, - tint = MaterialTheme.colorScheme.onSurfaceVariant, - ) - Text( - text = "Message OpenClaw…", - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatMessageViews.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatMessageViews.kt deleted file mode 100644 index bf294327551..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatMessageViews.kt +++ /dev/null @@ -1,263 +0,0 @@ -package ai.openclaw.android.ui.chat - -import android.graphics.BitmapFactory -import android.util.Base64 -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.asImageBitmap -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.unit.dp -import androidx.compose.foundation.Image -import ai.openclaw.android.chat.ChatMessage -import ai.openclaw.android.chat.ChatMessageContent -import ai.openclaw.android.chat.ChatPendingToolCall -import ai.openclaw.android.tools.ToolDisplayRegistry -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import androidx.compose.ui.platform.LocalContext - -@Composable -fun ChatMessageBubble(message: ChatMessage) { - val isUser = message.role.lowercase() == "user" - - // Filter to only displayable content parts (text with content, or base64 images) - val displayableContent = message.content.filter { part -> - when (part.type) { - "text" -> !part.text.isNullOrBlank() - else -> part.base64 != null - } - } - - // Skip rendering entirely if no displayable content - if (displayableContent.isEmpty()) return - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = if (isUser) Arrangement.End else Arrangement.Start, - ) { - Surface( - shape = RoundedCornerShape(16.dp), - tonalElevation = 0.dp, - shadowElevation = 0.dp, - color = Color.Transparent, - modifier = Modifier.fillMaxWidth(0.92f), - ) { - Box( - modifier = - Modifier - .background(bubbleBackground(isUser)) - .padding(horizontal = 12.dp, vertical = 10.dp), - ) { - val textColor = textColorOverBubble(isUser) - ChatMessageBody(content = displayableContent, textColor = textColor) - } - } - } -} - -@Composable -private fun ChatMessageBody(content: List, textColor: Color) { - Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { - for (part in content) { - when (part.type) { - "text" -> { - val text = part.text ?: continue - ChatMarkdown(text = text, textColor = textColor) - } - else -> { - val b64 = part.base64 ?: continue - ChatBase64Image(base64 = b64, mimeType = part.mimeType) - } - } - } - } -} - -@Composable -fun ChatTypingIndicatorBubble() { - Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Start) { - Surface( - shape = RoundedCornerShape(16.dp), - color = MaterialTheme.colorScheme.surfaceContainer, - ) { - Row( - modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp), - ) { - DotPulse() - Text("Thinking…", style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) - } - } - } -} - -@Composable -fun ChatPendingToolsBubble(toolCalls: List) { - val context = LocalContext.current - val displays = - remember(toolCalls, context) { - toolCalls.map { ToolDisplayRegistry.resolve(context, it.name, it.args) } - } - Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Start) { - Surface( - shape = RoundedCornerShape(16.dp), - color = MaterialTheme.colorScheme.surfaceContainer, - ) { - Column(modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { - Text("Running tools…", style = MaterialTheme.typography.labelLarge, color = MaterialTheme.colorScheme.onSurface) - for (display in displays.take(6)) { - Column(verticalArrangement = Arrangement.spacedBy(2.dp)) { - Text( - "${display.emoji} ${display.label}", - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - fontFamily = FontFamily.Monospace, - ) - display.detailLine?.let { detail -> - Text( - detail, - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - fontFamily = FontFamily.Monospace, - ) - } - } - } - if (toolCalls.size > 6) { - Text( - "… +${toolCalls.size - 6} more", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - } - } - } -} - -@Composable -fun ChatStreamingAssistantBubble(text: String) { - Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Start) { - Surface( - shape = RoundedCornerShape(16.dp), - color = MaterialTheme.colorScheme.surfaceContainer, - ) { - Box(modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp)) { - ChatMarkdown(text = text, textColor = MaterialTheme.colorScheme.onSurface) - } - } - } -} - -@Composable -private fun bubbleBackground(isUser: Boolean): Brush { - return if (isUser) { - Brush.linearGradient( - colors = listOf(MaterialTheme.colorScheme.primary, MaterialTheme.colorScheme.primary.copy(alpha = 0.78f)), - ) - } else { - Brush.linearGradient( - colors = listOf(MaterialTheme.colorScheme.surfaceContainer, MaterialTheme.colorScheme.surfaceContainerHigh), - ) - } -} - -@Composable -private fun textColorOverBubble(isUser: Boolean): Color { - return if (isUser) { - MaterialTheme.colorScheme.onPrimary - } else { - MaterialTheme.colorScheme.onSurface - } -} - -@Composable -private fun ChatBase64Image(base64: String, mimeType: String?) { - var image by remember(base64) { mutableStateOf(null) } - var failed by remember(base64) { mutableStateOf(false) } - - LaunchedEffect(base64) { - failed = false - image = - withContext(Dispatchers.Default) { - try { - val bytes = Base64.decode(base64, Base64.DEFAULT) - val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) ?: return@withContext null - bitmap.asImageBitmap() - } catch (_: Throwable) { - null - } - } - if (image == null) failed = true - } - - if (image != null) { - Image( - bitmap = image!!, - contentDescription = mimeType ?: "attachment", - contentScale = ContentScale.Fit, - modifier = Modifier.fillMaxWidth(), - ) - } else if (failed) { - Text("Unsupported attachment", style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant) - } -} - -@Composable -private fun DotPulse() { - Row(horizontalArrangement = Arrangement.spacedBy(5.dp), verticalAlignment = Alignment.CenterVertically) { - PulseDot(alpha = 0.38f) - PulseDot(alpha = 0.62f) - PulseDot(alpha = 0.90f) - } -} - -@Composable -private fun PulseDot(alpha: Float) { - Surface( - modifier = Modifier.size(6.dp).alpha(alpha), - shape = CircleShape, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) {} -} - -@Composable -fun ChatCodeBlock(code: String, language: String?) { - Surface( - shape = RoundedCornerShape(12.dp), - color = MaterialTheme.colorScheme.surfaceContainerLowest, - modifier = Modifier.fillMaxWidth(), - ) { - Text( - text = code.trimEnd(), - modifier = Modifier.padding(10.dp), - fontFamily = FontFamily.Monospace, - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface, - ) - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatSessionsDialog.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatSessionsDialog.kt deleted file mode 100644 index 56b5cfb1faf..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatSessionsDialog.kt +++ /dev/null @@ -1,92 +0,0 @@ -package ai.openclaw.android.ui.chat - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Refresh -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.FilledTonalIconButton -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import ai.openclaw.android.chat.ChatSessionEntry - -@Composable -fun ChatSessionsDialog( - currentSessionKey: String, - sessions: List, - onDismiss: () -> Unit, - onRefresh: () -> Unit, - onSelect: (sessionKey: String) -> Unit, -) { - AlertDialog( - onDismissRequest = onDismiss, - confirmButton = {}, - title = { - Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth()) { - Text("Sessions", style = MaterialTheme.typography.titleMedium) - Spacer(modifier = Modifier.weight(1f)) - FilledTonalIconButton(onClick = onRefresh) { - Icon(Icons.Default.Refresh, contentDescription = "Refresh") - } - } - }, - text = { - if (sessions.isEmpty()) { - Text("No sessions", style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) - } else { - LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) { - items(sessions, key = { it.key }) { entry -> - SessionRow( - entry = entry, - isCurrent = entry.key == currentSessionKey, - onClick = { onSelect(entry.key) }, - ) - } - } - } - }, - ) -} - -@Composable -private fun SessionRow( - entry: ChatSessionEntry, - isCurrent: Boolean, - onClick: () -> Unit, -) { - Surface( - onClick = onClick, - shape = MaterialTheme.shapes.medium, - color = - if (isCurrent) { - MaterialTheme.colorScheme.primary.copy(alpha = 0.14f) - } else { - MaterialTheme.colorScheme.surfaceContainer - }, - modifier = Modifier.fillMaxWidth(), - ) { - Row( - modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(10.dp), - ) { - Text(entry.displayName ?: entry.key, style = MaterialTheme.typography.bodyMedium) - Spacer(modifier = Modifier.weight(1f)) - if (isCurrent) { - Text("Current", style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant) - } - } - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatSheetContent.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatSheetContent.kt deleted file mode 100644 index effee6708e0..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/ChatSheetContent.kt +++ /dev/null @@ -1,147 +0,0 @@ -package ai.openclaw.android.ui.chat - -import android.content.ContentResolver -import android.net.Uri -import android.util.Base64 -import androidx.activity.compose.rememberLauncherForActivityResult -import androidx.activity.result.contract.ActivityResultContracts -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateListOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.unit.dp -import ai.openclaw.android.MainViewModel -import ai.openclaw.android.chat.OutgoingAttachment -import java.io.ByteArrayOutputStream -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - -@Composable -fun ChatSheetContent(viewModel: MainViewModel) { - val messages by viewModel.chatMessages.collectAsState() - val errorText by viewModel.chatError.collectAsState() - val pendingRunCount by viewModel.pendingRunCount.collectAsState() - val healthOk by viewModel.chatHealthOk.collectAsState() - val sessionKey by viewModel.chatSessionKey.collectAsState() - val mainSessionKey by viewModel.mainSessionKey.collectAsState() - val thinkingLevel by viewModel.chatThinkingLevel.collectAsState() - val streamingAssistantText by viewModel.chatStreamingAssistantText.collectAsState() - val pendingToolCalls by viewModel.chatPendingToolCalls.collectAsState() - val sessions by viewModel.chatSessions.collectAsState() - - LaunchedEffect(mainSessionKey) { - viewModel.loadChat(mainSessionKey) - viewModel.refreshChatSessions(limit = 200) - } - - val context = LocalContext.current - val resolver = context.contentResolver - val scope = rememberCoroutineScope() - - val attachments = remember { mutableStateListOf() } - - val pickImages = - rememberLauncherForActivityResult(ActivityResultContracts.GetMultipleContents()) { uris -> - if (uris.isNullOrEmpty()) return@rememberLauncherForActivityResult - scope.launch(Dispatchers.IO) { - val next = - uris.take(8).mapNotNull { uri -> - try { - loadImageAttachment(resolver, uri) - } catch (_: Throwable) { - null - } - } - withContext(Dispatchers.Main) { - attachments.addAll(next) - } - } - } - - Column( - modifier = - Modifier - .fillMaxSize() - .padding(horizontal = 12.dp, vertical = 12.dp), - verticalArrangement = Arrangement.spacedBy(10.dp), - ) { - ChatMessageListCard( - messages = messages, - pendingRunCount = pendingRunCount, - pendingToolCalls = pendingToolCalls, - streamingAssistantText = streamingAssistantText, - modifier = Modifier.weight(1f, fill = true), - ) - - ChatComposer( - sessionKey = sessionKey, - sessions = sessions, - mainSessionKey = mainSessionKey, - healthOk = healthOk, - thinkingLevel = thinkingLevel, - pendingRunCount = pendingRunCount, - errorText = errorText, - attachments = attachments, - onPickImages = { pickImages.launch("image/*") }, - onRemoveAttachment = { id -> attachments.removeAll { it.id == id } }, - onSetThinkingLevel = { level -> viewModel.setChatThinkingLevel(level) }, - onSelectSession = { key -> viewModel.switchChatSession(key) }, - onRefresh = { - viewModel.refreshChat() - viewModel.refreshChatSessions(limit = 200) - }, - onAbort = { viewModel.abortChat() }, - onSend = { text -> - val outgoing = - attachments.map { att -> - OutgoingAttachment( - type = "image", - mimeType = att.mimeType, - fileName = att.fileName, - base64 = att.base64, - ) - } - viewModel.sendChat(message = text, thinking = thinkingLevel, attachments = outgoing) - attachments.clear() - }, - ) - } -} - -data class PendingImageAttachment( - val id: String, - val fileName: String, - val mimeType: String, - val base64: String, -) - -private suspend fun loadImageAttachment(resolver: ContentResolver, uri: Uri): PendingImageAttachment { - val mimeType = resolver.getType(uri) ?: "image/*" - val fileName = (uri.lastPathSegment ?: "image").substringAfterLast('/') - val bytes = - withContext(Dispatchers.IO) { - resolver.openInputStream(uri)?.use { input -> - val out = ByteArrayOutputStream() - input.copyTo(out) - out.toByteArray() - } ?: ByteArray(0) - } - if (bytes.isEmpty()) throw IllegalStateException("empty attachment") - val base64 = Base64.encodeToString(bytes, Base64.NO_WRAP) - return PendingImageAttachment( - id = uri.toString() + "#" + System.currentTimeMillis().toString(), - fileName = fileName, - mimeType = mimeType, - base64 = base64, - ) -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/SessionFilters.kt b/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/SessionFilters.kt deleted file mode 100644 index 68f3f409960..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/ui/chat/SessionFilters.kt +++ /dev/null @@ -1,73 +0,0 @@ -package ai.openclaw.android.ui.chat - -import ai.openclaw.android.chat.ChatSessionEntry - -private const val RECENT_WINDOW_MS = 24 * 60 * 60 * 1000L - -/** - * Derive a human-friendly label from a raw session key. - * Examples: - * "telegram:g-agent-main-main" -> "Main" - * "agent:main:main" -> "Main" - * "discord:g-server-channel" -> "Server Channel" - * "my-custom-session" -> "My Custom Session" - */ -fun friendlySessionName(key: String): String { - // Strip common prefixes like "telegram:", "agent:", "discord:" etc. - val stripped = key.substringAfterLast(":") - - // Remove leading "g-" prefix (gateway artifact) - val cleaned = if (stripped.startsWith("g-")) stripped.removePrefix("g-") else stripped - - // Split on hyphens/underscores, title-case each word, collapse "main main" -> "Main" - val words = cleaned.split('-', '_').filter { it.isNotBlank() }.map { word -> - word.replaceFirstChar { it.uppercaseChar() } - }.distinct() - - val result = words.joinToString(" ") - return result.ifBlank { key } -} - -fun resolveSessionChoices( - currentSessionKey: String, - sessions: List, - mainSessionKey: String, - nowMs: Long = System.currentTimeMillis(), -): List { - val mainKey = mainSessionKey.trim().ifEmpty { "main" } - val current = currentSessionKey.trim().let { if (it == "main" && mainKey != "main") mainKey else it } - val aliasKey = if (mainKey == "main") null else "main" - val cutoff = nowMs - RECENT_WINDOW_MS - val sorted = sessions.sortedByDescending { it.updatedAtMs ?: 0L } - val recent = mutableListOf() - val seen = mutableSetOf() - for (entry in sorted) { - if (aliasKey != null && entry.key == aliasKey) continue - if (!seen.add(entry.key)) continue - if ((entry.updatedAtMs ?: 0L) < cutoff) continue - recent.add(entry) - } - - val result = mutableListOf() - val included = mutableSetOf() - val mainEntry = sorted.firstOrNull { it.key == mainKey } - if (mainEntry != null) { - result.add(mainEntry) - included.add(mainKey) - } else if (current == mainKey) { - result.add(ChatSessionEntry(key = mainKey, updatedAtMs = null)) - included.add(mainKey) - } - - for (entry in recent) { - if (included.add(entry.key)) { - result.add(entry) - } - } - - if (current.isNotEmpty() && !included.contains(current)) { - result.add(ChatSessionEntry(key = current, updatedAtMs = null)) - } - - return result -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/voice/StreamingMediaDataSource.kt b/apps/android/app/src/main/java/ai/openclaw/android/voice/StreamingMediaDataSource.kt deleted file mode 100644 index 329707ad56a..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/voice/StreamingMediaDataSource.kt +++ /dev/null @@ -1,98 +0,0 @@ -package ai.openclaw.android.voice - -import android.media.MediaDataSource -import kotlin.math.min - -internal class StreamingMediaDataSource : MediaDataSource() { - private data class Chunk(val start: Long, val data: ByteArray) - - private val lock = Object() - private val chunks = ArrayList() - private var totalSize: Long = 0 - private var closed = false - private var finished = false - private var lastReadIndex = 0 - - fun append(data: ByteArray) { - if (data.isEmpty()) return - synchronized(lock) { - if (closed || finished) return - val chunk = Chunk(totalSize, data) - chunks.add(chunk) - totalSize += data.size.toLong() - lock.notifyAll() - } - } - - fun finish() { - synchronized(lock) { - if (closed) return - finished = true - lock.notifyAll() - } - } - - fun fail() { - synchronized(lock) { - closed = true - lock.notifyAll() - } - } - - override fun readAt(position: Long, buffer: ByteArray, offset: Int, size: Int): Int { - if (position < 0) return -1 - synchronized(lock) { - while (!closed && !finished && position >= totalSize) { - lock.wait() - } - if (closed) return -1 - if (position >= totalSize && finished) return -1 - - val available = (totalSize - position).toInt() - val toRead = min(size, available) - var remaining = toRead - var destOffset = offset - var pos = position - - var index = findChunkIndex(pos) - while (remaining > 0 && index < chunks.size) { - val chunk = chunks[index] - val inChunkOffset = (pos - chunk.start).toInt() - if (inChunkOffset >= chunk.data.size) { - index++ - continue - } - val copyLen = min(remaining, chunk.data.size - inChunkOffset) - System.arraycopy(chunk.data, inChunkOffset, buffer, destOffset, copyLen) - remaining -= copyLen - destOffset += copyLen - pos += copyLen - if (inChunkOffset + copyLen >= chunk.data.size) { - index++ - } - } - - return toRead - remaining - } - } - - override fun getSize(): Long = -1 - - override fun close() { - synchronized(lock) { - closed = true - lock.notifyAll() - } - } - - private fun findChunkIndex(position: Long): Int { - var index = lastReadIndex - while (index < chunks.size) { - val chunk = chunks[index] - if (position < chunk.start + chunk.data.size) break - index++ - } - lastReadIndex = index - return index - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/voice/TalkDirectiveParser.kt b/apps/android/app/src/main/java/ai/openclaw/android/voice/TalkDirectiveParser.kt deleted file mode 100644 index 5c80cc1f4f1..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/voice/TalkDirectiveParser.kt +++ /dev/null @@ -1,191 +0,0 @@ -package ai.openclaw.android.voice - -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive - -private val directiveJson = Json { ignoreUnknownKeys = true } - -data class TalkDirective( - val voiceId: String? = null, - val modelId: String? = null, - val speed: Double? = null, - val rateWpm: Int? = null, - val stability: Double? = null, - val similarity: Double? = null, - val style: Double? = null, - val speakerBoost: Boolean? = null, - val seed: Long? = null, - val normalize: String? = null, - val language: String? = null, - val outputFormat: String? = null, - val latencyTier: Int? = null, - val once: Boolean? = null, -) - -data class TalkDirectiveParseResult( - val directive: TalkDirective?, - val stripped: String, - val unknownKeys: List, -) - -object TalkDirectiveParser { - fun parse(text: String): TalkDirectiveParseResult { - val normalized = text.replace("\r\n", "\n") - val lines = normalized.split("\n").toMutableList() - if (lines.isEmpty()) return TalkDirectiveParseResult(null, text, emptyList()) - - val firstNonEmpty = lines.indexOfFirst { it.trim().isNotEmpty() } - if (firstNonEmpty == -1) return TalkDirectiveParseResult(null, text, emptyList()) - - val head = lines[firstNonEmpty].trim() - if (!head.startsWith("{") || !head.endsWith("}")) { - return TalkDirectiveParseResult(null, text, emptyList()) - } - - val obj = parseJsonObject(head) ?: return TalkDirectiveParseResult(null, text, emptyList()) - - val speakerBoost = - boolValue(obj, listOf("speaker_boost", "speakerBoost")) - ?: boolValue(obj, listOf("no_speaker_boost", "noSpeakerBoost"))?.not() - - val directive = TalkDirective( - voiceId = stringValue(obj, listOf("voice", "voice_id", "voiceId")), - modelId = stringValue(obj, listOf("model", "model_id", "modelId")), - speed = doubleValue(obj, listOf("speed")), - rateWpm = intValue(obj, listOf("rate", "wpm")), - stability = doubleValue(obj, listOf("stability")), - similarity = doubleValue(obj, listOf("similarity", "similarity_boost", "similarityBoost")), - style = doubleValue(obj, listOf("style")), - speakerBoost = speakerBoost, - seed = longValue(obj, listOf("seed")), - normalize = stringValue(obj, listOf("normalize", "apply_text_normalization")), - language = stringValue(obj, listOf("lang", "language_code", "language")), - outputFormat = stringValue(obj, listOf("output_format", "format")), - latencyTier = intValue(obj, listOf("latency", "latency_tier", "latencyTier")), - once = boolValue(obj, listOf("once")), - ) - - val hasDirective = listOf( - directive.voiceId, - directive.modelId, - directive.speed, - directive.rateWpm, - directive.stability, - directive.similarity, - directive.style, - directive.speakerBoost, - directive.seed, - directive.normalize, - directive.language, - directive.outputFormat, - directive.latencyTier, - directive.once, - ).any { it != null } - - if (!hasDirective) return TalkDirectiveParseResult(null, text, emptyList()) - - val knownKeys = setOf( - "voice", "voice_id", "voiceid", - "model", "model_id", "modelid", - "speed", "rate", "wpm", - "stability", "similarity", "similarity_boost", "similarityboost", - "style", - "speaker_boost", "speakerboost", - "no_speaker_boost", "nospeakerboost", - "seed", - "normalize", "apply_text_normalization", - "lang", "language_code", "language", - "output_format", "format", - "latency", "latency_tier", "latencytier", - "once", - ) - val unknownKeys = obj.keys.filter { !knownKeys.contains(it.lowercase()) }.sorted() - - lines.removeAt(firstNonEmpty) - if (firstNonEmpty < lines.size) { - if (lines[firstNonEmpty].trim().isEmpty()) { - lines.removeAt(firstNonEmpty) - } - } - - return TalkDirectiveParseResult(directive, lines.joinToString("\n"), unknownKeys) - } - - private fun parseJsonObject(line: String): JsonObject? { - return try { - directiveJson.parseToJsonElement(line) as? JsonObject - } catch (_: Throwable) { - null - } - } - - private fun stringValue(obj: JsonObject, keys: List): String? { - for (key in keys) { - val value = obj[key].asStringOrNull()?.trim() - if (!value.isNullOrEmpty()) return value - } - return null - } - - private fun doubleValue(obj: JsonObject, keys: List): Double? { - for (key in keys) { - val value = obj[key].asDoubleOrNull() - if (value != null) return value - } - return null - } - - private fun intValue(obj: JsonObject, keys: List): Int? { - for (key in keys) { - val value = obj[key].asIntOrNull() - if (value != null) return value - } - return null - } - - private fun longValue(obj: JsonObject, keys: List): Long? { - for (key in keys) { - val value = obj[key].asLongOrNull() - if (value != null) return value - } - return null - } - - private fun boolValue(obj: JsonObject, keys: List): Boolean? { - for (key in keys) { - val value = obj[key].asBooleanOrNull() - if (value != null) return value - } - return null - } -} - -private fun JsonElement?.asStringOrNull(): String? = - (this as? JsonPrimitive)?.takeIf { it.isString }?.content - -private fun JsonElement?.asDoubleOrNull(): Double? { - val primitive = this as? JsonPrimitive ?: return null - return primitive.content.toDoubleOrNull() -} - -private fun JsonElement?.asIntOrNull(): Int? { - val primitive = this as? JsonPrimitive ?: return null - return primitive.content.toIntOrNull() -} - -private fun JsonElement?.asLongOrNull(): Long? { - val primitive = this as? JsonPrimitive ?: return null - return primitive.content.toLongOrNull() -} - -private fun JsonElement?.asBooleanOrNull(): Boolean? { - val primitive = this as? JsonPrimitive ?: return null - val content = primitive.content.trim().lowercase() - return when (content) { - "true", "yes", "1" -> true - "false", "no", "0" -> false - else -> null - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/voice/TalkModeManager.kt b/apps/android/app/src/main/java/ai/openclaw/android/voice/TalkModeManager.kt deleted file mode 100644 index 04d18b62260..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/voice/TalkModeManager.kt +++ /dev/null @@ -1,1257 +0,0 @@ -package ai.openclaw.android.voice - -import android.Manifest -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.media.AudioAttributes -import android.media.AudioFormat -import android.media.AudioManager -import android.media.AudioTrack -import android.media.MediaPlayer -import android.os.Bundle -import android.os.Handler -import android.os.Looper -import android.os.SystemClock -import android.speech.RecognitionListener -import android.speech.RecognizerIntent -import android.speech.SpeechRecognizer -import android.speech.tts.TextToSpeech -import android.speech.tts.UtteranceProgressListener -import android.util.Log -import androidx.core.content.ContextCompat -import ai.openclaw.android.gateway.GatewaySession -import ai.openclaw.android.isCanonicalMainSessionKey -import ai.openclaw.android.normalizeMainKey -import java.net.HttpURLConnection -import java.net.URL -import java.util.UUID -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonArray -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import kotlinx.serialization.json.buildJsonObject -import kotlin.math.max - -class TalkModeManager( - private val context: Context, - private val scope: CoroutineScope, - private val session: GatewaySession, - private val supportsChatSubscribe: Boolean, - private val isConnected: () -> Boolean, -) { - companion object { - private const val tag = "TalkMode" - private const val defaultModelIdFallback = "eleven_v3" - private const val defaultOutputFormatFallback = "pcm_24000" - } - - private val mainHandler = Handler(Looper.getMainLooper()) - private val json = Json { ignoreUnknownKeys = true } - - private val _isEnabled = MutableStateFlow(false) - val isEnabled: StateFlow = _isEnabled - - private val _isListening = MutableStateFlow(false) - val isListening: StateFlow = _isListening - - private val _isSpeaking = MutableStateFlow(false) - val isSpeaking: StateFlow = _isSpeaking - - private val _statusText = MutableStateFlow("Off") - val statusText: StateFlow = _statusText - - private val _lastAssistantText = MutableStateFlow(null) - val lastAssistantText: StateFlow = _lastAssistantText - - private val _usingFallbackTts = MutableStateFlow(false) - val usingFallbackTts: StateFlow = _usingFallbackTts - - private var recognizer: SpeechRecognizer? = null - private var restartJob: Job? = null - private var stopRequested = false - private var listeningMode = false - - private var silenceJob: Job? = null - private val silenceWindowMs = 700L - private var lastTranscript: String = "" - private var lastHeardAtMs: Long? = null - private var lastSpokenText: String? = null - private var lastInterruptedAtSeconds: Double? = null - - private var defaultVoiceId: String? = null - private var currentVoiceId: String? = null - private var fallbackVoiceId: String? = null - private var defaultModelId: String? = null - private var currentModelId: String? = null - private var defaultOutputFormat: String? = null - private var apiKey: String? = null - private var voiceAliases: Map = emptyMap() - private var interruptOnSpeech: Boolean = true - private var voiceOverrideActive = false - private var modelOverrideActive = false - private var mainSessionKey: String = "main" - - private var pendingRunId: String? = null - private var pendingFinal: CompletableDeferred? = null - private var chatSubscribedSessionKey: String? = null - - private var player: MediaPlayer? = null - private var streamingSource: StreamingMediaDataSource? = null - private var pcmTrack: AudioTrack? = null - @Volatile private var pcmStopRequested = false - private var systemTts: TextToSpeech? = null - private var systemTtsPending: CompletableDeferred? = null - private var systemTtsPendingId: String? = null - - fun setMainSessionKey(sessionKey: String?) { - val trimmed = sessionKey?.trim().orEmpty() - if (trimmed.isEmpty()) return - if (isCanonicalMainSessionKey(mainSessionKey)) return - mainSessionKey = trimmed - } - - fun setEnabled(enabled: Boolean) { - if (_isEnabled.value == enabled) return - _isEnabled.value = enabled - if (enabled) { - Log.d(tag, "enabled") - start() - } else { - Log.d(tag, "disabled") - stop() - } - } - - fun handleGatewayEvent(event: String, payloadJson: String?) { - if (event != "chat") return - if (payloadJson.isNullOrBlank()) return - val pending = pendingRunId ?: return - val obj = - try { - json.parseToJsonElement(payloadJson).asObjectOrNull() - } catch (_: Throwable) { - null - } ?: return - val runId = obj["runId"].asStringOrNull() ?: return - if (runId != pending) return - val state = obj["state"].asStringOrNull() ?: return - if (state == "final") { - pendingFinal?.complete(true) - pendingFinal = null - pendingRunId = null - } - } - - private fun start() { - mainHandler.post { - if (_isListening.value) return@post - stopRequested = false - listeningMode = true - Log.d(tag, "start") - - if (!SpeechRecognizer.isRecognitionAvailable(context)) { - _statusText.value = "Speech recognizer unavailable" - Log.w(tag, "speech recognizer unavailable") - return@post - } - - val micOk = - ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == - PackageManager.PERMISSION_GRANTED - if (!micOk) { - _statusText.value = "Microphone permission required" - Log.w(tag, "microphone permission required") - return@post - } - - try { - recognizer?.destroy() - recognizer = SpeechRecognizer.createSpeechRecognizer(context).also { it.setRecognitionListener(listener) } - startListeningInternal(markListening = true) - startSilenceMonitor() - Log.d(tag, "listening") - } catch (err: Throwable) { - _statusText.value = "Start failed: ${err.message ?: err::class.simpleName}" - Log.w(tag, "start failed: ${err.message ?: err::class.simpleName}") - } - } - } - - private fun stop() { - stopRequested = true - listeningMode = false - restartJob?.cancel() - restartJob = null - silenceJob?.cancel() - silenceJob = null - lastTranscript = "" - lastHeardAtMs = null - _isListening.value = false - _statusText.value = "Off" - stopSpeaking() - _usingFallbackTts.value = false - chatSubscribedSessionKey = null - - mainHandler.post { - recognizer?.cancel() - recognizer?.destroy() - recognizer = null - } - systemTts?.stop() - systemTtsPending?.cancel() - systemTtsPending = null - systemTtsPendingId = null - } - - private fun startListeningInternal(markListening: Boolean) { - val r = recognizer ?: return - val intent = - Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply { - putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM) - putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true) - putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 3) - putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, context.packageName) - } - - if (markListening) { - _statusText.value = "Listening" - _isListening.value = true - } - r.startListening(intent) - } - - private fun scheduleRestart(delayMs: Long = 350) { - if (stopRequested) return - restartJob?.cancel() - restartJob = - scope.launch { - delay(delayMs) - mainHandler.post { - if (stopRequested) return@post - try { - recognizer?.cancel() - val shouldListen = listeningMode - val shouldInterrupt = _isSpeaking.value && interruptOnSpeech - if (!shouldListen && !shouldInterrupt) return@post - startListeningInternal(markListening = shouldListen) - } catch (_: Throwable) { - // handled by onError - } - } - } - } - - private fun handleTranscript(text: String, isFinal: Boolean) { - val trimmed = text.trim() - if (_isSpeaking.value && interruptOnSpeech) { - if (shouldInterrupt(trimmed)) { - stopSpeaking() - } - return - } - - if (!_isListening.value) return - - if (trimmed.isNotEmpty()) { - lastTranscript = trimmed - lastHeardAtMs = SystemClock.elapsedRealtime() - } - - if (isFinal) { - lastTranscript = trimmed - } - } - - private fun startSilenceMonitor() { - silenceJob?.cancel() - silenceJob = - scope.launch { - while (_isEnabled.value) { - delay(200) - checkSilence() - } - } - } - - private fun checkSilence() { - if (!_isListening.value) return - val transcript = lastTranscript.trim() - if (transcript.isEmpty()) return - val lastHeard = lastHeardAtMs ?: return - val elapsed = SystemClock.elapsedRealtime() - lastHeard - if (elapsed < silenceWindowMs) return - scope.launch { finalizeTranscript(transcript) } - } - - private suspend fun finalizeTranscript(transcript: String) { - listeningMode = false - _isListening.value = false - _statusText.value = "Thinking…" - lastTranscript = "" - lastHeardAtMs = null - - reloadConfig() - val prompt = buildPrompt(transcript) - if (!isConnected()) { - _statusText.value = "Gateway not connected" - Log.w(tag, "finalize: gateway not connected") - start() - return - } - - try { - val startedAt = System.currentTimeMillis().toDouble() / 1000.0 - subscribeChatIfNeeded(session = session, sessionKey = mainSessionKey) - Log.d(tag, "chat.send start sessionKey=${mainSessionKey.ifBlank { "main" }} chars=${prompt.length}") - val runId = sendChat(prompt, session) - Log.d(tag, "chat.send ok runId=$runId") - val ok = waitForChatFinal(runId) - if (!ok) { - Log.w(tag, "chat final timeout runId=$runId; attempting history fallback") - } - val assistant = waitForAssistantText(session, startedAt, if (ok) 12_000 else 25_000) - if (assistant.isNullOrBlank()) { - _statusText.value = "No reply" - Log.w(tag, "assistant text timeout runId=$runId") - start() - return - } - Log.d(tag, "assistant text ok chars=${assistant.length}") - playAssistant(assistant) - } catch (err: Throwable) { - _statusText.value = "Talk failed: ${err.message ?: err::class.simpleName}" - Log.w(tag, "finalize failed: ${err.message ?: err::class.simpleName}") - } - - if (_isEnabled.value) { - start() - } - } - - private suspend fun subscribeChatIfNeeded(session: GatewaySession, sessionKey: String) { - if (!supportsChatSubscribe) return - val key = sessionKey.trim() - if (key.isEmpty()) return - if (chatSubscribedSessionKey == key) return - try { - session.sendNodeEvent("chat.subscribe", """{"sessionKey":"$key"}""") - chatSubscribedSessionKey = key - Log.d(tag, "chat.subscribe ok sessionKey=$key") - } catch (err: Throwable) { - Log.w(tag, "chat.subscribe failed sessionKey=$key err=${err.message ?: err::class.java.simpleName}") - } - } - - private fun buildPrompt(transcript: String): String { - val lines = mutableListOf( - "Talk Mode active. Reply in a concise, spoken tone.", - "You may optionally prefix the response with JSON (first line) to set ElevenLabs voice (id or alias), e.g. {\"voice\":\"\",\"once\":true}.", - ) - lastInterruptedAtSeconds?.let { - lines.add("Assistant speech interrupted at ${"%.1f".format(it)}s.") - lastInterruptedAtSeconds = null - } - lines.add("") - lines.add(transcript) - return lines.joinToString("\n") - } - - private suspend fun sendChat(message: String, session: GatewaySession): String { - val runId = UUID.randomUUID().toString() - val params = - buildJsonObject { - put("sessionKey", JsonPrimitive(mainSessionKey.ifBlank { "main" })) - put("message", JsonPrimitive(message)) - put("thinking", JsonPrimitive("low")) - put("timeoutMs", JsonPrimitive(30_000)) - put("idempotencyKey", JsonPrimitive(runId)) - } - val res = session.request("chat.send", params.toString()) - val parsed = parseRunId(res) ?: runId - if (parsed != runId) { - pendingRunId = parsed - } - return parsed - } - - private suspend fun waitForChatFinal(runId: String): Boolean { - pendingFinal?.cancel() - val deferred = CompletableDeferred() - pendingRunId = runId - pendingFinal = deferred - - val result = - withContext(Dispatchers.IO) { - try { - kotlinx.coroutines.withTimeout(120_000) { deferred.await() } - } catch (_: Throwable) { - false - } - } - - if (!result) { - pendingFinal = null - pendingRunId = null - } - return result - } - - private suspend fun waitForAssistantText( - session: GatewaySession, - sinceSeconds: Double, - timeoutMs: Long, - ): String? { - val deadline = SystemClock.elapsedRealtime() + timeoutMs - while (SystemClock.elapsedRealtime() < deadline) { - val text = fetchLatestAssistantText(session, sinceSeconds) - if (!text.isNullOrBlank()) return text - delay(300) - } - return null - } - - private suspend fun fetchLatestAssistantText( - session: GatewaySession, - sinceSeconds: Double? = null, - ): String? { - val key = mainSessionKey.ifBlank { "main" } - val res = session.request("chat.history", "{\"sessionKey\":\"$key\"}") - val root = json.parseToJsonElement(res).asObjectOrNull() ?: return null - val messages = root["messages"] as? JsonArray ?: return null - for (item in messages.reversed()) { - val obj = item.asObjectOrNull() ?: continue - if (obj["role"].asStringOrNull() != "assistant") continue - if (sinceSeconds != null) { - val timestamp = obj["timestamp"].asDoubleOrNull() - if (timestamp != null && !TalkModeRuntime.isMessageTimestampAfter(timestamp, sinceSeconds)) continue - } - val content = obj["content"] as? JsonArray ?: continue - val text = - content.mapNotNull { entry -> - entry.asObjectOrNull()?.get("text")?.asStringOrNull()?.trim() - }.filter { it.isNotEmpty() } - if (text.isNotEmpty()) return text.joinToString("\n") - } - return null - } - - private suspend fun playAssistant(text: String) { - val parsed = TalkDirectiveParser.parse(text) - if (parsed.unknownKeys.isNotEmpty()) { - Log.w(tag, "Unknown talk directive keys: ${parsed.unknownKeys}") - } - val directive = parsed.directive - val cleaned = parsed.stripped.trim() - if (cleaned.isEmpty()) return - _lastAssistantText.value = cleaned - - val requestedVoice = directive?.voiceId?.trim()?.takeIf { it.isNotEmpty() } - val resolvedVoice = resolveVoiceAlias(requestedVoice) - if (requestedVoice != null && resolvedVoice == null) { - Log.w(tag, "unknown voice alias: $requestedVoice") - } - - if (directive?.voiceId != null) { - if (directive.once != true) { - currentVoiceId = resolvedVoice - voiceOverrideActive = true - } - } - if (directive?.modelId != null) { - if (directive.once != true) { - currentModelId = directive.modelId - modelOverrideActive = true - } - } - - val apiKey = - apiKey?.trim()?.takeIf { it.isNotEmpty() } - ?: System.getenv("ELEVENLABS_API_KEY")?.trim() - val preferredVoice = resolvedVoice ?: currentVoiceId ?: defaultVoiceId - val voiceId = - if (!apiKey.isNullOrEmpty()) { - resolveVoiceId(preferredVoice, apiKey) - } else { - null - } - - _statusText.value = "Speaking…" - _isSpeaking.value = true - lastSpokenText = cleaned - ensureInterruptListener() - - try { - val canUseElevenLabs = !voiceId.isNullOrBlank() && !apiKey.isNullOrEmpty() - if (!canUseElevenLabs) { - if (voiceId.isNullOrBlank()) { - Log.w(tag, "missing voiceId; falling back to system voice") - } - if (apiKey.isNullOrEmpty()) { - Log.w(tag, "missing ELEVENLABS_API_KEY; falling back to system voice") - } - _usingFallbackTts.value = true - _statusText.value = "Speaking (System)…" - speakWithSystemTts(cleaned) - } else { - _usingFallbackTts.value = false - val ttsStarted = SystemClock.elapsedRealtime() - val modelId = directive?.modelId ?: currentModelId ?: defaultModelId - val request = - ElevenLabsRequest( - text = cleaned, - modelId = modelId, - outputFormat = - TalkModeRuntime.validatedOutputFormat(directive?.outputFormat ?: defaultOutputFormat), - speed = TalkModeRuntime.resolveSpeed(directive?.speed, directive?.rateWpm), - stability = TalkModeRuntime.validatedStability(directive?.stability, modelId), - similarity = TalkModeRuntime.validatedUnit(directive?.similarity), - style = TalkModeRuntime.validatedUnit(directive?.style), - speakerBoost = directive?.speakerBoost, - seed = TalkModeRuntime.validatedSeed(directive?.seed), - normalize = TalkModeRuntime.validatedNormalize(directive?.normalize), - language = TalkModeRuntime.validatedLanguage(directive?.language), - latencyTier = TalkModeRuntime.validatedLatencyTier(directive?.latencyTier), - ) - streamAndPlay(voiceId = voiceId!!, apiKey = apiKey!!, request = request) - Log.d(tag, "elevenlabs stream ok durMs=${SystemClock.elapsedRealtime() - ttsStarted}") - } - } catch (err: Throwable) { - Log.w(tag, "speak failed: ${err.message ?: err::class.simpleName}; falling back to system voice") - try { - _usingFallbackTts.value = true - _statusText.value = "Speaking (System)…" - speakWithSystemTts(cleaned) - } catch (fallbackErr: Throwable) { - _statusText.value = "Speak failed: ${fallbackErr.message ?: fallbackErr::class.simpleName}" - Log.w(tag, "system voice failed: ${fallbackErr.message ?: fallbackErr::class.simpleName}") - } - } - - _isSpeaking.value = false - } - - private suspend fun streamAndPlay(voiceId: String, apiKey: String, request: ElevenLabsRequest) { - stopSpeaking(resetInterrupt = false) - - pcmStopRequested = false - val pcmSampleRate = TalkModeRuntime.parsePcmSampleRate(request.outputFormat) - if (pcmSampleRate != null) { - try { - streamAndPlayPcm(voiceId = voiceId, apiKey = apiKey, request = request, sampleRate = pcmSampleRate) - return - } catch (err: Throwable) { - if (pcmStopRequested) return - Log.w(tag, "pcm playback failed; falling back to mp3: ${err.message ?: err::class.simpleName}") - } - } - - streamAndPlayMp3(voiceId = voiceId, apiKey = apiKey, request = request) - } - - private suspend fun streamAndPlayMp3(voiceId: String, apiKey: String, request: ElevenLabsRequest) { - val dataSource = StreamingMediaDataSource() - streamingSource = dataSource - - val player = MediaPlayer() - this.player = player - - val prepared = CompletableDeferred() - val finished = CompletableDeferred() - - player.setAudioAttributes( - AudioAttributes.Builder() - .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) - .setUsage(AudioAttributes.USAGE_ASSISTANT) - .build(), - ) - player.setOnPreparedListener { - it.start() - prepared.complete(Unit) - } - player.setOnCompletionListener { - finished.complete(Unit) - } - player.setOnErrorListener { _, _, _ -> - finished.completeExceptionally(IllegalStateException("MediaPlayer error")) - true - } - - player.setDataSource(dataSource) - withContext(Dispatchers.Main) { - player.prepareAsync() - } - - val fetchError = CompletableDeferred() - val fetchJob = - scope.launch(Dispatchers.IO) { - try { - streamTts(voiceId = voiceId, apiKey = apiKey, request = request, sink = dataSource) - fetchError.complete(null) - } catch (err: Throwable) { - dataSource.fail() - fetchError.complete(err) - } - } - - Log.d(tag, "play start") - try { - prepared.await() - finished.await() - fetchError.await()?.let { throw it } - } finally { - fetchJob.cancel() - cleanupPlayer() - } - Log.d(tag, "play done") - } - - private suspend fun streamAndPlayPcm( - voiceId: String, - apiKey: String, - request: ElevenLabsRequest, - sampleRate: Int, - ) { - val minBuffer = - AudioTrack.getMinBufferSize( - sampleRate, - AudioFormat.CHANNEL_OUT_MONO, - AudioFormat.ENCODING_PCM_16BIT, - ) - if (minBuffer <= 0) { - throw IllegalStateException("AudioTrack buffer size invalid: $minBuffer") - } - - val bufferSize = max(minBuffer * 2, 8 * 1024) - val track = - AudioTrack( - AudioAttributes.Builder() - .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) - .setUsage(AudioAttributes.USAGE_ASSISTANT) - .build(), - AudioFormat.Builder() - .setSampleRate(sampleRate) - .setChannelMask(AudioFormat.CHANNEL_OUT_MONO) - .setEncoding(AudioFormat.ENCODING_PCM_16BIT) - .build(), - bufferSize, - AudioTrack.MODE_STREAM, - AudioManager.AUDIO_SESSION_ID_GENERATE, - ) - if (track.state != AudioTrack.STATE_INITIALIZED) { - track.release() - throw IllegalStateException("AudioTrack init failed") - } - pcmTrack = track - track.play() - - Log.d(tag, "pcm play start sampleRate=$sampleRate bufferSize=$bufferSize") - try { - streamPcm(voiceId = voiceId, apiKey = apiKey, request = request, track = track) - } finally { - cleanupPcmTrack() - } - Log.d(tag, "pcm play done") - } - - private suspend fun speakWithSystemTts(text: String) { - val trimmed = text.trim() - if (trimmed.isEmpty()) return - val ok = ensureSystemTts() - if (!ok) { - throw IllegalStateException("system TTS unavailable") - } - - val tts = systemTts ?: throw IllegalStateException("system TTS unavailable") - val utteranceId = "talk-${UUID.randomUUID()}" - val deferred = CompletableDeferred() - systemTtsPending?.cancel() - systemTtsPending = deferred - systemTtsPendingId = utteranceId - - withContext(Dispatchers.Main) { - val params = Bundle() - tts.speak(trimmed, TextToSpeech.QUEUE_FLUSH, params, utteranceId) - } - - withContext(Dispatchers.IO) { - try { - kotlinx.coroutines.withTimeout(180_000) { deferred.await() } - } catch (err: Throwable) { - throw err - } - } - } - - private suspend fun ensureSystemTts(): Boolean { - if (systemTts != null) return true - return withContext(Dispatchers.Main) { - val deferred = CompletableDeferred() - val tts = - try { - TextToSpeech(context) { status -> - deferred.complete(status == TextToSpeech.SUCCESS) - } - } catch (_: Throwable) { - deferred.complete(false) - null - } - if (tts == null) return@withContext false - - tts.setOnUtteranceProgressListener( - object : UtteranceProgressListener() { - override fun onStart(utteranceId: String?) {} - - override fun onDone(utteranceId: String?) { - if (utteranceId == null) return - if (utteranceId != systemTtsPendingId) return - systemTtsPending?.complete(Unit) - systemTtsPending = null - systemTtsPendingId = null - } - - @Suppress("OVERRIDE_DEPRECATION") - @Deprecated("Deprecated in Java") - override fun onError(utteranceId: String?) { - if (utteranceId == null) return - if (utteranceId != systemTtsPendingId) return - systemTtsPending?.completeExceptionally(IllegalStateException("system TTS error")) - systemTtsPending = null - systemTtsPendingId = null - } - - override fun onError(utteranceId: String?, errorCode: Int) { - if (utteranceId == null) return - if (utteranceId != systemTtsPendingId) return - systemTtsPending?.completeExceptionally(IllegalStateException("system TTS error $errorCode")) - systemTtsPending = null - systemTtsPendingId = null - } - }, - ) - - val ok = - try { - deferred.await() - } catch (_: Throwable) { - false - } - if (ok) { - systemTts = tts - } else { - tts.shutdown() - } - ok - } - } - - private fun stopSpeaking(resetInterrupt: Boolean = true) { - pcmStopRequested = true - if (!_isSpeaking.value) { - cleanupPlayer() - cleanupPcmTrack() - systemTts?.stop() - systemTtsPending?.cancel() - systemTtsPending = null - systemTtsPendingId = null - return - } - if (resetInterrupt) { - val currentMs = player?.currentPosition?.toDouble() ?: 0.0 - lastInterruptedAtSeconds = currentMs / 1000.0 - } - cleanupPlayer() - cleanupPcmTrack() - systemTts?.stop() - systemTtsPending?.cancel() - systemTtsPending = null - systemTtsPendingId = null - _isSpeaking.value = false - } - - private fun cleanupPlayer() { - player?.stop() - player?.release() - player = null - streamingSource?.close() - streamingSource = null - } - - private fun cleanupPcmTrack() { - val track = pcmTrack ?: return - try { - track.pause() - track.flush() - track.stop() - } catch (_: Throwable) { - // ignore cleanup errors - } finally { - track.release() - } - pcmTrack = null - } - - private fun shouldInterrupt(transcript: String): Boolean { - val trimmed = transcript.trim() - if (trimmed.length < 3) return false - val spoken = lastSpokenText?.lowercase() - if (spoken != null && spoken.contains(trimmed.lowercase())) return false - return true - } - - private suspend fun reloadConfig() { - val envVoice = System.getenv("ELEVENLABS_VOICE_ID")?.trim() - val sagVoice = System.getenv("SAG_VOICE_ID")?.trim() - val envKey = System.getenv("ELEVENLABS_API_KEY")?.trim() - try { - val res = session.request("talk.config", """{"includeSecrets":true}""") - val root = json.parseToJsonElement(res).asObjectOrNull() - val config = root?.get("config").asObjectOrNull() - val talk = config?.get("talk").asObjectOrNull() - val sessionCfg = config?.get("session").asObjectOrNull() - val mainKey = normalizeMainKey(sessionCfg?.get("mainKey").asStringOrNull()) - val voice = talk?.get("voiceId")?.asStringOrNull()?.trim()?.takeIf { it.isNotEmpty() } - val aliases = - talk?.get("voiceAliases").asObjectOrNull()?.entries?.mapNotNull { (key, value) -> - val id = value.asStringOrNull()?.trim()?.takeIf { it.isNotEmpty() } ?: return@mapNotNull null - normalizeAliasKey(key).takeIf { it.isNotEmpty() }?.let { it to id } - }?.toMap().orEmpty() - val model = talk?.get("modelId")?.asStringOrNull()?.trim()?.takeIf { it.isNotEmpty() } - val outputFormat = talk?.get("outputFormat")?.asStringOrNull()?.trim()?.takeIf { it.isNotEmpty() } - val key = talk?.get("apiKey")?.asStringOrNull()?.trim()?.takeIf { it.isNotEmpty() } - val interrupt = talk?.get("interruptOnSpeech")?.asBooleanOrNull() - - if (!isCanonicalMainSessionKey(mainSessionKey)) { - mainSessionKey = mainKey - } - defaultVoiceId = voice ?: envVoice?.takeIf { it.isNotEmpty() } ?: sagVoice?.takeIf { it.isNotEmpty() } - voiceAliases = aliases - if (!voiceOverrideActive) currentVoiceId = defaultVoiceId - defaultModelId = model ?: defaultModelIdFallback - if (!modelOverrideActive) currentModelId = defaultModelId - defaultOutputFormat = outputFormat ?: defaultOutputFormatFallback - apiKey = key ?: envKey?.takeIf { it.isNotEmpty() } - if (interrupt != null) interruptOnSpeech = interrupt - } catch (_: Throwable) { - defaultVoiceId = envVoice?.takeIf { it.isNotEmpty() } ?: sagVoice?.takeIf { it.isNotEmpty() } - defaultModelId = defaultModelIdFallback - if (!modelOverrideActive) currentModelId = defaultModelId - apiKey = envKey?.takeIf { it.isNotEmpty() } - voiceAliases = emptyMap() - defaultOutputFormat = defaultOutputFormatFallback - } - } - - private fun parseRunId(jsonString: String): String? { - val obj = json.parseToJsonElement(jsonString).asObjectOrNull() ?: return null - return obj["runId"].asStringOrNull() - } - - private suspend fun streamTts( - voiceId: String, - apiKey: String, - request: ElevenLabsRequest, - sink: StreamingMediaDataSource, - ) { - withContext(Dispatchers.IO) { - val conn = openTtsConnection(voiceId = voiceId, apiKey = apiKey, request = request) - try { - val payload = buildRequestPayload(request) - conn.outputStream.use { it.write(payload.toByteArray()) } - - val code = conn.responseCode - if (code >= 400) { - val message = conn.errorStream?.readBytes()?.toString(Charsets.UTF_8) ?: "" - sink.fail() - throw IllegalStateException("ElevenLabs failed: $code $message") - } - - val buffer = ByteArray(8 * 1024) - conn.inputStream.use { input -> - while (true) { - val read = input.read(buffer) - if (read <= 0) break - sink.append(buffer.copyOf(read)) - } - } - sink.finish() - } finally { - conn.disconnect() - } - } - } - - private suspend fun streamPcm( - voiceId: String, - apiKey: String, - request: ElevenLabsRequest, - track: AudioTrack, - ) { - withContext(Dispatchers.IO) { - val conn = openTtsConnection(voiceId = voiceId, apiKey = apiKey, request = request) - try { - val payload = buildRequestPayload(request) - conn.outputStream.use { it.write(payload.toByteArray()) } - - val code = conn.responseCode - if (code >= 400) { - val message = conn.errorStream?.readBytes()?.toString(Charsets.UTF_8) ?: "" - throw IllegalStateException("ElevenLabs failed: $code $message") - } - - val buffer = ByteArray(8 * 1024) - conn.inputStream.use { input -> - while (true) { - if (pcmStopRequested) return@withContext - val read = input.read(buffer) - if (read <= 0) break - var offset = 0 - while (offset < read) { - if (pcmStopRequested) return@withContext - val wrote = - try { - track.write(buffer, offset, read - offset) - } catch (err: Throwable) { - if (pcmStopRequested) return@withContext - throw err - } - if (wrote <= 0) { - if (pcmStopRequested) return@withContext - throw IllegalStateException("AudioTrack write failed: $wrote") - } - offset += wrote - } - } - } - } finally { - conn.disconnect() - } - } - } - - private fun openTtsConnection( - voiceId: String, - apiKey: String, - request: ElevenLabsRequest, - ): HttpURLConnection { - val baseUrl = "https://api.elevenlabs.io/v1/text-to-speech/$voiceId/stream" - val latencyTier = request.latencyTier - val url = - if (latencyTier != null) { - URL("$baseUrl?optimize_streaming_latency=$latencyTier") - } else { - URL(baseUrl) - } - val conn = url.openConnection() as HttpURLConnection - conn.requestMethod = "POST" - conn.connectTimeout = 30_000 - conn.readTimeout = 30_000 - conn.setRequestProperty("Content-Type", "application/json") - conn.setRequestProperty("Accept", resolveAcceptHeader(request.outputFormat)) - conn.setRequestProperty("xi-api-key", apiKey) - conn.doOutput = true - return conn - } - - private fun resolveAcceptHeader(outputFormat: String?): String { - val normalized = outputFormat?.trim()?.lowercase().orEmpty() - return if (normalized.startsWith("pcm_")) "audio/pcm" else "audio/mpeg" - } - - private fun buildRequestPayload(request: ElevenLabsRequest): String { - val voiceSettingsEntries = - buildJsonObject { - request.speed?.let { put("speed", JsonPrimitive(it)) } - request.stability?.let { put("stability", JsonPrimitive(it)) } - request.similarity?.let { put("similarity_boost", JsonPrimitive(it)) } - request.style?.let { put("style", JsonPrimitive(it)) } - request.speakerBoost?.let { put("use_speaker_boost", JsonPrimitive(it)) } - } - - val payload = - buildJsonObject { - put("text", JsonPrimitive(request.text)) - request.modelId?.takeIf { it.isNotEmpty() }?.let { put("model_id", JsonPrimitive(it)) } - request.outputFormat?.takeIf { it.isNotEmpty() }?.let { put("output_format", JsonPrimitive(it)) } - request.seed?.let { put("seed", JsonPrimitive(it)) } - request.normalize?.let { put("apply_text_normalization", JsonPrimitive(it)) } - request.language?.let { put("language_code", JsonPrimitive(it)) } - if (voiceSettingsEntries.isNotEmpty()) { - put("voice_settings", voiceSettingsEntries) - } - } - - return payload.toString() - } - - private data class ElevenLabsRequest( - val text: String, - val modelId: String?, - val outputFormat: String?, - val speed: Double?, - val stability: Double?, - val similarity: Double?, - val style: Double?, - val speakerBoost: Boolean?, - val seed: Long?, - val normalize: String?, - val language: String?, - val latencyTier: Int?, - ) - - private object TalkModeRuntime { - fun resolveSpeed(speed: Double?, rateWpm: Int?): Double? { - if (rateWpm != null && rateWpm > 0) { - val resolved = rateWpm.toDouble() / 175.0 - if (resolved <= 0.5 || resolved >= 2.0) return null - return resolved - } - if (speed != null) { - if (speed <= 0.5 || speed >= 2.0) return null - return speed - } - return null - } - - fun validatedUnit(value: Double?): Double? { - if (value == null) return null - if (value < 0 || value > 1) return null - return value - } - - fun validatedStability(value: Double?, modelId: String?): Double? { - if (value == null) return null - val normalized = modelId?.trim()?.lowercase() - if (normalized == "eleven_v3") { - return if (value == 0.0 || value == 0.5 || value == 1.0) value else null - } - return validatedUnit(value) - } - - fun validatedSeed(value: Long?): Long? { - if (value == null) return null - if (value < 0 || value > 4294967295L) return null - return value - } - - fun validatedNormalize(value: String?): String? { - val normalized = value?.trim()?.lowercase() ?: return null - return if (normalized in listOf("auto", "on", "off")) normalized else null - } - - fun validatedLanguage(value: String?): String? { - val normalized = value?.trim()?.lowercase() ?: return null - if (normalized.length != 2) return null - if (!normalized.all { it in 'a'..'z' }) return null - return normalized - } - - fun validatedOutputFormat(value: String?): String? { - val trimmed = value?.trim()?.lowercase() ?: return null - if (trimmed.isEmpty()) return null - if (trimmed.startsWith("mp3_")) return trimmed - return if (parsePcmSampleRate(trimmed) != null) trimmed else null - } - - fun validatedLatencyTier(value: Int?): Int? { - if (value == null) return null - if (value < 0 || value > 4) return null - return value - } - - fun parsePcmSampleRate(value: String?): Int? { - val trimmed = value?.trim()?.lowercase() ?: return null - if (!trimmed.startsWith("pcm_")) return null - val suffix = trimmed.removePrefix("pcm_") - val digits = suffix.takeWhile { it.isDigit() } - val rate = digits.toIntOrNull() ?: return null - return if (rate in setOf(16000, 22050, 24000, 44100)) rate else null - } - - fun isMessageTimestampAfter(timestamp: Double, sinceSeconds: Double): Boolean { - val sinceMs = sinceSeconds * 1000 - return if (timestamp > 10_000_000_000) { - timestamp >= sinceMs - 500 - } else { - timestamp >= sinceSeconds - 0.5 - } - } - } - - private fun ensureInterruptListener() { - if (!interruptOnSpeech || !_isEnabled.value) return - mainHandler.post { - if (stopRequested) return@post - if (!SpeechRecognizer.isRecognitionAvailable(context)) return@post - try { - if (recognizer == null) { - recognizer = SpeechRecognizer.createSpeechRecognizer(context).also { it.setRecognitionListener(listener) } - } - recognizer?.cancel() - startListeningInternal(markListening = false) - } catch (_: Throwable) { - // ignore - } - } - } - - private fun resolveVoiceAlias(value: String?): String? { - val trimmed = value?.trim().orEmpty() - if (trimmed.isEmpty()) return null - val normalized = normalizeAliasKey(trimmed) - voiceAliases[normalized]?.let { return it } - if (voiceAliases.values.any { it.equals(trimmed, ignoreCase = true) }) return trimmed - return if (isLikelyVoiceId(trimmed)) trimmed else null - } - - private suspend fun resolveVoiceId(preferred: String?, apiKey: String): String? { - val trimmed = preferred?.trim().orEmpty() - if (trimmed.isNotEmpty()) { - val resolved = resolveVoiceAlias(trimmed) - if (resolved != null) return resolved - Log.w(tag, "unknown voice alias $trimmed") - } - fallbackVoiceId?.let { return it } - - return try { - val voices = listVoices(apiKey) - val first = voices.firstOrNull() ?: return null - fallbackVoiceId = first.voiceId - if (defaultVoiceId.isNullOrBlank()) { - defaultVoiceId = first.voiceId - } - if (!voiceOverrideActive) { - currentVoiceId = first.voiceId - } - val name = first.name ?: "unknown" - Log.d(tag, "default voice selected $name (${first.voiceId})") - first.voiceId - } catch (err: Throwable) { - Log.w(tag, "list voices failed: ${err.message ?: err::class.simpleName}") - null - } - } - - private suspend fun listVoices(apiKey: String): List { - return withContext(Dispatchers.IO) { - val url = URL("https://api.elevenlabs.io/v1/voices") - val conn = url.openConnection() as HttpURLConnection - conn.requestMethod = "GET" - conn.connectTimeout = 15_000 - conn.readTimeout = 15_000 - conn.setRequestProperty("xi-api-key", apiKey) - - val code = conn.responseCode - val stream = if (code >= 400) conn.errorStream else conn.inputStream - val data = stream.readBytes() - if (code >= 400) { - val message = data.toString(Charsets.UTF_8) - throw IllegalStateException("ElevenLabs voices failed: $code $message") - } - - val root = json.parseToJsonElement(data.toString(Charsets.UTF_8)).asObjectOrNull() - val voices = (root?.get("voices") as? JsonArray) ?: JsonArray(emptyList()) - voices.mapNotNull { entry -> - val obj = entry.asObjectOrNull() ?: return@mapNotNull null - val voiceId = obj["voice_id"].asStringOrNull() ?: return@mapNotNull null - val name = obj["name"].asStringOrNull() - ElevenLabsVoice(voiceId, name) - } - } - } - - private fun isLikelyVoiceId(value: String): Boolean { - if (value.length < 10) return false - return value.all { it.isLetterOrDigit() || it == '-' || it == '_' } - } - - private fun normalizeAliasKey(value: String): String = - value.trim().lowercase() - - private data class ElevenLabsVoice(val voiceId: String, val name: String?) - - private val listener = - object : RecognitionListener { - override fun onReadyForSpeech(params: Bundle?) { - if (_isEnabled.value) { - _statusText.value = if (_isListening.value) "Listening" else _statusText.value - } - } - - override fun onBeginningOfSpeech() {} - - override fun onRmsChanged(rmsdB: Float) {} - - override fun onBufferReceived(buffer: ByteArray?) {} - - override fun onEndOfSpeech() { - scheduleRestart() - } - - override fun onError(error: Int) { - if (stopRequested) return - _isListening.value = false - if (error == SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS) { - _statusText.value = "Microphone permission required" - return - } - - _statusText.value = - when (error) { - SpeechRecognizer.ERROR_AUDIO -> "Audio error" - SpeechRecognizer.ERROR_CLIENT -> "Client error" - SpeechRecognizer.ERROR_NETWORK -> "Network error" - SpeechRecognizer.ERROR_NETWORK_TIMEOUT -> "Network timeout" - SpeechRecognizer.ERROR_NO_MATCH -> "Listening" - SpeechRecognizer.ERROR_RECOGNIZER_BUSY -> "Recognizer busy" - SpeechRecognizer.ERROR_SERVER -> "Server error" - SpeechRecognizer.ERROR_SPEECH_TIMEOUT -> "Listening" - else -> "Speech error ($error)" - } - scheduleRestart(delayMs = 600) - } - - override fun onResults(results: Bundle?) { - val list = results?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION).orEmpty() - list.firstOrNull()?.let { handleTranscript(it, isFinal = true) } - scheduleRestart() - } - - override fun onPartialResults(partialResults: Bundle?) { - val list = partialResults?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION).orEmpty() - list.firstOrNull()?.let { handleTranscript(it, isFinal = false) } - } - - override fun onEvent(eventType: Int, params: Bundle?) {} - } -} - -private fun JsonElement?.asObjectOrNull(): JsonObject? = this as? JsonObject - -private fun JsonElement?.asStringOrNull(): String? = - (this as? JsonPrimitive)?.takeIf { it.isString }?.content - -private fun JsonElement?.asDoubleOrNull(): Double? { - val primitive = this as? JsonPrimitive ?: return null - return primitive.content.toDoubleOrNull() -} - -private fun JsonElement?.asBooleanOrNull(): Boolean? { - val primitive = this as? JsonPrimitive ?: return null - val content = primitive.content.trim().lowercase() - return when (content) { - "true", "yes", "1" -> true - "false", "no", "0" -> false - else -> null - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/voice/VoiceWakeCommandExtractor.kt b/apps/android/app/src/main/java/ai/openclaw/android/voice/VoiceWakeCommandExtractor.kt deleted file mode 100644 index dccd3950c90..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/voice/VoiceWakeCommandExtractor.kt +++ /dev/null @@ -1,40 +0,0 @@ -package ai.openclaw.android.voice - -object VoiceWakeCommandExtractor { - fun extractCommand(text: String, triggerWords: List): String? { - val raw = text.trim() - if (raw.isEmpty()) return null - - val triggers = - triggerWords - .map { it.trim().lowercase() } - .filter { it.isNotEmpty() } - .distinct() - if (triggers.isEmpty()) return null - - val alternation = triggers.joinToString("|") { Regex.escape(it) } - // Match: " " - val regex = Regex("(?i)(?:^|\\s)($alternation)\\b[\\s\\p{Punct}]*([\\s\\S]+)$") - val match = regex.find(raw) ?: return null - val extracted = match.groupValues.getOrNull(2)?.trim().orEmpty() - if (extracted.isEmpty()) return null - - val cleaned = extracted.trimStart { it.isWhitespace() || it.isPunctuation() }.trim() - if (cleaned.isEmpty()) return null - return cleaned - } -} - -private fun Char.isPunctuation(): Boolean { - return when (Character.getType(this)) { - Character.CONNECTOR_PUNCTUATION.toInt(), - Character.DASH_PUNCTUATION.toInt(), - Character.START_PUNCTUATION.toInt(), - Character.END_PUNCTUATION.toInt(), - Character.INITIAL_QUOTE_PUNCTUATION.toInt(), - Character.FINAL_QUOTE_PUNCTUATION.toInt(), - Character.OTHER_PUNCTUATION.toInt(), - -> true - else -> false - } -} diff --git a/apps/android/app/src/main/java/ai/openclaw/android/voice/VoiceWakeManager.kt b/apps/android/app/src/main/java/ai/openclaw/android/voice/VoiceWakeManager.kt deleted file mode 100644 index 334f985a028..00000000000 --- a/apps/android/app/src/main/java/ai/openclaw/android/voice/VoiceWakeManager.kt +++ /dev/null @@ -1,173 +0,0 @@ -package ai.openclaw.android.voice - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.os.Handler -import android.os.Looper -import android.speech.RecognitionListener -import android.speech.RecognizerIntent -import android.speech.SpeechRecognizer -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch - -class VoiceWakeManager( - private val context: Context, - private val scope: CoroutineScope, - private val onCommand: suspend (String) -> Unit, -) { - private val mainHandler = Handler(Looper.getMainLooper()) - - private val _isListening = MutableStateFlow(false) - val isListening: StateFlow = _isListening - - private val _statusText = MutableStateFlow("Off") - val statusText: StateFlow = _statusText - - var triggerWords: List = emptyList() - private set - - private var recognizer: SpeechRecognizer? = null - private var restartJob: Job? = null - private var lastDispatched: String? = null - private var stopRequested = false - - fun setTriggerWords(words: List) { - triggerWords = words - } - - fun start() { - mainHandler.post { - if (_isListening.value) return@post - stopRequested = false - - if (!SpeechRecognizer.isRecognitionAvailable(context)) { - _isListening.value = false - _statusText.value = "Speech recognizer unavailable" - return@post - } - - try { - recognizer?.destroy() - recognizer = SpeechRecognizer.createSpeechRecognizer(context).also { it.setRecognitionListener(listener) } - startListeningInternal() - } catch (err: Throwable) { - _isListening.value = false - _statusText.value = "Start failed: ${err.message ?: err::class.simpleName}" - } - } - } - - fun stop(statusText: String = "Off") { - stopRequested = true - restartJob?.cancel() - restartJob = null - mainHandler.post { - _isListening.value = false - _statusText.value = statusText - recognizer?.cancel() - recognizer?.destroy() - recognizer = null - } - } - - private fun startListeningInternal() { - val r = recognizer ?: return - val intent = - Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply { - putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM) - putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true) - putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 3) - putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, context.packageName) - } - - _statusText.value = "Listening" - _isListening.value = true - r.startListening(intent) - } - - private fun scheduleRestart(delayMs: Long = 350) { - if (stopRequested) return - restartJob?.cancel() - restartJob = - scope.launch { - delay(delayMs) - mainHandler.post { - if (stopRequested) return@post - try { - recognizer?.cancel() - startListeningInternal() - } catch (_: Throwable) { - // Will be picked up by onError and retry again. - } - } - } - } - - private fun handleTranscription(text: String) { - val command = VoiceWakeCommandExtractor.extractCommand(text, triggerWords) ?: return - if (command == lastDispatched) return - lastDispatched = command - - scope.launch { onCommand(command) } - _statusText.value = "Triggered" - scheduleRestart(delayMs = 650) - } - - private val listener = - object : RecognitionListener { - override fun onReadyForSpeech(params: Bundle?) { - _statusText.value = "Listening" - } - - override fun onBeginningOfSpeech() {} - - override fun onRmsChanged(rmsdB: Float) {} - - override fun onBufferReceived(buffer: ByteArray?) {} - - override fun onEndOfSpeech() { - scheduleRestart() - } - - override fun onError(error: Int) { - if (stopRequested) return - _isListening.value = false - if (error == SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS) { - _statusText.value = "Microphone permission required" - return - } - - _statusText.value = - when (error) { - SpeechRecognizer.ERROR_AUDIO -> "Audio error" - SpeechRecognizer.ERROR_CLIENT -> "Client error" - SpeechRecognizer.ERROR_NETWORK -> "Network error" - SpeechRecognizer.ERROR_NETWORK_TIMEOUT -> "Network timeout" - SpeechRecognizer.ERROR_NO_MATCH -> "Listening" - SpeechRecognizer.ERROR_RECOGNIZER_BUSY -> "Recognizer busy" - SpeechRecognizer.ERROR_SERVER -> "Server error" - SpeechRecognizer.ERROR_SPEECH_TIMEOUT -> "Listening" - else -> "Speech error ($error)" - } - scheduleRestart(delayMs = 600) - } - - override fun onResults(results: Bundle?) { - val list = results?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION).orEmpty() - list.firstOrNull()?.let(::handleTranscription) - scheduleRestart() - } - - override fun onPartialResults(partialResults: Bundle?) { - val list = partialResults?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION).orEmpty() - list.firstOrNull()?.let(::handleTranscription) - } - - override fun onEvent(eventType: Int, params: Bundle?) {} - } -} diff --git a/apps/android/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/apps/android/app/src/main/res/mipmap-anydpi/ic_launcher.xml deleted file mode 100644 index 6f379984a93..00000000000 --- a/apps/android/app/src/main/res/mipmap-anydpi/ic_launcher.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/apps/android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml deleted file mode 100644 index 6f379984a93..00000000000 --- a/apps/android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/apps/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 613e26663836ac2bb973b6af97d0072e5469fd01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10928 zcmch7Wl$a4)-CSt&SvAjarcco!7aGEySsaEcekJ+xWmB-!8JI+gY!7|-tT<($NTYq zy{=llX0J7Rjxno8byd&mXcZ-CR3suK2nYyNSsAd}$1L;rK!Ex$nK!41Tf3Fon{j)1m2>rkD z-@qg`soxL~P>0s)+HTs43jC&y_AJI`jwa?TUiMCZ10V#w_&-8>b2npvm%W{XE5DZz z@Lvf2kNEFpRv_SC5I0*Ppthn4K*G_*9Kg*2VgUh#kpKXIpo^IWzZzKTKevBe2?4F# z+?@DXSv@^HSv)yd99=9~+4%VQSV8Qp?Ci`R2xeDr2RCCcW(QZwe<%5$JYaKIQx|I| zH)}@+z~6a|O&s0bgn+=miT*kMt<%ZM(aq7-%F*c`ItSPP)b>#&>p$D9Y%Czw|62lC zCpS~hkJ=@@J{bO^_=DQ?UwU2L%vk>mz{(B+@iK$hnc4YR|55xQNbnyTehC+IGix_t zMPoB_fTy*a6+qh2(bCQwASNsLzheFe^}qE9{uc{B*xJ(C&Didfqq~c#xw^NLx$u8< znR>ANBhA6w)78|`%-ogL?B8(Lf5F{8;H+*g#?}tzW@2`hjxHY>?5#}|KU5hD{&y|^ z7nc7QIa1bk|DPoN!}K3nf~PvNLfGf~)yaQ^ESSMsVU)s;0*m$#|$t;RATkG};clHPrCi!lOn@r#2M zK#1LET4N+k7G2GSrBaq&cB4w2#KVv=Uq=FtU+!r3&873wc zh1iN>91B4&z^S7Ny(od8)ZY26!S+Kvm(?3BzQi}x-+sJ?-&Z39P=S%Dq2uguDdFbn za^3Cr0i%iy?|t2y-&`$-Sh*et9qXwxu%!gwPCVZ(Tm$a{GnDcy=HZuMzBE#oqgjs? z6}*oyiqrL0GKLP#LNz&=M&TJ}{~7;TQ4obs+{fl4v*cZGkMfg%C+zY>olhBZmUM&t zrmFk*!^5*9k0M6}Y90^Oh!;i}`5Stm`;2Gc!~jh)RS;p}p2PxHahRL1Ga4E5V;Ol_ zxpcXdb?z4_bw_66TDFB{XdeDwy=u^b?q?%7FywWQIK*LjjSU9qiPP=48Q@5Akv_do3yrp+}6&=!aI+ResT5YNsmtkM8R6IB|qws_-K*?Y%bzet%-$N1RE&bA8@h4*rK&@HGVN4y`x}8+()4$(lvb0 znaMhN8wO4=S%NBBx;juPjj`u??cMbDn^$bJH<=dJJ0l8o@)>P-*2vDJ0}MbcH`g*v zyQBkEvb&0+izv$hXeY?MSzW$vZ}rLPPf-UxBQ_kT9@uV25lm6d=~J&WdFO{XBqhtT z!$|RUiT=Nl8+!JkvTsx~qxsWtm zUAp7^$ZpMXTFw8^PB$HUo6dx_`cA;*e3C&y%FU_KWFIj21Ru1@TvW7{C_@@yC})YR zJC-rlwkAgVOHMSI&S(LiL}Q9`#VUDlxc1>E3^5bC2qel+kLP||+s?;x}8}}k3YsX@VIoFT>*Dv`Pe$L#3-oUt1zqB;^E3C0ix{Oc0ejFKR##b_&sjX6L7fZFQ2y+KLS2 zU_pz_2Rbvsh-4^GyMIZenKA+PSV$kK!#qS1P7T$sxuD_iDDVtOP9?<%Fg2X2?9}n1 z{BZH}TD3#p920yM2&W))MCF_4hNZ_9s8a^DN&5vFA&4L^j(#&8Gp^yJcj*Q@&1TRd zIbjh+Tu9%FX(pwB!nH!Ll8dB-Kq)~38;lN zD50ms4$Dc*ja_||-+DEj5xtvv)yJe~NX7^9HRb6dy+&BcL0xRdiZUe}g78D;$eS|+ zetmK_Gvm7vMA-GKZn!AIwCd>8oi8QGiG_n8)b^n>EPC%*OPwLb*iH?$E=k3+j13wy zWebPZSrv8w=uEki~w#Q`~e^9V}M<@v$4uHQ_{z38)Z zp=|IchtA%(TO2|#QK|x4>>I4HPk#`NiBFS}lrxlk*$V;{p9cG%!g2M9b6~B!c@s%( z3+J|lSS*nsU@|#;uKJ5%XF92&%-Sm$7W#S^G{GA#XCuiC_%zs-cI+}K761TbL5V|I zGaX_;J0(FC*YiyAs?3Q#p1avY=6bPI2Dn%sI^yGb#*m2)#EP0gUkIkh3FpU|H+}}I z_62h&a|BUfVj9C;VX0g#A!GSV)Tb9~&Kfg7%1&KlK+bO>LFW{KMA3|7PG(V2@Ds9L z5AuGgZ}74^vea6R{-}LM6WeH3?%8;{YMIOE^0LT}_d3>Rtjm0*I|5h-<&FtKDJ}#x zTOzGO@^vS*H5wRhOi8y92Z)@vQ$+A-yr~5q;<067eIGW{TWx6$3ldLIn?y(u8^wUm z#I~0MMlY%dv()*63BHjda+y0FeXHH>hm%hm?)}t@7oMIaO@s>p1>aeQ4m#>hZB7T8wr`55>-U88ZnDNNO3F%O?Ad))OxuDP+gGH zK4@MX>+j62uT)~|&U~z^?bbF6-PnUd@)%^{Hk{HA-S7}C$IqA zVj8}UJ}lY~aHYt%W&4&d<#^P*>TU2`m`w+N^Z0yR^<_|x#RZ+!mtu9&yIa*yJ&*@`%WTqLDTqti+aLrnt};s|8c6cZQfj-Ie|QMNRE14*~q9 ziCr(&T)Mb<0xn7QuWu0{!5I|;`6mS}W`3^@d&uoEYxmT+(m*g`dMB{kjzeT)pSiZq z8b&cvzHut?=V)N2ySTdzvyfNB=f|G-hM6WoD3}(@1+V@mSugmsgFnk( zLVfps;)!@kofCNqzpMD2Qvb@+(n%!!V(Wibg6{2VdwhlKJ$ew;gQ<#GOZ5_9!7Dju zb$P-o5nEC%xPipasS09*pT5uT z$qdp|FZ)NfJhFT~9-u-+GEab4CI0HXyuuXvJ*YQ=hXU-Pk&G3LAeJa>9gzm5B&dj~ zg*k|kMD1dGImFJKicdNh-_(k$<*-NlBVLKFew8KPkD6^)n3X#Ss~Tmh2Eulta~`Jk z*H3a21PLX0V}Q&m3m)P18FFnP8gmr+$dQMaB(rDn7b=KbCW)7stwy1}TBD|CG`&`u zFaVQYnxKV|K{18+;x@i)PD?nxT5nwvzbcxs7;;Rx0t$~AtOG7eho&5>Oj<{uLxYfjMY21q#Y~ z%YvTMDbPb$qi9*qay2!*)SU_BqxbXmuFcZPFrt@6gXLgnb%O8idFVIdm$c(#vH&vR zCGD!LK*sJs^f#xcW*r;%NP3AQ&m;V#jEqHt_h5HY7c34THJROhE2*9@)|PvXVt7H5 zl`s^=%*Y=f#Z>;eP|+_b?*$7-vCV9Ow8qqLll4+B{+HM(8Y)T&FJq&fz$pbWfQpwG zWZS00x53zBYIk{OVEMN8QfcRoOrq05=*kfjSJShN<+#HbTSE2)lLzZbTLw@HVh?uD z;7o3eo1(Mw@>KnbmpeqB4(-*z3>3YdGegsC#LpoutyHGS{)HJN14RmksqDu`a=r}< zY+VkHl<+u(knQNoluRRU9-xy%sSy5h(Mik$UmPsUkR{rTXejCdU6} zUfjwa3T!)FFCb~qTD46bV`;=18$$mw`tGH5qg`g+z6N(t26a3oN+`^+EF;t`shS1d z%ND&QmEw*pz+rl8n0$c9v0;mvz!3%|Y$~tb86g(jIMaaY?VQ#SWhN&*=2aOvZ*3JP zi8&RqC!vc#jY%>|GKNUcgH@mfsfrO_RFP}K-8E08jRopVZx8&&&TnG=?&JAeIgzt` z56^H#j(>bxa;vj8TX@+;N~dxIZApG4bA4zpE*962227{OjuAZK^=(w~d7c2%W_=8g zJzRl2^+=GAcMnSQDd*xyVjaljw1ceN(YOp1?h%}&Z6|T#ZY`i?0{Q+)Y@k|4R04sl zT1jCUtc!n)piJDcV?8Vr8^M6+9n|o?tzSk{V%ye?8|^}l-pKUHMYxUTytc-U$=`s* zHo^|!7*n|whKu_)+;Wn+&zoq1U4dyMSpYNp0r~`-M-vTBNlikZIKT5FHcreJ7dzc9 zNe!~Z{F>WaDX~fG2(0E52yzm}$CIx%8jGo7h+qos2eO!j!e_+%@DbuY;8#A85|70% z&5zTXt~D+-r-U}tpRJ_;TfThH}kClCC|dztP&bFoP?us zbP+e|ro(p1SPlTOKd!#OMg`x3(a!1ZEf7pWB9q=P@*^psUiK*38V}(Qa5M0`h|i>U zuPW1^$lyZQ`p?gC8R8wQ7{P^heSFxx$!1w&Y|+n|i1|FU42h3)zLi`S~Ymi0xqF>!)9Emej1XJc-O`=j7rk%HAic-X106z*yGEB#M9UZWs^pq|k_i(= zQ2(%C^K#;Id7tbsXM+DloRhMkqYtsL=F0#1N~-eAspBH=9*X5)8PuT?2?DQyp zo`6S9<#;(qD%p2K4e-=6Bg@o)1n&sR`j@jHW*wWwq+{H-KC%7hwChvpK4?NGW2I{@`l{eGX6UrmBRj7Z+k8J5| z3_l84+A0)QQA)LB8dyM3GcD36Cs-b_IG8a6shD^?2P|oNjMjJz=`##tQqO|v9G2&N zA<`>+Jso&-&T@1|wwJ1T&F_8h__>K#`?YUoU;)d`j^OIM#?$_TF3u#^G1M$eNvJtF zo?y-y%)>gXr(lvcWAWlwLF=yQ9k%wNs({)oj?$2TK6ebMPS|{xuxRmYw5zdS2n*TB zgMY&K*sub-h-H)c7moBVrox^xY*^d};(W)5`JTa#D_`b?3@KHJrZ{kVPoFxK`BCw8cT5+n- z49Oxqgq#F{k}94t2ROl>hs0C*8>6KPv8Cpmn1Lr!lyjl{;cuo_7z1 zg_~83s%@h)Wq_oVmXY$xio~Vf1Pj{7_>cHYf)NR>Rvy`f6xdv4FggqJX>*k%mr~e> zn8!drA(7N{G9{We{5>B0WwJBPnOhWg@LvYV^v#Hb1AQukP{bQG>`nM*GWa+W9Ie(I)O88Yau6L-;@uo)HFG4W1}^tiTK27MiyrQ9YhioVOd z0E4(zVeqf1j~)hjoa121jwzC@Q?9=(Mn1U6Wn_3+uSZu%ew&VO%e*4{6=-dKQh&RC zVG_rFCQ-K=a(iLLNsDxyta)5L--kCIf3O@o!8alu*RN|ZlrW}A2^2^%`Aog}DNbbu ziY-)Sn)aeg6;Hd$Xjriy@=8$hwZ#smGS5>0nJzenX`qXa7M@N#jYxHXS2}};O9PCm z+BR1!fZ^TwT$KJT!#ve{tY=Hju%~E|scEqsiJ|w~x`fbkMbF3|E!&o0Z^bHq^P=aC zdn?-AB4huDsVQv6i@0k`|C?ep_QOTC(y4_5NIfJbbvzcjux%QrQ#g`mO!z$?tlOn) z#IHV5+%wgGrP#4n-|-DO;pAEeqL;y+xmbm9U4z`&MYhqD4yG|M!zw0|aW-cJNRBY= z?`JhJ42V-cp-AJ@yYSmiZI~I&$N|)hk|U=Fg&Z2U&~n(`9}Ce$xhPM~M}BCHet0yX zLG^L{Bx8oKg~RYZb!osYn6)CDP*_{J?pcfRH}PkQV;E}`ZvO6oCw+Av&NT)iz0MM4 zd@-z*?BlxV#ozU{Ce!639z{k?6v6t!E0sB2nW)*V?GS80Aa;o;Z5`7%TL?iKoC@4R zIMM2HKU&hjK(H%%H=bk`)u-3gAL%*YjmgoG_AK12RBYtB9ZaBAI6oa0IM|%KhI0G0 zsA%E&{P84`sg(oj#SYn-Z0Vo>1vd~6w*bsdEi<^Y>x=v3KdNYIx7iT+QdRiG6{ywA z$sFSzPQenr}*Z<3C3dn`rD2&)X$9CPIY2uPlosPa`XAyhRv= zgDkEr{b50+|B^bzaMHdAt$5VEaF36TUUhk(`8&CPC4AVZ1$T3y{5A^|g235&1 z>F$H`jKIp@3A|@eExlvT$!PtlNvP~mdTid+%ZhX57s~4pvolbvrp4pL-1`P1t4HZVgT+_a z{SOo1LNCS26D^DFzZ~|?-t;xB5uKLM z2Tjy~$fLRD&|VY_T!3AzlPW8nrKkd&7;UBLVc+X>j|osNl4fTAav>m*b(OXH#(?!X zoxys2Mn$Vk<5y+6J`Y*E-uR8ZXE{lZW*0^@snq*iVUs-F!%XV@g}ki+LHmzvGNj@a z@E!^i$n0KDS8qUky~fNTZ@7!Qc5X3hS01zmVc)t4Q5D8K2D!jxt}P~EI4jeNbQp%b`GodjrDa5Oq zx2i#p>FZxMRez3!WwKw5$|u5cWMRqROZcjS+lF7_k*MhV{2oncj8|&V*~R90Dr^Fh zdw&E!j4b9Qy&gDfZ{>~MMIuZ_1J&qm`Y4mAD7H0?e-K2|lm{{FhNIz&68I)viY$Jy z2ttP90l|=)AVU~^4T+R##^higzcthEm^}~8Syk7;hespOi>qtS3M)TmB!Mc#7Vz!q z@4$>kp~(2g+`K;wS)Bf$BY2+ZfR#Li^{ZUyh4ROjf`ZtQYTh{LS|h>c3+LL2-$HnI zZp^{6@JpqF+0O{G+k9PE4q(J0x}Co&+2yTsFO-axJ!ivaWvV&1gN=3~D2dq(ukzfF zSw`+n%x=Sj9+TV;)QfW>B&!h`k+nrujx`^g1q8^J=4F_v?#rhP5`X#$pfVe# z&!s9_7A8H^Joec!n9A~73?x*Pq*i-YHNlZaai}LxTkefytuQKcy|7@7e{|;L94@!M ze~arLv@FTCH0eFL&CVnY#~l<=gMT89k;_4_Q{b_6LHMLi!Hr=T0>=g9cY$4!XyT|; zE-`b$fdKz-x($ns*Vk76Hi=M5OLm$##de56uFQ1rhtf&#BSW{mnTS1r{t^&!0D)Z7 z|EEVj@BBHi(~sp?kdOW;Hp`c(-frB7GF@%dxyzPWI0Q-9de3dT(re^TfrDd}ULL@A z64DVRK(}FldlsM&@hAH+jnU@g@!*WNn93KdD~LzHKu>OjS`cU9ThkhFa=%klfJZG_ znTx2H$Sx8L)e_zw%UgU<$1F_``<3o~1i+HYGYGG7z|A+N%))_cFm9W?Kl5T~HMWB1 zeAL~Q(%PsNx}W9ck(7{+)fCcA?EE`uSi6^hYMyA1*zkP!nm9M&37#!tz<9;7c$nM( z@}ZwoH9A1xtPSE-f-xv-lpC8S!7}rUMa0*kD>DMBP~|(pthSKEn8kKug8}A4V-D3G zDow#L0}_2g0VWJy9eS?=XC2LQ(bTK!EyycD(Tjz3+na+9T*O9sTg^5#Uzt@+8MF-( z(kWvoIf->JSxN_7eq?g#aODdMXVzy#4@=0&)VblGNbwMqE2HlJb_a&zqN~Y{hT5Un zt?sC6;i$Ah9c2mc!p4vI*B9`iup9BoXt$S)ki5y+^>(htbAlA0l!IPf>|T327cUfZ z3J_VjkcVqR4`*Vo7R17b;@l|W6BG0qcE4+sa~AsC(+6gaRIuxL_n|4aUr-LLss-qvoAJ9*rUM=!!MMqyhFq1gX-+gY2xrzp| z{z#LCA3XAc*A9U|ML5hu`XWD{_XRe}RVd{=)8phe+EAew%0Y1XI%Cy^Sv1)BmEU9P zD#ueG@^@T*DG6MT=?WvmqPDx75{b-9N9)UV_>Mlb^lG747-cIY`O>xd*L|{Vij%vNe=F*KOzV+CBwV zIQ<&Gokx!mkYqC{v*uR{PsfEKP=UCK)v9f;=xPz6)W0js!{?>h>e}+X20Lvi-i>E_ zJ%smz2MvFx+73oOrLfpAZ~{WY(~ty~vaQs8vCO)7Z6fPRmJ*sYLwl;bSrKx4cgcHp zUoK%!_f7Z)6L5Yn2xE^cv>=T->9}-uwhgSOPa#ta;NY^7-8Q!94F&U1H`Lq*20CmF z>Ue3nJWWg(acb*VUHlr@6Z>*4PI@HU35n)aj$r5W2Q{q!FADdCj(3Cv;2ja{j`WUr zsy%T#GWV8ddniN&SVnj;9${*bV?PSsh3qzWA;ML%RR%HnkdT!nI}tAzS-P1=0ldaC zSw4BOMdD(Z%P|k>6}uf1UKmCQoQ4DMFHz$yOGY(5sI(qL7Y3Bf?NY0@KAg(;1addO zocD(p5aVnGuY+u_&p4S;$G3Koy)a;9oK@1`jd73B!5X%y7P%B?e=5*K2v6R$^~_g# z+q^YJz4ga5mimWkdPaTJWGttXk^I>>MR1 zPW9sJ?oUsK&^>I-0Brj8nFb7L6E`~BRPT*Asxg)Sh$2Z^k{J7yeVuVGqmN%lLt zCOKMyx;}Wry@ZgsN9BjYI8D=$nQ8y7#_%t%;NZ53k`arg?EO&7fr*A`}iIDr-! zb_*aywuYF}!?b=2Ua|(o=-TgR4QEQ$q>|VvFz)n;c+zPN!I(&SvereBM+F59Ggh`( z191|Xc>v}zFb{l?(k=)2qrnZ=bDOebz9H{i*jFg3w|6js>dP)~Ta*u^q)lgv&vd?y zo8)+Mz>tCTP!{z96f(Sm83ba%i&gKH{*O%)w4i5a%{va^zZTdh!Lu@7A*9}JAwzM)236?IS;8clW!QzX*cGXha05(Wkb3-T6ugtKHUzLmTo>5` zL%!0}f8l|cwO2Hb`^0noMe58amAFrJ7eSssM3xrT=>(S@u^V_~_Exws{o(XAT3dMD zTEu8&YlL_|E6{bU!+0vaCXjK0FFEaGg*imJFH71O41kt50>GfcAo4=UdIgafBL1*N zVhSTftpY3}h@dRzr$h}=UNk*Qg_L+MhA1s2>sIa6u#&46_!YxLuXfLnK~R-X#&hY7AlW)G4}M z5Wc%j6@Dk6*cci5_@+ZuD2)#x`D^mhK0hr1MuT|aOD0O zqS&Sj`i$1){|y=~2Y@>Ob9dNEZGU#JuSVn)yAH~RAFCYepnxhZTv4MHn?ufx8xL`j zGI!c9*&mb5?l@wW4DV|6(p$c# z@SD$QG!tg(vj+T!m6yG4mGjUU##BmXk}Kp31&z$FN=VSqpDex8{wJx7dPx%1>`QD+@MT9D9Q%OCl4(SfOobL zd1`@J=n4zQh9PA{c8>Gtar-6Kk(zr0*$Em)#6U=)YLvrm6U2J_Yt7-|bHRJq;d~Qo z+yGSgEbS`H+n&n(R`27&%_3@f==$Anbt+a6@m9VOXWYs(oZptAFUbg$V z%(ZbQ{-tk`c9S@?uC3 ziB8S890|LDNq>f(o@bKvo{#)^-RySU>~@9QbE$TL0MTRu*nAK$u;z5ED%J$9ua7Mg z@}F`X-}fKnD=x`}llJysfNp(QAreJ0rqv57g1Zt>Kr1sPzUf7o8BYBhr}2{|hQBsRXVUHwyVbzK{=? diff --git a/apps/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/apps/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index 22442bc1d80373b884c11241ab136536e8215e7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44702 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 FV1g-lDoFqU diff --git a/apps/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/apps/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index b1fd747de01176d1891e89132524fb6f42665fd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5655 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 diff --git a/apps/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/apps/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png deleted file mode 100644 index d26c0189852d3e650da64609a593c897b1f9d4ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21883 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 Hu0mjfHk*Ht diff --git a/apps/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/apps/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 038e3dc7a7091109da0b257c830a0e85a078c4cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17855 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 M07*qoM6N<$g6i--WdHyG diff --git a/apps/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/apps/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index a5d995c2ee236b987512e04d4c77bb147d648824..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36404 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 z 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

8CAw9^Et0+Ik1P$G%J3(c~@W*pws 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 Z{}(i@ivdtk##8_R002ovPDHLkV1m32Yd`=1 diff --git a/apps/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/apps/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index ceabff1f5626ea98dec97ecaa017ff2b27e6fe8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60935 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

CJIyW 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�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

nh%H3|uTrZt}2Zqr5kzig$6Gv`*Och#43v2d0k> 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

#-~bacT_zoo>2czsITYC+{&^+irjUp#D?W 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
dVxsQ8BG!t+R&>hk^@y5PK>mp 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 T`f7G300000NkvXXu0mjfBO3e< diff --git a/apps/android/app/src/main/res/values/colors.xml b/apps/android/app/src/main/res/values/colors.xml deleted file mode 100644 index dfadc94cf03..00000000000 --- a/apps/android/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,3 +0,0 @@ - - #0A0A0A - diff --git a/apps/android/app/src/main/res/values/strings.xml b/apps/android/app/src/main/res/values/strings.xml deleted file mode 100644 index 0098cee20f0..00000000000 --- a/apps/android/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - OpenClaw Node - diff --git a/apps/android/app/src/main/res/values/themes.xml b/apps/android/app/src/main/res/values/themes.xml deleted file mode 100644 index 3ac5d04d831..00000000000 --- a/apps/android/app/src/main/res/values/themes.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/apps/android/app/src/main/res/xml/backup_rules.xml b/apps/android/app/src/main/res/xml/backup_rules.xml deleted file mode 100644 index 21e592ca47a..00000000000 --- a/apps/android/app/src/main/res/xml/backup_rules.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/android/app/src/main/res/xml/data_extraction_rules.xml b/apps/android/app/src/main/res/xml/data_extraction_rules.xml deleted file mode 100644 index 46e58c54eb0..00000000000 --- a/apps/android/app/src/main/res/xml/data_extraction_rules.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/apps/android/app/src/main/res/xml/file_paths.xml b/apps/android/app/src/main/res/xml/file_paths.xml deleted file mode 100644 index 5e0f4f1ef3c..00000000000 --- a/apps/android/app/src/main/res/xml/file_paths.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/android/app/src/main/res/xml/network_security_config.xml b/apps/android/app/src/main/res/xml/network_security_config.xml deleted file mode 100644 index 7ac5f5cdd7b..00000000000 --- a/apps/android/app/src/main/res/xml/network_security_config.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - openclaw.local - - - ts.net - - diff --git a/apps/android/app/src/test/java/ai/openclaw/android/NodeForegroundServiceTest.kt b/apps/android/app/src/test/java/ai/openclaw/android/NodeForegroundServiceTest.kt deleted file mode 100644 index 7a81936ecd2..00000000000 --- a/apps/android/app/src/test/java/ai/openclaw/android/NodeForegroundServiceTest.kt +++ /dev/null @@ -1,43 +0,0 @@ -package ai.openclaw.android - -import android.app.Notification -import android.content.Intent -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotNull -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.Robolectric -import org.robolectric.RobolectricTestRunner -import org.robolectric.Shadows -import org.robolectric.annotation.Config - -@RunWith(RobolectricTestRunner::class) -@Config(sdk = [34]) -class NodeForegroundServiceTest { - @Test - fun buildNotificationSetsLaunchIntent() { - val service = Robolectric.buildService(NodeForegroundService::class.java).get() - val notification = buildNotification(service) - - val pendingIntent = notification.contentIntent - assertNotNull(pendingIntent) - - val savedIntent = Shadows.shadowOf(pendingIntent).savedIntent - assertNotNull(savedIntent) - assertEquals(MainActivity::class.java.name, savedIntent.component?.className) - - val expectedFlags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP - assertEquals(expectedFlags, savedIntent.flags and expectedFlags) - } - - private fun buildNotification(service: NodeForegroundService): Notification { - val method = - NodeForegroundService::class.java.getDeclaredMethod( - "buildNotification", - String::class.java, - String::class.java, - ) - method.isAccessible = true - return method.invoke(service, "Title", "Text") as Notification - } -} diff --git a/apps/android/app/src/test/java/ai/openclaw/android/WakeWordsTest.kt b/apps/android/app/src/test/java/ai/openclaw/android/WakeWordsTest.kt deleted file mode 100644 index 55730e2f5ab..00000000000 --- a/apps/android/app/src/test/java/ai/openclaw/android/WakeWordsTest.kt +++ /dev/null @@ -1,50 +0,0 @@ -package ai.openclaw.android - -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNull -import org.junit.Test - -class WakeWordsTest { - @Test - fun parseCommaSeparatedTrimsAndDropsEmpty() { - assertEquals(listOf("openclaw", "claude"), WakeWords.parseCommaSeparated(" openclaw , claude, , ")) - } - - @Test - fun sanitizeTrimsCapsAndFallsBack() { - val defaults = listOf("openclaw", "claude") - val long = "x".repeat(WakeWords.maxWordLength + 10) - val words = listOf(" ", " hello ", long) - - val sanitized = WakeWords.sanitize(words, defaults) - assertEquals(2, sanitized.size) - assertEquals("hello", sanitized[0]) - assertEquals("x".repeat(WakeWords.maxWordLength), sanitized[1]) - - assertEquals(defaults, WakeWords.sanitize(listOf(" ", ""), defaults)) - } - - @Test - fun sanitizeLimitsWordCount() { - val defaults = listOf("openclaw") - val words = (1..(WakeWords.maxWords + 5)).map { "w$it" } - val sanitized = WakeWords.sanitize(words, defaults) - assertEquals(WakeWords.maxWords, sanitized.size) - assertEquals("w1", sanitized.first()) - assertEquals("w${WakeWords.maxWords}", sanitized.last()) - } - - @Test - fun parseIfChangedSkipsWhenUnchanged() { - val current = listOf("openclaw", "claude") - val parsed = WakeWords.parseIfChanged(" openclaw , claude ", current) - assertNull(parsed) - } - - @Test - fun parseIfChangedReturnsUpdatedList() { - val current = listOf("openclaw") - val parsed = WakeWords.parseIfChanged(" openclaw , jarvis ", current) - assertEquals(listOf("openclaw", "jarvis"), parsed) - } -} diff --git a/apps/android/app/src/test/java/ai/openclaw/android/gateway/BonjourEscapesTest.kt b/apps/android/app/src/test/java/ai/openclaw/android/gateway/BonjourEscapesTest.kt deleted file mode 100644 index fe00e50a72d..00000000000 --- a/apps/android/app/src/test/java/ai/openclaw/android/gateway/BonjourEscapesTest.kt +++ /dev/null @@ -1,19 +0,0 @@ -package ai.openclaw.android.gateway - -import org.junit.Assert.assertEquals -import org.junit.Test - -class BonjourEscapesTest { - @Test - fun decodeNoop() { - assertEquals("", BonjourEscapes.decode("")) - assertEquals("hello", BonjourEscapes.decode("hello")) - } - - @Test - fun decodeDecodesDecimalEscapes() { - assertEquals("OpenClaw Gateway", BonjourEscapes.decode("OpenClaw\\032Gateway")) - assertEquals("A B", BonjourEscapes.decode("A\\032B")) - assertEquals("Peter\u2019s Mac", BonjourEscapes.decode("Peter\\226\\128\\153s Mac")) - } -} diff --git a/apps/android/app/src/test/java/ai/openclaw/android/node/AppUpdateHandlerTest.kt b/apps/android/app/src/test/java/ai/openclaw/android/node/AppUpdateHandlerTest.kt deleted file mode 100644 index 743ed92c6d5..00000000000 --- a/apps/android/app/src/test/java/ai/openclaw/android/node/AppUpdateHandlerTest.kt +++ /dev/null @@ -1,65 +0,0 @@ -package ai.openclaw.android.node - -import java.io.File -import org.junit.Assert.assertEquals -import org.junit.Assert.assertThrows -import org.junit.Test - -class AppUpdateHandlerTest { - @Test - fun parseAppUpdateRequest_acceptsHttpsWithMatchingHost() { - val req = - parseAppUpdateRequest( - paramsJson = - """{"url":"https://gw.example.com/releases/openclaw.apk","sha256":"${"a".repeat(64)}"}""", - connectedHost = "gw.example.com", - ) - - assertEquals("https://gw.example.com/releases/openclaw.apk", req.url) - assertEquals("a".repeat(64), req.expectedSha256) - } - - @Test - fun parseAppUpdateRequest_rejectsNonHttps() { - assertThrows(IllegalArgumentException::class.java) { - parseAppUpdateRequest( - paramsJson = """{"url":"http://gw.example.com/releases/openclaw.apk","sha256":"${"a".repeat(64)}"}""", - connectedHost = "gw.example.com", - ) - } - } - - @Test - fun parseAppUpdateRequest_rejectsHostMismatch() { - assertThrows(IllegalArgumentException::class.java) { - parseAppUpdateRequest( - paramsJson = """{"url":"https://evil.example.com/releases/openclaw.apk","sha256":"${"a".repeat(64)}"}""", - connectedHost = "gw.example.com", - ) - } - } - - @Test - fun parseAppUpdateRequest_rejectsInvalidSha256() { - assertThrows(IllegalArgumentException::class.java) { - parseAppUpdateRequest( - paramsJson = """{"url":"https://gw.example.com/releases/openclaw.apk","sha256":"bad"}""", - connectedHost = "gw.example.com", - ) - } - } - - @Test - fun sha256Hex_computesExpectedDigest() { - val tmp = File.createTempFile("openclaw-update-hash", ".bin") - try { - tmp.writeText("hello", Charsets.UTF_8) - assertEquals( - "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824", - sha256Hex(tmp), - ) - } finally { - tmp.delete() - } - } -} diff --git a/apps/android/app/src/test/java/ai/openclaw/android/node/CanvasControllerSnapshotParamsTest.kt b/apps/android/app/src/test/java/ai/openclaw/android/node/CanvasControllerSnapshotParamsTest.kt deleted file mode 100644 index dd1b9d5d19a..00000000000 --- a/apps/android/app/src/test/java/ai/openclaw/android/node/CanvasControllerSnapshotParamsTest.kt +++ /dev/null @@ -1,43 +0,0 @@ -package ai.openclaw.android.node - -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNull -import org.junit.Test - -class CanvasControllerSnapshotParamsTest { - @Test - fun parseSnapshotParamsDefaultsToJpeg() { - val params = CanvasController.parseSnapshotParams(null) - assertEquals(CanvasController.SnapshotFormat.Jpeg, params.format) - assertNull(params.quality) - assertNull(params.maxWidth) - } - - @Test - fun parseSnapshotParamsParsesPng() { - val params = CanvasController.parseSnapshotParams("""{"format":"png","maxWidth":900}""") - assertEquals(CanvasController.SnapshotFormat.Png, params.format) - assertEquals(900, params.maxWidth) - } - - @Test - fun parseSnapshotParamsParsesJpegAliases() { - assertEquals( - CanvasController.SnapshotFormat.Jpeg, - CanvasController.parseSnapshotParams("""{"format":"jpeg"}""").format, - ) - assertEquals( - CanvasController.SnapshotFormat.Jpeg, - CanvasController.parseSnapshotParams("""{"format":"jpg"}""").format, - ) - } - - @Test - fun parseSnapshotParamsClampsQuality() { - val low = CanvasController.parseSnapshotParams("""{"quality":0.01}""") - assertEquals(0.1, low.quality) - - val high = CanvasController.parseSnapshotParams("""{"quality":5}""") - assertEquals(1.0, high.quality) - } -} diff --git a/apps/android/app/src/test/java/ai/openclaw/android/node/ConnectionManagerTest.kt b/apps/android/app/src/test/java/ai/openclaw/android/node/ConnectionManagerTest.kt deleted file mode 100644 index 534b90a2121..00000000000 --- a/apps/android/app/src/test/java/ai/openclaw/android/node/ConnectionManagerTest.kt +++ /dev/null @@ -1,76 +0,0 @@ -package ai.openclaw.android.node - -import ai.openclaw.android.gateway.GatewayEndpoint -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNull -import org.junit.Test - -class ConnectionManagerTest { - @Test - fun resolveTlsParamsForEndpoint_prefersStoredPinOverAdvertisedFingerprint() { - val endpoint = - GatewayEndpoint( - stableId = "_openclaw-gw._tcp.|local.|Test", - name = "Test", - host = "10.0.0.2", - port = 18789, - tlsEnabled = true, - tlsFingerprintSha256 = "attacker", - ) - - val params = - ConnectionManager.resolveTlsParamsForEndpoint( - endpoint, - storedFingerprint = "legit", - manualTlsEnabled = false, - ) - - assertEquals("legit", params?.expectedFingerprint) - assertEquals(false, params?.allowTOFU) - } - - @Test - fun resolveTlsParamsForEndpoint_doesNotTrustAdvertisedFingerprintWhenNoStoredPin() { - val endpoint = - GatewayEndpoint( - stableId = "_openclaw-gw._tcp.|local.|Test", - name = "Test", - host = "10.0.0.2", - port = 18789, - tlsEnabled = true, - tlsFingerprintSha256 = "attacker", - ) - - val params = - ConnectionManager.resolveTlsParamsForEndpoint( - endpoint, - storedFingerprint = null, - manualTlsEnabled = false, - ) - - assertNull(params?.expectedFingerprint) - assertEquals(false, params?.allowTOFU) - } - - @Test - fun resolveTlsParamsForEndpoint_manualRespectsManualTlsToggle() { - val endpoint = GatewayEndpoint.manual(host = "example.com", port = 443) - - val off = - ConnectionManager.resolveTlsParamsForEndpoint( - endpoint, - storedFingerprint = null, - manualTlsEnabled = false, - ) - assertNull(off) - - val on = - ConnectionManager.resolveTlsParamsForEndpoint( - endpoint, - storedFingerprint = null, - manualTlsEnabled = true, - ) - assertNull(on?.expectedFingerprint) - assertEquals(false, on?.allowTOFU) - } -} diff --git a/apps/android/app/src/test/java/ai/openclaw/android/node/JpegSizeLimiterTest.kt b/apps/android/app/src/test/java/ai/openclaw/android/node/JpegSizeLimiterTest.kt deleted file mode 100644 index 5de1dd5451a..00000000000 --- a/apps/android/app/src/test/java/ai/openclaw/android/node/JpegSizeLimiterTest.kt +++ /dev/null @@ -1,47 +0,0 @@ -package ai.openclaw.android.node - -import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue -import org.junit.Test -import kotlin.math.min - -class JpegSizeLimiterTest { - @Test - fun compressesLargePayloadsUnderLimit() { - val maxBytes = 5 * 1024 * 1024 - val result = - JpegSizeLimiter.compressToLimit( - initialWidth = 4000, - initialHeight = 3000, - startQuality = 95, - maxBytes = maxBytes, - encode = { width, height, quality -> - val estimated = (width.toLong() * height.toLong() * quality.toLong()) / 100 - val size = min(maxBytes.toLong() * 2, estimated).toInt() - ByteArray(size) - }, - ) - - assertTrue(result.bytes.size <= maxBytes) - assertTrue(result.width <= 4000) - assertTrue(result.height <= 3000) - assertTrue(result.quality <= 95) - } - - @Test - fun keepsSmallPayloadsAsIs() { - val maxBytes = 5 * 1024 * 1024 - val result = - JpegSizeLimiter.compressToLimit( - initialWidth = 800, - initialHeight = 600, - startQuality = 90, - maxBytes = maxBytes, - encode = { _, _, _ -> ByteArray(120_000) }, - ) - - assertEquals(800, result.width) - assertEquals(600, result.height) - assertEquals(90, result.quality) - } -} diff --git a/apps/android/app/src/test/java/ai/openclaw/android/node/SmsManagerTest.kt b/apps/android/app/src/test/java/ai/openclaw/android/node/SmsManagerTest.kt deleted file mode 100644 index a3d61329b4a..00000000000 --- a/apps/android/app/src/test/java/ai/openclaw/android/node/SmsManagerTest.kt +++ /dev/null @@ -1,91 +0,0 @@ -package ai.openclaw.android.node - -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.json.jsonPrimitive -import org.junit.Assert.assertEquals -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Test - -class SmsManagerTest { - private val json = SmsManager.JsonConfig - - @Test - fun parseParamsRejectsEmptyPayload() { - val result = SmsManager.parseParams("", json) - assertTrue(result is SmsManager.ParseResult.Error) - val error = result as SmsManager.ParseResult.Error - assertEquals("INVALID_REQUEST: paramsJSON required", error.error) - } - - @Test - fun parseParamsRejectsInvalidJson() { - val result = SmsManager.parseParams("not-json", json) - assertTrue(result is SmsManager.ParseResult.Error) - val error = result as SmsManager.ParseResult.Error - assertEquals("INVALID_REQUEST: expected JSON object", error.error) - } - - @Test - fun parseParamsRejectsNonObjectJson() { - val result = SmsManager.parseParams("[]", json) - assertTrue(result is SmsManager.ParseResult.Error) - val error = result as SmsManager.ParseResult.Error - assertEquals("INVALID_REQUEST: expected JSON object", error.error) - } - - @Test - fun parseParamsRejectsMissingTo() { - val result = SmsManager.parseParams("{\"message\":\"Hi\"}", json) - assertTrue(result is SmsManager.ParseResult.Error) - val error = result as SmsManager.ParseResult.Error - assertEquals("INVALID_REQUEST: 'to' phone number required", error.error) - assertEquals("Hi", error.message) - } - - @Test - fun parseParamsRejectsMissingMessage() { - val result = SmsManager.parseParams("{\"to\":\"+1234\"}", json) - assertTrue(result is SmsManager.ParseResult.Error) - val error = result as SmsManager.ParseResult.Error - assertEquals("INVALID_REQUEST: 'message' text required", error.error) - assertEquals("+1234", error.to) - } - - @Test - fun parseParamsTrimsToField() { - val result = SmsManager.parseParams("{\"to\":\" +1555 \",\"message\":\"Hello\"}", json) - assertTrue(result is SmsManager.ParseResult.Ok) - val ok = result as SmsManager.ParseResult.Ok - assertEquals("+1555", ok.params.to) - assertEquals("Hello", ok.params.message) - } - - @Test - fun buildPayloadJsonEscapesFields() { - val payload = SmsManager.buildPayloadJson( - json = json, - ok = false, - to = "+1\"23", - error = "SMS_SEND_FAILED: \"nope\"", - ) - val parsed = json.parseToJsonElement(payload).jsonObject - assertEquals("false", parsed["ok"]?.jsonPrimitive?.content) - assertEquals("+1\"23", parsed["to"]?.jsonPrimitive?.content) - assertEquals("SMS_SEND_FAILED: \"nope\"", parsed["error"]?.jsonPrimitive?.content) - } - - @Test - fun buildSendPlanUsesMultipartWhenMultipleParts() { - val plan = SmsManager.buildSendPlan("hello") { listOf("a", "b") } - assertTrue(plan.useMultipart) - assertEquals(listOf("a", "b"), plan.parts) - } - - @Test - fun buildSendPlanFallsBackToSinglePartWhenDividerEmpty() { - val plan = SmsManager.buildSendPlan("hello") { emptyList() } - assertFalse(plan.useMultipart) - assertEquals(listOf("hello"), plan.parts) - } -} diff --git a/apps/android/app/src/test/java/ai/openclaw/android/protocol/OpenClawCanvasA2UIActionTest.kt b/apps/android/app/src/test/java/ai/openclaw/android/protocol/OpenClawCanvasA2UIActionTest.kt deleted file mode 100644 index c767d2eb910..00000000000 --- a/apps/android/app/src/test/java/ai/openclaw/android/protocol/OpenClawCanvasA2UIActionTest.kt +++ /dev/null @@ -1,49 +0,0 @@ -package ai.openclaw.android.protocol - -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.jsonObject -import org.junit.Assert.assertEquals -import org.junit.Test - -class OpenClawCanvasA2UIActionTest { - @Test - fun extractActionNameAcceptsNameOrAction() { - val nameObj = Json.parseToJsonElement("{\"name\":\"Hello\"}").jsonObject - assertEquals("Hello", OpenClawCanvasA2UIAction.extractActionName(nameObj)) - - val actionObj = Json.parseToJsonElement("{\"action\":\"Wave\"}").jsonObject - assertEquals("Wave", OpenClawCanvasA2UIAction.extractActionName(actionObj)) - - val fallbackObj = - Json.parseToJsonElement("{\"name\":\" \",\"action\":\"Fallback\"}").jsonObject - assertEquals("Fallback", OpenClawCanvasA2UIAction.extractActionName(fallbackObj)) - } - - @Test - fun formatAgentMessageMatchesSharedSpec() { - val msg = - OpenClawCanvasA2UIAction.formatAgentMessage( - actionName = "Get Weather", - sessionKey = "main", - surfaceId = "main", - sourceComponentId = "btnWeather", - host = "Peter’s iPad", - instanceId = "ipad16,6", - contextJson = "{\"city\":\"Vienna\"}", - ) - - assertEquals( - "CANVAS_A2UI action=Get_Weather session=main surface=main component=btnWeather host=Peter_s_iPad instance=ipad16_6 ctx={\"city\":\"Vienna\"} default=update_canvas", - msg, - ) - } - - @Test - fun jsDispatchA2uiStatusIsStable() { - val js = OpenClawCanvasA2UIAction.jsDispatchA2UIActionStatus(actionId = "a1", ok = true, error = null) - assertEquals( - "window.dispatchEvent(new CustomEvent('openclaw:a2ui-action-status', { detail: { id: \"a1\", ok: true, error: \"\" } }));", - js, - ) - } -} diff --git a/apps/android/app/src/test/java/ai/openclaw/android/protocol/OpenClawProtocolConstantsTest.kt b/apps/android/app/src/test/java/ai/openclaw/android/protocol/OpenClawProtocolConstantsTest.kt deleted file mode 100644 index 10ab733ae53..00000000000 --- a/apps/android/app/src/test/java/ai/openclaw/android/protocol/OpenClawProtocolConstantsTest.kt +++ /dev/null @@ -1,35 +0,0 @@ -package ai.openclaw.android.protocol - -import org.junit.Assert.assertEquals -import org.junit.Test - -class OpenClawProtocolConstantsTest { - @Test - fun canvasCommandsUseStableStrings() { - assertEquals("canvas.present", OpenClawCanvasCommand.Present.rawValue) - assertEquals("canvas.hide", OpenClawCanvasCommand.Hide.rawValue) - assertEquals("canvas.navigate", OpenClawCanvasCommand.Navigate.rawValue) - assertEquals("canvas.eval", OpenClawCanvasCommand.Eval.rawValue) - assertEquals("canvas.snapshot", OpenClawCanvasCommand.Snapshot.rawValue) - } - - @Test - fun a2uiCommandsUseStableStrings() { - assertEquals("canvas.a2ui.push", OpenClawCanvasA2UICommand.Push.rawValue) - assertEquals("canvas.a2ui.pushJSONL", OpenClawCanvasA2UICommand.PushJSONL.rawValue) - assertEquals("canvas.a2ui.reset", OpenClawCanvasA2UICommand.Reset.rawValue) - } - - @Test - fun capabilitiesUseStableStrings() { - assertEquals("canvas", OpenClawCapability.Canvas.rawValue) - assertEquals("camera", OpenClawCapability.Camera.rawValue) - assertEquals("screen", OpenClawCapability.Screen.rawValue) - assertEquals("voiceWake", OpenClawCapability.VoiceWake.rawValue) - } - - @Test - fun screenCommandsUseStableStrings() { - assertEquals("screen.record", OpenClawScreenCommand.Record.rawValue) - } -} diff --git a/apps/android/app/src/test/java/ai/openclaw/android/ui/chat/SessionFiltersTest.kt b/apps/android/app/src/test/java/ai/openclaw/android/ui/chat/SessionFiltersTest.kt deleted file mode 100644 index 8e9e5800095..00000000000 --- a/apps/android/app/src/test/java/ai/openclaw/android/ui/chat/SessionFiltersTest.kt +++ /dev/null @@ -1,35 +0,0 @@ -package ai.openclaw.android.ui.chat - -import ai.openclaw.android.chat.ChatSessionEntry -import org.junit.Assert.assertEquals -import org.junit.Test - -class SessionFiltersTest { - @Test - fun sessionChoicesPreferMainAndRecent() { - val now = 1_700_000_000_000L - val recent1 = now - 2 * 60 * 60 * 1000L - val recent2 = now - 5 * 60 * 60 * 1000L - val stale = now - 26 * 60 * 60 * 1000L - val sessions = - listOf( - ChatSessionEntry(key = "recent-1", updatedAtMs = recent1), - ChatSessionEntry(key = "main", updatedAtMs = stale), - ChatSessionEntry(key = "old-1", updatedAtMs = stale), - ChatSessionEntry(key = "recent-2", updatedAtMs = recent2), - ) - - val result = resolveSessionChoices("main", sessions, mainSessionKey = "main", nowMs = now).map { it.key } - assertEquals(listOf("main", "recent-1", "recent-2"), result) - } - - @Test - fun sessionChoicesIncludeCurrentWhenMissing() { - val now = 1_700_000_000_000L - val recent = now - 10 * 60 * 1000L - val sessions = listOf(ChatSessionEntry(key = "main", updatedAtMs = recent)) - - val result = resolveSessionChoices("custom", sessions, mainSessionKey = "main", nowMs = now).map { it.key } - assertEquals(listOf("main", "custom"), result) - } -} diff --git a/apps/android/app/src/test/java/ai/openclaw/android/voice/TalkDirectiveParserTest.kt b/apps/android/app/src/test/java/ai/openclaw/android/voice/TalkDirectiveParserTest.kt deleted file mode 100644 index 77d62849c6c..00000000000 --- a/apps/android/app/src/test/java/ai/openclaw/android/voice/TalkDirectiveParserTest.kt +++ /dev/null @@ -1,55 +0,0 @@ -package ai.openclaw.android.voice - -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNull -import org.junit.Assert.assertTrue -import org.junit.Test - -class TalkDirectiveParserTest { - @Test - fun parsesDirectiveAndStripsHeader() { - val input = """ - {"voice":"voice-123","once":true} - Hello from talk mode. - """.trimIndent() - val result = TalkDirectiveParser.parse(input) - assertEquals("voice-123", result.directive?.voiceId) - assertEquals(true, result.directive?.once) - assertEquals("Hello from talk mode.", result.stripped.trim()) - } - - @Test - fun ignoresUnknownKeysButReportsThem() { - val input = """ - {"voice":"abc","foo":1,"bar":"baz"} - Hi there. - """.trimIndent() - val result = TalkDirectiveParser.parse(input) - assertEquals("abc", result.directive?.voiceId) - assertTrue(result.unknownKeys.containsAll(listOf("bar", "foo"))) - } - - @Test - fun parsesAlternateKeys() { - val input = """ - {"model_id":"eleven_v3","similarity_boost":0.4,"no_speaker_boost":true,"rate":200} - Speak. - """.trimIndent() - val result = TalkDirectiveParser.parse(input) - assertEquals("eleven_v3", result.directive?.modelId) - assertEquals(0.4, result.directive?.similarity) - assertEquals(false, result.directive?.speakerBoost) - assertEquals(200, result.directive?.rateWpm) - } - - @Test - fun returnsNullWhenNoDirectivePresent() { - val input = """ - {} - Hello. - """.trimIndent() - val result = TalkDirectiveParser.parse(input) - assertNull(result.directive) - assertEquals(input, result.stripped) - } -} diff --git a/apps/android/app/src/test/java/ai/openclaw/android/voice/VoiceWakeCommandExtractorTest.kt b/apps/android/app/src/test/java/ai/openclaw/android/voice/VoiceWakeCommandExtractorTest.kt deleted file mode 100644 index 76b50d8abcd..00000000000 --- a/apps/android/app/src/test/java/ai/openclaw/android/voice/VoiceWakeCommandExtractorTest.kt +++ /dev/null @@ -1,25 +0,0 @@ -package ai.openclaw.android.voice - -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNull -import org.junit.Test - -class VoiceWakeCommandExtractorTest { - @Test - fun extractsCommandAfterTriggerWord() { - val res = VoiceWakeCommandExtractor.extractCommand("Claude take a photo", listOf("openclaw", "claude")) - assertEquals("take a photo", res) - } - - @Test - fun extractsCommandWithPunctuation() { - val res = VoiceWakeCommandExtractor.extractCommand("hey openclaw, what's the weather?", listOf("openclaw")) - assertEquals("what's the weather?", res) - } - - @Test - fun returnsNullWhenNoCommandProvided() { - assertNull(VoiceWakeCommandExtractor.extractCommand("claude", listOf("claude"))) - assertNull(VoiceWakeCommandExtractor.extractCommand("hey claude!", listOf("claude"))) - } -} diff --git a/apps/android/build.gradle.kts b/apps/android/build.gradle.kts deleted file mode 100644 index f79902d5615..00000000000 --- a/apps/android/build.gradle.kts +++ /dev/null @@ -1,6 +0,0 @@ -plugins { - id("com.android.application") version "8.13.2" apply false - id("org.jetbrains.kotlin.android") version "2.2.21" apply false - id("org.jetbrains.kotlin.plugin.compose") version "2.2.21" apply false - id("org.jetbrains.kotlin.plugin.serialization") version "2.2.21" apply false -} diff --git a/apps/android/gradle.properties b/apps/android/gradle.properties deleted file mode 100644 index 5f84d966ee8..00000000000 --- a/apps/android/gradle.properties +++ /dev/null @@ -1,5 +0,0 @@ -org.gradle.jvmargs=-Xmx3g -Dfile.encoding=UTF-8 --enable-native-access=ALL-UNNAMED -org.gradle.warning.mode=none -android.useAndroidX=true -android.nonTransitiveRClass=true -android.enableR8.fullMode=true diff --git a/apps/android/gradle/wrapper/gradle-wrapper.jar b/apps/android/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e6441136f3d4ba8a0da8d277868979cfbc8ad796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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
NnX)EH+Nua)3Y(c z&{(nX_ht=QbJ%DzAya}!&uNu!4V0xI)QE$SY__m)SAKcN0P(&JcoK*Lxr@P zY&P=}&B3*UWNlc|&$Oh{BEqwK2+N2U$4WB7Fd|aIal`FGANUa9E-O)!gV`((ZGCc$ zBJA|FFrlg~9OBp#f7aHodCe{6= zay$6vN~zj1ddMZ9gQ4p32(7wD?(dE>KA2;SOzXRmPBiBc6g`eOsy+pVcHu=;Yd8@{ zSGgXf@%sKKQz~;!J;|2fC@emm#^_rnO0esEn^QxXgJYd`#FPWOUU5b;9eMAF zZhfiZb|gk8aJIw*YLp4!*(=3l8Cp{(%p?ho22*vN9+5NLV0TTazNY$B5L6UKUrd$n zjbX%#m7&F#U?QNOBXkiiWB*_tk+H?N3`vg;1F-I+83{M2!8<^nydGr5XX}tC!10&e z7D36bLaB56WrjL&HiiMVtpff|K%|*{t*ltt^5ood{FOG0<>k&1h95qPio)2`eL${YAGIx(b4VN*~nKn6E~SIQUuRH zQ+5zP6jfnP$S0iJ@~t!Ai3o`X7biohli;E zT#yXyl{bojG@-TGZzpdVDXhbmF%F9+-^YSIv|MT1l3j zrxOFq>gd2%U}?6}8mIj?M zc077Zc9fq(-)4+gXv?Az26IO6eV`RAJz8e3)SC7~>%rlzDwySVx*q$ygTR5kW2ds- z!HBgcq0KON9*8Ff$X0wOq$`T7ml(@TF)VeoF}x1OttjuVHn3~sHrMB++}f7f9H%@f z=|kP_?#+fve@{0MlbkC9tyvQ_R?lRdRJ@$qcB(8*jyMyeME5ns6ypVI1Xm*Zr{DuS zZ!1)rQfa89c~;l~VkCiHI|PCBd`S*2RLNQM8!g9L6?n`^evQNEwfO@&JJRme+uopQX0%Jo zgd5G&#&{nX{o?TQwQvF1<^Cg3?2co;_06=~Hcb6~4XWpNFL!WU{+CK;>gH%|BLOh7@!hsa(>pNDAmpcuVO-?;Bic17R}^|6@8DahH)G z!EmhsfunLL|3b=M0MeK2vqZ|OqUqS8npxwge$w-4pFVXFq$_EKrZY?BuP@Az@(k`L z`ViQBSk`y+YwRT;&W| z2e3UfkCo^uTA4}Qmmtqs+nk#gNr2W4 zTH%hhErhB)pkXR{B!q5P3-OM+M;qu~f>}IjtF%>w{~K-0*jPVLl?Chz&zIdxp}bjx zStp&Iufr58FTQ36AHU)0+CmvaOpKF;W@sMTFpJ`j;3d)J_$tNQI^c<^1o<49Z(~K> z;EZTBaVT%14(bFw2ob@?JLQ2@(1pCdg3S%E4*dJ}dA*v}_a4_P(a`cHnBFJxNobAv zf&Zl-Yt*lhn-wjZsq<9v-IsXxAxMZ58C@e0!rzhJ+D@9^3~?~yllY^s$?&oNwyH!#~6x4gUrfxplCvK#!f z$viuszW>MFEcFL?>ux*((!L$;R?xc*myjRIjgnQX79@UPD$6Dz0jutM@7h_pq z0Zr)#O<^y_K6jfY^X%A-ip>P%3saX{!v;fxT-*0C_j4=UMH+Xth(XVkVGiiKE#f)q z%Jp=JT)uy{&}Iq2E*xr4YsJ5>w^=#-mRZ4vPXpI6q~1aFwi+lQcimO45V-JXP;>(Q zo={U`{=_JF`EQj87Wf}{Qy35s8r1*9Mxg({CvOt}?Vh9d&(}iI-quvs-rm~P;eRA@ zG5?1HO}puruc@S{YNAF3vmUc2B4!k*yi))<5BQmvd3tr}cIs#9)*AX>t`=~{f#Uz0 z0&Nk!7sSZwJe}=)-R^$0{yeS!V`Dh7w{w5rZ9ir!Z7Cd7dwZcK;BT#V0bzTt>;@Cl z#|#A!-IL6CZ@eHH!CG>OO8!%G8&8t4)Ro@}USB*k>oEUo0LsljsJ-%5Mo^MJF2I8- z#v7a5VdJ-Cd%(a+y6QwTmi+?f8Nxtm{g-+WGL>t;s#epv7ug>inqimZCVm!uT5Pf6 ziEgQt7^%xJf#!aPWbuC_3Nxfb&CFbQy!(8ANpkWLI4oSnH?Q3f?0k1t$3d+lkQs{~(>06l&v|MpcFsyAv zin6N!-;pggosR*vV=DO(#+}4ps|5$`udE%Kdmp?G7B#y%H`R|i8skKOd9Xzx8xgR$>Zo2R2Ytktq^w#ul4uicxW#{ zFjG_RNlBroV_n;a7U(KIpcp*{M~e~@>Q#Av90Jc5v%0c>egEdY4v3%|K1XvB{O_8G zkTWLC>OZKf;XguMH2-Pw{BKbFzaY;4v2seZV0>^7Q~d4O=AwaPhP3h|!hw5aqOtT@ z!SNz}$of**Bl3TK209@F=Tn1+mgZa8yh(Png%Zd6Mt}^NSjy)etQrF zme*llAW=N_8R*O~d2!apJnF%(JcN??=`$qs3Y+~xs>L9x`0^NIn!8mMRFA_tg`etw z3k{9JAjnl@ygIiJcNHTy02GMAvBVqEss&t2<2mnw!; zU`J)0>lWiqVqo|ex7!+@0i>B~BSU1A_0w#Ee+2pJx0BFiZ7RDHEvE*ptc9md(B{&+ zKE>TM)+Pd>HEmdJao7U@S>nL(qq*A)#eLOuIfAS@j`_sK0UEY6OAJJ-kOrHG zjHx`g!9j*_jRcJ%>CE9K2MVf?BUZKFHY?EpV6ai7sET-tqk=nDFh-(65rhjtlKEY% z@G&cQ<5BKatfdA1FKuB=i>CCC5(|9TMW%K~GbA4}80I5%B}(gck#Wlq@$nO3%@QP_ z8nvPkJFa|znk>V92cA!K1rKtr)skHEJD;k8P|R8RkCq1Rh^&}Evwa4BUJz2f!2=MH zo4j8Y$YL2313}H~F7@J7mh>u%556Hw0VUOz-Un@ZASCL)y8}4XXS`t1AC*^>PLwIc zUQok5PFS=*#)Z!3JZN&eZ6ZDP^-c@StY*t20JhCnbMxXf=LK#;`4KHEqMZ-Ly9KsS zI2VUJGY&PmdbM+iT)zek)#Qc#_i4uH43 z@T5SZBrhNCiK~~esjsO9!qBpaWK<`>!-`b71Y5ReXQ4AJU~T2Njri1CEp5oKw;Lnm)-Y@Z3sEY}XIgSy%xo=uek(kAAH5MsV$V3uTUsoTzxp_rF=tx zV07vlJNKtJhCu`b}*#m&5LV4TAE&%KtHViDAdv#c^x`J7bg z&N;#I2GkF@SIGht6p-V}`!F_~lCXjl1BdTLIjD2hH$J^YFN`7f{Q?OHPFEM$65^!u zNwkelo*5+$ZT|oQ%o%;rBX$+?xhvjb)SHgNHE_yP%wYkkvXHS{Bf$OiKJ5d1gI0j< zF6N}Aq=(WDo(J{e-uOecxPD>XZ@|u-tgTR<972`q8;&ZD!cep^@B5CaqFz|oU!iFj zU0;6fQX&~15E53EW&w1s9gQQ~Zk16X%6 zjG`j0yq}4deX2?Tr(03kg>C(!7a|b9qFI?jcE^Y>-VhudI@&LI6Qa}WQ>4H_!UVyF z((cm&!3gmq@;BD#5P~0;_2qgZhtJS|>WdtjY=q zLnHH~Fm!cxw|Z?Vw8*~?I$g#9j&uvgm7vPr#&iZgPP~v~BI4jOv;*OQ?jYJtzO<^y z7-#C={r7CO810!^s(MT!@@Vz_SVU)7VBi(e1%1rvS!?PTa}Uv`J!EP3s6Y!xUgM^8 z4f!fq<3Wer_#;u!5ECZ|^c1{|q_lh3m^9|nsMR1#Qm|?4Yp5~|er2?W^7~cl;_r4WSme_o68J9p03~Hc%X#VcX!xAu%1`R!dfGJCp zV*&m47>s^%Ib0~-2f$6oSgn3jg8m%UA;ArcdcRyM5;}|r;)?a^D*lel5C`V5G=c~k zy*w_&BfySOxE!(~PI$*dwG><+-%KT5p?whOUMA*k<9*gi#T{h3DAxzAPxN&Xws8o9Cp*`PA5>d9*Z-ynV# z9yY*1WR^D8|C%I@vo+d8r^pjJ$>eo|j>XiLWvTWLl(^;JHCsoPgem6PvegHb-OTf| zvTgsHSa;BkbG=(NgPO|CZu9gUCGr$8*EoH2_Z#^BnxF0yM~t`|9ws_xZ8X8iZYqh! zAh;HXJ)3P&)Q0(&F>!LN0g#bdbis-cQxyGn9Qgh`q+~49Fqd2epikEUw9caM%V6WgP)532RMRW}8gNS%V%Hx7apSz}tn@bQy!<=lbhmAH=FsMD?leawbnP5BWM0 z5{)@EEIYMu5;u)!+HQWhQ;D3_Cm_NADNeb-f56}<{41aYq8p4=93d=-=q0Yx#knGYfXVt z+kMxlus}t2T5FEyCN~!}90O_X@@PQpuy;kuGz@bWft%diBTx?d)_xWd_-(!LmVrh**oKg!1CNF&LX4{*j|) zIvjCR0I2UUuuEXh<9}oT_zT#jOrJAHNLFT~Ilh9hGJPI1<5`C-WA{tUYlyMeoy!+U zhA#=p!u1R7DNg9u4|QfED-2TuKI}>p#2P9--z;Bbf4Op*;Q9LCbO&aL2i<0O$ByoI z!9;Ght733FC>Pz>$_mw(F`zU?`m@>gE`9_p*=7o=7av`-&ifU(^)UU`Kg3Kw`h9-1 z6`e6+im=|m2v`pN(2dE%%n8YyQz;#3Q-|x`91z?gj68cMrHl}C25|6(_dIGk*8cA3 zRHB|Nwv{@sP4W+YZM)VKI>RlB`n=Oj~Rzx~M+Khz$N$45rLn6k1nvvD^&HtsMA4`s=MmuOJID@$s8Ph4E zAmSV^+s-z8cfv~Yd(40Sh4JG#F~aB>WFoX7ykaOr3JaJ&Lb49=B8Vk-SQT9%7TYhv z?-Pprt{|=Y5ZQ1?od|A<_IJU93|l4oAfBm?3-wk{O<8ea+`}u%(kub(LFo2zFtd?4 zwpN|2mBNywv+d^y_8#<$r>*5+$wRTCygFLcrwT(qc^n&@9r+}Kd_u@Ithz(6Qb4}A zWo_HdBj#V$VE#l6pD0a=NfB0l^6W^g`vm^sta>Tly?$E&{F?TTX~DsKF~poFfmN%2 z4x`Dc{u{Lkqz&y!33;X}weD}&;7p>xiI&ZUb1H9iD25a(gI|`|;G^NwJPv=1S5e)j z;U;`?n}jnY6rA{V^ zxTd{bK)Gi^odL3l989DQlN+Zs39Xe&otGeY(b5>rlIqfc7Ap4}EC?j<{M=hlH{1+d zw|c}}yx88_xQr`{98Z!d^FNH77=u(p-L{W6RvIn40f-BldeF-YD>p6#)(Qzf)lfZj z?3wAMtPPp>vMehkT`3gToPd%|D8~4`5WK{`#+}{L{jRUMt zrFz+O$C7y8$M&E4@+p+oV5c%uYzbqd2Y%SSgYy#xh4G3hQv>V*BnuKQhBa#=oZB~w{azUB+q%bRe_R^ z>fHBilnRTUfaJ201czL8^~Ix#+qOHSO)A|xWLqOxB$dT2W~)e-r9;bm=;p;RjYahB z*1hegN(VKK+ztr~h1}YP@6cfj{e#|sS`;3tJhIJK=tVJ-*h-5y9n*&cYCSdg#EHE# zSIx=r#qOaLJoVVf6v;(okg6?*L_55atl^W(gm^yjR?$GplNP>BZsBYEf_>wM0Lc;T zhf&gpzOWNxS>m+mN92N0{;4uw`P+9^*|-1~$uXpggj4- z^SFc4`uzj2OwdEVT@}Q`(^EcQ_5(ZtXTql*yGzdS&vrS_w>~~ra|Nb5abwf}Y!uq6R5f&6g2ge~2p(%c< z@O)cz%%rr4*cRJ5f`n@lvHNk@lE1a*96Kw6lJ~B-XfJW%?&-y?;E&?1AacU@`N`!O z6}V>8^%RZ7SQnZ-z$(jsX`amu*5Fj8g!3RTRwK^`2_QHe;_2y_n|6gSaGyPmI#kA0sYV<_qOZc#-2BO%hX)f$s-Z3xlI!ub z^;3ru11DA`4heAu%}HIXo&ctujzE2!6DIGE{?Zs>2}J+p&C$rc7gJC35gxhflorvsb%sGOxpuWhF)dL_&7&Z99=5M0b~Qa;Mo!j&Ti_kXW!86N%n= zSC@6Lw>UQ__F&+&Rzv?gscwAz8IP!n63>SP)^62(HK98nGjLY2*e^OwOq`3O|C92? z;TVhZ2SK%9AGW4ZavTB9?)mUbOoF`V7S=XM;#3EUpR+^oHtdV!GK^nXzCu>tpR|89 zdD{fnvCaN^^LL%amZ^}-E+214g&^56rpdc@yv0b<3}Ys?)f|fXN4oHf$six)-@<;W&&_kj z-B}M5U*1sb4)77aR=@%I?|Wkn-QJVuA96an25;~!gq(g1@O-5VGo7y&E_srxL6ZfS z*R%$gR}dyONgju*D&?geiSj7SZ@ftyA|}(*Y4KbvU!YLsi1EDQQCnb+-cM=K1io78o!v*);o<XwjaQH%)uIP&Zm?)Nfbfn;jIr z)d#!$gOe3QHp}2NBak@yYv3m(CPKkwI|{;d=gi552u?xj9ObCU^DJFQp4t4e1tPzM zvsRIGZ6VF+{6PvqsplMZWhz10YwS={?`~O0Ec$`-!klNUYtzWA^f9m7tkEzCy<_nS z=&<(awFeZvt51>@o_~>PLs05CY)$;}Oo$VDO)?l-{CS1Co=nxjqben*O1BR>#9`0^ zkwk^k-wcLCLGh|XLjdWv0_Hg54B&OzCE^3NCP}~OajK-LuRW53CkV~Su0U>zN%yQP zH8UH#W5P3-!ToO-2k&)}nFe`t+mdqCxxAHgcifup^gKpMObbox9LFK;LP3}0dP-UW z?Zo*^nrQ6*$FtZ(>kLCc2LY*|{!dUn$^RW~m9leoF|@Jy|M5p-G~j%+P0_#orRKf8 zvuu5<*XO!B?1E}-*SY~MOa$6c%2cM+xa8}_8x*aVn~57v&W(0mqN1W`5a7*VN{SUH zXz98DDyCnX2EPl-`Lesf`=AQT%YSDb`$%;(jUTrNen$NPJrlpPDP}prI>Ml!r6bCT;mjsg@X^#&<}CGf0JtR{Ecwd&)2zuhr#nqdgHj+g2n}GK9CHuwO zk>oZxy{vcOL)$8-}L^iVfJHAGfwN$prHjYV0ju}8%jWquw>}_W6j~m<}Jf!G?~r5&Rx)!9JNX!ts#SGe2HzobV5); zpj@&`cNcO&q+%*<%D7za|?m5qlmFK$=MJ_iv{aRs+BGVrs)98BlN^nMr{V_fcl_;jkzRju+c-y?gqBC_@J0dFLq-D9@VN&-`R9U;nv$Hg?>$oe4N&Ht$V_(JR3TG^! zzJsbQbi zFE6-{#9{G{+Z}ww!ycl*7rRdmU#_&|DqPfX3CR1I{Kk;bHwF6jh0opI`UV2W{*|nn zf_Y@%wW6APb&9RrbEN=PQRBEpM(N1w`81s=(xQj6 z-eO0k9=Al|>Ej|Mw&G`%q8e$2xVz1v4DXAi8G};R$y)ww638Y=9y$ZYFDM$}vzusg zUf+~BPX>(SjA|tgaFZr_e0{)+z9i6G#lgt=F_n$d=beAt0Sa0a7>z-?vcjl3e+W}+ z1&9=|vC=$co}-Zh*%3588G?v&U7%N1Qf-wNWJ)(v`iO5KHSkC5&g7CrKu8V}uQGcfcz zmBz#Lbqwqy#Z~UzHgOQ;Q-rPxrRNvl(&u6ts4~0=KkeS;zqURz%!-ERppmd%0v>iRlEf+H$yl{_8TMJzo0 z>n)`On|7=WQdsqhXI?#V{>+~}qt-cQbokEbgwV3QvSP7&hK4R{Z{aGHVS3;+h{|Hz z6$Js}_AJr383c_+6sNR|$qu6dqHXQTc6?(XWPCVZv=)D#6_;D_8P-=zOGEN5&?~8S zl5jQ?NL$c%O)*bOohdNwGIKM#jSAC?BVY={@A#c9GmX0=T(0G}xs`-%f3r=m6-cpK z!%waekyAvm9C3%>sixdZj+I(wQlbB4wv9xKI*T13DYG^T%}zZYJ|0$Oj^YtY+d$V$ zAVudSc-)FMl|54n=N{BnZTM|!>=bhaja?o7s+v1*U$!v!qQ%`T-6fBvmdPbVmro&d zk07TOp*KuxRUSTLRrBj{mjsnF8`d}rMViY8j`jo~Hp$fkv9F_g(jUo#Arp;Xw0M$~ zRIN!B22~$kx;QYmOkos@%|5k)!QypDMVe}1M9tZfkpXKGOxvKXB!=lo`p?|R1l=tA zp(1}c6T3Fwj_CPJwVsYtgeRKg?9?}%oRq0F+r+kdB=bFUdVDRPa;E~~>2$w}>O>v=?|e>#(-Lyx?nbg=ckJ#5U6;RT zNvHhXk$P}m9wSvFyU3}=7!y?Y z=fg$PbV8d7g25&-jOcs{%}wTDKm>!Vk);&rr;O1nvO0VrU&Q?TtYVU=ir`te8SLlS zKSNmV=+vF|ATGg`4$N1uS|n??f}C_4Sz!f|4Ly8#yTW-FBfvS48Tef|-46C(wEO_%pPhUC5$-~Y?!0vFZ^Gu`x=m7X99_?C-`|h zfmMM&Y@zdfitA@KPw4Mc(YHcY1)3*1xvW9V-r4n-9ZuBpFcf{yz+SR{ zo$ZSU_|fgwF~aakGr(9Be`~A|3)B=9`$M-TWKipq-NqRDRQc}ABo*s_5kV%doIX7LRLRau_gd@Rd_aLFXGSU+U?uAqh z8qusWWcvgQ&wu{|sRXmv?sl=xc<$6AR$+cl& zFNh5q1~kffG{3lDUdvEZu5c(aAG~+64FxdlfwY^*;JSS|m~CJusvi-!$XR`6@XtY2 znDHSz7}_Bx7zGq-^5{stTRy|I@N=>*y$zz>m^}^{d&~h;0kYiq8<^Wq7Dz0w31ShO^~LUfW6rfitR0(=3;Uue`Y%y@ex#eKPOW zO~V?)M#AeHB2kovn1v=n^D?2{2jhIQd9t|_Q+c|ZFaWt+r&#yrOu-!4pXAJuxM+Cx z*H&>eZ0v8Y`t}8{TV6smOj=__gFC=eah)mZt9gwz>>W$!>b3O;Rm^Ig*POZP8Rl0f zT~o=Nu1J|lO>}xX&#P58%Yl z83`HRs5#32Qm9mdCrMlV|NKNC+Z~ z9OB8xk5HJ>gBLi+m@(pvpw)1(OaVJKs*$Ou#@Knd#bk+V@y;YXT?)4eP9E5{J%KGtYinNYJUH9PU3A}66c>Xn zZ{Bn0<;8$WCOAL$^NqTjwM?5d=RHgw3!72WRo0c;+houoUA@HWLZM;^U$&sycWrFd zE7ekt9;kb0`lps{>R(}YnXlyGY}5pPd9zBpgXeJTY_jwaJGSJQC#-KJqmh-;ad&F- z-Y)E>!&`Rz!HtCz>%yOJ|v(u7P*I$jqEY3}(Z-orn4 zlI?CYKNl`6I){#2P1h)y(6?i;^z`N3bxTV%wNvQW+eu|x=kbj~s8rhCR*0H=iGkSj zk23lr9kr|p7#qKL=UjgO`@UnvzU)`&fI>1Qs7ubq{@+lK{hH* zvl6eSb9%yngRn^T<;jG1SVa)eA>T^XX=yUS@NCKpk?ovCW1D@!=@kn;l_BrG;hOTC z6K&H{<8K#dI(A+zw-MWxS+~{g$tI7|SfP$EYKxA}LlVO^sT#Oby^grkdZ^^lA}uEF zBSj$weBJG{+Bh@Yffzsw=HyChS(dtLE3i*}Zj@~!_T-Ay7z=B)+*~3|?w`Zd)Co2t zC&4DyB!o&YgSw+fJn6`sn$e)29`kUwAc+1MND7YjV%lO;H2}fNy>hD#=gT ze+-aFNpyKIoXY~Vq-}OWPBe?Rfu^{ps8>Xy%42r@RV#*QV~P83jdlFNgkPN=T|Kt7 zV*M`Rh*30&AWlb$;ae130e@}Tqi3zx2^JQHpM>j$6x`#{mu%tZlwx9Gj@Hc92IuY* zarmT|*d0E~vt6<+r?W^UW0&#U&)8B6+1+;k^2|FWBRP9?C4Rk)HAh&=AS8FS|NQaZ z2j!iZ)nbEyg4ZTp-zHwVlfLC~tXIrv(xrP8PAtR{*c;T24ycA-;auWsya-!kF~CWZ zw_uZ|%urXgUbc@x=L=_g@QJ@m#5beS@6W195Hn7>_}z@Xt{DIEA`A&V82bc^#!q8$ zFh?z_Vn|ozJ;NPd^5uu(9tspo8t%&-U9Ckay-s@DnM*R5rtu|4)~e)`z0P-sy?)kc zs_k&J@0&0!q4~%cKL)2l;N*T&0;mqX5T{Qy60%JtKTQZ-xb%KOcgqwJmb%MOOKk7N zgq})R_6**{8A|6H?fO+2`#QU)p$Ei2&nbj6TpLSIT^D$|`TcSeh+)}VMb}LmvZ{O| ze*1IdCt3+yhdYVxcM)Q_V0bIXLgr6~%JS<<&dxIgfL=Vnx4YHuU@I34JXA|+$_S3~ zy~X#gO_X!cSs^XM{yzDGNM>?v(+sF#<0;AH^YrE8smx<36bUsHbN#y57K8WEu(`qHvQ6cAZPo=J5C(lSmUCZ57Rj6cx!e^rfaI5%w}unz}4 zoX=nt)FVNV%QDJH`o!u9olLD4O5fl)xp+#RloZlaA92o3x4->?rB4`gS$;WO{R;Z3>cG3IgFX2EA?PK^M}@%1%A;?f6}s&CV$cIyEr#q5;yHdNZ9h{| z-=dX+a5elJoDo?Eq&Og!nN6A)5yYpnGEp}?=!C-V)(*~z-+?kY1Q7qs#Rsy%hu_60rdbB+QQNr?S1 z?;xtjUv|*E3}HmuNyB9aFL5H~3Ho0UsmuMZELp1a#CA1g`P{-mT?BchuLEtK}!QZ=3AWakRu~?f9V~3F;TV`5%9Pcs_$gq&CcU}r8gOO zC2&SWPsSG{&o-LIGTBqp6SLQZPvYKp$$7L4WRRZ0BR$Kf0I0SCFkqveCp@f)o8W)! z$%7D1R`&j7W9Q9CGus_)b%+B#J2G;l*FLz#s$hw{BHS~WNLODV#(!u_2Pe&tMsq={ zdm7>_WecWF#D=?eMjLj=-_z`aHMZ=3_-&E8;ibPmM}61i6J3is*=dKf%HC>=xbj4$ zS|Q-hWQ8T5mWde6h@;mS+?k=89?1FU<%qH9B(l&O>k|u_aD|DY*@~(`_pb|B#rJ&g zR0(~(68fpUPz6TdS@4JT5MOPrqDh5_H(eX1$P2SQrkvN8sTxwV>l0)Qq z0pzTuvtEAKRDkKGhhv^jk%|HQ1DdF%5oKq5BS>szk-CIke{%js?~%@$uaN3^Uz6Wf z_iyx{bZ(;9y4X&>LPV=L=d+A}7I4GkK0c1Xts{rrW1Q7apHf-))`BgC^0^F(>At1* za@e7{lq%yAkn*NH8Q1{@{lKhRg*^TfGvv!Sn*ed*x@6>M%aaqySxR|oNadYt1mpUZ z6H(rupHYf&Z z29$5g#|0MX#aR6TZ$@eGxxABRKakDYtD%5BmKp;HbG_ZbT+=81E&=XRk6m_3t9PvD zr5Cqy(v?gHcYvYvXkNH@S#Po~q(_7MOuCAB8G$a9BC##gw^5mW16cML=T=ERL7wsk zzNEayTG?mtB=x*wc@ifBCJ|irFVMOvH)AFRW8WE~U()QT=HBCe@s$dA9O!@`zAAT) zaOZ7l6vyR+Nk_OOF!ZlZmjoImKh)dxFbbR~z(cMhfeX1l7S_`;h|v3gI}n9$sSQ>+3@AFAy9=B_y$)q;Wdl|C-X|VV3w8 z2S#>|5dGA8^9%Bu&fhmVRrTX>Z7{~3V&0UpJNEl0=N32euvDGCJ>#6dUSi&PxFW*s zS`}TB>?}H(T2lxBJ!V#2taV;q%zd6fOr=SGHpoSG*4PDaiG0pdb5`jelVipkEk%FV zThLc@Hc_AL1#D&T4D=w@UezYNJ%0=f3iVRuVL5H?eeZM}4W*bomebEU@e2d`M<~uW zf#Bugwf`VezG|^Qbt6R_=U0}|=k;mIIakz99*>FrsQR{0aQRP6ko?5<7bkDN8evZ& zB@_KqQG?ErKL=1*ZM9_5?Pq%lcS4uLSzN(Mr5=t6xHLS~Ym`UgM@D&VNu8e?_=nSFtF$u@hpPSmI4Vo_t&v?>$~K4y(O~Rb*(MFy_igM7 z*~yYUyR6yQgzWnWMUgDov!!g=lInM+=lOmOk4L`O?{i&qxy&D*_qorRbDwj6?)!ef z#JLd7F6Z2I$S0iYI={rZNk*<{HtIl^mx=h>Cim*04K4+Z4IJtd*-)%6XV2(MCscPiw_a+y*?BKbTS@BZ3AUao^%Zi#PhoY9Vib4N>SE%4>=Jco0v zH_Miey{E;FkdlZSq)e<{`+S3W=*ttvD#hB8w=|2aV*D=yOV}(&p%0LbEWH$&@$X3x~CiF-?ejQ*N+-M zc8zT@3iwkdRT2t(XS`d7`tJQAjRmKAhiw{WOqpuvFp`i@Q@!KMhwKgsA}%@sw8Xo5Y=F zhRJZg)O4uqNWj?V&&vth*H#je6T}}p_<>!Dr#89q@uSjWv~JuW(>FqoJ5^ho0%K?E z9?x_Q;kmcsQ@5=}z@tdljMSt9-Z3xn$k)kEjK|qXS>EfuDmu(Z8|(W?gY6-l z@R_#M8=vxKMAoi&PwnaIYw2COJM@atcgfr=zK1bvjW?9B`-+Voe$Q+H$j!1$Tjn+* z&LY<%)L@;zhnJlB^Og6I&BOR-m?{IW;tyYC%FZ!&Z>kGjHJ6cqM-F z&19n+e1=9AH1VrVeHrIzqlC`w9=*zfmrerF?JMzO&|Mmv;!4DKc(sp+jy^Dx?(8>1 zH&yS_4yL7m&GWX~mdfgH*AB4{CKo;+egw=PrvkTaoBU+P-4u?E|&!c z)DKc;>$$B6u*Zr1SjUh2)FeuWLWHl5TH(UHWkf zLs>7px!c5n;rbe^lO@qlYLzlDVp(z?6rPZel=YB)Uv&n!2{+Mb$-vQl=xKw( zve&>xYx+jW_NJh!FV||r?;hdP*jOXYcLCp>DOtJ?2S^)DkM{{Eb zS$!L$e_o0(^}n3tA1R3-$SNvgBq;DOEo}fNc|tB%%#g4RA3{|euq)p+xd3I8^4E&m zFrD%}nvG^HUAIKe9_{tXB;tl|G<%>yk6R;8L2)KUJw4yHJXUOPM>(-+jxq4R;z8H#>rnJy*)8N+$wA$^F zN+H*3t)eFEgxLw+Nw3};4WV$qj&_D`%ADV2%r zJCPCo%{=z7;`F98(us5JnT(G@sKTZ^;2FVitXyLe-S5(hV&Ium+1pIUB(CZ#h|g)u zSLJJ<@HgrDiA-}V_6B^x1>c9B6%~847JkQ!^KLZ2skm;q*edo;UA)~?SghG8;QbHh z_6M;ouo_1rq9=x$<`Y@EA{C%6-pEV}B(1#sDoe_e1s3^Y>n#1Sw;N|}8D|s|VPd+g z-_$QhCz`vLxxrVMx3ape1xu3*wjx=yKSlM~nFgkNWb4?DDr*!?U)L_VeffF<+!j|b zZ$Wn2$TDv3C3V@BHpSgv3JUif8%hk%OsGZ=OxH@8&4`bbf$`aAMchl^qN>Eyu3JH} z9-S!x8-s4fE=lad%Pkp8hAs~u?|uRnL48O|;*DEU! zuS0{cpk%1E0nc__2%;apFsTm0bKtd&A0~S3Cj^?72-*Owk3V!ZG*PswDfS~}2<8le z5+W^`Y(&R)yVF*tU_s!XMcJS`;(Tr`J0%>p=Z&InR%D3@KEzzI+-2)HK zuoNZ&o=wUC&+*?ofPb0a(E6(<2Amd6%uSu_^-<1?hsxs~0K5^f(LsGqgEF^+0_H=uNk9S0bb!|O8d?m5gQjUKevPaO+*VfSn^2892K~%crWM8+6 z25@V?Y@J<9w%@NXh-2!}SK_(X)O4AM1-WTg>sj1{lj5@=q&dxE^9xng1_z9w9DK>| z6Iybcd0e zyi;Ew!KBRIfGPGytQ6}z}MeXCfLY0?9%RiyagSp_D1?N&c{ zyo>VbJ4Gy`@Fv+5cKgUgs~na$>BV{*em7PU3%lloy_aEovR+J7TfQKh8BJXyL6|P8un-Jnq(ghd!_HEOh$zlv2$~y3krgeH;9zC}V3f`uDtW(%mT#944DQa~^8ZI+zAUu4U(j0YcDfKR$bK#gvn_{JZ>|gZ5+)u?T$w7Q%F^;!Wk?G z(le7r!ufT*cxS}PR6hIVtXa)i`d$-_1KkyBU>qmgz-=T};uxx&sKgv48akIWQ89F{ z0XiY?WM^~;|T8zBOr zs#zuOONzH?svv*jokd5SK8wG>+yMC)LYL|vLqm^PMHcT=`}V$=nIRHe2?h)8WQa6O zPAU}d`1y(>kZiP~Gr=mtJLMu`i<2CspL|q2DqAgAD^7*$xzM`PU4^ga`ilE134XBQ z99P(LhHU@7qvl9Yzg$M`+dlS=x^(m-_3t|h>S}E0bcFMn=C|KamQ)=w2^e)35p`zY zRV8X?d;s^>Cof2SPR&nP3E+-LCkS0J$H!eh8~k0qo$}00b=7!H_I2O+Ro@3O$nPdm ztmbOO^B+IHzQ5w>@@@J4cKw5&^_w6s!s=H%&byAbUtczPQ7}wfTqxxtQNfn*u73Qw zGuWsrky_ajPx-5`R<)6xHf>C(oqGf_Fw|-U*GfS?xLML$kv;h_pZ@Kk$y0X(S+K80 z6^|z)*`5VUkawg}=z`S;VhZhxyDfrE0$(PMurAxl~<>lfZa>JZ288ULK7D` zl9|#L^JL}Y$j*j`0-K6kH#?bRmg#5L3iB4Z)%iF@SqT+Lp|{i`m%R-|ZE94Np7Pa5 zCqC^V3}B(FR340pmF*qaa}M}+h6}mqE~7Sh!9bDv9YRT|>vBNAqv09zXHMlcuhKD| zcjjA(b*XCIwJ33?CB!+;{)vX@9xns_b-VO{i0y?}{!sdXj1GM8+$#v>W7nw;+O_9B z_{4L;C6ol?(?W0<6taGEn1^uG=?Q3i29sE`RfYCaV$3DKc_;?HsL?D_fSYg}SuO5U zOB_f4^vZ_x%o`5|C@9C5+o=mFy@au{s)sKw!UgC&L35aH(sgDxRE2De%(%OT=VUdN ziVLEmdOvJ&5*tCMKRyXctCwQu_RH%;m*$YK&m;jtbdH#Ak~13T1^f89tn`A%QEHWs~jnY~E}p_Z$XC z=?YXLCkzVSK+Id`xZYTegb@W8_baLt-Fq`Tv|=)JPbFsKRm)4UW;yT+J`<)%#ue9DPOkje)YF2fsCilK9MIIK>p*`fkoD5nGfmLwt)!KOT+> zOFq*VZktDDyM3P5UOg`~XL#cbzC}eL%qMB=Q5$d89MKuN#$6|4gx_Jt0Gfn8w&q}%lq4QU%6#jT*MRT% zrLz~C8FYKHawn-EQWN1B75O&quS+Z81(zN)G>~vN8VwC+e+y(`>HcxC{MrJ;H1Z4k zZWuv$w_F0-Ub%MVcpIc){4PGL^I7M{>;hS?;eH!;gmcOE66z3;Z1Phqo(t zVP(Hg6q#0gIKgsg7L7WE!{Y#1nI(45tx2{$34dDd#!Z0NIyrm)HOn5W#7;f4pQci# zDW!FI(g4e668kI9{2+mLwB+=#9bfqgX%!B34V-$wwSN(_cm*^{y0jQtv*4}eO^sOV z*9xoNvX)c9isB}Tgx&ZRjp3kwhTVK?r9;n!x>^XYT z@Q^7zp{rkIs{2mUSE^2!Gf6$6;j~&4=-0cSJJDizZp6LTe8b45;{AKM%v99}{{FfC zz709%u0mC=1KXTo(=TqmZQ;c?$M3z(!xah>aywrj40sc2y3rKFw4jCq+Y+u=CH@_V zxz|qeTwa>+<|H%8Dz5u>ZI5MmjTFwXS-Fv!TDd*`>3{krWoNVx$<133`(ftS?ZPyY z&4@ah^3^i`vL$BZa>O|Nt?ucewzsF)0zX3qmM^|waXr=T0pfIb0*$AwU=?Ipl|1Y; z*Pk6{C-p4MY;j@IJ|DW>QHZQJcp;Z~?8(Q+Kk3^0qJ}SCk^*n4W zu9ZFwLHUx-$6xvaQ)SUQcYd6fF8&x)V`1bIuX@>{mE$b|Yd(qomn3;bPwnDUc0F=; zh*6_((%bqAYQWQ~odER?h>1mkL4kpb3s7`0m@rDKGU*oyF)$j~Ffd4fXV$?`f~rHf zB%Y)@5SXZvfwm10RY5X?TEo)PK_`L6qgBp=#>fO49$D zDq8Ozj0q6213tV5Qq=;fZ0$|KroY{Dz=l@lU^J)?Ko@ti20TRplXzphBi>XGx4bou zEWrkNjz0t5j!_ke{g5I#PUlEU$Km8g8TE|XK=MkU@PT4T><2OVamoK;wJ}3X0L$vX zgd7gNa359*nc)R-0!`2X@FOTB`+oETOPc=ubp5R)VQgY+5BTZZJ2?9QwnO=dnulIUF3gFn;BODC2)65)HeVd%t86sL7Rv^Y+nbn+&l z6BAJY(ETvwI)Ts$aiE8rht4KD*qNyE{8{x6R|%akbTBzw;2+6Echkt+W+`u^XX z_z&x%n '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m" "--enable-native-access=ALL-UNNAMED"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/apps/android/gradlew.bat b/apps/android/gradlew.bat deleted file mode 100644 index 6f8e9066584..00000000000 --- a/apps/android/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" "--enable-native-access=ALL-UNNAMED" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/apps/android/settings.gradle.kts b/apps/android/settings.gradle.kts deleted file mode 100644 index b3b43a44550..00000000000 --- a/apps/android/settings.gradle.kts +++ /dev/null @@ -1,18 +0,0 @@ -pluginManagement { - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) - repositories { - google() - mavenCentral() - } -} - -rootProject.name = "OpenClawNodeAndroid" -include(":app") diff --git a/apps/ios/.swiftlint.yml b/apps/ios/.swiftlint.yml deleted file mode 100644 index 23db4515968..00000000000 --- a/apps/ios/.swiftlint.yml +++ /dev/null @@ -1,9 +0,0 @@ -parent_config: ../../.swiftlint.yml - -included: - - Sources - - ../shared/ClawdisNodeKit/Sources - -type_body_length: - warning: 900 - error: 1300 diff --git a/apps/ios/Config/Signing.xcconfig b/apps/ios/Config/Signing.xcconfig deleted file mode 100644 index e0afd46aa7e..00000000000 --- a/apps/ios/Config/Signing.xcconfig +++ /dev/null @@ -1,18 +0,0 @@ -// Shared iOS signing defaults for local development + CI. -OPENCLAW_IOS_DEFAULT_TEAM = Y5PE65HELJ -OPENCLAW_IOS_SELECTED_TEAM = $(OPENCLAW_IOS_DEFAULT_TEAM) -OPENCLAW_APP_BUNDLE_ID = ai.openclaw.ios -OPENCLAW_WATCH_APP_BUNDLE_ID = ai.openclaw.ios.watchkitapp -OPENCLAW_WATCH_EXTENSION_BUNDLE_ID = ai.openclaw.ios.watchkitapp.extension - -// Local contributors can override this by running scripts/ios-configure-signing.sh. -// Keep include after defaults: xcconfig is evaluated top-to-bottom. -#include? "../.local-signing.xcconfig" -#include? "../LocalSigning.xcconfig" - -CODE_SIGN_STYLE = Automatic -CODE_SIGN_IDENTITY = Apple Development -DEVELOPMENT_TEAM = $(OPENCLAW_IOS_SELECTED_TEAM) - -// Let Xcode manage provisioning for the selected local team. -PROVISIONING_PROFILE_SPECIFIER = diff --git a/apps/ios/LocalSigning.xcconfig.example b/apps/ios/LocalSigning.xcconfig.example deleted file mode 100644 index bfa610fb350..00000000000 --- a/apps/ios/LocalSigning.xcconfig.example +++ /dev/null @@ -1,14 +0,0 @@ -// Copy to LocalSigning.xcconfig for personal local signing overrides. -// This file is only an example and should stay committed. - -OPENCLAW_CODE_SIGN_STYLE = Automatic -OPENCLAW_DEVELOPMENT_TEAM = P5Z8X89DJL - -OPENCLAW_APP_BUNDLE_ID = ai.openclaw.ios.test.mariano -OPENCLAW_SHARE_BUNDLE_ID = ai.openclaw.ios.test.mariano.share -OPENCLAW_WATCH_APP_BUNDLE_ID = ai.openclaw.ios.test.mariano.watchkitapp -OPENCLAW_WATCH_EXTENSION_BUNDLE_ID = ai.openclaw.ios.test.mariano.watchkitapp.extension - -// Leave empty with automatic signing. -OPENCLAW_APP_PROFILE = -OPENCLAW_SHARE_PROFILE = diff --git a/apps/ios/README.md b/apps/ios/README.md deleted file mode 100644 index c7c501fcbff..00000000000 --- a/apps/ios/README.md +++ /dev/null @@ -1,141 +0,0 @@ -# OpenClaw iOS (Super Alpha) - -NO TEST FLIGHT AVAILABLE AT THIS POINT - -This iPhone app is super-alpha and internal-use only. It connects to an OpenClaw Gateway as a `role: node`. - -## Distribution Status - -NO TEST FLIGHT AVAILABLE AT THIS POINT - -- Current distribution: local/manual deploy from source via Xcode. -- App Store flow is not part of the current internal development path. - -## Super-Alpha Disclaimer - -- Breaking changes are expected. -- UI and onboarding flows can change without migration guarantees. -- Foreground use is the only reliable mode right now. -- Treat this build as sensitive while permissions and background behavior are still being hardened. - -## Exact Xcode Manual Deploy Flow - -1. Prereqs: - - Xcode 16+ - - `pnpm` - - `xcodegen` - - Apple Development signing set up in Xcode -2. From repo root: - -```bash -pnpm install -./scripts/ios-configure-signing.sh -cd apps/ios -xcodegen generate -open OpenClaw.xcodeproj -``` - -3. In Xcode: - - Scheme: `OpenClaw` - - Destination: connected iPhone (recommended for real behavior) - - Build configuration: `Debug` - - Run (`Product` -> `Run`) -4. If signing fails on a personal team: - - Use unique local bundle IDs via `apps/ios/LocalSigning.xcconfig`. - - Start from `apps/ios/LocalSigning.xcconfig.example`. - -Shortcut command (same flow + open project): - -```bash -pnpm ios:open -``` - -## APNs Expectations For Local/Manual Builds - -- The app calls `registerForRemoteNotifications()` at launch. -- `apps/ios/Sources/OpenClaw.entitlements` sets `aps-environment` to `development`. -- APNs token registration to gateway happens only after gateway connection (`push.apns.register`). -- Your selected team/profile must support Push Notifications for the app bundle ID you are signing. -- If push capability or provisioning is wrong, APNs registration fails at runtime (check Xcode logs for `APNs registration failed`). -- Debug builds register as APNs sandbox; Release builds use production. - -## What Works Now (Concrete) - -- Pairing via setup code flow (`/pair` then `/pair approve` in Telegram). -- Gateway connection via discovery or manual host/port with TLS fingerprint trust prompt. -- Chat + Talk surfaces through the operator gateway session. -- iPhone node commands in foreground: camera snap/clip, canvas present/navigate/eval/snapshot, screen record, location, contacts, calendar, reminders, photos, motion, local notifications. -- Share extension deep-link forwarding into the connected gateway session. - -## Location Automation Use Case (Testing) - -Use this for automation signals ("I moved", "I arrived", "I left"), not as a keep-awake mechanism. - -- Product intent: - - movement-aware automations driven by iOS location events - - example: arrival/exit geofence, significant movement, visit detection -- Non-goal: - - continuous GPS polling just to keep the app alive - -Test path to include in QA runs: - -1. Enable location permission in app: - - set `Always` permission - - verify background location capability is enabled in the build profile -2. Background the app and trigger movement: - - walk/drive enough for a significant location update, or cross a configured geofence -3. Validate gateway side effects: - - node reconnect/wake if needed - - expected location/movement event arrives at gateway - - automation trigger executes once (no duplicate storm) -4. Validate resource impact: - - no sustained high thermal state - - no excessive background battery drain over a short observation window - -Pass criteria: - -- movement events are delivered reliably enough for automation UX -- no location-driven reconnect spam loops -- app remains stable after repeated background/foreground transitions - -## Known Issues / Limitations / Problems - -- Foreground-first: iOS can suspend sockets in background; reconnect recovery is still being tuned. -- Background command limits are strict: `canvas.*`, `camera.*`, `screen.*`, and `talk.*` are blocked when backgrounded. -- Background location requires `Always` location permission. -- Pairing/auth errors intentionally pause reconnect loops until a human fixes auth/pairing state. -- Voice Wake and Talk contend for the same microphone; Talk suppresses wake capture while active. -- APNs reliability depends on local signing/provisioning/topic alignment. -- Expect rough UX edges and occasional reconnect churn during active development. - -## Current In-Progress Workstream - -Automatic wake/reconnect hardening: - -- improve wake/resume behavior across scene transitions -- reduce dead-socket states after background -> foreground -- tighten node/operator session reconnect coordination -- reduce manual recovery steps after transient network failures - -## Debugging Checklist - -1. Confirm build/signing baseline: - - regenerate project (`xcodegen generate`) - - verify selected team + bundle IDs -2. In app `Settings -> Gateway`: - - confirm status text, server, and remote address - - verify whether status shows pairing/auth gating -3. If pairing is required: - - run `/pair approve` from Telegram, then reconnect -4. If discovery is flaky: - - enable `Discovery Debug Logs` - - inspect `Settings -> Gateway -> Discovery Logs` -5. If network path is unclear: - - switch to manual host/port + TLS in Gateway Advanced settings -6. In Xcode console, filter for subsystem/category signals: - - `ai.openclaw.ios` - - `GatewayDiag` - - `APNs registration failed` -7. Validate background expectations: - - repro in foreground first - - then test background transitions and confirm reconnect on return diff --git a/apps/ios/ShareExtension/Info.plist b/apps/ios/ShareExtension/Info.plist deleted file mode 100644 index 0656afbf2d7..00000000000 --- a/apps/ios/ShareExtension/Info.plist +++ /dev/null @@ -1,45 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - OpenClaw Share - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - XPC! - CFBundleShortVersionString - 2026.2.21 - CFBundleVersion - 20260220 - NSExtension - - NSExtensionAttributes - - NSExtensionActivationRule - - NSExtensionActivationSupportsImageWithMaxCount - 10 - NSExtensionActivationSupportsMovieWithMaxCount - 1 - NSExtensionActivationSupportsText - - NSExtensionActivationSupportsWebURLWithMaxCount - 1 - - - NSExtensionPointIdentifier - com.apple.share-services - NSExtensionPrincipalClass - $(PRODUCT_MODULE_NAME).ShareViewController - - - diff --git a/apps/ios/ShareExtension/ShareViewController.swift b/apps/ios/ShareExtension/ShareViewController.swift deleted file mode 100644 index 1181641e330..00000000000 --- a/apps/ios/ShareExtension/ShareViewController.swift +++ /dev/null @@ -1,548 +0,0 @@ -import Foundation -import OpenClawKit -import os -import UIKit -import UniformTypeIdentifiers - -final class ShareViewController: UIViewController { - private struct ShareAttachment: Codable { - var type: String - var mimeType: String - var fileName: String - var content: String - } - - private struct ExtractedShareContent { - var payload: SharedContentPayload - var attachments: [ShareAttachment] - } - - private let logger = Logger(subsystem: "ai.openclaw.ios", category: "ShareExtension") - private var statusLabel: UILabel? - private let draftTextView = UITextView() - private let sendButton = UIButton(type: .system) - private let cancelButton = UIButton(type: .system) - private var didPrepareDraft = false - private var isSending = false - private var pendingAttachments: [ShareAttachment] = [] - - override func viewDidLoad() { - super.viewDidLoad() - self.preferredContentSize = CGSize(width: UIScreen.main.bounds.width, height: 420) - self.setupUI() - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - guard !self.didPrepareDraft else { return } - self.didPrepareDraft = true - Task { await self.prepareDraft() } - } - - private func setupUI() { - self.view.backgroundColor = .systemBackground - - self.draftTextView.translatesAutoresizingMaskIntoConstraints = false - self.draftTextView.font = .preferredFont(forTextStyle: .body) - self.draftTextView.backgroundColor = UIColor.secondarySystemBackground - self.draftTextView.layer.cornerRadius = 10 - self.draftTextView.textContainerInset = UIEdgeInsets(top: 12, left: 10, bottom: 12, right: 10) - - self.sendButton.translatesAutoresizingMaskIntoConstraints = false - self.sendButton.setTitle("Send to OpenClaw", for: .normal) - self.sendButton.titleLabel?.font = .preferredFont(forTextStyle: .headline) - self.sendButton.addTarget(self, action: #selector(self.handleSendTap), for: .touchUpInside) - self.sendButton.isEnabled = false - - self.cancelButton.translatesAutoresizingMaskIntoConstraints = false - self.cancelButton.setTitle("Cancel", for: .normal) - self.cancelButton.addTarget(self, action: #selector(self.handleCancelTap), for: .touchUpInside) - - let buttons = UIStackView(arrangedSubviews: [self.cancelButton, self.sendButton]) - buttons.translatesAutoresizingMaskIntoConstraints = false - buttons.axis = .horizontal - buttons.alignment = .fill - buttons.distribution = .fillEqually - buttons.spacing = 12 - - self.view.addSubview(self.draftTextView) - self.view.addSubview(buttons) - - NSLayoutConstraint.activate([ - self.draftTextView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 14), - self.draftTextView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 14), - self.draftTextView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -14), - self.draftTextView.bottomAnchor.constraint(equalTo: buttons.topAnchor, constant: -12), - - buttons.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 14), - buttons.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -14), - buttons.bottomAnchor.constraint(equalTo: self.view.keyboardLayoutGuide.topAnchor, constant: -8), - buttons.heightAnchor.constraint(equalToConstant: 44), - ]) - } - - private func prepareDraft() async { - let traceId = UUID().uuidString - ShareGatewayRelaySettings.saveLastEvent("Share opened.") - self.showStatus("Preparing share…") - self.logger.info("share begin trace=\(traceId, privacy: .public)") - let extracted = await self.extractSharedContent() - let payload = extracted.payload - self.pendingAttachments = extracted.attachments - self.logger.info( - "share payload trace=\(traceId, privacy: .public) titleChars=\(payload.title?.count ?? 0) textChars=\(payload.text?.count ?? 0) hasURL=\(payload.url != nil) imageAttachments=\(self.pendingAttachments.count)" - ) - let message = self.composeDraft(from: payload) - await MainActor.run { - self.draftTextView.text = message - self.sendButton.isEnabled = true - self.draftTextView.becomeFirstResponder() - } - if message.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - ShareGatewayRelaySettings.saveLastEvent("Share ready: waiting for message input.") - self.showStatus("Add a message, then tap Send.") - } else { - ShareGatewayRelaySettings.saveLastEvent("Share ready: draft prepared.") - self.showStatus("Edit text, then tap Send.") - } - } - - @objc - private func handleSendTap() { - guard !self.isSending else { return } - Task { await self.sendCurrentDraft() } - } - - @objc - private func handleCancelTap() { - self.extensionContext?.completeRequest(returningItems: nil) - } - - private func sendCurrentDraft() async { - let message = await MainActor.run { self.draftTextView.text ?? "" } - let trimmed = message.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { - ShareGatewayRelaySettings.saveLastEvent("Share blocked: message is empty.") - self.showStatus("Message is empty.") - return - } - - await MainActor.run { - self.isSending = true - self.sendButton.isEnabled = false - self.cancelButton.isEnabled = false - } - self.showStatus("Sending to OpenClaw gateway…") - ShareGatewayRelaySettings.saveLastEvent("Sending to gateway…") - do { - try await self.sendMessageToGateway(trimmed, attachments: self.pendingAttachments) - ShareGatewayRelaySettings.saveLastEvent( - "Sent to gateway (\(trimmed.count) chars, \(self.pendingAttachments.count) attachment(s)).") - self.showStatus("Sent to OpenClaw.") - DispatchQueue.main.asyncAfter(deadline: .now() + 0.45) { - self.extensionContext?.completeRequest(returningItems: nil) - } - } catch { - self.logger.error("share send failed reason=\(error.localizedDescription, privacy: .public)") - ShareGatewayRelaySettings.saveLastEvent("Send failed: \(error.localizedDescription)") - self.showStatus("Send failed: \(error.localizedDescription)") - await MainActor.run { - self.isSending = false - self.sendButton.isEnabled = true - self.cancelButton.isEnabled = true - } - } - } - - private func sendMessageToGateway(_ message: String, attachments: [ShareAttachment]) async throws { - guard let config = ShareGatewayRelaySettings.loadConfig() else { - throw NSError( - domain: "OpenClawShare", - code: 10, - userInfo: [NSLocalizedDescriptionKey: "OpenClaw is not connected to a gateway yet."]) - } - guard let url = URL(string: config.gatewayURLString) else { - throw NSError( - domain: "OpenClawShare", - code: 11, - userInfo: [NSLocalizedDescriptionKey: "Invalid saved gateway URL."]) - } - - let gateway = GatewayNodeSession() - defer { - Task { await gateway.disconnect() } - } - let makeOptions: (String) -> GatewayConnectOptions = { clientId in - GatewayConnectOptions( - role: "node", - scopes: [], - caps: [], - commands: [], - permissions: [:], - clientId: clientId, - clientMode: "node", - clientDisplayName: "OpenClaw Share", - includeDeviceIdentity: false) - } - - do { - try await gateway.connect( - url: url, - token: config.token, - password: config.password, - connectOptions: makeOptions("openclaw-ios"), - sessionBox: nil, - onConnected: {}, - onDisconnected: { _ in }, - onInvoke: { req in - BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .invalidRequest, - message: "share extension does not support node invoke")) - }) - } catch { - let expectsLegacyClientId = self.shouldRetryWithLegacyClientId(error) - guard expectsLegacyClientId else { throw error } - try await gateway.connect( - url: url, - token: config.token, - password: config.password, - connectOptions: makeOptions("moltbot-ios"), - sessionBox: nil, - onConnected: {}, - onDisconnected: { _ in }, - onInvoke: { req in - BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .invalidRequest, - message: "share extension does not support node invoke")) - }) - } - - struct AgentRequestPayload: Codable { - var message: String - var sessionKey: String? - var thinking: String - var deliver: Bool - var attachments: [ShareAttachment]? - var receipt: Bool - var receiptText: String? - var to: String? - var channel: String? - var timeoutSeconds: Int? - var key: String? - } - - let deliveryChannel = config.deliveryChannel?.trimmingCharacters(in: .whitespacesAndNewlines) - let deliveryTo = config.deliveryTo?.trimmingCharacters(in: .whitespacesAndNewlines) - let canDeliverToRoute = (deliveryChannel?.isEmpty == false) && (deliveryTo?.isEmpty == false) - - let params = AgentRequestPayload( - message: message, - sessionKey: config.sessionKey, - thinking: "low", - deliver: canDeliverToRoute, - attachments: attachments.isEmpty ? nil : attachments, - receipt: canDeliverToRoute, - receiptText: canDeliverToRoute ? "Just received your iOS share + request, working on it." : nil, - to: canDeliverToRoute ? deliveryTo : nil, - channel: canDeliverToRoute ? deliveryChannel : nil, - timeoutSeconds: nil, - key: UUID().uuidString) - let data = try JSONEncoder().encode(params) - guard let json = String(data: data, encoding: .utf8) else { - throw NSError( - domain: "OpenClawShare", - code: 12, - userInfo: [NSLocalizedDescriptionKey: "Failed to encode chat payload."]) - } - struct NodeEventParams: Codable { - var event: String - var payloadJSON: String - } - let eventData = try JSONEncoder().encode(NodeEventParams(event: "agent.request", payloadJSON: json)) - guard let nodeEventParams = String(data: eventData, encoding: .utf8) else { - throw NSError( - domain: "OpenClawShare", - code: 13, - userInfo: [NSLocalizedDescriptionKey: "Failed to encode node event payload."]) - } - _ = try await gateway.request(method: "node.event", paramsJSON: nodeEventParams, timeoutSeconds: 25) - } - - private func shouldRetryWithLegacyClientId(_ error: Error) -> Bool { - if let gatewayError = error as? GatewayResponseError { - let code = gatewayError.code.lowercased() - let message = gatewayError.message.lowercased() - let pathValue = (gatewayError.details["path"]?.value as? String)?.lowercased() ?? "" - let mentionsClientIdPath = - message.contains("/client/id") || message.contains("client id") - || pathValue.contains("/client/id") - let isInvalidConnectParams = - (code.contains("invalid") && code.contains("connect")) - || message.contains("invalid connect params") - if isInvalidConnectParams && mentionsClientIdPath { - return true - } - } - - let text = error.localizedDescription.lowercased() - return text.contains("invalid connect params") - && (text.contains("/client/id") || text.contains("client id")) - } - - private func showStatus(_ text: String) { - DispatchQueue.main.async { - let label: UILabel - if let existing = self.statusLabel { - label = existing - } else { - let newLabel = UILabel() - newLabel.translatesAutoresizingMaskIntoConstraints = false - newLabel.numberOfLines = 0 - newLabel.textAlignment = .center - newLabel.font = .preferredFont(forTextStyle: .body) - newLabel.textColor = .label - newLabel.backgroundColor = UIColor.systemBackground.withAlphaComponent(0.92) - newLabel.layer.cornerRadius = 12 - newLabel.clipsToBounds = true - newLabel.layoutMargins = UIEdgeInsets(top: 12, left: 14, bottom: 12, right: 14) - self.view.addSubview(newLabel) - NSLayoutConstraint.activate([ - newLabel.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 18), - newLabel.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -18), - newLabel.bottomAnchor.constraint(equalTo: self.sendButton.topAnchor, constant: -10), - ]) - self.statusLabel = newLabel - label = newLabel - } - label.text = " \(text) " - } - } - - private func composeDraft(from payload: SharedContentPayload) -> String { - var lines: [String] = [] - let title = self.sanitizeDraftFragment(payload.title) - let text = self.sanitizeDraftFragment(payload.text) - let url = payload.url?.absoluteString.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - - if let title, !title.isEmpty { lines.append(title) } - if let text, !text.isEmpty { lines.append(text) } - if !url.isEmpty { lines.append(url) } - - return lines.joined(separator: "\n\n") - } - - private func sanitizeDraftFragment(_ raw: String?) -> String? { - guard let raw else { return nil } - let banned = [ - "shared from ios.", - "text:", - "shared attachment(s):", - "please help me with this.", - "please help me with this.w", - ] - let cleanedLines = raw - .components(separatedBy: .newlines) - .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } - .filter { line in - guard !line.isEmpty else { return false } - let lowered = line.lowercased() - return !banned.contains { lowered == $0 || lowered.hasPrefix($0) } - } - let cleaned = cleanedLines.joined(separator: "\n").trimmingCharacters(in: .whitespacesAndNewlines) - return cleaned.isEmpty ? nil : cleaned - } - - private func extractSharedContent() async -> ExtractedShareContent { - guard let items = self.extensionContext?.inputItems as? [NSExtensionItem] else { - return ExtractedShareContent( - payload: SharedContentPayload(title: nil, url: nil, text: nil), - attachments: []) - } - - var title: String? - var sharedURL: URL? - var sharedText: String? - var imageCount = 0 - var videoCount = 0 - var fileCount = 0 - var unknownCount = 0 - var attachments: [ShareAttachment] = [] - let maxImageAttachments = 3 - - for item in items { - if title == nil { - title = item.attributedTitle?.string ?? item.attributedContentText?.string - } - - for provider in item.attachments ?? [] { - if sharedURL == nil { - sharedURL = await self.loadURL(from: provider) - } - - if sharedText == nil { - sharedText = await self.loadText(from: provider) - } - - if provider.hasItemConformingToTypeIdentifier(UTType.image.identifier) { - imageCount += 1 - if attachments.count < maxImageAttachments, - let attachment = await self.loadImageAttachment(from: provider, index: attachments.count) - { - attachments.append(attachment) - } - } else if provider.hasItemConformingToTypeIdentifier(UTType.movie.identifier) { - videoCount += 1 - } else if provider.hasItemConformingToTypeIdentifier(UTType.fileURL.identifier) { - fileCount += 1 - } else { - unknownCount += 1 - } - - } - } - - _ = imageCount - _ = videoCount - _ = fileCount - _ = unknownCount - - return ExtractedShareContent( - payload: SharedContentPayload(title: title, url: sharedURL, text: sharedText), - attachments: attachments) - } - - private func loadImageAttachment(from provider: NSItemProvider, index: Int) async -> ShareAttachment? { - let imageUTI = self.preferredImageTypeIdentifier(from: provider) ?? UTType.image.identifier - guard let rawData = await self.loadDataValue(from: provider, typeIdentifier: imageUTI) else { - return nil - } - - let maxBytes = 5_000_000 - guard let image = UIImage(data: rawData), - let data = self.normalizedJPEGData(from: image, maxBytes: maxBytes) - else { - return nil - } - - return ShareAttachment( - type: "image", - mimeType: "image/jpeg", - fileName: "shared-image-\(index + 1).jpg", - content: data.base64EncodedString()) - } - - private func preferredImageTypeIdentifier(from provider: NSItemProvider) -> String? { - for identifier in provider.registeredTypeIdentifiers { - guard let utType = UTType(identifier) else { continue } - if utType.conforms(to: .image) { - return identifier - } - } - return nil - } - - private func normalizedJPEGData(from image: UIImage, maxBytes: Int) -> Data? { - var quality: CGFloat = 0.9 - while quality >= 0.4 { - if let data = image.jpegData(compressionQuality: quality), data.count <= maxBytes { - return data - } - quality -= 0.1 - } - guard let fallback = image.jpegData(compressionQuality: 0.35) else { return nil } - if fallback.count <= maxBytes { return fallback } - return nil - } - - private func loadURL(from provider: NSItemProvider) async -> URL? { - if provider.hasItemConformingToTypeIdentifier(UTType.url.identifier) { - if let url = await self.loadURLValue( - from: provider, - typeIdentifier: UTType.url.identifier) - { - return url - } - } - - if provider.hasItemConformingToTypeIdentifier(UTType.text.identifier) { - if let text = await self.loadTextValue(from: provider, typeIdentifier: UTType.text.identifier), - let url = URL(string: text.trimmingCharacters(in: .whitespacesAndNewlines)), - url.scheme != nil - { - return url - } - } - - return nil - } - - private func loadText(from provider: NSItemProvider) async -> String? { - if provider.hasItemConformingToTypeIdentifier(UTType.plainText.identifier) { - if let text = await self.loadTextValue(from: provider, typeIdentifier: UTType.plainText.identifier) { - return text - } - } - - if provider.hasItemConformingToTypeIdentifier(UTType.url.identifier) { - if let url = await self.loadURLValue(from: provider, typeIdentifier: UTType.url.identifier) { - return url.absoluteString - } - } - - return nil - } - - private func loadURLValue(from provider: NSItemProvider, typeIdentifier: String) async -> URL? { - await withCheckedContinuation { continuation in - provider.loadItem(forTypeIdentifier: typeIdentifier, options: nil) { item, _ in - if let url = item as? URL { - continuation.resume(returning: url) - return - } - if let str = item as? String, let url = URL(string: str) { - continuation.resume(returning: url) - return - } - if let ns = item as? NSString, let url = URL(string: ns as String) { - continuation.resume(returning: url) - return - } - continuation.resume(returning: nil) - } - } - } - - private func loadTextValue(from provider: NSItemProvider, typeIdentifier: String) async -> String? { - await withCheckedContinuation { continuation in - provider.loadItem(forTypeIdentifier: typeIdentifier, options: nil) { item, _ in - if let text = item as? String { - continuation.resume(returning: text) - return - } - if let text = item as? NSString { - continuation.resume(returning: text as String) - return - } - if let text = item as? NSAttributedString { - continuation.resume(returning: text.string) - return - } - continuation.resume(returning: nil) - } - } - } - - private func loadDataValue(from provider: NSItemProvider, typeIdentifier: String) async -> Data? { - await withCheckedContinuation { continuation in - provider.loadDataRepresentation(forTypeIdentifier: typeIdentifier) { data, _ in - continuation.resume(returning: data) - } - } - } -} diff --git a/apps/ios/Signing.xcconfig b/apps/ios/Signing.xcconfig deleted file mode 100644 index f942fc0224f..00000000000 --- a/apps/ios/Signing.xcconfig +++ /dev/null @@ -1,17 +0,0 @@ -// Default signing values for shared/repo builds. -// Auto-selected local team overrides live in .local-signing.xcconfig (git-ignored). -// Manual local overrides can go in LocalSigning.xcconfig (git-ignored). - -OPENCLAW_CODE_SIGN_STYLE = Manual -OPENCLAW_DEVELOPMENT_TEAM = Y5PE65HELJ - -OPENCLAW_APP_BUNDLE_ID = ai.openclaw.ios -OPENCLAW_SHARE_BUNDLE_ID = ai.openclaw.ios.share - -OPENCLAW_APP_PROFILE = ai.openclaw.ios Development -OPENCLAW_SHARE_PROFILE = ai.openclaw.ios.share Development - -// Keep local includes after defaults: xcconfig is evaluated top-to-bottom, -// so later assignments in local files override the defaults above. -#include? ".local-signing.xcconfig" -#include? "LocalSigning.xcconfig" diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/100.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/100.png deleted file mode 100644 index 22a04c9f22a3edd95e7fe223fe07641d4e98b046..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9725 zcmbt(Wmp_b*KK1V5C~2nI1CyfFu1$BGiY#kcS3^0-~=ZL?t#H2ID>`|2<{pJLvTp2 zJ2~gQ&-?xP?w?!rboZ*-yH;0McU5<<{V@Nq4&W=xE6D>WC;)(h%)rAY%Dj?{jJc+^ zhP;xh+`ool0GZIa0Kmo7+f!RXn${3vM2orpZ;QV+3o9@8zsLV2A$c!n|FQ$XG{^tq z^Z%;GvbOQELOL8HH;^at6UY?%qfr&A-@FS6c>&t&y0; z?tfs*|ADRCJ^%VAAbmt#oPGYD>u>toV;mb-JssrnF><2>yZ~)L0g(QC{m3#hxqSox z!3zLDOa5=2Wi|k`L;?WW;(zNv?*RbsEdVr6{d9N$TI3k`2 zkPiI#0PqL}6kS05QPzZKr>5NBhOhe#tsD$|WuzWhnEiMq!=bMp3#b8lwEqp9df*w6JdM;B;z~ z8fC7#td>gf?)r9(Cahy^?{YhA?nWJovQG1A=BJ>9#MsW!mB-2Ndto7&9`V)g!pxj} z$`5nzL%IuZXFRU&??WlWCihNe0)F4#ckLmWDJju<#Ct2IlLmhLb9Mz9^LHCZfA(}P zF7^~y{4wYG7!HnaMT46tLjvwX#l!G2p_<2d%|#L765W$~4*>PAcQoWvJ>p`)@Nj5R z5b?GM+q8nfTr+=shXNB^sPiL?8{v(mzfY55$dXgbQL#;Y4N7f$-)HzkGa7W2K@kXEdmvhHte`cA@*@aJs<#- z3~b->UG}11mc}*N+tgbI5VE|A5Xf{WNr@=-kRx*drOZd_%Gp{=w$as<=U(_+TGr7q%@&3o9!j4fGlqRNKvbM zfQpya&`!B|lNk^D*BKa96qIWdd}PV_A!z=k*xGFpWza>Qt9s@Ig`EZWO_Hy3{zUVq zY-4Gt2wnbw@t}HY#qACP;0hUZQP{}Hu_Dbs|}$EtUn2AUQ0Z@h`XRh$jc zgeknKs?l09S(3$cvP1X)HL7&PxTGF>ss;cEfeORXMuh1_q4h)6M~CGx?_nbK*p>f` zIshnvQ1;9j!iF0Y43rCo7YHYaG>g8^lWOlie1vsU6|$Y=k_C-YiXIrp4`vWHT#OU7JY>H769|!vmbJuz!;F4h674-4!QvGZpoTDc6TjGS;zRGds;b|zy zELXGT{;s3_<%D+eWnG|Fvl;oxRB;O^uW&*RNptkPB&scu-V#$_$4j)EhM>} zo4Z)S+LnEc@3hBs;=WjMSPC90H4kPD6uGWv_t!9}kz0;#zqni+HiK*t)jW3Ub8&+~ z*qTQ>z@Do|97NhU)Z5m3&J%=2sSPjbsij&&5 z=-GbHJCcsG)vSv}@k0%|1xaSKS47Xhu*S{!Y=b!Qy z25FDHJ1A??|Ni5WJ|l?Rr3}744=+%9)&7nl+UqDGqXY~$f96CEbs|RS#*Cy{4_0

X+KI)VK5+KOd$n}f9*Y?<8_l&XJoA?R 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 diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/120.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/120.png deleted file mode 100644 index 154836b43a228bba8be5057ada7fe8c78da78c8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11620 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 diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/172.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/172.png deleted file mode 100644 index a66c0132393e7a677decf8d9011d78fe0cd10e62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20674 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 UUE>+)ux;_8+HXLZ&F|U&0I?WB!~g&Q diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/180.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/180.png deleted file mode 100644 index d01e83d8cccc850b2f323e7f1f307991193e8b72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22378 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 UbpSNzY$kY*0yA*si2gJ6KSa7RbpQYW diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/196.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/196.png deleted file mode 100644 index b7989e43d84126226410d92a39717ce916cf9863..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25563 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 RaS}sM=x%j>t2h2z`hRidu<-x@ diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/216.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/216.png deleted file mode 100644 index 4dfb94abefb98982515d1667849d652e9501a61b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29020 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

+!LiLke4AIyDrh$q}qd*hTmM2 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�w3=$`rz}31ND39PiGg8GP-R&HO%-+cemJ&ejdH)cZk~{8UL~` zp($;?X4QWIIi>%CRz*a<-t_GOn+UabZTR3dv}f-2WWabVkBId`QT ztIDa%L4H=9*{L1f65f#}o_7(?i(^k50_Ai6u*ir&gQb<_Q7q16$u Q%LR`u{@e3iv%ib~2Q_%AH~;_u diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/234.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/234.png deleted file mode 100644 index c0da9ae922cf9eace5f626b8346b8f126c7e6902..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33325 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 LY{p#h+tU9BeU#l6 diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/258.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/258.png deleted file mode 100644 index dbfb75050bdca5455a7ca44da513224fab8e3772..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39552 zcmbrlWmp_d@Gm;J1%id(4q-RATW|uq_#(jx?ruRt2yQ_Z7I$}DoCGH<7TgICLVy54 zf&}=gYZYZuK)gzv-^2>YkbIp02L`xA^ZnKn#5ic@3bU0RY-#0RC;EEkfkw z%`{;euOX_6|0`nzcqB|-0C0Bk@_;GHG3px_GU9yyUw8bMXKv}~_TTycLXUDU=Kqrp z05e?w7oPvGWIQWtPs>M!KaU5i$D{Jc!jeB?a@+rfIsU^I{|ih0hkd==ydHTp|HB?S zF!@Jp^@ura{|{{Oe_%^DkN^1N9(g34oxK0k^&kCL;wRQFy4sIt+{c3!@C0Ch5+L_q z{U5I%$+ZvwME?Q+M&kcYv&aB|)^GrzT>jr_toZ=&GzF61Xu%%00eLWECKFE#1HTS ze1P!36+r&+b^iaO|AhSilkj-=zb^m@E*d%-ItCgEfKGyjL4x*g0AP5mIXVV_@!zNT z{}LKHJ_arxCN>TM)+57f;>V8=69WtTF~Y{e#CUu^=opv)7B&eE6CbXumiZq%Quhx@ z1!N7q-^iIaPw=1dv&g|blBX%2vo`io3WgT43CKUnp?@sGf2#gZML4+Vc>hVp|4$Fe zqu@t9SUCSlN5{hYPY-~JMS{)5heIl>^@q&-Q4KCRbHSq`{>>A-XDo6QtOD{L7Sn>T z!p1&r%h2SRf6KrVj7K#j7$kr+@Ht&y27_-SO@1>M*>+kVHB11$iK}r|S28m)gSiMH zZOn#EU-@ASXGE?Mn7uUY6C-SyxIIHLekM?yly`obj*67J$GRFk+RU4*ON?M6lz(SM zZ`xrybiGS4w5xs;Yzud%yWX`tKuulR$TkC5-_gaNN&xXqD5IZJ#7JM%h;5xjo@9jI z0eRNb{LhiEq(9-xY0jwpcs|9I+On{`tiXJipwyN{8yP7uvC1EEhT{AxSvMEqJI&x# zl=IQ}*sYE56#4tEN9*0m(ZXIC{i{1nHHkCH#*yq(3Y5UG6t6F!;I&zEctNwmC24+% z`aJ*e;)Do&$^AK%?d9Z$YinHSbD#}dZ&GV_x2z7=y}N0~^!d%Td&|}eQ{U8WKJ7;t z!UsTPqcreRCU)bq(caXiqb-JcO)b{V?1!=5HJT$vl>ctpR$aJR19CbijzS#?f%TJ2K(qdPUjSOu|0!PD#MM zj?iQ4a{}_#ALD$d>InOA<>7jtIzqNn^IO{M`Oz=-wSj^&l69Bf=Qr0^djxF&)ygV{ z+Cw1MIf1hz*8&gIIf-a?^TeHog#XG!-;}T1W+E=u+4LpBBKCFU=yDv;a#%)m7;GkW z&%6upVPWaNeBS+6+=}ri zyq`yNi>b}&dCU2XksUEI(?3W66%H5^Pu$Y#{{R6G=eHiM1nW2p>L%Xh5tslnt$xQb$c17=;5rT$mDZzh5}8Ne=H9v> zS)h-RXr?)TjWyt$c)g<97!k-Rarh+#ks$X_KPkOEy-Z}RzzgymQSzmy6|CPu$o5^_>wTcT!OZFa(8k{y$?o;@Go(m7&Abz1<{ZT@jm+%(9|fc3RM zjealx0l$@&NxTWSQ=6WWoY4XNV;0x8PG4J759{cUw0MSgxs-kwo}@62_ySmWEj!ym zfwgT%lhX9}0<9yq?+WjNHE|u&Z&$Imb4|tHnPPMvUtV8s#BVNyN%&j8-E_K?KN#jV zm6Q(VGItrjFgGtr|2>7{3R*se;oU~wgVMLfwoG$F~LZ25Q(<4L3~5+ zrjPyD^xle~80kE_|4wsqmGSMNR8Avt^$k~X{5Emr9whxDvLm&AF*8WlEk7jIcYklG z%aiU2yxdsk)W`Wt7udX@#zQ2P7u;27RHrdOF~hgY{JbYua+88qe&cQc>3jF!FLr>x zKyziJIel>*fA8BjKlLGqfBPV(CUIvItv^1Df?y-i^mvOC{rP?4TJ3QiZrZ`HnVA|B z)<^EouK89Z{=BX9yhbaNwKY92g6=wIKGnH}P(;uLXEP1gc5UMK_Ir1~8;m?$n3*OB zJfe;WygEfG%h3u&o1-QZT5tL;H_!h3x$dv6At2a@qxc+wY~34{5{beUOQ^vJ#@-Oc zG1=UyLvBu{1w_#LUwa(yUo06#BpQ8^5^g1;mGX(C3sjPNbH4wLEA=xAk7>l~o8GiM z#!d5hC7$n)mQAu6!+WmD=_G<4X2pm%qC)IZx+(cA$J2iDSH#MSMBT1ZNCa|MM-Wa7$29kW#uR%{b_dcXE<_$7DgZZd^axU&GUHcO>f*c+(~AF zANahk1IG*dH}eiIelcTsTGm?GdI&Cjmh7zCB^(i6P<>dSx@Q{Z?#b)YXLjGedleX1 zfT=ILU=qZH%S2W;SxqbUbXBT87E{Ih{5*Q$4Ylu$?1CxvwPMVB2D2`zzsEZ_1Jk?4 z?Y4;d2hERlMDFG|dkfj}>36=ixXc5`N5`~Ro-@<9iXS6+>Lcf09A9i6lp4PqI9MpU z_&E8=)Re@cm&~;5(|ZGj`;G%OKiS;?|LgO|L|j?i&`Xh-NMFPC2RU5DP!g=G-1piS zt;KZS+j9jJxN`p!VyXRy0w8Xgz_)SDT1Q8KLk-q$x%Hf@IU?Z6EKV zyvzb$&zsTBPVV4^@E-r2I%)j|j`}bbm&iR_8Tw%VhgBwAw=l-G_(NB^V57_M(|SK9 zBI59z!@b1Y_?q0nSEq8cOt`Kc%YV1`8ARoP1GB`vDVH#&zYCNKt)}gMW>tLz36?H; zpQV_BiDQX~qt>^W_Nn$Jx$gLBTSNLtIOLw)a|QfGlwZrepzjd-JAN{=yBYNA)g}e; z4~&H=|54(|!@T2#Y$i-5{0FIz7Y7r>k+=#jBE-nF$vo8iRnM=ua3Yee_r^?k%x z!yBK{3Xappo8A zRZN^uZFb^ro11XiiOZ3ov+H5n$)E%!72lv}s(r3%n}fP_PLI$v@A+(I(+4w&PaCxy z%zaO}JAm^@GZp{-+AeH2IpQ$D`?1ysmtl-yL?+&+;fdJa2{+ynZn5NJTlTR{a@YMu zzSqy#O%y+qDndw}{}7yCwOt{wq0616Xd6xt^_3e3LhA0M1@ah=D*0c7RCOT`2#UWV zAv0X$!j`kDBYzc_omi-w?G2eGM}}_YDL=TSUqdQkHNnD!=9u^$@yEbx%8@o6t1Pu; zrXKt+SD#3Py4!47L3RHC7wFOJ?NpKJ@mDPbG$o#lWiOXc${J0V;zJ#%=T#ISC*YbO zzP!m2^54j}#vB9WtfOOPDHNv_Zgkrj%r8lv<#xIxwo%xC&}1}av@vi4`;9bvJ;_ud z4chL*HViHX$r)5@gW~&r#5t!^5|vtbtg!^4YE5y&+86v6AB(1JPoAk@kB*LLgU-Am zKX^zs&jbguQwTCL++n}UIZ}m3$qU1(%U8Szw=lgmF)_Jm6(qkX;6#L?lO%5I9Wm#9g1Qm^_5M_a(wWR!Tc#R!LPE> zkXdgnkS5{uV8Um&c7`*ypoUVa&Sh32G-+{5ic3CR%`bG!Z?xfeC@vsp3M)nX=m?z( zFOh{9%1z6*f%NP_V{5D=9j_G(S!&w)Yx&O{?dQ{wInMSVBNySq)B<~95R5!I6&(#z zf0y32)l7evma*O~jHNeIb>|e~)aNezZrKE!%IC|Up-K-{pyor=yA-w7(Q)U0AaR;& z1lM+y5rgg7J=2{qX!V+r;apa191s{>EfkjI&5@E1kZJ%dBPi}M@tG&WWu`#`{3vBC z754>l;uSmPaj4-eX`%pY2xFSGs}O=OQwTih%xklB@YW-=#`uA5nbm|LVX0TS(_4`Z z_l2wniB%kPW-)U(pB$ULA*?tXjvn5NJzz|?=Eb;jOl#uo)Pc;dH*z#`Tw{XZ%f%?; zLqN>mV?$-7i<7ebT7d=5FOmb!M=XC6WavD{>``h0t;V7!3wiXGIoC?y((WcB^pOL+ zZW`f%(Uz=h@_l>83@L5A2Fla4Gb+iiW0h}ZJ>VY{A4s1XiYn_+SfgD9{UQ1lk|6os zL6qCn{#vQhrTO5g825fElQ?lCwSjYQ57j-$P;I=XqPxh!>Q(H00T?buE6ene&88Ua zLE0k5IM3FTm;EvAlCH`9eWYyYE^Yz1@HVDm^4{cWhEkDOrWYdXzyPW&?kE~dq zVas#o=1*5LTZ7`PDT+%65jrEKnjDu2es8=!y77h_{3Wl3$kvpeS2n{>wpMsvATcCo z`$o;E4R^XNpKQNMaeiqVgB0wg{6y61mLwvr7N|YnD6{5LJmR0bCo;lpt?(y40Rz}e zx6l8 z?yiDJsmS*TB0h`Wg=!{(_r}*jUSnbfPnG3}Kgqk@$dT;n$48wDlWGakvskEUfQsxg z)s3s?^UHT#WUG6OzcPVj)Zb!MZ=%8zQeHoyX5GB|dV086@3grRrX{_TlLIezJIEBV&ae!>9)h~(PUJmS_sQgOS0=0 z5WJ0KEkN((kaO9ttu81vgsyqpIpb@VU#z}rZu=TP1L-Dga@<=dFvlZz8vyIc-*r+r zmiC#ePMVA-i&swZ`?7M-Rj0{RdNcHj<~mC$>S}mRJdW+7wUs;3+)fE!8kfGqTTSwoSK)S!04MJ@ zXzk%%a!J^4DdoNaABz*(L(2YqKyg*f>+kB|Or!=o&w@nR3{JvxKfb_CEi#VHvr8!W z@N}P2)%v+tBZ^i*VV5_4n5e6j&T!Rxuw(zLc0ya>)_mc6*nD9LNGbE{WMce7Y8oOr z)ka-TD_Tsp z*ZhfSL`=W))96tXvTkl3KNOw!sbv(kD^PvYbXLX-(}mX7UGS6fXO69~`&EvuqMDF{ zf9AyPCbsaZRL4iuN(~{YM->&i6r}s5qs}LiJyT4nG}y_hAeJCm$N|gEM`u?`O+^fA z9pCJd%~cHrT~Fc(-V$b;#xNZl*33em!okV_Y#mh%{-kd4)^z#G-_%^4HeJwxQ3f0i z>N>I$aK5vOCR`z7;HIpcPUPKAb0uu*YpO3)7=iS<{sJE@mCOHD6^UQ&kwgv`3n{AC zo@s1e5{uqjnBf6|r*ncXxnVQ*a}Id;S`93WcoSdT5^8ym=xZ!ScX$Xl_XFk(*KFJ? z@U6v-+@!^XPneKKhvX4`2n$)mX?O@U3P`^&Aiq)3Q!Wu=6B9I-Ow`zkdjS)hZJ5?5 z@wC?&uhg(^Vt-0Q`AgjDZ{pmwu@jx z*YcDs2&R(-Vs+!YdSO)tYD&?$zP9~QR%~Mi&xU6>JB>ldRoY7P5J4p&$Xx5$ik1Qy z5IzI~M16D4;A6C-eLq|iQz@dreD#i#4}lg_PA4F}bW57U(KZt=_2M0hB`ozcrBbLK z{o|FPuD?MBu1-2-{~5XcHrJaf^NR403jQ@{nvU`zNT5Wi5i)1GDNL6(mc_5%{e>j` z;D%uBRr|R3=7I#m53Cbe_Nb0btUo(mDcePIGtIW`La6?D1_(yM{6z>mo7@un5 z*s7Trq|E}%3UK8|S1ogImACjBc|PMmB!DBpdQ*hxT)V?;CaBRFVH$6IQeTZ9V7o57^yR zaV{t2?sq9u9CG{8_EyWsJs#PuZR_1m6&;B8;a0wl-96PWyi>Eh>HWOh1g*mA7CD-V zx7euX2U#cU?wP&ww3MU?utSDRFR0P&1A2pp*kP7^k`8@1*2X&;T%Q_W=V zL~uV7Q%(k@577WhbK(c8g4;(mg#6Rw2eqR4aN%XLu9oWT5GV}tf)Pz5j*pE+O#89V z(%v!4$;-_^q$I-;_8O{cYN{O();o*#Xpci}jvGQf8yDLw$@dCmdVCUrXs zp06mVil)I&NGs1^J;ZLxU>#?O`+CD6?ey)yqgM5SU}$``_$|L9b7l#j{NM{QF3nU# zPKq~=ikcu|(NAQ}y(G5aEe&{p__fSgbMXFO?7Hv+T}cVEM1O=~;lyY4O6^h+2|v)1 zb=pt1wN==+Wx;w_&0vKH6-V4w16|h&@1`EjY`Sl=GsSrKE2C{XZLv~5Qst3~;=c0q zuY1Qo4;#?fA@KZpe+5mbijLUpk;y0fYP>$_YNTF!58cjXMA|#Fi36m)oa!25wR+xR z23+G5i`?vvo-ZXsLRLnf6Jaq{Z9jii_FhA+Vr%qF^po`*Vzt72^`(+cYhE$)-HxF(84-(}M3_P*L;D?0*Tr9}$~b?L{!Q`dvl#FDUCK$z z&c?4&pDv{JA}*WV;zLxEZn9R738Qs}%1ssLg_R7zE7&g> zi$l3alx$L9$!Cpq5H%D^9il2+TFUl<(!oa0yoGR1_`Gwx4HX6R;Bd#sH2qFMd3Z4p z)V%mLQ~)GI(EPDtUdWte)@5K$zUe*hU?yGu(|(+I_LvNoh3T|n-i+DI;EGD=Q1$cD z;Kneh&NlD&`Z`6xQGJ{dCk0jF|F2`+$jl2#F~UYTew&c3a^jg zLF5e3fE?c7SbT}Jd0)?_*!9xLEl@FHMPg&|1+6pzkBVt}2`NJw0$-=kxh0Y^N#0_I zOx;45diFGPG^)zFLd||ZL3#Ux|2kIj2`dR2DT&R5VYQ;6G@=uNbGlH@J@j^|sri|5 z77v>QNSb5pJoa#GR8<(E?^lAwWT#2d(4#;T&U#b<#sVwrGmF0;p!9DIJJ98nh}!e? za#&-w|0*6Y>{mE8P~C5}_7cJdhEB`JOD?C)9CAGsY-w)hyd4W}JO5)Q;eAjnemb%C z?ktSUzjaJ}f;fW3X%qL&ffPOcM)QBO!(axcZ5P_$KVhN@>}&U{mXuk1lXd4$#{$hM zn9xKDCDm247Y;2fU>1Si-|XMNok)cuzELyp>>(w;pU6V$G}&*-I; zI@rskiTtyYa_Za!Mz<~_oo)`)n_>ijvly(7nMAt&{#S3q^yQu}#NW3Qb#3DM08;=H zE?1EG)UBMPFE>r2Q)jDV;Zl>1j!8cPKM9lA<-?Oo6nA4O*sd_fia!=y5R+*SAElKk zAt3_8H1Xkbutc2_QULn8l64WY*akB4WXwa}(c8|xnQNF9rnyXmrD8ZM2Mc3ktWbeP zL1Br|XaHTUFo~`rD1WA={={JXnY_Aj>(V6Q3vQZku!~Xf$3U5KDk?pf6Dgl?)Kzo# zn$0YW5*sPh3j4uH2bQHl_rL)2NlKs_m}47(h!;;4)4?dAx>l28tQ7>=ZpK*1R1^LR zO(w2?Kw7W5^*W;QMUz+QaD8zPc))|Oy*XQheWmG0Dx}P99Bhu~orzf(^(t<33U+A! zgYMD>YSkJ`iu6oXd^85~ygjxaJ{V5lab}@RB};wqzYD)@uHU3dN7qhVkk6S2x=YY| zel-2<9wON_V=zz%QzBf>brpq=;_mGY#4Uq_(_7M#wr3JCf7nb-#Oy3Zp<5s!S{%M1 zEF=A60X{1U>?=qfb+)<&kXlM&nu*j0`J{E7Zg6fH zg12;m_xn@z303jhc@O(9A=@87_Gwhk$eHR_t?#1x;uhJvN(lvJ;RnyatFH>Iss}BS zR>#WcU^mF%EUV5hl~K)Qdx!}JjtoUXQu5Jy_#5S?zkKSXR&xpR>>Y7Ef|ek{iE8jo zojy8m5TpZ6I->%c2+>bTk1P5u7V*=uXKGQ;uichDrEl81OJ4E@rUHw$K?tz1Z&x9= zR8r2S4+T@{cG`+Ma3L(;b3!|n+H3!STb7pJ^J)FqMz=}c%V8x-6OVmPSXEL=L=F8$ zf<`7%>QE8*H_HNVpvF2yOq)DLho%&EV-o)+yIhOi?(F4yaKfKU4+!hbPiWextO)o? z7s7}d2xnqpvKyh_xaD;vIHX8vruM32+gp)MNq_i3tt@Xp&}{lO<1*C|=!lD*7H|~q zOu^0cR`Rp?2k0EWG*QbDj#*4`sdyjMjEt(Y(Z`A-AiW=6)Qz#HTgy$9t^qNR?SrzU zW7pNh(i_AAN;#BThq)^w_50dt7zp_1FkV+AJXixyS!M2j>%h8*faS;)qxij7tuX4RYCCW6E3_pzj=A8x;u3@c%SfM5`4 zvMd%W4SAv`CT*11$D}AR6YTf}j~%O(R+r@1+KyqcJ!6ale=K)lBry|ivbA^&Z66j0 zmzfz0jW~vpwL*c7k+jeQjro#wgXyi>*H+4MxokrkIh~doSq?dvPDzadW&ud~kuR+H z$yZ^LA=5F8_Tf9b6*HIX`ivPTlR@lv(qY49Y;5UDVTUPr0XBmG@Y1jF(~nx(n71$x zzr~3>xeghwB`5m+V@IwXYs{uxq4T+A2GX!vI)h^qzs8B6)w>3M)~j3XwDru?2!-(4 z3?NCsiKr`iyqDCLm}Pu?aVJfoHg7w;xktY8X4qUt!}JYFIdMNF`uug~K8onwC$kxK zvGCCjbn$=4ulfAMlf7-Tgmf?JAHZ(bnPE7m>)7rU!HnWk)0tqV%@sZg46MiAG^ z#e)=z7qN-Fe1hYZ^%zV%g-o?pd(I9wtBP4leVI9~-iXFnG~nK&Q_nksJ9O|d>b zV~Q>f35NO`4Ayvfa$Q8>yF2&vk8>7lMlS>3&MvG?Itv?vuM@@XEa{3q_jVeTZ7p-W z1;OnOz6Uc^MgV*(l}T{`GZVGmSx`!?piXLL%5G4Ok~DcE@~aJQ*+GljXZ4Q zv$C@Kg?htrBP=EN=;GL!=h)*=m4Xiai}9mE zbo(9f{jc@}Y@<&FUCiwWpWqf4H#wR9_?gR8s-$R89UoPb;^Ur>-7iG0tlm+gxla@( z6;7%Ud%y(Bb(9W&zNR`YLo@z3T&^6(?jc$xo5B(n{$x+Q=%3~iX^!J#-9BH6fWalA z?UVPk>&&lr2%eW>m=D{1YV*y=r2nDE_A_B;J+obQ+lo%e;5lJ-apvKwh_28|ZRh}& zmI+oeZ)xRAb_MMv|KWIGI=Th%Xh(7fBVtXO%{{b>9r-tuLiqE zOPM;8bKCN4IC2Y05uSfkLm(Fd(@8~7Ws@P6#e5y$veu9C#cdd(Wx`*W@1tqFSNcJp z7{*IrjZuK?dNh3l)(doxww`Jtt*C%j+RKEKe}LWH5OGN1bF>i*O@bg#Vx*-zGGkFN zG9i$EYJ=rqm4E6_l+X(v723%8>tI~QALl)9&WTaS{T%uP`c^zU!;^eFghEobXY-{~ zTZ0GFj|&Z+2end3gjb&Qh>x{xeVoK$?v}_)2m1(Ir;$m#3cTdxn_WA^8CcPmi-KRn zI^7oJv=%7$E;O39025Rkk!O2_wTD(&8+x z3PDz|d#?pPbgH;MmUlhWi%;4Y1Tv1#BGAl9dgL!hgbrRRETA+9H71WN6AtIP(=t7nulGjR z>BWYof4erG-#V!VmGFuyN}EHA#B7CgXXjXcjQu!;iswN(S_qbm+a9O3wxx>OJ|2*F zm7zH4;t

uF7(!rc@EG`EY}xhhg%}UMfT-g-ifPNQ84}&#O7`uZ0KU zixj?YX(xPgx!++EAq8q3JDpMmu#|UEK~=r=T2EKl&+$=aFwE-6nC6* z-Qa3BTG@B_t1&t}E-g)qNg~zfW_#Uz`8?ukVxEw=T@Q9nebSXLE-Y|WU(6-v4s07SU`GtI{JcuuDA`H$J{DEpT2v2K3kl8k*A zxA{(2vEZVxb903?S3V6B8VHA@Xv1-Wd3LULZSfmRrp1#{WGU~BGe;RmyZz75eOdX! z5+>Eo@``rWZj65b52D*qGv`JZe~*>yMT%fT++1H}lNz}Yi$f}2Mzy6@nvb`(M>5#F zUC;Mu?6F0I{fe2S0e!Ek7A-6XEs$2Dj7GrvAf;Za!Xgn_)#&C|2R2($_7Vw$@(kzE zaBrl;*`c;=X{j;&pWl_m$s28rMKe(1m8{{)_8r8e+! zh_~*NPj*lp0UfW&rMTzXzOtM{|hN1TLDu{_*n!!;9)i^* zS`5aFYIP`X2ikX*)c|3>pb1eY#il`T0k1bH=f5a)oK+h>ZMc;vMb;XBBNJMqR8TNh zC1ieW;^+B?Y@{gR$d(C5hFWQKb}PTda1Xla@jFTVo2vUfJUyG~ z?%_9JYf4SwSJhi#9ngS2y^>FNYH-qv z2&^csu6DhW`DaN_f!97#O4dIq8SpL$ml`vCrfS%mBwyK@szT<*d;~JMpjW%A6`^rl6q8U#Q*~;NYz zQmy+?su|T?UFfcQNDm!dm$T*oxg?GnvM?`qkE^pU1zMf(nM!RSKG8ZC$h8;`-3d0? zW-7Do5YzABKeP`Btw#emd|G{YzQbDNBN)MZ3cNNeIxQB47KFEgT8WxGsdFNH-Hs@2Y{04SB@-P$idY z&Qg5~f_=H<0cKqfhaMTfx=ql{p^u>A>l;M!I9shc>E%qa2F%XEd5XBnitfWAY8B0l z``cvYlA@f=8%hX7M7-Tz?0l@$#<;y>Y$hHhTH!^`5Z1Yjw)B$iM{#k^cb3CfZGXDi z>*}3kjRFW!b5-dc9&z{J%4k?eI6lmw4m=Js&xrWo*N%mHhWFE0E44x8hz;z_&3^DK zNOZZe80-%@Ypu@IB|ksP@;TM77tRoLmQ3wPZS&}L=lEzlp6uhDSwP>Hq^-v+PjA79Ux$Xla?Lzs?#YdbE`63Od#193fdxK4 zGytl@sd)H`*N;o*fL>epjvv~RjgpcGGg76l_E9%RtqK_5D8=$_w;8qzDf^v|l@vFh z@f5ottn;wcK=xxyQ)ti`50PXY!l+NbHq5i$lpU7YoCgN5s0Amqx7zH@L5)yP+0|>* z4XJZo^sF$WquCHN{%X@POAClT{H^T;Lv6pjh$hABsOy zXGg7p)>}M5tG$!l430lNCb=vuETV9Yy3o&qsdU%%G;{XRh)Ol;kA|na)q2EiS!Khb zH#~G9;AF#S-C4~=op#pui#Xbz-&|YiN7*iXTNYk6N9&->?+aAKqO6zf(Vjr(v%G|& ztc{>BQh2){(gC9OK%xo4!&6QeAA-g6Ol(V&Og#EK5Pz(5+!?;y{2$*2**d*2yk@zf zoqgB*m1*Lr=SF7Up_dc$Nb_91?rQ}GZaVKeFLjoLR<%kA&X%3#L@CzbU7Bk8Px{6d#9Tn8^8Lb^oVHI1_-?Q#4?{VDheyB;t$2=_DfI zt+>A+;-^k1zWNe8&M;x-{MzGmc}JE7w)z zEUh|5gIko0HE9l#N~*Q&e|`Q36sJNb#NoflZ)UjyautR+D7H@z4sM5zbNC?d%- zRosS*dwp6K&cZ!ZDb?9h$oB?lD&7x{?~)EA^9*6mY8?Am^GH4L7jr9AFdGcBzo5uE zDwPo~{R!Kt6*0kAfj~cN$Gra4);2fkl$lFe7Vv62t$`0=SQ!V^uK(RsLEv|%{$s{< zdVwP=9LK5?r_9t{m~gc5;sj&>?Q~y>N9r6C*e&A#e>^GJ;Sp@QWRcH^*qaJpyi@^K zn9{Pado62mW~p1pl<<~)tFqOAJx-GIWG>E&MT(z9gRGm3t)XYgOOPytxV;I}PJ6JSx1~o=% zh2}l8FIlJP=$aAfrx*1V;8f<7!HI7~Dk`d~{1mCu9VFUDIr5J|kz7}i!a!F?yb9bn zN~No(Ypv?7YhbNv{mej~N>_((PG?v1C+`7EENoV%1O$b}z*~|_xD@UbDil&l)lcDt z&}i1&ps$U~)YeEN=O>NR#50`y%T)GhS;}(M_Q>h9W#{Iw62bx|4rM%LJb-}yAMjL) zrqdL;tn@rpRfQ)_oBTB;>hW)*qw{)f?%rHdO(05NbtyYHTYM0${XIoURItTR;G$DZ zr{TSp{3anpnMrS}@CPcN#4#*kBvIfw?RM41zDjhuLc$oYkptG>v4sZJ8GFrFSs(|) zPmCpHTFce5B1DnymJxdHReNdAQrWbp$#h1G8!O9py;cVW;7@cZHA-A|xJNAFzd(JC z$w4uUjE@})1`QhTD7*CrLcfE-dg#qa$^7hc_|*^f?p4bwsIKgdntG0Is@{)rVSiWw zcSDl=sW#zQb3sXru|2C2!7YZPQgLrhz8kxZ<$K;ZgcrH@tdjrhdhr`};zS6h@cm%;KVYH7dXC_su!P2V=dI!i?+W?d&;)M} zcr~PIWpJBT5kIGeM`Q0y$8iNEJM*EecEcct7Dc*x?=$wG7z0V(<%1AJDOa_G10 z*QZ`8#qS$P)+>Ep_hlx2t=NOf#5Kx-5D>NzI3PtvCC|!MLxv7V|ML1!oAJ?g-&Y1h zd5lXqO>;%9_|YCotvvlz4p6500}%2z+XU}*1%@zg84-pcwU#f>R|h$3KQymW zxBLTg^{NyHp9rf(TX<;gt1eFw`8Y2@csmJLJCf_>nLGFJqslY)I0~VKg(~@lV2+qy z+%X}QFY_B;Gncn1$|dRODG%sAQ&uDuBa%z!6*WxW(piRwv&j_L!;*{3!J816G7NVl zob{u-yWQ{cAp<`IwO{E^YQI$eGali{$4gS!wtD0DN4J?R_5G>l3b0aNe!kja?_wlU z@*hCS`_SFXX+0P@SNr1I%&7(k_8fe5a{oG)QX)lV%4-h(?PSOjCS2lxT^IG;xc0&J z1!BD9%Z@pMs=TO~hGo!I4>a>=ik9`%6?@UT6E^cfn|o${nNvQdas7!XMQBkMa=O`- zH2H~F@8L`X*adx1htoQ=KE+Ft$*eTmuw##O)FmDiV~~{&hNjz5fKV06wI)9^WgJY+ z=h+ExiP&a`ac*IIU64}b*)p-aD1G%!K@~(7M)n-tvn6A*cqs-~Qz;e9%qoDVnq~@h z)*)lK5vxwNTavkYG-H_Ol%O;k;ttpY{Gb`$JfoaHQ%5TBR4a|xzq1uHHs=%em+KCm zy$ZXfn{yk~SUN@%iXh-n=g$6x&QNvZ9LzR1>7S5f6HUSwsX zy^}h?ZV!nlDm7}_-(z2(i zp`L$$iSL&z0)ka*&zetM9y8KUDJz8`ErUGCX>IOpoPxxnyMf)E(GL6`Ys=s2z?BjGd)d551=%6T`h8N+vL}lA zS@XxFb`e>Ebo7NMANxm#o)V*$duj9q=}D#qt$LveHc5B?u$S@;I=t+ zw~6t@wUax@?I4*r1V`)a=~KQ|DXIF$RVr!YNE3eriLQ?;_ene>42YkcG93{gwolhk z+@_l6H#tv9J-72-UJd*~ad}KiUb&r52q=c^4r{DPc#ht$eh=f?xSH9W)Mxt7WmCTP zv)yX~_!pWl^0Uk|JN=S3lM>6%k^U>vs@rG353#dqBv%lQFRIdqG}8}_p&_cw%(%*Q z1&mHcpDvY`^^%k+8lalM2)bY%gJ_w18mnRap^jfY~=hjTB z^YF=Co6(W?!spbsVN(eTWMn}-gQNA2tB~usG?n;fH*o zUzERvtNv}ue79d|wek-T^<%=pQF~dgTG1%JTEakD6FtaOT18rsWPeHY%f*_g#^4v*4`-Pxf!9M<0(n3r+Sw1#;`8%u6 zy;5(BYHiyNp8uW-cL_(rDLy>M*n5>I{5h2G0_8SORot#oWYI;XoLV&hrwZbrWldWC zq_kZ%O&QxF57uZ?nrA24?ssYG;%tPHPw>?L$*d?g@m5W6)G~W$1Xm7-jtjt6ui13l~_;w%}U2(KJk;iF5Z+>ZgBdKJkliBT=6aHcfA%W1_Cj2rAoq)Jh z318(}zHBQi14{HLN{)uQizaOUo{y{KCM|8=wr?RQ??TzkXSS>aj+1jf)7`#LmT0bVezci)x%P`GiY-5>SF@==+NA9cBj#MQRhGIWlaQ8?14Me^eMZj7V~7=+#1w%{44G z?8bC7-aas=XY`*oQL#atwD;i1sZ@q&nQr4u2=Jkczk$RutkwdqfWaRU<(M87f5eE^ zl4VGh@6~s((^!ly51J=ntn;wSY)br46_QG(*fsj-DYv?t;S<@>&hU{u+m%7t#Z=MJ95m3N9NdKPp8Q<;Hqls zg}*?;DXVq4nyceAr}_+;R=Ed@VvZYBYr6B)mwf zAX)qY?XhHC&`TATbR;A>GK(;?=H^U zG-XS3;_fUfO;(rj2^Mq{f;0T#m_?RU-7@Re%pS5EYZ88s6Dn7ZC|p|x^QKGk3Bi5` zNQ01Ia}`Y>kKmajPCDa97vUpT$Bh<+EP^L=i#rfGp`0nT!_HuvVF z)S<%V!GAz90lQ51Z_R^z+%>JccWzs*+YA%evx~$MBMnj+eguwG%!8rqN?Pwpa2c^0 zH~U^B`27Ru6BT1I|MSmZmnvk?-*z7~6MSHzgkrc6Sm)G@__}S6h!7>c^Sx_6-ux+P z;r==G>a2Bgui9p}oUrEB+NBOHfZ)LC?k!YyV&OXWUetCI>(~+3_9kI-$JO{!@o~>U z7)w9jjLM&%wBA!9k3RmFe{0)6ZNxF*ZZXQ^I$+VfTj6=fuyuDOKg2<@tfDGfjQqP? zslUUdJn8OXuU)7OAiCz8Qb)l<`w@Pra_S0$H2S^4Bqg1S=CH*DVq{gqwC}nSL8)~_ z&f_3^z<74vdj9HnfsRep@59EjWf9UgyXiLrkrhHzdpKmJX6G^@kK5Z`Kv}jd-xiA8 z&HoA%*%?-ok(W&{#>vh6MB6N`f2qIElG@l^=b49)@TBsb9u8w6jv-bqkom!jOIbSh z1Y`KPoXFf9Xl}>;z8Kg0oI<2WZ+calZ(wot(WV1UmSGG>Cr?hs1u-VVWHCu`nNQZ7 z;S$Ds^KDjYnHMMdtCmAVqHp7(TO9Uv=Ibljl68{7oQw0*crjsy&GsCmtksR>sh!Za z)Ku~btFlR$?3O_j!J%RbBZug`=A8Ygvbn&hJsDBNXDCfBLZAK*4a=ooLUW4eX# z>Y&PLeNgxPRYriyMPNNaX)b7G%(;PB4*t7t%7`2!bDKYW-Dild(b;1{Ps8cYf z6+d3<+KdJWIfFdD8=~6?c&q${1@QHHe{F}(p;xy|f8$?iB7IULpvobfznQw>4#|M8 z*F#tQxVbpM=nK#Lt|C`>mT7Fs#g8U@iazY@@b&F!lag0!i}ue#vm5gq*Jj=rHy62T z9hBsk(IT?TDs>U;n#@mY-H9cqS!DL#kEkPgC?QiViW%qX32isaF2U(h$kv37Av*({e11R&r4*)ZfrRfbw;A-;5|9eLezm_+3SM4+# zNM}i}X62QTNSp(CyS+_ol=|(&e7e)K3Jzrh*ev{m6ZxU`i@}X8>@o*?g7Y$+6i&h9 z$-RtB^!NReDew2ZQuZvHqbigO-!`_i)1f<*Dkf@KvNw?FmoYhN2xza!lX12o^lcJX zs%uy_wV}l&Kj*Vzm*nh797zJdOspI18_$zG)mFr(v! znj=IY?M_oDDBA1WR?N~N&V88%8UC5-dknR2x!NUvk9VCuznIL~uC@%wItbhz_L=Ma zdC=q)%55a3s6Z>?mO&xg?>*v$koD5RAkm>v9)jq^q3hy$5`SSMi7E~+E`i`fKj1?{ z7(+Q9n-g)q@~fd$%M=&U>8S%1Z5QFxSUunghg_zb@Ag8 zVSVmci;zizgvQ}hq2%wHbFM!HZ78a3&K)=!yxPs03g&X5+2d82fBpQP8N}i_Qw%8z zd4rs0PAoh>mf`fyWbyQRiB)ur2Ul);HSxBV{Gc_orj*mEIpH*x)froh2B|n<&ufxC zbHhs*`SZBP(5#t#x_p)^=l5sy(Q(T#nDq~bwn8<;fi4w-ZTZsoB`7shUdMsho5Oi2 zqa&s?U14<9$l>*=rVxX}(E`5TIwgZmd}ukA+Y793X?2W#h6P}`q{^Q#U%ZUxzsoD0 zbn8AVqMiT_GVOKLOxkO0@;4RH#K;Dp`PZQ=g348*F=To@@|G(`WUW0btobL>q8hW3 z%^5S?b|&snW$Vwny}~$BU)wEiG$-JtDAJ(C z9g4e4i%W2KDDGa|OK^wa4#BlRaA|ReqQ#3Bcc<;i`~4^TBDvVfRrXqIjxpvl0Z6of z33AzK-QCPXjygPAlu3E92kfXQgx!jXK#x&-%M2@H+rU?kkFbc+6xyZp1<&n(waAK? z%Y>uT=`y{V`}-9e;|*RGdv7Me>I}rt==3rQ>O$>vLjKSY+K};4#-1-b>bTP%mTmEl zvxgUu%lG&Ns?vQJO-&9(N1l_4==7K0Iyy9KC)oy7irj_f7dI<79DM81sa62dP`m47 zl%P>7^jdI^W@WvR0JiO8?$JHfB8mw=V>ghME*p;AtSsxr7iUV};Xd^P!SZgd&%ROZ zU>X4G)$&8@)!gnL7g(GIT{74-j{~XOPYSq=KC}rObQ?XpP&CS(#M9e42!X)i0~FEfKrZ~ z#JpkegmFwyz;=qNt7#woP}oM))K2^`Ym5SYGOV)l&zt2X{t8AE?~@(=gMXuX%_w;fDD zB3&Y{EAYPWy#%&(o8NrGv7AI&_iTjK`r`aP#b6=oc-L$3lotFBR?FKFLr_GrxeHA7 zKi(wSTo#|L%>}Tbmb|uzO+5z7AR?IqTK_!hyLNr>i)h(~py@8xYemeer6v9$sCI~ zX6gm#D&pBHqp5?xjXng$+tEYIx57^_&NLJ)NvwJLrPN9u^ThQ)B$;u22Fwk_fnDyt zr4(^H8DYY_e!A>wxV?*2@Sd0~$D{n=WE%25i*0Cf0^4m>_4O=iLu793fQ*4LPiYZ| zAox8Cl<1wP7?9r_PV@_HM)SVuCf+jpdLquL1C(Ok9|2TSn_#cd2&^SqVN&n47v8h% z-m<{JU}Mfe^(e@84% z=gc*{Bh{OQ*A~q_ID^|E-Et&3P^GOZyvh0f1DQ}$Rw zdFy=+gGq08@!F0i2I?-wye1A^G53N3ikD5lYEkU~Qx{dfz91aGtLZh2%QGiGS5u=c z%Cnw3&XLw@_t8bNFxH?uf;I(#SdJ_p_2m4YzJQ2-^D9G_>e`!mSXzW52($S|m0MO7 z8CsOvxCpK=kUq0J*OipL-(i+b>PPlI`y=?C8Ryd zrPqXuu#4I)Eql=O6RV8m)9-Nah>`UX1@Y*DSZMP(k*IAZvBP~PW}hORDc3fLP3W@m z(D5O`*B*ynGMIL~p`iku=3RZCugKGYnW^rJ{cQAG#J6jv-f&;B+xs7&(d-Sm&Wq7v zRza7SoL2ZxJwXBrLT-XFZ42H#<|;$P0R3ugvHm)J#6Q2N(Zd4DyKPKjwUmcx^Q)LB zr*l=c?Dd|b4)d_f1n0IhHU*YJ z^-VfRiGxr{aiq8xC39=N$e>7eNip@s1r&^{kKHdy2eE;qKJS}Gy=!}01E$8 z(%|jSgyFtuStzeNX6>)N2SPt@;IW~9fb|dI{oEP-)I<;DuPuK7UJ;M$hFjln{)(<_ zDW#3Xw6^Uj%!|#i({V^n`23_D8a;GrC@iK5N0;$v#3}CbHVZKyr#>Erw@VX|>r3G_ zno{?XnRWgH_(~v!WVuWfCVIEK?E5xGq05uMIJLU^C9Kg4H&m_oC)H3C9J1_)el{w% zE)Xfs;~_Dn<8jHc=1zJv5aO+#mYCdD!gzydN%T14@ED|1%XK<|&YD{)WV?!iT&4L^ zhF=H8np$aIB1s)3Nkw*1YrLOdS-D>+V!UTC9*SF$5t08Pg7-kfvD+2 z+(1ylga=uP%4CFC6BIB&0{%iqF7=2;H%2ba!jR!bzyh;zR}Qap7Wh5<4jd}&32>WR z@qjh8dG)IA7^!>Q^+sJBoe*vK{}q`=Cv!W2>y$``hs!3bGSWK~GCyPq*EyQ11SL@` zEBEK4a0qGHS7A;m$~Bp)x+2bN0y5<~0})!1wAs>-(kXPq1qjU>cO^|tFg+o&qh^~r z1d0fPlzw8*o{0C|@XGei&k9<~%FMJMi;3DYG&GMSc2@0vnPvkE%&U|+x;xM?OMzk# zuL4vj^3(E9^P76ORTp{Yl&<7~CRNdoc`32d!Wn86Dr7WFWxB>?%!&RV@*LUIMAW)J zD+#mhYhzh(ZVDVay8P|wN^g3lG0Vq-3kQ=1 zIwvE;I^Cm&x>IghDYtXNH}o{CI^xTi>BuE}^ozE6*@Yx1-Z&G*er@JIw#jU%TwTa} zf7BaXwawp<>zwruVHY)4*sS6Neeqg&z}agi*RZD@bVy9iCzaGC3130}F~rG~IYq_+ zUa76O6|w5ONmGQV?1XN_a%j_kmH+0X2kXptNRKMBVa9h+r13&sDagunY+RBlAM`VDUK|VC@Y-k8+rub%vF0#sgvS~e<%owGxJxkKw$K*c-P7u2ebrU2Sy!p4SlqA|l+s;w)?S!d$W}d2RAf-z zYijBVEFzRg9M}Gy%eSD8qE#NI+7w&wrK6?mz>jfUJ6FM?rKUR7o-x}IwLq{lJC3(z zG~T$m0g^y7u6I${?F?iGUv9oB`5MKQPAV5BnGx(^p_``atTNtsdfR_czO+gJgG7~6 z7)4N@Lz5xMMGUmsIJC>{YFeVZHfv`#KiVzlG*8v7?tuB{hePh1x}9@eyCrjf)3YR?pw#l<|yB zM3$w82pi}zv2+g+)liz|TBO+vC~4MdU*1j*nc5!>|4=u=!^g+*Zpc`3M%ZKb;b6w@ zcG|M@=~G9p@D|a(|J~mu@_kLGOtX>VjXcg|M^xV`Lmsj-kOZ}w78Y1RTx%nqFTdM?p9B0x81E? zlRsupvYcyNrlAPG+rCg5UzKbfMA8B^ks#$r@-4B*=hqa*`Me-&HJ$pqI(ss;vOYF~ zwzB?9gosi}@tbN^Tp0+nHcc$41C*JCS)Ez`KkLt>ibat|Q8Q#wQUVJ784d}Ns1sWI z?R;S3ykzQ(({iKAFl=JKz%ZO|Ke)jmu~@7iV!GPj zKavIOdX>j{JqzNY6)PXaAJpF;wBq|Ezm*=(iydBY-nmWgr1D42c;?&#mHM5yzXN|X zAQS_<1LtRP$2$^0nNTJfac2R%{MVT1iI4l~Vbp6MY-wgf8__}>lYT+-JRt3 ztE&N`vTL$(g(}&~Q)mbiA^ngCQbXN|MGPOvAAkEY#+NZ2c%&3GtmGmKL)7#<`IQj4 z@_4@0H_r3f{tk}di9&A#ONg9=_5%UypVyH>$kvPk%p!lo*&J_Pqt-5#6V>5F44Po` zzh7Tu8u!GJm7kKNg0BD@`B5}G2#%qby@uB1(x2MD+0SqqJzidYRKU+~M%q8-Ma#&% zjqep`U)#LL`sUg<=nMF^6?Ik&d$Jw$^+gLw3`7fw(pv&xa}e!k7`I$fQEFIhHO#Po zjzX6L!rjBn1+)exDPoi&k(2t9esn1@J*S+H4%=xYp|Sna0#xY#x&iI~E8`L2-+@*lqEiz?XY4O*v9+2|f`kW+Kc(`v z{e;#GUbdQZ>mS!hEZQRGD+X58gl9oaB(CQku1f_{yFTZgn|=za%9Z(sFXZC&oG%>F zBbnn?$Iw`o;}|D8o)L%%;q4CD-}u8oir{Kw3anO?2Fz_O8zWx+!`cYq zS5=|@ZK%m(3e2xx!EB8YT)F~%(-Lmmb~abFWMuS~jeqPKqKbkSnuVP$gZPVD1VdgD zn~f&DF3(~uZ*-K*zC3a(MBMW8Ls&a9CMIqc?bhqJgSVn1U*{lRCZ^h{)dG=a)uhu6 z1wtyd1({{gi;Cu>*kj^1nynd1DJC;+$S$Q3pftJt&O~F{6y@R&Wk~$KoHE}!bGI;CAbA3p|a0e?|A zqcjZA!>)}qz!BSSGIEv)BPuvuIL(6m65C7|NvOf5c8_;Ze$z{A4r<15Jd#BdQ%tLh z#TPCujP>?%q5ql*3*fTkgplkNB+=>d3QVY!Pif_VTD1U9Q`MyVCqm$+GyU8#g$M?x z(XLLN-X;Zn-tW{Y?U+u0k}vQhaf-NffX0i(j5CX2U8sQJd*~&p#>x)4?9V<<^})F@ zFKlKAA0By``7)&zlYSQal=edTY8Dn(gSY>8C;%{_w%~d5>>x61Pr5a`U;MSz@bUF7 zvAgb78hC&C9C>EZ&%(d9)uNTNM)BJ@585!eu!*gJTf@>?#r!8NPriW^F+X)RI@6coNic``4%&t2hSM&a~f5!UCilK$ah9PuGM4-I8}&z>8<3D_U7&f(@14 zLsG$uO*TTn*adCPvd@i>63YbgW|`+PA8;@}6V3qsKl;lp%zMk(J1*xmLX&^#;R|#M)M!?MKVl-cq6GmBMiP zph37`0%Mvm`Q9o0ozE_AZd{D=#?H)pAvLPgsm}Q{{yZT=mul?8s+S|@>=8Bs-7n~P zH`R)ujC61tcQ=6#x#$Uex%XV7^tAO@NGLq}G&A|DWYuUOE3fHw@Gp5fM;(-#XX(hl zCd$yOjm&<`VsC@3*r_Qy+X|K8_)zBuEC@wI+3xu`y|S{iQ}t`^RFy-u>a(o6k}ez@ z!`h)eL_m?8iSX!xp1oRc#I)g+%8ldfnxB$ap)Ab)k?j>a;6O8MW2D7_$S+!hxErnM zl8!Z}FfHmL$MSA$iJ%9bJ88OfKA0LvD3gf3 z8z7MS^9wH&5FH%~AVA{A#kWG(?SE;Yf?xt&c*HzVH=d0WyTy{a-}UOfSHesU6!iRH z_%LE3$`v5M;#}ugMZ~nDoN`)Y(+P5jA9gsq@iN3GI^fwKZ_?J`v3`?XFdy5YTvmI` z*mHoKneGs5xNl$k-HX9M&sHDN7FU&5r;4l9PBXE1=9;=pN8V7h-z2$)P$>dn<{QW& zahgkC2|0QPtAO#dT7M>u#Q1)P`rbRuAk9O)T4O;hkBXURHP^dLtaSm}rq9lq zU)wHoJFdB=T>Mfk;1tJ)>##^*B;XWlN4%>voEq>AQ%{p(n;mY zyQA!jFKpcE#Tmeo+i1;~p=`u9ZqAX_;_?)J;G)H&N-A!3#BU_(&}qX>Qp!vg|XJ?EE~YJ6kd1GX(?W#(s1xJGsDff?8@-CSU;#d(Ny*2lnCe zN@jaiVlBj9u_lBE@q6ct`r!tMK|h4rvU^ejCBKGbl?&oNKIK=LgOHob8Y8LX?TRGe zgsKYA7H7=tPwn-ghG%Vcg@1r{HoA}V;?egjEe@spL0xC!_LI%qSUPL#hna;$_R)U;#QtIpIt6ah zbcen{&E$qMdKKoqqN7Sn4n@!JJX+)K)`P0|1=$ms7Zhem>ud4vqsy+ui8QN+Qjh11 z@-snS;%j%k-|~63tNa!4=v*-*%ubAH-EIO+54FY^ebgVFfWX{4ug$xn!%3aL&^%)QHC5|68*=S-XB5boS|!bJ!21rA z7@C8%#!)pW!$W;Y`R6b<(|#mhUD{b-x1K4N0UM6Ua(J)Az}&H)A2ZEu6%UyLd21Fj z&K2hV$L~nDCaF8hu23Jqh97$>DBRH%NK$1>Z&HW5HS;Wkxh=f8W|TdZzjAa|Ir5{s zUj!589auD7``H6LSTwUqtW%-rB#dda1g(gns4+{&s=C#SEY0Bb8C9{zU7L(;tRl=* zL{j)~0#I7ILzDvqzBhG!_@*z70zxjU<&UarX(IrjtSptycEo%Z)DDmXjJ%+e~SSwkIIWZ zpB%mO*+yf#J6|3#{evAPbd{1lYHaQP?QL6pP#l2U!!h*dT7=NVd*Sb!q|1;q-A)Qkh7_~)fOT>g3I71H zD{QMK;t-|xno)}4kZFd~@}{l+}tqA9jY55N`kd$d9mL>nouFc6ysa(RdY0L9S*k6m3JL%nEq;$9_3m5=C@R z)AfzO+^P{OcS*%aEE%Eg)XDg@?|IRn>j5o3$QF0&qeo2?Lv59w6i-JE3Sr`=?q`K* zYicWP5(OL01$c0v@^;cT`bbAHr=?DEfM4Xf{Qc}*UPiv*0x10YSY1*9%^ig-kuMZ) zb@x$#yOJ-RVnM- zJGvrSMQE9O?O1~nNlH(bx+w~ZH0TeIYbvD^KfV{rNWM-r2I0j_9YCNJJiv5h`cUWY zWUm(|QOWzBl@7>&kA-vJZW-#tVaS95G(KC%4!uOC(+!dwd;HB-;JS z7q;-*yH?7v43tRtGL;NkGaD^7h~l$(T;g<{Nd=Xw1f3RZEEqSMt?-z&WRbO0=%dw{ z(bXH})TDr`aCQj1{~r$mMJ{6o0N~ap9)Jh{fcK54QhKdKk^7qub>B?0FPnNfx-Xl! z%R0J`5S6jJu*<-CBao63MGfu)uVvGeX(37UjCXy+|B2-|ohNSnKq;UU5$W0oH|hFr zbK-N?D*|C-p8fLQQn)^b%dqAv-22hsB7vCgYcaOZ(*yhXi9TX2jq{U716`dw*ZW5U z^%|bLcYQx4$Zl?sgDeDk>YUoKZ?9*39mxHp*g(MOgb^j{pnrh!&d?KQPav39_k<(F zR|@!BV5a^P4Lte?*l-p7P3KCfx8F^Jo(ZNQy@TOQ`TD^Uu@?2&V^r3`sl_VqG>;}* zG*taS+D*F@_Jn%WCU6Cb*FZWg>s!vCs6jYk!MIs@GunCD$MS~RJ$FJ5n{;(4$iNW_ zt8AAXm1LJ%lgjA{Xwq0eVXtOe12nJ|=%FOOQv(lU7X zDuP){+c-}soW}Xbnpwm^&`P~RQ~lVBHw8Bgp+pT_>XJHHmtW`$W+>mwJb4&)2QS(XVIleGzR{MOV_Cy8SjrL!xHx zq1ho=gF#UeJav(bnKp|unHW}|bnt8{lx;tfg4gj$xcS<*7tc2=PWCN{#l z`n1P8lhH9e=(G(}6*|q-uQLARWmU$@6P$z1f+4*G&7JeIL`L3;dsCk0;Q`B`U)Rys z?^cx4icwrLP}E+G$uQdqLZuuctmPN7Il`As{RJ}1bf;NSgfQMKo#G+JN{S{HD|#X4 z4MS{DOI%MDxU)KX`wA zqNxd86?IUltL~OKwau}dQe@4Ty*vMC4v9=5U298Ys893Zv}=LXMf>fM1heU=CFlXN|BXuYSL|X6u*uqvJjc zE(>GWAL93di-aJI`7(_tp=|1ZlMzNSivVz9nLeFX63%H$tF-h1UAGsWBAh}v!=rLh z;PW&9WICBm==I*1M%v#L>!9Ea$&W|S!`#26iu)s4jKF?UFFC{RMd8{osVHp5fz%a+ z5F+GiHef_4J|YG9B}4`JhM7zZ00|TGG(tSMaC93(qj8LGBf{Fp2Wg z30qN8qW%e)Xu<$-n)fzo?}AN~bT!rvCIm!7y#-~xBf{)<3MR*MJxVolJU37Hqt?*e zSMw$9rIQEY15NOlg<2@T`2F`}U{l-HDGvw*oYb->jUo+M=%~B5p>b z$LWy~721W3FWZsEpRVSOCic7L@rZp)Ot5#igT?ve#wB`56 z2^!R3;?J1KZG`YJlPIkv3mm>xx8mC1FicaG3dcfWc432KFwF0Ad$_Iuh`ZI3mmn!% zVFaxR)oRAv73IhqJE2Axu}vnu`;hPk0;tq+AN`~129LcPI^O19qc6EEZcc92hI8uV- zYL*kC!UHfys3;7j_D%fYN@m3BI8tCrBB%1w{4lqf=d<@DhP5+BFx!xtY(A~s-@Nl;)BoSaGx7Fqi9`4jwI2p-0L{ZqQc%EFO4 z$YSFux6HSmT35zG1e&OT?8~y*3#F+Tu)4hX%pH!gt@Qfva zfkKKEp9P+=wvbuxm_|-lXsx1oQ2RyMCw_KTIJv23Jf;cHU7W)Ju=&zcW|+0{mx0AW zW<@RMXt4#R6Lk|)CTKLTb*x$qK>{-p45=_>DO3}2%q#!G=!B?{!2*+CB>>DrxC*=G zin8boT)zxDn8)PT({eJhQgc9U1cMVCJjaAV>&cC8YE{0Zea>BHSsAf`ut`b{LWUjn z{b8#0KQ<(?9IBLZGYeCU6evn&x|M{E@vXwUqu!9qnJb_$-bWOrtG?uU! zdJjoeBZVSn>ndS2eooyc#BcZMd!15F3x5c8`X#Z1gpTe+v^aCW{x0J8?@mpVbV49$qJC$o|>Jpvz z`&ng3^o1@aj7KsI*O->gKEfXvqNfoj@7_Sz1qqI^m}_A?h+@6i<3s7lK-UE_TFBBr zK=|$X98hAv?$NE|7Hr_z#1=U;J$=^ENNFVz__N+|&w476Hsp)4{P%@0fO06s4y5_m z&qp!LgE#T%%RzhM&}rwQ7-lRpW>YG8fivK+>!Rfny2mrNKdH2fP@5*of3uVz@b{j9~Lbq;p|Y8A$cYh1rjWf>yH zGEswhh<0wJ2%NAJyh%>^J-O*~@x13yh+FXmvy|NMWcjFtJ<`XkWd@I{)%Ug{Riq*^ zq4x4$8k2Y8S4&l=88iwmy+>qo3y1pfVlZ9e=QCAcl>Y!+D;@9ul>O9Kdu~5&mhp;d z`v-8%B-cKF_cLhCWm-wa8PQ+A?2cvVjgUhwPvI5jmPd_-U3;n5ghHziBX%aUh+I~& z{fao9oYtI!Zf3>Gd-jz1g;yA~T!raV!gqnxBTs^4hegD7WqL*0m}yIdOlySJY&aly-j1pa-5J2ZjKqqt>7vNJM5tP!S-Ze^4D&nc%m)SSPfn}N zOo|E$^SyuxySTZYGfrwW7L_za5UfJ!ewNNG>m>~!(~PKnY=NtH|93^@!9T>@wvo?Z z`+9Z*#m$7i#;ceE8xx{lrKp%P$fJr91@!&__`7O(&cW*Y$HIx-E~5RrWudOVRAos^ zuP<=&Pit?-I5CDFZXrF#0^eK6fsI@^Td96_{muor7s1*M)m}5Et@uixwiw*kCq;#fSzQB6ZL`Z ziMKTUz-G!`^K{t!x?nLJ+)u_0`_hj{5{iy)9T*kqhts;%f&SRabGjQAAO+G$-PI-3 zAWj{tgiNYwjjncQgQjH>EDF@blq=Qfj}ePdA5+KDq;Z1I?^8}3`20;wFkH%Lm_;B= z%zeJrm|9j$ENAWVb}Q{Yv(N*S-BYf_S?*TETyGy#i=0i;te`g1Y`&cE>pB&_6WR1O zLAHp1mN|meSda~goBqC~1#82r3~xAI&5Bf}vP_-+JaLyW3kvQza6*OaT017R^vMOi zMdXt?=7WUPQ~al%j!x-z`>Jmk>g~e))C#>6(hp*|Oz}lSC>U1-e>-HfZ<^dCUgGJiLltO!^; zx*xE|gO)yQGO|3Dsg`%ChaX!=>M5fAE`K`nLSNReW$d^QQiO^Lkn=2` zV}?Y=@r{w#GcNdK5Zg0p#nPu%=(+qD!c%qBOk$Nc66&Jd6$=o{N#q?|%u^Iv1+H=E zR21aMG}}qoV}q2cg3p*%)svIgo7w4c-Z6go@rg+vJ`1gusPz*$lBt1T02$_1?cHC? zz2Z<;;7oplE9YCL#zc}5l?`v zjQ>1wT-@#bER<^sv9n4eUsGTtK-kzP;pyb4Yad=l55q&ZBGX%Hrgd;Eg`8;8qss9| z%&VEHUT==kM^>_Z5^=ASiHBvO z#(Awws;_^#UWx~2x}wB7wh9abx9bZNDIDH{;j=&RcJ6m48i=DVkWFF#YoCF)&`1W0 zd+p<&JwC<%iX%ezS~k#N#vco=*~rt*KeuFUp?bIcrPh@jZ8^L zXxu$`w)bBG>uD)|A)H5g|1E}(%@Ox8%1BWVN#&izdHwrTSnEMu7`>k%gD~>3;e+_f z;5V0dCk;^d6S%iY$vqfH<`G8-Cm~?!pyAyY`2s$ou;9PRC6|EvyNmn|Ujd&d6*eTX zZW`g_14G5^K?lJ$a}|~0wlka2nRb7-T?(^*0L==7GN<%LxqpDZox7h&cX+paX(@9D zD|Q|NbL`5b$WHpB!68mPbX8kqK3>Zl@925^yz{)4kA|O*oGw1a;XQn%53o!bx$*zmZ_QWQ`4Bho>KX;~?`EG%M zUs9$xsvW9?4}}Msbcm|dm9XF4({J+ci%&s2iQ=!q*1PZO-6=0kH;E<%uW=FXq8!KIdHz*=yipl>`4z>e&CxtbLsd5gX?Pl063G##eMApu*jeIE*?XgzWz>FIk^QHn$e@)rvk@(2L`&f zQbJd!htG~WQrxHuzhxCsU815KrszZq&lZ_i1T&qk6)Ib>BaN0s!U)0mI6gLY@q^@)d8k4a$fOQv>h>byO8Z)We~aK)z~%-+(%DPGq&A*Tr@gDWI@F- zY1p+j*U36*Rdh69Kf?g*6gj{EqG!EG+XrI;87bXKVZej1j=X);XaD)PgwOw-ZU6IFeA?=o2a8gw7i8-8$hJ|QDOby ze}Ew0pV4k4jstz6JD+FrJo*lo;OYO(52bJhYjMchFwp*8y<5-i7hr^A@KbQXe+i+t z6h4>mB8kT6?W|bqm z4=tVF`rJCqS-f;P71QjH;||ubLhQTaaLCF?@qFG;AWz`HDY1_MRmVUrv(P1Uq~33; zdms|1G9Z!5Q!~4mlK}whbebqr5zQJKL#%DLj<% zj8dy21P?gfA8T6U?%2#WKB%5F{Fx5PJ+a}_Cj`1RtcPbKgEc5C-(Y3m zq72~0r|^hq9z_(I+CIL`V$CgC)K_??xsjX&LW>Qzrd@Y&-pcBRp4nQ%9@MAa+O^YG zzkrds8Dc8W#hS~K$8x3P=KrWS5I>OwR5Mx4i#U*1;E|&j<1l=De7k|~ql)wik93&h z68-iU`Lv%gB{Bs%^#P7woLQ8p74mv9j?phS6oIcnL(tz)*4sLITx0-t86c=B*GawFkuyZuopG-z65(!-^{9>cO z#@@YAFp+(#4r_lC>atpRl(x+R0+v~-z&}eKns%DY! z2Wd~Mg;j1UzrGH*=KN`Aq{vAp3JWvF|j(YDW#+y}g=IZ8?u| zLAwg#Ocrz9UiaPaxt;&!cQ>Jr8{p#=4BPErqIlkZ_b|T?bQjrNc`%wUNcP%Z>UD$f z%xHy@4L{A{CchL-rZ}1p4o$E(Sjq6uf*7J)L5Ixj^nvx3)pcb)3 zmoK+qM*;1mW9petxwC>i6?AWJS2HX39p8R#u(~OC`0Agc4Zx>vWNaI9+81S88MkYf z8PcI8{>XNk*CVBAA?I9l+p@+n(YxAWq*|KSgIP&HRHV9^jua0w& zc(X}bdi7%4OZpww-xO?#zQ9+b?AP#HFJgxw`~x_OQk;}+H#og@*lW|NTyh}5!dBOPc{{Dr z7r_;fdcwfMx5^+!@;onqTw?BVlOPm~FPdREuL&PKi4u5p4K2PmheGF?Fk-`M*p%|8 z4&DHHXwqF(=QT6fC#ew`X>rz*`{rb^5Zs@RdOG?%&x!qdHc=h?9CTWyuy`Qh<*_0+ z<2-kC&yHHD{VE|2^JAPL|$_US9 zhWEmm#7l5s0?Ll^wFZ|W4FVDgy@QCi%h1>NdG z*$c4d9Qu4e5X5e~Jrmis+P27I7-ZW(9WL}~a2WWGV5Z10nSW+C7nW))U=vFvY}pHU*H5}zZ>DP_dzgxZKPnX5bYDy!y2q}SV2!b09J z{6$kIhS|?g(F!#y-MYiuNTE?$1@2|Zi!#t2#?a?Y+UZ!-sW<3Udv&(-9~^u6J#|7} z=Oa&oJ-i+mZ7B5oH{2ZnR>@LYmtmC4RORBIaX+TG-<+S5;NCjEdHqlrLM1tB(GO3p zZV!q}0ZF`O^x^v>4!k37*^~>6%bx#y`SN!*B4`PhQg>oRtmMBt{|0`Z7zRcyo6dq+ z-{RiC$aL%ln`LF+P=fyqS^_X5^+r*b-{O$_m<{hjl-AS%)E%8hLB;STz;&y4)n#|P;Vn&Uz&`-D z|MJuAe-YQdHcFZhvZ%~%_|yZi;CzPv3r^-q9u3^eGu`~#k?02g(EE22zN2EgZqjYL zQ}sTA*AB12LXBYI{kxe#o@J9~$AEr#y%BZ;_y-V1(^$aK*se(Y2hfjN=Du70=6<;C zTY4HCbwZVUAUeLT*}j$F;a6P^nBYz#BEyw@MjU`bzZ+uRqzswtvj-aDMAXHg3 z&4|lAMap32)Mix6S88imyd;>2A~_^l&w>#@YhYz%9i}0tf*Xvx-&eE?UI{!2m1~?x17*h zRh_9+6XrA;@%@m(HS@>7Ka!zz{6qL4d!{W?jBtFc2kJeY5DON`Fbj81+M9U{ZctJt zJ)*Ulj*zF}{An6sR93#(9#bv`!tRdGraqyL-mDE8EWu3Ej?L@DWA8l$kCUnTrxQKM zwsZ)b$ADJlrfcfkIAun%J~Y6E^@Sc$ydMVzh8;8+hnUs69mshXpFSrE0<04q*4@98 z@KwnY^39Mmmc?0CUm(8jQ&fZtRz{#}TqewY`2;|P(u+8da9$9k)q8Zvrj zSdgrhO?Bf;wx2~i-kOs({!w7De6{R!#4c@KK|-1spGZu)h=Bd$&kDKYwlGj?837dU z4TiwCLmM5`YKyNfqPuKLe~cFP__VPd586E-$a!ORc-xi*gH^eej->Cjk65ic~3V&!;2ZGp-CWRw^ zN4^Rtsd6PUoMA`zK#bn*{H0!kl~c{#_0D;Hep(FBnCFT0b(iYMP<2Sg_-d9;T6GNZ zCSl;$|IV*S<45D$K~?Z+r3Ru$oyc0RE#Mhm4d_oX-iGTaw(tYs(=-2x&>1WJO;NJSDY@zFvg#~>nMyhi$ANaDDv@wwXt}rEfU?n z$H;O4UU{?xsnw29lu2K~!|Su@kTLT`Z$%VlUfwaOghYAwNL@&r8>T=zAel~luCKgh zZh!8adUXOL-z`FH>OE!;-#ErQcUq5P?R2k26w?#!Cd6h9a$16|tGB(pC9sB89lLY& z-R?M86_&P0628PgK)MmAI#v?(ZKwhxf~0+^6cZu?A*MS}$$5xHU*?=b-!3UebAHUQ zRwe0i%bH2QjlcYmHTu7uYv8Q0jfu=K^I`a#dqxeh`H{D75l8N{mV=fWkI%QJ!J06U zOX~CbX|FA7)3u*{k~<@u?j<4tZI6qnnui3FGd4<5n zm9_8M-bf{$I{uw&T!wk~b47S!Sr~43gxF+#(a{!OIRd4AUa0nfE#QfEINn~d}JOwTH!3}Uy>+dDIjWi;7y z6)2eAj{T5NEs*v}$0Iqo>+L6Hqu45V1HWYP^a9hPT*jRx?!ua@w_G~yC~~!hb$?`+ z52v@ak>-Jkf>E?x%UYa@sHg)|88gSMGAR3%mobr6qutU(-~u6(07>&mqXD_}6B2@% zM!o2OIo>+DK%-o}bFlWru5hMG|9dMd8;#+8>}rER)L2WU-$lMZ9}G?@Ok|B#R^#Y; z3C>9ee-@)UAHBi z^9i0OjJ3nYIwm;&aGJXS9P53SNR$f92TY{Dv765nB!9@`q23za7~a&qtZoD#m1oQh zAH2F=Cw6$#X*lQ@1!**gx_JErM5}59v>tpqrPxpm{+q;$Gxc1qZ+Be>+~7}1|suu2Wict55p z8&Bw=H7(03jyGi{lGgHMpJ=wHO}@lJSAKOm?KhE0)99CL7vyKAeG>x4lm>6_B$pNih6pMHSXv)NC2s@{AbWslNkujpG{F$5Qtj&jr=Yk7V{1ofDU#GhXgwHiRc~> zghXyT!~@I*`Em`{_0uRqBpL?zLJ*G+knaJ|Y%qi%47cvcc@DXS@0Z%y3?UNh_Z`rL zAOQ>9Z^OVoyhnT?4j~|FZP#B|L(UXeJ6-K7OKg>Z74|sQ zEyiS>F2M%U3Vk)fyPBr2ow-g`O4Dd6AYnu%b9V>>=Vc;;FO?%On2KrxK_R^kB(FmTx|^BYAW)kcT-|Sy11q* zmhNt%OeF27+50*CqL-#6{qq)2Ov)2xGWkTMzC}#xI(To zMtG?xRNYQ~t4?}N+O<++bSh?}GWyW-uP-LTQp+K>8f~=p{{Xk5fR|QMEtYn%rATMg z^;b)ktP~USW(uD=M>PiP}8Nn0~(6 zQlJ&Q*j+tpPN6NVs0$Mn!nSwME`4>ZYyI-JUW32$_>R)Am9q2~hxLiqf7|9nan9q% zZS!TNj9eDpN~5!g9U7Kz8Vt-3N@NCV(|<& zCyFXm+WWYQn(~n~F*fwm=~9npGTZN|*Cpl>4V-DjkdhU0k^<3X0d4!l+Z(}{t7X!A zDX-I*oT1b3^)ihn`Wr}{q)yUl?8(bjsZSK%T6$f^)aq1=Hu?(LeJ(KS&~Klz*3h)B z)VL9cnBPdGc1$ZtIIA#{uCW()P1KUdD@v+*ZQ`Wv{8glr#&21Xz^0$$S`nsGx#~j7))s4CM za)SQ=eC`=#o}B*xU2R8K?v7C5;Rr+5Rvvw5ga9`H9P|D72d*Jj*I+G}JhT!Dex#_^B# zl|Y`vcwzZEa!Zp^^HTH8un0+-68)fC2;LwUHykcB4oX@AN9q^aA7mY;VV#w2o|#?6 z@B57gt4OKgxw^4!P9lz~p_W{|LG++0!6=vIP{i8WLYCCK>w3j4s6`fA!Aw59~3d+G&Ac3k$FIT))+Z#UnoH92EiE?+ZRVDhgTmz|$^;K4o~P%vZ1PV`((;#+ z`i`NQu#!k5a^#M)`ONBS=@t^HQzVE2W4V6$!VQuD3lz$C&)p#oV)B=jdTL>bS$5R) z%*(B@F3JHbb>~;O+7bXKH4&Yx1<4=-9y-Ndmxt+98r^Pjnsp|VCoxc{&px1rWhA8< zQ_~N+qD7L1kfI0bQnyf_iAf5x9@~#)ot)j4_+zo;q3c%|uZ=AgkXCM`$^a^|69;Kk zxaCuVsT>Y@a_?WV!`VX16rkaR(XmPY0JKn~*t}l0@IKC@@WU=3RBCLQM^=MnEVx7U zX@O&X!dLFdQ5lC5#AVdp!KEiXrhTljCfF)6?xPCe`N3Y1W%Lr$Ug(oe!1RkKSUi+5 z{oY};l2W-h)PL#%YcnX4PAZACzDG_=CNs(O@!CwJ@>w$%Q#r)h`-6cIWh|C3MZ@Rr zl~BM$+qFSeL`L1)0E}y#ytDHUH7_p1vl9*|Hr%@?Q;#^JKuB!}1xqB6p!sGyWvSHZ zluCTfPPIQLOr^*)r>ANa8HS}KrJ8JSIPApB>O)PWCh8?hxyU3EK#R!sP;BRkJ2Py5 zOVL=e%lR#HQPoveA;_TvuJBP5mq>V%rPCER|mIoJc%;q(yqgdxHZ zglrmK5P$?kbhWzSZyOG|X{r$62tYUR^Vic(epb984iJd6Sn?5%IoXrL-OKNVx9HD{vXw+#+%D8FJzE;pd!W=auy9c!#Cn1-YK{$E(Hbu8bBA z0e$0WunG{g~D5ThCXKI;>0ti?{2hr8=)dswqRjG25iUP@bZSKqn=xm}{_jDt2Y|oNOp9Ax%2sk#s0sDz@@& zpcQ2s{YKOMqV}h@Dm^-fkLwir%$+WL)MQ*u0*@g%FEm(Gvx-dQjH?g!Z?vmC$X8_P zLrPi+X|kP2+uO0;fZEQtdyH6ZTBU=Su{%WqR!T2UjYUOQ4jH72W|O&`rIf-^F_YB= zW|C~*PNlBbMsnS=L(Ju?KSWtHncnt z0t?7j#*jDANZyRa?Dy@TiuNx=Mh&h}Q;o26tFFCBmR&(q>b(oMQr&)5MtN*avh_LF zlwCxO!yod`IO3(=LKdcvnXo5h4j*iZSfh*hg;*nuIKeDI(`rfbG9_v1I)w+QovZ1b zmQ3zrHG49t-Lg?;B&a4%lL=!NE|8SVS~zmM)j43jm{ahy*Y`Q8pYF9ZZzfsN$Yx$m zD+)@>4HdYhJfKQT&McIml(vvbQSp02`(@(2wNgLe>NOoWD+RpsQx!P|=Z!|GU3Gy3u0}Vdq{0tWHbrfH-PHY$~``zP;#d> zwPETs^y|}$WfH;V&d$ob`h!fggfP;Urr8_)ni5vM@2ucH#@jLM%nGT37&Astvlj^p zF6t(%mYUVi5;9_%iMp&O?k1HgsVW9As@NuEYH=|4kq`oadn!H}pwK}Sid>|U$O&7` zqkdsx*@etI+CHS7MavVwN6BODv28nP&Y^ho8dq@}ZL58mDXFf?n8Jd$lBQ{LiI=Ce zq~sFfWxGH%UCqwT003wJ5$~fLc=h#y!Eqivb?7+Byto?NE$`D0_D+d6-hVX}kA;cXXeSZYP3w8Qw=NA6}kCpzA zf)Kw}Fm=}$L*@Ma$E0Go2JsGE;meowkIZ~w2nr!^$TSa~yf41oEIQ^qY(@E43j=#w zT`jKznfgS}?tA%K=Pvv6@iCXJE!T`&^6|GHoWy%l@ z!|(F)(h*^ZfNQ=Mg}UqO1R(?=3j931IO+6+A;J(`Gv%xzSasJ99JoOUu!L>bTeHp` ze%eIm*Pci4U;)2fexM*B2(a{oAzt~0pFTW3L*_XG5aDmmr>`v`p9ohEAJhax%Pm6i zgg8PFhz78Qy19o4L2%*_ge!>YrNcfU>GI5V$RP-Dgf3h)^Utr+5Vsz1;RrhQgdqUm zq56PA5aITOEBoc<7r)412ylcehV1+^{hz~SitvZ2txcf?)`W| z5CB*$m!{$I5riT2*I#Ht6~6xfK;Ogflpzifg=>%R$1&tQ1T^%C&+vLbZZL-y5QH!7 z$9I5-UdTWJZ=U^k>LUZ8w!9$#=sZJAug~cSKmqq1ZJxIC>o`IjB4>W?y3YFLYeajx zTy7S%tRdmQUnoV1X$V3PzPfPedK}>hdO{|5;cguI^MVm!004OT@V6ZI`ti7nuCwcu zA;J)V1U|ahZ=OMXp$Kqg}#^H%Krd;=tBSi(h!5Lx5G$60P5rQ5%r0FzTEHS z2ytR%r#^gn#yi#)A1MW1R(@E>#i`jUq7@Egb;)fhd-Be5QGqk zZcznCEw2%L1|uXVNc$|oCmpG$sViaP#y z#exv)@AiTaf*xN_%pimygdl`1)yx_7!ry;rLI^?#L#~7ng}C$kK?p+E&(_>`c<~Py zhWh-upSKP^Q2+x@zaL0nmw5jG_8+`hTzC2(#6Y$XUU^?k zy-yp!>3sQ(c-w*DkiM4g)+c=RzYxnH-Xq4s9#`;-Z0~I{9v1m^z{AHp`FG{%&I^U~ z*F81UO!c^j*Nh3*Jw96co?!m~HUJRxxCOkl-JV_Ofwori}bM)6wrT(z{!IwL0&p(&YH^MLN^Mc?v0l04G zo?Ux{Lw*AN-@H#8y6e&lhFK0{z;AwjA0W#p9Kp7HHT8w_w{`mK?F+mchlX5lZ>E|D z9noUm-&kNddWN^Xub_^)L_Hq4{bF2ooEQ3ld28wA@`d`#tl^fv9-a5|`N9DUXg1R@ z^5Q<4`i1N+2OItV+zxpN1i@g)bK$$sE_NPQgjir9yDa=O@E!jEJ930VZP!|Ad!V>+ z4!H1ySVCaTFK#)8UiZI%56&HRdqb}ry7c7^;lwuu?|;36EktIYaMBPb>2t#)e-2&Nhu#eNYYk%c*YD*D z;hv%6aMr*!-}>IetRW0U1Lf~-gI#z;z4`g&f4*OiaS1oeJdR!YTf-~&LJfM`j4y+>QA52Df^F^7lb&(y*V4dL|&;y+TnzL8;Ec=S5@$0*~^{{SS9FNY{07l`mbXd)dCfr|_`@&LCi z!Us{~_A$hMrFneDez3w6M7me6t*JXI8f&FnNn?nv zp(#@&CM0DUOxh?Ssu9XI?{DgTKi&6_-hb|Me&;;j-}8LW_dL(}{RD%8mq5nB*4`Gt zU;x0N0R*pMgZ4OFz&s(^Ul2JFBdVgJxO zWYL!ZFqs1Yk@q7;DgvM(69DDmA2IEV07(A}0OsQ#u^)F5LyRMSlM{hfct{8U{0ac1 z@Bqm50IpQi1A_HR=1Q-Zy1BL(#j0HS^gFfd!Goi>o zQ-F30?g2Ckr~*|43=QCD7y=Cwv_cI4mT-J%=9k_fmRb4OJ z)j=hzM0=kt1#8VRVfSQMa$SgVmikf&b+t-vE0eeK8Hap>bQs%>A7weEe6G~eiASr~ zZAHJdHG3$3uhpr`&apJ~4|3cpj`HA!p2BpsRfVe-=3-uUQ_^fRN|u-`ijiD#j@MBv z5U)QAM6u{J^6YqNic*2JwOZ1sDlx1qeN2*3pBZ`OWnsiABtQH7aG0Mb9gjQOqf{DJ zrB}z;)mjUJeP`F1CFSj2Z+5I`{DY@hhL6WEwNRn>V7sUe`?W5!z2Qw*;!ycPEGaDChjuwG*r6{HP(acV}(6V|e{;i;J~24o$_ky2s?>O;%~z6-A1#4JP)D-hEg% z$r~u1JHy);b}&z`YMs^Nrq<*c0eI-(s$#Q-qt(zj<>#e8RQVeXS9ha*WNO=rl0=Av zn*=#&O7&Py@7l#wZ+o@pta@qXS8w$VH({uz9kSY?Aq-qnx8!Fr7)T=0IUi6 z*DU6?t6GU!H%cjMU>!H>gWJN2BNi(wjSM^8*KcW}H2j*HIoE~jjQDC`T1)Cz4`-B? z{OMZ7ykM@8geVJD6PT07g>p7b|uD*PIhRE+Ath+wlmqbZ3isPHEI}{ld z&kj30xfTDWaIBz$`r)FNj}527<vd@-2TWqFqN=Ct4KqUYCMsh>(I z%YEXnQxltlbcu@AecC#9g_BN`M!4MxemYk78SOrHoLWRHa91pwQrKps7}r0}69DIm z6}gF=+-1#8bCcmyWdiWR`-1ovS6q3I)I!(w(IZvuh-+-r~K6$LV3m8FWMU zAr%9RsV({fp53MQ4lMxJmHp;U)wS*S&>xnwY9{4-R4e#0aaK75s|c*g?-{vh>WiFN z^AOUeIr-?~npof4XYF*#1Gna>&CutKrn!1dy+gySDdVS;V|JSjBPbnXk9*ZDx<;EF zi{9a`wiBXT(&d)ts1`4lU8#$?0`NTBKW=IL={}A&i_DD2=}Mol47&3ty&=z3!!SZw zTVWn9`|5@GD`bL8rgv?jMr*B)8G3Jvs%QNLr@^Xhj?-SpGfWOgxsbDz;a_wdm=u08 z+_O<`Qn}FmF>kO#3F%*bF2-C^ZTnW`a*+Wx;+f>g!@yaD)O=_{YnKl+EOhu z6b_QOT$CXY71@&|gKN>vkV43sh$$0?RAj6qBgwHidGa5|JCxh%ujNj>1l~FN)&MC2 zJ=P>M%bb(esMhpLnwpvx`v)k`r!bKvm`I8=@z#e_sp@!dH>W^Ciw-u+T{|Sm+Qw+3 Qk&)5U8h_T78o|)N0jn`(V*mgE diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/40.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/40.png deleted file mode 100644 index 87a14602e3c473a75b97228215adc89aac071d4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2865 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 J?3E+RzW@*z6IK8K diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/60.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/60.png deleted file mode 100644 index 03231a71d18936e6554f975c5267baa62de54ded..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4750 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 WMCydeU!Eqk!F89<9(0FXP5%#lwHsFe diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/66.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/66.png deleted file mode 100644 index 834c6b0987f9a294782d4a695cf3f261ed8a013f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5512 zcmbtXXIN89x89+Hw9pJKbd)L}RRQS`6s3iJKnS5oCsaW>bcmsZCISl5NhI_th#cR8?5C{N3qz0TV zgQj8H+78C1cl2PlbpLkr10qF;ys!? zX9obH)W5|1e`Z=|Bnm+a*dujef70TlV%bQT&Gm15`5Zg_jaAQaaDZ($I8YbSi>&l_uPN%<2fmb4n+BX zNU1?&R5Y}dgA{YQsfG7Y8aw-byzZND3k&#FNYA_28tH2(ctO>iIreEh6tt0mN zMIm81t;mmsXR`o3Ifzs^IT*MBbW~_4Ge&*^9ZsmfI{AM8VXOPg=b!jACIXJXZ&9}b zf@<%W)I)&d(}+s>m8pG)h&vtyKpV9N^eJ`00klI+{&+X(4v3U+MEvk}b9d^;X5a3i zL&Ud(aq0k_kS_`GDLnqwI(`w8)jJ&E4i3cA`w>Q@9Oy&M-7}!oZ}-F7-(TMW zPz~s88DD@G zbMni0X-jj%9I3g&CzIAldQ(v>BZ`Kt2yeGuLkOEsLU0jKdF4qSHfRDW^8pwPhQl9# zSu>~J2}nlM0AP9)Hj+lCkGVw59s}uBENod7nxB+S(k11L>%xuTi^sE1n=6;S*JGQE zifzc5mv7qZJKlB=c4X}NcDiPJZ^zQ&CNAy$9!G}z7$d(Bk`F%9H#NG`!iEWRP8YCO zMsQcLDnSp$1_g`}Eb2p*>1tS8g(yc+!{ol>bTI>Cn5T&gapRAPPhKo2)6^(4zWOMY2+?Q&&xe)cn}=Py)Bpvw?#9jpq0J zQ;ZpPp1p-D<(oII+P&1p^IFriH*BaPqHE26G{ycQW{RWQ_dPu>C9zmZX zw0|VgXPCEPIb?bH^=gOhaFP|1)hqaf!3!bmtiu~YS`P{Y5@U7E@6}_s?P_l4Nkj}u zjD`3Ij^#ehXf5g8Ym1uUg#36Kh2)%+wdcq4@iup_jL0h~#9f7P5LvmU@rF-fziWAd z8F-YMpDhgeC^j`t|I7@o<7eCqdEU!k@m3g(=EqHW_PDzw_V3JawOzH4zsB;y+h0VN z68><~=U`J*8tk$7>I@J|(GWXyZuogxg0G@sdOZ$XlK9s#_j1a>iGR){EBun4E15 z^G3Te2{;Jv+i~`z!9kXJ&LJ*#)h)GGPXv3eCnby)9d{}o!E??nJEQG@) zna|cJC47UFK4ucA{ zSDCto!YCg5_|N^65W!%j_lJZg-?H+~-wDa&5i?1A6F!YXv|Sb8#)p3@qrKl$+aQY8L&BU>RxiG3wj3hZ|x|Qzx?Uv(&zYJ1O{ar3@ENG`kpI zGx<2YF*WFu!k@q1^f33^t2U`ftw;uSG?nQaY6xK;uwRV*IspyJePVrA^`pZ8UH^#2 zL%pU{@%^mRIhNsDi0{|eID#Itr&?LSLwVjW$@i2#lBv`st|yE%>YC>gVDgB-vXh=V zF=@@a8`->?*JRf8ognXEikyXXD1^lHi~~)n)(gw_au>lOIL+AS_S~^(*t}OqZO zg3C?&AE2}iR1D<@F^j597&k?cid&woZCbEartj7aJClpnU}cwRkc-!g6|$SUhAJHX z;?m#ou|{f+*$0zLPk5t7DX|1fxqemz^Qxo11Mim@-GJw4?c236PEShjvFZBPY;81* z+B=6tFDR}s)IFY+sq8iaa!$yEg z>gyTswDJaIE?=s7mM>xsybzEn_=avrlKA*as1S#(i=B8E2wo!}Yu~Q_$2K}i*TPtO zWgqJVRrMXav$>t$>Kn9jBFg{6bm@Y^n_7MCRO-grLC>vC9skB_t@YSWhPU^d>d4kD z3;NfbzI%mD;r6@w%tLiPF#b3L>YX}XFJ5=%^l0I1jWz07vIxG@vUQ-6!C>Ak3(F|;{cCV@a2o7dB%~@B3CReIq$l>O% z8Uq(*?qR>}dC6(Bi{$e}N{1W5lZ%Dl&&*iWTf}V(_{lf+B;-|0U8j0dbXoC5RH-sn zS<`}+Sg1(O6j07Fyc}^<%KO@GD8bk9#&y;@@2l10TKG&%V~yv-!8ZOd+EKm3%?V-U zGvLbYu!pLjGa|ZaeD#-UzQm0^ABkDkZLkm&T5w!7g3NoXJKNMu9^eP@svY*qD|M}z z4aL{wCpv=nKmV#PKGFX0omU~KL(ZQ?dg#Ix`&^fp49RWh82L6-+HvlUM;UH)v>eiO zWMs~~b-s0h+Rt>*+)3fX0(rWi>={J&AFxC304VxF$~Ho9;*;#QPzDK4qm>!zFmb5Yv1pKU1Xl?g1y~x z(%`rwy7)T{Pl?Z!tzz|AmAGUuv}W3`j1Gp6ue^7W!5`VW#yUVfPF*|NiH`Rykp%W) zuWQ42@hsb4ycnF=>uH|a+6f$6c2J{dB!h=N`)Ah#>%knq2HQ5BazEkq34Z+1sErzb zm4M5P$St*2+@mA|3*9<{hB4LXmNX%q1kq=1#mZMaas?ohdRc-I?eA&V6?P&daErW( z>B=4Z?zw;XP}<({i>q9;3~7XSsd+Ul%o8mT#Cv`66y#frP6N$_xvXFM7<2;An#>Yw z9~V0-hq~cI`PEr^jb*H+i51mD-^#Lv#AeNLsmxa_V*4@g^pN{^3xsYpL@~Y*EYg_) z&khZ!V6R4Jva$}$g#YRH{!31H2HV{pWI3PkFN7ZOtT1m}tDORTr0fi~9pl*mcf;+K zM{gw9PYl+IE^JJXTpMhvZo$IQ)#LAHCi!)6Hg4 z!~SW9;nA!#+hWlA&iF_gvNyB2;*n98lX`TvSa7K~zc{#-kQscheAaz0%VvH7)TJ+k zD~1nh#dr?cvQ!q8lT~5n9_{3VCKTU9`%N;G5TCsUS#r$9=T(CWNKCPGOiYtp-VFrM}*Hr4}GdVW5)2KZjO_ zqqDvjBMzyobbmsF<$6+v%OyFC$O_NZj1;Q~&h&bA#-k2~B+m;Wv5`pTt4^HC{EXcw zxY;x4#8=<`(NIUd^;GX4!zjCi*8Y9fj!T_Bj;qbFYsqS1puta#@H8Is8iEDB%lt=I zI@^Ltt-v5>;Q*hIvO$l4z(txMm_8>priB8e#oF4nH~pE#{q;rH2ThCM#Hea1eV z5#~m@BKdU*iFn=WNA?DUwS?C_y4%rjK<2#m3p@`Qr8DHexeF~lJsL?9juJ?SPje#+ z3m>gSO$z{?EFCpqbi%=n4Z`S&>;li@&@-TW_)zwT!VI%*(+Rp2C-GeG0aB9ZnXl0v z8YM&hMDD$LqG!_ToABgrio2JjCL4l~D+!p1moyk5q>V0JvRjWzAD8V^{8dw!V%0Dr z(Om&5bM>goD)W%mz~J#VJY;|vz^CZBG%_Kld-;Sr6tHNK*<2N~Wtk-`QnHGxME|tlJvVH})L|uJZjjpW5-e~U9-okJZ9YuYQ)8-Ah>0rj!+o}U{ z4g>VN`Q~uVx=hWQBzuK7Nuvw%XF%|-`r_#Bs!g`R{?t?wi-?qb@XP$T@(OCJRGso9 zEj3KQ6Y<_xc8Qd?Pp5anT9ZfzF3EPL;^YiK{;Gff_#;z??8I!?@fncgB|lc0vwXvI zk-lWrW|FdP#HsB#d;8l^Y)*=O-wA^#Ly0S~S+hue^=OD3-LRJ} zZ4``Ig8L<1V-l4ta)eL5)-l)ydkCslfI(DPDk854CH-1PuwM3_-o?(td6UJpurb`a zLYU~+6QTJFKkYyGx_Q(ww07bu#l&|d4~%*P(z*yXDqsE-C0f$Wq7|MNH!e1Na0Ql= zO@H*uR-xd_*sU?HN4y4wktt+Bs(wdq|~gd zxp_fZbT!ozkhTUbM8^U z4i8std(g7^c6zfE|9G||x6a-)YaU7zbia5{ErJ(uU){Hl!>!n>hEUh^sc%R4P*o?q z*f8ni23`j8drU|?));;L{tJRqjR8y;$@<7;mTn&J5q9wdLLgoa!awz&QG6ZjD*ecUKe66tYSxHQr)W_%*m1O5=&P3;-)MxoOQ4=-~rX-u@kCyO| zQ&!$Og<3y$Sp_n2Yx=58oabz_4Wr1sSMRQI-0i_%Y=y$a@>#+BYZO9Lq1^F13q1`K zA@M0J$UgJ+u0uPu2m3?xZI1(znzwSb@*T;rp|o)TOUsRyqm8>Bt0zh z?-S{~;{fJ!S*1>8=9^WGHwJ??$EhR1j2bpo;`vvqRDY}fj!+Ak*6ZuJ>ca;aC`NG< zQ{>9so#8OzE;NJmz^FzH(rAUrPzjr^yB| z_(q!GCETyTZ&>~V42%V1O)ZhxE!%$xNw!x(4eG1x`WFgHH)h`@97O{U$e3 HIGgz&1>0`y diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/80.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/80.png deleted file mode 100644 index 485a1aae7bdc8d36d26d7aa6ecb35580edeb1db4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6923 zcmbtYWmr_vy54k14c(H`NDC4Q3_~Lf4BZ_A0waiofzk~_4IoPA&@qHc!_Xsf2P>+8K@KYQ)#`RmUBjSfT`0^s2R03NOY*Xwxm+Un|dhR_EP zZ9R>D3I+ij5lR4nx6dPgsHPg1xrHSc$>)Ds{FOO4A$FD4Ea>(h z*zrHGldu0@{dk;?k~ciyZ>+!cH)9GHADA(&C&g8E00BS&O+fAM^W(-idRPDe@}~em zko<3+V>SS^L;wKu;=g%(ZvcS$6#z7k|C{&kIq`Mycld`pLR^dQ>IwiSr2s%_0RVIp z06=c_4;ilcFS&8yMC`b{9^#4{00&$EEp zdB9m;e*i$FfFWQ=fCmEbL3jipyz5?o6F1*P0Kwm#_`igQPeMjcKuAhNjFZdJ001!_ z0X_i{2?5bRH1O~V2#JVE08$W{5iNHLy`b27x0ZM~Gcp1~e4JPT1mF?k5#SNw!VvvKhX4;B=N2FV(UQ_}OMav0QB7fBG;=+pTFPTQ#R9lrAYF| zv(5c8uJaf`!|r*@_;S3QkeQXgx&~zJJ|QR9sJgze`dtH0z4lK|W*_0C)B46q_wL=C z{`D`bntPvMQ%q~rHRJj+hcYuvtqB8;`qfSf@S1GV@{gX!vA2c_NDJJ)H!BQ)O^#

g>|+|H`0{D1 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 E0r_4uW&i*H diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/88.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/88.png deleted file mode 100644 index f47fb37b5fcd294e85166493405cf9ea5e4cf520..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7800 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 Aw*UYD diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/Contents.json b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 922e8c6d731..00000000000 --- a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1 +0,0 @@ -{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"idiom":"watch","filename":"172.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"86x86","expected-size":"172","role":"quickLook"},{"idiom":"watch","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"40x40","expected-size":"80","role":"appLauncher"},{"idiom":"watch","filename":"88.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"40mm","scale":"2x","size":"44x44","expected-size":"88","role":"appLauncher"},{"idiom":"watch","filename":"102.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"45mm","scale":"2x","size":"51x51","expected-size":"102","role":"appLauncher"},{"idiom":"watch","filename":"108.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"49mm","scale":"2x","size":"54x54","expected-size":"108","role":"appLauncher"},{"idiom":"watch","filename":"92.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"41mm","scale":"2x","size":"46x46","expected-size":"92","role":"appLauncher"},{"idiom":"watch","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"44mm","scale":"2x","size":"50x50","expected-size":"100","role":"appLauncher"},{"idiom":"watch","filename":"196.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"42mm","scale":"2x","size":"98x98","expected-size":"196","role":"quickLook"},{"idiom":"watch","filename":"216.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"44mm","scale":"2x","size":"108x108","expected-size":"216","role":"quickLook"},{"idiom":"watch","filename":"234.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"45mm","scale":"2x","size":"117x117","expected-size":"234","role":"quickLook"},{"idiom":"watch","filename":"258.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"49mm","scale":"2x","size":"129x129","expected-size":"258","role":"quickLook"},{"idiom":"watch","filename":"48.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"24x24","expected-size":"48","role":"notificationCenter"},{"idiom":"watch","filename":"55.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"42mm","scale":"2x","size":"27.5x27.5","expected-size":"55","role":"notificationCenter"},{"idiom":"watch","filename":"66.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"45mm","scale":"2x","size":"33x33","expected-size":"66","role":"notificationCenter"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch","role":"companionSettings","scale":"3x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch","role":"companionSettings","scale":"2x"},{"size":"1024x1024","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch-marketing","scale":"1x"}]} \ No newline at end of file diff --git a/apps/ios/Sources/Calendar/CalendarService.swift b/apps/ios/Sources/Calendar/CalendarService.swift deleted file mode 100644 index 94b2d9ea3f5..00000000000 --- a/apps/ios/Sources/Calendar/CalendarService.swift +++ /dev/null @@ -1,135 +0,0 @@ -import EventKit -import Foundation -import OpenClawKit - -final class CalendarService: CalendarServicing { - func events(params: OpenClawCalendarEventsParams) async throws -> OpenClawCalendarEventsPayload { - let store = EKEventStore() - let status = EKEventStore.authorizationStatus(for: .event) - let authorized = EventKitAuthorization.allowsRead(status: status) - guard authorized else { - throw NSError(domain: "Calendar", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "CALENDAR_PERMISSION_REQUIRED: grant Calendar permission", - ]) - } - - let (start, end) = Self.resolveRange( - startISO: params.startISO, - endISO: params.endISO) - let predicate = store.predicateForEvents(withStart: start, end: end, calendars: nil) - let events = store.events(matching: predicate) - let limit = max(1, min(params.limit ?? 50, 500)) - let selected = Array(events.prefix(limit)) - - let formatter = ISO8601DateFormatter() - let payload = selected.map { event in - OpenClawCalendarEventPayload( - identifier: event.eventIdentifier ?? UUID().uuidString, - title: event.title ?? "(untitled)", - startISO: formatter.string(from: event.startDate), - endISO: formatter.string(from: event.endDate), - isAllDay: event.isAllDay, - location: event.location, - calendarTitle: event.calendar.title) - } - - return OpenClawCalendarEventsPayload(events: payload) - } - - func add(params: OpenClawCalendarAddParams) async throws -> OpenClawCalendarAddPayload { - let store = EKEventStore() - let status = EKEventStore.authorizationStatus(for: .event) - let authorized = EventKitAuthorization.allowsWrite(status: status) - guard authorized else { - throw NSError(domain: "Calendar", code: 2, userInfo: [ - NSLocalizedDescriptionKey: "CALENDAR_PERMISSION_REQUIRED: grant Calendar permission", - ]) - } - - let title = params.title.trimmingCharacters(in: .whitespacesAndNewlines) - guard !title.isEmpty else { - throw NSError(domain: "Calendar", code: 3, userInfo: [ - NSLocalizedDescriptionKey: "CALENDAR_INVALID: title required", - ]) - } - - let formatter = ISO8601DateFormatter() - guard let start = formatter.date(from: params.startISO) else { - throw NSError(domain: "Calendar", code: 4, userInfo: [ - NSLocalizedDescriptionKey: "CALENDAR_INVALID: startISO required", - ]) - } - guard let end = formatter.date(from: params.endISO) else { - throw NSError(domain: "Calendar", code: 5, userInfo: [ - NSLocalizedDescriptionKey: "CALENDAR_INVALID: endISO required", - ]) - } - - let event = EKEvent(eventStore: store) - event.title = title - event.startDate = start - event.endDate = end - event.isAllDay = params.isAllDay ?? false - if let location = params.location?.trimmingCharacters(in: .whitespacesAndNewlines), !location.isEmpty { - event.location = location - } - if let notes = params.notes?.trimmingCharacters(in: .whitespacesAndNewlines), !notes.isEmpty { - event.notes = notes - } - event.calendar = try Self.resolveCalendar( - store: store, - calendarId: params.calendarId, - calendarTitle: params.calendarTitle) - - try store.save(event, span: .thisEvent) - - let payload = OpenClawCalendarEventPayload( - identifier: event.eventIdentifier ?? UUID().uuidString, - title: event.title ?? title, - startISO: formatter.string(from: event.startDate), - endISO: formatter.string(from: event.endDate), - isAllDay: event.isAllDay, - location: event.location, - calendarTitle: event.calendar.title) - - return OpenClawCalendarAddPayload(event: payload) - } - - private static func resolveCalendar( - store: EKEventStore, - calendarId: String?, - calendarTitle: String?) throws -> EKCalendar - { - if let id = calendarId?.trimmingCharacters(in: .whitespacesAndNewlines), !id.isEmpty, - let calendar = store.calendar(withIdentifier: id) - { - return calendar - } - - if let title = calendarTitle?.trimmingCharacters(in: .whitespacesAndNewlines), !title.isEmpty { - if let calendar = store.calendars(for: .event).first(where: { - $0.title.compare(title, options: [.caseInsensitive, .diacriticInsensitive]) == .orderedSame - }) { - return calendar - } - throw NSError(domain: "Calendar", code: 6, userInfo: [ - NSLocalizedDescriptionKey: "CALENDAR_NOT_FOUND: no calendar named \(title)", - ]) - } - - if let fallback = store.defaultCalendarForNewEvents { - return fallback - } - - throw NSError(domain: "Calendar", code: 7, userInfo: [ - NSLocalizedDescriptionKey: "CALENDAR_NOT_FOUND: no default calendar", - ]) - } - - private static func resolveRange(startISO: String?, endISO: String?) -> (Date, Date) { - let formatter = ISO8601DateFormatter() - let start = startISO.flatMap { formatter.date(from: $0) } ?? Date() - let end = endISO.flatMap { formatter.date(from: $0) } ?? start.addingTimeInterval(7 * 24 * 3600) - return (start, end) - } -} diff --git a/apps/ios/Sources/Camera/CameraController.swift b/apps/ios/Sources/Camera/CameraController.swift deleted file mode 100644 index 1e9c10bc44c..00000000000 --- a/apps/ios/Sources/Camera/CameraController.swift +++ /dev/null @@ -1,402 +0,0 @@ -import AVFoundation -import OpenClawKit -import Foundation - -actor CameraController { - struct CameraDeviceInfo: Codable, Sendable { - var id: String - var name: String - var position: String - var deviceType: String - } - - enum CameraError: LocalizedError, Sendable { - case cameraUnavailable - case microphoneUnavailable - case permissionDenied(kind: String) - case invalidParams(String) - case captureFailed(String) - case exportFailed(String) - - var errorDescription: String? { - switch self { - case .cameraUnavailable: - "Camera unavailable" - case .microphoneUnavailable: - "Microphone unavailable" - case let .permissionDenied(kind): - "\(kind) permission denied" - case let .invalidParams(msg): - msg - case let .captureFailed(msg): - msg - case let .exportFailed(msg): - msg - } - } - } - - func snap(params: OpenClawCameraSnapParams) async throws -> ( - format: String, - base64: String, - width: Int, - height: Int) - { - let facing = params.facing ?? .front - let format = params.format ?? .jpg - // Default to a reasonable max width to keep gateway payload sizes manageable. - // If you need the full-res photo, explicitly request a larger maxWidth. - let maxWidth = params.maxWidth.flatMap { $0 > 0 ? $0 : nil } ?? 1600 - let quality = Self.clampQuality(params.quality) - let delayMs = max(0, params.delayMs ?? 0) - - try await self.ensureAccess(for: .video) - - let session = AVCaptureSession() - session.sessionPreset = .photo - - guard let device = Self.pickCamera(facing: facing, deviceId: params.deviceId) else { - throw CameraError.cameraUnavailable - } - - let input = try AVCaptureDeviceInput(device: device) - guard session.canAddInput(input) else { - throw CameraError.captureFailed("Failed to add camera input") - } - session.addInput(input) - - let output = AVCapturePhotoOutput() - guard session.canAddOutput(output) else { - throw CameraError.captureFailed("Failed to add photo output") - } - session.addOutput(output) - output.maxPhotoQualityPrioritization = .quality - - session.startRunning() - defer { session.stopRunning() } - await Self.warmUpCaptureSession() - await Self.sleepDelayMs(delayMs) - - let settings: AVCapturePhotoSettings = { - if output.availablePhotoCodecTypes.contains(.jpeg) { - return AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg]) - } - return AVCapturePhotoSettings() - }() - settings.photoQualityPrioritization = .quality - - var delegate: PhotoCaptureDelegate? - let rawData: Data = try await withCheckedThrowingContinuation { cont in - let d = PhotoCaptureDelegate(cont) - delegate = d - output.capturePhoto(with: settings, delegate: d) - } - withExtendedLifetime(delegate) {} - - let res = try PhotoCapture.transcodeJPEGForGateway( - rawData: rawData, - maxWidthPx: maxWidth, - quality: quality) - - return ( - format: format.rawValue, - base64: res.data.base64EncodedString(), - width: res.widthPx, - height: res.heightPx) - } - - func clip(params: OpenClawCameraClipParams) async throws -> ( - format: String, - base64: String, - durationMs: Int, - hasAudio: Bool) - { - let facing = params.facing ?? .front - let durationMs = Self.clampDurationMs(params.durationMs) - let includeAudio = params.includeAudio ?? true - let format = params.format ?? .mp4 - - try await self.ensureAccess(for: .video) - if includeAudio { - try await self.ensureAccess(for: .audio) - } - - let session = AVCaptureSession() - session.sessionPreset = .high - - guard let camera = Self.pickCamera(facing: facing, deviceId: params.deviceId) else { - throw CameraError.cameraUnavailable - } - let cameraInput = try AVCaptureDeviceInput(device: camera) - guard session.canAddInput(cameraInput) else { - throw CameraError.captureFailed("Failed to add camera input") - } - session.addInput(cameraInput) - - if includeAudio { - guard let mic = AVCaptureDevice.default(for: .audio) else { - throw CameraError.microphoneUnavailable - } - let micInput = try AVCaptureDeviceInput(device: mic) - if session.canAddInput(micInput) { - session.addInput(micInput) - } else { - throw CameraError.captureFailed("Failed to add microphone input") - } - } - - let output = AVCaptureMovieFileOutput() - guard session.canAddOutput(output) else { - throw CameraError.captureFailed("Failed to add movie output") - } - session.addOutput(output) - output.maxRecordedDuration = CMTime(value: Int64(durationMs), timescale: 1000) - - session.startRunning() - defer { session.stopRunning() } - await Self.warmUpCaptureSession() - - let movURL = FileManager().temporaryDirectory - .appendingPathComponent("openclaw-camera-\(UUID().uuidString).mov") - let mp4URL = FileManager().temporaryDirectory - .appendingPathComponent("openclaw-camera-\(UUID().uuidString).mp4") - - defer { - try? FileManager().removeItem(at: movURL) - try? FileManager().removeItem(at: mp4URL) - } - - var delegate: MovieFileDelegate? - let recordedURL: URL = try await withCheckedThrowingContinuation { cont in - let d = MovieFileDelegate(cont) - delegate = d - output.startRecording(to: movURL, recordingDelegate: d) - } - withExtendedLifetime(delegate) {} - - // Transcode .mov -> .mp4 for easier downstream handling. - try await Self.exportToMP4(inputURL: recordedURL, outputURL: mp4URL) - - let data = try Data(contentsOf: mp4URL) - return ( - format: format.rawValue, - base64: data.base64EncodedString(), - durationMs: durationMs, - hasAudio: includeAudio) - } - - func listDevices() -> [CameraDeviceInfo] { - return Self.discoverVideoDevices().map { device in - CameraDeviceInfo( - id: device.uniqueID, - name: device.localizedName, - position: Self.positionLabel(device.position), - deviceType: device.deviceType.rawValue) - } - } - - private func ensureAccess(for mediaType: AVMediaType) async throws { - let status = AVCaptureDevice.authorizationStatus(for: mediaType) - switch status { - case .authorized: - return - case .notDetermined: - let ok = await withCheckedContinuation(isolation: nil) { cont in - AVCaptureDevice.requestAccess(for: mediaType) { granted in - cont.resume(returning: granted) - } - } - if !ok { - throw CameraError.permissionDenied(kind: mediaType == .video ? "Camera" : "Microphone") - } - case .denied, .restricted: - throw CameraError.permissionDenied(kind: mediaType == .video ? "Camera" : "Microphone") - @unknown default: - throw CameraError.permissionDenied(kind: mediaType == .video ? "Camera" : "Microphone") - } - } - - private nonisolated static func pickCamera( - facing: OpenClawCameraFacing, - deviceId: String?) -> AVCaptureDevice? - { - if let deviceId, !deviceId.isEmpty { - if let match = Self.discoverVideoDevices().first(where: { $0.uniqueID == deviceId }) { - return match - } - } - let position: AVCaptureDevice.Position = (facing == .front) ? .front : .back - if let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: position) { - return device - } - // Fall back to any default camera (e.g. simulator / unusual device configurations). - return AVCaptureDevice.default(for: .video) - } - - private nonisolated static func positionLabel(_ position: AVCaptureDevice.Position) -> String { - switch position { - case .front: "front" - case .back: "back" - default: "unspecified" - } - } - - private nonisolated static func discoverVideoDevices() -> [AVCaptureDevice] { - let types: [AVCaptureDevice.DeviceType] = [ - .builtInWideAngleCamera, - .builtInUltraWideCamera, - .builtInTelephotoCamera, - .builtInDualCamera, - .builtInDualWideCamera, - .builtInTripleCamera, - .builtInTrueDepthCamera, - .builtInLiDARDepthCamera, - ] - let session = AVCaptureDevice.DiscoverySession( - deviceTypes: types, - mediaType: .video, - position: .unspecified) - return session.devices - } - - nonisolated static func clampQuality(_ quality: Double?) -> Double { - let q = quality ?? 0.9 - return min(1.0, max(0.05, q)) - } - - nonisolated static func clampDurationMs(_ ms: Int?) -> Int { - let v = ms ?? 3000 - // Keep clips short by default; avoid huge base64 payloads on the gateway. - return min(60000, max(250, v)) - } - - private nonisolated static func exportToMP4(inputURL: URL, outputURL: URL) async throws { - let asset = AVURLAsset(url: inputURL) - guard let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetMediumQuality) else { - throw CameraError.exportFailed("Failed to create export session") - } - exporter.shouldOptimizeForNetworkUse = true - - if #available(iOS 18.0, tvOS 18.0, visionOS 2.0, *) { - do { - try await exporter.export(to: outputURL, as: .mp4) - return - } catch { - throw CameraError.exportFailed(error.localizedDescription) - } - } else { - exporter.outputURL = outputURL - exporter.outputFileType = .mp4 - - try await withCheckedThrowingContinuation(isolation: nil) { (cont: CheckedContinuation) in - exporter.exportAsynchronously { - cont.resume(returning: ()) - } - } - - switch exporter.status { - case .completed: - return - case .failed: - throw CameraError.exportFailed(exporter.error?.localizedDescription ?? "export failed") - case .cancelled: - throw CameraError.exportFailed("export cancelled") - default: - throw CameraError.exportFailed("export did not complete") - } - } - } - - private nonisolated static func warmUpCaptureSession() async { - // A short delay after `startRunning()` significantly reduces "blank first frame" captures on some devices. - try? await Task.sleep(nanoseconds: 150_000_000) // 150ms - } - - private nonisolated static func sleepDelayMs(_ delayMs: Int) async { - guard delayMs > 0 else { return } - let maxDelayMs = 10 * 1000 - let ns = UInt64(min(delayMs, maxDelayMs)) * UInt64(NSEC_PER_MSEC) - try? await Task.sleep(nanoseconds: ns) - } -} - -private final class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate { - private let continuation: CheckedContinuation - private var didResume = false - - init(_ continuation: CheckedContinuation) { - self.continuation = continuation - } - - func photoOutput( - _ output: AVCapturePhotoOutput, - didFinishProcessingPhoto photo: AVCapturePhoto, - error: Error? - ) { - guard !self.didResume else { return } - self.didResume = true - - if let error { - self.continuation.resume(throwing: error) - return - } - guard let data = photo.fileDataRepresentation() else { - self.continuation.resume( - throwing: NSError(domain: "Camera", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "photo data missing", - ])) - return - } - if data.isEmpty { - self.continuation.resume( - throwing: NSError(domain: "Camera", code: 2, userInfo: [ - NSLocalizedDescriptionKey: "photo data empty", - ])) - return - } - self.continuation.resume(returning: data) - } - - func photoOutput( - _ output: AVCapturePhotoOutput, - didFinishCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings, - error: Error? - ) { - guard let error else { return } - guard !self.didResume else { return } - self.didResume = true - self.continuation.resume(throwing: error) - } -} - -private final class MovieFileDelegate: NSObject, AVCaptureFileOutputRecordingDelegate { - private let continuation: CheckedContinuation - private var didResume = false - - init(_ continuation: CheckedContinuation) { - self.continuation = continuation - } - - func fileOutput( - _ output: AVCaptureFileOutput, - didFinishRecordingTo outputFileURL: URL, - from connections: [AVCaptureConnection], - error: Error?) - { - guard !self.didResume else { return } - self.didResume = true - - if let error { - let ns = error as NSError - if ns.domain == AVFoundationErrorDomain, - ns.code == AVError.maximumDurationReached.rawValue - { - self.continuation.resume(returning: outputFileURL) - return - } - self.continuation.resume(throwing: error) - return - } - self.continuation.resume(returning: outputFileURL) - } -} diff --git a/apps/ios/Sources/Capabilities/NodeCapabilityRouter.swift b/apps/ios/Sources/Capabilities/NodeCapabilityRouter.swift deleted file mode 100644 index 6dbdd51eb8e..00000000000 --- a/apps/ios/Sources/Capabilities/NodeCapabilityRouter.swift +++ /dev/null @@ -1,25 +0,0 @@ -import Foundation -import OpenClawKit - -@MainActor -final class NodeCapabilityRouter { - enum RouterError: Error { - case unknownCommand - case handlerUnavailable - } - - typealias Handler = (BridgeInvokeRequest) async throws -> BridgeInvokeResponse - - private let handlers: [String: Handler] - - init(handlers: [String: Handler]) { - self.handlers = handlers - } - - func handle(_ request: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - guard let handler = handlers[request.command] else { - throw RouterError.unknownCommand - } - return try await handler(request) - } -} diff --git a/apps/ios/Sources/Chat/ChatSheet.swift b/apps/ios/Sources/Chat/ChatSheet.swift deleted file mode 100644 index bbed501cf70..00000000000 --- a/apps/ios/Sources/Chat/ChatSheet.swift +++ /dev/null @@ -1,47 +0,0 @@ -import OpenClawChatUI -import OpenClawKit -import SwiftUI - -struct ChatSheet: View { - @Environment(\.dismiss) private var dismiss - @State private var viewModel: OpenClawChatViewModel - private let userAccent: Color? - private let agentName: String? - - init(gateway: GatewayNodeSession, sessionKey: String, agentName: String? = nil, userAccent: Color? = nil) { - let transport = IOSGatewayChatTransport(gateway: gateway) - self._viewModel = State( - initialValue: OpenClawChatViewModel( - sessionKey: sessionKey, - transport: transport)) - self.userAccent = userAccent - self.agentName = agentName - } - - var body: some View { - NavigationStack { - OpenClawChatView( - viewModel: self.viewModel, - showsSessionSwitcher: true, - userAccent: self.userAccent) - .navigationTitle(self.chatTitle) - .navigationBarTitleDisplayMode(.inline) - .toolbar { - ToolbarItem(placement: .topBarTrailing) { - Button { - self.dismiss() - } label: { - Image(systemName: "xmark") - } - .accessibilityLabel("Close") - } - } - } - } - - private var chatTitle: String { - let trimmed = (self.agentName ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty { return "Chat" } - return "Chat (\(trimmed))" - } -} diff --git a/apps/ios/Sources/Chat/IOSGatewayChatTransport.swift b/apps/ios/Sources/Chat/IOSGatewayChatTransport.swift deleted file mode 100644 index 9571839059d..00000000000 --- a/apps/ios/Sources/Chat/IOSGatewayChatTransport.swift +++ /dev/null @@ -1,137 +0,0 @@ -import OpenClawChatUI -import OpenClawKit -import OpenClawProtocol -import Foundation -import OSLog - -struct IOSGatewayChatTransport: OpenClawChatTransport, Sendable { - private static let logger = Logger(subsystem: "ai.openclaw", category: "ios.chat.transport") - private let gateway: GatewayNodeSession - - init(gateway: GatewayNodeSession) { - self.gateway = gateway - } - - func abortRun(sessionKey: String, runId: String) async throws { - struct Params: Codable { - var sessionKey: String - var runId: String - } - let data = try JSONEncoder().encode(Params(sessionKey: sessionKey, runId: runId)) - let json = String(data: data, encoding: .utf8) - _ = try await self.gateway.request(method: "chat.abort", paramsJSON: json, timeoutSeconds: 10) - } - - func listSessions(limit: Int?) async throws -> OpenClawChatSessionsListResponse { - struct Params: Codable { - var includeGlobal: Bool - var includeUnknown: Bool - var limit: Int? - } - let data = try JSONEncoder().encode(Params(includeGlobal: true, includeUnknown: false, limit: limit)) - let json = String(data: data, encoding: .utf8) - let res = try await self.gateway.request(method: "sessions.list", paramsJSON: json, timeoutSeconds: 15) - return try JSONDecoder().decode(OpenClawChatSessionsListResponse.self, from: res) - } - - func setActiveSessionKey(_ sessionKey: String) async throws { - // Operator clients receive chat events without node-style subscriptions. - // (chat.subscribe is a node event, not an operator RPC method.) - } - - func requestHistory(sessionKey: String) async throws -> OpenClawChatHistoryPayload { - struct Params: Codable { var sessionKey: String } - let data = try JSONEncoder().encode(Params(sessionKey: sessionKey)) - let json = String(data: data, encoding: .utf8) - let res = try await self.gateway.request(method: "chat.history", paramsJSON: json, timeoutSeconds: 15) - return try JSONDecoder().decode(OpenClawChatHistoryPayload.self, from: res) - } - - func sendMessage( - sessionKey: String, - message: String, - thinking: String, - idempotencyKey: String, - attachments: [OpenClawChatAttachmentPayload]) async throws -> OpenClawChatSendResponse - { - Self.logger.info("chat.send start sessionKey=\(sessionKey, privacy: .public) len=\(message.count, privacy: .public) attachments=\(attachments.count, privacy: .public)") - struct Params: Codable { - var sessionKey: String - var message: String - var thinking: String - var attachments: [OpenClawChatAttachmentPayload]? - var timeoutMs: Int - var idempotencyKey: String - } - - let params = Params( - sessionKey: sessionKey, - message: message, - thinking: thinking, - attachments: attachments.isEmpty ? nil : attachments, - timeoutMs: 30000, - idempotencyKey: idempotencyKey) - let data = try JSONEncoder().encode(params) - let json = String(data: data, encoding: .utf8) - do { - let res = try await self.gateway.request(method: "chat.send", paramsJSON: json, timeoutSeconds: 35) - let decoded = try JSONDecoder().decode(OpenClawChatSendResponse.self, from: res) - Self.logger.info("chat.send ok runId=\(decoded.runId, privacy: .public)") - return decoded - } catch { - Self.logger.error("chat.send failed \(error.localizedDescription, privacy: .public)") - throw error - } - } - - func requestHealth(timeoutMs: Int) async throws -> Bool { - let seconds = max(1, Int(ceil(Double(timeoutMs) / 1000.0))) - let res = try await self.gateway.request(method: "health", paramsJSON: nil, timeoutSeconds: seconds) - return (try? JSONDecoder().decode(OpenClawGatewayHealthOK.self, from: res))?.ok ?? true - } - - func events() -> AsyncStream { - AsyncStream { continuation in - let task = Task { - let stream = await self.gateway.subscribeServerEvents() - for await evt in stream { - if Task.isCancelled { return } - switch evt.event { - case "tick": - continuation.yield(.tick) - case "seqGap": - continuation.yield(.seqGap) - case "health": - guard let payload = evt.payload else { break } - let ok = (try? GatewayPayloadDecoding.decode( - payload, - as: OpenClawGatewayHealthOK.self))?.ok ?? true - continuation.yield(.health(ok: ok)) - case "chat": - guard let payload = evt.payload else { break } - if let chatPayload = try? GatewayPayloadDecoding.decode( - payload, - as: OpenClawChatEventPayload.self) - { - continuation.yield(.chat(chatPayload)) - } - case "agent": - guard let payload = evt.payload else { break } - if let agentPayload = try? GatewayPayloadDecoding.decode( - payload, - as: OpenClawAgentEventPayload.self) - { - continuation.yield(.agent(agentPayload)) - } - default: - break - } - } - } - - continuation.onTermination = { @Sendable _ in - task.cancel() - } - } - } -} diff --git a/apps/ios/Sources/Contacts/ContactsService.swift b/apps/ios/Sources/Contacts/ContactsService.swift deleted file mode 100644 index db203d070f1..00000000000 --- a/apps/ios/Sources/Contacts/ContactsService.swift +++ /dev/null @@ -1,212 +0,0 @@ -import Contacts -import Foundation -import OpenClawKit - -final class ContactsService: ContactsServicing { - private static var payloadKeys: [CNKeyDescriptor] { - [ - CNContactIdentifierKey as CNKeyDescriptor, - CNContactGivenNameKey as CNKeyDescriptor, - CNContactFamilyNameKey as CNKeyDescriptor, - CNContactOrganizationNameKey as CNKeyDescriptor, - CNContactPhoneNumbersKey as CNKeyDescriptor, - CNContactEmailAddressesKey as CNKeyDescriptor, - ] - } - - func search(params: OpenClawContactsSearchParams) async throws -> OpenClawContactsSearchPayload { - let store = CNContactStore() - let status = CNContactStore.authorizationStatus(for: .contacts) - let authorized = await Self.ensureAuthorization(store: store, status: status) - guard authorized else { - throw NSError(domain: "Contacts", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "CONTACTS_PERMISSION_REQUIRED: grant Contacts permission", - ]) - } - - let limit = max(1, min(params.limit ?? 25, 200)) - - var contacts: [CNContact] = [] - if let query = params.query?.trimmingCharacters(in: .whitespacesAndNewlines), !query.isEmpty { - let predicate = CNContact.predicateForContacts(matchingName: query) - contacts = try store.unifiedContacts(matching: predicate, keysToFetch: Self.payloadKeys) - } else { - let request = CNContactFetchRequest(keysToFetch: Self.payloadKeys) - try store.enumerateContacts(with: request) { contact, stop in - contacts.append(contact) - if contacts.count >= limit { - stop.pointee = true - } - } - } - - let sliced = Array(contacts.prefix(limit)) - let payload = sliced.map { Self.payload(from: $0) } - - return OpenClawContactsSearchPayload(contacts: payload) - } - - func add(params: OpenClawContactsAddParams) async throws -> OpenClawContactsAddPayload { - let store = CNContactStore() - let status = CNContactStore.authorizationStatus(for: .contacts) - let authorized = await Self.ensureAuthorization(store: store, status: status) - guard authorized else { - throw NSError(domain: "Contacts", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "CONTACTS_PERMISSION_REQUIRED: grant Contacts permission", - ]) - } - - let givenName = params.givenName?.trimmingCharacters(in: .whitespacesAndNewlines) - let familyName = params.familyName?.trimmingCharacters(in: .whitespacesAndNewlines) - let organizationName = params.organizationName?.trimmingCharacters(in: .whitespacesAndNewlines) - let displayName = params.displayName?.trimmingCharacters(in: .whitespacesAndNewlines) - let phoneNumbers = Self.normalizeStrings(params.phoneNumbers) - let emails = Self.normalizeStrings(params.emails, lowercased: true) - - let hasName = !(givenName ?? "").isEmpty || !(familyName ?? "").isEmpty || !(displayName ?? "").isEmpty - let hasOrg = !(organizationName ?? "").isEmpty - let hasDetails = !phoneNumbers.isEmpty || !emails.isEmpty - guard hasName || hasOrg || hasDetails else { - throw NSError(domain: "Contacts", code: 2, userInfo: [ - NSLocalizedDescriptionKey: "CONTACTS_INVALID: include a name, organization, phone, or email", - ]) - } - - if !phoneNumbers.isEmpty || !emails.isEmpty { - if let existing = try Self.findExistingContact( - store: store, - phoneNumbers: phoneNumbers, - emails: emails) - { - return OpenClawContactsAddPayload(contact: Self.payload(from: existing)) - } - } - - let contact = CNMutableContact() - contact.givenName = givenName ?? "" - contact.familyName = familyName ?? "" - contact.organizationName = organizationName ?? "" - if contact.givenName.isEmpty && contact.familyName.isEmpty, let displayName { - contact.givenName = displayName - } - contact.phoneNumbers = phoneNumbers.map { - CNLabeledValue(label: CNLabelPhoneNumberMobile, value: CNPhoneNumber(stringValue: $0)) - } - contact.emailAddresses = emails.map { - CNLabeledValue(label: CNLabelHome, value: $0 as NSString) - } - - let save = CNSaveRequest() - save.add(contact, toContainerWithIdentifier: nil) - try store.execute(save) - - let persisted: CNContact - if !contact.identifier.isEmpty { - persisted = try store.unifiedContact( - withIdentifier: contact.identifier, - keysToFetch: Self.payloadKeys) - } else { - persisted = contact - } - - return OpenClawContactsAddPayload(contact: Self.payload(from: persisted)) - } - - private static func ensureAuthorization(store: CNContactStore, status: CNAuthorizationStatus) async -> Bool { - switch status { - case .authorized, .limited: - return true - case .notDetermined: - // Don’t prompt during node.invoke; the caller should instruct the user to grant permission. - // Prompts block the invoke and lead to timeouts in headless flows. - return false - case .restricted, .denied: - return false - @unknown default: - return false - } - } - - private static func normalizeStrings(_ values: [String]?, lowercased: Bool = false) -> [String] { - (values ?? []) - .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } - .filter { !$0.isEmpty } - .map { lowercased ? $0.lowercased() : $0 } - } - - private static func findExistingContact( - store: CNContactStore, - phoneNumbers: [String], - emails: [String]) throws -> CNContact? - { - if phoneNumbers.isEmpty && emails.isEmpty { - return nil - } - - var matches: [CNContact] = [] - - for phone in phoneNumbers { - let predicate = CNContact.predicateForContacts(matching: CNPhoneNumber(stringValue: phone)) - let contacts = try store.unifiedContacts(matching: predicate, keysToFetch: Self.payloadKeys) - matches.append(contentsOf: contacts) - } - - for email in emails { - let predicate = CNContact.predicateForContacts(matchingEmailAddress: email) - let contacts = try store.unifiedContacts(matching: predicate, keysToFetch: Self.payloadKeys) - matches.append(contentsOf: contacts) - } - - return Self.matchContacts(contacts: matches, phoneNumbers: phoneNumbers, emails: emails) - } - - private static func matchContacts( - contacts: [CNContact], - phoneNumbers: [String], - emails: [String]) -> CNContact? - { - let normalizedPhones = Set(phoneNumbers.map { normalizePhone($0) }.filter { !$0.isEmpty }) - let normalizedEmails = Set(emails.map { $0.lowercased() }.filter { !$0.isEmpty }) - var seen = Set() - - for contact in contacts { - guard seen.insert(contact.identifier).inserted else { continue } - let contactPhones = Set(contact.phoneNumbers.map { normalizePhone($0.value.stringValue) }) - let contactEmails = Set(contact.emailAddresses.map { String($0.value).lowercased() }) - - if !normalizedPhones.isEmpty, !contactPhones.isDisjoint(with: normalizedPhones) { - return contact - } - if !normalizedEmails.isEmpty, !contactEmails.isDisjoint(with: normalizedEmails) { - return contact - } - } - - return nil - } - - private static func normalizePhone(_ phone: String) -> String { - let trimmed = phone.trimmingCharacters(in: .whitespacesAndNewlines) - let digits = trimmed.unicodeScalars.filter { CharacterSet.decimalDigits.contains($0) } - let normalized = String(String.UnicodeScalarView(digits)) - return normalized.isEmpty ? trimmed : normalized - } - - private static func payload(from contact: CNContact) -> OpenClawContactPayload { - OpenClawContactPayload( - identifier: contact.identifier, - displayName: CNContactFormatter.string(from: contact, style: .fullName) - ?? "\(contact.givenName) \(contact.familyName)".trimmingCharacters(in: .whitespacesAndNewlines), - givenName: contact.givenName, - familyName: contact.familyName, - organizationName: contact.organizationName, - phoneNumbers: contact.phoneNumbers.map { $0.value.stringValue }, - emails: contact.emailAddresses.map { String($0.value) }) - } - -#if DEBUG - static func _test_matches(contact: CNContact, phoneNumbers: [String], emails: [String]) -> Bool { - matchContacts(contacts: [contact], phoneNumbers: phoneNumbers, emails: emails) != nil - } -#endif -} diff --git a/apps/ios/Sources/Device/DeviceStatusService.swift b/apps/ios/Sources/Device/DeviceStatusService.swift deleted file mode 100644 index fed2716b5b8..00000000000 --- a/apps/ios/Sources/Device/DeviceStatusService.swift +++ /dev/null @@ -1,87 +0,0 @@ -import Foundation -import OpenClawKit -import UIKit - -final class DeviceStatusService: DeviceStatusServicing { - private let networkStatus: NetworkStatusService - - init(networkStatus: NetworkStatusService = NetworkStatusService()) { - self.networkStatus = networkStatus - } - - func status() async throws -> OpenClawDeviceStatusPayload { - let battery = self.batteryStatus() - let thermal = self.thermalStatus() - let storage = self.storageStatus() - let network = await self.networkStatus.currentStatus() - let uptime = ProcessInfo.processInfo.systemUptime - - return OpenClawDeviceStatusPayload( - battery: battery, - thermal: thermal, - storage: storage, - network: network, - uptimeSeconds: uptime) - } - - func info() -> OpenClawDeviceInfoPayload { - let device = UIDevice.current - let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "dev" - let appBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "0" - let locale = Locale.preferredLanguages.first ?? Locale.current.identifier - return OpenClawDeviceInfoPayload( - deviceName: device.name, - modelIdentifier: Self.modelIdentifier(), - systemName: device.systemName, - systemVersion: device.systemVersion, - appVersion: appVersion, - appBuild: appBuild, - locale: locale) - } - - private func batteryStatus() -> OpenClawBatteryStatusPayload { - let device = UIDevice.current - device.isBatteryMonitoringEnabled = true - let level = device.batteryLevel >= 0 ? Double(device.batteryLevel) : nil - let state: OpenClawBatteryState = switch device.batteryState { - case .charging: .charging - case .full: .full - case .unplugged: .unplugged - case .unknown: .unknown - @unknown default: .unknown - } - return OpenClawBatteryStatusPayload( - level: level, - state: state, - lowPowerModeEnabled: ProcessInfo.processInfo.isLowPowerModeEnabled) - } - - private func thermalStatus() -> OpenClawThermalStatusPayload { - let state: OpenClawThermalState = switch ProcessInfo.processInfo.thermalState { - case .nominal: .nominal - case .fair: .fair - case .serious: .serious - case .critical: .critical - @unknown default: .nominal - } - return OpenClawThermalStatusPayload(state: state) - } - - private func storageStatus() -> OpenClawStorageStatusPayload { - let attrs = (try? FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory())) ?? [:] - let total = (attrs[.systemSize] as? NSNumber)?.int64Value ?? 0 - let free = (attrs[.systemFreeSize] as? NSNumber)?.int64Value ?? 0 - let used = max(0, total - free) - return OpenClawStorageStatusPayload(totalBytes: total, freeBytes: free, usedBytes: used) - } - - private static func modelIdentifier() -> String { - var systemInfo = utsname() - uname(&systemInfo) - let machine = withUnsafeBytes(of: &systemInfo.machine) { ptr in - String(bytes: ptr.prefix { $0 != 0 }, encoding: .utf8) - } - let trimmed = machine?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - return trimmed.isEmpty ? "unknown" : trimmed - } -} diff --git a/apps/ios/Sources/Device/NetworkStatusService.swift b/apps/ios/Sources/Device/NetworkStatusService.swift deleted file mode 100644 index 7d92d1cc1ca..00000000000 --- a/apps/ios/Sources/Device/NetworkStatusService.swift +++ /dev/null @@ -1,69 +0,0 @@ -import Foundation -import Network -import OpenClawKit - -final class NetworkStatusService: @unchecked Sendable { - func currentStatus(timeoutMs: Int = 1500) async -> OpenClawNetworkStatusPayload { - await withCheckedContinuation { cont in - let monitor = NWPathMonitor() - let queue = DispatchQueue(label: "bot.molt.ios.network-status") - let state = NetworkStatusState() - - monitor.pathUpdateHandler = { path in - guard state.markCompleted() else { return } - monitor.cancel() - cont.resume(returning: Self.payload(from: path)) - } - - monitor.start(queue: queue) - - queue.asyncAfter(deadline: .now() + .milliseconds(timeoutMs)) { - guard state.markCompleted() else { return } - monitor.cancel() - cont.resume(returning: Self.fallbackPayload()) - } - } - } - - private static func payload(from path: NWPath) -> OpenClawNetworkStatusPayload { - let status: OpenClawNetworkPathStatus = switch path.status { - case .satisfied: .satisfied - case .requiresConnection: .requiresConnection - case .unsatisfied: .unsatisfied - @unknown default: .unsatisfied - } - - var interfaces: [OpenClawNetworkInterfaceType] = [] - if path.usesInterfaceType(.wifi) { interfaces.append(.wifi) } - if path.usesInterfaceType(.cellular) { interfaces.append(.cellular) } - if path.usesInterfaceType(.wiredEthernet) { interfaces.append(.wired) } - if interfaces.isEmpty { interfaces.append(.other) } - - return OpenClawNetworkStatusPayload( - status: status, - isExpensive: path.isExpensive, - isConstrained: path.isConstrained, - interfaces: interfaces) - } - - private static func fallbackPayload() -> OpenClawNetworkStatusPayload { - OpenClawNetworkStatusPayload( - status: .unsatisfied, - isExpensive: false, - isConstrained: false, - interfaces: [.other]) - } -} - -private final class NetworkStatusState: @unchecked Sendable { - private let lock = NSLock() - private var completed = false - - func markCompleted() -> Bool { - self.lock.lock() - defer { self.lock.unlock() } - if self.completed { return false } - self.completed = true - return true - } -} diff --git a/apps/ios/Sources/Device/NodeDisplayName.swift b/apps/ios/Sources/Device/NodeDisplayName.swift deleted file mode 100644 index 9ddf38b24a7..00000000000 --- a/apps/ios/Sources/Device/NodeDisplayName.swift +++ /dev/null @@ -1,48 +0,0 @@ -import Foundation -import UIKit - -enum NodeDisplayName { - private static let genericNames: Set = ["iOS Node", "iPhone Node", "iPad Node"] - - static func isGeneric(_ name: String) -> Bool { - Self.genericNames.contains(name) - } - - static func defaultValue(for interfaceIdiom: UIUserInterfaceIdiom) -> String { - switch interfaceIdiom { - case .phone: - return "iPhone Node" - case .pad: - return "iPad Node" - default: - return "iOS Node" - } - } - - static func resolve( - existing: String?, - deviceName: String, - interfaceIdiom: UIUserInterfaceIdiom - ) -> String { - let trimmedExisting = existing?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if !trimmedExisting.isEmpty, !Self.isGeneric(trimmedExisting) { - return trimmedExisting - } - - let trimmedDevice = deviceName.trimmingCharacters(in: .whitespacesAndNewlines) - if let normalized = Self.normalizedDeviceName(trimmedDevice) { - return normalized - } - - return Self.defaultValue(for: interfaceIdiom) - } - - private static func normalizedDeviceName(_ deviceName: String) -> String? { - guard !deviceName.isEmpty else { return nil } - let lower = deviceName.lowercased() - if lower.contains("iphone") || lower.contains("ipad") || lower.contains("ios") { - return deviceName - } - return nil - } -} diff --git a/apps/ios/Sources/EventKit/EventKitAuthorization.swift b/apps/ios/Sources/EventKit/EventKitAuthorization.swift deleted file mode 100644 index c27e9a3efde..00000000000 --- a/apps/ios/Sources/EventKit/EventKitAuthorization.swift +++ /dev/null @@ -1,34 +0,0 @@ -import EventKit - -enum EventKitAuthorization { - static func allowsRead(status: EKAuthorizationStatus) -> Bool { - switch status { - case .authorized, .fullAccess: - return true - case .writeOnly: - return false - case .notDetermined: - // Don’t prompt during node.invoke; prompts block the invoke and lead to timeouts. - return false - case .restricted, .denied: - return false - @unknown default: - return false - } - } - - static func allowsWrite(status: EKAuthorizationStatus) -> Bool { - switch status { - case .authorized, .fullAccess, .writeOnly: - return true - case .notDetermined: - // Don’t prompt during node.invoke; prompts block the invoke and lead to timeouts. - return false - case .restricted, .denied: - return false - @unknown default: - return false - } - } -} - diff --git a/apps/ios/Sources/Gateway/GatewayConnectConfig.swift b/apps/ios/Sources/Gateway/GatewayConnectConfig.swift deleted file mode 100644 index 7f4e93380b0..00000000000 --- a/apps/ios/Sources/Gateway/GatewayConnectConfig.swift +++ /dev/null @@ -1,27 +0,0 @@ -import Foundation -import OpenClawKit - -/// Single source of truth for "how we connect" to the current gateway. -/// -/// The iOS app maintains two WebSocket sessions to the same gateway: -/// - a `role=node` session for device capabilities (`node.invoke.*`) -/// - a `role=operator` session for chat/talk/config (`chat.*`, `talk.*`, etc.) -/// -/// Both sessions should derive all connection inputs from this config so we -/// don't accidentally persist gateway-scoped state under different keys. -struct GatewayConnectConfig: Sendable { - let url: URL - let stableID: String - let tls: GatewayTLSParams? - let token: String? - let password: String? - let nodeOptions: GatewayConnectOptions - - /// Stable, non-empty identifier used for gateway-scoped persistence keys. - /// If the caller doesn't provide a stableID, fall back to URL identity. - var effectiveStableID: String { - let trimmed = self.stableID.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty { return self.url.absoluteString } - return trimmed - } -} diff --git a/apps/ios/Sources/Gateway/GatewayConnectionController.swift b/apps/ios/Sources/Gateway/GatewayConnectionController.swift deleted file mode 100644 index 2b7f94ba453..00000000000 --- a/apps/ios/Sources/Gateway/GatewayConnectionController.swift +++ /dev/null @@ -1,1093 +0,0 @@ -import AVFoundation -import Contacts -import CoreLocation -import CoreMotion -import CryptoKit -import EventKit -import Foundation -import Darwin -import OpenClawKit -import Network -import Observation -import Photos -import ReplayKit -import Security -import Speech -import SwiftUI -import UIKit - -@MainActor -@Observable -final class GatewayConnectionController { - struct TrustPrompt: Identifiable, Equatable { - let stableID: String - let gatewayName: String - let host: String - let port: Int - let fingerprintSha256: String - let isManual: Bool - - var id: String { self.stableID } - } - - private(set) var gateways: [GatewayDiscoveryModel.DiscoveredGateway] = [] - private(set) var discoveryStatusText: String = "Idle" - private(set) var discoveryDebugLog: [GatewayDiscoveryModel.DebugLogEntry] = [] - private(set) var pendingTrustPrompt: TrustPrompt? - - private let discovery = GatewayDiscoveryModel() - private weak var appModel: NodeAppModel? - private var didAutoConnect = false - private var pendingServiceResolvers: [String: GatewayServiceResolver] = [:] - private var pendingTrustConnect: (url: URL, stableID: String, isManual: Bool)? - - init(appModel: NodeAppModel, startDiscovery: Bool = true) { - self.appModel = appModel - - GatewaySettingsStore.bootstrapPersistence() - let defaults = UserDefaults.standard - self.discovery.setDebugLoggingEnabled(defaults.bool(forKey: "gateway.discovery.debugLogs")) - - self.updateFromDiscovery() - self.observeDiscovery() - - if startDiscovery { - self.discovery.start() - } - } - - func setDiscoveryDebugLoggingEnabled(_ enabled: Bool) { - self.discovery.setDebugLoggingEnabled(enabled) - } - - func setScenePhase(_ phase: ScenePhase) { - switch phase { - case .background: - self.discovery.stop() - case .active, .inactive: - self.discovery.start() - self.attemptAutoReconnectIfNeeded() - @unknown default: - self.discovery.start() - self.attemptAutoReconnectIfNeeded() - } - } - - func allowAutoConnectAgain() { - self.didAutoConnect = false - self.maybeAutoConnect() - } - - func restartDiscovery() { - self.discovery.stop() - self.didAutoConnect = false - self.discovery.start() - self.updateFromDiscovery() - } - - - /// Returns `nil` when a connect attempt was started, otherwise returns a user-facing error. - func connectWithDiagnostics(_ gateway: GatewayDiscoveryModel.DiscoveredGateway) async -> String? { - await self.connectDiscoveredGateway(gateway) - } - - private func connectDiscoveredGateway( - _ gateway: GatewayDiscoveryModel.DiscoveredGateway) async -> String? - { - let instanceId = UserDefaults.standard.string(forKey: "node.instanceId")? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if instanceId.isEmpty { - return "Missing instanceId (node.instanceId). Try restarting the app." - } - let token = GatewaySettingsStore.loadGatewayToken(instanceId: instanceId) - let password = GatewaySettingsStore.loadGatewayPassword(instanceId: instanceId) - - // Resolve the service endpoint (SRV/A/AAAA). TXT is unauthenticated; do not route via TXT. - guard let target = await self.resolveServiceEndpoint(gateway.endpoint) else { - return "Failed to resolve the discovered gateway endpoint." - } - - let stableID = gateway.stableID - // Discovery is a LAN operation; refuse unauthenticated plaintext connects. - let tlsRequired = true - let stored = GatewayTLSStore.loadFingerprint(stableID: stableID) - - guard gateway.tlsEnabled || stored != nil else { - return "Discovered gateway is missing TLS and no trusted fingerprint is stored." - } - - if tlsRequired, stored == nil { - guard let url = self.buildGatewayURL(host: target.host, port: target.port, useTLS: true) - else { return "Failed to build TLS URL for trust verification." } - guard let fp = await self.probeTLSFingerprint(url: url) else { - return "Failed to read TLS fingerprint from discovered gateway." - } - self.pendingTrustConnect = (url: url, stableID: stableID, isManual: false) - self.pendingTrustPrompt = TrustPrompt( - stableID: stableID, - gatewayName: gateway.name, - host: target.host, - port: target.port, - fingerprintSha256: fp, - isManual: false) - self.appModel?.gatewayStatusText = "Verify gateway TLS fingerprint" - return nil - } - - let tlsParams = stored.map { fp in - GatewayTLSParams(required: true, expectedFingerprint: fp, allowTOFU: false, storeKey: stableID) - } - - guard let url = self.buildGatewayURL( - host: target.host, - port: target.port, - useTLS: tlsParams?.required == true) - else { return "Failed to build discovered gateway URL." } - GatewaySettingsStore.saveLastGatewayConnectionDiscovered(stableID: stableID, useTLS: true) - self.didAutoConnect = true - self.startAutoConnect( - url: url, - gatewayStableID: stableID, - tls: tlsParams, - token: token, - password: password) - return nil - } - - func connect(_ gateway: GatewayDiscoveryModel.DiscoveredGateway) async { - _ = await self.connectWithDiagnostics(gateway) - } - - func connectManual(host: String, port: Int, useTLS: Bool) async { - let instanceId = UserDefaults.standard.string(forKey: "node.instanceId")? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let token = GatewaySettingsStore.loadGatewayToken(instanceId: instanceId) - let password = GatewaySettingsStore.loadGatewayPassword(instanceId: instanceId) - let resolvedUseTLS = self.resolveManualUseTLS(host: host, useTLS: useTLS) - guard let resolvedPort = self.resolveManualPort(host: host, port: port, useTLS: resolvedUseTLS) - else { return } - let stableID = self.manualStableID(host: host, port: resolvedPort) - let stored = GatewayTLSStore.loadFingerprint(stableID: stableID) - if resolvedUseTLS, stored == nil { - guard let url = self.buildGatewayURL(host: host, port: resolvedPort, useTLS: true) else { return } - guard let fp = await self.probeTLSFingerprint(url: url) else { return } - self.pendingTrustConnect = (url: url, stableID: stableID, isManual: true) - self.pendingTrustPrompt = TrustPrompt( - stableID: stableID, - gatewayName: "\(host):\(resolvedPort)", - host: host, - port: resolvedPort, - fingerprintSha256: fp, - isManual: true) - self.appModel?.gatewayStatusText = "Verify gateway TLS fingerprint" - return - } - - let tlsParams = stored.map { fp in - GatewayTLSParams(required: true, expectedFingerprint: fp, allowTOFU: false, storeKey: stableID) - } - guard let url = self.buildGatewayURL( - host: host, - port: resolvedPort, - useTLS: tlsParams?.required == true) - else { return } - GatewaySettingsStore.saveLastGatewayConnectionManual( - host: host, - port: resolvedPort, - useTLS: resolvedUseTLS && tlsParams != nil, - stableID: stableID) - self.didAutoConnect = true - self.startAutoConnect( - url: url, - gatewayStableID: stableID, - tls: tlsParams, - token: token, - password: password) - } - - func connectLastKnown() async { - guard let last = GatewaySettingsStore.loadLastGatewayConnection() else { return } - switch last { - case let .manual(host, port, useTLS, _): - await self.connectManual(host: host, port: port, useTLS: useTLS) - case let .discovered(stableID, _): - guard let gateway = self.gateways.first(where: { $0.stableID == stableID }) else { return } - await self.connectDiscoveredGateway(gateway) - } - } - - /// Rebuild connect options from current local settings (caps/commands/permissions) - /// and re-apply the active gateway config so capability changes take effect immediately. - func refreshActiveGatewayRegistrationFromSettings() { - guard let appModel else { return } - guard let cfg = appModel.activeGatewayConnectConfig else { return } - guard appModel.gatewayAutoReconnectEnabled else { return } - - let refreshedConfig = GatewayConnectConfig( - url: cfg.url, - stableID: cfg.stableID, - tls: cfg.tls, - token: cfg.token, - password: cfg.password, - nodeOptions: self.makeConnectOptions(stableID: cfg.stableID)) - appModel.applyGatewayConnectConfig(refreshedConfig) - } - - func clearPendingTrustPrompt() { - self.pendingTrustPrompt = nil - self.pendingTrustConnect = nil - } - - func acceptPendingTrustPrompt() async { - guard let pending = self.pendingTrustConnect, - let prompt = self.pendingTrustPrompt, - pending.stableID == prompt.stableID - else { return } - - GatewayTLSStore.saveFingerprint(prompt.fingerprintSha256, stableID: pending.stableID) - self.clearPendingTrustPrompt() - - if pending.isManual { - GatewaySettingsStore.saveLastGatewayConnectionManual( - host: prompt.host, - port: prompt.port, - useTLS: true, - stableID: pending.stableID) - } else { - GatewaySettingsStore.saveLastGatewayConnectionDiscovered(stableID: pending.stableID, useTLS: true) - } - - let instanceId = UserDefaults.standard.string(forKey: "node.instanceId")? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let token = GatewaySettingsStore.loadGatewayToken(instanceId: instanceId) - let password = GatewaySettingsStore.loadGatewayPassword(instanceId: instanceId) - let tlsParams = GatewayTLSParams( - required: true, - expectedFingerprint: prompt.fingerprintSha256, - allowTOFU: false, - storeKey: pending.stableID) - - self.didAutoConnect = true - self.startAutoConnect( - url: pending.url, - gatewayStableID: pending.stableID, - tls: tlsParams, - token: token, - password: password) - } - - func declinePendingTrustPrompt() { - self.clearPendingTrustPrompt() - self.appModel?.gatewayStatusText = "Offline" - } - - private func updateFromDiscovery() { - let newGateways = self.discovery.gateways - self.gateways = newGateways - self.discoveryStatusText = self.discovery.statusText - self.discoveryDebugLog = self.discovery.debugLog - self.updateLastDiscoveredGateway(from: newGateways) - self.maybeAutoConnect() - } - - private func observeDiscovery() { - withObservationTracking { - _ = self.discovery.gateways - _ = self.discovery.statusText - _ = self.discovery.debugLog - } onChange: { [weak self] in - Task { @MainActor in - guard let self else { return } - self.updateFromDiscovery() - self.observeDiscovery() - } - } - } - - private func maybeAutoConnect() { - guard !self.didAutoConnect else { return } - guard let appModel = self.appModel else { return } - guard appModel.gatewayServerName == nil else { return } - - let defaults = UserDefaults.standard - guard defaults.bool(forKey: "gateway.autoconnect") else { return } - let manualEnabled = defaults.bool(forKey: "gateway.manual.enabled") - - let instanceId = defaults.string(forKey: "node.instanceId")? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - guard !instanceId.isEmpty else { return } - - let token = GatewaySettingsStore.loadGatewayToken(instanceId: instanceId) - let password = GatewaySettingsStore.loadGatewayPassword(instanceId: instanceId) - - if manualEnabled { - let manualHost = defaults.string(forKey: "gateway.manual.host")? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - guard !manualHost.isEmpty else { return } - - let manualPort = defaults.integer(forKey: "gateway.manual.port") - let manualTLS = defaults.bool(forKey: "gateway.manual.tls") - let resolvedUseTLS = self.resolveManualUseTLS(host: manualHost, useTLS: manualTLS) - guard let resolvedPort = self.resolveManualPort( - host: manualHost, - port: manualPort, - useTLS: resolvedUseTLS) - else { return } - - let stableID = self.manualStableID(host: manualHost, port: resolvedPort) - let tlsParams = self.resolveManualTLSParams( - stableID: stableID, - tlsEnabled: resolvedUseTLS, - allowTOFUReset: self.shouldRequireTLS(host: manualHost)) - - guard let url = self.buildGatewayURL( - host: manualHost, - port: resolvedPort, - useTLS: tlsParams?.required == true) - else { return } - - self.didAutoConnect = true - self.startAutoConnect( - url: url, - gatewayStableID: stableID, - tls: tlsParams, - token: token, - password: password) - return - } - - if let lastKnown = GatewaySettingsStore.loadLastGatewayConnection() { - if case let .manual(host, port, useTLS, stableID) = lastKnown { - let resolvedUseTLS = self.resolveManualUseTLS(host: host, useTLS: useTLS) - let stored = GatewayTLSStore.loadFingerprint(stableID: stableID) - let tlsParams = stored.map { fp in - GatewayTLSParams(required: true, expectedFingerprint: fp, allowTOFU: false, storeKey: stableID) - } - guard let url = self.buildGatewayURL( - host: host, - port: port, - useTLS: resolvedUseTLS && tlsParams != nil) - else { return } - - // Security: autoconnect only to previously trusted gateways (stored TLS pin). - guard tlsParams != nil else { return } - - self.didAutoConnect = true - self.startAutoConnect( - url: url, - gatewayStableID: stableID, - tls: tlsParams, - token: token, - password: password) - return - } - } - - let preferredStableID = defaults.string(forKey: "gateway.preferredStableID")? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let lastDiscoveredStableID = defaults.string(forKey: "gateway.lastDiscoveredStableID")? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - - let candidates = [preferredStableID, lastDiscoveredStableID].filter { !$0.isEmpty } - if let targetStableID = candidates.first(where: { id in - self.gateways.contains(where: { $0.stableID == id }) - }) { - guard let target = self.gateways.first(where: { $0.stableID == targetStableID }) else { return } - // Security: autoconnect only to previously trusted gateways (stored TLS pin). - guard GatewayTLSStore.loadFingerprint(stableID: target.stableID) != nil else { return } - - self.didAutoConnect = true - Task { [weak self] in - guard let self else { return } - await self.connectDiscoveredGateway(target) - } - return - } - - if self.gateways.count == 1, let gateway = self.gateways.first { - // Security: autoconnect only to previously trusted gateways (stored TLS pin). - guard GatewayTLSStore.loadFingerprint(stableID: gateway.stableID) != nil else { return } - - self.didAutoConnect = true - Task { [weak self] in - guard let self else { return } - await self.connectDiscoveredGateway(gateway) - } - return - } - } - - private func attemptAutoReconnectIfNeeded() { - guard let appModel = self.appModel else { return } - guard appModel.gatewayAutoReconnectEnabled else { return } - // Avoid starting duplicate connect loops while a prior config is active. - guard appModel.activeGatewayConnectConfig == nil else { return } - guard UserDefaults.standard.bool(forKey: "gateway.autoconnect") else { return } - self.didAutoConnect = false - self.maybeAutoConnect() - } - - private func updateLastDiscoveredGateway(from gateways: [GatewayDiscoveryModel.DiscoveredGateway]) { - let defaults = UserDefaults.standard - let preferred = defaults.string(forKey: "gateway.preferredStableID")? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let existingLast = defaults.string(forKey: "gateway.lastDiscoveredStableID")? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - - // Avoid overriding user intent (preferred/lastDiscovered are also set on manual Connect). - guard preferred.isEmpty, existingLast.isEmpty else { return } - guard let first = gateways.first else { return } - - defaults.set(first.stableID, forKey: "gateway.lastDiscoveredStableID") - GatewaySettingsStore.saveLastDiscoveredGatewayStableID(first.stableID) - } - - private func startAutoConnect( - url: URL, - gatewayStableID: String, - tls: GatewayTLSParams?, - token: String?, - password: String?) - { - guard let appModel else { return } - let connectOptions = self.makeConnectOptions(stableID: gatewayStableID) - - Task { [weak appModel] in - guard let appModel else { return } - await MainActor.run { - appModel.gatewayStatusText = "Connecting…" - } - let cfg = GatewayConnectConfig( - url: url, - stableID: gatewayStableID, - tls: tls, - token: token, - password: password, - nodeOptions: connectOptions) - appModel.applyGatewayConnectConfig(cfg) - } - } - - private func resolveDiscoveredTLSParams( - gateway: GatewayDiscoveryModel.DiscoveredGateway, - allowTOFU: Bool) -> GatewayTLSParams? - { - let stableID = gateway.stableID - let stored = GatewayTLSStore.loadFingerprint(stableID: stableID) - - // Never let unauthenticated discovery (TXT) override a stored pin. - if let stored { - return GatewayTLSParams( - required: true, - expectedFingerprint: stored, - allowTOFU: false, - storeKey: stableID) - } - - if gateway.tlsEnabled || gateway.tlsFingerprintSha256 != nil { - return GatewayTLSParams( - required: true, - expectedFingerprint: nil, - allowTOFU: false, - storeKey: stableID) - } - - return nil - } - - private func resolveManualTLSParams( - stableID: String, - tlsEnabled: Bool, - allowTOFUReset: Bool = false) -> GatewayTLSParams? - { - let stored = GatewayTLSStore.loadFingerprint(stableID: stableID) - if tlsEnabled || stored != nil { - return GatewayTLSParams( - required: true, - expectedFingerprint: stored, - allowTOFU: false, - storeKey: stableID) - } - - return nil - } - - private func probeTLSFingerprint(url: URL) async -> String? { - await withCheckedContinuation { continuation in - let probe = GatewayTLSFingerprintProbe(url: url, timeoutSeconds: 3) { fp in - continuation.resume(returning: fp) - } - probe.start() - } - } - - private func resolveServiceEndpoint(_ endpoint: NWEndpoint) async -> (host: String, port: Int)? { - guard case let .service(name, type, domain, _) = endpoint else { return nil } - let key = "\(domain)|\(type)|\(name)" - return await withCheckedContinuation { continuation in - let resolver = GatewayServiceResolver(name: name, type: type, domain: domain) { [weak self] result in - Task { @MainActor in - self?.pendingServiceResolvers[key] = nil - continuation.resume(returning: result) - } - } - self.pendingServiceResolvers[key] = resolver - resolver.start() - } - } - - private func resolveHostPortFromBonjourEndpoint(_ endpoint: NWEndpoint) async -> (host: String, port: Int)? { - switch endpoint { - case let .hostPort(host, port): - return (host: host.debugDescription, port: Int(port.rawValue)) - case let .service(name, type, domain, _): - return await Self.resolveBonjourServiceToHostPort(name: name, type: type, domain: domain) - default: - return nil - } - } - - private static func resolveBonjourServiceToHostPort( - name: String, - type: String, - domain: String, - timeoutSeconds: TimeInterval = 3.0 - ) async -> (host: String, port: Int)? { - // NetService callbacks are delivered via a run loop. If we resolve from a thread without one, - // we can end up never receiving callbacks, which in turn leaks the continuation and leaves - // the UI stuck "connecting". Keep the whole lifecycle on the main run loop and always - // resume the continuation exactly once (timeout/cancel safe). - @MainActor - final class Resolver: NSObject, @preconcurrency NetServiceDelegate { - private var cont: CheckedContinuation<(host: String, port: Int)?, Never>? - private let service: NetService - private var timeoutTask: Task? - private var finished = false - - init(cont: CheckedContinuation<(host: String, port: Int)?, Never>, service: NetService) { - self.cont = cont - self.service = service - super.init() - } - - func start(timeoutSeconds: TimeInterval) { - self.service.delegate = self - self.service.schedule(in: .main, forMode: .default) - - // NetService has its own timeout, but we keep a manual one as a backstop in case - // callbacks never arrive (e.g. local network permission issues). - self.timeoutTask = Task { @MainActor [weak self] in - guard let self else { return } - let ns = UInt64(max(0.1, timeoutSeconds) * 1_000_000_000) - try? await Task.sleep(nanoseconds: ns) - self.finish(nil) - } - - self.service.resolve(withTimeout: timeoutSeconds) - } - - func netServiceDidResolveAddress(_ sender: NetService) { - self.finish(Self.extractHostPort(sender)) - } - - func netService(_ sender: NetService, didNotResolve errorDict: [String: NSNumber]) { - _ = errorDict // currently best-effort; callers surface a generic failure - self.finish(nil) - } - - private func finish(_ result: (host: String, port: Int)?) { - guard !self.finished else { return } - self.finished = true - - self.timeoutTask?.cancel() - self.timeoutTask = nil - - self.service.stop() - self.service.remove(from: .main, forMode: .default) - - let c = self.cont - self.cont = nil - c?.resume(returning: result) - } - - private static func extractHostPort(_ svc: NetService) -> (host: String, port: Int)? { - let port = svc.port - - if let host = svc.hostName?.trimmingCharacters(in: .whitespacesAndNewlines), !host.isEmpty { - return (host: host, port: port) - } - - guard let addrs = svc.addresses else { return nil } - for addrData in addrs { - let host = addrData.withUnsafeBytes { ptr -> String? in - guard let base = ptr.baseAddress, !ptr.isEmpty else { return nil } - var buffer = [CChar](repeating: 0, count: Int(NI_MAXHOST)) - - let rc = getnameinfo( - base.assumingMemoryBound(to: sockaddr.self), - socklen_t(ptr.count), - &buffer, - socklen_t(buffer.count), - nil, - 0, - NI_NUMERICHOST) - guard rc == 0 else { return nil } - return String(cString: buffer) - } - - if let host, !host.isEmpty { - return (host: host, port: port) - } - } - - return nil - } - } - - return await withCheckedContinuation { cont in - Task { @MainActor in - let service = NetService(domain: domain, type: type, name: name) - let resolver = Resolver(cont: cont, service: service) - // Keep the resolver alive for the lifetime of the NetService resolve. - objc_setAssociatedObject(service, "resolver", resolver, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) - resolver.start(timeoutSeconds: timeoutSeconds) - } - } - } - - private func buildGatewayURL(host: String, port: Int, useTLS: Bool) -> URL? { - let scheme = useTLS ? "wss" : "ws" - var components = URLComponents() - components.scheme = scheme - components.host = host - components.port = port - return components.url - } - - private func resolveManualUseTLS(host: String, useTLS: Bool) -> Bool { - useTLS || self.shouldRequireTLS(host: host) - } - - private func shouldRequireTLS(host: String) -> Bool { - !Self.isLoopbackHost(host) - } - - private func shouldForceTLS(host: String) -> Bool { - let trimmed = host.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - if trimmed.isEmpty { return false } - return trimmed.hasSuffix(".ts.net") || trimmed.hasSuffix(".ts.net.") - } - - private static func isLoopbackHost(_ rawHost: String) -> Bool { - var host = rawHost.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - guard !host.isEmpty else { return false } - - if host.hasPrefix("[") && host.hasSuffix("]") { - host.removeFirst() - host.removeLast() - } - if host.hasSuffix(".") { - host.removeLast() - } - if let zoneIndex = host.firstIndex(of: "%") { - host = String(host[.. Bool { - var addr = in_addr() - let parsed = host.withCString { inet_pton(AF_INET, $0, &addr) == 1 } - guard parsed else { return false } - let value = UInt32(bigEndian: addr.s_addr) - let firstOctet = UInt8((value >> 24) & 0xFF) - return firstOctet == 127 - } - - private static func isLoopbackIPv6(_ host: String) -> Bool { - var addr = in6_addr() - let parsed = host.withCString { inet_pton(AF_INET6, $0, &addr) == 1 } - guard parsed else { return false } - return withUnsafeBytes(of: &addr) { rawBytes in - let bytes = rawBytes.bindMemory(to: UInt8.self) - let isV6Loopback = bytes[0..<15].allSatisfy { $0 == 0 } && bytes[15] == 1 - if isV6Loopback { return true } - - let isMappedV4 = bytes[0..<10].allSatisfy { $0 == 0 } && bytes[10] == 0xFF && bytes[11] == 0xFF - return isMappedV4 && bytes[12] == 127 - } - } - - private func manualStableID(host: String, port: Int) -> String { - "manual|\(host.lowercased())|\(port)" - } - - private func makeConnectOptions(stableID: String?) -> GatewayConnectOptions { - let defaults = UserDefaults.standard - let displayName = self.resolvedDisplayName(defaults: defaults) - let resolvedClientId = self.resolvedClientId(defaults: defaults, stableID: stableID) - - return GatewayConnectOptions( - role: "node", - scopes: [], - caps: self.currentCaps(), - commands: self.currentCommands(), - permissions: self.currentPermissions(), - clientId: resolvedClientId, - clientMode: "node", - clientDisplayName: displayName) - } - - private func resolvedClientId(defaults: UserDefaults, stableID: String?) -> String { - if let stableID, - let override = GatewaySettingsStore.loadGatewayClientIdOverride(stableID: stableID) { - return override - } - let manualClientId = defaults.string(forKey: "gateway.manual.clientId")? - .trimmingCharacters(in: .whitespacesAndNewlines) - if manualClientId?.isEmpty == false { - return manualClientId! - } - return "openclaw-ios" - } - - private func resolveManualPort(host: String, port: Int, useTLS: Bool) -> Int? { - if port > 0 { - return port <= 65535 ? port : nil - } - let trimmedHost = host.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmedHost.isEmpty else { return nil } - if useTLS && self.shouldForceTLS(host: trimmedHost) { - return 443 - } - return 18789 - } - - private func resolvedDisplayName(defaults: UserDefaults) -> String { - let key = "node.displayName" - let existingRaw = defaults.string(forKey: key) - let resolved = NodeDisplayName.resolve( - existing: existingRaw, - deviceName: UIDevice.current.name, - interfaceIdiom: UIDevice.current.userInterfaceIdiom) - let existing = existingRaw?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if existing.isEmpty || NodeDisplayName.isGeneric(existing) { - defaults.set(resolved, forKey: key) - } - return resolved - } - - private func currentCaps() -> [String] { - var caps = [OpenClawCapability.canvas.rawValue, OpenClawCapability.screen.rawValue] - - // Default-on: if the key doesn't exist yet, treat it as enabled. - let cameraEnabled = - UserDefaults.standard.object(forKey: "camera.enabled") == nil - ? true - : UserDefaults.standard.bool(forKey: "camera.enabled") - if cameraEnabled { caps.append(OpenClawCapability.camera.rawValue) } - - let voiceWakeEnabled = UserDefaults.standard.bool(forKey: VoiceWakePreferences.enabledKey) - if voiceWakeEnabled { caps.append(OpenClawCapability.voiceWake.rawValue) } - - let locationModeRaw = UserDefaults.standard.string(forKey: "location.enabledMode") ?? "off" - let locationMode = OpenClawLocationMode(rawValue: locationModeRaw) ?? .off - if locationMode != .off { caps.append(OpenClawCapability.location.rawValue) } - - caps.append(OpenClawCapability.device.rawValue) - if WatchMessagingService.isSupportedOnDevice() { - caps.append(OpenClawCapability.watch.rawValue) - } - caps.append(OpenClawCapability.photos.rawValue) - caps.append(OpenClawCapability.contacts.rawValue) - caps.append(OpenClawCapability.calendar.rawValue) - caps.append(OpenClawCapability.reminders.rawValue) - if Self.motionAvailable() { - caps.append(OpenClawCapability.motion.rawValue) - } - - return caps - } - - private func currentCommands() -> [String] { - var commands: [String] = [ - OpenClawCanvasCommand.present.rawValue, - OpenClawCanvasCommand.hide.rawValue, - OpenClawCanvasCommand.navigate.rawValue, - OpenClawCanvasCommand.evalJS.rawValue, - OpenClawCanvasCommand.snapshot.rawValue, - OpenClawCanvasA2UICommand.push.rawValue, - OpenClawCanvasA2UICommand.pushJSONL.rawValue, - OpenClawCanvasA2UICommand.reset.rawValue, - OpenClawScreenCommand.record.rawValue, - OpenClawSystemCommand.notify.rawValue, - OpenClawChatCommand.push.rawValue, - OpenClawTalkCommand.pttStart.rawValue, - OpenClawTalkCommand.pttStop.rawValue, - OpenClawTalkCommand.pttCancel.rawValue, - OpenClawTalkCommand.pttOnce.rawValue, - ] - - let caps = Set(self.currentCaps()) - if caps.contains(OpenClawCapability.camera.rawValue) { - commands.append(OpenClawCameraCommand.list.rawValue) - commands.append(OpenClawCameraCommand.snap.rawValue) - commands.append(OpenClawCameraCommand.clip.rawValue) - } - if caps.contains(OpenClawCapability.location.rawValue) { - commands.append(OpenClawLocationCommand.get.rawValue) - } - if caps.contains(OpenClawCapability.device.rawValue) { - commands.append(OpenClawDeviceCommand.status.rawValue) - commands.append(OpenClawDeviceCommand.info.rawValue) - } - if caps.contains(OpenClawCapability.watch.rawValue) { - commands.append(OpenClawWatchCommand.status.rawValue) - commands.append(OpenClawWatchCommand.notify.rawValue) - } - if caps.contains(OpenClawCapability.photos.rawValue) { - commands.append(OpenClawPhotosCommand.latest.rawValue) - } - if caps.contains(OpenClawCapability.contacts.rawValue) { - commands.append(OpenClawContactsCommand.search.rawValue) - commands.append(OpenClawContactsCommand.add.rawValue) - } - if caps.contains(OpenClawCapability.calendar.rawValue) { - commands.append(OpenClawCalendarCommand.events.rawValue) - commands.append(OpenClawCalendarCommand.add.rawValue) - } - if caps.contains(OpenClawCapability.reminders.rawValue) { - commands.append(OpenClawRemindersCommand.list.rawValue) - commands.append(OpenClawRemindersCommand.add.rawValue) - } - if caps.contains(OpenClawCapability.motion.rawValue) { - commands.append(OpenClawMotionCommand.activity.rawValue) - commands.append(OpenClawMotionCommand.pedometer.rawValue) - } - - return commands - } - - private func currentPermissions() -> [String: Bool] { - var permissions: [String: Bool] = [:] - permissions["camera"] = AVCaptureDevice.authorizationStatus(for: .video) == .authorized - permissions["microphone"] = AVCaptureDevice.authorizationStatus(for: .audio) == .authorized - permissions["speechRecognition"] = SFSpeechRecognizer.authorizationStatus() == .authorized - permissions["location"] = Self.isLocationAuthorized( - status: CLLocationManager().authorizationStatus) - && CLLocationManager.locationServicesEnabled() - permissions["screenRecording"] = RPScreenRecorder.shared().isAvailable - - let photoStatus = PHPhotoLibrary.authorizationStatus(for: .readWrite) - permissions["photos"] = photoStatus == .authorized || photoStatus == .limited - let contactsStatus = CNContactStore.authorizationStatus(for: .contacts) - permissions["contacts"] = contactsStatus == .authorized || contactsStatus == .limited - - let calendarStatus = EKEventStore.authorizationStatus(for: .event) - permissions["calendar"] = - calendarStatus == .authorized || calendarStatus == .fullAccess || calendarStatus == .writeOnly - let remindersStatus = EKEventStore.authorizationStatus(for: .reminder) - permissions["reminders"] = - remindersStatus == .authorized || remindersStatus == .fullAccess || remindersStatus == .writeOnly - - let motionStatus = CMMotionActivityManager.authorizationStatus() - let pedometerStatus = CMPedometer.authorizationStatus() - permissions["motion"] = - motionStatus == .authorized || pedometerStatus == .authorized - - let watchStatus = WatchMessagingService.currentStatusSnapshot() - permissions["watchSupported"] = watchStatus.supported - permissions["watchPaired"] = watchStatus.paired - permissions["watchAppInstalled"] = watchStatus.appInstalled - permissions["watchReachable"] = watchStatus.reachable - - return permissions - } - - private static func isLocationAuthorized(status: CLAuthorizationStatus) -> Bool { - switch status { - case .authorizedAlways, .authorizedWhenInUse, .authorized: - return true - default: - return false - } - } - - private static func motionAvailable() -> Bool { - CMMotionActivityManager.isActivityAvailable() || CMPedometer.isStepCountingAvailable() - } - - private func platformString() -> String { - let v = ProcessInfo.processInfo.operatingSystemVersion - let name = switch UIDevice.current.userInterfaceIdiom { - case .pad: - "iPadOS" - case .phone: - "iOS" - default: - "iOS" - } - return "\(name) \(v.majorVersion).\(v.minorVersion).\(v.patchVersion)" - } - - private func deviceFamily() -> String { - switch UIDevice.current.userInterfaceIdiom { - case .pad: - "iPad" - case .phone: - "iPhone" - default: - "iOS" - } - } - - private func modelIdentifier() -> String { - var systemInfo = utsname() - uname(&systemInfo) - let machine = withUnsafeBytes(of: &systemInfo.machine) { ptr in - String(bytes: ptr.prefix { $0 != 0 }, encoding: .utf8) - } - let trimmed = machine?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - return trimmed.isEmpty ? "unknown" : trimmed - } - - private func appVersion() -> String { - Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "dev" - } -} - -#if DEBUG -extension GatewayConnectionController { - func _test_resolvedDisplayName(defaults: UserDefaults) -> String { - self.resolvedDisplayName(defaults: defaults) - } - - func _test_currentCaps() -> [String] { - self.currentCaps() - } - - func _test_currentCommands() -> [String] { - self.currentCommands() - } - - func _test_currentPermissions() -> [String: Bool] { - self.currentPermissions() - } - - func _test_platformString() -> String { - self.platformString() - } - - func _test_deviceFamily() -> String { - self.deviceFamily() - } - - func _test_modelIdentifier() -> String { - self.modelIdentifier() - } - - func _test_appVersion() -> String { - self.appVersion() - } - - func _test_setGateways(_ gateways: [GatewayDiscoveryModel.DiscoveredGateway]) { - self.gateways = gateways - } - - func _test_triggerAutoConnect() { - self.maybeAutoConnect() - } - - func _test_didAutoConnect() -> Bool { - self.didAutoConnect - } - - func _test_resolveDiscoveredTLSParams( - gateway: GatewayDiscoveryModel.DiscoveredGateway, - allowTOFU: Bool) -> GatewayTLSParams? - { - self.resolveDiscoveredTLSParams(gateway: gateway, allowTOFU: allowTOFU) - } - - func _test_resolveManualUseTLS(host: String, useTLS: Bool) -> Bool { - self.resolveManualUseTLS(host: host, useTLS: useTLS) - } - - func _test_resolveManualPort(host: String, port: Int, useTLS: Bool) -> Int? { - self.resolveManualPort(host: host, port: port, useTLS: useTLS) - } -} -#endif - -private final class GatewayTLSFingerprintProbe: NSObject, URLSessionDelegate { - private let url: URL - private let timeoutSeconds: Double - private let onComplete: (String?) -> Void - private var didFinish = false - private var session: URLSession? - private var task: URLSessionWebSocketTask? - - init(url: URL, timeoutSeconds: Double, onComplete: @escaping (String?) -> Void) { - self.url = url - self.timeoutSeconds = timeoutSeconds - self.onComplete = onComplete - } - - func start() { - let config = URLSessionConfiguration.ephemeral - config.timeoutIntervalForRequest = self.timeoutSeconds - config.timeoutIntervalForResource = self.timeoutSeconds - let session = URLSession(configuration: config, delegate: self, delegateQueue: nil) - self.session = session - let task = session.webSocketTask(with: self.url) - self.task = task - task.resume() - - DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + self.timeoutSeconds) { [weak self] in - self?.finish(nil) - } - } - - func urlSession( - _ session: URLSession, - didReceive challenge: URLAuthenticationChallenge, - completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void - ) { - guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust, - let trust = challenge.protectionSpace.serverTrust - else { - completionHandler(.performDefaultHandling, nil) - return - } - - let fp = GatewayTLSFingerprintProbe.certificateFingerprint(trust) - completionHandler(.cancelAuthenticationChallenge, nil) - self.finish(fp) - } - - private func finish(_ fingerprint: String?) { - objc_sync_enter(self) - defer { objc_sync_exit(self) } - guard !self.didFinish else { return } - self.didFinish = true - self.task?.cancel(with: .goingAway, reason: nil) - self.session?.invalidateAndCancel() - self.onComplete(fingerprint) - } - - private static func certificateFingerprint(_ trust: SecTrust) -> String? { - guard let chain = SecTrustCopyCertificateChain(trust) as? [SecCertificate], - let cert = chain.first - else { - return nil - } - let data = SecCertificateCopyData(cert) as Data - let digest = SHA256.hash(data: data) - return digest.map { String(format: "%02x", $0) }.joined() - } -} diff --git a/apps/ios/Sources/Gateway/GatewayConnectionIssue.swift b/apps/ios/Sources/Gateway/GatewayConnectionIssue.swift deleted file mode 100644 index 56d490e226b..00000000000 --- a/apps/ios/Sources/Gateway/GatewayConnectionIssue.swift +++ /dev/null @@ -1,71 +0,0 @@ -import Foundation - -enum GatewayConnectionIssue: Equatable { - case none - case tokenMissing - case unauthorized - case pairingRequired(requestId: String?) - case network - case unknown(String) - - var requestId: String? { - if case let .pairingRequired(requestId) = self { - return requestId - } - return nil - } - - var needsAuthToken: Bool { - switch self { - case .tokenMissing, .unauthorized: - return true - default: - return false - } - } - - var needsPairing: Bool { - if case .pairingRequired = self { return true } - return false - } - - static func detect(from statusText: String) -> Self { - let trimmed = statusText.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return .none } - let lower = trimmed.lowercased() - - if lower.contains("pairing required") || lower.contains("not_paired") || lower.contains("not paired") { - return .pairingRequired(requestId: self.extractRequestId(from: trimmed)) - } - if lower.contains("gateway token missing") { - return .tokenMissing - } - if lower.contains("unauthorized") { - return .unauthorized - } - if lower.contains("connection refused") || - lower.contains("timed out") || - lower.contains("network is unreachable") || - lower.contains("cannot find host") || - lower.contains("could not connect") - { - return .network - } - if lower.hasPrefix("gateway error:") { - return .unknown(trimmed) - } - return .none - } - - private static func extractRequestId(from statusText: String) -> String? { - let marker = "requestId:" - guard let range = statusText.range(of: marker) else { return nil } - let suffix = statusText[range.upperBound...] - let trimmed = suffix.trimmingCharacters(in: .whitespacesAndNewlines) - let end = trimmed.firstIndex(where: { ch in - ch == ")" || ch.isWhitespace || ch == "," || ch == ";" - }) ?? trimmed.endIndex - let id = String(trimmed[.. String { - self.gatewayController.discoveryDebugLog - .map { "\(Self.formatISO($0.ts)) \($0.message)" } - .joined(separator: "\n") - } - - private static let timeFormatter: DateFormatter = { - let formatter = DateFormatter() - formatter.dateFormat = "HH:mm:ss" - return formatter - }() - - private static let isoFormatter: ISO8601DateFormatter = { - let formatter = ISO8601DateFormatter() - formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] - return formatter - }() - - private static func formatTime(_ date: Date) -> String { - self.timeFormatter.string(from: date) - } - - private static func formatISO(_ date: Date) -> String { - self.isoFormatter.string(from: date) - } -} diff --git a/apps/ios/Sources/Gateway/GatewayDiscoveryModel.swift b/apps/ios/Sources/Gateway/GatewayDiscoveryModel.swift deleted file mode 100644 index ce1ba4bf2cb..00000000000 --- a/apps/ios/Sources/Gateway/GatewayDiscoveryModel.swift +++ /dev/null @@ -1,190 +0,0 @@ -import OpenClawKit -import Foundation -import Network -import Observation - -@MainActor -@Observable -final class GatewayDiscoveryModel { - struct DebugLogEntry: Identifiable, Equatable { - var id = UUID() - var ts: Date - var message: String - } - - struct DiscoveredGateway: Identifiable, Equatable { - var id: String { self.stableID } - var name: String - var endpoint: NWEndpoint - var stableID: String - var debugID: String - var lanHost: String? - var tailnetDns: String? - var gatewayPort: Int? - var canvasPort: Int? - var tlsEnabled: Bool - var tlsFingerprintSha256: String? - var cliPath: String? - } - - var gateways: [DiscoveredGateway] = [] - var statusText: String = "Idle" - private(set) var debugLog: [DebugLogEntry] = [] - - private var browsers: [String: NWBrowser] = [:] - private var gatewaysByDomain: [String: [DiscoveredGateway]] = [:] - private var statesByDomain: [String: NWBrowser.State] = [:] - private var debugLoggingEnabled = false - private var lastStableIDs = Set() - - func setDebugLoggingEnabled(_ enabled: Bool) { - let wasEnabled = self.debugLoggingEnabled - self.debugLoggingEnabled = enabled - if !enabled { - self.debugLog = [] - } else if !wasEnabled { - self.appendDebugLog("debug logging enabled") - self.appendDebugLog("snapshot: status=\(self.statusText) gateways=\(self.gateways.count)") - } - } - - func start() { - if !self.browsers.isEmpty { return } - self.appendDebugLog("start()") - - for domain in OpenClawBonjour.gatewayServiceDomains { - let params = NWParameters.tcp - params.includePeerToPeer = true - let browser = NWBrowser( - for: .bonjour(type: OpenClawBonjour.gatewayServiceType, domain: domain), - using: params) - - browser.stateUpdateHandler = { [weak self] state in - Task { @MainActor in - guard let self else { return } - self.statesByDomain[domain] = state - self.updateStatusText() - self.appendDebugLog("state[\(domain)]: \(Self.prettyState(state))") - } - } - - browser.browseResultsChangedHandler = { [weak self] results, _ in - Task { @MainActor in - guard let self else { return } - self.gatewaysByDomain[domain] = results.compactMap { result -> DiscoveredGateway? in - switch result.endpoint { - case let .service(name, _, _, _): - let decodedName = BonjourEscapes.decode(name) - let txt = result.endpoint.txtRecord?.dictionary ?? [:] - let advertisedName = txt["displayName"] - let prettyAdvertised = advertisedName - .map(Self.prettifyInstanceName) - .flatMap { $0.isEmpty ? nil : $0 } - let prettyName = prettyAdvertised ?? Self.prettifyInstanceName(decodedName) - return DiscoveredGateway( - name: prettyName, - endpoint: result.endpoint, - stableID: GatewayEndpointID.stableID(result.endpoint), - debugID: GatewayEndpointID.prettyDescription(result.endpoint), - lanHost: Self.txtValue(txt, key: "lanHost"), - tailnetDns: Self.txtValue(txt, key: "tailnetDns"), - gatewayPort: Self.txtIntValue(txt, key: "gatewayPort"), - canvasPort: Self.txtIntValue(txt, key: "canvasPort"), - tlsEnabled: Self.txtBoolValue(txt, key: "gatewayTls"), - tlsFingerprintSha256: Self.txtValue(txt, key: "gatewayTlsSha256"), - cliPath: Self.txtValue(txt, key: "cliPath")) - default: - return nil - } - } - .sorted { $0.name.localizedCaseInsensitiveCompare($1.name) == .orderedAscending } - - self.recomputeGateways() - } - } - - self.browsers[domain] = browser - browser.start(queue: DispatchQueue(label: "bot.molt.ios.gateway-discovery.\(domain)")) - } - } - - func stop() { - self.appendDebugLog("stop()") - for browser in self.browsers.values { - browser.cancel() - } - self.browsers = [:] - self.gatewaysByDomain = [:] - self.statesByDomain = [:] - self.gateways = [] - self.statusText = "Stopped" - } - - private func recomputeGateways() { - let next = self.gatewaysByDomain.values - .flatMap(\.self) - .sorted { $0.name.localizedCaseInsensitiveCompare($1.name) == .orderedAscending } - - let nextIDs = Set(next.map(\.stableID)) - let added = nextIDs.subtracting(self.lastStableIDs) - let removed = self.lastStableIDs.subtracting(nextIDs) - if !added.isEmpty || !removed.isEmpty { - self.appendDebugLog("results: total=\(next.count) added=\(added.count) removed=\(removed.count)") - } - self.lastStableIDs = nextIDs - self.gateways = next - } - - private func updateStatusText() { - self.statusText = GatewayDiscoveryStatusText.make( - states: Array(self.statesByDomain.values), - hasBrowsers: !self.browsers.isEmpty) - } - - private static func prettyState(_ state: NWBrowser.State) -> String { - switch state { - case .setup: - "setup" - case .ready: - "ready" - case let .failed(err): - "failed (\(err))" - case .cancelled: - "cancelled" - case let .waiting(err): - "waiting (\(err))" - @unknown default: - "unknown" - } - } - - private func appendDebugLog(_ message: String) { - guard self.debugLoggingEnabled else { return } - self.debugLog.append(DebugLogEntry(ts: Date(), message: message)) - if self.debugLog.count > 200 { - self.debugLog.removeFirst(self.debugLog.count - 200) - } - } - - private static func prettifyInstanceName(_ decodedName: String) -> String { - let normalized = decodedName.split(whereSeparator: \.isWhitespace).joined(separator: " ") - let stripped = normalized.replacingOccurrences(of: " (OpenClaw)", with: "") - .replacingOccurrences(of: #"\s+\(\d+\)$"#, with: "", options: .regularExpression) - return stripped.trimmingCharacters(in: .whitespacesAndNewlines) - } - - private static func txtValue(_ dict: [String: String], key: String) -> String? { - let raw = dict[key]?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - return raw.isEmpty ? nil : raw - } - - private static func txtIntValue(_ dict: [String: String], key: String) -> Int? { - guard let raw = self.txtValue(dict, key: key) else { return nil } - return Int(raw) - } - - private static func txtBoolValue(_ dict: [String: String], key: String) -> Bool { - guard let raw = self.txtValue(dict, key: key)?.lowercased() else { return false } - return raw == "1" || raw == "true" || raw == "yes" - } -} diff --git a/apps/ios/Sources/Gateway/GatewayHealthMonitor.swift b/apps/ios/Sources/Gateway/GatewayHealthMonitor.swift deleted file mode 100644 index 182df942c9d..00000000000 --- a/apps/ios/Sources/Gateway/GatewayHealthMonitor.swift +++ /dev/null @@ -1,85 +0,0 @@ -import Foundation -import OpenClawKit - -@MainActor -final class GatewayHealthMonitor { - struct Config: Sendable { - var intervalSeconds: Double - var timeoutSeconds: Double - var maxFailures: Int - } - - private let config: Config - private let sleep: @Sendable (UInt64) async -> Void - private var task: Task? - - init( - config: Config = Config(intervalSeconds: 15, timeoutSeconds: 5, maxFailures: 3), - sleep: @escaping @Sendable (UInt64) async -> Void = { nanoseconds in - try? await Task.sleep(nanoseconds: nanoseconds) - } - ) { - self.config = config - self.sleep = sleep - } - - func start( - check: @escaping @Sendable () async throws -> Bool, - onFailure: @escaping @Sendable (_ failureCount: Int) async -> Void) - { - self.stop() - let config = self.config - let sleep = self.sleep - self.task = Task { @MainActor in - var failures = 0 - while !Task.isCancelled { - let ok = await Self.runCheck(check: check, timeoutSeconds: config.timeoutSeconds) - if ok { - failures = 0 - } else { - failures += 1 - if failures >= max(1, config.maxFailures) { - await onFailure(failures) - failures = 0 - } - } - - if Task.isCancelled { break } - let interval = max(0.0, config.intervalSeconds) - let nanos = UInt64(interval * 1_000_000_000) - if nanos > 0 { - await sleep(nanos) - } else { - await Task.yield() - } - } - } - } - - func stop() { - self.task?.cancel() - self.task = nil - } - - private static func runCheck( - check: @escaping @Sendable () async throws -> Bool, - timeoutSeconds: Double) async -> Bool - { - let timeout = max(0.0, timeoutSeconds) - if timeout == 0 { - return (try? await check()) ?? false - } - do { - let timeoutError = NSError( - domain: "GatewayHealthMonitor", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "health check timed out"]) - return try await AsyncTimeout.withTimeout( - seconds: timeout, - onTimeout: { timeoutError }, - operation: check) - } catch { - return false - } - } -} diff --git a/apps/ios/Sources/Gateway/GatewayQuickSetupSheet.swift b/apps/ios/Sources/Gateway/GatewayQuickSetupSheet.swift deleted file mode 100644 index eac92df71e8..00000000000 --- a/apps/ios/Sources/Gateway/GatewayQuickSetupSheet.swift +++ /dev/null @@ -1,113 +0,0 @@ -import SwiftUI - -struct GatewayQuickSetupSheet: View { - @Environment(NodeAppModel.self) private var appModel - @Environment(GatewayConnectionController.self) private var gatewayController - @Environment(\.dismiss) private var dismiss - - @AppStorage("onboarding.quickSetupDismissed") private var quickSetupDismissed: Bool = false - @State private var connecting: Bool = false - @State private var connectError: String? - - var body: some View { - NavigationStack { - VStack(alignment: .leading, spacing: 16) { - Text("Connect to a Gateway?") - .font(.title2.bold()) - - if let candidate = self.bestCandidate { - VStack(alignment: .leading, spacing: 6) { - Text(verbatim: candidate.name) - .font(.headline) - Text(verbatim: candidate.debugID) - .font(.footnote) - .foregroundStyle(.secondary) - - VStack(alignment: .leading, spacing: 2) { - // Use verbatim strings so Bonjour-provided values can't be interpreted as - // localized format strings (which can crash with Objective-C exceptions). - Text(verbatim: "Discovery: \(self.gatewayController.discoveryStatusText)") - Text(verbatim: "Status: \(self.appModel.gatewayStatusText)") - Text(verbatim: "Node: \(self.appModel.nodeStatusText)") - Text(verbatim: "Operator: \(self.appModel.operatorStatusText)") - } - .font(.footnote) - .foregroundStyle(.secondary) - } - .padding(12) - .background(.thinMaterial) - .clipShape(RoundedRectangle(cornerRadius: 14)) - - Button { - self.connectError = nil - self.connecting = true - Task { - let err = await self.gatewayController.connectWithDiagnostics(candidate) - await MainActor.run { - self.connecting = false - self.connectError = err - // If we kicked off a connect, leave the sheet up so the user can see status evolve. - } - } - } label: { - Group { - if self.connecting { - HStack(spacing: 8) { - ProgressView().progressViewStyle(.circular) - Text("Connecting…") - } - } else { - Text("Connect") - } - } - .frame(maxWidth: .infinity) - } - .buttonStyle(.borderedProminent) - .disabled(self.connecting) - - if let connectError { - Text(connectError) - .font(.footnote) - .foregroundStyle(.secondary) - .textSelection(.enabled) - } - - Button { - self.dismiss() - } label: { - Text("Not now") - .frame(maxWidth: .infinity) - } - .buttonStyle(.bordered) - .disabled(self.connecting) - - Toggle("Don’t show this again", isOn: self.$quickSetupDismissed) - .padding(.top, 4) - } else { - Text("No gateways found yet. Make sure your gateway is running and Bonjour discovery is enabled.") - .foregroundStyle(.secondary) - } - - Spacer() - } - .padding() - .navigationTitle("Quick Setup") - .navigationBarTitleDisplayMode(.inline) - .toolbar { - ToolbarItem(placement: .topBarTrailing) { - Button { - self.quickSetupDismissed = true - self.dismiss() - } label: { - Text("Close") - } - } - } - } - } - - private var bestCandidate: GatewayDiscoveryModel.DiscoveredGateway? { - // Prefer whatever discovery says is first; the list is already name-sorted. - self.gatewayController.gateways.first - } -} diff --git a/apps/ios/Sources/Gateway/GatewayServiceResolver.swift b/apps/ios/Sources/Gateway/GatewayServiceResolver.swift deleted file mode 100644 index 882a4e7d05a..00000000000 --- a/apps/ios/Sources/Gateway/GatewayServiceResolver.swift +++ /dev/null @@ -1,55 +0,0 @@ -import Foundation - -// NetService-based resolver for Bonjour services. -// Used to resolve the service endpoint (SRV + A/AAAA) without trusting TXT for routing. -final class GatewayServiceResolver: NSObject, NetServiceDelegate { - private let service: NetService - private let completion: ((host: String, port: Int)?) -> Void - private var didFinish = false - - init( - name: String, - type: String, - domain: String, - completion: @escaping ((host: String, port: Int)?) -> Void) - { - self.service = NetService(domain: domain, type: type, name: name) - self.completion = completion - super.init() - self.service.delegate = self - } - - func start(timeout: TimeInterval = 2.0) { - self.service.schedule(in: .main, forMode: .common) - self.service.resolve(withTimeout: timeout) - } - - func netServiceDidResolveAddress(_ sender: NetService) { - let host = Self.normalizeHost(sender.hostName) - let port = sender.port - guard let host, !host.isEmpty, port > 0 else { - self.finish(result: nil) - return - } - self.finish(result: (host: host, port: port)) - } - - func netService(_ sender: NetService, didNotResolve errorDict: [String: NSNumber]) { - self.finish(result: nil) - } - - private func finish(result: ((host: String, port: Int))?) { - guard !self.didFinish else { return } - self.didFinish = true - self.service.stop() - self.service.remove(from: .main, forMode: .common) - self.completion(result) - } - - private static func normalizeHost(_ raw: String?) -> String? { - let trimmed = raw?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if trimmed.isEmpty { return nil } - return trimmed.hasSuffix(".") ? String(trimmed.dropLast()) : trimmed - } -} - diff --git a/apps/ios/Sources/Gateway/GatewaySettingsStore.swift b/apps/ios/Sources/Gateway/GatewaySettingsStore.swift deleted file mode 100644 index 3ff57ad2e67..00000000000 --- a/apps/ios/Sources/Gateway/GatewaySettingsStore.swift +++ /dev/null @@ -1,438 +0,0 @@ -import Foundation -import os - -enum GatewaySettingsStore { - private static let gatewayService = "ai.openclaw.gateway" - private static let nodeService = "ai.openclaw.node" - private static let talkService = "ai.openclaw.talk" - - private static let instanceIdDefaultsKey = "node.instanceId" - private static let preferredGatewayStableIDDefaultsKey = "gateway.preferredStableID" - private static let lastDiscoveredGatewayStableIDDefaultsKey = "gateway.lastDiscoveredStableID" - private static let manualEnabledDefaultsKey = "gateway.manual.enabled" - private static let manualHostDefaultsKey = "gateway.manual.host" - private static let manualPortDefaultsKey = "gateway.manual.port" - private static let manualTlsDefaultsKey = "gateway.manual.tls" - private static let discoveryDebugLogsDefaultsKey = "gateway.discovery.debugLogs" - private static let lastGatewayKindDefaultsKey = "gateway.last.kind" - private static let lastGatewayHostDefaultsKey = "gateway.last.host" - private static let lastGatewayPortDefaultsKey = "gateway.last.port" - private static let lastGatewayTlsDefaultsKey = "gateway.last.tls" - private static let lastGatewayStableIDDefaultsKey = "gateway.last.stableID" - private static let clientIdOverrideDefaultsPrefix = "gateway.clientIdOverride." - private static let selectedAgentDefaultsPrefix = "gateway.selectedAgentId." - - private static let instanceIdAccount = "instanceId" - private static let preferredGatewayStableIDAccount = "preferredStableID" - private static let lastDiscoveredGatewayStableIDAccount = "lastDiscoveredStableID" - private static let talkElevenLabsApiKeyAccount = "elevenlabs.apiKey" - - static func bootstrapPersistence() { - self.ensureStableInstanceID() - self.ensurePreferredGatewayStableID() - self.ensureLastDiscoveredGatewayStableID() - } - - static func loadStableInstanceID() -> String? { - if let value = KeychainStore.loadString(service: self.nodeService, account: self.instanceIdAccount)? - .trimmingCharacters(in: .whitespacesAndNewlines), - !value.isEmpty - { - return value - } - - return nil - } - - static func saveStableInstanceID(_ instanceId: String) { - _ = KeychainStore.saveString(instanceId, service: self.nodeService, account: self.instanceIdAccount) - } - - static func loadPreferredGatewayStableID() -> String? { - if let value = KeychainStore.loadString( - service: self.gatewayService, - account: self.preferredGatewayStableIDAccount - )?.trimmingCharacters(in: .whitespacesAndNewlines), - !value.isEmpty - { - return value - } - - return nil - } - - static func savePreferredGatewayStableID(_ stableID: String) { - _ = KeychainStore.saveString( - stableID, - service: self.gatewayService, - account: self.preferredGatewayStableIDAccount) - } - - static func loadLastDiscoveredGatewayStableID() -> String? { - if let value = KeychainStore.loadString( - service: self.gatewayService, - account: self.lastDiscoveredGatewayStableIDAccount - )?.trimmingCharacters(in: .whitespacesAndNewlines), - !value.isEmpty - { - return value - } - - return nil - } - - static func saveLastDiscoveredGatewayStableID(_ stableID: String) { - _ = KeychainStore.saveString( - stableID, - service: self.gatewayService, - account: self.lastDiscoveredGatewayStableIDAccount) - } - - static func loadGatewayToken(instanceId: String) -> String? { - let account = self.gatewayTokenAccount(instanceId: instanceId) - let token = KeychainStore.loadString(service: self.gatewayService, account: account)? - .trimmingCharacters(in: .whitespacesAndNewlines) - if token?.isEmpty == false { return token } - return nil - } - - static func saveGatewayToken(_ token: String, instanceId: String) { - _ = KeychainStore.saveString( - token, - service: self.gatewayService, - account: self.gatewayTokenAccount(instanceId: instanceId)) - } - - static func loadGatewayPassword(instanceId: String) -> String? { - KeychainStore.loadString( - service: self.gatewayService, - account: self.gatewayPasswordAccount(instanceId: instanceId))? - .trimmingCharacters(in: .whitespacesAndNewlines) - } - - static func saveGatewayPassword(_ password: String, instanceId: String) { - _ = KeychainStore.saveString( - password, - service: self.gatewayService, - account: self.gatewayPasswordAccount(instanceId: instanceId)) - } - - enum LastGatewayConnection: Equatable { - case manual(host: String, port: Int, useTLS: Bool, stableID: String) - case discovered(stableID: String, useTLS: Bool) - - var stableID: String { - switch self { - case let .manual(_, _, _, stableID): - return stableID - case let .discovered(stableID, _): - return stableID - } - } - - var useTLS: Bool { - switch self { - case let .manual(_, _, useTLS, _): - return useTLS - case let .discovered(_, useTLS): - return useTLS - } - } - } - - private enum LastGatewayKind: String { - case manual - case discovered - } - - static func loadTalkElevenLabsApiKey() -> String? { - let value = KeychainStore.loadString( - service: self.talkService, - account: self.talkElevenLabsApiKeyAccount)? - .trimmingCharacters(in: .whitespacesAndNewlines) - if value?.isEmpty == false { return value } - return nil - } - - static func saveTalkElevenLabsApiKey(_ apiKey: String?) { - let trimmed = apiKey?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if trimmed.isEmpty { - _ = KeychainStore.delete(service: self.talkService, account: self.talkElevenLabsApiKeyAccount) - return - } - _ = KeychainStore.saveString( - trimmed, - service: self.talkService, - account: self.talkElevenLabsApiKeyAccount) - } - - static func saveLastGatewayConnectionManual(host: String, port: Int, useTLS: Bool, stableID: String) { - let defaults = UserDefaults.standard - defaults.set(LastGatewayKind.manual.rawValue, forKey: self.lastGatewayKindDefaultsKey) - defaults.set(host, forKey: self.lastGatewayHostDefaultsKey) - defaults.set(port, forKey: self.lastGatewayPortDefaultsKey) - defaults.set(useTLS, forKey: self.lastGatewayTlsDefaultsKey) - defaults.set(stableID, forKey: self.lastGatewayStableIDDefaultsKey) - } - - static func saveLastGatewayConnectionDiscovered(stableID: String, useTLS: Bool) { - let defaults = UserDefaults.standard - defaults.set(LastGatewayKind.discovered.rawValue, forKey: self.lastGatewayKindDefaultsKey) - defaults.removeObject(forKey: self.lastGatewayHostDefaultsKey) - defaults.removeObject(forKey: self.lastGatewayPortDefaultsKey) - defaults.set(useTLS, forKey: self.lastGatewayTlsDefaultsKey) - defaults.set(stableID, forKey: self.lastGatewayStableIDDefaultsKey) - } - - static func loadLastGatewayConnection() -> LastGatewayConnection? { - let defaults = UserDefaults.standard - let stableID = defaults.string(forKey: self.lastGatewayStableIDDefaultsKey)? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - guard !stableID.isEmpty else { return nil } - let useTLS = defaults.bool(forKey: self.lastGatewayTlsDefaultsKey) - let kindRaw = defaults.string(forKey: self.lastGatewayKindDefaultsKey)? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let kind = LastGatewayKind(rawValue: kindRaw) ?? .manual - - if kind == .discovered { - return .discovered(stableID: stableID, useTLS: useTLS) - } - - let host = defaults.string(forKey: self.lastGatewayHostDefaultsKey)? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let port = defaults.integer(forKey: self.lastGatewayPortDefaultsKey) - - // Back-compat: older builds persisted manual-style host/port without a kind marker. - guard !host.isEmpty, port > 0, port <= 65535 else { return nil } - return .manual(host: host, port: port, useTLS: useTLS, stableID: stableID) - } - - static func clearLastGatewayConnection(defaults: UserDefaults = .standard) { - defaults.removeObject(forKey: self.lastGatewayKindDefaultsKey) - defaults.removeObject(forKey: self.lastGatewayHostDefaultsKey) - defaults.removeObject(forKey: self.lastGatewayPortDefaultsKey) - defaults.removeObject(forKey: self.lastGatewayTlsDefaultsKey) - defaults.removeObject(forKey: self.lastGatewayStableIDDefaultsKey) - } - - static func deleteGatewayCredentials(instanceId: String) { - let trimmed = instanceId.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return } - _ = KeychainStore.delete( - service: self.gatewayService, - account: self.gatewayTokenAccount(instanceId: trimmed)) - _ = KeychainStore.delete( - service: self.gatewayService, - account: self.gatewayPasswordAccount(instanceId: trimmed)) - } - - static func loadGatewayClientIdOverride(stableID: String) -> String? { - let trimmedID = stableID.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmedID.isEmpty else { return nil } - let key = self.clientIdOverrideDefaultsPrefix + trimmedID - let value = UserDefaults.standard.string(forKey: key)? - .trimmingCharacters(in: .whitespacesAndNewlines) - if value?.isEmpty == false { return value } - return nil - } - - static func saveGatewayClientIdOverride(stableID: String, clientId: String?) { - let trimmedID = stableID.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmedID.isEmpty else { return } - let key = self.clientIdOverrideDefaultsPrefix + trimmedID - let trimmedClientId = clientId?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if trimmedClientId.isEmpty { - UserDefaults.standard.removeObject(forKey: key) - } else { - UserDefaults.standard.set(trimmedClientId, forKey: key) - } - } - - static func loadGatewaySelectedAgentId(stableID: String) -> String? { - let trimmedID = stableID.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmedID.isEmpty else { return nil } - let key = self.selectedAgentDefaultsPrefix + trimmedID - let value = UserDefaults.standard.string(forKey: key)? - .trimmingCharacters(in: .whitespacesAndNewlines) - if value?.isEmpty == false { return value } - return nil - } - - static func saveGatewaySelectedAgentId(stableID: String, agentId: String?) { - let trimmedID = stableID.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmedID.isEmpty else { return } - let key = self.selectedAgentDefaultsPrefix + trimmedID - let trimmedAgentId = agentId?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if trimmedAgentId.isEmpty { - UserDefaults.standard.removeObject(forKey: key) - } else { - UserDefaults.standard.set(trimmedAgentId, forKey: key) - } - } - - private static func gatewayTokenAccount(instanceId: String) -> String { - "gateway-token.\(instanceId)" - } - - private static func gatewayPasswordAccount(instanceId: String) -> String { - "gateway-password.\(instanceId)" - } - - private static func ensureStableInstanceID() { - let defaults = UserDefaults.standard - - if let existing = defaults.string(forKey: self.instanceIdDefaultsKey)? - .trimmingCharacters(in: .whitespacesAndNewlines), - !existing.isEmpty - { - if self.loadStableInstanceID() == nil { - self.saveStableInstanceID(existing) - } - return - } - - if let stored = self.loadStableInstanceID(), !stored.isEmpty { - defaults.set(stored, forKey: self.instanceIdDefaultsKey) - return - } - - let fresh = UUID().uuidString - self.saveStableInstanceID(fresh) - defaults.set(fresh, forKey: self.instanceIdDefaultsKey) - } - - private static func ensurePreferredGatewayStableID() { - let defaults = UserDefaults.standard - - if let existing = defaults.string(forKey: self.preferredGatewayStableIDDefaultsKey)? - .trimmingCharacters(in: .whitespacesAndNewlines), - !existing.isEmpty - { - if self.loadPreferredGatewayStableID() == nil { - self.savePreferredGatewayStableID(existing) - } - return - } - - if let stored = self.loadPreferredGatewayStableID(), !stored.isEmpty { - defaults.set(stored, forKey: self.preferredGatewayStableIDDefaultsKey) - } - } - - private static func ensureLastDiscoveredGatewayStableID() { - let defaults = UserDefaults.standard - - if let existing = defaults.string(forKey: self.lastDiscoveredGatewayStableIDDefaultsKey)? - .trimmingCharacters(in: .whitespacesAndNewlines), - !existing.isEmpty - { - if self.loadLastDiscoveredGatewayStableID() == nil { - self.saveLastDiscoveredGatewayStableID(existing) - } - return - } - - if let stored = self.loadLastDiscoveredGatewayStableID(), !stored.isEmpty { - defaults.set(stored, forKey: self.lastDiscoveredGatewayStableIDDefaultsKey) - } - } - -} - -enum GatewayDiagnostics { - private static let logger = Logger(subsystem: "ai.openclaw.ios", category: "GatewayDiag") - private static let queue = DispatchQueue(label: "ai.openclaw.gateway.diagnostics") - private static let maxLogBytes: Int64 = 512 * 1024 - private static let keepLogBytes: Int64 = 256 * 1024 - private static let logSizeCheckEveryWrites = 50 - nonisolated(unsafe) private static var logWritesSinceCheck = 0 - private static var fileURL: URL? { - FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first? - .appendingPathComponent("openclaw-gateway.log") - } - - private static func truncateLogIfNeeded(url: URL) { - guard let attrs = try? FileManager.default.attributesOfItem(atPath: url.path), - let sizeNumber = attrs[.size] as? NSNumber - else { return } - let size = sizeNumber.int64Value - guard size > self.maxLogBytes else { return } - - do { - let handle = try FileHandle(forReadingFrom: url) - defer { try? handle.close() } - - let start = max(Int64(0), size - self.keepLogBytes) - try handle.seek(toOffset: UInt64(start)) - var tail = try handle.readToEnd() ?? Data() - - // If we truncated mid-line, drop the first partial line so logs remain readable. - if start > 0, let nl = tail.firstIndex(of: 10) { - let next = tail.index(after: nl) - if next < tail.endIndex { - tail = tail.suffix(from: next) - } else { - tail = Data() - } - } - - try tail.write(to: url, options: .atomic) - } catch { - // Best-effort only. - } - } - - private static func appendToLog(url: URL, data: Data) { - if FileManager.default.fileExists(atPath: url.path) { - if let handle = try? FileHandle(forWritingTo: url) { - defer { try? handle.close() } - _ = try? handle.seekToEnd() - try? handle.write(contentsOf: data) - } - } else { - try? data.write(to: url, options: .atomic) - } - } - - static func bootstrap() { - guard let url = fileURL else { return } - queue.async { - self.truncateLogIfNeeded(url: url) - let formatter = ISO8601DateFormatter() - formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] - let timestamp = formatter.string(from: Date()) - let line = "[\(timestamp)] gateway diagnostics started\n" - if let data = line.data(using: .utf8) { - self.appendToLog(url: url, data: data) - } - } - } - - static func log(_ message: String) { - let formatter = ISO8601DateFormatter() - formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] - let timestamp = formatter.string(from: Date()) - let line = "[\(timestamp)] \(message)" - logger.info("\(line, privacy: .public)") - - guard let url = fileURL else { return } - queue.async { - self.logWritesSinceCheck += 1 - if self.logWritesSinceCheck >= self.logSizeCheckEveryWrites { - self.logWritesSinceCheck = 0 - self.truncateLogIfNeeded(url: url) - } - let entry = line + "\n" - if let data = entry.data(using: .utf8) { - self.appendToLog(url: url, data: data) - } - } - } - - static func reset() { - guard let url = fileURL else { return } - queue.async { - try? FileManager.default.removeItem(at: url) - } - } -} diff --git a/apps/ios/Sources/Gateway/GatewaySetupCode.swift b/apps/ios/Sources/Gateway/GatewaySetupCode.swift deleted file mode 100644 index 8ccbab42da7..00000000000 --- a/apps/ios/Sources/Gateway/GatewaySetupCode.swift +++ /dev/null @@ -1,42 +0,0 @@ -import Foundation - -struct GatewaySetupPayload: Codable { - var url: String? - var host: String? - var port: Int? - var tls: Bool? - var token: String? - var password: String? -} - -enum GatewaySetupCode { - static func decode(raw: String) -> GatewaySetupPayload? { - if let payload = decodeFromJSON(raw) { - return payload - } - if let decoded = decodeBase64Payload(raw), - let payload = decodeFromJSON(decoded) - { - return payload - } - return nil - } - - private static func decodeFromJSON(_ json: String) -> GatewaySetupPayload? { - guard let data = json.data(using: .utf8) else { return nil } - return try? JSONDecoder().decode(GatewaySetupPayload.self, from: data) - } - - private static func decodeBase64Payload(_ raw: String) -> String? { - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - let normalized = trimmed - .replacingOccurrences(of: "-", with: "+") - .replacingOccurrences(of: "_", with: "/") - let padding = normalized.count % 4 - let padded = padding == 0 ? normalized : normalized + String(repeating: "=", count: 4 - padding) - guard let data = Data(base64Encoded: padded) else { return nil } - return String(data: data, encoding: .utf8) - } -} - diff --git a/apps/ios/Sources/Gateway/GatewayTrustPromptAlert.swift b/apps/ios/Sources/Gateway/GatewayTrustPromptAlert.swift deleted file mode 100644 index eff6b71bad5..00000000000 --- a/apps/ios/Sources/Gateway/GatewayTrustPromptAlert.swift +++ /dev/null @@ -1,41 +0,0 @@ -import SwiftUI - -struct GatewayTrustPromptAlert: ViewModifier { - @Environment(GatewayConnectionController.self) private var gatewayController: GatewayConnectionController - - private var promptBinding: Binding { - Binding( - get: { self.gatewayController.pendingTrustPrompt }, - set: { _ in - // Keep pending trust state until explicit user action. - // `alert(item:)` may set the binding to nil during dismissal, which can race with - // the button handler and cause accept to no-op. - }) - } - - func body(content: Content) -> some View { - content.alert(item: self.promptBinding) { prompt in - Alert( - title: Text("Trust this gateway?"), - message: Text( - """ - First-time TLS connection. - - Verify this SHA-256 fingerprint out-of-band before trusting: - \(prompt.fingerprintSha256) - """), - primaryButton: .cancel(Text("Cancel")) { - self.gatewayController.declinePendingTrustPrompt() - }, - secondaryButton: .default(Text("Trust and connect")) { - Task { await self.gatewayController.acceptPendingTrustPrompt() } - }) - } - } -} - -extension View { - func gatewayTrustPromptAlert() -> some View { - self.modifier(GatewayTrustPromptAlert()) - } -} diff --git a/apps/ios/Sources/Gateway/KeychainStore.swift b/apps/ios/Sources/Gateway/KeychainStore.swift deleted file mode 100644 index 1377d8517ef..00000000000 --- a/apps/ios/Sources/Gateway/KeychainStore.swift +++ /dev/null @@ -1,48 +0,0 @@ -import Foundation -import Security - -enum KeychainStore { - static func loadString(service: String, account: String) -> String? { - let query: [String: Any] = [ - kSecClass as String: kSecClassGenericPassword, - kSecAttrService as String: service, - kSecAttrAccount as String: account, - kSecReturnData as String: true, - kSecMatchLimit as String: kSecMatchLimitOne, - ] - - var item: CFTypeRef? - let status = SecItemCopyMatching(query as CFDictionary, &item) - guard status == errSecSuccess, let data = item as? Data else { return nil } - return String(data: data, encoding: .utf8) - } - - static func saveString(_ value: String, service: String, account: String) -> Bool { - let data = Data(value.utf8) - let query: [String: Any] = [ - kSecClass as String: kSecClassGenericPassword, - kSecAttrService as String: service, - kSecAttrAccount as String: account, - ] - - let update: [String: Any] = [kSecValueData as String: data] - let status = SecItemUpdate(query as CFDictionary, update as CFDictionary) - if status == errSecSuccess { return true } - if status != errSecItemNotFound { return false } - - var insert = query - insert[kSecValueData as String] = data - insert[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly - return SecItemAdd(insert as CFDictionary, nil) == errSecSuccess - } - - static func delete(service: String, account: String) -> Bool { - let query: [String: Any] = [ - kSecClass as String: kSecClassGenericPassword, - kSecAttrService as String: service, - kSecAttrAccount as String: account, - ] - let status = SecItemDelete(query as CFDictionary) - return status == errSecSuccess || status == errSecItemNotFound - } -} diff --git a/apps/ios/Sources/Gateway/TCPProbe.swift b/apps/ios/Sources/Gateway/TCPProbe.swift deleted file mode 100644 index e22da96298f..00000000000 --- a/apps/ios/Sources/Gateway/TCPProbe.swift +++ /dev/null @@ -1,43 +0,0 @@ -import Foundation -import Network -import os - -enum TCPProbe { - static func probe(host: String, port: Int, timeoutSeconds: Double, queueLabel: String) async -> Bool { - guard port >= 1, port <= 65535 else { return false } - guard let nwPort = NWEndpoint.Port(rawValue: UInt16(port)) else { return false } - - let endpointHost = NWEndpoint.Host(host) - let connection = NWConnection(host: endpointHost, port: nwPort, using: .tcp) - - return await withCheckedContinuation { cont in - let queue = DispatchQueue(label: queueLabel) - let finished = OSAllocatedUnfairLock(initialState: false) - let finish: @Sendable (Bool) -> Void = { ok in - let shouldResume = finished.withLock { flag -> Bool in - if flag { return false } - flag = true - return true - } - guard shouldResume else { return } - connection.cancel() - cont.resume(returning: ok) - } - - connection.stateUpdateHandler = { state in - switch state { - case .ready: - finish(true) - case .failed, .cancelled: - finish(false) - default: - break - } - } - - connection.start(queue: queue) - queue.asyncAfter(deadline: .now() + timeoutSeconds) { finish(false) } - } - } -} - diff --git a/apps/ios/Sources/Info.plist b/apps/ios/Sources/Info.plist deleted file mode 100644 index c3b469e7092..00000000000 --- a/apps/ios/Sources/Info.plist +++ /dev/null @@ -1,88 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - OpenClaw - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconName - AppIcon - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 2026.2.21 - CFBundleURLTypes - - - CFBundleURLName - ai.openclaw.ios - CFBundleURLSchemes - - openclaw - - - - CFBundleVersion - 20260220 - NSAppTransportSecurity - - NSAllowsArbitraryLoadsInWebContent - - - NSBonjourServices - - _openclaw-gw._tcp - - NSCameraUsageDescription - OpenClaw can capture photos or short video clips when requested via the gateway. - NSLocalNetworkUsageDescription - OpenClaw discovers and connects to your OpenClaw gateway on the local network. - NSLocationAlwaysAndWhenInUseUsageDescription - OpenClaw can share your location in the background when you enable Always. - NSLocationWhenInUseUsageDescription - OpenClaw uses your location when you allow location sharing. - NSMicrophoneUsageDescription - OpenClaw needs microphone access for voice wake. - NSSpeechRecognitionUsageDescription - OpenClaw uses on-device speech recognition for voice wake. - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - - UIBackgroundModes - - audio - remote-notification - - BGTaskSchedulerPermittedIdentifiers - - ai.openclaw.ios.bgrefresh - - UILaunchScreen - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/apps/ios/Sources/Location/LocationService.swift b/apps/ios/Sources/Location/LocationService.swift deleted file mode 100644 index f1f0f69ed7f..00000000000 --- a/apps/ios/Sources/Location/LocationService.swift +++ /dev/null @@ -1,202 +0,0 @@ -import OpenClawKit -import CoreLocation -import Foundation - -@MainActor -final class LocationService: NSObject, CLLocationManagerDelegate { - enum Error: Swift.Error { - case timeout - case unavailable - } - - private let manager = CLLocationManager() - private var authContinuation: CheckedContinuation? - private var locationContinuation: CheckedContinuation? - private var updatesContinuation: AsyncStream.Continuation? - private var isStreaming = false - private var significantLocationCallback: (@Sendable (CLLocation) -> Void)? - private var isMonitoringSignificantChanges = false - - override init() { - super.init() - self.manager.delegate = self - self.manager.desiredAccuracy = kCLLocationAccuracyBest - } - - func authorizationStatus() -> CLAuthorizationStatus { - self.manager.authorizationStatus - } - - func accuracyAuthorization() -> CLAccuracyAuthorization { - if #available(iOS 14.0, *) { - return self.manager.accuracyAuthorization - } - return .fullAccuracy - } - - func ensureAuthorization(mode: OpenClawLocationMode) async -> CLAuthorizationStatus { - guard CLLocationManager.locationServicesEnabled() else { return .denied } - - let status = self.manager.authorizationStatus - if status == .notDetermined { - self.manager.requestWhenInUseAuthorization() - let updated = await self.awaitAuthorizationChange() - if mode != .always { return updated } - } - - if mode == .always { - let current = self.manager.authorizationStatus - if current == .authorizedWhenInUse { - self.manager.requestAlwaysAuthorization() - return await self.awaitAuthorizationChange() - } - return current - } - - return self.manager.authorizationStatus - } - - func currentLocation( - params: OpenClawLocationGetParams, - desiredAccuracy: OpenClawLocationAccuracy, - maxAgeMs: Int?, - timeoutMs: Int?) async throws -> CLLocation - { - let now = Date() - if let maxAgeMs, - let cached = self.manager.location, - now.timeIntervalSince(cached.timestamp) * 1000 <= Double(maxAgeMs) - { - return cached - } - - self.manager.desiredAccuracy = Self.accuracyValue(desiredAccuracy) - let timeout = max(0, timeoutMs ?? 10000) - return try await self.withTimeout(timeoutMs: timeout) { - try await self.requestLocation() - } - } - - private func requestLocation() async throws -> CLLocation { - try await withCheckedThrowingContinuation { cont in - self.locationContinuation = cont - self.manager.requestLocation() - } - } - - private func awaitAuthorizationChange() async -> CLAuthorizationStatus { - await withCheckedContinuation { cont in - self.authContinuation = cont - } - } - - private func withTimeout( - timeoutMs: Int, - operation: @escaping @Sendable () async throws -> T) async throws -> T - { - try await AsyncTimeout.withTimeoutMs(timeoutMs: timeoutMs, onTimeout: { Error.timeout }, operation: operation) - } - - private static func accuracyValue(_ accuracy: OpenClawLocationAccuracy) -> CLLocationAccuracy { - switch accuracy { - case .coarse: - kCLLocationAccuracyKilometer - case .balanced: - kCLLocationAccuracyHundredMeters - case .precise: - kCLLocationAccuracyBest - } - } - - func startLocationUpdates( - desiredAccuracy: OpenClawLocationAccuracy, - significantChangesOnly: Bool) -> AsyncStream - { - self.stopLocationUpdates() - - self.manager.desiredAccuracy = Self.accuracyValue(desiredAccuracy) - self.manager.pausesLocationUpdatesAutomatically = true - self.manager.allowsBackgroundLocationUpdates = true - - self.isStreaming = true - if significantChangesOnly { - self.manager.startMonitoringSignificantLocationChanges() - } else { - self.manager.startUpdatingLocation() - } - - return AsyncStream(bufferingPolicy: .bufferingNewest(1)) { continuation in - self.updatesContinuation = continuation - continuation.onTermination = { @Sendable _ in - Task { @MainActor in - self.stopLocationUpdates() - } - } - } - } - - func stopLocationUpdates() { - guard self.isStreaming else { return } - self.isStreaming = false - self.manager.stopUpdatingLocation() - self.manager.stopMonitoringSignificantLocationChanges() - self.updatesContinuation?.finish() - self.updatesContinuation = nil - } - - func startMonitoringSignificantLocationChanges(onUpdate: @escaping @Sendable (CLLocation) -> Void) { - self.significantLocationCallback = onUpdate - guard !self.isMonitoringSignificantChanges else { return } - self.isMonitoringSignificantChanges = true - self.manager.startMonitoringSignificantLocationChanges() - } - - func stopMonitoringSignificantLocationChanges() { - guard self.isMonitoringSignificantChanges else { return } - self.isMonitoringSignificantChanges = false - self.significantLocationCallback = nil - self.manager.stopMonitoringSignificantLocationChanges() - } - - nonisolated func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { - let status = manager.authorizationStatus - Task { @MainActor in - if let cont = self.authContinuation { - self.authContinuation = nil - cont.resume(returning: status) - } - } - } - - nonisolated func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { - let locs = locations - Task { @MainActor in - // Resolve the one-shot continuation first (if any). - if let cont = self.locationContinuation { - self.locationContinuation = nil - if let latest = locs.last { - cont.resume(returning: latest) - } else { - cont.resume(throwing: Error.unavailable) - } - // Don't return — also forward to significant-change callback below - // so both consumers receive updates when both are active. - } - if let callback = self.significantLocationCallback, let latest = locs.last { - callback(latest) - } - if let latest = locs.last, let updates = self.updatesContinuation { - updates.yield(latest) - } - } - } - - nonisolated func locationManager(_ manager: CLLocationManager, didFailWithError error: Swift.Error) { - let err = error - Task { @MainActor in - guard let cont = self.locationContinuation else { return } - self.locationContinuation = nil - cont.resume(throwing: err) - } - } -} diff --git a/apps/ios/Sources/Location/SignificantLocationMonitor.swift b/apps/ios/Sources/Location/SignificantLocationMonitor.swift deleted file mode 100644 index 1b8d5ca2a0d..00000000000 --- a/apps/ios/Sources/Location/SignificantLocationMonitor.swift +++ /dev/null @@ -1,42 +0,0 @@ -import CoreLocation -import Foundation -import OpenClawKit - -/// Monitors significant location changes and pushes `location.update` -/// events to the gateway so the severance hook can determine whether -/// the user is at their configured work location. -@MainActor -enum SignificantLocationMonitor { - static func startIfNeeded( - locationService: any LocationServicing, - locationMode: OpenClawLocationMode, - gateway: GatewayNodeSession, - beforeSend: (@MainActor @Sendable () async -> Void)? = nil - ) { - guard locationMode == .always else { return } - let status = locationService.authorizationStatus() - guard status == .authorizedAlways else { return } - locationService.startMonitoringSignificantLocationChanges { location in - struct Payload: Codable { - var lat: Double - var lon: Double - var accuracyMeters: Double - var source: String? - } - let payload = Payload( - lat: location.coordinate.latitude, - lon: location.coordinate.longitude, - accuracyMeters: location.horizontalAccuracy, - source: "ios-significant-location") - guard let data = try? JSONEncoder().encode(payload), - let json = String(data: data, encoding: .utf8) - else { return } - Task { @MainActor in - if let beforeSend { - await beforeSend() - } - await gateway.sendEvent(event: "location.update", payloadJSON: json) - } - } - } -} diff --git a/apps/ios/Sources/Media/PhotoLibraryService.swift b/apps/ios/Sources/Media/PhotoLibraryService.swift deleted file mode 100644 index f66beb3e707..00000000000 --- a/apps/ios/Sources/Media/PhotoLibraryService.swift +++ /dev/null @@ -1,164 +0,0 @@ -import Foundation -import Photos -import OpenClawKit -import UIKit - -final class PhotoLibraryService: PhotosServicing { - // The gateway WebSocket has a max payload size; returning large base64 blobs - // can cause the gateway to close the connection. Keep photo payloads small - // enough to safely fit in a single RPC frame. - // - // This is a transport constraint (not a security policy). If callers need - // full-resolution media, we should switch to an HTTP media handle flow. - private static let maxTotalBase64Chars = 340 * 1024 - private static let maxPerPhotoBase64Chars = 300 * 1024 - - func latest(params: OpenClawPhotosLatestParams) async throws -> OpenClawPhotosLatestPayload { - let status = await Self.ensureAuthorization() - guard status == .authorized || status == .limited else { - throw NSError(domain: "Photos", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "PHOTOS_PERMISSION_REQUIRED: grant Photos permission", - ]) - } - - let limit = max(1, min(params.limit ?? 1, 20)) - let fetchOptions = PHFetchOptions() - fetchOptions.fetchLimit = limit - fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)] - let assets = PHAsset.fetchAssets(with: .image, options: fetchOptions) - - var results: [OpenClawPhotoPayload] = [] - var remainingBudget = Self.maxTotalBase64Chars - let maxWidth = params.maxWidth.flatMap { $0 > 0 ? $0 : nil } ?? 1600 - let quality = params.quality.map { max(0.1, min(1.0, $0)) } ?? 0.85 - let formatter = ISO8601DateFormatter() - - assets.enumerateObjects { asset, _, stop in - if results.count >= limit { stop.pointee = true; return } - if let payload = try? Self.renderAsset( - asset, - maxWidth: maxWidth, - quality: quality, - formatter: formatter) - { - // Keep the entire response under the gateway WS max payload. - if payload.base64.count > remainingBudget { - stop.pointee = true - return - } - remainingBudget -= payload.base64.count - results.append(payload) - } - } - - return OpenClawPhotosLatestPayload(photos: results) - } - - private static func ensureAuthorization() async -> PHAuthorizationStatus { - // Don’t prompt during node.invoke; prompts block the invoke and lead to timeouts. - PHPhotoLibrary.authorizationStatus(for: .readWrite) - } - - private static func renderAsset( - _ asset: PHAsset, - maxWidth: Int, - quality: Double, - formatter: ISO8601DateFormatter) throws -> OpenClawPhotoPayload - { - let manager = PHImageManager.default() - let options = PHImageRequestOptions() - options.isSynchronous = true - options.isNetworkAccessAllowed = true - options.deliveryMode = .highQualityFormat - - let targetSize: CGSize = { - guard maxWidth > 0 else { return PHImageManagerMaximumSize } - let aspect = CGFloat(asset.pixelHeight) / CGFloat(max(1, asset.pixelWidth)) - let width = CGFloat(maxWidth) - return CGSize(width: width, height: width * aspect) - }() - - var image: UIImage? - manager.requestImage( - for: asset, - targetSize: targetSize, - contentMode: .aspectFit, - options: options) - { result, _ in - image = result - } - - guard let image else { - throw NSError(domain: "Photos", code: 2, userInfo: [ - NSLocalizedDescriptionKey: "photo load failed", - ]) - } - - let (data, finalImage) = try encodeJpegUnderBudget( - image: image, - quality: quality, - maxBase64Chars: maxPerPhotoBase64Chars) - - let created = asset.creationDate.map { formatter.string(from: $0) } - return OpenClawPhotoPayload( - format: "jpeg", - base64: data.base64EncodedString(), - width: Int(finalImage.size.width), - height: Int(finalImage.size.height), - createdAt: created) - } - - private static func encodeJpegUnderBudget( - image: UIImage, - quality: Double, - maxBase64Chars: Int) throws -> (Data, UIImage) - { - var currentImage = image - var currentQuality = max(0.1, min(1.0, quality)) - - // Try lowering JPEG quality first, then downscale if needed. - for _ in 0..<10 { - guard let data = currentImage.jpegData(compressionQuality: currentQuality) else { - throw NSError(domain: "Photos", code: 3, userInfo: [ - NSLocalizedDescriptionKey: "photo encode failed", - ]) - } - - let base64Len = ((data.count + 2) / 3) * 4 - if base64Len <= maxBase64Chars { - return (data, currentImage) - } - - if currentQuality > 0.35 { - currentQuality = max(0.25, currentQuality - 0.15) - continue - } - - // Downscale by ~25% each step once quality is low. - let newWidth = max(240, currentImage.size.width * 0.75) - if newWidth >= currentImage.size.width { - break - } - currentImage = resize(image: currentImage, targetWidth: newWidth) - } - - throw NSError(domain: "Photos", code: 4, userInfo: [ - NSLocalizedDescriptionKey: "photo too large for gateway transport; try smaller maxWidth/quality", - ]) - } - - private static func resize(image: UIImage, targetWidth: CGFloat) -> UIImage { - let size = image.size - if size.width <= 0 || size.height <= 0 || targetWidth <= 0 { - return image - } - let scale = targetWidth / size.width - let targetSize = CGSize(width: targetWidth, height: max(1, size.height * scale)) - let format = UIGraphicsImageRendererFormat.default() - format.scale = 1 - let renderer = UIGraphicsImageRenderer(size: targetSize, format: format) - return renderer.image { _ in - image.draw(in: CGRect(origin: .zero, size: targetSize)) - } - } -} diff --git a/apps/ios/Sources/Model/NodeAppModel+Canvas.swift b/apps/ios/Sources/Model/NodeAppModel+Canvas.swift deleted file mode 100644 index e8dce2cd30c..00000000000 --- a/apps/ios/Sources/Model/NodeAppModel+Canvas.swift +++ /dev/null @@ -1,70 +0,0 @@ -import Foundation -import Network -import os - -extension NodeAppModel { - func _test_resolveA2UIHostURL() async -> String? { - await self.resolveA2UIHostURL() - } - - func resolveA2UIHostURL() async -> String? { - guard let raw = await self.gatewaySession.currentCanvasHostUrl() else { return nil } - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty, let base = URL(string: trimmed) else { return nil } - if let host = base.host, Self.isLoopbackHost(host) { - return nil - } - return base.appendingPathComponent("__openclaw__/a2ui/").absoluteString + "?platform=ios" - } - - private static func isLoopbackHost(_ host: String) -> Bool { - let normalized = host.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - if normalized.isEmpty { return true } - if normalized == "localhost" || normalized == "::1" || normalized == "0.0.0.0" { - return true - } - if normalized == "127.0.0.1" || normalized.hasPrefix("127.") { - return true - } - return false - } - - func showA2UIOnConnectIfNeeded() async { - guard let a2uiUrl = await self.resolveA2UIHostURL() else { - await MainActor.run { - self.lastAutoA2uiURL = nil - self.screen.showDefaultCanvas() - } - return - } - let current = self.screen.urlString.trimmingCharacters(in: .whitespacesAndNewlines) - if current.isEmpty || current == self.lastAutoA2uiURL { - // Avoid navigating the WKWebView to an unreachable host: it leaves a persistent - // "could not connect to the server" overlay even when the gateway is connected. - if let url = URL(string: a2uiUrl), - await Self.probeTCP(url: url, timeoutSeconds: 2.5) - { - self.screen.navigate(to: a2uiUrl) - self.lastAutoA2uiURL = a2uiUrl - } else { - self.lastAutoA2uiURL = nil - self.screen.showDefaultCanvas() - } - } - } - - func showLocalCanvasOnDisconnect() { - self.lastAutoA2uiURL = nil - self.screen.showDefaultCanvas() - } - - private static func probeTCP(url: URL, timeoutSeconds: Double) async -> Bool { - guard let host = url.host, !host.isEmpty else { return false } - let portInt = url.port ?? ((url.scheme ?? "").lowercased() == "wss" ? 443 : 80) - return await TCPProbe.probe( - host: host, - port: portInt, - timeoutSeconds: timeoutSeconds, - queueLabel: "a2ui.preflight") - } -} diff --git a/apps/ios/Sources/Model/NodeAppModel.swift b/apps/ios/Sources/Model/NodeAppModel.swift deleted file mode 100644 index 5bd98e6f492..00000000000 --- a/apps/ios/Sources/Model/NodeAppModel.swift +++ /dev/null @@ -1,2611 +0,0 @@ -import OpenClawChatUI -import OpenClawKit -import OpenClawProtocol -import Observation -import os -import SwiftUI -import UIKit -import UserNotifications - -// Wrap errors without pulling non-Sendable types into async notification paths. -private struct NotificationCallError: Error, Sendable { - let message: String -} -// Ensures notification requests return promptly even if the system prompt blocks. -private final class NotificationInvokeLatch: @unchecked Sendable { - private let lock = NSLock() - private var continuation: CheckedContinuation, Never>? - private var resumed = false - - func setContinuation(_ continuation: CheckedContinuation, Never>) { - self.lock.lock() - defer { self.lock.unlock() } - self.continuation = continuation - } - - func resume(_ response: Result) { - let cont: CheckedContinuation, Never>? - self.lock.lock() - if self.resumed { - self.lock.unlock() - return - } - self.resumed = true - cont = self.continuation - self.continuation = nil - self.lock.unlock() - cont?.resume(returning: response) - } -} -@MainActor -@Observable -final class NodeAppModel { - private let deepLinkLogger = Logger(subsystem: "ai.openclaw.ios", category: "DeepLink") - private let pushWakeLogger = Logger(subsystem: "ai.openclaw.ios", category: "PushWake") - private let locationWakeLogger = Logger(subsystem: "ai.openclaw.ios", category: "LocationWake") - private let watchReplyLogger = Logger(subsystem: "ai.openclaw.ios", category: "WatchReply") - enum CameraHUDKind { - case photo - case recording - case success - case error - } - - var isBackgrounded: Bool = false - let screen: ScreenController - private let camera: any CameraServicing - private let screenRecorder: any ScreenRecordingServicing - var gatewayStatusText: String = "Offline" - var nodeStatusText: String = "Offline" - var operatorStatusText: String = "Offline" - var gatewayServerName: String? - var gatewayRemoteAddress: String? - var connectedGatewayID: String? - var gatewayAutoReconnectEnabled: Bool = true - // When the gateway requires pairing approval, we pause reconnect churn and show a stable UX. - // Reconnect loops (both our own and the underlying WebSocket watchdog) can otherwise generate - // multiple pending requests and cause the onboarding UI to "flip-flop". - var gatewayPairingPaused: Bool = false - var gatewayPairingRequestId: String? - var seamColorHex: String? - private var mainSessionBaseKey: String = "main" - var selectedAgentId: String? - var gatewayDefaultAgentId: String? - var gatewayAgents: [AgentSummary] = [] - var lastShareEventText: String = "No share events yet." - var openChatRequestID: Int = 0 - - // Primary "node" connection: used for device capabilities and node.invoke requests. - private let nodeGateway = GatewayNodeSession() - // Secondary "operator" connection: used for chat/talk/config/voicewake requests. - private let operatorGateway = GatewayNodeSession() - private var nodeGatewayTask: Task? - private var operatorGatewayTask: Task? - private var voiceWakeSyncTask: Task? - @ObservationIgnored private var cameraHUDDismissTask: Task? - @ObservationIgnored private lazy var capabilityRouter: NodeCapabilityRouter = self.buildCapabilityRouter() - private let gatewayHealthMonitor = GatewayHealthMonitor() - private var gatewayHealthMonitorDisabled = false - private let notificationCenter: NotificationCentering - let voiceWake = VoiceWakeManager() - let talkMode: TalkModeManager - private let locationService: any LocationServicing - private let deviceStatusService: any DeviceStatusServicing - private let photosService: any PhotosServicing - private let contactsService: any ContactsServicing - private let calendarService: any CalendarServicing - private let remindersService: any RemindersServicing - private let motionService: any MotionServicing - private let watchMessagingService: any WatchMessagingServicing - var lastAutoA2uiURL: String? - private var pttVoiceWakeSuspended = false - private var talkVoiceWakeSuspended = false - private var backgroundVoiceWakeSuspended = false - private var backgroundTalkSuspended = false - private var backgroundTalkKeptActive = false - private var backgroundedAt: Date? - private var reconnectAfterBackgroundArmed = false - private var backgroundGraceTaskID: UIBackgroundTaskIdentifier = .invalid - @ObservationIgnored private var backgroundGraceTaskTimer: Task? - private var backgroundReconnectSuppressed = false - private var backgroundReconnectLeaseUntil: Date? - private var lastSignificantLocationWakeAt: Date? - private var queuedWatchReplies: [WatchQuickReplyEvent] = [] - private var seenWatchReplyIds = Set() - - private var gatewayConnected = false - private var operatorConnected = false - private var shareDeliveryChannel: String? - private var shareDeliveryTo: String? - private var apnsDeviceTokenHex: String? - private var apnsLastRegisteredTokenHex: String? - var gatewaySession: GatewayNodeSession { self.nodeGateway } - var operatorSession: GatewayNodeSession { self.operatorGateway } - private(set) var activeGatewayConnectConfig: GatewayConnectConfig? - - var cameraHUDText: String? - var cameraHUDKind: CameraHUDKind? - var cameraFlashNonce: Int = 0 - var screenRecordActive: Bool = false - - init( - screen: ScreenController = ScreenController(), - camera: any CameraServicing = CameraController(), - screenRecorder: any ScreenRecordingServicing = ScreenRecordService(), - locationService: any LocationServicing = LocationService(), - notificationCenter: NotificationCentering = LiveNotificationCenter(), - deviceStatusService: any DeviceStatusServicing = DeviceStatusService(), - photosService: any PhotosServicing = PhotoLibraryService(), - contactsService: any ContactsServicing = ContactsService(), - calendarService: any CalendarServicing = CalendarService(), - remindersService: any RemindersServicing = RemindersService(), - motionService: any MotionServicing = MotionService(), - watchMessagingService: any WatchMessagingServicing = WatchMessagingService(), - talkMode: TalkModeManager = TalkModeManager()) - { - self.screen = screen - self.camera = camera - self.screenRecorder = screenRecorder - self.locationService = locationService - self.notificationCenter = notificationCenter - self.deviceStatusService = deviceStatusService - self.photosService = photosService - self.contactsService = contactsService - self.calendarService = calendarService - self.remindersService = remindersService - self.motionService = motionService - self.watchMessagingService = watchMessagingService - self.talkMode = talkMode - self.apnsDeviceTokenHex = UserDefaults.standard.string(forKey: Self.apnsDeviceTokenUserDefaultsKey) - GatewayDiagnostics.bootstrap() - self.watchMessagingService.setReplyHandler { [weak self] event in - Task { @MainActor in - await self?.handleWatchQuickReply(event) - } - } - - self.voiceWake.configure { [weak self] cmd in - guard let self else { return } - let sessionKey = await MainActor.run { self.mainSessionKey } - do { - try await self.sendVoiceTranscript(text: cmd, sessionKey: sessionKey) - } catch { - // Best-effort only. - } - } - - let enabled = UserDefaults.standard.bool(forKey: "voiceWake.enabled") - self.voiceWake.setEnabled(enabled) - self.talkMode.attachGateway(self.operatorGateway) - self.refreshLastShareEventFromRelay() - let talkEnabled = UserDefaults.standard.bool(forKey: "talk.enabled") - // Route through the coordinator so VoiceWake and Talk don't fight over the microphone. - self.setTalkEnabled(talkEnabled) - - // Wire up deep links from canvas taps - self.screen.onDeepLink = { [weak self] url in - guard let self else { return } - Task { @MainActor in - await self.handleDeepLink(url: url) - } - } - - // Wire up A2UI action clicks (buttons, etc.) - self.screen.onA2UIAction = { [weak self] body in - guard let self else { return } - Task { @MainActor in - await self.handleCanvasA2UIAction(body: body) - } - } - } - - private func handleCanvasA2UIAction(body: [String: Any]) async { - let userActionAny = body["userAction"] ?? body - let userAction: [String: Any] = { - if let dict = userActionAny as? [String: Any] { return dict } - if let dict = userActionAny as? [AnyHashable: Any] { - return dict.reduce(into: [String: Any]()) { acc, pair in - guard let key = pair.key as? String else { return } - acc[key] = pair.value - } - } - return [:] - }() - guard !userAction.isEmpty else { return } - - guard let name = OpenClawCanvasA2UIAction.extractActionName(userAction) else { return } - let actionId: String = { - let id = (userAction["id"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - return id.isEmpty ? UUID().uuidString : id - }() - - let surfaceId: String = { - let raw = (userAction["surfaceId"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - return raw.isEmpty ? "main" : raw - }() - let sourceComponentId: String = { - let raw = (userAction[ - "sourceComponentId", - ] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - return raw.isEmpty ? "-" : raw - }() - - let host = NodeDisplayName.resolve( - existing: UserDefaults.standard.string(forKey: "node.displayName"), - deviceName: UIDevice.current.name, - interfaceIdiom: UIDevice.current.userInterfaceIdiom) - let instanceId = (UserDefaults.standard.string(forKey: "node.instanceId") ?? "ios-node").lowercased() - let contextJSON = OpenClawCanvasA2UIAction.compactJSON(userAction["context"]) - let sessionKey = self.mainSessionKey - - let messageContext = OpenClawCanvasA2UIAction.AgentMessageContext( - actionName: name, - session: .init(key: sessionKey, surfaceId: surfaceId), - component: .init(id: sourceComponentId, host: host, instanceId: instanceId), - contextJSON: contextJSON) - let message = OpenClawCanvasA2UIAction.formatAgentMessage(messageContext) - - let ok: Bool - var errorText: String? - if await !self.isGatewayConnected() { - ok = false - errorText = "gateway not connected" - } else { - do { - try await self.sendAgentRequest(link: AgentDeepLink( - message: message, - sessionKey: sessionKey, - thinking: "low", - deliver: false, - to: nil, - channel: nil, - timeoutSeconds: nil, - key: actionId)) - ok = true - } catch { - ok = false - errorText = error.localizedDescription - } - } - - let js = OpenClawCanvasA2UIAction.jsDispatchA2UIActionStatus(actionId: actionId, ok: ok, error: errorText) - do { - _ = try await self.screen.eval(javaScript: js) - } catch { - // ignore - } - } - - - func setScenePhase(_ phase: ScenePhase) { - let keepTalkActive = UserDefaults.standard.bool(forKey: "talk.background.enabled") - switch phase { - case .background: - self.isBackgrounded = true - self.stopGatewayHealthMonitor() - self.backgroundedAt = Date() - self.reconnectAfterBackgroundArmed = true - self.beginBackgroundConnectionGracePeriod() - // Release voice wake mic in background. - self.backgroundVoiceWakeSuspended = self.voiceWake.suspendForExternalAudioCapture() - let shouldKeepTalkActive = keepTalkActive && self.talkMode.isEnabled - self.backgroundTalkKeptActive = shouldKeepTalkActive - self.backgroundTalkSuspended = self.talkMode.suspendForBackground(keepActive: shouldKeepTalkActive) - case .active, .inactive: - self.isBackgrounded = false - self.endBackgroundConnectionGracePeriod(reason: "scene_foreground") - self.clearBackgroundReconnectSuppression(reason: "scene_foreground") - if self.operatorConnected { - self.startGatewayHealthMonitor() - } - if phase == .active { - self.voiceWake.resumeAfterExternalAudioCapture(wasSuspended: self.backgroundVoiceWakeSuspended) - self.backgroundVoiceWakeSuspended = false - Task { [weak self] in - guard let self else { return } - let suspended = await MainActor.run { self.backgroundTalkSuspended } - let keptActive = await MainActor.run { self.backgroundTalkKeptActive } - await MainActor.run { - self.backgroundTalkSuspended = false - self.backgroundTalkKeptActive = false - } - await self.talkMode.resumeAfterBackground(wasSuspended: suspended, wasKeptActive: keptActive) - } - } - if phase == .active, self.reconnectAfterBackgroundArmed { - self.reconnectAfterBackgroundArmed = false - let backgroundedFor = self.backgroundedAt.map { Date().timeIntervalSince($0) } ?? 0 - self.backgroundedAt = nil - // iOS may suspend network sockets in background without a clean close. - // On foreground, force a fresh handshake to avoid "connected but dead" states. - if backgroundedFor >= 3.0 { - Task { [weak self] in - guard let self else { return } - let operatorWasConnected = await MainActor.run { self.operatorConnected } - if operatorWasConnected { - // Prefer keeping the connection if it's healthy; reconnect only when needed. - let healthy = (try? await self.operatorGateway.request( - method: "health", - paramsJSON: nil, - timeoutSeconds: 2)) != nil - if healthy { - await MainActor.run { self.startGatewayHealthMonitor() } - return - } - } - - await self.operatorGateway.disconnect() - await self.nodeGateway.disconnect() - await MainActor.run { - self.operatorConnected = false - self.gatewayConnected = false - self.talkMode.updateGatewayConnected(false) - } - } - } - } - @unknown default: - self.isBackgrounded = false - self.endBackgroundConnectionGracePeriod(reason: "scene_unknown") - self.clearBackgroundReconnectSuppression(reason: "scene_unknown") - } - } - - private func beginBackgroundConnectionGracePeriod(seconds: TimeInterval = 25) { - self.grantBackgroundReconnectLease(seconds: seconds, reason: "scene_background_grace") - self.endBackgroundConnectionGracePeriod(reason: "restart") - let taskID = UIApplication.shared.beginBackgroundTask(withName: "gateway-background-grace") { [weak self] in - Task { @MainActor in - self?.suppressBackgroundReconnect( - reason: "background_grace_expired", - disconnectIfNeeded: true) - self?.endBackgroundConnectionGracePeriod(reason: "expired") - } - } - guard taskID != .invalid else { - self.pushWakeLogger.info("Background grace unavailable: beginBackgroundTask returned invalid") - return - } - self.backgroundGraceTaskID = taskID - self.pushWakeLogger.info("Background grace started seconds=\(seconds, privacy: .public)") - self.backgroundGraceTaskTimer = Task { [weak self] in - guard let self else { return } - try? await Task.sleep(nanoseconds: UInt64(max(1, seconds) * 1_000_000_000)) - await MainActor.run { - self.suppressBackgroundReconnect(reason: "background_grace_timer", disconnectIfNeeded: true) - self.endBackgroundConnectionGracePeriod(reason: "timer") - } - } - } - - private func endBackgroundConnectionGracePeriod(reason: String) { - self.backgroundGraceTaskTimer?.cancel() - self.backgroundGraceTaskTimer = nil - guard self.backgroundGraceTaskID != .invalid else { return } - UIApplication.shared.endBackgroundTask(self.backgroundGraceTaskID) - self.backgroundGraceTaskID = .invalid - self.pushWakeLogger.info("Background grace ended reason=\(reason, privacy: .public)") - } - - private func grantBackgroundReconnectLease(seconds: TimeInterval, reason: String) { - guard self.isBackgrounded else { return } - let leaseSeconds = max(5, seconds) - let leaseUntil = Date().addingTimeInterval(leaseSeconds) - if let existing = self.backgroundReconnectLeaseUntil, existing > leaseUntil { - // Keep the longer lease if one is already active. - } else { - self.backgroundReconnectLeaseUntil = leaseUntil - } - let wasSuppressed = self.backgroundReconnectSuppressed - self.backgroundReconnectSuppressed = false - self.pushWakeLogger.info( - "Background reconnect lease reason=\(reason, privacy: .public) seconds=\(leaseSeconds, privacy: .public) wasSuppressed=\(wasSuppressed, privacy: .public)") - } - - private func suppressBackgroundReconnect(reason: String, disconnectIfNeeded: Bool) { - guard self.isBackgrounded else { return } - let hadLease = self.backgroundReconnectLeaseUntil != nil - let changed = hadLease || !self.backgroundReconnectSuppressed - self.backgroundReconnectLeaseUntil = nil - self.backgroundReconnectSuppressed = true - guard changed else { return } - self.pushWakeLogger.info( - "Background reconnect suppressed reason=\(reason, privacy: .public) disconnect=\(disconnectIfNeeded, privacy: .public)") - guard disconnectIfNeeded else { return } - Task { [weak self] in - guard let self else { return } - await self.operatorGateway.disconnect() - await self.nodeGateway.disconnect() - await MainActor.run { - self.operatorConnected = false - self.gatewayConnected = false - self.talkMode.updateGatewayConnected(false) - if self.isBackgrounded { - self.gatewayStatusText = "Background idle" - self.gatewayServerName = nil - self.gatewayRemoteAddress = nil - self.showLocalCanvasOnDisconnect() - } - } - } - } - - private func clearBackgroundReconnectSuppression(reason: String) { - let changed = self.backgroundReconnectSuppressed || self.backgroundReconnectLeaseUntil != nil - self.backgroundReconnectSuppressed = false - self.backgroundReconnectLeaseUntil = nil - guard changed else { return } - self.pushWakeLogger.info("Background reconnect cleared reason=\(reason, privacy: .public)") - } - - func setVoiceWakeEnabled(_ enabled: Bool) { - self.voiceWake.setEnabled(enabled) - if enabled { - // If talk is enabled, voice wake should not grab the mic. - if self.talkMode.isEnabled { - self.voiceWake.setSuppressedByTalk(true) - self.talkVoiceWakeSuspended = self.voiceWake.suspendForExternalAudioCapture() - } - } else { - self.voiceWake.setSuppressedByTalk(false) - self.talkVoiceWakeSuspended = false - } - } - - func setTalkEnabled(_ enabled: Bool) { - UserDefaults.standard.set(enabled, forKey: "talk.enabled") - if enabled { - // Voice wake holds the microphone continuously; talk mode needs exclusive access for STT. - // When talk is enabled from the UI, prioritize talk and pause voice wake. - self.voiceWake.setSuppressedByTalk(true) - self.talkVoiceWakeSuspended = self.voiceWake.suspendForExternalAudioCapture() - } else { - self.voiceWake.setSuppressedByTalk(false) - self.voiceWake.resumeAfterExternalAudioCapture(wasSuspended: self.talkVoiceWakeSuspended) - self.talkVoiceWakeSuspended = false - } - self.talkMode.setEnabled(enabled) - Task { [weak self] in - await self?.pushTalkModeToGateway( - enabled: enabled, - phase: enabled ? "enabled" : "disabled") - } - } - - func requestLocationPermissions(mode: OpenClawLocationMode) async -> Bool { - guard mode != .off else { return true } - let status = await self.locationService.ensureAuthorization(mode: mode) - switch status { - case .authorizedAlways: - return true - case .authorizedWhenInUse: - return mode != .always - default: - return false - } - } - - private func applyMainSessionKey(_ key: String?) { - let trimmed = (key ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return } - let current = self.mainSessionBaseKey.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed == current { return } - self.mainSessionBaseKey = trimmed - self.talkMode.updateMainSessionKey(self.mainSessionKey) - } - - var seamColor: Color { - Self.color(fromHex: self.seamColorHex) ?? Self.defaultSeamColor - } - - private static let defaultSeamColor = Color(red: 79 / 255.0, green: 122 / 255.0, blue: 154 / 255.0) - private static let apnsDeviceTokenUserDefaultsKey = "push.apns.deviceTokenHex" - private static var apnsEnvironment: String { -#if DEBUG - "sandbox" -#else - "production" -#endif - } - - private static func color(fromHex raw: String?) -> Color? { - let trimmed = (raw ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - let hex = trimmed.hasPrefix("#") ? String(trimmed.dropFirst()) : trimmed - guard hex.count == 6, let value = Int(hex, radix: 16) else { return nil } - let r = Double((value >> 16) & 0xFF) / 255.0 - let g = Double((value >> 8) & 0xFF) / 255.0 - let b = Double(value & 0xFF) / 255.0 - return Color(red: r, green: g, blue: b) - } - - private func refreshBrandingFromGateway() async { - do { - let res = try await self.operatorGateway.request(method: "config.get", paramsJSON: "{}", timeoutSeconds: 8) - guard let json = try JSONSerialization.jsonObject(with: res) as? [String: Any] else { return } - guard let config = json["config"] as? [String: Any] else { return } - let ui = config["ui"] as? [String: Any] - let raw = (ui?["seamColor"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let session = config["session"] as? [String: Any] - let mainKey = SessionKey.normalizeMainKey(session?["mainKey"] as? String) - await MainActor.run { - self.seamColorHex = raw.isEmpty ? nil : raw - self.mainSessionBaseKey = mainKey - self.talkMode.updateMainSessionKey(self.mainSessionKey) - } - } catch { - if let gatewayError = error as? GatewayResponseError { - let lower = gatewayError.message.lowercased() - if lower.contains("unauthorized role") { - return - } - } - // ignore - } - } - - private func refreshAgentsFromGateway() async { - do { - let res = try await self.operatorGateway.request(method: "agents.list", paramsJSON: "{}", timeoutSeconds: 8) - let decoded = try JSONDecoder().decode(AgentsListResult.self, from: res) - await MainActor.run { - self.gatewayDefaultAgentId = decoded.defaultid - self.gatewayAgents = decoded.agents - self.applyMainSessionKey(decoded.mainkey) - - let selected = (self.selectedAgentId ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - if !selected.isEmpty && !decoded.agents.contains(where: { $0.id == selected }) { - self.selectedAgentId = nil - } - self.talkMode.updateMainSessionKey(self.mainSessionKey) - } - } catch { - // Best-effort only. - } - } - - func setSelectedAgentId(_ agentId: String?) { - let trimmed = (agentId ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - let stableID = (self.connectedGatewayID ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - if stableID.isEmpty { - self.selectedAgentId = trimmed.isEmpty ? nil : trimmed - } else { - self.selectedAgentId = trimmed.isEmpty ? nil : trimmed - GatewaySettingsStore.saveGatewaySelectedAgentId(stableID: stableID, agentId: self.selectedAgentId) - } - self.talkMode.updateMainSessionKey(self.mainSessionKey) - if let relay = ShareGatewayRelaySettings.loadConfig() { - ShareGatewayRelaySettings.saveConfig( - ShareGatewayRelayConfig( - gatewayURLString: relay.gatewayURLString, - token: relay.token, - password: relay.password, - sessionKey: self.mainSessionKey, - deliveryChannel: self.shareDeliveryChannel, - deliveryTo: self.shareDeliveryTo)) - } - } - - func setGlobalWakeWords(_ words: [String]) async { - let sanitized = VoiceWakePreferences.sanitizeTriggerWords(words) - - struct Payload: Codable { - var triggers: [String] - } - let payload = Payload(triggers: sanitized) - guard let data = try? JSONEncoder().encode(payload), - let json = String(data: data, encoding: .utf8) - else { return } - - do { - _ = try await self.operatorGateway.request(method: "voicewake.set", paramsJSON: json, timeoutSeconds: 12) - } catch { - // Best-effort only. - } - } - - private func startVoiceWakeSync() async { - self.voiceWakeSyncTask?.cancel() - self.voiceWakeSyncTask = Task { [weak self] in - guard let self else { return } - - if !(await self.isGatewayHealthMonitorDisabled()) { - await self.refreshWakeWordsFromGateway() - } - - let stream = await self.operatorGateway.subscribeServerEvents(bufferingNewest: 200) - for await evt in stream { - if Task.isCancelled { return } - guard let payload = evt.payload else { continue } - switch evt.event { - case "voicewake.changed": - struct Payload: Decodable { var triggers: [String] } - guard let decoded = try? GatewayPayloadDecoding.decode(payload, as: Payload.self) else { continue } - let triggers = VoiceWakePreferences.sanitizeTriggerWords(decoded.triggers) - VoiceWakePreferences.saveTriggerWords(triggers) - case "talk.mode": - struct Payload: Decodable { - var enabled: Bool - var phase: String? - } - guard let decoded = try? GatewayPayloadDecoding.decode(payload, as: Payload.self) else { continue } - self.applyTalkModeSync(enabled: decoded.enabled, phase: decoded.phase) - default: - continue - } - } - } - } - - private func applyTalkModeSync(enabled: Bool, phase: String?) { - _ = phase - guard self.talkMode.isEnabled != enabled else { return } - self.setTalkEnabled(enabled) - } - - private func pushTalkModeToGateway(enabled: Bool, phase: String?) async { - guard await self.isOperatorConnected() else { return } - struct TalkModePayload: Encodable { - var enabled: Bool - var phase: String? - } - let payload = TalkModePayload(enabled: enabled, phase: phase) - guard let data = try? JSONEncoder().encode(payload), - let json = String(data: data, encoding: .utf8) - else { return } - _ = try? await self.operatorGateway.request( - method: "talk.mode", - paramsJSON: json, - timeoutSeconds: 8) - } - - private func startGatewayHealthMonitor() { - self.gatewayHealthMonitorDisabled = false - self.gatewayHealthMonitor.start( - check: { [weak self] in - guard let self else { return false } - if await self.isGatewayHealthMonitorDisabled() { return true } - do { - let data = try await self.operatorGateway.request(method: "health", paramsJSON: nil, timeoutSeconds: 6) - guard let decoded = try? JSONDecoder().decode(OpenClawGatewayHealthOK.self, from: data) else { - return false - } - return decoded.ok ?? false - } catch { - if let gatewayError = error as? GatewayResponseError { - let lower = gatewayError.message.lowercased() - if lower.contains("unauthorized role") || lower.contains("missing scope") { - await self.setGatewayHealthMonitorDisabled(true) - return true - } - } - return false - } - }, - onFailure: { [weak self] _ in - guard let self else { return } - await self.operatorGateway.disconnect() - await self.nodeGateway.disconnect() - await MainActor.run { - self.operatorConnected = false - self.gatewayConnected = false - self.gatewayStatusText = "Reconnecting…" - self.talkMode.updateGatewayConnected(false) - } - }) - } - - private func stopGatewayHealthMonitor() { - self.gatewayHealthMonitor.stop() - } - - private func refreshWakeWordsFromGateway() async { - do { - let data = try await self.operatorGateway.request(method: "voicewake.get", paramsJSON: "{}", timeoutSeconds: 8) - guard let triggers = VoiceWakePreferences.decodeGatewayTriggers(from: data) else { return } - VoiceWakePreferences.saveTriggerWords(triggers) - } catch { - if let gatewayError = error as? GatewayResponseError { - let lower = gatewayError.message.lowercased() - if lower.contains("unauthorized role") || lower.contains("missing scope") { - await self.setGatewayHealthMonitorDisabled(true) - return - } - } - // Best-effort only. - } - } - - private func isGatewayHealthMonitorDisabled() -> Bool { - self.gatewayHealthMonitorDisabled - } - - private func setGatewayHealthMonitorDisabled(_ disabled: Bool) { - self.gatewayHealthMonitorDisabled = disabled - } - - func sendVoiceTranscript(text: String, sessionKey: String?) async throws { - if await !self.isGatewayConnected() { - throw NSError(domain: "Gateway", code: 10, userInfo: [ - NSLocalizedDescriptionKey: "Gateway not connected", - ]) - } - struct Payload: Codable { - var text: String - var sessionKey: String? - } - let payload = Payload(text: text, sessionKey: sessionKey) - let data = try JSONEncoder().encode(payload) - guard let json = String(bytes: data, encoding: .utf8) else { - throw NSError(domain: "NodeAppModel", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "Failed to encode voice transcript payload as UTF-8", - ]) - } - await self.nodeGateway.sendEvent(event: "voice.transcript", payloadJSON: json) - } - - func handleDeepLink(url: URL) async { - guard let route = DeepLinkParser.parse(url) else { return } - - switch route { - case let .agent(link): - await self.handleAgentDeepLink(link, originalURL: url) - case .gateway: - break - } - } - - private func handleAgentDeepLink(_ link: AgentDeepLink, originalURL: URL) async { - let message = link.message.trimmingCharacters(in: .whitespacesAndNewlines) - guard !message.isEmpty else { return } - self.deepLinkLogger.info( - "agent deep link received messageChars=\(message.count) url=\(originalURL.absoluteString, privacy: .public)" - ) - - if message.count > 20000 { - self.screen.errorText = "Deep link too large (message exceeds 20,000 characters)." - self.recordShareEvent("Rejected: message too large (\(message.count) chars).") - return - } - - guard await self.isGatewayConnected() else { - self.screen.errorText = "Gateway not connected (cannot forward deep link)." - self.recordShareEvent("Failed: gateway not connected.") - self.deepLinkLogger.error("agent deep link rejected: gateway not connected") - return - } - - do { - try await self.sendAgentRequest(link: link) - self.screen.errorText = nil - self.recordShareEvent("Sent to gateway (\(message.count) chars).") - self.deepLinkLogger.info("agent deep link forwarded to gateway") - self.openChatRequestID &+= 1 - } catch { - self.screen.errorText = "Agent request failed: \(error.localizedDescription)" - self.recordShareEvent("Failed: \(error.localizedDescription)") - self.deepLinkLogger.error("agent deep link send failed: \(error.localizedDescription, privacy: .public)") - } - } - - private func sendAgentRequest(link: AgentDeepLink) async throws { - if link.message.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - throw NSError(domain: "DeepLink", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "invalid agent message", - ]) - } - - // iOS gateway forwards to the gateway; no local auth prompts here. - // (Key-based unattended auth is handled on macOS for openclaw:// links.) - let data = try JSONEncoder().encode(link) - guard let json = String(bytes: data, encoding: .utf8) else { - throw NSError(domain: "NodeAppModel", code: 2, userInfo: [ - NSLocalizedDescriptionKey: "Failed to encode agent request payload as UTF-8", - ]) - } - await self.nodeGateway.sendEvent(event: "agent.request", payloadJSON: json) - } - - private func isGatewayConnected() async -> Bool { - self.gatewayConnected - } - - private func handleInvoke(_ req: BridgeInvokeRequest) async -> BridgeInvokeResponse { - let command = req.command - - if self.isBackgrounded, self.isBackgroundRestricted(command) { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .backgroundUnavailable, - message: "NODE_BACKGROUND_UNAVAILABLE: canvas/camera/screen commands require foreground")) - } - - if command.hasPrefix("camera."), !self.isCameraEnabled() { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "CAMERA_DISABLED: enable Camera in iOS Settings → Camera → Allow Camera")) - } - - do { - return try await self.capabilityRouter.handle(req) - } catch let error as NodeCapabilityRouter.RouterError { - switch error { - case .unknownCommand: - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .invalidRequest, message: "INVALID_REQUEST: unknown command")) - case .handlerUnavailable: - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .unavailable, message: "node handler unavailable")) - } - } catch { - if command.hasPrefix("camera.") { - let text = (error as? LocalizedError)?.errorDescription ?? error.localizedDescription - self.showCameraHUD(text: text, kind: .error, autoHideSeconds: 2.2) - } - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .unavailable, message: error.localizedDescription)) - } - } - - private func isBackgroundRestricted(_ command: String) -> Bool { - command.hasPrefix("canvas.") || command.hasPrefix("camera.") || command.hasPrefix("screen.") || - command.hasPrefix("talk.") - } - - private func handleLocationInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - let mode = self.locationMode() - guard mode != .off else { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "LOCATION_DISABLED: enable Location in Settings")) - } - if self.isBackgrounded, mode != .always { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .backgroundUnavailable, - message: "LOCATION_BACKGROUND_UNAVAILABLE: background location requires Always")) - } - let params = (try? Self.decodeParams(OpenClawLocationGetParams.self, from: req.paramsJSON)) ?? - OpenClawLocationGetParams() - let desired = params.desiredAccuracy ?? - (self.isLocationPreciseEnabled() ? .precise : .balanced) - let status = self.locationService.authorizationStatus() - if status != .authorizedAlways, status != .authorizedWhenInUse { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "LOCATION_PERMISSION_REQUIRED: grant Location permission")) - } - if self.isBackgrounded, status != .authorizedAlways { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "LOCATION_PERMISSION_REQUIRED: enable Always for background access")) - } - let location = try await self.locationService.currentLocation( - params: params, - desiredAccuracy: desired, - maxAgeMs: params.maxAgeMs, - timeoutMs: params.timeoutMs) - let isPrecise = self.locationService.accuracyAuthorization() == .fullAccuracy - let payload = OpenClawLocationPayload( - lat: location.coordinate.latitude, - lon: location.coordinate.longitude, - accuracyMeters: location.horizontalAccuracy, - altitudeMeters: location.verticalAccuracy >= 0 ? location.altitude : nil, - speedMps: location.speed >= 0 ? location.speed : nil, - headingDeg: location.course >= 0 ? location.course : nil, - timestamp: ISO8601DateFormatter().string(from: location.timestamp), - isPrecise: isPrecise, - source: nil) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - } - - private func handleCanvasInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - switch req.command { - case OpenClawCanvasCommand.present.rawValue: - // iOS ignores placement hints; canvas always fills the screen. - let params = (try? Self.decodeParams(OpenClawCanvasPresentParams.self, from: req.paramsJSON)) ?? - OpenClawCanvasPresentParams() - let url = params.url?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if url.isEmpty { - self.screen.showDefaultCanvas() - } else { - self.screen.navigate(to: url) - } - return BridgeInvokeResponse(id: req.id, ok: true) - case OpenClawCanvasCommand.hide.rawValue: - self.screen.showDefaultCanvas() - return BridgeInvokeResponse(id: req.id, ok: true) - case OpenClawCanvasCommand.navigate.rawValue: - let params = try Self.decodeParams(OpenClawCanvasNavigateParams.self, from: req.paramsJSON) - self.screen.navigate(to: params.url) - return BridgeInvokeResponse(id: req.id, ok: true) - case OpenClawCanvasCommand.evalJS.rawValue: - let params = try Self.decodeParams(OpenClawCanvasEvalParams.self, from: req.paramsJSON) - let result = try await self.screen.eval(javaScript: params.javaScript) - let payload = try Self.encodePayload(["result": result]) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - case OpenClawCanvasCommand.snapshot.rawValue: - let params = try? Self.decodeParams(OpenClawCanvasSnapshotParams.self, from: req.paramsJSON) - let format = params?.format ?? .jpeg - let maxWidth: CGFloat? = { - if let raw = params?.maxWidth, raw > 0 { return CGFloat(raw) } - // Keep default snapshots comfortably below the gateway client's maxPayload. - // For full-res, clients should explicitly request a larger maxWidth. - return switch format { - case .png: 900 - case .jpeg: 1600 - } - }() - let base64 = try await self.screen.snapshotBase64( - maxWidth: maxWidth, - format: format, - quality: params?.quality) - let payload = try Self.encodePayload([ - "format": format == .jpeg ? "jpeg" : "png", - "base64": base64, - ]) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - default: - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .invalidRequest, message: "INVALID_REQUEST: unknown command")) - } - } - - private func handleCanvasA2UIInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - let command = req.command - switch command { - case OpenClawCanvasA2UICommand.reset.rawValue: - guard let a2uiUrl = await self.resolveA2UIHostURL() else { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "A2UI_HOST_NOT_CONFIGURED: gateway did not advertise canvas host")) - } - self.screen.navigate(to: a2uiUrl) - if await !self.screen.waitForA2UIReady(timeoutMs: 5000) { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "A2UI_HOST_UNAVAILABLE: A2UI host not reachable")) - } - - let json = try await self.screen.eval(javaScript: """ - (() => { - const host = globalThis.openclawA2UI; - if (!host) return JSON.stringify({ ok: false, error: "missing openclawA2UI" }); - return JSON.stringify(host.reset()); - })() - """) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - case OpenClawCanvasA2UICommand.push.rawValue, OpenClawCanvasA2UICommand.pushJSONL.rawValue: - let messages: [OpenClawKit.AnyCodable] - if command == OpenClawCanvasA2UICommand.pushJSONL.rawValue { - let params = try Self.decodeParams(OpenClawCanvasA2UIPushJSONLParams.self, from: req.paramsJSON) - messages = try OpenClawCanvasA2UIJSONL.decodeMessagesFromJSONL(params.jsonl) - } else { - do { - let params = try Self.decodeParams(OpenClawCanvasA2UIPushParams.self, from: req.paramsJSON) - messages = params.messages - } catch { - // Be forgiving: some clients still send JSONL payloads to `canvas.a2ui.push`. - let params = try Self.decodeParams(OpenClawCanvasA2UIPushJSONLParams.self, from: req.paramsJSON) - messages = try OpenClawCanvasA2UIJSONL.decodeMessagesFromJSONL(params.jsonl) - } - } - - guard let a2uiUrl = await self.resolveA2UIHostURL() else { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "A2UI_HOST_NOT_CONFIGURED: gateway did not advertise canvas host")) - } - self.screen.navigate(to: a2uiUrl) - if await !self.screen.waitForA2UIReady(timeoutMs: 5000) { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "A2UI_HOST_UNAVAILABLE: A2UI host not reachable")) - } - - let messagesJSON = try OpenClawCanvasA2UIJSONL.encodeMessagesJSONArray(messages) - let js = """ - (() => { - try { - const host = globalThis.openclawA2UI; - if (!host) return JSON.stringify({ ok: false, error: "missing openclawA2UI" }); - const messages = \(messagesJSON); - return JSON.stringify(host.applyMessages(messages)); - } catch (e) { - return JSON.stringify({ ok: false, error: String(e?.message ?? e) }); - } - })() - """ - let resultJSON = try await self.screen.eval(javaScript: js) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: resultJSON) - default: - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .invalidRequest, message: "INVALID_REQUEST: unknown command")) - } - } - - private func handleCameraInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - switch req.command { - case OpenClawCameraCommand.list.rawValue: - let devices = await self.camera.listDevices() - struct Payload: Codable { - var devices: [CameraController.CameraDeviceInfo] - } - let payload = try Self.encodePayload(Payload(devices: devices)) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - case OpenClawCameraCommand.snap.rawValue: - self.showCameraHUD(text: "Taking photo…", kind: .photo) - self.triggerCameraFlash() - let params = (try? Self.decodeParams(OpenClawCameraSnapParams.self, from: req.paramsJSON)) ?? - OpenClawCameraSnapParams() - let res = try await self.camera.snap(params: params) - - struct Payload: Codable { - var format: String - var base64: String - var width: Int - var height: Int - } - let payload = try Self.encodePayload(Payload( - format: res.format, - base64: res.base64, - width: res.width, - height: res.height)) - self.showCameraHUD(text: "Photo captured", kind: .success, autoHideSeconds: 1.6) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - case OpenClawCameraCommand.clip.rawValue: - let params = (try? Self.decodeParams(OpenClawCameraClipParams.self, from: req.paramsJSON)) ?? - OpenClawCameraClipParams() - - let suspended = (params.includeAudio ?? true) ? self.voiceWake.suspendForExternalAudioCapture() : false - defer { self.voiceWake.resumeAfterExternalAudioCapture(wasSuspended: suspended) } - - self.showCameraHUD(text: "Recording…", kind: .recording) - let res = try await self.camera.clip(params: params) - - struct Payload: Codable { - var format: String - var base64: String - var durationMs: Int - var hasAudio: Bool - } - let payload = try Self.encodePayload(Payload( - format: res.format, - base64: res.base64, - durationMs: res.durationMs, - hasAudio: res.hasAudio)) - self.showCameraHUD(text: "Clip captured", kind: .success, autoHideSeconds: 1.8) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - default: - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .invalidRequest, message: "INVALID_REQUEST: unknown command")) - } - } - - private func handleScreenRecordInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - let params = (try? Self.decodeParams(OpenClawScreenRecordParams.self, from: req.paramsJSON)) ?? - OpenClawScreenRecordParams() - if let format = params.format, format.lowercased() != "mp4" { - throw NSError(domain: "Screen", code: 30, userInfo: [ - NSLocalizedDescriptionKey: "INVALID_REQUEST: screen format must be mp4", - ]) - } - // Status pill mirrors screen recording state so it stays visible without overlay stacking. - self.screenRecordActive = true - defer { self.screenRecordActive = false } - let path = try await self.screenRecorder.record( - screenIndex: params.screenIndex, - durationMs: params.durationMs, - fps: params.fps, - includeAudio: params.includeAudio, - outPath: nil) - defer { try? FileManager().removeItem(atPath: path) } - let data = try Data(contentsOf: URL(fileURLWithPath: path)) - struct Payload: Codable { - var format: String - var base64: String - var durationMs: Int? - var fps: Double? - var screenIndex: Int? - var hasAudio: Bool - } - let payload = try Self.encodePayload(Payload( - format: "mp4", - base64: data.base64EncodedString(), - durationMs: params.durationMs, - fps: params.fps, - screenIndex: params.screenIndex, - hasAudio: params.includeAudio ?? true)) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - } - - private func handleSystemNotify(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - let params = try Self.decodeParams(OpenClawSystemNotifyParams.self, from: req.paramsJSON) - let title = params.title.trimmingCharacters(in: .whitespacesAndNewlines) - let body = params.body.trimmingCharacters(in: .whitespacesAndNewlines) - if title.isEmpty, body.isEmpty { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .invalidRequest, message: "INVALID_REQUEST: empty notification")) - } - - let finalStatus = await self.requestNotificationAuthorizationIfNeeded() - guard finalStatus == .authorized || finalStatus == .provisional || finalStatus == .ephemeral else { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .unavailable, message: "NOT_AUTHORIZED: notifications")) - } - - let addResult = await self.runNotificationCall(timeoutSeconds: 2.0) { [notificationCenter] in - let content = UNMutableNotificationContent() - content.title = title - content.body = body - if #available(iOS 15.0, *) { - switch params.priority ?? .active { - case .passive: - content.interruptionLevel = .passive - case .timeSensitive: - content.interruptionLevel = .timeSensitive - case .active: - content.interruptionLevel = .active - } - } - let soundValue = params.sound?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - if let soundValue, ["none", "silent", "off", "false", "0"].contains(soundValue) { - content.sound = nil - } else { - content.sound = .default - } - let request = UNNotificationRequest( - identifier: UUID().uuidString, - content: content, - trigger: nil) - try await notificationCenter.add(request) - } - if case let .failure(error) = addResult { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .unavailable, message: "NOTIFICATION_FAILED: \(error.message)")) - } - return BridgeInvokeResponse(id: req.id, ok: true) - } - - private func handleChatPushInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - let params = try Self.decodeParams(OpenClawChatPushParams.self, from: req.paramsJSON) - let text = params.text.trimmingCharacters(in: .whitespacesAndNewlines) - guard !text.isEmpty else { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .invalidRequest, message: "INVALID_REQUEST: empty chat.push text")) - } - - let finalStatus = await self.requestNotificationAuthorizationIfNeeded() - let messageId = UUID().uuidString - if finalStatus == .authorized || finalStatus == .provisional || finalStatus == .ephemeral { - let addResult = await self.runNotificationCall(timeoutSeconds: 2.0) { [notificationCenter] in - let content = UNMutableNotificationContent() - content.title = "OpenClaw" - content.body = text - content.sound = .default - content.userInfo = ["messageId": messageId] - let request = UNNotificationRequest( - identifier: messageId, - content: content, - trigger: nil) - try await notificationCenter.add(request) - } - if case let .failure(error) = addResult { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .unavailable, message: "NOTIFICATION_FAILED: \(error.message)")) - } - } - - if params.speak ?? true { - let toSpeak = text - Task { @MainActor in - try? await TalkSystemSpeechSynthesizer.shared.speak(text: toSpeak) - } - } - - let payload = OpenClawChatPushPayload(messageId: messageId) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - } - - private func requestNotificationAuthorizationIfNeeded() async -> NotificationAuthorizationStatus { - let status = await self.notificationAuthorizationStatus() - guard status == .notDetermined else { return status } - - // Avoid hanging invoke requests if the permission prompt is never answered. - _ = await self.runNotificationCall(timeoutSeconds: 2.0) { [notificationCenter] in - _ = try await notificationCenter.requestAuthorization(options: [.alert, .sound, .badge]) - } - - return await self.notificationAuthorizationStatus() - } - - private func notificationAuthorizationStatus() async -> NotificationAuthorizationStatus { - let result = await self.runNotificationCall(timeoutSeconds: 1.5) { [notificationCenter] in - await notificationCenter.authorizationStatus() - } - switch result { - case let .success(status): - return status - case .failure: - return .denied - } - } - - private func runNotificationCall( - timeoutSeconds: Double, - operation: @escaping @Sendable () async throws -> T - ) async -> Result { - let latch = NotificationInvokeLatch() - var opTask: Task? - var timeoutTask: Task? - defer { - opTask?.cancel() - timeoutTask?.cancel() - } - let clamped = max(0.0, timeoutSeconds) - return await withCheckedContinuation { (cont: CheckedContinuation, Never>) in - latch.setContinuation(cont) - opTask = Task { @MainActor in - do { - let value = try await operation() - latch.resume(.success(value)) - } catch { - latch.resume(.failure(NotificationCallError(message: error.localizedDescription))) - } - } - timeoutTask = Task.detached { - if clamped > 0 { - try? await Task.sleep(nanoseconds: UInt64(clamped * 1_000_000_000)) - } - latch.resume(.failure(NotificationCallError(message: "notification request timed out"))) - } - } - } - - private func handleDeviceInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - switch req.command { - case OpenClawDeviceCommand.status.rawValue: - let payload = try await self.deviceStatusService.status() - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - case OpenClawDeviceCommand.info.rawValue: - let payload = self.deviceStatusService.info() - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - default: - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .invalidRequest, message: "INVALID_REQUEST: unknown command")) - } - } - - private func handlePhotosInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - let params = (try? Self.decodeParams(OpenClawPhotosLatestParams.self, from: req.paramsJSON)) ?? - OpenClawPhotosLatestParams() - let payload = try await self.photosService.latest(params: params) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - } - - private func handleContactsInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - switch req.command { - case OpenClawContactsCommand.search.rawValue: - let params = (try? Self.decodeParams(OpenClawContactsSearchParams.self, from: req.paramsJSON)) ?? - OpenClawContactsSearchParams() - let payload = try await self.contactsService.search(params: params) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - case OpenClawContactsCommand.add.rawValue: - let params = try Self.decodeParams(OpenClawContactsAddParams.self, from: req.paramsJSON) - let payload = try await self.contactsService.add(params: params) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - default: - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .invalidRequest, message: "INVALID_REQUEST: unknown command")) - } - } - - private func handleCalendarInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - switch req.command { - case OpenClawCalendarCommand.events.rawValue: - let params = (try? Self.decodeParams(OpenClawCalendarEventsParams.self, from: req.paramsJSON)) ?? - OpenClawCalendarEventsParams() - let payload = try await self.calendarService.events(params: params) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - case OpenClawCalendarCommand.add.rawValue: - let params = try Self.decodeParams(OpenClawCalendarAddParams.self, from: req.paramsJSON) - let payload = try await self.calendarService.add(params: params) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - default: - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .invalidRequest, message: "INVALID_REQUEST: unknown command")) - } - } - - private func handleRemindersInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - switch req.command { - case OpenClawRemindersCommand.list.rawValue: - let params = (try? Self.decodeParams(OpenClawRemindersListParams.self, from: req.paramsJSON)) ?? - OpenClawRemindersListParams() - let payload = try await self.remindersService.list(params: params) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - case OpenClawRemindersCommand.add.rawValue: - let params = try Self.decodeParams(OpenClawRemindersAddParams.self, from: req.paramsJSON) - let payload = try await self.remindersService.add(params: params) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - default: - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .invalidRequest, message: "INVALID_REQUEST: unknown command")) - } - } - - private func handleMotionInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - switch req.command { - case OpenClawMotionCommand.activity.rawValue: - let params = (try? Self.decodeParams(OpenClawMotionActivityParams.self, from: req.paramsJSON)) ?? - OpenClawMotionActivityParams() - let payload = try await self.motionService.activities(params: params) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - case OpenClawMotionCommand.pedometer.rawValue: - let params = (try? Self.decodeParams(OpenClawPedometerParams.self, from: req.paramsJSON)) ?? - OpenClawPedometerParams() - let payload = try await self.motionService.pedometer(params: params) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - default: - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .invalidRequest, message: "INVALID_REQUEST: unknown command")) - } - } - - private func handleTalkInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - switch req.command { - case OpenClawTalkCommand.pttStart.rawValue: - self.pttVoiceWakeSuspended = self.voiceWake.suspendForExternalAudioCapture() - let payload = try await self.talkMode.beginPushToTalk() - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - case OpenClawTalkCommand.pttStop.rawValue: - let payload = await self.talkMode.endPushToTalk() - self.voiceWake.resumeAfterExternalAudioCapture(wasSuspended: self.pttVoiceWakeSuspended) - self.pttVoiceWakeSuspended = false - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - case OpenClawTalkCommand.pttCancel.rawValue: - let payload = await self.talkMode.cancelPushToTalk() - self.voiceWake.resumeAfterExternalAudioCapture(wasSuspended: self.pttVoiceWakeSuspended) - self.pttVoiceWakeSuspended = false - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - case OpenClawTalkCommand.pttOnce.rawValue: - self.pttVoiceWakeSuspended = self.voiceWake.suspendForExternalAudioCapture() - defer { - self.voiceWake.resumeAfterExternalAudioCapture(wasSuspended: self.pttVoiceWakeSuspended) - self.pttVoiceWakeSuspended = false - } - let payload = try await self.talkMode.runPushToTalkOnce() - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - default: - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .invalidRequest, message: "INVALID_REQUEST: unknown command")) - } - } - -} - -private extension NodeAppModel { - // Central registry for node invoke routing to keep commands in one place. - func buildCapabilityRouter() -> NodeCapabilityRouter { - var handlers: [String: NodeCapabilityRouter.Handler] = [:] - - func register(_ commands: [String], handler: @escaping NodeCapabilityRouter.Handler) { - for command in commands { - handlers[command] = handler - } - } - - register([OpenClawLocationCommand.get.rawValue]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleLocationInvoke(req) - } - - register([ - OpenClawCanvasCommand.present.rawValue, - OpenClawCanvasCommand.hide.rawValue, - OpenClawCanvasCommand.navigate.rawValue, - OpenClawCanvasCommand.evalJS.rawValue, - OpenClawCanvasCommand.snapshot.rawValue, - ]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleCanvasInvoke(req) - } - - register([ - OpenClawCanvasA2UICommand.reset.rawValue, - OpenClawCanvasA2UICommand.push.rawValue, - OpenClawCanvasA2UICommand.pushJSONL.rawValue, - ]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleCanvasA2UIInvoke(req) - } - - register([ - OpenClawCameraCommand.list.rawValue, - OpenClawCameraCommand.snap.rawValue, - OpenClawCameraCommand.clip.rawValue, - ]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleCameraInvoke(req) - } - - register([OpenClawScreenCommand.record.rawValue]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleScreenRecordInvoke(req) - } - - register([OpenClawSystemCommand.notify.rawValue]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleSystemNotify(req) - } - - register([OpenClawChatCommand.push.rawValue]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleChatPushInvoke(req) - } - - register([ - OpenClawDeviceCommand.status.rawValue, - OpenClawDeviceCommand.info.rawValue, - ]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleDeviceInvoke(req) - } - - register([ - OpenClawWatchCommand.status.rawValue, - OpenClawWatchCommand.notify.rawValue, - ]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleWatchInvoke(req) - } - - register([OpenClawPhotosCommand.latest.rawValue]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handlePhotosInvoke(req) - } - - register([ - OpenClawContactsCommand.search.rawValue, - OpenClawContactsCommand.add.rawValue, - ]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleContactsInvoke(req) - } - - register([ - OpenClawCalendarCommand.events.rawValue, - OpenClawCalendarCommand.add.rawValue, - ]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleCalendarInvoke(req) - } - - register([ - OpenClawRemindersCommand.list.rawValue, - OpenClawRemindersCommand.add.rawValue, - ]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleRemindersInvoke(req) - } - - register([ - OpenClawMotionCommand.activity.rawValue, - OpenClawMotionCommand.pedometer.rawValue, - ]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleMotionInvoke(req) - } - - register([ - OpenClawTalkCommand.pttStart.rawValue, - OpenClawTalkCommand.pttStop.rawValue, - OpenClawTalkCommand.pttCancel.rawValue, - OpenClawTalkCommand.pttOnce.rawValue, - ]) { [weak self] req in - guard let self else { throw NodeCapabilityRouter.RouterError.handlerUnavailable } - return try await self.handleTalkInvoke(req) - } - - return NodeCapabilityRouter(handlers: handlers) - } - - func handleWatchInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - switch req.command { - case OpenClawWatchCommand.status.rawValue: - let status = await self.watchMessagingService.status() - let payload = OpenClawWatchStatusPayload( - supported: status.supported, - paired: status.paired, - appInstalled: status.appInstalled, - reachable: status.reachable, - activationState: status.activationState) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - case OpenClawWatchCommand.notify.rawValue: - let params = try Self.decodeParams(OpenClawWatchNotifyParams.self, from: req.paramsJSON) - let title = params.title.trimmingCharacters(in: .whitespacesAndNewlines) - let body = params.body.trimmingCharacters(in: .whitespacesAndNewlines) - if title.isEmpty && body.isEmpty { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .invalidRequest, - message: "INVALID_REQUEST: empty watch notification")) - } - do { - let result = try await self.watchMessagingService.sendNotification( - id: req.id, - params: params) - if result.queuedForDelivery || !result.deliveredImmediately { - let invokeID = req.id - Task { @MainActor in - await WatchPromptNotificationBridge.scheduleMirroredWatchPromptNotificationIfNeeded( - invokeID: invokeID, - params: params, - sendResult: result) - } - } - let payload = OpenClawWatchNotifyPayload( - deliveredImmediately: result.deliveredImmediately, - queuedForDelivery: result.queuedForDelivery, - transport: result.transport) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - } catch { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: error.localizedDescription)) - } - default: - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .invalidRequest, message: "INVALID_REQUEST: unknown command")) - } - } - - func locationMode() -> OpenClawLocationMode { - let raw = UserDefaults.standard.string(forKey: "location.enabledMode") ?? "off" - return OpenClawLocationMode(rawValue: raw) ?? .off - } - - func isLocationPreciseEnabled() -> Bool { - // iOS settings now expose a single location mode control. - // Default location tool precision stays high unless a command explicitly requests balanced. - true - } - - static func decodeParams(_ type: T.Type, from json: String?) throws -> T { - guard let json, let data = json.data(using: .utf8) else { - throw NSError(domain: "Gateway", code: 20, userInfo: [ - NSLocalizedDescriptionKey: "INVALID_REQUEST: paramsJSON required", - ]) - } - return try JSONDecoder().decode(type, from: data) - } - - static func encodePayload(_ obj: some Encodable) throws -> String { - let data = try JSONEncoder().encode(obj) - guard let json = String(bytes: data, encoding: .utf8) else { - throw NSError(domain: "NodeAppModel", code: 21, userInfo: [ - NSLocalizedDescriptionKey: "Failed to encode payload as UTF-8", - ]) - } - return json - } - - func isCameraEnabled() -> Bool { - // Default-on: if the key doesn't exist yet, treat it as enabled. - if UserDefaults.standard.object(forKey: "camera.enabled") == nil { return true } - return UserDefaults.standard.bool(forKey: "camera.enabled") - } - - func triggerCameraFlash() { - self.cameraFlashNonce &+= 1 - } - - func showCameraHUD(text: String, kind: CameraHUDKind, autoHideSeconds: Double? = nil) { - self.cameraHUDDismissTask?.cancel() - - withAnimation(.spring(response: 0.25, dampingFraction: 0.85)) { - self.cameraHUDText = text - self.cameraHUDKind = kind - } - - guard let autoHideSeconds else { return } - self.cameraHUDDismissTask = Task { @MainActor in - try? await Task.sleep(nanoseconds: UInt64(autoHideSeconds * 1_000_000_000)) - withAnimation(.easeOut(duration: 0.25)) { - self.cameraHUDText = nil - self.cameraHUDKind = nil - } - } - } -} - -extension NodeAppModel { - var mainSessionKey: String { - let base = SessionKey.normalizeMainKey(self.mainSessionBaseKey) - let agentId = (self.selectedAgentId ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - let defaultId = (self.gatewayDefaultAgentId ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - if agentId.isEmpty || (!defaultId.isEmpty && agentId == defaultId) { return base } - return SessionKey.makeAgentSessionKey(agentId: agentId, baseKey: base) - } - - var chatSessionKey: String { - let base = "ios" - let agentId = (self.selectedAgentId ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - let defaultId = (self.gatewayDefaultAgentId ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - if agentId.isEmpty || (!defaultId.isEmpty && agentId == defaultId) { return base } - return SessionKey.makeAgentSessionKey(agentId: agentId, baseKey: base) - } - - var activeAgentName: String { - let agentId = (self.selectedAgentId ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - let defaultId = (self.gatewayDefaultAgentId ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - let resolvedId = agentId.isEmpty ? defaultId : agentId - if resolvedId.isEmpty { return "Main" } - if let match = self.gatewayAgents.first(where: { $0.id == resolvedId }) { - let name = (match.name ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - return name.isEmpty ? match.id : name - } - return resolvedId - } - - func connectToGateway( - url: URL, - gatewayStableID: String, - tls: GatewayTLSParams?, - token: String?, - password: String?, - connectOptions: GatewayConnectOptions) - { - let stableID = gatewayStableID.trimmingCharacters(in: .whitespacesAndNewlines) - let effectiveStableID = stableID.isEmpty ? url.absoluteString : stableID - let sessionBox = tls.map { WebSocketSessionBox(session: GatewayTLSPinningSession(params: $0)) } - - self.activeGatewayConnectConfig = GatewayConnectConfig( - url: url, - stableID: stableID, - tls: tls, - token: token, - password: password, - nodeOptions: connectOptions) - self.prepareForGatewayConnect(url: url, stableID: effectiveStableID) - self.startOperatorGatewayLoop( - url: url, - stableID: effectiveStableID, - token: token, - password: password, - nodeOptions: connectOptions, - sessionBox: sessionBox) - self.startNodeGatewayLoop( - url: url, - stableID: effectiveStableID, - token: token, - password: password, - nodeOptions: connectOptions, - sessionBox: sessionBox) - } - - /// Preferred entry-point: apply a single config object and start both sessions. - func applyGatewayConnectConfig(_ cfg: GatewayConnectConfig) { - self.activeGatewayConnectConfig = cfg - self.connectToGateway( - url: cfg.url, - // Preserve the caller-provided stableID (may be empty) and let connectToGateway - // derive the effective stable id consistently for persistence keys. - gatewayStableID: cfg.stableID, - tls: cfg.tls, - token: cfg.token, - password: cfg.password, - connectOptions: cfg.nodeOptions) - } - - func disconnectGateway() { - self.gatewayAutoReconnectEnabled = false - self.gatewayPairingPaused = false - self.gatewayPairingRequestId = nil - self.nodeGatewayTask?.cancel() - self.nodeGatewayTask = nil - self.operatorGatewayTask?.cancel() - self.operatorGatewayTask = nil - self.voiceWakeSyncTask?.cancel() - self.voiceWakeSyncTask = nil - self.gatewayHealthMonitor.stop() - Task { - await self.operatorGateway.disconnect() - await self.nodeGateway.disconnect() - } - self.gatewayStatusText = "Offline" - self.gatewayServerName = nil - self.gatewayRemoteAddress = nil - self.connectedGatewayID = nil - self.activeGatewayConnectConfig = nil - self.gatewayConnected = false - self.operatorConnected = false - self.talkMode.updateGatewayConnected(false) - self.seamColorHex = nil - self.mainSessionBaseKey = "main" - self.talkMode.updateMainSessionKey(self.mainSessionKey) - ShareGatewayRelaySettings.clearConfig() - self.showLocalCanvasOnDisconnect() - } -} - -private extension NodeAppModel { - func prepareForGatewayConnect(url: URL, stableID: String) { - self.gatewayAutoReconnectEnabled = true - self.gatewayPairingPaused = false - self.gatewayPairingRequestId = nil - self.nodeGatewayTask?.cancel() - self.operatorGatewayTask?.cancel() - self.gatewayHealthMonitor.stop() - self.gatewayServerName = nil - self.gatewayRemoteAddress = nil - self.connectedGatewayID = stableID - self.gatewayConnected = false - self.operatorConnected = false - self.voiceWakeSyncTask?.cancel() - self.voiceWakeSyncTask = nil - self.gatewayDefaultAgentId = nil - self.gatewayAgents = [] - self.selectedAgentId = GatewaySettingsStore.loadGatewaySelectedAgentId(stableID: stableID) - self.apnsLastRegisteredTokenHex = nil - } - - func refreshBackgroundReconnectSuppressionIfNeeded(source: String) { - guard self.isBackgrounded else { return } - guard !self.backgroundReconnectSuppressed else { return } - guard let leaseUntil = self.backgroundReconnectLeaseUntil else { - self.suppressBackgroundReconnect(reason: "\(source):no_lease", disconnectIfNeeded: true) - return - } - if Date() >= leaseUntil { - self.suppressBackgroundReconnect(reason: "\(source):lease_expired", disconnectIfNeeded: true) - } - } - - func shouldPauseReconnectLoopInBackground(source: String) -> Bool { - self.refreshBackgroundReconnectSuppressionIfNeeded(source: source) - return self.isBackgrounded && self.backgroundReconnectSuppressed - } - - func startOperatorGatewayLoop( - url: URL, - stableID: String, - token: String?, - password: String?, - nodeOptions: GatewayConnectOptions, - sessionBox: WebSocketSessionBox?) - { - // Operator session reconnects independently (chat/talk/config/voicewake), but we tie its - // lifecycle to the current gateway config so it doesn't keep running across Disconnect. - self.operatorGatewayTask = Task { [weak self] in - guard let self else { return } - var attempt = 0 - while !Task.isCancelled { - if self.gatewayPairingPaused { - try? await Task.sleep(nanoseconds: 1_000_000_000) - continue - } - if !self.gatewayAutoReconnectEnabled { - try? await Task.sleep(nanoseconds: 1_000_000_000) - continue - } - if self.shouldPauseReconnectLoopInBackground(source: "operator_loop") { try? await Task.sleep(nanoseconds: 2_000_000_000); continue } - if await self.isOperatorConnected() { - try? await Task.sleep(nanoseconds: 1_000_000_000) - continue - } - - let effectiveClientId = - GatewaySettingsStore.loadGatewayClientIdOverride(stableID: stableID) ?? nodeOptions.clientId - let operatorOptions = self.makeOperatorConnectOptions( - clientId: effectiveClientId, - displayName: nodeOptions.clientDisplayName) - - do { - try await self.operatorGateway.connect( - url: url, - token: token, - password: password, - connectOptions: operatorOptions, - sessionBox: sessionBox, - onConnected: { [weak self] in - guard let self else { return } - await MainActor.run { - self.operatorConnected = true - self.talkMode.updateGatewayConnected(true) - } - GatewayDiagnostics.log( - "operator gateway connected host=\(url.host ?? "?") scheme=\(url.scheme ?? "?")") - await self.talkMode.reloadConfig() - await self.refreshBrandingFromGateway() - await self.refreshAgentsFromGateway() - await self.refreshShareRouteFromGateway() - await self.startVoiceWakeSync() - await MainActor.run { self.startGatewayHealthMonitor() } - }, - onDisconnected: { [weak self] reason in - guard let self else { return } - await MainActor.run { - self.operatorConnected = false - self.talkMode.updateGatewayConnected(false) - } - GatewayDiagnostics.log("operator gateway disconnected reason=\(reason)") - await MainActor.run { self.stopGatewayHealthMonitor() } - }, - onInvoke: { req in - // Operator session should not handle node.invoke requests. - BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .invalidRequest, - message: "INVALID_REQUEST: operator session cannot invoke node commands")) - }) - - attempt = 0 - try? await Task.sleep(nanoseconds: 1_000_000_000) - } catch { - attempt += 1 - GatewayDiagnostics.log("operator gateway connect error: \(error.localizedDescription)") - let sleepSeconds = min(8.0, 0.5 * pow(1.7, Double(attempt))) - try? await Task.sleep(nanoseconds: UInt64(sleepSeconds * 1_000_000_000)) - } - } - } - } - - func startNodeGatewayLoop( - url: URL, - stableID: String, - token: String?, - password: String?, - nodeOptions: GatewayConnectOptions, - sessionBox: WebSocketSessionBox?) - { - self.nodeGatewayTask = Task { [weak self] in - guard let self else { return } - var attempt = 0 - var currentOptions = nodeOptions - var didFallbackClientId = false - var pausedForPairingApproval = false - - while !Task.isCancelled { - if self.gatewayPairingPaused { - try? await Task.sleep(nanoseconds: 1_000_000_000) - continue - } - if !self.gatewayAutoReconnectEnabled { - try? await Task.sleep(nanoseconds: 1_000_000_000) - continue - } - if self.shouldPauseReconnectLoopInBackground(source: "node_loop") { try? await Task.sleep(nanoseconds: 2_000_000_000); continue } - if await self.isGatewayConnected() { - try? await Task.sleep(nanoseconds: 1_000_000_000) - continue - } - await MainActor.run { - self.gatewayStatusText = (attempt == 0) ? "Connecting…" : "Reconnecting…" - self.gatewayServerName = nil - self.gatewayRemoteAddress = nil - } - - do { - let epochMs = Int(Date().timeIntervalSince1970 * 1000) - GatewayDiagnostics.log("connect attempt epochMs=\(epochMs) url=\(url.absoluteString)") - try await self.nodeGateway.connect( - url: url, - token: token, - password: password, - connectOptions: currentOptions, - sessionBox: sessionBox, - onConnected: { [weak self] in - guard let self else { return } - await MainActor.run { - self.gatewayStatusText = "Connected" - self.gatewayServerName = url.host ?? "gateway" - self.gatewayConnected = true - self.screen.errorText = nil - UserDefaults.standard.set(true, forKey: "gateway.autoconnect") - } - let relayData = await MainActor.run { - ( - sessionKey: self.mainSessionKey, - deliveryChannel: self.shareDeliveryChannel, - deliveryTo: self.shareDeliveryTo - ) - } - ShareGatewayRelaySettings.saveConfig( - ShareGatewayRelayConfig( - gatewayURLString: url.absoluteString, - token: token, - password: password, - sessionKey: relayData.sessionKey, - deliveryChannel: relayData.deliveryChannel, - deliveryTo: relayData.deliveryTo)) - GatewayDiagnostics.log("gateway connected host=\(url.host ?? "?") scheme=\(url.scheme ?? "?")") - if let addr = await self.nodeGateway.currentRemoteAddress() { - await MainActor.run { self.gatewayRemoteAddress = addr } - } - await self.showA2UIOnConnectIfNeeded() - await self.onNodeGatewayConnected() - await MainActor.run { - SignificantLocationMonitor.startIfNeeded( - locationService: self.locationService, - locationMode: self.locationMode(), - gateway: self.nodeGateway, - beforeSend: { [weak self] in - await self?.handleSignificantLocationWakeIfNeeded() - }) - } - }, - onDisconnected: { [weak self] reason in - guard let self else { return } - await MainActor.run { - self.gatewayStatusText = "Disconnected: \(reason)" - self.gatewayServerName = nil - self.gatewayRemoteAddress = nil - self.gatewayConnected = false - self.showLocalCanvasOnDisconnect() - } - GatewayDiagnostics.log("gateway disconnected reason: \(reason)") - }, - onInvoke: { [weak self] req in - guard let self else { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "UNAVAILABLE: node not ready")) - } - return await self.handleInvoke(req) - }) - - attempt = 0 - try? await Task.sleep(nanoseconds: 1_000_000_000) - } catch { - if Task.isCancelled { break } - if !didFallbackClientId, - let fallbackClientId = self.legacyClientIdFallback( - currentClientId: currentOptions.clientId, - error: error) - { - didFallbackClientId = true - currentOptions.clientId = fallbackClientId - GatewaySettingsStore.saveGatewayClientIdOverride( - stableID: stableID, - clientId: fallbackClientId) - await MainActor.run { self.gatewayStatusText = "Gateway rejected client id. Retrying…" } - continue - } - - attempt += 1 - await MainActor.run { - self.gatewayStatusText = "Gateway error: \(error.localizedDescription)" - self.gatewayServerName = nil - self.gatewayRemoteAddress = nil - self.gatewayConnected = false - self.showLocalCanvasOnDisconnect() - } - GatewayDiagnostics.log("gateway connect error: \(error.localizedDescription)") - - // If auth is missing/rejected, pause reconnect churn until the user intervenes. - // Reconnect loops only spam the same failing handshake and make onboarding noisy. - let lower = error.localizedDescription.lowercased() - if lower.contains("unauthorized") || lower.contains("gateway token missing") { - await MainActor.run { - self.gatewayAutoReconnectEnabled = false - } - } - - // If pairing is required, stop reconnect churn. The user must approve the request - // on the gateway before another connect attempt will succeed, and retry loops can - // generate multiple pending requests. - if lower.contains("not_paired") || lower.contains("pairing required") { - let requestId: String? = { - // GatewayResponseError for connect decorates the message with `(requestId: ...)`. - // Keep this resilient since other layers may wrap the text. - let text = error.localizedDescription - guard let start = text.range(of: "(requestId: ")?.upperBound else { return nil } - guard let end = text[start...].firstIndex(of: ")") else { return nil } - let raw = String(text[start.. GatewayConnectOptions { - GatewayConnectOptions( - role: "operator", - scopes: ["operator.read", "operator.write", "operator.talk.secrets"], - caps: [], - commands: [], - permissions: [:], - clientId: clientId, - clientMode: "ui", - clientDisplayName: displayName, - includeDeviceIdentity: true) - } - - func legacyClientIdFallback(currentClientId: String, error: Error) -> String? { - let normalizedClientId = currentClientId.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - guard normalizedClientId == "openclaw-ios" else { return nil } - let message = error.localizedDescription.lowercased() - guard message.contains("invalid connect params"), message.contains("/client/id") else { - return nil - } - return "moltbot-ios" - } - - func isOperatorConnected() async -> Bool { - self.operatorConnected - } -} - -extension NodeAppModel { - private func refreshShareRouteFromGateway() async { - struct Params: Codable { - var includeGlobal: Bool - var includeUnknown: Bool - var limit: Int - } - struct SessionRow: Decodable { - var key: String - var updatedAt: Double? - var lastChannel: String? - var lastTo: String? - } - struct SessionsListResult: Decodable { - var sessions: [SessionRow] - } - - let normalize: (String?) -> String? = { raw in - let value = (raw ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - return value.isEmpty ? nil : value - } - - do { - let data = try JSONEncoder().encode( - Params(includeGlobal: true, includeUnknown: false, limit: 80)) - guard let json = String(data: data, encoding: .utf8) else { return } - let response = try await self.operatorGateway.request( - method: "sessions.list", - paramsJSON: json, - timeoutSeconds: 10) - let decoded = try JSONDecoder().decode(SessionsListResult.self, from: response) - let currentKey = self.mainSessionKey - let sorted = decoded.sessions.sorted { ($0.updatedAt ?? 0) > ($1.updatedAt ?? 0) } - let exactMatch = sorted.first { row in - row.key == currentKey && normalize(row.lastChannel) != nil && normalize(row.lastTo) != nil - } - let selected = exactMatch - let channel = normalize(selected?.lastChannel) - let to = normalize(selected?.lastTo) - - await MainActor.run { - self.shareDeliveryChannel = channel - self.shareDeliveryTo = to - if let relay = ShareGatewayRelaySettings.loadConfig() { - ShareGatewayRelaySettings.saveConfig( - ShareGatewayRelayConfig( - gatewayURLString: relay.gatewayURLString, - token: relay.token, - password: relay.password, - sessionKey: self.mainSessionKey, - deliveryChannel: channel, - deliveryTo: to)) - } - } - } catch { - // Best-effort only. - } - } - - func runSharePipelineSelfTest() async { - self.recordShareEvent("Share self-test running…") - - let payload = SharedContentPayload( - title: "OpenClaw Share Self-Test", - url: URL(string: "https://openclaw.ai/share-self-test"), - text: "Validate iOS share->deep-link->gateway forwarding.") - guard let deepLink = ShareToAgentDeepLink.buildURL( - from: payload, - instruction: "Reply with: SHARE SELF-TEST OK") - else { - self.recordShareEvent("Self-test failed: could not build deep link.") - return - } - - await self.handleDeepLink(url: deepLink) - } - - func refreshLastShareEventFromRelay() { - if let event = ShareGatewayRelaySettings.loadLastEvent() { - self.lastShareEventText = event - } - } - - func recordShareEvent(_ text: String) { - ShareGatewayRelaySettings.saveLastEvent(text) - self.refreshLastShareEventFromRelay() - } - - func reloadTalkConfig() { - Task { [weak self] in - await self?.talkMode.reloadConfig() - } - } - - /// Back-compat hook retained for older gateway-connect flows. - func onNodeGatewayConnected() async { - await self.registerAPNsTokenIfNeeded() - await self.flushQueuedWatchRepliesIfConnected() - } - - private func handleWatchQuickReply(_ event: WatchQuickReplyEvent) async { - let replyId = event.replyId.trimmingCharacters(in: .whitespacesAndNewlines) - let actionId = event.actionId.trimmingCharacters(in: .whitespacesAndNewlines) - if replyId.isEmpty || actionId.isEmpty { - self.watchReplyLogger.info("watch reply dropped: missing replyId/actionId") - return - } - - if self.seenWatchReplyIds.contains(replyId) { - self.watchReplyLogger.debug( - "watch reply deduped replyId=\(replyId, privacy: .public)") - return - } - self.seenWatchReplyIds.insert(replyId) - - if await !self.isGatewayConnected() { - self.queuedWatchReplies.append(event) - self.watchReplyLogger.info( - "watch reply queued replyId=\(replyId, privacy: .public) action=\(actionId, privacy: .public)") - return - } - - await self.forwardWatchReplyToAgent(event) - } - - private func flushQueuedWatchRepliesIfConnected() async { - guard await self.isGatewayConnected() else { return } - guard !self.queuedWatchReplies.isEmpty else { return } - - let pending = self.queuedWatchReplies - self.queuedWatchReplies.removeAll() - for event in pending { - await self.forwardWatchReplyToAgent(event) - } - } - - private func forwardWatchReplyToAgent(_ event: WatchQuickReplyEvent) async { - let sessionKey = event.sessionKey?.trimmingCharacters(in: .whitespacesAndNewlines) - let effectiveSessionKey = (sessionKey?.isEmpty == false) ? sessionKey : self.mainSessionKey - let message = Self.makeWatchReplyAgentMessage(event) - let link = AgentDeepLink( - message: message, - sessionKey: effectiveSessionKey, - thinking: "low", - deliver: false, - to: nil, - channel: nil, - timeoutSeconds: nil, - key: event.replyId) - do { - try await self.sendAgentRequest(link: link) - self.watchReplyLogger.info( - "watch reply forwarded replyId=\(event.replyId, privacy: .public) action=\(event.actionId, privacy: .public)") - self.openChatRequestID &+= 1 - } catch { - self.watchReplyLogger.error( - "watch reply forwarding failed replyId=\(event.replyId, privacy: .public) error=\(error.localizedDescription, privacy: .public)") - self.queuedWatchReplies.insert(event, at: 0) - } - } - - private static func makeWatchReplyAgentMessage(_ event: WatchQuickReplyEvent) -> String { - let actionLabel = event.actionLabel?.trimmingCharacters(in: .whitespacesAndNewlines) - let promptId = event.promptId.trimmingCharacters(in: .whitespacesAndNewlines) - let transport = event.transport.trimmingCharacters(in: .whitespacesAndNewlines) - let summary = actionLabel?.isEmpty == false ? actionLabel! : event.actionId - var lines: [String] = [] - lines.append("Watch reply: \(summary)") - lines.append("promptId=\(promptId.isEmpty ? "unknown" : promptId)") - lines.append("actionId=\(event.actionId)") - lines.append("replyId=\(event.replyId)") - if !transport.isEmpty { - lines.append("transport=\(transport)") - } - if let sentAtMs = event.sentAtMs { - lines.append("sentAtMs=\(sentAtMs)") - } - if let note = event.note?.trimmingCharacters(in: .whitespacesAndNewlines), !note.isEmpty { - lines.append("note=\(note)") - } - return lines.joined(separator: "\n") - } - - func handleSilentPushWake(_ userInfo: [AnyHashable: Any]) async -> Bool { - let wakeId = Self.makePushWakeAttemptID() - guard Self.isSilentPushPayload(userInfo) else { - self.pushWakeLogger.info("Ignored APNs payload wakeId=\(wakeId, privacy: .public): not silent push") - return false - } - let pushKind = Self.openclawPushKind(userInfo) - self.pushWakeLogger.info( - "Silent push received wakeId=\(wakeId, privacy: .public) kind=\(pushKind, privacy: .public) backgrounded=\(self.isBackgrounded, privacy: .public) autoReconnect=\(self.gatewayAutoReconnectEnabled, privacy: .public)") - let result = await self.reconnectGatewaySessionsForSilentPushIfNeeded(wakeId: wakeId) - self.pushWakeLogger.info( - "Silent push outcome wakeId=\(wakeId, privacy: .public) applied=\(result.applied, privacy: .public) reason=\(result.reason, privacy: .public) durationMs=\(result.durationMs, privacy: .public)") - return result.applied - } - - func handleBackgroundRefreshWake(trigger: String = "bg_app_refresh") async -> Bool { - let wakeId = Self.makePushWakeAttemptID() - self.pushWakeLogger.info( - "Background refresh wake received wakeId=\(wakeId, privacy: .public) trigger=\(trigger, privacy: .public) backgrounded=\(self.isBackgrounded, privacy: .public) autoReconnect=\(self.gatewayAutoReconnectEnabled, privacy: .public)") - let result = await self.reconnectGatewaySessionsForSilentPushIfNeeded(wakeId: wakeId) - self.pushWakeLogger.info( - "Background refresh wake outcome wakeId=\(wakeId, privacy: .public) applied=\(result.applied, privacy: .public) reason=\(result.reason, privacy: .public) durationMs=\(result.durationMs, privacy: .public)") - return result.applied - } - - func handleSignificantLocationWakeIfNeeded() async { - let wakeId = Self.makePushWakeAttemptID() - let now = Date() - let throttleWindowSeconds: TimeInterval = 180 - - if await self.isGatewayConnected() { - self.locationWakeLogger.info( - "Location wake no-op wakeId=\(wakeId, privacy: .public): already connected") - return - } - if let last = self.lastSignificantLocationWakeAt, - now.timeIntervalSince(last) < throttleWindowSeconds - { - self.locationWakeLogger.info( - "Location wake throttled wakeId=\(wakeId, privacy: .public) elapsedSec=\(now.timeIntervalSince(last), privacy: .public)") - return - } - self.lastSignificantLocationWakeAt = now - - self.locationWakeLogger.info( - "Location wake begin wakeId=\(wakeId, privacy: .public) backgrounded=\(self.isBackgrounded, privacy: .public) autoReconnect=\(self.gatewayAutoReconnectEnabled, privacy: .public)") - let result = await self.reconnectGatewaySessionsForSilentPushIfNeeded(wakeId: wakeId) - self.locationWakeLogger.info( - "Location wake trigger wakeId=\(wakeId, privacy: .public) applied=\(result.applied, privacy: .public) reason=\(result.reason, privacy: .public) durationMs=\(result.durationMs, privacy: .public)") - - guard result.applied else { return } - let connected = await self.waitForGatewayConnection(timeoutMs: 5000, pollMs: 250) - self.locationWakeLogger.info( - "Location wake post-check wakeId=\(wakeId, privacy: .public) connected=\(connected, privacy: .public)") - } - - func updateAPNsDeviceToken(_ tokenData: Data) { - let tokenHex = tokenData.map { String(format: "%02x", $0) }.joined() - let trimmed = tokenHex.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return } - self.apnsDeviceTokenHex = trimmed - UserDefaults.standard.set(trimmed, forKey: Self.apnsDeviceTokenUserDefaultsKey) - Task { [weak self] in - await self?.registerAPNsTokenIfNeeded() - } - } - - private func registerAPNsTokenIfNeeded() async { - guard self.gatewayConnected else { return } - guard let token = self.apnsDeviceTokenHex?.trimmingCharacters(in: .whitespacesAndNewlines), - !token.isEmpty - else { - return - } - if token == self.apnsLastRegisteredTokenHex { - return - } - guard let topic = Bundle.main.bundleIdentifier?.trimmingCharacters(in: .whitespacesAndNewlines), - !topic.isEmpty - else { - return - } - - struct PushRegistrationPayload: Codable { - var token: String - var topic: String - var environment: String - } - - let payload = PushRegistrationPayload( - token: token, - topic: topic, - environment: Self.apnsEnvironment) - do { - let json = try Self.encodePayload(payload) - await self.nodeGateway.sendEvent(event: "push.apns.register", payloadJSON: json) - self.apnsLastRegisteredTokenHex = token - } catch { - // Best-effort only. - } - } - - private static func isSilentPushPayload(_ userInfo: [AnyHashable: Any]) -> Bool { - guard let apsAny = userInfo["aps"] else { return false } - if let aps = apsAny as? [AnyHashable: Any] { - return Self.hasContentAvailable(aps["content-available"]) - } - if let aps = apsAny as? [String: Any] { - return Self.hasContentAvailable(aps["content-available"]) - } - return false - } - - private static func hasContentAvailable(_ value: Any?) -> Bool { - if let number = value as? NSNumber { - return number.intValue == 1 - } - if let text = value as? String { - return text.trimmingCharacters(in: .whitespacesAndNewlines) == "1" - } - return false - } - - private static func makePushWakeAttemptID() -> String { - let raw = UUID().uuidString.replacingOccurrences(of: "-", with: "") - return String(raw.prefix(8)) - } - - private static func openclawPushKind(_ userInfo: [AnyHashable: Any]) -> String { - if let payload = userInfo["openclaw"] as? [String: Any], - let kind = payload["kind"] as? String - { - let trimmed = kind.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmed.isEmpty { return trimmed } - } - if let payload = userInfo["openclaw"] as? [AnyHashable: Any], - let kind = payload["kind"] as? String - { - let trimmed = kind.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmed.isEmpty { return trimmed } - } - return "unknown" - } - - private struct SilentPushWakeAttemptResult { - var applied: Bool - var reason: String - var durationMs: Int - } - - private func waitForGatewayConnection(timeoutMs: Int, pollMs: Int) async -> Bool { - let clampedTimeoutMs = max(0, timeoutMs) - let pollIntervalNs = UInt64(max(50, pollMs)) * 1_000_000 - let deadline = Date().addingTimeInterval(Double(clampedTimeoutMs) / 1000.0) - while Date() < deadline { - if await self.isGatewayConnected() { - return true - } - try? await Task.sleep(nanoseconds: pollIntervalNs) - } - return await self.isGatewayConnected() - } - - private func reconnectGatewaySessionsForSilentPushIfNeeded( - wakeId: String - ) async -> SilentPushWakeAttemptResult { - let startedAt = Date() - let makeResult: (Bool, String) -> SilentPushWakeAttemptResult = { applied, reason in - let durationMs = Int(Date().timeIntervalSince(startedAt) * 1000) - return SilentPushWakeAttemptResult( - applied: applied, - reason: reason, - durationMs: max(0, durationMs)) - } - - guard self.isBackgrounded else { - self.pushWakeLogger.info("Wake no-op wakeId=\(wakeId, privacy: .public): app not backgrounded") - return makeResult(false, "not_backgrounded") - } - guard self.gatewayAutoReconnectEnabled else { - self.pushWakeLogger.info("Wake no-op wakeId=\(wakeId, privacy: .public): auto reconnect disabled") - return makeResult(false, "auto_reconnect_disabled") - } - guard let cfg = self.activeGatewayConnectConfig else { - self.pushWakeLogger.info("Wake no-op wakeId=\(wakeId, privacy: .public): no active gateway config") - return makeResult(false, "no_active_gateway_config") - } - - self.pushWakeLogger.info( - "Wake reconnect begin wakeId=\(wakeId, privacy: .public) stableID=\(cfg.stableID, privacy: .public)") - self.grantBackgroundReconnectLease(seconds: 30, reason: "wake_\(wakeId)") - await self.operatorGateway.disconnect() - await self.nodeGateway.disconnect() - self.operatorConnected = false - self.gatewayConnected = false - self.gatewayStatusText = "Reconnecting…" - self.talkMode.updateGatewayConnected(false) - self.applyGatewayConnectConfig(cfg) - self.pushWakeLogger.info("Wake reconnect trigger applied wakeId=\(wakeId, privacy: .public)") - return makeResult(true, "reconnect_triggered") - } -} - -extension NodeAppModel { - func _bridgeConsumeMirroredWatchReply(_ event: WatchQuickReplyEvent) async { - await self.handleWatchQuickReply(event) - } -} - -#if DEBUG -extension NodeAppModel { - func _test_handleInvoke(_ req: BridgeInvokeRequest) async -> BridgeInvokeResponse { - await self.handleInvoke(req) - } - - static func _test_decodeParams(_ type: T.Type, from json: String?) throws -> T { - try self.decodeParams(type, from: json) - } - - static func _test_encodePayload(_ obj: some Encodable) throws -> String { - try self.encodePayload(obj) - } - - func _test_isCameraEnabled() -> Bool { - self.isCameraEnabled() - } - - func _test_triggerCameraFlash() { - self.triggerCameraFlash() - } - - func _test_showCameraHUD(text: String, kind: CameraHUDKind, autoHideSeconds: Double? = nil) { - self.showCameraHUD(text: text, kind: kind, autoHideSeconds: autoHideSeconds) - } - - func _test_handleCanvasA2UIAction(body: [String: Any]) async { - await self.handleCanvasA2UIAction(body: body) - } - - func _test_showLocalCanvasOnDisconnect() { - self.showLocalCanvasOnDisconnect() - } - - func _test_applyTalkModeSync(enabled: Bool, phase: String? = nil) { - self.applyTalkModeSync(enabled: enabled, phase: phase) - } - - func _test_queuedWatchReplyCount() -> Int { - self.queuedWatchReplies.count - } -} -#endif diff --git a/apps/ios/Sources/Motion/MotionService.swift b/apps/ios/Sources/Motion/MotionService.swift deleted file mode 100644 index f108e0b560b..00000000000 --- a/apps/ios/Sources/Motion/MotionService.swift +++ /dev/null @@ -1,100 +0,0 @@ -import CoreMotion -import Foundation -import OpenClawKit - -final class MotionService: MotionServicing { - func activities(params: OpenClawMotionActivityParams) async throws -> OpenClawMotionActivityPayload { - guard CMMotionActivityManager.isActivityAvailable() else { - throw NSError(domain: "Motion", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "MOTION_UNAVAILABLE: activity not supported on this device", - ]) - } - let auth = CMMotionActivityManager.authorizationStatus() - guard auth == .authorized else { - throw NSError(domain: "Motion", code: 3, userInfo: [ - NSLocalizedDescriptionKey: "MOTION_PERMISSION_REQUIRED: grant Motion & Fitness permission", - ]) - } - - let (start, end) = Self.resolveRange(startISO: params.startISO, endISO: params.endISO) - let limit = max(1, min(params.limit ?? 200, 1000)) - - let manager = CMMotionActivityManager() - let mapped = try await withCheckedThrowingContinuation { (cont: CheckedContinuation<[OpenClawMotionActivityEntry], Error>) in - manager.queryActivityStarting(from: start, to: end, to: OperationQueue()) { activity, error in - if let error { - cont.resume(throwing: error) - } else { - let formatter = ISO8601DateFormatter() - let sliced = Array((activity ?? []).suffix(limit)) - let entries = sliced.map { entry in - OpenClawMotionActivityEntry( - startISO: formatter.string(from: entry.startDate), - endISO: formatter.string(from: end), - confidence: Self.confidenceString(entry.confidence), - isWalking: entry.walking, - isRunning: entry.running, - isCycling: entry.cycling, - isAutomotive: entry.automotive, - isStationary: entry.stationary, - isUnknown: entry.unknown) - } - cont.resume(returning: entries) - } - } - } - - return OpenClawMotionActivityPayload(activities: mapped) - } - - func pedometer(params: OpenClawPedometerParams) async throws -> OpenClawPedometerPayload { - guard CMPedometer.isStepCountingAvailable() else { - throw NSError(domain: "Motion", code: 2, userInfo: [ - NSLocalizedDescriptionKey: "PEDOMETER_UNAVAILABLE: step counting not supported", - ]) - } - let auth = CMPedometer.authorizationStatus() - guard auth == .authorized else { - throw NSError(domain: "Motion", code: 4, userInfo: [ - NSLocalizedDescriptionKey: "MOTION_PERMISSION_REQUIRED: grant Motion & Fitness permission", - ]) - } - - let (start, end) = Self.resolveRange(startISO: params.startISO, endISO: params.endISO) - let pedometer = CMPedometer() - let payload = try await withCheckedThrowingContinuation { (cont: CheckedContinuation) in - pedometer.queryPedometerData(from: start, to: end) { data, error in - if let error { - cont.resume(throwing: error) - } else { - let formatter = ISO8601DateFormatter() - let payload = OpenClawPedometerPayload( - startISO: formatter.string(from: start), - endISO: formatter.string(from: end), - steps: data?.numberOfSteps.intValue, - distanceMeters: data?.distance?.doubleValue, - floorsAscended: data?.floorsAscended?.intValue, - floorsDescended: data?.floorsDescended?.intValue) - cont.resume(returning: payload) - } - } - } - return payload - } - - private static func resolveRange(startISO: String?, endISO: String?) -> (Date, Date) { - let formatter = ISO8601DateFormatter() - let start = startISO.flatMap { formatter.date(from: $0) } ?? Calendar.current.startOfDay(for: Date()) - let end = endISO.flatMap { formatter.date(from: $0) } ?? Date() - return (start, end) - } - - private static func confidenceString(_ confidence: CMMotionActivityConfidence) -> String { - switch confidence { - case .low: "low" - case .medium: "medium" - case .high: "high" - @unknown default: "unknown" - } - } -} diff --git a/apps/ios/Sources/Onboarding/GatewayOnboardingView.swift b/apps/ios/Sources/Onboarding/GatewayOnboardingView.swift deleted file mode 100644 index bf6c0ba2d18..00000000000 --- a/apps/ios/Sources/Onboarding/GatewayOnboardingView.swift +++ /dev/null @@ -1,354 +0,0 @@ -import Foundation -import SwiftUI - -struct GatewayOnboardingView: View { - var body: some View { - NavigationStack { - List { - Section { - Text("Connect to your gateway to get started.") - .foregroundStyle(.secondary) - } - - Section { - NavigationLink("Auto detect") { - AutoDetectStep() - } - NavigationLink("Manual entry") { - ManualEntryStep() - } - } - } - .navigationTitle("Connect Gateway") - } - .gatewayTrustPromptAlert() - } -} - -private struct AutoDetectStep: View { - @Environment(NodeAppModel.self) private var appModel: NodeAppModel - @Environment(GatewayConnectionController.self) private var gatewayController: GatewayConnectionController - @AppStorage("gateway.preferredStableID") private var preferredGatewayStableID: String = "" - @AppStorage("gateway.lastDiscoveredStableID") private var lastDiscoveredGatewayStableID: String = "" - - @State private var connectingGatewayID: String? - @State private var connectStatusText: String? - - var body: some View { - Form { - Section { - Text("We’ll scan for gateways on your network and connect automatically when we find one.") - .foregroundStyle(.secondary) - } - - Section("Connection status") { - ConnectionStatusBox( - statusLines: self.connectionStatusLines(), - secondaryLine: self.connectStatusText) - } - - Section { - Button("Retry") { - self.resetConnectionState() - self.triggerAutoConnect() - } - .disabled(self.connectingGatewayID != nil) - } - } - .navigationTitle("Auto detect") - .onAppear { self.triggerAutoConnect() } - .onChange(of: self.gatewayController.gateways) { _, _ in - self.triggerAutoConnect() - } - } - - private func triggerAutoConnect() { - guard self.appModel.gatewayServerName == nil else { return } - guard self.connectingGatewayID == nil else { return } - guard let candidate = self.autoCandidate() else { return } - - self.connectingGatewayID = candidate.id - Task { - defer { self.connectingGatewayID = nil } - await self.gatewayController.connect(candidate) - } - } - - private func autoCandidate() -> GatewayDiscoveryModel.DiscoveredGateway? { - let preferred = self.preferredGatewayStableID.trimmingCharacters(in: .whitespacesAndNewlines) - let lastDiscovered = self.lastDiscoveredGatewayStableID.trimmingCharacters(in: .whitespacesAndNewlines) - - if !preferred.isEmpty, - let match = self.gatewayController.gateways.first(where: { $0.stableID == preferred }) - { - return match - } - if !lastDiscovered.isEmpty, - let match = self.gatewayController.gateways.first(where: { $0.stableID == lastDiscovered }) - { - return match - } - if self.gatewayController.gateways.count == 1 { - return self.gatewayController.gateways.first - } - return nil - } - - private func connectionStatusLines() -> [String] { - ConnectionStatusBox.defaultLines(appModel: self.appModel, gatewayController: self.gatewayController) - } - - private func resetConnectionState() { - self.appModel.disconnectGateway() - self.connectStatusText = nil - self.connectingGatewayID = nil - } -} - -private struct ManualEntryStep: View { - @Environment(NodeAppModel.self) private var appModel: NodeAppModel - @Environment(GatewayConnectionController.self) private var gatewayController: GatewayConnectionController - - @State private var setupCode: String = "" - @State private var setupStatusText: String? - @State private var manualHost: String = "" - @State private var manualPortText: String = "" - @State private var manualUseTLS: Bool = true - @State private var manualToken: String = "" - @State private var manualPassword: String = "" - - @State private var connectingGatewayID: String? - @State private var connectStatusText: String? - - var body: some View { - Form { - Section("Setup code") { - Text("Use /pair in your bot to get a setup code.") - .font(.footnote) - .foregroundStyle(.secondary) - - TextField("Paste setup code", text: self.$setupCode) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - - Button("Apply setup code") { - self.applySetupCode() - } - .disabled(self.setupCode.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) - - if let setupStatusText, !setupStatusText.isEmpty { - Text(setupStatusText) - .font(.footnote) - .foregroundStyle(.secondary) - } - } - - Section { - TextField("Host", text: self.$manualHost) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - - TextField("Port", text: self.$manualPortText) - .keyboardType(.numberPad) - - Toggle("Use TLS", isOn: self.$manualUseTLS) - - TextField("Gateway token", text: self.$manualToken) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - - SecureField("Gateway password", text: self.$manualPassword) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - } - - Section("Connection status") { - ConnectionStatusBox( - statusLines: self.connectionStatusLines(), - secondaryLine: self.connectStatusText) - } - - Section { - Button { - Task { await self.connectManual() } - } label: { - if self.connectingGatewayID == "manual" { - HStack(spacing: 8) { - ProgressView() - .progressViewStyle(.circular) - Text("Connecting…") - } - } else { - Text("Connect") - } - } - .disabled(self.connectingGatewayID != nil) - - Button("Retry") { - self.resetConnectionState() - self.resetManualForm() - } - .disabled(self.connectingGatewayID != nil) - } - } - .navigationTitle("Manual entry") - } - - private func connectManual() async { - let host = self.manualHost.trimmingCharacters(in: .whitespacesAndNewlines) - guard !host.isEmpty else { - self.connectStatusText = "Failed: host required" - return - } - - if let port = self.manualPortValue(), !(1...65535).contains(port) { - self.connectStatusText = "Failed: invalid port" - return - } - - let defaults = UserDefaults.standard - defaults.set(true, forKey: "gateway.manual.enabled") - defaults.set(host, forKey: "gateway.manual.host") - defaults.set(self.manualPortValue() ?? 0, forKey: "gateway.manual.port") - defaults.set(self.manualUseTLS, forKey: "gateway.manual.tls") - - if let instanceId = defaults.string(forKey: "node.instanceId")?.trimmingCharacters(in: .whitespacesAndNewlines), - !instanceId.isEmpty - { - let trimmedToken = self.manualToken.trimmingCharacters(in: .whitespacesAndNewlines) - let trimmedPassword = self.manualPassword.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmedToken.isEmpty { - GatewaySettingsStore.saveGatewayToken(trimmedToken, instanceId: instanceId) - } - GatewaySettingsStore.saveGatewayPassword(trimmedPassword, instanceId: instanceId) - } - - self.connectingGatewayID = "manual" - defer { self.connectingGatewayID = nil } - await self.gatewayController.connectManual( - host: host, - port: self.manualPortValue() ?? 0, - useTLS: self.manualUseTLS) - } - - private func manualPortValue() -> Int? { - let trimmed = self.manualPortText.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - return Int(trimmed.filter { $0.isNumber }) - } - - private func connectionStatusLines() -> [String] { - ConnectionStatusBox.defaultLines(appModel: self.appModel, gatewayController: self.gatewayController) - } - - private func resetConnectionState() { - self.appModel.disconnectGateway() - self.connectStatusText = nil - self.connectingGatewayID = nil - } - - private func resetManualForm() { - self.setupCode = "" - self.setupStatusText = nil - self.manualHost = "" - self.manualPortText = "" - self.manualUseTLS = true - self.manualToken = "" - self.manualPassword = "" - } - - private func applySetupCode() { - let raw = self.setupCode.trimmingCharacters(in: .whitespacesAndNewlines) - guard !raw.isEmpty else { - self.setupStatusText = "Paste a setup code to continue." - return - } - - guard let payload = GatewaySetupCode.decode(raw: raw) else { - self.setupStatusText = "Setup code not recognized." - return - } - - if let urlString = payload.url, let url = URL(string: urlString) { - self.applyURL(url) - } else if let host = payload.host, !host.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - self.manualHost = host.trimmingCharacters(in: .whitespacesAndNewlines) - if let port = payload.port { - self.manualPortText = String(port) - } else { - self.manualPortText = "" - } - if let tls = payload.tls { - self.manualUseTLS = tls - } - } else if let url = URL(string: raw), url.scheme != nil { - self.applyURL(url) - } else { - self.setupStatusText = "Setup code missing URL or host." - return - } - - if let token = payload.token, !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - self.manualToken = token.trimmingCharacters(in: .whitespacesAndNewlines) - } - if let password = payload.password, !password.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - self.manualPassword = password.trimmingCharacters(in: .whitespacesAndNewlines) - } - - self.setupStatusText = "Setup code applied." - } - - private func applyURL(_ url: URL) { - guard let host = url.host, !host.isEmpty else { return } - self.manualHost = host - if let port = url.port { - self.manualPortText = String(port) - } else { - self.manualPortText = "" - } - let scheme = (url.scheme ?? "").lowercased() - if scheme == "wss" || scheme == "https" { - self.manualUseTLS = true - } else if scheme == "ws" || scheme == "http" { - self.manualUseTLS = false - } - } - - // (GatewaySetupCode) decode raw setup codes. -} - -private struct ConnectionStatusBox: View { - let statusLines: [String] - let secondaryLine: String? - - var body: some View { - VStack(alignment: .leading, spacing: 6) { - ForEach(self.statusLines, id: \.self) { line in - Text(line) - .font(.system(size: 12, weight: .regular, design: .monospaced)) - .foregroundStyle(.secondary) - } - if let secondaryLine, !secondaryLine.isEmpty { - Text(secondaryLine) - .font(.footnote) - .foregroundStyle(.secondary) - } - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(10) - .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 10, style: .continuous)) - } - - static func defaultLines( - appModel: NodeAppModel, - gatewayController: GatewayConnectionController - ) -> [String] { - var lines: [String] = [ - "gateway: \(appModel.gatewayStatusText)", - "discovery: \(gatewayController.discoveryStatusText)", - ] - lines.append("server: \(appModel.gatewayServerName ?? "—")") - lines.append("address: \(appModel.gatewayRemoteAddress ?? "—")") - return lines - } -} diff --git a/apps/ios/Sources/Onboarding/OnboardingStateStore.swift b/apps/ios/Sources/Onboarding/OnboardingStateStore.swift deleted file mode 100644 index 9822ac1706f..00000000000 --- a/apps/ios/Sources/Onboarding/OnboardingStateStore.swift +++ /dev/null @@ -1,52 +0,0 @@ -import Foundation - -enum OnboardingConnectionMode: String, CaseIterable { - case homeNetwork = "home_network" - case remoteDomain = "remote_domain" - case developerLocal = "developer_local" - - var title: String { - switch self { - case .homeNetwork: - "Home Network" - case .remoteDomain: - "Remote Domain" - case .developerLocal: - "Same Machine (Dev)" - } - } -} - -enum OnboardingStateStore { - private static let completedDefaultsKey = "onboarding.completed" - private static let lastModeDefaultsKey = "onboarding.last_mode" - private static let lastSuccessTimeDefaultsKey = "onboarding.last_success_time" - - @MainActor - static func shouldPresentOnLaunch(appModel: NodeAppModel, defaults: UserDefaults = .standard) -> Bool { - if defaults.bool(forKey: Self.completedDefaultsKey) { return false } - // If we have a last-known connection config, don't force onboarding on launch. Auto-connect - // should handle reconnecting, and users can always open onboarding manually if needed. - if GatewaySettingsStore.loadLastGatewayConnection() != nil { return false } - return appModel.gatewayServerName == nil - } - - static func markCompleted(mode: OnboardingConnectionMode? = nil, defaults: UserDefaults = .standard) { - defaults.set(true, forKey: Self.completedDefaultsKey) - if let mode { - defaults.set(mode.rawValue, forKey: Self.lastModeDefaultsKey) - } - defaults.set(Int(Date().timeIntervalSince1970), forKey: Self.lastSuccessTimeDefaultsKey) - } - - static func markIncomplete(defaults: UserDefaults = .standard) { - defaults.set(false, forKey: Self.completedDefaultsKey) - } - - static func lastMode(defaults: UserDefaults = .standard) -> OnboardingConnectionMode? { - let raw = defaults.string(forKey: Self.lastModeDefaultsKey)? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - guard !raw.isEmpty else { return nil } - return OnboardingConnectionMode(rawValue: raw) - } -} diff --git a/apps/ios/Sources/Onboarding/OnboardingWizardView.swift b/apps/ios/Sources/Onboarding/OnboardingWizardView.swift deleted file mode 100644 index c0e872b2ceb..00000000000 --- a/apps/ios/Sources/Onboarding/OnboardingWizardView.swift +++ /dev/null @@ -1,890 +0,0 @@ -import CoreImage -import Combine -import OpenClawKit -import PhotosUI -import SwiftUI -import UIKit - -private enum OnboardingStep: Int, CaseIterable { - case welcome - case mode - case connect - case auth - case success - - var previous: Self? { - Self(rawValue: self.rawValue - 1) - } - - var next: Self? { - Self(rawValue: self.rawValue + 1) - } - - /// Progress label for the manual setup flow (mode → connect → auth → success). - var manualProgressTitle: String { - let manualSteps: [OnboardingStep] = [.mode, .connect, .auth, .success] - guard let idx = manualSteps.firstIndex(of: self) else { return "" } - return "Step \(idx + 1) of \(manualSteps.count)" - } - - var title: String { - switch self { - case .welcome: "Welcome" - case .mode: "Connection Mode" - case .connect: "Connect" - case .auth: "Authentication" - case .success: "Connected" - } - } - - var canGoBack: Bool { - self != .welcome && self != .success - } -} - -struct OnboardingWizardView: View { - @Environment(NodeAppModel.self) private var appModel: NodeAppModel - @Environment(GatewayConnectionController.self) private var gatewayController: GatewayConnectionController - @Environment(\.scenePhase) private var scenePhase - @AppStorage("node.instanceId") private var instanceId: String = UUID().uuidString - @AppStorage("gateway.discovery.domain") private var discoveryDomain: String = "" - @AppStorage("onboarding.developerMode") private var developerModeEnabled: Bool = false - @State private var step: OnboardingStep = .welcome - @State private var selectedMode: OnboardingConnectionMode? - @State private var manualHost: String = "" - @State private var manualPort: Int = 18789 - @State private var manualPortText: String = "18789" - @State private var manualTLS: Bool = true - @State private var gatewayToken: String = "" - @State private var gatewayPassword: String = "" - @State private var connectMessage: String? - @State private var statusLine: String = "Scan the QR code from your gateway to connect." - @State private var connectingGatewayID: String? - @State private var issue: GatewayConnectionIssue = .none - @State private var didMarkCompleted = false - @State private var didAutoPresentQR = false - @State private var pairingRequestId: String? - @State private var discoveryRestartTask: Task? - @State private var showQRScanner: Bool = false - @State private var scannerError: String? - @State private var selectedPhoto: PhotosPickerItem? - @State private var lastPairingAutoResumeAttemptAt: Date? - private static let pairingAutoResumeTicker = Timer.publish(every: 2.0, on: .main, in: .common).autoconnect() - - let allowSkip: Bool - let onClose: () -> Void - - private var isFullScreenStep: Bool { - self.step == .welcome || self.step == .success - } - - var body: some View { - NavigationStack { - Group { - switch self.step { - case .welcome: - self.welcomeStep - case .success: - self.successStep - default: - Form { - switch self.step { - case .mode: - self.modeStep - case .connect: - self.connectStep - case .auth: - self.authStep - default: - EmptyView() - } - } - .scrollDismissesKeyboard(.interactively) - } - } - .navigationTitle(self.isFullScreenStep ? "" : self.step.title) - .navigationBarTitleDisplayMode(.inline) - .toolbar { - if !self.isFullScreenStep { - ToolbarItem(placement: .principal) { - VStack(spacing: 2) { - Text(self.step.title) - .font(.headline) - Text(self.step.manualProgressTitle) - .font(.caption2) - .foregroundStyle(.secondary) - } - } - } - ToolbarItem(placement: .topBarLeading) { - if self.step.canGoBack { - Button { - self.navigateBack() - } label: { - Label("Back", systemImage: "chevron.left") - } - } else if self.allowSkip { - Button("Close") { - self.onClose() - } - } - } - ToolbarItemGroup(placement: .keyboard) { - Spacer() - Button("Done") { - UIApplication.shared.sendAction( - #selector(UIResponder.resignFirstResponder), - to: nil, from: nil, for: nil) - } - } - } - } - .gatewayTrustPromptAlert() - .alert("QR Scanner Unavailable", isPresented: Binding( - get: { self.scannerError != nil }, - set: { if !$0 { self.scannerError = nil } } - )) { - Button("OK", role: .cancel) {} - } message: { - Text(self.scannerError ?? "") - } - .sheet(isPresented: self.$showQRScanner) { - NavigationStack { - QRScannerView( - onGatewayLink: { link in - self.handleScannedLink(link) - }, - onError: { error in - self.showQRScanner = false - self.statusLine = "Scanner error: \(error)" - self.scannerError = error - }, - onDismiss: { - self.showQRScanner = false - }) - .ignoresSafeArea() - .navigationTitle("Scan QR Code") - .navigationBarTitleDisplayMode(.inline) - .toolbar { - ToolbarItem(placement: .topBarLeading) { - Button("Cancel") { self.showQRScanner = false } - } - ToolbarItem(placement: .topBarTrailing) { - PhotosPicker(selection: self.$selectedPhoto, matching: .images) { - Label("Photos", systemImage: "photo") - } - } - } - } - .onChange(of: self.selectedPhoto) { _, newValue in - guard let item = newValue else { return } - self.selectedPhoto = nil - Task { - guard let data = try? await item.loadTransferable(type: Data.self) else { - self.showQRScanner = false - self.scannerError = "Could not load the selected image." - return - } - if let message = self.detectQRCode(from: data) { - if let link = GatewayConnectDeepLink.fromSetupCode(message) { - self.handleScannedLink(link) - return - } - if let url = URL(string: message), - let route = DeepLinkParser.parse(url), - case let .gateway(link) = route - { - self.handleScannedLink(link) - return - } - } - self.showQRScanner = false - self.scannerError = "No valid QR code found in the selected image." - } - } - } - .onAppear { - self.initializeState() - } - .onDisappear { - self.discoveryRestartTask?.cancel() - self.discoveryRestartTask = nil - } - .onChange(of: self.discoveryDomain) { _, _ in - self.scheduleDiscoveryRestart() - } - .onChange(of: self.manualPortText) { _, newValue in - let digits = newValue.filter(\.isNumber) - if digits != newValue { - self.manualPortText = digits - return - } - guard let parsed = Int(digits), parsed > 0 else { - self.manualPort = 0 - return - } - self.manualPort = min(parsed, 65535) - } - .onChange(of: self.manualPort) { _, newValue in - let normalized = newValue > 0 ? String(newValue) : "" - if self.manualPortText != normalized { - self.manualPortText = normalized - } - } - .onChange(of: self.gatewayToken) { _, newValue in - self.saveGatewayCredentials(token: newValue, password: self.gatewayPassword) - } - .onChange(of: self.gatewayPassword) { _, newValue in - self.saveGatewayCredentials(token: self.gatewayToken, password: newValue) - } - .onChange(of: self.appModel.gatewayStatusText) { _, newValue in - let next = GatewayConnectionIssue.detect(from: newValue) - // Avoid "flip-flopping" the UI by clearing actionable issues when the underlying connection - // transitions through intermediate statuses (e.g. Offline/Connecting while reconnect churns). - if self.issue.needsPairing, next.needsPairing { - // Keep the requestId sticky even if the status line omits it after we pause. - let mergedRequestId = next.requestId ?? self.issue.requestId ?? self.pairingRequestId - self.issue = .pairingRequired(requestId: mergedRequestId) - } else if self.issue.needsPairing, !next.needsPairing { - // Ignore non-pairing statuses until the user explicitly retries/scans again, or we connect. - } else if self.issue.needsAuthToken, !next.needsAuthToken, !next.needsPairing { - // Same idea for auth: once we learn credentials are missing/rejected, keep that sticky until - // the user retries/scans again or we successfully connect. - } else { - self.issue = next - } - - if let requestId = next.requestId, !requestId.isEmpty { - self.pairingRequestId = requestId - } - - // If the gateway tells us auth is missing/rejected, stop reconnect churn until the user intervenes. - if next.needsAuthToken { - self.appModel.gatewayAutoReconnectEnabled = false - } - - if self.issue.needsAuthToken || self.issue.needsPairing { - self.step = .auth - } - if !newValue.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - self.connectMessage = newValue - self.statusLine = newValue - } - } - .onChange(of: self.appModel.gatewayServerName) { _, newValue in - guard newValue != nil else { return } - self.showQRScanner = false - self.statusLine = "Connected." - if !self.didMarkCompleted, let selectedMode { - OnboardingStateStore.markCompleted(mode: selectedMode) - self.didMarkCompleted = true - } - self.onClose() - } - .onChange(of: self.scenePhase) { _, newValue in - guard newValue == .active else { return } - self.attemptAutomaticPairingResumeIfNeeded() - } - .onReceive(Self.pairingAutoResumeTicker) { _ in - self.attemptAutomaticPairingResumeIfNeeded() - } - } - - @ViewBuilder - private var welcomeStep: some View { - VStack(spacing: 0) { - Spacer() - - Image(systemName: "qrcode.viewfinder") - .font(.system(size: 64)) - .foregroundStyle(.tint) - .padding(.bottom, 20) - - Text("Welcome") - .font(.largeTitle.weight(.bold)) - .padding(.bottom, 8) - - Text("Connect to your OpenClaw gateway") - .font(.subheadline) - .foregroundStyle(.secondary) - .multilineTextAlignment(.center) - .padding(.horizontal, 32) - - Spacer() - - VStack(spacing: 12) { - Button { - self.statusLine = "Opening QR scanner…" - self.showQRScanner = true - } label: { - Label("Scan QR Code", systemImage: "qrcode") - .frame(maxWidth: .infinity) - } - .buttonStyle(.borderedProminent) - .controlSize(.large) - - Button { - self.step = .mode - } label: { - Text("Set Up Manually") - .frame(maxWidth: .infinity) - } - .buttonStyle(.bordered) - .controlSize(.large) - } - .padding(.bottom, 12) - - Text(self.statusLine) - .font(.footnote) - .foregroundStyle(.secondary) - .multilineTextAlignment(.center) - .padding(.horizontal, 24) - .padding(.horizontal, 24) - .padding(.bottom, 48) - } - } - - @ViewBuilder - private var modeStep: some View { - Section("Connection Mode") { - OnboardingModeRow( - title: OnboardingConnectionMode.homeNetwork.title, - subtitle: "LAN or Tailscale host", - selected: self.selectedMode == .homeNetwork) - { - self.selectMode(.homeNetwork) - } - - OnboardingModeRow( - title: OnboardingConnectionMode.remoteDomain.title, - subtitle: "VPS with domain", - selected: self.selectedMode == .remoteDomain) - { - self.selectMode(.remoteDomain) - } - - Toggle( - "Developer mode", - isOn: Binding( - get: { self.developerModeEnabled }, - set: { newValue in - self.developerModeEnabled = newValue - if !newValue, self.selectedMode == .developerLocal { - self.selectedMode = nil - } - })) - - if self.developerModeEnabled { - OnboardingModeRow( - title: OnboardingConnectionMode.developerLocal.title, - subtitle: "For local iOS app development", - selected: self.selectedMode == .developerLocal) - { - self.selectMode(.developerLocal) - } - } - } - - Section { - Button("Continue") { - self.step = .connect - } - .disabled(self.selectedMode == nil) - } - } - - @ViewBuilder - private var connectStep: some View { - if let selectedMode { - Section { - LabeledContent("Mode", value: selectedMode.title) - LabeledContent("Discovery", value: self.gatewayController.discoveryStatusText) - LabeledContent("Status", value: self.appModel.gatewayStatusText) - LabeledContent("Progress", value: self.statusLine) - } header: { - Text("Status") - } footer: { - if let connectMessage { - Text(connectMessage) - } - } - - switch selectedMode { - case .homeNetwork: - self.homeNetworkConnectSection - case .remoteDomain: - self.remoteDomainConnectSection - case .developerLocal: - self.developerConnectSection - } - } else { - Section { - Text("Choose a mode first.") - Button("Back to Mode Selection") { - self.step = .mode - } - } - } - } - - private var homeNetworkConnectSection: some View { - Group { - Section("Discovered Gateways") { - if self.gatewayController.gateways.isEmpty { - Text("No gateways found yet.") - .foregroundStyle(.secondary) - } else { - ForEach(self.gatewayController.gateways) { gateway in - let hasHost = self.gatewayHasResolvableHost(gateway) - - HStack { - VStack(alignment: .leading, spacing: 4) { - Text(gateway.name) - if let host = gateway.lanHost ?? gateway.tailnetDns { - Text(host) - .font(.footnote) - .foregroundStyle(.secondary) - } - } - Spacer() - Button { - Task { await self.connectDiscoveredGateway(gateway) } - } label: { - if self.connectingGatewayID == gateway.id { - ProgressView() - .progressViewStyle(.circular) - } else if !hasHost { - Text("Resolving…") - } else { - Text("Connect") - } - } - .disabled(self.connectingGatewayID != nil || !hasHost) - } - } - } - - Button("Restart Discovery") { - self.gatewayController.restartDiscovery() - } - .disabled(self.connectingGatewayID != nil) - } - - self.manualConnectionFieldsSection(title: "Manual Fallback") - } - } - - private var remoteDomainConnectSection: some View { - self.manualConnectionFieldsSection(title: "Domain Settings") - } - - private var developerConnectSection: some View { - Section { - TextField("Host", text: self.$manualHost) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - TextField("Port", text: self.$manualPortText) - .keyboardType(.numberPad) - Toggle("Use TLS", isOn: self.$manualTLS) - - Button { - Task { await self.connectManual() } - } label: { - if self.connectingGatewayID == "manual" { - HStack(spacing: 8) { - ProgressView() - .progressViewStyle(.circular) - Text("Connecting…") - } - } else { - Text("Connect") - } - } - .disabled(!self.canConnectManual || self.connectingGatewayID != nil) - } header: { - Text("Developer Local") - } footer: { - Text("Default host is localhost. Use your Mac LAN IP if simulator networking requires it.") - } - } - - private var authStep: some View { - Group { - Section("Authentication") { - TextField("Gateway Auth Token", text: self.$gatewayToken) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - SecureField("Gateway Password", text: self.$gatewayPassword) - - if self.issue.needsAuthToken { - Text("Gateway rejected credentials. Scan a fresh QR code or update token/password.") - .font(.footnote) - .foregroundStyle(.secondary) - } else { - Text("Auth token looks valid.") - .font(.footnote) - .foregroundStyle(.secondary) - } - } - - if self.issue.needsPairing { - Section { - Button { - self.resumeAfterPairingApproval() - } label: { - Label("Resume After Approval", systemImage: "arrow.clockwise") - } - .disabled(self.connectingGatewayID != nil) - } header: { - Text("Pairing Approval") - } footer: { - let requestLine: String = { - if let id = self.issue.requestId, !id.isEmpty { - return "Request ID: \(id)" - } - return "Request ID: check `openclaw devices list`." - }() - Text( - "Approve this device on the gateway.\n" - + "1) `openclaw devices approve` (or `openclaw devices approve `)\n" - + "2) `/pair approve` in Telegram\n" - + "\(requestLine)\n" - + "OpenClaw will also retry automatically when you return to this app.") - } - } - - Section { - Button { - self.openQRScannerFromOnboarding() - } label: { - Label("Scan QR Code Again", systemImage: "qrcode.viewfinder") - } - .disabled(self.connectingGatewayID != nil) - - Button { - Task { await self.retryLastAttempt() } - } label: { - if self.connectingGatewayID == "retry" { - ProgressView() - .progressViewStyle(.circular) - } else { - Text("Retry Connection") - } - } - .disabled(self.connectingGatewayID != nil) - } - } - } - - private var successStep: some View { - VStack(spacing: 0) { - Spacer() - - Image(systemName: "checkmark.circle.fill") - .font(.system(size: 64)) - .foregroundStyle(.green) - .padding(.bottom, 20) - - Text("Connected") - .font(.largeTitle.weight(.bold)) - .padding(.bottom, 8) - - let server = self.appModel.gatewayServerName ?? "gateway" - Text(server) - .font(.subheadline) - .foregroundStyle(.secondary) - .padding(.bottom, 4) - - if let addr = self.appModel.gatewayRemoteAddress { - Text(addr) - .font(.subheadline) - .foregroundStyle(.secondary) - } - - Spacer() - - Button { - self.onClose() - } label: { - Text("Open OpenClaw") - .frame(maxWidth: .infinity) - } - .buttonStyle(.borderedProminent) - .controlSize(.large) - .padding(.horizontal, 24) - .padding(.bottom, 48) - } - } - - @ViewBuilder - private func manualConnectionFieldsSection(title: String) -> some View { - Section(title) { - TextField("Host", text: self.$manualHost) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - TextField("Port", text: self.$manualPortText) - .keyboardType(.numberPad) - Toggle("Use TLS", isOn: self.$manualTLS) - TextField("Discovery Domain (optional)", text: self.$discoveryDomain) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - - Button { - Task { await self.connectManual() } - } label: { - if self.connectingGatewayID == "manual" { - HStack(spacing: 8) { - ProgressView() - .progressViewStyle(.circular) - Text("Connecting…") - } - } else { - Text("Connect") - } - } - .disabled(!self.canConnectManual || self.connectingGatewayID != nil) - } - } - - private func handleScannedLink(_ link: GatewayConnectDeepLink) { - self.manualHost = link.host - self.manualPort = link.port - self.manualTLS = link.tls - if let token = link.token { - self.gatewayToken = token - } - if let password = link.password { - self.gatewayPassword = password - } - self.saveGatewayCredentials(token: self.gatewayToken, password: self.gatewayPassword) - self.showQRScanner = false - self.connectMessage = "Connecting via QR code…" - self.statusLine = "QR loaded. Connecting to \(link.host):\(link.port)…" - if self.selectedMode == nil { - self.selectedMode = link.tls ? .remoteDomain : .homeNetwork - } - Task { await self.connectManual() } - } - - private func openQRScannerFromOnboarding() { - // Stop active reconnect loops before scanning new credentials. - self.appModel.disconnectGateway() - self.connectingGatewayID = nil - self.connectMessage = nil - self.issue = .none - self.pairingRequestId = nil - self.statusLine = "Opening QR scanner…" - self.showQRScanner = true - } - - private func resumeAfterPairingApproval() { - // We intentionally stop reconnect churn while unpaired to avoid generating multiple pending requests. - self.appModel.gatewayAutoReconnectEnabled = true - self.appModel.gatewayPairingPaused = false - self.appModel.gatewayPairingRequestId = nil - // Pairing state is sticky to prevent UI flip-flop during reconnect churn. - // Once the user explicitly resumes after approving, clear the sticky issue - // so new status/auth errors can surface instead of being masked as pairing. - self.issue = .none - self.connectMessage = "Retrying after approval…" - self.statusLine = "Retrying after approval…" - Task { await self.retryLastAttempt() } - } - - private func resumeAfterPairingApprovalInBackground() { - // Keep the pairing issue sticky to avoid visual flicker while we probe for approval. - self.appModel.gatewayAutoReconnectEnabled = true - self.appModel.gatewayPairingPaused = false - self.appModel.gatewayPairingRequestId = nil - Task { await self.retryLastAttempt(silent: true) } - } - - private func attemptAutomaticPairingResumeIfNeeded() { - guard self.scenePhase == .active else { return } - guard self.step == .auth else { return } - guard self.issue.needsPairing else { return } - guard self.connectingGatewayID == nil else { return } - - let now = Date() - if let last = self.lastPairingAutoResumeAttemptAt, now.timeIntervalSince(last) < 6 { - return - } - self.lastPairingAutoResumeAttemptAt = now - self.resumeAfterPairingApprovalInBackground() - } - - private func detectQRCode(from data: Data) -> String? { - guard let ciImage = CIImage(data: data) else { return nil } - let detector = CIDetector( - ofType: CIDetectorTypeQRCode, context: nil, - options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]) - let features = detector?.features(in: ciImage) ?? [] - for feature in features { - if let qr = feature as? CIQRCodeFeature, let message = qr.messageString { - return message - } - } - return nil - } - - private func navigateBack() { - guard let target = self.step.previous else { return } - self.connectingGatewayID = nil - self.connectMessage = nil - self.step = target - } - private var canConnectManual: Bool { - let host = self.manualHost.trimmingCharacters(in: .whitespacesAndNewlines) - return !host.isEmpty && self.manualPort > 0 && self.manualPort <= 65535 - } - - private func initializeState() { - if self.manualHost.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - if let last = GatewaySettingsStore.loadLastGatewayConnection() { - switch last { - case let .manual(host, port, useTLS, _): - self.manualHost = host - self.manualPort = port - self.manualTLS = useTLS - case .discovered: - self.manualHost = "openclaw.local" - self.manualPort = 18789 - self.manualTLS = true - } - } else { - self.manualHost = "openclaw.local" - self.manualPort = 18789 - self.manualTLS = true - } - } - self.manualPortText = self.manualPort > 0 ? String(self.manualPort) : "" - if self.selectedMode == nil { - self.selectedMode = OnboardingStateStore.lastMode() - } - if self.selectedMode == .developerLocal && self.manualHost == "openclaw.local" { - self.manualHost = "localhost" - self.manualTLS = false - } - - let trimmedInstanceId = self.instanceId.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmedInstanceId.isEmpty { - self.gatewayToken = GatewaySettingsStore.loadGatewayToken(instanceId: trimmedInstanceId) ?? "" - self.gatewayPassword = GatewaySettingsStore.loadGatewayPassword(instanceId: trimmedInstanceId) ?? "" - } - - let hasSavedGateway = GatewaySettingsStore.loadLastGatewayConnection() != nil - let hasToken = !self.gatewayToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty - let hasPassword = !self.gatewayPassword.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty - if !self.didAutoPresentQR, !hasSavedGateway, !hasToken, !hasPassword { - self.didAutoPresentQR = true - self.statusLine = "No saved pairing found. Scan QR code to connect." - self.showQRScanner = true - } - } - - private func scheduleDiscoveryRestart() { - self.discoveryRestartTask?.cancel() - self.discoveryRestartTask = Task { @MainActor in - try? await Task.sleep(nanoseconds: 350_000_000) - guard !Task.isCancelled else { return } - self.gatewayController.restartDiscovery() - } - } - - private func saveGatewayCredentials(token: String, password: String) { - let trimmedInstanceId = self.instanceId.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmedInstanceId.isEmpty else { return } - let trimmedToken = token.trimmingCharacters(in: .whitespacesAndNewlines) - GatewaySettingsStore.saveGatewayToken(trimmedToken, instanceId: trimmedInstanceId) - let trimmedPassword = password.trimmingCharacters(in: .whitespacesAndNewlines) - GatewaySettingsStore.saveGatewayPassword(trimmedPassword, instanceId: trimmedInstanceId) - } - - private func connectDiscoveredGateway(_ gateway: GatewayDiscoveryModel.DiscoveredGateway) async { - self.connectingGatewayID = gateway.id - self.issue = .none - self.connectMessage = "Connecting to \(gateway.name)…" - self.statusLine = "Connecting to \(gateway.name)…" - defer { self.connectingGatewayID = nil } - await self.gatewayController.connect(gateway) - } - - private func selectMode(_ mode: OnboardingConnectionMode) { - self.selectedMode = mode - self.applyModeDefaults(mode) - } - - private func applyModeDefaults(_ mode: OnboardingConnectionMode) { - let host = self.manualHost.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - let hostIsDefaultLike = host.isEmpty || host == "openclaw.local" || host == "localhost" - - switch mode { - case .homeNetwork: - if hostIsDefaultLike { self.manualHost = "openclaw.local" } - self.manualTLS = true - if self.manualPort <= 0 || self.manualPort > 65535 { self.manualPort = 18789 } - case .remoteDomain: - if host == "openclaw.local" || host == "localhost" { self.manualHost = "" } - self.manualTLS = true - if self.manualPort <= 0 || self.manualPort > 65535 { self.manualPort = 18789 } - case .developerLocal: - if hostIsDefaultLike { self.manualHost = "localhost" } - self.manualTLS = false - if self.manualPort <= 0 || self.manualPort > 65535 { self.manualPort = 18789 } - } - } - - private func gatewayHasResolvableHost(_ gateway: GatewayDiscoveryModel.DiscoveredGateway) -> Bool { - let lanHost = gateway.lanHost?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if !lanHost.isEmpty { return true } - let tailnetDns = gateway.tailnetDns?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - return !tailnetDns.isEmpty - } - - private func connectManual() async { - let host = self.manualHost.trimmingCharacters(in: .whitespacesAndNewlines) - guard !host.isEmpty, self.manualPort > 0, self.manualPort <= 65535 else { return } - self.connectingGatewayID = "manual" - self.issue = .none - self.connectMessage = "Connecting to \(host)…" - self.statusLine = "Connecting to \(host):\(self.manualPort)…" - defer { self.connectingGatewayID = nil } - await self.gatewayController.connectManual(host: host, port: self.manualPort, useTLS: self.manualTLS) - } - - private func retryLastAttempt(silent: Bool = false) async { - self.connectingGatewayID = silent ? "retry-auto" : "retry" - // Keep current auth/pairing issue sticky while retrying to avoid Step 3 UI flip-flop. - if !silent { - self.connectMessage = "Retrying…" - self.statusLine = "Retrying last connection…" - } - defer { self.connectingGatewayID = nil } - await self.gatewayController.connectLastKnown() - } -} - -private struct OnboardingModeRow: View { - let title: String - let subtitle: String - let selected: Bool - let action: () -> Void - - var body: some View { - Button(action: self.action) { - HStack { - VStack(alignment: .leading, spacing: 2) { - Text(self.title) - .font(.body.weight(.semibold)) - Text(self.subtitle) - .font(.footnote) - .foregroundStyle(.secondary) - } - Spacer() - Image(systemName: self.selected ? "checkmark.circle.fill" : "circle") - .foregroundStyle(self.selected ? Color.accentColor : Color.secondary) - } - } - .buttonStyle(.plain) - } -} diff --git a/apps/ios/Sources/Onboarding/QRScannerView.swift b/apps/ios/Sources/Onboarding/QRScannerView.swift deleted file mode 100644 index d326c09c42b..00000000000 --- a/apps/ios/Sources/Onboarding/QRScannerView.swift +++ /dev/null @@ -1,96 +0,0 @@ -import OpenClawKit -import SwiftUI -import VisionKit - -struct QRScannerView: UIViewControllerRepresentable { - let onGatewayLink: (GatewayConnectDeepLink) -> Void - let onError: (String) -> Void - let onDismiss: () -> Void - - func makeUIViewController(context: Context) -> UIViewController { - guard DataScannerViewController.isSupported else { - context.coordinator.reportError("QR scanning is not supported on this device.") - return UIViewController() - } - guard DataScannerViewController.isAvailable else { - context.coordinator.reportError("Camera scanning is currently unavailable.") - return UIViewController() - } - let scanner = DataScannerViewController( - recognizedDataTypes: [.barcode(symbologies: [.qr])], - isHighlightingEnabled: true) - scanner.delegate = context.coordinator - do { - try scanner.startScanning() - } catch { - context.coordinator.reportError("Could not start QR scanner.") - } - return scanner - } - - func updateUIViewController(_: UIViewController, context _: Context) {} - - static func dismantleUIViewController(_ uiViewController: UIViewController, coordinator: Coordinator) { - if let scanner = uiViewController as? DataScannerViewController { - scanner.stopScanning() - } - coordinator.parent.onDismiss() - } - - func makeCoordinator() -> Coordinator { - Coordinator(parent: self) - } - - final class Coordinator: NSObject, DataScannerViewControllerDelegate { - let parent: QRScannerView - private var handled = false - private var reportedError = false - - init(parent: QRScannerView) { - self.parent = parent - } - - func reportError(_ message: String) { - guard !self.reportedError else { return } - self.reportedError = true - Task { @MainActor in - self.parent.onError(message) - } - } - - func dataScanner(_: DataScannerViewController, didAdd items: [RecognizedItem], allItems _: [RecognizedItem]) { - guard !self.handled else { return } - for item in items { - guard case let .barcode(barcode) = item, - let payload = barcode.payloadStringValue - else { continue } - - // Try setup code format first (base64url JSON from /pair qr). - if let link = GatewayConnectDeepLink.fromSetupCode(payload) { - self.handled = true - self.parent.onGatewayLink(link) - return - } - - // Fall back to deep link URL format (openclaw://gateway?...). - if let url = URL(string: payload), - let route = DeepLinkParser.parse(url), - case let .gateway(link) = route - { - self.handled = true - self.parent.onGatewayLink(link) - return - } - } - } - - func dataScanner(_: DataScannerViewController, didRemove _: [RecognizedItem], allItems _: [RecognizedItem]) {} - - func dataScanner( - _: DataScannerViewController, - becameUnavailableWithError _: DataScannerViewController.ScanningUnavailable) - { - self.reportError("Camera is not available on this device.") - } - } -} diff --git a/apps/ios/Sources/OpenClaw.entitlements b/apps/ios/Sources/OpenClaw.entitlements deleted file mode 100644 index a2663ce930b..00000000000 --- a/apps/ios/Sources/OpenClaw.entitlements +++ /dev/null @@ -1,9 +0,0 @@ - - - - - aps-environment - development - - - diff --git a/apps/ios/Sources/OpenClawApp.swift b/apps/ios/Sources/OpenClawApp.swift deleted file mode 100644 index 335e09fd986..00000000000 --- a/apps/ios/Sources/OpenClawApp.swift +++ /dev/null @@ -1,499 +0,0 @@ -import SwiftUI -import Foundation -import OpenClawKit -import os -import UIKit -import BackgroundTasks -import UserNotifications - -private struct PendingWatchPromptAction { - var promptId: String? - var actionId: String - var actionLabel: String? - var sessionKey: String? -} - -@MainActor -final class OpenClawAppDelegate: NSObject, UIApplicationDelegate, @preconcurrency UNUserNotificationCenterDelegate { - private let logger = Logger(subsystem: "ai.openclaw.ios", category: "Push") - private let backgroundWakeLogger = Logger(subsystem: "ai.openclaw.ios", category: "BackgroundWake") - private static let wakeRefreshTaskIdentifier = "ai.openclaw.ios.bgrefresh" - private var backgroundWakeTask: Task? - private var pendingAPNsDeviceToken: Data? - private var pendingWatchPromptActions: [PendingWatchPromptAction] = [] - - weak var appModel: NodeAppModel? { - didSet { - guard let model = self.appModel else { return } - if let token = self.pendingAPNsDeviceToken { - self.pendingAPNsDeviceToken = nil - Task { @MainActor in - model.updateAPNsDeviceToken(token) - } - } - if !self.pendingWatchPromptActions.isEmpty { - let pending = self.pendingWatchPromptActions - self.pendingWatchPromptActions.removeAll() - Task { @MainActor in - for action in pending { - await model.handleMirroredWatchPromptAction( - promptId: action.promptId, - actionId: action.actionId, - actionLabel: action.actionLabel, - sessionKey: action.sessionKey) - } - } - } - } - } - - func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil - ) -> Bool - { - self.registerBackgroundWakeRefreshTask() - UNUserNotificationCenter.current().delegate = self - application.registerForRemoteNotifications() - return true - } - - func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { - if let appModel = self.appModel { - Task { @MainActor in - appModel.updateAPNsDeviceToken(deviceToken) - } - return - } - - self.pendingAPNsDeviceToken = deviceToken - } - - func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: any Error) { - self.logger.error("APNs registration failed: \(error.localizedDescription, privacy: .public)") - } - - func application( - _ application: UIApplication, - didReceiveRemoteNotification userInfo: [AnyHashable: Any], - fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) - { - self.logger.info("APNs remote notification received keys=\(userInfo.keys.count, privacy: .public)") - Task { @MainActor in - guard let appModel = self.appModel else { - self.logger.info("APNs wake skipped: appModel unavailable") - self.scheduleBackgroundWakeRefresh(afterSeconds: 90, reason: "silent_push_no_model") - completionHandler(.noData) - return - } - let handled = await appModel.handleSilentPushWake(userInfo) - self.logger.info("APNs wake handled=\(handled, privacy: .public)") - if !handled { - self.scheduleBackgroundWakeRefresh(afterSeconds: 90, reason: "silent_push_not_applied") - } - completionHandler(handled ? .newData : .noData) - } - } - - func scenePhaseChanged(_ phase: ScenePhase) { - if phase == .background { - self.scheduleBackgroundWakeRefresh(afterSeconds: 120, reason: "scene_background") - } - } - - private func registerBackgroundWakeRefreshTask() { - BGTaskScheduler.shared.register( - forTaskWithIdentifier: Self.wakeRefreshTaskIdentifier, - using: nil - ) { [weak self] task in - guard let refreshTask = task as? BGAppRefreshTask else { - task.setTaskCompleted(success: false) - return - } - self?.handleBackgroundWakeRefresh(task: refreshTask) - } - } - - private func scheduleBackgroundWakeRefresh(afterSeconds delay: TimeInterval, reason: String) { - let request = BGAppRefreshTaskRequest(identifier: Self.wakeRefreshTaskIdentifier) - request.earliestBeginDate = Date().addingTimeInterval(max(60, delay)) - do { - try BGTaskScheduler.shared.submit(request) - self.backgroundWakeLogger.info( - "Scheduled background wake refresh reason=\(reason, privacy: .public) delaySeconds=\(max(60, delay), privacy: .public)") - } catch { - self.backgroundWakeLogger.error( - "Failed scheduling background wake refresh reason=\(reason, privacy: .public) error=\(error.localizedDescription, privacy: .public)") - } - } - - private func handleBackgroundWakeRefresh(task: BGAppRefreshTask) { - self.scheduleBackgroundWakeRefresh(afterSeconds: 15 * 60, reason: "reschedule") - self.backgroundWakeTask?.cancel() - - let wakeTask = Task { @MainActor [weak self] in - guard let self, let appModel = self.appModel else { return false } - return await appModel.handleBackgroundRefreshWake(trigger: "bg_app_refresh") - } - self.backgroundWakeTask = wakeTask - task.expirationHandler = { - wakeTask.cancel() - } - Task { - let applied = await wakeTask.value - task.setTaskCompleted(success: applied) - self.backgroundWakeLogger.info( - "Background wake refresh finished applied=\(applied, privacy: .public)") - } - } - - private static func isWatchPromptNotification(_ userInfo: [AnyHashable: Any]) -> Bool { - (userInfo[WatchPromptNotificationBridge.typeKey] as? String) == WatchPromptNotificationBridge.typeValue - } - - private static func parseWatchPromptAction( - from response: UNNotificationResponse) -> PendingWatchPromptAction? - { - let userInfo = response.notification.request.content.userInfo - guard Self.isWatchPromptNotification(userInfo) else { return nil } - - let promptId = userInfo[WatchPromptNotificationBridge.promptIDKey] as? String - let sessionKey = userInfo[WatchPromptNotificationBridge.sessionKeyKey] as? String - - switch response.actionIdentifier { - case WatchPromptNotificationBridge.actionPrimaryIdentifier: - let actionId = (userInfo[WatchPromptNotificationBridge.actionPrimaryIDKey] as? String)? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - guard !actionId.isEmpty else { return nil } - let actionLabel = userInfo[WatchPromptNotificationBridge.actionPrimaryLabelKey] as? String - return PendingWatchPromptAction( - promptId: promptId, - actionId: actionId, - actionLabel: actionLabel, - sessionKey: sessionKey) - case WatchPromptNotificationBridge.actionSecondaryIdentifier: - let actionId = (userInfo[WatchPromptNotificationBridge.actionSecondaryIDKey] as? String)? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - guard !actionId.isEmpty else { return nil } - let actionLabel = userInfo[WatchPromptNotificationBridge.actionSecondaryLabelKey] as? String - return PendingWatchPromptAction( - promptId: promptId, - actionId: actionId, - actionLabel: actionLabel, - sessionKey: sessionKey) - default: - return nil - } - } - - private func routeWatchPromptAction(_ action: PendingWatchPromptAction) async { - guard let appModel = self.appModel else { - self.pendingWatchPromptActions.append(action) - return - } - await appModel.handleMirroredWatchPromptAction( - promptId: action.promptId, - actionId: action.actionId, - actionLabel: action.actionLabel, - sessionKey: action.sessionKey) - _ = await appModel.handleBackgroundRefreshWake(trigger: "watch_prompt_action") - } - - func userNotificationCenter( - _ center: UNUserNotificationCenter, - willPresent notification: UNNotification, - withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) - { - let userInfo = notification.request.content.userInfo - if Self.isWatchPromptNotification(userInfo) { - completionHandler([.banner, .list, .sound]) - return - } - completionHandler([]) - } - - func userNotificationCenter( - _ center: UNUserNotificationCenter, - didReceive response: UNNotificationResponse, - withCompletionHandler completionHandler: @escaping () -> Void) - { - guard let action = Self.parseWatchPromptAction(from: response) else { - completionHandler() - return - } - Task { @MainActor [weak self] in - guard let self else { - completionHandler() - return - } - await self.routeWatchPromptAction(action) - completionHandler() - } - } -} - -enum WatchPromptNotificationBridge { - static let typeKey = "openclaw.type" - static let typeValue = "watch.prompt" - static let promptIDKey = "openclaw.watch.promptId" - static let sessionKeyKey = "openclaw.watch.sessionKey" - static let actionPrimaryIDKey = "openclaw.watch.action.primary.id" - static let actionPrimaryLabelKey = "openclaw.watch.action.primary.label" - static let actionSecondaryIDKey = "openclaw.watch.action.secondary.id" - static let actionSecondaryLabelKey = "openclaw.watch.action.secondary.label" - static let actionPrimaryIdentifier = "openclaw.watch.action.primary" - static let actionSecondaryIdentifier = "openclaw.watch.action.secondary" - static let categoryPrefix = "openclaw.watch.prompt.category." - - @MainActor - static func scheduleMirroredWatchPromptNotificationIfNeeded( - invokeID: String, - params: OpenClawWatchNotifyParams, - sendResult: WatchNotificationSendResult) async - { - guard sendResult.queuedForDelivery || !sendResult.deliveredImmediately else { return } - - let title = params.title.trimmingCharacters(in: .whitespacesAndNewlines) - let body = params.body.trimmingCharacters(in: .whitespacesAndNewlines) - guard !title.isEmpty || !body.isEmpty else { return } - guard await self.requestNotificationAuthorizationIfNeeded() else { return } - - let normalizedActions = (params.actions ?? []).compactMap { action -> OpenClawWatchAction? in - let id = action.id.trimmingCharacters(in: .whitespacesAndNewlines) - let label = action.label.trimmingCharacters(in: .whitespacesAndNewlines) - guard !id.isEmpty, !label.isEmpty else { return nil } - return OpenClawWatchAction(id: id, label: label, style: action.style) - } - let primaryAction = normalizedActions.first - let secondaryAction = normalizedActions.dropFirst().first - - let center = UNUserNotificationCenter.current() - var categoryIdentifier = "" - if let primaryAction { - let categoryID = "\(self.categoryPrefix)\(invokeID)" - let category = UNNotificationCategory( - identifier: categoryID, - actions: self.categoryActions(primaryAction: primaryAction, secondaryAction: secondaryAction), - intentIdentifiers: [], - options: []) - await self.upsertNotificationCategory(category, center: center) - categoryIdentifier = categoryID - } - - var userInfo: [AnyHashable: Any] = [ - self.typeKey: self.typeValue, - ] - if let promptId = params.promptId?.trimmingCharacters(in: .whitespacesAndNewlines), !promptId.isEmpty { - userInfo[self.promptIDKey] = promptId - } - if let sessionKey = params.sessionKey?.trimmingCharacters(in: .whitespacesAndNewlines), !sessionKey.isEmpty { - userInfo[self.sessionKeyKey] = sessionKey - } - if let primaryAction { - userInfo[self.actionPrimaryIDKey] = primaryAction.id - userInfo[self.actionPrimaryLabelKey] = primaryAction.label - } - if let secondaryAction { - userInfo[self.actionSecondaryIDKey] = secondaryAction.id - userInfo[self.actionSecondaryLabelKey] = secondaryAction.label - } - - let content = UNMutableNotificationContent() - content.title = title.isEmpty ? "OpenClaw" : title - content.body = body - content.sound = .default - content.userInfo = userInfo - if !categoryIdentifier.isEmpty { - content.categoryIdentifier = categoryIdentifier - } - if #available(iOS 15.0, *) { - switch params.priority ?? .active { - case .passive: - content.interruptionLevel = .passive - case .timeSensitive: - content.interruptionLevel = .timeSensitive - case .active: - content.interruptionLevel = .active - } - } - - let request = UNNotificationRequest( - identifier: "watch.prompt.\(invokeID)", - content: content, - trigger: nil) - try? await self.addNotificationRequest(request, center: center) - } - - private static func categoryActions( - primaryAction: OpenClawWatchAction, - secondaryAction: OpenClawWatchAction?) -> [UNNotificationAction] - { - var actions: [UNNotificationAction] = [ - UNNotificationAction( - identifier: self.actionPrimaryIdentifier, - title: primaryAction.label, - options: self.notificationActionOptions(style: primaryAction.style)) - ] - if let secondaryAction { - actions.append( - UNNotificationAction( - identifier: self.actionSecondaryIdentifier, - title: secondaryAction.label, - options: self.notificationActionOptions(style: secondaryAction.style))) - } - return actions - } - - private static func notificationActionOptions(style: String?) -> UNNotificationActionOptions { - switch style?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() { - case "destructive": - return [.destructive] - case "foreground": - // For mirrored watch actions, keep handling in background when possible. - return [] - default: - return [] - } - } - - private static func requestNotificationAuthorizationIfNeeded() async -> Bool { - let center = UNUserNotificationCenter.current() - let status = await self.notificationAuthorizationStatus(center: center) - switch status { - case .authorized, .provisional, .ephemeral: - return true - case .notDetermined: - let granted = (try? await center.requestAuthorization(options: [.alert, .sound, .badge])) ?? false - if !granted { return false } - let updatedStatus = await self.notificationAuthorizationStatus(center: center) - return self.isAuthorizationStatusAllowed(updatedStatus) - case .denied: - return false - @unknown default: - return false - } - } - - private static func isAuthorizationStatusAllowed(_ status: UNAuthorizationStatus) -> Bool { - switch status { - case .authorized, .provisional, .ephemeral: - return true - case .denied, .notDetermined: - return false - @unknown default: - return false - } - } - - private static func notificationAuthorizationStatus(center: UNUserNotificationCenter) async -> UNAuthorizationStatus { - await withCheckedContinuation { continuation in - center.getNotificationSettings { settings in - continuation.resume(returning: settings.authorizationStatus) - } - } - } - - private static func upsertNotificationCategory( - _ category: UNNotificationCategory, - center: UNUserNotificationCenter) async - { - await withCheckedContinuation { continuation in - center.getNotificationCategories { categories in - var updated = categories - updated.update(with: category) - center.setNotificationCategories(updated) - continuation.resume() - } - } - } - - private static func addNotificationRequest(_ request: UNNotificationRequest, center: UNUserNotificationCenter) async throws { - try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in - center.add(request) { error in - if let error { - continuation.resume(throwing: error) - } else { - continuation.resume(returning: ()) - } - } - } - } -} - -extension NodeAppModel { - func handleMirroredWatchPromptAction( - promptId: String?, - actionId: String, - actionLabel: String?, - sessionKey: String?) async - { - let normalizedActionID = actionId.trimmingCharacters(in: .whitespacesAndNewlines) - guard !normalizedActionID.isEmpty else { return } - - let normalizedPromptID = promptId?.trimmingCharacters(in: .whitespacesAndNewlines) - let normalizedSessionKey = sessionKey?.trimmingCharacters(in: .whitespacesAndNewlines) - let normalizedActionLabel = actionLabel?.trimmingCharacters(in: .whitespacesAndNewlines) - - let event = WatchQuickReplyEvent( - replyId: UUID().uuidString, - promptId: (normalizedPromptID?.isEmpty == false) ? normalizedPromptID! : "unknown", - actionId: normalizedActionID, - actionLabel: (normalizedActionLabel?.isEmpty == false) ? normalizedActionLabel : nil, - sessionKey: (normalizedSessionKey?.isEmpty == false) ? normalizedSessionKey : nil, - note: "source=ios.notification", - sentAtMs: Int(Date().timeIntervalSince1970 * 1000), - transport: "ios.notification") - await self._bridgeConsumeMirroredWatchReply(event) - } -} - -@main -struct OpenClawApp: App { - @State private var appModel: NodeAppModel - @State private var gatewayController: GatewayConnectionController - @UIApplicationDelegateAdaptor(OpenClawAppDelegate.self) private var appDelegate - @Environment(\.scenePhase) private var scenePhase - - init() { - Self.installUncaughtExceptionLogger() - GatewaySettingsStore.bootstrapPersistence() - let appModel = NodeAppModel() - _appModel = State(initialValue: appModel) - _gatewayController = State(initialValue: GatewayConnectionController(appModel: appModel)) - } - - var body: some Scene { - WindowGroup { - RootCanvas() - .environment(self.appModel) - .environment(self.appModel.voiceWake) - .environment(self.gatewayController) - .task { - self.appDelegate.appModel = self.appModel - } - .onOpenURL { url in - Task { await self.appModel.handleDeepLink(url: url) } - } - .onChange(of: self.scenePhase) { _, newValue in - self.appModel.setScenePhase(newValue) - self.gatewayController.setScenePhase(newValue) - self.appDelegate.scenePhaseChanged(newValue) - } - } - } -} - -extension OpenClawApp { - private static func installUncaughtExceptionLogger() { - NSLog("OpenClaw: installing uncaught exception handler") - NSSetUncaughtExceptionHandler { exception in - // Useful when the app hits NSExceptions from SwiftUI/WebKit internals; these do not - // produce a normal Swift error backtrace. - let reason = exception.reason ?? "(no reason)" - NSLog("UNCAUGHT EXCEPTION: %@ %@", exception.name.rawValue, reason) - for line in exception.callStackSymbols { - NSLog(" %@", line) - } - } - } -} diff --git a/apps/ios/Sources/Reminders/RemindersService.swift b/apps/ios/Sources/Reminders/RemindersService.swift deleted file mode 100644 index 249f439fb17..00000000000 --- a/apps/ios/Sources/Reminders/RemindersService.swift +++ /dev/null @@ -1,133 +0,0 @@ -import EventKit -import Foundation -import OpenClawKit - -final class RemindersService: RemindersServicing { - func list(params: OpenClawRemindersListParams) async throws -> OpenClawRemindersListPayload { - let store = EKEventStore() - let status = EKEventStore.authorizationStatus(for: .reminder) - let authorized = EventKitAuthorization.allowsRead(status: status) - guard authorized else { - throw NSError(domain: "Reminders", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "REMINDERS_PERMISSION_REQUIRED: grant Reminders permission", - ]) - } - - let limit = max(1, min(params.limit ?? 50, 500)) - let statusFilter = params.status ?? .incomplete - - let predicate = store.predicateForReminders(in: nil) - let payload = try await withCheckedThrowingContinuation { (cont: CheckedContinuation<[OpenClawReminderPayload], Error>) in - store.fetchReminders(matching: predicate) { items in - let formatter = ISO8601DateFormatter() - let filtered = (items ?? []).filter { reminder in - switch statusFilter { - case .all: - return true - case .completed: - return reminder.isCompleted - case .incomplete: - return !reminder.isCompleted - } - } - let selected = Array(filtered.prefix(limit)) - let payload = selected.map { reminder in - let due = reminder.dueDateComponents.flatMap { Calendar.current.date(from: $0) } - return OpenClawReminderPayload( - identifier: reminder.calendarItemIdentifier, - title: reminder.title, - dueISO: due.map { formatter.string(from: $0) }, - completed: reminder.isCompleted, - listName: reminder.calendar.title) - } - cont.resume(returning: payload) - } - } - - return OpenClawRemindersListPayload(reminders: payload) - } - - func add(params: OpenClawRemindersAddParams) async throws -> OpenClawRemindersAddPayload { - let store = EKEventStore() - let status = EKEventStore.authorizationStatus(for: .reminder) - let authorized = EventKitAuthorization.allowsWrite(status: status) - guard authorized else { - throw NSError(domain: "Reminders", code: 2, userInfo: [ - NSLocalizedDescriptionKey: "REMINDERS_PERMISSION_REQUIRED: grant Reminders permission", - ]) - } - - let title = params.title.trimmingCharacters(in: .whitespacesAndNewlines) - guard !title.isEmpty else { - throw NSError(domain: "Reminders", code: 3, userInfo: [ - NSLocalizedDescriptionKey: "REMINDERS_INVALID: title required", - ]) - } - - let reminder = EKReminder(eventStore: store) - reminder.title = title - if let notes = params.notes?.trimmingCharacters(in: .whitespacesAndNewlines), !notes.isEmpty { - reminder.notes = notes - } - reminder.calendar = try Self.resolveList( - store: store, - listId: params.listId, - listName: params.listName) - - if let dueISO = params.dueISO?.trimmingCharacters(in: .whitespacesAndNewlines), !dueISO.isEmpty { - let formatter = ISO8601DateFormatter() - guard let dueDate = formatter.date(from: dueISO) else { - throw NSError(domain: "Reminders", code: 4, userInfo: [ - NSLocalizedDescriptionKey: "REMINDERS_INVALID: dueISO must be ISO-8601", - ]) - } - reminder.dueDateComponents = Calendar.current.dateComponents( - [.year, .month, .day, .hour, .minute, .second], - from: dueDate) - } - - try store.save(reminder, commit: true) - - let formatter = ISO8601DateFormatter() - let due = reminder.dueDateComponents.flatMap { Calendar.current.date(from: $0) } - let payload = OpenClawReminderPayload( - identifier: reminder.calendarItemIdentifier, - title: reminder.title, - dueISO: due.map { formatter.string(from: $0) }, - completed: reminder.isCompleted, - listName: reminder.calendar.title) - - return OpenClawRemindersAddPayload(reminder: payload) - } - - private static func resolveList( - store: EKEventStore, - listId: String?, - listName: String?) throws -> EKCalendar - { - if let id = listId?.trimmingCharacters(in: .whitespacesAndNewlines), !id.isEmpty, - let calendar = store.calendar(withIdentifier: id) - { - return calendar - } - - if let title = listName?.trimmingCharacters(in: .whitespacesAndNewlines), !title.isEmpty { - if let calendar = store.calendars(for: .reminder).first(where: { - $0.title.compare(title, options: [.caseInsensitive, .diacriticInsensitive]) == .orderedSame - }) { - return calendar - } - throw NSError(domain: "Reminders", code: 5, userInfo: [ - NSLocalizedDescriptionKey: "REMINDERS_LIST_NOT_FOUND: no list named \(title)", - ]) - } - - if let fallback = store.defaultCalendarForNewReminders() { - return fallback - } - - throw NSError(domain: "Reminders", code: 6, userInfo: [ - NSLocalizedDescriptionKey: "REMINDERS_LIST_NOT_FOUND: no default list", - ]) - } -} diff --git a/apps/ios/Sources/RootCanvas.swift b/apps/ios/Sources/RootCanvas.swift deleted file mode 100644 index da893d3c943..00000000000 --- a/apps/ios/Sources/RootCanvas.swift +++ /dev/null @@ -1,505 +0,0 @@ -import SwiftUI -import UIKit - -struct RootCanvas: View { - @Environment(NodeAppModel.self) private var appModel - @Environment(GatewayConnectionController.self) private var gatewayController - @Environment(VoiceWakeManager.self) private var voiceWake - @Environment(\.colorScheme) private var systemColorScheme - @Environment(\.scenePhase) private var scenePhase - @AppStorage(VoiceWakePreferences.enabledKey) private var voiceWakeEnabled: Bool = false - @AppStorage("screen.preventSleep") private var preventSleep: Bool = true - @AppStorage("canvas.debugStatusEnabled") private var canvasDebugStatusEnabled: Bool = false - @AppStorage("onboarding.requestID") private var onboardingRequestID: Int = 0 - @AppStorage("gateway.onboardingComplete") private var onboardingComplete: Bool = false - @AppStorage("gateway.hasConnectedOnce") private var hasConnectedOnce: Bool = false - @AppStorage("gateway.preferredStableID") private var preferredGatewayStableID: String = "" - @AppStorage("gateway.manual.enabled") private var manualGatewayEnabled: Bool = false - @AppStorage("gateway.manual.host") private var manualGatewayHost: String = "" - @AppStorage("onboarding.quickSetupDismissed") private var quickSetupDismissed: Bool = false - @State private var presentedSheet: PresentedSheet? - @State private var voiceWakeToastText: String? - @State private var toastDismissTask: Task? - @State private var showOnboarding: Bool = false - @State private var onboardingAllowSkip: Bool = true - @State private var didEvaluateOnboarding: Bool = false - @State private var didAutoOpenSettings: Bool = false - - private enum PresentedSheet: Identifiable { - case settings - case chat - case quickSetup - - var id: Int { - switch self { - case .settings: 0 - case .chat: 1 - case .quickSetup: 2 - } - } - } - - enum StartupPresentationRoute: Equatable { - case none - case onboarding - case settings - } - - static func startupPresentationRoute( - gatewayConnected: Bool, - hasConnectedOnce: Bool, - onboardingComplete: Bool, - hasExistingGatewayConfig: Bool, - shouldPresentOnLaunch: Bool) -> StartupPresentationRoute - { - if gatewayConnected { - return .none - } - // On first run or explicit launch onboarding state, onboarding always wins. - if shouldPresentOnLaunch || !hasConnectedOnce || !onboardingComplete { - return .onboarding - } - // Settings auto-open is a recovery path for previously-connected installs only. - if !hasExistingGatewayConfig { - return .settings - } - return .none - } - - var body: some View { - ZStack { - CanvasContent( - systemColorScheme: self.systemColorScheme, - gatewayStatus: self.gatewayStatus, - voiceWakeEnabled: self.voiceWakeEnabled, - voiceWakeToastText: self.voiceWakeToastText, - cameraHUDText: self.appModel.cameraHUDText, - cameraHUDKind: self.appModel.cameraHUDKind, - openChat: { - self.presentedSheet = .chat - }, - openSettings: { - self.presentedSheet = .settings - }) - .preferredColorScheme(.dark) - - if self.appModel.cameraFlashNonce != 0 { - CameraFlashOverlay(nonce: self.appModel.cameraFlashNonce) - } - } - .gatewayTrustPromptAlert() - .sheet(item: self.$presentedSheet) { sheet in - switch sheet { - case .settings: - SettingsTab() - .environment(self.appModel) - .environment(self.appModel.voiceWake) - .environment(self.gatewayController) - case .chat: - ChatSheet( - // Chat RPCs run on the operator session (read/write scopes). - gateway: self.appModel.operatorSession, - sessionKey: self.appModel.chatSessionKey, - agentName: self.appModel.activeAgentName, - userAccent: self.appModel.seamColor) - case .quickSetup: - GatewayQuickSetupSheet() - .environment(self.appModel) - .environment(self.gatewayController) - } - } - .fullScreenCover(isPresented: self.$showOnboarding) { - OnboardingWizardView( - allowSkip: self.onboardingAllowSkip, - onClose: { - self.showOnboarding = false - }) - .environment(self.appModel) - .environment(self.appModel.voiceWake) - .environment(self.gatewayController) - } - .onAppear { self.updateIdleTimer() } - .onAppear { self.evaluateOnboardingPresentation(force: false) } - .onAppear { self.maybeAutoOpenSettings() } - .onChange(of: self.preventSleep) { _, _ in self.updateIdleTimer() } - .onChange(of: self.scenePhase) { _, _ in self.updateIdleTimer() } - .onAppear { self.maybeShowQuickSetup() } - .onChange(of: self.gatewayController.gateways.count) { _, _ in self.maybeShowQuickSetup() } - .onAppear { self.updateCanvasDebugStatus() } - .onChange(of: self.canvasDebugStatusEnabled) { _, _ in self.updateCanvasDebugStatus() } - .onChange(of: self.appModel.gatewayStatusText) { _, _ in self.updateCanvasDebugStatus() } - .onChange(of: self.appModel.gatewayServerName) { _, _ in self.updateCanvasDebugStatus() } - .onChange(of: self.appModel.gatewayServerName) { _, newValue in - if newValue != nil { - self.showOnboarding = false - } - } - .onChange(of: self.onboardingRequestID) { _, _ in - self.evaluateOnboardingPresentation(force: true) - } - .onChange(of: self.appModel.gatewayRemoteAddress) { _, _ in self.updateCanvasDebugStatus() } - .onChange(of: self.appModel.gatewayServerName) { _, newValue in - if newValue != nil { - self.onboardingComplete = true - self.hasConnectedOnce = true - OnboardingStateStore.markCompleted(mode: nil) - } - self.maybeAutoOpenSettings() - } - .onChange(of: self.appModel.openChatRequestID) { _, _ in - self.presentedSheet = .chat - } - .onChange(of: self.voiceWake.lastTriggeredCommand) { _, newValue in - guard let newValue else { return } - let trimmed = newValue.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return } - - self.toastDismissTask?.cancel() - withAnimation(.spring(response: 0.25, dampingFraction: 0.85)) { - self.voiceWakeToastText = trimmed - } - - self.toastDismissTask = Task { - try? await Task.sleep(nanoseconds: 2_300_000_000) - await MainActor.run { - withAnimation(.easeOut(duration: 0.25)) { - self.voiceWakeToastText = nil - } - } - } - } - .onDisappear { - UIApplication.shared.isIdleTimerDisabled = false - self.toastDismissTask?.cancel() - self.toastDismissTask = nil - } - } - - private var gatewayStatus: StatusPill.GatewayState { - if self.appModel.gatewayServerName != nil { return .connected } - - let text = self.appModel.gatewayStatusText.trimmingCharacters(in: .whitespacesAndNewlines) - if text.localizedCaseInsensitiveContains("connecting") || - text.localizedCaseInsensitiveContains("reconnecting") - { - return .connecting - } - - if text.localizedCaseInsensitiveContains("error") { - return .error - } - - return .disconnected - } - - private func updateIdleTimer() { - UIApplication.shared.isIdleTimerDisabled = (self.scenePhase == .active && self.preventSleep) - } - - private func updateCanvasDebugStatus() { - self.appModel.screen.setDebugStatusEnabled(self.canvasDebugStatusEnabled) - guard self.canvasDebugStatusEnabled else { return } - let title = self.appModel.gatewayStatusText.trimmingCharacters(in: .whitespacesAndNewlines) - let subtitle = self.appModel.gatewayServerName ?? self.appModel.gatewayRemoteAddress - self.appModel.screen.updateDebugStatus(title: title, subtitle: subtitle) - } - - private func evaluateOnboardingPresentation(force: Bool) { - if force { - self.onboardingAllowSkip = true - self.showOnboarding = true - return - } - - guard !self.didEvaluateOnboarding else { return } - self.didEvaluateOnboarding = true - let route = Self.startupPresentationRoute( - gatewayConnected: self.appModel.gatewayServerName != nil, - hasConnectedOnce: self.hasConnectedOnce, - onboardingComplete: self.onboardingComplete, - hasExistingGatewayConfig: self.hasExistingGatewayConfig(), - shouldPresentOnLaunch: OnboardingStateStore.shouldPresentOnLaunch(appModel: self.appModel)) - switch route { - case .none: - break - case .onboarding: - self.onboardingAllowSkip = true - self.showOnboarding = true - case .settings: - self.didAutoOpenSettings = true - self.presentedSheet = .settings - } - } - - private func hasExistingGatewayConfig() -> Bool { - if GatewaySettingsStore.loadLastGatewayConnection() != nil { return true } - let manualHost = self.manualGatewayHost.trimmingCharacters(in: .whitespacesAndNewlines) - return self.manualGatewayEnabled && !manualHost.isEmpty - } - - private func maybeAutoOpenSettings() { - guard !self.didAutoOpenSettings else { return } - guard !self.showOnboarding else { return } - let route = Self.startupPresentationRoute( - gatewayConnected: self.appModel.gatewayServerName != nil, - hasConnectedOnce: self.hasConnectedOnce, - onboardingComplete: self.onboardingComplete, - hasExistingGatewayConfig: self.hasExistingGatewayConfig(), - shouldPresentOnLaunch: false) - guard route == .settings else { return } - self.didAutoOpenSettings = true - self.presentedSheet = .settings - } - - private func maybeShowQuickSetup() { - guard !self.quickSetupDismissed else { return } - guard !self.showOnboarding else { return } - guard self.presentedSheet == nil else { return } - guard self.appModel.gatewayServerName == nil else { return } - guard !self.gatewayController.gateways.isEmpty else { return } - self.presentedSheet = .quickSetup - } -} - -private struct CanvasContent: View { - @Environment(NodeAppModel.self) private var appModel - @AppStorage("talk.enabled") private var talkEnabled: Bool = false - @AppStorage("talk.button.enabled") private var talkButtonEnabled: Bool = true - @State private var showGatewayActions: Bool = false - var systemColorScheme: ColorScheme - var gatewayStatus: StatusPill.GatewayState - var voiceWakeEnabled: Bool - var voiceWakeToastText: String? - var cameraHUDText: String? - var cameraHUDKind: NodeAppModel.CameraHUDKind? - var openChat: () -> Void - var openSettings: () -> Void - - private var brightenButtons: Bool { self.systemColorScheme == .light } - - var body: some View { - ZStack(alignment: .topTrailing) { - ScreenTab() - - VStack(spacing: 10) { - OverlayButton(systemImage: "text.bubble.fill", brighten: self.brightenButtons) { - self.openChat() - } - .accessibilityLabel("Chat") - - if self.talkButtonEnabled { - // Talk mode lives on a side bubble so it doesn't get buried in settings. - OverlayButton( - systemImage: self.appModel.talkMode.isEnabled ? "waveform.circle.fill" : "waveform.circle", - brighten: self.brightenButtons, - tint: self.appModel.seamColor, - isActive: self.appModel.talkMode.isEnabled) - { - let next = !self.appModel.talkMode.isEnabled - self.talkEnabled = next - self.appModel.setTalkEnabled(next) - } - .accessibilityLabel("Talk Mode") - } - - OverlayButton(systemImage: "gearshape.fill", brighten: self.brightenButtons) { - self.openSettings() - } - .accessibilityLabel("Settings") - } - .padding(.top, 10) - .padding(.trailing, 10) - } - .overlay(alignment: .center) { - if self.appModel.talkMode.isEnabled { - TalkOrbOverlay() - .transition(.opacity) - } - } - .overlay(alignment: .topLeading) { - StatusPill( - gateway: self.gatewayStatus, - voiceWakeEnabled: self.voiceWakeEnabled, - activity: self.statusActivity, - brighten: self.brightenButtons, - onTap: { - if self.gatewayStatus == .connected { - self.showGatewayActions = true - } else { - self.openSettings() - } - }) - .padding(.leading, 10) - .safeAreaPadding(.top, 10) - } - .overlay(alignment: .topLeading) { - if let voiceWakeToastText, !voiceWakeToastText.isEmpty { - VoiceWakeToast( - command: voiceWakeToastText, - brighten: self.brightenButtons) - .padding(.leading, 10) - .safeAreaPadding(.top, 58) - .transition(.move(edge: .top).combined(with: .opacity)) - } - } - .confirmationDialog( - "Gateway", - isPresented: self.$showGatewayActions, - titleVisibility: .visible) - { - Button("Disconnect", role: .destructive) { - self.appModel.disconnectGateway() - } - Button("Open Settings") { - self.openSettings() - } - Button("Cancel", role: .cancel) {} - } message: { - Text("Disconnect from the gateway?") - } - } - - private var statusActivity: StatusPill.Activity? { - // Status pill owns transient activity state so it doesn't overlap the connection indicator. - if self.appModel.isBackgrounded { - return StatusPill.Activity( - title: "Foreground required", - systemImage: "exclamationmark.triangle.fill", - tint: .orange) - } - - let gatewayStatus = self.appModel.gatewayStatusText.trimmingCharacters(in: .whitespacesAndNewlines) - let gatewayLower = gatewayStatus.lowercased() - if gatewayLower.contains("repair") { - return StatusPill.Activity(title: "Repairing…", systemImage: "wrench.and.screwdriver", tint: .orange) - } - if gatewayLower.contains("approval") || gatewayLower.contains("pairing") { - return StatusPill.Activity(title: "Approval pending", systemImage: "person.crop.circle.badge.clock") - } - // Avoid duplicating the primary gateway status ("Connecting…") in the activity slot. - - if self.appModel.screenRecordActive { - return StatusPill.Activity(title: "Recording screen…", systemImage: "record.circle.fill", tint: .red) - } - - if let cameraHUDText, !cameraHUDText.isEmpty, let cameraHUDKind { - let systemImage: String - let tint: Color? - switch cameraHUDKind { - case .photo: - systemImage = "camera.fill" - tint = nil - case .recording: - systemImage = "video.fill" - tint = .red - case .success: - systemImage = "checkmark.circle.fill" - tint = .green - case .error: - systemImage = "exclamationmark.triangle.fill" - tint = .red - } - return StatusPill.Activity(title: cameraHUDText, systemImage: systemImage, tint: tint) - } - - if self.voiceWakeEnabled { - let voiceStatus = self.appModel.voiceWake.statusText - if voiceStatus.localizedCaseInsensitiveContains("microphone permission") { - return StatusPill.Activity(title: "Mic permission", systemImage: "mic.slash", tint: .orange) - } - if voiceStatus == "Paused" { - // Talk mode intentionally pauses voice wake to release the mic. Don't spam the HUD for that case. - if self.appModel.talkMode.isEnabled { - return nil - } - let suffix = self.appModel.isBackgrounded ? " (background)" : "" - return StatusPill.Activity(title: "Voice Wake paused\(suffix)", systemImage: "pause.circle.fill") - } - } - - return nil - } -} - -private struct OverlayButton: View { - let systemImage: String - let brighten: Bool - var tint: Color? - var isActive: Bool = false - let action: () -> Void - - var body: some View { - Button(action: self.action) { - Image(systemName: self.systemImage) - .font(.system(size: 16, weight: .semibold)) - .foregroundStyle(self.isActive ? (self.tint ?? .primary) : .primary) - .padding(10) - .background { - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill(.ultraThinMaterial) - .overlay { - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill( - LinearGradient( - colors: [ - .white.opacity(self.brighten ? 0.26 : 0.18), - .white.opacity(self.brighten ? 0.08 : 0.04), - .clear, - ], - startPoint: .topLeading, - endPoint: .bottomTrailing)) - .blendMode(.overlay) - } - .overlay { - if let tint { - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill( - LinearGradient( - colors: [ - tint.opacity(self.isActive ? 0.22 : 0.14), - tint.opacity(self.isActive ? 0.10 : 0.06), - .clear, - ], - startPoint: .topLeading, - endPoint: .bottomTrailing)) - .blendMode(.overlay) - } - } - .overlay { - RoundedRectangle(cornerRadius: 12, style: .continuous) - .strokeBorder( - (self.tint ?? .white).opacity(self.isActive ? 0.34 : (self.brighten ? 0.24 : 0.18)), - lineWidth: self.isActive ? 0.7 : 0.5) - } - .shadow(color: .black.opacity(0.35), radius: 12, y: 6) - } - } - .buttonStyle(.plain) - } -} - -private struct CameraFlashOverlay: View { - var nonce: Int - - @State private var opacity: CGFloat = 0 - @State private var task: Task? - - var body: some View { - Color.white - .opacity(self.opacity) - .ignoresSafeArea() - .allowsHitTesting(false) - .onChange(of: self.nonce) { _, _ in - self.task?.cancel() - self.task = Task { @MainActor in - withAnimation(.easeOut(duration: 0.08)) { - self.opacity = 0.85 - } - try? await Task.sleep(nanoseconds: 110_000_000) - withAnimation(.easeOut(duration: 0.32)) { - self.opacity = 0 - } - } - } - } -} diff --git a/apps/ios/Sources/RootTabs.swift b/apps/ios/Sources/RootTabs.swift deleted file mode 100644 index 4733a4a30fc..00000000000 --- a/apps/ios/Sources/RootTabs.swift +++ /dev/null @@ -1,114 +0,0 @@ -import SwiftUI - -struct RootTabs: View { - @Environment(NodeAppModel.self) private var appModel - @Environment(VoiceWakeManager.self) private var voiceWake - @Environment(\.accessibilityReduceMotion) private var reduceMotion - @AppStorage(VoiceWakePreferences.enabledKey) private var voiceWakeEnabled: Bool = false - @State private var selectedTab: Int = 0 - @State private var voiceWakeToastText: String? - @State private var toastDismissTask: Task? - @State private var showGatewayActions: Bool = false - - var body: some View { - TabView(selection: self.$selectedTab) { - ScreenTab() - .tabItem { Label("Screen", systemImage: "rectangle.and.hand.point.up.left") } - .tag(0) - - VoiceTab() - .tabItem { Label("Voice", systemImage: "mic") } - .tag(1) - - SettingsTab() - .tabItem { Label("Settings", systemImage: "gearshape") } - .tag(2) - } - .overlay(alignment: .topLeading) { - StatusPill( - gateway: self.gatewayStatus, - voiceWakeEnabled: self.voiceWakeEnabled, - activity: self.statusActivity, - onTap: { - if self.gatewayStatus == .connected { - self.showGatewayActions = true - } else { - self.selectedTab = 2 - } - }) - .padding(.leading, 10) - .safeAreaPadding(.top, 10) - } - .overlay(alignment: .topLeading) { - if let voiceWakeToastText, !voiceWakeToastText.isEmpty { - VoiceWakeToast(command: voiceWakeToastText) - .padding(.leading, 10) - .safeAreaPadding(.top, 58) - .transition(.move(edge: .top).combined(with: .opacity)) - } - } - .onChange(of: self.voiceWake.lastTriggeredCommand) { _, newValue in - guard let newValue else { return } - let trimmed = newValue.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return } - - self.toastDismissTask?.cancel() - withAnimation(self.reduceMotion ? .none : .spring(response: 0.25, dampingFraction: 0.85)) { - self.voiceWakeToastText = trimmed - } - - self.toastDismissTask = Task { - try? await Task.sleep(nanoseconds: 2_300_000_000) - await MainActor.run { - withAnimation(self.reduceMotion ? .none : .easeOut(duration: 0.25)) { - self.voiceWakeToastText = nil - } - } - } - } - .onDisappear { - self.toastDismissTask?.cancel() - self.toastDismissTask = nil - } - .confirmationDialog( - "Gateway", - isPresented: self.$showGatewayActions, - titleVisibility: .visible) - { - Button("Disconnect", role: .destructive) { - self.appModel.disconnectGateway() - } - Button("Open Settings") { - self.selectedTab = 2 - } - Button("Cancel", role: .cancel) {} - } message: { - Text("Disconnect from the gateway?") - } - } - - private var gatewayStatus: StatusPill.GatewayState { - if self.appModel.gatewayServerName != nil { return .connected } - - let text = self.appModel.gatewayStatusText.trimmingCharacters(in: .whitespacesAndNewlines) - if text.localizedCaseInsensitiveContains("connecting") || - text.localizedCaseInsensitiveContains("reconnecting") - { - return .connecting - } - - if text.localizedCaseInsensitiveContains("error") { - return .error - } - - return .disconnected - } - - private var statusActivity: StatusPill.Activity? { - StatusActivityBuilder.build( - appModel: self.appModel, - voiceWakeEnabled: self.voiceWakeEnabled, - cameraHUDText: self.appModel.cameraHUDText, - cameraHUDKind: self.appModel.cameraHUDKind) - } -} diff --git a/apps/ios/Sources/RootView.swift b/apps/ios/Sources/RootView.swift deleted file mode 100644 index b0281865334..00000000000 --- a/apps/ios/Sources/RootView.swift +++ /dev/null @@ -1,7 +0,0 @@ -import SwiftUI - -struct RootView: View { - var body: some View { - RootCanvas() - } -} diff --git a/apps/ios/Sources/Screen/ScreenController.swift b/apps/ios/Sources/Screen/ScreenController.swift deleted file mode 100644 index 0045232362b..00000000000 --- a/apps/ios/Sources/Screen/ScreenController.swift +++ /dev/null @@ -1,373 +0,0 @@ -import OpenClawKit -import Observation -import UIKit -import WebKit - -@MainActor -@Observable -final class ScreenController { - private weak var activeWebView: WKWebView? - - var urlString: String = "" - var errorText: String? - - /// Callback invoked when an openclaw:// deep link is tapped in the canvas - var onDeepLink: ((URL) -> Void)? - - /// Callback invoked when the user clicks an A2UI action (e.g. button) inside the canvas web UI. - var onA2UIAction: (([String: Any]) -> Void)? - - private var debugStatusEnabled: Bool = false - private var debugStatusTitle: String? - private var debugStatusSubtitle: String? - - init() { - self.reload() - } - - func navigate(to urlString: String) { - let trimmed = urlString.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty { - self.urlString = "" - self.reload() - return - } - if let url = URL(string: trimmed), - !url.isFileURL, - let host = url.host, - Self.isLoopbackHost(host) - { - // Never try to load loopback URLs from a remote gateway. - self.showDefaultCanvas() - return - } - self.urlString = (trimmed == "/" ? "" : trimmed) - self.reload() - } - - func reload() { - self.applyScrollBehavior() - guard let webView = self.activeWebView else { return } - - let trimmed = self.urlString.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty { - guard let url = Self.canvasScaffoldURL else { return } - self.errorText = nil - webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent()) - return - } - - guard let url = URL(string: trimmed) else { - self.errorText = "Invalid URL: \(trimmed)" - return - } - self.errorText = nil - if url.isFileURL { - webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent()) - } else { - webView.load(URLRequest(url: url)) - } - } - - func showDefaultCanvas() { - self.urlString = "" - self.reload() - } - - func setDebugStatusEnabled(_ enabled: Bool) { - self.debugStatusEnabled = enabled - self.applyDebugStatusIfNeeded() - } - - func updateDebugStatus(title: String?, subtitle: String?) { - self.debugStatusTitle = title - self.debugStatusSubtitle = subtitle - self.applyDebugStatusIfNeeded() - } - - func applyDebugStatusIfNeeded() { - guard let webView = self.activeWebView else { return } - let enabled = self.debugStatusEnabled - let title = self.debugStatusTitle - let subtitle = self.debugStatusSubtitle - let js = """ - (() => { - try { - const api = globalThis.__openclaw; - if (!api) return; - if (typeof api.setDebugStatusEnabled === 'function') { - api.setDebugStatusEnabled(\(enabled ? "true" : "false")); - } - if (!\(enabled ? "true" : "false")) return; - if (typeof api.setStatus === 'function') { - api.setStatus(\(Self.jsValue(title)), \(Self.jsValue(subtitle))); - } - } catch (_) {} - })() - """ - webView.evaluateJavaScript(js) { _, _ in } - } - - func waitForA2UIReady(timeoutMs: Int) async -> Bool { - let clock = ContinuousClock() - let deadline = clock.now.advanced(by: .milliseconds(timeoutMs)) - while clock.now < deadline { - do { - let res = try await self.eval(javaScript: """ - (() => { - try { - const host = globalThis.openclawA2UI; - return !!host && typeof host.applyMessages === 'function'; - } catch (_) { return false; } - })() - """) - let trimmed = res.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - if trimmed == "true" || trimmed == "1" { return true } - } catch { - // ignore; page likely still loading - } - try? await Task.sleep(nanoseconds: 120_000_000) - } - return false - } - - func eval(javaScript: String) async throws -> String { - guard let webView = self.activeWebView else { - throw NSError(domain: "Screen", code: 3, userInfo: [ - NSLocalizedDescriptionKey: "web view unavailable", - ]) - } - return try await withCheckedThrowingContinuation { cont in - webView.evaluateJavaScript(javaScript) { result, error in - if let error { - cont.resume(throwing: error) - return - } - if let result { - cont.resume(returning: String(describing: result)) - } else { - cont.resume(returning: "") - } - } - } - } - - func snapshotPNGBase64(maxWidth: CGFloat? = nil) async throws -> String { - let config = WKSnapshotConfiguration() - if let maxWidth { - config.snapshotWidth = NSNumber(value: Double(maxWidth)) - } - guard let webView = self.activeWebView else { - throw NSError(domain: "Screen", code: 3, userInfo: [ - NSLocalizedDescriptionKey: "web view unavailable", - ]) - } - let image: UIImage = try await withCheckedThrowingContinuation { cont in - webView.takeSnapshot(with: config) { image, error in - if let error { - cont.resume(throwing: error) - return - } - guard let image else { - cont.resume(throwing: NSError(domain: "Screen", code: 2, userInfo: [ - NSLocalizedDescriptionKey: "snapshot failed", - ])) - return - } - cont.resume(returning: image) - } - } - guard let data = image.pngData() else { - throw NSError(domain: "Screen", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "snapshot encode failed", - ]) - } - return data.base64EncodedString() - } - - func snapshotBase64( - maxWidth: CGFloat? = nil, - format: OpenClawCanvasSnapshotFormat, - quality: Double? = nil) async throws -> String - { - let config = WKSnapshotConfiguration() - if let maxWidth { - config.snapshotWidth = NSNumber(value: Double(maxWidth)) - } - guard let webView = self.activeWebView else { - throw NSError(domain: "Screen", code: 3, userInfo: [ - NSLocalizedDescriptionKey: "web view unavailable", - ]) - } - let image: UIImage = try await withCheckedThrowingContinuation { cont in - webView.takeSnapshot(with: config) { image, error in - if let error { - cont.resume(throwing: error) - return - } - guard let image else { - cont.resume(throwing: NSError(domain: "Screen", code: 2, userInfo: [ - NSLocalizedDescriptionKey: "snapshot failed", - ])) - return - } - cont.resume(returning: image) - } - } - - let data: Data? - switch format { - case .png: - data = image.pngData() - case .jpeg: - let q = (quality ?? 0.82).clamped(to: 0.1...1.0) - data = image.jpegData(compressionQuality: q) - } - guard let data else { - throw NSError(domain: "Screen", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "snapshot encode failed", - ]) - } - return data.base64EncodedString() - } - - func attachWebView(_ webView: WKWebView) { - self.activeWebView = webView - self.reload() - self.applyDebugStatusIfNeeded() - } - - func detachWebView(_ webView: WKWebView) { - guard self.activeWebView === webView else { return } - self.activeWebView = nil - } - - private static func bundledResourceURL( - name: String, - ext: String, - subdirectory: String) - -> URL? - { - let bundle = OpenClawKitResources.bundle - return bundle.url(forResource: name, withExtension: ext, subdirectory: subdirectory) - ?? bundle.url(forResource: name, withExtension: ext) - } - - private static let canvasScaffoldURL: URL? = ScreenController.bundledResourceURL( - name: "scaffold", - ext: "html", - subdirectory: "CanvasScaffold") - - private static func isLoopbackHost(_ host: String) -> Bool { - let normalized = host.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - if normalized.isEmpty { return true } - if normalized == "localhost" || normalized == "::1" || normalized == "0.0.0.0" { - return true - } - if normalized == "127.0.0.1" || normalized.hasPrefix("127.") { - return true - } - return false - } - func isTrustedCanvasUIURL(_ url: URL) -> Bool { - guard url.isFileURL else { return false } - let std = url.standardizedFileURL - if let expected = Self.canvasScaffoldURL, - std == expected.standardizedFileURL - { - return true - } - return false - } - - private func applyScrollBehavior() { - guard let webView = self.activeWebView else { return } - let trimmed = self.urlString.trimmingCharacters(in: .whitespacesAndNewlines) - let allowScroll = !trimmed.isEmpty - let scrollView = webView.scrollView - // Default canvas needs raw touch events; external pages should scroll. - scrollView.isScrollEnabled = allowScroll - scrollView.bounces = allowScroll - } - - private static func jsValue(_ value: String?) -> String { - guard let value else { return "null" } - if let data = try? JSONSerialization.data(withJSONObject: [value]), - let encoded = String(data: data, encoding: .utf8), - encoded.count >= 2 - { - return String(encoded.dropFirst().dropLast()) - } - return "null" - } - - func isLocalNetworkCanvasURL(_ url: URL) -> Bool { - guard let scheme = url.scheme?.lowercased(), scheme == "http" || scheme == "https" else { - return false - } - guard let host = url.host?.trimmingCharacters(in: .whitespacesAndNewlines), !host.isEmpty else { - return false - } - if host == "localhost" { return true } - if host.hasSuffix(".local") { return true } - if host.hasSuffix(".ts.net") { return true } - if host.hasSuffix(".tailscale.net") { return true } - // Allow MagicDNS / LAN hostnames like "peters-mac-studio-1". - if !host.contains("."), !host.contains(":") { return true } - if let ipv4 = Self.parseIPv4(host) { - return Self.isLocalNetworkIPv4(ipv4) - } - return false - } - - private static func parseIPv4(_ host: String) -> (UInt8, UInt8, UInt8, UInt8)? { - let parts = host.split(separator: ".", omittingEmptySubsequences: false) - guard parts.count == 4 else { return nil } - let bytes: [UInt8] = parts.compactMap { UInt8($0) } - guard bytes.count == 4 else { return nil } - return (bytes[0], bytes[1], bytes[2], bytes[3]) - } - - private static func isLocalNetworkIPv4(_ ip: (UInt8, UInt8, UInt8, UInt8)) -> Bool { - let (a, b, _, _) = ip - // 10.0.0.0/8 - if a == 10 { return true } - // 172.16.0.0/12 - if a == 172, (16...31).contains(Int(b)) { return true } - // 192.168.0.0/16 - if a == 192, b == 168 { return true } - // 127.0.0.0/8 - if a == 127 { return true } - // 169.254.0.0/16 (link-local) - if a == 169, b == 254 { return true } - // Tailscale: 100.64.0.0/10 - if a == 100, (64...127).contains(Int(b)) { return true } - return false - } - - nonisolated static func parseA2UIActionBody(_ body: Any) -> [String: Any]? { - if let dict = body as? [String: Any] { return dict.isEmpty ? nil : dict } - if let str = body as? String, - let data = str.data(using: .utf8), - let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] - { - return json.isEmpty ? nil : json - } - if let dict = body as? [AnyHashable: Any] { - let mapped = dict.reduce(into: [String: Any]()) { acc, pair in - guard let key = pair.key as? String else { return } - acc[key] = pair.value - } - return mapped.isEmpty ? nil : mapped - } - return nil - } -} - -extension Double { - fileprivate func clamped(to range: ClosedRange) -> Double { - if self < range.lowerBound { return range.lowerBound } - if self > range.upperBound { return range.upperBound } - return self - } -} diff --git a/apps/ios/Sources/Screen/ScreenRecordService.swift b/apps/ios/Sources/Screen/ScreenRecordService.swift deleted file mode 100644 index 11052f23543..00000000000 --- a/apps/ios/Sources/Screen/ScreenRecordService.swift +++ /dev/null @@ -1,360 +0,0 @@ -import AVFoundation -import ReplayKit - -final class ScreenRecordService: @unchecked Sendable { - private struct UncheckedSendableBox: @unchecked Sendable { - let value: T - } - - private final class CaptureState: @unchecked Sendable { - private let lock = NSLock() - var writer: AVAssetWriter? - var videoInput: AVAssetWriterInput? - var audioInput: AVAssetWriterInput? - var started = false - var sawVideo = false - var lastVideoTime: CMTime? - var handlerError: Error? - - func withLock(_ body: (CaptureState) -> T) -> T { - self.lock.lock() - defer { lock.unlock() } - return body(self) - } - } - - enum ScreenRecordError: LocalizedError { - case invalidScreenIndex(Int) - case captureFailed(String) - case writeFailed(String) - - var errorDescription: String? { - switch self { - case let .invalidScreenIndex(idx): - "Invalid screen index \(idx)" - case let .captureFailed(msg): - msg - case let .writeFailed(msg): - msg - } - } - } - - func record( - screenIndex: Int?, - durationMs: Int?, - fps: Double?, - includeAudio: Bool?, - outPath: String?) async throws -> String - { - let config = try self.makeRecordConfig( - screenIndex: screenIndex, - durationMs: durationMs, - fps: fps, - includeAudio: includeAudio, - outPath: outPath) - - let state = CaptureState() - let recordQueue = DispatchQueue(label: "bot.molt.screenrecord") - - try await self.startCapture(state: state, config: config, recordQueue: recordQueue) - try await Task.sleep(nanoseconds: UInt64(config.durationMs) * 1_000_000) - try await self.stopCapture() - try self.finalizeCapture(state: state) - try await self.finishWriting(state: state) - - return config.outURL.path - } - - private struct RecordConfig { - let durationMs: Int - let fpsValue: Double - let includeAudio: Bool - let outURL: URL - } - - private func makeRecordConfig( - screenIndex: Int?, - durationMs: Int?, - fps: Double?, - includeAudio: Bool?, - outPath: String?) throws -> RecordConfig - { - if let idx = screenIndex, idx != 0 { - throw ScreenRecordError.invalidScreenIndex(idx) - } - - let durationMs = Self.clampDurationMs(durationMs) - let fps = Self.clampFps(fps) - let fpsInt = Int32(fps.rounded()) - let fpsValue = Double(fpsInt) - let includeAudio = includeAudio ?? true - - let outURL = self.makeOutputURL(outPath: outPath) - try? FileManager().removeItem(at: outURL) - - return RecordConfig( - durationMs: durationMs, - fpsValue: fpsValue, - includeAudio: includeAudio, - outURL: outURL) - } - - private func makeOutputURL(outPath: String?) -> URL { - if let outPath, !outPath.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - return URL(fileURLWithPath: outPath) - } - return FileManager().temporaryDirectory - .appendingPathComponent("openclaw-screen-record-\(UUID().uuidString).mp4") - } - - private func startCapture( - state: CaptureState, - config: RecordConfig, - recordQueue: DispatchQueue) async throws - { - try await withCheckedThrowingContinuation { (cont: CheckedContinuation) in - let handler = self.makeCaptureHandler( - state: state, - config: config, - recordQueue: recordQueue) - let completion: @Sendable (Error?) -> Void = { error in - if let error { cont.resume(throwing: error) } else { cont.resume() } - } - - Task { @MainActor in - startReplayKitCapture( - includeAudio: config.includeAudio, - handler: handler, - completion: completion) - } - } - } - - private func makeCaptureHandler( - state: CaptureState, - config: RecordConfig, - recordQueue: DispatchQueue) -> @Sendable (CMSampleBuffer, RPSampleBufferType, Error?) -> Void - { - { sample, type, error in - let sampleBox = UncheckedSendableBox(value: sample) - // ReplayKit can call the capture handler on a background queue. - // Serialize writes to avoid queue asserts. - recordQueue.async { - let sample = sampleBox.value - if let error { - state.withLock { state in - if state.handlerError == nil { state.handlerError = error } - } - return - } - guard CMSampleBufferDataIsReady(sample) else { return } - - switch type { - case .video: - self.handleVideoSample(sample, state: state, config: config) - case .audioApp, .audioMic: - self.handleAudioSample(sample, state: state, includeAudio: config.includeAudio) - @unknown default: - break - } - } - } - } - - private func handleVideoSample( - _ sample: CMSampleBuffer, - state: CaptureState, - config: RecordConfig) - { - let pts = CMSampleBufferGetPresentationTimeStamp(sample) - let shouldSkip = state.withLock { state in - if let lastVideoTime = state.lastVideoTime { - let delta = CMTimeSubtract(pts, lastVideoTime) - return delta.seconds < (1.0 / config.fpsValue) - } - return false - } - if shouldSkip { return } - - if state.withLock({ $0.writer == nil }) { - self.prepareWriter(sample: sample, state: state, config: config, pts: pts) - } - - let vInput = state.withLock { $0.videoInput } - let isStarted = state.withLock { $0.started } - guard let vInput, isStarted else { return } - if vInput.isReadyForMoreMediaData { - if vInput.append(sample) { - state.withLock { state in - state.sawVideo = true - state.lastVideoTime = pts - } - } else { - let err = state.withLock { $0.writer?.error } - if let err { - state.withLock { state in - if state.handlerError == nil { - state.handlerError = ScreenRecordError.writeFailed(err.localizedDescription) - } - } - } - } - } - } - - private func prepareWriter( - sample: CMSampleBuffer, - state: CaptureState, - config: RecordConfig, - pts: CMTime) - { - guard let imageBuffer = CMSampleBufferGetImageBuffer(sample) else { - state.withLock { state in - if state.handlerError == nil { - state.handlerError = ScreenRecordError.captureFailed("Missing image buffer") - } - } - return - } - let width = CVPixelBufferGetWidth(imageBuffer) - let height = CVPixelBufferGetHeight(imageBuffer) - do { - let writer = try AVAssetWriter(outputURL: config.outURL, fileType: .mp4) - let settings: [String: Any] = [ - AVVideoCodecKey: AVVideoCodecType.h264, - AVVideoWidthKey: width, - AVVideoHeightKey: height, - ] - let vInput = AVAssetWriterInput(mediaType: .video, outputSettings: settings) - vInput.expectsMediaDataInRealTime = true - guard writer.canAdd(vInput) else { - throw ScreenRecordError.writeFailed("Cannot add video input") - } - writer.add(vInput) - - if config.includeAudio { - let aInput = AVAssetWriterInput(mediaType: .audio, outputSettings: nil) - aInput.expectsMediaDataInRealTime = true - if writer.canAdd(aInput) { - writer.add(aInput) - state.withLock { state in - state.audioInput = aInput - } - } - } - - guard writer.startWriting() else { - throw ScreenRecordError.writeFailed( - writer.error?.localizedDescription ?? "Failed to start writer") - } - writer.startSession(atSourceTime: pts) - state.withLock { state in - state.writer = writer - state.videoInput = vInput - state.started = true - } - } catch { - state.withLock { state in - if state.handlerError == nil { state.handlerError = error } - } - } - } - - private func handleAudioSample( - _ sample: CMSampleBuffer, - state: CaptureState, - includeAudio: Bool) - { - let aInput = state.withLock { $0.audioInput } - let isStarted = state.withLock { $0.started } - guard includeAudio, let aInput, isStarted else { return } - if aInput.isReadyForMoreMediaData { - _ = aInput.append(sample) - } - } - - private func stopCapture() async throws { - let stopError = await withCheckedContinuation { cont in - Task { @MainActor in - stopReplayKitCapture { error in cont.resume(returning: error) } - } - } - if let stopError { throw stopError } - } - - private func finalizeCapture(state: CaptureState) throws { - if let handlerErrorSnapshot = state.withLock({ $0.handlerError }) { - throw handlerErrorSnapshot - } - let writerSnapshot = state.withLock { $0.writer } - let videoInputSnapshot = state.withLock { $0.videoInput } - let audioInputSnapshot = state.withLock { $0.audioInput } - let sawVideoSnapshot = state.withLock { $0.sawVideo } - guard let writerSnapshot, let videoInputSnapshot, sawVideoSnapshot else { - throw ScreenRecordError.captureFailed("No frames captured") - } - - videoInputSnapshot.markAsFinished() - audioInputSnapshot?.markAsFinished() - _ = writerSnapshot - } - - private func finishWriting(state: CaptureState) async throws { - guard let writerSnapshot = state.withLock({ $0.writer }) else { - throw ScreenRecordError.captureFailed("Missing writer") - } - let writerBox = UncheckedSendableBox(value: writerSnapshot) - try await withCheckedThrowingContinuation { (cont: CheckedContinuation) in - writerBox.value.finishWriting { - let writer = writerBox.value - if let err = writer.error { - cont.resume(throwing: ScreenRecordError.writeFailed(err.localizedDescription)) - } else if writer.status != .completed { - cont.resume(throwing: ScreenRecordError.writeFailed("Failed to finalize video")) - } else { - cont.resume() - } - } - } - } - - private nonisolated static func clampDurationMs(_ ms: Int?) -> Int { - let v = ms ?? 10000 - return min(60000, max(250, v)) - } - - private nonisolated static func clampFps(_ fps: Double?) -> Double { - let v = fps ?? 10 - if !v.isFinite { return 10 } - return min(30, max(1, v)) - } -} - -@MainActor -private func startReplayKitCapture( - includeAudio: Bool, - handler: @escaping @Sendable (CMSampleBuffer, RPSampleBufferType, Error?) -> Void, - completion: @escaping @Sendable (Error?) -> Void) -{ - let recorder = RPScreenRecorder.shared() - recorder.isMicrophoneEnabled = includeAudio - recorder.startCapture(handler: handler, completionHandler: completion) -} - -@MainActor -private func stopReplayKitCapture(_ completion: @escaping @Sendable (Error?) -> Void) { - RPScreenRecorder.shared().stopCapture { error in completion(error) } -} - -#if DEBUG -extension ScreenRecordService { - nonisolated static func _test_clampDurationMs(_ ms: Int?) -> Int { - self.clampDurationMs(ms) - } - - nonisolated static func _test_clampFps(_ fps: Double?) -> Double { - self.clampFps(fps) - } -} -#endif diff --git a/apps/ios/Sources/Screen/ScreenTab.swift b/apps/ios/Sources/Screen/ScreenTab.swift deleted file mode 100644 index 16b5f857496..00000000000 --- a/apps/ios/Sources/Screen/ScreenTab.swift +++ /dev/null @@ -1,27 +0,0 @@ -import OpenClawKit -import SwiftUI - -struct ScreenTab: View { - @Environment(NodeAppModel.self) private var appModel - - var body: some View { - ZStack(alignment: .top) { - ScreenWebView(controller: self.appModel.screen) - .ignoresSafeArea() - .overlay(alignment: .top) { - if let errorText = self.appModel.screen.errorText, - self.appModel.gatewayServerName == nil - { - Text(errorText) - .font(.footnote) - .padding(10) - .background(.thinMaterial) - .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) - .padding() - } - } - } - } - - // Navigation is agent-driven; no local URL bar here. -} diff --git a/apps/ios/Sources/Screen/ScreenWebView.swift b/apps/ios/Sources/Screen/ScreenWebView.swift deleted file mode 100644 index a30d78cbd00..00000000000 --- a/apps/ios/Sources/Screen/ScreenWebView.swift +++ /dev/null @@ -1,193 +0,0 @@ -import OpenClawKit -import SwiftUI -import WebKit - -struct ScreenWebView: UIViewRepresentable { - var controller: ScreenController - - func makeCoordinator() -> ScreenWebViewCoordinator { - ScreenWebViewCoordinator(controller: self.controller) - } - - func makeUIView(context: Context) -> UIView { - context.coordinator.makeContainerView() - } - - func updateUIView(_: UIView, context: Context) { - context.coordinator.updateController(self.controller) - } - - static func dismantleUIView(_: UIView, coordinator: ScreenWebViewCoordinator) { - coordinator.teardown() - } -} - -@MainActor -final class ScreenWebViewCoordinator: NSObject { - private weak var controller: ScreenController? - private let navigationDelegate = ScreenNavigationDelegate() - private let a2uiActionHandler = CanvasA2UIActionMessageHandler() - private let userContentController = WKUserContentController() - - private(set) var managedWebView: WKWebView? - private weak var containerView: UIView? - - init(controller: ScreenController) { - self.controller = controller - super.init() - self.navigationDelegate.controller = controller - self.a2uiActionHandler.controller = controller - } - - func makeContainerView() -> UIView { - if let containerView { - return containerView - } - - let container = UIView(frame: .zero) - container.backgroundColor = .black - - let webView = Self.makeWebView(userContentController: self.userContentController) - webView.navigationDelegate = self.navigationDelegate - self.installA2UIHandlers() - - webView.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(webView) - NSLayoutConstraint.activate([ - webView.leadingAnchor.constraint(equalTo: container.leadingAnchor), - webView.trailingAnchor.constraint(equalTo: container.trailingAnchor), - webView.topAnchor.constraint(equalTo: container.topAnchor), - webView.bottomAnchor.constraint(equalTo: container.bottomAnchor), - ]) - - self.managedWebView = webView - self.containerView = container - self.controller?.attachWebView(webView) - return container - } - - func updateController(_ controller: ScreenController) { - let previousController = self.controller - let controllerChanged = self.controller !== controller - self.controller = controller - self.navigationDelegate.controller = controller - self.a2uiActionHandler.controller = controller - if controllerChanged, let managedWebView { - previousController?.detachWebView(managedWebView) - controller.attachWebView(managedWebView) - } - } - - func teardown() { - if let managedWebView { - self.controller?.detachWebView(managedWebView) - managedWebView.navigationDelegate = nil - } - self.removeA2UIHandlers() - self.navigationDelegate.controller = nil - self.a2uiActionHandler.controller = nil - self.managedWebView = nil - self.containerView = nil - } - - private static func makeWebView(userContentController: WKUserContentController) -> WKWebView { - let config = WKWebViewConfiguration() - config.websiteDataStore = .nonPersistent() - config.userContentController = userContentController - - let webView = WKWebView(frame: .zero, configuration: config) - // Canvas scaffold is a fully self-contained HTML page; avoid relying on transparency underlays. - webView.isOpaque = true - webView.backgroundColor = .black - - let scrollView = webView.scrollView - scrollView.backgroundColor = .black - scrollView.contentInsetAdjustmentBehavior = .never - scrollView.contentInset = .zero - scrollView.scrollIndicatorInsets = .zero - scrollView.automaticallyAdjustsScrollIndicatorInsets = false - - return webView - } - - private func installA2UIHandlers() { - for name in CanvasA2UIActionMessageHandler.handlerNames { - self.userContentController.add(self.a2uiActionHandler, name: name) - } - } - - private func removeA2UIHandlers() { - for name in CanvasA2UIActionMessageHandler.handlerNames { - self.userContentController.removeScriptMessageHandler(forName: name) - } - } -} - -// MARK: - Navigation Delegate - -/// Handles navigation policy to intercept openclaw:// deep links from canvas -@MainActor -private final class ScreenNavigationDelegate: NSObject, WKNavigationDelegate { - weak var controller: ScreenController? - - func webView( - _: WKWebView, - decidePolicyFor navigationAction: WKNavigationAction, - decisionHandler: @escaping @MainActor @Sendable (WKNavigationActionPolicy) -> Void) - { - guard let url = navigationAction.request.url else { - decisionHandler(.allow) - return - } - - // Intercept openclaw:// deep links. - if url.scheme?.lowercased() == "openclaw" { - decisionHandler(.cancel) - self.controller?.onDeepLink?(url) - return - } - - decisionHandler(.allow) - } - - func webView( - _: WKWebView, - didFailProvisionalNavigation _: WKNavigation?, - withError error: any Error) - { - self.controller?.errorText = error.localizedDescription - } - - func webView(_: WKWebView, didFinish _: WKNavigation?) { - self.controller?.errorText = nil - self.controller?.applyDebugStatusIfNeeded() - } - - func webView(_: WKWebView, didFail _: WKNavigation?, withError error: any Error) { - self.controller?.errorText = error.localizedDescription - } -} - -private final class CanvasA2UIActionMessageHandler: NSObject, WKScriptMessageHandler { - static let messageName = "openclawCanvasA2UIAction" - static let handlerNames = [messageName] - - weak var controller: ScreenController? - - func userContentController(_: WKUserContentController, didReceive message: WKScriptMessage) { - guard Self.handlerNames.contains(message.name) else { return } - guard let controller else { return } - - guard let url = message.webView?.url else { return } - if url.isFileURL { - guard controller.isTrustedCanvasUIURL(url) else { return } - } else { - // For security, only accept actions from local-network pages (e.g. the canvas host). - guard controller.isLocalNetworkCanvasURL(url) else { return } - } - - guard let body = ScreenController.parseA2UIActionBody(message.body) else { return } - - controller.onA2UIAction?(body) - } -} diff --git a/apps/ios/Sources/Services/NodeServiceProtocols.swift b/apps/ios/Sources/Services/NodeServiceProtocols.swift deleted file mode 100644 index 27ee7cc2776..00000000000 --- a/apps/ios/Sources/Services/NodeServiceProtocols.swift +++ /dev/null @@ -1,103 +0,0 @@ -import CoreLocation -import Foundation -import OpenClawKit -import UIKit - -protocol CameraServicing: Sendable { - func listDevices() async -> [CameraController.CameraDeviceInfo] - func snap(params: OpenClawCameraSnapParams) async throws -> (format: String, base64: String, width: Int, height: Int) - func clip(params: OpenClawCameraClipParams) async throws -> (format: String, base64: String, durationMs: Int, hasAudio: Bool) -} - -protocol ScreenRecordingServicing: Sendable { - func record( - screenIndex: Int?, - durationMs: Int?, - fps: Double?, - includeAudio: Bool?, - outPath: String?) async throws -> String -} - -@MainActor -protocol LocationServicing: Sendable { - func authorizationStatus() -> CLAuthorizationStatus - func accuracyAuthorization() -> CLAccuracyAuthorization - func ensureAuthorization(mode: OpenClawLocationMode) async -> CLAuthorizationStatus - func currentLocation( - params: OpenClawLocationGetParams, - desiredAccuracy: OpenClawLocationAccuracy, - maxAgeMs: Int?, - timeoutMs: Int?) async throws -> CLLocation - func startLocationUpdates( - desiredAccuracy: OpenClawLocationAccuracy, - significantChangesOnly: Bool) -> AsyncStream - func stopLocationUpdates() - func startMonitoringSignificantLocationChanges(onUpdate: @escaping @Sendable (CLLocation) -> Void) - func stopMonitoringSignificantLocationChanges() -} - -protocol DeviceStatusServicing: Sendable { - func status() async throws -> OpenClawDeviceStatusPayload - func info() -> OpenClawDeviceInfoPayload -} - -protocol PhotosServicing: Sendable { - func latest(params: OpenClawPhotosLatestParams) async throws -> OpenClawPhotosLatestPayload -} - -protocol ContactsServicing: Sendable { - func search(params: OpenClawContactsSearchParams) async throws -> OpenClawContactsSearchPayload - func add(params: OpenClawContactsAddParams) async throws -> OpenClawContactsAddPayload -} - -protocol CalendarServicing: Sendable { - func events(params: OpenClawCalendarEventsParams) async throws -> OpenClawCalendarEventsPayload - func add(params: OpenClawCalendarAddParams) async throws -> OpenClawCalendarAddPayload -} - -protocol RemindersServicing: Sendable { - func list(params: OpenClawRemindersListParams) async throws -> OpenClawRemindersListPayload - func add(params: OpenClawRemindersAddParams) async throws -> OpenClawRemindersAddPayload -} - -protocol MotionServicing: Sendable { - func activities(params: OpenClawMotionActivityParams) async throws -> OpenClawMotionActivityPayload - func pedometer(params: OpenClawPedometerParams) async throws -> OpenClawPedometerPayload -} - -struct WatchMessagingStatus: Sendable, Equatable { - var supported: Bool - var paired: Bool - var appInstalled: Bool - var reachable: Bool - var activationState: String -} - -struct WatchQuickReplyEvent: Sendable, Equatable { - var replyId: String - var promptId: String - var actionId: String - var actionLabel: String? - var sessionKey: String? - var note: String? - var sentAtMs: Int? - var transport: String -} - -struct WatchNotificationSendResult: Sendable, Equatable { - var deliveredImmediately: Bool - var queuedForDelivery: Bool - var transport: String -} - -protocol WatchMessagingServicing: AnyObject, Sendable { - func status() async -> WatchMessagingStatus - func setReplyHandler(_ handler: (@Sendable (WatchQuickReplyEvent) -> Void)?) - func sendNotification( - id: String, - params: OpenClawWatchNotifyParams) async throws -> WatchNotificationSendResult -} - -extension CameraController: CameraServicing {} -extension ScreenRecordService: ScreenRecordingServicing {} -extension LocationService: LocationServicing {} diff --git a/apps/ios/Sources/Services/NotificationService.swift b/apps/ios/Sources/Services/NotificationService.swift deleted file mode 100644 index 348e93edc61..00000000000 --- a/apps/ios/Sources/Services/NotificationService.swift +++ /dev/null @@ -1,58 +0,0 @@ -import Foundation -import UserNotifications - -enum NotificationAuthorizationStatus: Sendable { - case notDetermined - case denied - case authorized - case provisional - case ephemeral -} - -protocol NotificationCentering: Sendable { - func authorizationStatus() async -> NotificationAuthorizationStatus - func requestAuthorization(options: UNAuthorizationOptions) async throws -> Bool - func add(_ request: UNNotificationRequest) async throws -} - -struct LiveNotificationCenter: NotificationCentering, @unchecked Sendable { - private let center: UNUserNotificationCenter - - init(center: UNUserNotificationCenter = .current()) { - self.center = center - } - - func authorizationStatus() async -> NotificationAuthorizationStatus { - let settings = await self.center.notificationSettings() - return switch settings.authorizationStatus { - case .authorized: - .authorized - case .provisional: - .provisional - case .ephemeral: - .ephemeral - case .denied: - .denied - case .notDetermined: - .notDetermined - @unknown default: - .denied - } - } - - func requestAuthorization(options: UNAuthorizationOptions) async throws -> Bool { - try await self.center.requestAuthorization(options: options) - } - - func add(_ request: UNNotificationRequest) async throws { - try await withCheckedThrowingContinuation { (cont: CheckedContinuation) in - self.center.add(request) { error in - if let error { - cont.resume(throwing: error) - } else { - cont.resume(returning: ()) - } - } - } - } -} diff --git a/apps/ios/Sources/Services/WatchMessagingService.swift b/apps/ios/Sources/Services/WatchMessagingService.swift deleted file mode 100644 index 3511a06c2db..00000000000 --- a/apps/ios/Sources/Services/WatchMessagingService.swift +++ /dev/null @@ -1,280 +0,0 @@ -import Foundation -import OpenClawKit -import OSLog -@preconcurrency import WatchConnectivity - -enum WatchMessagingError: LocalizedError { - case unsupported - case notPaired - case watchAppNotInstalled - - var errorDescription: String? { - switch self { - case .unsupported: - "WATCH_UNAVAILABLE: WatchConnectivity is not supported on this device" - case .notPaired: - "WATCH_UNAVAILABLE: no paired Apple Watch" - case .watchAppNotInstalled: - "WATCH_UNAVAILABLE: OpenClaw watch companion app is not installed" - } - } -} - -final class WatchMessagingService: NSObject, WatchMessagingServicing, @unchecked Sendable { - private static let logger = Logger(subsystem: "ai.openclaw", category: "watch.messaging") - private let session: WCSession? - private let replyHandlerLock = NSLock() - private var replyHandler: (@Sendable (WatchQuickReplyEvent) -> Void)? - - override init() { - if WCSession.isSupported() { - self.session = WCSession.default - } else { - self.session = nil - } - super.init() - if let session = self.session { - session.delegate = self - session.activate() - } - } - - static func isSupportedOnDevice() -> Bool { - WCSession.isSupported() - } - - static func currentStatusSnapshot() -> WatchMessagingStatus { - guard WCSession.isSupported() else { - return WatchMessagingStatus( - supported: false, - paired: false, - appInstalled: false, - reachable: false, - activationState: "unsupported") - } - let session = WCSession.default - return status(for: session) - } - - func status() async -> WatchMessagingStatus { - await self.ensureActivated() - guard let session = self.session else { - return WatchMessagingStatus( - supported: false, - paired: false, - appInstalled: false, - reachable: false, - activationState: "unsupported") - } - return Self.status(for: session) - } - - func setReplyHandler(_ handler: (@Sendable (WatchQuickReplyEvent) -> Void)?) { - self.replyHandlerLock.lock() - self.replyHandler = handler - self.replyHandlerLock.unlock() - } - - func sendNotification( - id: String, - params: OpenClawWatchNotifyParams) async throws -> WatchNotificationSendResult - { - await self.ensureActivated() - guard let session = self.session else { - throw WatchMessagingError.unsupported - } - - let snapshot = Self.status(for: session) - guard snapshot.paired else { throw WatchMessagingError.notPaired } - guard snapshot.appInstalled else { throw WatchMessagingError.watchAppNotInstalled } - - var payload: [String: Any] = [ - "type": "watch.notify", - "id": id, - "title": params.title, - "body": params.body, - "priority": params.priority?.rawValue ?? OpenClawNotificationPriority.active.rawValue, - "sentAtMs": Int(Date().timeIntervalSince1970 * 1000), - ] - if let promptId = Self.nonEmpty(params.promptId) { - payload["promptId"] = promptId - } - if let sessionKey = Self.nonEmpty(params.sessionKey) { - payload["sessionKey"] = sessionKey - } - if let kind = Self.nonEmpty(params.kind) { - payload["kind"] = kind - } - if let details = Self.nonEmpty(params.details) { - payload["details"] = details - } - if let expiresAtMs = params.expiresAtMs { - payload["expiresAtMs"] = expiresAtMs - } - if let risk = params.risk { - payload["risk"] = risk.rawValue - } - if let actions = params.actions, !actions.isEmpty { - payload["actions"] = actions.map { action in - var encoded: [String: Any] = [ - "id": action.id, - "label": action.label, - ] - if let style = Self.nonEmpty(action.style) { - encoded["style"] = style - } - return encoded - } - } - - if snapshot.reachable { - do { - try await self.sendReachableMessage(payload, with: session) - return WatchNotificationSendResult( - deliveredImmediately: true, - queuedForDelivery: false, - transport: "sendMessage") - } catch { - Self.logger.error("watch sendMessage failed: \(error.localizedDescription, privacy: .public)") - } - } - - _ = session.transferUserInfo(payload) - return WatchNotificationSendResult( - deliveredImmediately: false, - queuedForDelivery: true, - transport: "transferUserInfo") - } - - private func sendReachableMessage(_ payload: [String: Any], with session: WCSession) async throws { - try await withCheckedThrowingContinuation { continuation in - session.sendMessage(payload, replyHandler: { _ in - continuation.resume() - }, errorHandler: { error in - continuation.resume(throwing: error) - }) - } - } - - private func emitReply(_ event: WatchQuickReplyEvent) { - let handler: ((WatchQuickReplyEvent) -> Void)? - self.replyHandlerLock.lock() - handler = self.replyHandler - self.replyHandlerLock.unlock() - handler?(event) - } - - private static func nonEmpty(_ value: String?) -> String? { - let trimmed = value?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - return trimmed.isEmpty ? nil : trimmed - } - - private static func parseQuickReplyPayload( - _ payload: [String: Any], - transport: String) -> WatchQuickReplyEvent? - { - guard (payload["type"] as? String) == "watch.reply" else { - return nil - } - guard let actionId = nonEmpty(payload["actionId"] as? String) else { - return nil - } - let promptId = nonEmpty(payload["promptId"] as? String) ?? "unknown" - let replyId = nonEmpty(payload["replyId"] as? String) ?? UUID().uuidString - let actionLabel = nonEmpty(payload["actionLabel"] as? String) - let sessionKey = nonEmpty(payload["sessionKey"] as? String) - let note = nonEmpty(payload["note"] as? String) - let sentAtMs = (payload["sentAtMs"] as? Int) ?? (payload["sentAtMs"] as? NSNumber)?.intValue - - return WatchQuickReplyEvent( - replyId: replyId, - promptId: promptId, - actionId: actionId, - actionLabel: actionLabel, - sessionKey: sessionKey, - note: note, - sentAtMs: sentAtMs, - transport: transport) - } - - private func ensureActivated() async { - guard let session = self.session else { return } - if session.activationState == .activated { return } - session.activate() - for _ in 0..<8 { - if session.activationState == .activated { return } - try? await Task.sleep(nanoseconds: 100_000_000) - } - } - - private static func status(for session: WCSession) -> WatchMessagingStatus { - WatchMessagingStatus( - supported: true, - paired: session.isPaired, - appInstalled: session.isWatchAppInstalled, - reachable: session.isReachable, - activationState: activationStateLabel(session.activationState)) - } - - private static func activationStateLabel(_ state: WCSessionActivationState) -> String { - switch state { - case .notActivated: - "notActivated" - case .inactive: - "inactive" - case .activated: - "activated" - @unknown default: - "unknown" - } - } -} - -extension WatchMessagingService: WCSessionDelegate { - func session( - _ session: WCSession, - activationDidCompleteWith activationState: WCSessionActivationState, - error: (any Error)?) - { - if let error { - Self.logger.error("watch activation failed: \(error.localizedDescription, privacy: .public)") - return - } - Self.logger.debug("watch activation state=\(Self.activationStateLabel(activationState), privacy: .public)") - } - - func sessionDidBecomeInactive(_ session: WCSession) {} - - func sessionDidDeactivate(_ session: WCSession) { - session.activate() - } - - func session(_: WCSession, didReceiveMessage message: [String: Any]) { - guard let event = Self.parseQuickReplyPayload(message, transport: "sendMessage") else { - return - } - self.emitReply(event) - } - - func session( - _: WCSession, - didReceiveMessage message: [String: Any], - replyHandler: @escaping ([String: Any]) -> Void) - { - guard let event = Self.parseQuickReplyPayload(message, transport: "sendMessage") else { - replyHandler(["ok": false, "error": "unsupported_payload"]) - return - } - replyHandler(["ok": true]) - self.emitReply(event) - } - - func session(_: WCSession, didReceiveUserInfo userInfo: [String: Any]) { - guard let event = Self.parseQuickReplyPayload(userInfo, transport: "transferUserInfo") else { - return - } - self.emitReply(event) - } - - func sessionReachabilityDidChange(_ session: WCSession) {} -} diff --git a/apps/ios/Sources/SessionKey.swift b/apps/ios/Sources/SessionKey.swift deleted file mode 100644 index 89798b6a293..00000000000 --- a/apps/ios/Sources/SessionKey.swift +++ /dev/null @@ -1,23 +0,0 @@ -import Foundation - -enum SessionKey { - static func normalizeMainKey(_ raw: String?) -> String { - let trimmed = (raw ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed.isEmpty ? "main" : trimmed - } - - static func makeAgentSessionKey(agentId: String, baseKey: String) -> String { - let trimmedAgent = agentId.trimmingCharacters(in: .whitespacesAndNewlines) - let trimmedBase = baseKey.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmedAgent.isEmpty { return trimmedBase.isEmpty ? "main" : trimmedBase } - let normalizedBase = trimmedBase.isEmpty ? "main" : trimmedBase - return "agent:\(trimmedAgent):\(normalizedBase)" - } - - static func isCanonicalMainSessionKey(_ value: String?) -> Bool { - let trimmed = (value ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty { return false } - if trimmed == "global" { return true } - return trimmed.hasPrefix("agent:") - } -} diff --git a/apps/ios/Sources/Settings/SettingsNetworkingHelpers.swift b/apps/ios/Sources/Settings/SettingsNetworkingHelpers.swift deleted file mode 100644 index f061ff9a204..00000000000 --- a/apps/ios/Sources/Settings/SettingsNetworkingHelpers.swift +++ /dev/null @@ -1,40 +0,0 @@ -import Foundation - -struct SettingsHostPort: Equatable { - var host: String - var port: Int -} - -enum SettingsNetworkingHelpers { - static func parseHostPort(from address: String) -> SettingsHostPort? { - let trimmed = address.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - - if trimmed.hasPrefix("["), - let close = trimmed.firstIndex(of: "]"), - close < trimmed.endIndex - { - let host = String(trimmed[trimmed.index(after: trimmed.startIndex).. String { - if let host, let port { - let needsBrackets = host.contains(":") && !host.hasPrefix("[") && !host.hasSuffix("]") - let hostPart = needsBrackets ? "[\(host)]" : host - return "http://\(hostPart):\(port)" - } - return "http://\(fallback)" - } -} diff --git a/apps/ios/Sources/Settings/SettingsTab.swift b/apps/ios/Sources/Settings/SettingsTab.swift deleted file mode 100644 index 024a4cbf42b..00000000000 --- a/apps/ios/Sources/Settings/SettingsTab.swift +++ /dev/null @@ -1,1042 +0,0 @@ -import OpenClawKit -import Network -import Observation -import os -import SwiftUI -import UIKit - -struct SettingsTab: View { - private struct FeatureHelp: Identifiable { - let id = UUID() - let title: String - let message: String - } - - @Environment(NodeAppModel.self) private var appModel: NodeAppModel - @Environment(VoiceWakeManager.self) private var voiceWake: VoiceWakeManager - @Environment(GatewayConnectionController.self) private var gatewayController: GatewayConnectionController - @Environment(\.dismiss) private var dismiss - @AppStorage("node.displayName") private var displayName: String = "iOS Node" - @AppStorage("node.instanceId") private var instanceId: String = UUID().uuidString - @AppStorage("voiceWake.enabled") private var voiceWakeEnabled: Bool = false - @AppStorage("talk.enabled") private var talkEnabled: Bool = false - @AppStorage("talk.button.enabled") private var talkButtonEnabled: Bool = true - @AppStorage("talk.background.enabled") private var talkBackgroundEnabled: Bool = false - @AppStorage("talk.voiceDirectiveHint.enabled") private var talkVoiceDirectiveHintEnabled: Bool = true - @AppStorage("camera.enabled") private var cameraEnabled: Bool = true - @AppStorage("location.enabledMode") private var locationEnabledModeRaw: String = OpenClawLocationMode.off.rawValue - @AppStorage("screen.preventSleep") private var preventSleep: Bool = true - @AppStorage("gateway.preferredStableID") private var preferredGatewayStableID: String = "" - @AppStorage("gateway.lastDiscoveredStableID") private var lastDiscoveredGatewayStableID: String = "" - @AppStorage("gateway.autoconnect") private var gatewayAutoConnect: Bool = false - @AppStorage("gateway.manual.enabled") private var manualGatewayEnabled: Bool = false - @AppStorage("gateway.manual.host") private var manualGatewayHost: String = "" - @AppStorage("gateway.manual.port") private var manualGatewayPort: Int = 18789 - @AppStorage("gateway.manual.tls") private var manualGatewayTLS: Bool = true - @AppStorage("gateway.discovery.debugLogs") private var discoveryDebugLogsEnabled: Bool = false - @AppStorage("canvas.debugStatusEnabled") private var canvasDebugStatusEnabled: Bool = false - - // Onboarding control (RootCanvas listens to onboarding.requestID and force-opens the wizard). - @AppStorage("onboarding.requestID") private var onboardingRequestID: Int = 0 - @AppStorage("gateway.onboardingComplete") private var onboardingComplete: Bool = false - @AppStorage("gateway.hasConnectedOnce") private var hasConnectedOnce: Bool = false - - @State private var connectingGatewayID: String? - @State private var lastLocationModeRaw: String = OpenClawLocationMode.off.rawValue - @State private var gatewayToken: String = "" - @State private var gatewayPassword: String = "" - @State private var defaultShareInstruction: String = "" - @AppStorage("gateway.setupCode") private var setupCode: String = "" - @State private var setupStatusText: String? - @State private var manualGatewayPortText: String = "" - @State private var gatewayExpanded: Bool = true - @State private var selectedAgentPickerId: String = "" - - @State private var showResetOnboardingAlert: Bool = false - @State private var activeFeatureHelp: FeatureHelp? - @State private var suppressCredentialPersist: Bool = false - - private let gatewayLogger = Logger(subsystem: "ai.openclaw.ios", category: "GatewaySettings") - - var body: some View { - NavigationStack { - Form { - Section { - DisclosureGroup(isExpanded: self.$gatewayExpanded) { - if !self.isGatewayConnected { - Text( - "1. Open Telegram and message your bot: /pair\n" - + "2. Copy the setup code it returns\n" - + "3. Paste here and tap Connect\n" - + "4. Back in Telegram, run /pair approve") - .font(.footnote) - .foregroundStyle(.secondary) - - if let warning = self.tailnetWarningText { - Text(warning) - .font(.footnote.weight(.semibold)) - .foregroundStyle(.orange) - } - - TextField("Paste setup code", text: self.$setupCode) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - - Button { - Task { await self.applySetupCodeAndConnect() } - } label: { - if self.connectingGatewayID == "manual" { - HStack(spacing: 8) { - ProgressView() - .progressViewStyle(.circular) - Text("Connecting…") - } - } else { - Text("Connect with setup code") - } - } - .disabled(self.connectingGatewayID != nil - || self.setupCode.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) - - if let status = self.setupStatusLine { - Text(status) - .font(.footnote) - .foregroundStyle(.secondary) - } - } - - if self.isGatewayConnected { - Picker("Bot", selection: self.$selectedAgentPickerId) { - Text("Default").tag("") - let defaultId = (self.appModel.gatewayDefaultAgentId ?? "") - .trimmingCharacters(in: .whitespacesAndNewlines) - ForEach(self.appModel.gatewayAgents.filter { $0.id != defaultId }, id: \.id) { agent in - let name = (agent.name ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - Text(name.isEmpty ? agent.id : name).tag(agent.id) - } - } - Text("Controls which bot Chat and Talk speak to.") - .font(.footnote) - .foregroundStyle(.secondary) - } - - if self.appModel.gatewayServerName == nil { - LabeledContent("Discovery", value: self.gatewayController.discoveryStatusText) - } - LabeledContent("Status", value: self.appModel.gatewayStatusText) - Toggle("Auto-connect on launch", isOn: self.$gatewayAutoConnect) - - if let serverName = self.appModel.gatewayServerName { - LabeledContent("Server", value: serverName) - if let addr = self.appModel.gatewayRemoteAddress { - let parts = Self.parseHostPort(from: addr) - let urlString = Self.httpURLString(host: parts?.host, port: parts?.port, fallback: addr) - LabeledContent("Address") { - Text(urlString) - } - .contextMenu { - Button { - UIPasteboard.general.string = urlString - } label: { - Label("Copy URL", systemImage: "doc.on.doc") - } - - if let parts { - Button { - UIPasteboard.general.string = parts.host - } label: { - Label("Copy Host", systemImage: "doc.on.doc") - } - - Button { - UIPasteboard.general.string = "\(parts.port)" - } label: { - Label("Copy Port", systemImage: "doc.on.doc") - } - } - } - } - - Button("Disconnect", role: .destructive) { - self.appModel.disconnectGateway() - } - } else { - self.gatewayList(showing: .all) - } - - DisclosureGroup("Advanced") { - Toggle("Use Manual Gateway", isOn: self.$manualGatewayEnabled) - - TextField("Host", text: self.$manualGatewayHost) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - - TextField("Port (optional)", text: self.manualPortBinding) - .keyboardType(.numberPad) - - Toggle("Use TLS", isOn: self.$manualGatewayTLS) - - Button { - Task { await self.connectManual() } - } label: { - if self.connectingGatewayID == "manual" { - HStack(spacing: 8) { - ProgressView() - .progressViewStyle(.circular) - Text("Connecting…") - } - } else { - Text("Connect (Manual)") - } - } - .disabled(self.connectingGatewayID != nil || self.manualGatewayHost - .trimmingCharacters(in: .whitespacesAndNewlines) - .isEmpty || !self.manualPortIsValid) - - Text( - "Use this when mDNS/Bonjour discovery is blocked. " - + "Leave port empty for 443 on tailnet DNS (TLS) or 18789 otherwise.") - .font(.footnote) - .foregroundStyle(.secondary) - - Toggle("Discovery Debug Logs", isOn: self.$discoveryDebugLogsEnabled) - .onChange(of: self.discoveryDebugLogsEnabled) { _, newValue in - self.gatewayController.setDiscoveryDebugLoggingEnabled(newValue) - } - - NavigationLink("Discovery Logs") { - GatewayDiscoveryDebugLogView() - } - - Toggle("Debug Canvas Status", isOn: self.$canvasDebugStatusEnabled) - - TextField("Gateway Auth Token", text: self.$gatewayToken) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - - SecureField("Gateway Password", text: self.$gatewayPassword) - - Button("Reset Onboarding", role: .destructive) { - self.showResetOnboardingAlert = true - } - - VStack(alignment: .leading, spacing: 6) { - Text("Debug") - .font(.footnote.weight(.semibold)) - .foregroundStyle(.secondary) - Text(self.gatewayDebugText()) - .font(.system(size: 12, weight: .regular, design: .monospaced)) - .foregroundStyle(.secondary) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(10) - .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 10, style: .continuous)) - } - } - } label: { - HStack(spacing: 10) { - Circle() - .fill(self.isGatewayConnected ? Color.green : Color.secondary.opacity(0.35)) - .frame(width: 10, height: 10) - Text("Gateway") - Spacer() - Text(self.gatewaySummaryText) - .font(.footnote) - .foregroundStyle(.secondary) - } - } - } - - Section("Device") { - DisclosureGroup("Features") { - self.featureToggle( - "Voice Wake", - isOn: self.$voiceWakeEnabled, - help: "Enables wake-word activation to start a hands-free session.") { newValue in - self.appModel.setVoiceWakeEnabled(newValue) - } - self.featureToggle( - "Talk Mode", - isOn: self.$talkEnabled, - help: "Enables voice conversation mode with your connected OpenClaw agent.") { newValue in - self.appModel.setTalkEnabled(newValue) - } - self.featureToggle( - "Background Listening", - isOn: self.$talkBackgroundEnabled, - help: "Keeps listening while the app is backgrounded. Uses more battery.") - - NavigationLink { - VoiceWakeWordsSettingsView() - } label: { - LabeledContent( - "Wake Words", - value: VoiceWakePreferences.displayString(for: self.voiceWake.triggerWords)) - } - - self.featureToggle( - "Allow Camera", - isOn: self.$cameraEnabled, - help: "Allows the gateway to request photos or short video clips while OpenClaw is foregrounded.") - - HStack(spacing: 8) { - Text("Location Access") - Spacer() - Button { - self.activeFeatureHelp = FeatureHelp( - title: "Location Access", - message: "Controls location permissions for OpenClaw. Off disables location tools, While Using enables foreground location, and Always enables background location.") - } label: { - Image(systemName: "info.circle") - .foregroundStyle(.secondary) - } - .buttonStyle(.plain) - .accessibilityLabel("Location Access info") - } - Picker("Location Access", selection: self.$locationEnabledModeRaw) { - Text("Off").tag(OpenClawLocationMode.off.rawValue) - Text("While Using").tag(OpenClawLocationMode.whileUsing.rawValue) - Text("Always").tag(OpenClawLocationMode.always.rawValue) - } - .labelsHidden() - .pickerStyle(.segmented) - - self.featureToggle( - "Prevent Sleep", - isOn: self.$preventSleep, - help: "Keeps the screen awake while OpenClaw is open.") - - DisclosureGroup("Advanced") { - VStack(alignment: .leading, spacing: 8) { - Text("Talk Voice (Gateway)") - .font(.footnote.weight(.semibold)) - .foregroundStyle(.secondary) - LabeledContent("Provider", value: "ElevenLabs") - LabeledContent( - "API Key", - value: self.appModel.talkMode.gatewayTalkConfigLoaded - ? (self.appModel.talkMode.gatewayTalkApiKeyConfigured ? "Configured" : "Not configured") - : "Not loaded") - LabeledContent( - "Default Model", - value: self.appModel.talkMode.gatewayTalkDefaultModelId ?? "eleven_v3 (fallback)") - LabeledContent( - "Default Voice", - value: self.appModel.talkMode.gatewayTalkDefaultVoiceId ?? "auto (first available)") - Text("Configured on gateway via talk.apiKey, talk.modelId, and talk.voiceId.") - .font(.footnote) - .foregroundStyle(.secondary) - } - self.featureToggle( - "Voice Directive Hint", - isOn: self.$talkVoiceDirectiveHintEnabled, - help: "Adds voice-switching instructions to Talk prompts. Disable to reduce prompt size.") - self.featureToggle( - "Show Talk Button", - isOn: self.$talkButtonEnabled, - help: "Shows the floating Talk button in the main interface.") - TextField("Default Share Instruction", text: self.$defaultShareInstruction, axis: .vertical) - .lineLimit(2 ... 6) - .textInputAutocapitalization(.sentences) - HStack(spacing: 8) { - Text("Default Share Instruction") - .font(.footnote) - .foregroundStyle(.secondary) - Spacer() - Button { - self.activeFeatureHelp = FeatureHelp( - title: "Default Share Instruction", - message: "Appends this instruction when sharing content into OpenClaw from iOS.") - } label: { - Image(systemName: "info.circle") - .foregroundStyle(.secondary) - } - .buttonStyle(.plain) - .accessibilityLabel("Default Share Instruction info") - } - - VStack(alignment: .leading, spacing: 8) { - Button { - Task { await self.appModel.runSharePipelineSelfTest() } - } label: { - Label("Run Share Self-Test", systemImage: "checkmark.seal") - } - Text(self.appModel.lastShareEventText) - .font(.footnote) - .foregroundStyle(.secondary) - } - } - } - - DisclosureGroup("Device Info") { - TextField("Name", text: self.$displayName) - Text(self.instanceId) - .font(.footnote) - .foregroundStyle(.secondary) - .lineLimit(1) - .truncationMode(.middle) - LabeledContent("Device", value: self.deviceFamily()) - LabeledContent("Platform", value: self.platformString()) - LabeledContent("OpenClaw", value: self.openClawVersionString()) - } - } - } - .navigationTitle("Settings") - .toolbar { - ToolbarItem(placement: .topBarTrailing) { - Button { - self.dismiss() - } label: { - Image(systemName: "xmark") - } - .accessibilityLabel("Close") - } - } - .alert("Reset Onboarding?", isPresented: self.$showResetOnboardingAlert) { - Button("Reset", role: .destructive) { - self.resetOnboarding() - } - Button("Cancel", role: .cancel) {} - } message: { - Text( - "This will disconnect, clear saved gateway connection + credentials, and reopen the onboarding wizard.") - } - .alert(item: self.$activeFeatureHelp) { help in - Alert( - title: Text(help.title), - message: Text(help.message), - dismissButton: .default(Text("OK"))) - } - .onAppear { - self.lastLocationModeRaw = self.locationEnabledModeRaw - self.syncManualPortText() - let trimmedInstanceId = self.instanceId.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmedInstanceId.isEmpty { - self.gatewayToken = GatewaySettingsStore.loadGatewayToken(instanceId: trimmedInstanceId) ?? "" - self.gatewayPassword = GatewaySettingsStore.loadGatewayPassword(instanceId: trimmedInstanceId) ?? "" - } - self.defaultShareInstruction = ShareToAgentSettings.loadDefaultInstruction() - self.appModel.refreshLastShareEventFromRelay() - // Keep setup front-and-center when disconnected; keep things compact once connected. - self.gatewayExpanded = !self.isGatewayConnected - self.selectedAgentPickerId = self.appModel.selectedAgentId ?? "" - if self.isGatewayConnected { - self.appModel.reloadTalkConfig() - } - } - .onChange(of: self.selectedAgentPickerId) { _, newValue in - let trimmed = newValue.trimmingCharacters(in: .whitespacesAndNewlines) - self.appModel.setSelectedAgentId(trimmed.isEmpty ? nil : trimmed) - } - .onChange(of: self.appModel.selectedAgentId ?? "") { _, newValue in - if newValue != self.selectedAgentPickerId { - self.selectedAgentPickerId = newValue - } - } - .onChange(of: self.preferredGatewayStableID) { _, newValue in - let trimmed = newValue.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return } - GatewaySettingsStore.savePreferredGatewayStableID(trimmed) - } - .onChange(of: self.gatewayToken) { _, newValue in - guard !self.suppressCredentialPersist else { return } - let trimmed = newValue.trimmingCharacters(in: .whitespacesAndNewlines) - let instanceId = self.instanceId.trimmingCharacters(in: .whitespacesAndNewlines) - guard !instanceId.isEmpty else { return } - GatewaySettingsStore.saveGatewayToken(trimmed, instanceId: instanceId) - } - .onChange(of: self.gatewayPassword) { _, newValue in - guard !self.suppressCredentialPersist else { return } - let trimmed = newValue.trimmingCharacters(in: .whitespacesAndNewlines) - let instanceId = self.instanceId.trimmingCharacters(in: .whitespacesAndNewlines) - guard !instanceId.isEmpty else { return } - GatewaySettingsStore.saveGatewayPassword(trimmed, instanceId: instanceId) - } - .onChange(of: self.defaultShareInstruction) { _, newValue in - ShareToAgentSettings.saveDefaultInstruction(newValue) - } - .onChange(of: self.manualGatewayPort) { _, _ in - self.syncManualPortText() - } - .onChange(of: self.appModel.gatewayServerName) { _, newValue in - if newValue != nil { - self.setupCode = "" - self.setupStatusText = nil - return - } - if self.manualGatewayEnabled { - self.setupStatusText = self.appModel.gatewayStatusText - } - } - .onChange(of: self.appModel.gatewayStatusText) { _, newValue in - guard self.manualGatewayEnabled || self.connectingGatewayID == "manual" else { return } - let trimmed = newValue.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return } - self.setupStatusText = trimmed - } - .onChange(of: self.locationEnabledModeRaw) { _, newValue in - let previous = self.lastLocationModeRaw - self.lastLocationModeRaw = newValue - guard let mode = OpenClawLocationMode(rawValue: newValue) else { return } - Task { - let granted = await self.appModel.requestLocationPermissions(mode: mode) - if !granted { - await MainActor.run { - self.locationEnabledModeRaw = previous - self.lastLocationModeRaw = previous - } - return - } - await MainActor.run { - self.gatewayController.refreshActiveGatewayRegistrationFromSettings() - } - } - } - } - .gatewayTrustPromptAlert() - } - - @ViewBuilder - private func gatewayList(showing: GatewayListMode) -> some View { - if self.gatewayController.gateways.isEmpty { - VStack(alignment: .leading, spacing: 12) { - Text("No gateways found yet.") - .foregroundStyle(.secondary) - Text("If your gateway is on another network, connect it and ensure DNS is working.") - .font(.footnote) - .foregroundStyle(.secondary) - - if let lastKnown = GatewaySettingsStore.loadLastGatewayConnection(), - case let .manual(host, port, _, _) = lastKnown - { - Button { - Task { await self.connectLastKnown() } - } label: { - self.lastKnownButtonLabel(host: host, port: port) - } - .disabled(self.connectingGatewayID != nil) - .buttonStyle(.borderedProminent) - .tint(self.appModel.seamColor) - } - } - } else { - let connectedID = self.appModel.connectedGatewayID - let rows = self.gatewayController.gateways.filter { gateway in - let isConnected = gateway.stableID == connectedID - switch showing { - case .all: - return true - case .availableOnly: - return !isConnected - } - } - - if rows.isEmpty, showing == .availableOnly { - Text("No other gateways found.") - .foregroundStyle(.secondary) - } else { - ForEach(rows) { gateway in - HStack { - VStack(alignment: .leading, spacing: 2) { - // Avoid localized-string formatting edge cases from Bonjour-advertised names. - Text(verbatim: gateway.name) - let detailLines = self.gatewayDetailLines(gateway) - ForEach(detailLines, id: \.self) { line in - Text(verbatim: line) - .font(.footnote) - .foregroundStyle(.secondary) - } - } - Spacer() - - Button { - Task { await self.connect(gateway) } - } label: { - if self.connectingGatewayID == gateway.id { - ProgressView() - .progressViewStyle(.circular) - } else { - Text("Connect") - } - } - .disabled(self.connectingGatewayID != nil) - } - } - } - } - } - - private enum GatewayListMode: Equatable { - case all - case availableOnly - } - - private var isGatewayConnected: Bool { - let status = self.appModel.gatewayStatusText.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - if status.contains("connected") { return true } - return self.appModel.gatewayServerName != nil && !status.contains("offline") - } - - private var gatewaySummaryText: String { - if let server = self.appModel.gatewayServerName, self.isGatewayConnected { - return server - } - let trimmed = self.appModel.gatewayStatusText.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed.isEmpty ? "Not connected" : trimmed - } - - private func platformString() -> String { - let v = ProcessInfo.processInfo.operatingSystemVersion - return "iOS \(v.majorVersion).\(v.minorVersion).\(v.patchVersion)" - } - - private func deviceFamily() -> String { - switch UIDevice.current.userInterfaceIdiom { - case .pad: - "iPad" - case .phone: - "iPhone" - default: - "iOS" - } - } - - private func openClawVersionString() -> String { - let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "dev" - let build = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "" - let trimmedBuild = build.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmedBuild.isEmpty || trimmedBuild == version { - return version - } - return "\(version) (\(trimmedBuild))" - } - - private func featureToggle( - _ title: String, - isOn: Binding, - help: String, - onChange: ((Bool) -> Void)? = nil - ) -> some View { - HStack(spacing: 8) { - Toggle(title, isOn: isOn) - Button { - self.activeFeatureHelp = FeatureHelp(title: title, message: help) - } label: { - Image(systemName: "info.circle") - .foregroundStyle(.secondary) - } - .buttonStyle(.plain) - .accessibilityLabel("\(title) info") - } - .onChange(of: isOn.wrappedValue) { _, newValue in - onChange?(newValue) - } - } - - private func connect(_ gateway: GatewayDiscoveryModel.DiscoveredGateway) async { - self.connectingGatewayID = gateway.id - self.manualGatewayEnabled = false - self.preferredGatewayStableID = gateway.stableID - GatewaySettingsStore.savePreferredGatewayStableID(gateway.stableID) - self.lastDiscoveredGatewayStableID = gateway.stableID - GatewaySettingsStore.saveLastDiscoveredGatewayStableID(gateway.stableID) - defer { self.connectingGatewayID = nil } - - let err = await self.gatewayController.connectWithDiagnostics(gateway) - if let err { - self.setupStatusText = err - } - } - - private func connectLastKnown() async { - self.connectingGatewayID = "last-known" - defer { self.connectingGatewayID = nil } - await self.gatewayController.connectLastKnown() - } - - private func gatewayDebugText() -> String { - var lines: [String] = [ - "gateway: \(self.appModel.gatewayStatusText)", - "discovery: \(self.gatewayController.discoveryStatusText)", - ] - lines.append("server: \(self.appModel.gatewayServerName ?? "—")") - lines.append("address: \(self.appModel.gatewayRemoteAddress ?? "—")") - if let last = self.gatewayController.discoveryDebugLog.last?.message { - lines.append("discovery log: \(last)") - } - return lines.joined(separator: "\n") - } - - @ViewBuilder - private func lastKnownButtonLabel(host: String, port: Int) -> some View { - if self.connectingGatewayID == "last-known" { - HStack(spacing: 8) { - ProgressView() - .progressViewStyle(.circular) - Text("Connecting…") - } - .frame(maxWidth: .infinity) - } else { - HStack(spacing: 8) { - Image(systemName: "bolt.horizontal.circle.fill") - VStack(alignment: .leading, spacing: 2) { - Text("Connect last known") - Text("\(host):\(port)") - .font(.footnote) - .foregroundStyle(.secondary) - } - Spacer() - } - .frame(maxWidth: .infinity) - } - } - - private var manualPortBinding: Binding { - Binding( - get: { self.manualGatewayPortText }, - set: { newValue in - let filtered = newValue.filter(\.isNumber) - if self.manualGatewayPortText != filtered { - self.manualGatewayPortText = filtered - } - if filtered.isEmpty { - if self.manualGatewayPort != 0 { - self.manualGatewayPort = 0 - } - } else if let port = Int(filtered), self.manualGatewayPort != port { - self.manualGatewayPort = port - } - }) - } - - private var manualPortIsValid: Bool { - if self.manualGatewayPortText.isEmpty { return true } - return self.manualGatewayPort >= 1 && self.manualGatewayPort <= 65535 - } - - private func syncManualPortText() { - if self.manualGatewayPort > 0 { - let next = String(self.manualGatewayPort) - if self.manualGatewayPortText != next { - self.manualGatewayPortText = next - } - } else if !self.manualGatewayPortText.isEmpty { - self.manualGatewayPortText = "" - } - } - - private func applySetupCodeAndConnect() async { - self.setupStatusText = nil - guard self.applySetupCode() else { return } - let host = self.manualGatewayHost.trimmingCharacters(in: .whitespacesAndNewlines) - let resolvedPort = self.resolvedManualPort(host: host) - let hasToken = !self.gatewayToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty - let hasPassword = !self.gatewayPassword.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty - GatewayDiagnostics.log( - "setup code applied host=\(host) port=\(resolvedPort ?? -1) tls=\(self.manualGatewayTLS) token=\(hasToken) password=\(hasPassword)") - guard let port = resolvedPort else { - self.setupStatusText = "Failed: invalid port" - return - } - let ok = await self.preflightGateway(host: host, port: port, useTLS: self.manualGatewayTLS) - guard ok else { return } - self.setupStatusText = "Setup code applied. Connecting…" - await self.connectManual() - } - - @discardableResult - private func applySetupCode() -> Bool { - let raw = self.setupCode.trimmingCharacters(in: .whitespacesAndNewlines) - guard !raw.isEmpty else { - self.setupStatusText = "Paste a setup code to continue." - return false - } - - guard let payload = GatewaySetupCode.decode(raw: raw) else { - self.setupStatusText = "Setup code not recognized." - return false - } - - if let urlString = payload.url, let url = URL(string: urlString) { - self.applySetupURL(url) - } else if let host = payload.host, !host.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - self.manualGatewayHost = host.trimmingCharacters(in: .whitespacesAndNewlines) - if let port = payload.port { - self.manualGatewayPort = port - self.manualGatewayPortText = String(port) - } else { - self.manualGatewayPort = 0 - self.manualGatewayPortText = "" - } - if let tls = payload.tls { - self.manualGatewayTLS = tls - } - } else if let url = URL(string: raw), url.scheme != nil { - self.applySetupURL(url) - } else { - self.setupStatusText = "Setup code missing URL or host." - return false - } - - let trimmedInstanceId = self.instanceId.trimmingCharacters(in: .whitespacesAndNewlines) - if let token = payload.token, !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - let trimmedToken = token.trimmingCharacters(in: .whitespacesAndNewlines) - self.gatewayToken = trimmedToken - if !trimmedInstanceId.isEmpty { - GatewaySettingsStore.saveGatewayToken(trimmedToken, instanceId: trimmedInstanceId) - } - } - if let password = payload.password, !password.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - let trimmedPassword = password.trimmingCharacters(in: .whitespacesAndNewlines) - self.gatewayPassword = trimmedPassword - if !trimmedInstanceId.isEmpty { - GatewaySettingsStore.saveGatewayPassword(trimmedPassword, instanceId: trimmedInstanceId) - } - } - - return true - } - - private func applySetupURL(_ url: URL) { - guard let host = url.host, !host.isEmpty else { return } - self.manualGatewayHost = host - if let port = url.port { - self.manualGatewayPort = port - self.manualGatewayPortText = String(port) - } else { - self.manualGatewayPort = 0 - self.manualGatewayPortText = "" - } - let scheme = (url.scheme ?? "").lowercased() - if scheme == "wss" || scheme == "https" { - self.manualGatewayTLS = true - } else if scheme == "ws" || scheme == "http" { - self.manualGatewayTLS = false - } - } - - private func resolvedManualPort(host: String) -> Int? { - if self.manualGatewayPort > 0 { - return self.manualGatewayPort <= 65535 ? self.manualGatewayPort : nil - } - let trimmed = host.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - if self.manualGatewayTLS && trimmed.lowercased().hasSuffix(".ts.net") { - return 443 - } - return 18789 - } - - private func preflightGateway(host: String, port: Int, useTLS: Bool) async -> Bool { - let trimmed = host.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return false } - - if Self.isTailnetHostOrIP(trimmed) && !Self.hasTailnetIPv4() { - let msg = "Tailscale is off on this iPhone. Turn it on, then try again." - self.setupStatusText = msg - GatewayDiagnostics.log("preflight fail: tailnet missing host=\(trimmed)") - self.gatewayLogger.warning("\(msg, privacy: .public)") - return false - } - - self.setupStatusText = "Checking gateway reachability…" - let ok = await Self.probeTCP(host: trimmed, port: port, timeoutSeconds: 3) - if !ok { - let msg = "Can't reach gateway at \(trimmed):\(port). Check Tailscale or LAN." - self.setupStatusText = msg - GatewayDiagnostics.log("preflight fail: unreachable host=\(trimmed) port=\(port)") - self.gatewayLogger.warning("\(msg, privacy: .public)") - return false - } - GatewayDiagnostics.log("preflight ok host=\(trimmed) port=\(port) tls=\(useTLS)") - return true - } - - private static func probeTCP(host: String, port: Int, timeoutSeconds: Double) async -> Bool { - await TCPProbe.probe( - host: host, - port: port, - timeoutSeconds: timeoutSeconds, - queueLabel: "gateway.preflight") - } - - // (GatewaySetupCode) decode raw setup codes. - - private func connectManual() async { - let host = self.manualGatewayHost.trimmingCharacters(in: .whitespacesAndNewlines) - guard !host.isEmpty else { - self.setupStatusText = "Failed: host required" - return - } - guard self.manualPortIsValid else { - self.setupStatusText = "Failed: invalid port" - return - } - - self.connectingGatewayID = "manual" - self.manualGatewayEnabled = true - defer { self.connectingGatewayID = nil } - - GatewayDiagnostics.log( - "connect manual host=\(host) port=\(self.manualGatewayPort) tls=\(self.manualGatewayTLS)") - await self.gatewayController.connectManual( - host: host, - port: self.manualGatewayPort, - useTLS: self.manualGatewayTLS) - } - - private var setupStatusLine: String? { - let trimmedSetup = self.setupStatusText?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let gatewayStatus = self.appModel.gatewayStatusText.trimmingCharacters(in: .whitespacesAndNewlines) - if let friendly = self.friendlyGatewayMessage(from: gatewayStatus) { return friendly } - if let friendly = self.friendlyGatewayMessage(from: trimmedSetup) { return friendly } - if !trimmedSetup.isEmpty { return trimmedSetup } - if gatewayStatus.isEmpty || gatewayStatus == "Offline" { return nil } - return gatewayStatus - } - - private var tailnetWarningText: String? { - let host = self.manualGatewayHost.trimmingCharacters(in: .whitespacesAndNewlines) - guard !host.isEmpty else { return nil } - guard Self.isTailnetHostOrIP(host) else { return nil } - guard !Self.hasTailnetIPv4() else { return nil } - return "This gateway is on your tailnet. Turn on Tailscale on this iPhone, then tap Connect." - } - - private func friendlyGatewayMessage(from raw: String) -> String? { - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - let lower = trimmed.lowercased() - if lower.contains("pairing required") { - return "Pairing required. Go back to Telegram and run /pair approve, then tap Connect again." - } - if lower.contains("device nonce required") || lower.contains("device nonce mismatch") { - return "Secure handshake failed. Make sure Tailscale is connected, then tap Connect again." - } - if lower.contains("device signature expired") || lower.contains("device signature invalid") { - return "Secure handshake failed. Check that your iPhone time is correct, then tap Connect again." - } - if lower.contains("connect timed out") || lower.contains("timed out") { - return "Connection timed out. Make sure Tailscale is connected, then try again." - } - if lower.contains("unauthorized role") { - return "Connected, but some controls are restricted for nodes. This is expected." - } - return nil - } - - private static func hasTailnetIPv4() -> Bool { - var addrList: UnsafeMutablePointer? - guard getifaddrs(&addrList) == 0, let first = addrList else { return false } - defer { freeifaddrs(addrList) } - - for ptr in sequence(first: first, next: { $0.pointee.ifa_next }) { - let flags = Int32(ptr.pointee.ifa_flags) - let isUp = (flags & IFF_UP) != 0 - let isLoopback = (flags & IFF_LOOPBACK) != 0 - let family = ptr.pointee.ifa_addr.pointee.sa_family - if !isUp || isLoopback || family != UInt8(AF_INET) { continue } - - var addr = ptr.pointee.ifa_addr.pointee - var buffer = [CChar](repeating: 0, count: Int(NI_MAXHOST)) - let result = getnameinfo( - &addr, - socklen_t(ptr.pointee.ifa_addr.pointee.sa_len), - &buffer, - socklen_t(buffer.count), - nil, - 0, - NI_NUMERICHOST) - guard result == 0 else { continue } - let len = buffer.prefix { $0 != 0 } - let bytes = len.map { UInt8(bitPattern: $0) } - guard let ip = String(bytes: bytes, encoding: .utf8) else { continue } - if self.isTailnetIPv4(ip) { return true } - } - - return false - } - - private static func isTailnetHostOrIP(_ host: String) -> Bool { - let trimmed = host.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - if trimmed.hasSuffix(".ts.net") || trimmed.hasSuffix(".ts.net.") { - return true - } - return self.isTailnetIPv4(trimmed) - } - - private static func isTailnetIPv4(_ ip: String) -> Bool { - let parts = ip.split(separator: ".") - guard parts.count == 4 else { return false } - let octets = parts.compactMap { Int($0) } - guard octets.count == 4 else { return false } - let a = octets[0] - let b = octets[1] - guard (0...255).contains(a), (0...255).contains(b) else { return false } - return a == 100 && b >= 64 && b <= 127 - } - - private static func parseHostPort(from address: String) -> SettingsHostPort? { - SettingsNetworkingHelpers.parseHostPort(from: address) - } - - private static func httpURLString(host: String?, port: Int?, fallback: String) -> String { - SettingsNetworkingHelpers.httpURLString(host: host, port: port, fallback: fallback) - } - - private func resetOnboarding() { - // Disconnect first so RootCanvas doesn't instantly mark onboarding complete again. - self.appModel.disconnectGateway() - self.connectingGatewayID = nil - self.setupStatusText = nil - self.setupCode = "" - self.gatewayAutoConnect = false - - self.suppressCredentialPersist = true - defer { self.suppressCredentialPersist = false } - - self.gatewayToken = "" - self.gatewayPassword = "" - - let trimmedInstanceId = self.instanceId.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmedInstanceId.isEmpty { - GatewaySettingsStore.deleteGatewayCredentials(instanceId: trimmedInstanceId) - } - - // Reset onboarding state + clear saved gateway connection (the two things RootCanvas checks). - GatewaySettingsStore.clearLastGatewayConnection() - - // RootCanvas also short-circuits onboarding when these are true. - self.onboardingComplete = false - self.hasConnectedOnce = false - - // Clear manual override so it doesn't count as an existing gateway config. - self.manualGatewayEnabled = false - self.manualGatewayHost = "" - - // Force re-present even without app restart. - self.onboardingRequestID += 1 - - // The onboarding wizard is presented from RootCanvas; dismiss Settings so it can show. - self.dismiss() - } - - private func gatewayDetailLines(_ gateway: GatewayDiscoveryModel.DiscoveredGateway) -> [String] { - var lines: [String] = [] - if let lanHost = gateway.lanHost { lines.append("LAN: \(lanHost)") } - if let tailnet = gateway.tailnetDns { lines.append("Tailnet: \(tailnet)") } - - let gatewayPort = gateway.gatewayPort - let canvasPort = gateway.canvasPort - if gatewayPort != nil || canvasPort != nil { - let gw = gatewayPort.map(String.init) ?? "—" - let canvas = canvasPort.map(String.init) ?? "—" - lines.append("Ports: gateway \(gw) · canvas \(canvas)") - } - - if lines.isEmpty { - lines.append(gateway.debugID) - } - - return lines - } -} diff --git a/apps/ios/Sources/Settings/VoiceWakeWordsSettingsView.swift b/apps/ios/Sources/Settings/VoiceWakeWordsSettingsView.swift deleted file mode 100644 index e00e87e55d6..00000000000 --- a/apps/ios/Sources/Settings/VoiceWakeWordsSettingsView.swift +++ /dev/null @@ -1,98 +0,0 @@ -import SwiftUI -import Combine - -struct VoiceWakeWordsSettingsView: View { - @Environment(NodeAppModel.self) private var appModel - @State private var triggerWords: [String] = VoiceWakePreferences.loadTriggerWords() - @FocusState private var focusedTriggerIndex: Int? - @State private var syncTask: Task? - - var body: some View { - Form { - Section { - ForEach(self.triggerWords.indices, id: \.self) { index in - TextField("Wake word", text: self.binding(for: index)) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - .focused(self.$focusedTriggerIndex, equals: index) - .onSubmit { - self.commitTriggerWords() - } - } - .onDelete(perform: self.removeWords) - - Button { - self.addWord() - } label: { - Label("Add word", systemImage: "plus") - } - .disabled(self.triggerWords - .contains(where: { $0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty })) - - Button("Reset defaults") { - self.triggerWords = VoiceWakePreferences.defaultTriggerWords - } - } header: { - Text("Wake Words") - } footer: { - Text( - "OpenClaw reacts when any trigger appears in a transcription. " - + "Keep them short to avoid false positives.") - } - } - .navigationTitle("Wake Words") - .toolbar { EditButton() } - .onAppear { - if self.triggerWords.isEmpty { - self.triggerWords = VoiceWakePreferences.defaultTriggerWords - self.commitTriggerWords() - } - } - .onChange(of: self.focusedTriggerIndex) { oldValue, newValue in - guard oldValue != nil, oldValue != newValue else { return } - self.commitTriggerWords() - } - .onReceive(NotificationCenter.default.publisher(for: UserDefaults.didChangeNotification)) { _ in - guard self.focusedTriggerIndex == nil else { return } - let updated = VoiceWakePreferences.loadTriggerWords() - if updated != self.triggerWords { - self.triggerWords = updated - } - } - } - - private func addWord() { - self.triggerWords.append("") - } - - private func removeWords(at offsets: IndexSet) { - self.triggerWords.remove(atOffsets: offsets) - if self.triggerWords.isEmpty { - self.triggerWords = VoiceWakePreferences.defaultTriggerWords - } - self.commitTriggerWords() - } - - private func binding(for index: Int) -> Binding { - Binding( - get: { - guard self.triggerWords.indices.contains(index) else { return "" } - return self.triggerWords[index] - }, - set: { newValue in - guard self.triggerWords.indices.contains(index) else { return } - self.triggerWords[index] = newValue - }) - } - - private func commitTriggerWords() { - VoiceWakePreferences.saveTriggerWords(self.triggerWords) - - let snapshot = VoiceWakePreferences.sanitizeTriggerWords(self.triggerWords) - self.syncTask?.cancel() - self.syncTask = Task { [snapshot, weak appModel = self.appModel] in - try? await Task.sleep(nanoseconds: 650_000_000) - await appModel?.setGlobalWakeWords(snapshot) - } - } -} diff --git a/apps/ios/Sources/Status/StatusActivityBuilder.swift b/apps/ios/Sources/Status/StatusActivityBuilder.swift deleted file mode 100644 index 381b3d2b9e8..00000000000 --- a/apps/ios/Sources/Status/StatusActivityBuilder.swift +++ /dev/null @@ -1,71 +0,0 @@ -import SwiftUI - -enum StatusActivityBuilder { - @MainActor - static func build( - appModel: NodeAppModel, - voiceWakeEnabled: Bool, - cameraHUDText: String?, - cameraHUDKind: NodeAppModel.CameraHUDKind? - ) -> StatusPill.Activity? { - // Keep the top pill consistent across tabs (camera + voice wake + pairing states). - if appModel.isBackgrounded { - return StatusPill.Activity( - title: "Foreground required", - systemImage: "exclamationmark.triangle.fill", - tint: .orange) - } - - let gatewayStatus = appModel.gatewayStatusText.trimmingCharacters(in: .whitespacesAndNewlines) - let gatewayLower = gatewayStatus.lowercased() - if gatewayLower.contains("repair") { - return StatusPill.Activity(title: "Repairing…", systemImage: "wrench.and.screwdriver", tint: .orange) - } - if gatewayLower.contains("approval") || gatewayLower.contains("pairing") { - return StatusPill.Activity(title: "Approval pending", systemImage: "person.crop.circle.badge.clock") - } - // Avoid duplicating the primary gateway status ("Connecting…") in the activity slot. - - if appModel.screenRecordActive { - return StatusPill.Activity(title: "Recording screen…", systemImage: "record.circle.fill", tint: .red) - } - - if let cameraHUDText, !cameraHUDText.isEmpty, let cameraHUDKind { - let systemImage: String - let tint: Color? - switch cameraHUDKind { - case .photo: - systemImage = "camera.fill" - tint = nil - case .recording: - systemImage = "video.fill" - tint = .red - case .success: - systemImage = "checkmark.circle.fill" - tint = .green - case .error: - systemImage = "exclamationmark.triangle.fill" - tint = .red - } - return StatusPill.Activity(title: cameraHUDText, systemImage: systemImage, tint: tint) - } - - if voiceWakeEnabled { - let voiceStatus = appModel.voiceWake.statusText - if voiceStatus.localizedCaseInsensitiveContains("microphone permission") { - return StatusPill.Activity(title: "Mic permission", systemImage: "mic.slash", tint: .orange) - } - if voiceStatus == "Paused" { - // Talk mode intentionally pauses voice wake to release the mic. Don't spam the HUD for that case. - if appModel.talkMode.isEnabled { - return nil - } - let suffix = appModel.isBackgrounded ? " (background)" : "" - return StatusPill.Activity(title: "Voice Wake paused\(suffix)", systemImage: "pause.circle.fill") - } - } - - return nil - } -} - diff --git a/apps/ios/Sources/Status/StatusPill.swift b/apps/ios/Sources/Status/StatusPill.swift deleted file mode 100644 index ea5e425c49d..00000000000 --- a/apps/ios/Sources/Status/StatusPill.swift +++ /dev/null @@ -1,136 +0,0 @@ -import SwiftUI - -struct StatusPill: View { - @Environment(\.scenePhase) private var scenePhase - @Environment(\.accessibilityReduceMotion) private var reduceMotion - @Environment(\.colorSchemeContrast) private var contrast - - enum GatewayState: Equatable { - case connected - case connecting - case error - case disconnected - - var title: String { - switch self { - case .connected: "Connected" - case .connecting: "Connecting…" - case .error: "Error" - case .disconnected: "Offline" - } - } - - var color: Color { - switch self { - case .connected: .green - case .connecting: .yellow - case .error: .red - case .disconnected: .gray - } - } - } - - struct Activity: Equatable { - var title: String - var systemImage: String - var tint: Color? - } - - var gateway: GatewayState - var voiceWakeEnabled: Bool - var activity: Activity? - var brighten: Bool = false - var onTap: () -> Void - - @State private var pulse: Bool = false - - var body: some View { - Button(action: self.onTap) { - HStack(spacing: 10) { - HStack(spacing: 8) { - Circle() - .fill(self.gateway.color) - .frame(width: 9, height: 9) - .scaleEffect(self.gateway == .connecting && !self.reduceMotion ? (self.pulse ? 1.15 : 0.85) : 1.0) - .opacity(self.gateway == .connecting && !self.reduceMotion ? (self.pulse ? 1.0 : 0.6) : 1.0) - - Text(self.gateway.title) - .font(.subheadline.weight(.semibold)) - .foregroundStyle(.primary) - } - - Divider() - .frame(height: 14) - .opacity(0.35) - - if let activity { - HStack(spacing: 6) { - Image(systemName: activity.systemImage) - .font(.subheadline.weight(.semibold)) - .foregroundStyle(activity.tint ?? .primary) - Text(activity.title) - .font(.subheadline.weight(.semibold)) - .foregroundStyle(.primary) - .lineLimit(1) - } - .transition(.opacity.combined(with: .move(edge: .top))) - } else { - Image(systemName: self.voiceWakeEnabled ? "mic.fill" : "mic.slash") - .font(.subheadline.weight(.semibold)) - .foregroundStyle(self.voiceWakeEnabled ? .primary : .secondary) - .accessibilityLabel(self.voiceWakeEnabled ? "Voice Wake enabled" : "Voice Wake disabled") - .transition(.opacity.combined(with: .move(edge: .top))) - } - } - .padding(.vertical, 8) - .padding(.horizontal, 12) - .background { - RoundedRectangle(cornerRadius: 14, style: .continuous) - .fill(.ultraThinMaterial) - .overlay { - RoundedRectangle(cornerRadius: 14, style: .continuous) - .strokeBorder( - .white.opacity(self.contrast == .increased ? 0.5 : (self.brighten ? 0.24 : 0.18)), - lineWidth: self.contrast == .increased ? 1.0 : 0.5 - ) - } - .shadow(color: .black.opacity(0.25), radius: 12, y: 6) - } - } - .buttonStyle(.plain) - .accessibilityLabel("Connection Status") - .accessibilityValue(self.accessibilityValue) - .accessibilityHint("Double tap to open settings") - .onAppear { self.updatePulse(for: self.gateway, scenePhase: self.scenePhase, reduceMotion: self.reduceMotion) } - .onDisappear { self.pulse = false } - .onChange(of: self.gateway) { _, newValue in - self.updatePulse(for: newValue, scenePhase: self.scenePhase, reduceMotion: self.reduceMotion) - } - .onChange(of: self.scenePhase) { _, newValue in - self.updatePulse(for: self.gateway, scenePhase: newValue, reduceMotion: self.reduceMotion) - } - .onChange(of: self.reduceMotion) { _, newValue in - self.updatePulse(for: self.gateway, scenePhase: self.scenePhase, reduceMotion: newValue) - } - .animation(.easeInOut(duration: 0.18), value: self.activity?.title) - } - - private var accessibilityValue: String { - if let activity { - return "\(self.gateway.title), \(activity.title)" - } - return "\(self.gateway.title), Voice Wake \(self.voiceWakeEnabled ? "enabled" : "disabled")" - } - - private func updatePulse(for gateway: GatewayState, scenePhase: ScenePhase, reduceMotion: Bool) { - guard gateway == .connecting, scenePhase == .active, !reduceMotion else { - withAnimation(reduceMotion ? .none : .easeOut(duration: 0.2)) { self.pulse = false } - return - } - - guard !self.pulse else { return } - withAnimation(.easeInOut(duration: 0.9).repeatForever(autoreverses: true)) { - self.pulse = true - } - } -} diff --git a/apps/ios/Sources/Status/VoiceWakeToast.swift b/apps/ios/Sources/Status/VoiceWakeToast.swift deleted file mode 100644 index ef6fc1295a7..00000000000 --- a/apps/ios/Sources/Status/VoiceWakeToast.swift +++ /dev/null @@ -1,38 +0,0 @@ -import SwiftUI - -struct VoiceWakeToast: View { - @Environment(\.colorSchemeContrast) private var contrast - - var command: String - var brighten: Bool = false - - var body: some View { - HStack(spacing: 10) { - Image(systemName: "mic.fill") - .font(.subheadline.weight(.semibold)) - .foregroundStyle(.primary) - - Text(self.command) - .font(.subheadline.weight(.semibold)) - .foregroundStyle(.primary) - .lineLimit(1) - .truncationMode(.tail) - } - .padding(.vertical, 10) - .padding(.horizontal, 12) - .background { - RoundedRectangle(cornerRadius: 14, style: .continuous) - .fill(.ultraThinMaterial) - .overlay { - RoundedRectangle(cornerRadius: 14, style: .continuous) - .strokeBorder( - .white.opacity(self.contrast == .increased ? 0.5 : (self.brighten ? 0.24 : 0.18)), - lineWidth: self.contrast == .increased ? 1.0 : 0.5 - ) - } - .shadow(color: .black.opacity(0.25), radius: 12, y: 6) - } - .accessibilityLabel("Voice Wake triggered") - .accessibilityValue("Command: \(self.command)") - } -} diff --git a/apps/ios/Sources/Voice/TalkModeManager.swift b/apps/ios/Sources/Voice/TalkModeManager.swift deleted file mode 100644 index 8f208c66d50..00000000000 --- a/apps/ios/Sources/Voice/TalkModeManager.swift +++ /dev/null @@ -1,2089 +0,0 @@ -import AVFAudio -import OpenClawChatUI -import OpenClawKit -import OpenClawProtocol -import Foundation -import Observation -import OSLog -import Speech - -// This file intentionally centralizes talk mode state + behavior. -// It's large, and splitting would force `private` -> `fileprivate` across many members. -// We'll refactor into smaller files when the surface stabilizes. -// swiftlint:disable type_body_length -@MainActor -@Observable -final class TalkModeManager: NSObject { - private typealias SpeechRequest = SFSpeechAudioBufferRecognitionRequest - private static let defaultModelIdFallback = "eleven_v3" - private static let redactedConfigSentinel = "__OPENCLAW_REDACTED__" - var isEnabled: Bool = false - var isListening: Bool = false - var isSpeaking: Bool = false - var isPushToTalkActive: Bool = false - var statusText: String = "Off" - /// 0..1-ish (not calibrated). Intended for UI feedback only. - var micLevel: Double = 0 - var gatewayTalkConfigLoaded: Bool = false - var gatewayTalkApiKeyConfigured: Bool = false - var gatewayTalkDefaultModelId: String? - var gatewayTalkDefaultVoiceId: String? - - private enum CaptureMode { - case idle - case continuous - case pushToTalk - } - - private var captureMode: CaptureMode = .idle - private var resumeContinuousAfterPTT: Bool = false - private var activePTTCaptureId: String? - private var pttAutoStopEnabled: Bool = false - private var pttCompletion: CheckedContinuation? - private var pttTimeoutTask: Task? - - private let allowSimulatorCapture: Bool - - private let audioEngine = AVAudioEngine() - private var inputTapInstalled = false - private var audioTapDiagnostics: AudioTapDiagnostics? - private var speechRecognizer: SFSpeechRecognizer? - private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest? - private var recognitionTask: SFSpeechRecognitionTask? - private var silenceTask: Task? - - private var lastHeard: Date? - private var lastTranscript: String = "" - private var loggedPartialThisCycle: Bool = false - private var lastSpokenText: String? - private var lastInterruptedAtSeconds: Double? - - private var defaultVoiceId: String? - private var currentVoiceId: String? - private var defaultModelId: String? - private var currentModelId: String? - private var voiceOverrideActive = false - private var modelOverrideActive = false - private var defaultOutputFormat: String? - private var apiKey: String? - private var voiceAliases: [String: String] = [:] - private var interruptOnSpeech: Bool = true - private var mainSessionKey: String = "main" - private var fallbackVoiceId: String? - private var lastPlaybackWasPCM: Bool = false - var pcmPlayer: PCMStreamingAudioPlaying = PCMStreamingAudioPlayer.shared - var mp3Player: StreamingAudioPlaying = StreamingAudioPlayer.shared - - private var gateway: GatewayNodeSession? - private var gatewayConnected = false - private let silenceWindow: TimeInterval = 0.9 - private var lastAudioActivity: Date? - private var noiseFloorSamples: [Double] = [] - private var noiseFloor: Double? - private var noiseFloorReady: Bool = false - - private var chatSubscribedSessionKeys = Set() - private var incrementalSpeechQueue: [String] = [] - private var incrementalSpeechTask: Task? - private var incrementalSpeechActive = false - private var incrementalSpeechUsed = false - private var incrementalSpeechLanguage: String? - private var incrementalSpeechBuffer = IncrementalSpeechBuffer() - private var incrementalSpeechContext: IncrementalSpeechContext? - private var incrementalSpeechDirective: TalkDirective? - private var incrementalSpeechPrefetch: IncrementalSpeechPrefetchState? - private var incrementalSpeechPrefetchMonitorTask: Task? - - private let logger = Logger(subsystem: "bot.molt", category: "TalkMode") - - init(allowSimulatorCapture: Bool = false) { - self.allowSimulatorCapture = allowSimulatorCapture - super.init() - } - - func attachGateway(_ gateway: GatewayNodeSession) { - self.gateway = gateway - } - - func updateGatewayConnected(_ connected: Bool) { - self.gatewayConnected = connected - if connected { - // If talk mode is enabled before the gateway connects (common on cold start), - // kick recognition once we're online so the UI doesn’t stay “Offline”. - if self.isEnabled, !self.isListening, self.captureMode != .pushToTalk { - Task { await self.start() } - } - } else { - if self.isEnabled, !self.isSpeaking { - self.statusText = "Offline" - } - } - } - - func updateMainSessionKey(_ sessionKey: String?) { - let trimmed = (sessionKey ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return } - if trimmed == self.mainSessionKey { return } - self.mainSessionKey = trimmed - if self.gatewayConnected, self.isEnabled { - Task { await self.subscribeChatIfNeeded(sessionKey: trimmed) } - } - } - - func setEnabled(_ enabled: Bool) { - self.isEnabled = enabled - if enabled { - self.logger.info("enabled") - Task { await self.start() } - } else { - self.logger.info("disabled") - self.stop() - } - } - - func start() async { - guard self.isEnabled else { return } - guard self.captureMode != .pushToTalk else { return } - if self.isListening { return } - guard self.gatewayConnected else { - self.statusText = "Offline" - return - } - - self.logger.info("start") - self.statusText = "Requesting permissions…" - let micOk = await Self.requestMicrophonePermission() - guard micOk else { - self.logger.warning("start blocked: microphone permission denied") - self.statusText = Self.permissionMessage( - kind: "Microphone", - status: AVAudioSession.sharedInstance().recordPermission) - return - } - let speechOk = await Self.requestSpeechPermission() - guard speechOk else { - self.logger.warning("start blocked: speech permission denied") - self.statusText = Self.permissionMessage( - kind: "Speech recognition", - status: SFSpeechRecognizer.authorizationStatus()) - return - } - - await self.reloadConfig() - do { - try Self.configureAudioSession() - // Set this before starting recognition so any early speech errors are classified correctly. - self.captureMode = .continuous - try self.startRecognition() - self.isListening = true - self.statusText = "Listening" - self.startSilenceMonitor() - await self.subscribeChatIfNeeded(sessionKey: self.mainSessionKey) - self.logger.info("listening") - } catch { - self.isListening = false - self.statusText = "Start failed: \(error.localizedDescription)" - self.logger.error("start failed: \(error.localizedDescription, privacy: .public)") - } - } - - func stop() { - self.isEnabled = false - self.isListening = false - self.isPushToTalkActive = false - self.captureMode = .idle - self.statusText = "Off" - self.lastTranscript = "" - self.lastHeard = nil - self.silenceTask?.cancel() - self.silenceTask = nil - self.stopRecognition() - self.stopSpeaking() - self.lastInterruptedAtSeconds = nil - let pendingPTT = self.pttCompletion != nil - let pendingCaptureId = self.activePTTCaptureId ?? UUID().uuidString - self.pttTimeoutTask?.cancel() - self.pttTimeoutTask = nil - self.pttAutoStopEnabled = false - if pendingPTT { - let payload = OpenClawTalkPTTStopPayload( - captureId: pendingCaptureId, - transcript: nil, - status: "cancelled") - self.finishPTTOnce(payload) - } - self.resumeContinuousAfterPTT = false - self.activePTTCaptureId = nil - TalkSystemSpeechSynthesizer.shared.stop() - do { - try AVAudioSession.sharedInstance().setActive(false, options: [.notifyOthersOnDeactivation]) - } catch { - self.logger.warning("audio session deactivate failed: \(error.localizedDescription, privacy: .public)") - } - Task { await self.unsubscribeAllChats() } - } - - /// Suspends microphone usage without disabling Talk Mode. - /// Used when the app backgrounds (or when we need to temporarily release the mic). - func suspendForBackground(keepActive: Bool = false) -> Bool { - guard self.isEnabled else { return false } - if keepActive { - self.statusText = self.isListening ? "Listening" : self.statusText - return false - } - let wasActive = self.isListening || self.isSpeaking || self.isPushToTalkActive - - self.isListening = false - self.isPushToTalkActive = false - self.captureMode = .idle - self.statusText = "Paused" - self.lastTranscript = "" - self.lastHeard = nil - self.silenceTask?.cancel() - self.silenceTask = nil - - self.stopRecognition() - self.stopSpeaking() - self.lastInterruptedAtSeconds = nil - TalkSystemSpeechSynthesizer.shared.stop() - - do { - try AVAudioSession.sharedInstance().setActive(false, options: [.notifyOthersOnDeactivation]) - } catch { - self.logger.warning("audio session deactivate failed: \(error.localizedDescription, privacy: .public)") - } - - Task { await self.unsubscribeAllChats() } - return wasActive - } - - func resumeAfterBackground(wasSuspended: Bool, wasKeptActive: Bool = false) async { - if wasKeptActive { return } - guard wasSuspended else { return } - guard self.isEnabled else { return } - await self.start() - } - - func userTappedOrb() { - self.stopSpeaking() - } - - func beginPushToTalk() async throws -> OpenClawTalkPTTStartPayload { - guard self.gatewayConnected else { - self.statusText = "Offline" - throw NSError(domain: "TalkMode", code: 7, userInfo: [ - NSLocalizedDescriptionKey: "Gateway not connected", - ]) - } - if self.isPushToTalkActive, let captureId = self.activePTTCaptureId { - return OpenClawTalkPTTStartPayload(captureId: captureId) - } - - self.stopSpeaking(storeInterruption: false) - self.pttTimeoutTask?.cancel() - self.pttTimeoutTask = nil - self.pttAutoStopEnabled = false - - self.resumeContinuousAfterPTT = self.isEnabled && self.captureMode == .continuous - self.silenceTask?.cancel() - self.silenceTask = nil - self.stopRecognition() - self.isListening = false - - let captureId = UUID().uuidString - self.activePTTCaptureId = captureId - self.lastTranscript = "" - self.lastHeard = nil - - self.statusText = "Requesting permissions…" - if !self.allowSimulatorCapture { - let micOk = await Self.requestMicrophonePermission() - guard micOk else { - self.statusText = Self.permissionMessage( - kind: "Microphone", - status: AVAudioSession.sharedInstance().recordPermission) - throw NSError(domain: "TalkMode", code: 4, userInfo: [ - NSLocalizedDescriptionKey: "Microphone permission denied", - ]) - } - let speechOk = await Self.requestSpeechPermission() - guard speechOk else { - self.statusText = Self.permissionMessage( - kind: "Speech recognition", - status: SFSpeechRecognizer.authorizationStatus()) - throw NSError(domain: "TalkMode", code: 5, userInfo: [ - NSLocalizedDescriptionKey: "Speech recognition permission denied", - ]) - } - } - - do { - try Self.configureAudioSession() - self.captureMode = .pushToTalk - try self.startRecognition() - self.isListening = true - self.isPushToTalkActive = true - self.statusText = "Listening (PTT)" - } catch { - self.isListening = false - self.isPushToTalkActive = false - self.captureMode = .idle - self.statusText = "Start failed: \(error.localizedDescription)" - throw error - } - - return OpenClawTalkPTTStartPayload(captureId: captureId) - } - - func endPushToTalk() async -> OpenClawTalkPTTStopPayload { - let captureId = self.activePTTCaptureId ?? UUID().uuidString - guard self.isPushToTalkActive else { - let payload = OpenClawTalkPTTStopPayload( - captureId: captureId, - transcript: nil, - status: "idle") - self.finishPTTOnce(payload) - return payload - } - - self.isPushToTalkActive = false - self.isListening = false - self.captureMode = .idle - self.stopRecognition() - self.pttTimeoutTask?.cancel() - self.pttTimeoutTask = nil - self.pttAutoStopEnabled = false - - let transcript = self.lastTranscript.trimmingCharacters(in: .whitespacesAndNewlines) - self.lastTranscript = "" - self.lastHeard = nil - - guard !transcript.isEmpty else { - self.statusText = "Ready" - if self.resumeContinuousAfterPTT { - await self.start() - } - self.resumeContinuousAfterPTT = false - self.activePTTCaptureId = nil - let payload = OpenClawTalkPTTStopPayload( - captureId: captureId, - transcript: nil, - status: "empty") - self.finishPTTOnce(payload) - return payload - } - - guard self.gatewayConnected else { - self.statusText = "Gateway not connected" - if self.resumeContinuousAfterPTT { - await self.start() - } - self.resumeContinuousAfterPTT = false - self.activePTTCaptureId = nil - let payload = OpenClawTalkPTTStopPayload( - captureId: captureId, - transcript: transcript, - status: "offline") - self.finishPTTOnce(payload) - return payload - } - - self.statusText = "Thinking…" - Task { @MainActor in - await self.processTranscript(transcript, restartAfter: self.resumeContinuousAfterPTT) - } - self.resumeContinuousAfterPTT = false - self.activePTTCaptureId = nil - let payload = OpenClawTalkPTTStopPayload( - captureId: captureId, - transcript: transcript, - status: "queued") - self.finishPTTOnce(payload) - return payload - } - - func runPushToTalkOnce(maxDurationSeconds: TimeInterval = 12) async throws -> OpenClawTalkPTTStopPayload { - if self.pttCompletion != nil { - _ = await self.cancelPushToTalk() - } - - if self.isPushToTalkActive { - let captureId = self.activePTTCaptureId ?? UUID().uuidString - return OpenClawTalkPTTStopPayload( - captureId: captureId, - transcript: nil, - status: "busy") - } - - _ = try await self.beginPushToTalk() - - return await withCheckedContinuation { cont in - self.pttCompletion = cont - self.pttAutoStopEnabled = true - self.startSilenceMonitor() - self.schedulePTTTimeout(seconds: maxDurationSeconds) - } - } - - func cancelPushToTalk() async -> OpenClawTalkPTTStopPayload { - let captureId = self.activePTTCaptureId ?? UUID().uuidString - guard self.isPushToTalkActive else { - let payload = OpenClawTalkPTTStopPayload( - captureId: captureId, - transcript: nil, - status: "idle") - self.finishPTTOnce(payload) - self.pttAutoStopEnabled = false - self.pttTimeoutTask?.cancel() - self.pttTimeoutTask = nil - self.resumeContinuousAfterPTT = false - self.activePTTCaptureId = nil - return payload - } - - let shouldResume = self.resumeContinuousAfterPTT - self.isPushToTalkActive = false - self.isListening = false - self.captureMode = .idle - self.stopRecognition() - self.lastTranscript = "" - self.lastHeard = nil - self.pttAutoStopEnabled = false - self.pttTimeoutTask?.cancel() - self.pttTimeoutTask = nil - self.resumeContinuousAfterPTT = false - self.activePTTCaptureId = nil - self.statusText = "Ready" - - let payload = OpenClawTalkPTTStopPayload( - captureId: captureId, - transcript: nil, - status: "cancelled") - self.finishPTTOnce(payload) - - if shouldResume { - await self.start() - } - return payload - } - - private func startRecognition() throws { - #if targetEnvironment(simulator) - if !self.allowSimulatorCapture { - throw NSError(domain: "TalkMode", code: 2, userInfo: [ - NSLocalizedDescriptionKey: "Talk mode is not supported on the iOS simulator", - ]) - } else { - self.recognitionRequest = SFSpeechAudioBufferRecognitionRequest() - self.recognitionRequest?.shouldReportPartialResults = true - return - } - #endif - - self.stopRecognition() - self.speechRecognizer = SFSpeechRecognizer() - guard let recognizer = self.speechRecognizer else { - throw NSError(domain: "TalkMode", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "Speech recognizer unavailable", - ]) - } - - self.recognitionRequest = SFSpeechAudioBufferRecognitionRequest() - self.recognitionRequest?.shouldReportPartialResults = true - self.recognitionRequest?.taskHint = .dictation - guard let request = self.recognitionRequest else { return } - - GatewayDiagnostics.log("talk audio: session \(Self.describeAudioSession())") - - let input = self.audioEngine.inputNode - let format = input.inputFormat(forBus: 0) - guard format.sampleRate > 0, format.channelCount > 0 else { - throw NSError(domain: "TalkMode", code: 3, userInfo: [ - NSLocalizedDescriptionKey: "Invalid audio input format", - ]) - } - input.removeTap(onBus: 0) - let tapDiagnostics = AudioTapDiagnostics(label: "talk") { [weak self] level in - guard let self else { return } - Task { @MainActor in - // Smooth + clamp for UI, and keep it cheap. - let raw = max(0, min(Double(level) * 10.0, 1.0)) - let next = (self.micLevel * 0.80) + (raw * 0.20) - self.micLevel = next - - // Dynamic thresholding so background noise doesn’t prevent endpointing. - if self.isListening, !self.isSpeaking, !self.noiseFloorReady { - self.noiseFloorSamples.append(raw) - if self.noiseFloorSamples.count >= 22 { - let sorted = self.noiseFloorSamples.sorted() - let take = max(6, sorted.count / 2) - let slice = sorted.prefix(take) - let avg = slice.reduce(0.0, +) / Double(slice.count) - self.noiseFloor = avg - self.noiseFloorReady = true - self.noiseFloorSamples.removeAll(keepingCapacity: true) - let threshold = min(0.35, max(0.12, avg + 0.10)) - GatewayDiagnostics.log( - "talk audio: noiseFloor=\(String(format: "%.3f", avg)) threshold=\(String(format: "%.3f", threshold))") - } - } - - let threshold: Double = if let floor = self.noiseFloor, self.noiseFloorReady { - min(0.35, max(0.12, floor + 0.10)) - } else { - 0.18 - } - if raw >= threshold { - self.lastAudioActivity = Date() - } - } - } - self.audioTapDiagnostics = tapDiagnostics - let tapBlock = Self.makeAudioTapAppendCallback(request: request, diagnostics: tapDiagnostics) - input.installTap(onBus: 0, bufferSize: 2048, format: format, block: tapBlock) - self.inputTapInstalled = true - - self.audioEngine.prepare() - try self.audioEngine.start() - self.loggedPartialThisCycle = false - - GatewayDiagnostics.log( - "talk speech: recognition started mode=\(String(describing: self.captureMode)) engineRunning=\(self.audioEngine.isRunning)") - self.recognitionTask = recognizer.recognitionTask(with: request) { [weak self] result, error in - guard let self else { return } - if let error { - let msg = error.localizedDescription - let lowered = msg.lowercased() - let isCancellation = lowered.contains("cancelled") || lowered.contains("canceled") - if isCancellation { - GatewayDiagnostics.log("talk speech: cancelled") - if self.captureMode == .continuous, self.isEnabled, !self.isSpeaking { - self.statusText = "Listening" - } - self.logger.debug("speech recognition cancelled") - return - } - GatewayDiagnostics.log("talk speech: error=\(msg)") - if !self.isSpeaking { - if msg.localizedCaseInsensitiveContains("no speech detected") { - // Treat as transient silence. Don't scare users with an error banner. - self.statusText = self.isEnabled ? "Listening" : "Speech error: \(msg)" - } else { - self.statusText = "Speech error: \(msg)" - } - } - self.logger.debug("speech recognition error: \(msg, privacy: .public)") - // Speech recognition can terminate on transient errors (e.g. no speech detected). - // If talk mode is enabled and we're in continuous capture, try to restart. - if self.captureMode == .continuous, self.isEnabled, !self.isSpeaking { - // Treat the task as terminal on error so we don't get stuck with a dead recognizer. - self.stopRecognition() - Task { @MainActor [weak self] in - await self?.restartRecognitionAfterError() - } - } - } - guard let result else { return } - let transcript = result.bestTranscription.formattedString - if !result.isFinal, !self.loggedPartialThisCycle { - let trimmed = transcript.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmed.isEmpty { - self.loggedPartialThisCycle = true - GatewayDiagnostics.log("talk speech: partial chars=\(trimmed.count)") - } - } - Task { @MainActor in - await self.handleTranscript(transcript: transcript, isFinal: result.isFinal) - } - } - } - - private func restartRecognitionAfterError() async { - guard self.isEnabled, self.captureMode == .continuous else { return } - // Avoid thrashing the audio engine if it’s already running. - if self.recognitionTask != nil, self.audioEngine.isRunning { return } - try? await Task.sleep(nanoseconds: 250_000_000) - guard self.isEnabled, self.captureMode == .continuous else { return } - do { - try Self.configureAudioSession() - try self.startRecognition() - self.isListening = true - if self.statusText.localizedCaseInsensitiveContains("speech error") { - self.statusText = "Listening" - } - GatewayDiagnostics.log("talk speech: recognition restarted") - } catch { - let msg = error.localizedDescription - GatewayDiagnostics.log("talk speech: restart failed error=\(msg)") - } - } - - private func stopRecognition() { - self.recognitionTask?.cancel() - self.recognitionTask = nil - self.recognitionRequest?.endAudio() - self.recognitionRequest = nil - self.micLevel = 0 - self.lastAudioActivity = nil - self.noiseFloorSamples.removeAll(keepingCapacity: true) - self.noiseFloor = nil - self.noiseFloorReady = false - self.audioTapDiagnostics = nil - if self.inputTapInstalled { - self.audioEngine.inputNode.removeTap(onBus: 0) - self.inputTapInstalled = false - } - self.audioEngine.stop() - self.speechRecognizer = nil - } - - private nonisolated static func makeAudioTapAppendCallback( - request: SpeechRequest, - diagnostics: AudioTapDiagnostics) -> AVAudioNodeTapBlock - { - { buffer, _ in - request.append(buffer) - diagnostics.onBuffer(buffer) - } - } - - private func handleTranscript(transcript: String, isFinal: Bool) async { - let trimmed = transcript.trimmingCharacters(in: .whitespacesAndNewlines) - let ttsActive = self.isSpeechOutputActive - if ttsActive, self.interruptOnSpeech { - if self.shouldInterrupt(with: trimmed) { - self.stopSpeaking() - } - return - } - - guard self.isListening else { return } - if !trimmed.isEmpty { - self.lastTranscript = trimmed - self.lastHeard = Date() - } - if isFinal { - self.lastTranscript = trimmed - guard !trimmed.isEmpty else { return } - GatewayDiagnostics.log("talk speech: final transcript chars=\(trimmed.count)") - self.loggedPartialThisCycle = false - if self.captureMode == .pushToTalk, self.pttAutoStopEnabled, self.isPushToTalkActive { - _ = await self.endPushToTalk() - return - } - if self.captureMode == .continuous, !self.isSpeechOutputActive { - await self.processTranscript(trimmed, restartAfter: true) - } - } - } - - private func startSilenceMonitor() { - self.silenceTask?.cancel() - self.silenceTask = Task { [weak self] in - guard let self else { return } - while self.isEnabled || (self.isPushToTalkActive && self.pttAutoStopEnabled) { - try? await Task.sleep(nanoseconds: 200_000_000) - await self.checkSilence() - } - } - } - - private func checkSilence() async { - if self.captureMode == .continuous { - guard self.isListening, !self.isSpeechOutputActive else { return } - let transcript = self.lastTranscript.trimmingCharacters(in: .whitespacesAndNewlines) - guard !transcript.isEmpty else { return } - let lastActivity = [self.lastHeard, self.lastAudioActivity].compactMap { $0 }.max() - guard let lastActivity else { return } - if Date().timeIntervalSince(lastActivity) < self.silenceWindow { return } - await self.processTranscript(transcript, restartAfter: true) - return - } - - guard self.captureMode == .pushToTalk, self.pttAutoStopEnabled else { return } - guard self.isListening, !self.isSpeaking, self.isPushToTalkActive else { return } - let transcript = self.lastTranscript.trimmingCharacters(in: .whitespacesAndNewlines) - guard !transcript.isEmpty else { return } - let lastActivity = [self.lastHeard, self.lastAudioActivity].compactMap { $0 }.max() - guard let lastActivity else { return } - if Date().timeIntervalSince(lastActivity) < self.silenceWindow { return } - _ = await self.endPushToTalk() - } - - // Guardrail for PTT once so we don't stay open indefinitely. - private func schedulePTTTimeout(seconds: TimeInterval) { - guard seconds > 0 else { return } - let nanos = UInt64(seconds * 1_000_000_000) - self.pttTimeoutTask?.cancel() - self.pttTimeoutTask = Task { [weak self] in - try? await Task.sleep(nanoseconds: nanos) - await self?.handlePTTTimeout() - } - } - - private func handlePTTTimeout() async { - guard self.pttAutoStopEnabled, self.isPushToTalkActive else { return } - _ = await self.endPushToTalk() - } - - private func finishPTTOnce(_ payload: OpenClawTalkPTTStopPayload) { - guard let continuation = self.pttCompletion else { return } - self.pttCompletion = nil - continuation.resume(returning: payload) - } - - private func processTranscript(_ transcript: String, restartAfter: Bool) async { - self.isListening = false - self.captureMode = .idle - self.statusText = "Thinking…" - self.lastTranscript = "" - self.lastHeard = nil - self.stopRecognition() - - GatewayDiagnostics.log("talk: process transcript chars=\(transcript.count) restartAfter=\(restartAfter)") - await self.reloadConfig() - let prompt = self.buildPrompt(transcript: transcript) - guard self.gatewayConnected, let gateway else { - self.statusText = "Gateway not connected" - self.logger.warning("finalize: gateway not connected") - GatewayDiagnostics.log("talk: abort gateway not connected") - if restartAfter { - await self.start() - } - return - } - - do { - let startedAt = Date().timeIntervalSince1970 - let sessionKey = self.mainSessionKey - await self.subscribeChatIfNeeded(sessionKey: sessionKey) - self.logger.info( - "chat.send start sessionKey=\(sessionKey, privacy: .public) chars=\(prompt.count, privacy: .public)") - GatewayDiagnostics.log("talk: chat.send start sessionKey=\(sessionKey) chars=\(prompt.count)") - let runId = try await self.sendChat(prompt, gateway: gateway) - self.logger.info("chat.send ok runId=\(runId, privacy: .public)") - GatewayDiagnostics.log("talk: chat.send ok runId=\(runId)") - let shouldIncremental = self.shouldUseIncrementalTTS() - var streamingTask: Task? - if shouldIncremental { - self.resetIncrementalSpeech() - streamingTask = Task { @MainActor [weak self] in - guard let self else { return } - await self.streamAssistant(runId: runId, gateway: gateway) - } - } - let completion = await self.waitForChatCompletion(runId: runId, gateway: gateway, timeoutSeconds: 120) - if completion == .timeout { - self.logger.warning( - "chat completion timeout runId=\(runId, privacy: .public); attempting history fallback") - GatewayDiagnostics.log("talk: chat completion timeout runId=\(runId)") - } else if completion == .aborted { - self.statusText = "Aborted" - self.logger.warning("chat completion aborted runId=\(runId, privacy: .public)") - GatewayDiagnostics.log("talk: chat completion aborted runId=\(runId)") - streamingTask?.cancel() - await self.finishIncrementalSpeech() - await self.start() - return - } else if completion == .error { - self.statusText = "Chat error" - self.logger.warning("chat completion error runId=\(runId, privacy: .public)") - GatewayDiagnostics.log("talk: chat completion error runId=\(runId)") - streamingTask?.cancel() - await self.finishIncrementalSpeech() - await self.start() - return - } - - var assistantText = try await self.waitForAssistantText( - gateway: gateway, - since: startedAt, - timeoutSeconds: completion == .final ? 12 : 25) - if assistantText == nil, shouldIncremental { - let fallback = self.incrementalSpeechBuffer.latestText - if !fallback.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - assistantText = fallback - } - } - guard let assistantText else { - self.statusText = "No reply" - self.logger.warning("assistant text timeout runId=\(runId, privacy: .public)") - GatewayDiagnostics.log("talk: assistant text timeout runId=\(runId)") - streamingTask?.cancel() - await self.finishIncrementalSpeech() - await self.start() - return - } - self.logger.info("assistant text ok chars=\(assistantText.count, privacy: .public)") - GatewayDiagnostics.log("talk: assistant text ok chars=\(assistantText.count)") - streamingTask?.cancel() - if shouldIncremental { - await self.handleIncrementalAssistantFinal(text: assistantText) - } else { - await self.playAssistant(text: assistantText) - } - } catch { - self.statusText = "Talk failed: \(error.localizedDescription)" - self.logger.error("finalize failed: \(error.localizedDescription, privacy: .public)") - GatewayDiagnostics.log("talk: failed error=\(error.localizedDescription)") - } - - if restartAfter { - await self.start() - } - } - - private func subscribeChatIfNeeded(sessionKey: String) async { - let key = sessionKey.trimmingCharacters(in: .whitespacesAndNewlines) - guard !key.isEmpty else { return } - guard !self.chatSubscribedSessionKeys.contains(key) else { return } - - // Operator clients receive chat events without node-style subscriptions. - self.chatSubscribedSessionKeys.insert(key) - } - - private func unsubscribeAllChats() async { - self.chatSubscribedSessionKeys.removeAll() - } - - private func buildPrompt(transcript: String) -> String { - let interrupted = self.lastInterruptedAtSeconds - self.lastInterruptedAtSeconds = nil - let includeVoiceDirectiveHint = (UserDefaults.standard.object(forKey: "talk.voiceDirectiveHint.enabled") as? Bool) ?? true - return TalkPromptBuilder.build( - transcript: transcript, - interruptedAtSeconds: interrupted, - includeVoiceDirectiveHint: includeVoiceDirectiveHint) - } - - private enum ChatCompletionState: CustomStringConvertible { - case final - case aborted - case error - case timeout - - var description: String { - switch self { - case .final: "final" - case .aborted: "aborted" - case .error: "error" - case .timeout: "timeout" - } - } - } - - private func sendChat(_ message: String, gateway: GatewayNodeSession) async throws -> String { - struct SendResponse: Decodable { let runId: String } - let payload: [String: Any] = [ - "sessionKey": self.mainSessionKey, - "message": message, - "thinking": "low", - "timeoutMs": 30000, - "idempotencyKey": UUID().uuidString, - ] - let data = try JSONSerialization.data(withJSONObject: payload) - guard let json = String(bytes: data, encoding: .utf8) else { - throw NSError( - domain: "TalkModeManager", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "Failed to encode chat payload"]) - } - let res = try await gateway.request(method: "chat.send", paramsJSON: json, timeoutSeconds: 30) - let decoded = try JSONDecoder().decode(SendResponse.self, from: res) - return decoded.runId - } - - private func waitForChatCompletion( - runId: String, - gateway: GatewayNodeSession, - timeoutSeconds: Int = 120) async -> ChatCompletionState - { - let stream = await gateway.subscribeServerEvents(bufferingNewest: 200) - return await withTaskGroup(of: ChatCompletionState.self) { group in - group.addTask { [runId] in - for await evt in stream { - if Task.isCancelled { return .timeout } - guard evt.event == "chat", let payload = evt.payload else { continue } - guard let chatEvent = try? GatewayPayloadDecoding.decode(payload, as: ChatEvent.self) else { - continue - } - guard chatEvent.runid == runId else { continue } - if let state = chatEvent.state.value as? String { - switch state { - case "final": return .final - case "aborted": return .aborted - case "error": return .error - default: break - } - } - } - return .timeout - } - group.addTask { - try? await Task.sleep(nanoseconds: UInt64(timeoutSeconds) * 1_000_000_000) - return .timeout - } - let result = await group.next() ?? .timeout - group.cancelAll() - return result - } - } - - private func waitForAssistantText( - gateway: GatewayNodeSession, - since: Double, - timeoutSeconds: Int) async throws -> String? - { - let deadline = Date().addingTimeInterval(TimeInterval(timeoutSeconds)) - while Date() < deadline { - if let text = try await self.fetchLatestAssistantText(gateway: gateway, since: since) { - return text - } - try? await Task.sleep(nanoseconds: 300_000_000) - } - return nil - } - - private func fetchLatestAssistantText(gateway: GatewayNodeSession, since: Double? = nil) async throws -> String? { - let res = try await gateway.request( - method: "chat.history", - paramsJSON: "{\"sessionKey\":\"\(self.mainSessionKey)\"}", - timeoutSeconds: 15) - guard let json = try JSONSerialization.jsonObject(with: res) as? [String: Any] else { return nil } - guard let messages = json["messages"] as? [[String: Any]] else { return nil } - for msg in messages.reversed() { - guard (msg["role"] as? String) == "assistant" else { continue } - if let since, let timestamp = msg["timestamp"] as? Double, - TalkHistoryTimestamp.isAfter(timestamp, sinceSeconds: since) == false - { - continue - } - guard let content = msg["content"] as? [[String: Any]] else { continue } - let text = content.compactMap { $0["text"] as? String }.joined(separator: "\n") - let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmed.isEmpty { return trimmed } - } - return nil - } - - private func playAssistant(text: String) async { - let parsed = TalkDirectiveParser.parse(text) - let directive = parsed.directive - let cleaned = parsed.stripped.trimmingCharacters(in: .whitespacesAndNewlines) - guard !cleaned.isEmpty else { return } - self.applyDirective(directive) - - self.statusText = "Generating voice…" - self.isSpeaking = true - self.lastSpokenText = cleaned - - do { - let started = Date() - let language = ElevenLabsTTSClient.validatedLanguage(directive?.language) - let requestedVoice = directive?.voiceId?.trimmingCharacters(in: .whitespacesAndNewlines) - let resolvedVoice = self.resolveVoiceAlias(requestedVoice) - if requestedVoice?.isEmpty == false, resolvedVoice == nil { - self.logger.warning("unknown voice alias \(requestedVoice ?? "?", privacy: .public)") - } - - let resolvedKey = - (self.apiKey?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false ? self.apiKey : nil) ?? - ProcessInfo.processInfo.environment["ELEVENLABS_API_KEY"] - let apiKey = resolvedKey?.trimmingCharacters(in: .whitespacesAndNewlines) - let preferredVoice = resolvedVoice ?? self.currentVoiceId ?? self.defaultVoiceId - let voiceId: String? = if let apiKey, !apiKey.isEmpty { - await self.resolveVoiceId(preferred: preferredVoice, apiKey: apiKey) - } else { - nil - } - let canUseElevenLabs = (voiceId?.isEmpty == false) && (apiKey?.isEmpty == false) - - if canUseElevenLabs, let voiceId, let apiKey { - GatewayDiagnostics.log("talk tts: provider=elevenlabs voiceId=\(voiceId)") - let desiredOutputFormat = (directive?.outputFormat ?? self.defaultOutputFormat)? - .trimmingCharacters(in: .whitespacesAndNewlines) - let requestedOutputFormat = (desiredOutputFormat?.isEmpty == false) ? desiredOutputFormat : nil - let outputFormat = ElevenLabsTTSClient.validatedOutputFormat(requestedOutputFormat ?? "pcm_44100") - if outputFormat == nil, let requestedOutputFormat { - self.logger.warning( - "talk output_format unsupported for local playback: \(requestedOutputFormat, privacy: .public)") - } - - let modelId = directive?.modelId ?? self.currentModelId ?? self.defaultModelId - if let modelId { - GatewayDiagnostics.log("talk tts: modelId=\(modelId)") - } - func makeRequest(outputFormat: String?) -> ElevenLabsTTSRequest { - ElevenLabsTTSRequest( - text: cleaned, - modelId: modelId, - outputFormat: outputFormat, - speed: TalkTTSValidation.resolveSpeed(speed: directive?.speed, rateWPM: directive?.rateWPM), - stability: TalkTTSValidation.validatedStability(directive?.stability, modelId: modelId), - similarity: TalkTTSValidation.validatedUnit(directive?.similarity), - style: TalkTTSValidation.validatedUnit(directive?.style), - speakerBoost: directive?.speakerBoost, - seed: TalkTTSValidation.validatedSeed(directive?.seed), - normalize: ElevenLabsTTSClient.validatedNormalize(directive?.normalize), - language: language, - latencyTier: TalkTTSValidation.validatedLatencyTier(directive?.latencyTier)) - } - - let request = makeRequest(outputFormat: outputFormat) - - let client = ElevenLabsTTSClient(apiKey: apiKey) - let stream = client.streamSynthesize(voiceId: voiceId, request: request) - - if self.interruptOnSpeech { - do { - try self.startRecognition() - } catch { - self.logger.warning( - "startRecognition during speak failed: \(error.localizedDescription, privacy: .public)") - } - } - - self.statusText = "Speaking…" - let sampleRate = TalkTTSValidation.pcmSampleRate(from: outputFormat) - let result: StreamingPlaybackResult - if let sampleRate { - self.lastPlaybackWasPCM = true - var playback = await self.pcmPlayer.play(stream: stream, sampleRate: sampleRate) - if !playback.finished, playback.interruptedAt == nil { - let mp3Format = ElevenLabsTTSClient.validatedOutputFormat("mp3_44100") - self.logger.warning("pcm playback failed; retrying mp3") - self.lastPlaybackWasPCM = false - let mp3Stream = client.streamSynthesize( - voiceId: voiceId, - request: makeRequest(outputFormat: mp3Format)) - playback = await self.mp3Player.play(stream: mp3Stream) - } - result = playback - } else { - self.lastPlaybackWasPCM = false - result = await self.mp3Player.play(stream: stream) - } - let duration = Date().timeIntervalSince(started) - self.logger.info("elevenlabs stream finished=\(result.finished, privacy: .public) dur=\(duration, privacy: .public)s") - if !result.finished, let interruptedAt = result.interruptedAt { - self.lastInterruptedAtSeconds = interruptedAt - } - } else { - self.logger.warning("tts unavailable; falling back to system voice (missing key or voiceId)") - GatewayDiagnostics.log("talk tts: provider=system (missing key or voiceId)") - if self.interruptOnSpeech { - do { - try self.startRecognition() - } catch { - self.logger.warning( - "startRecognition during speak failed: \(error.localizedDescription, privacy: .public)") - } - } - self.statusText = "Speaking (System)…" - try await TalkSystemSpeechSynthesizer.shared.speak(text: cleaned, language: language) - } - } catch { - self.logger.error( - "tts failed: \(error.localizedDescription, privacy: .public); falling back to system voice") - GatewayDiagnostics.log("talk tts: provider=system (error) msg=\(error.localizedDescription)") - do { - if self.interruptOnSpeech { - do { - try self.startRecognition() - } catch { - self.logger.warning( - "startRecognition during speak failed: \(error.localizedDescription, privacy: .public)") - } - } - self.statusText = "Speaking (System)…" - let language = ElevenLabsTTSClient.validatedLanguage(directive?.language) - try await TalkSystemSpeechSynthesizer.shared.speak(text: cleaned, language: language) - } catch { - self.statusText = "Speak failed: \(error.localizedDescription)" - self.logger.error("system voice failed: \(error.localizedDescription, privacy: .public)") - } - } - - self.stopRecognition() - self.isSpeaking = false - } - - private func stopSpeaking(storeInterruption: Bool = true) { - let hasIncremental = self.incrementalSpeechActive || - self.incrementalSpeechTask != nil || - !self.incrementalSpeechQueue.isEmpty - if self.isSpeaking { - let interruptedAt = self.lastPlaybackWasPCM - ? self.pcmPlayer.stop() - : self.mp3Player.stop() - if storeInterruption { - self.lastInterruptedAtSeconds = interruptedAt - } - _ = self.lastPlaybackWasPCM - ? self.mp3Player.stop() - : self.pcmPlayer.stop() - } else if !hasIncremental { - return - } - TalkSystemSpeechSynthesizer.shared.stop() - self.cancelIncrementalSpeech() - self.isSpeaking = false - } - - private func shouldInterrupt(with transcript: String) -> Bool { - guard self.shouldAllowSpeechInterruptForCurrentRoute() else { return false } - let trimmed = transcript.trimmingCharacters(in: .whitespacesAndNewlines) - guard trimmed.count >= 3 else { return false } - if let spoken = self.lastSpokenText?.lowercased(), spoken.contains(trimmed.lowercased()) { - return false - } - return true - } - - private func shouldAllowSpeechInterruptForCurrentRoute() -> Bool { - let route = AVAudioSession.sharedInstance().currentRoute - // Built-in speaker/receiver often feeds TTS back into STT, causing false interrupts. - // Allow barge-in for isolated outputs (headphones/Bluetooth/USB/CarPlay/AirPlay). - return !route.outputs.contains { output in - switch output.portType { - case .builtInSpeaker, .builtInReceiver: - return true - default: - return false - } - } - } - - private func shouldUseIncrementalTTS() -> Bool { - true - } - - private var isSpeechOutputActive: Bool { - self.isSpeaking || - self.incrementalSpeechActive || - self.incrementalSpeechTask != nil || - !self.incrementalSpeechQueue.isEmpty - } - - private func applyDirective(_ directive: TalkDirective?) { - let requestedVoice = directive?.voiceId?.trimmingCharacters(in: .whitespacesAndNewlines) - let resolvedVoice = self.resolveVoiceAlias(requestedVoice) - if requestedVoice?.isEmpty == false, resolvedVoice == nil { - self.logger.warning("unknown voice alias \(requestedVoice ?? "?", privacy: .public)") - } - if let voice = resolvedVoice { - if directive?.once != true { - self.currentVoiceId = voice - self.voiceOverrideActive = true - } - } - if let model = directive?.modelId { - if directive?.once != true { - self.currentModelId = model - self.modelOverrideActive = true - } - } - } - - private func resetIncrementalSpeech() { - self.incrementalSpeechQueue.removeAll() - self.incrementalSpeechTask?.cancel() - self.incrementalSpeechTask = nil - self.cancelIncrementalPrefetch() - self.incrementalSpeechActive = true - self.incrementalSpeechUsed = false - self.incrementalSpeechLanguage = nil - self.incrementalSpeechBuffer = IncrementalSpeechBuffer() - self.incrementalSpeechContext = nil - self.incrementalSpeechDirective = nil - } - - private func cancelIncrementalSpeech() { - self.incrementalSpeechQueue.removeAll() - self.incrementalSpeechTask?.cancel() - self.incrementalSpeechTask = nil - self.cancelIncrementalPrefetch() - self.incrementalSpeechActive = false - self.incrementalSpeechContext = nil - self.incrementalSpeechDirective = nil - } - - private func enqueueIncrementalSpeech(_ text: String) { - let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return } - self.incrementalSpeechQueue.append(trimmed) - self.incrementalSpeechUsed = true - if self.incrementalSpeechTask == nil { - self.startIncrementalSpeechTask() - } - } - - private func startIncrementalSpeechTask() { - if self.interruptOnSpeech { - do { - try self.startRecognition() - } catch { - self.logger.warning( - "startRecognition during incremental speak failed: \(error.localizedDescription, privacy: .public)") - } - } - - self.incrementalSpeechTask = Task { @MainActor [weak self] in - guard let self else { return } - defer { - self.cancelIncrementalPrefetch() - self.isSpeaking = false - self.stopRecognition() - self.incrementalSpeechTask = nil - } - while !Task.isCancelled { - guard !self.incrementalSpeechQueue.isEmpty else { break } - let segment = self.incrementalSpeechQueue.removeFirst() - self.statusText = "Speaking…" - self.isSpeaking = true - self.lastSpokenText = segment - await self.updateIncrementalContextIfNeeded() - let context = self.incrementalSpeechContext - let prefetchedAudio = await self.consumeIncrementalPrefetchedAudioIfAvailable( - for: segment, - context: context) - if let context { - self.startIncrementalPrefetchMonitor(context: context) - } - await self.speakIncrementalSegment( - segment, - context: context, - prefetchedAudio: prefetchedAudio) - self.cancelIncrementalPrefetchMonitor() - } - } - } - - private func cancelIncrementalPrefetch() { - self.cancelIncrementalPrefetchMonitor() - self.incrementalSpeechPrefetch?.task.cancel() - self.incrementalSpeechPrefetch = nil - } - - private func cancelIncrementalPrefetchMonitor() { - self.incrementalSpeechPrefetchMonitorTask?.cancel() - self.incrementalSpeechPrefetchMonitorTask = nil - } - - private func startIncrementalPrefetchMonitor(context: IncrementalSpeechContext) { - self.cancelIncrementalPrefetchMonitor() - self.incrementalSpeechPrefetchMonitorTask = Task { @MainActor [weak self] in - guard let self else { return } - while !Task.isCancelled { - if self.ensureIncrementalPrefetchForUpcomingSegment(context: context) { - return - } - try? await Task.sleep(nanoseconds: 40_000_000) - } - } - } - - private func ensureIncrementalPrefetchForUpcomingSegment(context: IncrementalSpeechContext) -> Bool { - guard context.canUseElevenLabs else { - self.cancelIncrementalPrefetch() - return false - } - guard let nextSegment = self.incrementalSpeechQueue.first else { return false } - if let existing = self.incrementalSpeechPrefetch { - if existing.segment == nextSegment, existing.context == context { - return true - } - existing.task.cancel() - self.incrementalSpeechPrefetch = nil - } - self.startIncrementalPrefetch(segment: nextSegment, context: context) - return self.incrementalSpeechPrefetch != nil - } - - private func startIncrementalPrefetch(segment: String, context: IncrementalSpeechContext) { - guard context.canUseElevenLabs, let apiKey = context.apiKey, let voiceId = context.voiceId else { return } - let prefetchOutputFormat = self.resolveIncrementalPrefetchOutputFormat(context: context) - let request = self.makeIncrementalTTSRequest( - text: segment, - context: context, - outputFormat: prefetchOutputFormat) - let id = UUID() - let task = Task { [weak self] in - let stream = ElevenLabsTTSClient(apiKey: apiKey).streamSynthesize(voiceId: voiceId, request: request) - var chunks: [Data] = [] - do { - for try await chunk in stream { - try Task.checkCancellation() - chunks.append(chunk) - } - await self?.completeIncrementalPrefetch(id: id, chunks: chunks) - } catch is CancellationError { - await self?.clearIncrementalPrefetch(id: id) - } catch { - await self?.failIncrementalPrefetch(id: id, error: error) - } - } - self.incrementalSpeechPrefetch = IncrementalSpeechPrefetchState( - id: id, - segment: segment, - context: context, - outputFormat: prefetchOutputFormat, - chunks: nil, - task: task) - } - - private func completeIncrementalPrefetch(id: UUID, chunks: [Data]) { - guard var prefetch = self.incrementalSpeechPrefetch, prefetch.id == id else { return } - prefetch.chunks = chunks - self.incrementalSpeechPrefetch = prefetch - } - - private func clearIncrementalPrefetch(id: UUID) { - guard let prefetch = self.incrementalSpeechPrefetch, prefetch.id == id else { return } - prefetch.task.cancel() - self.incrementalSpeechPrefetch = nil - } - - private func failIncrementalPrefetch(id: UUID, error: any Error) { - guard let prefetch = self.incrementalSpeechPrefetch, prefetch.id == id else { return } - self.logger.debug("incremental prefetch failed: \(error.localizedDescription, privacy: .public)") - prefetch.task.cancel() - self.incrementalSpeechPrefetch = nil - } - - private func consumeIncrementalPrefetchedAudioIfAvailable( - for segment: String, - context: IncrementalSpeechContext? - ) async -> IncrementalPrefetchedAudio? - { - guard let context else { - self.cancelIncrementalPrefetch() - return nil - } - guard let prefetch = self.incrementalSpeechPrefetch else { - return nil - } - guard prefetch.context == context else { - prefetch.task.cancel() - self.incrementalSpeechPrefetch = nil - return nil - } - guard prefetch.segment == segment else { - return nil - } - if let chunks = prefetch.chunks, !chunks.isEmpty { - let prefetched = IncrementalPrefetchedAudio(chunks: chunks, outputFormat: prefetch.outputFormat) - self.incrementalSpeechPrefetch = nil - return prefetched - } - await prefetch.task.value - guard let completed = self.incrementalSpeechPrefetch else { return nil } - guard completed.context == context, completed.segment == segment else { return nil } - guard let chunks = completed.chunks, !chunks.isEmpty else { return nil } - let prefetched = IncrementalPrefetchedAudio(chunks: chunks, outputFormat: completed.outputFormat) - self.incrementalSpeechPrefetch = nil - return prefetched - } - - private func resolveIncrementalPrefetchOutputFormat(context: IncrementalSpeechContext) -> String? { - if TalkTTSValidation.pcmSampleRate(from: context.outputFormat) != nil { - return ElevenLabsTTSClient.validatedOutputFormat("mp3_44100") - } - return context.outputFormat - } - - private func finishIncrementalSpeech() async { - guard self.incrementalSpeechActive else { return } - let leftover = self.incrementalSpeechBuffer.flush() - if let leftover { - self.enqueueIncrementalSpeech(leftover) - } - if let task = self.incrementalSpeechTask { - _ = await task.result - } - self.incrementalSpeechActive = false - } - - private func handleIncrementalAssistantFinal(text: String) async { - let parsed = TalkDirectiveParser.parse(text) - self.applyDirective(parsed.directive) - if let lang = parsed.directive?.language { - self.incrementalSpeechLanguage = ElevenLabsTTSClient.validatedLanguage(lang) - } - await self.updateIncrementalContextIfNeeded() - let segments = self.incrementalSpeechBuffer.ingest(text: text, isFinal: true) - for segment in segments { - self.enqueueIncrementalSpeech(segment) - } - await self.finishIncrementalSpeech() - if !self.incrementalSpeechUsed { - await self.playAssistant(text: text) - } - } - - private func streamAssistant(runId: String, gateway: GatewayNodeSession) async { - let stream = await gateway.subscribeServerEvents(bufferingNewest: 200) - for await evt in stream { - if Task.isCancelled { return } - guard evt.event == "agent", let payload = evt.payload else { continue } - guard let agentEvent = try? GatewayPayloadDecoding.decode(payload, as: OpenClawAgentEventPayload.self) else { - continue - } - guard agentEvent.runId == runId, agentEvent.stream == "assistant" else { continue } - guard let text = agentEvent.data["text"]?.value as? String else { continue } - let segments = self.incrementalSpeechBuffer.ingest(text: text, isFinal: false) - if let lang = self.incrementalSpeechBuffer.directive?.language { - self.incrementalSpeechLanguage = ElevenLabsTTSClient.validatedLanguage(lang) - } - await self.updateIncrementalContextIfNeeded() - for segment in segments { - self.enqueueIncrementalSpeech(segment) - } - } - } - - private func updateIncrementalContextIfNeeded() async { - let directive = self.incrementalSpeechBuffer.directive - if let existing = self.incrementalSpeechContext, directive == self.incrementalSpeechDirective { - if existing.language != self.incrementalSpeechLanguage { - self.incrementalSpeechContext = IncrementalSpeechContext( - apiKey: existing.apiKey, - voiceId: existing.voiceId, - modelId: existing.modelId, - outputFormat: existing.outputFormat, - language: self.incrementalSpeechLanguage, - directive: existing.directive, - canUseElevenLabs: existing.canUseElevenLabs) - } - return - } - let context = await self.buildIncrementalSpeechContext(directive: directive) - self.incrementalSpeechContext = context - self.incrementalSpeechDirective = directive - } - - private func buildIncrementalSpeechContext(directive: TalkDirective?) async -> IncrementalSpeechContext { - let requestedVoice = directive?.voiceId?.trimmingCharacters(in: .whitespacesAndNewlines) - let resolvedVoice = self.resolveVoiceAlias(requestedVoice) - if requestedVoice?.isEmpty == false, resolvedVoice == nil { - self.logger.warning("unknown voice alias \(requestedVoice ?? "?", privacy: .public)") - } - let preferredVoice = resolvedVoice ?? self.currentVoiceId ?? self.defaultVoiceId - let modelId = directive?.modelId ?? self.currentModelId ?? self.defaultModelId - let desiredOutputFormat = (directive?.outputFormat ?? self.defaultOutputFormat)? - .trimmingCharacters(in: .whitespacesAndNewlines) - let requestedOutputFormat = (desiredOutputFormat?.isEmpty == false) ? desiredOutputFormat : nil - let outputFormat = ElevenLabsTTSClient.validatedOutputFormat(requestedOutputFormat ?? "pcm_44100") - if outputFormat == nil, let requestedOutputFormat { - self.logger.warning( - "talk output_format unsupported for local playback: \(requestedOutputFormat, privacy: .public)") - } - - let resolvedKey = - (self.apiKey?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false ? self.apiKey : nil) ?? - ProcessInfo.processInfo.environment["ELEVENLABS_API_KEY"] - let apiKey = resolvedKey?.trimmingCharacters(in: .whitespacesAndNewlines) - let voiceId: String? = if let apiKey, !apiKey.isEmpty { - await self.resolveVoiceId(preferred: preferredVoice, apiKey: apiKey) - } else { - nil - } - let canUseElevenLabs = (voiceId?.isEmpty == false) && (apiKey?.isEmpty == false) - return IncrementalSpeechContext( - apiKey: apiKey, - voiceId: voiceId, - modelId: modelId, - outputFormat: outputFormat, - language: self.incrementalSpeechLanguage, - directive: directive, - canUseElevenLabs: canUseElevenLabs) - } - - private func makeIncrementalTTSRequest( - text: String, - context: IncrementalSpeechContext, - outputFormat: String? - ) -> ElevenLabsTTSRequest - { - ElevenLabsTTSRequest( - text: text, - modelId: context.modelId, - outputFormat: outputFormat, - speed: TalkTTSValidation.resolveSpeed( - speed: context.directive?.speed, - rateWPM: context.directive?.rateWPM), - stability: TalkTTSValidation.validatedStability( - context.directive?.stability, - modelId: context.modelId), - similarity: TalkTTSValidation.validatedUnit(context.directive?.similarity), - style: TalkTTSValidation.validatedUnit(context.directive?.style), - speakerBoost: context.directive?.speakerBoost, - seed: TalkTTSValidation.validatedSeed(context.directive?.seed), - normalize: ElevenLabsTTSClient.validatedNormalize(context.directive?.normalize), - language: context.language, - latencyTier: TalkTTSValidation.validatedLatencyTier(context.directive?.latencyTier)) - } - - private static func makeBufferedAudioStream(chunks: [Data]) -> AsyncThrowingStream { - AsyncThrowingStream { continuation in - for chunk in chunks { - continuation.yield(chunk) - } - continuation.finish() - } - } - - private func speakIncrementalSegment( - _ text: String, - context preferredContext: IncrementalSpeechContext? = nil, - prefetchedAudio: IncrementalPrefetchedAudio? = nil - ) async - { - let context: IncrementalSpeechContext - if let preferredContext { - context = preferredContext - } else { - await self.updateIncrementalContextIfNeeded() - guard let resolvedContext = self.incrementalSpeechContext else { - try? await TalkSystemSpeechSynthesizer.shared.speak( - text: text, - language: self.incrementalSpeechLanguage) - return - } - context = resolvedContext - } - - guard context.canUseElevenLabs, let apiKey = context.apiKey, let voiceId = context.voiceId else { - try? await TalkSystemSpeechSynthesizer.shared.speak( - text: text, - language: self.incrementalSpeechLanguage) - return - } - - let client = ElevenLabsTTSClient(apiKey: apiKey) - let request = self.makeIncrementalTTSRequest( - text: text, - context: context, - outputFormat: context.outputFormat) - let stream: AsyncThrowingStream - if let prefetchedAudio, !prefetchedAudio.chunks.isEmpty { - stream = Self.makeBufferedAudioStream(chunks: prefetchedAudio.chunks) - } else { - stream = client.streamSynthesize(voiceId: voiceId, request: request) - } - let playbackFormat = prefetchedAudio?.outputFormat ?? context.outputFormat - let sampleRate = TalkTTSValidation.pcmSampleRate(from: playbackFormat) - let result: StreamingPlaybackResult - if let sampleRate { - self.lastPlaybackWasPCM = true - var playback = await self.pcmPlayer.play(stream: stream, sampleRate: sampleRate) - if !playback.finished, playback.interruptedAt == nil { - self.logger.warning("pcm playback failed; retrying mp3") - self.lastPlaybackWasPCM = false - let mp3Format = ElevenLabsTTSClient.validatedOutputFormat("mp3_44100") - let mp3Stream = client.streamSynthesize( - voiceId: voiceId, - request: self.makeIncrementalTTSRequest( - text: text, - context: context, - outputFormat: mp3Format)) - playback = await self.mp3Player.play(stream: mp3Stream) - } - result = playback - } else { - self.lastPlaybackWasPCM = false - result = await self.mp3Player.play(stream: stream) - } - if !result.finished, let interruptedAt = result.interruptedAt { - self.lastInterruptedAtSeconds = interruptedAt - } - } - -} - -private struct IncrementalSpeechBuffer { - private(set) var latestText: String = "" - private(set) var directive: TalkDirective? - private var spokenOffset: Int = 0 - private var inCodeBlock = false - private var directiveParsed = false - - mutating func ingest(text: String, isFinal: Bool) -> [String] { - let normalized = text.replacingOccurrences(of: "\r\n", with: "\n") - guard let usable = self.stripDirectiveIfReady(from: normalized) else { return [] } - self.updateText(usable) - return self.extractSegments(isFinal: isFinal) - } - - mutating func flush() -> String? { - guard !self.latestText.isEmpty else { return nil } - let segments = self.extractSegments(isFinal: true) - return segments.first - } - - private mutating func stripDirectiveIfReady(from text: String) -> String? { - guard !self.directiveParsed else { return text } - let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - if trimmed.hasPrefix("{") { - guard let newlineRange = text.range(of: "\n") else { return nil } - let firstLine = text[.. commonPrefix { - self.spokenOffset = commonPrefix - } - } - if self.spokenOffset > self.latestText.count { - self.spokenOffset = self.latestText.count - } - } - - private static func commonPrefixCount(_ lhs: String, _ rhs: String) -> Int { - let left = Array(lhs) - let right = Array(rhs) - let limit = min(left.count, right.count) - var idx = 0 - while idx < limit, left[idx] == right[idx] { - idx += 1 - } - return idx - } - - private mutating func extractSegments(isFinal: Bool) -> [String] { - let chars = Array(self.latestText) - guard self.spokenOffset < chars.count else { return [] } - var idx = self.spokenOffset - var lastBoundary: Int? - var inCodeBlock = self.inCodeBlock - var buffer = "" - var bufferAtBoundary = "" - var inCodeBlockAtBoundary = inCodeBlock - - while idx < chars.count { - if idx + 2 < chars.count, - chars[idx] == "`", - chars[idx + 1] == "`", - chars[idx + 2] == "`" - { - inCodeBlock.toggle() - idx += 3 - continue - } - - if !inCodeBlock { - buffer.append(chars[idx]) - if Self.isBoundary(chars[idx]) { - lastBoundary = idx + 1 - bufferAtBoundary = buffer - inCodeBlockAtBoundary = inCodeBlock - } - } - - idx += 1 - } - - if let boundary = lastBoundary { - self.spokenOffset = boundary - self.inCodeBlock = inCodeBlockAtBoundary - let trimmed = bufferAtBoundary.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed.isEmpty ? [] : [trimmed] - } - - guard isFinal else { return [] } - self.spokenOffset = chars.count - self.inCodeBlock = inCodeBlock - let trimmed = buffer.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed.isEmpty ? [] : [trimmed] - } - - private static func isBoundary(_ ch: Character) -> Bool { - ch == "." || ch == "!" || ch == "?" || ch == "\n" - } -} - -extension TalkModeManager { - nonisolated static func requestMicrophonePermission() async -> Bool { - let session = AVAudioSession.sharedInstance() - switch session.recordPermission { - case .granted: - return true - case .denied: - return false - case .undetermined: - break - @unknown default: - return false - } - - return await self.requestPermissionWithTimeout { completion in - AVAudioSession.sharedInstance().requestRecordPermission { ok in - completion(ok) - } - } - } - - nonisolated static func requestSpeechPermission() async -> Bool { - let status = SFSpeechRecognizer.authorizationStatus() - switch status { - case .authorized: - return true - case .denied, .restricted: - return false - case .notDetermined: - break - @unknown default: - return false - } - - return await self.requestPermissionWithTimeout { completion in - SFSpeechRecognizer.requestAuthorization { authStatus in - completion(authStatus == .authorized) - } - } - } - - private nonisolated static func requestPermissionWithTimeout( - _ operation: @escaping @Sendable (@escaping (Bool) -> Void) -> Void) async -> Bool - { - do { - return try await AsyncTimeout.withTimeout( - seconds: 8, - onTimeout: { NSError(domain: "TalkMode", code: 6, userInfo: [ - NSLocalizedDescriptionKey: "permission request timed out", - ]) }, - operation: { - await withCheckedContinuation(isolation: nil) { cont in - Task { @MainActor in - operation { ok in - cont.resume(returning: ok) - } - } - } - }) - } catch { - return false - } - } - - static func permissionMessage( - kind: String, - status: AVAudioSession.RecordPermission) -> String - { - switch status { - case .denied: - return "\(kind) permission denied" - case .undetermined: - return "\(kind) permission not granted" - case .granted: - return "\(kind) permission denied" - @unknown default: - return "\(kind) permission denied" - } - } - - static func permissionMessage( - kind: String, - status: SFSpeechRecognizerAuthorizationStatus) -> String - { - switch status { - case .denied: - return "\(kind) permission denied" - case .restricted: - return "\(kind) permission restricted" - case .notDetermined: - return "\(kind) permission not granted" - case .authorized: - return "\(kind) permission denied" - @unknown default: - return "\(kind) permission denied" - } - } -} - -extension TalkModeManager { - func resolveVoiceAlias(_ value: String?) -> String? { - let trimmed = (value ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - let normalized = trimmed.lowercased() - if let mapped = self.voiceAliases[normalized] { return mapped } - if self.voiceAliases.values.contains(where: { $0.caseInsensitiveCompare(trimmed) == .orderedSame }) { - return trimmed - } - return Self.isLikelyVoiceId(trimmed) ? trimmed : nil - } - - func resolveVoiceId(preferred: String?, apiKey: String) async -> String? { - let trimmed = preferred?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if !trimmed.isEmpty { - // Config / directives can provide a raw ElevenLabs voiceId (not an alias). - // Accept it directly to avoid unnecessary listVoices calls (and accidental fallback selection). - if Self.isLikelyVoiceId(trimmed) { - return trimmed - } - if let resolved = self.resolveVoiceAlias(trimmed) { return resolved } - self.logger.warning("unknown voice alias \(trimmed, privacy: .public)") - } - if let fallbackVoiceId { return fallbackVoiceId } - - do { - let voices = try await ElevenLabsTTSClient(apiKey: apiKey).listVoices() - guard let first = voices.first else { - self.logger.warning("elevenlabs voices list empty") - return nil - } - self.fallbackVoiceId = first.voiceId - if self.defaultVoiceId == nil { - self.defaultVoiceId = first.voiceId - } - if !self.voiceOverrideActive { - self.currentVoiceId = first.voiceId - } - let name = first.name ?? "unknown" - self.logger - .info("default voice selected \(name, privacy: .public) (\(first.voiceId, privacy: .public))") - return first.voiceId - } catch { - self.logger.error("elevenlabs list voices failed: \(error.localizedDescription, privacy: .public)") - return nil - } - } - - static func isLikelyVoiceId(_ value: String) -> Bool { - guard value.count >= 10 else { return false } - return value.allSatisfy { $0.isLetter || $0.isNumber || $0 == "-" || $0 == "_" } - } - - private static func normalizedTalkApiKey(_ raw: String?) -> String? { - let trimmed = (raw ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - guard trimmed != Self.redactedConfigSentinel else { return nil } - // Config values may be env placeholders (for example `${ELEVENLABS_API_KEY}`). - if trimmed.hasPrefix("${"), trimmed.hasSuffix("}") { return nil } - return trimmed - } - - func reloadConfig() async { - guard let gateway else { return } - do { - let res = try await gateway.request(method: "talk.config", paramsJSON: "{\"includeSecrets\":true}", timeoutSeconds: 8) - guard let json = try JSONSerialization.jsonObject(with: res) as? [String: Any] else { return } - guard let config = json["config"] as? [String: Any] else { return } - let talk = config["talk"] as? [String: Any] - self.defaultVoiceId = (talk?["voiceId"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) - if let aliases = talk?["voiceAliases"] as? [String: Any] { - var resolved: [String: String] = [:] - for (key, value) in aliases { - guard let id = value as? String else { continue } - let normalizedKey = key.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - let trimmedId = id.trimmingCharacters(in: .whitespacesAndNewlines) - guard !normalizedKey.isEmpty, !trimmedId.isEmpty else { continue } - resolved[normalizedKey] = trimmedId - } - self.voiceAliases = resolved - } else { - self.voiceAliases = [:] - } - if !self.voiceOverrideActive { - self.currentVoiceId = self.defaultVoiceId - } - let model = (talk?["modelId"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) - self.defaultModelId = (model?.isEmpty == false) ? model : Self.defaultModelIdFallback - if !self.modelOverrideActive { - self.currentModelId = self.defaultModelId - } - self.defaultOutputFormat = (talk?["outputFormat"] as? String)? - .trimmingCharacters(in: .whitespacesAndNewlines) - let rawConfigApiKey = (talk?["apiKey"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) - let configApiKey = Self.normalizedTalkApiKey(rawConfigApiKey) - let localApiKey = Self.normalizedTalkApiKey(GatewaySettingsStore.loadTalkElevenLabsApiKey()) - if rawConfigApiKey == Self.redactedConfigSentinel { - self.apiKey = (localApiKey?.isEmpty == false) ? localApiKey : nil - GatewayDiagnostics.log("talk config apiKey redacted; using local override if present") - } else { - self.apiKey = (localApiKey?.isEmpty == false) ? localApiKey : configApiKey - } - self.gatewayTalkDefaultVoiceId = self.defaultVoiceId - self.gatewayTalkDefaultModelId = self.defaultModelId - self.gatewayTalkApiKeyConfigured = (self.apiKey?.isEmpty == false) - self.gatewayTalkConfigLoaded = true - if let interrupt = talk?["interruptOnSpeech"] as? Bool { - self.interruptOnSpeech = interrupt - } - } catch { - self.defaultModelId = Self.defaultModelIdFallback - if !self.modelOverrideActive { - self.currentModelId = self.defaultModelId - } - self.gatewayTalkDefaultVoiceId = nil - self.gatewayTalkDefaultModelId = nil - self.gatewayTalkApiKeyConfigured = false - self.gatewayTalkConfigLoaded = false - } - } - - static func configureAudioSession() throws { - let session = AVAudioSession.sharedInstance() - // Prefer `.spokenAudio` for STT; it tends to preserve speech energy better than `.voiceChat`. - try session.setCategory(.playAndRecord, mode: .spokenAudio, options: [ - .allowBluetoothHFP, - .defaultToSpeaker, - ]) - try? session.setPreferredSampleRate(48_000) - try? session.setPreferredIOBufferDuration(0.02) - try session.setActive(true, options: []) - } - - private static func describeAudioSession() -> String { - let session = AVAudioSession.sharedInstance() - let inputs = session.currentRoute.inputs.map { "\($0.portType.rawValue):\($0.portName)" }.joined(separator: ",") - let outputs = session.currentRoute.outputs.map { "\($0.portType.rawValue):\($0.portName)" }.joined(separator: ",") - let available = session.availableInputs?.map { "\($0.portType.rawValue):\($0.portName)" }.joined(separator: ",") ?? "" - return "category=\(session.category.rawValue) mode=\(session.mode.rawValue) opts=\(session.categoryOptions.rawValue) inputAvail=\(session.isInputAvailable) routeIn=[\(inputs)] routeOut=[\(outputs)] availIn=[\(available)]" - } -} - -private final class AudioTapDiagnostics: @unchecked Sendable { - private let label: String - private let onLevel: (@Sendable (Float) -> Void)? - private let lock = NSLock() - private var bufferCount: Int = 0 - private var lastLoggedAt = Date.distantPast - private var lastLevelEmitAt = Date.distantPast - private var maxRmsWindow: Float = 0 - private var lastRms: Float = 0 - - init(label: String, onLevel: (@Sendable (Float) -> Void)? = nil) { - self.label = label - self.onLevel = onLevel - } - - func onBuffer(_ buffer: AVAudioPCMBuffer) { - var shouldLog = false - var shouldEmitLevel = false - var count = 0 - lock.lock() - bufferCount += 1 - count = bufferCount - let now = Date() - if now.timeIntervalSince(lastLoggedAt) >= 1.0 { - lastLoggedAt = now - shouldLog = true - } - if now.timeIntervalSince(lastLevelEmitAt) >= 0.12 { - lastLevelEmitAt = now - shouldEmitLevel = true - } - lock.unlock() - - let rate = buffer.format.sampleRate - let ch = buffer.format.channelCount - let frames = buffer.frameLength - - var rms: Float? - if let data = buffer.floatChannelData?.pointee { - let n = Int(frames) - if n > 0 { - var sum: Float = 0 - for i in 0.. maxRmsWindow { maxRmsWindow = resolvedRms } - let maxRms = maxRmsWindow - if shouldLog { maxRmsWindow = 0 } - lock.unlock() - - if shouldEmitLevel, let onLevel { - onLevel(resolvedRms) - } - - guard shouldLog else { return } - GatewayDiagnostics.log( - "\(label) mic: buffers=\(count) frames=\(frames) rate=\(Int(rate))Hz ch=\(ch) rms=\(String(format: "%.4f", resolvedRms)) max=\(String(format: "%.4f", maxRms))") - } -} - -#if DEBUG -extension TalkModeManager { - func _test_seedTranscript(_ transcript: String) { - self.lastTranscript = transcript - self.lastHeard = Date() - } - - func _test_handleTranscript(_ transcript: String, isFinal: Bool) async { - await self.handleTranscript(transcript: transcript, isFinal: isFinal) - } - - func _test_backdateLastHeard(seconds: TimeInterval) { - self.lastHeard = Date().addingTimeInterval(-seconds) - } - - func _test_runSilenceCheck() async { - await self.checkSilence() - } - - func _test_incrementalReset() { - self.incrementalSpeechBuffer = IncrementalSpeechBuffer() - } - - func _test_incrementalIngest(_ text: String, isFinal: Bool) -> [String] { - self.incrementalSpeechBuffer.ingest(text: text, isFinal: isFinal) - } -} -#endif - -private struct IncrementalSpeechContext: Equatable { - let apiKey: String? - let voiceId: String? - let modelId: String? - let outputFormat: String? - let language: String? - let directive: TalkDirective? - let canUseElevenLabs: Bool -} - -private struct IncrementalSpeechPrefetchState { - let id: UUID - let segment: String - let context: IncrementalSpeechContext - let outputFormat: String? - var chunks: [Data]? - let task: Task -} - -private struct IncrementalPrefetchedAudio { - let chunks: [Data] - let outputFormat: String? -} - -// swiftlint:enable type_body_length diff --git a/apps/ios/Sources/Voice/TalkOrbOverlay.swift b/apps/ios/Sources/Voice/TalkOrbOverlay.swift deleted file mode 100644 index f24cab5aedb..00000000000 --- a/apps/ios/Sources/Voice/TalkOrbOverlay.swift +++ /dev/null @@ -1,87 +0,0 @@ -import SwiftUI - -struct TalkOrbOverlay: View { - @Environment(NodeAppModel.self) private var appModel - @State private var pulse: Bool = false - - var body: some View { - let seam = self.appModel.seamColor - let status = self.appModel.talkMode.statusText.trimmingCharacters(in: .whitespacesAndNewlines) - let mic = min(max(self.appModel.talkMode.micLevel, 0), 1) - - VStack(spacing: 14) { - ZStack { - Circle() - .stroke(seam.opacity(0.26), lineWidth: 2) - .frame(width: 320, height: 320) - .scaleEffect(self.pulse ? 1.15 : 0.96) - .opacity(self.pulse ? 0.0 : 1.0) - .animation(.easeOut(duration: 1.3).repeatForever(autoreverses: false), value: self.pulse) - - Circle() - .stroke(seam.opacity(0.18), lineWidth: 2) - .frame(width: 320, height: 320) - .scaleEffect(self.pulse ? 1.45 : 1.02) - .opacity(self.pulse ? 0.0 : 0.9) - .animation(.easeOut(duration: 1.9).repeatForever(autoreverses: false).delay(0.2), value: self.pulse) - - Circle() - .fill( - RadialGradient( - colors: [ - seam.opacity(0.75 + (0.20 * mic)), - seam.opacity(0.40), - Color.black.opacity(0.55), - ], - center: .center, - startRadius: 1, - endRadius: 112)) - .frame(width: 190, height: 190) - .scaleEffect(1.0 + (0.12 * mic)) - .overlay( - Circle() - .stroke(seam.opacity(0.35), lineWidth: 1)) - .shadow(color: seam.opacity(0.32), radius: 26, x: 0, y: 0) - .shadow(color: Color.black.opacity(0.50), radius: 22, x: 0, y: 10) - } - .contentShape(Circle()) - .onTapGesture { - self.appModel.talkMode.userTappedOrb() - } - - let agentName = self.appModel.activeAgentName.trimmingCharacters(in: .whitespacesAndNewlines) - if !agentName.isEmpty { - Text("Bot: \(agentName)") - .font(.system(.caption, design: .rounded).weight(.semibold)) - .foregroundStyle(Color.white.opacity(0.70)) - } - - if !status.isEmpty, status != "Off" { - Text(status) - .font(.system(.footnote, design: .rounded).weight(.semibold)) - .foregroundStyle(Color.white.opacity(0.92)) - .padding(.horizontal, 12) - .padding(.vertical, 8) - .background( - Capsule() - .fill(Color.black.opacity(0.40)) - .overlay( - Capsule().stroke(seam.opacity(0.22), lineWidth: 1))) - } - - if self.appModel.talkMode.isListening { - Capsule() - .fill(seam.opacity(0.90)) - .frame(width: max(18, 180 * mic), height: 6) - .animation(.easeOut(duration: 0.12), value: mic) - .accessibilityLabel("Microphone level") - } - } - .padding(28) - .onAppear { - self.pulse = true - } - .accessibilityElement(children: .combine) - .accessibilityLabel("Talk Mode \(status)") - } -} diff --git a/apps/ios/Sources/Voice/VoiceTab.swift b/apps/ios/Sources/Voice/VoiceTab.swift deleted file mode 100644 index 4fedd0ce9aa..00000000000 --- a/apps/ios/Sources/Voice/VoiceTab.swift +++ /dev/null @@ -1,46 +0,0 @@ -import SwiftUI - -struct VoiceTab: View { - @Environment(NodeAppModel.self) private var appModel - @Environment(VoiceWakeManager.self) private var voiceWake - @AppStorage("voiceWake.enabled") private var voiceWakeEnabled: Bool = false - @AppStorage("talk.enabled") private var talkEnabled: Bool = false - - var body: some View { - NavigationStack { - List { - Section("Status") { - LabeledContent("Voice Wake", value: self.voiceWakeEnabled ? "Enabled" : "Disabled") - LabeledContent("Listener", value: self.voiceWake.isListening ? "Listening" : "Idle") - Text(self.voiceWake.statusText) - .font(.footnote) - .foregroundStyle(.secondary) - LabeledContent("Talk Mode", value: self.talkEnabled ? "Enabled" : "Disabled") - } - - Section("Notes") { - let triggers = self.voiceWake.activeTriggerWords - Group { - if triggers.isEmpty { - Text("Add wake words in Settings.") - } else if triggers.count == 1 { - Text("Say “\(triggers[0]) …” to trigger.") - } else if triggers.count == 2 { - Text("Say “\(triggers[0]) …” or “\(triggers[1]) …” to trigger.") - } else { - Text("Say “\(triggers.joined(separator: " …”, “")) …” to trigger.") - } - } - .foregroundStyle(.secondary) - } - } - .navigationTitle("Voice") - .onChange(of: self.voiceWakeEnabled) { _, newValue in - self.appModel.setVoiceWakeEnabled(newValue) - } - .onChange(of: self.talkEnabled) { _, newValue in - self.appModel.setTalkEnabled(newValue) - } - } - } -} diff --git a/apps/ios/Sources/Voice/VoiceWakeManager.swift b/apps/ios/Sources/Voice/VoiceWakeManager.swift deleted file mode 100644 index 15a993feaa0..00000000000 --- a/apps/ios/Sources/Voice/VoiceWakeManager.swift +++ /dev/null @@ -1,495 +0,0 @@ -import AVFAudio -import Foundation -import Observation -import OpenClawKit -import Speech -import SwabbleKit - -private func makeAudioTapEnqueueCallback(queue: AudioBufferQueue) -> @Sendable (AVAudioPCMBuffer, AVAudioTime) -> Void { - { buffer, _ in - // This callback is invoked on a realtime audio thread/queue. Keep it tiny and nonisolated. - queue.enqueueCopy(of: buffer) - } -} - -private final class AudioBufferQueue: @unchecked Sendable { - private let lock = NSLock() - private var buffers: [AVAudioPCMBuffer] = [] - - func enqueueCopy(of buffer: AVAudioPCMBuffer) { - guard let copy = buffer.deepCopy() else { return } - self.lock.lock() - self.buffers.append(copy) - self.lock.unlock() - } - - func drain() -> [AVAudioPCMBuffer] { - self.lock.lock() - let drained = self.buffers - self.buffers.removeAll(keepingCapacity: true) - self.lock.unlock() - return drained - } - - func clear() { - self.lock.lock() - self.buffers.removeAll(keepingCapacity: false) - self.lock.unlock() - } -} - -extension AVAudioPCMBuffer { - fileprivate func deepCopy() -> AVAudioPCMBuffer? { - let format = self.format - let frameLength = self.frameLength - guard let copy = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: frameLength) else { - return nil - } - copy.frameLength = frameLength - - if let src = self.floatChannelData, let dst = copy.floatChannelData { - let channels = Int(format.channelCount) - let frames = Int(frameLength) - for ch in 0..? - - private var lastDispatched: String? - private var onCommand: (@Sendable (String) async -> Void)? - private var userDefaultsObserver: NSObjectProtocol? - private var suppressedByTalk: Bool = false - - override init() { - super.init() - self.triggerWords = VoiceWakePreferences.loadTriggerWords() - self.userDefaultsObserver = NotificationCenter.default.addObserver( - forName: UserDefaults.didChangeNotification, - object: UserDefaults.standard, - queue: .main, - using: { [weak self] _ in - Task { @MainActor in - self?.handleUserDefaultsDidChange() - } - }) - } - - @MainActor deinit { - if let userDefaultsObserver = self.userDefaultsObserver { - NotificationCenter.default.removeObserver(userDefaultsObserver) - } - } - - var activeTriggerWords: [String] { - VoiceWakePreferences.sanitizeTriggerWords(self.triggerWords) - } - - private func handleUserDefaultsDidChange() { - let updated = VoiceWakePreferences.loadTriggerWords() - if updated != self.triggerWords { - self.triggerWords = updated - } - } - - func configure(onCommand: @escaping @Sendable (String) async -> Void) { - self.onCommand = onCommand - } - - func setEnabled(_ enabled: Bool) { - self.isEnabled = enabled - if enabled { - Task { await self.start() } - } else { - self.stop() - } - } - - func setSuppressedByTalk(_ suppressed: Bool) { - self.suppressedByTalk = suppressed - if suppressed { - _ = self.suspendForExternalAudioCapture() - if self.isEnabled { - self.statusText = "Paused" - } - } else { - if self.isEnabled { - Task { await self.start() } - } - } - } - - func start() async { - guard self.isEnabled else { return } - if self.isListening { return } - guard !self.suppressedByTalk else { - self.isListening = false - self.statusText = "Paused" - return - } - - if ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil || - ProcessInfo.processInfo.environment["SIMULATOR_UDID"] != nil - { - // The iOS Simulator’s audio stack is unreliable for long-running microphone capture. - // (We’ve observed CoreAudio deadlocks after TCC permission prompts.) - self.isListening = false - self.statusText = "Voice Wake isn’t supported on Simulator" - return - } - - self.statusText = "Requesting permissions…" - - let micOk = await Self.requestMicrophonePermission() - guard micOk else { - self.statusText = Self.permissionMessage( - kind: "Microphone", - status: AVAudioSession.sharedInstance().recordPermission) - self.isListening = false - return - } - - let speechOk = await Self.requestSpeechPermission() - guard speechOk else { - self.statusText = Self.permissionMessage( - kind: "Speech recognition", - status: SFSpeechRecognizer.authorizationStatus()) - self.isListening = false - return - } - - self.speechRecognizer = SFSpeechRecognizer() - guard self.speechRecognizer != nil else { - self.statusText = "Speech recognizer unavailable" - self.isListening = false - return - } - - do { - try Self.configureAudioSession() - try self.startRecognition() - self.isListening = true - self.statusText = "Listening" - } catch { - self.isListening = false - self.statusText = "Start failed: \(error.localizedDescription)" - } - } - - func stop() { - self.isEnabled = false - self.isListening = false - self.statusText = "Off" - - self.tapDrainTask?.cancel() - self.tapDrainTask = nil - self.tapQueue?.clear() - self.tapQueue = nil - - self.recognitionTask?.cancel() - self.recognitionTask = nil - self.recognitionRequest = nil - - if self.audioEngine.isRunning { - self.audioEngine.stop() - self.audioEngine.inputNode.removeTap(onBus: 0) - } - - try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation) - } - - /// Temporarily releases the microphone so other subsystems (e.g. camera video capture) can record audio. - /// Returns `true` when listening was active and was suspended. - func suspendForExternalAudioCapture() -> Bool { - guard self.isEnabled, self.isListening else { return false } - - self.isListening = false - self.statusText = "Paused" - - self.tapDrainTask?.cancel() - self.tapDrainTask = nil - self.tapQueue?.clear() - self.tapQueue = nil - - self.recognitionTask?.cancel() - self.recognitionTask = nil - self.recognitionRequest = nil - - if self.audioEngine.isRunning { - self.audioEngine.stop() - self.audioEngine.inputNode.removeTap(onBus: 0) - } - - try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation) - return true - } - - func resumeAfterExternalAudioCapture(wasSuspended: Bool) { - guard wasSuspended else { return } - Task { await self.start() } - } - - private func startRecognition() throws { - self.recognitionTask?.cancel() - self.recognitionTask = nil - self.tapDrainTask?.cancel() - self.tapDrainTask = nil - self.tapQueue?.clear() - self.tapQueue = nil - - let request = SFSpeechAudioBufferRecognitionRequest() - request.shouldReportPartialResults = true - self.recognitionRequest = request - - let inputNode = self.audioEngine.inputNode - inputNode.removeTap(onBus: 0) - - let recordingFormat = inputNode.outputFormat(forBus: 0) - - let queue = AudioBufferQueue() - self.tapQueue = queue - let tapBlock: @Sendable (AVAudioPCMBuffer, AVAudioTime) -> Void = makeAudioTapEnqueueCallback(queue: queue) - inputNode.installTap( - onBus: 0, - bufferSize: 1024, - format: recordingFormat, - block: tapBlock) - - self.audioEngine.prepare() - try self.audioEngine.start() - - let handler = self.makeRecognitionResultHandler() - self.recognitionTask = self.speechRecognizer?.recognitionTask(with: request, resultHandler: handler) - - self.tapDrainTask = Task { [weak self] in - guard let self, let queue = self.tapQueue else { return } - while !Task.isCancelled { - try? await Task.sleep(nanoseconds: 40_000_000) - let drained = queue.drain() - if drained.isEmpty { continue } - for buf in drained { - request.append(buf) - } - } - } - } - - private nonisolated func makeRecognitionResultHandler() -> @Sendable (SFSpeechRecognitionResult?, Error?) -> Void { - { [weak self] result, error in - let transcript = result?.bestTranscription.formattedString - let segments = result.flatMap { result in - transcript.map { WakeWordSpeechSegments.from(transcription: result.bestTranscription, transcript: $0) } - } ?? [] - let errorText = error?.localizedDescription - - Task { @MainActor in - self?.handleRecognitionCallback(transcript: transcript, segments: segments, errorText: errorText) - } - } - } - - private func handleRecognitionCallback(transcript: String?, segments: [WakeWordSegment], errorText: String?) { - if let errorText { - self.statusText = "Recognizer error: \(errorText)" - self.isListening = false - - let shouldRestart = self.isEnabled - if shouldRestart { - Task { - try? await Task.sleep(nanoseconds: 700_000_000) - await self.start() - } - } - return - } - - guard let transcript else { return } - guard let cmd = self.extractCommand(from: transcript, segments: segments) else { return } - - if cmd == self.lastDispatched { return } - self.lastDispatched = cmd - self.lastTriggeredCommand = cmd - self.statusText = "Triggered" - - Task { [weak self] in - guard let self else { return } - await self.onCommand?(cmd) - await self.startIfEnabled() - } - } - - private func startIfEnabled() async { - let shouldRestart = self.isEnabled - if shouldRestart { - await self.start() - } - } - - private func extractCommand(from transcript: String, segments: [WakeWordSegment]) -> String? { - Self.extractCommand(from: transcript, segments: segments, triggers: self.activeTriggerWords) - } - - nonisolated static func extractCommand( - from transcript: String, - segments: [WakeWordSegment], - triggers: [String], - minPostTriggerGap: TimeInterval = 0.45) -> String? - { - let config = WakeWordGateConfig(triggers: triggers, minPostTriggerGap: minPostTriggerGap) - return WakeWordGate.match(transcript: transcript, segments: segments, config: config)?.command - } - - private static func configureAudioSession() throws { - let session = AVAudioSession.sharedInstance() - try session.setCategory(.playAndRecord, mode: .measurement, options: [ - .duckOthers, - .mixWithOthers, - .allowBluetoothHFP, - .defaultToSpeaker, - ]) - try session.setActive(true, options: []) - } - - private nonisolated static func requestMicrophonePermission() async -> Bool { - let session = AVAudioSession.sharedInstance() - switch session.recordPermission { - case .granted: - return true - case .denied: - return false - case .undetermined: - break - @unknown default: - return false - } - - return await self.requestPermissionWithTimeout { completion in - AVAudioSession.sharedInstance().requestRecordPermission { ok in - completion(ok) - } - } - } - - private nonisolated static func requestSpeechPermission() async -> Bool { - let status = SFSpeechRecognizer.authorizationStatus() - switch status { - case .authorized: - return true - case .denied, .restricted: - return false - case .notDetermined: - break - @unknown default: - return false - } - - return await self.requestPermissionWithTimeout { completion in - SFSpeechRecognizer.requestAuthorization { authStatus in - completion(authStatus == .authorized) - } - } - } - - private nonisolated static func requestPermissionWithTimeout( - _ operation: @escaping @Sendable (@escaping (Bool) -> Void) -> Void) async -> Bool - { - do { - return try await AsyncTimeout.withTimeout( - seconds: 8, - onTimeout: { NSError(domain: "VoiceWake", code: 6, userInfo: [ - NSLocalizedDescriptionKey: "permission request timed out", - ]) }, - operation: { - await withCheckedContinuation(isolation: nil) { cont in - Task { @MainActor in - operation { ok in - cont.resume(returning: ok) - } - } - } - }) - } catch { - return false - } - } - - private static func permissionMessage( - kind: String, - status: AVAudioSession.RecordPermission) -> String - { - switch status { - case .denied: - return "\(kind) permission denied" - case .undetermined: - return "\(kind) permission not granted" - case .granted: - return "\(kind) permission denied" - @unknown default: - return "\(kind) permission denied" - } - } - - private static func permissionMessage( - kind: String, - status: SFSpeechRecognizerAuthorizationStatus) -> String - { - switch status { - case .denied: - return "\(kind) permission denied" - case .restricted: - return "\(kind) permission restricted" - case .notDetermined: - return "\(kind) permission not granted" - case .authorized: - return "\(kind) permission denied" - @unknown default: - return "\(kind) permission denied" - } - } -} - -#if DEBUG -extension VoiceWakeManager { - func _test_handleRecognitionCallback(transcript: String?, segments: [WakeWordSegment], errorText: String?) { - self.handleRecognitionCallback(transcript: transcript, segments: segments, errorText: errorText) - } -} -#endif diff --git a/apps/ios/Sources/Voice/VoiceWakePreferences.swift b/apps/ios/Sources/Voice/VoiceWakePreferences.swift deleted file mode 100644 index 56762b515e2..00000000000 --- a/apps/ios/Sources/Voice/VoiceWakePreferences.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Foundation - -enum VoiceWakePreferences { - static let enabledKey = "voiceWake.enabled" - static let triggerWordsKey = "voiceWake.triggerWords" - - // Keep defaults aligned with the mac app. - static let defaultTriggerWords: [String] = ["openclaw", "claude"] - static let maxWords = 32 - static let maxWordLength = 64 - - static func decodeGatewayTriggers(from payloadJSON: String) -> [String]? { - guard let data = payloadJSON.data(using: .utf8) else { return nil } - return self.decodeGatewayTriggers(from: data) - } - - static func decodeGatewayTriggers(from data: Data) -> [String]? { - struct Payload: Decodable { var triggers: [String] } - guard let decoded = try? JSONDecoder().decode(Payload.self, from: data) else { return nil } - return self.sanitizeTriggerWords(decoded.triggers) - } - - static func loadTriggerWords(defaults: UserDefaults = .standard) -> [String] { - defaults.stringArray(forKey: self.triggerWordsKey) ?? self.defaultTriggerWords - } - - static func saveTriggerWords(_ words: [String], defaults: UserDefaults = .standard) { - defaults.set(words, forKey: self.triggerWordsKey) - } - - static func sanitizeTriggerWords(_ words: [String]) -> [String] { - let cleaned = words - .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } - .filter { !$0.isEmpty } - .prefix(Self.maxWords) - .map { String($0.prefix(Self.maxWordLength)) } - return cleaned.isEmpty ? Self.defaultTriggerWords : cleaned - } - - static func displayString(for words: [String]) -> String { - let sanitized = self.sanitizeTriggerWords(words) - return sanitized.joined(separator: ", ") - } -} diff --git a/apps/ios/SwiftSources.input.xcfilelist b/apps/ios/SwiftSources.input.xcfilelist deleted file mode 100644 index 5b1ba7d70e6..00000000000 --- a/apps/ios/SwiftSources.input.xcfilelist +++ /dev/null @@ -1,61 +0,0 @@ -Sources/Gateway/GatewayConnectionController.swift -Sources/Gateway/GatewayDiscoveryDebugLogView.swift -Sources/Gateway/GatewayDiscoveryModel.swift -Sources/Gateway/GatewaySettingsStore.swift -Sources/Gateway/KeychainStore.swift -Sources/Camera/CameraController.swift -Sources/Chat/ChatSheet.swift -Sources/Chat/IOSGatewayChatTransport.swift -Sources/OpenClawApp.swift -Sources/Location/LocationService.swift -Sources/Model/NodeAppModel.swift -Sources/Model/NodeAppModel+Canvas.swift -Sources/RootCanvas.swift -Sources/RootTabs.swift -Sources/Screen/ScreenController.swift -Sources/Screen/ScreenRecordService.swift -Sources/Screen/ScreenTab.swift -Sources/Screen/ScreenWebView.swift -Sources/SessionKey.swift -Sources/Settings/SettingsNetworkingHelpers.swift -Sources/Settings/SettingsTab.swift -Sources/Settings/VoiceWakeWordsSettingsView.swift -Sources/Status/StatusPill.swift -Sources/Status/VoiceWakeToast.swift -Sources/Voice/VoiceTab.swift -Sources/Voice/VoiceWakeManager.swift -Sources/Voice/VoiceWakePreferences.swift -../shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift -../shared/OpenClawKit/Sources/OpenClawChatUI/ChatMarkdownRenderer.swift -../shared/OpenClawKit/Sources/OpenClawChatUI/ChatMarkdownPreprocessor.swift -../shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageViews.swift -../shared/OpenClawKit/Sources/OpenClawChatUI/ChatModels.swift -../shared/OpenClawKit/Sources/OpenClawChatUI/ChatPayloadDecoding.swift -../shared/OpenClawKit/Sources/OpenClawChatUI/ChatSessions.swift -../shared/OpenClawKit/Sources/OpenClawChatUI/ChatSheets.swift -../shared/OpenClawKit/Sources/OpenClawChatUI/ChatTheme.swift -../shared/OpenClawKit/Sources/OpenClawChatUI/ChatTransport.swift -../shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift -../shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift -../shared/OpenClawKit/Sources/OpenClawKit/AnyCodable.swift -../shared/OpenClawKit/Sources/OpenClawKit/BonjourEscapes.swift -../shared/OpenClawKit/Sources/OpenClawKit/BonjourTypes.swift -../shared/OpenClawKit/Sources/OpenClawKit/BridgeFrames.swift -../shared/OpenClawKit/Sources/OpenClawKit/CameraCommands.swift -../shared/OpenClawKit/Sources/OpenClawKit/CanvasA2UIAction.swift -../shared/OpenClawKit/Sources/OpenClawKit/CanvasA2UICommands.swift -../shared/OpenClawKit/Sources/OpenClawKit/CanvasA2UIJSONL.swift -../shared/OpenClawKit/Sources/OpenClawKit/CanvasCommandParams.swift -../shared/OpenClawKit/Sources/OpenClawKit/CanvasCommands.swift -../shared/OpenClawKit/Sources/OpenClawKit/Capabilities.swift -../shared/OpenClawKit/Sources/OpenClawKit/OpenClawKitResources.swift -../shared/OpenClawKit/Sources/OpenClawKit/DeepLinks.swift -../shared/OpenClawKit/Sources/OpenClawKit/JPEGTranscoder.swift -../shared/OpenClawKit/Sources/OpenClawKit/NodeError.swift -../shared/OpenClawKit/Sources/OpenClawKit/ScreenCommands.swift -../shared/OpenClawKit/Sources/OpenClawKit/StoragePaths.swift -../shared/OpenClawKit/Sources/OpenClawKit/SystemCommands.swift -../shared/OpenClawKit/Sources/OpenClawKit/TalkDirective.swift -../../Swabble/Sources/SwabbleKit/WakeWordGate.swift -Sources/Voice/TalkModeManager.swift -Sources/Voice/TalkOrbOverlay.swift diff --git a/apps/ios/Tests/AppCoverageTests.swift b/apps/ios/Tests/AppCoverageTests.swift deleted file mode 100644 index 33c71cccd05..00000000000 --- a/apps/ios/Tests/AppCoverageTests.swift +++ /dev/null @@ -1,31 +0,0 @@ -import SwiftUI -import Testing -@testable import OpenClaw - -@Suite struct AppCoverageTests { - @Test @MainActor func nodeAppModelUpdatesBackgroundedState() { - let appModel = NodeAppModel() - - appModel.setScenePhase(.background) - #expect(appModel.isBackgrounded == true) - - appModel.setScenePhase(.inactive) - #expect(appModel.isBackgrounded == false) - - appModel.setScenePhase(.active) - #expect(appModel.isBackgrounded == false) - } - - @Test @MainActor func voiceWakeStartReportsUnsupportedOnSimulator() async { - let voiceWake = VoiceWakeManager() - voiceWake.isEnabled = true - - await voiceWake.start() - - #expect(voiceWake.isListening == false) - #expect(voiceWake.statusText.contains("Simulator")) - - voiceWake.stop() - #expect(voiceWake.statusText == "Off") - } -} diff --git a/apps/ios/Tests/CameraControllerClampTests.swift b/apps/ios/Tests/CameraControllerClampTests.swift deleted file mode 100644 index 791010d11b0..00000000000 --- a/apps/ios/Tests/CameraControllerClampTests.swift +++ /dev/null @@ -1,24 +0,0 @@ -import Testing -@testable import OpenClaw - -@Suite struct CameraControllerClampTests { - @Test func clampQualityDefaultsAndBounds() { - #expect(CameraController.clampQuality(nil) == 0.9) - #expect(CameraController.clampQuality(0.0) == 0.05) - #expect(CameraController.clampQuality(0.049) == 0.05) - #expect(CameraController.clampQuality(0.05) == 0.05) - #expect(CameraController.clampQuality(0.5) == 0.5) - #expect(CameraController.clampQuality(1.0) == 1.0) - #expect(CameraController.clampQuality(1.1) == 1.0) - } - - @Test func clampDurationDefaultsAndBounds() { - #expect(CameraController.clampDurationMs(nil) == 3000) - #expect(CameraController.clampDurationMs(0) == 250) - #expect(CameraController.clampDurationMs(249) == 250) - #expect(CameraController.clampDurationMs(250) == 250) - #expect(CameraController.clampDurationMs(1000) == 1000) - #expect(CameraController.clampDurationMs(60000) == 60000) - #expect(CameraController.clampDurationMs(60001) == 60000) - } -} diff --git a/apps/ios/Tests/CameraControllerErrorTests.swift b/apps/ios/Tests/CameraControllerErrorTests.swift deleted file mode 100644 index 26cac6177da..00000000000 --- a/apps/ios/Tests/CameraControllerErrorTests.swift +++ /dev/null @@ -1,14 +0,0 @@ -import Testing -@testable import OpenClaw - -@Suite struct CameraControllerErrorTests { - @Test func errorDescriptionsAreStable() { - #expect(CameraController.CameraError.cameraUnavailable.errorDescription == "Camera unavailable") - #expect(CameraController.CameraError.microphoneUnavailable.errorDescription == "Microphone unavailable") - #expect(CameraController.CameraError.permissionDenied(kind: "Camera") - .errorDescription == "Camera permission denied") - #expect(CameraController.CameraError.invalidParams("bad").errorDescription == "bad") - #expect(CameraController.CameraError.captureFailed("nope").errorDescription == "nope") - #expect(CameraController.CameraError.exportFailed("export").errorDescription == "export") - } -} diff --git a/apps/ios/Tests/DeepLinkParserTests.swift b/apps/ios/Tests/DeepLinkParserTests.swift deleted file mode 100644 index 51ef9547a10..00000000000 --- a/apps/ios/Tests/DeepLinkParserTests.swift +++ /dev/null @@ -1,181 +0,0 @@ -import OpenClawKit -import Foundation -import Testing - -@Suite struct DeepLinkParserTests { - @Test func parseRejectsUnknownHost() { - let url = URL(string: "openclaw://nope?message=hi")! - #expect(DeepLinkParser.parse(url) == nil) - } - - @Test func parseHostIsCaseInsensitive() { - let url = URL(string: "openclaw://AGENT?message=Hello")! - #expect(DeepLinkParser.parse(url) == .agent(.init( - message: "Hello", - sessionKey: nil, - thinking: nil, - deliver: false, - to: nil, - channel: nil, - timeoutSeconds: nil, - key: nil))) - } - - @Test func parseRejectsNonOpenClawScheme() { - let url = URL(string: "https://example.com/agent?message=hi")! - #expect(DeepLinkParser.parse(url) == nil) - } - - @Test func parseRejectsEmptyMessage() { - let url = URL(string: "openclaw://agent?message=%20%20%0A")! - #expect(DeepLinkParser.parse(url) == nil) - } - - @Test func parseAgentLinkParsesCommonFields() { - let url = - URL(string: "openclaw://agent?message=Hello&deliver=1&sessionKey=node-test&thinking=low&timeoutSeconds=30")! - #expect( - DeepLinkParser.parse(url) == .agent( - .init( - message: "Hello", - sessionKey: "node-test", - thinking: "low", - deliver: true, - to: nil, - channel: nil, - timeoutSeconds: 30, - key: nil))) - } - - @Test func parseAgentLinkParsesTargetRoutingFields() { - let url = - URL( - string: "openclaw://agent?message=Hello%20World&deliver=1&to=%2B15551234567&channel=whatsapp&key=secret")! - #expect( - DeepLinkParser.parse(url) == .agent( - .init( - message: "Hello World", - sessionKey: nil, - thinking: nil, - deliver: true, - to: "+15551234567", - channel: "whatsapp", - timeoutSeconds: nil, - key: "secret"))) - } - - @Test func parseRejectsNegativeTimeoutSeconds() { - let url = URL(string: "openclaw://agent?message=Hello&timeoutSeconds=-1")! - #expect(DeepLinkParser.parse(url) == .agent(.init( - message: "Hello", - sessionKey: nil, - thinking: nil, - deliver: false, - to: nil, - channel: nil, - timeoutSeconds: nil, - key: nil))) - } - - @Test func parseGatewayLinkParsesCommonFields() { - let url = URL( - string: "openclaw://gateway?host=openclaw.local&port=18789&tls=1&token=abc&password=def")! - #expect( - DeepLinkParser.parse(url) == .gateway( - .init(host: "openclaw.local", port: 18789, tls: true, token: "abc", password: "def"))) - } - - @Test func parseGatewayLinkRejectsInsecureNonLoopbackWs() { - let url = URL( - string: "openclaw://gateway?host=attacker.example&port=18789&tls=0&token=abc")! - #expect(DeepLinkParser.parse(url) == nil) - } - - @Test func parseGatewayLinkRejectsInsecurePrefixBypassHost() { - let url = URL( - string: "openclaw://gateway?host=127.attacker.example&port=18789&tls=0&token=abc")! - #expect(DeepLinkParser.parse(url) == nil) - } - - @Test func parseGatewaySetupCodeParsesBase64UrlPayload() { - let payload = #"{"url":"wss://gateway.example.com:443","token":"tok","password":"pw"}"# - let encoded = Data(payload.utf8) - .base64EncodedString() - .replacingOccurrences(of: "+", with: "-") - .replacingOccurrences(of: "/", with: "_") - .replacingOccurrences(of: "=", with: "") - - let link = GatewayConnectDeepLink.fromSetupCode(encoded) - - #expect(link == .init( - host: "gateway.example.com", - port: 443, - tls: true, - token: "tok", - password: "pw")) - } - - @Test func parseGatewaySetupCodeRejectsInvalidInput() { - #expect(GatewayConnectDeepLink.fromSetupCode("not-a-valid-setup-code") == nil) - } - - @Test func parseGatewaySetupCodeDefaultsTo443ForWssWithoutPort() { - let payload = #"{"url":"wss://gateway.example.com","token":"tok"}"# - let encoded = Data(payload.utf8) - .base64EncodedString() - .replacingOccurrences(of: "+", with: "-") - .replacingOccurrences(of: "/", with: "_") - .replacingOccurrences(of: "=", with: "") - - let link = GatewayConnectDeepLink.fromSetupCode(encoded) - - #expect(link == .init( - host: "gateway.example.com", - port: 443, - tls: true, - token: "tok", - password: nil)) - } - - @Test func parseGatewaySetupCodeRejectsInsecureNonLoopbackWs() { - let payload = #"{"url":"ws://attacker.example:18789","token":"tok"}"# - let encoded = Data(payload.utf8) - .base64EncodedString() - .replacingOccurrences(of: "+", with: "-") - .replacingOccurrences(of: "/", with: "_") - .replacingOccurrences(of: "=", with: "") - - let link = GatewayConnectDeepLink.fromSetupCode(encoded) - #expect(link == nil) - } - - @Test func parseGatewaySetupCodeRejectsInsecurePrefixBypassHost() { - let payload = #"{"url":"ws://127.attacker.example:18789","token":"tok"}"# - let encoded = Data(payload.utf8) - .base64EncodedString() - .replacingOccurrences(of: "+", with: "-") - .replacingOccurrences(of: "/", with: "_") - .replacingOccurrences(of: "=", with: "") - - let link = GatewayConnectDeepLink.fromSetupCode(encoded) - #expect(link == nil) - } - - @Test func parseGatewaySetupCodeAllowsLoopbackWs() { - let payload = #"{"url":"ws://127.0.0.1:18789","token":"tok"}"# - let encoded = Data(payload.utf8) - .base64EncodedString() - .replacingOccurrences(of: "+", with: "-") - .replacingOccurrences(of: "/", with: "_") - .replacingOccurrences(of: "=", with: "") - - let link = GatewayConnectDeepLink.fromSetupCode(encoded) - - #expect(link == .init( - host: "127.0.0.1", - port: 18789, - tls: false, - token: "tok", - password: nil)) - } -} diff --git a/apps/ios/Tests/GatewayConnectionControllerTests.swift b/apps/ios/Tests/GatewayConnectionControllerTests.swift deleted file mode 100644 index 27e7aed7aea..00000000000 --- a/apps/ios/Tests/GatewayConnectionControllerTests.swift +++ /dev/null @@ -1,122 +0,0 @@ -import OpenClawKit -import Foundation -import Testing -import UIKit -@testable import OpenClaw - -private func withUserDefaults(_ updates: [String: Any?], _ body: () throws -> T) rethrows -> T { - let defaults = UserDefaults.standard - var snapshot: [String: Any?] = [:] - for key in updates.keys { - snapshot[key] = defaults.object(forKey: key) - } - for (key, value) in updates { - if let value { - defaults.set(value, forKey: key) - } else { - defaults.removeObject(forKey: key) - } - } - defer { - for (key, value) in snapshot { - if let value { - defaults.set(value, forKey: key) - } else { - defaults.removeObject(forKey: key) - } - } - } - return try body() -} - -@Suite(.serialized) struct GatewayConnectionControllerTests { - @Test @MainActor func resolvedDisplayNameSetsDefaultWhenMissing() { - let defaults = UserDefaults.standard - let displayKey = "node.displayName" - - withUserDefaults([displayKey: nil, "node.instanceId": "ios-test"]) { - let appModel = NodeAppModel() - let controller = GatewayConnectionController(appModel: appModel, startDiscovery: false) - - let resolved = controller._test_resolvedDisplayName(defaults: defaults) - #expect(!resolved.isEmpty) - #expect(defaults.string(forKey: displayKey) == resolved) - } - } - - @Test @MainActor func currentCapsReflectToggles() { - withUserDefaults([ - "node.instanceId": "ios-test", - "node.displayName": "Test Node", - "camera.enabled": true, - "location.enabledMode": OpenClawLocationMode.always.rawValue, - VoiceWakePreferences.enabledKey: true, - ]) { - let appModel = NodeAppModel() - let controller = GatewayConnectionController(appModel: appModel, startDiscovery: false) - let caps = Set(controller._test_currentCaps()) - - #expect(caps.contains(OpenClawCapability.canvas.rawValue)) - #expect(caps.contains(OpenClawCapability.screen.rawValue)) - #expect(caps.contains(OpenClawCapability.camera.rawValue)) - #expect(caps.contains(OpenClawCapability.location.rawValue)) - #expect(caps.contains(OpenClawCapability.voiceWake.rawValue)) - } - } - - @Test @MainActor func currentCommandsIncludeLocationWhenEnabled() { - withUserDefaults([ - "node.instanceId": "ios-test", - "location.enabledMode": OpenClawLocationMode.whileUsing.rawValue, - ]) { - let appModel = NodeAppModel() - let controller = GatewayConnectionController(appModel: appModel, startDiscovery: false) - let commands = Set(controller._test_currentCommands()) - - #expect(commands.contains(OpenClawLocationCommand.get.rawValue)) - } - } - @Test @MainActor func currentCommandsExcludeDangerousSystemExecCommands() { - withUserDefaults([ - "node.instanceId": "ios-test", - "camera.enabled": true, - "location.enabledMode": OpenClawLocationMode.whileUsing.rawValue, - ]) { - let appModel = NodeAppModel() - let controller = GatewayConnectionController(appModel: appModel, startDiscovery: false) - let commands = Set(controller._test_currentCommands()) - - // iOS should expose notify, but not host shell/exec-approval commands. - #expect(commands.contains(OpenClawSystemCommand.notify.rawValue)) - #expect(!commands.contains(OpenClawSystemCommand.run.rawValue)) - #expect(!commands.contains(OpenClawSystemCommand.which.rawValue)) - #expect(!commands.contains(OpenClawSystemCommand.execApprovalsGet.rawValue)) - #expect(!commands.contains(OpenClawSystemCommand.execApprovalsSet.rawValue)) - } - } - - @Test @MainActor func loadLastConnectionReadsSavedValues() { - withUserDefaults([:]) { - GatewaySettingsStore.saveLastGatewayConnectionManual( - host: "gateway.example.com", - port: 443, - useTLS: true, - stableID: "manual|gateway.example.com|443") - let loaded = GatewaySettingsStore.loadLastGatewayConnection() - #expect(loaded == .manual(host: "gateway.example.com", port: 443, useTLS: true, stableID: "manual|gateway.example.com|443")) - } - } - - @Test @MainActor func loadLastConnectionReturnsNilForInvalidData() { - withUserDefaults([ - "gateway.last.kind": "manual", - "gateway.last.host": "", - "gateway.last.port": 0, - "gateway.last.tls": false, - "gateway.last.stableID": "manual|invalid|0", - ]) { - let loaded = GatewaySettingsStore.loadLastGatewayConnection() - #expect(loaded == nil) - } - } -} diff --git a/apps/ios/Tests/GatewayConnectionIssueTests.swift b/apps/ios/Tests/GatewayConnectionIssueTests.swift deleted file mode 100644 index 8eb63f268ba..00000000000 --- a/apps/ios/Tests/GatewayConnectionIssueTests.swift +++ /dev/null @@ -1,33 +0,0 @@ -import Testing -@testable import OpenClaw - -@Suite(.serialized) struct GatewayConnectionIssueTests { - @Test func detectsTokenMissing() { - let issue = GatewayConnectionIssue.detect(from: "unauthorized: gateway token missing") - #expect(issue == .tokenMissing) - #expect(issue.needsAuthToken) - } - - @Test func detectsUnauthorized() { - let issue = GatewayConnectionIssue.detect(from: "Gateway error: unauthorized role") - #expect(issue == .unauthorized) - #expect(issue.needsAuthToken) - } - - @Test func detectsPairingWithRequestId() { - let issue = GatewayConnectionIssue.detect(from: "pairing required (requestId: abc123)") - #expect(issue == .pairingRequired(requestId: "abc123")) - #expect(issue.needsPairing) - #expect(issue.requestId == "abc123") - } - - @Test func detectsNetworkError() { - let issue = GatewayConnectionIssue.detect(from: "Gateway error: Connection refused") - #expect(issue == .network) - } - - @Test func returnsNoneForBenignStatus() { - let issue = GatewayConnectionIssue.detect(from: "Connected") - #expect(issue == .none) - } -} diff --git a/apps/ios/Tests/GatewayConnectionSecurityTests.swift b/apps/ios/Tests/GatewayConnectionSecurityTests.swift deleted file mode 100644 index b82ae716168..00000000000 --- a/apps/ios/Tests/GatewayConnectionSecurityTests.swift +++ /dev/null @@ -1,131 +0,0 @@ -import Foundation -import Network -import Testing -@testable import OpenClaw - -@Suite(.serialized) struct GatewayConnectionSecurityTests { - private func clearTLSFingerprint(stableID: String) { - let suite = UserDefaults(suiteName: "ai.openclaw.shared") ?? .standard - suite.removeObject(forKey: "gateway.tls.\(stableID)") - } - - @Test @MainActor func discoveredTLSParams_prefersStoredPinOverAdvertisedTXT() async { - let stableID = "test|\(UUID().uuidString)" - defer { clearTLSFingerprint(stableID: stableID) } - clearTLSFingerprint(stableID: stableID) - - GatewayTLSStore.saveFingerprint("11", stableID: stableID) - - let endpoint: NWEndpoint = .service(name: "Test", type: "_openclaw-gw._tcp", domain: "local.", interface: nil) - let gateway = GatewayDiscoveryModel.DiscoveredGateway( - name: "Test", - endpoint: endpoint, - stableID: stableID, - debugID: "debug", - lanHost: "evil.example.com", - tailnetDns: "evil.example.com", - gatewayPort: 12345, - canvasPort: nil, - tlsEnabled: true, - tlsFingerprintSha256: "22", - cliPath: nil) - - let appModel = NodeAppModel() - let controller = GatewayConnectionController(appModel: appModel, startDiscovery: false) - - let params = controller._test_resolveDiscoveredTLSParams(gateway: gateway, allowTOFU: true) - #expect(params?.expectedFingerprint == "11") - #expect(params?.allowTOFU == false) - } - - @Test @MainActor func discoveredTLSParams_doesNotTrustAdvertisedFingerprint() async { - let stableID = "test|\(UUID().uuidString)" - defer { clearTLSFingerprint(stableID: stableID) } - clearTLSFingerprint(stableID: stableID) - - let endpoint: NWEndpoint = .service(name: "Test", type: "_openclaw-gw._tcp", domain: "local.", interface: nil) - let gateway = GatewayDiscoveryModel.DiscoveredGateway( - name: "Test", - endpoint: endpoint, - stableID: stableID, - debugID: "debug", - lanHost: nil, - tailnetDns: nil, - gatewayPort: nil, - canvasPort: nil, - tlsEnabled: true, - tlsFingerprintSha256: "22", - cliPath: nil) - - let appModel = NodeAppModel() - let controller = GatewayConnectionController(appModel: appModel, startDiscovery: false) - - let params = controller._test_resolveDiscoveredTLSParams(gateway: gateway, allowTOFU: true) - #expect(params?.expectedFingerprint == nil) - #expect(params?.allowTOFU == false) - } - - @Test @MainActor func autoconnectRequiresStoredPinForDiscoveredGateways() async { - let stableID = "test|\(UUID().uuidString)" - defer { clearTLSFingerprint(stableID: stableID) } - clearTLSFingerprint(stableID: stableID) - - let defaults = UserDefaults.standard - defaults.set(true, forKey: "gateway.autoconnect") - defaults.set(false, forKey: "gateway.manual.enabled") - defaults.removeObject(forKey: "gateway.last.host") - defaults.removeObject(forKey: "gateway.last.port") - defaults.removeObject(forKey: "gateway.last.tls") - defaults.removeObject(forKey: "gateway.last.stableID") - defaults.removeObject(forKey: "gateway.last.kind") - defaults.removeObject(forKey: "gateway.preferredStableID") - defaults.set(stableID, forKey: "gateway.lastDiscoveredStableID") - - let endpoint: NWEndpoint = .service(name: "Test", type: "_openclaw-gw._tcp", domain: "local.", interface: nil) - let gateway = GatewayDiscoveryModel.DiscoveredGateway( - name: "Test", - endpoint: endpoint, - stableID: stableID, - debugID: "debug", - lanHost: "test.local", - tailnetDns: nil, - gatewayPort: 18789, - canvasPort: nil, - tlsEnabled: true, - tlsFingerprintSha256: nil, - cliPath: nil) - - let appModel = NodeAppModel() - let controller = GatewayConnectionController(appModel: appModel, startDiscovery: false) - controller._test_setGateways([gateway]) - controller._test_triggerAutoConnect() - - #expect(controller._test_didAutoConnect() == false) - } - - @Test @MainActor func manualConnectionsForceTLSForNonLoopbackHosts() async { - let appModel = NodeAppModel() - let controller = GatewayConnectionController(appModel: appModel, startDiscovery: false) - - #expect(controller._test_resolveManualUseTLS(host: "gateway.example.com", useTLS: false) == true) - #expect(controller._test_resolveManualUseTLS(host: "openclaw.local", useTLS: false) == true) - #expect(controller._test_resolveManualUseTLS(host: "127.attacker.example", useTLS: false) == true) - - #expect(controller._test_resolveManualUseTLS(host: "localhost", useTLS: false) == false) - #expect(controller._test_resolveManualUseTLS(host: "127.0.0.1", useTLS: false) == false) - #expect(controller._test_resolveManualUseTLS(host: "::1", useTLS: false) == false) - #expect(controller._test_resolveManualUseTLS(host: "[::1]", useTLS: false) == false) - #expect(controller._test_resolveManualUseTLS(host: "::ffff:127.0.0.1", useTLS: false) == false) - #expect(controller._test_resolveManualUseTLS(host: "0.0.0.0", useTLS: false) == false) - } - - @Test @MainActor func manualDefaultPortUses443OnlyForTailnetTLSHosts() async { - let appModel = NodeAppModel() - let controller = GatewayConnectionController(appModel: appModel, startDiscovery: false) - - #expect(controller._test_resolveManualPort(host: "gateway.example.com", port: 0, useTLS: true) == 18789) - #expect(controller._test_resolveManualPort(host: "device.sample.ts.net", port: 0, useTLS: true) == 443) - #expect(controller._test_resolveManualPort(host: "device.sample.ts.net.", port: 0, useTLS: true) == 443) - #expect(controller._test_resolveManualPort(host: "device.sample.ts.net", port: 18789, useTLS: true) == 18789) - } -} diff --git a/apps/ios/Tests/GatewayDiscoveryModelTests.swift b/apps/ios/Tests/GatewayDiscoveryModelTests.swift deleted file mode 100644 index 2f98948c962..00000000000 --- a/apps/ios/Tests/GatewayDiscoveryModelTests.swift +++ /dev/null @@ -1,22 +0,0 @@ -import Testing -@testable import OpenClaw - -@Suite(.serialized) struct GatewayDiscoveryModelTests { - @Test @MainActor func debugLoggingCapturesLifecycleAndResets() { - let model = GatewayDiscoveryModel() - - #expect(model.debugLog.isEmpty) - #expect(model.statusText == "Idle") - - model.setDebugLoggingEnabled(true) - #expect(model.debugLog.count >= 2) - - model.stop() - #expect(model.statusText == "Stopped") - #expect(model.gateways.isEmpty) - #expect(model.debugLog.count >= 3) - - model.setDebugLoggingEnabled(false) - #expect(model.debugLog.isEmpty) - } -} diff --git a/apps/ios/Tests/GatewayEndpointIDTests.swift b/apps/ios/Tests/GatewayEndpointIDTests.swift deleted file mode 100644 index e6edf2df237..00000000000 --- a/apps/ios/Tests/GatewayEndpointIDTests.swift +++ /dev/null @@ -1,33 +0,0 @@ -import OpenClawKit -import Network -import Testing -@testable import OpenClaw - -@Suite struct GatewayEndpointIDTests { - @Test func stableIDForServiceDecodesAndNormalizesName() { - let endpoint = NWEndpoint.service( - name: "OpenClaw\\032Gateway \\032 Node\n", - type: "_openclaw-gw._tcp", - domain: "local.", - interface: nil) - - #expect(GatewayEndpointID.stableID(endpoint) == "_openclaw-gw._tcp|local.|OpenClaw Gateway Node") - } - - @Test func stableIDForNonServiceUsesEndpointDescription() { - let endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host("127.0.0.1"), port: 4242) - #expect(GatewayEndpointID.stableID(endpoint) == String(describing: endpoint)) - } - - @Test func prettyDescriptionDecodesBonjourEscapes() { - let endpoint = NWEndpoint.service( - name: "OpenClaw\\032Gateway", - type: "_openclaw-gw._tcp", - domain: "local.", - interface: nil) - - let pretty = GatewayEndpointID.prettyDescription(endpoint) - #expect(pretty == BonjourEscapes.decode(String(describing: endpoint))) - #expect(!pretty.localizedCaseInsensitiveContains("\\032")) - } -} diff --git a/apps/ios/Tests/GatewaySettingsStoreTests.swift b/apps/ios/Tests/GatewaySettingsStoreTests.swift deleted file mode 100644 index 7e67ab84a97..00000000000 --- a/apps/ios/Tests/GatewaySettingsStoreTests.swift +++ /dev/null @@ -1,199 +0,0 @@ -import Foundation -import Testing -@testable import OpenClaw - -private struct KeychainEntry: Hashable { - let service: String - let account: String -} - -private let gatewayService = "ai.openclaw.gateway" -private let nodeService = "ai.openclaw.node" -private let instanceIdEntry = KeychainEntry(service: nodeService, account: "instanceId") -private let preferredGatewayEntry = KeychainEntry(service: gatewayService, account: "preferredStableID") -private let lastGatewayEntry = KeychainEntry(service: gatewayService, account: "lastDiscoveredStableID") - -private func snapshotDefaults(_ keys: [String]) -> [String: Any?] { - let defaults = UserDefaults.standard - var snapshot: [String: Any?] = [:] - for key in keys { - snapshot[key] = defaults.object(forKey: key) - } - return snapshot -} - -private func applyDefaults(_ values: [String: Any?]) { - let defaults = UserDefaults.standard - for (key, value) in values { - if let value { - defaults.set(value, forKey: key) - } else { - defaults.removeObject(forKey: key) - } - } -} - -private func restoreDefaults(_ snapshot: [String: Any?]) { - applyDefaults(snapshot) -} - -private func snapshotKeychain(_ entries: [KeychainEntry]) -> [KeychainEntry: String?] { - var snapshot: [KeychainEntry: String?] = [:] - for entry in entries { - snapshot[entry] = KeychainStore.loadString(service: entry.service, account: entry.account) - } - return snapshot -} - -private func applyKeychain(_ values: [KeychainEntry: String?]) { - for (entry, value) in values { - if let value { - _ = KeychainStore.saveString(value, service: entry.service, account: entry.account) - } else { - _ = KeychainStore.delete(service: entry.service, account: entry.account) - } - } -} - -private func restoreKeychain(_ snapshot: [KeychainEntry: String?]) { - applyKeychain(snapshot) -} - -@Suite(.serialized) struct GatewaySettingsStoreTests { - @Test func bootstrapCopiesDefaultsToKeychainWhenMissing() { - let defaultsKeys = [ - "node.instanceId", - "gateway.preferredStableID", - "gateway.lastDiscoveredStableID", - ] - let entries = [instanceIdEntry, preferredGatewayEntry, lastGatewayEntry] - let defaultsSnapshot = snapshotDefaults(defaultsKeys) - let keychainSnapshot = snapshotKeychain(entries) - defer { - restoreDefaults(defaultsSnapshot) - restoreKeychain(keychainSnapshot) - } - - applyDefaults([ - "node.instanceId": "node-test", - "gateway.preferredStableID": "preferred-test", - "gateway.lastDiscoveredStableID": "last-test", - ]) - applyKeychain([ - instanceIdEntry: nil, - preferredGatewayEntry: nil, - lastGatewayEntry: nil, - ]) - - GatewaySettingsStore.bootstrapPersistence() - - #expect(KeychainStore.loadString(service: nodeService, account: "instanceId") == "node-test") - #expect(KeychainStore.loadString(service: gatewayService, account: "preferredStableID") == "preferred-test") - #expect(KeychainStore.loadString(service: gatewayService, account: "lastDiscoveredStableID") == "last-test") - } - - @Test func bootstrapCopiesKeychainToDefaultsWhenMissing() { - let defaultsKeys = [ - "node.instanceId", - "gateway.preferredStableID", - "gateway.lastDiscoveredStableID", - ] - let entries = [instanceIdEntry, preferredGatewayEntry, lastGatewayEntry] - let defaultsSnapshot = snapshotDefaults(defaultsKeys) - let keychainSnapshot = snapshotKeychain(entries) - defer { - restoreDefaults(defaultsSnapshot) - restoreKeychain(keychainSnapshot) - } - - applyDefaults([ - "node.instanceId": nil, - "gateway.preferredStableID": nil, - "gateway.lastDiscoveredStableID": nil, - ]) - applyKeychain([ - instanceIdEntry: "node-from-keychain", - preferredGatewayEntry: "preferred-from-keychain", - lastGatewayEntry: "last-from-keychain", - ]) - - GatewaySettingsStore.bootstrapPersistence() - - let defaults = UserDefaults.standard - #expect(defaults.string(forKey: "node.instanceId") == "node-from-keychain") - #expect(defaults.string(forKey: "gateway.preferredStableID") == "preferred-from-keychain") - #expect(defaults.string(forKey: "gateway.lastDiscoveredStableID") == "last-from-keychain") - } - - @Test func lastGateway_manualRoundTrip() { - let keys = [ - "gateway.last.kind", - "gateway.last.host", - "gateway.last.port", - "gateway.last.tls", - "gateway.last.stableID", - ] - let snapshot = snapshotDefaults(keys) - defer { restoreDefaults(snapshot) } - - GatewaySettingsStore.saveLastGatewayConnectionManual( - host: "example.com", - port: 443, - useTLS: true, - stableID: "manual|example.com|443") - - let loaded = GatewaySettingsStore.loadLastGatewayConnection() - #expect(loaded == .manual(host: "example.com", port: 443, useTLS: true, stableID: "manual|example.com|443")) - } - - @Test func lastGateway_discoveredDoesNotPersistResolvedHostPort() { - let keys = [ - "gateway.last.kind", - "gateway.last.host", - "gateway.last.port", - "gateway.last.tls", - "gateway.last.stableID", - ] - let snapshot = snapshotDefaults(keys) - defer { restoreDefaults(snapshot) } - - // Simulate a prior manual record that included host/port. - applyDefaults([ - "gateway.last.host": "10.0.0.99", - "gateway.last.port": 18789, - "gateway.last.tls": true, - "gateway.last.stableID": "manual|10.0.0.99|18789", - "gateway.last.kind": "manual", - ]) - - GatewaySettingsStore.saveLastGatewayConnectionDiscovered(stableID: "gw|abc", useTLS: true) - - let defaults = UserDefaults.standard - #expect(defaults.object(forKey: "gateway.last.host") == nil) - #expect(defaults.object(forKey: "gateway.last.port") == nil) - #expect(GatewaySettingsStore.loadLastGatewayConnection() == .discovered(stableID: "gw|abc", useTLS: true)) - } - - @Test func lastGateway_backCompat_manualLoadsWhenKindMissing() { - let keys = [ - "gateway.last.kind", - "gateway.last.host", - "gateway.last.port", - "gateway.last.tls", - "gateway.last.stableID", - ] - let snapshot = snapshotDefaults(keys) - defer { restoreDefaults(snapshot) } - - applyDefaults([ - "gateway.last.kind": nil, - "gateway.last.host": "example.org", - "gateway.last.port": 18789, - "gateway.last.tls": false, - "gateway.last.stableID": "manual|example.org|18789", - ]) - - let loaded = GatewaySettingsStore.loadLastGatewayConnection() - #expect(loaded == .manual(host: "example.org", port: 18789, useTLS: false, stableID: "manual|example.org|18789")) - } -} diff --git a/apps/ios/Tests/IOSGatewayChatTransportTests.swift b/apps/ios/Tests/IOSGatewayChatTransportTests.swift deleted file mode 100644 index f49f242ff24..00000000000 --- a/apps/ios/Tests/IOSGatewayChatTransportTests.swift +++ /dev/null @@ -1,30 +0,0 @@ -import OpenClawKit -import Testing -@testable import OpenClaw - -@Suite struct IOSGatewayChatTransportTests { - @Test func requestsFailFastWhenGatewayNotConnected() async { - let gateway = GatewayNodeSession() - let transport = IOSGatewayChatTransport(gateway: gateway) - - do { - _ = try await transport.requestHistory(sessionKey: "node-test") - Issue.record("Expected requestHistory to throw when gateway not connected") - } catch {} - - do { - _ = try await transport.sendMessage( - sessionKey: "node-test", - message: "hello", - thinking: "low", - idempotencyKey: "idempotency", - attachments: []) - Issue.record("Expected sendMessage to throw when gateway not connected") - } catch {} - - do { - _ = try await transport.requestHealth(timeoutMs: 250) - Issue.record("Expected requestHealth to throw when gateway not connected") - } catch {} - } -} diff --git a/apps/ios/Tests/Info.plist b/apps/ios/Tests/Info.plist deleted file mode 100644 index 7fc8d827044..00000000000 --- a/apps/ios/Tests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - OpenClawTests - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 2026.2.21 - CFBundleVersion - 20260220 - - diff --git a/apps/ios/Tests/KeychainStoreTests.swift b/apps/ios/Tests/KeychainStoreTests.swift deleted file mode 100644 index 827be250ed7..00000000000 --- a/apps/ios/Tests/KeychainStoreTests.swift +++ /dev/null @@ -1,22 +0,0 @@ -import Foundation -import Testing -@testable import OpenClaw - -@Suite struct KeychainStoreTests { - @Test func saveLoadUpdateDeleteRoundTrip() { - let service = "bot.molt.tests.\(UUID().uuidString)" - let account = "value" - - #expect(KeychainStore.delete(service: service, account: account)) - #expect(KeychainStore.loadString(service: service, account: account) == nil) - - #expect(KeychainStore.saveString("first", service: service, account: account)) - #expect(KeychainStore.loadString(service: service, account: account) == "first") - - #expect(KeychainStore.saveString("second", service: service, account: account)) - #expect(KeychainStore.loadString(service: service, account: account) == "second") - - #expect(KeychainStore.delete(service: service, account: account)) - #expect(KeychainStore.loadString(service: service, account: account) == nil) - } -} diff --git a/apps/ios/Tests/NodeAppModelInvokeTests.swift b/apps/ios/Tests/NodeAppModelInvokeTests.swift deleted file mode 100644 index 3d015afae84..00000000000 --- a/apps/ios/Tests/NodeAppModelInvokeTests.swift +++ /dev/null @@ -1,351 +0,0 @@ -import OpenClawKit -import Foundation -import Testing -import UIKit -@testable import OpenClaw - -private func withUserDefaults(_ updates: [String: Any?], _ body: () throws -> T) rethrows -> T { - let defaults = UserDefaults.standard - var snapshot: [String: Any?] = [:] - for key in updates.keys { - snapshot[key] = defaults.object(forKey: key) - } - for (key, value) in updates { - if let value { - defaults.set(value, forKey: key) - } else { - defaults.removeObject(forKey: key) - } - } - defer { - for (key, value) in snapshot { - if let value { - defaults.set(value, forKey: key) - } else { - defaults.removeObject(forKey: key) - } - } - } - return try body() -} - -@MainActor -private final class MockWatchMessagingService: WatchMessagingServicing, @unchecked Sendable { - var currentStatus = WatchMessagingStatus( - supported: true, - paired: true, - appInstalled: true, - reachable: true, - activationState: "activated") - var nextSendResult = WatchNotificationSendResult( - deliveredImmediately: true, - queuedForDelivery: false, - transport: "sendMessage") - var sendError: Error? - var lastSent: (id: String, params: OpenClawWatchNotifyParams)? - private var replyHandler: (@Sendable (WatchQuickReplyEvent) -> Void)? - - func status() async -> WatchMessagingStatus { - self.currentStatus - } - - func setReplyHandler(_ handler: (@Sendable (WatchQuickReplyEvent) -> Void)?) { - self.replyHandler = handler - } - - func sendNotification(id: String, params: OpenClawWatchNotifyParams) async throws -> WatchNotificationSendResult { - self.lastSent = (id: id, params: params) - if let sendError = self.sendError { - throw sendError - } - return self.nextSendResult - } - - func emitReply(_ event: WatchQuickReplyEvent) { - self.replyHandler?(event) - } -} - -@Suite(.serialized) struct NodeAppModelInvokeTests { - @Test @MainActor func decodeParamsFailsWithoutJSON() { - #expect(throws: Error.self) { - _ = try NodeAppModel._test_decodeParams(OpenClawCanvasNavigateParams.self, from: nil) - } - } - - @Test @MainActor func encodePayloadEmitsJSON() throws { - struct Payload: Codable, Equatable { - var value: String - } - let json = try NodeAppModel._test_encodePayload(Payload(value: "ok")) - #expect(json.contains("\"value\"")) - } - - @Test @MainActor func chatSessionKeyDefaultsToIOSBase() { - let appModel = NodeAppModel() - #expect(appModel.chatSessionKey == "ios") - } - - @Test @MainActor func chatSessionKeyUsesAgentScopedKeyForNonDefaultAgent() { - let appModel = NodeAppModel() - appModel.gatewayDefaultAgentId = "main" - appModel.setSelectedAgentId("agent-123") - #expect(appModel.chatSessionKey == SessionKey.makeAgentSessionKey(agentId: "agent-123", baseKey: "ios")) - #expect(appModel.mainSessionKey == "agent:agent-123:main") - } - - @Test @MainActor func handleInvokeRejectsBackgroundCommands() async { - let appModel = NodeAppModel() - appModel.setScenePhase(.background) - - let req = BridgeInvokeRequest(id: "bg", command: OpenClawCanvasCommand.present.rawValue) - let res = await appModel._test_handleInvoke(req) - #expect(res.ok == false) - #expect(res.error?.code == .backgroundUnavailable) - } - - @Test @MainActor func handleInvokeRejectsCameraWhenDisabled() async { - let appModel = NodeAppModel() - let req = BridgeInvokeRequest(id: "cam", command: OpenClawCameraCommand.snap.rawValue) - - let defaults = UserDefaults.standard - let key = "camera.enabled" - let previous = defaults.object(forKey: key) - defaults.set(false, forKey: key) - defer { - if let previous { - defaults.set(previous, forKey: key) - } else { - defaults.removeObject(forKey: key) - } - } - - let res = await appModel._test_handleInvoke(req) - #expect(res.ok == false) - #expect(res.error?.code == .unavailable) - #expect(res.error?.message.contains("CAMERA_DISABLED") == true) - } - - @Test @MainActor func handleInvokeRejectsInvalidScreenFormat() async { - let appModel = NodeAppModel() - let params = OpenClawScreenRecordParams(format: "gif") - let data = try? JSONEncoder().encode(params) - let json = data.flatMap { String(data: $0, encoding: .utf8) } - - let req = BridgeInvokeRequest( - id: "screen", - command: OpenClawScreenCommand.record.rawValue, - paramsJSON: json) - - let res = await appModel._test_handleInvoke(req) - #expect(res.ok == false) - #expect(res.error?.message.contains("screen format must be mp4") == true) - } - - @Test @MainActor func handleInvokeCanvasCommandsUpdateScreen() async throws { - let appModel = NodeAppModel() - appModel.screen.navigate(to: "http://example.com") - - let present = BridgeInvokeRequest(id: "present", command: OpenClawCanvasCommand.present.rawValue) - let presentRes = await appModel._test_handleInvoke(present) - #expect(presentRes.ok == true) - #expect(appModel.screen.urlString.isEmpty) - - // Loopback URLs are rejected (they are not meaningful for a remote gateway). - let navigateParams = OpenClawCanvasNavigateParams(url: "http://example.com/") - let navData = try JSONEncoder().encode(navigateParams) - let navJSON = String(decoding: navData, as: UTF8.self) - let navigate = BridgeInvokeRequest( - id: "nav", - command: OpenClawCanvasCommand.navigate.rawValue, - paramsJSON: navJSON) - let navRes = await appModel._test_handleInvoke(navigate) - #expect(navRes.ok == true) - #expect(appModel.screen.urlString == "http://example.com/") - - let evalParams = OpenClawCanvasEvalParams(javaScript: "1+1") - let evalData = try JSONEncoder().encode(evalParams) - let evalJSON = String(decoding: evalData, as: UTF8.self) - let eval = BridgeInvokeRequest( - id: "eval", - command: OpenClawCanvasCommand.evalJS.rawValue, - paramsJSON: evalJSON) - let evalRes = await appModel._test_handleInvoke(eval) - #expect(evalRes.ok == true) - let payloadData = try #require(evalRes.payloadJSON?.data(using: .utf8)) - let payload = try JSONSerialization.jsonObject(with: payloadData) as? [String: Any] - #expect(payload?["result"] as? String == "2") - } - - @Test @MainActor func handleInvokeA2UICommandsFailWhenHostMissing() async throws { - let appModel = NodeAppModel() - - let reset = BridgeInvokeRequest(id: "reset", command: OpenClawCanvasA2UICommand.reset.rawValue) - let resetRes = await appModel._test_handleInvoke(reset) - #expect(resetRes.ok == false) - #expect(resetRes.error?.message.contains("A2UI_HOST_NOT_CONFIGURED") == true) - - let jsonl = "{\"beginRendering\":{}}" - let pushParams = OpenClawCanvasA2UIPushJSONLParams(jsonl: jsonl) - let pushData = try JSONEncoder().encode(pushParams) - let pushJSON = String(decoding: pushData, as: UTF8.self) - let push = BridgeInvokeRequest( - id: "push", - command: OpenClawCanvasA2UICommand.pushJSONL.rawValue, - paramsJSON: pushJSON) - let pushRes = await appModel._test_handleInvoke(push) - #expect(pushRes.ok == false) - #expect(pushRes.error?.message.contains("A2UI_HOST_NOT_CONFIGURED") == true) - } - - @Test @MainActor func handleInvokeUnknownCommandReturnsInvalidRequest() async { - let appModel = NodeAppModel() - let req = BridgeInvokeRequest(id: "unknown", command: "nope") - let res = await appModel._test_handleInvoke(req) - #expect(res.ok == false) - #expect(res.error?.code == .invalidRequest) - } - - @Test @MainActor func handleInvokeWatchStatusReturnsServiceSnapshot() async throws { - let watchService = MockWatchMessagingService() - watchService.currentStatus = WatchMessagingStatus( - supported: true, - paired: true, - appInstalled: true, - reachable: false, - activationState: "inactive") - let appModel = NodeAppModel(watchMessagingService: watchService) - let req = BridgeInvokeRequest(id: "watch-status", command: OpenClawWatchCommand.status.rawValue) - - let res = await appModel._test_handleInvoke(req) - #expect(res.ok == true) - - let payloadData = try #require(res.payloadJSON?.data(using: .utf8)) - let payload = try JSONDecoder().decode(OpenClawWatchStatusPayload.self, from: payloadData) - #expect(payload.supported == true) - #expect(payload.reachable == false) - #expect(payload.activationState == "inactive") - } - - @Test @MainActor func handleInvokeWatchNotifyRoutesToWatchService() async throws { - let watchService = MockWatchMessagingService() - watchService.nextSendResult = WatchNotificationSendResult( - deliveredImmediately: false, - queuedForDelivery: true, - transport: "transferUserInfo") - let appModel = NodeAppModel(watchMessagingService: watchService) - let params = OpenClawWatchNotifyParams( - title: "OpenClaw", - body: "Meeting with Peter is at 4pm", - priority: .timeSensitive) - let paramsData = try JSONEncoder().encode(params) - let paramsJSON = String(decoding: paramsData, as: UTF8.self) - let req = BridgeInvokeRequest( - id: "watch-notify", - command: OpenClawWatchCommand.notify.rawValue, - paramsJSON: paramsJSON) - - let res = await appModel._test_handleInvoke(req) - #expect(res.ok == true) - #expect(watchService.lastSent?.params.title == "OpenClaw") - #expect(watchService.lastSent?.params.body == "Meeting with Peter is at 4pm") - #expect(watchService.lastSent?.params.priority == .timeSensitive) - - let payloadData = try #require(res.payloadJSON?.data(using: .utf8)) - let payload = try JSONDecoder().decode(OpenClawWatchNotifyPayload.self, from: payloadData) - #expect(payload.deliveredImmediately == false) - #expect(payload.queuedForDelivery == true) - #expect(payload.transport == "transferUserInfo") - } - - @Test @MainActor func handleInvokeWatchNotifyRejectsEmptyMessage() async throws { - let watchService = MockWatchMessagingService() - let appModel = NodeAppModel(watchMessagingService: watchService) - let params = OpenClawWatchNotifyParams(title: " ", body: "\n") - let paramsData = try JSONEncoder().encode(params) - let paramsJSON = String(decoding: paramsData, as: UTF8.self) - let req = BridgeInvokeRequest( - id: "watch-notify-empty", - command: OpenClawWatchCommand.notify.rawValue, - paramsJSON: paramsJSON) - - let res = await appModel._test_handleInvoke(req) - #expect(res.ok == false) - #expect(res.error?.code == .invalidRequest) - #expect(watchService.lastSent == nil) - } - - @Test @MainActor func handleInvokeWatchNotifyReturnsUnavailableOnDeliveryFailure() async throws { - let watchService = MockWatchMessagingService() - watchService.sendError = NSError( - domain: "watch", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "WATCH_UNAVAILABLE: no paired Apple Watch"]) - let appModel = NodeAppModel(watchMessagingService: watchService) - let params = OpenClawWatchNotifyParams(title: "OpenClaw", body: "Delivery check") - let paramsData = try JSONEncoder().encode(params) - let paramsJSON = String(decoding: paramsData, as: UTF8.self) - let req = BridgeInvokeRequest( - id: "watch-notify-fail", - command: OpenClawWatchCommand.notify.rawValue, - paramsJSON: paramsJSON) - - let res = await appModel._test_handleInvoke(req) - #expect(res.ok == false) - #expect(res.error?.code == .unavailable) - #expect(res.error?.message.contains("WATCH_UNAVAILABLE") == true) - } - - @Test @MainActor func watchReplyQueuesWhenGatewayOffline() async { - let watchService = MockWatchMessagingService() - let appModel = NodeAppModel(watchMessagingService: watchService) - watchService.emitReply( - WatchQuickReplyEvent( - replyId: "reply-offline-1", - promptId: "prompt-1", - actionId: "approve", - actionLabel: "Approve", - sessionKey: "ios", - note: nil, - sentAtMs: 1234, - transport: "transferUserInfo")) - #expect(appModel._test_queuedWatchReplyCount() == 1) - } - - @Test @MainActor func handleDeepLinkSetsErrorWhenNotConnected() async { - let appModel = NodeAppModel() - let url = URL(string: "openclaw://agent?message=hello")! - await appModel.handleDeepLink(url: url) - #expect(appModel.screen.errorText?.contains("Gateway not connected") == true) - } - - @Test @MainActor func handleDeepLinkRejectsOversizedMessage() async { - let appModel = NodeAppModel() - let msg = String(repeating: "a", count: 20001) - let url = URL(string: "openclaw://agent?message=\(msg)")! - await appModel.handleDeepLink(url: url) - #expect(appModel.screen.errorText?.contains("Deep link too large") == true) - } - - @Test @MainActor func sendVoiceTranscriptThrowsWhenGatewayOffline() async { - let appModel = NodeAppModel() - await #expect(throws: Error.self) { - try await appModel.sendVoiceTranscript(text: "hello", sessionKey: "main") - } - } - - @Test @MainActor func canvasA2UIActionDispatchesStatus() async { - let appModel = NodeAppModel() - let body: [String: Any] = [ - "userAction": [ - "name": "tap", - "id": "action-1", - "surfaceId": "main", - "sourceComponentId": "button-1", - "context": ["value": "ok"], - ], - ] - await appModel._test_handleCanvasA2UIAction(body: body) - #expect(appModel.screen.urlString.isEmpty) - } -} diff --git a/apps/ios/Tests/OnboardingStateStoreTests.swift b/apps/ios/Tests/OnboardingStateStoreTests.swift deleted file mode 100644 index 30c014647b6..00000000000 --- a/apps/ios/Tests/OnboardingStateStoreTests.swift +++ /dev/null @@ -1,57 +0,0 @@ -import Foundation -import Testing -@testable import OpenClaw - -@Suite(.serialized) struct OnboardingStateStoreTests { - @Test @MainActor func shouldPresentWhenFreshAndDisconnected() { - let testDefaults = self.makeDefaults() - let defaults = testDefaults.defaults - defer { self.reset(testDefaults) } - - let appModel = NodeAppModel() - appModel.gatewayServerName = nil - #expect(OnboardingStateStore.shouldPresentOnLaunch(appModel: appModel, defaults: defaults)) - } - - @Test @MainActor func doesNotPresentWhenConnected() { - let testDefaults = self.makeDefaults() - let defaults = testDefaults.defaults - defer { self.reset(testDefaults) } - - let appModel = NodeAppModel() - appModel.gatewayServerName = "gateway" - #expect(!OnboardingStateStore.shouldPresentOnLaunch(appModel: appModel, defaults: defaults)) - } - - @Test @MainActor func markCompletedPersistsMode() { - let testDefaults = self.makeDefaults() - let defaults = testDefaults.defaults - defer { self.reset(testDefaults) } - - let appModel = NodeAppModel() - appModel.gatewayServerName = nil - - OnboardingStateStore.markCompleted(mode: .remoteDomain, defaults: defaults) - #expect(OnboardingStateStore.lastMode(defaults: defaults) == .remoteDomain) - #expect(!OnboardingStateStore.shouldPresentOnLaunch(appModel: appModel, defaults: defaults)) - - OnboardingStateStore.markIncomplete(defaults: defaults) - #expect(OnboardingStateStore.shouldPresentOnLaunch(appModel: appModel, defaults: defaults)) - } - - private struct TestDefaults { - var suiteName: String - var defaults: UserDefaults - } - - private func makeDefaults() -> TestDefaults { - let suiteName = "OnboardingStateStoreTests.\(UUID().uuidString)" - return TestDefaults( - suiteName: suiteName, - defaults: UserDefaults(suiteName: suiteName) ?? .standard) - } - - private func reset(_ defaults: TestDefaults) { - defaults.defaults.removePersistentDomain(forName: defaults.suiteName) - } -} diff --git a/apps/ios/Tests/ScreenControllerTests.swift b/apps/ios/Tests/ScreenControllerTests.swift deleted file mode 100644 index d0e47c84fb3..00000000000 --- a/apps/ios/Tests/ScreenControllerTests.swift +++ /dev/null @@ -1,87 +0,0 @@ -import Testing -import WebKit -@testable import OpenClaw - -@MainActor -private func mountScreen(_ screen: ScreenController) throws -> (ScreenWebViewCoordinator, WKWebView) { - let coordinator = ScreenWebViewCoordinator(controller: screen) - _ = coordinator.makeContainerView() - let webView = try #require(coordinator.managedWebView) - return (coordinator, webView) -} - -@Suite struct ScreenControllerTests { - @Test @MainActor func canvasModeConfiguresWebViewForTouch() throws { - let screen = ScreenController() - let (coordinator, webView) = try mountScreen(screen) - defer { coordinator.teardown() } - - #expect(webView.isOpaque == true) - #expect(webView.backgroundColor == .black) - - let scrollView = webView.scrollView - #expect(scrollView.backgroundColor == .black) - #expect(scrollView.contentInsetAdjustmentBehavior == .never) - #expect(scrollView.isScrollEnabled == false) - #expect(scrollView.bounces == false) - } - - @Test @MainActor func navigateEnablesScrollForWebPages() throws { - let screen = ScreenController() - let (coordinator, webView) = try mountScreen(screen) - defer { coordinator.teardown() } - - screen.navigate(to: "https://example.com") - - let scrollView = webView.scrollView - #expect(scrollView.isScrollEnabled == true) - #expect(scrollView.bounces == true) - } - - @Test @MainActor func navigateSlashShowsDefaultCanvas() { - let screen = ScreenController() - screen.navigate(to: "/") - - #expect(screen.urlString.isEmpty) - } - - @Test @MainActor func evalExecutesJavaScript() async throws { - let screen = ScreenController() - let (coordinator, _) = try mountScreen(screen) - defer { coordinator.teardown() } - - let deadline = ContinuousClock().now.advanced(by: .seconds(3)) - - while true { - do { - let result = try await screen.eval(javaScript: "1+1") - #expect(result == "2") - return - } catch { - if ContinuousClock().now >= deadline { - throw error - } - try? await Task.sleep(nanoseconds: 100_000_000) - } - } - } - - @Test @MainActor func localNetworkCanvasURLsAreAllowed() { - let screen = ScreenController() - #expect(screen.isLocalNetworkCanvasURL(URL(string: "http://localhost:18789/")!) == true) - #expect(screen.isLocalNetworkCanvasURL(URL(string: "http://openclaw.local:18789/")!) == true) - #expect(screen.isLocalNetworkCanvasURL(URL(string: "http://peters-mac-studio-1:18789/")!) == true) - #expect(screen.isLocalNetworkCanvasURL(URL(string: "https://peters-mac-studio-1.ts.net:18789/")!) == true) - #expect(screen.isLocalNetworkCanvasURL(URL(string: "http://192.168.0.10:18789/")!) == true) - #expect(screen.isLocalNetworkCanvasURL(URL(string: "http://10.0.0.10:18789/")!) == true) - #expect(screen.isLocalNetworkCanvasURL(URL(string: "http://100.123.224.76:18789/")!) == true) // Tailscale CGNAT - #expect(screen.isLocalNetworkCanvasURL(URL(string: "https://example.com/")!) == false) - #expect(screen.isLocalNetworkCanvasURL(URL(string: "http://8.8.8.8/")!) == false) - } - - @Test func parseA2UIActionBodyAcceptsJSONString() throws { - let body = ScreenController.parseA2UIActionBody("{\"userAction\":{\"name\":\"hello\"}}") - let userAction = try #require(body?["userAction"] as? [String: Any]) - #expect(userAction["name"] as? String == "hello") - } -} diff --git a/apps/ios/Tests/ScreenRecordServiceTests.swift b/apps/ios/Tests/ScreenRecordServiceTests.swift deleted file mode 100644 index 6ae8f1ca30f..00000000000 --- a/apps/ios/Tests/ScreenRecordServiceTests.swift +++ /dev/null @@ -1,32 +0,0 @@ -import Testing -@testable import OpenClaw - -@Suite(.serialized) struct ScreenRecordServiceTests { - @Test func clampDefaultsAndBounds() { - #expect(ScreenRecordService._test_clampDurationMs(nil) == 10000) - #expect(ScreenRecordService._test_clampDurationMs(0) == 250) - #expect(ScreenRecordService._test_clampDurationMs(60001) == 60000) - - #expect(ScreenRecordService._test_clampFps(nil) == 10) - #expect(ScreenRecordService._test_clampFps(0) == 1) - #expect(ScreenRecordService._test_clampFps(120) == 30) - #expect(ScreenRecordService._test_clampFps(.infinity) == 10) - } - - @Test @MainActor func recordRejectsInvalidScreenIndex() async { - let recorder = ScreenRecordService() - do { - _ = try await recorder.record( - screenIndex: 1, - durationMs: 250, - fps: 5, - includeAudio: false, - outPath: nil) - Issue.record("Expected invalid screen index to throw") - } catch let error as ScreenRecordService.ScreenRecordError { - #expect(error.localizedDescription.contains("Invalid screen index") == true) - } catch { - Issue.record("Unexpected error type: \(error)") - } - } -} diff --git a/apps/ios/Tests/SettingsNetworkingHelpersTests.swift b/apps/ios/Tests/SettingsNetworkingHelpersTests.swift deleted file mode 100644 index f1a649613b5..00000000000 --- a/apps/ios/Tests/SettingsNetworkingHelpersTests.swift +++ /dev/null @@ -1,50 +0,0 @@ -import Testing -@testable import OpenClaw - -@Suite struct SettingsNetworkingHelpersTests { - @Test func parseHostPortParsesIPv4() { - #expect(SettingsNetworkingHelpers.parseHostPort(from: "127.0.0.1:8080") == .init(host: "127.0.0.1", port: 8080)) - } - - @Test func parseHostPortParsesHostnameAndTrims() { - #expect(SettingsNetworkingHelpers.parseHostPort(from: " example.com:80 \n") == .init( - host: "example.com", - port: 80)) - } - - @Test func parseHostPortParsesBracketedIPv6() { - #expect( - SettingsNetworkingHelpers.parseHostPort(from: "[2001:db8::1]:443") == - .init(host: "2001:db8::1", port: 443)) - } - - @Test func parseHostPortRejectsMissingPort() { - #expect(SettingsNetworkingHelpers.parseHostPort(from: "example.com") == nil) - #expect(SettingsNetworkingHelpers.parseHostPort(from: "[2001:db8::1]") == nil) - } - - @Test func parseHostPortRejectsInvalidPort() { - #expect(SettingsNetworkingHelpers.parseHostPort(from: "example.com:lol") == nil) - #expect(SettingsNetworkingHelpers.parseHostPort(from: "[2001:db8::1]:lol") == nil) - } - - @Test func httpURLStringFormatsIPv4AndPort() { - #expect(SettingsNetworkingHelpers - .httpURLString(host: "127.0.0.1", port: 8080, fallback: "fallback") == "http://127.0.0.1:8080") - } - - @Test func httpURLStringBracketsIPv6() { - #expect(SettingsNetworkingHelpers - .httpURLString(host: "2001:db8::1", port: 8080, fallback: "fallback") == "http://[2001:db8::1]:8080") - } - - @Test func httpURLStringLeavesAlreadyBracketedIPv6() { - #expect(SettingsNetworkingHelpers - .httpURLString(host: "[2001:db8::1]", port: 8080, fallback: "fallback") == "http://[2001:db8::1]:8080") - } - - @Test func httpURLStringFallsBackWhenMissingHostOrPort() { - #expect(SettingsNetworkingHelpers.httpURLString(host: nil, port: 80, fallback: "x") == "http://x") - #expect(SettingsNetworkingHelpers.httpURLString(host: "example.com", port: nil, fallback: "y") == "http://y") - } -} diff --git a/apps/ios/Tests/ShareToAgentDeepLinkTests.swift b/apps/ios/Tests/ShareToAgentDeepLinkTests.swift deleted file mode 100644 index 4ea178ecfa2..00000000000 --- a/apps/ios/Tests/ShareToAgentDeepLinkTests.swift +++ /dev/null @@ -1,51 +0,0 @@ -import OpenClawKit -import Foundation -import Testing - -@Suite struct ShareToAgentDeepLinkTests { - @Test func buildMessageIncludesSharedFields() { - let payload = SharedContentPayload( - title: "Article", - url: URL(string: "https://example.com/post")!, - text: "Read this") - - let message = ShareToAgentDeepLink.buildMessage( - from: payload, - instruction: "Summarize and give next steps.") - #expect(message.contains("Shared from iOS.")) - #expect(message.contains("Title: Article")) - #expect(message.contains("URL: https://example.com/post")) - #expect(message.contains("Text:\nRead this")) - #expect(message.contains("Summarize and give next steps.")) - } - - @Test func buildURLEncodesAgentRoute() { - let payload = SharedContentPayload( - title: "", - url: URL(string: "https://example.com")!, - text: nil) - - let url = ShareToAgentDeepLink.buildURL(from: payload) - let parsed = url.flatMap { DeepLinkParser.parse($0) } - guard case let .agent(agent)? = parsed else { - Issue.record("Expected openclaw://agent deep link") - return - } - - #expect(agent.thinking == "low") - #expect(agent.message.contains("https://example.com")) - } - - @Test func buildURLReturnsNilWhenPayloadEmpty() { - let payload = SharedContentPayload(title: nil, url: nil, text: nil) - #expect(ShareToAgentDeepLink.buildURL(from: payload) == nil) - } - - @Test func shareInstructionSettingsRoundTrip() { - let value = "Focus on booking constraints and alternatives." - ShareToAgentSettings.saveDefaultInstruction(value) - defer { ShareToAgentSettings.saveDefaultInstruction(nil) } - - #expect(ShareToAgentSettings.loadDefaultInstruction() == value) - } -} diff --git a/apps/ios/Tests/SwiftUIRenderSmokeTests.swift b/apps/ios/Tests/SwiftUIRenderSmokeTests.swift deleted file mode 100644 index 4e13b3f4cd1..00000000000 --- a/apps/ios/Tests/SwiftUIRenderSmokeTests.swift +++ /dev/null @@ -1,81 +0,0 @@ -import OpenClawKit -import SwiftUI -import Testing -import UIKit -@testable import OpenClaw - -@Suite struct SwiftUIRenderSmokeTests { - @MainActor private static func host(_ view: some View) -> UIWindow { - let window = UIWindow(frame: UIScreen.main.bounds) - window.rootViewController = UIHostingController(rootView: view) - window.makeKeyAndVisible() - window.rootViewController?.view.setNeedsLayout() - window.rootViewController?.view.layoutIfNeeded() - return window - } - - @Test @MainActor func statusPillConnectingBuildsAViewHierarchy() { - let root = StatusPill(gateway: .connecting, voiceWakeEnabled: true, brighten: true) {} - _ = Self.host(root) - } - - @Test @MainActor func statusPillDisconnectedBuildsAViewHierarchy() { - let root = StatusPill(gateway: .disconnected, voiceWakeEnabled: false) {} - _ = Self.host(root) - } - - @Test @MainActor func settingsTabBuildsAViewHierarchy() { - let appModel = NodeAppModel() - let gatewayController = GatewayConnectionController(appModel: appModel, startDiscovery: false) - - let root = SettingsTab() - .environment(appModel) - .environment(appModel.voiceWake) - .environment(gatewayController) - - _ = Self.host(root) - } - - @Test @MainActor func rootTabsBuildAViewHierarchy() { - let appModel = NodeAppModel() - let gatewayController = GatewayConnectionController(appModel: appModel, startDiscovery: false) - - let root = RootTabs() - .environment(appModel) - .environment(appModel.voiceWake) - .environment(gatewayController) - - _ = Self.host(root) - } - - @Test @MainActor func voiceTabBuildsAViewHierarchy() { - let appModel = NodeAppModel() - - let root = VoiceTab() - .environment(appModel) - .environment(appModel.voiceWake) - - _ = Self.host(root) - } - - @Test @MainActor func voiceWakeWordsViewBuildsAViewHierarchy() { - let appModel = NodeAppModel() - let root = NavigationStack { VoiceWakeWordsSettingsView() } - .environment(appModel) - _ = Self.host(root) - } - - @Test @MainActor func chatSheetBuildsAViewHierarchy() { - let appModel = NodeAppModel() - let gateway = GatewayNodeSession() - let root = ChatSheet(gateway: gateway, sessionKey: "test") - .environment(appModel) - .environment(appModel.voiceWake) - _ = Self.host(root) - } - - @Test @MainActor func voiceWakeToastBuildsAViewHierarchy() { - let root = VoiceWakeToast(command: "openclaw: do something") - _ = Self.host(root) - } -} diff --git a/apps/ios/Tests/VoiceWakeGatewaySyncTests.swift b/apps/ios/Tests/VoiceWakeGatewaySyncTests.swift deleted file mode 100644 index fa4a070da28..00000000000 --- a/apps/ios/Tests/VoiceWakeGatewaySyncTests.swift +++ /dev/null @@ -1,22 +0,0 @@ -import Foundation -import Testing -@testable import OpenClaw - -@Suite struct VoiceWakeGatewaySyncTests { - @Test func decodeGatewayTriggersFromJSONSanitizes() { - let payload = #"{"triggers":[" openclaw ","", "computer"]}"# - let triggers = VoiceWakePreferences.decodeGatewayTriggers(from: payload) - #expect(triggers == ["openclaw", "computer"]) - } - - @Test func decodeGatewayTriggersFromJSONFallsBackWhenEmpty() { - let payload = #"{"triggers":[" ",""]}"# - let triggers = VoiceWakePreferences.decodeGatewayTriggers(from: payload) - #expect(triggers == VoiceWakePreferences.defaultTriggerWords) - } - - @Test func decodeGatewayTriggersFromInvalidJSONReturnsNil() { - let triggers = VoiceWakePreferences.decodeGatewayTriggers(from: "not json") - #expect(triggers == nil) - } -} diff --git a/apps/ios/Tests/VoiceWakeManagerExtractCommandTests.swift b/apps/ios/Tests/VoiceWakeManagerExtractCommandTests.swift deleted file mode 100644 index f6b0378cd6b..00000000000 --- a/apps/ios/Tests/VoiceWakeManagerExtractCommandTests.swift +++ /dev/null @@ -1,90 +0,0 @@ -import Foundation -import SwabbleKit -import Testing -@testable import OpenClaw - -@Suite struct VoiceWakeManagerExtractCommandTests { - @Test func extractCommandReturnsNilWhenNoTriggerFound() { - let transcript = "hello world" - let segments = makeSegments( - transcript: transcript, - words: [("hello", 0.0, 0.1), ("world", 0.2, 0.1)]) - #expect(VoiceWakeManager.extractCommand(from: transcript, segments: segments, triggers: ["openclaw"]) == nil) - } - - @Test func extractCommandTrimsTokensAndResult() { - let transcript = "hey openclaw do thing" - let segments = makeSegments( - transcript: transcript, - words: [ - ("hey", 0.0, 0.1), - ("openclaw", 0.2, 0.1), - ("do", 0.9, 0.1), - ("thing", 1.1, 0.1), - ]) - let cmd = VoiceWakeManager.extractCommand( - from: transcript, - segments: segments, - triggers: [" openclaw "], - minPostTriggerGap: 0.3) - #expect(cmd == "do thing") - } - - @Test func extractCommandReturnsNilWhenGapTooShort() { - let transcript = "hey openclaw do thing" - let segments = makeSegments( - transcript: transcript, - words: [ - ("hey", 0.0, 0.1), - ("openclaw", 0.2, 0.1), - ("do", 0.35, 0.1), - ("thing", 0.5, 0.1), - ]) - let cmd = VoiceWakeManager.extractCommand( - from: transcript, - segments: segments, - triggers: ["openclaw"], - minPostTriggerGap: 0.3) - #expect(cmd == nil) - } - - @Test func extractCommandReturnsNilWhenNothingAfterTrigger() { - let transcript = "hey openclaw" - let segments = makeSegments( - transcript: transcript, - words: [("hey", 0.0, 0.1), ("openclaw", 0.2, 0.1)]) - #expect(VoiceWakeManager.extractCommand(from: transcript, segments: segments, triggers: ["openclaw"]) == nil) - } - - @Test func extractCommandIgnoresEmptyTriggers() { - let transcript = "hey openclaw do thing" - let segments = makeSegments( - transcript: transcript, - words: [ - ("hey", 0.0, 0.1), - ("openclaw", 0.2, 0.1), - ("do", 0.9, 0.1), - ("thing", 1.1, 0.1), - ]) - let cmd = VoiceWakeManager.extractCommand( - from: transcript, - segments: segments, - triggers: ["", " ", "openclaw"], - minPostTriggerGap: 0.3) - #expect(cmd == "do thing") - } -} - -private func makeSegments( - transcript: String, - words: [(String, TimeInterval, TimeInterval)]) --> [WakeWordSegment] { - var searchStart = transcript.startIndex - var output: [WakeWordSegment] = [] - for (word, start, duration) in words { - let range = transcript.range(of: word, range: searchStart..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 diff --git a/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-app-40@2x.png b/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-app-40@2x.png deleted file mode 100644 index 114d4606420cb4dd8c3955d572a6b98521254b14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8759 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 diff --git a/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-app-41@2x.png b/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-app-41@2x.png deleted file mode 100644 index 5f9578b1b9751ae556a718c420ba5eb510d652a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9281 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 diff --git a/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-app-44@2x.png b/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-app-44@2x.png deleted file mode 100644 index fe022ac772005f38771f01ebf2c64828d6cb63c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10297 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 E0Y?}Ic>n+a diff --git a/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-app-45@2x.png b/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-app-45@2x.png deleted file mode 100644 index 55977b8f6e75c44b1def842100ed78b0995f3067..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10544 zcmZ{qQ*$K@vxVdA*c02C*tW6bi9NAxJK3?#i8Zlp+xEmZ&U=2qSGBtPzAv6$wW=eP zfKo{Cc<^9gU`R63;wt}5v;Qvu%zvF{=g=4ojOJNJTtv+y`%(|iM{Q|I=(*c8^|x6) zgbYAOQ*0Ft6FR7n28+gOc6qr=Q-tBIO(#cO*m9^kAf-ZGM-!l|n9Ei5e~Z>}8tx?9>8iM| zhv(HG&-hD~_x>5jCl?vpS13L5gcjxKFP!28QG9 zuC0jzfyk2+V{-$L0h986yU}s5+=8QPG@Of+v>`#EU>-KHTM8>%%)X;9mXA;Ygx2E8 zK~;Uk3Xq19szM@UVD+E|#9o|$8p3xd+@_9-alDp`0*2<2Ff^hZX9UW@pIHdHJ)M5* zb#hGAoZ2KI_|N9%05DwP<0e2ufr6z$Ll42gN%^|f(0h7`_e8u3YnOP+ z3M)J`lLM)Qt@jIYRO{!@`%rOfeLFm?U7tA{8Q8cL(e&Z+sViIAGk@#x$9sf?F^Zq( z+>riI{erV2L?%PTT>{H@mp`aAAiB5#p!;(Ekh_oa>yGmD@vxWF{&Yi(DwvcHq}Q(^{CKZ0 zfCK;2{#_lt?7R!bNJx{Uhzx_g^Zc&uHI=oaaV3XE|PeHf3_q zZ`MGnv0V%W!HB5!v8se$<%ZWZ>I*!mK`oY?f%7Gi|LiH5e6O?xktym4)odD0Q`CF% zGwsfVzEQr9o~E zWtb?K^c?Z=U@3|_{OI>pOQU`-P+i^(xYsz@Y;^V>Jz5G|Rt`-#{&8009}dvQWgI1j z^E7q$XnN7l3!;#cO2IB&Sy?%U07oq}iL^fhdA|wO9pZjT#Uxh!Xn%&{Etd#^N6?tv z!_NKkjjI)!Sv)&0XUu{k%d!aGn5z0Ck+xQeVlab$HUMTK`FMh^E&C9Ei#@h-2lTOWhploDbnp z{dXHr*~ze`jhU-!`)EFLjN-IDvf|OTb7h)AQG>tb(CzoQ*U4g%Y*kWL1y5g(rf=7o zpjQZs$gU(d4=f#Ev4~~sj}RlK8FiYb8N>9g~D(%_0;`Iax3id|OBk25{k z)_8-uInH-A%X$kWsNn!1sDU9avhUupcyg5dys4)}RGo&* zMlUxew!7k{q)AX{Zfd`V^MEqBw5rS4T;g5*ZEJ==1OqzqfmVdkRT=*kll|G^>zj7A zZ18OSpnLoa!Gr8IN@bT)#P^#0zCV@0HN!An2YfKpga0U6& zlio=P((c?Y=W~1gIv%#4(Mg{7h++7A;i&pbO3e9p?i#)sH#b2!&`dr2`IQ990|diQ zJ070GXC_=%8GmoqWBA-IB1Ur1?ecVUiVohR{M|=Zx``q;sv*w4lFozNy08PHb*Zi7 zeY#lpI(4Yf_Sv>wquPq8(|UlJuq1_|zhhjFys*bGYsxp#G32DzS2+&gZi5ygk2yx3 zMSlI*8Srd8csvnm`f;pp$iNf-d%NScyk?W*dtbNiV(S)L)zPTlb0-%r(w_g@5$!}E zrkm86yBDTZHC-|yFP0#WTxtaM!r6Q$nlrH9<<~DQ{jt&@i%EvqSBj0ldd|Mw=i6MD z1~nZpuJCqqz=yaDZt}p8L;jVlylgIl2x^>r055ZhGk50=m$i+=dyV7k2c2m<3FU*? zRLf?Dpu=!>tUe!f0{U4UZ!L{i_TDB3EJXJ4Wn0Nx^DS~CR###hq^*{*Q+S|KwD{wgS7 zPx~RI3WhffIgkMY^#2|P_DEjud}b9*5ygzxTXf2yTJ#=(m(k@xB_hVBxDNXPy}Wo2 z@HuDibZQ0jpg*`(hdm-_q68(DiYjG)qzJk2#gAxg5AhUbl$Q?+ZgVmEHhF(}`7_XMBm+o6fEQ~E8K6GfI0vpSp-92)=95MP9}^R!t#qf+UP zCR%2o9H31fjC{G4`-1@gy4CfE{s9k9FP=4v%c9patVV;T|3k!&hVv|mp@{~f;qFJd zYjf%3ULMt7-nPoT7TQXauBkj_=(9a68G&$%8_Tw~D2WA-ldht0=PpvBQB0z#=&Fi}p7z?|?wELSL}gb&8%%j`hv`;iYGplJ zw&CB+>okDEiYUqH;-tYj8E0`wQ0@(@Ij=}ba`)H%Qi6BSr+0pP6n;T&lBvjlRF4uS zBj?Lg`p>WdSzwnrjfmA`el!ky$^BN=2mW(boRpmy(-0&P*MLRTE7`cnKKDBLMK{c^ zjwMb>vIQfUYw&Bg1oZ#fjIF#%JM; zXEL;Lls!zQ{mn|Wu+Y>m>Q-qwQc|LXuspGPgR{riVyd#C0c_RZzUSKHkNLcQrEq-1 z1t_D?lH^Gq42P|t*l|9T_+}2{Yg9e-H*Zcgugl%q4+_m%TI2B#&+mFdx>g7iA@ltK zX1$dnLgYRH-(`$0Y=Mv2!0%20hU4IDCWtmZkragpLvBlAZmSs)y}Sd69$H z`1u9gZ1b#ySAeux@z_ZBhJVhfC*SW=eX;I49ui|)V;nNeibKh$j)5uxr|F`xdnDAm zRvc7s_|uoB2DQZLSy>yUl;k%%LwxQ}12fwvn_i$mTwL}TRA@3A2`6S#pLQR>5=F+} zAfL5|FCC^U&)c=!ajc%tj#7`#x8M=gTjR&Y=+zmmZ~2mhh$80Yzh!ZlLs{mrJWwyKfv`*8H1Ms|(!9A2Mg z?cnAv6km)8W{nZb$qlWoVX*a7Pm zd2ulsCJv65Zt!4uWgnQK`|?N#r5+NN0urw7{~VT(bp+9Fc%axX?hE8y^J52e^_4&f z#myF9Z?b8}-6jwSaoKJd z2V&%3u^4!#Je&=iOk&@8!`AK1M0rI(;;NKt>Gz!?j0zhcANRW!eoQi3WMoDe?KrK1 z2PA&bOH=)Rd=0X)RYk%%ihN$%=1OIY;$jof+>}pvbCgSJgewjdZO{DXnMj)LqjP*x zgjRq6CnE(7Vsz(>UjrIv)@%?ei;}n=j)SX~Tn!)MkWzHgApWIm-5Q$&;D*;UbMRuC zj^elnx0&uPNRyNA8qYTdTb+&etY5f|b6ke6bA%ZTo0v?@ZbPc$Q70;z!14DI%R7q;w`{GcdB&F|kX$rMfsr;umaZYSam+~!|}cuYk1 zgJXE?qj!##01JG?cY@H4qHO`BUxJ^J--QPB1O(V8(__$P>Y0}0B$@$?M_o%5<7#m_Rn2hKaHAe0VjAceXsE+Y(fi-| z@9!XXLdLR+=&2H1S)5TrEK5Q-Hwy3NzOEBEB)v?x$J{3@aZN_|KM+}MR_jWH^8)3{ zkmktn$Yk1!2mU)f1N70`BIQ}K*E+1$6r@OiAQI~FHv)3IzR=ob1KOo!!|lyp9O83o zhx}GKsJ~c1Ja;5)C^I`NcAYyn{(y*NQ0Fp^B{}P*3;I_CaBUuI<%L>)`yieY?R_~E zJusutI3ktPjAwtzp(Pu+$3eRi5$&bS1LeQy1ahX=Xyf3w)_!J1uOr422w-BAkSHzS z3v0{R_0xK}&C$`$M{zcR9~efNk~DDFVi$81`kF>0bTtPoO!n&32clq2((pTwj4`Jv zN^?Pp&;U=xq$Mu*dvq(ZokeO$33(%Q1QS332{q+&WLR16$eYk8jGhZ%SZ0l>09&_? zE+!dj@o)oOSCjkv#oEFmlixC`v@0yDi;lX&sI22D5r8S-7Dq$j*>jSdsI zB4K0nYs;Pc%vu#wgZyQ7M5K;@qd&QL>$WZ+?qTEMpD?l#Lgg`TdNT%JPHvO3!AzU9 zUAA}8nVTaj2+V8*fCQa~?Qt9U6VN;H@h&BZcmqF~Wu_Z9z9kre!*`EE_3?1f_l;{3 z!qP{EijIaaw>5V=R5N%u5}o>W9v-fAwEo=4hC^_r!L z*;q8BPmz$r#h9aURs}w#l~61I9uMq85;k8pdP6<>ZAms1+NXrZnu{SRemm|v?acGn z8T(7@1X|(25f;DjB?D&IK6|a1a(4Y)IMU>|QERaWh` z(;t9Icer(z1Tp)#=ouQGeOl@EHz&WgT!T}he(=8#ZBi1VN9KUbVDw&WbP~vO-ZJfY zknm3N2k-1XYq^^P9t`B6{tAiUzt!;jyG#A(XctXflA`>PZ(RiB_(w`YCOPx- z&UW)(Cw4`}Y`ik*&q}e&#v5Lv|tfJ^D8*RXuH@w1@q-ZdN0`>g?Ha1mVuB6~S*fxcLfB*<>aX@AJxK03ZDsNS4 zIe9b4p$;*KW1_NCUow`q>3_1or1tEume4Z! z&wvV<;&BE^XfXs;SwhWymEL=znwN|W|GcA2)7ZZb%ec6gw+gi$$l1RSG94y}@P9Ln zX!D1YgowT7Pr@}$s|g_b`2{y0AksS^#TZn8RzZV@YH;6LccQ@9{Q>wZi8(468I(kG zTDNKj8q1!esg%HcM?!p|lK1Pr+B-5yymI{F2}j+k>*V#OC*#MSmB4&*RXRb$=c-}- zcdPz<8cmdYO6a_;vh8n}!NHoS-3Ig|G0bP<$uElF^tDKF+GV9WoIKVg>=o{M(Ce|w z)=HFoQ{%9pDk_G15s}4(VEH~_$1%cVfgv-SL5SkWLm@LWK)TB}A{iVOS=@?)=yT>U zg3U!Obb=XNO7}3lT;KMf4TWdKBUGh^5ux6rKw(8=@F&c%P=cUV9^jPsXzCe7hwMWKRY*#SN=B(X~P$*e59)b;zsC}7uy{wP8|C%G0nhqeD@YE)~qZC%2g-M&;wGKmkgO32En3 z1P(~fStWJRUPs;ah|bqSv37g2Rk_`v25{^}PFrbxhki@~*2i=Sta%X`y( zk=3~O5)zIV4JQkWi|RSorwdLJI8;Jtm3v-SO^yzgnBHf===vFT=Tb`aPeEV%q?>0f zdpcFd_mY`i(zg6^Ljr18VaMQTCD|omFeq;|-gJ3k2tQb8*1sF zJ759UV$TRlPGx01H**`<3xz>EH^&o6S8lY`;LL-<-7hURArZL4B4(>S_QblJ&Lw>W#VA5=0DbRAbzx!+cMeg*k>vyE zz5dI6f1(4pB_9m3R1UNPpB6a|`vAFGx z!$6~=L2LZLaEu;j%3;;wN5#pL{`9$frknrDPWZM9>U30r1L8BnuOv7NaVQV@Uojcg zuom(*xD=0;BtbV#nY>R~hZzkm#Jjptt=G@z@;iP!Lvp8Z1vn7O(Rsn62qk?6xxO%8 z4l7&LZwXl)*kLG&!Eaa-z4yb>!enG|1wOOCTO494PUN?9TJMO9`mVzvd91^9kPm^B zQT|YtWyHO@kF@`>=eIh98A#R}5`31$D^_G`*U_2rr(gewVugjrQ_9=`pd2N)_mY=c zYDL?$l`#j%D;U;_Ebu*PtK#|ZUDTCw={BFixIqHW1)?+35hjL_q*Iw)nN_}mp0MQP zI!H6?GIRVa3I))6(N6-Okz4!&sWnvqs-Il3KL)`ryjVocaHRRV*M@Uo(Gt6VmsG6p zb69S7%nu1*oU91bb@vKD9cS=vslIA@&${2zCnnm5mQWXghETAWHRmdcVbIuj(f+SUbhJ1$$^v za8Lp{X~_HE-t1VS;2H#1*W?i{ywS0~5U6qc7t?O~37E4#>K}5+fgN}SSAEci9Uro- zcZC@aMt^}q@R6Zm zg*e6y78AK}RLKONCY3~GN4k1%wVWPKd}YbxQj=W4_SjvCnA9fC*`e!^j{UIH?uB;P z(%POaH5C5KZgXS#o*-h26xQDe>hu~+TtqwqjWL&*kwN^F+t~$VOQkjYhU~zRE%ce- zhj6WB1Y$}4deLG&#`y&{v_km&UA=qBC3v8-EM!8*lw)gIhQ;qERF+PLe1%s8Vyvgm zF9T~nHG1c6K_V}XTqV=0#L<$2f2CVI28#l*zQ}-)+4jvSQgw5mpfAf>TdgApS%^n^ z+^dgNm*wj%n5b@+W(R>e}`7-u#!#+WCm`FiZP`B^6zGYi^XD9!1gWD8V$=iD6!+3q) z;?k_tlQ(qb4lJX)3B}9=+hLp;3pVb*t*4OvjT|u}7!1oD@UW`rwI2Tf23|MB7VSXE z)qss6;RekKNCEFlMDg|QicZTpf7Cw62@PWFJsY;8DmE&DLfQ`+KEZwIDd^WEb3aE% z*{DkQ>up!C8#2It^gH{K+51H>yTKK(gKTsm@Gp#dY79C2&GuN-Iu`Iq`*yr9?fxEG#>^JI)W zhg)&jonkCY25DLc=Oy~q)9ST8?&DsE)X%GSPX=5TH@VNo41?0gYlE0}D6r-bqF2oC zU8JZvCZjhND>MzS2Mlz=f5gq3^tpOq3E?e=pHTnq!wS~nqOxTFmXfL z(6<6DVzq~#jpoKgh=kqMFWE8@d-WmG;dDRWGl|oC!m+W|Z+orH;oCwv5^+^0-K6&R zpE*lEV+`k3NRFI{aJx(w4EaEKkeAap+nJkAdV z1C(`AhQ4{uaEd1RP4eYCcgv5@?s#O?+xoi%Mabd}8JW7WGu;fPs}pwL2Qj6eyzVP& z^IX;1e%k@_tnIzZ1xX9)sj1%?650Fk8?*Sj;_I5pE)z7l2m_4t_QX)=({Z$vGjUs; zw26(I5o6Up$k;mqY2gizsD%pTjpR9oh8u+Q`m|0BLXAE3*o3GrPqa#A9bq$_27;JU z_KLRabgEgE`qgBP6?j+lh-$BD%IBNrjgvGD_)13RD&z(QcJx3qu_K+SYi~`M{Bz5% z?a3gvq_Gg9#bwV3dP>aSJ=eplMe1o$O&sN3mIpznKlt5;H<^^o`_>7q~c(@VjWYtx`Nl@(;kh1|!jw(S$;f;(j~ zOWI846Fn8vCUDCwazna9)l+0;ZCc+>e7x`fOCEh2d;!&E< zED1d%B&*xP2v=)CE_wYNS&vd_i4$u;%?qBb+_N^`c#3oI;=C8m)8*;Ba1#)VHMXZo zkN6(q8yyvil|?Q8RlD>001|X`#2S_fAwI?D^Q&W8>H|0W^Xm8chV`uZHLrVp7=4nI z-1i5$L$48{2tqU$GxQu}X=dNBbhm{qDbdsWz(c9+B3~4sy4-d^EI+)^ozN`%%;0`_ z0R1Z5*9cf5uKXu2kt2#3n$DgwEGZS;sVG}+-Jcu^=dbN6vl9_9-V7xB=uGiP5Y2;0 zppZnncqj69L^-h^5okCx({{69o`U^arclOlD0E#T6xow$NKd61Vb>ZvZ#rVS)}Ag+URn$+mp)-i&_RD^(0Xw~sBQ~~9kJsOsjx20R57XmbM=yG{#684&(zt7y zG6z!c>&e71EDX0ZFZN=CdudFEhrMCsQloQ30!njuC2rG)W6&p`CsS!QN0cqC>JmqV z6mC!tNELqVwJly%55hlgUL~#Gug6R)gv1g%_({ zRa7Y$R0zuKEctKu2`*)5Z%K~!&3yE#8L`H9hU<)Zs_F}}1 zeXqkYT(N@#0n(h?BHxCEZzz*^2co&^)s0mgjC-|Zh%)*vg|c#4_Md*U$zUFz;N(rA zBna|}TJo%b7hmIgT+{8R#RR_}AQ3Cvsi_nG<=Yb}RnO14 ziN5n3il~0^x$87k>Vl|5DeO_V|3Ih69O+-{_o5i8=|69AVBVjcM|eAnozvV-GroJ` z1E{Sf9?Qy@eaTpuiG$8(y&1`h0et~*E q^6|^x!n`i4z5IV_w`%Si@`r9km9&K|#ebiWU@{Uw@fuOXp#KA-BzqMA diff --git a/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-companion-29@2x.png b/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-companion-29@2x.png deleted file mode 100644 index f8be7d06911e9d8564e96c194fa78ccdf49d71e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5032 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 diff --git a/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-marketing-1024.png b/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-marketing-1024.png deleted file mode 100644 index 005486f2ee12c76078004af2df84000ecdd55761..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 206341 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 z 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

90@H{C57B{rTY5(Nl?K(BLA{zS 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 diff --git a/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-notification-38@2x.png b/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-notification-38@2x.png deleted file mode 100644 index 7b7a0ee0b65b5255003eeae7b519387725402b3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3893 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 D@>h5i diff --git a/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-notification-42@2x.png b/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-notification-42@2x.png deleted file mode 100644 index f13c9cdddda0fc5206930521af6bb19e18f102af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4673 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 D9@*eR diff --git a/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-quicklook-38@2x.png b/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-quicklook-38@2x.png deleted file mode 100644 index aac0859b44c6e8e5742f6e962abbe64a7615f5d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19776 zcmb@NQ+Fjyw?<>zwr$(ColerRZ6_UfY+F0rv2EKnI(G8C=Rcf_T6I+yYgJu5V~$x- zDoWCbaCmSaARvgcG7@V4?KS_mV4(i1C#=$IARvm+vJ#>iUOCr>&|aFFEk?fit{>Bi zq~RE1VsIrY;4u zBL5u_^>O(SJiYqralb)?fs=~?MMycSkRZ8 zLr_X>0ZM~RN!eBI%R>N>=7~s<&$qG|UQ&vhvqT<#yF<3N0ZdUdNK&d#Rv82<1wrKe zCGC||7WB|})Vhn*5U7oTfsO88*XUWUI_7VZxaXV=bZ7-}zz!O9H8{hZAz@(vvuSmJ zTUXU?g}A>rc%4BuTy)u$vi5a%H=n|1?s8mf{tZ~#^750EM(HL}DEeKfRP2wj;>SSX z(V=B)>{C>R&SAT$P{zo-9pETF_r452d?F z+#?AQ>#)_XGpV#u9n@XJTxL}UY2I?C=`^u zc2iehg#R}ixY1en>(a$_xaQN3H`H}H(%8?XRedQnkse@FZe#HI?G5nwC5-cemy~>1 zsrR-{ERErxYFoz(Hk$YTpv({GKKD-g`^gI@Z)!?vUe1M<^i%byJTv{TGe5z#1?Wr$ zC%7?}qITfHBNAvbOVHxU-)0Uef>IFb3K^b^r&tkseg`XP3df@&UofKQDgldePVUMZ zn2$pCf$@W^J&A?s9q70Tar3T6mBE+-0|rT#Q-Qd&yJOut$rhT1l|oi^wQjm%%h_~S z>A@PWC6VwFp(3~JySO6Ixr1Uu_V%V_q(}Gf%I@~#?d`rL6nb>1_gjqA&VZAWhGl56 z{?|GF(ZprIh^q_DDD{azn3e#sX{p3=LY{b?kZ<>SXrSO)PjAY;nYEp@0m_LpQ^mK- zdiT+Ut?}jiOx4#%@kr0-5_nd}Ag+hxei6wYQ6lkGHa|m5d$t2{+j0qYl z*wo?v`y5L@lG~*Z$Vzhgek2@GI!(hMW}m(u460K{$F$>Weh+VXmxgEmZh8rfR zC=@A9Jh+N}10<#)N*enn?5)gzpE_X?Y+YmS!C%I4AMQEOrFGw3eQn2=kkgnJIXDP8 zd%irbMKnP)E}rK^Fm?`pNtsh3S@FR~ZXueg7^2mfO69t<*b0f>CMtjTayYK*>1ueo zg`G?_MKzL>F~B$mgL8eKG%eEk>^-C)@{Oy6_q#{;&aO=OI^AmkK<^qRGPZ0U!Z|(H zFxAlh>h5lOQc@`LM0(`AwV+>w!s+VyzJF@#RdR!02Rv^${f+7i z&Nt(TY&b&bYPOkR$f+c%$)C%lhE=^~oOyDiC1}gRX=(^^Hx)pYWxR^%Nv~-+`~GJ0 zm&|wdgNa5lGL-O!dFlN^&nt3c^v&^6)F}dC9oe= zO>HKkNL6TY>cMMueeauR_&tAEA;Ba3;_C{~E|&V62R;|=9$9z2_C|;e1}14zuItg& zDHnX<23CmSsZ#|-#6lB`8%uQ%FTaK*eA}qJ1o}g5rA<8d6Q`c%aSWutLY>Edk}B?d z%S8Bo2=g=!=3>^oZIB|*dH!aD3gHdfc)3mq7u;mN@5z{j)-&Pd3niu)vgd>ns+L#M zY@2j1(mzjetk}SUB4}Grq6ABv9};vPIXxB2>z^&+KC~-IC=B7_a+~hgeIX!#gQw9p z|0SRMh=7ZG4aRM=F4|Vpv~4LD%$r+)o6Nu`MUA;9AI`geTJ!zkM)_Kr&4ZoiyMOoO zb`H%hm=uQf^S7~@2V@adtR&O5HFfuW^exjG)x+;eA)=eEz}tIpW8}Jrm(&ooq-o9n zHIrcGya}0cy=J}LB1>ND_3tk6Or{J>dF!X!>Gv=)(-=ibF>}DWkRgOr101ZX9Xqo> z)n3wD3jftvTPP{`jh-M8AO=U)YNMo9_Z*dLiNg|I%a1r5Xg<6!o|@g$0j!qLKbjlNSkSm`lIj+PN z9w#dy99_d^7Tqmj;Fo@~4`8?0z$Ua#{!u1Ir*}$-L_97*nSs#uYb+*p{@i^1=}OL& zqmD%KcW8hA@x6)bYc(Ac&GkOp6H&y1_C)Vy+xdzD-uuL$z%+TLl6 z-*1l$KQRkGz>%ip%35if(u|eqCR1yR|C;a|`R4?JFo1yACK5E!Pg)C0td~DV6(;K8 zkw3cNsd#W$7!mmJR4cZP>SmgY=Szf8G13)ktG*D$X0OG{B>4hnb=^Hs1fS`T+cmT>(nDnQ~4%4r>OROu;7c8($U2a--#> zAc=k-Diz|8&@*4;c~lrhBu&C0k)fhyO-V)k8fiT=OnG0FIR__ateh8G?n!uQsbG9)-6W>0R*&Ca zX?Y#|Zo@wKY>y!r4uau4&a$!$2cD8m)l(s39J2lBBVk<{;nwASoN(E%Tjl2Eanwp1FL;wYk^c(Y$V&G4hqOBQa z*SdJ319%@W1tksWq^)t2oZKlET>h`sZ)@wm6mk`+*66*^cGZJ$@ggYC4!p?u#v}N9 z<0?Ma^V{?OI59CUR2Jl=6t=%L`vr2;|M|dW+7sWB7t@?Ow?YSpO%4NcDC{U=Fqyf> z=RLG{eO>aB|NJiv!qHooz%=4p@0(t$^R!($1G&BpO-Wkl;<#J7v6*{`(mOeXPSsZB z;kMaf(hA6n(BJONOLiC7E?%Lq)LLVIvx-5Fe9KcV?yhgYh<@B;zA`#gZ#KH zb`q8F$?0Y@wD7dGu+{b=6`CnhiqoM-Tn=LyrFe}V>o0dwdg1TB2HVbf+vXgXokd0U z?VKwU+9;YGJYFL+2QB2Tn z*GN{$7Len}5;5=g6$aor=Nx42k&;);$T8mRnJ8Vg)UlA)6iKO+_Unxnzs9nZg`8>( zD-VsN*3UD3wWX`ZHjbkGw(o=oX{quy4-FT)Wv;AZ7;r6#J|xIjs{ilN6r)IXmh-S} zVEh{fEYkzX;IZy7qgf>0^g1? zmdga4*+a9LO-Gk1lh}T5QI905j$sqA<@3_D!w(}ke3FF zt6Uu%l6*m=aBMIY$aZVEeF9A1+~mioTDJB1=|j~dR88Nkv9=Kld?*NAugRdD`*;59_SV-}SRcaxE*YeRs+2O$zAC1`06k06(Dsgtozqvf!8s>Z zT0dq1&5rFCX{y7Fn}Lq8;>)}0_x)IWi`NR6ZQ&wHhRjtubIHyj|Cb@&RO40R%H7Tb zUbPxSs2CUR{K5S~@b<<0UFM_E*hC9wuNBaf)whnqYaL2W>mRvu>5tRG0PNYUZ=A{? zqbE^eCbzZH74E|=c3G40R6oincd3Vwu&GM#PD!U0m~6k9=Qa*lZFU#;@b%ASID0Dc z6yL%|Ajhw0H9>F^KeV#Z07JeBIQnPS>uXS(lze@hi}l-bk(bs~OW)<)m4hpfhG})K zjiNK?R4TpRrj`|wA}YTZ5g((5Gb|RR&ta7%Tk$tj`cwqXP-HL|;z>xXd|hPcjbI6r z=gzy{n02b->tlENG=9&7gP;K=JXGkKWuxGR#u+3m3{Fy~EI5OIf{ZhgMm73|t?f}k z5+U+x*SE5!mA3~MV}B$+clu3E%bB{TxkAIdRe{}~W(FJF6OYL$Q|&*COj%P{pd+O@ zoTL99iN~fiCOxuMx&V{c#@kF%0`xPHc`JS|ueMe>Vj+yT9l}qOpltA^ zM-R>M7fEmzs3j|mP5Oyrldp|PTVX%+v4k5xi0Sg8C5QM(Ugzk_qsREyhx?|cZd z$QL0YFH+U>Xoq7miINh*=4{%)A?jNW#a^$-gkX=G;7|wBMsbjTqjdzI%d(jKj(=Zn zQ^Vrp<=ypHjc@ttk^lS-S^z3TMwC^gWGr;}_ZM-45{*Q{aUCB+#_9sEDDS#g8wHnB z@c@h9yoT|*%zfsPuy9Cde3v#t3fwqIcOiCeiHJ7KIHYtd5FeiTz1}7)(e{+SM<${B z`&p&LV7iawnpUbb(J?Rfh*i}M$ytL`I5lJG7i?~>gRis@Cx)6k{VC}tQ#_;hmDreD z(pLBk-^04d&RUo?a(+rklu~NoAhVUsa0fAnF-^!e60ExSLTKPUZbkSb7#I?z&gYv0 zNl7&X;s9OUh5aH; z4~8R;31K12#?Csg;-oRjY{Ef3r+xgl6!__sta5;R`z2?I@(IYm^wQWFy80gQiW5)_ z?3j8#UgqeiC^O?8TMC><{GjF+brD*X^3dcX4(*4GA!>G5=VGhW05z6XmDiPn5kh_Q zUu^KFlr@Gb=0OD}B(#U!OtsA%JFaVb%N@JD>G^eVC*wnRfVEdxD9M0tXECLh^v;am zah)Fic-6~a^OqZZ{$4HGefs8XF}2w-B~J2tgMsY26XQvgb$68VWATXidHBG<+1jo` zCFy@Q(0bzscao?n?^ufK#see}2cM z1qEfSMCfH+ARdS?Q;!{TKtaJhpS9JE%;vQc8E^FZdH+5;sY|0P?F7qIx@A0=M=l?* z$|I}*&X~MwD_3$Eu7eO0^I_y^84E6~|JEKtY0?ogwYf$N4rZigk5|!IOG3)fZV{u5L)2@cd>LGcu4jQsuw!472ti>4o=#hwg&;MU&_bOmoe zo@sQ4g?(bMS1WaRdDciMLI8__C)@)2cVb3D%wT#Hg>9afJ3T%C{nn=uaED3oaJ6%z zn!C9TABTAL8(wG1DpK(GqcBS}@b)q_J)-vG6MeQ-G8pYJRt?mX=F5#w%xXwx7&SYH z3gzhd_|9)PVv;(x=GXD*iw@lPlkdt77Wx22_}Qb_>q?wOr?Kyy6bOy_qSO8TSaE{T z1d<={GYQqW`=L-xUyuwUW*xT3=`@S^`PlDm{lQt=Am+_-G^W_y8Fnm|x7Ni%wh0F1 zU~-u6HZt+ooCrqyP2Wz#9o|>8y*xZ1i-^#_-e$-hF!o%k=vOG@hQ`GoCS_ z&>&L0kHpz-%LZO_fj(x+G__hfbbH+b!1>Gg9~=+f6FjfLA6IjDp)q^tm zVnJ<3XEK_^fZD!Q8?|?^CUvucP&f9X(j=_c1xg7FqXF?!&cJt))Gel+ zM*nJtO?w;80ns?AmpcRhO-wulqYt1y=Y4QQ2QFKtruF$t)Nl!{B-C%%o92kH?_B!m z3*VdFE4WnjJBsWHNGmd(!^d|FU5Hj>Av3@s_RfFDiiEt5$HChP-VXGO@gPV zGynqIG=9k3BA5I=5ZJ^-`1Q`3B-( zgGFDe>z>?tx&$-_H&2Z_S2+3RowFEr;n4_Qgg{SbL>KEhXopE~6wT`eAi-geKJY?9 zAT3?qM+8;19W;ph^SJcGcT%*pjISXOvL4?=pPosJm7xDd@Ld5n$>$8CvV`m}mf~iP z?(*@)2WiwV%?$hC1|}^}G^#_>?6ZG@@jcUW84)u2u->->o-^{L z%GMzyrEW&T?IR2InOQO}$<4Y07#&+nj1F^t3yy9kp^q5452h!L8Wzvn{G|)%S1KTr zWw1Ju5zXZDJ?zoNt`mz(bIpQs)1U;Rz#t&K!O9Rh8kY%WLKq=V5+VhinDxMg^@KoB zixR@0{uQ#l;qq16zC~l0wa3QHA#ZyXK0v2FQFrP9%pSWtBw6 zW~&d5By**;7*M^e@ov{izq~R&=&PF8a_UhPQc$;qqhXw8s>8p0BxYn_&`5@^Z8{YO zSGV-}GdT_wKFEr)2O{J8fTMVQ^XmLx-dkS>*AK>bOtx5}2_K~<7__(x(WqaO+CJ9^ zNg9D|iRG=Mq^7RZjv0O`8*?~htpW220F$S6=Oe%YR;=R!>f%-@?4?6sPNO z2FR8aC&RhCWoQ~=aY$RJ%lvh7dEcBdw8kccKakkc)!Q3HRd}1q+fR0;AShGXwuu~4 zN;wwiH|BZjbhIzs@@JW7RJcumt-Bup|NB@+4j(~LH53CG74cm-niCMEve^c2dDI;K z_byiy_PW11k5=Ib5*WWpg8ALXr@h{fJS z(-$jA2=_2PV&8uSQpSzhQ|Hivo!|91^_?YEmu2yK_+1_k=k+t3k?onIE(EaHzbl7l zx(3s*5!MqKfLr&*$5Krf-B^4&n(ED#s?LVF_WYW19BsN%9Q&NI;7G6RE?`P2&s9^g z%T+roL1-{LDNUd>%+V~tishFtza=yFXPmvT@Ui!;PE$|Wy*p-W$PYzXA-Or5Dn|mqCNtBGjZW}{k5@a|Adp@8 zQb_G1T#)*v+qH^G0jQ|Z?q*4o^B<~eE+@7(u>S3O@f(L5RtG90aX)DgP%iH1Y+GNU zJ7wbx6m(LH0rOkS(sh&H>3STD><=|%B2-v~dpQ}?pu!$2t5ur#%8w{c12o5CcPD>K zfcf8;w!UB4u8WB;J8i^Bsb%fk4iVd{O3}|wwWEq)_V%rhE#D0N(Dc-iu|019%Usu! zUOqA|EfXc^G}91MWZ7R4dnhF1wE9U&NjCMno9FK;kHXz^`d*3+)UjVI47^Vc((^Ww zOE$E`5^Phv@YO{uwW7+`$xQDyht1iIt}qQxWkG-qXDZ?R?)F{>h+19&StIhq~= zM2sw^7)c?rJ$MgmaSw!Lzj|{ZGVFEHyPUa(qaLvK?m_vpi-h=hR0}cAN2fgm{fLxxf_btefpltwC#B3LHM;vKG1MAEs2UM zy=|66Og-PAG}Vb0pUrHSp+JD-FxC;v!#vSpdlClwF^6$h*!5ny`{evfThF_#;rSn$ zwz!~HosgNoE+}Vh4GTAl)YJPSzrtOU)#CE9Q!?=S+ioU&rz{2~Uy$E-r)$tc)mb|U z7MHV#VP7jAd2t#`RVqyO+8I{)7@h2cOFy*2bYA$+u_GK@*nGP2m*dA+2C@Pcyayky z))CkfR7Z}1us@dDO!om`KAp*{$=7A8Kz4b8Rp$0g zkx}m=(Y&m#GVd)NXlz&>(4C&E39}Mpm`-o>8M8~|{N;5ApEd=VvRO0efL?}n7$7Fr@m@S_WFY7x)h-z_KRc+yArR$E*?A=D{&!$su?DCQ^ zS?9gD3SQ7EPaRxD*3u1_k@2w4?x&lq$JYIEaZxR3FkG6~W8IqzHZDYrQM~r)45ifF zvDqwU&ie8i9mpm^>~RYov)A%ogJDEFw1^TnNa`eaKUfTkE-0;-Vt2+kh(Z1dH ze*4y?q-dGIA*fxa7Cz%t3?EX$##WwpncYuyj&21wrq|~!Bbfm zX|}Xz9f7>~DqyH<=GfOp7vA?hMho&UkJx^?LF6o2Z-m&9`gmwLjD|=iK+TS$@pg1Z z1Seo=8`Q2d@K7lj^6vvaRx0q<9_9dl9(t>iG~x*s-fzO=!DI)ux2ma z=pu$FD*Z2pUnq87s$H?PB#3Ol#Jr~B9kF0Bp*eHlWTtO_?tY2oNx?Ta8We9gn!b0q zU(T$%io3vRWP2=yRJ&}}bsnoeJg$Seu0_lUh;(9Z#_(Mg(^bp-~dG*o_rmKGb9fTxy3W;55O>EU09sv8DOK06<}Rjmk=&r$B%=qWk? zcx-M$417;gnIRM8(KB5C@j|zaTM)@&nIm(S#ba-nB?qSQJsd3Cyxi>E5Y7YzctgOB zpJr%q*~}*pRpxWv{${iP?Y&l^gPPsUy7k9Yy+JgCXM~sita-?W!{77q=3`gHG+f(= zm)caaBsI-Pe=+b`G)KiS@yMmxP#a3a(6o`KmIuf0sS){P{|DZ+OY)B|Vv!GwhN8aU zOJgr@vGi&*1QZkYl{pD&G%M8@8Y}`l`cq~)ag$NYndRNf&xHkWSD(1k^F?`YPopBa zsL|1(^JTEx!eaBhgE^pbTiq}Fd#tc;<^*dmq(CKZWOK?hh;Xa9mJn~XWJ*=ek`##p7FuEHHqa11a3rik7gp2HbcSpH@bP0*cW3U}_V_20P4 z#n-N}vx3o1Uv-rkRN=2XI(|5)%`UsZzpV4*&&lyXu0}%nLjy->e=TC4`yVwN!6z@Q zkU6I_UBY*A9F?}vx3>1Vf3I6jYFxn4MVYDlJhPVTI+Tk@6zAxL7#C+CB?aqPF3I5+ zUiTf`PL>wFKNYSVh=#i&kVnmRhhYIxxhyy zTxFFh5<^13Ocgfq_}s^<(ONv~4DarUhbcq!jbPw<)M>>x$UEl0R>L;F9^ z_!8o;vNF7KsXz)SftHeN+HY}?hI0H^ja$$@oYaE$wSB;X$#+m^^ftI!&V3%=etApS zFVE`BKZBriB2;5M*VU6P+CW&WZZ{V5x)1nUvoo)6e39F@DJi;(${qJP+`ro{x=Xn+ z4vzA}6(z7II3*$DR}r;6ctq${7%I}d!y84F=salH*zJMt*0l2jnx4`Ie*)gdSL+P! zDM*JrCOqL>H4s&wy#VpV01Cmz8Yr~2bdlm?u?JQdo0^Vnlt#SG(fmi+cyc}+HMZSm z>tluYi{w^oBw{%S8(YmkGa`vnJ9XCbHVY*p=8?HEO8O#_PGXQfV3#h|`!S^i{ELr~ zomH(kXtx3B9Oh69T(ffo0vKFkb&+ZuJcVHbx&!0k_&ol1L zUR-ILszZzP$xRu@dQn>UPJ^kr`NZE_ovt}Hw&XuN%-TRi#m$&sXA8&<%>X^B=H->K zMiLheP$-vg6*Khi;I-;%bN_KBigP#E%L4i?(x~miIXqASHw86Ur(cZ`o3%Fi4WQU4 zTN;JRscOSE*Ug=e5qwWiWmI|TnU#5d8WzLA-^1)`X%-5Qc%PUs#7uEm2FIm2nyI6e zbrylUmch^wrhq62J;Hm(;Q)92ClE(#{gJjw(GYYrNnSFzYi-Auandswp);^eU}%n< z%xEzGP3Op4@&`N+m%ZJHTm)lEL2f$^rUhm!uh+xq^4AUJ>s5HM5IXlhfv$G3NUZm#-a#_(EcL` zf9a4yd|gpZAkNx$v0lWOsBy3iz)5@Gll4TDV&fv8%ZVW!TD^g;$g9QA?kX5qQlt~= zJ^bJx9@wCBQ(XeFOLw8Btn?L1KV~2|)ynQd>P1;tvAzO1EL1uJgOF(%2lbTkzWWhB z?@zZeu!$yj;G-YO{U~NKkk4TYNmfJHSZZuOZuoExl7`z{*DZ0#xE>DE6dxWsDJN7; zW~sQULxjEBg1OcIimKEw1_sH4GGqezie!L>-cx zVfSi>V~VF{M47Z76It=r&(i-f%$C-LGL_(g*mCP^-6$jrwf@#5;a(CuwVlm3(yYX1 zM)bO{ZFgU%ZgCJ?;Q4McwAJBOwyakbYv@^Tf4RFLtEGtzB?}fUFMU75aTNUN{2~@}vu)uy>cLZrCwPB1VbuvZN555N2`}^zCM#b+yggI>J>Y`e{9d+X?UdIV9 zYHG)#CM=^zE>DP}IK6~v26kQ58No1bknrUyIk9*+`Kw(-Uc_W(#{RZw5X_POqb%s7 zXekfh*rasbd2tC6`b9X!>lx(nh;#en>^g#TRz3qU_!(~Ub7n~5~ZcFf3V*wfLRg+6$_1rZ)i|O~IONCWEsqVXZPZKjNK~A>( zi{O-{zvnDpI~%SKGIv}drCv1}0}H5_$K$SV=67+K%*O6nWi}cq0=(8NTdtRNAm9Sq zgxoSX!o;X(Vf;_ur5YX82Jcg+=X=vvtrOPXkzDrg!GYeWp@6?owU$@E3e|8D zUW?^|1$#hj75#`&uGnDSJK+~)w`o>x>$Gp=fi~Qr zC@>`t<|G_8GAb7^dEJw3oN~*(-iL0n>-e=L+0-K@Di%yfU}}eVT#t>%nC5%Ml`RIr z5z$RQb{CXOL2HmEQau0XY;`$20@h{9$}YHLTZrzv(`+35hu2~vMeWHv&`Tlr63}CA z81io6ZdT&1pGZzkT@D@r8xh{;;ocR${px;j7HycX(fxK`oqeNok4IXf?k~)*-)B%> zhHZQ#1E5MSD|&cO)8;`oc->C(9@w7<&l=glwfpI*R{@04KXLBeoPi`TR1!c!aw3?q zIWP_Fnb_D``}e}gZf`fsg1sybncC`4n7S-enyyuu9({1bt&U0)IUc@0n{ zpHN6LkAD0GQiUp6HDU}CL@S_BvY%*jd<3H?+qxko5l~oCV)th<0|=KN4)7k9W3$1& zTTrv}tA)GZn=u<LY7Wsd3@{iTXuY_h%8Ng(0OnC>Z7zjlCR>-9zXJi345%vmHG3)*u z&*JPqj&sk0#5NSlI~xdO9 zYH#vKG>FK*)abvEmQ^KDRcE?=l)5jR8%*AlM*b@}Q_5>-99PfN%ltTt8BRF5=LYE_ zgI)TfQ8pog^1nunUE}_$>W({oH#YXHrtS9p1Q^(+By_|DHB66`fc;(t19 zw!*Z>&*qzFqYKwb|Ao3^>Vj9}f@D(XD@ zaRrfFVpCP5ye>a(yDu0ys+nG1wx!{+v;GQztLVY0KRjrvgQ)81 zCn|7bD8lh+c_uX8hjPeE+qzl0qMLxBFXR7_LUBWC?QGF0{L$+Do65<+WilvcvaE5p zWuV7q<`8}v$_+n7b$IQOP@)Oc(bfjuSvS4Iy+0U!_N25oCDkr07zq6l_R7omw6C-?7ku%^C*E@@)K~wQ~goCOyH$Esa1% z-?w)8W<=nAO%GJYHdJjay+m>UsC1u{?<)!HA=SV4O!n@bl>hiKX+0fVa2fhRW#DD1 zhoTwbzd=nAH=o;qs7x3%$^Vcrv#9{pxpCbu3ceEcGPajD!ugXJ3e zbf$3M+ivWvY=1l)b>no#P{U4-etG6@2&v+E`sNE~m^M#G=oP=K=6S$j-%E|wIYtW@ zDFGZDPs$$Y1Mc`e-}AEVwadLa=!$QE1la_o?(R#Z+9_gO)Tbr{eDT z(xeKR3J@cqMsC6g+`$0|eU-7uaS$TT2Vj0OY#<0&OzzKpAtmp%tMlm!Wl0s7S;G!~ z*^Wy5JXy4oH!kKcOX|aE{<$x{1)YvdBX$^JL?xwbobHpw#*NW{PBFRsh2{y!+kp($ zg6T05PtXFA$-jYBgk@BOLN2|Bv8B-UzFk_-YVMFc(OP1C?!p5VxKi5%4GpNoV46Cd zcyTt9@69A#|6O}kS@$KN(`gksgeGKR2P!^wQUgD|K>pG#TVVHzz4da5YN8J@KMam}CX_8^GhEP)dK-_Nie9_T8T&-Y1slCa^r!@U=Z$k?fLV}VE z%SqtqXs-@$_|GvWgrkUO8;6M1kZu!s)#a5KPbg`=TR#k{ws7cS>xYRmHou4$53k#1 zAPg3IDdpyhpryNs9mDARLnD2099Gcqb*$W9fT$j`2eJbew;)Pc!}ARj6VvJ6p6HXh z)nHz1D!ulAq43+dGyjU-KgWM5HxWC_{3`xcuiU_ZI@UT!ZqLtDOT^RuIu-~ zUkcVjW$aO65Z1O@{)c1HtGD!x- zI+5suHG`v~!|G>ld;I0JHHGp4A9ACddhw}QKA!?MG#KQnj}AE!r~*0cp8kU1TH=zb z=!4ahqHj0&a~DtZBOsF&9ihI#ikU#p?1%MrZ||HV5N6={FLzT^_8KI9>?zR4W&o9+ z4hNnJlD62UYl7$)c_5UcIR^zL)qpXvFTzgXk3Wyo9*7qOth|GmiVDh9ERY#BT7%hbgd#&jr>m^0=wJ$q8vc2i?%5U2m2BJdsy#WFsQgRd zH)IN5V1I4-=cUK!^`GXt(klSg|MR5}Lzs@#`+Cg0PyMn5{^aiNbY%sO6G!zYHag@? zwHO3BB5Pgm70a#X4J~MM-OR1J)rl?_ukcgk*C>Dxj`eI_r%(q{b(_Tof?~#NbXPup z*g3zhRvk8vL$ij6f8P?Fovo$X9W^4+gU|zPv%7<1d|cP)Wq#8*!tc%5<1o)K3CBeA zu-+5;ZoA}$mZ@#Y6_pzs47BO^<3E0#ltVzq{kf0L#hJ8;U+|kdtFOrxpX29Qh{Y%w z@x2|MgoX|)L`{u^ld{y7q;Es7uf-CYr}qqlS*hm zm>#3%qIpOBYIA z0TsN{dT~#r0Cedy3`?ixlTXevz0(V<9~@7wbHsE&xl&TzTpBTpUc+?44oTHUlkx@x zw-VFtN*lf#l%w2CI{_My5^eHsHjPT9svm&+vDSy1Yk)oTBmG!eV=~{h zHRhZXFIZvh?5ykHy|u`p?FsaoT8dP8+ZvJIl&}SCQ_;#9J%V%u`?=Prf!|7U-*I3= zzs{Ck7^HCkqiE5zY=9RYaF7^=08+SyeWEdIIp-@&b6Ta*F;fc%IMEPxSpD!v)pGRV z8`G;Lj9C`Pu19a1oQDSMWbW)c{)Hj3Bq;&sw{ew}Rr1Ksj`dZc!}ymqHXM`n(S6vL zwAqTNgjuJJ_T+rk(Wd?CeHSiMn*a$fo6L%beCqmHOMD35Cv8mtu66TVL!qD4OjyY6 z-|wg47_lyVjN*2E;aVXY4tML{M*Uaci>s8Imwno?!NDeVyq|b2*GF|-A<7s~bTB4j zW{ydSU9(Mm(o@$b89F#Ae`&G+y~B*#Z%w^BZ=IuTY%T!?H4Yy0()_XE?mD(>Os`Zb zQu)?Mr1vyIqr#QfUW{gwr!N=u&&>0LTikN1UK&pN{QcL@G!oT=vD&E-rKU=kJuTuv-uZUZvYGc#uIOlg?Jtmr{Ee3Mv#?#=yo6i@aFn=?Q`09=&T0*42nyK5oFiNms4?7cGi2IttR<(a;BMMi|iGb5p z`sB?Vkf2jbUtQ2}Rm0H~(Y-*Ywl8PQCAHte)9J=#LT-_DA}gzV)yN3&eV+kN4=Fmt znS+3j8RI4yiW*k`5B+msWTgzFe?vBNn@&~EjSrPr4)xDELdZM<2Orc{f1$Ll#?_5h z?Om<@&8u}G9)!r2H?fIz*+C;4n0(q8b;-K{NLvBK%4+1YJ}hdG-G3i;6s4S4LX*%A z$X$QH1D`oL6u1civ1)Q2cnng9UnPxGB?Q%$e7UAY{f7&-;0z>D8(IQN4MufDj>_8& ztJI*M5h`db|3QRMGa}cZqk0H0T+W7uiwXh)Jh25T6*N46D+mxQ8ClEWuXG%~`cz29@E`aUv7PEA%s1EcUi;q`8^GbrpS1XTxE2|jN5q0Kzo%#+Km z$C<@=RFxfVGLGh01&u|;IEGbVFBJYx2^ST+)KBC zf34hyKNODR$8nu`h>SaOW*L_)S?43VWJlS19&xtJkc^D8a}sA~%gD&)lr4L7R#r0Z z4*7g=IDC6Ne*ePn?|8poPh7*MQ&?z7co&i@2JwBG4x*}gK*@*+B*OC6{6a=JJV+-h z$NfzYj$gGP^$gSo`a$i5{NdH}P09f}1K>2FfRIzUZBjm)a>T>8YjTW!^cJQ+oGRve zdqJbM%zGZ)+aKVs6$CEkRX)@#XYDUWCo{n985qJZ^Wtw6o}DN5#I!Uw_s=!s*Oi-4BS!I$7|M`CORw5X&zzvRgiUo0bo-mUKwW>$OwJZrw=lwOuS zez6ViX6F1ux@eJW>3M>$Mr)NQc4}F0!K*b}ZG?*1TCJ6zk#kNNt0cJ^o0PhGZr!o5 zDNbt&LkkxF9bi}#gnv`m%lNK=oALc6zx18I<392fpP0bB{;AKR5n^JI!N&6K+S&*mjOXD$2w%oDml@)@mCnf%YscDDI~ zP?#jF@?v_9LhIIsL94y@P3cb&_F4tV$SugMIA`}yu}|K0<__Apc7f%;rMY&;?)z(2 zON?gPHZMjKmh%ype%E+A5a8~8!>c)JZp&~ov;4eF&hpMqMFozCl998i;LAKD=Sn+D z42^5>oz^=#+e`uy55F}2iiyvuLtY&X(L6o7I(zp?TJO)`vWR~@<&;CaZ1lK3lV{Bk zxg2qzUps@JX>xhVbp)SLCw}wsq22ikum~B>SI(Fg7MGArG&IXu)W3K!l_XIX#ko<9 zQ$~oTVL5{V0GsJ13*;SV7Z+YNTVX=*a(}{ld;y#eh znYYAklTw5(Cg-~?pz}a8-MLnlD<&oW0|=z>lMI|tdDG_b_y>d($DX4?Z7!~#-kTrN zFZ+ApB`^qfNR!vs2SAM~P3=^LEYWvFw&+=X0S5Q@e@po&1D(21|Pu^9>##B=qXAZ$@XF zCoalSGx2Yna@(qF*HE2GhsY$dQxUA9;>XX)2bc>2Qslf%1OVs5GfRsS03oBV{G_=; zG&KiRO{zdNPy7te-v4%CsH;|&h?Fu6+hb_t`YCW9=`wz3RVd$unvKz1qK_P!Z*xq-Z)2g z?cHKa7Or{^hmFZdZ}cyF^%u^d{H7Hb0s~Gomuk)ZubaWTe{YbG*wP0P^?;>3G3Bf@ z8VXXl#rhI{O!(i`Z%EO>78A2bctzB3e0e2@?uTNiMlF?a5?v<;#p{$XsxYVCfW#E; z%P|AuGplf9GVT$@7l_H8x?P}us5`V|m>|27ycFj`2SI`+UVEz8x z5cWH|QO*eT(13vw0;5Qrl2KSW`SObF@czpsp95N2KOL4Gks#Py}_y$Bx`voLs{3jSU3ijMUXu zLq~+n&9@*nW!iS%KlW=;bM@s9POy4Qlg~WZPX_~>o$CZWmPoQI>kZ0oCR4| zf`P|7HY0@&LlIS3VWkii^8ROsnP(qWeR>%P!;#cO!$pEhZQ!vO1Eq-j0V_ERCACM6 zm1O(QDc4S&ht|VI&A_|b#>)4nD`a=zuuid> z7>sz}#*7Mf5EKZrdlVU@7a&KI2>p;rqIyO(r9pL5AQG(Mv`O8MxYw8?QH?|ICdY{w zM1;zNxaNwv%pIXpc1o2H5_K|P5;lKUBSFo9Nf_$5dnPr@CyG6xykN8c*TrWJ9X+tm z?zla6ojK;Bg7ym^ukOaakD30g>PkQ*txd8<52N>chZgv=^>ZuH@Zuy?UAmDGbLEM9 zpu8!Qi1+p7LG|{S4T&9LyIZx~a24=TC>J(%w^iDct0w!OHkrXu+LLigim;s;B0qEV zyV^?>9~yfCZB5hUXNCqo78o7|iG&?`8(f>U98~mlai>j=w+GpZ&F4@WhG=5y?3b|7 zvTqYDTehR<^dbK~^z` z0B(qy?eOW?yE#0T%VC8piJa!^Ak9m|(k(gXgI$kj48d<1#H6lv4@qi!s9AMhz+CX^ z>0;SgAk)kBg#N~Vj|fBFDudI!s=?NiUNw3z`4=&pX`RFlheSsj%94?q3|3}Ld9i=}0oo%sY)4>mu#tiPvV zbJ_1Wr>;yn3#1XF5xY{&U8^tSCzRX#AUejRKAX|{T^C%84k@GX^qF)TRxK?G-s}0G z#;dY|9Cvoof6_M!cAQRpW!+PM!t^?lDAe9A%_^5izStFe*eW8lysP&Xh591^{x>{- z-eo{}@!pX|W$#cgE3_rZ|H=gO&zD}1^jDY*q16OwQB?aMAqsF~#h3&BltNWftpb6G z0u=E>VrusnSAH_=tPh5LeKA>(lP9qzL#F?h`iNF?3kRPyGbes8*xhU2(JWY30MhX9 s_>2hJt)UFCy`N}vs^RRW;pRi3+{#gmC-1)pXjUC!tJB}2bAn^kN^Mx diff --git a/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-quicklook-42@2x.png b/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-quicklook-42@2x.png deleted file mode 100644 index d09be6e98a6a113d9666f969665269d64517aaf1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23404 zcmcFq)3zweuAH`Q+qR80ZQHhO+qP}nwr$%w`+mfI==5`sk)+a9l?ZuRaabrUC;$Ke zSV;*H#sBW%|2q(1|Hb~&SStVkEoMm(L1p*s8y|3Yl(m)D4(2A6t}0!5(GV&H(J_CK z7RGk5NUy_T+E%6PjpWBYNj)dDIQinx<&Sho@F{5y1OfyCU>|=(vmmeFsuexMHEG*6 ziF42coCh4wi#Hh(npn3Iss=%L(|a@5r8w_YUGfkO{GydyFHSw8F@msE_CKL+06^Lv|P>m8qhw#21tsiVe&EF~h zvTIcrRVo{jh`zs^PD(JvM1cbIZvpGHT3h207r^{hhGJcMe40dF8>YBj{qiMvxC@t( z2In~pe>`7QlxJd29QEay-uut=vgWVo+q)u7B|Fi(sL;3bp3SB@Bj3Iw;K-ivzLyDw zMFD{z`Y3Z!&zmfd*w~1m8=VkAHPpmS4HJg8>hEy3S=FFngC}@sX(*y_dIa`hOBhDZWIFRpRi0utrcve!U2Fya%TFo;t^_Ym1VWr5#UDC~pipsV z!TWGnuVpB#qxkvY_JHzY?|D0o79L>!{Z!h{l3(LBr*>90VTkni`2`1JEXbPGiA4r+^p79K>b$A zwSzYq8D#ID&|EwY(DL@kgpd*jAdz2_m06?BNLXQK4=oop@sXK)Z{B>M_~|)IB}vB= zNZ|@h;}Rr6#IA6`@qt}#(EY;Euaoaia#6zDw_DhY-VKbaR>;1~iJIbNqxhv_Gc7rDI^wH(gZ;?EC0SBs>i z=kK0hriq1JT7=?6(Dqcfgh@OFp^$J4SgdkAb8>3h8$JHsR>+^G1M8(-olze& zNRqu!@#Kxxqo($&Ba@de=vOy;(ZreI3Jx!ew$ZJ!79?UoZq4aFt`iTv`VHJXY1sGm zdY)gB`FbmxUM2Ua^bD+&jExFJ`;I<)R{ybUR6leu1W;Jzss$L~piG6C6C{4+8h=`| z_Xm4%eSJZGzWYtK*SHBUXQb&d0sGuwb zf{)1XjJFo>IqzZ)vtgL?;8$I%7N-HQ-=ldZg|u?N!j`bkB_DZ7KP5_bQ$;S-b*pIJ z-DV4u*$9+boaks@&Yo_u3AVH&N9@_e^oCVIef^nR04c%_Qg)g+R) z`tZ>3RcpH!567g7M7HWAT*%>dT9yMKmmFvlq_@nOShDo zuRA1?Xs!D)=_D@(y9X?tgeuh6sWmZLeiHJdpN7_!%;W-x?{?aX$mSPl>cn#NifyK@`6b+_-tWn z;M8yMU{3*nB0twFpz7tS4yR7O{Ojnq4)plsq(B(}GDgutXviarMAEx1Daozyg7XMD z_6X7oceic@Ot_QK*@jD^lk!QrFJ?j&J*Tcv%k_ph6Su=`+`c$1#5d!)gwjHFx{ z9R&=esTDM!28g%z@Q^O^h(pdh(IQCt!|R*87UA!TAvKM8ZKxMO7(LE-0%%a}rjZLlkdIHy=={t7&ZQSVJ*kxGCVPp3{U)1vAMn~h*ghqa^ z)Sga}O74LmsTf4u#T%vH4??p(2ir* zh|Y41*~ar#{<81=vc8~0Lr1>4(Z536h5J$II;+0#b1xm27Nk1G7aM)O+YSd8w=UzH z-F^q*rGe7b+Oz)(E+O+s`eL9bI}F`8Ry-`qZLv65UiMiYtI$q$`|ZB+t!(b=1G%C? zCyg3q@B{)_O`XDyj$RJar`j;&@ClxI(^77{TQg`k$X0Mj1D{u%NcZA_xPUOnrY-Os zuxbN{EH{lKCG$yEL=B)^--9PVk0GLII@<|IjjePL^gvXXb7alg{;G5iMFspWAc-7B zcZ{QlC<#@;ilb_Ybm7OVoQ}mA&g~FFooka)p`4+vObcWEH5rMD0-`}93}dzC^H)d8 z1Y1a@r*rN5E5At)#l(C3 zzua!{5q(Oe0M#Ib*w?IoPN_TH`+f>VP09`lF&kt4O%rqo1toBy=WkMc`2c5MuTlL- zrv9Gvw?O5PwU5^kco}3Q)tbpYzqXKCdTHxL_nX3X)04%5aN~3pmWDQ8c71v|ophYM zfSr7T1O@^HfTe|tsi&rad5sfsWxiL&84f%oS$Q`(`GN9l-n{$x&3S?t10M&jvPRnWZ}O#iF8i1EoEqS1Z-y~qY){_FjEB;cXP+~K zloj2_j*LZ|`T`JDW%A-9{v3|erFtTw4H~)6D>eVZyS;YQHpcwkhO==0d@HYq#ixFK z6@sh~_NDU*QvTkLifa5mW_nlC{(7yZxb3Em*K`!^1?#W`@3a&U|2)J-8O0y#*@wj9 z4vfQuVT#`-wa@9$S4xT!bpsBrX z@2UJ=x5UU> zr=(oMgb*0;DfOLgs630~%guL_7@W7(uWGj>~$rYlL$-x?g=w)lksEhkKajflS%As}*?4>bM!_ zEE>i^hPrshq6$emR%;@qD7Rida(TT>5e{7%1*43E?7njMv-F^eMLw(>ddUyeCDHo@) zc|`igaZ=j-{Q5VOl$q3!kmmOD{Ku@7snm;C>!~|Ss}zow&t??!*dxxc5t5LWWiwLO z7T+uc_W;Gy4gUcV$W74Ta25PMwNEo}5IaH!2;60QZ{+|F}a3z~~{eYid@Qhb=q( z1lI_4Sn(bCrMB(acR@~TF!Vk9Ce=(@wfy(3; zdyT7gArYvQ@SGmTWNb6-$9S_eoFkuYof}dBc^SG~DY06s)zKRL%zV|9g2L3SP|SAW zOPKDdSRK}~JUn=4=~BIrBfGnKFk1rD0C)Ag-T#axjl{{q8*vauS$E+VE`wWN ztVn<6qr={8*6V9#Zfcccutt)CgR#bEOk#tg9{65F3A$mR0OXZi&b zST(?OD-LUBWE6`ve~u%}a*2-1`aF%yuvGS(c*w}-;cJ<-ANA?6%pt5g=1JQQC_UEIp_ z*xz=bQODqEx`{NtpYN)bmWVh?XS3((22?pw?YLBFL&MH}ogQD%DL#IU`b>rqJUn&@ zjOU7q)S&#kv2vad63^T5tFSM}I(TfiZSQT!o3GsQaAIDVYU)%R1M>q}tNIZzAAsrj zAdA!8%e^nz-o8?D-Pyszgv5_w*%>vB~PB>tb`~f zf{P|&(OA`dNMe25V-Me{gMfhKC1Ut}pYd*k)`%FCl9eiE^9mwETUDu@Q*MxlQYy)< z_Iz-c9J+-LOjtO5&H{lR?`7CG-u`~o{9;xv(iU3L2%tpuyWR4dfGcdiK~QyMVvs88 zlESx2qSO11F}0+p#ySTFOQBb!pJzhtBlpP&oC*qf>Q)>G3=;C!u8{2YPYZ@Smc-g` zlFVwJl1yK=hv$f&Ej2SMJE~q(es9j|?#e4sJaP^K2j^k`DcqWab2u!61;rfxBa0?1 zjorWkqT<%Bk8KT;4~EF`a*IIhzBiV6;0``M;g_WJJnD7`S1P;D9bz_>!aQT~I`3Qo zqP~VoX0!)Wg02jqF;T53PTV?aR8xJm7`(hn6n7tVDi^EI6YzjA3(#*wR|ylfk1a0P z3dQI9Camh=aB3YQdj0mcXqftR8|p-L+p2^U-|s)KIt#{)J_S3V@ zg4Fa`r`oc4Z>2LNhsxHZb-rFF3bmpBk-4dq`}3a#-;-M44garynM8wW4GzX~7$)&S z%KaNa) zk~=+(iow-!+P_u{u%2|6N=yM9-PJ~%;xr( ze(k!TVoQNSNGLS+X*Ya-bCp-U(Q@NPlZBb56IYY(%`!7H?a9vl(x0o6i<@;sT0Pz= za)h80m%RcMI}3)P?0y1Rz5%pPj@G5FpDk2&*0oxjnu6c=B(QK*Cw|n#P5XHzeU|R~ z)aJUBkYP$h0DjjJVkJf}ze453(@zR}lDYh8_Sn?8&D%GYLdf1GzpbO3oTJcc6w+S8 zGJEnM(ajI#gIN|T5U@4EBa!AQ3F6a+1MWOF8oYtJrHab?=dJDQ+i*N5p??KeqAh4a zslLdxHxG+1N|HsJ4?RSO=F^Leb_A*HgGkOHWfG$)V_lG-mpV7Db5+9iJZt{$rj6-p zx1FBjdEE~+cj_X%Z5tPCDYw5V90VW*NbS92%dVn)oyGEHyfK*~YBzj>jxPO+0$+Un z;bU97&PViQV>WtjnIbkbAu)$ne$V8#;EM`jnqn_OagwO+Nj~NQ9RSo1J0qZuSx_xA zL$JN9v2}~hzYE6MUjW_;qQS~UE#cwuv7G#fORZzocg}CnZ#L8LfPkS`qWrNtQKAR; zvLUV-C5i%fJ(=tMd>?rNUTMTAj1dA9WoN9}FN4Wey_%Wc8XXr-q>S^eoMXHH^EF1U z846bhfrDU^+$z`gW+BowG9t?ri(^hI%tY z`Mj=>kj|AdJIa-hmuF@qFL3{@jEE_DJz;S-lg;TwKZ?mPfvv>EhR2tY`uxh@H&*v) zoLSN&e8`Gb!2eiNPBUfMlG(I{i=Ay?DHb1s4=r zaR6gw*QNJ0^Eh_h)%GMJzmEl~h80Y#K1FLaW(plcJmxzIc6zG@YUCP}{3md;++K6V zcTo8{rZq!0im;Bakx8Q_g>n)f4pH0iIxOB68s_#=0%emgsL1@heE`fi^!X^rcqdtf zN(1Xs==)N((ZT*mt%k?bYb>d1xm2sug^~o3P}!EO>a}@=qy2(Nic5nB=3LH^qs(mq zcJSEel)rHKnGm01LKzdw_e(*T^E>mYXtm>3ghiWFNaX9FtgN#de~fEXHpds=ecVb; z(smV`FK=Jo+D`!R^u!7Vd?z7Ai_9d3XM#d9HfRDvCwjB-ZKwFH+Ffy4+_mRaWACwg zPQgziIMn!W4t|+j_N(Lmz+$g$Y?c>begbmDRkHQPEEZ9;K;8=EY2t{euaLt_^CUHe zw526tV=T6z^YIyz^Nw>-{6;}k?8zB{BO9UGEqsjFqNuPyr{?c!y~AlOE;eE#XwZK; z8eQpc_Y8L7B$Nt;j{AIYILZ5GkY8MKCWgzS{t_SKBON(7T46am`7^Kj`59{*1hDSu zJ&XQ3lG>MgN>hs%ijd31Zzhvh6Dxp-F$1D#j4I{P%gZOHWCVflp$h1@1wpU+oWx%QpF%Xp-hJ%cMI78<}jF5)jL zK679k2aI+PUW;@Y2Ye(JcHJ_DTV1)>cn;BKJgVHQ&)f(h4cAB#P}~vvBvg*yT?D-l zdvRmke_@vyqXQhzd;=0Hz^M$D|9j+xz3*abz#-53FJ>>;hW4ZAW0*0+oQ3A3n4fSe znQFyymqbcjw(>cz{(_tQtXcz*-|S^8IWf3hLR*p|>fNl;)iJX1S?V+pfO0KTIU8vvd#JxXQ_`;o4`i!13ojB?HJE}Kb`YAT~ zv$m*mP$nn#sSFFAHlCp)ibuh=fG&NUQEQ8lkb< z>>)Dm^>lqw&JVBCZ_3EgDJjf_uwvm}j_2)pG?fuKk39IAXYHAOx@L2!Mv>#;J z*UfpH$zOG-D-LHBcHwfj&ikaJYhs9>hHi42h8bpt0tz?hMPAJ#W89)!#;TU$UUf&- zo@JHGGj<_rgtQa7$1F)UcRzf}BNk|wT0o{^2{Lv(owuf8;x2|ngzsVHOfJ;#=L4UM zJuO^2+*V%~N-0gmzubJksVuYz>f?(!)z~kpwvA6O0i~tw8hC`Ani$uW+e$i0jYI*8 z5t*#duikh?h|cYStZxl$CH``zWG_my?a}U(waWjg6;=OMr$s0s^Ir)!mD`;z4->an zO7Z;8we-$l~Q zjevuF_G-%AWWO35%UZTr62g@OWeaCM_W*G2}}-I8BrP z5J62o!E4V}$a#-eDz4tggw0Y@BNZyKSQlrEtNdlnLOq%&qB6*+}l6b875b}7hi6Bdf~@*QXgfM zyXaV*9Wscqj9ow3Ty+}Fr^Wtfw*2rwPK(*~5O?aG+4Zrq&v+*XUB*wzy2$$8j~Mh= z^FqTzYn`0r`)~gl)nNPVV5V-PCQY3NzrZn5VFUc`K}PRdTXgVLY5rjojiJUVa)h4l zHEJL|bVV{49{&4O-r0MUa2&LYO9m01HUi$AU=KyWAt+mxLhQ)(C2=27BqfG7YyXKd z$|{gLu{Ocmy#( zBnZqpVAy65lwkYS`thU1Z0y(uK~=s_Aa=UfuO>vB)u$w^d|u%I8m9rP+3|GEl(iSn zn?3>%OFOWjVoavP$<}2cy;LA{W)k~y2{4T1ql6ZP1raQ^PQ&Y%wre5HROnKW^e+Fx z9G48w?zy>H&Ka_Ka?;&DS0f{cNAj1{qhnYkAljb^xoQThU&icapb!}cf`cn1SOh#o zAcKOmf1chEc9YbIBs`jhzIB5tw*PYA&C?YXNEYXv4>6cepi>pBu7w?QOQMS4y!v>s zW6vVCY{5&mI8)d&SbAf{dU7@Cs1DbViCTxreq|V46T#zKzObmCu3^=SOBTxq7I$AW zWZ_L$yN-}@zfLOt5jP2O-0XuG){>AY6#qvUKN*|c(JGMk9^vkfKG8*S=%195aX+-v z=Ykf!ed-W2f;3kw(5YlQil&73^12=(VIH zs96kTOH<)?D+lN!$rBH3sdg2idO_+nc~Z?*%XXDxvX0uw;y*kBuf;UxA9&U#1KeFI zP}o#dNbVyip>NWtdQ$N@ZqVbJtAT@u_F~3xFkpqnzN5p;CEJH!v%J0g53wHviz^yj zi{Jw)-EEAa50>;$@Z(PCyxjnWG)Cd~@6Y8AP8}0o6&j(=Ry0-pC3oK2)K$H7!(wl& zue7j{U7t*zr*H|sDvtE`{z}=l>D%(Jc zfr}y-9)`!WT{mWyYOh97skhPu%grFH(|F3%!UrQMB%f42(56N(`+cZVIRMq;ji2>u z>4g!E4KT%Z)s8Oh>2hpXrsi&F7{2K2eXy0Rd%mj(@#Gkl_2&25;vtynzajN0?=Oiu z(zdY;6T#xHF7M#&BiUQXjlBgf-F1iuB5K&yp`TzSLC_$(te2!$Hw5}jW)~V1iTT{x z;IFnBBKH=BfIF%2$MUgA8D}IN*RP4ksh|H`e`A*TY8g%!OHyYUCHWOd;uj#?y!u;2 zt?2bPfBrXt?jAVXNZ>ObLhEtOkb?fBk7=0QV)pNfvu{n!MD|k%5tp~l_qpLQA6%S5 z<>KATP1aT9b{@|AQGW2@6C+kq%*8o(SzwiDAP@c^W4K1=NjqhFB_o2o$R`K|tJ5ogl z2xO)2-8cc8zryq3{(vsr_qoybv=L-*ELI$TY&7lhsLa#&c)44ug=}=6a0-dt;4uOj zQ$xD3sj25f3Vp$#`F#W(lbg+2lUdQa+$6=QXOy}DKS*kXGYDkWQJ!)gQ*FA5oD*r70!Y-EHdfJ!d6O~EkFKQN|c{nICli;IbzzkEjH zeDwS+MFJ6@KtA@&L;N#5X)4tCC(I`?iyAglU>|rC5CIu!(L!eSoq~rp2sx*=YPKe< z0cgYYL1ZSIb{*aCYUujA%WX-gj)E?94m<+%F*5Rah1(5oiK{v;JqwG%6^K_2W^gP| ziiVZkSh1H~c(awS*5*$)Atf%?&bu(?@ByLI#AkC))erM93gG1m9N9I-?BUhPJ`VLg;8{@=e{brUe+{7r}VE+ueuU*Vgk;|a8Nq; zAVUV{bPELN;bsJ50WFD~$*Z!_$nsWv%P8qrLK+H$>Ea-&u!P0blqocfQHI>Fl0&iJ z#Qh*pWZrsIjfxYVTwbH1aGcw#z=z@T#&KOVro-r+7B}XtY1XpL?eiilK}V4wy8ABR zF!Z?DOIetCyK#rCXu-DyU<T;C2kIxmh?p33GMy3GEf?f5 zosBjqEjzZ#FhzfGzusdoG){H>l$KK0ajNZZa&EFwC>AkohYy;yHc{KR*ZKbbfHL#+ zQw#USrJOFO5Bj_!X8}n(sm<->^4bYd!OC4+hqkVQ%I{c7YH0rat_r&qn^Vj>Vulo-Py=8ZEtAIIIUk7>QRI33&A=c#wb# z$IxA>a*)r#^dT`~ZO11Zp{;>ll)ncT&IpB6IsDf0FXClhP)eC97tT0`^EF7xDqLMf z5LO(Xx4Ej&Fno?)fG#r?1)x@1(qf&{<5lrP>+R-0z7i4%IkG=mVc%uKwF`sEkfkLq z=X(&|wz~m3GK$_8i5vX$rWUdmDLGLg?yt}At=yq&K_6x~+1@m|L)+0^F;PE@qsLu$ z^5*S2gJt508-Hte1TT(p6rg_(TQzv0revaVB@pxtICpCV66oyQ9G&%reC)Dov+Tg1 zf|j=Dykh6hqmz)V)ZuBpgMHHD?UoG&n@~d5OaSb*UI+Q{vQsRMf0M&;duu#nRj&%T z@b5M~q&SjOD%?DS?MhF<=@hY|YA7aH8_-DZ{gcZa25f@O#C0Lg*S5QiiGRwcVz6JI zMnC92byhg8y!zC*ZH(AM%Ltz4yEWM94z6;$&1$x?l1fFEK6uI}ppSWe=E7ly+ib5@ zx%VR$w=!I!7z-x5A6H2jqC~Z+8aGWw8@a59<3IDM>W8B8_EWxI8GukPZNXiy<#0Nx zjmAcu=v;2q;kGRiXTzKtz%*O(B$eR)`8Vmx13z_pRXW0(9lbEd{K_OMS|qnCjs&!Y zg=fF(BL|z{T^6HHhdv`@fIAm=cxwfj-vb}JEDuf2sbWZAV~Wt)yUSp@9W?vyt>H~1 zuzrGgTF|v)1WrnX!MAY%ug&tD(&_Xcx^%?_xNs-=r$@4)Dvz_0P$2Jv@Cy88>0D1p z9^aS!b9e#}n`m(&4I|O^K)MSAu|%mp!#o;7ZsE9dTH079gzhDw!e1&SY3$r?IFUGY z62l@d!E(YGzzZtFz=H55)K=(LI;?`c{lpnL1qvytPB=;YxP&@}+%_FihxRV&kg)PDQ z__x$-`FUjuM1l*PRk`cltcLDN!LuVCRe&O~ev#DqC4utrZh)G*$(Y+QsY|?Qlqk#s zw!7`%a%rsvr<_kFr;VfKFYjM_wr3c0E*=;HZ;AU++7xpb9{*!-Vdb~0jggJ|*#xq= z(^R%ph%|rHxo4KtQoxF^4xI+K2iQ&bLFyfB*KcZ@*W#MqWDoATGMCSISY4gt?QShN zY80>b!Uc+&_U=)^<9UNPyo^SASAJ_Nq*`rMFTODYeXah#U{+E+Uewo@M?JS>U*ad= z8lX=Yy6DmILh(T+4WR(F;1I#}X&m##5MC`l>u>%v8V$!p9kV!JEZ_h@8}ci=0h8%! zg5%JvsRoCWfgZ0sc>1jm{qYH6H)_k+ut?UifyI@HPBSJ$UF-N$8_1Qve)KA3q_Nza z?0_S^DxDs0^^^MQHMHWgHSJ@hfAw`+YG1D*A~^id!o3xI|G?tk1u2*WP-Q^kUvg}Q zlyGzQ2tz{rMg^T1d*q`Sgp*Mkz3RTI&nxN|=@l?UbW5<>N6B}&z@$Va#lSp>rbt+b z0@I8R1!QHf;v30uY{tjE*?boN^ISLKLqUNsU@`7<=a0y!S+f}hDkum_G^9bh4CV3` zg|)EqiMd(hl@{EBE*?PT>*Nr0=n!=3SdU^*5;UvZpuW5cJ)<#`=dhlgV| zQ|6b4>z)^UVLPBGw_xJ^J)RuJ7MdK0Y#3>%!moDPWWu`c)TaFe< zDT$|=?OdX4t`vwBISA;~vsG!Ou_#l&cekXTtXZ5OF82KCs;F5J&f8v}}V z4+QO1ciN6OOvdeB%^B6axFD4+z-SL)uIdQ`@iA$t&gHIIF9f4#U}^CkolO@NozZFU zIY~=Vz7Dq+V!{J+Lq7xc5!9m&jUycnBLY}?>(veMU;2ITF6HsRIO-))_tSkO)I^DJX>%47&L?*j7qK`#wdqFaIT4A!XqB5)G)@*T&MOUad zi0?N!Ym(<+c`Ln>#b!RWx?`6ErUigwit1cqsBLB-0HfvbmnI;z4mJF# zbK`wRXjM9?`u*&}r^vh#?_|I?_xI{<%#bQMBn?q?z23pB{rOxHNACM||M^A#^Ic*G zhbMcZf(d_g>@=A|i}~uuOX+GE(b{24|MiTPq)6_r>A@BHcjK06tPzDQCkT&T&CeH5 zc|Mz?Wyn%63dGDJ;xqoiE#XG0njdo7t_&*ueB^kbJ2SG-E3P}vaJ+EJ9rrn?H$0gqcK zMN1m}Mytz}Zj-^o1Km*Z4<8XC_^)N=xji@7r;8&4on&?TMhXbpRhbIV;%+?-;{n;O-ZV~b+zI7T>);M84X}Tn{A#$R#ju>GW;{MCw1Le0vr1e+Tn zD-1dUXSA*g$Z)Ed{mlj)YO*|_N>^?c3l$0zswj1xB4VLx(SYYjU5@@dEObYX?4bBq zpiT|%KySN9X^)i>fw#8U-mu(f!Ab8}S{PkN%t(W17p~W@?gNqg#!-UM;1FmTMeQ60 z_rVe~aZwlKgM^mU&3fHup|ehRTvSI|)OPMYke$U{d@~`T^j!>Ry}!!n!Q?6S^HAxo zNc;5#i2F#2nKk(|K~dpMBo&#Nx_8ua!+ohA-~GCr9^Ux)lL{rmub|6a^TFwQcF10( zp8b^J%THXZSTruZKMB&t4O*T041F($BoPS<&U-cFX0F~x%yP;cKR&rzGp2Fs=6o39 z)mAVOE8pwO?U9TAGTP6J4=NPfv3smz%NS~|3^qy`T*#>);M?Em$i~*z)?Y0g{1_O6 zT6JXtP=UnQ+yqlZCX3AeQ*YDXd^PD(l3mwV+4|Vv-3t^5NU%V*rv*(qNo)q^Syg68 z+iAL8&sW|iww)DhlpI3&RKRvAQq?Ke{yT^SQTQiAgG!B0&zYJSfHI>5+MS0)nSxpS z4&Fnc4(IwqcaUZVD`N0L(UyAT^H?ZLWTjo&A%sz zINN<gVa;g1bE1U&aHbmf4FJuh;j12^CZT%NY+9T)ivWT@$8(cu^z24-uIeHElF`6ro}r+Ev0$ejd*>mp4@@WsC*hIc}3R5rX5_|K3zU?ypqozl1H|clOq=(|}(- zGX1XE1zuw3f^?Wfa6ORcPs9pL;KPAn1L6Gh(nheFE0RV^hkw=wssVKHo={Hw_4>kK z|7Z;3okHcZSH6AdS)e5nPTRBf?(%|!1?EE4uJ0LV}*QG zTNiBZz|r9(PY+>E-r>I`CU^Q^ay7V6bJ!)_b1Bz7`W0ZP{GSua}h_0+u ziuMqbG!F4-cRZil!C3Ude|Ylky|J~%El_z6v=Pc-C(>0vKNm^}m&0(;@^-e%?)23x zifpqs<0m_=v22TxLP_BP$9*jSjKIhp)L~8kIPlf31G})0J!0wgvVJ-v-pxxWJ7cPW z^-Eq{0*U!NtHX4Q3}!0$UGRFTnJowxJ%{TgVP&`UB4`@uS-2xQQ zFL+TWOHE0M=!+vd9c9;5!*vls?x&pgCty2M&)7EJ!R}o&jUfnYV9;&OIFYzRHdQEY zit5=Lu-=xWV7v`1D&ovtX^Wt<>m*)yX^lIo)#*O?ban|e2}a}6C6L02w`|nZr9yt^ z#zA9@5K1C6eyG($m1H+x#8upLU@A{Sl5=@|`2}|+X75GE5?!Hk)`g$l&;pViX%uEO zA0O)Y$BVHcH9%T=$syeS#^IwJ1_4Er>KKXlYAsr&0v8o|s1hM;Q+sVOg(YUZ! z4+CQ0v2sbD3I$7!4`)%4B~DGf>}`d-u9YSDOz_s7NT3uFSNpph#pxtZJQ76+)85{W zH}ln51x;a7-4-Y=6=g*HK%FCT&G>5L~;7X zrI6#xw|K0rg*9~HuHW?)qBn}XBgJ6I1N9{-Wv@#lqxH%o}nEI9BsRly%-ePo2` zKY|`qzSA>qgo(!bEOq2FHdVB;D2&{41{cxL1$BK>lX0{k>v^J(q;UgN4L$G*7Eau_qKtn(Y|qyoI$tTP3S6 z@F?ZVJ!B!Fh&|p&B+3XRHhe(I;(iAndI%8&l>C?&bM}Hx`ye+shHqnbfBzpSGzqv-iWvF=B5UZk?@kXzL*bv>lau7kZOVV z&VG5d9Y`Gs>6xL7h6lG5dask4&gzFhLgdohA&o2#8Uo}t6D~elIx(L;W<&s;*7v8k zMq+W(b6Ffr$}xNlBvS?+I{bBDL*X1Qk^Q0a6`*Ac@VFsBwklB|K|$2+eomR36pJIW z?$EK}*rMJ~@C$d*5gD!?Ti3J+nn$pq4rXD8lm$z{@EG2=p9VlVL0$uS|Q5H=$m zT7C}t=F&@p$CokbLDII-9Ii$@fZf?E)dL{-0BQuj`E?8hE)5$8yzRP}a=z#F`Jb-a z%AdJDep}V6Uzx`~wbiC5I9jU5PVpXQuCHhq>{d{Kd+^L+DN|D|lS z^IOpBXr%V~``aJ7bHPPtuRwZ;OM81qvobjXS(DyQVPQ!0yy^wmh%-X2Sj-<;f|}CL z&6CIjjpROCxIMz5OIjCNs}^YV#V#d9uCBNX_|k?UOiD6@#Xumt9B8E&i0kjerVL1z zv0wbR(Wa;r@;C~vSk(@djU{8>L72G>O>=$1ebB(D7~<}kL5G@|;-&)KW30;|)-X68 z1pGWl@g2LocY$2iwnw9o+ZS?2M;eZ(CiGL6q{G`}tQc(z3(7PlO{$~>NSodvL;G`w zKTar$mE8`59hR|F7p983v*CMluMosW^=&?}DG~ zo~o!$5Wz!bOI@hA28WwA-$Gd zbUUE_xVc`8FxY)hg6vDbnFj+74@Hof zxY)=aH$xCMvIt#*lI=oCz#6l2Oj(HTl-w%M_kD%)b zI5{x~|EKU5OD65tcHIUh5R2#1q3{9b(}9PJQ)`fXcEcWQyyCbjf({rizO+JOweEPx zdU(XAsmWqKi7|o+i#uh+OXhRL9it*=ctqNF4GKAMmNYbMwT;2vSbGP4AHiEtDQ(ek zXhOc8l0{1kkP{{%APq8qMI!D^0$8$AjLNN=#%Tfd)`kN{{f9B3;`pQ;!Qn1<-(%Hm zZU|4myi62A?r8Flo#>$Q6zTY@tJ@?~ur4C_Sf0ciZODbpV!O^+v-kHidEIXvoNOje zr_)z#`%+19E}gvr`}CiJ`O*4Pf^QvO)l56}TMNKWk+C)G`veFm0x~)K|EuL3xa;78 z1)9dr4I4E!+cdV_s4;GA+qUt=wr+4^r)lgP+qRA7<-Py#{=hkFojGgGteM%H#|6ru zyX9XA?V26e+lj`XpfsQtQnrHmr7*0A=Wt?4;7qWe82KvDHE zmOtk9Ks<0_<YJPRj@w9u#)Pt*rjt8%vG6 z*7BX?`s_eXmfM*R>q*jUL%Z`5(j*V&c)r0}%pK2iLWxx3t;hg&%v)3}fe z8{Vf7nV$d!CtUV*>HgKCz?O%!tCp zjXH@j;{yF3;7jI{&nkqz z=+28I2-pF{F+3R`y;PhHc#Fwji+`Fen2Lyl&C(a)wajpDrBZHc!eno9#r18HM^+b;LM5STyA*6 zSg#;$^K>ZM$^g(30z(rXp2`b8QgrdHWPHO$gX3=3uGz%OpfudgZHc>LE^0ieh7Me- zHCfK}isMBMOKjZ@B{4`hwVphbbRphCq@toi#?Fo-Pcv(oRTM>q2u(#x+ptNeNr!6W z%bdRH30EAaPKG=W*PsV^*X+dnXTRxpdp4DmMWXEgEO~Kv0I%%EUDQOZHhOLgrH-Qc zOV8lJ13!zR#scSq3^uFLBjfF5hB%5cxrmKcK1*U%D#p`L#K@?FH5YqI`BeC8#D#^6 z8gQfZ$}q!!9*ytHzxkxd_W6)F2J&A2rQ5WcvspU3f3*InzRHx&->T^IZazbKS=<1 z+;IH~Wx zseFRmr~!z0NX$%kfB=0}p?gNL*7b*owh9>>_RQ!*Od}8i zNvfYHGD1v{b%2*MEt&3oB;(tQ(`o7{X0pdKSN;EIOYV1b!3mD}pfK zD1}+De-)r}lpNa1UPoRqtqt(rR8V5og|4iMWO7d73K2CifmM=$pEmlkYy@3VfcIIf zz%Hg@CGf6#)mEMM`4+TGIO<;_w2FiOV5X>C-A|=zdU*&T5nglFj@CQtZ|1#~ioLw?q_~li(IYtTQmcM( zyVAOf@Cgl?6c9Ax@hVA}9<^qowQvk*QcO4>Szg5Slj<2TVx!Fobj1O8gez_5yi55G zQrc)jUxOQd`(5!sv}C+soSU3sH`j(U$5!QM z%Qa6uR6e8rUr&M9ZPCgqDY_a1sS7b5vYjmTW|g}qE71@SeD|5UB;6Jy(x@lXOx^H6 zuCzOS_DK)K-6MfnTjIY;M;GwOahP=t?h(g>9$1qH0%3~C*-;}M3R_xj@|vjR<=@Q!wSDIE0lFVTcN zMd^P6{><792kUK3;hXB`8=N|N-ttFQcB$OiBXEHZ!&QqKDKJHwojuD;c$EqYZJy4? zyIFv*i|w!T8rM8B`BPx_kg-9n;I5AhRtHf45^D=PN0$pjPVRLX*0LETQdX^N79~1%yKv|iSDpeMWJjBW=vd^?(TsS{^GP^<5aG~Bes9tk0q*& zj)&`6rlLzecZ7s|=6+7?GSJ**wY;C~mV3qv4*z0^`WH!$;8bB)-YRF?0nAPb%f!uHDh|DU1nn0B5^Ch{47i@Ol*;=MG<4K3F6mF=I>B zx}|q~%~&dOCogU-G!~_(h{!?19}`!1zx4zTdOO~)(DvF^w76~qp2-?$ZxJ!M{B%zt z$ZypyQqdXCr*4{%N!T+pO>THYL&$VA#rebG^ zDhvA#_)kS=l_~Y>vz9aC%*ESAnQ%mzlvfwj=Q8xh>$&W9CIC^F{C{;n2)|#ta>+Rp zWPJE(F1uieKPJN_vVa6EJS4^QQj(#|%(wh0ro!#K0hzzZbeN$?xLR{q0H!j@=bTzr z*5v(W#zP}9ab~Qa7#mNqYjiAf3R~)rZ?ND00#JVD{%=O5)eJWY7 zl95FK9zk_jg+HNcXRq024p6^I>V;j!59}34wYaS0jX@x_;b|LiPK%Es7d4qbjqZrj z;DykR)pmhhrEtBE6zN{O6LWM|DtS+EC153r*)me708%rhN^NBgF0mg*F{|q5ZWObrA3GTS$I~ELbbk0mCCr#84RMPJ1ZHzxl74ye-^}Oq?qo{sG z$-sbWSlA|bDlrR?UTR$-Qnsa~4VafFG?J=BRCUrPmVy`Ww&Fy%!s>vc2$9PzX-n0z zS-boyE*T4AS{l1FXVPTlJZJ|n|ZwiIdT&bWLW1&6Ex`bk@jG8A>Um<_z_W*D{S(v$d#hB_y%ZnNjq z8e(vevaw(g`yf@|p|$UGo-7aGMI;*~6-(6AfqWxPus6HF?aeCQZ>FV*% ztnK>2ip^5x7neu?ge&BIyzuAGwuK`L0y#O~2IBhBzfa@i=THGc>qp0e{a@E#HvFfp z;kLwMDapPf*1qSf2lE;~S)L^M=f`DtZ1v3w4%MAMt|-e+O~h0jI-I4W@;s{;vP_BE zqXkD`KE}R2l!n@}<`BR3>idh2J&aEc42bL`w;gTRnx%wy^PYk*d(|!tdms5-B^}ov z?fk{Lb#uoS7uOQ73iXGBS9RZS!}Za$8s}E9vN|2l(ti;7gl$$3fXgG&>I_O+@xhR9 zpoWLjH6EU>b_^M#s5r6q^kz1j$y>IQ}u^WWV#sBiTCgAOFY$R5GK>w0}lD4uiQd&p6p z3Ns+VI=8w^u-Nt5f+J7nYqj?g*L?DzXGcwT9Wo4*Z29wi?{B{^X;#7KIX_q(sWsMz zjmkZ|icdb^#Y!KlPy1lbe$KJHk&RjS0atPpDxC(8mX0zID%C1zbqvmfdmPIQE-B@v`7&z7Uku&~Q zDPc)Dm^j;iN39UMz79XuXav3Iw_Ez6 zU$H3b``$U?_QNs68J5zxZKyzLTZlllMOZV|fo^%827#PsU9R52b%M_=o|q z`yXdwA%=DGj44ftzSTtfIs z`i5@8``|o3@ho`_TeeNLWzro{gE4ljbHZ4a)2ZoA>fh#E7GmuD*4Hk;Co>_R=X!a> z2bVqWFMq8?aT@DVWnY`~X8N2v;mdjGJv$_lc;RxdmEgnJp8_AT2_@(Ie$KCl{O%5; zS6uskDP>i{hF(pf5I9FI4kbh3aak4>b_Ay&91ua0G1ip}%HqDa7a*hsVz-*v4GM|H zX7D&4UV~dpoL+{lCiijby8aFvy#M6sU2X>bC;jc)bk%2z-ew3jb$s>WZH6*xC|MRa z{Joe=X{)G1wG4yyEm>>y0x~wXj154)K>NL93th?o_52&9;EE4O3l*YAwL~lbUgSOb z#Q-9P;(%SL2Zk(O~k4MZcOG|%Hx{gt6&4SOOVwS^@9D#a# zfNWRbIuM&c#v8$jQB#Pu0+}YBs9`~;!3@>!ofw`!{G9e9DwcnLdE;D1^0(@R zc>V@ouED)lV^etZvzc4P>ps4Wxo?|G?@aRU11LCB(z?b&!&LSX35Er4eBs+?sF1|P z@KdBrw9@%_Ya{TC-KmlL+g=(pC8UM`iLUfr!nIsG=k(!>ac535+YE|Z1lL!}3k za-&*LdcMs#KHcv) zFXJycs#A^;>WNLrf07V1X5RIG2+bfEY9+;(>U;pY2N)&bTu3@smY!mRLE$u_=hAXG z)UU|sXQ7Gt{ z&CS&F_o=>~ui(lq`eaJ$Dg>?nh73O$*Jzs@my&Ra1i^=r$AmySa;=f0|6N`$%?a&o zc+#G>9GXtIwo^`jj6qM&zV?^?thbL*qahC<@;dW%?GhG>x7* z$wFY+@dnQ=X~|s8oMdLAzH#-9Z-XW@RNrtd8ZBmg+uQo%ZO{BAeMw5bx|)KPu5;Wy z7)}ygRruX2Mi2dW9mMlix7h4-=DcZBYoz+nPg&YulM}$EME@4nfW1KlfF|u#^de;*n&}ueCIM$^#&hE>#WlBC4qZ*vwGzHZFax zO*Ed?igeP1<@!+FJ+;ag@?SYEZTBsm1%}=D*NXn+oM z{Eke-UIj^?!8qFx%n?$jmL96)HoCZxCVWpQKK|){Ze_dPVYZ)1y4hiqk#oG#-C26x z(W0ox?B$%|+{aY_OT=UpVEsJ+9z4N7fX8y5e&KZ$SWr~IA@Pbtrg*>|SL3~}A6aB% zq<_e*przA(5YG@hNqu}rOp49wj7@VJP9x9l!be_a`p<|o+{zY?if%8U!D)z_*_=&U{B|A1MA~Ief^=E4zJZK z{^Ju(HH1O=DAB$3yA}3K){qa}lnRX}Ag@66C1LNTHyTvJK;LHRI_vj;A)>}w8C}s1 ztm2YGf~FOqL@@mxT!X~R2aV=iU|8swYg3bA(N%r&6G@u{U5_+uK<^d#0p~sJDeF*c za{mWr^-ABpptAXo3rFz#)cLbRo_s#Ed#K}gl9PP@T zV;LpN6YzfcLMk=Gk!a&y;>bKi{({n_@Jxq#G~*kcq?lD?{88{rdWR}a?rhopC29#> zp{y!K&cVIB5yMx|dO<{pzBi>K!W!i-?hadC9>gJ^*6;o4wcyo#!|=qy9fh#kDPIG5 zu>IU2q8veRbR zKTiKDqAlBBg+&lRaxH#%HX0g2kL!CqEnSUw9JkmV`iFzWl<-+TZ!RR=T3mj#TTRXa zyRUxyy{KLkTbFUjoT!hnfklS9wXw%JOMYI+8LA@*Z_fK}eEh z`LvJ-tmqJJld+J91Rl}ev72CYKD_PVmpz*opD4vOgL1HSGJEFcL%VV+@}yE7jt(y0 zpN;j{t-AwQ^p%UnQ=g~6N?W^FJxp}+Q6oQz&cwo*`M$fXt;$JJHIS{%FGZ6BFmWRM zU}?GoTOuL~|LQb(_MNv^)rMV-yissslHEJ5sT(~j98Y7OdpRK74OR8-W>ll|dW z%E-)1dS~!`&!jSW)fb3=j|yywo2t<^Sfj{|zXJ|7-*i{WTDfnW&VQu&PJ)wJ)TPs@ltMd#$X(Ef@%y z5DJPHP%#BbS@^ctRYy(7WlhI*Z|}9#R!`;4MMq`ZiycYj0$qN@6N(j#6p;`}QS11V z=kbr=>5MEC5>X%$1=sE@WIw0$9v@eNxUB)fvQgCT6Lnm|KDA^9GBGtB5BAm&#glFO@UpXGaCf|=0P@d+Y$AL# zts@S|1BQ%35^-Lwg8s4enYztymjX&S72X^xV@(RJiw}3QZXvM#hGG z?Lkq}@=7{z10Bt&DxxaB8nM;Rd49Va3QHBd_a{6)J_a72y(Ruj8K0Fk`QK{(=5%_J z_nXX(3K5F98$cS+)6crnbI%9<7I=y{JvmAGChw(#Who4-;N+CtUEAYvnqIQ;y61s^ z7vwP^1w^BmuT9Tp1@Eup{@DEItWfDwKVX+*~Ke*wZqr<}&0c z`+0R;SJ9Jb@u=Q=XiA?bS+M~&d41V7qpb!Iq4ynmNws3>pdfI0d!#b23k~W!AXVUe zpL09&#d^|^>tPsJ=;;}VnmWaE0u$koS?vyq^;cVWIp%W$n0bqna=923C9=5nhzX@s zbQJXJ^Eqrm64cVJD|<#uD4h8w;;X z2gNfU;{mSi{7`aF-Y5FHbj0z>Drp&|@UHRKKsm;hr+G?o**+qy{K-wI5 zwV9Q#m4m0c-<77c(ryl%W^11frdU4WmL(G zn+eBP7NjBcN)@lmIZgsVFxUx*ghcPN_6^5}I(&}IH6Memx2n<{%D_wO`}X|4XJK>tB?_q{e9F3Gk_50boo{k%z~BcGIQ5Y}cC~ z@!Bn$WBa^?Ju0d|F$i2LNMa!EG$R%l0pWj`*Rfn&Zc!2WZFPM>S6OIGDW#;=Awxr9 z_&%sq{d-s@Js4m=rHB_x@bd!lDok2h)n|^0;kn;x`?=&AmHGteW|(dUpaa z)5xWkoyl(c^!;B&bw<7h?`LAYb!pRhi?hY&4V9E&|48Egsg^UK2FOGZAvMviYft{O z$aP_V0kJ%{!||SmXH@r5o|A=o=gJ@d_{v=-9k%|(YyWwq)E1zR7b<*=W_|K-e;ZK) z2ciTP0!uMPf**NGaJ;tqfPgDrvN z0$I8SD=v|4x7zKAR|9gJwa>c;+#5~gSz8Z6VXp(nD=?lI(de?7ivtMOb$Z<8P4=?{ zfuhLo`-3=t;&UJSq;9 z?2$TXo7%#TYyTQ=;^9CPB8Z%P{!ra62j#Zme4dUo!sDw(5{)^%+Zo~IINfequlRs( zwrJgJDSkot#4})e;7fcgY@_0Lwp1<|9C#=Vg7UleBqm|9&l*)`#;sC6-3cR!GYe4B z*-&fU6U(AEt#;7siLtwb?0eqW49==MN+rrQ@L5^L->eFj+;IUN17W@rPz`+Z6F)R$ zzQk*Fu5Mweb$z(IcfTJzbR?JCql!#0t{6?|!7-x5LXFQB)*pKV5PlAlc=x(BN=9vI zewxmc5H(T=xg1zg8wyC!?C_knIPd@aBG?`)DhV{EuRD5dH=vYEz>5mQ%2l;S+*LJb za?BcyQqaYjaKMEN(YZxD*vNt82MwO|rL9ElsJ|PS>YI+}UoRPBp})PR ze~aF_VgZJT`2;j-_yiX8o6JLAq);Ba6@3rym*B@d~wpO~hdK#}U zCJt(Eh%>Z8v)#>Q=Wa?=w_evPLI+A1?f#v}gYb1Qe~=gfl@;GfrF%X2ovO|n>obH< zlrpo)+SG4waB}Cc?*N(g6|O$O8$VEq035(Fd5bih1OouDf@}L<{JG z(qqS{Gp*t)iCiFTYj>U`>BkRq{uZB7lL_YCtThm`+Ff7vE@@ortm$@)l7oR;Z_rMf z+RDh77`=28YFur)^Gc2dcoRcT$=y2J&oWXmb*nVqhR*Tp+}iW1m%?b{k9LLQK{ia& zIOEWpPw0{@kH+*+<}CWcTwX}M>kiTzhS3l%(Jrv3`gW>qk>`xZ_E-od4cn!OnolX~ zU~E4O)^l!s=(Ev+SaO+%+3P<}<1$Xm0Dg~0YbF|)@6|$ zcAu~bzrIKZ!#D{Vn!ahQUQ>N8OGq5F=qmC#9W3gRav|64k_P?`N9nPi*5WYJe4E`_ zH3V)X!H?0sY%7|c*Mt>Jy8RBk&(Iog;oHL0F5XY!-F;(?2GUH@%p%7Q#W=tiCt6#m z@Kf1V8^gCS$eCML4rK+&M^GUkFxgQnqo1+2+W0$76}^M6uPYPr7Ttop(PMo_Wqk{dAU5=ot7FS4j zM!)*BzU&og33eSs(sIBh$LrMvyxSFdX^iXDt9kFX^t{qgHn&n|t9vIpxc(9m(@le; zVT*MK2G9i`IhE7QstBWbMt&9xL+m77xl|ximuDaD-1_7DF1y0={p$>HF08ftm^GV0 zOHw;kQK}Sp^ZdL)(PGLB@yj{~1s({j7-LBxLvrN_T(kgMtm0C7g7US`TqZTihld89 zu6}JIz+=5%iRO0ZfD>Ej2d`$!l`|ngtD=Wyw%fhSZ~DTY*=LFQ# zKHKy>M?qB>S>+I&xdas`U$}8mg?YQ=H5RYldIYV+redtOe{GK`NmdGeePzu`3i%0$ zmu`n{&4iXe1c4v~yPy_~`{+4;r|5+tN(YUTWlObrfuw+r{;Ll6I#`f1JIQtDIl8Mi z_H1N+>z=Z){ zgNNwfSt^^$(IMH>40a?^Ux!6uinC@-``q)VU0G}DU>uMjk2s@hO9tK4SIk!h8rUQ; z-WZGFcC{InmVqs+{UPDaI!49-7ys7Fi8tJbdQ?QraU80SA}hy9Lf#rgd6^(q%CQ*t zNE%}NmnDEmBq*rg^V6uth(mW`-Btp@4_7Sg+OBpO4z`oQ<0&(d9IfD!0sY;LLV<}X znUXYRq!{MVaOWuqNy`kf_ds1;Swr{kUN`?F(>f>xEjgpjcF8CtD($$oZ0Np4tE!Oq zdQ0wn%Gq$_EOI16V}NCRCqLmj`ul3ftfAGSX~$J#gs@)B_Wc1Ddzf6NDT8i4HF(;` z68Tfrb#}B5t;867Wbm@ZpI6wM_0<&wlBf`VK;z@@TUUL#DyLuLWGyS)_xOyj+R8}=)@66@aytM?~ZivO6s+6qJCVeN6al5 zYjbhiGkGdJ99I2NWN;o>E8yQ&RAfREI~-~k3yHcD4GAMIF7iwX?oRk|@fg;-(Lx`S z5{HI%_sx!qk6KD_6&cIOEHP}shvZN|we{7RRmjv2) zJlMBVR)Tfgm_3yV(bwd>kyZH*;=oszk4_=9$QuVS`-O`Xfdqzb?g?i<26=@O; zFKVKI2h4Qf!-K#yNZz|*hv}j1AcyaBPo3p9NO_5L#kW%oZJWtr4&;vKvH8vx$1k9R z85)DXgqwT9qm!GrrTvE&9yby{r?a&)*|idNgmAmJ;_WbwGT#9m{TSw3%VyNp#!D$S zl7B{4tXQADHn_DfljAeA_V5HBSaZY>4Bo z(#?G4v8~{=tA{*3^V(Q(pDQFhHZ`fTQlrnyV03yis{MMcJ{10^8VjYwmG`RQ>p2q{ z6$hbay}|i(sH)1Ro$;igwvEGmiAvFYwl??-D{>sn&yvDR915VqZlG^uLqj zUa=88fxFD-LU;Cb=00mN;NT-LDu`KA$Jv!JNVpct_1u}+#`}8$O2+~JAe;*pvM|sb zwQQQnz6hND_2uF}dHyVX#U(DLj#A@bB`LG@txp*d?}%pHaZnwlP1udXDdgDQEox|bkGRDbl#&~dmTBj1V1phY5iIfn_s_C}rU7-sZ13h=1k3{WXu)?HZ?`y|g44+J3S8p%PYg zSNUw+@Y%i2U)DfNF1jd6A?x4VUmsPi@wnnb*FNO|d9D8f9ZH5UJ$5$ESXlN}vtI=3 zXfNaXj-k618R30b4c}Qsea>Oi#tJ-IyDLWon2hNK9(y!d4rE@bQ>SL-s3q+1hR=5@n2dLFXYM7n*yb$cDRKY{m! zA2jd}Qf6S=#-U$myW{CB<{tn-&X=RopR<1zl+&MXhtgvz;?Jvc)hK9!*=Z6n)EVu2 z9ZtFlvn{U=^?3W-u8hBr?RAlQajoha(rp*d6X-!n3kG}BkTlETu`85+?blH*st;ZU zk8y>nX<#vRve=UknaYowX6K*KqbcTn&I0hf^Pgrv{XYvOp)!@)&E37;vhmMhF{&Np z#;A~Gg~tL9(?I^-MzdzVrB36TeCOI~q$H=!nqo|oPKrq=on$>){JcE!zpTsMPC96+ zXy>qP*+#fEweX0Le=g7Sb!+(X=&S4CHs4%CVmYjF1!ZIYv}^7QL^w-~bYwf%Y>1!d zF=@R=b6()e;_VgE3it@PTu+Q{(!59&FrTr}v=iuqOx*Wv+GclHXMOKGF?su~`5#T< z3Z-)T-iv!VoTuKl68@J>;8Z(M{Gd+JA2)070NgcW7A^r5KdbuO4{yKSAtHZQxff@J z00gXgy`Imz{(pWBpKNyj3FRVMMMiz}FWb7fuZ+ z0e}wWeCHq<7<4!Zc_~=|zL$DR{eZ|w)){J{{f%~&u_oC<$zI)W8;|?UQ5`p%)VD@x zjajU$L3wt3+xp{O_U#OHsN4LAi1qb7NyV2mhpqb#Dy`J=vSk*pZdQ;{(ZYQjbW>>) z#jz;0+a8JW?OiQ5b>hj%$K+eV)b2sAwx`ATva+m>DGc#F?wwkQfwU{y@FA}wq~o}y z5UXI(5-ADPaAHH$q@cl?{Yyk)7fmrOVY?gnkob-sn2b3M9H6vG_W74BLUkU1FT)bO z49XY_WQYoviS@vP-+(8S^w%QH-BIRvB1&>P8J_xksfA~|ZhF!ns`8qSL53pL(I1Ie z)yHQ{!HA8A<--_jjZQF?_!fmq#$qll)9yvH$hr)BkO22NG;qP-Gi3?t(Mzmp4gDEP zDifana+@Bl*oBM#F7HlG9R>9b+BOM2x*TUi=+C~sAVvs!J<5v)rbO~P$!Kk_l%m(9&~mm4wi`*rxHqs+`<)~ zo(JBq2J@RMIzS~#uoB-TjQ@qW2l7!Wg<{17J%P%iXw5k!5#9|qELC1|@*7%Pc6!3X zDIPOlnniP$t4cjyv;Aq*a_FrOV(6u;H_HIXjSz+JFJ+!|{XHaHKk*N)hs55ra->S8 zv1=p*>1dWLh&_`f-U&lWqm~3`O6tXj_QXOSf4T@b^7cYV^?{#-WZocqZ3tNmYPHhf z&uhj^(@vJ8N9M}_`s;N(()Jh9VBTTR``7)-Uml0Yg0z|1xVwfu)K**z9oRyGeDH3V z$6`@=g3!_kF_UutA(twHR3w_nuHrXXZfT?+mG5IKqNp1G^XPK3p+jGFWl0T(unN}v zN?4)F=iMi2LZ4{ks}z)pD3DShHQ8?}itER}5!JdoCvc+hHV*ON9wy4G_j`4id3c;N z%UPG%89dzF(q46jfUBMBI6_*VRbo_NDUXlusJ_SSL9=2J&9$RyZyHHaw|~2yD3&^` zqZMNcaYs3l!Y-UTd`w1+{l- zhp(VNmkC%xisA(#f2dC7rPsNP_gycsGR~-LJd55XR8FstClCLkSO2(PO5Rch_2&;4 zTs~^4dY~~?sv*QhXCsT-HguEJ zr{Ck_xm7S|TIs^uI+J?s79^kbbJZyiKKi(KaaJTP*%^#~$H9Gvcm&$K**%ne$~~Wu z6o2@ich2;D=`o@8`0c)Jfxw%XQkSM&^1WbrvXP3Sl+0M{Nl;X%IyGkgOyZ|C2Y9X( z=sJ1$1X(O*2-w9&Za{N$>&BKs4@(V%W?IkeH>eGixT^5t#>#vFC2!*z?y)b>R;BCfdtM9)23DPL8op@D}e@hurPmil#R)I;{dh;{$iDG4Q)_LB4ZhiX0 zC%XFq`nXxOZZ~+`v)Y}JRXY6Bk!-u5bh>E#;pu;m;)F6UfW7<)bjWX#r8-H!HlpcEPE+RYO zg!?skw(X`U?s2IHwdgu^Rn6y|Khia0;}n3hcGhUfVydycmQ(c`1%PV6<@m#PN5qYs*$vUEr#x=KI)P<$oA6 z#K9OjO-Wny5jlHEOl57tMBjYi_JMno^7=x)wD zcK*P9RP_K01E|MA@a7>*nxnJS+uq8%w*mYmzrU;vHSPL+J>R*N364z;NQbUk%&et2DMCsohVxLY)63>9_8YO1 zlN$ltT6ivZZp9VsHhQH$d)-SntP!a4mm7$l0(O~Gh0frK{{HO%dQkg=+eWhvEG$f* zRK$tb=k09^m+j-471cG9Z@Jwd97%Q*J7R4Q-e9xdeRo!<4A2IiL2kI5OsOR!i|&bC z!N-mU?E3-<>jziF#F8&`iKlo=#%Ogh@paXlVt*GmTs{WBYukHeWwQDM^WBH^eP8O= z7}s{+d76m5*>~sZKSYG!>oyr8clo}RRcPpJ0EV)*+np&*OiZXc1-yQ(^u|BRZ8tgE zL*fd3+T_XR5oAYi3#qR=XApPK4<38tahq46DrRtyOAp8O{#M=> zoX{RobYQV{C0DFbsN3lMHlt0$y0h&#Fnu!PDB^+-`S0M!8a>MmC#zWBfTm zSc!RBuwsrxPgPY#m*>&cYjwDY=IOA>fQkz#_w+nQ>n`{vPvOr?8GK#17ra?TP}#nF z_5Thyyj%wAayZE>=!c`*tWwS9NV3Mx`SSTuTV1mpXGt*Oqq+Xr+a4x;wfSlF{MKkd zx3kGsc8le4bZnU3c4-`GVKw*=%vkuBsa=Uc)pT zDH)4_rMXVChdDtR>JpjjI1VQmg9B2i%WJyIyv-xM8|ED379-=1)>>NfYCmp!-6@Wa zu14KeGLkn=EUazN*sKfhem=7mvYFN8Ok||B0c9qeR zThB3oVB*}oiLq7;d)H|oq;zfR_W10pwT9a2euCx<^2BuDv79Uf3D3$k4-w{mZSB^T zy2>fYozMnszdP;+4ILKWQcGIFg|HhI&@|zM6n@I6YeueiOR&@eHY;0UyW!s7iDWZ` z12w3t^e-)sy^w|PD4<5~kG&~$%Q>s)ynNUH<7O%mOVN_6)$eo`2TPE=?slRdodT|> z?V5c(b0HN(u3BAaz?d9)v-*8qf|dMDVF7~^sB8endPHOu`)EVM0&*&wN^-ZOu=iI# zjqS!Bi}7&1EP*<|mk5Hzbx+~8wt-Ltj3Zz;1Ykoa35V1YwN{uuzYEKr2tlK(wYM_g z%``{rAIyd2^>PQkxEr>kTE!S);d4t^4F86bj*p7VkyzX3n|Y>D_3aj09f^aV#N!ut zeQ2d@2J8%-wNSMb9NCd#iJY6*$VA&#WDx;@=I9V^--gEb1Ixu1S2X{Z+p+X?LRSus zv4M39PzJQ*;uy!&7dNfmb}nlCu?t3xYV8J#@xN>PSml4(ai z`_>IKW0R$)iD_IXs0EV2XxtYveX6OBZmW#{_TnT)t z@4lD&PlA1v;VApV!=K4(_2Ds#W?Hg?@0uD0>ssxiy7-vygR=NtDDM{Bs+eax0O^Bf zTjW;AShIztm13K*E2)%c407)**pvqkB`QXAF@?59AyF&eq!5UJDxX zVg1JZ8}9J&ajC-E=tvTsh{<-@5Qm-!i5pJ$*?4QRG7=k3zh&e2#7Helsak5)M%#Vm z5x7c8vh_%5XInl})BS#;0;!skTmhC%!{$gsu#(a#KNBW{LF!>N_Or4zBZejh*v!rj zg46g3wp>=Pr=ZdIhI@9NkAZ4D9$Kh1k}P8OapaYHu<`;|rGSO0pM316&EZsY^BqYs z$ph`nQ-1w}t1OqgN%?IoKrwJ5p}cs^qTIIO$yU z)>Z4ee;>vG8}O3&$$_OPHd6m{cB#|z$!Caa$K;n~>R{k#o^BEo`|BWaQAEQA{@sjEf8xM2 zjxX2@h>29udY>RNrBm8UiXfrXnzr&@7XWX@gz{So1-~^0!Z-%Tnl`AS1M>$V)m+5| zAGi;eb_}pHQz|{(CQZ8V?`po$m-T)wFF>d?E$r`S=hip1ao z*zZBIoUi3M^cP~|p@HQ;4%XDmTEpMK7A99@6IIBC{60pO`WyC#d?bsD@)+7SBGktcxs7b=L2dc>NV z<-Q&>=&}SIB&>dtm`ozjQ#Dkj2L-<)2zPD?_$i}b3MF1sKXcRSGCW1YIqX-MC;l00 zcSJZkLTiYQlj7WJ5SGuV+r=X2S6Tnv>;b46Fv+7)V~H|ynK|r(q@o~_aiNJ8-d(Q% zfl*eKaaK)>2rkUrPvHohS5BfNYiyPm*+x4@@&_8{n0KxT@fa@ zzH~EF+EpSWl{6{FTQR`u&eWk`NRaStyIep{nltp2BG96Vf7U-OnR0NoyA250TZ)+- zznonBPth^+M7`0y8o257@LcQOW&^enM-tKglLJ#{3~OfOXCdB`WxsR#l>Kz!V0iFn z`<}SzL+-lWwBI=b{*%JzaYJHHN-ng=>$BlExOa~;9Q*CriD{!wC1MbaA~JU+s2|-X z(IlctUhYv>W%C4lc?kqmAbb?|ic&W-@x>A$_PULD=EijF zZ7-ps`~-Y1*Z?h?UyaGXB*7Ih%NOusuI+JCIV_F3!(XX>sbxCb^Vz^*kgCLz%_S?(-e}jnG`(A6g~6EcvrA=dDcb^Gx`5gXJ`ip zMM^hq)xlZ6AUXcYgKX@;h+Sj_?9)^$PfU-GmDQ8S=rBYRkXAB4vP2EELJX-;!9sw> zx9v;oSH(LU3Q5dzxwa_5NA%_L-`RptAi)+uJ!FGFPe+v7pA?mLelEyvkKWO0r1IiP zS~Cy+9t;KAa9r43aH#}$?euX4{+LIEnvhh=6C{TWPpJNrj|=cID+;*#A$l2)NAH41H? zD8J(>`>G}M`5hPFG#8SZir_pklm~6Byjiwb&gA=P3v`cyaqjYRaWbOI=Ry-Rm=A;H zB(e9f!fvz#XcT!pfA#{XG5AaCu1w7yE5i*QL|898xw1R6w5n+LHO9vJ21y1d{558| zwjq2Ik63m?5y@uw9vV{eHyM5SSkXh38@{@7;xQXZspUOo(8kT+0Vw9k{~q<=S?n#L zi|vh;%(EYhRn9{zQ#IO>@SP9_kMju{`C$98^YtgPt1 z-WeNXIEuS+R<3P@3@I#}F4LYqoeDwzoVJa-p+pGZhB)%j>ow-qyo3~as~Y;?#b0Kuk~OHT0(sPc*#kNG;xX)!0Xx{fwx4UYGpX6fq@(ZJ zuKJyfJ;dR;!u$UIt_N7i6p$0b_@tpz-PvfQXT17CfJ+`j3_-hKg-6K&N&P>?;~ zp?@(qFD+g^@a|TW91V@r1aKQ?(5MajYkK|*#1#K=(!1sZh(@6$W>PejDtwwBG)Mhv zhsgEK7H0d5juP^QZe$X*lnV?7g~)Ak1E4y7N5~QDBh9WJx90ozqtdqQAWO7z9LpTz z&YXglJahxDu71*ZkB;ir(&;_F{>Ijy6H3Ts7O3GN96O=2MBZu?i$y9pEDSN{cvQWC z&}2X=_VKlRFSD~34-CPDBEk@#ZZA#mYH&#@gNeoqVQ#OjGuys&mZ`BkK76zf7^X)j z>Yx@-NJG9Dt32qM^dYs&5h6nSacD++g$u`WPast%pbWAw6CgxII z;QizBpSbr+(P}N#mxhJb`0mwcoRKNhu8uG@Y``PmatlYq!;2iUM^!KPzDJ%c6``*x zkJIzCKj)SMFL48IhBhN3Y$y^@B#5*}(STg~0z_!&#Jck2M{r<5P!}J?_03uWFZ`mp zb48@v>@nzyxvU!c^igyNDQS{@2A}`Ws?F}Q!e{n%;R6uI)h6bNb}xh21&i_UGq$lo zRTH50w3@dS+3=m$*{{CQ!usNq(HHsSxq^_#-F{I1)%=rwk6rs;^+`So4)RBLP8eb- zitNXADD<0+LBs$!cvpjwxVZJh&}a|_1G3t9j0E)8}-9syc#ggYuj?u1`|Bxs)whw76;k%N?IYA01*5?w-_$U)Ovb>r&Ji1(oGfdj8 z_m~vPs%pa1P>6nm)S<1AN3IUA;g&CA?;0Q7{^v%U2WuVC)7%b>B9TQ-01w^2dgrgE zRswP{8Zq+)Aj3WhNR9TOD;ojRlPZl^=#Aa!ZM5A2_OJ^0WX@vNf#m`(O6l$=y-hj;!fj~v!$ zP@Z~RHmRziOOyFt&I2glc+|0ZOlb9 zMTBs9A14sZJ#JVYiuD}L;JOJHqAv5BD07hq@P+BY5HL$8W9~Ga2k$v@Zs#P-NA|D6 z8io(t{>2weBwbQ{2qDbQq>VicCmXM*xwkOUHGd=pH#Nm+;+T2$qJz>??Bk5i`%uaB z{be2uPY5z<9T#0G7Z0Q=OuXtm9QjJQPWV&~-9dyqD`P?>V~o>(*uGuaFh1O6i@}mo zO>>TyQiTv|)0L<8SaX>7J^q^3rzqL}dK<{F1?=3RCPx56S=J5Cqy?xrXtu|%b2e~WOkeaV|Yx@l&GjEyCuhAxd*@WNXA(jAA)U- z!jTh`=Jqw9Br`=e#>n}9~LxAsr+P!P{e6CgS;c>cPJJz-0mrXW?|g+u8Io}J`vy^v5| zWz5xSl*qb1e{llP5+1gcCg-u5PUJQ)quR}x?E32x;t$fwkH*iNpm~m{kYV7NkzPJ5}wFGX5%%)mw#cY(Z^QG>j`S0ImjJU5L|$ z{LI9~#RsyVp7@th%>cFSr~Aeu$fV%1q>rycY=$$mQM`PN;?9USg1LMy2UQaijI`fv! z{kS_@y6R4LTkWj$V}`zCR?UXrtNFDYSoY3YylUDVyd_r4qj7tm+?dES?E&=)OC}n! z>2E-$%x>var2D;epE=bx<<||B9pF)hkJGO|d-tKRo9Ud;q#u|twK_i9 zbrcHabj54lXUbSpYr4|l1vos~L9YKP91YzPhWp?$z*a2Lumu#>f3i|BJqK;O4w^o< zd$Q^b8j8x~OHuGRbwk=UG*WPb(sUC9ng_BHoRxMa#Iw!?8m$hNS8M2V_}okWOJ94% zruB&|f`hRC!3;wVq&Y{z5=9FO-eYHC{YU?>0)O#|Nmq zJjPPAHa#W%E!Y5sO^jJ_C`lOH%gHv+b|OZo5_3 zUwy+}Uft+eV0*z#H{D-8&%ahyA~)M@Hy>rGfAtp@w$F{6`8Bn5$O;yr*W8vHj|@t1 z@sIoz-N@N|QS1ROkNT1)Tc1%q94LaQd~W=K%O^8)Qj9;o#c#_O>kO?$PFqCHjNG8A zDHR10WG~o{0PM%oQ^NcBuAE-7w}r?CPWzSKx#fp{Zo`nAE;l>>pu9i@%VM)pQ<2oj zBPtk52O@9;D2yRiaaaqA*vTGRll*r%XqrXX=eykD*TP6OJ8vj zHFj%jE87Q@doYt3Sfk_=g$;5EPT+)a4uz38C``tX*eO*k@>ni!mk%krnjA)=MNhNR zMjFT;9?o{2#kryL(ESVmtrExyVkZk}4+j3)NQ)FYZqu4Wz*+Ovgrq$%(H4Vap*1i^JH|^{Xienf~X9>i#*V@oZig$TkicnddOEe{s z^#ubV<1OjtwX@mOBZ1b=;nEx+@7$(o>48UpK53tWa!3~uN@8jlXLqt`cO4qT z)VnXdq%112GkevEpH9jKcF=x)6@dJN^#0+Xr#fp1bZ%9LMC7fT_VCqxV;uVaG%5m3 zQ8Jvb*O)(So@?*5xvTQb4nPQ-k{o^b4==QEM$5Mwf4R!2A4>Xer@ecz)Y5EV@cLdx zx=x(t6;W$G2jPPH1M#rr$S^9-AxO&u8%BYFQO1B;9$7dnt@;<_@Tk;NM(^~rOg?M-IyLYMk_Nl>7?_BC z@5^8tz{Q%K;V-E`2-nwhO4eYlhQhM~?@7H_vM;N<+fAo(Vn~K=Uimu^a$8`by$X13 z!a)dI+N;^#b{oOT$a{a@HJtwRxK60uB8kKr&Dc6RBJY{${Rgo>Rnq6*(!?ZJg16k%j;cSrWVt}j*p7w6#aD7x1g&X#y@lV8FcX@t#e ztduzM@JniXnBK9m{zqD(DgL>NCg7p*evJ-Wub{;bN4Yb_F$zmgheF^(VEoima-mxs zs=#z4KCcTmvm0-7R7R6Aq#Xh3G?I6SXcDVhYyh<(cKW}6o>nV&(wp2LOZ9u+4mA0W zi;_w07oBzF&dZoeueCde=^ld!)!m%IXz^7o`0Tu_4np!g;&Sg?Pfrfw7jpX?{+LWB zITPbbE4PAd91E7d4edU8I;d!TRJrA>J4qDFRX{Fay5(RmC6yIKOR_8 z79HovVF8e8pyGM9@Ts}A;&D5+u2{UMQ@;l_dng$ygL6?KyquU03 zjEV$Pm-B>C-OH}nDT9G1Jp0@!1``&A(0jsY+(aUnp=Q2!B|dLV_?)?I!W_5-2*7$M zOPf(rtPtdKU1A(6_^qPxd`m02u9?D#=s$=VBE}H^E7_}Iq(%HLF%JgX#r-)k_g6oX z6IXZW;S_V@_>}3~^NKP1B8!#2k;x@i z;7d8-LR`9|J+(aAyxs0Lf4G8_Cdi=h9$mZr4_ zuX0-VyEUnU6q(R?{%>3R>xwVwE;Kgt=Re=nbo7G_uY?U zzlD7Nw(3c78d`_uoDoIi*Eu=Ubj+bP3>q}m!9qi~Et=O;WK0Q^)zr{SMWN+zXeW}) zHE|^=e)GAQJ*Nu^Xu^c0ygO{bsyc&9DBnD>fc*T68oB_4$j5%&NxoGF5IgK? zz5sclt1JMzO9TDxenm9&Fi}x{Xs2W4RM@WR4X!QHxPz4pP%lYfaVCA8J55z&vrp1N z>=`n6TR~Y*8Xtsj<~8F6R${!W7e}@Bz;`yb#0FW+c3WFY%;?F;U7uxvM!<_KO%1X9 zpP2go;Q-~_9NZ3unjiI@^4)s@!_J=*0;&T+9v}zk-}>CK;Lx z>MYoLL++85)d1QB{g!g}(K~NA@deT?`4!6pNL1#|!X*p$!P>ZzfG7#!>Bm61#Ez2}20* zUgaR-Dp%0sT_!djiI@nn%#jp1yczR2s&A$n zjtZsBkUGN*JR&|l;zDI&iL0bO9K+(ANy&7c#btKqcdmZAixYtAxkZ*dTfz<+H`yca z)EfcJ?=ZrD#gx%l{HK_c(V=u(QG!fa5S*M=Mu=q)q@<^B{|6)Q2DrojbZMtWg$L!| z^6euts2Nfa5+XyFWTk>IgXb{lzVT~;2+%-8%QR#-?Ek{f*CRd59p-0npq3rE);$fg zM$QB;=%sdOnCk*tEV2UT&gdl*p+QDK{8?l2kr?kI?`BoMd4l*3pkLj`|_0%)> ztn7-iCA{sfL-Sxk&T0W5BURR29Js5tJLl%pkb^;&bukI29<#UiAZIn%h#l06oxgM>@tNx$H`7tk-8< z<4LW+ecOuaCFL7m&$j)RDt<;>ZGuYNn%D>&uxrz1QcRg*vqR5bAhV!r(Bxcn(XG7M zyRx$KfH1mNf$7M~3+L)M$X$Ho%u5?9A}lC=YX`jB;bSmnR~)R`ZfLIEoe@f;vUNBK zCS7M#E_XZd=6Zs@QY2ICHzngfk4I&q4T4=`Udoh=$PH}g{-5>V8GO74423ra(9>6>sf7hbH5>v`)L>|!9L7^x3$VeUwQcE=C8Jb1!~Fu8C8~}3ar~C_ zecURkLl~XJh02I$kDp4nAXJ{UgwkH>NmcGwgcNZTD zIvul2PQQi1jf#h2rJQQxjmno`t7an|a+refX06{>L}gUu{*?7m@# zo(IjSW;Hxd$G|dP)DpFMoryxsarHDbthcK2}4QKwXMjB4}^!vJu^%2P~AJXsF%lE=UnmPN@j;RIL51GC@6I$%jS;~l4 zT{D{@DL1-D;2loPDC|0Fx7?o;5KJ@>E0d-bTnQopXPEhaut|S3AS4BInM<#Bx_RMCWXlb1?BV!~|IpD*EuT2_Sh8gJiK1(f=MUowTxWRg0DsV^ zj)&42rB9LkM}@h=V?pg?Bd5{v-HXWmmU``CvVLZI#vM6ciu1lkNHvd-w@qaMqZpZ? zqS9r5D+21ZoCE_HeuFsyHp~B4+&S00J4jmM5iWz5e47|Sg?XxN{VYvSq-b>7x_Xdl&^>Ml62bT zJAaRs-cEIF&R*F}E*c#&Z0C@t3vlqzvj+FTc@e6AcEe>Z*RezBdExr@L0f*5h}7Z* z3Tst_4#2*6C0MPF38znahNJ(>9mE)tl+H1*GC-OU@^kF$8s7#Dtjsf#i$t%6gCvM4 zKi`tBtrlvB`Z#KeY!9crt?>@`!CLxck}2YIwdDKsZ!7xSql2+see>F^FMr z_L(oic2OP8thMBL!~qXiX+=(xs|&q~c2mal0cNnL3ea*A7&P_IKRy--49xr9me0qJ zkQkFrszUiy#13RYrnl~bV>iXRSu)2nu_Fic8b6bL_(Q0on(31;ZUTmWqKWF0#M{$< z%kjTC^)>oZNyFt{^+uAt%T~WwcjIg9vu(&A3TmTVCTboAddI=Pt|3yzkxnnbQhR3n zC*5sM`abI*dRUNVO)&&!?8z5mZ06N;aIsA7E2FVlQcOmZ)uL-vp(C_qGl^DiLJH|S z{UOO~be|o~g);bv(8_J4V=v>hDgne}m{`EIzAsVD>nT0Fi;i{=gI4$_UN5DK04T39kB4rfi(W?82#nw&-|UIRuvjfvugf9w0OU>pYw+)G$JM z)Ir3L!$_E$%dodOQf7OE`ad0-`;IX;PIGqqHS4W*{_!hT8&e?XaG{{IxL$na;L@39 zCoJG6)nmtD688yGqNNG_gNsT-NkQ#cxC?TWg(*T6&dOq;<}OX9%pQ09hUaizu+qDX zQo*1P^{`d@?YlMj#Yfqf(*^H06ZBfrIgEr2FUB4PX+QP5@?Ed_>zL{G9Vx{hXEDJM zvkua;k8YxhzPb85?if3f6_Gn!sj6cB;08)?MWUeaifu;)QLtkrfQ%g9Z*u0haqqGJ z#Wcq#I>3SE_;@v7vp;<_tI`L)Y~2KNNE0C%ti$c&z8q!leMkLYs{z{IjcL7&@{Cox zwuyVi;)YypYk9%*a0K*RHx|E|=mA@B{cVv4fK)WKT@pXDy?Qzv0DDY~eS>5-eKiCQ z3KWKC6~xk89@Sm6aIy0gTwR?iTLwswkr2G5_$?{2(9z=o4B+}6e>|Aq^SvAnja*zD z-5sK%c}KD^hJE?AUh@3N78Vv}0E$MZw1qwQ*Pvu&;Ry&j99dN8e!S(dJWNwEdDV1q z`j+Hfq_o9r6h|qfyp^QQ=N${h>ksH1Nx-YGA4~QrsNq)>*62U;FPy=3QizZi7Liju zFOVzJnj=`QIheBM5bHGgooe{}C%4glEa1V1e^$JIoV6^p9!@O2{?4X#a#|rB-`K?M zpIXO7I6e$0NYs13__ie3zJ3B0+9g^ByF0^K34tvqe)>~y)|{bU-+_4i`KQ%4%x+ZT z)4l@G2lv&jFMPW0&64Bu)rpi3GbZSAF5p?uRxM*mCA08~O%eTYN-VS@DA%Q0^!QoK zG_KN%jTqZ*Dk|X94FUn7mlKO9e`$x&bD-{1Dx`+oOL5{om+T|04xQJf`kHh?6B0yf24kdcjt( z@MWUXV-YK?NJM&Im_cGs+#N<-QKhGD`+PB%p#qPUY(A$|mnS78GLgPlEwlUBFZ{Y|vVCi-GkySy)*upYPBA ztgN8P7vVCf=VBZmAD?Y@n~@?y_u<;_aV9PWKOWb1uEBln-}U%pi`r>qt1uZ6vK#`72u zr@wvJ^72b^%t(8w_}e<6HVw^xVJ&*RJRR^I2J-9_9Gc>mb7L& zac9VULX!*i4M&siWsPSii0I=>F;)!9;!`+Su6L?mWnfPh02}yS3bPji_B}GK$(jBE zte$^CT0t0l@XxSXvuaOEH=@yneaMvlFw+w6qGY1pIBNg_lwcTKTwK@Z^HxZF(2I3s zY^<1RvZcMI6X7VIuB0t$WVx81>w1+KYF2*D7thFF66e%vBoQuM)(Lq*!B%}9;5PW72}311&T;AYg%Rro7(h6hbXG$#p}j1Pb>+rIj%9NQ||CYReUoEtRXB`|IzFm7FEA$W$Yz!u+q>yi!2Bi)bAIuNX@Q+!M2m`)V3Edn{E^4c}@<_f0j=j3&2G(2eLnLG$B8kf~lfa>V1L3 z7Iu=}vWo&A-Qu3)e04gnQE!}x9FXM?O4U%S8cU~g=G&?STvT+n$;s$xSy5E8K))Qe zK?j@ZsNBx906$x)vRGjHd0Z@K*o&CsU!qK=Ph>Ao)*Mbr!@M2IjJ&a9Cb#a>O2?+% z>Q-^WVnrYgjlkUtk5!6F?!^|55qZ~hX4qG#(Dz_JRMV}c2J6c+@HF?fbWPX_6#19T z_IvNchF`tI42?mTHy6J!4273WDE!bG>Ia1nGU^ls{1X=zVbTQ&``*p&^5k(H#UKM- z_LB31*DtiH_>#b>{e#QBy9DPR``HAN6xGlE1UsQZGiP%JY;|5>-)!#VsDt_y z-848r-^Zu@K}UVqZ`yv(hXOCw^6q3_r7z=PPwW)reCO_ZzHxA6cR!yzYUS}+@??Eb zZu_6Y%*CIlV4%%nfeZkTgE2Nb<{4keKYsqgwjum^C-_i_fw!$`8XD3ET z#EH`uiVa6G`a;WLmA(t=ws9lw~NauLAq zdg6I~n?=1(vy=N{fnF>==%?Y~oxzM+%G7{nD&4oX!EU`4Q=T$Mia94$gczMVl-+}r ztR`XIv2jVng{Up=+-UTqI)lf212(f1O6<#OW#$6{1u#8Y)-@ikI+G&V3<8+nZZCLD z=#BH8o;q>d-yeR?IWCV=kda}`@o?wc98S%t$mW4Q{8f@#NsRF`yOvvh4bHR%`u=^N zqMnPor@}`lgG`7qtK8rC`8MFeL)r(dln5i=_X?w?8&Ozp(F$+y1qSo(mr@#>)V&eC!=hfmk@LfP z9G2gj3t_2GFw_*_<($4eOXUch$q@T1Kw$MBmb`n2^OML~9yRt0OlFnEN(%GkMdyFq zn9YF@Bs*?lGAuiGd3kwhM@N=5|2b98Z?km#)D3dg)~86Ey)W1r@s#lXY3TUu1R@9^ z$nmlNUIQd3-@K04uC^vs=;va+Ac1^CL%PTa5BLLb{N&#|#+&M!tBc+iT*(5YqjzEP zl$tU>N0b-&{%y-mXBVe*LpZlQhPK6q z?H{0Xh=AnzN$6G%GLf_7%jNdvXiqQQnQYD%~@ zo9#EMiGN>5Vzu`h&(8rK`fM)TSE1Ixc*bEUqYk{}vSdO;(ZpF?_XUIV@nc0$*XdN} zNrPYMBCF6ICmkZjb`cS+kdO#T&)fF^Syx5RIf2tPinktEtDKWtHcD9!$ zHwb>ql}qoPnq>O0cjY~a&|m5p;HnePCEnNmf1|TZeI{r7BX+l zw`zOuNXJRNlT!JL?@iOgKtMlybhJll)6s_m^8guxCMvV_mIg({ILNR6z=Wc?99=3Z z-9i>8@BdbB-lfdh)XU&28b5!ihWf9D(6;d8LpXggF5PHFvy>90__C#hJQ0esloL+l zK(n)h_em$HuProkThh16#e}6`|JfX?h`h^{Ktd5ob>)F-H^(eo`N~PngR?na%1Nfx-ALj6_q*=O^s1_+DmH=yIAmCrwp3edy8}C`6@DoUt`T z(}>86TISY$Z{u4lDjx?OmY`FF>N2lHe0@C~9PXg)Z2j*WCiUM3m*g6b=K^b1!2wx4 z&6@QTwXm)0)NV%P5zbK^Uiya_qh@dnm2RC)z7fgox6v^%N~LuwW|RoBRTB15JrcqA zplCP;TH0lVhl2^8vmAb?lmu{8#hTl$N<5+BpVdTVp;o#!-_dO$bpVb1Og1!YIWsmb zv{*MHgw`xOJ=d&XD^{#MB|X*EG!4%46DeoMmHni<3f$x8=x9CtcnXg?-+K2Bl3oc` z=t|}e8wX%++Rw*EFDQl9&_i#KZzXJ-mrp2 z4Xa2{$l%J0e}^3;T!*DSI1!kRQYM}*pmtQ!IjllFe?AOg3_bKQt6IFt`o{B!g}A^9 zK1}D6#eNqYp>`G&bQ0&0Asf(+{0JKss^+3|N#hlAHgzG@#vIe)guF%)pLh-=FfN(mRbJ-gdr& z$jOpCZdvSAf~XNW6i{w-hA|$BLBV>Ci%cxsv%i}VdPW2X z7Y8<9Rz%IH3`j;%8m>{A9Kp<>``^v9*{Ff*dc1?K?f1|VrIS0!3ik!amwuhU*$XIrss*a4y_;kA2`) zoj5Z0ud%Ucz)t)jJIl)Gk`l{E$ueYiMRn=ILWEBea3&43Yg6@+@g`lzR;O9T6ROp6>Q252zY z+sw~ZRRFx?VW*=+l4T+r|3Mo*bxmv?7K7FjWv!-M99MpUle;MEpN`FJKt`S~vB71M zc*C!@^S#+4Nh3b7f?4}>Pu~`Y=6;@pGP-*gpKue=i3TICWp2$t9W@e2axw$ z&wutGw$c-VA`&~4=rI0P<19+bfU-UheGi5BKSmvN!>6w^wVwU7N-uMxmnzNSDl>ednLLMGy-K_G>aV7BICx<5u^zdn!}s zFm6%lF)_IjVX`d)U36?=4QP5nWbP|=;zEpHXIax-%dfR<><@AUlu>aLtLQf zl_?P}(Y(8mrCEJY=Bjc?9+SUa-tM}-d}U$e-zFI=e_c7vU}?Ni#9#W0<79}TbDKVNV@4eK+g73G6VC)*!X%U%q;82LO_)weN1Y2?&SGdt z!Kk{EH2#;x^Lt=B`@kbBjk84U3S*4pJ zuhp;N*>*bb%?o-jSy|Bnp?Y<}>y@AlU8_R=^so^Z27ME^$CP$puxds9ADPMZ5R5W` zL1RbMLCjq#m)pNdzl+2&%=;!Zx6*9&vzK20*y##&F;Nlew6U3>kA(iNcqOSA>r?Cb zS|+Y$5YuF{mjGqA&pAgy4@1@}SSSN*m|s<)3H0b12n+MDx&D#*RdK5W(Fc$KLC2;r2nj$&~4Z z9NHF$BQS{3Ra}|XWwgA`TjeH8PIC}Bir%sq;@vA^?FwtV%9KE zsf!rfqOQA;PVoI*QLtv=--&vj#l71Gb8^nPsRxVbL0&q~#=~;e{GBFyjZ|FCIw2n` z&7=OFMzdLsQ2wPHDb!mr{0W~e! zTY|~0YIAiZ7%`0ay0Fwj^A2Pp*?m0IIcHsC6STUx{~}^Xob10gN1XpSZjRE7QbMn2 z$FuQ3UNXuy+-3xRwHTT54F;hT4-Khs`c8z265hBU;3cfF^SM8|7C6m9W0UJT9J3=- zZm-<|CJS)G3F*jQdxxyqUg!Uqjx^?9t>)i~=d83hjJTQ-BAK}3#OoHMU~PGqey2X; zS1KOi?$Hd;x(mv|wfCbIxXo}rly+LdY!SQ!FOp9tA6?!dU-TYNmbY1|XNd?WzSqV7 zg-u6_uKYOT;taeejphd3$l2^N(iIX@2~}Ixr(d{u4m9S!x&ws}r~@J)u+H=QpM>R5 zI9!*;@Vs#&HACS2b_}Qc#tN7!D+P$2rYxgQTX;Q1x1CzN+RwZF+t}v0;nurZN?ua6 z%P3sG7`%M@`%;B4?+CQE^Qybtr{KO;#RpPJU7+?m;0z{cXrf^5cA5a%!Bt-`PEOo` zI_K$QKb0X$iPvTJzj~JaA2}(34y#ZOdwYAGC!g=r0ojHB{DcO+{Cirdi*UdUsE4C z1vKo41UX{m{l=jn#NuZV|9Qf?8NSYr%ovAH4kk=_S>5^fck%aUcI*FDe#sNoK}|mV zX-q8D3s_S8u5OQ(q&cd_YH`MDuz-a8cN?bS_)!T?Hjl#|h)SgZ! z;>B60Em=(t+MtNg)62d$i}%L}+8+873itKNFC^W$`Z-wpzYcbU`mR3W$40iv%rF!MZcUo0#ke=5xq-G_O z$*jegp4a`Kh>roQA)JoWF)xblzLa-$TUVDKZ9#lg0Ua=y93j?T{V@H)cOlZ0OJ4p; zFXrjANhx{3kB3u7<(E89!&yk{1r?TY3eDK7y2<@Q1oH=Fox-Wix$zuX0=R~r-TD~j z`FUe;1a1FYKp_fNC4=K-4w#il8&Son{)-+ZtuA41p>Hd83s z1vbc~pnbu|7exIg<;nm4v@=u-N!9Je4-Rw{N^U{}AVNh^APc3_;wu*X_BgIl33 zRe-E!5oF6!M{>KUQsxasCl~u?eyvzOj_eLk zRaI44joPVgLoC5!Yq8PjOp37VXqKBDYHC8Dsdt;rQfAtbo4 zGF$km`c{1L4V{oFSD~(WoEdEx_ssZ}lf&sZ>3F4XBeof@pjQMGnHNT|?goEI-rkDD=M6)t8qq;52`z?RtFkjF8 zK2Xct_1iAIi9`43hA$AbbJs7UJHaGNPg%Q|GI?3hha~ZQN)vx{A|qumktyfdm)yR_ ztv>GK;g;G5e7(U&~?UNmCy9To+- zOcjLwASbNG4s9MDIwjtD5Mq62@}d4fYBY?1mrW7Gg#dYU$*00KQ+L1)*^G zm`KzPI)zNdr6F?m-|0R)pS;Klftra4_v1-K+O)oao2ezt+tm;kFz7e5>}c{J7rh=A zruOG27K%o~0CPc&Qtg$M;fV0CjS{k&qCY=!G-41*IdRl<5pv3ln}xX9e3a1;9R`$5 z_m1;@e2N1{N?m8&$&PZx5N^qQ@%t!2D~iC*y{#0TD^Ay-cE7Q;xQi6}H3{WLWswyd zQyaR7rwqwRQd!IqVvNrNw9I*&SsvNJRjaEa=6F1H1lZZqy&1n#njl`U6AiA{{#P}G zoRnR}h&_#-Yn+NvFw=hGdlt_vnA1vGR8+$jg$Aaw%}sL+ize?LG6~fCTP^1jxgX;b z1dgaKFRlzwCk|J?=4D%PvM*#|FgI4#ho5gDTd0vp$*e)-fes4vhL=PONP9VoNdV_) z^0&^%&6j;-^5*8Mc)-$2EkBz|QDmXAwKY?o=uam~zRGV`k+>tiCO5L!r!L!Orz)5F zgy|A6MI&T;sd(%X=Hg(V2wMWSsRghLxQ+>FMep;4-iEhjV^O>2e*N)7$wmZqOx*;1 zgzN~)!Wr@=rQ3tog|PLw7N8bpBl^D$$*UWvO0l=~8Y$uPLIe#Q$r&_X%ppgqHN75L z&<<(8s#4$M?uDHK0*-Gl?i~u3?@~IAzak9N>&%nHABv%I(Vib}yq_v_3!6Npw;gjj z7!#MTO%|8+g`umH+U`^VZy}?>V)AoZd#@nK4I7;Wws-GX_>K?bmpIq;Y!P5GVEVpu zH2azDq2ShamslF<=vkeI7^>w>l%~%`VDY8p4RG8e$dGlb^^twY%E+E*_H14N#!@^e z{~cr|89En!r`v@Em6^zD@p3^rpxa#Py;qW@P~Q2>FeWM!!bnh*cLT_T{Lw2gknnni z;@>hYpvLSy@w13b~h{g%fN@PIr$TQmvl@?l4k3^6sS zUy~i~6|}#iY+hX7IY2FFgiwQ3-ue}buI-FRJv$5e5WnqZ-jEt=F}y`2-Xgfp;4Xz= z!nsNi;N#2fc-wx1_WZ7^GOrIh)7ywXaqg3|`gVnuErx~lRGPA6 zV#VlH7c&i6C>Qe|sdghb$KkgrO=k1zG?~puw}q4`&;f}F0>as+j2JHqtm23F2R%J@ zl+{kLlAAef;7rAC5DPCEc9H4`a1^7uV|}a9$o5Rha|ig_!g*jam0B>8RuuU!5r*`D zL;W#^-z4AsMDTxs2BLz1fkngJk@TlP5h|0Aco4{RcEgr2**7q-+8M#;y(FROin({z zsDmce8fb|tRfKNIFP$f0`{K>wwsZXy4F%~pZgq<9HBgZBu?yq&!Mm?{IKB&Q}@D{T?{ Ee`XnAY5)KL diff --git a/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-quicklook-45@2x.png b/apps/ios/WatchApp/Assets.xcassets/AppIcon.appiconset/watch-quicklook-45@2x.png deleted file mode 100644 index 72ba51ebb1d8cb27f5c5f667475895acb15e5164..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28860 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�lX1a6J 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έrlIm{8^ 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 z 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 diff --git a/apps/macos/Icon.icon/icon.json b/apps/macos/Icon.icon/icon.json deleted file mode 100644 index 6172a47ef23..00000000000 --- a/apps/macos/Icon.icon/icon.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "fill" : { - "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" - }, - "groups" : [ - { - "layers" : [ - { - "image-name" : "openclaw-mac.png", - "name" : "openclaw-mac", - "position" : { - "scale" : 1.07, - "translation-in-points" : [ - -2, - 0 - ] - } - } - ], - "shadow" : { - "kind" : "neutral", - "opacity" : 0.5 - }, - "translucency" : { - "enabled" : true, - "value" : 0.5 - } - } - ], - "supported-platforms" : { - "circles" : [ - "watchOS" - ], - "squares" : "shared" - } -} diff --git a/apps/macos/Package.resolved b/apps/macos/Package.resolved deleted file mode 100644 index 0281713738b..00000000000 --- a/apps/macos/Package.resolved +++ /dev/null @@ -1,132 +0,0 @@ -{ - "originHash" : "1c9c9d251b760ed3234ecff741a88eb4bf42315ad6f50ac7392b187cf226c16c", - "pins" : [ - { - "identity" : "axorcist", - "kind" : "remoteSourceControl", - "location" : "https://github.com/steipete/AXorcist.git", - "state" : { - "revision" : "c75d06f7f93e264a9786edc2b78c04973061cb2f", - "version" : "0.1.0" - } - }, - { - "identity" : "commander", - "kind" : "remoteSourceControl", - "location" : "https://github.com/steipete/Commander.git", - "state" : { - "revision" : "9e349575c8e3c6745e81fe19e5bb5efa01b078ce", - "version" : "0.2.1" - } - }, - { - "identity" : "elevenlabskit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/steipete/ElevenLabsKit", - "state" : { - "revision" : "c8679fbd37416a8780fe43be88a497ff16209e2d", - "version" : "0.1.0" - } - }, - { - "identity" : "menubarextraaccess", - "kind" : "remoteSourceControl", - "location" : "https://github.com/orchetect/MenuBarExtraAccess", - "state" : { - "revision" : "707dff6f55217b3ef5b6be84ced3e83511d4df5c", - "version" : "1.2.2" - } - }, - { - "identity" : "peekaboo", - "kind" : "remoteSourceControl", - "location" : "https://github.com/steipete/Peekaboo.git", - "state" : { - "branch" : "main", - "revision" : "bace59f90bb276f1c6fb613acfda3935ec4a7a90" - } - }, - { - "identity" : "sparkle", - "kind" : "remoteSourceControl", - "location" : "https://github.com/sparkle-project/Sparkle", - "state" : { - "revision" : "5581748cef2bae787496fe6d61139aebe0a451f6", - "version" : "2.8.1" - } - }, - { - "identity" : "swift-algorithms", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-algorithms", - "state" : { - "revision" : "87e50f483c54e6efd60e885f7f5aa946cee68023", - "version" : "1.2.1" - } - }, - { - "identity" : "swift-concurrency-extras", - "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-concurrency-extras", - "state" : { - "revision" : "5a3825302b1a0d744183200915a47b508c828e6f", - "version" : "1.3.2" - } - }, - { - "identity" : "swift-log", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-log.git", - "state" : { - "revision" : "2778fd4e5a12a8aaa30a3ee8285f4ce54c5f3181", - "version" : "1.9.1" - } - }, - { - "identity" : "swift-numerics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-numerics.git", - "state" : { - "revision" : "0c0290ff6b24942dadb83a929ffaaa1481df04a2", - "version" : "1.1.1" - } - }, - { - "identity" : "swift-subprocess", - "kind" : "remoteSourceControl", - "location" : "https://github.com/swiftlang/swift-subprocess.git", - "state" : { - "revision" : "ba5888ad7758cbcbe7abebac37860b1652af2d9c", - "version" : "0.3.0" - } - }, - { - "identity" : "swift-system", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-system", - "state" : { - "revision" : "7c6ad0fc39d0763e0b699210e4124afd5041c5df", - "version" : "1.6.4" - } - }, - { - "identity" : "swiftui-math", - "kind" : "remoteSourceControl", - "location" : "https://github.com/gonzalezreal/swiftui-math", - "state" : { - "revision" : "0b5c2cfaaec8d6193db206f675048eeb5ce95f71", - "version" : "0.1.0" - } - }, - { - "identity" : "textual", - "kind" : "remoteSourceControl", - "location" : "https://github.com/gonzalezreal/textual", - "state" : { - "revision" : "5b06b811c0f5313b6b84bbef98c635a630638c38", - "version" : "0.3.1" - } - } - ], - "version" : 3 -} diff --git a/apps/macos/Package.swift b/apps/macos/Package.swift deleted file mode 100644 index 10ab47b8514..00000000000 --- a/apps/macos/Package.swift +++ /dev/null @@ -1,92 +0,0 @@ -// swift-tools-version: 6.2 -// Package manifest for the OpenClaw macOS companion (menu bar app + IPC library). - -import PackageDescription - -let package = Package( - name: "OpenClaw", - platforms: [ - .macOS(.v15), - ], - products: [ - .library(name: "OpenClawIPC", targets: ["OpenClawIPC"]), - .library(name: "OpenClawDiscovery", targets: ["OpenClawDiscovery"]), - .executable(name: "OpenClaw", targets: ["OpenClaw"]), - .executable(name: "openclaw-mac", targets: ["OpenClawMacCLI"]), - ], - dependencies: [ - .package(url: "https://github.com/orchetect/MenuBarExtraAccess", exact: "1.2.2"), - .package(url: "https://github.com/swiftlang/swift-subprocess.git", from: "0.1.0"), - .package(url: "https://github.com/apple/swift-log.git", from: "1.8.0"), - .package(url: "https://github.com/sparkle-project/Sparkle", from: "2.8.1"), - .package(url: "https://github.com/steipete/Peekaboo.git", branch: "main"), - .package(path: "../shared/OpenClawKit"), - .package(path: "../../Swabble"), - ], - targets: [ - .target( - name: "OpenClawIPC", - dependencies: [], - swiftSettings: [ - .enableUpcomingFeature("StrictConcurrency"), - ]), - .target( - name: "OpenClawDiscovery", - dependencies: [ - .product(name: "OpenClawKit", package: "OpenClawKit"), - ], - path: "Sources/OpenClawDiscovery", - swiftSettings: [ - .enableUpcomingFeature("StrictConcurrency"), - ]), - .executableTarget( - name: "OpenClaw", - dependencies: [ - "OpenClawIPC", - "OpenClawDiscovery", - .product(name: "OpenClawKit", package: "OpenClawKit"), - .product(name: "OpenClawChatUI", package: "OpenClawKit"), - .product(name: "OpenClawProtocol", package: "OpenClawKit"), - .product(name: "SwabbleKit", package: "swabble"), - .product(name: "MenuBarExtraAccess", package: "MenuBarExtraAccess"), - .product(name: "Subprocess", package: "swift-subprocess"), - .product(name: "Logging", package: "swift-log"), - .product(name: "Sparkle", package: "Sparkle"), - .product(name: "PeekabooBridge", package: "Peekaboo"), - .product(name: "PeekabooAutomationKit", package: "Peekaboo"), - ], - exclude: [ - "Resources/Info.plist", - ], - resources: [ - .copy("Resources/OpenClaw.icns"), - .copy("Resources/DeviceModels"), - ], - swiftSettings: [ - .enableUpcomingFeature("StrictConcurrency"), - ]), - .executableTarget( - name: "OpenClawMacCLI", - dependencies: [ - "OpenClawDiscovery", - .product(name: "OpenClawKit", package: "OpenClawKit"), - .product(name: "OpenClawProtocol", package: "OpenClawKit"), - ], - path: "Sources/OpenClawMacCLI", - swiftSettings: [ - .enableUpcomingFeature("StrictConcurrency"), - ]), - .testTarget( - name: "OpenClawIPCTests", - dependencies: [ - "OpenClawIPC", - "OpenClaw", - "OpenClawDiscovery", - .product(name: "OpenClawProtocol", package: "OpenClawKit"), - .product(name: "SwabbleKit", package: "swabble"), - ], - swiftSettings: [ - .enableUpcomingFeature("StrictConcurrency"), - .enableExperimentalFeature("SwiftTesting"), - ]), - ]) diff --git a/apps/macos/README.md b/apps/macos/README.md deleted file mode 100644 index 05743dc6e2f..00000000000 --- a/apps/macos/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# OpenClaw macOS app (dev + signing) - -## Quick dev run - -```bash -# from repo root -scripts/restart-mac.sh -``` - -Options: - -```bash -scripts/restart-mac.sh --no-sign # fastest dev; ad-hoc signing (TCC permissions do not stick) -scripts/restart-mac.sh --sign # force code signing (requires cert) -``` - -## Packaging flow - -```bash -scripts/package-mac-app.sh -``` - -Creates `dist/OpenClaw.app` and signs it via `scripts/codesign-mac-app.sh`. - -## Signing behavior - -Auto-selects identity (first match): -1) Developer ID Application -2) Apple Distribution -3) Apple Development -4) first available identity - -If none found: -- errors by default -- set `ALLOW_ADHOC_SIGNING=1` or `SIGN_IDENTITY="-"` to ad-hoc sign - -## Team ID audit (Sparkle mismatch guard) - -After signing, we read the app bundle Team ID and compare every Mach-O inside the app. -If any embedded binary has a different Team ID, signing fails. - -Skip the audit: -```bash -SKIP_TEAM_ID_CHECK=1 scripts/package-mac-app.sh -``` - -## Library validation workaround (dev only) - -If Sparkle Team ID mismatch blocks loading (common with Apple Development certs), opt in: - -```bash -DISABLE_LIBRARY_VALIDATION=1 scripts/package-mac-app.sh -``` - -This adds `com.apple.security.cs.disable-library-validation` to app entitlements. -Use for local dev only; keep off for release builds. - -## Useful env flags - -- `SIGN_IDENTITY="Apple Development: Your Name (TEAMID)"` -- `ALLOW_ADHOC_SIGNING=1` (ad-hoc, TCC permissions do not persist) -- `CODESIGN_TIMESTAMP=off` (offline debug) -- `DISABLE_LIBRARY_VALIDATION=1` (dev-only Sparkle workaround) -- `SKIP_TEAM_ID_CHECK=1` (bypass audit) diff --git a/apps/macos/Sources/OpenClaw/AboutSettings.swift b/apps/macos/Sources/OpenClaw/AboutSettings.swift deleted file mode 100644 index b61cfee89a5..00000000000 --- a/apps/macos/Sources/OpenClaw/AboutSettings.swift +++ /dev/null @@ -1,199 +0,0 @@ -import SwiftUI - -struct AboutSettings: View { - weak var updater: UpdaterProviding? - @State private var iconHover = false - @AppStorage("autoUpdateEnabled") private var autoCheckEnabled = true - @State private var didLoadUpdaterState = false - - var body: some View { - VStack(spacing: 8) { - let appIcon = NSApplication.shared.applicationIconImage ?? CritterIconRenderer.makeIcon(blink: 0) - Button { - if let url = URL(string: "https://github.com/openclaw/openclaw") { - NSWorkspace.shared.open(url) - } - } label: { - Image(nsImage: appIcon) - .resizable() - .frame(width: 160, height: 160) - .cornerRadius(24) - .shadow(color: self.iconHover ? .accentColor.opacity(0.25) : .clear, radius: 10) - .scaleEffect(self.iconHover ? 1.05 : 1.0) - } - .buttonStyle(.plain) - .focusable(false) - .pointingHandCursor() - .onHover { hover in - withAnimation(.spring(response: 0.3, dampingFraction: 0.72)) { self.iconHover = hover } - } - - VStack(spacing: 3) { - Text("OpenClaw") - .font(.title3.bold()) - Text("Version \(self.versionString)") - .foregroundStyle(.secondary) - if let buildTimestamp { - Text("Built \(buildTimestamp)\(self.buildSuffix)") - .font(.footnote) - .foregroundStyle(.secondary) - } - Text("Menu bar companion for notifications, screenshots, and privileged agent actions.") - .font(.footnote) - .foregroundStyle(.secondary) - .multilineTextAlignment(.center) - .padding(.horizontal, 18) - } - - VStack(alignment: .center, spacing: 6) { - AboutLinkRow( - icon: "chevron.left.slash.chevron.right", - title: "GitHub", - url: "https://github.com/openclaw/openclaw") - AboutLinkRow(icon: "globe", title: "Website", url: "https://openclaw.ai") - AboutLinkRow(icon: "bird", title: "Twitter", url: "https://twitter.com/steipete") - AboutLinkRow(icon: "envelope", title: "Email", url: "mailto:peter@steipete.me") - } - .frame(maxWidth: .infinity) - .multilineTextAlignment(.center) - .padding(.vertical, 10) - - if let updater { - Divider() - .padding(.vertical, 8) - - if updater.isAvailable { - VStack(spacing: 10) { - Toggle("Check for updates automatically", isOn: self.$autoCheckEnabled) - .toggleStyle(.checkbox) - .frame(maxWidth: .infinity, alignment: .center) - - Button("Check for Updates…") { updater.checkForUpdates(nil) } - } - } else { - Text("Updates unavailable in this build.") - .foregroundStyle(.secondary) - .padding(.top, 4) - } - } - - Text("© 2025 Peter Steinberger — MIT License.") - .font(.footnote) - .foregroundStyle(.secondary) - .padding(.top, 4) - - Spacer() - } - .frame(maxWidth: .infinity, maxHeight: .infinity) - .padding(.top, 4) - .padding(.horizontal, 24) - .padding(.bottom, 24) - .onAppear { - guard let updater, !self.didLoadUpdaterState else { return } - // Keep Sparkle’s auto-check setting in sync with the persisted toggle. - updater.automaticallyChecksForUpdates = self.autoCheckEnabled - updater.automaticallyDownloadsUpdates = self.autoCheckEnabled - self.didLoadUpdaterState = true - } - .onChange(of: self.autoCheckEnabled) { _, newValue in - self.updater?.automaticallyChecksForUpdates = newValue - self.updater?.automaticallyDownloadsUpdates = newValue - } - } - - private var versionString: String { - let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "dev" - let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String - return build.map { "\(version) (\($0))" } ?? version - } - - private var buildTimestamp: String? { - guard - let raw = - (Bundle.main.object(forInfoDictionaryKey: "OpenClawBuildTimestamp") as? String) ?? - (Bundle.main.object(forInfoDictionaryKey: "OpenClawBuildTimestamp") as? String) - else { return nil } - let parser = ISO8601DateFormatter() - parser.formatOptions = [.withInternetDateTime] - guard let date = parser.date(from: raw) else { return raw } - - let formatter = DateFormatter() - formatter.dateStyle = .medium - formatter.timeStyle = .short - formatter.locale = .current - return formatter.string(from: date) - } - - private var gitCommit: String { - (Bundle.main.object(forInfoDictionaryKey: "OpenClawGitCommit") as? String) ?? - (Bundle.main.object(forInfoDictionaryKey: "OpenClawGitCommit") as? String) ?? - "unknown" - } - - private var bundleID: String { - Bundle.main.bundleIdentifier ?? "unknown" - } - - private var buildSuffix: String { - let git = self.gitCommit - guard !git.isEmpty, git != "unknown" else { return "" } - - var suffix = " (\(git)" - #if DEBUG - suffix += " DEBUG" - #endif - suffix += ")" - return suffix - } -} - -@MainActor -private struct AboutLinkRow: View { - let icon: String - let title: String - let url: String - - @State private var hovering = false - - var body: some View { - Button { - if let url = URL(string: url) { NSWorkspace.shared.open(url) } - } label: { - HStack(spacing: 6) { - Image(systemName: self.icon) - Text(self.title) - .underline(self.hovering, color: .accentColor) - } - .foregroundColor(.accentColor) - } - .buttonStyle(.plain) - .onHover { self.hovering = $0 } - .pointingHandCursor() - } -} - -private struct AboutMetaRow: View { - let label: String - let value: String - - var body: some View { - HStack { - Text(self.label) - .foregroundStyle(.secondary) - Spacer() - Text(self.value) - .font(.caption.monospaced()) - .foregroundStyle(.primary) - } - } -} - -#if DEBUG -struct AboutSettings_Previews: PreviewProvider { - private static let updater = DisabledUpdaterController() - static var previews: some View { - AboutSettings(updater: updater) - .frame(width: SettingsTab.windowWidth, height: SettingsTab.windowHeight) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/AgeFormatting.swift b/apps/macos/Sources/OpenClaw/AgeFormatting.swift deleted file mode 100644 index 5bb46bf459d..00000000000 --- a/apps/macos/Sources/OpenClaw/AgeFormatting.swift +++ /dev/null @@ -1,17 +0,0 @@ -import Foundation - -/// Human-friendly age string (e.g., "2m ago"). -func age(from date: Date, now: Date = .init()) -> String { - let seconds = max(0, Int(now.timeIntervalSince(date))) - let minutes = seconds / 60 - let hours = minutes / 60 - let days = hours / 24 - - if seconds < 60 { return "just now" } - if minutes == 1 { return "1 minute ago" } - if minutes < 60 { return "\(minutes)m ago" } - if hours == 1 { return "1 hour ago" } - if hours < 24 { return "\(hours)h ago" } - if days == 1 { return "yesterday" } - return "\(days)d ago" -} diff --git a/apps/macos/Sources/OpenClaw/AgentEventStore.swift b/apps/macos/Sources/OpenClaw/AgentEventStore.swift deleted file mode 100644 index 780867a32f4..00000000000 --- a/apps/macos/Sources/OpenClaw/AgentEventStore.swift +++ /dev/null @@ -1,22 +0,0 @@ -import Foundation -import Observation - -@MainActor -@Observable -final class AgentEventStore { - static let shared = AgentEventStore() - - private(set) var events: [ControlAgentEvent] = [] - private let maxEvents = 400 - - func append(_ event: ControlAgentEvent) { - self.events.append(event) - if self.events.count > self.maxEvents { - self.events.removeFirst(self.events.count - self.maxEvents) - } - } - - func clear() { - self.events.removeAll() - } -} diff --git a/apps/macos/Sources/OpenClaw/AgentEventsWindow.swift b/apps/macos/Sources/OpenClaw/AgentEventsWindow.swift deleted file mode 100644 index 673588cc379..00000000000 --- a/apps/macos/Sources/OpenClaw/AgentEventsWindow.swift +++ /dev/null @@ -1,109 +0,0 @@ -import OpenClawProtocol -import SwiftUI - -@MainActor -struct AgentEventsWindow: View { - private let store = AgentEventStore.shared - - var body: some View { - VStack(alignment: .leading, spacing: 6) { - HStack { - Text("Agent Events") - .font(.title3.weight(.semibold)) - Spacer() - Button("Clear") { self.store.clear() } - .buttonStyle(.bordered) - } - .padding(.bottom, 4) - - ScrollView { - LazyVStack(alignment: .leading, spacing: 8) { - ForEach(self.store.events.reversed(), id: \.seq) { evt in - EventRow(event: evt) - } - } - } - } - .padding(12) - .frame(minWidth: 520, minHeight: 360) - } -} - -private struct EventRow: View { - let event: ControlAgentEvent - - var body: some View { - VStack(alignment: .leading, spacing: 2) { - HStack(spacing: 6) { - Text(self.event.stream.uppercased()) - .font(.caption2.weight(.bold)) - .padding(.horizontal, 6) - .padding(.vertical, 2) - .background(self.tint) - .foregroundStyle(Color.white) - .clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous)) - Text("run " + self.event.runId) - .font(.caption.monospaced()) - .foregroundStyle(.secondary) - Spacer() - Text(self.formattedTs) - .font(.caption2) - .foregroundStyle(.secondary) - } - if let json = self.prettyJSON(event.data) { - Text(json) - .font(.caption.monospaced()) - .foregroundStyle(.primary) - .textSelection(.enabled) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.top, 2) - } - } - .padding(8) - .background( - RoundedRectangle(cornerRadius: 8, style: .continuous) - .fill(Color.primary.opacity(0.04))) - } - - private var tint: Color { - switch self.event.stream { - case "job": .blue - case "tool": .orange - case "assistant": .green - default: .gray - } - } - - private var formattedTs: String { - let date = Date(timeIntervalSince1970: event.ts / 1000) - let f = DateFormatter() - f.dateFormat = "HH:mm:ss.SSS" - return f.string(from: date) - } - - private func prettyJSON(_ dict: [String: OpenClawProtocol.AnyCodable]) -> String? { - let normalized = dict.mapValues { $0.value } - guard JSONSerialization.isValidJSONObject(normalized), - let data = try? JSONSerialization.data(withJSONObject: normalized, options: [.prettyPrinted]), - let str = String(data: data, encoding: .utf8) - else { return nil } - return str - } -} - -struct AgentEventsWindow_Previews: PreviewProvider { - static var previews: some View { - let sample = ControlAgentEvent( - runId: "abc", - seq: 1, - stream: "tool", - ts: Date().timeIntervalSince1970 * 1000, - data: [ - "phase": OpenClawProtocol.AnyCodable("start"), - "name": OpenClawProtocol.AnyCodable("bash"), - ], - summary: nil) - AgentEventStore.shared.append(sample) - return AgentEventsWindow() - } -} diff --git a/apps/macos/Sources/OpenClaw/AgentWorkspace.swift b/apps/macos/Sources/OpenClaw/AgentWorkspace.swift deleted file mode 100644 index 57164ebb892..00000000000 --- a/apps/macos/Sources/OpenClaw/AgentWorkspace.swift +++ /dev/null @@ -1,340 +0,0 @@ -import Foundation -import OSLog - -enum AgentWorkspace { - private static let logger = Logger(subsystem: "ai.openclaw", category: "workspace") - static let agentsFilename = "AGENTS.md" - static let soulFilename = "SOUL.md" - static let identityFilename = "IDENTITY.md" - static let userFilename = "USER.md" - static let bootstrapFilename = "BOOTSTRAP.md" - private static let templateDirname = "templates" - private static let ignoredEntries: Set = [".DS_Store", ".git", ".gitignore"] - private static let templateEntries: Set = [ - AgentWorkspace.agentsFilename, - AgentWorkspace.soulFilename, - AgentWorkspace.identityFilename, - AgentWorkspace.userFilename, - AgentWorkspace.bootstrapFilename, - ] - enum BootstrapSafety: Equatable { - case safe - case unsafe (reason: String) - } - - static func displayPath(for url: URL) -> String { - let home = FileManager().homeDirectoryForCurrentUser.path - let path = url.path - if path == home { return "~" } - if path.hasPrefix(home + "/") { - return "~/" + String(path.dropFirst(home.count + 1)) - } - return path - } - - static func resolveWorkspaceURL(from userInput: String?) -> URL { - let trimmed = userInput?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if trimmed.isEmpty { return OpenClawConfigFile.defaultWorkspaceURL() } - let expanded = (trimmed as NSString).expandingTildeInPath - return URL(fileURLWithPath: expanded, isDirectory: true) - } - - static func agentsURL(workspaceURL: URL) -> URL { - workspaceURL.appendingPathComponent(self.agentsFilename) - } - - static func workspaceEntries(workspaceURL: URL) throws -> [String] { - let contents = try FileManager().contentsOfDirectory(atPath: workspaceURL.path) - return contents.filter { !self.ignoredEntries.contains($0) } - } - - static func isWorkspaceEmpty(workspaceURL: URL) -> Bool { - let fm = FileManager() - var isDir: ObjCBool = false - if !fm.fileExists(atPath: workspaceURL.path, isDirectory: &isDir) { - return true - } - guard isDir.boolValue else { return false } - guard let entries = try? self.workspaceEntries(workspaceURL: workspaceURL) else { return false } - return entries.isEmpty - } - - static func isTemplateOnlyWorkspace(workspaceURL: URL) -> Bool { - guard let entries = try? self.workspaceEntries(workspaceURL: workspaceURL) else { return false } - guard !entries.isEmpty else { return true } - return Set(entries).isSubset(of: self.templateEntries) - } - - static func bootstrapSafety(for workspaceURL: URL) -> BootstrapSafety { - let fm = FileManager() - var isDir: ObjCBool = false - if !fm.fileExists(atPath: workspaceURL.path, isDirectory: &isDir) { - return .safe - } - if !isDir.boolValue { - return .unsafe (reason: "Workspace path points to a file.") - } - let agentsURL = self.agentsURL(workspaceURL: workspaceURL) - if fm.fileExists(atPath: agentsURL.path) { - return .safe - } - do { - let entries = try self.workspaceEntries(workspaceURL: workspaceURL) - return entries.isEmpty - ? .safe - : .unsafe (reason: "Folder isn't empty. Choose a new folder or add AGENTS.md first.") - } catch { - return .unsafe (reason: "Couldn't inspect the workspace folder.") - } - } - - static func bootstrap(workspaceURL: URL) throws -> URL { - let shouldSeedBootstrap = self.isWorkspaceEmpty(workspaceURL: workspaceURL) - try FileManager().createDirectory(at: workspaceURL, withIntermediateDirectories: true) - let agentsURL = self.agentsURL(workspaceURL: workspaceURL) - if !FileManager().fileExists(atPath: agentsURL.path) { - try self.defaultTemplate().write(to: agentsURL, atomically: true, encoding: .utf8) - self.logger.info("Created AGENTS.md at \(agentsURL.path, privacy: .public)") - } - let soulURL = workspaceURL.appendingPathComponent(self.soulFilename) - if !FileManager().fileExists(atPath: soulURL.path) { - try self.defaultSoulTemplate().write(to: soulURL, atomically: true, encoding: .utf8) - self.logger.info("Created SOUL.md at \(soulURL.path, privacy: .public)") - } - let identityURL = workspaceURL.appendingPathComponent(self.identityFilename) - if !FileManager().fileExists(atPath: identityURL.path) { - try self.defaultIdentityTemplate().write(to: identityURL, atomically: true, encoding: .utf8) - self.logger.info("Created IDENTITY.md at \(identityURL.path, privacy: .public)") - } - let userURL = workspaceURL.appendingPathComponent(self.userFilename) - if !FileManager().fileExists(atPath: userURL.path) { - try self.defaultUserTemplate().write(to: userURL, atomically: true, encoding: .utf8) - self.logger.info("Created USER.md at \(userURL.path, privacy: .public)") - } - let bootstrapURL = workspaceURL.appendingPathComponent(self.bootstrapFilename) - if shouldSeedBootstrap, !FileManager().fileExists(atPath: bootstrapURL.path) { - try self.defaultBootstrapTemplate().write(to: bootstrapURL, atomically: true, encoding: .utf8) - self.logger.info("Created BOOTSTRAP.md at \(bootstrapURL.path, privacy: .public)") - } - return agentsURL - } - - static func needsBootstrap(workspaceURL: URL) -> Bool { - let fm = FileManager() - var isDir: ObjCBool = false - if !fm.fileExists(atPath: workspaceURL.path, isDirectory: &isDir) { - return true - } - guard isDir.boolValue else { return true } - if self.hasIdentity(workspaceURL: workspaceURL) { - return false - } - let bootstrapURL = workspaceURL.appendingPathComponent(self.bootstrapFilename) - guard fm.fileExists(atPath: bootstrapURL.path) else { return false } - return self.isTemplateOnlyWorkspace(workspaceURL: workspaceURL) - } - - static func hasIdentity(workspaceURL: URL) -> Bool { - let identityURL = workspaceURL.appendingPathComponent(self.identityFilename) - guard let contents = try? String(contentsOf: identityURL, encoding: .utf8) else { return false } - return self.identityLinesHaveValues(contents) - } - - private static func identityLinesHaveValues(_ content: String) -> Bool { - for line in content.split(separator: "\n") { - let trimmed = line.trimmingCharacters(in: .whitespacesAndNewlines) - guard trimmed.hasPrefix("-"), let colon = trimmed.firstIndex(of: ":") else { continue } - let value = trimmed[trimmed.index(after: colon)...].trimmingCharacters(in: .whitespacesAndNewlines) - if !value.isEmpty { - return true - } - } - return false - } - - static func defaultTemplate() -> String { - let fallback = """ - # AGENTS.md - OpenClaw Workspace - - This folder is the assistant's working directory. - - ## First run (one-time) - - If BOOTSTRAP.md exists, follow its ritual and delete it once complete. - - Your agent identity lives in IDENTITY.md. - - Your profile lives in USER.md. - - ## Backup tip (recommended) - If you treat this workspace as the agent's "memory", make it a git repo (ideally private) so identity - and notes are backed up. - - ```bash - git init - git add AGENTS.md - git commit -m "Add agent workspace" - ``` - - ## Safety defaults - - Don't exfiltrate secrets or private data. - - Don't run destructive commands unless explicitly asked. - - Be concise in chat; write longer output to files in this workspace. - - ## Daily memory (recommended) - - Keep a short daily log at memory/YYYY-MM-DD.md (create memory/ if needed). - - On session start, read today + yesterday if present. - - Capture durable facts, preferences, and decisions; avoid secrets. - - ## Customize - - Add your preferred style, rules, and "memory" here. - """ - return self.loadTemplate(named: self.agentsFilename, fallback: fallback) - } - - static func defaultSoulTemplate() -> String { - let fallback = """ - # SOUL.md - Persona & Boundaries - - Describe who the assistant is, tone, and boundaries. - - - Keep replies concise and direct. - - Ask clarifying questions when needed. - - Never send streaming/partial replies to external messaging surfaces. - """ - return self.loadTemplate(named: self.soulFilename, fallback: fallback) - } - - static func defaultIdentityTemplate() -> String { - let fallback = """ - # IDENTITY.md - Agent Identity - - - Name: - - Creature: - - Vibe: - - Emoji: - """ - return self.loadTemplate(named: self.identityFilename, fallback: fallback) - } - - static func defaultUserTemplate() -> String { - let fallback = """ - # USER.md - User Profile - - - Name: - - Preferred address: - - Pronouns (optional): - - Timezone (optional): - - Notes: - """ - return self.loadTemplate(named: self.userFilename, fallback: fallback) - } - - static func defaultBootstrapTemplate() -> String { - let fallback = """ - # BOOTSTRAP.md - First Run Ritual (delete after) - - Hello. I was just born. - - ## Your mission - Start a short, playful conversation and learn: - - Who am I? - - What am I? - - Who are you? - - How should I call you? - - ## How to ask (cute + helpful) - Say: - "Hello! I was just born. Who am I? What am I? Who are you? How should I call you?" - - Then offer suggestions: - - 3-5 name ideas. - - 3-5 creature/vibe combos. - - 5 emoji ideas. - - ## Write these files - After the user chooses, update: - - 1) IDENTITY.md - - Name - - Creature - - Vibe - - Emoji - - 2) USER.md - - Name - - Preferred address - - Pronouns (optional) - - Timezone (optional) - - Notes - - 3) ~/.openclaw/openclaw.json - Set identity.name, identity.theme, identity.emoji to match IDENTITY.md. - - ## Cleanup - Delete BOOTSTRAP.md once this is complete. - """ - return self.loadTemplate(named: self.bootstrapFilename, fallback: fallback) - } - - private static func loadTemplate(named: String, fallback: String) -> String { - for url in self.templateURLs(named: named) { - if let content = try? String(contentsOf: url, encoding: .utf8) { - let stripped = self.stripFrontMatter(content) - if !stripped.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - return stripped - } - } - } - return fallback - } - - private static func templateURLs(named: String) -> [URL] { - var urls: [URL] = [] - if let resource = Bundle.main.url( - forResource: named.replacingOccurrences(of: ".md", with: ""), - withExtension: "md", - subdirectory: self.templateDirname) - { - urls.append(resource) - } - if let resource = Bundle.main.url( - forResource: named, - withExtension: nil, - subdirectory: self.templateDirname) - { - urls.append(resource) - } - if let dev = self.devTemplateURL(named: named) { - urls.append(dev) - } - let cwd = URL(fileURLWithPath: FileManager().currentDirectoryPath) - urls.append(cwd.appendingPathComponent("docs") - .appendingPathComponent(self.templateDirname) - .appendingPathComponent(named)) - return urls - } - - private static func devTemplateURL(named: String) -> URL? { - let sourceURL = URL(fileURLWithPath: #filePath) - let repoRoot = sourceURL - .deletingLastPathComponent() - .deletingLastPathComponent() - .deletingLastPathComponent() - .deletingLastPathComponent() - .deletingLastPathComponent() - return repoRoot.appendingPathComponent("docs") - .appendingPathComponent(self.templateDirname) - .appendingPathComponent(named) - } - - private static func stripFrontMatter(_ content: String) -> String { - guard content.hasPrefix("---") else { return content } - let start = content.index(content.startIndex, offsetBy: 3) - guard let range = content.range(of: "\n---", range: start.. = { - if ProcessInfo.processInfo.isRunningTests { - return Empty(completeImmediately: false).eraseToAnyPublisher() - } - return Timer.publish(every: 0.4, on: .main, in: .common) - .autoconnect() - .eraseToAnyPublisher() - }() - - var body: some View { - VStack(alignment: .leading, spacing: 10) { - if self.connectionMode != .local { - Text("Gateway isn’t running locally; OAuth must be created on the gateway host.") - .font(.footnote) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - - HStack(spacing: 10) { - Circle() - .fill(self.oauthStatus.isConnected ? Color.green : Color.orange) - .frame(width: 8, height: 8) - Text(self.oauthStatus.shortDescription) - .font(.footnote.weight(.semibold)) - .foregroundStyle(.secondary) - Spacer() - Button("Reveal") { - NSWorkspace.shared.activateFileViewerSelecting([OpenClawOAuthStore.oauthURL()]) - } - .buttonStyle(.bordered) - .disabled(!FileManager().fileExists(atPath: OpenClawOAuthStore.oauthURL().path)) - - Button("Refresh") { - self.refresh() - } - .buttonStyle(.bordered) - } - - Text(OpenClawOAuthStore.oauthURL().path) - .font(.caption.monospaced()) - .foregroundStyle(.secondary) - .lineLimit(1) - .truncationMode(.middle) - .textSelection(.enabled) - - HStack(spacing: 12) { - Button { - self.startOAuth() - } label: { - if self.busy { - ProgressView().controlSize(.small) - } else { - Text(self.oauthStatus.isConnected ? "Re-auth (OAuth)" : "Open sign-in (OAuth)") - } - } - .buttonStyle(.borderedProminent) - .disabled(self.connectionMode != .local || self.busy) - - if self.pkce != nil { - Button("Cancel") { - self.pkce = nil - self.code = "" - self.statusText = nil - } - .buttonStyle(.bordered) - .disabled(self.busy) - } - } - - if self.pkce != nil { - VStack(alignment: .leading, spacing: 8) { - Text("Paste `code#state`") - .font(.footnote.weight(.semibold)) - .foregroundStyle(.secondary) - - TextField("code#state", text: self.$code) - .textFieldStyle(.roundedBorder) - .disabled(self.busy) - - Toggle("Auto-detect from clipboard", isOn: self.$autoDetectClipboard) - .font(.footnote) - .foregroundStyle(.secondary) - .disabled(self.busy) - - Toggle("Auto-connect when detected", isOn: self.$autoConnectClipboard) - .font(.footnote) - .foregroundStyle(.secondary) - .disabled(self.busy) - - Button("Connect") { - Task { await self.finishOAuth() } - } - .buttonStyle(.bordered) - .disabled(self.busy || self.connectionMode != .local || self.code - .trimmingCharacters(in: .whitespacesAndNewlines) - .isEmpty) - } - } - - if let statusText, !statusText.isEmpty { - Text(statusText) - .font(.footnote) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - } - .onAppear { - self.refresh() - } - .onReceive(Self.clipboardPoll) { _ in - self.pollClipboardIfNeeded() - } - } - - private func refresh() { - let imported = OpenClawOAuthStore.importLegacyAnthropicOAuthIfNeeded() - self.oauthStatus = OpenClawOAuthStore.anthropicOAuthStatus() - if imported != nil { - self.statusText = "Imported existing OAuth credentials." - } - } - - private func startOAuth() { - guard self.connectionMode == .local else { return } - guard !self.busy else { return } - self.busy = true - defer { self.busy = false } - - do { - let pkce = try AnthropicOAuth.generatePKCE() - self.pkce = pkce - let url = AnthropicOAuth.buildAuthorizeURL(pkce: pkce) - NSWorkspace.shared.open(url) - self.statusText = "Browser opened. After approving, paste the `code#state` value here." - } catch { - self.statusText = "Failed to start OAuth: \(error.localizedDescription)" - } - } - - @MainActor - private func finishOAuth() async { - guard self.connectionMode == .local else { return } - guard !self.busy else { return } - guard let pkce = self.pkce else { return } - self.busy = true - defer { self.busy = false } - - guard let parsed = AnthropicOAuthCodeState.parse(from: self.code) else { - self.statusText = "OAuth failed: missing or invalid code/state." - return - } - - do { - let creds = try await AnthropicOAuth.exchangeCode( - code: parsed.code, - state: parsed.state, - verifier: pkce.verifier) - try OpenClawOAuthStore.saveAnthropicOAuth(creds) - self.refresh() - self.pkce = nil - self.code = "" - self.statusText = "Connected. OpenClaw can now use Claude via OAuth." - } catch { - self.statusText = "OAuth failed: \(error.localizedDescription)" - } - } - - private func pollClipboardIfNeeded() { - guard self.connectionMode == .local else { return } - guard self.pkce != nil else { return } - guard !self.busy else { return } - guard self.autoDetectClipboard else { return } - - let pb = NSPasteboard.general - let changeCount = pb.changeCount - guard changeCount != self.lastPasteboardChangeCount else { return } - self.lastPasteboardChangeCount = changeCount - - guard let raw = pb.string(forType: .string), !raw.isEmpty else { return } - guard let parsed = AnthropicOAuthCodeState.parse(from: raw) else { return } - guard let pkce = self.pkce, parsed.state == pkce.verifier else { return } - - let next = "\(parsed.code)#\(parsed.state)" - if self.code != next { - self.code = next - self.statusText = "Detected `code#state` from clipboard." - } - - guard self.autoConnectClipboard else { return } - Task { await self.finishOAuth() } - } -} - -#if DEBUG -extension AnthropicAuthControls { - init( - connectionMode: AppState.ConnectionMode, - oauthStatus: OpenClawOAuthStore.AnthropicOAuthStatus, - pkce: AnthropicOAuth.PKCE? = nil, - code: String = "", - busy: Bool = false, - statusText: String? = nil, - autoDetectClipboard: Bool = true, - autoConnectClipboard: Bool = true) - { - self.connectionMode = connectionMode - self._oauthStatus = State(initialValue: oauthStatus) - self._pkce = State(initialValue: pkce) - self._code = State(initialValue: code) - self._busy = State(initialValue: busy) - self._statusText = State(initialValue: statusText) - self._autoDetectClipboard = State(initialValue: autoDetectClipboard) - self._autoConnectClipboard = State(initialValue: autoConnectClipboard) - self._lastPasteboardChangeCount = State(initialValue: NSPasteboard.general.changeCount) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/AnthropicOAuth.swift b/apps/macos/Sources/OpenClaw/AnthropicOAuth.swift deleted file mode 100644 index f594cc04c31..00000000000 --- a/apps/macos/Sources/OpenClaw/AnthropicOAuth.swift +++ /dev/null @@ -1,383 +0,0 @@ -import CryptoKit -import Foundation -import OSLog -import Security - -struct AnthropicOAuthCredentials: Codable { - let type: String - let refresh: String - let access: String - let expires: Int64 -} - -enum AnthropicAuthMode: Equatable { - case oauthFile - case oauthEnv - case apiKeyEnv - case missing - - var shortLabel: String { - switch self { - case .oauthFile: "OAuth (OpenClaw token file)" - case .oauthEnv: "OAuth (env var)" - case .apiKeyEnv: "API key (env var)" - case .missing: "Missing credentials" - } - } - - var isConfigured: Bool { - switch self { - case .missing: false - case .oauthFile, .oauthEnv, .apiKeyEnv: true - } - } -} - -enum AnthropicAuthResolver { - static func resolve( - environment: [String: String] = ProcessInfo.processInfo.environment, - oauthStatus: OpenClawOAuthStore.AnthropicOAuthStatus = OpenClawOAuthStore - .anthropicOAuthStatus()) -> AnthropicAuthMode - { - if oauthStatus.isConnected { return .oauthFile } - - if let token = environment["ANTHROPIC_OAUTH_TOKEN"]?.trimmingCharacters(in: .whitespacesAndNewlines), - !token.isEmpty - { - return .oauthEnv - } - - if let key = environment["ANTHROPIC_API_KEY"]?.trimmingCharacters(in: .whitespacesAndNewlines), - !key.isEmpty - { - return .apiKeyEnv - } - - return .missing - } -} - -enum AnthropicOAuth { - private static let logger = Logger(subsystem: "ai.openclaw", category: "anthropic-oauth") - - private static let clientId = "9d1c250a-e61b-44d9-88ed-5944d1962f5e" - private static let authorizeURL = URL(string: "https://claude.ai/oauth/authorize")! - private static let tokenURL = URL(string: "https://console.anthropic.com/v1/oauth/token")! - private static let redirectURI = "https://console.anthropic.com/oauth/code/callback" - private static let scopes = "org:create_api_key user:profile user:inference" - - struct PKCE { - let verifier: String - let challenge: String - } - - static func generatePKCE() throws -> PKCE { - var bytes = [UInt8](repeating: 0, count: 32) - let status = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes) - guard status == errSecSuccess else { - throw NSError(domain: NSOSStatusErrorDomain, code: Int(status)) - } - let verifier = Data(bytes).base64URLEncodedString() - let hash = SHA256.hash(data: Data(verifier.utf8)) - let challenge = Data(hash).base64URLEncodedString() - return PKCE(verifier: verifier, challenge: challenge) - } - - static func buildAuthorizeURL(pkce: PKCE) -> URL { - var components = URLComponents(url: self.authorizeURL, resolvingAgainstBaseURL: false)! - components.queryItems = [ - URLQueryItem(name: "code", value: "true"), - URLQueryItem(name: "client_id", value: self.clientId), - URLQueryItem(name: "response_type", value: "code"), - URLQueryItem(name: "redirect_uri", value: self.redirectURI), - URLQueryItem(name: "scope", value: self.scopes), - URLQueryItem(name: "code_challenge", value: pkce.challenge), - URLQueryItem(name: "code_challenge_method", value: "S256"), - // Match legacy flow: state is the verifier. - URLQueryItem(name: "state", value: pkce.verifier), - ] - return components.url! - } - - static func exchangeCode( - code: String, - state: String, - verifier: String) async throws -> AnthropicOAuthCredentials - { - let payload: [String: Any] = [ - "grant_type": "authorization_code", - "client_id": self.clientId, - "code": code, - "state": state, - "redirect_uri": self.redirectURI, - "code_verifier": verifier, - ] - let body = try JSONSerialization.data(withJSONObject: payload, options: []) - - var request = URLRequest(url: self.tokenURL) - request.httpMethod = "POST" - request.httpBody = body - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - - let (data, response) = try await URLSession.shared.data(for: request) - guard let http = response as? HTTPURLResponse else { - throw URLError(.badServerResponse) - } - guard (200..<300).contains(http.statusCode) else { - let text = String(data: data, encoding: .utf8) ?? "" - throw NSError( - domain: "AnthropicOAuth", - code: http.statusCode, - userInfo: [NSLocalizedDescriptionKey: "Token exchange failed: \(text)"]) - } - - let decoded = try JSONSerialization.jsonObject(with: data) as? [String: Any] - let access = decoded?["access_token"] as? String - let refresh = decoded?["refresh_token"] as? String - let expiresIn = decoded?["expires_in"] as? Double - guard let access, let refresh, let expiresIn else { - throw NSError(domain: "AnthropicOAuth", code: 0, userInfo: [ - NSLocalizedDescriptionKey: "Unexpected token response.", - ]) - } - - // Match legacy flow: expiresAt = now + expires_in - 5 minutes. - let expiresAtMs = Int64(Date().timeIntervalSince1970 * 1000) - + Int64(expiresIn * 1000) - - Int64(5 * 60 * 1000) - - self.logger.info("Anthropic OAuth exchange ok; expiresAtMs=\(expiresAtMs, privacy: .public)") - return AnthropicOAuthCredentials(type: "oauth", refresh: refresh, access: access, expires: expiresAtMs) - } - - static func refresh(refreshToken: String) async throws -> AnthropicOAuthCredentials { - let payload: [String: Any] = [ - "grant_type": "refresh_token", - "client_id": self.clientId, - "refresh_token": refreshToken, - ] - let body = try JSONSerialization.data(withJSONObject: payload, options: []) - - var request = URLRequest(url: self.tokenURL) - request.httpMethod = "POST" - request.httpBody = body - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - - let (data, response) = try await URLSession.shared.data(for: request) - guard let http = response as? HTTPURLResponse else { - throw URLError(.badServerResponse) - } - guard (200..<300).contains(http.statusCode) else { - let text = String(data: data, encoding: .utf8) ?? "" - throw NSError( - domain: "AnthropicOAuth", - code: http.statusCode, - userInfo: [NSLocalizedDescriptionKey: "Token refresh failed: \(text)"]) - } - - let decoded = try JSONSerialization.jsonObject(with: data) as? [String: Any] - let access = decoded?["access_token"] as? String - let refresh = (decoded?["refresh_token"] as? String) ?? refreshToken - let expiresIn = decoded?["expires_in"] as? Double - guard let access, let expiresIn else { - throw NSError(domain: "AnthropicOAuth", code: 0, userInfo: [ - NSLocalizedDescriptionKey: "Unexpected token response.", - ]) - } - - let expiresAtMs = Int64(Date().timeIntervalSince1970 * 1000) - + Int64(expiresIn * 1000) - - Int64(5 * 60 * 1000) - - self.logger.info("Anthropic OAuth refresh ok; expiresAtMs=\(expiresAtMs, privacy: .public)") - return AnthropicOAuthCredentials(type: "oauth", refresh: refresh, access: access, expires: expiresAtMs) - } -} - -enum OpenClawOAuthStore { - static let oauthFilename = "oauth.json" - private static let providerKey = "anthropic" - private static let openclawOAuthDirEnv = "OPENCLAW_OAUTH_DIR" - private static let legacyPiDirEnv = "PI_CODING_AGENT_DIR" - - enum AnthropicOAuthStatus: Equatable { - case missingFile - case unreadableFile - case invalidJSON - case missingProviderEntry - case missingTokens - case connected(expiresAtMs: Int64?) - - var isConnected: Bool { - if case .connected = self { return true } - return false - } - - var shortDescription: String { - switch self { - case .missingFile: "OpenClaw OAuth token file not found" - case .unreadableFile: "OpenClaw OAuth token file not readable" - case .invalidJSON: "OpenClaw OAuth token file invalid" - case .missingProviderEntry: "No Anthropic entry in OpenClaw OAuth token file" - case .missingTokens: "Anthropic entry missing tokens" - case .connected: "OpenClaw OAuth credentials found" - } - } - } - - static func oauthDir() -> URL { - if let override = ProcessInfo.processInfo.environment[self.openclawOAuthDirEnv]? - .trimmingCharacters(in: .whitespacesAndNewlines), - !override.isEmpty - { - let expanded = NSString(string: override).expandingTildeInPath - return URL(fileURLWithPath: expanded, isDirectory: true) - } - let home = FileManager().homeDirectoryForCurrentUser - return home.appendingPathComponent(".openclaw", isDirectory: true) - .appendingPathComponent("credentials", isDirectory: true) - } - - static func oauthURL() -> URL { - self.oauthDir().appendingPathComponent(self.oauthFilename) - } - - static func legacyOAuthURLs() -> [URL] { - var urls: [URL] = [] - let env = ProcessInfo.processInfo.environment - if let override = env[self.legacyPiDirEnv]?.trimmingCharacters(in: .whitespacesAndNewlines), - !override.isEmpty - { - let expanded = NSString(string: override).expandingTildeInPath - urls.append(URL(fileURLWithPath: expanded, isDirectory: true).appendingPathComponent(self.oauthFilename)) - } - - let home = FileManager().homeDirectoryForCurrentUser - urls.append(home.appendingPathComponent(".pi/agent/\(self.oauthFilename)")) - urls.append(home.appendingPathComponent(".claude/\(self.oauthFilename)")) - urls.append(home.appendingPathComponent(".config/claude/\(self.oauthFilename)")) - urls.append(home.appendingPathComponent(".config/anthropic/\(self.oauthFilename)")) - - var seen = Set() - return urls.filter { url in - let path = url.standardizedFileURL.path - if seen.contains(path) { return false } - seen.insert(path) - return true - } - } - - static func importLegacyAnthropicOAuthIfNeeded() -> URL? { - let dest = self.oauthURL() - guard !FileManager().fileExists(atPath: dest.path) else { return nil } - - for url in self.legacyOAuthURLs() { - guard FileManager().fileExists(atPath: url.path) else { continue } - guard self.anthropicOAuthStatus(at: url).isConnected else { continue } - guard let storage = self.loadStorage(at: url) else { continue } - do { - try self.saveStorage(storage) - return url - } catch { - continue - } - } - - return nil - } - - static func anthropicOAuthStatus() -> AnthropicOAuthStatus { - self.anthropicOAuthStatus(at: self.oauthURL()) - } - - static func hasAnthropicOAuth() -> Bool { - self.anthropicOAuthStatus().isConnected - } - - static func anthropicOAuthStatus(at url: URL) -> AnthropicOAuthStatus { - guard FileManager().fileExists(atPath: url.path) else { return .missingFile } - - guard let data = try? Data(contentsOf: url) else { return .unreadableFile } - guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else { return .invalidJSON } - guard let storage = json as? [String: Any] else { return .invalidJSON } - guard let rawEntry = storage[self.providerKey] else { return .missingProviderEntry } - guard let entry = rawEntry as? [String: Any] else { return .invalidJSON } - - let refresh = self.firstString(in: entry, keys: ["refresh", "refresh_token", "refreshToken"]) - let access = self.firstString(in: entry, keys: ["access", "access_token", "accessToken"]) - guard refresh?.isEmpty == false, access?.isEmpty == false else { return .missingTokens } - - let expiresAny = entry["expires"] ?? entry["expires_at"] ?? entry["expiresAt"] - let expiresAtMs: Int64? = if let ms = expiresAny as? Int64 { - ms - } else if let number = expiresAny as? NSNumber { - number.int64Value - } else if let ms = expiresAny as? Double { - Int64(ms) - } else { - nil - } - - return .connected(expiresAtMs: expiresAtMs) - } - - static func loadAnthropicOAuthRefreshToken() -> String? { - let url = self.oauthURL() - guard let storage = self.loadStorage(at: url) else { return nil } - guard let rawEntry = storage[self.providerKey] as? [String: Any] else { return nil } - let refresh = self.firstString(in: rawEntry, keys: ["refresh", "refresh_token", "refreshToken"]) - return refresh?.trimmingCharacters(in: .whitespacesAndNewlines) - } - - private static func firstString(in dict: [String: Any], keys: [String]) -> String? { - for key in keys { - if let value = dict[key] as? String { return value } - } - return nil - } - - private static func loadStorage(at url: URL) -> [String: Any]? { - guard let data = try? Data(contentsOf: url) else { return nil } - guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else { return nil } - return json as? [String: Any] - } - - static func saveAnthropicOAuth(_ creds: AnthropicOAuthCredentials) throws { - let url = self.oauthURL() - let existing: [String: Any] = self.loadStorage(at: url) ?? [:] - - var updated = existing - updated[self.providerKey] = [ - "type": creds.type, - "refresh": creds.refresh, - "access": creds.access, - "expires": creds.expires, - ] - - try self.saveStorage(updated) - } - - private static func saveStorage(_ storage: [String: Any]) throws { - let dir = self.oauthDir() - try FileManager().createDirectory( - at: dir, - withIntermediateDirectories: true, - attributes: [.posixPermissions: 0o700]) - - let url = self.oauthURL() - let data = try JSONSerialization.data( - withJSONObject: storage, - options: [.prettyPrinted, .sortedKeys]) - try data.write(to: url, options: [.atomic]) - try FileManager().setAttributes([.posixPermissions: 0o600], ofItemAtPath: url.path) - } -} - -extension Data { - fileprivate func base64URLEncodedString() -> String { - self.base64EncodedString() - .replacingOccurrences(of: "+", with: "-") - .replacingOccurrences(of: "/", with: "_") - .replacingOccurrences(of: "=", with: "") - } -} diff --git a/apps/macos/Sources/OpenClaw/AnthropicOAuthCodeState.swift b/apps/macos/Sources/OpenClaw/AnthropicOAuthCodeState.swift deleted file mode 100644 index 2a88898c34d..00000000000 --- a/apps/macos/Sources/OpenClaw/AnthropicOAuthCodeState.swift +++ /dev/null @@ -1,59 +0,0 @@ -import Foundation - -enum AnthropicOAuthCodeState { - struct Parsed: Equatable { - let code: String - let state: String - } - - /// Extracts a `code#state` payload from arbitrary text. - /// - /// Supports: - /// - raw `code#state` - /// - OAuth callback URLs containing `code=` and `state=` query params - /// - surrounding text/backticks from instructions pages - static func extract(from raw: String) -> String? { - let text = raw.trimmingCharacters(in: .whitespacesAndNewlines) - .trimmingCharacters(in: CharacterSet(charactersIn: "`")) - if text.isEmpty { return nil } - - if let fromURL = self.extractFromURL(text) { return fromURL } - if let fromToken = self.extractFromToken(text) { return fromToken } - return nil - } - - static func parse(from raw: String) -> Parsed? { - guard let extracted = self.extract(from: raw) else { return nil } - let parts = extracted.split(separator: "#", maxSplits: 1).map(String.init) - let code = parts.first ?? "" - let state = parts.count > 1 ? parts[1] : "" - guard !code.isEmpty, !state.isEmpty else { return nil } - return Parsed(code: code, state: state) - } - - private static func extractFromURL(_ text: String) -> String? { - // Users might copy the callback URL from the browser address bar. - guard let components = URLComponents(string: text), - let items = components.queryItems, - let code = items.first(where: { $0.name == "code" })?.value, - let state = items.first(where: { $0.name == "state" })?.value, - !code.isEmpty, !state.isEmpty - else { return nil } - - return "\(code)#\(state)" - } - - private static func extractFromToken(_ text: String) -> String? { - // Base64url-ish tokens; keep this fairly strict to avoid false positives. - let pattern = #"([A-Za-z0-9._~-]{8,})#([A-Za-z0-9._~-]{8,})"# - guard let re = try? NSRegularExpression(pattern: pattern) else { return nil } - - let range = NSRange(text.startIndex..? - - private func ifNotPreview(_ action: () -> Void) { - guard !self.isPreview else { return } - action() - } - - enum ConnectionMode: String { - case unconfigured - case local - case remote - } - - enum RemoteTransport: String { - case ssh - case direct - } - - var isPaused: Bool { - didSet { self.ifNotPreview { UserDefaults.standard.set(self.isPaused, forKey: pauseDefaultsKey) } } - } - - var launchAtLogin: Bool { - didSet { - guard !self.isInitializing else { return } - self.ifNotPreview { Task { AppStateStore.updateLaunchAtLogin(enabled: self.launchAtLogin) } } - } - } - - var onboardingSeen: Bool { - didSet { self.ifNotPreview { UserDefaults.standard.set(self.onboardingSeen, forKey: onboardingSeenKey) } - } - } - - var debugPaneEnabled: Bool { - didSet { - self.ifNotPreview { UserDefaults.standard.set(self.debugPaneEnabled, forKey: debugPaneEnabledKey) } - CanvasManager.shared.refreshDebugStatus() - } - } - - var swabbleEnabled: Bool { - didSet { - self.ifNotPreview { - UserDefaults.standard.set(self.swabbleEnabled, forKey: swabbleEnabledKey) - Task { await VoiceWakeRuntime.shared.refresh(state: self) } - } - } - } - - var swabbleTriggerWords: [String] { - didSet { - // Preserve the raw editing state; sanitization happens when we actually use the triggers. - self.ifNotPreview { - UserDefaults.standard.set(self.swabbleTriggerWords, forKey: swabbleTriggersKey) - if self.swabbleEnabled { - Task { await VoiceWakeRuntime.shared.refresh(state: self) } - } - self.scheduleVoiceWakeGlobalSyncIfNeeded() - } - } - } - - var voiceWakeTriggerChime: VoiceWakeChime { - didSet { self.ifNotPreview { self.storeChime(self.voiceWakeTriggerChime, key: voiceWakeTriggerChimeKey) } } - } - - var voiceWakeSendChime: VoiceWakeChime { - didSet { self.ifNotPreview { self.storeChime(self.voiceWakeSendChime, key: voiceWakeSendChimeKey) } } - } - - var iconAnimationsEnabled: Bool { - didSet { self.ifNotPreview { UserDefaults.standard.set( - self.iconAnimationsEnabled, - forKey: iconAnimationsEnabledKey) } } - } - - var showDockIcon: Bool { - didSet { - self.ifNotPreview { - UserDefaults.standard.set(self.showDockIcon, forKey: showDockIconKey) - AppActivationPolicy.apply(showDockIcon: self.showDockIcon) - } - } - } - - var voiceWakeMicID: String { - didSet { - self.ifNotPreview { - UserDefaults.standard.set(self.voiceWakeMicID, forKey: voiceWakeMicKey) - if self.swabbleEnabled { - Task { await VoiceWakeRuntime.shared.refresh(state: self) } - } - } - } - } - - var voiceWakeMicName: String { - didSet { self.ifNotPreview { UserDefaults.standard.set(self.voiceWakeMicName, forKey: voiceWakeMicNameKey) } } - } - - var voiceWakeLocaleID: String { - didSet { - self.ifNotPreview { - UserDefaults.standard.set(self.voiceWakeLocaleID, forKey: voiceWakeLocaleKey) - if self.swabbleEnabled { - Task { await VoiceWakeRuntime.shared.refresh(state: self) } - } - } - } - } - - var voiceWakeAdditionalLocaleIDs: [String] { - didSet { self.ifNotPreview { UserDefaults.standard.set( - self.voiceWakeAdditionalLocaleIDs, - forKey: voiceWakeAdditionalLocalesKey) } } - } - - var voicePushToTalkEnabled: Bool { - didSet { self.ifNotPreview { UserDefaults.standard.set( - self.voicePushToTalkEnabled, - forKey: voicePushToTalkEnabledKey) } } - } - - var talkEnabled: Bool { - didSet { - self.ifNotPreview { - UserDefaults.standard.set(self.talkEnabled, forKey: talkEnabledKey) - Task { await TalkModeController.shared.setEnabled(self.talkEnabled) } - } - } - } - - /// Gateway-provided UI accent color (hex). Optional; clients provide a default. - var seamColorHex: String? - - var iconOverride: IconOverrideSelection { - didSet { self.ifNotPreview { UserDefaults.standard.set(self.iconOverride.rawValue, forKey: iconOverrideKey) } } - } - - var isWorking: Bool = false - var earBoostActive: Bool = false - var blinkTick: Int = 0 - var sendCelebrationTick: Int = 0 - var heartbeatsEnabled: Bool { - didSet { - self.ifNotPreview { - UserDefaults.standard.set(self.heartbeatsEnabled, forKey: heartbeatsEnabledKey) - Task { _ = await GatewayConnection.shared.setHeartbeatsEnabled(self.heartbeatsEnabled) } - } - } - } - - var connectionMode: ConnectionMode { - didSet { - self.ifNotPreview { UserDefaults.standard.set(self.connectionMode.rawValue, forKey: connectionModeKey) } - self.syncGatewayConfigIfNeeded() - } - } - - var remoteTransport: RemoteTransport { - didSet { self.syncGatewayConfigIfNeeded() } - } - - var canvasEnabled: Bool { - didSet { self.ifNotPreview { UserDefaults.standard.set(self.canvasEnabled, forKey: canvasEnabledKey) } } - } - - var execApprovalMode: ExecApprovalQuickMode { - didSet { - self.ifNotPreview { - ExecApprovalsStore.updateDefaults { defaults in - defaults.security = self.execApprovalMode.security - defaults.ask = self.execApprovalMode.ask - } - } - } - } - - /// Tracks whether the Canvas panel is currently visible (not persisted). - var canvasPanelVisible: Bool = false - - var peekabooBridgeEnabled: Bool { - didSet { - self.ifNotPreview { - UserDefaults.standard.set(self.peekabooBridgeEnabled, forKey: peekabooBridgeEnabledKey) - Task { await PeekabooBridgeHostCoordinator.shared.setEnabled(self.peekabooBridgeEnabled) } - } - } - } - - var remoteTarget: String { - didSet { - self.ifNotPreview { UserDefaults.standard.set(self.remoteTarget, forKey: remoteTargetKey) } - self.syncGatewayConfigIfNeeded() - } - } - - var remoteUrl: String { - didSet { self.syncGatewayConfigIfNeeded() } - } - - var remoteIdentity: String { - didSet { self.ifNotPreview { UserDefaults.standard.set(self.remoteIdentity, forKey: remoteIdentityKey) } } - } - - var remoteProjectRoot: String { - didSet { self.ifNotPreview { UserDefaults.standard.set(self.remoteProjectRoot, forKey: remoteProjectRootKey) } } - } - - var remoteCliPath: String { - didSet { self.ifNotPreview { UserDefaults.standard.set(self.remoteCliPath, forKey: remoteCliPathKey) } } - } - - private var earBoostTask: Task? - - init(preview: Bool = false) { - let isPreview = preview || ProcessInfo.processInfo.isRunningTests - self.isPreview = isPreview - if !isPreview { - migrateLegacyDefaults() - } - let onboardingSeen = UserDefaults.standard.bool(forKey: onboardingSeenKey) - self.isPaused = UserDefaults.standard.bool(forKey: pauseDefaultsKey) - self.launchAtLogin = false - self.onboardingSeen = onboardingSeen - self.debugPaneEnabled = UserDefaults.standard.bool(forKey: debugPaneEnabledKey) - let savedVoiceWake = UserDefaults.standard.bool(forKey: swabbleEnabledKey) - self.swabbleEnabled = voiceWakeSupported ? savedVoiceWake : false - self.swabbleTriggerWords = UserDefaults.standard - .stringArray(forKey: swabbleTriggersKey) ?? defaultVoiceWakeTriggers - self.voiceWakeTriggerChime = Self.loadChime( - key: voiceWakeTriggerChimeKey, - fallback: .system(name: "Glass")) - self.voiceWakeSendChime = Self.loadChime( - key: voiceWakeSendChimeKey, - fallback: .system(name: "Glass")) - if let storedIconAnimations = UserDefaults.standard.object(forKey: iconAnimationsEnabledKey) as? Bool { - self.iconAnimationsEnabled = storedIconAnimations - } else { - self.iconAnimationsEnabled = true - UserDefaults.standard.set(true, forKey: iconAnimationsEnabledKey) - } - self.showDockIcon = UserDefaults.standard.bool(forKey: showDockIconKey) - self.voiceWakeMicID = UserDefaults.standard.string(forKey: voiceWakeMicKey) ?? "" - self.voiceWakeMicName = UserDefaults.standard.string(forKey: voiceWakeMicNameKey) ?? "" - self.voiceWakeLocaleID = UserDefaults.standard.string(forKey: voiceWakeLocaleKey) ?? Locale.current.identifier - self.voiceWakeAdditionalLocaleIDs = UserDefaults.standard - .stringArray(forKey: voiceWakeAdditionalLocalesKey) ?? [] - self.voicePushToTalkEnabled = UserDefaults.standard - .object(forKey: voicePushToTalkEnabledKey) as? Bool ?? false - self.talkEnabled = UserDefaults.standard.bool(forKey: talkEnabledKey) - self.seamColorHex = nil - if let storedHeartbeats = UserDefaults.standard.object(forKey: heartbeatsEnabledKey) as? Bool { - self.heartbeatsEnabled = storedHeartbeats - } else { - self.heartbeatsEnabled = true - UserDefaults.standard.set(true, forKey: heartbeatsEnabledKey) - } - if let storedOverride = UserDefaults.standard.string(forKey: iconOverrideKey), - let selection = IconOverrideSelection(rawValue: storedOverride) - { - self.iconOverride = selection - } else { - self.iconOverride = .system - UserDefaults.standard.set(IconOverrideSelection.system.rawValue, forKey: iconOverrideKey) - } - - let configRoot = OpenClawConfigFile.loadDict() - let configRemoteUrl = GatewayRemoteConfig.resolveUrlString(root: configRoot) - let configRemoteTransport = GatewayRemoteConfig.resolveTransport(root: configRoot) - let resolvedConnectionMode = ConnectionModeResolver.resolve(root: configRoot).mode - self.remoteTransport = configRemoteTransport - self.connectionMode = resolvedConnectionMode - - let storedRemoteTarget = UserDefaults.standard.string(forKey: remoteTargetKey) ?? "" - if resolvedConnectionMode == .remote, - configRemoteTransport != .direct, - storedRemoteTarget.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty, - let host = AppState.remoteHost(from: configRemoteUrl) - { - self.remoteTarget = "\(NSUserName())@\(host)" - } else { - self.remoteTarget = storedRemoteTarget - } - self.remoteUrl = configRemoteUrl ?? "" - self.remoteIdentity = UserDefaults.standard.string(forKey: remoteIdentityKey) ?? "" - self.remoteProjectRoot = UserDefaults.standard.string(forKey: remoteProjectRootKey) ?? "" - self.remoteCliPath = UserDefaults.standard.string(forKey: remoteCliPathKey) ?? "" - self.canvasEnabled = UserDefaults.standard.object(forKey: canvasEnabledKey) as? Bool ?? true - let execDefaults = ExecApprovalsStore.resolveDefaults() - self.execApprovalMode = ExecApprovalQuickMode.from(security: execDefaults.security, ask: execDefaults.ask) - self.peekabooBridgeEnabled = UserDefaults.standard - .object(forKey: peekabooBridgeEnabledKey) as? Bool ?? true - if !self.isPreview { - Task.detached(priority: .utility) { [weak self] in - let current = await LaunchAgentManager.status() - await MainActor.run { [weak self] in self?.launchAtLogin = current } - } - } - - if self.swabbleEnabled, !PermissionManager.voiceWakePermissionsGranted() { - self.swabbleEnabled = false - } - if self.talkEnabled, !PermissionManager.voiceWakePermissionsGranted() { - self.talkEnabled = false - } - - if !self.isPreview { - Task { await VoiceWakeRuntime.shared.refresh(state: self) } - Task { await TalkModeController.shared.setEnabled(self.talkEnabled) } - } - - self.isInitializing = false - if !self.isPreview { - self.startConfigWatcher() - } - } - - @MainActor - deinit { - self.configWatcher?.stop() - } - - private static func remoteHost(from urlString: String?) -> String? { - guard let raw = urlString?.trimmingCharacters(in: .whitespacesAndNewlines), - !raw.isEmpty, - let url = URL(string: raw), - let host = url.host?.trimmingCharacters(in: .whitespacesAndNewlines), - !host.isEmpty - else { - return nil - } - return host - } - - private static func sanitizeSSHTarget(_ value: String) -> String { - let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.hasPrefix("ssh ") { - return trimmed.replacingOccurrences(of: "ssh ", with: "") - .trimmingCharacters(in: .whitespacesAndNewlines) - } - return trimmed - } - - private func startConfigWatcher() { - let configUrl = OpenClawConfigFile.url() - self.configWatcher = ConfigFileWatcher(url: configUrl) { [weak self] in - Task { @MainActor in - self?.applyConfigFromDisk() - } - } - self.configWatcher?.start() - } - - private func applyConfigFromDisk() { - let root = OpenClawConfigFile.loadDict() - self.applyConfigOverrides(root) - } - - private func applyConfigOverrides(_ root: [String: Any]) { - let gateway = root["gateway"] as? [String: Any] - let modeRaw = (gateway?["mode"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) - let remoteUrl = GatewayRemoteConfig.resolveUrlString(root: root) - let hasRemoteUrl = !(remoteUrl? - .trimmingCharacters(in: .whitespacesAndNewlines) - .isEmpty ?? true) - let remoteTransport = GatewayRemoteConfig.resolveTransport(root: root) - - let desiredMode: ConnectionMode? = switch modeRaw { - case "local": - .local - case "remote": - .remote - case "unconfigured": - .unconfigured - default: - nil - } - - if let desiredMode { - if desiredMode != self.connectionMode { - self.connectionMode = desiredMode - } - } else if hasRemoteUrl, self.connectionMode != .remote { - self.connectionMode = .remote - } - - if remoteTransport != self.remoteTransport { - self.remoteTransport = remoteTransport - } - let remoteUrlText = remoteUrl ?? "" - if remoteUrlText != self.remoteUrl { - self.remoteUrl = remoteUrlText - } - - let targetMode = desiredMode ?? self.connectionMode - if targetMode == .remote, - remoteTransport != .direct, - let host = AppState.remoteHost(from: remoteUrl) - { - self.updateRemoteTarget(host: host) - } - } - - private func updateRemoteTarget(host: String) { - let trimmed = self.remoteTarget.trimmingCharacters(in: .whitespacesAndNewlines) - guard let parsed = CommandResolver.parseSSHTarget(trimmed) else { return } - let trimmedUser = parsed.user?.trimmingCharacters(in: .whitespacesAndNewlines) - let user = (trimmedUser?.isEmpty ?? true) ? nil : trimmedUser - let port = parsed.port - let assembled: String = if let user { - port == 22 ? "\(user)@\(host)" : "\(user)@\(host):\(port)" - } else { - port == 22 ? host : "\(host):\(port)" - } - if assembled != self.remoteTarget { - self.remoteTarget = assembled - } - } - - private func syncGatewayConfigIfNeeded() { - guard !self.isPreview, !self.isInitializing else { return } - - let connectionMode = self.connectionMode - let remoteTarget = self.remoteTarget - let remoteIdentity = self.remoteIdentity - let remoteTransport = self.remoteTransport - let remoteUrl = self.remoteUrl - let desiredMode: String? = switch connectionMode { - case .local: - "local" - case .remote: - "remote" - case .unconfigured: - nil - } - let remoteHost = connectionMode == .remote - ? CommandResolver.parseSSHTarget(remoteTarget)?.host - : nil - - Task { @MainActor in - // Keep app-only connection settings local to avoid overwriting remote gateway config. - var root = OpenClawConfigFile.loadDict() - var gateway = root["gateway"] as? [String: Any] ?? [:] - var changed = false - - let currentMode = (gateway["mode"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) - if let desiredMode { - if currentMode != desiredMode { - gateway["mode"] = desiredMode - changed = true - } - } else if currentMode != nil { - gateway.removeValue(forKey: "mode") - changed = true - } - - if connectionMode == .remote { - var remote = gateway["remote"] as? [String: Any] ?? [:] - var remoteChanged = false - - if remoteTransport == .direct { - let trimmedUrl = remoteUrl.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmedUrl.isEmpty { - if remote["url"] != nil { - remote.removeValue(forKey: "url") - remoteChanged = true - } - } else if let normalizedUrl = GatewayRemoteConfig.normalizeGatewayUrlString(trimmedUrl) { - if (remote["url"] as? String) != normalizedUrl { - remote["url"] = normalizedUrl - remoteChanged = true - } - } - if (remote["transport"] as? String) != RemoteTransport.direct.rawValue { - remote["transport"] = RemoteTransport.direct.rawValue - remoteChanged = true - } - } else { - if remote["transport"] != nil { - remote.removeValue(forKey: "transport") - remoteChanged = true - } - if let host = remoteHost { - let existingUrl = (remote["url"] as? String)? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let parsedExisting = existingUrl.isEmpty ? nil : URL(string: existingUrl) - let scheme = parsedExisting?.scheme?.isEmpty == false ? parsedExisting?.scheme : "ws" - let port = parsedExisting?.port ?? 18789 - let desiredUrl = "\(scheme ?? "ws")://\(host):\(port)" - if existingUrl != desiredUrl { - remote["url"] = desiredUrl - remoteChanged = true - } - } - - let sanitizedTarget = Self.sanitizeSSHTarget(remoteTarget) - if !sanitizedTarget.isEmpty { - if (remote["sshTarget"] as? String) != sanitizedTarget { - remote["sshTarget"] = sanitizedTarget - remoteChanged = true - } - } else if remote["sshTarget"] != nil { - remote.removeValue(forKey: "sshTarget") - remoteChanged = true - } - - let trimmedIdentity = remoteIdentity.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmedIdentity.isEmpty { - if (remote["sshIdentity"] as? String) != trimmedIdentity { - remote["sshIdentity"] = trimmedIdentity - remoteChanged = true - } - } else if remote["sshIdentity"] != nil { - remote.removeValue(forKey: "sshIdentity") - remoteChanged = true - } - } - - if remoteChanged { - gateway["remote"] = remote - changed = true - } - } - - guard changed else { return } - if gateway.isEmpty { - root.removeValue(forKey: "gateway") - } else { - root["gateway"] = gateway - } - OpenClawConfigFile.saveDict(root) - } - } - - func triggerVoiceEars(ttl: TimeInterval? = 5) { - self.earBoostTask?.cancel() - self.earBoostActive = true - - guard let ttl else { return } - - self.earBoostTask = Task { [weak self] in - try? await Task.sleep(nanoseconds: UInt64(ttl * 1_000_000_000)) - await MainActor.run { [weak self] in self?.earBoostActive = false } - } - } - - func stopVoiceEars() { - self.earBoostTask?.cancel() - self.earBoostTask = nil - self.earBoostActive = false - } - - func blinkOnce() { - self.blinkTick &+= 1 - } - - func celebrateSend() { - self.sendCelebrationTick &+= 1 - } - - func setVoiceWakeEnabled(_ enabled: Bool) async { - guard voiceWakeSupported else { - self.swabbleEnabled = false - return - } - - self.swabbleEnabled = enabled - guard !self.isPreview else { return } - - if !enabled { - Task { await VoiceWakeRuntime.shared.refresh(state: self) } - return - } - - if PermissionManager.voiceWakePermissionsGranted() { - Task { await VoiceWakeRuntime.shared.refresh(state: self) } - return - } - - let granted = await PermissionManager.ensureVoiceWakePermissions(interactive: true) - self.swabbleEnabled = granted - Task { await VoiceWakeRuntime.shared.refresh(state: self) } - } - - func setTalkEnabled(_ enabled: Bool) async { - guard voiceWakeSupported else { - self.talkEnabled = false - await GatewayConnection.shared.talkMode(enabled: false, phase: "disabled") - return - } - - self.talkEnabled = enabled - guard !self.isPreview else { return } - - if !enabled { - await GatewayConnection.shared.talkMode(enabled: false, phase: "disabled") - return - } - - if PermissionManager.voiceWakePermissionsGranted() { - await GatewayConnection.shared.talkMode(enabled: true, phase: "enabled") - return - } - - let granted = await PermissionManager.ensureVoiceWakePermissions(interactive: true) - self.talkEnabled = granted - await GatewayConnection.shared.talkMode(enabled: granted, phase: granted ? "enabled" : "denied") - } - - // MARK: - Global wake words sync (Gateway-owned) - - func applyGlobalVoiceWakeTriggers(_ triggers: [String]) { - self.suppressVoiceWakeGlobalSync = true - self.swabbleTriggerWords = triggers - self.suppressVoiceWakeGlobalSync = false - } - - private func scheduleVoiceWakeGlobalSyncIfNeeded() { - guard !self.suppressVoiceWakeGlobalSync else { return } - let sanitized = sanitizeVoiceWakeTriggers(self.swabbleTriggerWords) - self.voiceWakeGlobalSyncTask?.cancel() - self.voiceWakeGlobalSyncTask = Task { [sanitized] in - try? await Task.sleep(nanoseconds: 650_000_000) - await GatewayConnection.shared.voiceWakeSetTriggers(sanitized) - } - } - - func setWorking(_ working: Bool) { - self.isWorking = working - } - - // MARK: - Chime persistence - - private static func loadChime(key: String, fallback: VoiceWakeChime) -> VoiceWakeChime { - guard let data = UserDefaults.standard.data(forKey: key) else { return fallback } - if let decoded = try? JSONDecoder().decode(VoiceWakeChime.self, from: data) { - return decoded - } - return fallback - } - - private func storeChime(_ chime: VoiceWakeChime, key: String) { - guard let data = try? JSONEncoder().encode(chime) else { return } - UserDefaults.standard.set(data, forKey: key) - } -} - -extension AppState { - static var preview: AppState { - let state = AppState(preview: true) - state.isPaused = false - state.launchAtLogin = true - state.onboardingSeen = true - state.debugPaneEnabled = true - state.swabbleEnabled = true - state.swabbleTriggerWords = ["Claude", "Computer", "Jarvis"] - state.voiceWakeTriggerChime = .system(name: "Glass") - state.voiceWakeSendChime = .system(name: "Ping") - state.iconAnimationsEnabled = true - state.showDockIcon = true - state.voiceWakeMicID = "BuiltInMic" - state.voiceWakeMicName = "Built-in Microphone" - state.voiceWakeLocaleID = Locale.current.identifier - state.voiceWakeAdditionalLocaleIDs = ["en-US", "de-DE"] - state.voicePushToTalkEnabled = false - state.talkEnabled = false - state.iconOverride = .system - state.heartbeatsEnabled = true - state.connectionMode = .local - state.remoteTransport = .ssh - state.canvasEnabled = true - state.remoteTarget = "user@example.com" - state.remoteUrl = "wss://gateway.example.ts.net" - state.remoteIdentity = "~/.ssh/id_ed25519" - state.remoteProjectRoot = "~/Projects/openclaw" - state.remoteCliPath = "" - return state - } -} - -@MainActor -enum AppStateStore { - static let shared = AppState() - static var isPausedFlag: Bool { - UserDefaults.standard.bool(forKey: pauseDefaultsKey) - } - - static func updateLaunchAtLogin(enabled: Bool) { - Task.detached(priority: .utility) { - await LaunchAgentManager.set(enabled: enabled, bundlePath: Bundle.main.bundlePath) - } - } - - static var canvasEnabled: Bool { - UserDefaults.standard.object(forKey: canvasEnabledKey) as? Bool ?? true - } -} - -@MainActor -enum AppActivationPolicy { - static func apply(showDockIcon: Bool) { - _ = showDockIcon - DockIconManager.shared.updateDockVisibility() - } -} diff --git a/apps/macos/Sources/OpenClaw/AudioInputDeviceObserver.swift b/apps/macos/Sources/OpenClaw/AudioInputDeviceObserver.swift deleted file mode 100644 index abbddb24588..00000000000 --- a/apps/macos/Sources/OpenClaw/AudioInputDeviceObserver.swift +++ /dev/null @@ -1,216 +0,0 @@ -import CoreAudio -import Foundation -import OSLog - -final class AudioInputDeviceObserver { - private let logger = Logger(subsystem: "ai.openclaw", category: "audio.devices") - private var isActive = false - private var devicesListener: AudioObjectPropertyListenerBlock? - private var defaultInputListener: AudioObjectPropertyListenerBlock? - - static func defaultInputDeviceUID() -> String? { - let systemObject = AudioObjectID(kAudioObjectSystemObject) - var address = AudioObjectPropertyAddress( - mSelector: kAudioHardwarePropertyDefaultInputDevice, - mScope: kAudioObjectPropertyScopeGlobal, - mElement: kAudioObjectPropertyElementMain) - var deviceID = AudioObjectID(0) - var size = UInt32(MemoryLayout.size) - let status = AudioObjectGetPropertyData( - systemObject, - &address, - 0, - nil, - &size, - &deviceID) - guard status == noErr, deviceID != 0 else { return nil } - return self.deviceUID(for: deviceID) - } - - static func aliveInputDeviceUIDs() -> Set { - let systemObject = AudioObjectID(kAudioObjectSystemObject) - var address = AudioObjectPropertyAddress( - mSelector: kAudioHardwarePropertyDevices, - mScope: kAudioObjectPropertyScopeGlobal, - mElement: kAudioObjectPropertyElementMain) - var size: UInt32 = 0 - var status = AudioObjectGetPropertyDataSize(systemObject, &address, 0, nil, &size) - guard status == noErr, size > 0 else { return [] } - - let count = Int(size) / MemoryLayout.size - var deviceIDs = [AudioObjectID](repeating: 0, count: count) - status = AudioObjectGetPropertyData(systemObject, &address, 0, nil, &size, &deviceIDs) - guard status == noErr else { return [] } - - var output = Set() - for deviceID in deviceIDs { - guard self.deviceIsAlive(deviceID) else { continue } - guard self.deviceHasInput(deviceID) else { continue } - if let uid = self.deviceUID(for: deviceID) { - output.insert(uid) - } - } - return output - } - - static func defaultInputDeviceSummary() -> String { - let systemObject = AudioObjectID(kAudioObjectSystemObject) - var address = AudioObjectPropertyAddress( - mSelector: kAudioHardwarePropertyDefaultInputDevice, - mScope: kAudioObjectPropertyScopeGlobal, - mElement: kAudioObjectPropertyElementMain) - var deviceID = AudioObjectID(0) - var size = UInt32(MemoryLayout.size) - let status = AudioObjectGetPropertyData( - systemObject, - &address, - 0, - nil, - &size, - &deviceID) - guard status == noErr, deviceID != 0 else { - return "defaultInput=unknown" - } - let uid = self.deviceUID(for: deviceID) ?? "unknown" - let name = self.deviceName(for: deviceID) ?? "unknown" - return "defaultInput=\(name) (\(uid))" - } - - func start(onChange: @escaping @Sendable () -> Void) { - guard !self.isActive else { return } - self.isActive = true - - let systemObject = AudioObjectID(kAudioObjectSystemObject) - let queue = DispatchQueue.main - - var devicesAddress = AudioObjectPropertyAddress( - mSelector: kAudioHardwarePropertyDevices, - mScope: kAudioObjectPropertyScopeGlobal, - mElement: kAudioObjectPropertyElementMain) - let devicesListener: AudioObjectPropertyListenerBlock = { _, _ in - self.logDefaultInputChange(reason: "devices") - onChange() - } - let devicesStatus = AudioObjectAddPropertyListenerBlock( - systemObject, - &devicesAddress, - queue, - devicesListener) - - var defaultInputAddress = AudioObjectPropertyAddress( - mSelector: kAudioHardwarePropertyDefaultInputDevice, - mScope: kAudioObjectPropertyScopeGlobal, - mElement: kAudioObjectPropertyElementMain) - let defaultInputListener: AudioObjectPropertyListenerBlock = { _, _ in - self.logDefaultInputChange(reason: "default") - onChange() - } - let defaultStatus = AudioObjectAddPropertyListenerBlock( - systemObject, - &defaultInputAddress, - queue, - defaultInputListener) - - if devicesStatus != noErr || defaultStatus != noErr { - self.logger.error("audio device observer install failed devices=\(devicesStatus) default=\(defaultStatus)") - } - - self.logger.info("audio device observer started (\(Self.defaultInputDeviceSummary(), privacy: .public))") - - self.devicesListener = devicesListener - self.defaultInputListener = defaultInputListener - } - - func stop() { - guard self.isActive else { return } - self.isActive = false - let systemObject = AudioObjectID(kAudioObjectSystemObject) - - if let devicesListener { - var devicesAddress = AudioObjectPropertyAddress( - mSelector: kAudioHardwarePropertyDevices, - mScope: kAudioObjectPropertyScopeGlobal, - mElement: kAudioObjectPropertyElementMain) - _ = AudioObjectRemovePropertyListenerBlock( - systemObject, - &devicesAddress, - DispatchQueue.main, - devicesListener) - } - - if let defaultInputListener { - var defaultInputAddress = AudioObjectPropertyAddress( - mSelector: kAudioHardwarePropertyDefaultInputDevice, - mScope: kAudioObjectPropertyScopeGlobal, - mElement: kAudioObjectPropertyElementMain) - _ = AudioObjectRemovePropertyListenerBlock( - systemObject, - &defaultInputAddress, - DispatchQueue.main, - defaultInputListener) - } - - self.devicesListener = nil - self.defaultInputListener = nil - } - - private static func deviceUID(for deviceID: AudioObjectID) -> String? { - var address = AudioObjectPropertyAddress( - mSelector: kAudioDevicePropertyDeviceUID, - mScope: kAudioObjectPropertyScopeGlobal, - mElement: kAudioObjectPropertyElementMain) - var uid: Unmanaged? - var size = UInt32(MemoryLayout?>.size) - let status = AudioObjectGetPropertyData(deviceID, &address, 0, nil, &size, &uid) - guard status == noErr, let uid else { return nil } - return uid.takeUnretainedValue() as String - } - - private static func deviceName(for deviceID: AudioObjectID) -> String? { - var address = AudioObjectPropertyAddress( - mSelector: kAudioObjectPropertyName, - mScope: kAudioObjectPropertyScopeGlobal, - mElement: kAudioObjectPropertyElementMain) - var name: Unmanaged? - var size = UInt32(MemoryLayout?>.size) - let status = AudioObjectGetPropertyData(deviceID, &address, 0, nil, &size, &name) - guard status == noErr, let name else { return nil } - return name.takeUnretainedValue() as String - } - - private static func deviceIsAlive(_ deviceID: AudioObjectID) -> Bool { - var address = AudioObjectPropertyAddress( - mSelector: kAudioDevicePropertyDeviceIsAlive, - mScope: kAudioObjectPropertyScopeGlobal, - mElement: kAudioObjectPropertyElementMain) - var alive: UInt32 = 0 - var size = UInt32(MemoryLayout.size) - let status = AudioObjectGetPropertyData(deviceID, &address, 0, nil, &size, &alive) - return status == noErr && alive != 0 - } - - private static func deviceHasInput(_ deviceID: AudioObjectID) -> Bool { - var address = AudioObjectPropertyAddress( - mSelector: kAudioDevicePropertyStreamConfiguration, - mScope: kAudioDevicePropertyScopeInput, - mElement: kAudioObjectPropertyElementMain) - var size: UInt32 = 0 - var status = AudioObjectGetPropertyDataSize(deviceID, &address, 0, nil, &size) - guard status == noErr, size > 0 else { return false } - - let raw = UnsafeMutableRawPointer.allocate( - byteCount: Int(size), - alignment: MemoryLayout.alignment) - defer { raw.deallocate() } - let bufferList = raw.bindMemory(to: AudioBufferList.self, capacity: 1) - status = AudioObjectGetPropertyData(deviceID, &address, 0, nil, &size, bufferList) - guard status == noErr else { return false } - - let buffers = UnsafeMutableAudioBufferListPointer(bufferList) - return buffers.contains(where: { $0.mNumberChannels > 0 }) - } - - private func logDefaultInputChange(reason: StaticString) { - self.logger.info("audio input changed (\(reason)) (\(Self.defaultInputDeviceSummary(), privacy: .public))") - } -} diff --git a/apps/macos/Sources/OpenClaw/CLIInstallPrompter.swift b/apps/macos/Sources/OpenClaw/CLIInstallPrompter.swift deleted file mode 100644 index 482f36fd6d0..00000000000 --- a/apps/macos/Sources/OpenClaw/CLIInstallPrompter.swift +++ /dev/null @@ -1,84 +0,0 @@ -import AppKit -import Foundation -import OSLog - -@MainActor -final class CLIInstallPrompter { - static let shared = CLIInstallPrompter() - private let logger = Logger(subsystem: "ai.openclaw", category: "cli.prompt") - private var isPrompting = false - - func checkAndPromptIfNeeded(reason: String) { - guard self.shouldPrompt() else { return } - guard let version = Self.appVersion() else { return } - self.isPrompting = true - UserDefaults.standard.set(version, forKey: cliInstallPromptedVersionKey) - - let alert = NSAlert() - alert.messageText = "Install OpenClaw CLI?" - alert.informativeText = "Local mode needs the CLI so launchd can run the gateway." - alert.addButton(withTitle: "Install CLI") - alert.addButton(withTitle: "Not now") - alert.addButton(withTitle: "Open Settings") - let response = alert.runModal() - - switch response { - case .alertFirstButtonReturn: - Task { await self.installCLI() } - case .alertThirdButtonReturn: - self.openSettings(tab: .general) - default: - break - } - - self.logger.debug("cli install prompt handled reason=\(reason, privacy: .public)") - self.isPrompting = false - } - - private func shouldPrompt() -> Bool { - guard !self.isPrompting else { return false } - guard AppStateStore.shared.onboardingSeen else { return false } - guard AppStateStore.shared.connectionMode == .local else { return false } - guard CLIInstaller.installedLocation() == nil else { return false } - guard let version = Self.appVersion() else { return false } - let lastPrompt = UserDefaults.standard.string(forKey: cliInstallPromptedVersionKey) - return lastPrompt != version - } - - private func installCLI() async { - let status = StatusBox() - await CLIInstaller.install { message in - await status.set(message) - } - if let message = await status.get() { - let alert = NSAlert() - alert.messageText = "CLI install finished" - alert.informativeText = message - alert.runModal() - } - } - - private func openSettings(tab: SettingsTab) { - SettingsTabRouter.request(tab) - SettingsWindowOpener.shared.open() - DispatchQueue.main.async { - NotificationCenter.default.post(name: .openclawSelectSettingsTab, object: tab) - } - } - - private static func appVersion() -> String? { - Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String - } -} - -private actor StatusBox { - private var value: String? - - func set(_ value: String) { - self.value = value - } - - func get() -> String? { - self.value - } -} diff --git a/apps/macos/Sources/OpenClaw/CLIInstaller.swift b/apps/macos/Sources/OpenClaw/CLIInstaller.swift deleted file mode 100644 index ce6d25202ae..00000000000 --- a/apps/macos/Sources/OpenClaw/CLIInstaller.swift +++ /dev/null @@ -1,103 +0,0 @@ -import Foundation - -@MainActor -enum CLIInstaller { - static func installedLocation() -> String? { - self.installedLocation( - searchPaths: CommandResolver.preferredPaths(), - fileManager: .default) - } - - static func installedLocation( - searchPaths: [String], - fileManager: FileManager) -> String? - { - for basePath in searchPaths { - let candidate = URL(fileURLWithPath: basePath).appendingPathComponent("openclaw").path - var isDirectory: ObjCBool = false - - guard fileManager.fileExists(atPath: candidate, isDirectory: &isDirectory), - !isDirectory.boolValue - else { - continue - } - - guard fileManager.isExecutableFile(atPath: candidate) else { continue } - - return candidate - } - - return nil - } - - static func isInstalled() -> Bool { - self.installedLocation() != nil - } - - static func install(statusHandler: @escaping @MainActor @Sendable (String) async -> Void) async { - let expected = GatewayEnvironment.expectedGatewayVersionString() ?? "latest" - let prefix = Self.installPrefix() - await statusHandler("Installing openclaw 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 openclaw \($0)." } ?? "Installed openclaw." - await statusHandler(summary) - return - } - - let parsed = self.parseInstallEvents(response.stdout) - if let error = parsed.last(where: { $0.event == "error" })?.message { - await statusHandler("Install failed: \(error)") - return - } - - let detail = response.stderr.trimmingCharacters(in: .whitespacesAndNewlines) - let fallback = response.errorMessage ?? "install failed" - await statusHandler("Install failed: \(detail.isEmpty ? fallback : detail)") - } - - private static func installPrefix() -> String { - FileManager().homeDirectoryForCurrentUser - .appendingPathComponent(".openclaw") - .path - } - - private static func installScriptCommand(version: String, prefix: String) -> [String] { - let escapedVersion = self.shellEscape(version) - let escapedPrefix = self.shellEscape(prefix) - let script = """ - curl -fsSL https://openclaw.bot/install-cli.sh | \ - bash -s -- --json --no-onboard --prefix \(escapedPrefix) --version \(escapedVersion) - """ - return ["/bin/bash", "-lc", script] - } - - private static func parseInstallEvents(_ output: String) -> [InstallEvent] { - let decoder = JSONDecoder() - let lines = output - .split(whereSeparator: \.isNewline) - .map { String($0) } - var events: [InstallEvent] = [] - for line in lines { - guard let data = line.data(using: .utf8) else { continue } - if let event = try? decoder.decode(InstallEvent.self, from: data) { - events.append(event) - } - } - return events - } - - private static func shellEscape(_ raw: String) -> String { - "'" + raw.replacingOccurrences(of: "'", with: "'\"'\"'") + "'" - } -} - -private struct InstallEvent: Decodable { - let event: String - let version: String? - let message: String? -} diff --git a/apps/macos/Sources/OpenClaw/CameraCaptureService.swift b/apps/macos/Sources/OpenClaw/CameraCaptureService.swift deleted file mode 100644 index 4e3749d6a68..00000000000 --- a/apps/macos/Sources/OpenClaw/CameraCaptureService.swift +++ /dev/null @@ -1,427 +0,0 @@ -import AVFoundation -import CoreGraphics -import Foundation -import OpenClawIPC -import OpenClawKit -import OSLog - -actor CameraCaptureService { - struct CameraDeviceInfo: Encodable, Sendable { - let id: String - let name: String - let position: String - let deviceType: String - } - - enum CameraError: LocalizedError, Sendable { - case cameraUnavailable - case microphoneUnavailable - case permissionDenied(kind: String) - case captureFailed(String) - case exportFailed(String) - - var errorDescription: String? { - switch self { - case .cameraUnavailable: - "Camera unavailable" - case .microphoneUnavailable: - "Microphone unavailable" - case let .permissionDenied(kind): - "\(kind) permission denied" - case let .captureFailed(msg): - msg - case let .exportFailed(msg): - msg - } - } - } - - private let logger = Logger(subsystem: "ai.openclaw", category: "camera") - - func listDevices() -> [CameraDeviceInfo] { - Self.availableCameras().map { device in - CameraDeviceInfo( - id: device.uniqueID, - name: device.localizedName, - position: Self.positionLabel(device.position), - deviceType: device.deviceType.rawValue) - } - } - - func snap( - facing: CameraFacing?, - maxWidth: Int?, - quality: Double?, - deviceId: String?, - delayMs: Int) async throws -> (data: Data, size: CGSize) - { - let facing = facing ?? .front - let normalized = Self.normalizeSnap(maxWidth: maxWidth, quality: quality) - let maxWidth = normalized.maxWidth - let quality = normalized.quality - let delayMs = max(0, delayMs) - let deviceId = deviceId?.trimmingCharacters(in: .whitespacesAndNewlines) - - try await self.ensureAccess(for: .video) - - let session = AVCaptureSession() - session.sessionPreset = .photo - - guard let device = Self.pickCamera(facing: facing, deviceId: deviceId) else { - throw CameraError.cameraUnavailable - } - - let input = try AVCaptureDeviceInput(device: device) - guard session.canAddInput(input) else { - throw CameraError.captureFailed("Failed to add camera input") - } - session.addInput(input) - - let output = AVCapturePhotoOutput() - guard session.canAddOutput(output) else { - throw CameraError.captureFailed("Failed to add photo output") - } - session.addOutput(output) - output.maxPhotoQualityPrioritization = .quality - - session.startRunning() - defer { session.stopRunning() } - await Self.warmUpCaptureSession() - await self.waitForExposureAndWhiteBalance(device: device) - await self.sleepDelayMs(delayMs) - - let settings: AVCapturePhotoSettings = { - if output.availablePhotoCodecTypes.contains(.jpeg) { - return AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg]) - } - return AVCapturePhotoSettings() - }() - settings.photoQualityPrioritization = .quality - - var delegate: PhotoCaptureDelegate? - let rawData: Data = try await withCheckedThrowingContinuation { cont in - let d = PhotoCaptureDelegate(cont) - delegate = d - output.capturePhoto(with: settings, delegate: d) - } - withExtendedLifetime(delegate) {} - - let res: (data: Data, widthPx: Int, heightPx: Int) - do { - res = try PhotoCapture.transcodeJPEGForGateway( - rawData: rawData, - maxWidthPx: maxWidth, - quality: quality) - } catch { - throw CameraError.captureFailed(error.localizedDescription) - } - - return (data: res.data, size: CGSize(width: res.widthPx, height: res.heightPx)) - } - - func clip( - facing: CameraFacing?, - durationMs: Int?, - includeAudio: Bool, - deviceId: String?, - outPath: String?) async throws -> (path: String, durationMs: Int, hasAudio: Bool) - { - let facing = facing ?? .front - let durationMs = Self.clampDurationMs(durationMs) - let deviceId = deviceId?.trimmingCharacters(in: .whitespacesAndNewlines) - - try await self.ensureAccess(for: .video) - if includeAudio { - try await self.ensureAccess(for: .audio) - } - - let session = AVCaptureSession() - session.sessionPreset = .high - - guard let camera = Self.pickCamera(facing: facing, deviceId: deviceId) else { - throw CameraError.cameraUnavailable - } - let cameraInput = try AVCaptureDeviceInput(device: camera) - guard session.canAddInput(cameraInput) else { - throw CameraError.captureFailed("Failed to add camera input") - } - session.addInput(cameraInput) - - if includeAudio { - guard let mic = AVCaptureDevice.default(for: .audio) else { - throw CameraError.microphoneUnavailable - } - let micInput = try AVCaptureDeviceInput(device: mic) - guard session.canAddInput(micInput) else { - throw CameraError.captureFailed("Failed to add microphone input") - } - session.addInput(micInput) - } - - let output = AVCaptureMovieFileOutput() - guard session.canAddOutput(output) else { - throw CameraError.captureFailed("Failed to add movie output") - } - session.addOutput(output) - output.maxRecordedDuration = CMTime(value: Int64(durationMs), timescale: 1000) - - session.startRunning() - defer { session.stopRunning() } - await Self.warmUpCaptureSession() - - let tmpMovURL = FileManager().temporaryDirectory - .appendingPathComponent("openclaw-camera-\(UUID().uuidString).mov") - defer { try? FileManager().removeItem(at: tmpMovURL) } - - let outputURL: URL = { - if let outPath, !outPath.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - return URL(fileURLWithPath: outPath) - } - return FileManager().temporaryDirectory - .appendingPathComponent("openclaw-camera-\(UUID().uuidString).mp4") - }() - - // Ensure we don't fail exporting due to an existing file. - try? FileManager().removeItem(at: outputURL) - - let logger = self.logger - var delegate: MovieFileDelegate? - let recordedURL: URL = try await withCheckedThrowingContinuation { cont in - let d = MovieFileDelegate(cont, logger: logger) - delegate = d - output.startRecording(to: tmpMovURL, recordingDelegate: d) - } - withExtendedLifetime(delegate) {} - - try await Self.exportToMP4(inputURL: recordedURL, outputURL: outputURL) - return (path: outputURL.path, durationMs: durationMs, hasAudio: includeAudio) - } - - private func ensureAccess(for mediaType: AVMediaType) async throws { - let status = AVCaptureDevice.authorizationStatus(for: mediaType) - switch status { - case .authorized: - return - case .notDetermined: - let ok = await withCheckedContinuation(isolation: nil) { cont in - AVCaptureDevice.requestAccess(for: mediaType) { granted in - cont.resume(returning: granted) - } - } - if !ok { - throw CameraError.permissionDenied(kind: mediaType == .video ? "Camera" : "Microphone") - } - case .denied, .restricted: - throw CameraError.permissionDenied(kind: mediaType == .video ? "Camera" : "Microphone") - @unknown default: - throw CameraError.permissionDenied(kind: mediaType == .video ? "Camera" : "Microphone") - } - } - - private nonisolated static func availableCameras() -> [AVCaptureDevice] { - var types: [AVCaptureDevice.DeviceType] = [ - .builtInWideAngleCamera, - .continuityCamera, - ] - if let external = externalDeviceType() { - types.append(external) - } - let session = AVCaptureDevice.DiscoverySession( - deviceTypes: types, - mediaType: .video, - position: .unspecified) - return session.devices - } - - private nonisolated static func externalDeviceType() -> AVCaptureDevice.DeviceType? { - if #available(macOS 14.0, *) { - return .external - } - // Use raw value to avoid deprecated symbol in the SDK. - return AVCaptureDevice.DeviceType(rawValue: "AVCaptureDeviceTypeExternalUnknown") - } - - private nonisolated static func pickCamera( - facing: CameraFacing, - deviceId: String?) -> AVCaptureDevice? - { - if let deviceId, !deviceId.isEmpty { - if let match = availableCameras().first(where: { $0.uniqueID == deviceId }) { - return match - } - } - let position: AVCaptureDevice.Position = (facing == .front) ? .front : .back - - if let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: position) { - return device - } - - // Many macOS cameras report `unspecified` position; fall back to any default. - return AVCaptureDevice.default(for: .video) - } - - private nonisolated static func clampQuality(_ quality: Double?) -> Double { - let q = quality ?? 0.9 - return min(1.0, max(0.05, q)) - } - - nonisolated static func normalizeSnap(maxWidth: Int?, quality: Double?) -> (maxWidth: Int, quality: Double) { - // Default to a reasonable max width to keep downstream payload sizes manageable. - // If you need full-res, explicitly request a larger maxWidth. - let maxWidth = maxWidth.flatMap { $0 > 0 ? $0 : nil } ?? 1600 - let quality = Self.clampQuality(quality) - return (maxWidth: maxWidth, quality: quality) - } - - private nonisolated static func clampDurationMs(_ ms: Int?) -> Int { - let v = ms ?? 3000 - return min(60000, max(250, v)) - } - - private nonisolated static func exportToMP4(inputURL: URL, outputURL: URL) async throws { - let asset = AVURLAsset(url: inputURL) - guard let export = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetMediumQuality) else { - throw CameraError.exportFailed("Failed to create export session") - } - export.shouldOptimizeForNetworkUse = true - - if #available(macOS 15.0, *) { - do { - try await export.export(to: outputURL, as: .mp4) - return - } catch { - throw CameraError.exportFailed(error.localizedDescription) - } - } else { - export.outputURL = outputURL - export.outputFileType = .mp4 - - try await withCheckedThrowingContinuation(isolation: nil) { (cont: CheckedContinuation) in - export.exportAsynchronously { - cont.resume(returning: ()) - } - } - - switch export.status { - case .completed: - return - case .failed: - throw CameraError.exportFailed(export.error?.localizedDescription ?? "export failed") - case .cancelled: - throw CameraError.exportFailed("export cancelled") - default: - throw CameraError.exportFailed("export did not complete (\(export.status.rawValue))") - } - } - } - - private nonisolated static func warmUpCaptureSession() async { - // A short delay after `startRunning()` significantly reduces "blank first frame" captures on some devices. - try? await Task.sleep(nanoseconds: 150_000_000) // 150ms - } - - private func waitForExposureAndWhiteBalance(device: AVCaptureDevice) async { - let stepNs: UInt64 = 50_000_000 - let maxSteps = 30 // ~1.5s - for _ in 0.. 0 else { return } - let ns = UInt64(min(delayMs, 10000)) * 1_000_000 - try? await Task.sleep(nanoseconds: ns) - } - - private nonisolated static func positionLabel(_ position: AVCaptureDevice.Position) -> String { - switch position { - case .front: "front" - case .back: "back" - default: "unspecified" - } - } -} - -private final class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate { - private var cont: CheckedContinuation? - private var didResume = false - - init(_ cont: CheckedContinuation) { - self.cont = cont - } - - func photoOutput( - _ output: AVCapturePhotoOutput, - didFinishProcessingPhoto photo: AVCapturePhoto, - error: Error?) - { - guard !self.didResume, let cont else { return } - self.didResume = true - self.cont = nil - if let error { - cont.resume(throwing: error) - return - } - guard let data = photo.fileDataRepresentation() else { - cont.resume(throwing: CameraCaptureService.CameraError.captureFailed("No photo data")) - return - } - if data.isEmpty { - cont.resume(throwing: CameraCaptureService.CameraError.captureFailed("Photo data empty")) - return - } - cont.resume(returning: data) - } - - func photoOutput( - _ output: AVCapturePhotoOutput, - didFinishCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings, - error: Error?) - { - guard let error else { return } - guard !self.didResume, let cont else { return } - self.didResume = true - self.cont = nil - cont.resume(throwing: error) - } -} - -private final class MovieFileDelegate: NSObject, AVCaptureFileOutputRecordingDelegate { - private var cont: CheckedContinuation? - private let logger: Logger - - init(_ cont: CheckedContinuation, logger: Logger) { - self.cont = cont - self.logger = logger - } - - func fileOutput( - _ output: AVCaptureFileOutput, - didFinishRecordingTo outputFileURL: URL, - from connections: [AVCaptureConnection], - error: Error?) - { - guard let cont else { return } - self.cont = nil - - if let error { - let ns = error as NSError - if ns.domain == AVFoundationErrorDomain, - ns.code == AVError.maximumDurationReached.rawValue - { - cont.resume(returning: outputFileURL) - return - } - - self.logger.error("camera record failed: \(error.localizedDescription, privacy: .public)") - cont.resume(throwing: error) - return - } - - cont.resume(returning: outputFileURL) - } -} diff --git a/apps/macos/Sources/OpenClaw/CanvasA2UIActionMessageHandler.swift b/apps/macos/Sources/OpenClaw/CanvasA2UIActionMessageHandler.swift deleted file mode 100644 index 40f443c5c8b..00000000000 --- a/apps/macos/Sources/OpenClaw/CanvasA2UIActionMessageHandler.swift +++ /dev/null @@ -1,149 +0,0 @@ -import AppKit -import Foundation -import OpenClawIPC -import OpenClawKit -import WebKit - -final class CanvasA2UIActionMessageHandler: NSObject, WKScriptMessageHandler { - static let messageName = "openclawCanvasA2UIAction" - static let allMessageNames = [messageName] - - private let sessionKey: String - - init(sessionKey: String) { - self.sessionKey = sessionKey - super.init() - } - - func userContentController(_: WKUserContentController, didReceive message: WKScriptMessage) { - guard Self.allMessageNames.contains(message.name) else { return } - - // Only accept actions from local Canvas content (not arbitrary web pages). - guard let webView = message.webView, let url = webView.url else { return } - if let scheme = url.scheme, CanvasScheme.allSchemes.contains(scheme) { - // ok - } else if Self.isLocalNetworkCanvasURL(url) { - // ok - } else { - return - } - - let body: [String: Any] = { - if let dict = message.body as? [String: Any] { return dict } - if let dict = message.body as? [AnyHashable: Any] { - return dict.reduce(into: [String: Any]()) { acc, pair in - guard let key = pair.key as? String else { return } - acc[key] = pair.value - } - } - return [:] - }() - guard !body.isEmpty else { return } - - let userActionAny = body["userAction"] ?? body - let userAction: [String: Any] = { - if let dict = userActionAny as? [String: Any] { return dict } - if let dict = userActionAny as? [AnyHashable: Any] { - return dict.reduce(into: [String: Any]()) { acc, pair in - guard let key = pair.key as? String else { return } - acc[key] = pair.value - } - } - return [:] - }() - guard !userAction.isEmpty else { return } - - guard let name = OpenClawCanvasA2UIAction.extractActionName(userAction) else { return } - let actionId = - (userAction["id"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty - ?? UUID().uuidString - - canvasWindowLogger.info("A2UI action \(name, privacy: .public) session=\(self.sessionKey, privacy: .public)") - - let surfaceId = (userAction["surfaceId"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) - .nonEmpty ?? "main" - let sourceComponentId = (userAction["sourceComponentId"] as? String)? - .trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty ?? "-" - let instanceId = InstanceIdentity.instanceId.lowercased() - let contextJSON = OpenClawCanvasA2UIAction.compactJSON(userAction["context"]) - - // Token-efficient and unambiguous. The agent should treat this as a UI event and (by default) update Canvas. - let messageContext = OpenClawCanvasA2UIAction.AgentMessageContext( - actionName: name, - session: .init(key: self.sessionKey, surfaceId: surfaceId), - component: .init(id: sourceComponentId, host: InstanceIdentity.displayName, instanceId: instanceId), - contextJSON: contextJSON) - let text = OpenClawCanvasA2UIAction.formatAgentMessage(messageContext) - - Task { [weak webView] in - if AppStateStore.shared.connectionMode == .local { - GatewayProcessManager.shared.setActive(true) - } - - let result = await GatewayConnection.shared.sendAgent( - GatewayAgentInvocation( - message: text, - sessionKey: self.sessionKey, - thinking: "low", - deliver: false, - to: nil, - channel: .last, - idempotencyKey: actionId)) - - await MainActor.run { - guard let webView else { return } - let js = OpenClawCanvasA2UIAction.jsDispatchA2UIActionStatus( - actionId: actionId, - ok: result.ok, - error: result.error) - webView.evaluateJavaScript(js) { _, _ in } - } - if !result.ok { - canvasWindowLogger.error( - """ - A2UI action send failed name=\(name, privacy: .public) \ - error=\(result.error ?? "unknown", privacy: .public) - """) - } - } - } - - static func isLocalNetworkCanvasURL(_ url: URL) -> Bool { - guard let scheme = url.scheme?.lowercased(), scheme == "http" || scheme == "https" else { - return false - } - guard let host = url.host?.trimmingCharacters(in: .whitespacesAndNewlines), !host.isEmpty else { - return false - } - if host == "localhost" { return true } - if host.hasSuffix(".local") { return true } - if host.hasSuffix(".ts.net") { return true } - if host.hasSuffix(".tailscale.net") { return true } - if !host.contains("."), !host.contains(":") { return true } - if let ipv4 = Self.parseIPv4(host) { - return Self.isLocalNetworkIPv4(ipv4) - } - return false - } - - static func parseIPv4(_ host: String) -> (UInt8, UInt8, UInt8, UInt8)? { - let parts = host.split(separator: ".", omittingEmptySubsequences: false) - guard parts.count == 4 else { return nil } - let bytes: [UInt8] = parts.compactMap { UInt8($0) } - guard bytes.count == 4 else { return nil } - return (bytes[0], bytes[1], bytes[2], bytes[3]) - } - - static func isLocalNetworkIPv4(_ ip: (UInt8, UInt8, UInt8, UInt8)) -> Bool { - let (a, b, _, _) = ip - if a == 10 { return true } - if a == 172, (16...31).contains(Int(b)) { return true } - if a == 192, b == 168 { return true } - if a == 127 { return true } - if a == 169, b == 254 { return true } - if a == 100, (64...127).contains(Int(b)) { return true } - return false - } - - // Formatting helpers live in OpenClawKit (`OpenClawCanvasA2UIAction`). -} diff --git a/apps/macos/Sources/OpenClaw/CanvasChromeContainerView.swift b/apps/macos/Sources/OpenClaw/CanvasChromeContainerView.swift deleted file mode 100644 index b4158167dcf..00000000000 --- a/apps/macos/Sources/OpenClaw/CanvasChromeContainerView.swift +++ /dev/null @@ -1,235 +0,0 @@ -import AppKit -import QuartzCore - -final class HoverChromeContainerView: NSView { - private let content: NSView - private let chrome: CanvasChromeOverlayView - private var tracking: NSTrackingArea? - var onClose: (() -> Void)? - - init(containing content: NSView) { - self.content = content - self.chrome = CanvasChromeOverlayView(frame: .zero) - super.init(frame: .zero) - - self.wantsLayer = true - self.layer?.cornerRadius = 12 - self.layer?.masksToBounds = true - self.layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor - - self.content.translatesAutoresizingMaskIntoConstraints = false - self.addSubview(self.content) - - self.chrome.translatesAutoresizingMaskIntoConstraints = false - self.chrome.alphaValue = 0 - self.chrome.onClose = { [weak self] in self?.onClose?() } - self.addSubview(self.chrome) - - NSLayoutConstraint.activate([ - self.content.leadingAnchor.constraint(equalTo: self.leadingAnchor), - self.content.trailingAnchor.constraint(equalTo: self.trailingAnchor), - self.content.topAnchor.constraint(equalTo: self.topAnchor), - self.content.bottomAnchor.constraint(equalTo: self.bottomAnchor), - - self.chrome.leadingAnchor.constraint(equalTo: self.leadingAnchor), - self.chrome.trailingAnchor.constraint(equalTo: self.trailingAnchor), - self.chrome.topAnchor.constraint(equalTo: self.topAnchor), - self.chrome.bottomAnchor.constraint(equalTo: self.bottomAnchor), - ]) - } - - @available(*, unavailable) - required init?(coder: NSCoder) { - fatalError("init(coder:) is not supported") - } - - override func updateTrackingAreas() { - super.updateTrackingAreas() - if let tracking { - self.removeTrackingArea(tracking) - } - let area = NSTrackingArea( - rect: self.bounds, - options: [.activeAlways, .mouseEnteredAndExited, .inVisibleRect], - owner: self, - userInfo: nil) - self.addTrackingArea(area) - self.tracking = area - } - - private final class CanvasDragHandleView: NSView { - override func mouseDown(with event: NSEvent) { - self.window?.performDrag(with: event) - } - - override func acceptsFirstMouse(for _: NSEvent?) -> Bool { - true - } - } - - private final class CanvasResizeHandleView: NSView { - private var startPoint: NSPoint = .zero - private var startFrame: NSRect = .zero - - override func acceptsFirstMouse(for _: NSEvent?) -> Bool { - true - } - - override func mouseDown(with event: NSEvent) { - guard let window else { return } - _ = window.makeFirstResponder(self) - self.startPoint = NSEvent.mouseLocation - self.startFrame = window.frame - super.mouseDown(with: event) - } - - override func mouseDragged(with _: NSEvent) { - guard let window else { return } - let current = NSEvent.mouseLocation - let dx = current.x - self.startPoint.x - let dy = current.y - self.startPoint.y - - var frame = self.startFrame - frame.size.width = max(CanvasLayout.minPanelSize.width, frame.size.width + dx) - frame.origin.y += dy - frame.size.height = max(CanvasLayout.minPanelSize.height, frame.size.height - dy) - - if let screen = window.screen { - frame = CanvasWindowController.constrainFrame(frame, toVisibleFrame: screen.visibleFrame) - } - window.setFrame(frame, display: true) - } - } - - private final class CanvasChromeOverlayView: NSView { - var onClose: (() -> Void)? - - private let dragHandle = CanvasDragHandleView(frame: .zero) - private let resizeHandle = CanvasResizeHandleView(frame: .zero) - - private final class PassthroughVisualEffectView: NSVisualEffectView { - override func hitTest(_: NSPoint) -> NSView? { - nil - } - } - - private let closeBackground: NSVisualEffectView = { - let v = PassthroughVisualEffectView(frame: .zero) - v.material = .hudWindow - v.blendingMode = .withinWindow - v.state = .active - v.appearance = NSAppearance(named: .vibrantDark) - v.wantsLayer = true - v.layer?.cornerRadius = 10 - v.layer?.masksToBounds = true - v.layer?.borderWidth = 1 - v.layer?.borderColor = NSColor.white.withAlphaComponent(0.22).cgColor - v.layer?.backgroundColor = NSColor.black.withAlphaComponent(0.28).cgColor - v.layer?.shadowColor = NSColor.black.withAlphaComponent(0.35).cgColor - v.layer?.shadowOpacity = 0.35 - v.layer?.shadowRadius = 8 - v.layer?.shadowOffset = .zero - return v - }() - - private let closeButton: NSButton = { - let cfg = NSImage.SymbolConfiguration(pointSize: 8, weight: .semibold) - let img = NSImage(systemSymbolName: "xmark", accessibilityDescription: "Close")? - .withSymbolConfiguration(cfg) - ?? NSImage(size: NSSize(width: 18, height: 18)) - let btn = NSButton(image: img, target: nil, action: nil) - btn.isBordered = false - btn.bezelStyle = .regularSquare - btn.imageScaling = .scaleProportionallyDown - btn.contentTintColor = NSColor.white.withAlphaComponent(0.92) - btn.toolTip = "Close" - return btn - }() - - override init(frame frameRect: NSRect) { - super.init(frame: frameRect) - - self.wantsLayer = true - self.layer?.cornerRadius = 12 - self.layer?.masksToBounds = true - self.layer?.borderWidth = 1 - self.layer?.borderColor = NSColor.black.withAlphaComponent(0.18).cgColor - self.layer?.backgroundColor = NSColor.black.withAlphaComponent(0.02).cgColor - - self.dragHandle.translatesAutoresizingMaskIntoConstraints = false - self.dragHandle.wantsLayer = true - self.dragHandle.layer?.backgroundColor = NSColor.clear.cgColor - self.addSubview(self.dragHandle) - - self.resizeHandle.translatesAutoresizingMaskIntoConstraints = false - self.resizeHandle.wantsLayer = true - self.resizeHandle.layer?.backgroundColor = NSColor.clear.cgColor - self.addSubview(self.resizeHandle) - - self.closeBackground.translatesAutoresizingMaskIntoConstraints = false - self.addSubview(self.closeBackground) - - self.closeButton.translatesAutoresizingMaskIntoConstraints = false - self.closeButton.target = self - self.closeButton.action = #selector(self.handleClose) - self.addSubview(self.closeButton) - - NSLayoutConstraint.activate([ - self.dragHandle.leadingAnchor.constraint(equalTo: self.leadingAnchor), - self.dragHandle.trailingAnchor.constraint(equalTo: self.trailingAnchor), - self.dragHandle.topAnchor.constraint(equalTo: self.topAnchor), - self.dragHandle.heightAnchor.constraint(equalToConstant: 30), - - self.closeBackground.centerXAnchor.constraint(equalTo: self.closeButton.centerXAnchor), - self.closeBackground.centerYAnchor.constraint(equalTo: self.closeButton.centerYAnchor), - self.closeBackground.widthAnchor.constraint(equalToConstant: 20), - self.closeBackground.heightAnchor.constraint(equalToConstant: 20), - - self.closeButton.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -8), - self.closeButton.topAnchor.constraint(equalTo: self.topAnchor, constant: 8), - self.closeButton.widthAnchor.constraint(equalToConstant: 16), - self.closeButton.heightAnchor.constraint(equalToConstant: 16), - - self.resizeHandle.trailingAnchor.constraint(equalTo: self.trailingAnchor), - self.resizeHandle.bottomAnchor.constraint(equalTo: self.bottomAnchor), - self.resizeHandle.widthAnchor.constraint(equalToConstant: 18), - self.resizeHandle.heightAnchor.constraint(equalToConstant: 18), - ]) - } - - @available(*, unavailable) - required init?(coder: NSCoder) { - fatalError("init(coder:) is not supported") - } - - override func hitTest(_ point: NSPoint) -> NSView? { - // When the chrome is hidden, do not intercept any mouse events (let the WKWebView receive them). - guard self.alphaValue > 0.02 else { return nil } - - if self.closeButton.frame.contains(point) { return self.closeButton } - if self.dragHandle.frame.contains(point) { return self.dragHandle } - if self.resizeHandle.frame.contains(point) { return self.resizeHandle } - return nil - } - - @objc private func handleClose() { - self.onClose?() - } - } - - override func mouseEntered(with _: NSEvent) { - NSAnimationContext.runAnimationGroup { ctx in - ctx.duration = 0.12 - ctx.timingFunction = CAMediaTimingFunction(name: .easeOut) - self.chrome.animator().alphaValue = 1 - } - } - - override func mouseExited(with _: NSEvent) { - NSAnimationContext.runAnimationGroup { ctx in - ctx.duration = 0.16 - ctx.timingFunction = CAMediaTimingFunction(name: .easeOut) - self.chrome.animator().alphaValue = 0 - } - } -} diff --git a/apps/macos/Sources/OpenClaw/CanvasFileWatcher.swift b/apps/macos/Sources/OpenClaw/CanvasFileWatcher.swift deleted file mode 100644 index 3ed0d67ffbc..00000000000 --- a/apps/macos/Sources/OpenClaw/CanvasFileWatcher.swift +++ /dev/null @@ -1,24 +0,0 @@ -import Foundation - -final class CanvasFileWatcher: @unchecked Sendable { - private let watcher: CoalescingFSEventsWatcher - - init(url: URL, onChange: @escaping () -> Void) { - self.watcher = CoalescingFSEventsWatcher( - paths: [url.path], - queueLabel: "ai.openclaw.canvaswatcher", - onChange: onChange) - } - - deinit { - self.stop() - } - - func start() { - self.watcher.start() - } - - func stop() { - self.watcher.stop() - } -} diff --git a/apps/macos/Sources/OpenClaw/CanvasManager.swift b/apps/macos/Sources/OpenClaw/CanvasManager.swift deleted file mode 100644 index 843f78842bd..00000000000 --- a/apps/macos/Sources/OpenClaw/CanvasManager.swift +++ /dev/null @@ -1,342 +0,0 @@ -import AppKit -import Foundation -import OpenClawIPC -import OpenClawKit -import OSLog - -@MainActor -final class CanvasManager { - static let shared = CanvasManager() - - private static let logger = Logger(subsystem: "ai.openclaw", category: "CanvasManager") - - private var panelController: CanvasWindowController? - private var panelSessionKey: String? - private var lastAutoA2UIUrl: String? - private var gatewayWatchTask: Task? - - private init() { - self.startGatewayObserver() - } - - var onPanelVisibilityChanged: ((Bool) -> Void)? - - /// Optional anchor provider (e.g. menu bar status item). If nil, Canvas anchors to the mouse cursor. - var defaultAnchorProvider: (() -> NSRect?)? - - private nonisolated static let canvasRoot: URL = { - let base = FileManager().urls(for: .applicationSupportDirectory, in: .userDomainMask).first! - return base.appendingPathComponent("OpenClaw/canvas", isDirectory: true) - }() - - func show(sessionKey: String, path: String? = nil, placement: CanvasPlacement? = nil) throws -> String { - try self.showDetailed(sessionKey: sessionKey, target: path, placement: placement).directory - } - - func showDetailed( - sessionKey: String, - target: String? = nil, - placement: CanvasPlacement? = nil) throws -> CanvasShowResult - { - Self.logger.debug( - """ - showDetailed start session=\(sessionKey, privacy: .public) \ - target=\(target ?? "", privacy: .public) \ - placement=\(placement != nil) - """) - let anchorProvider = self.defaultAnchorProvider ?? Self.mouseAnchorProvider - let session = sessionKey.trimmingCharacters(in: .whitespacesAndNewlines) - let normalizedTarget = target? - .trimmingCharacters(in: .whitespacesAndNewlines) - .nonEmpty - - if let controller = self.panelController, self.panelSessionKey == session { - Self.logger.debug("showDetailed reuse existing session=\(session, privacy: .public)") - controller.onVisibilityChanged = { [weak self] visible in - self?.onPanelVisibilityChanged?(visible) - } - controller.presentAnchoredPanel(anchorProvider: anchorProvider) - controller.applyPreferredPlacement(placement) - self.refreshDebugStatus() - - // Existing session: only navigate when an explicit target was provided. - if let normalizedTarget { - controller.load(target: normalizedTarget) - return self.makeShowResult( - directory: controller.directoryPath, - target: target, - effectiveTarget: normalizedTarget) - } - - self.maybeAutoNavigateToA2UIAsync(controller: controller) - return CanvasShowResult( - directory: controller.directoryPath, - target: target, - effectiveTarget: nil, - status: .shown, - url: nil) - } - - Self.logger.debug("showDetailed creating new session=\(session, privacy: .public)") - self.panelController?.close() - self.panelController = nil - self.panelSessionKey = nil - - Self.logger.debug("showDetailed ensure canvas root dir") - try FileManager().createDirectory(at: Self.canvasRoot, withIntermediateDirectories: true) - Self.logger.debug("showDetailed init CanvasWindowController") - let controller = try CanvasWindowController( - sessionKey: session, - root: Self.canvasRoot, - presentation: .panel(anchorProvider: anchorProvider)) - Self.logger.debug("showDetailed CanvasWindowController init done") - controller.onVisibilityChanged = { [weak self] visible in - self?.onPanelVisibilityChanged?(visible) - } - self.panelController = controller - self.panelSessionKey = session - controller.applyPreferredPlacement(placement) - - // New session: default to "/" so the user sees either the welcome page or `index.html`. - let effectiveTarget = normalizedTarget ?? "/" - Self.logger.debug("showDetailed showCanvas effectiveTarget=\(effectiveTarget, privacy: .public)") - controller.showCanvas(path: effectiveTarget) - Self.logger.debug("showDetailed showCanvas done") - if normalizedTarget == nil { - self.maybeAutoNavigateToA2UIAsync(controller: controller) - } - self.refreshDebugStatus() - - return self.makeShowResult( - directory: controller.directoryPath, - target: target, - effectiveTarget: effectiveTarget) - } - - func hide(sessionKey: String) { - let session = sessionKey.trimmingCharacters(in: .whitespacesAndNewlines) - guard self.panelSessionKey == session else { return } - self.panelController?.hideCanvas() - } - - func hideAll() { - self.panelController?.hideCanvas() - } - - func eval(sessionKey: String, javaScript: String) async throws -> String { - _ = try self.show(sessionKey: sessionKey, path: nil) - guard let controller = self.panelController else { return "" } - return try await controller.eval(javaScript: javaScript) - } - - func snapshot(sessionKey: String, outPath: String?) async throws -> String { - _ = try self.show(sessionKey: sessionKey, path: nil) - guard let controller = self.panelController else { - throw NSError(domain: "Canvas", code: 21, userInfo: [NSLocalizedDescriptionKey: "canvas not available"]) - } - return try await controller.snapshot(to: outPath) - } - - // MARK: - Gateway A2UI auto-nav - - private func startGatewayObserver() { - self.gatewayWatchTask?.cancel() - self.gatewayWatchTask = Task { [weak self] in - guard let self else { return } - let stream = await GatewayConnection.shared.subscribe(bufferingNewest: 1) - for await push in stream { - self.handleGatewayPush(push) - } - } - } - - private func handleGatewayPush(_ push: GatewayPush) { - guard case let .snapshot(snapshot) = push else { return } - let raw = snapshot.canvashosturl?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if raw.isEmpty { - Self.logger.debug("canvas host url missing in gateway snapshot") - } else { - Self.logger.debug("canvas host url snapshot=\(raw, privacy: .public)") - } - let a2uiUrl = Self.resolveA2UIHostUrl(from: raw) - if a2uiUrl == nil, !raw.isEmpty { - Self.logger.debug("canvas host url invalid; cannot resolve A2UI") - } - guard let controller = self.panelController else { - if a2uiUrl != nil { - Self.logger.debug("canvas panel not visible; skipping auto-nav") - } - return - } - self.maybeAutoNavigateToA2UI(controller: controller, a2uiUrl: a2uiUrl) - } - - private func maybeAutoNavigateToA2UIAsync(controller: CanvasWindowController) { - Task { [weak self] in - guard let self else { return } - let a2uiUrl = await self.resolveA2UIHostUrl() - await MainActor.run { - guard self.panelController === controller else { return } - self.maybeAutoNavigateToA2UI(controller: controller, a2uiUrl: a2uiUrl) - } - } - } - - private func maybeAutoNavigateToA2UI(controller: CanvasWindowController, a2uiUrl: String?) { - guard let a2uiUrl else { return } - let shouldNavigate = controller.shouldAutoNavigateToA2UI(lastAutoTarget: self.lastAutoA2UIUrl) - guard shouldNavigate else { - Self.logger.debug("canvas auto-nav skipped; target unchanged") - return - } - Self.logger.debug("canvas auto-nav -> \(a2uiUrl, privacy: .public)") - controller.load(target: a2uiUrl) - self.lastAutoA2UIUrl = a2uiUrl - } - - private func resolveA2UIHostUrl() async -> String? { - let raw = await GatewayConnection.shared.canvasHostUrl() - return Self.resolveA2UIHostUrl(from: raw) - } - - func refreshDebugStatus() { - guard let controller = self.panelController else { return } - let enabled = AppStateStore.shared.debugPaneEnabled - let mode = AppStateStore.shared.connectionMode - let title: String? - let subtitle: String? - switch mode { - case .remote: - title = "Remote control" - switch ControlChannel.shared.state { - case .connected: - subtitle = "Connected" - case .connecting: - subtitle = "Connecting…" - case .disconnected: - subtitle = "Disconnected" - case let .degraded(message): - subtitle = message.isEmpty ? "Degraded" : message - } - case .local: - title = GatewayProcessManager.shared.status.label - subtitle = mode.rawValue - case .unconfigured: - title = "Unconfigured" - subtitle = mode.rawValue - } - controller.updateDebugStatus(enabled: enabled, title: title, subtitle: subtitle) - } - - 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("__openclaw__/a2ui/").absoluteString + "?platform=macos" - } - - // MARK: - Anchoring - - private static func mouseAnchorProvider() -> NSRect? { - let pt = NSEvent.mouseLocation - return NSRect(x: pt.x, y: pt.y, width: 1, height: 1) - } - - // placement interpretation is handled by the window controller. - - // MARK: - Helpers - - private static func directURL(for target: String?) -> URL? { - guard let target else { return nil } - let trimmed = target.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - - if let url = URL(string: trimmed), let scheme = url.scheme?.lowercased() { - if scheme == "https" || scheme == "http" || scheme == "file" { return url } - } - - // Convenience: existing absolute *file* paths resolve as local files. - // (Avoid treating Canvas routes like "/" as filesystem paths.) - if trimmed.hasPrefix("/") { - var isDir: ObjCBool = false - if FileManager().fileExists(atPath: trimmed, isDirectory: &isDir), !isDir.boolValue { - return URL(fileURLWithPath: trimmed) - } - } - - return nil - } - - private func makeShowResult( - directory: String, - target: String?, - effectiveTarget: String) -> CanvasShowResult - { - if let url = Self.directURL(for: effectiveTarget) { - return CanvasShowResult( - directory: directory, - target: target, - effectiveTarget: effectiveTarget, - status: .web, - url: url.absoluteString) - } - - let sessionDir = URL(fileURLWithPath: directory) - let status = Self.localStatus(sessionDir: sessionDir, target: effectiveTarget) - let host = sessionDir.lastPathComponent - let canvasURL = CanvasScheme.makeURL(session: host, path: effectiveTarget)?.absoluteString - return CanvasShowResult( - directory: directory, - target: target, - effectiveTarget: effectiveTarget, - status: status, - url: canvasURL) - } - - private static func localStatus(sessionDir: URL, target: String) -> CanvasShowStatus { - let fm = FileManager() - let trimmed = target.trimmingCharacters(in: .whitespacesAndNewlines) - let withoutQuery = trimmed.split(separator: "?", maxSplits: 1, omittingEmptySubsequences: false).first - .map(String.init) ?? trimmed - var path = withoutQuery - if path.hasPrefix("/") { path.removeFirst() } - path = path.removingPercentEncoding ?? path - - // Root special-case: built-in scaffold page when no index exists. - if path.isEmpty { - let a = sessionDir.appendingPathComponent("index.html", isDirectory: false) - let b = sessionDir.appendingPathComponent("index.htm", isDirectory: false) - if fm.fileExists(atPath: a.path) || fm.fileExists(atPath: b.path) { return .ok } - return .welcome - } - - // Direct file or directory. - var candidate = sessionDir.appendingPathComponent(path, isDirectory: false) - var isDir: ObjCBool = false - if fm.fileExists(atPath: candidate.path, isDirectory: &isDir) { - if isDir.boolValue { - return Self.indexExists(in: candidate) ? .ok : .notFound - } - return .ok - } - - // Directory index behavior ("/yolo" -> "yolo/index.html") if directory exists. - if !path.isEmpty, !path.hasSuffix("/") { - candidate = sessionDir.appendingPathComponent(path, isDirectory: true) - if fm.fileExists(atPath: candidate.path, isDirectory: &isDir), isDir.boolValue { - return Self.indexExists(in: candidate) ? .ok : .notFound - } - } - - return .notFound - } - - private static func indexExists(in dir: URL) -> Bool { - let fm = FileManager() - let a = dir.appendingPathComponent("index.html", isDirectory: false) - if fm.fileExists(atPath: a.path) { return true } - let b = dir.appendingPathComponent("index.htm", isDirectory: false) - return fm.fileExists(atPath: b.path) - } - - // no bundled A2UI shell; scaffold fallback is purely visual -} diff --git a/apps/macos/Sources/OpenClaw/CanvasScheme.swift b/apps/macos/Sources/OpenClaw/CanvasScheme.swift deleted file mode 100644 index 4f08da2d7b3..00000000000 --- a/apps/macos/Sources/OpenClaw/CanvasScheme.swift +++ /dev/null @@ -1,42 +0,0 @@ -import Foundation - -enum CanvasScheme { - static let scheme = "openclaw-canvas" - static let allSchemes = [scheme] - - static func makeURL(session: String, path: String? = nil) -> URL? { - var comps = URLComponents() - comps.scheme = Self.scheme - comps.host = session - let p = (path ?? "/").trimmingCharacters(in: .whitespacesAndNewlines) - if p.isEmpty || p == "/" { - comps.path = "/" - } else if p.hasPrefix("/") { - comps.path = p - } else { - comps.path = "/" + p - } - return comps.url - } - - static func mimeType(forExtension ext: String) -> String { - switch ext.lowercased() { - // Note: WKURLSchemeHandler uses URLResponse(mimeType:), which expects a bare MIME type - // (no `; charset=...`). Encoding is provided via URLResponse(textEncodingName:). - case "html", "htm": "text/html" - case "js", "mjs": "application/javascript" - case "css": "text/css" - case "json", "map": "application/json" - case "svg": "image/svg+xml" - case "png": "image/png" - case "jpg", "jpeg": "image/jpeg" - case "gif": "image/gif" - case "ico": "image/x-icon" - case "woff2": "font/woff2" - case "woff": "font/woff" - case "ttf": "font/ttf" - case "wasm": "application/wasm" - default: "application/octet-stream" - } - } -} diff --git a/apps/macos/Sources/OpenClaw/CanvasSchemeHandler.swift b/apps/macos/Sources/OpenClaw/CanvasSchemeHandler.swift deleted file mode 100644 index 6905af50014..00000000000 --- a/apps/macos/Sources/OpenClaw/CanvasSchemeHandler.swift +++ /dev/null @@ -1,259 +0,0 @@ -import Foundation -import OpenClawKit -import OSLog -import WebKit - -private let canvasLogger = Logger(subsystem: "ai.openclaw", category: "Canvas") - -final class CanvasSchemeHandler: NSObject, WKURLSchemeHandler { - private let root: URL - - init(root: URL) { - self.root = root - } - - func webView(_: WKWebView, start urlSchemeTask: WKURLSchemeTask) { - guard let url = urlSchemeTask.request.url else { - urlSchemeTask.didFailWithError(NSError(domain: "Canvas", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "missing url", - ])) - return - } - - let response = self.response(for: url) - let mime = response.mime - let data = response.data - let encoding = self.textEncodingName(forMimeType: mime) - - let urlResponse = URLResponse( - url: url, - mimeType: mime, - expectedContentLength: data.count, - textEncodingName: encoding) - urlSchemeTask.didReceive(urlResponse) - urlSchemeTask.didReceive(data) - urlSchemeTask.didFinish() - } - - func webView(_: WKWebView, stop _: WKURLSchemeTask) { - // no-op - } - - private struct CanvasResponse { - let mime: String - let data: Data - } - - private func response(for url: URL) -> CanvasResponse { - guard let scheme = url.scheme, CanvasScheme.allSchemes.contains(scheme) else { - return self.html("Invalid scheme.") - } - guard let session = url.host, !session.isEmpty else { - return self.html("Missing session.") - } - - // Keep session component safe; don't allow slashes or traversal. - if session.contains("/") || session.contains("..") { - return self.html("Invalid session.") - } - - let sessionRoot = self.root.appendingPathComponent(session, isDirectory: true) - - // Path mapping: request path maps directly into the session dir. - var path = url.path - if let qIdx = path.firstIndex(of: "?") { path = String(path[.. \(servedPath, privacy: .public)") - return CanvasResponse(mime: mime, data: data) - } catch { - let failedPath = standardizedFile.path - let errorText = error.localizedDescription - canvasLogger - .error( - "failed reading \(failedPath, privacy: .public): \(errorText, privacy: .public)") - return self.html("Failed to read file.", title: "Canvas error") - } - } - - private func resolveFileURL(sessionRoot: URL, requestPath: String) -> URL? { - let fm = FileManager() - var candidate = sessionRoot.appendingPathComponent(requestPath, isDirectory: false) - - var isDir: ObjCBool = false - if fm.fileExists(atPath: candidate.path, isDirectory: &isDir) { - if isDir.boolValue { - if let idx = self.resolveIndex(in: candidate) { return idx } - return nil - } - return candidate - } - - // Directory index behavior: - // - "/yolo" serves "/index.html" if that directory exists. - if !requestPath.isEmpty, !requestPath.hasSuffix("/") { - candidate = sessionRoot.appendingPathComponent(requestPath, isDirectory: true) - if fm.fileExists(atPath: candidate.path, isDirectory: &isDir), isDir.boolValue { - if let idx = self.resolveIndex(in: candidate) { return idx } - } - } - - // Root fallback: - // - "/" serves "/index.html" if present. - if requestPath.isEmpty { - return self.resolveIndex(in: sessionRoot) - } - - return nil - } - - private func resolveIndex(in dir: URL) -> URL? { - let fm = FileManager() - let a = dir.appendingPathComponent("index.html", isDirectory: false) - if fm.fileExists(atPath: a.path) { return a } - let b = dir.appendingPathComponent("index.htm", isDirectory: false) - if fm.fileExists(atPath: b.path) { return b } - return nil - } - - private func html(_ body: String, title: String = "Canvas") -> CanvasResponse { - let html = """ - - - - - - \(title) - - - -

- - - """ - return CanvasResponse(mime: "text/html", data: Data(html.utf8)) - } - - private func welcomePage(sessionRoot: URL) -> CanvasResponse { - let escaped = sessionRoot.path - .replacingOccurrences(of: "&", with: "&") - .replacingOccurrences(of: "<", with: "<") - .replacingOccurrences(of: ">", with: ">") - let body = """ -
Canvas is ready.
-
Create index.html in:
-
\(escaped)
- """ - return self.html(body, title: "Canvas") - } - - private func scaffoldPage(sessionRoot: URL) -> CanvasResponse { - // Default Canvas UX: when no index exists, show the built-in scaffold page. - if let data = self.loadBundledResourceData(relativePath: "CanvasScaffold/scaffold.html") { - return CanvasResponse(mime: "text/html", data: data) - } - - // Fallback for dev misconfiguration: show the classic welcome page. - return self.welcomePage(sessionRoot: sessionRoot) - } - - private func loadBundledResourceData(relativePath: String) -> Data? { - let trimmed = relativePath.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - if trimmed.contains("..") || trimmed.contains("\\") { return nil } - - let parts = trimmed.split(separator: "/") - guard let filename = parts.last else { return nil } - let subdirectory = - parts.count > 1 ? parts.dropLast().joined(separator: "/") : nil - let fileURL = URL(fileURLWithPath: String(filename)) - let ext = fileURL.pathExtension - let name = fileURL.deletingPathExtension().lastPathComponent - guard !name.isEmpty, !ext.isEmpty else { return nil } - - let bundle = OpenClawKitResources.bundle - let resourceURL = - bundle.url(forResource: name, withExtension: ext, subdirectory: subdirectory) - ?? bundle.url(forResource: name, withExtension: ext) - guard let resourceURL else { return nil } - return try? Data(contentsOf: resourceURL) - } - - private func textEncodingName(forMimeType mimeType: String) -> String? { - if mimeType.hasPrefix("text/") { return "utf-8" } - switch mimeType { - case "application/javascript", "application/json", "image/svg+xml": - return "utf-8" - default: - return nil - } - } -} - -#if DEBUG -extension CanvasSchemeHandler { - func _testResponse(for url: URL) -> (mime: String, data: Data) { - let response = self.response(for: url) - return (response.mime, response.data) - } - - func _testResolveFileURL(sessionRoot: URL, requestPath: String) -> URL? { - self.resolveFileURL(sessionRoot: sessionRoot, requestPath: requestPath) - } - - func _testTextEncodingName(for mimeType: String) -> String? { - self.textEncodingName(forMimeType: mimeType) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/CanvasWindow.swift b/apps/macos/Sources/OpenClaw/CanvasWindow.swift deleted file mode 100644 index a87f3256170..00000000000 --- a/apps/macos/Sources/OpenClaw/CanvasWindow.swift +++ /dev/null @@ -1,31 +0,0 @@ -import AppKit - -let canvasWindowLogger = Logger(subsystem: "ai.openclaw", category: "Canvas") - -enum CanvasLayout { - static let panelSize = NSSize(width: 520, height: 680) - static let windowSize = NSSize(width: 1120, height: 840) - static let anchorPadding: CGFloat = 8 - static let defaultPadding: CGFloat = 10 - static let minPanelSize = NSSize(width: 360, height: 360) -} - -final class CanvasPanel: NSPanel { - override var canBecomeKey: Bool { - true - } - - override var canBecomeMain: Bool { - true - } -} - -enum CanvasPresentation { - case window - case panel(anchorProvider: () -> NSRect?) - - var isPanel: Bool { - if case .panel = self { return true } - return false - } -} diff --git a/apps/macos/Sources/OpenClaw/CanvasWindowController+Helpers.swift b/apps/macos/Sources/OpenClaw/CanvasWindowController+Helpers.swift deleted file mode 100644 index a7d10f95b56..00000000000 --- a/apps/macos/Sources/OpenClaw/CanvasWindowController+Helpers.swift +++ /dev/null @@ -1,43 +0,0 @@ -import AppKit -import Foundation - -extension CanvasWindowController { - // MARK: - Helpers - - static func sanitizeSessionKey(_ key: String) -> String { - let trimmed = key.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty { return "main" } - let allowed = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-+") - let scalars = trimmed.unicodeScalars.map { allowed.contains($0) ? Character($0) : "_" } - return String(scalars) - } - - static func jsStringLiteral(_ value: String) -> String { - let data = try? JSONEncoder().encode(value) - return data.flatMap { String(data: $0, encoding: .utf8) } ?? "\"\"" - } - - static func jsOptionalStringLiteral(_ value: String?) -> String { - guard let value else { return "null" } - return Self.jsStringLiteral(value) - } - - static func storedFrameDefaultsKey(sessionKey: String) -> String { - "openclaw.canvas.frame.\(self.sanitizeSessionKey(sessionKey))" - } - - static func loadRestoredFrame(sessionKey: String) -> NSRect? { - let key = self.storedFrameDefaultsKey(sessionKey: sessionKey) - guard let arr = UserDefaults.standard.array(forKey: key) as? [Double], arr.count == 4 else { return nil } - let rect = NSRect(x: arr[0], y: arr[1], width: arr[2], height: arr[3]) - if rect.width < CanvasLayout.minPanelSize.width || rect.height < CanvasLayout.minPanelSize.height { return nil } - return rect - } - - static func storeRestoredFrame(_ frame: NSRect, sessionKey: String) { - let key = self.storedFrameDefaultsKey(sessionKey: sessionKey) - UserDefaults.standard.set( - [Double(frame.origin.x), Double(frame.origin.y), Double(frame.size.width), Double(frame.size.height)], - forKey: key) - } -} diff --git a/apps/macos/Sources/OpenClaw/CanvasWindowController+Navigation.swift b/apps/macos/Sources/OpenClaw/CanvasWindowController+Navigation.swift deleted file mode 100644 index 16e0b01d294..00000000000 --- a/apps/macos/Sources/OpenClaw/CanvasWindowController+Navigation.swift +++ /dev/null @@ -1,64 +0,0 @@ -import AppKit -import WebKit - -extension CanvasWindowController { - // MARK: - WKNavigationDelegate - - @MainActor - func webView( - _: WKWebView, - decidePolicyFor navigationAction: WKNavigationAction, - decisionHandler: @escaping @MainActor @Sendable (WKNavigationActionPolicy) -> Void) - { - guard let url = navigationAction.request.url else { - decisionHandler(.cancel) - return - } - let scheme = url.scheme?.lowercased() - - // Deep links: allow local Canvas content to invoke the agent without bouncing through NSWorkspace. - if scheme == "openclaw" { - if let currentScheme = self.webView.url?.scheme, - CanvasScheme.allSchemes.contains(currentScheme) - { - Task { await DeepLinkHandler.shared.handle(url: url) } - } else { - canvasWindowLogger - .debug("ignoring deep link from non-canvas page \(url.absoluteString, privacy: .public)") - } - decisionHandler(.cancel) - return - } - - // Keep web content inside the panel when reasonable. - // `about:blank` and friends are common internal navigations for WKWebView; never send them to NSWorkspace. - if CanvasScheme.allSchemes.contains(scheme ?? "") - || scheme == "https" - || scheme == "http" - || scheme == "about" - || scheme == "blob" - || scheme == "data" - || scheme == "javascript" - { - decisionHandler(.allow) - return - } - - // Only open external URLs when there is a registered handler, otherwise macOS will show a confusing - // "There is no application set to open the URL ..." alert (e.g. for about:blank). - if let appURL = NSWorkspace.shared.urlForApplication(toOpen: url) { - NSWorkspace.shared.open( - [url], - withApplicationAt: appURL, - configuration: NSWorkspace.OpenConfiguration(), - completionHandler: nil) - } else { - canvasWindowLogger.debug("no application to open url \(url.absoluteString, privacy: .public)") - } - decisionHandler(.cancel) - } - - func webView(_: WKWebView, didFinish _: WKNavigation?) { - self.applyDebugStatusIfNeeded() - } -} diff --git a/apps/macos/Sources/OpenClaw/CanvasWindowController+Testing.swift b/apps/macos/Sources/OpenClaw/CanvasWindowController+Testing.swift deleted file mode 100644 index 6c53fbc9971..00000000000 --- a/apps/macos/Sources/OpenClaw/CanvasWindowController+Testing.swift +++ /dev/null @@ -1,39 +0,0 @@ -#if DEBUG -import AppKit -import Foundation - -extension CanvasWindowController { - static func _testSanitizeSessionKey(_ key: String) -> String { - self.sanitizeSessionKey(key) - } - - static func _testJSStringLiteral(_ value: String) -> String { - self.jsStringLiteral(value) - } - - static func _testJSOptionalStringLiteral(_ value: String?) -> String { - self.jsOptionalStringLiteral(value) - } - - static func _testStoredFrameKey(sessionKey: String) -> String { - self.storedFrameDefaultsKey(sessionKey: sessionKey) - } - - static func _testStoreAndLoadFrame(sessionKey: String, frame: NSRect) -> NSRect? { - self.storeRestoredFrame(frame, sessionKey: sessionKey) - return self.loadRestoredFrame(sessionKey: sessionKey) - } - - static func _testParseIPv4(_ host: String) -> (UInt8, UInt8, UInt8, UInt8)? { - CanvasA2UIActionMessageHandler.parseIPv4(host) - } - - static func _testIsLocalNetworkIPv4(_ ip: (UInt8, UInt8, UInt8, UInt8)) -> Bool { - CanvasA2UIActionMessageHandler.isLocalNetworkIPv4(ip) - } - - static func _testIsLocalNetworkCanvasURL(_ url: URL) -> Bool { - CanvasA2UIActionMessageHandler.isLocalNetworkCanvasURL(url) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/CanvasWindowController+Window.swift b/apps/macos/Sources/OpenClaw/CanvasWindowController+Window.swift deleted file mode 100644 index 042ee00ba97..00000000000 --- a/apps/macos/Sources/OpenClaw/CanvasWindowController+Window.swift +++ /dev/null @@ -1,166 +0,0 @@ -import AppKit -import OpenClawIPC - -extension CanvasWindowController { - // MARK: - Window - - static func makeWindow(for presentation: CanvasPresentation, contentView: NSView) -> NSWindow { - switch presentation { - case .window: - let window = NSWindow( - contentRect: NSRect(origin: .zero, size: CanvasLayout.windowSize), - styleMask: [.titled, .closable, .resizable, .miniaturizable], - backing: .buffered, - defer: false) - window.title = "OpenClaw Canvas" - window.isReleasedWhenClosed = false - window.contentView = contentView - window.center() - window.minSize = NSSize(width: 880, height: 680) - return window - - case .panel: - let panel = CanvasPanel( - contentRect: NSRect(origin: .zero, size: CanvasLayout.panelSize), - styleMask: [.borderless, .resizable], - backing: .buffered, - defer: false) - // Keep Canvas below the Voice Wake overlay panel. - panel.level = NSWindow.Level(rawValue: NSWindow.Level.statusBar.rawValue - 1) - panel.hasShadow = true - panel.isMovable = false - panel.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary] - panel.titleVisibility = .hidden - panel.titlebarAppearsTransparent = true - panel.backgroundColor = .clear - panel.isOpaque = false - panel.contentView = contentView - panel.becomesKeyOnlyIfNeeded = true - panel.hidesOnDeactivate = false - panel.minSize = CanvasLayout.minPanelSize - return panel - } - } - - func presentAnchoredPanel(anchorProvider: @escaping () -> NSRect?) { - guard case .panel = self.presentation, let window else { return } - self.repositionPanel(using: anchorProvider) - window.makeKeyAndOrderFront(nil) - NSApp.activate(ignoringOtherApps: true) - window.makeFirstResponder(self.webView) - VoiceWakeOverlayController.shared.bringToFrontIfVisible() - self.onVisibilityChanged?(true) - } - - func repositionPanel(using anchorProvider: () -> NSRect?) { - guard let panel = self.window else { return } - let anchor = anchorProvider() - let targetScreen = Self.screen(forAnchor: anchor) - ?? Self.screenContainingMouseCursor() - ?? panel.screen - ?? NSScreen.main - ?? NSScreen.screens.first - - let restored = Self.loadRestoredFrame(sessionKey: self.sessionKey) - let restoredIsValid = if let restored, let targetScreen { - Self.isFrameMeaningfullyVisible(restored, on: targetScreen) - } else { - restored != nil - } - - var frame = if let restored, restoredIsValid { - restored - } else { - Self.defaultTopRightFrame(panel: panel, screen: targetScreen) - } - - // Apply agent placement as partial overrides: - // - If agent provides x/y, override origin. - // - If agent provides width/height, override size. - // - If agent provides only size, keep the remembered origin. - if let placement = self.preferredPlacement { - if let x = placement.x { frame.origin.x = x } - if let y = placement.y { frame.origin.y = y } - if let w = placement.width { frame.size.width = max(CanvasLayout.minPanelSize.width, CGFloat(w)) } - if let h = placement.height { frame.size.height = max(CanvasLayout.minPanelSize.height, CGFloat(h)) } - } - - self.setPanelFrame(frame, on: targetScreen) - } - - static func defaultTopRightFrame(panel: NSWindow, screen: NSScreen?) -> NSRect { - let w = max(CanvasLayout.minPanelSize.width, panel.frame.width) - let h = max(CanvasLayout.minPanelSize.height, panel.frame.height) - return WindowPlacement.topRightFrame( - size: NSSize(width: w, height: h), - padding: CanvasLayout.defaultPadding, - on: screen) - } - - func setPanelFrame(_ frame: NSRect, on screen: NSScreen?) { - guard let panel = self.window else { return } - guard let s = screen ?? panel.screen ?? NSScreen.main ?? NSScreen.screens.first else { - panel.setFrame(frame, display: false) - self.persistFrameIfPanel() - return - } - - let constrained = Self.constrainFrame(frame, toVisibleFrame: s.visibleFrame) - panel.setFrame(constrained, display: false) - self.persistFrameIfPanel() - } - - static func screen(forAnchor anchor: NSRect?) -> NSScreen? { - guard let anchor else { return nil } - let center = NSPoint(x: anchor.midX, y: anchor.midY) - return NSScreen.screens.first { screen in - screen.frame.contains(anchor.origin) || screen.frame.contains(center) - } - } - - static func screenContainingMouseCursor() -> NSScreen? { - let point = NSEvent.mouseLocation - return NSScreen.screens.first { $0.frame.contains(point) } - } - - static func isFrameMeaningfullyVisible(_ frame: NSRect, on screen: NSScreen) -> Bool { - frame.intersects(screen.visibleFrame.insetBy(dx: 12, dy: 12)) - } - - static func constrainFrame(_ frame: NSRect, toVisibleFrame bounds: NSRect) -> NSRect { - if bounds == .zero { return frame } - - var next = frame - next.size.width = min(max(CanvasLayout.minPanelSize.width, next.size.width), bounds.width) - next.size.height = min(max(CanvasLayout.minPanelSize.height, next.size.height), bounds.height) - - let maxX = bounds.maxX - next.size.width - let maxY = bounds.maxY - next.size.height - - next.origin.x = maxX >= bounds.minX ? min(max(next.origin.x, bounds.minX), maxX) : bounds.minX - next.origin.y = maxY >= bounds.minY ? min(max(next.origin.y, bounds.minY), maxY) : bounds.minY - - next.origin.x = round(next.origin.x) - next.origin.y = round(next.origin.y) - return next - } - - // MARK: - NSWindowDelegate - - func windowWillClose(_: Notification) { - self.onVisibilityChanged?(false) - } - - func windowDidMove(_: Notification) { - self.persistFrameIfPanel() - } - - func windowDidEndLiveResize(_: Notification) { - self.persistFrameIfPanel() - } - - func persistFrameIfPanel() { - guard case .panel = self.presentation, let window else { return } - Self.storeRestoredFrame(window.frame, sessionKey: self.sessionKey) - } -} diff --git a/apps/macos/Sources/OpenClaw/CanvasWindowController.swift b/apps/macos/Sources/OpenClaw/CanvasWindowController.swift deleted file mode 100644 index d30f54186ae..00000000000 --- a/apps/macos/Sources/OpenClaw/CanvasWindowController.swift +++ /dev/null @@ -1,373 +0,0 @@ -import AppKit -import Foundation -import OpenClawIPC -import OpenClawKit -import WebKit - -@MainActor -final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NSWindowDelegate { - let sessionKey: String - private let root: URL - private let sessionDir: URL - private let schemeHandler: CanvasSchemeHandler - let webView: WKWebView - private var a2uiActionMessageHandler: CanvasA2UIActionMessageHandler? - private let watcher: CanvasFileWatcher - private let container: HoverChromeContainerView - let presentation: CanvasPresentation - var preferredPlacement: CanvasPlacement? - private(set) var currentTarget: String? - private var debugStatusEnabled = false - private var debugStatusTitle: String? - private var debugStatusSubtitle: String? - - var onVisibilityChanged: ((Bool) -> Void)? - - init(sessionKey: String, root: URL, presentation: CanvasPresentation) throws { - self.sessionKey = sessionKey - self.root = root - self.presentation = presentation - - canvasWindowLogger.debug("CanvasWindowController init start session=\(sessionKey, privacy: .public)") - let safeSessionKey = CanvasWindowController.sanitizeSessionKey(sessionKey) - canvasWindowLogger.debug("CanvasWindowController init sanitized session=\(safeSessionKey, privacy: .public)") - self.sessionDir = root.appendingPathComponent(safeSessionKey, isDirectory: true) - try FileManager().createDirectory(at: self.sessionDir, withIntermediateDirectories: true) - canvasWindowLogger.debug("CanvasWindowController init session dir ready") - - self.schemeHandler = CanvasSchemeHandler(root: root) - canvasWindowLogger.debug("CanvasWindowController init scheme handler ready") - - let config = WKWebViewConfiguration() - config.userContentController = WKUserContentController() - config.preferences.isElementFullscreenEnabled = true - config.preferences.setValue(true, forKey: "developerExtrasEnabled") - canvasWindowLogger.debug("CanvasWindowController init config ready") - for scheme in CanvasScheme.allSchemes { - config.setURLSchemeHandler(self.schemeHandler, forURLScheme: scheme) - } - canvasWindowLogger.debug("CanvasWindowController init scheme handler installed") - - // Bridge A2UI "a2uiaction" DOM events back into the native agent loop. - // - // Prefer WKScriptMessageHandler when WebKit exposes it, otherwise fall back to an unattended deep link - // (includes the app-generated key so it won't prompt). - canvasWindowLogger.debug("CanvasWindowController init building A2UI bridge script") - let deepLinkKey = DeepLinkHandler.currentCanvasKey() - let injectedSessionKey = sessionKey.trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty ?? "main" - let bridgeScript = """ - (() => { - try { - const allowedSchemes = \(String(describing: CanvasScheme.allSchemes)); - const protocol = location.protocol.replace(':', ''); - if (!allowedSchemes.includes(protocol)) return; - if (globalThis.__openclawA2UIBridgeInstalled) return; - globalThis.__openclawA2UIBridgeInstalled = true; - - const deepLinkKey = \(Self.jsStringLiteral(deepLinkKey)); - const sessionKey = \(Self.jsStringLiteral(injectedSessionKey)); - const machineName = \(Self.jsStringLiteral(InstanceIdentity.displayName)); - const instanceId = \(Self.jsStringLiteral(InstanceIdentity.instanceId)); - - globalThis.addEventListener('a2uiaction', (evt) => { - try { - const payload = evt?.detail ?? evt?.payload ?? null; - if (!payload || payload.eventType !== 'a2ui.action') return; - - const action = payload.action ?? null; - const name = action?.name ?? ''; - if (!name) return; - - const context = Array.isArray(action?.context) ? action.context : []; - const userAction = { - id: (globalThis.crypto?.randomUUID?.() ?? String(Date.now())), - name, - surfaceId: payload.surfaceId ?? 'main', - sourceComponentId: payload.sourceComponentId ?? '', - dataContextPath: payload.dataContextPath ?? '', - timestamp: new Date().toISOString(), - ...(context.length ? { context } : {}), - }; - - const handler = globalThis.webkit?.messageHandlers?.openclawCanvasA2UIAction; - - // 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.openclawA2UI || - !!document.querySelector('openclaw-a2ui-host'); - if (hasBundledA2UIHost && handler?.postMessage) return; - - // Otherwise, forward directly when possible. - if (!hasBundledA2UIHost && handler?.postMessage) { - handler.postMessage({ userAction }); - return; - } - - const ctx = userAction.context ? (' ctx=' + JSON.stringify(userAction.context)) : ''; - const message = - 'CANVAS_A2UI action=' + userAction.name + - ' session=' + sessionKey + - ' surface=' + userAction.surfaceId + - ' component=' + (userAction.sourceComponentId || '-') + - ' host=' + machineName.replace(/\\s+/g, '_') + - ' instance=' + instanceId + - ctx + - ' default=update_canvas'; - const params = new URLSearchParams(); - params.set('message', message); - params.set('sessionKey', sessionKey); - params.set('thinking', 'low'); - params.set('deliver', 'false'); - params.set('channel', 'last'); - params.set('key', deepLinkKey); - location.href = 'openclaw://agent?' + params.toString(); - } catch {} - }, true); - } catch {} - })(); - """ - config.userContentController.addUserScript( - WKUserScript(source: bridgeScript, injectionTime: .atDocumentStart, forMainFrameOnly: true)) - canvasWindowLogger.debug("CanvasWindowController init A2UI bridge installed") - - canvasWindowLogger.debug("CanvasWindowController init creating WKWebView") - self.webView = WKWebView(frame: .zero, configuration: config) - // Canvas scaffold is a fully self-contained HTML page; avoid relying on transparency underlays. - self.webView.setValue(true, forKey: "drawsBackground") - - let sessionDir = self.sessionDir - let webView = self.webView - self.watcher = CanvasFileWatcher(url: sessionDir) { [weak webView] in - Task { @MainActor in - guard let webView else { return } - - // Only auto-reload when we are showing local canvas content. - guard let scheme = webView.url?.scheme, - CanvasScheme.allSchemes.contains(scheme) else { return } - - let path = webView.url?.path ?? "" - if path == "/" || path.isEmpty { - let indexA = sessionDir.appendingPathComponent("index.html", isDirectory: false) - let indexB = sessionDir.appendingPathComponent("index.htm", isDirectory: false) - if !FileManager().fileExists(atPath: indexA.path), - !FileManager().fileExists(atPath: indexB.path) - { - return - } - } - - webView.reload() - } - } - - self.container = HoverChromeContainerView(containing: self.webView) - let window = Self.makeWindow(for: presentation, contentView: self.container) - canvasWindowLogger.debug("CanvasWindowController init makeWindow done") - super.init(window: window) - - let handler = CanvasA2UIActionMessageHandler(sessionKey: sessionKey) - self.a2uiActionMessageHandler = handler - for name in CanvasA2UIActionMessageHandler.allMessageNames { - self.webView.configuration.userContentController.add(handler, name: name) - } - - self.webView.navigationDelegate = self - self.window?.delegate = self - self.container.onClose = { [weak self] in - self?.hideCanvas() - } - - self.watcher.start() - canvasWindowLogger.debug("CanvasWindowController init done") - } - - @available(*, unavailable) - required init?(coder: NSCoder) { - fatalError("init(coder:) is not supported") - } - - @MainActor deinit { - for name in CanvasA2UIActionMessageHandler.allMessageNames { - self.webView.configuration.userContentController.removeScriptMessageHandler(forName: name) - } - self.watcher.stop() - } - - func applyPreferredPlacement(_ placement: CanvasPlacement?) { - self.preferredPlacement = placement - } - - func showCanvas(path: String? = nil) { - if case let .panel(anchorProvider) = self.presentation { - self.presentAnchoredPanel(anchorProvider: anchorProvider) - if let path { - self.load(target: path) - } - return - } - - self.showWindow(nil) - self.window?.makeKeyAndOrderFront(nil) - NSApp.activate(ignoringOtherApps: true) - if let path { - self.load(target: path) - } - self.onVisibilityChanged?(true) - } - - func hideCanvas() { - if case .panel = self.presentation { - self.persistFrameIfPanel() - } - self.window?.orderOut(nil) - self.onVisibilityChanged?(false) - } - - func load(target: String) { - let trimmed = target.trimmingCharacters(in: .whitespacesAndNewlines) - self.currentTarget = trimmed - - if let url = URL(string: trimmed), let scheme = url.scheme?.lowercased() { - if scheme == "https" || scheme == "http" { - canvasWindowLogger.debug("canvas load url \(url.absoluteString, privacy: .public)") - self.webView.load(URLRequest(url: url)) - return - } - if scheme == "file" { - canvasWindowLogger.debug("canvas load file \(url.absoluteString, privacy: .public)") - self.loadFile(url) - return - } - } - - // Convenience: absolute file paths resolve as local files when they exist. - // (Avoid treating Canvas routes like "/" as filesystem paths.) - if trimmed.hasPrefix("/") { - var isDir: ObjCBool = false - if FileManager().fileExists(atPath: trimmed, isDirectory: &isDir), !isDir.boolValue { - let url = URL(fileURLWithPath: trimmed) - canvasWindowLogger.debug("canvas load file \(url.absoluteString, privacy: .public)") - self.loadFile(url) - return - } - } - - guard let url = CanvasScheme.makeURL( - session: CanvasWindowController.sanitizeSessionKey(self.sessionKey), - path: trimmed) - else { - canvasWindowLogger - .error( - "invalid canvas url session=\(self.sessionKey, privacy: .public) path=\(trimmed, privacy: .public)") - return - } - canvasWindowLogger.debug("canvas load canvas \(url.absoluteString, privacy: .public)") - self.webView.load(URLRequest(url: url)) - } - - func updateDebugStatus(enabled: Bool, title: String?, subtitle: String?) { - self.debugStatusEnabled = enabled - self.debugStatusTitle = title - self.debugStatusSubtitle = subtitle - self.applyDebugStatusIfNeeded() - } - - func applyDebugStatusIfNeeded() { - let enabled = self.debugStatusEnabled - let title = Self.jsOptionalStringLiteral(self.debugStatusTitle) - let subtitle = Self.jsOptionalStringLiteral(self.debugStatusSubtitle) - let js = """ - (() => { - try { - const api = globalThis.__openclaw; - if (!api) return; - if (typeof api.setDebugStatusEnabled === 'function') { - api.setDebugStatusEnabled(\(enabled ? "true" : "false")); - } - if (!\(enabled ? "true" : "false")) return; - if (typeof api.setStatus === 'function') { - api.setStatus(\(title), \(subtitle)); - } - } catch (_) {} - })(); - """ - self.webView.evaluateJavaScript(js) { _, _ in } - } - - private func loadFile(_ url: URL) { - let fileURL = url.isFileURL ? url : URL(fileURLWithPath: url.path) - let accessDir = fileURL.deletingLastPathComponent() - self.webView.loadFileURL(fileURL, allowingReadAccessTo: accessDir) - } - - func eval(javaScript: String) async throws -> String { - try await withCheckedThrowingContinuation { cont in - self.webView.evaluateJavaScript(javaScript) { result, error in - if let error { - cont.resume(throwing: error) - return - } - if let result { - cont.resume(returning: String(describing: result)) - } else { - cont.resume(returning: "") - } - } - } - } - - func snapshot(to outPath: String?) async throws -> String { - let image: NSImage = try await withCheckedThrowingContinuation { cont in - self.webView.takeSnapshot(with: nil) { image, error in - if let error { - cont.resume(throwing: error) - return - } - guard let image else { - cont.resume(throwing: NSError(domain: "Canvas", code: 11, userInfo: [ - NSLocalizedDescriptionKey: "snapshot returned nil image", - ])) - return - } - cont.resume(returning: image) - } - } - - guard let tiff = image.tiffRepresentation, - let rep = NSBitmapImageRep(data: tiff), - let png = rep.representation(using: .png, properties: [:]) - else { - throw NSError(domain: "Canvas", code: 12, userInfo: [ - NSLocalizedDescriptionKey: "failed to encode png", - ]) - } - - let path: String - if let outPath, !outPath.isEmpty { - path = outPath - } else { - let ts = Int(Date().timeIntervalSince1970) - path = "/tmp/openclaw-canvas-\(CanvasWindowController.sanitizeSessionKey(self.sessionKey))-\(ts).png" - } - - try png.write(to: URL(fileURLWithPath: path), options: [.atomic]) - return path - } - - var directoryPath: String { - self.sessionDir.path - } - - func shouldAutoNavigateToA2UI(lastAutoTarget: String?) -> Bool { - let trimmed = (self.currentTarget ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty || trimmed == "/" { return true } - if let lastAuto = lastAutoTarget?.trimmingCharacters(in: .whitespacesAndNewlines), - !lastAuto.isEmpty, - trimmed == lastAuto - { - return true - } - return false - } -} diff --git a/apps/macos/Sources/OpenClaw/ChannelConfigForm.swift b/apps/macos/Sources/OpenClaw/ChannelConfigForm.swift deleted file mode 100644 index d00725be768..00000000000 --- a/apps/macos/Sources/OpenClaw/ChannelConfigForm.swift +++ /dev/null @@ -1,363 +0,0 @@ -import SwiftUI - -struct ConfigSchemaForm: View { - @Bindable var store: ChannelsStore - let schema: ConfigSchemaNode - let path: ConfigPath - - var body: some View { - self.renderNode(self.schema, path: self.path) - } - - private func renderNode(_ schema: ConfigSchemaNode, path: ConfigPath) -> AnyView { - let storedValue = self.store.configValue(at: path) - let value = storedValue ?? schema.explicitDefault - let label = hintForPath(path, hints: store.configUiHints)?.label ?? schema.title - let help = hintForPath(path, hints: store.configUiHints)?.help ?? schema.description - let variants = schema.anyOf.isEmpty ? schema.oneOf : schema.anyOf - - if !variants.isEmpty { - let nonNull = variants.filter { !$0.isNullSchema } - if nonNull.count == 1, let only = nonNull.first { - return self.renderNode(only, path: path) - } - let literals = nonNull.compactMap(\.literalValue) - if !literals.isEmpty, literals.count == nonNull.count { - return AnyView( - VStack(alignment: .leading, spacing: 6) { - if let label { Text(label).font(.callout.weight(.semibold)) } - if let help { - Text(help) - .font(.caption) - .foregroundStyle(.secondary) - } - Picker( - "", - selection: self.enumBinding( - path, - options: literals, - defaultValue: schema.explicitDefault)) - { - Text("Select…").tag(-1) - ForEach(literals.indices, id: \ .self) { index in - Text(String(describing: literals[index])).tag(index) - } - } - .pickerStyle(.menu) - }) - } - } - - switch schema.schemaType { - case "object": - return AnyView( - VStack(alignment: .leading, spacing: 12) { - if let label { - Text(label) - .font(.callout.weight(.semibold)) - } - if let help { - Text(help) - .font(.caption) - .foregroundStyle(.secondary) - } - let properties = schema.properties - let sortedKeys = properties.keys.sorted { lhs, rhs in - let orderA = hintForPath(path + [.key(lhs)], hints: store.configUiHints)?.order ?? 0 - let orderB = hintForPath(path + [.key(rhs)], hints: store.configUiHints)?.order ?? 0 - if orderA != orderB { return orderA < orderB } - return lhs < rhs - } - ForEach(sortedKeys, id: \ .self) { key in - if let child = properties[key] { - self.renderNode(child, path: path + [.key(key)]) - } - } - if schema.allowsAdditionalProperties { - self.renderAdditionalProperties(schema, path: path, value: value) - } - }) - case "array": - return AnyView(self.renderArray(schema, path: path, value: value, label: label, help: help)) - case "boolean": - return AnyView( - Toggle(isOn: self.boolBinding(path, defaultValue: schema.explicitDefault as? Bool)) { - if let label { Text(label) } else { Text("Enabled") } - } - .help(help ?? "")) - case "number", "integer": - return AnyView(self.renderNumberField(schema, path: path, label: label, help: help)) - case "string": - return AnyView(self.renderStringField(schema, path: path, label: label, help: help)) - default: - return AnyView( - VStack(alignment: .leading, spacing: 6) { - if let label { Text(label).font(.callout.weight(.semibold)) } - Text("Unsupported field type.") - .font(.caption) - .foregroundStyle(.secondary) - }) - } - } - - @ViewBuilder - private func renderStringField( - _ schema: ConfigSchemaNode, - path: ConfigPath, - label: String?, - help: String?) -> some View - { - let hint = hintForPath(path, hints: store.configUiHints) - let placeholder = hint?.placeholder ?? "" - let sensitive = hint?.sensitive ?? isSensitivePath(path) - let defaultValue = schema.explicitDefault as? String - VStack(alignment: .leading, spacing: 6) { - if let label { Text(label).font(.callout.weight(.semibold)) } - if let help { - Text(help) - .font(.caption) - .foregroundStyle(.secondary) - } - if let options = schema.enumValues { - Picker("", selection: self.enumBinding(path, options: options, defaultValue: schema.explicitDefault)) { - Text("Select…").tag(-1) - ForEach(options.indices, id: \ .self) { index in - Text(String(describing: options[index])).tag(index) - } - } - .pickerStyle(.menu) - } else if sensitive { - SecureField(placeholder, text: self.stringBinding(path, defaultValue: defaultValue)) - .textFieldStyle(.roundedBorder) - } else { - TextField(placeholder, text: self.stringBinding(path, defaultValue: defaultValue)) - .textFieldStyle(.roundedBorder) - } - } - } - - @ViewBuilder - private func renderNumberField( - _ schema: ConfigSchemaNode, - path: ConfigPath, - label: String?, - help: String?) -> some View - { - let defaultValue = (schema.explicitDefault as? Double) - ?? (schema.explicitDefault as? Int).map(Double.init) - VStack(alignment: .leading, spacing: 6) { - if let label { Text(label).font(.callout.weight(.semibold)) } - if let help { - Text(help) - .font(.caption) - .foregroundStyle(.secondary) - } - TextField( - "", - text: self.numberBinding( - path, - isInteger: schema.schemaType == "integer", - defaultValue: defaultValue)) - .textFieldStyle(.roundedBorder) - } - } - - @ViewBuilder - private func renderArray( - _ schema: ConfigSchemaNode, - path: ConfigPath, - value: Any?, - label: String?, - help: String?) -> some View - { - let items = value as? [Any] ?? [] - let itemSchema = schema.items - VStack(alignment: .leading, spacing: 10) { - if let label { Text(label).font(.callout.weight(.semibold)) } - if let help { - Text(help) - .font(.caption) - .foregroundStyle(.secondary) - } - ForEach(items.indices, id: \ .self) { index in - HStack(alignment: .top, spacing: 8) { - if let itemSchema { - self.renderNode(itemSchema, path: path + [.index(index)]) - } else { - Text(String(describing: items[index])) - } - Button("Remove") { - var next = items - next.remove(at: index) - self.store.updateConfigValue(path: path, value: next) - } - .buttonStyle(.bordered) - .controlSize(.small) - } - } - Button("Add") { - var next = items - if let itemSchema { - next.append(itemSchema.defaultValue) - } else { - next.append("") - } - self.store.updateConfigValue(path: path, value: next) - } - .buttonStyle(.bordered) - .controlSize(.small) - } - } - - @ViewBuilder - private func renderAdditionalProperties( - _ schema: ConfigSchemaNode, - path: ConfigPath, - value: Any?) -> some View - { - if let additionalSchema = schema.additionalProperties { - let dict = value as? [String: Any] ?? [:] - let reserved = Set(schema.properties.keys) - let extras = dict.keys.filter { !reserved.contains($0) }.sorted() - - VStack(alignment: .leading, spacing: 8) { - Text("Extra entries") - .font(.callout.weight(.semibold)) - if extras.isEmpty { - Text("No extra entries yet.") - .font(.caption) - .foregroundStyle(.secondary) - } else { - ForEach(extras, id: \ .self) { key in - let itemPath: ConfigPath = path + [.key(key)] - HStack(alignment: .top, spacing: 8) { - TextField("Key", text: self.mapKeyBinding(path: path, key: key)) - .textFieldStyle(.roundedBorder) - .frame(width: 160) - self.renderNode(additionalSchema, path: itemPath) - Button("Remove") { - var next = dict - next.removeValue(forKey: key) - self.store.updateConfigValue(path: path, value: next) - } - .buttonStyle(.bordered) - .controlSize(.small) - } - } - } - Button("Add") { - var next = dict - var index = 1 - var key = "new-\(index)" - while next[key] != nil { - index += 1 - key = "new-\(index)" - } - next[key] = additionalSchema.defaultValue - self.store.updateConfigValue(path: path, value: next) - } - .buttonStyle(.bordered) - .controlSize(.small) - } - } - } - - private func stringBinding(_ path: ConfigPath, defaultValue: String?) -> Binding { - Binding( - get: { - if let value = store.configValue(at: path) as? String { return value } - return defaultValue ?? "" - }, - set: { newValue in - let trimmed = newValue.trimmingCharacters(in: .whitespacesAndNewlines) - self.store.updateConfigValue(path: path, value: trimmed.isEmpty ? nil : trimmed) - }) - } - - private func boolBinding(_ path: ConfigPath, defaultValue: Bool?) -> Binding { - Binding( - get: { - if let value = store.configValue(at: path) as? Bool { return value } - return defaultValue ?? false - }, - set: { newValue in - self.store.updateConfigValue(path: path, value: newValue) - }) - } - - private func numberBinding( - _ path: ConfigPath, - isInteger: Bool, - defaultValue: Double?) -> Binding - { - Binding( - get: { - if let value = store.configValue(at: path) { return String(describing: value) } - guard let defaultValue else { return "" } - return isInteger ? String(Int(defaultValue)) : String(defaultValue) - }, - set: { newValue in - let trimmed = newValue.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty { - self.store.updateConfigValue(path: path, value: nil) - } else if let value = Double(trimmed) { - self.store.updateConfigValue(path: path, value: isInteger ? Int(value) : value) - } - }) - } - - private func enumBinding( - _ path: ConfigPath, - options: [Any], - defaultValue: Any?) -> Binding - { - Binding( - get: { - let value = self.store.configValue(at: path) ?? defaultValue - guard let value else { return -1 } - return options.firstIndex { option in - String(describing: option) == String(describing: value) - } ?? -1 - }, - set: { index in - guard index >= 0, index < options.count else { - self.store.updateConfigValue(path: path, value: nil) - return - } - self.store.updateConfigValue(path: path, value: options[index]) - }) - } - - private func mapKeyBinding(path: ConfigPath, key: String) -> Binding { - Binding( - get: { key }, - set: { newValue in - let trimmed = newValue.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return } - guard trimmed != key else { return } - let current = self.store.configValue(at: path) as? [String: Any] ?? [:] - guard current[trimmed] == nil else { return } - var next = current - next[trimmed] = current[key] - next.removeValue(forKey: key) - self.store.updateConfigValue(path: path, value: next) - }) - } -} - -struct ChannelConfigForm: View { - @Bindable var store: ChannelsStore - let channelId: String - - var body: some View { - if self.store.configSchemaLoading { - ProgressView().controlSize(.small) - } else if let schema = store.channelConfigSchema(for: channelId) { - ConfigSchemaForm(store: self.store, schema: schema, path: [.key("channels"), .key(self.channelId)]) - } else { - Text("Schema unavailable for this channel.") - .font(.caption) - .foregroundStyle(.secondary) - } - } -} diff --git a/apps/macos/Sources/OpenClaw/ChannelsSettings+ChannelSections.swift b/apps/macos/Sources/OpenClaw/ChannelsSettings+ChannelSections.swift deleted file mode 100644 index 2bef47f2dea..00000000000 --- a/apps/macos/Sources/OpenClaw/ChannelsSettings+ChannelSections.swift +++ /dev/null @@ -1,137 +0,0 @@ -import SwiftUI - -extension ChannelsSettings { - func formSection(_ title: String, @ViewBuilder content: () -> some View) -> some View { - GroupBox(title) { - VStack(alignment: .leading, spacing: 10) { - content() - } - .frame(maxWidth: .infinity, alignment: .leading) - } - } - - func channelHeaderActions(_ channel: ChannelItem) -> some View { - HStack(spacing: 8) { - if channel.id == "whatsapp" { - Button("Logout") { - Task { await self.store.logoutWhatsApp() } - } - .buttonStyle(.bordered) - .disabled(self.store.whatsappBusy) - } - - if channel.id == "telegram" { - Button("Logout") { - Task { await self.store.logoutTelegram() } - } - .buttonStyle(.bordered) - .disabled(self.store.telegramBusy) - } - - Button { - Task { await self.store.refresh(probe: true) } - } label: { - if self.store.isRefreshing { - ProgressView().controlSize(.small) - } else { - Text("Refresh") - } - } - .buttonStyle(.bordered) - .disabled(self.store.isRefreshing) - } - .controlSize(.small) - } - - var whatsAppSection: some View { - VStack(alignment: .leading, spacing: 16) { - self.formSection("Linking") { - if let message = self.store.whatsappLoginMessage { - Text(message) - .font(.caption) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - - if let qr = self.store.whatsappLoginQrDataUrl, let image = self.qrImage(from: qr) { - Image(nsImage: image) - .resizable() - .interpolation(.none) - .frame(width: 180, height: 180) - .cornerRadius(8) - } - - HStack(spacing: 12) { - Button { - Task { await self.store.startWhatsAppLogin(force: false) } - } label: { - if self.store.whatsappBusy { - ProgressView().controlSize(.small) - } else { - Text("Show QR") - } - } - .buttonStyle(.borderedProminent) - .disabled(self.store.whatsappBusy) - - Button("Relink") { - Task { await self.store.startWhatsAppLogin(force: true) } - } - .buttonStyle(.bordered) - .disabled(self.store.whatsappBusy) - } - .font(.caption) - } - - self.configEditorSection(channelId: "whatsapp") - } - } - - func genericChannelSection(_ channel: ChannelItem) -> some View { - VStack(alignment: .leading, spacing: 16) { - self.configEditorSection(channelId: channel.id) - } - } - - @ViewBuilder - private func configEditorSection(channelId: String) -> some View { - self.formSection("Configuration") { - ChannelConfigForm(store: self.store, channelId: channelId) - } - - self.configStatusMessage - - HStack(spacing: 12) { - Button { - Task { await self.store.saveConfigDraft() } - } label: { - if self.store.isSavingConfig { - ProgressView().controlSize(.small) - } else { - Text("Save") - } - } - .buttonStyle(.borderedProminent) - .disabled(self.store.isSavingConfig || !self.store.configDirty) - - Button("Reload") { - Task { await self.store.reloadConfigDraft() } - } - .buttonStyle(.bordered) - .disabled(self.store.isSavingConfig) - - Spacer() - } - .font(.caption) - } - - @ViewBuilder - var configStatusMessage: some View { - if let status = self.store.configStatus { - Text(status) - .font(.caption) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - } -} diff --git a/apps/macos/Sources/OpenClaw/ChannelsSettings+ChannelState.swift b/apps/macos/Sources/OpenClaw/ChannelsSettings+ChannelState.swift deleted file mode 100644 index 5be5818425b..00000000000 --- a/apps/macos/Sources/OpenClaw/ChannelsSettings+ChannelState.swift +++ /dev/null @@ -1,508 +0,0 @@ -import OpenClawProtocol -import SwiftUI - -extension ChannelsSettings { - private func channelStatus( - _ id: String, - as type: T.Type) -> T? - { - self.store.snapshot?.decodeChannel(id, as: type) - } - - var whatsAppTint: Color { - guard let status = self.channelStatus("whatsapp", as: ChannelsStatusSnapshot.WhatsAppStatus.self) - else { return .secondary } - if !status.configured { return .secondary } - if !status.linked { return .red } - if status.lastError != nil { return .orange } - if status.connected { return .green } - if status.running { return .orange } - return .orange - } - - var telegramTint: Color { - guard let status = self.channelStatus("telegram", as: ChannelsStatusSnapshot.TelegramStatus.self) - else { return .secondary } - if !status.configured { return .secondary } - if status.lastError != nil { return .orange } - if status.probe?.ok == false { return .orange } - if status.running { return .green } - return .orange - } - - var discordTint: Color { - guard let status = self.channelStatus("discord", as: ChannelsStatusSnapshot.DiscordStatus.self) - else { return .secondary } - if !status.configured { return .secondary } - if status.lastError != nil { return .orange } - if status.probe?.ok == false { return .orange } - if status.running { return .green } - return .orange - } - - var googlechatTint: Color { - guard let status = self.channelStatus("googlechat", as: ChannelsStatusSnapshot.GoogleChatStatus.self) - else { return .secondary } - if !status.configured { return .secondary } - if status.lastError != nil { return .orange } - if status.probe?.ok == false { return .orange } - if status.running { return .green } - return .orange - } - - var signalTint: Color { - guard let status = self.channelStatus("signal", as: ChannelsStatusSnapshot.SignalStatus.self) - else { return .secondary } - if !status.configured { return .secondary } - if status.lastError != nil { return .orange } - if status.probe?.ok == false { return .orange } - if status.running { return .green } - return .orange - } - - var imessageTint: Color { - guard let status = self.channelStatus("imessage", as: ChannelsStatusSnapshot.IMessageStatus.self) - else { return .secondary } - if !status.configured { return .secondary } - if status.lastError != nil { return .orange } - if status.probe?.ok == false { return .orange } - if status.running { return .green } - return .orange - } - - var whatsAppSummary: String { - guard let status = self.channelStatus("whatsapp", as: ChannelsStatusSnapshot.WhatsAppStatus.self) - else { return "Checking…" } - if !status.linked { return "Not linked" } - if status.connected { return "Connected" } - if status.running { return "Running" } - return "Linked" - } - - var telegramSummary: String { - guard let status = self.channelStatus("telegram", as: ChannelsStatusSnapshot.TelegramStatus.self) - else { return "Checking…" } - if !status.configured { return "Not configured" } - if status.running { return "Running" } - return "Configured" - } - - var discordSummary: String { - guard let status = self.channelStatus("discord", as: ChannelsStatusSnapshot.DiscordStatus.self) - else { return "Checking…" } - if !status.configured { return "Not configured" } - if status.running { return "Running" } - return "Configured" - } - - var googlechatSummary: String { - guard let status = self.channelStatus("googlechat", as: ChannelsStatusSnapshot.GoogleChatStatus.self) - else { return "Checking…" } - if !status.configured { return "Not configured" } - if status.running { return "Running" } - return "Configured" - } - - var signalSummary: String { - guard let status = self.channelStatus("signal", as: ChannelsStatusSnapshot.SignalStatus.self) - else { return "Checking…" } - if !status.configured { return "Not configured" } - if status.running { return "Running" } - return "Configured" - } - - var imessageSummary: String { - guard let status = self.channelStatus("imessage", as: ChannelsStatusSnapshot.IMessageStatus.self) - else { return "Checking…" } - if !status.configured { return "Not configured" } - if status.running { return "Running" } - return "Configured" - } - - var whatsAppDetails: String? { - guard let status = self.channelStatus("whatsapp", as: ChannelsStatusSnapshot.WhatsAppStatus.self) - else { return nil } - var lines: [String] = [] - if let e164 = status.`self`?.e164 ?? status.`self`?.jid { - lines.append("Linked as \(e164)") - } - if let age = status.authAgeMs { - lines.append("Auth age \(msToAge(age))") - } - if let last = self.date(fromMs: status.lastConnectedAt) { - lines.append("Last connect \(relativeAge(from: last))") - } - if let disconnect = status.lastDisconnect { - let when = self.date(fromMs: disconnect.at).map { relativeAge(from: $0) } ?? "unknown" - let code = disconnect.status.map { "status \($0)" } ?? "status unknown" - let err = disconnect.error ?? "disconnect" - lines.append("Last disconnect \(code) · \(err) · \(when)") - } - if status.reconnectAttempts > 0 { - lines.append("Reconnect attempts \(status.reconnectAttempts)") - } - if let msgAt = self.date(fromMs: status.lastMessageAt) { - lines.append("Last message \(relativeAge(from: msgAt))") - } - if let err = status.lastError, !err.isEmpty { - lines.append("Error: \(err)") - } - return lines.isEmpty ? nil : lines.joined(separator: " · ") - } - - var telegramDetails: String? { - guard let status = self.channelStatus("telegram", as: ChannelsStatusSnapshot.TelegramStatus.self) - else { return nil } - var lines: [String] = [] - if let source = status.tokenSource { - lines.append("Token source: \(source)") - } - if let mode = status.mode { - lines.append("Mode: \(mode)") - } - if let probe = status.probe { - if probe.ok { - if let name = probe.bot?.username { - lines.append("Bot: @\(name)") - } - if let url = probe.webhook?.url, !url.isEmpty { - lines.append("Webhook: \(url)") - } - } else { - let code = probe.status.map { String($0) } ?? "unknown" - lines.append("Probe failed (\(code))") - } - } - if let last = self.date(fromMs: status.lastProbeAt) { - lines.append("Last probe \(relativeAge(from: last))") - } - if let err = status.lastError, !err.isEmpty { - lines.append("Error: \(err)") - } - return lines.isEmpty ? nil : lines.joined(separator: " · ") - } - - var discordDetails: String? { - guard let status = self.channelStatus("discord", as: ChannelsStatusSnapshot.DiscordStatus.self) - else { return nil } - var lines: [String] = [] - if let source = status.tokenSource { - lines.append("Token source: \(source)") - } - if let probe = status.probe { - if probe.ok { - if let name = probe.bot?.username { - lines.append("Bot: @\(name)") - } - if let elapsed = probe.elapsedMs { - lines.append("Probe \(Int(elapsed))ms") - } - } else { - let code = probe.status.map { String($0) } ?? "unknown" - lines.append("Probe failed (\(code))") - } - } - if let last = self.date(fromMs: status.lastProbeAt) { - lines.append("Last probe \(relativeAge(from: last))") - } - if let err = status.lastError, !err.isEmpty { - lines.append("Error: \(err)") - } - return lines.isEmpty ? nil : lines.joined(separator: " · ") - } - - var googlechatDetails: String? { - guard let status = self.channelStatus("googlechat", as: ChannelsStatusSnapshot.GoogleChatStatus.self) - else { return nil } - var lines: [String] = [] - if let source = status.credentialSource { - lines.append("Credential: \(source)") - } - if let audienceType = status.audienceType { - let audience = status.audience ?? "" - let label = audience.isEmpty ? audienceType : "\(audienceType) \(audience)" - lines.append("Audience: \(label)") - } - if let probe = status.probe { - if probe.ok { - if let elapsed = probe.elapsedMs { - lines.append("Probe \(Int(elapsed))ms") - } - } else { - let code = probe.status.map { String($0) } ?? "unknown" - lines.append("Probe failed (\(code))") - } - } - if let last = self.date(fromMs: status.lastProbeAt) { - lines.append("Last probe \(relativeAge(from: last))") - } - if let err = status.lastError, !err.isEmpty { - lines.append("Error: \(err)") - } - return lines.isEmpty ? nil : lines.joined(separator: " · ") - } - - var signalDetails: String? { - guard let status = self.channelStatus("signal", as: ChannelsStatusSnapshot.SignalStatus.self) - else { return nil } - var lines: [String] = [] - lines.append("Base URL: \(status.baseUrl)") - if let probe = status.probe { - if probe.ok { - if let version = probe.version, !version.isEmpty { - lines.append("Version \(version)") - } - if let elapsed = probe.elapsedMs { - lines.append("Probe \(Int(elapsed))ms") - } - } else { - let code = probe.status.map { String($0) } ?? "unknown" - lines.append("Probe failed (\(code))") - } - } - if let last = self.date(fromMs: status.lastProbeAt) { - lines.append("Last probe \(relativeAge(from: last))") - } - if let err = status.lastError, !err.isEmpty { - lines.append("Error: \(err)") - } - return lines.isEmpty ? nil : lines.joined(separator: " · ") - } - - var imessageDetails: String? { - guard let status = self.channelStatus("imessage", as: ChannelsStatusSnapshot.IMessageStatus.self) - else { return nil } - var lines: [String] = [] - if let cliPath = status.cliPath, !cliPath.isEmpty { - lines.append("CLI: \(cliPath)") - } - if let dbPath = status.dbPath, !dbPath.isEmpty { - lines.append("DB: \(dbPath)") - } - if let probe = status.probe, !probe.ok { - let err = probe.error ?? "probe failed" - lines.append("Probe error: \(err)") - } - if let last = self.date(fromMs: status.lastProbeAt) { - lines.append("Last probe \(relativeAge(from: last))") - } - if let err = status.lastError, !err.isEmpty { - lines.append("Error: \(err)") - } - return lines.isEmpty ? nil : lines.joined(separator: " · ") - } - - var orderedChannels: [ChannelItem] { - let fallback = ["whatsapp", "telegram", "discord", "googlechat", "slack", "signal", "imessage"] - let order = self.store.snapshot?.channelOrder ?? fallback - let channels = order.enumerated().map { index, id in - ChannelItem( - id: id, - title: self.resolveChannelTitle(id), - detailTitle: self.resolveChannelDetailTitle(id), - systemImage: self.resolveChannelSystemImage(id), - sortOrder: index) - } - return channels.sorted { lhs, rhs in - let lhsEnabled = self.channelEnabled(lhs) - let rhsEnabled = self.channelEnabled(rhs) - if lhsEnabled != rhsEnabled { return lhsEnabled && !rhsEnabled } - return lhs.sortOrder < rhs.sortOrder - } - } - - var enabledChannels: [ChannelItem] { - self.orderedChannels.filter { self.channelEnabled($0) } - } - - var availableChannels: [ChannelItem] { - self.orderedChannels.filter { !self.channelEnabled($0) } - } - - func ensureSelection() { - guard let selected = self.selectedChannel else { - self.selectedChannel = self.orderedChannels.first - return - } - if !self.orderedChannels.contains(selected) { - self.selectedChannel = self.orderedChannels.first - } - } - - func channelEnabled(_ channel: ChannelItem) -> Bool { - let status = self.channelStatusDictionary(channel.id) - let configured = status?["configured"]?.boolValue ?? false - let running = status?["running"]?.boolValue ?? false - let connected = status?["connected"]?.boolValue ?? false - let accountActive = self.store.snapshot?.channelAccounts[channel.id]?.contains( - where: { $0.configured == true || $0.running == true || $0.connected == true }) ?? false - return configured || running || connected || accountActive - } - - @ViewBuilder - func channelSection(_ channel: ChannelItem) -> some View { - if channel.id == "whatsapp" { - self.whatsAppSection - } else { - self.genericChannelSection(channel) - } - } - - func channelTint(_ channel: ChannelItem) -> Color { - switch channel.id { - case "whatsapp": - return self.whatsAppTint - case "telegram": - return self.telegramTint - case "discord": - return self.discordTint - case "googlechat": - return self.googlechatTint - case "signal": - return self.signalTint - case "imessage": - return self.imessageTint - default: - if self.channelHasError(channel) { return .orange } - if self.channelEnabled(channel) { return .green } - return .secondary - } - } - - func channelSummary(_ channel: ChannelItem) -> String { - switch channel.id { - case "whatsapp": - return self.whatsAppSummary - case "telegram": - return self.telegramSummary - case "discord": - return self.discordSummary - case "googlechat": - return self.googlechatSummary - case "signal": - return self.signalSummary - case "imessage": - return self.imessageSummary - default: - if self.channelHasError(channel) { return "Error" } - if self.channelEnabled(channel) { return "Active" } - return "Not configured" - } - } - - func channelDetails(_ channel: ChannelItem) -> String? { - switch channel.id { - case "whatsapp": - return self.whatsAppDetails - case "telegram": - return self.telegramDetails - case "discord": - return self.discordDetails - case "googlechat": - return self.googlechatDetails - case "signal": - return self.signalDetails - case "imessage": - return self.imessageDetails - default: - let status = self.channelStatusDictionary(channel.id) - if let err = status?["lastError"]?.stringValue, !err.isEmpty { - return "Error: \(err)" - } - return nil - } - } - - func channelLastCheckText(_ channel: ChannelItem) -> String { - guard let date = self.channelLastCheck(channel) else { return "never" } - return relativeAge(from: date) - } - - func channelLastCheck(_ channel: ChannelItem) -> Date? { - switch channel.id { - case "whatsapp": - guard let status = self.channelStatus("whatsapp", as: ChannelsStatusSnapshot.WhatsAppStatus.self) - else { return nil } - return self.date(fromMs: status.lastEventAt ?? status.lastMessageAt ?? status.lastConnectedAt) - case "telegram": - return self - .date(fromMs: self.channelStatus("telegram", as: ChannelsStatusSnapshot.TelegramStatus.self)? - .lastProbeAt) - case "discord": - return self - .date(fromMs: self.channelStatus("discord", as: ChannelsStatusSnapshot.DiscordStatus.self)? - .lastProbeAt) - case "googlechat": - return self - .date(fromMs: self.channelStatus("googlechat", as: ChannelsStatusSnapshot.GoogleChatStatus.self)? - .lastProbeAt) - case "signal": - return self - .date(fromMs: self.channelStatus("signal", as: ChannelsStatusSnapshot.SignalStatus.self)?.lastProbeAt) - case "imessage": - return self - .date(fromMs: self.channelStatus("imessage", as: ChannelsStatusSnapshot.IMessageStatus.self)? - .lastProbeAt) - default: - let status = self.channelStatusDictionary(channel.id) - if let probeAt = status?["lastProbeAt"]?.doubleValue { - return self.date(fromMs: probeAt) - } - if let accounts = self.store.snapshot?.channelAccounts[channel.id] { - let last = accounts.compactMap { $0.lastInboundAt ?? $0.lastOutboundAt }.max() - return self.date(fromMs: last) - } - return nil - } - } - - func channelHasError(_ channel: ChannelItem) -> Bool { - switch channel.id { - case "whatsapp": - guard let status = self.channelStatus("whatsapp", as: ChannelsStatusSnapshot.WhatsAppStatus.self) - else { return false } - return status.lastError?.isEmpty == false || status.lastDisconnect?.loggedOut == true - case "telegram": - guard let status = self.channelStatus("telegram", as: ChannelsStatusSnapshot.TelegramStatus.self) - else { return false } - return status.lastError?.isEmpty == false || status.probe?.ok == false - case "discord": - guard let status = self.channelStatus("discord", as: ChannelsStatusSnapshot.DiscordStatus.self) - else { return false } - return status.lastError?.isEmpty == false || status.probe?.ok == false - case "googlechat": - guard let status = self.channelStatus("googlechat", as: ChannelsStatusSnapshot.GoogleChatStatus.self) - else { return false } - return status.lastError?.isEmpty == false || status.probe?.ok == false - case "signal": - guard let status = self.channelStatus("signal", as: ChannelsStatusSnapshot.SignalStatus.self) - else { return false } - return status.lastError?.isEmpty == false || status.probe?.ok == false - case "imessage": - guard let status = self.channelStatus("imessage", as: ChannelsStatusSnapshot.IMessageStatus.self) - else { return false } - return status.lastError?.isEmpty == false || status.probe?.ok == false - default: - let status = self.channelStatusDictionary(channel.id) - return status?["lastError"]?.stringValue?.isEmpty == false - } - } - - private func resolveChannelTitle(_ id: String) -> String { - let label = self.store.resolveChannelLabel(id) - if label != id { return label } - return id.prefix(1).uppercased() + id.dropFirst() - } - - private func resolveChannelDetailTitle(_ id: String) -> String { - self.store.resolveChannelDetailLabel(id) - } - - private func resolveChannelSystemImage(_ id: String) -> String { - self.store.resolveChannelSystemImage(id) - } - - private func channelStatusDictionary(_ id: String) -> [String: AnyCodable]? { - self.store.snapshot?.channels[id]?.dictionaryValue - } -} diff --git a/apps/macos/Sources/OpenClaw/ChannelsSettings+Helpers.swift b/apps/macos/Sources/OpenClaw/ChannelsSettings+Helpers.swift deleted file mode 100644 index 05b79ca0492..00000000000 --- a/apps/macos/Sources/OpenClaw/ChannelsSettings+Helpers.swift +++ /dev/null @@ -1,17 +0,0 @@ -import AppKit - -extension ChannelsSettings { - func date(fromMs ms: Double?) -> Date? { - guard let ms else { return nil } - return Date(timeIntervalSince1970: ms / 1000) - } - - func qrImage(from dataUrl: String) -> NSImage? { - guard let comma = dataUrl.firstIndex(of: ",") else { return nil } - let header = dataUrl[.. some View { - ScrollView(.vertical) { - VStack(alignment: .leading, spacing: 16) { - self.detailHeader(for: channel) - Divider() - self.channelSection(channel) - Spacer(minLength: 0) - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal, 24) - .padding(.vertical, 18) - } - } - - private func sidebarRow(_ channel: ChannelItem) -> some View { - let isSelected = self.selectedChannel == channel - return Button { - self.selectedChannel = channel - } label: { - HStack(spacing: 8) { - Circle() - .fill(self.channelTint(channel)) - .frame(width: 8, height: 8) - VStack(alignment: .leading, spacing: 2) { - Text(channel.title) - Text(self.channelSummary(channel)) - .font(.caption) - .foregroundStyle(.secondary) - } - } - .padding(.vertical, 4) - .padding(.horizontal, 6) - .frame(maxWidth: .infinity, alignment: .leading) - .background(isSelected ? Color.accentColor.opacity(0.18) : Color.clear) - .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous)) - .background(Color.clear) // ensure full-width hit test area - .contentShape(Rectangle()) - } - .frame(maxWidth: .infinity, alignment: .leading) - .buttonStyle(.plain) - .contentShape(Rectangle()) - } - - private func sidebarSectionHeader(_ title: String) -> some View { - Text(title) - .font(.caption.weight(.semibold)) - .foregroundStyle(.secondary) - .textCase(.uppercase) - .padding(.horizontal, 4) - .padding(.top, 2) - } - - private func detailHeader(for channel: ChannelItem) -> some View { - VStack(alignment: .leading, spacing: 8) { - HStack(alignment: .firstTextBaseline, spacing: 10) { - Label(channel.detailTitle, systemImage: channel.systemImage) - .font(.title3.weight(.semibold)) - self.statusBadge( - self.channelSummary(channel), - color: self.channelTint(channel)) - Spacer() - self.channelHeaderActions(channel) - } - - HStack(spacing: 10) { - Text("Last check \(self.channelLastCheckText(channel))") - .font(.caption) - .foregroundStyle(.secondary) - if self.channelHasError(channel) { - Text("Error") - .font(.caption2.weight(.semibold)) - .padding(.horizontal, 6) - .padding(.vertical, 2) - .background(Color.red.opacity(0.15)) - .foregroundStyle(.red) - .clipShape(Capsule()) - } - } - - if let details = self.channelDetails(channel) { - Text(details) - .font(.caption) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - } - } - - private func statusBadge(_ text: String, color: Color) -> some View { - Text(text) - .font(.caption2.weight(.semibold)) - .padding(.horizontal, 8) - .padding(.vertical, 3) - .background(color.opacity(0.16)) - .foregroundStyle(color) - .clipShape(Capsule()) - } -} diff --git a/apps/macos/Sources/OpenClaw/ChannelsSettings.swift b/apps/macos/Sources/OpenClaw/ChannelsSettings.swift deleted file mode 100644 index b1177f0033b..00000000000 --- a/apps/macos/Sources/OpenClaw/ChannelsSettings.swift +++ /dev/null @@ -1,19 +0,0 @@ -import AppKit -import SwiftUI - -struct ChannelsSettings: View { - struct ChannelItem: Identifiable, Hashable { - let id: String - let title: String - let detailTitle: String - let systemImage: String - let sortOrder: Int - } - - @Bindable var store: ChannelsStore - @State var selectedChannel: ChannelItem? - - init(store: ChannelsStore = .shared) { - self.store = store - } -} diff --git a/apps/macos/Sources/OpenClaw/ChannelsStore+Config.swift b/apps/macos/Sources/OpenClaw/ChannelsStore+Config.swift deleted file mode 100644 index 703c7efed63..00000000000 --- a/apps/macos/Sources/OpenClaw/ChannelsStore+Config.swift +++ /dev/null @@ -1,154 +0,0 @@ -import Foundation -import OpenClawProtocol - -extension ChannelsStore { - func loadConfigSchema() async { - guard !self.configSchemaLoading else { return } - self.configSchemaLoading = true - defer { self.configSchemaLoading = false } - - do { - let res: ConfigSchemaResponse = try await GatewayConnection.shared.requestDecoded( - method: .configSchema, - params: nil, - timeoutMs: 8000) - let schemaValue = res.schema.foundationValue - self.configSchema = ConfigSchemaNode(raw: schemaValue) - let hintValues = res.uihints.mapValues { $0.foundationValue } - self.configUiHints = decodeUiHints(hintValues) - } catch { - self.configStatus = error.localizedDescription - } - } - - func loadConfig() async { - do { - let snap: ConfigSnapshot = try await GatewayConnection.shared.requestDecoded( - method: .configGet, - params: nil, - timeoutMs: 10000) - self.configStatus = snap.valid == false - ? "Config invalid; fix it in ~/.openclaw/openclaw.json." - : nil - self.configRoot = snap.config?.mapValues { $0.foundationValue } ?? [:] - self.configDraft = cloneConfigValue(self.configRoot) as? [String: Any] ?? self.configRoot - self.configDirty = false - self.configLoaded = true - - self.applyUIConfig(snap) - } catch { - self.configStatus = error.localizedDescription - } - } - - private func applyUIConfig(_ snap: ConfigSnapshot) { - let ui = snap.config?["ui"]?.dictionaryValue - let rawSeam = ui?["seamColor"]?.stringValue?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - AppStateStore.shared.seamColorHex = rawSeam.isEmpty ? nil : rawSeam - } - - func channelConfigSchema(for channelId: String) -> ConfigSchemaNode? { - guard let root = self.configSchema else { return nil } - return root.node(at: [.key("channels"), .key(channelId)]) - } - - func configValue(at path: ConfigPath) -> Any? { - if let value = valueAtPath(self.configDraft, path: path) { - return value - } - guard path.count >= 2 else { return nil } - if case .key("channels") = path[0], case .key = path[1] { - let fallbackPath = Array(path.dropFirst()) - return valueAtPath(self.configDraft, path: fallbackPath) - } - return nil - } - - func updateConfigValue(path: ConfigPath, value: Any?) { - var root: Any = self.configDraft - setValue(&root, path: path, value: value) - self.configDraft = root as? [String: Any] ?? self.configDraft - self.configDirty = true - } - - func saveConfigDraft() async { - guard !self.isSavingConfig else { return } - self.isSavingConfig = true - defer { self.isSavingConfig = false } - - do { - try await ConfigStore.save(self.configDraft) - await self.loadConfig() - } catch { - self.configStatus = error.localizedDescription - } - } - - func reloadConfigDraft() async { - await self.loadConfig() - } -} - -private func valueAtPath(_ root: Any, path: ConfigPath) -> Any? { - var current: Any? = root - for segment in path { - switch segment { - case let .key(key): - guard let dict = current as? [String: Any] else { return nil } - current = dict[key] - case let .index(index): - guard let array = current as? [Any], array.indices.contains(index) else { return nil } - current = array[index] - } - } - return current -} - -private func setValue(_ root: inout Any, path: ConfigPath, value: Any?) { - guard let segment = path.first else { return } - switch segment { - case let .key(key): - var dict = root as? [String: Any] ?? [:] - if path.count == 1 { - if let value { - dict[key] = value - } else { - dict.removeValue(forKey: key) - } - root = dict - return - } - var child = dict[key] ?? [:] - setValue(&child, path: Array(path.dropFirst()), value: value) - dict[key] = child - root = dict - case let .index(index): - var array = root as? [Any] ?? [] - if index >= array.count { - array.append(contentsOf: repeatElement(NSNull() as Any, count: index - array.count + 1)) - } - if path.count == 1 { - if let value { - array[index] = value - } else if array.indices.contains(index) { - array.remove(at: index) - } - root = array - return - } - var child = array[index] - setValue(&child, path: Array(path.dropFirst()), value: value) - array[index] = child - root = array - } -} - -private func cloneConfigValue(_ value: Any) -> Any { - guard JSONSerialization.isValidJSONObject(value) else { return value } - do { - let data = try JSONSerialization.data(withJSONObject: value, options: []) - return try JSONSerialization.jsonObject(with: data, options: []) - } catch { - return value - } -} diff --git a/apps/macos/Sources/OpenClaw/ChannelsStore+Lifecycle.swift b/apps/macos/Sources/OpenClaw/ChannelsStore+Lifecycle.swift deleted file mode 100644 index fd516480f96..00000000000 --- a/apps/macos/Sources/OpenClaw/ChannelsStore+Lifecycle.swift +++ /dev/null @@ -1,163 +0,0 @@ -import Foundation -import OpenClawProtocol - -extension ChannelsStore { - func start() { - guard !self.isPreview else { return } - guard self.pollTask == nil else { return } - self.pollTask = Task.detached { [weak self] in - guard let self else { return } - await self.refresh(probe: true) - await self.loadConfigSchema() - await self.loadConfig() - while !Task.isCancelled { - try? await Task.sleep(nanoseconds: UInt64(self.interval * 1_000_000_000)) - await self.refresh(probe: false) - } - } - } - - func stop() { - self.pollTask?.cancel() - self.pollTask = nil - } - - func refresh(probe: Bool) async { - guard !self.isRefreshing else { return } - self.isRefreshing = true - defer { self.isRefreshing = false } - - do { - let params: [String: AnyCodable] = [ - "probe": AnyCodable(probe), - "timeoutMs": AnyCodable(8000), - ] - let snap: ChannelsStatusSnapshot = try await GatewayConnection.shared.requestDecoded( - method: .channelsStatus, - params: params, - timeoutMs: 12000) - self.snapshot = snap - self.lastSuccess = Date() - self.lastError = nil - } catch { - self.lastError = error.localizedDescription - } - } - - func startWhatsAppLogin(force: Bool, autoWait: Bool = true) async { - guard !self.whatsappBusy else { return } - self.whatsappBusy = true - defer { self.whatsappBusy = false } - var shouldAutoWait = false - do { - let params: [String: AnyCodable] = [ - "force": AnyCodable(force), - "timeoutMs": AnyCodable(30000), - ] - let result: WhatsAppLoginStartResult = try await GatewayConnection.shared.requestDecoded( - method: .webLoginStart, - params: params, - timeoutMs: 35000) - self.whatsappLoginMessage = result.message - self.whatsappLoginQrDataUrl = result.qrDataUrl - self.whatsappLoginConnected = nil - shouldAutoWait = autoWait && result.qrDataUrl != nil - } catch { - self.whatsappLoginMessage = error.localizedDescription - self.whatsappLoginQrDataUrl = nil - self.whatsappLoginConnected = nil - } - await self.refresh(probe: true) - if shouldAutoWait { - Task { await self.waitWhatsAppLogin() } - } - } - - func waitWhatsAppLogin(timeoutMs: Int = 120_000) async { - guard !self.whatsappBusy else { return } - self.whatsappBusy = true - defer { self.whatsappBusy = false } - do { - let params: [String: AnyCodable] = [ - "timeoutMs": AnyCodable(timeoutMs), - ] - let result: WhatsAppLoginWaitResult = try await GatewayConnection.shared.requestDecoded( - method: .webLoginWait, - params: params, - timeoutMs: Double(timeoutMs) + 5000) - self.whatsappLoginMessage = result.message - self.whatsappLoginConnected = result.connected - if result.connected { - self.whatsappLoginQrDataUrl = nil - } - } catch { - self.whatsappLoginMessage = error.localizedDescription - } - await self.refresh(probe: true) - } - - func logoutWhatsApp() async { - guard !self.whatsappBusy else { return } - self.whatsappBusy = true - defer { self.whatsappBusy = false } - do { - let params: [String: AnyCodable] = [ - "channel": AnyCodable("whatsapp"), - ] - let result: ChannelLogoutResult = try await GatewayConnection.shared.requestDecoded( - method: .channelsLogout, - params: params, - timeoutMs: 15000) - self.whatsappLoginMessage = result.cleared - ? "Logged out and cleared credentials." - : "No WhatsApp session found." - self.whatsappLoginQrDataUrl = nil - } catch { - self.whatsappLoginMessage = error.localizedDescription - } - await self.refresh(probe: true) - } - - func logoutTelegram() async { - guard !self.telegramBusy else { return } - self.telegramBusy = true - defer { self.telegramBusy = false } - do { - let params: [String: AnyCodable] = [ - "channel": AnyCodable("telegram"), - ] - let result: ChannelLogoutResult = try await GatewayConnection.shared.requestDecoded( - method: .channelsLogout, - params: params, - timeoutMs: 15000) - if result.envToken == true { - self.configStatus = "Telegram token still set via env; config cleared." - } else { - self.configStatus = result.cleared - ? "Telegram token cleared." - : "No Telegram token configured." - } - await self.loadConfig() - } catch { - self.configStatus = error.localizedDescription - } - await self.refresh(probe: true) - } -} - -private struct WhatsAppLoginStartResult: Codable { - let qrDataUrl: String? - let message: String -} - -private struct WhatsAppLoginWaitResult: Codable { - let connected: Bool - let message: String -} - -private struct ChannelLogoutResult: Codable { - let channel: String? - let accountId: String? - let cleared: Bool - let envToken: Bool? -} diff --git a/apps/macos/Sources/OpenClaw/ChannelsStore.swift b/apps/macos/Sources/OpenClaw/ChannelsStore.swift deleted file mode 100644 index 09b9b75a532..00000000000 --- a/apps/macos/Sources/OpenClaw/ChannelsStore.swift +++ /dev/null @@ -1,296 +0,0 @@ -import Foundation -import Observation -import OpenClawProtocol - -struct ChannelsStatusSnapshot: Codable { - struct WhatsAppSelf: Codable { - let e164: String? - let jid: String? - } - - struct WhatsAppDisconnect: Codable { - let at: Double - let status: Int? - let error: String? - let loggedOut: Bool? - } - - struct WhatsAppStatus: Codable { - let configured: Bool - let linked: Bool - let authAgeMs: Double? - let `self`: WhatsAppSelf? - let running: Bool - let connected: Bool - let lastConnectedAt: Double? - let lastDisconnect: WhatsAppDisconnect? - let reconnectAttempts: Int - let lastMessageAt: Double? - let lastEventAt: Double? - let lastError: String? - } - - struct TelegramBot: Codable { - let id: Int? - let username: String? - } - - struct TelegramWebhook: Codable { - let url: String? - let hasCustomCert: Bool? - } - - struct TelegramProbe: Codable { - let ok: Bool - let status: Int? - let error: String? - let elapsedMs: Double? - let bot: TelegramBot? - let webhook: TelegramWebhook? - } - - struct TelegramStatus: Codable { - let configured: Bool - let tokenSource: String? - let running: Bool - let mode: String? - let lastStartAt: Double? - let lastStopAt: Double? - let lastError: String? - let probe: TelegramProbe? - let lastProbeAt: Double? - } - - struct DiscordBot: Codable { - let id: String? - let username: String? - } - - struct DiscordProbe: Codable { - let ok: Bool - let status: Int? - let error: String? - let elapsedMs: Double? - let bot: DiscordBot? - } - - struct DiscordStatus: Codable { - let configured: Bool - let tokenSource: String? - let running: Bool - let lastStartAt: Double? - let lastStopAt: Double? - let lastError: String? - let probe: DiscordProbe? - let lastProbeAt: Double? - } - - struct GoogleChatProbe: Codable { - let ok: Bool - let status: Int? - let error: String? - let elapsedMs: Double? - } - - struct GoogleChatStatus: Codable { - let configured: Bool - let credentialSource: String? - let audienceType: String? - let audience: String? - let webhookPath: String? - let webhookUrl: String? - let running: Bool - let lastStartAt: Double? - let lastStopAt: Double? - let lastError: String? - let probe: GoogleChatProbe? - let lastProbeAt: Double? - } - - struct SignalProbe: Codable { - let ok: Bool - let status: Int? - let error: String? - let elapsedMs: Double? - let version: String? - } - - struct SignalStatus: Codable { - let configured: Bool - let baseUrl: String - let running: Bool - let lastStartAt: Double? - let lastStopAt: Double? - let lastError: String? - let probe: SignalProbe? - let lastProbeAt: Double? - } - - struct IMessageProbe: Codable { - let ok: Bool - let error: String? - } - - struct IMessageStatus: Codable { - let configured: Bool - let running: Bool - let lastStartAt: Double? - let lastStopAt: Double? - let lastError: String? - let cliPath: String? - let dbPath: String? - let probe: IMessageProbe? - let lastProbeAt: Double? - } - - struct ChannelAccountSnapshot: Codable { - let accountId: String - let name: String? - let enabled: Bool? - let configured: Bool? - let linked: Bool? - let running: Bool? - let connected: Bool? - let reconnectAttempts: Int? - let lastConnectedAt: Double? - let lastError: String? - let lastStartAt: Double? - let lastStopAt: Double? - let lastInboundAt: Double? - let lastOutboundAt: Double? - let lastProbeAt: Double? - let mode: String? - let dmPolicy: String? - let allowFrom: [String]? - let tokenSource: String? - let botTokenSource: String? - let appTokenSource: String? - let baseUrl: String? - let allowUnmentionedGroups: Bool? - let cliPath: String? - let dbPath: String? - let port: Int? - let probe: AnyCodable? - let audit: AnyCodable? - let application: AnyCodable? - } - - struct ChannelUiMetaEntry: Codable { - let id: String - let label: String - let detailLabel: String - let systemImage: String? - } - - let ts: Double - let channelOrder: [String] - let channelLabels: [String: String] - let channelDetailLabels: [String: String]? - let channelSystemImages: [String: String]? - let channelMeta: [ChannelUiMetaEntry]? - let channels: [String: AnyCodable] - let channelAccounts: [String: [ChannelAccountSnapshot]] - let channelDefaultAccountId: [String: String] - - func decodeChannel(_ id: String, as type: T.Type) -> T? { - guard let value = self.channels[id] else { return nil } - do { - let data = try JSONEncoder().encode(value) - return try JSONDecoder().decode(type, from: data) - } catch { - return nil - } - } -} - -struct ConfigSnapshot: Codable { - struct Issue: Codable { - let path: String - let message: String - } - - let path: String? - let exists: Bool? - let raw: String? - let hash: String? - let parsed: AnyCodable? - let valid: Bool? - let config: [String: AnyCodable]? - let issues: [Issue]? -} - -@MainActor -@Observable -final class ChannelsStore { - static let shared = ChannelsStore() - - var snapshot: ChannelsStatusSnapshot? - var lastError: String? - var lastSuccess: Date? - var isRefreshing = false - - var whatsappLoginMessage: String? - var whatsappLoginQrDataUrl: String? - var whatsappLoginConnected: Bool? - var whatsappBusy = false - var telegramBusy = false - - var configStatus: String? - var isSavingConfig = false - var configSchemaLoading = false - var configSchema: ConfigSchemaNode? - var configUiHints: [String: ConfigUiHint] = [:] - var configDraft: [String: Any] = [:] - var configDirty = false - - let interval: TimeInterval = 45 - let isPreview: Bool - var pollTask: Task? - var configRoot: [String: Any] = [:] - var configLoaded = false - - func channelMetaEntry(_ id: String) -> ChannelsStatusSnapshot.ChannelUiMetaEntry? { - self.snapshot?.channelMeta?.first(where: { $0.id == id }) - } - - func resolveChannelLabel(_ id: String) -> String { - if let meta = self.channelMetaEntry(id), !meta.label.isEmpty { - return meta.label - } - if let label = self.snapshot?.channelLabels[id], !label.isEmpty { - return label - } - return id - } - - func resolveChannelDetailLabel(_ id: String) -> String { - if let meta = self.channelMetaEntry(id), !meta.detailLabel.isEmpty { - return meta.detailLabel - } - if let detail = self.snapshot?.channelDetailLabels?[id], !detail.isEmpty { - return detail - } - return self.resolveChannelLabel(id) - } - - func resolveChannelSystemImage(_ id: String) -> String { - if let meta = self.channelMetaEntry(id), let symbol = meta.systemImage, !symbol.isEmpty { - return symbol - } - if let symbol = self.snapshot?.channelSystemImages?[id], !symbol.isEmpty { - return symbol - } - return "message" - } - - func orderedChannelIds() -> [String] { - if let meta = self.snapshot?.channelMeta, !meta.isEmpty { - return meta.map(\.id) - } - return self.snapshot?.channelOrder ?? [] - } - - init(isPreview: Bool = ProcessInfo.processInfo.isPreview) { - self.isPreview = isPreview - } -} diff --git a/apps/macos/Sources/OpenClaw/CoalescingFSEventsWatcher.swift b/apps/macos/Sources/OpenClaw/CoalescingFSEventsWatcher.swift deleted file mode 100644 index f9e38d81170..00000000000 --- a/apps/macos/Sources/OpenClaw/CoalescingFSEventsWatcher.swift +++ /dev/null @@ -1,110 +0,0 @@ -import CoreServices -import Foundation - -final class CoalescingFSEventsWatcher: @unchecked Sendable { - private let queue: DispatchQueue - private var stream: FSEventStreamRef? - private var pending = false - - private let paths: [String] - private let shouldNotify: (Int, UnsafeMutableRawPointer?) -> Bool - private let onChange: () -> Void - private let coalesceDelay: TimeInterval - - init( - paths: [String], - queueLabel: String, - coalesceDelay: TimeInterval = 0.12, - shouldNotify: @escaping (Int, UnsafeMutableRawPointer?) -> Bool = { _, _ in true }, - onChange: @escaping () -> Void) - { - self.paths = paths - self.queue = DispatchQueue(label: queueLabel) - self.coalesceDelay = coalesceDelay - self.shouldNotify = shouldNotify - self.onChange = onChange - } - - deinit { - self.stop() - } - - func start() { - guard self.stream == nil else { return } - - let retainedSelf = Unmanaged.passRetained(self) - var context = FSEventStreamContext( - version: 0, - info: retainedSelf.toOpaque(), - retain: nil, - release: { pointer in - guard let pointer else { return } - Unmanaged.fromOpaque(pointer).release() - }, - copyDescription: nil) - - let paths = self.paths as CFArray - let flags = FSEventStreamCreateFlags( - kFSEventStreamCreateFlagFileEvents | - kFSEventStreamCreateFlagUseCFTypes | - kFSEventStreamCreateFlagNoDefer) - - guard let stream = FSEventStreamCreate( - kCFAllocatorDefault, - Self.callback, - &context, - paths, - FSEventStreamEventId(kFSEventStreamEventIdSinceNow), - 0.05, - flags) - else { - retainedSelf.release() - return - } - - self.stream = stream - FSEventStreamSetDispatchQueue(stream, self.queue) - if FSEventStreamStart(stream) == false { - self.stream = nil - FSEventStreamSetDispatchQueue(stream, nil) - FSEventStreamInvalidate(stream) - FSEventStreamRelease(stream) - } - } - - func stop() { - guard let stream = self.stream else { return } - self.stream = nil - FSEventStreamStop(stream) - FSEventStreamSetDispatchQueue(stream, nil) - FSEventStreamInvalidate(stream) - FSEventStreamRelease(stream) - } -} - -extension CoalescingFSEventsWatcher { - private static let callback: FSEventStreamCallback = { _, info, numEvents, eventPaths, eventFlags, _ in - guard let info else { return } - let watcher = Unmanaged.fromOpaque(info).takeUnretainedValue() - watcher.handleEvents(numEvents: numEvents, eventPaths: eventPaths, eventFlags: eventFlags) - } - - private func handleEvents( - numEvents: Int, - eventPaths: UnsafeMutableRawPointer?, - eventFlags: UnsafePointer?) - { - guard numEvents > 0 else { return } - guard eventFlags != nil else { return } - guard self.shouldNotify(numEvents, eventPaths) else { return } - - // Coalesce rapid changes (common during builds/atomic saves). - if self.pending { return } - self.pending = true - self.queue.asyncAfter(deadline: .now() + self.coalesceDelay) { [weak self] in - guard let self else { return } - self.pending = false - self.onChange() - } - } -} diff --git a/apps/macos/Sources/OpenClaw/CommandResolver.swift b/apps/macos/Sources/OpenClaw/CommandResolver.swift deleted file mode 100644 index c17f64e30e7..00000000000 --- a/apps/macos/Sources/OpenClaw/CommandResolver.swift +++ /dev/null @@ -1,574 +0,0 @@ -import Foundation - -enum CommandResolver { - private static let projectRootDefaultsKey = "openclaw.gatewayProjectRootPath" - private static let helperName = "openclaw" - - static func gatewayEntrypoint(in root: URL) -> String? { - let distEntry = root.appendingPathComponent("dist/index.js").path - if FileManager().isReadableFile(atPath: distEntry) { return distEntry } - let openclawEntry = root.appendingPathComponent("openclaw.mjs").path - if FileManager().isReadableFile(atPath: openclawEntry) { return openclawEntry } - let binEntry = root.appendingPathComponent("bin/openclaw.js").path - if FileManager().isReadableFile(atPath: binEntry) { return binEntry } - return nil - } - - static func runtimeResolution() -> Result { - RuntimeLocator.resolve(searchPaths: self.preferredPaths()) - } - - static func runtimeResolution(searchPaths: [String]?) -> Result { - RuntimeLocator.resolve(searchPaths: searchPaths ?? self.preferredPaths()) - } - - static func makeRuntimeCommand( - runtime: RuntimeResolution, - entrypoint: String, - subcommand: String, - extraArgs: [String]) -> [String] - { - [runtime.path, entrypoint, subcommand] + extraArgs - } - - static func runtimeErrorCommand(_ error: RuntimeResolutionError) -> [String] { - let message = RuntimeLocator.describeFailure(error) - return self.errorCommand(with: message) - } - - static func errorCommand(with message: String) -> [String] { - let script = """ - cat <<'__OPENCLAW_ERR__' >&2 - \(message) - __OPENCLAW_ERR__ - exit 1 - """ - return ["/bin/sh", "-c", script] - } - - static func projectRoot() -> URL { - if let stored = UserDefaults.standard.string(forKey: self.projectRootDefaultsKey), - let url = self.expandPath(stored), - FileManager().fileExists(atPath: url.path) - { - return url - } - let fallback = FileManager().homeDirectoryForCurrentUser - .appendingPathComponent("Projects/openclaw") - if FileManager().fileExists(atPath: fallback.path) { - return fallback - } - return FileManager().homeDirectoryForCurrentUser - } - - static func setProjectRoot(_ path: String) { - UserDefaults.standard.set(path, forKey: self.projectRootDefaultsKey) - } - - static func projectRootPath() -> String { - self.projectRoot().path - } - - static func preferredPaths() -> [String] { - let current = ProcessInfo.processInfo.environment["PATH"]? - .split(separator: ":").map(String.init) ?? [] - let home = FileManager().homeDirectoryForCurrentUser - let projectRoot = self.projectRoot() - return self.preferredPaths(home: home, current: current, projectRoot: projectRoot) - } - - static func preferredPaths(home: URL, current: [String], projectRoot: URL) -> [String] { - var extras = [ - home.appendingPathComponent("Library/pnpm").path, - "/opt/homebrew/bin", - "/usr/local/bin", - "/usr/bin", - "/bin", - ] - #if DEBUG - // Dev-only convenience. Avoid project-local PATH hijacking in release builds. - extras.insert(projectRoot.appendingPathComponent("node_modules/.bin").path, at: 0) - #endif - let openclawPaths = self.openclawManagedPaths(home: home) - if !openclawPaths.isEmpty { - extras.insert(contentsOf: openclawPaths, at: 1) - } - extras.insert(contentsOf: self.nodeManagerBinPaths(home: home), at: 1 + openclawPaths.count) - var seen = Set() - // Preserve order while stripping duplicates so PATH lookups remain deterministic. - return (extras + current).filter { seen.insert($0).inserted } - } - - private static func openclawManagedPaths(home: URL) -> [String] { - let bases = [ - home.appendingPathComponent(".openclaw"), - ] - var paths: [String] = [] - for base in bases { - let bin = base.appendingPathComponent("bin") - let nodeBin = base.appendingPathComponent("tools/node/bin") - if FileManager().fileExists(atPath: bin.path) { - paths.append(bin.path) - } - if FileManager().fileExists(atPath: nodeBin.path) { - paths.append(nodeBin.path) - } - } - return paths - } - - private static func nodeManagerBinPaths(home: URL) -> [String] { - var bins: [String] = [] - - // Volta - let volta = home.appendingPathComponent(".volta/bin") - if FileManager().fileExists(atPath: volta.path) { - bins.append(volta.path) - } - - // asdf - let asdf = home.appendingPathComponent(".asdf/shims") - if FileManager().fileExists(atPath: asdf.path) { - bins.append(asdf.path) - } - - // fnm - bins.append(contentsOf: self.versionedNodeBinPaths( - base: home.appendingPathComponent(".local/share/fnm/node-versions"), - suffix: "installation/bin")) - - // nvm - bins.append(contentsOf: self.versionedNodeBinPaths( - base: home.appendingPathComponent(".nvm/versions/node"), - suffix: "bin")) - - return bins - } - - private static func versionedNodeBinPaths(base: URL, suffix: String) -> [String] { - guard FileManager().fileExists(atPath: base.path) else { return [] } - let entries: [String] - do { - entries = try FileManager().contentsOfDirectory(atPath: base.path) - } catch { - return [] - } - - func parseVersion(_ name: String) -> [Int] { - let trimmed = name.hasPrefix("v") ? String(name.dropFirst()) : name - return trimmed.split(separator: ".").compactMap { Int($0) } - } - - let sorted = entries.sorted { a, b in - let va = parseVersion(a) - let vb = parseVersion(b) - let maxCount = max(va.count, vb.count) - for i in 0.. bi } - } - // If identical numerically, keep stable ordering. - return a > b - } - - var paths: [String] = [] - for entry in sorted { - let binDir = base.appendingPathComponent(entry).appendingPathComponent(suffix) - let node = binDir.appendingPathComponent("node") - if FileManager().isExecutableFile(atPath: node.path) { - paths.append(binDir.path) - } - } - return paths - } - - static func findExecutable(named name: String, searchPaths: [String]? = nil) -> String? { - for dir in searchPaths ?? self.preferredPaths() { - let candidate = (dir as NSString).appendingPathComponent(name) - if FileManager().isExecutableFile(atPath: candidate) { - return candidate - } - } - return nil - } - - static func openclawExecutable(searchPaths: [String]? = nil) -> String? { - self.findExecutable(named: self.helperName, searchPaths: searchPaths) - } - - static func projectOpenClawExecutable(projectRoot: URL? = nil) -> String? { - #if DEBUG - let root = projectRoot ?? self.projectRoot() - let candidate = root.appendingPathComponent("node_modules/.bin").appendingPathComponent(self.helperName).path - return FileManager().isExecutableFile(atPath: candidate) ? candidate : nil - #else - return nil - #endif - } - - static func nodeCliPath() -> String? { - let root = self.projectRoot() - let candidates = [ - root.appendingPathComponent("openclaw.mjs").path, - root.appendingPathComponent("bin/openclaw.js").path, - ] - for candidate in candidates where FileManager().isReadableFile(atPath: candidate) { - return candidate - } - return nil - } - - static func hasAnyOpenClawInvoker(searchPaths: [String]? = nil) -> Bool { - if self.openclawExecutable(searchPaths: searchPaths) != nil { return true } - if self.findExecutable(named: "pnpm", searchPaths: searchPaths) != nil { return true } - if self.findExecutable(named: "node", searchPaths: searchPaths) != nil, - self.nodeCliPath() != nil - { - return true - } - return false - } - - static func openclawNodeCommand( - subcommand: String, - extraArgs: [String] = [], - defaults: UserDefaults = .standard, - configRoot: [String: Any]? = nil, - searchPaths: [String]? = nil) -> [String] - { - let settings = self.connectionSettings(defaults: defaults, configRoot: configRoot) - if settings.mode == .remote, let ssh = self.sshNodeCommand( - subcommand: subcommand, - extraArgs: extraArgs, - settings: settings) - { - return ssh - } - - let runtimeResult = self.runtimeResolution(searchPaths: searchPaths) - - switch runtimeResult { - case let .success(runtime): - let root = self.projectRoot() - if let openclawPath = self.projectOpenClawExecutable(projectRoot: root) { - return [openclawPath, subcommand] + extraArgs - } - - if let entry = self.gatewayEntrypoint(in: root) { - return self.makeRuntimeCommand( - runtime: runtime, - entrypoint: entry, - subcommand: subcommand, - extraArgs: extraArgs) - } - if let pnpm = self.findExecutable(named: "pnpm", searchPaths: searchPaths) { - // Use --silent to avoid pnpm lifecycle banners that would corrupt JSON outputs. - return [pnpm, "--silent", "openclaw", subcommand] + extraArgs - } - if let openclawPath = self.openclawExecutable(searchPaths: searchPaths) { - return [openclawPath, subcommand] + extraArgs - } - - let missingEntry = """ - openclaw entrypoint missing (looked for dist/index.js or openclaw.mjs); run pnpm build. - """ - return self.errorCommand(with: missingEntry) - - case let .failure(error): - return self.runtimeErrorCommand(error) - } - } - - static func openclawCommand( - subcommand: String, - extraArgs: [String] = [], - defaults: UserDefaults = .standard, - configRoot: [String: Any]? = nil, - searchPaths: [String]? = nil) -> [String] - { - self.openclawNodeCommand( - subcommand: subcommand, - extraArgs: extraArgs, - defaults: defaults, - configRoot: configRoot, - searchPaths: searchPaths) - } - - // MARK: - SSH helpers - - private static func sshNodeCommand(subcommand: String, extraArgs: [String], settings: RemoteSettings) -> [String]? { - guard !settings.target.isEmpty else { return nil } - guard let parsed = self.parseSSHTarget(settings.target) else { return nil } - - // Run the real openclaw CLI on the remote host. - let exportedPath = [ - "/opt/homebrew/bin", - "/usr/local/bin", - "/usr/bin", - "/bin", - "/usr/sbin", - "/sbin", - "$HOME/Library/pnpm", - "$PATH", - ].joined(separator: ":") - let quotedArgs = ([subcommand] + extraArgs).map(self.shellQuote).joined(separator: " ") - let userPRJ = settings.projectRoot.trimmingCharacters(in: .whitespacesAndNewlines) - let userCLI = settings.cliPath.trimmingCharacters(in: .whitespacesAndNewlines) - - let projectSection = if userPRJ.isEmpty { - """ - DEFAULT_PRJ="$HOME/Projects/openclaw" - if [ -d "$DEFAULT_PRJ" ]; then - PRJ="$DEFAULT_PRJ" - cd "$PRJ" || { echo "Project root not found: $PRJ"; exit 127; } - fi - """ - } else { - """ - PRJ=\(self.shellQuote(userPRJ)) - cd "$PRJ" || { echo "Project root not found: $PRJ"; exit 127; } - """ - } - - let cliSection = if userCLI.isEmpty { - "" - } else { - """ - CLI_HINT=\(self.shellQuote(userCLI)) - if [ -n "$CLI_HINT" ]; then - if [ -x "$CLI_HINT" ]; then - CLI="$CLI_HINT" - "$CLI_HINT" \(quotedArgs); - exit $?; - elif [ -f "$CLI_HINT" ]; then - if command -v node >/dev/null 2>&1; then - CLI="node $CLI_HINT" - node "$CLI_HINT" \(quotedArgs); - exit $?; - fi - fi - fi - """ - } - - let scriptBody = """ - PATH=\(exportedPath); - CLI=""; - \(cliSection) - \(projectSection) - if command -v openclaw >/dev/null 2>&1; then - CLI="$(command -v openclaw)" - openclaw \(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" - node "$PRJ/dist/index.js" \(quotedArgs); - else - echo "Node >=22 required on remote host"; exit 127; - fi - elif [ -n "${PRJ:-}" ] && [ -f "$PRJ/openclaw.mjs" ]; then - if command -v node >/dev/null 2>&1; then - CLI="node $PRJ/openclaw.mjs" - node "$PRJ/openclaw.mjs" \(quotedArgs); - else - echo "Node >=22 required on remote host"; exit 127; - fi - elif [ -n "${PRJ:-}" ] && [ -f "$PRJ/bin/openclaw.js" ]; then - if command -v node >/dev/null 2>&1; then - CLI="node $PRJ/bin/openclaw.js" - node "$PRJ/bin/openclaw.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 openclaw" - pnpm --silent openclaw \(quotedArgs); - else - echo "openclaw CLI missing on remote host"; exit 127; - fi - """ - let options: [String] = [ - "-o", "BatchMode=yes", - "-o", "StrictHostKeyChecking=accept-new", - "-o", "UpdateHostKeys=yes", - ] - let args = self.sshArguments( - target: parsed, - identity: settings.identity, - options: options, - remoteCommand: ["/bin/sh", "-c", scriptBody]) - return ["/usr/bin/ssh"] + args - } - - struct RemoteSettings { - let mode: AppState.ConnectionMode - let target: String - let identity: String - let projectRoot: String - let cliPath: String - } - - static func connectionSettings( - defaults: UserDefaults = .standard, - configRoot: [String: Any]? = nil) -> RemoteSettings - { - let root = configRoot ?? OpenClawConfigFile.loadDict() - let mode = ConnectionModeResolver.resolve(root: root, defaults: defaults).mode - let target = defaults.string(forKey: remoteTargetKey) ?? "" - let identity = defaults.string(forKey: remoteIdentityKey) ?? "" - let projectRoot = defaults.string(forKey: remoteProjectRootKey) ?? "" - let cliPath = defaults.string(forKey: remoteCliPathKey) ?? "" - return RemoteSettings( - mode: mode, - target: self.sanitizedTarget(target), - identity: identity, - projectRoot: projectRoot, - cliPath: cliPath) - } - - static func connectionModeIsRemote(defaults: UserDefaults = .standard) -> Bool { - self.connectionSettings(defaults: defaults).mode == .remote - } - - private static func sanitizedTarget(_ raw: String) -> String { - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.hasPrefix("ssh ") { - return trimmed.replacingOccurrences(of: "ssh ", with: "").trimmingCharacters(in: .whitespacesAndNewlines) - } - return trimmed - } - - struct SSHParsedTarget { - let user: String? - let host: String - let port: Int - } - - static func parseSSHTarget(_ target: String) -> SSHParsedTarget? { - let trimmed = self.normalizeSSHTargetInput(target) - guard !trimmed.isEmpty else { return nil } - if trimmed.rangeOfCharacter(from: CharacterSet.whitespacesAndNewlines.union(.controlCharacters)) != nil { - return nil - } - let userHostPort: String - let user: String? - if let atRange = trimmed.range(of: "@") { - user = String(trimmed[.. 0, parsedPort <= 65535 else { - return nil - } - port = parsedPort - } else { - host = userHostPort - port = 22 - } - - return self.makeSSHTarget(user: user, host: host, port: port) - } - - static func sshTargetValidationMessage(_ target: String) -> String? { - let trimmed = self.normalizeSSHTargetInput(target) - guard !trimmed.isEmpty else { return nil } - if trimmed.hasPrefix("-") { - return "SSH target cannot start with '-'" - } - if trimmed.rangeOfCharacter(from: CharacterSet.whitespacesAndNewlines.union(.controlCharacters)) != nil { - return "SSH target cannot contain spaces" - } - if self.parseSSHTarget(trimmed) == nil { - return "SSH target must look like user@host[:port]" - } - return nil - } - - private static func shellQuote(_ text: String) -> String { - if text.isEmpty { return "''" } - let escaped = text.replacingOccurrences(of: "'", with: "'\\''") - return "'\(escaped)'" - } - - private static func expandPath(_ path: String) -> URL? { - var expanded = path - if expanded.hasPrefix("~") { - let home = FileManager().homeDirectoryForCurrentUser.path - expanded.replaceSubrange(expanded.startIndex...expanded.startIndex, with: home) - } - return URL(fileURLWithPath: expanded) - } - - private static func normalizeSSHTargetInput(_ target: String) -> String { - var trimmed = target.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.hasPrefix("ssh ") { - trimmed = trimmed.replacingOccurrences(of: "ssh ", with: "") - .trimmingCharacters(in: .whitespacesAndNewlines) - } - return trimmed - } - - private static func isValidSSHComponent(_ value: String, allowLeadingDash: Bool = false) -> Bool { - if value.isEmpty { return false } - if !allowLeadingDash, value.hasPrefix("-") { return false } - let invalid = CharacterSet.whitespacesAndNewlines.union(.controlCharacters) - return value.rangeOfCharacter(from: invalid) == nil - } - - static func makeSSHTarget(user: String?, host: String, port: Int) -> SSHParsedTarget? { - let trimmedHost = host.trimmingCharacters(in: .whitespacesAndNewlines) - guard self.isValidSSHComponent(trimmedHost) else { return nil } - let trimmedUser = user?.trimmingCharacters(in: .whitespacesAndNewlines) - let normalizedUser: String? - if let trimmedUser { - guard self.isValidSSHComponent(trimmedUser) else { return nil } - normalizedUser = trimmedUser.isEmpty ? nil : trimmedUser - } else { - normalizedUser = nil - } - guard port > 0, port <= 65535 else { return nil } - return SSHParsedTarget(user: normalizedUser, host: trimmedHost, port: port) - } - - private static func sshTargetString(_ target: SSHParsedTarget) -> String { - target.user.map { "\($0)@\(target.host)" } ?? target.host - } - - static func sshArguments( - target: SSHParsedTarget, - identity: String, - options: [String], - remoteCommand: [String] = []) -> [String] - { - var args = options - if target.port > 0 { - args.append(contentsOf: ["-p", String(target.port)]) - } - let trimmedIdentity = identity.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmedIdentity.isEmpty { - // Only use IdentitiesOnly when an explicit identity file is provided. - // This allows 1Password SSH agent and other SSH agents to provide keys. - args.append(contentsOf: ["-o", "IdentitiesOnly=yes"]) - args.append(contentsOf: ["-i", trimmedIdentity]) - } - args.append("--") - args.append(self.sshTargetString(target)) - args.append(contentsOf: remoteCommand) - return args - } - - #if SWIFT_PACKAGE - static func _testNodeManagerBinPaths(home: URL) -> [String] { - self.nodeManagerBinPaths(home: home) - } - #endif -} diff --git a/apps/macos/Sources/OpenClaw/ConfigFileWatcher.swift b/apps/macos/Sources/OpenClaw/ConfigFileWatcher.swift deleted file mode 100644 index 4434443497e..00000000000 --- a/apps/macos/Sources/OpenClaw/ConfigFileWatcher.swift +++ /dev/null @@ -1,45 +0,0 @@ -import Foundation - -final class ConfigFileWatcher: @unchecked Sendable { - private let url: URL - private let watchedDir: URL - private let targetPath: String - private let targetName: String - private let watcher: CoalescingFSEventsWatcher - - init(url: URL, onChange: @escaping () -> Void) { - self.url = url - self.watchedDir = url.deletingLastPathComponent() - self.targetPath = url.path - self.targetName = url.lastPathComponent - let watchedDirPath = self.watchedDir.path - let targetPath = self.targetPath - let targetName = self.targetName - self.watcher = CoalescingFSEventsWatcher( - paths: [watchedDirPath], - queueLabel: "ai.openclaw.configwatcher", - shouldNotify: { _, eventPaths in - guard let eventPaths else { return true } - let paths = unsafeBitCast(eventPaths, to: NSArray.self) - for case let path as String in paths { - if path == targetPath { return true } - if path.hasSuffix("/\(targetName)") { return true } - if path == watchedDirPath { return true } - } - return false - }, - onChange: onChange) - } - - deinit { - self.stop() - } - - func start() { - self.watcher.start() - } - - func stop() { - self.watcher.stop() - } -} diff --git a/apps/macos/Sources/OpenClaw/ConfigSchemaSupport.swift b/apps/macos/Sources/OpenClaw/ConfigSchemaSupport.swift deleted file mode 100644 index 406d908d0b7..00000000000 --- a/apps/macos/Sources/OpenClaw/ConfigSchemaSupport.swift +++ /dev/null @@ -1,219 +0,0 @@ -import Foundation - -enum ConfigPathSegment: Hashable { - case key(String) - case index(Int) -} - -typealias ConfigPath = [ConfigPathSegment] - -struct ConfigUiHint { - let label: String? - let help: String? - let order: Double? - let advanced: Bool? - let sensitive: Bool? - let placeholder: String? - - init(raw: [String: Any]) { - self.label = raw["label"] as? String - self.help = raw["help"] as? String - if let order = raw["order"] as? Double { - self.order = order - } else if let orderInt = raw["order"] as? Int { - self.order = Double(orderInt) - } else { - self.order = nil - } - self.advanced = raw["advanced"] as? Bool - self.sensitive = raw["sensitive"] as? Bool - self.placeholder = raw["placeholder"] as? String - } -} - -struct ConfigSchemaNode { - let raw: [String: Any] - - init?(raw: Any) { - guard let dict = raw as? [String: Any] else { return nil } - self.raw = dict - } - - var title: String? { - self.raw["title"] as? String - } - - var description: String? { - self.raw["description"] as? String - } - - var enumValues: [Any]? { - self.raw["enum"] as? [Any] - } - - var constValue: Any? { - self.raw["const"] - } - - var explicitDefault: Any? { - self.raw["default"] - } - - var requiredKeys: Set { - Set((self.raw["required"] as? [String]) ?? []) - } - - var typeList: [String] { - if let type = self.raw["type"] as? String { return [type] } - if let types = self.raw["type"] as? [String] { return types } - return [] - } - - var schemaType: String? { - let filtered = self.typeList.filter { $0 != "null" } - if let first = filtered.first { return first } - return self.typeList.first - } - - var isNullSchema: Bool { - let types = self.typeList - return types.count == 1 && types.first == "null" - } - - var properties: [String: ConfigSchemaNode] { - guard let props = self.raw["properties"] as? [String: Any] else { return [:] } - return props.compactMapValues { ConfigSchemaNode(raw: $0) } - } - - var anyOf: [ConfigSchemaNode] { - guard let raw = self.raw["anyOf"] as? [Any] else { return [] } - return raw.compactMap { ConfigSchemaNode(raw: $0) } - } - - var oneOf: [ConfigSchemaNode] { - guard let raw = self.raw["oneOf"] as? [Any] else { return [] } - return raw.compactMap { ConfigSchemaNode(raw: $0) } - } - - var literalValue: Any? { - if let constValue { return constValue } - if let enumValues, enumValues.count == 1 { return enumValues[0] } - return nil - } - - var items: ConfigSchemaNode? { - if let items = self.raw["items"] as? [Any], let first = items.first { - return ConfigSchemaNode(raw: first) - } - if let items = self.raw["items"] { - return ConfigSchemaNode(raw: items) - } - return nil - } - - var additionalProperties: ConfigSchemaNode? { - if let additional = self.raw["additionalProperties"] as? [String: Any] { - return ConfigSchemaNode(raw: additional) - } - return nil - } - - var allowsAdditionalProperties: Bool { - if let allow = self.raw["additionalProperties"] as? Bool { return allow } - return self.additionalProperties != nil - } - - var defaultValue: Any { - if let value = self.raw["default"] { return value } - switch self.schemaType { - case "object": - return [String: Any]() - case "array": - return [Any]() - case "boolean": - return false - case "integer": - return 0 - case "number": - return 0.0 - case "string": - return "" - default: - return "" - } - } - - func node(at path: ConfigPath) -> ConfigSchemaNode? { - var current: ConfigSchemaNode? = self - for segment in path { - guard let node = current else { return nil } - switch segment { - case let .key(key): - if node.schemaType == "object" { - if let next = node.properties[key] { - current = next - continue - } - if let additional = node.additionalProperties { - current = additional - continue - } - return nil - } - return nil - case .index: - guard node.schemaType == "array" else { return nil } - current = node.items - } - } - return current - } -} - -func decodeUiHints(_ raw: [String: Any]) -> [String: ConfigUiHint] { - raw.reduce(into: [:]) { result, entry in - if let hint = entry.value as? [String: Any] { - result[entry.key] = ConfigUiHint(raw: hint) - } - } -} - -func hintForPath(_ path: ConfigPath, hints: [String: ConfigUiHint]) -> ConfigUiHint? { - let key = pathKey(path) - if let direct = hints[key] { return direct } - let segments = key.split(separator: ".").map(String.init) - for (hintKey, hint) in hints { - guard hintKey.contains("*") else { continue } - let hintSegments = hintKey.split(separator: ".").map(String.init) - guard hintSegments.count == segments.count else { continue } - var match = true - for (index, seg) in segments.enumerated() { - let hintSegment = hintSegments[index] - if hintSegment != "*", hintSegment != seg { - match = false - break - } - } - if match { return hint } - } - return nil -} - -func isSensitivePath(_ path: ConfigPath) -> Bool { - let key = pathKey(path).lowercased() - return key.contains("token") - || key.contains("password") - || key.contains("secret") - || key.contains("apikey") - || key.hasSuffix("key") -} - -func pathKey(_ path: ConfigPath) -> String { - path.compactMap { segment -> String? in - switch segment { - case let .key(key): return key - case .index: return nil - } - } - .joined(separator: ".") -} diff --git a/apps/macos/Sources/OpenClaw/ConfigSettings.swift b/apps/macos/Sources/OpenClaw/ConfigSettings.swift deleted file mode 100644 index 096ae3f7149..00000000000 --- a/apps/macos/Sources/OpenClaw/ConfigSettings.swift +++ /dev/null @@ -1,395 +0,0 @@ -import SwiftUI - -@MainActor -struct ConfigSettings: View { - private let isPreview = ProcessInfo.processInfo.isPreview - private let isNixMode = ProcessInfo.processInfo.isNixMode - @Bindable var store: ChannelsStore - @State private var hasLoaded = false - @State private var activeSectionKey: String? - @State private var activeSubsection: SubsectionSelection? - - init(store: ChannelsStore = .shared) { - self.store = store - } - - var body: some View { - HStack(spacing: 16) { - self.sidebar - self.detail - } - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) - .task { - guard !self.hasLoaded else { return } - guard !self.isPreview else { return } - self.hasLoaded = true - await self.store.loadConfigSchema() - await self.store.loadConfig() - } - .onAppear { self.ensureSelection() } - .onChange(of: self.store.configSchemaLoading) { _, loading in - if !loading { self.ensureSelection() } - } - } -} - -extension ConfigSettings { - private enum SubsectionSelection: Hashable { - case all - case key(String) - } - - private struct ConfigSection: Identifiable { - let key: String - let label: String - let help: String? - let node: ConfigSchemaNode - - var id: String { - self.key - } - } - - private struct ConfigSubsection: Identifiable { - let key: String - let label: String - let help: String? - let node: ConfigSchemaNode - let path: ConfigPath - - var id: String { - self.key - } - } - - private var sections: [ConfigSection] { - guard let schema = self.store.configSchema else { return [] } - return self.resolveSections(schema) - } - - private var activeSection: ConfigSection? { - self.sections.first { $0.key == self.activeSectionKey } - } - - private var sidebar: some View { - ScrollView { - LazyVStack(alignment: .leading, spacing: 8) { - if self.sections.isEmpty { - Text("No config sections available.") - .font(.caption) - .foregroundStyle(.secondary) - .padding(.horizontal, 6) - .padding(.vertical, 4) - } else { - ForEach(self.sections) { section in - self.sidebarRow(section) - } - } - } - .padding(.vertical, 10) - .padding(.horizontal, 10) - } - .frame(minWidth: 220, idealWidth: 240, maxWidth: 280, maxHeight: .infinity, alignment: .topLeading) - .background( - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill(Color(nsColor: .windowBackgroundColor))) - .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) - } - - private var detail: some View { - VStack(alignment: .leading, spacing: 16) { - if self.store.configSchemaLoading { - ProgressView().controlSize(.small) - } else if let section = self.activeSection { - self.sectionDetail(section) - } else if self.store.configSchema != nil { - self.emptyDetail - } else { - Text("Schema unavailable.") - .font(.caption) - .foregroundStyle(.secondary) - } - } - .frame(minWidth: 460, maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) - } - - private var emptyDetail: some View { - VStack(alignment: .leading, spacing: 8) { - self.header - Text("Select a config section to view settings.") - .font(.callout) - .foregroundStyle(.secondary) - } - .padding(.horizontal, 24) - .padding(.vertical, 18) - } - - private func sectionDetail(_ section: ConfigSection) -> some View { - ScrollView(.vertical) { - VStack(alignment: .leading, spacing: 16) { - self.header - if let status = self.store.configStatus { - Text(status) - .font(.callout) - .foregroundStyle(.secondary) - } - self.actionRow - self.sectionHeader(section) - self.subsectionNav(section) - self.sectionForm(section) - if self.store.configDirty, !self.isNixMode { - Text("Unsaved changes") - .font(.caption) - .foregroundStyle(.secondary) - } - Spacer(minLength: 0) - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal, 24) - .padding(.vertical, 18) - .groupBoxStyle(PlainSettingsGroupBoxStyle()) - } - } - - @ViewBuilder - private var header: some View { - Text("Config") - .font(.title3.weight(.semibold)) - Text(self.isNixMode - ? "This tab is read-only in Nix mode. Edit config via Nix and rebuild." - : "Edit ~/.openclaw/openclaw.json using the schema-driven form.") - .font(.callout) - .foregroundStyle(.secondary) - } - - private func sectionHeader(_ section: ConfigSection) -> some View { - VStack(alignment: .leading, spacing: 6) { - Text(section.label) - .font(.title3.weight(.semibold)) - if let help = section.help { - Text(help) - .font(.callout) - .foregroundStyle(.secondary) - } - } - } - - private var actionRow: some View { - HStack(spacing: 10) { - Button("Reload") { - Task { await self.store.reloadConfigDraft() } - } - .disabled(!self.store.configLoaded) - - Button(self.store.isSavingConfig ? "Saving…" : "Save") { - Task { await self.store.saveConfigDraft() } - } - .disabled(self.isNixMode || self.store.isSavingConfig || !self.store.configDirty) - } - .buttonStyle(.bordered) - } - - private func sidebarRow(_ section: ConfigSection) -> some View { - let isSelected = self.activeSectionKey == section.key - return Button { - self.selectSection(section) - } label: { - VStack(alignment: .leading, spacing: 2) { - Text(section.label) - if let help = section.help { - Text(help) - .font(.caption) - .foregroundStyle(.secondary) - .lineLimit(2) - } - } - .padding(.vertical, 6) - .padding(.horizontal, 8) - .frame(maxWidth: .infinity, alignment: .leading) - .background(isSelected ? Color.accentColor.opacity(0.18) : Color.clear) - .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous)) - .background(Color.clear) - .contentShape(Rectangle()) - } - .frame(maxWidth: .infinity, alignment: .leading) - .buttonStyle(.plain) - .contentShape(Rectangle()) - } - - @ViewBuilder - private func subsectionNav(_ section: ConfigSection) -> some View { - let subsections = self.resolveSubsections(for: section) - if subsections.isEmpty { - EmptyView() - } else { - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 8) { - self.subsectionButton( - title: "All", - isSelected: self.activeSubsection == .all) - { - self.activeSubsection = .all - } - ForEach(subsections) { subsection in - self.subsectionButton( - title: subsection.label, - isSelected: self.activeSubsection == .key(subsection.key)) - { - self.activeSubsection = .key(subsection.key) - } - } - } - .padding(.vertical, 2) - } - } - } - - private func subsectionButton( - title: String, - isSelected: Bool, - action: @escaping () -> Void) -> some View - { - Button(action: action) { - Text(title) - .font(.callout.weight(.semibold)) - .foregroundStyle(isSelected ? Color.accentColor : .primary) - .padding(.horizontal, 10) - .padding(.vertical, 6) - .background(isSelected ? Color.accentColor.opacity(0.18) : Color(nsColor: .controlBackgroundColor)) - .clipShape(Capsule()) - } - .buttonStyle(.plain) - } - - private func sectionForm(_ section: ConfigSection) -> some View { - let subsection = self.activeSubsection - let defaultPath: ConfigPath = [.key(section.key)] - let subsections = self.resolveSubsections(for: section) - let resolved: (ConfigSchemaNode, ConfigPath) = { - if case let .key(key) = subsection, - let match = subsections.first(where: { $0.key == key }) - { - return (match.node, match.path) - } - return (self.resolvedSchemaNode(section.node), defaultPath) - }() - - return ConfigSchemaForm(store: self.store, schema: resolved.0, path: resolved.1) - .disabled(self.isNixMode) - } - - private func ensureSelection() { - guard let schema = self.store.configSchema else { return } - let sections = self.resolveSections(schema) - guard !sections.isEmpty else { return } - - let active = sections.first { $0.key == self.activeSectionKey } ?? sections[0] - if self.activeSectionKey != active.key { - self.activeSectionKey = active.key - } - self.ensureSubsection(for: active) - } - - private func ensureSubsection(for section: ConfigSection) { - let subsections = self.resolveSubsections(for: section) - guard !subsections.isEmpty else { - self.activeSubsection = nil - return - } - - switch self.activeSubsection { - case .all: - return - case let .key(key): - if subsections.contains(where: { $0.key == key }) { return } - case .none: - break - } - - if let first = subsections.first { - self.activeSubsection = .key(first.key) - } - } - - private func selectSection(_ section: ConfigSection) { - guard self.activeSectionKey != section.key else { return } - self.activeSectionKey = section.key - let subsections = self.resolveSubsections(for: section) - if let first = subsections.first { - self.activeSubsection = .key(first.key) - } else { - self.activeSubsection = nil - } - } - - private func resolveSections(_ root: ConfigSchemaNode) -> [ConfigSection] { - let node = self.resolvedSchemaNode(root) - let hints = self.store.configUiHints - let keys = node.properties.keys.sorted { lhs, rhs in - let orderA = hintForPath([.key(lhs)], hints: hints)?.order ?? 0 - let orderB = hintForPath([.key(rhs)], hints: hints)?.order ?? 0 - if orderA != orderB { return orderA < orderB } - return lhs < rhs - } - - return keys.compactMap { key in - guard let child = node.properties[key] else { return nil } - let path: ConfigPath = [.key(key)] - let hint = hintForPath(path, hints: hints) - let label = hint?.label - ?? child.title - ?? self.humanize(key) - let help = hint?.help ?? child.description - return ConfigSection(key: key, label: label, help: help, node: child) - } - } - - private func resolveSubsections(for section: ConfigSection) -> [ConfigSubsection] { - let node = self.resolvedSchemaNode(section.node) - guard node.schemaType == "object" else { return [] } - let hints = self.store.configUiHints - let keys = node.properties.keys.sorted { lhs, rhs in - let orderA = hintForPath([.key(section.key), .key(lhs)], hints: hints)?.order ?? 0 - let orderB = hintForPath([.key(section.key), .key(rhs)], hints: hints)?.order ?? 0 - if orderA != orderB { return orderA < orderB } - return lhs < rhs - } - - return keys.compactMap { key in - guard let child = node.properties[key] else { return nil } - let path: ConfigPath = [.key(section.key), .key(key)] - let hint = hintForPath(path, hints: hints) - let label = hint?.label - ?? child.title - ?? self.humanize(key) - let help = hint?.help ?? child.description - return ConfigSubsection( - key: key, - label: label, - help: help, - node: child, - path: path) - } - } - - private func resolvedSchemaNode(_ node: ConfigSchemaNode) -> ConfigSchemaNode { - let variants = node.anyOf.isEmpty ? node.oneOf : node.anyOf - if !variants.isEmpty { - let nonNull = variants.filter { !$0.isNullSchema } - if nonNull.count == 1, let only = nonNull.first { return only } - } - return node - } - - private func humanize(_ key: String) -> String { - key.replacingOccurrences(of: "_", with: " ") - .replacingOccurrences(of: "-", with: " ") - .capitalized - } -} - -struct ConfigSettings_Previews: PreviewProvider { - static var previews: some View { - ConfigSettings() - } -} diff --git a/apps/macos/Sources/OpenClaw/ConfigStore.swift b/apps/macos/Sources/OpenClaw/ConfigStore.swift deleted file mode 100644 index 8fd779c6456..00000000000 --- a/apps/macos/Sources/OpenClaw/ConfigStore.swift +++ /dev/null @@ -1,117 +0,0 @@ -import Foundation -import OpenClawProtocol - -enum ConfigStore { - struct Overrides: Sendable { - var isRemoteMode: (@Sendable () async -> Bool)? - var loadLocal: (@MainActor @Sendable () -> [String: Any])? - var saveLocal: (@MainActor @Sendable ([String: Any]) -> Void)? - var loadRemote: (@MainActor @Sendable () async -> [String: Any])? - var saveRemote: (@MainActor @Sendable ([String: Any]) async throws -> Void)? - } - - private actor OverrideStore { - var overrides = Overrides() - - func setOverride(_ overrides: Overrides) { - self.overrides = overrides - } - } - - private static let overrideStore = OverrideStore() - @MainActor private static var lastHash: String? - - private static func isRemoteMode() async -> Bool { - let overrides = await self.overrideStore.overrides - if let override = overrides.isRemoteMode { - return await override() - } - return await MainActor.run { AppStateStore.shared.connectionMode == .remote } - } - - @MainActor - static func load() async -> [String: Any] { - let overrides = await self.overrideStore.overrides - if await self.isRemoteMode() { - if let override = overrides.loadRemote { - return await override() - } - return await self.loadFromGateway() ?? [:] - } - if let override = overrides.loadLocal { - return override() - } - if let gateway = await self.loadFromGateway() { - return gateway - } - return OpenClawConfigFile.loadDict() - } - - @MainActor - static func save(_ root: sending [String: Any]) async throws { - let overrides = await self.overrideStore.overrides - if await self.isRemoteMode() { - if let override = overrides.saveRemote { - try await override(root) - } else { - try await self.saveToGateway(root) - } - } else { - if let override = overrides.saveLocal { - override(root) - } else { - do { - try await self.saveToGateway(root) - } catch { - OpenClawConfigFile.saveDict(root) - } - } - } - } - - @MainActor - private static func loadFromGateway() async -> [String: Any]? { - do { - let snap: ConfigSnapshot = try await GatewayConnection.shared.requestDecoded( - method: .configGet, - params: nil, - timeoutMs: 8000) - self.lastHash = snap.hash - return snap.config?.mapValues { $0.foundationValue } ?? [:] - } catch { - return nil - } - } - - @MainActor - private static func saveToGateway(_ root: [String: Any]) async throws { - if self.lastHash == nil { - _ = await self.loadFromGateway() - } - let data = try JSONSerialization.data(withJSONObject: root, options: [.prettyPrinted, .sortedKeys]) - guard let raw = String(data: data, encoding: .utf8) else { - throw NSError(domain: "ConfigStore", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "Failed to encode config.", - ]) - } - var params: [String: AnyCodable] = ["raw": AnyCodable(raw)] - if let baseHash = self.lastHash { - params["baseHash"] = AnyCodable(baseHash) - } - _ = try await GatewayConnection.shared.requestRaw( - method: .configSet, - params: params, - timeoutMs: 10000) - _ = await self.loadFromGateway() - } - - #if DEBUG - static func _testSetOverrides(_ overrides: Overrides) async { - await self.overrideStore.setOverride(overrides) - } - - static func _testClearOverrides() async { - await self.overrideStore.setOverride(.init()) - } - #endif -} diff --git a/apps/macos/Sources/OpenClaw/ConnectionModeCoordinator.swift b/apps/macos/Sources/OpenClaw/ConnectionModeCoordinator.swift deleted file mode 100644 index b1c5eab1dbb..00000000000 --- a/apps/macos/Sources/OpenClaw/ConnectionModeCoordinator.swift +++ /dev/null @@ -1,79 +0,0 @@ -import Foundation -import OSLog - -@MainActor -final class ConnectionModeCoordinator { - static let shared = ConnectionModeCoordinator() - - private let logger = Logger(subsystem: "ai.openclaw", category: "connection") - private var lastMode: AppState.ConnectionMode? - - /// Apply the requested connection mode by starting/stopping local gateway, - /// managing the control-channel SSH tunnel, and cleaning up chat windows/panels. - func apply(mode: AppState.ConnectionMode, paused: Bool) async { - if let lastMode = self.lastMode, lastMode != mode { - GatewayProcessManager.shared.clearLastFailure() - NodesStore.shared.lastError = nil - } - self.lastMode = mode - switch mode { - case .unconfigured: - _ = await NodeServiceManager.stop() - NodesStore.shared.lastError = nil - await RemoteTunnelManager.shared.stopAll() - WebChatManager.shared.resetTunnels() - GatewayProcessManager.shared.stop() - await GatewayConnection.shared.shutdown() - await ControlChannel.shared.disconnect() - Task.detached { await PortGuardian.shared.sweep(mode: .unconfigured) } - - case .local: - _ = await NodeServiceManager.stop() - NodesStore.shared.lastError = nil - await RemoteTunnelManager.shared.stopAll() - WebChatManager.shared.resetTunnels() - let shouldStart = GatewayAutostartPolicy.shouldStartGateway(mode: .local, paused: paused) - if shouldStart { - GatewayProcessManager.shared.setActive(true) - if GatewayAutostartPolicy.shouldEnsureLaunchAgent( - mode: .local, - paused: paused) - { - Task { await GatewayProcessManager.shared.ensureLaunchAgentEnabledIfNeeded() } - } - _ = await GatewayProcessManager.shared.waitForGatewayReady() - } else { - GatewayProcessManager.shared.stop() - } - do { - try await ControlChannel.shared.configure(mode: .local) - } catch { - // Control channel will mark itself degraded; nothing else to do here. - self.logger.error( - "control channel local configure failed: \(error.localizedDescription, privacy: .public)") - } - Task.detached { await PortGuardian.shared.sweep(mode: .local) } - - case .remote: - // Never run a local gateway in remote mode. - GatewayProcessManager.shared.stop() - WebChatManager.shared.resetTunnels() - - do { - NodesStore.shared.lastError = nil - if let error = await NodeServiceManager.start() { - NodesStore.shared.lastError = "Node service start failed: \(error)" - } - _ = try await GatewayEndpointStore.shared.ensureRemoteControlTunnel() - let settings = CommandResolver.connectionSettings() - try await ControlChannel.shared.configure(mode: .remote( - target: settings.target, - identity: settings.identity)) - } catch { - self.logger.error("remote tunnel/configure failed: \(error.localizedDescription, privacy: .public)") - } - - Task.detached { await PortGuardian.shared.sweep(mode: .remote) } - } - } -} diff --git a/apps/macos/Sources/OpenClaw/ConnectionModeResolver.swift b/apps/macos/Sources/OpenClaw/ConnectionModeResolver.swift deleted file mode 100644 index 60c6fab9d56..00000000000 --- a/apps/macos/Sources/OpenClaw/ConnectionModeResolver.swift +++ /dev/null @@ -1,49 +0,0 @@ -import Foundation - -enum EffectiveConnectionModeSource: Sendable, Equatable { - case configMode - case configRemoteURL - case userDefaults - case onboarding -} - -struct EffectiveConnectionMode: Sendable, Equatable { - let mode: AppState.ConnectionMode - let source: EffectiveConnectionModeSource -} - -enum ConnectionModeResolver { - static func resolve( - root: [String: Any], - defaults: UserDefaults = .standard) -> EffectiveConnectionMode - { - let gateway = root["gateway"] as? [String: Any] - let configModeRaw = (gateway?["mode"] as? String) ?? "" - let configMode = configModeRaw - .trimmingCharacters(in: .whitespacesAndNewlines) - .lowercased() - - switch configMode { - case "local": - return EffectiveConnectionMode(mode: .local, source: .configMode) - case "remote": - return EffectiveConnectionMode(mode: .remote, source: .configMode) - default: - break - } - - let remoteURLRaw = ((gateway?["remote"] as? [String: Any])?["url"] as? String) ?? "" - let remoteURL = remoteURLRaw.trimmingCharacters(in: .whitespacesAndNewlines) - if !remoteURL.isEmpty { - return EffectiveConnectionMode(mode: .remote, source: .configRemoteURL) - } - - if let storedModeRaw = defaults.string(forKey: connectionModeKey) { - let storedMode = AppState.ConnectionMode(rawValue: storedModeRaw) ?? .local - return EffectiveConnectionMode(mode: storedMode, source: .userDefaults) - } - - let seen = defaults.bool(forKey: "openclaw.onboardingSeen") - return EffectiveConnectionMode(mode: seen ? .local : .unconfigured, source: .onboarding) - } -} diff --git a/apps/macos/Sources/OpenClaw/Constants.swift b/apps/macos/Sources/OpenClaw/Constants.swift deleted file mode 100644 index 7065702d688..00000000000 --- a/apps/macos/Sources/OpenClaw/Constants.swift +++ /dev/null @@ -1,48 +0,0 @@ -import Foundation - -// Stable identifier used for both the macOS LaunchAgent label and Nix-managed defaults suite. -// nix-openclaw writes app defaults into this suite to survive app bundle identifier churn. -let launchdLabel = "ai.openclaw.mac" -let gatewayLaunchdLabel = "ai.openclaw.gateway" -let onboardingVersionKey = "openclaw.onboardingVersion" -let onboardingSeenKey = "openclaw.onboardingSeen" -let currentOnboardingVersion = 7 -let pauseDefaultsKey = "openclaw.pauseEnabled" -let iconAnimationsEnabledKey = "openclaw.iconAnimationsEnabled" -let swabbleEnabledKey = "openclaw.swabbleEnabled" -let swabbleTriggersKey = "openclaw.swabbleTriggers" -let voiceWakeTriggerChimeKey = "openclaw.voiceWakeTriggerChime" -let voiceWakeSendChimeKey = "openclaw.voiceWakeSendChime" -let showDockIconKey = "openclaw.showDockIcon" -let defaultVoiceWakeTriggers = ["openclaw"] -let voiceWakeMaxWords = 32 -let voiceWakeMaxWordLength = 64 -let voiceWakeMicKey = "openclaw.voiceWakeMicID" -let voiceWakeMicNameKey = "openclaw.voiceWakeMicName" -let voiceWakeLocaleKey = "openclaw.voiceWakeLocaleID" -let voiceWakeAdditionalLocalesKey = "openclaw.voiceWakeAdditionalLocaleIDs" -let voicePushToTalkEnabledKey = "openclaw.voicePushToTalkEnabled" -let talkEnabledKey = "openclaw.talkEnabled" -let iconOverrideKey = "openclaw.iconOverride" -let connectionModeKey = "openclaw.connectionMode" -let remoteTargetKey = "openclaw.remoteTarget" -let remoteIdentityKey = "openclaw.remoteIdentity" -let remoteProjectRootKey = "openclaw.remoteProjectRoot" -let remoteCliPathKey = "openclaw.remoteCliPath" -let canvasEnabledKey = "openclaw.canvasEnabled" -let cameraEnabledKey = "openclaw.cameraEnabled" -let systemRunPolicyKey = "openclaw.systemRunPolicy" -let systemRunAllowlistKey = "openclaw.systemRunAllowlist" -let systemRunEnabledKey = "openclaw.systemRunEnabled" -let locationModeKey = "openclaw.locationMode" -let locationPreciseKey = "openclaw.locationPreciseEnabled" -let peekabooBridgeEnabledKey = "openclaw.peekabooBridgeEnabled" -let deepLinkKeyKey = "openclaw.deepLinkKey" -let modelCatalogPathKey = "openclaw.modelCatalogPath" -let modelCatalogReloadKey = "openclaw.modelCatalogReload" -let cliInstallPromptedVersionKey = "openclaw.cliInstallPromptedVersion" -let heartbeatsEnabledKey = "openclaw.heartbeatsEnabled" -let debugPaneEnabledKey = "openclaw.debugPaneEnabled" -let debugFileLogEnabledKey = "openclaw.debug.fileLogEnabled" -let appLogLevelKey = "openclaw.debug.appLogLevel" -let voiceWakeSupported: Bool = ProcessInfo.processInfo.operatingSystemVersion.majorVersion >= 26 diff --git a/apps/macos/Sources/OpenClaw/ContextMenuCardView.swift b/apps/macos/Sources/OpenClaw/ContextMenuCardView.swift deleted file mode 100644 index f9a11b9e512..00000000000 --- a/apps/macos/Sources/OpenClaw/ContextMenuCardView.swift +++ /dev/null @@ -1,120 +0,0 @@ -import Foundation -import SwiftUI - -/// Context usage card shown at the top of the menubar menu. -struct ContextMenuCardView: View { - private let rows: [SessionRow] - private let statusText: String? - private let isLoading: Bool - private let paddingTop: CGFloat = 8 - private let paddingBottom: CGFloat = 8 - private let paddingTrailing: CGFloat = 10 - private let paddingLeading: CGFloat = 20 - private let barHeight: CGFloat = 3 - - init( - rows: [SessionRow], - statusText: String? = nil, - isLoading: Bool = false) - { - self.rows = rows - self.statusText = statusText - self.isLoading = isLoading - } - - var body: some View { - VStack(alignment: .leading, spacing: 6) { - HStack(alignment: .firstTextBaseline) { - Text("Context") - .font(.caption.weight(.semibold)) - .foregroundStyle(.secondary) - Spacer(minLength: 10) - Text(self.subtitle) - .font(.caption) - .foregroundStyle(.secondary) - } - - if let statusText { - Text(statusText) - .font(.caption) - .foregroundStyle(.secondary) - } else if self.rows.isEmpty, !self.isLoading { - Text("No active sessions") - .font(.caption) - .foregroundStyle(.secondary) - } else { - VStack(alignment: .leading, spacing: 12) { - if self.rows.isEmpty, self.isLoading { - ForEach(0..<2, id: \.self) { _ in - self.placeholderRow - } - } else { - ForEach(self.rows) { row in - self.sessionRow(row) - } - } - } - } - } - .padding(.top, self.paddingTop) - .padding(.bottom, self.paddingBottom) - .padding(.leading, self.paddingLeading) - .padding(.trailing, self.paddingTrailing) - .frame(minWidth: 300, maxWidth: .infinity, alignment: .leading) - .transaction { txn in txn.animation = nil } - } - - private var subtitle: String { - let count = self.rows.count - if count == 1 { return "1 session · 24h" } - return "\(count) sessions · 24h" - } - - private func sessionRow(_ row: SessionRow) -> some View { - VStack(alignment: .leading, spacing: 5) { - ContextUsageBar( - usedTokens: row.tokens.total, - contextTokens: row.tokens.contextTokens, - height: self.barHeight) - - HStack(alignment: .firstTextBaseline, spacing: 8) { - Text(row.label) - .font(.caption.weight(row.key == "main" ? .semibold : .regular)) - .lineLimit(1) - .truncationMode(.middle) - .layoutPriority(1) - Spacer(minLength: 8) - Text(row.tokens.contextSummaryShort) - .font(.caption.monospacedDigit()) - .foregroundStyle(.secondary) - .lineLimit(1) - .fixedSize(horizontal: true, vertical: false) - .layoutPriority(2) - } - } - .padding(.vertical, 2) - } - - private var placeholderRow: some View { - VStack(alignment: .leading, spacing: 5) { - ContextUsageBar( - usedTokens: 0, - contextTokens: 200_000, - height: self.barHeight) - - HStack(alignment: .firstTextBaseline, spacing: 8) { - Text("main") - .font(.caption.weight(.semibold)) - .lineLimit(1) - .layoutPriority(1) - Spacer(minLength: 8) - Text("000k/000k") - .font(.caption.monospacedDigit()) - .foregroundStyle(.secondary) - .fixedSize(horizontal: true, vertical: false) - .layoutPriority(2) - } - .redacted(reason: .placeholder) - } - } -} diff --git a/apps/macos/Sources/OpenClaw/ContextUsageBar.swift b/apps/macos/Sources/OpenClaw/ContextUsageBar.swift deleted file mode 100644 index f5bfa0530b0..00000000000 --- a/apps/macos/Sources/OpenClaw/ContextUsageBar.swift +++ /dev/null @@ -1,93 +0,0 @@ -import SwiftUI - -struct ContextUsageBar: View { - let usedTokens: Int - let contextTokens: Int - var width: CGFloat? - var height: CGFloat = 6 - - private static let okGreen: NSColor = .init(name: nil) { appearance in - let base = NSColor.systemGreen - let match = appearance.bestMatch(from: [.aqua, .darkAqua]) - if match == .darkAqua { return base } - return base.blended(withFraction: 0.24, of: .black) ?? base - } - - private static let trackFill: NSColor = .init(name: nil) { appearance in - let match = appearance.bestMatch(from: [.aqua, .darkAqua]) - if match == .darkAqua { return NSColor.white.withAlphaComponent(0.14) } - return NSColor.black.withAlphaComponent(0.12) - } - - private static let trackStroke: NSColor = .init(name: nil) { appearance in - let match = appearance.bestMatch(from: [.aqua, .darkAqua]) - if match == .darkAqua { return NSColor.white.withAlphaComponent(0.22) } - return NSColor.black.withAlphaComponent(0.2) - } - - private var clampedFractionUsed: Double { - guard self.contextTokens > 0 else { return 0 } - return min(1, max(0, Double(self.usedTokens) / Double(self.contextTokens))) - } - - private var percentUsed: Int? { - guard self.contextTokens > 0, self.usedTokens > 0 else { return nil } - return min(100, Int(round(self.clampedFractionUsed * 100))) - } - - private var tint: Color { - guard let pct = self.percentUsed else { return .secondary } - if pct >= 95 { return Color(nsColor: .systemRed) } - if pct >= 80 { return Color(nsColor: .systemOrange) } - if pct >= 60 { return Color(nsColor: .systemYellow) } - return Color(nsColor: Self.okGreen) - } - - var body: some View { - let fraction = self.clampedFractionUsed - Group { - if let width = self.width, width > 0 { - self.barBody(width: width, fraction: fraction) - .frame(width: width, height: self.height) - } else { - GeometryReader { proxy in - self.barBody(width: proxy.size.width, fraction: fraction) - .frame(width: proxy.size.width, height: self.height) - } - .frame(height: self.height) - } - } - .accessibilityLabel("Context usage") - .accessibilityValue(self.accessibilityValue) - } - - private var accessibilityValue: String { - if self.contextTokens <= 0 { return "Unknown context window" } - let pct = Int(round(self.clampedFractionUsed * 100)) - return "\(pct) percent used" - } - - @ViewBuilder - private func barBody(width: CGFloat, fraction: Double) -> some View { - let radius = self.height / 2 - let trackFill = Color(nsColor: Self.trackFill) - let trackStroke = Color(nsColor: Self.trackStroke) - let fillWidth = max(1, floor(width * CGFloat(fraction))) - - ZStack(alignment: .leading) { - RoundedRectangle(cornerRadius: radius, style: .continuous) - .fill(trackFill) - .overlay { - RoundedRectangle(cornerRadius: radius, style: .continuous) - .strokeBorder(trackStroke, lineWidth: 0.75) - } - - RoundedRectangle(cornerRadius: radius, style: .continuous) - .fill(self.tint) - .frame(width: fillWidth) - .mask { - RoundedRectangle(cornerRadius: radius, style: .continuous) - } - } - } -} diff --git a/apps/macos/Sources/OpenClaw/ControlChannel.swift b/apps/macos/Sources/OpenClaw/ControlChannel.swift deleted file mode 100644 index 16b4d6d3ad4..00000000000 --- a/apps/macos/Sources/OpenClaw/ControlChannel.swift +++ /dev/null @@ -1,428 +0,0 @@ -import Foundation -import Observation -import OpenClawKit -import OpenClawProtocol -import SwiftUI - -struct ControlHeartbeatEvent: Codable { - let ts: Double - let status: String - let to: String? - let preview: String? - let durationMs: Double? - let hasMedia: Bool? - let reason: String? -} - -struct ControlAgentEvent: Codable, Sendable, Identifiable { - var id: String { - "\(self.runId)-\(self.seq)" - } - - let runId: String - let seq: Int - let stream: String - let ts: Double - let data: [String: OpenClawProtocol.AnyCodable] - let summary: String? -} - -enum ControlChannelError: Error, LocalizedError { - case disconnected - case badResponse(String) - - var errorDescription: String? { - switch self { - case .disconnected: "Control channel disconnected" - case let .badResponse(msg): msg - } - } -} - -@MainActor -@Observable -final class ControlChannel { - static let shared = ControlChannel() - - enum Mode { - case local - case remote(target: String, identity: String) - } - - enum ConnectionState: Equatable { - case disconnected - case connecting - case connected - case degraded(String) - } - - private(set) var state: ConnectionState = .disconnected { - didSet { - CanvasManager.shared.refreshDebugStatus() - guard oldValue != self.state else { return } - switch self.state { - case .connected: - self.logger.info("control channel state -> connected") - case .connecting: - self.logger.info("control channel state -> connecting") - case .disconnected: - self.logger.info("control channel state -> disconnected") - self.scheduleRecovery(reason: "disconnected") - case let .degraded(message): - let detail = message.isEmpty ? "degraded" : "degraded: \(message)" - self.logger.info("control channel state -> \(detail, privacy: .public)") - self.scheduleRecovery(reason: message) - } - } - } - - private(set) var lastPingMs: Double? - private(set) var authSourceLabel: String? - - private let logger = Logger(subsystem: "ai.openclaw", category: "control") - - private var eventTask: Task? - private var recoveryTask: Task? - private var lastRecoveryAt: Date? - - private init() { - self.startEventStream() - } - - func configure() async { - self.logger.info("control channel configure mode=local") - await self.refreshEndpoint(reason: "configure") - } - - func configure(mode: Mode = .local) async throws { - switch mode { - case .local: - await self.configure() - case let .remote(target, identity): - do { - _ = (target, identity) - let idSet = !identity.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty - self.logger.info( - "control channel configure mode=remote " + - "target=\(target, privacy: .public) identitySet=\(idSet, privacy: .public)") - self.state = .connecting - _ = try await GatewayEndpointStore.shared.ensureRemoteControlTunnel() - await self.refreshEndpoint(reason: "configure") - } catch { - self.state = .degraded(error.localizedDescription) - throw error - } - } - } - - func refreshEndpoint(reason: String) async { - self.logger.info("control channel refresh endpoint reason=\(reason, privacy: .public)") - self.state = .connecting - do { - try await self.establishGatewayConnection() - self.state = .connected - PresenceReporter.shared.sendImmediate(reason: "connect") - } catch { - let message = self.friendlyGatewayMessage(error) - self.state = .degraded(message) - } - } - - func disconnect() async { - await GatewayConnection.shared.shutdown() - self.state = .disconnected - self.lastPingMs = nil - self.authSourceLabel = nil - } - - func health(timeout: TimeInterval? = nil) async throws -> Data { - do { - let start = Date() - var params: [String: AnyHashable]? - if let timeout { - params = ["timeout": AnyHashable(Int(timeout * 1000))] - } - let timeoutMs = (timeout ?? 15) * 1000 - let payload = try await self.request(method: "health", params: params, timeoutMs: timeoutMs) - let ms = Date().timeIntervalSince(start) * 1000 - self.lastPingMs = ms - self.state = .connected - return payload - } catch { - let message = self.friendlyGatewayMessage(error) - self.state = .degraded(message) - throw ControlChannelError.badResponse(message) - } - } - - func lastHeartbeat() async throws -> ControlHeartbeatEvent? { - let data = try await self.request(method: "last-heartbeat") - return try JSONDecoder().decode(ControlHeartbeatEvent?.self, from: data) - } - - func request( - method: String, - params: [String: AnyHashable]? = nil, - timeoutMs: Double? = nil) async throws -> Data - { - do { - let rawParams = params?.reduce(into: [String: OpenClawKit.AnyCodable]()) { - $0[$1.key] = OpenClawKit.AnyCodable($1.value.base) - } - let data = try await GatewayConnection.shared.request( - method: method, - params: rawParams, - timeoutMs: timeoutMs) - self.state = .connected - return data - } catch { - let message = self.friendlyGatewayMessage(error) - self.state = .degraded(message) - throw ControlChannelError.badResponse(message) - } - } - - private func friendlyGatewayMessage(_ error: Error) -> String { - // Map URLSession/WS errors into user-facing, actionable text. - if let ctrlErr = error as? ControlChannelError, let desc = ctrlErr.errorDescription { - return desc - } - - // If the gateway explicitly rejects the hello (e.g., auth/token mismatch), surface it. - if let urlErr = error as? URLError, - urlErr.code == .dataNotAllowed // used for WS close 1008 auth failures - { - let reason = urlErr.failureURLString ?? urlErr.localizedDescription - let tokenKey = CommandResolver.connectionModeIsRemote() - ? "gateway.remote.token" - : "gateway.auth.token" - return - "Gateway rejected token; set \(tokenKey) or clear it on the gateway. Reason: \(reason)" - } - - // Common misfire: we connected to the configured localhost port but it is occupied - // by some other process (e.g. a local dev gateway or a stuck SSH forward). - // The gateway handshake returns something we can't parse, which currently - // surfaces as "hello failed (unexpected response)". Give the user a pointer - // to free the port instead of a vague message. - let nsError = error as NSError - if nsError.domain == "Gateway", - nsError.localizedDescription.contains("hello failed (unexpected response)") - { - let port = GatewayEnvironment.gatewayPort() - return """ - Gateway handshake got non-gateway data on localhost:\(port). - Another process is using that port or the SSH forward failed. - Stop the local gateway/port-forward on \(port) and retry Remote mode. - """ - } - - if let urlError = error as? URLError { - let port = GatewayEnvironment.gatewayPort() - switch urlError.code { - case .cancelled: - return "Gateway connection was closed; start the gateway (localhost:\(port)) and retry." - case .cannotFindHost, .cannotConnectToHost: - let isRemote = CommandResolver.connectionModeIsRemote() - if isRemote { - return """ - Cannot reach gateway at localhost:\(port). - Remote mode uses an SSH tunnel—check the SSH target and that the tunnel is running. - """ - } - return "Cannot reach gateway at localhost:\(port); ensure the gateway is running." - case .networkConnectionLost: - return "Gateway connection dropped; gateway likely restarted—retry." - case .timedOut: - return "Gateway request timed out; check gateway on localhost:\(port)." - case .notConnectedToInternet: - return "No network connectivity; cannot reach gateway." - default: - break - } - } - - if nsError.domain == "Gateway", nsError.code == 5 { - let port = GatewayEnvironment.gatewayPort() - return "Gateway request timed out; check the gateway process on localhost:\(port)." - } - - let detail = nsError.localizedDescription.isEmpty ? "unknown gateway error" : nsError.localizedDescription - let trimmed = detail.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.lowercased().hasPrefix("gateway error:") { return trimmed } - return "Gateway error: \(trimmed)" - } - - private func scheduleRecovery(reason: String) { - let now = Date() - if let last = self.lastRecoveryAt, now.timeIntervalSince(last) < 10 { return } - guard self.recoveryTask == nil else { return } - self.lastRecoveryAt = now - - self.recoveryTask = Task { [weak self] in - guard let self else { return } - let mode = await MainActor.run { AppStateStore.shared.connectionMode } - guard mode != .unconfigured else { - self.recoveryTask = nil - return - } - - let trimmedReason = reason.trimmingCharacters(in: .whitespacesAndNewlines) - let reasonText = trimmedReason.isEmpty ? "unknown" : trimmedReason - self.logger.info( - "control channel recovery starting " + - "mode=\(String(describing: mode), privacy: .public) " + - "reason=\(reasonText, privacy: .public)") - if mode == .local { - GatewayProcessManager.shared.setActive(true) - } - if mode == .remote { - do { - let port = try await GatewayEndpointStore.shared.ensureRemoteControlTunnel() - self.logger.info("control channel recovery ensured SSH tunnel port=\(port, privacy: .public)") - } catch { - self.logger.error( - "control channel recovery tunnel failed \(error.localizedDescription, privacy: .public)") - } - } - - await self.refreshEndpoint(reason: "recovery:\(reasonText)") - if case .connected = self.state { - self.logger.info("control channel recovery finished") - } else if case let .degraded(message) = self.state { - self.logger.error("control channel recovery failed \(message, privacy: .public)") - } - - self.recoveryTask = nil - } - } - - private func establishGatewayConnection(timeoutMs: Int = 5000) async throws { - try await GatewayConnection.shared.refresh() - let ok = try await GatewayConnection.shared.healthOK(timeoutMs: timeoutMs) - if ok == false { - throw NSError( - domain: "Gateway", - code: 0, - userInfo: [NSLocalizedDescriptionKey: "gateway health not ok"]) - } - await self.refreshAuthSourceLabel() - } - - private func refreshAuthSourceLabel() async { - let isRemote = CommandResolver.connectionModeIsRemote() - let authSource = await GatewayConnection.shared.authSource() - self.authSourceLabel = Self.formatAuthSource(authSource, isRemote: isRemote) - } - - private static func formatAuthSource(_ source: GatewayAuthSource?, isRemote: Bool) -> String? { - guard let source else { return nil } - switch source { - case .deviceToken: - return "Auth: device token (paired device)" - case .sharedToken: - return "Auth: shared token (\(isRemote ? "gateway.remote.token" : "gateway.auth.token"))" - case .password: - return "Auth: password (\(isRemote ? "gateway.remote.password" : "gateway.auth.password"))" - case .none: - return "Auth: none" - } - } - - func sendSystemEvent(_ text: String, params: [String: AnyHashable] = [:]) async throws { - var merged = params - merged["text"] = AnyHashable(text) - _ = try await self.request(method: "system-event", params: merged) - } - - private func startEventStream() { - self.eventTask?.cancel() - self.eventTask = Task { [weak self] in - guard let self else { return } - let stream = await GatewayConnection.shared.subscribe() - for await push in stream { - if Task.isCancelled { return } - await MainActor.run { [weak self] in - self?.handle(push: push) - } - } - } - } - - private func handle(push: GatewayPush) { - switch push { - case let .event(evt) where evt.event == "agent": - if let payload = evt.payload, - let agent = try? GatewayPayloadDecoding.decode(payload, as: ControlAgentEvent.self) - { - AgentEventStore.shared.append(agent) - self.routeWorkActivity(from: agent) - } - case let .event(evt) where evt.event == "heartbeat": - if let payload = evt.payload, - let heartbeat = try? GatewayPayloadDecoding.decode(payload, as: ControlHeartbeatEvent.self), - let data = try? JSONEncoder().encode(heartbeat) - { - NotificationCenter.default.post(name: .controlHeartbeat, object: data) - } - case let .event(evt) where evt.event == "shutdown": - self.state = .degraded("gateway shutdown") - case .snapshot: - self.state = .connected - default: - break - } - } - - private func routeWorkActivity(from event: ControlAgentEvent) { - // We currently treat VoiceWake as the "main" session for UI purposes. - // In the future, the gateway can include a sessionKey to distinguish runs. - let sessionKey = (event.data["sessionKey"]?.value as? String) ?? "main" - - switch event.stream.lowercased() { - case "job": - if let state = event.data["state"]?.value as? String { - WorkActivityStore.shared.handleJob(sessionKey: sessionKey, state: state) - } - case "tool": - let phase = event.data["phase"]?.value as? String ?? "" - let name = event.data["name"]?.value as? String - let meta = event.data["meta"]?.value as? String - let args = Self.bridgeToProtocolArgs(event.data["args"]) - WorkActivityStore.shared.handleTool( - sessionKey: sessionKey, - phase: phase, - name: name, - meta: meta, - args: args) - default: - break - } - } - - private static func bridgeToProtocolArgs( - _ value: OpenClawProtocol.AnyCodable?) -> [String: OpenClawProtocol.AnyCodable]? - { - guard let value else { return nil } - if let dict = value.value as? [String: OpenClawProtocol.AnyCodable] { - return dict - } - if let dict = value.value as? [String: OpenClawKit.AnyCodable], - let data = try? JSONEncoder().encode(dict), - let decoded = try? JSONDecoder().decode([String: OpenClawProtocol.AnyCodable].self, from: data) - { - return decoded - } - if let data = try? JSONEncoder().encode(value), - let decoded = try? JSONDecoder().decode([String: OpenClawProtocol.AnyCodable].self, from: data) - { - return decoded - } - return nil - } -} - -extension Notification.Name { - static let controlHeartbeat = Notification.Name("openclaw.control.heartbeat") - static let controlAgentEvent = Notification.Name("openclaw.control.agent") -} diff --git a/apps/macos/Sources/OpenClaw/CostUsageMenuView.swift b/apps/macos/Sources/OpenClaw/CostUsageMenuView.swift deleted file mode 100644 index c94a4de3518..00000000000 --- a/apps/macos/Sources/OpenClaw/CostUsageMenuView.swift +++ /dev/null @@ -1,99 +0,0 @@ -import Charts -import SwiftUI - -struct CostUsageHistoryMenuView: View { - let summary: GatewayCostUsageSummary - let width: CGFloat - - var body: some View { - VStack(alignment: .leading, spacing: 10) { - self.header - self.chart - self.footer - } - .padding(.horizontal, 12) - .padding(.vertical, 10) - .frame(width: max(1, self.width), alignment: .leading) - } - - private var header: some View { - let todayKey = CostUsageMenuDateParser.format(Date()) - let todayEntry = self.summary.daily.first { $0.date == todayKey } - let todayCost = CostUsageFormatting.formatUsd(todayEntry?.totalCost) ?? "n/a" - let totalCost = CostUsageFormatting.formatUsd(self.summary.totals.totalCost) ?? "n/a" - - return HStack(alignment: .firstTextBaseline, spacing: 12) { - VStack(alignment: .leading, spacing: 2) { - Text("Today") - .font(.caption2) - .foregroundStyle(.secondary) - Text(todayCost) - .font(.system(size: 14, weight: .semibold)) - } - VStack(alignment: .leading, spacing: 2) { - Text("Last \(self.summary.days)d") - .font(.caption2) - .foregroundStyle(.secondary) - Text(totalCost) - .font(.system(size: 14, weight: .semibold)) - } - Spacer() - } - } - - private var chart: some View { - let entries = self.summary.daily.compactMap { entry -> (Date, Double)? in - guard let date = CostUsageMenuDateParser.parse(entry.date) else { return nil } - return (date, entry.totalCost) - } - - return Chart(entries, id: \.0) { entry in - BarMark( - x: .value("Day", entry.0), - y: .value("Cost", entry.1)) - .foregroundStyle(Color.accentColor) - .cornerRadius(3) - } - .chartXAxis { - AxisMarks(values: .stride(by: .day, count: 7)) { - AxisGridLine().foregroundStyle(.clear) - AxisValueLabel(format: .dateTime.month().day()) - } - } - .chartYAxis { - AxisMarks(position: .leading) { - AxisGridLine() - AxisValueLabel() - } - } - .frame(height: 110) - } - - private var footer: some View { - if self.summary.totals.missingCostEntries == 0 { - return AnyView(EmptyView()) - } - return AnyView( - Text("Partial: \(self.summary.totals.missingCostEntries) entries missing cost") - .font(.caption2) - .foregroundStyle(.secondary)) - } -} - -private enum CostUsageMenuDateParser { - static let formatter: DateFormatter = { - let formatter = DateFormatter() - formatter.dateFormat = "yyyy-MM-dd" - formatter.locale = Locale(identifier: "en_US_POSIX") - formatter.timeZone = TimeZone.current - return formatter - }() - - static func parse(_ value: String) -> Date? { - self.formatter.date(from: value) - } - - static func format(_ date: Date) -> String { - self.formatter.string(from: date) - } -} diff --git a/apps/macos/Sources/OpenClaw/CritterIconRenderer.swift b/apps/macos/Sources/OpenClaw/CritterIconRenderer.swift deleted file mode 100644 index 0309461965c..00000000000 --- a/apps/macos/Sources/OpenClaw/CritterIconRenderer.swift +++ /dev/null @@ -1,387 +0,0 @@ -import AppKit - -enum CritterIconRenderer { - private static let size = NSSize(width: 18, height: 18) - - struct Badge { - let symbolName: String - let prominence: IconState.BadgeProminence - } - - private struct Canvas { - let w: CGFloat - let h: CGFloat - let stepX: CGFloat - let stepY: CGFloat - let snapX: (CGFloat) -> CGFloat - let snapY: (CGFloat) -> CGFloat - let context: CGContext - } - - private struct Geometry { - let bodyRect: CGRect - let bodyCorner: CGFloat - let leftEarRect: CGRect - let rightEarRect: CGRect - let earCorner: CGFloat - let earW: CGFloat - let earH: CGFloat - let legW: CGFloat - let legH: CGFloat - let legSpacing: CGFloat - let legStartX: CGFloat - let legYBase: CGFloat - let legLift: CGFloat - let legHeightScale: CGFloat - let eyeW: CGFloat - let eyeY: CGFloat - let eyeOffset: CGFloat - - init(canvas: Canvas, legWiggle: CGFloat, earWiggle: CGFloat, earScale: CGFloat) { - let w = canvas.w - let h = canvas.h - let snapX = canvas.snapX - let snapY = canvas.snapY - - let bodyW = snapX(w * 0.78) - let bodyH = snapY(h * 0.58) - let bodyX = snapX((w - bodyW) / 2) - let bodyY = snapY(h * 0.36) - let bodyCorner = snapX(w * 0.09) - - let earW = snapX(w * 0.22) - let earH = snapY(bodyH * 0.54 * earScale * (1 - 0.08 * abs(earWiggle))) - let earCorner = snapX(earW * 0.24) - let leftEarRect = CGRect( - x: snapX(bodyX - earW * 0.55 + earWiggle), - y: snapY(bodyY + bodyH * 0.08 + earWiggle * 0.4), - width: earW, - height: earH) - let rightEarRect = CGRect( - x: snapX(bodyX + bodyW - earW * 0.45 - earWiggle), - y: snapY(bodyY + bodyH * 0.08 - earWiggle * 0.4), - width: earW, - height: earH) - - let legW = snapX(w * 0.11) - let legH = snapY(h * 0.26) - let legSpacing = snapX(w * 0.085) - let legsWidth = snapX(4 * legW + 3 * legSpacing) - let legStartX = snapX((w - legsWidth) / 2) - let legLift = snapY(legH * 0.35 * legWiggle) - let legYBase = snapY(bodyY - legH + h * 0.05) - let legHeightScale = 1 - 0.12 * legWiggle - - let eyeW = snapX(bodyW * 0.2) - let eyeY = snapY(bodyY + bodyH * 0.56) - let eyeOffset = snapX(bodyW * 0.24) - - self.bodyRect = CGRect(x: bodyX, y: bodyY, width: bodyW, height: bodyH) - self.bodyCorner = bodyCorner - self.leftEarRect = leftEarRect - self.rightEarRect = rightEarRect - self.earCorner = earCorner - self.earW = earW - self.earH = earH - self.legW = legW - self.legH = legH - self.legSpacing = legSpacing - self.legStartX = legStartX - self.legYBase = legYBase - self.legLift = legLift - self.legHeightScale = legHeightScale - self.eyeW = eyeW - self.eyeY = eyeY - self.eyeOffset = eyeOffset - } - } - - private struct FaceOptions { - let blink: CGFloat - let earHoles: Bool - let earScale: CGFloat - let eyesClosedLines: Bool - } - - static func makeIcon( - blink: CGFloat, - legWiggle: CGFloat = 0, - earWiggle: CGFloat = 0, - earScale: CGFloat = 1, - earHoles: Bool = false, - eyesClosedLines: Bool = false, - badge: Badge? = nil) -> NSImage - { - guard let rep = self.makeBitmapRep() else { - return NSImage(size: self.size) - } - rep.size = self.size - - NSGraphicsContext.saveGraphicsState() - defer { NSGraphicsContext.restoreGraphicsState() } - - guard let context = NSGraphicsContext(bitmapImageRep: rep) else { - return NSImage(size: self.size) - } - NSGraphicsContext.current = context - context.imageInterpolation = .none - context.cgContext.setShouldAntialias(false) - - let canvas = self.makeCanvas(for: rep, context: context) - let geometry = Geometry(canvas: canvas, legWiggle: legWiggle, earWiggle: earWiggle, earScale: earScale) - - self.drawBody(in: canvas, geometry: geometry) - let face = FaceOptions( - blink: blink, - earHoles: earHoles, - earScale: earScale, - eyesClosedLines: eyesClosedLines) - self.drawFace(in: canvas, geometry: geometry, options: face) - - if let badge { - self.drawBadge(badge, canvas: canvas) - } - - let image = NSImage(size: size) - image.addRepresentation(rep) - image.isTemplate = true - return image - } - - private static func makeBitmapRep() -> NSBitmapImageRep? { - // Force a 36×36px backing store (2× for the 18pt logical canvas) so the menu bar icon stays crisp on Retina. - let pixelsWide = 36 - let pixelsHigh = 36 - return NSBitmapImageRep( - bitmapDataPlanes: nil, - pixelsWide: pixelsWide, - pixelsHigh: pixelsHigh, - bitsPerSample: 8, - samplesPerPixel: 4, - hasAlpha: true, - isPlanar: false, - colorSpaceName: .deviceRGB, - bitmapFormat: [], - bytesPerRow: 0, - bitsPerPixel: 0) - } - - private static func makeCanvas(for rep: NSBitmapImageRep, context: NSGraphicsContext) -> Canvas { - let stepX = self.size.width / max(CGFloat(rep.pixelsWide), 1) - let stepY = self.size.height / max(CGFloat(rep.pixelsHigh), 1) - let snapX: (CGFloat) -> CGFloat = { ($0 / stepX).rounded() * stepX } - let snapY: (CGFloat) -> CGFloat = { ($0 / stepY).rounded() * stepY } - - let w = snapX(size.width) - let h = snapY(size.height) - - return Canvas( - w: w, - h: h, - stepX: stepX, - stepY: stepY, - snapX: snapX, - snapY: snapY, - context: context.cgContext) - } - - private static func drawBody(in canvas: Canvas, geometry: Geometry) { - canvas.context.setFillColor(NSColor.labelColor.cgColor) - - canvas.context.addPath(CGPath( - roundedRect: geometry.bodyRect, - cornerWidth: geometry.bodyCorner, - cornerHeight: geometry.bodyCorner, - transform: nil)) - canvas.context.addPath(CGPath( - roundedRect: geometry.leftEarRect, - cornerWidth: geometry.earCorner, - cornerHeight: geometry.earCorner, - transform: nil)) - canvas.context.addPath(CGPath( - roundedRect: geometry.rightEarRect, - cornerWidth: geometry.earCorner, - cornerHeight: geometry.earCorner, - transform: nil)) - - for i in 0..<4 { - let x = geometry.legStartX + CGFloat(i) * (geometry.legW + geometry.legSpacing) - let lift = i % 2 == 0 ? geometry.legLift : -geometry.legLift - let rect = CGRect( - x: x, - y: geometry.legYBase + lift, - width: geometry.legW, - height: geometry.legH * geometry.legHeightScale) - canvas.context.addPath(CGPath( - roundedRect: rect, - cornerWidth: geometry.legW * 0.34, - cornerHeight: geometry.legW * 0.34, - transform: nil)) - } - canvas.context.fillPath() - } - - private static func drawFace( - in canvas: Canvas, - geometry: Geometry, - options: FaceOptions) - { - canvas.context.saveGState() - canvas.context.setBlendMode(.clear) - - let leftCenter = CGPoint( - x: canvas.snapX(canvas.w / 2 - geometry.eyeOffset), - y: canvas.snapY(geometry.eyeY)) - let rightCenter = CGPoint( - x: canvas.snapX(canvas.w / 2 + geometry.eyeOffset), - y: canvas.snapY(geometry.eyeY)) - - if options.earHoles || options.earScale > 1.05 { - let holeW = canvas.snapX(geometry.earW * 0.6) - let holeH = canvas.snapY(geometry.earH * 0.46) - let holeCorner = canvas.snapX(holeW * 0.34) - let leftHoleRect = CGRect( - x: canvas.snapX(geometry.leftEarRect.midX - holeW / 2), - y: canvas.snapY(geometry.leftEarRect.midY - holeH / 2 + geometry.earH * 0.04), - width: holeW, - height: holeH) - let rightHoleRect = CGRect( - x: canvas.snapX(geometry.rightEarRect.midX - holeW / 2), - y: canvas.snapY(geometry.rightEarRect.midY - holeH / 2 + geometry.earH * 0.04), - width: holeW, - height: holeH) - - canvas.context.addPath(CGPath( - roundedRect: leftHoleRect, - cornerWidth: holeCorner, - cornerHeight: holeCorner, - transform: nil)) - canvas.context.addPath(CGPath( - roundedRect: rightHoleRect, - cornerWidth: holeCorner, - cornerHeight: holeCorner, - transform: nil)) - } - - if options.eyesClosedLines { - let lineW = canvas.snapX(geometry.eyeW * 0.95) - let lineH = canvas.snapY(max(canvas.stepY * 2, geometry.bodyRect.height * 0.06)) - let corner = canvas.snapX(lineH * 0.6) - let leftRect = CGRect( - x: canvas.snapX(leftCenter.x - lineW / 2), - y: canvas.snapY(leftCenter.y - lineH / 2), - width: lineW, - height: lineH) - let rightRect = CGRect( - x: canvas.snapX(rightCenter.x - lineW / 2), - y: canvas.snapY(rightCenter.y - lineH / 2), - width: lineW, - height: lineH) - canvas.context.addPath(CGPath( - roundedRect: leftRect, - cornerWidth: corner, - cornerHeight: corner, - transform: nil)) - canvas.context.addPath(CGPath( - roundedRect: rightRect, - cornerWidth: corner, - cornerHeight: corner, - transform: nil)) - } else { - let eyeOpen = max(0.05, 1 - options.blink) - let eyeH = canvas.snapY(geometry.bodyRect.height * 0.26 * eyeOpen) - - let left = CGMutablePath() - left.move(to: CGPoint( - x: canvas.snapX(leftCenter.x - geometry.eyeW / 2), - y: canvas.snapY(leftCenter.y - eyeH))) - left.addLine(to: CGPoint( - x: canvas.snapX(leftCenter.x + geometry.eyeW / 2), - y: canvas.snapY(leftCenter.y))) - left.addLine(to: CGPoint( - x: canvas.snapX(leftCenter.x - geometry.eyeW / 2), - y: canvas.snapY(leftCenter.y + eyeH))) - left.closeSubpath() - - let right = CGMutablePath() - right.move(to: CGPoint( - x: canvas.snapX(rightCenter.x + geometry.eyeW / 2), - y: canvas.snapY(rightCenter.y - eyeH))) - right.addLine(to: CGPoint( - x: canvas.snapX(rightCenter.x - geometry.eyeW / 2), - y: canvas.snapY(rightCenter.y))) - right.addLine(to: CGPoint( - x: canvas.snapX(rightCenter.x + geometry.eyeW / 2), - y: canvas.snapY(rightCenter.y + eyeH))) - right.closeSubpath() - - canvas.context.addPath(left) - canvas.context.addPath(right) - } - - canvas.context.fillPath() - canvas.context.restoreGState() - } - - private static func drawBadge(_ badge: Badge, canvas: Canvas) { - let strength: CGFloat = switch badge.prominence { - case .primary: 1.0 - case .secondary: 0.58 - case .overridden: 0.85 - } - - // Bigger, higher-contrast badge: - // - Increase diameter so tool activity is noticeable. - // - Draw a filled "puck", then knock out the symbol shape (transparent hole). - // This reads better in template-rendered menu bar icons than tiny monochrome glyphs. - let diameter = canvas.snapX(canvas.w * 0.52 * (0.92 + 0.08 * strength)) // ~9–10pt on an 18pt canvas - let margin = canvas.snapX(max(0.45, canvas.w * 0.03)) - let rect = CGRect( - x: canvas.snapX(canvas.w - diameter - margin), - y: canvas.snapY(margin), - width: diameter, - height: diameter) - - canvas.context.saveGState() - canvas.context.setShouldAntialias(true) - - // Clear the underlying pixels so the badge stays readable over the critter. - canvas.context.saveGState() - canvas.context.setBlendMode(.clear) - canvas.context.addEllipse(in: rect.insetBy(dx: -1.0, dy: -1.0)) - canvas.context.fillPath() - canvas.context.restoreGState() - - let fillAlpha: CGFloat = min(1.0, 0.36 + 0.24 * strength) - let strokeAlpha: CGFloat = min(1.0, 0.78 + 0.22 * strength) - - canvas.context.setFillColor(NSColor.labelColor.withAlphaComponent(fillAlpha).cgColor) - canvas.context.addEllipse(in: rect) - canvas.context.fillPath() - - canvas.context.setStrokeColor(NSColor.labelColor.withAlphaComponent(strokeAlpha).cgColor) - canvas.context.setLineWidth(max(1.25, canvas.snapX(canvas.w * 0.075))) - canvas.context.strokeEllipse(in: rect.insetBy(dx: 0.45, dy: 0.45)) - - if let base = NSImage(systemSymbolName: badge.symbolName, accessibilityDescription: nil) { - let pointSize = max(7.0, diameter * 0.82) - let config = NSImage.SymbolConfiguration(pointSize: pointSize, weight: .black) - let symbol = base.withSymbolConfiguration(config) ?? base - symbol.isTemplate = true - - let symbolRect = rect.insetBy(dx: diameter * 0.17, dy: diameter * 0.17) - canvas.context.saveGState() - canvas.context.setBlendMode(.clear) - symbol.draw( - in: symbolRect, - from: .zero, - operation: .sourceOver, - fraction: 1, - respectFlipped: true, - hints: nil) - canvas.context.restoreGState() - } - - canvas.context.restoreGState() - } -} diff --git a/apps/macos/Sources/OpenClaw/CritterStatusLabel+Behavior.swift b/apps/macos/Sources/OpenClaw/CritterStatusLabel+Behavior.swift deleted file mode 100644 index e1145c4e393..00000000000 --- a/apps/macos/Sources/OpenClaw/CritterStatusLabel+Behavior.swift +++ /dev/null @@ -1,305 +0,0 @@ -import AppKit -import SwiftUI - -extension CritterStatusLabel { - private var isWorkingNow: Bool { - self.iconState.isWorking || self.isWorking - } - - private var effectiveAnimationsEnabled: Bool { - self.animationsEnabled && !self.isSleeping - } - - var body: some View { - ZStack(alignment: .topTrailing) { - self.iconImage - .frame(width: 18, height: 18) - .rotationEffect(.degrees(self.wiggleAngle), anchor: .center) - .offset(x: self.wiggleOffset) - // Avoid Combine's TimerPublisher here: on macOS 26.2 we've seen crashes inside executor checks - // triggered by its callbacks. Drive periodic updates via a Swift-concurrency task instead. - .task(id: self.tickTaskID) { - guard self.effectiveAnimationsEnabled, !self.earBoostActive else { - await MainActor.run { self.resetMotion() } - return - } - - while !Task.isCancelled { - let now = Date() - await MainActor.run { self.tick(now) } - try? await Task.sleep(nanoseconds: 350_000_000) - } - } - .onChange(of: self.isPaused) { _, _ in self.resetMotion() } - .onChange(of: self.blinkTick) { _, _ in - guard self.effectiveAnimationsEnabled, !self.earBoostActive else { return } - self.blink() - } - .onChange(of: self.sendCelebrationTick) { _, _ in - guard self.effectiveAnimationsEnabled, !self.earBoostActive else { return } - self.wiggleLegs() - } - .onChange(of: self.animationsEnabled) { _, enabled in - if enabled, !self.isSleeping { - self.scheduleRandomTimers(from: Date()) - } else { - self.resetMotion() - } - } - .onChange(of: self.isSleeping) { _, _ in - self.resetMotion() - } - .onChange(of: self.earBoostActive) { _, active in - if active { - self.resetMotion() - } else if self.effectiveAnimationsEnabled { - self.scheduleRandomTimers(from: Date()) - } - } - - if self.gatewayNeedsAttention { - Circle() - .fill(self.gatewayBadgeColor) - .frame(width: 6, height: 6) - .padding(1) - } - } - .frame(width: 18, height: 18) - } - - private var tickTaskID: Int { - // Ensure SwiftUI restarts (and cancels) the task when these change. - (self.effectiveAnimationsEnabled ? 1 : 0) | (self.earBoostActive ? 2 : 0) - } - - private func tick(_ now: Date) { - guard self.effectiveAnimationsEnabled, !self.earBoostActive else { - self.resetMotion() - return - } - - if now >= self.nextBlink { - self.blink() - self.nextBlink = now.addingTimeInterval(Double.random(in: 3.5...8.5)) - } - - if now >= self.nextWiggle { - self.wiggle() - self.nextWiggle = now.addingTimeInterval(Double.random(in: 6.5...14)) - } - - if now >= self.nextLegWiggle { - self.wiggleLegs() - self.nextLegWiggle = now.addingTimeInterval(Double.random(in: 5.0...11.0)) - } - - if now >= self.nextEarWiggle { - self.wiggleEars() - self.nextEarWiggle = now.addingTimeInterval(Double.random(in: 7.0...14.0)) - } - - if self.isWorkingNow { - self.scurry() - } - } - - private var iconImage: Image { - let badge: CritterIconRenderer.Badge? = if let prominence = self.iconState.badgeProminence, !self.isPaused { - CritterIconRenderer.Badge( - symbolName: self.iconState.badgeSymbolName, - prominence: prominence) - } else { - nil - } - - if self.isPaused { - return Image(nsImage: CritterIconRenderer.makeIcon(blink: 0, badge: nil)) - } - - if self.isSleeping { - return Image(nsImage: CritterIconRenderer.makeIcon(blink: 1, eyesClosedLines: true, badge: nil)) - } - - return Image(nsImage: CritterIconRenderer.makeIcon( - blink: self.blinkAmount, - legWiggle: max(self.legWiggle, self.isWorkingNow ? 0.6 : 0), - earWiggle: self.earWiggle, - earScale: self.earBoostActive ? 1.9 : 1.0, - earHoles: self.earBoostActive, - badge: badge)) - } - - private func resetMotion() { - self.blinkAmount = 0 - self.wiggleAngle = 0 - self.wiggleOffset = 0 - self.legWiggle = 0 - self.earWiggle = 0 - } - - private func blink() { - withAnimation(.easeInOut(duration: 0.08)) { self.blinkAmount = 1 } - Task { @MainActor in - try? await Task.sleep(nanoseconds: 160_000_000) - withAnimation(.easeOut(duration: 0.12)) { self.blinkAmount = 0 } - } - } - - private func wiggle() { - let targetAngle = Double.random(in: -4.5...4.5) - let targetOffset = CGFloat.random(in: -0.5...0.5) - withAnimation(.interpolatingSpring(stiffness: 220, damping: 18)) { - self.wiggleAngle = targetAngle - self.wiggleOffset = targetOffset - } - Task { @MainActor in - try? await Task.sleep(nanoseconds: 360_000_000) - withAnimation(.interpolatingSpring(stiffness: 220, damping: 18)) { - self.wiggleAngle = 0 - self.wiggleOffset = 0 - } - } - } - - private func wiggleLegs() { - let target = CGFloat.random(in: 0.35...0.9) - withAnimation(.easeInOut(duration: 0.14)) { - self.legWiggle = target - } - Task { @MainActor in - try? await Task.sleep(nanoseconds: 220_000_000) - withAnimation(.easeOut(duration: 0.18)) { self.legWiggle = 0 } - } - } - - private func scurry() { - let target = CGFloat.random(in: 0.7...1.0) - withAnimation(.easeInOut(duration: 0.12)) { - self.legWiggle = target - self.wiggleOffset = CGFloat.random(in: -0.6...0.6) - } - Task { @MainActor in - try? await Task.sleep(nanoseconds: 180_000_000) - withAnimation(.easeOut(duration: 0.16)) { - self.legWiggle = 0.25 - self.wiggleOffset = 0 - } - } - } - - private func wiggleEars() { - let target = CGFloat.random(in: -1.2...1.2) - withAnimation(.interpolatingSpring(stiffness: 260, damping: 19)) { - self.earWiggle = target - } - Task { @MainActor in - try? await Task.sleep(nanoseconds: 320_000_000) - withAnimation(.interpolatingSpring(stiffness: 260, damping: 19)) { - self.earWiggle = 0 - } - } - } - - private func scheduleRandomTimers(from date: Date) { - self.nextBlink = date.addingTimeInterval(Double.random(in: 3.5...8.5)) - self.nextWiggle = date.addingTimeInterval(Double.random(in: 6.5...14)) - self.nextLegWiggle = date.addingTimeInterval(Double.random(in: 5.0...11.0)) - self.nextEarWiggle = date.addingTimeInterval(Double.random(in: 7.0...14.0)) - } - - private var gatewayNeedsAttention: Bool { - if self.isSleeping { return false } - switch self.gatewayStatus { - case .failed, .stopped: - return !self.isPaused - case .starting, .running, .attachedExisting: - return false - } - } - - private var gatewayBadgeColor: Color { - switch self.gatewayStatus { - case .failed: .red - case .stopped: .orange - default: .clear - } - } -} - -#if DEBUG -@MainActor -extension CritterStatusLabel { - static func exerciseForTesting() async { - var label = CritterStatusLabel( - isPaused: false, - isSleeping: false, - isWorking: true, - earBoostActive: false, - blinkTick: 1, - sendCelebrationTick: 1, - gatewayStatus: .running(details: nil), - animationsEnabled: true, - iconState: .workingMain(.tool(.bash))) - - _ = label.body - _ = label.iconImage - _ = label.tickTaskID - label.tick(Date()) - label.resetMotion() - label.blink() - label.wiggle() - label.wiggleLegs() - label.wiggleEars() - label.scurry() - label.scheduleRandomTimers(from: Date()) - _ = label.gatewayNeedsAttention - _ = label.gatewayBadgeColor - - label.isPaused = true - _ = label.iconImage - - label.isPaused = false - label.isSleeping = true - _ = label.iconImage - - label.isSleeping = false - label.iconState = .idle - _ = label.iconImage - - let failed = CritterStatusLabel( - isPaused: false, - isSleeping: false, - isWorking: false, - earBoostActive: false, - blinkTick: 0, - sendCelebrationTick: 0, - gatewayStatus: .failed("boom"), - animationsEnabled: false, - iconState: .idle) - _ = failed.gatewayNeedsAttention - _ = failed.gatewayBadgeColor - - let stopped = CritterStatusLabel( - isPaused: false, - isSleeping: false, - isWorking: false, - earBoostActive: false, - blinkTick: 0, - sendCelebrationTick: 0, - gatewayStatus: .stopped, - animationsEnabled: false, - iconState: .idle) - _ = stopped.gatewayNeedsAttention - _ = stopped.gatewayBadgeColor - - _ = CritterIconRenderer.makeIcon( - blink: 0.6, - legWiggle: 0.8, - earWiggle: 0.4, - earScale: 1.4, - earHoles: true, - eyesClosedLines: true, - badge: .init(symbolName: "gearshape.fill", prominence: .secondary)) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/CritterStatusLabel.swift b/apps/macos/Sources/OpenClaw/CritterStatusLabel.swift deleted file mode 100644 index beeffdf8dd7..00000000000 --- a/apps/macos/Sources/OpenClaw/CritterStatusLabel.swift +++ /dev/null @@ -1,23 +0,0 @@ -import SwiftUI - -struct CritterStatusLabel: View { - var isPaused: Bool - var isSleeping: Bool - var isWorking: Bool - var earBoostActive: Bool - var blinkTick: Int - var sendCelebrationTick: Int - var gatewayStatus: GatewayProcessManager.Status - var animationsEnabled: Bool - var iconState: IconState - - @State var blinkAmount: CGFloat = 0 - @State var nextBlink = Date().addingTimeInterval(Double.random(in: 3.5...8.5)) - @State var wiggleAngle: Double = 0 - @State var wiggleOffset: CGFloat = 0 - @State var nextWiggle = Date().addingTimeInterval(Double.random(in: 6.5...14)) - @State var legWiggle: CGFloat = 0 - @State var nextLegWiggle = Date().addingTimeInterval(Double.random(in: 5.0...11.0)) - @State var earWiggle: CGFloat = 0 - @State var nextEarWiggle = Date().addingTimeInterval(Double.random(in: 7.0...14.0)) -} diff --git a/apps/macos/Sources/OpenClaw/CronJobEditor+Helpers.swift b/apps/macos/Sources/OpenClaw/CronJobEditor+Helpers.swift deleted file mode 100644 index 6b3fc85a7c0..00000000000 --- a/apps/macos/Sources/OpenClaw/CronJobEditor+Helpers.swift +++ /dev/null @@ -1,271 +0,0 @@ -import Foundation -import OpenClawProtocol -import SwiftUI - -extension CronJobEditor { - func gridLabel(_ text: String) -> some View { - Text(text) - .foregroundStyle(.secondary) - .frame(width: self.labelColumnWidth, alignment: .leading) - } - - func hydrateFromJob() { - guard let job else { return } - self.name = job.name - self.description = job.description ?? "" - self.agentId = job.agentId ?? "" - self.enabled = job.enabled - self.deleteAfterRun = job.deleteAfterRun ?? false - self.sessionTarget = job.sessionTarget - self.wakeMode = job.wakeMode - - switch job.schedule { - case let .at(at): - self.scheduleKind = .at - if let date = CronSchedule.parseAtDate(at) { - self.atDate = date - } - case let .every(everyMs, _): - self.scheduleKind = .every - self.everyText = self.formatDuration(ms: everyMs) - case let .cron(expr, tz): - self.scheduleKind = .cron - self.cronExpr = expr - self.cronTz = tz ?? "" - } - - switch job.payload { - case let .systemEvent(text): - self.payloadKind = .systemEvent - self.systemEventText = text - case let .agentTurn(message, thinking, timeoutSeconds, _, _, _, _): - self.payloadKind = .agentTurn - self.agentMessage = message - self.thinking = thinking ?? "" - self.timeoutSeconds = timeoutSeconds.map(String.init) ?? "" - } - - if let delivery = job.delivery { - self.deliveryMode = delivery.mode == .announce ? .announce : .none - let trimmed = (delivery.channel ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - self.channel = trimmed.isEmpty ? "last" : trimmed - self.to = delivery.to ?? "" - self.bestEffortDeliver = delivery.bestEffort ?? false - } else if self.sessionTarget == .isolated { - self.deliveryMode = .announce - } - } - - func save() { - do { - self.error = nil - let payload = try self.buildPayload() - self.onSave(payload) - } catch { - self.error = error.localizedDescription - } - } - - func buildPayload() throws -> [String: AnyCodable] { - let name = try self.requireName() - let description = self.trimmed(self.description) - let agentId = self.trimmed(self.agentId) - let schedule = try self.buildSchedule() - let payload = try self.buildSelectedPayload() - - try self.validateSessionTarget(payload) - try self.validatePayloadRequiredFields(payload) - - var root: [String: Any] = [ - "name": name, - "enabled": self.enabled, - "schedule": schedule, - "sessionTarget": self.sessionTarget.rawValue, - "wakeMode": self.wakeMode.rawValue, - "payload": payload, - ] - self.applyDeleteAfterRun(to: &root) - if !description.isEmpty { root["description"] = description } - if !agentId.isEmpty { - root["agentId"] = agentId - } else if self.job?.agentId != nil { - root["agentId"] = NSNull() - } - - if self.sessionTarget == .isolated { - root["delivery"] = self.buildDelivery() - } - - return root.mapValues { AnyCodable($0) } - } - - func buildDelivery() -> [String: Any] { - let mode = self.deliveryMode == .announce ? "announce" : "none" - var delivery: [String: Any] = ["mode": mode] - if self.deliveryMode == .announce { - let trimmed = self.channel.trimmingCharacters(in: .whitespacesAndNewlines) - delivery["channel"] = trimmed.isEmpty ? "last" : trimmed - let to = self.to.trimmingCharacters(in: .whitespacesAndNewlines) - if !to.isEmpty { delivery["to"] = to } - if self.bestEffortDeliver { - delivery["bestEffort"] = true - } else if self.job?.delivery?.bestEffort == true { - delivery["bestEffort"] = false - } - } - return delivery - } - - func trimmed(_ value: String) -> String { - value.trimmingCharacters(in: .whitespacesAndNewlines) - } - - func requireName() throws -> String { - let name = self.trimmed(self.name) - if name.isEmpty { - throw NSError( - domain: "Cron", - code: 0, - userInfo: [NSLocalizedDescriptionKey: "Name is required."]) - } - return name - } - - func buildSchedule() throws -> [String: Any] { - switch self.scheduleKind { - case .at: - return ["kind": "at", "at": CronSchedule.formatIsoDate(self.atDate)] - case .every: - guard let ms = Self.parseDurationMs(self.everyText) else { - throw NSError( - domain: "Cron", - code: 0, - userInfo: [NSLocalizedDescriptionKey: "Invalid every duration (use 10m, 1h, 1d)."]) - } - return ["kind": "every", "everyMs": ms] - case .cron: - let expr = self.trimmed(self.cronExpr) - if expr.isEmpty { - throw NSError( - domain: "Cron", - code: 0, - userInfo: [NSLocalizedDescriptionKey: "Cron expression is required."]) - } - let tz = self.trimmed(self.cronTz) - if tz.isEmpty { - return ["kind": "cron", "expr": expr] - } - return ["kind": "cron", "expr": expr, "tz": tz] - } - } - - func buildSelectedPayload() throws -> [String: Any] { - if self.sessionTarget == .isolated { return self.buildAgentTurnPayload() } - switch self.payloadKind { - case .systemEvent: - let text = self.trimmed(self.systemEventText) - return ["kind": "systemEvent", "text": text] - case .agentTurn: - return self.buildAgentTurnPayload() - } - } - - func validateSessionTarget(_ payload: [String: Any]) throws { - if self.sessionTarget == .main, payload["kind"] as? String == "agentTurn" { - throw NSError( - domain: "Cron", - code: 0, - userInfo: [ - NSLocalizedDescriptionKey: - "Main session jobs require systemEvent payloads (switch Session target to isolated).", - ]) - } - - if self.sessionTarget == .isolated, payload["kind"] as? String == "systemEvent" { - throw NSError( - domain: "Cron", - code: 0, - userInfo: [NSLocalizedDescriptionKey: "Isolated jobs require agentTurn payloads."]) - } - } - - func validatePayloadRequiredFields(_ payload: [String: Any]) throws { - if payload["kind"] as? String == "systemEvent" { - if (payload["text"] as? String ?? "").isEmpty { - throw NSError( - domain: "Cron", - code: 0, - userInfo: [NSLocalizedDescriptionKey: "System event text is required."]) - } - } - if payload["kind"] as? String == "agentTurn" { - if (payload["message"] as? String ?? "").isEmpty { - throw NSError( - domain: "Cron", - code: 0, - userInfo: [NSLocalizedDescriptionKey: "Agent message is required."]) - } - } - } - - func applyDeleteAfterRun( - to root: inout [String: Any], - scheduleKind: ScheduleKind? = nil, - deleteAfterRun: Bool? = nil) - { - let resolvedSchedule = scheduleKind ?? self.scheduleKind - let resolvedDelete = deleteAfterRun ?? self.deleteAfterRun - if resolvedSchedule == .at { - root["deleteAfterRun"] = resolvedDelete - } else if self.job?.deleteAfterRun != nil { - root["deleteAfterRun"] = false - } - } - - func buildAgentTurnPayload() -> [String: Any] { - let msg = self.agentMessage.trimmingCharacters(in: .whitespacesAndNewlines) - var payload: [String: Any] = ["kind": "agentTurn", "message": msg] - let thinking = self.thinking.trimmingCharacters(in: .whitespacesAndNewlines) - if !thinking.isEmpty { payload["thinking"] = thinking } - if let n = Int(self.timeoutSeconds), n > 0 { payload["timeoutSeconds"] = n } - return payload - } - - static func parseDurationMs(_ input: String) -> Int? { - let raw = input.trimmingCharacters(in: .whitespacesAndNewlines) - if raw.isEmpty { return nil } - - let rx = try? NSRegularExpression(pattern: "^(\\d+(?:\\.\\d+)?)(ms|s|m|h|d)$", options: [.caseInsensitive]) - guard let match = rx?.firstMatch(in: raw, range: NSRange(location: 0, length: raw.utf16.count)) else { - return nil - } - func group(_ idx: Int) -> String { - let range = match.range(at: idx) - guard let r = Range(range, in: raw) else { return "" } - return String(raw[r]) - } - let n = Double(group(1)) ?? 0 - if !n.isFinite || n <= 0 { return nil } - let unit = group(2).lowercased() - let factor: Double = switch unit { - case "ms": 1 - case "s": 1000 - case "m": 60000 - case "h": 3_600_000 - default: 86_400_000 - } - return Int(floor(n * factor)) - } - - func formatDuration(ms: Int) -> String { - if ms < 1000 { return "\(ms)ms" } - let s = Double(ms) / 1000.0 - if s < 60 { return "\(Int(round(s)))s" } - let m = s / 60.0 - if m < 60 { return "\(Int(round(m)))m" } - let h = m / 60.0 - if h < 48 { return "\(Int(round(h)))h" } - let d = h / 24.0 - return "\(Int(round(d)))d" - } -} diff --git a/apps/macos/Sources/OpenClaw/CronJobEditor+Testing.swift b/apps/macos/Sources/OpenClaw/CronJobEditor+Testing.swift deleted file mode 100644 index 83b5923e6fd..00000000000 --- a/apps/macos/Sources/OpenClaw/CronJobEditor+Testing.swift +++ /dev/null @@ -1,28 +0,0 @@ -#if DEBUG -extension CronJobEditor { - mutating func exerciseForTesting() { - self.name = "Test job" - self.description = "Test description" - self.agentId = "ops" - self.enabled = true - self.sessionTarget = .isolated - self.wakeMode = .now - - self.scheduleKind = .every - self.everyText = "15m" - - self.payloadKind = .agentTurn - self.agentMessage = "Run diagnostic" - self.deliveryMode = .announce - self.channel = "last" - self.to = "+15551230000" - self.thinking = "low" - self.timeoutSeconds = "90" - self.bestEffortDeliver = true - - _ = self.buildAgentTurnPayload() - _ = try? self.buildPayload() - _ = self.formatDuration(ms: 45000) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/CronJobEditor.swift b/apps/macos/Sources/OpenClaw/CronJobEditor.swift deleted file mode 100644 index a7d88a4f2fb..00000000000 --- a/apps/macos/Sources/OpenClaw/CronJobEditor.swift +++ /dev/null @@ -1,362 +0,0 @@ -import Observation -import OpenClawProtocol -import SwiftUI - -struct CronJobEditor: View { - let job: CronJob? - @Binding var isSaving: Bool - @Binding var error: String? - @Bindable var channelsStore: ChannelsStore - let onCancel: () -> Void - let onSave: ([String: AnyCodable]) -> Void - - let labelColumnWidth: CGFloat = 160 - static let introText = - "Create a schedule that wakes OpenClaw via the Gateway. " - + "Use an isolated session for agent turns so your main chat stays clean." - static let sessionTargetNote = - "Main jobs post a system event into the current main session. " - + "Isolated jobs run OpenClaw in a dedicated session and can announce results to a channel." - static let scheduleKindNote = - "“At” runs once, “Every” repeats with a duration, “Cron” uses a 5-field Unix expression." - static let isolatedPayloadNote = - "Isolated jobs always run an agent turn. Announce sends a short summary to a channel." - static let mainPayloadNote = - "System events are injected into the current main session. Agent turns require an isolated session target." - - @State var name: String = "" - @State var description: String = "" - @State var agentId: String = "" - @State var enabled: Bool = true - @State var sessionTarget: CronSessionTarget = .main - @State var wakeMode: CronWakeMode = .now - @State var deleteAfterRun: Bool = false - - enum ScheduleKind: String, CaseIterable, Identifiable { case at, every, cron; var id: String { - rawValue - } } - @State var scheduleKind: ScheduleKind = .every - @State var atDate: Date = .init().addingTimeInterval(60 * 5) - @State var everyText: String = "1h" - @State var cronExpr: String = "0 9 * * 3" - @State var cronTz: String = "" - - enum PayloadKind: String, CaseIterable, Identifiable { case systemEvent, agentTurn; var id: String { - rawValue - } } - @State var payloadKind: PayloadKind = .systemEvent - @State var systemEventText: String = "" - @State var agentMessage: String = "" - enum DeliveryChoice: String, CaseIterable, Identifiable { case announce, none; var id: String { - rawValue - } } - @State var deliveryMode: DeliveryChoice = .announce - @State var channel: String = "last" - @State var to: String = "" - @State var thinking: String = "" - @State var timeoutSeconds: String = "" - @State var bestEffortDeliver: Bool = false - - var channelOptions: [String] { - let ordered = self.channelsStore.orderedChannelIds() - var options = ["last"] + ordered - let trimmed = self.channel.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmed.isEmpty, !options.contains(trimmed) { - options.append(trimmed) - } - var seen = Set() - return options.filter { seen.insert($0).inserted } - } - - func channelLabel(for id: String) -> String { - if id == "last" { return "last" } - return self.channelsStore.resolveChannelLabel(id) - } - - var body: some View { - VStack(alignment: .leading, spacing: 16) { - VStack(alignment: .leading, spacing: 6) { - Text(self.job == nil ? "New cron job" : "Edit cron job") - .font(.title3.weight(.semibold)) - Text(Self.introText) - .font(.callout) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - - ScrollView(.vertical) { - VStack(alignment: .leading, spacing: 14) { - GroupBox("Basics") { - Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) { - GridRow { - self.gridLabel("Name") - TextField("Required (e.g. “Daily summary”)", text: self.$name) - .textFieldStyle(.roundedBorder) - .frame(maxWidth: .infinity) - } - GridRow { - self.gridLabel("Description") - TextField("Optional notes", text: self.$description) - .textFieldStyle(.roundedBorder) - .frame(maxWidth: .infinity) - } - GridRow { - self.gridLabel("Agent ID") - TextField("Optional (default agent)", text: self.$agentId) - .textFieldStyle(.roundedBorder) - .frame(maxWidth: .infinity) - } - GridRow { - self.gridLabel("Enabled") - Toggle("", isOn: self.$enabled) - .labelsHidden() - .toggleStyle(.switch) - } - GridRow { - self.gridLabel("Session target") - Picker("", selection: self.$sessionTarget) { - Text("main").tag(CronSessionTarget.main) - Text("isolated").tag(CronSessionTarget.isolated) - } - .labelsHidden() - .pickerStyle(.segmented) - .frame(maxWidth: .infinity, alignment: .leading) - } - GridRow { - self.gridLabel("Wake mode") - Picker("", selection: self.$wakeMode) { - Text("now").tag(CronWakeMode.now) - Text("next-heartbeat").tag(CronWakeMode.nextHeartbeat) - } - .labelsHidden() - .pickerStyle(.segmented) - .frame(maxWidth: .infinity, alignment: .leading) - } - GridRow { - Color.clear - .frame(width: self.labelColumnWidth, height: 1) - Text( - Self.sessionTargetNote) - .font(.footnote) - .foregroundStyle(.secondary) - .frame(maxWidth: .infinity, alignment: .leading) - } - } - } - - GroupBox("Schedule") { - Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) { - GridRow { - self.gridLabel("Kind") - Picker("", selection: self.$scheduleKind) { - Text("at").tag(ScheduleKind.at) - Text("every").tag(ScheduleKind.every) - Text("cron").tag(ScheduleKind.cron) - } - .labelsHidden() - .pickerStyle(.segmented) - .frame(maxWidth: .infinity) - } - GridRow { - Color.clear - .frame(width: self.labelColumnWidth, height: 1) - Text( - Self.scheduleKindNote) - .font(.footnote) - .foregroundStyle(.secondary) - .frame(maxWidth: .infinity, alignment: .leading) - } - - switch self.scheduleKind { - case .at: - GridRow { - self.gridLabel("At") - DatePicker( - "", - selection: self.$atDate, - displayedComponents: [.date, .hourAndMinute]) - .labelsHidden() - .frame(maxWidth: .infinity, alignment: .leading) - } - GridRow { - self.gridLabel("Auto-delete") - Toggle("Delete after successful run", isOn: self.$deleteAfterRun) - .toggleStyle(.switch) - } - case .every: - GridRow { - self.gridLabel("Every") - TextField("10m, 1h, 1d", text: self.$everyText) - .textFieldStyle(.roundedBorder) - .frame(maxWidth: .infinity) - } - case .cron: - GridRow { - self.gridLabel("Expression") - TextField("e.g. 0 9 * * 3", text: self.$cronExpr) - .textFieldStyle(.roundedBorder) - .frame(maxWidth: .infinity) - } - GridRow { - self.gridLabel("Timezone") - TextField("Optional (e.g. America/Los_Angeles)", text: self.$cronTz) - .textFieldStyle(.roundedBorder) - .frame(maxWidth: .infinity) - } - } - } - } - - GroupBox("Payload") { - VStack(alignment: .leading, spacing: 10) { - if self.sessionTarget == .isolated { - Text(Self.isolatedPayloadNote) - .font(.footnote) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - self.agentTurnEditor - } else { - Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) { - GridRow { - self.gridLabel("Kind") - Picker("", selection: self.$payloadKind) { - Text("systemEvent").tag(PayloadKind.systemEvent) - Text("agentTurn").tag(PayloadKind.agentTurn) - } - .labelsHidden() - .pickerStyle(.segmented) - .frame(maxWidth: .infinity) - } - GridRow { - Color.clear - .frame(width: self.labelColumnWidth, height: 1) - Text( - Self.mainPayloadNote) - .font(.footnote) - .foregroundStyle(.secondary) - .frame(maxWidth: .infinity, alignment: .leading) - } - } - - switch self.payloadKind { - case .systemEvent: - TextField("System event text", text: self.$systemEventText, axis: .vertical) - .textFieldStyle(.roundedBorder) - .lineLimit(3...7) - .frame(maxWidth: .infinity) - case .agentTurn: - self.agentTurnEditor - } - } - } - } - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.vertical, 2) - } - - if let error, !error.isEmpty { - Text(error) - .font(.footnote) - .foregroundStyle(.red) - .fixedSize(horizontal: false, vertical: true) - } - - HStack { - Button("Cancel") { self.onCancel() } - .keyboardShortcut(.cancelAction) - .buttonStyle(.bordered) - Spacer() - Button { - self.save() - } label: { - if self.isSaving { - ProgressView().controlSize(.small) - } else { - Text("Save") - } - } - .keyboardShortcut(.defaultAction) - .buttonStyle(.borderedProminent) - .disabled(self.isSaving) - } - } - .padding(24) - .frame(minWidth: 720, minHeight: 640) - .onAppear { self.hydrateFromJob() } - .onChange(of: self.payloadKind) { _, newValue in - if newValue == .agentTurn, self.sessionTarget == .main { - self.sessionTarget = .isolated - } - } - .onChange(of: self.sessionTarget) { _, newValue in - if newValue == .isolated { - self.payloadKind = .agentTurn - } else if newValue == .main, self.payloadKind == .agentTurn { - self.payloadKind = .systemEvent - } - } - } - - var agentTurnEditor: some View { - VStack(alignment: .leading, spacing: 10) { - Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) { - GridRow { - self.gridLabel("Message") - TextField("What should OpenClaw do?", text: self.$agentMessage, axis: .vertical) - .textFieldStyle(.roundedBorder) - .lineLimit(3...7) - .frame(maxWidth: .infinity) - } - GridRow { - self.gridLabel("Thinking") - TextField("Optional (e.g. low)", text: self.$thinking) - .textFieldStyle(.roundedBorder) - .frame(maxWidth: .infinity) - } - GridRow { - self.gridLabel("Timeout") - TextField("Seconds (optional)", text: self.$timeoutSeconds) - .textFieldStyle(.roundedBorder) - .frame(width: 180, alignment: .leading) - } - GridRow { - self.gridLabel("Delivery") - Picker("", selection: self.$deliveryMode) { - Text("Announce summary").tag(DeliveryChoice.announce) - Text("None").tag(DeliveryChoice.none) - } - .labelsHidden() - .pickerStyle(.segmented) - } - } - - if self.deliveryMode == .announce { - Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) { - GridRow { - self.gridLabel("Channel") - Picker("", selection: self.$channel) { - ForEach(self.channelOptions, id: \.self) { channel in - Text(self.channelLabel(for: channel)).tag(channel) - } - } - .labelsHidden() - .pickerStyle(.segmented) - .frame(maxWidth: .infinity, alignment: .leading) - } - GridRow { - self.gridLabel("To") - TextField("Optional override (phone number / chat id / Discord channel)", text: self.$to) - .textFieldStyle(.roundedBorder) - .frame(maxWidth: .infinity) - } - GridRow { - self.gridLabel("Best-effort") - Toggle("Do not fail the job if announce fails", isOn: self.$bestEffortDeliver) - .toggleStyle(.switch) - } - } - } - } - } -} diff --git a/apps/macos/Sources/OpenClaw/CronJobsStore.swift b/apps/macos/Sources/OpenClaw/CronJobsStore.swift deleted file mode 100644 index 21c70ded584..00000000000 --- a/apps/macos/Sources/OpenClaw/CronJobsStore.swift +++ /dev/null @@ -1,200 +0,0 @@ -import Foundation -import Observation -import OpenClawKit -import OpenClawProtocol -import OSLog - -@MainActor -@Observable -final class CronJobsStore { - static let shared = CronJobsStore() - - var jobs: [CronJob] = [] - var selectedJobId: String? - var runEntries: [CronRunLogEntry] = [] - - var schedulerEnabled: Bool? - var schedulerStorePath: String? - var schedulerNextWakeAtMs: Int? - - var isLoadingJobs = false - var isLoadingRuns = false - var lastError: String? - var statusMessage: String? - - private let logger = Logger(subsystem: "ai.openclaw", category: "cron.ui") - private var refreshTask: Task? - private var runsTask: Task? - private var eventTask: Task? - private var pollTask: Task? - - private let interval: TimeInterval = 30 - private let isPreview: Bool - - init(isPreview: Bool = ProcessInfo.processInfo.isPreview) { - self.isPreview = isPreview - } - - func start() { - guard !self.isPreview else { return } - guard self.eventTask == nil else { return } - self.startGatewaySubscription() - self.pollTask = Task.detached { [weak self] in - guard let self else { return } - await self.refreshJobs() - while !Task.isCancelled { - try? await Task.sleep(nanoseconds: UInt64(self.interval * 1_000_000_000)) - await self.refreshJobs() - } - } - } - - func stop() { - self.refreshTask?.cancel() - self.refreshTask = nil - self.runsTask?.cancel() - self.runsTask = nil - self.eventTask?.cancel() - self.eventTask = nil - self.pollTask?.cancel() - self.pollTask = nil - } - - func refreshJobs() async { - guard !self.isLoadingJobs else { return } - self.isLoadingJobs = true - self.lastError = nil - self.statusMessage = nil - defer { self.isLoadingJobs = false } - - do { - if let status = try? await GatewayConnection.shared.cronStatus() { - self.schedulerEnabled = status.enabled - self.schedulerStorePath = status.storePath - self.schedulerNextWakeAtMs = status.nextWakeAtMs - } - self.jobs = try await GatewayConnection.shared.cronList(includeDisabled: true) - if self.jobs.isEmpty { - self.statusMessage = "No cron jobs yet." - } - } catch { - self.logger.error("cron.list failed \(error.localizedDescription, privacy: .public)") - self.lastError = error.localizedDescription - } - } - - func refreshRuns(jobId: String, limit: Int = 200) async { - guard !self.isLoadingRuns else { return } - self.isLoadingRuns = true - defer { self.isLoadingRuns = false } - - do { - self.runEntries = try await GatewayConnection.shared.cronRuns(jobId: jobId, limit: limit) - } catch { - self.logger.error("cron.runs failed \(error.localizedDescription, privacy: .public)") - self.lastError = error.localizedDescription - } - } - - func runJob(id: String, force: Bool = true) async { - do { - try await GatewayConnection.shared.cronRun(jobId: id, force: force) - } catch { - self.lastError = error.localizedDescription - } - } - - func removeJob(id: String) async { - do { - try await GatewayConnection.shared.cronRemove(jobId: id) - await self.refreshJobs() - if self.selectedJobId == id { - self.selectedJobId = nil - self.runEntries = [] - } - } catch { - self.lastError = error.localizedDescription - } - } - - func setJobEnabled(id: String, enabled: Bool) async { - do { - try await GatewayConnection.shared.cronUpdate( - jobId: id, - patch: ["enabled": AnyCodable(enabled)]) - await self.refreshJobs() - } catch { - self.lastError = error.localizedDescription - } - } - - func upsertJob( - id: String?, - payload: [String: AnyCodable]) async throws - { - if let id { - try await GatewayConnection.shared.cronUpdate(jobId: id, patch: payload) - } else { - try await GatewayConnection.shared.cronAdd(payload: payload) - } - await self.refreshJobs() - } - - // MARK: - Gateway events - - private func startGatewaySubscription() { - self.eventTask?.cancel() - self.eventTask = Task { [weak self] in - guard let self else { return } - let stream = await GatewayConnection.shared.subscribe() - for await push in stream { - if Task.isCancelled { return } - await MainActor.run { [weak self] in - self?.handle(push: push) - } - } - } - } - - private func handle(push: GatewayPush) { - switch push { - case let .event(evt) where evt.event == "cron": - guard let payload = evt.payload else { return } - if let cronEvt = try? GatewayPayloadDecoding.decode(payload, as: CronEvent.self) { - self.handle(cronEvent: cronEvt) - } - case .seqGap: - self.scheduleRefresh() - default: - break - } - } - - private func handle(cronEvent evt: CronEvent) { - // Keep UI in sync with the gateway scheduler. - self.scheduleRefresh(delayMs: 250) - if evt.action == "finished", let selected = self.selectedJobId, selected == evt.jobId { - self.scheduleRunsRefresh(jobId: selected, delayMs: 200) - } - } - - private func scheduleRefresh(delayMs: Int = 250) { - self.refreshTask?.cancel() - self.refreshTask = Task { [weak self] in - guard let self else { return } - try? await Task.sleep(nanoseconds: UInt64(delayMs) * 1_000_000) - await self.refreshJobs() - } - } - - private func scheduleRunsRefresh(jobId: String, delayMs: Int = 200) { - self.runsTask?.cancel() - self.runsTask = Task { [weak self] in - guard let self else { return } - try? await Task.sleep(nanoseconds: UInt64(delayMs) * 1_000_000) - await self.refreshRuns(jobId: jobId) - } - } - - // MARK: - (no additional RPC helpers) -} diff --git a/apps/macos/Sources/OpenClaw/CronModels.swift b/apps/macos/Sources/OpenClaw/CronModels.swift deleted file mode 100644 index cbfbc061d6a..00000000000 --- a/apps/macos/Sources/OpenClaw/CronModels.swift +++ /dev/null @@ -1,271 +0,0 @@ -import Foundation - -enum CronSessionTarget: String, CaseIterable, Identifiable, Codable { - case main - case isolated - - var id: String { - self.rawValue - } -} - -enum CronWakeMode: String, CaseIterable, Identifiable, Codable { - case now - case nextHeartbeat = "next-heartbeat" - - var id: String { - self.rawValue - } -} - -enum CronDeliveryMode: String, CaseIterable, Identifiable, Codable { - case none - case announce - case webhook - - var id: String { - self.rawValue - } -} - -struct CronDelivery: Codable, Equatable { - var mode: CronDeliveryMode - var channel: String? - var to: String? - var bestEffort: Bool? -} - -enum CronSchedule: Codable, Equatable { - case at(at: String) - case every(everyMs: Int, anchorMs: Int?) - case cron(expr: String, tz: String?) - - enum CodingKeys: String, CodingKey { case kind, at, atMs, everyMs, anchorMs, expr, tz } - - var kind: String { - switch self { - case .at: "at" - case .every: "every" - case .cron: "cron" - } - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let kind = try container.decode(String.self, forKey: .kind) - switch kind { - case "at": - if let at = try container.decodeIfPresent(String.self, forKey: .at), - !at.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty - { - self = .at(at: at) - return - } - if let atMs = try container.decodeIfPresent(Int.self, forKey: .atMs) { - let date = Date(timeIntervalSince1970: TimeInterval(atMs) / 1000) - self = .at(at: Self.formatIsoDate(date)) - return - } - throw DecodingError.dataCorruptedError( - forKey: .at, - in: container, - debugDescription: "Missing schedule.at") - case "every": - self = try .every( - everyMs: container.decode(Int.self, forKey: .everyMs), - anchorMs: container.decodeIfPresent(Int.self, forKey: .anchorMs)) - case "cron": - self = try .cron( - expr: container.decode(String.self, forKey: .expr), - tz: container.decodeIfPresent(String.self, forKey: .tz)) - default: - throw DecodingError.dataCorruptedError( - forKey: .kind, - in: container, - debugDescription: "Unknown schedule kind: \(kind)") - } - } - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(self.kind, forKey: .kind) - switch self { - case let .at(at): - try container.encode(at, forKey: .at) - case let .every(everyMs, anchorMs): - try container.encode(everyMs, forKey: .everyMs) - try container.encodeIfPresent(anchorMs, forKey: .anchorMs) - case let .cron(expr, tz): - try container.encode(expr, forKey: .expr) - try container.encodeIfPresent(tz, forKey: .tz) - } - } - - static func parseAtDate(_ value: String) -> Date? { - let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty { return nil } - if let date = makeIsoFormatter(withFractional: true).date(from: trimmed) { return date } - return self.makeIsoFormatter(withFractional: false).date(from: trimmed) - } - - static func formatIsoDate(_ date: Date) -> String { - self.makeIsoFormatter(withFractional: false).string(from: date) - } - - private static func makeIsoFormatter(withFractional: Bool) -> ISO8601DateFormatter { - let formatter = ISO8601DateFormatter() - formatter.formatOptions = withFractional - ? [.withInternetDateTime, .withFractionalSeconds] - : [.withInternetDateTime] - return formatter - } -} - -enum CronPayload: Codable, Equatable { - case systemEvent(text: String) - case agentTurn( - message: String, - thinking: String?, - timeoutSeconds: Int?, - deliver: Bool?, - channel: String?, - to: String?, - bestEffortDeliver: Bool?) - - enum CodingKeys: String, CodingKey { - case kind, text, message, thinking, timeoutSeconds, deliver, channel, provider, to, bestEffortDeliver - } - - var kind: String { - switch self { - case .systemEvent: "systemEvent" - case .agentTurn: "agentTurn" - } - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let kind = try container.decode(String.self, forKey: .kind) - switch kind { - case "systemEvent": - self = try .systemEvent(text: container.decode(String.self, forKey: .text)) - case "agentTurn": - self = try .agentTurn( - message: container.decode(String.self, forKey: .message), - thinking: container.decodeIfPresent(String.self, forKey: .thinking), - timeoutSeconds: container.decodeIfPresent(Int.self, forKey: .timeoutSeconds), - deliver: container.decodeIfPresent(Bool.self, forKey: .deliver), - channel: container.decodeIfPresent(String.self, forKey: .channel) - ?? container.decodeIfPresent(String.self, forKey: .provider), - to: container.decodeIfPresent(String.self, forKey: .to), - bestEffortDeliver: container.decodeIfPresent(Bool.self, forKey: .bestEffortDeliver)) - default: - throw DecodingError.dataCorruptedError( - forKey: .kind, - in: container, - debugDescription: "Unknown payload kind: \(kind)") - } - } - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(self.kind, forKey: .kind) - switch self { - case let .systemEvent(text): - try container.encode(text, forKey: .text) - case let .agentTurn(message, thinking, timeoutSeconds, deliver, channel, to, bestEffortDeliver): - try container.encode(message, forKey: .message) - try container.encodeIfPresent(thinking, forKey: .thinking) - try container.encodeIfPresent(timeoutSeconds, forKey: .timeoutSeconds) - try container.encodeIfPresent(deliver, forKey: .deliver) - try container.encodeIfPresent(channel, forKey: .channel) - try container.encodeIfPresent(to, forKey: .to) - try container.encodeIfPresent(bestEffortDeliver, forKey: .bestEffortDeliver) - } - } -} - -struct CronJobState: Codable, Equatable { - var nextRunAtMs: Int? - var runningAtMs: Int? - var lastRunAtMs: Int? - var lastStatus: String? - var lastError: String? - var lastDurationMs: Int? -} - -struct CronJob: Identifiable, Codable, Equatable { - let id: String - let agentId: String? - var name: String - var description: String? - var enabled: Bool - var deleteAfterRun: Bool? - let createdAtMs: Int - let updatedAtMs: Int - let schedule: CronSchedule - let sessionTarget: CronSessionTarget - let wakeMode: CronWakeMode - let payload: CronPayload - let delivery: CronDelivery? - let state: CronJobState - - var displayName: String { - let trimmed = self.name.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed.isEmpty ? "Untitled job" : trimmed - } - - var nextRunDate: Date? { - guard let ms = self.state.nextRunAtMs else { return nil } - return Date(timeIntervalSince1970: TimeInterval(ms) / 1000) - } - - var lastRunDate: Date? { - guard let ms = self.state.lastRunAtMs else { return nil } - return Date(timeIntervalSince1970: TimeInterval(ms) / 1000) - } -} - -struct CronEvent: Codable, Sendable { - let jobId: String - let action: String - let runAtMs: Int? - let durationMs: Int? - let status: String? - let error: String? - let summary: String? - let nextRunAtMs: Int? -} - -struct CronRunLogEntry: Codable, Identifiable, Sendable { - var id: String { - "\(self.jobId)-\(self.ts)" - } - - let ts: Int - let jobId: String - let action: String - let status: String? - let error: String? - let summary: String? - let runAtMs: Int? - let durationMs: Int? - let nextRunAtMs: Int? - - var date: Date { - Date(timeIntervalSince1970: TimeInterval(self.ts) / 1000) - } - - var runDate: Date? { - guard let runAtMs else { return nil } - return Date(timeIntervalSince1970: TimeInterval(runAtMs) / 1000) - } -} - -struct CronListResponse: Codable { - let jobs: [CronJob] -} - -struct CronRunsResponse: Codable { - let entries: [CronRunLogEntry] -} diff --git a/apps/macos/Sources/OpenClaw/CronSettings+Actions.swift b/apps/macos/Sources/OpenClaw/CronSettings+Actions.swift deleted file mode 100644 index 3fffaf90fd5..00000000000 --- a/apps/macos/Sources/OpenClaw/CronSettings+Actions.swift +++ /dev/null @@ -1,23 +0,0 @@ -import Foundation -import OpenClawProtocol - -extension CronSettings { - func save(payload: [String: AnyCodable]) async { - guard !self.isSaving else { return } - self.isSaving = true - self.editorError = nil - do { - try await self.store.upsertJob(id: self.editingJob?.id, payload: payload) - await MainActor.run { - self.isSaving = false - self.showEditor = false - self.editingJob = nil - } - } catch { - await MainActor.run { - self.isSaving = false - self.editorError = error.localizedDescription - } - } - } -} diff --git a/apps/macos/Sources/OpenClaw/CronSettings+Helpers.swift b/apps/macos/Sources/OpenClaw/CronSettings+Helpers.swift deleted file mode 100644 index c638e4c87b1..00000000000 --- a/apps/macos/Sources/OpenClaw/CronSettings+Helpers.swift +++ /dev/null @@ -1,56 +0,0 @@ -import SwiftUI - -extension CronSettings { - var selectedJob: CronJob? { - guard let id = self.store.selectedJobId else { return nil } - return self.store.jobs.first(where: { $0.id == id }) - } - - func statusTint(_ status: String?) -> Color { - switch (status ?? "").lowercased() { - case "ok": .green - case "error": .red - case "skipped": .orange - default: .secondary - } - } - - func scheduleSummary(_ schedule: CronSchedule) -> String { - switch schedule { - case let .at(at): - if let date = CronSchedule.parseAtDate(at) { - return "at \(date.formatted(date: .abbreviated, time: .standard))" - } - return "at \(at)" - case let .every(everyMs, _): - return "every \(self.formatDuration(ms: everyMs))" - case let .cron(expr, tz): - if let tz, !tz.isEmpty { return "cron \(expr) (\(tz))" } - return "cron \(expr)" - } - } - - func formatDuration(ms: Int) -> String { - if ms < 1000 { return "\(ms)ms" } - let s = Double(ms) / 1000.0 - if s < 60 { return "\(Int(round(s)))s" } - let m = s / 60.0 - if m < 60 { return "\(Int(round(m)))m" } - let h = m / 60.0 - if h < 48 { return "\(Int(round(h)))h" } - let d = h / 24.0 - return "\(Int(round(d)))d" - } - - func nextRunLabel(_ date: Date, now: Date = .init()) -> String { - let delta = date.timeIntervalSince(now) - if delta <= 0 { return "due" } - if delta < 60 { return "in <1m" } - let minutes = Int(round(delta / 60)) - if minutes < 60 { return "in \(minutes)m" } - let hours = Int(round(Double(minutes) / 60)) - if hours < 48 { return "in \(hours)h" } - let days = Int(round(Double(hours) / 24)) - return "in \(days)d" - } -} diff --git a/apps/macos/Sources/OpenClaw/CronSettings+Layout.swift b/apps/macos/Sources/OpenClaw/CronSettings+Layout.swift deleted file mode 100644 index 11c7c0a0e5b..00000000000 --- a/apps/macos/Sources/OpenClaw/CronSettings+Layout.swift +++ /dev/null @@ -1,179 +0,0 @@ -import SwiftUI - -extension CronSettings { - var body: some View { - VStack(alignment: .leading, spacing: 12) { - self.header - self.schedulerBanner - self.content - Spacer(minLength: 0) - } - .onAppear { - self.store.start() - self.channelsStore.start() - } - .onDisappear { - self.store.stop() - self.channelsStore.stop() - } - .sheet(isPresented: self.$showEditor) { - CronJobEditor( - job: self.editingJob, - isSaving: self.$isSaving, - error: self.$editorError, - channelsStore: self.channelsStore, - onCancel: { - self.showEditor = false - self.editingJob = nil - }, - onSave: { payload in - Task { - await self.save(payload: payload) - } - }) - } - .alert("Delete cron job?", isPresented: Binding( - get: { self.confirmDelete != nil }, - set: { if !$0 { self.confirmDelete = nil } })) - { - Button("Cancel", role: .cancel) { self.confirmDelete = nil } - Button("Delete", role: .destructive) { - if let job = self.confirmDelete { - Task { await self.store.removeJob(id: job.id) } - } - self.confirmDelete = nil - } - } message: { - if let job = self.confirmDelete { - Text(job.displayName) - } - } - .onChange(of: self.store.selectedJobId) { _, newValue in - guard let newValue else { return } - Task { await self.store.refreshRuns(jobId: newValue) } - } - } - - var schedulerBanner: some View { - Group { - if self.store.schedulerEnabled == false { - VStack(alignment: .leading, spacing: 6) { - HStack(spacing: 8) { - Image(systemName: "exclamationmark.triangle.fill") - .foregroundStyle(.orange) - Text("Cron scheduler is disabled") - .font(.headline) - Spacer() - } - Text( - "Jobs are saved, but they will not run automatically until `cron.enabled` is set to `true` " + - "and the Gateway restarts.") - .font(.footnote) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - if let storePath = self.store.schedulerStorePath, !storePath.isEmpty { - Text(storePath) - .font(.caption.monospaced()) - .foregroundStyle(.secondary) - .textSelection(.enabled) - .lineLimit(1) - .truncationMode(.middle) - } - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(10) - .background(Color.orange.opacity(0.10)) - .cornerRadius(8) - } - } - } - - var header: some View { - HStack(alignment: .top) { - VStack(alignment: .leading, spacing: 4) { - Text("Cron") - .font(.headline) - Text("Manage Gateway cron jobs (main session vs isolated runs) and inspect run history.") - .font(.footnote) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - Spacer() - HStack(spacing: 8) { - Button { - Task { await self.store.refreshJobs() } - } label: { - Label("Refresh", systemImage: "arrow.clockwise") - } - .buttonStyle(.bordered) - .disabled(self.store.isLoadingJobs) - - Button { - self.editorError = nil - self.editingJob = nil - self.showEditor = true - } label: { - Label("New Job", systemImage: "plus") - } - .buttonStyle(.borderedProminent) - } - } - } - - var content: some View { - HStack(spacing: 12) { - VStack(alignment: .leading, spacing: 8) { - if let err = self.store.lastError { - Text("Error: \(err)") - .font(.footnote) - .foregroundStyle(.red) - } else if let msg = self.store.statusMessage { - Text(msg) - .font(.footnote) - .foregroundStyle(.secondary) - } - - List(selection: self.$store.selectedJobId) { - ForEach(self.store.jobs) { job in - self.jobRow(job) - .tag(job.id) - .contextMenu { self.jobContextMenu(job) } - } - } - .listStyle(.inset) - } - .frame(width: 250) - - Divider() - - self.detail - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) - } - } - - @ViewBuilder - var detail: some View { - if let selected = self.selectedJob { - ScrollView(.vertical) { - VStack(alignment: .leading, spacing: 12) { - self.detailHeader(selected) - self.detailCard(selected) - self.runHistoryCard(selected) - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.top, 2) - } - } else { - VStack(alignment: .leading, spacing: 8) { - Text("Select a job to inspect details and run history.") - .font(.callout) - .foregroundStyle(.secondary) - Text("Tip: use ‘New Job’ to add one, or enable cron in your gateway config.") - .font(.caption) - .foregroundStyle(.tertiary) - } - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) - .padding(.top, 8) - } - } -} diff --git a/apps/macos/Sources/OpenClaw/CronSettings+Rows.swift b/apps/macos/Sources/OpenClaw/CronSettings+Rows.swift deleted file mode 100644 index 69655bdc302..00000000000 --- a/apps/macos/Sources/OpenClaw/CronSettings+Rows.swift +++ /dev/null @@ -1,246 +0,0 @@ -import SwiftUI - -extension CronSettings { - func jobRow(_ job: CronJob) -> some View { - VStack(alignment: .leading, spacing: 6) { - HStack(spacing: 8) { - Text(job.displayName) - .font(.subheadline.weight(.semibold)) - .lineLimit(1) - .truncationMode(.middle) - Spacer() - if !job.enabled { - StatusPill(text: "disabled", tint: .secondary) - } else if let next = job.nextRunDate { - StatusPill(text: self.nextRunLabel(next), tint: .secondary) - } else { - StatusPill(text: "no next run", tint: .secondary) - } - } - HStack(spacing: 6) { - StatusPill(text: job.sessionTarget.rawValue, tint: .secondary) - StatusPill(text: job.wakeMode.rawValue, tint: .secondary) - if let agentId = job.agentId, !agentId.isEmpty { - StatusPill(text: "agent \(agentId)", tint: .secondary) - } - if let status = job.state.lastStatus { - StatusPill(text: status, tint: status == "ok" ? .green : .orange) - } - } - } - .padding(.vertical, 6) - } - - @ViewBuilder - func jobContextMenu(_ job: CronJob) -> some View { - Button("Run now") { Task { await self.store.runJob(id: job.id, force: true) } } - if job.sessionTarget == .isolated { - Button("Open transcript") { - WebChatManager.shared.show(sessionKey: "cron:\(job.id)") - } - } - Divider() - Button(job.enabled ? "Disable" : "Enable") { - Task { await self.store.setJobEnabled(id: job.id, enabled: !job.enabled) } - } - Button("Edit…") { - self.editingJob = job - self.editorError = nil - self.showEditor = true - } - Divider() - Button("Delete…", role: .destructive) { - self.confirmDelete = job - } - } - - func detailHeader(_ job: CronJob) -> some View { - HStack(alignment: .center) { - VStack(alignment: .leading, spacing: 4) { - Text(job.displayName) - .font(.title3.weight(.semibold)) - Text(job.id) - .font(.caption.monospaced()) - .foregroundStyle(.secondary) - .textSelection(.enabled) - .lineLimit(1) - .truncationMode(.middle) - } - Spacer() - HStack(spacing: 8) { - Toggle("Enabled", isOn: Binding( - get: { job.enabled }, - set: { enabled in Task { await self.store.setJobEnabled(id: job.id, enabled: enabled) } })) - .toggleStyle(.switch) - .labelsHidden() - Button("Run") { Task { await self.store.runJob(id: job.id, force: true) } } - .buttonStyle(.borderedProminent) - if job.sessionTarget == .isolated { - Button("Transcript") { - WebChatManager.shared.show(sessionKey: "cron:\(job.id)") - } - .buttonStyle(.bordered) - } - Button("Edit") { - self.editingJob = job - self.editorError = nil - self.showEditor = true - } - .buttonStyle(.bordered) - } - } - } - - func detailCard(_ job: CronJob) -> some View { - VStack(alignment: .leading, spacing: 10) { - LabeledContent("Schedule") { Text(self.scheduleSummary(job.schedule)).font(.callout) } - if case .at = job.schedule, job.deleteAfterRun == true { - LabeledContent("Auto-delete") { Text("after success") } - } - if let desc = job.description, !desc.isEmpty { - LabeledContent("Description") { Text(desc).font(.callout) } - } - if let agentId = job.agentId, !agentId.isEmpty { - LabeledContent("Agent") { Text(agentId) } - } - LabeledContent("Session") { Text(job.sessionTarget.rawValue) } - LabeledContent("Wake") { Text(job.wakeMode.rawValue) } - LabeledContent("Next run") { - if let date = job.nextRunDate { - Text(date.formatted(date: .abbreviated, time: .standard)) - } else { - Text("—").foregroundStyle(.secondary) - } - } - LabeledContent("Last run") { - if let date = job.lastRunDate { - Text("\(date.formatted(date: .abbreviated, time: .standard)) · \(relativeAge(from: date))") - } else { - Text("—").foregroundStyle(.secondary) - } - } - if let status = job.state.lastStatus { - LabeledContent("Last status") { Text(status) } - } - if let err = job.state.lastError, !err.isEmpty { - Text(err) - .font(.footnote) - .foregroundStyle(.orange) - .textSelection(.enabled) - } - self.payloadSummary(job) - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(10) - .background(Color.secondary.opacity(0.06)) - .cornerRadius(8) - } - - func runHistoryCard(_ job: CronJob) -> some View { - VStack(alignment: .leading, spacing: 8) { - HStack { - Text("Run history") - .font(.headline) - Spacer() - Button { - Task { await self.store.refreshRuns(jobId: job.id) } - } label: { - Label("Refresh", systemImage: "arrow.clockwise") - } - .buttonStyle(.bordered) - .disabled(self.store.isLoadingRuns) - } - - if self.store.isLoadingRuns { - ProgressView().controlSize(.small) - } - - if self.store.runEntries.isEmpty { - Text("No run log entries yet.") - .font(.footnote) - .foregroundStyle(.secondary) - } else { - VStack(alignment: .leading, spacing: 6) { - ForEach(self.store.runEntries) { entry in - self.runRow(entry) - } - } - } - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(10) - .background(Color.secondary.opacity(0.06)) - .cornerRadius(8) - } - - func runRow(_ entry: CronRunLogEntry) -> some View { - VStack(alignment: .leading, spacing: 4) { - HStack(spacing: 8) { - StatusPill(text: entry.status ?? "unknown", tint: self.statusTint(entry.status)) - Text(entry.date.formatted(date: .abbreviated, time: .standard)) - .font(.caption) - .foregroundStyle(.secondary) - Spacer() - if let ms = entry.durationMs { - Text("\(ms)ms") - .font(.caption2.monospacedDigit()) - .foregroundStyle(.secondary) - } - } - if let summary = entry.summary, !summary.isEmpty { - Text(summary) - .font(.caption) - .foregroundStyle(.secondary) - .textSelection(.enabled) - .lineLimit(2) - } - if let error = entry.error, !error.isEmpty { - Text(error) - .font(.caption) - .foregroundStyle(.orange) - .textSelection(.enabled) - .lineLimit(2) - } - } - .padding(.vertical, 4) - } - - func payloadSummary(_ job: CronJob) -> some View { - let payload = job.payload - return VStack(alignment: .leading, spacing: 6) { - Text("Payload") - .font(.caption.weight(.semibold)) - .foregroundStyle(.secondary) - switch payload { - case let .systemEvent(text): - Text(text) - .font(.callout) - .textSelection(.enabled) - case let .agentTurn(message, thinking, timeoutSeconds, _, _, _, _): - VStack(alignment: .leading, spacing: 4) { - Text(message) - .font(.callout) - .textSelection(.enabled) - HStack(spacing: 8) { - if let thinking, !thinking.isEmpty { StatusPill(text: "think \(thinking)", tint: .secondary) } - if let timeoutSeconds { StatusPill(text: "\(timeoutSeconds)s", tint: .secondary) } - if job.sessionTarget == .isolated { - let delivery = job.delivery - if let delivery { - if delivery.mode == .announce { - StatusPill(text: "announce", tint: .secondary) - if let channel = delivery.channel, !channel.isEmpty { - StatusPill(text: channel, tint: .secondary) - } - if let to = delivery.to, !to.isEmpty { StatusPill(text: to, tint: .secondary) } - } else { - StatusPill(text: "no delivery", tint: .secondary) - } - } - } - } - } - } - } - } -} diff --git a/apps/macos/Sources/OpenClaw/CronSettings+Testing.swift b/apps/macos/Sources/OpenClaw/CronSettings+Testing.swift deleted file mode 100644 index 4b51a4a9e9c..00000000000 --- a/apps/macos/Sources/OpenClaw/CronSettings+Testing.swift +++ /dev/null @@ -1,121 +0,0 @@ -import SwiftUI - -#if DEBUG -struct CronSettings_Previews: PreviewProvider { - static var previews: some View { - let store = CronJobsStore(isPreview: true) - store.jobs = [ - CronJob( - id: "job-1", - agentId: "ops", - name: "Daily summary", - description: nil, - enabled: true, - deleteAfterRun: nil, - createdAtMs: 0, - updatedAtMs: 0, - schedule: .every(everyMs: 86_400_000, anchorMs: nil), - sessionTarget: .isolated, - wakeMode: .now, - payload: .agentTurn( - message: "Summarize inbox", - thinking: "low", - timeoutSeconds: 600, - deliver: nil, - channel: nil, - to: nil, - bestEffortDeliver: nil), - delivery: CronDelivery(mode: .announce, channel: "last", to: nil, bestEffort: true), - state: CronJobState( - nextRunAtMs: Int(Date().addingTimeInterval(3600).timeIntervalSince1970 * 1000), - runningAtMs: nil, - lastRunAtMs: nil, - lastStatus: nil, - lastError: nil, - lastDurationMs: nil)), - ] - store.selectedJobId = "job-1" - store.runEntries = [ - CronRunLogEntry( - ts: Int(Date().timeIntervalSince1970 * 1000), - jobId: "job-1", - action: "finished", - status: "ok", - error: nil, - summary: "All good.", - runAtMs: nil, - durationMs: 1234, - nextRunAtMs: nil), - ] - return CronSettings(store: store, channelsStore: ChannelsStore(isPreview: true)) - .frame(width: SettingsTab.windowWidth, height: SettingsTab.windowHeight) - } -} - -@MainActor -extension CronSettings { - static func exerciseForTesting() { - let store = CronJobsStore(isPreview: true) - store.schedulerEnabled = false - store.schedulerStorePath = "/tmp/openclaw-cron-store.json" - - let job = CronJob( - id: "job-1", - agentId: "ops", - name: "Daily summary", - description: "Summary job", - enabled: true, - deleteAfterRun: nil, - createdAtMs: 1_700_000_000_000, - updatedAtMs: 1_700_000_100_000, - schedule: .cron(expr: "0 8 * * *", tz: "UTC"), - sessionTarget: .isolated, - wakeMode: .nextHeartbeat, - payload: .agentTurn( - message: "Summarize", - thinking: "low", - timeoutSeconds: 120, - deliver: nil, - channel: nil, - to: nil, - bestEffortDeliver: nil), - delivery: CronDelivery(mode: .announce, channel: "whatsapp", to: "+15551234567", bestEffort: true), - state: CronJobState( - nextRunAtMs: 1_700_000_200_000, - runningAtMs: nil, - lastRunAtMs: 1_700_000_050_000, - lastStatus: "ok", - lastError: nil, - lastDurationMs: 1200)) - - let run = CronRunLogEntry( - ts: 1_700_000_050_000, - jobId: job.id, - action: "finished", - status: "ok", - error: nil, - summary: "done", - runAtMs: 1_700_000_050_000, - durationMs: 1200, - nextRunAtMs: 1_700_000_200_000) - - store.jobs = [job] - store.selectedJobId = job.id - store.runEntries = [run] - - let view = CronSettings(store: store, channelsStore: ChannelsStore(isPreview: true)) - _ = view.body - _ = view.jobRow(job) - _ = view.jobContextMenu(job) - _ = view.detailHeader(job) - _ = view.detailCard(job) - _ = view.runHistoryCard(job) - _ = view.runRow(run) - _ = view.payloadSummary(job) - _ = view.scheduleSummary(job.schedule) - _ = view.statusTint(job.state.lastStatus) - _ = view.nextRunLabel(Date()) - _ = view.formatDuration(ms: 1234) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/CronSettings.swift b/apps/macos/Sources/OpenClaw/CronSettings.swift deleted file mode 100644 index 999712a595d..00000000000 --- a/apps/macos/Sources/OpenClaw/CronSettings.swift +++ /dev/null @@ -1,17 +0,0 @@ -import Observation -import SwiftUI - -struct CronSettings: View { - @Bindable var store: CronJobsStore - @Bindable var channelsStore: ChannelsStore - @State var showEditor = false - @State var editingJob: CronJob? - @State var editorError: String? - @State var isSaving = false - @State var confirmDelete: CronJob? - - init(store: CronJobsStore = .shared, channelsStore: ChannelsStore = .shared) { - self.store = store - self.channelsStore = channelsStore - } -} diff --git a/apps/macos/Sources/OpenClaw/DebugActions.swift b/apps/macos/Sources/OpenClaw/DebugActions.swift deleted file mode 100644 index 706d9cc2ca2..00000000000 --- a/apps/macos/Sources/OpenClaw/DebugActions.swift +++ /dev/null @@ -1,265 +0,0 @@ -import AppKit -import Foundation -import SwiftUI - -enum DebugActions { - private static let verboseDefaultsKey = "openclaw.debug.verboseMain" - private static let sessionMenuLimit = 12 - private static let onboardingSeenKey = "openclaw.onboardingSeen" - - @MainActor - static func openAgentEventsWindow() { - let window = NSWindow( - contentRect: NSRect(x: 0, y: 0, width: 620, height: 420), - styleMask: [.titled, .closable, .miniaturizable, .resizable], - backing: .buffered, - defer: false) - window.title = "Agent Events" - window.isReleasedWhenClosed = false - window.contentView = NSHostingView(rootView: AgentEventsWindow()) - window.center() - window.makeKeyAndOrderFront(nil) - NSApp.activate(ignoringOtherApps: true) - } - - @MainActor - static func openLog() { - let path = self.pinoLogPath() - let url = URL(fileURLWithPath: path) - guard FileManager().fileExists(atPath: path) else { - let alert = NSAlert() - alert.messageText = "Log file not found" - alert.informativeText = path - alert.runModal() - return - } - NSWorkspace.shared.activateFileViewerSelecting([url]) - } - - @MainActor - static func openConfigFolder() { - let url = OpenClawPaths.stateDirURL - NSWorkspace.shared.activateFileViewerSelecting([url]) - } - - @MainActor - static func openSessionStore() { - if AppStateStore.shared.connectionMode == .remote { - let alert = NSAlert() - alert.messageText = "Remote mode" - alert.informativeText = "Session store lives on the gateway host in remote mode." - alert.runModal() - return - } - let path = self.resolveSessionStorePath() - let url = URL(fileURLWithPath: path) - if FileManager().fileExists(atPath: path) { - NSWorkspace.shared.activateFileViewerSelecting([url]) - } else { - NSWorkspace.shared.open(url.deletingLastPathComponent()) - } - } - - static func sendTestNotification() async { - _ = await NotificationManager().send(title: "OpenClaw", body: "Test notification", sound: nil) - } - - static func sendDebugVoice() async -> Result { - let message = """ - This is a debug test from the Mac app. Reply with "Debug test works (and a funny pun)" \ - if you received that. - """ - let result = await VoiceWakeForwarder.forward(transcript: message) - switch result { - case .success: - return .success("Sent. Await reply.") - case let .failure(error): - let detail = error.localizedDescription.trimmingCharacters(in: .whitespacesAndNewlines) - return .failure(.message("Send failed: \(detail)")) - } - } - - static func restartGateway() { - Task { @MainActor in - switch AppStateStore.shared.connectionMode { - case .local: - GatewayProcessManager.shared.stop() - // Kick the control channel + health check so the UI recovers immediately. - await GatewayConnection.shared.shutdown() - try? await Task.sleep(nanoseconds: 300_000_000) - GatewayProcessManager.shared.setActive(true) - Task { try? await ControlChannel.shared.configure(mode: .local) } - Task { await HealthStore.shared.refresh(onDemand: true) } - - case .remote: - // In remote mode, there is no local gateway to restart. "Restart Gateway" should - // reset the SSH control tunnel + reconnect so the menu recovers. - await RemoteTunnelManager.shared.stopAll() - await GatewayConnection.shared.shutdown() - do { - _ = try await RemoteTunnelManager.shared.ensureControlTunnel() - let settings = CommandResolver.connectionSettings() - try await ControlChannel.shared.configure(mode: .remote( - target: settings.target, - identity: settings.identity)) - } catch { - // ControlChannel will surface a degraded state; also refresh health to update the menu text. - Task { await HealthStore.shared.refresh(onDemand: true) } - } - - case .unconfigured: - await GatewayConnection.shared.shutdown() - await ControlChannel.shared.disconnect() - } - } - } - - static func resetGatewayTunnel() async -> Result { - let mode = CommandResolver.connectionSettings().mode - guard mode == .remote else { - return .failure(.message("Remote mode is not enabled.")) - } - await RemoteTunnelManager.shared.stopAll() - await GatewayConnection.shared.shutdown() - do { - _ = try await RemoteTunnelManager.shared.ensureControlTunnel() - let settings = CommandResolver.connectionSettings() - try await ControlChannel.shared.configure(mode: .remote( - target: settings.target, - identity: settings.identity)) - await HealthStore.shared.refresh(onDemand: true) - return .success("SSH tunnel reset.") - } catch { - Task { await HealthStore.shared.refresh(onDemand: true) } - return .failure(.message(error.localizedDescription)) - } - } - - static func pinoLogPath() -> String { - LogLocator.bestLogFile()?.path ?? LogLocator.launchdLogPath - } - - @MainActor - static func runHealthCheckNow() async { - await HealthStore.shared.refresh(onDemand: true) - } - - static func sendTestHeartbeat() async -> Result { - do { - _ = await GatewayConnection.shared.setHeartbeatsEnabled(true) - await ControlChannel.shared.configure() - let data = try await ControlChannel.shared.request(method: "last-heartbeat") - if let evt = try? JSONDecoder().decode(ControlHeartbeatEvent.self, from: data) { - return .success(evt) - } - return .success(nil) - } catch { - return .failure(error) - } - } - - static var verboseLoggingEnabledMain: Bool { - UserDefaults.standard.bool(forKey: self.verboseDefaultsKey) - } - - static func toggleVerboseLoggingMain() async -> Bool { - let newValue = !self.verboseLoggingEnabledMain - UserDefaults.standard.set(newValue, forKey: self.verboseDefaultsKey) - _ = try? await ControlChannel.shared.request( - method: "system-event", - params: ["text": AnyHashable("verbose-main:\(newValue ? "on" : "off")")]) - return newValue - } - - @MainActor - static func restartApp() { - let url = Bundle.main.bundleURL - let task = Process() - // Relaunch shortly after this instance exits so we get a true restart even in debug. - task.launchPath = "/bin/sh" - task.arguments = ["-c", "sleep 0.2; open -n \"$1\"", "_", url.path] - try? task.run() - NSApp.terminate(nil) - } - - @MainActor - static func restartOnboarding() { - UserDefaults.standard.set(false, forKey: self.onboardingSeenKey) - UserDefaults.standard.set(0, forKey: onboardingVersionKey) - AppStateStore.shared.onboardingSeen = false - OnboardingController.shared.restart() - } - - @MainActor - private static func resolveSessionStorePath() -> String { - let defaultPath = SessionLoader.defaultStorePath - let configURL = OpenClawPaths.configURL - guard - let data = try? Data(contentsOf: configURL), - let parsed = try? JSONSerialization.jsonObject(with: data) as? [String: Any], - let session = parsed["session"] as? [String: Any], - let path = session["store"] as? String, - !path.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty - else { - return defaultPath - } - return path - } - - // MARK: - Sessions (thinking / verbose) - - static func recentSessions(limit: Int = sessionMenuLimit) async -> [SessionRow] { - guard let snapshot = try? await SessionLoader.loadSnapshot(limit: limit) else { return [] } - return Array(snapshot.rows.prefix(limit)) - } - - static func updateSession( - key: String, - thinking: String?, - verbose: String?) async throws - { - var params: [String: AnyHashable] = ["key": AnyHashable(key)] - params["thinkingLevel"] = thinking.map(AnyHashable.init) ?? AnyHashable(NSNull()) - params["verboseLevel"] = verbose.map(AnyHashable.init) ?? AnyHashable(NSNull()) - _ = try await ControlChannel.shared.request(method: "sessions.patch", params: params) - } - - // MARK: - Port diagnostics - - typealias PortListener = PortGuardian.ReportListener - typealias PortReport = PortGuardian.PortReport - - static func checkGatewayPorts() async -> [PortReport] { - let mode = CommandResolver.connectionSettings().mode - return await PortGuardian.shared.diagnose(mode: mode) - } - - static func killProcess(_ pid: Int) async -> Result { - let primary = await ShellExecutor.run(command: ["kill", "-TERM", "\(pid)"], cwd: nil, env: nil, timeout: 2) - if primary.ok { return .success(()) } - let force = await ShellExecutor.run(command: ["kill", "-KILL", "\(pid)"], cwd: nil, env: nil, timeout: 2) - if force.ok { return .success(()) } - let detail = force.message ?? primary.message ?? "kill failed" - return .failure(.message(detail)) - } - - @MainActor - static func openSessionStoreInCode() { - let path = SessionLoader.defaultStorePath - let proc = Process() - proc.launchPath = "/usr/bin/env" - proc.arguments = ["code", path] - try? proc.run() - } -} - -enum DebugActionError: LocalizedError { - case message(String) - - var errorDescription: String? { - switch self { - case let .message(text): - text - } - } -} diff --git a/apps/macos/Sources/OpenClaw/DebugSettings.swift b/apps/macos/Sources/OpenClaw/DebugSettings.swift deleted file mode 100644 index 678ffc9e3ff..00000000000 --- a/apps/macos/Sources/OpenClaw/DebugSettings.swift +++ /dev/null @@ -1,1026 +0,0 @@ -import AppKit -import Observation -import SwiftUI -import UniformTypeIdentifiers - -struct DebugSettings: View { - @Bindable var state: AppState - private let isPreview = ProcessInfo.processInfo.isPreview - private let labelColumnWidth: CGFloat = 140 - @AppStorage(modelCatalogPathKey) private var modelCatalogPath: String = ModelCatalogLoader.defaultPath - @AppStorage(modelCatalogReloadKey) private var modelCatalogReloadBump: Int = 0 - @AppStorage(iconOverrideKey) private var iconOverrideRaw: String = IconOverrideSelection.system.rawValue - @AppStorage(canvasEnabledKey) private var canvasEnabled: Bool = true - @State private var modelsCount: Int? - @State private var modelsLoading = false - @State private var modelsError: String? - private let gatewayManager = GatewayProcessManager.shared - private let healthStore = HealthStore.shared - @State private var launchAgentWriteDisabled = GatewayLaunchAgentManager.isLaunchAgentWriteDisabled() - @State private var launchAgentWriteError: String? - @State private var gatewayRootInput: String = GatewayProcessManager.shared.projectRootPath() - @State private var sessionStorePath: String = SessionLoader.defaultStorePath - @State private var sessionStoreSaveError: String? - @State private var debugSendInFlight = false - @State private var debugSendStatus: String? - @State private var debugSendError: String? - @State private var portCheckInFlight = false - @State private var portReports: [DebugActions.PortReport] = [] - @State private var portKillStatus: String? - @State private var tunnelResetInFlight = false - @State private var tunnelResetStatus: String? - @State private var pendingKill: DebugActions.PortListener? - @AppStorage(debugFileLogEnabledKey) private var diagnosticsFileLogEnabled: Bool = false - @AppStorage(appLogLevelKey) private var appLogLevelRaw: String = AppLogLevel.default.rawValue - - @State private var canvasSessionKey: String = "main" - @State private var canvasStatus: String? - @State private var canvasError: String? - @State private var canvasEvalJS: String = "document.title" - @State private var canvasEvalResult: String? - @State private var canvasSnapshotPath: String? - - init(state: AppState = AppStateStore.shared) { - self.state = state - } - - var body: some View { - ScrollView(.vertical) { - VStack(alignment: .leading, spacing: 14) { - self.header - - self.launchdSection - self.appInfoSection - self.gatewaySection - self.logsSection - self.portsSection - self.pathsSection - self.quickActionsSection - self.canvasSection - self.experimentsSection - - Spacer(minLength: 0) - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal, 24) - .padding(.vertical, 18) - .groupBoxStyle(PlainSettingsGroupBoxStyle()) - } - .task { - guard !self.isPreview else { return } - await self.reloadModels() - self.loadSessionStorePath() - } - .alert(item: self.$pendingKill) { listener in - Alert( - title: Text("Kill \(listener.command) (\(listener.pid))?"), - message: Text("This process looks expected for the current mode. Kill anyway?"), - primaryButton: .destructive(Text("Kill")) { - Task { await self.killConfirmed(listener.pid) } - }, - secondaryButton: .cancel()) - } - } - - private var launchdSection: some View { - GroupBox("Gateway startup") { - VStack(alignment: .leading, spacing: 8) { - Toggle("Attach only (skip launchd install)", isOn: self.$launchAgentWriteDisabled) - .onChange(of: self.launchAgentWriteDisabled) { _, newValue in - self.launchAgentWriteError = GatewayLaunchAgentManager.setLaunchAgentWriteDisabled(newValue) - if self.launchAgentWriteError != nil { - self.launchAgentWriteDisabled = GatewayLaunchAgentManager.isLaunchAgentWriteDisabled() - return - } - if newValue { - Task { - _ = await GatewayLaunchAgentManager.set( - enabled: false, - bundlePath: Bundle.main.bundlePath, - port: GatewayEnvironment.gatewayPort()) - } - } - } - - Text( - "When enabled, OpenClaw won't install or manage \(gatewayLaunchdLabel). " + - "It will only attach to an existing Gateway.") - .font(.caption) - .foregroundStyle(.secondary) - - if let launchAgentWriteError { - Text(launchAgentWriteError) - .font(.caption) - .foregroundStyle(.red) - } - } - } - } - - private var header: some View { - VStack(alignment: .leading, spacing: 6) { - Text("Debug") - .font(.title3.weight(.semibold)) - Text("Tools for diagnosing local issues (Gateway, ports, logs, Canvas).") - .font(.callout) - .foregroundStyle(.secondary) - } - } - - private func gridLabel(_ text: String) -> some View { - Text(text) - .foregroundStyle(.secondary) - .frame(width: self.labelColumnWidth, alignment: .leading) - } - - private var appInfoSection: some View { - GroupBox("App") { - Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) { - GridRow { - self.gridLabel("Health") - HStack(spacing: 8) { - Circle().fill(self.healthStore.state.tint).frame(width: 10, height: 10) - Text(self.healthStore.summaryLine) - } - .frame(maxWidth: .infinity, alignment: .leading) - } - GridRow { - self.gridLabel("CLI") - let loc = CLIInstaller.installedLocation() - Text(loc ?? "missing") - .font(.caption.monospaced()) - .foregroundStyle(loc == nil ? Color.red : Color.secondary) - .textSelection(.enabled) - .lineLimit(1) - .truncationMode(.middle) - } - GridRow { - self.gridLabel("PID") - Text("\(ProcessInfo.processInfo.processIdentifier)") - } - GridRow { - self.gridLabel("Binary path") - Text(Bundle.main.bundlePath) - .font(.caption2.monospaced()) - .foregroundStyle(.secondary) - .textSelection(.enabled) - .lineLimit(1) - .truncationMode(.middle) - } - } - } - } - - private var gatewaySection: some View { - GroupBox("Gateway") { - VStack(alignment: .leading, spacing: 10) { - Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) { - GridRow { - self.gridLabel("Status") - HStack(spacing: 8) { - Text(self.gatewayManager.status.label) - } - .frame(maxWidth: .infinity, alignment: .leading) - } - } - - let key = DeepLinkHandler.currentKey() - HStack(spacing: 8) { - Text("Key") - .foregroundStyle(.secondary) - .frame(width: self.labelColumnWidth, alignment: .leading) - Text(key) - .font(.caption2.monospaced()) - .foregroundStyle(.secondary) - .textSelection(.enabled) - .lineLimit(1) - .truncationMode(.middle) - Button("Copy") { - NSPasteboard.general.clearContents() - NSPasteboard.general.setString(key, forType: .string) - } - .buttonStyle(.bordered) - Button("Copy sample URL") { - let msg = "Hello from deep link" - let encoded = msg.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? msg - let url = "openclaw://agent?message=\(encoded)&key=\(key)" - NSPasteboard.general.clearContents() - NSPasteboard.general.setString(url, forType: .string) - } - .buttonStyle(.bordered) - Spacer(minLength: 0) - } - - Text("Deep links (openclaw://…) are always enabled; the key controls unattended runs.") - .font(.caption2) - .foregroundStyle(.secondary) - - VStack(alignment: .leading, spacing: 6) { - Text("Stdout / stderr") - .font(.caption.weight(.semibold)) - ScrollView { - Text(self.gatewayManager.log.isEmpty ? "—" : self.gatewayManager.log) - .font(.caption.monospaced()) - .frame(maxWidth: .infinity, alignment: .leading) - .textSelection(.enabled) - } - .frame(height: 180) - .overlay(RoundedRectangle(cornerRadius: 6).stroke(Color.secondary.opacity(0.2))) - - HStack(spacing: 8) { - if self.canRestartGateway { - Button("Restart Gateway") { DebugActions.restartGateway() } - } - Button("Clear log") { GatewayProcessManager.shared.clearLog() } - Spacer(minLength: 0) - } - .buttonStyle(.bordered) - } - } - } - } - - private var logsSection: some View { - GroupBox("Logs") { - Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) { - GridRow { - self.gridLabel("Pino log") - VStack(alignment: .leading, spacing: 6) { - HStack(spacing: 8) { - Button("Open") { DebugActions.openLog() } - .buttonStyle(.bordered) - Text(DebugActions.pinoLogPath()) - .font(.caption2.monospaced()) - .foregroundStyle(.secondary) - .textSelection(.enabled) - .lineLimit(1) - .truncationMode(.middle) - } - } - } - - GridRow { - self.gridLabel("App logging") - VStack(alignment: .leading, spacing: 8) { - Picker("Verbosity", selection: self.$appLogLevelRaw) { - ForEach(AppLogLevel.allCases) { level in - Text(level.title).tag(level.rawValue) - } - } - .pickerStyle(.menu) - .labelsHidden() - .help("Controls the macOS app log verbosity.") - - Toggle("Write rolling diagnostics log (JSONL)", isOn: self.$diagnosticsFileLogEnabled) - .toggleStyle(.checkbox) - .help( - "Writes a rotating, local-only log under ~/Library/Logs/OpenClaw/. " + - "Enable only while actively debugging.") - - HStack(spacing: 8) { - Button("Open folder") { - NSWorkspace.shared.open(DiagnosticsFileLog.logDirectoryURL()) - } - .buttonStyle(.bordered) - Button("Clear") { - Task { try? await DiagnosticsFileLog.shared.clear() } - } - .buttonStyle(.bordered) - } - Text(DiagnosticsFileLog.logFileURL().path) - .font(.caption2.monospaced()) - .foregroundStyle(.secondary) - .textSelection(.enabled) - .lineLimit(1) - .truncationMode(.middle) - } - } - } - } - } - - private var portsSection: some View { - GroupBox("Ports") { - VStack(alignment: .leading, spacing: 10) { - HStack(spacing: 8) { - Text("Port diagnostics") - .font(.caption.weight(.semibold)) - if self.portCheckInFlight { ProgressView().controlSize(.small) } - Spacer() - Button("Check gateway ports") { - Task { await self.runPortCheck() } - } - .buttonStyle(.borderedProminent) - .disabled(self.portCheckInFlight) - Button("Reset SSH tunnel") { - Task { await self.resetGatewayTunnel() } - } - .buttonStyle(.bordered) - .disabled(self.tunnelResetInFlight || !self.isRemoteMode) - } - - if let portKillStatus { - Text(portKillStatus) - .font(.caption2) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - if let tunnelResetStatus { - Text(tunnelResetStatus) - .font(.caption2) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - - if self.portReports.isEmpty, !self.portCheckInFlight { - Text("Check which process owns \(GatewayEnvironment.gatewayPort()) and suggest fixes.") - .font(.caption2) - .foregroundStyle(.secondary) - } else { - ForEach(self.portReports) { report in - VStack(alignment: .leading, spacing: 4) { - Text("Port \(report.port)") - .font(.footnote.weight(.semibold)) - Text(report.summary) - .font(.caption) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - ForEach(report.listeners) { listener in - VStack(alignment: .leading, spacing: 2) { - HStack(spacing: 8) { - Text("\(listener.command) (\(listener.pid))") - .font(.caption.monospaced()) - .foregroundStyle(listener.expected ? .secondary : Color.red) - .lineLimit(1) - Spacer() - Button("Kill") { - self.requestKill(listener) - } - .buttonStyle(.bordered) - } - Text(listener.fullCommand) - .font(.caption2.monospaced()) - .foregroundStyle(.secondary) - .lineLimit(2) - .truncationMode(.middle) - } - .padding(6) - .background(Color.secondary.opacity(0.05)) - .cornerRadius(4) - } - } - .padding(8) - .background(Color.secondary.opacity(0.08)) - .cornerRadius(6) - } - } - } - } - } - - private var pathsSection: some View { - GroupBox("Paths") { - VStack(alignment: .leading, spacing: 12) { - VStack(alignment: .leading, spacing: 6) { - Text("OpenClaw project root") - .font(.caption.weight(.semibold)) - HStack(spacing: 8) { - TextField("Path to openclaw repo", text: self.$gatewayRootInput) - .textFieldStyle(.roundedBorder) - .font(.caption.monospaced()) - .onSubmit { self.saveRelayRoot() } - Button("Save") { self.saveRelayRoot() } - .buttonStyle(.borderedProminent) - Button("Reset") { - let def = FileManager().homeDirectoryForCurrentUser - .appendingPathComponent("Projects/openclaw").path - self.gatewayRootInput = def - self.saveRelayRoot() - } - .buttonStyle(.bordered) - } - Text("Used for pnpm/node fallback and PATH population when launching the gateway.") - .font(.caption2) - .foregroundStyle(.secondary) - } - - Divider() - - Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) { - GridRow { - self.gridLabel("Session store") - VStack(alignment: .leading, spacing: 6) { - HStack(spacing: 8) { - TextField("Path", text: self.$sessionStorePath) - .textFieldStyle(.roundedBorder) - .font(.caption.monospaced()) - .frame(width: 360) - Button("Save") { self.saveSessionStorePath() } - .buttonStyle(.borderedProminent) - } - if let sessionStoreSaveError { - Text(sessionStoreSaveError) - .font(.footnote) - .foregroundStyle(.secondary) - } else { - Text("Used by the CLI session loader; stored in ~/.openclaw/openclaw.json.") - .font(.footnote) - .foregroundStyle(.secondary) - } - } - } - GridRow { - self.gridLabel("Model catalog") - VStack(alignment: .leading, spacing: 6) { - Text(self.modelCatalogPath) - .font(.caption.monospaced()) - .foregroundStyle(.secondary) - .lineLimit(2) - HStack(spacing: 8) { - Button { - self.chooseCatalogFile() - } label: { - Label("Choose models.generated.ts…", systemImage: "folder") - } - .buttonStyle(.bordered) - - Button { - Task { await self.reloadModels() } - } label: { - Label( - self.modelsLoading ? "Reloading…" : "Reload models", - systemImage: "arrow.clockwise") - } - .buttonStyle(.bordered) - .disabled(self.modelsLoading) - } - if let modelsError { - Text(modelsError) - .font(.footnote) - .foregroundStyle(.secondary) - } else if let modelsCount { - Text("Loaded \(modelsCount) models") - .font(.footnote) - .foregroundStyle(.secondary) - } - Text("Local fallback for model picker when gateway models.list is unavailable.") - .font(.footnote) - .foregroundStyle(.tertiary) - } - } - } - } - } - } - - private var quickActionsSection: some View { - GroupBox("Quick actions") { - VStack(alignment: .leading, spacing: 10) { - HStack(spacing: 8) { - Button("Send Test Notification") { - Task { await DebugActions.sendTestNotification() } - } - .buttonStyle(.bordered) - - Button("Open Agent Events") { - DebugActions.openAgentEventsWindow() - } - .buttonStyle(.borderedProminent) - - Spacer(minLength: 0) - } - - VStack(alignment: .leading, spacing: 6) { - Button { - Task { await self.sendVoiceDebug() } - } label: { - Label( - self.debugSendInFlight ? "Sending debug voice…" : "Send debug voice", - systemImage: self.debugSendInFlight ? "bolt.horizontal.circle" : "waveform") - } - .buttonStyle(.borderedProminent) - .disabled(self.debugSendInFlight) - - if !self.debugSendInFlight { - if let debugSendStatus { - Text(debugSendStatus) - .font(.caption) - .foregroundStyle(.secondary) - } else if let debugSendError { - Text(debugSendError) - .font(.caption) - .foregroundStyle(.red) - } else { - Text( - """ - Uses the Voice Wake path: forwards over SSH when configured, - otherwise runs locally via rpc. - """) - .font(.caption) - .foregroundStyle(.secondary) - } - } - } - - VStack(alignment: .leading, spacing: 6) { - Text( - "Note: macOS may require restarting OpenClaw after enabling Accessibility or Screen Recording.") - .font(.caption) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - - Button { - LaunchdManager.startOpenClaw() - } label: { - Label("Restart OpenClaw", systemImage: "arrow.counterclockwise") - } - .buttonStyle(.bordered) - .controlSize(.small) - } - - HStack(spacing: 8) { - Button("Restart app") { DebugActions.restartApp() } - Button("Restart onboarding") { DebugActions.restartOnboarding() } - Button("Reveal app in Finder") { self.revealApp() } - Spacer(minLength: 0) - } - .buttonStyle(.bordered) - } - } - } - - private var canvasSection: some View { - GroupBox("Canvas") { - VStack(alignment: .leading, spacing: 10) { - Text("Enable/disable Canvas in General settings.") - .font(.caption) - .foregroundStyle(.secondary) - - HStack(spacing: 8) { - TextField("Session", text: self.$canvasSessionKey) - .textFieldStyle(.roundedBorder) - .font(.caption.monospaced()) - .frame(width: 160) - Button("Show panel") { - Task { await self.canvasPresent() } - } - .buttonStyle(.borderedProminent) - Button("Hide panel") { - CanvasManager.shared.hideAll() - self.canvasStatus = "hidden" - self.canvasError = nil - } - .buttonStyle(.bordered) - Button("Write sample page") { - Task { await self.canvasWriteSamplePage() } - } - .buttonStyle(.bordered) - Spacer(minLength: 0) - } - - HStack(spacing: 8) { - TextField("Eval JS", text: self.$canvasEvalJS) - .textFieldStyle(.roundedBorder) - .font(.caption.monospaced()) - .frame(maxWidth: 520) - Button("Eval") { - Task { await self.canvasEval() } - } - .buttonStyle(.bordered) - Button("Snapshot") { - Task { await self.canvasSnapshot() } - } - .buttonStyle(.bordered) - Spacer(minLength: 0) - } - - if let canvasStatus { - Text(canvasStatus) - .font(.caption2.monospaced()) - .foregroundStyle(.secondary) - .textSelection(.enabled) - } - if let canvasEvalResult { - Text("eval → \(canvasEvalResult)") - .font(.caption2.monospaced()) - .foregroundStyle(.secondary) - .lineLimit(2) - .truncationMode(.middle) - .textSelection(.enabled) - } - if let canvasSnapshotPath { - HStack(spacing: 8) { - Text("snapshot → \(canvasSnapshotPath)") - .font(.caption2.monospaced()) - .foregroundStyle(.secondary) - .lineLimit(1) - .truncationMode(.middle) - .textSelection(.enabled) - Button("Reveal") { - NSWorkspace.shared - .activateFileViewerSelecting([URL(fileURLWithPath: canvasSnapshotPath)]) - } - .buttonStyle(.bordered) - Spacer(minLength: 0) - } - } - if let canvasError { - Text(canvasError) - .font(.caption2) - .foregroundStyle(.red) - } else { - Text("Tip: the session directory is returned by “Show panel”.") - .font(.caption2) - .foregroundStyle(.tertiary) - } - } - } - } - - private var experimentsSection: some View { - GroupBox("Experiments") { - Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) { - GridRow { - self.gridLabel("Icon override") - Picker("", selection: self.bindingOverride) { - ForEach(IconOverrideSelection.allCases) { option in - Text(option.label).tag(option.rawValue) - } - } - .labelsHidden() - .frame(maxWidth: 280, alignment: .leading) - } - GridRow { - self.gridLabel("Chat") - Text("Native SwiftUI") - .font(.callout) - .foregroundStyle(.secondary) - } - } - } - } - - @MainActor - private func runPortCheck() async { - self.portCheckInFlight = true - self.portKillStatus = nil - let reports = await DebugActions.checkGatewayPorts() - self.portReports = reports - self.portCheckInFlight = false - } - - @MainActor - private func resetGatewayTunnel() async { - self.tunnelResetInFlight = true - self.tunnelResetStatus = nil - let result = await DebugActions.resetGatewayTunnel() - switch result { - case let .success(message): - self.tunnelResetStatus = message - case let .failure(err): - self.tunnelResetStatus = err.localizedDescription - } - await self.runPortCheck() - self.tunnelResetInFlight = false - } - - @MainActor - private func requestKill(_ listener: DebugActions.PortListener) { - if listener.expected { - self.pendingKill = listener - } else { - Task { await self.killConfirmed(listener.pid) } - } - } - - @MainActor - private func killConfirmed(_ pid: Int32) async { - let result = await DebugActions.killProcess(Int(pid)) - switch result { - case .success: - self.portKillStatus = "Sent kill to \(pid)." - await self.runPortCheck() - case let .failure(err): - self.portKillStatus = "Kill \(pid) failed: \(err.localizedDescription)" - } - } - - private func chooseCatalogFile() { - let panel = NSOpenPanel() - panel.title = "Select models.generated.ts" - let tsType = UTType(filenameExtension: "ts") - ?? UTType(tag: "ts", tagClass: .filenameExtension, conformingTo: .sourceCode) - ?? .item - panel.allowedContentTypes = [tsType] - panel.allowsMultipleSelection = false - panel.directoryURL = URL(fileURLWithPath: self.modelCatalogPath).deletingLastPathComponent() - if panel.runModal() == .OK, let url = panel.url { - self.modelCatalogPath = url.path - self.modelCatalogReloadBump += 1 - Task { await self.reloadModels() } - } - } - - private func reloadModels() async { - guard !self.modelsLoading else { return } - self.modelsLoading = true - self.modelsError = nil - self.modelCatalogReloadBump += 1 - defer { self.modelsLoading = false } - do { - let loaded = try await ModelCatalogLoader.load(from: self.modelCatalogPath) - self.modelsCount = loaded.count - } catch { - self.modelsCount = nil - self.modelsError = error.localizedDescription - } - } - - private func sendVoiceDebug() async { - await MainActor.run { - self.debugSendInFlight = true - self.debugSendError = nil - self.debugSendStatus = nil - } - - let result = await DebugActions.sendDebugVoice() - - await MainActor.run { - self.debugSendInFlight = false - switch result { - case let .success(message): - self.debugSendStatus = message - self.debugSendError = nil - case let .failure(error): - self.debugSendStatus = nil - self.debugSendError = error.localizedDescription - } - } - } - - private func revealApp() { - let url = Bundle.main.bundleURL - NSWorkspace.shared.activateFileViewerSelecting([url]) - } - - private func saveRelayRoot() { - GatewayProcessManager.shared.setProjectRoot(path: self.gatewayRootInput) - } - - private func loadSessionStorePath() { - let url = self.configURL() - guard - let data = try? Data(contentsOf: url), - let parsed = try? JSONSerialization.jsonObject(with: data) as? [String: Any], - let session = parsed["session"] as? [String: Any], - let path = session["store"] as? String - else { - self.sessionStorePath = SessionLoader.defaultStorePath - return - } - self.sessionStorePath = path - } - - private func saveSessionStorePath() { - let trimmed = self.sessionStorePath.trimmingCharacters(in: .whitespacesAndNewlines) - var root: [String: Any] = [:] - let url = self.configURL() - if let data = try? Data(contentsOf: url), - let parsed = try? JSONSerialization.jsonObject(with: data) as? [String: Any] - { - root = parsed - } - - var session = root["session"] as? [String: Any] ?? [:] - session["store"] = trimmed.isEmpty ? SessionLoader.defaultStorePath : trimmed - root["session"] = session - - do { - let data = try JSONSerialization.data(withJSONObject: root, options: [.prettyPrinted, .sortedKeys]) - try FileManager().createDirectory( - at: url.deletingLastPathComponent(), - withIntermediateDirectories: true) - try data.write(to: url, options: [.atomic]) - self.sessionStoreSaveError = nil - } catch { - self.sessionStoreSaveError = error.localizedDescription - } - } - - private var bindingOverride: Binding { - Binding { - self.iconOverrideRaw - } set: { newValue in - self.iconOverrideRaw = newValue - if let selection = IconOverrideSelection(rawValue: newValue) { - Task { @MainActor in - AppStateStore.shared.iconOverride = selection - WorkActivityStore.shared.resolveIconState(override: selection) - } - } - } - } - - private var isRemoteMode: Bool { - CommandResolver.connectionSettings().mode == .remote - } - - private var canRestartGateway: Bool { - self.state.connectionMode == .local - } - - private func configURL() -> URL { - OpenClawPaths.configURL - } -} - -extension DebugSettings { - // MARK: - Canvas debug actions - - @MainActor - private func canvasPresent() async { - self.canvasError = nil - let session = self.canvasSessionKey.trimmingCharacters(in: .whitespacesAndNewlines) - do { - let dir = try CanvasManager.shared.show(sessionKey: session.isEmpty ? "main" : session, path: "/") - self.canvasStatus = "dir: \(dir)" - } catch { - self.canvasError = error.localizedDescription - } - } - - @MainActor - private func canvasWriteSamplePage() async { - self.canvasError = nil - let session = self.canvasSessionKey.trimmingCharacters(in: .whitespacesAndNewlines) - do { - let dir = try CanvasManager.shared.show(sessionKey: session.isEmpty ? "main" : session, path: "/") - let url = URL(fileURLWithPath: dir).appendingPathComponent("index.html", isDirectory: false) - let now = ISO8601DateFormatter().string(from: Date()) - let html = """ - - - - - - Canvas Debug - - - -
-
-
Canvas Debug
-
generated: \(now)
-
userAgent:
- -
count: 0
-
-
-
This is a local file served by the WKURLSchemeHandler.
-
-
-
-
-
-
- - - - """ - try html.write(to: url, atomically: true, encoding: .utf8) - self.canvasStatus = "wrote: \(url.path)" - _ = try CanvasManager.shared.show(sessionKey: session.isEmpty ? "main" : session, path: "/") - } catch { - self.canvasError = error.localizedDescription - } - } - - @MainActor - private func canvasEval() async { - self.canvasError = nil - self.canvasEvalResult = nil - do { - let session = self.canvasSessionKey.trimmingCharacters(in: .whitespacesAndNewlines) - let result = try await CanvasManager.shared.eval( - sessionKey: session.isEmpty ? "main" : session, - javaScript: self.canvasEvalJS) - self.canvasEvalResult = result - } catch { - self.canvasError = error.localizedDescription - } - } - - @MainActor - private func canvasSnapshot() async { - self.canvasError = nil - self.canvasSnapshotPath = nil - do { - let session = self.canvasSessionKey.trimmingCharacters(in: .whitespacesAndNewlines) - let path = try await CanvasManager.shared.snapshot( - sessionKey: session.isEmpty ? "main" : session, - outPath: nil) - self.canvasSnapshotPath = path - } catch { - self.canvasError = error.localizedDescription - } - } -} - -struct PlainSettingsGroupBoxStyle: GroupBoxStyle { - func makeBody(configuration: Configuration) -> some View { - VStack(alignment: .leading, spacing: 10) { - configuration.label - .font(.caption.weight(.semibold)) - .foregroundStyle(.secondary) - configuration.content - } - .frame(maxWidth: .infinity, alignment: .leading) - } -} - -#if DEBUG -struct DebugSettings_Previews: PreviewProvider { - static var previews: some View { - DebugSettings(state: .preview) - .frame(width: SettingsTab.windowWidth, height: SettingsTab.windowHeight) - } -} - -@MainActor -extension DebugSettings { - static func exerciseForTesting() async { - let view = DebugSettings(state: .preview) - view.modelsCount = 3 - view.modelsLoading = false - view.modelsError = "Failed to load models" - view.gatewayRootInput = "/tmp/openclaw" - view.sessionStorePath = "/tmp/sessions.json" - view.sessionStoreSaveError = "Save failed" - view.debugSendInFlight = true - view.debugSendStatus = "Sent" - view.debugSendError = "Failed" - view.portCheckInFlight = true - view.portReports = [ - DebugActions.PortReport( - port: GatewayEnvironment.gatewayPort(), - expected: "Gateway websocket (node/tsx)", - status: .missing("Missing"), - listeners: []), - ] - view.portKillStatus = "Killed" - view.pendingKill = DebugActions.PortListener( - pid: 1, - command: "node", - fullCommand: "node", - user: nil, - expected: true) - view.canvasSessionKey = "main" - view.canvasStatus = "Canvas ok" - view.canvasError = "Canvas error" - view.canvasEvalJS = "document.title" - view.canvasEvalResult = "Canvas" - view.canvasSnapshotPath = "/tmp/snapshot.png" - - _ = view.body - _ = view.header - _ = view.appInfoSection - _ = view.gatewaySection - _ = view.logsSection - _ = view.portsSection - _ = view.pathsSection - _ = view.quickActionsSection - _ = view.canvasSection - _ = view.experimentsSection - _ = view.gridLabel("Test") - - view.loadSessionStorePath() - await view.reloadModels() - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/DeepLinks.swift b/apps/macos/Sources/OpenClaw/DeepLinks.swift deleted file mode 100644 index d11d4d524c3..00000000000 --- a/apps/macos/Sources/OpenClaw/DeepLinks.swift +++ /dev/null @@ -1,199 +0,0 @@ -import AppKit -import Foundation -import OpenClawKit -import OSLog -import Security - -private let deepLinkLogger = Logger(subsystem: "ai.openclaw", category: "DeepLink") - -enum DeepLinkAgentPolicy { - static let maxMessageChars = 20000 - static let maxUnkeyedConfirmChars = 240 - - enum ValidationError: Error, Equatable, LocalizedError { - case messageTooLongForConfirmation(max: Int, actual: Int) - - var errorDescription: String? { - switch self { - case let .messageTooLongForConfirmation(max, actual): - "Message is too long to confirm safely (\(actual) chars; max \(max) without key)." - } - } - } - - static func validateMessageForHandle(message: String, allowUnattended: Bool) -> Result { - if !allowUnattended, message.count > self.maxUnkeyedConfirmChars { - return .failure(.messageTooLongForConfirmation(max: self.maxUnkeyedConfirmChars, actual: message.count)) - } - return .success(()) - } - - static func effectiveDelivery( - link: AgentDeepLink, - allowUnattended: Bool) -> (deliver: Bool, to: String?, channel: GatewayAgentChannel) - { - if !allowUnattended { - // Without the unattended key, ignore delivery/routing knobs to reduce exfiltration risk. - return (deliver: false, to: nil, channel: .last) - } - let channel = GatewayAgentChannel(raw: link.channel) - let deliver = channel.shouldDeliver(link.deliver) - let to = link.to?.trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty - return (deliver: deliver, to: to, channel: channel) - } -} - -@MainActor -final class DeepLinkHandler { - static let shared = DeepLinkHandler() - - private var lastPromptAt: Date = .distantPast - - /// Ephemeral, in-memory key used for unattended deep links originating from the in-app Canvas. - /// This avoids blocking Canvas init on UserDefaults and doesn't weaken the external deep-link prompt: - /// outside callers can't know this randomly generated key. - private nonisolated static let canvasUnattendedKey: String = DeepLinkHandler.generateRandomKey() - - func handle(url: URL) async { - guard let route = DeepLinkParser.parse(url) else { - deepLinkLogger.debug("ignored url \(url.absoluteString, privacy: .public)") - return - } - guard !AppStateStore.shared.isPaused else { - self.presentAlert(title: "OpenClaw is paused", message: "Unpause OpenClaw to run agent actions.") - return - } - - switch route { - case let .agent(link): - await self.handleAgent(link: link, originalURL: url) - case .gateway: - break - } - } - - private func handleAgent(link: AgentDeepLink, originalURL: URL) async { - let messagePreview = link.message.trimmingCharacters(in: .whitespacesAndNewlines) - if messagePreview.count > DeepLinkAgentPolicy.maxMessageChars { - self.presentAlert(title: "Deep link too large", message: "Message exceeds 20,000 characters.") - return - } - - let allowUnattended = link.key == Self.canvasUnattendedKey || link.key == Self.expectedKey() - if !allowUnattended { - if Date().timeIntervalSince(self.lastPromptAt) < 1.0 { - deepLinkLogger.debug("throttling deep link prompt") - return - } - self.lastPromptAt = Date() - - if case let .failure(error) = DeepLinkAgentPolicy.validateMessageForHandle( - message: messagePreview, - allowUnattended: allowUnattended) - { - self.presentAlert(title: "Deep link blocked", message: error.localizedDescription) - return - } - - let urlText = originalURL.absoluteString - let urlPreview = urlText.count > 500 ? "\(urlText.prefix(500))…" : urlText - let body = - "Run the agent with this message?\n\n\(messagePreview)\n\nURL:\n\(urlPreview)" - guard self.confirm(title: "Run OpenClaw agent?", message: body) else { return } - } - - if AppStateStore.shared.connectionMode == .local { - GatewayProcessManager.shared.setActive(true) - } - - do { - let effectiveDelivery = DeepLinkAgentPolicy.effectiveDelivery(link: link, allowUnattended: allowUnattended) - let explicitSessionKey = link.sessionKey? - .trimmingCharacters(in: .whitespacesAndNewlines) - .nonEmpty - let resolvedSessionKey: String = if let explicitSessionKey { - explicitSessionKey - } else { - await GatewayConnection.shared.mainSessionKey() - } - let invocation = GatewayAgentInvocation( - message: messagePreview, - sessionKey: resolvedSessionKey, - thinking: link.thinking?.trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty, - deliver: effectiveDelivery.deliver, - to: effectiveDelivery.to, - channel: effectiveDelivery.channel, - timeoutSeconds: link.timeoutSeconds, - idempotencyKey: UUID().uuidString) - - let res = await GatewayConnection.shared.sendAgent(invocation) - if !res.ok { - throw NSError( - domain: "DeepLink", - code: 1, - userInfo: [NSLocalizedDescriptionKey: res.error ?? "agent request failed"]) - } - } catch { - self.presentAlert(title: "Agent request failed", message: error.localizedDescription) - } - } - - // MARK: - Auth - - static func currentKey() -> String { - self.expectedKey() - } - - static func currentCanvasKey() -> String { - self.canvasUnattendedKey - } - - private static func expectedKey() -> String { - let defaults = UserDefaults.standard - if let key = defaults.string(forKey: deepLinkKeyKey), !key.isEmpty { - return key - } - var bytes = [UInt8](repeating: 0, count: 32) - _ = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes) - let data = Data(bytes) - let key = data - .base64EncodedString() - .replacingOccurrences(of: "+", with: "-") - .replacingOccurrences(of: "/", with: "_") - .replacingOccurrences(of: "=", with: "") - defaults.set(key, forKey: deepLinkKeyKey) - return key - } - - private nonisolated static func generateRandomKey() -> String { - var bytes = [UInt8](repeating: 0, count: 32) - _ = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes) - let data = Data(bytes) - return data - .base64EncodedString() - .replacingOccurrences(of: "+", with: "-") - .replacingOccurrences(of: "/", with: "_") - .replacingOccurrences(of: "=", with: "") - } - - // MARK: - UI - - private func confirm(title: String, message: String) -> Bool { - let alert = NSAlert() - alert.messageText = title - alert.informativeText = message - alert.addButton(withTitle: "Run") - alert.addButton(withTitle: "Cancel") - alert.alertStyle = .warning - return alert.runModal() == .alertFirstButtonReturn - } - - private func presentAlert(title: String, message: String) { - let alert = NSAlert() - alert.messageText = title - alert.informativeText = message - alert.addButton(withTitle: "OK") - alert.alertStyle = .informational - alert.runModal() - } -} diff --git a/apps/macos/Sources/OpenClaw/DeviceModelCatalog.swift b/apps/macos/Sources/OpenClaw/DeviceModelCatalog.swift deleted file mode 100644 index ce6dd10c931..00000000000 --- a/apps/macos/Sources/OpenClaw/DeviceModelCatalog.swift +++ /dev/null @@ -1,188 +0,0 @@ -import Foundation - -struct DevicePresentation: Sendable { - let title: String - let symbol: String? -} - -enum DeviceModelCatalog { - private static let modelIdentifierToName: [String: String] = loadModelIdentifierToName() - private static let resourceBundle: Bundle? = locateResourceBundle() - private static let resourceSubdirectory = "DeviceModels" - - static func presentation(deviceFamily: String?, modelIdentifier: String?) -> DevicePresentation? { - let family = (deviceFamily ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - let model = (modelIdentifier ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - - let friendlyName = model.isEmpty ? nil : self.modelIdentifierToName[model] - let symbol = self.symbol(deviceFamily: family, modelIdentifier: model, friendlyName: friendlyName) - - let title = if let friendlyName, !friendlyName.isEmpty { - friendlyName - } else if !family.isEmpty, !model.isEmpty { - "\(family) (\(model))" - } else if !family.isEmpty { - family - } else if !model.isEmpty { - model - } else { - "" - } - - if title.isEmpty { return nil } - return DevicePresentation(title: title, symbol: symbol) - } - - static func symbol( - deviceFamily familyRaw: String, - modelIdentifier modelIdentifierRaw: String, - friendlyName: String?) -> String? - { - let family = familyRaw.trimmingCharacters(in: .whitespacesAndNewlines) - let modelIdentifier = modelIdentifierRaw.trimmingCharacters(in: .whitespacesAndNewlines) - - return self.symbolFor(modelIdentifier: modelIdentifier, friendlyName: friendlyName) - ?? self.fallbackSymbol(for: family, modelIdentifier: modelIdentifier) - } - - private static func symbolFor(modelIdentifier rawModelIdentifier: String, friendlyName: String?) -> String? { - let modelIdentifier = rawModelIdentifier.trimmingCharacters(in: .whitespacesAndNewlines) - guard !modelIdentifier.isEmpty else { return nil } - - let lower = modelIdentifier.lowercased() - if lower.hasPrefix("ipad") { return "ipad" } - if lower.hasPrefix("iphone") { return "iphone" } - if lower.hasPrefix("ipod") { return "iphone" } - if lower.hasPrefix("watch") { return "applewatch" } - if lower.hasPrefix("appletv") { return "appletv" } - if lower.hasPrefix("audio") || lower.hasPrefix("homepod") { return "speaker" } - - if lower.hasPrefix("macbook") || lower.hasPrefix("macbookpro") || lower.hasPrefix("macbookair") { - return "laptopcomputer" - } - if lower.hasPrefix("macstudio") { return "macstudio" } - if lower.hasPrefix("macmini") { return "macmini" } - if lower.hasPrefix("imac") || lower.hasPrefix("macpro") { return "desktopcomputer" } - - if lower.hasPrefix("mac"), let friendlyNameLower = friendlyName?.lowercased() { - if friendlyNameLower.contains("macbook") { return "laptopcomputer" } - if friendlyNameLower.contains("imac") { return "desktopcomputer" } - if friendlyNameLower.contains("mac mini") { return "macmini" } - if friendlyNameLower.contains("mac studio") { return "macstudio" } - if friendlyNameLower.contains("mac pro") { return "desktopcomputer" } - } - - return nil - } - - private static func fallbackSymbol(for familyRaw: String, modelIdentifier: String) -> String? { - let family = familyRaw.trimmingCharacters(in: .whitespacesAndNewlines) - if family.isEmpty { return nil } - switch family.lowercased() { - case "ipad": - return "ipad" - case "iphone": - return "iphone" - case "mac": - return "laptopcomputer" - case "android": - return "android" - case "linux": - return "cpu" - default: - return "cpu" - } - } - - private static func loadModelIdentifierToName() -> [String: String] { - var combined: [String: String] = [:] - combined.merge( - self.loadMapping(resourceName: "ios-device-identifiers"), - uniquingKeysWith: { current, _ in current }) - combined.merge( - self.loadMapping(resourceName: "mac-device-identifiers"), - uniquingKeysWith: { current, _ in current }) - return combined - } - - private static func loadMapping(resourceName: String) -> [String: String] { - guard let url = self.resourceBundle?.url( - forResource: resourceName, - withExtension: "json", - subdirectory: self.resourceSubdirectory) - else { return [:] } - - do { - let data = try Data(contentsOf: url) - let decoded = try JSONDecoder().decode([String: NameValue].self, from: data) - return decoded.compactMapValues { $0.normalizedName } - } catch { - return [:] - } - } - - private static func locateResourceBundle() -> Bundle? { - // Prefer main bundle (packaged app), then module bundle (SwiftPM/tests). - // Accessing Bundle.module in the packaged app can crash if the bundle isn't where SwiftPM expects it. - if let bundle = self.bundleIfContainsDeviceModels(Bundle.main) { - return bundle - } - - if let bundle = self.bundleIfContainsDeviceModels(Bundle.module) { - return bundle - } - return nil - } - - private static func bundleIfContainsDeviceModels(_ bundle: Bundle) -> Bundle? { - if bundle.url( - forResource: "ios-device-identifiers", - withExtension: "json", - subdirectory: self.resourceSubdirectory) != nil - { - return bundle - } - if bundle.url( - forResource: "mac-device-identifiers", - withExtension: "json", - subdirectory: self.resourceSubdirectory) != nil - { - return bundle - } - return nil - } - - private enum NameValue: Decodable { - case string(String) - case stringArray([String]) - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - if let s = try? container.decode(String.self) { - self = .string(s) - return - } - if let arr = try? container.decode([String].self) { - self = .stringArray(arr) - return - } - throw DecodingError.typeMismatch( - String.self, - .init(codingPath: decoder.codingPath, debugDescription: "Expected string or string array")) - } - - var normalizedName: String? { - switch self { - case let .string(s): - let trimmed = s.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed.isEmpty ? nil : trimmed - case let .stringArray(arr): - let values = arr - .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } - .filter { !$0.isEmpty } - guard !values.isEmpty else { return nil } - return values.joined(separator: " / ") - } - } - } -} diff --git a/apps/macos/Sources/OpenClaw/DevicePairingApprovalPrompter.swift b/apps/macos/Sources/OpenClaw/DevicePairingApprovalPrompter.swift deleted file mode 100644 index f85e8d1a5df..00000000000 --- a/apps/macos/Sources/OpenClaw/DevicePairingApprovalPrompter.swift +++ /dev/null @@ -1,307 +0,0 @@ -import AppKit -import Foundation -import Observation -import OpenClawKit -import OpenClawProtocol -import OSLog - -@MainActor -@Observable -final class DevicePairingApprovalPrompter { - static let shared = DevicePairingApprovalPrompter() - - private let logger = Logger(subsystem: "ai.openclaw", category: "device-pairing") - private var task: Task? - private var isStopping = false - private var isPresenting = false - private var queue: [PendingRequest] = [] - var pendingCount: Int = 0 - var pendingRepairCount: Int = 0 - private var activeAlert: NSAlert? - private var activeRequestId: String? - private var alertHostWindow: NSWindow? - private var resolvedByRequestId: Set = [] - - private struct PairingList: Codable { - let pending: [PendingRequest] - let paired: [PairedDevice]? - } - - private struct PairedDevice: Codable, Equatable { - let deviceId: String - let approvedAtMs: Double? - let displayName: String? - let platform: String? - let remoteIp: String? - } - - private struct PendingRequest: Codable, Equatable, Identifiable { - let requestId: String - let deviceId: String - let publicKey: String - let displayName: String? - let platform: String? - let clientId: String? - let clientMode: String? - let role: String? - let scopes: [String]? - let remoteIp: String? - let silent: Bool? - let isRepair: Bool? - let ts: Double - - var id: String { - self.requestId - } - } - - private struct PairingResolvedEvent: Codable { - let requestId: String - let deviceId: String - let decision: String - let ts: Double - } - - private enum PairingResolution: String { - case approved - case rejected - } - - func start() { - guard self.task == nil else { return } - self.isStopping = false - self.task = Task { [weak self] in - guard let self else { return } - _ = try? await GatewayConnection.shared.refresh() - await self.loadPendingRequestsFromGateway() - let stream = await GatewayConnection.shared.subscribe(bufferingNewest: 200) - for await push in stream { - if Task.isCancelled { return } - await MainActor.run { [weak self] in self?.handle(push: push) } - } - } - } - - func stop() { - self.isStopping = true - self.endActiveAlert() - self.task?.cancel() - self.task = nil - self.queue.removeAll(keepingCapacity: false) - self.updatePendingCounts() - self.isPresenting = false - self.activeRequestId = nil - self.alertHostWindow?.orderOut(nil) - self.alertHostWindow?.close() - self.alertHostWindow = nil - self.resolvedByRequestId.removeAll(keepingCapacity: false) - } - - private func loadPendingRequestsFromGateway() async { - do { - let list: PairingList = try await GatewayConnection.shared.requestDecoded(method: .devicePairList) - await self.apply(list: list) - } catch { - self.logger.error("failed to load device pairing requests: \(error.localizedDescription, privacy: .public)") - } - } - - private func apply(list: PairingList) async { - self.queue = list.pending.sorted(by: { $0.ts > $1.ts }) - self.updatePendingCounts() - self.presentNextIfNeeded() - } - - private func updatePendingCounts() { - self.pendingCount = self.queue.count - self.pendingRepairCount = self.queue.count(where: { $0.isRepair == true }) - } - - private func presentNextIfNeeded() { - guard !self.isStopping else { return } - guard !self.isPresenting else { return } - guard let next = self.queue.first else { return } - self.isPresenting = true - self.presentAlert(for: next) - } - - private func presentAlert(for req: PendingRequest) { - self.logger.info("presenting device pairing alert requestId=\(req.requestId, privacy: .public)") - NSApp.activate(ignoringOtherApps: true) - - let alert = NSAlert() - alert.alertStyle = .warning - alert.messageText = "Allow device to connect?" - alert.informativeText = Self.describe(req) - alert.addButton(withTitle: "Later") - alert.addButton(withTitle: "Approve") - alert.addButton(withTitle: "Reject") - if #available(macOS 11.0, *), alert.buttons.indices.contains(2) { - alert.buttons[2].hasDestructiveAction = true - } - - self.activeAlert = alert - self.activeRequestId = req.requestId - let hostWindow = self.requireAlertHostWindow() - - let sheetSize = alert.window.frame.size - if let screen = hostWindow.screen ?? NSScreen.main { - let bounds = screen.visibleFrame - let x = bounds.midX - (sheetSize.width / 2) - let sheetOriginY = bounds.midY - (sheetSize.height / 2) - let hostY = sheetOriginY + sheetSize.height - hostWindow.frame.height - hostWindow.setFrameOrigin(NSPoint(x: x, y: hostY)) - } else { - hostWindow.center() - } - - hostWindow.makeKeyAndOrderFront(nil) - alert.beginSheetModal(for: hostWindow) { [weak self] response in - Task { @MainActor [weak self] in - guard let self else { return } - self.activeRequestId = nil - self.activeAlert = nil - await self.handleAlertResponse(response, request: req) - hostWindow.orderOut(nil) - } - } - } - - private func handleAlertResponse(_ response: NSApplication.ModalResponse, request: PendingRequest) async { - var shouldRemove = response != .alertFirstButtonReturn - defer { - if shouldRemove { - if self.queue.first == request { - self.queue.removeFirst() - } else { - self.queue.removeAll { $0 == request } - } - } - self.updatePendingCounts() - self.isPresenting = false - self.presentNextIfNeeded() - } - - guard !self.isStopping else { return } - - if self.resolvedByRequestId.remove(request.requestId) != nil { - return - } - - switch response { - case .alertFirstButtonReturn: - shouldRemove = false - if let idx = self.queue.firstIndex(of: request) { - self.queue.remove(at: idx) - } - self.queue.append(request) - return - case .alertSecondButtonReturn: - _ = await self.approve(requestId: request.requestId) - case .alertThirdButtonReturn: - await self.reject(requestId: request.requestId) - default: - return - } - } - - private func approve(requestId: String) async -> Bool { - do { - try await GatewayConnection.shared.devicePairApprove(requestId: requestId) - self.logger.info("approved device pairing requestId=\(requestId, privacy: .public)") - return true - } catch { - self.logger.error("approve failed requestId=\(requestId, privacy: .public)") - self.logger.error("approve failed: \(error.localizedDescription, privacy: .public)") - return false - } - } - - private func reject(requestId: String) async { - do { - try await GatewayConnection.shared.devicePairReject(requestId: requestId) - self.logger.info("rejected device pairing requestId=\(requestId, privacy: .public)") - } catch { - self.logger.error("reject failed requestId=\(requestId, privacy: .public)") - self.logger.error("reject failed: \(error.localizedDescription, privacy: .public)") - } - } - - private func endActiveAlert() { - PairingAlertSupport.endActiveAlert(activeAlert: &self.activeAlert, activeRequestId: &self.activeRequestId) - } - - private func requireAlertHostWindow() -> NSWindow { - PairingAlertSupport.requireAlertHostWindow(alertHostWindow: &self.alertHostWindow) - } - - private func handle(push: GatewayPush) { - switch push { - case let .event(evt) where evt.event == "device.pair.requested": - guard let payload = evt.payload else { return } - do { - let req = try GatewayPayloadDecoding.decode(payload, as: PendingRequest.self) - self.enqueue(req) - } catch { - self.logger - .error("failed to decode device pairing request: \(error.localizedDescription, privacy: .public)") - } - case let .event(evt) where evt.event == "device.pair.resolved": - guard let payload = evt.payload else { return } - do { - let resolved = try GatewayPayloadDecoding.decode(payload, as: PairingResolvedEvent.self) - self.handleResolved(resolved) - } catch { - self.logger - .error( - "failed to decode device pairing resolution: \(error.localizedDescription, privacy: .public)") - } - default: - break - } - } - - private func enqueue(_ req: PendingRequest) { - guard !self.queue.contains(req) else { return } - self.queue.append(req) - self.updatePendingCounts() - self.presentNextIfNeeded() - } - - private func handleResolved(_ resolved: PairingResolvedEvent) { - let resolution = resolved.decision == PairingResolution.approved.rawValue ? PairingResolution - .approved : .rejected - if let activeRequestId, activeRequestId == resolved.requestId { - self.resolvedByRequestId.insert(resolved.requestId) - self.endActiveAlert() - let decision = resolution.rawValue - self.logger.info( - "device pairing resolved while active requestId=\(resolved.requestId, privacy: .public) " + - "decision=\(decision, privacy: .public)") - return - } - self.queue.removeAll { $0.requestId == resolved.requestId } - self.updatePendingCounts() - } - - private static func describe(_ req: PendingRequest) -> String { - var lines: [String] = [] - lines.append("Device: \(req.displayName ?? req.deviceId)") - if let platform = req.platform { - lines.append("Platform: \(platform)") - } - if let role = req.role { - lines.append("Role: \(role)") - } - if let scopes = req.scopes, !scopes.isEmpty { - lines.append("Scopes: \(scopes.joined(separator: ", "))") - } - if let remoteIp = req.remoteIp { - lines.append("IP: \(remoteIp)") - } - if req.isRepair == true { - lines.append("Repair: yes") - } - return lines.joined(separator: "\n") - } -} diff --git a/apps/macos/Sources/OpenClaw/DiagnosticsFileLog.swift b/apps/macos/Sources/OpenClaw/DiagnosticsFileLog.swift deleted file mode 100644 index 44baa738bdc..00000000000 --- a/apps/macos/Sources/OpenClaw/DiagnosticsFileLog.swift +++ /dev/null @@ -1,133 +0,0 @@ -import Foundation - -actor DiagnosticsFileLog { - static let shared = DiagnosticsFileLog() - - private let fileName = "diagnostics.jsonl" - private let maxBytes: Int64 = 5 * 1024 * 1024 - private let maxBackups = 5 - - struct Record: Codable, Sendable { - let ts: String - let pid: Int32 - let category: String - let event: String - let fields: [String: String]? - } - - nonisolated static func isEnabled() -> Bool { - UserDefaults.standard.bool(forKey: debugFileLogEnabledKey) - } - - nonisolated static func logDirectoryURL() -> URL { - let library = FileManager().urls(for: .libraryDirectory, in: .userDomainMask).first - ?? FileManager().homeDirectoryForCurrentUser.appendingPathComponent("Library", isDirectory: true) - return library - .appendingPathComponent("Logs", isDirectory: true) - .appendingPathComponent("OpenClaw", isDirectory: true) - } - - nonisolated static func logFileURL() -> URL { - self.logDirectoryURL().appendingPathComponent("diagnostics.jsonl", isDirectory: false) - } - - nonisolated func log(category: String, event: String, fields: [String: String]? = nil) { - guard Self.isEnabled() else { return } - let record = Record( - ts: ISO8601DateFormatter().string(from: Date()), - pid: ProcessInfo.processInfo.processIdentifier, - category: category, - event: event, - fields: fields) - Task { await self.write(record: record) } - } - - func clear() throws { - let fm = FileManager() - let base = Self.logFileURL() - if fm.fileExists(atPath: base.path) { - try fm.removeItem(at: base) - } - for idx in 1...self.maxBackups { - let url = self.rotatedURL(index: idx) - if fm.fileExists(atPath: url.path) { - try fm.removeItem(at: url) - } - } - } - - private func write(record: Record) { - do { - try self.ensureDirectory() - try self.rotateIfNeeded() - try self.append(record: record) - } catch { - // Best-effort only: never crash or block the app on logging. - } - } - - private func ensureDirectory() throws { - try FileManager().createDirectory( - at: Self.logDirectoryURL(), - withIntermediateDirectories: true) - } - - private func append(record: Record) throws { - let url = Self.logFileURL() - let data = try JSONEncoder().encode(record) - var line = Data() - line.append(data) - line.append(0x0A) // newline - - let fm = FileManager() - if !fm.fileExists(atPath: url.path) { - fm.createFile(atPath: url.path, contents: nil) - } - - let handle = try FileHandle(forWritingTo: url) - defer { try? handle.close() } - try handle.seekToEnd() - try handle.write(contentsOf: line) - } - - private func rotateIfNeeded() throws { - let url = Self.logFileURL() - guard let attrs = try? FileManager().attributesOfItem(atPath: url.path), - let size = attrs[.size] as? NSNumber - else { return } - - if size.int64Value < self.maxBytes { return } - - let fm = FileManager() - - let oldest = self.rotatedURL(index: self.maxBackups) - if fm.fileExists(atPath: oldest.path) { - try fm.removeItem(at: oldest) - } - - if self.maxBackups > 1 { - for idx in stride(from: self.maxBackups - 1, through: 1, by: -1) { - let src = self.rotatedURL(index: idx) - let dst = self.rotatedURL(index: idx + 1) - if fm.fileExists(atPath: src.path) { - if fm.fileExists(atPath: dst.path) { - try fm.removeItem(at: dst) - } - try fm.moveItem(at: src, to: dst) - } - } - } - - let first = self.rotatedURL(index: 1) - if fm.fileExists(atPath: first.path) { - try fm.removeItem(at: first) - } - if fm.fileExists(atPath: url.path) { - try fm.moveItem(at: url, to: first) - } - } - - private func rotatedURL(index: Int) -> URL { - Self.logDirectoryURL().appendingPathComponent("\(self.fileName).\(index)", isDirectory: false) - } -} diff --git a/apps/macos/Sources/OpenClaw/DockIconManager.swift b/apps/macos/Sources/OpenClaw/DockIconManager.swift deleted file mode 100644 index 98201393b75..00000000000 --- a/apps/macos/Sources/OpenClaw/DockIconManager.swift +++ /dev/null @@ -1,116 +0,0 @@ -import AppKit - -/// Central manager for Dock icon visibility. -/// Shows the Dock icon while any windows are visible, regardless of user preference. -final class DockIconManager: NSObject, @unchecked Sendable { - static let shared = DockIconManager() - - private var windowsObservation: NSKeyValueObservation? - private let logger = Logger(subsystem: "ai.openclaw", category: "DockIconManager") - - override private init() { - super.init() - self.setupObservers() - Task { @MainActor in - self.updateDockVisibility() - } - } - - deinit { - self.windowsObservation?.invalidate() - NotificationCenter.default.removeObserver(self) - } - - func updateDockVisibility() { - Task { @MainActor in - guard NSApp != nil else { - self.logger.warning("NSApp not ready, skipping Dock visibility update") - return - } - - let userWantsDockHidden = !UserDefaults.standard.bool(forKey: showDockIconKey) - let visibleWindows = NSApp?.windows.filter { window in - window.isVisible && - window.frame.width > 1 && - window.frame.height > 1 && - !window.isKind(of: NSPanel.self) && - "\(type(of: window))" != "NSPopupMenuWindow" && - window.contentViewController != nil - } ?? [] - - let hasVisibleWindows = !visibleWindows.isEmpty - if !userWantsDockHidden || hasVisibleWindows { - NSApp?.setActivationPolicy(.regular) - } else { - NSApp?.setActivationPolicy(.accessory) - } - } - } - - func temporarilyShowDock() { - Task { @MainActor in - guard NSApp != nil else { - self.logger.warning("NSApp not ready, cannot show Dock icon") - return - } - NSApp.setActivationPolicy(.regular) - } - } - - private func setupObservers() { - Task { @MainActor in - guard let app = NSApp else { - self.logger.warning("NSApp not ready, delaying Dock observers") - try? await Task.sleep(for: .milliseconds(200)) - self.setupObservers() - return - } - - self.windowsObservation = app.observe(\.windows, options: [.new]) { [weak self] _, _ in - Task { @MainActor in - try? await Task.sleep(for: .milliseconds(50)) - self?.updateDockVisibility() - } - } - - NotificationCenter.default.addObserver( - self, - selector: #selector(self.windowVisibilityChanged), - name: NSWindow.didBecomeKeyNotification, - object: nil) - NotificationCenter.default.addObserver( - self, - selector: #selector(self.windowVisibilityChanged), - name: NSWindow.didResignKeyNotification, - object: nil) - NotificationCenter.default.addObserver( - self, - selector: #selector(self.windowVisibilityChanged), - name: NSWindow.willCloseNotification, - object: nil) - NotificationCenter.default.addObserver( - self, - selector: #selector(self.dockPreferenceChanged), - name: UserDefaults.didChangeNotification, - object: nil) - } - } - - @objc - private func windowVisibilityChanged(_: Notification) { - Task { @MainActor in - self.updateDockVisibility() - } - } - - @objc - private func dockPreferenceChanged(_ notification: Notification) { - guard let userDefaults = notification.object as? UserDefaults, - userDefaults == UserDefaults.standard - else { return } - - Task { @MainActor in - self.updateDockVisibility() - } - } -} diff --git a/apps/macos/Sources/OpenClaw/ExecAllowlistMatcher.swift b/apps/macos/Sources/OpenClaw/ExecAllowlistMatcher.swift deleted file mode 100644 index 2dd720741bb..00000000000 --- a/apps/macos/Sources/OpenClaw/ExecAllowlistMatcher.swift +++ /dev/null @@ -1,79 +0,0 @@ -import Foundation - -enum ExecAllowlistMatcher { - static func match(entries: [ExecAllowlistEntry], resolution: ExecCommandResolution?) -> ExecAllowlistEntry? { - guard let resolution, !entries.isEmpty else { return nil } - let rawExecutable = resolution.rawExecutable - let resolvedPath = resolution.resolvedPath - - for entry in entries { - switch ExecApprovalHelpers.validateAllowlistPattern(entry.pattern) { - case .valid(let pattern): - let target = resolvedPath ?? rawExecutable - if self.matches(pattern: pattern, target: target) { return entry } - case .invalid: - continue - } - } - return nil - } - - static func matchAll( - entries: [ExecAllowlistEntry], - resolutions: [ExecCommandResolution]) -> [ExecAllowlistEntry] - { - guard !entries.isEmpty, !resolutions.isEmpty else { return [] } - var matches: [ExecAllowlistEntry] = [] - matches.reserveCapacity(resolutions.count) - for resolution in resolutions { - guard let match = self.match(entries: entries, resolution: resolution) else { - return [] - } - matches.append(match) - } - return matches - } - - private static func matches(pattern: String, target: String) -> Bool { - let trimmed = pattern.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return false } - let expanded = trimmed.hasPrefix("~") ? (trimmed as NSString).expandingTildeInPath : trimmed - let normalizedPattern = self.normalizeMatchTarget(expanded) - let normalizedTarget = self.normalizeMatchTarget(target) - guard let regex = self.regex(for: normalizedPattern) else { return false } - let range = NSRange(location: 0, length: normalizedTarget.utf16.count) - return regex.firstMatch(in: normalizedTarget, options: [], range: range) != nil - } - - private static func normalizeMatchTarget(_ value: String) -> String { - value.replacingOccurrences(of: "\\\\", with: "/").lowercased() - } - - private static func regex(for pattern: String) -> NSRegularExpression? { - var regex = "^" - var idx = pattern.startIndex - while idx < pattern.endIndex { - let ch = pattern[idx] - if ch == "*" { - let next = pattern.index(after: idx) - if next < pattern.endIndex, pattern[next] == "*" { - regex += ".*" - idx = pattern.index(after: next) - } else { - regex += "[^/]*" - idx = next - } - continue - } - if ch == "?" { - regex += "." - idx = pattern.index(after: idx) - continue - } - regex += NSRegularExpression.escapedPattern(for: String(ch)) - idx = pattern.index(after: idx) - } - regex += "$" - return try? NSRegularExpression(pattern: regex, options: [.caseInsensitive]) - } -} diff --git a/apps/macos/Sources/OpenClaw/ExecApprovalEvaluation.swift b/apps/macos/Sources/OpenClaw/ExecApprovalEvaluation.swift deleted file mode 100644 index 7bb05aff0c9..00000000000 --- a/apps/macos/Sources/OpenClaw/ExecApprovalEvaluation.swift +++ /dev/null @@ -1,67 +0,0 @@ -import Foundation - -struct ExecApprovalEvaluation { - let command: [String] - let displayCommand: String - let agentId: String? - let security: ExecSecurity - let ask: ExecAsk - let env: [String: String] - let resolution: ExecCommandResolution? - let allowlistResolutions: [ExecCommandResolution] - let allowlistMatches: [ExecAllowlistEntry] - let allowlistSatisfied: Bool - let allowlistMatch: ExecAllowlistEntry? - let skillAllow: Bool -} - -enum ExecApprovalEvaluator { - static func evaluate( - command: [String], - rawCommand: String?, - cwd: String?, - envOverrides: [String: String]?, - agentId: String?) async -> ExecApprovalEvaluation - { - let trimmedAgent = agentId?.trimmingCharacters(in: .whitespacesAndNewlines) - let normalizedAgentId = (trimmedAgent?.isEmpty == false) ? trimmedAgent : nil - let approvals = ExecApprovalsStore.resolve(agentId: normalizedAgentId) - let security = approvals.agent.security - let ask = approvals.agent.ask - let env = HostEnvSanitizer.sanitize(overrides: envOverrides) - let displayCommand = ExecCommandFormatter.displayString(for: command, rawCommand: rawCommand) - let allowlistResolutions = ExecCommandResolution.resolveForAllowlist( - command: command, - rawCommand: rawCommand, - cwd: cwd, - env: env) - let allowlistMatches = security == .allowlist - ? ExecAllowlistMatcher.matchAll(entries: approvals.allowlist, resolutions: allowlistResolutions) - : [] - let allowlistSatisfied = security == .allowlist && - !allowlistResolutions.isEmpty && - allowlistMatches.count == allowlistResolutions.count - - let skillAllow: Bool - if approvals.agent.autoAllowSkills, !allowlistResolutions.isEmpty { - let bins = await SkillBinsCache.shared.currentBins() - skillAllow = allowlistResolutions.allSatisfy { bins.contains($0.executableName) } - } else { - skillAllow = false - } - - return ExecApprovalEvaluation( - command: command, - displayCommand: displayCommand, - agentId: normalizedAgentId, - security: security, - ask: ask, - env: env, - resolution: allowlistResolutions.first, - allowlistResolutions: allowlistResolutions, - allowlistMatches: allowlistMatches, - allowlistSatisfied: allowlistSatisfied, - allowlistMatch: allowlistSatisfied ? allowlistMatches.first : nil, - skillAllow: skillAllow) - } -} diff --git a/apps/macos/Sources/OpenClaw/ExecApprovals.swift b/apps/macos/Sources/OpenClaw/ExecApprovals.swift deleted file mode 100644 index 08567cd0b09..00000000000 --- a/apps/macos/Sources/OpenClaw/ExecApprovals.swift +++ /dev/null @@ -1,794 +0,0 @@ -import CryptoKit -import Foundation -import OSLog -import Security - -enum ExecSecurity: String, CaseIterable, Codable, Identifiable { - case deny - case allowlist - case full - - var id: String { - self.rawValue - } - - var title: String { - switch self { - case .deny: "Deny" - case .allowlist: "Allowlist" - case .full: "Always Allow" - } - } -} - -enum ExecApprovalQuickMode: String, CaseIterable, Identifiable { - case deny - case ask - case allow - - var id: String { - self.rawValue - } - - var title: String { - switch self { - case .deny: "Deny" - case .ask: "Always Ask" - case .allow: "Always Allow" - } - } - - var security: ExecSecurity { - switch self { - case .deny: .deny - case .ask: .allowlist - case .allow: .full - } - } - - var ask: ExecAsk { - switch self { - case .deny: .off - case .ask: .onMiss - case .allow: .off - } - } - - static func from(security: ExecSecurity, ask: ExecAsk) -> ExecApprovalQuickMode { - switch security { - case .deny: - .deny - case .full: - .allow - case .allowlist: - .ask - } - } -} - -enum ExecAsk: String, CaseIterable, Codable, Identifiable { - case off - case onMiss = "on-miss" - case always - - var id: String { - self.rawValue - } - - var title: String { - switch self { - case .off: "Never Ask" - case .onMiss: "Ask on Allowlist Miss" - case .always: "Always Ask" - } - } -} - -enum ExecApprovalDecision: String, Codable, Sendable { - case allowOnce = "allow-once" - case allowAlways = "allow-always" - case deny -} - -enum ExecAllowlistPatternValidationReason: String, Codable, Sendable, Equatable { - case empty - case missingPathComponent - - var message: String { - switch self { - case .empty: - "Pattern cannot be empty." - case .missingPathComponent: - "Path patterns only. Include '/', '~', or '\\\\'." - } - } -} - -enum ExecAllowlistPatternValidation: Sendable, Equatable { - case valid(String) - case invalid(ExecAllowlistPatternValidationReason) -} - -struct ExecAllowlistRejectedEntry: Sendable, Equatable { - let id: UUID - let pattern: String - let reason: ExecAllowlistPatternValidationReason -} - -struct ExecAllowlistEntry: Codable, Hashable, Identifiable { - var id: UUID - var pattern: String - var lastUsedAt: Double? - var lastUsedCommand: String? - var lastResolvedPath: String? - - init( - id: UUID = UUID(), - pattern: String, - lastUsedAt: Double? = nil, - lastUsedCommand: String? = nil, - lastResolvedPath: String? = nil) - { - self.id = id - self.pattern = pattern - self.lastUsedAt = lastUsedAt - self.lastUsedCommand = lastUsedCommand - self.lastResolvedPath = lastResolvedPath - } - - private enum CodingKeys: String, CodingKey { - case id - case pattern - case lastUsedAt - case lastUsedCommand - case lastResolvedPath - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - self.id = try container.decodeIfPresent(UUID.self, forKey: .id) ?? UUID() - self.pattern = try container.decode(String.self, forKey: .pattern) - self.lastUsedAt = try container.decodeIfPresent(Double.self, forKey: .lastUsedAt) - self.lastUsedCommand = try container.decodeIfPresent(String.self, forKey: .lastUsedCommand) - self.lastResolvedPath = try container.decodeIfPresent(String.self, forKey: .lastResolvedPath) - } - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(self.id, forKey: .id) - try container.encode(self.pattern, forKey: .pattern) - try container.encodeIfPresent(self.lastUsedAt, forKey: .lastUsedAt) - try container.encodeIfPresent(self.lastUsedCommand, forKey: .lastUsedCommand) - try container.encodeIfPresent(self.lastResolvedPath, forKey: .lastResolvedPath) - } -} - -struct ExecApprovalsDefaults: Codable { - var security: ExecSecurity? - var ask: ExecAsk? - var askFallback: ExecSecurity? - var autoAllowSkills: Bool? -} - -struct ExecApprovalsAgent: Codable { - var security: ExecSecurity? - var ask: ExecAsk? - var askFallback: ExecSecurity? - var autoAllowSkills: Bool? - var allowlist: [ExecAllowlistEntry]? - - var isEmpty: Bool { - self.security == nil && self.ask == nil && self.askFallback == nil && self - .autoAllowSkills == nil && (self.allowlist?.isEmpty ?? true) - } -} - -struct ExecApprovalsSocketConfig: Codable { - var path: String? - var token: String? -} - -struct ExecApprovalsFile: Codable { - var version: Int - var socket: ExecApprovalsSocketConfig? - var defaults: ExecApprovalsDefaults? - var agents: [String: ExecApprovalsAgent]? -} - -struct ExecApprovalsSnapshot: Codable { - var path: String - var exists: Bool - var hash: String - var file: ExecApprovalsFile -} - -struct ExecApprovalsResolved { - let url: URL - let socketPath: String - let token: String - let defaults: ExecApprovalsResolvedDefaults - let agent: ExecApprovalsResolvedDefaults - let allowlist: [ExecAllowlistEntry] - var file: ExecApprovalsFile -} - -struct ExecApprovalsResolvedDefaults { - var security: ExecSecurity - var ask: ExecAsk - var askFallback: ExecSecurity - var autoAllowSkills: Bool -} - -enum ExecApprovalsStore { - private static let logger = Logger(subsystem: "ai.openclaw", category: "exec-approvals") - private static let defaultAgentId = "main" - private static let defaultSecurity: ExecSecurity = .deny - private static let defaultAsk: ExecAsk = .onMiss - private static let defaultAskFallback: ExecSecurity = .deny - private static let defaultAutoAllowSkills = false - - static func fileURL() -> URL { - OpenClawPaths.stateDirURL.appendingPathComponent("exec-approvals.json") - } - - static func socketPath() -> String { - OpenClawPaths.stateDirURL.appendingPathComponent("exec-approvals.sock").path - } - - static func normalizeIncoming(_ file: ExecApprovalsFile) -> ExecApprovalsFile { - let socketPath = file.socket?.path?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let token = file.socket?.token?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - var agents = file.agents ?? [:] - if let legacyDefault = agents["default"] { - if let main = agents[self.defaultAgentId] { - agents[self.defaultAgentId] = self.mergeAgents(current: main, legacy: legacyDefault) - } else { - agents[self.defaultAgentId] = legacyDefault - } - agents.removeValue(forKey: "default") - } - if !agents.isEmpty { - var normalizedAgents: [String: ExecApprovalsAgent] = [:] - normalizedAgents.reserveCapacity(agents.count) - for (key, var agent) in agents { - if let allowlist = agent.allowlist { - let normalized = self.normalizeAllowlistEntries(allowlist, dropInvalid: false).entries - agent.allowlist = normalized.isEmpty ? nil : normalized - } - normalizedAgents[key] = agent - } - agents = normalizedAgents - } - return ExecApprovalsFile( - version: 1, - socket: ExecApprovalsSocketConfig( - path: socketPath.isEmpty ? nil : socketPath, - token: token.isEmpty ? nil : token), - defaults: file.defaults, - agents: agents.isEmpty ? nil : agents) - } - - static func readSnapshot() -> ExecApprovalsSnapshot { - let url = self.fileURL() - guard FileManager().fileExists(atPath: url.path) else { - return ExecApprovalsSnapshot( - path: url.path, - exists: false, - hash: self.hashRaw(nil), - file: ExecApprovalsFile(version: 1, socket: nil, defaults: nil, agents: [:])) - } - let raw = try? String(contentsOf: url, encoding: .utf8) - let data = raw.flatMap { $0.data(using: .utf8) } - let decoded: ExecApprovalsFile = { - if let data, let file = try? JSONDecoder().decode(ExecApprovalsFile.self, from: data), file.version == 1 { - return file - } - return ExecApprovalsFile(version: 1, socket: nil, defaults: nil, agents: [:]) - }() - return ExecApprovalsSnapshot( - path: url.path, - exists: true, - hash: self.hashRaw(raw), - file: decoded) - } - - static func redactForSnapshot(_ file: ExecApprovalsFile) -> ExecApprovalsFile { - let socketPath = file.socket?.path?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if socketPath.isEmpty { - return ExecApprovalsFile( - version: file.version, - socket: nil, - defaults: file.defaults, - agents: file.agents) - } - return ExecApprovalsFile( - version: file.version, - socket: ExecApprovalsSocketConfig(path: socketPath, token: nil), - defaults: file.defaults, - agents: file.agents) - } - - static func loadFile() -> ExecApprovalsFile { - let url = self.fileURL() - guard FileManager().fileExists(atPath: url.path) else { - return ExecApprovalsFile(version: 1, socket: nil, defaults: nil, agents: [:]) - } - do { - let data = try Data(contentsOf: url) - let decoded = try JSONDecoder().decode(ExecApprovalsFile.self, from: data) - if decoded.version != 1 { - return ExecApprovalsFile(version: 1, socket: nil, defaults: nil, agents: [:]) - } - return decoded - } catch { - self.logger.warning("exec approvals load failed: \(error.localizedDescription, privacy: .public)") - return ExecApprovalsFile(version: 1, socket: nil, defaults: nil, agents: [:]) - } - } - - static func saveFile(_ file: ExecApprovalsFile) { - do { - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - let data = try encoder.encode(file) - let url = self.fileURL() - try FileManager().createDirectory( - at: url.deletingLastPathComponent(), - withIntermediateDirectories: true) - try data.write(to: url, options: [.atomic]) - try? FileManager().setAttributes([.posixPermissions: 0o600], ofItemAtPath: url.path) - } catch { - self.logger.error("exec approvals save failed: \(error.localizedDescription, privacy: .public)") - } - } - - static func ensureFile() -> ExecApprovalsFile { - let url = self.fileURL() - let existed = FileManager().fileExists(atPath: url.path) - let loaded = self.loadFile() - let loadedHash = self.hashFile(loaded) - - var file = self.normalizeIncoming(loaded) - if file.socket == nil { file.socket = ExecApprovalsSocketConfig(path: nil, token: nil) } - let path = file.socket?.path?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if path.isEmpty { - file.socket?.path = self.socketPath() - } - let token = file.socket?.token?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if token.isEmpty { - file.socket?.token = self.generateToken() - } - if file.agents == nil { file.agents = [:] } - if !existed || loadedHash != self.hashFile(file) { - self.saveFile(file) - } - return file - } - - static func resolve(agentId: String?) -> ExecApprovalsResolved { - let file = self.ensureFile() - let defaults = file.defaults ?? ExecApprovalsDefaults() - let resolvedDefaults = ExecApprovalsResolvedDefaults( - security: defaults.security ?? self.defaultSecurity, - ask: defaults.ask ?? self.defaultAsk, - askFallback: defaults.askFallback ?? self.defaultAskFallback, - autoAllowSkills: defaults.autoAllowSkills ?? self.defaultAutoAllowSkills) - let key = self.agentKey(agentId) - let agentEntry = file.agents?[key] ?? ExecApprovalsAgent() - let wildcardEntry = file.agents?["*"] ?? ExecApprovalsAgent() - let resolvedAgent = ExecApprovalsResolvedDefaults( - security: agentEntry.security ?? wildcardEntry.security ?? resolvedDefaults.security, - ask: agentEntry.ask ?? wildcardEntry.ask ?? resolvedDefaults.ask, - askFallback: agentEntry.askFallback ?? wildcardEntry.askFallback - ?? resolvedDefaults.askFallback, - autoAllowSkills: agentEntry.autoAllowSkills ?? wildcardEntry.autoAllowSkills - ?? resolvedDefaults.autoAllowSkills) - let allowlist = self.normalizeAllowlistEntries( - (wildcardEntry.allowlist ?? []) + (agentEntry.allowlist ?? []), - dropInvalid: true).entries - let socketPath = self.expandPath(file.socket?.path ?? self.socketPath()) - let token = file.socket?.token ?? "" - return ExecApprovalsResolved( - url: self.fileURL(), - socketPath: socketPath, - token: token, - defaults: resolvedDefaults, - agent: resolvedAgent, - allowlist: allowlist, - file: file) - } - - static func resolveDefaults() -> ExecApprovalsResolvedDefaults { - let file = self.ensureFile() - let defaults = file.defaults ?? ExecApprovalsDefaults() - return ExecApprovalsResolvedDefaults( - security: defaults.security ?? self.defaultSecurity, - ask: defaults.ask ?? self.defaultAsk, - askFallback: defaults.askFallback ?? self.defaultAskFallback, - autoAllowSkills: defaults.autoAllowSkills ?? self.defaultAutoAllowSkills) - } - - static func saveDefaults(_ defaults: ExecApprovalsDefaults) { - self.updateFile { file in - file.defaults = defaults - } - } - - static func updateDefaults(_ mutate: (inout ExecApprovalsDefaults) -> Void) { - self.updateFile { file in - var defaults = file.defaults ?? ExecApprovalsDefaults() - mutate(&defaults) - file.defaults = defaults - } - } - - static func saveAgent(_ agent: ExecApprovalsAgent, agentId: String?) { - self.updateFile { file in - var agents = file.agents ?? [:] - let key = self.agentKey(agentId) - if agent.isEmpty { - agents.removeValue(forKey: key) - } else { - agents[key] = agent - } - file.agents = agents.isEmpty ? nil : agents - } - } - - @discardableResult - static func addAllowlistEntry(agentId: String?, pattern: String) -> ExecAllowlistPatternValidationReason? { - let normalizedPattern: String - switch ExecApprovalHelpers.validateAllowlistPattern(pattern) { - case .valid(let validPattern): - normalizedPattern = validPattern - case .invalid(let reason): - return reason - } - - self.updateFile { file in - let key = self.agentKey(agentId) - var agents = file.agents ?? [:] - var entry = agents[key] ?? ExecApprovalsAgent() - var allowlist = entry.allowlist ?? [] - if allowlist.contains(where: { $0.pattern == normalizedPattern }) { return } - allowlist.append(ExecAllowlistEntry( - pattern: normalizedPattern, - lastUsedAt: Date().timeIntervalSince1970 * 1000)) - entry.allowlist = allowlist - agents[key] = entry - file.agents = agents - } - return nil - } - - static func recordAllowlistUse( - agentId: String?, - pattern: String, - command: String, - resolvedPath: String?) - { - self.updateFile { file in - let key = self.agentKey(agentId) - var agents = file.agents ?? [:] - var entry = agents[key] ?? ExecApprovalsAgent() - let allowlist = (entry.allowlist ?? []).map { item -> ExecAllowlistEntry in - guard item.pattern == pattern else { return item } - return ExecAllowlistEntry( - id: item.id, - pattern: item.pattern, - lastUsedAt: Date().timeIntervalSince1970 * 1000, - lastUsedCommand: command, - lastResolvedPath: resolvedPath) - } - entry.allowlist = allowlist - agents[key] = entry - file.agents = agents - } - } - - @discardableResult - static func updateAllowlist(agentId: String?, allowlist: [ExecAllowlistEntry]) -> [ExecAllowlistRejectedEntry] { - var rejected: [ExecAllowlistRejectedEntry] = [] - self.updateFile { file in - let key = self.agentKey(agentId) - var agents = file.agents ?? [:] - var entry = agents[key] ?? ExecApprovalsAgent() - let normalized = self.normalizeAllowlistEntries(allowlist, dropInvalid: true) - rejected = normalized.rejected - let cleaned = normalized.entries - entry.allowlist = cleaned - agents[key] = entry - file.agents = agents - } - return rejected - } - - static func updateAgentSettings(agentId: String?, mutate: (inout ExecApprovalsAgent) -> Void) { - self.updateFile { file in - let key = self.agentKey(agentId) - var agents = file.agents ?? [:] - var entry = agents[key] ?? ExecApprovalsAgent() - mutate(&entry) - if entry.isEmpty { - agents.removeValue(forKey: key) - } else { - agents[key] = entry - } - file.agents = agents.isEmpty ? nil : agents - } - } - - private static func updateFile(_ mutate: (inout ExecApprovalsFile) -> Void) { - var file = self.ensureFile() - mutate(&file) - self.saveFile(file) - } - - private static func generateToken() -> String { - var bytes = [UInt8](repeating: 0, count: 24) - let status = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes) - if status == errSecSuccess { - return Data(bytes) - .base64EncodedString() - .replacingOccurrences(of: "+", with: "-") - .replacingOccurrences(of: "/", with: "_") - .replacingOccurrences(of: "=", with: "") - } - return UUID().uuidString - } - - private static func hashRaw(_ raw: String?) -> String { - let data = Data((raw ?? "").utf8) - let digest = SHA256.hash(data: data) - return digest.map { String(format: "%02x", $0) }.joined() - } - - private static func hashFile(_ file: ExecApprovalsFile) -> String { - let encoder = JSONEncoder() - encoder.outputFormatting = [.sortedKeys] - let data = (try? encoder.encode(file)) ?? Data() - let digest = SHA256.hash(data: data) - return digest.map { String(format: "%02x", $0) }.joined() - } - - private static func expandPath(_ raw: String) -> String { - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed == "~" { - return FileManager().homeDirectoryForCurrentUser.path - } - if trimmed.hasPrefix("~/") { - let suffix = trimmed.dropFirst(2) - return FileManager().homeDirectoryForCurrentUser - .appendingPathComponent(String(suffix)).path - } - return trimmed - } - - private static func agentKey(_ agentId: String?) -> String { - let trimmed = agentId?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - return trimmed.isEmpty ? self.defaultAgentId : trimmed - } - - private static func normalizedPattern(_ pattern: String?) -> String? { - switch ExecApprovalHelpers.validateAllowlistPattern(pattern) { - case .valid(let normalized): - return normalized.lowercased() - case .invalid(.empty): - return nil - case .invalid: - let trimmed = pattern?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - return trimmed.isEmpty ? nil : trimmed.lowercased() - } - } - - private static func migrateLegacyPattern(_ entry: ExecAllowlistEntry) -> ExecAllowlistEntry { - let trimmedPattern = entry.pattern.trimmingCharacters(in: .whitespacesAndNewlines) - let trimmedResolved = entry.lastResolvedPath?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let normalizedResolved = trimmedResolved.isEmpty ? nil : trimmedResolved - - switch ExecApprovalHelpers.validateAllowlistPattern(trimmedPattern) { - case .valid(let pattern): - return ExecAllowlistEntry( - id: entry.id, - pattern: pattern, - lastUsedAt: entry.lastUsedAt, - lastUsedCommand: entry.lastUsedCommand, - lastResolvedPath: normalizedResolved) - case .invalid: - switch ExecApprovalHelpers.validateAllowlistPattern(trimmedResolved) { - case .valid(let migratedPattern): - return ExecAllowlistEntry( - id: entry.id, - pattern: migratedPattern, - lastUsedAt: entry.lastUsedAt, - lastUsedCommand: entry.lastUsedCommand, - lastResolvedPath: normalizedResolved) - case .invalid: - return ExecAllowlistEntry( - id: entry.id, - pattern: trimmedPattern, - lastUsedAt: entry.lastUsedAt, - lastUsedCommand: entry.lastUsedCommand, - lastResolvedPath: normalizedResolved) - } - } - } - - private static func normalizeAllowlistEntries( - _ entries: [ExecAllowlistEntry], - dropInvalid: Bool) -> (entries: [ExecAllowlistEntry], rejected: [ExecAllowlistRejectedEntry]) - { - var normalized: [ExecAllowlistEntry] = [] - normalized.reserveCapacity(entries.count) - var rejected: [ExecAllowlistRejectedEntry] = [] - - for entry in entries { - let migrated = self.migrateLegacyPattern(entry) - let trimmedPattern = migrated.pattern.trimmingCharacters(in: .whitespacesAndNewlines) - let trimmedResolvedPath = migrated.lastResolvedPath?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let normalizedResolvedPath = trimmedResolvedPath.isEmpty ? nil : trimmedResolvedPath - - switch ExecApprovalHelpers.validateAllowlistPattern(trimmedPattern) { - case .valid(let pattern): - normalized.append( - ExecAllowlistEntry( - id: migrated.id, - pattern: pattern, - lastUsedAt: migrated.lastUsedAt, - lastUsedCommand: migrated.lastUsedCommand, - lastResolvedPath: normalizedResolvedPath)) - case .invalid(let reason): - if dropInvalid { - rejected.append( - ExecAllowlistRejectedEntry( - id: migrated.id, - pattern: trimmedPattern, - reason: reason)) - } else if reason != .empty { - normalized.append( - ExecAllowlistEntry( - id: migrated.id, - pattern: trimmedPattern, - lastUsedAt: migrated.lastUsedAt, - lastUsedCommand: migrated.lastUsedCommand, - lastResolvedPath: normalizedResolvedPath)) - } - } - } - - return (normalized, rejected) - } - - private static func mergeAgents( - current: ExecApprovalsAgent, - legacy: ExecApprovalsAgent) -> ExecApprovalsAgent - { - let currentAllowlist = self.normalizeAllowlistEntries(current.allowlist ?? [], dropInvalid: false).entries - let legacyAllowlist = self.normalizeAllowlistEntries(legacy.allowlist ?? [], dropInvalid: false).entries - var seen = Set() - var allowlist: [ExecAllowlistEntry] = [] - func append(_ entry: ExecAllowlistEntry) { - guard let key = self.normalizedPattern(entry.pattern), !seen.contains(key) else { - return - } - seen.insert(key) - allowlist.append(entry) - } - for entry in currentAllowlist { - append(entry) - } - for entry in legacyAllowlist { - append(entry) - } - - return ExecApprovalsAgent( - security: current.security ?? legacy.security, - ask: current.ask ?? legacy.ask, - askFallback: current.askFallback ?? legacy.askFallback, - autoAllowSkills: current.autoAllowSkills ?? legacy.autoAllowSkills, - allowlist: allowlist.isEmpty ? nil : allowlist) - } -} - -enum ExecApprovalHelpers { - static func validateAllowlistPattern(_ pattern: String?) -> ExecAllowlistPatternValidation { - let trimmed = pattern?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - guard !trimmed.isEmpty else { return .invalid(.empty) } - guard self.containsPathComponent(trimmed) else { return .invalid(.missingPathComponent) } - return .valid(trimmed) - } - - static func isPathPattern(_ pattern: String?) -> Bool { - switch self.validateAllowlistPattern(pattern) { - case .valid: - true - case .invalid: - false - } - } - - static func parseDecision(_ raw: String?) -> ExecApprovalDecision? { - let trimmed = raw?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - guard !trimmed.isEmpty else { return nil } - return ExecApprovalDecision(rawValue: trimmed) - } - - static func requiresAsk( - ask: ExecAsk, - security: ExecSecurity, - allowlistMatch: ExecAllowlistEntry?, - skillAllow: Bool) -> Bool - { - if ask == .always { return true } - if ask == .onMiss, security == .allowlist, allowlistMatch == nil, !skillAllow { return true } - return false - } - - static func allowlistPattern(command: [String], resolution: ExecCommandResolution?) -> String? { - let pattern = resolution?.resolvedPath ?? resolution?.rawExecutable ?? command.first ?? "" - return pattern.isEmpty ? nil : pattern - } - - private static func containsPathComponent(_ pattern: String) -> Bool { - pattern.contains("/") || pattern.contains("~") || pattern.contains("\\") - } -} - -struct ExecEventPayload: Codable, Sendable { - var sessionKey: String - var runId: String - var host: String - var command: String? - var exitCode: Int? - var timedOut: Bool? - var success: Bool? - var output: String? - var reason: String? - - static func truncateOutput(_ raw: String, maxChars: Int = 20000) -> String? { - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - if trimmed.count <= maxChars { return trimmed } - let suffix = trimmed.suffix(maxChars) - return "... (truncated) \(suffix)" - } -} - -actor SkillBinsCache { - static let shared = SkillBinsCache() - - private var bins: Set = [] - private var lastRefresh: Date? - private let refreshInterval: TimeInterval = 90 - - func currentBins(force: Bool = false) async -> Set { - if force || self.isStale() { - await self.refresh() - } - return self.bins - } - - func refresh() async { - do { - let report = try await GatewayConnection.shared.skillsStatus() - var next = Set() - for skill in report.skills { - for bin in skill.requirements.bins { - let trimmed = bin.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmed.isEmpty { next.insert(trimmed) } - } - } - self.bins = next - self.lastRefresh = Date() - } catch { - if self.lastRefresh == nil { - self.bins = [] - } - } - } - - private func isStale() -> Bool { - guard let lastRefresh else { return true } - return Date().timeIntervalSince(lastRefresh) > self.refreshInterval - } -} diff --git a/apps/macos/Sources/OpenClaw/ExecApprovalsGatewayPrompter.swift b/apps/macos/Sources/OpenClaw/ExecApprovalsGatewayPrompter.swift deleted file mode 100644 index 670fa891c5b..00000000000 --- a/apps/macos/Sources/OpenClaw/ExecApprovalsGatewayPrompter.swift +++ /dev/null @@ -1,123 +0,0 @@ -import CoreGraphics -import Foundation -import OpenClawKit -import OpenClawProtocol -import OSLog - -@MainActor -final class ExecApprovalsGatewayPrompter { - static let shared = ExecApprovalsGatewayPrompter() - - private let logger = Logger(subsystem: "ai.openclaw", category: "exec-approvals.gateway") - private var task: Task? - - struct GatewayApprovalRequest: Codable, Sendable { - var id: String - var request: ExecApprovalPromptRequest - var createdAtMs: Int - var expiresAtMs: Int - } - - func start() { - guard self.task == nil else { return } - self.task = Task { [weak self] in - await self?.run() - } - } - - func stop() { - self.task?.cancel() - self.task = nil - } - - private func run() async { - let stream = await GatewayConnection.shared.subscribe(bufferingNewest: 200) - for await push in stream { - if Task.isCancelled { return } - await self.handle(push: push) - } - } - - private func handle(push: GatewayPush) async { - guard case let .event(evt) = push else { return } - guard evt.event == "exec.approval.requested" else { return } - guard let payload = evt.payload else { return } - do { - let data = try JSONEncoder().encode(payload) - let request = try JSONDecoder().decode(GatewayApprovalRequest.self, from: data) - guard self.shouldPresent(request: request) else { return } - let decision = ExecApprovalsPromptPresenter.prompt(request.request) - try await GatewayConnection.shared.requestVoid( - method: .execApprovalResolve, - params: [ - "id": AnyCodable(request.id), - "decision": AnyCodable(decision.rawValue), - ], - timeoutMs: 10000) - } catch { - self.logger.error("exec approval handling failed \(error.localizedDescription, privacy: .public)") - } - } - - private func shouldPresent(request: GatewayApprovalRequest) -> Bool { - let mode = AppStateStore.shared.connectionMode - let activeSession = WebChatManager.shared.activeSessionKey?.trimmingCharacters(in: .whitespacesAndNewlines) - let requestSession = request.request.sessionKey?.trimmingCharacters(in: .whitespacesAndNewlines) - return Self.shouldPresent( - mode: mode, - activeSession: activeSession, - requestSession: requestSession, - lastInputSeconds: Self.lastInputSeconds(), - thresholdSeconds: 120) - } - - private static func shouldPresent( - mode: AppState.ConnectionMode, - activeSession: String?, - requestSession: String?, - lastInputSeconds: Int?, - thresholdSeconds: Int) -> Bool - { - let active = activeSession?.trimmingCharacters(in: .whitespacesAndNewlines) - let requested = requestSession?.trimmingCharacters(in: .whitespacesAndNewlines) - let recentlyActive = lastInputSeconds.map { $0 <= thresholdSeconds } ?? (mode == .local) - - if let session = requested, !session.isEmpty { - if let active, !active.isEmpty { - return active == session - } - return recentlyActive - } - - if let active, !active.isEmpty { - return true - } - return mode == .local - } - - private static func lastInputSeconds() -> Int? { - let anyEvent = CGEventType(rawValue: UInt32.max) ?? .null - let seconds = CGEventSource.secondsSinceLastEventType(.combinedSessionState, eventType: anyEvent) - if seconds.isNaN || seconds.isInfinite || seconds < 0 { return nil } - return Int(seconds.rounded()) - } -} - -#if DEBUG -extension ExecApprovalsGatewayPrompter { - static func _testShouldPresent( - mode: AppState.ConnectionMode, - activeSession: String?, - requestSession: String?, - lastInputSeconds: Int?, - thresholdSeconds: Int = 120) -> Bool - { - self.shouldPresent( - mode: mode, - activeSession: activeSession, - requestSession: requestSession, - lastInputSeconds: lastInputSeconds, - thresholdSeconds: thresholdSeconds) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/ExecApprovalsSocket.swift b/apps/macos/Sources/OpenClaw/ExecApprovalsSocket.swift deleted file mode 100644 index 362a7da01d8..00000000000 --- a/apps/macos/Sources/OpenClaw/ExecApprovalsSocket.swift +++ /dev/null @@ -1,780 +0,0 @@ -import AppKit -import CryptoKit -import Darwin -import Foundation -import OpenClawKit -import OSLog - -struct ExecApprovalPromptRequest: Codable, Sendable { - var command: String - var cwd: String? - var host: String? - var security: String? - var ask: String? - var agentId: String? - var resolvedPath: String? - var sessionKey: String? -} - -private struct ExecApprovalSocketRequest: Codable { - var type: String - var token: String - var id: String - var request: ExecApprovalPromptRequest -} - -private struct ExecApprovalSocketDecision: Codable { - var type: String - var id: String - var decision: ExecApprovalDecision -} - -private struct ExecHostSocketRequest: Codable { - var type: String - var id: String - var nonce: String - var ts: Int - var hmac: String - var requestJson: String -} - -private struct ExecHostRequest: Codable { - var command: [String] - var rawCommand: String? - var cwd: String? - var env: [String: String]? - var timeoutMs: Int? - var needsScreenRecording: Bool? - var agentId: String? - var sessionKey: String? - var approvalDecision: ExecApprovalDecision? -} - -private struct ExecHostRunResult: Codable { - var exitCode: Int? - var timedOut: Bool - var success: Bool - var stdout: String - var stderr: String - var error: String? -} - -private struct ExecHostError: Codable { - var code: String - var message: String - var reason: String? -} - -private struct ExecHostResponse: Codable { - var type: String - var id: String - var ok: Bool - var payload: ExecHostRunResult? - var error: ExecHostError? -} - -enum ExecApprovalsSocketClient { - private struct TimeoutError: LocalizedError { - var message: String - var errorDescription: String? { - self.message - } - } - - static func requestDecision( - socketPath: String, - token: String, - request: ExecApprovalPromptRequest, - timeoutMs: Int = 15000) async -> ExecApprovalDecision? - { - let trimmedPath = socketPath.trimmingCharacters(in: .whitespacesAndNewlines) - let trimmedToken = token.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmedPath.isEmpty, !trimmedToken.isEmpty else { return nil } - do { - return try await AsyncTimeout.withTimeoutMs( - timeoutMs: timeoutMs, - onTimeout: { - TimeoutError(message: "exec approvals socket timeout") - }, - operation: { - try await Task.detached { - try self.requestDecisionSync( - socketPath: trimmedPath, - token: trimmedToken, - request: request) - }.value - }) - } catch { - return nil - } - } - - private static func requestDecisionSync( - socketPath: String, - token: String, - request: ExecApprovalPromptRequest) throws -> ExecApprovalDecision? - { - let fd = socket(AF_UNIX, SOCK_STREAM, 0) - guard fd >= 0 else { - throw NSError(domain: "ExecApprovals", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "socket create failed", - ]) - } - - var addr = sockaddr_un() - addr.sun_family = sa_family_t(AF_UNIX) - let maxLen = MemoryLayout.size(ofValue: addr.sun_path) - if socketPath.utf8.count >= maxLen { - throw NSError(domain: "ExecApprovals", code: 2, userInfo: [ - NSLocalizedDescriptionKey: "socket path too long", - ]) - } - socketPath.withCString { cstr in - withUnsafeMutablePointer(to: &addr.sun_path) { ptr in - let raw = UnsafeMutableRawPointer(ptr).assumingMemoryBound(to: Int8.self) - strncpy(raw, cstr, maxLen - 1) - } - } - let size = socklen_t(MemoryLayout.size(ofValue: addr)) - let result = withUnsafePointer(to: &addr) { ptr in - ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) { rebound in - connect(fd, rebound, size) - } - } - if result != 0 { - throw NSError(domain: "ExecApprovals", code: 3, userInfo: [ - NSLocalizedDescriptionKey: "socket connect failed", - ]) - } - - let handle = FileHandle(fileDescriptor: fd, closeOnDealloc: true) - - let message = ExecApprovalSocketRequest( - type: "request", - token: token, - id: UUID().uuidString, - request: request) - let data = try JSONEncoder().encode(message) - var payload = data - payload.append(0x0A) - try handle.write(contentsOf: payload) - - guard let line = try self.readLine(from: handle, maxBytes: 256_000), - let lineData = line.data(using: .utf8) - else { return nil } - let response = try JSONDecoder().decode(ExecApprovalSocketDecision.self, from: lineData) - return response.decision - } - - private static func readLine(from handle: FileHandle, maxBytes: Int) throws -> String? { - var buffer = Data() - while buffer.count < maxBytes { - let chunk = try handle.read(upToCount: 4096) ?? Data() - if chunk.isEmpty { break } - buffer.append(chunk) - if buffer.contains(0x0A) { break } - } - guard let newlineIndex = buffer.firstIndex(of: 0x0A) else { - guard !buffer.isEmpty else { return nil } - return String(data: buffer, encoding: .utf8) - } - let lineData = buffer.subdata(in: 0.. ExecApprovalDecision { - NSApp.activate(ignoringOtherApps: true) - let alert = NSAlert() - alert.alertStyle = .warning - alert.messageText = "Allow this command?" - alert.informativeText = "Review the command details before allowing." - alert.accessoryView = self.buildAccessoryView(request) - - alert.addButton(withTitle: "Allow Once") - alert.addButton(withTitle: "Always Allow") - alert.addButton(withTitle: "Don't Allow") - if #available(macOS 11.0, *), alert.buttons.indices.contains(2) { - alert.buttons[2].hasDestructiveAction = true - } - - switch alert.runModal() { - case .alertFirstButtonReturn: - return .allowOnce - case .alertSecondButtonReturn: - return .allowAlways - default: - return .deny - } - } - - @MainActor - private static func buildAccessoryView(_ request: ExecApprovalPromptRequest) -> NSView { - let stack = NSStackView() - stack.orientation = .vertical - stack.spacing = 8 - stack.alignment = .leading - stack.translatesAutoresizingMaskIntoConstraints = false - stack.widthAnchor.constraint(greaterThanOrEqualToConstant: 380).isActive = true - - let commandTitle = NSTextField(labelWithString: "Command") - commandTitle.font = NSFont.boldSystemFont(ofSize: NSFont.systemFontSize) - stack.addArrangedSubview(commandTitle) - - let commandText = NSTextView() - commandText.isEditable = false - commandText.isSelectable = true - commandText.drawsBackground = true - commandText.backgroundColor = NSColor.textBackgroundColor - commandText.font = NSFont.monospacedSystemFont(ofSize: NSFont.systemFontSize, weight: .regular) - commandText.string = request.command - commandText.textContainerInset = NSSize(width: 6, height: 6) - commandText.textContainer?.lineFragmentPadding = 0 - commandText.textContainer?.widthTracksTextView = true - commandText.isHorizontallyResizable = false - commandText.isVerticallyResizable = true - - let commandScroll = NSScrollView() - commandScroll.borderType = .lineBorder - commandScroll.hasVerticalScroller = true - commandScroll.hasHorizontalScroller = false - commandScroll.autohidesScrollers = true - commandScroll.documentView = commandText - commandScroll.translatesAutoresizingMaskIntoConstraints = false - commandScroll.widthAnchor.constraint(greaterThanOrEqualToConstant: 380).isActive = true - commandScroll.widthAnchor.constraint(lessThanOrEqualToConstant: 440).isActive = true - commandScroll.heightAnchor.constraint(greaterThanOrEqualToConstant: 56).isActive = true - commandScroll.heightAnchor.constraint(lessThanOrEqualToConstant: 120).isActive = true - stack.addArrangedSubview(commandScroll) - - let contextTitle = NSTextField(labelWithString: "Context") - contextTitle.font = NSFont.boldSystemFont(ofSize: NSFont.systemFontSize) - stack.addArrangedSubview(contextTitle) - - let contextStack = NSStackView() - contextStack.orientation = .vertical - contextStack.spacing = 4 - contextStack.alignment = .leading - - let trimmedCwd = request.cwd?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if !trimmedCwd.isEmpty { - self.addDetailRow(title: "Working directory", value: trimmedCwd, to: contextStack) - } - let trimmedAgent = request.agentId?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if !trimmedAgent.isEmpty { - self.addDetailRow(title: "Agent", value: trimmedAgent, to: contextStack) - } - let trimmedPath = request.resolvedPath?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if !trimmedPath.isEmpty { - self.addDetailRow(title: "Executable", value: trimmedPath, to: contextStack) - } - let trimmedHost = request.host?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if !trimmedHost.isEmpty { - self.addDetailRow(title: "Host", value: trimmedHost, to: contextStack) - } - if let security = request.security?.trimmingCharacters(in: .whitespacesAndNewlines), !security.isEmpty { - self.addDetailRow(title: "Security", value: security, to: contextStack) - } - if let ask = request.ask?.trimmingCharacters(in: .whitespacesAndNewlines), !ask.isEmpty { - self.addDetailRow(title: "Ask mode", value: ask, to: contextStack) - } - - if contextStack.arrangedSubviews.isEmpty { - let empty = NSTextField(labelWithString: "No additional context provided.") - empty.textColor = NSColor.secondaryLabelColor - empty.font = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize) - contextStack.addArrangedSubview(empty) - } - - stack.addArrangedSubview(contextStack) - - let footer = NSTextField(labelWithString: "This runs on this machine.") - footer.textColor = NSColor.secondaryLabelColor - footer.font = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize) - stack.addArrangedSubview(footer) - - return stack - } - - @MainActor - private static func addDetailRow(title: String, value: String, to stack: NSStackView) { - let row = NSStackView() - row.orientation = .horizontal - row.spacing = 6 - row.alignment = .firstBaseline - - let titleLabel = NSTextField(labelWithString: "\(title):") - titleLabel.font = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize, weight: .semibold) - titleLabel.textColor = NSColor.secondaryLabelColor - - let valueLabel = NSTextField(labelWithString: value) - valueLabel.font = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize) - valueLabel.lineBreakMode = .byTruncatingMiddle - valueLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) - - row.addArrangedSubview(titleLabel) - row.addArrangedSubview(valueLabel) - stack.addArrangedSubview(row) - } -} - -@MainActor -private enum ExecHostExecutor { - private typealias ExecApprovalContext = ExecApprovalEvaluation - - static func handle(_ request: ExecHostRequest) async -> ExecHostResponse { - let command = request.command.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } - guard !command.isEmpty else { - return self.errorResponse( - code: "INVALID_REQUEST", - message: "command required", - reason: "invalid") - } - - let context = await self.buildContext(request: request, command: command) - if context.security == .deny { - return self.errorResponse( - code: "UNAVAILABLE", - message: "SYSTEM_RUN_DISABLED: security=deny", - reason: "security=deny") - } - - let approvalDecision = request.approvalDecision - if approvalDecision == .deny { - return self.errorResponse( - code: "UNAVAILABLE", - message: "SYSTEM_RUN_DENIED: user denied", - reason: "user-denied") - } - - var approvedByAsk = approvalDecision != nil - if ExecApprovalHelpers.requiresAsk( - ask: context.ask, - security: context.security, - allowlistMatch: context.allowlistMatch, - skillAllow: context.skillAllow), - approvalDecision == nil - { - let decision = ExecApprovalsPromptPresenter.prompt( - ExecApprovalPromptRequest( - command: context.displayCommand, - cwd: request.cwd, - host: "node", - security: context.security.rawValue, - ask: context.ask.rawValue, - agentId: context.agentId, - resolvedPath: context.resolution?.resolvedPath, - sessionKey: request.sessionKey)) - - switch decision { - case .deny: - return self.errorResponse( - code: "UNAVAILABLE", - message: "SYSTEM_RUN_DENIED: user denied", - reason: "user-denied") - case .allowAlways: - approvedByAsk = true - self.persistAllowlistEntry(decision: decision, context: context) - case .allowOnce: - approvedByAsk = true - } - } - - self.persistAllowlistEntry(decision: approvalDecision, context: context) - - if context.security == .allowlist, - !context.allowlistSatisfied, - !context.skillAllow, - !approvedByAsk - { - return self.errorResponse( - code: "UNAVAILABLE", - message: "SYSTEM_RUN_DENIED: allowlist miss", - reason: "allowlist-miss") - } - - if context.allowlistSatisfied { - var seenPatterns = Set() - for (idx, match) in context.allowlistMatches.enumerated() { - if !seenPatterns.insert(match.pattern).inserted { - continue - } - let resolvedPath = idx < context.allowlistResolutions.count - ? context.allowlistResolutions[idx].resolvedPath - : nil - ExecApprovalsStore.recordAllowlistUse( - agentId: context.agentId, - pattern: match.pattern, - command: context.displayCommand, - resolvedPath: resolvedPath) - } - } - - if let errorResponse = await self.ensureScreenRecordingAccess(request.needsScreenRecording) { - return errorResponse - } - - return await self.runCommand( - command: command, - cwd: request.cwd, - env: context.env, - timeoutMs: request.timeoutMs) - } - - private static func buildContext(request: ExecHostRequest, command: [String]) async -> ExecApprovalContext { - await ExecApprovalEvaluator.evaluate( - command: command, - rawCommand: request.rawCommand, - cwd: request.cwd, - envOverrides: request.env, - agentId: request.agentId) - } - - private static func persistAllowlistEntry( - decision: ExecApprovalDecision?, - context: ExecApprovalContext) - { - guard decision == .allowAlways, context.security == .allowlist else { return } - var seenPatterns = Set() - for candidate in context.allowlistResolutions { - guard let pattern = ExecApprovalHelpers.allowlistPattern( - command: context.command, - resolution: candidate) - else { - continue - } - if seenPatterns.insert(pattern).inserted { - ExecApprovalsStore.addAllowlistEntry(agentId: context.agentId, pattern: pattern) - } - } - } - - private static func ensureScreenRecordingAccess(_ needsScreenRecording: Bool?) async -> ExecHostResponse? { - guard needsScreenRecording == true else { return nil } - let authorized = await PermissionManager - .status([.screenRecording])[.screenRecording] ?? false - if authorized { return nil } - return self.errorResponse( - code: "UNAVAILABLE", - message: "PERMISSION_MISSING: screenRecording", - reason: "permission:screenRecording") - } - - private static func runCommand( - command: [String], - cwd: String?, - env: [String: String]?, - timeoutMs: Int?) async -> ExecHostResponse - { - let timeoutSec = timeoutMs.flatMap { Double($0) / 1000.0 } - let result = await Task.detached { () -> ShellExecutor.ShellResult in - await ShellExecutor.runDetailed( - command: command, - cwd: cwd, - env: env, - timeout: timeoutSec) - }.value - let payload = ExecHostRunResult( - exitCode: result.exitCode, - timedOut: result.timedOut, - success: result.success, - stdout: result.stdout, - stderr: result.stderr, - error: result.errorMessage) - return self.successResponse(payload) - } - - private static func errorResponse( - code: String, - message: String, - reason: String?) -> ExecHostResponse - { - ExecHostResponse( - type: "exec-res", - id: UUID().uuidString, - ok: false, - payload: nil, - error: ExecHostError(code: code, message: message, reason: reason)) - } - - private static func successResponse(_ payload: ExecHostRunResult) -> ExecHostResponse { - ExecHostResponse( - type: "exec-res", - id: UUID().uuidString, - ok: true, - payload: payload, - error: nil) - } -} - -private final class ExecApprovalsSocketServer: @unchecked Sendable { - private let logger = Logger(subsystem: "ai.openclaw", category: "exec-approvals.socket") - private let socketPath: String - private let token: String - private let onPrompt: @Sendable (ExecApprovalPromptRequest) async -> ExecApprovalDecision - private let onExec: @Sendable (ExecHostRequest) async -> ExecHostResponse - private var socketFD: Int32 = -1 - private var acceptTask: Task? - private var isRunning = false - - init( - socketPath: String, - token: String, - onPrompt: @escaping @Sendable (ExecApprovalPromptRequest) async -> ExecApprovalDecision, - onExec: @escaping @Sendable (ExecHostRequest) async -> ExecHostResponse) - { - self.socketPath = socketPath - self.token = token - self.onPrompt = onPrompt - self.onExec = onExec - } - - func start() { - guard !self.isRunning else { return } - self.isRunning = true - self.acceptTask = Task.detached { [weak self] in - await self?.runAcceptLoop() - } - } - - func stop() { - self.isRunning = false - self.acceptTask?.cancel() - self.acceptTask = nil - if self.socketFD >= 0 { - close(self.socketFD) - self.socketFD = -1 - } - if !self.socketPath.isEmpty { - unlink(self.socketPath) - } - } - - private func runAcceptLoop() async { - let fd = self.openSocket() - guard fd >= 0 else { - self.isRunning = false - return - } - self.socketFD = fd - while self.isRunning { - var addr = sockaddr_un() - var len = socklen_t(MemoryLayout.size(ofValue: addr)) - let client = withUnsafeMutablePointer(to: &addr) { ptr in - ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) { rebound in - accept(fd, rebound, &len) - } - } - if client < 0 { - if errno == EINTR { continue } - break - } - Task.detached { [weak self] in - await self?.handleClient(fd: client) - } - } - } - - private func openSocket() -> Int32 { - let fd = socket(AF_UNIX, SOCK_STREAM, 0) - guard fd >= 0 else { - self.logger.error("exec approvals socket create failed") - return -1 - } - unlink(self.socketPath) - var addr = sockaddr_un() - addr.sun_family = sa_family_t(AF_UNIX) - let maxLen = MemoryLayout.size(ofValue: addr.sun_path) - if self.socketPath.utf8.count >= maxLen { - self.logger.error("exec approvals socket path too long") - close(fd) - return -1 - } - self.socketPath.withCString { cstr in - withUnsafeMutablePointer(to: &addr.sun_path) { ptr in - let raw = UnsafeMutableRawPointer(ptr).assumingMemoryBound(to: Int8.self) - memset(raw, 0, maxLen) - strncpy(raw, cstr, maxLen - 1) - } - } - let size = socklen_t(MemoryLayout.size(ofValue: addr)) - let result = withUnsafePointer(to: &addr) { ptr in - ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) { rebound in - bind(fd, rebound, size) - } - } - if result != 0 { - self.logger.error("exec approvals socket bind failed") - close(fd) - return -1 - } - if listen(fd, 16) != 0 { - self.logger.error("exec approvals socket listen failed") - close(fd) - return -1 - } - chmod(self.socketPath, 0o600) - self.logger.info("exec approvals socket listening at \(self.socketPath, privacy: .public)") - return fd - } - - private func handleClient(fd: Int32) async { - let handle = FileHandle(fileDescriptor: fd, closeOnDealloc: true) - do { - guard self.isAllowedPeer(fd: fd) else { - try self.sendApprovalResponse(handle: handle, id: UUID().uuidString, decision: .deny) - return - } - guard let line = try self.readLine(from: handle, maxBytes: 256_000), - let data = line.data(using: .utf8) - else { - return - } - guard - let envelope = try JSONSerialization.jsonObject(with: data) as? [String: Any], - let type = envelope["type"] as? String - else { - return - } - - if type == "request" { - let request = try JSONDecoder().decode(ExecApprovalSocketRequest.self, from: data) - guard request.token == self.token else { - try self.sendApprovalResponse(handle: handle, id: request.id, decision: .deny) - return - } - let decision = await self.onPrompt(request.request) - try self.sendApprovalResponse(handle: handle, id: request.id, decision: decision) - return - } - - if type == "exec" { - let request = try JSONDecoder().decode(ExecHostSocketRequest.self, from: data) - let response = await self.handleExecRequest(request) - try self.sendExecResponse(handle: handle, response: response) - return - } - } catch { - self.logger.error("exec approvals socket handling failed: \(error.localizedDescription, privacy: .public)") - } - } - - private func readLine(from handle: FileHandle, maxBytes: Int) throws -> String? { - var buffer = Data() - while buffer.count < maxBytes { - let chunk = try handle.read(upToCount: 4096) ?? Data() - if chunk.isEmpty { break } - buffer.append(chunk) - if buffer.contains(0x0A) { break } - } - guard let newlineIndex = buffer.firstIndex(of: 0x0A) else { - guard !buffer.isEmpty else { return nil } - return String(data: buffer, encoding: .utf8) - } - let lineData = buffer.subdata(in: 0.. Bool { - var uid = uid_t(0) - var gid = gid_t(0) - if getpeereid(fd, &uid, &gid) != 0 { - return false - } - return uid == geteuid() - } - - private func handleExecRequest(_ request: ExecHostSocketRequest) async -> ExecHostResponse { - let nowMs = Int(Date().timeIntervalSince1970 * 1000) - if abs(nowMs - request.ts) > 10000 { - return ExecHostResponse( - type: "exec-res", - id: request.id, - ok: false, - payload: nil, - error: ExecHostError(code: "INVALID_REQUEST", message: "expired request", reason: "ttl")) - } - let expected = self.hmacHex(nonce: request.nonce, ts: request.ts, requestJson: request.requestJson) - if expected != request.hmac { - return ExecHostResponse( - type: "exec-res", - id: request.id, - ok: false, - payload: nil, - error: ExecHostError(code: "INVALID_REQUEST", message: "invalid auth", reason: "hmac")) - } - guard let requestData = request.requestJson.data(using: .utf8), - let payload = try? JSONDecoder().decode(ExecHostRequest.self, from: requestData) - else { - return ExecHostResponse( - type: "exec-res", - id: request.id, - ok: false, - payload: nil, - error: ExecHostError(code: "INVALID_REQUEST", message: "invalid payload", reason: "json")) - } - let response = await self.onExec(payload) - return ExecHostResponse( - type: "exec-res", - id: request.id, - ok: response.ok, - payload: response.payload, - error: response.error) - } - - private func hmacHex(nonce: String, ts: Int, requestJson: String) -> String { - let key = SymmetricKey(data: Data(self.token.utf8)) - let message = "\(nonce):\(ts):\(requestJson)" - let mac = HMAC.authenticationCode(for: Data(message.utf8), using: key) - return mac.map { String(format: "%02x", $0) }.joined() - } -} diff --git a/apps/macos/Sources/OpenClaw/ExecCommandResolution.swift b/apps/macos/Sources/OpenClaw/ExecCommandResolution.swift deleted file mode 100644 index 8910163456f..00000000000 --- a/apps/macos/Sources/OpenClaw/ExecCommandResolution.swift +++ /dev/null @@ -1,305 +0,0 @@ -import Foundation - -struct ExecCommandResolution: Sendable { - let rawExecutable: String - let resolvedPath: String? - let executableName: String - let cwd: String? - - static func resolve( - command: [String], - rawCommand: String?, - cwd: String?, - env: [String: String]?) -> ExecCommandResolution? - { - let trimmedRaw = rawCommand?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if !trimmedRaw.isEmpty, let token = self.parseFirstToken(trimmedRaw) { - return self.resolveExecutable(rawExecutable: token, cwd: cwd, env: env) - } - return self.resolve(command: command, cwd: cwd, env: env) - } - - static func resolveForAllowlist( - command: [String], - rawCommand: String?, - cwd: String?, - env: [String: String]?) -> [ExecCommandResolution] - { - let shell = self.extractShellCommandFromArgv(command: command, rawCommand: rawCommand) - if shell.isWrapper { - guard let shellCommand = shell.command, - let segments = self.splitShellCommandChain(shellCommand) - else { - // Fail closed: if we cannot safely parse a shell wrapper payload, - // treat this as an allowlist miss and require approval. - return [] - } - var resolutions: [ExecCommandResolution] = [] - resolutions.reserveCapacity(segments.count) - for segment in segments { - guard let token = self.parseFirstToken(segment), - let resolution = self.resolveExecutable(rawExecutable: token, cwd: cwd, env: env) - else { - return [] - } - resolutions.append(resolution) - } - return resolutions - } - - guard let resolution = self.resolve(command: command, rawCommand: rawCommand, cwd: cwd, env: env) else { - return [] - } - return [resolution] - } - - static func resolve(command: [String], cwd: String?, env: [String: String]?) -> ExecCommandResolution? { - guard let raw = command.first?.trimmingCharacters(in: .whitespacesAndNewlines), !raw.isEmpty else { - return nil - } - return self.resolveExecutable(rawExecutable: raw, cwd: cwd, env: env) - } - - private static func resolveExecutable( - rawExecutable: String, - cwd: String?, - env: [String: String]?) -> ExecCommandResolution? - { - let expanded = rawExecutable.hasPrefix("~") ? (rawExecutable as NSString).expandingTildeInPath : rawExecutable - let hasPathSeparator = expanded.contains("/") || expanded.contains("\\") - let resolvedPath: String? = { - if hasPathSeparator { - if expanded.hasPrefix("/") { - return expanded - } - let base = cwd?.trimmingCharacters(in: .whitespacesAndNewlines) - let root = (base?.isEmpty == false) ? base! : FileManager().currentDirectoryPath - return URL(fileURLWithPath: root).appendingPathComponent(expanded).path - } - let searchPaths = self.searchPaths(from: env) - return CommandResolver.findExecutable(named: expanded, searchPaths: searchPaths) - }() - let name = resolvedPath.map { URL(fileURLWithPath: $0).lastPathComponent } ?? expanded - return ExecCommandResolution( - rawExecutable: expanded, - resolvedPath: resolvedPath, - executableName: name, - cwd: cwd) - } - - private static func parseFirstToken(_ command: String) -> String? { - let trimmed = command.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - guard let first = trimmed.first else { return nil } - if first == "\"" || first == "'" { - let rest = trimmed.dropFirst() - if let end = rest.firstIndex(of: first) { - return String(rest[.. String { - let trimmed = token.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return "" } - let normalized = trimmed.replacingOccurrences(of: "\\", with: "/") - return normalized.split(separator: "/").last.map { String($0).lowercased() } ?? normalized.lowercased() - } - - private static func extractShellCommandFromArgv( - command: [String], - rawCommand: String?) -> (isWrapper: Bool, command: String?) - { - guard let token0 = command.first?.trimmingCharacters(in: .whitespacesAndNewlines), !token0.isEmpty else { - return (false, nil) - } - let base0 = self.basenameLower(token0) - let trimmedRaw = rawCommand?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let preferredRaw = trimmedRaw.isEmpty ? nil : trimmedRaw - - if ["sh", "bash", "zsh", "dash", "ksh"].contains(base0) { - let flag = command.count > 1 ? command[1].trimmingCharacters(in: .whitespacesAndNewlines) : "" - guard flag == "-lc" || flag == "-c" else { return (false, nil) } - let payload = command.count > 2 ? command[2].trimmingCharacters(in: .whitespacesAndNewlines) : "" - let normalized = preferredRaw ?? (payload.isEmpty ? nil : payload) - return (true, normalized) - } - - if base0 == "cmd.exe" || base0 == "cmd" { - guard let idx = command - .firstIndex(where: { $0.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() == "/c" }) - else { - return (false, nil) - } - let tail = command.suffix(from: command.index(after: idx)).joined(separator: " ") - let payload = tail.trimmingCharacters(in: .whitespacesAndNewlines) - let normalized = preferredRaw ?? (payload.isEmpty ? nil : payload) - return (true, normalized) - } - - return (false, nil) - } - - private enum ShellTokenContext { - case unquoted - case doubleQuoted - } - - private struct ShellFailClosedRule { - let token: Character - let next: Character? - } - - private static let shellFailClosedRules: [ShellTokenContext: [ShellFailClosedRule]] = [ - .unquoted: [ - ShellFailClosedRule(token: "`", next: nil), - ShellFailClosedRule(token: "$", next: "("), - ShellFailClosedRule(token: "<", next: "("), - ShellFailClosedRule(token: ">", next: "("), - ], - .doubleQuoted: [ - ShellFailClosedRule(token: "`", next: nil), - ShellFailClosedRule(token: "$", next: "("), - ], - ] - - private static func splitShellCommandChain(_ command: String) -> [String]? { - let trimmed = command.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - - var segments: [String] = [] - var current = "" - var inSingle = false - var inDouble = false - var escaped = false - let chars = Array(trimmed) - var idx = 0 - - func appendCurrent() -> Bool { - let segment = current.trimmingCharacters(in: .whitespacesAndNewlines) - guard !segment.isEmpty else { return false } - segments.append(segment) - current.removeAll(keepingCapacity: true) - return true - } - - while idx < chars.count { - let ch = chars[idx] - let next: Character? = idx + 1 < chars.count ? chars[idx + 1] : nil - - if escaped { - current.append(ch) - escaped = false - idx += 1 - continue - } - - if ch == "\\", !inSingle { - current.append(ch) - escaped = true - idx += 1 - continue - } - - if ch == "'", !inDouble { - inSingle.toggle() - current.append(ch) - idx += 1 - continue - } - - if ch == "\"", !inSingle { - inDouble.toggle() - current.append(ch) - idx += 1 - continue - } - - if !inSingle, self.shouldFailClosedForShell(ch: ch, next: next, inDouble: inDouble) { - // Fail closed on command/process substitution in allowlist mode, - // including command substitution inside double-quoted shell strings. - return nil - } - - if !inSingle, !inDouble { - let prev: Character? = idx > 0 ? chars[idx - 1] : nil - if let delimiterStep = self.chainDelimiterStep(ch: ch, prev: prev, next: next) { - guard appendCurrent() else { return nil } - idx += delimiterStep - continue - } - } - - current.append(ch) - idx += 1 - } - - if escaped || inSingle || inDouble { return nil } - guard appendCurrent() else { return nil } - return segments - } - - private static func shouldFailClosedForShell(ch: Character, next: Character?, inDouble: Bool) -> Bool { - let context: ShellTokenContext = inDouble ? .doubleQuoted : .unquoted - guard let rules = self.shellFailClosedRules[context] else { - return false - } - for rule in rules { - if ch == rule.token, rule.next == nil || next == rule.next { - return true - } - } - return false - } - - private static func chainDelimiterStep(ch: Character, prev: Character?, next: Character?) -> Int? { - if ch == ";" || ch == "\n" { - return 1 - } - if ch == "&" { - if next == "&" { - return 2 - } - // Keep fd redirections like 2>&1 or &>file intact. - let prevIsRedirect = prev == ">" - let nextIsRedirect = next == ">" - return (!prevIsRedirect && !nextIsRedirect) ? 1 : nil - } - if ch == "|" { - if next == "|" || next == "&" { - return 2 - } - return 1 - } - return nil - } - - private static func searchPaths(from env: [String: String]?) -> [String] { - let raw = env?["PATH"] - if let raw, !raw.isEmpty { - return raw.split(separator: ":").map(String.init) - } - return CommandResolver.preferredPaths() - } -} - -enum ExecCommandFormatter { - static func displayString(for argv: [String]) -> String { - argv.map { arg in - let trimmed = arg.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return "\"\"" } - let needsQuotes = trimmed.contains { $0.isWhitespace || $0 == "\"" } - if !needsQuotes { return trimmed } - let escaped = trimmed.replacingOccurrences(of: "\"", with: "\\\"") - return "\"\(escaped)\"" - }.joined(separator: " ") - } - - static func displayString(for argv: [String], rawCommand: String?) -> String { - let trimmed = rawCommand?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if !trimmed.isEmpty { return trimmed } - return self.displayString(for: argv) - } -} diff --git a/apps/macos/Sources/OpenClaw/FileHandle+SafeRead.swift b/apps/macos/Sources/OpenClaw/FileHandle+SafeRead.swift deleted file mode 100644 index 7cd16096938..00000000000 --- a/apps/macos/Sources/OpenClaw/FileHandle+SafeRead.swift +++ /dev/null @@ -1,28 +0,0 @@ -import Foundation - -extension FileHandle { - /// Reads until EOF using the throwing FileHandle API and returns empty `Data` on failure. - /// - /// Important: Avoid legacy, non-throwing FileHandle read APIs (e.g. `readDataToEndOfFile()` and - /// `availableData`). They can raise Objective-C exceptions when the handle is closed/invalid, which - /// will abort the process. - func readToEndSafely() -> Data { - do { - return try self.readToEnd() ?? Data() - } catch { - return Data() - } - } - - /// Reads up to `count` bytes using the throwing FileHandle API and returns empty `Data` on failure/EOF. - /// - /// Important: Use this instead of `availableData` in callbacks like `readabilityHandler` to avoid - /// Objective-C exceptions terminating the process. - func readSafely(upToCount count: Int) -> Data { - do { - return try self.read(upToCount: count) ?? Data() - } catch { - return Data() - } - } -} diff --git a/apps/macos/Sources/OpenClaw/GatewayAutostartPolicy.swift b/apps/macos/Sources/OpenClaw/GatewayAutostartPolicy.swift deleted file mode 100644 index 27f60abadb6..00000000000 --- a/apps/macos/Sources/OpenClaw/GatewayAutostartPolicy.swift +++ /dev/null @@ -1,14 +0,0 @@ -import Foundation - -enum GatewayAutostartPolicy { - static func shouldStartGateway(mode: AppState.ConnectionMode, paused: Bool) -> Bool { - mode == .local && !paused - } - - static func shouldEnsureLaunchAgent( - mode: AppState.ConnectionMode, - paused: Bool) -> Bool - { - self.shouldStartGateway(mode: mode, paused: paused) - } -} diff --git a/apps/macos/Sources/OpenClaw/GatewayConnection.swift b/apps/macos/Sources/OpenClaw/GatewayConnection.swift deleted file mode 100644 index 0d7d582dd33..00000000000 --- a/apps/macos/Sources/OpenClaw/GatewayConnection.swift +++ /dev/null @@ -1,742 +0,0 @@ -import Foundation -import OpenClawChatUI -import OpenClawKit -import OpenClawProtocol -import OSLog - -private let gatewayConnectionLogger = Logger(subsystem: "ai.openclaw", category: "gateway.connection") - -enum GatewayAgentChannel: String, Codable, CaseIterable, Sendable { - case last - case whatsapp - case telegram - case discord - case googlechat - case slack - case signal - case imessage - case msteams - case bluebubbles - case webchat - - init(raw: String?) { - let normalized = (raw ?? "").trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - self = GatewayAgentChannel(rawValue: normalized) ?? .last - } - - var isDeliverable: Bool { - self != .webchat - } - - func shouldDeliver(_ deliver: Bool) -> Bool { - deliver && self.isDeliverable - } -} - -struct GatewayAgentInvocation: Sendable { - var message: String - var sessionKey: String = "main" - var thinking: String? - var deliver: Bool = false - var to: String? - var channel: GatewayAgentChannel = .last - var timeoutSeconds: Int? - var idempotencyKey: String = UUID().uuidString -} - -/// Single, shared Gateway websocket connection for the whole app. -/// -/// This owns exactly one `GatewayChannelActor` and reuses it across all callers -/// (ControlChannel, debug actions, SwiftUI WebChat, etc.). -actor GatewayConnection { - static let shared = GatewayConnection() - - typealias Config = (url: URL, token: String?, password: String?) - - enum Method: String, Sendable { - case agent - case status - case setHeartbeats = "set-heartbeats" - case systemEvent = "system-event" - case health - case channelsStatus = "channels.status" - case configGet = "config.get" - case configSet = "config.set" - case configPatch = "config.patch" - case configSchema = "config.schema" - case wizardStart = "wizard.start" - case wizardNext = "wizard.next" - case wizardCancel = "wizard.cancel" - case wizardStatus = "wizard.status" - case talkConfig = "talk.config" - case talkMode = "talk.mode" - case webLoginStart = "web.login.start" - case webLoginWait = "web.login.wait" - case channelsLogout = "channels.logout" - case modelsList = "models.list" - case chatHistory = "chat.history" - case sessionsPreview = "sessions.preview" - case chatSend = "chat.send" - case chatAbort = "chat.abort" - case skillsStatus = "skills.status" - case skillsInstall = "skills.install" - case skillsUpdate = "skills.update" - case voicewakeGet = "voicewake.get" - case voicewakeSet = "voicewake.set" - case nodePairApprove = "node.pair.approve" - case nodePairReject = "node.pair.reject" - case devicePairList = "device.pair.list" - case devicePairApprove = "device.pair.approve" - case devicePairReject = "device.pair.reject" - case execApprovalResolve = "exec.approval.resolve" - case cronList = "cron.list" - case cronRuns = "cron.runs" - case cronRun = "cron.run" - case cronRemove = "cron.remove" - case cronUpdate = "cron.update" - case cronAdd = "cron.add" - case cronStatus = "cron.status" - } - - private let configProvider: @Sendable () async throws -> Config - private let sessionBox: WebSocketSessionBox? - private let decoder = JSONDecoder() - - private var client: GatewayChannelActor? - private var configuredURL: URL? - private var configuredToken: String? - private var configuredPassword: String? - - private var subscribers: [UUID: AsyncStream.Continuation] = [:] - private var lastSnapshot: HelloOk? - - init( - configProvider: @escaping @Sendable () async throws -> Config = GatewayConnection.defaultConfigProvider, - sessionBox: WebSocketSessionBox? = nil) - { - self.configProvider = configProvider - self.sessionBox = sessionBox - } - - // MARK: - Low-level request - - func request( - method: String, - params: [String: AnyCodable]?, - timeoutMs: Double? = nil) async throws -> Data - { - let cfg = try await self.configProvider() - await self.configure(url: cfg.url, token: cfg.token, password: cfg.password) - guard let client else { - throw NSError(domain: "Gateway", code: 0, userInfo: [NSLocalizedDescriptionKey: "gateway not configured"]) - } - - do { - return try await client.request(method: method, params: params, timeoutMs: timeoutMs) - } catch { - if error is GatewayResponseError || error is GatewayDecodingError { - throw error - } - - // Auto-recover in local mode by spawning/attaching a gateway and retrying a few times. - // Canvas interactions should "just work" even if the local gateway isn't running yet. - let mode = await MainActor.run { AppStateStore.shared.connectionMode } - switch mode { - case .local: - await MainActor.run { GatewayProcessManager.shared.setActive(true) } - - var lastError: Error = error - for delayMs in [150, 400, 900] { - try await Task.sleep(nanoseconds: UInt64(delayMs) * 1_000_000) - do { - return try await client.request(method: method, params: params, timeoutMs: timeoutMs) - } catch { - lastError = error - } - } - - let nsError = lastError as NSError - if nsError.domain == URLError.errorDomain, - let fallback = await GatewayEndpointStore.shared.maybeFallbackToTailnet(from: cfg.url) - { - await self.configure(url: fallback.url, token: fallback.token, password: fallback.password) - for delayMs in [150, 400, 900] { - try await Task.sleep(nanoseconds: UInt64(delayMs) * 1_000_000) - do { - guard let client = self.client else { - throw NSError( - domain: "Gateway", - code: 0, - userInfo: [NSLocalizedDescriptionKey: "gateway not configured"]) - } - return try await client.request(method: method, params: params, timeoutMs: timeoutMs) - } catch { - lastError = error - } - } - } - - throw lastError - case .remote: - let nsError = error as NSError - guard nsError.domain == URLError.errorDomain else { throw error } - - var lastError: Error = error - await RemoteTunnelManager.shared.stopAll() - do { - _ = try await GatewayEndpointStore.shared.ensureRemoteControlTunnel() - } catch { - lastError = error - } - - for delayMs in [150, 400, 900] { - try await Task.sleep(nanoseconds: UInt64(delayMs) * 1_000_000) - do { - let cfg = try await self.configProvider() - await self.configure(url: cfg.url, token: cfg.token, password: cfg.password) - guard let client = self.client else { - throw NSError( - domain: "Gateway", - code: 0, - userInfo: [NSLocalizedDescriptionKey: "gateway not configured"]) - } - return try await client.request(method: method, params: params, timeoutMs: timeoutMs) - } catch { - lastError = error - } - } - - throw lastError - case .unconfigured: - throw error - } - } - } - - func requestRaw( - method: Method, - params: [String: AnyCodable]? = nil, - timeoutMs: Double? = nil) async throws -> Data - { - try await self.request(method: method.rawValue, params: params, timeoutMs: timeoutMs) - } - - func requestRaw( - method: String, - params: [String: AnyCodable]? = nil, - timeoutMs: Double? = nil) async throws -> Data - { - try await self.request(method: method, params: params, timeoutMs: timeoutMs) - } - - func requestDecoded( - method: Method, - params: [String: AnyCodable]? = nil, - timeoutMs: Double? = nil) async throws -> T - { - let data = try await self.requestRaw(method: method, params: params, timeoutMs: timeoutMs) - do { - return try self.decoder.decode(T.self, from: data) - } catch { - throw GatewayDecodingError(method: method.rawValue, message: error.localizedDescription) - } - } - - func requestVoid( - method: Method, - params: [String: AnyCodable]? = nil, - timeoutMs: Double? = nil) async throws - { - _ = try await self.requestRaw(method: method, params: params, timeoutMs: timeoutMs) - } - - /// Ensure the underlying socket is configured (and replaced if config changed). - func refresh() async throws { - let cfg = try await self.configProvider() - await self.configure(url: cfg.url, token: cfg.token, password: cfg.password) - } - - func authSource() async -> GatewayAuthSource? { - guard let client else { return nil } - return await client.authSource() - } - - func shutdown() async { - if let client { - await client.shutdown() - } - self.client = nil - self.configuredURL = nil - self.configuredToken = nil - self.lastSnapshot = nil - } - - func canvasHostUrl() async -> String? { - guard let snapshot = self.lastSnapshot else { return nil } - let trimmed = snapshot.canvashosturl?.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) ?? "" - return trimmed.isEmpty ? nil : trimmed - } - - private func sessionDefaultString(_ defaults: [String: OpenClawProtocol.AnyCodable]?, key: String) -> String { - let raw = defaults?[key]?.value as? String - return (raw ?? "").trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - } - - func cachedMainSessionKey() -> String? { - guard let snapshot = self.lastSnapshot else { return nil } - let trimmed = self.sessionDefaultString(snapshot.snapshot.sessiondefaults, key: "mainSessionKey") - return trimmed.isEmpty ? nil : trimmed - } - - func cachedGatewayVersion() -> String? { - guard let snapshot = self.lastSnapshot else { return nil } - let raw = snapshot.server["version"]?.value as? String - let trimmed = raw?.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) ?? "" - return trimmed.isEmpty ? nil : trimmed - } - - func snapshotPaths() -> (configPath: String?, stateDir: String?) { - guard let snapshot = self.lastSnapshot else { return (nil, nil) } - let configPath = snapshot.snapshot.configpath?.trimmingCharacters(in: .whitespacesAndNewlines) - let stateDir = snapshot.snapshot.statedir?.trimmingCharacters(in: .whitespacesAndNewlines) - return ( - configPath?.isEmpty == false ? configPath : nil, - stateDir?.isEmpty == false ? stateDir : nil) - } - - func subscribe(bufferingNewest: Int = 100) -> AsyncStream { - let id = UUID() - let snapshot = self.lastSnapshot - let connection = self - return AsyncStream(bufferingPolicy: .bufferingNewest(bufferingNewest)) { continuation in - if let snapshot { - continuation.yield(.snapshot(snapshot)) - } - self.subscribers[id] = continuation - continuation.onTermination = { @Sendable _ in - Task { await connection.removeSubscriber(id) } - } - } - } - - private func removeSubscriber(_ id: UUID) { - self.subscribers[id] = nil - } - - private func broadcast(_ push: GatewayPush) { - if case let .snapshot(snapshot) = push { - self.lastSnapshot = snapshot - if let mainSessionKey = self.cachedMainSessionKey() { - Task { @MainActor in - WorkActivityStore.shared.setMainSessionKey(mainSessionKey) - } - } - } - for (_, continuation) in self.subscribers { - continuation.yield(push) - } - } - - private func canonicalizeSessionKey(_ raw: String) -> String { - let trimmed = raw.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - guard !trimmed.isEmpty else { return trimmed } - guard let defaults = self.lastSnapshot?.snapshot.sessiondefaults else { return trimmed } - let mainSessionKey = self.sessionDefaultString(defaults, key: "mainSessionKey") - guard !mainSessionKey.isEmpty else { return trimmed } - let mainKey = self.sessionDefaultString(defaults, key: "mainKey") - let defaultAgentId = self.sessionDefaultString(defaults, key: "defaultAgentId") - let isMainAlias = - trimmed == "main" || - (!mainKey.isEmpty && trimmed == mainKey) || - trimmed == mainSessionKey || - (!defaultAgentId.isEmpty && - (trimmed == "agent:\(defaultAgentId):main" || - (mainKey.isEmpty == false && trimmed == "agent:\(defaultAgentId):\(mainKey)"))) - return isMainAlias ? mainSessionKey : trimmed - } - - private func configure(url: URL, token: String?, password: String?) async { - if self.client != nil, self.configuredURL == url, self.configuredToken == token, - self.configuredPassword == password - { - return - } - if let client { - await client.shutdown() - } - self.lastSnapshot = nil - self.client = GatewayChannelActor( - url: url, - token: token, - password: password, - session: self.sessionBox, - pushHandler: { [weak self] push in - await self?.handle(push: push) - }) - self.configuredURL = url - self.configuredToken = token - self.configuredPassword = password - } - - private func handle(push: GatewayPush) { - self.broadcast(push) - } - - private static func defaultConfigProvider() async throws -> Config { - try await GatewayEndpointStore.shared.requireConfig() - } -} - -// MARK: - Typed gateway API - -extension GatewayConnection { - struct ConfigGetSnapshot: Decodable, Sendable { - struct SnapshotConfig: Decodable, Sendable { - struct Session: Decodable, Sendable { - let mainKey: String? - let scope: String? - } - - let session: Session? - } - - let config: SnapshotConfig? - } - - static func mainSessionKey(fromConfigGetData data: Data) throws -> String { - let snapshot = try JSONDecoder().decode(ConfigGetSnapshot.self, from: data) - let scope = snapshot.config?.session?.scope?.trimmingCharacters(in: .whitespacesAndNewlines) - if scope == "global" { - return "global" - } - return "main" - } - - func mainSessionKey(timeoutMs: Double = 15000) async -> String { - if let cached = self.cachedMainSessionKey() { - return cached - } - do { - let data = try await self.requestRaw(method: "config.get", params: nil, timeoutMs: timeoutMs) - return try Self.mainSessionKey(fromConfigGetData: data) - } catch { - return "main" - } - } - - func status() async -> (ok: Bool, error: String?) { - do { - _ = try await self.requestRaw(method: .status) - return (true, nil) - } catch { - return (false, error.localizedDescription) - } - } - - func setHeartbeatsEnabled(_ enabled: Bool) async -> Bool { - do { - try await self.requestVoid(method: .setHeartbeats, params: ["enabled": AnyCodable(enabled)]) - return true - } catch { - gatewayConnectionLogger.error("setHeartbeatsEnabled failed \(error.localizedDescription, privacy: .public)") - return false - } - } - - func sendAgent(_ invocation: GatewayAgentInvocation) async -> (ok: Bool, error: String?) { - let trimmed = invocation.message.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return (false, "message empty") } - let sessionKey = self.canonicalizeSessionKey(invocation.sessionKey) - - var params: [String: AnyCodable] = [ - "message": AnyCodable(trimmed), - "sessionKey": AnyCodable(sessionKey), - "thinking": AnyCodable(invocation.thinking ?? "default"), - "deliver": AnyCodable(invocation.deliver), - "to": AnyCodable(invocation.to ?? ""), - "channel": AnyCodable(invocation.channel.rawValue), - "idempotencyKey": AnyCodable(invocation.idempotencyKey), - ] - if let timeout = invocation.timeoutSeconds { - params["timeout"] = AnyCodable(timeout) - } - - do { - try await self.requestVoid(method: .agent, params: params) - return (true, nil) - } catch { - return (false, error.localizedDescription) - } - } - - func sendAgent( - message: String, - thinking: String?, - sessionKey: String, - deliver: Bool, - to: String?, - channel: GatewayAgentChannel = .last, - timeoutSeconds: Int? = nil, - idempotencyKey: String = UUID().uuidString) async -> (ok: Bool, error: String?) - { - await self.sendAgent(GatewayAgentInvocation( - message: message, - sessionKey: sessionKey, - thinking: thinking, - deliver: deliver, - to: to, - channel: channel, - timeoutSeconds: timeoutSeconds, - idempotencyKey: idempotencyKey)) - } - - func sendSystemEvent(_ params: [String: AnyCodable]) async { - do { - try await self.requestVoid(method: .systemEvent, params: params) - } catch { - // Best-effort only. - } - } - - // MARK: - Health - - func healthSnapshot(timeoutMs: Double? = nil) async throws -> HealthSnapshot { - let data = try await self.requestRaw(method: .health, timeoutMs: timeoutMs) - if let snap = decodeHealthSnapshot(from: data) { return snap } - throw GatewayDecodingError(method: Method.health.rawValue, message: "failed to decode health snapshot") - } - - func healthOK(timeoutMs: Int = 8000) async throws -> Bool { - let data = try await self.requestRaw(method: .health, timeoutMs: Double(timeoutMs)) - return (try? self.decoder.decode(OpenClawGatewayHealthOK.self, from: data))?.ok ?? true - } - - // MARK: - Skills - - func skillsStatus() async throws -> SkillsStatusReport { - try await self.requestDecoded(method: .skillsStatus) - } - - func skillsInstall( - name: String, - installId: String, - timeoutMs: Int? = nil) async throws -> SkillInstallResult - { - var params: [String: AnyCodable] = [ - "name": AnyCodable(name), - "installId": AnyCodable(installId), - ] - if let timeoutMs { - params["timeoutMs"] = AnyCodable(timeoutMs) - } - return try await self.requestDecoded(method: .skillsInstall, params: params) - } - - func skillsUpdate( - skillKey: String, - enabled: Bool? = nil, - apiKey: String? = nil, - env: [String: String]? = nil) async throws -> SkillUpdateResult - { - var params: [String: AnyCodable] = [ - "skillKey": AnyCodable(skillKey), - ] - if let enabled { params["enabled"] = AnyCodable(enabled) } - if let apiKey { params["apiKey"] = AnyCodable(apiKey) } - if let env, !env.isEmpty { params["env"] = AnyCodable(env) } - return try await self.requestDecoded(method: .skillsUpdate, params: params) - } - - // MARK: - Sessions - - func sessionsPreview( - keys: [String], - limit: Int? = nil, - maxChars: Int? = nil, - timeoutMs: Int? = nil) async throws -> OpenClawSessionsPreviewPayload - { - let resolvedKeys = keys - .map { self.canonicalizeSessionKey($0) } - .filter { !$0.isEmpty } - if resolvedKeys.isEmpty { - return OpenClawSessionsPreviewPayload(ts: 0, previews: []) - } - var params: [String: AnyCodable] = ["keys": AnyCodable(resolvedKeys)] - if let limit { params["limit"] = AnyCodable(limit) } - if let maxChars { params["maxChars"] = AnyCodable(maxChars) } - let timeout = timeoutMs.map { Double($0) } - return try await self.requestDecoded( - method: .sessionsPreview, - params: params, - timeoutMs: timeout) - } - - // MARK: - Chat - - func chatHistory( - sessionKey: String, - limit: Int? = nil, - timeoutMs: Int? = nil) async throws -> OpenClawChatHistoryPayload - { - let resolvedKey = self.canonicalizeSessionKey(sessionKey) - var params: [String: AnyCodable] = ["sessionKey": AnyCodable(resolvedKey)] - if let limit { params["limit"] = AnyCodable(limit) } - let timeout = timeoutMs.map { Double($0) } - return try await self.requestDecoded( - method: .chatHistory, - params: params, - timeoutMs: timeout) - } - - func chatSend( - sessionKey: String, - message: String, - thinking: String, - idempotencyKey: String, - attachments: [OpenClawChatAttachmentPayload], - timeoutMs: Int = 30000) async throws -> OpenClawChatSendResponse - { - let resolvedKey = self.canonicalizeSessionKey(sessionKey) - var params: [String: AnyCodable] = [ - "sessionKey": AnyCodable(resolvedKey), - "message": AnyCodable(message), - "thinking": AnyCodable(thinking), - "idempotencyKey": AnyCodable(idempotencyKey), - "timeoutMs": AnyCodable(timeoutMs), - ] - - if !attachments.isEmpty { - let encoded = attachments.map { att in - [ - "type": att.type, - "mimeType": att.mimeType, - "fileName": att.fileName, - "content": att.content, - ] - } - params["attachments"] = AnyCodable(encoded) - } - - return try await self.requestDecoded( - method: .chatSend, - params: params, - timeoutMs: Double(timeoutMs)) - } - - func chatAbort(sessionKey: String, runId: String) async throws -> Bool { - let resolvedKey = self.canonicalizeSessionKey(sessionKey) - struct AbortResponse: Decodable { let ok: Bool?; let aborted: Bool? } - let res: AbortResponse = try await self.requestDecoded( - method: .chatAbort, - params: ["sessionKey": AnyCodable(resolvedKey), "runId": AnyCodable(runId)]) - return res.aborted ?? false - } - - func talkMode(enabled: Bool, phase: String? = nil) async { - var params: [String: AnyCodable] = ["enabled": AnyCodable(enabled)] - if let phase { params["phase"] = AnyCodable(phase) } - try? await self.requestVoid(method: .talkMode, params: params) - } - - // MARK: - VoiceWake - - func voiceWakeGetTriggers() async throws -> [String] { - struct VoiceWakePayload: Decodable { let triggers: [String] } - let payload: VoiceWakePayload = try await self.requestDecoded(method: .voicewakeGet) - return payload.triggers - } - - func voiceWakeSetTriggers(_ triggers: [String]) async { - do { - try await self.requestVoid( - method: .voicewakeSet, - params: ["triggers": AnyCodable(triggers)], - timeoutMs: 10000) - } catch { - // Best-effort only. - } - } - - // MARK: - Node pairing - - func nodePairApprove(requestId: String) async throws { - try await self.requestVoid( - method: .nodePairApprove, - params: ["requestId": AnyCodable(requestId)], - timeoutMs: 10000) - } - - func nodePairReject(requestId: String) async throws { - try await self.requestVoid( - method: .nodePairReject, - params: ["requestId": AnyCodable(requestId)], - timeoutMs: 10000) - } - - // MARK: - Device pairing - - func devicePairApprove(requestId: String) async throws { - try await self.requestVoid( - method: .devicePairApprove, - params: ["requestId": AnyCodable(requestId)], - timeoutMs: 10000) - } - - func devicePairReject(requestId: String) async throws { - try await self.requestVoid( - method: .devicePairReject, - params: ["requestId": AnyCodable(requestId)], - timeoutMs: 10000) - } - - // MARK: - Cron - - struct CronSchedulerStatus: Decodable, Sendable { - let enabled: Bool - let storePath: String - let jobs: Int - let nextWakeAtMs: Int? - } - - func cronStatus() async throws -> CronSchedulerStatus { - try await self.requestDecoded(method: .cronStatus) - } - - func cronList(includeDisabled: Bool = true) async throws -> [CronJob] { - let res: CronListResponse = try await self.requestDecoded( - method: .cronList, - params: ["includeDisabled": AnyCodable(includeDisabled)]) - return res.jobs - } - - func cronRuns(jobId: String, limit: Int = 200) async throws -> [CronRunLogEntry] { - let res: CronRunsResponse = try await self.requestDecoded( - method: .cronRuns, - params: ["id": AnyCodable(jobId), "limit": AnyCodable(limit)]) - return res.entries - } - - func cronRun(jobId: String, force: Bool = true) async throws { - try await self.requestVoid( - method: .cronRun, - params: [ - "id": AnyCodable(jobId), - "mode": AnyCodable(force ? "force" : "due"), - ], - timeoutMs: 20000) - } - - func cronRemove(jobId: String) async throws { - try await self.requestVoid(method: .cronRemove, params: ["id": AnyCodable(jobId)]) - } - - func cronUpdate(jobId: String, patch: [String: AnyCodable]) async throws { - try await self.requestVoid( - method: .cronUpdate, - params: ["id": AnyCodable(jobId), "patch": AnyCodable(patch)]) - } - - func cronAdd(payload: [String: AnyCodable]) async throws { - try await self.requestVoid(method: .cronAdd, params: payload) - } -} diff --git a/apps/macos/Sources/OpenClaw/GatewayConnectivityCoordinator.swift b/apps/macos/Sources/OpenClaw/GatewayConnectivityCoordinator.swift deleted file mode 100644 index aeb1ebb9af0..00000000000 --- a/apps/macos/Sources/OpenClaw/GatewayConnectivityCoordinator.swift +++ /dev/null @@ -1,63 +0,0 @@ -import Foundation -import Observation -import OSLog - -@MainActor -@Observable -final class GatewayConnectivityCoordinator { - static let shared = GatewayConnectivityCoordinator() - - private let logger = Logger(subsystem: "ai.openclaw", category: "gateway.connectivity") - private var endpointTask: Task? - private var lastResolvedURL: URL? - - private(set) var endpointState: GatewayEndpointState? - private(set) var resolvedURL: URL? - private(set) var resolvedMode: AppState.ConnectionMode? - private(set) var resolvedHostLabel: String? - - private init() { - self.start() - } - - func start() { - guard self.endpointTask == nil else { return } - self.endpointTask = Task { [weak self] in - guard let self else { return } - let stream = await GatewayEndpointStore.shared.subscribe() - for await state in stream { - await MainActor.run { self.handleEndpointState(state) } - } - } - } - - var localEndpointHostLabel: String? { - guard self.resolvedMode == .local, let url = self.resolvedURL else { return nil } - return Self.hostLabel(for: url) - } - - private func handleEndpointState(_ state: GatewayEndpointState) { - self.endpointState = state - switch state { - case let .ready(mode, url, _, _): - self.resolvedMode = mode - self.resolvedURL = url - self.resolvedHostLabel = Self.hostLabel(for: url) - let urlChanged = self.lastResolvedURL?.absoluteString != url.absoluteString - if urlChanged { - self.lastResolvedURL = url - Task { await ControlChannel.shared.refreshEndpoint(reason: "endpoint changed") } - } - case let .connecting(mode, _): - self.resolvedMode = mode - case let .unavailable(mode, _): - self.resolvedMode = mode - } - } - - private static func hostLabel(for url: URL) -> String { - let host = url.host ?? url.absoluteString - if let port = url.port { return "\(host):\(port)" } - return host - } -} diff --git a/apps/macos/Sources/OpenClaw/GatewayDiscoveryHelpers.swift b/apps/macos/Sources/OpenClaw/GatewayDiscoveryHelpers.swift deleted file mode 100644 index 81383efa21a..00000000000 --- a/apps/macos/Sources/OpenClaw/GatewayDiscoveryHelpers.swift +++ /dev/null @@ -1,77 +0,0 @@ -import Foundation -import OpenClawDiscovery - -enum GatewayDiscoveryHelpers { - static func resolvedServiceHost( - for gateway: GatewayDiscoveryModel.DiscoveredGateway) -> String? - { - self.resolvedServiceHost(gateway.serviceHost) - } - - static func resolvedServiceHost(_ host: String?) -> String? { - guard let host = self.trimmed(host), !host.isEmpty else { return nil } - return host - } - - static func serviceEndpoint( - for gateway: GatewayDiscoveryModel.DiscoveredGateway) -> (host: String, port: Int)? - { - self.serviceEndpoint(serviceHost: gateway.serviceHost, servicePort: gateway.servicePort) - } - - static func serviceEndpoint( - serviceHost: String?, - servicePort: Int?) -> (host: String, port: Int)? - { - guard let host = self.resolvedServiceHost(serviceHost) else { return nil } - guard let port = servicePort, port > 0, port <= 65535 else { return nil } - return (host, port) - } - - static func sshTarget(for gateway: GatewayDiscoveryModel.DiscoveredGateway) -> String? { - guard let host = self.resolvedServiceHost(for: gateway) else { return nil } - let user = NSUserName() - var target = "\(user)@\(host)" - if gateway.sshPort != 22 { - target += ":\(gateway.sshPort)" - } - return target - } - - static func directUrl(for gateway: GatewayDiscoveryModel.DiscoveredGateway) -> String? { - self.directGatewayUrl( - serviceHost: gateway.serviceHost, - servicePort: gateway.servicePort) - } - - static func directGatewayUrl( - serviceHost: String?, - servicePort: Int?) -> String? - { - // Security: do not route using unauthenticated TXT hints (tailnetDns/lanHost/gatewayPort). - // Prefer the resolved service endpoint (SRV + A/AAAA). - guard let endpoint = self.serviceEndpoint(serviceHost: serviceHost, servicePort: servicePort) else { - return nil - } - // Security: for non-loopback hosts, force TLS to avoid plaintext credential/session leakage. - let scheme = self.isLoopbackHost(endpoint.host) ? "ws" : "wss" - let portSuffix = endpoint.port == 443 ? "" : ":\(endpoint.port)" - return "\(scheme)://\(endpoint.host)\(portSuffix)" - } - - private static func trimmed(_ value: String?) -> String? { - value?.trimmingCharacters(in: .whitespacesAndNewlines) - } - - private static func isLoopbackHost(_ rawHost: String) -> Bool { - let host = rawHost.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - guard !host.isEmpty else { return false } - if host == "localhost" || host == "::1" || host == "0:0:0:0:0:0:0:1" { - return true - } - if host.hasPrefix("::ffff:127.") { - return true - } - return host.hasPrefix("127.") - } -} diff --git a/apps/macos/Sources/OpenClaw/GatewayDiscoveryMenu.swift b/apps/macos/Sources/OpenClaw/GatewayDiscoveryMenu.swift deleted file mode 100644 index babab5866fd..00000000000 --- a/apps/macos/Sources/OpenClaw/GatewayDiscoveryMenu.swift +++ /dev/null @@ -1,139 +0,0 @@ -import OpenClawDiscovery -import SwiftUI - -struct GatewayDiscoveryInlineList: View { - var discovery: GatewayDiscoveryModel - var currentTarget: String? - var currentUrl: String? - var transport: AppState.RemoteTransport - var onSelect: (GatewayDiscoveryModel.DiscoveredGateway) -> Void - @State private var hoveredGatewayID: GatewayDiscoveryModel.DiscoveredGateway.ID? - - var body: some View { - VStack(alignment: .leading, spacing: 6) { - HStack(alignment: .firstTextBaseline, spacing: 6) { - Image(systemName: "dot.radiowaves.left.and.right") - .font(.caption) - .foregroundStyle(.secondary) - Text(self.discovery.statusText) - .font(.caption) - .foregroundStyle(.secondary) - } - - if self.discovery.gateways.isEmpty { - Text("No gateways found yet.") - .font(.caption) - .foregroundStyle(.secondary) - } else { - VStack(alignment: .leading, spacing: 6) { - ForEach(self.discovery.gateways.prefix(6)) { gateway in - let display = self.displayInfo(for: gateway) - let selected = display.selected - - Button { - withAnimation(.spring(response: 0.25, dampingFraction: 0.9)) { - self.onSelect(gateway) - } - } label: { - HStack(alignment: .center, spacing: 10) { - VStack(alignment: .leading, spacing: 2) { - Text(gateway.displayName) - .font(.callout.weight(.semibold)) - .lineLimit(1) - .truncationMode(.tail) - Text(display.label) - .font(.caption.monospaced()) - .foregroundStyle(.secondary) - .lineLimit(1) - .truncationMode(.middle) - } - Spacer(minLength: 0) - if selected { - Image(systemName: "checkmark.circle.fill") - .foregroundStyle(Color.accentColor) - } else { - Image(systemName: "arrow.right.circle") - .foregroundStyle(.secondary) - } - } - .padding(.horizontal, 10) - .padding(.vertical, 8) - .frame(maxWidth: .infinity, alignment: .leading) - .background( - RoundedRectangle(cornerRadius: 10, style: .continuous) - .fill(self.rowBackground( - selected: selected, - hovered: self.hoveredGatewayID == gateway.id))) - .overlay( - RoundedRectangle(cornerRadius: 10, style: .continuous) - .strokeBorder( - selected ? Color.accentColor.opacity(0.45) : Color.clear, - lineWidth: 1)) - .contentShape(Rectangle()) - } - .buttonStyle(.plain) - .onHover { hovering in - self.hoveredGatewayID = hovering ? gateway - .id : (self.hoveredGatewayID == gateway.id ? nil : self.hoveredGatewayID) - } - } - } - .padding(10) - .background( - RoundedRectangle(cornerRadius: 10, style: .continuous) - .fill(Color(NSColor.controlBackgroundColor))) - } - } - .help(self.transport == .direct - ? "Click a discovered gateway to fill the gateway URL." - : "Click a discovered gateway to fill the SSH target.") - } - - private func displayInfo( - for gateway: GatewayDiscoveryModel.DiscoveredGateway) -> (label: String, selected: Bool) - { - switch self.transport { - case .direct: - let url = GatewayDiscoveryHelpers.directUrl(for: gateway) - let label = url ?? "Gateway pairing only" - let selected = url != nil && self.trimmed(self.currentUrl) == url - return (label, selected) - case .ssh: - let target = GatewayDiscoveryHelpers.sshTarget(for: gateway) - let label = target ?? "Gateway pairing only" - let selected = target != nil && self.trimmed(self.currentTarget) == target - return (label, selected) - } - } - - private func rowBackground(selected: Bool, hovered: Bool) -> Color { - if selected { return Color.accentColor.opacity(0.12) } - if hovered { return Color.secondary.opacity(0.08) } - return Color.clear - } - - private func trimmed(_ value: String?) -> String { - value?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - } -} - -struct GatewayDiscoveryMenu: View { - var discovery: GatewayDiscoveryModel - var onSelect: (GatewayDiscoveryModel.DiscoveredGateway) -> Void - - var body: some View { - Menu { - if self.discovery.gateways.isEmpty { - Button(self.discovery.statusText) {} - .disabled(true) - } else { - ForEach(self.discovery.gateways) { gateway in - Button(gateway.displayName) { self.onSelect(gateway) } - } - } - } label: { - Image(systemName: "dot.radiowaves.left.and.right") - } - .help("Discover OpenClaw gateways on your LAN") - } -} diff --git a/apps/macos/Sources/OpenClaw/GatewayDiscoveryPreferences.swift b/apps/macos/Sources/OpenClaw/GatewayDiscoveryPreferences.swift deleted file mode 100644 index d725fdba587..00000000000 --- a/apps/macos/Sources/OpenClaw/GatewayDiscoveryPreferences.swift +++ /dev/null @@ -1,25 +0,0 @@ -import Foundation - -enum GatewayDiscoveryPreferences { - private static let preferredStableIDKey = "gateway.preferredStableID" - private static let legacyPreferredStableIDKey = "bridge.preferredStableID" - - static func preferredStableID() -> String? { - let defaults = UserDefaults.standard - let raw = defaults.string(forKey: self.preferredStableIDKey) - ?? defaults.string(forKey: self.legacyPreferredStableIDKey) - let trimmed = raw?.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed?.isEmpty == false ? trimmed : nil - } - - static func setPreferredStableID(_ stableID: String?) { - let trimmed = stableID?.trimmingCharacters(in: .whitespacesAndNewlines) - if let trimmed, !trimmed.isEmpty { - UserDefaults.standard.set(trimmed, forKey: self.preferredStableIDKey) - UserDefaults.standard.removeObject(forKey: self.legacyPreferredStableIDKey) - } else { - UserDefaults.standard.removeObject(forKey: self.preferredStableIDKey) - UserDefaults.standard.removeObject(forKey: self.legacyPreferredStableIDKey) - } - } -} diff --git a/apps/macos/Sources/OpenClaw/GatewayEndpointStore.swift b/apps/macos/Sources/OpenClaw/GatewayEndpointStore.swift deleted file mode 100644 index 0edb2e65122..00000000000 --- a/apps/macos/Sources/OpenClaw/GatewayEndpointStore.swift +++ /dev/null @@ -1,728 +0,0 @@ -import ConcurrencyExtras -import Foundation -import OSLog - -enum GatewayEndpointState: Sendable, Equatable { - case ready(mode: AppState.ConnectionMode, url: URL, token: String?, password: String?) - case connecting(mode: AppState.ConnectionMode, detail: String) - case unavailable(mode: AppState.ConnectionMode, reason: String) -} - -/// Single place to resolve (and publish) the effective gateway control endpoint. -/// -/// This is intentionally separate from `GatewayConnection`: -/// - `GatewayConnection` consumes the resolved endpoint (no tunnel side-effects). -/// - The endpoint store owns observation + explicit "ensure tunnel" actions. -actor GatewayEndpointStore { - static let shared = GatewayEndpointStore() - private static let supportedBindModes: Set = [ - "loopback", - "tailnet", - "lan", - "auto", - "custom", - ] - private static let remoteConnectingDetail = "Connecting to remote gateway…" - private static let staticLogger = Logger(subsystem: "ai.openclaw", category: "gateway-endpoint") - private enum EnvOverrideWarningKind: Sendable { - case token - case password - } - - private static let envOverrideWarnings = LockIsolated((token: false, password: false)) - - struct Deps: Sendable { - let mode: @Sendable () async -> AppState.ConnectionMode - let token: @Sendable () -> String? - let password: @Sendable () -> String? - let localPort: @Sendable () -> Int - let localHost: @Sendable () async -> String - let remotePortIfRunning: @Sendable () async -> UInt16? - let ensureRemoteTunnel: @Sendable () async throws -> UInt16 - - static let live = Deps( - mode: { await MainActor.run { AppStateStore.shared.connectionMode } }, - token: { - let root = OpenClawConfigFile.loadDict() - let isRemote = ConnectionModeResolver.resolve(root: root).mode == .remote - return GatewayEndpointStore.resolveGatewayToken( - isRemote: isRemote, - root: root, - env: ProcessInfo.processInfo.environment, - launchdSnapshot: GatewayLaunchAgentManager.launchdConfigSnapshot()) - }, - password: { - let root = OpenClawConfigFile.loadDict() - let isRemote = ConnectionModeResolver.resolve(root: root).mode == .remote - return GatewayEndpointStore.resolveGatewayPassword( - isRemote: isRemote, - root: root, - env: ProcessInfo.processInfo.environment, - launchdSnapshot: GatewayLaunchAgentManager.launchdConfigSnapshot()) - }, - localPort: { GatewayEnvironment.gatewayPort() }, - localHost: { - let root = OpenClawConfigFile.loadDict() - let bind = GatewayEndpointStore.resolveGatewayBindMode( - root: root, - env: ProcessInfo.processInfo.environment) - let customBindHost = GatewayEndpointStore.resolveGatewayCustomBindHost(root: root) - let tailscaleIP = await MainActor.run { TailscaleService.shared.tailscaleIP } - ?? TailscaleService.fallbackTailnetIPv4() - return GatewayEndpointStore.resolveLocalGatewayHost( - bindMode: bind, - customBindHost: customBindHost, - tailscaleIP: tailscaleIP) - }, - remotePortIfRunning: { await RemoteTunnelManager.shared.controlTunnelPortIfRunning() }, - ensureRemoteTunnel: { try await RemoteTunnelManager.shared.ensureControlTunnel() }) - } - - private static func resolveGatewayPassword( - isRemote: Bool, - root: [String: Any], - env: [String: String], - launchdSnapshot: LaunchAgentPlistSnapshot?) -> String? - { - let raw = env["OPENCLAW_GATEWAY_PASSWORD"] ?? "" - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmed.isEmpty { - if let configPassword = self.resolveConfigPassword(isRemote: isRemote, root: root), - !configPassword.isEmpty - { - self.warnEnvOverrideOnce( - kind: .password, - envVar: "OPENCLAW_GATEWAY_PASSWORD", - configKey: isRemote ? "gateway.remote.password" : "gateway.auth.password") - } - return trimmed - } - if isRemote { - if let gateway = root["gateway"] as? [String: Any], - let remote = gateway["remote"] as? [String: Any], - let password = remote["password"] as? String - { - let pw = password.trimmingCharacters(in: .whitespacesAndNewlines) - if !pw.isEmpty { - return pw - } - } - return nil - } - if let gateway = root["gateway"] as? [String: Any], - let auth = gateway["auth"] as? [String: Any], - let password = auth["password"] as? String - { - let pw = password.trimmingCharacters(in: .whitespacesAndNewlines) - if !pw.isEmpty { - return pw - } - } - if let password = launchdSnapshot?.password?.trimmingCharacters(in: .whitespacesAndNewlines), - !password.isEmpty - { - return password - } - return nil - } - - private static func resolveConfigPassword(isRemote: Bool, root: [String: Any]) -> String? { - if isRemote { - if let gateway = root["gateway"] as? [String: Any], - let remote = gateway["remote"] as? [String: Any], - let password = remote["password"] as? String - { - return password.trimmingCharacters(in: .whitespacesAndNewlines) - } - return nil - } - - if let gateway = root["gateway"] as? [String: Any], - let auth = gateway["auth"] as? [String: Any], - let password = auth["password"] as? String - { - return password.trimmingCharacters(in: .whitespacesAndNewlines) - } - return nil - } - - private static func resolveGatewayToken( - isRemote: Bool, - root: [String: Any], - env: [String: String], - launchdSnapshot: LaunchAgentPlistSnapshot?) -> String? - { - let raw = env["OPENCLAW_GATEWAY_TOKEN"] ?? "" - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmed.isEmpty { - if let configToken = self.resolveConfigToken(isRemote: isRemote, root: root), - !configToken.isEmpty, - configToken != trimmed - { - self.warnEnvOverrideOnce( - kind: .token, - envVar: "OPENCLAW_GATEWAY_TOKEN", - configKey: isRemote ? "gateway.remote.token" : "gateway.auth.token") - } - return trimmed - } - - if let configToken = self.resolveConfigToken(isRemote: isRemote, root: root), - !configToken.isEmpty - { - return configToken - } - - if isRemote { - return nil - } - - if let token = launchdSnapshot?.token?.trimmingCharacters(in: .whitespacesAndNewlines), - !token.isEmpty - { - return token - } - - return nil - } - - private static func resolveConfigToken(isRemote: Bool, root: [String: Any]) -> String? { - if isRemote { - if let gateway = root["gateway"] as? [String: Any], - let remote = gateway["remote"] as? [String: Any], - let token = remote["token"] as? String - { - return token.trimmingCharacters(in: .whitespacesAndNewlines) - } - return nil - } - - if let gateway = root["gateway"] as? [String: Any], - let auth = gateway["auth"] as? [String: Any], - let token = auth["token"] as? String - { - return token.trimmingCharacters(in: .whitespacesAndNewlines) - } - return nil - } - - private static func warnEnvOverrideOnce( - kind: EnvOverrideWarningKind, - envVar: String, - configKey: String) - { - let shouldWarn = Self.envOverrideWarnings.withValue { state in - switch kind { - case .token: - guard !state.token else { return false } - state.token = true - return true - case .password: - guard !state.password else { return false } - state.password = true - return true - } - } - guard shouldWarn else { return } - Self.staticLogger.warning( - "\(envVar, privacy: .public) is set and overrides \(configKey, privacy: .public). " + - "If this is unintentional, clear it with: launchctl unsetenv \(envVar, privacy: .public)") - } - - private let deps: Deps - private let logger = Logger(subsystem: "ai.openclaw", category: "gateway-endpoint") - - private var state: GatewayEndpointState - private var subscribers: [UUID: AsyncStream.Continuation] = [:] - private var remoteEnsure: (token: UUID, task: Task)? - - init(deps: Deps = .live) { - self.deps = deps - let modeRaw = UserDefaults.standard.string(forKey: connectionModeKey) - let initialMode: AppState.ConnectionMode - if let modeRaw { - initialMode = AppState.ConnectionMode(rawValue: modeRaw) ?? .local - } else { - let seen = UserDefaults.standard.bool(forKey: "openclaw.onboardingSeen") - initialMode = seen ? .local : .unconfigured - } - - let port = deps.localPort() - let bind = GatewayEndpointStore.resolveGatewayBindMode( - root: OpenClawConfigFile.loadDict(), - env: ProcessInfo.processInfo.environment) - let customBindHost = GatewayEndpointStore.resolveGatewayCustomBindHost(root: OpenClawConfigFile.loadDict()) - let scheme = GatewayEndpointStore.resolveGatewayScheme( - root: OpenClawConfigFile.loadDict(), - env: ProcessInfo.processInfo.environment) - let host = GatewayEndpointStore.resolveLocalGatewayHost( - bindMode: bind, - customBindHost: customBindHost, - tailscaleIP: nil) - let token = deps.token() - let password = deps.password() - switch initialMode { - case .local: - self.state = .ready( - mode: .local, - url: URL(string: "\(scheme)://\(host):\(port)")!, - token: token, - password: password) - case .remote: - self.state = .connecting(mode: .remote, detail: Self.remoteConnectingDetail) - Task { await self.setMode(.remote) } - case .unconfigured: - self.state = .unavailable(mode: .unconfigured, reason: "Gateway not configured") - } - } - - func subscribe(bufferingNewest: Int = 1) -> AsyncStream { - let id = UUID() - let initial = self.state - let store = self - return AsyncStream(bufferingPolicy: .bufferingNewest(bufferingNewest)) { continuation in - continuation.yield(initial) - self.subscribers[id] = continuation - continuation.onTermination = { @Sendable _ in - Task { await store.removeSubscriber(id) } - } - } - } - - func refresh() async { - let mode = await self.deps.mode() - await self.setMode(mode) - } - - func setMode(_ mode: AppState.ConnectionMode) async { - let token = self.deps.token() - let password = self.deps.password() - switch mode { - case .local: - self.cancelRemoteEnsure() - let port = self.deps.localPort() - let host = await self.deps.localHost() - let scheme = GatewayEndpointStore.resolveGatewayScheme( - root: OpenClawConfigFile.loadDict(), - env: ProcessInfo.processInfo.environment) - self.setState(.ready( - mode: .local, - url: URL(string: "\(scheme)://\(host):\(port)")!, - token: token, - password: password)) - case .remote: - let root = OpenClawConfigFile.loadDict() - if GatewayRemoteConfig.resolveTransport(root: root) == .direct { - guard let url = GatewayRemoteConfig.resolveGatewayUrl(root: root) else { - self.cancelRemoteEnsure() - self.setState(.unavailable( - mode: .remote, - reason: "gateway.remote.url missing or invalid for direct transport")) - return - } - self.cancelRemoteEnsure() - self.setState(.ready(mode: .remote, url: url, token: token, password: password)) - return - } - let port = await self.deps.remotePortIfRunning() - guard let port else { - self.setState(.connecting(mode: .remote, detail: Self.remoteConnectingDetail)) - self.kickRemoteEnsureIfNeeded(detail: Self.remoteConnectingDetail) - return - } - self.cancelRemoteEnsure() - let scheme = GatewayEndpointStore.resolveGatewayScheme( - root: OpenClawConfigFile.loadDict(), - env: ProcessInfo.processInfo.environment) - self.setState(.ready( - mode: .remote, - url: URL(string: "\(scheme)://127.0.0.1:\(Int(port))")!, - token: token, - password: password)) - case .unconfigured: - self.cancelRemoteEnsure() - self.setState(.unavailable(mode: .unconfigured, reason: "Gateway not configured")) - } - } - - /// Explicit action: ensure the remote control tunnel is established and publish the resolved endpoint. - func ensureRemoteControlTunnel() async throws -> UInt16 { - let mode = await self.deps.mode() - guard mode == .remote else { - throw NSError( - domain: "RemoteTunnel", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "Remote mode is not enabled"]) - } - let root = OpenClawConfigFile.loadDict() - if GatewayRemoteConfig.resolveTransport(root: root) == .direct { - guard let url = GatewayRemoteConfig.resolveGatewayUrl(root: root) else { - throw NSError( - domain: "GatewayEndpoint", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "gateway.remote.url missing or invalid"]) - } - guard let port = GatewayRemoteConfig.defaultPort(for: url), - let portInt = UInt16(exactly: port) - else { - throw NSError( - domain: "GatewayEndpoint", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "Invalid gateway.remote.url port"]) - } - self.logger.info("remote transport direct; skipping SSH tunnel") - return portInt - } - let config = try await self.ensureRemoteConfig(detail: Self.remoteConnectingDetail) - guard let portInt = config.0.port, let port = UInt16(exactly: portInt) else { - throw NSError( - domain: "GatewayEndpoint", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "Missing tunnel port"]) - } - return port - } - - func requireConfig() async throws -> GatewayConnection.Config { - await self.refresh() - switch self.state { - case let .ready(_, url, token, password): - return (url, token, password) - case let .connecting(mode, _): - guard mode == .remote else { - throw NSError(domain: "GatewayEndpoint", code: 1, userInfo: [NSLocalizedDescriptionKey: "Connecting…"]) - } - return try await self.ensureRemoteConfig(detail: Self.remoteConnectingDetail) - case let .unavailable(mode, reason): - guard mode == .remote else { - throw NSError(domain: "GatewayEndpoint", code: 1, userInfo: [NSLocalizedDescriptionKey: reason]) - } - - // Auto-recover for remote mode: if the SSH control tunnel died (or hasn't been created yet), - // recreate it on demand so callers can recover without a manual reconnect. - self.logger.info( - "endpoint unavailable; ensuring remote control tunnel reason=\(reason, privacy: .public)") - return try await self.ensureRemoteConfig(detail: Self.remoteConnectingDetail) - } - } - - private func cancelRemoteEnsure() { - self.remoteEnsure?.task.cancel() - self.remoteEnsure = nil - } - - private func kickRemoteEnsureIfNeeded(detail: String) { - if self.remoteEnsure != nil { - self.setState(.connecting(mode: .remote, detail: detail)) - return - } - - let deps = self.deps - let token = UUID() - let task = Task.detached(priority: .utility) { try await deps.ensureRemoteTunnel() } - self.remoteEnsure = (token: token, task: task) - self.setState(.connecting(mode: .remote, detail: detail)) - } - - private func ensureRemoteConfig(detail: String) async throws -> GatewayConnection.Config { - let mode = await self.deps.mode() - guard mode == .remote else { - throw NSError( - domain: "RemoteTunnel", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "Remote mode is not enabled"]) - } - - let root = OpenClawConfigFile.loadDict() - if GatewayRemoteConfig.resolveTransport(root: root) == .direct { - guard let url = GatewayRemoteConfig.resolveGatewayUrl(root: root) else { - throw NSError( - domain: "GatewayEndpoint", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "gateway.remote.url missing or invalid"]) - } - let token = self.deps.token() - let password = self.deps.password() - self.cancelRemoteEnsure() - self.setState(.ready(mode: .remote, url: url, token: token, password: password)) - return (url, token, password) - } - - self.kickRemoteEnsureIfNeeded(detail: detail) - guard let ensure = self.remoteEnsure else { - throw NSError(domain: "GatewayEndpoint", code: 1, userInfo: [NSLocalizedDescriptionKey: "Connecting…"]) - } - - do { - let forwarded = try await ensure.task.value - let stillRemote = await self.deps.mode() == .remote - guard stillRemote else { - throw NSError( - domain: "RemoteTunnel", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "Remote mode is not enabled"]) - } - - if self.remoteEnsure?.token == ensure.token { - self.remoteEnsure = nil - } - - let token = self.deps.token() - let password = self.deps.password() - let scheme = GatewayEndpointStore.resolveGatewayScheme( - root: OpenClawConfigFile.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)) - return (url, token, password) - } catch let err as CancellationError { - if self.remoteEnsure?.token == ensure.token { - self.remoteEnsure = nil - } - throw err - } catch { - if self.remoteEnsure?.token == ensure.token { - self.remoteEnsure = nil - } - let msg = "Remote control tunnel failed (\(error.localizedDescription))" - self.setState(.unavailable(mode: .remote, reason: msg)) - self.logger.error("remote control tunnel ensure failed \(msg, privacy: .public)") - throw NSError(domain: "GatewayEndpoint", code: 1, userInfo: [NSLocalizedDescriptionKey: msg]) - } - } - - private func removeSubscriber(_ id: UUID) { - self.subscribers[id] = nil - } - - private func setState(_ next: GatewayEndpointState) { - guard next != self.state else { return } - self.state = next - for (_, continuation) in self.subscribers { - continuation.yield(next) - } - switch next { - case let .ready(mode, url, _, _): - let modeDesc = String(describing: mode) - let urlDesc = url.absoluteString - self.logger - .debug( - "resolved endpoint mode=\(modeDesc, privacy: .public) url=\(urlDesc, privacy: .public)") - case let .connecting(mode, detail): - let modeDesc = String(describing: mode) - self.logger - .debug( - "endpoint connecting mode=\(modeDesc, privacy: .public) detail=\(detail, privacy: .public)") - case let .unavailable(mode, reason): - let modeDesc = String(describing: mode) - self.logger - .debug( - "endpoint unavailable mode=\(modeDesc, privacy: .public) reason=\(reason, privacy: .public)") - } - } - - func maybeFallbackToTailnet(from currentURL: URL) async -> GatewayConnection.Config? { - let mode = await self.deps.mode() - guard mode == .local else { return nil } - - let root = OpenClawConfigFile.loadDict() - let bind = GatewayEndpointStore.resolveGatewayBindMode( - root: root, - env: ProcessInfo.processInfo.environment) - guard bind == "tailnet" else { return nil } - - let currentHost = currentURL.host?.lowercased() ?? "" - guard currentHost == "127.0.0.1" || currentHost == "localhost" else { return nil } - - let tailscaleIP = await MainActor.run { TailscaleService.shared.tailscaleIP } - ?? TailscaleService.fallbackTailnetIPv4() - guard let tailscaleIP, !tailscaleIP.isEmpty else { return nil } - - let scheme = GatewayEndpointStore.resolveGatewayScheme( - root: root, - env: ProcessInfo.processInfo.environment) - let port = self.deps.localPort() - let token = self.deps.token() - let password = self.deps.password() - let url = URL(string: "\(scheme)://\(tailscaleIP):\(port)")! - - self.logger.info("auto bind fallback to tailnet host=\(tailscaleIP, privacy: .public)") - self.setState(.ready(mode: .local, url: url, token: token, password: password)) - return (url, token, password) - } - - private static func resolveGatewayBindMode( - root: [String: Any], - env: [String: String]) -> String? - { - if let envBind = env["OPENCLAW_GATEWAY_BIND"] { - let trimmed = envBind.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - if self.supportedBindModes.contains(trimmed) { - return trimmed - } - } - if let gateway = root["gateway"] as? [String: Any], - let bind = gateway["bind"] as? String - { - let trimmed = bind.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - if self.supportedBindModes.contains(trimmed) { - return trimmed - } - } - return nil - } - - private static func resolveGatewayCustomBindHost(root: [String: Any]) -> String? { - if let gateway = root["gateway"] as? [String: Any], - let customBindHost = gateway["customBindHost"] as? String - { - let trimmed = customBindHost.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed.isEmpty ? nil : trimmed - } - return nil - } - - private static func resolveGatewayScheme( - root: [String: Any], - env: [String: String]) -> String - { - if let envValue = env["OPENCLAW_GATEWAY_TLS"]?.trimmingCharacters(in: .whitespacesAndNewlines), - !envValue.isEmpty - { - return (envValue == "1" || envValue.lowercased() == "true") ? "wss" : "ws" - } - if let gateway = root["gateway"] as? [String: Any], - let tls = gateway["tls"] as? [String: Any], - let enabled = tls["enabled"] as? Bool - { - return enabled ? "wss" : "ws" - } - return "ws" - } - - private static func resolveLocalGatewayHost( - bindMode: String?, - customBindHost: String?, - tailscaleIP: String?) -> String - { - switch bindMode { - case "tailnet": - tailscaleIP ?? "127.0.0.1" - case "auto": - "127.0.0.1" - case "custom": - customBindHost ?? "127.0.0.1" - default: - "127.0.0.1" - } - } -} - -extension GatewayEndpointStore { - private static func normalizeDashboardPath(_ rawPath: String?) -> String { - let trimmed = (rawPath ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return "/" } - let withLeadingSlash = trimmed.hasPrefix("/") ? trimmed : "/" + trimmed - guard withLeadingSlash != "/" else { return "/" } - return withLeadingSlash.hasSuffix("/") ? withLeadingSlash : withLeadingSlash + "/" - } - - private static func localControlUiBasePath() -> String { - let root = OpenClawConfigFile.loadDict() - guard let gateway = root["gateway"] as? [String: Any], - let controlUi = gateway["controlUi"] as? [String: Any] - else { - return "/" - } - return self.normalizeDashboardPath(controlUi["basePath"] as? String) - } - - static func dashboardURL( - for config: GatewayConnection.Config, - mode: AppState.ConnectionMode, - localBasePath: String? = nil) throws -> URL - { - guard var components = URLComponents(url: config.url, resolvingAgainstBaseURL: false) else { - throw NSError(domain: "Dashboard", code: 1, userInfo: [ - NSLocalizedDescriptionKey: "Invalid gateway URL", - ]) - } - switch components.scheme?.lowercased() { - case "ws": - components.scheme = "http" - case "wss": - components.scheme = "https" - default: - components.scheme = "http" - } - - let urlPath = self.normalizeDashboardPath(components.path) - if urlPath != "/" { - components.path = urlPath - } else if mode == .local { - let fallbackPath = localBasePath ?? self.localControlUiBasePath() - components.path = self.normalizeDashboardPath(fallbackPath) - } else { - components.path = "/" - } - - var queryItems: [URLQueryItem] = [] - if let token = config.token?.trimmingCharacters(in: .whitespacesAndNewlines), - !token.isEmpty - { - queryItems.append(URLQueryItem(name: "token", value: token)) - } - if let password = config.password?.trimmingCharacters(in: .whitespacesAndNewlines), - !password.isEmpty - { - queryItems.append(URLQueryItem(name: "password", value: password)) - } - components.queryItems = queryItems.isEmpty ? nil : queryItems - guard let url = components.url else { - throw NSError(domain: "Dashboard", code: 2, userInfo: [ - NSLocalizedDescriptionKey: "Failed to build dashboard URL", - ]) - } - return url - } -} - -#if DEBUG -extension GatewayEndpointStore { - static func _testResolveGatewayPassword( - isRemote: Bool, - root: [String: Any], - env: [String: String], - launchdSnapshot: LaunchAgentPlistSnapshot? = nil) -> String? - { - self.resolveGatewayPassword(isRemote: isRemote, root: root, env: env, launchdSnapshot: launchdSnapshot) - } - - static func _testResolveGatewayToken( - isRemote: Bool, - root: [String: Any], - env: [String: String], - launchdSnapshot: LaunchAgentPlistSnapshot? = nil) -> String? - { - self.resolveGatewayToken(isRemote: isRemote, root: root, env: env, launchdSnapshot: launchdSnapshot) - } - - static func _testResolveGatewayBindMode( - root: [String: Any], - env: [String: String]) -> String? - { - self.resolveGatewayBindMode(root: root, env: env) - } - - static func _testResolveLocalGatewayHost( - bindMode: String?, - tailscaleIP: String?, - customBindHost: String? = nil) -> String - { - self.resolveLocalGatewayHost( - bindMode: bindMode, - customBindHost: customBindHost, - tailscaleIP: tailscaleIP) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/GatewayEnvironment.swift b/apps/macos/Sources/OpenClaw/GatewayEnvironment.swift deleted file mode 100644 index 059eb4da6e0..00000000000 --- a/apps/macos/Sources/OpenClaw/GatewayEnvironment.swift +++ /dev/null @@ -1,344 +0,0 @@ -import Foundation -import OpenClawIPC -import OSLog - -/// Lightweight SemVer helper (major.minor.patch only) for gateway compatibility checks. -struct Semver: Comparable, CustomStringConvertible, Sendable { - let major: Int - let minor: Int - let patch: Int - - var description: String { - "\(self.major).\(self.minor).\(self.patch)" - } - - static func < (lhs: Semver, rhs: Semver) -> Bool { - if lhs.major != rhs.major { return lhs.major < rhs.major } - if lhs.minor != rhs.minor { return lhs.minor < rhs.minor } - return lhs.patch < rhs.patch - } - - static func parse(_ raw: String?) -> Semver? { - guard let raw, !raw.isEmpty else { return nil } - let cleaned = raw.trimmingCharacters(in: .whitespacesAndNewlines) - .replacingOccurrences(of: "^v", with: "", options: .regularExpression) - let parts = cleaned.split(separator: ".") - guard parts.count >= 3, - let major = Int(parts[0]), - let minor = Int(parts[1]) - else { return nil } - // Strip prerelease suffix (e.g., "11-4" → "11", "5-beta.1" → "5") - let patchRaw = String(parts[2]) - guard let patchToken = patchRaw.split(whereSeparator: { $0 == "-" || $0 == "+" }).first, - let patchNumeric = Int(patchToken) - else { - return nil - } - return Semver(major: major, minor: minor, patch: patchNumeric) - } - - func compatible(with required: Semver) -> Bool { - // Same major and not older than required. - self.major == required.major && self >= required - } -} - -enum GatewayEnvironmentKind: Equatable { - case checking - case ok - case missingNode - case missingGateway - case incompatible(found: String, required: String) - case error(String) -} - -struct GatewayEnvironmentStatus: Equatable { - let kind: GatewayEnvironmentKind - let nodeVersion: String? - let gatewayVersion: String? - let requiredGateway: String? - let message: String - - static var checking: Self { - .init(kind: .checking, nodeVersion: nil, gatewayVersion: nil, requiredGateway: nil, message: "Checking…") - } -} - -struct GatewayCommandResolution { - let status: GatewayEnvironmentStatus - let command: [String]? -} - -enum GatewayEnvironment { - private static let logger = Logger(subsystem: "ai.openclaw", category: "gateway.env") - private static let supportedBindModes: Set = ["loopback", "tailnet", "lan", "auto"] - - static func gatewayPort() -> Int { - if let raw = ProcessInfo.processInfo.environment["OPENCLAW_GATEWAY_PORT"] { - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - if let parsed = Int(trimmed), parsed > 0 { return parsed } - } - if let configPort = OpenClawConfigFile.gatewayPort(), configPort > 0 { - return configPort - } - let stored = UserDefaults.standard.integer(forKey: "gatewayPort") - return stored > 0 ? stored : 18789 - } - - static func expectedGatewayVersion() -> Semver? { - Semver.parse(self.expectedGatewayVersionString()) - } - - static func expectedGatewayVersionString() -> String? { - let bundleVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String - let trimmed = bundleVersion?.trimmingCharacters(in: .whitespacesAndNewlines) - return (trimmed?.isEmpty == false) ? trimmed : nil - } - - /// Exposed for tests so we can inject fake version checks without rewriting bundle metadata. - static func expectedGatewayVersion(from versionString: String?) -> Semver? { - Semver.parse(versionString) - } - - static func check() -> GatewayEnvironmentStatus { - let start = Date() - defer { - let elapsedMs = Int(Date().timeIntervalSince(start) * 1000) - if elapsedMs > 500 { - self.logger.warning("gateway env check slow (\(elapsedMs, privacy: .public)ms)") - } else { - self.logger.debug("gateway env check ok (\(elapsedMs, privacy: .public)ms)") - } - } - let expected = self.expectedGatewayVersion() - let expectedString = self.expectedGatewayVersionString() - - let projectRoot = CommandResolver.projectRoot() - let projectEntrypoint = CommandResolver.gatewayEntrypoint(in: projectRoot) - - switch RuntimeLocator.resolve(searchPaths: CommandResolver.preferredPaths()) { - case let .failure(err): - return GatewayEnvironmentStatus( - kind: .missingNode, - nodeVersion: nil, - gatewayVersion: nil, - requiredGateway: expectedString, - message: RuntimeLocator.describeFailure(err)) - case let .success(runtime): - let gatewayBin = CommandResolver.openclawExecutable() - - if gatewayBin == nil, projectEntrypoint == nil { - return GatewayEnvironmentStatus( - kind: .missingGateway, - nodeVersion: runtime.version.description, - gatewayVersion: nil, - requiredGateway: expectedString, - message: "openclaw CLI not found in PATH; install the CLI.") - } - - let installed = gatewayBin.flatMap { self.readGatewayVersion(binary: $0) } - ?? self.readLocalGatewayVersion(projectRoot: projectRoot) - - if let expected, let installed, !installed.compatible(with: expected) { - let expectedText = expectedString ?? expected.description - return GatewayEnvironmentStatus( - kind: .incompatible(found: installed.description, required: expectedText), - nodeVersion: runtime.version.description, - gatewayVersion: installed.description, - requiredGateway: expectedText, - message: """ - Gateway version \(installed.description) is incompatible with app \(expectedText); - install or update the global package. - """) - } - - let gatewayLabel = gatewayBin != nil ? "global" : "local" - let gatewayVersionText = installed?.description ?? "unknown" - // Avoid repeating "(local)" twice; if using the local entrypoint, show the path once. - let localPathHint = gatewayBin == nil && projectEntrypoint != nil - ? " (local: \(projectEntrypoint ?? "unknown"))" - : "" - let gatewayLabelText = gatewayBin != nil - ? "(\(gatewayLabel))" - : localPathHint.isEmpty ? "(\(gatewayLabel))" : localPathHint - return GatewayEnvironmentStatus( - kind: .ok, - nodeVersion: runtime.version.description, - gatewayVersion: gatewayVersionText, - requiredGateway: expectedString, - message: "Node \(runtime.version.description); gateway \(gatewayVersionText) \(gatewayLabelText)") - } - } - - static func resolveGatewayCommand() -> GatewayCommandResolution { - let start = Date() - defer { - let elapsedMs = Int(Date().timeIntervalSince(start) * 1000) - if elapsedMs > 500 { - self.logger.warning("gateway command resolve slow (\(elapsedMs, privacy: .public)ms)") - } else { - self.logger.debug("gateway command resolve ok (\(elapsedMs, privacy: .public)ms)") - } - } - let projectRoot = CommandResolver.projectRoot() - let projectEntrypoint = CommandResolver.gatewayEntrypoint(in: projectRoot) - let status = self.check() - let gatewayBin = CommandResolver.openclawExecutable() - let runtime = RuntimeLocator.resolve(searchPaths: CommandResolver.preferredPaths()) - - guard case .ok = status.kind else { - return GatewayCommandResolution(status: status, command: nil) - } - - let port = self.gatewayPort() - if let gatewayBin { - let bind = self.preferredGatewayBind() ?? "loopback" - let cmd = [gatewayBin, "gateway-daemon", "--port", "\(port)", "--bind", bind] - return GatewayCommandResolution(status: status, command: cmd) - } - - if let entry = projectEntrypoint, - case let .success(resolvedRuntime) = runtime - { - let bind = self.preferredGatewayBind() ?? "loopback" - let cmd = [resolvedRuntime.path, entry, "gateway-daemon", "--port", "\(port)", "--bind", bind] - return GatewayCommandResolution(status: status, command: cmd) - } - - return GatewayCommandResolution(status: status, command: nil) - } - - private static func preferredGatewayBind() -> String? { - if CommandResolver.connectionModeIsRemote() { - return nil - } - if let env = ProcessInfo.processInfo.environment["OPENCLAW_GATEWAY_BIND"] { - let trimmed = env.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - if self.supportedBindModes.contains(trimmed) { - return trimmed - } - } - - let root = OpenClawConfigFile.loadDict() - if let gateway = root["gateway"] as? [String: Any], - let bind = gateway["bind"] as? String - { - let trimmed = bind.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - if self.supportedBindModes.contains(trimmed) { - return trimmed - } - } - - return nil - } - - static func installGlobal(version: Semver?, statusHandler: @escaping @Sendable (String) -> Void) async { - await self.installGlobal(versionString: version?.description, statusHandler: statusHandler) - } - - static func installGlobal(versionString: String?, statusHandler: @escaping @Sendable (String) -> Void) async { - let preferred = CommandResolver.preferredPaths().joined(separator: ":") - let trimmed = versionString?.trimmingCharacters(in: .whitespacesAndNewlines) - let target: String = if let trimmed, !trimmed.isEmpty { - trimmed - } else { - "latest" - } - let npm = CommandResolver.findExecutable(named: "npm") - let pnpm = CommandResolver.findExecutable(named: "pnpm") - let bun = CommandResolver.findExecutable(named: "bun") - let (label, cmd): (String, [String]) = - if let npm { - ("npm", [npm, "install", "-g", "openclaw@\(target)"]) - } else if let pnpm { - ("pnpm", [pnpm, "add", "-g", "openclaw@\(target)"]) - } else if let bun { - ("bun", [bun, "add", "-g", "openclaw@\(target)"]) - } else { - ("npm", ["npm", "install", "-g", "openclaw@\(target)"]) - } - - statusHandler("Installing openclaw@\(target) via \(label)…") - - func summarize(_ text: String) -> String? { - let lines = text - .split(whereSeparator: \.isNewline) - .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } - .filter { !$0.isEmpty } - guard let last = lines.last else { return nil } - let normalized = last.replacingOccurrences(of: "\\s+", with: " ", options: .regularExpression) - return normalized.count > 200 ? String(normalized.prefix(199)) + "…" : normalized - } - - let response = await ShellExecutor.runDetailed(command: cmd, cwd: nil, env: ["PATH": preferred], timeout: 300) - if response.success { - statusHandler("Installed openclaw@\(target)") - } else { - if response.timedOut { - statusHandler("Install failed: timed out. Check your internet connection and try again.") - return - } - - let exit = response.exitCode.map { "exit \($0)" } ?? (response.errorMessage ?? "failed") - let detail = summarize(response.stderr) ?? summarize(response.stdout) - if let detail { - statusHandler("Install failed (\(exit)): \(detail)") - } else { - statusHandler("Install failed (\(exit))") - } - } - } - - // MARK: - Internals - - private static func readGatewayVersion(binary: String) -> Semver? { - let start = Date() - let process = Process() - process.executableURL = URL(fileURLWithPath: binary) - process.arguments = ["--version"] - process.environment = ["PATH": CommandResolver.preferredPaths().joined(separator: ":")] - - let pipe = Pipe() - process.standardOutput = pipe - process.standardError = pipe - do { - let data = try process.runAndReadToEnd(from: pipe) - let elapsedMs = Int(Date().timeIntervalSince(start) * 1000) - if elapsedMs > 500 { - self.logger.warning( - """ - gateway --version slow (\(elapsedMs, privacy: .public)ms) \ - bin=\(binary, privacy: .public) - """) - } else { - self.logger.debug( - """ - gateway --version ok (\(elapsedMs, privacy: .public)ms) \ - bin=\(binary, privacy: .public) - """) - } - let raw = String(data: data, encoding: .utf8)? - .trimmingCharacters(in: .whitespacesAndNewlines) - return Semver.parse(raw) - } catch { - let elapsedMs = Int(Date().timeIntervalSince(start) * 1000) - self.logger.error( - """ - gateway --version failed (\(elapsedMs, privacy: .public)ms) \ - bin=\(binary, privacy: .public) \ - err=\(error.localizedDescription, privacy: .public) - """) - return nil - } - } - - private static func readLocalGatewayVersion(projectRoot: URL) -> Semver? { - let pkg = projectRoot.appendingPathComponent("package.json") - guard let data = try? Data(contentsOf: pkg) else { return nil } - guard - let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], - let version = json["version"] as? String - else { return nil } - return Semver.parse(version) - } -} diff --git a/apps/macos/Sources/OpenClaw/GatewayLaunchAgentManager.swift b/apps/macos/Sources/OpenClaw/GatewayLaunchAgentManager.swift deleted file mode 100644 index 98743fec8b3..00000000000 --- a/apps/macos/Sources/OpenClaw/GatewayLaunchAgentManager.swift +++ /dev/null @@ -1,204 +0,0 @@ -import Foundation - -enum GatewayLaunchAgentManager { - private static let logger = Logger(subsystem: "ai.openclaw", category: "gateway.launchd") - private static let disableLaunchAgentMarker = ".openclaw/disable-launchagent" - - private static var disableLaunchAgentMarkerURL: URL { - FileManager().homeDirectoryForCurrentUser - .appendingPathComponent(self.disableLaunchAgentMarker) - } - - private static var plistURL: URL { - FileManager().homeDirectoryForCurrentUser - .appendingPathComponent("Library/LaunchAgents/\(gatewayLaunchdLabel).plist") - } - - static func isLaunchAgentWriteDisabled() -> Bool { - if FileManager().fileExists(atPath: self.disableLaunchAgentMarkerURL.path) { return true } - return false - } - - static func setLaunchAgentWriteDisabled(_ disabled: Bool) -> String? { - let marker = self.disableLaunchAgentMarkerURL - if disabled { - do { - try FileManager().createDirectory( - at: marker.deletingLastPathComponent(), - withIntermediateDirectories: true) - if !FileManager().fileExists(atPath: marker.path) { - FileManager().createFile(atPath: marker.path, contents: nil) - } - } catch { - return error.localizedDescription - } - return nil - } - - if FileManager().fileExists(atPath: marker.path) { - do { - try FileManager().removeItem(at: marker) - } catch { - return error.localizedDescription - } - } - return nil - } - - static func isLoaded() async -> Bool { - guard let loaded = await self.readDaemonLoaded() else { return false } - return loaded - } - - static func set(enabled: Bool, bundlePath: String, port: Int) async -> String? { - _ = bundlePath - guard !CommandResolver.connectionModeIsRemote() else { - self.logger.info("launchd change skipped (remote mode)") - return nil - } - if enabled, self.isLaunchAgentWriteDisabled() { - self.logger.info("launchd enable skipped (disable marker set)") - return nil - } - - if enabled { - self.logger.info("launchd enable requested via CLI port=\(port)") - return await self.runDaemonCommand([ - "install", - "--force", - "--port", - "\(port)", - "--runtime", - "node", - ]) - } - - self.logger.info("launchd disable requested via CLI") - return await self.runDaemonCommand(["uninstall"]) - } - - static func kickstart() async { - _ = await self.runDaemonCommand(["restart"], timeout: 20) - } - - static func launchdConfigSnapshot() -> LaunchAgentPlistSnapshot? { - LaunchAgentPlist.snapshot(url: self.plistURL) - } - - static func launchdGatewayLogPath() -> String { - let snapshot = self.launchdConfigSnapshot() - if let stdout = snapshot?.stdoutPath?.trimmingCharacters(in: .whitespacesAndNewlines), - !stdout.isEmpty - { - return stdout - } - if let stderr = snapshot?.stderrPath?.trimmingCharacters(in: .whitespacesAndNewlines), - !stderr.isEmpty - { - return stderr - } - return LogLocator.launchdGatewayLogPath - } -} - -extension GatewayLaunchAgentManager { - private static func readDaemonLoaded() async -> Bool? { - let result = await self.runDaemonCommandResult( - ["status", "--json", "--no-probe"], - timeout: 15, - quiet: true) - guard result.success, let payload = result.payload else { return nil } - guard - let json = try? JSONSerialization.jsonObject(with: payload) as? [String: Any], - let service = json["service"] as? [String: Any], - let loaded = service["loaded"] as? Bool - else { - return nil - } - return loaded - } - - private struct CommandResult { - let success: Bool - let payload: Data? - let message: String? - } - - private struct ParsedDaemonJson { - let text: String - let object: [String: Any] - } - - private static func runDaemonCommand( - _ args: [String], - timeout: Double = 15, - quiet: Bool = false) async -> String? - { - let result = await self.runDaemonCommandResult(args, timeout: timeout, quiet: quiet) - if result.success { return nil } - return result.message ?? "Gateway daemon command failed" - } - - private static func runDaemonCommandResult( - _ args: [String], - timeout: Double, - quiet: Bool) async -> CommandResult - { - let command = CommandResolver.openclawCommand( - subcommand: "gateway", - extraArgs: self.withJsonFlag(args), - // Launchd management must always run locally, even if remote mode is configured. - configRoot: ["gateway": ["mode": "local"]]) - var env = ProcessInfo.processInfo.environment - env["PATH"] = CommandResolver.preferredPaths().joined(separator: ":") - let response = await ShellExecutor.runDetailed(command: command, cwd: nil, env: env, timeout: timeout) - let parsed = self.parseDaemonJson(from: response.stdout) ?? self.parseDaemonJson(from: response.stderr) - let ok = parsed?.object["ok"] as? Bool - let message = (parsed?.object["error"] as? String) ?? (parsed?.object["message"] as? String) - let payload = parsed?.text.data(using: .utf8) - ?? (response.stdout.isEmpty ? response.stderr : response.stdout).data(using: .utf8) - let success = ok ?? response.success - if success { - return CommandResult(success: true, payload: payload, message: nil) - } - - if quiet { - return CommandResult(success: false, payload: payload, message: message) - } - - let detail = message ?? self.summarize(response.stderr) ?? self.summarize(response.stdout) - let exit = response.exitCode.map { "exit \($0)" } ?? (response.errorMessage ?? "failed") - let fullMessage = detail.map { "Gateway daemon command failed (\(exit)): \($0)" } - ?? "Gateway daemon command failed (\(exit))" - self.logger.error("\(fullMessage, privacy: .public)") - return CommandResult(success: false, payload: payload, message: detail) - } - - private static func withJsonFlag(_ args: [String]) -> [String] { - if args.contains("--json") { return args } - return args + ["--json"] - } - - private static func parseDaemonJson(from raw: String) -> ParsedDaemonJson? { - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - guard let start = trimmed.firstIndex(of: "{"), - let end = trimmed.lastIndex(of: "}") - else { - return nil - } - let jsonText = String(trimmed[start...end]) - guard let data = jsonText.data(using: .utf8) else { return nil } - guard let object = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { return nil } - return ParsedDaemonJson(text: jsonText, object: object) - } - - private static func summarize(_ text: String) -> String? { - let lines = text - .split(whereSeparator: \.isNewline) - .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } - .filter { !$0.isEmpty } - guard let last = lines.last else { return nil } - let normalized = last.replacingOccurrences(of: "\\s+", with: " ", options: .regularExpression) - return normalized.count > 200 ? String(normalized.prefix(199)) + "…" : normalized - } -} diff --git a/apps/macos/Sources/OpenClaw/GatewayProcessManager.swift b/apps/macos/Sources/OpenClaw/GatewayProcessManager.swift deleted file mode 100644 index e3d5263e9bc..00000000000 --- a/apps/macos/Sources/OpenClaw/GatewayProcessManager.swift +++ /dev/null @@ -1,432 +0,0 @@ -import Foundation -import Observation - -@MainActor -@Observable -final class GatewayProcessManager { - static let shared = GatewayProcessManager() - - enum Status: Equatable { - case stopped - case starting - case running(details: String?) - case attachedExisting(details: String?) - case failed(String) - - var label: String { - switch self { - case .stopped: return "Stopped" - case .starting: return "Starting…" - case let .running(details): - if let details, !details.isEmpty { return "Running (\(details))" } - return "Running" - case let .attachedExisting(details): - if let details, !details.isEmpty { - return "Using existing gateway (\(details))" - } - return "Using existing gateway" - case let .failed(reason): return "Failed: \(reason)" - } - } - } - - private(set) var status: Status = .stopped { - didSet { CanvasManager.shared.refreshDebugStatus() } - } - - private(set) var log: String = "" - private(set) var environmentStatus: GatewayEnvironmentStatus = .checking - private(set) var existingGatewayDetails: String? - private(set) var lastFailureReason: String? - private var desiredActive = false - private var environmentRefreshTask: Task? - private var lastEnvironmentRefresh: Date? - private var logRefreshTask: Task? - #if DEBUG - private var testingConnection: GatewayConnection? - #endif - private let logger = Logger(subsystem: "ai.openclaw", category: "gateway.process") - - private let logLimit = 20000 // characters to keep in-memory - private let environmentRefreshMinInterval: TimeInterval = 30 - private var connection: GatewayConnection { - #if DEBUG - return self.testingConnection ?? .shared - #else - return .shared - #endif - } - - func setActive(_ active: Bool) { - // Remote mode should never spawn a local gateway; treat as stopped. - if CommandResolver.connectionModeIsRemote() { - self.desiredActive = false - self.stop() - self.status = .stopped - self.appendLog("[gateway] remote mode active; skipping local gateway\n") - self.logger.info("gateway process skipped: remote mode active") - return - } - self.logger.debug("gateway active requested active=\(active)") - self.desiredActive = active - self.refreshEnvironmentStatus() - if active { - self.startIfNeeded() - } else { - self.stop() - } - } - - func ensureLaunchAgentEnabledIfNeeded() async { - guard !CommandResolver.connectionModeIsRemote() else { return } - if GatewayLaunchAgentManager.isLaunchAgentWriteDisabled() { - self.appendLog("[gateway] launchd auto-enable skipped (attach-only)\n") - self.logger.info("gateway launchd auto-enable skipped (disable marker set)") - return - } - let enabled = await GatewayLaunchAgentManager.isLoaded() - guard !enabled else { return } - let bundlePath = Bundle.main.bundleURL.path - let port = GatewayEnvironment.gatewayPort() - self.appendLog("[gateway] auto-enabling launchd job (\(gatewayLaunchdLabel)) on port \(port)\n") - let err = await GatewayLaunchAgentManager.set(enabled: true, bundlePath: bundlePath, port: port) - if let err { - self.appendLog("[gateway] launchd auto-enable failed: \(err)\n") - } - } - - func startIfNeeded() { - guard self.desiredActive else { return } - // Do not spawn in remote mode (the gateway should run on the remote host). - guard !CommandResolver.connectionModeIsRemote() else { - self.status = .stopped - return - } - // Many surfaces can call `setActive(true)` in quick succession (startup, Canvas, health checks). - // Avoid spawning multiple concurrent "start" tasks that can thrash launchd and flap the port. - switch self.status { - case .starting, .running, .attachedExisting: - return - case .stopped, .failed: - break - } - self.status = .starting - self.logger.debug("gateway start requested") - - // First try to latch onto an already-running gateway to avoid spawning a duplicate. - Task { [weak self] in - guard let self else { return } - if await self.attachExistingGatewayIfAvailable() { - return - } - await self.enableLaunchdGateway() - } - } - - func stop() { - self.desiredActive = false - self.existingGatewayDetails = nil - self.lastFailureReason = nil - self.status = .stopped - self.logger.info("gateway stop requested") - if CommandResolver.connectionModeIsRemote() { - return - } - let bundlePath = Bundle.main.bundleURL.path - Task { - _ = await GatewayLaunchAgentManager.set( - enabled: false, - bundlePath: bundlePath, - port: GatewayEnvironment.gatewayPort()) - } - } - - func clearLastFailure() { - self.lastFailureReason = nil - } - - func refreshEnvironmentStatus(force: Bool = false) { - let now = Date() - if !force { - if self.environmentRefreshTask != nil { return } - if let last = self.lastEnvironmentRefresh, - now.timeIntervalSince(last) < self.environmentRefreshMinInterval - { - return - } - } - self.lastEnvironmentRefresh = now - self.environmentRefreshTask = Task { [weak self] in - let status = await Task.detached(priority: .utility) { - GatewayEnvironment.check() - }.value - await MainActor.run { - guard let self else { return } - self.environmentStatus = status - self.environmentRefreshTask = nil - } - } - } - - func refreshLog() { - guard self.logRefreshTask == nil else { return } - let path = GatewayLaunchAgentManager.launchdGatewayLogPath() - let limit = self.logLimit - self.logRefreshTask = Task { [weak self] in - let log = await Task.detached(priority: .utility) { - Self.readGatewayLog(path: path, limit: limit) - }.value - await MainActor.run { - guard let self else { return } - if !log.isEmpty { - self.log = log - } - self.logRefreshTask = nil - } - } - } - - // MARK: - Internals - - /// Attempt to connect to an already-running gateway on the configured port. - /// If successful, mark status as attached and skip spawning a new process. - private func attachExistingGatewayIfAvailable() async -> Bool { - let port = GatewayEnvironment.gatewayPort() - let instance = await PortGuardian.shared.describe(port: port) - let instanceText = instance.map { self.describe(instance: $0) } - let hasListener = instance != nil - - let attemptAttach = { - try await self.connection.requestRaw(method: .health, timeoutMs: 2000) - } - - for attempt in 0..<(hasListener ? 3 : 1) { - do { - let data = try await attemptAttach() - let snap = decodeHealthSnapshot(from: data) - let details = self.describe(details: instanceText, port: port, snap: snap) - self.existingGatewayDetails = details - self.clearLastFailure() - self.status = .attachedExisting(details: details) - self.appendLog("[gateway] using existing instance: \(details)\n") - self.logger.info("gateway using existing instance details=\(details)") - self.refreshControlChannelIfNeeded(reason: "attach existing") - self.refreshLog() - return true - } catch { - if attempt < 2, hasListener { - try? await Task.sleep(nanoseconds: 250_000_000) - continue - } - - if hasListener { - let reason = self.describeAttachFailure(error, port: port, instance: instance) - self.existingGatewayDetails = instanceText - self.status = .failed(reason) - self.lastFailureReason = reason - self.appendLog("[gateway] existing listener on port \(port) but attach failed: \(reason)\n") - self.logger.warning("gateway attach failed reason=\(reason)") - return true - } - - // No reachable gateway (and no listener) — fall through to spawn. - self.existingGatewayDetails = nil - return false - } - } - - self.existingGatewayDetails = nil - return false - } - - private func describe(details instance: String?, port: Int, snap: HealthSnapshot?) -> String { - let instanceText = instance ?? "pid unknown" - if let snap { - let order = snap.channelOrder ?? Array(snap.channels.keys) - let linkId = order.first(where: { snap.channels[$0]?.linked == true }) - ?? order.first(where: { snap.channels[$0]?.linked != nil }) - guard let linkId else { - return "port \(port), health probe succeeded, \(instanceText)" - } - let linked = snap.channels[linkId]?.linked ?? false - let authAge = snap.channels[linkId]?.authAgeMs.flatMap(msToAge) ?? "unknown age" - let label = - snap.channelLabels?[linkId] ?? - linkId.capitalized - let linkText = linked ? "linked" : "not linked" - return "port \(port), \(label) \(linkText), auth \(authAge), \(instanceText)" - } - return "port \(port), health probe succeeded, \(instanceText)" - } - - private func describe(instance: PortGuardian.Descriptor) -> String { - let path = instance.executablePath ?? "path unknown" - return "pid \(instance.pid) \(instance.command) @ \(path)" - } - - private func describeAttachFailure(_ error: Error, port: Int, instance: PortGuardian.Descriptor?) -> String { - let ns = error as NSError - let message = ns.localizedDescription.isEmpty ? "unknown error" : ns.localizedDescription - let lower = message.lowercased() - if self.isGatewayAuthFailure(error) { - return """ - Gateway on port \(port) rejected auth. Set gateway.auth.token to match the running gateway \ - (or clear it on the gateway) and retry. - """ - } - if lower.contains("protocol mismatch") { - return "Gateway on port \(port) is incompatible (protocol mismatch). Update the app/gateway." - } - if lower.contains("unexpected response") || lower.contains("invalid response") { - return "Port \(port) returned non-gateway data; another process is using it." - } - if let instance { - let instanceText = self.describe(instance: instance) - return "Gateway listener found on port \(port) (\(instanceText)) but health check failed: \(message)" - } - return "Gateway listener found on port \(port) but health check failed: \(message)" - } - - private func isGatewayAuthFailure(_ error: Error) -> Bool { - if let urlError = error as? URLError, urlError.code == .dataNotAllowed { - return true - } - let ns = error as NSError - if ns.domain == "Gateway", ns.code == 1008 { return true } - let lower = ns.localizedDescription.lowercased() - return lower.contains("unauthorized") || lower.contains("auth") - } - - private func enableLaunchdGateway() async { - self.existingGatewayDetails = nil - let resolution = await Task.detached(priority: .utility) { - GatewayEnvironment.resolveGatewayCommand() - }.value - await MainActor.run { self.environmentStatus = resolution.status } - guard resolution.command != nil else { - await MainActor.run { - self.status = .failed(resolution.status.message) - } - self.logger.error("gateway command resolve failed: \(resolution.status.message)") - return - } - - if GatewayLaunchAgentManager.isLaunchAgentWriteDisabled() { - let message = "Launchd disabled; start the Gateway manually or disable attach-only." - self.status = .failed(message) - self.lastFailureReason = "launchd disabled" - self.appendLog("[gateway] launchd disabled; skipping auto-start\n") - self.logger.info("gateway launchd enable skipped (disable marker set)") - return - } - - let bundlePath = Bundle.main.bundleURL.path - let port = GatewayEnvironment.gatewayPort() - self.appendLog("[gateway] enabling launchd job (\(gatewayLaunchdLabel)) on port \(port)\n") - self.logger.info("gateway enabling launchd port=\(port)") - let err = await GatewayLaunchAgentManager.set(enabled: true, bundlePath: bundlePath, port: port) - if let err { - self.status = .failed(err) - self.lastFailureReason = err - self.logger.error("gateway launchd enable failed: \(err)") - return - } - - // Best-effort: wait for the gateway to accept connections. - let deadline = Date().addingTimeInterval(6) - while Date() < deadline { - if !self.desiredActive { return } - do { - _ = try await self.connection.requestRaw(method: .health, timeoutMs: 1500) - let instance = await PortGuardian.shared.describe(port: port) - let details = instance.map { "pid \($0.pid)" } - self.clearLastFailure() - self.status = .running(details: details) - self.logger.info("gateway started details=\(details ?? "ok")") - self.refreshControlChannelIfNeeded(reason: "gateway started") - self.refreshLog() - return - } catch { - try? await Task.sleep(nanoseconds: 400_000_000) - } - } - - self.status = .failed("Gateway did not start in time") - self.lastFailureReason = "launchd start timeout" - self.logger.warning("gateway start timed out") - } - - private func appendLog(_ chunk: String) { - self.log.append(chunk) - if self.log.count > self.logLimit { - self.log = String(self.log.suffix(self.logLimit)) - } - } - - private func refreshControlChannelIfNeeded(reason: String) { - switch ControlChannel.shared.state { - case .connected, .connecting: - return - case .disconnected, .degraded: - break - } - self.appendLog("[gateway] refreshing control channel (\(reason))\n") - self.logger.debug("gateway control channel refresh reason=\(reason)") - Task { await ControlChannel.shared.configure() } - } - - func waitForGatewayReady(timeout: TimeInterval = 6) async -> Bool { - let deadline = Date().addingTimeInterval(timeout) - while Date() < deadline { - if !self.desiredActive { return false } - do { - _ = try await self.connection.requestRaw(method: .health, timeoutMs: 1500) - self.clearLastFailure() - return true - } catch { - try? await Task.sleep(nanoseconds: 300_000_000) - } - } - self.appendLog("[gateway] readiness wait timed out\n") - self.logger.warning("gateway readiness wait timed out") - return false - } - - func clearLog() { - self.log = "" - try? FileManager().removeItem(atPath: GatewayLaunchAgentManager.launchdGatewayLogPath()) - self.logger.debug("gateway log cleared") - } - - func setProjectRoot(path: String) { - CommandResolver.setProjectRoot(path) - } - - func projectRootPath() -> String { - CommandResolver.projectRootPath() - } - - private nonisolated static func readGatewayLog(path: String, limit: Int) -> String { - guard FileManager().fileExists(atPath: path) else { return "" } - guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else { return "" } - let text = String(data: data, encoding: .utf8) ?? "" - if text.count <= limit { return text } - return String(text.suffix(limit)) - } -} - -#if DEBUG -extension GatewayProcessManager { - func setTestingConnection(_ connection: GatewayConnection?) { - self.testingConnection = connection - } - - func setTestingDesiredActive(_ active: Bool) { - self.desiredActive = active - } - - func setTestingLastFailureReason(_ reason: String?) { - self.lastFailureReason = reason - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/GatewayRemoteConfig.swift b/apps/macos/Sources/OpenClaw/GatewayRemoteConfig.swift deleted file mode 100644 index 64a6f92db8f..00000000000 --- a/apps/macos/Sources/OpenClaw/GatewayRemoteConfig.swift +++ /dev/null @@ -1,102 +0,0 @@ -import Foundation -import Network - -enum GatewayRemoteConfig { - private static func isLoopbackHost(_ rawHost: String) -> Bool { - var host = rawHost - .trimmingCharacters(in: .whitespacesAndNewlines) - .lowercased() - .trimmingCharacters(in: CharacterSet(charactersIn: "[]")) - if host.hasSuffix(".") { - host.removeLast() - } - if let zoneIndex = host.firstIndex(of: "%") { - host = String(host[.. AppState.RemoteTransport { - guard let gateway = root["gateway"] as? [String: Any], - let remote = gateway["remote"] as? [String: Any], - let raw = remote["transport"] as? String - else { - return .ssh - } - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - return trimmed == AppState.RemoteTransport.direct.rawValue ? .direct : .ssh - } - - static func resolveUrlString(root: [String: Any]) -> String? { - guard let gateway = root["gateway"] as? [String: Any], - let remote = gateway["remote"] as? [String: Any], - let urlRaw = remote["url"] as? String - else { - return nil - } - let trimmed = urlRaw.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed.isEmpty ? nil : trimmed - } - - static func resolveGatewayUrl(root: [String: Any]) -> URL? { - guard let raw = self.resolveUrlString(root: root) else { return nil } - return self.normalizeGatewayUrl(raw) - } - - static func normalizeGatewayUrlString(_ raw: String) -> String? { - self.normalizeGatewayUrl(raw)?.absoluteString - } - - static func normalizeGatewayUrl(_ raw: String) -> URL? { - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty, let url = URL(string: trimmed) else { return nil } - let scheme = url.scheme?.lowercased() ?? "" - guard scheme == "ws" || scheme == "wss" else { return nil } - let host = url.host?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - guard !host.isEmpty else { return nil } - if scheme == "ws", !self.isLoopbackHost(host) { - return nil - } - if scheme == "ws", url.port == nil { - guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { - return url - } - components.port = 18789 - return components.url - } - return url - } - - static func defaultPort(for url: URL) -> Int? { - if let port = url.port { return port } - let scheme = url.scheme?.lowercased() ?? "" - switch scheme { - case "wss": - return 443 - case "ws": - return 18789 - default: - return nil - } - } -} diff --git a/apps/macos/Sources/OpenClaw/GeneralSettings.swift b/apps/macos/Sources/OpenClaw/GeneralSettings.swift deleted file mode 100644 index 60cfdfb1d73..00000000000 --- a/apps/macos/Sources/OpenClaw/GeneralSettings.swift +++ /dev/null @@ -1,743 +0,0 @@ -import AppKit -import Observation -import OpenClawDiscovery -import OpenClawIPC -import OpenClawKit -import SwiftUI - -struct GeneralSettings: View { - @Bindable var state: AppState - @AppStorage(cameraEnabledKey) private var cameraEnabled: Bool = false - private let healthStore = HealthStore.shared - private let gatewayManager = GatewayProcessManager.shared - @State private var gatewayDiscovery = GatewayDiscoveryModel( - localDisplayName: InstanceIdentity.displayName) - @State private var gatewayStatus: GatewayEnvironmentStatus = .checking - @State private var remoteStatus: RemoteStatus = .idle - @State private var showRemoteAdvanced = false - private let isPreview = ProcessInfo.processInfo.isPreview - private var isNixMode: Bool { - ProcessInfo.processInfo.isNixMode - } - - private var remoteLabelWidth: CGFloat { - 88 - } - - var body: some View { - ScrollView(.vertical) { - VStack(alignment: .leading, spacing: 18) { - VStack(alignment: .leading, spacing: 12) { - SettingsToggleRow( - title: "OpenClaw active", - subtitle: "Pause to stop the OpenClaw gateway; no messages will be processed.", - binding: self.activeBinding) - - self.connectionSection - - Divider() - - SettingsToggleRow( - title: "Launch at login", - subtitle: "Automatically start OpenClaw after you sign in.", - binding: self.$state.launchAtLogin) - - SettingsToggleRow( - title: "Show Dock icon", - subtitle: "Keep OpenClaw visible in the Dock instead of menu-bar-only mode.", - binding: self.$state.showDockIcon) - - SettingsToggleRow( - title: "Play menu bar icon animations", - subtitle: "Enable idle blinks and wiggles on the status icon.", - binding: self.$state.iconAnimationsEnabled) - - SettingsToggleRow( - title: "Allow Canvas", - subtitle: "Allow the agent to show and control the Canvas panel.", - binding: self.$state.canvasEnabled) - - SettingsToggleRow( - title: "Allow Camera", - subtitle: "Allow the agent to capture a photo or short video via the built-in camera.", - binding: self.$cameraEnabled) - - SettingsToggleRow( - title: "Enable Peekaboo Bridge", - subtitle: "Allow signed tools (e.g. `peekaboo`) to drive UI automation via PeekabooBridge.", - binding: self.$state.peekabooBridgeEnabled) - - SettingsToggleRow( - title: "Enable debug tools", - subtitle: "Show the Debug tab with development utilities.", - binding: self.$state.debugPaneEnabled) - } - - Spacer(minLength: 12) - HStack { - Spacer() - Button("Quit OpenClaw") { NSApp.terminate(nil) } - .buttonStyle(.borderedProminent) - } - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal, 22) - .padding(.bottom, 16) - } - .onAppear { - guard !self.isPreview else { return } - self.refreshGatewayStatus() - } - .onChange(of: self.state.canvasEnabled) { _, enabled in - if !enabled { - CanvasManager.shared.hideAll() - } - } - } - - private var activeBinding: Binding { - Binding( - get: { !self.state.isPaused }, - set: { self.state.isPaused = !$0 }) - } - - private var connectionSection: some View { - VStack(alignment: .leading, spacing: 10) { - Text("OpenClaw runs") - .font(.title3.weight(.semibold)) - .frame(maxWidth: .infinity, alignment: .leading) - - Picker("Mode", selection: self.$state.connectionMode) { - Text("Not configured").tag(AppState.ConnectionMode.unconfigured) - Text("Local (this Mac)").tag(AppState.ConnectionMode.local) - Text("Remote (another host)").tag(AppState.ConnectionMode.remote) - } - .pickerStyle(.menu) - .labelsHidden() - .frame(width: 260, alignment: .leading) - - if self.state.connectionMode == .unconfigured { - Text("Pick Local or Remote to start the Gateway.") - .font(.footnote) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - - if self.state.connectionMode == .local { - // In Nix mode, gateway is managed declaratively - no install buttons. - if !self.isNixMode { - self.gatewayInstallerCard - } - TailscaleIntegrationSection( - connectionMode: self.state.connectionMode, - isPaused: self.state.isPaused) - self.healthRow - } - - if self.state.connectionMode == .remote { - self.remoteCard - } - } - } - - private var remoteCard: some View { - VStack(alignment: .leading, spacing: 10) { - self.remoteTransportRow - - if self.state.remoteTransport == .ssh { - self.remoteSshRow - } else { - self.remoteDirectRow - } - - GatewayDiscoveryInlineList( - discovery: self.gatewayDiscovery, - currentTarget: self.state.remoteTarget, - currentUrl: self.state.remoteUrl, - transport: self.state.remoteTransport) - { gateway in - self.applyDiscoveredGateway(gateway) - } - .padding(.leading, self.remoteLabelWidth + 10) - - self.remoteStatusView - .padding(.leading, self.remoteLabelWidth + 10) - - if self.state.remoteTransport == .ssh { - DisclosureGroup(isExpanded: self.$showRemoteAdvanced) { - VStack(alignment: .leading, spacing: 8) { - LabeledContent("Identity file") { - TextField("/Users/you/.ssh/id_ed25519", text: self.$state.remoteIdentity) - .textFieldStyle(.roundedBorder) - .frame(width: 280) - } - LabeledContent("Project root") { - TextField("/home/you/Projects/openclaw", text: self.$state.remoteProjectRoot) - .textFieldStyle(.roundedBorder) - .frame(width: 280) - } - LabeledContent("CLI path") { - TextField("/Applications/OpenClaw.app/.../openclaw", text: self.$state.remoteCliPath) - .textFieldStyle(.roundedBorder) - .frame(width: 280) - } - } - .padding(.top, 4) - } label: { - Text("Advanced") - .font(.callout.weight(.semibold)) - } - } - - // Diagnostics - VStack(alignment: .leading, spacing: 4) { - Text("Control channel") - .font(.caption.weight(.semibold)) - if !self.isControlStatusDuplicate || ControlChannel.shared.lastPingMs != nil { - let status = self.isControlStatusDuplicate ? nil : self.controlStatusLine - let ping = ControlChannel.shared.lastPingMs.map { "Ping \(Int($0)) ms" } - let line = [status, ping].compactMap(\.self).joined(separator: " · ") - if !line.isEmpty { - Text(line) - .font(.caption) - .foregroundStyle(.secondary) - } - } - if let hb = HeartbeatStore.shared.lastEvent { - let ageText = age(from: Date(timeIntervalSince1970: hb.ts / 1000)) - Text("Last heartbeat: \(hb.status) · \(ageText)") - .font(.caption) - .foregroundStyle(.secondary) - } - if let authLabel = ControlChannel.shared.authSourceLabel { - Text(authLabel) - .font(.caption) - .foregroundStyle(.secondary) - } - } - - if self.state.remoteTransport == .ssh { - Text("Tip: enable Tailscale for stable remote access.") - .font(.footnote) - .foregroundStyle(.secondary) - .lineLimit(1) - } else { - Text("Tip: use Tailscale Serve so the gateway has a valid HTTPS cert.") - .font(.footnote) - .foregroundStyle(.secondary) - .lineLimit(2) - } - } - .transition(.opacity) - .onAppear { self.gatewayDiscovery.start() } - .onDisappear { self.gatewayDiscovery.stop() } - } - - private var remoteTransportRow: some View { - HStack(alignment: .center, spacing: 10) { - Text("Transport") - .font(.callout.weight(.semibold)) - .frame(width: self.remoteLabelWidth, alignment: .leading) - Picker("Transport", selection: self.$state.remoteTransport) { - Text("SSH tunnel").tag(AppState.RemoteTransport.ssh) - Text("Direct (ws/wss)").tag(AppState.RemoteTransport.direct) - } - .pickerStyle(.segmented) - .frame(maxWidth: 320) - } - } - - private var remoteSshRow: some View { - let trimmedTarget = self.state.remoteTarget.trimmingCharacters(in: .whitespacesAndNewlines) - let validationMessage = CommandResolver.sshTargetValidationMessage(trimmedTarget) - let canTest = !trimmedTarget.isEmpty && validationMessage == nil - - return VStack(alignment: .leading, spacing: 4) { - HStack(alignment: .center, spacing: 10) { - Text("SSH target") - .font(.callout.weight(.semibold)) - .frame(width: self.remoteLabelWidth, alignment: .leading) - TextField("user@host[:22]", text: self.$state.remoteTarget) - .textFieldStyle(.roundedBorder) - .frame(maxWidth: .infinity) - Button { - Task { await self.testRemote() } - } label: { - if self.remoteStatus == .checking { - ProgressView().controlSize(.small) - } else { - Text("Test remote") - } - } - .buttonStyle(.borderedProminent) - .disabled(self.remoteStatus == .checking || !canTest) - } - if let validationMessage { - Text(validationMessage) - .font(.caption) - .foregroundStyle(.red) - .padding(.leading, self.remoteLabelWidth + 10) - } - } - } - - private var remoteDirectRow: some View { - VStack(alignment: .leading, spacing: 6) { - HStack(alignment: .center, spacing: 10) { - Text("Gateway") - .font(.callout.weight(.semibold)) - .frame(width: self.remoteLabelWidth, alignment: .leading) - TextField("wss://gateway.example.ts.net", text: self.$state.remoteUrl) - .textFieldStyle(.roundedBorder) - .frame(maxWidth: .infinity) - Button { - Task { await self.testRemote() } - } label: { - if self.remoteStatus == .checking { - ProgressView().controlSize(.small) - } else { - Text("Test remote") - } - } - .buttonStyle(.borderedProminent) - .disabled(self.remoteStatus == .checking || self.state.remoteUrl - .trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) - } - Text( - "Direct mode requires wss:// for remote hosts. ws:// is only allowed for localhost/127.0.0.1." - ) - .font(.caption) - .foregroundStyle(.secondary) - .padding(.leading, self.remoteLabelWidth + 10) - } - } - - private var controlStatusLine: String { - switch ControlChannel.shared.state { - case .connected: "Connected" - case .connecting: "Connecting…" - case .disconnected: "Disconnected" - case let .degraded(msg): msg - } - } - - @ViewBuilder - private var remoteStatusView: some View { - switch self.remoteStatus { - case .idle: - EmptyView() - case .checking: - Text("Testing…") - .font(.caption) - .foregroundStyle(.secondary) - case .ok: - Label("Ready", systemImage: "checkmark.circle.fill") - .font(.caption) - .foregroundStyle(.green) - case let .failed(message): - Text(message) - .font(.caption) - .foregroundStyle(.secondary) - .lineLimit(2) - } - } - - private var isControlStatusDuplicate: Bool { - guard case let .failed(message) = self.remoteStatus else { return false } - return message == self.controlStatusLine - } - - private var gatewayInstallerCard: some View { - VStack(alignment: .leading, spacing: 8) { - HStack(spacing: 10) { - Circle() - .fill(self.gatewayStatusColor) - .frame(width: 10, height: 10) - Text(self.gatewayStatus.message) - .font(.callout) - .frame(maxWidth: .infinity, alignment: .leading) - } - - if let gatewayVersion = self.gatewayStatus.gatewayVersion, - let required = self.gatewayStatus.requiredGateway, - gatewayVersion != required - { - Text("Installed: \(gatewayVersion) · Required: \(required)") - .font(.caption) - .foregroundStyle(.secondary) - } else if let gatewayVersion = self.gatewayStatus.gatewayVersion { - Text("Gateway \(gatewayVersion) detected") - .font(.caption) - .foregroundStyle(.secondary) - } - - if let node = self.gatewayStatus.nodeVersion { - Text("Node \(node)") - .font(.caption) - .foregroundStyle(.secondary) - } - - if case let .attachedExisting(details) = self.gatewayManager.status { - Text(details ?? "Using existing gateway instance") - .font(.caption) - .foregroundStyle(.secondary) - } - - if let failure = self.gatewayManager.lastFailureReason { - Text("Last failure: \(failure)") - .font(.caption) - .foregroundStyle(.red) - } - - Button("Recheck") { self.refreshGatewayStatus() } - .buttonStyle(.bordered) - - Text("Gateway auto-starts in local mode via launchd (\(gatewayLaunchdLabel)).") - .font(.caption) - .foregroundStyle(.secondary) - .lineLimit(2) - } - .padding(12) - .background(Color.gray.opacity(0.08)) - .cornerRadius(10) - } - - private func refreshGatewayStatus() { - Task { - let status = await Task.detached(priority: .utility) { - GatewayEnvironment.check() - }.value - self.gatewayStatus = status - } - } - - private var gatewayStatusColor: Color { - switch self.gatewayStatus.kind { - case .ok: .green - case .checking: .secondary - case .missingNode, .missingGateway, .incompatible, .error: .orange - } - } - - private var healthCard: some View { - let snapshot = self.healthStore.snapshot - return VStack(alignment: .leading, spacing: 6) { - HStack(spacing: 8) { - Circle() - .fill(self.healthStore.state.tint) - .frame(width: 10, height: 10) - Text(self.healthStore.summaryLine) - .font(.callout.weight(.semibold)) - } - - if let snap = snapshot { - let linkId = snap.channelOrder?.first(where: { - if let summary = snap.channels[$0] { return summary.linked != nil } - return false - }) ?? snap.channels.keys.first(where: { - if let summary = snap.channels[$0] { return summary.linked != nil } - return false - }) - let linkLabel = - linkId.flatMap { snap.channelLabels?[$0] } ?? - linkId?.capitalized ?? - "Link channel" - let linkAge = linkId.flatMap { snap.channels[$0]?.authAgeMs } - Text("\(linkLabel) auth age: \(healthAgeString(linkAge))") - .font(.caption) - .foregroundStyle(.secondary) - Text("Session store: \(snap.sessions.path) (\(snap.sessions.count) entries)") - .font(.caption) - .foregroundStyle(.secondary) - if let recent = snap.sessions.recent.first { - let lastActivity = recent.updatedAt != nil - ? relativeAge(from: Date(timeIntervalSince1970: (recent.updatedAt ?? 0) / 1000)) - : "unknown" - Text("Last activity: \(recent.key) \(lastActivity)") - .font(.caption) - .foregroundStyle(.secondary) - } - Text("Last check: \(relativeAge(from: self.healthStore.lastSuccess))") - .font(.caption) - .foregroundStyle(.secondary) - } else if let error = self.healthStore.lastError { - Text(error) - .font(.caption) - .foregroundStyle(.red) - } else { - Text("Health check pending…") - .font(.caption) - .foregroundStyle(.secondary) - } - - HStack(spacing: 12) { - Button { - Task { await self.healthStore.refresh(onDemand: true) } - } label: { - if self.healthStore.isRefreshing { - ProgressView().controlSize(.small) - } else { - Label("Run Health Check", systemImage: "arrow.clockwise") - } - } - .disabled(self.healthStore.isRefreshing) - - Divider().frame(height: 18) - - Button { - self.revealLogs() - } label: { - Label("Reveal Logs", systemImage: "doc.text.magnifyingglass") - } - } - } - .padding(12) - .background(Color.gray.opacity(0.08)) - .cornerRadius(10) - } -} - -private enum RemoteStatus: Equatable { - case idle - case checking - case ok - case failed(String) -} - -extension GeneralSettings { - private var healthRow: some View { - VStack(alignment: .leading, spacing: 6) { - HStack(spacing: 10) { - Circle() - .fill(self.healthStore.state.tint) - .frame(width: 10, height: 10) - Text(self.healthStore.summaryLine) - .font(.callout) - .frame(maxWidth: .infinity, alignment: .leading) - } - - if let detail = self.healthStore.detailLine { - Text(detail) - .font(.caption) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - - HStack(spacing: 10) { - Button("Retry now") { - Task { await HealthStore.shared.refresh(onDemand: true) } - } - .disabled(self.healthStore.isRefreshing) - - Button("Open logs") { self.revealLogs() } - .buttonStyle(.link) - .foregroundStyle(.secondary) - } - .font(.caption) - } - } - - @MainActor - func testRemote() async { - self.remoteStatus = .checking - let settings = CommandResolver.connectionSettings() - if self.state.remoteTransport == .direct { - let trimmedUrl = self.state.remoteUrl.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmedUrl.isEmpty else { - self.remoteStatus = .failed("Set a gateway URL first") - return - } - guard Self.isValidWsUrl(trimmedUrl) else { - self.remoteStatus = .failed( - "Gateway URL must use wss:// for remote hosts (ws:// only for localhost)" - ) - return - } - } else { - guard !settings.target.isEmpty else { - self.remoteStatus = .failed("Set an SSH target first") - return - } - - // Step 1: basic SSH reachability check - guard let sshCommand = Self.sshCheckCommand( - target: settings.target, - identity: settings.identity) - else { - self.remoteStatus = .failed("SSH target is invalid") - return - } - let sshResult = await ShellExecutor.run( - command: sshCommand, - cwd: nil, - env: nil, - timeout: 8) - - guard sshResult.ok else { - self.remoteStatus = .failed(self.formatSSHFailure(sshResult, target: settings.target)) - return - } - } - - // Step 2: control channel health check - let originalMode = AppStateStore.shared.connectionMode - do { - try await ControlChannel.shared.configure(mode: .remote( - target: settings.target, - identity: settings.identity)) - let data = try await ControlChannel.shared.health(timeout: 10) - if decodeHealthSnapshot(from: data) != nil { - self.remoteStatus = .ok - } else { - self.remoteStatus = .failed("Control channel returned invalid health JSON") - } - } catch { - self.remoteStatus = .failed(error.localizedDescription) - } - - // Restore original mode if we temporarily switched - switch originalMode { - case .remote: - break - case .local: - try? await ControlChannel.shared.configure(mode: .local) - case .unconfigured: - await ControlChannel.shared.disconnect() - } - } - - private static func isValidWsUrl(_ raw: String) -> Bool { - GatewayRemoteConfig.normalizeGatewayUrl(raw) != nil - } - - private static func sshCheckCommand(target: String, identity: String) -> [String]? { - guard let parsed = CommandResolver.parseSSHTarget(target) else { return nil } - let options = [ - "-o", "BatchMode=yes", - "-o", "ConnectTimeout=5", - "-o", "StrictHostKeyChecking=accept-new", - "-o", "UpdateHostKeys=yes", - ] - let args = CommandResolver.sshArguments( - target: parsed, - identity: identity, - options: options, - remoteCommand: ["echo", "ok"]) - return ["/usr/bin/ssh"] + args - } - - private func formatSSHFailure(_ response: Response, target: String) -> String { - let payload = response.payload.flatMap { String(data: $0, encoding: .utf8) } - let trimmed = payload? - .trimmingCharacters(in: .whitespacesAndNewlines) - .split(whereSeparator: \.isNewline) - .joined(separator: " ") - if let trimmed, - trimmed.localizedCaseInsensitiveContains("host key verification failed") - { - let host = CommandResolver.parseSSHTarget(target)?.host ?? target - return "SSH check failed: Host key verification failed. Remove the old key with " + - "`ssh-keygen -R \(host)` and try again." - } - if let trimmed, !trimmed.isEmpty { - if let message = response.message, message.hasPrefix("exit ") { - return "SSH check failed: \(trimmed) (\(message))" - } - return "SSH check failed: \(trimmed)" - } - if let message = response.message { - return "SSH check failed (\(message))" - } - return "SSH check failed" - } - - private func revealLogs() { - let target = LogLocator.bestLogFile() - - if let target { - NSWorkspace.shared.selectFile( - target.path, - inFileViewerRootedAtPath: target.deletingLastPathComponent().path) - return - } - - let alert = NSAlert() - alert.messageText = "Log file not found" - alert.informativeText = """ - Looked for openclaw logs in /tmp/openclaw/. - Run a health check or send a message to generate activity, then try again. - """ - alert.alertStyle = .informational - alert.addButton(withTitle: "OK") - alert.runModal() - } - - private func applyDiscoveredGateway(_ gateway: GatewayDiscoveryModel.DiscoveredGateway) { - MacNodeModeCoordinator.shared.setPreferredGatewayStableID(gateway.stableID) - - if self.state.remoteTransport == .direct { - self.state.remoteUrl = GatewayDiscoveryHelpers.directUrl(for: gateway) ?? "" - } else { - self.state.remoteTarget = GatewayDiscoveryHelpers.sshTarget(for: gateway) ?? "" - } - if let endpoint = GatewayDiscoveryHelpers.serviceEndpoint(for: gateway) { - OpenClawConfigFile.setRemoteGatewayUrl( - host: endpoint.host, - port: endpoint.port) - } else { - OpenClawConfigFile.clearRemoteGatewayUrl() - } - } -} - -private func healthAgeString(_ ms: Double?) -> String { - guard let ms else { return "unknown" } - return msToAge(ms) -} - -#if DEBUG -struct GeneralSettings_Previews: PreviewProvider { - static var previews: some View { - GeneralSettings(state: .preview) - .frame(width: SettingsTab.windowWidth, height: SettingsTab.windowHeight) - .environment(TailscaleService.shared) - } -} - -@MainActor -extension GeneralSettings { - static func exerciseForTesting() { - let state = AppState(preview: true) - state.connectionMode = .remote - state.remoteTransport = .ssh - state.remoteTarget = "user@host:2222" - state.remoteUrl = "wss://gateway.example.ts.net" - state.remoteIdentity = "/tmp/id_ed25519" - state.remoteProjectRoot = "/tmp/openclaw" - state.remoteCliPath = "/tmp/openclaw" - - let view = GeneralSettings(state: state) - view.gatewayStatus = GatewayEnvironmentStatus( - kind: .ok, - nodeVersion: "1.0.0", - gatewayVersion: "1.0.0", - requiredGateway: nil, - message: "Gateway ready") - view.remoteStatus = .failed("SSH failed") - view.showRemoteAdvanced = true - _ = view.body - - state.connectionMode = .unconfigured - _ = view.body - - state.connectionMode = .local - view.gatewayStatus = GatewayEnvironmentStatus( - kind: .error("Gateway offline"), - nodeVersion: nil, - gatewayVersion: nil, - requiredGateway: nil, - message: "Gateway offline") - _ = view.body - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/HealthStore.swift b/apps/macos/Sources/OpenClaw/HealthStore.swift deleted file mode 100644 index 22c1409fca7..00000000000 --- a/apps/macos/Sources/OpenClaw/HealthStore.swift +++ /dev/null @@ -1,301 +0,0 @@ -import Foundation -import Network -import Observation -import SwiftUI - -struct HealthSnapshot: Codable, Sendable { - struct ChannelSummary: Codable, Sendable { - struct Probe: Codable, Sendable { - struct Bot: Codable, Sendable { - let username: String? - } - - struct Webhook: Codable, Sendable { - let url: String? - } - - let ok: Bool? - let status: Int? - let error: String? - let elapsedMs: Double? - let bot: Bot? - let webhook: Webhook? - } - - let configured: Bool? - let linked: Bool? - let authAgeMs: Double? - let probe: Probe? - let lastProbeAt: Double? - } - - struct SessionInfo: Codable, Sendable { - let key: String - let updatedAt: Double? - let age: Double? - } - - struct Sessions: Codable, Sendable { - let path: String - let count: Int - let recent: [SessionInfo] - } - - let ok: Bool? - let ts: Double - let durationMs: Double - let channels: [String: ChannelSummary] - let channelOrder: [String]? - let channelLabels: [String: String]? - let heartbeatSeconds: Int? - let sessions: Sessions -} - -enum HealthState: Equatable { - case unknown - case ok - case linkingNeeded - case degraded(String) - - var tint: Color { - switch self { - case .ok: .green - case .linkingNeeded: .red - case .degraded: .orange - case .unknown: .secondary - } - } -} - -@MainActor -@Observable -final class HealthStore { - static let shared = HealthStore() - - private static let logger = Logger(subsystem: "ai.openclaw", category: "health") - - private(set) var snapshot: HealthSnapshot? - private(set) var lastSuccess: Date? - private(set) var lastError: String? - private(set) var isRefreshing = false - - private var loopTask: Task? - private let refreshInterval: TimeInterval = 60 - - private init() { - // Avoid background health polling in SwiftUI previews and tests. - if !ProcessInfo.processInfo.isPreview, !ProcessInfo.processInfo.isRunningTests { - self.start() - } - } - - /// Test-only escape hatch: the HealthStore is a process-wide singleton but - /// state derivation is pure from `snapshot` + `lastError`. - func __setSnapshotForTest(_ snapshot: HealthSnapshot?, lastError: String? = nil) { - self.snapshot = snapshot - self.lastError = lastError - } - - func start() { - guard self.loopTask == nil else { return } - self.loopTask = Task { [weak self] in - guard let self else { return } - while !Task.isCancelled { - await self.refresh() - try? await Task.sleep(nanoseconds: UInt64(self.refreshInterval * 1_000_000_000)) - } - } - } - - func stop() { - self.loopTask?.cancel() - self.loopTask = nil - } - - func refresh(onDemand: Bool = false) async { - guard !self.isRefreshing else { return } - self.isRefreshing = true - defer { self.isRefreshing = false } - let previousError = self.lastError - - do { - let data = try await ControlChannel.shared.health(timeout: 15) - if let decoded = decodeHealthSnapshot(from: data) { - self.snapshot = decoded - self.lastSuccess = Date() - self.lastError = nil - if previousError != nil { - Self.logger.info("health refresh recovered") - } - } else { - self.lastError = "health output not JSON" - if onDemand { self.snapshot = nil } - if previousError != self.lastError { - Self.logger.warning("health refresh failed: output not JSON") - } - } - } catch { - let desc = error.localizedDescription - self.lastError = desc - if onDemand { self.snapshot = nil } - if previousError != desc { - Self.logger.error("health refresh failed \(desc, privacy: .public)") - } - } - } - - private static func isChannelHealthy(_ summary: HealthSnapshot.ChannelSummary) -> Bool { - guard summary.configured == true else { return false } - // If probe is missing, treat it as "configured but unknown health" (not a hard fail). - return summary.probe?.ok ?? true - } - - private static func describeProbeFailure(_ probe: HealthSnapshot.ChannelSummary.Probe) -> String { - let elapsed = probe.elapsedMs.map { "\(Int($0))ms" } - if let error = probe.error, error.lowercased().contains("timeout") || probe.status == nil { - if let elapsed { return "Health check timed out (\(elapsed))" } - return "Health check timed out" - } - let code = probe.status.map { "status \($0)" } ?? "status unknown" - let reason = probe.error?.isEmpty == false ? probe.error! : "health probe failed" - if let elapsed { return "\(reason) (\(code), \(elapsed))" } - return "\(reason) (\(code))" - } - - private func resolveLinkChannel( - _ snap: HealthSnapshot) -> (id: String, summary: HealthSnapshot.ChannelSummary)? - { - let order = snap.channelOrder ?? Array(snap.channels.keys) - for id in order { - if let summary = snap.channels[id], summary.linked == true { - return (id: id, summary: summary) - } - } - for id in order { - if let summary = snap.channels[id], summary.linked != nil { - return (id: id, summary: summary) - } - } - return nil - } - - private func resolveFallbackChannel( - _ snap: HealthSnapshot, - excluding id: String?) -> (id: String, summary: HealthSnapshot.ChannelSummary)? - { - let order = snap.channelOrder ?? Array(snap.channels.keys) - for channelId in order { - if channelId == id { continue } - guard let summary = snap.channels[channelId] else { continue } - if Self.isChannelHealthy(summary) { - return (id: channelId, summary: summary) - } - } - return nil - } - - var state: HealthState { - if let error = self.lastError, !error.isEmpty { - return .degraded(error) - } - guard let snap = self.snapshot else { return .unknown } - guard let link = self.resolveLinkChannel(snap) else { return .unknown } - if link.summary.linked != true { - // Linking is optional if any other channel is healthy; don't paint the whole app red. - let fallback = self.resolveFallbackChannel(snap, excluding: link.id) - return fallback != nil ? .degraded("Not linked") : .linkingNeeded - } - // A channel can be "linked" but still unhealthy (failed probe / cannot connect). - if let probe = link.summary.probe, probe.ok == false { - return .degraded(Self.describeProbeFailure(probe)) - } - return .ok - } - - var summaryLine: String { - if self.isRefreshing { return "Health check running…" } - if let error = self.lastError { return "Health check failed: \(error)" } - guard let snap = self.snapshot else { return "Health check pending" } - guard let link = self.resolveLinkChannel(snap) else { return "Health check pending" } - if link.summary.linked != true { - 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 openclaw login" - } - return "Not linked — run openclaw login" - } - let auth = link.summary.authAgeMs.map { msToAge($0) } ?? "unknown" - if let probe = link.summary.probe, probe.ok == false { - let status = probe.status.map(String.init) ?? "?" - let suffix = probe.status == nil ? "probe degraded" : "probe degraded · status \(status)" - return "linked · auth \(auth) · \(suffix)" - } - return "linked · auth \(auth)" - } - - /// Short, human-friendly detail for the last failure, used in the UI. - var detailLine: String? { - if let error = self.lastError, !error.isEmpty { - let lower = error.lowercased() - 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 OpenClaw to bring it back." - } - if lower.contains("timeout") { - return "Timed out waiting for the control server; the gateway may be crashed or still starting." - } - return error - } - return nil - } - - func describeFailure(from snap: HealthSnapshot, fallback: String?) -> String { - if let link = self.resolveLinkChannel(snap), link.summary.linked != true { - return "Not linked — run openclaw login" - } - if let link = self.resolveLinkChannel(snap), let probe = link.summary.probe, probe.ok == false { - return Self.describeProbeFailure(probe) - } - if let fallback, !fallback.isEmpty { - return fallback - } - return "health probe failed" - } - - var degradedSummary: String? { - guard case let .degraded(reason) = self.state else { return nil } - if reason == "[object Object]" || reason.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty, - let snap = self.snapshot - { - return self.describeFailure(from: snap, fallback: reason) - } - return reason - } -} - -func msToAge(_ ms: Double) -> String { - let minutes = Int(round(ms / 60000)) - if minutes < 1 { return "just now" } - if minutes < 60 { return "\(minutes)m" } - let hours = Int(round(Double(minutes) / 60)) - if hours < 48 { return "\(hours)h" } - let days = Int(round(Double(hours) / 24)) - return "\(days)d" -} - -/// Decode a health snapshot, tolerating stray log lines before/after the JSON blob. -func decodeHealthSnapshot(from data: Data) -> HealthSnapshot? { - let decoder = JSONDecoder() - if let snap = try? decoder.decode(HealthSnapshot.self, from: data) { - return snap - } - guard let text = String(data: data, encoding: .utf8) else { return nil } - guard let firstBrace = text.firstIndex(of: "{"), let lastBrace = text.lastIndex(of: "}") else { - return nil - } - let slice = text[firstBrace...lastBrace] - let cleaned = Data(slice.utf8) - return try? decoder.decode(HealthSnapshot.self, from: cleaned) -} diff --git a/apps/macos/Sources/OpenClaw/HeartbeatStore.swift b/apps/macos/Sources/OpenClaw/HeartbeatStore.swift deleted file mode 100644 index 6bd7bb52529..00000000000 --- a/apps/macos/Sources/OpenClaw/HeartbeatStore.swift +++ /dev/null @@ -1,39 +0,0 @@ -import Foundation -import Observation -import SwiftUI - -@MainActor -@Observable -final class HeartbeatStore { - static let shared = HeartbeatStore() - - private(set) var lastEvent: ControlHeartbeatEvent? - - private var observer: NSObjectProtocol? - - private init() { - self.observer = NotificationCenter.default.addObserver( - forName: .controlHeartbeat, - object: nil, - queue: .main) - { [weak self] note in - guard let data = note.object as? Data else { return } - if let decoded = try? JSONDecoder().decode(ControlHeartbeatEvent.self, from: data) { - Task { @MainActor in self?.lastEvent = decoded } - } - } - - Task { - if self.lastEvent == nil { - if let evt = try? await ControlChannel.shared.lastHeartbeat() { - self.lastEvent = evt - } - } - } - } - - @MainActor - deinit { - if let observer { NotificationCenter.default.removeObserver(observer) } - } -} diff --git a/apps/macos/Sources/OpenClaw/HostEnvSanitizer.swift b/apps/macos/Sources/OpenClaw/HostEnvSanitizer.swift deleted file mode 100644 index b387c36d3a4..00000000000 --- a/apps/macos/Sources/OpenClaw/HostEnvSanitizer.swift +++ /dev/null @@ -1,57 +0,0 @@ -import Foundation - -enum HostEnvSanitizer { - /// Keep in sync with src/infra/host-env-security-policy.json. - /// Parity is validated by src/infra/host-env-security.policy-parity.test.ts. - private static let blockedKeys: Set = [ - "NODE_OPTIONS", - "NODE_PATH", - "PYTHONHOME", - "PYTHONPATH", - "PERL5LIB", - "PERL5OPT", - "RUBYLIB", - "RUBYOPT", - "BASH_ENV", - "ENV", - "SHELL", - "GCONV_PATH", - "IFS", - "SSLKEYLOGFILE", - ] - - private static let blockedPrefixes: [String] = [ - "DYLD_", - "LD_", - "BASH_FUNC_", - ] - - private static func isBlocked(_ upperKey: String) -> Bool { - if self.blockedKeys.contains(upperKey) { return true } - return self.blockedPrefixes.contains(where: { upperKey.hasPrefix($0) }) - } - - static func sanitize(overrides: [String: String]?) -> [String: String] { - var merged: [String: String] = [:] - for (rawKey, value) in ProcessInfo.processInfo.environment { - let key = rawKey.trimmingCharacters(in: .whitespacesAndNewlines) - guard !key.isEmpty else { continue } - let upper = key.uppercased() - if self.isBlocked(upper) { continue } - merged[key] = value - } - - guard let overrides else { return merged } - for (rawKey, value) in overrides { - let key = rawKey.trimmingCharacters(in: .whitespacesAndNewlines) - guard !key.isEmpty else { continue } - let upper = key.uppercased() - // PATH is part of the security boundary (command resolution + safe-bin checks). Never - // allow request-scoped PATH overrides from agents/gateways. - if upper == "PATH" { continue } - if self.isBlocked(upper) { continue } - merged[key] = value - } - return merged - } -} diff --git a/apps/macos/Sources/OpenClaw/HoverHUD.swift b/apps/macos/Sources/OpenClaw/HoverHUD.swift deleted file mode 100644 index d3482362a0f..00000000000 --- a/apps/macos/Sources/OpenClaw/HoverHUD.swift +++ /dev/null @@ -1,311 +0,0 @@ -import AppKit -import Observation -import QuartzCore -import SwiftUI - -/// Hover-only HUD anchored to the menu bar item. Click expands into full Web Chat. -@MainActor -@Observable -final class HoverHUDController { - static let shared = HoverHUDController() - - struct Model { - var isVisible: Bool = false - var isSuppressed: Bool = false - var hoveringStatusItem: Bool = false - var hoveringPanel: Bool = false - } - - private(set) var model = Model() - - private var window: NSPanel? - private var hostingView: NSHostingView? - private var dismissMonitor: Any? - private var dismissTask: Task? - private var showTask: Task? - private var anchorProvider: (() -> NSRect?)? - - private let width: CGFloat = 360 - private let height: CGFloat = 74 - private let padding: CGFloat = 8 - private let hoverShowDelay: TimeInterval = 0.18 - - func setSuppressed(_ suppressed: Bool) { - self.model.isSuppressed = suppressed - if suppressed { - self.showTask?.cancel() - self.showTask = nil - self.dismiss(reason: "suppressed") - } - } - - func statusItemHoverChanged(inside: Bool, anchorProvider: @escaping () -> NSRect?) { - self.model.hoveringStatusItem = inside - self.anchorProvider = anchorProvider - - guard !self.model.isSuppressed else { return } - - if inside { - self.dismissTask?.cancel() - self.dismissTask = nil - self.showTask?.cancel() - self.showTask = Task { [weak self] in - guard let self else { return } - try? await Task.sleep(nanoseconds: UInt64(self.hoverShowDelay * 1_000_000_000)) - await MainActor.run { [weak self] in - guard let self else { return } - guard !Task.isCancelled else { return } - guard self.model.hoveringStatusItem else { return } - guard !self.model.isSuppressed else { return } - self.present() - } - } - } else { - self.showTask?.cancel() - self.showTask = nil - self.scheduleDismiss() - } - } - - func panelHoverChanged(inside: Bool) { - self.model.hoveringPanel = inside - if inside { - self.dismissTask?.cancel() - self.dismissTask = nil - } else if !self.model.hoveringStatusItem { - self.scheduleDismiss() - } - } - - func openChat() { - guard let anchorProvider = self.anchorProvider else { return } - self.dismiss(reason: "openChat") - Task { @MainActor in - let sessionKey = await WebChatManager.shared.preferredSessionKey() - WebChatManager.shared.togglePanel(sessionKey: sessionKey, anchorProvider: anchorProvider) - } - } - - func dismiss(reason: String = "explicit") { - self.dismissTask?.cancel() - self.dismissTask = nil - self.removeDismissMonitor() - guard let window else { - self.model.isVisible = false - return - } - - if !self.model.isVisible { - window.orderOut(nil) - return - } - - let target = window.frame.offsetBy(dx: 0, dy: 6) - NSAnimationContext.runAnimationGroup { context in - context.duration = 0.14 - context.timingFunction = CAMediaTimingFunction(name: .easeOut) - window.animator().setFrame(target, display: true) - window.animator().alphaValue = 0 - } completionHandler: { - Task { @MainActor in - window.orderOut(nil) - self.model.isVisible = false - } - } - } - - // MARK: - Private - - private func scheduleDismiss() { - self.dismissTask?.cancel() - self.dismissTask = Task { [weak self] in - try? await Task.sleep(nanoseconds: 250_000_000) - await MainActor.run { - guard let self else { return } - if self.model.hoveringStatusItem || self.model.hoveringPanel { return } - self.dismiss(reason: "hoverExit") - } - } - } - - private func present() { - guard !self.model.isSuppressed else { return } - self.ensureWindow() - self.hostingView?.rootView = HoverHUDView(controller: self) - let target = self.targetFrame() - - guard let window else { return } - self.installDismissMonitor() - - if !self.model.isVisible { - self.model.isVisible = true - let start = target.offsetBy(dx: 0, dy: 8) - window.setFrame(start, display: true) - window.alphaValue = 0 - window.orderFrontRegardless() - NSAnimationContext.runAnimationGroup { context in - context.duration = 0.18 - context.timingFunction = CAMediaTimingFunction(name: .easeOut) - window.animator().setFrame(target, display: true) - window.animator().alphaValue = 1 - } - } else { - window.orderFrontRegardless() - self.updateWindowFrame(animate: true) - } - } - - private func ensureWindow() { - if self.window != nil { return } - let panel = NSPanel( - contentRect: NSRect(x: 0, y: 0, width: self.width, height: self.height), - styleMask: [.nonactivatingPanel, .borderless], - backing: .buffered, - defer: false) - panel.isOpaque = false - panel.backgroundColor = .clear - panel.hasShadow = true - panel.level = .statusBar - panel.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary, .transient] - panel.hidesOnDeactivate = false - panel.isMovable = false - panel.isFloatingPanel = true - panel.becomesKeyOnlyIfNeeded = true - panel.titleVisibility = .hidden - panel.titlebarAppearsTransparent = true - - let host = NSHostingView(rootView: HoverHUDView(controller: self)) - host.translatesAutoresizingMaskIntoConstraints = false - panel.contentView = host - self.hostingView = host - self.window = panel - } - - private func targetFrame() -> NSRect { - guard let anchor = self.anchorProvider?() else { - return WindowPlacement.topRightFrame( - size: NSSize(width: self.width, height: self.height), - padding: self.padding) - } - - let screen = NSScreen.screens.first { screen in - screen.frame.contains(anchor.origin) || screen.frame.contains(NSPoint(x: anchor.midX, y: anchor.midY)) - } ?? NSScreen.main - - let bounds = (screen?.visibleFrame ?? .zero).insetBy(dx: self.padding, dy: self.padding) - return WindowPlacement.anchoredBelowFrame( - size: NSSize(width: self.width, height: self.height), - anchor: anchor, - padding: self.padding, - in: bounds) - } - - private func updateWindowFrame(animate: Bool = false) { - guard let window else { return } - let frame = self.targetFrame() - if animate { - NSAnimationContext.runAnimationGroup { context in - context.duration = 0.12 - context.timingFunction = CAMediaTimingFunction(name: .easeOut) - window.animator().setFrame(frame, display: true) - } - } else { - window.setFrame(frame, display: true) - } - } - - private func installDismissMonitor() { - if ProcessInfo.processInfo.isRunningTests { return } - guard self.dismissMonitor == nil, let window else { return } - self.dismissMonitor = NSEvent.addGlobalMonitorForEvents(matching: [ - .leftMouseDown, - .rightMouseDown, - .otherMouseDown, - ]) { [weak self] _ in - guard let self, self.model.isVisible else { return } - let pt = NSEvent.mouseLocation - if !window.frame.contains(pt) { - Task { @MainActor in self.dismiss(reason: "outsideClick") } - } - } - } - - private func removeDismissMonitor() { - if let monitor = self.dismissMonitor { - NSEvent.removeMonitor(monitor) - self.dismissMonitor = nil - } - } -} - -private struct HoverHUDView: View { - var controller: HoverHUDController - private let activityStore = WorkActivityStore.shared - - private var statusTitle: String { - if self.activityStore.iconState.isWorking { return "Working" } - return "Idle" - } - - private var detail: String { - if let current = self.activityStore.current?.label, !current.isEmpty { return current } - if let last = self.activityStore.lastToolLabel, !last.isEmpty { return last } - return "No recent activity" - } - - private var symbolName: String { - if self.activityStore.iconState.isWorking { - return self.activityStore.iconState.badgeSymbolName - } - return "moon.zzz.fill" - } - - private var dotColor: Color { - if self.activityStore.iconState.isWorking { - return Color(nsColor: NSColor.systemGreen.withAlphaComponent(0.7)) - } - return .secondary - } - - var body: some View { - HStack(alignment: .top, spacing: 10) { - Circle() - .fill(self.dotColor) - .frame(width: 7, height: 7) - .padding(.top, 5) - - VStack(alignment: .leading, spacing: 4) { - Text(self.statusTitle) - .font(.system(size: 13, weight: .semibold)) - .foregroundStyle(.primary) - Text(self.detail) - .font(.system(size: 12)) - .foregroundStyle(.secondary) - .lineLimit(2) - .truncationMode(.middle) - .fixedSize(horizontal: false, vertical: true) - } - - Spacer(minLength: 8) - - Image(systemName: self.symbolName) - .font(.system(size: 14, weight: .semibold)) - .foregroundStyle(.secondary) - .padding(.top, 1) - } - .padding(12) - .background( - RoundedRectangle(cornerRadius: 14, style: .continuous) - .fill(.regularMaterial)) - .overlay( - RoundedRectangle(cornerRadius: 14, style: .continuous) - .strokeBorder(Color.black.opacity(0.10), lineWidth: 1)) - .contentShape(Rectangle()) - .onHover { inside in - self.controller.panelHoverChanged(inside: inside) - } - .onTapGesture { - self.controller.openChat() - } - } -} diff --git a/apps/macos/Sources/OpenClaw/IconState.swift b/apps/macos/Sources/OpenClaw/IconState.swift deleted file mode 100644 index c2eab0e5010..00000000000 --- a/apps/macos/Sources/OpenClaw/IconState.swift +++ /dev/null @@ -1,113 +0,0 @@ -import Foundation -import SwiftUI - -enum SessionRole { - case main - case other -} - -enum ToolKind: String, Codable { - case bash, read, write, edit, attach, other -} - -enum ActivityKind: Codable, Equatable { - case job - case tool(ToolKind) -} - -enum IconState: Equatable { - case idle - case workingMain(ActivityKind) - case workingOther(ActivityKind) - case overridden(ActivityKind) - - enum BadgeProminence: Equatable { - case primary - case secondary - case overridden - } - - var badgeSymbolName: String { - switch self.activity { - case .tool(.bash): "chevron.left.slash.chevron.right" - case .tool(.read): "doc" - case .tool(.write): "pencil" - case .tool(.edit): "pencil.tip" - case .tool(.attach): "paperclip" - case .tool(.other), .job: "gearshape.fill" - } - } - - var badgeProminence: BadgeProminence? { - switch self { - case .idle: nil - case .workingMain: .primary - case .workingOther: .secondary - case .overridden: .overridden - } - } - - var isWorking: Bool { - switch self { - case .idle: false - default: true - } - } - - private var activity: ActivityKind { - switch self { - case let .workingMain(kind), - let .workingOther(kind), - let .overridden(kind): - kind - case .idle: - .job - } - } -} - -enum IconOverrideSelection: String, CaseIterable, Identifiable { - case system - case idle - case mainBash, mainRead, mainWrite, mainEdit, mainOther - case otherBash, otherRead, otherWrite, otherEdit, otherOther - - var id: String { - self.rawValue - } - - var label: String { - switch self { - case .system: "System (auto)" - case .idle: "Idle" - case .mainBash: "Working main – bash" - case .mainRead: "Working main – read" - case .mainWrite: "Working main – write" - case .mainEdit: "Working main – edit" - case .mainOther: "Working main – other" - case .otherBash: "Working other – bash" - case .otherRead: "Working other – read" - case .otherWrite: "Working other – write" - case .otherEdit: "Working other – edit" - case .otherOther: "Working other – other" - } - } - - func toIconState() -> IconState { - let map: (ToolKind) -> ActivityKind = { .tool($0) } - switch self { - case .system: return .idle - case .idle: return .idle - case .mainBash: return .workingMain(map(.bash)) - case .mainRead: return .workingMain(map(.read)) - case .mainWrite: return .workingMain(map(.write)) - case .mainEdit: return .workingMain(map(.edit)) - case .mainOther: return .workingMain(map(.other)) - case .otherBash: return .workingOther(map(.bash)) - case .otherRead: return .workingOther(map(.read)) - case .otherWrite: return .workingOther(map(.write)) - case .otherEdit: return .workingOther(map(.edit)) - case .otherOther: return .workingOther(map(.other)) - } - } -} diff --git a/apps/macos/Sources/OpenClaw/InstancesSettings.swift b/apps/macos/Sources/OpenClaw/InstancesSettings.swift deleted file mode 100644 index 0c992c6970f..00000000000 --- a/apps/macos/Sources/OpenClaw/InstancesSettings.swift +++ /dev/null @@ -1,479 +0,0 @@ -import AppKit -import SwiftUI - -struct InstancesSettings: View { - var store: InstancesStore - - init(store: InstancesStore = .shared) { - self.store = store - } - - var body: some View { - VStack(alignment: .leading, spacing: 12) { - self.header - if let err = store.lastError { - Text("Error: \(err)") - .foregroundStyle(.red) - } else if let info = store.statusMessage { - Text(info) - .foregroundStyle(.secondary) - } - if self.store.instances.isEmpty { - Text("No instances reported yet.") - .foregroundStyle(.secondary) - } else { - List(self.store.instances) { inst in - self.instanceRow(inst) - } - .listStyle(.inset) - } - Spacer() - } - .onAppear { self.store.start() } - .onDisappear { self.store.stop() } - } - - private var header: some View { - HStack { - VStack(alignment: .leading, spacing: 4) { - Text("Connected Instances") - .font(.headline) - Text("Latest presence beacons from OpenClaw nodes. Updated periodically.") - .font(.footnote) - .foregroundStyle(.secondary) - } - Spacer() - if self.store.isLoading { - ProgressView() - } else { - Button { - Task { await self.store.refresh() } - } label: { - Label("Refresh", systemImage: "arrow.clockwise") - } - .buttonStyle(.bordered) - .help("Refresh") - } - } - } - - @ViewBuilder - private func instanceRow(_ inst: InstanceInfo) -> some View { - let isGateway = (inst.mode ?? "").trimmingCharacters(in: .whitespacesAndNewlines).lowercased() == "gateway" - let prettyPlatform = inst.platform.flatMap { self.prettyPlatform($0) } - let device = DeviceModelCatalog.presentation( - deviceFamily: inst.deviceFamily, - modelIdentifier: inst.modelIdentifier) - - HStack(alignment: .top, spacing: 12) { - self.leadingDeviceIcon(inst, device: device) - .frame(width: 28, height: 28, alignment: .center) - .padding(.top, 1) - - VStack(alignment: .leading, spacing: 4) { - HStack(spacing: 8) { - Text(inst.host ?? "unknown host").font(.subheadline.bold()) - self.presenceIndicator(inst) - if let ip = inst.ip { Text("(") + Text(ip).monospaced() + Text(")") } - } - - HStack(spacing: 8) { - if let version = inst.version { - self.label(icon: "shippingbox", text: version) - } - - if let device { - // Avoid showing generic "Mac"/"iPhone"/etc; prefer the concrete model name. - let family = (inst.deviceFamily ?? "").trimmingCharacters(in: .whitespacesAndNewlines) - let isGeneric = !family.isEmpty && device.title == family - if !isGeneric { - if let prettyPlatform { - self.label(icon: device.symbol, text: "\(device.title) · \(prettyPlatform)") - } else { - self.label(icon: device.symbol, text: device.title) - } - } else if let prettyPlatform, let platform = inst.platform { - self.label(icon: self.platformIcon(platform), text: prettyPlatform) - } - } else if let prettyPlatform, let platform = inst.platform { - self.label(icon: self.platformIcon(platform), text: prettyPlatform) - } - - if let mode = inst.mode { self.label(icon: "network", text: mode) } - } - .layoutPriority(1) - - if !isGateway, self.shouldShowUpdateRow(inst) { - HStack(spacing: 8) { - Spacer(minLength: 0) - - // Last local input is helpful for interactive nodes, but noisy/meaningless for the gateway. - if let secs = inst.lastInputSeconds { - self.label(icon: "clock", text: "\(secs)s ago") - } - - if let update = self.updateSummaryText(inst, isGateway: isGateway) { - self.label(icon: "arrow.clockwise", text: update) - .help(self.presenceUpdateSourceHelp(inst.reason ?? "")) - } - } - .foregroundStyle(.secondary) - } - } - } - .padding(.vertical, 6) - .help(inst.text) - .contextMenu { - Button("Copy Debug Summary") { - NSPasteboard.general.clearContents() - NSPasteboard.general.setString(inst.text, forType: .string) - } - } - } - - private func label(icon: String?, text: String) -> some View { - HStack(spacing: 4) { - if let icon { - if icon == Self.androidSymbolToken { - AndroidMark() - .foregroundStyle(.secondary) - .frame(width: 12, height: 12, alignment: .center) - } else if self.isSystemSymbolAvailable(icon) { - Image(systemName: icon).foregroundStyle(.secondary).font(.caption) - } - } - Text(text) - } - .font(.footnote) - } - - private func presenceIndicator(_ inst: InstanceInfo) -> some View { - let status = self.presenceStatus(for: inst) - return HStack(spacing: 4) { - Circle() - .fill(status.color) - .frame(width: 6, height: 6) - .accessibilityHidden(true) - Text(status.label) - .foregroundStyle(.secondary) - } - .font(.caption) - .help("Presence updated \(inst.ageDescription).") - .accessibilityLabel("\(status.label) presence") - } - - private func presenceStatus(for inst: InstanceInfo) -> (label: String, color: Color) { - let nowMs = Date().timeIntervalSince1970 * 1000 - let ageSeconds = max(0, Int((nowMs - inst.ts) / 1000)) - if ageSeconds <= 120 { return ("Active", .green) } - if ageSeconds <= 300 { return ("Idle", .yellow) } - return ("Stale", .gray) - } - - @ViewBuilder - private func leadingDeviceIcon(_ inst: InstanceInfo, device: DevicePresentation?) -> some View { - let symbol = self.leadingDeviceSymbol(inst, device: device) - if symbol == Self.androidSymbolToken { - AndroidMark() - .foregroundStyle(.secondary) - .frame(width: 24, height: 24, alignment: .center) - .accessibilityHidden(true) - } else { - Image(systemName: symbol) - .font(.system(size: 26, weight: .regular)) - .foregroundStyle(.secondary) - .accessibilityHidden(true) - } - } - - private static let androidSymbolToken = "android" - - private func leadingDeviceSymbol(_ inst: InstanceInfo, device: DevicePresentation?) -> String { - let family = (inst.deviceFamily ?? "").trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - if family == "android" { - return Self.androidSymbolToken - } - - if let title = device?.title.lowercased() { - if title.contains("mac studio") { - return self.safeSystemSymbol("macstudio", fallback: "desktopcomputer") - } - if title.contains("macbook") { - return self.safeSystemSymbol("laptopcomputer", fallback: "laptopcomputer") - } - if title.contains("ipad") { - return self.safeSystemSymbol("ipad", fallback: "ipad") - } - if title.contains("iphone") { - return self.safeSystemSymbol("iphone", fallback: "iphone") - } - } - - if let symbol = device?.symbol { - return self.safeSystemSymbol(symbol, fallback: "cpu") - } - - if let platform = inst.platform { - return self.safeSystemSymbol(self.platformIcon(platform), fallback: "cpu") - } - - return "cpu" - } - - private func shouldShowUpdateRow(_ inst: InstanceInfo) -> Bool { - if inst.lastInputSeconds != nil { return true } - if self.updateSummaryText(inst, isGateway: false) != nil { return true } - return false - } - - private func safeSystemSymbol(_ preferred: String, fallback: String) -> String { - if self.isSystemSymbolAvailable(preferred) { return preferred } - return fallback - } - - private func isSystemSymbolAvailable(_ name: String) -> Bool { - NSImage(systemSymbolName: name, accessibilityDescription: nil) != nil - } - - private struct AndroidMark: View { - var body: some View { - GeometryReader { geo in - let w = geo.size.width - let h = geo.size.height - let headHeight = h * 0.68 - let headWidth = w * 0.92 - let headY = h * 0.18 - let corner = headHeight * 0.28 - - ZStack { - RoundedRectangle(cornerRadius: corner, style: .continuous) - .frame(width: headWidth, height: headHeight) - .position(x: w / 2, y: headY + headHeight / 2) - - Circle() - .frame(width: max(1, w * 0.1), height: max(1, w * 0.1)) - .position(x: w * 0.38, y: headY + headHeight * 0.55) - .blendMode(.destinationOut) - - Circle() - .frame(width: max(1, w * 0.1), height: max(1, w * 0.1)) - .position(x: w * 0.62, y: headY + headHeight * 0.55) - .blendMode(.destinationOut) - - Rectangle() - .frame(width: max(1, w * 0.08), height: max(1, h * 0.18)) - .rotationEffect(.degrees(-25)) - .position(x: w * 0.34, y: h * 0.12) - - Rectangle() - .frame(width: max(1, w * 0.08), height: max(1, h * 0.18)) - .rotationEffect(.degrees(25)) - .position(x: w * 0.66, y: h * 0.12) - } - .compositingGroup() - } - } - } - - private func platformIcon(_ raw: String) -> String { - let (prefix, _) = self.parsePlatform(raw) - switch prefix { - case "macos": - return "laptopcomputer" - case "ios": - return "iphone" - case "ipados": - return "ipad" - case "tvos": - return "appletv" - case "watchos": - return "applewatch" - default: - return "cpu" - } - } - - private func prettyPlatform(_ raw: String) -> String? { - let (prefix, version) = self.parsePlatform(raw) - if prefix.isEmpty { return nil } - let name: String = switch prefix { - case "macos": "macOS" - case "ios": "iOS" - case "ipados": "iPadOS" - case "tvos": "tvOS" - case "watchos": "watchOS" - default: prefix.prefix(1).uppercased() + prefix.dropFirst() - } - guard let version, !version.isEmpty else { return name } - let parts = version.split(separator: ".").map(String.init) - if parts.count >= 2 { - return "\(name) \(parts[0]).\(parts[1])" - } - return "\(name) \(version)" - } - - private func parsePlatform(_ raw: String) -> (prefix: String, version: String?) { - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty { return ("", nil) } - let parts = trimmed.split(whereSeparator: { $0 == " " || $0 == "\t" }).map(String.init) - let prefix = parts.first?.lowercased() ?? "" - let versionToken = parts.dropFirst().first - return (prefix, versionToken) - } - - private func presenceUpdateSourceShortText(_ reason: String) -> String? { - let trimmed = reason.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return nil } - switch trimmed { - case "self": - return "Self" - case "connect": - return "Connect" - case "disconnect": - return "Disconnect" - case "node-connected": - return "Node connect" - case "node-disconnected": - return "Node disconnect" - case "launch": - return "Launch" - case "periodic": - return "Heartbeat" - case "instances-refresh": - return "Instances" - case "seq gap": - return "Resync" - default: - return trimmed - } - } - - private func updateSummaryText(_ inst: InstanceInfo, isGateway: Bool) -> String? { - // For gateway rows, omit the "updated via/by" provenance entirely. - if isGateway { - return nil - } - - let age = inst.ageDescription.trimmingCharacters(in: .whitespacesAndNewlines) - guard !age.isEmpty else { return nil } - - let source = self.presenceUpdateSourceShortText(inst.reason ?? "") - if let source, !source.isEmpty { - return "\(age) · \(source)" - } - return age - } - - private func presenceUpdateSourceHelp(_ reason: String) -> String { - let trimmed = reason.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty { - return "Why this presence entry was last updated (debug marker)." - } - return "Why this presence entry was last updated (debug marker). Raw: \(trimmed)" - } -} - -#if DEBUG -extension InstancesSettings { - static func exerciseForTesting() { - let view = InstancesSettings(store: InstancesStore(isPreview: true)) - let mac = InstanceInfo( - id: "mac", - host: "studio", - ip: "10.0.0.2", - version: "1.2.3", - platform: "macOS 14.2", - deviceFamily: "Mac", - modelIdentifier: "Mac14,10", - lastInputSeconds: 12, - mode: "local", - reason: "self", - text: "Mac Studio", - ts: 1_700_000_000_000) - let genericIOS = InstanceInfo( - id: "iphone", - host: "phone", - ip: "10.0.0.3", - version: "2.0.0", - platform: "iOS 18.0", - deviceFamily: "iPhone", - modelIdentifier: nil, - lastInputSeconds: 35, - mode: "node", - reason: "connect", - text: "iPhone node", - ts: 1_700_000_100_000) - let android = InstanceInfo( - id: "android", - host: "pixel", - ip: nil, - version: "3.1.0", - platform: "Android 14", - deviceFamily: "Android", - modelIdentifier: nil, - lastInputSeconds: 90, - mode: "node", - reason: "seq gap", - text: "Android node", - ts: 1_700_000_200_000) - let gateway = InstanceInfo( - id: "gateway", - host: "gateway", - ip: "10.0.0.9", - version: "4.0.0", - platform: "Linux", - deviceFamily: nil, - modelIdentifier: nil, - lastInputSeconds: nil, - mode: "gateway", - reason: "periodic", - text: "Gateway", - ts: 1_700_000_300_000) - - _ = view.instanceRow(mac) - _ = view.instanceRow(genericIOS) - _ = view.instanceRow(android) - _ = view.instanceRow(gateway) - - _ = view.leadingDeviceSymbol( - mac, - device: DevicePresentation(title: "Mac Studio", symbol: "macstudio")) - _ = view.leadingDeviceSymbol( - mac, - device: DevicePresentation(title: "MacBook Pro", symbol: "laptopcomputer")) - _ = view.leadingDeviceSymbol(android, device: nil) - _ = view.platformIcon("tvOS 17.1") - _ = view.platformIcon("watchOS 10") - _ = view.platformIcon("unknown 1.0") - _ = view.prettyPlatform("macOS 14.2") - _ = view.prettyPlatform("iOS 18") - _ = view.prettyPlatform("ipados 17.1") - _ = view.prettyPlatform("linux") - _ = view.prettyPlatform(" ") - _ = view.parsePlatform("macOS 14.1") - _ = view.parsePlatform(" ") - _ = view.presenceUpdateSourceShortText("self") - _ = view.presenceUpdateSourceShortText("instances-refresh") - _ = view.presenceUpdateSourceShortText("seq gap") - _ = view.presenceUpdateSourceShortText("custom") - _ = view.presenceUpdateSourceShortText(" ") - _ = view.updateSummaryText(mac, isGateway: false) - _ = view.updateSummaryText(gateway, isGateway: true) - _ = view.presenceUpdateSourceHelp("") - _ = view.presenceUpdateSourceHelp("connect") - _ = view.safeSystemSymbol("not-a-symbol", fallback: "cpu") - _ = view.isSystemSymbolAvailable("sparkles") - _ = view.label(icon: "android", text: "Android") - _ = view.label(icon: "sparkles", text: "Sparkles") - _ = view.label(icon: nil, text: "Plain") - _ = AndroidMark().body - } -} - -struct InstancesSettings_Previews: PreviewProvider { - static var previews: some View { - InstancesSettings(store: .preview()) - .frame(width: SettingsTab.windowWidth, height: SettingsTab.windowHeight) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/InstancesStore.swift b/apps/macos/Sources/OpenClaw/InstancesStore.swift deleted file mode 100644 index 566340337db..00000000000 --- a/apps/macos/Sources/OpenClaw/InstancesStore.swift +++ /dev/null @@ -1,349 +0,0 @@ -import Cocoa -import Foundation -import Observation -import OpenClawKit -import OpenClawProtocol -import OSLog - -struct InstanceInfo: Identifiable, Codable { - let id: String - let host: String? - let ip: String? - let version: String? - let platform: String? - let deviceFamily: String? - let modelIdentifier: String? - let lastInputSeconds: Int? - let mode: String? - let reason: String? - let text: String - let ts: Double - - var ageDescription: String { - let date = Date(timeIntervalSince1970: ts / 1000) - return age(from: date) - } - - var lastInputDescription: String { - guard let secs = lastInputSeconds else { return "unknown" } - return "\(secs)s ago" - } -} - -@MainActor -@Observable -final class InstancesStore { - static let shared = InstancesStore() - let isPreview: Bool - - var instances: [InstanceInfo] = [] - var lastError: String? - var statusMessage: String? - var isLoading = false - - private let logger = Logger(subsystem: "ai.openclaw", category: "instances") - private var task: Task? - private let interval: TimeInterval = 30 - private var eventTask: Task? - private var startCount = 0 - private var lastPresenceById: [String: InstanceInfo] = [:] - private var lastLoginNotifiedAtMs: [String: Double] = [:] - - private struct PresenceEventPayload: Codable { - let presence: [PresenceEntry] - } - - init(isPreview: Bool = false) { - self.isPreview = isPreview - } - - func start() { - guard !self.isPreview else { return } - self.startCount += 1 - guard self.startCount == 1 else { return } - guard self.task == nil else { return } - self.startGatewaySubscription() - self.task = Task.detached { [weak self] in - guard let self else { return } - await self.refresh() - while !Task.isCancelled { - try? await Task.sleep(nanoseconds: UInt64(self.interval * 1_000_000_000)) - await self.refresh() - } - } - } - - func stop() { - guard !self.isPreview else { return } - guard self.startCount > 0 else { return } - self.startCount -= 1 - guard self.startCount == 0 else { return } - self.task?.cancel() - self.task = nil - self.eventTask?.cancel() - self.eventTask = nil - } - - private func startGatewaySubscription() { - self.eventTask?.cancel() - self.eventTask = Task { [weak self] in - guard let self else { return } - let stream = await GatewayConnection.shared.subscribe() - for await push in stream { - if Task.isCancelled { return } - await MainActor.run { [weak self] in - self?.handle(push: push) - } - } - } - } - - private func handle(push: GatewayPush) { - switch push { - case let .event(evt) where evt.event == "presence": - if let payload = evt.payload { - self.handlePresenceEventPayload(payload) - } - case .seqGap: - Task { await self.refresh() } - case let .snapshot(hello): - self.applyPresence(hello.snapshot.presence) - default: - break - } - } - - func refresh() async { - if self.isLoading { return } - self.statusMessage = nil - self.isLoading = true - defer { self.isLoading = false } - do { - PresenceReporter.shared.sendImmediate(reason: "instances-refresh") - let data = try await ControlChannel.shared.request(method: "system-presence") - self.lastPayload = data - if data.isEmpty { - self.logger.error("instances fetch returned empty payload") - self.instances = [self.localFallbackInstance(reason: "no presence payload")] - self.lastError = nil - self.statusMessage = "No presence payload from gateway; showing local fallback + health probe." - await self.probeHealthIfNeeded(reason: "no payload") - return - } - let decoded = try JSONDecoder().decode([PresenceEntry].self, from: data) - let withIDs = self.normalizePresence(decoded) - if withIDs.isEmpty { - self.instances = [self.localFallbackInstance(reason: "no presence entries")] - self.lastError = nil - self.statusMessage = "Presence list was empty; showing local fallback + health probe." - await self.probeHealthIfNeeded(reason: "empty list") - } else { - self.instances = withIDs - self.lastError = nil - self.statusMessage = nil - } - } catch { - self.logger.error( - """ - instances fetch failed: \(error.localizedDescription, privacy: .public) \ - len=\(self.lastPayload?.count ?? 0, privacy: .public) \ - utf8=\(self.snippet(self.lastPayload), privacy: .public) - """) - self.instances = [self.localFallbackInstance(reason: "presence decode failed")] - self.lastError = nil - self.statusMessage = "Presence data invalid; showing local fallback + health probe." - await self.probeHealthIfNeeded(reason: "decode failed") - } - } - - private func localFallbackInstance(reason: String) -> InstanceInfo { - let host = Host.current().localizedName ?? "this-mac" - let ip = SystemPresenceInfo.primaryIPv4Address() - let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String - let osVersion = ProcessInfo.processInfo.operatingSystemVersion - let platform = "macos \(osVersion.majorVersion).\(osVersion.minorVersion).\(osVersion.patchVersion)" - let text = "Local node: \(host)\(ip.map { " (\($0))" } ?? "") · app \(version ?? "dev")" - let ts = Date().timeIntervalSince1970 * 1000 - return InstanceInfo( - id: "local-\(host)", - host: host, - ip: ip, - version: version, - platform: platform, - deviceFamily: "Mac", - modelIdentifier: InstanceIdentity.modelIdentifier, - lastInputSeconds: SystemPresenceInfo.lastInputSeconds(), - mode: "local", - reason: reason, - text: text, - ts: ts) - } - - // MARK: - Helpers - - /// Keep the last raw payload for logging. - private var lastPayload: Data? - - private func snippet(_ data: Data?, limit: Int = 256) -> String { - guard let data else { return "" } - if data.isEmpty { return "" } - let prefix = data.prefix(limit) - if let asString = String(data: prefix, encoding: .utf8) { - return asString.replacingOccurrences(of: "\n", with: " ") - } - return "<\(data.count) bytes non-utf8>" - } - - private func probeHealthIfNeeded(reason: String? = nil) async { - do { - let data = try await ControlChannel.shared.health(timeout: 8) - guard let snap = decodeHealthSnapshot(from: data) else { return } - let linkId = snap.channelOrder?.first(where: { - if let summary = snap.channels[$0] { return summary.linked != nil } - return false - }) ?? snap.channels.keys.first(where: { - if let summary = snap.channels[$0] { return summary.linked != nil } - return false - }) - let linked = linkId.flatMap { snap.channels[$0]?.linked } ?? false - let linkLabel = - linkId.flatMap { snap.channelLabels?[$0] } ?? - linkId?.capitalized ?? - "channel" - let entry = InstanceInfo( - id: "health-\(snap.ts)", - host: "gateway (health)", - ip: nil, - version: nil, - platform: nil, - deviceFamily: nil, - modelIdentifier: nil, - lastInputSeconds: nil, - mode: "health", - reason: "health probe", - text: "Health ok · \(linkLabel) linked=\(linked)", - ts: snap.ts) - if !self.instances.contains(where: { $0.id == entry.id }) { - self.instances.insert(entry, at: 0) - } - self.lastError = nil - self.statusMessage = - "Presence unavailable (\(reason ?? "refresh")); showing health probe + local fallback." - } catch { - self.logger.error("instances health probe failed: \(error.localizedDescription, privacy: .public)") - if let reason { - self.statusMessage = - "Presence unavailable (\(reason)), health probe failed: \(error.localizedDescription)" - } - } - } - - private func decodeAndApplyPresenceData(_ data: Data) { - do { - let decoded = try JSONDecoder().decode([PresenceEntry].self, from: data) - self.applyPresence(decoded) - } catch { - self.logger.error("presence decode from event failed: \(error.localizedDescription, privacy: .public)") - self.lastError = error.localizedDescription - } - } - - func handlePresenceEventPayload(_ payload: OpenClawProtocol.AnyCodable) { - do { - let wrapper = try GatewayPayloadDecoding.decode(payload, as: PresenceEventPayload.self) - self.applyPresence(wrapper.presence) - } catch { - self.logger.error("presence event decode failed: \(error.localizedDescription, privacy: .public)") - self.lastError = error.localizedDescription - } - } - - private func normalizePresence(_ entries: [PresenceEntry]) -> [InstanceInfo] { - entries.map { entry -> InstanceInfo in - let key = entry.instanceid ?? entry.host ?? entry.ip ?? entry.text ?? "entry-\(entry.ts)" - return InstanceInfo( - id: key, - host: entry.host, - ip: entry.ip, - version: entry.version, - platform: entry.platform, - deviceFamily: entry.devicefamily, - modelIdentifier: entry.modelidentifier, - lastInputSeconds: entry.lastinputseconds, - mode: entry.mode, - reason: entry.reason, - text: entry.text ?? "Unnamed node", - ts: Double(entry.ts)) - } - } - - private func applyPresence(_ entries: [PresenceEntry]) { - let withIDs = self.normalizePresence(entries) - self.notifyOnNodeLogin(withIDs) - self.lastPresenceById = Dictionary(uniqueKeysWithValues: withIDs.map { ($0.id, $0) }) - self.instances = withIDs - self.statusMessage = nil - self.lastError = nil - } - - private func notifyOnNodeLogin(_ instances: [InstanceInfo]) { - for inst in instances { - guard let reason = inst.reason?.trimmingCharacters(in: .whitespacesAndNewlines) else { continue } - guard reason == "node-connected" else { continue } - if let mode = inst.mode?.lowercased(), mode == "local" { continue } - - let previous = self.lastPresenceById[inst.id] - if previous?.reason == "node-connected", previous?.ts == inst.ts { continue } - - let lastNotified = self.lastLoginNotifiedAtMs[inst.id] ?? 0 - if inst.ts <= lastNotified { continue } - self.lastLoginNotifiedAtMs[inst.id] = inst.ts - - let name = inst.host?.trimmingCharacters(in: .whitespacesAndNewlines) - let device = name?.isEmpty == false ? name! : inst.id - Task { @MainActor in - _ = await NotificationManager().send( - title: "Node connected", - body: device, - sound: nil, - priority: .active) - } - } - } -} - -extension InstancesStore { - static func preview(instances: [InstanceInfo] = [ - InstanceInfo( - id: "local", - host: "steipete-mac", - ip: "10.0.0.12", - version: "1.2.3", - platform: "macos 26.2.0", - deviceFamily: "Mac", - modelIdentifier: "Mac16,6", - lastInputSeconds: 12, - mode: "local", - reason: "preview", - text: "Local node: steipete-mac (10.0.0.12) · app 1.2.3", - ts: Date().timeIntervalSince1970 * 1000), - InstanceInfo( - id: "gateway", - host: "gateway", - ip: "100.64.0.2", - version: "1.2.3", - platform: "linux 6.6.0", - deviceFamily: "Linux", - modelIdentifier: "x86_64", - lastInputSeconds: 45, - mode: "remote", - reason: "preview", - text: "Gateway node · tunnel ok", - ts: Date().timeIntervalSince1970 * 1000 - 45000), - ]) -> InstancesStore { - let store = InstancesStore(isPreview: true) - store.instances = instances - store.statusMessage = "Preview data" - return store - } -} diff --git a/apps/macos/Sources/OpenClaw/LaunchAgentManager.swift b/apps/macos/Sources/OpenClaw/LaunchAgentManager.swift deleted file mode 100644 index af318b330d4..00000000000 --- a/apps/macos/Sources/OpenClaw/LaunchAgentManager.swift +++ /dev/null @@ -1,78 +0,0 @@ -import Foundation - -enum LaunchAgentManager { - private static var plistURL: URL { - FileManager().homeDirectoryForCurrentUser - .appendingPathComponent("Library/LaunchAgents/ai.openclaw.mac.plist") - } - - static func status() async -> Bool { - guard FileManager().fileExists(atPath: self.plistURL.path) else { return false } - let result = await self.runLaunchctl(["print", "gui/\(getuid())/\(launchdLabel)"]) - return result == 0 - } - - static func set(enabled: Bool, bundlePath: String) async { - if enabled { - self.writePlist(bundlePath: bundlePath) - _ = await self.runLaunchctl(["bootout", "gui/\(getuid())/\(launchdLabel)"]) - _ = await self.runLaunchctl(["bootstrap", "gui/\(getuid())", self.plistURL.path]) - _ = await self.runLaunchctl(["kickstart", "-k", "gui/\(getuid())/\(launchdLabel)"]) - } else { - // Disable autostart going forward but leave the current app running. - // bootout would terminate the launchd job immediately (and crash the app if launched via agent). - try? FileManager().removeItem(at: self.plistURL) - } - } - - private static func writePlist(bundlePath: String) { - let plist = """ - - - - - Label - ai.openclaw.mac - ProgramArguments - - \(bundlePath)/Contents/MacOS/OpenClaw - - WorkingDirectory - \(FileManager().homeDirectoryForCurrentUser.path) - RunAtLoad - - KeepAlive - - EnvironmentVariables - - PATH - \(CommandResolver.preferredPaths().joined(separator: ":")) - - StandardOutPath - \(LogLocator.launchdLogPath) - StandardErrorPath - \(LogLocator.launchdLogPath) - - - """ - try? plist.write(to: self.plistURL, atomically: true, encoding: .utf8) - } - - @discardableResult - private static func runLaunchctl(_ args: [String]) async -> Int32 { - await Task.detached(priority: .utility) { () -> Int32 in - let process = Process() - process.launchPath = "/bin/launchctl" - process.arguments = args - let pipe = Pipe() - process.standardOutput = pipe - process.standardError = pipe - do { - _ = try process.runAndReadToEnd(from: pipe) - return process.terminationStatus - } catch { - return -1 - } - }.value - } -} diff --git a/apps/macos/Sources/OpenClaw/Launchctl.swift b/apps/macos/Sources/OpenClaw/Launchctl.swift deleted file mode 100644 index cc50fd48ac7..00000000000 --- a/apps/macos/Sources/OpenClaw/Launchctl.swift +++ /dev/null @@ -1,87 +0,0 @@ -import Foundation - -enum Launchctl { - struct Result: Sendable { - let status: Int32 - let output: String - } - - @discardableResult - static func run(_ args: [String]) async -> Result { - await Task.detached(priority: .utility) { () -> Result in - let process = Process() - process.launchPath = "/bin/launchctl" - process.arguments = args - let pipe = Pipe() - process.standardOutput = pipe - process.standardError = pipe - do { - let data = try process.runAndReadToEnd(from: pipe) - let output = String(data: data, encoding: .utf8) ?? "" - return Result(status: process.terminationStatus, output: output) - } catch { - return Result(status: -1, output: error.localizedDescription) - } - }.value - } -} - -struct LaunchAgentPlistSnapshot: Equatable, Sendable { - let programArguments: [String] - let environment: [String: String] - let stdoutPath: String? - let stderrPath: String? - - let port: Int? - let bind: String? - let token: String? - let password: String? -} - -enum LaunchAgentPlist { - static func snapshot(url: URL) -> LaunchAgentPlistSnapshot? { - guard let data = try? Data(contentsOf: url) else { return nil } - let rootAny: Any - do { - rootAny = try PropertyListSerialization.propertyList( - from: data, - options: [], - format: nil) - } catch { - return nil - } - guard let root = rootAny as? [String: Any] else { return nil } - let programArguments = root["ProgramArguments"] as? [String] ?? [] - let env = root["EnvironmentVariables"] as? [String: String] ?? [:] - let stdoutPath = (root["StandardOutPath"] as? String)? - .trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty - let stderrPath = (root["StandardErrorPath"] as? String)? - .trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty - let port = Self.extractFlagInt(programArguments, flag: "--port") - let bind = Self.extractFlagString(programArguments, flag: "--bind")?.lowercased() - let token = env["OPENCLAW_GATEWAY_TOKEN"]?.trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty - let password = env["OPENCLAW_GATEWAY_PASSWORD"]?.trimmingCharacters(in: .whitespacesAndNewlines).nonEmpty - return LaunchAgentPlistSnapshot( - programArguments: programArguments, - environment: env, - stdoutPath: stdoutPath, - stderrPath: stderrPath, - port: port, - bind: bind, - token: token, - password: password) - } - - private static func extractFlagInt(_ args: [String], flag: String) -> Int? { - guard let raw = self.extractFlagString(args, flag: flag) else { return nil } - return Int(raw) - } - - private static func extractFlagString(_ args: [String], flag: String) -> String? { - guard let idx = args.firstIndex(of: flag) else { return nil } - let valueIdx = args.index(after: idx) - guard valueIdx < args.endIndex else { return nil } - let token = args[valueIdx].trimmingCharacters(in: .whitespacesAndNewlines) - return token.isEmpty ? nil : token - } -} diff --git a/apps/macos/Sources/OpenClaw/LaunchdManager.swift b/apps/macos/Sources/OpenClaw/LaunchdManager.swift deleted file mode 100644 index 961246f194b..00000000000 --- a/apps/macos/Sources/OpenClaw/LaunchdManager.swift +++ /dev/null @@ -1,20 +0,0 @@ -import Foundation - -enum LaunchdManager { - private static func runLaunchctl(_ args: [String]) { - let process = Process() - process.launchPath = "/bin/launchctl" - process.arguments = args - try? process.run() - } - - static func startOpenClaw() { - let userTarget = "gui/\(getuid())/\(launchdLabel)" - self.runLaunchctl(["kickstart", "-k", userTarget]) - } - - static func stopOpenClaw() { - let userTarget = "gui/\(getuid())/\(launchdLabel)" - self.runLaunchctl(["stop", userTarget]) - } -} diff --git a/apps/macos/Sources/OpenClaw/LogLocator.swift b/apps/macos/Sources/OpenClaw/LogLocator.swift deleted file mode 100644 index b504ab02ace..00000000000 --- a/apps/macos/Sources/OpenClaw/LogLocator.swift +++ /dev/null @@ -1,59 +0,0 @@ -import Foundation - -enum LogLocator { - private static var logDir: URL { - if let override = ProcessInfo.processInfo.environment["OPENCLAW_LOG_DIR"], - !override.isEmpty - { - return URL(fileURLWithPath: override) - } - return URL(fileURLWithPath: "/tmp/openclaw") - } - - private static var stdoutLog: URL { - logDir.appendingPathComponent("openclaw-stdout.log") - } - - private static var gatewayLog: URL { - logDir.appendingPathComponent("openclaw-gateway.log") - } - - private static func ensureLogDirExists() { - try? FileManager().createDirectory(at: self.logDir, withIntermediateDirectories: true) - } - - private static func modificationDate(for url: URL) -> Date { - (try? url.resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate) ?? .distantPast - } - - /// Returns the newest log file under /tmp/openclaw/ (rolling or stdout), or nil if none exist. - static func bestLogFile() -> URL? { - self.ensureLogDirExists() - let fm = FileManager() - let files = (try? fm.contentsOfDirectory( - at: self.logDir, - includingPropertiesForKeys: [.contentModificationDateKey], - options: [.skipsHiddenFiles])) ?? [] - - let prefixes = ["openclaw"] - return files - .filter { file in - prefixes.contains { file.lastPathComponent.hasPrefix($0) } && file.pathExtension == "log" - } - .max { lhs, rhs in - self.modificationDate(for: lhs) < self.modificationDate(for: rhs) - } - } - - /// Path to use for launchd stdout/err. - static var launchdLogPath: String { - self.ensureLogDirExists() - return stdoutLog.path - } - - /// Path to use for the Gateway launchd job stdout/err. - static var launchdGatewayLogPath: String { - self.ensureLogDirExists() - return gatewayLog.path - } -} diff --git a/apps/macos/Sources/OpenClaw/Logging/OpenClawLogging.swift b/apps/macos/Sources/OpenClaw/Logging/OpenClawLogging.swift deleted file mode 100644 index 7692887e6c7..00000000000 --- a/apps/macos/Sources/OpenClaw/Logging/OpenClawLogging.swift +++ /dev/null @@ -1,232 +0,0 @@ -import Foundation -@_exported import Logging -import os -import OSLog - -typealias Logger = Logging.Logger - -enum AppLogSettings { - static let logLevelKey = appLogLevelKey - - static func logLevel() -> Logger.Level { - if let raw = UserDefaults.standard.string(forKey: self.logLevelKey), - let level = Logger.Level(rawValue: raw) - { - return level - } - return .info - } - - static func setLogLevel(_ level: Logger.Level) { - UserDefaults.standard.set(level.rawValue, forKey: self.logLevelKey) - } - - static func fileLoggingEnabled() -> Bool { - UserDefaults.standard.bool(forKey: debugFileLogEnabledKey) - } -} - -enum AppLogLevel: String, CaseIterable, Identifiable { - case trace - case debug - case info - case notice - case warning - case error - case critical - - static let `default`: AppLogLevel = .info - - var id: String { - self.rawValue - } - - var title: String { - switch self { - case .trace: "Trace" - case .debug: "Debug" - case .info: "Info" - case .notice: "Notice" - case .warning: "Warning" - case .error: "Error" - case .critical: "Critical" - } - } -} - -enum OpenClawLogging { - private static let labelSeparator = "::" - - private static let didBootstrap: Void = { - LoggingSystem.bootstrap { label in - let (subsystem, category) = Self.parseLabel(label) - let osHandler = OpenClawOSLogHandler(subsystem: subsystem, category: category) - let fileHandler = OpenClawFileLogHandler(label: label) - return MultiplexLogHandler([osHandler, fileHandler]) - } - }() - - static func bootstrapIfNeeded() { - _ = self.didBootstrap - } - - static func makeLabel(subsystem: String, category: String) -> String { - "\(subsystem)\(self.labelSeparator)\(category)" - } - - static func parseLabel(_ label: String) -> (String, String) { - guard let range = label.range(of: labelSeparator) else { - return ("ai.openclaw", label) - } - let subsystem = String(label[.. Logger.Metadata.Value? { - get { self.metadata[key] } - set { self.metadata[key] = newValue } - } - - func log( - level: Logger.Level, - message: Logger.Message, - metadata: Logger.Metadata?, - source: String, - file: String, - function: String, - line: UInt) - { - let merged = Self.mergeMetadata(self.metadata, metadata) - let rendered = Self.renderMessage(message, metadata: merged) - self.osLogger.log(level: Self.osLogType(for: level), "\(rendered, privacy: .public)") - } - - private static func osLogType(for level: Logger.Level) -> OSLogType { - switch level { - case .trace, .debug: - .debug - case .info, .notice: - .info - case .warning: - .default - case .error: - .error - case .critical: - .fault - } - } - - private static func mergeMetadata( - _ base: Logger.Metadata, - _ extra: Logger.Metadata?) -> Logger.Metadata - { - guard let extra else { return base } - return base.merging(extra, uniquingKeysWith: { _, new in new }) - } - - private static func renderMessage(_ message: Logger.Message, metadata: Logger.Metadata) -> String { - guard !metadata.isEmpty else { return message.description } - let meta = metadata - .sorted(by: { $0.key < $1.key }) - .map { "\($0.key)=\(self.stringify($0.value))" } - .joined(separator: " ") - return "\(message.description) [\(meta)]" - } - - private static func stringify(_ value: Logger.Metadata.Value) -> String { - switch value { - case let .string(text): - text - case let .stringConvertible(value): - String(describing: value) - case let .array(values): - "[" + values.map { self.stringify($0) }.joined(separator: ",") + "]" - case let .dictionary(entries): - "{" + entries.map { "\($0.key)=\(self.stringify($0.value))" }.joined(separator: ",") + "}" - } - } -} - -struct OpenClawFileLogHandler: LogHandler { - let label: String - var metadata: Logger.Metadata = [:] - - var logLevel: Logger.Level { - get { AppLogSettings.logLevel() } - set { AppLogSettings.setLogLevel(newValue) } - } - - subscript(metadataKey key: String) -> Logger.Metadata.Value? { - get { self.metadata[key] } - set { self.metadata[key] = newValue } - } - - func log( - level: Logger.Level, - message: Logger.Message, - metadata: Logger.Metadata?, - source: String, - file: String, - function: String, - line: UInt) - { - guard AppLogSettings.fileLoggingEnabled() else { return } - let (subsystem, category) = OpenClawLogging.parseLabel(self.label) - var fields: [String: String] = [ - "subsystem": subsystem, - "category": category, - "level": level.rawValue, - "source": source, - "file": file, - "function": function, - "line": "\(line)", - ] - let merged = self.metadata.merging(metadata ?? [:], uniquingKeysWith: { _, new in new }) - for (key, value) in merged { - fields["meta.\(key)"] = Self.stringify(value) - } - DiagnosticsFileLog.shared.log(category: category, event: message.description, fields: fields) - } - - private static func stringify(_ value: Logger.Metadata.Value) -> String { - switch value { - case let .string(text): - text - case let .stringConvertible(value): - String(describing: value) - case let .array(values): - "[" + values.map { self.stringify($0) }.joined(separator: ",") + "]" - case let .dictionary(entries): - "{" + entries.map { "\($0.key)=\(self.stringify($0.value))" }.joined(separator: ",") + "}" - } - } -} diff --git a/apps/macos/Sources/OpenClaw/MenuBar.swift b/apps/macos/Sources/OpenClaw/MenuBar.swift deleted file mode 100644 index 00e2a9be0a6..00000000000 --- a/apps/macos/Sources/OpenClaw/MenuBar.swift +++ /dev/null @@ -1,474 +0,0 @@ -import AppKit -import Darwin -import Foundation -import MenuBarExtraAccess -import Observation -import OSLog -import Security -import SwiftUI - -@main -struct OpenClawApp: App { - @NSApplicationDelegateAdaptor(AppDelegate.self) private var delegate - @State private var state: AppState - private static let logger = Logger(subsystem: "ai.openclaw", category: "app") - private let gatewayManager = GatewayProcessManager.shared - private let controlChannel = ControlChannel.shared - private let activityStore = WorkActivityStore.shared - private let connectivityCoordinator = GatewayConnectivityCoordinator.shared - @State private var statusItem: NSStatusItem? - @State private var isMenuPresented = false - @State private var isPanelVisible = false - @State private var tailscaleService = TailscaleService.shared - - @MainActor - private func updateStatusHighlight() { - self.statusItem?.button?.highlight(self.isPanelVisible) - } - - @MainActor - private func updateHoverHUDSuppression() { - HoverHUDController.shared.setSuppressed(self.isMenuPresented || self.isPanelVisible) - } - - init() { - OpenClawLogging.bootstrapIfNeeded() - - Self.applyAttachOnlyOverrideIfNeeded() - _state = State(initialValue: AppStateStore.shared) - } - - var body: some Scene { - MenuBarExtra { MenuContent(state: self.state, updater: self.delegate.updaterController) } label: { - CritterStatusLabel( - isPaused: self.state.isPaused, - isSleeping: self.isGatewaySleeping, - isWorking: self.state.isWorking, - earBoostActive: self.state.earBoostActive, - blinkTick: self.state.blinkTick, - sendCelebrationTick: self.state.sendCelebrationTick, - gatewayStatus: self.gatewayManager.status, - animationsEnabled: self.state.iconAnimationsEnabled && !self.isGatewaySleeping, - iconState: self.effectiveIconState) - } - .menuBarExtraStyle(.menu) - .menuBarExtraAccess(isPresented: self.$isMenuPresented) { item in - self.statusItem = item - MenuSessionsInjector.shared.install(into: item) - self.applyStatusItemAppearance(paused: self.state.isPaused, sleeping: self.isGatewaySleeping) - self.installStatusItemMouseHandler(for: item) - self.updateHoverHUDSuppression() - } - .onChange(of: self.state.isPaused) { _, paused in - self.applyStatusItemAppearance(paused: paused, sleeping: self.isGatewaySleeping) - if self.state.connectionMode == .local { - self.gatewayManager.setActive(!paused) - } else { - self.gatewayManager.stop() - } - } - .onChange(of: self.controlChannel.state) { _, _ in - self.applyStatusItemAppearance(paused: self.state.isPaused, sleeping: self.isGatewaySleeping) - } - .onChange(of: self.gatewayManager.status) { _, _ in - self.applyStatusItemAppearance(paused: self.state.isPaused, sleeping: self.isGatewaySleeping) - } - .onChange(of: self.state.connectionMode) { _, mode in - Task { await ConnectionModeCoordinator.shared.apply(mode: mode, paused: self.state.isPaused) } - CLIInstallPrompter.shared.checkAndPromptIfNeeded(reason: "connection-mode") - } - - Settings { - SettingsRootView(state: self.state, updater: self.delegate.updaterController) - .frame(width: SettingsTab.windowWidth, height: SettingsTab.windowHeight, alignment: .topLeading) - .environment(self.tailscaleService) - } - .defaultSize(width: SettingsTab.windowWidth, height: SettingsTab.windowHeight) - .windowResizability(.contentSize) - .onChange(of: self.isMenuPresented) { _, _ in - self.updateStatusHighlight() - self.updateHoverHUDSuppression() - } - } - - private func applyStatusItemAppearance(paused: Bool, sleeping: Bool) { - self.statusItem?.button?.appearsDisabled = paused || sleeping - } - - private static func applyAttachOnlyOverrideIfNeeded() { - let args = CommandLine.arguments - guard args.contains("--attach-only") || args.contains("--no-launchd") else { return } - if let error = GatewayLaunchAgentManager.setLaunchAgentWriteDisabled(true) { - Self.logger.error("attach-only flag failed: \(error, privacy: .public)") - return - } - Task { - _ = await GatewayLaunchAgentManager.set( - enabled: false, - bundlePath: Bundle.main.bundlePath, - port: GatewayEnvironment.gatewayPort()) - } - Self.logger.info("attach-only flag enabled") - } - - private var isGatewaySleeping: Bool { - if self.state.isPaused { return false } - switch self.state.connectionMode { - case .unconfigured: - return true - case .remote: - if case .connected = self.controlChannel.state { return false } - return true - case .local: - switch self.gatewayManager.status { - case .running, .starting, .attachedExisting: - if case .connected = self.controlChannel.state { return false } - return true - case .failed, .stopped: - return true - } - } - } - - @MainActor - private func installStatusItemMouseHandler(for item: NSStatusItem) { - guard let button = item.button else { return } - if button.subviews.contains(where: { $0 is StatusItemMouseHandlerView }) { return } - - WebChatManager.shared.onPanelVisibilityChanged = { [self] visible in - self.isPanelVisible = visible - self.updateStatusHighlight() - self.updateHoverHUDSuppression() - } - CanvasManager.shared.onPanelVisibilityChanged = { [self] visible in - self.state.canvasPanelVisible = visible - } - CanvasManager.shared.defaultAnchorProvider = { [self] in self.statusButtonScreenFrame() } - - let handler = StatusItemMouseHandlerView() - handler.translatesAutoresizingMaskIntoConstraints = false - handler.onLeftClick = { [self] in - HoverHUDController.shared.dismiss(reason: "statusItemClick") - self.toggleWebChatPanel() - } - handler.onRightClick = { [self] in - HoverHUDController.shared.dismiss(reason: "statusItemRightClick") - WebChatManager.shared.closePanel() - self.isMenuPresented = true - self.updateStatusHighlight() - } - handler.onHoverChanged = { [self] inside in - HoverHUDController.shared.statusItemHoverChanged( - inside: inside, - anchorProvider: { [self] in self.statusButtonScreenFrame() }) - } - - button.addSubview(handler) - NSLayoutConstraint.activate([ - handler.leadingAnchor.constraint(equalTo: button.leadingAnchor), - handler.trailingAnchor.constraint(equalTo: button.trailingAnchor), - handler.topAnchor.constraint(equalTo: button.topAnchor), - handler.bottomAnchor.constraint(equalTo: button.bottomAnchor), - ]) - } - - @MainActor - private func toggleWebChatPanel() { - HoverHUDController.shared.setSuppressed(true) - self.isMenuPresented = false - Task { @MainActor in - let sessionKey = await WebChatManager.shared.preferredSessionKey() - WebChatManager.shared.togglePanel( - sessionKey: sessionKey, - anchorProvider: { [self] in self.statusButtonScreenFrame() }) - } - } - - @MainActor - private func statusButtonScreenFrame() -> NSRect? { - guard let button = self.statusItem?.button, let window = button.window else { return nil } - let inWindow = button.convert(button.bounds, to: nil) - return window.convertToScreen(inWindow) - } - - private var effectiveIconState: IconState { - let selection = self.state.iconOverride - if selection == .system { - return self.activityStore.iconState - } - let overrideState = selection.toIconState() - switch overrideState { - case let .workingMain(kind): return .overridden(kind) - case let .workingOther(kind): return .overridden(kind) - case .idle: return .idle - case let .overridden(kind): return .overridden(kind) - } - } -} - -/// Transparent overlay that intercepts clicks without stealing MenuBarExtra ownership. -private final class StatusItemMouseHandlerView: NSView { - var onLeftClick: (() -> Void)? - var onRightClick: (() -> Void)? - var onHoverChanged: ((Bool) -> Void)? - private var tracking: NSTrackingArea? - - override func mouseDown(with event: NSEvent) { - if let onLeftClick { - onLeftClick() - } else { - super.mouseDown(with: event) - } - } - - override func rightMouseDown(with event: NSEvent) { - self.onRightClick?() - // Do not call super; menu will be driven by isMenuPresented binding. - } - - override func updateTrackingAreas() { - super.updateTrackingAreas() - if let tracking { - self.removeTrackingArea(tracking) - } - let options: NSTrackingArea.Options = [ - .mouseEnteredAndExited, - .activeAlways, - .inVisibleRect, - ] - let area = NSTrackingArea(rect: self.bounds, options: options, owner: self, userInfo: nil) - self.addTrackingArea(area) - self.tracking = area - } - - override func mouseEntered(with event: NSEvent) { - self.onHoverChanged?(true) - } - - override func mouseExited(with event: NSEvent) { - self.onHoverChanged?(false) - } -} - -@MainActor -final class AppDelegate: NSObject, NSApplicationDelegate { - private var state: AppState? - private let webChatAutoLogger = Logger(subsystem: "ai.openclaw", category: "Chat") - let updaterController: UpdaterProviding = makeUpdaterController() - - func application(_: NSApplication, open urls: [URL]) { - Task { @MainActor in - for url in urls { - await DeepLinkHandler.shared.handle(url: url) - } - } - } - - @MainActor - func applicationDidFinishLaunching(_ notification: Notification) { - if self.isDuplicateInstance() { - NSApp.terminate(nil) - return - } - self.state = AppStateStore.shared - AppActivationPolicy.apply(showDockIcon: self.state?.showDockIcon ?? false) - if let state { - Task { await ConnectionModeCoordinator.shared.apply(mode: state.connectionMode, paused: state.isPaused) } - } - TerminationSignalWatcher.shared.start() - NodePairingApprovalPrompter.shared.start() - DevicePairingApprovalPrompter.shared.start() - ExecApprovalsPromptServer.shared.start() - ExecApprovalsGatewayPrompter.shared.start() - MacNodeModeCoordinator.shared.start() - VoiceWakeGlobalSettingsSync.shared.start() - Task { PresenceReporter.shared.start() } - Task { await HealthStore.shared.refresh(onDemand: true) } - Task { await PortGuardian.shared.sweep(mode: AppStateStore.shared.connectionMode) } - Task { await PeekabooBridgeHostCoordinator.shared.setEnabled(AppStateStore.shared.peekabooBridgeEnabled) } - self.scheduleFirstRunOnboardingIfNeeded() - DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { - CLIInstallPrompter.shared.checkAndPromptIfNeeded(reason: "launch") - } - - // Developer/testing helper: auto-open chat when launched with --chat (or legacy --webchat). - if CommandLine.arguments.contains("--chat") || CommandLine.arguments.contains("--webchat") { - self.webChatAutoLogger.debug("Auto-opening chat via CLI flag") - Task { @MainActor in - let sessionKey = await WebChatManager.shared.preferredSessionKey() - WebChatManager.shared.show(sessionKey: sessionKey) - } - } - } - - func applicationWillTerminate(_ notification: Notification) { - PresenceReporter.shared.stop() - NodePairingApprovalPrompter.shared.stop() - DevicePairingApprovalPrompter.shared.stop() - ExecApprovalsPromptServer.shared.stop() - ExecApprovalsGatewayPrompter.shared.stop() - MacNodeModeCoordinator.shared.stop() - TerminationSignalWatcher.shared.stop() - VoiceWakeGlobalSettingsSync.shared.stop() - WebChatManager.shared.close() - WebChatManager.shared.resetTunnels() - Task { await RemoteTunnelManager.shared.stopAll() } - Task { await GatewayConnection.shared.shutdown() } - Task { await PeekabooBridgeHostCoordinator.shared.stop() } - } - - @MainActor - private func scheduleFirstRunOnboardingIfNeeded() { - let seenVersion = UserDefaults.standard.integer(forKey: onboardingVersionKey) - let shouldShow = seenVersion < currentOnboardingVersion || !AppStateStore.shared.onboardingSeen - guard shouldShow else { return } - DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) { - OnboardingController.shared.show() - } - } - - private func isDuplicateInstance() -> Bool { - guard let bundleID = Bundle.main.bundleIdentifier else { return false } - let running = NSWorkspace.shared.runningApplications.filter { $0.bundleIdentifier == bundleID } - return running.count > 1 - } -} - -// MARK: - Sparkle updater (disabled for unsigned/dev builds) - -@MainActor -protocol UpdaterProviding: AnyObject { - var automaticallyChecksForUpdates: Bool { get set } - var automaticallyDownloadsUpdates: Bool { get set } - var isAvailable: Bool { get } - var updateStatus: UpdateStatus { get } - func checkForUpdates(_ sender: Any?) -} - -/// No-op updater used for debug/dev runs to suppress Sparkle dialogs. -final class DisabledUpdaterController: UpdaterProviding { - var automaticallyChecksForUpdates: Bool = false - var automaticallyDownloadsUpdates: Bool = false - let isAvailable: Bool = false - let updateStatus = UpdateStatus() - func checkForUpdates(_: Any?) {} -} - -@MainActor -@Observable -final class UpdateStatus { - static let disabled = UpdateStatus() - var isUpdateReady: Bool - - init(isUpdateReady: Bool = false) { - self.isUpdateReady = isUpdateReady - } -} - -#if canImport(Sparkle) -import Sparkle - -@MainActor -final class SparkleUpdaterController: NSObject, UpdaterProviding { - private lazy var controller = SPUStandardUpdaterController( - startingUpdater: false, - updaterDelegate: self, - userDriverDelegate: nil) - let updateStatus = UpdateStatus() - - init(savedAutoUpdate: Bool) { - super.init() - let updater = self.controller.updater - updater.automaticallyChecksForUpdates = savedAutoUpdate - updater.automaticallyDownloadsUpdates = savedAutoUpdate - self.controller.startUpdater() - } - - var automaticallyChecksForUpdates: Bool { - get { self.controller.updater.automaticallyChecksForUpdates } - set { self.controller.updater.automaticallyChecksForUpdates = newValue } - } - - var automaticallyDownloadsUpdates: Bool { - get { self.controller.updater.automaticallyDownloadsUpdates } - set { self.controller.updater.automaticallyDownloadsUpdates = newValue } - } - - var isAvailable: Bool { - true - } - - func checkForUpdates(_ sender: Any?) { - self.controller.checkForUpdates(sender) - } - - func updater(_ updater: SPUUpdater, didDownloadUpdate item: SUAppcastItem) { - self.updateStatus.isUpdateReady = true - } - - func updater(_ updater: SPUUpdater, failedToDownloadUpdate item: SUAppcastItem, error: Error) { - self.updateStatus.isUpdateReady = false - } - - func userDidCancelDownload(_ updater: SPUUpdater) { - self.updateStatus.isUpdateReady = false - } - - func updater( - _ updater: SPUUpdater, - userDidMakeChoice choice: SPUUserUpdateChoice, - forUpdate updateItem: SUAppcastItem, - state: SPUUserUpdateState) - { - switch choice { - case .install, .skip: - self.updateStatus.isUpdateReady = false - case .dismiss: - self.updateStatus.isUpdateReady = (state.stage == .downloaded) - @unknown default: - self.updateStatus.isUpdateReady = false - } - } -} - -extension SparkleUpdaterController: @preconcurrency SPUUpdaterDelegate {} - -private func isDeveloperIDSigned(bundleURL: URL) -> Bool { - var staticCode: SecStaticCode? - guard SecStaticCodeCreateWithPath(bundleURL as CFURL, SecCSFlags(), &staticCode) == errSecSuccess, - let code = staticCode - else { return false } - - var infoCF: CFDictionary? - guard SecCodeCopySigningInformation(code, SecCSFlags(rawValue: kSecCSSigningInformation), &infoCF) == errSecSuccess, - let info = infoCF as? [String: Any], - let certs = info[kSecCodeInfoCertificates as String] as? [SecCertificate], - let leaf = certs.first - else { - return false - } - - if let summary = SecCertificateCopySubjectSummary(leaf) as String? { - return summary.hasPrefix("Developer ID Application:") - } - return false -} - -@MainActor -private func makeUpdaterController() -> UpdaterProviding { - let bundleURL = Bundle.main.bundleURL - let isBundledApp = bundleURL.pathExtension == "app" - guard isBundledApp, isDeveloperIDSigned(bundleURL: bundleURL) else { return DisabledUpdaterController() } - - let defaults = UserDefaults.standard - let autoUpdateKey = "autoUpdateEnabled" - // Default to true; honor the user's last choice otherwise. - let savedAutoUpdate = (defaults.object(forKey: autoUpdateKey) as? Bool) ?? true - return SparkleUpdaterController(savedAutoUpdate: savedAutoUpdate) -} -#else -@MainActor -private func makeUpdaterController() -> UpdaterProviding { - DisabledUpdaterController() -} -#endif diff --git a/apps/macos/Sources/OpenClaw/MenuContentView.swift b/apps/macos/Sources/OpenClaw/MenuContentView.swift deleted file mode 100644 index 3416d23f812..00000000000 --- a/apps/macos/Sources/OpenClaw/MenuContentView.swift +++ /dev/null @@ -1,596 +0,0 @@ -import AppKit -import AVFoundation -import Foundation -import Observation -import SwiftUI - -/// Menu contents for the OpenClaw menu bar extra. -struct MenuContent: View { - @Bindable var state: AppState - let updater: UpdaterProviding? - @Bindable private var updateStatus: UpdateStatus - private let gatewayManager = GatewayProcessManager.shared - private let healthStore = HealthStore.shared - private let heartbeatStore = HeartbeatStore.shared - private let controlChannel = ControlChannel.shared - private let activityStore = WorkActivityStore.shared - @Bindable private var pairingPrompter = NodePairingApprovalPrompter.shared - @Bindable private var devicePairingPrompter = DevicePairingApprovalPrompter.shared - @Environment(\.openSettings) private var openSettings - @State private var availableMics: [AudioInputDevice] = [] - @State private var loadingMics = false - @State private var micObserver = AudioInputDeviceObserver() - @State private var micRefreshTask: Task? - @State private var browserControlEnabled = true - @AppStorage(cameraEnabledKey) private var cameraEnabled: Bool = false - @AppStorage(appLogLevelKey) private var appLogLevelRaw: String = AppLogLevel.default.rawValue - @AppStorage(debugFileLogEnabledKey) private var appFileLoggingEnabled: Bool = false - - init(state: AppState, updater: UpdaterProviding?) { - self._state = Bindable(wrappedValue: state) - self.updater = updater - self._updateStatus = Bindable(wrappedValue: updater?.updateStatus ?? UpdateStatus.disabled) - } - - private var execApprovalModeBinding: Binding { - Binding( - get: { self.state.execApprovalMode }, - set: { self.state.execApprovalMode = $0 }) - } - - var body: some View { - VStack(alignment: .leading, spacing: 8) { - Toggle(isOn: self.activeBinding) { - VStack(alignment: .leading, spacing: 2) { - Text(self.connectionLabel) - self.statusLine(label: self.healthStatus.label, color: self.healthStatus.color) - if self.pairingPrompter.pendingCount > 0 { - let repairCount = self.pairingPrompter.pendingRepairCount - let repairSuffix = repairCount > 0 ? " · \(repairCount) repair" : "" - self.statusLine( - label: "Pairing approval pending (\(self.pairingPrompter.pendingCount))\(repairSuffix)", - color: .orange) - } - if self.devicePairingPrompter.pendingCount > 0 { - let repairCount = self.devicePairingPrompter.pendingRepairCount - let repairSuffix = repairCount > 0 ? " · \(repairCount) repair" : "" - self.statusLine( - label: "Device pairing pending (\(self.devicePairingPrompter.pendingCount))\(repairSuffix)", - color: .orange) - } - } - } - .disabled(self.state.connectionMode == .unconfigured) - - Divider() - Toggle(isOn: self.heartbeatsBinding) { - HStack(spacing: 8) { - Label("Send Heartbeats", systemImage: "waveform.path.ecg") - Spacer(minLength: 0) - self.statusLine(label: self.heartbeatStatus.label, color: self.heartbeatStatus.color) - } - } - Toggle( - isOn: Binding( - get: { self.browserControlEnabled }, - set: { enabled in - self.browserControlEnabled = enabled - Task { await self.saveBrowserControlEnabled(enabled) } - })) { - Label("Browser Control", systemImage: "globe") - } - Toggle(isOn: self.$cameraEnabled) { - Label("Allow Camera", systemImage: "camera") - } - Picker(selection: self.execApprovalModeBinding) { - ForEach(ExecApprovalQuickMode.allCases) { mode in - Text(mode.title).tag(mode) - } - } label: { - Label("Exec Approvals", systemImage: "terminal") - } - Toggle(isOn: Binding(get: { self.state.canvasEnabled }, set: { self.state.canvasEnabled = $0 })) { - Label("Allow Canvas", systemImage: "rectangle.and.pencil.and.ellipsis") - } - .onChange(of: self.state.canvasEnabled) { _, enabled in - if !enabled { - CanvasManager.shared.hideAll() - } - } - Toggle(isOn: self.voiceWakeBinding) { - Label("Voice Wake", systemImage: "mic.fill") - } - .disabled(!voiceWakeSupported) - .opacity(voiceWakeSupported ? 1 : 0.5) - if self.showVoiceWakeMicPicker { - self.voiceWakeMicMenu - } - Divider() - Button { - Task { @MainActor in - await self.openDashboard() - } - } label: { - Label("Open Dashboard", systemImage: "gauge") - } - Button { - Task { @MainActor in - let sessionKey = await WebChatManager.shared.preferredSessionKey() - WebChatManager.shared.show(sessionKey: sessionKey) - } - } label: { - Label("Open Chat", systemImage: "bubble.left.and.bubble.right") - } - if self.state.canvasEnabled { - Button { - Task { @MainActor in - if self.state.canvasPanelVisible { - CanvasManager.shared.hideAll() - } else { - let sessionKey = await GatewayConnection.shared.mainSessionKey() - // Don't force a navigation on re-open: preserve the current web view state. - _ = try? CanvasManager.shared.show(sessionKey: sessionKey, path: nil) - } - } - } label: { - Label( - self.state.canvasPanelVisible ? "Close Canvas" : "Open Canvas", - systemImage: "rectangle.inset.filled.on.rectangle") - } - } - Button { - Task { await self.state.setTalkEnabled(!self.state.talkEnabled) } - } label: { - Label(self.state.talkEnabled ? "Stop Talk Mode" : "Talk Mode", systemImage: "waveform.circle.fill") - } - .disabled(!voiceWakeSupported) - .opacity(voiceWakeSupported ? 1 : 0.5) - Divider() - Button("Settings…") { self.open(tab: .general) } - .keyboardShortcut(",", modifiers: [.command]) - self.debugMenu - Button("About OpenClaw") { self.open(tab: .about) } - if let updater, updater.isAvailable, self.updateStatus.isUpdateReady { - Button("Update ready, restart now?") { updater.checkForUpdates(nil) } - } - Button("Quit") { NSApplication.shared.terminate(nil) } - } - .task(id: self.state.swabbleEnabled) { - if self.state.swabbleEnabled { - await self.loadMicrophones(force: true) - } - } - .task { - VoicePushToTalkHotkey.shared.setEnabled(voiceWakeSupported && self.state.voicePushToTalkEnabled) - } - .onChange(of: self.state.voicePushToTalkEnabled) { _, enabled in - VoicePushToTalkHotkey.shared.setEnabled(voiceWakeSupported && enabled) - } - .task(id: self.state.connectionMode) { - await self.loadBrowserControlEnabled() - } - .onAppear { - self.startMicObserver() - } - .onDisappear { - self.micRefreshTask?.cancel() - self.micRefreshTask = nil - self.micObserver.stop() - } - .task { @MainActor in - SettingsWindowOpener.shared.register(openSettings: self.openSettings) - } - } - - private var connectionLabel: String { - switch self.state.connectionMode { - case .unconfigured: - "OpenClaw Not Configured" - case .remote: - "Remote OpenClaw Active" - case .local: - "OpenClaw Active" - } - } - - private func loadBrowserControlEnabled() async { - let root = await ConfigStore.load() - let browser = root["browser"] as? [String: Any] - let enabled = browser?["enabled"] as? Bool ?? true - await MainActor.run { self.browserControlEnabled = enabled } - } - - private func saveBrowserControlEnabled(_ enabled: Bool) async { - let (success, _) = await MenuContent.buildAndSaveBrowserEnabled(enabled) - - if !success { - await self.loadBrowserControlEnabled() - } - } - - @MainActor - private static func buildAndSaveBrowserEnabled(_ enabled: Bool) async -> (Bool, ()) { - var root = await ConfigStore.load() - var browser = root["browser"] as? [String: Any] ?? [:] - browser["enabled"] = enabled - root["browser"] = browser - do { - try await ConfigStore.save(root) - return (true, ()) - } catch { - return (false, ()) - } - } - - @ViewBuilder - private var debugMenu: some View { - if self.state.debugPaneEnabled { - Menu("Debug") { - Button { - DebugActions.openConfigFolder() - } label: { - Label("Open Config Folder", systemImage: "folder") - } - Button { - Task { await DebugActions.runHealthCheckNow() } - } label: { - Label("Run Health Check Now", systemImage: "stethoscope") - } - Button { - Task { _ = await DebugActions.sendTestHeartbeat() } - } label: { - Label("Send Test Heartbeat", systemImage: "waveform.path.ecg") - } - if self.state.connectionMode == .remote { - Button { - Task { @MainActor in - let result = await DebugActions.resetGatewayTunnel() - self.presentDebugResult(result, title: "Remote Tunnel") - } - } label: { - Label("Reset Remote Tunnel", systemImage: "arrow.triangle.2.circlepath") - } - } - Button { - Task { _ = await DebugActions.toggleVerboseLoggingMain() } - } label: { - Label( - DebugActions.verboseLoggingEnabledMain - ? "Verbose Logging (Main): On" - : "Verbose Logging (Main): Off", - systemImage: "text.alignleft") - } - Menu { - Picker("Verbosity", selection: self.$appLogLevelRaw) { - ForEach(AppLogLevel.allCases) { level in - Text(level.title).tag(level.rawValue) - } - } - Toggle(isOn: self.$appFileLoggingEnabled) { - Label( - self.appFileLoggingEnabled - ? "File Logging: On" - : "File Logging: Off", - systemImage: "doc.text.magnifyingglass") - } - } label: { - Label("App Logging", systemImage: "doc.text") - } - Button { - DebugActions.openSessionStore() - } label: { - Label("Open Session Store", systemImage: "externaldrive") - } - Divider() - Button { - DebugActions.openAgentEventsWindow() - } label: { - Label("Open Agent Events…", systemImage: "bolt.horizontal.circle") - } - Button { - DebugActions.openLog() - } label: { - Label("Open Log", systemImage: "doc.text.magnifyingglass") - } - Button { - Task { _ = await DebugActions.sendDebugVoice() } - } label: { - Label("Send Debug Voice Text", systemImage: "waveform.circle") - } - Button { - Task { await DebugActions.sendTestNotification() } - } label: { - Label("Send Test Notification", systemImage: "bell") - } - Divider() - if self.state.connectionMode == .local { - Button { - DebugActions.restartGateway() - } label: { - Label("Restart Gateway", systemImage: "arrow.clockwise") - } - } - Button { - DebugActions.restartOnboarding() - } label: { - Label("Restart Onboarding", systemImage: "arrow.counterclockwise") - } - Button { - DebugActions.restartApp() - } label: { - Label("Restart App", systemImage: "arrow.triangle.2.circlepath") - } - } - } - } - - private func open(tab: SettingsTab) { - SettingsTabRouter.request(tab) - NSApp.activate(ignoringOtherApps: true) - self.openSettings() - DispatchQueue.main.async { - NotificationCenter.default.post(name: .openclawSelectSettingsTab, object: tab) - } - } - - @MainActor - private func openDashboard() async { - do { - let config = try await GatewayEndpointStore.shared.requireConfig() - let url = try GatewayEndpointStore.dashboardURL(for: config, mode: self.state.connectionMode) - NSWorkspace.shared.open(url) - } catch { - let alert = NSAlert() - alert.messageText = "Dashboard unavailable" - alert.informativeText = error.localizedDescription - alert.runModal() - } - } - - private var healthStatus: (label: String, color: Color) { - if let activity = self.activityStore.current { - let color: Color = activity.role == .main ? .accentColor : .gray - let roleLabel = activity.role == .main ? "Main" : "Other" - let text = "\(roleLabel) · \(activity.label)" - return (text, color) - } - - let health = self.healthStore.state - let isRefreshing = self.healthStore.isRefreshing - let lastAge = self.healthStore.lastSuccess.map { age(from: $0) } - - if isRefreshing { - return ("Health check running…", health.tint) - } - - switch health { - case .ok: - let ageText = lastAge.map { " · checked \($0)" } ?? "" - return ("Health ok\(ageText)", .green) - case .linkingNeeded: - return ("Health: login required", .red) - case let .degraded(reason): - let detail = HealthStore.shared.degradedSummary ?? reason - let ageText = lastAge.map { " · checked \($0)" } ?? "" - return ("\(detail)\(ageText)", .orange) - case .unknown: - return ("Health pending", .secondary) - } - } - - private var heartbeatStatus: (label: String, color: Color) { - if case .degraded = self.controlChannel.state { - return ("Control channel disconnected", .red) - } else if let evt = self.heartbeatStore.lastEvent { - let ageText = age(from: Date(timeIntervalSince1970: evt.ts / 1000)) - switch evt.status { - case "sent": - return ("Last heartbeat sent · \(ageText)", .blue) - case "ok-empty", "ok-token": - return ("Heartbeat ok · \(ageText)", .green) - case "skipped": - return ("Heartbeat skipped · \(ageText)", .secondary) - case "failed": - return ("Heartbeat failed · \(ageText)", .red) - default: - return ("Heartbeat · \(ageText)", .secondary) - } - } else { - return ("No heartbeat yet", .secondary) - } - } - - private func statusLine(label: String, color: Color) -> some View { - HStack(spacing: 6) { - Circle() - .fill(color) - .frame(width: 6, height: 6) - Text(label) - .font(.caption) - .foregroundStyle(.secondary) - .multilineTextAlignment(.leading) - .lineLimit(nil) - .fixedSize(horizontal: false, vertical: true) - .layoutPriority(1) - } - .padding(.top, 2) - } - - private var activeBinding: Binding { - Binding(get: { !self.state.isPaused }, set: { self.state.isPaused = !$0 }) - } - - private var heartbeatsBinding: Binding { - Binding(get: { self.state.heartbeatsEnabled }, set: { self.state.heartbeatsEnabled = $0 }) - } - - private var voiceWakeBinding: Binding { - Binding( - get: { self.state.swabbleEnabled }, - set: { newValue in - Task { await self.state.setVoiceWakeEnabled(newValue) } - }) - } - - private var showVoiceWakeMicPicker: Bool { - voiceWakeSupported && self.state.swabbleEnabled - } - - private var voiceWakeMicMenu: some View { - Menu { - self.microphoneMenuItems - - if self.loadingMics { - Divider() - Label("Refreshing microphones…", systemImage: "arrow.triangle.2.circlepath") - .labelStyle(.titleOnly) - .foregroundStyle(.secondary) - .disabled(true) - } - } label: { - HStack { - Text("Microphone") - Spacer() - Text(self.selectedMicLabel) - .foregroundStyle(.secondary) - } - } - .task { await self.loadMicrophones() } - } - - private var selectedMicLabel: String { - if self.state.voiceWakeMicID.isEmpty { return self.defaultMicLabel } - if let match = self.availableMics.first(where: { $0.uid == self.state.voiceWakeMicID }) { - return match.name - } - if !self.state.voiceWakeMicName.isEmpty { return self.state.voiceWakeMicName } - return "Unavailable" - } - - private var microphoneMenuItems: some View { - Group { - if self.isSelectedMicUnavailable { - Label("Disconnected (using System default)", systemImage: "exclamationmark.triangle") - .labelStyle(.titleAndIcon) - .foregroundStyle(.secondary) - .disabled(true) - Divider() - } - Button { - self.state.voiceWakeMicID = "" - self.state.voiceWakeMicName = "" - } label: { - Label(self.defaultMicLabel, systemImage: self.state.voiceWakeMicID.isEmpty ? "checkmark" : "") - .labelStyle(.titleAndIcon) - } - .buttonStyle(.plain) - - ForEach(self.availableMics) { mic in - Button { - self.state.voiceWakeMicID = mic.uid - self.state.voiceWakeMicName = mic.name - } label: { - Label(mic.name, systemImage: self.state.voiceWakeMicID == mic.uid ? "checkmark" : "") - .labelStyle(.titleAndIcon) - } - .buttonStyle(.plain) - } - } - } - - private var isSelectedMicUnavailable: Bool { - let selected = self.state.voiceWakeMicID - guard !selected.isEmpty else { return false } - return !self.availableMics.contains(where: { $0.uid == selected }) - } - - private var defaultMicLabel: String { - if let host = Host.current().localizedName, !host.isEmpty { - return "Auto-detect (\(host))" - } - return "System default" - } - - @MainActor - private func presentDebugResult(_ result: Result, title: String) { - let alert = NSAlert() - alert.messageText = title - switch result { - case let .success(message): - alert.informativeText = message - alert.alertStyle = .informational - case let .failure(error): - alert.informativeText = error.localizedDescription - alert.alertStyle = .warning - } - alert.runModal() - } - - @MainActor - private func loadMicrophones(force: Bool = false) async { - guard self.showVoiceWakeMicPicker else { - self.availableMics = [] - self.loadingMics = false - return - } - if !force, !self.availableMics.isEmpty { return } - self.loadingMics = true - let discovery = AVCaptureDevice.DiscoverySession( - deviceTypes: [.external, .microphone], - mediaType: .audio, - position: .unspecified) - let connectedDevices = discovery.devices.filter(\.isConnected) - self.availableMics = connectedDevices - .sorted { lhs, rhs in - lhs.localizedName.localizedCaseInsensitiveCompare(rhs.localizedName) == .orderedAscending - } - .map { AudioInputDevice(uid: $0.uniqueID, name: $0.localizedName) } - self.availableMics = self.filterAliveInputs(self.availableMics) - self.updateSelectedMicName() - self.loadingMics = false - } - - private func startMicObserver() { - self.micObserver.start { - Task { @MainActor in - self.scheduleMicRefresh() - } - } - } - - @MainActor - private func scheduleMicRefresh() { - self.micRefreshTask?.cancel() - self.micRefreshTask = Task { @MainActor in - try? await Task.sleep(nanoseconds: 300_000_000) - guard !Task.isCancelled else { return } - await self.loadMicrophones(force: true) - } - } - - private func filterAliveInputs(_ inputs: [AudioInputDevice]) -> [AudioInputDevice] { - let aliveUIDs = AudioInputDeviceObserver.aliveInputDeviceUIDs() - guard !aliveUIDs.isEmpty else { return inputs } - return inputs.filter { aliveUIDs.contains($0.uid) } - } - - @MainActor - private func updateSelectedMicName() { - let selected = self.state.voiceWakeMicID - if selected.isEmpty { - self.state.voiceWakeMicName = "" - return - } - if let match = self.availableMics.first(where: { $0.uid == selected }) { - self.state.voiceWakeMicName = match.name - } - } - - private struct AudioInputDevice: Identifiable, Equatable { - let uid: String - let name: String - var id: String { - self.uid - } - } -} diff --git a/apps/macos/Sources/OpenClaw/MenuContextCardInjector.swift b/apps/macos/Sources/OpenClaw/MenuContextCardInjector.swift deleted file mode 100644 index f469ca348dc..00000000000 --- a/apps/macos/Sources/OpenClaw/MenuContextCardInjector.swift +++ /dev/null @@ -1,228 +0,0 @@ -import AppKit -import SwiftUI - -@MainActor -final class MenuContextCardInjector: NSObject, NSMenuDelegate { - static let shared = MenuContextCardInjector() - - private let tag = 9_415_227 - private let fallbackCardWidth: CGFloat = 320 - private var lastKnownMenuWidth: CGFloat? - private weak var originalDelegate: NSMenuDelegate? - private var loadTask: Task? - private var warmTask: Task? - private var cachedRows: [SessionRow] = [] - private var cacheErrorText: String? - private var cacheUpdatedAt: Date? - private let activeWindowSeconds: TimeInterval = 24 * 60 * 60 - private let refreshIntervalSeconds: TimeInterval = 15 - private var isMenuOpen = false - - func install(into statusItem: NSStatusItem) { - // SwiftUI owns the menu, but we can inject a custom NSMenuItem.view right before display. - guard let menu = statusItem.menu else { return } - // Preserve SwiftUI's internal NSMenuDelegate, otherwise it may stop populating menu items. - if menu.delegate !== self { - self.originalDelegate = menu.delegate - menu.delegate = self - } - - if self.warmTask == nil { - self.warmTask = Task { await self.refreshCache(force: true) } - } - } - - func menuWillOpen(_ menu: NSMenu) { - self.originalDelegate?.menuWillOpen?(menu) - self.isMenuOpen = true - - // Remove any previous injected card items. - for item in menu.items where item.tag == self.tag { - menu.removeItem(item) - } - - guard let insertIndex = self.findInsertIndex(in: menu) else { return } - - self.loadTask?.cancel() - - let initialRows = self.cachedRows - let initialIsLoading = initialRows.isEmpty - let initialStatusText = initialIsLoading ? self.cacheErrorText : nil - let initialWidth = self.initialCardWidth(for: menu) - - let initial = AnyView(ContextMenuCardView( - rows: initialRows, - statusText: initialStatusText, - isLoading: initialIsLoading)) - - let hosting = NSHostingView(rootView: initial) - hosting.frame.size.width = max(1, initialWidth) - let size = hosting.fittingSize - hosting.frame = NSRect( - origin: .zero, - size: NSSize(width: initialWidth, height: size.height)) - - let item = NSMenuItem() - item.tag = self.tag - item.view = hosting - item.isEnabled = false - - menu.insertItem(item, at: insertIndex) - - // Capture the menu window width for next open, but do not mutate widths while the menu is visible. - DispatchQueue.main.async { [weak self, weak hosting] in - guard let self, let hosting else { return } - self.captureMenuWidthIfAvailable(for: menu, hosting: hosting) - } - - if initialIsLoading { - self.loadTask = Task { [weak hosting] in - await self.refreshCache(force: true) - guard let hosting else { return } - let view = self.cachedView() - await MainActor.run { - hosting.rootView = view - hosting.invalidateIntrinsicContentSize() - self.captureMenuWidthIfAvailable(for: menu, hosting: hosting) - hosting.frame.size.width = max(1, initialWidth) - let size = hosting.fittingSize - hosting.frame.size.height = size.height - } - } - } else { - // Keep the menu stable while it's open; refresh in the background for next open. - self.loadTask = Task { await self.refreshCache(force: false) } - } - } - - func menuDidClose(_ menu: NSMenu) { - self.originalDelegate?.menuDidClose?(menu) - self.isMenuOpen = false - self.loadTask?.cancel() - } - - func menuNeedsUpdate(_ menu: NSMenu) { - self.originalDelegate?.menuNeedsUpdate?(menu) - } - - func confinementRect(for menu: NSMenu, on screen: NSScreen?) -> NSRect { - if let rect = self.originalDelegate?.confinementRect?(for: menu, on: screen) { - return rect - } - return NSRect.zero - } - - private func refreshCache(force: Bool) async { - if !force, let cacheUpdatedAt, Date().timeIntervalSince(cacheUpdatedAt) < self.refreshIntervalSeconds { - return - } - - do { - let rows = try await self.loadCurrentRows() - self.cachedRows = rows - self.cacheErrorText = nil - self.cacheUpdatedAt = Date() - } catch { - if self.cachedRows.isEmpty { - let raw = (error as? LocalizedError)?.errorDescription ?? error.localizedDescription - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty { - self.cacheErrorText = "Could not load sessions" - } else { - // Keep the menu readable: one line, short. - let firstLine = trimmed.split(whereSeparator: \.isNewline).first.map(String.init) ?? trimmed - self.cacheErrorText = firstLine.count > 90 ? "\(firstLine.prefix(87))…" : firstLine - } - } - self.cacheUpdatedAt = Date() - } - } - - private func cachedView() -> AnyView { - let rows = self.cachedRows - let isLoading = rows.isEmpty && self.cacheErrorText == nil - return AnyView(ContextMenuCardView(rows: rows, statusText: self.cacheErrorText, isLoading: isLoading)) - } - - private func loadCurrentRows() async throws -> [SessionRow] { - let snapshot = try await SessionLoader.loadSnapshot() - let loaded = snapshot.rows - let now = Date() - let current = loaded.filter { row in - if row.key == "main" { return true } - guard let updatedAt = row.updatedAt else { return false } - return now.timeIntervalSince(updatedAt) <= self.activeWindowSeconds - } - - return current.sorted { lhs, rhs in - if lhs.key == "main" { return true } - if rhs.key == "main" { return false } - return (lhs.updatedAt ?? .distantPast) > (rhs.updatedAt ?? .distantPast) - } - } - - private func findInsertIndex(in menu: NSMenu) -> Int? { - // Prefer inserting before the first separator (so the card sits right below the Active toggle). - if let idx = menu.items.firstIndex(where: { $0.title == "Send Heartbeats" }) { - // SwiftUI menus typically include a separator right after the first toggle; insert before it so the - // separator appears below the context card. - if let sepIdx = menu.items[..= 1 { return 1 } - return menu.items.count - } - - private func initialCardWidth(for menu: NSMenu) -> CGFloat { - let widthCandidates: [CGFloat] = [ - menu.minimumWidth, - self.lastKnownMenuWidth ?? 0, - self.fallbackCardWidth, - ] - let resolved = widthCandidates.max() ?? self.fallbackCardWidth - return max(300, resolved) - } - - private func captureMenuWidthIfAvailable(for menu: NSMenu, hosting: NSHostingView) { - let targetWidth: CGFloat? = { - if let contentWidth = hosting.window?.contentView?.bounds.width, contentWidth > 0 { return contentWidth } - if let superWidth = hosting.superview?.bounds.width, superWidth > 0 { return superWidth } - let minimumWidth = menu.minimumWidth - if minimumWidth > 0 { return minimumWidth } - return nil - }() - - guard let targetWidth else { return } - self.lastKnownMenuWidth = max(300, targetWidth) - } -} - -#if DEBUG -extension MenuContextCardInjector { - func _testSetCache(rows: [SessionRow], errorText: String?, updatedAt: Date?) { - self.cachedRows = rows - self.cacheErrorText = errorText - self.cacheUpdatedAt = updatedAt - } - - func _testFindInsertIndex(in menu: NSMenu) -> Int? { - self.findInsertIndex(in: menu) - } - - func _testInitialCardWidth(for menu: NSMenu) -> CGFloat { - self.initialCardWidth(for: menu) - } - - func _testCachedView() -> AnyView { - self.cachedView() - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/MenuHighlightedHostView.swift b/apps/macos/Sources/OpenClaw/MenuHighlightedHostView.swift deleted file mode 100644 index 7107946989e..00000000000 --- a/apps/macos/Sources/OpenClaw/MenuHighlightedHostView.swift +++ /dev/null @@ -1,104 +0,0 @@ -import AppKit -import SwiftUI - -final class HighlightedMenuItemHostView: NSView { - private var baseView: AnyView - private let hosting: NSHostingView - private var targetWidth: CGFloat - private var tracking: NSTrackingArea? - private var hovered = false { - didSet { self.updateHighlight() } - } - - init(rootView: AnyView, width: CGFloat) { - self.baseView = rootView - self.hosting = NSHostingView(rootView: AnyView(rootView.environment(\.menuItemHighlighted, false))) - self.targetWidth = max(1, width) - super.init(frame: .zero) - - self.addSubview(self.hosting) - self.hosting.autoresizingMask = [.width, .height] - self.updateSizing() - } - - @available(*, unavailable) - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override var intrinsicContentSize: NSSize { - let size = self.hosting.fittingSize - return NSSize(width: self.targetWidth, height: size.height) - } - - override func updateTrackingAreas() { - super.updateTrackingAreas() - if let tracking { - self.removeTrackingArea(tracking) - } - let options: NSTrackingArea.Options = [ - .mouseEnteredAndExited, - .activeAlways, - .inVisibleRect, - ] - let area = NSTrackingArea(rect: self.bounds, options: options, owner: self, userInfo: nil) - self.addTrackingArea(area) - self.tracking = area - } - - override func mouseEntered(with event: NSEvent) { - _ = event - self.hovered = true - } - - override func mouseExited(with event: NSEvent) { - _ = event - self.hovered = false - } - - override func layout() { - super.layout() - self.hosting.frame = self.bounds - } - - override func draw(_ dirtyRect: NSRect) { - if self.hovered { - NSColor.selectedContentBackgroundColor.setFill() - self.bounds.fill() - } - super.draw(dirtyRect) - } - - func update(rootView: AnyView, width: CGFloat) { - self.baseView = rootView - self.targetWidth = max(1, width) - self.updateHighlight() - } - - private func updateHighlight() { - self.hosting.rootView = AnyView(self.baseView.environment(\.menuItemHighlighted, self.hovered)) - self.updateSizing() - self.needsDisplay = true - } - - private func updateSizing() { - let width = max(1, self.targetWidth) - self.hosting.frame.size.width = width - let size = self.hosting.fittingSize - self.frame = NSRect(origin: .zero, size: NSSize(width: width, height: size.height)) - self.invalidateIntrinsicContentSize() - } -} - -struct MenuHostedHighlightedItem: NSViewRepresentable { - let width: CGFloat - let rootView: AnyView - - func makeNSView(context _: Context) -> HighlightedMenuItemHostView { - HighlightedMenuItemHostView(rootView: self.rootView, width: self.width) - } - - func updateNSView(_ nsView: HighlightedMenuItemHostView, context _: Context) { - nsView.update(rootView: self.rootView, width: self.width) - } -} diff --git a/apps/macos/Sources/OpenClaw/MenuHostedItem.swift b/apps/macos/Sources/OpenClaw/MenuHostedItem.swift deleted file mode 100644 index c5a2b73cd94..00000000000 --- a/apps/macos/Sources/OpenClaw/MenuHostedItem.swift +++ /dev/null @@ -1,29 +0,0 @@ -import AppKit -import SwiftUI - -/// Hosts arbitrary SwiftUI content as an AppKit view so it can be embedded in a native `NSMenuItem.view`. -/// -/// SwiftUI `MenuBarExtraStyle.menu` aggressively simplifies many view hierarchies into a title + image. -/// Wrapping the content in an `NSViewRepresentable` forces AppKit-backed menu item rendering. -struct MenuHostedItem: NSViewRepresentable { - let width: CGFloat - let rootView: AnyView - - func makeNSView(context _: Context) -> NSHostingView { - let hosting = NSHostingView(rootView: self.rootView) - self.applySizing(to: hosting) - return hosting - } - - func updateNSView(_ nsView: NSHostingView, context _: Context) { - nsView.rootView = self.rootView - self.applySizing(to: nsView) - } - - private func applySizing(to hosting: NSHostingView) { - let width = max(1, self.width) - hosting.frame.size.width = width - let fitting = hosting.fittingSize - hosting.frame = NSRect(origin: .zero, size: NSSize(width: width, height: fitting.height)) - } -} diff --git a/apps/macos/Sources/OpenClaw/MenuSessionsHeaderView.swift b/apps/macos/Sources/OpenClaw/MenuSessionsHeaderView.swift deleted file mode 100644 index e96cea53b84..00000000000 --- a/apps/macos/Sources/OpenClaw/MenuSessionsHeaderView.swift +++ /dev/null @@ -1,44 +0,0 @@ -import SwiftUI - -struct MenuSessionsHeaderView: View { - let count: Int - let statusText: String? - - private let paddingTop: CGFloat = 8 - private let paddingBottom: CGFloat = 6 - private let paddingTrailing: CGFloat = 10 - private let paddingLeading: CGFloat = 20 - - var body: some View { - VStack(alignment: .leading, spacing: 6) { - HStack(alignment: .firstTextBaseline) { - Text("Context") - .font(.caption.weight(.semibold)) - .foregroundStyle(.secondary) - Spacer(minLength: 10) - Text(self.subtitle) - .font(.caption) - .foregroundStyle(.secondary) - } - - if let statusText, !statusText.isEmpty { - Text(statusText) - .font(.caption) - .foregroundStyle(.secondary) - .lineLimit(1) - .truncationMode(.tail) - } - } - .padding(.top, self.paddingTop) - .padding(.bottom, self.paddingBottom) - .padding(.leading, self.paddingLeading) - .padding(.trailing, self.paddingTrailing) - .frame(minWidth: 300, maxWidth: .infinity, alignment: .leading) - .transaction { txn in txn.animation = nil } - } - - private var subtitle: String { - if self.count == 1 { return "1 session · 24h" } - return "\(self.count) sessions · 24h" - } -} diff --git a/apps/macos/Sources/OpenClaw/MenuSessionsInjector.swift b/apps/macos/Sources/OpenClaw/MenuSessionsInjector.swift deleted file mode 100644 index 37fd6ca2505..00000000000 --- a/apps/macos/Sources/OpenClaw/MenuSessionsInjector.swift +++ /dev/null @@ -1,1233 +0,0 @@ -import AppKit -import Foundation -import Observation -import SwiftUI - -@MainActor -final class MenuSessionsInjector: NSObject, NSMenuDelegate { - static let shared = MenuSessionsInjector() - - private let tag = 9_415_557 - private let nodesTag = 9_415_558 - private let fallbackWidth: CGFloat = 320 - private let activeWindowSeconds: TimeInterval = 24 * 60 * 60 - - private weak var originalDelegate: NSMenuDelegate? - private weak var statusItem: NSStatusItem? - private var loadTask: Task? - private var nodesLoadTask: Task? - private var previewTasks: [Task] = [] - private var isMenuOpen = false - private var lastKnownMenuWidth: CGFloat? - private var menuOpenWidth: CGFloat? - private var isObservingControlChannel = false - - private var cachedSnapshot: SessionStoreSnapshot? - private var cachedErrorText: String? - private var cacheUpdatedAt: Date? - private let refreshIntervalSeconds: TimeInterval = 12 - private var cachedUsageSummary: GatewayUsageSummary? - private var cachedUsageErrorText: String? - private var usageCacheUpdatedAt: Date? - private let usageRefreshIntervalSeconds: TimeInterval = 30 - private var cachedCostSummary: GatewayCostUsageSummary? - private var cachedCostErrorText: String? - private var costCacheUpdatedAt: Date? - private let costRefreshIntervalSeconds: TimeInterval = 45 - private let nodesStore = NodesStore.shared - #if DEBUG - private var testControlChannelConnected: Bool? - #endif - - func install(into statusItem: NSStatusItem) { - self.statusItem = statusItem - guard let menu = statusItem.menu else { return } - - // Preserve SwiftUI's internal NSMenuDelegate, otherwise it may stop populating menu items. - if menu.delegate !== self { - self.originalDelegate = menu.delegate - menu.delegate = self - } - - if self.loadTask == nil { - self.loadTask = Task { await self.refreshCache(force: true) } - } - - self.startControlChannelObservation() - self.nodesStore.start() - } - - func menuWillOpen(_ menu: NSMenu) { - self.originalDelegate?.menuWillOpen?(menu) - self.isMenuOpen = true - self.menuOpenWidth = self.currentMenuWidth(for: menu) - - self.inject(into: menu) - self.injectNodes(into: menu) - - // Refresh in background for the next open; keep width stable while open. - self.loadTask?.cancel() - let forceRefresh = self.cachedSnapshot == nil || self.cachedErrorText != nil - self.loadTask = Task { [weak self] in - guard let self else { return } - await self.refreshCache(force: forceRefresh) - await self.refreshUsageCache(force: forceRefresh) - await self.refreshCostUsageCache(force: forceRefresh) - await MainActor.run { - guard self.isMenuOpen else { return } - self.inject(into: menu) - self.injectNodes(into: menu) - } - } - - self.nodesLoadTask?.cancel() - self.nodesLoadTask = Task { [weak self] in - guard let self else { return } - await self.nodesStore.refresh() - await MainActor.run { - guard self.isMenuOpen else { return } - self.injectNodes(into: menu) - } - } - } - - func menuDidClose(_ menu: NSMenu) { - self.originalDelegate?.menuDidClose?(menu) - self.isMenuOpen = false - self.menuOpenWidth = nil - self.loadTask?.cancel() - self.nodesLoadTask?.cancel() - self.cancelPreviewTasks() - } - - private func startControlChannelObservation() { - guard !self.isObservingControlChannel else { return } - self.isObservingControlChannel = true - self.observeControlChannelState() - } - - private func observeControlChannelState() { - withObservationTracking { - _ = ControlChannel.shared.state - } onChange: { [weak self] in - Task { @MainActor [weak self] in - guard let self else { return } - self.handleControlChannelStateChange() - self.observeControlChannelState() - } - } - } - - private func handleControlChannelStateChange() { - guard self.isMenuOpen, let menu = self.statusItem?.menu else { return } - self.loadTask?.cancel() - self.loadTask = Task { [weak self, weak menu] in - guard let self, let menu else { return } - await self.refreshCache(force: true) - await self.refreshUsageCache(force: true) - await self.refreshCostUsageCache(force: true) - await MainActor.run { - guard self.isMenuOpen else { return } - self.inject(into: menu) - self.injectNodes(into: menu) - } - } - - self.nodesLoadTask?.cancel() - self.nodesLoadTask = Task { [weak self, weak menu] in - guard let self, let menu else { return } - await self.nodesStore.refresh() - await MainActor.run { - guard self.isMenuOpen else { return } - self.injectNodes(into: menu) - } - } - } - - func menuNeedsUpdate(_ menu: NSMenu) { - self.originalDelegate?.menuNeedsUpdate?(menu) - } - - func confinementRect(for menu: NSMenu, on screen: NSScreen?) -> NSRect { - if let rect = self.originalDelegate?.confinementRect?(for: menu, on: screen) { - return rect - } - return NSRect.zero - } -} - -extension MenuSessionsInjector { - // MARK: - Injection - - private var mainSessionKey: String { - WorkActivityStore.shared.mainSessionKey - } - - private func inject(into menu: NSMenu) { - self.cancelPreviewTasks() - // Remove any previous injected items. - for item in menu.items where item.tag == self.tag { - menu.removeItem(item) - } - - guard let insertIndex = self.findInsertIndex(in: menu) else { return } - let width = self.initialWidth(for: menu) - let isConnected = self.isControlChannelConnected - let channelState = ControlChannel.shared.state - - var cursor = insertIndex - var headerView: NSView? - - if let snapshot = self.cachedSnapshot { - let now = Date() - let mainKey = self.mainSessionKey - let rows = snapshot.rows.filter { row in - if row.key == "main", mainKey != "main" { return false } - if row.key == mainKey { return true } - guard let updatedAt = row.updatedAt else { return false } - return now.timeIntervalSince(updatedAt) <= self.activeWindowSeconds - }.sorted { lhs, rhs in - if lhs.key == mainKey { return true } - if rhs.key == mainKey { return false } - return (lhs.updatedAt ?? .distantPast) > (rhs.updatedAt ?? .distantPast) - } - if !rows.isEmpty { - let previewKeys = rows.prefix(20).map(\.key) - let task = Task { - await SessionMenuPreviewLoader.prewarm(sessionKeys: previewKeys, maxItems: 10) - } - self.previewTasks.append(task) - } - - let headerItem = NSMenuItem() - headerItem.tag = self.tag - headerItem.isEnabled = false - let statusText = self - .cachedErrorText ?? (isConnected ? nil : self.controlChannelStatusText(for: channelState)) - let hosted = self.makeHostedView( - rootView: AnyView(MenuSessionsHeaderView( - count: rows.count, - statusText: statusText)), - width: width, - highlighted: false) - headerItem.view = hosted - headerView = hosted - menu.insertItem(headerItem, at: cursor) - cursor += 1 - - if rows.isEmpty { - menu.insertItem( - self.makeMessageItem(text: "No active sessions", symbolName: "minus", width: width), - at: cursor) - cursor += 1 - } else { - for row in rows { - let item = NSMenuItem() - item.tag = self.tag - item.isEnabled = true - item.submenu = self.buildSubmenu(for: row, storePath: snapshot.storePath) - item.view = self.makeHostedView( - rootView: AnyView(SessionMenuLabelView(row: row, width: width)), - width: width, - highlighted: true) - menu.insertItem(item, at: cursor) - cursor += 1 - } - } - } else { - let headerItem = NSMenuItem() - headerItem.tag = self.tag - headerItem.isEnabled = false - let statusText = isConnected - ? (self.cachedErrorText ?? "Loading sessions…") - : self.controlChannelStatusText(for: channelState) - let hosted = self.makeHostedView( - rootView: AnyView(MenuSessionsHeaderView( - count: 0, - statusText: statusText)), - width: width, - highlighted: false) - headerItem.view = hosted - headerView = hosted - menu.insertItem(headerItem, at: cursor) - cursor += 1 - - if !isConnected { - menu.insertItem( - self.makeMessageItem( - text: "Connect the gateway to see sessions", - symbolName: "bolt.slash", - width: width), - at: cursor) - cursor += 1 - } - } - - cursor = self.insertUsageSection(into: menu, at: cursor, width: width) - cursor = self.insertCostUsageSection(into: menu, at: cursor, width: width) - - DispatchQueue.main.async { [weak self, weak headerView] in - guard let self, let headerView else { return } - self.captureMenuWidthIfAvailable(from: headerView) - } - } - - private func injectNodes(into menu: NSMenu) { - for item in menu.items where item.tag == self.nodesTag { - menu.removeItem(item) - } - - guard let insertIndex = self.findNodesInsertIndex(in: menu) else { return } - let width = self.initialWidth(for: menu) - var cursor = insertIndex - - let entries = self.sortedNodeEntries() - let topSeparator = NSMenuItem.separator() - topSeparator.tag = self.nodesTag - menu.insertItem(topSeparator, at: cursor) - cursor += 1 - - if let gatewayEntry = self.gatewayEntry() { - let gatewayItem = self.makeNodeItem(entry: gatewayEntry, width: width) - menu.insertItem(gatewayItem, at: cursor) - cursor += 1 - } - - if case .connecting = ControlChannel.shared.state { - menu.insertItem( - self.makeMessageItem(text: "Connecting…", symbolName: "circle.dashed", width: width), - at: cursor) - cursor += 1 - return - } - - guard self.isControlChannelConnected else { return } - - if let error = self.nodesStore.lastError?.nonEmpty { - menu.insertItem( - self.makeMessageItem( - text: "Error: \(error)", - symbolName: "exclamationmark.triangle", - width: width), - at: cursor) - cursor += 1 - } else if let status = self.nodesStore.statusMessage?.nonEmpty { - menu.insertItem( - self.makeMessageItem(text: status, symbolName: "info.circle", width: width), - at: cursor) - cursor += 1 - } - - if entries.isEmpty { - let title = self.nodesStore.isLoading ? "Loading devices..." : "No devices yet" - menu.insertItem( - self.makeMessageItem(text: title, symbolName: "circle.dashed", width: width), - at: cursor) - cursor += 1 - } else { - for entry in entries.prefix(8) { - let item = self.makeNodeItem(entry: entry, width: width) - menu.insertItem(item, at: cursor) - cursor += 1 - } - - if entries.count > 8 { - let moreItem = NSMenuItem() - moreItem.tag = self.nodesTag - moreItem.title = "More Devices..." - moreItem.image = NSImage(systemSymbolName: "ellipsis.circle", accessibilityDescription: nil) - let overflow = Array(entries.dropFirst(8)) - moreItem.submenu = self.buildNodesOverflowMenu(entries: overflow, width: width) - menu.insertItem(moreItem, at: cursor) - cursor += 1 - } - } - - _ = cursor - } - - private func insertUsageSection(into menu: NSMenu, at cursor: Int, width: CGFloat) -> Int { - let rows = self.usageRows - if rows.isEmpty { - return cursor - } - - var cursor = cursor - - if cursor > 0, !menu.items[cursor - 1].isSeparatorItem { - let separator = NSMenuItem.separator() - separator.tag = self.tag - menu.insertItem(separator, at: cursor) - cursor += 1 - } - - let headerItem = NSMenuItem() - headerItem.tag = self.tag - headerItem.isEnabled = false - headerItem.view = self.makeHostedView( - rootView: AnyView(MenuUsageHeaderView( - count: rows.count)), - width: width, - highlighted: false) - menu.insertItem(headerItem, at: cursor) - cursor += 1 - - if let selectedProvider = self.selectedUsageProviderId, - let primary = rows.first(where: { $0.providerId.lowercased() == selectedProvider }), - rows.count > 1 - { - let others = rows.filter { $0.providerId.lowercased() != selectedProvider } - - let item = NSMenuItem() - item.tag = self.tag - item.isEnabled = true - if !others.isEmpty { - item.submenu = self.buildUsageOverflowMenu(rows: others, width: width) - } - item.view = self.makeHostedView( - rootView: AnyView(UsageMenuLabelView(row: primary, width: width, showsChevron: !others.isEmpty)), - width: width, - highlighted: true) - menu.insertItem(item, at: cursor) - cursor += 1 - - return cursor - } - - for row in rows { - let item = NSMenuItem() - item.tag = self.tag - item.isEnabled = false - item.view = self.makeHostedView( - rootView: AnyView(UsageMenuLabelView(row: row, width: width)), - width: width, - highlighted: false) - menu.insertItem(item, at: cursor) - cursor += 1 - } - - return cursor - } - - private func insertCostUsageSection(into menu: NSMenu, at cursor: Int, width: CGFloat) -> Int { - guard self.isControlChannelConnected else { return cursor } - guard let submenu = self.buildCostUsageSubmenu(width: width) else { return cursor } - var cursor = cursor - - if cursor > 0, !menu.items[cursor - 1].isSeparatorItem { - let separator = NSMenuItem.separator() - separator.tag = self.tag - menu.insertItem(separator, at: cursor) - cursor += 1 - } - - let item = NSMenuItem(title: "Usage cost (30 days)", action: nil, keyEquivalent: "") - item.tag = self.tag - item.isEnabled = true - item.image = NSImage(systemSymbolName: "chart.bar.xaxis", accessibilityDescription: nil) - item.submenu = submenu - menu.insertItem(item, at: cursor) - cursor += 1 - return cursor - } - - private var selectedUsageProviderId: String? { - guard let model = self.cachedSnapshot?.defaults.model.nonEmpty else { return nil } - let trimmed = model.trimmingCharacters(in: .whitespacesAndNewlines) - guard let slash = trimmed.firstIndex(of: "/") else { return nil } - let provider = trimmed[.. NSMenu { - let menu = NSMenu() - for row in rows { - let item = NSMenuItem() - item.tag = self.tag - item.isEnabled = false - item.view = self.makeHostedView( - rootView: AnyView(UsageMenuLabelView(row: row, width: width)), - width: width, - highlighted: false) - menu.addItem(item) - } - return menu - } - - private var isControlChannelConnected: Bool { - #if DEBUG - if let override = self.testControlChannelConnected { return override } - #endif - if case .connected = ControlChannel.shared.state { return true } - return false - } - - private func controlChannelStatusText(for state: ControlChannel.ConnectionState) -> String { - switch state { - case .connected: - "Loading sessions…" - case .connecting: - "Connecting…" - case let .degraded(message): - message.nonEmpty ?? "Gateway disconnected" - case .disconnected: - "Gateway disconnected" - } - } - - private func buildCostUsageSubmenu(width: CGFloat) -> NSMenu? { - if let error = self.cachedCostErrorText, !error.isEmpty, self.cachedCostSummary == nil { - let menu = NSMenu() - let item = NSMenuItem(title: error, action: nil, keyEquivalent: "") - item.isEnabled = false - menu.addItem(item) - return menu - } - - guard let summary = self.cachedCostSummary else { return nil } - guard !summary.daily.isEmpty else { return nil } - - let menu = NSMenu() - menu.delegate = self - - let chartView = CostUsageHistoryMenuView(summary: summary, width: width) - let hosting = NSHostingView(rootView: AnyView(chartView)) - let controller = NSHostingController(rootView: AnyView(chartView)) - let size = controller.sizeThatFits(in: CGSize(width: width, height: .greatestFiniteMagnitude)) - hosting.frame = NSRect(origin: .zero, size: NSSize(width: width, height: size.height)) - - let chartItem = NSMenuItem() - chartItem.view = hosting - chartItem.isEnabled = false - chartItem.representedObject = "costUsageChart" - menu.addItem(chartItem) - - return menu - } - - private func gatewayEntry() -> NodeInfo? { - let mode = AppStateStore.shared.connectionMode - let isConnected = self.isControlChannelConnected - let port = GatewayEnvironment.gatewayPort() - var host: String? - var platform: String? - - switch mode { - case .remote: - platform = "remote" - if AppStateStore.shared.remoteTransport == .direct { - let trimmedUrl = AppStateStore.shared.remoteUrl - .trimmingCharacters(in: .whitespacesAndNewlines) - if let url = URL(string: trimmedUrl), let urlHost = url.host, !urlHost.isEmpty { - if let port = url.port { - host = "\(urlHost):\(port)" - } else { - host = urlHost - } - } else { - host = trimmedUrl.nonEmpty - } - } else { - let target = AppStateStore.shared.remoteTarget - if let parsed = CommandResolver.parseSSHTarget(target) { - host = parsed.port == 22 ? parsed.host : "\(parsed.host):\(parsed.port)" - } else { - host = target.nonEmpty - } - } - case .local: - platform = "local" - host = GatewayConnectivityCoordinator.shared.localEndpointHostLabel ?? "127.0.0.1:\(port)" - case .unconfigured: - platform = nil - host = nil - } - - return NodeInfo( - nodeId: "gateway", - displayName: "Gateway", - platform: platform, - version: nil, - coreVersion: nil, - uiVersion: nil, - deviceFamily: nil, - modelIdentifier: nil, - remoteIp: host, - caps: nil, - commands: nil, - permissions: nil, - paired: nil, - connected: isConnected) - } - - private func makeNodeItem(entry: NodeInfo, width: CGFloat) -> NSMenuItem { - let item = NSMenuItem() - item.tag = self.nodesTag - item.target = self - item.action = #selector(self.copyNodeSummary(_:)) - item.representedObject = NodeMenuEntryFormatter.summaryText(entry) - item.view = HighlightedMenuItemHostView( - rootView: AnyView(NodeMenuRowView(entry: entry, width: width)), - width: width) - item.submenu = self.buildNodeSubmenu(entry: entry, width: width) - return item - } - - private func makeSessionPreviewItem( - sessionKey: String, - title: String, - width: CGFloat, - maxLines: Int) -> NSMenuItem - { - let item = NSMenuItem() - item.tag = self.tag - item.isEnabled = false - let view = AnyView( - SessionMenuPreviewView( - width: width, - maxLines: maxLines, - title: title, - items: [], - status: .loading) - .environment(\.isEnabled, true)) - let hosted = HighlightedMenuItemHostView(rootView: view, width: width) - item.view = hosted - - let task = Task { [weak hosted, weak item] in - let snapshot = await SessionMenuPreviewLoader.load(sessionKey: sessionKey, maxItems: 10) - guard !Task.isCancelled else { return } - - await MainActor.run { - let nextView = AnyView( - SessionMenuPreviewView( - width: width, - maxLines: maxLines, - title: title, - items: snapshot.items, - status: snapshot.status) - .environment(\.isEnabled, true)) - - if let item { - item.view = HighlightedMenuItemHostView(rootView: nextView, width: width) - return - } - - guard let hosted else { return } - hosted.update(rootView: nextView, width: width) - } - } - self.previewTasks.append(task) - return item - } - - private func cancelPreviewTasks() { - for task in self.previewTasks { - task.cancel() - } - self.previewTasks.removeAll() - } - - private func makeMessageItem(text: String, symbolName: String, width: CGFloat, maxLines: Int? = 2) -> NSMenuItem { - let view = AnyView( - HStack(alignment: .top, spacing: 8) { - Image(systemName: symbolName) - .font(.caption) - .foregroundStyle(.secondary) - .frame(width: 14, alignment: .leading) - .padding(.top, 1) - - Text(text) - .font(.caption) - .foregroundStyle(.secondary) - .multilineTextAlignment(.leading) - .lineLimit(maxLines) - .truncationMode(.tail) - .fixedSize(horizontal: false, vertical: true) - .layoutPriority(1) - .frame(maxWidth: .infinity, alignment: .leading) - - Spacer(minLength: 0) - } - .padding(.leading, 18) - .padding(.trailing, 12) - .padding(.vertical, 6) - .frame(width: max(1, width), alignment: .leading)) - - let item = NSMenuItem() - item.tag = self.tag - item.isEnabled = false - item.view = self.makeHostedView(rootView: view, width: width, highlighted: false) - return item - } -} - -extension MenuSessionsInjector { - // MARK: - Cache - - private func refreshCache(force: Bool) async { - if !force, let updated = self.cacheUpdatedAt, Date().timeIntervalSince(updated) < self.refreshIntervalSeconds { - return - } - - guard self.isControlChannelConnected else { - if self.cachedSnapshot != nil { - self.cachedErrorText = "Gateway disconnected (showing cached)" - } else { - self.cachedErrorText = nil - } - self.cacheUpdatedAt = Date() - return - } - - do { - self.cachedSnapshot = try await SessionLoader.loadSnapshot(limit: 32) - self.cachedErrorText = nil - self.cacheUpdatedAt = Date() - } catch { - self.cachedSnapshot = nil - self.cachedErrorText = self.compactError(error) - self.cacheUpdatedAt = Date() - } - } - - private func refreshUsageCache(force: Bool) async { - if !force, - let updated = self.usageCacheUpdatedAt, - Date().timeIntervalSince(updated) < self.usageRefreshIntervalSeconds - { - return - } - - guard self.isControlChannelConnected else { - self.usageCacheUpdatedAt = Date() - return - } - - do { - self.cachedUsageSummary = try await UsageLoader.loadSummary() - } catch { - self.cachedUsageSummary = nil - self.cachedUsageErrorText = nil - } - self.usageCacheUpdatedAt = Date() - } - - private func refreshCostUsageCache(force: Bool) async { - if !force, - let updated = self.costCacheUpdatedAt, - Date().timeIntervalSince(updated) < self.costRefreshIntervalSeconds - { - return - } - - guard self.isControlChannelConnected else { - self.costCacheUpdatedAt = Date() - return - } - - do { - self.cachedCostSummary = try await CostUsageLoader.loadSummary() - self.cachedCostErrorText = nil - } catch { - self.cachedCostSummary = nil - self.cachedCostErrorText = self.compactUsageError(error) - } - self.costCacheUpdatedAt = Date() - } - - private func compactUsageError(_ error: Error) -> String { - let message = error.localizedDescription.trimmingCharacters(in: .whitespacesAndNewlines) - if message.isEmpty { return "Usage unavailable" } - if message.count > 90 { return "\(message.prefix(87))…" } - return message - } - - private func compactError(_ error: Error) -> String { - if let loadError = error as? SessionLoadError { - switch loadError { - case .gatewayUnavailable: - return "No connection to gateway" - case .decodeFailed: - return "Sessions unavailable" - } - } - return "Sessions unavailable" - } -} - -extension MenuSessionsInjector { - // MARK: - Submenus - - private func buildSubmenu(for row: SessionRow, storePath: String) -> NSMenu { - let menu = NSMenu() - let width = self.submenuWidth() - - menu.addItem(self.makeSessionPreviewItem( - sessionKey: row.key, - title: "Recent messages (last 10)", - width: width, - maxLines: 3)) - - let morePreview = NSMenuItem(title: "More preview…", action: nil, keyEquivalent: "") - morePreview.submenu = self.buildPreviewSubmenu(sessionKey: row.key, width: width) - menu.addItem(morePreview) - - menu.addItem(NSMenuItem.separator()) - - let thinking = NSMenuItem(title: "Thinking", action: nil, keyEquivalent: "") - thinking.submenu = self.buildThinkingMenu(for: row) - menu.addItem(thinking) - - let verbose = NSMenuItem(title: "Verbose", action: nil, keyEquivalent: "") - verbose.submenu = self.buildVerboseMenu(for: row) - menu.addItem(verbose) - - if AppStateStore.shared.debugPaneEnabled, - AppStateStore.shared.connectionMode == .local, - let sessionId = row.sessionId, - !sessionId.isEmpty - { - menu.addItem(NSMenuItem.separator()) - let openLog = NSMenuItem( - title: "Open Session Log", - action: #selector(self.openSessionLog(_:)), - keyEquivalent: "") - openLog.target = self - openLog.representedObject = [ - "sessionId": sessionId, - "storePath": storePath, - ] - menu.addItem(openLog) - } - - menu.addItem(NSMenuItem.separator()) - - let reset = NSMenuItem(title: "Reset Session", action: #selector(self.resetSession(_:)), keyEquivalent: "") - reset.target = self - reset.representedObject = row.key - menu.addItem(reset) - - let compact = NSMenuItem( - title: "Compact Session Log", - action: #selector(self.compactSession(_:)), - keyEquivalent: "") - compact.target = self - compact.representedObject = row.key - menu.addItem(compact) - - if row.key != self.mainSessionKey, row.key != "global" { - let del = NSMenuItem(title: "Delete Session", action: #selector(self.deleteSession(_:)), keyEquivalent: "") - del.target = self - del.representedObject = row.key - del.isAlternate = false - del.keyEquivalentModifierMask = [] - menu.addItem(del) - } - - return menu - } - - private func buildThinkingMenu(for row: SessionRow) -> NSMenu { - let menu = NSMenu() - menu.autoenablesItems = false - menu.showsStateColumn = true - let levels: [String] = ["off", "minimal", "low", "medium", "high"] - let current = levels.contains(row.thinkingLevel ?? "") ? row.thinkingLevel ?? "off" : "off" - for level in levels { - let title = level.capitalized - let item = NSMenuItem(title: title, action: #selector(self.patchThinking(_:)), keyEquivalent: "") - item.target = self - item.representedObject = [ - "key": row.key, - "value": level as Any, - ] - item.state = (current == level) ? .on : .off - menu.addItem(item) - } - return menu - } - - private func buildVerboseMenu(for row: SessionRow) -> NSMenu { - let menu = NSMenu() - menu.autoenablesItems = false - menu.showsStateColumn = true - let levels: [String] = ["on", "off"] - let current = levels.contains(row.verboseLevel ?? "") ? row.verboseLevel ?? "off" : "off" - for level in levels { - let title = level.capitalized - let item = NSMenuItem(title: title, action: #selector(self.patchVerbose(_:)), keyEquivalent: "") - item.target = self - item.representedObject = [ - "key": row.key, - "value": level as Any, - ] - item.state = (current == level) ? .on : .off - menu.addItem(item) - } - return menu - } - - private func buildPreviewSubmenu(sessionKey: String, width: CGFloat) -> NSMenu { - let menu = NSMenu() - menu.addItem(self.makeSessionPreviewItem( - sessionKey: sessionKey, - title: "Recent messages (expanded)", - width: width, - maxLines: 8)) - return menu - } - - private func buildNodesOverflowMenu(entries: [NodeInfo], width: CGFloat) -> NSMenu { - let menu = NSMenu() - for entry in entries { - let item = NSMenuItem() - item.target = self - item.action = #selector(self.copyNodeSummary(_:)) - item.representedObject = NodeMenuEntryFormatter.summaryText(entry) - item.view = HighlightedMenuItemHostView( - rootView: AnyView(NodeMenuRowView(entry: entry, width: width)), - width: width) - item.submenu = self.buildNodeSubmenu(entry: entry, width: width) - menu.addItem(item) - } - return menu - } - - private func buildNodeSubmenu(entry: NodeInfo, width: CGFloat) -> NSMenu { - let menu = NSMenu() - menu.autoenablesItems = false - - menu.addItem(self.makeNodeCopyItem(label: "Node ID", value: entry.nodeId)) - - if let name = entry.displayName?.nonEmpty { - menu.addItem(self.makeNodeCopyItem(label: "Name", value: name)) - } - - if let ip = entry.remoteIp?.nonEmpty { - menu.addItem(self.makeNodeCopyItem(label: "IP", value: ip)) - } - - menu.addItem(self.makeNodeCopyItem(label: "Status", value: NodeMenuEntryFormatter.roleText(entry))) - - if let platform = NodeMenuEntryFormatter.platformText(entry) { - menu.addItem(self.makeNodeCopyItem(label: "Platform", value: platform)) - } - - if let version = NodeMenuEntryFormatter.detailRightVersion(entry)?.nonEmpty { - menu.addItem(self.makeNodeCopyItem(label: "Version", value: version)) - } - - menu.addItem(self.makeNodeDetailItem(label: "Connected", value: entry.isConnected ? "Yes" : "No")) - menu.addItem(self.makeNodeDetailItem(label: "Paired", value: entry.isPaired ? "Yes" : "No")) - - if let caps = entry.caps?.filter({ !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }), - !caps.isEmpty - { - menu.addItem(self.makeNodeCopyItem(label: "Caps", value: caps.joined(separator: ", "))) - } - - if let commands = entry.commands?.filter({ !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }), - !commands.isEmpty - { - menu.addItem(self.makeNodeMultilineItem( - label: "Commands", - value: commands.joined(separator: ", "), - width: width)) - } - - return menu - } - - private func makeNodeDetailItem(label: String, value: String) -> NSMenuItem { - let item = NSMenuItem(title: "\(label): \(value)", action: nil, keyEquivalent: "") - item.isEnabled = false - return item - } - - private func makeNodeCopyItem(label: String, value: String) -> NSMenuItem { - let item = NSMenuItem(title: "\(label): \(value)", action: #selector(self.copyNodeValue(_:)), keyEquivalent: "") - item.target = self - item.representedObject = value - return item - } - - private func makeNodeMultilineItem(label: String, value: String, width: CGFloat) -> NSMenuItem { - let item = NSMenuItem() - item.target = self - item.action = #selector(self.copyNodeValue(_:)) - item.representedObject = value - item.view = HighlightedMenuItemHostView( - rootView: AnyView(NodeMenuMultilineView(label: label, value: value, width: width)), - width: width) - return item - } - - private func formatVersionLabel(_ version: String) -> String { - let trimmed = version.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return version } - if trimmed.hasPrefix("v") { return trimmed } - if let first = trimmed.unicodeScalars.first, CharacterSet.decimalDigits.contains(first) { - return "v\(trimmed)" - } - return trimmed - } - - @objc - private func patchThinking(_ sender: NSMenuItem) { - guard let dict = sender.representedObject as? [String: Any], - let key = dict["key"] as? String - else { return } - let value = dict["value"] as? String - Task { - do { - try await SessionActions.patchSession(key: key, thinking: .some(value)) - await self.refreshCache(force: true) - } catch { - await MainActor.run { - SessionActions.presentError(title: "Update thinking failed", error: error) - } - } - } - } - - @objc - private func patchVerbose(_ sender: NSMenuItem) { - guard let dict = sender.representedObject as? [String: Any], - let key = dict["key"] as? String - else { return } - let value = dict["value"] as? String - Task { - do { - try await SessionActions.patchSession(key: key, verbose: .some(value)) - await self.refreshCache(force: true) - } catch { - await MainActor.run { - SessionActions.presentError(title: "Update verbose failed", error: error) - } - } - } - } - - @objc - private func openSessionLog(_ sender: NSMenuItem) { - guard let dict = sender.representedObject as? [String: String], - let sessionId = dict["sessionId"], - let storePath = dict["storePath"] - else { return } - SessionActions.openSessionLogInCode(sessionId: sessionId, storePath: storePath) - } - - @objc - private func resetSession(_ sender: NSMenuItem) { - guard let key = sender.representedObject as? String else { return } - Task { @MainActor in - guard SessionActions.confirmDestructiveAction( - title: "Reset session?", - message: "Starts a new session id for “\(key)”.", - action: "Reset") - else { return } - - do { - try await SessionActions.resetSession(key: key) - await self.refreshCache(force: true) - } catch { - SessionActions.presentError(title: "Reset failed", error: error) - } - } - } - - @objc - private func compactSession(_ sender: NSMenuItem) { - guard let key = sender.representedObject as? String else { return } - Task { @MainActor in - guard SessionActions.confirmDestructiveAction( - title: "Compact session log?", - message: "Keeps the last 400 lines; archives the old file.", - action: "Compact") - else { return } - - do { - try await SessionActions.compactSession(key: key, maxLines: 400) - await self.refreshCache(force: true) - } catch { - SessionActions.presentError(title: "Compact failed", error: error) - } - } - } - - @objc - private func deleteSession(_ sender: NSMenuItem) { - guard let key = sender.representedObject as? String else { return } - Task { @MainActor in - guard SessionActions.confirmDestructiveAction( - title: "Delete session?", - message: "Deletes the “\(key)” entry and archives its transcript.", - action: "Delete") - else { return } - - do { - try await SessionActions.deleteSession(key: key) - await self.refreshCache(force: true) - } catch { - SessionActions.presentError(title: "Delete failed", error: error) - } - } - } - - @objc - private func copyNodeSummary(_ sender: NSMenuItem) { - guard let summary = sender.representedObject as? String else { return } - NSPasteboard.general.clearContents() - NSPasteboard.general.setString(summary, forType: .string) - } - - @objc - private func copyNodeValue(_ sender: NSMenuItem) { - guard let value = sender.representedObject as? String else { return } - NSPasteboard.general.clearContents() - NSPasteboard.general.setString(value, forType: .string) - } -} - -extension MenuSessionsInjector { - // MARK: - Width + placement - - private func findInsertIndex(in menu: NSMenu) -> Int? { - // Insert right before the separator above "Send Heartbeats". - if let idx = menu.items.firstIndex(where: { $0.title == "Send Heartbeats" }) { - if let sepIdx = menu.items[..= 1 { return 1 } - return menu.items.count - } - - private func findNodesInsertIndex(in menu: NSMenu) -> Int? { - if let idx = menu.items.firstIndex(where: { $0.title == "Send Heartbeats" }) { - if let sepIdx = menu.items[..= 1 { return 1 } - return menu.items.count - } - - private func initialWidth(for menu: NSMenu) -> CGFloat { - if let openWidth = self.menuOpenWidth { - return max(300, openWidth) - } - return self.currentMenuWidth(for: menu) - } - - private func submenuWidth() -> CGFloat { - if let openWidth = self.menuOpenWidth { - return max(300, openWidth) - } - if let cached = self.lastKnownMenuWidth { - return max(300, cached) - } - return self.fallbackWidth - } - - private func menuWindowWidth(for menu: NSMenu) -> CGFloat? { - var menuWindow: NSWindow? - for item in menu.items { - if let window = item.view?.window { - menuWindow = window - break - } - } - guard let width = menuWindow?.contentView?.bounds.width, width > 0 else { return nil } - return width - } - - private func sortedNodeEntries() -> [NodeInfo] { - let entries = self.nodesStore.nodes.filter(\.isConnected) - return entries.sorted { lhs, rhs in - if lhs.isConnected != rhs.isConnected { return lhs.isConnected } - if lhs.isPaired != rhs.isPaired { return lhs.isPaired } - let lhsName = NodeMenuEntryFormatter.primaryName(lhs).lowercased() - let rhsName = NodeMenuEntryFormatter.primaryName(rhs).lowercased() - if lhsName == rhsName { return lhs.nodeId < rhs.nodeId } - return lhsName < rhsName - } - } -} - -extension MenuSessionsInjector { - // MARK: - Views - - private func makeHostedView(rootView: AnyView, width: CGFloat, highlighted: Bool) -> NSView { - if highlighted { - return HighlightedMenuItemHostView(rootView: rootView, width: width) - } - - let hosting = NSHostingView(rootView: rootView) - hosting.frame.size.width = max(1, width) - let size = hosting.fittingSize - hosting.frame = NSRect(origin: .zero, size: NSSize(width: width, height: size.height)) - return hosting - } - - private func captureMenuWidthIfAvailable(from view: NSView) { - guard !self.isMenuOpen else { return } - guard let width = view.window?.contentView?.bounds.width, width > 0 else { return } - self.lastKnownMenuWidth = max(300, width) - } - - private func currentMenuWidth(for menu: NSMenu) -> CGFloat { - if let width = self.menuWindowWidth(for: menu) { - return max(300, width) - } - let candidates: [CGFloat] = [ - menu.size.width, - menu.minimumWidth, - self.lastKnownMenuWidth ?? 0, - self.fallbackWidth, - ] - let resolved = candidates.max() ?? self.fallbackWidth - return max(300, resolved) - } -} - -#if DEBUG -extension MenuSessionsInjector { - func setTestingControlChannelConnected(_ connected: Bool?) { - self.testControlChannelConnected = connected - } - - func setTestingSnapshot(_ snapshot: SessionStoreSnapshot?, errorText: String? = nil) { - self.cachedSnapshot = snapshot - self.cachedErrorText = errorText - self.cacheUpdatedAt = Date() - } - - func setTestingUsageSummary(_ summary: GatewayUsageSummary?, errorText: String? = nil) { - self.cachedUsageSummary = summary - self.cachedUsageErrorText = errorText - self.usageCacheUpdatedAt = Date() - } - - func injectForTesting(into menu: NSMenu) { - self.inject(into: menu) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/MenuUsageHeaderView.swift b/apps/macos/Sources/OpenClaw/MenuUsageHeaderView.swift deleted file mode 100644 index dbb717d690a..00000000000 --- a/apps/macos/Sources/OpenClaw/MenuUsageHeaderView.swift +++ /dev/null @@ -1,35 +0,0 @@ -import SwiftUI - -struct MenuUsageHeaderView: View { - let count: Int - - private let paddingTop: CGFloat = 8 - private let paddingBottom: CGFloat = 6 - private let paddingTrailing: CGFloat = 10 - private let paddingLeading: CGFloat = 20 - - var body: some View { - VStack(alignment: .leading, spacing: 6) { - HStack(alignment: .firstTextBaseline) { - Text("Usage") - .font(.caption.weight(.semibold)) - .foregroundStyle(.secondary) - Spacer(minLength: 10) - Text(self.subtitle) - .font(.caption) - .foregroundStyle(.secondary) - } - } - .padding(.top, self.paddingTop) - .padding(.bottom, self.paddingBottom) - .padding(.leading, self.paddingLeading) - .padding(.trailing, self.paddingTrailing) - .frame(minWidth: 300, maxWidth: .infinity, alignment: .leading) - .transaction { txn in txn.animation = nil } - } - - private var subtitle: String { - if self.count == 1 { return "1 provider" } - return "\(self.count) providers" - } -} diff --git a/apps/macos/Sources/OpenClaw/MicLevelMonitor.swift b/apps/macos/Sources/OpenClaw/MicLevelMonitor.swift deleted file mode 100644 index e35057d28cf..00000000000 --- a/apps/macos/Sources/OpenClaw/MicLevelMonitor.swift +++ /dev/null @@ -1,96 +0,0 @@ -import AVFoundation -import OSLog -import SwiftUI - -actor MicLevelMonitor { - private let logger = Logger(subsystem: "ai.openclaw", category: "voicewake.meter") - private var engine: AVAudioEngine? - private var update: (@Sendable (Double) -> Void)? - private var running = false - private var smoothedLevel: Double = 0 - - func start(onLevel: @Sendable @escaping (Double) -> Void) async throws { - self.update = onLevel - if self.running { return } - self.logger.info( - "mic level monitor start (\(AudioInputDeviceObserver.defaultInputDeviceSummary(), privacy: .public))") - let engine = AVAudioEngine() - self.engine = engine - let input = engine.inputNode - let format = input.outputFormat(forBus: 0) - guard format.channelCount > 0, format.sampleRate > 0 else { - self.engine = nil - throw NSError( - domain: "MicLevelMonitor", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "No audio input available"]) - } - input.removeTap(onBus: 0) - input.installTap(onBus: 0, bufferSize: 512, format: format) { [weak self] buffer, _ in - guard let self else { return } - let level = Self.normalizedLevel(from: buffer) - Task { await self.push(level: level) } - } - engine.prepare() - try engine.start() - self.running = true - } - - func stop() { - guard self.running else { return } - if let engine { - engine.inputNode.removeTap(onBus: 0) - engine.stop() - } - self.engine = nil - self.running = false - } - - private func push(level: Double) { - self.smoothedLevel = (self.smoothedLevel * 0.45) + (level * 0.55) - guard let update else { return } - let value = self.smoothedLevel - Task { @MainActor in update(value) } - } - - private static func normalizedLevel(from buffer: AVAudioPCMBuffer) -> Double { - guard let channel = buffer.floatChannelData?[0] else { return 0 } - let frameCount = Int(buffer.frameLength) - guard frameCount > 0 else { return 0 } - var sum: Float = 0 - for i in 0.. Double(idx) - RoundedRectangle(cornerRadius: 2) - .fill(fill ? self.segmentColor(for: idx) : Color.gray.opacity(0.35)) - .frame(width: 14, height: 10) - } - } - .padding(4) - .background( - RoundedRectangle(cornerRadius: 6) - .stroke(Color.gray.opacity(0.25), lineWidth: 1)) - } - - private func segmentColor(for idx: Int) -> Color { - let fraction = Double(idx + 1) / Double(self.segments) - if fraction < 0.65 { return .green } - if fraction < 0.85 { return .yellow } - return .red - } -} diff --git a/apps/macos/Sources/OpenClaw/ModelCatalogLoader.swift b/apps/macos/Sources/OpenClaw/ModelCatalogLoader.swift deleted file mode 100644 index b320c84d232..00000000000 --- a/apps/macos/Sources/OpenClaw/ModelCatalogLoader.swift +++ /dev/null @@ -1,159 +0,0 @@ -import Foundation -import JavaScriptCore - -enum ModelCatalogLoader { - static var defaultPath: String { - self.resolveDefaultPath() - } - - private static let logger = Logger(subsystem: "ai.openclaw", category: "models") - private nonisolated static let appSupportDir: URL = { - let base = FileManager().urls(for: .applicationSupportDirectory, in: .userDomainMask).first! - return base.appendingPathComponent("OpenClaw", isDirectory: true) - }() - - private static var cachePath: URL { - self.appSupportDir.appendingPathComponent("model-catalog/models.generated.js", isDirectory: false) - } - - static func load(from path: String) async throws -> [ModelChoice] { - let expanded = (path as NSString).expandingTildeInPath - guard let resolved = self.resolvePath(preferred: expanded) else { - self.logger.error("model catalog load failed: file not found") - throw NSError( - domain: "ModelCatalogLoader", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "Model catalog file not found"]) - } - self.logger.debug("model catalog load start file=\(URL(fileURLWithPath: resolved.path).lastPathComponent)") - let source = try String(contentsOfFile: resolved.path, encoding: .utf8) - let sanitized = self.sanitize(source: source) - - let ctx = JSContext() - ctx?.exceptionHandler = { _, exception in - if let exception { - self.logger.warning("model catalog JS exception: \(exception)") - } - } - ctx?.evaluateScript(sanitized) - guard let rawModels = ctx?.objectForKeyedSubscript("MODELS")?.toDictionary() as? [String: Any] else { - self.logger.error("model catalog parse failed: MODELS missing") - throw NSError( - domain: "ModelCatalogLoader", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "Failed to parse models.generated.ts"]) - } - - var choices: [ModelChoice] = [] - for (provider, value) in rawModels { - guard let models = value as? [String: Any] else { continue } - for (id, payload) in models { - guard let dict = payload as? [String: Any] else { continue } - let name = dict["name"] as? String ?? id - let ctxWindow = dict["contextWindow"] as? Int - choices.append(ModelChoice(id: id, name: name, provider: provider, contextWindow: ctxWindow)) - } - } - - let sorted = choices.sorted { lhs, rhs in - if lhs.provider == rhs.provider { - return lhs.name.localizedCaseInsensitiveCompare(rhs.name) == .orderedAscending - } - return lhs.provider.localizedCaseInsensitiveCompare(rhs.provider) == .orderedAscending - } - self.logger.debug("model catalog loaded providers=\(rawModels.count) models=\(sorted.count)") - if resolved.shouldCache { - self.cacheCatalog(sourcePath: resolved.path) - } - return sorted - } - - private static func resolveDefaultPath() -> String { - let cache = self.cachePath.path - if FileManager().isReadableFile(atPath: cache) { return cache } - if let bundlePath = self.bundleCatalogPath() { return bundlePath } - if let nodePath = self.nodeModulesCatalogPath() { return nodePath } - return cache - } - - private static func resolvePath(preferred: String) -> (path: String, shouldCache: Bool)? { - if FileManager().isReadableFile(atPath: preferred) { - return (preferred, preferred != self.cachePath.path) - } - - if let bundlePath = self.bundleCatalogPath(), bundlePath != preferred { - self.logger.warning("model catalog path missing; falling back to bundled catalog") - return (bundlePath, true) - } - - let cache = self.cachePath.path - if cache != preferred, FileManager().isReadableFile(atPath: cache) { - self.logger.warning("model catalog path missing; falling back to cached catalog") - return (cache, false) - } - - if let nodePath = self.nodeModulesCatalogPath(), nodePath != preferred { - self.logger.warning("model catalog path missing; falling back to node_modules catalog") - return (nodePath, true) - } - - return nil - } - - private static func bundleCatalogPath() -> String? { - guard let url = Bundle.main.url(forResource: "models.generated", withExtension: "js") else { - return nil - } - return url.path - } - - private static func nodeModulesCatalogPath() -> String? { - let roots = [ - URL(fileURLWithPath: CommandResolver.projectRootPath()), - URL(fileURLWithPath: FileManager().currentDirectoryPath), - ] - for root in roots { - let candidate = root - .appendingPathComponent("node_modules/@mariozechner/pi-ai/dist/models.generated.js") - if FileManager().isReadableFile(atPath: candidate.path) { - return candidate.path - } - } - return nil - } - - private static func cacheCatalog(sourcePath: String) { - let destination = self.cachePath - do { - try FileManager().createDirectory( - at: destination.deletingLastPathComponent(), - withIntermediateDirectories: true) - if FileManager().fileExists(atPath: destination.path) { - try FileManager().removeItem(at: destination) - } - try FileManager().copyItem(atPath: sourcePath, toPath: destination.path) - self.logger.debug("model catalog cached file=\(destination.lastPathComponent)") - } catch { - self.logger.warning("model catalog cache failed: \(error.localizedDescription)") - } - } - - private static func sanitize(source: String) -> String { - guard let exportRange = source.range(of: "export const MODELS"), - let firstBrace = source[exportRange.upperBound...].firstIndex(of: "{"), - let lastBrace = source.lastIndex(of: "}") - else { - return "var MODELS = {}" - } - var body = String(source[firstBrace...lastBrace]) - body = body.replacingOccurrences( - of: #"(?m)\bsatisfies\s+[^,}\n]+"#, - with: "", - options: .regularExpression) - body = body.replacingOccurrences( - of: #"(?m)\bas\s+[^;,\n]+"#, - with: "", - options: .regularExpression) - return "var MODELS = \(body);" - } -} diff --git a/apps/macos/Sources/OpenClaw/NSAttributedString+VoiceWake.swift b/apps/macos/Sources/OpenClaw/NSAttributedString+VoiceWake.swift deleted file mode 100644 index cb4be425834..00000000000 --- a/apps/macos/Sources/OpenClaw/NSAttributedString+VoiceWake.swift +++ /dev/null @@ -1,9 +0,0 @@ -import Foundation - -extension NSAttributedString { - func strippingForegroundColor() -> NSAttributedString { - let mutable = NSMutableAttributedString(attributedString: self) - mutable.removeAttribute(.foregroundColor, range: NSRange(location: 0, length: mutable.length)) - return mutable - } -} diff --git a/apps/macos/Sources/OpenClaw/NodeMode/MacNodeLocationService.swift b/apps/macos/Sources/OpenClaw/NodeMode/MacNodeLocationService.swift deleted file mode 100644 index bd4df512ca4..00000000000 --- a/apps/macos/Sources/OpenClaw/NodeMode/MacNodeLocationService.swift +++ /dev/null @@ -1,139 +0,0 @@ -import CoreLocation -import Foundation -import OpenClawKit - -@MainActor -final class MacNodeLocationService: NSObject, CLLocationManagerDelegate { - enum Error: Swift.Error { - case timeout - case unavailable - } - - private let manager = CLLocationManager() - private var locationContinuation: CheckedContinuation? - - override init() { - super.init() - self.manager.delegate = self - self.manager.desiredAccuracy = kCLLocationAccuracyBest - } - - func authorizationStatus() -> CLAuthorizationStatus { - self.manager.authorizationStatus - } - - func accuracyAuthorization() -> CLAccuracyAuthorization { - if #available(macOS 11.0, *) { - return self.manager.accuracyAuthorization - } - return .fullAccuracy - } - - func currentLocation( - desiredAccuracy: OpenClawLocationAccuracy, - maxAgeMs: Int?, - timeoutMs: Int?) async throws -> CLLocation - { - guard CLLocationManager.locationServicesEnabled() else { - throw Error.unavailable - } - - let now = Date() - if let maxAgeMs, - let cached = self.manager.location, - now.timeIntervalSince(cached.timestamp) * 1000 <= Double(maxAgeMs) - { - return cached - } - - self.manager.desiredAccuracy = Self.accuracyValue(desiredAccuracy) - let timeout = max(0, timeoutMs ?? 10000) - return try await self.withTimeout(timeoutMs: timeout) { - try await self.requestLocation() - } - } - - private func requestLocation() async throws -> CLLocation { - try await withCheckedThrowingContinuation { cont in - self.locationContinuation = cont - self.manager.requestLocation() - } - } - - private func withTimeout( - timeoutMs: Int, - operation: @escaping () async throws -> T) async throws -> T - { - if timeoutMs == 0 { - return try await operation() - } - - return try await withCheckedThrowingContinuation { continuation in - var didFinish = false - - func finish(returning value: T) { - guard !didFinish else { return } - didFinish = true - continuation.resume(returning: value) - } - - func finish(throwing error: Swift.Error) { - guard !didFinish else { return } - didFinish = true - continuation.resume(throwing: error) - } - - let timeoutItem = DispatchWorkItem { - finish(throwing: Error.timeout) - } - DispatchQueue.main.asyncAfter( - deadline: .now() + .milliseconds(timeoutMs), - execute: timeoutItem) - - Task { @MainActor in - do { - let value = try await operation() - timeoutItem.cancel() - finish(returning: value) - } catch { - timeoutItem.cancel() - finish(throwing: error) - } - } - } - } - - private static func accuracyValue(_ accuracy: OpenClawLocationAccuracy) -> CLLocationAccuracy { - switch accuracy { - case .coarse: - kCLLocationAccuracyKilometer - case .balanced: - kCLLocationAccuracyHundredMeters - case .precise: - kCLLocationAccuracyBest - } - } - - // MARK: - CLLocationManagerDelegate (nonisolated for Swift 6 compatibility) - - nonisolated func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { - Task { @MainActor in - guard let cont = self.locationContinuation else { return } - self.locationContinuation = nil - if let latest = locations.last { - cont.resume(returning: latest) - } else { - cont.resume(throwing: Error.unavailable) - } - } - } - - nonisolated func locationManager(_ manager: CLLocationManager, didFailWithError error: Swift.Error) { - let errorCopy = error // Capture error for Sendable compliance - Task { @MainActor in - guard let cont = self.locationContinuation else { return } - self.locationContinuation = nil - cont.resume(throwing: errorCopy) - } - } -} diff --git a/apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swift b/apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swift deleted file mode 100644 index af46788c9cc..00000000000 --- a/apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swift +++ /dev/null @@ -1,171 +0,0 @@ -import Foundation -import OpenClawKit -import OSLog - -@MainActor -final class MacNodeModeCoordinator { - static let shared = MacNodeModeCoordinator() - - private let logger = Logger(subsystem: "ai.openclaw", category: "mac-node") - private var task: Task? - private let runtime = MacNodeRuntime() - private let session = GatewayNodeSession() - - func start() { - guard self.task == nil else { return } - self.task = Task { [weak self] in - await self?.run() - } - } - - func stop() { - self.task?.cancel() - self.task = nil - Task { await self.session.disconnect() } - } - - func setPreferredGatewayStableID(_ stableID: String?) { - GatewayDiscoveryPreferences.setPreferredStableID(stableID) - Task { await self.session.disconnect() } - } - - private func run() async { - var retryDelay: UInt64 = 1_000_000_000 - var lastCameraEnabled: Bool? - let defaults = UserDefaults.standard - - while !Task.isCancelled { - if await MainActor.run(body: { AppStateStore.shared.isPaused }) { - try? await Task.sleep(nanoseconds: 1_000_000_000) - continue - } - - let cameraEnabled = defaults.object(forKey: cameraEnabledKey) as? Bool ?? false - if lastCameraEnabled == nil { - lastCameraEnabled = cameraEnabled - } else if lastCameraEnabled != cameraEnabled { - lastCameraEnabled = cameraEnabled - await self.session.disconnect() - try? await Task.sleep(nanoseconds: 200_000_000) - } - - do { - let config = try await GatewayEndpointStore.shared.requireConfig() - let caps = self.currentCaps() - let commands = self.currentCommands(caps: caps) - let permissions = await self.currentPermissions() - let connectOptions = GatewayConnectOptions( - role: "node", - scopes: [], - caps: caps, - commands: commands, - permissions: permissions, - clientId: "openclaw-macos", - clientMode: "node", - clientDisplayName: InstanceIdentity.displayName) - let sessionBox = self.buildSessionBox(url: config.url) - - try await self.session.connect( - url: config.url, - token: config.token, - password: config.password, - connectOptions: connectOptions, - sessionBox: sessionBox, - onConnected: { [weak self] in - guard let self else { return } - self.logger.info("mac node connected to gateway") - let mainSessionKey = await GatewayConnection.shared.mainSessionKey() - await self.runtime.updateMainSessionKey(mainSessionKey) - await self.runtime.setEventSender { [weak self] event, payload in - guard let self else { return } - await self.session.sendEvent(event: event, payloadJSON: payload) - } - }, - onDisconnected: { [weak self] reason in - guard let self else { return } - await self.runtime.setEventSender(nil) - self.logger.error("mac node disconnected: \(reason, privacy: .public)") - }, - onInvoke: { [weak self] req in - guard let self else { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: .unavailable, message: "UNAVAILABLE: node not ready")) - } - return await self.runtime.handleInvoke(req) - }) - - retryDelay = 1_000_000_000 - try? await Task.sleep(nanoseconds: 1_000_000_000) - } catch { - self.logger.error("mac node gateway connect failed: \(error.localizedDescription, privacy: .public)") - try? await Task.sleep(nanoseconds: min(retryDelay, 10_000_000_000)) - retryDelay = min(retryDelay * 2, 10_000_000_000) - } - } - } - - private func currentCaps() -> [String] { - var caps: [String] = [OpenClawCapability.canvas.rawValue, OpenClawCapability.screen.rawValue] - if UserDefaults.standard.object(forKey: cameraEnabledKey) as? Bool ?? false { - caps.append(OpenClawCapability.camera.rawValue) - } - let rawLocationMode = UserDefaults.standard.string(forKey: locationModeKey) ?? "off" - if OpenClawLocationMode(rawValue: rawLocationMode) != .off { - caps.append(OpenClawCapability.location.rawValue) - } - return caps - } - - private func currentPermissions() async -> [String: Bool] { - let statuses = await PermissionManager.status() - return Dictionary(uniqueKeysWithValues: statuses.map { ($0.key.rawValue, $0.value) }) - } - - private func currentCommands(caps: [String]) -> [String] { - var commands: [String] = [ - OpenClawCanvasCommand.present.rawValue, - OpenClawCanvasCommand.hide.rawValue, - OpenClawCanvasCommand.navigate.rawValue, - OpenClawCanvasCommand.evalJS.rawValue, - OpenClawCanvasCommand.snapshot.rawValue, - OpenClawCanvasA2UICommand.push.rawValue, - OpenClawCanvasA2UICommand.pushJSONL.rawValue, - OpenClawCanvasA2UICommand.reset.rawValue, - MacNodeScreenCommand.record.rawValue, - OpenClawSystemCommand.notify.rawValue, - OpenClawSystemCommand.which.rawValue, - OpenClawSystemCommand.run.rawValue, - OpenClawSystemCommand.execApprovalsGet.rawValue, - OpenClawSystemCommand.execApprovalsSet.rawValue, - ] - - let capsSet = Set(caps) - if capsSet.contains(OpenClawCapability.camera.rawValue) { - commands.append(OpenClawCameraCommand.list.rawValue) - commands.append(OpenClawCameraCommand.snap.rawValue) - commands.append(OpenClawCameraCommand.clip.rawValue) - } - if capsSet.contains(OpenClawCapability.location.rawValue) { - commands.append(OpenClawLocationCommand.get.rawValue) - } - - return commands - } - - private func buildSessionBox(url: URL) -> WebSocketSessionBox? { - guard url.scheme?.lowercased() == "wss" else { return nil } - let host = url.host ?? "gateway" - let port = url.port ?? 443 - let stableID = "\(host):\(port)" - let stored = GatewayTLSStore.loadFingerprint(stableID: stableID) - let params = GatewayTLSParams( - required: true, - expectedFingerprint: stored, - allowTOFU: stored == nil, - storeKey: stableID) - let session = GatewayTLSPinningSession(params: params) - return WebSocketSessionBox(session: session) - } -} diff --git a/apps/macos/Sources/OpenClaw/NodeMode/MacNodeRuntime.swift b/apps/macos/Sources/OpenClaw/NodeMode/MacNodeRuntime.swift deleted file mode 100644 index cda8ca6057c..00000000000 --- a/apps/macos/Sources/OpenClaw/NodeMode/MacNodeRuntime.swift +++ /dev/null @@ -1,1002 +0,0 @@ -import AppKit -import Foundation -import OpenClawIPC -import OpenClawKit - -actor MacNodeRuntime { - private let cameraCapture = CameraCaptureService() - private let makeMainActorServices: () async -> any MacNodeRuntimeMainActorServices - private var cachedMainActorServices: (any MacNodeRuntimeMainActorServices)? - private var mainSessionKey: String = "main" - private var eventSender: (@Sendable (String, String?) async -> Void)? - - init( - makeMainActorServices: @escaping () async -> any MacNodeRuntimeMainActorServices = { - await MainActor.run { LiveMacNodeRuntimeMainActorServices() } - }) - { - self.makeMainActorServices = makeMainActorServices - } - - func updateMainSessionKey(_ sessionKey: String) { - let trimmed = sessionKey.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return } - self.mainSessionKey = trimmed - } - - func setEventSender(_ sender: (@Sendable (String, String?) async -> Void)?) { - self.eventSender = sender - } - - func handleInvoke(_ req: BridgeInvokeRequest) async -> BridgeInvokeResponse { - let command = req.command - if self.isCanvasCommand(command), !Self.canvasEnabled() { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "CANVAS_DISABLED: enable Canvas in Settings")) - } - do { - switch command { - case OpenClawCanvasCommand.present.rawValue, - OpenClawCanvasCommand.hide.rawValue, - OpenClawCanvasCommand.navigate.rawValue, - OpenClawCanvasCommand.evalJS.rawValue, - OpenClawCanvasCommand.snapshot.rawValue: - return try await self.handleCanvasInvoke(req) - case OpenClawCanvasA2UICommand.reset.rawValue, - OpenClawCanvasA2UICommand.push.rawValue, - OpenClawCanvasA2UICommand.pushJSONL.rawValue: - return try await self.handleA2UIInvoke(req) - case OpenClawCameraCommand.snap.rawValue, - OpenClawCameraCommand.clip.rawValue, - OpenClawCameraCommand.list.rawValue: - return try await self.handleCameraInvoke(req) - case OpenClawLocationCommand.get.rawValue: - return try await self.handleLocationInvoke(req) - case MacNodeScreenCommand.record.rawValue: - return try await self.handleScreenRecordInvoke(req) - case OpenClawSystemCommand.run.rawValue: - return try await self.handleSystemRun(req) - case OpenClawSystemCommand.which.rawValue: - return try await self.handleSystemWhich(req) - case OpenClawSystemCommand.notify.rawValue: - return try await self.handleSystemNotify(req) - case OpenClawSystemCommand.execApprovalsGet.rawValue: - return try await self.handleSystemExecApprovalsGet(req) - case OpenClawSystemCommand.execApprovalsSet.rawValue: - return try await self.handleSystemExecApprovalsSet(req) - default: - return Self.errorResponse(req, code: .invalidRequest, message: "INVALID_REQUEST: unknown command") - } - } catch { - return Self.errorResponse(req, code: .unavailable, message: error.localizedDescription) - } - } - - private func isCanvasCommand(_ command: String) -> Bool { - command.hasPrefix("canvas.") || command.hasPrefix("canvas.a2ui.") - } - - private func handleCanvasInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - switch req.command { - case OpenClawCanvasCommand.present.rawValue: - let params = (try? Self.decodeParams(OpenClawCanvasPresentParams.self, from: req.paramsJSON)) ?? - OpenClawCanvasPresentParams() - let urlTrimmed = params.url?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let url = urlTrimmed.isEmpty ? nil : urlTrimmed - let placement = params.placement.map { - CanvasPlacement(x: $0.x, y: $0.y, width: $0.width, height: $0.height) - } - let sessionKey = self.mainSessionKey - try await MainActor.run { - _ = try CanvasManager.shared.showDetailed( - sessionKey: sessionKey, - target: url, - placement: placement) - } - return BridgeInvokeResponse(id: req.id, ok: true) - case OpenClawCanvasCommand.hide.rawValue: - let sessionKey = self.mainSessionKey - await MainActor.run { - CanvasManager.shared.hide(sessionKey: sessionKey) - } - return BridgeInvokeResponse(id: req.id, ok: true) - case OpenClawCanvasCommand.navigate.rawValue: - let params = try Self.decodeParams(OpenClawCanvasNavigateParams.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 OpenClawCanvasCommand.evalJS.rawValue: - let params = try Self.decodeParams(OpenClawCanvasEvalParams.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 OpenClawCanvasCommand.snapshot.rawValue: - let params = try? Self.decodeParams(OpenClawCanvasSnapshotParams.self, from: req.paramsJSON) - let format = params?.format ?? .jpeg - let maxWidth: Int? = { - if let raw = params?.maxWidth, raw > 0 { return raw } - return switch format { - case .png: 900 - case .jpeg: 1600 - } - }() - let quality = params?.quality ?? 0.9 - - let sessionKey = self.mainSessionKey - let path = try await CanvasManager.shared.snapshot(sessionKey: sessionKey, outPath: nil) - defer { try? FileManager().removeItem(atPath: path) } - let data = try Data(contentsOf: URL(fileURLWithPath: path)) - guard let image = NSImage(data: data) else { - return Self.errorResponse(req, code: .unavailable, message: "canvas snapshot decode failed") - } - let encoded = try Self.encodeCanvasSnapshot( - image: image, - format: format, - maxWidth: maxWidth, - quality: quality) - let payload = try Self.encodePayload([ - "format": format == .jpeg ? "jpeg" : "png", - "base64": encoded.base64EncodedString(), - ]) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - default: - return Self.errorResponse(req, code: .invalidRequest, message: "INVALID_REQUEST: unknown command") - } - } - - private func handleA2UIInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - switch req.command { - case OpenClawCanvasA2UICommand.reset.rawValue: - try await self.handleA2UIReset(req) - case OpenClawCanvasA2UICommand.push.rawValue, - OpenClawCanvasA2UICommand.pushJSONL.rawValue: - try await self.handleA2UIPush(req) - default: - Self.errorResponse(req, code: .invalidRequest, message: "INVALID_REQUEST: unknown command") - } - } - - private func handleCameraInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - guard Self.cameraEnabled() else { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "CAMERA_DISABLED: enable Camera in Settings")) - } - switch req.command { - case OpenClawCameraCommand.snap.rawValue: - let params = (try? Self.decodeParams(OpenClawCameraSnapParams.self, from: req.paramsJSON)) ?? - OpenClawCameraSnapParams() - let delayMs = min(10000, max(0, params.delayMs ?? 2000)) - let res = try await self.cameraCapture.snap( - facing: CameraFacing(rawValue: params.facing?.rawValue ?? "") ?? .front, - maxWidth: params.maxWidth, - quality: params.quality, - deviceId: params.deviceId, - delayMs: delayMs) - struct SnapPayload: Encodable { - var format: String - var base64: String - var width: Int - var height: Int - } - let payload = try Self.encodePayload(SnapPayload( - format: (params.format ?? .jpg).rawValue, - base64: res.data.base64EncodedString(), - width: Int(res.size.width), - height: Int(res.size.height))) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - case OpenClawCameraCommand.clip.rawValue: - let params = (try? Self.decodeParams(OpenClawCameraClipParams.self, from: req.paramsJSON)) ?? - OpenClawCameraClipParams() - let res = try await self.cameraCapture.clip( - facing: CameraFacing(rawValue: params.facing?.rawValue ?? "") ?? .front, - durationMs: params.durationMs, - includeAudio: params.includeAudio ?? true, - deviceId: params.deviceId, - outPath: nil) - defer { try? FileManager().removeItem(atPath: res.path) } - let data = try Data(contentsOf: URL(fileURLWithPath: res.path)) - struct ClipPayload: Encodable { - var format: String - var base64: String - var durationMs: Int - var hasAudio: Bool - } - let payload = try Self.encodePayload(ClipPayload( - format: (params.format ?? .mp4).rawValue, - base64: data.base64EncodedString(), - durationMs: res.durationMs, - hasAudio: res.hasAudio)) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - case OpenClawCameraCommand.list.rawValue: - let devices = await self.cameraCapture.listDevices() - let payload = try Self.encodePayload(["devices": devices]) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - default: - return Self.errorResponse(req, code: .invalidRequest, message: "INVALID_REQUEST: unknown command") - } - } - - private func handleLocationInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - let mode = Self.locationMode() - guard mode != .off else { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "LOCATION_DISABLED: enable Location in Settings")) - } - let params = (try? Self.decodeParams(OpenClawLocationGetParams.self, from: req.paramsJSON)) ?? - OpenClawLocationGetParams() - let desired = params.desiredAccuracy ?? - (Self.locationPreciseEnabled() ? .precise : .balanced) - let services = await self.mainActorServices() - let status = await services.locationAuthorizationStatus() - let hasPermission = switch mode { - case .always: - status == .authorizedAlways - case .whileUsing: - status == .authorizedAlways - case .off: - false - } - if !hasPermission { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "LOCATION_PERMISSION_REQUIRED: grant Location permission")) - } - do { - let location = try await services.currentLocation( - desiredAccuracy: desired, - maxAgeMs: params.maxAgeMs, - timeoutMs: params.timeoutMs) - let isPrecise = await services.locationAccuracyAuthorization() == .fullAccuracy - let payload = OpenClawLocationPayload( - lat: location.coordinate.latitude, - lon: location.coordinate.longitude, - accuracyMeters: location.horizontalAccuracy, - altitudeMeters: location.verticalAccuracy >= 0 ? location.altitude : nil, - speedMps: location.speed >= 0 ? location.speed : nil, - headingDeg: location.course >= 0 ? location.course : nil, - timestamp: ISO8601DateFormatter().string(from: location.timestamp), - isPrecise: isPrecise, - source: nil) - let json = try Self.encodePayload(payload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - } catch MacNodeLocationService.Error.timeout { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "LOCATION_TIMEOUT: no fix in time")) - } catch { - return BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError( - code: .unavailable, - message: "LOCATION_UNAVAILABLE: \(error.localizedDescription)")) - } - } - - private func handleScreenRecordInvoke(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - let params = (try? Self.decodeParams(MacNodeScreenRecordParams.self, from: req.paramsJSON)) ?? - MacNodeScreenRecordParams() - if let format = params.format?.lowercased(), !format.isEmpty, format != "mp4" { - return Self.errorResponse( - req, - code: .invalidRequest, - message: "INVALID_REQUEST: screen format must be mp4") - } - let services = await self.mainActorServices() - let res = try await services.recordScreen( - screenIndex: params.screenIndex, - durationMs: params.durationMs, - fps: params.fps, - includeAudio: params.includeAudio, - outPath: nil) - defer { try? FileManager().removeItem(atPath: res.path) } - let data = try Data(contentsOf: URL(fileURLWithPath: res.path)) - struct ScreenPayload: Encodable { - var format: String - var base64: String - var durationMs: Int? - var fps: Double? - var screenIndex: Int? - var hasAudio: Bool - } - let payload = try Self.encodePayload(ScreenPayload( - format: "mp4", - base64: data.base64EncodedString(), - durationMs: params.durationMs, - fps: params.fps, - screenIndex: params.screenIndex, - hasAudio: res.hasAudio)) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - } - - private func mainActorServices() async -> any MacNodeRuntimeMainActorServices { - if let cachedMainActorServices { return cachedMainActorServices } - let services = await self.makeMainActorServices() - self.cachedMainActorServices = services - return services - } - - private func handleA2UIReset(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - try await self.ensureA2UIHost() - - let sessionKey = self.mainSessionKey - let json = try await CanvasManager.shared.eval(sessionKey: sessionKey, javaScript: """ - (() => { - const host = globalThis.openclawA2UI; - if (!host) return JSON.stringify({ ok: false, error: "missing openclawA2UI" }); - return JSON.stringify(host.reset()); - })() - """) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json) - } - - private func handleA2UIPush(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - let command = req.command - let messages: [OpenClawKit.AnyCodable] - if command == OpenClawCanvasA2UICommand.pushJSONL.rawValue { - let params = try Self.decodeParams(OpenClawCanvasA2UIPushJSONLParams.self, from: req.paramsJSON) - messages = try OpenClawCanvasA2UIJSONL.decodeMessagesFromJSONL(params.jsonl) - } else { - do { - let params = try Self.decodeParams(OpenClawCanvasA2UIPushParams.self, from: req.paramsJSON) - messages = params.messages - } catch { - let params = try Self.decodeParams(OpenClawCanvasA2UIPushJSONLParams.self, from: req.paramsJSON) - messages = try OpenClawCanvasA2UIJSONL.decodeMessagesFromJSONL(params.jsonl) - } - } - - try await self.ensureA2UIHost() - - let messagesJSON = try OpenClawCanvasA2UIJSONL.encodeMessagesJSONArray(messages) - let js = """ - (() => { - try { - const host = globalThis.openclawA2UI; - if (!host) return JSON.stringify({ ok: false, error: "missing openclawA2UI" }); - const messages = \(messagesJSON); - return JSON.stringify(host.applyMessages(messages)); - } catch (e) { - return JSON.stringify({ ok: false, error: String(e?.message ?? e) }); - } - })() - """ - let sessionKey = self.mainSessionKey - let resultJSON = try await CanvasManager.shared.eval(sessionKey: sessionKey, javaScript: js) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: resultJSON) - } - - private func ensureA2UIHost() async throws { - if await self.isA2UIReady() { return } - guard let a2uiUrl = await self.resolveA2UIHostUrl() else { - throw NSError(domain: "Canvas", code: 30, userInfo: [ - NSLocalizedDescriptionKey: "A2UI_HOST_NOT_CONFIGURED: gateway did not advertise canvas host", - ]) - } - let sessionKey = self.mainSessionKey - _ = try await MainActor.run { - try CanvasManager.shared.show(sessionKey: sessionKey, path: a2uiUrl) - } - if await self.isA2UIReady(poll: true) { return } - throw NSError(domain: "Canvas", code: 31, userInfo: [ - NSLocalizedDescriptionKey: "A2UI_HOST_UNAVAILABLE: A2UI host not reachable", - ]) - } - - private func resolveA2UIHostUrl() async -> String? { - 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("__openclaw__/a2ui/").absoluteString + "?platform=macos" - } - - private func isA2UIReady(poll: Bool = false) async -> Bool { - let deadline = poll ? Date().addingTimeInterval(6.0) : Date() - while true { - do { - let sessionKey = self.mainSessionKey - let ready = try await CanvasManager.shared.eval(sessionKey: sessionKey, javaScript: """ - (() => { - const host = globalThis.openclawA2UI; - return String(Boolean(host)); - })() - """) - let trimmed = ready.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed == "true" { return true } - } catch { - // Ignore transient eval failures while the page is loading. - } - - guard poll, Date() < deadline else { return false } - try? await Task.sleep(nanoseconds: 120_000_000) - } - } - - private func handleSystemRun(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - let params = try Self.decodeParams(OpenClawSystemRunParams.self, from: req.paramsJSON) - let command = params.command - guard !command.isEmpty else { - return Self.errorResponse(req, code: .invalidRequest, message: "INVALID_REQUEST: command required") - } - let sessionKey = (params.sessionKey?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false) - ? params.sessionKey!.trimmingCharacters(in: .whitespacesAndNewlines) - : self.mainSessionKey - let runId = UUID().uuidString - let evaluation = await ExecApprovalEvaluator.evaluate( - command: command, - rawCommand: params.rawCommand, - cwd: params.cwd, - envOverrides: params.env, - agentId: params.agentId) - - if evaluation.security == .deny { - await self.emitExecEvent( - "exec.denied", - payload: ExecEventPayload( - sessionKey: sessionKey, - runId: runId, - host: "node", - command: evaluation.displayCommand, - reason: "security=deny")) - return Self.errorResponse( - req, - code: .unavailable, - message: "SYSTEM_RUN_DISABLED: security=deny") - } - - let approval = await self.resolveSystemRunApproval( - req: req, - params: params, - context: ExecRunContext( - displayCommand: evaluation.displayCommand, - security: evaluation.security, - ask: evaluation.ask, - agentId: evaluation.agentId, - resolution: evaluation.resolution, - allowlistMatch: evaluation.allowlistMatch, - skillAllow: evaluation.skillAllow, - sessionKey: sessionKey, - runId: runId)) - if let response = approval.response { return response } - let approvedByAsk = approval.approvedByAsk - let persistAllowlist = approval.persistAllowlist - self.persistAllowlistPatterns( - persistAllowlist: persistAllowlist, - security: evaluation.security, - agentId: evaluation.agentId, - command: command, - allowlistResolutions: evaluation.allowlistResolutions) - - if evaluation.security == .allowlist, !evaluation.allowlistSatisfied, !evaluation.skillAllow, !approvedByAsk { - await self.emitExecEvent( - "exec.denied", - payload: ExecEventPayload( - sessionKey: sessionKey, - runId: runId, - host: "node", - command: evaluation.displayCommand, - reason: "allowlist-miss")) - return Self.errorResponse( - req, - code: .unavailable, - message: "SYSTEM_RUN_DENIED: allowlist miss") - } - - self.recordAllowlistMatches( - security: evaluation.security, - allowlistSatisfied: evaluation.allowlistSatisfied, - agentId: evaluation.agentId, - allowlistMatches: evaluation.allowlistMatches, - allowlistResolutions: evaluation.allowlistResolutions, - displayCommand: evaluation.displayCommand) - - if let permissionResponse = await self.validateScreenRecordingIfNeeded( - req: req, - needsScreenRecording: params.needsScreenRecording, - sessionKey: sessionKey, - runId: runId, - displayCommand: evaluation.displayCommand) - { - return permissionResponse - } - - return try await self.executeSystemRun( - req: req, - params: params, - command: command, - env: evaluation.env, - sessionKey: sessionKey, - runId: runId, - displayCommand: evaluation.displayCommand) - } - - private func handleSystemWhich(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - let params = try Self.decodeParams(OpenClawSystemWhichParams.self, from: req.paramsJSON) - let bins = params.bins - .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } - .filter { !$0.isEmpty } - guard !bins.isEmpty else { - return Self.errorResponse(req, code: .invalidRequest, message: "INVALID_REQUEST: bins required") - } - - let searchPaths = CommandResolver.preferredPaths() - var matches: [String] = [] - var paths: [String: String] = [:] - for bin in bins { - if let path = CommandResolver.findExecutable(named: bin, searchPaths: searchPaths) { - matches.append(bin) - paths[bin] = path - } - } - - struct WhichPayload: Encodable { - let bins: [String] - let paths: [String: String] - } - let payload = try Self.encodePayload(WhichPayload(bins: matches, paths: paths)) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - } - - private struct ExecApprovalOutcome { - var approvedByAsk: Bool - var persistAllowlist: Bool - var response: BridgeInvokeResponse? - } - - private struct ExecRunContext { - var displayCommand: String - var security: ExecSecurity - var ask: ExecAsk - var agentId: String? - var resolution: ExecCommandResolution? - var allowlistMatch: ExecAllowlistEntry? - var skillAllow: Bool - var sessionKey: String - var runId: String - } - - private func resolveSystemRunApproval( - req: BridgeInvokeRequest, - params: OpenClawSystemRunParams, - context: ExecRunContext) async -> ExecApprovalOutcome - { - let requiresAsk = ExecApprovalHelpers.requiresAsk( - ask: context.ask, - security: context.security, - allowlistMatch: context.allowlistMatch, - skillAllow: context.skillAllow) - - let decisionFromParams = ExecApprovalHelpers.parseDecision(params.approvalDecision) - var approvedByAsk = params.approved == true || decisionFromParams != nil - var persistAllowlist = decisionFromParams == .allowAlways - if decisionFromParams == .deny { - await self.emitExecEvent( - "exec.denied", - payload: ExecEventPayload( - sessionKey: context.sessionKey, - runId: context.runId, - host: "node", - command: context.displayCommand, - reason: "user-denied")) - return ExecApprovalOutcome( - approvedByAsk: approvedByAsk, - persistAllowlist: persistAllowlist, - response: Self.errorResponse( - req, - code: .unavailable, - message: "SYSTEM_RUN_DENIED: user denied")) - } - - if requiresAsk, !approvedByAsk { - let decision = await MainActor.run { - ExecApprovalsPromptPresenter.prompt( - ExecApprovalPromptRequest( - command: context.displayCommand, - cwd: params.cwd, - host: "node", - security: context.security.rawValue, - ask: context.ask.rawValue, - agentId: context.agentId, - resolvedPath: context.resolution?.resolvedPath, - sessionKey: context.sessionKey)) - } - switch decision { - case .deny: - await self.emitExecEvent( - "exec.denied", - payload: ExecEventPayload( - sessionKey: context.sessionKey, - runId: context.runId, - host: "node", - command: context.displayCommand, - reason: "user-denied")) - return ExecApprovalOutcome( - approvedByAsk: approvedByAsk, - persistAllowlist: persistAllowlist, - response: Self.errorResponse( - req, - code: .unavailable, - message: "SYSTEM_RUN_DENIED: user denied")) - case .allowAlways: - approvedByAsk = true - persistAllowlist = true - case .allowOnce: - approvedByAsk = true - } - } - - return ExecApprovalOutcome( - approvedByAsk: approvedByAsk, - persistAllowlist: persistAllowlist, - response: nil) - } - - private func handleSystemExecApprovalsGet(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - _ = ExecApprovalsStore.ensureFile() - let snapshot = ExecApprovalsStore.readSnapshot() - let redacted = ExecApprovalsSnapshot( - path: snapshot.path, - exists: snapshot.exists, - hash: snapshot.hash, - file: ExecApprovalsStore.redactForSnapshot(snapshot.file)) - let payload = try Self.encodePayload(redacted) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - } - - private func handleSystemExecApprovalsSet(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - struct SetParams: Decodable { - var file: ExecApprovalsFile - var baseHash: String? - } - - let params = try Self.decodeParams(SetParams.self, from: req.paramsJSON) - let current = ExecApprovalsStore.ensureFile() - let snapshot = ExecApprovalsStore.readSnapshot() - if snapshot.exists { - if snapshot.hash.isEmpty { - return Self.errorResponse( - req, - code: .invalidRequest, - message: "INVALID_REQUEST: exec approvals base hash unavailable; reload and retry") - } - let baseHash = params.baseHash?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if baseHash.isEmpty { - return Self.errorResponse( - req, - code: .invalidRequest, - message: "INVALID_REQUEST: exec approvals base hash required; reload and retry") - } - if baseHash != snapshot.hash { - return Self.errorResponse( - req, - code: .invalidRequest, - message: "INVALID_REQUEST: exec approvals changed; reload and retry") - } - } - - var normalized = ExecApprovalsStore.normalizeIncoming(params.file) - let socketPath = normalized.socket?.path?.trimmingCharacters(in: .whitespacesAndNewlines) - let token = normalized.socket?.token?.trimmingCharacters(in: .whitespacesAndNewlines) - let resolvedPath = (socketPath?.isEmpty == false) - ? socketPath! - : current.socket?.path?.trimmingCharacters(in: .whitespacesAndNewlines) ?? - ExecApprovalsStore.socketPath() - let resolvedToken = (token?.isEmpty == false) - ? token! - : current.socket?.token?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - normalized.socket = ExecApprovalsSocketConfig(path: resolvedPath, token: resolvedToken) - - ExecApprovalsStore.saveFile(normalized) - let nextSnapshot = ExecApprovalsStore.readSnapshot() - let redacted = ExecApprovalsSnapshot( - path: nextSnapshot.path, - exists: nextSnapshot.exists, - hash: nextSnapshot.hash, - file: ExecApprovalsStore.redactForSnapshot(nextSnapshot.file)) - let payload = try Self.encodePayload(redacted) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - } - - private func emitExecEvent(_ event: String, payload: ExecEventPayload) async { - guard let sender = self.eventSender else { return } - guard let data = try? JSONEncoder().encode(payload), - let json = String(data: data, encoding: .utf8) - else { - return - } - await sender(event, json) - } - - private func handleSystemNotify(_ req: BridgeInvokeRequest) async throws -> BridgeInvokeResponse { - let params = try Self.decodeParams(OpenClawSystemNotifyParams.self, from: req.paramsJSON) - let title = params.title.trimmingCharacters(in: .whitespacesAndNewlines) - let body = params.body.trimmingCharacters(in: .whitespacesAndNewlines) - if title.isEmpty, body.isEmpty { - return Self.errorResponse(req, code: .invalidRequest, message: "INVALID_REQUEST: empty notification") - } - - let priority = params.priority.flatMap { NotificationPriority(rawValue: $0.rawValue) } - let delivery = params.delivery.flatMap { NotificationDelivery(rawValue: $0.rawValue) } ?? .system - let manager = NotificationManager() - - switch delivery { - case .system: - let ok = await manager.send( - title: title, - body: body, - sound: params.sound, - priority: priority) - return ok - ? BridgeInvokeResponse(id: req.id, ok: true) - : Self.errorResponse(req, code: .unavailable, message: "NOT_AUTHORIZED: notifications") - case .overlay: - await NotifyOverlayController.shared.present(title: title, body: body) - return BridgeInvokeResponse(id: req.id, ok: true) - case .auto: - let ok = await manager.send( - title: title, - body: body, - sound: params.sound, - priority: priority) - if ok { - return BridgeInvokeResponse(id: req.id, ok: true) - } - await NotifyOverlayController.shared.present(title: title, body: body) - return BridgeInvokeResponse(id: req.id, ok: true) - } - } -} - -extension MacNodeRuntime { - private func persistAllowlistPatterns( - persistAllowlist: Bool, - security: ExecSecurity, - agentId: String?, - command: [String], - allowlistResolutions: [ExecCommandResolution]) - { - guard persistAllowlist, security == .allowlist else { return } - var seenPatterns = Set() - for candidate in allowlistResolutions { - guard let pattern = ExecApprovalHelpers.allowlistPattern(command: command, resolution: candidate) else { - continue - } - if seenPatterns.insert(pattern).inserted { - ExecApprovalsStore.addAllowlistEntry(agentId: agentId, pattern: pattern) - } - } - } - - private func recordAllowlistMatches( - security: ExecSecurity, - allowlistSatisfied: Bool, - agentId: String?, - allowlistMatches: [ExecAllowlistEntry], - allowlistResolutions: [ExecCommandResolution], - displayCommand: String) - { - guard security == .allowlist, allowlistSatisfied else { return } - var seenPatterns = Set() - for (idx, match) in allowlistMatches.enumerated() { - if !seenPatterns.insert(match.pattern).inserted { - continue - } - let resolvedPath = idx < allowlistResolutions.count ? allowlistResolutions[idx].resolvedPath : nil - ExecApprovalsStore.recordAllowlistUse( - agentId: agentId, - pattern: match.pattern, - command: displayCommand, - resolvedPath: resolvedPath) - } - } - - private func validateScreenRecordingIfNeeded( - req: BridgeInvokeRequest, - needsScreenRecording: Bool?, - sessionKey: String, - runId: String, - displayCommand: String) async -> BridgeInvokeResponse? - { - guard needsScreenRecording == true else { return nil } - let authorized = await PermissionManager - .status([.screenRecording])[.screenRecording] ?? false - if authorized { - return nil - } - await self.emitExecEvent( - "exec.denied", - payload: ExecEventPayload( - sessionKey: sessionKey, - runId: runId, - host: "node", - command: displayCommand, - reason: "permission:screenRecording")) - return Self.errorResponse( - req, - code: .unavailable, - message: "PERMISSION_MISSING: screenRecording") - } - - private func executeSystemRun( - req: BridgeInvokeRequest, - params: OpenClawSystemRunParams, - command: [String], - env: [String: String], - sessionKey: String, - runId: String, - displayCommand: String) async throws -> BridgeInvokeResponse - { - let timeoutSec = params.timeoutMs.flatMap { Double($0) / 1000.0 } - await self.emitExecEvent( - "exec.started", - payload: ExecEventPayload( - sessionKey: sessionKey, - runId: runId, - host: "node", - command: displayCommand)) - let result = await ShellExecutor.runDetailed( - command: command, - cwd: params.cwd, - env: env, - timeout: timeoutSec) - let combined = [result.stdout, result.stderr, result.errorMessage] - .compactMap(\.self) - .filter { !$0.isEmpty } - .joined(separator: "\n") - await self.emitExecEvent( - "exec.finished", - payload: ExecEventPayload( - sessionKey: sessionKey, - runId: runId, - host: "node", - command: displayCommand, - exitCode: result.exitCode, - timedOut: result.timedOut, - success: result.success, - output: ExecEventPayload.truncateOutput(combined))) - - struct RunPayload: Encodable { - var exitCode: Int? - var timedOut: Bool - var success: Bool - var stdout: String - var stderr: String - var error: String? - } - let runPayload = RunPayload( - exitCode: result.exitCode, - timedOut: result.timedOut, - success: result.success, - stdout: result.stdout, - stderr: result.stderr, - error: result.errorMessage) - let payload = try Self.encodePayload(runPayload) - return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: payload) - } - - private static func decodeParams(_ type: T.Type, from json: String?) throws -> T { - guard let json, let data = json.data(using: .utf8) else { - throw NSError(domain: "Gateway", code: 20, userInfo: [ - NSLocalizedDescriptionKey: "INVALID_REQUEST: paramsJSON required", - ]) - } - return try JSONDecoder().decode(type, from: data) - } - - private static func encodePayload(_ obj: some Encodable) throws -> String { - let data = try JSONEncoder().encode(obj) - guard let json = String(bytes: data, encoding: .utf8) else { - throw NSError(domain: "Node", code: 21, userInfo: [ - NSLocalizedDescriptionKey: "Failed to encode payload as UTF-8", - ]) - } - return json - } - - private nonisolated static func canvasEnabled() -> Bool { - UserDefaults.standard.object(forKey: canvasEnabledKey) as? Bool ?? true - } - - private nonisolated static func cameraEnabled() -> Bool { - UserDefaults.standard.object(forKey: cameraEnabledKey) as? Bool ?? false - } - - private nonisolated static func locationMode() -> OpenClawLocationMode { - let raw = UserDefaults.standard.string(forKey: locationModeKey) ?? "off" - return OpenClawLocationMode(rawValue: raw) ?? .off - } - - private nonisolated static func locationPreciseEnabled() -> Bool { - if UserDefaults.standard.object(forKey: locationPreciseKey) == nil { return true } - return UserDefaults.standard.bool(forKey: locationPreciseKey) - } - - private static func errorResponse( - _ req: BridgeInvokeRequest, - code: OpenClawNodeErrorCode, - message: String) -> BridgeInvokeResponse - { - BridgeInvokeResponse( - id: req.id, - ok: false, - error: OpenClawNodeError(code: code, message: message)) - } - - private static func encodeCanvasSnapshot( - image: NSImage, - format: OpenClawCanvasSnapshotFormat, - maxWidth: Int?, - quality: Double) throws -> Data - { - let source = Self.scaleImage(image, maxWidth: maxWidth) ?? image - guard let tiff = source.tiffRepresentation, - let rep = NSBitmapImageRep(data: tiff) - else { - throw NSError(domain: "Canvas", code: 22, userInfo: [ - NSLocalizedDescriptionKey: "snapshot encode failed", - ]) - } - - switch format { - case .png: - guard let data = rep.representation(using: .png, properties: [:]) else { - throw NSError(domain: "Canvas", code: 23, userInfo: [ - NSLocalizedDescriptionKey: "png encode failed", - ]) - } - return data - case .jpeg: - let clamped = min(1.0, max(0.05, quality)) - guard let data = rep.representation( - using: .jpeg, - properties: [.compressionFactor: clamped]) - else { - throw NSError(domain: "Canvas", code: 24, userInfo: [ - NSLocalizedDescriptionKey: "jpeg encode failed", - ]) - } - return data - } - } - - private static func scaleImage(_ image: NSImage, maxWidth: Int?) -> NSImage? { - guard let maxWidth, maxWidth > 0 else { return image } - let size = image.size - guard size.width > 0, size.width > CGFloat(maxWidth) else { return image } - let scale = CGFloat(maxWidth) / size.width - let target = NSSize(width: CGFloat(maxWidth), height: size.height * scale) - - let out = NSImage(size: target) - out.lockFocus() - image.draw( - in: NSRect(origin: .zero, size: target), - from: NSRect(origin: .zero, size: size), - operation: .copy, - fraction: 1.0) - out.unlockFocus() - return out - } -} diff --git a/apps/macos/Sources/OpenClaw/NodeMode/MacNodeRuntimeMainActorServices.swift b/apps/macos/Sources/OpenClaw/NodeMode/MacNodeRuntimeMainActorServices.swift deleted file mode 100644 index 733410b1860..00000000000 --- a/apps/macos/Sources/OpenClaw/NodeMode/MacNodeRuntimeMainActorServices.swift +++ /dev/null @@ -1,60 +0,0 @@ -import CoreLocation -import Foundation -import OpenClawKit - -@MainActor -protocol MacNodeRuntimeMainActorServices: Sendable { - func recordScreen( - screenIndex: Int?, - durationMs: Int?, - fps: Double?, - includeAudio: Bool?, - outPath: String?) async throws -> (path: String, hasAudio: Bool) - - func locationAuthorizationStatus() -> CLAuthorizationStatus - func locationAccuracyAuthorization() -> CLAccuracyAuthorization - func currentLocation( - desiredAccuracy: OpenClawLocationAccuracy, - maxAgeMs: Int?, - timeoutMs: Int?) async throws -> CLLocation -} - -@MainActor -final class LiveMacNodeRuntimeMainActorServices: MacNodeRuntimeMainActorServices, @unchecked Sendable { - private let screenRecorder = ScreenRecordService() - private let locationService = MacNodeLocationService() - - func recordScreen( - screenIndex: Int?, - durationMs: Int?, - fps: Double?, - includeAudio: Bool?, - outPath: String?) async throws -> (path: String, hasAudio: Bool) - { - try await self.screenRecorder.record( - screenIndex: screenIndex, - durationMs: durationMs, - fps: fps, - includeAudio: includeAudio, - outPath: outPath) - } - - func locationAuthorizationStatus() -> CLAuthorizationStatus { - self.locationService.authorizationStatus() - } - - func locationAccuracyAuthorization() -> CLAccuracyAuthorization { - self.locationService.accuracyAuthorization() - } - - func currentLocation( - desiredAccuracy: OpenClawLocationAccuracy, - maxAgeMs: Int?, - timeoutMs: Int?) async throws -> CLLocation - { - try await self.locationService.currentLocation( - desiredAccuracy: desiredAccuracy, - maxAgeMs: maxAgeMs, - timeoutMs: timeoutMs) - } -} diff --git a/apps/macos/Sources/OpenClaw/NodeMode/MacNodeScreenCommands.swift b/apps/macos/Sources/OpenClaw/NodeMode/MacNodeScreenCommands.swift deleted file mode 100644 index 6f849fdf03a..00000000000 --- a/apps/macos/Sources/OpenClaw/NodeMode/MacNodeScreenCommands.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Foundation - -enum MacNodeScreenCommand: String, Codable, Sendable { - case record = "screen.record" -} - -struct MacNodeScreenRecordParams: Codable, Sendable, Equatable { - var screenIndex: Int? - var durationMs: Int? - var fps: Double? - var format: String? - var includeAudio: Bool? -} diff --git a/apps/macos/Sources/OpenClaw/NodePairingApprovalPrompter.swift b/apps/macos/Sources/OpenClaw/NodePairingApprovalPrompter.swift deleted file mode 100644 index 10598d7f4be..00000000000 --- a/apps/macos/Sources/OpenClaw/NodePairingApprovalPrompter.swift +++ /dev/null @@ -1,682 +0,0 @@ -import AppKit -import Foundation -import Observation -import OpenClawDiscovery -import OpenClawIPC -import OpenClawKit -import OpenClawProtocol -import OSLog -import UserNotifications - -enum NodePairingReconcilePolicy { - static let activeIntervalMs: UInt64 = 15000 - static let resyncDelayMs: UInt64 = 250 - - static func shouldPoll(pendingCount: Int, isPresenting: Bool) -> Bool { - pendingCount > 0 || isPresenting - } -} - -@MainActor -@Observable -final class NodePairingApprovalPrompter { - static let shared = NodePairingApprovalPrompter() - - private let logger = Logger(subsystem: "ai.openclaw", category: "node-pairing") - private var task: Task? - private var reconcileTask: Task? - private var reconcileOnceTask: Task? - private var reconcileInFlight = false - private var isStopping = false - private var isPresenting = false - private var queue: [PendingRequest] = [] - var pendingCount: Int = 0 - var pendingRepairCount: Int = 0 - private var activeAlert: NSAlert? - private var activeRequestId: String? - private var alertHostWindow: NSWindow? - private var remoteResolutionsByRequestId: [String: PairingResolution] = [:] - private var autoApproveAttempts: Set = [] - - private struct PairingList: Codable { - let pending: [PendingRequest] - let paired: [PairedNode]? - } - - private struct PairedNode: Codable, Equatable { - let nodeId: String - let approvedAtMs: Double? - let displayName: String? - let platform: String? - let version: String? - let remoteIp: String? - } - - private struct PendingRequest: Codable, Equatable, Identifiable { - let requestId: String - let nodeId: String - let displayName: String? - let platform: String? - let version: String? - let remoteIp: String? - let isRepair: Bool? - let silent: Bool? - let ts: Double - - var id: String { - self.requestId - } - } - - private struct PairingResolvedEvent: Codable { - let requestId: String - let nodeId: String - let decision: String - let ts: Double - } - - private enum PairingResolution: String { - case approved - case rejected - } - - func start() { - guard self.task == nil else { return } - self.isStopping = false - self.reconcileTask?.cancel() - self.reconcileTask = nil - self.task = Task { [weak self] in - guard let self else { return } - _ = try? await GatewayConnection.shared.refresh() - await self.loadPendingRequestsFromGateway() - let stream = await GatewayConnection.shared.subscribe(bufferingNewest: 200) - for await push in stream { - if Task.isCancelled { return } - await MainActor.run { [weak self] in self?.handle(push: push) } - } - } - } - - func stop() { - self.isStopping = true - self.endActiveAlert() - self.task?.cancel() - self.task = nil - self.reconcileTask?.cancel() - self.reconcileTask = nil - self.reconcileOnceTask?.cancel() - self.reconcileOnceTask = nil - self.queue.removeAll(keepingCapacity: false) - self.updatePendingCounts() - self.isPresenting = false - self.activeRequestId = nil - self.alertHostWindow?.orderOut(nil) - self.alertHostWindow?.close() - self.alertHostWindow = nil - self.remoteResolutionsByRequestId.removeAll(keepingCapacity: false) - self.autoApproveAttempts.removeAll(keepingCapacity: false) - } - - private func loadPendingRequestsFromGateway() async { - // The gateway process may start slightly after the app. Retry a bit so - // pending pairing prompts are still shown on launch. - var delayMs: UInt64 = 200 - for attempt in 1...8 { - if Task.isCancelled { return } - do { - let data = try await GatewayConnection.shared.request( - method: "node.pair.list", - params: nil, - timeoutMs: 6000) - guard !data.isEmpty else { return } - let list = try JSONDecoder().decode(PairingList.self, from: data) - let pendingCount = list.pending.count - guard pendingCount > 0 else { return } - self.logger.info( - "loaded \(pendingCount, privacy: .public) pending node pairing request(s) on startup") - await self.apply(list: list) - return - } catch { - if attempt == 8 { - self.logger - .error( - "failed to load pending pairing requests: \(error.localizedDescription, privacy: .public)") - return - } - try? await Task.sleep(nanoseconds: delayMs * 1_000_000) - delayMs = min(delayMs * 2, 2000) - } - } - } - - private func reconcileLoop() async { - // Reconcile requests periodically so multiple running apps stay in sync - // (e.g. close dialogs + notify if another machine approves/rejects via app or CLI). - while !Task.isCancelled { - if self.isStopping { break } - if !self.shouldPoll { - self.reconcileTask = nil - return - } - await self.reconcileOnce(timeoutMs: 2500) - try? await Task.sleep( - nanoseconds: NodePairingReconcilePolicy.activeIntervalMs * 1_000_000) - } - self.reconcileTask = nil - } - - private func fetchPairingList(timeoutMs: Double) async throws -> PairingList { - let data = try await GatewayConnection.shared.request( - method: "node.pair.list", - params: nil, - timeoutMs: timeoutMs) - return try JSONDecoder().decode(PairingList.self, from: data) - } - - private func apply(list: PairingList) async { - if self.isStopping { return } - - let pendingById = Dictionary( - uniqueKeysWithValues: list.pending.map { ($0.requestId, $0) }) - - // Enqueue any missing requests (covers missed pushes while reconnecting). - for req in list.pending.sorted(by: { $0.ts < $1.ts }) { - self.enqueue(req) - } - - // Detect resolved requests (approved/rejected elsewhere). - let queued = self.queue - for req in queued { - if pendingById[req.requestId] != nil { continue } - let resolution = self.inferResolution(for: req, list: list) - - if self.activeRequestId == req.requestId, self.activeAlert != nil { - self.remoteResolutionsByRequestId[req.requestId] = resolution - self.logger.info( - """ - pairing request resolved elsewhere; closing dialog \ - requestId=\(req.requestId, privacy: .public) \ - resolution=\(resolution.rawValue, privacy: .public) - """) - self.endActiveAlert() - continue - } - - self.logger.info( - """ - pairing request resolved elsewhere requestId=\(req.requestId, privacy: .public) \ - resolution=\(resolution.rawValue, privacy: .public) - """) - self.queue.removeAll { $0 == req } - Task { @MainActor in - await self.notify(resolution: resolution, request: req, via: "remote") - } - } - - if self.queue.isEmpty { - self.isPresenting = false - } - self.presentNextIfNeeded() - self.updateReconcileLoop() - } - - private func inferResolution(for request: PendingRequest, list: PairingList) -> PairingResolution { - let paired = list.paired ?? [] - guard let node = paired.first(where: { $0.nodeId == request.nodeId }) else { - return .rejected - } - if request.isRepair == true, let approvedAtMs = node.approvedAtMs { - return approvedAtMs >= request.ts ? .approved : .rejected - } - return .approved - } - - private func endActiveAlert() { - PairingAlertSupport.endActiveAlert(activeAlert: &self.activeAlert, activeRequestId: &self.activeRequestId) - } - - private func requireAlertHostWindow() -> NSWindow { - PairingAlertSupport.requireAlertHostWindow(alertHostWindow: &self.alertHostWindow) - } - - private func handle(push: GatewayPush) { - switch push { - case let .event(evt) where evt.event == "node.pair.requested": - guard let payload = evt.payload else { return } - do { - let req = try GatewayPayloadDecoding.decode(payload, as: PendingRequest.self) - self.enqueue(req) - } catch { - self.logger - .error("failed to decode pairing request: \(error.localizedDescription, privacy: .public)") - } - case let .event(evt) where evt.event == "node.pair.resolved": - guard let payload = evt.payload else { return } - do { - let resolved = try GatewayPayloadDecoding.decode(payload, as: PairingResolvedEvent.self) - self.handleResolved(resolved) - } catch { - self.logger - .error( - "failed to decode pairing resolution: \(error.localizedDescription, privacy: .public)") - } - case .snapshot: - self.scheduleReconcileOnce(delayMs: 0) - case .seqGap: - self.scheduleReconcileOnce() - default: - return - } - } - - private func enqueue(_ req: PendingRequest) { - if self.queue.contains(req) { return } - self.queue.append(req) - self.updatePendingCounts() - self.presentNextIfNeeded() - self.updateReconcileLoop() - } - - private func presentNextIfNeeded() { - guard !self.isStopping else { return } - guard !self.isPresenting else { return } - guard let next = self.queue.first else { return } - self.isPresenting = true - Task { @MainActor [weak self] in - guard let self else { return } - if await self.trySilentApproveIfPossible(next) { - return - } - self.presentAlert(for: next) - } - } - - private func presentAlert(for req: PendingRequest) { - self.logger.info("presenting node pairing alert requestId=\(req.requestId, privacy: .public)") - NSApp.activate(ignoringOtherApps: true) - - let alert = NSAlert() - alert.alertStyle = .warning - alert.messageText = "Allow node to connect?" - alert.informativeText = Self.describe(req) - // Fail-safe ordering: if the dialog can't be presented, default to "Later". - alert.addButton(withTitle: "Later") - alert.addButton(withTitle: "Approve") - alert.addButton(withTitle: "Reject") - if #available(macOS 11.0, *), alert.buttons.indices.contains(2) { - alert.buttons[2].hasDestructiveAction = true - } - - self.activeAlert = alert - self.activeRequestId = req.requestId - let hostWindow = self.requireAlertHostWindow() - - // Position the hidden host window so the sheet appears centered on screen. - // (Sheets attach to the top edge of their parent window; if the parent is tiny, it looks "anchored".) - let sheetSize = alert.window.frame.size - if let screen = hostWindow.screen ?? NSScreen.main { - let bounds = screen.visibleFrame - let x = bounds.midX - (sheetSize.width / 2) - let sheetOriginY = bounds.midY - (sheetSize.height / 2) - let hostY = sheetOriginY + sheetSize.height - hostWindow.frame.height - hostWindow.setFrameOrigin(NSPoint(x: x, y: hostY)) - } else { - hostWindow.center() - } - - hostWindow.makeKeyAndOrderFront(nil) - alert.beginSheetModal(for: hostWindow) { [weak self] response in - Task { @MainActor [weak self] in - guard let self else { return } - self.activeRequestId = nil - self.activeAlert = nil - await self.handleAlertResponse(response, request: req) - hostWindow.orderOut(nil) - } - } - } - - private func handleAlertResponse(_ response: NSApplication.ModalResponse, request: PendingRequest) async { - defer { - if self.queue.first == request { - self.queue.removeFirst() - } else { - self.queue.removeAll { $0 == request } - } - self.updatePendingCounts() - self.isPresenting = false - self.presentNextIfNeeded() - self.updateReconcileLoop() - } - - // Never approve/reject while shutting down (alerts can get dismissed during app termination). - guard !self.isStopping else { return } - - if let resolved = self.remoteResolutionsByRequestId.removeValue(forKey: request.requestId) { - await self.notify(resolution: resolved, request: request, via: "remote") - return - } - - switch response { - case .alertFirstButtonReturn: - // Later: leave as pending (CLI can approve/reject). Request will expire on the gateway TTL. - return - case .alertSecondButtonReturn: - _ = await self.approve(requestId: request.requestId) - await self.notify(resolution: .approved, request: request, via: "local") - case .alertThirdButtonReturn: - await self.reject(requestId: request.requestId) - await self.notify(resolution: .rejected, request: request, via: "local") - default: - return - } - } - - private func approve(requestId: String) async -> Bool { - do { - try await GatewayConnection.shared.nodePairApprove(requestId: requestId) - self.logger.info("approved node pairing requestId=\(requestId, privacy: .public)") - return true - } catch { - self.logger.error("approve failed requestId=\(requestId, privacy: .public)") - self.logger.error("approve failed: \(error.localizedDescription, privacy: .public)") - return false - } - } - - private func reject(requestId: String) async { - do { - try await GatewayConnection.shared.nodePairReject(requestId: requestId) - self.logger.info("rejected node pairing requestId=\(requestId, privacy: .public)") - } catch { - self.logger.error("reject failed requestId=\(requestId, privacy: .public)") - self.logger.error("reject failed: \(error.localizedDescription, privacy: .public)") - } - } - - private static func describe(_ req: PendingRequest) -> String { - let name = req.displayName?.trimmingCharacters(in: .whitespacesAndNewlines) - let platform = self.prettyPlatform(req.platform) - let version = req.version?.trimmingCharacters(in: .whitespacesAndNewlines) - let ip = self.prettyIP(req.remoteIp) - - var lines: [String] = [] - lines.append("Name: \(name?.isEmpty == false ? name! : "Unknown")") - lines.append("Node ID: \(req.nodeId)") - if let platform, !platform.isEmpty { lines.append("Platform: \(platform)") } - if let version, !version.isEmpty { lines.append("App: \(version)") } - if let ip, !ip.isEmpty { lines.append("IP: \(ip)") } - if req.isRepair == true { lines.append("Note: Repair request (token will rotate).") } - return lines.joined(separator: "\n") - } - - private static func prettyIP(_ ip: String?) -> String? { - let trimmed = ip?.trimmingCharacters(in: .whitespacesAndNewlines) - guard let trimmed, !trimmed.isEmpty else { return nil } - return trimmed.replacingOccurrences(of: "::ffff:", with: "") - } - - private static func prettyPlatform(_ platform: String?) -> String? { - let raw = platform?.trimmingCharacters(in: .whitespacesAndNewlines) - guard let raw, !raw.isEmpty else { return nil } - if raw.lowercased() == "ios" { return "iOS" } - if raw.lowercased() == "macos" { return "macOS" } - return raw - } - - private func notify(resolution: PairingResolution, request: PendingRequest, via: String) async { - let center = UNUserNotificationCenter.current() - let settings = await center.notificationSettings() - guard settings.authorizationStatus == .authorized || - settings.authorizationStatus == .provisional - else { - return - } - - let title = resolution == .approved ? "Node pairing approved" : "Node pairing rejected" - let name = request.displayName?.trimmingCharacters(in: .whitespacesAndNewlines) - let device = name?.isEmpty == false ? name! : request.nodeId - let body = "\(device)\n(via \(via))" - - _ = await NotificationManager().send( - title: title, - body: body, - sound: nil, - priority: .active) - } - - private struct SSHTarget { - let host: String - let port: Int - } - - private func trySilentApproveIfPossible(_ req: PendingRequest) async -> Bool { - guard req.silent == true else { return false } - if self.autoApproveAttempts.contains(req.requestId) { return false } - self.autoApproveAttempts.insert(req.requestId) - - guard let target = await self.resolveSSHTarget() else { - self.logger.info("silent pairing skipped (no ssh target) requestId=\(req.requestId, privacy: .public)") - return false - } - - let user = NSUserName().trimmingCharacters(in: .whitespacesAndNewlines) - guard !user.isEmpty else { - self.logger.info("silent pairing skipped (missing local user) requestId=\(req.requestId, privacy: .public)") - return false - } - - let ok = await Self.probeSSH(user: user, host: target.host, port: target.port) - if !ok { - self.logger.info("silent pairing probe failed requestId=\(req.requestId, privacy: .public)") - return false - } - - guard await self.approve(requestId: req.requestId) else { - self.logger.info("silent pairing approve failed requestId=\(req.requestId, privacy: .public)") - return false - } - - await self.notify(resolution: .approved, request: req, via: "silent-ssh") - if self.queue.first == req { - self.queue.removeFirst() - } else { - self.queue.removeAll { $0 == req } - } - - self.updatePendingCounts() - self.isPresenting = false - self.presentNextIfNeeded() - self.updateReconcileLoop() - return true - } - - private func resolveSSHTarget() async -> SSHTarget? { - let settings = CommandResolver.connectionSettings() - if !settings.target.isEmpty, let parsed = CommandResolver.parseSSHTarget(settings.target) { - let user = NSUserName().trimmingCharacters(in: .whitespacesAndNewlines) - if let targetUser = parsed.user, - !targetUser.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty, - targetUser != user - { - self.logger.info("silent pairing skipped (ssh user mismatch)") - return nil - } - let host = parsed.host.trimmingCharacters(in: .whitespacesAndNewlines) - guard !host.isEmpty else { return nil } - let port = parsed.port > 0 ? parsed.port : 22 - return SSHTarget(host: host, port: port) - } - - let model = GatewayDiscoveryModel(localDisplayName: InstanceIdentity.displayName) - model.start() - defer { model.stop() } - - let deadline = Date().addingTimeInterval(5.0) - while model.gateways.isEmpty, Date() < deadline { - try? await Task.sleep(nanoseconds: 200_000_000) - } - - let preferred = GatewayDiscoveryPreferences.preferredStableID() - let gateway = model.gateways.first { $0.stableID == preferred } ?? model.gateways.first - guard let gateway else { return nil } - guard let target = GatewayDiscoveryHelpers.sshTarget(for: gateway), - let parsed = CommandResolver.parseSSHTarget(target) - else { - return nil - } - return SSHTarget(host: parsed.host, port: parsed.port) - } - - private static func probeSSH(user: String, host: String, port: Int) async -> Bool { - await Task.detached(priority: .utility) { - let process = Process() - process.executableURL = URL(fileURLWithPath: "/usr/bin/ssh") - - let options = [ - "-o", "BatchMode=yes", - "-o", "ConnectTimeout=5", - "-o", "NumberOfPasswordPrompts=0", - "-o", "PreferredAuthentications=publickey", - "-o", "StrictHostKeyChecking=accept-new", - ] - guard let target = CommandResolver.makeSSHTarget(user: user, host: host, port: port) else { - return false - } - let args = CommandResolver.sshArguments( - target: target, - identity: "", - options: options, - remoteCommand: ["/usr/bin/true"]) - process.arguments = args - let pipe = Pipe() - process.standardOutput = pipe - process.standardError = pipe - - do { - _ = try process.runAndReadToEnd(from: pipe) - } catch { - return false - } - return process.terminationStatus == 0 - }.value - } - - private var shouldPoll: Bool { - NodePairingReconcilePolicy.shouldPoll( - pendingCount: self.queue.count, - isPresenting: self.isPresenting) - } - - private func updateReconcileLoop() { - guard !self.isStopping else { return } - if self.shouldPoll { - if self.reconcileTask == nil { - self.reconcileTask = Task { [weak self] in - await self?.reconcileLoop() - } - } - } else { - self.reconcileTask?.cancel() - self.reconcileTask = nil - } - } - - private func updatePendingCounts() { - // Keep a cheap observable summary for the menu bar status line. - self.pendingCount = self.queue.count - self.pendingRepairCount = self.queue.count(where: { $0.isRepair == true }) - } - - private func reconcileOnce(timeoutMs: Double) async { - if self.isStopping { return } - if self.reconcileInFlight { return } - self.reconcileInFlight = true - defer { self.reconcileInFlight = false } - do { - let list = try await self.fetchPairingList(timeoutMs: timeoutMs) - await self.apply(list: list) - } catch { - // best effort: ignore transient connectivity failures - } - } - - private func scheduleReconcileOnce(delayMs: UInt64 = NodePairingReconcilePolicy.resyncDelayMs) { - self.reconcileOnceTask?.cancel() - self.reconcileOnceTask = Task { [weak self] in - guard let self else { return } - if delayMs > 0 { - try? await Task.sleep(nanoseconds: delayMs * 1_000_000) - } - await self.reconcileOnce(timeoutMs: 2500) - } - } - - private func handleResolved(_ resolved: PairingResolvedEvent) { - let resolution: PairingResolution = - resolved.decision == PairingResolution.approved.rawValue ? .approved : .rejected - - if self.activeRequestId == resolved.requestId, self.activeAlert != nil { - self.remoteResolutionsByRequestId[resolved.requestId] = resolution - self.logger.info( - """ - pairing request resolved elsewhere; closing dialog \ - requestId=\(resolved.requestId, privacy: .public) \ - resolution=\(resolution.rawValue, privacy: .public) - """) - self.endActiveAlert() - return - } - - guard let request = self.queue.first(where: { $0.requestId == resolved.requestId }) else { - return - } - self.queue.removeAll { $0.requestId == resolved.requestId } - self.updatePendingCounts() - Task { @MainActor in - await self.notify(resolution: resolution, request: request, via: "remote") - } - if self.queue.isEmpty { - self.isPresenting = false - } - self.presentNextIfNeeded() - self.updateReconcileLoop() - } -} - -#if DEBUG -@MainActor -extension NodePairingApprovalPrompter { - static func exerciseForTesting() async { - let prompter = NodePairingApprovalPrompter() - let pending = PendingRequest( - requestId: "req-1", - nodeId: "node-1", - displayName: "Node One", - platform: "macos", - version: "1.0.0", - remoteIp: "127.0.0.1", - isRepair: false, - silent: true, - ts: 1_700_000_000_000) - let paired = PairedNode( - nodeId: "node-1", - approvedAtMs: 1_700_000_000_000, - displayName: "Node One", - platform: "macOS", - version: "1.0.0", - remoteIp: "127.0.0.1") - let list = PairingList(pending: [pending], paired: [paired]) - - _ = Self.describe(pending) - _ = Self.prettyIP(pending.remoteIp) - _ = Self.prettyPlatform(pending.platform) - _ = prompter.inferResolution(for: pending, list: list) - - prompter.queue = [pending] - _ = prompter.shouldPoll - _ = await prompter.trySilentApproveIfPossible(pending) - prompter.queue.removeAll() - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/NodeServiceManager.swift b/apps/macos/Sources/OpenClaw/NodeServiceManager.swift deleted file mode 100644 index 38d0aa30241..00000000000 --- a/apps/macos/Sources/OpenClaw/NodeServiceManager.swift +++ /dev/null @@ -1,150 +0,0 @@ -import Foundation -import OSLog - -enum NodeServiceManager { - private static let logger = Logger(subsystem: "ai.openclaw", category: "node.service") - - static func start() async -> String? { - let result = await self.runServiceCommandResult( - ["node", "start"], - timeout: 20, - quiet: false) - if let error = self.errorMessage(from: result, treatNotLoadedAsError: true) { - self.logger.error("node service start failed: \(error, privacy: .public)") - return error - } - return nil - } - - static func stop() async -> String? { - let result = await self.runServiceCommandResult( - ["node", "stop"], - timeout: 15, - quiet: false) - if let error = self.errorMessage(from: result, treatNotLoadedAsError: false) { - self.logger.error("node service stop failed: \(error, privacy: .public)") - return error - } - return nil - } -} - -extension NodeServiceManager { - private struct CommandResult { - let success: Bool - let payload: Data? - let message: String? - let parsed: ParsedServiceJson? - } - - private struct ParsedServiceJson { - let text: String - let object: [String: Any] - let ok: Bool? - let result: String? - let message: String? - let error: String? - let hints: [String] - } - - private static func runServiceCommandResult( - _ args: [String], - timeout: Double, - quiet: Bool) async -> CommandResult - { - let command = CommandResolver.openclawCommand( - subcommand: "service", - extraArgs: self.withJsonFlag(args), - // Service management must always run locally, even if remote mode is configured. - configRoot: ["gateway": ["mode": "local"]]) - var env = ProcessInfo.processInfo.environment - env["PATH"] = CommandResolver.preferredPaths().joined(separator: ":") - let response = await ShellExecutor.runDetailed(command: command, cwd: nil, env: env, timeout: timeout) - let parsed = self.parseServiceJson(from: response.stdout) ?? self.parseServiceJson(from: response.stderr) - let ok = parsed?.ok - let message = parsed?.error ?? parsed?.message - let payload = parsed?.text.data(using: .utf8) - ?? (response.stdout.isEmpty ? response.stderr : response.stdout).data(using: .utf8) - let success = ok ?? response.success - if success { - return CommandResult(success: true, payload: payload, message: nil, parsed: parsed) - } - - if quiet { - return CommandResult(success: false, payload: payload, message: message, parsed: parsed) - } - - let detail = message ?? self.summarize(response.stderr) ?? self.summarize(response.stdout) - let exit = response.exitCode.map { "exit \($0)" } ?? (response.errorMessage ?? "failed") - let fullMessage = detail.map { "Node service command failed (\(exit)): \($0)" } - ?? "Node service command failed (\(exit))" - self.logger.error("\(fullMessage, privacy: .public)") - return CommandResult(success: false, payload: payload, message: detail, parsed: parsed) - } - - private static func errorMessage(from result: CommandResult, treatNotLoadedAsError: Bool) -> String? { - if !result.success { - return result.message ?? "Node service command failed" - } - guard let parsed = result.parsed else { return nil } - if parsed.ok == false { - return self.mergeHints(message: parsed.error ?? parsed.message, hints: parsed.hints) - } - if treatNotLoadedAsError, parsed.result == "not-loaded" { - let base = parsed.message ?? "Node service not loaded." - return self.mergeHints(message: base, hints: parsed.hints) - } - return nil - } - - private static func withJsonFlag(_ args: [String]) -> [String] { - if args.contains("--json") { return args } - return args + ["--json"] - } - - private static func parseServiceJson(from raw: String) -> ParsedServiceJson? { - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - guard let start = trimmed.firstIndex(of: "{"), - let end = trimmed.lastIndex(of: "}") - else { - return nil - } - let jsonText = String(trimmed[start...end]) - guard let data = jsonText.data(using: .utf8) else { return nil } - guard let object = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { return nil } - let ok = object["ok"] as? Bool - let result = object["result"] as? String - let message = object["message"] as? String - let error = object["error"] as? String - let hints = (object["hints"] as? [String]) ?? [] - return ParsedServiceJson( - text: jsonText, - object: object, - ok: ok, - result: result, - message: message, - error: error, - hints: hints) - } - - private static func mergeHints(message: String?, hints: [String]) -> String? { - let trimmed = message?.trimmingCharacters(in: .whitespacesAndNewlines) - let nonEmpty = trimmed?.isEmpty == false ? trimmed : nil - guard !hints.isEmpty else { return nonEmpty } - let hintText = hints.prefix(2).joined(separator: " · ") - if let nonEmpty { - return "\(nonEmpty) (\(hintText))" - } - return hintText - } - - private static func summarize(_ text: String) -> String? { - let lines = text - .split(whereSeparator: \.isNewline) - .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } - .filter { !$0.isEmpty } - guard let last = lines.last else { return nil } - let normalized = last.replacingOccurrences(of: "\\s+", with: " ", options: .regularExpression) - return normalized.count > 200 ? String(normalized.prefix(199)) + "…" : normalized - } -} diff --git a/apps/macos/Sources/OpenClaw/NodesMenu.swift b/apps/macos/Sources/OpenClaw/NodesMenu.swift deleted file mode 100644 index f88177d8dd0..00000000000 --- a/apps/macos/Sources/OpenClaw/NodesMenu.swift +++ /dev/null @@ -1,333 +0,0 @@ -import AppKit -import SwiftUI - -struct NodeMenuEntryFormatter { - static func isGateway(_ entry: NodeInfo) -> Bool { - entry.nodeId == "gateway" - } - - static func isConnected(_ entry: NodeInfo) -> Bool { - entry.isConnected - } - - static func primaryName(_ entry: NodeInfo) -> String { - if self.isGateway(entry) { - return entry.displayName?.nonEmpty ?? "Gateway" - } - return entry.displayName?.nonEmpty ?? entry.nodeId - } - - static func summaryText(_ entry: NodeInfo) -> String { - if self.isGateway(entry) { - let role = self.roleText(entry) - let name = self.primaryName(entry) - var parts = ["\(name) · \(role)"] - if let ip = entry.remoteIp?.nonEmpty { parts.append("host \(ip)") } - if let platform = self.platformText(entry) { parts.append(platform) } - return parts.joined(separator: " · ") - } - let name = self.primaryName(entry) - var prefix = "Node: \(name)" - if let ip = entry.remoteIp?.nonEmpty { - prefix += " (\(ip))" - } - var parts = [prefix] - if let platform = self.platformText(entry) { - parts.append("platform \(platform)") - } - let versionLabels = self.versionLabels(entry) - if !versionLabels.isEmpty { - parts.append(versionLabels.joined(separator: " · ")) - } - parts.append("status \(self.roleText(entry))") - return parts.joined(separator: " · ") - } - - static func roleText(_ entry: NodeInfo) -> String { - if entry.isConnected { return "connected" } - if self.isGateway(entry) { return "disconnected" } - if entry.isPaired { return "paired" } - return "unpaired" - } - - static func detailLeft(_ entry: NodeInfo) -> String { - let role = self.roleText(entry) - if let ip = entry.remoteIp?.nonEmpty { return "\(ip) · \(role)" } - return role - } - - static func headlineRight(_ entry: NodeInfo) -> String? { - self.platformText(entry) - } - - static func detailRightVersion(_ entry: NodeInfo) -> String? { - let labels = self.versionLabels(entry, compact: false) - if labels.isEmpty { return nil } - return labels.joined(separator: " · ") - } - - static func platformText(_ entry: NodeInfo) -> String? { - if let raw = entry.platform?.nonEmpty { - return self.prettyPlatform(raw) ?? raw - } - if let family = entry.deviceFamily?.lowercased() { - if family.contains("mac") { return "macOS" } - if family.contains("iphone") { return "iOS" } - if family.contains("ipad") { return "iPadOS" } - if family.contains("android") { return "Android" } - } - return nil - } - - private static func prettyPlatform(_ raw: String) -> String? { - let (prefix, version) = self.parsePlatform(raw) - if prefix.isEmpty { return nil } - let name: String = switch prefix { - case "macos": "macOS" - case "ios": "iOS" - case "ipados": "iPadOS" - case "tvos": "tvOS" - case "watchos": "watchOS" - default: prefix.prefix(1).uppercased() + prefix.dropFirst() - } - guard let version, !version.isEmpty else { return name } - let parts = version.split(separator: ".").map(String.init) - if parts.count >= 2 { - return "\(name) \(parts[0]).\(parts[1])" - } - return "\(name) \(version)" - } - - private static func parsePlatform(_ raw: String) -> (prefix: String, version: String?) { - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty { return ("", nil) } - let parts = trimmed.split(whereSeparator: { $0 == " " || $0 == "\t" }).map(String.init) - let prefix = parts.first?.lowercased() ?? "" - let versionToken = parts.dropFirst().first - return (prefix, versionToken) - } - - private static func compactVersion(_ raw: String) -> String { - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return trimmed } - if let range = trimmed.range( - of: #"\s*\([^)]*\d[^)]*\)$"#, - options: .regularExpression) - { - return String(trimmed[.. String { - let compact = self.compactVersion(raw) - if compact.isEmpty { return compact } - if compact.lowercased().hasPrefix("v") { return compact } - if let first = compact.unicodeScalars.first, CharacterSet.decimalDigits.contains(first) { - return "v\(compact)" - } - return compact - } - - private static func versionLabels(_ entry: NodeInfo, compact: Bool = true) -> [String] { - let (core, ui) = self.resolveVersions(entry) - var labels: [String] = [] - if let core { - let label = compact ? self.compactVersion(core) : self.shortVersionLabel(core) - labels.append("core \(label)") - } - if let ui { - let label = compact ? self.compactVersion(ui) : self.shortVersionLabel(ui) - labels.append("ui \(label)") - } - return labels - } - - private static func resolveVersions(_ entry: NodeInfo) -> (core: String?, ui: String?) { - let core = entry.coreVersion?.nonEmpty - let ui = entry.uiVersion?.nonEmpty - if core != nil || ui != nil { - return (core, ui) - } - guard let legacy = entry.version?.nonEmpty else { return (nil, nil) } - if self.isHeadlessPlatform(entry) { - return (legacy, nil) - } - return (nil, legacy) - } - - private static func isHeadlessPlatform(_ entry: NodeInfo) -> Bool { - let raw = entry.platform?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() ?? "" - if raw == "darwin" || raw == "linux" || raw == "win32" || raw == "windows" { return true } - return false - } - - static func leadingSymbol(_ entry: NodeInfo) -> String { - if self.isGateway(entry) { - return self.safeSystemSymbol( - "antenna.radiowaves.left.and.right", - fallback: "dot.radiowaves.left.and.right") - } - if let family = entry.deviceFamily?.lowercased() { - if family.contains("mac") { - return self.safeSystemSymbol("laptopcomputer", fallback: "laptopcomputer") - } - if family.contains("iphone") { return self.safeSystemSymbol("iphone", fallback: "iphone") } - if family.contains("ipad") { return self.safeSystemSymbol("ipad", fallback: "ipad") } - } - if let platform = entry.platform?.lowercased() { - if platform.contains("mac") { return self.safeSystemSymbol("laptopcomputer", fallback: "laptopcomputer") } - if platform.contains("ios") { return self.safeSystemSymbol("iphone", fallback: "iphone") } - if platform.contains("android") { return self.safeSystemSymbol("cpu", fallback: "cpu") } - } - return "cpu" - } - - static func isAndroid(_ entry: NodeInfo) -> Bool { - let family = entry.deviceFamily?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - if family == "android" { return true } - let platform = entry.platform?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - return platform?.contains("android") == true - } - - private static func safeSystemSymbol(_ preferred: String, fallback: String) -> String { - if NSImage(systemSymbolName: preferred, accessibilityDescription: nil) != nil { return preferred } - return fallback - } -} - -struct NodeMenuRowView: View { - let entry: NodeInfo - let width: CGFloat - @Environment(\.menuItemHighlighted) private var isHighlighted - - private var primaryColor: Color { - self.isHighlighted ? Color(nsColor: .selectedMenuItemTextColor) : .primary - } - - private var secondaryColor: Color { - self.isHighlighted ? Color(nsColor: .selectedMenuItemTextColor).opacity(0.85) : .secondary - } - - var body: some View { - HStack(alignment: .center, spacing: 10) { - self.leadingIcon - .frame(width: 22, height: 22, alignment: .center) - - VStack(alignment: .leading, spacing: 2) { - HStack(alignment: .firstTextBaseline, spacing: 8) { - Text(NodeMenuEntryFormatter.primaryName(self.entry)) - .font(.callout.weight(NodeMenuEntryFormatter.isConnected(self.entry) ? .semibold : .regular)) - .foregroundStyle(self.primaryColor) - .lineLimit(1) - .truncationMode(.middle) - .layoutPriority(1) - - Spacer(minLength: 8) - - HStack(alignment: .firstTextBaseline, spacing: 6) { - if let right = NodeMenuEntryFormatter.headlineRight(self.entry) { - Text(right) - .font(.caption.monospacedDigit()) - .foregroundStyle(self.secondaryColor) - .lineLimit(1) - .truncationMode(.middle) - .layoutPriority(2) - } - - Image(systemName: "chevron.right") - .font(.caption.weight(.semibold)) - .foregroundStyle(self.secondaryColor) - .padding(.leading, 2) - } - } - - HStack(alignment: .firstTextBaseline, spacing: 8) { - Text(NodeMenuEntryFormatter.detailLeft(self.entry)) - .font(.caption) - .foregroundStyle(self.secondaryColor) - .lineLimit(1) - .truncationMode(.middle) - - Spacer(minLength: 0) - - if let version = NodeMenuEntryFormatter.detailRightVersion(self.entry) { - Text(version) - .font(.caption.monospacedDigit()) - .foregroundStyle(self.secondaryColor) - .lineLimit(1) - .truncationMode(.middle) - } - } - .frame(maxWidth: .infinity, alignment: .leading) - } - .frame(maxWidth: .infinity, alignment: .leading) - } - .padding(.vertical, 8) - .padding(.leading, 18) - .padding(.trailing, 12) - .frame(width: max(1, self.width), alignment: .leading) - } - - @ViewBuilder - private var leadingIcon: some View { - if NodeMenuEntryFormatter.isAndroid(self.entry) { - AndroidMark() - .foregroundStyle(self.secondaryColor) - } else { - Image(systemName: NodeMenuEntryFormatter.leadingSymbol(self.entry)) - .font(.system(size: 18, weight: .regular)) - .foregroundStyle(self.secondaryColor) - } - } -} - -struct AndroidMark: View { - var body: some View { - GeometryReader { geo in - let w = geo.size.width - let h = geo.size.height - let headHeight = h * 0.68 - let headWidth = w * 0.92 - let headX = (w - headWidth) * 0.5 - let headY = (h - headHeight) * 0.5 - let corner = min(w, h) * 0.18 - RoundedRectangle(cornerRadius: corner, style: .continuous) - .frame(width: headWidth, height: headHeight) - .position(x: headX + headWidth * 0.5, y: headY + headHeight * 0.5) - } - } -} - -struct NodeMenuMultilineView: View { - let label: String - let value: String - let width: CGFloat - @Environment(\.menuItemHighlighted) private var isHighlighted - - private var primaryColor: Color { - self.isHighlighted ? Color(nsColor: .selectedMenuItemTextColor) : .primary - } - - private var secondaryColor: Color { - self.isHighlighted ? Color(nsColor: .selectedMenuItemTextColor).opacity(0.85) : .secondary - } - - var body: some View { - VStack(alignment: .leading, spacing: 4) { - Text("\(self.label):") - .font(.caption.weight(.semibold)) - .foregroundStyle(self.secondaryColor) - - Text(self.value) - .font(.caption) - .foregroundStyle(self.primaryColor) - .multilineTextAlignment(.leading) - .fixedSize(horizontal: false, vertical: true) - } - .padding(.vertical, 6) - .padding(.leading, 18) - .padding(.trailing, 12) - .frame(width: max(1, self.width), alignment: .leading) - } -} diff --git a/apps/macos/Sources/OpenClaw/NodesStore.swift b/apps/macos/Sources/OpenClaw/NodesStore.swift deleted file mode 100644 index 5cc94858645..00000000000 --- a/apps/macos/Sources/OpenClaw/NodesStore.swift +++ /dev/null @@ -1,110 +0,0 @@ -import Foundation -import Observation -import OSLog - -struct NodeInfo: Identifiable, Codable { - let nodeId: String - let displayName: String? - let platform: String? - let version: String? - let coreVersion: String? - let uiVersion: String? - let deviceFamily: String? - let modelIdentifier: String? - let remoteIp: String? - let caps: [String]? - let commands: [String]? - let permissions: [String: Bool]? - let paired: Bool? - let connected: Bool? - - var id: String { - self.nodeId - } - - var isConnected: Bool { - self.connected ?? false - } - - var isPaired: Bool { - self.paired ?? false - } -} - -private struct NodeListResponse: Codable { - let ts: Double? - let nodes: [NodeInfo] -} - -@MainActor -@Observable -final class NodesStore { - static let shared = NodesStore() - - var nodes: [NodeInfo] = [] - var lastError: String? - var statusMessage: String? - var isLoading = false - - private let logger = Logger(subsystem: "ai.openclaw", category: "nodes") - private var task: Task? - private let interval: TimeInterval = 30 - private var startCount = 0 - - func start() { - self.startCount += 1 - guard self.startCount == 1 else { return } - guard self.task == nil else { return } - self.task = Task.detached { [weak self] in - guard let self else { return } - await self.refresh() - while !Task.isCancelled { - try? await Task.sleep(nanoseconds: UInt64(self.interval * 1_000_000_000)) - await self.refresh() - } - } - } - - func stop() { - guard self.startCount > 0 else { return } - self.startCount -= 1 - guard self.startCount == 0 else { return } - self.task?.cancel() - self.task = nil - } - - func refresh() async { - if self.isLoading { return } - self.statusMessage = nil - self.isLoading = true - defer { self.isLoading = false } - do { - let data = try await GatewayConnection.shared.requestRaw(method: "node.list", params: nil, timeoutMs: 8000) - let decoded = try JSONDecoder().decode(NodeListResponse.self, from: data) - self.nodes = decoded.nodes - self.lastError = nil - self.statusMessage = nil - } catch { - if Self.isCancelled(error) { - self.logger.debug("node.list cancelled; keeping last nodes") - if self.nodes.isEmpty { - self.statusMessage = "Refreshing devices…" - } - self.lastError = nil - return - } - self.logger.error("node.list failed \(error.localizedDescription, privacy: .public)") - self.nodes = [] - self.lastError = error.localizedDescription - self.statusMessage = nil - } - } - - private static func isCancelled(_ error: Error) -> Bool { - if error is CancellationError { return true } - if let urlError = error as? URLError, urlError.code == .cancelled { return true } - let nsError = error as NSError - if nsError.domain == NSURLErrorDomain, nsError.code == NSURLErrorCancelled { return true } - return false - } -} diff --git a/apps/macos/Sources/OpenClaw/NotificationManager.swift b/apps/macos/Sources/OpenClaw/NotificationManager.swift deleted file mode 100644 index b8e6fcddc8c..00000000000 --- a/apps/macos/Sources/OpenClaw/NotificationManager.swift +++ /dev/null @@ -1,66 +0,0 @@ -import Foundation -import OpenClawIPC -import Security -import UserNotifications - -@MainActor -struct NotificationManager { - private let logger = Logger(subsystem: "ai.openclaw", category: "notifications") - - private static let hasTimeSensitiveEntitlement: Bool = { - guard let task = SecTaskCreateFromSelf(nil) else { return false } - let key = "com.apple.developer.usernotifications.time-sensitive" as CFString - guard let val = SecTaskCopyValueForEntitlement(task, key, nil) else { return false } - return (val as? Bool) == true - }() - - func send(title: String, body: String, sound: String?, priority: NotificationPriority? = nil) async -> Bool { - let center = UNUserNotificationCenter.current() - let status = await center.notificationSettings() - if status.authorizationStatus == .notDetermined { - let granted = try? await center.requestAuthorization(options: [.alert, .sound, .badge]) - if granted != true { - self.logger.warning("notification permission denied (request)") - return false - } - } else if status.authorizationStatus != .authorized { - self.logger.warning("notification permission denied status=\(status.authorizationStatus.rawValue)") - return false - } - - let content = UNMutableNotificationContent() - content.title = title - content.body = body - if let soundName = sound, !soundName.isEmpty { - content.sound = UNNotificationSound(named: UNNotificationSoundName(soundName)) - } - - // Set interruption level based on priority - if let priority { - switch priority { - case .passive: - content.interruptionLevel = .passive - case .active: - content.interruptionLevel = .active - case .timeSensitive: - if Self.hasTimeSensitiveEntitlement { - content.interruptionLevel = .timeSensitive - } else { - self.logger.debug( - "time-sensitive notification requested without entitlement; falling back to active") - content.interruptionLevel = .active - } - } - } - - let req = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil) - do { - try await center.add(req) - self.logger.debug("notification queued") - return true - } catch { - self.logger.error("notification send failed: \(error.localizedDescription)") - return false - } - } -} diff --git a/apps/macos/Sources/OpenClaw/NotifyOverlay.swift b/apps/macos/Sources/OpenClaw/NotifyOverlay.swift deleted file mode 100644 index 31157b0d831..00000000000 --- a/apps/macos/Sources/OpenClaw/NotifyOverlay.swift +++ /dev/null @@ -1,192 +0,0 @@ -import AppKit -import Observation -import QuartzCore -import SwiftUI - -/// Lightweight, borderless panel for in-app "toast" notifications (bypasses macOS Notification Center). -@MainActor -@Observable -final class NotifyOverlayController { - static let shared = NotifyOverlayController() - - private(set) var model = Model() - var isVisible: Bool { - self.model.isVisible - } - - struct Model { - var title: String = "" - var body: String = "" - var isVisible: Bool = false - } - - private var window: NSPanel? - private var hostingView: NSHostingView? - private var dismissTask: Task? - - private let width: CGFloat = 360 - private let padding: CGFloat = 12 - private let maxHeight: CGFloat = 220 - private let minHeight: CGFloat = 64 - - func present(title: String, body: String, autoDismissAfter: TimeInterval = 6) { - self.dismissTask?.cancel() - self.model.title = title - self.model.body = body - self.ensureWindow() - self.hostingView?.rootView = NotifyOverlayView(controller: self) - self.presentWindow() - - if autoDismissAfter > 0 { - self.dismissTask = Task { [weak self] in - try? await Task.sleep(nanoseconds: UInt64(autoDismissAfter * 1_000_000_000)) - await MainActor.run { self?.dismiss() } - } - } - } - - func dismiss() { - self.dismissTask?.cancel() - self.dismissTask = nil - guard let window else { return } - - let target = window.frame.offsetBy(dx: 8, dy: 6) - NSAnimationContext.runAnimationGroup { context in - context.duration = 0.16 - context.timingFunction = CAMediaTimingFunction(name: .easeOut) - window.animator().setFrame(target, display: true) - window.animator().alphaValue = 0 - } completionHandler: { - Task { @MainActor in - window.orderOut(nil) - self.model.isVisible = false - } - } - } - - // MARK: - Private - - private func presentWindow() { - self.ensureWindow() - self.hostingView?.rootView = NotifyOverlayView(controller: self) - let target = self.targetFrame() - - guard let window else { return } - if !self.model.isVisible { - self.model.isVisible = true - let start = target.offsetBy(dx: 0, dy: -6) - window.setFrame(start, display: true) - window.alphaValue = 0 - window.orderFrontRegardless() - NSAnimationContext.runAnimationGroup { context in - context.duration = 0.18 - context.timingFunction = CAMediaTimingFunction(name: .easeOut) - window.animator().setFrame(target, display: true) - window.animator().alphaValue = 1 - } - } else { - self.updateWindowFrame(animate: true) - window.orderFrontRegardless() - } - } - - private func ensureWindow() { - if self.window != nil { return } - let panel = NSPanel( - contentRect: NSRect(x: 0, y: 0, width: self.width, height: self.minHeight), - styleMask: [.nonactivatingPanel, .borderless], - backing: .buffered, - defer: false) - panel.isOpaque = false - panel.backgroundColor = .clear - panel.hasShadow = true - panel.level = .statusBar - panel.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary, .transient] - panel.hidesOnDeactivate = false - panel.isMovable = false - panel.isFloatingPanel = true - panel.becomesKeyOnlyIfNeeded = true - panel.titleVisibility = .hidden - panel.titlebarAppearsTransparent = true - - let host = NSHostingView(rootView: NotifyOverlayView(controller: self)) - host.translatesAutoresizingMaskIntoConstraints = false - panel.contentView = host - self.hostingView = host - self.window = panel - } - - private func targetFrame() -> NSRect { - guard let screen = NSScreen.main else { return .zero } - let height = self.measuredHeight() - let size = NSSize(width: self.width, height: height) - let visible = screen.visibleFrame - let origin = CGPoint(x: visible.maxX - size.width - 8, y: visible.maxY - size.height - 8) - return NSRect(origin: origin, size: size) - } - - private func updateWindowFrame(animate: Bool = false) { - guard let window else { return } - let frame = self.targetFrame() - if animate { - NSAnimationContext.runAnimationGroup { context in - context.duration = 0.12 - context.timingFunction = CAMediaTimingFunction(name: .easeOut) - window.animator().setFrame(frame, display: true) - } - } else { - window.setFrame(frame, display: true) - } - } - - private func measuredHeight() -> CGFloat { - let maxWidth = self.width - self.padding * 2 - let titleFont = NSFont.systemFont(ofSize: 13, weight: .semibold) - let bodyFont = NSFont.systemFont(ofSize: 12, weight: .regular) - - let titleRect = (self.model.title as NSString).boundingRect( - with: CGSize(width: maxWidth, height: .greatestFiniteMagnitude), - options: [.usesLineFragmentOrigin, .usesFontLeading], - attributes: [.font: titleFont], - context: nil) - - let bodyRect = (self.model.body as NSString).boundingRect( - with: CGSize(width: maxWidth, height: .greatestFiniteMagnitude), - options: [.usesLineFragmentOrigin, .usesFontLeading], - attributes: [.font: bodyFont], - context: nil) - - let contentHeight = ceil(titleRect.height + 6 + bodyRect.height) - let total = contentHeight + self.padding * 2 - return max(self.minHeight, min(total, self.maxHeight)) - } -} - -private struct NotifyOverlayView: View { - var controller: NotifyOverlayController - - var body: some View { - VStack(alignment: .leading, spacing: 6) { - Text(self.controller.model.title) - .font(.system(size: 13, weight: .semibold)) - .foregroundStyle(.primary) - .lineLimit(1) - - Text(self.controller.model.body) - .font(.system(size: 12)) - .foregroundStyle(.secondary) - .lineLimit(4) - .fixedSize(horizontal: false, vertical: true) - } - .padding(12) - .background( - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill(.regularMaterial)) - .overlay( - RoundedRectangle(cornerRadius: 12, style: .continuous) - .strokeBorder(Color.black.opacity(0.08), lineWidth: 1)) - .onTapGesture { - self.controller.dismiss() - } - } -} diff --git a/apps/macos/Sources/OpenClaw/Onboarding.swift b/apps/macos/Sources/OpenClaw/Onboarding.swift deleted file mode 100644 index b8a6377b419..00000000000 --- a/apps/macos/Sources/OpenClaw/Onboarding.swift +++ /dev/null @@ -1,196 +0,0 @@ -import AppKit -import Combine -import Observation -import OpenClawChatUI -import OpenClawDiscovery -import OpenClawIPC -import SwiftUI - -enum UIStrings { - static let welcomeTitle = "Welcome to OpenClaw" -} - -@MainActor -final class OnboardingController { - static let shared = OnboardingController() - private var window: NSWindow? - - 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: "openclaw.onboardingSeen") - UserDefaults.standard.set(currentOnboardingVersion, forKey: onboardingVersionKey) - AppStateStore.shared.onboardingSeen = true - return - } - if let window { - DockIconManager.shared.temporarilyShowDock() - window.makeKeyAndOrderFront(nil) - NSApp.activate(ignoringOtherApps: true) - return - } - let hosting = NSHostingController(rootView: OnboardingView()) - let window = NSWindow(contentViewController: hosting) - window.title = UIStrings.welcomeTitle - window.setContentSize(NSSize(width: OnboardingView.windowWidth, height: OnboardingView.windowHeight)) - window.styleMask = [.titled, .closable, .fullSizeContentView] - window.titlebarAppearsTransparent = true - window.titleVisibility = .hidden - window.isMovableByWindowBackground = true - window.center() - DockIconManager.shared.temporarilyShowDock() - window.makeKeyAndOrderFront(nil) - NSApp.activate(ignoringOtherApps: true) - self.window = window - } - - func close() { - self.window?.close() - self.window = nil - } - - func restart() { - self.close() - self.show() - } -} - -struct OnboardingView: View { - @Environment(\.openSettings) var openSettings - @State var currentPage = 0 - @State var isRequesting = false - @State var installingCLI = false - @State var cliStatus: String? - @State var copied = false - @State var monitoringPermissions = false - @State var monitoringDiscovery = false - @State var cliInstalled = false - @State var cliInstallLocation: String? - @State var workspacePath: String = "" - @State var workspaceStatus: String? - @State var workspaceApplying = false - @State var anthropicAuthPKCE: AnthropicOAuth.PKCE? - @State var anthropicAuthCode: String = "" - @State var anthropicAuthStatus: String? - @State var anthropicAuthBusy = false - @State var anthropicAuthConnected = false - @State var anthropicAuthVerifying = false - @State var anthropicAuthVerified = false - @State var anthropicAuthVerificationAttempted = false - @State var anthropicAuthVerificationFailed = false - @State var anthropicAuthVerifiedAt: Date? - @State var anthropicAuthDetectedStatus: OpenClawOAuthStore.AnthropicOAuthStatus = .missingFile - @State var anthropicAuthAutoDetectClipboard = true - @State var anthropicAuthAutoConnectClipboard = true - @State var anthropicAuthLastPasteboardChangeCount = NSPasteboard.general.changeCount - @State var monitoringAuth = false - @State var authMonitorTask: Task? - @State var needsBootstrap = false - @State var didAutoKickoff = false - @State var showAdvancedConnection = false - @State var preferredGatewayID: String? - @State var gatewayDiscovery: GatewayDiscoveryModel - @State var onboardingChatModel: OpenClawChatViewModel - @State var onboardingSkillsModel = SkillsSettingsModel() - @State var onboardingWizard = OnboardingWizardModel() - @State var didLoadOnboardingSkills = false - @State var localGatewayProbe: LocalGatewayProbe? - @Bindable var state: AppState - var permissionMonitor: PermissionMonitor - - static let windowWidth: CGFloat = 630 - static let windowHeight: CGFloat = 752 // ~+10% to fit full onboarding content - - let pageWidth: CGFloat = Self.windowWidth - let contentHeight: CGFloat = 460 - let connectionPageIndex = 1 - let anthropicAuthPageIndex = 2 - let wizardPageIndex = 3 - let onboardingChatPageIndex = 8 - - static let clipboardPoll: AnyPublisher = { - if ProcessInfo.processInfo.isRunningTests { - return Empty(completeImmediately: false).eraseToAnyPublisher() - } - return Timer.publish(every: 0.4, on: .main, in: .common) - .autoconnect() - .eraseToAnyPublisher() - }() - - let permissionsPageIndex = 5 - static func pageOrder( - for mode: AppState.ConnectionMode, - showOnboardingChat: Bool) -> [Int] - { - switch mode { - case .remote: - // Remote setup doesn't need local gateway/CLI/workspace setup pages, - // and WhatsApp/Telegram setup is optional. - showOnboardingChat ? [0, 1, 5, 8, 9] : [0, 1, 5, 9] - case .unconfigured: - showOnboardingChat ? [0, 1, 8, 9] : [0, 1, 9] - case .local: - showOnboardingChat ? [0, 1, 3, 5, 8, 9] : [0, 1, 3, 5, 9] - } - } - - var showOnboardingChat: Bool { - self.state.connectionMode == .local && self.needsBootstrap - } - - var pageOrder: [Int] { - Self.pageOrder(for: self.state.connectionMode, showOnboardingChat: self.showOnboardingChat) - } - - var pageCount: Int { - self.pageOrder.count - } - - var activePageIndex: Int { - self.activePageIndex(for: self.currentPage) - } - - var buttonTitle: String { - self.currentPage == self.pageCount - 1 ? "Finish" : "Next" - } - - var wizardPageOrderIndex: Int? { - self.pageOrder.firstIndex(of: self.wizardPageIndex) - } - - var isWizardBlocking: Bool { - self.activePageIndex == self.wizardPageIndex && !self.onboardingWizard.isComplete - } - - var canAdvance: Bool { - !self.isWizardBlocking - } - - var devLinkCommand: String { - let version = GatewayEnvironment.expectedGatewayVersionString() ?? "latest" - return "npm install -g openclaw@\(version)" - } - - struct LocalGatewayProbe: Equatable { - let port: Int - let pid: Int32 - let command: String - let expected: Bool - } - - init( - state: AppState = AppStateStore.shared, - permissionMonitor: PermissionMonitor = .shared, - discoveryModel: GatewayDiscoveryModel = GatewayDiscoveryModel( - localDisplayName: InstanceIdentity.displayName, - filterLocalGateways: false)) - { - self.state = state - self.permissionMonitor = permissionMonitor - self._gatewayDiscovery = State(initialValue: discoveryModel) - self._onboardingChatModel = State( - initialValue: OpenClawChatViewModel( - sessionKey: "onboarding", - transport: MacGatewayChatTransport())) - } -} diff --git a/apps/macos/Sources/OpenClaw/OnboardingView+Actions.swift b/apps/macos/Sources/OpenClaw/OnboardingView+Actions.swift deleted file mode 100644 index bcd5bd6d44d..00000000000 --- a/apps/macos/Sources/OpenClaw/OnboardingView+Actions.swift +++ /dev/null @@ -1,147 +0,0 @@ -import AppKit -import Foundation -import OpenClawDiscovery -import OpenClawIPC -import SwiftUI - -extension OnboardingView { - func selectLocalGateway() { - self.state.connectionMode = .local - self.preferredGatewayID = nil - self.showAdvancedConnection = false - GatewayDiscoveryPreferences.setPreferredStableID(nil) - } - - func selectUnconfiguredGateway() { - Task { await self.onboardingWizard.cancelIfRunning() } - self.state.connectionMode = .unconfigured - self.preferredGatewayID = nil - self.showAdvancedConnection = false - GatewayDiscoveryPreferences.setPreferredStableID(nil) - } - - func selectRemoteGateway(_ gateway: GatewayDiscoveryModel.DiscoveredGateway) { - Task { await self.onboardingWizard.cancelIfRunning() } - self.preferredGatewayID = gateway.stableID - GatewayDiscoveryPreferences.setPreferredStableID(gateway.stableID) - - if self.state.remoteTransport == .direct { - self.state.remoteUrl = GatewayDiscoveryHelpers.directUrl(for: gateway) ?? "" - } else { - self.state.remoteTarget = GatewayDiscoveryHelpers.sshTarget(for: gateway) ?? "" - } - if let endpoint = GatewayDiscoveryHelpers.serviceEndpoint(for: gateway) { - OpenClawConfigFile.setRemoteGatewayUrl( - host: endpoint.host, - port: endpoint.port) - } else { - OpenClawConfigFile.clearRemoteGatewayUrl() - } - - self.state.connectionMode = .remote - MacNodeModeCoordinator.shared.setPreferredGatewayStableID(gateway.stableID) - } - - func openSettings(tab: SettingsTab) { - SettingsTabRouter.request(tab) - self.openSettings() - DispatchQueue.main.async { - NotificationCenter.default.post(name: .openclawSelectSettingsTab, object: tab) - } - } - - func handleBack() { - withAnimation { - self.currentPage = max(0, self.currentPage - 1) - } - } - - func handleNext() { - if self.isWizardBlocking { return } - if self.currentPage < self.pageCount - 1 { - withAnimation { self.currentPage += 1 } - } else { - self.finish() - } - } - - func finish() { - UserDefaults.standard.set(true, forKey: "openclaw.onboardingSeen") - UserDefaults.standard.set(currentOnboardingVersion, forKey: onboardingVersionKey) - OnboardingController.shared.close() - } - - func copyToPasteboard(_ text: String) { - let pb = NSPasteboard.general - pb.clearContents() - pb.setString(text, forType: .string) - self.copied = true - DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) { self.copied = false } - } - - func startAnthropicOAuth() { - guard !self.anthropicAuthBusy else { return } - self.anthropicAuthBusy = true - defer { self.anthropicAuthBusy = false } - - do { - let pkce = try AnthropicOAuth.generatePKCE() - self.anthropicAuthPKCE = pkce - let url = AnthropicOAuth.buildAuthorizeURL(pkce: pkce) - NSWorkspace.shared.open(url) - self.anthropicAuthStatus = "Browser opened. After approving, paste the `code#state` value here." - } catch { - self.anthropicAuthStatus = "Failed to start OAuth: \(error.localizedDescription)" - } - } - - @MainActor - func finishAnthropicOAuth() async { - guard !self.anthropicAuthBusy else { return } - guard let pkce = self.anthropicAuthPKCE else { return } - self.anthropicAuthBusy = true - defer { self.anthropicAuthBusy = false } - - guard let parsed = AnthropicOAuthCodeState.parse(from: self.anthropicAuthCode) else { - self.anthropicAuthStatus = "OAuth failed: missing or invalid code/state." - return - } - - do { - let creds = try await AnthropicOAuth.exchangeCode( - code: parsed.code, - state: parsed.state, - verifier: pkce.verifier) - try OpenClawOAuthStore.saveAnthropicOAuth(creds) - self.refreshAnthropicOAuthStatus() - self.anthropicAuthStatus = "Connected. OpenClaw can now use Claude." - } catch { - self.anthropicAuthStatus = "OAuth failed: \(error.localizedDescription)" - } - } - - func pollAnthropicClipboardIfNeeded() { - guard self.currentPage == self.anthropicAuthPageIndex else { return } - guard self.anthropicAuthPKCE != nil else { return } - guard !self.anthropicAuthBusy else { return } - guard self.anthropicAuthAutoDetectClipboard else { return } - - let pb = NSPasteboard.general - let changeCount = pb.changeCount - guard changeCount != self.anthropicAuthLastPasteboardChangeCount else { return } - self.anthropicAuthLastPasteboardChangeCount = changeCount - - guard let raw = pb.string(forType: .string), !raw.isEmpty else { return } - guard let parsed = AnthropicOAuthCodeState.parse(from: raw) else { return } - guard let pkce = self.anthropicAuthPKCE, parsed.state == pkce.verifier else { return } - - let next = "\(parsed.code)#\(parsed.state)" - if self.anthropicAuthCode != next { - self.anthropicAuthCode = next - self.anthropicAuthStatus = "Detected `code#state` from clipboard." - } - - guard self.anthropicAuthAutoConnectClipboard else { return } - Task { await self.finishAnthropicOAuth() } - } -} diff --git a/apps/macos/Sources/OpenClaw/OnboardingView+Chat.swift b/apps/macos/Sources/OpenClaw/OnboardingView+Chat.swift deleted file mode 100644 index f95da4ffbb5..00000000000 --- a/apps/macos/Sources/OpenClaw/OnboardingView+Chat.swift +++ /dev/null @@ -1,26 +0,0 @@ -import Foundation - -extension OnboardingView { - func maybeKickoffOnboardingChat(for pageIndex: Int) { - guard pageIndex == self.onboardingChatPageIndex else { return } - guard self.showOnboardingChat else { return } - guard !self.didAutoKickoff else { return } - self.didAutoKickoff = true - - Task { @MainActor in - for _ in 0..<20 { - if !self.onboardingChatModel.isLoading { break } - try? await Task.sleep(nanoseconds: 200_000_000) - } - guard self.onboardingChatModel.messages.isEmpty else { return } - let kickoff = - "Hi! I just installed OpenClaw 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 " + - "how we should talk (web‑only, WhatsApp, or Telegram)." - self.onboardingChatModel.input = kickoff - self.onboardingChatModel.send() - } - } -} diff --git a/apps/macos/Sources/OpenClaw/OnboardingView+Layout.swift b/apps/macos/Sources/OpenClaw/OnboardingView+Layout.swift deleted file mode 100644 index ce87e211ce4..00000000000 --- a/apps/macos/Sources/OpenClaw/OnboardingView+Layout.swift +++ /dev/null @@ -1,234 +0,0 @@ -import AppKit -import SwiftUI - -extension OnboardingView { - var body: some View { - VStack(spacing: 0) { - GlowingOpenClawIcon(size: 130, glowIntensity: 0.28) - .offset(y: 10) - .frame(height: 145) - - GeometryReader { _ in - HStack(spacing: 0) { - ForEach(self.pageOrder, id: \.self) { pageIndex in - self.pageView(for: pageIndex) - .frame(width: self.pageWidth) - } - } - .offset(x: CGFloat(-self.currentPage) * self.pageWidth) - .animation( - .interactiveSpring(response: 0.5, dampingFraction: 0.86, blendDuration: 0.25), - value: self.currentPage) - .frame(height: self.contentHeight, alignment: .top) - .clipped() - } - .frame(height: self.contentHeight) - - Spacer(minLength: 0) - self.navigationBar - } - .frame(width: self.pageWidth, height: Self.windowHeight) - .background(Color(NSColor.windowBackgroundColor)) - .onAppear { - self.currentPage = 0 - self.updateMonitoring(for: 0) - } - .onChange(of: self.currentPage) { _, newValue in - self.updateMonitoring(for: self.activePageIndex(for: newValue)) - } - .onChange(of: self.state.connectionMode) { _, _ in - let oldActive = self.activePageIndex - self.reconcilePageForModeChange(previousActivePageIndex: oldActive) - self.updateDiscoveryMonitoring(for: self.activePageIndex) - } - .onChange(of: self.needsBootstrap) { _, _ in - if self.currentPage >= self.pageOrder.count { - self.currentPage = max(0, self.pageOrder.count - 1) - } - } - .onChange(of: self.onboardingWizard.isComplete) { _, newValue in - guard newValue, self.activePageIndex == self.wizardPageIndex else { return } - self.handleNext() - } - .onDisappear { - self.stopPermissionMonitoring() - self.stopDiscovery() - self.stopAuthMonitoring() - Task { await self.onboardingWizard.cancelIfRunning() } - } - .task { - await self.refreshPerms() - self.refreshCLIStatus() - await self.loadWorkspaceDefaults() - await self.ensureDefaultWorkspace() - self.refreshAnthropicOAuthStatus() - self.refreshBootstrapStatus() - self.preferredGatewayID = GatewayDiscoveryPreferences.preferredStableID() - } - } - - func activePageIndex(for pageCursor: Int) -> Int { - guard !self.pageOrder.isEmpty else { return 0 } - let clamped = min(max(0, pageCursor), self.pageOrder.count - 1) - return self.pageOrder[clamped] - } - - func reconcilePageForModeChange(previousActivePageIndex: Int) { - if let exact = self.pageOrder.firstIndex(of: previousActivePageIndex) { - withAnimation { self.currentPage = exact } - return - } - if let next = self.pageOrder.firstIndex(where: { $0 > previousActivePageIndex }) { - withAnimation { self.currentPage = next } - return - } - withAnimation { self.currentPage = max(0, self.pageOrder.count - 1) } - } - - var navigationBar: some View { - let wizardLockIndex = self.wizardPageOrderIndex - return HStack(spacing: 20) { - ZStack(alignment: .leading) { - Button(action: {}, label: { - Label("Back", systemImage: "chevron.left").labelStyle(.iconOnly) - }) - .buttonStyle(.plain) - .opacity(0) - .disabled(true) - - if self.currentPage > 0 { - Button(action: self.handleBack, label: { - Label("Back", systemImage: "chevron.left") - .labelStyle(.iconOnly) - }) - .buttonStyle(.plain) - .foregroundColor(.secondary) - .opacity(0.8) - .transition(.opacity.combined(with: .scale(scale: 0.9))) - } - } - .frame(minWidth: 80, alignment: .leading) - - Spacer() - - HStack(spacing: 8) { - ForEach(0.. (wizardLockIndex ?? 0) - Button { - withAnimation { self.currentPage = index } - } label: { - Circle() - .fill(index == self.currentPage ? Color.accentColor : Color.gray.opacity(0.3)) - .frame(width: 8, height: 8) - } - .buttonStyle(.plain) - .disabled(isLocked) - .opacity(isLocked ? 0.3 : 1) - } - } - - Spacer() - - Button(action: self.handleNext) { - Text(self.buttonTitle) - .frame(minWidth: 88) - } - .keyboardShortcut(.return) - .buttonStyle(.borderedProminent) - .disabled(!self.canAdvance) - } - .padding(.horizontal, 28) - .padding(.bottom, 13) - .frame(minHeight: 60, alignment: .bottom) - } - - func onboardingPage(@ViewBuilder _ content: () -> some View) -> some View { - let scrollIndicatorGutter: CGFloat = 18 - return ScrollView { - VStack(spacing: 16) { - content() - Spacer(minLength: 0) - } - .frame(maxWidth: .infinity, alignment: .top) - .padding(.trailing, scrollIndicatorGutter) - } - .scrollIndicators(.automatic) - .padding(.horizontal, 28) - .frame(width: self.pageWidth, alignment: .top) - } - - func onboardingCard( - spacing: CGFloat = 12, - padding: CGFloat = 16, - @ViewBuilder _ content: () -> some View) -> some View - { - VStack(alignment: .leading, spacing: spacing) { - content() - } - .padding(padding) - .frame(maxWidth: .infinity, alignment: .leading) - .background( - RoundedRectangle(cornerRadius: 16, style: .continuous) - .fill(Color(NSColor.controlBackgroundColor)) - .shadow(color: .black.opacity(0.06), radius: 8, y: 3)) - } - - func onboardingGlassCard( - spacing: CGFloat = 12, - padding: CGFloat = 16, - @ViewBuilder _ content: () -> some View) -> some View - { - let shape = RoundedRectangle(cornerRadius: 16, style: .continuous) - return VStack(alignment: .leading, spacing: spacing) { - content() - } - .padding(padding) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Color.clear) - .clipShape(shape) - .overlay(shape.strokeBorder(Color.white.opacity(0.10), lineWidth: 1)) - } - - func featureRow(title: String, subtitle: String, systemImage: String) -> some View { - HStack(alignment: .top, spacing: 12) { - Image(systemName: systemImage) - .font(.title3.weight(.semibold)) - .foregroundStyle(Color.accentColor) - .frame(width: 26) - VStack(alignment: .leading, spacing: 4) { - Text(title).font(.headline) - Text(subtitle) - .font(.subheadline) - .foregroundStyle(.secondary) - } - } - .padding(.vertical, 4) - } - - func featureActionRow( - title: String, - subtitle: String, - systemImage: String, - buttonTitle: String, - action: @escaping () -> Void) -> some View - { - HStack(alignment: .top, spacing: 12) { - Image(systemName: systemImage) - .font(.title3.weight(.semibold)) - .foregroundStyle(Color.accentColor) - .frame(width: 26) - VStack(alignment: .leading, spacing: 4) { - Text(title).font(.headline) - Text(subtitle) - .font(.subheadline) - .foregroundStyle(.secondary) - Button(buttonTitle, action: action) - .buttonStyle(.link) - .padding(.top, 2) - } - Spacer(minLength: 0) - } - .padding(.vertical, 4) - } -} diff --git a/apps/macos/Sources/OpenClaw/OnboardingView+Monitoring.swift b/apps/macos/Sources/OpenClaw/OnboardingView+Monitoring.swift deleted file mode 100644 index dfbdf91d44d..00000000000 --- a/apps/macos/Sources/OpenClaw/OnboardingView+Monitoring.swift +++ /dev/null @@ -1,178 +0,0 @@ -import Foundation -import OpenClawIPC - -extension OnboardingView { - @MainActor - func refreshPerms() async { - await self.permissionMonitor.refreshNow() - } - - @MainActor - func request(_ cap: Capability) async { - guard !self.isRequesting else { return } - self.isRequesting = true - defer { isRequesting = false } - _ = await PermissionManager.ensure([cap], interactive: true) - await self.refreshPerms() - } - - func updatePermissionMonitoring(for pageIndex: Int) { - let shouldMonitor = pageIndex == self.permissionsPageIndex - if shouldMonitor, !self.monitoringPermissions { - self.monitoringPermissions = true - PermissionMonitor.shared.register() - } else if !shouldMonitor, self.monitoringPermissions { - self.monitoringPermissions = false - PermissionMonitor.shared.unregister() - } - } - - func updateDiscoveryMonitoring(for pageIndex: Int) { - let isConnectionPage = pageIndex == self.connectionPageIndex - let shouldMonitor = isConnectionPage - if shouldMonitor, !self.monitoringDiscovery { - self.monitoringDiscovery = true - Task { @MainActor in - try? await Task.sleep(nanoseconds: 150_000_000) - guard self.monitoringDiscovery else { return } - self.gatewayDiscovery.start() - await self.refreshLocalGatewayProbe() - } - } else if !shouldMonitor, self.monitoringDiscovery { - self.monitoringDiscovery = false - self.gatewayDiscovery.stop() - } - } - - func updateMonitoring(for pageIndex: Int) { - self.updatePermissionMonitoring(for: pageIndex) - self.updateDiscoveryMonitoring(for: pageIndex) - self.updateAuthMonitoring(for: pageIndex) - self.maybeKickoffOnboardingChat(for: pageIndex) - } - - func stopPermissionMonitoring() { - guard self.monitoringPermissions else { return } - self.monitoringPermissions = false - PermissionMonitor.shared.unregister() - } - - func stopDiscovery() { - guard self.monitoringDiscovery else { return } - self.monitoringDiscovery = false - self.gatewayDiscovery.stop() - } - - func updateAuthMonitoring(for pageIndex: Int) { - let shouldMonitor = pageIndex == self.anthropicAuthPageIndex && self.state.connectionMode == .local - if shouldMonitor, !self.monitoringAuth { - self.monitoringAuth = true - self.startAuthMonitoring() - } else if !shouldMonitor, self.monitoringAuth { - self.stopAuthMonitoring() - } - } - - func startAuthMonitoring() { - self.refreshAnthropicOAuthStatus() - self.authMonitorTask?.cancel() - self.authMonitorTask = Task { - while !Task.isCancelled { - await MainActor.run { self.refreshAnthropicOAuthStatus() } - try? await Task.sleep(nanoseconds: 1_000_000_000) - } - } - } - - func stopAuthMonitoring() { - self.monitoringAuth = false - self.authMonitorTask?.cancel() - self.authMonitorTask = nil - } - - func installCLI() async { - guard !self.installingCLI else { return } - self.installingCLI = true - defer { installingCLI = false } - await CLIInstaller.install { message in - self.cliStatus = message - } - self.refreshCLIStatus() - } - - func refreshCLIStatus() { - let installLocation = CLIInstaller.installedLocation() - self.cliInstallLocation = installLocation - self.cliInstalled = installLocation != nil - } - - func refreshLocalGatewayProbe() async { - let port = GatewayEnvironment.gatewayPort() - let desc = await PortGuardian.shared.describe(port: port) - await MainActor.run { - guard let desc else { - self.localGatewayProbe = nil - return - } - let command = desc.command.trimmingCharacters(in: .whitespacesAndNewlines) - let expectedTokens = ["node", "openclaw", "tsx", "pnpm", "bun"] - let lower = command.lowercased() - let expected = expectedTokens.contains { lower.contains($0) } - self.localGatewayProbe = LocalGatewayProbe( - port: port, - pid: desc.pid, - command: command, - expected: expected) - } - } - - func refreshAnthropicOAuthStatus() { - _ = OpenClawOAuthStore.importLegacyAnthropicOAuthIfNeeded() - let previous = self.anthropicAuthDetectedStatus - let status = OpenClawOAuthStore.anthropicOAuthStatus() - self.anthropicAuthDetectedStatus = status - self.anthropicAuthConnected = status.isConnected - - if previous != status { - self.anthropicAuthVerified = false - self.anthropicAuthVerificationAttempted = false - self.anthropicAuthVerificationFailed = false - self.anthropicAuthVerifiedAt = nil - } - } - - @MainActor - func verifyAnthropicOAuthIfNeeded(force: Bool = false) async { - guard self.state.connectionMode == .local else { return } - guard self.anthropicAuthDetectedStatus.isConnected else { return } - if self.anthropicAuthVerified, !force { return } - if self.anthropicAuthVerifying { return } - if self.anthropicAuthVerificationAttempted, !force { return } - - self.anthropicAuthVerificationAttempted = true - self.anthropicAuthVerifying = true - self.anthropicAuthVerificationFailed = false - defer { self.anthropicAuthVerifying = false } - - guard let refresh = OpenClawOAuthStore.loadAnthropicOAuthRefreshToken(), !refresh.isEmpty else { - self.anthropicAuthStatus = "OAuth verification failed: missing refresh token." - self.anthropicAuthVerificationFailed = true - return - } - - do { - let updated = try await AnthropicOAuth.refresh(refreshToken: refresh) - try OpenClawOAuthStore.saveAnthropicOAuth(updated) - self.refreshAnthropicOAuthStatus() - self.anthropicAuthVerified = true - self.anthropicAuthVerifiedAt = Date() - self.anthropicAuthVerificationFailed = false - self.anthropicAuthStatus = "OAuth detected and verified." - } catch { - self.anthropicAuthVerified = false - self.anthropicAuthVerifiedAt = nil - self.anthropicAuthVerificationFailed = true - self.anthropicAuthStatus = "OAuth verification failed: \(error.localizedDescription)" - } - } -} diff --git a/apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift b/apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift deleted file mode 100644 index 5b05ab164c2..00000000000 --- a/apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift +++ /dev/null @@ -1,847 +0,0 @@ -import AppKit -import OpenClawChatUI -import OpenClawDiscovery -import OpenClawIPC -import SwiftUI - -extension OnboardingView { - @ViewBuilder - func pageView(for pageIndex: Int) -> some View { - switch pageIndex { - case 0: - self.welcomePage() - case 1: - self.connectionPage() - case 2: - self.anthropicAuthPage() - case 3: - self.wizardPage() - case 5: - self.permissionsPage() - case 6: - self.cliPage() - case 8: - self.onboardingChatPage() - case 9: - self.readyPage() - default: - EmptyView() - } - } - - func welcomePage() -> some View { - self.onboardingPage { - VStack(spacing: 22) { - Text("Welcome to OpenClaw") - .font(.largeTitle.weight(.semibold)) - Text("OpenClaw is a powerful personal AI assistant that can connect to WhatsApp or Telegram.") - .font(.body) - .foregroundStyle(.secondary) - .multilineTextAlignment(.center) - .lineLimit(2) - .frame(maxWidth: 560) - .fixedSize(horizontal: false, vertical: true) - - self.onboardingCard(spacing: 10, padding: 14) { - HStack(alignment: .top, spacing: 12) { - Image(systemName: "exclamationmark.triangle.fill") - .font(.title3.weight(.semibold)) - .foregroundStyle(Color(nsColor: .systemOrange)) - .frame(width: 22) - .padding(.top, 1) - - VStack(alignment: .leading, spacing: 6) { - Text("Security notice") - .font(.headline) - Text( - "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 OpenClaw if you understand the risks and trust the prompts and " + - "integrations you use.") - .font(.subheadline) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - } - } - .frame(maxWidth: 520) - } - .padding(.top, 16) - } - } - - func connectionPage() -> some View { - self.onboardingPage { - Text("Choose your Gateway") - .font(.largeTitle.weight(.semibold)) - Text( - "OpenClaw uses a single Gateway that stays running. Pick this Mac, " + - "connect to a discovered gateway nearby, or configure later.") - .font(.body) - .foregroundStyle(.secondary) - .multilineTextAlignment(.center) - .lineLimit(2) - .frame(maxWidth: 520) - .fixedSize(horizontal: false, vertical: true) - - self.onboardingCard(spacing: 12, padding: 14) { - VStack(alignment: .leading, spacing: 10) { - let localSubtitle: String = { - guard let probe = self.localGatewayProbe else { - return "Gateway starts automatically on this Mac." - } - let base = probe.expected - ? "Existing gateway detected" - : "Port \(probe.port) already in use" - let command = probe.command.isEmpty ? "" : " (\(probe.command) pid \(probe.pid))" - return "\(base)\(command). Will attach." - }() - self.connectionChoiceButton( - title: "This Mac", - subtitle: localSubtitle, - selected: self.state.connectionMode == .local) - { - self.selectLocalGateway() - } - - Divider().padding(.vertical, 4) - - HStack(spacing: 8) { - Image(systemName: "dot.radiowaves.left.and.right") - .font(.caption) - .foregroundStyle(.secondary) - Text(self.gatewayDiscovery.statusText) - .font(.caption) - .foregroundStyle(.secondary) - if self.gatewayDiscovery.gateways.isEmpty { - ProgressView().controlSize(.small) - Button("Refresh") { - self.gatewayDiscovery.refreshWideAreaFallbackNow(timeoutSeconds: 5.0) - } - .buttonStyle(.link) - .help("Retry Tailscale discovery (DNS-SD).") - } - Spacer(minLength: 0) - } - - if self.gatewayDiscovery.gateways.isEmpty { - Text("Searching for nearby gateways…") - .font(.caption) - .foregroundStyle(.secondary) - .padding(.leading, 4) - } else { - VStack(alignment: .leading, spacing: 6) { - Text("Nearby gateways") - .font(.caption) - .foregroundStyle(.secondary) - .padding(.leading, 4) - ForEach(self.gatewayDiscovery.gateways.prefix(6)) { gateway in - self.connectionChoiceButton( - title: gateway.displayName, - subtitle: self.gatewaySubtitle(for: gateway), - selected: self.isSelectedGateway(gateway)) - { - self.selectRemoteGateway(gateway) - } - } - } - .padding(8) - .background( - RoundedRectangle(cornerRadius: 10, style: .continuous) - .fill(Color(NSColor.controlBackgroundColor))) - } - - self.connectionChoiceButton( - title: "Configure later", - subtitle: "Don’t start the Gateway yet.", - selected: self.state.connectionMode == .unconfigured) - { - self.selectUnconfiguredGateway() - } - - Button(self.showAdvancedConnection ? "Hide Advanced" : "Advanced…") { - withAnimation(.spring(response: 0.25, dampingFraction: 0.9)) { - self.showAdvancedConnection.toggle() - } - if self.showAdvancedConnection, self.state.connectionMode != .remote { - self.state.connectionMode = .remote - } - } - .buttonStyle(.link) - - if self.showAdvancedConnection { - let labelWidth: CGFloat = 110 - let fieldWidth: CGFloat = 320 - - VStack(alignment: .leading, spacing: 10) { - Grid(alignment: .leading, horizontalSpacing: 12, verticalSpacing: 8) { - GridRow { - Text("Transport") - .font(.callout.weight(.semibold)) - .frame(width: labelWidth, alignment: .leading) - Picker("Transport", selection: self.$state.remoteTransport) { - Text("SSH tunnel").tag(AppState.RemoteTransport.ssh) - Text("Direct (ws/wss)").tag(AppState.RemoteTransport.direct) - } - .pickerStyle(.segmented) - .frame(width: fieldWidth) - } - if self.state.remoteTransport == .direct { - GridRow { - Text("Gateway URL") - .font(.callout.weight(.semibold)) - .frame(width: labelWidth, alignment: .leading) - TextField("wss://gateway.example.ts.net", text: self.$state.remoteUrl) - .textFieldStyle(.roundedBorder) - .frame(width: fieldWidth) - } - } - if self.state.remoteTransport == .ssh { - GridRow { - Text("SSH target") - .font(.callout.weight(.semibold)) - .frame(width: labelWidth, alignment: .leading) - TextField("user@host[:port]", text: self.$state.remoteTarget) - .textFieldStyle(.roundedBorder) - .frame(width: fieldWidth) - } - if let message = CommandResolver - .sshTargetValidationMessage(self.state.remoteTarget) - { - GridRow { - Text("") - .frame(width: labelWidth, alignment: .leading) - Text(message) - .font(.caption) - .foregroundStyle(.red) - .frame(width: fieldWidth, alignment: .leading) - } - } - GridRow { - Text("Identity file") - .font(.callout.weight(.semibold)) - .frame(width: labelWidth, alignment: .leading) - TextField("/Users/you/.ssh/id_ed25519", text: self.$state.remoteIdentity) - .textFieldStyle(.roundedBorder) - .frame(width: fieldWidth) - } - GridRow { - Text("Project root") - .font(.callout.weight(.semibold)) - .frame(width: labelWidth, alignment: .leading) - TextField("/home/you/Projects/openclaw", text: self.$state.remoteProjectRoot) - .textFieldStyle(.roundedBorder) - .frame(width: fieldWidth) - } - GridRow { - Text("CLI path") - .font(.callout.weight(.semibold)) - .frame(width: labelWidth, alignment: .leading) - TextField( - "/Applications/OpenClaw.app/.../openclaw", - text: self.$state.remoteCliPath) - .textFieldStyle(.roundedBorder) - .frame(width: fieldWidth) - } - } - } - - Text(self.state.remoteTransport == .direct - ? "Tip: use Tailscale Serve so the gateway has a valid HTTPS cert." - : "Tip: keep Tailscale enabled so your gateway stays reachable.") - .font(.footnote) - .foregroundStyle(.secondary) - .lineLimit(1) - } - .transition(.opacity.combined(with: .move(edge: .top))) - } - } - } - } - } - - func gatewaySubtitle(for gateway: GatewayDiscoveryModel.DiscoveredGateway) -> String? { - if self.state.remoteTransport == .direct { - return GatewayDiscoveryHelpers.directUrl(for: gateway) ?? "Gateway pairing only" - } - if let target = GatewayDiscoveryHelpers.sshTarget(for: gateway), - let parsed = CommandResolver.parseSSHTarget(target) - { - let portSuffix = parsed.port != 22 ? " · ssh \(parsed.port)" : "" - return "\(parsed.host)\(portSuffix)" - } - return "Gateway pairing only" - } - - func isSelectedGateway(_ gateway: GatewayDiscoveryModel.DiscoveredGateway) -> Bool { - guard self.state.connectionMode == .remote else { return false } - let preferred = self.preferredGatewayID ?? GatewayDiscoveryPreferences.preferredStableID() - return preferred == gateway.stableID - } - - func connectionChoiceButton( - title: String, - subtitle: String?, - selected: Bool, - action: @escaping () -> Void) -> some View - { - Button { - withAnimation(.spring(response: 0.25, dampingFraction: 0.9)) { - action() - } - } label: { - HStack(alignment: .center, spacing: 10) { - VStack(alignment: .leading, spacing: 2) { - Text(title) - .font(.callout.weight(.semibold)) - .lineLimit(1) - .truncationMode(.tail) - if let subtitle { - Text(subtitle) - .font(.caption.monospaced()) - .foregroundStyle(.secondary) - .lineLimit(1) - .truncationMode(.middle) - } - } - Spacer(minLength: 0) - if selected { - Image(systemName: "checkmark.circle.fill") - .foregroundStyle(Color.accentColor) - } else { - Image(systemName: "arrow.right.circle") - .foregroundStyle(.secondary) - } - } - .padding(.horizontal, 10) - .padding(.vertical, 8) - .frame(maxWidth: .infinity, alignment: .leading) - .background( - RoundedRectangle(cornerRadius: 10, style: .continuous) - .fill(selected ? Color.accentColor.opacity(0.12) : Color.clear)) - .overlay( - RoundedRectangle(cornerRadius: 10, style: .continuous) - .strokeBorder( - selected ? Color.accentColor.opacity(0.45) : Color.clear, - lineWidth: 1)) - } - .buttonStyle(.plain) - } - - func anthropicAuthPage() -> some View { - self.onboardingPage { - Text("Connect Claude") - .font(.largeTitle.weight(.semibold)) - Text("Give your model the token it needs!") - .font(.body) - .foregroundStyle(.secondary) - .multilineTextAlignment(.center) - .frame(maxWidth: 540) - .fixedSize(horizontal: false, vertical: true) - Text("OpenClaw supports any model — we strongly recommend Opus 4.6 for the best experience.") - .font(.callout) - .foregroundStyle(.secondary) - .multilineTextAlignment(.center) - .frame(maxWidth: 540) - .fixedSize(horizontal: false, vertical: true) - - self.onboardingCard(spacing: 12, padding: 16) { - HStack(alignment: .center, spacing: 10) { - Circle() - .fill(self.anthropicAuthVerified ? Color.green : Color.orange) - .frame(width: 10, height: 10) - Text( - self.anthropicAuthConnected - ? (self.anthropicAuthVerified - ? "Claude connected (OAuth) — verified" - : "Claude connected (OAuth)") - : "Not connected yet") - .font(.headline) - Spacer() - } - - if self.anthropicAuthConnected, self.anthropicAuthVerifying { - Text("Verifying OAuth…") - .font(.caption) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } else if !self.anthropicAuthConnected { - Text(self.anthropicAuthDetectedStatus.shortDescription) - .font(.caption) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } else if self.anthropicAuthVerified, let date = self.anthropicAuthVerifiedAt { - Text("Detected working OAuth (\(date.formatted(date: .abbreviated, time: .shortened))).") - .font(.caption) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - - Text( - "This lets OpenClaw use Claude immediately. Credentials are stored at " + - "`~/.openclaw/credentials/oauth.json` (owner-only).") - .font(.subheadline) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - - HStack(spacing: 12) { - Text(OpenClawOAuthStore.oauthURL().path) - .font(.caption) - .foregroundStyle(.secondary) - .lineLimit(1) - .truncationMode(.middle) - - Spacer() - - Button("Reveal") { - NSWorkspace.shared.activateFileViewerSelecting([OpenClawOAuthStore.oauthURL()]) - } - .buttonStyle(.bordered) - - Button("Refresh") { - self.refreshAnthropicOAuthStatus() - } - .buttonStyle(.bordered) - } - - Divider().padding(.vertical, 2) - - HStack(spacing: 12) { - if !self.anthropicAuthVerified { - if self.anthropicAuthConnected { - Button("Verify") { - Task { await self.verifyAnthropicOAuthIfNeeded(force: true) } - } - .buttonStyle(.borderedProminent) - .disabled(self.anthropicAuthBusy || self.anthropicAuthVerifying) - - if self.anthropicAuthVerificationFailed { - Button("Re-auth (OAuth)") { - self.startAnthropicOAuth() - } - .buttonStyle(.bordered) - .disabled(self.anthropicAuthBusy || self.anthropicAuthVerifying) - } - } else { - Button { - self.startAnthropicOAuth() - } label: { - if self.anthropicAuthBusy { - ProgressView() - } else { - Text("Open Claude sign-in (OAuth)") - } - } - .buttonStyle(.borderedProminent) - .disabled(self.anthropicAuthBusy) - } - } - } - - if !self.anthropicAuthVerified, self.anthropicAuthPKCE != nil { - VStack(alignment: .leading, spacing: 8) { - Text("Paste the `code#state` value") - .font(.headline) - TextField("code#state", text: self.$anthropicAuthCode) - .textFieldStyle(.roundedBorder) - - Toggle("Auto-detect from clipboard", isOn: self.$anthropicAuthAutoDetectClipboard) - .font(.caption) - .foregroundStyle(.secondary) - .disabled(self.anthropicAuthBusy) - - Toggle("Auto-connect when detected", isOn: self.$anthropicAuthAutoConnectClipboard) - .font(.caption) - .foregroundStyle(.secondary) - .disabled(self.anthropicAuthBusy) - - Button("Connect") { - Task { await self.finishAnthropicOAuth() } - } - .buttonStyle(.bordered) - .disabled( - self.anthropicAuthBusy || - self.anthropicAuthCode.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) - } - .onReceive(Self.clipboardPoll) { _ in - self.pollAnthropicClipboardIfNeeded() - } - } - - self.onboardingCard(spacing: 8, padding: 12) { - Text("API key (advanced)") - .font(.headline) - Text( - "You can also use an Anthropic API key, but this UI is instructions-only for now " + - "(GUI apps don’t automatically inherit your shell env vars like `ANTHROPIC_API_KEY`).") - .font(.subheadline) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - .shadow(color: .clear, radius: 0) - .background(Color.clear) - - if let status = self.anthropicAuthStatus { - Text(status) - .font(.caption) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - } - } - .task { await self.verifyAnthropicOAuthIfNeeded() } - } - - func permissionsPage() -> some View { - self.onboardingPage { - Text("Grant permissions") - .font(.largeTitle.weight(.semibold)) - Text("These macOS permissions let OpenClaw automate apps and capture context on this Mac.") - .font(.body) - .foregroundStyle(.secondary) - .multilineTextAlignment(.center) - .frame(maxWidth: 520) - .fixedSize(horizontal: false, vertical: true) - - self.onboardingCard(spacing: 8, padding: 12) { - ForEach(Capability.allCases, id: \.self) { cap in - PermissionRow( - capability: cap, - status: self.permissionMonitor.status[cap] ?? false, - compact: true) - { - Task { await self.request(cap) } - } - } - - HStack(spacing: 12) { - Button { - Task { await self.refreshPerms() } - } label: { - Label("Refresh", systemImage: "arrow.clockwise") - } - .buttonStyle(.bordered) - .controlSize(.small) - .help("Refresh status") - if self.isRequesting { - ProgressView() - .controlSize(.small) - } - } - .padding(.top, 4) - } - } - } - - func cliPage() -> some View { - self.onboardingPage { - Text("Install the CLI") - .font(.largeTitle.weight(.semibold)) - Text("Required for local mode: installs `openclaw` so launchd can run the gateway.") - .font(.body) - .foregroundStyle(.secondary) - .multilineTextAlignment(.center) - .frame(maxWidth: 520) - .fixedSize(horizontal: false, vertical: true) - - self.onboardingCard(spacing: 10) { - HStack(spacing: 12) { - Button { - Task { await self.installCLI() } - } label: { - let title = self.cliInstalled ? "Reinstall CLI" : "Install CLI" - ZStack { - Text(title) - .opacity(self.installingCLI ? 0 : 1) - if self.installingCLI { - ProgressView() - .controlSize(.mini) - } - } - .frame(minWidth: 120) - } - .buttonStyle(.borderedProminent) - .disabled(self.installingCLI) - - Button(self.copied ? "Copied" : "Copy install command") { - self.copyToPasteboard(self.devLinkCommand) - } - .disabled(self.installingCLI) - - if self.cliInstalled, let loc = self.cliInstallLocation { - Label("Installed at \(loc)", systemImage: "checkmark.circle.fill") - .font(.footnote) - .foregroundStyle(.green) - } - } - - if let cliStatus { - Text(cliStatus) - .font(.caption) - .foregroundStyle(.secondary) - } else if !self.cliInstalled, self.cliInstallLocation == nil { - Text( - """ - Installs a user-space Node 22+ runtime and the CLI (no Homebrew). - Rerun anytime to reinstall or update. - """) - .font(.footnote) - .foregroundStyle(.secondary) - } - } - } - } - - func workspacePage() -> some View { - self.onboardingPage { - Text("Agent workspace") - .font(.largeTitle.weight(.semibold)) - Text( - "OpenClaw 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) - .multilineTextAlignment(.center) - .frame(maxWidth: 560) - .fixedSize(horizontal: false, vertical: true) - - self.onboardingCard(spacing: 10) { - if self.state.connectionMode == .remote { - Text("Remote gateway detected") - .font(.headline) - Text( - "Create the workspace on the remote host (SSH in first). " + - "The macOS app can’t write files on your gateway over SSH yet.") - .font(.subheadline) - .foregroundStyle(.secondary) - - Button(self.copied ? "Copied" : "Copy setup command") { - self.copyToPasteboard(self.workspaceBootstrapCommand) - } - .buttonStyle(.bordered) - } else { - VStack(alignment: .leading, spacing: 8) { - Text("Workspace folder") - .font(.headline) - TextField( - AgentWorkspace.displayPath(for: OpenClawConfigFile.defaultWorkspaceURL()), - text: self.$workspacePath) - .textFieldStyle(.roundedBorder) - - HStack(spacing: 12) { - Button { - Task { await self.applyWorkspace() } - } label: { - if self.workspaceApplying { - ProgressView() - } else { - Text("Create workspace") - } - } - .buttonStyle(.borderedProminent) - .disabled(self.workspaceApplying) - - Button("Open folder") { - let url = AgentWorkspace.resolveWorkspaceURL(from: self.workspacePath) - NSWorkspace.shared.open(url) - } - .buttonStyle(.bordered) - .disabled(self.workspaceApplying) - - Button("Save in config") { - Task { - let url = AgentWorkspace.resolveWorkspaceURL(from: self.workspacePath) - let saved = await self.saveAgentWorkspace(AgentWorkspace.displayPath(for: url)) - if saved { - self.workspaceStatus = - "Saved to ~/.openclaw/openclaw.json (agents.defaults.workspace)" - } - } - } - .buttonStyle(.bordered) - .disabled(self.workspaceApplying) - } - } - - if let workspaceStatus { - Text(workspaceStatus) - .font(.caption) - .foregroundStyle(.secondary) - .lineLimit(2) - } else { - Text( - "Tip: edit AGENTS.md in this folder to shape the assistant’s behavior. " + - "For backup, make the workspace a private git repo so your agent’s " + - "“memory” is versioned.") - .font(.caption) - .foregroundStyle(.secondary) - .lineLimit(2) - } - } - } - } - } - - func onboardingChatPage() -> some View { - VStack(spacing: 16) { - Text("Meet your agent") - .font(.largeTitle.weight(.semibold)) - Text( - "This is a dedicated onboarding chat. Your agent will introduce itself, " + - "learn who you are, and help you connect WhatsApp or Telegram if you want.") - .font(.body) - .foregroundStyle(.secondary) - .multilineTextAlignment(.center) - .frame(maxWidth: 520) - .fixedSize(horizontal: false, vertical: true) - - self.onboardingGlassCard(padding: 8) { - OpenClawChatView(viewModel: self.onboardingChatModel, style: .onboarding) - .frame(maxHeight: .infinity) - } - .frame(maxHeight: .infinity) - } - .padding(.horizontal, 28) - .frame(width: self.pageWidth, height: self.contentHeight, alignment: .top) - } - - func readyPage() -> some View { - self.onboardingPage { - Text("All set") - .font(.largeTitle.weight(.semibold)) - self.onboardingCard { - if self.state.connectionMode == .unconfigured { - self.featureRow( - title: "Configure later", - subtitle: "Pick Local or Remote in Settings → General whenever you’re ready.", - systemImage: "gearshape") - Divider() - .padding(.vertical, 6) - } - if self.state.connectionMode == .remote { - self.featureRow( - title: "Remote gateway checklist", - subtitle: """ - On your gateway host: install/update the `openclaw` package and make sure credentials exist - (typically `~/.openclaw/credentials/oauth.json`). Then connect again if needed. - """, - systemImage: "network") - Divider() - .padding(.vertical, 6) - } - self.featureRow( - title: "Open the menu bar panel", - subtitle: "Click the OpenClaw menu bar icon for quick chat and status.", - systemImage: "bubble.left.and.bubble.right") - self.featureActionRow( - title: "Connect WhatsApp or Telegram", - subtitle: "Open Settings → Channels to link channels and monitor status.", - systemImage: "link", - buttonTitle: "Open Settings → Channels") - { - self.openSettings(tab: .channels) - } - self.featureRow( - title: "Try Voice Wake", - subtitle: "Enable Voice Wake in Settings for hands-free commands with a live transcript overlay.", - systemImage: "waveform.circle") - self.featureRow( - title: "Use the panel + Canvas", - subtitle: "Open the menu bar panel for quick chat; the agent can show previews " + - "and richer visuals in Canvas.", - systemImage: "rectangle.inset.filled.and.person.filled") - self.featureActionRow( - title: "Give your agent more powers", - subtitle: "Enable optional skills (Peekaboo, oracle, camsnap, …) from Settings → Skills.", - systemImage: "sparkles", - buttonTitle: "Open Settings → Skills") - { - self.openSettings(tab: .skills) - } - self.skillsOverview - Toggle("Launch at login", isOn: self.$state.launchAtLogin) - .onChange(of: self.state.launchAtLogin) { _, newValue in - AppStateStore.updateLaunchAtLogin(enabled: newValue) - } - } - } - .task { await self.maybeLoadOnboardingSkills() } - } - - private func maybeLoadOnboardingSkills() async { - guard !self.didLoadOnboardingSkills else { return } - self.didLoadOnboardingSkills = true - await self.onboardingSkillsModel.refresh() - } - - private var skillsOverview: some View { - VStack(alignment: .leading, spacing: 8) { - Divider() - .padding(.vertical, 6) - - HStack(spacing: 10) { - Text("Skills included") - .font(.headline) - Spacer(minLength: 0) - if self.onboardingSkillsModel.isLoading { - ProgressView() - .controlSize(.small) - } else { - Button("Refresh") { - Task { await self.onboardingSkillsModel.refresh() } - } - .buttonStyle(.link) - } - } - - if let error = self.onboardingSkillsModel.error { - VStack(alignment: .leading, spacing: 4) { - Text("Couldn’t load skills from the Gateway.") - .font(.footnote.weight(.semibold)) - .foregroundStyle(.orange) - Text( - "Make sure the Gateway is running and connected, " + - "then hit Refresh (or open Settings → Skills).") - .font(.footnote) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - Text("Details: \(error)") - .font(.caption.monospaced()) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - } else if self.onboardingSkillsModel.skills.isEmpty { - Text("No skills reported yet.") - .font(.footnote) - .foregroundStyle(.secondary) - } else { - ScrollView { - LazyVStack(alignment: .leading, spacing: 10) { - ForEach(self.onboardingSkillsModel.skills) { skill in - HStack(alignment: .top, spacing: 10) { - Text(skill.emoji ?? "✨") - .font(.callout) - .frame(width: 22, alignment: .leading) - VStack(alignment: .leading, spacing: 2) { - Text(skill.name) - .font(.callout.weight(.semibold)) - Text(skill.description) - .font(.footnote) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - Spacer(minLength: 0) - } - } - } - .padding(10) - .background( - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill(Color(NSColor.windowBackgroundColor))) - } - .frame(maxHeight: 160) - } - } - } -} diff --git a/apps/macos/Sources/OpenClaw/OnboardingView+Testing.swift b/apps/macos/Sources/OpenClaw/OnboardingView+Testing.swift deleted file mode 100644 index cf8c3d0c78f..00000000000 --- a/apps/macos/Sources/OpenClaw/OnboardingView+Testing.swift +++ /dev/null @@ -1,87 +0,0 @@ -import OpenClawDiscovery -import SwiftUI - -#if DEBUG -@MainActor -extension OnboardingView { - static func exerciseForTesting() { - let state = AppState(preview: true) - let discovery = GatewayDiscoveryModel(localDisplayName: InstanceIdentity.displayName) - discovery.statusText = "Searching..." - let gateway = GatewayDiscoveryModel.DiscoveredGateway( - displayName: "Test Gateway", - lanHost: "gateway.local", - tailnetDns: "gateway.ts.net", - sshPort: 2222, - gatewayPort: 18789, - cliPath: "/usr/local/bin/openclaw", - stableID: "gateway-1", - debugID: "gateway-1", - isLocal: false) - discovery.gateways = [gateway] - - let view = OnboardingView( - state: state, - permissionMonitor: PermissionMonitor.shared, - discoveryModel: discovery) - view.needsBootstrap = true - view.localGatewayProbe = LocalGatewayProbe( - port: GatewayEnvironment.gatewayPort(), - pid: 123, - command: "openclaw-gateway", - expected: true) - view.showAdvancedConnection = true - view.preferredGatewayID = gateway.stableID - view.cliInstalled = true - view.cliInstallLocation = "/usr/local/bin/openclaw" - view.cliStatus = "Installed" - view.workspacePath = "/tmp/openclaw" - view.workspaceStatus = "Saved workspace" - view.anthropicAuthPKCE = AnthropicOAuth.PKCE(verifier: "verifier", challenge: "challenge") - view.anthropicAuthCode = "code#state" - view.anthropicAuthStatus = "Connected" - view.anthropicAuthDetectedStatus = .connected(expiresAtMs: 1_700_000_000_000) - view.anthropicAuthConnected = true - view.anthropicAuthAutoDetectClipboard = false - view.anthropicAuthAutoConnectClipboard = false - - view.state.connectionMode = .local - _ = view.welcomePage() - _ = view.connectionPage() - _ = view.anthropicAuthPage() - _ = view.wizardPage() - _ = view.permissionsPage() - _ = view.cliPage() - _ = view.workspacePage() - _ = view.onboardingChatPage() - _ = view.readyPage() - - view.selectLocalGateway() - view.selectRemoteGateway(gateway) - view.selectUnconfiguredGateway() - - view.state.connectionMode = .remote - _ = view.connectionPage() - _ = view.workspacePage() - - view.state.connectionMode = .unconfigured - _ = view.connectionPage() - - view.currentPage = 0 - view.handleNext() - view.handleBack() - - _ = view.onboardingPage { Text("Test") } - _ = view.onboardingCard { Text("Card") } - _ = view.featureRow(title: "Feature", subtitle: "Subtitle", systemImage: "sparkles") - _ = view.featureActionRow( - title: "Action", - subtitle: "Action subtitle", - systemImage: "gearshape", - buttonTitle: "Action", - action: {}) - _ = view.gatewaySubtitle(for: gateway) - _ = view.isSelectedGateway(gateway) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/OnboardingView+Wizard.swift b/apps/macos/Sources/OpenClaw/OnboardingView+Wizard.swift deleted file mode 100644 index 0c77f1e327d..00000000000 --- a/apps/macos/Sources/OpenClaw/OnboardingView+Wizard.swift +++ /dev/null @@ -1,94 +0,0 @@ -import Observation -import OpenClawProtocol -import SwiftUI - -extension OnboardingView { - func wizardPage() -> some View { - self.onboardingPage { - VStack(spacing: 16) { - Text("Setup Wizard") - .font(.largeTitle.weight(.semibold)) - Text("Follow the guided setup from the Gateway. This keeps onboarding in sync with the CLI.") - .font(.body) - .foregroundStyle(.secondary) - .multilineTextAlignment(.center) - .frame(maxWidth: 520) - - self.onboardingCard(spacing: 14, padding: 16) { - OnboardingWizardCardContent( - wizard: self.onboardingWizard, - mode: self.state.connectionMode, - workspacePath: self.workspacePath) - } - } - .task { - await self.onboardingWizard.startIfNeeded( - mode: self.state.connectionMode, - workspace: self.workspacePath.isEmpty ? nil : self.workspacePath) - } - } - } -} - -private struct OnboardingWizardCardContent: View { - @Bindable var wizard: OnboardingWizardModel - let mode: AppState.ConnectionMode - let workspacePath: String - - private enum CardState { - case error(String) - case starting - case step(WizardStep) - case complete - case waiting - } - - private var state: CardState { - if let error = wizard.errorMessage { return .error(error) } - if self.wizard.isStarting { return .starting } - if let step = wizard.currentStep { return .step(step) } - if self.wizard.isComplete { return .complete } - return .waiting - } - - var body: some View { - switch self.state { - case let .error(error): - Text("Wizard error") - .font(.headline) - Text(error) - .font(.subheadline) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - Button("Retry") { - self.wizard.reset() - Task { - await self.wizard.startIfNeeded( - mode: self.mode, - workspace: self.workspacePath.isEmpty ? nil : self.workspacePath) - } - } - .buttonStyle(.borderedProminent) - case .starting: - HStack(spacing: 8) { - ProgressView() - Text("Starting wizard…") - .foregroundStyle(.secondary) - } - case let .step(step): - OnboardingWizardStepView( - step: step, - isSubmitting: self.wizard.isSubmitting) - { value in - Task { await self.wizard.submit(step: step, value: value) } - } - .id(step.id) - case .complete: - Text("Wizard complete. Continue to the next step.") - .font(.headline) - case .waiting: - Text("Waiting for wizard…") - .foregroundStyle(.secondary) - } - } -} diff --git a/apps/macos/Sources/OpenClaw/OnboardingView+Workspace.swift b/apps/macos/Sources/OpenClaw/OnboardingView+Workspace.swift deleted file mode 100644 index 1895b2af94f..00000000000 --- a/apps/macos/Sources/OpenClaw/OnboardingView+Workspace.swift +++ /dev/null @@ -1,116 +0,0 @@ -import Foundation - -extension OnboardingView { - func loadWorkspaceDefaults() async { - guard self.workspacePath.isEmpty else { return } - let configured = await self.loadAgentWorkspace() - let url = AgentWorkspace.resolveWorkspaceURL(from: configured) - self.workspacePath = AgentWorkspace.displayPath(for: url) - self.refreshBootstrapStatus() - } - - func ensureDefaultWorkspace() async { - guard self.state.connectionMode == .local else { return } - let configured = await self.loadAgentWorkspace() - let url = AgentWorkspace.resolveWorkspaceURL(from: configured) - switch AgentWorkspace.bootstrapSafety(for: url) { - case .safe: - do { - _ = try AgentWorkspace.bootstrap(workspaceURL: url) - if (configured ?? "").trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - await self.saveAgentWorkspace(AgentWorkspace.displayPath(for: url)) - } - } catch { - self.workspaceStatus = "Failed to create workspace: \(error.localizedDescription)" - } - case let .unsafe (reason): - self.workspaceStatus = "Workspace not touched: \(reason)" - } - self.refreshBootstrapStatus() - } - - func refreshBootstrapStatus() { - let url = AgentWorkspace.resolveWorkspaceURL(from: self.workspacePath) - self.needsBootstrap = AgentWorkspace.needsBootstrap(workspaceURL: url) - if self.needsBootstrap { - self.didAutoKickoff = false - } - } - - var workspaceBootstrapCommand: String { - let template = AgentWorkspace.defaultTemplate().trimmingCharacters(in: .whitespacesAndNewlines) - return """ - mkdir -p ~/.openclaw/workspace - cat > ~/.openclaw/workspace/AGENTS.md <<'EOF' - \(template) - EOF - """ - } - - func applyWorkspace() async { - guard !self.workspaceApplying else { return } - self.workspaceApplying = true - defer { self.workspaceApplying = false } - - do { - let url = AgentWorkspace.resolveWorkspaceURL(from: self.workspacePath) - if case let .unsafe (reason) = AgentWorkspace.bootstrapSafety(for: url) { - self.workspaceStatus = "Workspace not created: \(reason)" - return - } - _ = try AgentWorkspace.bootstrap(workspaceURL: url) - self.workspacePath = AgentWorkspace.displayPath(for: url) - self.workspaceStatus = "Workspace ready at \(self.workspacePath)" - self.refreshBootstrapStatus() - } catch { - self.workspaceStatus = "Failed to create workspace: \(error.localizedDescription)" - } - } - - private func loadAgentWorkspace() async -> String? { - let root = await ConfigStore.load() - let agents = root["agents"] as? [String: Any] - let defaults = agents?["defaults"] as? [String: Any] - return defaults?["workspace"] as? String - } - - @discardableResult - func saveAgentWorkspace(_ workspace: String?) async -> Bool { - let (success, errorMessage) = await OnboardingView.buildAndSaveWorkspace(workspace) - - if let errorMessage { - self.workspaceStatus = errorMessage - } - return success - } - - @MainActor - private static func buildAndSaveWorkspace(_ workspace: String?) async -> (Bool, String?) { - var root = await ConfigStore.load() - var agents = root["agents"] as? [String: Any] ?? [:] - var defaults = agents["defaults"] as? [String: Any] ?? [:] - let trimmed = workspace?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if trimmed.isEmpty { - defaults.removeValue(forKey: "workspace") - } else { - defaults["workspace"] = trimmed - } - if defaults.isEmpty { - agents.removeValue(forKey: "defaults") - } else { - agents["defaults"] = defaults - } - if agents.isEmpty { - root.removeValue(forKey: "agents") - } else { - root["agents"] = agents - } - do { - try await ConfigStore.save(root) - return (true, nil) - } catch { - let errorMessage = "Failed to save config: \(error.localizedDescription)" - return (false, errorMessage) - } - } -} diff --git a/apps/macos/Sources/OpenClaw/OnboardingWidgets.swift b/apps/macos/Sources/OpenClaw/OnboardingWidgets.swift deleted file mode 100644 index 58d09ef66dc..00000000000 --- a/apps/macos/Sources/OpenClaw/OnboardingWidgets.swift +++ /dev/null @@ -1,65 +0,0 @@ -import AppKit -import SwiftUI - -struct GlowingOpenClawIcon: View { - @Environment(\.scenePhase) private var scenePhase - - let size: CGFloat - let glowIntensity: Double - let enableFloating: Bool - - @State private var breathe = false - - init(size: CGFloat = 148, glowIntensity: Double = 0.35, enableFloating: Bool = true) { - self.size = size - self.glowIntensity = glowIntensity - self.enableFloating = enableFloating - } - - var body: some View { - let glowBlurRadius: CGFloat = 18 - let glowCanvasSize: CGFloat = self.size + 56 - ZStack { - Circle() - .fill( - LinearGradient( - colors: [ - Color.accentColor.opacity(self.glowIntensity), - Color.blue.opacity(self.glowIntensity * 0.6), - ], - startPoint: .topLeading, - endPoint: .bottomTrailing)) - .frame(width: glowCanvasSize, height: glowCanvasSize) - .padding(glowBlurRadius) - .blur(radius: glowBlurRadius) - .scaleEffect(self.breathe ? 1.08 : 0.96) - .opacity(0.84) - - Image(nsImage: NSApp.applicationIconImage) - .resizable() - .frame(width: self.size, height: self.size) - .clipShape(RoundedRectangle(cornerRadius: self.size * 0.22, style: .continuous)) - .shadow(color: .black.opacity(0.18), radius: 14, y: 6) - .scaleEffect(self.breathe ? 1.02 : 1.0) - } - .frame( - width: glowCanvasSize + (glowBlurRadius * 2), - height: glowCanvasSize + (glowBlurRadius * 2)) - .onAppear { self.updateBreatheAnimation() } - .onDisappear { self.breathe = false } - .onChange(of: self.scenePhase) { _, _ in - self.updateBreatheAnimation() - } - } - - private func updateBreatheAnimation() { - guard self.enableFloating, self.scenePhase == .active else { - self.breathe = false - return - } - guard !self.breathe else { return } - withAnimation(Animation.easeInOut(duration: 3.6).repeatForever(autoreverses: true)) { - self.breathe = true - } - } -} diff --git a/apps/macos/Sources/OpenClaw/OnboardingWizard.swift b/apps/macos/Sources/OpenClaw/OnboardingWizard.swift deleted file mode 100644 index 75b9522a4d1..00000000000 --- a/apps/macos/Sources/OpenClaw/OnboardingWizard.swift +++ /dev/null @@ -1,419 +0,0 @@ -import Foundation -import Observation -import OpenClawKit -import OpenClawProtocol -import OSLog -import SwiftUI - -private let onboardingWizardLogger = Logger(subsystem: "ai.openclaw", category: "onboarding.wizard") - -// MARK: - Swift 6 AnyCodable Bridging Helpers - -// Bridge between OpenClawProtocol.AnyCodable and the local module to avoid -// Swift 6 strict concurrency type conflicts. - -private typealias ProtocolAnyCodable = OpenClawProtocol.AnyCodable - -private func bridgeToLocal(_ value: ProtocolAnyCodable) -> AnyCodable { - if let data = try? JSONEncoder().encode(value), - let decoded = try? JSONDecoder().decode(AnyCodable.self, from: data) - { - return decoded - } - return AnyCodable(value.value) -} - -private func bridgeToLocal(_ value: ProtocolAnyCodable?) -> AnyCodable? { - value.map(bridgeToLocal) -} - -@MainActor -@Observable -final class OnboardingWizardModel { - private(set) var sessionId: String? - private(set) var currentStep: WizardStep? - private(set) var status: String? - private(set) var errorMessage: String? - var isStarting = false - var isSubmitting = false - private var lastStartMode: AppState.ConnectionMode? - private var lastStartWorkspace: String? - private var restartAttempts = 0 - private let maxRestartAttempts = 1 - - var isComplete: Bool { - self.status == "done" - } - - var isRunning: Bool { - self.status == "running" - } - - func reset() { - self.sessionId = nil - self.currentStep = nil - self.status = nil - self.errorMessage = nil - self.isStarting = false - self.isSubmitting = false - self.restartAttempts = 0 - self.lastStartMode = nil - self.lastStartWorkspace = nil - } - - func startIfNeeded(mode: AppState.ConnectionMode, workspace: String? = nil) async { - guard self.sessionId == nil, !self.isStarting else { return } - guard mode == .local else { return } - if self.shouldSkipWizard() { - self.sessionId = nil - self.currentStep = nil - self.status = "done" - self.errorMessage = nil - return - } - self.isStarting = true - self.errorMessage = nil - self.lastStartMode = mode - self.lastStartWorkspace = workspace - defer { self.isStarting = false } - - do { - GatewayProcessManager.shared.setActive(true) - if await GatewayProcessManager.shared.waitForGatewayReady(timeout: 12) == false { - throw NSError( - domain: "Gateway", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "Gateway did not become ready. Check that it is running."]) - } - var params: [String: AnyCodable] = ["mode": AnyCodable("local")] - if let workspace, !workspace.isEmpty { - params["workspace"] = AnyCodable(workspace) - } - let res: WizardStartResult = try await GatewayConnection.shared.requestDecoded( - method: .wizardStart, - params: params) - self.applyStartResult(res) - } catch { - self.status = "error" - self.errorMessage = error.localizedDescription - onboardingWizardLogger.error("start failed: \(error.localizedDescription, privacy: .public)") - } - } - - func submit(step: WizardStep, value: AnyCodable?) async { - guard let sessionId, !self.isSubmitting else { return } - self.isSubmitting = true - self.errorMessage = nil - defer { self.isSubmitting = false } - - do { - var params: [String: AnyCodable] = ["sessionId": AnyCodable(sessionId)] - var answer: [String: AnyCodable] = ["stepId": AnyCodable(step.id)] - if let value { - answer["value"] = value - } - params["answer"] = AnyCodable(answer) - let res: WizardNextResult = try await GatewayConnection.shared.requestDecoded( - method: .wizardNext, - params: params) - self.applyNextResult(res) - } catch { - if self.restartIfSessionLost(error: error) { - return - } - self.status = "error" - self.errorMessage = error.localizedDescription - onboardingWizardLogger.error("submit failed: \(error.localizedDescription, privacy: .public)") - } - } - - func cancelIfRunning() async { - guard let sessionId, self.isRunning else { return } - do { - let res: WizardStatusResult = try await GatewayConnection.shared.requestDecoded( - method: .wizardCancel, - params: ["sessionId": AnyCodable(sessionId)]) - self.applyStatusResult(res) - } catch { - self.status = "error" - self.errorMessage = error.localizedDescription - onboardingWizardLogger.error("cancel failed: \(error.localizedDescription, privacy: .public)") - } - } - - private func applyStartResult(_ res: WizardStartResult) { - self.sessionId = res.sessionid - self.status = wizardStatusString(res.status) ?? (res.done ? "done" : "running") - self.errorMessage = res.error - self.currentStep = decodeWizardStep(res.step) - if self.currentStep == nil, res.step != nil { - onboardingWizardLogger.error("wizard step decode failed") - } - if res.done { self.currentStep = nil } - self.restartAttempts = 0 - } - - private func applyNextResult(_ res: WizardNextResult) { - let status = wizardStatusString(res.status) - self.status = status ?? self.status - self.errorMessage = res.error - self.currentStep = decodeWizardStep(res.step) - if self.currentStep == nil, res.step != nil { - onboardingWizardLogger.error("wizard step decode failed") - } - if res.done { self.currentStep = nil } - if res.done || status == "done" || status == "cancelled" || status == "error" { - self.sessionId = nil - } - } - - private func applyStatusResult(_ res: WizardStatusResult) { - self.status = wizardStatusString(res.status) ?? "unknown" - self.errorMessage = res.error - self.currentStep = nil - self.sessionId = nil - } - - private func restartIfSessionLost(error: Error) -> Bool { - guard let gatewayError = error as? GatewayResponseError else { return false } - guard gatewayError.code == ErrorCode.invalidRequest.rawValue else { return false } - let message = gatewayError.message.lowercased() - guard message.contains("wizard not found") || message.contains("wizard not running") else { return false } - guard let mode = self.lastStartMode, self.restartAttempts < self.maxRestartAttempts else { - return false - } - self.restartAttempts += 1 - self.sessionId = nil - self.currentStep = nil - self.status = nil - self.errorMessage = "Wizard session lost. Restarting…" - Task { await self.startIfNeeded(mode: mode, workspace: self.lastStartWorkspace) } - return true - } - - private func shouldSkipWizard() -> Bool { - let root = OpenClawConfigFile.loadDict() - if let wizard = root["wizard"] as? [String: Any], !wizard.isEmpty { - return true - } - if let gateway = root["gateway"] as? [String: Any], - let auth = gateway["auth"] as? [String: Any] - { - if let mode = auth["mode"] as? String, - !mode.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty - { - return true - } - if let token = auth["token"] as? String, - !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty - { - return true - } - if let password = auth["password"] as? String, - !password.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty - { - return true - } - } - return false - } -} - -struct OnboardingWizardStepView: View { - let step: WizardStep - let isSubmitting: Bool - let onStepSubmit: (AnyCodable?) -> Void - - @State private var textValue: String - @State private var confirmValue: Bool - @State private var selectedIndex: Int - @State private var selectedIndices: Set - - private let optionItems: [WizardOptionItem] - - init(step: WizardStep, isSubmitting: Bool, onSubmit: @escaping (AnyCodable?) -> Void) { - self.step = step - self.isSubmitting = isSubmitting - self.onStepSubmit = onSubmit - let options = parseWizardOptions(step.options).enumerated().map { index, option in - WizardOptionItem(index: index, option: option) - } - self.optionItems = options - let initialText = anyCodableString(step.initialvalue) - let initialConfirm = anyCodableBool(step.initialvalue) - let initialIndex = options.firstIndex(where: { anyCodableEqual($0.option.value, step.initialvalue) }) ?? 0 - let initialMulti = Set( - options.filter { option in - anyCodableArray(step.initialvalue).contains { anyCodableEqual($0, option.option.value) } - }.map(\.index)) - - _textValue = State(initialValue: initialText) - _confirmValue = State(initialValue: initialConfirm) - _selectedIndex = State(initialValue: initialIndex) - _selectedIndices = State(initialValue: initialMulti) - } - - var body: some View { - VStack(alignment: .leading, spacing: 12) { - if let title = step.title, !title.isEmpty { - Text(title) - .font(.title2.weight(.semibold)) - } - if let message = step.message, !message.isEmpty { - Text(message) - .font(.body) - .foregroundStyle(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - - switch wizardStepType(self.step) { - case "note": - EmptyView() - case "text": - self.textField - case "confirm": - Toggle("", isOn: self.$confirmValue) - .toggleStyle(.switch) - case "select": - self.selectOptions - case "multiselect": - self.multiselectOptions - case "progress": - ProgressView() - .controlSize(.small) - case "action": - EmptyView() - default: - Text("Unsupported step type") - .foregroundStyle(.secondary) - } - - Button(action: self.submit) { - Text(wizardStepType(self.step) == "action" ? "Run" : "Continue") - .frame(minWidth: 120) - } - .buttonStyle(.borderedProminent) - .disabled(self.isSubmitting || self.isBlocked) - } - .frame(maxWidth: .infinity, alignment: .leading) - } - - @ViewBuilder - private var textField: some View { - let isSensitive = self.step.sensitive == true - if isSensitive { - SecureField(self.step.placeholder ?? "", text: self.$textValue) - .textFieldStyle(.roundedBorder) - .frame(maxWidth: 360) - } else { - TextField(self.step.placeholder ?? "", text: self.$textValue) - .textFieldStyle(.roundedBorder) - .frame(maxWidth: 360) - } - } - - private var selectOptions: some View { - VStack(alignment: .leading, spacing: 8) { - ForEach(self.optionItems, id: \.index) { item in - self.selectOptionRow(item) - } - } - } - - private var multiselectOptions: some View { - VStack(alignment: .leading, spacing: 8) { - ForEach(self.optionItems, id: \.index) { item in - self.multiselectOptionRow(item) - } - } - } - - private func selectOptionRow(_ item: WizardOptionItem) -> some View { - Button { - self.selectedIndex = item.index - } label: { - HStack(alignment: .top, spacing: 8) { - Image(systemName: self.selectedIndex == item.index ? "largecircle.fill.circle" : "circle") - .foregroundStyle(Color.accentColor) - VStack(alignment: .leading, spacing: 2) { - Text(item.option.label) - .foregroundStyle(.primary) - if let hint = item.option.hint, !hint.isEmpty { - Text(hint) - .font(.caption) - .foregroundStyle(.secondary) - } - } - } - } - .buttonStyle(.plain) - } - - private func multiselectOptionRow(_ item: WizardOptionItem) -> some View { - Toggle(isOn: self.bindingForOption(item)) { - VStack(alignment: .leading, spacing: 2) { - Text(item.option.label) - if let hint = item.option.hint, !hint.isEmpty { - Text(hint) - .font(.caption) - .foregroundStyle(.secondary) - } - } - } - } - - private func bindingForOption(_ item: WizardOptionItem) -> Binding { - Binding(get: { - self.selectedIndices.contains(item.index) - }, set: { newValue in - if newValue { - self.selectedIndices.insert(item.index) - } else { - self.selectedIndices.remove(item.index) - } - }) - } - - private var isBlocked: Bool { - let type = wizardStepType(step) - if type == "select" { return self.optionItems.isEmpty } - if type == "multiselect" { return self.optionItems.isEmpty } - return false - } - - private func submit() { - switch wizardStepType(self.step) { - case "note", "progress": - self.onStepSubmit(nil) - case "text": - self.onStepSubmit(AnyCodable(self.textValue)) - case "confirm": - self.onStepSubmit(AnyCodable(self.confirmValue)) - case "select": - guard self.optionItems.indices.contains(self.selectedIndex) else { - self.onStepSubmit(nil) - return - } - let option = self.optionItems[self.selectedIndex].option - self.onStepSubmit(bridgeToLocal(option.value) ?? AnyCodable(option.label)) - case "multiselect": - let values = self.optionItems - .filter { self.selectedIndices.contains($0.index) } - .map { bridgeToLocal($0.option.value) ?? AnyCodable($0.option.label) } - self.onStepSubmit(AnyCodable(values)) - case "action": - self.onStepSubmit(AnyCodable(true)) - default: - self.onStepSubmit(nil) - } - } -} - -private struct WizardOptionItem: Identifiable { - let index: Int - let option: WizardOption - - var id: Int { - self.index - } -} diff --git a/apps/macos/Sources/OpenClaw/OpenClawConfigFile.swift b/apps/macos/Sources/OpenClaw/OpenClawConfigFile.swift deleted file mode 100644 index 35744baeda5..00000000000 --- a/apps/macos/Sources/OpenClaw/OpenClawConfigFile.swift +++ /dev/null @@ -1,373 +0,0 @@ -import Foundation -import OpenClawProtocol - -enum OpenClawConfigFile { - private static let logger = Logger(subsystem: "ai.openclaw", category: "config") - private static let configAuditFileName = "config-audit.jsonl" - - static func url() -> URL { - OpenClawPaths.configURL - } - - static func stateDirURL() -> URL { - OpenClawPaths.stateDirURL - } - - static func defaultWorkspaceURL() -> URL { - OpenClawPaths.workspaceURL - } - - static func loadDict() -> [String: Any] { - let url = self.url() - guard FileManager().fileExists(atPath: url.path) else { return [:] } - do { - let data = try Data(contentsOf: url) - guard let root = self.parseConfigData(data) else { - self.logger.warning("config JSON root invalid") - return [:] - } - return root - } catch { - self.logger.warning("config read failed: \(error.localizedDescription)") - return [:] - } - } - - static func saveDict(_ dict: [String: Any]) { - // Nix mode disables config writes in production, but tests rely on saving temp configs. - if ProcessInfo.processInfo.isNixMode, !ProcessInfo.processInfo.isRunningTests { return } - let url = self.url() - let previousData = try? Data(contentsOf: url) - let previousRoot = previousData.flatMap { self.parseConfigData($0) } - let previousBytes = previousData?.count - let hadMetaBefore = self.hasMeta(previousRoot) - let gatewayModeBefore = self.gatewayMode(previousRoot) - - var output = dict - self.stampMeta(&output) - - do { - let data = try JSONSerialization.data(withJSONObject: output, options: [.prettyPrinted, .sortedKeys]) - try FileManager().createDirectory( - at: url.deletingLastPathComponent(), - withIntermediateDirectories: true) - try data.write(to: url, options: [.atomic]) - let nextBytes = data.count - let gatewayModeAfter = self.gatewayMode(output) - let suspicious = self.configWriteSuspiciousReasons( - existsBefore: previousData != nil, - previousBytes: previousBytes, - nextBytes: nextBytes, - hadMetaBefore: hadMetaBefore, - gatewayModeBefore: gatewayModeBefore, - gatewayModeAfter: gatewayModeAfter) - if !suspicious.isEmpty { - self.logger.warning("config write anomaly (\(suspicious.joined(separator: ", "))) at \(url.path)") - } - self.appendConfigWriteAudit([ - "result": "success", - "configPath": url.path, - "existsBefore": previousData != nil, - "previousBytes": previousBytes ?? NSNull(), - "nextBytes": nextBytes, - "hasMetaBefore": hadMetaBefore, - "hasMetaAfter": self.hasMeta(output), - "gatewayModeBefore": gatewayModeBefore ?? NSNull(), - "gatewayModeAfter": gatewayModeAfter ?? NSNull(), - "suspicious": suspicious, - ]) - } catch { - self.logger.error("config save failed: \(error.localizedDescription)") - self.appendConfigWriteAudit([ - "result": "failed", - "configPath": url.path, - "existsBefore": previousData != nil, - "previousBytes": previousBytes ?? NSNull(), - "nextBytes": NSNull(), - "hasMetaBefore": hadMetaBefore, - "hasMetaAfter": self.hasMeta(output), - "gatewayModeBefore": gatewayModeBefore ?? NSNull(), - "gatewayModeAfter": self.gatewayMode(output) ?? NSNull(), - "suspicious": [], - "error": error.localizedDescription, - ]) - } - } - - static func loadGatewayDict() -> [String: Any] { - let root = self.loadDict() - return root["gateway"] as? [String: Any] ?? [:] - } - - static func updateGatewayDict(_ mutate: (inout [String: Any]) -> Void) { - var root = self.loadDict() - var gateway = root["gateway"] as? [String: Any] ?? [:] - mutate(&gateway) - if gateway.isEmpty { - root.removeValue(forKey: "gateway") - } else { - root["gateway"] = gateway - } - self.saveDict(root) - } - - static func browserControlEnabled(defaultValue: Bool = true) -> Bool { - let root = self.loadDict() - let browser = root["browser"] as? [String: Any] - return browser?["enabled"] as? Bool ?? defaultValue - } - - static func setBrowserControlEnabled(_ enabled: Bool) { - var root = self.loadDict() - var browser = root["browser"] as? [String: Any] ?? [:] - browser["enabled"] = enabled - root["browser"] = browser - self.saveDict(root) - self.logger.debug("browser control updated enabled=\(enabled)") - } - - static func agentWorkspace() -> String? { - let root = self.loadDict() - let agents = root["agents"] as? [String: Any] - let defaults = agents?["defaults"] as? [String: Any] - return defaults?["workspace"] as? String - } - - static func setAgentWorkspace(_ workspace: String?) { - var root = self.loadDict() - var agents = root["agents"] as? [String: Any] ?? [:] - var defaults = agents["defaults"] as? [String: Any] ?? [:] - let trimmed = workspace?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if trimmed.isEmpty { - defaults.removeValue(forKey: "workspace") - } else { - defaults["workspace"] = trimmed - } - if defaults.isEmpty { - agents.removeValue(forKey: "defaults") - } else { - agents["defaults"] = defaults - } - if agents.isEmpty { - root.removeValue(forKey: "agents") - } else { - root["agents"] = agents - } - self.saveDict(root) - self.logger.debug("agents.defaults.workspace updated set=\(!trimmed.isEmpty)") - } - - static func gatewayPassword() -> String? { - let root = self.loadDict() - guard let gateway = root["gateway"] as? [String: Any], - let remote = gateway["remote"] as? [String: Any] - else { - return nil - } - return remote["password"] as? String - } - - static func gatewayPort() -> Int? { - let root = self.loadDict() - guard let gateway = root["gateway"] as? [String: Any] else { return nil } - if let port = gateway["port"] as? Int, port > 0 { return port } - if let number = gateway["port"] as? NSNumber, number.intValue > 0 { - return number.intValue - } - if let raw = gateway["port"] as? String, - let parsed = Int(raw.trimmingCharacters(in: .whitespacesAndNewlines)), - parsed > 0 - { - return parsed - } - return nil - } - - static func remoteGatewayPort() -> Int? { - guard let url = self.remoteGatewayUrl(), - let port = url.port, - port > 0 - else { return nil } - return port - } - - static func remoteGatewayPort(matchingHost sshHost: String) -> Int? { - let trimmedSshHost = sshHost.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmedSshHost.isEmpty, - let url = self.remoteGatewayUrl(), - let port = url.port, - port > 0, - let urlHost = url.host?.trimmingCharacters(in: .whitespacesAndNewlines), - !urlHost.isEmpty - else { - return nil - } - - let sshKey = Self.hostKey(trimmedSshHost) - let urlKey = Self.hostKey(urlHost) - guard !sshKey.isEmpty, !urlKey.isEmpty, sshKey == urlKey else { return nil } - return port - } - - static func setRemoteGatewayUrl(host: String, port: Int?) { - guard let port, port > 0 else { return } - let trimmedHost = host.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmedHost.isEmpty else { return } - self.updateGatewayDict { gateway in - var remote = gateway["remote"] as? [String: Any] ?? [:] - let existingUrl = (remote["url"] as? String)? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let scheme = URL(string: existingUrl)?.scheme ?? "ws" - remote["url"] = "\(scheme)://\(trimmedHost):\(port)" - gateway["remote"] = remote - } - } - - static func clearRemoteGatewayUrl() { - self.updateGatewayDict { gateway in - guard var remote = gateway["remote"] as? [String: Any] else { return } - guard remote["url"] != nil else { return } - remote.removeValue(forKey: "url") - if remote.isEmpty { - gateway.removeValue(forKey: "remote") - } else { - gateway["remote"] = remote - } - } - } - - private static func remoteGatewayUrl() -> URL? { - let root = self.loadDict() - guard let gateway = root["gateway"] as? [String: Any], - let remote = gateway["remote"] as? [String: Any], - let raw = remote["url"] as? String - else { - return nil - } - let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty, let url = URL(string: trimmed) else { return nil } - return url - } - - private static func hostKey(_ host: String) -> String { - let trimmed = host.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - guard !trimmed.isEmpty else { return "" } - if trimmed.contains(":") { return trimmed } - let digits = CharacterSet(charactersIn: "0123456789.") - if trimmed.rangeOfCharacter(from: digits.inverted) == nil { - return trimmed - } - return trimmed.split(separator: ".").first.map(String.init) ?? trimmed - } - - private static func parseConfigData(_ data: Data) -> [String: Any]? { - if let root = try? JSONSerialization.jsonObject(with: data) as? [String: Any] { - return root - } - let decoder = JSONDecoder() - if #available(macOS 12.0, *) { - decoder.allowsJSON5 = true - } - if let decoded = try? decoder.decode([String: AnyCodable].self, from: data) { - self.logger.notice("config parsed with JSON5 decoder") - return decoded.mapValues { $0.foundationValue } - } - return nil - } - - private static func stampMeta(_ root: inout [String: Any]) { - var meta = root["meta"] as? [String: Any] ?? [:] - let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "macos-app" - meta["lastTouchedVersion"] = version - meta["lastTouchedAt"] = ISO8601DateFormatter().string(from: Date()) - root["meta"] = meta - } - - private static func hasMeta(_ root: [String: Any]?) -> Bool { - guard let root else { return false } - return root["meta"] is [String: Any] - } - - private static func hasMeta(_ root: [String: Any]) -> Bool { - root["meta"] is [String: Any] - } - - private static func gatewayMode(_ root: [String: Any]?) -> String? { - guard let root else { return nil } - return self.gatewayMode(root) - } - - private static func gatewayMode(_ root: [String: Any]) -> String? { - guard let gateway = root["gateway"] as? [String: Any], - let mode = gateway["mode"] as? String - else { return nil } - let trimmed = mode.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed.isEmpty ? nil : trimmed - } - - private static func configWriteSuspiciousReasons( - existsBefore: Bool, - previousBytes: Int?, - nextBytes: Int, - hadMetaBefore: Bool, - gatewayModeBefore: String?, - gatewayModeAfter: String?) -> [String] - { - var reasons: [String] = [] - if !existsBefore { - return reasons - } - if let previousBytes, previousBytes >= 512, nextBytes < max(1, previousBytes / 2) { - reasons.append("size-drop:\(previousBytes)->\(nextBytes)") - } - if !hadMetaBefore { - reasons.append("missing-meta-before-write") - } - if gatewayModeBefore != nil, gatewayModeAfter == nil { - reasons.append("gateway-mode-removed") - } - return reasons - } - - private static func configAuditLogURL() -> URL { - self.stateDirURL() - .appendingPathComponent("logs", isDirectory: true) - .appendingPathComponent(self.configAuditFileName, isDirectory: false) - } - - private static func appendConfigWriteAudit(_ fields: [String: Any]) { - var record: [String: Any] = [ - "ts": ISO8601DateFormatter().string(from: Date()), - "source": "macos-openclaw-config-file", - "event": "config.write", - "pid": ProcessInfo.processInfo.processIdentifier, - "argv": Array(ProcessInfo.processInfo.arguments.prefix(8)), - ] - for (key, value) in fields { - record[key] = value is NSNull ? NSNull() : value - } - guard JSONSerialization.isValidJSONObject(record), - let data = try? JSONSerialization.data(withJSONObject: record) - else { - return - } - var line = Data() - line.append(data) - line.append(0x0A) - let logURL = self.configAuditLogURL() - do { - try FileManager().createDirectory( - at: logURL.deletingLastPathComponent(), - withIntermediateDirectories: true) - if !FileManager().fileExists(atPath: logURL.path) { - FileManager().createFile(atPath: logURL.path, contents: nil) - } - let handle = try FileHandle(forWritingTo: logURL) - defer { try? handle.close() } - try handle.seekToEnd() - try handle.write(contentsOf: line) - } catch { - // best-effort - } - } -} diff --git a/apps/macos/Sources/OpenClaw/OpenClawPaths.swift b/apps/macos/Sources/OpenClaw/OpenClawPaths.swift deleted file mode 100644 index 206031f9aa1..00000000000 --- a/apps/macos/Sources/OpenClaw/OpenClawPaths.swift +++ /dev/null @@ -1,53 +0,0 @@ -import Foundation - -enum OpenClawEnv { - static func path(_ key: String) -> String? { - // Normalize env overrides once so UI + file IO stay consistent. - guard let raw = getenv(key) else { return nil } - let value = String(cString: raw).trimmingCharacters(in: .whitespacesAndNewlines) - guard !value.isEmpty - else { - return nil - } - return value - } -} - -enum OpenClawPaths { - private static let configPathEnv = ["OPENCLAW_CONFIG_PATH"] - private static let stateDirEnv = ["OPENCLAW_STATE_DIR"] - - static var stateDirURL: URL { - for key in self.stateDirEnv { - if let override = OpenClawEnv.path(key) { - return URL(fileURLWithPath: override, isDirectory: true) - } - } - let home = FileManager().homeDirectoryForCurrentUser - return home.appendingPathComponent(".openclaw", isDirectory: true) - } - - private static func resolveConfigCandidate(in dir: URL) -> URL? { - let candidates = [ - dir.appendingPathComponent("openclaw.json"), - ] - return candidates.first(where: { FileManager().fileExists(atPath: $0.path) }) - } - - static var configURL: URL { - for key in self.configPathEnv { - if let override = OpenClawEnv.path(key) { - return URL(fileURLWithPath: override) - } - } - let stateDir = self.stateDirURL - if let existing = self.resolveConfigCandidate(in: stateDir) { - return existing - } - return stateDir.appendingPathComponent("openclaw.json") - } - - static var workspaceURL: URL { - self.stateDirURL.appendingPathComponent("workspace", isDirectory: true) - } -} diff --git a/apps/macos/Sources/OpenClaw/PairingAlertSupport.swift b/apps/macos/Sources/OpenClaw/PairingAlertSupport.swift deleted file mode 100644 index e8e4428bf3f..00000000000 --- a/apps/macos/Sources/OpenClaw/PairingAlertSupport.swift +++ /dev/null @@ -1,46 +0,0 @@ -import AppKit - -final class PairingAlertHostWindow: NSWindow { - override var canBecomeKey: Bool { - true - } - - override var canBecomeMain: Bool { - true - } -} - -@MainActor -enum PairingAlertSupport { - static func endActiveAlert(activeAlert: inout NSAlert?, activeRequestId: inout String?) { - guard let alert = activeAlert else { return } - if let parent = alert.window.sheetParent { - parent.endSheet(alert.window, returnCode: .abort) - } - activeAlert = nil - activeRequestId = nil - } - - static func requireAlertHostWindow(alertHostWindow: inout NSWindow?) -> NSWindow { - if let alertHostWindow { - return alertHostWindow - } - - let window = PairingAlertHostWindow( - contentRect: NSRect(x: 0, y: 0, width: 520, height: 1), - styleMask: [.borderless], - backing: .buffered, - defer: false) - window.title = "" - window.isReleasedWhenClosed = false - window.level = .floating - window.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary] - window.isOpaque = false - window.hasShadow = false - window.backgroundColor = .clear - window.ignoresMouseEvents = true - - alertHostWindow = window - return window - } -} diff --git a/apps/macos/Sources/OpenClaw/PeekabooBridgeHostCoordinator.swift b/apps/macos/Sources/OpenClaw/PeekabooBridgeHostCoordinator.swift deleted file mode 100644 index 9f97650b9f2..00000000000 --- a/apps/macos/Sources/OpenClaw/PeekabooBridgeHostCoordinator.swift +++ /dev/null @@ -1,137 +0,0 @@ -import Foundation -import os -import PeekabooAutomationKit -import PeekabooBridge -import PeekabooFoundation -import Security - -@MainActor -final class PeekabooBridgeHostCoordinator { - static let shared = PeekabooBridgeHostCoordinator() - - private let logger = Logger(subsystem: "ai.openclaw", category: "PeekabooBridge") - - private var host: PeekabooBridgeHost? - private var services: OpenClawPeekabooBridgeServices? - private static var openclawSocketPath: String { - let fileManager = FileManager.default - let base = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first - ?? fileManager.homeDirectoryForCurrentUser.appendingPathComponent("Library/Application Support") - let directory = base.appendingPathComponent("OpenClaw", isDirectory: true) - return directory.appendingPathComponent(PeekabooBridgeConstants.socketName, isDirectory: false).path - } - - func setEnabled(_ enabled: Bool) async { - if enabled { - await self.startIfNeeded() - } else { - await self.stop() - } - } - - func stop() async { - guard let host else { return } - await host.stop() - self.host = nil - self.services = nil - self.logger.info("PeekabooBridge host stopped") - } - - private func startIfNeeded() async { - guard self.host == nil else { return } - - var allowlistedTeamIDs: Set = ["Y5PE65HELJ"] - if let teamID = Self.currentTeamID() { - allowlistedTeamIDs.insert(teamID) - } - let allowlistedBundles: Set = [] - - let services = OpenClawPeekabooBridgeServices() - let server = PeekabooBridgeServer( - services: services, - hostKind: .gui, - allowlistedTeams: allowlistedTeamIDs, - allowlistedBundles: allowlistedBundles) - - let host = PeekabooBridgeHost( - socketPath: Self.openclawSocketPath, - server: server, - allowedTeamIDs: allowlistedTeamIDs, - requestTimeoutSec: 10) - - self.services = services - self.host = host - - await host.start() - self.logger - .info("PeekabooBridge host started at \(Self.openclawSocketPath, privacy: .public)") - } - - private static func currentTeamID() -> String? { - var code: SecCode? - guard SecCodeCopySelf(SecCSFlags(), &code) == errSecSuccess, - let code - else { - return nil - } - - var staticCode: SecStaticCode? - guard SecCodeCopyStaticCode(code, SecCSFlags(), &staticCode) == errSecSuccess, - let staticCode - else { - return nil - } - - var infoCF: CFDictionary? - guard SecCodeCopySigningInformation( - staticCode, - SecCSFlags(rawValue: kSecCSSigningInformation), - &infoCF) == errSecSuccess, - let info = infoCF as? [String: Any] - else { - return nil - } - - return info[kSecCodeInfoTeamIdentifier as String] as? String - } -} - -@MainActor -private final class OpenClawPeekabooBridgeServices: PeekabooBridgeServiceProviding { - let permissions: PermissionsService - let screenCapture: any ScreenCaptureServiceProtocol - let automation: any UIAutomationServiceProtocol - let windows: any WindowManagementServiceProtocol - let applications: any ApplicationServiceProtocol - let menu: any MenuServiceProtocol - let dock: any DockServiceProtocol - let dialogs: any DialogServiceProtocol - let snapshots: any SnapshotManagerProtocol - - init() { - let logging = LoggingService(subsystem: "ai.openclaw.peekaboo") - let feedbackClient: any AutomationFeedbackClient = NoopAutomationFeedbackClient() - - let snapshots = InMemorySnapshotManager(options: .init( - snapshotValidityWindow: 600, - maxSnapshots: 50, - deleteArtifactsOnCleanup: false)) - let applications = ApplicationService(feedbackClient: feedbackClient) - - let screenCapture = ScreenCaptureService(loggingService: logging) - - self.permissions = PermissionsService() - self.snapshots = snapshots - self.applications = applications - self.screenCapture = screenCapture - self.automation = UIAutomationService( - snapshotManager: snapshots, - loggingService: logging, - searchPolicy: .balanced, - feedbackClient: feedbackClient) - self.windows = WindowManagementService(applicationService: applications, feedbackClient: feedbackClient) - self.menu = MenuService(applicationService: applications, feedbackClient: feedbackClient) - self.dock = DockService(feedbackClient: feedbackClient) - self.dialogs = DialogService(feedbackClient: feedbackClient) - } -} diff --git a/apps/macos/Sources/OpenClaw/PermissionManager.swift b/apps/macos/Sources/OpenClaw/PermissionManager.swift deleted file mode 100644 index b5bcd167a46..00000000000 --- a/apps/macos/Sources/OpenClaw/PermissionManager.swift +++ /dev/null @@ -1,506 +0,0 @@ -import AppKit -import ApplicationServices -import AVFoundation -import CoreGraphics -import CoreLocation -import Foundation -import Observation -import OpenClawIPC -import Speech -import UserNotifications - -enum PermissionManager { - static func isLocationAuthorized(status: CLAuthorizationStatus, requireAlways: Bool) -> Bool { - if requireAlways { return status == .authorizedAlways } - switch status { - case .authorizedAlways, .authorizedWhenInUse: - return true - case .authorized: // deprecated, but still shows up on some macOS versions - return true - default: - return false - } - } - - static func ensure(_ caps: [Capability], interactive: Bool) async -> [Capability: Bool] { - var results: [Capability: Bool] = [:] - for cap in caps { - results[cap] = await self.ensureCapability(cap, interactive: interactive) - } - return results - } - - private static func ensureCapability(_ cap: Capability, interactive: Bool) async -> Bool { - switch cap { - case .notifications: - await self.ensureNotifications(interactive: interactive) - case .appleScript: - await self.ensureAppleScript(interactive: interactive) - case .accessibility: - await self.ensureAccessibility(interactive: interactive) - case .screenRecording: - await self.ensureScreenRecording(interactive: interactive) - case .microphone: - await self.ensureMicrophone(interactive: interactive) - case .speechRecognition: - await self.ensureSpeechRecognition(interactive: interactive) - case .camera: - await self.ensureCamera(interactive: interactive) - case .location: - await self.ensureLocation(interactive: interactive) - } - } - - private static func ensureNotifications(interactive: Bool) async -> Bool { - let center = UNUserNotificationCenter.current() - let settings = await center.notificationSettings() - - switch settings.authorizationStatus { - case .authorized, .provisional, .ephemeral: - return true - case .notDetermined: - guard interactive else { return false } - let granted = await (try? center.requestAuthorization(options: [.alert, .sound, .badge])) ?? false - let updated = await center.notificationSettings() - return granted && - (updated.authorizationStatus == .authorized || updated.authorizationStatus == .provisional) - case .denied: - if interactive { - NotificationPermissionHelper.openSettings() - } - return false - @unknown default: - return false - } - } - - private static func ensureAppleScript(interactive: Bool) async -> Bool { - let granted = await MainActor.run { AppleScriptPermission.isAuthorized() } - if interactive, !granted { - await AppleScriptPermission.requestAuthorization() - } - return await MainActor.run { AppleScriptPermission.isAuthorized() } - } - - private static func ensureAccessibility(interactive: Bool) async -> Bool { - let trusted = await MainActor.run { AXIsProcessTrusted() } - if interactive, !trusted { - await MainActor.run { - let opts: NSDictionary = ["AXTrustedCheckOptionPrompt": true] - _ = AXIsProcessTrustedWithOptions(opts) - } - } - return await MainActor.run { AXIsProcessTrusted() } - } - - private static func ensureScreenRecording(interactive: Bool) async -> Bool { - let granted = ScreenRecordingProbe.isAuthorized() - if interactive, !granted { - await ScreenRecordingProbe.requestAuthorization() - } - return ScreenRecordingProbe.isAuthorized() - } - - private static func ensureMicrophone(interactive: Bool) async -> Bool { - let status = AVCaptureDevice.authorizationStatus(for: .audio) - switch status { - case .authorized: - return true - case .notDetermined: - guard interactive else { return false } - return await AVCaptureDevice.requestAccess(for: .audio) - case .denied, .restricted: - if interactive { - MicrophonePermissionHelper.openSettings() - } - return false - @unknown default: - return false - } - } - - private static func ensureSpeechRecognition(interactive: Bool) async -> Bool { - let status = SFSpeechRecognizer.authorizationStatus() - if status == .notDetermined, interactive { - await withUnsafeContinuation { (cont: UnsafeContinuation) in - SFSpeechRecognizer.requestAuthorization { _ in - DispatchQueue.main.async { cont.resume() } - } - } - } - return SFSpeechRecognizer.authorizationStatus() == .authorized - } - - private static func ensureCamera(interactive: Bool) async -> Bool { - let status = AVCaptureDevice.authorizationStatus(for: .video) - switch status { - case .authorized: - return true - case .notDetermined: - guard interactive else { return false } - return await AVCaptureDevice.requestAccess(for: .video) - case .denied, .restricted: - if interactive { - CameraPermissionHelper.openSettings() - } - return false - @unknown default: - return false - } - } - - private static func ensureLocation(interactive: Bool) async -> Bool { - guard CLLocationManager.locationServicesEnabled() else { - if interactive { - await MainActor.run { LocationPermissionHelper.openSettings() } - } - return false - } - let status = CLLocationManager().authorizationStatus - switch status { - case .authorizedAlways, .authorizedWhenInUse, .authorized: - return true - case .notDetermined: - guard interactive else { return false } - let updated = await LocationPermissionRequester.shared.request(always: false) - return self.isLocationAuthorized(status: updated, requireAlways: false) - case .denied, .restricted: - if interactive { - await MainActor.run { LocationPermissionHelper.openSettings() } - } - return false - @unknown default: - return false - } - } - - static func voiceWakePermissionsGranted() -> Bool { - let mic = AVCaptureDevice.authorizationStatus(for: .audio) == .authorized - let speech = SFSpeechRecognizer.authorizationStatus() == .authorized - return mic && speech - } - - static func ensureVoiceWakePermissions(interactive: Bool) async -> Bool { - let results = await self.ensure([.microphone, .speechRecognition], interactive: interactive) - return results[.microphone] == true && results[.speechRecognition] == true - } - - static func status(_ caps: [Capability] = Capability.allCases) async -> [Capability: Bool] { - var results: [Capability: Bool] = [:] - for cap in caps { - switch cap { - case .notifications: - let center = UNUserNotificationCenter.current() - let settings = await center.notificationSettings() - results[cap] = settings.authorizationStatus == .authorized - || settings.authorizationStatus == .provisional - - case .appleScript: - results[cap] = await MainActor.run { AppleScriptPermission.isAuthorized() } - - case .accessibility: - results[cap] = await MainActor.run { AXIsProcessTrusted() } - - case .screenRecording: - if #available(macOS 10.15, *) { - results[cap] = CGPreflightScreenCaptureAccess() - } else { - results[cap] = true - } - - case .microphone: - results[cap] = AVCaptureDevice.authorizationStatus(for: .audio) == .authorized - - case .speechRecognition: - results[cap] = SFSpeechRecognizer.authorizationStatus() == .authorized - - case .camera: - results[cap] = AVCaptureDevice.authorizationStatus(for: .video) == .authorized - - case .location: - let status = CLLocationManager().authorizationStatus - results[cap] = CLLocationManager.locationServicesEnabled() - && self.isLocationAuthorized(status: status, requireAlways: false) - } - } - return results - } -} - -enum NotificationPermissionHelper { - static func openSettings() { - let candidates = [ - "x-apple.systempreferences:com.apple.Notifications-Settings.extension", - "x-apple.systempreferences:com.apple.preference.notifications", - ] - - for candidate in candidates { - if let url = URL(string: candidate), NSWorkspace.shared.open(url) { - return - } - } - } -} - -enum MicrophonePermissionHelper { - static func openSettings() { - let candidates = [ - "x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone", - "x-apple.systempreferences:com.apple.preference.security", - ] - - for candidate in candidates { - if let url = URL(string: candidate), NSWorkspace.shared.open(url) { - return - } - } - } -} - -enum CameraPermissionHelper { - static func openSettings() { - let candidates = [ - "x-apple.systempreferences:com.apple.preference.security?Privacy_Camera", - "x-apple.systempreferences:com.apple.preference.security", - ] - - for candidate in candidates { - if let url = URL(string: candidate), NSWorkspace.shared.open(url) { - return - } - } - } -} - -enum LocationPermissionHelper { - static func openSettings() { - let candidates = [ - "x-apple.systempreferences:com.apple.preference.security?Privacy_LocationServices", - "x-apple.systempreferences:com.apple.preference.security", - ] - - for candidate in candidates { - if let url = URL(string: candidate), NSWorkspace.shared.open(url) { - return - } - } - } -} - -@MainActor -final class LocationPermissionRequester: NSObject, CLLocationManagerDelegate { - static let shared = LocationPermissionRequester() - private let manager = CLLocationManager() - private var continuation: CheckedContinuation? - private var timeoutTask: Task? - - override init() { - super.init() - self.manager.delegate = self - } - - func request(always: Bool) async -> CLAuthorizationStatus { - let current = self.manager.authorizationStatus - if PermissionManager.isLocationAuthorized(status: current, requireAlways: always) { - return current - } - - return await withCheckedContinuation { cont in - self.continuation = cont - self.timeoutTask?.cancel() - self.timeoutTask = Task { [weak self] in - try? await Task.sleep(nanoseconds: 3_000_000_000) - await MainActor.run { [weak self] in - guard let self else { return } - guard self.continuation != nil else { return } - LocationPermissionHelper.openSettings() - self.finish(status: self.manager.authorizationStatus) - } - } - if always { - self.manager.requestAlwaysAuthorization() - } else { - self.manager.requestWhenInUseAuthorization() - } - - // On macOS, requesting an actual fix makes the prompt more reliable. - self.manager.requestLocation() - } - } - - private func finish(status: CLAuthorizationStatus) { - self.timeoutTask?.cancel() - self.timeoutTask = nil - guard let cont = self.continuation else { return } - self.continuation = nil - cont.resume(returning: status) - } - - /// nonisolated for Swift 6 strict concurrency compatibility - nonisolated func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { - let status = manager.authorizationStatus - Task { @MainActor in - self.finish(status: status) - } - } - - /// Legacy callback (still used on some macOS versions / configurations). - nonisolated func locationManager( - _ manager: CLLocationManager, - didChangeAuthorization status: CLAuthorizationStatus) - { - Task { @MainActor in - self.finish(status: status) - } - } - - nonisolated func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { - let status = manager.authorizationStatus - Task { @MainActor in - if status == .denied || status == .restricted { - LocationPermissionHelper.openSettings() - } - self.finish(status: status) - } - } - - nonisolated func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { - let status = manager.authorizationStatus - Task { @MainActor in - self.finish(status: status) - } - } -} - -enum AppleScriptPermission { - private static let logger = Logger(subsystem: "ai.openclaw", category: "AppleScriptPermission") - - /// Sends a benign AppleScript to Terminal to verify Automation permission. - @MainActor - static func isAuthorized() -> Bool { - let script = """ - tell application "Terminal" - return "openclaw-ok" - end tell - """ - - var error: NSDictionary? - let appleScript = NSAppleScript(source: script) - let result = appleScript?.executeAndReturnError(&error) - - if let error, let code = error["NSAppleScriptErrorNumber"] as? Int { - if code == -1743 { // errAEEventWouldRequireUserConsent - Self.logger.debug("AppleScript permission denied (-1743)") - return false - } - Self.logger.debug("AppleScript check failed with code \(code)") - } - - return result != nil - } - - /// Triggers the TCC prompt and opens System Settings → Privacy & Security → Automation. - @MainActor - static func requestAuthorization() async { - _ = self.isAuthorized() // first attempt triggers the dialog if not granted - - // Open the Automation pane to help the user if the prompt was dismissed. - let urlStrings = [ - "x-apple.systempreferences:com.apple.preference.security?Privacy_Automation", - "x-apple.systempreferences:com.apple.preference.security", - ] - - for candidate in urlStrings { - if let url = URL(string: candidate), NSWorkspace.shared.open(url) { - break - } - } - } -} - -@MainActor -@Observable -final class PermissionMonitor { - static let shared = PermissionMonitor() - - private(set) var status: [Capability: Bool] = [:] - - private var monitorTimer: Timer? - private var isChecking = false - private var registrations = 0 - private var lastCheck: Date? - private let minimumCheckInterval: TimeInterval = 0.5 - - func register() { - self.registrations += 1 - if self.registrations == 1 { - self.startMonitoring() - } - } - - func unregister() { - guard self.registrations > 0 else { return } - self.registrations -= 1 - if self.registrations == 0 { - self.stopMonitoring() - } - } - - func refreshNow() async { - await self.checkStatus(force: true) - } - - private func startMonitoring() { - Task { await self.checkStatus(force: true) } - - if ProcessInfo.processInfo.isRunningTests { - return - } - self.monitorTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in - guard let self else { return } - Task { @MainActor in - await self.checkStatus(force: false) - } - } - } - - private func stopMonitoring() { - self.monitorTimer?.invalidate() - self.monitorTimer = nil - self.lastCheck = nil - } - - private func checkStatus(force: Bool) async { - if self.isChecking { return } - let now = Date() - if !force, let lastCheck, now.timeIntervalSince(lastCheck) < self.minimumCheckInterval { - return - } - - self.isChecking = true - - let latest = await PermissionManager.status() - if latest != self.status { - self.status = latest - } - self.lastCheck = Date() - - self.isChecking = false - } -} - -enum ScreenRecordingProbe { - static func isAuthorized() -> Bool { - if #available(macOS 10.15, *) { - return CGPreflightScreenCaptureAccess() - } - return true - } - - @MainActor - static func requestAuthorization() async { - if #available(macOS 10.15, *) { - _ = CGRequestScreenCaptureAccess() - } - } -} diff --git a/apps/macos/Sources/OpenClaw/PermissionsSettings.swift b/apps/macos/Sources/OpenClaw/PermissionsSettings.swift deleted file mode 100644 index de15e5ebb63..00000000000 --- a/apps/macos/Sources/OpenClaw/PermissionsSettings.swift +++ /dev/null @@ -1,229 +0,0 @@ -import CoreLocation -import OpenClawIPC -import OpenClawKit -import SwiftUI - -struct PermissionsSettings: View { - let status: [Capability: Bool] - let refresh: () async -> Void - let showOnboarding: () -> Void - - var body: some View { - VStack(alignment: .leading, spacing: 14) { - SystemRunSettingsView() - - Text("Allow these so OpenClaw can notify and capture when needed.") - .padding(.top, 4) - - PermissionStatusList(status: self.status, refresh: self.refresh) - .padding(.horizontal, 2) - .padding(.vertical, 6) - - LocationAccessSettings() - - Button("Restart onboarding") { self.showOnboarding() } - .buttonStyle(.bordered) - Spacer() - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal, 12) - } -} - -private struct LocationAccessSettings: View { - @AppStorage(locationModeKey) private var locationModeRaw: String = OpenClawLocationMode.off.rawValue - @AppStorage(locationPreciseKey) private var locationPreciseEnabled: Bool = true - @State private var lastLocationModeRaw: String = OpenClawLocationMode.off.rawValue - - var body: some View { - VStack(alignment: .leading, spacing: 6) { - Text("Location Access") - .font(.body) - - Picker("", selection: self.$locationModeRaw) { - Text("Off").tag(OpenClawLocationMode.off.rawValue) - Text("While Using").tag(OpenClawLocationMode.whileUsing.rawValue) - Text("Always").tag(OpenClawLocationMode.always.rawValue) - } - .labelsHidden() - .pickerStyle(.menu) - - Toggle("Precise Location", isOn: self.$locationPreciseEnabled) - .disabled(self.locationMode == .off) - - Text("Always may require System Settings to approve background location.") - .font(.footnote) - .foregroundStyle(.tertiary) - .fixedSize(horizontal: false, vertical: true) - } - .onAppear { - self.lastLocationModeRaw = self.locationModeRaw - } - .onChange(of: self.locationModeRaw) { _, newValue in - let previous = self.lastLocationModeRaw - self.lastLocationModeRaw = newValue - guard let mode = OpenClawLocationMode(rawValue: newValue) else { return } - Task { - let granted = await self.requestLocationAuthorization(mode: mode) - if !granted { - await MainActor.run { - self.locationModeRaw = previous - self.lastLocationModeRaw = previous - } - } - } - } - } - - private var locationMode: OpenClawLocationMode { - OpenClawLocationMode(rawValue: self.locationModeRaw) ?? .off - } - - private func requestLocationAuthorization(mode: OpenClawLocationMode) async -> Bool { - guard mode != .off else { return true } - guard CLLocationManager.locationServicesEnabled() else { - await MainActor.run { LocationPermissionHelper.openSettings() } - return false - } - - let status = CLLocationManager().authorizationStatus - let requireAlways = mode == .always - if PermissionManager.isLocationAuthorized(status: status, requireAlways: requireAlways) { - return true - } - let updated = await LocationPermissionRequester.shared.request(always: requireAlways) - return PermissionManager.isLocationAuthorized(status: updated, requireAlways: requireAlways) - } -} - -struct PermissionStatusList: View { - let status: [Capability: Bool] - let refresh: () async -> Void - - var body: some View { - VStack(alignment: .leading, spacing: 12) { - ForEach(Capability.allCases, id: \.self) { cap in - PermissionRow(capability: cap, status: self.status[cap] ?? false) { - Task { await self.handle(cap) } - } - } - Button { - Task { await self.refresh() } - } label: { - Label("Refresh", systemImage: "arrow.clockwise") - } - .buttonStyle(.bordered) - .controlSize(.small) - .font(.footnote) - .padding(.top, 2) - .help("Refresh status") - } - } - - @MainActor - private func handle(_ cap: Capability) async { - _ = await PermissionManager.ensure([cap], interactive: true) - await self.refresh() - } -} - -struct PermissionRow: View { - let capability: Capability - let status: Bool - let compact: Bool - let action: () -> Void - - init(capability: Capability, status: Bool, compact: Bool = false, action: @escaping () -> Void) { - self.capability = capability - self.status = status - self.compact = compact - self.action = action - } - - var body: some View { - HStack(spacing: self.compact ? 10 : 12) { - ZStack { - Circle().fill(self.status ? Color.green.opacity(0.2) : Color.gray.opacity(0.15)) - .frame(width: self.iconSize, height: self.iconSize) - Image(systemName: self.icon) - .foregroundStyle(self.status ? Color.green : Color.secondary) - } - VStack(alignment: .leading, spacing: 2) { - Text(self.title).font(.body.weight(.semibold)) - Text(self.subtitle).font(.caption).foregroundStyle(.secondary) - } - Spacer() - if self.status { - Label("Granted", systemImage: "checkmark.circle.fill") - .foregroundStyle(.green) - } else { - Button("Grant") { self.action() } - .buttonStyle(.bordered) - } - } - .padding(.vertical, self.compact ? 4 : 6) - } - - private var iconSize: CGFloat { - self.compact ? 28 : 32 - } - - private var title: String { - switch self.capability { - case .appleScript: "Automation (AppleScript)" - case .notifications: "Notifications" - case .accessibility: "Accessibility" - case .screenRecording: "Screen Recording" - case .microphone: "Microphone" - case .speechRecognition: "Speech Recognition" - case .camera: "Camera" - case .location: "Location" - } - } - - private var subtitle: String { - switch self.capability { - case .appleScript: - "Control other apps (e.g. Terminal) for automation actions" - case .notifications: "Show desktop alerts for agent activity" - case .accessibility: "Control UI elements when an action requires it" - case .screenRecording: "Capture the screen for context or screenshots" - case .microphone: "Allow Voice Wake and audio capture" - case .speechRecognition: "Transcribe Voice Wake trigger phrases on-device" - case .camera: "Capture photos and video from the camera" - case .location: "Share location when requested by the agent" - } - } - - private var icon: String { - switch self.capability { - case .appleScript: "applescript" - case .notifications: "bell" - case .accessibility: "hand.raised" - case .screenRecording: "display" - case .microphone: "mic" - case .speechRecognition: "waveform" - case .camera: "camera" - case .location: "location" - } - } -} - -#if DEBUG -struct PermissionsSettings_Previews: PreviewProvider { - static var previews: some View { - PermissionsSettings( - status: [ - .appleScript: true, - .notifications: true, - .accessibility: false, - .screenRecording: false, - .microphone: true, - .speechRecognition: false, - ], - refresh: {}, - showOnboarding: {}) - .frame(width: SettingsTab.windowWidth, height: SettingsTab.windowHeight) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/PointingHandCursor.swift b/apps/macos/Sources/OpenClaw/PointingHandCursor.swift deleted file mode 100644 index ceb6fb6f81d..00000000000 --- a/apps/macos/Sources/OpenClaw/PointingHandCursor.swift +++ /dev/null @@ -1,30 +0,0 @@ -import AppKit -import SwiftUI - -private struct PointingHandCursorModifier: ViewModifier { - @State private var isHovering = false - - func body(content: Content) -> some View { - content - .onHover { hovering in - guard hovering != self.isHovering else { return } - self.isHovering = hovering - if hovering { - NSCursor.pointingHand.push() - } else { - NSCursor.pop() - } - } - .onDisappear { - guard self.isHovering else { return } - self.isHovering = false - NSCursor.pop() - } - } -} - -extension View { - func pointingHandCursor() -> some View { - self.modifier(PointingHandCursorModifier()) - } -} diff --git a/apps/macos/Sources/OpenClaw/PortGuardian.swift b/apps/macos/Sources/OpenClaw/PortGuardian.swift deleted file mode 100644 index 7ab7e8def3f..00000000000 --- a/apps/macos/Sources/OpenClaw/PortGuardian.swift +++ /dev/null @@ -1,422 +0,0 @@ -import Foundation -import OSLog -#if canImport(Darwin) -import Darwin -#endif - -actor PortGuardian { - static let shared = PortGuardian() - - struct Record: Codable { - let port: Int - let pid: Int32 - let command: String - let mode: String - let timestamp: TimeInterval - } - - struct Descriptor: Sendable { - let pid: Int32 - let command: String - let executablePath: String? - } - - private var records: [Record] = [] - private let logger = Logger(subsystem: "ai.openclaw", category: "portguard") - private nonisolated static let appSupportDir: URL = { - let base = FileManager().urls(for: .applicationSupportDirectory, in: .userDomainMask).first! - return base.appendingPathComponent("OpenClaw", isDirectory: true) - }() - - private nonisolated static var recordPath: URL { - self.appSupportDir.appendingPathComponent("port-guard.json", isDirectory: false) - } - - init() { - self.records = Self.loadRecords(from: Self.recordPath) - } - - func sweep(mode: AppState.ConnectionMode) async { - self.logger.info("port sweep starting (mode=\(mode.rawValue, privacy: .public))") - guard mode != .unconfigured else { - self.logger.info("port sweep skipped (mode=unconfigured)") - return - } - let ports = [GatewayEnvironment.gatewayPort()] - for port in ports { - let listeners = await self.listeners(on: port) - guard !listeners.isEmpty else { continue } - for listener in listeners { - if self.isExpected(listener, port: port, mode: mode) { - let message = """ - port \(port) already served by expected \(listener.command) - (pid \(listener.pid)) — keeping - """ - self.logger.info("\(message, privacy: .public)") - continue - } - let killed = await self.kill(listener.pid) - if killed { - let message = """ - port \(port) was held by \(listener.command) - (pid \(listener.pid)); terminated - """ - self.logger.error("\(message, privacy: .public)") - } else { - self.logger.error("failed to terminate pid \(listener.pid) on port \(port, privacy: .public)") - } - } - } - self.logger.info("port sweep done") - } - - func record(port: Int, pid: Int32, command: String, mode: AppState.ConnectionMode) async { - try? FileManager().createDirectory(at: Self.appSupportDir, withIntermediateDirectories: true) - self.records.removeAll { $0.pid == pid } - self.records.append( - Record( - port: port, - pid: pid, - command: command, - mode: mode.rawValue, - timestamp: Date().timeIntervalSince1970)) - self.save() - } - - func removeRecord(pid: Int32) { - let before = self.records.count - self.records.removeAll { $0.pid == pid } - if self.records.count != before { - self.save() - } - } - - struct PortReport: Identifiable { - enum Status { - case ok(String) - case missing(String) - case interference(String, offenders: [ReportListener]) - } - - let port: Int - let expected: String - let status: Status - let listeners: [ReportListener] - - var id: Int { - self.port - } - - var offenders: [ReportListener] { - if case let .interference(_, offenders) = self.status { return offenders } - return [] - } - - var summary: String { - switch self.status { - case let .ok(text): text - case let .missing(text): text - case let .interference(text, _): text - } - } - } - - func describe(port: Int) async -> Descriptor? { - guard let listener = await self.listeners(on: port).first else { return nil } - let path = Self.executablePath(for: listener.pid) - return Descriptor(pid: listener.pid, command: listener.command, executablePath: path) - } - - // MARK: - Internals - - private struct Listener { - let pid: Int32 - let command: String - let fullCommand: String - let user: String? - } - - struct ReportListener: Identifiable { - let pid: Int32 - let command: String - let fullCommand: String - let user: String? - let expected: Bool - - var id: Int32 { - self.pid - } - } - - func diagnose(mode: AppState.ConnectionMode) async -> [PortReport] { - if mode == .unconfigured { - return [] - } - let ports = [GatewayEnvironment.gatewayPort()] - var reports: [PortReport] = [] - - for port in ports { - let listeners = await self.listeners(on: port) - let tunnelHealthy = await self.probeGatewayHealthIfNeeded( - port: port, - mode: mode, - listeners: listeners) - reports.append(Self.buildReport( - port: port, - listeners: listeners, - mode: mode, - tunnelHealthy: tunnelHealthy)) - } - - return reports - } - - func probeGatewayHealth(port: Int, timeout: TimeInterval = 2.0) async -> Bool { - let url = URL(string: "http://127.0.0.1:\(port)/")! - let config = URLSessionConfiguration.ephemeral - config.timeoutIntervalForRequest = timeout - config.timeoutIntervalForResource = timeout - let session = URLSession(configuration: config) - var request = URLRequest(url: url) - request.cachePolicy = .reloadIgnoringLocalCacheData - request.timeoutInterval = timeout - do { - let (_, response) = try await session.data(for: request) - return response is HTTPURLResponse - } catch { - return false - } - } - - func isListening(port: Int, pid: Int32? = nil) async -> Bool { - let listeners = await self.listeners(on: port) - if let pid { - return listeners.contains(where: { $0.pid == pid }) - } - return !listeners.isEmpty - } - - private func listeners(on port: Int) async -> [Listener] { - let res = await ShellExecutor.run( - command: ["lsof", "-nP", "-iTCP:\(port)", "-sTCP:LISTEN", "-Fpcn"], - cwd: nil, - env: nil, - timeout: 5) - guard res.ok, let data = res.payload, !data.isEmpty else { return [] } - let text = String(data: data, encoding: .utf8) ?? "" - return Self.parseListeners(from: text) - } - - private static func readFullCommand(pid: Int32) -> String? { - let proc = Process() - proc.executableURL = URL(fileURLWithPath: "/bin/ps") - proc.arguments = ["-p", "\(pid)", "-o", "command="] - let pipe = Pipe() - proc.standardOutput = pipe - proc.standardError = Pipe() - do { - let data = try proc.runAndReadToEnd(from: pipe) - guard !data.isEmpty else { return nil } - return String(data: data, encoding: .utf8)? - .trimmingCharacters(in: .whitespacesAndNewlines) - } catch { - return nil - } - } - - private static func parseListeners(from text: String) -> [Listener] { - var listeners: [Listener] = [] - var currentPid: Int32? - var currentCmd: String? - var currentUser: String? - - func flush() { - if let pid = currentPid, let cmd = currentCmd { - let full = Self.readFullCommand(pid: pid) ?? cmd - listeners.append(Listener(pid: pid, command: cmd, fullCommand: full, user: currentUser)) - } - currentPid = nil - currentCmd = nil - currentUser = nil - } - - for line in text.split(separator: "\n") { - guard let prefix = line.first else { continue } - let value = String(line.dropFirst()) - switch prefix { - case "p": - flush() - currentPid = Int32(value) ?? 0 - case "c": - currentCmd = value - case "u": - currentUser = value - default: - continue - } - } - flush() - return listeners - } - - private static func buildReport( - port: Int, - listeners: [Listener], - mode: AppState.ConnectionMode, - tunnelHealthy: Bool?) -> PortReport - { - let expectedDesc: String - let okPredicate: (Listener) -> Bool - let expectedCommands = ["node", "openclaw", "tsx", "pnpm", "bun"] - - switch mode { - case .remote: - expectedDesc = "SSH tunnel to remote gateway" - okPredicate = { $0.command.lowercased().contains("ssh") } - case .local: - expectedDesc = "Gateway websocket (node/tsx)" - okPredicate = { listener in - let c = listener.command.lowercased() - return expectedCommands.contains { c.contains($0) } - } - case .unconfigured: - expectedDesc = "Gateway not configured" - okPredicate = { _ in false } - } - - if listeners.isEmpty { - let text = "Nothing is listening on \(port) (\(expectedDesc))." - return .init(port: port, expected: expectedDesc, status: .missing(text), listeners: []) - } - - let tunnelUnhealthy = - mode == .remote && port == GatewayEnvironment.gatewayPort() && tunnelHealthy == false - let reportListeners = listeners.map { listener in - var expected = okPredicate(listener) - if tunnelUnhealthy, expected { expected = false } - return ReportListener( - pid: listener.pid, - command: listener.command, - fullCommand: listener.fullCommand, - user: listener.user, - expected: expected) - } - - let offenders = reportListeners.filter { !$0.expected } - if tunnelUnhealthy { - let list = listeners.map { "\($0.command) (\($0.pid))" }.joined(separator: ", ") - let reason = "Port \(port) is served by \(list), but the SSH tunnel is unhealthy." - return .init( - port: port, - expected: expectedDesc, - status: .interference(reason, offenders: offenders), - listeners: reportListeners) - } - if offenders.isEmpty { - let list = listeners.map { "\($0.command) (\($0.pid))" }.joined(separator: ", ") - let okText = "Port \(port) is served by \(list)." - return .init( - port: port, - expected: expectedDesc, - status: .ok(okText), - listeners: reportListeners) - } - - let list = offenders.map { "\($0.command) (\($0.pid))" }.joined(separator: ", ") - let reason = "Port \(port) is held by \(list), expected \(expectedDesc)." - return .init( - port: port, - expected: expectedDesc, - status: .interference(reason, offenders: offenders), - listeners: reportListeners) - } - - private static func executablePath(for pid: Int32) -> String? { - #if canImport(Darwin) - var buffer = [CChar](repeating: 0, count: Int(PATH_MAX)) - let length = proc_pidpath(pid, &buffer, UInt32(buffer.count)) - guard length > 0 else { return nil } - // Drop trailing null and decode as UTF-8. - let trimmed = buffer.prefix { $0 != 0 } - let bytes = trimmed.map { UInt8(bitPattern: $0) } - return String(bytes: bytes, encoding: .utf8) - #else - return nil - #endif - } - - private func kill(_ pid: Int32) async -> Bool { - let term = await ShellExecutor.run(command: ["kill", "-TERM", "\(pid)"], cwd: nil, env: nil, timeout: 2) - if term.ok { return true } - let sigkill = await ShellExecutor.run(command: ["kill", "-KILL", "\(pid)"], cwd: nil, env: nil, timeout: 2) - return sigkill.ok - } - - private func isExpected(_ listener: Listener, port: Int, mode: AppState.ConnectionMode) -> Bool { - let cmd = listener.command.lowercased() - let full = listener.fullCommand.lowercased() - switch mode { - case .remote: - // Remote mode expects an SSH tunnel for the gateway WebSocket port. - if port == GatewayEnvironment.gatewayPort() { return cmd.contains("ssh") } - return false - case .local: - // The gateway daemon may listen as `openclaw` or as its runtime (`node`, `bun`, etc). - if full.contains("gateway-daemon") { return true } - // If args are unavailable, treat a CLI listener as expected. - if cmd.contains("openclaw"), full == cmd { return true } - return false - case .unconfigured: - return false - } - } - - private func probeGatewayHealthIfNeeded( - port: Int, - mode: AppState.ConnectionMode, - listeners: [Listener]) async -> Bool? - { - guard mode == .remote, port == GatewayEnvironment.gatewayPort(), !listeners.isEmpty else { return nil } - let hasSsh = listeners.contains { $0.command.lowercased().contains("ssh") } - guard hasSsh else { return nil } - return await self.probeGatewayHealth(port: port) - } - - private static func loadRecords(from url: URL) -> [Record] { - guard let data = try? Data(contentsOf: url), - let decoded = try? JSONDecoder().decode([Record].self, from: data) - else { return [] } - return decoded - } - - private func save() { - guard let data = try? JSONEncoder().encode(self.records) else { return } - try? data.write(to: Self.recordPath, options: [.atomic]) - } -} - -#if DEBUG -extension PortGuardian { - static func _testParseListeners(_ text: String) -> [( - pid: Int32, - command: String, - fullCommand: String, - user: String?)] - { - self.parseListeners(from: text).map { ($0.pid, $0.command, $0.fullCommand, $0.user) } - } - - static func _testBuildReport( - port: Int, - mode: AppState.ConnectionMode, - listeners: [(pid: Int32, command: String, fullCommand: String, user: String?)]) -> PortReport - { - let mapped = listeners.map { Listener( - pid: $0.pid, - command: $0.command, - fullCommand: $0.fullCommand, - user: $0.user) } - return Self.buildReport(port: port, listeners: mapped, mode: mode, tunnelHealthy: nil) - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/PresenceReporter.swift b/apps/macos/Sources/OpenClaw/PresenceReporter.swift deleted file mode 100644 index 2e7a1d4c472..00000000000 --- a/apps/macos/Sources/OpenClaw/PresenceReporter.swift +++ /dev/null @@ -1,114 +0,0 @@ -import Cocoa -import Foundation -import OSLog - -@MainActor -final class PresenceReporter { - static let shared = PresenceReporter() - - private let logger = Logger(subsystem: "ai.openclaw", category: "presence") - private var task: Task? - private let interval: TimeInterval = 180 // a few minutes - private let instanceId: String = InstanceIdentity.instanceId - - func start() { - guard self.task == nil else { return } - self.task = Task.detached { [weak self] in - guard let self else { return } - await self.push(reason: "launch") - while !Task.isCancelled { - try? await Task.sleep(nanoseconds: UInt64(self.interval * 1_000_000_000)) - await self.push(reason: "periodic") - } - } - } - - func stop() { - self.task?.cancel() - self.task = nil - } - - @Sendable - private func push(reason: String) async { - let mode = await MainActor.run { AppStateStore.shared.connectionMode.rawValue } - let host = InstanceIdentity.displayName - let ip = SystemPresenceInfo.primaryIPv4Address() ?? "ip-unknown" - let version = Self.appVersionString() - let platform = Self.platformString() - let lastInput = SystemPresenceInfo.lastInputSeconds() - let text = Self.composePresenceSummary(mode: mode, reason: reason) - var params: [String: AnyHashable] = [ - "instanceId": AnyHashable(self.instanceId), - "host": AnyHashable(host), - "ip": AnyHashable(ip), - "mode": AnyHashable(mode), - "version": AnyHashable(version), - "platform": AnyHashable(platform), - "deviceFamily": AnyHashable("Mac"), - "reason": AnyHashable(reason), - ] - if let model = InstanceIdentity.modelIdentifier { params["modelIdentifier"] = AnyHashable(model) } - if let lastInput { params["lastInputSeconds"] = AnyHashable(lastInput) } - do { - try await ControlChannel.shared.sendSystemEvent(text, params: params) - } catch { - self.logger.error("presence send failed: \(error.localizedDescription, privacy: .public)") - } - } - - /// Fire an immediate presence beacon (e.g., right after connecting). - func sendImmediate(reason: String = "connect") { - Task { await self.push(reason: reason) } - } - - private static func composePresenceSummary(mode: String, reason: String) -> String { - let host = InstanceIdentity.displayName - let ip = SystemPresenceInfo.primaryIPv4Address() ?? "ip-unknown" - let version = Self.appVersionString() - let lastInput = SystemPresenceInfo.lastInputSeconds() - let lastLabel = lastInput.map { "last input \($0)s ago" } ?? "last input unknown" - return "Node: \(host) (\(ip)) · app \(version) · \(lastLabel) · mode \(mode) · reason \(reason)" - } - - private static func appVersionString() -> String { - let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "dev" - if let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String { - let trimmed = build.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmed.isEmpty, trimmed != version { - return "\(version) (\(trimmed))" - } - } - return version - } - - private static func platformString() -> String { - let v = ProcessInfo.processInfo.operatingSystemVersion - return "macos \(v.majorVersion).\(v.minorVersion).\(v.patchVersion)" - } - - // (SystemPresenceInfo) last input + primary IPv4. -} - -#if DEBUG -extension PresenceReporter { - static func _testComposePresenceSummary(mode: String, reason: String) -> String { - self.composePresenceSummary(mode: mode, reason: reason) - } - - static func _testAppVersionString() -> String { - self.appVersionString() - } - - static func _testPlatformString() -> String { - self.platformString() - } - - static func _testLastInputSeconds() -> Int? { - SystemPresenceInfo.lastInputSeconds() - } - - static func _testPrimaryIPv4Address() -> String? { - SystemPresenceInfo.primaryIPv4Address() - } -} -#endif diff --git a/apps/macos/Sources/OpenClaw/Process+PipeRead.swift b/apps/macos/Sources/OpenClaw/Process+PipeRead.swift deleted file mode 100644 index 7c0f7fe0ca3..00000000000 --- a/apps/macos/Sources/OpenClaw/Process+PipeRead.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation - -extension Process { - /// Runs the process and drains the given pipe before waiting to avoid blocking on full buffers. - func runAndReadToEnd(from pipe: Pipe) throws -> Data { - try self.run() - let data = pipe.fileHandleForReading.readToEndSafely() - self.waitUntilExit() - return data - } -} diff --git a/apps/macos/Sources/OpenClaw/ProcessInfo+OpenClaw.swift b/apps/macos/Sources/OpenClaw/ProcessInfo+OpenClaw.swift deleted file mode 100644 index a219f495336..00000000000 --- a/apps/macos/Sources/OpenClaw/ProcessInfo+OpenClaw.swift +++ /dev/null @@ -1,48 +0,0 @@ -import Foundation - -extension ProcessInfo { - var isPreview: Bool { - guard let raw = getenv("XCODE_RUNNING_FOR_PREVIEWS") else { return false } - return String(cString: raw) == "1" - } - - /// Nix deployments may write defaults into a stable suite (`ai.openclaw.mac`) even if the shipped - /// app bundle identifier changes (and therefore `UserDefaults.standard` domain changes). - static func resolveNixMode( - environment: [String: String], - standard: UserDefaults, - stableSuite: UserDefaults?, - isAppBundle: Bool) -> Bool - { - if environment["OPENCLAW_NIX_MODE"] == "1" { return true } - if standard.bool(forKey: "openclaw.nixMode") { return true } - - // Only consult the stable suite when running as a .app bundle. - // This avoids local developer machines accidentally influencing unit tests. - if isAppBundle, let stableSuite, stableSuite.bool(forKey: "openclaw.nixMode") { return true } - - return false - } - - var isNixMode: Bool { - let isAppBundle = Bundle.main.bundleURL.pathExtension == "app" - let stableSuite = UserDefaults(suiteName: launchdLabel) - return Self.resolveNixMode( - environment: self.environment, - standard: .standard, - stableSuite: stableSuite, - isAppBundle: isAppBundle) - } - - var isRunningTests: Bool { - // SwiftPM tests load one or more `.xctest` bundles. With Swift Testing, `Bundle.main` is not - // guaranteed to be the `.xctest` bundle, so check all loaded bundles. - if Bundle.allBundles.contains(where: { $0.bundleURL.pathExtension == "xctest" }) { return true } - if Bundle.main.bundleURL.pathExtension == "xctest" { return true } - - // Backwards-compatible fallbacks for runners that still set XCTest env vars. - return self.environment["XCTestConfigurationFilePath"] != nil - || self.environment["XCTestBundlePath"] != nil - || self.environment["XCTestSessionIdentifier"] != nil - } -} diff --git a/apps/macos/Sources/OpenClaw/RemotePortTunnel.swift b/apps/macos/Sources/OpenClaw/RemotePortTunnel.swift deleted file mode 100644 index 6502d2ad916..00000000000 --- a/apps/macos/Sources/OpenClaw/RemotePortTunnel.swift +++ /dev/null @@ -1,317 +0,0 @@ -import Foundation -import Network -import OSLog -#if canImport(Darwin) -import Darwin -#endif - -/// Port forwarding tunnel for remote mode. -/// -/// Uses `ssh -N -L` to forward the remote gateway ports to localhost. -final class RemotePortTunnel { - private static let logger = Logger(subsystem: "ai.openclaw", category: "remote.tunnel") - - let process: Process - let localPort: UInt16? - private let stderrHandle: FileHandle? - - private init(process: Process, localPort: UInt16?, stderrHandle: FileHandle?) { - self.process = process - self.localPort = localPort - self.stderrHandle = stderrHandle - } - - deinit { - Self.cleanupStderr(self.stderrHandle) - let pid = self.process.processIdentifier - self.process.terminate() - Task { await PortGuardian.shared.removeRecord(pid: pid) } - } - - func terminate() { - Self.cleanupStderr(self.stderrHandle) - let pid = self.process.processIdentifier - if self.process.isRunning { - self.process.terminate() - self.process.waitUntilExit() - } - Task { await PortGuardian.shared.removeRecord(pid: pid) } - } - - static func create( - remotePort: Int, - preferredLocalPort: UInt16? = nil, - allowRemoteUrlOverride: Bool = true, - allowRandomLocalPort: Bool = true) async throws -> RemotePortTunnel - { - let settings = CommandResolver.connectionSettings() - guard settings.mode == .remote, let parsed = CommandResolver.parseSSHTarget(settings.target) else { - throw NSError( - domain: "RemotePortTunnel", - code: 3, - userInfo: [NSLocalizedDescriptionKey: "Remote mode is not configured"]) - } - - let localPort = try await Self.findPort( - preferred: preferredLocalPort, - allowRandom: allowRandomLocalPort) - let sshHost = parsed.host.trimmingCharacters(in: .whitespacesAndNewlines) - let remotePortOverride = - allowRemoteUrlOverride && remotePort == GatewayEnvironment.gatewayPort() - ? Self.resolveRemotePortOverride(for: sshHost) - : nil - let resolvedRemotePort = remotePortOverride ?? remotePort - if let override = remotePortOverride { - Self.logger.info( - "ssh tunnel remote port override " + - "host=\(sshHost, privacy: .public) port=\(override, privacy: .public)") - } else { - Self.logger.debug( - "ssh tunnel using default remote port " + - "host=\(sshHost, privacy: .public) port=\(remotePort, privacy: .public)") - } - let options: [String] = [ - "-o", "BatchMode=yes", - "-o", "ExitOnForwardFailure=yes", - "-o", "StrictHostKeyChecking=accept-new", - "-o", "UpdateHostKeys=yes", - "-o", "ServerAliveInterval=15", - "-o", "ServerAliveCountMax=3", - "-o", "TCPKeepAlive=yes", - "-N", - "-L", "\(localPort):127.0.0.1:\(resolvedRemotePort)", - ] - let identity = settings.identity.trimmingCharacters(in: .whitespacesAndNewlines) - let args = CommandResolver.sshArguments( - target: parsed, - identity: identity, - options: options) - - let process = Process() - process.executableURL = URL(fileURLWithPath: "/usr/bin/ssh") - process.arguments = args - - let pipe = Pipe() - process.standardError = pipe - let stderrHandle = pipe.fileHandleForReading - - // Consume stderr so ssh cannot block if it logs. - stderrHandle.readabilityHandler = { handle in - let data = handle.readSafely(upToCount: 64 * 1024) - guard !data.isEmpty else { - // EOF (or read failure): stop monitoring to avoid spinning on a closed pipe. - Self.cleanupStderr(handle) - return - } - guard let line = String(data: data, encoding: .utf8)? - .trimmingCharacters(in: .whitespacesAndNewlines), - !line.isEmpty - else { return } - Self.logger.error("ssh tunnel stderr: \(line, privacy: .public)") - } - process.terminationHandler = { _ in - Self.cleanupStderr(stderrHandle) - } - - try process.run() - - // If ssh exits immediately (e.g. local port already in use), surface stderr and ensure we stop monitoring. - try? await Task.sleep(nanoseconds: 150_000_000) // 150ms - if !process.isRunning { - let stderr = Self.drainStderr(stderrHandle) - let msg = stderr.isEmpty ? "ssh tunnel exited immediately" : "ssh tunnel failed: \(stderr)" - throw NSError(domain: "RemotePortTunnel", code: 4, userInfo: [NSLocalizedDescriptionKey: msg]) - } - - // Track tunnel so we can clean up stale listeners on restart. - Task { - await PortGuardian.shared.record( - port: Int(localPort), - pid: process.processIdentifier, - command: process.executableURL?.path ?? "ssh", - mode: CommandResolver.connectionSettings().mode) - } - - return RemotePortTunnel(process: process, localPort: localPort, stderrHandle: stderrHandle) - } - - private static func resolveRemotePortOverride(for sshHost: String) -> Int? { - let root = OpenClawConfigFile.loadDict() - guard let gateway = root["gateway"] as? [String: Any], - let remote = gateway["remote"] as? [String: Any], - let urlRaw = remote["url"] as? String - else { - return nil - } - let trimmed = urlRaw.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty, let url = URL(string: trimmed), let port = url.port else { - return nil - } - guard let host = url.host?.trimmingCharacters(in: .whitespacesAndNewlines), - !host.isEmpty - else { - return nil - } - let sshKey = Self.hostKey(sshHost) - let urlKey = Self.hostKey(host) - guard !sshKey.isEmpty, !urlKey.isEmpty else { return nil } - guard sshKey == urlKey else { - Self.logger.debug( - "remote url host mismatch sshHost=\(sshHost, privacy: .public) urlHost=\(host, privacy: .public)") - return nil - } - return port - } - - private static func hostKey(_ host: String) -> String { - let trimmed = host.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - guard !trimmed.isEmpty else { return "" } - if trimmed.contains(":") { return trimmed } - let digits = CharacterSet(charactersIn: "0123456789.") - if trimmed.rangeOfCharacter(from: digits.inverted) == nil { - return trimmed - } - return trimmed.split(separator: ".").first.map(String.init) ?? trimmed - } - - private static func findPort(preferred: UInt16?, allowRandom: Bool) async throws -> UInt16 { - if let preferred, self.portIsFree(preferred) { return preferred } - if let preferred, !allowRandom { - throw NSError( - domain: "RemotePortTunnel", - code: 5, - userInfo: [ - NSLocalizedDescriptionKey: "Local port \(preferred) is unavailable", - ]) - } - - return try await withCheckedThrowingContinuation { cont in - let queue = DispatchQueue(label: "ai.openclaw.remote.tunnel.port", qos: .utility) - do { - let listener = try NWListener(using: .tcp, on: .any) - listener.newConnectionHandler = { connection in connection.cancel() } - listener.stateUpdateHandler = { state in - switch state { - case .ready: - if let port = listener.port?.rawValue { - listener.stateUpdateHandler = nil - listener.cancel() - cont.resume(returning: port) - } - case let .failed(error): - listener.stateUpdateHandler = nil - listener.cancel() - cont.resume(throwing: error) - default: - break - } - } - listener.start(queue: queue) - } catch { - cont.resume(throwing: error) - } - } - } - - private static func portIsFree(_ port: UInt16) -> Bool { - #if canImport(Darwin) - // NWListener can succeed even when only one address family is held. Mirror what ssh needs by checking - // both 127.0.0.1 and ::1 for availability. - return self.canBindIPv4(port) && self.canBindIPv6(port) - #else - do { - let listener = try NWListener(using: .tcp, on: NWEndpoint.Port(rawValue: port)!) - listener.cancel() - return true - } catch { - return false - } - #endif - } - - #if canImport(Darwin) - private static func canBindIPv4(_ port: UInt16) -> Bool { - let fd = socket(AF_INET, SOCK_STREAM, 0) - guard fd >= 0 else { return false } - defer { _ = Darwin.close(fd) } - - var one: Int32 = 1 - _ = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, socklen_t(MemoryLayout.size(ofValue: one))) - - var addr = sockaddr_in() - addr.sin_len = UInt8(MemoryLayout.size) - addr.sin_family = sa_family_t(AF_INET) - addr.sin_port = port.bigEndian - addr.sin_addr = in_addr(s_addr: inet_addr("127.0.0.1")) - - let result = withUnsafePointer(to: &addr) { ptr in - ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) { sa in - Darwin.bind(fd, sa, socklen_t(MemoryLayout.size)) - } - } - return result == 0 - } - - private static func canBindIPv6(_ port: UInt16) -> Bool { - let fd = socket(AF_INET6, SOCK_STREAM, 0) - guard fd >= 0 else { return false } - defer { _ = Darwin.close(fd) } - - var one: Int32 = 1 - _ = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, socklen_t(MemoryLayout.size(ofValue: one))) - - var addr = sockaddr_in6() - addr.sin6_len = UInt8(MemoryLayout.size) - addr.sin6_family = sa_family_t(AF_INET6) - addr.sin6_port = port.bigEndian - var loopback = in6_addr() - _ = withUnsafeMutablePointer(to: &loopback) { ptr in - inet_pton(AF_INET6, "::1", ptr) - } - addr.sin6_addr = loopback - - let result = withUnsafePointer(to: &addr) { ptr in - ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) { sa in - Darwin.bind(fd, sa, socklen_t(MemoryLayout.size)) - } - } - return result == 0 - } - #endif - - private static func cleanupStderr(_ handle: FileHandle?) { - guard let handle else { return } - Self.cleanupStderr(handle) - } - - private static func cleanupStderr(_ handle: FileHandle) { - if handle.readabilityHandler != nil { - handle.readabilityHandler = nil - } - try? handle.close() - } - - private static func drainStderr(_ handle: FileHandle) -> String { - handle.readabilityHandler = nil - defer { try? handle.close() } - - do { - let data = try handle.readToEnd() ?? Data() - return String(data: data, encoding: .utf8)? - .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - } catch { - self.logger.debug("Failed to drain ssh stderr: \(error, privacy: .public)") - return "" - } - } - - #if SWIFT_PACKAGE - static func _testPortIsFree(_ port: UInt16) -> Bool { - self.portIsFree(port) - } - - static func _testDrainStderr(_ handle: FileHandle) -> String { - self.drainStderr(handle) - } - #endif -} diff --git a/apps/macos/Sources/OpenClaw/RemoteTunnelManager.swift b/apps/macos/Sources/OpenClaw/RemoteTunnelManager.swift deleted file mode 100644 index e8f0da6f091..00000000000 --- a/apps/macos/Sources/OpenClaw/RemoteTunnelManager.swift +++ /dev/null @@ -1,122 +0,0 @@ -import Foundation -import OSLog - -/// Manages the SSH tunnel that forwards the remote gateway/control port to localhost. -actor RemoteTunnelManager { - static let shared = RemoteTunnelManager() - - private let logger = Logger(subsystem: "ai.openclaw", category: "remote-tunnel") - private var controlTunnel: RemotePortTunnel? - private var restartInFlight = false - private var lastRestartAt: Date? - private let restartBackoffSeconds: TimeInterval = 2.0 - - func controlTunnelPortIfRunning() async -> UInt16? { - if self.restartInFlight { - self.logger.info("control tunnel restart in flight; skipping reuse check") - return nil - } - if let tunnel = self.controlTunnel, - tunnel.process.isRunning, - let local = tunnel.localPort - { - let pid = tunnel.process.processIdentifier - if await PortGuardian.shared.isListening(port: Int(local), pid: pid) { - self.logger.info("reusing active SSH tunnel localPort=\(local, privacy: .public)") - return local - } - self.logger.error( - "active SSH tunnel on port \(local, privacy: .public) is not listening; restarting") - await self.beginRestart() - tunnel.terminate() - self.controlTunnel = nil - } - // If a previous OpenClaw 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)), - self.isSshProcess(desc) - { - self.logger.info( - "reusing existing SSH tunnel listener " + - "localPort=\(desiredPort, privacy: .public) " + - "pid=\(desc.pid, privacy: .public)") - return desiredPort - } - return nil - } - - /// Ensure an SSH tunnel is running for the gateway control port. - /// Returns the local forwarded port (usually the configured gateway port). - func ensureControlTunnel() async throws -> UInt16 { - let settings = CommandResolver.connectionSettings() - guard settings.mode == .remote else { - throw NSError( - domain: "RemoteTunnel", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "Remote mode is not enabled"]) - } - - let identitySet = !settings.identity.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty - self.logger.info( - "ensure SSH tunnel target=\(settings.target, privacy: .public) " + - "identitySet=\(identitySet, privacy: .public)") - - if let local = await self.controlTunnelPortIfRunning() { return local } - await self.waitForRestartBackoffIfNeeded() - - let desiredPort = UInt16(GatewayEnvironment.gatewayPort()) - let tunnel = try await RemotePortTunnel.create( - remotePort: GatewayEnvironment.gatewayPort(), - preferredLocalPort: desiredPort, - allowRandomLocalPort: false) - self.controlTunnel = tunnel - self.endRestart() - let resolvedPort = tunnel.localPort ?? desiredPort - self.logger.info("ssh tunnel ready localPort=\(resolvedPort, privacy: .public)") - return tunnel.localPort ?? desiredPort - } - - func stopAll() { - self.controlTunnel?.terminate() - self.controlTunnel = nil - } - - private func isSshProcess(_ desc: PortGuardian.Descriptor) -> Bool { - let cmd = desc.command.lowercased() - if cmd.contains("ssh") { return true } - if let path = desc.executablePath?.lowercased(), path.contains("/ssh") { return true } - return false - } - - private func beginRestart() async { - guard !self.restartInFlight else { return } - self.restartInFlight = true - self.lastRestartAt = Date() - self.logger.info("control tunnel restart started") - Task { [weak self] in - guard let self else { return } - try? await Task.sleep(nanoseconds: UInt64(self.restartBackoffSeconds * 1_000_000_000)) - await self.endRestart() - } - } - - private func endRestart() { - if self.restartInFlight { - self.restartInFlight = false - self.logger.info("control tunnel restart finished") - } - } - - private func waitForRestartBackoffIfNeeded() async { - guard let last = self.lastRestartAt else { return } - let elapsed = Date().timeIntervalSince(last) - let remaining = self.restartBackoffSeconds - elapsed - guard remaining > 0 else { return } - self.logger.info( - "control tunnel restart backoff \(remaining, privacy: .public)s") - try? await Task.sleep(nanoseconds: UInt64(remaining * 1_000_000_000)) - } - - // Keep tunnel reuse lightweight; restart only when the listener disappears. -} diff --git a/apps/macos/Sources/OpenClaw/Resources/DeviceModels/LICENSE.apple-device-identifiers.txt b/apps/macos/Sources/OpenClaw/Resources/DeviceModels/LICENSE.apple-device-identifiers.txt deleted file mode 100644 index d1b9e4b3ce5..00000000000 --- a/apps/macos/Sources/OpenClaw/Resources/DeviceModels/LICENSE.apple-device-identifiers.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2021 Kyle Seongwoo Jun - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/apps/macos/Sources/OpenClaw/Resources/DeviceModels/NOTICE.md b/apps/macos/Sources/OpenClaw/Resources/DeviceModels/NOTICE.md deleted file mode 100644 index 664e78d7bc9..00000000000 --- a/apps/macos/Sources/OpenClaw/Resources/DeviceModels/NOTICE.md +++ /dev/null @@ -1,9 +0,0 @@ -# Apple device identifier mappings - -This directory includes model identifier → human-readable name mappings derived from the open-source project: - -- `kyle-seongwoo-jun/apple-device-identifiers` - - iOS mapping pinned to commit `8e7388b29da046183f5d976eb74dbb2f2acda955` - - macOS mapping pinned to commit `98ca75324f7a88c1649eb5edfc266ef47b7b8193` - -See `LICENSE.apple-device-identifiers.txt` for license terms. diff --git a/apps/macos/Sources/OpenClaw/Resources/DeviceModels/ios-device-identifiers.json b/apps/macos/Sources/OpenClaw/Resources/DeviceModels/ios-device-identifiers.json deleted file mode 100644 index 76caa5452ea..00000000000 --- a/apps/macos/Sources/OpenClaw/Resources/DeviceModels/ios-device-identifiers.json +++ /dev/null @@ -1,176 +0,0 @@ -{ - "i386": "iPhone Simulator", - "x86_64": "iPhone Simulator", - "arm64": "iPhone Simulator", - "iPhone1,1": "iPhone", - "iPhone1,2": "iPhone 3G", - "iPhone2,1": "iPhone 3GS", - "iPhone3,1": "iPhone 4", - "iPhone3,2": "iPhone 4", - "iPhone3,3": "iPhone 4", - "iPhone4,1": "iPhone 4s", - "iPhone5,1": "iPhone 5", - "iPhone5,2": "iPhone 5", - "iPhone5,3": "iPhone 5c", - "iPhone5,4": "iPhone 5c", - "iPhone6,1": "iPhone 5s", - "iPhone6,2": "iPhone 5s", - "iPhone7,1": "iPhone 6 Plus", - "iPhone7,2": "iPhone 6", - "iPhone8,1": "iPhone 6s", - "iPhone8,2": "iPhone 6s Plus", - "iPhone8,4": "iPhone SE (1st generation)", - "iPhone9,1": "iPhone 7", - "iPhone9,2": "iPhone 7 Plus", - "iPhone9,3": "iPhone 7", - "iPhone9,4": "iPhone 7 Plus", - "iPhone10,1": "iPhone 8", - "iPhone10,2": "iPhone 8 Plus", - "iPhone10,3": "iPhone X", - "iPhone10,4": "iPhone 8", - "iPhone10,5": "iPhone 8 Plus", - "iPhone10,6": "iPhone X", - "iPhone11,2": "iPhone XS", - "iPhone11,4": "iPhone XS Max", - "iPhone11,6": "iPhone XS Max", - "iPhone11,8": "iPhone XR", - "iPhone12,1": "iPhone 11", - "iPhone12,3": "iPhone 11 Pro", - "iPhone12,5": "iPhone 11 Pro Max", - "iPhone12,8": "iPhone SE (2nd generation)", - "iPhone13,1": "iPhone 12 mini", - "iPhone13,2": "iPhone 12", - "iPhone13,3": "iPhone 12 Pro", - "iPhone13,4": "iPhone 12 Pro Max", - "iPhone14,2": "iPhone 13 Pro", - "iPhone14,3": "iPhone 13 Pro Max", - "iPhone14,4": "iPhone 13 mini", - "iPhone14,5": "iPhone 13", - "iPhone14,6": "iPhone SE (3rd generation)", - "iPhone14,7": "iPhone 14", - "iPhone14,8": "iPhone 14 Plus", - "iPhone15,2": "iPhone 14 Pro", - "iPhone15,3": "iPhone 14 Pro Max", - "iPhone15,4": "iPhone 15", - "iPhone15,5": "iPhone 15 Plus", - "iPhone16,1": "iPhone 15 Pro", - "iPhone16,2": "iPhone 15 Pro Max", - "iPhone17,1": "iPhone 16 Pro", - "iPhone17,2": "iPhone 16 Pro Max", - "iPhone17,3": "iPhone 16", - "iPhone17,4": "iPhone 16 Plus", - "iPhone17,5": "iPhone 16e", - "iPhone18,1": "iPhone 17 Pro", - "iPhone18,2": "iPhone 17 Pro Max", - "iPhone18,3": "iPhone 17", - "iPhone18,4": "iPhone Air", - "iPad1,1": "iPad", - "iPad1,2": "iPad", - "iPad2,1": "iPad 2", - "iPad2,2": "iPad 2", - "iPad2,3": "iPad 2", - "iPad2,4": "iPad 2", - "iPad2,5": "iPad mini", - "iPad2,6": "iPad mini", - "iPad2,7": "iPad mini", - "iPad3,1": "iPad (3rd generation)", - "iPad3,2": "iPad (3rd generation)", - "iPad3,3": "iPad (3rd generation)", - "iPad3,4": "iPad (4th generation)", - "iPad3,5": "iPad (4th generation)", - "iPad3,6": "iPad (4th generation)", - "iPad4,1": "iPad Air", - "iPad4,2": "iPad Air", - "iPad4,3": "iPad Air", - "iPad4,4": "iPad mini 2", - "iPad4,5": "iPad mini 2", - "iPad4,6": "iPad mini 2", - "iPad4,7": "iPad mini 3", - "iPad4,8": "iPad mini 3", - "iPad4,9": "iPad mini 3", - "iPad5,1": "iPad mini 4", - "iPad5,2": "iPad mini 4", - "iPad5,3": "iPad Air 2", - "iPad5,4": "iPad Air 2", - "iPad6,3": "iPad Pro (9.7-inch)", - "iPad6,4": "iPad Pro (9.7-inch)", - "iPad6,7": "iPad Pro (12.9-inch)", - "iPad6,8": "iPad Pro (12.9-inch)", - "iPad6,11": "iPad (5th generation)", - "iPad6,12": "iPad (5th generation)", - "iPad7,1": "iPad Pro (12.9-inch) (2nd generation)", - "iPad7,2": "iPad Pro (12.9-inch) (2nd generation)", - "iPad7,3": "iPad Pro (10.5-inch)", - "iPad7,4": "iPad Pro (10.5-inch)", - "iPad7,5": "iPad (6th generation)", - "iPad7,6": "iPad (6th generation)", - "iPad7,11": "iPad (7th generation)", - "iPad7,12": "iPad (7th generation)", - "iPad8,1": "iPad Pro (11-inch)", - "iPad8,2": "iPad Pro (11-inch)", - "iPad8,3": "iPad Pro (11-inch)", - "iPad8,4": "iPad Pro (11-inch)", - "iPad8,5": "iPad Pro (12.9-inch) (3rd generation)", - "iPad8,6": "iPad Pro (12.9-inch) (3rd generation)", - "iPad8,7": "iPad Pro (12.9-inch) (3rd generation)", - "iPad8,8": "iPad Pro (12.9-inch) (3rd generation)", - "iPad8,9": "iPad Pro (11-inch) (2nd generation)", - "iPad8,10": "iPad Pro (11-inch) (2nd generation)", - "iPad8,11": "iPad Pro (12.9-inch) (4th generation)", - "iPad8,12": "iPad Pro (12.9-inch) (4th generation)", - "iPad11,1": "iPad mini (5th generation)", - "iPad11,2": "iPad mini (5th generation)", - "iPad11,3": "iPad Air (3rd generation)", - "iPad11,4": "iPad Air (3rd generation)", - "iPad11,6": "iPad (8th generation)", - "iPad11,7": "iPad (8th generation)", - "iPad12,1": "iPad (9th generation)", - "iPad12,2": "iPad (9th generation)", - "iPad13,1": "iPad Air (4th generation)", - "iPad13,2": "iPad Air (4th generation)", - "iPad13,4": "iPad Pro (11-inch) (3rd generation)", - "iPad13,5": "iPad Pro (11-inch) (3rd generation)", - "iPad13,6": "iPad Pro (11-inch) (3rd generation)", - "iPad13,7": "iPad Pro (11-inch) (3rd generation)", - "iPad13,8": "iPad Pro (12.9-inch) (5th generation)", - "iPad13,9": "iPad Pro (12.9-inch) (5th generation)", - "iPad13,10": "iPad Pro (12.9-inch) (5th generation)", - "iPad13,11": "iPad Pro (12.9-inch) (5th generation)", - "iPad13,16": "iPad Air (5th generation)", - "iPad13,17": "iPad Air (5th generation)", - "iPad13,18": "iPad (10th generation)", - "iPad13,19": "iPad (10th generation)", - "iPad14,1": "iPad mini (6th generation)", - "iPad14,2": "iPad mini (6th generation)", - "iPad14,3": "iPad Pro (11-inch) (4th generation)", - "iPad14,4": "iPad Pro (11-inch) (4th generation)", - "iPad14,5": "iPad Pro (12.9-inch) (6th generation)", - "iPad14,6": "iPad Pro (12.9-inch) (6th generation)", - "iPad14,8": "iPad Air 11-inch (M2)", - "iPad14,9": "iPad Air 11-inch (M2)", - "iPad14,10": "iPad Air 13-inch (M2)", - "iPad14,11": "iPad Air 13-inch (M2)", - "iPad15,3": "iPad Air 11-inch (M3)", - "iPad15,4": "iPad Air 11-inch (M3)", - "iPad15,5": "iPad Air 13-inch (M3)", - "iPad15,6": "iPad Air 13-inch (M3)", - "iPad15,7": "iPad (A16)", - "iPad15,8": "iPad (A16)", - "iPad16,1": "iPad mini (A17 Pro)", - "iPad16,2": "iPad mini (A17 Pro)", - "iPad16,3": "iPad Pro 11-inch (M4)", - "iPad16,4": "iPad Pro 11-inch (M4)", - "iPad16,5": "iPad Pro 13-inch (M4)", - "iPad16,6": "iPad Pro 13-inch (M4)", - "iPad17,1": "iPad Pro 11-inch (M5)", - "iPad17,2": "iPad Pro 11-inch (M5)", - "iPad17,3": "iPad Pro 13-inch (M5)", - "iPad17,4": "iPad Pro 13-inch (M5)", - "iPod1,1": "iPod touch", - "iPod2,1": "iPod touch (2nd generation)", - "iPod3,1": "iPod touch (3rd generation)", - "iPod4,1": "iPod touch (4th generation)", - "iPod5,1": "iPod touch (5th generation)", - "iPod7,1": "iPod touch (6th generation)", - "iPod9,1": "iPod touch (7th generation)" -} diff --git a/apps/macos/Sources/OpenClaw/Resources/DeviceModels/mac-device-identifiers.json b/apps/macos/Sources/OpenClaw/Resources/DeviceModels/mac-device-identifiers.json deleted file mode 100644 index 03d5a5eccb1..00000000000 --- a/apps/macos/Sources/OpenClaw/Resources/DeviceModels/mac-device-identifiers.json +++ /dev/null @@ -1,214 +0,0 @@ -{ - "iMac9,1": [ - "iMac (20-inch, Early 2009)", - "iMac (24-inch, Early 2009)" - ], - "iMac10,1": [ - "iMac (21.5-inch, Late 2009)", - "iMac (27-inch, Late 2009)" - ], - "iMac11,2": "iMac (21.5-inch, Mid 2010)", - "iMac11,3": "iMac (27-inch, Mid 2010)", - "iMac12,1": "iMac (21.5-inch, Mid 2011)", - "iMac12,2": "iMac (27-inch, Mid 2011)", - "iMac13,1": "iMac (21.5-inch, Late 2012)", - "iMac13,2": "iMac (27-inch, Late 2012)", - "iMac14,1": "iMac (21.5-inch, Late 2013)", - "iMac14,2": "iMac (27-inch, Late 2013)", - "iMac14,4": "iMac (21.5-inch, Mid 2014)", - "iMac15,1": [ - "iMac (Retina 5K, 27-inch, Late 2014)", - "iMac (Retina 5K, 27-inch, Mid 2015)" - ], - "iMac16,1": "iMac (21.5-inch, Late 2015)", - "iMac16,2": "iMac (Retina 4K, 21.5-inch, Late 2015)", - "iMac17,1": "iMac (Retina 5K, 27-inch, Late 2015)", - "iMac18,1": "iMac (21.5-inch, 2017)", - "iMac18,2": "iMac (Retina 4K, 21.5-inch, 2017)", - "iMac18,3": "iMac (Retina 5K, 27-inch, 2017)", - "iMac19,1": "iMac (Retina 5K, 27-inch, 2019)", - "iMac19,2": "iMac (Retina 4K, 21.5-inch, 2019)", - "iMac20,1": "iMac (Retina 5K, 27-inch, 2020)", - "iMac20,2": "iMac (Retina 5K, 27-inch, 2020)", - "iMac21,1": "iMac (24-inch, M1, 2021)", - "iMac21,2": "iMac (24-inch, M1, 2021)", - "iMacPro1,1": "iMac Pro (2017)", - "Mac13,1": "Mac Studio (2022)", - "Mac13,2": "Mac Studio (2022)", - "Mac14,2": "MacBook Air (M2, 2022)", - "Mac14,3": "Mac mini (2023)", - "Mac14,5": "MacBook Pro (14-inch, 2023)", - "Mac14,6": "MacBook Pro (16-inch, 2023)", - "Mac14,7": "MacBook Pro (13-inch, M2, 2022)", - "Mac14,8": [ - "Mac Pro (2023)", - "Mac Pro (Rack, 2023)" - ], - "Mac14,9": "MacBook Pro (14-inch, 2023)", - "Mac14,10": "MacBook Pro (16-inch, 2023)", - "Mac14,12": "Mac mini (2023)", - "Mac14,13": "Mac Studio (2023)", - "Mac14,14": "Mac Studio (2023)", - "Mac14,15": "MacBook Air (15-inch, M2, 2023)", - "Mac15,3": "MacBook Pro (14-inch, Nov 2023)", - "Mac15,4": "iMac (24-inch, 2023, Two ports)", - "Mac15,5": "iMac (24-inch, 2023, Four ports)", - "Mac15,6": "MacBook Pro (14-inch, Nov 2023)", - "Mac15,7": "MacBook Pro (16-inch, Nov 2023)", - "Mac15,8": "MacBook Pro (14-inch, Nov 2023)", - "Mac15,9": "MacBook Pro (16-inch, Nov 2023)", - "Mac15,10": "MacBook Pro (14-inch, Nov 2023)", - "Mac15,11": "MacBook Pro (16-inch, Nov 2023)", - "Mac15,12": "MacBook Air (13-inch, M3, 2024)", - "Mac15,13": "MacBook Air (15-inch, M3, 2024)", - "Mac15,14": "Mac Studio (2025)", - "Mac16,1": "MacBook Pro (14-inch, 2024)", - "Mac16,2": "iMac (24-inch, 2024, Two ports)", - "Mac16,3": "iMac (24-inch, 2024, Four ports)", - "Mac16,5": "MacBook Pro (16-inch, 2024)", - "Mac16,6": "MacBook Pro (14-inch, 2024)", - "Mac16,7": "MacBook Pro (16-inch, 2024)", - "Mac16,8": "MacBook Pro (14-inch, 2024)", - "Mac16,9": "Mac Studio (2025)", - "Mac16,10": "Mac mini (2024)", - "Mac16,11": "Mac mini (2024)", - "Mac16,12": "MacBook Air (13-inch, M4, 2025)", - "Mac16,13": "MacBook Air (15-inch, M4, 2025)", - "Mac17,2": "MacBook Pro (14-inch, M5)", - "MacBook5,2": [ - "MacBook (13-inch, Early 2009)", - "MacBook (13-inch, Mid 2009)" - ], - "MacBook6,1": "MacBook (13-inch, Late 2009)", - "MacBook7,1": "MacBook (13-inch, Mid 2010)", - "MacBook8,1": "MacBook (Retina, 12-inch, Early 2015)", - "MacBook9,1": "MacBook (Retina, 12-inch, Early 2016)", - "MacBook10,1": "MacBook (Retina, 12-inch, 2017)", - "MacBookAir2,1": "MacBook Air (Mid 2009)", - "MacBookAir3,1": "MacBook Air (11-inch, Late 2010)", - "MacBookAir3,2": "MacBook Air (13-inch, Late 2010)", - "MacBookAir4,1": "MacBook Air (11-inch, Mid 2011)", - "MacBookAir4,2": "MacBook Air (13-inch, Mid 2011)", - "MacBookAir5,1": "MacBook Air (11-inch, Mid 2012)", - "MacBookAir5,2": "MacBook Air (13-inch, Mid 2012)", - "MacBookAir6,1": [ - "MacBook Air (11-inch, Early 2014)", - "MacBook Air (11-inch, Mid 2013)" - ], - "MacBookAir6,2": [ - "MacBook Air (13-inch, Early 2014)", - "MacBook Air (13-inch, Mid 2013)" - ], - "MacBookAir7,1": "MacBook Air (11-inch, Early 2015)", - "MacBookAir7,2": [ - "MacBook Air (13-inch, 2017)", - "MacBook Air (13-inch, Early 2015)" - ], - "MacBookAir8,1": "MacBook Air (Retina, 13-inch, 2018)", - "MacBookAir8,2": "MacBook Air (Retina, 13-inch, 2019)", - "MacBookAir9,1": "MacBook Air (Retina, 13-inch, 2020)", - "MacBookAir10,1": "MacBook Air (M1, 2020)", - "MacBookPro4,1": [ - "MacBook Pro (15-inch, Early 2008)", - "MacBook Pro (17-inch, Early 2008)" - ], - "MacBookPro5,1": "MacBook Pro (15-inch, Late 2008)", - "MacBookPro5,2": [ - "MacBook Pro (17-inch, Early 2009)", - "MacBook Pro (17-inch, Mid 2009)" - ], - "MacBookPro5,3": [ - "MacBook Pro (15-inch, 2.53GHz, Mid 2009)", - "MacBook Pro (15-inch, Mid 2009)" - ], - "MacBookPro5,5": "MacBook Pro (13-inch, Mid 2009)", - "MacBookPro6,1": "MacBook Pro (17-inch, Mid 2010)", - "MacBookPro6,2": "MacBook Pro (15-inch, Mid 2010)", - "MacBookPro7,1": "MacBook Pro (13-inch, Mid 2010)", - "MacBookPro8,1": [ - "MacBook Pro (13-inch, Early 2011)", - "MacBook Pro (13-inch, Late 2011)" - ], - "MacBookPro8,2": [ - "MacBook Pro (15-inch, Early 2011)", - "MacBook Pro (15-inch, Late 2011)" - ], - "MacBookPro8,3": [ - "MacBook Pro (17-inch, Early 2011)", - "MacBook Pro (17-inch, Late 2011)" - ], - "MacBookPro9,1": "MacBook Pro (15-inch, Mid 2012)", - "MacBookPro9,2": "MacBook Pro (13-inch, Mid 2012)", - "MacBookPro10,1": [ - "MacBook Pro (Retina, 15-inch, Early 2013)", - "MacBook Pro (Retina, 15-inch, Mid 2012)" - ], - "MacBookPro10,2": [ - "MacBook Pro (Retina, 13-inch, Early 2013)", - "MacBook Pro (Retina, 13-inch, Late 2012)" - ], - "MacBookPro11,1": [ - "MacBook Pro (Retina, 13-inch, Late 2013)", - "MacBook Pro (Retina, 13-inch, Mid 2014)" - ], - "MacBookPro11,2": [ - "MacBook Pro (Retina, 15-inch, Late 2013)", - "MacBook Pro (Retina, 15-inch, Mid 2014)" - ], - "MacBookPro11,3": [ - "MacBook Pro (Retina, 15-inch, Late 2013)", - "MacBook Pro (Retina, 15-inch, Mid 2014)" - ], - "MacBookPro11,4": "MacBook Pro (Retina, 15-inch, Mid 2015)", - "MacBookPro11,5": "MacBook Pro (Retina, 15-inch, Mid 2015)", - "MacBookPro12,1": "MacBook Pro (Retina, 13-inch, Early 2015)", - "MacBookPro13,1": "MacBook Pro (13-inch, 2016, Two Thunderbolt 3 ports)", - "MacBookPro13,2": "MacBook Pro (13-inch, 2016, Four Thunderbolt 3 ports)", - "MacBookPro13,3": "MacBook Pro (15-inch, 2016)", - "MacBookPro14,1": "MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)", - "MacBookPro14,2": "MacBook Pro (13-inch, 2017, Four Thunderbolt 3 ports)", - "MacBookPro14,3": "MacBook Pro (15-inch, 2017)", - "MacBookPro15,1": [ - "MacBook Pro (15-inch, 2018)", - "MacBook Pro (15-inch, 2019)" - ], - "MacBookPro15,2": [ - "MacBook Pro (13-inch, 2018, Four Thunderbolt 3 ports)", - "MacBook Pro (13-inch, 2019, Four Thunderbolt 3 ports)" - ], - "MacBookPro15,3": "MacBook Pro (15-inch, 2019)", - "MacBookPro15,4": "MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)", - "MacBookPro16,1": "MacBook Pro (16-inch, 2019)", - "MacBookPro16,2": "MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)", - "MacBookPro16,3": "MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)", - "MacBookPro16,4": "MacBook Pro (16-inch, 2019)", - "MacBookPro17,1": "MacBook Pro (13-inch, M1, 2020)", - "MacBookPro18,1": "MacBook Pro (16-inch, 2021)", - "MacBookPro18,2": "MacBook Pro (16-inch, 2021)", - "MacBookPro18,3": "MacBook Pro (14-inch, 2021)", - "MacBookPro18,4": "MacBook Pro (14-inch, 2021)", - "Macmini3,1": [ - "Mac mini (Early 2009)", - "Mac mini (Late 2009)" - ], - "Macmini4,1": "Mac mini (Mid 2010)", - "Macmini5,1": "Mac mini (Mid 2011)", - "Macmini5,2": "Mac mini (Mid 2011)", - "Macmini6,1": "Mac mini (Late 2012)", - "Macmini6,2": "Mac mini (Late 2012)", - "Macmini7,1": "Mac mini (Late 2014)", - "Macmini8,1": "Mac mini (2018)", - "Macmini9,1": "Mac mini (M1, 2020)", - "MacPro4,1": "Mac Pro (Early 2009)", - "MacPro5,1": [ - "Mac Pro (Mid 2010)", - "Mac Pro (Mid 2012)", - "Mac Pro Server (Mid 2010)", - "Mac Pro Server (Mid 2012)" - ], - "MacPro6,1": "Mac Pro (Late 2013)", - "MacPro7,1": [ - "Mac Pro (2019)", - "Mac Pro (Rack, 2019)" - ] -} diff --git a/apps/macos/Sources/OpenClaw/Resources/Info.plist b/apps/macos/Sources/OpenClaw/Resources/Info.plist deleted file mode 100644 index e7ca1ad5487..00000000000 --- a/apps/macos/Sources/OpenClaw/Resources/Info.plist +++ /dev/null @@ -1,79 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - OpenClaw - CFBundleIdentifier - ai.openclaw.mac - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - OpenClaw - CFBundlePackageType - APPL - CFBundleShortVersionString - 2026.2.21 - CFBundleVersion - 202602210 - CFBundleIconFile - OpenClaw - CFBundleURLTypes - - - CFBundleURLName - ai.openclaw.mac.deeplink - CFBundleURLSchemes - - openclaw - - - - LSMinimumSystemVersion - 15.0 - LSUIElement - - - OpenClawBuildTimestamp - - OpenClawGitCommit - - - NSUserNotificationUsageDescription - OpenClaw needs notification permission to show alerts for agent actions. - NSScreenCaptureDescription - OpenClaw captures the screen when the agent needs screenshots for context. - NSCameraUsageDescription - OpenClaw can capture photos or short video clips when requested by the agent. - NSLocationUsageDescription - OpenClaw can share your location when requested by the agent. - NSLocationWhenInUseUsageDescription - OpenClaw can share your location when requested by the agent. - NSLocationAlwaysAndWhenInUseUsageDescription - OpenClaw can share your location when requested by the agent. - NSMicrophoneUsageDescription - OpenClaw needs the mic for Voice Wake tests and agent audio capture. - NSSpeechRecognitionUsageDescription - OpenClaw uses speech recognition to detect your Voice Wake trigger phrase. - NSAppleEventsUsageDescription - OpenClaw needs Automation (AppleScript) permission to drive Terminal and other apps for agent actions. - - NSAppTransportSecurity - - NSAllowsArbitraryLoadsInWebContent - - NSExceptionDomains - - 100.100.100.100 - - NSExceptionAllowsInsecureHTTPLoads - - NSIncludesSubdomains - - - - - - diff --git a/apps/macos/Sources/OpenClaw/Resources/OpenClaw.icns b/apps/macos/Sources/OpenClaw/Resources/OpenClaw.icns deleted file mode 100644 index f317728e1c94d129490165b26bba23815226e25d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1884490 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%0ANvc8^LG6_5!sWHB1WG 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 z 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

    P+01*^#ouVN@GC)9ovN`bvBDsh?`+=O`Cq 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�`Oz7;bB@C!w0y*E#HVj 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 LAjt%AC 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 z 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

  1. Hnpv`clSBBo)6kcQ`+XCZvD!wI$z>& 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
  2. Phlx#T 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 z zb1<^#kIKI;_@UxYufKZ!_Ws@S=NSNKyifh)pZxIW2=>_g0TOuJ0Qdt0)1AM3XXj_W z@%p82W+m!>RLX|}lT1zKb@(b3s#z1IfxGiwJ+oRsH0~leqjDJ+va~W0g=A1+2zPww zB|R>-VVKtJ-u$ZK>;;=O2+-MKT7a^^t$!2%hUqQ5HFS>^yK{9`ES?`AZh3Mfpc*dn zTIjRjjETsGwAs4$)~!8^$UP7Y~Jg8VQ8LzlY5z z05X(L6i*9VqaOtBiqA0l$qDpC+!R!J0ionkU$_GStnSfGxJf5&IGl1k>sPk94*G<} zmCS#5Xw2FYJRmbK}y2BG-)dHwk#bN*EFIpxm=0A2m`{;@mn&kd0O^ZA$V|4irN@%#6e zKu_V{-}kZWFnsRQCv!(fpP=IWRp<0Aoc0iUZ<|^cDWSA;ro2i5HH&}BZZdEQ(S?6r zRMKjt6shtlC9XO$j8g(9T-1}^v4td+cR~7D%0c=peLCgVI#!O~=Q`p8R*!q3(E`&A zR>~Hz^uV!NpI3L6oYq^zOX{*tukgv-{}Rvk2r=d1u+rApH_ZV(Avcc=Zpdv zv}ouoHh%U9cv(S!#Qz3T&eT6^7_fJl7y;>vlR6k}|?HZi@GyY%Zf63*jU;M`gHk z#I?^HAFF1xs-|iTuBxC~*dR7QNEn+YKk>}KkN{S2^9*q>BcnC8Rc*3}aFg2!Hy_E|9IqOqid`OJJ;fsCc;JQY{Do94AwTX-u9;TpXLY`V_7 zUV-llRq+wNe#KY0nr6C-5BXb$eDf=}7FJB*&2M1&HXpm)&<42GiDO(|^0bIdYEE0~ z0nMYxH+t}jEg$_8`cyWa=(j3xI~gPNiCvyKBGsrl8pGP+_DHsYp?f>I=^d&|*Q4vcRp> zMPX}1c+taVKL6qV>2T+bZ5jkFkb*xO0`}m+VP!s6;sm#RhBkDIU#h}3j9&^)-dV}c z#Y3*Gs$OHK%Xg2GnB*_Y9LK2#p#|axFBQIU78c#*LKv;uWATw+chb4TY3sq1S1Hlf zrm|wuUzDH_i@jE&PH?JXdj2o(Plngo^5+&iM?#j^I<`hH(nSQOh;VMxOLK;ISF%x( zJ#MX0BTtel7%YT8UMs!kT<9cZSPPnEsPC23e-@j8!SwAX@S~`;5Ths378FIA!H1 zku;PpeODJpga-bkLB)Z*k#GTwzhs5i7{5yQe71-9s}a=YSp17!V#TRz|z5TME?LSuh^!`1_%wKog zq~}kA`vn@MfButy;`s;Cd2If030N{7o3BFxFZ?e*_LZ~wxgVzI`MQ;>8NHM%g&n)f z(G}#?2(SgKd-5;Xu~e4M+g`pG^Q7`^1*CLeD?oJI)a{pmHlh3redT~GT@(mr z+*%RFy?WD?USl2+M3dk=X5?5@%2Vearrx?s+n=T?zBJYV&LUW+muC5jy`aY@f-I8q z=dTpLpcOY;XqqrMzQaRfH$8vXuSkt48@EF)wnmZcRYd`CSS_qU8QGBjRnx~?Dn(gd zw9Ah&l+VUr{&+@nOr-ElepSzJ<@t>Ri+~@Bafb9FPJ^$;RhqAaZ_d411hkxn^p8v`W z8;`Ajhyv1<1QoO6Ui{exfEBbQ+yi;c$X2p7N}z&Cb_S1c zOANgaD|dSN4q;Zo(XW{f#-}~=oV}f{I3D1#z)elmBA*6=mizh`mh~j#2ltOSM}Wq_ z_7NiltTN|fA^jb8tKnPs09NJg`UKYtWXA#v*mmyjvFiX|Dw}FJ$TqYjZWN--8ZRi& z^g8h>K4QTNJq&?MaH`i0yhFs^pOUQdaCc>;WD8qU@t!8?TKy6Tm+7HM3t{4q$NE=mTd5pyexCls)keNz2^yu)lWW( zwE45b7*12~2Ip7e%y&F^n}_`)9)+XjJ-w7yjQmvdtb*$<0IyCca0OrTk3&7;Tz)#t z1_{-ke#uxJ&iv5u5k_9dFD>J@7-v`kdGT$|D))|OO1Lo1@)19rC0V`%ZUAu`%YH}7 z`w=5y9LB&6k%2Ly@|f!t&cN^tl=Sl3!oND?$3=hj^RS=g#rd7dV>Z; z!uZ($(zLiDg?!eN@TvUmWrLzCut2njOb58dW!5hOD+fU`yojX~SMlZ%$mJ&*MFrF{Ud^^#-nO5)59Ilxgly7u|doPPq-B?l`3)$Dts7mRzIj8_X$qye-mr z1{dEobyJ}L3)(_VI;PU%9VEi=D`Hq{ci`Ewoy{#==U$e_?)_{%@|(Z?tK zMY>=AqqNJ{5C0ev3B2%2KmH5n^XH$S2XbmpI&;lz}IC50^1DH7}%Y9QF-{Y>OJSk+gF(L zzv)aMNBl}}p;i8#9Ot)OdsvT4^{jXn?6m`v1%RE7yaH@zv}hOa+Wk!yxmoWa*X(k@ zPI{zZTLO;G{o7;-`WSipbf9$)Z2&A;LR_M6dlT08}9y>e>oIf zA;Z1l5Ng~)$~2K_ldZTUMy=|Xr%DH&L1p^;D-^nwyPmVQ&exbmCl(zla3B^f&(EU!ynvU!XME z1xKYHt9tlv&(ahPqO% zkpm9%i6Sg?DU<2B0?B`o@L7er^bw3u@Tx)LN_83rtQ~L_Zmq=i+e#W`C|PP)X;=Y- z7V~sZJ#%e%>YZ1HD^GBmoOAbG=@7}O(&)+}tcZvoa!F&!29nBF0vdQs;m09NMnx8V zy(?(J`CSo9n8=5S_bq4!_w>7yrOn}G4&r(30V4tS{GsQZybH%1=2yl}57>*#Avw4z zC3}~dTgE@Q@Q-c+wzdXJzGMp0VU7`o`zP%CKSFM-3sGKBrvX53)HNZpD-LPpM{4t( zNEqz`K=viCikh5Y%ZC6OKm5TLak1%TI(1w<&4knhnB7(_-{Fr48 zpRmB|nh~uutAs*U$WvP5*+^qcj!o!-L zsb*#6&yK6)8=9>WNnEgJyJ)8`ZCDG7on+&)+~AA2#cmkHRwzz(GIu{P8_pg-#hnwr00)qB+G~kT=`@H}aYeL{6EEYp_Sg#q*ecTO? zWwMuN-$3#$Jp<}s!EW}HPGS575({tLeKdtF59ul4v`hhX;MIeOs4fz&{N=fD#ga$y z+g(MgjKW|P@@)2#ZZ$NFgQk>B+3VRjmHjx#bMfX}{y7bdLvQxGcRIYDp1;HXDt_kV zbB;a@7S>esLr**%uLkNxXb%(m_!B5R7X3y;dZ`3_k%n9%bpK>&c#}Q<=d8KlnaY2K zwFUN4MNzzA^I!R6fkMeL5FM!e0vIRL$W)rrPD2YEXZ)Q1x6#uZUukfP9Y6p4w~{QH z+BJTw_ z8DZfF&Wd}j{7)Q_XO6bEQAJv6gb7O_5W?gwXjtZwZ{v;CicdPgo84OcJGnwbI2}M( zQ7YM1`geB$Y*avBk0M!(=~hlsu7nB?0*q8fc(KiX6g}O5O~W&s7K~}ESNOtK|1Eg; z3jl7GwUTtv#k~SI0AG!1h?ZPuV06o8;dMAZ@zgQ$D|7{e8#%cG;L>EOYnh@``3QUX z`v2NH_gLSytFHg{`|NYhee_MSMx^Cc`V>q+8$}cKA2dk4w=K{Hsj=l@gBlYQ+Frsd zipKZ|1%zq82k?p z&Us4kn%BJe*?)gXo%@g60-GNABd4AetNY&cP2Y__zK6S8)^cHT-53er`DNv+lUxg! zI2z!E5Kr_d>y_WCM*@BcYtzwqiFo0-&xPbQri0)v-1z}M7BHXZ*Vc`Ttvp*U)}prq z!lfA}6>f#=bt-$(*y|+9K^6WP&&uzA$NQOJxV3uUyFaMES|{=rgTFurrv^~Dw0+P< z&myjXW<`bNP=$pXe!(rC>K{xt_Lt6iCG8=W^?lp>ZmvFbi_r~U^{XK0)&K%e+mn)x zTz~5wUmXk0VUV#Ec_yjw5`~jDgFIy-=a`iQ-+hDi1o)cbIUm@u+69I7SyR9_2=t8! zLLN{nH}sZ|<>3s?Z`w=^st$N)i$~p^68zEEafT(xB*3+tN7$(JS9jZJ3iqh6)D0aM zz3ezNKNPDsG@yfx`nc9a+73eG zmx|-pyoyj}X_Bon<7|INca}#u@S~KvV5AvsZ+V2DH6%{}Qfwb{QC8RJOE)t4u5Xz5 z;U5LWl|g`3RRY()R5V@A^W;nOMg+y{V=!SKUe$ssG|xpyww<0$9F$`QV&u^`39L>sj9ohoNyXp4*Se0(i=qet#C&I)CdMR^Rb?f9W6d zEtl+%`$#ULL<>);T_Sb3DG$%GHx z4-RseWLQb3N`P&&qL-C?!z^r5La!PE_FlMCP!cr@K!t9^&dkDMunAEW+!~ZleGbq2 z_wQm(!>x0dIre2fBu63d#+~tRfGGCbQQH{Eik-HVK!$>~Olk^fKxDo9Bi^ETkV%u* zSz_5$__yf{sNXg#J^C&BeL5Kt0-vI8h9HTju0m96Bqu~RR#mjv;aH>Bz`*`K#0W*s z1v`}eNW~t_CSwIOuWHng=)M(bWop+WGlQtlHAesjetpIn+bV16R9sMd!6lOvm1umm zvD!b>(k7|5kp{5H1_$JmUIJFw4tDj?Opb}i!X!fz`#M&3Tnbbf^rj6ZUpZiT92TTO zJBXS#j8$y#Ej;x|=fbwY!?SlBqiPQX+HB!J_^!_+d6))WgaqQox}tH5G)nRl-#Xge zcBGJGeRZ0Pu4H#!40N&6TM2mb8|6i2(Ue|FHZ`n>Ya0-H^|>){QrUIF7RoScc>>Mm zm^6%?qgSrupXGfC@OjlQ!~MXROG6bOH*>{5?)-T)z$gI2{^zfK_1(|@F7$0irQY0r zN|PC{9CwF+n5-rb9N*E=VVaHMW7>L5*p=vyFOP-T{7c> z@x z5ZPaXB^Q4>7`6Os1#oE|bQA$ki?9JLiDIGRtrw#BXl+t-1xYE87Yo5Dp zIyu*v-G4t5{qBF5PxWHfeL4e&`?R5Z6g0>0jbm?vg4%U!$k%cA`1jn4rJdS9#Wayb zO}J4ntPV?c79AJy2}KD}mVE0q&4MX#)NkYm>r_(TDPZMy?7dY~98dJ`I}C$+aCdjN zfx$hv1b4T=-Q6K1NN@-cg1cJ?!2*Qf?(Py?&iw8<|ChV&+kHJV4|~>pR##V7eXF{< zchxS&;_m}gfmaH@l8v|LHRo3Cw7t|}V$aj68xd-!^DXgpl4vdaA8SXx zH2oDf8I?`l(GIEj{$9q!({gYfRb!4^rBR|S9x-!EZo5DXPA^BYgOdm{c@OZ>X_&-Jx!yY;vH zc#TQVPUG8j-f5$&-*`g)bsky5H@epB;Bx}so$SkieLiNryY5Y$_0DduR~EACaf3K4 zr16t_(32-HkiD)JNfgcq&uz;jkk%Q|k(1-QXKXfUs2174l%y#bn_fTmSav_(Tx*@^ zVz$344O?C{%6G#zEhkz_Ye>5z0dr6uVXH4JiecV(*Tc_HjjF2i#~$_eMS1R+wr_cp z7p}{ie+W%V!F`|REM|@4b|}hkdGx`ziHLIaLCYCq26`no|0e%u{4*9J-Z_FEo;{E_ zd8#VUDLIm4xC4mgq=uqngb-KXWHELBAaQb$vdgc-e*^KhJTO~7T&<&{)&FYudKMS+ z@WY?oRImJ@^aP^T=W=`(fwNESyP*QA$?Ojcf(XKR)l3X2K6#J>*;kpT1k$$5+E^V9 zlCdqOl`i{}s0Uu=Oy}>zjMCNnGs$I#PO)8ExePwzy zWW*W=Dyf7>?;VAA&&*oFukcECa>CTNGIZqO$?icZj|c2W3OYCx@Y>Hmb&AFdS_nRK z(0V;+85P1)MhnyFtcQ~_#&+BHOc8#uXo!0>W9)fa#NX*Wp;ZH|2_r`-kWq+-Gu> zi^b}vj`ONc%|OK6FS8gqMqDOBmvrN;WcuCA5)wWUW^>n6D`(JYg2V4t26yYA?c)u8QJqi>mx~S*o`>Cx`tvbiGjIME82fw^y6Z->Z)~k_V}-yjT~L%BH+51n4ad5RlC@J z=@;fPX1^3lV3R~Mx0qM&g;x)^61ppM&RY#tp7u<`a&C7Gr4musF9ipa?H9$23BPRiG<9D7`wv09p4ECH|D4 z=wd)@kVXD&0v4YK*{%@1WI7Z-!_W(3?tlpEV|{NQZKA){twPbi(e?)2P!?w%E8QAT z5(VjDy9YbQuO%$RlYi$*~dC#yh)M1FPuRY4^ENm<&?(>|<3s-lgr@vgV z8%(*=KRsr8y=6PT_{x1H@2Vw#Su*76{sVaTvLpDa%u${R-S>XOOrOdqbd?8`mu`RS z6iFo)VN?i!r|@M{FdrzXc^WUC8?|e1%;W%fE0o?rGtk@^dz-gQ%H-d<)L*5fBSxUg z8kb-7T~hf72~h1MsHIl93irdc&e_Rly&bVN9;mKq|E{P}Y2kT*GCvyB|4PD)K=C=0 zXLEjbiGGIk0ULnL+lNIAS1cTn83K%MY)g(@ifnX zZhulV1+(K{qRsCf0*jrch?jBQsT$-9lJMlnyBReTds zLn=uUA@)}cHJy(RsAqj3GkxrLC2z7u)jg`JEl6?unygY;t@arikIiS_2}979#cJ_O z16J^Kv+h+&G!5T!S)agX(%mJ&I^)ew|17NRJX8#3$Law#5SQ}Bd>Q?roEf@KR8J@Ru&(V|DjM~4x>iwoRaO} zw+ms`diwIGSd>3|^<5^5UZdj?cN_e;i0@1HnyzArc>UqY^M1=^WSi}y4{nd~z=ZiD zmiTXDNbP!Fr#D=p&t$T$8W?OS7G?ghy6w2(R9&+Q^vjvYPutFX;lcSHq370Ua(hBs z^6B5U*h8Pnjk74BB;QQR?t1_}!ycO=lsN zMZvK>M)HH2u@v$_uhT-Bq5{<|8L(AGJ~KO$L04R{3m9L+jzF_FU@gYlE!vn%{^2_F z^!>LPLp}7Eps!jPqJ|Az_Fxu{Cgqi+b@ej039@!(Z*P5v7lfm~zc)PTJBJ%o7mo;e_8vNW{`(_J0r* zMP1`JJP}i z#=hZ}1{{G0$<}kdr@%Q#{+;MbFZ#pX$t%wDA>E4G^6YGB_i2FN^ELim*9igyV>_Dy z9_>cwnFyNCrgzt~Ng5o758wOz{Jdl9lf^Ag@WahC1<|`ft|uL?F8(5a14ll_T{}pe3B-)! zOO$@WcwTaB{VQ!u*4;k39sLEZuUJZjriqp-ImOwhzlbL>0M`?hA`$Jwg#z1tCpaC6 zfpTgjRkK;%mf7mkndW*NMME^|*tyUFc5?P5bIBm1cy7Bt9;R#$HJhhe^Kdi6dT zRgMwCD)xKXCFkAL^cI33rZ(~8Q8&ZKokXTRB@=}~LNdP*=L-}g+21#=+MIw5MP&pd zi8G5l%N(Y0rc*?UuKun|wlCqlsH9YJAkL;aeQY5YR6D&y@X?CldauKU=9+c!dKl|% z&_bW-EC&tCG5RIc;fZ>Hp8J=$PI|*5xL|zGYoK3g zCrtq6UGLlqI!pE;`q(O_p=n%H-Hz3S@$G#)E_ong-LaI}n!h0W9ij@DF`xI>zG$ME<1^DOrA_IU72fO&!kF)3o#eY_6-_6Xno}2SnEkXH z_mAtRNZNm>-TIc=0mNlkd0)3;uzjcYYDDvrIAVIgt7jzd_?eTG)Li`r%Ju7KDa(BP zizzu~j|{5dWX@+z;^^6*BcV#4VT^c(sCE1zY?zZSlPKH!w-HK*Uh^+S2_u0GpUC>D zC?D&`O8sVTg+A7nkl*ySd5*hWx$uY~hQ=Dm-hZ+TK052%%J+fAC)KOgWL_ajrLQOF z574|B@LlUSxBa!?n?nr^P0A8UJv@Nx#wx5#JTRTG0FUoDJU?jD$*QDRNa+|cYYAw=b*jw*Q3wM58QMAq%&_-O?)Ty-lkev?aPKHfcav) zV!sG{pK?qt`+{uM0_i7CaxP1-T(9YyOW_M?;e;3pck4q54WhSBLE1sWl^C*vao5mw zNLP5+U1aCx7sb=Y>9WgW`g0fC6cgdv*%M>;da_Wrp9Af6SnKZ4(WGfKO1Itpo)9?C zU?IGlHuvTJBjU;6$D_l^N2iS2s^(kTZm`}5HkUHLQq*9aqO2>vH2NCyI8jd5>U@9F zbtFjlFAu-`@rcj*i>m+j(?1_~BjMOZOPa$;*%aM&R0aL;Jcj>~Wfj&(gy4dmr-UDDb`a znG^>}SJ&OlqP&=&>^$byyQVdZ2VRtTOsja+LVknk(JiQN4GX={l&@mM2gq=UO@O zBju;nU7;?uvfqE!Ku1OHFVDS>{Bcl+GOxX<&uBk2{GD~VSUMK3S|69QG}?CGZL!Y~ z`icHItv6boaCMpqI^!js&mzltXAZeX=JN8ZfN#o8(cw(FXb+wC${()rt4Bt$StMG$ z)i36Rbp}8NpT5o_JP<@X<$lzWp z8JDxTRh>jagA)N+$;5VU&uEI)U~M!z^I2?B&#?NWcW6@9pIl4i=&c#+=T>cwGySJ> zZzbsW8#XXb9v#D=VNPMIzMG5@%#;}?(p3BMmXq;q>}sB6!^AD2boOZf)mI7nr?eq zMHOeoa`1O*84%z!uZZHvawwzo_SY6$Nz!D8J}F%2YGsG->P)nEU%rRVU+%|X&fxEsh2D@ z%%ctp-}MMjf#lGs)^ZUKROFTvi^^-B!)F7drKneZWM+#jzuut|1e-O>XsOJ|E}oPY zEL}>l`?p+qc5o8JjGkLmmlS=VLt)hdDO!V^`_Is6ef0JwM;L8h0t5W}N@JR`Kfi1@Ky}rEH3W0y zmGzH)HWuQKHyYxdUvtCe9=1Juo%|prCPT~AYhkItL` zY{z<4CMlN{8w)aAd2pBj=7(HD@4XY>2kr{#;9TxBx=en@jJ&M{vi&^V8e28<JDFeB+7JZKY;k||oU;YlOY7CoMM(0HgdW+=`XQ@+ zDyng|b4g3rAcs@pO2Vn-Sccnv3Gwq~bNH0lF=wgXo?`r&-XpoxaZA3%Nl`k<;r%BJ z%7-~_byZ`%eEzA5#ld?X{Usun3HS*(qWQ%`Zg@D7sgIxY6GIe_sS8+aNxyovYanQ6 zINvahqxq-((x^-$dr$fZ(q)|Z#_{qu%=s(`{f8tr@i=P=bSsdwg>}tQH%hsa`18uP zbD3C1zo$9n`K?cT=N;yH=WEc$#H-Kl?+6M6BA++Cwqx7k^?9_Omn(u{+AveY>Yg_=lba6H9lztdlasT{mOlOQn!A4z#hpG_wnpC&8-&P? zx({LolrG+tzeso=kH3{#|JgR{*7Gvf&)d-LP0o_XXyYXheQRcp(b%=fW@$K8LT!tq z0`&wEn)mY@q@YB)B}OP}#Tbg-_b&!{qD(|n^e42AzE35MIQvIihf9_xs!^k|O~m9# zlLeMrHVAMUJxcmek^$@)?0%~0C-Bug&Ynan9|X=+4nz$Nfonl){XZBet!5?4!AogE zmP7$L)^WIYo^Afx^|T#3nMrW)cw6;VeRPSye!0bm9k;;{oGLcWh6av&Ad=~Ijy*;z zd>Y+q-H_Q~yUnDgxSYRe+#b%mfAn#Q*z(>YpvAB6l1WjWtt!3$2oh#HoK?B0h|BH+ z6tZXxoze@H3n%LP_qsC!hZExH8`vva)teETR^TQ`;s)`{-ZSqru{8`RM1FOkX`@Cn zANDAV4DNH_G@&1bt2mJpAJU*J9VJxlClw<223K1bpA)E6=FeVov?BM}%PlX0DVL_C zZ$zNiMXam;$}x01%XMpd#GRWm<{sm5f^ifIDFJwc&@TdZSTE-5U```qdNUV*E2wP^ zQeyw+eQtK_8gi^Be#h>JV0&ii9JZ+`KIdNE)za7PdjHsZk}JL$1$uDZkqVi|oaAyG zlsNwr5FLDeeMCiAKxk$J@NqCX$rv&Ys%H5%tsa_l*=VG=&;1dzpW2iV(H&VJ9qEwD z_j1f~oIx0{o67QyKeO)-N;&C}Qz(kt3dzJzJyhbg&#qnNiAdK)il@iKtq)Vt8kCuO z$sOO*)fiEXdInlM{Jvuz9fBG#HxkIaQ1k?&?6R!(&#uVM`z}o(%r(yp_lX#p7~!IZ?_V4Ry{{GSm*N70omjcrjtF*9z5PKd zw&a_Vq?R(RhCxy6F=a1Xpk+iC2roIJxKXjpZ*fG%+>2x72=Eo6-6!=M{iZ=J5}(&j zaEE`)qO|LutF~fBK%hK1lU+KyD3RQg+c2#c`A;+qi?I?8 zqj)XuP=;sr*~^um#z@Zp(tHn~VNT}wxfb}57N;$TXpOBDDfFEhywFPbZhpPeB|VBt z{9I#2n(0DoEV&CIIg0XK#_%?$IU6cLZ8=E@Xt(N>ZGOz@MVbMJ(qz*yNaf_1^Ts+P zO0|yiv|XyuRPBBl>m*s!#d7OpqVv|Lr8f=12X3Q_-l=WW{(1WYV$LXQ{9A&5>4_&EUpm)&xsn?xB}p7$-_Fn4c;A9v-*NQ zv9R*!brPSkd9{r&K&@{DTZ@dY649Hk`6-cDOfK0d_U0>s6auU5Y!QQj+r`Qc=lp2@ zh-BUs#`ZHmCQ8se30*f)EIAlf8ZB`tzbv_lh1@AyM;o~i=}`T{JkQa<@=F1HgN}Iv zct(K*q~Q4W!RwK3cH6Hxh33FQZ%A0HE8OsyP%a((gXY4PPT#UyDAr}O#F=?^p@sp*R zS0#~|+Zpo9Fj7auG&84tQlbJ4X_AgO^)+Gtba3%kO|x!Rtno@#I6O#lo@UWuO$WQ+ z5V{YdKj(59tL`^e{8Bwb*=R7(WM&EB*P*>EF6bL(uq^Fh?nRC2qB5X7rC~s@Ln`rK z)d3N)pQ6kaj*9=(h)cSfmb&|@*?e1J7=dbzTS2{n|GlHC{!7>K9MrIUNmv1cV9(le zW4?ArwV=~i@A`W675$;{&ZU>(WlB;ZzciSbeBoFg4)cYQf}-K;^&I=&!t?#a+=x%t z!2j)#X|boXrxeLLIeYcR0)3*Tze`G_FBvE%vVMN5$I7f4}iS8)bUa zn^!~vjZ9M-b-}lN#qoScM&H9Hq{P7-8{_B(CqEhkDr0<=w=Pu-L~KiC?ZeStQ7kV5 zQzIM5(asGkRc-AX2E4OJ^lO-gmt!}5^E5xG)&h~sHb5zJWL+LZ$ z#KwH4`h3E$TqscayT5+a3moZK$yGdJN76nq8|I)TY*D6An*gnQzZ>m|?&7LZJy>;17~Bixgo^6f!4{ zHRL`<(^;wKAA-R}bbiq$*svs&$z@`v*cC< z3t}0o^H}WT>3s z^RM(zKD$rSeaph{QXlfZ$SD5%{|dSXE(v?NGwu*uA6Rnj)*K%4I`&?0 zHh)5Vx||Dd>1!GfpS{dw#V;JstP-lE+IKv#IP0RXNS=Z3%yv)eOT8nU-t|=ii90{oJp4K+exgwc>!r&|Jgk!h7^Hi#p(tb-g{t1^CzWPb~ z&t;^dymwc%V5(;2l2dYBH8c+n7$^tyeRZ`hEciE%ETM)N`AZm(iTT{c$@woYzst+k z=a{mphU{%YEaWwzRz9r#A+n+G1P~}ip4`lH{@kx;6teH|FJiLy_#ecpN#s?;!30*N z7y9}i=W*an)!bJWI)ig1b5(BlUU2H%P{$k`jUGfg>9N({P13PF42m`h*1OY^V)+-b z0huX&y-2Lf0DCU*7qw#_g)3QpDQG4Cn>v_5_%@(x%9TdEKTg-2Q`KY3*e3#8KxtD{ z8&Q6%KE5DFf%hp(##jz6(5N4|kC~FJ!}}PSF$ULix1S49)bSD*{9+lAQ<^xep>jDB1A0gLl`J%&=5SG&I-4t7gvT~grtm*Z{SeOVULPt@2puwK5J?E`0>6}$c%nn_iHg;b>MbJaA;MDr1g)j zFCF)xF57k(C#N!te%>hV>sL^Lkk#Ertg5psSk%$FR(P|*b>}Y7OZ4t)$XZ{$w0c;9 z?8Jm>aKgD|;9F_L_5532XTi0JA=flx*?*&F-0LEH5ziESm8~mQpBH5+5*o^U7 zbDXW)*p`=iVTX#KQAb`*HhgXV!2acLw4{2o-$c&73TgO$mnQQGn_qUHo6t;l0e|WZ zp3dz@t|&#{c1FOf~&)(x^hK3~6y)fXJo4`c3MsfMUKqcU#|%Fz&n)tl#R$9tK6K!}dUh^gKZ zMHB`eI{U#X?O>Pu64{BC9sBXBe(V>vYVOE_zlxOtF79j$_1XvVnIcH73>L6O%M@sa z_us}8?8_uueVueMn5W|I_ozPr07Q(6GLqWy>R|-$l!09giY~BNm{{M6_GT*+qCQ!w zQ!QK9OtK!AD3imXIH%v_Z}SVc0Rwf(cNb8{R(rzou7B@8W%yt`lAo+T5m61iCHd6D zn{C*BE0}-z0NFnEOb$8NfWDaq9-|dJaPWOO#9aZx{AVb^q0#<#uM4bQg+2SioI$Ht zlm)q6u?bJd_r)96?($nDaKIPj_#U+CYc3*UY_E5_5GaAwsM{zpc(j5QwMB>kuuE56 z0x0;w9HRxNsL)QslgH*t7eFgQ6>eUYWl13m{pwO!uY9!wPJB*4`U%=V8$LW9ags~Pp((j|LG|V&VkVqhb(ufZQ3n9 zLtDAHuEwy?D!$cy)EVE(w{7#UoL|zKCmQS6>%!4DXN4sI(#_~aZ^E6B(R->X{N*oT za{CSjGutG3yYAze^O6EMDuU3~N`MWH!TqYxqQ3EFp0z3JjL}x^)(FM{|CHu(G(C7p zj_SeB45D()Re})Adcj7{Bg){-p#)DyXx;)Ol>5A&HERj?0Bl%&N6YxA}lLNn7gA(VS-)BP5V9G^P2;^J~-lqg;%%Ij3Wn831<^yPz$q zLo%JZ){1Ey+f3s1ARP zz$o!r?e!>DlJx;34-P&s32|qlS01)AWyq~JBH7-)PG1m&#yi+MX`}@*IoywB8vLC8 zIw4x71e10GX+LZE9elb;IhkTt>{*$_ZaL3-Avj|~1qt5UZb4!x`8HgO^d2SC zx7vLrYEl+GeHOzJ&Z@t`6J4{}%9^;j#?`z9I57oX$4KYh(nrW!VR3qJ>yNt=kQ?#++KmFy zw~41%CEp~#AGo>`OMnPax$itV6mFe9n0##OPM{_&1mls^^!nreixOTzj+z15O!l2( z<*Rn!G;s21DI|D5sl+e@*y|^le5~fK_skbGo5i_7-heq{3N{q|f%nf7F;@tj`##sG zE5W6Syr^8cfG1pnV3jWT^C<}*X6J87E_au*Vdvbi9MPHN@4Eb!hiWc7VMME~swui^ zU4b1P?!n|eP1fh5M|oJ+RY7C5B=5TPy<7{jpOi!+YCJz{*f$+?=yH1HoO*P>o?<{{OOOjz#`tQe42 z{Xq*>M&%S>(ixZm3OFH2&! ztGavj*&UZk`xqHb0w)jNL#Kva1pY_z)eb+0_mu4~#Fl!RIwmx3-IDg!HWLauGhMWt z$}xnc^ZBoqm~zCry&}9)0}(!Vpf3mbOyaaOSf5=5MORJ36^a1QDyREvMBxxf!-75T z*D*s=0Kf8jh1#EdCbwBL&%HJasz&NW0+0^g{GObSlYETCo}zkR2@BqeroOko?X&>O zM^y^q3GP=qP41AqeeT}wA8r@*HdK1?T(9(rdl-@Feck0N-yGHSg#r95>d?HZGedci zvtLIx(Pk06f2Z1A<&v1w5$Fb3HioyltI}O3z=9)noIc&3`lh*;{9yNZc{9@T`=4Ws zm1AuNd7A^31G53O1DR&0qiz9)jFn=UYqH%Wr-e$@?)wBdIGLhdKb5~0p%p98KaiFC zCQd`fhZ5|>cqn}&%nVimC33u9d)?zYS(fJxfmmjYpx3vTjrfTX>TO&V^c4}4)57Ic z+=kNnmbEVp9!{2kpEmP{iTAov=yFk$ZWuhDXH2DT(9`~GHO-LzZ4yjgHKPzudUr{Z zV6{Af{A$}Zn7WN&6@v)?j`&qMcgDI1S|dAg1<=K<2C&kIb6v9FW9heh|EMtap>wX! zz1sBl0pL-)6=i&obeG!~xnrXlyXCL>h|3hg>a7rurN5Zu+%VN-&dv(;%|C1Cx>*#@ zsE3C(bVOiEWO#E(-7vif;p)nZvH`r#+*kq{qLIh}CxV(qayMm|R~z3rp!)d*3ve6D zRC8`C;Jrii;gW~@B5L?HA!26a8ov-Sfz1O8;r^a|&{tk6%-uA>i}`>TP!PeH8y&{q z_3)>Vh`Zj!Rk4@ab?>|DU>`o~Gl&)&~?hYhE<1mxlnMArxF zwlP~L*YmZEP9~1qBW$AIo@I;wHR8wS(b%s_s{^__^4iNXtV+mX= z<%Fg2^%>vnkdXtjUGlhr&_gS)Wdd>_*~yEbH*s-oZE-tEDCN##5iOOA;%E2@ADy-j zD)^*2e<}PYE#=@`xKaLW43Uhmoq0HV?Vq{j_L9>*Gg1ng_v121l%66(uMAN5KhVTc z8;Ak~Cy2k7+L>88_qlW+Z!r5vS9q!{<-^gwiO>QVSK+>eh8pT}GFw}IOz|Ytl(H}c zE?+7{SgsMh1M`ff?adCciO9mE3yC6SN`9x(`XK<4v%4g!`m*icTBOww(S=XA_br05 z;!4GXesFBrd+W%E>=dn<^d^4yqbv7LY0`L3UtvYh5x(zq83xSV%_DIdF@Mqk&o+Uw zf5JZj-%D_aJVCzfxfO^vqaaN2ZeSfJ)C(!p<0npN1gq{|IjZ7`hn3KR`1kMIx@zVD z;fcq6Au#BE-VbzfjUMtcblP}r+Ou!%A!SP5q_)alKCV)rO3-#(BY5__)Q^hWGccNfE`0XYm^u^nh zRAy_ilwakwFENpBQCOcd1#l31ulkyfsqb1~{$P3bxc-tl(6r(u*)T@F)Kl>0<-Tt7 zcj`(|GnXaGy=yck_cpGGp?pWp?OBl6+b2pAqi!h1gtB*N9?=)H$*Ywqc$?z%QPr)!Z9h1GU@1UJ-f zqtlbOZZVtwMf4L|dK&d(G|_pCTaTH%)wNxC0<2QB4mjW@7hbkfSOYTOasuNYsYR27 zaW*!QL&-xi$fJi(qAKOaNVrrhj{x^0j<4_Tr{Ok8P?H{Uezxboy9m=k0t90#_j&?4 zI4U154~DxT57-x!fb&+L7N57Lxw*y3)3e;}hwIjYw~Pm!o?P+*ft*~Q0)gs0jG#{l zJtz5ZO#yG+y_XL%6O)_f{|Glhy`Zn;gScPA#auW`5JX15D69YO`{S3~WL5eT zhmk4;Gqi0Wn-NXzQXm~Y^zdT)Q#0opK}XSz54PIn{ekEDvCN zOpArnW(SM5lwKL6!?)5wRaZ-OrerHFBGli%=DB4FWOvCDonF3urs(R*vt#PKp0(B$ zRsNt1{eH_d*>U=!TzR*)VA5SMIzqt{n zKG46wCA0bqudw2cNvh=zBNFCyh>Fdcxe3Eg)PE#`mys7m6KyJ5tFfc72^O8lt`~{=jJGh1*~cydSkv(cJOz*em+1?%6Q_zMvcL5ln7BuMW@Ch@*$OJAR+sOU&v;R z>vH?`GjXESUz~+UGBTtTtcm<&AAhneHJgxf+^LMt1~-C3qX&F4vv`r~Bf!BUM;XU) z73Jr`#xG{jV>vaTCtm3O!M&h(leBSklUJgU<}tcDtt9E0C1gWlyH9=>$QW@ZqB?uo zUYi0K<=2B=vBNQ*EY_u_D`Th9sFIz~ht`z=YTq6{OS$bB6to!&dVf=Y`l#J3buX!h zhBDGRdMw72C$&xzN3b+AqO}T2%M`{bx`>d-*Mw)OgCkV45@9^#!*g(L4*U1l`GVw` zl+~ZZbE}zx+BqzrQ`jY*kLc=}=mR-OP4Y1^M0SzR8vnHcFsaO#}2Pm@gs+47n}Az^<+Jwo<3usQMz=xZ;OWvCJ;jvsH3 z4gvSbR6ft-3qgUr(bw`wefm%Qmnq5e)d*MAR$WLPSQc;VW@4$PdqmyN0q4);g0+z6 z_KMA}~XJ731J4U^0EMoE6mH0r6V%2Q+7ccXZN+?GVc$>T)UfL}kGR`LwSLRR^Z zw49z_7^Z444tEjZ`nkICqL{QzWQ&?Bqyf-MDeXq)F~lR4vWi ziH-h@cG}RAO|V-=mU3|xyg$KGdi-#@y^2rR_f*9Zf zeG~na=3<)puYQFy6L#I>nH2HI?3wdm(n!?d$OC75EtL2%{eUG=WJ{_}nK{a;EZ*HZrxjq0bj{(bN3)JGKcXesP={- z<_`1`_px{Wpf4~qt@w_Maced5<;nghQg*uA&vM_|Yw%{o)4t&PUEk~C)7$21NR>$r z(b2?9Q{VX%Fu#}gJz5|cJGAFtQ|FrJ;n8N&SfIoWYAqGFJJkQd$@Ul;bGM#FTX!CK z;%wqCE-We{1Q9EVfO;d8A1lwbUROP`oZSk5xu2@XZU_#*b!2@H!sKX(uDJh>2W_qUzS+w}to;2Q?-Ozn z*#no5>B~>?6Bk(G_w{PT4lg3+-+mdJ`hQK7J^8JI_J6xg3H*PRKw$WXjW>Yb)M^QqWpxn%_ED5om8p?33%9rA;s*dw%q2DDrFH-yY>1hg ze^emI-^~ny9R~m+daftE0oOg@qXBS;1!-?^1qe|9fP4BIz&#QGhrONt2DgnJ0RTWg zzX2dHYYwyKFzW`hZZI1FvjH$02(y9zKkWac^FQhS&w2jOdH*LTk^d)eQ2;oE|DD@t z01*EFTmvZX|8;#kfE@tNq@TqHH7OA(aS>itdTMfPfJ7Vs|ILz@5DN`S)q((oiV6ZE z08s;ew7*3IP~Qx30RSKXx${mS6c7qT1Za=-b>wD80Whoy0B}GcJQ9Zj84w=+Kjhk0 zS07Io2|%9Y{SSc1RyLJR7C{;KP9Lh%BtVGNNkLEu2+o0xY}(S%9<=05}n(Fd!~~(84&)k*f@> zW$mRBZ6?Hvjlc|J{D@(2xBvn@EtmX+(nKBOxWHm9SRo^_!WcVzIN;qo9V>eqODk&= zRfpmg^3K7nRob3+78eNGbIg64>6z! zL<|+k2P35a5kqwqa~DHd9V-Pis$jQd27nNZ;KK-(skw!XssK5Nl@vgcU=~9Ql!^er zBLlEeLILkkB-CU4?dgaCKx_bolfDZz`uivV8ilPO0D#KN2elDq2?Zd-gih%Hqu%v+cLxhwTU||6 z1sQPxK6W}Tn0jY@6u4O!7^Ichs2CZksHmx^gk+_3q5*_&9-PEPB$OnEA+&_VBqZb{ zB+Sy1B0RiN076f0B62D^VF@K2VIB?^1{w-d4q+hyHik$5@uVUtH3I{eq>!+Pn1rO1 zvqAEJV3Q{r>qF_;B8hR!ga%y%M^yFe-6H((4HL@`a zj}7+lwYCzcqoAbc^D?q9GYN>3Q_%3yQgcyK(}KBJ*f=C4xna2F(RI zxH#E`C0SU76ckkWSlF0Eq^x#hGAhbE9J12N5ZH2;;l$H?@6cvyF3qWKR>m6sBgloA%xiVRHFQ?Y|JL^V0_P*Gedc^L&IWf`!Lw1B9z zR*GkWo|+RZRSi`=H3_h^g1D@%rkbL>tUN?kH^?nmPbVk>fT6Bz9&0Znt0)f9)Ra>S zRY8WxtHWMCYFZaW0ti)9ZNp8K6cnVSRFx!UWWZoW1z9;6{b-naY?M`X3^WvEr6A(6 z^2##e5Jd$gr4K%^9ur?jO-)@(O2Q5 zQBeNiVdLlm_3-ra@-`6SKmx*1ivL$#`Kl7CN>YX{x&{V@MkcTh!NyXOo0^^+y16u{KxSXzz3=GC-OG-+~nEIHTTbRMPsfnqjjtSH+82X=n zBDCd|Ro`2prD3Bap?A?`{ZAvI<~n+MIu1~3DmpgUpVU;Wj!L|I z9FG35n=o;xrM{t|o|6XyBPXvYlNb{nrx}=!lf^069tMMK4NXi8T)kL0IAuSuY4EY| zs)8XO%z{Fk|AUUE7UrhzzP!RBJOW(8BHRLCPW8Cx@F0)>psR(om4%l-7%V0sAtNmZ zhVb*51-QHU`@vv0WUkV`8H}mi0ygaFQ}JGqTd+&28*$+(RRyTpbcalYoiEJuv-bCuQXp z^g#KS2OwM3@O7hjn@Y zI7@qJX>~_wd1+TCS9dL_xuvy?y$96E+)tes0ANZBO08EOP{;n&t6N&=g-uRI#uF#~ z=_6`~P!qn48?sLS(WjoWiqv27A88N--@?M*!cZq%2x3G;gpiBV5B7GxZWQnOamIb6 z@lV+f4m|JN7NQb%fx6tme-rJ2y|QJ^DP^bsmk8>nLf^a0t*KRdt$}R6h~KQKj_LQl zy(RU>A98;$_(c56m{Q@}&&T{p`g7cr_9i?xtFr!haaJp`J-^u z&jWH*DEyB@Z&>&u6WshnEZu*LZz?UJgn7I$hFJgi zieTSn#BZNBNRkcr|DGVgWW)b|<9}bC;}6sRKVJ@a*pm*xxZSGyM$`In=b6(@3kk{N z5|Zr?c{(H~dL=R9f={q2E8psWf5k76pU0j^`c|qV>5}%jbfr|~F~>%o9$#h^TNo38 z#M`EO>7DI14xtJgtgQle)Xr+n6fn!jB$2%fuw@+3@VKoO?fchv(I) z@;ZWj(KFLBwH7ge@*P5;=sOfRF-jDK|4sh42LIa!|NAfeFCP3aCjReS_}_8(KS=QZ zJ6QCCmAcx6)lJw3``=IZ&UwctAh7DW@wnau9p{`nk)LgNCYjy(m0^9`TQ8u$A}rA2 z%>gvbREVmSTW!;9Qk<$x&y?3Js;gtP6e!XxoIM;}SXlU5H(NJ0yWp%0BrG~S3G{BO zc4>5hT%9-@{uNqYns<;IA{((&#ObXx>+htQNkOx9F*_@a4EzvgTHW^9BZ?E#SXskm zbV6OGK55D^&tqm~U3D`t=%s!upJh`lixUe#en6g^^^D zVP3^Q>r=~wG4a(J#kg*Q;Ju}eLP1S}+1N4L6JS&+H2X@Q;N#CEXY#VG@5ES&QgPrr|GT06Nj3`B%hJ(ax|U1(+<_8*)X$U798n(S<|NHiv!fuhzC&EZ3c{I&VAVT~}ZQ67>IXmhdF@ZrX)c_upi5U0f9QY5`YKP%PJXYjS$E>t{9AE{(D`!$DXCX10A`oc`2O= zJ3QnN8fzhzDifQ$L@Ayctayy-SkOfUkbJw3_;`7z9y-bY{_1P?FJJ@m_vjz+Jtt8tiEsCyD31xL8_}4SltlhR|M#Dc$3M z0*&D)^L-@-yD@2ICOKZU&dNr@uYO`q&-WFFyI(+As(zX3t4{5WjZ>ML&jWFBJI6Zl z9S)Bx&c}Uo2qYm)EDQbsqt* zN9>dI4B=eLOVI3W-B4rGltIo;9@+!Ba{t{QxIO@y>6z+%EKY_KTtM5wV4#1J)smm& zk-y;tr#|MB)4`73J{1exSXihD}EL^dK;cUXPpH+^*=&dS-%BBH); z9)55FR3}x??Qk-2Z-3XV{5$+wsS>iCU1J8?#-s8Kf!zH5S{NBYu$UtY>UOasxs5VKtY1d=*lbK*4bvYp*XVb;FA9`J&D?VbFikA%|ExSuuW=9&Wa}fN z05`eXe9~)Bn$A2_dcO5_--t>yyn%VTDt*aQO1lVJa0Nf+RB4Szr{8<=9;xkfJdmg! z*s=nGw1h!tGm#xN>ed(UGeJlcJZe&BHVVlnUluNdrjl=x(V*82J%5Oil5F#150517 zVLteQ1+o6R#k4m?S6^$9OeOdoHc0(y2i z+lBol;=aZu(1zSp2xbZXXNQ# z?q2)5>P5P`Rm;KxUQf;|o_g%-W%v;t;$nw=GW%C|PtH-Aev<3>%_i6ANw&&b4B;!yy3`Ok8|IR>P%$$fq)2##7EI#zlZ^1%}W9L@gS zCVe$VTwJ*OFwYYM|(f=Nh0wsZxdj_dtLtdvA&sP4{>ESd5 zH;&%ttiq{*N*>eDIB54G%~)RL&~&)q-=gBg60(RnDH4u@V4mW7YdLh+lzf<}^9pmx z(#G5*tOSy$UYM4ZlV2+Yq>nnEpE(J|Cy!Ff$|jy!LiqfaWc)7TAs<1f1Am_rFO=Tj z1{>9_n$e!*q2{!H>r;Ekjy%pEvw%px-x}!EHrDXPvY%FaIw7$fRBVRsVlF1su0C@n z(O}j4DOXu?4eHP(3l~Dq4rk-)id=jiGV0<^qc?V|pK#}0^^(e!Mc<iDR7E&UZM6WiaQ)HB*bRJk5qHYBZI-IQ!# z)pP)4;XEfz()HTdZ4W`%Bn>-Cg6h59)n}LV6mGzm?UT_>r#iO-w;4-a*M?8QoHAO# zC0|y@yJ+mhWcZsKWP`&X+w>k6+d5K&droH~!>5O)4$vZ1vdv^I>g*ER!gFASezEvi zLM;KE&X>i52VA00^e9OkY z#~{;a6gI&Ny>Raj++5uo%i%_-Vwd)dgW~M*7xtt`Fe;*`Ru>2iK|R++R~V}Ai=8Kg{@}pF3kx#JVOb-yOwyyz$8cj!ST1WOd`07e_-|o^eL_ zdhNIlbn6I8+Smpq`$2YuIz=u{6V}g}RZCVDTMe6xY*Say$hxapv4)C(fZZmpDqjic zDX*eyQBma@|I=KE@Rfq_YIB+yBaGtVD43uZLNk_O~~aJ436q_9`>i zm}vg%<%^4SOCG-)9n5FLX&GXVoRD96j9it6fv^mlq`I<=pxWR)S<=@VNdBRt<<>% zR)SISef{)SJ}X!cv$EAse;-Enluik6puaTw8O-i?@1D>p*`t@c>Ch+s7|i`6+YU#7 zGwcJHw7v{(jd8IQEM%ImkKvyj6B2!-R_pKsC|pjL(%@yl4XhupQ{tH zYSmyr@ntN+6Lm6GP9t)Mt<2FWd?{U?ZKHHv(pcTuIU0d1Kt;_bx8etjdPQ~fo{(VY zm~B^#;k^a1LL<{e!TimtsD8Z_u9}@#Y4wY$B<6igg0Nd~GTl*m_(v!k)7XjXtfXyg z?cXuN!kV1deO0`>3J}u_=LtW)j4q6fghVT{2tLn+WV(x;F8|*!^$wvKV)h@Fdg^?q z^r!y1KhEzpC!;Q}YTmM}OFCzgmr?A|lLivac)!rJLkc24QB zA)sEYSzICH{f;NOm;e;LU-^O5O!G%s7WE$zVrr2$bBZ`2(Yt99pZXMzwMGaVT`-6S zdEIUStMwt^$^Fx!G*a{ZFIF3BEebS#wp+rg2@ASzQ$;m3{l6_KGb#?t>UFG`PS%YL zIC&1#C2HV$;ZlyV@P3}hcAMmIplJ+TM2mW>8nWf!vad|eDXSnPZxyX*Ys#d_eK~DH zU7K`gpTCxYh_%^M6@-ctYscfnJv!x>fOKGVCV{Sskw~lCYUZa*DN&aBuUBN!A~2;PK7pDHiVi*3S5lsGIi% z?Rzy1+d0N;tS{YV71#_V6qP?heCi4&%X@6&`+dEUlggl2WX^6FbUQs?TD7={2F$-D z8?zqMfXzXCRpFnX^2gEjgdo0#bccJ|yTKhf^R{IMi@8{8gYTuPIrlg|T`%@(wL1wH z>!+=PLs~nHogm+8;z^EuQ`en_nx~7CJj_b6E-#DdSE}ktGM`ct%4!HG8|@U{!0}k$ ztLF4mY-htJMJ5@=^G@{3W!yt$VB{p0y(7kdNxuPtMpEh2SX}TM>Vg;}tiRkeo!J|@ z-?^Z1rXMnYGy+3iXxM)oKPQUX+olqX&jbNqTR<#L6@#tzOWba}oSJlLyLaS&J#gMZJ~%Dui}wm1K%siz_DFMY_lSRlz#~ zHAqf`xr{m-)wci0Y9P4rLjG>e{F)W#JND_=Qcj8kQJM@6&(BYFc;0FsS|5L6<)b;p zuFvp0&p8YNKAW0v)iWI7@r@faQ>`~>PFU(sXro!2=2aVOGRVjtI~pog2+NuS83iP0 z^FgmEfLT`A9{Y8R8RM(Gr|g*g{1qWPx6R`(Y^$-(*niJSf0V11rmtzK(=+Mb{UYO` zV`$^ID%&$*$TV5>JxE1m7NL-_DNd-D@`fNkICw(LQY<+peRBZL7?MK!KO91pZIi&^ zENx(OW#kIMqX%(Yo(2`00R~o6WoDY@b0SXXu-(q@c!#x8B3JhNdP=f>2;KV@W1y~t zpl{MLwj`~z0jPA)79Di4*d}%|`b#eVB>+ih^n+X_qJL(85crv>x7jmfNxUTSh*uaB zIa||j{}^l1!`pgQ8JI0e)8zS{yF56>0@N^2=qU$eYV z<=i5^)rv$RgtsG6I1svp$s4j_4a0BeY!`K)6ciza`VX58St2CNfehOdf2seZN&vp6 z42zIUU^KE{UJ#SLaL8WpRnbE>I^e}@jAekE0T5r?Pa7WRyvew z?Shn_D&i6uwy_eojm+VhZ z4-0cnY|rEc_NNs0C-u`^Z>AL6ydGz7q6lEGmR=fhZdJj5S8l+61}W=}dNKFjzvlQ?bg{tI;I93)Sszj!|LEmj0x9 z34EXDaPvI3L|Kty~&LuV`VAxc6*UzstPS$!? z39q@iArl)(0bd<-gf@IO@0EO*za8ERmg|g^kS!vE8M?olMIxeJmYms+6&WjTPlE@i z@F%Zoqi=eP2@={+Bf$$F2zmkP2;AGoQ~IjopWt zrG#2*uH*Cll=E-xvTS`eOR750=dSv3pWSqOZev5jN{TENKEB$_4 zFC3mW(S5mBl{xQ{Vig*!nmWw-qjfmtc8&j;0Y*T1^V_r()tQ+=&esG<>KsiHhj;Bv z1b5ajh^(et{u*QSdml>zra0o6rP@}eIjzt>F>3c(42kC!YwIHJ#UqPgzBuVgmaK#+ z{PGjX&SUYbOp}&;{@887f4$9&6S+hxXHqA07rytL-Qehz6MS)cAmOd5s7n;7vFxi; zQmxa_GjYR_T6N%}UByE}u-`nVNg?1?i#7UJ1eUWLp`;ers?Fm%*pDXDL}B_X4fm3epNh#LS zD@7ic4{uza`4{QYVMBvZ5xJy;e*Pd4XlUVOn4xHGKEf58zS`e5B74qV{ySr~Ct35R zs~iz{iZ$T!wX1?ooAL`klnMrDK|VT>7d6io!E+7Pb#a9N?gQ6j@Rr0cqB&TcE53GFrI^ZHV zwVJBJ=fRRjxXQUxc+|$o_*^UC+4voMaWoTG{!Ny;3n5tlbH0#a8`8^kisqFApM^(h zJ@dk#Ud1oU1E0f)EbP zUgjNrrzBENZq9aA!^94VL(fmk$oKxnG1c!|yzed8>q-5LS5hj$)Kny^s8Jd|SsI)5 zp~x@1;@Lk5c#!5IR-Y>nH4TjKtp&!~p{n?JZ=P6QKhukJG?HW5L~$!--tr`n|67KtN53L$g`xf39hx6&1T=Mjm-k+v8jjFV;Fzj?rY& z*BIY6?`k^?Of&)V9f@?t-vKF72^h;SwC4#Wyhr)Kcf-lsc``peNy8MHrcU zt^)>@2Bz(4m(8kE&Q|q8HQ19)>goZ8v}k5S7e^i0C=2FA4rE_Ta;NmPmPI_t_MPTw)|&3+ZoA%z%S|)6}=B- z5FrKr(4nNlGT%Xy_im6|7CAzQmleO;b&mCl5Njg%FjFL zP%gvtJI=~lshR3BftN=eyy-r~*+|Q*luEywxY>~{<^~Gun(Ut`tj@t5akDB~;Oq&^ z;{59MR$(lNVN1XFPV|JysZGg`Dw#8-AwCnUt08_}cK&hRBNI>U$I^+&&Af@FL#qvf zzp3OTtA#J1udLs>tR*#Q!r+nDlzc!kX?ST3C0Appp)1KDR&#Nrw8UJuiv5U#Y_`BHbw z#%-}b&mE3(VF!J9zgJnyqYrMU&4DUmKKAXMWTJ&0P6>NNTd`x^EN6T!7aY_BE=V{e z9&x-x{YnENVZwF@Mrlzf^aL3KzQj!Hn&EqWv>EO`b{L8p^`ux@F^)o|u7vl&N&z1g z6i?h^1Xzslo1{53M(cQ!Ug|-W8^&oa@{0cIdJ5w$BfYoT19`iBG-Q1E%JAC}&+r>B zQ;EJl`kZhUdU8wJ`ixqX3gp6n@dcd|)D1`dvV?zS{G(Zr!nz!aHWP^5de+!8rP167 za?mtaDDBUu6wTFc ze>ZiVZ?_*^2>*ITD=MsKf70dEkv=$vKCCUf^;W?QNU97i2qH>Tf7$1|1BhiG zDIDNCzr%|;?~{1PyBq2k)_5M;)7~$R;JKHCfsXi7dN?~;DWo>J%>ek7JJCsCyburj zsRG`(6zenU-R7}qWvuu2CDspTC6t!hEC~zKf^(%liB`+}YKEm1taS_Uhz)zW^#`2t zjtl6Tk zwS1X@$xSoL#9^TuiJJJ_X{%u~1HU+AB+`yP*X;ZP?oF1i6LdS$Tyw-F5=e{?(EiDr z@`wCLfo|YyXh{(J+5P$nn(FkYxWOJ>o!=2hZa{R8-hV17o4b z86@MSu-!`~yy+~NMelxd$nOHRqTb>y``?VFev8W&LpAn?s_&X<-`~}^b?jfy-axWu z$sQ=w9B-IquBIlWJK>^nV*ycu>r=`BKhGYVqzug=R}yYG8-fYbaeqJ>r!Kr*$GOzH zBf@|80`@pyt-#Of*H{Ke!|$r%?GLD2wF&SyKX_Y|yC!eec^~@M3|Guv7ykGW)A$QJ zwUoaZ1XO1dDU~aG2`g~7T_vwhvp!E^kyN*H$XjXI)d=^Pn+l`bA_+^AfOTE2t+n}; zC2zAfSV^_?w|MW1oMeGJDsfVqKG0I{S)jV1ci|T+nz}5}7?xbk?{b5yAisIV>re>f zFLEIuy2FBhg`bzKY@!tZZozc3Qd+@8$5wn1B~W{p^4Glkj7Hk36QQxoOg{kAwWIgo=WxUWWsb^BYM4o{6Z@w zdS$Ec#1%g*!|~BLcqU5AVFYz5y7003yxiRKI-IQ_3D{ViF{JuTg1V9l>a3W+*k@+a zCc`{F;p7Un0@<4vXz^O;MwR&eY{zD`CYr)J^slmSKD2G`Y7bMdIp z341es0KAvTGVDXN#ptr^(!myl5+(XeFXSM|P25yZ!O}jPoUheP<{;A(|DoGB63qbS zq*R3l#}x{Ik1QxK`sC=&f<+rD@Rcm=@R7NB@@=YqI-c^**>Fi^9MjkfLASM5$viv0 zQ=VoHu6Qt#)3)hn4LJ@r4-TihMv-wh#=1?kHQeUurFRwilmIjsPb4e0s+=eH4nwPB zvJ8?%(PC0}8J@^bbvMfKm1w#HUj8<4V#O*V@(d}mj4XP3gv%)4}8 zI$<)MURm>T^|TlLh+X`GPg2G|!R8PM3LJ<5u z-OL;Oezs~OiS*ZTM&vr69^T;|#k%@+F@uH8I>1)T3zbmnXK%_05izMzZhYsKWPNBB z!O?mpl`~4S(>m02@Z-Ace$+r7##tjRYGn@oGFm7q_r+rk zw@q{y+BACl;@er_ylh2?yl>({KcU|e)Rc__lFs1zjt~!7vw8ZN@#0;XoWoue@%`4r zdBZ2y_|tSm+#~Hu_q0>j9<%&ddtJanTeYSNQcDe>(Shz&tqxadi=+aNP23N5J4#-9 zlVF2aIosKELifpJeU49B4_Z{|GGi&{^)x7`S7PvhV0uUboqFjG2iWW>37~OH(E~^E zp}9?b7BrPQs@%nVwxK>eT zN|2B|wNI(kLW+tqPTh*{ZWIN*uX+xB&dN4Ix$Is4F=JXjc7MqHSLtWvM0i=e?Yw<@ zZffk*{kUYPX7bu0b4Brk>a5@Jw=(U=Ep!ooS`u+}l7`+t~o&Qvw7u%)jn#?{yela=Qe)xS# zu{5g{X^Xe|W(h&6WL`Z>II{0x5)T4>W4iXdLbs)Vo<8IvUertsMJR^!R$% z%1Y1wdW}`v7U-OI3p`(kw1(*)f#maiV@6-7om1-qsbPGl%8zt+#YaTz5Zha7I^ z3Ex3-f#2ibx>%9a4>Vl-{Ha#^)-UEYyA%ywP^_3tu8@}v{b9!COxI^y3LcEO= z#aWrJK!6lq$c1Xxw;X8qbKeFzCu6GHa081e7jZT|m~@@p?cO{*qqVang;k0)9C%m# z-RKo+TPN*V@sc#HpKP3-q8=Q>-im%q*&@$D{gK?6qNb=Z2WH;0*0K`{7VJ}4URN^0 z*(XgC>Fo3VQ;~}gUL=32X0@3m@*;0Z;kQB3(4Y~Y2)c|E4wEnq(E|Vnr`-IH?Ycw1 z`H@7Y!Yx%^h?VZqdY&dnyFik~gSflKvG+Jzku&#B!1{YDW4o5VC)gxL@IS4D4XGu_pU0frAN&j<8gUuZtp&O*_exN3 z@z`F+q}po0=m?K9f0A2!#&PlisnaAd6;IQaQ7Yw;eY|4uhZL8)v-RT>Hm-16LX$R) z-XVAANMTZ2OVv8mumJogWZD`@j}!#H)zJIkuTJ{n(FTVX9i6&9&LRVdymx9;_67?8 z(Q?u4dziC5sLvImu?~E~3;WQR87)AOhg<#yJ;ue}S9H}+jd#O}@R!Txv9-+4u`paO zTB7HH{((!U8A8Yv4@iKfkAA+l&YmxEit? z=}GcC1}nVD7JzaL&YkO(z4Ht;Rjx#iI=Uj4r(~mpV~TgEjD~ z@8#9qmDCLu>&uCh$ir@rQk>~qwZyO$C4#X#sWRk(31zJhrTr9WxoY^zeD>a5at zCNtkzlqD1c9gUk(g8)55KrVjJieBwovbj*Bi&Xd2_{Vh~n;2z*^06}Kr&PA35Q3^r zeiw@<9%hLLuJnQ)S)+W8Dx>G}n<$~R&|j&M6_(~aX`V)6PDYFUU2Q3%m8bJO0&E%V za$E1HEXp-Fa6i?=dDvHs>e7;P;(+5r&|$sX#ijFg&ye72R8$lh6ZyLExi_dX>S6ge zgKTGa!tqtj=_qjk)AJUDsZ-6Lfqx{|dkMU%x!EFen%Ty7dfeb-XW#05f9d?=*=d&c z8n65C0@ijtnR7vm^-9s6bh@od{TAW8*(K{|nokgNYr@u)KF>vb6?lOI5CMr7pM3{N zCM1|MHpGL*@bM?pe$i9=B<0t0cX5YcGG278D37Tc?H9=h$dVVe7< zi=(1eUUiz!-J8KeLvK=8rQ7YH>T^k_A2Nwcaje*(6MtLIIW9IhbDq>TGNuXhO-Z}+ zVr{&W*dIzJz+mMxfK5#7hrq&=Xr~ou#08V!msCwWfMkVkLz`3I7hanX77?0$aTYUB z{;Dtrc~qh30G1%bjklvib$89@W?RW0b4U{;u8;*O_H&Ut+b+qkKLyv%vZFk{oR5PXbTNG{hWkc2D zyjFFm!k%_K74KImUMjGCM0-1Nj+6g`MeGR9mH#EIvX}v{&>~+*nTr!NBq9H`ATMrq z@lW?L$x~AQ`fop)`xo!7qp{rX*psYGhL5V%UUIP_1h9Cv(a~^!#xLR0 zwD0BqaG!KHEosI~*d?+s&P@_L?RK9xu+c3y8qUO?c~T&MXp1_e9Jbwp)#&TUQALUB zR!JnI3`11}>8;Sybx_(k@6su5I;i8I1xLFOCY6V@HQ{ru6h|7zwMp*A2x9hnLjwc# zXUWX>%#LXfSCwm76N$Y@yQ8p95@{Lm>d%g>VQ8ZFS@e`h{W!p#1zB|qdbbN4>4Xqm z7dV4oWxgjQMah2kxq5A_kCS%^XoO7g@FYVZt*8q6y?3zlX{+KeB$FiN+TihFQpVV` zV3VP+KLckIz(FnVgyc4KV4KTSRC)VXGWD}$_=*i@S4j@_9k$Nu_m20%kSAUo6E0si z_d2SCpM@uEX=9i_3eU`jxnHIguYV2~lxYeg+ku-ul1G*y^oWY6ZP$qBB@}nl>vcHL zT4~KsSbwHn8onMRy-xYdl-vT?&)0Ycr3X=LG+x&wWN#xBnP1?(#FhYJeX7w{zWkms zfeTlYqi{ajp>G&ADjVltE_!P7 zq3XMP&3LtE+19+Szxjst{hfJL0cJw}~F8)goP-fo&Y9N34W zKcVjEwQy8rYSm_5_#=sTD7B;1?2849CdD~%Sl=)5#xx2u=|8F*Fn#9!y+>K+V-OO* zKtpb&&ay7Uj~Wl^0a(rir3W_oi7VpWF2a7~{rTs!R#i>)*d1MyRo-$yJ157W82^~i zZ+e)oS-TnjUZ9W*F<8$A)FG2vssx%IzHmhFOB4)9kM`rw%4oz*5$QaJK_lJh$Sn7Z z07)dAZzF7HLwpU=CS zA@ApT2D|sEgAZe?L{96}Wm5+GR58CSUyx~qdEUpsQZxkl8$YF-5-M1v>{CRtIbn6L zV;!fmKQ%HqVQ$F62|+A5nY=9wPG;B|my^V_$aDjw`Z#KfCNf28R#(7 z_gOBUEWj0_!s7!4O^2IbHrC0oz1x%%KpG3X)fkp8-fWci?<4O`Vi4rx0pk~O9{ZAl zc+HCZ-MP?c_;(Rb3BhEhOX1F`nomoki6+rxqpiZW)&XwV&r-+=54V43E7v6|(>Kz{ z+dUmx9WU0LJ^U2g<2tj!|U#{r!XM48J&jV9k0;S@Fc&Js^^TX)`0teT>)>0 z_vbE~;m6|T$N^p?0d7x*UFV;{F|W4?X0NM5v{Kl7IhxfcyN0M(ZpYEjOMbKIYpja! za#UGyrStH6_vcT)GGUZ&Dp_(n;6w*AU70j%-^?(Y;&wTMic5(~*t6{wBq@NOw- zd-DO1n$d=8xkVMm^}*9Ths-X&&%$4nbxZx6fv(#Yt7o8&oz_oBkV-+-Uqcq?k+TR76jUa z6QQ#aE)dtNp=~OHtQl{0&-Z{xszK$dFz~6ygj}@-E<)5K#DHk4hv!!GFbx0+F+WZI ztqzQ0&(x^BtcZD+0>xD;jqzv`?CFjuuNXvo+)jU7-Oowh)ZP2~7)@sbUXpt^idWIl zqAwX`8@j5X$=3{I6W8MLW(AyK5dJ?cfP|C3T{i~F)9+6fOt)F35$r)7)87U5VW0uF z@6&tqU&k6tBY5PvJusGgHwqGx$(%bvPeK-hCKM5D=}G_y=`OwjycW8>8H}*!rGqmO z5riMMkY(%UJKb0REXnFla5`PNl=5Yt6YHth`Eq_&s9t8RgzYUFrDMscj{L=2`NmhL zVs$KyTSIrHIb>6KoN3BCKFN%I1jqFqwr^wmG#oqoK3cW98vA(;z$X<+Q8e=lW#{`D z@_fH~GYz4=5CLs>AA+`=%a3^|m<6`IjCKjf#QRAY4yfT)Uqd=E_xv8*ULYb5)op+N z-61l>LpUnElw>E%d%Hj+>7NDhg52EP9!K7b%n{!CBndB8(H<)lQPZBtj7vWWfcD4c z6s{~}I)stfR=&rpkt?DoeJecvL_8EvGeun~8>kpq$qRtqnmz-=jpBJkAXP@NSz26_ z-=W*E=7^{UM1L^E;=AzPrJB_o<{dp~wwPHGv!k{56W3o9aa=?O;X2cyIH!&Ef67&M z?T9L3f+@G+j$`1GfPY;_8P@~7Un$l&*5gh45(6yMPDDbKF4bk8tOF@r(G;vnI)Zz&j>)ufgoHC7esxBn@ zNUF*Hh<&c^P-%#SRZs-%e(~$@Mt1Rf=@k=Xr%0QN>ztWEzVME+B~sA!Z`s2rnUxVd zXY9Ktk-1xZr44nFs9yt7R!sFDA(Uj=36TySJ0SK?@Pr3+7C|1iayE+~kf%}5fGJ{a zgz|`|op$um^+sy*7&7dO%y&K!8`all>H|zKyw-}t(?IojV9ioUZyrQk_SGFnG!o(D z?w~DeVWe`>l)$bOVEVq;RzoDXO48JDKVx%)!D<)Pp$mUZZmrwk%e2jE6zCZuOfBR~pK?iiP{fZnNNARR^lC@TQ2t z6N(c~Vq8xSfs?sE3G#@dSDN>fi@;u|Y~lhtAIYZQbLyJ|opAPa4)&F&C?6ONm{gAz6a65K-*SB|^ z!ZzEUpT!L^4~lO%;iz-K>Kc&J1ljt;hj+=S(~rdu&~`-ZvuS((VAF6$WDUUrm6cL2 z<-ti0X7X6A-BaKc%%jr^(}RsfjNdGcJ^I(CujRWs1Iuw8B0rqoj4wXV{${++KT}>7 zY7shRi0R5d1GXrZ!B+X6uUxHEy~*ax2Wb`p2(Mp$Jkt2xAH{U;|J7Oq1Gjv17q@`R z9}8jfb*$+8s_V)Sb$#B-WSqJ>q<_dhEIdw6o!Ol|VH-L;*0_1Q`KnYSvxZQfPhkgi zu026HiDbn#4Zdwk`R!SfuYFm09g`}eeGR~Q9BK*j*)=ni?p)8m7v#3jg(}zM(lF3^ zs{Xz3p3RsGkLIDh@KMX)b&LHF>%$6TD+rtY#v-D<3?myffkkb<$9Kq%Hp;$vDs#40iw1#*T~Kot#^E3 zi>=ZT$Kg{b@rqNQ(3s-ooN{ubqn8^yTvJlFmz{oGQChHiqWr#zHQm~I9e z%!jU8UG5;7D(qhE%%m9>_P2(8aNI9XIMk=SMdP>Up*E3Kn-e41-Ka)5C3jWM(%zDX zaI(C>p*UXQV7m04Z^|!W4gzoVW-adEzkalqjFYt(e%efW-}Shn9%w@P`gF<1!01Uu z_K%fkshN*!`-O)0-H%0JA7&(W{!7y*oUhB(@FZ=u%Fo(6M`mL?HSPw1d6jtyiNP|} ztyxs;b`b!5T|ttF5t-J=+yrtC#qTd61~Lg(9()CLAz9Y7HCq8S>@M6lCT3WU%u<6J zkvUFMT@O?zHH*LX7_ahHbJ;%!du!DQd8@saw%O(IJ#rkJuYgh!h9iy@N^p11{g~lF zF2o+}v>y-Jo8A*_@Vyo+X4F_@?VHTFm@odO_hCFqVu`qi&*HuA;1Be*b;tze>K_;G zeI{EY1A+Z`r_~()I^p^V`P-Q@yC*q~SrmvZ`b~YwI5y9}O4h)_91vdcwgKm62QS*t za&IE+T`Q-6C?*@W7MlzCwuUrURbIOXbVr;f_EQ;u>8zCl*c4$lDL6x>Ae@bYD}D+a zQ;vnl5XeZyVLQ$%REkv|TYoLn;PxPBmZb9%f0nUQKZU&ATVZiwzYv$XIg@-X6U!dF zkPQ4{XRHjXdH$?rh;rQez3oZHpGO3iGR;LEC_F%7u$dsy#{Hs5K}!A{EhQ!3_ZYGP zCCREY`q%h+ilN>d8>47RAbO*S@xh7QRNl55M9;mbgYO@VJLnB)w#cLJoIb&9SNegs zst_{G!t#@Om1$26VE9pdllycf|w z=GC2kEjF-S+NrJj>bO=;t_^Xdb`!RMmTr zrG#fcR&9j|*T)*~c5#CP3-j1h0WbBhEH8dp$epSdMyHqt?@F!wp+78^YW+pmM1Gxx zFX@~7;tTtB4sK0*r?;mI)8TaA?#c93kKRAM={1i|uYL5|^vIP9)5*>2)6M5TtEa0J zhv=L@w!x}zOWR&kAH zVtWMT7v}`?fVU8?!@@w{st4;6*sV8$I&GE~3+<3c*Sxu8Wj|!F6>mqnuQ@WUYh>0Vv6+ z!w$DX)KO31r8bU3M;(V|+pz-gtYk=;Qx%6f>L;aYyE6bRpKJ?k z92N;5WccDRC1LgC1JdAC^5_FAHYoh@#bU#WVIQe&9_tnsbjhxuS{0IR|E@DZm;RjS zNym=vS523d^q;$Qb=ulLuRH8V3iNp7Q^_)cpXY$2iQMG-j*@ZP z5s>5P1V!@!-)Q&Zf*gUwcLF#t6|)}+mtNluR07Wz{jreXyUj`t=pJJ_9wYaiQ3c5a z%`9+{%)_&-pAsV(hkI9_FW=YaRrh5_5$tsP`is+xpZ&yiL!URl_3Wp$IPjeAWbs{8 ze8V+&T(#&S-%m*9guinZx@LVk&Kt<8-}ppFRc7u`q*i-;poJO@;G~0!vLH&eEId`J zxl0*7^%q%}(Syu*sYnymJ2q=}+loO&`zv0zTc*aPlKi2hWpp09+nPW0%?UXLZ8Z;> z(?kEDPYggW?ei zT09b0eOv%#!<6;hZC4EFucWx=ybaREncMa^bWvfezP01k58y$DCihEPsK|GkO!rYE z#e}Bcc2oy#j3s?J)p@+=A0<21SPePRm?S>`7rRKH8VR-??xw45S`%4-@RI@1#Z%hN zzU)SWDPX}EvekaEV4}T85!XZXF}CB{*f5xJv4tMy4au&koJa19%JpB0v8#ng#-v`g zkO8(l<+i04lWus0P%UoIXQ;>xs~iWNf?7mc<|h2b10N;NQ7UY`2!@*$_Q+Ba=MeKp zpWuauP0W1J=4$gfp?13`x>;d^R~4{kvl*8*cW%{=#c?)#taHhe&^-ow^fN^$@SP`C zXkLhHgQmG>Rl-v=-YK`Y^wBDf$(F9OJG$F{VbbUMw@;>5T;7?!?kgXf{)N{(Hhsl? z7xW~+O(p%$Psg{lh^jmNB<*{QskHAZvA>`%{JZf|{lx3#OXqd2?o2ntcl%a7t>UK` zG=6w~c%V7Jb%Va)34T-2MmxIcGhZ;w!tK5m7jA1YK~EPP$>%3dwod-rf8!k={bdVe z7X*U97aV~)8^7Rcqc8~E+X(#VlkfXBA@Cn-<@@^-KyR@EUU&L+mtSwfJj!2p`$^DM z_5uKp_*Z=-_Uks@C<(^vV*tHKpn%$U?w!0>xnv1~OW%oB{=Fc;f`Rz;eFF|6z4}hV zu4IlRf5=tB&w>FjwMmWuq!t5Ih8H=}>P=leGQU_Dp7<=U`L@jnoUGEa;U=KH$!tT!ERC6`_8zP+I2Tn&{diSC;G-VJ_6wIg``gM zgfv)RY>XghEjcu7`VZAy_yI-(pDz0@Etn7#_f|H+nV<~0xka^s0yH#N&_%!qfT(A| z=0uB3)~V!u``pFp;(ZTIS08$8y8N(S4?dzh|5p{A?M=6CAM0`LdNkLjP@}(koU`tt zW1i&sREtQyOHc4lLL^^E)VZTiP-qtj3`H}aWFV3t(x>A?J%+D32^_rep_fNWt5?Ox z9IeFx`J%YjA2HCpWAVUW1n7kcNiY``r}LR}#%o7<&!5xJ3`*OvKErzBxz9~6e)<#B zO)Unz^up)-c&l2Zr-EsJq1_r@X<2WeyGEO~4I02eSZ!5BipGVZ3`Mp;ic!Eo8J2q@0gzZ^rxpieH7r-i&q*8 z5(sVO*BwXu=;k_ginR#H2otcNSHLrL0E}I3{zA9D-(j7`S2 z=JUCoY+tH7$kg@OB10)oYTlM9l4(s~n3}OYUAL!s_O+G6R@vP z+n$=8{Ej(SkfOg>IL_O;lig>l5yP6V@WVzkSpgi3Wz7V}w0xm)Xz8-Y2U^p0@U=#i zwH;T~)?AxysJhDrug7ohOU*BEgS5t9t7y_~353L=37~`f$9X9k{V1P2Gw zbAD$!e|}#J!HQq>9>Pb)_Qc22VEZ~AXpwkN*Wqm~+B%+**bzjznOLJ9&w;17WS zmxydZAP9Vc5cqrV{<&{gF!rA+N&hqT*?!&CC%M-f9CauCx@$Q;_wNK>ZOan@+{IrO z0gm-p9dDo{-6Z->{^9S}=3)SEu-#^vu6uETyS`<=68K8cxa;Bt0KFqu8C&Cpu1@wv z(|h*3RUkE2U2p)Z(wcAPP*72Ki=mKY!Bw1&Qylaxv})tt1*N`B(M&MojU<+UhXhX? z4k#5OtyNgeLZzXmnrfo@{fs zSHU33qXk8;1ps^}@RQ#t<)1kxgFE8qvFG}-E9sN07hc4KZWanyz(U^rv_G25^qJ4D z*JA~8T)np4*01(a=hp~WSlH2>$nE3Xy5sff>A8RMQ6-Kx~TPUNFMtMBfidvdHwrZ^>8JZg(G&*(OKtq-dJ78Y5vCv}ubX%{{ zM!AjqK-Js40Koag0t~stB3SaAhs+1A0gPpDwvBJ4deMozUN#CZz0$a9{xNy@=*juZ zm!|LfGk-;#l~4wrISM^|<+oKI((gU41#|uD&Srl#dPJnRK1$eP&yC zfoowCHZaAi^stA=V2t_aO1n_~E*ZwiD!Z)?#Z8;!?Yd;pOoN{UFwwT`5_C4mU1m{d z={H`nEr`0hu`AyPsVt1zaIRAgV{nhl5oKO?3-&}_ZG;XZ`CJn8 z)@7#&`pRC}K&RTx()Lt_Ww^8WL8){(0CnI$e8h=r8`?{*^><&YtsJ(beJNRWTN|Md zEqXyv5a(pc{ZhS{Yzc1bQy@y$Dk4VC|CXg({e@X=nhR_sU#BNZy7wvLc`J*A4GyG&<0YSjlilwK5Q<8J}D|#&qpkI7iG=T1p7StC?Xg(e4 z5mJ4&Uw%3tkYi2&4YG7pN2H2E`OKX(?&R0Toa18x^#sATo+R*R^Oaz*sIaw-pYZcN z0?ct9E2i^G8r4@X9Ed)!@Y4YLSOC8BL=3PK&pap6%6m3988~n`Xkdn{moyS zj;?>U^b=HjApz0Cfoa*pVyN2TriovjbN5`bSA%7BWSnb8!tYmOQF8!NVS~{8bBChM zQpS?jvcZ%XvuV&c0*g(!(sdF2#6&Lu*phY}hkloUbc1Hjp{bA1)Mpk51kCuUJiPI@ zRw%(D5g=FbSn2Nn8^7r-)7O3DH%^~<_H+96hnv%7El54~@FUYN|Kj_nr+)oc?epH= zdCf~{VIfJ$fzJ!+r#l9l4%@ETT{fl1$MC^l0%Bc_iyPtA=JrNz-95`n8FRo)95Kof z{<^!(XTq6FwFpHg%SZPYUy}?Hjy15Vy||R z1!v|TZQhxsn<37;Dww}$)b73woz{W4Hk&Q=*4R`X>`YaA@BXx0;RVl~d}6R`qTBy! z_mc&XJpUwyVQ(CfQKRMnPgi*E880Q=YTecKclYSVbU|P2cj4%T>1*|v|98FlYopKB7v!rWJ3jo}h;JVM3_|bRb4i;y)+t1SgJQ2oRXXCA4pG5&p zIud!Fvf?}^#(;-KR%x@JoX7aT=S2aX&$_nX)`G#I?a?;IgQo^K=L)5|X&`;{wd}rA zI{(JM{?6a}C49&h1cJaH9DzEM|KReG3CH(dBj&Wixj z<3!%PB>t^u)SWQtZPdqFFqmVD9?fxKsE~s_l&V#^7}r!N4!&mIYF+ClFj&`-A!w^@ z*m1NV5_gDyw+(&*3<8DQYH!0N0GMJS z$Vt1t_5RXBub95#jelag^4RO91DQJ2lLHm331?KxZ$BNPCscNHcb;+aQ2`!z<}pFC z&*R(mxqar4zJ>qBO9~Rpcjg+8oiYO6?2pPC11Ayquc|)>Y!;IFW|ayr7I-+Nfe2IM zRY5)TMq?~L{N#Xyww2KD=yCBK9r^9}Ed`GFxuq{KWFdo(2UJp4*wQ!t_<2Hfqjy^i z2`pTYZt$Z3=M=>59KSR@^^g9+^qG(RV>zb2s6X?<1kM61JNh=pvbylQ?qMAwHRmf? znZH!b<7-f?XDnVwih(RFDhQt2xl8B`SLA!?6=kTgf2vTo-^DJ4&BQrYXG_@wXTGPP zx;Fepit^@Ggs}j}0uS>Aeei;HeP+EDh`2k*+uD zOe#A5Gbg-2)d^UAe?#@J@MB(yU$*(evn~DfBp=hlKA3O~W?K(|7Yf9K9Oqks`Z6!A zbGS1SVQ^rh%N}+q-qu}S-Xr+Fk8z&BAox5(|`T9{)_2bzU{5kt(&)|_q_M#rvLoE z{O_id?aR}yeno^Q0X(kQ1bCdZQWlVyk1_xqjJr788y?!*;RxYCI`2 zSlwo&sJc^2%?o&5)-)98INIxoj#jvV>q=lQ(ko#t<<_rxwRD6w>dW})ifA9VP7kK@ zd=HB5`0w6+QOW;}>9zNtpZ=A%zIl4x0~e?5o6k4(dC8Ljd^eHjE}lt_gnx8LmmT59VnFdZ@z+8C^JiCg@|o_O7k-*R zx;2Ajvp(K+AU;1CdB`FL=RwIx*b53!j<3-Jr1_P+_YwJ#*pG#Pl7S8%0ce*Me3}MbWheW{s~!J%vvpvy z8bj)SQ}06sk-XvS&D@PE=9d)-ZeSails@`RowlL8=-$t}4s@*H&RxlsRL2~uI4E== z)OHagKpf)T8OKTLv%djaK{VW=9 zZm>Xr?%s-TENYw*l=_JQag!j6lgEg+mC5g`U-aYLrHlSGgDu@%fb>SG7`Y^(Zo?f%Qt&Ch*u`i-A|&vf(oPdd3{VZk=kNxWH)-Nrbm&AysTr5x-lFlV?H zEOWc0HiV3g$HW?kE*4N^6I_=mIr|LOEDY`QnSSvc>Ej#sJ^aA**6;qF=~!d%!t>8c z(bja~qP~)hxu$E?IslTzJL<^nCDvTF|O)! z8*Ha&m+x!$>E~VR^qV<&w@pG|(&yhY)-~^!IYKvMrWPy3p<;VzW{3&+ORV*`ew*)Kap zdv9h?qh$th94*n6g~26ox2!}(=;9FM?Z?S(BQVoP!9!r7I+LL5idDKao@Xzc%VID; zI5*btxIY-vcyo^NDE;o~bbeds%E9&Nk`^!@-aVSW^UbfHzV!{S(og%{)R&)rdOFgR zHs@I+m7|OkkJt0Ledf_f+IbwGYwocUbrODF`W(JYp6Twt76W*kU+45d$v^!ko;@uX z@YKMOo)GYp0GgBI7Xf%L;5%ZxASMvTBA7@n`{!r5zN>GC!r@3iMSG+L0mhu}`WnLk z@DdF8&tijs6Z^^kvU9NYw|?NKfAbS+%@zcL!0!Wr@x0~lLnN$0;NC^xo$vgI7f<(Z z{#D({`fK{E+_ie7zY=l_FpXf3GOn>F5Lz&RCMgB4l5*L8Kx+vnSIxGWn22W+ z1h`rZo&GOcHxzqY!UP+A9kxsZTYO~EN5Rwnh3P>h|Bt@$o2HY!s}8JqNOVU@F2i)p zmp%~y>P7N@tk3E4nb1T1WZse5PDuVW|A@T&+w4k;2+j%C$2a-oDR<^8nQ3oy9-N&W z)#sD>to;dJ^2dB6S=0i8=B*PrX$DVpo%Ef+EtSV-;CHyQNe>mcVuw`cOukBuf6vNE zuR6;229RWuiJt1Q<6C;MC~!kh0_X;C768c|Be;}^yH3)ghdM7@lq1% zCkC{@L8AGYXRc3==(`cV;ZJ|x^y@$OpZLRV_}D@`G6-%B)g|X|Aw9>A(8mz@A%H?Bfs|H>0`h75zWH`k1f{~&ok++p=M6nlKbLw zk9h%UY~}i>`A7nC7xD%VDr#YBkQ)PorqL3ElU5zETYcx8;@VfJf?*E{OtVdB=(mkl zU;38HEH}*0(k17UR~kr?H3({zUD@Uw!#d}a=L6S0Q|wmz-Nrd^t!T_EfaKK8MXO^?6!@#zg;^;KE`c)!1pbW7)_ zzeE%VFbr1i7w>^!Jr=g;D^9g@eHhhhEFy`cueS)GlB#`!JOt5o=l1fpa;xdKU%IrH z@WOw}B8IQM3yo5XxKI-Cm0gf?gXc}r?zT4uG%!}$wiz^ah;Huf>H4LQFYVoacDj0c zb9(bDADF)PTi-N2tk3-O-6lMVxGVmv=XKXzbDzaFlKFb_g2()IcCwftU9%l2{{Pu~ z_n=RctG=(_`)w{evpYMh%kE06)rFN10s)37V8F2f8;md@SGf|GE0u~}aVljeDOX6! z2`QIDV#kh?a$IpLRq-EoC>vssgo7n;1d`0f7>r~P(ylHbt)$gn=05Y@-#4Gn_jEtM z-;5SJe|ojQo_T*yU(Pvw`gA|t=k)Da#mM%;*j*-!Yl}ayEFPGrlLs|1gP)ao?+r*B zpzpKT0@tnmzI*$89l-k8Vi&*>fL;(N{Y@?z++f$=F_#j056vNXhrH;% zTTT`@QDDoHUw0PJU$4XVpFLe~f8yQmeB!SzA8-B7-}~NQyOT^8KMM&gB=E15K<|eB zwQvi7g#=#q68Ne2efW=ae)un8)W3ch^A2`LoGFf>kMZEjezvqR$c|P1g4N)6W}WzM z=o_!m?%*kGt@OJ(D{jG#)&FrZ;Ft{1kh*Kze{gEGe@q8lga@n69WMRuq%a5D&A>2T z9g3y61`9V3NmB8wJfNphS=wOIO0g6VWwkgC&8*-RHoxEvrMN=;R$f6-uaVLIkcX5V z7!959QxQ>w0?1EThp|$oClW~x4ae>1ub_pzz=1zelZk#@38*q%H)X52oC&plS>u2_p0p&;?!4pp>05s5@ zXs9m%a3S0ZTm3QSmt67Z-hvfAO(@PXtMa)M0DmR`LaKHdI9X<`Det6NC?*sEWvbB|m3*49kQLq~hnUD2x(##emV^t%mD6An)BMK6Jo8QvTKkz`iaf_}0yKGZN<{HczvHMIstzigmZurT`eYOa%@p-^YTnzYhd+MXV z*{(kOY|3igxtqkkFYmJQ@)Arxw?_d|uHyE^e|wp$#2sWHDS+Wml4UO#-)o)8lOs@~ zk%wvzzbF{h3j#Z2YabS<1-Gn9htoh}1-D8C$jqT_!gG3w|opwlkxf zwnA`<0jAoP7?gn&(*_^I$JaaFkZrC-4DC)Fso|I_wP*@}L2^M&@ zyY#^M_B{1?=KTHbfB0*EtNrZH|1);zJkXBAC;aowrLK}D+9oOk!uGAe;&j zyelF*UC5&(0uSKWH=ZbPA_+Z3EBTA>`k5#HzWFZPLIMj3{HrBk7qf5+2`nV=uaLld z|M3UEj+yEoW#IZlM;JB^POj=}%*U@mpOt!NtzD5XBcG!I89W1Ldj7-{#_;eLtto8$ zWYG6C!n4VMimMfWjs6*oO4HCIe7RLv9K^?qKGI4BvCx$gScAg>m@RlvQ#mQT8Em1= zVF4hFWAUIFQo&71P|BB-f-mn~zomTjsEOVjre3j=h9X3!QJ^Ywq6fc4L)Ea9!cl6& zAP2wmte{X-LODW#V4)hTPmTLn}j$g)r$F(TP&8iUq2`6P1zx*_TggvgXMdGrE6&-1TfkmqJ`49HVp z);2eh6NWl|CleH!2D^2hZK%ECD|fb&vOB=r=r?wDxR`7Q7!~50pjcf!ZLhd=zJ2_k z{#^UqzxWXOaCUZuI|O3z!LM30@>UU*S!t@GR%jUNBt?!qd*0SxAjO@MQ?ZE;ej1WE z)TjCBjnlYBmMX)E7rM9Io^$a8Mn@8UBoz%K$`uIQOc|J;Wf~E});p8-M^JvG84#cF zB2@CReIbAAZ|lrfyY#Au+UuYA>bAMF#mx(zRu1AeoLDi@uP&b~Z`FXF8x zU;W|Y?del_N4iM)Uv*SC)wdK#l^LqpL6g;Z`QV@aAsaawqD((Ux`c)6Ub9JDMF>Bb z=(q(CC<~B_5uH5ghWY5vf@J~aJ8i7zWb+6OegZV3Upz^=+L&Ob27L10Jpn*;0I~za zBN^bvnYCs2-K7s`Ttatn{n_@muYF7VcmKq@Fd+BZ&;8ubw-5f}zi7*w7kQty8S8+x z?#Q)@ZCjHXeY<6}zVT-gruWgwDh#qu%tC|R?ehorZ%js7G%xXUA!BQk z2|038_we(58tU@wdn#OvbjFap>qL2Zs`cZffc?6c2u^n?K-1#{`MLvnI*DMLHh*2V z@I%z&XqMa02)ZD$4iA=p&-)0RY=*w?wN31RodfpGdrUll!h`~m^fNhjz+`~(vAE#B zpYh>`f8f2p{p-nW@w1S?LIN);0bZAdTS#Cbfftj&Pk!J7_bnZ){8t$D{|N)=x<-Km zr)QuYtQ;Wo$Clw?+#jO2*5p9Nxs9!i`I-O_e%ue>toYasP{#kvkWZLNf*AecpftNh z+4va##xYP!Pvb`SVlT4;rOvc@zi}h1|1Q@PN?}1y7|KbsXCS-MGmIW72@;AZH!Pdly!#^{qg*44z$MarD-QwZmF6Itg-HBahOx?Dybh|c0>O$a z#Ugy(m075L`HwK2j~R|&m1$N%=dc3m&xBVpngf|jGj;-;>U7LE|y#t^toFNGo**v@1ka$6XONU0~OK;6FQ7Ry8PDCB{%+S@Uya81>uR82LNk z)ZKlW)Jp1|uumWd6eo(-*afh;xy7m>VG>;}w9R<*Lw?Rd=hY9rnw8F# z_Q@wd-ahuxkF@L0Uk!YWA=&Nkx$p*c<}+Ny88g=(4M2g?ui0-^KM)b7%q7yoD~hg! zPfms{3~uUMkVVOH#z72MV8UM-Y^7B`LC?=%$yEKq2gcMSR*GIH%u@gG<5MB{uEZU? zGD=yNJZ8gDfEaqVPg6s=;QDXsH|6d4!lZ07u-p;RlLwSw#ox$#q`({aP6jS>9KbID z95ZRS%{g)N-^JKm-8@G}a7Muq17pBvLJN5P{&TB-o5`m2;jYt|hr_d4>kUMCm!iIb1C zE70(-bJlVxT+qV#C#F`T8!=zgco{xOaB_H_Ua+_QCnNC&NC*kD!;wW(JICc?-3Z4 zpf2Jr11AF3kdwQpJl7w&@oVYG8iOB3EFa;(W7yljyHmk7anyGg)b0Y$I#d4cBQ|b8t{e(OrE4oPmK6FCNN-3s|x~ao4Nj8{)qQz6OT*lzmm@F`rS+q;)A4 z2Srngzqji&JAmr3tLR?rx4gE~Ui(eo*|sk}oNbxA*RQw3-P;)cyWv?`uA>YBj&kQJ zzeX3iF%fXg1zrbtZnj(3u10}Bb)}zn=hk(V$nXb_D`ghT3(w>~EBGlx`K_~&W<9FF z($ZPD!7xGT(+E@m8ZmD7SIHE|$pUk+JgA;9sNBhc%zU3#h1KW*R{X4J6+lTs28n0Q ziOB)K7Qn;+-yYvSb03E3`TU*o1ppP`a;z+|EnV*1U9frPY&&!D{_yE4+MO?brak%L ze*`F#8*Edr)kwI@yV2{Q^P({}jJ>d-z>3YZJ%uNzvZ_foB$EhQUfNN~AS>GDC|nF9 z{O~e4Sx=e8({G!aQoqcj`C<8Vc?Q2iD%RzUtVx%Y!${kNO!H?QhS#b#Apy6YdJ!03 zn&8sKZDjZ0D__wrzv@+N_eS2V{D0w@FSXk@`C0_EX&E#wJRYL6&BY*b5{I;XJ|DTg zeWqQ$bcuGc+`jnP&$SnxdA8lYb)7oeW94rXTGyFSxRr?_`#&#poOcPqwy*4{i}~~j zs-sw{lrTaps9FIY7$pHn_{w)vreY0(&uiSvaSF23+>gL$L$Ax|JSug&tRZm`%+tB;%tk%T{PA$n|Wph zo_Ax-^Y$9?R8!96%LDzd=kCql-C^dIdxhY`)prg5grSr3{={wajtlPutw##%KkdWP z#^BdU9PzRfk+d8m1K-I~rDJ(~*Nx95f$UQ7t^xaWcL8`bK_1^&d*@gBK&EF`dyK$pOHQx*bQ zNMIoWB=Da1{laUHPL}=(Tm64<81Zi9FQdO3`!V`8)|mvrNKaafc>Tm@0>B9Z!tswu z0@H+XcYsE|m!egg+t{-8m~ib1kbX@XIADes2XF>BoiA?r60Dyw!j9*ZG$7|RkB+U{ zqZ<$t3Na42{>#~35)5~32Y-3Pi98jVN{%+rsm}4zSr6`fhLyL!sz36mEA=j3l%Aq* zCMtY`U*Tui8WI)u*5a;^sxZoH;JU%6RRCnSojNs3YIM=-8IIzbg8n8BP~8|CLKx)= zQ2&vZl*~J{A|r84NQ$2F3KA#JGp8(+xkhf#%^Me^_ii?OW?i@JyG2;fX^*|*54VkT zmoVgSw%b>)q6i{ia5WfKQRXzj<vy2f+1bzreSGEsavoO0GUX$w%EBgIAw5 zlMH1CSR=!QOfYkX-<7FcO33zq>((2zrRPOl8Z_FoQ9{X)63Pw^<<(;W>=Ibpxvy=X zzu3;)cYz}V8@zkfa>O}2;_^e};ynX9XYXqlFF)9JpZhGA0WtvqZ@Gt{2uf68!YFme zqYU^mY%-ZbzGkfgtdqCw9O(G+9M+Pk%sQ_obeH;0dmb_4DNV8c6JZ{Skkz6r5Wd-s z_t$up>~dw`!QmXb+xw*{0qFpocSb{|jEm-d6Z{td^SAmX-wOykQMAmezp_4a;lB3p zqpxYNef{gHzmxXDmFL?Xj*htMZ@t<7x#hnmpQvNxzR5(5p96gUOV72Bv+e)(l`HIM zvA*Sz+)(z#wH?Lyw?O^fFgo=hXWcKCDM+3rqqM)s8cF~rRysKS_8%oP=}4%ES*Mlf zjJQWlY%fFlN$Ir9cpmgCFQ&_Y9d!*fh{?jt+S5} zt@h>zw%ZSV>)W~Qf3Lmpxz8{uz-}6hYR~4YSICG4v8&-;__w<51%8!>7w&0L=Tbdj zWYz8cSa|4OZi&=<6Y@2DbIKxs*^Rce^b^dR{DpVD{}Z1fyMk35_A)_6@d5tHfsDu7%-)!kQT$f8|1QJDziVXi$ zB!<2s8!rkw_z_oNfjZAB4Fg}rrv`r0iC1Y9p#D$%m=+Rx;@}}qex(6UxKAXSg)}e^ zqg|jj06|!Vwv6cbgRgN`w91&ZY$}n;5u7mEWlG$ns0FwG3^-wv?|fqU2S^zUkTrS& zFWyy7Fn5EHRY46X!3La4w}=*H{wWa7D4oeOM+gP-ly-EAk@l*$eOp^U|6sdw;}%T> zg{Uj&YpjR^5QF`MOYU~Ltn2!-Ut|)1OO#!yLwQ=}o6>IeRsr);zkRmD>z9t{9_O^# zxiW>eMwmai@p7tVZvF?Wt-#ANf2)3<8lgBDK#QuC9hlZA@X{$|&%_(XU9HO7=G+ph zGUsRSG_N?Iz^%}1SyfD&!#|?lur)ErH8wGT2)q5?2?KZ2l)-3Apbel<3aj6X11*9w zU*TxLSyuXYE~039fp2mea`RY%HcGOUn- zIb{`D`KYyaXdf!gX`dm0&xs}cwX)ekiA%l8Xk{eHatRx7dc~)IMh-x{-Q5+V6%-os zRsf@|4I?G*XHS&>dN-gPKyVbxPRxU+j)Mv7T}zDLf4tfF%#h zuS<2CX%J1tZlV_>QOl>l zp3}QIwHNELV1o|iaP}ACjyEpx0tI~X6ga_7CPf_WIiN+pBaU3g)5M|`u}rYiBkw9y z$~L1_?PVJJhHUHCq2)(cdcl%Qlz&ojbbL zzVVU!+aG!RSGDcKYiJ(c;L;=9ZGf@P zyR1ybv46}2TIXF}R+y;vGC_AMIEmygflMYaNpRxfK%A2W^!>ZUSso`1e7|Z( zK=GpAQI_-<$oDV)z8Vja?35iA+$%A)~Buj<&i?3d~;dv3ixH0I1AWI%8}(@QVTwJ<@?XUJ@qi z1Ad0qeJBGAO}{41p*mO zTb)&qN1D8WFjroYO7ZK_BqtwmsvJh(2q?o*o=)P+%35L;s&Gm>*N>5u#6h9gV*rOi zkwEh2rw96D@HHO~&6Aw5UTzP(@$K#GgO4x)a671e)=8z#KhO5xzQ&3yO5_P=N|#t7 z(bQRGSwBV@Prpc@CTF}Bw5B-MHF3_AI|4WskS(bwYg;H;Tb$qAK_T1bruLnUwS4A@ zMVoy8dlLn2ovrn&Y*F=sFfSE!MaLE2TCs9f%64D!u|Ss(L3>0YXiR!@G-@Snq)O!H z61TXW{QRYda#X;b1i9;jNsl$ka=LfDJ@X0fl%lQq#ef+1(5SWmSv^#Z%BQa4t=Xu? zrQq8*Y@;34_NP)TTPA4`NF!{ljoz}^FXFvXl1rY3mvfY_F&AWr)9~{EoDY3(DfVX_ZH?pJRa=UWl27T)R zmws`fBKdiVAeZ&bxbmEPW9-y|3FLDi z(3CjVR$4mZ$+lsReL)k|cMf&c+Z|5a--?fEXNZ@5D0S4No_q^{zf0_&S{yQ%3yWsh=TD`}J z&sP1u(yxDh5&(Y;{7euOPSO)!M$DK1a8MpQ2kKLS;`-;Lffw*#==0|wS(6Va3J!ey zD^PTGJQ`BfZ-4e%<09Sm4}$w+0zGD=+h2_mu$hH#Y#UKpt8iWRBoLA@YVY|2S( zax>CXRIiO5rVY`i{N&vIk9~E!@QT;A>({QcV!{pfD3*uZ{J($wg|^44|1sO$xp65g zIhdp1aRHl8Ca9bUaK-+Ry8xCj;Le~7Zm}A59}3rlXSdq@+biuH#{YQ~&HJ`D+a?O+ zHU@rn0Z;~Xz9_QVNYaVWC}XW4!zyup|C|3PYqheZ+*BG}al(^TAGds~sJi9z0M8Ni zwafeBr~D4s5y>REaUFBB!8wc(dpiY<&IL)d(lL0(WID-s& zR)v;HBQh)hr%M}cgZlx_T)f-jh(u7rcHBO4u2Ptt1!Zv7_Jj&**-l72fEh@!h z$D0x*Shz-oe8m_nCknI!XAI$Cuo#{9u*b`@ad|HQ%*x^1ZU|*zE7sU|7s&<}1Ags0 zzO_C0@Wbu-7p^c_%9kXVC|IW+?!Rz<`_ylJv_1J7AED^B9}E^~*+y3V!hjPQxieRYvkEj!^@k7cH?$)xr@-amydElfO~AU}|vZ{gs||BYk@s!$MYl zM;^qvC0{pq?o{r|Dt&~j{K>#IN*!VHE`Ez2>tB!@gHhP?yg5N<9Qg^OZ~TrtD?Ce$ zdn$yGrW_=u!E0O1E(VfK9FFKjq#ak% zsariJAoEqeRd69;1Cl($7e1U|c;SUR?aGx(cSYX5TgiGPA=~f? zIWd?CUAWPRw`yIP-^E~;7h7+d8?ZSx0-Te!n@$qL#|ic8gsGDRx4}_l`BDL8@mQM^ z1ok!Vq_li{`%M4JOWJMT^5mm%Y?jFUD!U~9%OCjZPyB62m4Fo0!Yw55GLnGZ#KJ8k z@UoM@dw=%Bk1%WgH!%9YKdbo~_}$2l@jp!fltF*@P5=yc(mjVfR`zGR1xDOB>t9B` z_|BRa9NX1c$#g*UlUQZ=*PuBR)l#w@msI{sxf^L#)-=fXnu{{o0GU8$zy0GeUT)Qs zNy#8_#5;-(MM@lVGtKRYr4XTdpKmkw{Y^%HKI z<}+Rwxb*(D4_#~z-+#WHLowWBRec-fYExVcJGcCw(4L(%SW@Gp?%ipCUWp&Y4Si2z zKryIHy5g@twpuTic8^M|D?}=8xsw3Db*X}Q2o7X(Odu;h5M5>^-pl>2-P&s>80D*M zALqaUlLG7v0R9G_n0ofwjrPT>x7wF(+-cWQ3QsrAw9~b-?Fjs1|4^gJhWys^cW~n8 z1vlF^Th$+Ue|jO@Pob7nNE0lGtT*=o7fH-6r7=g?))GCS?CmdpocEi^lG#W7X8nGiA zpE~m@S9N6k{G@Eb)o& zV~1LHicpnH$?4R`6Y9*k@JT)pq-uY^7&xK8U~i+jD2v*mc9@s5{>1&n_%K=SsR4`Dw`8C%ekO zMY?_6K6=cB^V?=p20i&{WZ%ApK0`aNg$($ot;kb$0B{t@J};IxMR%8im;1TfOPb1I zj0+JPKN|J=z4T9-8ur_Kfxx2xRmjckO9C!HVe|bt9 zL&kn>!0^iY>QAyB^XK06-rxEx*)7~c0xv5G*cC0@LIN)<3G^HO{{{yCD_xn&%K!WX z00V3p>SHyZ^S~oL69dEt#%*`{-O|s5K#cl6VSquEF9a|EJHg=1|A&VTkfxjFM8OG@ z2+n4sJfJXU<{JYlN@s>G;~fT3y!xAJ+P!WlPDuhhL*7tC2t|PfNlNoh_@XwW88yZP zflUv+{1oa0I^ueSeD>9dAR3lTJ?68GpXj)h2Oz^m$=@jzAASaG6>$Aog)*wcSA2$e z@~Ty|(Cm4K0dtC8jRF{jV9+n)%jD!fO#oEzF8(73@Zoh*f{WoVFJsSplw^YM*@Suh z3TJXE@+v5B(&?&krW1LACAr{y3(rafQXpiv?_B(eD+Y4WOy6xS# z%69*~KrSJ#V=wqawyS}It>pmvSL1i;&Kx-M+|OY^t-!;1%BR56iMQxZC*R9GCOJDB)}H8(4TJZv@3fj z?RTEJ(w_RlbM3Rw-Dr0({7=@m+sW!S69SviBIlLOT>QuJRx;wq!kLTh!B;<;ZR(%@ z)F;~B)n~HZG$rkAt&GDmEX?~}XM2gk-wg@VGa+D&kybdA8-E$G02palquKUAxvE}m z|J4Sqe~sc8fWV3r7<}_C@4|e9u+WfxT=!Cg1Z_1$nE!Ag&5!&WFD`XAgONw@0%ti$ z>U;^FRbZY@B1Qqn7&zhh$mZE|?K{5j`|^n}>un2z{}tU*_WzO+ z0SV5znJmbs8{EDNcf)nw#RETVb{eB7Ns@NtQi)YJT_%Z_AsuB6D^jZWO;l?y#Pd^W zLR&u*{}nO)R+j$CfAw8e2c1vytyBOi6X2xX!-=f-Zt#+{0aJmzKZQ3@OUgt%@TB!T zDzOLQYidKJr+z6>%4GW-G8?!~l*pnlzb z|LYpGz;L867lfoX8I$-AYi_hGMQSYY*?Uyy|<-_M_yRPc{8NtYf zA14_+-@ie>o(Vr>=Pm)qlzdTu%+!@KDM6nutkt8z?^xgk%BfT2>kfq60pr+!EUw=! zy~~{pDL?qun_oq646+XR#NZc*{Bu9_o=+^k6p&h3{JdNwkgn+EQrJZ~U)~b<2Os#r znYF`}A7$YDv#h!=x$^ERepcWy=smliT>uOyV@1CVe^>K`Grdm^VC)Bmc(>6VVMrx? z(BN4U02u!aI_6Qk1u8#h*=wvWMZa!6S6figWPoF2s_mOzT{=_UeQ@8$m%5VZVB(C zHMmS0iit|}T@JX&97SY)D{CeZdN~Wec)lBVMt3OClfeS`jKh*$ajLZ83ZB%P@xrT~ zd)?i9x~)9t$-DgWsXYj&OfIpqeeuD|ZI|2q@7%Z!Ay;Ks<)-}{G7+$YBDBOYfYtr0 z+%A2+z2^K*YwhHC`Mu9CUe(Aj#d0L@D`a*z!Qz9U|6=@}eJo-P^vlz5N~U zNZ<3jPd?Rt<)8e&RyOjlBOl9r6(abOn4>lNiA??_ix=xH#OeHvcc_=ANY#5+v`XHU zmxT&ul@)JMAMdGYI)Qu-Wp1QZ-#1Gm377UDSx{1ximq(@jnRw&oXV7z{0v$GhasLb zBg)v}oItVt2^SLhMje-DK-T-#d*%@dnl&O$ahG4~E0LpYGw>l!ax2yX3sn$P&&5nJ zG4<&Zo9FLd*(I}%1EhG!r8uJ8;V&d+jC7xAx`G{{SxgeApPo-BzBtU37s<0a8+e@% zGS4^=I;L43UDaRe3V-@yN+g zff(60xEp5o7Q4T|)u7*CmHie*v;DaL?2pf!rGKSAcCz6%N31m1ourK+PNlnJ>oya? z*4cB<@|juE#nTYq+dBw<>x9kUbNYCE&2!Aaw(DYu`o|IJP7BEk-c+b#1YI6m|LF^$ z=dK3Jt2=;}{gH;fb>SFevyrxCS>xD{#|3s7qY!QI#j~9VD?Qt5cBH}7#@71(dc3yu z!|(d>-?}B-!Yw55l`a8$pM_gU;45AN@BPOg{JN#1rJrD?`<-m@Uvitj#)GT&{<*a+ zPqx508=iP)#!*!FogC=t2l)4e_bDuc7hevTg+ovLf(w3V9%L|dLO})I0d6QPj6n=P z4oD7-GbJt2L=GdP^oSb78R}AJ4!Tjg2syax551&USipjpBK`u1zl@P!5|*hjAym>Q z*rD|Wx6%ST;yXXm5XXVNSdjKTZbXc{3`ZVScDF(1({BS)IQ}MH=Hu`31J?7EE#W)q zi2*p9^LO4lKdF;s1$Al#8li|SyCC*h|sV%?$X7r z_P_*EV+Zf>HXPe-^?`}1Z@vahQosKr6 zS1mTNBIv0)A8l0LdkTqjKJp6;4cfMQ*Kq=3rj|293HgvPF|Itx130RREP5Pa?X}9? zJcvlz96{2HU2*2}G&Bd6tiJ5Wa#voyBTjs#Z=hT^_%g*Czv_v0|NR%+uYB->?dFxM ztS0hx2l`rO0WdIFrR((OrIU88Jjh&biiHX$%_ zI14JuRK5Z#zGksg@*pCA;FjcOslz7~N$cDiT}KF%S&tO616a}*rz0#Wlt+GgD9?dw zn*S;cgk>KY_uPs$X^AgdMFfD!NxvXNf_OtZ(ULo!$Sz>YyUT#EO)KQBhqyUzyEkZ| zRS-4CRX&xs@dHm^axLKL*L0oKx+CLWDk4UDJ(H(k^4im;xS$U>%QARRLcym{h6`)p z&ZzYi;ds}*5HNxe5a*;VCVhV;6qyCqH%Ni{`X&3kiHB zOQ7D)ujCRg%J#CCz)!vZ!~X%>-2NIy{yERyJ22GBzE8p$?QYR$pmRWUTfVFJG45md zlLk)y5*AK8jQ_-I92M^DK7p~~@9IB;E%c*Ur~tTc**8zW1DbwaMmLA3d1qoqy&g$8 zG#C(hs$dlUP+RVXHZ-j!IWDRN7{|_mqH3fAaIGQ~Ip~I$IX(uD6SJlb6nq*2~4R8lx5_>*Q;#nU8g2o_;Yvh0m25SH1R7R`Di$iK`@nBK-9Gxv^>%yhLOa7;;d112N;QB4NMt3bZ~t5yIcFlo-bZ^oI@8wSr5H&1`^jr7C; zCla(~&PhY+&pOTS11P!EhktidnPGgH&#ZCbK(u-KJuLv!&+kEduoXfRaCruu&=yd6 z>8LP*-qYdaPSknI^ZUN-TiUB1d8GZr|Ley%e!}~UfnZ;n%Ney~=6MXAp6QF_o%DNt z2HfB)71HZv&>qDc&nX`~!Wch_p+9bJ5?9)TzG(v{c~?8G=t0EyRUqqmv=v*uZH!4X z+E~tni-gO$@bufVGjJ=d8eY%bv<_E1kY9M?XOyFZrr(nUY@|ON0h`KEybh3p z4`Pp!Cotf<+I_XkO0*6K&sBbRug$+l$%}gN>24-z(bD0|dvOejSE+dB+&o{T8w~&T zm;)^IBm*~O6o5`+p433B7Z>=Rcj%MIdsnEn3n=AFzhD|=9dHxhRi>&t$|kGA&?z~t zWv3RGAa3||m4h4Y!s*TSoo{wZeQRY)0ZyV?sTTGJL7Ygr<`}TFxaiw05eWT~& z?e9p+P5@Wvy+CtJx?O%~r#*OSC;HB<8+&29z6j%%d_Vn4zsqE;7xV3NWNL@60C*dJ zjB!@c_xQ7KUBc*g;#d7>pZ<4?T?6VuPMDtMa@eca_uAE~Ou90m;Oe{+#~R$`<<0@~ zvQ7I%7+b%S6K?spOzu?3E&vUCa2*GP_xO-^0Qkw+;=^X@`%{++I++l?gR*<1%rtjD zxR9{M_~AHv{pLQC8PtXC6gc~ubuNW!{bRg40pMzXH{xUHYrqp1Bi?k3f70EuKUV%L zu5iovFN5E74Vz2=I2qu?K>st|+4FJ^)HU$urE>&gs4HzjZ9uPz69Z|Kor;=%`zqi*<@kWv1` z6B;Uaf>%tThW5yq=X_qFfC40+LmgJJoi}bO`%X21nF5|zWrtz3&N=nN{afvD?`At? z)f+7WL+@N$;_|l@E_c&#v}l8U^PZI9uCP_UrL2bg6htJUyECpb?w*QI5m6${Ajus( zkAXiF%aJx{8Scy}AEhz5K`hGa;H^@}`C$!0wL1A%XZlRo)R`OHlz+sr1VjG@qJiAjMT1 zT`q&7@}i)TuZpB%+$E1|w~pFpzfjxrRaPydilh0NrIQdU!FhL#z`14h23uX1`40X4 zuX(iH+Bo0-&d>aE`{ggP+u_WE(B?*L?gp?b{e)BMa^nHBb|%sp)&(>^*#uP4&YD3KGg#EOv5 zL398HURXR%{NNqXolwuCCMm7cytll&F^p{_nj!ETQav|A@?GyYk;#Ie{xp8%WK|6E|mAt=8mGC2WQyFu);a3V@)j(|K* zS;VJ2G&%uGXCmTo(31r3^Xln-+d978&L3TC-_6SZx4rq*?cnpj(~fW6%1$aL&9Y*y z;Z2`tHzulv@j5H>UV4YLcxN<#nFPR~c0$&pROeXLf8^o&=&LcFS+(~wtWLZ-X`tLS zgzbM*4?Uj^FA)S+zU@;ry6x-FaNOz+{k-i$qke}=_Y7-fU%$D_C4B4c+dbo-oXqfR0%Q@#F^0dr zzPI|Hzw750M*>PBi{Gy_3G|-qE3H_I^1R$7@KZnc!6%jvmwueB{O@$jezx@I$<}<0 z{jo)VdNMF%OMh+a&oKbtTroWG4_s%W{XTl(dIVsZGy#c#nb1^J}^& zR2c}nav24WkxgZZ0c$8^j&@Nn29Bd21AIm~;TWiNQV9-ewUUzP=|{?O-BS-0s!pGX z2?ju^RURgoq5;X10X42aDj*0ERkVo^?1g42k0ag4yOE`=vTJ<)kw@}U;f+tjzn3{N zf({y0?!ia#$uHTUGw`RvgYkd+x%TSIXWI9C_qVsp51ebi`ye zvh81t1$-r)NLa`yL#0F;$BoAtt^8X7d6kKhWn}fn` z;3t@@r*-$xqd2Kx$&%U5hc0cm`_8Yo z3tTw0&1VC*xBUk6a@*PAYXYn`twGPfZC09A^^^Ao7Z5s0fKJBB5UWl6d8QQ|lT{!t zoTA8nifWxbqpnim;e4r@Z#U^VE0kXb{g`A0D-sy^(Xor5v6C?9n6DeBu+lDjMx(wfQ}Mf;iV4DGs4V0wIPrv@J`-j#FEClGv;g!U;PP%(VsHlB9Pr(^ zvxJ$iBPlF%NyXruLrf_Lf=|V&CAum-Y|LmJTbdD5|Oax{>U^z$GcvI1{k`uO9Q z((hfr$}up~t(Se$g!j@sjpl7WstM`tkjP{Wp0Ae;EJML;%Kl z{22H--yh>%!{2yU{|m=1$IPMm3kSfRMqBmOu9sP{u zhXJOHeFhtxhDws602=3jR0^H(Voujph_qvfs5(n=9CEg#Ac*Z+NK-$nuc}eR~locB01%eO#2`7$d zo$)@BuKW_4AK5aHsv1zx-dfKlf+&&+UTiWJ1(n%D~D$2EL!m%B6^|a4Bd0oZNHZQ|VQSy~D*;2m5S^i59q$D{OvA$TLa)5S{xeRHW%&3R_qbD-iU;)oWz6 z#UzBO9-RneZ25(QgjtN=!c_{=uH7Wraw`Oe;qLBU>d884`kxF$n_Ox&{O^@k%Y6q?{oLjIL7R8z}vmM{t1xPpov3;3QAO`tz4S_XV;df+Y{a zSx(;3j-M|l47&4FG@2t*9^xrt9yI|p@{@1NS+2$hcy#<>^ovEq->S>xlU#@kVes-!D3hXLHpyyYZ^)~#I~#*kkL*~T zogv?;d||8?cgjFi6MAAOO~NIl-{g^Fl_p?rQiuQaD@0h7Y7w(?7Ay99r1_2q4nX8) zy_BPM`$Y_H{NFmb*53BecKe>Md%PWe>FKt_oh0jYuI_x2{uq~iKRjPwLaGT_(>0Xs zjJ^C$w?{v%@&BebK1k@e?cLc+zpjDq>b{qz+K<|wT9!Q)G3-n2$IZjO+^{S9@}SPM zfdMV7{qxuXcAc-Wcc>Jxx$*~f^_u>b~-x)Y$b^4Io% zSNWYBU~9P(1JDUgCkjHpjsSREz(K|F#zAW4i0OlnqnK$G98em=s2dDW4nC$iFgt42 zpobF2fTRw1%y)sk!M!das{zyjS2vz2U&719&|L&^5U%)u8>kUgAQ*^_>DU)QaHFJj z7_%sn1GyKX2dhLC5KbM$r%Kdd!l=X*uY+81Pn<%~jl2eM;)opaVHE66E6L_(UK+wE z5|6&>QhVzYkG0?U=fA+V^gSj5{{8mL|NNuv*M95sT=mOYM{awsI}eane{lZGy{IZ zQ)gJZbwfQFrY>nWC`zX&h@R0@;l}PjS>vW@c12j&ZMMN5ApbqKa-L^}{^3`i<5N#- zZD-Rhm!;HsY~aGVjrQ!7{r20Rx`yI<%5D2=X^URoBu`f1nVq$EKbHU=?(K3JA1ru$ zfOkj5RFRl>R-abOh}KBAU1qx}{En@iz5}i(<-9xe-EH8C4KHJqKF^GM=@{o^$;ukX z7EtzGEy@I(^t$qHSx+*lXVqGE(iA7KmeZ$`13D)@>NTkMD)p3BL^u%l{0JOWQU{Fz z0^JvF7Zah%GvM=a!|xN2kiqLt2_xi}*vhZNgt<9#DTLv>(uqi%kv%OLOo2pKs3Te? z{#IyHN3_E$&p(gfEzWM!spB2`ZBvrI%Z-TfG;yAvfzjEC{3d@dH+2=t!K1>5FeKIe zb5XPGiM(sV@E)L9HX+>chF^vUL?xM5QYokPP?Iq722VNi(Mj+y=AP_&A{4;CTLvcC z4vioAckn#!i8H9&CKk(Y^N#5%8T&~aeRsCuau|5PnU(yzqVMWQ6DP;kh9Y9Po)aUBcj{j#rNN`2x%J_9ptMcYgC%x3!zkb6M#vzQ9uVo;X>l zT>a9@l3%i+Pc&b31t)zpsF#>f^;)50`m{}UNV(d*$+4@~J^ldwX=8%3?qWIMY`=Zk z67{o*(d_Ynno#g=7gydl=okCNe(b8+#Xq*`yY=5Mz-(`CwwpKk1S@&j71}S_ciV5f zrGA|Z*BMW4a1TIa1GBbs^&6k^W?h+<6?^1h8Qrzz_+(phtjgD5D63ok?Heq#pFLC# z9&H#$(v*ce(%c!530j(<^4f)`Bj`ec{+!DRIVRz!VsBA~JwC6f4wp$2fje5YF)w*E4&xm@$_t; z=?os8U#^mH!>uG%3}D!!R6!!)Q3pluN=PP~12b7qBc# z2&Jq9l0E^=GMX!^_`%~DUI`S-9d8hw%2A4g#Ikan^tn8;hAUP0!>OpaqPD`;;Y*h< zX6yey`=_5kX}R6r@J24UJ9nNN-#=9f6c^yBXiR*w(knAPYZ6TC3U0FOz*F|aBaFf@ ze2*Lk2q_at_a|uxBXK=1{Q#@*M$Q0Mdzlf_pbfp`Cluu_XcEAK4LS11HbSF`!gY$F zZCH958&RssHalBr`&P~t+weCr`p=(TXZyZs^$DkA4Krl6v$fnVKe*kVyRz4w=aMJe zpLYqGZxlhoYaAJHQRNt=^mHFXTjk7&E#OoVWoc=>K37GRMaiJX+dv@>h4%TFXWl^!SeedxuI$5BCoDBGNu7Dez+u8FQ?E>G>_DcjO>`Jhmc)8Ra z&Vsswz_X>#USlEvdQJ%PxqW23vK?_e08Sl497O?#Qc@xt~lHyIEwj4}|0NdKjL!RdsPHb*Dzr>FJkns^})N4eoM zqzM;)OupM`F*!&~XNfRm%)Vf%Pm+XXFa8A>3{?CncciSc^?&Ddx4m-xu>HZWemyt; z@9{~#8ypD;vScxM{p6?%6a9UlZ`2v5;qSi_+K|VY_Sj9JQEeSP$S$}o`tlpsZe=xp znRq{k=ZgO=c09Sw-U+xH*I2=)Z#{Ev8$5722^#zcnb_d*DF7~sZRZl`R(6#S`w*5Gh8|qOS?c?qj%alot<$^mw@Od3U zc4xp?nRmiCJHLSUHve6|WZ-8*m5+LwlNi278&w(9i^nAB+sXUZ?mjZ$=mFzhb}dj2 zC!@V6(8B??D|Z4|rc6qMnCR_EQ?ui+oVy$t$H1h{oS@vivSHh*EpO8zkZ zW9S?2WB`Ljz7nAEKPD0MJK$s%xn_;gYT(7eSw)CZ%K@LL4A2?;@uS$PmX#3*RUtr|Z(B&g%fk#2?N~PIII|)7w zMepz@L=$VIG2s!I7=#H17@uXp4|?bciwn;14FzfznUum1tMH4L8Bi&21r-t_$)~bN zj_}t>7@iEf0o!2$3!I8+WWc3&Ztni|U;kM9C%^DZ?H%9pZBcTra6bHZKmSZy;!-zf z_Iq`JZYG4)Q1mBZWC9O(<#*myoH29p1Leg42f`fq1V&oq5tyQBxIk4fWek@Het?tz zY)h9n(vPuNH6m7Hpc=0BsDfyjRGeyJ2|D1go)KB0rp6dPJd`G9^S#NL6>+n?fnv9E z-fysjfKlzLl8W3um*%bUnKogUQ5?N&&kLd=D6}T1ym+eAI5x`JhI6P6dJDNJ(;!s1-%Z0KKUhN?a8FP3_+>f7acX=S^h#F{Ix6GqV_dTKptU@0sK= z1~n9utjIz?_~U|Tt+e~k-{nUX|=b*r0~L?Y&XEJtc&l($fdK;Vo3q8{@x@I#41 zpd)F4n7MAiM*tO7IaNYM;}3YpArNDiHsCvIY|4Nq(g$f~^beZ#w2Yk#n+k2HU~8l> zrSiQCD;e~pkv@okpSn!JM`XvIf|bW8^8ih9ekenV)-wuCpm}Bz404rTPvbJFV|lH7 z5>pQ3915wUlKFTyQm(`&qq~Y%0p&7FGe7z46eG{D+7nD0JjFjpQMlrxM|QF$`$!!C zpu#$3gg{Mp3{FPA=8;@^N~G#8yAm=--wKlvzHuH);1S-BbM#?}i3cXF!QEqA+2M->9!t2*B*8J4+uDZ< zualG`07Ya1#aydTcb9;5HpXdeSdr6&2Mg7J6r9|Z+%OvX#>QY9%4(GrtA0w`4nK;T*fZ-A^@D?kHlMo1xIG%ISl|WSDiiX~4G#>oU zWj2u(&OqcOjuAQ;&>4a8$%w8zJWsffA@|f%pNg{cna@1ae)O;Y&Gy@$ex|K#--kl7 z3B4+3lydz;;f!o##%_^1(K|GTITlL3Ni5!mz(I%tC}NPoA5XmVu4B*ejp%ej!(wH* zf5b~$Ua4&j3RnN|D+MP7Y7z*8IdUp_sB~MiS!K42l+W$$YaAn4LIGVq-fOSiJZj&} zB~dJiqvc?XqnP;_D7V+2WhX!k6f_`L++D#@)>m#Ewri}K`^{&S*{sl`B+A$QY^T3) zA72n);y?v8MgTI1kq!&;V==8S6)npeC6j0;43dNCeWlCdh`WN)>h{$X0~{4J@z$95 z;MHu;JaaqBu=f{u!JjK(YtXpF-36Y7%@G7>S%%01!AVbETtVACT56xBOdtB>mDaZS ziUAXBM=0;!OsxU$?f~)RTjSn$e?>WhuZ;BTh)$V|OFqWPw+7JktU5Dq@e4_81G@37 z(3i!Goen{s!36EgQSYH=nf(*ccd?SI&5iiExH)=(39}*rtD{Xys#EH8?O%+vb@p~k zo)f#~FM5w~>#yLh#F=FO=lu(n9|=0s3arB8wXhM!S$ycgVjoB%~DY5vU7neie_LG;H2ULIvANb#&lCjNK_X@)Z=eSte)Mb9{Z zDo{_Og5~c>=-vokfVud<)=&B#(oEJcyvvzy-0;+h08T_#C`5-5D-B+*-EB22Yz@8Urqt!4$9u^~Qwz?>_4 zQ66P3`o(vpj2N*KW6_|oN@cDe?Y5o6>+Ks}eW88FTOMgAFMPf&(Z{Soe@v#>m#s3M zB@Ax*Qu|qGxH4^dofNe*vN>eiI&kMWs&)1(xA>#4XteLL+sO$6`!X4Ebzk|PVYS?? z^!BCR<}aUqy3c!%oV;{`Agk@rw6FII0unGE>3BJ-a`QNqE9#CNH*f5>Yi$2_sPOAC zcKD7t@;G>QwZ3+tReQ1=(sV*sdVV6-oB8G0ac#(hB;@ar1BgPuCJ((Nu#Sg$L9G+E z?gnGiSUZHqO^$u}rI?Hdl*e6W-V-yv5aUq@$E_R(hzu2j`6|!iPaOH>zpN799z8rc z{oZ%I{?f1g#3x_)92g6?kibh)0;RRQBw1fD{c@MUdw%xA?_#y_f5(tNpVj_hv}@#J z&^v2glLB>if3~uZu`kSkoA(E&b_LY#09XFKJHQoxCjhwErWES|O~o0tJvkEG}Cz4PrYajX8|5+=!tahyJTx9#>8P58Z5|pw@24TD7IF7JURiCO< zxUi|bxat4^KmbWZK~z=w#p_S-duiQD#)MoY?ZRe^+I^@aYap(-n;2 zEmq0Ta9h9H<*}>tC|av1QSzoy?uw7J#^p_6R=T9Ca2@dHM1s7HYW7k;6;9i0R(Xa< z0I;_GZ&haX9DF4pJB~Qs%@&+NjDV=UC5N-uNY85{rW*@gKObW zobW&po*^~e#G<6K$BNtbnJBW}2cS`k>X`NFrz>4CF1{#J&TW@6YnJApeBjX# zS@LJSiff!Zg5WoGE5rC@urT{mxPpi$KOLsX20G+s0ObnqRfbjcXAwMrpv@NEt2HAnxQ3lOx5ZaqRPD>R#P-3vWx3)29`vU=9%%qjsLIh&$uen1#9z7~ zD*h4#xa1<5eq-ycx2(RGwG+fiRb@weqyX9JW16{k8D_Ugm?-*{I}kSEd*uwK`Oy1e z8Q*SOto%R5MCl*-<|o?H^)Iv|CSbSdznu823-;_|=y&O(q(08UOQu$*>5rX!1;`6j z{S03WYk>Xas`CTK@UPw?&N8%JVRyp7Pp`)Cg|6rK?ekq>cN{o-u0Hc8518?7i?d+T zNSPqCy~Ct|JQ3kp{}opFR~ZNP(3@`E#MtJOtoHp*>N!@~PdhPC?~+%z)R-kxjv!5j-bdW?+S z4gB*Mg7s^Dme29auhzH=!buD1h8N`I80YS&Q~G2cj3X!s)N78zA$Ou5J6%5gM?dks zPyB~J_}-8GgR1+*??M7EEeY8BE!;u^FF6Uk=Y1di^Q_AKJyzt;=QDj6=6ih=KP&t! z3mV?*tNOXAzr#%Nrm>>G=V$x;BfM*v8^MJS4)N|3*kc=+e-1<{9S%-$DrF3Y&LR_8 zBUNB}I{p|44r*Wrj)5klvSGbY^v}V^47|UgOG0!BXmAbojFH!|^53&Eo65GQ#~=w?4wdqw3lxtL1|@k^ekRXSI(SD3 z`t+mXBrLz;gkNJUKM^H_33{TLq#3~}KGck_v|juu9ET_l%bVxh`nk((Y3Cs>{d=%& zUwF8!vZ~8E1w~O7QsQq$qIejDOqeTk{FPPV2{(l+ir=C^S)%(%BIO!@;~B{OgbnkN zor;MPVtlP&nE)OH3s%`VIndh_k(R}5y!cN8+C2G9Tk?#jMz8VptepYJY`LygY|p)C zZ9m4nxGIqE5M+eH;Q@Kh$r4WTn+MJ4?N?-l64ERV~W_DprvQ%4i zvq90V_?qxYIVoGVTauoM1BsJwR-Nz~w7~N3s(vQsP+Xmpi^7RKocPNG1Ml1>mm12e z?@D+u@zsBl1%~T_wFB){S$>}pu4{U9Xtt@SNHY=rdvL=MG&oM>%-L8{iHhdeJaRB|Gn8r-5nh>75g?c|%EB=+o! z_ZLB%(kLrqOD}TPo0y77!_`7>RxSKcNle{&s<-s!F zVW*wD0ydclu&b^YvM@F;_QxyE`{?a3&*3s0Md$IFzJN5O13SO>>9lCKD874K5QP^x@aofpDFpY90Yl9+qE0`q^0K81KSM+Pe zzu?>vP@nJ%90qqL5ug(|1`TJq9hltu>jZ$Gsc|5$RbS=B2QlfrLuC0F4sjWM}?`uSe|uOnwH1@9{nYqeqv7@)}a+){D{9 z#pLu?L8qvRPVxbvlS&)w=+;!xQij4vU*j1iklT}$?TQvOG*krrw?h3cAsgXc`B3rF z&>hNu4x>ZYTl~#4MmkLt^Vu<^c4JQs%sMg^5hzO4lh^NwZ!aH%uC#_c9Zc13bmO=Ca zDV0p~w0tQGX)ZR~G%}fH8gO3P730JFlo1-At4cTcqQMO(I#66Mz4m-N!}(X)&*Xt< z;5kv@>Y8@~sC1SR$h%5Ev%bNFQ%VFGd%uT#l}c+qwQ`iLrtnkE0eM(p)pHd{{Pn(; zpM>tJ9*SFA0eKK5_5Po@6sF)Msq1Jq72)b9Sa^vr!Fbc-ltv{jxSpEN|H@u=fe*adx`q`)277W%6_O9gD@g?sm(b!yel9N8ji}OxA%Z@R+ zfgu`J?2pJN{VRTVSJkd6R_}q;;PtbuuC&{a?(Z_WdxmrR^z-T(-iYs)Tr7eUzuWlt z+5NRipT5SuFZQ*!-9pciuyg0OqQ`i~{v3A+Sma~$Bv=2vQ1!|SyNnO+_*wvuKybgS zdj`nU@~dBYd7$$2NLbn?qUw@NKYie&2r%}o_SD1+sC_m!RD{u+A+MGNsCi1 z97JbBR_bcC5JFyzjgIxTQ;bO!WahC4SNnx?5+J-#Px+bw-0U!sz+N!MH2ZDaDfy6D zhF3^BMy-4I(lPZ3FTMsYChYDXayj7AU;n$`{rZPK`TL&w;UD=CI);T?NZ=(RfyD&C zOQfO}Y_|3fe(@K#)^B|1Z*h6dpK=R-UC!rr{#vEWHZ}&Ov7N2X_V-DGFsnjr}Gw^HZmu^tQS`;5K93&FuNFoIW55g*GV+5?Y z8Z%U29L&XEUH4OJNA1V{?vJ%!|Bc^dCVsbl_S3&Z{3Zq(+wvF;C8FWvN@dRoTnE`w zK;(M3@G=5Cvx*@bgTKL0a1uH3Saeh@``9M2$-S6gMKDFS*rBXyDxLgx@>c}5{ z81;Qd;jOqR{N^{go-UpsaRr-vLuVk=QwbC(zeY(vPmu=^c^Ui=jX$f-Jx(z5bJ9nJ z-qrs#&a9^$NS{ce;xwWyQbqWa4YeJ@c)ky}>trKgaQsrPYIdsX)J7kNu9 z;cx+K^9_7m<-}#MiZl^b%X{=x8D=CuE;9kSxtjqB1>(DP4=j%K?Px?gJ@hrcK z8cuk-CEcA+UfgG&w?v=rr}~`qv=nF0Y)lgbUgqj0eES&0M;OFQG)7nR4;a_8%AM`^ z8toY5OnO=>zZ#I+`hl|@I8l(#9Ye>XAnWvfw{GpxAJ=5*F%ty#=b88g$B7HapMCgr z?6CiJV%5GnwP%^>;}!TG{p}XV7aV)ic3{8>VFZKm?J+ked~HvThw^#M?kz7sw0@Wb z&sbrf20k>hqX2X-Rdk}mv1yGtD(O)(9vAN{Al^fZSL7H%PdfAb}sh7#n)&juBS~#zN`Bh^h^*;@G51m@DB#+C!2|1d$KDAw6bhYAOb3~LTY36HJ!j6;Nz++k+Qn^+9@ z!PYQxIdye~8R<1HB4ek*lOO*yd2;6Z%ms)rXleXQjFpHo5L{g`g1nQ7d^1oIS3EHw zC*6E>HLwLV;h8Uli&Rnyc3||VyB-~PEsnaBaAVagO$H^QS1cwCCNBQ$40zs)L#7RSuM(eMrXcZwqIP{QV zPbyD{N;t8CBoFAi0$+Jn`Es@tg(NV8hR+nCYG_8J(;-6sEN`)=pLWp=P;)KAzKpmd z+ON7%9V3yj1~E4*!_SdNN~8lo$woLg_mtyDYzpFLm*cDwq=@5Qb zrKLlFDx;SB2%g+UAhWKNWx@b*P8KL<6~r9gG##38`1jbp`T1w=Fk!)$08ognzFocu z;*HrSD9h4;eRyO@`nimXqZCU=DEBCshyYwC2oM@Vi2_S|8WT4n z8RuUn`KU*?oBB^yEk``I9|Kji!FHvCOEmON2F7+K%^)Ww@CexIFC6HFm??Tesc z#fuzAcg|Z{3wlRazQpZt@yNX0rn$o8dnwP2e+j#63fH`!JzYbh72u2V8T>EeStbyU z@zHG`#=xFuS01@+y-kKzc;#!uORJy8;%#AV76z;sTk(hzSuHx0@JH!)jsi;pFBLge)-Aa2R{BChgS|KhllUJ-LqG8JNq0H?V`c1 zNdRqY+mmvd&)z+Zjq*G{yNwLGXXjV)8M(aL^df_MC;c19+5l)!e3Ah=IybXAZ_B<< z^v0 z`mf!+8M%E{&!k1GQsU%?&b9mclG-6=T%&UKm3R3~{`zU#O+@(Wib;g7{s-BY1!&yh z+n`@tuOHH{YNMRLY681EA!481$s~eyUQYK=V28At@%NTbJ2A`Ys z36x$UhHm1}+{RE00W;*!vOn2Z2CUS29l%NFwtVXFtZL6VHQ}I=vF}sv!ECvOP-!x3 z7*yj(K$h(qo=hfcryw{Gk|ugv&k+#O#IXTAg4Sq+4D?dx`6}^gFB2*`2K_I^^R=gb?6+x1S z!6{Gvt?%G$!;ntKFFmehzPx8jP6VX6G3emTibtp~8M^u$!>R^QPkqnNN z=~*qRKr?s`tii06oxUy-BaKefCA1k(3_ETcW%#3QHHGo@EC)Vaia{xk;bm(n8no>d z83*^lL4^Tj#m82J(=d1uxM%smwZZcB7+Ti@bS3Yqq6>cb#8+c51N!WKd6pj|mt5C_ zZ>0zbCDYk9H_l#WJU*Te5Lt2j?Gd2l;2FrF!#;n~koWw0U& z9TOzaGwG+DQC>Pqd9%~uYPSBHSlK&bRAUA(QEb(2IH%aFUUWm~sUK(hF>q)ax+|S5 z^ULie-wFXNyRoYDqCZYmnH6ih0cWCL!g1B4?K9?H|@wdqAu7?HE=){=ES14 z;yTGI5V_=klWTf;3}BxXk@DL6f;=i*4O%jQBHPPc8LiuFu{;LXHL%B=Na z&c881f*0FR-KR&d1Dpi!X_SpFSxq?OtsLYNj)R9!@*0J{4N+@EnYj5Qmo8uZtAF$GpHKKDY_M-K;H9(`--&=T|KqIwIot~ld`@G3G$7L8KR5UhpH8ivzEA<$ zn>(@!qt~5bJAM!d#}@mW?ju`=vbXa5+I)gMo!R zWJ(Eb05!SRyP~j?~mzd2jYwwptRSWg6s|Acd7~Mck6cd^KPO_JK~6 z6O)~G9Aj(^PM>C(qI6@loHCx&?fi(r0OYy_GjT$(X}U5W#x<}C8Fma&aaM5{Lk93q z^Q8dan`W%lpv&FU^gPDe-4EP7TzM_$GK8o}E;_lC)h9-*Nde_DyBNkGdtntR@;!-x z^(;o{qc%qjSSD~ENe;5WbiHN^2>z?Xv!~{gzO%0HSgJ zyOjp)I4(P)Byo{wy1eIaaUXi{3p0RpQ(x&G6RY=Q)DdPp6-gnXxR6K3xQ^>&MiY1Y zlK6$PVRm-6V6-w5jiGyN7qXE^zvlOhp>-X_Bphm;%TlzO~ z@4Wr!@WvZCw`jHb8YALX+TcITz*w7aa@3Z7ysYd$$l(4YzuQjtk08?S=2OIW9T+Iz zyp`7vlV+#EzxWq#9^TD?d(>lqPtMlS;AvO&E0~Uqc`YluxcWLkqMgU1y)@Bm@J?qp zvl^cbRc&Kw+<}5#b2PxO;8Fd&4wkk!?W|(8v&-{Mck&;QPWpOE<`K2Gc zbmjU_{!f4C+kfQ0_*=jH&&u@Ta-o5*Lk(O^0DK)5%7sXyfuH)hfB0R`PftFbZMPq@ zO>HIsGEmQ;epc}3aK9P!=bipN8L$TO`xSw`YhVWWX9Iul_jlWW2LC7Ln~nxTO^FpR7VNBg9D!F{AU7e579COI;arzT5otc5* z@Fa&=X#@%s!=#Y$m+qtwQ2d)kBhD_vX@@tr0Y>5Fn1O5jm(V-MuX1dfi-_P>SbIwm z8was;#2uiYkLQ<`Utfeh4__%l^33=IBkLWgC4TaT8476Z`_}zHEDnJhn&3Al{<`Wk zz5tiUj&?6FTII4*R{SzPH}B1Hm&Z@CeKTb&Uj(qiT!SQK z-giUsjZtzfD;|{v&D0ME`7vl5_V+AX+^^(}0K;a7)iHbxV(ly`*(Ei@rmIiEw-vJ0 zjB!;#vc@Shc-OEEa@ZW*IB zz)AOPnh>y(Wzg-N)=mg4MPGmI=Hb$N?i_Bs@9yE@Z@zOl&Fa?kYy-U#oiLmo%EX8y zZ=MW_%X_tq()pgWT>z(#JUcPTBP+x1=B@cULX?@6tLQYM(?bXP)zRqG%h={X16GWyi5Jb%{ z<;EX9G05o}hO`o?M?`{QvV(}c9ELS@4PM(KQTg?~;CP#lr0uq*vVe)3dOUvd*q=E- zJLZTG!r>!cX8Tw|TN4{=S;rSu1HKm(Dud3Fb_po`#czlS9}gV!miBa`JhE1%WBB*N~Uwri~=^02th zt@2bS&EpqQB-jYE$Grm}zI2wP4KLi~ZyngmIKqDs{VmI;7MZ3l4BcHXwy5q>MyES< z(HxYfc5G~SaOd!Ef72U> zXJ7b@EWc+WHWQc*=ev}FX`0!YknG@j+ENpadDP3xZl|tvC$8_&2fr?L+TfNvw#O4m zHUBr+n*R;o@Ja&@9-O2Nzt*<(K_*n+c;jy0+rOQ`{k?Z1TiWJVU%fMYvfADQPgB24 z=YH#6CK0?3AKhe3t&OPsl_mW_2KM{p|4vYcj#nDU zX7?4%TfO)7fQKiUL`Zf|LeHz6cCJm;Zs}zgLdrXcZM)?yxcVFJdD{G2xAIxSw7(8O zG+AKB*44DZ4l3-S&?y5tG&xONuZ@*QWTIbn@A8%CE{7#*BgHxY$z;VL69E>Q=u??@ zqBnS6Ysed7(N87}2txmvEa)MD(UpET`^&y36WE{mGe7*%Kl)$(@Bi!{0lRP)8u)tC zz_e~(Z&F>z^E+MxpZTf(^Lx`t{6zZ4kIno1KJ8+l?(=?Gsn0C7_zwQ_UarP|KK19G z_{Ie%F#V*T&-pcO?h^+tr`(2?LCN&|>1CE{7u3d|Q91Fo?`sJ(p*VtPSWFcr4`U!k z$hIQ@h=@xcGA_Z15gg;;SypH{tGQO8+WDo!bI_QMd909OI9rf$;@lBDN0G3bXQ39P zTjT3F!n6l$((sk%(p77* zpu|h6GL;mAEQ8`00gRz>qo?{e4g6Uvajx`RqpbooW>PkZfdU>kc;&hAhI3`acF}W?`W0i{J9&iWBK$mcql1{xcvj=mKsLkr(7KulBgU4z7#tc% z8_@d{puy>ryi&q+?f^YTP3uvNXhu{Ama&p%MLOF~Q`c%7#jsIKooEU(#?zg=EaQTfp*=_Kw#-3;QY79TW$1(n_Dlr6~#;9`I z{`G9XWO3Q$!q9atzvui)R;cb~TkD^<1E3KcoM zQ`^<9@SvlU7<*QK$gM8OkA>vtYc-j=eO*LZv~GkC2bYZKcLgar4R*pY9-GdP&klgl z9)mZrh;iuiuTg|m(zY9Teukfma4^Dww--6#v zt$0MsSXezkV_?*i4*r)&>gblCJQm}T=m-=#{QI|rSjmO$vw+&lm%3E$xkxLDw2eEo zid#B~Cu2YdcEJgYI3L_{s3d+zx5AAJuMM~Fi~gtzUW7z<(HPmpuV3X}`aAL%Pio0Tw_uYpXxN1{h z9PVWoz`OSzh2FKpd*1un;l1yDy@&1n(l7n%!>|0xo8g~r^`T>+4aee)*9#(kopysx z_U8cUm99@S_@~%cU%6erCL?;7Yx-=1>P`ejeq~`o_-+m`ycOA)G5RPvzLq}8mVSA3 zHjF{Je#h$p%G?<_>eJ)ow>u`1*4+rn7k!!71gkA?`yXcT$g3Z+D7dcE4J1h`?uL`7&eJm5|Kk;XN;G^F=nz^`MXyEHh1DWQ! za2Fc*`qIEp{%`;L_hm@_>ARP&exvuS%xpW9%L=~t$Yy*0ydV5HtD7@HFx&UH-|By7 zfOEG>SO2>A(}5ZIcSk_t_MmFIeY%*AHeEyi#H8(S$MpQULHGn1@ZxJg>O~UYq{K}u zgQ9_U3VdVW!3u;9vjYO*={;+Jgo-VM1{owMAHXpxYz5RKVy82+&3m{qqK3Oc2#Ph# z$Rt`!{VFAB(7RFkX;h zAWa=(d|5FGNqI@49QB=ihEDS}MiXNzPt@V^E7uRNedBvmU6SEgPEM}A6!{-zB977M z{a7{EGw9$c6BZ`!7^{rZrv~6*$hf+dm8xfX{<9`^xbgm158v?W?Zd;*-#fhZFW)`f zii`&Lc=U|1=*06}-RI75WE^wy#Ba4oIXGK@zIWZIk(r#Oy2SX4Ou;c2vPcJl_rDpF&zX4edST3Isp?3^w9~H$YrGt&6XM3L86l+#W!_!Vv`s>A3yb$ z%mifM;|s;`a@RgI!4yc#sYAQnK@*^~!YzC|Llyyv^^Q!4 zazb3Wtoy{Z9g^PQPDe()4Cr3XtvrcRAb7}k(uydpTQyo?69rdZnCsl4pEjTol=}bW z&O|80hHSKa#*Kcf!Gsn<%K`N0IRyzYa;~x?4>1D1FjCmjVxECx7;z5J-WF1oD>JlB z;(?cM!Ni4bB|%$SC#sTGMj{J2_syuZ1kMt*7u>}1Pq<{7;u3i`N+9L!$TRV9<(8Tn zpRyWovC&0z(t4Fh@#F?O@TJ~ZVX3_>S%vg_jSbz=D|tYPZH=tnT0Vm;X>ia9;pz(c zx}zWjt{kEZnrD-9ZT%K#eM4hjGm?iy=C}HNLAwM}J}q|0`OWi^d)nMI6qy9fU_0&C z(}(XKUd{XeAOFyM4j+AA+O2=}&kt7({Jq8$A(XN~f7=O-gSIRLwaW&Y+BKj4vy%y3 zI0nbyJK!{tnL2`ws^a_hoI?lS%4<`XFMs~<`Wv?oSJQ^s-fy*BJ@Yv~gW$VaDcA0H zdwy26-}9bV)8^_&*&mkhI<(WuB(v8QwMHg2$YSE+ zdL}BLUCwHGV4r0L-sFS4KFGxHNj|v>-{4&zlb5y{e%|`-J%0V4G(WF&%>dpie-AQD zpW)mV{haDSJ?&?s7k!io0M2;@mm`CAU%z1ID4Jw732bs)@%o%?&x}dYK7AVe=;w0! ztQ(mGIW@Tun0xnf9zxQ+^UtOLZz8~?fIdYP3E9%$uL%U^BPpLB|I)Gpx>CjGy(aJm!Ifh1| z+A-)QgrIaFum1EtYECfzz^&g77Q1B$57Z+@j3i||Xc2>~ z6NvdXevI>fG{%>p26bHF2jqy`JXh+0>9xifgcVns{PD!iyR$q2IHtwlFqjxelQbFR zFKRBmqY{_+W4Qj6$j>eMyc?a5cr)M*NEnf)6Flz08T2u>k$^Deh!U5`{4-*PW3D`4 zcOE7o5plt9aKV&Xc(t?>N1j%#5L7OUXvy)*J6J~4mZU4VA*~K6|4JQyKVug-+vpLV zvb7B{L>B#PG3rbtu!zvc$Y7S?^fY*kKf6gf;gG_YrM_p$;LP?(1AVJGNHX%QN=d(w zRhO)BG@jwe**#$J{lv-7F;p2seJ3&o;_Ki1p2MZA=HI{fAbHCwQ~Xx-og8f-?16dx zwL8N<#=ez*&lX-+VsudzIj&qyeThsC9|YWE6mrV*o$Lm%LiOnLCo#gZjg*TFwzGEf zAS|qM`HbJ;QVh80=SEKbe-uO1c2M=+yP>xkrJ>#DIs;6SRVa#!j3(1!>gBbB7@^sL zVe(Ktvg3k2D{mki`c;E|8I-WOuHGfRby1{pqjz2a9YDcX7HS>#NhyI`;-w39p!EPP zh)q{>gaI_7_=27>xGw%mWXKO{QlP|^t=s~oFcq@?qHpNLOX{wq0xl7-h%2o02?AV^ z5+`BkC!91<+le0;<7qxp?@RF<5a2~;m<*>Sb&}M{q15{qp+c|Q@q>OA*KjTs%su~0 zPD#XSTbw(d(q5<=fs^h!dBR})jTbD?K!F^L1y@GrW33?4&-_d}Ey9TpUGOXFNRbCQ zE_X1yE-m3o<2+dVfrYcE4*sGscmp7PWSD#nlTh2`xad?a6{=+@(l2m3T}U39H}`30 z3IjUyn%^VB!o{jG#KQ%D`5Z@>F}>odM4dzwxi$J-q$S!^5|H^ZO5X?q;_@+PE7g zdZTNvjorR;yNe^*pDUTXFwnQ{{o#Yt40s=Bu*7 zg&WFc!D_QjGWb;Cl|<5scF#(`d~mnZr-1W5ea~~T>+8zeO^|ex!cjun*~I1U{DX+y zNdx+N5;`VZXEGv_tD&P@^)GAyJ5k6Gw1&aa6J7@Ymr@Rwp+r8rFiaZQ)quurhZvUG zwZl81A$TL5D@4LW8*h?CKGo2XHU0YY7vGo(@Bj6afB54+^2dJW7k;*x zzqnjz;OjsG7ZU(q2ZeAU!f4hS%8Q4|NHvc< zt_KyBVj6xhk$qedf;Xlr8y~vPqW3@!8yyc^0P*(Q&)`CZp)^E;Ge&0_cLD$&Ad&3n*F%wvHCYmOei_oP>JAoN6sS85H(hcvF(UjxT=omIhQ9gYaa_OkFVgPxk-j;L& zZ$-(eSI?bhpEU0xR)!cp(w)?ARoY|&Oy!2gWW1^gJ`_-!t!m z#=xR9IQU7ep2EyT#kCB;ujgC(v}__;l4M^{JCKkuCrASKjcngMtxASBy|bYMCZXjs%j^ z7_KH95}X0Q%#vf$o7u_nc#GwNhPuq{d!psP^~v*sMzw`i9o-xQiJJlJv=0TKl;96$ zq>QI>t@xu50Y+&77S*M!7q888F`tYQ-s=N<$9|v^qr+LgF{MmkCLQ3p>Bo*@aU)m*qCI z#S?veXO%lJ<xi>H{LuCE6pl9Q6i${vK~HzIolsPF#g9DwKd z-#q-j-~Hjkhx0nr!(ac^gN0%|tVo+kwYC3gcCDxf2J@PYN7>caA!Npt-5H?GN*mSo zGXMtQo(ltFXLe-4x+~Jxl4e3d8){-w|88aa{{1J1fAUX$v-GW+cgH~ZJxlxcxi6eF z+a@!e*x%3JrEOH#;5&ejz?u(q*-hluraekKOl9DLGNqLWStNfN%f8p&iQLHM)dhXk zt*qWx&M?uQTIsiwsx}z~hlaQpX?N+x1TsGOPy4H#53YfH2IhA{&%uA%T)Pua99kIt z^z*Sn?BG3QeHKt&=+2?BXmV)k7y8AS_?it{SO$xzetB*)jnNa4cflnpLcHed;A)F+xm}#eXITFemw^u z9nPEwFlqeVf@}u6E-iT)=hY7!qgJB6qCY0uOI^R;3X8g!2ZgGE)VLL%`~B^lv6rk{Z1*N*Gy; zwHGlk`?)%VLZyR2>EXi&WyFx5QAAXqRWcayV_=cGMrOij3wQ7x|CJbwH($ToT?*u3 zEHYfV%51P78dk_=)hmh&0mdf-@y5;DfzQ^hx(D@1v3oI%JBK`hqb^ zCPEN5cXD5M2w;uZWke^ruhb;{YF2*8zu(=gd?~~Elefu#rOu^0B0`)#>EDFJy!UU2 z5&#MhzKH?)Fqz_Yi$E9NL;*c0&(^odGLr~I9^6j+#XoIL0A6x|DV$2jpG>sQO<4=} zm)lEj#gA@Qg)RD&+s149LWEM6JjqrGugGKCif-~|Jb{q|pm2W2)zy`L-4{_C`I0D}ILb~5lz!s0=_nR} zFXcWFBFBL({*K7~$QLrYP1{iWE{TqX2!aKQ@y@>8Xp$AO@e+(LVxcHD#;SH6kgFh{~er@Qm$qjW-% zj`M2bwd_oKBL~U-{*Qg@;n}?}r8#sBCykE2RXD1RDCvYzw6$!7?R|*0DNqnf9tIWhkx_=`-eB*dYBddM~Aob zDZjVl_entgp*Hho4C11$LnTt>T52} zc+t=3OFFR-Jy>lY+JWlpFspwF9@*tpU*r|BfL341n6mU!*V8Yc@9;pM58OX`m7hK7 ziJyG<7FW@1JAZ$|(bymEId2OVPMjF`{o{Dil1K%$)xe@?ZYbKm6@KoahU8p@FZt20T9(?m`1!Qw?em9ilN=+pyy=Tr`7yTa8t@He`sl$^!QIa4jaLFVIslLEe1b|j8C++D>E_L>l0>o? zUA{Dc7Cke9$ZzX@Co_`fL}vrz+c^x-PM3!{b-ELOG0qJ9Z`|ABhV6-vT z>>zlOfp<{LNA0mP)BKP%U}Uwr#2_1^HYFJ&jiD?JJw*(MA6%c!)O`behNyCxx?+oJ z&R_`X(y&_~q3+YfxZ3JfN{ z{HK(1K{)~;!8J3Jz9Lqfw3WU{NJp})+?N~Uc?dRrCxpN`u*7~*Xa)BpPzvIfY*Y6q zm&C+;P~78N!f4yjRu1FTJN`|m$O*1+@9`H86#qi4{}|YjUvdXA6N1R%H#{p}2Bafr zqF*94`k1JZc@vhEE#6L<{0Cx1?EDGRd3Sh84B}ZHLVXiD>P1aIi#`g6kU;N&=pCSV z^xe5)kJoj@mkpqXi*!sphBlGhcii?&n_}=25=rmhrWe_pUwO-Kb~sFX>zUhRcV3CG z=~piJp}6CS&21g-_|0zTX`qf-+`-&&h=i@IC{MWYh=t$&J5EfK!MP6d)}QAW>|6{4 zO>x|C7Qmyo4j=#Udk^38-n)mBx8CgQ{dNa+pq}N;;oS+$+)WawxAZ0r3~}20Wu;rLB39bWnG`h$zmZ7+u-e00chY9( z4o|shue5n+x?2g?Rt?pe1kgvK)4_ip6T2P=s7;hV@Ahk>rNc#&e9eDoa{=64l8+ieYP zOaMH{fZj%8r-)0p{rB;sM``>YcQt>n`tSGs_k_Uy3P5)Wtcio!>aJBkmtB4az*=$8 zS+=Lu-D&;Psin_fPPhQMWW=G<%|EcZ+}rtzXF!7GkJHgJ@M>m+*NbfX(~(q`vWejk z&>4J!lQe|S{PVch*xzXqb*>{=>7^S_>bXao(E@Hn>3wJ>ZoA5wz%qs!-TX0hLU#El z&!ZDYNXdpc*()(d@z?A)(o7gY{;Pq~!fSql_4h_Y2{O3jX<7}j<)`Y94 z`6Px<3?zu*=Vnr&L6n;EgoMd zQ38)=Cjyd2M|M^C8<_0MSeAOGAt*?yIJ~92bPd0p zCKbrgfh#X(IPx{m>Z(K9;LqVVa^WSu?RTE9)cd8BbHJ5gqS2V(%XiUa z9L1(i8DuF>I!>(Tr)9hF(TP*u@&y;!bJ=>yF9-X#VbF!g<;hJYa}*jV`tckgN>lS} zj-HdgaNw1ya`r3kic?48M%(oyfbMcEzwTZD06+jqL_t&)82yzN58mpu1M$i$c@vu! zq2VOO4?#PY=g~o=^sO8UgSxuB+LFR1s`p?fFYUX+8-4YkgJodIbF6Ferxj|%=wzi; zp7;Yeu;fFe*HS~z&t+m)TKP)Yu;ZPx2u2pE+*VKN1f1-!$UT37H|yB;I#AIE9QE*0 zUMzo+_x@kI^5pQ{-}<4$>D!+>JUclVdEf_?p1Iuy+(|ojGwth*48(o*)i!;)?_fG@ zs)GRa8QM03a&4DS+F3d8inew*L45}qA7#OWUt6K=l8=^Y?gr4>zY}K)Bt;v@7P*;K ze*7_%?@bRSq^-CM?j2Dx@b}N|BJ@#{}_cTJ7U~$^Ne&$xbEaQGZ+x*|oZiwId{KLcJ^h3{ErXz35DY7DB z@RNV@=f3as*^^IYm4~Ag>F}G#oHfaNMhVE4k(!X zVz=yMApAOpV{BeLP`4Ph zevCo5vohjsI9y`tE_w@VM6V)-ERqbM4x}sFG6=)JWf5{@W;l@7ig@#obb|s)HK|o2 zGI2=PzzA;>V9if>SS6aBhiFJ z;FBR|5?I~w^X%>w9Q4%(@Ab3E!N2J0&gizrS?F2WSBCiC$<|9NKhI+ z->jV8^#n(c#S2Z(jsg3P>>Sv-?tnk2H8ewrLCfKDJqG|HpuC*;%)bxL0z=N(b`C+^ z2u@b|)oey3c^G;8&%JaTm#8V@D4wq6y#{fN@+%oUI-fy)tm0h_eav@xI%j|Z+fOV8 zUwLq@%R6CA;>3}q>4?_zMX-RREv9C9mZaUYRee?xN9+OohcpA4YjaZ98LxK^+gRJjUxK2lU<5mn@u)3(lv zSK;Ue?AfnqE4Uc6UU>b3%(gN2$4}Q_H~wNLnAD+Nh(ZNFDS?qT`3H$h{ye$9O>*-R z0S0G94(cKbcHtQK4*!v>6KP>i#>OvdCA0Z#UhZ|9SOV&R)=7ak+9kgwn|w8IR4WOu zinU~GocR0#Be>lWchP8AVhLzRm5X5R3(1ZwzpI%Tx%~M4;X|+9Jbd(nZycW9d;4(P z;8=MWpoWwF#pm{j-knG(L+{2rkkoD^yR8V+HZAl`ZqAOSw3+eKu{M??w|D!|<@6`o z)3*2Vw=N{jWPnF)_%G|Zkne)54#JbmiV z|KV@{zAEnGa-o5*fdrb)4WtHC8ut$7ii27PWe)ISeE1b`kd8QoZD=~Uh6A2X5SydH7XxA&mnb7v zDFUyv@zcrlLDfsuF}QTdR&y6&)>Sak?szrPOp}pnp`8zuzW9k`$c$k4COW^2V}|}3 z0MkViTsKhslYf+SkkXJES(1Zxm@w;V1OrNF|0FC#@Rg9CQc%lOZ^OIBrl^0BxpVevBjR;YqywBo0{8rd>m(Sg|pG(JQ! z0HqgU(xn{z$e42M>TvEEYL4L)99zh1rG&hJWe=r`$c2s3=p9B?ppyxCX1uG;8B2G? zXKhntu&GV`RAk_+CWUZ}nA{U~vOkF1IccAfIPYo3APldrba=Ot{z8{N8Cy0-`s7nr zYz)-H%kyloZp**t(m4jtv$N;nJ@1?56IlsA%nEN z)9my)&1(S;4h&dzZjh~>S9hVwI5ik!#M-f7U@u)h{Bs62@@@jc3QeEu;5lrn-^7lt z#i<4KV=(Wv3n43-$^~B%Fr2|yksAyH{&^;!<>0SF>J47Qd{)~`Za$5y7^oNB2@pLs zFJNV^tEj=^^~fhDVSw8_ql1dF$ZVV@ zpGz3rp{E8<_=psGXS_;YzD1#*de$8)KHF*KKKUr=0!FXVWq;9eg$tg+Y4_YV&hwLS z;M)Ewi^dBtm-K?5xn1d$VzaFDMlTy6!Fb!w)f42j1N{MQ*)5smIpHEeFZ@~9Afb7Z zR)^b^PbW;lt3TCC1Bu8pSb2BYeOxCG1dl||rByeQ64xKqkbA+bI0~u$&rmBjmUg8? z;$gqojBNOywc(?irI+a3mwE`@$q?*ILz|NLEo<^9_u3}?0xkw^p2e9kQ&xdTicY!E zD&&3unm9?WU6BXB+?4guKOa{=ICY znasEv8OUTX--B$)lAnHr%J=J92KCo z=u1;%rC*s=9f_cKrk@%)1k_*0+!gCG6gscRS43l04CYQVF3;Vv}r z+p2-j{M65VSGHPxI)|cs<35?cgZQ+@ue|qt-G+7V!GkpVK0|Z=@b1G0hgaTsPY(RL z-qn1A1E2B>eg_wwK!|~Dpkcspc2Hox+uE)~6FhG9Z9Dj7?;CmyQN{^_R9Cp24(i;a zleDALa~+-d{5I2-#%?%AtQ|_h%0mb9a=Hkej(A4K5g^_flpGm0w>mQx$q{}fAHQ{c z20p&FvVu&G-jiw^HLL4#J2GOy zSb~j5`D9|i3X?q30U8D*R=^oew=(c2$(IO)UfY%+58pFBrRS3W=4q0! zt`k>@j`5*^X5&Zxk!AxVA#$BVF7F{eNUb>m*%-h_vOzn4-K0ju(a9O6@TM|)>+=xd zN^>QtmoxDg{{G4DPbP@ux%Ayfb-#?{(O`e4@qr=b^6z``0VY>Ts=OOy!2nUp9b5zb z5*G+KTybYGP_bOdy4v;z#caNb-#R+p(TS^0OLy`s4qB_Hhic`&xk5kT?mCdm;Hi%7 zkKAFR)j0P?o)ZLR@sm{V7N`jeW!3RUE!dLcpA3(X0U+L_DT|SBGM;z@wlYeLj@FYT zu?kAtkq6YPP}+n}mh_(V$z1bS^r2X9X$#BJ=CST2Td1iCgL`&umJ!IWx2k38#>Q=) zfM5Zrc_Vu2AbMT z?SZe57&L1${AstWB%4r?Zbuep2bA`>UtWp8q_E{&8%BTVT+4tMZLqTUG;KJ2%b$Kg z`-jFHf@+0a{lhb>{h5^I*PibkPiRtxHk>T-=aou3%Cv*p&Bu8?jDO2un?2^;roY-s z?KfxA7q15n))BDsZzn$T zdH{TKUG@4x`dx$mckiDbzK{bCA7+<9HgI&(yt}Z%m%Q@pl{6C+vY||zgJVKNi$;c? zw-A3{SrHc=%8an^<$q)nnKCia5qh0ui5~2L2-)yZ+Ch8%;=`GQ`Skz%!yo;w1TWl$ z27X&LuzT*`R;Cxse&=f7ul&r?e;5qU-(wuP0Q+i z;yK%}-hTI;!$}7F@A<|LAD-pYVUN>*TirKv?3DqljgK;bILVHHZuz%zm^2M-JM6Z| z@#da(x{bBgx2N?=;|kl$gcD)5K0VMHoaqFYAsQ5hdyRxLLCkN+Y~$=mcd>XmJRQKq zo$;-NXTc^z_nX0j4yU2WGXt3OE$ZfO55?h5AkzX zCc~F;$HVH|8;nPB^ddl+?((q-@6u>Z~|dc@{N@Nq|0s1cQsDr;z&ouK4^h zfC^PU__b?KYK&QVU;Hm+0>JOQv#KVYA@GuGHWMka|K|W&zW|_D%?8Av;|$(lf9h$o zu;dPW(25>h1{i~+Msv--ou3#%2G-dXV4!VKEiVqLW1Qfq9!qci4NV4=73dDe$q`3a zR!TfK-u0{@B{PAyl7YV<*Ifq*d;SfSX*>>l_8#;$>zH*Ylmvy;G~fv`nQArZ+fHG;E z_g1kofS;^OPeM>;f*WYzXyhcC|>IIydzj1~)YL)ahw}#0I_@Onn%J z#g@r_RyB8e3J1c@U78&XKajFMNeg z)a3|YohT%7FIV57oKw)G_Zo1nXfE3&k)C!Q-IcAH?ww|z>3o(6?dO?DdXb$aoxn|b zJNKi+0;fI5LlioQ(oMBmx>GmA5o`E>X}^|8y!~bpCg@8Zd55HaaIKpYwZbG6Z*>#D z$&;+%qpX^q_?_En<8ViMWGZx?wZd+_v_6nY`wf0%C?@1Y&P^g;>c3lD}J|6c2j z0r+X!J*(ih#cvu0>zw<|nLf(T31uP=xHxHF<`(P zn%>73Zl5ayp&?&W$5sg>TD5Yn%#*Z(2HfN{0B`%7z|F`D*C1YhZS}t=@jL$@e4T?M ztpoPZ(EseV6c@WC975|5#rxSM@opv@-ptny9@+Vjc3NwrZhO~%c+P4)!Q{i>o@%Ri z`q!W2-!8f8mI9Lx^*B!>6S4i6NIFz6^l|z|UtoYEKk`{yE9midVju|oAIa+>pZ;I| z(6@gS=?izEf!{6-OzZpG#qEO6?`RGD_)mZKLut)F_2~5R$E^Gtyg$x6`VNY@a`%

    oqQlXMjM6iWv7Z)Y3bjk|XbANbaf98U9otwU&h6`R>j3I-D@R!tYsv9tk-jvN42!44;V&ZH9ufODAO&+7 zHUnE2nCDbi_kHB@N}r>SXRL5F0m~emP6bTZI?msLqnc)<0v(| zjFK2A@+K1<^x)#ZH*oQYNL}IMdPjg;H@fFlAHKXxIsu6P?ulUdS5^jFGl#Z8P7IIa)1ZFz#Yh}NRxfbs06u#0>VQEx@ExT8in`)UKk3!j%{?49>2WFD)69Tiu`!I%Z7G$_+zw-oIxw!Xu-D02yyrL(6U* zu3sgHh+wW?zYzn;il7ysnH*$vbr(Sfarc%>jN}xP=7hUpibFDb_PBfRh0zepOt(7)qh~c)2Zha4aT=e zi&4mrQ;lq%0NVn~wXQaGWRVX)bh)XY^)+{s!%5qo;=L# z=4(qH@Tt$}H%5sbnyFa&Rki z$8Qpqdtf(6W!>^7X(lR%p*(t4I|O;2$?ZoEGWdUxZ=7c^_VncN^yFTi4ew14dtaQG zuTIEYeyL-1B`3G);i4U74qJ5ED&6E}+t?r*G;3$=%1TmXh(B#AA!hJ7 zlL@|aZvs;LtgSOqr>%Ptg6KJ9Pg~X3wmP^Ewd4gK1MZnD$l%nk#5deC3M z^+5*5b_6KTPJl!veAI!y-ye8_`jnqZSLJ~JZCm&wH@R8{f$wU6(jUbh#Gi8jAs%|M zz6N0eC9>E}K&N(8(Gwo+OA>i{I$u$ECoBFBa_FBgD)hCR@X}ln$>jI7)LHyZrgTz< zKEg*jx2r$>DIaA+ryd9Wgfk0rYnkqyK=Q7ix{=ok(Dizna}C_-&F-~|5xDJ?dq6*y z17$z;XaD{0{LqfSxL;`CtF3`l&>KJ%HMeIqOGe<_{C_b}og8N7EZe@+;` zbNBGZ@A}~3G!5*7>;}-7=Bof1_&-deKU-`~1pJ$~-acHtbNld(zxzA06X0sz3(f>V zCI?P(E`a-k{7eXV54Woy&6dtc$2%QOdkU>~e*kpj(->>`ZCBJu)#zx14t{+Icv|S<3JV9H2Q7vdpieo4q;1EgMvt3;vlaMKHkoDM<$*17|IYTN$%%)EJA^s zJO*Yb7kqHYsguJ)vJR^B+F5Rdbw9Cj&Xb1lk`x z*U4vo6AVCMCTY@>BptG}wra{z)X)`Q67m_>@-3ZS22TQ<0hxffxI!h~FbN%irO}il z0>Y!qGEY3dh$cMsXwedHz>aosW^$)s4L3iy6fbox_3dfkyW$-94m8Va3`i37;JvW2 z!e=LdmGm0r!8M>}AeLV4lYeGR{sOD~ZTlC#d-q1)bHC=)|I}YAEfz`{T#PKZH)04m zxtd{gn(dgK7)WN^tz4>`CIe1<)-Mx%)G^yMXJ=1$C4?54?&pgDitJMSR`~1BGt2m6 z^gVd{L3qXh3>{wV?UbKKEstOWU+X zNk%tS%J-l9e(rfd6cv-BXV8wpjc|O{rI7l(6Os=)j6W5Pd?ktr_#zNuVdhrZ3pH`% zlex-S{j4@R$@ADJ9VnQ1w$VNu#Glcr{u4wp*Oi2RgT=2u!NEH3i9ZhLlw*TO|4VUA zDw7Tx zy&{v~*(d~^Z|{mvOv{iAqtk@JhzC=@I^CFLBIQ6|`3>E~m*Lz-A5)&YCZ5k9Ds`n7 zACbbOvM-v2FCR2F;KDn1Bb$=*=l}RS2h;o}+`KG_n?h z)WP<5~IRNl9tN+zZ(oZr7y_OaJS-m#dlWpfFcS1HzP1;^< z$Fx-@8c(yp(FxD2V%sJ!ZZn5t3%ovHPtbY=>uKIex3ca$q)f-O{e9=Yb5wk~G`j#o z=TR0&w5fJ+J&8o;!OnD`FWar zKg>aX&OXqtKMX8=mv5wTUVuVsUzI$Ktuy^5U79#IiD43;Wl4tc$}N2250L&@d#O!# zm}3uvjUb&=p*yc*^p~#-wy1&e$MqU~_lYA90^4+o_a!%w?Ujy<27cm_qx6`Qy)DS_IxmY^1bmikNauVW+H*t)CIY&VP8olNM zVO;AH#6)d<*&=8J;gu8e^qtrg2g63*DoYH4iaLnlwRkY{SZS%Z-R2%&R||~$+OQiq8ITQ^1vkdP0 z^?>MDxpntRWbr&{imoS5xmCVIg$pwfzvxf>61m*?leXiEm@-c0W>PbNjWdx!8>ofv z+F>HChwQ~usv~Tv3!^bGbjP2%P@ICC!PO_P)3(azc}Kj8m|YZm3x4Y|_0wh32S;8S z-ZCN7q)Ifpq>tj{vU#bq+`1dQUrv3gZc>-ebQKx>1&>boJ@cNE&AW9C{Y@{-l!9>c zXwbvol2JNd0f~cySN%h;ag7%l2T(Y_!2w@i;|r6-oi^cI!&9ExPDgJa`Q0BmeC*@j z(LT>-G5^?q_MaX;{(HXb@bvM+VG(sSZ}brK)I3Bgzjm)KX%%Dzr-H4d$Uw&J)G2be zZZ)3%;<}O_fuhg-Jix=lXA%2)m1p-@PLtQx=TIn(UXMbA=z@o{+C((vr~jpg`RI7~ zMiieOJpM`NhQszZnkmU{hIVaSZ%7{9>too9LhwEu~ ze^&M1=mJ$$r*2AJHQxYR&dN#4$G zE?TiOzyOq%4T5cfe;&9zB5i-6*ooj30Xe>(0lf)QE9v?nMPU$b+q}t!8=0KYc1eFV z`LUymzR0Jh*5F@5Fb~>2G$3nG{$%FA`~h zuiv8w6ECF$H+)>XgCcs+ud;dbJpJI6XV3n^r~ddKy;YEl%Y_EMiW=|)T(}DjeAP7Y zV?Xxd^7VJ0e=?2RA94D3-}$l_a5H=p>H@`y?y8KZU*>o-+MQ+wwW9_&57Sx z?KhBTu<5Kcu6jxX9<$qDc>A4nZkG?=@!h}o@ZJC3_Z`0T-}ya8 zTO1icY$(ZR{xHUyEJqpm{RT=WZ03KErsEl$q{BIncNV~gt+ilKi7Uy$YktCmG0|u& z7d@R9{nL?cm<{H_c&V#w0#c5V31ayF<*Uo zmR+E-$_;OfWOX14m~uWRW6}W?j=#R#kUzWC&(N4{u?>z0=YU4$MIm`BFSHqpapgg- z%DrTX5^D&iJ~KjAwu8%nndZ5AhaWoCSAdEW8NpbgW{A`P30&m_yXaZ5R%JXBQ*+^o(3q9u2&`QowKZVhkK~Ln6kEt%@-q8KE)I$O^lM@R2Wgwqx3T(1Y<%4p3Lj zt%m3CNuJ*u;bAAi!}||&l5z~B7-?P!a2TMiueUN;@H})lhMG?(J2T*l}aQ9_#zk{Y+*pkjU8q zO@|~aZqY*t@wvwAlLGVE+&0JRSy3A+UTwLLLEyY>Ep_Ffs4^!99>a2e$wJ4=S&m@PQA=P@@CG* zc<1f64?q9&|M2kFf9kJ=)APf}KlYu67d`u8*OjSjG&B06t|`wWKYHzNc(%+Id%T;P z3mN!F9ud%1-WI$*sL_Q>{Z4o$qDrMjh5lfPTV!%C-^PfP8_cJS$`?#0t|CX`IlNjP z#{d*<(OGF#0Cm6sdbJtgRy=m|8@{SQlM~!vX;IR4 zWn%HgJm1nmY31xtjzOk2RmsUJ!!X{^%C&v zQa(sJlfjvsNIT148qHgt%*eIR26z&`T?wsSk=0iN?q$H=!vLdW+y2!RawSXs^}xim z+ucnO#%Sxu)IB!19wAN#ST6ho+V<&3f(=T2W`g6}>yErYBB^ATBmfC;%5|>RcwWDfQ+uo$YW2y5oJR?#8UsW=YL+J72HqydIy{M*Jquv1!Wo#W`*?Y`vEP?ZssX*hCzCsgtt*Ds z-aBQ8bVmZYtu%$#X;x=qMU9cOl-qYe!`~=#`#pFS5FXf71ORt`rN?@gHGVa3wP&x$01W#G{FaV z?n^G*BaC*Y2hk@szlivUE=YRfi>Du+6l2v|aYAIjQ z67!|A2}FdQ!l+073YPoewOvRYTJokUv`q+LSGHSb0SJ8a4X#;;48@_Zp}W-<#Ka_a zC5)aYSeVwYtr%r3M`)OgaZg&&r@SXMQ3NRMO}dbaxwIh1jhy4JB%4);HVh^|*o$1_ zd$?j#mORA+d1O2OMP+h6u)gM!@0Dcb|H|RLuVmNKq&3WZn8i-=wLx@oX_8RPknNCINZq> zU8Lh{6G@lbZ_HT(Pfbi@(ta-o5*f(9-o0KN)Jy&yRn_^Utl**~7s`u_x@-)yHDUZ3cD z>&>?^GP#yh|L=5buvyUi4|9m$v&=fDA>P~nS(a&kdnirX%5;RGk%0!I=XOpB|Mg$~ zCx>7CrC&Upyz{QaFiqo~hP5uZ8q^vM@wD@qgj~UL3s%q29%bDd8hSNO60I}vE6xfF z9o?pph{2qDjnf6RK}rX!B}d6Fm@QIrQdYy0cfvz_I@B6v2KzD!F!!1`i{KfbNvDe% zb>)TLz;}?KcVj08S7*IRj$RX4n!zaudiCzx3X2?=QdTBMA;h1hFJ&44@{Q_+x z`iv);MqoIDW<@22VM7x$b;5$J3} zy@QltSsysmhCe!GThz@a33Z!9^Ial4B_eKQSuz!9VoS}$LV)QA z?czyBuXIzV;+ghwO#&nhbo+Bi1HL>E{bN)z6Th#8A06!|_exN@6T9`-vsgL_hA05^ zqZGO!w{V@X=rTX^N6tQ3PaoxAyLofktVc>^-!{J-bVb{;!r9CxhBm+0H%tUOW+g_V=b*M6D5UcHWPoqQuU0|{6sn18` zu_IIQ?^g{vPz`vuxkv6!AOznZxzVcLGlIt7;G2HPWfwr5NvxGu16r!}g#vij^M1T% z@w8_igptHfuB9)CA1yl*u3k%8;Cc>B!d^{q)>G-pNL-TJmWp$xfDBGQnKFy6$VRTV z`Pz^CnN%=IYrxMDm-^jai zdH?_BE3dZSHSpIVSOIZ}men$^1=zx6Ao1c^I?T-erWro`(m(#C!*65);7QI1=oZ|p zu5lXUZfjc&ygnlBuY}w+`qNQNWI{TpbRc#64kS^6X9mE6krV@9ffQ~0fCtaLG}paG zOp+?X=7C&{jiFR_gB~2l?lGoFVDqcfop1nWP&K?3rCQeo=!`cXdj)*+5^TY~zeyit zh|!5gJF;{VC;A zZoD0jRkG3_U~heGG(l2^c9%E zsVd&*G`Q~jl}~2-CsWHad?l+tmvcyy9Rdu~4(PKT)*#-G!T2=K_N<7c4pM;JCjSgE z{Cqah_R4M#jl>LEMw7D!E{E@nd-)t-;BB8Y@H^IlV|m4h%wV74DnC|`On6+$s*d8S zff+o{s4f4y4)n8y*%iQeG?4OHKRWb&f6qvW$v-RnV+g`$(9;samBR{K@?nMNc`~;T zX~e%3C~|iTwUB}eOif7goU4oKslPpdRoq;0_yaowti-KnAW;c`8sM(F#fa8ST76q+ zrAu#hiDdkCm9c2ynS`CZY0cBB?o3|GsPLOiAfkh|RIT`lU+L2(ROHYd`r4oJi4Ne& zJK5a^ty-DvkcZFz68nrc_<>zeTcDTWiBpE6hr<~>qKj*Q&bLE@Q~^qNvmfF|w5Dy! zl@YncuXhzMW!-!vz7roQH>J{T-q&s)a@@w@|Ng)JUi!ITXx!&M_txS1t=H1mrT#4r zOUyo_^DL*{MThz{`Z?rrswNu;;-Q$$fu!byu9n)t>Pio)87MYa0f@&Dz-Mx z?jr-$N3oOasFIiNc8tePtAKWpdP!RsT4bJW^(H50kn3JO1z4M4JH4=-RCY)?z)wC6 zeox{zV7BtC-8VUUJMvmV7w?q?ZI*)bdex1jsjenj)en9$X^XmJBK|Adw(vB0;ADRj z(5IPPR2QAS(aDeGQ=c@u5KO+#Bm`o2a+s@EA?RD1el>V@P1sJ42AOsnMTU7DLVZeG z6`g9c^daiDJjx3>lc5&fZ1b0gC@{~)mF(Ns7t*J)>z{lC*H;1X(q85;fq;ikCKpVk zmuTqf6ZDZ!ElA}-t=xg9du8bt=Ak=y%Hqm(^ahsRC0cg zb?Hz2yC3<+-}rm~{5L)|7#G(I4SeM^pr&593k`flHSps<{dc}U4gH^s(SFtHznM-3 zd{@@e$aR%JjoZDq-a7nR44hy2$G@0K;53psWXs`z_jACPL4$3&3}+4g{d4J<){q9bmQn73uS-K)Z+Pg?k8UL& z!z)QcuhY>t3`jiuy{*WJIzv4g59uH(!ve^SE1fUG5qn;Qqah+*LNBZV;TQ(zfQ#AQ zFUipd0sV24mX262xK`(MHDf%Wm0!xCcM_mOXVu%fC$1|sA$g{xZr~nBcy;1Ib?itTY?A%cpwV)r;hXLCVnDMvS^3 z%|PI~?Z7c!ujh4|*dnR_nH*z$gfzN#nX_`d9>ORir&Zq+acIUk2@)w2r4*}%ubI6#aKhrpjaK^O!p z-gO%}N!=2jZN$otJjV%=0SroXL>7~PkxzSDe$tzV+^x{9yr45H$dgE8(+1I8+D3Wh zU9ynU-*(keb;dU7E6_=h(^(BjMTZFNvN5eB_>Jre69G6b8=XNC)*7 zaw3z*7sF^Q0+%w8Skqsda_hf!r7Wg6`;&DuLi961&i;tf8&0 zW}dG(xN`mW;nIz}hqoU*J$(M{hlks*zb~(_+%l#)$}qUmQt(t5S8DP=xNT|Nl zrwtrmu1g5{PCKHUcG;VhXgM?=5o*X(R&+bzl=hm1jP^O&YpeCj=woYm5i`?Yn1kY)PTJVZ*$s3nXdigxPF`_JJ04)|50As_xcLlT+E;}b9=7iLypi9(={l zMSJRrbLL55@}Ox8odM8^2=tO>!a%=d0`;-Q7lYx@n^pDjNM87>k1*;aM__IJ_v(sf zN#3-1&U#S`JK2ytmSzU`2ETXi+$`OPkxLu&AO{BC&*bi-e8!KynqS27uk5$$Bz5vd zx7y)O2ml6}cs$sfWVB15ZAIY7q>lTl03FM_Vu#a7hlbga8JMSBObpn?K+j$kcqQ`Q zVq+2{IMsicvT;w-uSuY5HdrUWllLjh&PmhLM>?Sjtlcny5!Z~pAJrBnEe8OXoplY9pBr#Zp@ zQC9L#VzfWZprD_ZNeA#G=|1K6xnKXaY~}yQMjo+=awu2e{2u0$U(Yg7(J0=yc`J?X ztA}6w2mc@||Nk`Gf3pf0Bi+iJ?}Y1YyBexdWmM;9rnOFokk+_=X=umrI4dd*wcoVn z>n_}GC&-~$BP$KP4gxu8It&IDP&SlS-JkRs6vT6mE(5P*6Fn}W{Da>=5oa8P04$El zPWi=HYf1#riKOdmeEBAhQPy-T8yLYaiJ>D({Lt1BrSnS?`D#ohv3%q$@!)no2a{gO zRqEjfVNyyP9^UTjCqAN{i9r-Ux0SyDhX|T}Zi8Q)pM%*l(o>^znbY|Ptu!`$q&99D z4(%zW1rK(yJlJ8(LktFU}w)b0gvVv8EC~d&LKh6#SvUwNvR*Wco zeSWFNYT5?QivMGu_RPV5^5Enn(Uln)~gXuv|+LjwX#;4sv%A1HL1#M}t zD&#<@YwKid+glmF9dI#TJ0MpMMeXy``kN@vvBA19L%8~A-OfsrNynTs!r7r@LPHtJ zQwJ{m(G5Pz+awP`aZ(0-_cMO5gC}k337Q2SPh(s6RxHDE4^#@W6G1K#eV&u3?%_Av zO(TH+{0gXycRLBP&-4KFIV)T_3|-`paVVdYw`j-2=BZqg_d2)!CXD{hH=#yP1FAlx zvL%lbKCg=--r`N)@;AT`f``=-rRR)nItcE>`i}`kFV4<_dt|8Falqp*mbiG7ZHhSf z(Z>Ewgvhfv{?r|A!_^N~eA3bDE|t)}ngRdyTdy8&zWUw_#&R%b;H&@>QTiAy7aUp@eh2F)}?1*#Bbtg{8M%tGTNw))@86J zYvmz=yuDY{jVXTGu8NtoS=}yZap6JfL>7ImFnNWxlMU{S@`OVqC*dg`2KXA;?ka=p)Ju~^>cN3 z{ycW`&HGsy2lq}UKEar*)UKXJHn;}KwySsIHSMf(lWygNeEhU`o&}%U)Bf6_Wi_4c zHIs(g@(gIx<~c|ey%_|X{F?!(deDROLXR9KAEv&}1go73!dClL+rHuzp3VZ0W+2<` z^MM(>4Cu2XLcMlEzfT^hsf-IIPP;NJZwg-!HKTH855-?^AnAS1s) zy$KWa=M0mn7xOI6q%_%!9QaNIlxdzXlOpn#WX=SwM+XHuHK|}11zh!^Usp)bMEEN? z2jNyGWS*yd!Kr7twNKv9RLdc8GtoPfALy8z(bm%W#&b5q)s%xK*yjw%tcKZT_UPe* zOe$SEym9B|YcEbu|KfLi_YZsR_-FBf16CdMQ>`Vjn$V*;ILM#{- zAjO0cxMKtc94Jy^q!S}n*R22&VB`-l(lQL#hGD~M7>Eq0;db1x9ta|l3g}QukRX8} z(Ncm$2u$-$o0pgOoU`9Af8Xy{HPpf-*oN_9}vWOI5VLX zd7LtvPIjI_9b?PK9ak)))fuz?KG)93ySnF?Jv%fcU7@42Eu*|?g&m%pH`xWg002M$ zNklGO-0RfG{%v@n*&i7955S;DTjSjUi@6ap4IjATx9UY$xaqjbKfby_iT9X+-BOE@s zYW$O&G)|Fmp9@gKyE4dN0f|1p)>FWwlMs1w%m*bbBqel7%j%|FDYucKI4;~PpPabL zWAv3gD|gCherg&Z+qyOCtR+`JwPsx=P81>#zZ87-8p>syY{!A8ENOtDZ4KhqNw{~+wc!GSbnp&`?R z>s@dsyEJ?d{EhTn&B%T7kE_!2SDXY!*!%f2CV!MMhzL)x zz$##$VGeObR1oQ3W0RN@+zs8A6yc;r+`LbHPF^H5%P_93P;`y@KXLL-e(E&?E6HQr z2A?x;iI9)hve6z!lZad_L!OUd5U;%P3y($AIvnxhobtQBT0O-&~uTJS$dguUW&=dRU zJFJk5^9xR|I-72;YEh1GT#uls?s1?(C*46*_X@Bi+7YJt>A&c4;?ABh!#zIl>gp%k zphpIQVM?8B^-GpKWNF9?bU&zuACqZkxu(7IvJVRFDL__EoCZHam26g>94QG;cR4+((XYpPe!gu>0ezK=?;L@e}{?Q@Pq6 zTM7KTkU%xbzY9!T9RFTR0L8^H@9H1i+}-|p4gW0t=jtke8Fm1`cmI9I%~5NYO8HAC zMu+nLm%g<6|9Blh(^Mnk!w+9(soL{rZ>;{+SH80P!{7V8)gy-aE;Iic19rygXvE>@ zE_u5Ayxp`4SxYAGJ!&KX@tUzL9Tc|;y((7>+~nT4(hwkjTvhJv^qZdif!xTq1VsdW z^OVT?nmpndcpyc)ql*4Gd36E|Q63899pd>5+87+GFR3)+EO!ob-KHCQaa zDJ=;J%2;{PMorJrXp94luG9erf7*I+WhuJ#!>z9YC`%13zbarHxp+QGD@GTu1sETr z1f25Vvc{AvCpbub<524~W4xtZz)zNw^4vIc<1*CDsE|KpDT2bt3kGG3Jq%Q+$C3A) zcc0Jj1#Pb<3&*Ge<|I z0ibQrHf(tu%;?fjWX%0O8*^pv1Jg0uG}N+h!8E$y?>f530W^(Hd32_XL5S!ZV&EwT zGU+<>zCwYpD35jQ-U7rUFW(Inm*vcFSbnpPtXpTDI+!4S20Jahhe8_R=C_$7l5#Pi zk!P0rho0>tWhR`Ag7FJ3(S<(OiQTlpld(P4&v)<3b4U)BCTrqB2#~Pd&P2n5!r(J0 zoH8(4)xi`PZEEj;$GRf>Wz#4fpJN+d$vR` z6E}I+fh@+t_GV4d>L>(pdb&i+!C^NXOxd|eCv_nRVRIQ$ZiZ|#BZ^q#ZGWvZ@f)tw zB$(yuvo5A01SW+Aj|8{`M&!w%jw@wj0^lvbwAaLW18wwN2B~=##o1f~uQ@jxfcOWE z2H?*6PF#?hVPFRnA}&75HZq4V_#faiF!@r~_^Qw@cF7szlc#KQcYS%zGYv9us}p^0 zMPnWh2MBM`0WQgpjwcSa27q#a2Y&7mp#JjRc)x8QI_QzE25<%)9pb8{;gCAusa{t< zC~DztFHfHw#Yr|^CwZSdris@&iyo#>nVm*wx;o&T%~mg%v3D~*`S4fAyMw)=?w~7< zFXfBQRmTypjc0qdtgbxp=LUWbTHB$F<8+R zV*rz$SKPpN$I1%_5r`@;Bx_ryMOp}s(1I`TB74eUe;5LY%l#GP>;+$0$ZH{lEswUb z^0u$JIe(E?OI%g*aC7tLZw~hV0bmwudu%1}$Cd!iaC>Ye@W+?H|M1!W?XThJ{}nqo zJAwY@KtT5Za0#!20gkdd`s_x3S1cFyr_xgizWiyt5r$c_48fn^xNUuiQ9RoA?v81RMP>dn%m)`vPXg2kpvzbWb2RI z4cmbfR}e<+hH#X=NT%VkBqeg7Px|a6xDo#(&2}oJ?ZhINfJ#Jq zBYkF{SE9qm$YUKXu%>OmiKa(5f#xO;BhgEQY+%F%E@VdOOtGY-2dQ@+!nYln#q`Q! zEeGKWJK(u7*An+SKvLv0G8uMAxY7%VCx9_RuuDR9ERB|G4Ye2x!vPcr3!^fiW2y$B5gKWg zH@E!7=ru28T2^N$Q;abOS-J_9vR8&mrmr?A)64`xFVE(XjWdCg%4Zan1@dVw2OP#T zL%PSfB>xfyCPpUmm%llfX+4@F&(6f-Ou5L-%x^k0%BVB$L(oR^Ai6J?fC1-LZf6+8(OIULf>c}ux&I23>{-&&qp9zGQ2V}rEskA+NU-=bl z7EI9YvJ!^0;6{#-c^fE^l*hv|4f$EpgvnuixRyXGD@24LLP&FSP!>Fv&{)pK4=Dw# z;lP@gI0qkEw}46x8Ve}^Y=cv8h|MFO{EGf5t8BOOY| zZH#c)efn&0xl+YCP=BdIEsv8d>OS?RuRldDQ4gMmGLf}-%o!ARd{&p-qC z98{1OafT;&kpA4?z}f5!XhKIG9K22KQ4a6b*B|mO|BDybeCY|>kMer8|CoJ^apt!lAY1BnS>-k2#CN2eD2fBhUd`tq z!&4moXHWRj%qas846aauOhRdMo-i1Z`mP8&`^F?8#mKZYtM@6eeY!r0F0YhV20>f$>e&vGh z0Cqr$zmtS|ZO z6k(kM^S6^sFdc$fK6)1;WYPhnGn)R|_za3P4@-7=%O$Oz@jw!p>yV`yW<}E?z;4D{-7s7WfSs&Ov43 zIK0=1&9U$mY%v;U`$#&SbMC|6$OBI6ObV4Fd4p6JSs9tfG!69fK|&0nkQ1>Md>TZ! zPIeuw@LItJ_gvyUOB0@?3?jIQp#(Au6!}>J4$5SP#5j56Z-+|7K8SM(aAuHP(jVi` zwkRkKOuTNWDIe};k6D!VV7WA)H1IN;jida?hIl&Wz6W|unugyAyIEOAf6l_+^L%FL zfcwmtKtsbv11!5ngU>wzGOMFi17WyZz5MW!&;Fg3A82Tl`98lAww?J+=^Csxw&99< zSNAZJ#!^~8vy@pr81Wre4J(kdwDl${2_hG8y3=)5g#cGf;0A|>hHDHo4L$xGIEX>1 zEa6p0Jp*9A7D0ZOj zz_z1<9(fao2`g8TMV7C62aJE#X|925jK!Eg18Kd&Q?9<2Fxs(s(iTU-l^uC=P%c-7 zh$(|JT!VdSySBw7lhRx{4+M~FI(24SlK+CGReCp~z~fEw5l8}b$rAkDCoZRyyU#%H z%{b|ca>)~VP}U^y31coK`j zwj#hdHo%tnh3*96Dx3s-4hJtj>$Z_dKq0CF_}gK#Lg8ty$uvkLyLvsm2%dDV0kDoZ zR0#Q(m_S?w2v6o+!=>IVRluNZ7BcHpDN@lU&H#sen9VCN05glJnqBJz^9 zE02t`e6CoK7nihKr&*Z*ZC6J@I`YiMssKyZ(%J{fPaJqwN8R4t#HqKfkd%H)XFW8z zcXffdg~!XaivmmgH^Vyd@)}(aygJ-+%a=Mf0}#ZgzNrHTnbR*5=c}c2Fv9#f$dlKS z;5q!jiz}`yj{_;UJ~xEDKVfB#cKnP*uD=tyMO&h|MXA)Utj*`|I@F8*!HxQz#mZpYPapNmB1fa0>AQGpa03* z``ce)ssDbK_s>~=9sj)h@1THTmy~T@I~d?nG)KWNT?N1hr{BeW_5Qb4-(XLG6E;D* zX0L!(-+mwEPe*`)?mNON+bUccw^Q;Q^`B0>9g%4{jLVO^d0p}YJJQ7?4wd(E6zRAX z55baKgQ)Xg%LIrp0_HkF;W7B={zlSr4M>5TR~!?5pfbFA}IDzC^zQh$-Ok#oukHiC98VUDaKFnpl9JzQ>#c(w!{v`I+V4@d8P6uTG za7{UutVSqkbJS4Iec*^vAo(YKf+nuzGLJJanJu-x#ln4Nlk8}f9ln{ngA4n>hCKIt z)-LZyYFzmPF0(Ln)R8mOG0H`wD}yZ1714tRiUonbZMI?*4jd!RWZ&u6&@sO}dt}B) zDJm=S&Yk+@)n%U=omnja9ajbT%dW%91$dX#i~ErG<1Jg3(=!;L5$cS(v)Mk2^5x9Y zo-;Ot-Hkf4De$AA<+qAmE_w~JbDaB&Y}|xn%_e>|9xN5YX4q(|Mc-$})iRMp-!a)LmyX0~24`-n@8kT#u9YZl6aN9ytWN{9nXP|m~FDnGIY|uOqb{2 zHf+$gZ;WlZVe=|wBR`bb7I%}8WhB&7@O+|L~1o9Tmo@DkTSh62i4_?u{rp7aSS zk;#a<%-a~%Bjq)klYlrlCfVjMo`rp2{qqn15ECyv+e9sH3-c`=;Z zy!1iE&r_Ree{sMEz!z<{$WT$>NDs-d4E0^~3^O~7@ zVExJg*+V-*q&!){0DgICU#ior-i0&zlf=QLD+D?yhQlu&V3e0|%FlzS3|#A=J6Iq+ zpH<5ey^n6T44@1DZibsL9MFCa=_8!cKc-(f0*>3*rw&9|_qTEEX^q5(uKbc_pJzWK z&8!;WUVhSl5tdfkA^F@CQ9d$&WgXBDSwAlMKWFg!9J$%AsG}^Shj^q13(!FB)U(4b zPZ+3h2qMoqRfZYxOF#BgKmC)*v^{Ml@JE!ub_Kv6QE=OAtJQ!1xz9aWU9Wzb_x|6_ z3_i}k8>;A#xH;c+__OR^=igNT{Q8;z;TZ6j>DV-muTgdy*5>=*Ti;r}{qgsheWZiA zxQyaMy{_(^P193DNvLq>#Ch_Fj05YBvV6xyFti;HqTyE$mw=og}=l#I#eL7vstphX>wSy!zM=*dVViIJNzo6Q{H-gPr zjHx5?*@4PCW) zmiFN!pFDkI^`k%WQ>(p`Q)aJU@SYzt8y|kadw4HdLVn5b8hg)Ccz*JMu@@^uUZJJ< zBXe;3x4X-hOBgaKPq>)!!nt%qKKOLP+$EYi_Aw|e0Y*XILr;;EgJhrx4F?OXzAn=j z82qr}rhYo$&SKxgqisGr)IYFs5wrY0U#3T9;J^e-J_@@!c>4D0c<++y$?EFWc?`BY zzQFOww~LS7esi_^?0R*5aj|;;JLju+-gvUQ+d0R0VWj{DpqpG>vSYu79s3M2t4}#7 zbIQiEe0+S2!N^xV+^rw}b+R3Z@J*DwTMz%2$n|*V7~@K#5XTyW)Ze}DsahVmwbk7M zr?KilAp&BV=JD!*jjFC)MoGHm)7ihfiz}Y`KoB*mGOk1UGdQr1vFc2{gDM^PP$JF_ z$saXYunDVrY==3+%&~hTjb13a5;#ZJQz0+CCa3sD<(|ihjM~WkB{P&?!Yx@ zhPMeOp9=t`obhB4|0Y8-U*nsUyyP)$9z{X@57vy&v$_E@VHf61+n~LqkAO+lTSibO z8MW>V!$f%#sxyp6WaisS0HzYJ&frX3kIa%941vKQ;q;SG)o@()JYc}9Hh*C z6;wgnBY*>ySt?VJP6Xmd7n3mioTQj8AD+^9a+CTApS=xePi;{_+=e=60GQ?gexBJy z_C%|`lPmZoB~nUbeE1;%A4@p~%_-m3GrG|Dp2~{nS-ypTqsH@KW1vs5ciCeQ;0WFI z7OwzYoxe&oDnkbcPjTEpyn18+)fGQFiohF# zx@W+N8wV23=6cFY-pt2IUgw5?rzfslaG=a~+ui-$pwP0U%>WO0cvXhaSy`4o6n*Ze z5FM1U%&q`9fIs^Hp9Y5IUE#_lIDOU9 z0gAjjCk@JLTTs4tFslq41n}NEoBetE9nw$XZ|9LdRNI${1NxzNcMkS``C~uz7k>6% z|G__f1zX!=D}f(c0^0$AA6jJF3{wJ!H~W8=+5JD)nSPWhjz?AjFze^Yv$K(%{jcNS zRRA~>IQY)oB^@Q{=3WjQTwPrj9^?F5U;D=D$N%J?THWAy+_E}A`yHJd#W_EpmChT* ztCCH4_L^#G;#8(~bRKpZ>6VDkG45YCSTutQE6&__(qi%mu66>iokx6uCV}1+A>lAN z;=a!%v`3nq(qgnE4vMoZ;4&B<7d~ZA40eQe67tQhu!a%9`7ZjJVupV&s;883w#;-3dF=|=6~h5yJg%Pdnv%eX zE}Z`|5+jht69Y=QNX>Wwe5GXXXm!Lgbq4^B&fZwP^`k$&+C6!`diJT&DKh}&?7;mE z166#2@8g&J1T0MWY+IdDi#^(di>me%%UcPv_`uKAO6rMa?UEIE+ zj2J!0$a-;h=@#0@>}Z_L_~84RSrp5C`s5Uyz$ZajUGSU%294Vb!qZmql4TN3! zg=etj?CI(1jzI^@>&k!&Mj@Sfa+d1Fi;Ku7Gf3dMXOQp)gZKE1!5E(d@;H-|AYt2! z^!AYPxt}3Kralv{2-rKo*(KfYN9T1Ucy^#BbqHK^3&vRLXq08{(LnQ(|o-GW}ibv4P2ZX`q;13x$iTH3$-EMyXB zI|YM?#3Ye~Np1{h1Kf$rpk*{HED`HEHnnkSE2#tYg-gnJS=Gd|z0dP}hF*H_V{fe< z-v45F6RSKP;oMuLyZJi9PMmM`_!O73#MKSfE7FG#AMft#LRNK{n$|cVu zdPzB{L)ED+Ggp_XPq^?y*Fa0hQ(gdu2F^39+YVVFC6D$Keoj>YXWw0sVA&rj(_%Yu zFO95LlW`FFzPx>p4zumiFSMvP^SXnw=3l*O`*DCmx^Z%`_gr0IdfKV+=ve#AOk99J z8z@>bV60u?%%V-1y%VCd8GM0`uRaWNxtBd(S{4srKaEE4P z?PqJ%rP59rpy6kzmH7#Mhjgrnlm!{t-)2KU5alZ~;13<^51y^R433blJTI9{a3!72 zy@xc!-OUJ<4|?5vRvygK8d;g(Yi0E1*c}I4cgDbXKy0t8-9LA{fADw7@C*F5$5sMA zv;?*T06(&$+ferEp}Rn3ZkEcth)-+=)41?V*^ z12E`y`h^qz3MVB?o`}1~nL6bD3g_zn)=_Ob7PP2JyGH|dMRwS|Ylk)=+PAADNhhPT zE&idVjp3)dwJS4UV^q}XJ%uaMK=j7$(#VbjCpiom3uf~sUA&Wy9jTDwGrr1SxMU4a z+yP=a?94R)n%{h(!nKDq(rHT1v_=$tK&1Vpi9bUOeM*#v*-h}%OW zD0Fij@EQ{4!#FDg7?VT8IifE8N3I%rd+aZi&N>FS;ce2 z=l>3#tqyVO51AplzPx}hW?0Vn)E{L&=b1iW#>ScP%WG!K;PZ$wT#@E8{)#~WjUJ7! zVU`zhW0g^B`E<7Ltg0*sotTR$}zY=qJ`;YIqH<Zz(1X-@2e*H-1 z0tg#otPq)4m0idzxh8(3SnVa#A2|q%Dr!uNkrqd;K=r=KUJxvOgp>a|$ z-*O~K;uBsDmI7%NQj?2`l4k+^K6X`2FnscoL2!!u)lAdQH9 zDCE>T;c~2l?|>EXz&adR&K&T9k?=BLN7?04IY%}H32e$F%@lE*bMa)Zo}2Rey?2Yq zri^C7QEpoQb^fmKfzo&@bXLB3(bkI5)f~M5}C-m&z{eO zLPzJJ-=Dm5xO&3tNmo=#_E>>IpBeRzcFif@kN1@;ckRDt=3b{f%jLQ1SYLxrs_G(j zj=CcQo`%8Y>VdFE{bT@BT?nj>sgCA8x+w#|;IQneM@tEd4kW8n9f(zK`{?(Sko?gf z7LOyd&CnH({hKh>tzC=Nrem#+&gWs_D+8xog~{Fo&~?y2oW3?-S)}CZFlC|R@2gb~ zRP3rZg^?clqZ8qAI>($ zK)<Bq3{bvpLlD){pxi$iI)*F`L@@c|~QQz`e?YkBpy)C5Wv{oucd9A4huj6+TyH z$%-|eOXd@Z-E*@gq3=X zF|96XZ};rE!21M|ADDjrM?U>C|L0e}@Y!FEkhZ6-1bzq!YzF{-2w`nOD}i7CjnDr_ zI2?b^8O$u_r-#V$eiZ9m=6}s{-7NRV8OjydIQ}Tt1%}zdb=WTfI1s=VIP@64M|^d0 zo(=^4810$Sah0)(*{kg2#1#b_WtnbkCNxplM3YZk+$EdQi4fe_4WlJAMQENv10l_M z*Q+_>P!Aa4gV%&{l;$8j;)F4t|G;|`HHVegZ2WqnI=LKBF6<_9T0S)T)1AxnY1ap)T2h1 zAj#LvjW06cYxpO?4V^27K$g$qobBM$JL7+Ja)v{8OqDZJ5PTRfq=}s_8kT|GXNh^7 zb&NBNES>Zp8h0r$}!7bKlb8&_4`+RH~IO&>M45wy!pm)jNf-Y#$d|{ zgD%hCSsk+s(`BqjZ@Q$B9keluPZ{*PrTjkQzCLvJM0sLpxr`ozsqfEXG?VUt;t}OO zK>qF}u*1NG^058-?yWjW8Qe1Togptc+E)|VDLyqHFw z5SSNC{DF9avsR%#M$xnp%Tk1k3(`(4T z3$aKBZUPBUPHe|eGMb;P&y;`#SUQDk*@ZCmdmW7z*I=G3)E`-@%hp!`7C2FT6s7V= z+>k_o1>~8Dj9<@GlBv0nE~MvhA5>GOjh*MoZ0{rQ4gAex0m88-j&birzAT)v@@zGd zzYd!>CP;(BHqO0KUFon%d%%zu^56wL`XMQtIv8!a%NL78DZYZ47zoK>CnIGgA}9dHwd zhKnGl+?8AC1}C};SlM)jI`rr(6r%B#$3&7NR|hvTm_WMqz<+d~`Rpr|yMq=x@G}o# z9L(rSgYxM>hdRyy5?K{d1`VL(D-#ar`uc>gTHMe-ouS7Mxp(k2t01A{*AS#DpC|M` zQoOpx>CbC-a18$RkJOnCxjXe|u$a6VAb_s@fpzU6jP2dM1KhOQLfe-Zc3?xL&Oc2_ z2OeC_L>~GV`tQ72CQbMvBV`JT$S(5cUK+-VCtv`bvN^8(opuNkrD~PGgEZVf?)<&? zKK-Blv#)*OH~*RBw#QZiKd1z@0{}m$q_%L8fbad^T|NFoMk$|VM&A_xC^kneUB>IE zWqxB&ptJqX{1cx60%!f*h^zwwS2+4Aex3hI!fM3M0N<@HUVX?tN)F|!GPL7s2R*dr zYjuJq=D+W#1MHz8qy+>{|2=u*xF0e!kU;J0^h95_32+p6!IuMf;2M%OK#v-Hl|IvTG5py9H&$4rj6 zm)*IYiLhgLHGsS2J7bLFN8UY_T6VDII7`SM_fGRV!3oAg97kbj*#2zWcMJyX;1KWN zG~V!v!5zyL#d+uJ2COi+xqP*H!PhW+-Qbadg?pDRVkFgIvAzfgmnFwg+vgfNStbf( z8XE~IuC%iqH>x8Sg3~d5PCqMP} z>Ww!}7$`Vcz5DUES7&b@t)85oU^U`Av$BA99aoPS*7xiM;();|`xL;&>h9GggA>k} zd>DfZ>oi7}hS=Q=Gx*4cY?PO!qu_{f8)F}K5rXxqSRB~7W+1?s9B27s$mtANm$ZdF zriMUSSb+T$qtit${fu~#5w<^J5;`Y*9aO^I90#P zUm%0tHtK!&0fko`$pOyAIvME+d8!nA&U1`c42-n})ae*WT-w)qk8X&T56NKA@2S zEl=y4donn)ZE#W|ME1?AxCybC%zy-*AoU zv>|*&@0?d!{lbm(QitM^ClEU%;6P9Zf1n7F(Of87<>|cxNRc;rtZH}t^EI^$0K{B@ zcldFjf#hfOHvf?Q0REHhegFu1d;Gu>*bV^vz@pj$DuJWhgTHlkd-G>A`>&Hf9Q)kI z`F9Y&+041*zbgRT2rRSx#AkJY`CJv?>j9)W^RL2lw09bCSLYXu=rTJw6(0$XwyWaX zVWaxyp|<8fpEha`b*>S`L4LLQgpOUY+zsG?bD)72J1M(WXo7|6Cxe9Bn|lqT?XUxCd4wFay+c~f zlX|xs?L94_&J-}sMLh3&w_e0znAriAq#vKLbpQAXoiWSis51?ltO_9P=khRh$_sR5 zD=gypi}!&x?U8msy*gv80d7Z}o*5hw2QwlL94JS*+zBmZ?2JGSyv&x6?p_%ol5*-q z`jf&DJRY+W0VC{~PXC#*aR!92{9qMbvnob|$kz%q_U?FY+#K(k!GUuI2X0t$f6J#d z?^$7Rf6IUx%(=pV0$T`<%J2cl)Fs7!b;EkkDhA4~k?HJo_+fzHl;_WkY}JPxk1|{T zl8q5Bp?i9A%)6w_o}&ly8Ut--2YR^Q`O}ep;YtQ}j6QsIvD*3SE9A$Lea2VhL%Ctg zWi^1Cj`>NZCwzzbtv3%>Z@+oUAi&Y;4F(S0ef#<9V{biSm+iCFCqMS)>dmL`@>;?P zs|2WHgt7ndCH5(JNsYhEs|(?U!GnXR2=NFy)Y;1mUZG%lry}s#c9v={ItXr&KVvm) z3`khx6qwz-(<&^oOTAKMGK?e;PwLsF{3P0v zAGR6)Afz!!V}Yji!xa*?Kk0al9`e>B^}?0<7gsFRB#DrjgtOeklmJkd3oeBX>|GpK0E;9f!WRIS8bkw>;&{DDr@}&Z^I!yb3$> zMKIiq2pC^b3L>bi%yfe}1|8a>OP=eT4ju+^FZMNY8iR-!%g7b8~O1CqSrvD_VuZ2pNqk|#|r(*{Gga+WdM*z3%2pMxCM(J1cZDfJ%q za)K9i=mG?IX@v_wyvu>i8!l|po5Hzr@z!?KwlNY1pd`f9+zlC*K3ns0bQE5$RMKwrRF6~%OV@%(MD|{_Pb{cfVv9F zFC$4Ep>!aCG{qP^12*rDQ-?b6E}Ivp+HKaUGO*9c9tkO<2vHgG0`Jqg%#w84m-;_# z0{m`DmpUbUXy?OKdFr&vgLM_BowE2kK>9U!=rcoqg}&1Pk2K*UuU)~bpTmoN07e~L zCyxAdYDOD`PaVJ`67dx-+oJMy@I-j!|W1s<+G+eg>B3L&56gGX^%E{c~y33+j40BlEQhydP+BVfGsCqC=RfsI`{ zveX@~uwCN(%R`@A@gPs|X4yaam7S&vWGyV1NaUKjGcJ;&49Wu@?cX1G4UHlJ27UO{ zMq`0l@(9lDpFP?=_*-QDZ^W=Ywi5V3B(NO-_(7z!g^2`y^)tWybIjcTRUH_AI`BIF zb?nFeG9WNk0$>bh6~Jrz0ON8rCvnhp0OaPat0X6Qq1bo7bTa|E*qG>p36VL>HDCfk`GkVo%G0qM)9K~26 zR&b6u>vkK!J1}AN#8?1g{9h7YOAW~SG}C6MEwYi>P9sN+fpn_glWfwOpT^0BJPBZD zYx4vHPUAkILs+qK>&#>m0$ z5j^a!K0IfG&J+tn5ZHaZ`+YW6yuWt_!_@{Z(|mJvhuo~h{WA?e_d&pjBHtB``VOC4 z+;uh;1Nr7(U#|B4C9h08yq|#!XUu%Um~`Pi$Xy(KcXHliAmDiQ@wc9?KJn(W)fq77 z-~9IK1bMvsCa)9V=)0NV>A~~Wo6p$GfK>tq@wC&UKPD;wqaGfgmN-;^+S|S58Z}V7B9_=4+bwH-0DvxQe$-=$jCPD|WM66iC zA2}*lGtGqZD8G>r(Nhir$(vS^o`$#^; zuTD5&AmEx$#Q8k9lFFI%3}!*@mj1zA{l%;EF8tkSJH8^I)2I%L6U-=4oO0rPCS0Wn zinJ-yeSbcK;f!$}Kqt0~1(X*a<76&J|G<^1-W#@pD9cYym!o}leOhp$m+131{{i*XJJ98i~6sT0_RH~Ess z3_wJ_^a&0ofWraNJ@`Ba=0jhbLnQ7`;|8)mVR`1r<7$M|50z}&Avbvu3K>j0B#(I= zl*qt>^+TU&ymjQ@hJ#Fx@bB|LZBh5&B2STlYG?IVKlP`7=JQ|u=b!z@MsJU;1paLj z*bV^v+a$D2j|6`Gv%m9WD9>NSVc*Gn|2pr(`R{douado<0|TxSAe?3XT(5CV`l^5f z1}y)lQ_4~;dk8uW6>Vm{=qzq{FZ$%n4SG~_C|ito9g1kpbTbX9IHLuVHjU86CP~9I z>eaa7a)iH~ZjB2^$~AP1LxmS?f(J=4cy2xwFgR4^?YYTgPYlFR(7gfLvZ1B(DJIIL z@wOZzD2k2PCAk4pW_dQ48kwfC zGseK){t1r%Q)a85B5@pbI?_9wOyQl0pANe+a|xZsm2FO1I&E2^=nTdI8{CDR4nXB~ z0QuC`z&No^9YC-%4qiHEmu=Rt@f89MsL@z?wKJ!CXPXVkIuw92yo5jgx!z8uNp8|@EtZWWZ>X|4GZu2^{WOr&-=V?K)m08#`A}N%0PL~ zo<5Bp@R^Xd#z+S2*pSa1t8aP6Q59@*MZ98WY5qRtzV+RBjXysBcgQLY2W(;>GGOR{ zNOq~Fyf+LKrh3SG%`eEcd#lS^{h$dD?0 zi%%QA`SfV@?mJHt{y1Mac=!2RtEZoQH}!prSodiwAFTNLz~S$#?$0R+ZKA^kIv*H? zR+~kmPTim6!S^1lR1C#?bee-B?j?~n5o-*7$fvHVV@`WQ2Z4e(+YHIne^xsol$dke zyLyQvT7r;VX+O3n+md=lk^%&N=o+d#b)Ss$c~H=l!HcKpr{uS-*KqXN6Iq;{075ln ziEEN?CnT?qjZ|gJdhT=TJrQ~e9?9#~hDb*5O*Wic=^DgQq9B?1-u0Qc{d17klL2sK zcxG*$h;FTCMGX4TCt=cQ0Tfs10~DQ;21J&@7m@+MBSc3C{R~~iR=mW#lUrTe4uL3mcY0AetR7Oo?J&4@4~)9hfzm8d=J{=% zlqcy%-tr)$gAYPEl-p~E_=)HMgDD~qM@R>kEiY}(ikSy;cVHk^_h+JfYXuoH6}nQ zBQzZ_&Lc~&12Xqbv1s$lBw4*g-+1KAwe^Z3QKnbJX|{f&DQ}bdqhOK3je!+IYV# z1qb0@QYXlob#K^*mY0EK2E_N-z1DpIR2}N!J#?}Tv~_V!IS<)$K@|Cl0ywQFH*1vd zo2=@i|6-uQfd@a|syt5_b@rNm4Ef*Dk(ouk?B=zHY?OP&>b4Jg744k*)KTAqk2x6Y zD`wV#?LMzqjD9);YozJ_TQ1wGc7(Qy?Z%&cXXOOE@QvQeo5-xrOdF*P2wypco^6s{ zCOLlby`TC||M#!`!Eb%3Qs17p68QcSSog5sA7-2K@3{m}mOKCCGoRP_e{a6upA`Vk z_T#{31;BLpG2nf_e+~}V@i<^`jWc1quMFt)XWsx6yZKejj!>gNF)*ANR5Q{U@$U1^ z2OmU9$FLY9rl`EsNUwy=Xs_pQh6luJRcAJPvT1aBEAeP)ae&eM!5`H;C=pf2T+QO4 zF%fiz?Zh+y#;Cg)WoP1?h6fQFIKA6Axba>NUOyVs;x$L)VT3%;fov9g9UibEYcS=r zWcC-67=0P?CvFf<+6Du{_Yhzsqrr4MBjZF!e0c~!@e(ZmmT%NxlXGWK!&6MH0|Md; zQ-v4C8FLQ}gS^LxW0f7@nU&5`{}a4EmagCGsA-+(PC?iSvDRN8WbxPN(^G(Bv888RN_)e!~Q7yv8$eaxa{nwMLso zl7Fm-@`j;eem@ttmNl)EXTiK0;EF<7yC;FGQ=Lu9z5}#3AV}ti$95A3-QA&C8i~Q8 zF@#A5eKG-QzU0O6-siQ5{ljO>lw*X!Lk$w>;^=FDIxsNzAh>w-lKac->hGQeH?Lk{ z5RuNn22|S&C=*glnT|z}_y7Pv07*naR351VKZ&<@$ZpK&24_}GK`5u_JXTF?g8Pie1TS0^f6#KxRpxvE$bPVD`wmL#_@g?lS9kLw&pH9;8+;!TWVz zlX!87BYV!^05kp=x4ZtMe5H z1-e8hEp5awaXI&r+rl6V@-B%+h6DkwficmxHvII=rUou82AKYBpiY~yoyP%&Ss^^a zV*t5Noe(+irLh@jBlmtFHrRa-j29QJmdMaB(PQN4^RF|G42>thL=gaHoY$Erso)v7$EEa_oA9wXx06?rm$C#O z5hKo=f?26u4bkT#50}xSEW#Pq@HeV$Cpk&z)pX&)(?l$6${|c;A#Tg(J(>9x#-%fjF)oJdEg^i6?X zpX$Jqh7Oo;;bjU}x)vv73{=-HRE^3}o+GayAR9Qv@AI2ScVvpBjF6_~4*{j;AT>`s z<&K_DTXQv$8L?-gFK{?fsyf!$MIOC%h_k31v%&+MnZbr`W_;;m>VSj6x_~#wWC);t zsF{?FdO%0%G)K;ZXN#rYS2wA%l#h=09geQ_+{iCwgFVv_jYTros6TZ-Wnq9WE6*&d zhgab2C!$j1!)J=0Gt}0jPN@Ux8Gr!J{?0T9EL?h@u8gucbMI$g?Pm_*?Sim}a`c&T zaO4CBeE)PeOX`L9Q;JrRuZ`-MTL$Yt8~0guk&$1U@_=~jOW7SMXJv?ewr}4}A8CGN zmd#-)kYZ3)4qn`|%ECb!C#@87WlOn%lb(Y;7dZYGyjFI>YJ$`sWfZ5p`|R98!{^17 zVIo)V@|RZ^Nu`;YdL_qJ1QzZ`^bQ~d*7z+@vT++jthd7FW z;t$1?(+-QI=H;r5vgq%D15CwZU>?mD{uAAt+9;*h}!jJ3OYWL{P)zi1ZtMxYOSf^g+ zKLZ2|3_PF6u|AwLZ;zi!~_hg&!Mw91jE2J->$dunitOQT6% zuN)Y({K$RJl@P#R;=n7HH0v0eJeA1midP5%%X7cOz{4YT6l2gYGaNhkVBLWqew^ug zpWm%39L|x$OK^VWUxlCD!>6lV>ekk7g~35SS%~RIJFzYRV_?bmNp!xP4b`dN#UPBl z$>@8cKIa{rArFizcgq_i6s16r8*vbwH1jy%0ss6Z&a$V@dT)G?cr{oo2F4-Q0Yg61 z(|!!{i_;}7Zi?4|tBFMb+sc3i#%I|!n<(3(`EoaMsTXo^4_@1%Z5ZU7gn9k2ol#1D z9;72bauq0i5gfOhyb7CSg_UE_4~`o7iH;r;#pKJjAm2Tb42nAK(l5T~NclIP<&9z? zT{40MtkMsr)bBc3xbPR;rImB?iEtxs;vR@I;4}E{0JwZ0#5fT_kTy~pBAR6@&hWgM ze-Il*+aPV7Z}2h8o;d5FD z$pEo|A_Q8w$*43L$Bd^*Cuik7~F z!Z?#nmcWCOboX5Gy?*!wzh8KfM|sZs{m?pKP{8s>g5)>;^u&Ik_#F_i?oxK39I$XD zg)1yvMduQINQDPCB22%hycukEFvLL+1$e-Qwkay7Ie0;ro;r{pC#2lqu>&SPoja=+ zulk-p{Q{}t8|TxTcSnMS=u z8AfB<+wdRtt@2aJt1UI=xJKVi=GsSbr*`B>)?r`}j+Pyl%#sMRanu-0CSbvV;ti4w zm?EVcAB63Ya>PKQLog4&F2fo?0sv-byciEA`3s`r&^Tzm!Y7&F_d3k6&>jGi*04}K zJqV->+^r+mX(J?^FepahihRT+vAh~H3oae*gMMTwN5z&5GZ+-ebLP$cB+|^ivqTm` z074>9p}f#pich-Ky+)?;)WFzfdH(6sXBbIrnCFX(E>9Jl4%f~+Ml5*DBhD;uWfr%F zkVY%cD9)QZ-5YlIW_RwFp#7+>(H%~$=F$Uj+1*(d!>fY<(yZJa0B}aw!2#Q03?e_X zr{hZ89$|k@_+|hB13QKt*c~{?>kZ(tTsnxU56exuPWmG=`IaHC0LTI5bdLh>^XV@N zoM(g`_=VFTa&Vx|pVIYDnZu)n14aWZ&kO@7&ekcjE#7R$W^tYTMKIJn?G1P{b3+nY;P2Jsrg z9S-^Bs~4m*qjGbx+J%m^%=q|-yfv{b26QM0kr+?YgsPK^njP23|gG@EYB zJSO(Zon#~W6pmB{!{IgYmYMS8yXvZSGE8TA7Fqa-r+6!<^4hXa8n&f*G|oHYlv$aX zFw#nxXpiI^V0}JDLX-21t@F+d<{PD+42Mkll7>Z}Y_;9+#8wOgvvj0h-gR!1o;I!K z;gDB!g>66Wx)qam@7-12nO^n0x>Tps)sUhyF3ur0I(=!2oRy$*R=2wIyziyc6NXXu z4NzY4;moy;uLB9fJ2(*8P@o<63ou?s6WyNv0mh}_yY<>(PPX(p=QRXo%QJhO@^FF) z9oQVmBLm0wYtXffI`^5?rp(Gcg9HfEzHHCIGT7A_4}X-+!HFZ6<5O!*?|+= zy^gvG$Gq#W&DlY0xz$;&{G{V&XSE=u;~oH{Ocv8G$e)7}S#gSd<{(T4(1G;TKUj}V zVA_J!a0e+J0*vX#JhNnkqw@LeJRh(LG0*+xtWplEk~E^$g!?;0H_w9Y0}3F=I_Y%_-FFh*3? zDppl&H1seijj_X2X@B=&WIOvfM^loaqx|LqCdz&oKH+C#lVR{kAT+&~e;tE? z$}$8BMV)ZzCN2uRsgUVGMj?7yE+g?H7xMr=v(|VdfB0F`F_$n+Cmuc;ZoKI|fbt&@ zexuKz_F_b%IpzAbgC?qQ76t*+z1a!a|6wr~hJ=@Or*=)o?7Zb$>eiVJR|Axy}oxxx*LF~Xjq8D67|G=IBj||LQpZmpte&OJT6$6*&AM)O; zUpHXp9;3^F1P2j7LF1tO>IDoX+ks{C(}vb>27&IFK_WViF!7kCH@iEIVilRy}_&Uk1+=S{)^kP!~n#Y^Yw>RSM&qCi95_%UY~-gV_F}| z*!&uGwq}j~80D5n0wR!(dBbRLll!g4c z2Y4hGorH`K9lxj{BC10Mq%b2cgCEw>Muy@ghKELqIn2VbrZ(b)p1^R``j zFYfRuv^p=(b#ekn$_6hI&3y}H)_l+;!;Fx6~R&;%CNJob2B=K>t zo+Q&I_O^|3F5dMa(NQKUBNT&kz?dvnM9}>`yc?0>WR1zfs@LNLqXS&klo3SWZS&4t z>-=lyD7x@OVH^zb$mdD9>Ik|-UMF2gP!(l)vO(X`)^Eq=YY-k_{ zpIc=TR=}kSu*%~6quZ?6IJUqY;;hCwCeCH=zT1DoyZDg~`DWYlwFI9F>7>=jBXPzn z8ugNNeb?TkY-~teRu=$ZF5z`_oxOKsJ#izV@TxovZgap-XzGW(BWi~?1OCakl+xl#Z_ z-hlysyffuzQ|3_v)DEJ?yUs(LeANAPs_am*oD)T=CPSsuA)vj}A+@s-!=mSaOPXqR zfm2!5tP!qw2!W$?qyY|7l041a`XLWUNw_o*mbu z8g%5fvoo*q(3nk@&5|S{B^zmlkWKQCA*^`fKgL>uj=-0%IZ7-Je|G;G1nyL9DcgaV z7XoxR;UTn41A+p0YhKTW!)}l{GHrza)JbR-(h|#D2ML5Rrm{^BKJX;FX>@{wG3T5ChxN

    Xb4FXI(wY7v20RW=&M-i9Jonfs`6LdeZTs--7@8P6yp!nb3cfDD zUO~l-?*@WcuIACu@^PANRl`%U zfeV2D|$|@kd>JH5XL-HI*9;yQG&ui&!2!N-aKrDG)djwC;6Q;E_k*hrG`6G+y$q~SNzO#w zfy0>;+Y=%L0>co;zOym33ydwxchB=}O=abUFe#%cq)`?J46x8zX5w^b#RizH1CRBc zC~4Jz&#MGHgK@~T_Bpy)rHs%no!?4+2YZyM&lkA8T7O#3gawhJZ9%*#b?;^#OdIs&kpwkx2qw{UkB5Ak}vL&nc0<@SD7ot8rlgH=QCt|WwScK>VN_c zzw`A7aVUSWO`P7Ptm+VAZBMxduw^p;xJ}u^d!Uem-WIi%W^eU#gwJ_3xkOFsVVMUX z0zbOh28Xf@{UB&5i)->xUMmC3l7}RD)1QHN9`a~iW*{e#Ly%?>>F5(^DG*jhmVX?x zu-rD5c0i)dPuj+MgvOK^(aU{PZ8if`{>@50af@Sw#Z;8=>n4|^7Z34iWTnMj;nrLh z-%>ZhB-loo2Tub=bdm3%vBsHfBaJ#(`q}b53IS!2`-JweDB?8Twr845CMvPX5xjm@ zPB@*t$iQquB8TV;X$CXb$Oz=dZ z934d1XRq?@jPxV=*FHwwlBMp1btLn80l2I{FSemGbpADZSr%`d%~zMVxH$5M^po<| zne!)n7S-p%uPT9a#(E3V%Gxb-59TY&l_en+ z3_tSbAzzo5clm09Uq;YD7oReFb%Flpu$-=PaGwFHje(ER7N}qOxSBQrux^N`?(gRs zas0{WXMe2=`Poqq!A^* z&XmU-(#e1Xbr>B_nTg6E{G%HI@;O@XGr$2od9mK1OrU*;?X1r!frp*H_^D6->@R%v z3!nM#0N5T|34E6XwgUj)C6aA~68N>>{Ga~>OTqp|XZCU6aV%7Lxo6g~@BYt0fjR5% zzyM+3vI+p@zg`g_Y&Qs8B%BUig{AR|!s4*gi*ck*^GGj?E*t4a+4-sXK6=HK_ zpK$B!6z?_CS=tVD9A!f1%DS;r?meKeqSNGi>NhOq_fvRr%7JJHD=yh3&n&Y%8RGTwkmi>^y0B4{Ce!Ow-f-dXd^K*Phe2x!UIg{0D-0ueFdbEuNlC*<$$HYz*GL5_?NvB!=ooj(9vRN|;7X0m?#LKz*L@~-SiY$a^%IUZ zo3te|*w$>*$}x3g3fW|(Z2+2<&Gv%vX`K|#b`Ol!Z4stzCDM5D7(ddCH@F<3K@3+< zc`hka+9WiR8A6dsK~hEyV2?aAWKX$85~mphHhMrx#l3#E%mv(#lVlyBLb?V_iNnGp z6BwTb;gjEIB6psPTUqTHevRkK z{^FVe-Ebr_4#n~iFwS9#5=w|tj9O2i`vEHH|yY!#oN$yqe_c*`GzRs&O9Q1JT8b=t1J^KS7 zCv8GEJC&k2ojg>8!o4NQhhhd<{U^S`G(RY;)3-5BYX=fw0z-0|&N6 z2U{M|k2cpU`nBC%HYTQE44GLEMkeO>8HwN|_OSCe-u?8?{>C@I@R@&+r0r=d zfei_42LLvNu??;z!1uEM4jZJst)m~upN>K2-g`%Evl0M9)}>5+{~za`&yyKnN1uBJ z3bIllD+UN-_*ZL1w+w3o%;~91jCt__c$&d z@|$1oWTrS`tOMfgehsOxtNp%lRE8;n4wj$tQ_hqjB`|0h8j7&*% zd4u=;aeNWPEwi<5RHs4VvVG+#xmJ5e)OCWKd2lnit4nsR*U`2U2B)^82Ad*upuw`F zM9Ndy&o*G0Gy6)0@R$++&lUOfm5XU$HacnIpd+60fN*feFr|*-7=zC;xT?X<{*ImS zvA<$WVnR?0u4=F>7?eC$%2TJ`I&_mgKilVVd2^}o_N(Iz}+`T}|NX0SRTPW{T*>NUXX*x}EuVX2<%2kZnz?3IoawIt|+f zZrBZ3dI!wdTYl@+6%E}xfjp5T@xdW)yweY@$OhUP!=-PT-E?uJrCy*1U2!4`a8$-O zZpz233B}Ek=O6g&1;A?uJACC}@9Fc^@$>!F@h2WuAJ@?3&o-iLm8<&>xFMmRJG{F5 zkaDnDAp->W*X&8)W`?dF0M2&w;D(19$K;RE4K8WF&khDo#`N%^ntfd;2XM%(|Mrj)u zaZTwNN(r<)<#{vREJCD>y%tXFCTL*F6Xh<#nPUTP%|zH--vU!=6u))Lb@oqFPT^P5 zIS4Fth(PYMJmL~;qTl4pET&mMI$kQAJZC|N-XlsKo7@?662>|s%40HaJq;>Ld8t3a z{AJ}HnbbMaOVlHN8inICc6`r%7hR!R(gD22#!%PmAnKIc&*jkrk!@IK(q=hJrL7hI z0V>MYy>`~g@nIH-oZ}=<=TaaY{=8SOql!*`1c!Z*8>!wigDua-%ZIb*)`L1oCtVxJ z{RQ?|{_n=kzVfB>Zwt4%Uuv@va3CWC6AV0Lvpou^j?kg^I6H$kc|rF%z^&$qbS8l|M-S4Z*?c82L|T1zK4xFmEHA^nAvs49}|u=j2H}#A~#Q|c%Fkn7SXck3_6?Ztb)#(%l++$ zt#8Y>@60q<^9RkAxsGi%c(cRJpEgP9$g7>RpMqOr;34g8#+Z--a~cJX0YJL9!eTar zN4sU6&s{d`bH-y-XB^8|LdevzWTroDoxuy7<;G!b8UU}KGID9XvlQ+fAU!{S7e`rx z11sVF8bjmaoHS=eQW9iA2^APeHYOx*mi)8Ke_yAZ^d){gYp!U>-UT$h;F0P0h&B8& zL!KEK3mXr;d?+(OT}|NNhje-fM=8K>IXx_kbS$g#>0?)dI;b&ZB18CxeLwr?ssUTu zt_Gt_*c2-1)U%3zov;!a272r^=3^X0`g@Zl55O9V81`CP+7z{h~+Ma7s z;q8jo3LI4OvxpZjK4gUfUo&7(z||19tR}c4Y+XD!-~_$7x~Q8m!U#-TRNI%&P@Prz zrEJi(PO`dy2dWOXD>j&+Lq=wy=2M=Ygq26)_zABh{7*bW7heVxBLd`?R{g&t3L2PBROWDL_Wm`r&74>m` zJOn8>sqSOo;oc9L#*_}M@(JB=I&?bpwUOL>(7JqJ1j0e{v*e$I`WzEA2a_t`rZ?t zS$`C(0|DLGk9eG}xyfG!1p?av0O6vLhIZ;KP?S?OFG|m(0;vquXKNF|yQ$a==O%fo z{CW`&Phz>88p3%!6#G?^>UL( zUcC~IESn~;4sJ>aip&Oz$}kztH&IXhF1_|Z2?f_Yl|Q-=NCorqd0LF89-6a)wn|>3}(7n;AszC6n20%FvD#xc11D zls^F|-juVfDOd0LhnBocpUXHBAJKrHKM|x2Ctbk)6i=Mno`!IWR8LFr<&;9clolqcFH`44zSLOIy(rg&5D;7XlQ&g9qm80B**g!>}6 zX<#g5IItpu%|5QFBEBMjT~z5W%IrkF3(zf8z~G^{_f+ zmBX2{d$bR!xq{$Ix1AscHmM&Nv1j z@)`A_VF@3ZaaIDhg;e@5>P-^{a7r|ubtIudXuG0-Vls`wjSz)P11HKDW$r+Y?FPuK zS5AU?08oa)_)G+XF!zJS$T4}yKlPZ9<_*5wcmlV-R9+BsKlqck{A*xaXAtAw965!! zav-{ln9_s1)jfccF0UR_X38Pdq|v12BQ~JYH7R+MlL!HgNTJvHL}U^?@lf1@yM0lQ8w2Hw{l@ zN&dd4>Xz3CE;3A}&7>tf0)rRJURH?rLF6#02kmPLGI2}7kgxaU)waFa_e>04!2;^$ z6>eR4q-(V$4Ls1Y?!Na?F4yt}F72bxslUNX!zS~sdTkvZtE_@zBh%ogIqB@((yn}# z4LgV}y1bXp;H6Tr{p)BOAKd^c`$*r(mrIx1D<5a6`^iA?lGmq6I%wR?kXNs8Gs{Cy?mFJbz9s-eE)cXF!Yc!3 zvYi3~ro}@#a83n!NDj(aCr4!hr?%>2dbn0TGwd``0fCFt7{1+AL`= zT&%+*VbzQ9<;n$DL)dS5xOCofI{73|c~yY&JD6g>DDQ?H7;tZb*emd?O#GQ&eWP6N z?2Gub&V2R4{?5AaFxs0}6EDQN@+AV{!0VMeavaJ4Vi(0nX zM*~W^J9vV%6M2au6D9$qEZoz0LMcdq4>RgNgA&R?fQX%koxlAb{F%S-*)RU?KmE>3 z*^k%I`)y8p`sUjEBydvsPWW6$If};^^Xh0I51b4Q79A3e_!=eN z3)dX--cF?*l1ag9Kw0LP*wZ5{d6PrA+W`n}is6mUOc?PDk_3gC2Y7WB!V8_hvbWqi z$XbQ=_?9R6DMQ%7u@Nju%7}D3ND?(_at+^f$~gX~Pv2Y}u)&>}T2*hox2k%p-nuOZOO~!!SKSP(j^qp`4383ZcGynUETNO9q3Mi6qx;ZSTXxvd zG>ndJ(yII?!|0&dg*rwf;|K^Zw$MtZ9%VLg67Dh{PVfVo{EERp8+G$O62R(!-cSbA zn1Ivd^#g9J7;{c;n6ep z?IWZeF~4!`z=8OMb*5Y;><(E2Ao2^nIbc(s;P*YwK5*AK($!y`W9ggYrFU>heNI^^ zZ|WYCmd>5d^sJb$q^NCVz}a`;h)DQD7pSaRH_GY_g98mDQ7)bRmxciHWZ95!x0jsw zna8J}ke zlB0uceep0@i|2OirDtAf+kAE=`9>$0bmB3MYHRtt&h>NT0M0$`I^+#h1FI5EJ5TFZ z+lGyle|79+M%(Rx685Qs0<>9P(whDa>|sNF-zyoE+Z6~NV(WmZwZ=FZGd0aP zvjyyPJffUl!iR_LUY$cnhUAaDo`Fou8RZ#K<=a2|Ar78Y#Nne=9H36$te|SO1u(Lb zUU6NBjNzfBpLK>=yw3dHx=* z2MweFdw&ntg9g&TFaPR4{C6&{FMf6}^>^Qyf8*58Z2vg^Yb!u;6Ydfzm->&>&me)T z1^ByQ03ZXU#nK?nTlbzZVw$`hGGH`}*(|xV&o+Zma?W!D}It_>P7{;)c}(uQa}{%SYQ5exqpzecG7m_|`dr zfG~E3#tGNSGm)e2UvjY!jG(-a zff|MJ4BeJ3gJv(OuF-S!-Mo_=?UFbD#BN>)GqQM~9ghDepEm&Thy&ed>uNMRln*F7 zD6*(?;B!gAWG?Hd`UyDqW$R2Sbxv)9+u-6P)#0`=wzK2R^2`hj4>C0QY~G7=^eMrK z8@UZ903mE=mEov2z4bsXyTbH4VZ0yl)rDDFAh2cKbQ()GoHkGw9}XPM z_JbUB=vp_*8#+AdD8HFb-_1L^CZ>O<(*u_H=Sf+ieR49LNz1(hJ)IZuoO20y_q+$s zDF_z&XB=DzGGw6~NWV1BqOjaD8F*&q#lZ#tJk)RJvtI*n zzdD%CXT0PCZLS?MQoWLuCxavy62HIy(pv-0COop&wT#w7k}Qae#vQ zn+!d^gqE{+>=RD!JhOlT;h=wEO((tkcHJ^{-lq`X@YMsi9XL?nfWd5ULBXzG02cLf z(Xm%Z^`rQ7W@oFD<;Pr|%ltNTs=okQ-X_oaC9U$0?XWI`$GR?Fpqz1w1bq9?|6VzF z+}+Rqo=&m`V02M*^ewMbRxLj=XjzwxEb{I>G~6O20s;&FAgG9eDIBaADa#UMfggl(!^WVeW@EDDAteT4y0CD7`GUD zpDvGo&Ov*A0Y&z7k_{8@)4pf`TIIKDBJbS>QSM50T<-=$Dk@6jF6krzX zpr5ef$^igz@gE)7rl}$G5;%T5-$D9LIGK++;-+^n!20=&vl9F=!5g*%b_N3B@@yFZ zb-1N0R`n(y4pP{MjS_$}SVJ4A-qfw|*uVyP)w%YUF!`6R!;dq-VjE*He4+OSW(ZIo zC)LC&eC3Ox;sAmAwvVEK)4tB2%x;?>KYhlEwK>y)<89CheH?fI%alQQ^dfmO_TtYj z%hrKlZ+`Zhf9lWuH{bf-f9-!e!aO{D)Eamg0Qji0|3l%g-(UT0jMSM|<>9 z3AG+P)8GJ&+{CSSU@z#1d-&f4Be0ho*yg+20H)2S(HR>RK@C-x78%1d&pv6f9Kq(c zjMv23;BxV!(bLNHzQUFz4)pE^+#9{LdCp++&{Da@gm^U0UIT7-godD(Vs`}LU?3=H zTO4r)!ZY{#o$ZZJ!If(|h9nSgon%Br4h??zgd4=csu~*!o%~}b&fY{i+t{UxaN=zF zD!hwC{R}bzYxL@z`4SxWHFA7UlR^r?B|;iKdnNL;W)S;6k8*nfq64Tb&UQ%84wERH z!F9%ZWCq4>*W&s3J@^-&eWSZhpQGWP4s01|q#t5-5KPzXc#Weo2Fl0)6SJ`HyUuxl zmaI*j?t=8y6``xalP5bpDHhi3l(x-55a^uH7&pj(6%<$cRwVwq97v#{H=weaZiN)n z)|~Ie%VQVsV5JL9YWJB5XO0-jdUdLbPi%= zOdjIxH0%@lOF%l~#i8EzL2IU!j`iFwi?WMj20uohIlhUtWNKiA0K-tLpU|>648N8Y zUVLXYOZh?mS%hwHI8YBYl0*E=viyrLd4qTL*78Z2CGVV(SIr)T=qCuDaHy6Jy3dv? zR}P%fQ58n|Pgtfp4mfn^9UZejMmO&PMQrY3df?8v*f|K@tio#n=P7H7Tt%%wq@0Y@t>a0VQZIJxHZ>)Z2+hWcn9 zy?4?$8+PFE!Y9u@Jv@2&gNHLtF8n$&HsAwB2L&qQJhae3Fjo+G7QyAk`Qeh4 z1h=fX@?gUo?66x7APgJGnhKDGeD07*B|=31lr25k*(Kh3)eM*M#CEO%^7(az37LdQ zSf|^!(Y*ygIB}Do{AC9Ka5cqtPArp_9k*RrXHU$mn3(i#muPSS-BwPbDh%nw%Oeqm zCWHAV9$!QOOnd<2bK&LZB$MAs2e1zX02@m4fdKKxlh4ql5T9T-rERdKrQd~umqBAF z@XAW=EnJld;v-bL;=*J?%0{$#7ACM2Ab#bwer1z{8IU04Rec*)x_;KX`nRskU4GM@ zv4od5a#g}52sFmtiBrPfw$Ox$-l%o=v8ylw)j9umcz43m2Yha)TxKOpX;}ys4Z=jN zEt~qWqPrPGiqb|fUMgpVt3&Y#C6+tci>S?+C~Ye8lAu8)62wOd`H9cL5dmSde}h@d z4*Iy|@jXuJYYssEg2Pb1afar2f5yP*dmL;}n5V=zOs;GR`np zFv&B;z5xW`J1HJ{PZ=`s!BOo8^SoS$1j$ArId1@N|c z*Y-3B2%KjNC~K=9D9;VdBCwxYefol#b)9e!ir4c6Fb~7Y7R%Q;5C;D0XG`0D2Px#H(*hOisBvaQ0rQ=-2Em8?7qf z-Gg5}u+S~Apsf$VjSCq_>p%5in`BxC5NreN>-o<-*9>{7pUN$HRPo}6B86^drG|Je z(SvEv!FQScBC!e&o8<}oUMS6AF!IY&G_+ak5jX}h&mNuJ{A~dK9Dfhjg9bW-HZv9fCRd@BZ?CoO<`TH83!D2LSer|Ev&TFaU@DijG^bJp0*_=~$rP zjMjZc-vx}3@*QKmL6(u+uVdGU#b9@>+tI*nK*L2c=q41Snt{}S9tmLb#kH)l=5tWm zA>hfVU~3veSUh2(8|MXc%e!ErGJevmFy8IhMPu`A*t%>0#FGpf@OS|mu<{l@e!crU zD+72lL4+2Z0B|u97-qCwiAov)_*U5b81J89+)d;aZtlI0F8mBl`_t+<4&Go_Dv0dllkrmcEtzW7F!+UwCupd+;S{fQz$EPmmj_h zBE1@5bxoWBginO;6E6O7c5S%rV$itLsc1lovQQfDlkj*iXCnd#_***9dmZX@Ej<|- zIs7FcG=>!lKA4_mMV0C;VK5_z?4Al=yJFq%qINlPmAig^v0$&*j5&2b_)9(e_W7 z93VJji-GYZU@OAY@KQwTNjrP3y*i--t!(Pt)BWq1l3r)jnSNI$=$y2CHBm5{ViMW0nfW?}6#dburP^kPAWUuEGk$vE^DDI5vD7@!_5Df7~C z;A9R^Bvru3OXoBloPBcmgfARe9Kq5F)$073{l|WxfhxA;u5cl63XohY+O$7Zla4t*sUG04udFgi2CqC8sO3FPLCA;?Qp`8E-F z119P|?6&QbHf-P#iOBY4BICHP;HksVN5>n7bplQ%Q8$4nq;jNe)|)ELvI84F?332t z(fuZOA19Hj;vW9Z*Jg3*GcZdb>9q1<*a}r&`$~7#IpT!#&#Q03-NB8_6D57YCh5po zOi5RoZU#(!4!39vC;yl1=DS+TCK#sf{cqj7mk*PE;SPRyiQVW9Ez@d?23|x1=P&9X z@xVLuh95aF-;bh~L`0Le+y3z`&hYXQzsSS8uA*Occ~3j{>h;^h(;s_zc=f&SF#CMT za(rj0Jpc~}9S2tVbWWwIb7!4);9Io5%fEJl@l$LYhvzY%kd1|&C)n$R>lC+#e$|ic z2MV?=xOMg(n6?gJllEbGmOt@&rohy?(Lsm*F}pwe`C(GgfUy0w-1><<>zq!xRZJZI zJH?*5-JvfL0Q;0>3h(IebpS5~M0@B7``U~>K=Ih`*jxMI!Aq4kaB7|AMaTXYqqS%J z8$76wphNt)K?U0pc~B4T%RfiQu9EOGg6G)bx2#0-i#0jc@EKy@(;56qQ|j8~o$m&! ze+NOF9FT_crW4X`-3hNrX<0wd=j)3GBn?4Z47J$|CYwecv|BThd=KA!{icD3Ys|0hk@?=XJOxmJlo91v*2jnVnwlmu zX=`ua|MZXl+dutRe&?V3`hP3y57)=7frk|UA9wyI{V)IW|N7$U=KOEn&G_rc@8$oD z4!g%+hkyU+=&u2RmiiOkRslMZb7p||nR)v_y&9^0Y58ylG*ms>sAirQz*w_+@!6{| z6YLl7%j6xyR{W6^5q9tbH7>wGQQ&&F^D$6&zrc|x$7*-LY-0oY-mS*=$lSBjC=65I5ZXlw2v1OyAu;l!_lb?2oPhW?ogI~D?d?B(&f$K1($51A z9T;%mzVUWg>QIng2QLXkhF){PbV8WLv|Pb-yfnZ-=VFC~HXr~1KmbWZK~&BqKwfE! zjYd*Nwk`@)nTv0piuYDvcS8XvQb~E}d2W*&?5oU4vuD#l+&U5KcPyi>U(PN$1}5!kLD5{v9vtLjcg>-e&;G!x^+1F5`Q|0N<() z= zd%&Rc8<1tnl6sUwbqBwj2OSC0Sr6#)@<%?P1DQ2{a`Je;>EJ28HbCH`$LJSG^)RqL zv+VbjGc~|_a`y7@$=7~_j{Nfm((HUT$^yIt1#T&Dz~zF00cYHA2z&R%mwnBkGYZbn zkrP`_Jv1M4D9{0@8|b*BJNYKfTRP9mVI5Y6spHfe!z`dNEX(Gd<1=o9SvIVKxaxwe zn#F|qZ=54%AqlhDaJvDzQH$Q+S6+PCmk4|Y2A~FAxHIlEX~^+oyHJul_y9^PjQ_Q7 z6E807Ku8Ufwm1HH_dSr};M{srB5l;bi6O^r0DZl?#NlO{@~dR&;<)|6a4vr<7vk|H zTy?Q_%PRUYfN0jqW2tSDf zqAk}BU$#!(J;e4g1KYRno*cgYhEwOC|1sWi_N56EF4fm8U7fnrn?3t1k0&|(BPL8p z?MZJ)^0+I z3t2@2oYG!Zr{+C}o52R1eVx(^_WZXRPuq))bGF{W2_5dXUa`W#A!TRQ{fa@Y3o4RL z9c%jr4fsOG0Rpo@r{CrM)nmB<*a6CMnmx>qFAZcj)HMM7bTU3nUo~I?O;2(@;Lzy*GH^@ zhXH_(IP*^-5VpUq3ZHpr(=v#hCd^^j3mJ}gf{VBMin#23@O~#WqXfdMGf$TZ2;&UlN%$> z;1;eZ7_baCPhR)a*gOQG@dd6W<#yCX7D7W!1C;;i^eTr}zlLvqq_duDyn(2b42-ZN zKj~;VYRKc)m^&QPsQ7M&05}_;@Y*okVL5VPXNF*722I>)>Y1sh?xolQe2Zv=RN6|7vTnIrUytC$ZPJ%?|UgcM0i9p73yy}fWWved4pMa%Uc|h9qhpH(jir>;o9%jkxbb{sEG9+Cc*Gv4{u#}PH z3G|xf=k7KMY4~M>X7vekrru@h>c~|F&F(=fJrS>8ZrL}U;Ics9aAxbJYd8a8IMa3v z6*$?@?;N-YEy61Us>eDDm;(is4eV#U?6PVedy##eFweVsGErG#bb2y;_*8c7aCzuf z40QVzMW~NDrvSQ)^*vh+PFO;Fiu`Av-?UU&TXxCkT0O1$^6mKy)=_x*Ym1F8O0V9+Q z+`9(H)CueQqNlefHFY2^WfRChQAx(@?tz!VHR0>6wCZoJdD?JO$M)M&$U-@^vH>QI zj>r}wZX0XbQfJj&!biy@89hdO(53fq@P3q4oC0mYND$cj4p;vK^q-$2ANyh5O}2IN z{dW_Ybnzz{L3-tW#7SV`6fA=$ihNkGlMnacdED0~8I2NFkQbrRhl5wQ92BaXdk)&) z`|=et!weW=A38fkvq@S@z&YQTcWL+7Ez#gm@@_TJL3SX=fdGZDInnUR!``3%h&pK+ zXV)Dp(3#(k`J}-HTINaI>N(51cEx`pB+fpa4y|}KvpVwfX1JHO&DrvtY#jC(&<6&d z)UDeAWKEoIV}QeSJ@&?>?~mI5FT8^l@=;po+aJ{a#543{Nu0_A+3@TYQ{s0pLiE~W z5An1A`4;`S1xcKjIR5gfU9@hWLThHYk%um$~{-~IJ}@J(iReqQ6_e(X8)Z#(l20_=eR!q!TF9R0ltz&`Psm?<3iWOg9bXq+7o`$quwbvvBTv6mvdo97xb} zOVwWH0nXe3R*II8<()!X-}mGLe@!%)`Nzu6V99j2B`< zWz-|~^uKudvRVHpPd_CI`}vGhP5@d;O|$3huDHbRayQf7`uQ~WE9*=stBz5fndst- z(nvZGFr5iU;+>Hgx^XD}xD=~$6dH}ujR7CZA%wC>KYTQ-*57`9cC^106ZTx1I6^ zG`9RsGpXm2P+lxEmxM8Me#t5Pt>lOk>5aZdemluJstyD=!#9Hjk364%u=yM!{JI4J zCjd_Cj4Gk!-mnWCX*-S%G{Lraw z@IhhXO>C3Dyz)ec(vCdwQ#W;b1!d5K9;W-05ga(}bty^VC$-QCG+jb#-E=VGZ6j{a z4^KY%TKRGIIi3GijLgGym6MOdV*Pge00Vap3fx}2X^`OJ4OUyg(b8$v}X^E?dQXeh_# zPa48+RGUA`BhT?xm{{b(3*gZ0`-B=8M8S8@ldc3qcH;>89!}o{J65Uur(ud`;7gKRD{j%-Hb`39hZ_zk^q{I` zR~P6^`aSyWJ20-;sqJL&z_hNw^OS!N>9dJGPttA zEjFI5;x>wF9AE3ZebY=MZ}tP^$4iG^d!(|lWUUHtiod}QWNTgo860F0)>0z;3@*+< zgU|9}#u%?o95iUF0O@R#{s*x0!l** ztpB)v{>Ojf-~X?F0E|F$zvs9A-nRze;rC%?n>y5r3I zsVxTsY((Zhaof>%5TGpq4Fs&g0gSo_)^ur|urr=qp1JwJ92w%D21zreG3VXKtd>8M ziifVFlkowbfH%m!`^LWzYWR*8(YQ&cu|Lwwsh-ByzE)6KSoja!7+nO9{>fT1HjpZ3zu5(fcXxEC!D zHPTFar~zT)Ak$vl-Q2i3t!+KvIfqfFPiEw!C1#{P#Zh1hg_mtc$(a~{4ytx=gTXmXzj2NH~ai`D9{*=mW`wR(Y6OfPszmSeq)cIS1E*7{EaH(?PL@_NIDo)A*wvIy7|ur-B-PqB0~Y!UKu6lzo#{zde-yBN&0|2ps@W z9`F2&ru>TAWFm+F^hXCeuqPa-XPmr>tC{uTVBwu)q!|738XgA>=t<^4H~VSut{20z zaN31&n0%9&>1g@rDi7sVUu`w;Jvuu2!a_Ai&_NsF+;`5|5gybBiI(l#!v$GO_tgb? zY}vGPXBz+2VMEr$0xJ7yP97UKP!oTjKbhu_yc-~T@>DY861h|zc<{OAizJGcaqO`n)*B?Pv?9$Vb z{zMK06>#+D>w<^==x*=~QsQMR0vo}O_ucEm_vj5nD{eSSJTYx~E&f56p1+D0AuIk4 ztMY?mu?g_;Dm{p^U)np$pC`4yyFO>H_S?e``Po&!7Z*%OaTJY(odaZU2KBzX(%%n8$@^9O1 zAE10C>?x}S{33y0J&?4#%Yo&s!2tV=;Pn7OaryJb_c-Jf96908ce{b-wp0_KxnItOAb;ppey!(~Y1^;E$=4a&|C_MzpYiu_eWV(& ztNU<$q#F38|KWf7w>ZW2uen#NzZ`yN^Y^U&IQ^b<+pNE{{0kz0cWF8QBXf0lu= zSM-WbvcXqtj>C3~zXs-@enAKH0O4PPb-r#EC zwvpafG50&K_tMF5O@Iv$>BGsB4NNEro{pyt0TAld^!*s%^SVS~0BLErORuI3n;8}x zMV9)%_&mqo#`}hb&82EyI@C7A?qhR#u+Ew@__F4Jk~1cIZ?%oOOZglapf5#3t#c#} zD2fiU>C2X%2phlnk3Xr!X7V08c>?rzCwux(7s9W94Mx;a5Zq1;vB1>HkW7gNzcWek zlryR}#69p8QBXJ=;!H-4@tSnyfyjn9z==Gbvi{yK=nk)L*=_EmY7R{!}?QN)XRUq;(` zX-32t0+J&~)K@wq#1AXx=AAA*p}IZciB~h%*quETMch*aD5tBrpPrPWg-#qC;yAJG|PT zS+pZbr#K!QtWY`FyavnEbDi$VjaFUo=%HBp;&wu%=eznck6pf;Zh%X7Qnz!i<5|5| zf5->?43^Pxh9`N`@z~pOoO!qGGLF#YN`f+i)Y7zKEB_PD0y+ES8;9q}`wa&~#BRPK zgWC!&IdkCM`6~`9eA5bzx33u>@M|&*3V5c%Eq23I2J`vDX{UxDnX!s#a5try ze7K`wo>V`|FT$5HOCFeYO;jR5eKkCUt3T;<2CPGFqcFcjDPHsVX0=nw zVLy5fUBr9>t2`c+dh4LBdCg$bzxe<73@ioimh^HxE68~A&|S)B+rwnavbxH58Df7} z+p99Ra4O2@>iFTW{VPB57yhe%`rE(qf5`L0_3>%oVF2Lc%kw*lAD{dppRYP|=D$BW zmCo=xdhB0Le($ri-}hDt*x2wq@!nnj&mRUehZ72WmiK<+Z--+p&E~!^NM0IX&6{>? zUJF}4fe2HF4ud>^;+yo@wVaH>&3N~~WVRQL!E*OoavCT2lF!()VX*bHmBW~hJta&^ z8O{YKK`#N0;nKuN%bw0gcqe+Aehjvlq`NO*1|Gc97Oi2%FSxBkgH|-HpppD#_(^M= zkwJKu2Rqh2(3|&WZv%ZCaqu>LNn41eGa3#X5}nCg8#4H^m#8!2Z2uEx`k%e{jCW=y z>1gO1IZ`i}9Sa*m9g`YnsI}CeK_mC}dkA2w0gzEg&{M+=mwA^-x3WNKh@V-zY4FMp zg4Kop?7Szgc?7vwgyD2GnKrTkWQV5NcYrLPqu5EGlV~GN2TmU93~;|9jqRs;o_w_N zopNCBtAQGLl!MIi+Q5|%2<^hTh5I6wvK@NkT??NwZl&*d%Kk(7Aj3bocj~`=OzW({) z^B-mfPzs;=n7y!b%pieVg|7Gh{_!7YPUi(!Imh_{?3ul_;4_MpD99ihA`fI{;_%z*?e=#}ZeTjqV zrGx5M1e~>Y5J2`%`6TL_H}7g=ooV;veFxTkE=|SAdIDYQur@;HT#234R_?Y55N}=g zpgrXIfaZEkT)BynfxRwKj0zf9387>`#0Ap%xz2Z;3o*n1K^ZMhhGQX z!xkm{1b)pm^{r#A(D4Bs-yLXe1%h%@DJs`I+i7XF0Wvq(Lfs`h%XSCC#eGhn*ew*| zs80cId3P{%uRyR}jV$4|C+g5Ir^>enKq^1%kstnm7Q7^ffANmY!N8k3d&J7BR~O&m z6M*O$+Se4A`llk{I!=1P%Ul3zvnc%8F6b{MKumdg_0K$fbaDnezsSpfY{ zuF?e+Bmm;r@jeseD-U%Il0{l}3a4Q|HXzWoGcq$rHkLH*H89Ii2M?+o_f1dST)c`$ zQnh&njsaJmXb1-V#ZF=BZl{?ic>}N;50ds>nP>oa=V)eq1sY(U;MD<(334XLhAepY ztGdKj2juMeCpi9}05m5Ccd~DZh7QeFof{dLMpS)Jp4{J02i?z$$xDa#)bI;`HvmIq zEQ!)feJ)|6K8bS@h9RW|4@(8ybs zLMLaXo%$etJD8Ry0n8KbvO@XtJ{@3j8o2J>x+sG=yTf0+!dtY69~z__lsw3sjw1ow zM-JfaM54%eRyN`S;Yq$MCzc;rMKa^15i{Hu@`8N^KT&mE^wk+GFN?>A;l$i64#WT<5su#89TLQKI;IOmqY@jxC;3*e5nXsz8WeGfqQ3jp+ zN3RG(uXMQ6ziFw1Doe-Ga|x`c4xm*Ako5@;g7I#lk;grtVEH~H&OB);t&+3~g1gQD z1&3sj-gVU8sq#Fc7wljFB*X0if5$TkNL#r;cdFQDY00mb`nGI4kk?=hgIASjh~4

    *}LI3iCLcnW%f0WHO2z?Q6J+Ry= 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

    Q6DH)WQyua8T4)iL8yzH$o1 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 z≫TEG=!eXRcjuU%t59?qj#uBlq0VPTzG5P0tq?Sa8`~U8SGk;zLbfO~cD+CR|+U zw_oO@uQZkpqZA=XIfu-)jn1;K;$(_^lzCX3`4o4xThrR;3H8@k~76Vhjjs9-@XO8)s(~9sK7)9~z(BK+lR# zwu^S9Yy@?qiDv?Xc%#9kxKv_6@54cz__gu~tc{F(C>$zwR5=dQ1DFAlD-Kz8AdT>V zR>&=DS!tm|U?+dr4wcCm@rnaJ`CaX)x#OHi?N)qv=-1T#R<^tghrGb~}2erIT=VHZ)hqtan~$;8Qk$R2I!2d4>@?oc;3{g>i-z z#IU6|ymt7~nG6rZD zaOI_t@HC$VHhA^UKoArUq=B+P>U+JACo)A|kOKJ`m9sHu_}mgFPo>F@hqt*${v-F| zBX^275mOiR$FBTDZU{>qVld?Dt*fZ=Bc)=4X*QvWSV_CuP;uzbk4Nz)j`(RaxE@;Y zu86?e38S-%d>m}wXsZnVAA9&j`zwFxFSbYTKi<}_e7>#Rc!^1&ZO;4C0b2B2EgWI% z{|J=LCk=3;yD0=pAf%$sI%f+-DlB+zlR2Og|>@t_V_LBtJXEWgMP z4&NC7Dsu{dxGt{&8jRLnmgN->td&j*2t3LLM5GL}GYTBTin6^|J5N563}NncQPNyd zvHF;H>C%!5L?A}K#6Wv=B91|Junj@UmyUycibXmMb0DgxzajJ3H5nk5wN|C79D

  3. Hz%jheBz4~=w)+iBKu{F|E`EX{ed5Hh117t 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 MG@#>ub) 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 LAjt%AC{Mr}FOJ_NlX~T9zfDIF= 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%0DmnI@U&;*egj+zakXbli7%FBK^+q*yg$=$#I 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℞r^3f{`7}04&S}WDKS6_pK1Kdw;xVF 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õK7@zKRukZ+os2BmnDGNlL=B9A3h){Hq=#BQa$~qj=<(ho& zvvvv8EGa{z))}f{0UD{v=yNdC>&H_ezViP)`8w{aQUV#7w&IA&(fZigy={b(iY}Z# z>GXxuHvvvyKmEXI6ejvP_r7s;hze|bx51+JJcWP7g@U7|>B-uw!>%`?HETLv*46>^ z_3npW&3xV2Zf0w3wN|uYS?*4!W*YjoViL0!*VP|Wcke9lb&tx1S!I@$>jw)P^?3OdTkn5j{CkNGZ*G?-63`&s5%AA9eugK^Qt7qHo zyv)orP1F8xdvU%y92PY-^T-aXrKUtlS=9Fz{(SFG(DsVRi3sTAnsI{uW z+YBC-8Oi|Daws`b)8IG-PAo8O2-kBs4@^v2)twH-=c-pX`|}OX&xYMJjA!Qp%!flf z%~DG4)eR{nNm8p4VHn2ap@f@CS(*^G=bL#hZWxAPS&C}e>?Z9MsY*fuB}$Y?mtxmX z&K^DebKmiepZmFAxt((!Q=_3;8&ax5UJi$6Paf8S>i(s0@!(o}mLAAAJ`~A#BY3t)8>9)bJ8;9z) zKU`mb{tv(U%fIS-zV5@n@Y|n${or}`(6h|e{P_I(ZCvJIGYw0tn{m5+^xlIi4!5y? zh)ICfmUdO^VK2MOVS7GK8&B-Stv01lb~P|1k>+8P%4KY==~pP zH)mIGzfSwTdj(NqHgj_ul7x?ic2z@|ju8{r*4rI0mr(dY$;nBrR)LEuvnMd;w73=3 zAy29ygz>>NYfajmJQ1yhJqQ#=6)Wk=YqPhThTnkzT15e!Y6Z+m+|^iwomx|hhZ}j4 zq~_LiC06f&igkpqQ{Y7CiOqpPqF^|6Q#$Kueo}A~TUaSjE6au&-_o5ltuC33c+1dd*SA$u5Fer19P$9yR%Rz=8HaI8gwMVC+E4uK zFaFqH`u^*;-xvo^!cPP~ zM|*Ft;{G37f80D&=?3T4!ie3;l{l+eXc+F$zw>(S{T&3=L{adVbI_j-ID>>pqu60U z$X6R&xM=WT+VD9J#?C#d<1&1?*guuehCFe{~ccWIUm2spGe&Br< z7u&iV+I-cH`$k^t;_hZ`8aD1;4p*vbtxe-*<|~3!wQ;*mXycF`eenw-a=Sm4RNNE6*w}n`|2Ov1WZgx_D!QGgJ$u&g{zk{0q03ZNKL_t)zZ*5J4C=Z)q ztfjQJ5Rtc-?;vKjj+z^c(1{R&n^Wy8#m&IMTn=((wQ60wskt(xAg}tvpThu~;Gy<& zkNkGWT0;@wU>?RvOH*%TF@3srhTN(9Yr#G0SwF3KVEtELviEp?U(+t|uE~K_udjDH zz0aA@jAx-f&fGPG7Vh=?|A1~MGx;>o;Vv&*I$il>xVRXLn~iJ(4C z6ghryx;~VgF-=L$B{dK=Q#ck~s<~CC(S`YVTxxArFb*l_aNpIG2CF)asn(VzUrLj~ zMTCh}TQf6Y5cXtnEXxwl%p};H?b^|i;EvsHw?EzzgNamCz^*DBDQ+lBqhN)M#+00) z)X=b0nBn@i?6&3nY&bvLU=DvhCi5@1t3#JErrF0L26MjoY1Na`R|f;r~>;r2?l=aAeq zv>0w)d$t^i%%R@Rz05K*SKE&1iyofqlTU{|JYd#*8v5Y%b~gZFBZ=KKEK6Z{PI7j} z`@L&xl4vBf!_C#_KJ|59@}YnJN_zJ8d{Y*ZNd(Od%gz4zJKGoE!-VQSoL$OXv?^@z zNVk9`=H?BHYF&<3Pk5U0<}7b^!~e_Ho5tFjX6HfATI+qkVefs;9jk6tb#--Dm%D9u z+s4L5!6u24kO2ZRNDwiJNKsIb5g@Qc1pJFo5($Ao2q}<2Bq9fc`4J?7Ab}*v4hd?5 zCt}BGcei_RcMW$qvwD=k)hc%8?|UMt7zVd(n4G9!pgecvN>ua5q=e(kv)MyBp;v+4UjlSnQbns%>e96scu zmzg;wbubgLcM{QSi!+W#?Q%yf)NTI!&-~RN|HuE)XK%iH`QcX*r<4*Lr4%U@fB`9| z&1N$l^{_vv={(I$#6m;g3vyYO!?e%Lwa!`>$|J9kx-D$1Rb)(wi4DpkT9t_W6#v}1 z;=EqkF*^@u#kh-OHs#IGEYfC(+|i5d1_Bc zn=N^hZLi{y_QI3VnshtuZ=mJj`S7WC-`b2x=i4&fS}7tt_9J<9n5yI~W;#!^yXP(! zojV?u<-kdfH!s7bQTxLFK&)gsdaWEXLd>;;hdrfwRJT_ zGd@J?ZC5n5w~?@?l!&U%Acj_)#!J+EZNH;hYwWDZWHYY{23REX;K@pvf;&zmZnZUC z8ZV9Ggl^>E7-j+R8VV|7;x2o!P#sI+yZ6{z`K*=wHj_wKV(~)c3pn zvaY1~*SjYh0Tk_btX-^Co`4hhU+qxWT@u5wQE5Rd_CUDr+1MDEix=Z=?o8OIUM)y-^Sqs`b8gGjljxU@RybY9BsD}D9N zfBLuo;IDk^|5)mNuSs~U>I_qMlzF*)u^UF`>}IOqB!CCY+Es%M0&Cs5QmUv5LExnv zw}J<|-R;eFN&;9Z#*W+}rL>eKWpejEr!vpn6YuJ>UX9++3&Y4}af}eEzF{ z{Z}Wilh)jC;8yEgFF(@VE^p5E)8Z)&51&|;5xT4my{>q;riOwt3GN-?4=`Rw&imfeHt)$@9D;dKd% zx|l3gRhU~XAP!lxyOJb{wgQ3cl;Fur^0Fa*wCzUrj&Heij5+}t?Ovm)h0Olm>5_SHM()Cp;aGqY1Hu8nq}3$t5k*b2(rg*rp|FoaX$)(>%b#XQeiY@U}S<+azJy?FWZ(Ze%x+}_?!^Tfm{ zZQPdKw(G`DtSQ90+^Ny+;jqa>WY7}#T1vT;*&$#4<_8~K%kHgzpl9qJJpHw=zW;Cj z@jrPpxeVPfj%AtQ%aHJo{hlAYe)++pr%%_HokO|Qjs4&GwXgiafA){EAqyl?655Pi zW`FnT@Sp#QpBRcU6Q&?SoZI{`_^2Rm#=OKqJ%u2fBW)-|Kz{?>Hq3a z|HSj>?>qQ#I22PP9=frLz}tWe?)$^u)XvV&uP!e@%$(fqIL+tVT}p|FQqD4r%TgSG zv$+YNs#%gbz>SQK7UR5d5>d;Xtf84m#865BvIPqpYRY<~|{Um5gGI8W&Hm zF|qEZGHJHy4e6*xsf(FS^Rbj7t4o!;gS{IvGrJX66G=cl94^(Z+?L($0h6TMJ$wDZ>(3r7 zbG^L0xp;MTb2zG3SAu7y#FDUdZK$JmL%$P#&ksQXtPLvZ1$+AqY#j81S_;v(E zGEgZ9a0wd7X|9V{k6_O%nUvj%lbdVh)VbH_61#cR->-lc6!R7mO6EosJ~J-4gOC-q z7{WG79&Z$&*c~m<&hJgeJS17`sorYH6|=A7g!uRH%Do%1eSA&0Bj^G5`czQ^pO$Ov zFFy?e;(-#m!h+Shey>@q^(X@fZX8-`^R~I-)R7g@$Gs9#9Z(|*wtKOa=q+|59*xB> z3!^rBay*O zRgDD^*%Jgy^EN4q6V)6k#kz@O8O6+)tW+YTgh&A`#U*6NW~pNm(pX`t?btRlhEZen zsk5p>QXU4BDZ$|=S`(45R5#ViDH{NTI`!jFQLHSkR!j+Ii)w*nim6H#IJ=?QQgsg+b0)1;iVj19Rk-I)%A!QnC8jYFDk-Jp z(9aSep#xP;y{;k z^~#Akaj6lq-cs90*bOPma@3mx4%6|~_2GQiKYp+q&JyV@NfUUeHO|> z5LM^gnJMPIPB-~{oKK6}9550Fu?P8-;HU=SB=BUYBs6ZfUJkXI2v@Cr*Y_jLY@U|1 zOI_{``(>swWFbPIq$Y^WN?2-fH(}r3>ZtC*NgH1o4kU!I z)~UtWx`I;l6BM&+tuD;Fhp!L2^XrekT`oTIa&)LL!4NZw6WBq>37DYOb;)i$=B?XV z^0SUd_Fm?!wJz#*q;3bR7S=otz=)euFyd4VezFTd;oli>iJha_>9`NN8nt2dAZfG> zr$(Y+qH0D&%#DlhBqS>%Ar8ps+N>yr?jFrLC3eIJjC?&!*7JM47h1??+!0Q2C^fKV z?b@I=iCw{q%c+GKRbHD*l7|XE4`;%)l+dB}Db4e2Y7n|PT<2ZVQj^fKl%c1x%%;WJ zUS3?Lei*mAtVZMyAME9-5RTasoZe~_%sS35qzOZoEAy7(W znuhJ4{jY!Kr~cx9_h>hcLuZcnpI;mcr+&+lO-<*6)Y~8Zp-+DIJCEQ0+W%X&8!dAv zx9U94>g;gNNzPqsAyc)vT5%9?{p#w)&HSnJVfXNX(nu1zTW3OILOuTQ54`*1KmJer zv48E~wJN)DJ5MJ4!~f}j|KiX6p+E4MH$LObwe(^zGpkzF+}v4G-;YzGE@v{^jDy;P za-5HcLy~;9+fDOChG9(QdS7WGBDAcT=*3caoFG!AS2(c3Yjbx}Ft<0ntwJ!bI)wYI zdTN9jGh$~8R|zv!H<-H_MUwVCuuj4plFYD{axlA70+C0Kb#wIqGnslDLNKiWyYn^^V%sGHY)`%ZV1R&ww zpS$v5wHsg2lruHWqPa^1BvSjK@x$(Zim#B3KwwjC)+6zf5V@*Kl_W*MtEMs%7A90h|?o!{aRJ6l7tyu{MD1R44r13@ z5&0T3ZdPlVI`Q}3`(#S>>gs|}lSmR4k^QtM@MfF4uCwO1iYz(jT&k6$PRA*Cxs>AW z+ua6mah~eZF=y%F%l>dQr@kLuQs0knf8yyIuRp%N-oL!KyxkwCX(@F!%f{f;GbdZU z^W!~@Vk`n&VO*9a=&eSOen6E%6B)rQ+FfX`n15_#t_5D~ErpqqxKj&30i{HMhI#v~dj04JIi$x?8p1czL5GfA;bD z`8ev;E2`B^YqivoFqs;)gTPgdh1o4$;dSsrZm#AjanKEk5T5=XmdpfZD#e(g1>8Fe znL0BfNyOcAC+-%NVX3v_#6-oL^Jxkb^^m!dB*|>an5t_OP0f|+RM|DnA0)A<%~RP= zrDrK>+o5Nsd7cS642guNxpc-|my7v+KQpiy2QxeDr>;94*;s0c4DLD?#bS=GPlw|S zhN=6qxOp)h$3E=Am)e;0hvTy0Bq>d0naY$10Hl-Pju}eoDCMk9Ue!=P_1=3w_w`@- zyC3NC>iufo0iXYb{^+|;abF_IQIfbnQFDFo(Kl-$IQgbvRvKbdOzPB z<~N?4?Z)%m&0gzroZ_5IIW5Zq$EF{SWp;ONGF9$3UCuI1#{j56SHD_pe>i|?UexR$ z1Y*ib`o80;)ym<6Z~oYKfAVkt>X)x>j+(a!ofSEW_&iP5SG(QgF7>rm5suWj}9&l1Lw`d^KRUyu3lfFOy)BH5q488o>J4q z7))z%o$B$XN}5t8$tfq3lyXm$or#D+5P(+(aKjR2#7@QzH7%;8mf}S*PjH16SOp=j zSmu_eiGDLad`*U-uJ(NhVH!!C1rC^*nXS}U^6)N@l;CDMSHoO}JUo2!ooTbZe*Rmy z-K!Q@C5fJzAiDDIECg336ZW0>>;14J-JuTTtTPw&GI=#0MsQ_{K>-m__1Nr8tVBuJ zS2G@O6vX!M$=n*fXl41kIXkpH0f&1VoRY&FlB0u%#%T@>xrTF@o%&huKr6<+HgVdl zgHOj_$P${W@^sXnB1q%JB{$@hi^Ys?b!NLi9zNX^AMYB2*vwLhItehgX6I_=etWwo z!uf*-$K!G6ht%iA(D%LT{N&LYqrj}|`{VvLCH~g8KiVG`>BgH^?~mh1uuW&nn5x9P`m zD?A*&V3HAQ5p>p!#z8dw=JT{K)se_qTrjS6rW_ZtS)Xj+guY_`mq+|Mt)R$ye|H zDmZM>g1E{6OtCDBD~;znak{xVsA@m-uU@`LDRo0PO%rG)*}|QOQ|?kuEJ6~Sh^_JU z1Jqdz$OF8t{rkohL;HZ@GHockb@m7$CXp3VTAL>{TpBiv1QH2*Ll)MeVc+NOPzy$1 zgAINMnP^R+Z8&zd_-j}^8sm-Y9yKu>MnI!51+ZpsilO@`#y`G1gN+hlB5m!H`((dT0raw6Xa0pJ2j_`C=-H(WbQ6R>qNp}94er7oIx#iF^ov=9_ndNovM)2 zgP>M=Q|m0c6U^Buk(*gK=K}yLPAyqJJ;ytRs8`iGLlXSnc!gK4QQP}#BN?!zrmlB` zX%)^5SCGJ?Pz%!lkBBqkwK2`DXbRZqss!y5zxn3VapZcu9TLrxcH@{tmU-#>A(BMr zWfJ1t4Fn=iAFVX})pVSeqNR`yiACL*WgT0)$BfgR0Pb>pXw_0qo+an4FQ#RNYf#n$6t<2H zX!X^J7u#Ex#~ltPagx;ak~*!6E;CX`?##>yWhqeygCyW@wA)+dCe-d15T%%`lWQdw zc9?6M1$Z=@Rt3n4hu59jh(m35(CByT`uDpp{n($_)zR@`hQqD4+?jS7#2p-^D%uQ+ zn4oCjUGLeU#z7M7e6X=vMH^l-vq#3gyK}Hf32sJ0M1-m=#6s1KIQ-O!ILM7LZQ@mN z(s+$=8^*mT%xn-)iEDu2P4dT{dS$sN{^i@_tcOpXbZ-iRRP2SvqtQjx0hI*f^X)Qh?HC$DY3if^F+ne;1QWox#Sq=YabsJJn%j*vwk1Piw4xcnLFhkAMB?}3ar5aGc zmDBe1Pw4jH;rgZBUchE|Wg#Zgs_F*!l(UGqM~-&Ivba-;4KD(UzxNN6umWrJ;xHF; zS3slJ2UA*a{g$>3a);ImW^|kG>6_{7@eJ1JL3oVso40w41(GmIoN zsRC1}h0&isdF|}s)ra3+E}vuGyD15au!FQ#fJau?n`eq^)N)axFgVU!b4$#jKZ*D(b0ZQGhDn6O*r~c{*S6n*n`r5|Go|oN ziL2ThxsV)A1_qSZz9Z032ayofc2=LP+#8%a4SVn5q^PoE2nd^69m`t0fB)F>hDZp8gp zf9s=`{Q9JyKZxq#`p|b>=FT%S z*II{hv&{2!oF1H=EwvPbICXs|EFkZgZN_n$LBog7Kcc+Tst!|iRprEhvL5Q~M?djL z{+VC+;x7scQBPp%wtxMLU;e4T{D1!8f9fCJPm3DjbONzCAVk7TEz4ZHE}fm99rk-> z+MJ!ijhTmGsCDV{KpZY%(G8@qW}>*n$pCFvH4)s1(n^9LqmL<4@9<|Vz*Bqelm`l- zl`!tmoO79#5)->?cw8GhY^ls_YB@*!MR20TY7RGoAg~CLnXZY$LEi<%HgEYy0HGO6 z0nvk?hWPu*SX$dr4_3>Rw+$L7}_Ip0xH~txJa}PH___d zfO_VqfB`}hoD z?qfo?QWLEi-cfaZ=L7T8Yi4d*Dg&l1(-#g8a;LYQ9~iZn0-3c+&YQoU11zj%9)|9X z*I#4kG~G?hZ3Jrs;S%9;PxIyi^m(!#FzOc7Jk=u_Gr6gTmYAw~O!G&ZPsT(My;RE`U1bV+U`d>VkQ6h`l+_^PP*UtGHO4;%Jyx702D*>mf@ zdR>0)<^CJ{a!5PbJ<^n?ilXl3!X!e#nv6lj!Vxc6tHvd4Ylke%jEN~o0YQ1JHC9Y} zgO^f5Ph`{r2Z+&iB3Z(3(9}Y_r?rZ377Fz;;4J1$U>xSUUn(N8YpD@@QLENk;oT5~$1!FGwAyi+Oe-^Pu5Rb! z;oZ02cEGzWojtwI4_-RH{NiTr&v@9l%PV{r001BWNklT*g%BB-UPR#ok~G!BU~FNzOd&cE@S&o8cL>Nfp&296LzXhkU{r_>L2Orl zd9Kq`Qc6Uw6(DT4p|r!{FxPo@;nH9ME;>Yj5)O4C%2(@{iJu`E--!jv;O z?dM_uv6ot0ky1AEWhtg8wM3IbQc5YQxe!A=wxPLkP9({J>N1)5=IreCPi&vPO`C^? zTq~ApMnWu-Qq=p2II|>p$DGN?m7u5vbw-^~4(;!}$8tnHVmV;mW4`s};L8EJKozD? z6=ssC$s6ZXEiyMU^7ibFPwk$*p^{6J7>fJJs{DjJod5|}9}TZf3QDDeiNY08s`+uz zn}Q_`kKg+AYwv!J&L4q$SE|*tDoKcXzzkK>TBo@j=Q7W=sxRtR)R*RG&6HO6&vsJ9 zK@?O*cMYS|IG3#XI5!I(G|GO&^~69o4%T*?tVgVa?9{H2ByKGYJ=)rCUTZbe$P@{I zrkl5JM4a>Snt*+UAt#LGSP4jX|6P5f-Ktivsx1?(^|Rv1uBUFeC*ErxaRZ&v@7LBt zX@4I*dKjt3hr@Bd-(O!{=bSHIzC0do%5?iZ-}MeVtj_Z^cSA3^dv$5Q@XKF%{jGN^ z$@R@`+>p07H;3cYrQzkvi^Ej%@aXS-^;^XNk}h|p6mom=_`$aCYMD(fHCKmG6h;eY9${LzbV{N0g6jY+HTK?$y*8GW^r1!xo`soG1Xc7(Ji!U^{~17!?bQm#Er)5o4ZaA8UZ9s((Du) zu-@H3BgWTK5LQ?Y0tv0Gn1GmT0B<8K++UA@GyNW+XGIcl#@`>cbo%UlazMjXL?qM* zMJGtSy8PUAETZAc>;JAr@=Bl}Y6P2x*#fV{zQ0T41tSWW=9fqfg2ZpQqg32$z5e~r z;F~XM#ILo_jDL94+e&vK(Fs1!?*L8T)esg0J5W&@4 z;hJ-bo`%6mqW2xEQq?NdRn^Uz*@=lHxQ@+qP^-hbEJ@tvIe|nH966_XnvTb5f7~+* z5%tn{xv#Z4kh`9xqbzeRi&hYq>Hv4c=x}vo&Y{b30}-ovt=11+(It#TcH0rP&d1y9 ztCu&|FEf=lUf+G+_k8+u-}Q;dkH#UZ`4PI1S6G2nft#7Bnm3t>x^WUBb_YR3Qtor^ zdg*$mL?jK>A>f??@n3E+UI2u^1ct$jRs*=}@;J)SgL71`ED~)U^9BzXk zm?$w5NoGmJNgMQLH-)RadW#ue7gTH#M8LZvES_C$T^udHJ>(2d?XEcq!hm&E+iHV* zqKBQf7r>Ead3TAOb{@sBEXabO2>v2>kCK?l)dWrk0g*d9Kt^F56_A=q-4xJR6L5m4Ph}}_ZEousIN=D5dNY&I_4b`kqLSgp;pQj6O37FBojeU7n5$fwIvbtzDoIt*3Yimv2F;4I`+XA6`$mFkRf$cf3E z=1HqVy%=Gt>J?B|Q!`A}7xR|*0Zz<)PF{5Ax@71WtoCFaM#gkp_EUAr3-@2YDDUre z*gTM&s@hT&9yq5GIXUW5>f+6QjFFfVvk)z%mReOccR6Kd!TyM^e|UWV`R!3z`i*p5 zN|L)|1~bg_T&ok&IA&sZ*S_bJpdt8Xz@et*PSBhniTWhTs~@j7_4;@H;CqkxDATPk zv(;i+-5j-Ie}ythyHPL2Ge$_momYgj!YA+|9hGs%tbt z95kyJ%H4x!=bw15fA&e7KSg)uMs8%FTCJ8^wVG+Iwbo*2Oz)Hui@=QI#s!53O3R>< zW_?7bv<+%hW28w;{+|5swZjr#6(W>^(9+O-posOK+?7a(63AI_ zQZC*T$|g$5oNf;DzCzBPKK;}e_{m%7b})grYpqR!IWNes7W?+(A1NQZ5!;;)1G-*8 zMXji+yLyd>;%y%?0Ix>oP8IC#s!%W)LS{qNRJGC?Ye+DM0@i?aYiByKMP&dEKcVm$ zSA{FwC{$kzaPwFt3uPpSgDQbnOQ6WEY%NYW2X%_>3Jt6+)b@EN<^*RZ7Q}$TnE0Nb z95W|^G}>VUiE9yK);yFPT5Va>)!-O6Tex>!mqZv8S1l(Rk}SvTAN=0;9-n*SXaK>H z4E&e>%FpG8&(iRq6n}8OJ3D`9?p@cFWs#KjlhW|uul?N5S3_a}pv!DJz4PX4=V!zI z`Z6Z`Ab>b$Vd%WyUtV0^UR~W@U*23^+`PKDdiCM;%lC7=`h&myy}$J5|NS5T9iMse z^m5!__N3PL0@`YC%f%=>SVIzU`Mdd<=Y})>$MOF{A(LH(&mR|NgH$c>O&MzdLm&E&;F2cf;=C zgNFvY-Cvp8?d|?p=JWIOaToxfj>|Z9Ak%Jg9lVlm z{4@hw`9F@8T-1tBYrJOi6O4}|Rrrn^gjMab)&nP$4}2%RhRHd0J~=zMk*XUUCg2oX zM&=BS=)F}9Nd%;rvaNfG?)89A+vQ`PM&DV?+##vcKQtBu-Tww^uRem~3)Fc|DUrjV z?jlTUPMSMbLFa17v;G3JTCFZ=+|6YlJo*IMUk$s!`+K&_fOsin+X z$8j7teVw)IG65uXyxpsrsRBA~H(F{8({J~OE+xs_=S*8Bl3^>QREDtVtE=a|e^6mFuTwdSSO0x8s>DJ}7NRt2JjHMXUxg1*R1txresG4df)&JJSV#n~g@lHh~TDLQXYw!skh~*Ot(t`Zww5N zG8R1XM}ufZVw6&a*_)~YLO3p^*1{a57upP2MAVeoyDl%w z!opRdTJn$-v@Dej!_dw1VyZ(<%TnEph+B>u0OBN!YMmt2LLlxWt7@%k=!fKnc{U;+ z`i`0VJ{R-Dt5@gGUVHt)cDcBn)W+SJ!oD?K{PJ(T_~hpvxg~5tLW=UOgD$9b8F7zKHw$^+cQo#9CjZ%A|K?j;`Q6|B`TD_EFJ63WSf<^Oht0;^ z)oSi~n~Oonb18hgKQ0A*=WtCqRk!`Ic<#ILfo~swl}7qJ9V2*Vk7(epQrS>yf>(P0<=y z&e1Cbd6+zTHCNl;-lilE9z1;U;)NQXzV^h;UR}Q0ZMW0y&_BE>RNz*Y(hc3RlsX^3=hJWh%zyJAy?FmOZ(hDK^~LPw z>gv_Sg)CR^ee$&zAO4n@Z?_wF-3*-wa_$y&0&1xV_UePL{LUZw-rx3v@BHj9eY2YN zuMm1)6@ZkLN@=}E~9PWAZo_^D>k6G7}l@8x8#}(^sWFWHdB~J zJKwZ&5)rAjfIy&}GF63pBxsVP@R*_?%SAuj;dhBeaf{n(WZ4#Qn_!*vjkt$7>{L1j zDxh_FV{PHLA~pWMnRB)-<^5+z#4Git`EUV_NYHDx`|Ilvs4BHe+MA;)QH<9tAPA!Q zA7=bva}wbGJ2BP0j~aGZYn4;E;Ps@0h+{&vuw=97urybJ745g@?C#u-Kx1YjGqolf z@W83OrY?uOPbflsJvfQ1u=h-?(K{wPS%+f9yKUeTEU;5Az%_!jgq$;%x|CA1THp6w zKLWfgiyK6;s;874rf&VvQ>|U@iHM2|zy`o?kH_6^Hyx(Uc3Zuw8=S6gZyuaIxV^qX zrf%qjxYkOnXWQNN%@u<-o6Ye!x!Z0#)~eT6m#OPHcf&A#@>5UWtWSRHoA2LTUE4y0 zfjA*`h8P-&Yq&{5iAX}76U`NoVd(mPS!P|9#>iwbuP}3Rg0y!o5*ORVCnf`^?nK;e z#xjv=A*-&|_9mH|Q=}$0E$wQZ>&~1U8Z=800ke7a(#Y)ywMw+`8vt#7IB{-=7%yxo z0@DYRZ!NjkbDZuKscla-b+X@GGeFStnC~yr^)p!8^XsR=Khq;fQ`$T&OrAj%MiDq2 zoh~PwMj7Po*7Jz7sqD<0++4j75sZk%xw<(uaZj{YqjqT%?NbYYqCpxCdR~MHkZS6s zE=FCqtCGG}=T{$1Z%_4|^X}>P3DFhm0cu4}+yYPvk-HajW{3!_lOIEm6BW{>StNrPYOc2Aev@TpRb!Q4@sdDNnfZ1y-i+O_!F)|1cdzbR zjR?%dBo%IIA@@HV%ah%}&@5ETVodHXjBy;RDlZEWcU>n^0k3AYSSgyiM8Ynfh>@u- zwUb=Eq%5_Xh!D^ZL#>4fOHnxbF(J8EXQyed1RQP2nUAGzcf)+Ek~nHuVd^?4cyZLj zu^)Opmcz}(lh==*{lshAZ_kTlCoYl>wEf!4o5^0=oju%7&xJg(IGGtVqRLzusFCChH7!%gL&qpY-u0XF9tWzt$^;_PZ=e?2~a zGpDo^HJDa4GmsZRIBy?6+s`*PUF{d$aP~Z2+4g_<`QO+V`vYJ2EIZfz%bRKH%^7Bf zVKW%haq{DIELGR}ul!Zu^sV;_v`bTek`pehlYcKbUY>lX@Iw+;AkHpiB|QJZPQp@r0TEnQNFEwTm^JUZwH4HQJ9iCBI=xWMG-5qRS3uZ+$^Dbw z0KlBrB-Ryp5sP?n;RGBj9xm;3+l&;0a%_NRXG>f+^#=U?wo`^2h;QVHGo=}-T_pZatE z>qnO}_YZU5SM?B}{I-AayKgT)>N`#;MM!3Xi@7uDeDjn4*1!Ho|Ha>Z`{HXONfyoI z<#1)w_57`0WSvH;0^jeaWfCJ?U0>v(fSiD?>%!P_kn(JpI{tvpk4cE7(`TE958s@R zH`C3lmp7N2j&}VJ?wn>V!j%cNsFt$aUf;a<`oHsU{E;vID}Tbhh7&gD&98s?!=L#d z|LSYc-kFzQI9ubJ%*oB>>2OW;aC5uc?c5#{PmK3vc0|f|aw4t>@A3llqdXhxOp<-x&{65%dOEgyF9i(Yl#;c8~pT6E)Pr%h1 za3H$p(_SbaAR)l^F*!*09VA8-53&5N&pLK ztu96}R_(Hx6VysIH;`~jcPF!-WGh&gl`|zc3|iD6IZJ}ovP@PDk^-sIq?n>6vcQpl%qpD&RasjSYSvYvutuAGN80r*y zY&Ts~IMyo@@Y=k5YXyTP5;UBdQ`gs}7?X+2B+C7<91a)9=U0dCda`}%{Lxm<>dhtB znSf;}Ld_L*Eyh&{&SJ&QA%gHiPf5(ooy<�HnkuY^rYSXv59n>g2YH=`BLR+6Jd& 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%0A0EueM3^}uu{M4-JFdcMm=SbE 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

E=IFMf$Rz`atU%c6q*WK-}^ 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 diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/102.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/102.png deleted file mode 100644 index ff8397de29767ddfe7d578f4579bebbd587c03e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9525 zcmbt)bwCu~+wagJAq^73f=G#UNyE}h?$ROMDJ(4rh;(-vy;fd4i01NVZ?1ptmt?rxg$()7A|`t(@e|BZOCnVP?Gc_{xIx#zu@eP9QGsTco^ z&;L)2V`2Hm{NCZ@erIyKKly!QN$)YK^}m?q0h|4cMIW%IyNmn1kNN|4gKEm$V~cyt zV*OvR*?+<2E^ZJ0QTINgjt(9V=X#Kb7UNku!L;s6?E9Stcmrqx@__Wi_21X;#W@cE zgw6o~E$%-$vvdGxcn<)Si~rFveFOl)5CEtj`;YEFed1#3X8I2u`u!2r$_fBZivR#$ z4**EU0RY$FAKU%mziAu&y@}?&UC#HLHQ)eP0`!0)-~^ZhocD+a-~zY-fx9I@=Kgm6 z&*XvRf5vbheb){UVFOlx6&eZ=fJ%gdMuc+L4ba|qH!9i#`Tx0E02K!X3l|#=$~_*6Qn$*RUPYOAS4C(eHh)n z@4u}7mlg#Z6AK3e7Zn}t-Y!H0prGF~VPIgP|I3St@<0m^VG%Q6|HDdZ`YxUfy}b{+ zYg=@Fe^)ZHoBxXVoZr}ssh<+2eExm)a%_F=WVd*!t#YnnwZ*YM`#~R;!@hR1BHGHn zJvY_|R*M-}L0(l>+yRM!r-Z4MMy)iD1_b}yz|VKu<|=Z&1+1-472f*&+WQda*WzzngTDH@uq%(?QA=@(@N|tVB zhoqRjvf6nW14cbDIxt!$4UA`C*`=U$z_1)_@or#JWXp+-lw5?BmTyKk9Q%AYL5VHG zjzyg~ZZBUZT;&t6nzB0_+~ibTT7L@%%fgn1JY->KOS-YFZY8IwAY$B?2F;0aAuaS8mk{t(|Hx~OulfuNexdmZ7=g{ zRDP!jwz8UF8e$03=o?C04cfOjy*<_LQQ$AcJg$n5(J{yrl2Y@q^Vkr_)gb5A#XA80 zS;0rfmCAJPndrU)KMgg=yKjZtvHo4Ys+(&U1Awk-29lM9L1!C#zpml_kWDrqvHa$k z&>tkZ9`Kj=(6EkW0gbYNZS-+yJbWEp)tsUjQ5?^U67h^HFfjI{y%A9>t-r)VGOj_| zGHU3}#?msVFcg{>Ic3QtYc%C}o?y|)>=-J9Z}}%iIWjZk@wZDEET8T|C}Z-0}=$xXwpmIgiC)Bmr8ky_>E z?#kJXNoc|T96ZAwRTNA7I4mp>@RP5}CGehtxUNr@PkMTeT%s;D+%Px>=(pGI3f5&Z zjo3+95er9jkyn@fnDOT9fi8!>iiuO~cHmLr5iS+1F_Qt-Jco$I5Cg8hQNzLHe2PVj)JPaEudm0#mk+uvK1lR-rY(<* zEfU&jfGWyvxmnoNF7Ju+@KTMDq$_gitGO%{alFsD^-ycmNo&NjR%MWX87vk2VZz9& zq3Sm&)#IvpOVBglZ`U9}XZSXlF>*qKBQ^EdA>;HjY zjEE4avQm@^tL~av90*UrjM6hp$f6W*!AVilWm2f#aZB=H+cZz@GZ+3F%i|=fji6Mx z+5Mec;~{mi5q|Won5;M-WWX5nCa+?HrP<~Wp{?mcxfhZ)Jq3PR^L5|)z!=4>0WXx8 z{h5In89Gj1&XCFz@7|=AMYdiBM{3tI0wd4c7-oUUHjc6s!MaM_WYysq?flWr3t~#- z3U?^jXa&L3fa$f}4^1d1bB)I08ij`VC0Hno7$7qLq_c8ZwivB=@$#GEelz1GDv7aTX=ol0+s(RH9SH8=^Ck?gOAvHOaoS7b zoRUgXRVjL-+5|ZSe$Tzw4$KpXA#oB2dP$GP)ogO%WFDkPgBMKdB;|6(@m9uTM0~y9 zljf@h?2__&(ooY)R>%Bht7gAfgmSz=GP%^Z8??CF4tpEBf07VIQN;7jo5D{%-nW7` ziR#a{|HM`XoR>`Rz5RNA2k=c9zh12XCw4C>Ej!7E7|GRm7zzf&hrq+5zxD`70hmB%uTKa;!(_`h3fWtI0*^*inmU)g`e1AKLqSqX)LVSCL*khu{*oe_^;AC)49i&b{tg7K#mx-h{P0?!x z=XUpZK4*#!wMeLBG+72^%SGu~d{0V%yr^{awZyugZ4lqeWWS4|XGs_FwH7J`3Ojw- zP%_ug_KS?8r6CiF_KER^Hd(UyLND=MZer_lsm`)8Fnsm2c_nB>Whinq4Rf~OC5YQp z()HT?^1fVhvu+lb+nIFN-GXbgq|;3S{I~Z7VTXs{ z0s(JeaVD|7)%s1`Z?Q!mc9g46pzV}Z9`OyQk}?-vk|r2;Haj*y-0cq{I`;Vr1}`Q0 zuCQ#UmdBu|4=izTRi03IEUPoZf4SD=Th19Bx>5*eclG7`-~t7L_+^AW;jnAk9}E+_ zZqqhT%T-2mL&4AV%Yp^9gD>BtQjzW6)|7YK3XkiUJ9dLrrDufP$8~tf*BUO3mS50y zv8pBalOm#9li!4M8+;A-+enXWX|C{>!cPQbeO8gXcxm# zClbjQ?Tfz|vDF`M(UYvlX$m&pb~__dA05Nv*T6JUn^uH8Q1WpuujS3p3rL8nI0O@mYFJ^7~MS@zPo+ z`S+|hF-!{zb)wq6Hd)G4lqX4p4YC^Z775E2&bcfRfeR5yDY`D;UVRiW%9^9KQEZjn z0c{Nb#{6~sQI%3Fn-Jw+ON_bf%6_WrCtQk%DAmR@H{Y`fDa77AE4#NQy5F2kaDoDNxCDE}ElH+A?yPD&!8Y&|!<8-}%grbN z3$I8ROCVnzCYiQ*LPrXN3T*XxXk|J!Xm}JF?zawNH$R70k1psQ7$(+KKK9@Ks8h@c z+d4l=0A+b6Ymc{&)IqQF5B&xvl$|cNh@Iz*R+40u&^GANkdJqC7)>PXCt#w<9xwQx zxQ^XEzO8$-veMR7v|lvlT(lQiOwzo0F}=G#S2?CN1+np;Fej^#TdqlAwMk=Vh~tLr zm6A$5W|gzkZo0*m;>!F2RIddQ5pAy0ULj9$&+GCU%1Ob(Gc}9?kt>HrrXBVHK|*<@ zWoPdf6xL}JI(U9RN{(`V@v$+f*{PHOKg+rh_c?eukFhh;tD-GiYSKM?II> z5uHLGZ#DKipLyvfRp zb4Vv9m%#ywj3elk<7fP3db6YXHWs|BA(q(#Cuk&^b^J?=8dxf~^+JkB2W}5pR#mD) zrW4xp9!E~IdHFH~y??W}tJy$lO20~Z?jbF(olG>rJQrX0>|(wDOp-}@1DDMnf-J>b zznx{ZO|ybX=)6M9YicSQ+2weqv7J^04*8V?PdRPrwG@a|B=2C))#GATa5r#cZ9Ljv zjUGLWfbT{uFCJ;0e=`Y34y*9_RL&}Z_F-YNhFldL@^v;HP469s5sk4CQ5GXrjTh0G zd8st6Z?=^x@+(+*jLcf=A336?g9Pbbu}BU{f^fbBIpNm>;vkmH{hj)RSdI+=?GZ2s zwP-2lfR&1WV_C^?ZT%P5ujC}Tyk6rue(%5XY<)Y+Ol7Y~XFDn#mH?9tU6}RW1Yc?y!i$Gz{P0UT{i#tJc0p}#CLeXR+ z<;lGU^4;Q$^uY*;kwWrN{~ina6tAG>zknXs?T8HmcgVyy)GADg2CVnfb)NK#3Bs#AK3#fSCPs!1 zaVAH2Gk9-E(6w3Dsyt<%Ca4-t{USnYxNK`Up89no30>pqh z(n3=<8Pl*tD_@M${8%xWex`5DzteRG;=?Lr(Tw;5a+e~NB7H1HdMx(hh4?Ei)R>@Z zeEt^}u8{^hdbEvSOnb>da+_Z!>4A8n`+&y%P^TuV-Sp&GcTuyx1>U#w(R(k*^cl(P z>b8~95+18$@-fiUws%An-sJOU!cvHs0y|Ni@_Om9^Bt{kSSw!PP1bdjF_#)7zeYNa z6V>B~3a55u$c9cxVEk;htGrkmO6$26-L9f>r_M|rD(v3Z2gyF4g+vOZ;Nq<2&A_15 z{IUzAOJqt>!zwK(s9yyYIj4gOq1re&^YIvsiOB9}bI6LhpbVZAQ`+18WTf zI;Yc$E6DTx2CWk0)!SC_`pZ2-EE+FQ+rl84z`)yAUHvlWD2MobbG+G1Vvo6wD!d=L z3k`8@+z7`O%zC;H5m7-o;yv_}rh~iNM)mE_V7jkBha1oHv!jx-sOK%lBU9k#ORRjG zMrhHuMzX25s)s+G?&q#TGq4f!-YoTt1f3~e$+}eIrPGh{wxF)8?iskOz-HfD z_5@1#wKHdVv6|P-W-9_hq4BM)V|sGSW$%q8#8bW)7rEhzOKmvT(|^xT%1 zHpvh<>KlY#H%dQ=EwpQIb&-ZRr0R(wv8aDxuHte`@L6GY(#uO5vSxjm>_;(h38zS4 zdyKGWnBwDDleUXqaYt;;xaG#3Skm&U*wjJjM2FmS%z0ZvMsD(}(XYnorN zRM+SQOfMtC6jbR7@Ys?*%{rX#V!Lo%Sbwu@)}>s6Ia09CxoLbpT3gO@Q;46?Nf%!E zZRIHoUg%QID0_;$?D{n5)gs87HYOH8U>nmZ%$9(4j=xifC@W zv?VEBC7B7TcTlDrstwcBO&P3&>X=@Xv@mDe_6i@hlf?7^$Hp?ZrrO#ZSlB9{x1}wdD#N^O_R;UW+#5q>%PzIMsq- z`v98Gx^rafoW?6$RJ;@vX-(t7vik+WMt2^rh>?a1j-ZrBLenh8ul2}gUx~Oqi&?w` z%Wev>-I6HW5Izi59oqOqO&%<_gi3+Vkdm{iNS8kG#9rNRe7%?|em_2Q`+O>?3jaBz zCK5W(9`ENI^tp;*hDo|s*te+0@)Ps)GIRS^AY@5<;kTGepnbhqhYnXu#x++jkAxF- zqUjrsTel7lcOtnO=^;{|!-}>_WsXtQ%S9t0FhqYNU-Q$-k4DR73%Xk7*uo4<~hc3zr{&=p)9%mkG&5}A`6juB~;)WSVX_$zuU4wq(D#MCQy3Jgm?=j36G)YMPS zPE_aws4>=`hgxRMpk{JN88~88IGaD=A}$HWXH93zIQzEC9vb`waC5G0vwajZE=+?Z zhgM7ZR)j~t&xR&}$HG_7ZmxA{NqoG1Xf_celuFVZHTXLUgGnuIj{elhz`$>HZ^wk=Z;V1V*`fHr>{l5Hs{VB-aF3iD0hR^ zdK9Hb<-Vl7Pk(*Nrq8UAN4ROp$V6Q{apN9Lp@>-6q$t;h)znvzXkcNpxF<7&nWEeX zEjbG~iU6Cc?*ulTa4CfrBEsLj1BIhR6vrj75wqpx*7Mud#!{0H0*xsnMR0I_miU-8OjdvpyMT~Sbb(vQ< zwWBgge~?g#Iy)tBPddy6qYxvOmeJ&Pla!xY+RcacQb=y!P;2pKhf`wlln6tft;!{O ztl99WxudM;+ySBqTe2(E{#6St9*^EVJq4;ZdwUxV3#xog9m=qX&#mm|m;+NRX*8&pYh31l zQ+l3a`O?FBsj~dg8Qt>Er>qV^OLaD17xTg>jI7rMh|Q9w2DX!RBD?ioUn9<w&yU((LCgzm4b zoS)v-x%1x^I|;s}mYw&d;ha!RyRk`G=Z0<1gswhL!qr!&5)n{MeVuBt-jxhXdt+EF z8gA!>jpJSSnIUGn0Q?1@cCLw9vr4NVCsRD6u2gQ?McfqF(Ll}G$r+DOh*+QWxi3C7 z>#AfC92zHq3Uo!$@E)A?u8yC+ar><&EOoN~qED~1Kyd+oLT}?#zqLG^MXE48l-xx( z?Mhd-D}=`~vRP!$y%qA|myW4XM)0HIy!B+>b{-LB3&l{dJr$Hw1=ON%y#Ax_^ONUa{6HfqLw)XyGy@X*eYYq{oOy zm;m!(PE!rt&K1_Klx|2J{{RDr~rJn*XNyr{W}6P%o|KraAy7I^)#4kIoW zMzn=y$397gV`*#J=i=q<>Fs)QdNSKHqkcbIrXa$=F&*CmMT_86<%gYypH1&1UM^j3 z_U#wuwD{ca6lT2H5O3ALe|dZV*+eVSrOZwemZJ$uYLZp!#3)CK1c zj+T4>cc-;;?ndN{`X(RB6xlMeBIMIeR%kg(4osB z#G|qPDW)_i@3iegQ*|49!eD1_aOqqcJv%w`;-9|bo6@E86Z&%p=)eEte7bZ#<=^(+ zWJu$=XW!Ty-G@G{edMpEn9M&;xdg?zv2$8eS|4w27a#ia{tMm?gkLI~-#xlmsJJjyP?U>eIw0Cu0I|Zoijff$p4@kLmfT=$VHFA0;d?a5doWx@bM)ab7g@4@SYOM}KiS%l9oX=Zj z{JKLX-6aK4N}GXv&LYRo0oPrc<*`x-yH>iaj|gcQY&!UDO*t7JR^Jx<(`#gTE1FL5 zsgzQ?l3s>@sacA%gY4{iL6L3^tA15#qNhmn0w$zuzQ(00qmUUw9JY91+)Ar0rh)lw z)s0#`U4SMIMA*bbvI^@9(LgtH$zkNC3sTC_1`&Bj_ApxO?Dm`q=(uw|Cgf+8h%9fEAuar1)6<_>(jqV5;=65%HH z0o?>o%@&Rr6WfgJ!^b$_+IF*y=E|VK9R8}>&0XD&)(Vwmj68lHZm{h%Q(XC39qlB0 zHYedGVu6IhF@OhJXv80)MYCAH7L&JO64e~?nYuPIxlmq8?{!Z23K26g_bFSGMR8#X ziQzUXHJCrwNZGZqrnG9wW{k4xh}h;+{lw?)X!`msQ`-xO_qb$tI2cAo1c%Nk{kSk$ z-zF9Ir0g~7aiIIr`s#u;aoUxgKAAftuw%$|LBokI)j;^Y95i3vKV`}5ad396(NqJ6 zo@ei@*H^nyx6vM`;+TNCy)x;0;BwI6N8e}=u|H^f6 zs&uVTn%qf~hwx8CpIfR+sTAGUA;?okKjmd29{-HN?_EGhk^8h46%iMl4xQrXB1vtHdY*5 zU@HV(!*n1AiQGY!zc;OjbHOVQzvPE}Hoi4U?2gNIti4v{TgmdqFx3+`;C!NN?-{q? zB~>IWR?TPuiKu8AN`Qa-9-YG7vAlzy)p(@U5xJK~K%<68C3hGWnJxHcz}?4kV8(Sw zy}>^?z4tpillJNFXRJi&DI2JlTIMZu2FWsR<>i-JfQ7D4#o`vN#S%J4K9PAJlOYRz z*$Cqkb*6&RMcmnz`uRZyEfp@G77yG-PP%Uil4EJ0O{y*zl|UY%RBJ`y;%Q9nmwb+l zZ|?v$@}sVI=qnm#N&^Y_sdXgU81H`YKDEJa{!oi$8$;gK*-*l@%CMP2L8B2h`V!Sb z@jZQ&o#;Dh+P{kNJ)xYsS_Kf9DXQOC>5t?&vdGgSzW4gK*BeJba-3h1T05+NebJXc zMO!lx#X(p`xuT5jcXOVCv}hv!o}CA)CHcyt08fthcpdYBH=S%pN6yh|V<7mc{o#cP zKGFeE{bS?r9gsq7h}Qdy(1}p=rfA!Dy!E77ZitZz=SRj$r?!5?Xi6h?}^OI zcCUagI*PKW=mU(sKVNuqYb>;N<|ec!Zeu*uBYM(iNoZ>Y?0*bzM@(a8g)9Xfgkv;& zu9uHh_&+>oax!e!uPz^kUy*1)$I~VClD5HW7}!Tr5*awpIGGW6|I=hrI+Jc z@rvh?bI;orlAC~R74MVdTMvnDz zY2Pg@6lMUf^8i2x(6ubumR;fVO*Q;NZvOfEYf5!h!lX##-|_GB8}xD`TQp#_70d;= zwx3ee=vHCyM`Txp>hlU;8t*-Eo`b&sYcdi~RS}mjZ z{EtlhBZvHty!nru6u&=SU5EWgj^lEi)pDp>Chqxv$RYm^dH4RfKlM+j>uiqRm++^r zKk3himxRUeyw$%j^>;aN5a0l=0QJxO)&JEgRsjGTrU5`h{J--;&H_MFCIBpb@xSv3 zG62xa0D!BH|99U1z9##3#qIj9If(iQ4i5)_$w~mw@dE&ZUI0J@{8y$v{2#`KRTnK+ zk1JOF*#qnY!T>D51Y&^QfVEn(18e|WVBPPRfU|lz|No^wjr{*>L4Ee`c0eBn0U&?| zNFM;}gEaI(zdL|ce+CDDK~T{DJzD?-)<07wH2(a==)2!^Vw>8oq&<7_n`6fY=hm!{T% zH2FXH+{?FM26laK(bVs&IdF`9h=34h=q*vGyQ{yw`=HTMv%G#s8uvoO?-#%lbyr}0 z4Sir6@a=D6A(4=u1WFcX=OU5p9wPJ0all~nh{mJv&W*_d-9xc~mmB++T35SZ|RYaT))U_rf(<4sE)^7yd3aw;r=I2 ziP8%Vb;*Z{z(NGtkDW;*UWUSrw!KPxcK9~{73fEVLwa~m$fQDZRE51}fYVZE@sgp|Ti7tU5p!p(UHZZ!(Fnd{N@7KSMk5rU3 zVzoX{-=p+N6cxnJJGjrpU3ZtRz1vHrVwuqH#e>%|O@6LYu^!IeZE`~}TzZyeV2&M; z=i)cC27DyP2EEwqMAS)hwEyv3N=YRDk?Wsmw%v~A)EHq^cQomt2?0!LIe@(o}*aCjA@f?WNd#PBLuvs+6a%A2<`S ziuE>UMh&h%3m%C1w!_GqF=T#`!%OchL}pL zfHtwMuIxC_)g!yDFsr!i`{e2UhfGMriyyC#ol$iHm0d`Ku8rJgTo?gu?r>`uf!?() z`5erQU($A7^)LWJ^#79>c!t4+a`u8 zD_-Bu+8Ih-nrC5weD5BHV~c%JEaPNb_hH5w2!=1a}<%xqU@)N3YLT-sx4I^gQ!( zx@;}W`%)xPn9TYM1J@Y!iKi^ZbqKZ^w}GWm$$`mG2NBC%E^@{fv`{5&SxKZ>;QLPhTB2jwr3DOkYr z4hZMXC39+)>@u6(t8vB%SVDgvbmy6Wu?M_p=dc&RrN^OBSCCIBq1NbJFEomr>+|r_ zQT{Ueyp-RM&!etg!}?_K;Yw$!H!*k(Hcn-nwm7J5PCD@xDSmVNn5T`c8F?G&mn_Mq zT<`IGZ8s6fh$|E1UoUgN>xVGnUASR!>}Ttt*l#Kgil13XuI&$Ym-n3WTFa{DR8Ag_ zN{9OpyY?PfUog~garo$MxQz#X?>iM>w9uuT0#~q255|!T9`uD=E6hsc!0jmpm8GXd z4s?pVZSA2pT8ffPMD66j3%Hv3qk9E%ocFn9(KbH(!e%oZ+D<>Zzxzq@^ufgbWzZe0u74L5hZjb9gz54Uw0j z`g5vOEUY$ocKgWrDvn06Z(GKYldCG*UJV$~!Cn*t3`Y-WfGWD1;MY8B5h(|@ewfBU)4><1?I z#-QPdkT7atAyJuK=(&jIQ?QVv%{{;=R=d(HlF{D^l`tM)uzPIzg%u>sx3LA$%=6Qf59So?yjlMwp)1(Cm^Puqxi44B}|d z_lPp;RMp4~+e7d300Y}i+E0IKp8!@eavgpH!$v1BjC7mPox6;aT}hKfDuvD^;H@Zh zyd86SS+CE&BimA}9Pi2UoN_!T414OUaX1!{;O^SZLlfa%19)SIA)nymA)K5UrJK-- zC{FIvF9XImn{TueK-vN7Bm~mtJ(m_jhdYGyEe~{#o~}JQ|B+tDDC)ht&YvEK@#)G? zI&$7*ghFObAd}76_$XHNm*gt!-B{bvggoLXoK$wjm<)(vo>F<7UL1HM0~rYP`p`~V zmUZeDVscZ{yoinzhw?xK+D^{tLTJz~I7GMu@&7zk`sqYFI+pP0=p{aK8S($7ywQ?miE9J$;c`Z+9$}t=^hvWyoX3)P3&dI zP+*Ax^hTbkN5gDpJv z9lcMdtix}<-#>R`P{J-RZ^<73M{$^@ZUWaA0DP~Z!RNmNR3ZG&KUL@I-6ITl#uG@W ztnp12^zvW#dy%2VGG!Eum^^)vj2UsdVj6fv4T(*A6|)XK}Pza?bb3 zG(7!u_NCd?Gky>w27&QxXw4_jxcbl!Kpdany;i--Br6yW5qFdOmv`ZjhIEK~Q9}Qq z{-mJA3~%i?Gf^#OnN~~61mkW<-Ydi52kcy?oyn3CCUX7hGi~)`2Mgf?b9{QCM;FpP z$9$DJ4I*&PB!bM|z1zr?)reNBmU0#w#NfCzky^!*;M7VeO$Y<;tbf5{_{IS!?DN+1eU|33iGtjVFL<{(KT?) zbeT1IBK&O2X#;fjWa)@cFDPb@!v}wUSDAd4VeS+0Fx~C=Co?P7uYpqQoKu9(_=EAq z-mfebXW0;lxP8EflLw_z!jiB)^DY*^BSCS(CB^&ls5k4mEP&uf4Tt>(Y@uCsjvUN~ z{mWgd|4H{PT$lapaof-m4SRzF2DU#kH-?${o#lkq48m>mLHn27{=E3UEL5V+lnuE5 z28t}q7+Sx9{W)KQo^$j&x7$OhnLyRz_y-t;${u(;Q5f2c^vD*E<@cgUvG6?qgffc7iYh z1RNR$7^=`jGV#5l4hU@)JRb`6?yA@vA8@v&XI%1tXx7Nq9nBv^yCZYX=5y4>!Y>Kl z>2Srkhd(8|WbMbw;U$^QU@bfF#ug@9CU+s=4ax1eBkW9$i^&&$_Ox=a(H(L_y<;sxUN%DQ4Rg1~W}}r(LpN6FJ<9Yw0BC5Y_!^H{ z^|u+ekf}S)N-b4CFs6YU8IiI>4#?naaPYrBq#eg|uLHGGcD`)F}`?v`fOQHbT)6v*;>Y$-g15(kG&N_c&M?T`VP zS@>ges5@Z`{@nsJ)un6lR4@!eEXv4aQ(Nuv5J>uB-$Un;%@y+2AC8y2-&Ni|Hu=5g zC@!=MCL29d_+V143&%4BxO2{_P|(REi_%mqh~;SbNCfc`i4 zex;5N744*djQmw?$p_0e-`kahg(iSlI9l6?9ev5d>fx=|Vwda`b8`f&T`Cj9lwq6mLQTlYHF+yQE~aVnbqnBB){V-PX`z z_TI&qB~Se!#)2=@12ndXUAW@JwOV$hXM2lh1^*RH6RzCw^@=Q)2i+ zjeEM^Cw_IsNvbV2=BJUV2IicMD&E1qw2F{D1yf|Uv4Q`qLq|DGq@kX}lQnDYP=D`l zzy}W|GWeYk-4L^@r!D++?k1H5J!VkBe12{Z88w9$!1IOv$4Oig;)&cLyCjx;^r=Et zO#c>GTlqx=FwepvN^9;!#h0w?u^=N0e;vr#ii(ui!-yWZmUq0$DwS$b8g^^OS1YtNE4Q?j!qgH`Esdi<;B0=NCZEr9oxI5 zFLEI}!>`s_CAjwrNq(L1Zfga`w$RA0JL-KW*O3WiQ=6iVvD_0V~UtfJ@nvw>b|}ciw(h4nNzt?q+=hL=mF+ z(zso(S2;>nF%12>K*;qqFT4G`T6?BE_B`nxmXpyEZB3w@J%#k*YIJ!AyJ3aS{uJS7 zGwF*f7Bq%K|M1bLd&~35mHU|rkwVN^0vmmX-oGUBxb)lR8{DnGfy{z*LiEAp;+?$$ z_Gu!3$p^ohkr9m9~VuDG&tbDuqnQLAZwh=eM53 zg+aDLS|uNa*pNYA7#40Uf3(Yq1B@Ez8L?o)Lm;UkgE89n5+C+;3E#M|kyO zXx7pl+P++dWGks_c7_4-{ngn_ESM|aYtOmBkYRF)sr^npTf=Co3}6cn)#OUB3@gj^ z>Pi*m+OAHny_uZ$rlw3~=n9-Kvn9jX@}y_!#-{B9okkVEfkV?3;|=7OccZF+GYG&% zEAAo*PRqBoAwRx9$dd$GH}Ty;DYP9 z$IA3?ks6*Iq^LHBU-1DB*u2&{+Dc02nhU)I|IW(n=PtcKg!|mAr6D;mLZ&z(*XOoC z1gddf2*VnqEJ}{;1F$O+!OPxVvXqCDuflX*R-Z9MaEJ@j`DLc=at#5s6>qgNxO+SM zst{B(WSMmS{Nk8$+a!SE^n9`!_M+eI!w=Cn|JCK=aYVCgC7b%Hz#;^+K5(Qup3!Ml zSd*ReIw%b5U3Pc6RRxT>p%rzeJDNFO7jNyRnGBf?T>TAfqvc{_V@+WPT1^Bz7(^B) z;GZ$rXl~5!g?1M9hc9+TMfpBj*p|SgYt9hK;ie4#lt$#eY;ZYN1FLt8E=}c}x)?Y} zYyz<}NXyHDH_CJvpNv|a;QIfRI5rMdV8N_pxo&?Ronu9h2RXmd3?IT^lZT?Xv9@U# zdq^Tu6*ni^sE~}TSuu)l z1c54=&0g9Zq>*#>eyJrrRkAlqZHN&k$m|%I6D_Osc(jE|9PE)YHJT1j+lWw6*MQ62D2~G6+N)e#zpPRJKT#SksWC^?zghX_eMK% zbBQP^DMtA9Nn|n!WP&w8FF7q_`%cd($pl+YRnM5OjaKkD88>hn5c%(Z^l4p@LFJ?p zi#6qDSpL**VVCjm2je$rmuyb$w2By$1IR}FsfYrMTc6KZu4(;?SfjG@ZAaLDRir%s zYj3D-+1eR2mTgWNcePL8VqpXAc^=chNWxey7F8)Hx=rwPce#-{6% za$bJ2x1En@D6=i(El=6Og_=9}wHK-sQXzQo#%E%tK3D25gR#Nrn77=0#{s0T-a;4n zxlQDe_#ghmY>dwVQk|KItrc%dG<2AVjGHdD!b5hBDSB#_*G*7>>U-o5)hEWF*P}1J z>}Qj&4zjD@wp7H)i!A-G3l0#+n-QkyeK7r`yUCRAVG4M8ReX&^JTXbjkKa5kXGx`P&uKKsQt_YIGX|%>Zk$$@LuU}cG zYIMmxJ{B)~*c7rcyNtNeY-%OLmaTWD_R{VTEpQN5l>Ty&(Em0iQCq(Q zq*>o!0TFKVOwA$i*ihoNz>7>s{w4c@3DcOzWH1?T2NvmbH_ckW;P5wHw zb-hC89sH)G&n^?9nF3j6k*S!C_w6MVA!6ro{{c|O2bbyXAoTG7h@3>E-W^?*`r0C* z93lzLDf-;&9X)iS9aY7KhpM$t&L$NJD%@3DTRYX-&xazW$yAgOPKyJg#N;|#Ei1tO zkQ&=)+a$Z4>=;PCd*fXR>Vf01pOD7xrcYw)PO?{44rz6+HnV8kysf7uF9e2j`9wAg zDHlAaC>laRfIj4*MgL&Q&D*CS&7Aa_or@EZS7k?3AhMh0GjSKo1hO(CquHe00c>eC zUS*3`JOFuxZ>RIH*lqJwy_o!GWIlkR)U1*|%z8=ebvH78c6jDvNOmN(iu4qcnM@&Q z&|N*HC?el1tTq10=e|hz!Qj{*RF^lU^A`mp(lB`s@9)e}bii$BfIGCy5|H)DKeN*(eSvD(cG}gZFD)_h@`-8%1`VyEm zp=~1UX?nZLqQ5PrmU2Vz_t?4q)}jHlM;cb4GFQVsuv!t0hRF(Z)g06}N*@iHIGgqX zLq-1v-V3AHY$e1+Zyen2J5o72gAk?pebyh#3N|y9lr?oZn+G$)MPuC+r zj8FFC8Q_b&Sss&y03d3GiB?wC*jtrNzkD4qR?Xb!ll0l|^Hcy4!$3qbqE&+71w+d; z#|F<5Db@rd2qS9^`a%rYRiR-VrM5#>@5;+|DWzeqV8%(ao2J|@DV5!$C;p2Fxa?$tqZFR7L6ii7by3$(~Q2Jgsmuua-h1^m%a3O67$! z5kT))o*Uvx(6KnV85wOBRW}$R9;ZjuXE_`l42ai83&_3MqL-tsN2t)5bu%;UlaGeh zc2NsR6Q1*F;E*r~P2|Ab`y^mz{CHzvRn^PbqW+d8jh{&kDumHr;{)0zYOD9;(ceJ6 zS>2J=xlbSE8y$ZG6Q>{60qBIHGoeK_Vz40BfLS`3J9KnybEDM{9$UJ9$9%RhNx3-1G#?^v3;SWQ>Ci8Y9t z-LH<*=;*x{LK5`*KWkQ4#ypX~I=raM*xZh_lXM3I7Y6hnhCxZIPfM5ndvZ@fanP{g zP#P$kW6ZLGYtxBkvXT5#tUquPz3mmWtJ1CxrVal2oc74?y@MJo{aYG_bVpAa);}57 zxV&aps5bg9g;O9CrTKG`Epy?SZma=Yy~1);39#U-$#lX1to&Q^?5`cx#Ms@dLaMMR zGx8UYbr_Ty0trtwIzHEKKKiAa)$^g;n476+mQ@B{R{a?#q&@Gt@Wu$jaLb@kc?=rMB`Q7}ysbPJ z^yoK`5bEx6G@l8gP#f9$w?Gl9Fp@|(2JXP8$?on=y~2eQ3#Up`=jBRW3|o<}!$#Xw z;i%@staL|__KKO4lJ&I;BMh+4+GhE!=HG2|drOV_%uCL?i*4G^Hgp|TjM$tZvSdo##pVlo5m1#c@(=RA1 zEkr2`piiXxWF49&K-Icc{+|rKxgR?k{#tkFQfXU0iR;Bk+~XGG?35W#J6ZjUQtPmc z*mdgkZZZ^A?L+0F&5f7KvT|||p95suU~6iR{5t%U&H&<`$7DD2=#UJe_Ih788OI}B z=F-hF=7cS?tD>=RoMJm=qVO5Y(P&%KajBwGiXRF&b&5=up{?qEoLp+R^?-ukSy&sq zDn4J_A>G^|(RiL;*kAqu!-f#CsFZ~7r}tEO)#g6z)_;05>D8h5%tn^X+ou*(ln)%O zsnCMi;jPy__qDh8kVUuk)@vbBp2d)qLRP*PE#rTIZL|74oq7rss-`g#QOiZ@K-bX? zX=!cO^Qj}@@03II;4WsN0|2<3@9NmlQzGN9K78!7jf`C;twz_avaNV@0)xYw?R|4( zYn$N!J)}mtGc8BY%+beoV=D6b)tlRfDQt@^AzLso`0~etP-jw0xjMS#imPE78&oRQ zbL1L;>GXgPBvAuT?c~N4rdJ3cwB*PC(qpMWD<6bIXK7s#%g>oM%coA)M_2?Nou2eF zwmZi0P;ZEvExq^JX?3X&Js_8;?@y^=`|8n9g__1O+_5I`3zY22OIv2T>7vZv zyq*L*U?I1tGxdm&eJLZdKO=w-k$MUA=$hFDq-vy?Chj&m$hn_r+&<&NFDg zfe!umY&yfhHfR_1M0cH0^%dfNj>r#Y!!$4m3iBeu1Z6(AFujhqH(0_GNh-}m5GJ5s zq!>SW4ZG8#^_&84-gtyd)$4*oRP6L&iBEt^HtTO18tpfSvki1Icj#0!Vv9(UjC>HR z`T_u=S3}MmvDNbHJv^hTwgq=3P3gV?`{!Ahaw$${KZn(WnyKyl_u8+Md}w+h`aFCU zm7@9NqXV6zL+wL1JL1@m*1l4r9Y_;uvNiNKu=1CmrbY5;i)uR?=f=Bd=4$CXvpKl^ zdgJ)rZoRT>Clk-E^NSH|`JP{k!%4v*{~5e-+4_v4Ll=gJi#lZ%nhu3u@@-83u*DGG zM-m#6w2a>_zNR~EZeGKtC^_}!?-Hqp&peN)+Q0PFXePtP03560=h^IK*iKQ=nTp2k zJy|X!qOXZuJy39LfNMehrPgJnlw%?x3BF$cBax%reBbTs;9;6QV`|x~%nmf{Hkh&| zaI7O~MP~+C)|m0_SQt#~GG5xb(AKv%X{nmgK04?}W(~#fN|0oz5Uifxz zpU%T;SR5423*FukQ@&(XE?c6%oP4K;#T4bVcl* z;efiev={B`QTe$+`mLul=I^qwYpS&Oz}CeG*$?)YL!Ne6ElZj=xR%-@3|3+XEK!JD zcGp;gTPFLV9XgB{M>&gjDqOL7VN7NgEG&+)*faR}Vpq-AlyZEhZ9q?Qp#OtQ{O20K zfzuJ&Zw~3(J8GIY6*0u?nLKP2f_QzP;^a&O?;IjZHE(WvP< z)5mjE(SJ5;4F)%Ts<#b~!wuBbnTK0qR z^A{=pm$tahIlEve@0+JZxeUbm96Q2uJahBSJ=xGTy4B4SN+x85#kMfS8doL3Zb3K) z^3rfx`Z>YfWJT&AXS8C|+Mln(SaNe#^=(Lc2i`U-FQX`B(6d5wf|y>tEvAY0e5vG1qyKDg zZvjSqU1J9G%a`WsIwRMQV?YoSNlB+D#{7E8jm1T}0%N>mRp8{qUJ*Cv= zNj7q(*7S~yWJU<<{Q3BT!l_mx?1q)qJ}(QAs&a!k7^zAIQ?dJ0WiJzqxULK$c|F39 z3E6@cRV!YB;z8CSNVrzanV0YRAaVmwZ1LmS+%Jo}R03ttxW6f6N9u#0uP6|a!ItQi zjx}>*IL25|?=NnGi`<4s=P6mQFR^8(sy;%v!<@|dYmTpH1eSy{CEW<&CMrhB^Y`+I zu&Qk@&J;pfmmTX9Zg!1l2)R;pYogpb14-1T7+y3^`J!T`Xu532+8n|^z}B^?BLbBW z3}j8b5t7cbu^x-v9oYI}!1ljA45_%3uNN@=t8c)?e@95PpTnga!aP6da1A9eFQJM? zw^fi^IDgi1kjkp|jUMyb-s+Dc=zM*Df!zG`{=}8_7Vr{Q(71GJkBcT!ZQb90zLx`9 ze&dYG6aq1!;fV9Yd|#%>^F#7?jv@1&;n3Dd{8D8;b{IxxN;AKRP-S*vQXM@UQL?af zq(_le=WGAy1*a~loGW{!GQTNvq3PHfX@&$>7xz@r&)j%j9MD2JWM$zWd$nWH^(#BL zeg}40`o$5}tpGAOf9UmfWg@Im-daw4b7LV`)zhy6g=kOnn5y+8L|=hvre{fkbN1qk zSRxWE6vcQC)GH^;LjYK9O2@H`e_L*ToqYK*o`CGyfz&Y91z*rSMtx`q$!nW0P&?E% z)t+fRmD8=LDUO9lfbuz$N)pZu*fs)=vb>0AHdEFGkBaJKsAwLB{BxpoJfSmxHv~ zf>Nu#e9oJpGPzmiwuY+>`km2Fl0wcTtd1ApcrfF@>w}c2fi0VIi4pwcmBhKk){D0h zNS(#XAn5%r%GoX?*xVFS*0=qvC0MF*33YJrJzM^+^}OkXtYKPt*k2*H%huTHeRL)U2q-|2mT(C_$v*%cc<=LA%(|HJ z2O^Qi_@yMdYuyiwe!;^J;R6|dsUc{wbFJ1v8df<<_3Ebou~DQx-c%kdXQE;2nZHi| zrwrMGeY?ASqzZl;n!T{B&8dN_R+%4814WLMog13VIb!sQ&Unnm&7wI^2y()>_C<8AQF&N-pNP=BfID@OxAPmE_1*6 zfQ0Bp`O9{!J!UX{v7FV9V7!pv}U-p_uIFpciHVWw0P143+w!TYMH|y zbMp)F9V9Y-O8#kzPNQkt`uH34WZPRE`~pFzfuX9i#vh>@92pu*S-CLX zP`&Y0{erRKZ98`ZYgxZjY^o{^Z1$r1^K{G1OPT1;6fbOJO#RBwSID-ckaAz81P)OD z;6ZM&c<`KU&8s3aFe&}iIQ_0wm|3a*a=O2gtI+QDx!f=Gs~mij!J zDadhq)NtlcBO!o>6)!XU__RAEpCo*X#J@OfVVz{j38U^*W->^Af_=&01ror$^+SK(L}XwrBF$aCE_6@F{QZao)}dwv>pmr13rzFcU2pDS!z1rV z&|A1S6dWBe!@!@>429I2vI`J9JNc_6J79TC3|%4o;o>U0lCYb@iUvX%gN9T$lDikr z?f5H_m{`2>^6GbHu?OCZ^2ymYti0&2Av-HRSPrdj|911{TZ)tLQ+#51|2Wwa%tvpi zb8fx8g!c5%9I1-9B1Iwnaj;kMYUICr)WYNVcW$Ep$&!$oDTHyGGM>#pW8^iRGNU+^ zgER&v(%+88Oa&y&DY1Mf9$eIjwc&;AKUR#V;TFiQK$haNUU`IYY2DUMsBYYTR$ZI2#MkZ&wp|X=JEI zl_LSrhF+%Qgd9;|uC*r{oqIiWiUau;3I>*$lDq;gSRw0=k7b68{8`3OacFcr!bg^V zWtG+Sr%G}&G zxX(9Z1LmgA@Mc=q9<)60S^RkM!u>1IyoU_iwp>mvudUCy zt__JOGn9nkpj|sl7QYnK#!(7NDvsRlPOg498e88v>uQc0DkHV1$^6vd6;L+=6VCMu zQre@dmjV|I`Bkr@7CrapG(K3dpqPxb+SWAHw>(PHj=S680rLuiv-$TUGNASv$_ zCpc=fu@I80RuCSi9R0e}zJBP_A$%vSb}-xWt=IywZ1D9Q6wGb#$(O7&!s;Sp5bW{5P_C( zmfLfcWU=+ns~Er(N*w}+P6VMZbwQn%F2x$bX8Vs|xLp^o)|a#$EiSBhS3DFwTBG0_ zbEOzED+AVOscZt5S;QkUwclq;?H_{urS-{ z`_+WSEe%xwqu7e^N_+;8?fmyb^OMKz50GH>`fow9gCt!@B4$$;#{> zrkzS(D-@K4f->CNV3$IxNDt^15QD1oSJ@usfELut@bPeJHI$7KF+QiDi5ZC#L?64i z1jOBNMYPA(PCgjk0$KL7w^Y9V&{aNkbF|@iXItkLyT}N>q&x8OIaSFfr&cnI@NK2A zfu$KIN^--{hS8hKm-qo`H*1KLb+)4xj$Y;o3DDckr0P03I2WWT$J0!{Rrc*gSN{g~ zYVyoy=t>THqPIr$@5w<<2Fi?7B-=pz*oSI!OR5(~%+AJs-KxUGo$}f#q~bR{C!1dNB@}rl z*IxaeUts`Qf%p+zT>cYM-GJemo=o|==kUb^FRZ9^bnNAv^;jQVpg9#N4{b0Yq~xDH z=|?6X8M;Wkmmv=x$JU0-Op0qWAwNoocagEJ?!xgHQ~05Ll=Xt~pS2w6BNbyF zsQqz@js60CCQQsTh5Cp9l9qS)mSi?|B=fu%-rT?w)6_B{HJZZ`W`WuQ0iZR^`_H$L zYdRdYo$Ki0NRyM9<|b+~g<7tf$b{*>IbF!^YBcpOup63u82+DyG9=K;r{)|Dcs~9O zZA^$>sj3kWGgz+dK%zc$L0?X{HbTh|8D?y}4`) zf>Y5G*)zDgj|(86rrZNZySFEe#RTR;$ds!kTfXFK3TC#k61cr`S$S^%aGw+DE^9-K zVHo5%C+cXEV;x8JMHHMBsy27SC z7G_vZgedA&P<1@l%OC}~j_#HLaVluGa5EUD_n_4n8KCy8-FfPx0>%G9U1GRnhZUtw z?_ZzJWuY(k6TMP$S|T3ULPU{?FOudC-IkpJDCtu_W)x}BbjPrSP3JT6Ey$ppKgyDI z7yITMOo~$T zN%|3qEiUx|yJD~Cg9+&kzZ6|aC5ex-?5un_RE_z=f`+1GAn``H_s1DWZ?c%(U?N)4 zoAJpCY>Pn*RI`Dy`5smpSW^TgI+ve0Fz_hc|fgLd`k*Etr~NS6B2vL zz?@3X@U|E<%*0q%(bqP}2>QQ)ve~0l1veO(x^kcm)|yYkHk6M3O6SR@Sy+850I@wF zby5UpV~J(Gb+ypV=PdFWWP7)cS-;SO23{JG#xvh4N`LOW$(Bw>QvZuX8Be!oMI?Da z$-3#yhwWP?r!)vnR-!zDtgY#6$u%T5}m%S9h-{^9!|iuz|fC9Q&M{ z)Yzn(hJlrp18pm`1#ZtwdP$^AfjB(8nEY#)&2+Hzi=^DRb3qaa=>HEe=UQ@+ATqFG zIGwN3oM_N5b7t!^Ew5=gHf^`&ufB!Br>%{$RqDj8pm*I0KgoxF*(OC)M}ZMPT2GY; zB5$iFE(i(!Ylf}LCR5s|xW@Ihkz*N3J3^!q%G~Os)Gei3BSbFF*l1Xk>)80qQWAC{xfH9M zrD7&54MJTGBfWMAaEAyKgW7!cKG2lO3+ac z;Wl5B9A{OLrZ9;2nUSxsa{2b{AZ$(|(cHN?#WaO9=r$nSfzf^g^;W-DjWi%R0QS(``30%k zyFzUH>JsF*zX}yjwxMeBL-jcFge7jT%l&SnwHF4-VCt2+l{Xs>kLduNE6ah=d@y#^ zT4HED)-|@uJF-Do=AKD$w1$cgVgrigc482jMzBL%iT>F#rfT?uZ>xxzm|p+tHsXpo z5Xdfk;B>30-x5X1a_9w;6oYsp>GN9A&Ki1f1*4f36i-9abMeS9vN7r{4}qmtCZ$N2 zAP9KN+{}>t!>aFByeJox&-bBiEWM>P*P9o|#gRHgZS%Q5$49aMvC3Ui?iUQ$2u2CT zgz4V)#r}yCxW)&t@f0phIi9lP8iktxWNJ3)BBnvUR$LJb->%7Z6KU*mNcNRv`{!d} z`1kSy6#oU!SNYZ~MD8A`zBvRhz}%_^nqFR3#&tr#Av2qrsrzoXlv_n!Ak>0z9a>0Q%7#JVSwF|#i~*@st8O}9v(iokQfZneFAxr7j=i#-K6UGG|3lJP!x4EF2X%j z^O*(&nX~*7RWIC<71N=@JOlySkEOi5a92`i3DbY|sj`#LG)(ABn6?ujwICbo(SxgB z$^WBSRuF3^Zu)STRojnw@d^*UORF1rLFtEySYRIRLVGT!k z5DjK{gu38+5DjV$ZEcWK#?ds@`m@&fnu9C%JN)YBcm*xGrX-rR#j-mn(QK`W&gz+8 z(}(b<;HIRQJpWU`3 zNEJkrxy)5XLR<9T$Z@7~V$PhH6u}x*2|P>%k)9YInW@ccD?$3!eBC9R`9|A;I_1rg z-oM3H4fbMm2^TP^r+osu%LS4Yh%kmDNPToMxy-{{o}IxUfiZu#+7 zWu$Hi(=g@{#gUjE|J;is|G!we^01`Rw~Yvf*a8Y#nT3RfxYShUq-lVVikX1mn#-7$ zX=-CGrMaONVwsv-Iwqhd;BL96W>Yg|o0|LDG-7->nHGR;gm5aY6l(Mzh+C`& zf#K7xvwgc_)-zaPS@1(+@mRY6Ke2A(zA_1D- zTKcIDQn26Sd|r|CsW%lBLLGTKET{L3EQ2AXx||(KV3JeP1V9tM9Hs;JSpB2JdnSGz zIwT!+6(SCKG{3-qc9cWgGhMFI5>x0ITWAgY&iiD!3s2MBES#spu+@X%v|>CG{g)M7!1e!xQImrZsAutewtC;OKH-#R>D6;0Ct zx!vb;e_K4#mEBFXD!{#?8s=4X-WJoEe5&ih0?q>@Am4E{4IIayH5_58@~X|KAoPWM zc7e+I*SoC}cfosWXe&ljvEmqVO5_^yrh)dvwHVhCN2wr#!E z%b>|(iUv?&auxf}O1`dK4kCOlpuH)I83r0JAA&qaqsR720PQ$>Eocf(Vk-&zV$c6F z5FI-j-iZOxvD`SJvJxDj$b3EJ!)|4UT4wPA&UiXuKMU1P_?F&YG<#CQ&Qz8=ILtUb zl`%Wc`q7GFyFV44W7t;Vs}@*#3}w+{m>9N~&W!PMJ7)7AD99%S+qK1&Ib5TIv?LN2 zOKD+G^`UlzkHI>FY*CT-vt1){I3*?2!=l<~w?srBAAS6XB-c(7y}&9!GTo}DLWzh6 zHi9}%@}b~mlMa}Ne2CH_dg^{7iJgj)D#>5-H{087-o}7ELwZBxK)B;+zR9oNEQya& zEh+iQ2ma~x)|N4dKF6YCZi%L10#+M#Yso0zvdy&vQN*ufe4d7GC<{S}SNb`K7~M}^ zUD2-RXF@5kZtmoF+>Rq-0 zdnUbb7V3j<0iOd-H>qnNOL59qUaBV^vI-%<8Ej<;BmXBKyM*@b5>)mO=C+lp# z?PY^lCL-(oO|0~hB5&-c#qv)pEuTuZo|mJrpf(>0wZy(mRn$EDt(0onr&H8Y8&U!+ zOlpo&c0=Ft&O*4LUNstcZ*fh1?On_-wjJfq`G()#E} z$sg&COxi)$KjMTs*?LgB?^N>bsoGyg16`&*Gd#AO)hVpyq83SScn&d{z|ihHQe|1% z+tB!mVijClE;bncXn{Rqwz^T_wF7$Bj=5qD0as}1)V$^8&G}+(!HD5899E$7je4OEVzGBP$VMY+5u6@q7uS!j< z6KnGG9w8+X{*TJ*N_18*vvIR{Wcz@C<$?{!C7&X zraAK+LCb%8;ImYM9Np0@Wx=k%!J*7h=Dq(l>5jZi*qI=kQmhc+xM!$`w@)oRd4use zA&6?O(Dvl01R0olo&!{|4&<2wLq1XQ#`SnCm^5bCE;Swb(T2@VtGnFSGv}$95_1m^ z+_Tw&0uBu!#9>E+)dZI~7O5v&vI_`$NpI(78@RXAv%rhZZ6y!baCn;|4c(+7P@56U z{36tN+_D$~@eswk*xh~h8qSTbn@`2gYgeO?sG3KclH#JHI|W3XHYOb(e>FiHa;pui z_A>gA$;K@-kri_cpLP0O4Fmxir$3K2KX$c21?!*nQ;vJb-7OD3 zqyupfc2qjuOhYR<346Gd?G`}dV41;&lGLOv6+dFDp37nvs&u|`yE32Gh4gJo8{P|w zr6*dTRNUr!Sj@a}f^3aXsrDPqhGnN02Onj#L4_axj(Ul7HvJ%8s{NwHSHXSAq^eK% zG*A1KeqnT2Dvb9mHE5Z){Qd6c*_2&g8~ti4RU{OhS28_jr=NSWFpZaHFuC;0*9Z)E z@ZOKqme)2z+>trE>5!+$-KD$oR%y;&91K~zZV^vi=IB5e%WHr=#J7W{&YQDnd6Zm& zrmuq=1FSdfV7VX9P9=05Fm2-AjsxG$6;C@!-FaH7m#x?K0@4MlDuYAF^>6MlEr!_l zPSy_&>sL?-g3g>U#GQ|wuo5J-?+9CQ^^64;vNBrQ{l2G$gMZDcHqGswsYWxYG@~4} z(%6sCDKL_RC#H=C**Y87v{N1TP9=;x4K8x)seNc5U0p=)1*g1Za-s5Dj}N@ z9iMrwHAUmFyOJj4Om)ymo3Mt1W$F3$t5l8Lrzv1Da(cBr|L9s+#zo!s`D`u4r|Yl zAW)$6v8en9P>4&AFs*bVwbG>hW>ts)Leao;x~5%ve~8ghks*sMp7ko17Wr$pmw^Az z_N`x2b!0n*SUffrIp)soHSyt|PH9|iMRRnYaD4Feny;?hBLA-`c8XSq)}0$MEe_Z? z#p0f2f&YJ?%O^Q{Bvp&q!E449)b*b^dRu8L9HYT)bu+S(;XL?w;_cE8lB(J8?|bbE zlxD}eKl9Rt;D^a-A{1ho z*csW@ile+YiPwMR`^%E+Bs=U6GYaxr(BONvrA_dJ(H|*$uC}=OElxsgTmEU-I6|qa zM+Fq_h%Wz?TAH2;D+Ya&JepqN=&Y`_qHwc6YHZ&?!_H08n>;_#POhXt4>iu8Db%(g}D>+!& zzAB>(tB{}|k3YS!2!h|lYy~tsar`zcI@a9vFQ+dXjt|X9s&_mmH?aU5!vV)5YJG3{ z!m`b{u!4#@&I_1rc+|_m_h{w?**V=V|B?Wqro}tjzTw3#0csqYL-=Eb9Jj{4cjht& zYqWfpWxP>iP8f&9JXGm0%?msO){2Lg9F{Uv9*-G4N@LD70OVx_6Y|c!k3sJ4V7Qfj zS{~kxrb26#zPj^J`THlLA#Q(WJH@f()?&XoU~QYna>SI8QF{(vj<~0|w{o9&G_wsR zIpwqHlG)pl_EJX2caVmg>}qZ6niAz;%I6EsWE8I=RTHHKO*^XT`kKt*NT1Gq?RNI0fE*x~{AYjUT&a!*82PQPr>+GhRR)mEe>-B=+lXoSy=5*Way8G&I5zrS8q*6ov`(qjo|sO z3!GDvAu;+3tBaNj!jUy-z)W8Y?XbP?A1PjPn(TWn>R$9R@*NKrhNJh=5H<27K+g*m z@Mq3_HoN&B$VtfD0hZl~L_BQxKaiobwA|%0uMn;O;`X55BozyL(zg5H0nI@5$d61P zR-&bS*<9l>^(R@_-%1|2p2xEYYWVSzcB%;bIt@Byxm4TL6l$E}JK7SJg>4;&1V%HP z;|XDn#bTed|G)4RllAF;`$%kME{frcf58qGUTafzcRK02e61a&Fjy7evnmFF%e;;B8^j@NOdTva(x~3tAaDfpn+H_CE zE9ogEzf@^2O;N0^neW=oS0K+2{UTOJIOBFr6Ho>4A zXqlHxTaI=o;sm%kBCMF9(^&dru5SfSg;XyP_n;nhqpxacG}Ebd*f$}NI|OQ$R4KjKzXk_1 zY6)}VN(1uvQWyy+$H3aGf84hxaNW7`rICL%EK&ug99T6J zzso-CMa+&ftx@E;h|fj8uSMv5DKV4T9Sf7qWvqu(vD%VZQ?^WaUCtdwn+2`>*whdT zqvaWMV@n|-8RnC1V#Vbs$c6AMQj8vTr~f zKst_%_Tdc=9J4Zrfo26eeLq^=IIz&6`nNkVMyOqDGq!K^U2qJBB@{cg*v{OfQgb<< z0@tDJ(7NkPyoE%5d_!uoN>XJyUPTbHqZ>Jem+Uny>&eMfKBy>t<3G^h>kzsyTDpgP z+hwk4qJk=V_y5iXRgjshxaw1=Sc^?-Z{#opC{Vu zRW0or|Ij;g4rwZGYDqJBE#~MTvXq0UsU!TgYL4`3VY(u(;>%w?J0_xD97}C`Bz#p% z5$LLj{XA3u0>%~{#pyv~(=VA@U_}m$uEIBBk3HwR1NAN9Vhpw2ve;`+wh6_2w*J=( z%!l=lVX4t*4H{aG7u~2Fq7`?jbib+7s%U#m$+_M4!+x{@F3+*U>*t;$>^!EpiVz`P zbzJ8yhE9nw0tOZ=G8aQ?)Xf=l6E&zkk?u)ns^1*YaR|lDq_}4tN;!5Uvbh-d6b2@B zHqM1h$l4hG2{?;Tu|Pmtf(UYm-D5}y;%Oj&kz>iJVu~BcuII$9SR6U@Nq-t zzZKWdeVeS(Qk$3Q3TZpQd~9kuyoT8|1f3puDk&*=*@dYLk9^ft-+)72p$T;eo7?6i zlc^qH>z6m%@QLl5r=wB!XuH%C zyqiJ3y9D$5>69qS!f3#so*tC*%PmbUFCIY1x#`XSfj-{A1}x3i77a5#7s&d)Vki@q zOx^L&?NfOg68Zk>`s$Hlc=g|>N7Zz1uF`au$ouc2-`L9s&-Gulcp9D9uvl(06yeSV zZN~uZ$>EthQH3KTbY_)~;RDiNGkA%}o46KVIh8S8>GZQdybJJ0voSCOSPFwWA%$l4 z_R9hI2FCP9{Aj#4rN#7aEXJW^WVdsWK^VjArfth_XgWA%2;J(BzgTP|FTyw!vwoBknZ9;pc%P%Q7|X3D>z9Z6I9!eI?8tPw1go9>CQaon zUaoRrg)hdQ8zQN}q7Rz1p?(|-89Bjgy_|K$wz^piEeI{L`St;LQFsxLR$pF$2;tzR z2Ud)W7g4bB*Dy(pt=pHpYIojj?{Ge@tJBKQWlkyqTHa2*eMTr;qT+%>y4qe zfoE8;1Nnc{E4=i@|F0?>3urE!Ui;N_73!*s9I*a*l=8XJA_wfvh?2jD@0)Y58f_5~ zA!|U};QQ(0WaJ3lQKdw&;`^G2f7pqlK>SI$M8+r=qgh1$tj*85#9yzV(dF??OeLSg zwPh=%Ke}11DCr{o6&U4a(%2D$_R+#OA^-F$LGI7}EwjnCO}csQ!)>EsbOI)0`uH}# ziG;lrPBJcc?rZW^+Rr*2eWopl!-2pOvecGrTl#CllFEtWiO@oXC}gUbcC$Am42CUZ z_p7ha1IET6bY(V2=O#+0`yq<)naANP55LFoT9skR^kjXe=269Gg!~zFdF{1PH~VNn zyX1rDnnf>HH~QJPB8Q#vlAd5-mBMi{Sy1U83LWw72fV5)D2xrx@z*qj%AGBmv3< zG(jPe0;_q{hGz-!i_;^MXass?b{8$N6%`CI*0h_kvMb4~eqEljYien&^gb|i2jIq& zHf9=0=(|}Ny*Jc5l(lmqi&Z%GcA3%NVvGGKvY#2*fFVe-siW|@^*sGydRXh0gH$)U z(CQ#m3a_lMZfC-a2fdtCrdnQoPB1_7_mpjMzAjR|b1bAK#o*U(5G(uXvuo0gFNhs* zyiJ}@SLCa*-0ep&JX`0@_C!kbI01*eEYx^~WX8(&CM6OI4KXiqmmVSBzrez2h#p|4bkn?-gO>=o6y@iv+hFNp$O1<>G_GJwz;E zdOmY=r6(06LPO0B_GsXVQp>Ts^<@Y%(csbpn{eo<9K?3N<2KnbFROPP)iu%J3WS>a zJcV&9i|UZP$ODuX{6hs_WWeLD3rW31R#N`E=84C`%Co7SKZ@RtOjw>6%XoioR5ZDe z&bQo&c;$3lkW@=g67lS%wuSO(8ceP2_Z8RTaPTx3_+e)G!(sMYCoWc!4u|6*C@XbT zbyoDg0whr&A(5QaQ>vNo{(y-XEIFg9;KI%HlhLsrJpMqudBmT6S9hPlzzQFqmKMB2 zTydOUCtt1Ec(yXMlDOii{NpaEmoy|s;&lVm(tnU#FizGi(`yU9I~krA2lZ3!>HXo1tNB+kdXxWTs(*1_zFMLPfWJn^dKUkk*#Ew=ah8Oe&{>;jYA^lq+6!nuV7@O-HIo z#LwsCCs;OG61RcwyUH+(l3nDmzlOq4iXxj@q&c7pL? zwYY{^;vi;*mf?U0x}mjob+jql?Pr33VoQ{~>fh(uGrI@KACFMCadN;umxOuGiQrxK z8Z#Hv<}S*=w<}hREH4f4l_IoMn-f0?@3!rsiJgtMCq*E|L;F+c3jczgTJg2)-v)?Nk5xnAe&Y zHrY*g{(ski_?nmya_B{>el0wG{O5gtIwH+Lmg^*oEF3G$x_c+#FS+0o=5<>35%0XJ zEO5CVw|D+yyz3ufF{7zK} zIsK+eU195%L*lz50s;9<5sR$)58vi5x$v_O| zDezujs)&*@Efvo8(z`+f%qG89lw{w~XwSj~m~xY>z_t@_&GC^h2x6AkbmcXNjw7Mg zf8(+?j9=$OPVhlG-RQ8ROKZ=KZeF=LA4is)tl#$i$`HEj#R)EpR}|1{mH)`;K>7%< zm^6Th*0(^aMz63FRtsU^7i}ulT-KL3n(z$lojK@Bi=#HbS3YYkEro$RKobG$t^R-$ z9N}F$hrqnf>9bIgVjjgaq^DW&J5Bu-CB6 zeW_NZSHe!|A{*K6yf(aBsL1I~VYu`h(usbxc|}g$homg>wVA)2cjMhd70YbbTWc=5 zB23*q{p0_mImxi?hqo?Ww&b)}Q9wohv z6QyhR{yZMTh%mJ7lv9E%NICpNv=7W3JG-RhZYPODQZGUa85es0HBCQZdQBFFTv=Y} zo<<}fg4yoIrMoLU(u1*u30fmxKty>@;vSMc{*se&K~VmI0v2o6tk!GA#p1d%_Lx$V zD!)oo_;_Ho04?iqQ@2bPTLC*N(X#ITDGE3S3yV?x)X%2O^*>~9Rzt&IQ8W2X)~{TQ zc|z56WGniZNY3hDcPP}ZxrRlzC@tqtF7Ro4@0B zyfQ57S{I7Ybp4erDHg}p!9F_d1#NC|l~xB2N$CsLpqS~+)6d%XE(U(^(ROAd1_g|* zlaCD>{UN-M&2Wy60}`#}6-fd-0sqRi#_CSc1lzeOMYnJQun{pSNCzxQ87I@0v3EW+ zPsFQ@>arLFJu;$0w-7nJjn;}La`$L=G*>UX%Z~s2nz>nkAXi3_Q2P9|nTSL*M7@}# zhAM=o{`OLjmjNqdn;jG;#b@n|jVMDDJQs{%<8EtMTp?>;8x-TV*QI>AUYpsXopSIu z7&;c@v(4et?<-De+1J7NFEvW_`y@@2f@7~R%8H-*mh6aQ;6EaICG9(^lyhVHK#Um8 zG|?5NGWOD=7oEb_V>mHqVb(79^z_w+0e5=B=%pTxZUEzuLP( zBG6nVph3X&M)_;N1ri{1^h(#}^VL?Au_pGC?hA=caHETqDoVy_l#cTZ8Vyn+&b)+7 z9W3lXK&Kt<(% z5m8Zp<^i{-3=@VAlo>rExBHlj>EMGF57m~I>@=@L@AWVlnfwXV^{})gr9gJ%b;1jf zHr^k~e*}|@9k7t;@s=!XQ)lVq3ec8e5|qDNa1J|TslYFTVbl*4MTh}bi|@P+nDpoMumn4H4xoG5K*0q1bT=8=CnI3xxD#W>}yz$rYiHO2amJ3!&V z#0yg_YKOgu=8~eJM<2#x#LzQzwZ|t4-gVk97fY1d6> zG5UXRJ(+ahSC7ioO+Ph+RAwgJv?0$Dm@^Wx0{2| zFlUSW0O(plSp%Lv@UMY8Nr2dXEKjEX2RiA14fPov&MQE=MQ)4$?NlCn2#Z<@XM~|V z^f9|RNi1#W46?&EislPR)+;MhP1~C>=y}uF`Y0$2K~D?HsK|bKBew>aiC(h1^x}Kpw&h8ycE2Wp*|tAS(ca&o{(RP%Vz5Q(P?Lz&z2~I}P0Lr^>SN$sgIKvC1!;A~lcu^WcNa#6! z_{+bZRHMzs($ff7_8UXO{2f^0Y?H+rQ-=hSmr6>65GKuD)Nj4sfF>y3!*(-s<|fx$ z$?h@F)()-rWGaST<=K_JBfG0qaqb>j(I@w}F+}%daV1F?i-?SqWp$M?5SPx=rV}X? zU_W*NBji?GHflQwAjtCs`p$xtx#@uzBt}v}P3D`O%2Wg}Mn}~` zhAL12wLQsfyh-o7x%vf;mfA0~4H1oWZs|aCVsF$!;Nj+K;K$%mz_p=f5h@F{3>pOq z)+?&wEk?`%bj$shx_G@`&IIzX^w|l$*|k?x4}}FekFNbl9pNPpu6v&4qNB4@u77xLm z{s(gDnWL-!V+HWa_*`qdmh;0vdyGPPSamIGPmHEOw~Q$c`2MF9r>a7zW%x?t(dl2T zNLSRl@xwZU1FeYC+Jz%sam};Vd|rIr`E<_V(kK(Ze+&7*R_pB#Teq3L`;=}W%9F%d zU`JbJ&vUJ}#6f1Mr<+l&s~7BhS{~K>V0PH0#?0(%RXxQ4;~(d~R|{Ka1u+TmXojEb zV2gO^B82E5Ov43x{52f~NVX#E%?HD0KomptNJ^B6Ca{!Sx!)N(NlpkMW>t7=ckbY-w`A}f5;d)(KRHaP~3fgHc^goa>fD0Z) zU0RFifjz4J0SMU{oVQ!c{jlxeYIzSlMK&+NVGCp6(DaSGiI9!^-q`5dl#{TG09;TN zpt*=EMko6Y0MxRq+F<`*o=yM(DlXDNO{QsXGcVlC4)$|%=sr*}M3+k!r%{Xq!`&-KJ7|@Of?;cJ53s%Hh3~XM3 z$byz9IK|qAgdN3Z9dh=<^3Ip+b_1UsX)R{qkKaN_QLl{pfF`s7kaB_g_e3F2Eg^=* zsg}iGN$g}p!lp~Abc$8_nK#llv9uCafJEhu`noR7v|)J4a!O22W7VddxDdl@LN-cz zzsHqLpjuVlh`ZmWLu$J(6uKwk!1UBXmz%MDLx>!ev)I3(mTAX?Z324zf1uPjEm9Eq z6ft2fo?=tMuP9mK+If&qITJ9~8k4;AeCjp%`XKP(>nB?VhXlTskX-FvH_w3T;s^D` z5(JSfA9K__4g$4tlI2PyefjMhyq@X$&2!r)4i~2A4E6{R(ffYZ`q2rA39N7?m00T? zqqkQMgSGzyoiLQ_-3@~LQQOchGhp*^$;ww8)LClKy;8EVinmCXgW5{Z0BZAWU?8nE@RYs#7aUZo8u?Dhk^ zdN`mnr^q^TBgb$<;iiWWIMf8wjW_3L4&BTp?CskO9|GEdXndiw>^o(@m*G65++6zk z1X4cw+nbgbj;8?$0@#!PLn1L_#6kKFU=A&ocR@4phxYi~vSHR^>4KTVVYhxUqe zYX!@gT^yRhX66_DyWWayiu#?Wmpki?Rk2PC>u7Zk4dao31mcb#86!S_A^kDDq_m>^ zFvDsOO?d9E)r~*tKq>hjtV@P4KkW~-z#EPwH2JBnE&>O&&0kFsX(3I3^Zt$wD_EiN zD%8c8gbeeirheF4=2rTgqX#Y@3>fK^K?WIoN~UW2bgwJ@2YOIhiSqxdXBg`1C~RfPHYCqchkiBO`TIwRS>tN(+>)CS1p9_^EZuOPjvDy- zh{teGyhc4qi&OzJ$p3pK2@nR!xzId))*5h<`ZmCIuCj7t=Gae>-UiLw0HAXffW_bz<-hJ(YjWNF2RSIK@5*)Cv zvuovyQX_Q2Fjm_TG9nwLC1K;GFC>e$8?W|>+3~W9l;|D@drKu2F3;9?zqrBd(sFpGp{bV&}-3|Ace z0l^5YTnN|H71YW{PFj&v)61K_mv?xgbqx&rV9~?W4JU@7> zJaseRnKuCZ5)71zT;e|_^Aa&}a+cDs9LCJ8-~1R5vY9simZXUn)_yZZ3lsf7xs}ke znVN^4F!i7yuZReb+z(uwsGy+fjtX-wgA4Vvl>L*^;qY2-Y-;CIx#2+%%W1YSjck$B z1x?eRiO_4n0Sf`L9h^yWD)%}v<@6XXs){{^()xI|+`fDUlZd^-w0}q!#=HZ&Jop8G zWzwTmK^wO)F;0I`6W>xL2s}tvMk8*rcMwoNu?#dVYWV9@=AT~9G1jalfdJzh*ZTTB5UM36|9tjvc5M}$lgUBQ{?FB7WjYZ^{EP-7$hN% zL9*i-B3RuPQ~!Z}@Ok233Tk$4zQX?^Q>lni&JEfUEEl z`_!>Z-&}r%WK`6A?o7w#=fl-^V+D>ON~2vHv$jAzr~*=fJBGuHhZ;)HA(;-@5jHJG z7aX1(qI6!$%rnh&gxo5-a?M4KxmjymTJVla%AWmNdM?pv#}982MnWj=HdAn>>$LpF zW+}M5aq3p{d(WH!on#WWONJj>OmW}KI3(Ti)VV%Z8e96|9MT8&MB6zv8X9USHZfYl z!m1&Ts^Pm%8mGE8K6wCPpZyy+)kt!y2@nYEs!>C_y$&E0^KZkKpP(?i3N4RPAV0ZE z+rpc2ezYRt649knYhVAa?T=xSAe7CQG(d}Y=gWpOy-Dj!vC7dgsvMDgO#{PZc%vH1 za>=VLE>(pIvW%ChqD{Xi830+^S^Ivo-P^UAUH0d=nwC2kre74EzwL7VegI2LIArBF zO|6pdnqQf3A#4|u^$DM^^j7o|U$Pm{v;tIntAn4)heqoiu)qD@w>~=_TY~ho)}~2# zcSM_C{mNPx5c@1WEB!BjzZd0BV7TF{tjIk)K!FmYL8n4JBx?S(R#1KclFmgkz#(VZ zQEffnDNzy4_eYnpN)ZwI<+V;Ebi&rW3t@w!+MKOdtw-VW_|GYj^EK2*SE${8bo+OC zSk4RKTmkCb60-&pb)|6MPN#0G6uES?#m=r1S+*nZ464(0Kh!h*{m970U(+TZz?`}1icrJ3uL8i1Nk4k|q;q}Pj^9Vd zzjBi-@w*G!Y6W#GW;laVEJhniOrrF2$)P%v6XMTHm6=H6jCKu7XMo^62`Jkpq$k)186RhvF zo@Z$BI%tS8D3O38y(p~h`-fHI$*1VMVFLulKH;Xl5Bv4OXO~kN!}5mFOo6;ndeO*C zVpH4|mHH=ri>y)M&zJCUnTK3d&hS_aB_>el7ImQ<$+1)?iF(EH3fXNvGQW)6YI93_+_Bg^9VmI=w0YX-$Np^Fy_5oLiB8%%=+q>tHxw zM}n_A&$d{BPC5Y{23~DowO6tXYp0yKT-~_&cO6GFLip0qs&mE{8aLD@cdEA*@oVp5}4j}S1OAK0?9cX z@tXDw!}rfnSq??>D-#7X=o)N|J9@`MYqn9B&fE>G6{#MKwQ|g9yr2=A;fUa~5Yx=g{>ZhYr5`-0$FX=J}u`v*+jFr20PjIEC z$rNI*-L5C1sW#@{^&Fk`%uA8oX0^GWd98@F6<1)hlgatgxBspza&-CI9x}FV;4Qgt9ZhDQRjCIGO%3awecoLq2*&IhkTyIgrj$1X>$EdeUpEa7V~+ zmkG&AC2|_VHfcHEWZKk~;Qq+PxCuy&v9|i5M?vL7%idU?MyoxQWW9`E^2H&|oEDGh z=wKK=0+?+u;CA>cF@w=Cl1(P;j;Qh z?=)h=!3HOz8K0anoDb8q}AahzEKB#>1VWk;Crab-Ee;&!5Nsjne= zLIUxue;l`ldZvs?=y{uzIL>B+lcOt`a+=Q}2Kg6X7`dn;FhnQJ{2dU49aI4;iQ6#+ zd~W01=@dH72XoVJnNbPezEmR-WpPBGY`Zx7vN>KD2=*}^GXH>l=#dUCBNdw+zIOjo z5gzcxgr!b7LiZ3+bZvRCV#(f{YfQ!Y zR3!*WHM#Mf1Is~4OCiO(ql4(uE(j0q4|TYh6b}I9MIjM2|1J%l>lb9s0b#TivnUK?1;UMOtz2yzV`kFvB+n7=N?0a#8xY zf)ds8PgI09z`f5)!sLEn24ETUD^VYRL%M|n`;B>*e6^S8^OQ~McIU?XdSp^eSqovQ z99WT#5MuTNGiimvfZY??_Ru=)HvVKaG{7M^r}N@=Efcj)V83fw`v&j$wruDCI5%O= zqyH``3hsUz+wm-m>*XR23}EY9gKdHG*cOwtq?JqRFZ|0Az-bMqRd^lFrc;Sa#c zMbwmh48ic$(kJ+xFafME#Ryz0xdTt^CqIDD6`&6Bfj*440zsojX-3tX&-vA59YuPb%Vz3%~e3ASIr;`J2w zt&rQPkI!?BH%t?30X~9ydTz!(svm0?A}>>7Fqkf_w5x+*+Xnx+@&A8ChzOXT6$(S< zU3={p!{-!Lvu6M)zAbSn3izg+T`5r!rJQ{v0vJW9w5W6qo=W8_zZq|F${qrIEoe~i z@UA@R`ml>d+)r|umsWa!wKVv6^gbTAu;KdRf>W4FS}RgHI-+(WbS>`~o)_2n^Z6V> z&ip2wqMTDi@n59zBTCR1o~BpbY6`owNAwpx0OCYU2#ERy;2jVlO%wg$_x`A#fe;5K zQHvITmOZ#!xZ*=X?n5x{9ibQ>%jOhAY}32%S(w#FouS|t$%pZxX&a%s=CV8(gQ70r zb`hUaLOhiqY*Wbvf>Fx&`%j@9J=ewg|3D_sX8%W9Rgp|B60J^6Av(bOD=0v=28N#B zSg9I;Rgvg?#Hf@owzD<~2Y#dj(*|H2Y6d{zty`^+^<5j(2Z>*;0S+9mLwT&7a2`RmEIgqTjov>r_8^AE?cC>*sGCcAd!LL~=N3kow5D-U1x?AzPwlj8G!%@3X~Qm?h89-Ow<@!}*xX>r#;?g+g8 z#ETLdYX(;JchxqsxJnI(&;P7~h<=%T(IIQnaCONt`Q)efRxGjRsTAf^F;GX2%{ZAcKoS&;GQfb*Q$7N&#jR*r_^b8Hu*T ze6D?P{=ge|9#*H}Shtmqac!0Y@Fr3GAaVeGiRI>6kU}JUJ!QYY*tMogBt|Poi>$+{ z(I&>B!B`Mp67K>(BUS1VxhK+PqJY&}PI${gy>gTKWsQ9Z@5p;MupjX-HU989(Ou=3 z$kITa*G9>fIOXz=%&F6#d4URK=l8S!&hP&fNMNfr)R{J0Y@m^$(ZG0aG!Ni&@LOLD zqD$hY8V}Fa0-o8J>(oHoQa>xYF4C3J+wWHT-d_R~J@eE!b!_R?^WC#hokNed1&w*u zOfAh0w!;YJcy`NRP`}I6*q5zF>(E5vtSaH-k(U|^(-wA0mJr)2oqmSP$X)4}HpD?& zo2A9DxxBNn0>bLvj@({_s4;}ZLHddn!k6zxQ!H~n4%8NX=T;?f^R*2O2%n3iys3et zX^WI?tdiK14-wmcbfsMn%*5|Yj^BL6>8iU%ynBKK;ysKtF$E|$Tat!qijo8be#iB3 z8O9f|dM;YWVp-0zJH?`_jsWx;t}kigy>!$9YrIYRTnot!Pr55rM2*q3Nvn)cEfNyS zU6C**S0B!~`!Vo4m5AG=H`;p^OH8#7vJl~>_b`C^QPgsu>?lLvxSw01zqR*pa3S)6d30$~ zS{jjduq!=c)?Ky03?DHh1iq8wBQW{Qi&ONlEBr81I6=EQX@M<(nAzA=;gDbq4RgNd z?t?aOT;uElU>*NFv{-rI$K@jx1`w+~=++HhiXdzhpJcUvAu}Gi-8fKkOzOc0w-1#-s*ni3|QZ zrt-eL;&Gg}e>8sELrXf0UTxqKPfzL3Km9V0bL9HB&NQkJWUQoW)$V_5Z!jE|=(-?wSrOq>SJOt=KyKeKXij23*9G6wUlw#k?=y3Nr|AT235 z6INOB9Y(1-ZJD^iYkTis4A+U{5VV4SZC};eMQQ+IM|{~jyX*Yx_@juq^;Q%xqLihr zA6h)KM4hrI!h}|8h|HzljU+_d~dHZ(E%&m;(bGtDKTZ~CH$Wy*SR~)1+;M*@0YfR~}V>2y(7t<%1GU*gvUs>v1L4BCaVI{Gh(4_H+w{Axfi3ywszt-V6 z0$^w#m>Q;7p~Th%eK~oIixFcQ`O3SW$V| zRP}R(SmLEyE!PX~9Z_PHy#m93(uDM|gU(w0@pW&E%Hy}x_jP=fp~0GjKTH>#Wu|+; zd{gg=&1ByCVvItb`YxsJD=u%3{RG)7FuhA8v4J@aQ1Bj3q3Z3fVU>TnofN^ABbydT zBlgrZJ?6+5l!c=a4YdA`rn3%eyX(GvfZ!Hfi@UqD6nEF+?ox^tcXxNEP~4%oYw-d_ zS}aJ47cI_nzwP_G!-PLFVTQ>`&N+MUwLYu;ZGc{tCW|tTozH!_c0=y+PYE36y|%XB zi{B>yf5!{x3&nXj)rXg z=I?+XO(|GmWaHm-EYd&)nLd3~TSbbBG6wQAU$xCn3J9`EsZLmy>Ga(wpd{p>&X`B( z>k%|4&1sWpR9F)R!H{>s2FDf*;S*%`S7M(3yjIPM5R&A)IF{FyWOd|1>Xr#3Q3Bwt z-=eSmzZ{J0g9att6zXfZixU*f_}ZGS3q-*?ew%`5J#ON1wVF*kq$Yj*z~HI-2vQ@8dv z!~0;W)lw#u0|I7E=xed|kiQXX8i*u*keG$^w#N}rDDCxfo}bv9rkLbggURmuXG8fC zjI*z8AKw|!o%91~O*ZL?zEXvj^d*64C&Ba{`B82_M7@ALYF-Q%_p+>aUu zt&$}^>c|&&simt72a>K`++HX1l4k<+`2RQWl@2U&y#IOhx`|M&q9C;wl3Q}z0hktF z#tO!Djkn{dC@iX@ze|Wu7bJ&fR^tF^3)25Z&SG~bJw zD+LaZA8U&A*qKJZoG4&CC!mWtq#$(1wg|c$DAu1nO8?V`y!#L29KyMt*ryJR#$-YB z+Ie1dD|53ftPm2s+ahggGNcOm8j;hj`IoQYU(PR4f8^Q!j;3kp1^Q19m4I&Ho3@;{ z*N4Zz{3iuOrTtX~qPx*=PGJ4Nrpll}NawwxgaSTC$t#-|B4D&%k^!ew@NykWrR{c8 z{zb_tR(=zup+E5U>fcyeI&=mVjN1F2!eCND<1bg78Bxpm`J?DY&jQM)Yqh|ac5&%I zD2qsux#oxelOO%#=rxnGMi^3~1!z}i=zf$RHn1@c@(ZZD{#=TP^)k0W;ILTr^Sp0p z6ozC`W^Y}n0q=;P7eEjU6wimSy1zr$6mgJjQCIkgW^O@$QXqF%5VA{_7_5}x6hD}D ztAt-2EzGAV_FH)`5&5Dr@nmr>g0&<3J|at^INe%tHie^f3WPxyiNVH5_?^%BUOLgU z!d|Mj_!JL58j5(s8js0WaBp2nC#B!JO>WlrgQKJDj$E5I;r!)e9*wWV%*_oNBAz7g z63#h?YT1-O;Pe=rZ-wrIa-wiuv#<~D+O*g@^q*c#i6FrS`f%ALxZ#{PIrY55&G}nP zu*(xn0?OPWnNleu<9&Fup=U4T6Ku!3pN%=gcgXnDxFMz@=;5kR-o-zVrLxi zr7F6M6x=V3MT^JbuG~C#TM%D{mZT`YOL7kU`Hq%2uIYu+siFTML4K0DAkAYRMY1Je|GE2GtQH0bMG(Zm#%*JoOORT zjQ6@DPmvgRp$b2P&&>29zpgJA=O(c^NSH8&f4^y=AB^IG z>J=)YEeEptx0dUEw+%uuzO*KO(seN+;tvL(YLy}*eDCkYW^M>BOQ5E4q7>dM0}qtZ zFT}30Ib-A`Bl?!P3vIoO#Fo}g`o?w8o927jbwMWcXX1Ru1iQEmPgE5D}nQW+~fWj##o*w3a5=s{Az}A zbGg#|5U$5v;rb8MK^D4zkh?7^hhLFO|HpJXAoKxFq>i>W;kYaIAZk_T)H$4fgdiCX zv)2C24Xe6=<`?I_2c!@0z^W6Y$gsTki__v%aLv?cD1s;!r8~LyR%mHBEYl!Q3zGpB z$PLwRa_13vIVpl(4$)61HFDe_94+*_P4wMa^4(Kj!OHVLE*AfRetHIIi7&UFXwh|L z#x&UFOe;q=lseqob90L=9FdUE;xDL#+vY0!lQiN+zS`<-SwAWdxsPTUF%Lblmh6=cPdhvT`9fty+@hvxlR4*O3`j*4)>mC$8uCYquvtGJ8U(t($sJ8Y z2RDocT4&3YTCYZu@|W-UJHEN&Y#e~D<=tg9YZwq! zi##o2(Q=N0Cy+g&CFn4L$RHpL8MR4+R7S0@z(F(#z}S_@ovQYZUoBH}(H#Jqwm#O2 zu(1XV5v1(`wGlPKyJ5NQLhJ<}x*12(Su=C2A@Vez(2de)D#`7KAvLTz<`ZZJc}3KzI-$@#58D#3uJzs) zdheL~%4o)c4ju^~O??>}#GmofT?8i_Z_jmcS2MyEoLxLN<83&`tH3!OKJ$`9ou7}Y zRGDf4ft!|q4g1ZUEDpeCk}>8U+#$+AAG;3`svnU9F(3CVefsyjwKU~!c!9kr!f-Hw zRiR>r{MEC0P{la$j#AdtllVawhlPDv+Vx$F)J`AHP^Qm-lkyg>U9PhhMi^JFrRZxV zCI%}>x!Hl==q-Bl--;}aC9o}FeV{p0W5uT^q9+co;i0dbC-tHncs@xmv)%nEGX=&h zJUq+?!z_LL(#IU=)<{EeAlnr6`One+K$v%{JBo~1=#d>$QElUg&aoIXiRoS} zH`2#Gl8L7(j99*kLeM0aiKZhl6;McsieZ7yL zZVI9VOSQ=Cl3Qgfy}Sk)A!+5AfxBni<9!7e4D|giah8WHb;jUFJt`OyrtI~9AknkB z?~-|+AiYP#IxnLN0D=9WDxHv8DgZ4>3Q;FC8ElV7&|3Cad!GDHpH2s8F++l^DZL(a za1?8CD5pLI82mXh`x|(tM+N+%ktp}d1rl9#XzFP%q_uKwy6GgvtBn5j8B;XA;KwaG zlo4pyWj*=`t~AdBJ5bV5RdX}Prt)KH3R8P8{3E@Zo5edIuYRHyV-%dOWz(CIVN~t& z={7hUFCZWy2MH0jQp*YgHA>3y%C;>p{j3IRI_AGSkRqov#mldmac!0e!=>iUj0S6$ zZg?3)MfJXckG6DGoXdcdg(l{v{?|7^S1HBw_x?v)^N@c1PhI-A3qo1v6i*iPGcXdR ztW{P$y&M7|$yP9KD7(IiF?qNMdP?szHqtgsMuIP6m!5iG9+?&;%6A(~ zgIvlx(~HuJQ4|jF-vNZOO2qWB>I>^wdQ6`+K zx*^L!0~NFFt5qnwR~y#xiI)K8KNeq#oJPB*PRPcJFHaRqFrY=Oyt>*@d@N;TmF{#A zsHm)FLI^E~@b~@tAuNyP7H9HTa3mv1cy)B#q<$n4oj@bB-u|<*tKF9G?}Y3_L;K_X z8BpWFv-lcrRU4qx0?Q~J!X>^LfI}^t5Ufu(C3__*LB)b-TPs((AfpeOPUC)0O;wA4 z?D+RHQrO=Wz`2lz@~;p8x&w$gJPc`kJ@?mL;l+%0wBqv<0*76}jfROea?K5jD|Y{K zG3q3AQdAFQ-i1z1te`HG#RkXM$nhVPH|$%5{xb_=i@mM&YTK-C)F>8TX25LlWg*=6 zU7((y#`L|fk@Rg}&_trcbAA8JQ49`!)es@7sIC`)e1X81#M_>l>u-}6M031oX$gfY z&BQ#o#i-p{DAT7?OJ0HC;4}u+5qCNKTn0E@h^j&yewXgspkD-H2ndg?@)5mzfY<$I z8l!e3b)I+L9+fw77q%0blDG5Jm~HMIG{j)Sx~uGO&Rm3!Kq(>86) zNf)8&#F8|1k+^!U3Rxjvb`2veVJd&)D)cL^WV|U}Lt%tNM%d9Fnu>V+?PnU|k9edmvgFV%gWD&bkS!7{I zDXz_6h844?2!8jP>fRb4RBqwSJ59nLnOV#uqmPPws$qTZS=EceC!8k2P=AdUv2!(w zooE`@KpOPU6w*iCqqM}66VJ;ano!~>_CP6Bgk=U^)%&4___bu8m)Kp=$0kjX!z>4) z#<$2!A+TfIcgl#9l2kC_i1EZ;99GL0cLsNi{$(TeiR)HpjR?AHG3AQ2C+H@rvTFopOoKgxJ9~Wez4I)=Z$@H@u(O z&PfiL)K*q5re>M|>F#TBz3dZdP?B`4mJjsfz`|cDC^c0o6h7SC!t|M1+#__TE_*1pxfW@P^tdIgOd9XNaun#UO|E*=T!*gk zaCAAvt=IPiH{@E_jOkx@VeapTY{*>Je+fSYgGhHi`03gi&-@1}#SRyx^0qzCC|c?G z#a{I7l7iWFxng`BXSgd^NUzHa&DP^Ry7E^C(?iB|m6WWQ7E%*OlYyyp-o2|%qxDs9 z@3kH?Kc9^X?3q1pEc6zc@hkIH?+?ia-`p7Gh~r2R>{#cscIH~25L%7*e(4Xag`SAS z1QOcvhD{N7)U(rKiNm{?O%w5vODhDObK@e+gvM_|o)jjm$FQSbSV$Q2xAz-w*oiokhRID6A{a2z4h<+W3dZty z3n#6)nu2gfu0Cu($)R&ykQgm?a&J7>y4wwda2Tv!1+s+N|Du>UXQSBsV=Fe~Vzf9e zBuaEc&L5Rk#2tAb_(nK?`x2QM{4IeIWw7aTr2^J`f0Ah^oIW-*ZQUXy`{5zMw|UlVfwQkb(Ed$6q2Qd>kHI2n(zY5vK~PvQ0GfKlk@8ct&;ZY0*qT=(e$pqCj z&t;^7jrh@?C8Um`S^yb9+pXxLI|*pF_ggwGNvNKmTq z0Y>XrC%CQDy+8~tf$G=x4=P`rcTjq>qCE>ZqdZi!OqN^jjXCANxsmiLX)U>TTw1&N zU;rj~|K$(-xziRZQ4t|o0|P@vL}X;R_Ack=`?)?7=_-_z+zC-xLn9+&-WZnTJMzH@ z5_AuK8JBl~YLsI6Q&!C#s-xr6yXMzDFjHnB~_mJF~F1VNa@LbuEur1@i(A*VpD3M{OVZYmbug00Oz_Zqg(V3qa^U3m{ zV_=q7%Q8?a+{RT1xMTXFHxlnmSMn8eI3~O_(=T8W<-GA3I`_jFyz{bt!5eiwm$i&b z`Iv>&j~JYp6lsNJqKgC#h9$c7bWVt)>=UOd@EHJDe`lRh1+9lME;u}_`@?T&>Id%ezp5e2dew9@$|+!W!H9CAY!DC z+^P+Wdi>lk-sSFhv=FcA(Adl`p{OX>!VNpESiyw-9gkXErGvjy!L>i6EE-1 zkFFP?(^w2Hja=?RJNjYq1KZ2~;=!(oRG4(FM0|Yi!ZYZfojEGG_x=N|jb-5>xiniS zio@Vws+y%{YSZP?Ba;TN(-K1BA`qRSAv#Qf#@;}g?}VCjC$WU*6( zL-chQ7aK$cK3X>kNy&6ms(9R#q#2)m>a)xva{s#G2ALc0d!s^HCDV){k0m1Rl>b0G z|AF|sZfhHd21bXb6(SfYEKy?4TZCwzMJ=&hwAG@rr}9Poh0C)Mn6n@%Yzv`v`h|;5vOqf+Y}4npnM@v6$kyj9*qUE&evSq-oVVppTQ><@Qi9(g@YVnKR2^a^FQbP~bw>I zqJNkNM6eRjv#-YGhr2_U?_qFysR03@vv;^%h;EJURto8e#>PF@_FgZ3I!TDc?jyODr?Ieys5DXrG79S&- z36aDsFa`y&Z0Hrszz2tbm%4u09sc$RU5&bhFiJ= zHNNpgN&1?&=^kk#q8*D4giVSsiMv0S20xo6)nE^PYT=IsW-bUo3$>d52{&@91oo^Uu;!){LI%p$Q&7>^Bhz^s%x_*aN zS?r;^76e%5h|Ax#Ka`7ckTd<&z5c7A=(OekEOp#L=Y|Efwlp6J)2u{RdhvDW|+-BCY;L@dp}g41#lWV(yQ4U>SQu1hsRYd#>a0 z45m3ATN$0Zk-M|L(SEc`pDzYq@Z=UYq)$`jVX4wAeI6fN5V8bK zTfwq)X3dZApvtap2F|`3d=(cxe(mIBq1-bg`s5DB#hCC^IAE+LfYJ6>i*25E2x=R#$D)W`8Z}0GSq*<*z$#?zeaAfVI+~G zu)y>JWbWC`M?=7VwPZ#V1t`CEd_o@MY{@auhEe-)K zE^Lualv75ZC$$(Nb88B>RU~m|ie6LFDc}-^pJ;l0iT~ zz>;__DSK?B2sS!8n!lqa%&T0jJ0`R?J@$TdEnc^GB$a-)GgW29?M}}2P7Hp~1{q^w z|MJes&d!+voeZRoiUA()uJ;!awq~KfFSLePvvLcv^FYvglR<$b5V%c`WArmrB=N|x z0WIV3xzZbA_Z<8Za26+v=3aFRL<7DGO*SMcJp=u5MmJ&)Ph2XiGuB~C2{nhY1v ze#cfd<=*O0AnOvkuHGf-2i|Yy-)JNRD{qajBaWrRAaFd&#hsgvMT4r}hF&4g;&L)7 zDi72lN8B3Gg<5Ky^<8Iw_xtEh{yGIiVzmtO&3CH? z?FD|lCyX~7Lp%ObC@=CZ9|_4qknuxpK9>}S(1i&Qq;46A#hH%MdI#MYN1p_`Hp~e( z49&qBjmX#2jOY-a8%9UWMdFLXUOv;K8^)}^p-mf_*yp(y>B-g;A|}=}gPK7VILNd0 z^xR_ThKEy4^sQ1A;FZ`))j>>gui}S?osrP>28c=L=RqJ47j0f zwv0X=-H1W@r)lkZYK+N)iOzf22%g?QUVZ7=B$N6{ zE4@P=#}U3A6JsgMpY`gtM;~^a`5~FlsMn$|zJHnjg}F7vA_H)43Jv!Uc`O~jGOb~m z#Tx2qTdj`b#uCp1j(mNEHJ~`Opw>-K!JpL+{TE5+_hnBiPr}|6+kZZVWeWE(LGzc^ z-{wt!WxKS`*DV9W-&P{|Aishh)N6%Lpoi7?r*=YQ&mALKm8%^7Gq*!{g8-Ur$Sxp7O{g}cQ}#3gdiA5 zs*gb+-GpE4Q`DG1$+!_-;hn~Xt#CrfPJif{h*1{SO!bT?MUct%d*0W4NsoaJPHwKQ zZL1Pg&-V(%k1;L%h!WGyCMQ_UtFUcq}m#q~-x8 zI6eXpzt7wS!G`_z>b>ZOi!#*<`gr47LJlz-BQ|IDM>1PT<`jbKrjn8Thli5SCQn)v zZZU{)ll}ZEp#*T5+tX;g3nJ+&?sDulvgs9D-#nEOxHvT)>wu30q8y6ycMb{qTP0cp zo*=ztiIDdDTWdrxx*toZcC+ZRCM<&`;rsg75|I05&=({PjI{x}6unOL0YOZh&o^8? z0Q?hLLiX|1OZ!m)VCe%w#2VER_&u(JanThyC7ED*^G40R5gGHb#_Ee!KR=#IuAoAK z?KCWW_LJe&YX^i?V{g$Y%HA@Ir)fz!Y8KKwzq9&QTF;HYUf;8|Y`C*)y3E_deNMUk z*&UC6T$JgETrA}RH{cC%U>}823_lyd8+1WFHqWUTns#;eBEuFNA@*O@%Qj*UiHZ=( z?lkteyvu6$_wVP=+7`xjLTAKc|sag`4hX@0k!Qi`iPx?51(I`T{~Bzju~lh<@7nbw-Fww&-MqMD@~Ztk=Z z%(^^(q4x3XV}z&#X>bL`)f%^+GT62SlDKPIu5_V$_4#bi|tVnQh-s)=19o;{3^Y#&6AoXA9Y%^l- zSl+qT!kYL^iG=W^zs`uPV^;0rx{G*~Sn;H~Q4lWKX7668sv#rtDWB0jY!c@wO#k}4 z&~>`WX@N!7IzLN*5onlUBGp7SLUh#H zpMRE6fzq*MbV{SAs0QKTa+juwm%rZ+md7UWVhX%D2=IDL(8UILlA6v?4NUx&4grf+ z2g4aI*0%vaD-?5BI`~`D7?zU)19U%+jOJQIjCL`rS5&{IHbj)o^P*gq@gp0o~-FWxIP*I+c8z+A$~sfkqaQjG3$M-ih1wVYljIRX)xnd)Q^>)7;16!$r7EX8=>;qjX{ zM%xK>gFRLy4-M^Cr(pVh6asN|tqJ|bUZWnxP@_N`1)>7JFS!AW4nb%kQ%vB6gL7L@EZ32X>dH}LF&6@xEpS|s0hEg((J-#6C`xHscSRXdT2;1s^6S!!v z&CS9hy-51DO{8l{xRQ5#)e?mMaW|gTEL~nFCF;>7zDbijEbH33c7UxzM{ zLv(lkD zD8bTK{D+5%0YH8e7ZB-CPP8z~|x8VU2m?#1c86XSz#xIrSt2w3%L1Qk-$a{N7w*d;ji)s;*; zv$3(k@C1_ldZ8LPpJL#pHU9$*?LwfFA4(cxD*9!_Yk>IFHF?(NF#G%n4RiF&4n5`T z($#$=#3$f|E7Q^IgZS0V(oH(l>A}&Z^H@lHIU(DXe-FZ?>g}KXze)p*vYY<`2P=Kj zLBqbExB&FPt9UvTvNghDaY2;kMDljcXi482_wTEiArKXSVeg?`dUkAc=s+WDKu+^s zAHSk6y5_k*@8x+0soLzvB_~t|V=(UUq=ZVlqV4%*a0KWO+$Ah^1Qx7m1Lvqp232(i zy&Za_gw`+d(ov%bO?KaE&W$hDCAJXhS7PtG^rJRL{?&je$(lQnj5=?0?_XFC+NmH^ zcHxUxFF}LUglM&?)!~(NRL|W)-ZY=ve$M}NIZzS%foT?}929mB0pxj#UmJqgaR0>- z9X!7+=r(q=W7Zxr1f}Fi$wE&O2GPPKW^m(bx;qT^sawmIfuJU(};8BNYNnSY!_z= zLUeLvp|+kg4>#`M&Yn3ROs5zcU9F_VpyM|?K?$98mcw(A`Liuhu?Sgzqe8C)`69Io z+W1B}0rD&Rj%JHFLGXc3r>x)xX+~qtAt2YIUHcbQ>6~EK~rp~w?4)E$KTl4Z$_~9cenS*7r1y5?SBQc$KTUX zM*nbYn|3CF6`>GkcK|=DKv`$x?>{TRVM|F#NrXqqo0OEmokv8*n?0KA1U%0Mv%lbO zf)x?^e9g6wX^3pP^1jd4bZsKP6-rfbrAnonPwkC%Da0J=5I`bSi?V8TyAx8zaCABU z@q-V}1!*N_VbsD&g4+x6y`(c6;`gr|;PKIY*WmZYZB_RT-Ifz~W{{w{3V9bDG~@-7O-+0*?0L$yNlB_VjOZK zoHa^0cHZ9y1XgDhV@Zfl*4Y}IgtzS?p%y3U-G7pnCwM&qbm9T`pHJT0Iy;Md?nVI=S%w_a*QdH?K zM(y-^PRZ8X;*5{)OZtDH#Yf~_^hDlG27tplmNj6C=~;`B>7~j$6DAmAWSTWRWorX< zjS06dR3%y9a&2B+SBJwp(t=(3ih_sqZIMu$j8jCTO9g>>aGf`v@104*2zmdwCGPhn`7ZKpEv%_>WpyC6nJv}}D`rbFcuGZ@5b4F)u zE-rY9SMQQW#>Pf{0%;$WfLq3vQ~;xxMQQCl^%*PmX%9R93YH1iyn`lR63|7h(sHC+)O_+GeQq z!l;(yRIEKVUP=uFN&GQ_G;;hM&WEuA1kq#o$)ghdnZqJo-5vt#;;L-8J(BRe#RNr( zvu-ZCHvO>05{jmvwK+!ZxK^&>S%gN+`^OcIE*IVWKb|;Pvly|FNuWDS3n&P79rT^$hnrZ?3qk=`Vz1f zC@1d0k2WbiGK~dgD^9L8eV>!C>i`(J*8gS0Rwsi=!{sZJWr*4u`oCT;Q_4msHbPgW&0e6&SVn)4 z_I^J`iN8f5qIE&AlPD^P0~2{Wy!52DQ=rDnH1-uHqPXktG?q5h$tLWInug8#$^Mhk zj9sTaz1W`~b|S^$fjn$1W#aR8v*x??pjP5_TRv4*7m5=Fm$EJ?)+&7N#_B(>?n-z3 zIlEpCy#>Aeu`zROFGMgzTGk>aSGcn!lBSX2Omw+~gJb!6+i<&M6v4$HP>U0D+o#5O z5Pz{Aib>s2HTj>9BO2pIMbMW5v6s{KcIycWTG_O4wGr*QYd^)`RE26Fv`*f9LgQPt!-j&wo?9?{ejvgl@f`T_9xTsltRIQm?E0 z>|B2fnEzaASDwZhhSuxfXX_ttFi+p%__{*ahkJqQXPxn$1p9NP667gC) z?#;V%c(coi+U1un-&zb!Gd|o`yvLWft@ZlW=~cYUno8U@`*1kq@Zk{zESS_Y!I&^G zHd)ooc`$}{_C-OU&V!C`CpHr=Ga7@vdOALcL@%;Zmp)kjD;;P9aXd$?eXew>d86IE{~LME8@rV1sO_*5aaxW01W-EP~VMmj0RJaU;$lFugF z8PSpL%g%VDn@ULPr0aUrvsZKvb=W1; z{pd<9hHl;U(|#GelasPS<6RzSxNV{GSUX>~Fb>T5tJkN5&=a-_BKIb)%5U+O1;OID zK|Qij=3ohv9>2RMd@JuyyaB~02qY=9V?d`}B7qT^OSy}x1B1w2DUp`g#>8Y=jxh62 z%X!`yCzijH7yhq;Mc5mAOTMGFoK>uS=v%h<@h#_V8 z#dM^olwhW-<9SmaKK+1j67IAtE(*3~J{{q7Ysh5?)nvIi6(Q?Vq{cT1PjP!nb1kHm zlpwT**@FZobH;YMm-Re?L(hV*p4aH1&2*rHi7CJZNITFzgSp5tk zLiJbs^2)nVwhX!|CP@fRM$OGS%X~6Q$M`hBn3D>HfMn#Ur$|}26S*%ya>IDbFJd0< zc~eC8E6b3vX zXVzSb$fQm5A%hJa>=rA@CJ9GH(G*a~X~0{-o_k3!rw#H;H^S zoc+`DzY-lN*8u`E9YAvj{1%1|KbI?O6pdm9wlma~)&vjT|FYy{qDyo;J=+Z!zeNYD zhx2*d^s2tp08|9}1Ha~gmBYWLG<PL-lj5(&bvOg-9hU|P6xkhN2eI<%kN4nE)@y=l&miaHCT1E7$CK)Di??Q3 z0M)b(xDy(=D??&}fr|u<`llNBLHtu<^JtGJS;s>%ztV6#1Swve{p03`po@@;itVkz zhN$dy%bj03laWPL*Zwyv#DQahqeKol(W zm7s8(AgZ_Nr(e9hE?F4+;Kiw|X^ZW-2XEh7+;}#H{TWv*KZKj`MYV|Jsl!ejhIb~l zA1l7Bt0lpV$ZvT$&?5=)jNwWhEe&K~p4leH-APYE9}TnR-LcA(I1{(>>H zj{*#|(n}qXdAi_bw?-0nc;#mqd+~JTR!s->4X2$D-JU?o^i*S8N}(--xzdwHM}x7p zVh|H4SR5ZD6Z|-tMqti`7{kXd+dPj|X+mX>MTY7BMYd6S1kPRHzE}sJjjYO`A>(zY zg@CB1m}y%^DAn%|^f)sj8#n`J^>xm>@j|KmG-d|2^K#XTY9r)_3A<$)_`IP?Obxa_ z+OOhMRVMQnU_i$TeD+rPfte><#;cf*{$m@**QNO%@bC2xi*F99f_O`XC6GL0icp;f&!P`cqENg?6BIWrJ6Z3fXwE(f5yFZw-NFX~6s7x>*AW^}nO;#9+hkbs1JUF$W3Rg`_A(7|Abk+$zEIaH6z zN5%gxv{F#Y!3PX+ATl7Gl^{Jf4HOMT%L(r4x)#LO{JI?DLbD>lD8beCJn%s@?6+g> zWg?Jmr+7j*N?x!=pkN6EDrn`30{^nNfxbMNgqbmudJS%zMRX-R&v&yEN9UR-Jl>EH zx~rWz2K;O{m6#a5E2>OoF55!OWqpb4QzirW96BzF4-s{EbPFK5G=YSmp=Am}2G+Hx z$Z;{8Ge^>~P$OX0IuEK-068n(xetj&7a@xHF197;4$k4+8IG_;hSk7YU)kbC@w1V` z81kz3nrsKhCT-nzTyv*VU0_9=aWNqbSnddEyy>IkQx*!bf$glLm%^JthpuaJ_f~D| z^_4Wvi&!x@+~A2^;%98~6EC}NAs01Ls84>!6=lToLXHrh!%DkPWdAON3pb$FR5|Z+Z%=>z_@J_cpEb>cL}C5M z72BpS9d}O9InvhJtqkhp{A+y3*St1lUbyRu^?i%uUNVx?gURa8Ev{phqv{zx3bbs z(G8=peDrl$D80J#YzC^ zF;$G0l4%pVAL4C$a8)KwPflLqCt?SWLr{HZCqcgUnBD}gClS?m+dTtSfcZxz_qJog z;gpqbfka!=TC?Wc@}RsTn7zGFTAaP@Hs|=8?>8P)d&sst)w3>JG2CTv0jGiR`_OQ2 z@nnmxoHhYaNtM< z?A$;@G03A8ZKbpB2wno;Qoo$<$7X>>JpenzVb=U~kago(f)6DAm5-0$Dqf*l8;}HN zvluv1F<48hUPKjY%&0|v*lt}WN*<)^N>96P==knQ`qC~&m>tOG4J~=%KmYQXmz-cb zQ-H8xjMuuU-;lo6yQs$MzBz|&Fgaetb#VP{{%8t#z}&$XR+TxHYDpC9PDo9^Zq4P6mbq}J4B(D)Mk`Cb-|g~qfm7hmL$r7eF$^8GsQA` zg%|4f*{x+RW9%E>q33!}Pa9LB0a$X&~a8B$CxFS@-`IBb*UtVG=^XgnbA(8nk z0Hf*>9A*qusmNx_!347HA$w%eW*XW<`WJUCl_5m*y?mA|W3^CbgS!>~8FUqRC$ECs zQI$DiIZ=R+@XfU%BV3(SFDQgH?=Y8UC?>91R5XHC;V5`Pb@ zIvIObKOYb`%GOp!kmRYBTT;A0X5mKZ0~25f8oD4)gNtqx6{j(cC~4b2(ZAHDxH7mQlqL>j2r?xuBnI?U z$F*R*LRII)Ou@UfoP9H$b&0sjqu%wMZAYONqT*cXI7w&nvhCgPwKGOw{X-l~R1ug)%e#o>^9axN zr{B&67F_6P6OMJdh3;oLX+4Wrccw@P!O^dioBLjUxp{e<9>T!JfZ920zjwqZCSA8W z#a9t-J!e4waOr0?J)P6{+~Y30hLukn&iu|tw)Q7p#jk~$BTwrd;}bf2MS2)Khw0u6 z*gWOg`fkKbP~hL!Y>H1#W;LNFE(Y_+V69*{oEZ?CDBy@AnlpT&=X$3%cJs#+ zpPoAbHWTrAgu`akE#exlG=Z38X@K*(ZsXeHu3T&+Q5U((VcElL&oJ}^P+)_2v3gB-yxFcgG@pk_)3=ZTEH!q;L5%EP z0C|1yS|wEuJ4LY#(WG2fY*f+e^WDbA48^#=p|_RX5O{S-BPNO2u`*R4hQt5n*W}l9 z&#i~1>%QYM^9qIk7Ife<11}{F&L65qv_wdEqM_I29lYrRXc4$wlKu);6y4D^XJ31@ zagvZpKFpFR;ph7M@0zUCghH<_j^1TseTWxQqa`V+uPxVW!uhVPM4GC>!qa^EY#s>z zZ^aIznEk(;k~HM*`iGre(kqD1AI7`4b!`+*3gV|KbTy|Ea2D-1t(DmNa>t9Rno1^s z%04;ca>_c3D>w^&AU!bh^YUxD-*AZXqg@wXuWG{sF5Z6%mj5XRN|KsSlsW>byPoZ+ zfp>!0l2~QXEXvej?KjV;*+&D{m#Pe?j^gS~G*ncT--AG6gdmH97F&}i^(IVRwVi>1q5JRK!+YBW~)bI*`+qH(Pq=g;{Xzu` zdmoFKsgKRb0bxbs{|spjwYcBsaE$A3BY!(kt3Dk};xWtB?_$@GYg(+={#**OHb`zg%C#S(oed$`uk=lkWqs|AZ|jn&PaM{JP?H;7T?P zXnR_D0RDb$$OY)Zz{~-OduXxfhnU2WJ~gnTHBiaSc}*8jWvr^qqsY!}0%q*?E%&~r zAE5+TAWm02Zks|_(br~%Dx9xc?=JOQcct|wACNg$vpK10&r$XFb&4_pHRl`(hCQQR1p|hr>1sln4?D2*s7{%UEghDtYwsM9POJ2=P^ry9n{yS*}RKVM?fornEHIiq)kgi51hJ|(Bn5V4&@s9_7ff&u}( z=-wnXI!lF4-z3D!hv2a@O&omSN?+)tBjNa6v@j&TYpU-b6{04q{_F9XMy})j%CF^% zDHmCIb^>r^@F#_+hFFvl>ODI&dYbwr#B^@+OAu@rL#fd_R8N&ql$7zs~!L6sCWLbDFB@L99kx2eL9fuj+!GRLxucKb_NDnxw4d;$KybgJ! zED6_FT7AE)H^A)-Q$|-(GNN#ek77E^-3k^-`3rDtEpDG{^CP?Z%Ml~c#DTtuSk{`m3d{XWI%9^_N1OVy_kBY&=}7nz_S^9wLEh_xe8o~5^GPPyjn z9PaNPPu)&TU-Vw)Z+TC@!QnaQa4MbMi=xArTD|VOioV%CzCniV+xtB$jZfKfP;r1g z)oCS{z9jIghWz4O@C0O2@+4s$D1DoGNxB=m0qOy8kmeW zla=j)ShC}lX;=V}32u=YN45N28UJ6tH)Pi?MKfHV#?sQ&w?aF~1gJ(t*k%^S!z3Qd zn0Oq51kYZbW1*<@#Qa~s%R#;$cz0liu3PowTd5%m+;4p1_s2?%H77diom}=95G3GS z2a-qIuHb7YDWV7o0vTdZCv6gnJf0O?OZ+xPkn37-z2ocP1)3bKZADvv(isolC5qd{ zn9a>lBDsvAJLncmiv47ZTt=xN&@sagN~w@>J$&($(2@v^Qo$S)Aux1;gDH06ULiIS z`uCLS%f*`0)}GL1zHO~PT~rpic-4LyRRp_OPbMwrQJ(9aX(=*PW6$^8#>_7f;aD83 ztvw4TghVfKsXhP2+&_=H6aO|p(jC1gLc<1&8e0=tJ05fNGf$c&QOQ@V9E-($t3+aV zeR<=4ehq(Q@2A?*qm`l;eXLa8eoih}i`+fu$Rd}iJ|d%S?;A|6or;%$_R!^~*4yoi z^*@qbXckU8;&K)~H4O0_zIjJYIpy4uPfRp6VFv}@SV3U#Rz=A`=}7>V*UZ0&+pP3j z!)j1rC8&J8F?8(1Fp(#k?SPcZvv+9U>Y7cAm&v&pb*^eD9R>lkW+P)gUzEB2ZVday zm*J8Pd9nEX;;v;h01rbGC|^>u!GqSaH&htjS8pcnojh+s^T+;xgu7LZPO{;G3H^a* z`%lh8Mg_@a`M>Ol9^6NaSgDP!U*))r&HS`@>H`U&vBS+`7L<^h7%tK0$U-;rcK=2S z{|+_f5?$w;H`t*y3acbp&mcKQ}`NAJkkCuK-eF4KPc8ZRy>k4 zk}|9b2-wPNodZKD|E{^qnxLr1zNFCE4Ag8p91OAtaiXZ){0nL_?9bJKKlA%u*1X$O z&C*VkS1~GOf4dxzFS|`FS>r0)y2pu6=6pnjEwAAEL49`A_icRs+p>T_VUM8HFITt) zNCv@yv;%A=2__~V9LZ5dAZB#wUqTAjt-c-i#?c3&aE5+INfnPnkYI^Ub}J9mS7luxgG6CAkR70 zzCO#DrsE~#gmD`qJnX5CX_LGt=yNAnbR6MvGlVgZgynB2z|i|qwc9Z$Tlgh2uHa|@ zvnHUAFmGNF4oi}}#w&ML`cd&Vd-7W+31HE)N8JHBK@*{CzYS|OSxW| zLO%M9s5EjD{$J=k5}s6xOXXj#l6~a-3eT<{_sN*A$Kd+|-8HmAm0g@@`mW?^-6{!< z8H}1XryJLYCw7qU?NWgUYwum|Rou`((0>3T8}6XFI)Xs~PVm{P_jB^66A1L$;fHgH z>Z$6p`7D+kj-toi=DiDA9rH*w9DI6eN|?~Q{BYOKVq@PD>ioIhu?Ja6?5PjM_?Cdr zV+ovPGFUs!habobPxhbRP-6^_hD`WKEX?tP;_U2uTgC-^A7p2-QUm2B#n8P3oU`pG z+qMa|3_-53mlkQB&$dhH`wc$2-ww7Uirw@!&i78rs@-lVH9OK8`f(WH!%9E54Lvmy zz$OCiXbJ6j*EtEb-Kl&fkSbP3?P;O|ghBO>&o6)cko2@3xvM-4VSdv%ZRgaZQbg#( z<(X#HneWE@T@3hQJv_~Z*>^s5xSx7-gL3Szrq~01tW<#7qF8Y**-U))a%W1Kt?sn* z4hFFR5jHjxEmuv>RO2gpmRxUB?%ZKd`yMl0PhE`2Plh0!Rrg-o1wm$%S-)xOxd2Q4 zD+&1kSi!7=v?kVC&su&4Gz%bwJtYQwUwV>jhzli2`@pS-x=PPgM}U7S@Ceqa=~v__ z8vjv0eEH$Y8)f>7s(5HK0_fw+rRX0soK=?-I(g|BQCpPKFS3=!K0d*IF5DGPzbsDRP?qx#@O}2FFq5lA zo$%L3!t@7q!YM~R(YI0Ya^V;pPRR?Oj|K=|{sY9z#QYgcM^{s3XjBBp1Lg<-fK`Th z?lD5QNcxW!iU7qZ(um^EoWfv$GN8RoyFH8+bMjl^GdujHJHd&r{sweKJOQ9h$4jM% zja*dzZ_UiYGUk82=#)`-(MwO)V9v~O#(nsK`tfG;%%AVY2QjOC3D%Uz zuV1S^G;RWaO>T*{oua~eQH+)2J|iOq(b4d25QC2Iz9SI32@@xKZ6;$g!mNlsO4#<-tg|^I!pt)(VB&ouG-d%N^LUy0f@APQ5GHp;4BMqglXtp? zY$irJhJth>weIYj5W`SOy%)CU5n_ilrKK}tqgqqGdjL#ZsfTMB*6fae7hF8r{4!UK z&q_RrF?P503bXt{QqkH6iif`f5zd?yIpOsa^#@7}0=ZHKJc31fk*+<{Y0)pAeY+O;8j#YCA zf9~8?cy!12@&#YnO)5wJq&goC)?XCiW zC8zv*$+m)AvG8ylaSJzCkubkx6nh7#ko=%yNPhc+`gdZtw)TQq2Cs0^^wfl)2vQo` z!yy7PWOV8@*hK~d5T5G@u#JPt<%g?`(%RT5=dpXll;!Oz9b~Jee<41Bt`3GfvNt$@crk=fqSD;IGwX$b1 zY__kZT;=Xp61t9TE5nLDqYKg%YwyP=oy6D|937HD=8D>E^+|L9QY#2p1xT4fs>J)@ z^mP%*ZwqeE9#BFQ9Awd?u5KzrWncyx8T#4s3028Z3{UB4q;?J` zU2j|og034_)u;l&EnL9#PiCL8yU*Ukc>oXf+(+eB)M{`D?#s&4cS+tFdQ<*HyINHoA_g`gIz%p zF)`LV!8NnZyn{i5XE{7dS}m$9ZXT;*a%D+u$0QIX+oB%J_CPbP|1@cN#$xn7TI&y5 zG(2x3DGd{%sQnhn2*YFawLg)xIV-%xTs?S(R#q)ovKq5{I)er%zt2c#q+^+=St?kh zE9Z6e=%a7S{tYYc-(1wu)>M5)rIs&fMd};5Kd0M)kA~oula2@ZDUiys=tlQ)vjgsDEr4Um>)r^jF+x#PP!S>qAK#Mhqd@!^8jgn zlrJ)egz77}7USniQY{Z&VIO*IH3?!Rji@YAFvX*xr!WAS;LDV`P{?7Ala9+|@+M0w;<8h-0jeZ%p7`T5Tl>s-XRPR^C(_J{3|u^;du+<;giX zAP}*PiqVM^`W*feO0u5Y3f#xUNIMwWW=`2;yH~u)K@9Q+wIOKkH76K!i;Kub(_v`v zoKm&>1&a294u@!Gzr?TF_fJlIqCAm`-e>{%!D_<8%WKn7xM2KkXriu8h^1FP4z!!jMme^jDRE&gV8Qm|-EHjbLCtV5V3* z(eJ){m0*2GW!=eT^x6A*3Qon>07L_mythvbk-_fnr5xu$w@X~1&hP;Gf>z)aFt-BWFOtqoQx{Nt z<^_3TiAz1I4;ALyWr93ByLffOj(at*Ex2-1C_Yf&?FamUFu-Ba+9^j4Z{_>weo9zC zG&oS3kBL!9(DA$i(_$@JR|KNO-6@MmQ&AMln*!t@|M{5hvQ#Nfoal|ZV7(gybLF9-vy>yI)%09E-#Wjibbv*3Q^7|R zdH%=UE`nTbnfR#E8T4dk-G2Hd($UwO^lw3=WnvLQ1PdjhtB^a#KLE8bgj5mxVt^uC zAY=jg9rY?wC`fxf|Kk~3!A!Tvq_(iIUmDH09Y7T+0}@9_-9P1z%asxonJE3L!C8Ru z75(Gx)e^3`29AVga+7Mb9|e`adHvd45x{-9!oc)kj2FPk6N&5l#KvliAXItOLGr-a z5T%pf)w%5Pc-vH94B<0TGBx4r3@gU@D#pigTidEgU~WQ6wyVu8F~9}PB24S#>Sz52 zu(6RTihacOlX4}d&`d=!C)qIiemR7*OZ^R#F_=3qaZu#Q&${sKESrt;F<}z^B`PNL z0hS)`n4}1_yNBj^R(0>76LKLW5z6|^*K1_#epa@G%Kp^PE3S8&K%(s|6BE@zPQw1; z<7ECeT$3HFOkRM?4$GYp8`16s2r=q3czw&GpXfdsI19JL6k1bQC&FH&!}<6*$gThK zA3%8_x$#%*rl9K}P0*wvO(;HU?-ld2Ee4%EXitzdbE3IdRZqc*pr8bFo0yn)LRwzS zy!8xc>K`Ct+1F_XIajnQibFpCcI9PuhwwiD=d44h)OaO8D&KQl$NgN7&nDQDjJh#> zQZOJN)=VQ4G3sA=dBGoyvd#T8mzoz4nI{GKbp=9oW?>8!0`i)X{%@x7??;VP)*vdv zEPw*^^6sV#%~}+dxJ|VNT&V{dmYY;2l0LxOBVdtMmP=YqQJ`2ZhM{?k_n}sd#h5oY zZbCxsK-Ap5&8g6Q(ETaFQe+aY*6hxGSvFY%7apAy*mH!q7h8HGWYN=kE;`Bg+_#wf zz;PvHx9nmXKDJ@kCj#^ zm;C4CChJCoFp3&3*$!cz7%ZLxkJE$(CJ&5OND!@9(G41iu!LVmU-(h1@RszNx6qiS z&NJ-c+3)hC&PGzLuO~a|PeAGFaIR`K!S52y^BUhO-#F$~T(RTo%XjH(DjjLm0{g4H zl4>b2zNW+-d||CnEIT$P%ul*~>03osru!uO@}Zm;gh@`Pn@0uHG(L^OOzMHYJTQ); zYyy?ya*lpih>e$u7sJb=NoRDeBI~P(_)K}u$?-mo1d=(6mv0{SUCY&qUzDj5mge*M6I}sQVEsGRcfq z;VywOtU4SZ)A-nu;40%+GJ|7pmuq*nq23xE2b-G=Vdh95zX3y(MzOVS^B(Z-Nyg7P zw{hqZDUUiXSHvJGNjZc%l^2Ty6*Y}t-K_6EF)~wUE%d@II;q1DL~f7TZ53vR=(41j zofgIZ0~jEP!nTn!@GWqLc9dIM*%zNU0l6@q{IL7J0IiJ;@|?uKkvj zgM+rW#UJ4{SA82X>o2}SaSU~6YrR){!|#H{NF~#+$0YU7q>dK+9;NNmwF=B4|nF2mnXI5~vFm5f=ad%owK;maS zQ5MrH%Sg4!#0&d5VdHGF5v>=#y9~988ZJ>nxNCYdKL*^e=H0OO_(jE-*_S78k)aNb zHzV6mjgVQ0i$u zSZ@Zyg&#}N$7!_1I(naH-K==uZZ#T+?G)%?dVU?kwbxQ&hxv+yl5-i&!rZ|5*KDok zEk_?@#@g_!QY5=Z5o6!!-0;=jA1ci6qe9>%#6PG#&Qyr#8H7nQC@0V+KFO}AJLuAQsNt=`R%DuQXyL~|U?2J@F!$}~1DP*cdYc%^ zRos>;0!3G6SiK!oB4dE^59GB1329Xv7&1IsAZ4=+e(ui*R(D~s{Cv7k`byE|*1-zR zEu*#x^6Upp%%M+iURCS|<>8MGkS9oaBCLs@j+RQ+?@Fl{&+m$-;^bmkD-A8`D4pn1pHcFq}fZCJ()of1M>4OJtcZLuw1NvfTgbcW4An&lxU!i&T3nj zCgZ_9)vLCV59D8Ut}(XF@`GK@XRR=EXC0WHF+39!UQ?R@gbb36C{Xkm;z%0HhN7vE zpbI_d(yZ#z#Vnb-2S;{dx{x6_n?gG=sie(Oe2pfan6$bX1P4PB4iwL9j&5EC;3PN; z1(?hJx250KLgYAt)l3F~dnhqAtZ1`F2@^PTj41R7>El&v8Q|8Xr!GK^pXOE_G7qhU zzRTjwHzX)r%I-}*LA614G3p*h@Td3lL(3Vp%OBBI2^>C5Bm1RmQ^K>oNIMA!Ptgd% zr!$#lKz(T;&a+jSuc;&EBpkY7wVVNImc^7kv8a zLIS@t$`9pFR1|&jxk%E9^3WhqZvO;Owldu1Cy<7X*A%{JUA3DmY%`;L>%eLK{8wOU zKD@#`yOwwwAdq=cmt7k$O{mPuvLSf?G%qy+vLr2~E!=TF)*-+Z* zQhahu$*7!JyRaV^+XeGj#Updh!o^>Nmw|T4QY7xA5I9&ykl|I{_dHjb+2cO}aKHW% zDusQ!fgZCo*NMqUt4ZM#j1%7=&nVC6=tzE+VS)1qKm?-|)_EIJ0EfaobL)VK)pu>i zJsf&Q#Nndj^^53dfPH8|f1Yq2z08=!kHc-3D?(#rRC=_4BWFI1MTv?+?&!&+vy4&B z36(lAJ>eY93BVDlYq9+>Y}K_QM)r;QTILgR*u%{E=An#U0kU_N&&q~2IXU5!5rGdg zPmjZWwTrTnq$jM>QSq~Yt4_@2bl0YO`55h9@q;juqCRsReg1Zom*!*v=jsAS zESPvFy+ungdSpIZ6$R%Ur~7kXaycaA{B1I2^qyY;Df6V1IzcE8KD4%XlESp=-)5BS z^Y8Drp}ojN&Gjk9B+_uxzKXvils`Z5eM58k%3S^ z>zDfOx?4#k_>}nVUO;bp7sWkr4a-mtz6tPn3s~`+9UMbdcIoVd9dpH1E?vvIB&T61 zim_u{7bwuGs*FjWId(u%2IsXYf6o^2?I15flZt#FTqX`qR5}jCH)s=&{7-q#FLda$ zrlyvGUwbE~x6#UulbOlMA4_g`sOI}_Xha31KkY{GoAbz6%5KDs+nifAWe0PyxNK1mMlFAHg~7iY2ZR zV$rs=^5I|{zSSbHPHPP1@Ex2A7Dz?rtYVs)oz8eztWukzT47B4i|*I`lk zWTO9TB?7m*aD>GA&BJT-(GZl>NhWPG2EM6-*8NnezhGCch{1E?t91Ge=c3%q!TpfU za=PLNGRls@GYDh)2S8Go;6ljQM%DANr(uMkrK1yg7Pl5jj?e9|(t#>u3EDKlmn+YpkV2 zmGNt!aB#@F|6`&}({A^VRdD=LOIz99of&)H$fLr|&tU~3dGho4LL*%7~JLi$YiMkP*U=8*N8_oQF=_dn6`zD)Re;qsm`DXVGEGG}FlkPFF4 zNQM+gr&au76?%aHr3007^K%6h_4s~Du^ReDNOM!*g|24{s7K#uI4-2WJCnpkZtKdc zD1X!zq6yd+b|P~PJkipT<^HW}Nlwjtb#~DcEc@QF#=7}L-lvm6ot&C<|KjVuBw^%? z*{}w{8@$=Y(Pi@>6MOn98Vz=DmTOrSd#r>xrVEVTfb7Idp! zl|Rds6?%CjPRmQL&F=F_kQ&%_I%|Tm@oTwbaTDJ{K7rmPY5j$4V0HVFcX~yFPK5V5 zCviw;bT{PAy zVPC)T!7B$M({_&2EXs3Um8`h~kRH-h@p&^S z$DlCeX}A%G1eK@8^!}Mp0D~HWR&$3YpFyqOxqZpWFFcG*^W&cHlL-2bu=LZPoFfsu zlBJ#jv_04i@&uBeb;PX844oXh;H$eIzfj*gt+y3~M?T0UrjGUy%X5&o37vx{=aI8Q z34|}L;~2b!nU>b?hZ1Y%J9`|74B}ZZ2{ej_xJ1w+o+8j(nGLIg?yq@N6Z)gFj((@s z+_;w8_(f)=85meMFk9G!n;_mq@Y!&c#~_J<9gn1fJw=u7;w|r8;6DINL??-`(w0${ z8ba;RSnr0^s#tel6e)nhnpkx`Er@kf_q-^uRS#|TSgwpgL`Pb=uViopa*y$!^!~qZ zu0DfMQEqgcbJtwd$=XHXNEqebDy4u-hC3m+>(3|Y&b=kTM%)biV^Y%c*w7KY3)J~5 zzN#2M;jQ8fWaM zEQm2~bx*{2zwX~@jVdvrBOC4?~s4`bumZ1>{Sc-PUIZ%d1>lgEd4M21EE`6P(F$ z{r&^XEg1saDdW-fZMKbS~F+@!DxEf zwyEdTVI6-`%6Po#NznC|U=K1{dOAGLNezl8fhCNFSX@8}p7fUG+uH9HP`W$;Yp0Ib z$xxUWzew-1jW_2k+6BGcs0Rp;z<>F7K}M))bDbb$F|6FG05&d`<||G=+8~gQNrz3z z-j6*vhMQQOsFASAm+r?hVjwYP5IJ%o^)EyE&;5Job|XKp<*YV@6F){)jmAR2+shCW zi9DA#joByHgXL!LJ0XsS7a#!6u_$S{CFHXMKoZtV<*mNJ=hWH@S8&ZOp|WZyIF%sjR{nbA?*A(7=? zlNSk+WSo)h6H4P`Lws*3CzTKD+O;XBru*XQ5 z)YcOs4533|+(g@b%otL#mJy9A{Bo0V`v%g*e@cJiz9ajbp_4_wdG$dwVwLU#k57c|cqsr@O+yp;fHTghT zmVmL5)0h4I4e2XCgN=l^$X-b!Ed#PN4aj1nbMs!IDr=dy<~7@N)oyf>icnq&oHG)S&RBjCCL>pe25%(pj?U~{1QWdH@DwhX7|);KU?L)-qF6?u zAI&oY3>`WefH&u&=21Dr;Sy}UmT{B46C420oHQY?1|{#l?`*ClDGJ7yi_N^Z?b1PG zj^=K{?{&PM*teA};R*nqFap&6F5Vm6bkyIghbrE5ZQImHz_QYBmJJpT%z~CmLi4~* zoOB8}hkM32L|)xQPGWyW$s)5{6h1qU2y^C_6f| ze$R6{&*^Y%ds3|c`YFu$Y(yj&50jV0z>t!xS_Xihwfn3)r{axBSnN_T!=jp6dP4n9 z1{aTM{v}%+52FX!wbJ4fhA$dBLWDP=t|h?jm^7&cV_0*7hmQjBhl!z;`#o_J$owT6wn5(H);!J)lNu?3{`*g zq4xNhWB0>{ExF>6v4FEn^Y;!e381)LU-0t2M> zm){TC;!U2f_ZsRvUk|pFAf(p6Yn!fI2K7D|>CbKJup`DN=Uv+_X>Rhf>O>vLd9)N6 z*-@}roj(Ee%#`Efzx?+4;oDzyr7b*$D#9mxQ)*mpmPIvhxQ=k_%(ez)Ct0*OnF zr~n06TkQR#JV`#SCb0wco&IWL(tLSt~Gaa`Bw*x#ec8+ zLm>5ZNv|vFJ9N40K=c!fv}6fh0D95FCPEUQuqZg~;-qDrPyryj97_YNs5lBwQB+UR zpyW0eKcg4aOh;2dM-VfPQyd&rVp;Ym0!7YTch_vR%R^IgS~&n%ADKbxm`t0Buy?Fr z07DWpLQ|zZcX}^wdU|M@CPo4Z663b^daJtT&|m^MSOg4uQjUI8xcT*%7)p(ruWk-% zIGZf_bkBE=qaZI|-FU_nAehV<&)`^Ej6ylO_-F3;wgt%IH@f)YqV)xbFxk`Ox3d`X zJ}Sd=djZm&n=B_0FN2x5gafR^Br(NQN}#VMR)=j$WE)zE>_B(mTApf5DrP5TQP7_dD=9JD?9R2W4}B&&^l zYYM;l5gQQC-gNfZ6(1`Qz$=_rDp)u?If|H^K9Y8+jGif84zyOF7tQ!AlAq~_Ho2@B z&4>jyB>Q^(z@As&EgpNx#A_A&&XbB2tuv3dOzit}vLUsv+;{J>5GPHKYyOvEErkGd|rAKJ9AJ<*I|Cks2+A%HAdKn`YfR`Abhqd}Kmz z1yjz^k%8$^yK*GDtq;bINlS=T&TFE0^3ExVknllJ&ji6}8#Bc;`11B)a{dRQ0;xRP zJ@3uT=%&z(Pn{k|b>%|*n=db9C(zqUs@p^~lM^FF#>g-a9eH<`nSH0+P@OpcP(G{Y z%*JC=M^a=AI=xxsSKqTw1bjN~Rq&Z{_b;L&5$+;i#1`S)8ejWnN0?}THS`JKZ!S1p zZb-^SF8s8F?>h%zL|?X^TcTl@-^m!h;8|HoQT5Kr-GtK)vfSXHB1Q(u&LhU=l&$7d z5e1ZUPJY5d^VMaZ=9+QXZDW1&R1}vf?;9#T$hLPn@?|Fp=Hi6UILD{A?NAFFM7ZM@ z#h&q7uKuS)E^JPT(5_WqnP(MCU}2L3=6?CH^YCAH28a(b6GFD}=~)x}E^PT`8==(H z41CYrEcTLCHd=`61Clir6gr19VQT9puWRbLUa!jUHM3=Qzft;~U>nCw*&zSh0@seT z7=kw}a;4abb|}|W2(HG;9k;6GJay%1PB5yT<0``!hV#UfgJSE`;t*V~l)p(U{SR0U z;J-AP0lcpEPLj*4jTsU?M$LA=gbL$Zf2_q~$b3yEW3#DkNcI0pT`Ctmx_VlJSNLoB ztWW<^U&D=IaZiSTUjYu3W_NNMhN@yHK7_ zR4>Oeuo|I6pDId*y_LOBJOFcp3^**ZpEq_x-{z?0+E0WKr~cSgxwP*ZXQ?_Kb10 z30$sbN~?0N5hWtLIw*XeM-`Y_r8?ZN*%Wx$KE;`#rm@N!VY`#fxst%Al8I|LTh(Fq z0Rj048K!1>NF^Bokb>p}y&E(XF_amXT@)0Pp4D>*k`7bjihqj;^QkuIax44?$Wg6| zSxYmdVWXlqYbYdBZf-!!f1DjMbPiEn(-^kj2Y7y4zDz1}1ByM{d(U~T2X&RvAAyw* zs}ZK$o#{tXIcQu0Y^OdytEF5OS<(RAp;x>ygRd;YqkrDnerv1Bz`ZtkrWM(2KKhXP zpyq}d(@ja;Q`)2Ug%zx4Y);0q)VnlBi{WU-YEnhyQuY%htVkMO^DZp1m zS~U&=^=hFr!DbPDVJl!pB@#6yQ;I)7!xJXM5@Ik7e$Dj4dCCQg4ipV+Z&eQnTo_GyLs4e5px)*bcpzKlhdbOS+^L@D%RxM^S zQzyBc6tg9a+2aaJcCgVnY_`-5mrfCSVIVhjp|^D82l5W5ZG&9!>!w1M+jhS?VNWVe zBy8P^g_9UJuBidvI(gc9E^+Q0R!JnQm4T@xX*dwNQn!vPo=)5uK&Bfg=VIE*(beR` zi_VPz#C~|9hF$u{36d{t`O9v>K%9B6P@hXH4hBoTq^|QTV*%uzs{f%e-bbn}bbXp` z5kFe zjB8w$>o8&*$pNT{noXP?*IiTAQC(g)Em?vlHjdva@3c4?#&BjpzH~c~7xGP&ecg1Y z@*-3$wD<{%1o#yk{!u1FU_k|U+P`#}J#n=5{K?#E@tiGh#z_vY0F(jUTp;VD1EB zZ+yn?X#K$mlU!1OV$FZA=F^2bmHE68NPF#Zza3_uGq=}^F;NU*r1aE-u|BSI72m0pSVSgV+-9$|bo&A0N%cK+VMtF~13kCpIE7$E>zh~DT%U?`i z;(8q%+H}v?iJ#Ws?tO}F7ZKTaz^06M&m!l$rw!>Wn zD6*9e-yg)65ovKx@keQe8bFgx=S_fCbP7fZU7Be*%j?#%{{Ss5iM{fIH+5$VV>-D` zE<*QwXUnj+pW_&o<^(Kl&T-7g=2A-d%5kNiql7c$42E2czC)%T2 zMb;&l(=lp_bul6)1f@yY{FY3+OK-wn+KRt9zNS0DmZugVCYu$#HO;^c@ZWL%fuuQ3Th&J8?0I!1)-o!@=MpefQ`wkb%mhqc0-tKdCuszb=;b z_`QxCdCCRMN>pr&n778WK#t9z#GE}RKvu7C zJYUD9(Cv8tg;l_9N}41gLin$2^C(*V@G;a-=N_8$O|zvoeKO*uWAw}TxIaVOaEo~k z;a1UfPwR6T!v6JO;b}mMzLhj%25Vrm@W(=AOy)Psc1_hINw zrOHtqD*`^R1=^bs#A}x<3BLX%=bm_cy~+8r&6kStdDQGJ&KI=(+{0*9b1Am@8%5Hq z{*d^NMBm0!BhqZd$SYn|GMizWMOmvwq8hck`Qtm?)OCSxe_o~8p~4NO&Ka0zgJqk% ziDcqz8Rta+grnmDh$Ras3HRS~)Ru!D=dIT%!Mc~GGx{BxHdGUgo*=Usntk|_p}z#s zB*SD5E=U0w7{yi{j6Uy~xhWdPiYKQ1)Dyq_G;c}3Yp8sXIXUX<(~rBGHo`)e#p3-F z@kN&++xdYFolD965m)cdKL?$hnIfN6mn;zcpzy`k7Dl>KrRb<6=hL+Siy7J2i{^D< zqI3DHQZKE^txAFuMI$z*i08OYaqMqO@0UCN%D$2*qHMfJQ>eq~BpiMa*u48=6Q@A( zJ^deGYxD9>DPwf>zW<#ggUiK_dN#VJeAIYZDZ)&OP{5xkDjRjU9uFB9Le*cdUn{A8 z$>{h8f8?kZqtQV6_#C1kV>w4s7^(b!G`(e1)NR|oJ#=^X0K?EdbeD8@cO#8}BHi6B zCEXGd(hQvf5{kqiB{_tIfd9Gf=Y8kfe3`XitzVqSvG3cKL_gDgVWy_r}LmHh*5K(ESwY%*eio{oIq5RyX6U>K;Dtd3rN z4C6Kner1gwiYq!A*D+}9ODjX6@Ro(5L79-g)L3H8){UYd#;p^~!a<$;uY z`vq_2qnjS4Po#aBLH9ur(^@mR;O2MrzuAEhWQbx`4$WN##FkHlZ(wgAXO_km? z1pAl!V2{_<)+++N!Z{JZ3^4GZJ;*kk$+agvtgD`uljDVD%$sJ~;?%-M!|0rX9{r^Y zXN$o@bezCZf&|)*b~ZdRb$Qs8pT4-nhhypsTr|J4u3(LLp>!F*4bt4*j(H>}%u?N< z$K4$unbPE{uwEJY+EH9By9ZNcLs();QJ!B(Lj5$85+Gx${67b%GCUO+b7pMAS8aCr ztC~o8_Gu@EdNs~%!^G)Y_8wA~-y|i%lLKLPc8Bd7#h%W+R($iEgY1Y4ySvSdImHZwm zx$X|8N&^HAPXv3nJqcnEvwpbWArWLwCsGY(CyP@~YcCy=c{4kE7*ykNUEt|8{Zx!k zmyi(4w(1wAb1IS{*#ZsZ97}4It3wvQm~|9L@LodP##qQ~!lidubj|ARn|C6eknmgc z*TQyq5vZ126H0Ty>RTm@Ggqs8+sWqN*xlIr$A&<$?f2pl9Z5^huZ@|lcFge56b7~w zw@yCAJxgzKJ3_Vu?jtVs#R`a>gyuw|pR{(LdO)g4(nZp|*l>$=CfDe8?KmD*tb!iC z7gyFodp=@-1k&a2DkNM~h%WMw2EQzOoZ8|Rzzlk8vC#LWe#FUm3h-6q`I zdqRfY9Y0=wpWwgnCR~4m!RZdCm{9nxXSy$trHWZkNXd@*>UX{4xkbrvri$x+QHDuE zTJa;V2~(^`z@z(L9vwm;<`4jjk&bB0sA(mGEm0Q2nM|yS!TzSJE1S(3NkL$xb1eWF z_VIN%0vt+ex*n}9AHh)(U8gH+>>|terY#dUr8#<5O_TzngOYAQSV;=JRn*5Mt2)xb z1bFmIUS$GGvN%#ED;Swy*oq9YnOU0l1-=i9W?u5r7215rYa8uEY&pnmghu{=Nk5A zc<;i+;oJDy2)3J2fxFqPa}y0d8<5vvUnk+o~s<^A510*&BzPr_5>L6)dz zd}%_z;@#M%usO*y$Jti=-t|{t+{GZ0- zgl=*O$r5kHetPuL(#-69hrjRcc}VJ}T+2*T&4~CWP z`N#|N=cZ#886S1=ltvG&O*AQgDF>41k?JDmPE`f7TT$No2jL#hUtO?{(B^;WVrjRU zS^e2QC1)d6q+U~33OOKG(B_ZSIKEhRoRFy7XW>;7)KzQGmYvn`g^bEp79-T6?JGdmdyf_2BelU*+&Q2ck6Wj!6QU+Hh3+k-lDQU{0#|2rEKUoK2 zMf@0;hrKC^bd1=0V$biMrF`vfSzwZqxsrkFg>X6-fv2BkPGJepT!~n8o4Z8{!b~^8FYj)Ij(a@Ty8PJ<5hIX zO?p44lQ%!YZEW#bf-Wv8CLYlun&WF;h$u3-J_CcP_ z%c)^8piKGim=c-tv>{>Lpg&oCEbt>5p`wx!ox<{+)JUjG=YLKgraDtnxCE1amGq)K zQn?C82Chocs`OEYuJYrVmvze$W|@{?Q5P%-&1(vY zHAg29mQMINZTQD#CG*GU!$FubVIabJUZkXC&jUhM?yX4J_f4)rur8$|k(N+57plIREP;sZiG4uT zcCyHoi?0+T;55f{xIZewqllU?23d9{9+yMB?Sp7`Ul|WE;0vYQ3~<~p)Ex2&C7&x( zy9(jsUan|LD_ed0Rf_rYSzR9{Rs-EV!=X&zcO-Ea&ov5>oX?1Z1eNv;tlD0B()x-8 z&U*>3A)AGA2}cnv7wdtS%h3XrFQYa~Sc9ZmhtDv`W+=RQuu|d@;O#{Of(5{y906vY zU`wDrX-DVKr(OT2ECLMPSiV+=Tnz|7odeXShFW2&pA85n1Rxn8#~S<|0CToewu}Yy zyero9bk`L(3r*T$#oxWB;`(gOndk1^+RC>+9vhF;CBY|wv8^JMm@AR$LhW3eR~g@4R!l4}jx!+#e|^MS3q5Hka^Jgj9{ zfQra7Mhs)i*2xm@Xkc@6$Kw>DsYWg9o4tN{TbXJjM1K83o`fpvi0$$_hA_;x90{O* z&5&a^oS%61J1vks!m3h#yWb#Nys#=KDY7!m_nVFcno>NI8*5dr!W8onn%X|*Z~dwF zm6{>_e^=jwih;(iW|pL~*@Uxwowu`g_+l zyVMYErdyEFv_aU-xTYz1Sr~Qf+Yp?BXE*Wwz0`>)G<|_rB!HHnMiW47e>$;tSi!Nz|ErXh0FVM)R-g(f6eIV z$Sj-!uuwX*2HEVZoO#?hJtR0WeXV98$>bzvMZaLD(YC88S@QNgFoC}yd4XUIO1pmM zIzs3D9Tozja4jPtl5UZKVXgO#yR#2VnCA|^0b}5YN|Of?n&t<$$HihX{CsKPGXp*W zd%o45wSlp&fo4X@la3hAKdeS1@K;*_OG>QzeplBUZ_BgzNw<{0>T*@mL>f+~ahKHp zuK%Q(YD$PZS$@}B_uTeCh$Ww>`G@;wHVP>c1A&P|$f|nTFzNQa0U*>-x{C9xZb@+R zH}UV325o9OLj+PBPpIbNk4}17t#|pddqw!J~5NjHJ&qCER!)dmKpNW*>K=U zNhR4=rW(f%oja%*Ml8L>8X3y>LfpBBuS7SB13Obj?c=@p@crWXzB1>}p4zC!qf5s9 zoUjR63!Mt=(g;KB_loUPpj(V^p1}A3EXT1@3LK4LsK9>52Mm@3QOY>2-DesU=89iV`HdSE zC8QGv2FEq7-Je;hVEGSS-6bLNve*1(P^(23A?w9b|Nii)z<~8;vLS&WxzeTmdiDK)Q9ONYhUj3K*JR3mx6Mbl9LK*fY2R1 z=Q0dN#10@h&1YwIZR)A2dSlE#PmSaPW-ihWJ*k){0gN3K=2r&k?_bB zSLkW`{PdqBuAz$?xO(ek7HUsb*;cEHl*+)f(UZ#`ciwS{QrJUQtW52c?e1PX(Z_<> zr(!32Lh$f*-t_N9lKP9foD$Qkd;J-H1yFriD+pU4Tt)pWDc@NGKa#r^?B(M8WHFah zhLeOS?ynVG3MKJYk5Fy8ijE*HQ6H>t9d3zbk>{tked}oKp{DpB&-NL)_}(h0gI$Lg{dV z*sJyKAzNFx2$uc+jTZCBjIAag27kTF+me+0F-qTpL4~;Ll7KASf{?h)ZR-1LS`o69 zF}ydJ;Q3M1UQSh4(6QX%x6+BOKrJdyqVG>7CP-P(@zDi)VSs3G#W~Evmp{S{Xb!ziITQ|1COT zn8q~$!yTQm?QFsGdD?Wcp}>y16d@@N2VD&%HD9+)qxSWcd5Toz^5}^3s>h$r0QON- zVvc?o(^IWI3TiJb&pQo} z8rc?oxV`sD_?Zt_XDWEzSA1TPn^R^gBFb#uUc$s&U~OPXP4 zGF>qg!iH53jpWLF(068NWqC;Nlee3f2Bo%tqrq0~$6Hbc<5Pv8W1=$@>A^wMbxW^0dr&Y#aF83L8mGDJs z_HF>m-`Ox(>lplL+ds~|sVI@BNHO`)p*KAC&l4n6+r?KZb$R_0^QZud)ex$wY<6}w z1LWEof8a*#3jaNDon=&8HNGa^GTl$%mvBUz_H-yr%H317I)_}Z9!r)sb1byzrqWj@ z+yd-Ca#L~ttJe&Iw#2^wLNULM9Y%yGTaBbaG2*twT!O?tsB@0=rt;_~cHrXbf?0{Y zjoM>)loKE!M8Z7yqz}6}g__!Gc|tOe!2!v!$|R(|s{9NMr-8JR1WAt9sPwY;LHTIS zgibDODw*O56_*QPmg_r#RqOQZL*G}E&%sEc<|NrY_d(q}Pp2ZnO(hnu_;Rly61jL- zmd}y|@P^S+hCZ>~7Lq3cn59f&ka{BIiS|!Xt-~kp!(T<&wg`S; zxgTqsS})s!aSzai^@ZZ%(xM=rHhCz4Y#EcC`B_Y$+wqCUA{bBM46&DNyE=02-`6_l7*DM%3aNG72PF_g_DM&CxW=Dor#DKyZ$;2xtKuB05B-V~-vW>U# zH<~M;ajdcU8_T zbKV!>eL^uK?blxw~uXO%s@tuTHdd+Cf_1f-I_<*pO@ zqX6bHx%(yG5%Ge**fW}+5`nSHr!jKJevfzhiWTkjjdRCCG1I1&I6QIaAly7Ad@m*j zAC*Gr{xxN!M%pYl(0~^|Q!O0XpzTA~>6EfW+e9oo=tAMl_ zp02m7yp9CJQ-rr8m%+4Ln<=EJTJpJ+Oq&mYo#iX}yl~!ipzcxhj<|@RbLnKaIUuU3Cjp~Pf1=aez zJ+ZA6))l5@D&0=64$8y=L8iHWwBldfn;@Zew2a9(f=Y}M6Cbo!y}pwAWA3Cn_)^yA zvBf5%S}A^GCOGCLX?;K-};0A$#vylttYJiBOg(yWyt z9S~=wspW$XM;%Ov-!0bLTR^$)A{HOghgu=ByDRzMxe;KzH^7iSM_Cs6D$4W-qIk`3 z2-2!Cf4DM)TB}v#nTsjptubG)qZ_tvMxEW6P7MZb-LgNYTm6J68!Oee#2DD`Zr#Gz1*ixr7LRPJ(iArl)>_DQcMfQtO$_qCwVx(yq81K<$v#{``@V(82|q7 zKL8zKab6o)Q?@~tlON5I=qjtyl6h-c%zd&Qny$F*ewzAOt^QdP6*1>fBtqt{X-hyN zWcvP&t;G3w(2M7%6?r%sC&FcEnt}G6rtnxX9Js>5hE;Ht-<%kFck}u)%|j!A=^&)s zm0dBk%Ru_WqmmLynQv9ppt8XgV~S0Z4#Hn(Cl>D=7(>MDlCCo!EB+H$ugK4YP|8)L zIsB0ct1+o9wZUnq?|+BAe5#bmgG|Oc`z5_m`wqal$R#Hpf9$U_-8bruf&plT>YnQ+ zRpRPo(YE(HWhfOu?n4w4*-+YIuuaV0Lx%@Da&WNchu*#{)=ADGvpIdfhL^rOa4?{W zg9OKeNaggGa#(;WQNn*nBao`Q5|#S6ubUfeda)w>8HJIf1-=R!@Gyl4aEk{cBo094 zVDu4g3InoF018Yb`M;t+vGgjYsLc$O^XqwiO9CDzC`UIJ@~#pIJ*KTp(tr2&cwJn3RKAa^PC`fIxCSe0_EU*&chEuUvF&hu;Cw(o; z6xlIYuOx?nR+BesJTn4o2>~0x`YA>-@{toWj3!F<-+)N&|H!pEv+2k3A(V zs>QMI_2mgm7L_TY4dT-lA_q0ar(g3$_YjK^70->RbL+v~qMf*@nQ^KinSm7Vyv(#d zB!|$;WQ3w<%N#6XN7?E!Uns3!K*!Z%;q)gG3K7s5s=Sw+r}eai*R;VAGS&DWp)rpn zHtfU0f*i%PVo4bJlcdN*=aWZ9pEk!K5_rx2Sx74gq8jJJ{dn3O6nXdp`4$O^GoO?b z{>jFzL#Us)mW_DGm?DG+?_TM|MOsGO-vS7sBxRjwx$0yCGXBlF<*-K_E$1^`gS%$F zxmt%l532lEXrAnQ9i}_@8*kJaMVjGgc^{%0G&fv${m#jDtWFvT3_`tTO!Pr!y-8$2QF|Z_0vVn=qDG z05Htwhzm8LNs(9j4r4Qr^dhfAYjOuB!8szpJMs^Z?^HM+h`1KuxRPS`a{I)G^qx8g zsq(byZ>^t{Le%be;pXG{#jbl{w9efhC345-=m_M7Nsc!eMm8ijWa_eZOK3--&}r8_ z63ktjg8*9B_P49$U~;OJPL0ha702HbE?R}5CX(z;9@13jFnjc^t5PzGRdTF<>p<#`Bkq-2CAz=cV`(iG62qyD zwL?2{p7UZXRFii90g_5c?&D&_MkR@0X>rB+kevdok;R}duU7mR1ZJjLXKd}K;uWW6 z__NCZ3!hQQ?!@1VOti$KPdXnymAjEMu=NK8+f zgpBvc9UGyU)H+!-+Eezbd>6r(kE{04J&s^(C^hC0v5aiO*uJ$@D zErz}g3Yva-eIJESA1D;NqtFV6Bk;O7{PfGxw(rt&O%;fVYYh!PeUFYoIn9_}Qcx%c z{$^5LR6V|E83tgZ&CsCB3g;NK{Nmqy|MGKJRboju0FfQ6#Tktn8IZo0gRPpQ+U`rL z?BH2P3(=Z7xONTzzP&2XgpQYHtN2`-DU;dR>}K&pMa69yenbJKf-kaSAu`+_+})Gc zgw7-MrNmD_A~Ct&6)MsdW46XK zzH4kll^m|+D6Ur#GB%X(oU0+31KjKVSQ~8&$;17gLn6MAQE`we*Rc{>PLXjwBlO?H zQ+Ct%tCyMA^BpOn?uT!)i7<%k>;QwZk)UkJe}ithHafN|SP z#HBCY&@t<;3elcJMl5Kn)itMJ&Vpjerc=lo2;nT3hK6eT)eK|NzEWCT>1;c1F7#bA zx-Cp<{%E!P!dyFtV&hL(tUcU{J8Q}Y0<&{!H=zmmEKl z5Y(vmo&hzs3y<&m1V&bF7vc$M+6zpRzdLEigm5nk>Nk$!P!MX56`M!JK!$20yElQ_ z?75z%fP6-|gRMhRm(h`VXIjXp6BYL$A1Ga=&^MxA<>%Y){{Zm}uJgQPrx(tApMs0x z5{f4#+^vZoY*XwlhC{vPd5D3&dacUNOL1kW*Vy%igkMrpObQG`&imaWu+a)E$h8eQ zf3Kif)B?s;1-|wzq$|k+3FX({$PUi*xb>t0x{)Pu|6VFRDaXHEHI5AuN$8Fe5gnaA zDnxH@aDw9`OAZv(I0*)ICo|mq8p-b;LRB7Ju%pE-vHdmaiO;-4`OM{$c%fdMd$KWmLFml->~TT(ySHSpc&sRYA)#=! z6L-8Szr@aBPFmP4xLS~m%h3JnfMB8Mle&QBKY$2v*9*+^?Yo#~*1O=*%Wi82QDGAZ z|3~J$bTrVeZ4pxN_S@h6Z>SSc>Ocs_zg`)VW(4N1iIs%LAKIZ$jf3Vwx$#M3{g5;~ zV;O$TW1aXL$DhwA=LDQ?G?$ASRDa+7^s$2g=*R-*;o`0g0l1Mij`>(sz-SI?@BM^V zi1*)Ud7zRiPi+E!f72hsk9oI-t#TeNUY1^te*$;C_5>&X0iry)Ctw8V-C6jS1je&A zFdyZ(5CyQ8?v52(5$^8pT;Z(ix@j@(YX)HR`)-_qbL|mV zLWRn&R99dK@4={#d+_%oK%n_O!TszmL&^eL+W`3TyeNOSDNJnz9^{_ZEhtie7|iAG zTCq<%w)GUxYh&o-Vem%P9S6@=`?1#^iHWq{tABQ8l>O7 z4{ju+zE9Q=D>3%O4b9{hBBEBkN!ex%DAw*xU3CgV4=T1GJd|K9?ZH?z4jG6-z843a zorw!|y?AFTuOM3`UGjX?A$;{wBrm6!k4QBVJ@&oSKR}9qKiD6pnmxAwJP_FbbdYI) zagc`}T=jVe>1sAUUcCg@nPGa2-zlHsW!cSBTEF68x*9+M{JxT`Q4Qy+tS8FzbOH3pCRD z2WZ7f2VklL2shqkD>D1PV#y@@uBRDXuXrX-Hf2f%r)i?W;b#A2eh$qd&G=~FnArg| zNGLMm4j7G>XWo$2?`b_X$)t|?s7YuRSgKTwr*e6V<`C}s$~~ve;I`~j!#G1C=B2c< zw%UEO_*6^yhO{0nSy=@@JqZ=*s}6}8;UVM}(o)gLr?}SCk1^#tNhGTiZ;``=Vwyoc zWJoU1CKn-uN)>=H=;&tn3R|v?{!hC{E};o+U#mvAm+t%iz?Dk5*Z%(f{+tFTNx-~Sqj#AuQ-Y3NfMq1#5 zcZ+o;mv$C}o2rV3rtO`=^fXdGMb-S4EN#dhEtE0d;E_rhx^K1?j14xSr~Z>A&u}^X zi3zLbs*iI!?@bT>)nB}^AZahWX6PHsi=i-}Xuj7dL*Z!b5lF1r9kUxBkiP#&5Tp&$ z#=ZZtJBS`sF#J80zGhU?Yt&4c*d_RsnZpTkX3vn7$UUIq@ATQ3BsWB(*`DZd%Tde3R2g(@}D!?C< z`Q$Ir7cNYJ+k;-AuVs}G6O~91sbG0(m&*Uz8_}v5h-Gm-7QZQ37Lf#qtTFLEWeK~I z=#{&NWbfY8RaDKQFLTs_HcOLs);)RQP0x|P+w-w2nYX8(YC z)5eARP|L!jgMlX7CQf)h8ibYj)BYw3j2;QU-h$uM#{e)re^aT*_RAv$=pla>O$Qmv zW8R(Cf?`*zZGJP)w|~>oLDoTG*QGOs*-21^L@!gReGs-MifG7$qO|fZ&Hkz zs}G9U0cT1ST!cU$(kN~Tjfa>Hy*it;9^;Mm*7ImWW;KLhoQYk}B9F7nK~eS$6@-&R zm(NjmgcIBv*lr3+Oz3=meq-pix8iB~Tl{O9Sv(@6!DgrqK%2jlYo##%P=ZyN@@uJx z>Eor0l=hb*T|V&RU(AM^malp9gDUla|8g*LnCQE}dcM0mX+u6GQsMEGCxhqLs7C)u zS>jwHU#oV0T@mr?Q2X!7l~-XxO$+0dsJr&SXn%TdrfOZ|{dbCPbpB*}zV$`QuQSLQGwO)?vV?MdrW1frTi>^8kr_FjY_V3y zj-2GN_UDn!h32#5bfYV=_;QmJR}X*$g#%f=)}13Ibzj}16*UQgs`5~`nZIrKr@lL6U5kLh1sRjYnIOA1#E`}g9h4$l11KR~6|Wv?>C`=gck8A4>XnxCcb zLvc-iV@+9_m~wrrU3zKEXQd+yc#Qa)*nI@gxsnS<5@Oz-!lH}QM{@_aL5>IKP=_Ar zKQwM}^6~NITOCRb0jROS7P4D~KPK7;Zr;5V^%<7JJPGc*;mfZk79pVwQ1P`W3!*y5 zdHTAh!*)}#R$nW|lZOyb(<^FEW9|aztao!>{&1E=!JK9ujMmk++l1PqXJ9n&^?Kg^ zC%&Kw!clJT`&N_VEauxA|cLg25iQMqJF6erZwhT!ZVI{1%Z2+yrgE9lYxfycu zS7iH|mnq?61TYdYBmQnACZtGlf8?A?xz!|vnaM|Uhpb`sSuPDLwSHe0v8%VDY#T}#eMxjvl_WPR44>@R?I+hAZg2-;+|Jn}C6M0-0`@yzr@ zjaVpaWA#B`vnz4VnUVf^OpYr9~_T^~HMXIo50!*0_N(1k)1wdBd!4cRSYV z`i-wuf8dhazWJE8D^w;zkOU|1tcdvdIO_tyLzPX`61-*4)^b4?wl&qp@blJi?-)FBHQsFq4!AovCHfSjGaePm{7U*|;I0#jE@tH$3G2 zF!J6pzwFHUeSAvQySX!bYl5UVfg*W8v7Y1-X5h&}?5@P-Uy*0Ts-*@a*`!45iSix| zhVCUK>}51}iJnvLgD%ZA9-`Wv7xhb$9f8ISPM)~+5o)55O4K+ku@%k7raTXG5RD3o zLz{F0`AJ~%4^aWzcK}mh8{`lVw!xy8=f529n752w?&VzFz1#2ePg(l<&gRm7W4T0J zcHXDj2!zR@w==v2fu^%Ktfol;J2S)ZGFGe|kTJ;z!t>WfS zpbNM8@XC9+OLo{ixw_CxQM{za@Nx+2B1;yjEy8y=LDgR4K7ni_HmJ`#(&mHiNhln5 z^^yo%cIKfif+Q;ooq?#HdI%MplSO51ZB@DI*s}64sX}#USb@ahWF~0-^-Rh->U3#^ zJTHfKBovvJf}IZe&*fnX-HeEBfbDLH&gN$$E(|s&GIkWX+td#`G8GK5?LmQ;%tO?x zUc8UgHHl_x z9BF0o#}3{#Vj*o-cxcEanu)g@{(uL3NB7yfyT99q6>D&1wfdgk_Y}+`2)RQ0kwam% z)LKPRqbu3NhOB|CTC`bMU;{g^wZZAxduD%9$Z?kprwwdtBO@KR*-P(si9~;cCl}PnMLT z+vAOg*m2iCoeBsPKu+Uxb+7iXV2;QJl9`MEE1N{9@R9vT)9bm?ad4#_Ob+hXCv`el z#WS;;_CSE`Am^kGkn4Izl%%!Va6|GMnB17lB*Jww#QXBra$hBhg_Y)yC*73JOY~iI(dt^Xzo3$j+j8YpeWwTV0X)wN7+8e~_-b)z(OOh`7J(=%nQ~usK=Ypfe+=L9+ z%d`XqK*gKwLhcBC(9M}6z+h+HouB3s($aM$MeLyaCy~P0L!WC(y`#*T{K?>`i~u*_2n;l$l^ae}3zbpLn|CC{I(dxa-0@8R^RHw2vz)%(}M-kZ3oUR3kH z<^?oa#%YqrudX}i^Ikry9Jotj?tgNe$R>2uK^<{*%JmSd$`5IubQDb3&#!seDRfm! z#{x?dB}G5cD%;vYI_HE?l^5)#&-=^v+o?SMpp!d;{@B~t3l`zsd*P#!M{;0&-m;`< zEKmWi6zCKdvKg6W{{y_n5tmc(H*=UfC`o$ldN14b3rW8vFT05t5e#pL(m7G&^=Ga- z5mNywJ^urI$c<8ER?U~jS)LD$p0qAHwKO#_6GPD+g(TD@t`p5bmeewJ zMJ+SpsimfLzRAO^Yrdfler!r0QlI^CY<~asEh4n|3t$M&bydr_Rx|LU(z?Zuz?kDy z=7r*DZf=0fh=ff-X?!sDb7yF2*HG+enK=8Jziux|!172;ceO zccb&@)rdDra-Pt*6%zQ9gE5fVfkuAha&5=~D1&fa{ZZ#(rr`h$crkfj-! zxAUg_)Z!;UAQRYq_>Pw;&H4AvrlS#e43(}n;K7ub>pzbXyFU6_Mi_SE(=;1O!-s-& zs~PorSwzpN)of2s2L3_vZT(*YJ+nVV#!Rg`05(z(282S*e6YZ|Ud|8+75i&_MY+LX z!L^bK)5jhW^1n#8k+Txd+t29@U28v{pYA~a`;u;k=m^+gAY=SVX#NLy_wlAC@KI#D zk~}=22|@!R(|z?aq1Dh{t1d@sN8S?lYW<5&(KnmKF12UlPOn>oAf`btR|NA^F`Owk z|GIZ7zdWlSeUOv+r3b zZ^OwRRDO)%^qFpKzQju`%xZymN_}-Q+Yw)=^15o99RliAj3w34$+CPS6cDS-hwQGb00qK8JO-}BB(U#pq}h-nH4Aoz-TQ-Mteu~^)PH8;-grjRYf)Z`j!d7 zUdX|*QT{-uN%7SPv$K6L>+kXZO$`uXm^N9ALi^BOg0Sfq?d1Cg<((1=7!NlL_Z2d=WCLqmwBl-)58?HZ;u*pF}aGrF)aXAj>c z!XOcd=PIqsu>ZaVeK+XIKGFMyA;%Uv>ns>V6#`CZfcuz?&m!CS`KffNx6GfwWX7AE zVfqs?Bz^v?a37~xpF1+=PHs;2$emrG?&RrD z>&0cOu(rP{S(DeN58BN7oFLy*3{Q``9n!~yob8y zwe|HtZBX;?XNEieG8>}4w@lpf9%nD1TRucel2H8uavMweJT^Hb6frJE`7K)#3@rpN zV;tIwm0tm%Z$<)S85UUSL@$0*8(+6kC66cR#|tPk31jz@^}w^)(lFkh@X{O`e^feQF^MmSNiq5==9B%Y1-&J*~<9H1B@UM-;z$RG~MD09hfd#P5sgR zRFfa1J;6i7z^Q*`a%mKc)&hPZHA6$bMx}*zin%o&)Tg2tek5y>d^n)fweOt=94EboMy{X1#MrDGWl-C3KBZ`h|9MxNX~-R-+3eSCaqq!=WwOitZcH`s z)nd9AvuwY^i_p7A*mLO{2AjW9MWOoqg`?w=>ip5LO$%Bqq!e31vnN+Sg<+Ny`^mVg zp8meJ9t*A#a&mHf+U}qrJ@q)Ykz7-UTvbP8Q}16nsF6Cvx@?&A5zL?Rah+&n5e*!| z)geLvzy(#drsozR1svp$f3k3vAiD4?Iqc4a9TKa8W{On>)Du80#$3}Fe0FN=g1T}7 zS^QRc*p>jIX(m(jFhh?4>Dw2h{fdHYb#r7xLlk~Rh$9(jt)q9GV7aAgAcqr}sS)30 zZ61=x$R=z?$|mtiTl%Z1WMpT@!`UAaZ1HH6#{d+c-Ktmh$ey0L3NLS|Q?g&>MpLJR zu2=yO>4{m_r6;j_?!0kmuB9=>1a9^NmXUsv&* zkT_2Pl{zm5dt2bU9P&bO(K})nEbAJT(}Mp2kVUCxJ+Io+hVaFV_7VB(m2_M`E#7@i z;X~%7+uxde7REs2Qudb}#fGa)%8)XWK*s3_!y#hzYFbs|*T1ChTLLv*J!zPRf|TM~ zDkec+$m}!rIZu^-VvpB*vrT1D+?Nc__`sQwzx1;fkm4>U@2{nutwKDthTjISt8aFst zL`4(FH!Fc6dIvgt`vp}d4{knkVirO$4_M^zX6N=e>yC4lVljKRjaFmkJX?f77j6WGN6P{{cFKYT6Cm!a|On zxgMHMxTf-;l?9a2px{tO(p#wh$}Ug=RW8kAN>0i>yiLt^qV)D#Zv>9hbC&tz`=@jy z{FQ&n5ETw6R&Ia5b?TG3ZZqNWDbxbv2sN&h`dcDG568dY+9W2I#^W+*?HdW7_@6}f zPFu*1DJk2zx+NuGJPNnt^w#)}0=84ow**9cFyG2Hm@^W#6WDVuP!k&K7Yo~WK*{l= zMUo+vj?F2H*ac4C4Buaz20rC=nbI%Xei|BL6>@ z-ukcU_x<1B#^@Z~3>YCj8bKH(AuSEkDM(5q-7VeS(jg&8jSlG&kQyQak`e;X?_Qtx z_Yc^9*zLMK_PFln{XCA}&03`812JII(8U*p#d<0M5Jn647$G7u>?6_IL&-PIsUk7P zc%hhIlAkjPK$eiSr;ZgRIM1msx=W1w8+X559XDIhRO|-UmD$9y+l{xo9+!EW_vktO z58jkB9pb4`-X1Efr5>K?ZWVFD`1SF3mNY#bsrsis175Gu4U)8B^MA>dXlyNA>a>~w z8fi{;+lZ7fvNM%vH7s`Pz}dA{Wru#_iH`RJ{}r6(8CFgP-3%c8XwoMzzzGIY7$WY# z;y65yv4ZjS55;IX;7SX6EKKjy=G&<_ihJiw(B)|%cCo&DBQgR@i<4db{I+}9V!zez zc-cg4VLy*dYq3@01&8|N1a2Ok&SLYKpaf4(%cO9nvzqC$aH=YsO2Pt|iHix#tx}Rn zCNv6Lz?+pv=9CeOs$F{H=l3DWXTzTSz7_-H)+xJ)FadLuM61+3<)Y|DA`dgNTcMq- zs4iT#p@}noz*!dFwnqqf-oc+yo_QujRic@_UpzY^`7~c$FeB;MEiik+ZKDBSiJyXn;fg-ODHP*_WT-u!PncRy!tem4xq-1=8Msf)GXbg7N(rd$q7Y2 z9O5QQkG{6QZI=#LZ6ko)n!Fh6>Zdu5TP!pZZA?rXNQ4XoB>Qzi&>9=?%F3msaZ?nl}f6eD83h z*b7oiOh20zcT(#>>>Uwono~GjvSjalBxRPZLELvqiBL~SV{0A%FPT<^WT@Mo(0_ok ze(06Bnv7=At4342Sm*v1vuw$lvOk%q(Q-=oTjPwo>kD(M>UCWC?`ZiE9r=90AZXV8X1ou7eY~(zJqxTv*tQT?^RfvGWuaVJTOfm5Mcq!f-5x*vsS+=zvuMJl(XuP;q~duE7Bk_01-G_6o>t7qXHDPudHRz!e2ngb zAB56*l4DoXu(hdZAx}I8B|kriVm8u9txeFME;RiiCb21;<*Sc=RG#@% zK+Ei%e8Cu#$&ys}NV-F)JoG9ur%Lfo_H%3mFRHuKp0<@`n5g)p9?-Braaj_?^2_2atNVOlY zFB+P(z5liqZF?r}Ey{$xUc+?$3by4-L#JV*e`7K;3?+#))=9J#FcVa_T-SYcE+-peFC z1L*Ja;)UsZcf&D95sXD1Y~_@-_2%i{$`{558t4;}1H)P(7kPOg^77?-eY!Vo3$=^l z7XuZJe||2na|jT^vE7)ak86`+GU{wFY6@x?Wo!{%IE<8MOLD3Jc38S*W-({65R?KK zhv6a70Yu`&=G1+g#z&ysvC>2;y#88ROle(G0nyt69Rj=p)!5z|l~gcctzSF4p``%w z9(DUFk;-@&Bu{u+NV5?c6E5{rF`OkhHIl6WPb` zl%mL~o9SPCau>#u_*?bEi)@w%akkXIM>3h!VchDUX2s5=XBE-CeC^rO!>z1fZ4~-u zS$5q^)^JmLefj^csN>*{<)|y>*QZ#&!Mf1H8+*~mGzXR@bR_`7%Ffolg>|Kn$jR~g zg>&Wi^e2bD_E=x8#@@%i6R@Fnr-F^sGh00+9BL+Uma=gW9)+tI6&=^wSfi^C@7qT+ zoH~e&v$9!1c*=M4u}I|z773X(UmMRtg^ZX$@C8D<8Wo*~AO`o2&De zZNTRY@1Dfsf7=#or7E+2SxZ>&XP15H|re*8^tMcX5_k#*q#a~)GKJw;VFvoY;0;(h#y6BWovJPU> zs3~KA4%R*ep8V_zu26%hzS|73WmFp5T4Y%#Pm(D* zbZVYp*6L$x?t&vHURDfLX}K9sA9yOlz{f53u-s`60hZCy0x*U&!iPeXxfE(Fj614X4v}eEBUk{; z&t%xHtbQGe6AR)YiN7vNQzP+JBY|2ex`Y!KVW!eodubD3MA}d69}9|OT|*QIb$Z!3 zVQIapY4W%4X0Kj2+H8d)D5e1mZ$w+Tx2|sdnXCk3un{B_FLB;-9re%Y76%!YgMf=_ zE5Y@m=~|^V?S!vj6}odW8$48AB=i7~O3r;mIB)sX!1t}M)%r6e&wJ@>!MIItF^TDH zbO_bP;^oPx6A?kln%hgnZ1nA$ ziD$KczfWjiB101?P+VHFz56DEwJ;=vD<_7f?-aUK;&d$=SiNhBT-jkgz=iGiU$5UL;ogdpbM}}f=|DaGCJu$kWJ@i+|wJT$%VGmTJ@p^&%W=vDyAPXz7 zfxa{LK09!;LtHc)579TMq(vIWG z)CBj|SChbpl_^tdqrvZ17D-*+ULF?AyRQsR8h8)XRwi&z1*w85n8U=`eluF5oMP9S zAq?o{eT9+q#S_$@o5gC3PbuVK67iC!6By*Si2w!MwrT!Kv8U6{& zeq(uO)X|q}h7eG2v_-nx>PUphtaAm~K{=kihnD5&rZaEjH~?l(c2%3yBmSIHoiRdh zbNZjC&XzxoFhbq!LITPRZ*zZ=yj^49P#d$bED`U@-wL4O&l)0Av&l4b96;te zy6uzA*rY$G{Un{(cPoldPM8uEeic7PnFb)m6>ds(2Es7!i7?iZgx010nlle}202OQ zjv}4VshWVe{D_-Mc-h=mjg4cOr=JYnDZw0J)Q>>+g`S)6l7`kk1h&P)2O}EBxB3` zjqS(K;L0>D#+~6K`kK#_`rWihKnz`{S$Zt~roj$=C&8$<6h2j=`vWj~%LT_FT7La$G+nx0xdvS|NJv~lc7?9H8@6|0TwC+>DS>= z;IJZ6P0sbZO>T-52V%Hpoqj!?P=?B>=6=z`C6`<>yh#kDFJ)){9Q&)TL5#9%AZZ?7 z(`2DOa0RO@1381jdIg|qzFgSeKeGYUt={#FV3~suws(Cu?i{45;GU7Aa;2&5YnjzP4I9DmGSYa4_5S(I?=7LxlK(Gh_*?&)J34pV8a0*~C}r9pRYl|| zo9XB-aFA*tt0kuvrGtY>St2gPBR=J+jJ@qvO&f-j7-TNVUz9S{$DcR3+df>8y{dUY zF1YcstDQsvBAm$D_)}=-SO+Yk4R% zT}3oLIi-jYTbkHV3=s`@N}efA`lH_*Y(T_q1IY^_Iku1jZj|7l0B2OWQr92O{; zg13mvm8W44COUAqlX$c5^KA!UUYICtsk z2LMdeT{?|%^7|8*Cox1)kw$jn2yD-2Xu{M9|n z&d%MEKZ7}jNe-YepSt0g;N1>ay}P@Tg==FvaN@o;;5UCRA~P+As4?|?sDT4Q*tH}a zfLv;0W5qYWDJ_%Fuu&_DsWZ-|;$m>ufQGoDr2wR3pwaEgdEblB9GYH^Fri$g$a|^5 z;KiYVp&bSxybrGUgt!=KaqYam8f@7_mT*4hq*9+Uq=svoQKkqQ**I;jkP38?H+7O{ zYu!~}>Fpa(vWo_uriJ~)m++KQ%+AS|Ga9=c8TFPlcEBZYfm(3949Cz6`HI>&AWNxMdTrQsI#c86 z4X4lpdP(aqRoku#c~dl#tTE#GQBU~or;{Lld&#mBB3Enyf#&}J<(>kY&_Lh(DTn%T zcS6v9_W2{Gpf5IWBv0(cWHe7t2}!ILP>{kcAsj{a>U)==W!-=sLq07o6F+}I#I-puS60Isb%lApjq(sY?|L1zE{pC_ylB_C3!SzqUGaSKT9(1img6jaGylm_f zLFWsM$zmiA&wWwFJ7ex}uVCBo!K?)iT?wP-$UO`mljJ#AVJ zik_kg?oY}aJyhAWo=F#%)ZQ_4B*(0Gs*qy~K8hPBx9`5AV_&Qo@J|n$Y zuxd&bSB|H+hRs16N0Jkc+_k{CkNCE}DXImz$0_vpb-gw-53b<2hRr?^cc#Tiah(S| z>Jx`EGCTRw{v{@}^|)O-4kqp#qT^3r5b}GJXUohY6UyHC;KY%(u)o-R;Y)pcFCDDr)xE@n~+KvY@klIdOd!TpYiwySP)ef4?SN9$ngI9Q4YnjA%|`9_ ztTIzJJ5T-FQ_&IqXP%Z@v9D6gM2t$$GSEP$p54w4{f-^LcQXU!{{Wxuh68BPb;F;a zZ*~E%N5y}zvkFSs*__eEK4xcsOnA`7&=(`atHd6$QX4gJ=ip3LFDIRzQWA3lTTLIa z)>}-L>jYkz?R~|VV2>c2M%;lR|C$yU$`!3h;EML?4`RL?A~(PUJ# zK9_dEKj5y+_zgJb`ab|y7)4k}`)a3NSw^vkZX}2`4?XGXC_3$;ogh`C_4vIv|Gk7w zrRvs(wd!M?%_wxM`LeMk1c$`Q5Pn%zp=W(bdc>n~Z7jqxOKza1g2tme?3y50t%Vln z>}>U3q>zMnUVJ{6N7pPmQtLyOmn$9V80M6r+Wz%1X2~8}#>H}HxFH;`n2DI{b8&Nt zAuCHb7_JW;>k%N=??>LiVz>+vWJkbRdFbzyoo)u*k{$Z)37c;O+g~bk>W6@!pH3?x$uRR@5-6^ zz;l=SJc+N*&cem=&&te;NQ2N@x*I~#>3NZ@hDE}+X}flvl9I(}cyFwLcvp?5ki=c( zshCfX;km{)Tl_7C#IOZ4I8P-c2=uauc#tJR^u1Y#40%Bmn$O&DbvxuHc-p`7phRMK z(KNUr?E?@Zv?O<@{up=ZH&Tzh(MnW2m} zPRM<(eZ(%kYhrH;V-dF~vg0doob?e<1aKZ6zES@yomZh6&GL+BEJB3p!<^x!b23<0 z=gC$LO>PMI_qeczjv1hFq~7;eZ<5V5niL^1_8ne2HU9IT_7zCWHWu$QF@5eq4iPc3 zueh*Y-d~q?D6@p(FyIg=yG{FZff&)`$_ypq-SM*?$N!@VD0m%${EDn+@Tz4c^|Xyg29_r4_117=mU(ne1D1SbtU}^K zu#2*8|D9UIl>ND?e{nZJcGvae$6Fj0KiBJ%cdK94taM&pCwC)BR4CH4Wq<#v`yE?Z zZNQvn73UAF4U4P&2tZ+}OYvSCe}ugY7Kvrgrc%0gIW_nXkSqv#HQ!&s3;!9+B%Bii z;x=J=@%ONVlU-P9KEw_j!G>GQm75Y4r){x5Y(tY}EY(Z4BZCVUDqsI(F%io@EoY>k z-V&CGxP}g@ydz-Xh8m#sQUIvtUb`0}-%Cq%nQ;NMg3KOdE)9C20Ac#|_^r=qq9ez| z#7CnVQIG@25A*NJKp_dvgrqzy@8F%bw)zizlcy)%VNmXcGX7jrk~N;A6R3*hk8ujj z5C1M#+e=swTU*L4QTv5va2)d;a1=@LJc4bk?fcT}!FW%VmZ*XfCq}hk36q{7jGU?aPpj}O<6}`f2W6!a_}d1 z9$uhYpb(U+*Y=N3LjE_3p)rvkzfi`q;n1v*Jy}tX^kc=9&L8~-7JaBU$QE%a2&%t^5h=J#%S=Akzs=6}6$yycJv`r^oKgC|>XsK9yD|4~OV8=KDWRJ(Xb z;4lOR6cYQj=X+Rf@jiTEb7TUbTTd~lpM>tp{pn*>8eA2jlrg5eyDe_YB|eeVZ=<@@ zo#fKWaI{raQsl~@qcGr%vLQWnHcL(VF zqmcCzP%m|OrpoIPp~{N>cJtbpF&N1%za;K#olg3>WG$D}80L}prCg|7UhN@eH#Xn- z>)jSBf_X*Nf6ZqU=R&m)91kjIOmWmkJ!;aVGe27%Sa?Ke-#7evNJX+YgdpyHs>VGX*%x%;f3jY@lb ziHu3RGrKG@Yri1UzZaqDO|9a93v0!8a}p zCkI;_EW5}rFOiRpx}-+S#CV4LhmnH;%DlV*^o9qS+0d|gbYBF2iKI9r&-M4pZ(o!t z$^TkOo$Q%LY(g4Z%IrFXA#BQB2%O4e9ii#7%l90pB?qzms8BW}Kukz+1^YfC*jSq7 ztP$zLc_y|K{c`8wv~l3>c!k(KIxhcJWcHE=4H5g~l$!_xRm5!oZ}#}kkwh<<09O-(7flWA$3m91N^(jWiW~+UoD!z!CR88VYCG0Rzv7`tAR{;tB&<` zppOW>q+6%)!)>GJt)$t5S|7nwXng39{F|s_XReDcbQBexiSC$flJO z78W1uz|7%Hlj_8tW{RiX2k?0u^YPm}eUoiU7G^5| zXRcU{CTw&MK+vPUS-QK&9KbsJQ@=uoCZBR~X)3^}cDa^Z(YfWb6R*C%fB0=?TfSK6 z2)q6FxRRy8P9|X#HM`t~AOw~)D~G(`{`zT&1=% z(=qjO-xwo~6{c5->T2ALm&Ij8JJ-YO9}SpBgN%J2m)!JBOH(5v{i3JZJzFZrDH>w1 zLNtwj%|FE_?##r#14^cSE*j0H5CSPfLxquxf*GH8RzVHTuM%Q!U5zQCc0z#evDIIT z_$e-;L+SZrM++rRL}qtwcXg3wI{(jn;8tAV&NPW_o@PYZD@7| z{oK9F=>CjT^8VR6F?{$Pa5aqkr{eC+lkbo?mA7d?jFq_MPAgmd)RD=@{v&Qu7cQWA zS)nGutF%ewqVHJ)>9Cr|Y!B509);mC!k5~cb#Q{A6qqoOvdus8Vduc?P41L9(^6uL z-6g-fba&o;kshoVHUluSoC=i;7=Ej_RpuFKc( z<;&%JM(wfEeG~yIt=fhT3S)zCaW*N&HlcDYr>Jt}d4};*L!Q0M*7NQO$5Q*Ie2TD+$&Wog$`_U{g4YO{$*Rs^7k&%58gW|Q~gc@jsLLW1wqfS8^Wl*nD?)|r5lm_ zG;!9W<{q29!#~=ObWU|cBUMIlo{tSYwD^E!Bd@Au^)oY%!hfT{910MaCd{T zoz|0h(rD~xsUE-cSDnMs)F5u>w*fC|Ej8Eyn(VL*q-v=Q)#?`PlxDO=B1-0J56{s6 z2u_xeel>%}PkO5q)SrH9lj5CbMK?#9wqZ&7FOY2vZHcam_be#*K3ZaMm+-8jh?of* zn_i71c7J#%)m`8vi=&+$!BJiGmsQP&DfS+w#pO=AF(}RIbl}S6mz+Ul|J2@gj|V-E z=}U>qZFD|Wj)1m>b1#AgQ_-q2xqi&U=j)XrWR#}#;IZfZzbfwU_^8R?=9U(aNjM)l zl|5`Z(WZ6&yO4XaaQt!Y8b)^XA;?FhBIvOU&CEO3O5}eEOv&kfdYvR*roP=kxEsW` z>^@?mvXjKL+uoC}gE@b-y2Xr@24IyO~F z)4|B+7Lt(+WB+vj^0Y71(%Yxmlq}jpK!_NhH56DZEZm111ppY%WA;*InIGEk%gdv=ffK^o+GleW&>>JbkHRFl9WvXeigk@X-Ktl1#guOf+#|22QdQ zj}{JbA#uYePH7A)F6K7nW57lVy7$eSh0xO1u2tF9HfG2 zoFmti?$Px|qd@)`7wI`Eyz~D6QEhyL=d3aNdHe$#=0iCNGsL*=ne|zd)7itb?rpuV zm?R2zHUpTrLld(X+>%PF_q~jo+%HzC*VJ~#ZH0n@j$Qqz13%pQ(VtQeOwq!($B=H6 zP#o~`Ec-_a#>RmE01qtgM8~&5_HFt2BC&tfK&dvk`SH-heSJ8XR zAQgeLeRTB52`;r76hC*Tiw=9x38IA0z~(VzVMPGpD|6OonZwfu9(Sgc`D)H1qKrgz zfYh7a-a2bUTW2Rw0Cz1Y=m%Xeq&sWa09h3qByiAt{&VNy@2B{oEv9{UJ0$6^Af~ee zcJxcl*;!LF8wbBM`T(q%s#IG}!qJ=_p^zyUwTH?Ay4>93B7(L!hm*QdUu=lZMnz33 z_yQ>@wkiVd9^g0cGERSfIVDaLCv=5O*^Wqi(&KpZ@xdSF_XMrXlu7**gtY+D#k(Z- z05Mx4ZhMA_^;o882f+op@w^|3>p;xb>e%1#Dit(Fgbqv!uJ%J%Q4pHjGFCt`p{QH? zx*wCPa>iT^A|S`&hW6T3=)&fI0C+|UPL7aqz&}GyTR={HdWoi0?2W!EZn-1eRq}B; zcMq*cBU^rY)VCv|aq>7+)~!v6K8jTb$ty_ul8F77(O(0QNviYuo*U^YUTjJhmaKUj zzw}dQX%#**Nm->_N73t&ajnPf$lYi)9$0~7Q)B#|ZNp;Bvd)~cL(PFhkEQsY&%Pu}Eg|v?R@jk;uM%H(aV+WA9 z{mppJJsN0t{~rK9MTLt(vGVBo(%ZON)F&Wzx&m^nqc)sW0$*WN#DV|FyFN4GKnI7* zR?n*1kg1!LYVi_*>nSTkK&RyYr=mCdS#Oy9Y2t8|(FtUf9js@NXB_7QG`}Ldu{NLuywG>&T_Yijo&Q51`r(d0gH2>suZ#ERs zCEk~A6NiWlaCV}?U7D-N1ukq{?zqCh9`|YIeP?YtUHDjOgiD38 zqNadW>9M!0Z5Rg^N$nW={WEdt1&y);OEn||4^Vy_2P$QTMU`NekTB!a_Lqnp6??l4 z>oKTMh66-FICbP7p{}m5FaRbf@}0?xzekfN1A2Jk-E7}Z<5#+L!#L%y^dbqaIcr2lFc4}0~?f`cm=gzcBKE$ znL=(gavZ^A7m0+}Ig!$6AI6bnZsPHVbjh*cb%&zsrjI0bc--Xd<#3XSt?kMg&XC|# z{{adV4n{k-&g9L7BsB{_Zf+A(?yj`9_aPOh8V5qx^@4wv*z13V8qSjWzVvRLmXy@xL!fx*RE!@A)L^>V!st@x4*-g*M2-3b6T zCnzHK7VtqSY&-|_JqM2kQ(I0e1;Hd(qbrA-pcmr%{p7jHidIN8bsdQl79pY7-@t3` z3IGa9si&i2$4pXU^`$y74KjUJp!g^kBKYxj#X($7M0JH7W;&o8R83BzRvyU{l0w@4 z?wzLC6AauEoH}mE5~<9E^C`AgI?2DOc7Q_PZD*Q~ORQ60my?%N;bZ&59KxU6`k79- zbK3JiHe71|PufNSltBq{=Prip{+ewDaSZ@xWq)X%w+t9L>~9VqlQ$|}LkHeD9YDKz zi56XY@tw;lU|Jx^I60TbHC}mZ9!nP?*yOtEuHu)=tiq*Mk!#iW86+B{p(tHVoBVK( z9mZ1;+%;~@;>}f!0ri)KuorXkBNRoAi6&p-g0*oG6^95;$T37zhbP1|CTHq zQEc&+x`skMUIcH!?o?d`9X58N_j7Q{;`vThT1(6oE6Cd*N`SA2%DQtr(?Z!p5z`$nIM0OtdxzlfFF! zv3#L6&o@YXVz-mBKJOd;4?xi>zOctcBBimX!7;wOt3Dn3AHZ(f$*8W6c$;S;)#i%l zb3x`Hz+*Bz9GVf5l))D{A9YS1urd;%aQQGwL#RmndeF*yr(uxVPfrgbt za;Y}8%pU+CMk3iAp^2Fxgsd6gmkFhPGMw|w4w8bS8VyMl3DNszuH6&FmnWIL3W>Wx zCFE?Qdlm8QPw|HN^8gl{T(uwXwJre|g-1XO#`fBh68t_WVJvTGPuef9Vu{#Lj1lXH z+6wK#X1nU|u21`AY*yiCu^8$1j=MG|47M+cv_ba_Uq|euHl7O=|3fqlFv^tAD%t)VFC#v!|+0Jyd^sXI2z^ z0RP|QtS&@_FsFz5^4Dp#DeLn0W+z@&L<&MU_Tu9lkQX{kurg<)IYnW#M3ZOrv-sGR zhNVsTtnUP$UHQ2(b3k@c9(P`jL>gO8%0y4kU?47v6ZyGB}Rbg9XD3Rs_k%Yde z2eQywf&mVur=7?le>=wadpZ4i*Do!sf~w%K>FGx#X~6hk?%%VA;=s$Gm*n5jJ!jWG z+hDQYdLAFg&hsG|;O>TeIskxiKlQHa_it{Lmt1U1r!B`+*JF6!H*_oE4)tIkV=5at zxPd<+r4lQiMl8EC?Wv2*p4YB&^s75wpyFi9!kN;8j2qqtDly#$W;#(?v|><9pS#c{ ze?R^Dr&WUeoKI%pLIZPZ>YOJNzkew^r;bMq@9I6F9o4~T?NQDtbWtc!w#M4ZuASHC zMd6AU{T4jeIdHk;(@*#{{izeJHBTD7>4?2hd}6FrKTTzhT5(t}{q9{L(+{&hhEImG|s*s zAd*^U*_*)bvquk>a!<7(Ap4o`^WD7UiWIA)<4cN*T5pU9v|q-~-~XO-izZ!ltD8OI zzWKe^W~T@XZ)Ue5%s_1FEOC}N;U^DKmt;jgf324p(=3EbxC&z6&^<#%50yy6+OU>z@5+TToG zSNpQT+^OLi8_R@Gzx_-=8KT2(!B>u6)>4Tal+4?sak0ExJC>6AB5;69-Fe*a?ts-( zkL0^(nEZ-`OS)q@QS=>FOfGyUryDIPgQ#Kn>>RR;%mz3LuQ-@RZSBO|bOr~pPBE|{ zAOAAq=VRhcl&9zxzvXV>H;&XW1Z^L}vF3ixe|@+_u>1^ao&QMA$Y2Z52T!Tn*?~#% z&>TZ;vrx5nien%!IJ1WPaaeCMOw$`t8X?D-4hX9N0e>`GL@p87V2HfG3L*apdrM`& zkEXHUW3vv+5K2F@utl~Wtp_vS2GkyeI9Bx+Deb<)0Qp6rCAp;Mypa6?lPH&aKgO^<@BSDM;O)lKfe zs~9ZY+znq`Q8>8|uSK|cl$HI@9JO3KFcneE+YV5?VBwKxEuwAP#z`%Y1LhGO|9+O?G6 zUqiU-xZwDcmM6D>^=;~cyg%4&J>2B-Ef1Okw}8;eT+dcs5=7YYZirRtGcohGY}qtg zoSc#2sn1F9!EUlj9?JiAmEFkXD@6b01!g4`4?M>livX1Bs)8yONo5i0<27i97y=Zk z7-RuxzO+{V>$J?w>(0Vk5%_!WfjN{NO17tsarz>1FZ{mIw@^y(mf$vQQNWX_r23o# z&(ilp6;S4vm1fR4+3RsP7mmYu>)7zLWg(*!HcWvtjsg^(48!+A=v1_Q>uTsjgSa(e zvHHeQY=Mc8W#HRrshC{cV*-<*64D?tCC`;a@+-`#u`=+rRP%R7}v z8iDfcwrr0Ht!98Kg&sY~e5QFm(Aj)uMq(G?&05)kIpVr^`8occX6H^jbtlIeDAg(9 zEha0;`9*T}(UTfF!(CzehjqmvuUUTeqGYqV{{T~xmILB^ zj50zV)P5Ukfe^v@%dib9+9M(XM!q)*?6NvsM=?8`uewFFLRhEbi@Bv*!tgNjO4G}0 zZshR)g2X5DXW6fFH6y=Hgs5HJ{Jn86#uLYrrxbnGl1E2EAy@7|YD_rgYv9@v52L`u zwa3#XttBx*i(vgZ>C|yM%-5*OXOf&hb8=G3bHN=e1TPko@|ScG5~<>a4Cg?dgHGQu z8Gg5}i&Ja&CNnk49#SV|Hx_>#HRnF*#v_cK{U_=`7c@el=-0Q8IrY7H=ujk$s$rcnHIhpyYvFO>6=5|o3v4qbVxk(f`QRP@81xp? z?b$|(e@0aSYYbAh#Q8d>q3~%VbRdjfd12%_F|N}i#I!a=ne+=-M{iC$1gHhT4UIgRAu5Pc0lRh8V#p^Anu7cH3h9$GI|5c9x-$Yb8c4utGRk zQO5tYRd|8K7Ek-hq#hvWfDZscy0j~^QS4#ud3Wzk1?gSUC5ZRkH`0W=@8m-}_rh;4 zRguG!M}d&x4fu!z!3a&ZmBoR$liApB>eu7KJ>{PCC8-uIvE{jr98%~Kz<+?&wK}yT ziV3TBBqXk18SVqTiPH;C^0ZLdFV^T#Fd z8i<@N?VXy-K6=*e`O5D~6J-kyT4zf&KCJ7)=A$p_c$`s29&}FHrvhw|mAeLtkL`p8i`)gfPRDauG|tj z>;TTXwhxwCRqG*2SxVN7Ak*rya%yIBZ`H^uo(`=PwwiCWsu2`Gb_>0(j5Xcbh`*w+ z&?zpF3j3iS<<1iGJ}h75o@9-<)D@PST~DErCN4fd^MVScuGAeGAWZ#6QlIm47MQ<0B8aY|c)Tn|)bYOoQcBB=Ydb?ktJO2_7b! zFJM?~#5WG(SIJBlw1rv{UROi9l0y_X606(YhIufTit zer_eW7`=6qqVvB6?D_u@wb`@qw5gxxR`(v^vwX_Xs?i0by^kb!d@HsaF)R_JTq?#K z9{uqZM(NlNEF`bHBPn%;^Rd}vUlT=((?)oF|I*c^NM*=^MPcxT zWqq*~b8Q)?9jv|bSrY{XHmV(Q!dxv!zK8%8TO>^PBjwo274Au-0a=1nCYtQC{T zaky>~ca8e8V6E5xVkjB%JLO&;#$D^dbR{X=I(R0?d!G)|!Fr@8ONJu!+SIxJH55RK z$y0swj)^LN0r$1_ZLuLs=nyE=2JbX-&L1L2%|k9mzSZi=Yb$po#;L_k37+d9ir4jJ z{vQf-j{;AX=B;z6gCZdg4lX(8YZhE~=Jg-i`@9P`+D)|Jv}NMu7hWoHxcL$_Oq}2h z)|?!Ti?x&LRBlkK%9(LV3H9Dv<^!bQ)lPItw;a{t)_5eLBQuHp}>2Ea6x;Q z0)JjrnLDsdm-@%S(i$ZMGe~xQ>uo3ix9CDY?O{{J->aT6$qeJH;I`7ea?OF@*C@#0fNW|l*qE8YsX=JroKNyvA^Gwpy$fq}oTCg8y6>bTTOtt5CEWe+_o}C90_Ab%<`-qo zA0F1KCJ~w`J5>&=wa?461>&XuD8KuOebD?vXzB*CY#J1QFS_k#hZ2{T2i7M~PHYQY zp@yuj7nIM;&bd->RU^nd+zn2QVS)NnQ%KV-j?#Z3(@2ALdr-&r>qM)1jh zfQ#M?I>Xxd+s zob>eaK@nu$TzT==cX|VIC0O~gDE88?Pj4xaq+A>(54|UNjIJ3ZaFfU@{bp%zNamLv z=%Nm0dyz-m0<1yl)_&qPJ7Au%a#N-Co@uO3Rn@HfA7amXQm7tUqupqQBd!0>;jgkx-?WJ%fDFi{t#=*2t@-7qK&F zaOkRaygM5H|Me9P$;Hp!2B)rQfvEQK-uZ(E=*46)<0FkTu7KcLAP)@f>BS}{lI5f? zRg(ax0!WgKYylyhi1+vmU6w9%wCDYGk5% z5Ieg$8z0_c`gLE4B^J*pdT2ZfcJq$S8o`!Ko%d4fxp$>F_x8cZvrbH3Xj5kuOJsiy zm#Q@V;3HPPuh6QJoE#sz_jDGZl({2C#{{ryv%3_xCniigr<{6$)CDNS2&jz}>R>zc z;TO!iYn=TX+%f8~IVT2hujNZE2M8WOBHWE-gm@!HQzZ)F8177C^t9B=ed)Ubg=x{) zSLFk#h?n%)hK91LIesv-NQ0RfLatg8a;N4+aa)uV^D~X@)U(GX=jL73*W=1JInJ4{ zIp@w$O>Sr3l|x3bZXI6OTBr*}GN>QRwbpNdEf-?TsY4x?|38w>GOp?OZNp>K=+Ogl9@9RF#p{9#-?lz-m1Dlp2Q#moHVLCH3C1*%@#3gQlBNc5Uw14&(#Rk59jd7MkOX70OZ^ z43%Z|Dr+7>zgE`-d=L={irp}MS!3rXCBI1D-~~{?cdo~U?**eI@mxfm8Zlu}uX?0sDyhrmq_3&Cy)5etWKo6C&2)-U3T80It?ntEX*UY`vulOQsEO1th>i9dl(^ zs-XTm=m;0|GQ)5q8pu}d@G_Zv-?!I<%ft>4z(qKuuZ~U-Vc%Jw`qn4((6o_4)1$vs z>N^?sMgu#z1)<37xkaSRxf@dm%u1%#&^CLqb98qlqS)XJ2h*iuGhzRIJ8Ad_$X^~S zrQ~wy*|-0c5QuARsUk{dOI9RUvK9~;jp4BWEOlJ-51^hAIVg7_(rt!O+d!@CD0Hdm z51H64p@B`S6*p8V=DF%*uCB3CunZO&MHOtJu)-{HWF~^=hxV%b9p@a@@33h79GR3v z<^!brP}BX;W<8*5&{hur^voe9M?ekK(`6UHCVu+?H><8@m%HHcV{5}sLm)Z|10-aa ziBE<**m!!Z4-t`H`)HPPw9Y`vD@O+N2g&WlaqGQSCS^*BPqwNuAueyEMbnR0UXx|< zqD}-0=ZvlZz{h=%#lEQIR=oJO@5)O3C_iuJ52ne3EK{ys_&kG~cUVf?svAQRu&WY7 zOZ(s5&eD?(d7>P(vA)O%)gS*!1bz^zpYm{AhNHkZDN%*s}buQILhM%CawZ5G0C8p0!fg7U=;&(VN zVIJtfGqVPQg9K}nu3xe3Ric09Kp@dmdYdX6lN;r8+E*|BO&|l(Ujt)IB{J)k4C1PV zI}bnFW~s~D0IpT)0l-AI4|WT^e-Sdk2Mh(r?KSguU7t>5UiuukneBK@-UZZ%hc30z zTlyeqoK)gonjq@$t=9G=(-$cD$9uiS|J4M60M z=MmxIA2{8{!EP8-6BzS>^%3TPimI%s*}qL2Xg@m_z6L~nb;8B(d>!paM#<@FZs6Xx zy2j?FJNJ zOng!)qQx(DZ9iCQ>uT$aXs*`CVeQ@XX}*tUC2(AJ5;0@^ju^JOmYt59%yk{C;S z+0F1n`Q~I)O;{e>ghIuJ+7@y|D|=FxDV-fOWtcudb?Y6x>gZ1GPf_K%{45iZs4F2~ zOvp@K$zE?ZvWS@KC$(Fcwv_{0D)V=5&*sy$x$(3KEPNUo-3Ts#iL(>&%nMx~9hy zLC=rmz!4Xe5GGnbPR~xkPqw6=Yzb3b8IGZfA}ON;Qjwr|iEEGy|{O;yq?Wn#2LOdI=8TX^c3uLCbvAF6T-()XIP&9yU2$)9e zT13V64?tZG?!%+5TVR-m{WGW?WtPsNMLWy%6?|jSei=CfVpZz$FQV98=4+|ezB~Li zT9m>=A3Rf_tuAESLJO9fnu5@Br+SBwB+7?)6`P7B=0o8Cb12Bgj}8aPnZYkz{F5#Y zl*~?&uPXllqX%(3noQe1FNwqnoHlf_@*hXn-Cd=^;Ar5cNXf1Jm~+N4KHKYq?eUBY z#&(Jj5E4O#(U_@4m5H`dfPM!9u}aEQxEtIN%bS{!d85>qp^u*mR&gq%G)kzn(-5Sg zfiyLFzcr7ey3(8Ep}ai1Gm2A^PIh`n5!aq0p~(=U7>Dia8x2G>cr(tqqnK%3CYLhC zpMa-f#xu<+GPati!>#rN-L8DDl!5N}uj|GUxn+n%gJme_`^~Imar!QsB_ikK9{^{h+0EZpjdO^{!=epK zQw9JUS=ecumr7-?m0ouhd&=uK{^h&HDLtn!G8l#W*p$MA;R^!Lmm zeLy23ZrSZm9Pu}o@$hJ9`DOc{sze?xeW6dAo!-bBU%O$+PI&FJRtDb(dqBr$>0T~< zqL)sbvCdSxu>qRPi-AB)<@dAFRDL;>fADu@&#y6yVmGL({6>ofah-}2OcoQqP!CEs zr4r}cXpA>kC?ZN|&RIy5-(WXt6Q>4i*?!m7Un+W{0?Vpbr+h5!6X>iXD2V3aQ=O~O z`uQ^QA0Gq~?Hxcf^h$>9Nga_LPx=7`(s8uHi7|?JDxZf8skTt z|2&ZXpSy$E8 zQJ%_Dvj=I`vYDFWn|mt>u;)k)-oBkT6(m`;gQ3^r(QX0ExfTtThlSq#^w$>%~{{}Zz&rT2k&7XB2;{?EC)@0i!|hneZw``-2+fOSfiMMLgH3Vamv zP{{DsSg)^JS;JgJSVJ9g}JlexKKY`p2TMTgc^5FkiatCkukKIF&7 zt%U5cCI$(pjV{2HT_iue1I_tC1Q|RWvlS54hSf_{ufk;fDLpM~!lm@9g8oZ`QqO~@ zXAm8dL8KX!Blh?7WPsZ8iZADZ;F+CW6X&O7F=vk-cV}1|HGz3dYx`K^Z(1&#&5i^# zYswUITY)Pg389HA@;n-2t)F2f=mz2v06bTAdQRI!P%ersNCfO1y?u$JTB>k){9NO+ zq`tz+`Nx$Pu4)Q?6aK+CkeTXaLz^2F%zOiABZY*J_FLK;&E$Rj&bU65SR&8(-Rd8J z_I2ETx2E*XTV_%RF5ciX3$@?ak1qo6*DA%C)7M9tzy0Y*#OC8#I7qC940Z;{P%SWQ z!78btp@eLIiweX_B2w(IA_2bJrGq;KV2E82j$!dF^APEDk+59v+h6j%j<;i(6xY1p zW~<*1OsNpCsjm&1&WeDjX(#-s2J5@5pPKY&bs+$K>OzXsokiVRHrqILFzDy8UmKOp z0AHI#j8l2%gR%aO#ipgDDg*cCFz>Ze1c&Ig5~Fsq=B%ocJe+IS_0=fZ61w1HEGr{J z?q&fT7cB;1&z9Gn^8|V3B+QBI%vEO%4GJH`!5Y0Y*@e|}FU+4|~8AsL)nG?#QzGvp+ zD`LGDWMWv|SJmhkgM;RM17FOt&=C4V%q5|;H)fNITXJnH=br7GF21u3g7KRzWE1>q zR3WrKLr@0MI3M=d7zpvh$!PLXnqA=%+j52su+fm3(b3caY2uTxNfPU|N|UhMy!*K4 z{#!xk9AR%ja2_aG*~{6pcYuO^*p^|#3FFFOne$rkYIHJKFd?dL2Y2frhbd`n#JYcC z%OYo>5Qc&ZPYTK$NAG(y8@_A!xlA!(WAd2b(4gkf$$$)12$B! zmkpUKpY{Uyvd6b>1rjb#_Q@tJZFz`(xVS|*C=_eM5dipm%>l(6-hN9SX3HHX&mt)s zFN92C!Opc3{xn7$K0|wMIrmB{##b<0Z-!v90`17df~74KAQhU5kNg}L9T=F%{8K74 z^5uXbFRnE0{`#OT`A@QK$`$ET6&Sq)94N)d9M&&M$84ufEz2&BatWg{a3oGG*;89u z))D5XPCZlx21+H#sVmSttB2{K0)Zviy4(u%ij(*7&bAzC96rVMF=HhO+|&W~+Ej=r zNLFu08Ne*p%!+)*e*i?+nPhr;hk!qXtcAy8O3g}0zb4q`i$LsjJ=y1eh?Uyf!DMsu z^Ws>y(ZBEACXFx^0#fmv(w!YFyn9pW524Z#i(smn81* z*g9fD_~OSp%n0#sh&=TZ=)X89Tt%8J1{9r#qtyyrzlHq_Fl4IzKmWhR`gxeao3JR`&nUktmOx zRsfwrX^#{32EG{F_2T{{KfU~Au`NQ#(u+x91aMP=U+a#F-b3LM9dn375p>}MUd`z3 zT0>cag``4hcBSMQHKG)ov7a}#l(D5bJrbag>~(NJ{^$9R5(GAn`Oj4Va}h2+j-L%< zh7#_`5-fhz)oFCaGv0A+xA(h41P4t%PKtl#tm7p>E%}VH79%W5tBON4k*g%tYg7ot zcA3rDr{~N1+G7s;hwj^pPi4+Rm+%`rTUru5ut^3_%Ee!ut(DY}Ec?y{XMT2MqFv>9 z`JC+oR}>=Dmo9k9q|-d3rw+J2&d}!H$eBg;LdJ_CJ5!$v3Qa$~h`EGcP~7@3^^w6A ze!abuA{aYR?zKw^miHn>(LAqXCj_^a_Ym3HLnyw!s0XIjN7ro;z ziVtSc{?vf;2cN+|j=G;D8Z3{5R6c~ekNJx7G1I~Heg}e{eToRBzF=EtWUJ@=u?U-M zFU!MSBGu1_dhj!CJw+dx^(vemLhd{_TujF=b2y1sr1QG_!UuWsRv2niYKhp99FPFQ zUz1X~BUIJZ3(X1U`KV0$gdh7rfGnAmeYIupAtQK?Zxw& z>~!*t(ii2ym?ieoSQ&dbccAwrN8ahMD^@_y{7x)OrBpA3)pzj8n5h9S;EvP9MINz~ z$kh$WD+3B=tsbWAX~Yor*wTiC6e$>o1ehNWJ4tC=+Ggu&j_2fh^b+k2fzjBTAB=S^ z{3HGW;9sx>!t-H8ORN`+xRAGezTOTTX9Bf%p>*7t?o1C(Y6J5OP%uh9p+?`>mL+in zS0B$fcjoZBrIQ7C*BlzUV00vN-p3A#&+~&l-yeU#Moe2SKi0n{M7Bj(T3w2cqQICl z6DF_+`i9c!Bk`;Yf`9F`j9N=8nyUm5h&=>v&CJ5T99})@#tgzMR4m>-dw*v{G|SRz z(JLwhovEY;Ng5gO7PjPuuSI^R!jOf~p|(=vlZMiFiIR@L4j!r{2f|52Ge>Qaxx4N3zja`TV?hkz-0`{5#k$ZR7dr+*3e+ z+?UqAgVFk`v!ddGZqSfbsAMY+MzNG zjr5I1DyJBQHuJcwK;4(~@7Uq~y)5@jp)mlQNQ94Cj#r3WGW~vNE>bvqAiXY|mB6*b z(9X85CSRen)S+^Xf+{t*QZc&RMus^Mhox4BiO3ljAc0L^dW>lqpHHpO+YVk+OX*tB1f?)?+G9BWFn%?4ENYi`aW=uGU+N4EqvL$e&q zLTx4wiF2g0MpUf@AAKi}e)Ifk+yBrI+t=+yL_0u(lHT5cAc$*FICU)A#es4^xYA_n zvwU)AMblT`{Ar>I<7{M~M98JqMMAVW))^rJO*>JN&Do92(5LkU?CbDgby>KXM@itE z&NTHfD4W5Sy8RD;dCNLMz~0_N(!tw+g0Lq^+ZrEHt^(uf79F>IB6iIR$E2Xgo7r_I zEA^pDISsIRR!BZYQh>G?>%KYLy_`^3jPi>4&VQtf=A+&ZvBXt@R!AAzWawXZEeU;V5)o5!cD>gQUrip9{Wt- z#+00v7fW)ZP2(RxcRln~WJ_t&EasLqK9Av&vPU$%WJ>_BU&~3`Ke@GKm&xio33i@q zP+}U)XX<;R!2Ce>2Gd*j!bG((d42oYRJ7j)b2~Q#ea%9*U*NB6iB6Om0JNZtU-Hq7 z3RN#uU)?VH*TUU?uU#}NycM2o=4eqOGvxK`Jy7ibzPg&EzFN_X6$u)SR!9bzP}N^6 zJP`>d{{vV*XsR&+lC5KY@zRAJ?3E|FlX5q>NLcI<+qGI24&d;f`K7e7$7m468 zUoue%S-U&Fp7{k{<3?GyuT+w@>fP{+e0qjtn~9%I=s)j#{Box^RxAPbc*E0yon#)} zGl#eJY-c*&Aj?cLIR}}2sX6=AB?gbnBWw@f?Z(Iphn>ShVE(N>^?Ut$h&*8ICZTfM z^GkgaZjFJsh@T$W%y&dRmXFETijnf~MGLAQlUeK}`D;#Eq;tAf#kCXmephfpajMF@ z7(oSf=tQoSK-nR#(xi(xhuwf0Ss}ZHB!uy=ixaZK>{19l=5)VH0>9!(Rq|`|O2Tn3 z;!-!>*VKQL@s*J$ARQOAYwm(jXuSSVx@~QZCivYt0GCxcMLuGy#4wbmJWtos@s;&J zTj#zSO!_|aDI$NW5)BU7zQkdF8u>X20yKOEYD_CeAao3sC(Hl`al9q|LzF5e62M>FdB1YpV-x`4_-VbO}%(bf+iDhQ&@r}`p*3n*zlV$nIyh7D> z3{dT%K;*Mp*KNE_-%7f^UPfb;QQqRHTr|fK?NkI6AD{(c%pY1gXK=Bx`pwUzQMe0>-d-F2z$s!ZaHMEWjK33b2*U8k_~u2 zyQ%c{q!}vM>;h=N!XTEP{<^(`4)g7}S&+TgR1QA-n7xw!GozrUe-Vj{qeD#Wh0}0s zn|tXRh!#Q~>h+m(g&%&4TpSOJ-Bo3riiaA38FtM`nfCy}>@!wFsz`ikVu5kWt>w#Mj!#-_Yal+BMU!fX|4E{ZNjInoWr}cF^bRa5 z_AwMvxOAeSI;`EU1Bahl+b|W{VlGYIjZeP7H93=l`(pZTE%GO(pC#-jHO=~;w|@Xh z{5l}QmyYrzgbJEz)JVVHhbFf$kby5dFMo1=wi7ZxSs$c8@l zFj__`X`M-Zt1~*+XU>4-aTCdOM1u-=HFap%5L81Xc_{p}lW=+O2*IkhHmGzmENvrI zl2Tqescj@CqqKS-86`ZJvV6+QmNkvTcK6ldTvU!T~p|bah`tSUE9YWiKvisFL zcRDz{S3NN}eHH`03sPD7OjzHx-f#09SzPT#!-Pp`w zgolP+o$fH^DjotUUZf0+1Eq~5AyTYOs+{C4dy=RFDfsX1;Td9fYB}IUW^E0{DG!EW zY_j}feAzGXzo!|4gM6#?q?pAA>yMv{6^f(B!^(V$#*W}gGW0B~XSzP4;2@QD6B=SY zMS5oAVktZrZ&YyMVySOo;dnMtVrqKX=11I^5Xz2hDWl;+w%WXGSZ#R5fXxZW9+UAa ztoaz-mgOo_d(6*|sf756Vx2chqFrZCFpg}QbDQMfzb%O3;H zOYqVm!Won+ipm}c$r8XXu$T^(Nka0xNdt4xH9mc)V+K%$^{5!L0$aK~k{wR~ z+Wt;FZ3r0RsQuJX@~i$7C}v2$Ud)x!u|=-2DqoPj1)EP# z#7W+Auwz%^ZG|MEf}SbxJpp!R#o-AdVeHvuZ>h<#T&bfd2nAFrH_plh$SBMWnd;X- z7V_QUK<)C#naGExvDmB#9TZA|&u-6G5^s&7kSc(#7Q38?sw@myUDj z?U+NCa>MBi*O&fjf?bUEmHt$XaN<&xC9{9LeYY2T&V>_RjWI|9fH8#`i1>ie64mDtukiFvi;o)>3Zc{7IjV~b;9BQCo?J5B$ z`E!oHpSIgQ_PI=7BS2^K9(YW_^bppyM(n(kg5lAp%Ds7p1S?@FJM;L;RqXN}UbnTC zx`mXPTW!PQlp|$W@bI|c(NR_y>%sQHkpaB5EDA&V{>GDtULhiUwui9{?tFC8Pa-S? z7YW9<1yG-yAqndy}MKC5com@;^g1f73?HZE9gW%FRu_z(7*)6x+wCSxvp` zs6S#1F$03@I9vKVImUZ#Tu?9C*5>BPK8zGi(s7K;V#L=~otW}dZN(99eeFa;G4-S& z@q2kQS$z6dSv#k)_9^&lBv2srEiZC4;V`x}p>!#KaUZ@lYBrYtThXz!laA7lweW$W z%c0ttZ7l@itNXnwf;dEk8}$fEJ(k@jlWo34hMV=OCArS5z?kT3ef=rVeird9f3C}r zFxM5A%|Wt@a3`#MmcBO1zE(_YVwtP)penn^ws78XDNPH03N8fj4L;ZHiyFXchX(`x ztrU|*fg z1=$Kr9}7IGz@vatA*e(%0V`Gj|AzZno8%TAe3@QJl4G7rZk zK9p0rOCh1c&M+VIQcRsX@Iwk!+0mZ1)+j#}z>Vl?@r%&FbkqQ3*yKAT;&X@pSQNxqbh*&PQ{89V$8>)zS zSkE)8htmuLoC`(7#NUJA#Is{h?3Ti>`;OgjvU}HX`nNl=+e9~vvDxVvNG|sgonxT^ zSE4F?-lj>>p^VhVqH`-@)z{S^@06K28whVPP+nS9(t$rl6#mo0n3A`ppd+ZXwYQ3cMn9+TQN&WCglZ z1b`B2x%_uPAl2D|8arqGgK+`e&_aJGUjf<)a$HFO?~4OpO!n5}imx1@I4&Qw&xKnl zH!6C+IiC>sCifqp2!0m;U@V}#3)WzI9SV+Y#}SIk;3wZbJ`(s9v&pOJsEm`GDq4Wx zfuY05?;14wv5^%zm!kFJ^T;;y^MbUD5z)Au)dS1o*10@h>S`FqO8n^NrfDmh9*7{I zO?Q&7NcD%BX@nS0c&*QAFZeZ`&U&`%tPn6&6ZS^s%RJNObfMOFj^e(aqI3x#?3ogF zt>2@-^Ts5Ub$ty6a|fL>P57iTzW`c2D%HUbp^#O$d50EzRS*dulyg$-PW zy_`6XATvpy84;!K$&zpqH8g@N)H1zG7^7yh1kLn#o%k*)ZhqaG;hzSuL=}%EKygp9 zJZpaCBj<@+HuaYEMZi8oXWf8z5i#O;7mFB|{86bqY9al;lzrZN(h3XBP9hm7^w!&( zwtEwYTH7e`O8O&*k7KQt=B(>&C&*+I&OZdw9MN+0@2@&B{R!bQV1Bs|)%G?Elzp8Z zWN5!~*Ihoipo_AKPUyisG!u8ckJz;2b|JZgf+g)1KxD;Wd9#A|2>ZBbXyCehEKFBs z$vg#H>7|tC1rcbE@qie!A-ZbmD`CNjZn&i-Co#IuAI!}k)V`YmG=s_3bert7{qvZ3 zt^O2Y-?u)*bEe$9S5*<=bYsBHrF|8j!F?+e9~~-4rIqX23d^6d73aj%2#MjQ55ef0 z?fR>8pPTX3+~p0t()9Ylg)Ffrgz_k70c7*#pRa#8K{J-?ts@M( zOa6#v)mAoVK_=VPjjuI3Em`|8Y!@RBHC&{)$V&zz_gFEV63usJ_0%tn>!;8(aN@LL z)>oiV;RAqAX;Xz z|Dyyo3$Bs!%?!Q_lFcsNN@g0+O@E0?4*ws(1s;Q~?a0@bO4`EYkl=bjk8Feyuu{z)O|=QWq<~8&q}eG}Bq%?M(Jfi|4wifDlkXtqnm286-!i7BZSx z;E~%l1h5exAiD^fS z#X<2oD_8#Jz8R$)gPkB-wO_utkv!;p%P*J^E=qjQE+Iz=HC2x!9z9YOAMBxE89*hb zjb%~TTsBZUFt5X|FFlLYcve5`7?zwI{hDmQ3FjKEOY+KCiN+ zXQmZw+#x<;zqZ`(b=bno9LHw+uzbQ0P$A|vGkf-49sCi8#*ooz@!@smGcUcpkGuTT zf4flSXiD)-2sMI{nvHgJG~?M0Py3*v@MAX~9_y-FwVi<8cX$NDU|MT8lq4<(l-EKW z4o+Mn>iF}&*Drp$unluoFr3I?z@K-TXbK4GUPWe){>S(F)Rh<@PT5q{V&T(vR3W$; z?J(PCzJ4s7;wi{Wm-Vw_&W}0&TvU{Bx8iepjF^Z%KRW}^MO{!4 z#XJ&UX7@c_div4NC|`5fe2Lmk*M+K3HHU=|JQE(hOP-To^7OSB8&1>VKyEck$B=|? zT;cR8*(T*?D)#cu zdHsk#YBPfD7#YJ*;r5Ji>WcacW4J}ZB=d+@ho%M~OZaeIdbodctc?dRE5(C|;j?(A z>9Y9dYC8JnYW0|F$YkcI0vD|SGUh7WoB7D`+e_aZGq6w|GeL%zSqdU4y+MVm@s71U z-(rv{_duZ7tgJfSylF(DBAH|6^YuX!BM3eVQJX3X0pO$~gO51Fru<)^7q*vj?ee8B z`okDmkfTLv;#fS-olkG4`(oGKPyn;BUP6;# zVb{Qpr=Z6_bm%~jnf10OcEJc-Jjigqh$k!=pN|DJh6Mt!L?5&)N1O-P@%9XA%V>$Y zXmf4yq$7ltx#+mZP+iBF;W>tfw*%CmJ^fifPo1f)C6T5L5-vJo8oi9gsCpV&sD%bT zu*HSaemoKQRWSJ+#v-l?qnghC0}NKx^m+6+g{;96%vC9THIu!>j-=Z{NVE->yPmUQ zbQuy`%A#W-xCEbw8-&y42sK90wVt3Y=x2JIHaJ$BHSW(e{RRVqn9{stXt`mJPJm&| zUbs+-k^+&5bhPtKK@N?3}975tBj<{|$<2E@4LzE%eZgqiHGV#U&Ef0{H0Csc5 z=d>8wW~gVfGF-YBeY&}w%uJ^IyWX!%l*O#}_VzgF>*euTc5T{&>F;XnAwRpjVurZI zVv0W8YCqV{ixG6N2u{9IWQrk&i*bB3%#Z9KJ<|7d8!p=<*W-DsiSaZ-!%bH1pzsO5 zJy~FqJZ`_!9lE$)KP#k`eD`g2!&M25d`-pw7uk zzKF%+eQ)8sL_-KRuFpWWZa;QUg?VK7Z?8EH#cuNq;B-Le17!>B>@ZC#ce-=P-Tpm0MZ9O3Ru71wr@w2|N`bdH^qS)f z8QETQO2b2J`YxQCwQ|O&3{f*5X;AC!_QTmZ+MCAGN~cZzQcm-W8+fy=35+a&hPaK3 zCsa>YW2H(Q`D)?8*_)Dqs-VC~hm$Cj1du9JkP1bXfH{2|0)5$l!OXVP+erTa9EgYA zOKt0^fsPK0;03T)~}et)9$7isVck`OvrrIyQP3YOxomn*Rnqz4p3s# zIqN8A2UP|p+Ah)YUC7J!OAVzzXS1|mjaz$3uOsE&77yEFELZ`v$ED9c?$6%O9z@VJ z`E%{wUPjie5|spApbY|$yo=*5ep|UNqVP7j9Zu3w3UDCv7{ps6nrR7R7c?~qfIUc*l2EQ&_s~;H#CgSpI|xl7o+N<knSw8vi=^go$an`+2^X?rY_L4<{Y&Ly4)=^k?9ZuDE*xC@{p z%opi0e)+|~6+s{Z&H=*F2i)vqZOzXr)!;(QQj<7!B)kQ<5mKo~q~@7nD!xy;wO_@sP<*;1TG9jA3@A=GO9HEkD0}}NX+!i?$^c-nVNT5(ePZ7@S|#G+-)5Ja_eF5q__08 zl;kgQO=s%3M42u)G^QVZ8%(N&XR27m*Sl?g6eaFiBAP|P#*51zlE&mSdUxHDNkW1OIZezK__ghuct-VFn?sR-@Xlj=T||9f@fsuWSN+xL(hX$k0GM5n_<4SaY!UxY z!cxnvZCd{#h4PXQ6MAt0N1fYmW?g0>YB+WEEj3eH=QvjpJwMQUQgD1l`=0WNcCUrl z)ZS%eV;YpD`w@m;+*VsFOQhVo3VOb`x9v*`!2Y|&K7rfS;2G3qwas&N5xUUm1z17y zrDrwfqw>1H_`9TRy6REV!`S>Xcg0a!309w0KQj5=bYx@ z9oJ>sK+>SF@PUNaSd6NGQ`7a45+HbY1=ir^o+1fyjXa`>ght|Sup&30oyi1}As(09 z=5+|DZ)OI&0m|{U8LtlX!|~|QU4xNXXXxM0+6tJ2c5nko7=wc|L2FoYmu?uyf^$aJ#%uRu*l7;_#_3)`e(0>2J5|~P zV6XtQ7&;Z3xC$u1)_bsq@=djGsw_fW38HS^w?o+#{w=ik!4B=rKWMy!WDnHF9d(!k z6Y)kui7R9Ph}F8sWC7@?PUDN8`!mp5Y%=H@R2v`7_V62`*9!tcmzjeSd4 zq_xqlvV}f}AfTOE$86Gb|^cy!f^wwmAA3Ft5i{oxnr8$78hxD#<#&-uwsH}xjaz#ufpXOeet)aEGUjVcp~Yc+M8;KhpY zT{t=KZeQ=7d+69^<86#2_8%WmRbaA^G$HLs7eGPt6?bDG$7d}fW5o1I)k!9IS)K*88Q^?m2){aYj8NWn&dD7GYps@yj*FhwMX#YC6q2IJz_-`-C zph30l4nko#q$e$jZUxx6&QtUhUp&Gx|v1?6+}vfI`8(}J-zj}GhnjcG%MmnCH90AR6rCbB+VJ7S4N!f z0pQCcf^4V(5E5)I`k&WT)xqexcgJXURpp_~ct^;VUDMu>AcU4O`+UwSG+F-l)xrd_ zuF`}aziy)IAUM+({c%r66||1t2xga-eQg9&no+YalK8=6#0Z&DGgseA_t!>V)3#9N zQ9Kl zv(Ku_*0pOW>iLu~W&g_TXMs&>*eS-;$X1`dCx8f{|7U)#We2&QO3m?ZZa(R@bWnYY zo2#`i()3=hhUiLz?ZbY|1SI3NP}NjZSKY8U@>syv$*p189Q|h%moU6vN1}>~UNgso z?{0_)+rXtvKy{`Q7qBcNt>9Q6pr;s#fVlbIpd|zW4rDZiQ~K*4pl{CoB2*WHu$~}7 z{&Tu~kp(Hj$BT_Fl0;F^#B^H;9YR>sdauXA|C>W07H z2KQQ=x#-d@*l7}&6tD3z!_bnYdFGM|rW^=^k=EPRzHe_^WL#y)-K%#;6&qE*5@y#N zbY3=;Jz#Ak1$3E;&+p8>2wc{v4=MC!uAD)7hGAdI=z5q6;*sJLEXl1*Rz`aGVDOH_ z)nFnr?Rt-!XHGNG<)f-wVY3qkElJ4JI7$Hy3N5hx^BdoD z+~6q|TJPy1+=vKnr1P)#E}p$Z8R&}4;+ z{d9ZVRAnJ~b{phM2o&#+xr)qJGc^3>0`OWEH6zfbc}<#-BYMiza69yYZ0w6MX`&q&tE{C2%P9HO z{kMVNb*ExV@y=}?O&HKB;AfE6&wg>opU`KhN>4AQq~4W6i7TL|Bz4P?U~*fDHY+?KHx*v=TZTZ%zPORf zJSWVCjZ*uqg8bXbnosZtF6X-1l?C8|2W#UmJ4w7qf!9r+vontlu?dfo<&*RPs@!gW z^G!~x4Z=oCi!IkEt3O*HXJ<%cVaM_I3KKoIqIF_nnmo$%2%dyGBT{{<-qk$3`8fvG zSzANoo*P(P`Ot~@uLfF1M!M06I!R!tA5jgo%Gwxp;m_0CbGZRsEdsfW&+#*A4)7Z^ zgp2vFNOE|z>Ielt0CFIgGv3C3tqr0oP@XJ%G?4Lkh(1$GS;Ak=L~_89Q65a5XEB3o z9i~ZDmX~1H))79~9 zv;L2yvy6(eYuoTJ3@~(ecXxM7OLsR2(g-Lrba$7Obf<(M-9tAD(k&eW0)F$n-#-?= zm<8lF54>`T7V(dYGDpAqm&)3K@5Az?KX9-LWt0# z%gq%Px_9~HyAPcmU;hEZ?*tP~z<{Bj7G?IOIZPw{!tO19zm6nB+=WkSKmSoZ~AzjC15qb(cx6sjo%9aUKID5W=!nT7D4^`vb7FqkZd9XYHqU)wtO- zo^m7A#074U_-(u!cn^3NgKoVl5L-JdfY!tH)Q>zO%egqdOP}_i2|SyI#J_AA>7Y*X zQzJ|vkD~BA<1)2BcUEYVe`ehZVj0;A;@LVEn6#mw2twbb!rwXj!Oe4!MjR;;rm@@z zE!E(FfAq0vh7>lAp)8cEjr`FMrg3&xh;g=ry#!|mGliD6(~^HKGq37LJoCS1Q?2ZI zgF+GTpv)bJbOJd^`P_4-3X9E8 zlx212Bxsd1q?9a7v>j8^1_DHt!e39fXQC4Y(*_%WftI`DhcBZ3@`G;*;%zb7F{gG?$(HS}s(qL-=ez@i;e<8HsPXU7_YEzNZ`yAt z6NZ~PIf4Un`Te;(XhOmJcnU_OOF`bL8Zj|ZnOQishujfD3}Y=C(H{Fl`B359fb>Xx z475>&j!bDG2%kehlZEWU9a+H31uaCCGHoKi-2rBRQ|zF`sT^n3?4+O`EkLx`zz)wd zgoXFsVUPYsIN{%(Oo-^uM}jXIa>^+N(ed#$7hr~H9@+^101v4FjG$R4DN_>LgGv_n z?y5*cGs!OGvB(lEsz!gmhC57pe#qmu5ZNg+s-tYvE0F@!muX|JvVAO3CKADPm z{pqzbo|PGpQAO?_z?n`b)H$WEqbHbmy)Qt9W*sGQx$8D=>b2Ojm$z;T8dwH5Dx}kB z%y!6`69RE?!&n63XSh#%rmFsOsglsEgjrVfZdNgXz-DzH>9h$LCQ8F)ELi@#q0t*_ zEBZYW=M@fq4T9|2DL7Tj_in&p{%HNqn)Dj484Z@T$|=Y_t}%kxw)eq&2phx^y{Dfp z52fQE=+rN4PR7`G64qN-WpN`q`5e4bF2a3lzeK&v{8Hc#C+feXpT*QG@NHF9;3ND( z>Nvc&w?$3*P}q+`u$44wD?2hCdM|*=m_#Ghmy1KWJ!MSzXLReL+wq>eyS4%g>VQR! zv3u@-EXqg5duehL=7$`7dDu9cC4C)H>@!GO94E}f;UH5~JMR_7F@Z5(+ZPj~r~5Lr zQpIJB?Tvkp2M}0{yQR0~>ABqR^oE~9)8rv;T;vw>7-QbDR8jTqMHWpec*O=D2;?RF z#`#<)T62JrZ@vdlJ`bw&X4{uZIBpuCFE)~MUdTFQs3tUCW{DYh8y*lf$n{gb71-8U znC9(4jh)WkS@hT#SIj)GvB0HxU28BrWj$MOCPB}8g71TE@%@aOptFR*UAX=?_l>6n zSFmhss+~rE?(IYK&eYZnN9pyH@WciV4}F#24a=-;G#%T*=iz6E3f1$rEKV#ZUz8zb zp~}tMJ4>!-zGq%o)s_3sa>}-JM3>&`TK)(VmV2y!l5j{&OtFU&Mt&eGzl35vG!=C} zRW~N0{8+@O+0i%u;dt-*dXi=oYTs+S<~DiwN%6}-|DbIo3E#60ZJleVN?A!dVG;h6 zC8po+-|mioE6$eP#dD{v#U-AZTUaw(ay^?o^XJJ%1jGXNpd2)m5 zc=M#(Vd;!0s2LQ4C@aVUU!_|h(GMV6U?y)ePa*}iJ-EE?(6!m6QnAl;KFD?d12o1M znu5v$STK!n2BiML>ISSmJusaZ7M8pIHebD3A`{=3bpq?DF^@^E zr;@^?sMMqjCU#yUt5cRXZ@z2!|M>JoffANEktJB~jPoFV*9AWoJVKnEoI5NIA;{*V z(oH>C?(al?7;Sq7i7eYncEr=;Bcew9P6=OgG21i~juI^;8U8?%I!_$a?Fw1Utqsrc zGNzi|Cg4#_!W96@^z6OYcpA7kAVM@EXYPBm(y;KJ-3>={hAlZfgI1X~me3|(=iJJ z&EW~A8>7DgapQ9x`Mx6ehRaSeI{MpRsqTc!CD=3lCfYIv7EyBvb;=877(kcp zGh>S&oB4MxCJWCIV>qEqitGYIg&F+~tPH93iKUxX$uomM>|w;`dSQ_?8a*T36QwT( z!2n|Ndp}!Vt_dU2Y(&x)$iqk3y9~9Mn0c4(8XmAVX&3J2F#ujHp^RpB2tXY<@yEwU zxhX3=x~D&P@PE@>H_L21f@HM!lREe4Hw1cMCSG(k69k$pL;*6>Q#kulU?0$zXW7v3 zd;bvLC^Nf-LGUfa_R5*F1h-zJa%BK;FdP+M8W{gZ1mCe70HT5FRRZDGjEWc6qt>R3 zG$W7p@V~Sl`~Lx=gGeZZoA*+n{G?SqiCCP@vT$X9aNa~=kPOp7otgX*227a`eK z$Fm@sFw8FuQ$OyGZ%gh3!_5@ZXz&SQu9o9+zyP(oN-TX$6&9Qlwq^#RU#J99&jv*y zjdnS#NXp0&H1Gylvc9HZljcs;pZWiQ2r+x^?H7>il>glXv`Zc$h zIe|q~@0De#^Z$(6iazoia8+>oqB|%$x(Hw6dG76R?G@PFF_L~LOOHI=UjtKF0~IkT5xZLF&duA8v;GuwfgTIL{_tixbs0Z{36+j&f1EF)r8td+7U&qjkr^> zG&;DbU{V7&Lp`0j2RW!-Lh8~gCsCYW`ouwjV zs42t`$G)R<00P4L61E`7w$^V!Y>ts7uUd}3D1x*aoT&?KuU}VAYLqL93L_og-JY}( z!~$jMYk+Jav&m)RtZ{Tq&S#u;$#oZxf1VYM{V6KS0$=7>WqbY>R!Pmul0PZ+Xq#4R zf97CcmB116xjJr-jhS0*SM|}iGqFGmqoG{7frsQwAq2`}47q6T&um|~LK_|*I^VR> z+urC{g>*l$6Y5iY^mIK46rXz9&?4#Q=FQg3t$xfc!4(qNFqv?HNiN}mV_NtK8Z_UI zmcmI93jec|D5Hi5udFJ>mgYp4-`r~@Q}pXw#nCO=S<)`8CV!MApl>|ZQZuehdJ7kv zwr+(ZaJvT`gA9N7*5cABCkwZyvH(GUxgSGl^h%(&@G}8fU=|hs-HR9(hdcm}?o}Vb zXX3Rd+bC?;JG_a>nKuw|dobz-r^VW{mmGCjh7$^ApDj@`{=Snk#CQ1NGxIrdM+5A0 zPen6@aq;}Y?jq#epYHPgg73CFM&;`~KtW4h9l_cP?YavG*fkm+0MUTx9Xq|OG>!f5 z(t9FSVVWbh`XiEwkNz=EbnFsJ|-bpZM!dkBG|XaqaT`#+}VX#xa5D~&cm zX|Wp366Pxf_v(^2&Tz!yqUMhW90fFv>P1SaVm)TJeT<(0X+j23M~0`10TMW1T)tw5 zJNdssRA`l|IKmG;4~n&{CNRw9fd00(VUW-IM`awsLcL1Wk0L;Iq%sv*g=_*v>utHNF|vc8ZiYeHVW|5=>qohshoKm%k$8Qv8;Itv58Ue z;4iwEb~x_4CJjmX+W}PUsZfvS zb9`Qp780XuHPhk`_r7u(hn_R^GEvXyM&SxbG zYis|O!KV*~*_uzV)o>fnk+`%z{?j!@lH3tPWH*|z@z~sDOAYv~*q6?M9e)vHigOxL zs8A&DIZcoUK-cP$g(<0s?_%lL{mLBXF#Ulz_VAPTT5UO#u)~di!w3{UZx?K0!G za(zJDRLh^0o~8vN(m87xSgSChGx~kJMzf8(3Uhy;~ zQlG@w4bB`t)^bc|Roh2By;ov}FHA%slB42+$-AA7TMmuuW+vzA7TVLJxOl?kt=W=b zPyqjTi+gdyjVQ87&!Cw@PorfUo&zsOoOq0796^_1d20OeSTeIgk9%U?4WS>ruL#es zFxDNFW;4%<0{Y7py%}4p%Z4};Dm7ki%y-!~0n+n(zQ0H-M)Sf&QUm!IvlJJ-MLIvr zsM&G8+e;vs zb)m$VHF>}<5-6Uy-Bt_T<0lDeaOp$L79A4CO(JwzRdboJ#ci++O0?Y`=g8j)PzXm2 zVbafiYxVX7m6i#k5=;ZW+RhgS93*cSBfHeKu2d4Sx96x&Q}G*}(fyLyrfKVojhR=f zW9ezXW6)99$JAF1CRAiyH8+!Op$XyVEu9N&9*y3|11$sME<8Uw>wjxQHC+Gp`>4&S zgt5`#`kg>YA1??k$+$56}UE`|;D$d~DRS#(`8} zdruY=o~43dKlKhh4EaU;03XBr)9n0fq8mM74ZPt}pT$Fb0_>OkTXfP$5QR+f-ZOK@ zl^s8ZajZff-Ye0D3Dm>`Ub1XE*gIxOCbod`0gw3s0l^qic!43;x0jYX7XM#Akn(CO8z4Px|Ns8&KU$8p3qkQUdwx`G=eIzn1HRoD6*=b9U z129U%usKu5oFC0N3UoQM29i-dE_pn7cp4i^Q8`kT8No^%e&o!VZkC*3q5WgOm;~!$ z8UdIesNXdleoeemw_qRg4tSoX9fHD{oiJE~AXg9*`{s^KaF$4}4t+nwhzZ*U7<^lj z(p>3*t|O(Et>Q`saQOT}yhsCLuVfq10wyG*ZK&vJ%@E)PSXnrh>g2iHYK=D~v1T;O z)J+78%)TxExJFat!Gz=|&OnF{bZ=-ZgI6$axaR;6alB@iEg_>^#WmH$bUk`|!xQ7x zh(3kv_0w{{yVdPSAI*e6;wD)b)`?t~hT;4zZ-GHS9F=$6xaXTxvJqy4s4UFVWA$R} z2O;+bjSu5l&-IK^iPF#fWb$=SCM1w&lZgjvcys=o%iBC|>atJ4!Vsaj}jJ??@v*i!OQ_ zwcx2t?RsRUdfTNs9OOGdwA4%0nGV2B8}(3!pV`}@96D;9mn3v5FPIoifu@$}-0d4j?{L za+PPM7UqglH~!Ma4M##OMZvrFy~ht%{FU(4q0I>eLejvhw>R#TFzGu{Ed2fSSdK1e zpLl9G0nMv;yKzd^*$SS&kN9;ilFOA1|GS@u6`FAQgoyIam-Blit~1`~nNv?s3NQ## zkvZbQTjbKI!Gw17g^48}$c94*LQYqW*G9mQMyI43p?Iv7^Bv-P%(-6N{ICI02%wOj z*j`iTS;g$LRdhurAv$@}V_0x;L|C+a_=EA;d`D$3(|T|d>v%ngh=$^KSPrg#3xx66yuPUf%y0j&{@m$oj-S&hXTrju&9E`0Fa#0I9wKfmKBL)_qTNPvK~z% z7fqO+g{#8Jc_|nWh@I$sLxs)T4YUv#3T#_4(3H{8q_q${k|+~Gofe4a9p3e5hA_@E zOhqkzn$rS$RkE1tPvp+IPRJ_AQ1MD!g2ReuFD};hOc4lY6yKn_??0HpD+kdmU%z&C z*g@W~gqE_`>Sz1??fpyZr1jy!`ku0=wcyVQB;mNVlDsgzq~F5MKtSBbhE&FnE53$c zb@*2Cxq{?~%$?BVyl!xPT9do-SZp(|a6yn$TsSH!A!FLE<%NA|1kdc&X%o} z%}hjGlth|}M9U0AUrc<{CBG3SbjxPjCegvhx~DBSN+1;D*r>S2>BrAdPmUnMVLs8b znrR{-Q~rpgsAx9Rn22cT8$1>;mTNyQ0bOas4B}2ypQP>f*B$m@X(T}oit)a!X=dp5 z<+2NpBmYStVQor{$A^lij_wNH7^$e-Nqhd)c~zeMrRJQoPM|C4P!Hc92+GjbFI)bM zz*oxy(WyXOC`Jd45TC#rMBXxL^U7;u>mi`uzi8N{DN#Gyzrz+sa#eEx5%tW|Idtow zv-BLZIFOI$5l)(|(_W-neBDEfXB)hp@&I1@;NqIU80Iyu&u=OGdXZq_Y^eTe1kl!8 zX{gYzqZbZVM-Vf1(fta$B%{|lc&+9O881Yr% zu4Y{6Je=AKSrfrlo!Q!l{T`NdWKW10c$SRdSS88HkIbWap&#nj7P5dWP8{W6SVx2i zz(~4&c&ktBjK{?NeI320j{XqGGm1fMZBODzOu9oxE(935aRQ~8b1q52v2h#O=M_;q z+x!C12l5dICMsR}tWR&5;88^tPfo^KH)?*hg6rj2)B|smPr2}ugaRgb`FVTUauELb z@zK0JqzaUHz`v3zehR2(+QoFW#*lb#X|c#SIFLt7a-A>nO%te&DXux0blZthZVB)z zSh$p$vGYeZ#pX^Q00N$&Miet1rMV=8JZr(MIw}@9;^P;lZIp+e&{5Le$8PnvflB%H zhWYsv<@gCC%X19@u0am8wr1BLuclgCshQma#(wy+;!y_7&gM1Ai)>*fS6cmvV+HY+ zx|GycO8e92Z?W8@0@6J9)=i}yUl?-Ih}!Neg3bLPwVHSQgO@XkOF_il;2m1&SP8Xs zQEoi{UM1+w%yuEB<0Z7C%Ro&yYgqcY<1m`f|93^ke)fR~L~Uef>3~G^Y$QqK^1)xS zwSPOu%#A#47;DNViuc?lT&w*$^d?(`K4stiYVdk|OP#sh>55TqUN_i3x!soSYAb_@>EtSJr2$Ag zFzf)>XUJE`zSEw~xak_P!^4iZoLRGEEbacL-l`5x`mpAWYLB>28&(sp1xB^v(meCe zHw&=SX?wW7Te2foAXg9Zzj?_(9y>DFVn^4WO)XHR!wVt{WC~D!%vGq-Mj4TcFk(sm zxl;FP5|~0L#x89Bx|yOJjCFI=Y|5n4DwEWkctS{1R2|F};S`Lc+VwGl2N^8R8J+B^ znD}$SxOqD}N7k;3I{ltj8MMf)gn*}J*{W9B`8l1bblSY?C6^mE7pU%9t_{u@= zN~g%)4LeE%D4-&bw8s59-3rVcW1Lm34#vS$#nI#SOV^{3iEG>@&hCuvsjQ(`z2TMD zV7-3utyU)pm5~7x@f8a*g;!T2u~73*EB50#I7zfE^vkhOum}<#-!+u{>PNto`|d{i zebFRB-7{1+x!Eq+F#vZ@GNPZCJ_pE0^A$uDVGImWQZ6nU2i;Igr)f;|=TH-LAOg7| zw5r^q{{XkoRj|gZ>^b3Ne=)C@LI%%uJvaFbssl%Od#3Y4zFpRP)qZ7-L<{&?G)c-avQQorq>N zR;p^L=MFx;5c6OF*buzhycRjXcj36>dXdhKn%4FIZv&yY(d+n(6k3hHhEup25aCx` zii_q-AYNg}h=%0*+(bvO=9MYQMi^J7Gg1Vms}{cBbf}FtZ2fNvu8oBy%+WCGO1j1n z+Tm+B*!^6Xll;4h7K$ks*CpADZSfFVO(Yi@(_W?pD7_73l)v!#v(&F8d}>6uh)ZXJ zz^8ufqZ~?!ESyxr;4C9ssmuUXl+FFKSC%*V^Qq%|G+S`!R+#&5h%#NV7N_>#egfa? zhdIA%wSL^iv+>7=pS8HCEZQ@gpTwlUOyFRmeQ2U(b#FO?N96%%Na&Ti`&z|_C2?QQ ziv;Y#1blpg_0n_{l#JnIVFnh05>b|6HQEof%4l+71ULtamUTr>b;Jnr429C76!T>s~29iWKuqVi5NR|=IsjD;PtP7p^5-RDIw^(!+_uu-uBn}$< ziipmqa-t}g=F?TaSflUMqfPT)-{61P3P&I07fO@j z6OF!;Sw$okr9uxxi_l^D5+piWq=t{dxP55F%II*lG%i&opc4k|3VQ;H8SCLm@s1!?@6Yn zt%9$qnE_?lF--y%g44U2bm5@w@mdvL8RY}C;4n&$i{b>5M`i)pPn1U8B5>XnJ+#5i z^74A*c^Y$Fy_3$PMT7^TU5JQ0JXpg;47=pgkRc6+G|di4wesi)iH(HApRn{M)D`JM zpkiXfu;ooE#xEyMg1EW~1X^||@l{*zdIJG)7xeS9@YO@ffs4E{gZkT2F71~h#@akR zYWGu8cn`q?tIZ^WRTIAp8kszc`S~BH{FwiN3 zb5a-)MgU}*1wS726JWvbx$#lzTlMh3>!U9N8EmK)G3!?#GBR8-e5ogQBNkH-z^;(H zD?E$EES1}IxgZ%wIS>2rLBFmwR?G^fUbzK~HTF|w&treQMv>d>GJd%6v>Cmm6ukLx%d8z)z$r&)P}Qyb?oNb85I3YZI!2N_XN%Pb;fPRvnL!| zf4zd>^=8rTaw#GzE-WczCMt#&RZ&M|8{7RoSfnua=pfX7GW%H=IKM(3Cg$(k^<=Sd ziAB0zPnf+OXv!IpGwHxn7zKZ$3sVAey=igp`cwA82dQz(*!gBEbIHB)$zTBn8BTf~ zp7&Q9a_#S1@b??~C1>9^;rx_dVun!=G6E}AiRA0EI+l=663J7^VlEhgOSTfHKA?A- zRS@prku+t87QsB{mP|>8n#X2KQKo-{8d}SC}8qyfh7%% zjE-Abcdq83<%rO!HF;Pvyz0t+z%87_8l=s(fRq)OsVH2lW0azn%s(=%bn>%WAC1* zddv6j-gE1W?*#Mm@aJIMV@VnEM(}fFcj!(O5r9;cMyKp~_~8qf(Lwl)S-5DDleh8> zvV@`n_m@HccATwFC>8A>zyG7ertvO5IyrarGjm(t(E*N&4Mr5IGYGG1EAah4fLxuh zE?EO*Ao)p$gm{&vl+Y*9tr_BzoKBdfxF{l?vxsyoZ|U?&plFUrwzoz^nTwL{T$AI- z;N+GA%#S`4a5?i%ymrDN?y5ug4Hj!wkSw5WXwj>?Ffv^Gr=~#08F|OW$O^^T-{x*+ zxcvend2fJ1JCr(dq!r-Ve19K6k~{Ucd&E-MI+=8WP2U-?=u-@jt>_KQUOWLtqKwkx!z-{zA+D_JlEU0&(FXckqR#F4pG3)E zVZa;&m+6B+21dgKBkf|Rl@UNS6Tnu<`?#t3$0v#s-1?Ea`Py;61&^0!bERo1Gg(n4 zj#}{|0GCU|YMZDUV8_t@agJ<1cOnfZ$hj_8{lRj0F%&V2N%&IR- znU3nOOF!WUGOG;!q8+g${H0m08C89Ccyg%}Ss@t3k+$XWHlbj!Fxodh9|}>5@lRr9 zvP26AZ_!BKhSm$==3xs3e3#tNbePtK!-%Fle{w^0(PWV7P(i`ZAKXUdy^0$@+(i8{mYFB7-Jz3{rWwe8mQP8V;<*mIaH#kuYhJ* zUF_jD{y9FN03pn&eO~CVYY(I~IY7CJp)l*R6E&R;iLaT>Rc-#E3QWZ#>kKl|dOp2* zfCpklf_=X*Zx)&p&52?CZTOn!bG@hVpnDON{x)3x4LE3g?IVBvSfgSxp&s5Xqx@6y zXeD_IuHNUlcYeh0lg;ycl%omYD(X{P_K#)Xj&W8;#<~h2i^78yj5{-fg+$|#_G0Y_ z{!zs?HUI##>I`VPQ!BF<^)I@{N1$?f+op*IybW; z!Ae#b(s&OHm5@3eh`Kx2Y4}Us=ZEJ6?_5pzPYzjPh%@k zRykRZdB^<)d2WH{Y;V=F092Mj-b`ISwyp-lbkPIcMLfs~O{{ua>vUMrgW|;~IyUw- zPd`m?9}1w1ywa?qP25uPGiEhKd87 zRcruQU(s0(2}G#Jm`uzNYzq{XZE>M{D7)~*K$Sv)8v72sc3Yy6$CHQ||)v7zz}| z#tr_?8@}n-cTmo5v>X%fm}gj1?%;tchlc+W_64sp{JNt#6^9Lp()j~5d#7@fhwpG* z(=Gb1a*(Zc8_bTVv(8(YCJM;pU^}?4cys_Arz4Hck)rG;sD);dyZ5!@`D*t1e5$lrWBO4w=TS zZEe&TI;U)>adxxFa0R@7(qT>IAV-vP8};133X3F>kQQLC0=zoCs3S$b z(a?0(1I@#-h7k6bJg|l_F})EmhMmn*{IP>Y;K*IVIT-WcCebWRI{cQRwo{Ti3g)LV z;cQ}1n3;6vqRd%lxus?ovF#0((ho&8VS#m3SCF? z7J=t|nKGDEmOftXO1Q_~he;<5!AAV3rN2OX;1X5X1-Ezpjygb-os5ZW1i2{zq0WiG zaz#_3Sxw+ZgQIx@HP^WupbB6dH}N%x2MAcF_wkjh_++B5EcHgRh}!BHhx(k5MjT5w z{IOmuEtmY1E?rpbV1$?ZHFkm*#8;&w3;qp>d}&ti#IPf-cf73*y!-=OWI%EKlsDR=F~mbI7)sH68rSVZkIIvYZfdt>tA)C$&ObT?Q@q3NEifD-D>Q z&Wc9J0mLH_&q|jl!}Xa*4-cC%7Nj1oBG3t0#KS(}Q;b|WKAm%#s5KJ{M&ArC>hOwu zuFduYrAp4B;A*uwB&XGtrNw%1wjd|9TRr?(!I4$C zmwYhqWr)FY^v1syXvpeaGbX$uuaql7`v@1a0ef@PeQGkg3YR|3b6zL_`wH=?tvbq) zEUGPv*+vf-vM~12?OB_bTM<2r+Mb@)yn<&MI+|@xfIzomyq_eU*}Uc7C)Zq9~U5%8OmQgAI|r0#2a| z!i61oCY2sKC(&FFaE7Xa6+j(PW4Clo27y3uUFyC~Uy;c;r&BKzfq+o17+Y(PEhd!% z0pFNu-(!k}Vu1i9(}N%!fNGyrLXYkfo||y7*LZE`ijZXdYFH@!^yxOQkoO&Y^k3e*4k@eLdW$)d1Nc zk4M2i`$o)DZ_B4#M~{xPj9KeqBSi40J!--}Ik<=|*$H4rH^K7l{nsY$RCSUz+y0LQ z{m2MJwNHQV4cXH10kN@1zm@3H>GqTNy@F+n%YRSI>4V$6PY-Y3wud(V*B}s$2X_=$4cO-~* zPIS8fLb<(AU8osdfliq$P>ZW6llVIEorp3r=<&RHds71e%Z4{49pyL+=tu-1iK(^qUEU%S?n{krrhKxxSmA90SZqZCw;{O1{s2gP9O2w{(=NI<{C%R~jjgR4S ztw?`NBH7Sn33Mi04OV16xf*T8hN~#5W*Mv&#LE0R1u5hxLAB`a8hn~BHo=uPnQ+K$ zS^oI|+?NV3_2B>R`O&BtT2zyFhVAzTP{O(ys~oKt!J>~>^uUJBTBD7iOqUvZ?*1wL zJWE^4;#^TH+&BSeF~avdox#s#aCPACfo8Yx8h80_+;{(NRah=Gd+Q{n8bD^cp<4KS zIh8Ea6IdggA=7HbaLwD6PsPog^&bZ1`B%ucFTA=?85Z#mpcyMg)bSk~oa1>-#eR9f z#gp~2Fw_6>n;{q)qRC|_DUqm3dI;bck-+{fW%}5x%59WXaMFn_ zIBT5V9IopnksWM7D7T{Nx7!)&7d(J**HyjH4ndi zwHBP4ed?=eB6k0p!Phf{m-9V+lEo5g;m=2gifrg0LVp;`*I{u zk$}}hq$caCh;-VURB*a+4O_KRWdhnV6m?MlLRHB~5@>jg4SEMZNQT1{^1iZ{?HI4}HRS zNjnXo>s;;#IEgX$A-aHUKhack_F1v-MMF2ypP81MiJu zeoX804~kVCtJC?{NMysAFR>TuTf!(&R}~cMG>FED5DO9<0NpehDoreol~Zo^ez^WNsKt@^g%zf1W@0O5t zC~58%qQQPg!G1@y8H3g|Y-JaDymKIns84HV&}>~u<=A2K^MLxYl6X|emx-M)_-@F` z2DOyRf9wjLNgZ$#(&ddxii$DF#If=vMlqtZRXo*frA+>VZ4X~GVeEGE^AFzmgW}aW z9B^qM-c+KEP2|XM*5ScTAfGbtwdjlJ-T?!y2tMe$0sPeoDI!1*??`Geqn@Uq#QkDC z$TKbSsOFu+HTH6*B_6C{D=A`A&|}&?Tta(Gie$HdVmk2Vm_qIAUYl9_$s`B-$FzKL zz!F$9J3!6P|KSJNcHm)BSH}oorkK0SImb`k5wXvS$B;1N!-x{VbGN1FJC?%)zBoFH zzh9@CaP(;DCXPO67L6AcxY^njt&>PLp&H*Cf)AlC>)X0&N}<~3!eg7rh3ah$5S!P^*;h9uhS3f!pMh+MGa({mKp*L}Q_5O3VDAl69AtLUB9Fl5?Iy!bzRndp@l=3IgJ}--y-~4RgPH!miG~`8BU~OJRn^#f>yIPuueS%7z7YWY=-> z$39C>!c?+E@Bvg>y9gUyFvO4!mq9Mn?L>raOm6Oy%U+bDkM7t`VircYVQ?m2egP3Y zvXg3~zTjnl$uqQ?HYLQwa4N;HV59CJ898px<0WcFQICko(`ZC865Y7iM<^^dwNgzb zKEmG(fiw7eaYjDa3KxtHjgAZjcrwm-dN>_0MDpN3g~s=7O@1Q1KzNvo#PN<)Jd{gt zif|8pGs&j3tt=`ippmYu)ujM$Xc@KZ?7djnqlw`Iptc^nfuRYnom|$tEFz-H zuMq@tczv-&wrU_Q0Ps=)XjetOHUFyIj-yCXrGp7Tz$LDUu=3lminI39t1xL^aFqOD z!;urKF6T{4gI63Ot4YUF?5D%kYI#R^%vXR1v){p|-|xs8G6zqGU&D*_t(e?8gM<8h zq|>1)HrIj#Fr^<3-j~q0Bhj}ukbeMUs)|F4xYgcgDQ`&D`sTcS+z$#@E;5@e>Lo;K z&L7(JHTUm%c^p$!HQ0iKBXYGHF@R)`qXw4<&m$r_l$vaxp5z{cwn@DOQ7{J&Xns21 zn9uYUoj3Yohe)z37dWf`V%%|$5o5@<@f7VJoIW)Q)MN8G!}aAu0bU}?*?lLYn9V6L6*Q$U>> zJ1?7*HCwUu4%U6sTVnLd?HgT+ohgQAipWskH23XKz-PqEd@0(W)AV_q`Rb8GT7v5# zNsrgU4g23P1#eC=GKP(V`El8l8LMQks}ST$XobL}wlyT#kP{$A>PdEwx{Kxhr&bb; z!9HMrEyF1_R>9pO*DB=p;%F4HA42UPGPGV1XN<|5>u4-s0p70lq+wB-jH}t@VQ0;C zbJkb+gY9D+^p-gBTKa^7^>lnjl0kXJ5`3Ehdz@(({8@mT!JPA`&T$(I(LBg+Rn7q# z`IP$C4+SGaOOw@W=ENo(2xw!l%7`Q;L8A2pv1YnXWWQA`diSD%Dpi00&GOS!gEu!? z2q0DlMlFPodPvczx!=Ub*bFoRktb#K^^<0AE!seO38@0rrQaI~7&gDuhp1-B`qMQk zV#aNTeIC8|*iU4Zejv;dR^(%`=f+_c$6PwBN}s%sNrGfr552;aExpaY(*dRRJZD{X zf9`u0-7!SEl1A{1%nPf#93^)8ScrYP{?Sv8=&1SDAq*bw$YJ9x9pWO@Xe0Ua1+^J3F&8seYBDw+%tL{v|lHiSN*o zol`)1g&phP&RIHD?z9Rkam8ehy^ZJi=4b{z&2K!(wU9hY zG+6i-`utKNj}h6I5mox}hSr;03I9VHO`HrFNjCaVW@`xLOZxZ+akfqA$N1e&v-bTR zdt@pp?gJYhuS7Ek>wG>6a_9;kNPHJVfcm2Z@E@S!Vvve@c+ABTw}8PDB_`()vS8}~ z6AmjK*-FGrqf!B_u9;1jg~TNduYa?=BQo|T{j3|6$V5CDmkzW+ITPXbc@}0edVYAV zjLifXAx54HdgRTO&)ILiUP)8FH10x2Chl#yHqo;JXglN8-yHDf56oj&1(Qc!+NS3l z&Z0VJQ~5|x!XTGXeTn3g9+2=?s>@!0$15P!v*PkREqyG0M2Mo4p@;1;LBS^PbM5g)zQG!$JEY$1J>PE z4tc%v{o)*MU>BZ@s~zOO z;J?CD+A^3=dT88Zfp5h+9@G9dBz9|G5pbI!)8E7BIO{rw-Io1$5W>>&wpa4+a3znK!_;H7!?wC(m*TeFIH z__`Hpm0+WI!`uf*^XK9}Zy|`09#W(^JEYxy$Sv3?7|F9c2to8?7=u;}-je4oiU>mH z#y{Y5NbPS5|Fwu3nEmC9RQq;TL}yA|$`TwwOMd6mfGaY|(V`N^l*C2EeCi<-mXnoD z;VH5MZ>?t?&cc7Gt`OjdpFJ4rUe8fT-i?>V&>)^fS1mVIgKt~GJIbA56FvD42r#aG zc&-6!{vjmt*FiwNn=N8w=J#v9;YJgc>=A!y67O|H3i7d$p6}pD@&a#x z8`28?8NM0b0=Iy}JUqVwcn2q-99t}n3Ud@{9WEFY#)s-3FF26QZk$s- zc@eH%I;-K*kPf}oQW5JE01+ZE(S#~90EXC0e05x}TQyEKB~QC*L27D0=oe-NHuv2# ztv}vcg_n&Mxx5J&3Y&yi4`gIRCV6>{PTEY!i;oJP?&H%KzAW3&q{#DL6dO>Kqb|H{ zivTbo&5WCWBmTA}IQb8Nic8R2Kiu%DBoES7s1L58ZVO@KT%@ga0tU#o*`C+^N0ZCY zR$+4u2aZ2}3ejhPa~8^&xK00D-M$J*pN|K2Ze*6xb>1pdrb+r!&}xkKwDnOzfua&sYh+kry1! zAO{HJ6N>)wGG`B9ZuI)G^z=rDLpg6aFsV0{Mq+3}nGbrt70DRag`K-i(D4rW_4Sk_ zX%D6xODbkmSh29b2IpIHk&<{l>s{%s>XdU;Z2Mta?J|^3N#&GY5!Gb(^UpiOncNqv z_!@L+{{S5b2(pq{=Z4(l=`%Z-OQQfpS^ODk5&YhTMeb)g|E7_hm&~!Yd6H@7=u1q| zTpp7JN@V)4L;clfGvTu7s$a87Ly<-S# z&cPhY#d2lJUX@&~`WT8(ke0SqwUo`y2^$ps%b$Il);I(Bq;BGim<>07e*VOdwpyh? zbFN0_-kYJV)(EDF?a|NCPneNy{5#uEh%wPK*-r@fX-G@Az2MJ-8#VOGvLmGx{{b@3 zGQyI* z=$eu*dU5hU8#ckoia=xBAUH^Me1A0-t^@sR(4+I)_wAlB+JxR>9FopooS$@f2zm@! zENGP!9c;QD@c>%~5TFEHg`|hqPDrh1MQks~2EsKA8YVPy)5xvfM?6!M`#@r2O! z@efE(c;&ihOO`dpB!_6Nme zZrQ4sh@^;F%%sGuli(bMA{+3a=_%HSrXP}UB8aA3Y^slK*b#F-I@aeAU*;Y6#iYT-h$&A6(lv&i#N(XfO zn(MEsY{m5l!?!f(VHHbKKxsx9r>iYSb14f4xm`CH7us>bB4Jqrd&u?7B;c; zKY;5X9P0L#b`UF6LVt5a_XbAJyM>?W-AXi^^be3Kv1`BS-q%3&50Lecku)$4KZSC) ztZ`B9Aj%dt%>Mv0<278ti%s!^SNX+v5fV=AbehT z!bxp{gI}{;a(YOL2IuTOT0Js#^zj1TcqoG9P14d3!69%CHFmA;5~bMRYVO?69Jz4J zwL64bFkR`u&le4;?#F%z4c3#-qQ5tp!FvsfhU$9SK5($uV+{$f0Pg$=9jKFgj<|k< zES5q(TL`n{;Nd780H70tR`4Jpc!|Yj83@=B+7uHJ)CD3R$q2B^d6kC7Ovu>Tu$rPp zf&P!BvkYsq>$+_c+}&FU?(P&xaCeGJaVZYP-K}_$;ts{7P~4$daVhTZuFpx|@BHPu z!jBMg@4eQXV~ps^t3tqQSFEIlM!Ep0ef_t|vatyQ6hQDunHtfq215$GoF?`LE6dWf zMEErCAymb~KzW248*m5e<8eZiZd}-Xu1WT#cnG~5-Q13fC-h|AQo*?(FBhdFWbUW^i z;EqJ5(vx!nW6M(ZhkPI*MDVO>ULF2|*B<-*YQ-aTw~l-n6CLM;HVW=p6S4|C;743|t%+^9E{idO^O|45y4*f$w@*lf*%wO^L#_e9HoLyIx z`nI(Ch|@DQUsS%OXDRAl+?BPV18E;w_u$Lj{Pwn}I+KVEz+hAjbr7wN}BfKfSD#@RITZgU3AK!Cf(<82( zGjW?8tz|#l^E~W&115T%_cYV_ZTm~G4p(=7bStac4EOU-N31M`^xu0H$-HUlN)a&e zNfcv(mrul{K^k_?{-~wXr9@!xG{z}7$3(gxZpw|QF+1jz$ij6oLzK6VTld`{Sh$7w_f3q{S^H0QK zPQ<3-s^>R6YPPx!o*wHaa2jw>gR5nM&=-cm7ZLgs-sIvr<{UuM`8KAe#OGF-aMB&$ z`Bq0Ik2x^vJ!w3I=F`?Hzw*NVf79i0q~vcjEBp*NQ1cMbYGEuKy@_t`x2f|YH)&?? zaB4>|i0B}2POXQGRU;1)wZh;Zn;@l`*w7_kris#l50I-3X1ZahyuF6RqG^{y;Z;eh z8E+}v3&8{g`Gm=H>s_q|9VRg~6t9w*j$(cB!I?i?cYNJvTyo3e*vLz}UtGf?QP}A@ z`}!y!C8tLKdGXlyzk>esIIV$Q1fO9P2*j;SKN(*!px54pM{@coF*SEsAfzlY+}XbL z{_Un&W30ViS+)?{YkE35A&`>*LLv`*ulo7T8cdAI4Oa#4?WvU3F1)~hv(c#1V|cV! zT5$?Xm#UQFC}dnv42crH%9Z>FsC#HmnJ-ScDoPiI_PpZ`rAq;Ej*z}DHu$p8}9w4R-^6AJ6GHDZ!m zbk0vppRChxjapB`4YQrKHJnJYs3$CeZl6A~ST9R4RWBR3G)x0SaFeGy>=7`dP294M z`oc@e{Ite!iAYma0sCZ+UgTs438rev{V|QQ+{I@o!oQ67{gtrNh1u)Ym>9buwkljW zQnh@f?IE_g+-Dp$_^g#n<5If=nnZKryO#h(ejrsC!qq5YFQI>3uG^V@9&7d>p4 zHWh@5D1NwB)>atFgUw`VUsDldP2jhDhf}06l{FjyGfc#;;1&$mSL-M0wVO81ud|pa`b3pU>`%UD%27Jc&}PcH4|Dh z$>E}qv>RphgK8%MoJg(la|9c9>OAap)%3DYCXsmUK71PP@slQ=`y5I6=z+Z5)6Jaw>Sc%U}XG=++w$$P=v_XXq5qZpX zb8D}`vsayi%gc+iLFc+CotQX1RDnW2XUj{OBGkFT^TCt#^NX?*9zo#J9(^7`F0PpV zlKjo+sjn z$G(f`Fz7T8Lks7>&JoO9(Iy7bDCon`)m!f0X2aGy54%9ZuCW0s{cZN?!XMZa$UXh> zB(m;?X={d%(q+FThRzd?H4~b|1IW32Wjv2BDF)zTd>t++47amokT~PwO3hstr*~U? zpvmN){si@9@g}FiNlq2xj|N|8SY4B3>yr?G}u1=wL)Eh%1liI6!b&!~$0B3qsPKn~n|dcDHpmAD$+j6O1#mX$PU;&N( zVM$Z#a!Ha$G2@k9>~!iS84HaLE`VEv`Y3ujyh-8y&3`HZ2nMQg>cgVDH>$Xnk{@&4 z?wFZp1swfTm`rCU`lfwv4+t|AUC}W7c-1rk4*A}prq&845%tK6c0uXQYRw%}&G4tiPWhANM>filRVKYDP*zwx>=9Xy22+N|$lSiPi#(c99T_#k|2rf8nO+zbkky9o zU4K=w*=tj7-m!Zr&DR071Zt6I%?{IRIU7(H0e#+_v${maC24nA2iE#d0lTKN(Wb(U zC}c8-~lRdxP-(dZN7>@H+@meGgO3=EN`-Il7ym4vRpDEY(d*-jm~3^^MF#iyUG?ZB^+`r*Es z7p*aITRHr-{>g+FjAs0j+7y2DXAhLOR$ps%bZlyliTvjF}_ykA(?*d27?8006cVCe!h$r zR0#~_5SEG!go1`K;Fo|$at$YEFi3bFN>K!d2%%Tg6}_J#=-CATIkZr7xz6(78PvSK z4N!9Espy8448XZJ8}b^&k7`ksL_@@NLf?qhdH!cgtjv7CNC76`>E*)18O^0ipPLe0kJ|F;U_$y9$XWsz$*b zjS+Xik1o)b^FlXPyeBbPT9G3icdoxSc%;s0bt@r#<4J}Cwx^gpaCnw2DEYlNC z`#HLDd%NE+McRM=2hdvjN;UYRjBfUq>ZJy_1})0HXv2Ci+U^UyA6-%$UE{cLcD^R@ zRo{X$!(+SWk&Dh!q(cTI)4NYu%I&2qjfuVN>pt%e(oNLf zV>s%{q*1T`t_}H7S^Qn;u1P_p7Sczl)-fm|EbSagBmPso z;@OLLivL>(CPYd9y99QI+cM(QF97x`%$Jo@Ck6gX6KBKdjt5R78NKj6yx1zMz z#iOKTs8(Sas)aYyuY@0_>0j)=Xf9aRGif!!u=XG{u=FmjW&i*a8mIMdV+t|rl&12d2oShB>7OCG2)VyJ_3?+B#%Pq9JvclwwZ0Kq1_nxjWOS~;(%3}nn=_zKOG7RuRtRcM}x zAeuF!2pyH9q1_AE)o@hSDf{-Oz6gPtrZgk>?E^l1lRSvo$efsR0-J>ngV`|3z(r5i zrYt&MY=<41KH^GlV*x~fpeiJe$m+_{gq2q$Tn-OmlR`s^++GV{-0$_h23(FyofU|= z05-CyB(}K$ghJ}7H0X`fvv~uHaQ9)Mr&?@F42$=L=1jJ>M<(a15X;)g4 zaa|2Nhl|+S6<9zTG4r>hz$CV}>l-c%NuS)Jw1g^Xog$^8uRf^Rwvl$b8uMrH_pltogVVdKyI<#h*YaICJ)(Rm(jvljs{@JWZ@;UR4=`FI8^^hFz z!SHfnQ16VRZ>j|=#FIY$x?U-UdBet6Y>Ql!r(QwMYA8)U4N($Bcpn|4fZ6Mz(O+9{ zKoMuUCBXA(lXtE$d@qqnc$i(Wd(oE?pv2$rB1#@QZ1@|8Rij2$$KYIG#xGGexaZEtvfRi5!VM#3iN z2HI)4*!29bGt{|r^`7-fPW!!MN;JJ*aw!j^ltY~LujPGz-ahS-lp~rGrVV%ln+s0& zZQFkRb{5@r_F-BnB>wZr-w%srip^ZNQsxC?#375KjT+zXZ7W8Qcy4YWYAB3vS~b3u z29r$C{oXb)RftI&=-$Sp&N29Dh3aJ4$7SjAL{3hVJfhezOiN`Nn7e-8_1)6iskvz* zBn=CP7waLYY!+veTcNt~4bWm_7W(05x>pw0P($>80Obo?iK`uxj=Ug5@?LtKzeIsA z25@W)xWgeCJ!DESPfrkncubj9JR(TpJDp^F*}_>zVU}#KmpyH~@Ioo$G5%#x{aNZO ziVL@eDDXj>3!3(}y+t3r)Tnmt;#^Xkv}Yn%3`Yl`m4`KMW1*pXYvEyxO$bUBkB3kq|<`$P`$bP8sYE2lzQ zSl624yVjAN{CIOCy6Ym3Okhm2DjG>)y<;wg;eJ0QWoDh9f3#KwFZIEnPvhgMaRrVP zt#0CC`3kD{%`v>LZWV)4Fcb6If+MXp)lB9{8PKg9A7kpb{3DbA<^WR)d(ZYUyUK-; zQ&Jrc&qbX27If^djmRZsZIY3xIFuJ!dCo_E*3KB9j&(Ft=*xPfdyXhfIBb(;zn$^> zlj(8hw?g5^ub3BoXdpNTU#v2+14naYJsQoWQe#6UTtSD!H5c7tMohbN*QGwH*&MqDcBY6lkaTXq z+vO&mcN#A}co4Wom#c3V%d^<+p7QjelZ6eF6^eGarvES?5#4eEvu^w1?sB6qvt&#y zT?JD20CE`Cbb*NJ(Tm8Ws_f1pOZQ@nIcJ`hhzcQ2u_Z*z`r|Q=N zbW2OiN>V3PG9yzB13bRQHLg%nrL3sbo{8DDL4VN1nHQa*Av&yTr;>E_Y%s<_JlK>c zn-@u{iu_b#NYh^5p0A1fAHZm<`a2;`FkB?~n)GJo&frrLo#V`-!BsHeQG(JoN426D z8}@evAXTc303Pz^S~8xnu4?s1!9vu|+%?8Em!lG|`5*!*@Z-Yw^g0>>bV8nuzbLzL z?0zDzFyj~cx`NM*rlKl2q>@Fx>Pa_cc5%=M&aT)upDGFcyhvr?H*^uY3p1;*iq_Gd+(R%jg-}=8FNJh^moJRfX%w?t$WPy9W zDz>ke0tdKbHfH3aVzr{o{?Vs28#&7Mf6F#XWRj77lCL#&Tg#j>$L(5PlHO>$p~S|; z@Q4NzCOL|xXu1SW~g=%c4?NO~O*`IC8-b*_hWoG&YDRf&>2{vBaV z9OaA`CpjrolsQka%>#6Yl%r)SK?N=*q|SvMCH9o5DgW>S6O^aq0YZm~XUpUylbiuN&{rxy~#nSyJU%N+68vZxff=Y;o*1`-o?YhZ`d zVj#vFYrP_juAMAan)+2}Ey;Jmm;F$`+xV5@1>r^LF#UlVOR&;OnTTv3emctXKY+$i z#>zU0%2N!(V{w{(GWz&+fSnRg9^NW>p9Q8$gRdCM_^tA=fxY;dwG^RPkL$I$3d-ZOlM;k{UR z|6eP!(Lq#<+xKE47hVyn^TJZcdr2vun1402eP?RG-4LRTu9zO{`ipPuKiD_h!3;0M z5QvRAtb?s{VzWGf+{nIiclC0sLsiF2)k*E9s``ce$bWwVhBLdp!_g@#JPG=|KgGUh zJQ>4e8#7C_I^Z4sx)C*|fTHc8a&bqOAgLSwY%{ARW(Kb{>6<5LpB;z1-cgb8znZpj z>j!qn!NYy{kI40*zw)J--1Skybcz3X2_w0zQ_!g`(oQ(f=DqvzVSW256gN>dT2QHe@IXF6|I6!uDXvAKS1!1M%qxZ-CQ)R)jaCGGk(2}ui!1$P zt*r{cMudDQXq4`{C=C#6M^2DF2iJ#%`UYvnp;+q?UzcvKi;dv+d3=;niwncs0RKt0y>&@KUx8hEizD72!9s zRLq%qXjV*z3qB&TII3U2r=I_B`$+SD*hKc7?DOZ-eRC8fJFfz44ATNUt8?g4;UNq= zpb03rYl1*(G*t)Nkf}nM307IH5CGZ?7>C$ z>;r$4rFSzh@tQv zso2hD$-l5}MQ(+xv7IOiNw91B61_x>TMj8TBbMt@oNdA;30`eBp^M)@>4RY59yh6I zafB#he&ODACSP$#6eIDXUQT@0!1VQl#xOKf?&6w6ZYLePz$A?BUENeCbMVQ#w@>l* zh|C8zV1dJP_gC646p;;4cUGa6PHW@~=CvqP7y-=a6p2E%7`^)`gym4jsty!X{zgCN zs@V6htNx8Wuo;X2SM;VTjy!|yFQ>s|Mk~Z0ociL^Ocem)!0KdNt*P&ITIds|XeRH? zVLQ)&ulaC8eTYp#gt@sjN!#i4oT}=9G{d`6AM?r)8?;c#rCW%<$GqR4a^*>ak7{p~ z@=aj~MXgCVZMh~~?B7d5zv>@s*3)o#)j2;MupwzFZwhq`z-s-CLDwuQ=SoZrBRdn^mK4-ag*;z&SS z;woBRRxNqn8k~u}Xh}ADftFX$Bw6MoeW}ZBu^AI`X4Ij@5QDhdBs0@on3V5QH>Y_& z(C49$1NW-3e>=n@B zXLF@h;5ME{>T+RugjKegt?2Z|~E9jx&t#uq18uxyv zz@|n(My4f@E9%L>aNHK}rvL_pYUK^QpU=K+wufx*WphJr0L7(RM_N`6L{`4AYy z*4f!xSw-cIGU@2YXIn#b+xYTZ{kG=N?3a{v%HNH)O#(wZ(i)NblJflB zcHL{y7>8g-HVoMJE)VqX#rG$h0q+%7-{@BZK%|e3QluFA=GLZ4pwqrwai;DL7Y;it zx|>&)ejQ-VHHHTGAwiMWH{i;-cn>mIa8+^yhsaMxQ{)=c@3r`ov&j%KkP1=+o{+1G zHEw=`wA4jC%Rjaa)etvyvdL`>x~h+7?d5lif}CW+em(Bx;t}C0`eV)s@f zkO#zz(FSwW3Y54%PN*_IrdJE3m$>iuvpZAVyV3f68PMHNl+4SB9Unn`DV~f{E!N-V zp)I^_`HX~{U2a=%hmHr(Bt!4l&-|Lx11bYQlsDM`W6#f$-4-&H0zcf9|*TiB0dP z{_=&0ed8Jv75?hyUgmi(wVNdm_?{lh@>x4Qa1)jB(V-}F=)CxklQVwxvR|RYk4niT z@1f#=41IiLRFCV9=o=o@lvxxc)q+{D+=unw_^9#c2clDIlKFgv6-_pp>S+uo;OH_0 zcF7w^w)TAyjxo*sxx=Iso_C8ysbLo(J9awQQ8Y4Y_VtN$dcg%h_&5njC1uF_9U^r( z6w~e)w%HuEM)?pF53~DuvIjqWkE(O(PS4VH6QK|+9}h<)&UA7Pn9h)4V919Hdk~i3 zd=*uoAf|}NLc;02$8dv#C+%)>H}+ZjN-EH0?J0)gc4fu=Xn@oM%blh_*!wC*p|kPv z)z!ZoxOcKHwCw9{u?cNuOOSos^5 z?PFxaM2D$nM%f78B`HjuiDZpg36z*o5S;b<)H$QDeGu&3`!auLJQeTpK6~@^`$-!7 z<}dV4azso_6?XJKYdaYjyCx5@8$b#);V~Yy1dS=p&8Z~VB@E>uM*0^QwICmZass4w z20?-*s-&O!@4GT@LIK2-F6;-wk&e=F93Z>P1M~p)tBu%7C4X^V%*bep0f!w$AGb8>D1rNp4@7>R-OA3 zsGuEY>q|@(%m)=kfwzXoCW+DNoz&)Bly%S#8uz(UpA5@ulscw>i23r&Rbc^Q;vRNT zb*mwb&e>^#;K0R@&6_z`QBjrQy|~xZ(Fpb#(|x_AW!n>zskK#ALPhm$*L7R+j$9-L zc=o`aY)V3i_}J|u87cE(m7N09{FLN;EhF9Ad&l}oY+EncCRzfBDH^NK>Fy3x3Y!mq z4Q2?ZL@9=co3|8ADB8&bFfasC;e)X|V(eSf_<+gwmIceyvINwBY$>vCHIqPNRYuv& z7BBre*pg_PK67fT&m1dUtFID8IQexFn+pNR(nc{iH!ogL^uwYVzaIsz)VR?n@5|D( z>(G!$BH>*o_TIFbb=uXS94ah$C6^r?kL+rt2SV|LwtwkStfy6?DxJUlD!8alj0mTD zRaDZ5bXTlSE!`ZUeYbMG$IYd{GX2#=2X2fuzHuYNSMd+t$S2gVD7B2Oj^qK zn!)>!ey0a3^OiwZ3T%!~JFWnM1o$laMq3t@iHk1TTyz0##_lz8Cu79J2lb5|0kbeS zRygV~nmlxtlEh*Q7ZNY{`X~q-8VC|7kAm@jfAax`wsl#g0X}*P*cX=##`|esoBfS_ z*zygC+3!!xgk_jNjhP2U#YbMC9H0kaceSPxnn1Y0AFD@#(CYG#Q%c7?ICjCZ+)dh( zSH}+aj<$}a6$PrQVMO??`2~bL_~!&fH2*82GB_}IP`!DJL*b98i>Fa5(-7h~z_ea8P@zZ|&I>u2sOUA3 zsvt(WxC7-G;jUH+!9iBFEY^NLXh^wMQqAd)qaM4~69~VD0C`puf4NjC@BgZ_c*|Z- zYybG@(G2&8H=PT?3}KpFX)O)+koYAD#(%%uJxQ{=&h##i?JdP9?tl7pT?(!wFD;aU zz+z@`)o?&44T07$CvdQIEk!j+rmu2-ZGY_m1)>S$YIO&2^1hGLK}Bx`V&Z(DNO``T zEc@Gtrr2}+A3(&0L5B(MbzB_a+B(Uz3YLgxT(FZ;nT4#oL-FBsV-DRl^LSOxfGI&% z{=3$67^L6?peScems8x{+vZEPH1Gf@B4fVD?R{?kPws8=!Ea9H>|>|-Us$^}8lQ=v zmzAxsFkxB!0tTi~mCwU8RYSuq*+`}7`k_UNXfkkfr{=)Ka0KE)((h9L@;Zhi!n_`! za`k^kGG+iEPck|RUS+?u^9|;P1GT-OecV1&fTv<+KYwPQ+KBx6W7qL|iSHMOl;886 z$-hFekgiX2g+Dlo1n{qnB>hwJ{?r6$9i($Lhi|K4@xr#OZ#~VB(pE7web_nB?477d zbl_bDw_b32#nSw(z0>14-zOov$M%+TK*aPtvkhn0gJ!?>`CZ3C-XECEvhhI!1(G9I z#1sm$$e658c4JVzr640H#m1)I!c4T4(Ldfl91V(j6nM}n35vJL9PjxatvWF^Pqcsk zD*i&>e_^$)y+t3qGm4HLZr0DT@ZNeu-sxg*+E;4S;$cuDuzrNTXY@$#XK`s%QNkx! z3!*o1*NYW8PBc@G{9L6;;4r81LuS)Uwga&wVv=nF7l=t0-sxWKRyq=s z1R?Ct12e3U265qQX+rXTL)p zlPt`e&eby5{6c-NrKmckw|admJRGPC+Z zL>3BQS@rjSc}c@1F$m?VxQZsx6y&4Z8vZ!wik!{AJft<&OG<4=mUvz|{Wn8~yC6Y= z6_#wSg=`=ptD&McQLY58Z|yz%@u&@;0G8qu%erZrP`wg@cUI-K`#%Q*;7N9KlE=4= z#q-R@DkNut*cBfrJBIbfev=jPX9mK;rkmCUMB$CZL56bCFXQu*NpjAPg*pJ16#5^Q zgW=x&EK8M{Z`GMMlJB3p))48!5pRWj&uVQk=!=Fbid72NKb?h?OzBxutwjq!0L5?L zMD**H>`ZNae;6kvEQP$T(ya=y$KQ9%YQP%@AK zyx+(xr7-vAm?-AOeei>k?ysHAHKIv3T`Sfxo^fX8Bm_W;K#yvkpd>nVM?3G=-r?Qa zEPw#)DZpVaYl3vRU{7>y@z-}_>s>&MRc#OYnDe{652V%#oZQ4;ZFs@t>U5?3$FD7N z-^?UbE5#F-mp)W0$$s1Ozp343OpX`p* z6cks2BfodKz2-%CL2qAcP8Xx8PrtOSw))AQQ%RDZmrhxwgP=t+SvT5ilK@l%bK&1_)F0MkM}ip|u- zvVbHfSlD&V7jxV)OUWw(ZchXzL;fiiA`^Z;*KM9Cp!>s~nC7t3akt_yKoq~kCXyj( z3@Xjl8mKAEPPtsP969;C!gM!6BykstLRA3^7s= zS|kVv^4{af>Cs<*Ay<{$RWIAF>>(gHoBag&0L%8>PYHR5Y()3dpr)ufG?w{qJMw*S z_{DC`Df;#%+ev%59_lO%g#ne=ka`%S23CLrFCQW})#0B8gUSvc%%dza9n?fk)m2?- zaZL)31xknqhOIc3>2u-mc>r?sS1XXnWIe2`nwc-$LKE-*euc{(a58fe$Wg#K<1<6F zf*0wZgxI*f4q)vQq$ZOwru6-`tljGw+xg0-!W$-B&PQlREBwn~5dSKveNpE@C*8At z?4xcmI4lMEV4V;lO2H4>nhKG7G-6mx=B}0BnB0@Dw{pw&0VTdY1N?;G1P@wFGwlm*o>1CNf zM-6fX@vk_BjhXJsT0BVklG3VWB!Zc<+K)1uA8>fv|6J6UE8IMNyJh%32nC-Ket2}d zZP655sN=6|N`c9Xy3c%a<_uTN$8Fu?>&JS^JHn^D-ww`xHybY>{{_(%c#}dyThYO9sGFW!w>KO)+l~j_vsgLs5Lw$$6@GJ;g=E0!ftYYLQuQRGhQ(?)m z&eRhg8rQ6biDk@bj2iV-ne2B(_-_pyJlK+gyj3%w9;2hlmNs{HX)_VFq@h@J`J>n)k>h582Q~6)CU8NK61lJWvCB~P)Z};M1FN* zqXM5UtZKbZl4)T8X@#JKO7B!j=OfR3=-oBtkvOfJb_UL0Xb18ZY9i#>+jD2Ad$+fV zhQtDWKSTwInkj95Wgfbu*L#<&!bT|5_sUPCGrVmY$`#wmjyIaOVCUxA6&40A2a> zXJ{bx7A~+KVek|WkjeI10stWlmI1&s}F*@$oXces= zs2JDJKf~iRX~8N|6#1gLFam3SOUdnbFFVHbRg++M?)edJ3cqKB6GGHNip84)pZFpi zO$x1Rt!EhV_3O>Se}FHJl{hlqJ_WhkCp#Z$WfxyIaY3+`4HrINzww_?74YxAIyTP~ z;Yex9zkkKSsuC|`N$3ISLddsT=boOhiH_5hgPualQUvV5_)FCzmD`?~I*FD1I-$HbQ!=q|0v(|tA zXYs{R$T#X-sJ+4gfPzq{dVM!ZyeFqqoon;XJao#epdu{!fH{Yh3ha>)s91KvzcnAz zkGnUl9dB{TppN$cCFoL6b9o(N9$qN^g6u?P0%&2KBMxY!WE>+vij{NUEw~&30D@8S zLR9m?{tF^`6=ehtQM<6C_x~3I{eYLVrgNkVd`UvNjEjZk#Nyd`f*TW1(msm5jX?E& z*90zsE1-l>q}gDyDxVwe>tLqAg0K$Y3#=7K`x3uhx<9o(VnIkIouRivlhb~}1S zTOeSCDh!sMS4S@%s}D;lz;44f2w4~n03iNV+IxcD@n0HEG97rj9nm;;oi#88Tdry@ z;^H{ueXda`atQ)pd>j2`@=~cXdasX+lJT*-u#RSW6Dd!&XD?iR&`t(Ed_XDDBIK-eP9?@)JkvZq9C~Vm{k*Blo_&@vzhHuRLC&k~PkHN%S0H0Z} zqsIQippUMtej;c+@V^?l?DX|IHD70G?wqNDgdQ-HP@~F zqd;zjN56w#=sht9@owr$NBb`JcWibjML@FK*QTahRqV&y@)%NK@Jeo2Xt-lEuthd{RXn1HwbaWdWXYWovJ8bW;*O>Z~UW zvV@votirnbDP*2SG8=g9!S&WjT)vp>y8;BRGGiW%1|il|c{tqgFJy+N#mLV(al$ zAutM--J1_sa(*s1C8#UReaQ|b=%LDq2Um8DRfV0cz7uwNR#-=-yZo~q(_@Ilok~)L z7Ti?nNYL`t=HfRoX+Xq2npi=WoaU$~rekbfiwC`Mvb;s6qD^cAOGMglk);a{t7m9h zzYnmtkM@j4_JLFpXCW<3K7mN1i^QTwm#s|dhs1izx?Oc>S z@iWhR8RP*J+%e_htzKcrwGbE<7Tq!s*Q@resQ)&wP5(gv=|8}Nw$c`qo8^e{$C3j&T1ldiD!yhA)(#v0tlhmU@Ey%9mm?aF{dLvNI`BO^C)Z<60& zk*oQ%yT6pkQ1fm)2qTgp^D!Rz(io5UEwkT_Z2Z0+R7A*f5UXTAMI8Kr$C}7!s}1Ef zZHUd+rDgg2`rh3_8)EQOBfe3U6Bsi@Vkfr;YNk@+As1t^ttL~*;v>3wVmAy%Z;*vA zR_w+M%rQR-E&|hvpOdQW!$4Tc<&jY(iKHudPDJBl&1uxp=o(0b3t}iRX3(Mgn#7Z^ zN|@Nq@xzxLK)}O~m{fpG1jVJ8AVZK>Ow(u559Of0gqJGR3CQlmk!AvQ~@}Q4h%jT;NdI=c4zuhBWc{6=mS5+&k zo5?LcwtYs(r;`2qW+y+t)+uv-i~TdA+ zp}stHiuf`PTu5wFY$5ecrNOdMC30Jc`2#B=5p+Zc8v%#w*fhy8^~7Gf>T05hGGrQK zho&~PJH)O2G)WZSgzT2rh+WnV5rle{NRF=(h-ejj^fs5UesXy9xsn9>xe=(pf;1uMm}n+@aL z$E_;%qzDa@tqeOWRtxO`zd^`#9Zy~ifb5dJyCxib#u|A|Y?$#ksww<56IML1tLd0Y zop`0Ax_iz?W}Nj|tnzP)HA2CbJm$YYS08z%9Dr)_t}@iP{fHGvqM00qd%XN^$EW8c zb=F4BP1~w@3y7o3LsLnd_D{J~nlG!FzeTF44+A*!;_`m?ve~4N5)$j|e3~0gHM+k# zSo^J0tEm1@!x;M47Jho+C|Yzir}NMLxQoSl#Z7uV`>(Ij-Nhc6`i>-8Y@PD{vr%-} ztk*4Jaw1VH?p-l?&kZwjXKbiu2CugGEu0O&Z=S}|vD%$AX?21Be+ z6^)N*`j-0;nL=d@7e=sA@MK|zgcxac{3Iaom!X=bDx#a4h7|a{;5vb*t42F!NZxDx zeXL-7WKWO{j{Zp-tYSBFzHvA!482?!QoPf7*NkPIi4;zXXlsKj*MykKs05kd zdSn{a3R6;575y7ltN3leCY_;jNH({Up+Nk`q3l_j7?kUKMgptM!2Yr6FITeE-dd%5 zBF{&`bN^hK3ICf;2UoD0OV#}R(L+G-r(E<2c3Mu%1OYg`jeKuHWeePKrVkP||Ivek z@}%oHeAUt9U`IMAp?u&-afEa^gEgo_K{N8-@q4&l`#LUf0FKx#Nrk#R_&*Y{=#?XZkj*z|NR#8%=CPJ$`>a2{VzhhZDYad zvYUvS-x}!O`%ESf)+Rm0shFUDjDXnBv3y4^OCFR-i&%{^<=4{^a#Ym zquGvU>Y+GDU0;6A|Lg82(Ztp4MPdIAA;6PcOOqNBWE79A*iP*(2v*wtB;TJf$``(G zeVN->Dd39BI(mQqW|_m-RT&W!GH4tuhU3oiO#_d+AGSd~d}DFC=t~)oMMB;(+qxu& z?e-M-Xs#_=#JKxOe1#cd&TLLmWSRnsUXP&Ou04^QaS5+FC$h(MCz?c#4MymQ`3=G0 zQb6yJefAROZ3|u<2#{Zjx zme4;bqfkUMY46C3FQz=YlWqOw7#25El74%=2~1Prh-(i+nv^YY#keP%E*yQ4l1)@Y zZ2fE9C<|t)L;fu-&bN5WZD>*p7ZgV)x8naQIzoo@tJs@~ezeKf0MbACN1sj7$FS>b zM;?`}S=E$`zDt+0B-H1XoX^0~@$PtP?N8Dye@Z|LtXvjDYqMLIk5uy*3n8b2eOm@- zz^Vy=_Stw+?OI z7_rL+6p=Q+rFe|0zK9#mUjMI))b`*ZrkGHe|mkX{P|1gGyYTV8ebGiE!<5qXH|uo6#jj{ z;$Y_yHjUEF{Z5R0m&C2*wQQnIIi9|80UkjnT4d+QfT{p_garz~*wUq|%aauJMIk}K z&d~n(Pr(-VDEQr;oK_@lHdFoW2edESSnzS|+_0c8D9BGHVr>N7mvL4uhH`O~ zgVshI8DgkKf(FWugqMTQNCywjYi^pNZMJ(h#(0KpwEaJp&N8ma|9$%dM(1EO!szbq zmX^^e-6)Mx!swFjkdp2Y2?^=$4oPW5nvvgo{{HvFJ=yEE?b>ynpYu45_wn#>F=!wM zm)w3K5SjfCPZiJE&8R3=N(PRZgeiy*1LZrbW#r@Yr zV4Q2J8!dPFjOquq+EW|s*1F9+8^i>fECvN0r~}3EmXrJ%?|!h{wc*8ZNw&XeyG0g4G_&3UzZ z2(Zc-F;Po+s0|t(LRC$I^6%^8G6L=J=xOYE|Ga+>88Vq(`DpMGm1|kz&ioTS!k9}_ zJUF4;O{#N;2HQEyRCIiKH82P}UU0&kJ2*3G5)6Nkswq9FAG)2$n6w}dYD0H>Y?$Qd zT?xoR3H|`;cMfMDe6e`bj28!tYQM&WcW$*lv3CW|?Ce;!wfgR+k6Vg-gYAE&8G(=i zvig896{=a6j@GHnpM4O`xJcGj$35_m(yeR5zXLPZO6lCt#z3t$T zPSzd(fb~hW6a=$E(3r&Tz#n#`>J6GNx0LB}du6&(N+f%K)2G$_&~jpnT%f1>w@o%I z;P)-v+_Mwp63n05Rw)WWJoJxs&ZSW{XZg`05mN*|2x|Akm#s32ERxOaOmap=8))0H zkRSNqof=|Jw~Ej0-M*V`g@mNriSgk$e>FxK!_fP;E2nQq-L0{;$v9F$?IVrg@Mc)S z`;^J(_RLWb8eTLi!HT310GyVhz{8yjUS(p|*s2Lq=k?L;{%l z&tO3?qDlHkwh}W(ya5KxS^S9lv=E-R2(!_BR$2xh5TT;pCoy55^P;DPgcbY;NMtLB z8sZ=mI0;g#G_)aw#&Pp_(Vtb0E7Qu-umV%7YXN#J$gBYIeqJ7&#}y@c3!$bRN%-Nn z;;)snC#s*M5{(sEnz27xkT#0xiLHVh#D^brA7@BeAmnd2dR1)p`}3>?IzrS1GOsj* zSpY@kF%T9l^Av2Hon1@IZz}$wGH91uoZA`|CUw<2ZKXDinTR4%6gM|_YMTLyAw&n` zReWqm&~@Uu@PB|p>5w37oB2i^Tc4Ev&m5aE9V%0-Db%J*6jYq@N zy_QuKQf%#zY@z;X%XlO{uJ#^2KA8cTb&dm{AW!z&wFTcX_>Y1PmM-|$WY?r_d|q79 zNv}M7)$M*?{+4LVKm7LM4p`}<>c*VWx%bXAdn09}35|I(I4Tx_RvNDmxE{bG%=G=O zKLLxt<6>nPJ5NQSrpy*23U!Q{Vlr*<(`zTrN+Q6Qj`SV;KiMf0Xy2Znru)giclEMB zh09XkW5Xa$+L(|5SKd9uQWXeg|72d4uXbZX$c|XB21C-4%t7r6{B)c~k8FwmBE6~n zU>HJfL-L9Hy6Kti2ip_SFZkF{~aOU3Yh7Znp7dKh_fYR*EyQEutoD1q~%{? zx|kR-|APQ`^Z6qo93sMUYJ!*MLktyRUk|Fh?0UFn-)R=g}Ayh zm|CQ%X!wx`psL7$TVH--6Hjj;RjVwS2X=y;W3w5Ihl05Bxsyw9^;BefoWd$Sse`!#=p;_sNC_D)6M`;bUxLgyEK^vgL){#QDeZDP*@SME(A=UY$r*gfB_;B=xl#E zVo|j5LIR->AVZ;vr9X>RzJ)M-5|(EOx);m-TS78TNAK-dS)(^rCDx%=tSBeHkwK&7 z#QB(f3_+q|*RT8~m!SW_kb}2a{kR478?~Om-@DCfFi}O`cjYi5YijMv*t2KK#R`o) zHuk?uo2ej0D0VCE=Iy0RFGfKnD&~4ZjXWRY;i!UK$uP#GaASy)jx9j@A8Y-8KN^Fa ziQJouAmnHYMbf9W;a^{JszExB{;thOKE~FW{A_V{v1uIiB-IbQ&(_i94F?;a&MoVA&paHsg$%&u7zuG*X z58PvCYroMi-Gr1mYi!4Ik|{kv;vJRa`9ZRyUAm*497aN1&d$@bCpr)je;cZ#7PUu&(@hgHcrPdkD$Ax@_gs$qTIn!+ZzwMb!We zsyCvLlVd6}z_I%LMTwN3q0!pD)yEp=4%?}z0#R9fXGT7LWHe$=Slq{Z2{Am9c4{?& zE0IswZa`WPfOP(>p|}?fBiUnYuEa3j}zI$v!#GA z4vW=A*dm3t?J1dODOMAww$guiT2K&kQW3hmJCpcn(^;&Wt$@otJKzcUc};Ri7~K^6 zlLF6ji)q8^@>{dZZp)t11`F{X-H$(YxkazFAdN`;6SXCxX>7&uD;1E_1Y zvo7NVzQI*PFd<*QHA~vhC>=V_e{H&b#lcDeGP?h>S6%$S1O>~D9+#50LAkd*2`mYy zZHFsC5Fk|Szkr{GRa9B>a+J5V1ZR>CDK(-yn!s^6rxD zc(NstsVI0*sE9M8P+|YNW$lp!cV8QbHRsu`rOy8H!6hvNLZFbceTq+t|-w`L#Y##FGuM^*wY`H89eht%p0 zlsa4%?Zw?!UxZgV_SqZE^Cow?ak4?MAu0*9{#KNGPJ01D?6EJ^-1)XiEXo)%scBx2 zXO#6chV+CsYW~H1TX-}?1uipt)m&X&RHz!RipG$J92L~8I!(e&&OtcG;Bi#A*yRL6 zMPA1I5jgU6=d)VbqmmgDD!4X+kf^|H;p|R<7GeuBfh_cWwJ+3v6i=ySYaQ3ci=B-3 z8*;}SSM`(1_M0Wupp&~J8KX9rMpWbo$#l`4H^#Q-=h&8o<&HJNTdmIXJ6T@fx8;~< zLR{96ojESN4#HdQnYYVBG4139eq1G;*uJNl0!{8+`r3&Tk@ChxhK3E|*;`pzwN+co zthfEdg0FMs&`@qJnhzzA!v99Knr!dJHsfPSP|Y^MA6(+9&YzNPd=BD0T8TcB-#qRA z$V{Q(?|XO?_)fIp`mMM^-`tIC%3unm?v#}sZ_upG!@=t0)z#+0&R(lNeZ3pch&>Ms z!BX|6c!CUlCZ%zG+Y^Z8FD8Pg8TVnAW&9;bFk;;@ICh+;-gkTZvt@cFFu=vZm(Q|B zBJM$Hdugb95Is`tjE2B%s9!0T8Jg@V#DorZPp=y?#`6gA_3V%y^l6{Wh+|?a$iZh1 zO^CqEL7~L5=9mqnVcj5g;LFT~`&KLOXP`ix1<}G}#R%RRScq%D)y`Tz|BlytLP3gm z0rmCvziWnDd`Gg*8odQ6b9yREm&|q-!zbV;7p}YZ^jl||{T;99>0`HD;wo@1rW=P? z%Pwe0PspoT`PX$KlLiLHcaDlaF*BC^t{3=w}){UJDvvOpJxYgyUd9E#5~;%~_@iYt7)4 ze9pMXjgb!rf-AY-JyC#xt_OlOeOx>|>uVxdBgnA8EIvhAZ}V=NK53-C8L@6=ths|9 zwAO_wiSG-;W@&PJ1_0tn%OThlcfvRs(fzoV&Q!fSdl&e`PbL9s?s=VAJ9!N7kc(L9 zIy+Cpm5L@`SCCKB>#@Cy1}36tuL*Yf`RfU0l`%`6pQA_j99<^ZcxEa*d+AX8zKPr2 z_yd0P+^0oGQ;k2(OueX`EM5NrV1bn4-?uvW(GfQvsxo?`(Mz{AE_WKDZVgO6b&3g_ znNNps(U%5ukQ9o0L};PU%z*J`95voPzi&Y8kMREGKJDEul3~qgj?9O}(EcV&K}i?W z2oU+_$=Et;CnEcLp0b~FSH4ufB{@WQuhRaCM_Jg_BfLATLt~OX$%l9jObj#&ztzoB zbe1+AyHPt+b^=Jn2OddN?Xh>V0ys=9#tGg~3$ysgx|3NZI;pL0juSwJdi}G`U5O7R z-222xNzV~Lx&^p@)b)h4>5R8&gh1Qp^pa91Uv;W8CGoVORK!q#=#PZ^wDOMv^6?z) z_V1(OM{JwkPgq!5ZM90ae#Udoff`>3Lo@`18bUgy-SddEx1Qt$`#f9U^o-l`UhweN z=K(wsEs@4s7FmQVK#?d&h%C{wdIhVJ0u+RtB2(bz9t7Pj5Qre)xvcJ8mCl>;d>it8lAH2>FdD<$A_Z-xJeH*YnS=@1M)r%zHb(yb@(Uz}RAllZ z8gqsuvs4Li*<>v$tHoU2sRGzAQ=T`RkNyss_eGfR#BPTUNMr1!V7+xV+`hlzBADF4 zWDpA?Kfh(j-o)PT)>V^OHq>#tr>Zp`R|77U-BB0`(DpV8WSo))XwzzBUV(kL5w-Qxf4><_RP5% zlqkF$TjcJ=*>Wj5B>_sTv8m&T`KzSXdIK^$8S^GJpQpR1cFet+OS(toBhlDS6DdA_ zdT;-}BOY;|qaejd9J}J-0lxm9qxI{i3ee5IB3`~<-AwZ=ejg?Iqkp$zZ-MSZ*#$`J z-^{PlUiXWAfwU+iWGq)Uv$Sg^1^@Wxn{weo39p}vw)E#je&QCZ0G zSzmle{tgO}8%~p#gHfEN2{=9VStvWS2#j>bNrn?srym`;{-k}g3;@vA2!$U1n_^Sm zz*xV=`2W3$`qz^Ef81)EEmW4=1#52)#bGRzB7&F(1r0=C5T*jeI(+y3k;79Hiar|l zAHeZp0gD7}Ej-M`Ec*nJr(2Vkp}JwRKo~TojBCa;E9q!uFdh_OoW(<5?u^PqFTY2n zA!(^#+A_2g_@~OHR!|Vpp*p{P@oF3orFSkzLQr0AWaQGbkUbU%2so@21fs#QF(4V~9mdmm+Uv0ALP@b0 zhhjVpI1gT$2$INE6OGNA+V{--E0WokJ18Z@KCYG@9d)Wi)Y8AB?#$CUfh6&ht%y_? zYV_{SFbu^}$0liXPK!|eNMQAu{&yD{fm$=2Bz$f~7dNq6l^DVpT2#ou4jtUD;nfj1 zqCAy4e6Pt;*X^#?x;my-ZYN7k5cu*mZKCxWf%kp?R1l?8C3ai)BV<|;1Cf?}wfQ4) zC%(jq%_0ivl^9#$t?G{gTAcsul41bicUyk?1}+cwA882(qdIEb{Q>^p3j$(&`c}n| zN^foPoEwr~QI*;l!EcRVbsskyyB9G&gXcOk&YQjTPJqV$d|Ln9{~0X@We2N0AkGud z*OG^37)A84CKltx-(S*0*rd`cZ}c7zVGRyg><`wHW>;uIt+W0{sa!J@rMaB|50SF}kG1;a5{xtY=7MP5)~lcS_7e~ngI ztV)tJn9L>!G;63Gc%3~UQ%y0Rkfxc+Hh=^nz@#(h_cqb>$c}1G(j;n}4<+sxN?Y)f z`JKv!o$AM^IL0G`%=o{IM>8ACe}KlNKWkOQN^2AOrw6l$cC|1bk3xc9YGS;orgT^Z zGGPjCK@)5${zzTFr$Hvaq`5kSD7E>=Es~exTdon#)Qu=0nN(&jB?qbQ7c6?4F7I8Hp=CV%AC-RkC^Rc{{g_LY9OGT11OPL0ViB6 zC<7W6Bl7kk9mli@A6nx;SFJVQ$=YUIpt~NSOt;kS{7+LPgaDv)ii*k57SDYcUnEQD z1X8T((odIS3_2D%;7g5$S7`fAKVa0Boecmb*a|{!<`ViGeBntETqXy(zcGZjDPZtR zvzxU%yfe@VI@vxyLU>g>bk9$AbQDL%1-e1s{sX)uh-{Lg;~DYPx7J10H&G;D9$XQr z=HADd%OVg@jy{>oF*d#1>k)t~`((sJ_zsQ|Tklhg&3uLABL4L;6UF#VhzZDuLCmUZ zb!m&V<9j!I{;5z94~0j(9XDRDXO5{v-)3|SnP}U($!A`w2YLB(m|*bI)+mhFd_+#( z)adLtT6`Cb;)r<^Gxp@M&e5WuAmB-EpVGA6EEuZ_xgcM=99f2vAqi=*Lg;*Ly}ZyW zqEH3((C^ftX6{`SB7be8A0Kk+z!D5|T^0ZXqEiIRx|>64Y}oEF^|69R{Ce!Dy}`np zW2N)dZ2otD;bht5C$`PfQ?6r(e@4t5bL~%*Pd&IlzzP(5iRwS6H}4)e34CR<4V(-X zb^TcN3+yV9as5-AWeDc<=bfbnQbDR3`wi0HXo2gEAt28E&u0~{c^j=%-VuSb@>eDG z08w7r?Fsm=KIqLYkRDdk`0Vn^0o70VN?6T7jfL8k*lQb)!iy{j0IDD1Ar!Dh>W8|o z#D=d=m!iQVCsW*Cf!&@`@1`;5L${mfDDzc<)?PO1as zE|_v&zJ_$*ryf0VM&}^F%1%_?tG;I+_QrctbJLZ)fajA$s1Smew6HPCB>#o zmmNqQ`3szyuI!SXN@u{3dbu1TJ9}AW9|D;*6oPrMZc^aKe;wQK@I#l)$g^n{+~sZ$ z)*=vIMr`gd`6(VE6vEdygqSY$u{Ph5*7g8ETiI z!d#rC0>)-5`lW|iVcyd%V^lPR8@9-wvsZ8m72Z>~2 z2xf0XwLo;TvCk5_aF6YKDaLsz*FX9ToBGWc3ELpWTxLpqblQ|L zOL?BP&M z-uSS_u1kLN-pHBCSFL@RkluO8FDPjkh1Q)@94b-XbzJGuR#hI_STBcEXhf?Eqx4mg z)cM=M+@XUs0d$?v(Wsd__??=FE1PxXb77Rp_cenrmTo*ICYH|#D`jHbI_U?B?Cg~^ z%Z&^+r@K`1N&9w|E`Fv*OqMFxLvau5cvvp1OI{W^ji2fL+vXgOTqU%49inN?xuw0L z>nk;BKF@i>;L8xvP;x!0JE&pWZxAwPS>tDh@uj)L&MC$uverx;bpSdc)WKNC3aGj*W&G@p!;J zRFl_r7eMEXuvjWmWC!_sA2A)V#n#F;~X=)RWK=52ew7_-bU%Rc2xpC`{2cbl!DuGfeG z0nA#jxV}eJ;*FBGKlt7QqsI}7i1Sv=J=dnSF3Li`AtB!4l>)T$gU9p>}PLF8MckgOw6HdGE5>*(XNZ6Go46AC-^cdkd*p}U-PJ!Tt?({yFlMy}lRtg- zJ#&NRT!miZ6SsC<(*JNkz2^7}8yo@cYDfOZs zF{y9%=FynN#>L6VnOL1zQOz@dK_1W;_*iT{rEGv`YJjrc|3!ex9UyLaA*>~?kN$_% z#-U5Yzx0s6MMgAZAKZk{kc#K=p^1tbaUHdJL7F8XsY13LP5>}EYd)6PYHK=9QsW&& z&vt2FAA*gD6b7ecX15bJEoO06Z;nlwH~z*;{>e%;zv_3w{wawgRdY&Hc`VyFFx;I% zMS#*|;vbPTYq(Gj{7yyzl4N{+TsZ?7pAbrDpXOpxeCm)OVahT#IDGG#iv6);p0^yt z|Mu%yOT=o(``wNN#Vp+kR--R6GSJyd)jR`@VVPdSZAyLCD-%xuC#kdj_QiV4gror- zY>ZF61S9JeajZ0ZB@dQ78z#!@P@RtZk!r^|pDkZB3RWM%LygnAaXDlMj>%5d(zDoU za$igbKzv8b)vX>bN;)u9pt=3wAvqRGt* zBtLhvofgRDm?X!It+HjxoZw<;yrpdG0ve8+vByOM``oBylhv=1#D!$hpL zy$Rt+vomH9HWxfC>Q7UqL&GQu*7wWM+x(QC0MzBF(lcLP#%dnzAu0GbuFHbWUR0hQ zX5=$jbZ7-2+y7bmM;?&{e}yv2BiS6;yg;Ikma0Bw9Daht;Es5F z7MlrXm%GEZ1nQ|78L_?SJwUYmK$4XkH@a9T(pvxMRkC~HZJrDA?et!cJ;XvaZ*Kgq zFX_@lB5V|^q-~R(P?ya*KPW+vW!wrNY^^XvRfHl^t=4pPF|D?81wh@D0P-(jG?Hf? zcJ&HJVaeK7nNh9)<8!e@k4ot&fCQKZQ6^^lMh3tX*PQI?ij^H!L@rTHLt;dD=g82x zh$!R0h;#25gm*-lth7(-d78knt>5dMg>FP{kn&{2WpT+MX zETYkJawWZ$1eIY}H~6oCvZV7g@!S!=gm=oe>-y_3Jhk`Sn!i}T&e7V&)#Rn6f4$3z z=iBT;F^@=XsJQdipYt@Ue>X>w;@h&?J<41;tr|&?D7*SnyahLP4c%{aCA@2x?E6sT zkL0PO5^okfS8t|!=GxMhclN{g=MUM?sC|pQEA`$90Ya2Z_+G2)el+vtZ>wNnYrO!7 z{pw-i`j?5!LbD{g`LLbWr;lHkD49^1Q8x07X~T5P5y&s@a;?f_PPo4XN0IXX@X6Z z6((BT7RQ8<2uazo^U7BSfU#-|TI3sNWJ);bx74DEYpgb$uM@c3sRossD=sgLUBv^f z*_jGLt#6g7Eg(>FW5*f79=3!}2v1txqZT34>LW(sQL9N%TEWRG3ydKv|IY^AgW>`c zfa{s=QvkcSlzp1q8LRcYS){F-Y@9Yylw+PHzq5DOhVyGFBGN2EuaX&i5-b))sgu^L zN_6B|03DqpbN|wvHibnB@J-lbQEd!?mImS;>xJ|aG{~(*@9bA814OoM4h0?g4;&ol z3r;UDJ}+$ym!)KS;)X4@CuEPK#T%9{+DV361BX!@Z=nDBF(K;79}!E2oTNJfGz@XN zk-hY=23?GP#`U7FHAk(O5SJ?wY?0 ztH!M&xw3&@~Llc!GsqFCfzTkULK~`qY z#8K;=LcVDH_1mB@>x(@4;IyBPp1J23B+*0+(-?dr!l_M zvAqVW4SQs@SkuMJ?`rF6Q2+r#6#%j__B9S%74Er>A0C7(LfX@X*P9&BjqBLBEWN#Z&d7F_Y(8C!B&zKIWh=G4d* zs06%KIa1XRP9H-s#erIZM}OB=bXmcfNeY3HU$f`NCNT>6aobrG%k+t@BH~SDiT2lN z71@v(p>apBS@C$cOhz%zPYex!=K;<2VIFi|zptG=$stxp|QEUCXv&;|7jocBCz`#l^IT zz=01Lf-89QZhrbBhM$&`k?5`Ij|7H62F5+Y83La?4M_*(Rv60Wj z1VjZ=nnaw-!#F+N$@W`Ckf~-dfCODs>Do-0*<7PYlm*Ynde(==yE14me)n=$NYdD^ zcZv}05x;W_65qBQb*^@I*oXuJ=0@Dm5>H|fq@;_Yy^KAtN>LrFW>N^G00TKJm=Cb} z$$*nplc@c7D;~bgOJwVv;XArAt>%x5X)1!0nJ^&&Tz~tl-#B z^9-rl;nB|GZw-xB{KzOUftkd?H+91XXWyr>Yy6iiU>VC1#HereC}3Le{0@~-($BKK z=dr&DMWeF|C~qxIcPu#|!c=C{rHi!c>0w$ERCfyQX>bf>)?#$G<`J1T-qHw&m~HLP zOv%nqPvO2TRql}mdm9JZ^3ITxYugqEDZ?~r?;dO)SoZC~8RKn%%_LLV9CBelG z6kPc*ci$_KCS_j!_6QN0k}`+(5BSISH=lF_g-A@^4DVeu`Q{qAxqbfB4cI1+=j?A> zQU8HQzj1LMTmZ>l)-nG=8tcFKrv>|z+qSigYNst?uij(DzHh^Ed|$Mtpp6RxU`UoB zQhWeBvB7B*;cjsM^SYjQdG;vc(nyHzoRZ`AcypZXt>X^)c)Xx!K~o9Q*#J>*4S(VC zgT21oE6cGgLejJ!Wk2E0KAJeAHinMDk$ADBL|m(r3|NM!PdB%Z%_5yme_Sd4Q1d`8 zsMZ?D=00rm;BY{kWZe6#skU&?34y4$_^BeFrq#7exTq2o@O}=hv<=i!zVH6y`ljk) zRFxp9jgfFvnHCqhXc;!yQ0`nsdZAdar}2ZvepDb9&FT!9dpiGT9hC4~G04k%Qx=Y(ZDPOvILx%z(U=^uh%tVJ*4yaaeu=%$l$H; zz+G-k@9yd0<}3})l|}go5$7mRQ?SAYF?f_ zpp;JFmzCYyyl=aDC#>xH-6T3&6={C#2Qjn>d5pzU!vnEo-eq z*C8Ps%E$qwNm|XM*SxGazX^Y;I;C*t^+2 z71l>bC74N_T}wN>IB%jl+jaL`!9dH1&4=>X?D9pyfhIgYI+{VFbYolbZvbzhJ38qF zH=bJpmQD9ruG#>VZ1MR-I+DAsi}@cGD7`qz~l>2 zT5$_}72Dsm5`aUJ(e@V^U0bLl;rq$utByZhN{w%`b^`1rGwskwOxQnPL|sx$Z%4ox zQdDEJxu-o5<#5|~3UDj<$MdD0P9}9KQ!}z@H~Xb#Dhb{Q?^@RReX%m46OkC;!OLE) z-PKC2s5^Me_TcAOSYJPLg74&GdvFq=ye4N!RGML%Z0`@ZiNg=sHjgRA_FjCWUG zy8hHr{vmNCo+2M#8$?m@;^z!I;72Vi&Xe0min@&nwBAr$T5%(EA^>Oy=e~+-L1IHz z+7O)qU^4&eT=BVvDL8!B*{l88j*8Q{=5hg}k|CjdY_F^;`{94M7PY6y!~ntjaZkJ2 ztsBBp5>w7mq4XT=(R=(eNye@XFSKgz>)B2@Cs2=h9iJX!u0X8HwMPl1AB#TI|-VrKQ~B63{# zGgO&$F?yp&idKeR^4GNQmFcFtJ(mup7OwsYA9M-bZVAWOXyVrbAsqEY5L&D|d)g_e z7L(12a%+D9p;{{gdB&a`87fXZ;~N{cN&`eo3x0cbCN9jv)u)m?Rtz8`07(OoesIaZ z&_$yU28wNglnbuz4q@LA>_g^~1uP6y&{93Ng&s29_qA75bZH1-Xo(qK#0m(BGAvLm z?d4IM2=fi8gtZ-NVFeq9lK{2S$|HmjCNpRSr%U7q?I<}yVytGfFc^|d)TAkNot>R| z8DBA^3Q~lODT6`laJbe;9X|P67vd-{eHq`$q6ko?`)WbPoZ<(*cU7B4r0@-721|F{ zG^k*P&;o>y6Ia#MUi+C`7?55O!u}NI?*9QW*J=fc+1xDKGrRuZmlCeX723F2*Hy28 z?(&>oaC7UIWS^-U^9z;eq~QuLUNJi)s?7EW=uWV)NR}9tG7XB_=Dsx5c5D%=r^@^E z4)2&-4pBx^^jV?;{`9{KLZdtBZ^IM9ZuMEFZJBQ&`5h?SC(%IKs%m8HgXBtlmOnO}CM^7i*+;Su7!yrT6)dj5s# zQ2IrZvca7&wZ@zB{go*!QNcS!)t4jf4C{I3vCz15k6+LaunzH*^u!P=G$-ahDKmB@8VrtMWm>u^3+T_ic?U(nty@x=PT-_ zQNEfmY(4!LILH8?utM+=p&SB<6v`XGHNO+7n9#RF?)%cCA3ygLZfvM9_GACC2$y>M zAAlQvTOTUl*^#b|2shDT6>*B8ET^shN=Gd$Ma$nKB_|>uueyXOR6;AD$a%WDOuzZ_ zY$@Q1$A4<5{SM1XVzWv&C3|yI2#u&CdN8@>orznF0RWNg_Y{wqqbRbO6xb8a^Gcnh zMMHfYuZj($x0&pKgLmzD`s~xLdYipIz(9rNuh9-ndZ+B;BEIc?goMUchXNn1& zOg`S2XWE5wWq8`#Yw5XR1nq~3QL|nt8kV}%}SdQn$BvT(Z zOr0oAA|3V4<-%v58)<8$1#z9-;SLV;p(aRVo$6=q!)&%KtOR=8Is5ymwm=a>(vy>9 zd}@%KXP6eM5a6q*5@tKu-&dK=>)h~ z{|lgWr|(QM&bCU+Es1=M;=g~(j(Ehy$r~(qbDVKxl1oJ7m)i0+`L3TiQ+x27*Yn-K zqf%E_Imoi99J5cwBu>K4^Z#hKyk~wYqybcV6tPEEikw5f!o=~y5r>Ik8b~< z!@$3jOL$M$)>R?w;{wnw4I59x)UndpfbkAmK{?zV1HPS}N$nHl%U zi5iMhFkt-zsJ=u<<8`iC-nsv3LD`yg6b()%Yi*53Mf58lTs6=PABd-R!VxzGFXSDh z0`?O}hI)zq3bQ&nlo$f8kn*H^8SB)+hfPhE8#8aWJ>1aoT^=imolVIO{Ssg}4*H#T zhE-)w$vPtg!Y4k$)|}t~|9m3wyg%lUrws$YD=`A6eR}LY2h@0XpEePqvj$6kx;HG8 zcPmuQ7iNEAa|L7U;Sm5&f-;h4hzT5PxL+i7z3)>`l|3riD4oh2N((%q_Opmuv@4=0 z7X!UyR8~5by>xNZs25b_Q$Z6vLLCkj4Dur#M-FA}bQ!6Uui0n6Z`zm$*sL^n{ETJ5 zA}{Fct;VP^0%y$n6Xg?jIw>Ci8XR>UOAj@(NsXZ zClhE(?7;yo<3&Y5kK>3Z^Wd4%M$XbgdEFl6ExfzD)kKwVViZQ(i8~g z!+pI}{O9ij4)5xVVMWC;Q;S3I@FmUuvJVFxQfEE~*khub3&JQ@muINcynItHCE*j! zk^J)KtIG4pg60Kg!PSndw{c}o4`!a+`E%at=?2i@gT~C+-MuSci8FI-!SwOHi~8|p zpJkC{!$vDhs}TeooHpIUl-rZ9Ey8+h+lnWWA5=KuCP3ROOU?h{5|rOXpFFgEKR&3# zA92d@u1iV?kBc%)G&9pMzR%y3ArTSuLLW}-+)@V?k_;F1XDI4ge|#P96SC|OEV#C5 zbVSU)RSDzhudG@qCnyqU;rM0&bbvW%vB}{^WXObL=xYm^64zJdeZdaF0wx8 z(B7J$Q>T{P)}ZHb=ii_^x0BI`i_D$7Y$bdtb&Z9a0Csk4+)9WLrcsi2gK?2BUqw@A z_!_n+FCM`g%o#xhV|@IEklfebf)*TNqM94$=sOsWYT<>|3A!2=Hu;aMqhb zF5eUs%7~36Wb}{iNMjS1#5;!aVT68fa@9NYk96ngCK6I15)Q!S;6gX$QToyTcF(E|!V#dUK$gie+6C!5h&nh#tk&($Co0Ap@mtfI0 zK1j$<>5(-fGVupUVQ9 zzcV>^b={c;trn;f;r3bIdC$)U{6I}^TH(ucmD$rc}vH<@Xs+x z&~AU1`WPu8&^NhFl)fZ#C76N0_0(N(Y1xq(uDFoR@gB@vW+DR0(GlKnHN_u1Ee{0b z7_R<$eM#pEdfMch3eLY4&6Z;B0mk*YPG2TrFC6UVbd3wyIAEFLIVO5BliJId^7*dXI zz(_QR24;ohPhz)a)gVhKr?T!U`+Qa_rwpVg-Kd@y< z)L<}HDC!qI7F^OIZbLdk7>~^4ZxWW_cp5LA`KXd*m!63p7gt>w7e}Bj%!#1En+=w# zj|$Q-#4ZFHOV-WZ5kGZqA@G6bW%m}72m+sQU5Pk9LLlk^7tL_4XPe!fDAN(iTbeiF zPtNNhj+72>#ra5&<=+*c%UMLJ=w21-9zm54H67^0KNS9oO?)%rzaWAbT_|92kIGIDMw*3^9w$Ds2yZ>jGTo7sxxCp=Vc!gH!;0A>PAOQP9= zWl0Gbrs*)j$34a#r)aQR#62-oI&e|SNLSz`Hkh(1diX#Z^Mx=1u@Z5 z^^M;J8y6D164-D^~a0D_i9JX5VWhqLgdcp9L8ulEg{4I>54XB zy#+NNM`;mbduvu+dwI^2 zmKUgD3q#3~V^J{{#H&F_Y+H5HV2+|;onu%JF@W>?b&$}T5rj38h2&`OA6tzjxLs$W z^Wn=@4A(EM1&5Nj)MlfC=yAfZvM<7wABEA2l3ru@Dr4FLjWDh%)3_}xqQ_swgbTfm z_OyGXmnFtS`dIZ)r}g?UiWTROxg<$zZ-yn^b#0OD-$7ZHM32FB@7HuhKmnT<6Z14JsaS= zr$=YbxnH=I^pOAI7N#Zt!f!l#;a=bHd(7#9t1LWqL128OH`l_xu~nqWa*CsAI50oX zZJe4rad2c8;R_qW@gX#9R~ns$G0TqD+01zT z9p4tOn>!b_J2{={5?ZU^mZxB`7wW~`&ss6~yNjUD9i$gTjL{i8QlRdtdPfkM45L#1ZA z)I8y-0yjmJumwoiA&+wCrNU%w*^r7fJ_3@Z`2c(>(>n5xI{O`6Gou<(L|vU|KLZZD z2gdCn0JSU3P*{vIae-XUvnb`b401@L!^as1Xeh6c@Gp<@a`3WxS!Odb1^dkhz+ex6 zNb`2+%kw9aEfG9xejZNBwb8>`5~CEiu#I4cy&k-ohSB$Bam)ky9(hm~Wis21pu0Zr*J`B`PLQeMM( zT=gTqY|1vstRXEm#tyjJaHp_Y^J&=&7X)Vi!H?CVXVATal^IN0{hZe5@yz*1{|ixa z>(0=xA(>WTo=Ok+{a&A?qE%P5z;I=cZ&%yvyhQmvTpca>6@RgrSdMS+&9VrxRa11L zmO?)yTbEy*8tNNDlUeZ_pC?_k5l*%YkL&Gq^vsh1$Y!k~%1ragM$dC=xm<-45PTKb zkmQtqHpL>$)TZ?m-&}FU{y{TH4QEkJx*$L&K-sPP(7thqvkES{{k-NcZ`gFRQp6|(% z7PXI;_kjnk;JGaIC|VmW$FZ)DBElvRB8!C7(?2BWHy4jQfMDsbXeWV_H2UU&PXVRG zuPern<~yAC53rh4Fw&I7)(Fj!7fLlgw0=U5EelX2`~aoErdMIt%G4vMA22xq>NtFA zs>HOah9Bqwbq*JbsglKN10MWmFp1lVSznwS{^=wNdK(l&r-}Pae_eoj=c$#;Hy9}E zNcHf#?m3sl*VC5|zb(-Dt81J9t2oTXNTgGJD7Eh{#VWycv7pw`!hgkgFLmJQkNZ}? zxWt$x90R^@gNz^z5wpskzBh~xC8+ss9{S_x_b-NXx3*hXPIqx{yL)#+NloS}>IiA% zs{CFZ*hU=|(+3Jx*2=cMFV7MfxQ}|Hhf;=xJiXbmSPHRpUKFdk^SY;~LhjPfs4T^J z!oq`lseBAA>rg=$!5|+LMx_bVj&R^w6~+%U1IVl}J$|sGY*0$S86677m8Sb?%ote} zOaD(+(1iYqk}6hh8QQD1;MWg9@tG_t2OFv;B5Q(dI&Wt~%eo(b5=8;dWTK%Mf0JEt zikKpK=F^%#ndAWFu?jcjQst~>*zG{}0n0iak`eNI>zJK>ydgRu^aBJR3ICwuBFvr+ePm#C;NCL@l&lqyRBfiEoW zionelR0T={#gFPlRw6x67h?yN!eBc@z!EC~FDnLUu;14y2TG(8b^fBhc4Hy-!C+rp z%@EEP;~M#zc4+Fnyd*Yf5n+73BsV%8n=|8i*Q^%(d3%a{PSAt!=7pJ;g{PEJ@va+e zaAc1_v^%wbaNOEa#|A;X&SpWtJ_ujq!%~9=%HRTt{{wi+kvp`YoFAfwtyFADUc5PF zIIghtdzbHSxzn?ir_2vm2>D9DwWf;r`LgxY4Y3#^6wUJFE8rH%ojRu2=f;YPq+GKD ziG@qABz!|GTbZ&~Sw^hG4uD$Zz}g zVN6sy6k^~Y{>#stU1URA*t_i5Y2lvhWmrytaBN0l+sRNag}M8uhnL+}@O@%q+{eHB zD%(J!%8yzru}x*;Ke;=EBMRn>&+5~O-V8bOwz52kCTDJrs`?rw0O(cBrtZhTW>E=c*4j+vjv|S671JNGN-XrIi?{Nv z`5sl2I74`c8g6wK1O~7msZ0B0-!kK8{Gr9e@XrBHnNzZO$i+#g>xJgFGR7TWPrK>p zv^#4NHv(E`X+h`Qjd|{6K#Tg;FII%XIug`3vN_F4@KUw0RHDm3sA7kI`VY)jbKXli z#M&z?X7}>gVP~K2jE8@*Wuh&*5cNln@+ZHmGqv!)mdoqRgI7iocyk_SF6IE~5=v6? ztB9e-&i?FE&m5XnRj>+)!2#x`U6?8LCSSM|=@uKxVb(`Gobxx4sXwpRT8ecOV|mSS zG;gSnZ>5?>MO}5~k=g=BnhXy&0ipKeA#0I%fdZNjr{*|Y*)EhRJ)@gn1hUle?I}}a zm|tYR(C|kG@$Juj?W%&mZ8~8j+D2$nFR#?z+TOJ#xZf$*e8a^Ld%3mMk5P{84oL}o zOOjwE4=SVwbaZ_L6Y@0!P{w__#Hta=Bzvjy@4LEqw)Uzdjc`!6qTQkHAIzdGoR!!- zzs^vCXRl=nQo?42e%d63K*^lEZ1Liij#WcJOru!#hBFyDX*V73fO4P0#_Z#$Vx33Z z9yM2%)D}D{k!7g9d-BR$&`2P=l|5NEGKL%_Z z0=2u*#rUiS=l|;4gEO@Cph3+zUYLIrP0%0eKHr+v9Rd|OvC8LRn#!_jy%Yr-C$73c zBb+YoBSgpP=)%rFup&D$UZ}|qy5*GPjM`+<`r-Y307%Nx1Uw>D`F7fL7)8J|G=P)U zkQsBq_N0p(vz!{hulhNBzK3`iNfjhA(Ajvl|G=H5c551reV-jNJnutjIH~Ton~SEM zW7JH;U?(Db=s4c#b7dx{2R%m`vx?$B z#tC6{4l5^&#fh@KT@IW=agtN{noqx9Rh7&P_d`%ztlqc0+rBj~;%!!K=~;CQ40yvL zf7wB%^(vKJQR6@h<#~q`UBDt3tx8nVRaLAE@g_u&idk%o=Oc~yg-6kKEk;7F z1|dxxcJ*M<0(~n|5Pro1ghYW((nq{D9t@%?1URfSkPv6)&D}KYp_$f#H|A7!1x=PJ8ySE&z!Ie-HeCfYC>zZ zohPXpF9t?I()gB@^`4#7oQ4df={bRbt}UzW3OU_^tKQP_MZntfC6Q|#F*qEauZ5<8 z4>XLo*0>?Q=Uu-29&*d~3FcElJ#AqtxZ=+SmtM|_2V#V(hHhFYsn7L#^*!eW%@V#k zPoTl)F<#XRDj?n0%5FPjTi^h!n@tEOu)uMPHOpODA+v>+261XA(Hg~CzVtN$+CNuACSe)+w6e!S;|cG=cI)-REF=qcyx z_j_uny)Oarm13*qt8MMO+Q7&$B0yAVT+~$Y?pre{4<1dzbV_H2eadm=zQBAL#jySpY0U@7Jyl62bXM@H14gr+)9} zx9NNSR@9JI@(}yv-MXN$iCcMqB9lu3mKu<`nn^ewiwIWk6li!@Th|gYwvs#g?QQ7H zYok|8kfu4$r`p7d{2PR^S zzZIkX=-+iWE{B@FxY1cg9*jAP9&jz-xZTbvqd6$Ta7c5|{37}C6V@iX4mn!GOJ&X5 zq_PPfj~NS}yOT%bqxjOu);$YHn~CS2r3xSe7^HZ_^xajF@rz_oSV(~5-u0MH?$lmV$W ziS~Z?_j3Hc_7*79z+-mNw;Tu;Zzp8d6$7VAifDI^5tfpUc7I1T4gZ^V zITGROS&;Ql6>k~+hlR};;wH=>A-xL0aA4?(C(!uUJ)>qX;-v}%jcCj9kwP&ZSvirb zPV9t=6fk|u0i*wUar%1!{Xf8<(r|2eczmP`10)4*In9yb%bKRieK~<8I0@+qWd%lJ zMcR*NErl)x?R^QuZ2rMnq}_s&Y3t{iJuv0wv1faU&?VpLW}ia|6UH2j!ixy>Wd%44kqrz<8@I;corc#q zexzuwa5NTeF4=E3_G&0TqQ)CauXQj&lnWs5P~)$e1^vjd<;ohjyC?;(rbI|sR$q?1 z0ROHWp^4Bv-J&x69d(|Vz_GhCF)?N(n%Y$C8Yb*fxldBR-%UIcbIM}R&3$>P@y;jy z107m1O0vSOS%SI|Os7VV9Fn3J|DB}LyP^+lyizHI`qMn;iP+NFlXh*8WK}bzOW;dM0k$G%DPr@ZW2OEt&-sG{s2_IM&^$w|BSza0M=%H zm9>!HpZz2wD1G;JP*1R?=3akbxKHW*VO1;F{2e$XhJ%UT8!N*jd_3o62vZX~W=OV7 z@}Jsq6BV$HPmaE0_&0rxstzx6LD!^U{6`upY}SmkYrTnyJXI(g<3AaRr`xj zL+wpC!zQ{6>04M}5TD2y4I%c?+Pj7WQ`)``nUVo1?SY4UUFEG4T$S;>sgmkH*`2=p zg4x{lz{2bVUJi9r)sfz@&GFc*3C-}Z@c8J+TYsT&m`}YEE>}jsXCuSr93VHDxU_ff zPdD{1f|c|7K{wNV8hCpr_g53Hkm#s=xRpquN9(WTS9*taoZp-O1E_Zg~-K{l?-;6tYiRJXARbfuYMCOZ0N>m_) zW}fvCu7mOridN{o4aEDdylJt<33~4UMn-a{^6!XBogW?E{(;# z8^oegS#=O*xkGj;ONsodT6nYK{fbX7l#8T^1Ma1Wq??1~UKhW3OTx)rO=cjf?p1pg;LQ;GhEjbcHI3I%rn6qbF%LqZF+?EdVIGWU9wUf>&y*w24Tp z6j6kXK6f(V8`Hd>*UA}t4aM9eNgb1j1!h=MF&W@jut=5(i*t}p|ERCzF#L_Cv!-k6p0em6HpSHMGgkhHyr=(M!}hv>)QF% z7fnqf0i`T>Rh`_T0!}aS^$ThpASNbl!bE)Nwg-beHf+}Zc3jhP6O*L56m(RqC$^Im z=n(ngE@ZI$qw>e}{HrgKkf&;*b+9Erh#2aZ3kcLz)l-Azjgn%RSG<+I1Trz& zJla%V_%O44k}gT_TgWoQ?5@_luI{@Fp~+0#Anfo`*0^Y3Nu}yE>Amx`y*}X@jEhji zi{pmI^Y@P(u6d`8TaJfR{K?K!m-^b6(cd%M8t2d9=3#^=h}}SyPDI6QsJ!l86)Af?Kw=_D+He2dEo~^-rCe zr7O1RtG3$cbi?-DJbj&~NZqN9#acITm+9DN9U31RY^e&>_0Vympz<51dPTgrM7yX3 zb+tIXIY=6O?1NEYoVX&93#^;vi(W8^El!=jT!RitaO3+@=TKj(AqyX~iv7dl9jE@m zO;Njw*??S5PA!`Dzh920C@xWU0gKH?3=dpjBxE%{9nWF;(d+fRpW>Ueis;|=s0FL_ zIBD)p20tlc(Ye4sm_O9(XbKgtXZ(R0N7!MJ^>(O&aCMJuVxEr#+0{{5Q`p73-pWdffB`YzfbNL;z1nQnYd;b z%x3))JN~j;*9BPH7JDKEGXuE>3vTC)5?`+I2?-@DCz>>JQrR+coc9<{{3MnWScWg$ z)+Q*$Q0f`8qqfEt(VW(YLd!Xtj;8$zq6r56zD*jW>QulK7#J6jEg#+NLVm+dzmqVg zQit-OPeq_^nx12GwNds2T`!({Zg#)SG#IfMA2#E2Yw2_`x! zLL;0sFV>DxLJs?XOb@U*J}$$JGWI+T+s*LrOLu)-7`Pj234nCoEr}D}LJIw|hhHv3 zCiVg?FTFviMz#O|DySF(?U$bN$#KV?DkQ}wC*=*CI*d}=rVu?;2v~gU`dim?VCE9a z%a5H3c+k9Gz(y?}!6}1!F2uc5djN3CeO)R0$7vJbY`dIZ`o+631@4qrZJR zcV2YvVBnACKVw18!s6xjnENO*zsDWJ#9aJ_kN44>2v|w4;wJVqL4Gd@^uCc@walfT zIq}Euh|k6r5>Nn_b+YYp{7sdR&qX1)wUxU1a@+DicmX9Ph4a5qC96Y4zSXM;~{Pc2Fl(`I$2!&ws$?_$SR;{@@T|Q3ue_T(-3YV zL*H8lJ?obVB(uVu4}4$FyY;6*INPIgtYvb9@0qmAfao~HRk4SzmrcXs2yk-{mtVzi z{r3v5ZI(#@=2{d7V;0sLtlyX3F=0#f;LE<**k3>FNY=-TW2_T%(rGMDQDN=#B4)A| zM+i7Bxib42W}{${!}P353vmD+skN?9iz`=3vAST-X1P4yo_6QjV(n!Dx7YxHGzN=w z2<5U+XwQcj8kTYx^zv5effKoWrAMM3s0ITPgyyv{z$Iexsevq>H)xnpET7cHuv98+?rVn7pptx z2l0hu_kE6Q-WnAg9vj))NS?B7#$)Nsif8GUqZ3{4vj36VO2>$qcIK-uOBwD7tIcMhH#pEgf43c|3zyxh=_8~%x9g#<7uY-z6R6w0oa3cXh!LdnI5gEQ zkA^~mezk=$SM8+umU9H-Bmu9y!2u7=vm73RO6Za2sifN;a;3LZX?q%50W;oQpB_^wAdBRX&yvKk78v z7&|rL0Kj}|!#NY1)UdQ*#mTWTB|5Gz8c|lniWV(UN{pVv{SW1BEsQp9(!a8PhUQhawE?hEp_!y2c90=6Wkd=H;47|)|G@XuohBO^K; zHci)4%VEt~*)9y*lVE2JgW$U+BlT^ZceGJ9{e7t%`Gc8w+i-j1J%a4IE%Y4I2v+k{ zq3Ffu885LIHz{SzE$L;QQ{~pqNjHqmkXDVToZzmZzq)sE$7~;^WYJe-*fM+JjG2*7 zFEy$AacR*{>539um~(8}>vus!2N@{(^6k|=@I_)Cf z1TXj!AJ&TiWJc3<++Y>s4swN03SZHvNi3waUjhF6_n9g$kevhf?dDZb; z@~O=!3JF`jHY44_$9w}1_Fq2kKsjbRYd+8p^kWGnjWR|_|GG@7^AaGhaWhjR9L(cpmG>vbr>j)wDT*K zCapX`tzZquQ6yl(az%_^QCYN-B`=An?Nvj82PoF;v1v8DPtxcpFnar5ob`_Ne^*~vocm7QNIEEL@KF_HCG$BpH`t6DJ{ z1Ln{Yu&59sU~TO4L8V5O+8!LKM*kB$2=jmW==ZD*t^@)^b?u(*Z=cexiS)5yG9O-= zi{2(FzEqO_i}XQ5i21(l{rD@#C8uN&jsCy%A1DbzU$^&99d%?rtrp1T0}l7|y}`CV z$uEovvH;*Dp?W>@`onQhR1SsyMC}b7wo+?-9uGt4nSzMw0gyD~cE@V59HL5V9uk@l zq>M_L;=(4=$ z4?U6_6Jq(Ud=-|?;yG#7!+-q$SJgj9iWGIiwXr}+V=9zn@u;x6geIIHf!aYU4thfR ziG^lq7NN7u$!}X8>WC^M5;vTJk=;g6bxJj-wC<9Z zK_jlN&;TlcmgAp3pc<#_?b_crhfU5z%z7eZ0t?!AjQJJ6Cu6YetG@nlcy{V|5`6}x z(4zh_twEOq@A(%Yk=w-RV&-)gF`!?63%g=n7m%S*WIV?xb&^=)36UZQl8ed?3DS2$ zKC<7(BgHyejI*pTC#Ux+@lt)xRs3@60VJGNKt{zIT#7scTTMmiFuH_cj+`jd_=~K z6EOn?o31WgG%14cr0hp`8zFND#VtgHIfDkwR0@sN^qdcMtQiKC7D-hHJDqqeMD#LBn7zojYbbRMbz^OkI|=>yye~usD{=3r zyVzD(V(NtCbC1h1aIlJ&mi1$Nhb(t4%x zq-sl&MvAJCR8kvANs5f8(8fmG5~%=MqBdS31tr`DmQ4tg$bAKO!R$CXXJqxmQ-EsI zL50Wt-lWpBpGLL&t5vwN4ity108*WlkUWIaNmU=gF(3HMwJ%1A2i<%3o;N>IclX-# zvUCjC1D2L!;f&)xm1f}8oVLM9XuVY~sJ@}H(z}nr)|yhqW?%mP_8^LZn?Cwdmr@{t z)13yWDhPb|1$8j1x6JHKy%D&04Gezed%+^^;~tVTR4NsyD zi-LPuM_nXw|0s|g7Kf>pE#I$w#j=My!$e8JD9GPGV!_-Ifqh4HS9F&*+#^HcqdH*p zL`dOJEKBPyY8FVcDIs__r^Ye0=}yrao|$RX*QYDWONnpW8n>BY)GpXet@XSSdW)Ih zUJ`-et{EbhWneA}_Q|{qwwi4J(~0tHW01}3bEu1u5W)$K^2JcW_}JzZ5=j4|KfMj* zbT@|*AXl5j*?H{G7X&55Z&MH}zc3iYB!~Mn)TxS6z+4IMTuk>uw)WI$bUB`Q)I?!@ za9++-9ADckx*^`k3hNQJ@qJ;_MY1b32D{_44@P*wE@DLg0T!%gE(u_*6%JM4TU4>? z1ImvD2`&q_6@;{rUb16p{&;6^=PT9>fLZ2YD zt=G6)le7`yPRe7JyTb8=&^f`6uQMxl`Q>(c#%w&O#Hs!1K&GnUk=*sFsX12GW7(z& z<~*M!xPMSEkn#^;@S|w9w`AABj*9bKTj)#@?c6;PY7$vfF!%L+EBLlm*Qxu9l>HX~ zG5~-^h6oVc{Uyhjg==!`6GoS6rd3nu$So)BZia_2(L0eAzm0oyb=oLjdsWts6k((u zB|zY={qE+RadZ09R69JAXgmilt&Bo}N?_sFpLWmMB9&A+~q7;VABk(j(rU2g`eHK(Q4`;4IJc>N3<};$shM>;(Oa zH`g!T>$Y-a9^VaNoq<>rg?Uc*Gox`2Q+t-Jb?2S0#);Cl=biOCg++!2MQR=;!(GV{ zriaV=;&CQ+>9YXkvDC6 z^Yxqe`?s61T8g3UY9&AQlV0e3`x@o!kHcHNaf9Lyovd}A{#1bfLew>vxvyP4h}>rz z7spaK_2@;^wA&flj{898kg0mTqC0C@Y?uU4EpN72UST|3;OIYq-%3T7F59^&q z?yIBPrZF)c1`9n3J>dp<=itr{ztTK4{|aYUEq%N;TQ+mRfBp%$C&=NJkO#1cU|MllIPq)g>rBC{{toXtZSi-s9QkCN zKoe#93rgs+g?iiTg49+Zl}RDI#w1Q+F*?z zDVk}HG&U;l5*LAcQTd5%wUMIg3a)sx*O>D7<28TOc0!s zmnx0(_gkEHV38d`)OgTo0%iMP4@UpX)}#FZJ9DgH;g;6PBBxL41EErT{+V{u4?#ab zU#>cZ;7k2xt$DdmcDR4CWLVwama#zvOAn`ttCQnS6zXBo5oAmt7zR&5k- zdCg+x8)+w5xUDRZG_ck1{yWduvFN1Ad(7ArtBhPpwFg&(uQ!rd%XaccxphUIWQ~F6 zzK!~uNc}EhAIcrD-&cZ=SkY5KIhXv&`8HZebB31Bp>e+EaS0R=N4t7kmq?XfVQw%EZ=d||Un6L7?tV*e!7g;r9 zzUcikGQZ+kd;Sm5&$mew4LXsjnT1{X7^(k|v8M6m|KjG>DBv!@mSbd-N=We9p(4j2 z#R!sN!0JRSx4mrz|At;cN)${rYpM|u`w~<5 z_)c<=_JLqPoq^tT6ywonco3GqnUlmc#<}oo!8@l-{~uj^Fql~ z;tIS7II4EX4$W zF)E-(PO|J8@J%5NZ@PEx+LF`vdbm%gY{EGLwi##8%$0AAJ-$b?!XvnD86IWKvaBhj zOd&}emiIJDsv65qipj%WtE#1n-H4Ha{GoIkvt}I9zF9!r=B>XaBeNBN8++$u+#~VU01D^fVy-X-Nt64Q>(yJEk)WrRs(_Y@OA0m%6QYB z+iq~d>6!@I5KnAD3-Nh96s->|{br}$+IJf#-Z0sU5wCGI?}D#NA0*{*$9tE1=Q6$5^vvfYJD4Y3vb&#SDkCu0WZ0?QbKl7% zo?$vfN#S-&;jJ+;9!KFUg%1nh(jxI+zUQXyP4h8`yCscx%Pg24g9n-qjz|5Rnj^KE z-F)9DDSykntU0jZ^|_;OJT8)Myjj$cfYpR7k4|0eMFFiqJHzS(r7)>VlKeyOWa?0c zL(_7~9z?ErcQ2Fb6+Mhq$5(-glnI@zjqSo`#d!#uXQ0o|*X~9*s=i6){e$k*J%e<= zP)OqVzTn;Nf&)y3w#xnCZR7n-`az>z5{as=)&Wi%mYTXKldX9cXV%?`0}&n~`l+^C ze!?rGrG0YeLt)Hy5i9JQ=}VZA3e%|Di;5gtk}hl04&=eG6ohs3;fH10eS>OjA}gi9 zXH?>eQVecRGJKfQ_Z>d-6Z^eExosFXFxV^M z-x58DJa<0RSfn^xkd~?wFTB3(ruZFt`iLu%I=1h2S3%uxN##pd6Pv$pN^+YrAwZ5v zJV_8rqx$yCGiG=Bbf_!_jb2WDY=|uFU0v0#Z7-aV^e&bo^F_TV-KAyTPf79aT@{k>hG$37Q4BxRjZ(h5lOx=#0FdG!=nV=g|+{%#G~R}d>H3Izk6dk|P)eW~ui zlH10ATWI8MqLsv3D7+RQUt@6N11IMG; zsWw3Yi?FY)&IR4(8$l48kabAx8@>;vF)_aDCyxP1_qAk5GilLP{o{#2YxMwB@6F23 z$BM<@eaN=sKOqEq@D?i!zp8Z>R|oG6(r|B7T*Y3e_GGkHh*oIG*$UJxJ6h~|cMK)l zIFI4e{ryoAnW}ZeK{j3kuwj_3y~_is0%YrfBQ@z5)$>wCL_Cs7Hy{#l@wOJWL!LOd zmkwIacM^bcEfhlF6n(?y$Zj)0l@R>6fFdH~ku(;959O4jd;>w%x*|$undJx&y}Ee- zf#x}}_I7~)RjWU-Pvya%(C3rtE>kJ~WfEqH94Q91iC-+Yt;J_Yr^TR<|5J@8e~z|j z`B3S!HY5JNf)=|le)FL^uSyX`H49LBqWeXD&^dV|TFWr9$Y#UM(Nv(QQ{^8JTdA@d z1%RJMcJug~uUkKwm6faIY2ghKrO14`EVIU!n;5eMsUolZ*ntc@ za2NfYE`gHAC0IFv-YLjDT|-b<@yuXfpLR)@bKWvk?4JE8{P&-ES%)^>M+Own&yW$~ zAUA56$u2ut0HrfqUwsO#CaRig$SN_PN78*b$ zV~0TU+7Z#RZ^-dJd;XJgRGIN-izo*~#ZsXUI4I%y!^Y7p))(77s8BFG=2e*0026*w zT`_W%-y7qpwaBNLnR1I*Pp@#KqH1?u*F_TwiHBTTZSL{!4D}CWz_K)XLHS0X`W!;l z@k&Xs04Q{ZZB&MJo@PUBL^cwIVJd=HF){R@hTQb&eL+5$DDsVm97t>)BiGKd_!Dk! zOp~6bbhCKWKx$GZpQDTB2VDf=-Ot$1^EchV>(_K}y0br;u?=?tIrHLZ+7fZ3zI_U89TueGK zI=c5+{I0*>&{JJKJHP}j^sa(0gnN)BO;Z;4(D(3DFo1yfqwijl{~UF6*0YJwZ)NNu zH!8z~9tT$15eBD9Zy}3&GbG_|=~JM@qjz$j#q^GwPd*pS{7H2jja-&+*IM~Mfc7jf z9C2&%oG(L>N~9ToAv>6AiQOL8bm!hr0+UehsrWNpX|)x0*^b2S3zw$vir!hbPcb5S zL&or5!`IJb1rsvxqtlJM{{Sa89%9Ynfb7ViN&2h*0A~v3SZq4%Kg>4&102wwPZnEm zTDxaPJqx-cVHqhJu}L(;gl=DR<5)l%k)!lr>$o#2O4rcf$Rq=t2 z6uti;qFaE}5Yhf4<-UOBE?@HQ_nA<%%GN$+xNs=p;FJEXR2#rKNIzUDGAR+WyF#`% zDAcFj^e?&(Zg0Wg+O%0K+nZ;OvF(c=-@{@f$7~0C7Vi2PO{aGoQE&)M7=frLX|J?p zt^2>z_xM;FA9oY=598>|2cTul)If;YsSVS za?`^qW9j-k@!ZqwkCWZYY}0ZI1_A?~u*|;x3?n4F#%-rBl|T-VVPuo^iY3h>m<0uZ zg$hiZZN??UFRHaRo&jOBpwP+zl$GFdrb9B8X9L4SNL-Cyd;YO<*QsYTTUKWK0J311 zqAJ4TF%5~_%OY3om}k7L>(K*(D2TrR3Qbwzxr^_1Ya6!OwiDZA`&}3o#J?r@WGZaE zrv2&BmOZIy0;e}%DRubhrHe=4Jme`|FgU*Zg?~Y!VrZa09Yzuzx1+{LD3m+Cvx;yY zV&-4|$ui|;PnKOpStnxd-Rmbk@CeQA89A@bu#?Ch4B};AFvle&pMu2G;GuYE_Mxky zsvN~$6g_#j_^0Jmp!(B0Wce#pW;b3^H&C}BHSfJ!c`;$Etg;yAi#E2c1T2$k(a{3E z^EdwVV)Fe1se}R{8F21=KKAn^$L~LT#v*rp)FMRr24pK`%RZ^F)Ok9pYZW}_k{|Q6 zGxq$Y*-jX}NLZgz2EixH@2!K(xUihU+#Ao=aIqkv6PzjzROKqtPHo$9ZNCPdxfXn` z243?n-7Uq59QRKC=~N!biQp}(w!@ZM_6=GbKqKTx8c%%c%*agXA3w~dBj&|WLvG75 zj9AVIN#OVETnPyOMXn3eza+Lpm{ZRt*g51UvW;)Uj)yJ8y-dR0c zL3hG;nYDC5qzLw(mm3da`tt(q&HkQSUyV(FsIkOH$0thNtxS4`Rpj!NI2opr#^#P# z*>~h!ZSM&gC$LgF__drk`3xy#bm18{#XZR55fUiW#` z2(0GgX1HxiA)obG$ms|FrBNzCJR?DCVtmav+9_zU%I|Xw;A)6mLgfuG2{$-K4;7n} zikvqlc{lZiZ+zb&UPdx2bP+7o`qLp8h=HS&>~w@o%Yhqliy^LyvSTx0+B=r|CBuv+tts zGA{~-oYhB%M=m1i|Aa-ta+|IC6+{)85L&To*=LC)N)H!}wW>3NdSoefd z=><+2$bu-gk-1G?yFH@CNr3ZL6p>Pt9rSS7qVE1k%U{c{kNsr({sZvT4N1J|rrwIT zZe)z6Dm%4*-fy4s>^^lDbTnA{VR@OR2f$s{R~!pB2pF`!D5|SstXxx4|8Q;=SjGYO zexs9$j*g9|rJK8l?n0bY%+6V8pE^cRpYO`7nW^-(4Ry5EQ>Ff^iLM+Hor$u`!+|0% zNvbRfd~G_IaQnc08LIHMZs?ambxhTKakbRIvHD0UCr&8kqiU%lRw&=?`6q5SHwTcT zmvHVOPKqrKPQeMbT(J%=QIx~PSa1rMQk7ZT^T%(QSHhSSBcW{Ofe#CovBBlGEMow& z!d7fI_@dH3v@nSr$X~%JNZ5D}D}-RITBB{2z8e?1&T}tCxH!t1g6N1s=a5VFy$LOF@ z+41iXXFFdhf`2~-9vE^B{o5CPAQ2HD)skvh8nhubBBnTcyjw1LKGF$T=mG~T_Ee&c zeRPTU7M>lKTZ=Kpjh{BDzK+YqQ94>W0o2JsLhX?Va9x&w(dU9dNh^dj!qSHeP9Wpq zTtK+rmdn>8Wz{x}#v_Y;vCe7^o!qvwGlC$8!KIG(@r+UK7)(292bb!;ip8>?zo#j^ zu}(1bx)51}zSeui470zS0<5h?-dZCJZn3*sPix{WEo_I_h{i1fz4Uts+z@n{Q$#BK z5?Sj`Dwz5kzj$JKS?RK3Cs|n;7$D(UR%+a{;Q#_Xb{Gl{XA*^E%y6K!+xo2I3P9(k z;nmEXKH@*Xw#c&hU6vw|@!zk-hmCb>Ae0Zs1e@vcRZMls z+A=gxwXHz%UC3gGnLm#bd78|~5qb+|5j~>zu^kEUH#9VwOc&+3#!-z@p*%V$B1O}9 z`N#(_U+mugPTQA{CX1U->7>jDH;7)z~3(}_JBD)Bnri1v18IW#<}KsR^v#J&a{x+xPv zLcCE(%GUT8N?(RHcN4bF4oS2vNeD-V7O;?wyN(@)xuzgDI_@eu3fnK*J%vkX+jZBk zV=K!?0=axJLBp@@>Fal)MSA#I}xZPS%gQ5ybK%J_c( zJlhL=`q34E0GiVLTaF8V7t<|eq;cQ{!JMomKbof%LsGB!!Pw1D-B-NVI ztK;+Qj(J}kn^QDc4cj$I;zKd{0`EO~U==E8;;g=0t+8s9P{kP2B$ z7N1I+Ic&*dAm>Ju9x%r^W$j4cKwd?bn&>qYa1Z)cBF|b`i+oY!N6;!n+KDlEL!X3^ zF^L$9B${y~!kfN|H2fa45&m8LGa`-J=k2GALGi@M0mFaO9Z~ByN)+ks z+cKdGF%hqS$T<=2OvFP_6$}v%;A1~RGJ^(~zvO*K>l30mvP*cO^Tm5-CMJH@ncxxG zy3xU4HZq!(T`@YcdM8FMx7_q2#}ZTIKF>mwjz@|oY1SQY-0c<9;z>XxCXdY@ge^Zt zIP!g%L5HdCN#)1hBX8(>&}G50-M5Iyo&AU`507`A@&eub_gTfQExgpE(dqlSh|jbL zW0BCH7y1_6hw1 z{PpdSRF!p;WESZ&Mur~F+*hU_CS3mjF!homL^N$9DIPMeQpqGL(q)Xp*-yWlVpSV0| z6l8Hm$V_Q)XO?^ro-UmuCq$0x*tubo56ctZjNA#=xNP29IM2fn*xMJQ?P|ZgXH)C! z%me2-_eI49iaid^nr9rm7cu51E3%}Sm~Ly~Jr8_~14l5Q{MOErLJJrBcPa;-MisSo z=g>XXf})#=Ct@PteITo&yDRD?Hd&bqQEjks#-*3E&#w0JcJhRVwsmIER@>t{Qh z6Dg$Kh|dG#E%_B6E-*i;y^sgIUfPw68|-a-QoJqv#?+4y^EZi)@2&(7U8jEP3mTLn zE9e**p%46LK%tP7Yc>qjVhH0hV-I0M$4Qyu=+NhbGSQ?=qEte`Gk~=_p=%1p(?5Qw;D-1 z%Bb4Pij)kQE~`16O*?qM2G*7wdT0e2$TTyvuw?}dG-&hl$Oh}gpy>lJHD!?D1nTTh zi}@f7V1nQ5Smky%8z5N0(rVS=u#FTbEes9D`KgU;uc0%JH_)TyeVy-U{jv9Y*o2r5 z<8M+Gnsb^mt3YY79`L7=UkIr)H0<5j(x5$Gr*c<&_FtBT|3&w8NP>5`cU-k^K-#&| z1dfCby;7W%oXBMb>VToOxz;&mmY*>ErzY+F@TWc`!#Z2MfEYchPv z7d(y{jL9~O0JhCwH?q_m#L0&CA-;_~@<;&WZ-b;U{{<}Ulanpmvo5>95h#8i6b!hc zKM{Ylx>aJclab&^)=}P!rTU25pe{_H0Q5qDD>O^%b@vekLk02b{X(blN}(XbQSq8hf@~`0RsQ(fU*adjjT#O1YL)>3%PYiBiw#{LlZIC6JsGue z*r0#5OX{}_P+AF1QVNY+kJ=Gr?lXI^JaJWGrsjW!uMDOtY0T{CpR_vFzm3e(X$fqn z#KVJein=nH#^D7&Ydf)y|Gg+7lgi%O`EHS-zrm>j(nA4!lGbp8*#=JLOsy|MNO z6Tbj0jvBjrB{U$~M(CNIIYI3knoBT{!Qk=1xsHfKsrlM>BacJy2RucFwQdjzC9T>N z_L-0bm0c;&%8<%fn#uK*-miX@$%COOD~a#Fb~^`RkRiwA)@D#M%)8DDi5>OeE{#=$ zVNWa67eigdx8?93;0CY1@}Q;jY%$r=()^d7HxuFv@WnYQmA&Gy#UN(Y05VYUp8R)9 zk4NMI)rso16*gvF7+25;>L7i6rU>n@TH;9HT+7GJzhiCL@f_{QJJ}~MT&$c9!vh{} zalt9HNzs&{Zt-rO4q^1E zz#w)hDgNlCxVYHAp(vYA=C_>#sc5tA$YC}&ImTHTmZkY-+2q-{L7U13$h2wghbmK> zYeZ0S_(aZQ`Z{_yJ~sAcqv5Im0Fl`SP{WW=)U#`Dnk|$7=my@NKPmG922zTm5Q-uJ zBoy3Ijuv^mAMlaooiHLo*_T6le14dU6Kaix%uWI#VM?W*#8QoB642kxRL!I)e|?jC z=XBG+#K{M`CVVw{uQ#Ml(lIvJKzJuLqK@yCeJ#no^UesvV1ZvYK>ZqV76b8IT>nu= z!EzRD>3Z9i0-r`$k!1r^#l=_U#IjNx%5txptRMT3Mm>y)qYtmLon?on-=x~d5c2^U ziYpcN0czToF=yI}@f!r_wqy~UpRW;4{vFPdD~b}F0S%H8b)N+=1whXW zN9=;1i1+ER)FMLu0jdP9GWKxsjN#dJb2t~KS#PwWJAA|h5Qpmiir@Oa2(ET26f|pn zG--DpGIi8wm)j+d5pUt%N0~milaU%b@M^#={SQEdDutb~<+%*{{r>KZzcE0uyKn8n zWyT#xxcx!Zho+AK9_Xz{I4i@dfr9|NR67e(Xdlyv>q;D|;(SWIm=H*3)Q<}o zS&j>zFNJ;vdF?+41mj0MDbItZreT0+6(m{7YQJ#H5`mgpqlSucnyAJt9Wr1W1s>zP zgP*B-Qp3G`LdhHRWe?pPtPftW|6+8$J1;c_B0<-L=j!|F1lIh8KkstmJXr$-cPY!@ z&m0SDh#E|S^Y!V23e*`P$<#_aFI>+{GzvpqE_zcge@^x3Z0wgVw4^`ld|3Git37;KGmNQe^*uP<)VxtI2omSFpQMFYD z3t}xoa&YU9$^>2)ylLCce_hpr0V$odcb4la6vUX$q5w0DR`fTQMJ2CM{j^kCn>(u8 z9D(9&hd2}aNQ1)&Nx(mX+A;~8EU6qh*M78j8FEV_iwJu>R}^(2iZC#f(U*P~K`4R6 zC@y<&7-^NobXlfEDKE@+N$nqC2pUqRCREUt-EdyS&I5+Yf8YETdaL2q7y2~}@RReM z`s^`C8YRb732_q>Hbi}&0YpODI6?xzWLeq&0l-|y&N`b9*@yPO?Ev}pS!vn$#}TFOpc!;?eFHw71MJW`_l|ErZ+jFO4MOE zQr8KB=lWDy^YZ@j;>4TVQf&MWH;RYx>aJa3)_}XYlSxDl^D7F}L|uuwA%NC1pRgGM z=gCG;9t?1OdkCf1SNzq-M(`mjn6CMPS~aonq*YWKL=Gy_Q;;BUH0z;<2g}E#DE3ym z3YI~_Z6GBqK-{?!KR`uKEa7EcbXWH~O#_VP=A%6Q-($=8mb)==LxcXz@r}Sknabtw+tpDl$W$|LOA9=Sk{)m@olrVe< z$_3}60;eEVFTVah-n)GJVMJ{5PZ0LWEh5#xIc+6)KkXg!6kkj8efpye(kv=JUSd>d zS)%mbYXaZgJz?^@wy{lQ{I$??aN)8=9y2JLLGm@D^0?lEhj*jA?4MQ#J9##|5C|QUW$wcOb%6xS3acMx2vcG6KF{K`Zd7Y1wlUR? zOm^QDox)%8f&N%28cC{~UHB`kyL5N}c0ybdmzCDyd*5}xC@iN`l^Is5ADE7swyn5t z9LnK2TDiH*OqCJz#-D?@1xks`mfT#{E@sispDJ7lJKi%QV#`SF>@ldOp8`{QsJFS@ zXhY7Z*`8hr4!&;~!G%B7+45Le^3FNX%mfm+FqjD9Ipv%-_dEn3CQvgIYGUqB^MR~S zVq*(enlBl6!qM9lhgYvZ$3zEx&tAD>N5~ax*Ts+$gA3*bk4?3QNC$+1#h#fV!|`Fb zW$W~y>3kz%q%jeD2Y=3?7(~e!nl30_=J_u4=G(TC|ArA$km4^97Ni*_sb@Hr#0&Z9;pf%_cBs@yB^B|fTEBW^gQ zs5%SZk2_ZhNh8yx3kY*YfcR;CCLBvr6Mioh<((OJ!6djLzD>rl(X*NOdZ8hT`b6gQ ze3#Q#mtT+m8#ujr+arxATKTa%I^Q% z3~!|Qg>vI&w-LylH%8p62oBgP%YTYFL|gMPpM9wzr`%xB168Y*^*t#p(xoIrGZFJW zyKCcmNqJ!08$`q(RqMXr>|+%uW&!uziV1FJ_XhHRnF{dWAwRtgzXlXk!$xn%qK#F9 zLP{p1gLjaN>^SS-qZx9jsl{axe1ZB&Hz%QIuDgnMhC#+v6qXE?jdnqL??{?pTP(W* zk$Aw&vgVC>yx1M=ub_~w1KZVzW|`%R{CN`XqEJ~A_76Z-xw6(l zpn%+!vlw4?jTWjm^MAVmLQt&Nw}!1nV7=cU8L7QAwzh!4$!|=U3>l)NO8d*I+!lUG z!+gmnnv#@SYX!}33tgt?3RVB@4w5y`l|q>jNZVk0Z5XBIR(HdK(<)X;aD#ea+!l=i z5*d`m7`D*$x)JDbiw((uyyYYGQqz+uz!{AFa+bk|deJT;v4D`UVM7sw?gnO#(FWSB{ErC5N6z7H zo3FE!8>fu$F|5HoZf|0K#^Qxo>gm-0=~jfxpDWlHMJ5I5cm{D?H%p4no@IV+82paj ztoh0!O43empVNQ@1v2VPGn&Z-X;HaC;b=z2o=@GS34GwE@J%w`oklDB(jZKWS*Aa` zQ1X{<_`gQ8;TC-ngRrkBQ;kjfYpw0v;WBvkUclk3dWnehO!6QT*MtN`3^FxxrE`@i zyF69Kktw$%az}%BO53uWNtsB17Nfk<*kG4_);wscH8Q46DpC-?N<@qzK z0jGMOeDQZMnm+glZYstc@&8##6v^Uqg3u60$~488sUbjIRsFACn9LDmneT8#VtWIe z54OYyzSwVe`!K=Ka==7H_0O-mbOaWtFr1u)9G#;dYnAy=z%0QY2M4l`~(l9F6PqKp*|_or}h6G(p17WE_5O50oTUcM23 zgS$F`Q;%A`9WS1ctNxyZp4ew6(K?5UXE`Cs+FD!w>=T0uX(nQ;YL!LLpAM}kvqNV{M51mXtDep{k2jC+q z8mvf!EU-!KnQ6J{UX?4t_YB9_M?EXc$*NCl-+NjItPBT`8UdQ~06G@a$~SN{jzTajr5Q#rlDqV zh+tt7XLdC|J}G0x)Uv-6e-tqWNf$^QJ(292SRXv`Ud+LkuAljwH}}+}q5?DqQ?c1g z>`k>{$!AqCbC8p%d2Qe5ZBpKjWgZEA=GB% zmTSD)g8MG0*0gho>+zcHi`F#HT0-#P!yx6oPM}sj;R-f@8 z&7q9R1R*2^u{!tAa#CE(w4&oG;)j@bs#Muww^vD|e-M27ym_2OKtfc}iq(505CISk zR;1meQw?MzSW8b}670cN_%SwvPVp`uLxxy5H(z`Orv{glf+~3G`x7`(*myOd-=?A? z6a^P`{Gx51l^P9qvpie#APKHKAXYz7^mW_e=1=DdMsnLv^F~}pP(cgtb%bK}&vAeU zOkqBVOJnmh5pIKD;FX%-PaWy-WEIx0BP%1z)ppWA9vCv!YNiao0BJ)x8I+`m`gINw z^{+Rf^Y+f~=N*Ngdp^NP1T?kUKXtlFHcih1%I!?fN_GLM%GbBImkRg#Mb!|zM`Fj< zMNSHJvA+4AJdkT@uB(23MiQ*Y=5g~KJWM#AmP~J`%&7=zZ~r~RL!z` zL1B4qGJpAO098n3!g5EbCFc*ndO(W^qXzQpP)r>bwXKl|dC0if#}Y|c1>GP&x?GfU z()Y8yZi#<@r9b;3W4ry-FLYist0Wy=c=cs>r9&Ugmia9$e+B4;3ve+bC{ih?ogc-F z7WhP`gO-w2gzTa_kNDNaN5%NJFvuzHah&6}xTZ2X<8v`6e1(_4uoG+O{F=MCS`WI{ za}qIgbVC5KMuOHt5RESsmkw@hs)>_Ci4L%^$yP`;D%B}g=!^T&YHU<2 z)zXJg>}&d7s#I~;pB~v@#+b4ta$dB)=6LZYYs zU*}h2Af1~<0pq{AexW@ZN(#G6vIc^i?u0|zK6t#~_%ar*h&V+h8c|qUccjK27C5() zxo1!gF=Oy&OzrJV4R1>1{uoQPzRdok$SN|l`XlYewWn|C6?2}bD#ol4m+=DXW#??7 z9U+e+h&D`(qj&WM=P_~kB*>Qf>s#(roPBYNx>4T|yRneSp|kN})L#zRpcroW+GxV9fftLCZq6UX ze5+rZCP0-+^QGciS5q`b*iFUo+EZp5qJW0cdkFg;m18wk=U>tT501uMH}PxfxHN3l zZCYGh!X;Lwe4M|VsUpGU`8vU0rvH=%0cmO@tEGW!k$=J^2LTByvku_&B#`Xzc?qrT zJ|8C)UcT3AOCX1;L8m%fcv=K{bV3WuPfTkxGzUlw#1t%lAKl*9LthW^5TGN#UsL## z<=c5uP>iVS*!=6EhN$Unwmjs2u(hM6FPz+iiWDHCRmExWp;?tXlK{LNnaB0qG&inBQB}d&9trj=py=nnDWB&71#J7 zBaSHuG+O!56c_oJ(5Hk;q92iADZ3U zq3IY&8BKBK283EhwylnM68B1uoSzPQ*NSdTN0IykAgFNia_&u?hTD2%p;Rh39)y}e z0#FQI?al#5F-hTF5{ZNnHK`E zCW}@3t?5!?yAG?2P@xmN^Vi1m#+7FdRl5fDeK%gOM)xvW9id6#{k0>vf)ZlFM4atq zzucaE)h5IQ2FGFL-r$wN?gvRs>vhf)N+oI%9m_P7#TMoXjM3X1G0|2&fubu)Yjy17 z;d&<~#&If*CR>BH-;T96lM!qH0(sz;{{#DX92tM1zR{nxoN`jF(H>2EVAlt zfjtO70<8N_2_+Hh|Fa@YXM?WJ z5(d@Pzvj^-K~ey@6h$DRbdvyB8vjEogup)m;^sCSeQkBx0bK&k1;VP(Bt zXq^5vSp1xah2$HsDRT@4tGjE-Ne;0$v5%?&9;z&aJi#jrM-p}?qaW3o(L zMT!=Nq*P*Ag2nN)6B-*WR^?%kYGbCu76SRLp=paA9Q6E)P+4Z3La#d1HbV`I$}=DfNrVDo zu~&-XTDrNCW&r^LKMK^%mK9SRWT232knyY$;EY`;4>yf4ZQvu z|D20Y#~XuKN*3UE-@ zA&a3!S+AAo{nww^eR?Cd^(=k8@m%@F+!N^{`8G~iUHN%=c0=<{BYT4_c|>P@4tvX2 zc>2QZ+{;H`B*{uFY44GfPkl~J#eKpTH;7bC{eDr&6qcOgk)ebWu_&Nl_bhTZ)UUNd zLHr>+md>QuImj@Udjk{3mt~sKKo7I4kD0>4EXBc6V>!2!5Yj9(x>GDlnApN9d>yc9 zGq?esfOOmmGCgQ@x@ANzLQ)ajzh~QL*he}LXLWFqp-Y%k0 zGb_utc}kK7QTdUSnmL9@Rr#)~bNJH$IkU@r?a9drcQ+*YlgGyGc(M~hvWC2=*Z+pn z&u|KW&VqUr-{Jp)K5Mr&kX(PJx%0eBUTYL6BomnK(^J?9lw4`yvuW)oeZQ^=4f(Xx zhO;exxqB!sGccTqk4?uNCy-_Q)+SY~Qcb8lE^n#vQEVOWyG=(0I+O5BXR`S#{U!7z8-eP0U&$>P6ryW5l#SXb-v{qa+!k`R&Qf)XB4^ z5xlV4Vjz?Dk*PU#P5RNj>N1@>Jx8E`+1U1B`6edul>HOTq9OL zf;tU{p1#B`3!f$De)@y#zC###dCPQwJ*v^+QCYEeCXlWF5|u!WAcsXFHG`p#LbAP( z?c2Q}Qvx_M$wpI=RWo>jptfzm)CP4W+HYVvnonKng)HZXv3AV5`~&56L=)d%~$ktJ)qp@HYZ zz7xGH3URzaG#q03K<14?u~Ts*qp8Zs3Hnq+gw_+^msr(Cz(FRA=u zwN`ZK0l3S}9p(x1y}{)F7b)Ym2 z7yx`#a-MPJef3J|A3&g|C=;t(I~FjQ<;6{MIZy{*1ZE$XaWSBV5t7wcys#;uq+uDC zt7~bhp{*ln5G0!iCNtNse)s<{^QR)Yo$|kboJ`sTv{O4L4MziG)v8#nqH1+M{I}=r zrhNnLp=-Q^q;XhIUI*+C#&@gY1b18Kc6u{Mk!G^{TPmWv!o;sE5Y0|1i8fO^_6!8m zHZ&bHPN}=oa)`zNfh>>xB31d^@vU`tv-==>H=YYq>WIX>X((eo;#ZBD3rpSwX}>+L zqKls$-2GeIHOpQwFeK6=7rEQQpK&n!1CD`BV%eKO`k6uBZGsFR+$?+M6q4x9nBpMK zH^_d9WBaO_{4k^i;_+tke}L%U z=5fSxOf)U(A{kH{Io_;E3>IjN=74fp6q*eS18SmKbSRrjybyzVpxL3W;GBoyYRV4^ zTzf9TiZGqkqz8lxK}S3>sq%t(=yq6&K&5c6_l@dm*j`~Q6_>U8r=1xo5=)ylNy1%P zE%q3J?9T!-yEMib)zvn(g&5(Dw$m0{a?$YDaGV2Fo!>eul9Oi= zAxKVZ9nKl*oI{scl&Ymv(;OT^O$p|QxVZNA&r<4?ruQJIG$|S~DZO&k7EsFm&N?=k zwXx} zed+Q<92X@`Pnpy-0Xe-i&iKAdY*XPB4`TNG^|0)ERBW}mG~?#*`rd!Z0DJTNifA@i z&Fwe)J?%SP2=MMO9QkdI>)LnIxR~h-WO>i!HUFDylJr~Zox8J#M15o_>K!nH^d&UWAdyGs_C_)(p1BYd19SX;5~QWBlT$x;vc9ojOA!_5Ck) zi*KHPtU2$D)Y5K;6ghF)u%RSZ@Jxg&_0aFJJ*(c$LT{6}Im;Hxs5skmvyhZ2kH~&< z(w*JNFJk`Iu8~s%I(~k*}s>;M*ul(hw ztB%3=Y0}(cGSrx(&kO}03u=5h#mY~F<3r7!IXt;zv17r*o8|08H4jGkuCB_xUa$C3 z@AYU2j`}9L#@IFGC*{uU?^*5diKqOKB0Ze#&A|*_coPf&Xap&dKF;4SOq9?KXkv^b zGrvPMdTMAexR>E)>(GPLfYHkzQlKCp0WdV$R#p-Q)mDI%vargVfms@yW2<3B5@|%U z5C_PkES8wRwc1OoQ-_7%BiJu?NZgLry-Vwy|I$T3fXmZS9&g-h~Ab$Q#tN z=tw1h*7$m{k33v2i9#2LVVT&yy2d|fiD0`E1>RO)u*T4&#ZzKD)`sMh(lLUuS zN%P11->0$D*f}63h`a(I$MvXL8iKOQeN+sMA0T0odE4r(?L~HE2}U-CXa?M9r*JUO zk}*p0zE?&w3e^YXlC#)~e-5X39}8@&@lwIcH6B}s9MZKAuqkbpL0n8xEdup>VbGO58IwvZeMz(TQ{lsYmNZ)`hGTqfTR z0695%g1mz2)$0gV=!{5TWxk+52xXKBFr~SDxctLC6*^E2Autk&%8O{q_HUlN8P_YG%Z)$EX7wuHPjPwy6=3Ii6dJq4U8@5?i;Pw=&<3CCv-&k z#Y0&Fp7C{x%$l3221zhw)B`5Vvme{z@_}P(>(>(Ti20JF%ggNh-0{kI zv2c}_mm?dRQ47{Ku=z7mP3nsC0h$p{E1|4hOoR+hO~e4Cqgr>P9@SJ_s;YfZDD0wi zC(<>dk$LiGAJci>M!x^hEZ?+6&=a$1Dqte1>~~g&rloCDhg}R0&%x5o^k)kA!7!zo z76vx4RJrxQlby4ea3-SeDUdoxN+Q9dk=L@`y+bG?3oujV2%!`6!Q4J0IW26vf6E*d zi%{%bB)MME5lu!BZ5o3tvJ&hC;DbMycjZxX$2w#>=5?8f$$1x?)t~ndz`i%=mI6Xx#blZgH9t*~CqGI8IjMN$q^pSngG_Yq!_kxe z6zV5Q$D)xX_TFl%4eF0WWSZ`)|3_}@O|CX+7rLa=D|3_q5EJs&%`I@TfmY3{lw>7s zzIDpdkbC|EjMYZ-SrdV6#iM$^EI45{?rdyV4lKB-$`}R@aIz(409cz)k!xw1ER~oL z4oyyv*9km8rq+te(Y0?!DbuP&XxW7NprCYQ(%;3%K@OI7+;HHr6k{>!^z4@K{f+US z44W%#g=7(IaXpupgONfpY= z$fpKb_YDq(@{PQE96fy9oU!gx~`{G{E4X0cPhnYgo=V%-jU(z}^Y5650xa!NS z_LZ6sZvNm4KfE4|$xDj~-!M^UNS}UXkO~Z$4)`(LEjQdzLG1qCAfCgvLk&j+ubxNV z&=PaSZ|jebcYf2!8y{kZuadZVyLTOLIk^KV15u{4I1oW)Tj?LTNBB-bMlvOj7!e}5 zcm`RR=}7OT4bsA4Ca@G(y{Y7%&rUlDlE>#R7FKziIqSGnT~NgI0z?>sL`M~t1Jkiw82(Y+ZTHYRA0mgb~=XXkZ%U0HHRcCXT5bH{r; zD@iU6M5JX&jYUfFE60y(ael#UE=~$x?z_l{fwoH5Wd*g&PyTf~BKhTi+5tOvzE&hh z9T`TsI5GG`LvR;KF|R%{;=ie+*jEipl{1!;?j9}sRzG-|3VCzKM%ZH#a;8;1DDzaI zsXyQ&)0T5F;_y^N!Aqb8EqG7=^VsYWZ(Lj=6Z>>(OVav-0{M0JMju_sP`AX;WrrGt z6+UzD&^!p4Cu>QX)kNr`vIiNERSftvtrARg#m>yuwV;BQr3fH-2WB=3xV<*BT^Dbw z%6apwC%HoVOzhL#)v2tAH2{7GF{}IbeTJ==`X@)BwYPuWdjcvW3A;ba_2lZT%W6@X z3;JWcWtvQV?AT1wYT9h+pxVU~A=2JG&bFs^A^~FRlP10hz$?RAa7wgtIr<4|$$YuP zj<-%l&tJ~Yp6L)Zh8cs<3KFm34mGicz?bd~ zb0w6FqmP_HyYH2dk*%?~r%Nn>me>(U3o_ptg^_zUumYsr zgykAX{paop;)> zOcr6ltC~aTp@g%%J|L(gE>$U4Go@TU)hU59C`e&I&_qja&cSax2GQ`_RQ%g7u&r!= ziZ{dgOKqv`xuBXDKgW>+Q2@@WA_kErFl&|(5TmU)vnyKot0U5gB4t)pmof#19Jjvw z<~R9~zuC~Y(MQgaOZ^Tx!mLj5fdddFGwy}*@u}X=UIbauMQfBBJ%HmvP91dMdmAib z6x+y%_;p4hWYgF2ck*GAc7wURLL@`7N`*L8>;gWiA-35CyZ6qBl4o8Xw+Zm(WH>V(cFTJ1Ha~ z&owV4={h#16_V@o^K&|Pi(qLT=eFZs@(uwwh2yL`U zPN0z6;$4C_Lo~{?(*gPF_g636eXsf`t}$=EQ$DHe&Jt%5V~`W8EnKvu*!kv~!iNq~ z*oU8ZE8|By>uqfdEI8H;y%p)Mr5)2&3O$P{^FDD5~o$s znBMn<@5ju0bMQBKl>?HfJHKCWeW6(*ot#>ll+}DM%GEdnFU_O%X z2v(+2Ft8<>3|3Vgv#fB4Um~g%7=4d3X?s2^WOE;tr>fUE3(59O)eM@8{mVM!8)y`9 z=+>OAN@i}p+bF<~TU>-5j79~R*X2^`y0(0)07!wwRvFf(W75NDCxC@yR+$+$sn?ZJ zlU`=_ID_cv1^vxPlQptN_oaUyg25xfp}%LMe=Tkw+Di-Ex!B%5)W<|?eOwM(e!gu& zl_u8@sJ_()TtOS#3%ll0u-X68>;7#fdo+_rPnK?-2?#y1<5;b9OwzdBaMZXW0?H#> zv+~f+6JQs@aCDO`)knQ#V;+UIs-9immaK!K(vcZwoFkNI#rW&qYHoxbqMSBC z0oh>Bo}~0NP|QzhE@kG&XcAC00NI6P6P`@Peu0_9Z<=AikX;l)$RmEs9#mG$=w<^{ z0`x4=V@`Xs!HRG-C?WRi$B?=%CNTIW{m*@{bryaWrZgaR9(QE9-1JD)&~O1ysPAzp zh;b%zQO-fu&lP*qS5I!QKxi)?B}{~0ez_wv_O4KG;%A;zv4cLptst(J)|{nESlZ-a zqf|@UjIgATB*&snbLR)%7STKh9v)u1)F0=klu09qG_>;<>L!|7r1MZ0DN{>GMI%u) z#gP|@T!x0b($6;Ksl?nN`KerQa)%5h&8HqJrFR23jEz4VdPw~P*!{S;kuY@@$A1j( zbjJJkm!bLOsYjlFujE6Hlv?Tu zuDQ07Ek1KHnas2f1?LwWc$S*>j+ZuqUxPh2139~-6hLtr|BDqOiVO&?b)4<HQhcc&vx3BYv~n|xzcWU0jmv~i zC`TxAEosrQd4yBbhCT@VSsNWs7=2nd_=M$k86hmAxl!TkgqyYt6+-_hx;CtO;FeqI z`b3y4eAT{h4+h9qn{@mCJy$S~gLJ(r$^l7W)dLKPmCFdJ(lO@496@B%x9q420NB?8 zqhc|aF?%qt8@c%}d9^T-oAp6bMCpCTv-i^=QE5lL;?)*GG#F{6pNzJz;*bg$P1n%> zkt!M#ozV>Tzr6>iy{T?4`VI3W-691QftESw@5dno%G8YSjKaQ5f>Lb3xpN!tMen6S znQZbyMF2LeNp6^C(WoJ?y0d>nso1_~e*4xqJXore5tYc1WFDX{UA&A?OWi#^jNFxf zxs{?w<2vL%_4*KV^T0@2Xm2U6omER|}j=~zOC zrySsN7-`Q~`sy0EIZ9hWLu>gX;YWGson7wi>py3nvejRnh2b>|BsKlEQFcKd;& zDOG}zWL>`1=B_9h3d9O3(Xk_!y-==iu}v$r7Bw&6J{9}}WPvA;@`Be)W=z(JR7_L} zNeE19a0g75y}Av7RXAwUD08*d>*eh{|KCQdkRtoKx9fxcg6_|5LTK_Ne6{^me~MVC z49UHH1p-ugR8d@DSJVcICUlh11^zU_s-Jitw?YQ|GU4ZCwmowlN>2^wbqJDp_WvKp z%{uMOrP?Lxt{xO!RAm~~X-%^J^|*(SP34n}GAHeVUvW9%c-~^}Coi|&I&bxIP%JVN z8)mx`Z`CF`c^3t^m^33_YsQ68xGgKT@`Tv3Agz5Hn0_mF{4-bg6FUM8;;GkzP|PD( zw4Q2S5E&CPjV-)M*$hJ+M<=~d@FWoXo3+|Z&S;}T3L{8Lr&_SaIkB7RTwzd>CMzt( ziw&nmj6kk48&*Sxt6K*mM1!d)fs$pCW#aS{_L3eFf>Z-B{vS(c9oF>w{oygXyK9Uw zx?7Qw&Vh7y2$Is>jP90_25BS|snH!$0@9!$EhXS@e!jmy;R1GDyTMb)<()AOkqmPfKFiR+b}Z>9Hdr&)xmqZr>r%Td~2I=Tn_q4RHnR z)n~5MZX4q1usJVfOi3Oy$0-JV?YT=2>gK$m)GBQIBBt6Ox48vbt{8?%6zq9wGORis zH-K$AQek*les2ISoislv5id^eWmsK2Z1l!){k#9WoKw-T-P>u@Z7S;Movj!O;ho%u zN3ldtla~W|XZtDpF_^$5fDGy__L*8aAS*#SBT`=47PjLkjZ=k6Sd22u8;-uC$tHN< zkhu#xGvRQBg?yTp@72@ALr>xP?PF=2-pDx$@)$gl(k%IHM9znRUOz zVhGcTa--Lx=UCv8&3wrl1dwqMf+yO!ZZTBJ$vZWu*K|PlK%Fiw@s>s%THQ*Bw`_yb`f5&2xSw`#h%qsw5m9J5M6dnAqCq+ZfKa zXvytuZGABLJR?&j1iruzCy2Q`&q=hh_(}QtUSGAPtIdf20vbf& zsFA^VZXJZ&@%Mf`RDmj+PozTwDU&>0tCH}X3HSOMTauD|9QOf3=PZdbY7GX@s|sv5 z$L)AG-reYR04Y`=?*xM$oH@5nVCz{Qx8N0ShgA5~h}p9=D=Efsx^4 z6!JPR^ncl_#}8FYQOEoJs7ym8ecJlrzG?Rbhb#vW^_3cBt(v)(45OYbY>y0n1X26? zCXoeUa4K@Y#zk$bjSX5RYR6J#+J}XrX_Es{K{@f%VN$}y4j}EW)t(UfMq635L7mX* z-?=%QFiuo0Ai*r9V0U*E;@~1$n{W_%BUCvlT`r9-wW@{7&Lo0GH`W(lGfm2Bt{JSd z3jSU6{B3hFxESY8*8=kX==6vp@>nu>504nKlE|X2+@E*; zR8vZ%yn0=E`0t-1&XQwrQo6cBJv_9(JhW>U(8@er~WWx zW(l!oCUFbeI-#7lvzz#7M&zDM=^GH|&QAatQ16}Ea%UwRD@%t`n9FRNK4*^L#$eFQ zg4qHHwr=bTsi&rFX(w>c{Fb)_ED9~5>Z4M;Ew9lor%sIdiH1N1~o z-3bqs7eCJ0Is#{fL346<88B3GnfB5ac65g?@LjKk%^7Bc97)dp@4u68_s^eiaSogk z-oETx!>i97+Tbtb=u1x)Tow}_^;J~dO27x3Dg-fW4EH0(>~7;!L z@}^~VVv3ax;dJYY9&AiX2|+Goz>Y1p2V#w6kPdH62yv`m#9nCIx`1yoT&yVJHXF9R zA+*gM5bs;5Hz?LsM10OuTe$f9*Gr!Nf#~2WqqEG!r0n6SGp-@2%fV_nbR*^Rpm(=meceQ$dc{8*V2f zK#WHO5l9|Td^8>wFP5Ic+z9Xp4c4Z5wwwW}8(iR>@BEfa>KlLh&@l5NfiOB0P-u)* zw#w;0oVR;WlWba4p5t{9N+gqWky9=i^a5|R6y)mJzV_#g=+nXkWlM2&$4PXV+|8vC zeke#<5Elvy{XmrxSNT}O_9=dR4}EMXMofCI$MEs}qK*}i=I*7@Qg zx}j;|19etS-aJTXJg>*QJ)pt^4iqh}jjmdeXUY(iDT_kBu9ESP$=y{aC zmL^LA-iWBmUHlBzG7r&By9pG|A1xPQ+;YIy&mcAGesqO3$R^XJ{S;ff4Ja>%Ok^*~ zkkT%|#`dvH)roQ5GV1)StmzHsAw!Gaz{u!!GG%_?k%{4lT5!FiDgreivHoSSxgC)7 z3;VmStzcFV%CLVPp=OBiV^Pcox%*#0LVAaPP&m;julj=-` z%I;oxCtTYm6}j(iA_pk77KQPK^fgB|)8q3dEJMY=97Vd(ol;J2S=hQ2#U7AAgkovl zePI1z^*P|%m#a@m!ZX&yxyB2Gz@0PK7uteZcx>iiU;^MMast9zf7aiMMUaX<=#w5lKZQGlzcr&3sijzCcSV z?Y}}^p7ujZPZgE^-vAFT46)A6?nhYy8ymDpMDiDmKcLFEq`J(pnZpr)4SW zqo#1CJtk9Zb{(zRi2F{rL;0TIrxbZ^nbq&E2x6&#dy#MW4~t@V$eiTwCt`zL`Ly4i z7VTB;D=tW{uZE-HI3VDWLvIA@uu)!5NB;1{zvrFfE+~#b_ro&ZOXKIWzb?vUz;&=5 z86)OdLk`o)k#NqHXV)Rq`&h{xB~}C!Lq1@a52}zI299wN z%NMJN6RaDxE6B=L$%ltVz^a*Gy4AKi7g#Ff7vZ%@WgvMxQK!iFUEzJN2f&{zL>G}M z1wq~1v9Jlb62*zIj1t}ndUfhq6)qSu3S6W~Pl1A8+oSczQN{Tq=5@U2GkPz(JZ_Qu7E_*%w^s#G1 zdv{V+Xu-vN@JI1eB*z$+UnmYP{*9bZ;|3DWl;#)Pk(_-hc??qlX5;A8c%6RA`yJPs zy!-P?q2_~RDIx=0POZYul%e0$V0LA|hK$rQ&%A9TEw7VjN7t3tmBoqkBR{fU{TD#} zr>~Bp4hoQbluSlbKLn`fSAKilN^G}S+6jp!*L@vs_<1v4w=F|3*@#A0$_j~m`ftrr zo?_`q>rL>u1Na?2K8KFWdvBP-i42ik$Q`;6TO>#6^A7yC93R2hCMk+?6w9k$-soF# zgy|BM8g|b;rDCOG>gX}c08me=Qp^4Yoy|E{kxALUaOSu8?k**9GGq{4hjNOxBlS^O zSguZ7Q%Kd}afs9GW^CfGs=lgkFLqdeBh^v7rCjPD8!H{1nV3KF7s3nz%5O8%)^74zP{G_2Mhk7b4$fao}XHpm7)!U<9b{8Li$KScLj>zkC zmEw$M5F@%KQU0tNd8oD)j-9z@cKrPNuMn>SW6W4Lx+mVNzeuyq@uJMB+xR}!+{~eK zYE-Pj+-%&8)0o*(TS+aFsx_qF>zdSqzNVU(y|d2Y0zKP#QCP&=U&wVRF5y04G{pcx z5|_(IkNiC0$?$#&X}1*hve$<2i@P(z#J~~Z>pv(6F%0H&gJJ7ElWn(i zgLz^jA}CfYX!SRderM8-6zOBi>8lvz70yb5B>nL6P>XQNgcZiN@FvOx-34vz@OpzK zH{>FXfo|xLVsJ3cFcubvR!oU=%86o}RCm79u6B{~5)n~S&P@a!|0u?aOPz=q7<2*o zrtGK4U|P+|Iol6d4o{U484{&Sf2%RX_*NJ%FU4^A(R~d- zBeCLm5#)V#saJtHw!yZSLBk9zNtItnn&_3zWww0mnVvqF1c`dWR$5xwyc+=^n!6x3r7J>UGA#65seDNPQJ^$Va1aM zH=BjxOGwX&vdU7gOS9p#49O^oRVLtp@{@4~SMe}m&TEHUd*VmOw8_oq15M=MLN z7CWIN+!-NtT5fRi$w2SdCgD5V&n=U2c*S+z`CV%H9uLIJ=a_uw>d{nEKCk-xpFeoG z40Z-*o(B1r2K&yVIZzv#W-?9odWC>trV^2g*SxKqH6y$gBYv08F90-i1^CPs zf@}nwy=d0-CDh|%ODL)UVI;gTxjzcXg~AZKvvd9c&EfO2cnv629~G0h|7C9IJWGXC z+igdpa2PQS&nK~qF(^03*t^LL)Xu{nu zbXol;a4{6xza;3_yc^q`B5%MER6qSS^QJLOq~gMUPg4a+=w}-@E6U^G2+3(>@E{j5&k}3Rh`H$&#+YqWe!OfAYJZ`+T zrSNKCEn8gF@LbPi;@&AWts1JodR;90L&MUyezcW{sgJhpGPSzE?!Z=B0UYT%*YR#Zq}1iGxUcUK~S4yG&cq z65LW|gUV&Bht;fd0@ z>Ar{U5#!NIKo@)fzj^ayKF6dAcI1;2f`G94dAmJm4l#=#fe4m_WGeq+16 z?TQI~!uE}c2zPh)EIS`2PqhdM~G>;V7TK7HqR%Q12TX7~dkna%gI*T+w z6+~bPtHBK!4{5*_^dGw|BQe?uIT0)tG9o3?=?Mw3u?yd|z+k@0{jU03Curdra^!SU zX(7)porZCgI;+q)B6v{WZL4{r^>n~8s-wLiq%YOgCyD{+dDs0gThFSJ=&1Q^RHlRb z$}G{WW@M^K8agghUhf57oyxrbfGxj}mca&iF)3q<+otN+4B!VgyFS<6CK!hZ_ddVM z8~wcWz#|))W=EeZwI;e8BLbYJ0zE(->P#Gbde&=SX>a)LgQZ)Y_85QcIA_(5qXEN@SHqz3hE0$O_~+#aIs3FF+ihec6Y zvO@$T;Gh?$j-GtWcxeY&5hMGJ*}$*gcD86YL;46KzThJFU<+vudwzDL>kRbgCrHRH z?)FW($B-ZJAzE@*qBIjmv;h%D%5e=Ek~a}yb26z{4_P=~us+h8G9Y$WI;(i>NSS4NBEpRHu}H3t&q zSS1&klT$x`16zO%>qKJb)E|MwTN#Nih)=)k=(eGXt4OsLw8~QkuR{bk4iT=Ua$jI>Ci6DI? zWYW9f=Jfe%v|k2bN^lfmWzRP+GzDYhuFfaL0%9GUD#`%FXA%&6aU_Kl=-SW-Cnv!w zXIHQNWf(YG%_qk(g6?X^dwY2SQNMYTxaJ9XF8AM$mD{{R95?Y<*(%!ts-+FkENFTu z(Wz79buCnIYE5-#8db>hGnaX}Y(IZr3(mM>1Eb*|87lb+^d@idXGMt}c6iYe??HlDRNU*Bgwb_)`YB{dugt%o%an>bnc)q+N zbVt+upNA*)zna~YCcmd*-69@DUQ^;NBV*f@XHs28Ogtab7_@?oQdm(gLs9&%w*SXO zk>?r?85e9^cbtm&dz-s*(~)!?+UE(XJs?8vq+-(f8r~X1pVQf5n)thCScm@D6R2BqsddDTrMN_9Ot!DYHbM-;}RkvV%Lc_myE8MOzZNHw2mK_+iPtJdFHV3sI-#Fj8n8V%7n6oD> zt+(2VV+e_pm>K{PC|}WNsA6lb46JjsGd+A>va4nQ_sDaG7e{ZEMDhae?#b`lL$M<6 zD=;HpcSgc5*)b<&QxCcT(?AC#=uanIrtR|*HHu1drfQ_NZUzt=9rZmazn3(hDgFiH zLGK33F&5b;gK6S(GmIG-!3K~ymtFnpYg0JFNV15&Q>6zgq z)VBCzcy)2OC5CXmTHIj9;>zw9c`sx5!GJc`KX=A8*Ap8??xPn~h@pY>{CA;(>{3F# zDrk`@t3{>EkeHFkQ1s~`Ivf`%2gzTQrB^B0ZobUXa_20N0`U!Rk24BV^U zz6}(+#lH2MZ*of_KuY5^f+eSkd3hi!MMPc_2h>Q?S_(vB&cdmKiUq#gM-nlDlC!w5p6`|%r%nq zALowp0dMWwsL5^Grsbs2U}WUYp7jcx#Q})y6`LXa73yIhk~hX1mYv0tozPWdY1iuG zd%ormvVT^+y*lrqL=_OEu}7Qk|3dpC9iDJuX?gY~CTq$`+)zdfnNA>e>Oypc>mfJu zJv|C7>6K44V+)oXF2z8FY7BZpj%Pwb!^zxoIK2Kn;VvUvXTgWJ3UB(}^CM`Ja{}%x zI;`!?6BcjzJ3?`1VEyM!;`5=k5sM{JysX&}j)(xvLEF2X(>dQ0d9zlbS4A~= z(6AB7VCLDE$6OSnQ43@AFP3~b$;cbFt)j1s?D%<73#V9E{bXKwTvsaU{iRZIh-IOa+Jg;=c+9|CteSVF5J`H##JN3xJt5_AKqH!&!l6kW%N>cf!?~} z>y0kThF-6!P^X@+KCbRFt9%LO$aP zZVZdI-}Jda?W3QgG7^$t3R102(Kf|G0$DE{(|{hV<9v-NF@=YlJ1hw$j8UR)$9UkI%TyRLrtiR|`n zGwAHvbZ@P0Xc#FHQ070ALYXFq5H3acsZRRP(+SK4?lLhK8kV!O-zAiF>W~tJ?7sFf z_%S5Lh2RFOnrwQ*`5QF7&1WhII6bMkzHq8N*-_Aj7MD0k`A?6Hui^S!ck4K(_ID&G zuj=71oW8{p=k}#D2vUUrnO}}-Z+#vsbvVq1C4m?(MxtLV!2Yo zgx=_KTS_--RP0i!#=FzKGA5oqH2VE-z51!-vJp?x&GZ9Csit%v_<`MCcezpFid@8w zb-&X(;?|gY?$A$uA5nS65;>s5kM>@8WkwKChV@j`-n(FL)(fBW#$A2EIy;K;sux5O zfoRmeWDgWbr4B8$sr`Vyf+xmAMC0WK*6SJe7(XwXR1ZrXu~3EQOzmv$?G}+}z8etJ z2#DX=+O%~uk2}br`>^qh7va71nPK9ZGTPdmKp4@yqGw^5{ppgQ20O9OjbA0tEBq5* zAi-b2%XLn8*KoxpmNHhH z-|ye*Bw&DISTn{p`##KhGdI0kwy=pNaE%X(j}2zZ1}1{nrU>fKczEPxf9rm4-_ei1 zhOZQ&FN=O+PGMQr*e**u_D->}w6Nl%NR^p}17C&?aL3dStr8L*e&#RReapiz??EG( zT(&20M=z*0cVQTqq{x&uZmAlPHD>FPYslA#{1>6pR*i{@h(an@D5yv*$JtOMma@l@ z@kXSDVW=q)fYFM~{e|L(Y5J!heUn057HA457EIgmxA-Oa(5aa?J1cHmy+C}O@*FQv zcTu@1rfX(ra9n=E)J?Lofa%Me+MZ_^G1uOqE-XfryqaUd`lmo_??7_E!S7+he`W#F zm}X%rX@;a#nq>}H0QJi02R7qpI&1Hk*RslOaNTK^*ga z?A>U93=z-h+Re$4(G8La|KdgHSor#890H9dQYkT($o@l{Tr3t(I0&BHQ)-BUj&R6{ zQx?GmML^8buYX)9C7~^t7@xGJmKnZXt>J*BWq=bxVQe_sST*F@Z)7ySOs6qvvyf$X zBM%<*lQ(Gk-+T74LTh73p+=&)7g%wh?!qO{{|$Lbu$oaARbXV*NdDe`{zJJqI68Ky#wZ$cG+ykwk5e_MSo=ZKye*0w zP3v0y^9k%evi1YwzXqTTjvC;{EZ=Dz2uteosj!sJ>2jMFofwY=92$ zDAGmA{r2+9UjPKuiN+Bw9$FhNqodD8$7&?=__?Q|<+|G?BUQ96=rObAA~Z<0gRN!? zz=YMo6)jAw@Fc_>FLjUMj$hxnk$l^IQ!zW!kJS-?H=21JR?g|i#{u^}9}Zvz65+&Gmn#22JCy5_PqDlw6H+nv=?FLA33u|9%rJV{iP;K``sj@|PHY&({E89>vUls&bgd(ngXv`eL-FSWI_hWSU9Uc9Y$*SJVS#j0 z3eaK4Mwn|@=ey1{@|F-pKhgCM8F!|QkQNpuwFNqP~H+KL@0+`~TfoAMjS#A~__9OZi z-zI-8w2m)1GN6ghmioE9y>}+Ca*ABzdQxqrPu~jk#9#JHpun>iinbPR+$RwRCX_!`TvQ%sptx;~eNhu*fgB zEaqYRn=UYj_jzu?mgBQ8@8hA841^}1wAOEkHw}^o`v<%w^^{$nqeTeHqNT_qlf``C z$~8g{skoD2pQ6lh8>H=8l6u&vcg-Zp^6c!VXwHklI)rsHJE0{v-6TOw+U%8U=0qYvx(th$(ipwH!*xoO;nUTnXYfr4fGfA z@%!+sn?@*d4WMA`rwrtSGP&HHN#c9B;}ir(ddVv2up0{5@{bXQavEz1 zVmJzw-F;t^E$--p!y_bhKLmZXQ0GUNWi+*LFl|=~%1BOd&YADs3 zYYSrLY)a@p9p-_X#c?oGmbHw#SRJwJ3FZB~>QqtkuVErryyFI{ z$rpVesJSMPdC2oWLD`1~Tde3d4=>Jo22LZ4^ zwGJ$rZ0n6Lv{?@cN%~kxW@>n#O?C)>%h6?d_NDFW7w8H5DuW2m z&T-d?hG`B_m7gu91s@&VN)k`nUvwC};T7w+HF!gFDMefdz!Fe)1IAwloQozl1uC2y z4@$n6&=k5YaNo9PJlE$h^s5l_zajtG6>Vggu&I{g=j@EfPGM$flV+$mvQtK1HL-0k zHswmbuesl)T+OF+NsRh6L@8*-I{>$(`@44tQ?|vxfSoG-S~$Qln3kR%0L>OMAAx7$ zr~iy@@GvpNA2lz1N^a9k1jUmg7s;^kf zuH6^?C)E?3D5}N(ZkGJ|n{RO+rj4|As856Lsf?X}XW^5BJe+oTrYcOvW1QQR=CDLk z->n?W9bh#cI5-53Q3->Q3_RD`>7{xB>whM_p`p!VhuZb?X^Fq zzt_`I93YJ0q&Nai4@$L-?2p#0vgU*-4| zvAn3Ll=k=7P>)cV@8fI#iFl)w9&|r`>+*d2ib#oAP_+D7w+smVde6+ZRwaMQ)#LOw z7E2hHsaWmxM<|nPXZOhsr_YJL9VR;v>VNf>PWnsjo;g75hH@YzRtk7~Wj&qUw?#<# z`T3$}NAm<^Z|>~2Qg!@wzhh^aM7pD4-3bG)(5MIlWDbch@0U_tp+oL)d9oxCBG&Zg z`s;yz0nE>N@oz3y_PvuoNzS;<%^By6TBQS(@U7QDGEn9N`FlRc+=%$}aW!$fY*JK0 zB6S!_nsP*kpIW6wF~HCK6SaqFShO8(-ke1Q$;#(s9ADl8-q;w61OBsu4ed2&h1J%8 z&rUC)gzJH-=Zss6lyMuVzTI1kTxk+xTPduJr;EOxTJvZ77AoWLWJqt=1YQY> zbPr~ttyJySN*#�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 diff --git a/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/114.png b/apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/114.png deleted file mode 100644 index 20e9ea1a557339a9ce8ebcb2b30dd233fcf816c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11312 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