@threadplane/a2ui 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +144 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # @threadplane/a2ui
2
+
3
+ The A2UI (Agent-to-UI) protocol layer behind generative UI in [Threadplane](https://github.com/cacheplane/threadplane), the open-source thread-plane for agents, targeting the **A2UI v0.9.1 stable release**. It defines the wire format an agent uses to drive a UI surface, plus the parser and resolver that read it — framework-agnostic, pure TypeScript, no Angular dependency, usable in any TypeScript environment.
4
+
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/@threadplane/a2ui">
7
+ <img alt="npm version" src="https://img.shields.io/npm/v/@threadplane%2Fa2ui?color=15253E&labelColor=0A0A0A&style=flat-square" />
8
+ </a>
9
+ <a href="https://opensource.org/licenses/MIT">
10
+ <img alt="MIT" src="https://img.shields.io/badge/License-MIT-15253E?labelColor=0A0A0A&style=flat-square" />
11
+ </a>
12
+ </p>
13
+
14
+ ## What it does
15
+
16
+ - **Protocol type system** — full TypeScript type vocabulary for every A2UI v0.9 message, component, dynamic value, action, and client→agent message.
17
+ - **Streaming message parser** — `createA2uiMessageParser()` returns a stateful parser that accepts JSONL chunks from a streaming agent response and emits typed `A2uiMessage` values as lines complete.
18
+ - **Dynamic value resolution** — `resolveDynamic()` resolves a dynamic value (bare literal or `{ path }` binding) against a client data model; `isPathRef` / `isFunctionCall` guards narrow dynamic values before use.
19
+ - **JSON-pointer utilities** — `getByPointer`, `setByPointer`, and `deleteByPointer` navigate and mutate the A2UI client data model using JSON-pointer paths, including the v0.9 array-delete rule (index set to `undefined`, length preserved).
20
+ - **Runtime-neutral** — pure TypeScript, no runtime dependencies, works in browsers and Node.js alike. Consumed by `@threadplane/chat` to render agent-emitted generative UI.
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ npm install @threadplane/a2ui
26
+ ```
27
+
28
+ No peer dependencies required.
29
+
30
+ ## Quick start
31
+
32
+ ### Parse a streaming A2UI response
33
+
34
+ ```typescript
35
+ import { createA2uiMessageParser } from '@threadplane/a2ui';
36
+ import type { A2uiMessage } from '@threadplane/a2ui';
37
+
38
+ const parser = createA2uiMessageParser();
39
+
40
+ // Feed chunks as they arrive from your agent's streaming response:
41
+ function onChunk(chunk: string): void {
42
+ const messages: A2uiMessage[] = parser.push(chunk);
43
+ for (const msg of messages) {
44
+ if ('createSurface' in msg) {
45
+ console.log('New surface:', msg.createSurface.surfaceId);
46
+ } else if ('updateComponents' in msg) {
47
+ console.log('Components for:', msg.updateComponents.surfaceId);
48
+ } else if ('updateDataModel' in msg) {
49
+ console.log('Data model update at:', msg.updateDataModel.path ?? '/');
50
+ } else if ('deleteSurface' in msg) {
51
+ console.log('Delete surface:', msg.deleteSurface.surfaceId);
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ Every envelope carries `"version": "v0.9"`. The component whose `id` is `"root"` is the tree root — rendering can begin as soon as it arrives, and the tree fills in progressively.
58
+
59
+ ### Resolve dynamic values against a data model
60
+
61
+ ```typescript
62
+ import { resolveDynamic } from '@threadplane/a2ui';
63
+
64
+ const model = { user: { name: 'Alice' } };
65
+
66
+ // Bare literal — passes through unchanged
67
+ const label = resolveDynamic('Submit', model);
68
+ // => 'Submit'
69
+
70
+ // Path binding — resolves against the model via JSON pointer
71
+ const name = resolveDynamic({ path: '/user/name' }, model);
72
+ // => 'Alice'
73
+ ```
74
+
75
+ ### JSON-pointer utilities
76
+
77
+ ```typescript
78
+ import { getByPointer, setByPointer, deleteByPointer } from '@threadplane/a2ui';
79
+
80
+ const model = { items: [{ id: 1 }, { id: 2 }] };
81
+
82
+ getByPointer(model, '/items/0/id'); // => 1
83
+ const updated = setByPointer(model, '/items/0/id', 99);
84
+ const removed = deleteByPointer(updated, '/items/0/id');
85
+ ```
86
+
87
+ ## Capabilities
88
+
89
+ ### Protocol message parsing
90
+
91
+ `createA2uiMessageParser()` returns an `A2uiMessageParser` with a single `push(chunk: string): A2uiMessage[]` method. The parser is stateful — it buffers partial lines between calls and emits complete messages as JSONL lines arrive. Malformed lines are silently skipped (safe for mid-stream partial JSON), and unknown envelope keys — such as future v1.0 messages — are skipped rather than treated as errors.
92
+
93
+ ```typescript
94
+ const parser = createA2uiMessageParser();
95
+ const messages = parser.push(chunk); // A2uiMessage[]
96
+ ```
97
+
98
+ ### Dynamic value resolution
99
+
100
+ `resolveDynamic(value, model, scope?)` resolves A2UI v0.9 dynamic values:
101
+
102
+ - Bare literals (string, number, boolean, string arrays, plain objects) — pass through unchanged.
103
+ - `{ path: string }` — looked up in `model` via JSON pointer. If an `A2uiScope` is provided, relative paths resolve against `scope.basePath` (used inside `children` templates).
104
+ - `{ call: string, args? }` — client-side function calls, executed through the registry passed as the fourth argument (`createA2uiFunctionRegistry()` provides the standard set: `formatString` with `${...}` interpolation, `formatNumber`, `formatCurrency`, `formatDate`, `pluralize`, `and`, `or`, `not`). Args resolve recursively. Without a registry, or for unknown names, calls resolve to `undefined`.
105
+
106
+ Type guards:
107
+
108
+ | Guard | Narrows to |
109
+ |---|---|
110
+ | `isPathRef(v)` | `{ path: string }` |
111
+ | `isFunctionCall(v)` | `{ call: string; args?: Record<string, unknown> }` |
112
+
113
+ ### JSON-pointer utilities
114
+
115
+ Three immutable helpers operate on `Record<string, unknown>` data models:
116
+
117
+ | Function | Description |
118
+ |---|---|
119
+ | `getByPointer(model, pointer)` | Read the value at `pointer`. Returns `undefined` if the path does not exist. |
120
+ | `setByPointer(model, pointer, value)` | Return a new model with `value` written at `pointer`. |
121
+ | `deleteByPointer(model, pointer)` | Return a new model with the key at `pointer` removed. Array indices are set to `undefined`, preserving length (v0.9 rule). |
122
+
123
+ Pointers follow standard `/segment/segment` syntax. An empty pointer (`''` or `'/'`) targets the root.
124
+
125
+ ### Type system
126
+
127
+ `@threadplane/a2ui` exports the complete A2UI v0.9 type vocabulary. Categories include:
128
+
129
+ - **Protocol constants** — `A2UI_WIRE_VERSION` (`'v0.9'`), `A2UI_MIME_TYPE` (`'application/a2ui+json'`), `A2UI_BASIC_CATALOG_ID`
130
+ - **Envelopes** — `A2uiMessage`, `A2uiCreateSurface`, `A2uiUpdateComponents`, `A2uiUpdateDataModel`, `A2uiDeleteSurface`
131
+ - **Components** — `A2uiComponent`, `A2uiComponentBase`, `A2uiCatalogComponent`, plus per-component shapes: `A2uiText`, `A2uiImage`, `A2uiIcon`, `A2uiVideo`, `A2uiAudioPlayer`, `A2uiRow`, `A2uiColumn`, `A2uiList`, `A2uiCard`, `A2uiTabs`, `A2uiModal`, `A2uiDivider`, `A2uiButton`, `A2uiCheckBox`, `A2uiTextField`, `A2uiDateTimeInput`, `A2uiChoicePicker`, `A2uiSlider`
132
+ - **Dynamic values** — `DynamicString`, `DynamicNumber`, `DynamicBoolean`, `DynamicStringList`, `DynamicValue`, `A2uiPathRef`, `A2uiFunctionCall`
133
+ - **Actions and checks** — `A2uiAction`, `A2uiEventAction`, `A2uiFunctionAction`, `A2uiCheck`, `A2uiCheckable`
134
+ - **Client → agent** — `A2uiActionMessage`, `A2uiErrorMessage`, `A2uiClientDataModel`, `A2uiClientCapabilities`
135
+ - **Theming** — `A2uiTheme`
136
+ - **Parser and scope** — `A2uiMessageParser`, `A2uiScope`, `A2uiChildren`
137
+
138
+ ## Reliability
139
+
140
+ Pure TypeScript with no runtime dependencies. No `Buffer`, no `process`, no DOM — safe in any TypeScript environment. Follows the repo's patch-only `0.0.x` release policy. The "Library — lint / test / build" CI job runs on every pull request.
141
+
142
+ ## License
143
+
144
+ MIT. See [LICENSE](../../LICENSE).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadplane/a2ui",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "A2UI protocol types, streaming parser, and dynamic-value resolver for agent-generated UI. Pure TypeScript.",
5
5
  "license": "MIT",
6
6
  "repository": {