chore: h5 fix
Browse files- README.md +2 -0
- desktop/index.html +1 -1
- desktop/scripts/build-macos-arm64.sh +7 -7
- desktop/scripts/build-sidecars.ts +2 -2
- desktop/scripts/e2e-slash-plugin-agent-browser.sh +1 -1
- desktop/src-tauri/capabilities/default.json +1 -1
- desktop/src-tauri/src/lib.rs +5 -5
- desktop/src-tauri/src/macos_notifications.m +2 -2
- desktop/src-tauri/tauri.conf.json +3 -3
- desktop/src-tauri/tauri.macos.conf.json +1 -1
- desktop/src-tauri/tauri.windows.conf.json +1 -1
- desktop/src-tauri/windows-installer-hooks.nsh +2 -2
- desktop/src/__tests__/generalSettings.test.tsx +11 -11
- desktop/src/components/chat/chatBlocks.test.tsx +1 -1
- desktop/src/components/shared/UpdateChecker.test.tsx +3 -3
- desktop/src/i18n/locales/en.ts +1 -1
- desktop/src/i18n/locales/zh.ts +1 -1
- desktop/src/pages/ActiveSession.tsx +1 -1
- desktop/src/pages/NewTaskModal.tsx +1 -1
- desktop/src/pages/ScheduledTasksEmpty.tsx +1 -1
- desktop/src/pages/ScheduledTasksList.tsx +1 -1
- desktop/src/pages/SessionControls.tsx +1 -1
- desktop/src/pages/Settings.tsx +2 -2
- desktop/src/stores/chatStore.test.ts +3 -3
- desktop/src/stores/chatStore.ts +3 -3
- desktop/tsconfig.tsbuildinfo +1 -0
- src/server/api/haha-oauth.ts +1 -1
- src/server/api/haha-openai-oauth.ts +1 -1
- src/server/services/desktopCliLauncherService.ts +2 -2
- src/server/services/hahaOpenAIOAuthService.ts +1 -1
README.md
CHANGED
|
@@ -126,6 +126,8 @@ firefox http://localhost:8080
|
|
| 126 |
```
|
| 127 |
|
| 128 |
```bash
|
|
|
|
|
|
|
| 129 |
cd desktop && bun run tauri dev
|
| 130 |
# ai_friend api in 8889 so local build Omni model or use cloud service on 8889
|
| 131 |
```
|
|
|
|
| 126 |
```
|
| 127 |
|
| 128 |
```bash
|
| 129 |
+
# cd desktop && rm -rf node_modules/.vite && bun run dev
|
| 130 |
+
# cd desktop && bun run vite build
|
| 131 |
cd desktop && bun run tauri dev
|
| 132 |
# ai_friend api in 8889 so local build Omni model or use cloud service on 8889
|
| 133 |
```
|
desktop/index.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8" />
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 6 |
-
<title>
|
| 7 |
<!-- Fonts are self-hosted in /fonts/ and declared via @font-face in globals.css -->
|
| 8 |
<style>
|
| 9 |
/* Prevent a warm flash before the theme is hydrated. */
|
|
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8" />
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 6 |
+
<title>Versper AI Claw</title>
|
| 7 |
<!-- Fonts are self-hosted in /fonts/ and declared via @font-face in globals.css -->
|
| 8 |
<style>
|
| 9 |
/* Prevent a warm flash before the theme is hydrated. */
|
desktop/scripts/build-macos-arm64.sh
CHANGED
|
@@ -9,12 +9,12 @@ REPO_ROOT="$(cd "${DESKTOP_DIR}/.." && pwd)"
|
|
| 9 |
TARGET_TRIPLE="aarch64-apple-darwin"
|
| 10 |
TAURI_TARGET_DIR="${DESKTOP_DIR}/src-tauri/target"
|
| 11 |
CANONICAL_OUTPUT_DIR="${DESKTOP_DIR}/build-artifacts/macos-arm64"
|
| 12 |
-
APP_BUNDLE_NAME="
|
| 13 |
-
APP_BUNDLE_ID="com.
|
| 14 |
|
| 15 |
usage() {
|
| 16 |
cat <<'EOF'
|
| 17 |
-
Build
|
| 18 |
|
| 19 |
Usage:
|
| 20 |
./desktop/scripts/build-macos-arm64.sh [extra tauri build args...]
|
|
@@ -191,7 +191,7 @@ build_canonical_dmg() {
|
|
| 191 |
|
| 192 |
# Create a read-write DMG first so we can customize the Finder layout
|
| 193 |
hdiutil create \
|
| 194 |
-
-volname "
|
| 195 |
-srcfolder "${staging_dir}" \
|
| 196 |
-ov \
|
| 197 |
-format UDRW \
|
|
@@ -212,7 +212,7 @@ build_canonical_dmg() {
|
|
| 212 |
# 所以这里允许 osascript 非零退出,只 warn,不让 set -e 炸掉整个脚本。
|
| 213 |
if ! osascript <<APPLESCRIPT
|
| 214 |
tell application "Finder"
|
| 215 |
-
tell disk "
|
| 216 |
open
|
| 217 |
set current view of container window to icon view
|
| 218 |
set toolbar visible of container window to false
|
|
@@ -283,7 +283,7 @@ sign_canonical_app_bundle() {
|
|
| 283 |
|
| 284 |
if [[ -n "${LATEST_APP}" ]]; then
|
| 285 |
# Normalize the Tauri-produced app in place before copying it anywhere.
|
| 286 |
-
# Without this, opening target/.../bundle/macos/
|
| 287 |
# uses the executable's ad-hoc signing identifier instead of the app bundle id,
|
| 288 |
# which makes macOS notification authorization behave like a different app.
|
| 289 |
sign_canonical_app_bundle "${LATEST_APP}"
|
|
@@ -298,7 +298,7 @@ if [[ -n "${LATEST_APP}" ]]; then
|
|
| 298 |
cp -R "${LATEST_APP}" "${CANONICAL_OUTPUT_DIR}/"
|
| 299 |
sign_canonical_app_bundle "${CANONICAL_OUTPUT_DIR}/${APP_BUNDLE_NAME}"
|
| 300 |
rm -f "${CANONICAL_OUTPUT_DIR}/"*.dmg
|
| 301 |
-
CANONICAL_DMG="${CANONICAL_OUTPUT_DIR}/$(basename "${LATEST_DMG:-
|
| 302 |
build_canonical_dmg \
|
| 303 |
"${CANONICAL_OUTPUT_DIR}/${APP_BUNDLE_NAME}" \
|
| 304 |
"${CANONICAL_DMG}"
|
|
|
|
| 9 |
TARGET_TRIPLE="aarch64-apple-darwin"
|
| 10 |
TAURI_TARGET_DIR="${DESKTOP_DIR}/src-tauri/target"
|
| 11 |
CANONICAL_OUTPUT_DIR="${DESKTOP_DIR}/build-artifacts/macos-arm64"
|
| 12 |
+
APP_BUNDLE_NAME="Versper AI Claw.app"
|
| 13 |
+
APP_BUNDLE_ID="com.versperai.claw.desktop"
|
| 14 |
|
| 15 |
usage() {
|
| 16 |
cat <<'EOF'
|
| 17 |
+
Build Versper AI Claw desktop for macOS Apple Silicon and output a DMG.
|
| 18 |
|
| 19 |
Usage:
|
| 20 |
./desktop/scripts/build-macos-arm64.sh [extra tauri build args...]
|
|
|
|
| 191 |
|
| 192 |
# Create a read-write DMG first so we can customize the Finder layout
|
| 193 |
hdiutil create \
|
| 194 |
+
-volname "Versper AI Claw" \
|
| 195 |
-srcfolder "${staging_dir}" \
|
| 196 |
-ov \
|
| 197 |
-format UDRW \
|
|
|
|
| 212 |
# 所以这里允许 osascript 非零退出,只 warn,不让 set -e 炸掉整个脚本。
|
| 213 |
if ! osascript <<APPLESCRIPT
|
| 214 |
tell application "Finder"
|
| 215 |
+
tell disk "Versper AI Claw"
|
| 216 |
open
|
| 217 |
set current view of container window to icon view
|
| 218 |
set toolbar visible of container window to false
|
|
|
|
| 283 |
|
| 284 |
if [[ -n "${LATEST_APP}" ]]; then
|
| 285 |
# Normalize the Tauri-produced app in place before copying it anywhere.
|
| 286 |
+
# Without this, opening target/.../bundle/macos/Versper AI Claw.app directly
|
| 287 |
# uses the executable's ad-hoc signing identifier instead of the app bundle id,
|
| 288 |
# which makes macOS notification authorization behave like a different app.
|
| 289 |
sign_canonical_app_bundle "${LATEST_APP}"
|
|
|
|
| 298 |
cp -R "${LATEST_APP}" "${CANONICAL_OUTPUT_DIR}/"
|
| 299 |
sign_canonical_app_bundle "${CANONICAL_OUTPUT_DIR}/${APP_BUNDLE_NAME}"
|
| 300 |
rm -f "${CANONICAL_OUTPUT_DIR}/"*.dmg
|
| 301 |
+
CANONICAL_DMG="${CANONICAL_OUTPUT_DIR}/$(basename "${LATEST_DMG:-Versper AI Claw_0.1.0_aarch64.dmg}")"
|
| 302 |
build_canonical_dmg \
|
| 303 |
"${CANONICAL_OUTPUT_DIR}/${APP_BUNDLE_NAME}" \
|
| 304 |
"${CANONICAL_DMG}"
|
desktop/scripts/build-sidecars.ts
CHANGED
|
@@ -32,7 +32,7 @@ await mkdir(binariesDir, { recursive: true })
|
|
| 32 |
await compileExecutable({
|
| 33 |
entrypoint: path.join(desktopRoot, 'sidecars/claude-sidecar.ts'),
|
| 34 |
outfileBase: path.join(binariesDir, `claude-sidecar-${targetTriple}`),
|
| 35 |
-
productName: '
|
| 36 |
bunTarget,
|
| 37 |
})
|
| 38 |
|
|
@@ -145,7 +145,7 @@ async function compileExecutable({
|
|
| 145 |
autoloadPackageJson: true,
|
| 146 |
windows: {
|
| 147 |
title: productName,
|
| 148 |
-
publisher: '
|
| 149 |
description: productName,
|
| 150 |
hideConsole: true,
|
| 151 |
},
|
|
|
|
| 32 |
await compileExecutable({
|
| 33 |
entrypoint: path.join(desktopRoot, 'sidecars/claude-sidecar.ts'),
|
| 34 |
outfileBase: path.join(binariesDir, `claude-sidecar-${targetTriple}`),
|
| 35 |
+
productName: 'Versper Sidecar',
|
| 36 |
bunTarget,
|
| 37 |
})
|
| 38 |
|
|
|
|
| 145 |
autoloadPackageJson: true,
|
| 146 |
windows: {
|
| 147 |
title: productName,
|
| 148 |
+
publisher: 'Versper AI',
|
| 149 |
description: productName,
|
| 150 |
hideConsole: true,
|
| 151 |
},
|
desktop/scripts/e2e-slash-plugin-agent-browser.sh
CHANGED
|
@@ -143,7 +143,7 @@ echo "Using MCP plugin: ${MCP_PLUGIN_NAME} (${MCP_PLUGIN_ID})"
|
|
| 143 |
|
| 144 |
"${AB[@]}" open "${WEB_URL}"
|
| 145 |
"${AB[@]}" wait --load networkidle
|
| 146 |
-
wait_for_text "
|
| 147 |
"${AB[@]}" screenshot "${ARTIFACT_DIR}/01-home.png" >/dev/null
|
| 148 |
|
| 149 |
# Always work from a fresh chat surface so slash-command behavior is deterministic.
|
|
|
|
| 143 |
|
| 144 |
"${AB[@]}" open "${WEB_URL}"
|
| 145 |
"${AB[@]}" wait --load networkidle
|
| 146 |
+
wait_for_text "Versper AI Claw"
|
| 147 |
"${AB[@]}" screenshot "${ARTIFACT_DIR}/01-home.png" >/dev/null
|
| 148 |
|
| 149 |
# Always work from a fresh chat surface so slash-command behavior is deterministic.
|
desktop/src-tauri/capabilities/default.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
{
|
| 2 |
"$schema": "https://raw.githubusercontent.com/nicegui/nicegui/main/nicegui/static/tauri-capabilities-schema-v2.json",
|
| 3 |
"identifier": "default",
|
| 4 |
-
"description": "Default capabilities for
|
| 5 |
"windows": ["main"],
|
| 6 |
"permissions": [
|
| 7 |
"core:default",
|
|
|
|
| 1 |
{
|
| 2 |
"$schema": "https://raw.githubusercontent.com/nicegui/nicegui/main/nicegui/static/tauri-capabilities-schema-v2.json",
|
| 3 |
"identifier": "default",
|
| 4 |
+
"description": "Default capabilities for Versper AI Claw Desktop",
|
| 5 |
"windows": ["main"],
|
| 6 |
"permissions": [
|
| 7 |
"core:default",
|
desktop/src-tauri/src/lib.rs
CHANGED
|
@@ -859,13 +859,13 @@ fn show_main_window(app: &AppHandle) {
|
|
| 859 |
|
| 860 |
fn setup_system_tray(app: &mut tauri::App) -> tauri::Result<()> {
|
| 861 |
let menu = MenuBuilder::new(app)
|
| 862 |
-
.text(TRAY_SHOW_ID, "Show
|
| 863 |
.separator()
|
| 864 |
-
.text(TRAY_QUIT_ID, "Quit
|
| 865 |
.build()?;
|
| 866 |
|
| 867 |
let mut tray = TrayIconBuilder::with_id("main-tray")
|
| 868 |
-
.tooltip("
|
| 869 |
.menu(&menu)
|
| 870 |
.show_menu_on_left_click(false)
|
| 871 |
.on_menu_event(|app, event| match event.id().as_ref() {
|
|
@@ -2137,12 +2137,12 @@ pub fn run() {
|
|
| 2137 |
let builder = builder
|
| 2138 |
.menu(|app| {
|
| 2139 |
let about_item =
|
| 2140 |
-
MenuItemBuilder::with_id("nav_about", "关于
|
| 2141 |
let settings_item = MenuItemBuilder::with_id("nav_settings", "设置...")
|
| 2142 |
.accelerator("CmdOrCtrl+,")
|
| 2143 |
.build(app)?;
|
| 2144 |
|
| 2145 |
-
let app_submenu = SubmenuBuilder::new(app, "
|
| 2146 |
.item(&about_item)
|
| 2147 |
.separator()
|
| 2148 |
.item(&settings_item)
|
|
|
|
| 859 |
|
| 860 |
fn setup_system_tray(app: &mut tauri::App) -> tauri::Result<()> {
|
| 861 |
let menu = MenuBuilder::new(app)
|
| 862 |
+
.text(TRAY_SHOW_ID, "Show Versper AI Claw")
|
| 863 |
.separator()
|
| 864 |
+
.text(TRAY_QUIT_ID, "Quit Versper AI Claw")
|
| 865 |
.build()?;
|
| 866 |
|
| 867 |
let mut tray = TrayIconBuilder::with_id("main-tray")
|
| 868 |
+
.tooltip("Versper AI Claw")
|
| 869 |
.menu(&menu)
|
| 870 |
.show_menu_on_left_click(false)
|
| 871 |
.on_menu_event(|app, event| match event.id().as_ref() {
|
|
|
|
| 2137 |
let builder = builder
|
| 2138 |
.menu(|app| {
|
| 2139 |
let about_item =
|
| 2140 |
+
MenuItemBuilder::with_id("nav_about", "关于 Versper AI Claw").build(app)?;
|
| 2141 |
let settings_item = MenuItemBuilder::with_id("nav_settings", "设置...")
|
| 2142 |
.accelerator("CmdOrCtrl+,")
|
| 2143 |
.build(app)?;
|
| 2144 |
|
| 2145 |
+
let app_submenu = SubmenuBuilder::new(app, "Versper AI Claw")
|
| 2146 |
.item(&about_item)
|
| 2147 |
.separator()
|
| 2148 |
.item(&settings_item)
|
desktop/src-tauri/src/macos_notifications.m
CHANGED
|
@@ -194,7 +194,7 @@ bool cchh_send_user_notification(const char *title, const char *body, const char
|
|
| 194 |
|
| 195 |
if (@available(macOS 10.14, *)) {
|
| 196 |
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
|
| 197 |
-
content.title = title != NULL ? [NSString stringWithUTF8String:title] : @"
|
| 198 |
if (body != NULL && strlen(body) > 0) {
|
| 199 |
content.body = [NSString stringWithUTF8String:body];
|
| 200 |
}
|
|
@@ -229,7 +229,7 @@ bool cchh_send_user_notification(const char *title, const char *body, const char
|
|
| 229 |
}
|
| 230 |
|
| 231 |
NSUserNotification *notification = [[NSUserNotification alloc] init];
|
| 232 |
-
notification.title = title != NULL ? [NSString stringWithUTF8String:title] : @"
|
| 233 |
if (body != NULL && strlen(body) > 0) {
|
| 234 |
notification.informativeText = [NSString stringWithUTF8String:body];
|
| 235 |
}
|
|
|
|
| 194 |
|
| 195 |
if (@available(macOS 10.14, *)) {
|
| 196 |
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
|
| 197 |
+
content.title = title != NULL ? [NSString stringWithUTF8String:title] : @"Versper AI Claw";
|
| 198 |
if (body != NULL && strlen(body) > 0) {
|
| 199 |
content.body = [NSString stringWithUTF8String:body];
|
| 200 |
}
|
|
|
|
| 229 |
}
|
| 230 |
|
| 231 |
NSUserNotification *notification = [[NSUserNotification alloc] init];
|
| 232 |
+
notification.title = title != NULL ? [NSString stringWithUTF8String:title] : @"Versper AI Claw";
|
| 233 |
if (body != NULL && strlen(body) > 0) {
|
| 234 |
notification.informativeText = [NSString stringWithUTF8String:body];
|
| 235 |
}
|
desktop/src-tauri/tauri.conf.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
| 1 |
{
|
| 2 |
"$schema": "https://raw.githubusercontent.com/nicegui/nicegui/main/nicegui/static/tauri-schema-v2.json",
|
| 3 |
-
"productName": "
|
| 4 |
"version": "0.2.9",
|
| 5 |
-
"identifier": "com.
|
| 6 |
"build": {
|
| 7 |
"frontendDist": "../dist",
|
| 8 |
"devUrl": "http://localhost:1420",
|
|
@@ -12,7 +12,7 @@
|
|
| 12 |
"app": {
|
| 13 |
"windows": [
|
| 14 |
{
|
| 15 |
-
"title": "
|
| 16 |
"width": 1440,
|
| 17 |
"height": 960,
|
| 18 |
"minWidth": 960,
|
|
|
|
| 1 |
{
|
| 2 |
"$schema": "https://raw.githubusercontent.com/nicegui/nicegui/main/nicegui/static/tauri-schema-v2.json",
|
| 3 |
+
"productName": "Versper AI Claw",
|
| 4 |
"version": "0.2.9",
|
| 5 |
+
"identifier": "com.versperai.claw.desktop",
|
| 6 |
"build": {
|
| 7 |
"frontendDist": "../dist",
|
| 8 |
"devUrl": "http://localhost:1420",
|
|
|
|
| 12 |
"app": {
|
| 13 |
"windows": [
|
| 14 |
{
|
| 15 |
+
"title": "Versper AI Claw",
|
| 16 |
"width": 1440,
|
| 17 |
"height": 960,
|
| 18 |
"minWidth": 960,
|
desktop/src-tauri/tauri.macos.conf.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
| 2 |
"app": {
|
| 3 |
"windows": [
|
| 4 |
{
|
| 5 |
-
"title": "
|
| 6 |
"width": 1440,
|
| 7 |
"height": 960,
|
| 8 |
"minWidth": 960,
|
|
|
|
| 2 |
"app": {
|
| 3 |
"windows": [
|
| 4 |
{
|
| 5 |
+
"title": "Versper AI Claw",
|
| 6 |
"width": 1440,
|
| 7 |
"height": 960,
|
| 8 |
"minWidth": 960,
|
desktop/src-tauri/tauri.windows.conf.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
| 2 |
"app": {
|
| 3 |
"windows": [
|
| 4 |
{
|
| 5 |
-
"title": "
|
| 6 |
"width": 1440,
|
| 7 |
"height": 960,
|
| 8 |
"minWidth": 960,
|
|
|
|
| 2 |
"app": {
|
| 3 |
"windows": [
|
| 4 |
{
|
| 5 |
+
"title": "Versper AI Claw",
|
| 6 |
"width": 1440,
|
| 7 |
"height": 960,
|
| 8 |
"minWidth": 960,
|
desktop/src-tauri/windows-installer-hooks.nsh
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
!macro NSIS_HOOK_PREINSTALL
|
| 2 |
-
DetailPrint "Stopping running
|
| 3 |
nsExec::ExecToLog 'taskkill /F /T /IM claude-sidecar-x86_64-pc-windows-msvc.exe'
|
| 4 |
Pop $0
|
| 5 |
nsExec::ExecToLog 'taskkill /F /T /IM claude-sidecar-aarch64-pc-windows-msvc.exe'
|
|
@@ -10,7 +10,7 @@
|
|
| 10 |
!macroend
|
| 11 |
|
| 12 |
!macro NSIS_HOOK_PREUNINSTALL
|
| 13 |
-
DetailPrint "Stopping running
|
| 14 |
nsExec::ExecToLog 'taskkill /F /T /IM claude-code-desktop.exe'
|
| 15 |
Pop $0
|
| 16 |
nsExec::ExecToLog 'taskkill /F /T /IM claude-sidecar-x86_64-pc-windows-msvc.exe'
|
|
|
|
| 1 |
!macro NSIS_HOOK_PREINSTALL
|
| 2 |
+
DetailPrint "Stopping running Versper AI Claw sidecars..."
|
| 3 |
nsExec::ExecToLog 'taskkill /F /T /IM claude-sidecar-x86_64-pc-windows-msvc.exe'
|
| 4 |
Pop $0
|
| 5 |
nsExec::ExecToLog 'taskkill /F /T /IM claude-sidecar-aarch64-pc-windows-msvc.exe'
|
|
|
|
| 10 |
!macroend
|
| 11 |
|
| 12 |
!macro NSIS_HOOK_PREUNINSTALL
|
| 13 |
+
DetailPrint "Stopping running Versper AI Claw processes..."
|
| 14 |
nsExec::ExecToLog 'taskkill /F /T /IM claude-code-desktop.exe'
|
| 15 |
Pop $0
|
| 16 |
nsExec::ExecToLog 'taskkill /F /T /IM claude-sidecar-x86_64-pc-windows-msvc.exe'
|
desktop/src/__tests__/generalSettings.test.tsx
CHANGED
|
@@ -207,7 +207,7 @@ describe('Settings > General tab', () => {
|
|
| 207 |
appMode: {
|
| 208 |
mode: 'default',
|
| 209 |
portableDir: null,
|
| 210 |
-
defaultPortableDir: '/Applications/
|
| 211 |
activeConfigDir: null,
|
| 212 |
configDirSource: 'system',
|
| 213 |
},
|
|
@@ -217,9 +217,9 @@ describe('Settings > General tab', () => {
|
|
| 217 |
useSettingsStore.setState({
|
| 218 |
appMode: {
|
| 219 |
mode,
|
| 220 |
-
portableDir: mode === 'portable' ? portableDir ?? '/Applications/
|
| 221 |
-
defaultPortableDir: '/Applications/
|
| 222 |
-
activeConfigDir: mode === 'portable' ? portableDir ?? '/Applications/
|
| 223 |
configDirSource: mode === 'portable' ? 'portable' : 'system',
|
| 224 |
},
|
| 225 |
appModeRequiresRestart: true,
|
|
@@ -435,7 +435,7 @@ describe('Settings > General tab', () => {
|
|
| 435 |
appMode: {
|
| 436 |
mode: 'portable',
|
| 437 |
portableDir: '/Users/test/cc-haha-data',
|
| 438 |
-
defaultPortableDir: '/Applications/
|
| 439 |
activeConfigDir: '/Users/test/cc-haha-data',
|
| 440 |
configDirSource: 'portable',
|
| 441 |
},
|
|
@@ -470,7 +470,7 @@ describe('Settings > General tab', () => {
|
|
| 470 |
expect(screen.getByText('Choose or enter a portable data directory first.')).toBeInTheDocument()
|
| 471 |
|
| 472 |
fireEvent.click(screen.getByRole('button', { name: 'Use the default portable folder beside the app' }))
|
| 473 |
-
expect(input).toHaveValue('/Applications/
|
| 474 |
expect(screen.queryByText('Choose or enter a portable data directory first.')).not.toBeInTheDocument()
|
| 475 |
})
|
| 476 |
|
|
@@ -494,7 +494,7 @@ describe('Settings > General tab', () => {
|
|
| 494 |
appMode: {
|
| 495 |
mode: 'portable',
|
| 496 |
portableDir: '/env/claude-data',
|
| 497 |
-
defaultPortableDir: '/Applications/
|
| 498 |
activeConfigDir: '/env/claude-data',
|
| 499 |
configDirSource: 'environment',
|
| 500 |
},
|
|
@@ -694,7 +694,7 @@ describe('Settings > General tab', () => {
|
|
| 694 |
expect(desktopNotificationsMock.requestDesktopNotificationPermission).toHaveBeenCalledTimes(1)
|
| 695 |
})
|
| 696 |
expect(desktopNotificationsMock.notifyDesktop).toHaveBeenCalledWith({
|
| 697 |
-
title: '
|
| 698 |
body: 'Permission prompts and completed agent replies will now use system notifications.',
|
| 699 |
})
|
| 700 |
})
|
|
@@ -1204,7 +1204,7 @@ describe('Settings > About tab', () => {
|
|
| 1204 |
useUpdateStore.setState({
|
| 1205 |
status: 'available',
|
| 1206 |
availableVersion: '0.1.5',
|
| 1207 |
-
releaseNotes: '#
|
| 1208 |
progressPercent: 0,
|
| 1209 |
downloadedBytes: 0,
|
| 1210 |
totalBytes: null,
|
|
@@ -1221,7 +1221,7 @@ describe('Settings > About tab', () => {
|
|
| 1221 |
it('renders release notes with markdown formatting', async () => {
|
| 1222 |
render(<Settings />)
|
| 1223 |
|
| 1224 |
-
expect(await screen.findByRole('heading', { name: '
|
| 1225 |
expect(screen.getByText('Fixed updater rendering')).toBeInTheDocument()
|
| 1226 |
expect(screen.getByText('Added markdown support')).toBeInTheDocument()
|
| 1227 |
})
|
|
@@ -1230,7 +1230,7 @@ describe('Settings > About tab', () => {
|
|
| 1230 |
useUpdateStore.setState({
|
| 1231 |
status: 'downloading',
|
| 1232 |
availableVersion: '0.1.5',
|
| 1233 |
-
releaseNotes: '#
|
| 1234 |
progressPercent: 0,
|
| 1235 |
downloadedBytes: 1536,
|
| 1236 |
totalBytes: null,
|
|
|
|
| 207 |
appMode: {
|
| 208 |
mode: 'default',
|
| 209 |
portableDir: null,
|
| 210 |
+
defaultPortableDir: '/Applications/Versper AI Claw/CLAUDE_CONFIG_DIR',
|
| 211 |
activeConfigDir: null,
|
| 212 |
configDirSource: 'system',
|
| 213 |
},
|
|
|
|
| 217 |
useSettingsStore.setState({
|
| 218 |
appMode: {
|
| 219 |
mode,
|
| 220 |
+
portableDir: mode === 'portable' ? portableDir ?? '/Applications/Versper AI Claw/CLAUDE_CONFIG_DIR' : null,
|
| 221 |
+
defaultPortableDir: '/Applications/Versper AI Claw/CLAUDE_CONFIG_DIR',
|
| 222 |
+
activeConfigDir: mode === 'portable' ? portableDir ?? '/Applications/Versper AI Claw/CLAUDE_CONFIG_DIR' : null,
|
| 223 |
configDirSource: mode === 'portable' ? 'portable' : 'system',
|
| 224 |
},
|
| 225 |
appModeRequiresRestart: true,
|
|
|
|
| 435 |
appMode: {
|
| 436 |
mode: 'portable',
|
| 437 |
portableDir: '/Users/test/cc-haha-data',
|
| 438 |
+
defaultPortableDir: '/Applications/Versper AI Claw/CLAUDE_CONFIG_DIR',
|
| 439 |
activeConfigDir: '/Users/test/cc-haha-data',
|
| 440 |
configDirSource: 'portable',
|
| 441 |
},
|
|
|
|
| 470 |
expect(screen.getByText('Choose or enter a portable data directory first.')).toBeInTheDocument()
|
| 471 |
|
| 472 |
fireEvent.click(screen.getByRole('button', { name: 'Use the default portable folder beside the app' }))
|
| 473 |
+
expect(input).toHaveValue('/Applications/Versper AI Claw/CLAUDE_CONFIG_DIR')
|
| 474 |
expect(screen.queryByText('Choose or enter a portable data directory first.')).not.toBeInTheDocument()
|
| 475 |
})
|
| 476 |
|
|
|
|
| 494 |
appMode: {
|
| 495 |
mode: 'portable',
|
| 496 |
portableDir: '/env/claude-data',
|
| 497 |
+
defaultPortableDir: '/Applications/Versper AI Claw/CLAUDE_CONFIG_DIR',
|
| 498 |
activeConfigDir: '/env/claude-data',
|
| 499 |
configDirSource: 'environment',
|
| 500 |
},
|
|
|
|
| 694 |
expect(desktopNotificationsMock.requestDesktopNotificationPermission).toHaveBeenCalledTimes(1)
|
| 695 |
})
|
| 696 |
expect(desktopNotificationsMock.notifyDesktop).toHaveBeenCalledWith({
|
| 697 |
+
title: 'Versper AI Claw notifications are enabled',
|
| 698 |
body: 'Permission prompts and completed agent replies will now use system notifications.',
|
| 699 |
})
|
| 700 |
})
|
|
|
|
| 1204 |
useUpdateStore.setState({
|
| 1205 |
status: 'available',
|
| 1206 |
availableVersion: '0.1.5',
|
| 1207 |
+
releaseNotes: '# Versper AI Claw v0.1.5\n\n- Fixed updater rendering\n- Added markdown support',
|
| 1208 |
progressPercent: 0,
|
| 1209 |
downloadedBytes: 0,
|
| 1210 |
totalBytes: null,
|
|
|
|
| 1221 |
it('renders release notes with markdown formatting', async () => {
|
| 1222 |
render(<Settings />)
|
| 1223 |
|
| 1224 |
+
expect(await screen.findByRole('heading', { name: 'Versper AI Claw v0.1.5' })).toBeInTheDocument()
|
| 1225 |
expect(screen.getByText('Fixed updater rendering')).toBeInTheDocument()
|
| 1226 |
expect(screen.getByText('Added markdown support')).toBeInTheDocument()
|
| 1227 |
})
|
|
|
|
| 1230 |
useUpdateStore.setState({
|
| 1231 |
status: 'downloading',
|
| 1232 |
availableVersion: '0.1.5',
|
| 1233 |
+
releaseNotes: '# Versper AI Claw v0.1.5',
|
| 1234 |
progressPercent: 0,
|
| 1235 |
downloadedBytes: 1536,
|
| 1236 |
totalBytes: null,
|
desktop/src/components/chat/chatBlocks.test.tsx
CHANGED
|
@@ -83,7 +83,7 @@ describe('chat blocks', () => {
|
|
| 83 |
toolName="mcp__computer-use__left_click"
|
| 84 |
input={{ coordinate: [120, 220] }}
|
| 85 |
result={{
|
| 86 |
-
content: '"
|
| 87 |
isError: true,
|
| 88 |
}}
|
| 89 |
/>,
|
|
|
|
| 83 |
toolName="mcp__computer-use__left_click"
|
| 84 |
input={{ coordinate: [120, 220] }}
|
| 85 |
result={{
|
| 86 |
+
content: '"Versper AI Claw" is not in the allowed applications and is currently in front. Take a new screenshot — it may have appeared since your last one.',
|
| 87 |
isError: true,
|
| 88 |
}}
|
| 89 |
/>,
|
desktop/src/components/shared/UpdateChecker.test.tsx
CHANGED
|
@@ -17,7 +17,7 @@ describe('UpdateChecker', () => {
|
|
| 17 |
useUpdateStore.setState({
|
| 18 |
status: 'available',
|
| 19 |
availableVersion: '0.1.5',
|
| 20 |
-
releaseNotes: '#
|
| 21 |
progressPercent: 0,
|
| 22 |
downloadedBytes: 0,
|
| 23 |
totalBytes: null,
|
|
@@ -35,7 +35,7 @@ describe('UpdateChecker', () => {
|
|
| 35 |
render(<UpdateChecker />)
|
| 36 |
|
| 37 |
expect(screen.getByText('v0.1.5 available')).toBeInTheDocument()
|
| 38 |
-
expect(screen.getByRole('heading', { name: '
|
| 39 |
|
| 40 |
const link = screen.getByRole('link', { name: 'Release notes' })
|
| 41 |
expect(link).toHaveAttribute('href', 'https://example.com/releases/v0.1.5')
|
|
@@ -46,7 +46,7 @@ describe('UpdateChecker', () => {
|
|
| 46 |
useUpdateStore.setState({
|
| 47 |
status: 'downloading',
|
| 48 |
availableVersion: '0.1.5',
|
| 49 |
-
releaseNotes: '#
|
| 50 |
progressPercent: 0,
|
| 51 |
downloadedBytes: 1536,
|
| 52 |
totalBytes: null,
|
|
|
|
| 17 |
useUpdateStore.setState({
|
| 18 |
status: 'available',
|
| 19 |
availableVersion: '0.1.5',
|
| 20 |
+
releaseNotes: '# Versper AI Claw v0.1.5\n\n[Release notes](https://example.com/releases/v0.1.5)',
|
| 21 |
progressPercent: 0,
|
| 22 |
downloadedBytes: 0,
|
| 23 |
totalBytes: null,
|
|
|
|
| 35 |
render(<UpdateChecker />)
|
| 36 |
|
| 37 |
expect(screen.getByText('v0.1.5 available')).toBeInTheDocument()
|
| 38 |
+
expect(screen.getByRole('heading', { name: 'Versper AI Claw v0.1.5' })).toBeInTheDocument()
|
| 39 |
|
| 40 |
const link = screen.getByRole('link', { name: 'Release notes' })
|
| 41 |
expect(link).toHaveAttribute('href', 'https://example.com/releases/v0.1.5')
|
|
|
|
| 46 |
useUpdateStore.setState({
|
| 47 |
status: 'downloading',
|
| 48 |
availableVersion: '0.1.5',
|
| 49 |
+
releaseNotes: '# Versper AI Claw v0.1.5',
|
| 50 |
progressPercent: 0,
|
| 51 |
downloadedBytes: 1536,
|
| 52 |
totalBytes: null,
|
desktop/src/i18n/locales/en.ts
CHANGED
|
@@ -878,7 +878,7 @@ export const en = {
|
|
| 878 |
'settings.general.notificationsStatusUnsupported': 'Unavailable in this environment',
|
| 879 |
'settings.general.notificationsAuthorize': 'Authorize',
|
| 880 |
'settings.general.notificationsOpenSettings': 'Open Settings',
|
| 881 |
-
'settings.general.notificationsTestTitle': '
|
| 882 |
'settings.general.notificationsTestBody': 'Permission prompts and completed agent replies will now use system notifications.',
|
| 883 |
'settings.general.h5AccessTitle': 'H5 Access',
|
| 884 |
'settings.general.h5AccessDescription': 'Expose the desktop H5 app on your local network. Phones connect with a QR link that includes a short-lived H5 token.',
|
|
|
|
| 878 |
'settings.general.notificationsStatusUnsupported': 'Unavailable in this environment',
|
| 879 |
'settings.general.notificationsAuthorize': 'Authorize',
|
| 880 |
'settings.general.notificationsOpenSettings': 'Open Settings',
|
| 881 |
+
'settings.general.notificationsTestTitle': 'Versper AI Claw notifications are enabled',
|
| 882 |
'settings.general.notificationsTestBody': 'Permission prompts and completed agent replies will now use system notifications.',
|
| 883 |
'settings.general.h5AccessTitle': 'H5 Access',
|
| 884 |
'settings.general.h5AccessDescription': 'Expose the desktop H5 app on your local network. Phones connect with a QR link that includes a short-lived H5 token.',
|
desktop/src/i18n/locales/zh.ts
CHANGED
|
@@ -880,7 +880,7 @@ export const zh: Record<TranslationKey, string> = {
|
|
| 880 |
'settings.general.notificationsStatusUnsupported': '当前环境不可用',
|
| 881 |
'settings.general.notificationsAuthorize': '授权通知',
|
| 882 |
'settings.general.notificationsOpenSettings': '打开系统设置',
|
| 883 |
-
'settings.general.notificationsTestTitle': '
|
| 884 |
'settings.general.notificationsTestBody': '后续授权确认和 Agent 回复完成都会通过系统通知提醒。',
|
| 885 |
'settings.general.h5AccessTitle': 'H5 访问',
|
| 886 |
'settings.general.h5AccessDescription': '在局域网内暴露桌面端 H5 应用。手机通过带 H5 token 的二维码快速连接。',
|
|
|
|
| 880 |
'settings.general.notificationsStatusUnsupported': '当前环境不可用',
|
| 881 |
'settings.general.notificationsAuthorize': '授权通知',
|
| 882 |
'settings.general.notificationsOpenSettings': '打开系统设置',
|
| 883 |
+
'settings.general.notificationsTestTitle': 'Versper AI Claw 通知已启用',
|
| 884 |
'settings.general.notificationsTestBody': '后续授权确认和 Agent 回复完成都会通过系统通知提醒。',
|
| 885 |
'settings.general.h5AccessTitle': 'H5 访问',
|
| 886 |
'settings.general.h5AccessDescription': '在局域网内暴露桌面端 H5 应用。手机通过带 H5 token 的二维码快速连接。',
|
desktop/src/pages/ActiveSession.tsx
CHANGED
|
@@ -408,7 +408,7 @@ export function ActiveSession() {
|
|
| 408 |
</>
|
| 409 |
) : (
|
| 410 |
<>
|
| 411 |
-
<img src="/app-icon.png" alt="
|
| 412 |
<h1 className="mb-2 text-3xl font-extrabold tracking-tight text-[var(--color-text-primary)]" style={{ fontFamily: 'var(--font-headline)' }}>
|
| 413 |
{t('empty.title')}
|
| 414 |
</h1>
|
|
|
|
| 408 |
</>
|
| 409 |
) : (
|
| 410 |
<>
|
| 411 |
+
<img src="/app-icon.png" alt="Versper AI Claw" className="mb-6 h-24 w-24" />
|
| 412 |
<h1 className="mb-2 text-3xl font-extrabold tracking-tight text-[var(--color-text-primary)]" style={{ fontFamily: 'var(--font-headline)' }}>
|
| 413 |
{t('empty.title')}
|
| 414 |
</h1>
|
desktop/src/pages/NewTaskModal.tsx
CHANGED
|
@@ -25,7 +25,7 @@ export default function NewTaskModal() {
|
|
| 25 |
<header className="bg-[var(--color-background)] flex justify-between items-center px-6 h-12 w-full z-40">
|
| 26 |
<div className="flex items-center gap-6">
|
| 27 |
<span className="text-sm font-bold text-[var(--color-text-primary)] uppercase tracking-tighter font-[var(--font-headline)]">
|
| 28 |
-
|
| 29 |
</span>
|
| 30 |
<nav className="hidden md:flex gap-4 font-[var(--font-headline)] font-semibold tracking-wide text-sm">
|
| 31 |
<a className="text-[var(--color-text-tertiary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer">Code</a>
|
|
|
|
| 25 |
<header className="bg-[var(--color-background)] flex justify-between items-center px-6 h-12 w-full z-40">
|
| 26 |
<div className="flex items-center gap-6">
|
| 27 |
<span className="text-sm font-bold text-[var(--color-text-primary)] uppercase tracking-tighter font-[var(--font-headline)]">
|
| 28 |
+
Versper AI Claw
|
| 29 |
</span>
|
| 30 |
<nav className="hidden md:flex gap-4 font-[var(--font-headline)] font-semibold tracking-wide text-sm">
|
| 31 |
<a className="text-[var(--color-text-tertiary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer">Code</a>
|
desktop/src/pages/ScheduledTasksEmpty.tsx
CHANGED
|
@@ -59,7 +59,7 @@ export function ScheduledTasksEmpty() {
|
|
| 59 |
{/* TopAppBar */}
|
| 60 |
<header className="fixed top-0 right-0 left-[280px] z-30 bg-[var(--color-background)] flex justify-between items-center px-6 h-12 w-full border-b border-[var(--color-border)]">
|
| 61 |
<div className="flex items-center gap-6 h-full">
|
| 62 |
-
<div className="text-sm font-bold text-[var(--color-text-primary)] uppercase tracking-tighter font-[Manrope,sans-serif]">
|
| 63 |
<nav className="flex items-center gap-4 h-full font-[Manrope,sans-serif] font-semibold tracking-wide text-sm">
|
| 64 |
<span className="text-[var(--color-text-tertiary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer active:opacity-70 h-full flex items-center">{t('titlebar.code')}</span>
|
| 65 |
<span className="text-[var(--color-text-tertiary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer active:opacity-70 h-full flex items-center">{t('titlebar.terminal')}</span>
|
|
|
|
| 59 |
{/* TopAppBar */}
|
| 60 |
<header className="fixed top-0 right-0 left-[280px] z-30 bg-[var(--color-background)] flex justify-between items-center px-6 h-12 w-full border-b border-[var(--color-border)]">
|
| 61 |
<div className="flex items-center gap-6 h-full">
|
| 62 |
+
<div className="text-sm font-bold text-[var(--color-text-primary)] uppercase tracking-tighter font-[Manrope,sans-serif]">Versper AI Claw</div>
|
| 63 |
<nav className="flex items-center gap-4 h-full font-[Manrope,sans-serif] font-semibold tracking-wide text-sm">
|
| 64 |
<span className="text-[var(--color-text-tertiary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer active:opacity-70 h-full flex items-center">{t('titlebar.code')}</span>
|
| 65 |
<span className="text-[var(--color-text-tertiary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer active:opacity-70 h-full flex items-center">{t('titlebar.terminal')}</span>
|
desktop/src/pages/ScheduledTasksList.tsx
CHANGED
|
@@ -77,7 +77,7 @@ export function ScheduledTasksList() {
|
|
| 77 |
{/* TopAppBar */}
|
| 78 |
<header className="bg-[var(--color-background)] h-12 w-full flex justify-between items-center px-6 z-30">
|
| 79 |
<div className="flex items-center gap-8">
|
| 80 |
-
<div className="font-[Manrope,sans-serif] font-bold text-[var(--color-text-primary)] uppercase tracking-tighter text-sm">
|
| 81 |
<nav className="flex items-center gap-6 font-[Manrope,sans-serif] font-semibold tracking-wide text-sm">
|
| 82 |
<a className="text-[var(--color-text-tertiary)] hover:text-[var(--color-brand)] transition-colors" href="#">{t('titlebar.code')}</a>
|
| 83 |
<a className="text-[var(--color-text-tertiary)] hover:text-[var(--color-brand)] transition-colors" href="#">{t('titlebar.terminal')}</a>
|
|
|
|
| 77 |
{/* TopAppBar */}
|
| 78 |
<header className="bg-[var(--color-background)] h-12 w-full flex justify-between items-center px-6 z-30">
|
| 79 |
<div className="flex items-center gap-8">
|
| 80 |
+
<div className="font-[Manrope,sans-serif] font-bold text-[var(--color-text-primary)] uppercase tracking-tighter text-sm">Versper AI Claw</div>
|
| 81 |
<nav className="flex items-center gap-6 font-[Manrope,sans-serif] font-semibold tracking-wide text-sm">
|
| 82 |
<a className="text-[var(--color-text-tertiary)] hover:text-[var(--color-brand)] transition-colors" href="#">{t('titlebar.code')}</a>
|
| 83 |
<a className="text-[var(--color-text-tertiary)] hover:text-[var(--color-brand)] transition-colors" href="#">{t('titlebar.terminal')}</a>
|
desktop/src/pages/SessionControls.tsx
CHANGED
|
@@ -42,7 +42,7 @@ export default function SessionControls() {
|
|
| 42 |
<header className="bg-[var(--color-background)] font-headline font-semibold tracking-wide text-sm fixed top-0 left-0 right-0 flex justify-between items-center px-6 h-12 z-40">
|
| 43 |
<div className="flex items-center gap-6">
|
| 44 |
<span className="text-sm font-bold text-[var(--color-text-primary)] uppercase tracking-tighter">
|
| 45 |
-
|
| 46 |
</span>
|
| 47 |
<nav className="hidden md:flex gap-4">
|
| 48 |
<a className="text-[var(--color-text-primary)] border-b-2 border-[var(--color-brand)] pb-1 cursor-pointer active:opacity-70">
|
|
|
|
| 42 |
<header className="bg-[var(--color-background)] font-headline font-semibold tracking-wide text-sm fixed top-0 left-0 right-0 flex justify-between items-center px-6 h-12 z-40">
|
| 43 |
<div className="flex items-center gap-6">
|
| 44 |
<span className="text-sm font-bold text-[var(--color-text-primary)] uppercase tracking-tighter">
|
| 45 |
+
Versper AI Claw
|
| 46 |
</span>
|
| 47 |
<nav className="hidden md:flex gap-4">
|
| 48 |
<a className="text-[var(--color-text-primary)] border-b-2 border-[var(--color-brand)] pb-1 cursor-pointer active:opacity-70">
|
desktop/src/pages/Settings.tsx
CHANGED
|
@@ -3557,8 +3557,8 @@ function AboutSettings() {
|
|
| 3557 |
return (
|
| 3558 |
<div className="w-full min-w-0 max-w-lg mx-auto flex flex-col items-center py-6">
|
| 3559 |
{/* Logo + App Name + Version */}
|
| 3560 |
-
<img src="/app-icon.png" alt="
|
| 3561 |
-
<h1 className="text-xl font-bold text-[var(--color-text-primary)]">
|
| 3562 |
{version && (
|
| 3563 |
<div className="mt-1 flex items-center gap-2 text-xs text-[var(--color-text-tertiary)]">
|
| 3564 |
<span>{t('settings.about.version')} {version}</span>
|
|
|
|
| 3557 |
return (
|
| 3558 |
<div className="w-full min-w-0 max-w-lg mx-auto flex flex-col items-center py-6">
|
| 3559 |
{/* Logo + App Name + Version */}
|
| 3560 |
+
<img src="/app-icon.png" alt="Versper AI Claw" className="w-20 h-20 mb-4" />
|
| 3561 |
+
<h1 className="text-xl font-bold text-[var(--color-text-primary)]">Versper AI Claw</h1>
|
| 3562 |
{version && (
|
| 3563 |
<div className="mt-1 flex items-center gap-2 text-xs text-[var(--color-text-tertiary)]">
|
| 3564 |
<span>{t('settings.about.version')} {version}</span>
|
desktop/src/stores/chatStore.test.ts
CHANGED
|
@@ -1464,7 +1464,7 @@ describe('chatStore history mapping', () => {
|
|
| 1464 |
dedupeKey: 'permission:perm-ask-1',
|
| 1465 |
cooldownScope: 'permission-prompt',
|
| 1466 |
requestAttention: true,
|
| 1467 |
-
title: '
|
| 1468 |
body: 'AskUserQuestion 请求执行,正在等待允许。',
|
| 1469 |
target: { type: 'session', sessionId: TEST_SESSION_ID },
|
| 1470 |
})
|
|
@@ -2557,7 +2557,7 @@ describe('chatStore history mapping', () => {
|
|
| 2557 |
dedupeKey: 'computer-use-permission:cu-1',
|
| 2558 |
cooldownScope: 'permission-prompt',
|
| 2559 |
requestAttention: true,
|
| 2560 |
-
title: '
|
| 2561 |
body: 'Open Finder and inspect a file',
|
| 2562 |
target: { type: 'session', sessionId: TEST_SESSION_ID },
|
| 2563 |
})
|
|
@@ -2997,7 +2997,7 @@ describe('chatStore history mapping', () => {
|
|
| 2997 |
|
| 2998 |
expect(notifyDesktopMock).toHaveBeenCalledWith(expect.objectContaining({
|
| 2999 |
cooldownScope: 'agent-completion',
|
| 3000 |
-
title: '
|
| 3001 |
body: '结果 修复完成 bun test 已通过',
|
| 3002 |
target: { type: 'session', sessionId: TEST_SESSION_ID },
|
| 3003 |
}))
|
|
|
|
| 1464 |
dedupeKey: 'permission:perm-ask-1',
|
| 1465 |
cooldownScope: 'permission-prompt',
|
| 1466 |
requestAttention: true,
|
| 1467 |
+
title: 'Versper AI Claw 需要你的确认',
|
| 1468 |
body: 'AskUserQuestion 请求执行,正在等待允许。',
|
| 1469 |
target: { type: 'session', sessionId: TEST_SESSION_ID },
|
| 1470 |
})
|
|
|
|
| 2557 |
dedupeKey: 'computer-use-permission:cu-1',
|
| 2558 |
cooldownScope: 'permission-prompt',
|
| 2559 |
requestAttention: true,
|
| 2560 |
+
title: 'Versper AI Claw 需要你的确认',
|
| 2561 |
body: 'Open Finder and inspect a file',
|
| 2562 |
target: { type: 'session', sessionId: TEST_SESSION_ID },
|
| 2563 |
})
|
|
|
|
| 2997 |
|
| 2998 |
expect(notifyDesktopMock).toHaveBeenCalledWith(expect.objectContaining({
|
| 2999 |
cooldownScope: 'agent-completion',
|
| 3000 |
+
title: 'Versper AI Claw 已完成回复',
|
| 3001 |
body: '结果 修复完成 bun test 已通过',
|
| 3002 |
target: { type: 'session', sessionId: TEST_SESSION_ID },
|
| 3003 |
}))
|
desktop/src/stores/chatStore.ts
CHANGED
|
@@ -560,7 +560,7 @@ function buildAgentCompletionNotification(
|
|
| 560 |
const lastAssistant = [...messages].reverse().find((message) => message.type === 'assistant_text')
|
| 561 |
const suffix = preview.length > AGENT_COMPLETION_NOTIFICATION_PREVIEW_CHARS ? '...' : ''
|
| 562 |
return {
|
| 563 |
-
title: '
|
| 564 |
body: preview.slice(0, AGENT_COMPLETION_NOTIFICATION_PREVIEW_CHARS) + suffix,
|
| 565 |
dedupeKey: `agent-completion:${sessionId}:${lastAssistant?.id ?? Date.now()}`,
|
| 566 |
}
|
|
@@ -1240,7 +1240,7 @@ export const useChatStore = create<ChatStore>((set, get) => ({
|
|
| 1240 |
dedupeKey: `permission:${msg.requestId}`,
|
| 1241 |
cooldownScope: 'permission-prompt',
|
| 1242 |
requestAttention: true,
|
| 1243 |
-
title: '
|
| 1244 |
body: msg.toolName
|
| 1245 |
? `${msg.toolName} 请求执行,正在等待允许。`
|
| 1246 |
: '有一个工具请求正在等待允许。',
|
|
@@ -1279,7 +1279,7 @@ export const useChatStore = create<ChatStore>((set, get) => ({
|
|
| 1279 |
dedupeKey: `computer-use-permission:${msg.requestId}`,
|
| 1280 |
cooldownScope: 'permission-prompt',
|
| 1281 |
requestAttention: true,
|
| 1282 |
-
title: '
|
| 1283 |
body: msg.request.reason || 'Computer Use 正在等待允许。',
|
| 1284 |
target: { type: 'session', sessionId },
|
| 1285 |
})
|
|
|
|
| 560 |
const lastAssistant = [...messages].reverse().find((message) => message.type === 'assistant_text')
|
| 561 |
const suffix = preview.length > AGENT_COMPLETION_NOTIFICATION_PREVIEW_CHARS ? '...' : ''
|
| 562 |
return {
|
| 563 |
+
title: 'Versper AI Claw 已完成回复',
|
| 564 |
body: preview.slice(0, AGENT_COMPLETION_NOTIFICATION_PREVIEW_CHARS) + suffix,
|
| 565 |
dedupeKey: `agent-completion:${sessionId}:${lastAssistant?.id ?? Date.now()}`,
|
| 566 |
}
|
|
|
|
| 1240 |
dedupeKey: `permission:${msg.requestId}`,
|
| 1241 |
cooldownScope: 'permission-prompt',
|
| 1242 |
requestAttention: true,
|
| 1243 |
+
title: 'Versper AI Claw 需要你的确认',
|
| 1244 |
body: msg.toolName
|
| 1245 |
? `${msg.toolName} 请求执行,正在等待允许。`
|
| 1246 |
: '有一个工具请求正在等待允许。',
|
|
|
|
| 1279 |
dedupeKey: `computer-use-permission:${msg.requestId}`,
|
| 1280 |
cooldownScope: 'permission-prompt',
|
| 1281 |
requestAttention: true,
|
| 1282 |
+
title: 'Versper AI Claw 需要你的确认',
|
| 1283 |
body: msg.request.reason || 'Computer Use 正在等待允许。',
|
| 1284 |
target: { type: 'session', sessionId },
|
| 1285 |
})
|
desktop/tsconfig.tsbuildinfo
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"root":["./src/App.tsx","./src/main.test.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/__tests__/agentsSettings.test.tsx","./src/__tests__/diagnosticsSettings.test.tsx","./src/__tests__/generalSettings.test.tsx","./src/__tests__/mcpSettings.test.tsx","./src/__tests__/memorySettings.test.tsx","./src/__tests__/pages.test.tsx","./src/__tests__/pluginsSettings.test.tsx","./src/__tests__/skillsSettings.test.tsx","./src/__tests__/tauriCapabilities.test.ts","./src/api/activityStats.ts","./src/api/adapters.ts","./src/api/agents.ts","./src/api/cliTasks.ts","./src/api/client.test.ts","./src/api/client.ts","./src/api/computerUse.ts","./src/api/desktopUiPreferences.ts","./src/api/diagnostics.ts","./src/api/doctor.ts","./src/api/filesystem.ts","./src/api/h5Access.ts","./src/api/hahaOAuth.ts","./src/api/hahaOpenAIOAuth.ts","./src/api/mcp.ts","./src/api/memory.ts","./src/api/models.ts","./src/api/openTargets.test.ts","./src/api/openTargets.ts","./src/api/plugins.ts","./src/api/providers.ts","./src/api/search.ts","./src/api/sessions.test.ts","./src/api/sessions.ts","./src/api/settings.ts","./src/api/skills.ts","./src/api/tasks.ts","./src/api/teams.ts","./src/api/terminal.ts","./src/api/websocket.test.ts","./src/api/websocket.ts","./src/components/ErrorBoundary.test.tsx","./src/components/ErrorBoundary.tsx","./src/components/chat/AskUserQuestion.test.tsx","./src/components/chat/AskUserQuestion.tsx","./src/components/chat/AssistantMessage.tsx","./src/components/chat/AttachmentGallery.test.tsx","./src/components/chat/AttachmentGallery.tsx","./src/components/chat/ChatInput.test.tsx","./src/components/chat/ChatInput.tsx","./src/components/chat/CodeViewer.test.tsx","./src/components/chat/CodeViewer.tsx","./src/components/chat/ComposerDropOverlay.tsx","./src/components/chat/ComputerUsePermissionModal.test.tsx","./src/components/chat/ComputerUsePermissionModal.tsx","./src/components/chat/ContextUsageIndicator.test.tsx","./src/components/chat/ContextUsageIndicator.tsx","./src/components/chat/CurrentTurnChangeCard.tsx","./src/components/chat/DiffViewer.tsx","./src/components/chat/FileSearchMenu.test.tsx","./src/components/chat/FileSearchMenu.tsx","./src/components/chat/ImageGalleryModal.tsx","./src/components/chat/InlineImageGallery.tsx","./src/components/chat/InlineTaskSummary.tsx","./src/components/chat/LocalSlashCommandPanel.test.tsx","./src/components/chat/LocalSlashCommandPanel.tsx","./src/components/chat/MermaidRenderer.test.tsx","./src/components/chat/MermaidRenderer.tsx","./src/components/chat/MessageActionBar.tsx","./src/components/chat/MessageList.test.tsx","./src/components/chat/MessageList.tsx","./src/components/chat/PermissionDialog.tsx","./src/components/chat/SessionTaskBar.test.tsx","./src/components/chat/SessionTaskBar.tsx","./src/components/chat/StreamingIndicator.tsx","./src/components/chat/TerminalChrome.tsx","./src/components/chat/ThinkingBlock.tsx","./src/components/chat/ToolCallBlock.tsx","./src/components/chat/ToolCallGroup.tsx","./src/components/chat/ToolResultBlock.tsx","./src/components/chat/UserMessage.test.tsx","./src/components/chat/UserMessage.tsx","./src/components/chat/chatBlocks.test.tsx","./src/components/chat/clipboard.ts","./src/components/chat/composerUtils.test.ts","./src/components/chat/composerUtils.ts","./src/components/chat/useComposerFileDrop.ts","./src/components/companion/CompanionControls.tsx","./src/components/companion/CompanionTranscript.tsx","./src/components/companion/CompanionVideoPanel.tsx","./src/components/controls/ModelSelector.test.tsx","./src/components/controls/ModelSelector.tsx","./src/components/controls/PermissionModeSelector.test.tsx","./src/components/controls/PermissionModeSelector.tsx","./src/components/doctor/DoctorPanel.tsx","./src/components/layout/AppShell.test.tsx","./src/components/layout/AppShell.tsx","./src/components/layout/ContentRouter.test.tsx","./src/components/layout/ContentRouter.tsx","./src/components/layout/H5ConnectionView.tsx","./src/components/layout/OpenProjectMenu.test.tsx","./src/components/layout/OpenProjectMenu.tsx","./src/components/layout/Sidebar.test.tsx","./src/components/layout/Sidebar.tsx","./src/components/layout/StartupErrorView.test.tsx","./src/components/layout/StartupErrorView.tsx","./src/components/layout/StatusBar.tsx","./src/components/layout/TabBar.test.tsx","./src/components/layout/TabBar.tsx","./src/components/layout/TitleBar.tsx","./src/components/layout/WindowControls.test.tsx","./src/components/layout/WindowControls.tsx","./src/components/markdown/MarkdownRenderer.test.tsx","./src/components/markdown/MarkdownRenderer.tsx","./src/components/plugins/PluginDetail.tsx","./src/components/plugins/PluginList.tsx","./src/components/settings/ChatGPTOfficialLogin.test.tsx","./src/components/settings/ChatGPTOfficialLogin.tsx","./src/components/settings/ClaudeOfficialLogin.tsx","./src/components/shared/Button.tsx","./src/components/shared/ConfirmDialog.tsx","./src/components/shared/CopyButton.tsx","./src/components/shared/DirectoryPicker.test.tsx","./src/components/shared/DirectoryPicker.tsx","./src/components/shared/Dropdown.tsx","./src/components/shared/Input.tsx","./src/components/shared/MobileBottomSheet.tsx","./src/components/shared/Modal.test.tsx","./src/components/shared/Modal.tsx","./src/components/shared/ProjectContextChip.test.tsx","./src/components/shared/ProjectContextChip.tsx","./src/components/shared/RepositoryLaunchControls.test.tsx","./src/components/shared/RepositoryLaunchControls.tsx","./src/components/shared/Spinner.tsx","./src/components/shared/Textarea.tsx","./src/components/shared/Toast.tsx","./src/components/shared/UpdateChecker.test.tsx","./src/components/shared/UpdateChecker.tsx","./src/components/skills/SkillDetail.test.tsx","./src/components/skills/SkillDetail.tsx","./src/components/skills/SkillList.tsx","./src/components/tasks/DayOfWeekPicker.tsx","./src/components/tasks/NewTaskModal.test.tsx","./src/components/tasks/NewTaskModal.tsx","./src/components/tasks/PromptEditor.tsx","./src/components/tasks/TaskEmptyState.tsx","./src/components/tasks/TaskList.tsx","./src/components/tasks/TaskRow.tsx","./src/components/tasks/TaskRunsPanel.test.tsx","./src/components/tasks/TaskRunsPanel.tsx","./src/components/teams/TeamStatusBar.tsx","./src/components/workspace/WorkspaceCodeSurface.tsx","./src/components/workspace/WorkspacePanel.test.tsx","./src/components/workspace/WorkspacePanel.tsx","./src/config/spinnerVerbs.ts","./src/constants/modelCatalog.ts","./src/constants/openaiOfficialProvider.ts","./src/hooks/useCompanionAudio.ts","./src/hooks/useCompanionWebSocket.ts","./src/hooks/useKeyboardShortcuts.test.tsx","./src/hooks/useKeyboardShortcuts.ts","./src/hooks/useMicrophone.ts","./src/hooks/useMobileViewport.test.tsx","./src/hooks/useMobileViewport.ts","./src/hooks/useScheduledTaskDesktopNotifications.test.tsx","./src/hooks/useScheduledTaskDesktopNotifications.ts","./src/hooks/useSelectionPopoverDismiss.ts","./src/hooks/useWebcam.ts","./src/i18n/index.test.tsx","./src/i18n/index.ts","./src/i18n/locales/en.ts","./src/i18n/locales/zh.ts","./src/lib/appZoom.test.ts","./src/lib/appZoom.ts","./src/lib/audioEngine.ts","./src/lib/composerAttachments.test.ts","./src/lib/composerAttachments.ts","./src/lib/cronDescribe.ts","./src/lib/desktopNotificationNavigation.test.ts","./src/lib/desktopNotificationNavigation.ts","./src/lib/desktopNotifications.test.ts","./src/lib/desktopNotifications.ts","./src/lib/desktopRuntime.test.ts","./src/lib/desktopRuntime.ts","./src/lib/diagnosticsCapture.ts","./src/lib/doctorRepair.test.ts","./src/lib/doctorRepair.ts","./src/lib/formatBytes.ts","./src/lib/parseRunOutput.ts","./src/lib/persistenceMigrations.test.ts","./src/lib/persistenceMigrations.ts","./src/lib/providerSettingsJson.ts","./src/lib/sessionTitle.test.ts","./src/lib/sessionTitle.ts","./src/lib/__tests__/cronDescribe.test.ts","./src/lib/__tests__/providerSettingsJson.test.ts","./src/mocks/data.ts","./src/pages/ActiveSession.test.tsx","./src/pages/ActiveSession.tsx","./src/pages/ActivitySettings.test.tsx","./src/pages/ActivitySettings.tsx","./src/pages/AdapterSettings.test.tsx","./src/pages/AdapterSettings.tsx","./src/pages/AgentTeams.tsx","./src/pages/Companion.tsx","./src/pages/ComputerUseSettings.test.tsx","./src/pages/ComputerUseSettings.tsx","./src/pages/DiagnosticsSettings.tsx","./src/pages/EmptySession.test.tsx","./src/pages/EmptySession.tsx","./src/pages/McpSettings.tsx","./src/pages/MemorySettings.tsx","./src/pages/NewTaskModal.tsx","./src/pages/ScheduledTasks.tsx","./src/pages/ScheduledTasksEmpty.tsx","./src/pages/ScheduledTasksList.tsx","./src/pages/SessionControls.tsx","./src/pages/Settings.tsx","./src/pages/TerminalSettings.test.tsx","./src/pages/TerminalSettings.tsx","./src/pages/ToolInspection.tsx","./src/stores/adapterStore.test.ts","./src/stores/adapterStore.ts","./src/stores/agentStore.ts","./src/stores/chatStore.test.ts","./src/stores/chatStore.ts","./src/stores/cliTaskStore.test.ts","./src/stores/cliTaskStore.ts","./src/stores/companionStore.ts","./src/stores/hahaOAuthStore.test.ts","./src/stores/hahaOAuthStore.ts","./src/stores/hahaOpenAIOAuthStore.test.ts","./src/stores/hahaOpenAIOAuthStore.ts","./src/stores/mcpStore.ts","./src/stores/memoryStore.ts","./src/stores/openTargetStore.test.ts","./src/stores/openTargetStore.ts","./src/stores/pluginStore.test.ts","./src/stores/pluginStore.ts","./src/stores/providerStore.test.ts","./src/stores/providerStore.ts","./src/stores/sessionRuntimeStore.ts","./src/stores/sessionStore.test.ts","./src/stores/sessionStore.ts","./src/stores/settingsStore.test.ts","./src/stores/settingsStore.ts","./src/stores/skillStore.ts","./src/stores/tabStore.test.ts","./src/stores/tabStore.ts","./src/stores/taskStore.ts","./src/stores/teamStore.ts","./src/stores/terminalPanelStore.ts","./src/stores/uiStore.test.ts","./src/stores/uiStore.ts","./src/stores/updateStore.test.ts","./src/stores/updateStore.ts","./src/stores/workspaceChatContextStore.test.ts","./src/stores/workspaceChatContextStore.ts","./src/stores/workspacePanelStore.test.ts","./src/stores/workspacePanelStore.ts","./src/theme/globals.test.ts","./src/types/adapter.ts","./src/types/chat.ts","./src/types/cliTask.ts","./src/types/companion.ts","./src/types/mcp.ts","./src/types/memory.ts","./src/types/plugin.ts","./src/types/provider.ts","./src/types/providerPreset.ts","./src/types/qrcode.d.ts","./src/types/runtime.ts","./src/types/session.ts","./src/types/settings.ts","./src/types/skill.ts","./src/types/task.ts","./src/types/team.ts"],"errors":true,"version":"5.9.3"}
|
src/server/api/haha-oauth.ts
CHANGED
|
@@ -106,7 +106,7 @@ function renderCallbackPage(success: boolean, errorMsg: string | null): string {
|
|
| 106 |
return `<!doctype html>
|
| 107 |
<html><head><meta charset="utf-8"><title>Login Success</title>
|
| 108 |
<style>body{font-family:-apple-system,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#fafafa;color:#333}.card{text-align:center;padding:40px;background:white;border-radius:12px;box-shadow:0 4px 16px rgba(0,0,0,.06)}h1{color:#16a34a;margin:0 0 12px}p{color:#666}</style>
|
| 109 |
-
</head><body><div class="card"><h1>✓ Login Successful</h1><p>You can close this window and return to
|
| 110 |
<script>setTimeout(() => window.close(), 1500)</script>
|
| 111 |
</body></html>`
|
| 112 |
}
|
|
|
|
| 106 |
return `<!doctype html>
|
| 107 |
<html><head><meta charset="utf-8"><title>Login Success</title>
|
| 108 |
<style>body{font-family:-apple-system,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#fafafa;color:#333}.card{text-align:center;padding:40px;background:white;border-radius:12px;box-shadow:0 4px 16px rgba(0,0,0,.06)}h1{color:#16a34a;margin:0 0 12px}p{color:#666}</style>
|
| 109 |
+
</head><body><div class="card"><h1>✓ Login Successful</h1><p>You can close this window and return to Versper AI Claw.</p></div>
|
| 110 |
<script>setTimeout(() => window.close(), 1500)</script>
|
| 111 |
</body></html>`
|
| 112 |
}
|
src/server/api/haha-openai-oauth.ts
CHANGED
|
@@ -101,7 +101,7 @@ function renderCallbackPage(success: boolean, errorMsg: string | null): string {
|
|
| 101 |
return `<!doctype html>
|
| 102 |
<html><head><meta charset="utf-8"><title>OpenAI Login Success</title>
|
| 103 |
<style>body{font-family:-apple-system,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#fafafa;color:#333}.card{text-align:center;padding:40px;background:white;border-radius:12px;box-shadow:0 4px 16px rgba(0,0,0,.06)}h1{color:#16a34a;margin:0 0 12px}p{color:#666}</style>
|
| 104 |
-
</head><body><div class="card"><h1>✓ OpenAI Login Successful</h1><p>You can close this window and return to
|
| 105 |
<script>setTimeout(() => window.close(), 1500)</script>
|
| 106 |
</body></html>`
|
| 107 |
}
|
|
|
|
| 101 |
return `<!doctype html>
|
| 102 |
<html><head><meta charset="utf-8"><title>OpenAI Login Success</title>
|
| 103 |
<style>body{font-family:-apple-system,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#fafafa;color:#333}.card{text-align:center;padding:40px;background:white;border-radius:12px;box-shadow:0 4px 16px rgba(0,0,0,.06)}h1{color:#16a34a;margin:0 0 12px}p{color:#666}</style>
|
| 104 |
+
</head><body><div class="card"><h1>✓ OpenAI Login Successful</h1><p>You can close this window and return to Versper AI Claw.</p></div>
|
| 105 |
<script>setTimeout(() => window.close(), 1500)</script>
|
| 106 |
</body></html>`
|
| 107 |
}
|
src/server/services/desktopCliLauncherService.ts
CHANGED
|
@@ -19,8 +19,8 @@ import { getShellConfigPaths } from '../../utils/shellConfig.js'
|
|
| 19 |
import { getUserBinDir } from '../../utils/xdg.js'
|
| 20 |
|
| 21 |
const DESKTOP_CLI_NAME = 'claude-haha'
|
| 22 |
-
const PATH_BLOCK_START = '# >>>
|
| 23 |
-
const PATH_BLOCK_END = '# <<<
|
| 24 |
const WINDOWS_PATH_TARGET = 'Windows User PATH'
|
| 25 |
const WINDOWS_USER_BIN_EXPR = '%USERPROFILE%\\.local\\bin'
|
| 26 |
|
|
|
|
| 19 |
import { getUserBinDir } from '../../utils/xdg.js'
|
| 20 |
|
| 21 |
const DESKTOP_CLI_NAME = 'claude-haha'
|
| 22 |
+
const PATH_BLOCK_START = '# >>> Versper AI Claw PATH >>>'
|
| 23 |
+
const PATH_BLOCK_END = '# <<< Versper AI Claw PATH <<<'
|
| 24 |
const WINDOWS_PATH_TARGET = 'Windows User PATH'
|
| 25 |
const WINDOWS_USER_BIN_EXPR = '%USERPROFILE%\\.local\\bin'
|
| 26 |
|
src/server/services/hahaOpenAIOAuthService.ts
CHANGED
|
@@ -56,7 +56,7 @@ const SESSION_TTL_MS = 5 * 60 * 1000
|
|
| 56 |
const HTML_SUCCESS = `<!doctype html>
|
| 57 |
<html><head><meta charset="utf-8"><title>OpenAI Login Success</title>
|
| 58 |
<style>body{font-family:-apple-system,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#fafafa;color:#333}.card{text-align:center;padding:40px;background:white;border-radius:12px;box-shadow:0 4px 16px rgba(0,0,0,.06)}h1{color:#16a34a;margin:0 0 12px}p{color:#666}</style>
|
| 59 |
-
</head><body><div class="card"><h1>OpenAI Login Successful</h1><p>You can close this window and return to
|
| 60 |
<script>setTimeout(() => window.close(), 1500)</script>
|
| 61 |
</body></html>`
|
| 62 |
|
|
|
|
| 56 |
const HTML_SUCCESS = `<!doctype html>
|
| 57 |
<html><head><meta charset="utf-8"><title>OpenAI Login Success</title>
|
| 58 |
<style>body{font-family:-apple-system,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#fafafa;color:#333}.card{text-align:center;padding:40px;background:white;border-radius:12px;box-shadow:0 4px 16px rgba(0,0,0,.06)}h1{color:#16a34a;margin:0 0 12px}p{color:#666}</style>
|
| 59 |
+
</head><body><div class="card"><h1>OpenAI Login Successful</h1><p>You can close this window and return to Versper AI Claw.</p></div>
|
| 60 |
<script>setTimeout(() => window.close(), 1500)</script>
|
| 61 |
</body></html>`
|
| 62 |
|