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>
This commit is contained in:
@@ -19,6 +19,14 @@ const OPENCLAW_HOME = process.env.OPENCLAW_HOME || path.join(
|
||||
|
||||
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}`);
|
||||
}
|
||||
@@ -50,35 +58,37 @@ function checkOpenClaw(): boolean {
|
||||
function setupConfig() {
|
||||
const configDir = OPENCLAW_HOME;
|
||||
const configFile = path.join(configDir, 'openclaw.json');
|
||||
const defaultConfigPath = path.join(ZCLAW_ROOT, 'config', 'openclaw.default.json');
|
||||
|
||||
// Create directory
|
||||
fs.mkdirSync(configDir, { recursive: true });
|
||||
|
||||
// Copy default config if no config exists
|
||||
if (!fs.existsSync(configFile)) {
|
||||
const defaultConfig = fs.readFileSync(
|
||||
path.join(ZCLAW_ROOT, 'config', 'openclaw.default.json'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
// Update plugin paths to absolute paths
|
||||
const config = JSON.parse(defaultConfig);
|
||||
if (config.plugins?.load?.paths) {
|
||||
config.plugins.load.paths = config.plugins.load.paths.map((p: string) =>
|
||||
path.resolve(ZCLAW_ROOT, p)
|
||||
);
|
||||
}
|
||||
if (config.skills?.load?.extraDirs) {
|
||||
config.skills.load.extraDirs = config.skills.load.extraDirs.map((p: string) =>
|
||||
path.resolve(ZCLAW_ROOT, p)
|
||||
);
|
||||
}
|
||||
|
||||
fs.writeFileSync(configFile, JSON.stringify(config, null, 2), 'utf-8');
|
||||
success(`Config written to ${configFile}`);
|
||||
} else {
|
||||
log(`Config already exists at ${configFile}, skipping`);
|
||||
}
|
||||
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'];
|
||||
|
||||
Reference in New Issue
Block a user