From 6e58da97504587eaa7e5bdb1d9a7799079dd1539 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 20 Apr 2026 17:24:01 +0100 Subject: [PATCH] build: stabilize a2ui bundle inputs --- scripts/bundle-a2ui.mjs | 33 +++++++------------------------ src/canvas-host/a2ui/.bundle.hash | 2 +- test/scripts/bundle-a2ui.test.ts | 33 +++++++++++-------------------- 3 files changed, 19 insertions(+), 49 deletions(-) diff --git a/scripts/bundle-a2ui.mjs b/scripts/bundle-a2ui.mjs index 096a56f3034..ffc9757cbec 100644 --- a/scripts/bundle-a2ui.mjs +++ b/scripts/bundle-a2ui.mjs @@ -2,7 +2,6 @@ import { spawnSync } from "node:child_process"; import { createHash } from "node:crypto"; -import { existsSync } from "node:fs"; import fs from "node:fs/promises"; import path from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; @@ -13,9 +12,10 @@ const hashFile = path.join(rootDir, "src", "canvas-host", "a2ui", ".bundle.hash" const outputFile = path.join(rootDir, "src", "canvas-host", "a2ui", "a2ui.bundle.js"); const a2uiRendererDir = path.join(rootDir, "vendor", "a2ui", "renderers", "lit"); const a2uiAppDir = path.join(rootDir, "apps", "shared", "OpenClawKit", "Tools", "CanvasA2UI"); +const rootPackageFile = path.join(rootDir, "package.json"); +const pnpmLockFile = path.join(rootDir, "pnpm-lock.yaml"); const uiPackageFile = path.join(rootDir, "ui", "package.json"); -const bundleDependencyIds = ["lit", "@lit/context", "@lit-labs/signals", "signal-utils"]; -const repoInputPaths = [uiPackageFile, a2uiRendererDir, a2uiAppDir]; +const repoInputPaths = [rootPackageFile, pnpmLockFile, uiPackageFile, a2uiRendererDir, a2uiAppDir]; const ignoredBundleHashInputPrefixes = ["vendor/a2ui/renderers/lit/dist"]; const relativeRepoInputPaths = repoInputPaths.map((inputPath) => normalizePath(path.relative(rootDir, inputPath)), @@ -67,34 +67,16 @@ export function getLocalRolldownCliCandidates(repoRoot = rootDir) { export function getBundleHashRepoInputPaths(repoRoot = rootDir) { return [ + path.join(repoRoot, "package.json"), + path.join(repoRoot, "pnpm-lock.yaml"), path.join(repoRoot, "ui", "package.json"), path.join(repoRoot, "vendor", "a2ui", "renderers", "lit"), path.join(repoRoot, "apps", "shared", "OpenClawKit", "Tools", "CanvasA2UI"), ]; } -export function getResolvedBundleDependencyPackageJsonPaths(repoRoot = rootDir) { - const uiNodeModules = path.join(repoRoot, "ui", "node_modules"); - const repoNodeModules = path.join(repoRoot, "node_modules"); - const paths = []; - for (const dependencyId of bundleDependencyIds) { - const candidates = [ - path.join(uiNodeModules, dependencyId, "package.json"), - path.join(repoNodeModules, dependencyId, "package.json"), - ]; - const match = candidates.find((candidate) => existsSync(candidate)); - if (match) { - paths.push(match); - } - } - return [...new Set(paths)]; -} - export function getBundleHashInputPaths(repoRoot = rootDir) { - return [ - ...getBundleHashRepoInputPaths(repoRoot), - ...getResolvedBundleDependencyPackageJsonPaths(repoRoot), - ]; + return getBundleHashRepoInputPaths(repoRoot); } export function compareNormalizedPaths(left, right) { @@ -138,7 +120,7 @@ function listTrackedInputFiles() { .filter(Boolean) .map((filePath) => path.join(rootDir, filePath)) .filter((filePath) => isBundleHashInputPath(filePath)); - return [...trackedFiles, ...getResolvedBundleDependencyPackageJsonPaths(rootDir)]; + return trackedFiles; } async function computeHash() { @@ -148,7 +130,6 @@ async function computeHash() { for (const inputPath of getBundleHashRepoInputPaths(rootDir)) { await walkFiles(inputPath, files); } - files.push(...getResolvedBundleDependencyPackageJsonPaths(rootDir)); } files = [...new Set(files)].toSorted(compareNormalizedPaths); diff --git a/src/canvas-host/a2ui/.bundle.hash b/src/canvas-host/a2ui/.bundle.hash index 67b139008a3..8cda681955a 100644 --- a/src/canvas-host/a2ui/.bundle.hash +++ b/src/canvas-host/a2ui/.bundle.hash @@ -1 +1 @@ -7d425e150815426138e00903b7553c28742a2f696ff7f608ee0047f21b2f7fe5 +445aaac0723949e8cee66e9bfa82ba789531c2cf3990e74a240939bc49e5933f diff --git a/test/scripts/bundle-a2ui.test.ts b/test/scripts/bundle-a2ui.test.ts index 6abfa705e8c..cd64197de87 100644 --- a/test/scripts/bundle-a2ui.test.ts +++ b/test/scripts/bundle-a2ui.test.ts @@ -5,7 +5,6 @@ import { getBundleHashInputPaths, getBundleHashRepoInputPaths, getLocalRolldownCliCandidates, - getResolvedBundleDependencyPackageJsonPaths, isBundleHashInputPath, } from "../../scripts/bundle-a2ui.mjs"; @@ -52,34 +51,24 @@ describe("scripts/bundle-a2ui.mjs", () => { ]); }); - it("keeps repo-root package churn out of bundle hash inputs", () => { + it("tracks repo dependency manifests through lockfile inputs", () => { const repoRoot = path.resolve("repo-root"); const inputPaths = getBundleHashRepoInputPaths(repoRoot); + expect(inputPaths).toContain(path.join(repoRoot, "package.json")); + expect(inputPaths).toContain(path.join(repoRoot, "pnpm-lock.yaml")); expect(inputPaths).toContain(path.join(repoRoot, "ui", "package.json")); - expect(inputPaths).not.toContain(path.join(repoRoot, "package.json")); - expect(inputPaths).not.toContain(path.join(repoRoot, "pnpm-lock.yaml")); }); - it("tracks only the resolved bundle dependency manifests from node_modules", () => { + it("keeps local node_modules state out of bundle hash inputs", () => { const repoRoot = process.cwd(); - const dependencyPaths = getResolvedBundleDependencyPackageJsonPaths(repoRoot); - const relativeDependencyPaths = dependencyPaths.map((dependencyPath) => - path.relative(repoRoot, dependencyPath).replaceAll(path.sep, "/"), - ); + const inputPaths = getBundleHashInputPaths(repoRoot); - expect( - relativeDependencyPaths.map((relativePath) => relativePath.replace(/^ui\//u, "")), - ).toEqual([ - path.posix.join("node_modules", "lit", "package.json"), - path.posix.join("node_modules", "@lit/context", "package.json"), - path.posix.join("node_modules", "@lit-labs/signals", "package.json"), - path.posix.join("node_modules", "signal-utils", "package.json"), - ]); - expect( - relativeDependencyPaths.every((relativePath) => /^(ui\/)?node_modules\//u.test(relativePath)), - ).toBe(true); - expect(getBundleHashInputPaths(repoRoot)).not.toContain(path.join(repoRoot, "package.json")); - expect(getBundleHashInputPaths(repoRoot)).not.toContain(path.join(repoRoot, "pnpm-lock.yaml")); + expect(inputPaths).toContain(path.join(repoRoot, "package.json")); + expect(inputPaths).toContain(path.join(repoRoot, "pnpm-lock.yaml")); + expect(inputPaths).not.toContain(path.join(repoRoot, "node_modules", "lit", "package.json")); + expect(inputPaths).not.toContain( + path.join(repoRoot, "ui", "node_modules", "lit", "package.json"), + ); }); });