Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/a2ui-catalog.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@ For the `<A2UI>` shell, treat `className` and `wrapSurface` as complementary the
When evolving `packages/genui/a2ui-playground`, treat protocol-prefixed hashes such as `#/a2ui/...` and `#/openui/...` as the canonical routes, and preserve the current mainline tab names (`create`, `examples`, `components`) when adding protocol-aware routing. If you keep compatibility aliases for older or transitional paths such as `#/demos` or `#/chat`, parse them into the canonical route model instead of letting a rebase silently rename the mainline routes.

When a GenUI package builds a CLI or other generated artifact that another workspace package executes during its own build, declare that package's `dist/**` (or equivalent generated directory) as Turbo `build.outputs`. Without explicit outputs, cache hits can skip restoring the built CLI and leave downstream workspace bins pointing at missing files.

When implementing A2UI v0.9 functions in `packages/genui/a2ui`, keep function resolution scoped to the active catalog first, with the global `FunctionRegistry` only as an escape hatch. Dynamic component props, checks, and function-call actions should all go through the same `resolveDynamicValue` / `executeFunctionCall` path so data bindings, nested function calls, zod argument coercion from `@a2ui/web_core`, and `formatString` data-context interpolation stay consistent.

When verifying `packages/genui/a2ui-playground`, remember that `pnpm -F @lynx-js/a2ui-reactlynx build` regenerates catalog JSON only. The playground consumes `@lynx-js/a2ui-reactlynx` through package exports under `dist/**`, so run `pnpm -F @lynx-js/a2ui-reactlynx exec tsc -p tsconfig.build.json` before rebuilding the playground if runtime TypeScript changed.

For known A2UI playground examples, keep the web preview URL on `?demo=<id>` instead of swapping it to the payload-store `messagesUrl`. `render.html` intentionally fetches known demo JSON in the browser shell and passes resolved messages into Lynx, avoiding fetch differences in the Lynx worker runtime; use payload-store URLs for custom edited JSON.
34 changes: 27 additions & 7 deletions packages/genui/a2ui-catalog-extractor/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import { pathToFileURL } from 'node:url';

import {
extractCatalogComponentsFromTypeDocJson,
extractCatalogFunctionsFromTypeDocJson,
findCatalogSourceFiles,
writeCatalogArtifacts,
writeCatalogComponents,
writeComponentCatalogs,
writeCatalogFunctions,
} from './index.js';
import type { TypeDocProject } from './index.js';

Expand Down Expand Up @@ -107,12 +109,20 @@ export async function runCli(
const components = extractCatalogComponentsFromTypeDocJson(project, {
cwd,
});
const functions = extractCatalogFunctionsFromTypeDocJson(project, {
cwd,
});

writeCatalogComponents(components, {
cwd,
outDir: options.outDir,
});
writeCatalogFunctions(functions, {
cwd,
outDir: options.outDir,
});
printGeneratedComponents(components);
printGeneratedFunctions(functions);
return 0;
}

Expand All @@ -137,24 +147,26 @@ export async function runCli(
);
}

const components = await writeComponentCatalogs({
const { components, functions } = await writeCatalogArtifacts({
cwd,
outDir: options.outDir,
sourceFiles: uniqueSourceFiles,
});

printGeneratedComponents(components);
printGeneratedFunctions(functions);

// Fail loudly if we matched source files but emitted no components
// Fail loudly if we matched source files but emitted no artifacts
// this used to silently succeed on Windows when TypeDoc rejected
// backslash entry-point paths, and downstream packages then failed
// to import the missing `catalog.json` files.
if (components.length === 0) {
if (components.length === 0 && functions.length === 0) {
console.error(
`[a2ui-catalog-extractor] Found ${uniqueSourceFiles.length} `
+ `source file(s) but emitted 0 component catalogs. Make sure `
+ `each catalog props interface is annotated with `
+ `\`@a2uiCatalog <Name>\`.`,
+ `source file(s) but emitted 0 component catalogs and 0 `
+ `function definitions. Make sure each catalog props interface `
+ `is annotated with \`@a2uiCatalog <Name>\` and each function `
+ `is annotated with \`@a2uiFunction <name>\`.`,
);
return 1;
}
Expand All @@ -169,6 +181,14 @@ function printGeneratedComponents(components: { name: string }[]): void {
}
}

function printGeneratedFunctions(functions: { name: string }[]): void {
if (functions.length === 0) return;
console.info(`Generated ${functions.length} A2UI function definition files.`);
for (const fn of functions) {
console.info(`Generated function definition for ${fn.name}`);
}
}

function readValue(args: string[], index: number, option: string): string {
const value = args[index];
if (!value || value.startsWith('-')) {
Expand Down
Loading
Loading