Files
zclaw_openfang/scripts/setup.ts
iven 07079293f4 feat(hands): restructure Hands UI with Chinese localization
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>
2026-03-14 23:16:32 +08:00

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);
});