Chore: harden A2UI bundle dependency resolution (#22507)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: d84c5bde51
Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
This commit is contained in:
Vincent Koc
2026-02-21 02:46:31 -05:00
committed by GitHub
parent 187f4ea41f
commit f4a59eb5d8
6 changed files with 49 additions and 50 deletions

View File

@@ -14,6 +14,7 @@ Docs: https://docs.openclaw.ai
- Security/Unused Dependencies: remove unused root devDependencies `@lit/context` and `@lit-labs/signals` flagged as unused by Knip dead-code reports. (#22471) Thanks @vincentkoc.
- Security/Unused Dependencies: remove unused root dependency `lit` that is now scoped to `ui/` package dependencies. (#22471) Thanks @vincentkoc.
- Security/Unused Dependencies: remove unused root dependencies `long` and `rolldown`; keep A2UI bundling functional by falling back to `pnpm dlx rolldown` when the binary is not locally installed. (#22481) Thanks @vincentkoc.
- Security/Unused Dependencies: harden A2UI bundling dependency resolution by resolving `lit`, `@lit/context`, `@lit-labs/signals`, and `signal-utils` from UI workspace or repo-root dependency locations to tolerate Docker layout differences without root-only assumptions. (#22507) Thanks @vincentkoc.
- Security/Unused Dependencies: fix A2UI bundle resolution for removed root `lit` deps by resolving `lit`, `@lit/context`, `@lit-labs/signals`, and `signal-utils` from UI workspace dependencies in `rolldown.config.mjs` during bundling. (#22481) Thanks @vincentkoc.
- Security/Unused Dependencies: simplify `canvas-a2ui` bundling script by removing temporary vendored `node_modules` symlink logic now that `ui` workspace dependencies are explicit. (#22481) Thanks @vincentkoc.
- Security/Unused Dependencies: remove unused `@microsoft/agents-hosting-express` and `@microsoft/agents-hosting-extensions-teams` from `extensions/msteams` because current code only uses `@microsoft/agents-hosting`. Thanks @vincentkoc.

View File

@@ -1,10 +1,10 @@
import path from "node:path";
import { existsSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { defineConfig } from "rolldown";
const here = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(here, "../../../../..");
const uiRoot = path.resolve(repoRoot, "ui");
const fromHere = (p) => path.resolve(here, p);
const outputFile = path.resolve(
here,
@@ -17,19 +17,28 @@ const outputFile = path.resolve(
const a2uiLitDist = path.resolve(repoRoot, "vendor/a2ui/renderers/lit/dist/src");
const a2uiThemeContext = path.resolve(a2uiLitDist, "0.8/ui/context/theme.js");
const a2uiNodeModules = path.resolve(repoRoot, "ui/node_modules");
const rootNodeModules = path.resolve(repoRoot, "node_modules");
const uiNodeModules = path.resolve(uiRoot, "node_modules");
const repoNodeModules = path.resolve(repoRoot, "node_modules");
const resolveA2uiDep = (pkg, rel = "") => {
const uiPath = path.resolve(a2uiNodeModules, pkg, rel);
if (existsSync(uiPath)) {
return uiPath;
function resolveUiDependency(moduleId) {
const candidates = [
path.resolve(uiNodeModules, moduleId),
path.resolve(repoNodeModules, moduleId),
];
for (const candidate of candidates) {
if (existsSync(candidate)) {
return candidate;
}
}
return path.resolve(rootNodeModules, pkg, rel);
};
const fallbackCandidates = candidates.join(", ");
throw new Error(
`A2UI bundle config cannot resolve ${moduleId}. Checked: ${fallbackCandidates}. ` +
"Keep dependency installed in ui workspace or repo root before bundling.",
);
}
export default defineConfig({
export default {
input: fromHere("bootstrap.js"),
experimental: {
attachDebugInfo: "none",
@@ -40,13 +49,13 @@ export default defineConfig({
"@a2ui/lit": path.resolve(a2uiLitDist, "index.js"),
"@a2ui/lit/ui": path.resolve(a2uiLitDist, "0.8/ui/ui.js"),
"@openclaw/a2ui-theme-context": a2uiThemeContext,
"@lit/context": resolveA2uiDep("@lit/context", "index.js"),
"@lit/context/": resolveA2uiDep("@lit/context"),
"@lit-labs/signals": resolveA2uiDep("@lit-labs/signals", "index.js"),
"@lit-labs/signals/": resolveA2uiDep("@lit-labs/signals"),
lit: resolveA2uiDep("lit", "index.js"),
"lit/": resolveA2uiDep("lit"),
"signal-utils/": resolveA2uiDep("signal-utils"),
"@lit/context": resolveUiDependency("@lit/context"),
"@lit/context/": resolveUiDependency("@lit/context/"),
"@lit-labs/signals": resolveUiDependency("@lit-labs/signals"),
"@lit-labs/signals/": resolveUiDependency("@lit-labs/signals/"),
lit: resolveUiDependency("lit"),
"lit/": resolveUiDependency("lit/"),
"signal-utils/": resolveUiDependency("signal-utils/"),
},
},
output: {
@@ -55,4 +64,4 @@ export default defineConfig({
codeSplitting: false,
sourcemap: false,
},
});
};

View File

@@ -5,8 +5,6 @@
"type": "module",
"dependencies": {
"@microsoft/agents-hosting": "^1.2.3",
"@microsoft/agents-hosting-express": "^1.2.3",
"@microsoft/agents-hosting-extensions-teams": "^1.2.3",
"express": "^5.2.1"
},
"devDependencies": {

View File

@@ -174,6 +174,7 @@
"json5": "^2.2.3",
"jszip": "^3.10.1",
"linkedom": "^0.18.12",
"long": "^5.3.2",
"markdown-it": "^14.1.1",
"node-edge-tts": "^1.2.10",
"opusscript": "^0.0.8",
@@ -192,6 +193,8 @@
},
"devDependencies": {
"@grammyjs/types": "^3.24.0",
"@lit-labs/signals": "^0.1.3",
"@lit/context": "^1.1.6",
"@types/express": "^5.0.6",
"@types/markdown-it": "^14.1.2",
"@types/node": "^25.3.0",
@@ -199,9 +202,11 @@
"@types/ws": "^8.18.1",
"@typescript/native-preview": "7.0.0-dev.20260219.1",
"@vitest/coverage-v8": "^4.0.18",
"lit": "^3.3.2",
"oxfmt": "0.33.0",
"oxlint": "^1.48.0",
"oxlint-tsgolint": "^0.14.1",
"signal-utils": "0.21.1",
"tsdown": "^0.20.3",
"tsx": "^4.21.0",
"typescript": "^5.9.3",

44
pnpm-lock.yaml generated
View File

@@ -131,6 +131,9 @@ importers:
linkedom:
specifier: ^0.18.12
version: 0.18.12
long:
specifier: ^5.3.2
version: 5.3.2
markdown-it:
specifier: ^14.1.1
version: 14.1.1
@@ -183,6 +186,12 @@ importers:
'@grammyjs/types':
specifier: ^3.24.0
version: 3.24.0
'@lit-labs/signals':
specifier: ^0.1.3
version: 0.1.3
'@lit/context':
specifier: ^1.1.6
version: 1.1.6
'@types/express':
specifier: ^5.0.6
version: 5.0.6
@@ -204,6 +213,9 @@ importers:
'@vitest/coverage-v8':
specifier: ^4.0.18
version: 4.0.18(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18))(vitest@4.0.18)
lit:
specifier: ^3.3.2
version: 3.3.2
oxfmt:
specifier: 0.33.0
version: 0.33.0
@@ -213,6 +225,9 @@ importers:
oxlint-tsgolint:
specifier: ^0.14.1
version: 0.14.1
signal-utils:
specifier: 0.21.1
version: 0.21.1(signal-polyfill@0.2.2)
tsdown:
specifier: ^0.20.3
version: 0.20.3(@typescript/native-preview@7.0.0-dev.20260219.1)(typescript@5.9.3)
@@ -405,12 +420,6 @@ importers:
'@microsoft/agents-hosting':
specifier: ^1.2.3
version: 1.2.3
'@microsoft/agents-hosting-express':
specifier: ^1.2.3
version: 1.2.3
'@microsoft/agents-hosting-extensions-teams':
specifier: ^1.2.3
version: 1.2.3
express:
specifier: ^5.2.1
version: 5.2.1
@@ -1561,14 +1570,6 @@ packages:
resolution: {integrity: sha512-XRQF+AVn6f9sGDUsfDQFiwLtmqqWNhM9JIwZRzK9XQLPTQmoWwjoWz8KMKc5fuvj5Ybly3974VrqYUbDOeMyTg==}
engines: {node: '>=20.0.0'}
'@microsoft/agents-hosting-express@1.2.3':
resolution: {integrity: sha512-aBgvyDJ+3ifeUKy/56qQuLJPAizN9UfGV3/1GVrhmyAqUKvphusK3LMxiRTpHDhAaUvuzFOr1AJ8XiRhOl9l3w==}
engines: {node: '>=20.0.0'}
'@microsoft/agents-hosting-extensions-teams@1.2.3':
resolution: {integrity: sha512-fZcn8JcU50VfjBgz6jTlCRiQReAZzj2f2Atudwa+ymxJQhfBb7NToJcY7OdLqM8hlnQhzAg71HJtGhPR/L2p1g==}
engines: {node: '>=20.0.0'}
'@microsoft/agents-hosting@1.2.3':
resolution: {integrity: sha512-8paXuxdbRc9X6tccYoR3lk0DSglt1SxpJG+6qDa8TVTuGiTvIuhnN4st9JZhIiazxPiFPTJAkhK5JSsOk+wLVQ==}
engines: {node: '>=20.0.0'}
@@ -7402,21 +7403,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@microsoft/agents-hosting-express@1.2.3':
dependencies:
'@microsoft/agents-hosting': 1.2.3
express: 5.2.1
transitivePeerDependencies:
- debug
- supports-color
'@microsoft/agents-hosting-extensions-teams@1.2.3':
dependencies:
'@microsoft/agents-hosting': 1.2.3
transitivePeerDependencies:
- debug
- supports-color
'@microsoft/agents-hosting@1.2.3':
dependencies:
'@azure/core-auth': 1.10.1

View File

@@ -89,7 +89,7 @@ pnpm -s exec tsc -p "$A2UI_RENDERER_DIR/tsconfig.json"
if command -v rolldown >/dev/null 2>&1; then
rolldown -c "$A2UI_APP_DIR/rolldown.config.mjs"
else
pnpm dlx "rolldown@1.0.0-rc.5" -c "$A2UI_APP_DIR/rolldown.config.mjs"
pnpm -s dlx rolldown -c "$A2UI_APP_DIR/rolldown.config.mjs"
fi
echo "$current_hash" > "$HASH_FILE"