From 796d5421e5bfeeb1cf99e69c5815372afd000b6f Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Mon, 26 Jan 2026 21:28:18 -0800 Subject: [PATCH 1/4] fix(ci): increase heap size for macOS test runner --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fcd8e457c..cd647d6e3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -277,6 +277,8 @@ jobs: checks-macos: if: github.event_name == 'pull_request' runs-on: macos-latest + env: + NODE_OPTIONS: --max-old-space-size=4096 strategy: fail-fast: false matrix: From c10d759c444fc10aeca462faf4a74912d231c44d Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Mon, 26 Jan 2026 22:20:39 -0800 Subject: [PATCH 2/4] fix(test): reset A2UI cache between tests to prevent CI flakiness --- src/canvas-host/a2ui.ts | 6 ++++++ src/canvas-host/server.test.ts | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/canvas-host/a2ui.ts b/src/canvas-host/a2ui.ts index 876436c57..bc33144f9 100644 --- a/src/canvas-host/a2ui.ts +++ b/src/canvas-host/a2ui.ts @@ -12,6 +12,12 @@ export const CANVAS_WS_PATH = "/__clawdbot/ws"; let cachedA2uiRootReal: string | null | undefined; let resolvingA2uiRoot: Promise | null = null; +/** Reset the A2UI root cache (for testing). */ +export function resetA2uiCache(): void { + cachedA2uiRootReal = undefined; + resolvingA2uiRoot = null; +} + async function resolveA2uiRoot(): Promise { const here = path.dirname(fileURLToPath(import.meta.url)); const candidates = [ diff --git a/src/canvas-host/server.test.ts b/src/canvas-host/server.test.ts index f51e2f5e0..0bd6bbffc 100644 --- a/src/canvas-host/server.test.ts +++ b/src/canvas-host/server.test.ts @@ -3,14 +3,22 @@ import { createServer } from "node:http"; import type { AddressInfo } from "node:net"; import os from "node:os"; import path from "node:path"; -import { describe, expect, it, vi } from "vitest"; +import { beforeEach, describe, expect, it, vi } from "vitest"; import { WebSocket } from "ws"; import { rawDataToString } from "../infra/ws.js"; import { defaultRuntime } from "../runtime.js"; -import { CANVAS_HOST_PATH, CANVAS_WS_PATH, injectCanvasLiveReload } from "./a2ui.js"; +import { + CANVAS_HOST_PATH, + CANVAS_WS_PATH, + injectCanvasLiveReload, + resetA2uiCache, +} from "./a2ui.js"; import { createCanvasHostHandler, startCanvasHost } from "./server.js"; describe("canvas host", () => { + beforeEach(() => { + resetA2uiCache(); + }); it("injects live reload script", () => { const out = injectCanvasLiveReload("Hello"); expect(out).toContain(CANVAS_WS_PATH); From 0ac8f6e4256e3f8c1fcd42b7a3576f503ae6aac1 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Mon, 26 Jan 2026 22:30:32 -0800 Subject: [PATCH 3/4] fix(ci): use sha256sum on Windows and improve A2UI path resolution --- scripts/bundle-a2ui.sh | 14 ++++++++++++-- src/canvas-host/a2ui.ts | 25 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/scripts/bundle-a2ui.sh b/scripts/bundle-a2ui.sh index 7e3418fa5..b0bcce221 100755 --- a/scripts/bundle-a2ui.sh +++ b/scripts/bundle-a2ui.sh @@ -23,10 +23,20 @@ collect_files() { } compute_hash() { + # Use sha256sum on Linux/Windows (Git Bash), shasum on macOS + local sha_cmd + if command -v sha256sum &>/dev/null; then + sha_cmd="sha256sum" + elif command -v shasum &>/dev/null; then + sha_cmd="shasum -a 256" + else + echo "No sha256 tool found (sha256sum or shasum)" >&2 + exit 1 + fi collect_files \ | LC_ALL=C sort -z \ - | xargs -0 shasum -a 256 \ - | shasum -a 256 \ + | xargs -0 $sha_cmd \ + | $sha_cmd \ | awk '{print $1}' } diff --git a/src/canvas-host/a2ui.ts b/src/canvas-host/a2ui.ts index bc33144f9..0b35832d2 100644 --- a/src/canvas-host/a2ui.ts +++ b/src/canvas-host/a2ui.ts @@ -18,6 +18,25 @@ export function resetA2uiCache(): void { resolvingA2uiRoot = null; } +async function findRepoRoot(startDir: string): Promise { + let dir = startDir; + for (let i = 0; i < 10; i++) { + try { + const pkgPath = path.join(dir, "package.json"); + await fs.stat(pkgPath); + // Verify it's the clawdbot package + const pkg = JSON.parse(await fs.readFile(pkgPath, "utf8")); + if (pkg.name === "clawdbot") return dir; + } catch { + // not found, go up + } + const parent = path.dirname(dir); + if (parent === dir) break; + dir = parent; + } + return null; +} + async function resolveA2uiRoot(): Promise { const here = path.dirname(fileURLToPath(import.meta.url)); const candidates = [ @@ -32,6 +51,12 @@ async function resolveA2uiRoot(): Promise { if (process.execPath) { candidates.unshift(path.resolve(path.dirname(process.execPath), "a2ui")); } + // Find repo root by walking up from `here` (handles vitest/vite transforms). + const repoRoot = await findRepoRoot(here); + if (repoRoot) { + candidates.push(path.resolve(repoRoot, "src/canvas-host/a2ui")); + candidates.push(path.resolve(repoRoot, "dist/canvas-host/a2ui")); + } for (const dir of candidates) { try { From 6489a324cb8903256bdb36a5ecc1c368ba54ac71 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Mon, 26 Jan 2026 22:32:15 -0800 Subject: [PATCH 4/4] chore: update pnpm-lock.yaml --- pnpm-lock.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 781a461a9..3bad565c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -409,6 +409,8 @@ importers: extensions/open-prose: {} + extensions/poe: {} + extensions/signal: {} extensions/slack: {}