Build: stop tracking bundled artifacts (#2455) (thanks @0oAstro)
Co-authored-by: 0oAstro <0oAstro@users.noreply.github.com>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -42,7 +42,6 @@ apps/ios/*.xcfilelist
|
|||||||
vendor/a2ui/renderers/lit/dist/
|
vendor/a2ui/renderers/lit/dist/
|
||||||
src/canvas-host/a2ui/*.bundle.js
|
src/canvas-host/a2ui/*.bundle.js
|
||||||
src/canvas-host/a2ui/*.map
|
src/canvas-host/a2ui/*.map
|
||||||
src/canvas-host/a2ui/index.html
|
|
||||||
.bundle.hash
|
.bundle.hash
|
||||||
|
|
||||||
# fastlane (iOS)
|
# fastlane (iOS)
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ Status: unreleased.
|
|||||||
- Browser: route browser control via gateway/node; remove standalone browser control command and control URL config.
|
- Browser: route browser control via gateway/node; remove standalone browser control command and control URL config.
|
||||||
- Browser: route `browser.request` via node proxies when available; honor proxy timeouts; derive browser ports from `gateway.port`.
|
- Browser: route `browser.request` via node proxies when available; honor proxy timeouts; derive browser ports from `gateway.port`.
|
||||||
- Update: ignore dist/control-ui for dirty checks and restore after ui builds. (#1976) Thanks @Glucksberg.
|
- Update: ignore dist/control-ui for dirty checks and restore after ui builds. (#1976) Thanks @Glucksberg.
|
||||||
|
- Build: bundle A2UI assets during build and stop tracking generated bundles. (#2455) Thanks @0oAstro.
|
||||||
- Telegram: allow caption param for media sends. (#1888) Thanks @mguellsegarra.
|
- Telegram: allow caption param for media sends. (#1888) Thanks @mguellsegarra.
|
||||||
- Telegram: support plugin sendPayload channelData (media/buttons) and validate plugin commands. (#1917) Thanks @JoshuaLelon.
|
- Telegram: support plugin sendPayload channelData (media/buttons) and validate plugin commands. (#1917) Thanks @JoshuaLelon.
|
||||||
- Telegram: avoid block replies when streaming is disabled. (#1885) Thanks @ivancasco.
|
- Telegram: avoid block replies when streaming is disabled. (#1885) Thanks @ivancasco.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default defineConfig({
|
|||||||
output: {
|
output: {
|
||||||
file: outputFile,
|
file: outputFile,
|
||||||
format: "esm",
|
format: "esm",
|
||||||
inlineDynamicImports: true,
|
codeSplitting: false,
|
||||||
sourcemap: false,
|
sourcemap: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ clawdbot onboard --install-daemon
|
|||||||
```
|
```
|
||||||
|
|
||||||
If you don’t have a global install yet, run the onboarding step via `pnpm clawdbot ...` from the repo.
|
If you don’t have a global install yet, run the onboarding step via `pnpm clawdbot ...` from the repo.
|
||||||
|
`pnpm build` also bundles A2UI assets; if you need to run just that step, use `pnpm canvas:a2ui:bundle`.
|
||||||
|
|
||||||
Gateway (from this repo):
|
Gateway (from this repo):
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@
|
|||||||
"docs:bin": "node scripts/build-docs-list.mjs",
|
"docs:bin": "node scripts/build-docs-list.mjs",
|
||||||
"docs:dev": "cd docs && mint dev",
|
"docs:dev": "cd docs && mint dev",
|
||||||
"docs:build": "cd docs && pnpm dlx --reporter append-only mint broken-links",
|
"docs:build": "cd docs && pnpm dlx --reporter append-only mint broken-links",
|
||||||
"build": "tsc -p tsconfig.json && node --import tsx scripts/canvas-a2ui-copy.ts && node --import tsx scripts/copy-hook-metadata.ts && node --import tsx scripts/write-build-info.ts",
|
"build": "pnpm canvas:a2ui:bundle && tsc -p tsconfig.json && node --import tsx scripts/canvas-a2ui-copy.ts && node --import tsx scripts/copy-hook-metadata.ts && node --import tsx scripts/write-build-info.ts",
|
||||||
"plugins:sync": "node --import tsx scripts/sync-plugin-versions.ts",
|
"plugins:sync": "node --import tsx scripts/sync-plugin-versions.ts",
|
||||||
"release:check": "node --import tsx scripts/release-check.ts",
|
"release:check": "node --import tsx scripts/release-check.ts",
|
||||||
"ui:install": "node scripts/ui.js install",
|
"ui:install": "node scripts/ui.js install",
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
on_error() {
|
||||||
|
echo "A2UI bundling failed. Re-run with: pnpm canvas:a2ui:bundle" >&2
|
||||||
|
echo "If this persists, verify pnpm deps and try again." >&2
|
||||||
|
}
|
||||||
|
trap on_error ERR
|
||||||
|
|
||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
HASH_FILE="$ROOT_DIR/src/canvas-host/a2ui/.bundle.hash"
|
HASH_FILE="$ROOT_DIR/src/canvas-host/a2ui/.bundle.hash"
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,44 @@
|
|||||||
import fs from "node:fs/promises";
|
import fs from "node:fs/promises";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||||
|
|
||||||
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
const srcDir = path.join(repoRoot, "src", "canvas-host", "a2ui");
|
|
||||||
const outDir = path.join(repoRoot, "dist", "canvas-host", "a2ui");
|
|
||||||
|
|
||||||
async function main() {
|
export function getA2uiPaths(env = process.env) {
|
||||||
await fs.stat(path.join(srcDir, "index.html"));
|
const srcDir =
|
||||||
await fs.stat(path.join(srcDir, "a2ui.bundle.js"));
|
env.CLAWDBOT_A2UI_SRC_DIR ?? path.join(repoRoot, "src", "canvas-host", "a2ui");
|
||||||
|
const outDir =
|
||||||
|
env.CLAWDBOT_A2UI_OUT_DIR ?? path.join(repoRoot, "dist", "canvas-host", "a2ui");
|
||||||
|
return { srcDir, outDir };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function copyA2uiAssets({
|
||||||
|
srcDir,
|
||||||
|
outDir,
|
||||||
|
}: {
|
||||||
|
srcDir: string;
|
||||||
|
outDir: string;
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
await fs.stat(path.join(srcDir, "index.html"));
|
||||||
|
await fs.stat(path.join(srcDir, "a2ui.bundle.js"));
|
||||||
|
} catch (err) {
|
||||||
|
const message =
|
||||||
|
'Missing A2UI bundle assets. Run "pnpm canvas:a2ui:bundle" and retry.';
|
||||||
|
throw new Error(message, { cause: err });
|
||||||
|
}
|
||||||
await fs.mkdir(path.dirname(outDir), { recursive: true });
|
await fs.mkdir(path.dirname(outDir), { recursive: true });
|
||||||
await fs.cp(srcDir, outDir, { recursive: true });
|
await fs.cp(srcDir, outDir, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch((err) => {
|
async function main() {
|
||||||
console.error(String(err));
|
const { srcDir, outDir } = getA2uiPaths();
|
||||||
process.exit(1);
|
await copyA2uiAssets({ srcDir, outDir });
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
|
||||||
|
main().catch((err) => {
|
||||||
|
console.error(String(err));
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export async function fetchBrowserJson<T>(
|
|||||||
const timeoutMs = init?.timeoutMs ?? 5000;
|
const timeoutMs = init?.timeoutMs ?? 5000;
|
||||||
try {
|
try {
|
||||||
if (isAbsoluteHttp(url)) {
|
if (isAbsoluteHttp(url)) {
|
||||||
return await fetchHttpJson<T>(url, { ...(init ?? {}), timeoutMs });
|
return await fetchHttpJson<T>(url, init ? { ...init, timeoutMs } : { timeoutMs });
|
||||||
}
|
}
|
||||||
const started = await startBrowserControlServiceFromConfig();
|
const started = await startBrowserControlServiceFromConfig();
|
||||||
if (!started) {
|
if (!started) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export function registerBrowserElementCommands(
|
|||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
: undefined;
|
: undefined;
|
||||||
try {
|
try {
|
||||||
const result = await callBrowserAct({
|
const result = await callBrowserAct<{ url?: string }>({
|
||||||
parent,
|
parent,
|
||||||
profile,
|
profile,
|
||||||
body: {
|
body: {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export function registerBrowserFilesAndDownloadsCommands(
|
|||||||
const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts);
|
const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts);
|
||||||
try {
|
try {
|
||||||
const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined;
|
const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined;
|
||||||
const result = await callBrowserRequest(
|
const result = await callBrowserRequest<{ download: { path: string } }>(
|
||||||
parent,
|
parent,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -68,7 +68,7 @@ export function registerBrowserFilesAndDownloadsCommands(
|
|||||||
const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts);
|
const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts);
|
||||||
try {
|
try {
|
||||||
const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined;
|
const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined;
|
||||||
const result = await callBrowserRequest(
|
const result = await callBrowserRequest<{ download: { path: string } }>(
|
||||||
parent,
|
parent,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -108,7 +108,7 @@ export function registerBrowserFilesAndDownloadsCommands(
|
|||||||
const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts);
|
const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts);
|
||||||
try {
|
try {
|
||||||
const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined;
|
const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined;
|
||||||
const result = await callBrowserRequest(
|
const result = await callBrowserRequest<{ download: { path: string } }>(
|
||||||
parent,
|
parent,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export function registerBrowserFormWaitEvalCommands(
|
|||||||
fields: opts.fields,
|
fields: opts.fields,
|
||||||
fieldsFile: opts.fieldsFile,
|
fieldsFile: opts.fieldsFile,
|
||||||
});
|
});
|
||||||
const result = await callBrowserAct({
|
const result = await callBrowserAct<{ result?: unknown }>({
|
||||||
parent,
|
parent,
|
||||||
profile,
|
profile,
|
||||||
body: {
|
body: {
|
||||||
@@ -66,7 +66,7 @@ export function registerBrowserFormWaitEvalCommands(
|
|||||||
? (opts.load as "load" | "domcontentloaded" | "networkidle")
|
? (opts.load as "load" | "domcontentloaded" | "networkidle")
|
||||||
: undefined;
|
: undefined;
|
||||||
const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined;
|
const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined;
|
||||||
const result = await callBrowserAct({
|
const result = await callBrowserAct<{ result?: unknown }>({
|
||||||
parent,
|
parent,
|
||||||
profile,
|
profile,
|
||||||
body: {
|
body: {
|
||||||
@@ -108,7 +108,7 @@ export function registerBrowserFormWaitEvalCommands(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const result = await callBrowserAct({
|
const result = await callBrowserAct<{ result?: unknown }>({
|
||||||
parent,
|
parent,
|
||||||
profile,
|
profile,
|
||||||
body: {
|
body: {
|
||||||
|
|||||||
40
src/scripts/canvas-a2ui-copy.test.ts
Normal file
40
src/scripts/canvas-a2ui-copy.test.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import os from "node:os";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { copyA2uiAssets } from "../../scripts/canvas-a2ui-copy.js";
|
||||||
|
|
||||||
|
describe("canvas a2ui copy", () => {
|
||||||
|
it("throws a helpful error when assets are missing", async () => {
|
||||||
|
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-a2ui-"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
await expect(copyA2uiAssets({ srcDir: dir, outDir: path.join(dir, "out") })).rejects.toThrow(
|
||||||
|
'Run "pnpm canvas:a2ui:bundle"',
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
await fs.rm(dir, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("copies bundled assets to dist", async () => {
|
||||||
|
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-a2ui-"));
|
||||||
|
const srcDir = path.join(dir, "src");
|
||||||
|
const outDir = path.join(dir, "dist");
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.mkdir(srcDir, { recursive: true });
|
||||||
|
await fs.writeFile(path.join(srcDir, "index.html"), "<html></html>", "utf8");
|
||||||
|
await fs.writeFile(path.join(srcDir, "a2ui.bundle.js"), "console.log(1);", "utf8");
|
||||||
|
|
||||||
|
await copyA2uiAssets({ srcDir, outDir });
|
||||||
|
|
||||||
|
await expect(fs.stat(path.join(outDir, "index.html"))).resolves.toBeTruthy();
|
||||||
|
await expect(fs.stat(path.join(outDir, "a2ui.bundle.js"))).resolves.toBeTruthy();
|
||||||
|
} finally {
|
||||||
|
await fs.rm(dir, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -2,7 +2,7 @@ import { listChannelPlugins } from "../channels/plugins/index.js";
|
|||||||
import { resolveChannelDefaultAccountId } from "../channels/plugins/helpers.js";
|
import { resolveChannelDefaultAccountId } from "../channels/plugins/helpers.js";
|
||||||
import type { ChannelId } from "../channels/plugins/types.js";
|
import type { ChannelId } from "../channels/plugins/types.js";
|
||||||
import type { ClawdbotConfig } from "../config/config.js";
|
import type { ClawdbotConfig } from "../config/config.js";
|
||||||
import { resolveBrowserConfig } from "../browser/config.js";
|
import { resolveBrowserConfig, resolveProfile } from "../browser/config.js";
|
||||||
import { resolveConfigPath, resolveStateDir } from "../config/paths.js";
|
import { resolveConfigPath, resolveStateDir } from "../config/paths.js";
|
||||||
import { resolveGatewayAuth } from "../gateway/auth.js";
|
import { resolveGatewayAuth } from "../gateway/auth.js";
|
||||||
import { formatCliCommand } from "../cli/command-format.js";
|
import { formatCliCommand } from "../cli/command-format.js";
|
||||||
|
|||||||
Reference in New Issue
Block a user