@rudra-js/a2ui 0.8.2 → 0.8.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 +61 -51
  2. package/package.json +7 -7
package/README.md CHANGED
@@ -8,10 +8,10 @@ It is not a hosted platform, a visual or low-code app builder, or a workspace yo
8
8
 
9
9
  This package puts that block inside the interfaces an [A2UI](https://a2ui.org) agent builds. It
10
10
  adds one component, `RudraRecommendations`, to the catalog your A2UI renderer draws from. The agent
11
- places it and hints at what the shopper is looking at. Your server still picks the products and
12
- builds the block with `@rudra-js/core`, and the browser renders it with `@rudra-js/react`.
11
+ places it and passes hints about what the shopper is looking at. Your server still picks the
12
+ products and builds the block with `@rudra-js/core`. The browser renders it with `@rudra-js/react`.
13
13
 
14
- It works with version 0.9 of the A2UI protocol, through `@a2ui/react` and `@a2ui/web_core` 0.14.
14
+ It works with version 0.9 of the A2UI protocol, using `@a2ui/react` and `@a2ui/web_core` 0.14.
15
15
 
16
16
  ## Install
17
17
 
@@ -19,28 +19,29 @@ It works with version 0.9 of the A2UI protocol, through `@a2ui/react` and `@a2ui
19
19
  npm install @rudra-js/a2ui@latest @rudra-js/core@latest @rudra-js/react@latest @rudra-js/attested@latest @a2ui/react@0.14 @a2ui/web_core@0.14 react react-dom
20
20
  ```
21
21
 
22
- Run the same command in a new app, in one that already uses rudra-js or A2UI, and to upgrade. If
23
- your app has `@rudra-js/anthropic`, add `@rudra-js/anthropic@latest` to the command. The
24
- `@rudra-js` packages are published together, and each one's peer ranges on the others start at its
25
- own version. For a bare name npm stays inside the range your `package.json` already has, so
26
- without `@latest` an app on an older core can get an `ERESOLVE`. `@0.14` is the `@a2ui` release
27
- this package works with. `react` and `react-dom` carry no version, so npm and pnpm keep a React 18
28
- app on 18.
22
+ Use the same command to install and to upgrade, whether or not your app already uses rudra-js or A2UI.
23
+ If your app has `@rudra-js/anthropic`, add `@rudra-js/anthropic@latest` to that command.
29
24
 
30
- Everything but zod is a peer dependency, so your app holds one copy of each. npm and pnpm add
31
- peers for you, but your code imports most of them itself, and pnpm lets it import only what your
32
- `package.json` names. Yarn doesn't add peers, so there you need the whole list. It does move a bare
33
- name to its latest version, so leave out `react` and `react-dom` if your app already has React. On
34
- pnpm, read [zod](#zod) first.
25
+ The `@rudra-js` packages are released together. Each one's peer range for the others starts at its
26
+ own version. For a package name with no version, npm stays inside the range your `package.json`
27
+ already has. Without `@latest`, an app on an older core can get an `ERESOLVE` error. `react`
28
+ and `react-dom` have no version, so npm and pnpm keep a React 18 app on 18.
35
29
 
36
- Keep `skipLibCheck: true`. Without it, A2UI's own declarations fail to typecheck: they need `"dom"`
37
- in `lib`, and two of their imports have no file extension, which `nodenext` refuses.
30
+ Everything except zod is a peer dependency, so your app holds one copy of each. npm and pnpm
31
+ install peers for you. List them anyway, because your code imports most of them itself.
32
+ pnpm only lets your code import what your `package.json` names. Yarn doesn't install peers, so on Yarn you
33
+ need the whole list. Yarn also moves a name with no version to its latest release. So on Yarn, if your app
34
+ already has React, leave out `react` and `react-dom`. On pnpm, read [zod](#zod) first.
35
+
36
+ Keep `skipLibCheck: true` in your `tsconfig.json`. Without it, A2UI's own type declarations fail
37
+ to typecheck. They need `"dom"` in `lib`. Two of their imports also have no file extension, which
38
+ `nodenext` refuses.
38
39
 
39
40
  ## Three pieces
40
41
 
41
42
  ### The catalog your agent is prompted with
42
43
 
43
- Put `agentCatalog.toJson()` in your agent's prompt and have it create surfaces with
44
+ Put `agentCatalog.toJson()` in your agent's prompt. Have the agent create surfaces with
44
45
  `catalogId: agentCatalog.id`. If you have catalog instructions of your own, join them to
45
46
  `RUDRA_RECOMMENDATIONS_INSTRUCTIONS`.
46
47
 
@@ -58,13 +59,16 @@ export const agentCatalog = new Catalog(
58
59
  );
59
60
  ```
60
61
 
61
- The first `toJson()` logs one "Recursive reference detected" warning per hint. It's harmless.
62
+ The first `toJson()` call logs one "Recursive reference detected" warning per hint. It's harmless.
62
63
 
63
64
  ### Your endpoint
64
65
 
65
- `shopperFor` and `candidatesFor` stand for the session and catalog code you already have.
66
- `provider: null` calls no model, so pass your own provider. In the default cohort mode the model
67
- never sees `searchQuery`, so the agent's search only counts with `generation: 'per-shopper'`.
66
+ `shopperFor` and `candidatesFor` stand in for the session and catalog code you already have.
67
+ `provider: null` calls no model, so pass your own provider.
68
+
69
+ `generation` defaults to `'cohort'`, which shares one block design between shoppers who look alike. In
70
+ that mode the model never sees `searchQuery`. The agent's search only matters with
71
+ `generation: 'per-shopper'`.
68
72
 
69
73
  ```ts
70
74
  import { createComponentGenerator, parseTrackingInput } from '@rudra-js/core';
@@ -103,11 +107,12 @@ export async function POST(request: Request): Promise<Response> {
103
107
  ```
104
108
 
105
109
  - `parseRecommendationRequest` accepts only `currentSku`, `currentCategory`, `searchQuery` and
106
- `maxItems`. Anything else is a 400.
107
- - `fitRecommendationRequest` drops a SKU or category none of your candidates has.
108
- - Pick candidates on your side, not from the hints. Each new category, `maxItems` or candidate set
109
- is a new model call, and with `per-shopper` so is each shopper and each new SKU or search, so
110
- rate-limit the endpoint (see [SECURITY.md](https://github.com/clivedsouza1010/rudra-js/blob/main/SECURITY.md)).
110
+ `maxItems`. Anything else gets a 400.
111
+ - `fitRecommendationRequest` drops a SKU or category that none of your candidates has.
112
+ - Pick candidates on your side, not from the hints.
113
+ - Each new category, `maxItems` or candidate set means a new model call. With `per-shopper`, so
114
+ does each shopper and each new SKU or search. Rate-limit the endpoint (see
115
+ [SECURITY.md](https://github.com/clivedsouza1010/rudra-js/blob/main/SECURITY.md)).
111
116
  - Send back `input.candidates` and `input.bundles`, not your raw catalog.
112
117
 
113
118
  ### The browser
@@ -142,51 +147,56 @@ const shopCatalog = new Catalog<ReactCatalogComponent>(
142
147
  export const processor = new MessageProcessor<ReactCatalogComponent>([shopCatalog]);
143
148
  ```
144
149
 
145
- Give the browser catalog the same id as the agent catalog, because A2UI looks it up by the
146
- `catalogId` the agent sends. Render the processor's surfaces with `A2uiSurface`. The options take
147
- `loadRecommendations`, `placeholder`, `onError`, and every `RudraComponent` prop except `spec`,
148
- `products` and `bundles`.
150
+ Give the browser catalog the same id as the agent catalog. A2UI looks it up by the `catalogId` the
151
+ agent sends. Render the processor's surfaces with `A2uiSurface`.
152
+
153
+ `createRudraRecommendationsComponent` takes `loadRecommendations`, `placeholder` and `onError`. It
154
+ also takes every `RudraComponent` prop except `spec`, `products` and `bundles`.
149
155
 
150
156
  ## What the component does
151
157
 
152
- - It reads each hint as a literal or from the agent's data model (`{ "path": "/viewing/sku" }`),
153
- and sends only the four. It leaves out a blank one, and one the server would turn away, like a
154
- `maxItems` of 40. A literal of the wrong type, like a numeric SKU, makes A2UI refuse the agent's
155
- whole message.
156
- - It asks once the hints hold still for 300 ms, and keeps the last block up until the next one
157
- arrives. `signal` aborts when the hints change or the component unmounts.
158
- - It checks the result against core's schemas before rendering any of it.
159
- - It shows `placeholder` until the first load. On a failed load, a bad result or a render error it
160
- shows nothing and calls `onError`.
158
+ - It reads each hint either as a literal value or from the agent's data model, like
159
+ `{ "path": "/viewing/sku" }`. It sends only the four hints the endpoint accepts.
160
+ - It leaves out a hint that is blank, or one the server would turn away, like a `maxItems` of 40.
161
+ - A literal of the wrong type, like a numeric SKU, makes A2UI refuse the agent's whole message.
162
+ - It waits until the hints stop changing for 300 ms, then calls `loadRecommendations`.
163
+ - It keeps showing the last block until the next one arrives.
164
+ - `signal` aborts when the hints change or the component unmounts.
165
+ - It checks the result against core's schemas before it renders any of it.
166
+ - It shows `placeholder` until the first load finishes.
167
+ - If a load fails or the result fails the schema check, it shows nothing and calls `onError`. It
168
+ does the same if the block throws while rendering.
161
169
  - Each component on a surface sends its own request.
162
170
 
163
171
  ## Where it runs
164
172
 
165
- `@rudra-js/a2ui` holds `createRudraRecommendationsComponent` and its types, and loads only in the
173
+ `@rudra-js/a2ui` holds `createRudraRecommendationsComponent` and its types. It loads only in the
166
174
  browser, because `@a2ui/react` needs a DOM. The agent catalog and your endpoint import from
167
- `@rudra-js/a2ui/server`, which runs anywhere. In Next.js a `'use client'` file still runs on the
168
- server for the first render, so load the one that imports `@rudra-js/a2ui` from a client component
169
- with `next/dynamic` and `ssr: false`.
175
+ `@rudra-js/a2ui/server`, which runs anywhere.
176
+
177
+ In Next.js, a `'use client'` file still runs on the server for the first render. Load the file
178
+ that imports `@rudra-js/a2ui` through `next/dynamic` with `ssr: false`, and make that call from a
179
+ client component.
170
180
 
171
- A2UI renders on the client, so a crawler won't see a block an agent places. For a product page,
181
+ A2UI renders in the browser, so a crawler won't see a block an agent places. For a product page,
172
182
  render `RudraComponent` on the server, as the
173
183
  [`@rudra-js/react` README](https://github.com/clivedsouza1010/rudra-js/tree/main/packages/react)
174
184
  describes.
175
185
 
176
186
  ## zod
177
187
 
178
- A2UI's schemas are zod 3, so this package depends on zod 3 while the rest of rudra-js uses zod 4.
179
- npm installs both, each where its package finds it, and you don't need either one yourself.
188
+ A2UI's schemas use zod 3, so this package depends on zod 3. The rest of rudra-js uses zod 4. npm
189
+ installs both, each where its own package finds it. With npm, you don't need either one yourself.
180
190
 
181
- On pnpm, `@a2ui/react` gets core's zod 4 as its zod peer, and the browser example stops
182
- typechecking (TS2344). If your app has no zod of its own, add zod 3:
191
+ On pnpm, `@a2ui/react` gets core's zod 4 as its zod peer. Then the browser example fails to
192
+ typecheck with TS2344. If your app has no zod of its own, add zod 3:
183
193
 
184
194
  ```sh
185
195
  pnpm add zod@^3.25.76
186
196
  ```
187
197
 
188
- If your app uses zod 4, drop the peer from `@a2ui/react` in `.pnpmfile.cjs`, and pnpm gives it
189
- the zod 3 it depends on:
198
+ If your app uses zod 4, remove the zod peer from `@a2ui/react` in `.pnpmfile.cjs`. pnpm then gives
199
+ it the zod 3 it depends on:
190
200
 
191
201
  ```js
192
202
  module.exports = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rudra-js/a2ui",
3
- "version": "0.8.2",
3
+ "version": "0.8.3",
4
4
  "description": "A2UI component for rudra-js: lets an A2UI agent place a product-recommendation block whose products, prices and wording come from your shop, not from the agent",
5
5
  "keywords": [
6
6
  "rudra-js",
@@ -62,19 +62,19 @@
62
62
  "peerDependencies": {
63
63
  "@a2ui/react": "^0.14.0",
64
64
  "@a2ui/web_core": "^0.14.0",
65
- "@rudra-js/core": "^0.8.2",
66
- "@rudra-js/react": "^0.8.2",
65
+ "@rudra-js/core": "^0.8.3",
66
+ "@rudra-js/react": "^0.8.3",
67
67
  "react": "^18.2.0 || ^19.0.0"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@a2ui/react": "0.14.0",
71
71
  "@a2ui/web_core": "0.14.0",
72
- "@rudra-js/core": "0.8.2",
73
- "@rudra-js/react": "0.8.2",
72
+ "@rudra-js/core": "0.8.3",
73
+ "@rudra-js/react": "0.8.3",
74
74
  "@types/react": "^19.3.0",
75
75
  "@types/react-dom": "^19.3.0",
76
76
  "jsdom": "^27.4.0",
77
- "react": "^19.3.0",
78
- "react-dom": "^19.3.0"
77
+ "react": "^19.3.1",
78
+ "react-dom": "^19.3.1"
79
79
  }
80
80
  }