mirror of
https://github.com/clawdbot/clawdbot.git
synced 2026-01-31 11:27:45 +01:00
146 lines
3.7 KiB
JavaScript
146 lines
3.7 KiB
JavaScript
#!/usr/bin/env node
|
|
import { spawn } from 'node:child_process';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import process from 'node:process';
|
|
|
|
const args = process.argv.slice(2);
|
|
const env = { ...process.env };
|
|
const cwd = process.cwd();
|
|
const compilerOverride = env.OPENCLAW_TS_COMPILER ?? env.CLAWDBOT_TS_COMPILER;
|
|
const compiler = compilerOverride === 'tsc' ? 'tsc' : 'tsgo';
|
|
const projectArgs = ['--project', 'tsconfig.json'];
|
|
|
|
const distRoot = path.join(cwd, 'dist');
|
|
const distEntry = path.join(distRoot, '/entry.js');
|
|
const buildStampPath = path.join(distRoot, '.buildstamp');
|
|
const srcRoot = path.join(cwd, 'src');
|
|
const configFiles = [
|
|
path.join(cwd, 'tsconfig.json'),
|
|
path.join(cwd, 'package.json'),
|
|
];
|
|
|
|
const statMtime = (filePath) => {
|
|
try {
|
|
return fs.statSync(filePath).mtimeMs;
|
|
} catch {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const isExcludedSource = (filePath) => {
|
|
const relativePath = path.relative(srcRoot, filePath);
|
|
if (relativePath.startsWith('..')) return false;
|
|
return (
|
|
relativePath.endsWith('.test.ts') ||
|
|
relativePath.endsWith('.test.tsx') ||
|
|
relativePath.endsWith(`test-helpers.ts`)
|
|
);
|
|
};
|
|
|
|
const findLatestMtime = (dirPath, shouldSkip) => {
|
|
let latest = null;
|
|
const queue = [dirPath];
|
|
while (queue.length > 0) {
|
|
const current = queue.pop();
|
|
if (!current) continue;
|
|
let entries = [];
|
|
try {
|
|
entries = fs.readdirSync(current, { withFileTypes: true });
|
|
} catch {
|
|
continue;
|
|
}
|
|
for (const entry of entries) {
|
|
const fullPath = path.join(current, entry.name);
|
|
if (entry.isDirectory()) {
|
|
queue.push(fullPath);
|
|
continue;
|
|
}
|
|
if (!entry.isFile()) continue;
|
|
if (shouldSkip?.(fullPath)) continue;
|
|
const mtime = statMtime(fullPath);
|
|
if (mtime == null) continue;
|
|
if (latest == null || mtime > latest) {
|
|
latest = mtime;
|
|
}
|
|
}
|
|
}
|
|
return latest;
|
|
};
|
|
|
|
const shouldBuild = () => {
|
|
if (env.OPENCLAW_FORCE_BUILD === '1') return true;
|
|
const stampMtime = statMtime(buildStampPath);
|
|
if (stampMtime == null) return true;
|
|
if (statMtime(distEntry) == null) return true;
|
|
|
|
for (const filePath of configFiles) {
|
|
const mtime = statMtime(filePath);
|
|
if (mtime != null && mtime > stampMtime) return true;
|
|
}
|
|
|
|
const srcMtime = findLatestMtime(srcRoot, isExcludedSource);
|
|
if (srcMtime != null && srcMtime > stampMtime) return true;
|
|
return false;
|
|
};
|
|
|
|
const logRunner = (message) => {
|
|
if (env.OPENCLAW_RUNNER_LOG === '0') return;
|
|
process.stderr.write(`[openclaw] ${message}\n`);
|
|
};
|
|
|
|
const runNode = () => {
|
|
const nodeProcess = spawn(process.execPath, ['openclaw.mjs', ...args], {
|
|
cwd,
|
|
env,
|
|
stdio: 'inherit',
|
|
});
|
|
|
|
nodeProcess.on('exit', (exitCode, exitSignal) => {
|
|
if (exitSignal) {
|
|
process.exit(1);
|
|
}
|
|
process.exit(exitCode ?? 1);
|
|
});
|
|
};
|
|
|
|
const writeBuildStamp = () => {
|
|
try {
|
|
fs.mkdirSync(distRoot, { recursive: true });
|
|
fs.writeFileSync(buildStampPath, `${Date.now()}\n`);
|
|
} catch (error) {
|
|
// Best-effort stamp; still allow the runner to start.
|
|
logRunner(
|
|
`Failed to write build stamp: ${error?.message ?? 'unknown error'}`,
|
|
);
|
|
}
|
|
};
|
|
|
|
if (!shouldBuild()) {
|
|
runNode();
|
|
} else {
|
|
logRunner('Building TypeScript (dist is stale).');
|
|
const pnpmArgs = ['exec', compiler, ...projectArgs];
|
|
const buildCmd = process.platform === 'win32' ? 'cmd.exe' : 'pnpm';
|
|
const buildArgs =
|
|
process.platform === 'win32'
|
|
? ['/d', '/s', '/c', 'pnpm', ...pnpmArgs]
|
|
: pnpmArgs;
|
|
const build = spawn(buildCmd, buildArgs, {
|
|
cwd,
|
|
env,
|
|
stdio: 'inherit',
|
|
});
|
|
|
|
build.on('exit', (code, signal) => {
|
|
if (signal) {
|
|
process.exit(1);
|
|
}
|
|
if (code !== 0 && code !== null) {
|
|
process.exit(code);
|
|
}
|
|
writeBuildStamp();
|
|
runNode();
|
|
});
|
|
}
|