revert: Switch back to tsc for compiling.

This commit is contained in:
cpojer
2026-01-31 18:31:49 +09:00
parent e25fedf932
commit 76361ae3ab
36 changed files with 527 additions and 843 deletions

View File

@@ -31,7 +31,7 @@ echo "Starting gateway container..."
-e "OPENCLAW_SKIP_CRON=1" \
-e "OPENCLAW_SKIP_CANVAS_HOST=1" \
"$IMAGE_NAME" \
bash -lc "node dist/index.mjs gateway --port $PORT --bind lan --allow-unconfigured > /tmp/gateway-net-e2e.log 2>&1"
bash -lc "node dist/index.js gateway --port $PORT --bind lan --allow-unconfigured > /tmp/gateway-net-e2e.log 2>&1"
echo "Waiting for gateway to come up..."
for _ in $(seq 1 20); do

View File

@@ -83,7 +83,7 @@ TRASH
}
start_gateway() {
node dist/index.mjs gateway --port 18789 --bind loopback --allow-unconfigured > /tmp/gateway-e2e.log 2>&1 &
node dist/index.js gateway --port 18789 --bind loopback --allow-unconfigured > /tmp/gateway-e2e.log 2>&1 &
GATEWAY_PID="$!"
}
@@ -185,7 +185,7 @@ TRASH
local validate_fn="${4:-}"
# Default onboarding command wrapper.
run_wizard_cmd "$case_name" "$home_dir" "node dist/index.mjs onboard $ONBOARD_FLAGS" "$send_fn" true "$validate_fn"
run_wizard_cmd "$case_name" "$home_dir" "node dist/index.js onboard $ONBOARD_FLAGS" "$send_fn" true "$validate_fn"
}
make_home() {
@@ -268,7 +268,7 @@ TRASH
home_dir="$(make_home local-basic)"
export HOME="$home_dir"
mkdir -p "$HOME"
node dist/index.mjs onboard \
node dist/index.js onboard \
--non-interactive \
--accept-risk \
--flow quickstart \
@@ -345,7 +345,7 @@ NODE
export HOME="$home_dir"
mkdir -p "$HOME"
# Smoke test non-interactive remote config write.
node dist/index.mjs onboard --non-interactive --accept-risk \
node dist/index.js onboard --non-interactive --accept-risk \
--mode remote \
--remote-url ws://gateway.local:18789 \
--remote-token remote-token \
@@ -398,7 +398,7 @@ NODE
}
JSON
node dist/index.mjs onboard \
node dist/index.js onboard \
--non-interactive \
--accept-risk \
--flow quickstart \
@@ -441,7 +441,7 @@ NODE
local home_dir
home_dir="$(make_home channels)"
# Channels-only configure flow.
run_wizard_cmd channels "$home_dir" "node dist/index.mjs configure --section channels" send_channels_flow
run_wizard_cmd channels "$home_dir" "node dist/index.js configure --section channels" send_channels_flow
config_path="$HOME/.openclaw/openclaw.json"
assert_file "$config_path"
@@ -492,7 +492,7 @@ NODE
}
JSON
run_wizard_cmd skills "$home_dir" "node dist/index.mjs configure --section skills" send_skills_flow
run_wizard_cmd skills "$home_dir" "node dist/index.js configure --section skills" send_skills_flow
config_path="$HOME/.openclaw/openclaw.json"
assert_file "$config_path"

View File

@@ -29,7 +29,7 @@ module.exports = {
};
JS
node dist/index.mjs plugins list --json > /tmp/plugins.json
node dist/index.js plugins list --json > /tmp/plugins.json
node - <<'"'"'NODE'"'"'
const fs = require("node:fs");
@@ -81,8 +81,8 @@ module.exports = {
JS
tar -czf /tmp/demo-plugin-tgz.tgz -C "$pack_dir" package
node dist/index.mjs plugins install /tmp/demo-plugin-tgz.tgz
node dist/index.mjs plugins list --json > /tmp/plugins2.json
node dist/index.js plugins install /tmp/demo-plugin-tgz.tgz
node dist/index.js plugins list --json > /tmp/plugins2.json
node - <<'"'"'NODE'"'"'
const fs = require("node:fs");
@@ -118,8 +118,8 @@ module.exports = {
};
JS
node dist/index.mjs plugins install "$dir_plugin"
node dist/index.mjs plugins list --json > /tmp/plugins3.json
node dist/index.js plugins install "$dir_plugin"
node dist/index.js plugins list --json > /tmp/plugins3.json
node - <<'"'"'NODE'"'"'
const fs = require("node:fs");
@@ -156,8 +156,8 @@ module.exports = {
};
JS
node dist/index.mjs plugins install "file:$file_pack_dir/package"
node dist/index.mjs plugins list --json > /tmp/plugins4.json
node dist/index.js plugins install "file:$file_pack_dir/package"
node dist/index.js plugins list --json > /tmp/plugins4.json
node - <<'"'"'NODE'"'"'
const fs = require("node:fs");

View File

@@ -110,8 +110,8 @@ merge_framework_machos() {
echo "📦 Ensuring deps (pnpm install)"
(cd "$ROOT_DIR" && pnpm install --no-frozen-lockfile --config.node-linker=hoisted)
if [[ "${SKIP_TSC:-0}" != "1" ]]; then
echo "📦 Building JS (pnpm tsdown)"
(cd "$ROOT_DIR" && pnpm tsdown)
echo "📦 Building JS (pnpm tsc)"
(cd "$ROOT_DIR" && pnpm tsc -p tsconfig.json --noEmit false)
else
echo "📦 Skipping TS build (SKIP_TSC=1)"
fi

View File

@@ -1,34 +1,36 @@
import fs from "node:fs";
import path from "node:path";
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
import { setupGitHooks } from "./setup-git-hooks.js";
import fs from 'node:fs';
import path from 'node:path';
import { spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { setupGitHooks } from './setup-git-hooks.js';
function detectPackageManager(ua = process.env.npm_config_user_agent ?? "") {
function detectPackageManager(ua = process.env.npm_config_user_agent ?? '') {
// Examples:
// - "pnpm/10.23.0 npm/? node/v22.21.1 darwin arm64"
// - "npm/10.9.4 node/v22.12.0 linux x64"
// - "bun/1.2.2"
const normalized = String(ua).trim();
if (normalized.startsWith("pnpm/")) return "pnpm";
if (normalized.startsWith("bun/")) return "bun";
if (normalized.startsWith("npm/")) return "npm";
if (normalized.startsWith("yarn/")) return "yarn";
return "unknown";
if (normalized.startsWith('pnpm/')) return 'pnpm';
if (normalized.startsWith('bun/')) return 'bun';
if (normalized.startsWith('npm/')) return 'npm';
if (normalized.startsWith('yarn/')) return 'yarn';
return 'unknown';
}
function shouldApplyPnpmPatchedDependenciesFallback(pm = detectPackageManager()) {
function shouldApplyPnpmPatchedDependenciesFallback(
pm = detectPackageManager(),
) {
// pnpm already applies pnpm.patchedDependencies itself; re-applying would fail.
return pm !== "pnpm";
return pm !== 'pnpm';
}
function getRepoRoot() {
const here = path.dirname(fileURLToPath(import.meta.url));
return path.resolve(here, "..");
return path.resolve(here, '..');
}
function ensureExecutable(targetPath) {
if (process.platform === "win32") return;
if (process.platform === 'win32') return;
if (!fs.existsSync(targetPath)) return;
try {
const mode = fs.statSync(targetPath).mode & 0o777;
@@ -40,29 +42,32 @@ function ensureExecutable(targetPath) {
}
function hasGit(repoRoot) {
const result = spawnSync("git", ["--version"], { cwd: repoRoot, stdio: "ignore" });
const result = spawnSync('git', ['--version'], {
cwd: repoRoot,
stdio: 'ignore',
});
return result.status === 0;
}
function extractPackageName(key) {
if (key.startsWith("@")) {
const idx = key.indexOf("@", 1);
if (key.startsWith('@')) {
const idx = key.indexOf('@', 1);
if (idx === -1) return key;
return key.slice(0, idx);
}
const idx = key.lastIndexOf("@");
const idx = key.lastIndexOf('@');
if (idx <= 0) return key;
return key.slice(0, idx);
}
function stripPrefix(p) {
if (p.startsWith("a/") || p.startsWith("b/")) return p.slice(2);
if (p.startsWith('a/') || p.startsWith('b/')) return p.slice(2);
return p;
}
function parseRange(segment) {
// segment: "-12,5" or "+7"
const [startRaw, countRaw] = segment.slice(1).split(",");
const [startRaw, countRaw] = segment.slice(1).split(',');
const start = Number.parseInt(startRaw, 10);
const count = countRaw ? Number.parseInt(countRaw, 10) : 1;
if (Number.isNaN(start) || Number.isNaN(count)) {
@@ -72,12 +77,12 @@ function parseRange(segment) {
}
function parsePatch(patchText) {
const lines = patchText.split("\n");
const lines = patchText.split('\n');
const files = [];
let i = 0;
while (i < lines.length) {
if (!lines[i].startsWith("diff --git ")) {
if (!lines[i].startsWith('diff --git ')) {
i += 1;
continue;
}
@@ -86,20 +91,22 @@ function parsePatch(patchText) {
i += 1;
// Skip index line(s)
while (i < lines.length && lines[i].startsWith("index ")) i += 1;
while (i < lines.length && lines[i].startsWith('index ')) i += 1;
if (i < lines.length && lines[i].startsWith("--- ")) {
if (i < lines.length && lines[i].startsWith('--- ')) {
file.oldPath = stripPrefix(lines[i].slice(4).trim());
i += 1;
}
if (i < lines.length && lines[i].startsWith("+++ ")) {
if (i < lines.length && lines[i].startsWith('+++ ')) {
file.newPath = stripPrefix(lines[i].slice(4).trim());
i += 1;
}
while (i < lines.length && lines[i].startsWith("@@")) {
while (i < lines.length && lines[i].startsWith('@@')) {
const header = lines[i];
const match = /^@@\s+(-\d+(?:,\d+)?)\s+(\+\d+(?:,\d+)?)\s+@@/.exec(header);
const match = /^@@\s+(-\d+(?:,\d+)?)\s+(\+\d+(?:,\d+)?)\s+@@/.exec(
header,
);
if (!match) throw new Error(`invalid hunk header: ${header}`);
const oldRange = parseRange(match[1]);
const newRange = parseRange(match[2]);
@@ -108,12 +115,12 @@ function parsePatch(patchText) {
const hunkLines = [];
while (i < lines.length) {
const line = lines[i];
if (line.startsWith("@@") || line.startsWith("diff --git ")) break;
if (line === "") {
if (line.startsWith('@@') || line.startsWith('diff --git ')) break;
if (line === '') {
i += 1;
continue;
}
if (line.startsWith("\\ No newline at end of file")) {
if (line.startsWith('\\ No newline at end of file')) {
i += 1;
continue;
}
@@ -142,16 +149,16 @@ function readFileLines(targetPath) {
if (!fs.existsSync(targetPath)) {
throw new Error(`target file missing: ${targetPath}`);
}
const raw = fs.readFileSync(targetPath, "utf-8");
const hasTrailingNewline = raw.endsWith("\n");
const parts = raw.split("\n");
const raw = fs.readFileSync(targetPath, 'utf-8');
const hasTrailingNewline = raw.endsWith('\n');
const parts = raw.split('\n');
if (hasTrailingNewline) parts.pop();
return { lines: parts, hasTrailingNewline };
}
function writeFileLines(targetPath, lines, hadTrailingNewline) {
const content = lines.join("\n") + (hadTrailingNewline ? "\n" : "");
fs.writeFileSync(targetPath, content, "utf-8");
const content = lines.join('\n') + (hadTrailingNewline ? '\n' : '');
fs.writeFileSync(targetPath, content, 'utf-8');
}
function applyHunk(lines, hunk, offset) {
@@ -159,7 +166,7 @@ function applyHunk(lines, hunk, offset) {
const expected = [];
for (const raw of hunk.lines) {
const marker = raw[0];
if (marker === " " || marker === "+") {
if (marker === ' ' || marker === '+') {
expected.push(raw.slice(1));
}
}
@@ -180,21 +187,21 @@ function applyHunk(lines, hunk, offset) {
for (const raw of hunk.lines) {
const marker = raw[0];
const text = raw.slice(1);
if (marker === " ") {
if (marker === ' ') {
if (lines[cursor] !== text) {
throw new Error(
`context mismatch at line ${cursor + 1}: expected "${text}", found "${lines[cursor] ?? "<eof>"}"`,
`context mismatch at line ${cursor + 1}: expected "${text}", found "${lines[cursor] ?? '<eof>'}"`,
);
}
cursor += 1;
} else if (marker === "-") {
} else if (marker === '-') {
if (lines[cursor] !== text) {
throw new Error(
`delete mismatch at line ${cursor + 1}: expected "${text}", found "${lines[cursor] ?? "<eof>"}"`,
`delete mismatch at line ${cursor + 1}: expected "${text}", found "${lines[cursor] ?? '<eof>'}"`,
);
}
lines.splice(cursor, 1);
} else if (marker === "+") {
} else if (marker === '+') {
lines.splice(cursor, 0, text);
cursor += 1;
} else {
@@ -207,11 +214,11 @@ function applyHunk(lines, hunk, offset) {
}
function applyPatchToFile(targetDir, filePatch) {
if (filePatch.newPath === "/dev/null") {
if (filePatch.newPath === '/dev/null') {
// deletion not needed for our patches
return;
}
const relPath = stripPrefix(filePatch.newPath ?? filePatch.oldPath ?? "");
const relPath = stripPrefix(filePatch.newPath ?? filePatch.oldPath ?? '');
const targetPath = path.join(targetDir, relPath);
const { lines, hasTrailingNewline } = readFileLines(targetPath);
@@ -225,7 +232,10 @@ function applyPatchToFile(targetDir, filePatch) {
function applyPatchSet({ patchText, targetDir }) {
let resolvedTarget = path.resolve(targetDir);
if (!fs.existsSync(resolvedTarget) || !fs.statSync(resolvedTarget).isDirectory()) {
if (
!fs.existsSync(resolvedTarget) ||
!fs.statSync(resolvedTarget).isDirectory()
) {
console.warn(`[postinstall] skip missing target: ${resolvedTarget}`);
return;
}
@@ -244,28 +254,28 @@ function applyPatchFile({ patchPath, targetDir }) {
if (!fs.existsSync(absPatchPath)) {
throw new Error(`missing patch: ${absPatchPath}`);
}
const patchText = fs.readFileSync(absPatchPath, "utf-8");
const patchText = fs.readFileSync(absPatchPath, 'utf-8');
applyPatchSet({ patchText, targetDir });
}
function trySetupCompletion(repoRoot) {
// Skip in CI or if explicitly disabled
if (process.env.CI || process.env.OPENCLAW_SKIP_COMPLETION_SETUP) return;
const binPath = path.join(repoRoot, "openclaw.mjs");
const binPath = path.join(repoRoot, 'openclaw.mjs');
if (!fs.existsSync(binPath)) return;
// In development, dist might not exist yet during postinstall
const distEntry = path.join(repoRoot, "dist", "index.js");
const distEntry = path.join(repoRoot, 'dist', 'index.js');
if (!fs.existsSync(distEntry)) return;
try {
// Run with OPENCLAW_SKIP_POSTINSTALL to avoid any weird recursion,
// though distinct from this script.
spawnSync(process.execPath, [binPath, "completion", "--install", "--yes"], {
spawnSync(process.execPath, [binPath, 'completion', '--install', '--yes'], {
cwd: repoRoot,
stdio: "inherit",
env: { ...process.env, OPENCLAW_SKIP_POSTINSTALL: "1" },
stdio: 'inherit',
env: { ...process.env, OPENCLAW_SKIP_POSTINSTALL: '1' },
});
} catch (err) {
// Ignore errors to not break install
@@ -276,7 +286,7 @@ function main() {
const repoRoot = getRepoRoot();
process.chdir(repoRoot);
ensureExecutable(path.join(repoRoot, "dist", "entry.mjs"));
ensureExecutable(path.join(repoRoot, 'dist', '/entry.js'));
setupGitHooks({ repoRoot });
trySetupCompletion(repoRoot);
@@ -284,18 +294,18 @@ function main() {
return;
}
const pkgPath = path.join(repoRoot, "package.json");
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
const pkgPath = path.join(repoRoot, 'package.json');
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
const patched = pkg?.pnpm?.patchedDependencies ?? {};
// Bun does not support pnpm.patchedDependencies. Apply these patch files to
// node_modules packages as a best-effort compatibility layer.
for (const [key, relPatchPath] of Object.entries(patched)) {
if (typeof relPatchPath !== "string" || !relPatchPath.trim()) continue;
if (typeof relPatchPath !== 'string' || !relPatchPath.trim()) continue;
const pkgName = extractPackageName(String(key));
if (!pkgName) continue;
applyPatchFile({
targetDir: path.join("node_modules", ...pkgName.split("/")),
targetDir: path.join('node_modules', ...pkgName.split('/')),
patchPath: relPatchPath,
});
}
@@ -303,10 +313,10 @@ function main() {
try {
const skip =
process.env.OPENCLAW_SKIP_POSTINSTALL === "1" ||
process.env.CLAWDBOT_SKIP_POSTINSTALL === "1" ||
process.env.VITEST === "true" ||
process.env.NODE_ENV === "test";
process.env.OPENCLAW_SKIP_POSTINSTALL === '1' ||
process.env.CLAWDBOT_SKIP_POSTINSTALL === '1' ||
process.env.VITEST === 'true' ||
process.env.NODE_ENV === 'test';
if (!skip) {
main();

View File

@@ -1,21 +1,24 @@
#!/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";
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 compiler = compilerOverride === 'tsc' ? 'tsc' : 'tsgo';
const projectArgs = ['--project', 'tsconfig.json'];
const distRoot = path.join(cwd, "dist");
const distEntry = path.join(distRoot, "entry.mjs");
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 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 {
@@ -27,10 +30,10 @@ const statMtime = (filePath) => {
const isExcludedSource = (filePath) => {
const relativePath = path.relative(srcRoot, filePath);
if (relativePath.startsWith("..")) return false;
if (relativePath.startsWith('..')) return false;
return (
relativePath.endsWith(".test.ts") ||
relativePath.endsWith(".test.tsx") ||
relativePath.endsWith('.test.ts') ||
relativePath.endsWith('.test.tsx') ||
relativePath.endsWith(`test-helpers.ts`)
);
};
@@ -66,7 +69,7 @@ const findLatestMtime = (dirPath, shouldSkip) => {
};
const shouldBuild = () => {
if (env.OPENCLAW_FORCE_BUILD === "1") return true;
if (env.OPENCLAW_FORCE_BUILD === '1') return true;
const stampMtime = statMtime(buildStampPath);
if (stampMtime == null) return true;
if (statMtime(distEntry) == null) return true;
@@ -82,18 +85,18 @@ const shouldBuild = () => {
};
const logRunner = (message) => {
if (env.OPENCLAW_RUNNER_LOG === "0") return;
if (env.OPENCLAW_RUNNER_LOG === '0') return;
process.stderr.write(`[openclaw] ${message}\n`);
};
const runNode = () => {
const nodeProcess = spawn(process.execPath, ["openclaw.mjs", ...args], {
const nodeProcess = spawn(process.execPath, ['openclaw.mjs', ...args], {
cwd,
env,
stdio: "inherit",
stdio: 'inherit',
});
nodeProcess.on("exit", (exitCode, exitSignal) => {
nodeProcess.on('exit', (exitCode, exitSignal) => {
if (exitSignal) {
process.exit(1);
}
@@ -107,25 +110,29 @@ const writeBuildStamp = () => {
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"}`);
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";
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;
process.platform === 'win32'
? ['/d', '/s', '/c', 'pnpm', ...pnpmArgs]
: pnpmArgs;
const build = spawn(buildCmd, buildArgs, {
cwd,
env,
stdio: "inherit",
stdio: 'inherit',
});
build.on("exit", (code, signal) => {
build.on('exit', (code, signal) => {
if (signal) {
process.exit(1);
}

View File

@@ -16,7 +16,7 @@ if (initialBuild.status !== 0) {
process.exit(initialBuild.status ?? 1);
}
const compilerProcess = spawn("pnpm", ["tsdown", '--watch', 'src/'], {
const compilerProcess = spawn("pnpm", ["tsc", '-p', 'tsconfig.json', '--noEmit', 'false', '--watch'], {
cwd,
env,
stdio: "inherit",