Files
qiming/qimingclaw/crates/agent-electron-client/scripts/sync-sgrobot-digital.js
2026-06-29 19:53:34 +08:00

89 lines
3.6 KiB
JavaScript

#!/usr/bin/env node
const fs = require('node:fs');
const path = require('node:path');
const clientRoot = path.resolve(__dirname, '..');
const repoRoot = path.resolve(clientRoot, '../..');
const defaultSgRobotWeb = path.resolve(repoRoot, '../../sgRobot/crates/sgclaw-core/web');
const sourceRoot = path.resolve(process.env.SGROBOT_WEB_DIR || defaultSgRobotWeb);
const targetRoot = path.resolve(clientRoot, 'embedded/sgrobot-digital');
const copies = [
['src/pages/digital/CommandDeck.tsx', 'src/pages/digital/CommandDeck.tsx'],
['src/pages/digital/MissionCenter.tsx', 'src/pages/digital/MissionCenter.tsx'],
['src/pages/digital/OpsSettings.tsx', 'src/pages/digital/OpsSettings.tsx'],
['src/pages/digital/demoScenario.ts', 'src/pages/digital/demoScenario.ts'],
['src/components/digital', 'src/components/digital'],
['src/components/shared/ApprovalActionCard.tsx', 'src/components/shared/ApprovalActionCard.tsx'],
['src/contexts/RoleContext.tsx', 'src/contexts/RoleContext.tsx'],
['src/lib/approvals.ts', 'src/lib/approvals.ts'],
['src/lib/auth.ts', 'src/lib/auth.ts'],
['src/lib/dateFormat.ts', 'src/lib/dateFormat.ts'],
['src/lib/i18n.ts', 'src/lib/i18n.ts'],
['src/lib/uuid.ts', 'src/lib/uuid.ts'],
['src/lib/ws.ts', 'src/lib/ws.ts'],
['src/planb/ChatInput.tsx', 'src/planb/ChatInput.tsx'],
['src/planb/PlanChat.tsx', 'src/planb/PlanChat.tsx'],
['src/index.css', 'src/index.css'],
['public/digital-assets', 'public/digital-assets'],
['public/logo.png', 'public/logo.png'],
];
function assertExists(location) {
if (!fs.existsSync(location)) {
throw new Error(`Missing required path: ${location}`);
}
}
function copyPath(from, to) {
assertExists(from);
fs.rmSync(to, { recursive: true, force: true });
fs.mkdirSync(path.dirname(to), { recursive: true });
fs.cpSync(from, to, { recursive: true });
}
function stripTauriWindowImport() {
const shellPath = path.join(targetRoot, 'src/pages/digital/DigitalEmployeeShell.tsx');
let source = fs.readFileSync(shellPath, 'utf8');
source = source.replace("import { isTauri } from '@/lib/tauri';\n", '');
source = source.replace(
/\n if \(isTauri\(\)\) \{\n void import\('@tauri-apps\/api\/window'\)[\s\S]*?\n return;\n \}/,
'',
);
fs.writeFileSync(shellPath, source);
}
function injectQimingclawApiAdapter() {
const apiPath = path.join(targetRoot, 'src/lib/api.ts');
let source = fs.readFileSync(apiPath, 'utf8');
if (!source.includes("import { handleQimingclawDigitalApi } from './qimingclawAdapter';")) {
source = source.replace(
"import { apiOrigin, apiBase } from './basePath';\n",
"import { apiOrigin, apiBase } from './basePath';\nimport { handleQimingclawDigitalApi } from './qimingclawAdapter';\n",
);
}
if (!source.includes('const adapterData = await handleQimingclawDigitalApi<T>(path, options);')) {
source = source.replace(
"): Promise<T> {\n const { timeoutMs = API_FETCH_TIMEOUT_MS, ...fetchOptions } = options;",
"): Promise<T> {\n const adapterData = await handleQimingclawDigitalApi<T>(path, options);\n if (adapterData !== undefined) {\n return adapterData;\n }\n\n const { timeoutMs = API_FETCH_TIMEOUT_MS, ...fetchOptions } = options;",
);
}
fs.writeFileSync(apiPath, source);
}
function main() {
assertExists(sourceRoot);
assertExists(targetRoot);
for (const [fromRel, toRel] of copies) {
copyPath(path.join(sourceRoot, fromRel), path.join(targetRoot, toRel));
}
console.log(`Synced sgRobot digital UI from ${sourceRoot}`);
console.log(`Target: ${targetRoot}`);
console.log('qimingclaw embedded adapters, types, shell navigation, and workbench pages were preserved.');
}
main();