diff --git a/package.json b/package.json index 9c1f63e00e5..a3d0b896a0a 100644 --- a/package.json +++ b/package.json @@ -223,9 +223,9 @@ "android:run": "cd apps/android && ./gradlew :app:installDebug && adb shell am start -n ai.openclaw.app/.MainActivity", "android:test": "cd apps/android && ./gradlew :app:testDebugUnitTest", "android:test:integration": "OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_ANDROID_NODE=1 vitest run --config vitest.live.config.ts src/gateway/android-node.capabilities.live.test.ts", - "build": "pnpm canvas:a2ui:bundle && tsdown && node scripts/copy-plugin-sdk-root-alias.mjs && pnpm build:plugin-sdk:dts && node --import tsx scripts/write-plugin-sdk-entry-dts.ts && node --import tsx scripts/canvas-a2ui-copy.ts && node --import tsx scripts/copy-hook-metadata.ts && node --import tsx scripts/copy-export-html-templates.ts && node --import tsx scripts/write-build-info.ts && node --import tsx scripts/write-cli-startup-metadata.ts && node --import tsx scripts/write-cli-compat.ts", + "build": "pnpm canvas:a2ui:bundle && node scripts/tsdown-build.mjs && node scripts/copy-plugin-sdk-root-alias.mjs && pnpm build:plugin-sdk:dts && node --import tsx scripts/write-plugin-sdk-entry-dts.ts && node --import tsx scripts/canvas-a2ui-copy.ts && node --import tsx scripts/copy-hook-metadata.ts && node --import tsx scripts/copy-export-html-templates.ts && node --import tsx scripts/write-build-info.ts && node --import tsx scripts/write-cli-startup-metadata.ts && node --import tsx scripts/write-cli-compat.ts", "build:plugin-sdk:dts": "tsc -p tsconfig.plugin-sdk.dts.json", - "build:strict-smoke": "pnpm canvas:a2ui:bundle && tsdown && node scripts/copy-plugin-sdk-root-alias.mjs && pnpm build:plugin-sdk:dts", + "build:strict-smoke": "pnpm canvas:a2ui:bundle && node scripts/tsdown-build.mjs && node scripts/copy-plugin-sdk-root-alias.mjs && pnpm build:plugin-sdk:dts", "canvas:a2ui:bundle": "bash scripts/bundle-a2ui.sh", "check": "pnpm format:check && pnpm tsgo && pnpm lint && pnpm lint:tmp:no-random-messaging && pnpm lint:tmp:channel-agnostic-boundaries && pnpm lint:tmp:no-raw-channel-fetch && pnpm lint:agent:ingress-owner && pnpm lint:plugins:no-register-http-handler && pnpm lint:plugins:no-monolithic-plugin-sdk-entry-imports && pnpm lint:webhook:no-low-level-body-read && pnpm lint:auth:no-pairing-store-group && pnpm lint:auth:pairing-account-scope && pnpm check:host-env-policy:swift", "check:docs": "pnpm format:docs:check && pnpm lint:docs && pnpm docs:check-links", diff --git a/scripts/copy-export-html-templates.ts b/scripts/copy-export-html-templates.ts index 8f9c494d213..ea652adc96f 100644 --- a/scripts/copy-export-html-templates.ts +++ b/scripts/copy-export-html-templates.ts @@ -9,6 +9,7 @@ import { fileURLToPath } from "node:url"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const projectRoot = path.resolve(__dirname, ".."); +const verbose = process.env.OPENCLAW_BUILD_VERBOSE === "1"; const srcDir = path.join(projectRoot, "src", "auto-reply", "reply", "export-html"); const distDir = path.join(projectRoot, "dist", "export-html"); @@ -26,12 +27,16 @@ function copyExportHtmlTemplates() { // Copy main template files const templateFiles = ["template.html", "template.css", "template.js"]; + let copiedCount = 0; for (const file of templateFiles) { const srcFile = path.join(srcDir, file); const distFile = path.join(distDir, file); if (fs.existsSync(srcFile)) { fs.copyFileSync(srcFile, distFile); - console.log(`[copy-export-html-templates] Copied ${file}`); + copiedCount += 1; + if (verbose) { + console.log(`[copy-export-html-templates] Copied ${file}`); + } } } @@ -48,12 +53,15 @@ function copyExportHtmlTemplates() { const distFile = path.join(distVendor, file); if (fs.statSync(srcFile).isFile()) { fs.copyFileSync(srcFile, distFile); - console.log(`[copy-export-html-templates] Copied vendor/${file}`); + copiedCount += 1; + if (verbose) { + console.log(`[copy-export-html-templates] Copied vendor/${file}`); + } } } } - console.log("[copy-export-html-templates] Done"); + console.log(`[copy-export-html-templates] Copied ${copiedCount} export-html assets.`); } copyExportHtmlTemplates(); diff --git a/scripts/copy-hook-metadata.ts b/scripts/copy-hook-metadata.ts index 737ed4a9d70..a63719812df 100644 --- a/scripts/copy-hook-metadata.ts +++ b/scripts/copy-hook-metadata.ts @@ -9,6 +9,7 @@ import { fileURLToPath } from "node:url"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const projectRoot = path.resolve(__dirname, ".."); +const verbose = process.env.OPENCLAW_BUILD_VERBOSE === "1"; const srcBundled = path.join(projectRoot, "src", "hooks", "bundled"); const distBundled = path.join(projectRoot, "dist", "bundled"); @@ -24,6 +25,7 @@ function copyHookMetadata() { } const entries = fs.readdirSync(srcBundled, { withFileTypes: true }); + let copiedCount = 0; for (const entry of entries) { if (!entry.isDirectory()) { @@ -46,10 +48,13 @@ function copyHookMetadata() { } fs.copyFileSync(srcHookMd, distHookMd); - console.log(`[copy-hook-metadata] Copied ${hookName}/HOOK.md`); + copiedCount += 1; + if (verbose) { + console.log(`[copy-hook-metadata] Copied ${hookName}/HOOK.md`); + } } - console.log("[copy-hook-metadata] Done"); + console.log(`[copy-hook-metadata] Copied ${copiedCount} hook metadata files.`); } copyHookMetadata(); diff --git a/scripts/tsdown-build.mjs b/scripts/tsdown-build.mjs new file mode 100644 index 00000000000..ccd56a4aff0 --- /dev/null +++ b/scripts/tsdown-build.mjs @@ -0,0 +1,19 @@ +#!/usr/bin/env node + +import { spawnSync } from "node:child_process"; + +const logLevel = process.env.OPENCLAW_BUILD_VERBOSE ? "info" : "warn"; +const result = spawnSync( + "pnpm", + ["exec", "tsdown", "--config-loader", "unrun", "--logLevel", logLevel], + { + stdio: "inherit", + shell: process.platform === "win32", + }, +); + +if (typeof result.status === "number") { + process.exit(result.status); +} + +process.exit(1); diff --git a/tsdown.config.ts b/tsdown.config.ts index b0c2d49c676..80833de2a14 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -4,6 +4,42 @@ const env = { NODE_ENV: "production", }; +function buildInputOptions(options: { onLog?: unknown; [key: string]: unknown }) { + if (process.env.OPENCLAW_BUILD_VERBOSE === "1") { + return undefined; + } + + const previousOnLog = typeof options.onLog === "function" ? options.onLog : undefined; + + return { + ...options, + onLog( + level: string, + log: { code?: string }, + defaultHandler: (level: string, log: { code?: string }) => void, + ) { + if (log.code === "PLUGIN_TIMINGS") { + return; + } + if (typeof previousOnLog === "function") { + previousOnLog(level, log, defaultHandler); + return; + } + defaultHandler(level, log); + }, + }; +} + +function nodeBuildConfig(config: Record) { + return { + ...config, + env, + fixedExtension: false, + platform: "node", + inputOptions: buildInputOptions, + }; +} + const pluginSdkEntrypoints = [ "index", "core", @@ -52,32 +88,20 @@ const pluginSdkEntrypoints = [ ] as const; export default defineConfig([ - { + nodeBuildConfig({ entry: "src/index.ts", - env, - fixedExtension: false, - platform: "node", - }, - { + }), + nodeBuildConfig({ entry: "src/entry.ts", - env, - fixedExtension: false, - platform: "node", - }, - { + }), + nodeBuildConfig({ // Ensure this module is bundled as an entry so legacy CLI shims can resolve its exports. entry: "src/cli/daemon-cli.ts", - env, - fixedExtension: false, - platform: "node", - }, - { + }), + nodeBuildConfig({ entry: "src/infra/warning-filter.ts", - env, - fixedExtension: false, - platform: "node", - }, - { + }), + nodeBuildConfig({ // Keep sync lazy-runtime channel modules as concrete dist files. entry: { "channels/plugins/agent-tools/whatsapp-login": @@ -91,27 +115,17 @@ export default defineConfig([ "line/send": "src/line/send.ts", "line/template-messages": "src/line/template-messages.ts", }, - env, - fixedExtension: false, - platform: "node", - }, - ...pluginSdkEntrypoints.map((entry) => ({ - entry: `src/plugin-sdk/${entry}.ts`, - outDir: "dist/plugin-sdk", - env, - fixedExtension: false, - platform: "node" as const, - })), - { + }), + ...pluginSdkEntrypoints.map((entry) => + nodeBuildConfig({ + entry: `src/plugin-sdk/${entry}.ts`, + outDir: "dist/plugin-sdk", + }), + ), + nodeBuildConfig({ entry: "src/extensionAPI.ts", - env, - fixedExtension: false, - platform: "node", - }, - { + }), + nodeBuildConfig({ entry: ["src/hooks/bundled/*/handler.ts", "src/hooks/llm-slug-generator.ts"], - env, - fixedExtension: false, - platform: "node", - }, + }), ]);