Major changes: - Add HandList.tsx component for left sidebar - Add HandTaskPanel.tsx for middle content area - Restructure Sidebar tabs: 分身/HANDS/Workflow - Remove Hands tab from RightPanel - Localize all UI text to Chinese - Archive legacy OpenClaw documentation - Add Hands integration lessons document - Update feature checklist with new components UI improvements: - Left sidebar now shows Hands list with status icons - Middle area shows selected Hand's tasks and results - Consistent styling with Tailwind CSS - Chinese status labels and buttons Documentation: - Create docs/archive/openclaw-legacy/ for old docs - Add docs/knowledge-base/hands-integration-lessons.md - Update docs/knowledge-base/feature-checklist.md - Update docs/knowledge-base/README.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
189 lines
5.6 KiB
TypeScript
189 lines
5.6 KiB
TypeScript
/**
|
|
* ZCLAW Setup Script
|
|
*
|
|
* First-time setup for ZCLAW:
|
|
* 1. Check if OpenClaw is installed
|
|
* 2. Copy default config files to ~/.openclaw/
|
|
* 3. Register ZCLAW custom plugins
|
|
* 4. Create workspace directory
|
|
*/
|
|
|
|
import { execSync, exec } from 'child_process';
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
|
|
const OPENCLAW_HOME = process.env.OPENCLAW_HOME || path.join(
|
|
process.env.HOME || process.env.USERPROFILE || '',
|
|
'.openclaw'
|
|
);
|
|
|
|
const ZCLAW_ROOT = path.resolve(__dirname, '..');
|
|
|
|
function uniqueStrings(values: string[]): string[] {
|
|
return Array.from(new Set(values.filter(Boolean)));
|
|
}
|
|
|
|
function resolveRepoPaths(values: string[] | undefined): string[] {
|
|
return (values || []).map((p) => path.resolve(ZCLAW_ROOT, p));
|
|
}
|
|
|
|
function log(msg: string) {
|
|
console.log(`[ZCLAW Setup] ${msg}`);
|
|
}
|
|
|
|
function error(msg: string) {
|
|
console.error(`[ZCLAW Setup] ❌ ${msg}`);
|
|
}
|
|
|
|
function success(msg: string) {
|
|
console.log(`[ZCLAW Setup] ✅ ${msg}`);
|
|
}
|
|
|
|
// Step 1: Check OpenClaw installation
|
|
function checkOpenClaw(): boolean {
|
|
try {
|
|
const version = execSync('openclaw --version', { encoding: 'utf-8' }).trim();
|
|
success(`OpenClaw found: ${version}`);
|
|
return true;
|
|
} catch {
|
|
error('OpenClaw not found. Please install it first:');
|
|
console.log(' Windows: iwr -useb https://openclaw.ai/install.ps1 | iex');
|
|
console.log(' macOS/Linux: curl -fsSL https://openclaw.ai/install.sh | bash');
|
|
console.log(' npm: npm install -g openclaw@latest');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Step 2: Copy default config
|
|
function setupConfig() {
|
|
const configDir = OPENCLAW_HOME;
|
|
const configFile = path.join(configDir, 'openclaw.json');
|
|
const defaultConfigPath = path.join(ZCLAW_ROOT, 'config', 'openclaw.default.json');
|
|
|
|
fs.mkdirSync(configDir, { recursive: true });
|
|
|
|
const defaultConfig = JSON.parse(fs.readFileSync(defaultConfigPath, 'utf-8'));
|
|
const config = fs.existsSync(configFile)
|
|
? JSON.parse(fs.readFileSync(configFile, 'utf-8'))
|
|
: defaultConfig;
|
|
|
|
const defaultPluginPaths = resolveRepoPaths(defaultConfig.plugins?.load?.paths);
|
|
const existingPluginPaths = Array.isArray(config.plugins?.load?.paths)
|
|
? config.plugins.load.paths
|
|
: [];
|
|
const mergedPluginPaths = uniqueStrings([...existingPluginPaths, ...defaultPluginPaths]);
|
|
|
|
const defaultSkillDirs = resolveRepoPaths(defaultConfig.skills?.load?.extraDirs);
|
|
const existingSkillDirs = Array.isArray(config.skills?.load?.extraDirs)
|
|
? config.skills.load.extraDirs
|
|
: [];
|
|
const mergedSkillDirs = uniqueStrings([...existingSkillDirs, ...defaultSkillDirs]);
|
|
|
|
config.plugins = config.plugins || {};
|
|
config.plugins.load = config.plugins.load || {};
|
|
config.plugins.load.paths = mergedPluginPaths;
|
|
|
|
config.skills = config.skills || {};
|
|
config.skills.load = config.skills.load || {};
|
|
config.skills.load.extraDirs = mergedSkillDirs;
|
|
|
|
fs.writeFileSync(configFile, JSON.stringify(config, null, 2), 'utf-8');
|
|
success(fs.existsSync(configFile) ? `Config updated at ${configFile}` : `Config written to ${configFile}`);
|
|
|
|
// Copy bootstrap files
|
|
const bootstrapFiles = ['SOUL.md', 'AGENTS.md', 'IDENTITY.md', 'USER.md'];
|
|
const workspaceDir = path.join(configDir, 'zclaw-workspace');
|
|
fs.mkdirSync(workspaceDir, { recursive: true });
|
|
|
|
for (const file of bootstrapFiles) {
|
|
const src = path.join(ZCLAW_ROOT, 'config', file);
|
|
const dest = path.join(workspaceDir, file);
|
|
if (fs.existsSync(src) && !fs.existsSync(dest)) {
|
|
fs.copyFileSync(src, dest);
|
|
success(`Bootstrap file copied: ${file}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Step 3: Register plugins
|
|
function registerPlugins() {
|
|
const pluginDirs = ['zclaw-chinese-models', 'zclaw-feishu', 'zclaw-ui'];
|
|
|
|
for (const plugin of pluginDirs) {
|
|
const pluginPath = path.join(ZCLAW_ROOT, 'plugins', plugin);
|
|
if (fs.existsSync(pluginPath)) {
|
|
try {
|
|
// Use openclaw plugins install -l (link mode) for development
|
|
execSync(`openclaw plugins install -l "${pluginPath}"`, {
|
|
encoding: 'utf-8',
|
|
stdio: 'pipe'
|
|
});
|
|
success(`Plugin linked: ${plugin}`);
|
|
} catch (err: any) {
|
|
// Plugin might already be registered, or command format different
|
|
log(`Plugin ${plugin} registration note: ${err.message?.split('\n')[0] || 'check manually'}`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Step 4: Create workspace
|
|
function setupWorkspace() {
|
|
const workspace = path.join(OPENCLAW_HOME, 'zclaw-workspace');
|
|
const dirs = ['skills', 'output', 'context'];
|
|
|
|
for (const dir of dirs) {
|
|
const fullPath = path.join(workspace, dir);
|
|
fs.mkdirSync(fullPath, { recursive: true });
|
|
}
|
|
success(`Workspace ready at ${workspace}`);
|
|
}
|
|
|
|
// Main
|
|
async function main() {
|
|
console.log('');
|
|
console.log('🦞 ZCLAW Setup');
|
|
console.log('─'.repeat(40));
|
|
console.log('');
|
|
|
|
// Step 1
|
|
log('Checking OpenClaw installation...');
|
|
const hasOpenClaw = checkOpenClaw();
|
|
|
|
if (!hasOpenClaw) {
|
|
console.log('');
|
|
console.log('Install OpenClaw first, then re-run this setup.');
|
|
process.exit(1);
|
|
}
|
|
|
|
// Step 2
|
|
console.log('');
|
|
log('Setting up configuration...');
|
|
setupConfig();
|
|
|
|
// Step 3
|
|
console.log('');
|
|
log('Registering plugins...');
|
|
registerPlugins();
|
|
|
|
// Step 4
|
|
console.log('');
|
|
log('Setting up workspace...');
|
|
setupWorkspace();
|
|
|
|
console.log('');
|
|
console.log('─'.repeat(40));
|
|
success('ZCLAW setup complete!');
|
|
console.log('');
|
|
console.log('Next steps:');
|
|
console.log(' 1. Configure API keys: openclaw configure');
|
|
console.log(' 2. Start gateway: openclaw gateway');
|
|
console.log(' 3. Launch ZCLAW desktop: cd desktop && pnpm tauri dev');
|
|
console.log('');
|
|
}
|
|
|
|
main().catch((err) => {
|
|
error(`Setup failed: ${err.message}`);
|
|
process.exit(1);
|
|
});
|