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
2 changes: 2 additions & 0 deletions .github/genui-tsconfig.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ applyTo: "packages/genui/**/*"
---

When adding a new package under `packages/genui`, add a package-level `tsconfig.json` and wire it into `packages/genui/tsconfig.json` references in the same change. Root type-aware ESLint uses the TypeScript project service, so new GenUI source files that are not reachable from those references will fail pre-commit parsing before code linting even starts.

When maintaining hand-written ESM CLI bin files under `packages/genui`, make entrypoint detection resolve `process.argv[1]` through `fs.realpathSync()` before comparing it with `import.meta.url`. pnpm `.bin` shims invoke workspace bins through symlink paths, and a raw path comparison can load the module without executing the CLI, making build scripts appear successful while generated artifacts are missing.
7 changes: 7 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,12 @@ export default tseslint.config(
reportUnusedDisableDirectives: true,
},
},
{
files: ['packages/genui/index.ts'],
rules: {
'import/no-unresolved': 'off',
},
},
// TypeScript-related
{
files: ['**/*.ts', '**/*.tsx'],
Expand All @@ -293,6 +299,7 @@ export default tseslint.config(
'rslib.config.ts',
'vitest.config.ts',
'rstest.config.ts',
'packages/genui/index.ts',
],
defaultProject: './tsconfig.json',
},
Expand Down
1 change: 1 addition & 0 deletions packages/genui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/dist/
170 changes: 170 additions & 0 deletions packages/genui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# @lynx-js/genui

Generative UI primitives for Lynx applications.

`@lynx-js/genui` is the single npm package for the GenUI toolchain. It exposes
A2UI rendering, OpenUI rendering, A2UI prompt/catalog utilities, and the CLI
from one package while keeping implementation directories private to this
monorepo.

## Installation

```bash
pnpm add @lynx-js/genui @lynx-js/react
```

`@lynx-js/react` is a peer dependency. Some built-in A2UI catalog components
also use `@lynx-js/lynx-ui`; install it when your app renders those components.

## Entry Points

```ts
import {
A2UI,
createMessageStore,
createOpenUiLibrary,
createStreamingParser,
buildA2UISystemPrompt,
extractCatalogComponents,
} from '@lynx-js/genui';
```

The root entry point exports the stable APIs most applications and tools need:

- A2UI ReactLynx renderer and data-store helpers.
- OpenUI parser, library, and renderer APIs.
- A2UI prompt builders.
- A2UI catalog extraction utilities.

Focused subpaths are also available:

```ts
import { A2UI, Text, Button } from '@lynx-js/genui/a2ui';
import { createMessageStore } from '@lynx-js/genui/a2ui/store';
import { createOpenUiLibrary } from '@lynx-js/genui/openui';
import { buildA2UISystemPrompt } from '@lynx-js/genui/a2ui-prompt';
import { extractCatalogComponents } from '@lynx-js/genui/a2ui-catalog-extractor';
```

Catalog manifests are exported through a single public catalog entry:

```ts
import { Text, Button } from '@lynx-js/genui/a2ui/catalog';
```

## A2UI

A2UI renders agent-generated UI messages that follow the A2UI v0.9 protocol.
Create a message store, push protocol messages into it from your transport, and
render the latest surface with `<A2UI>`.

```tsx
import { A2UI, Button, Text, createMessageStore } from '@lynx-js/genui/a2ui';

const messageStore = createMessageStore();

export function GenUIScreen() {
return (
<A2UI
messageStore={messageStore}
catalogs={[Text, Button]}
onAction={(action) => {
// Send the action back to your agent, then push response messages
// into the same messageStore.
}}
/>
);
}
```

Use the A2UI style entry when you want the packaged component styles:

```ts
import '@lynx-js/genui/a2ui/styles/theme.css';
```

See [`a2ui/README.md`](./a2ui/README.md) for catalog composition and custom
component details.

## OpenUI

OpenUI renders parsed OpenUI DSL through a configurable component library.

```tsx
import {
OpenUiRenderer,
createOpenUiLibrary,
createStreamingParser,
} from '@lynx-js/genui/openui';

const library = createOpenUiLibrary();
const parser = createStreamingParser(library.toJSONSchema());
const result = parser.push('root = Stack([TextContent("Hello")])');

export function OpenUIScreen() {
return <OpenUiRenderer result={result} library={library} />;
}
```

Renderer styles are explicit:

```ts
import '@lynx-js/genui/openui/styles/renderer.css';
```

See [`openui/README.md`](./openui/README.md) for streaming and custom library
examples.

## CLI

The package installs the GenUI CLI and the low-level catalog extractor binary:

```bash
genui --help
genui-cli --help
a2ui-catalog-extractor --help
```

`a2ui-cli` is also kept as a compatibility alias for existing A2UI scripts. New
scripts should prefer the namespace-first `genui a2ui ...` form so OpenUI
commands can be added under `genui openui ...` later.

Generate catalog artifacts:

```bash
genui a2ui generate catalog \
--catalog-dir src/catalog \
--source src/functions \
--out-dir dist/catalog
```

Generate an A2UI system prompt:

```bash
genui a2ui generate prompt \
--catalog-dir dist/catalog \
--out dist/a2ui-system-prompt.txt
```

## Published Package Layout

Only `@lynx-js/genui` is intended to be published. The package contains compiled
JavaScript and declarations under `dist/` directories, plus CLI entry points,
README files, styles, and extractor skills.

The root `index.ts` is compiled during build. Do not hand-write
`dist/index.js` or `dist/index.d.ts`; run:

```bash
pnpm -C packages/genui build
```

Before publishing, verify the package contents:

```bash
pnpm -C packages/genui pack --dry-run
```

## License

Apache-2.0
32 changes: 16 additions & 16 deletions packages/genui/a2ui-catalog-extractor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

English | [简体中文](./readme.zh_cn.md)

`@lynx-js/a2ui-catalog-extractor` is the internal TypeDoc-powered extraction
engine behind `npx @lynx-js/a2ui-cli generate catalog`. It turns TypeScript component
`@lynx-js/genui/a2ui-catalog-extractor` is the internal TypeDoc-powered extraction
engine behind `genui a2ui generate catalog`. It turns TypeScript component
interfaces into A2UI component catalog JSON. You write the public component
contract once as a TypeScript `interface`, describe it with normal TypeDoc
comments, and run the public `npx @lynx-js/a2ui-cli` command to generate the JSON Schema
comments, and run the public `genui a2ui` command to generate the JSON Schema
that an A2UI agent can read.

For user-facing scripts, use `npx @lynx-js/a2ui-cli generate catalog`. Treat
For user-facing scripts, use `genui a2ui generate catalog`. Treat
this package as the implementation layer for extraction behavior and tests.

## What It Does
Expand Down Expand Up @@ -58,18 +58,18 @@ the marked interface.

### Package manager

Run the public CLI package through `npx`:
Run the public CLI after installing `@lynx-js/genui`:

```bash
npx @lynx-js/a2ui-cli --help
genui a2ui --help
```

Then add a script to your package:

```json
{
"scripts": {
"build:catalog": "npx @lynx-js/a2ui-cli generate catalog --catalog-dir src/catalog --out-dir dist/catalog"
"build:catalog": "genui a2ui generate catalog --catalog-dir src/catalog --out-dir dist/catalog"
}
}
```
Expand Down Expand Up @@ -132,7 +132,7 @@ extractor that this interface should become a catalog component named
Run:

```bash
npx @lynx-js/a2ui-cli generate catalog --catalog-dir src/catalog --out-dir dist/catalog
genui a2ui generate catalog --catalog-dir src/catalog --out-dir dist/catalog
```

The extractor scans the catalog directory, finds interfaces marked with
Expand Down Expand Up @@ -391,13 +391,13 @@ export interface CardProps {
## CLI Reference

The public CLI entry point is
`npx @lynx-js/a2ui-cli generate catalog`. It delegates to this package
`genui a2ui generate catalog`. It delegates to this package
internally.

### Generate catalog artifacts

```bash
npx @lynx-js/a2ui-cli generate catalog [options]
genui a2ui generate catalog [options]
```

| Option | Description | Default |
Expand All @@ -417,10 +417,10 @@ files. It ignores `.d.ts`, `node_modules`, `dist`, and `.turbo`.

## Repository-internal Programmatic API

These exports are documented for maintainers of `@lynx-js/a2ui-cli`, extractor
These exports are documented for maintainers of `@lynx-js/genui-cli`, extractor
tests, and repository-internal tooling. They are not the external integration
surface for product code. Product build scripts should call
`npx @lynx-js/a2ui-cli generate catalog` instead of importing this package
`genui a2ui generate catalog` instead of importing this package
directly.

### Generate components from source files
Expand All @@ -429,7 +429,7 @@ directly.
import {
extractCatalogComponents,
writeComponentCatalogs,
} from '@lynx-js/a2ui-catalog-extractor';
} from '@lynx-js/genui/a2ui-catalog-extractor';

const components = await extractCatalogComponents({
sourceFiles: ['src/catalog/QuickStartCard.tsx'],
Expand Down Expand Up @@ -472,7 +472,7 @@ import * as fs from 'node:fs';
import {
extractCatalogComponentsFromTypeDocJson,
writeCatalogComponents,
} from '@lynx-js/a2ui-catalog-extractor';
} from '@lynx-js/genui/a2ui-catalog-extractor';

const projectJson = JSON.parse(
await fs.promises.readFile('typedoc.json', 'utf8'),
Expand All @@ -487,7 +487,7 @@ writeCatalogComponents(components, {
The equivalent CLI command is:

```bash
npx @lynx-js/a2ui-cli generate catalog --typedoc-json typedoc.json --out-dir dist/catalog
genui a2ui generate catalog --typedoc-json typedoc.json --out-dir dist/catalog
```

### Create a full A2UI catalog object
Expand All @@ -499,7 +499,7 @@ the other top-level A2UI catalog fields:
import {
createA2UICatalog,
extractCatalogComponents,
} from '@lynx-js/a2ui-catalog-extractor';
} from '@lynx-js/genui/a2ui-catalog-extractor';

const components = await extractCatalogComponents({
sourceFiles: ['src/catalog/QuickStartCard.tsx'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@
// Copyright 2026 The Lynx Authors. All rights reserved.
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.
// eslint-disable-next-line import/no-unresolved -- Generated by the package build.
import '../dist/cli.js';
5 changes: 3 additions & 2 deletions packages/genui/a2ui-catalog-extractor/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "@lynx-js/a2ui-catalog-extractor",
"name": "@lynx-js/genui-a2ui-catalog-extractor",
"version": "0.0.0",
"private": true,
"description": "TypeDoc-driven A2UI catalog extractor for TypeScript interfaces.",
"repository": {
"type": "git",
Expand Down Expand Up @@ -31,7 +32,7 @@
"README.md"
],
"scripts": {
"build": "rslib build",
"build": "tsc --project tsconfig.build.json",
"test": "rstest"
},
"dependencies": {
Expand Down
Loading
Loading