mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
Canvas: improve A2UI asset resolution and empty state (#20312)
Merged via /review-pr -> /prepare-pr -> /merge-pr.
Prepared head SHA: adce485695
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
This commit is contained in:
@@ -14,6 +14,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Canvas/A2UI: improve bundled-asset resolution and empty-state handling so UI fallbacks render reliably. (#20312) Thanks @mbelinky.
|
||||
- UI/Sessions: accept the canonical main session-key alias in Chat UI flows so main-session routing stays consistent. (#20311) Thanks @mbelinky.
|
||||
- iOS/Onboarding: prevent pairing-status flicker during auto-resume by keeping resumed state transitions stable. (#20310) Thanks @mbelinky.
|
||||
- OpenClawKit/Protocol: preserve JSON boolean literals (`true`/`false`) when bridging through `AnyCodable` so Apple client RPC params no longer re-encode booleans as `1`/`0`. Thanks @mbelinky.
|
||||
|
||||
@@ -451,7 +451,6 @@ class OpenClawA2UIHost extends LitElement {
|
||||
if (this.surfaces.length === 0) {
|
||||
return html`<div class="empty">
|
||||
<div class="empty-title">Canvas (A2UI)</div>
|
||||
<div>Waiting for A2UI messages…</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,14 +13,29 @@ export const CANVAS_WS_PATH = "/__openclaw__/ws";
|
||||
|
||||
let cachedA2uiRootReal: string | null | undefined;
|
||||
let resolvingA2uiRoot: Promise<string | null> | null = null;
|
||||
let cachedA2uiResolvedAtMs = 0;
|
||||
const A2UI_ROOT_RETRY_NULL_AFTER_MS = 10_000;
|
||||
|
||||
async function resolveA2uiRoot(): Promise<string | null> {
|
||||
const here = path.dirname(fileURLToPath(import.meta.url));
|
||||
const entryDir = process.argv[1] ? path.dirname(path.resolve(process.argv[1])) : null;
|
||||
const candidates = [
|
||||
// Running from source (bun) or dist (tsc + copied assets).
|
||||
// Running from source (bun) or dist/canvas-host chunk.
|
||||
path.resolve(here, "a2ui"),
|
||||
// Running from dist root chunk (common launchd path).
|
||||
path.resolve(here, "canvas-host/a2ui"),
|
||||
path.resolve(here, "../canvas-host/a2ui"),
|
||||
// Entry path fallbacks (helps when cwd is not the repo root).
|
||||
...(entryDir
|
||||
? [
|
||||
path.resolve(entryDir, "a2ui"),
|
||||
path.resolve(entryDir, "canvas-host/a2ui"),
|
||||
path.resolve(entryDir, "../canvas-host/a2ui"),
|
||||
]
|
||||
: []),
|
||||
// Running from dist without copied assets (fallback to source).
|
||||
path.resolve(here, "../../src/canvas-host/a2ui"),
|
||||
path.resolve(here, "../src/canvas-host/a2ui"),
|
||||
// Running from repo root.
|
||||
path.resolve(process.cwd(), "src/canvas-host/a2ui"),
|
||||
path.resolve(process.cwd(), "dist/canvas-host/a2ui"),
|
||||
@@ -44,13 +59,19 @@ async function resolveA2uiRoot(): Promise<string | null> {
|
||||
}
|
||||
|
||||
async function resolveA2uiRootReal(): Promise<string | null> {
|
||||
if (cachedA2uiRootReal !== undefined) {
|
||||
const nowMs = Date.now();
|
||||
if (
|
||||
cachedA2uiRootReal !== undefined &&
|
||||
(cachedA2uiRootReal !== null || nowMs - cachedA2uiResolvedAtMs < A2UI_ROOT_RETRY_NULL_AFTER_MS)
|
||||
) {
|
||||
return cachedA2uiRootReal;
|
||||
}
|
||||
if (!resolvingA2uiRoot) {
|
||||
resolvingA2uiRoot = (async () => {
|
||||
const root = await resolveA2uiRoot();
|
||||
cachedA2uiRootReal = root ? await fs.realpath(root) : null;
|
||||
cachedA2uiResolvedAtMs = Date.now();
|
||||
resolvingA2uiRoot = null;
|
||||
return cachedA2uiRootReal;
|
||||
})();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user