mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(scripts): include ui:build in build-all full and ciArtifacts profiles (#86010)
* fix(scripts): include ui:build in build-all full and ciArtifacts profiles Closes #85206. scripts/build-all.mjs only ran ui:build via a separate `pnpm ui:build` command. Because `pnpm build` invokes tsdown which removes `dist/`, a backend rebuild silently deletes any previously generated dist/control-ui assets, leaving the gateway to serve the "Control UI assets not found" message at startup. Documentation and startup auto-repair masked the bug at the worst possible time (LaunchAgent readiness / remote recovery) instead of guaranteeing the build artifact contract. This change adds ui:build as a build-all step after copy-export-html-templates and before write-build-info, and includes it in the full and ciArtifacts profiles. Minimal backend dev profiles (gatewayWatch, cliStartup) keep their existing fast-loop step lists and do not run ui:build. Regression coverage: - ciArtifacts step list assertion updated to match the new ordering. - Three new resolveBuildAllSteps assertions: ui:build is in full and ciArtifacts and runs after tsdown/runtime-postbuild-stamp and before write-build-info; ui:build is excluded from gatewayWatch/cliStartup; ui:build cache outputs declare dist/control-ui. * fix(scripts): leave ui:build uncached so dist/control-ui never restores stale build IDs ClawSweeper review on #86010 flagged that the original ui:build cache only hashed ui/, scripts/ui.js, and scripts/lib/copy-assets.ts, but ui/vite.config.ts also reads package.json plus git HEAD and the OPENCLAW_CONTROL_UI_BUILD_ID/OPENCLAW_VERSION env vars to embed a build ID into the app and service worker. A file-input cache signature cannot exactly invalidate those metadata sources, so a warm build-all hit could restore a previously generated dist/control-ui after tsdown clears dist and ship stale service-worker/app cache metadata. Leaving the step uncached keeps the contract simple: every pnpm build re-runs Vite, which is fast for the Control UI bundle and matches the existing behavior of every other un-cached build-all step. Backend-only profiles (gatewayWatch, cliStartup) are still unchanged. Tests: - Updated the ui:build cache assertion to require step.cache to be undefined and explain the metadata-input reason. - Existing presence/order/exclusion assertions for ui:build are unchanged and still cover the full and ciArtifacts profile contract. * fix(scripts): keep ui build fallback pnpm-free --------- Co-authored-by: 1052326311 <1052326311@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
+1
-2
@@ -7,7 +7,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Changes
|
||||
|
||||
- Control UI: add an ephemeral Activity tab for sanitized live tool activity summaries without persisting raw telemetry. Fixes #12831. Thanks @BunsDev.
|
||||
|
||||
- Build: include `ui:build` in the `full` and `ciArtifacts` profiles of `scripts/build-all.mjs` so `pnpm build` always rebuilds `dist/control-ui` after `tsdown` cleans `dist`, removing the second-command requirement and the missing-asset failure mode for source/runtime installs and CI artifact uploads. (#85206)
|
||||
### Fixes
|
||||
|
||||
- WebChat: keep message-tool replies visible in the chat while still summarizing internal tool results for the model. Fixes #86347. Thanks @shakkernerd.
|
||||
@@ -76,7 +76,6 @@ Docs: https://docs.openclaw.ai
|
||||
- Tests: fail Docker resource-ceiling checks when stats samples or configured limits are invalid instead of silently reporting zero peaks.
|
||||
- Agents: fail closed when provider-less session models match multiple provider-prefixed runtime policies so CLI runtime routing no longer depends on config order. (#85970) Thanks @potterdigital.
|
||||
- Control UI/agents: keep collapsed tool rows readable without early ellipses, preserve raw expanded tool details, and make post-compaction AGENTS.md reinjection opt-in to avoid duplicated project context. Fixes #45649 and #45488. Thanks @BunsDev.
|
||||
|
||||
## 2026.5.24
|
||||
|
||||
### Changes
|
||||
|
||||
@@ -17,6 +17,7 @@ const PNPM_STEP_NODE_FALLBACKS = new Map([
|
||||
["scripts/run-tsgo.mjs", "-p", "tsconfig.plugin-sdk.dts.json", "--declaration", "true"],
|
||||
],
|
||||
["plugins:assets:copy", ["scripts/bundled-plugin-assets.mjs", "--phase", "copy"]],
|
||||
["ui:build", ["scripts/ui.js", "build"]],
|
||||
]);
|
||||
export const BUILD_ALL_STEPS = [
|
||||
{ label: "plugins:assets:build", kind: "pnpm", pnpmArgs: ["plugins:assets:build"] },
|
||||
@@ -84,6 +85,16 @@ export const BUILD_ALL_STEPS = [
|
||||
outputs: ["dist/export-html"],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "ui:build",
|
||||
kind: "pnpm",
|
||||
pnpmArgs: ["ui:build"],
|
||||
// No build-all cache: ui/vite.config.ts derives the Control UI build ID
|
||||
// from package.json, git HEAD, and OPENCLAW_CONTROL_UI_BUILD_ID env, so a
|
||||
// file-input signature cannot exactly invalidate generated assets and a
|
||||
// warm hit could restore stale service-worker/app cache metadata.
|
||||
cache: undefined,
|
||||
},
|
||||
{
|
||||
label: "write-build-info",
|
||||
kind: "node",
|
||||
@@ -116,6 +127,7 @@ export const BUILD_ALL_PROFILES = {
|
||||
"plugins:assets:copy",
|
||||
"copy-hook-metadata",
|
||||
"copy-export-html-templates",
|
||||
"ui:build",
|
||||
"write-build-info",
|
||||
"write-cli-startup-metadata",
|
||||
"write-cli-compat",
|
||||
|
||||
+11
-19
@@ -168,42 +168,34 @@ export function main(argv = process.argv.slice(2)) {
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
const runner = resolveRunner();
|
||||
if (!runner) {
|
||||
process.stderr.write("Missing UI runner: install pnpm, then retry.\n");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const script = resolveScriptAction(action);
|
||||
if (action !== "install" && !script) {
|
||||
usage();
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
if (process.env.OPENCLAW_BUILD_ALL_NO_PNPM === "1" && action === "build") {
|
||||
run(process.execPath, [path.join(repoRoot, "node_modules/vite/bin/vite.js"), "build", ...rest]);
|
||||
return;
|
||||
}
|
||||
|
||||
const runner = resolveRunner();
|
||||
if (!runner) {
|
||||
process.stderr.write("Missing UI runner: install pnpm, then retry.\n");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (action === "install") {
|
||||
run(runner.cmd, ["install", ...rest]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!depsInstalled(action === "test" ? "test" : "build")) {
|
||||
if (process.env.OPENCLAW_BUILD_ALL_NO_PNPM === "1" && action === "build") {
|
||||
run(process.execPath, [
|
||||
path.join(repoRoot, "node_modules/vite/bin/vite.js"),
|
||||
"build",
|
||||
...rest,
|
||||
]);
|
||||
return;
|
||||
}
|
||||
const installEnv = process.env;
|
||||
const installArgs = ["install"];
|
||||
runSync(runner.cmd, installArgs, installEnv);
|
||||
}
|
||||
|
||||
if (process.env.OPENCLAW_BUILD_ALL_NO_PNPM === "1" && action === "build") {
|
||||
run(process.execPath, [path.join(repoRoot, "node_modules/vite/bin/vite.js"), "build", ...rest]);
|
||||
return;
|
||||
}
|
||||
|
||||
run(runner.cmd, ["run", script, ...rest]);
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,7 @@ describe("resolveBuildAllSteps", () => {
|
||||
"plugins:assets:copy",
|
||||
"copy-hook-metadata",
|
||||
"copy-export-html-templates",
|
||||
"ui:build",
|
||||
"write-build-info",
|
||||
"write-cli-startup-metadata",
|
||||
"write-cli-compat",
|
||||
@@ -209,6 +210,39 @@ describe("resolveBuildAllSteps", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("includes ui:build in the full and ciArtifacts profiles after runtime postbuild", () => {
|
||||
for (const profile of ["full", "ciArtifacts"]) {
|
||||
const labels = resolveBuildAllSteps(profile).map((step) => step.label);
|
||||
expect(labels).toContain("ui:build");
|
||||
// Control UI bundling must run after tsdown clears dist so that
|
||||
// dist/control-ui survives `pnpm build` without a second command.
|
||||
expect(labels.indexOf("ui:build")).toBeGreaterThan(labels.indexOf("tsdown"));
|
||||
expect(labels.indexOf("ui:build")).toBeGreaterThan(labels.indexOf("runtime-postbuild-stamp"));
|
||||
// ui:build must run before write-build-info so the build manifest can
|
||||
// see the final dist/control-ui assets.
|
||||
expect(labels.indexOf("ui:build")).toBeLessThan(labels.indexOf("write-build-info"));
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps ui:build out of minimal backend-only profiles", () => {
|
||||
for (const profile of ["gatewayWatch", "cliStartup"]) {
|
||||
const labels = resolveBuildAllSteps(profile).map((step) => step.label);
|
||||
expect(labels).not.toContain("ui:build");
|
||||
}
|
||||
});
|
||||
|
||||
it("does not cache ui:build because Vite reads package.json, git HEAD, and env metadata", () => {
|
||||
// ui/vite.config.ts derives the Control UI build ID from package.json,
|
||||
// git HEAD, and OPENCLAW_CONTROL_UI_BUILD_ID env, so a file-input
|
||||
// signature cannot exactly invalidate generated assets. Leaving this
|
||||
// step uncached avoids restoring stale service-worker/app cache
|
||||
// metadata after `tsdown` clears `dist`.
|
||||
const step = getBuildAllStep("ui:build");
|
||||
expect(step.kind).toBe("pnpm");
|
||||
expect(step.pnpmArgs).toEqual(["ui:build"]);
|
||||
expect(step.cache).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not cache plugin-sdk entry shims over compiled JS", () => {
|
||||
const step = getBuildAllStep("write-plugin-sdk-entry-dts");
|
||||
expect(step.cache).toBeUndefined();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
@@ -101,4 +102,21 @@ describe("scripts/ui windows spawn behavior", () => {
|
||||
|
||||
expect(isDirectScriptExecution(junctionScriptPath, realScriptPath, realpath)).toBe(true);
|
||||
});
|
||||
|
||||
it("honors build-all no-pnpm mode before requiring a pnpm runner", () => {
|
||||
const result = spawnSync(process.execPath, ["scripts/ui.js", "build", "--help"], {
|
||||
cwd: path.resolve("."),
|
||||
encoding: "utf8",
|
||||
env: {
|
||||
...process.env,
|
||||
OPENCLAW_BUILD_ALL_NO_PNPM: "1",
|
||||
PATH: "",
|
||||
},
|
||||
});
|
||||
|
||||
const output = `${result.stdout}${result.stderr}`;
|
||||
expect(result.status).toBe(0);
|
||||
expect(output).not.toContain("Missing UI runner");
|
||||
expect(output).toContain("vite");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user