feat: prepare Zhinian desktop client for pilot release

This commit is contained in:
inman
2026-04-29 10:23:20 +08:00
parent f9361e686a
commit 47b83b79fc
149 changed files with 15341 additions and 3590 deletions

View File

@@ -596,6 +596,21 @@ exports.default = async function afterPack(context) {
}
}
const staticPluginRoot = join(__dirname, '..', 'resources', 'openclaw-plugins');
if (existsSync(staticPluginRoot)) {
for (const entry of readdirSync(staticPluginRoot, { withFileTypes: true })) {
if (!entry.isDirectory()) continue;
const sourceDir = join(staticPluginRoot, entry.name);
if (!existsSync(join(sourceDir, 'openclaw.plugin.json'))) continue;
const pluginDestDir = join(pluginsDestRoot, entry.name);
console.log(`[after-pack] Copying static plugin ${entry.name} -> ${pluginDestDir}`);
rmSync(pluginDestDir, { recursive: true, force: true });
cpSync(sourceDir, pluginDestDir, { recursive: true, dereference: true });
cleanupUnnecessaryFiles(pluginDestDir);
patchPluginIds(pluginDestDir, entry.name);
}
}
// 1.2 Copy built-in extension node_modules that electron-builder skipped.
// OpenClaw 3.31+ ships built-in extensions (discord, qqbot, etc.) under
// dist/extensions/<ext>/node_modules/. These are skipped by extraResources

View File

@@ -23,6 +23,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, '..');
const OUTPUT_ROOT = path.join(ROOT, 'build', 'openclaw-plugins');
const NODE_MODULES = path.join(ROOT, 'node_modules');
const STATIC_PLUGIN_ROOT = path.join(ROOT, 'resources', 'openclaw-plugins');
// On Windows, pnpm virtual store paths can exceed MAX_PATH (260 chars).
// Adding \\?\ prefix bypasses the limit for Win32 fs calls.
@@ -241,4 +242,17 @@ for (const plugin of PLUGINS) {
bundleOnePlugin(plugin);
}
if (fs.existsSync(STATIC_PLUGIN_ROOT)) {
for (const entry of fs.readdirSync(STATIC_PLUGIN_ROOT, { withFileTypes: true })) {
if (!entry.isDirectory()) continue;
const sourceDir = path.join(STATIC_PLUGIN_ROOT, entry.name);
const outputDir = path.join(OUTPUT_ROOT, entry.name);
const manifestPath = path.join(sourceDir, 'openclaw.plugin.json');
if (!fs.existsSync(manifestPath)) continue;
echo`📦 Copying static plugin ${entry.name} -> ${outputDir}`;
fs.rmSync(outputDir, { recursive: true, force: true });
fs.cpSync(sourceDir, outputDir, { recursive: true, dereference: true });
}
}
echo`✅ Plugin mirrors ready: ${OUTPUT_ROOT}`;

View File

@@ -12,7 +12,7 @@ const PROJECT_ROOT = path.resolve(__dirname, '..');
const ICONS_DIR = path.join(PROJECT_ROOT, 'resources', 'icons');
const SVG_SOURCE = path.join(ICONS_DIR, 'icon.svg');
echo`🎨 Generating ClawX icons using Node.js...`;
echo`🎨 Generating 智念助手 icons using Node.js...`;
// Check if SVG source exists
if (!fs.existsSync(SVG_SOURCE)) {

View File

@@ -283,9 +283,11 @@
_cu_pathDone:
; Ask user if they want to remove AppData (preserves .openclaw)
; Ask user if they want to remove AppData.
; IMPORTANT: never remove .openclaw. It may contain a user-managed OpenClaw
; installation, skills, channel state, and the app-managed fallback runtime.
MessageBox MB_YESNO|MB_ICONQUESTION \
"Do you want to remove ClawX application data?$\r$\n$\r$\nThis will delete:$\r$\n • AppData\Local\clawx (local app data)$\r$\n • AppData\Roaming\clawx (roaming app data)$\r$\n$\r$\nYour .openclaw folder (configuration & skills) will be preserved.$\r$\nSelect 'No' to keep all data for future reinstallation." \
"Do you want to remove ClawX application data?$\r$\n$\r$\nThis will delete:$\r$\n • AppData\Local\clawx (local app data)$\r$\n • AppData\Roaming\clawx (roaming app data)$\r$\n$\r$\nYour .openclaw folder (OpenClaw runtime, configuration, skills, and channel data) will be preserved.$\r$\nSelect 'No' to keep all data for future reinstallation." \
/SD IDNO IDYES _cu_removeData IDNO _cu_skipRemove
_cu_removeData:
@@ -303,7 +305,7 @@
Sleep 2000
; --- Always remove current user's AppData first ---
; NOTE: .openclaw directory is intentionally preserved (user configuration & skills)
; NOTE: .openclaw directory is intentionally preserved (OpenClaw runtime, user configuration, skills, and channel data)
RMDir /r "$LOCALAPPDATA\clawx"
RMDir /r "$APPDATA\clawx"

View File

@@ -19,11 +19,16 @@ if [ -x /opt/ClawX/clawx ]; then
ln -sf /opt/ClawX/clawx /usr/local/bin/clawx 2>/dev/null || true
fi
# Create symbolic link for openclaw CLI
# Create symbolic link for the app-managed openclaw CLI only when it will not
# overwrite a user-managed OpenClaw installation.
OPENCLAW_WRAPPER="/opt/ClawX/resources/cli/openclaw"
if [ -f "$OPENCLAW_WRAPPER" ]; then
chmod +x "$OPENCLAW_WRAPPER" 2>/dev/null || true
ln -sf "$OPENCLAW_WRAPPER" /usr/local/bin/openclaw 2>/dev/null || true
if [ ! -e /usr/local/bin/openclaw ] || [ "$(readlink /usr/local/bin/openclaw 2>/dev/null || true)" = "$OPENCLAW_WRAPPER" ]; then
ln -sf "$OPENCLAW_WRAPPER" /usr/local/bin/openclaw 2>/dev/null || true
else
echo "Keeping existing /usr/local/bin/openclaw; it is not managed by ClawX."
fi
fi
# Set chrome-sandbox permissions.

View File

@@ -6,7 +6,13 @@ set -e
# Remove symbolic links
rm -f /usr/local/bin/clawx 2>/dev/null || true
rm -f /usr/local/bin/openclaw 2>/dev/null || true
# Only remove the app-managed OpenClaw CLI wrapper. If the user had OpenClaw
# installed separately, leave their command and ~/.openclaw data untouched.
OPENCLAW_WRAPPER="/opt/ClawX/resources/cli/openclaw"
if [ "$(readlink /usr/local/bin/openclaw 2>/dev/null || true)" = "$OPENCLAW_WRAPPER" ]; then
rm -f /usr/local/bin/openclaw 2>/dev/null || true
fi
# Update desktop database
if command -v update-desktop-database &> /dev/null; then