@rudra-js/a2ui 0.8.1 → 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.
- package/README.md +63 -42
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -8,28 +8,40 @@ 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
|
|
12
|
-
builds the block with `@rudra-js/core
|
|
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,
|
|
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
|
|
|
18
18
|
```sh
|
|
19
|
-
npm install @rudra-js/a2ui @rudra-js/core @rudra-js/react @rudra-js/attested @a2ui/react @a2ui/web_core react react-dom
|
|
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
|
-
|
|
23
|
-
|
|
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.
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
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.
|
|
29
|
+
|
|
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.
|
|
27
39
|
|
|
28
40
|
## Three pieces
|
|
29
41
|
|
|
30
42
|
### The catalog your agent is prompted with
|
|
31
43
|
|
|
32
|
-
Put `agentCatalog.toJson()` in your agent's prompt
|
|
44
|
+
Put `agentCatalog.toJson()` in your agent's prompt. Have the agent create surfaces with
|
|
33
45
|
`catalogId: agentCatalog.id`. If you have catalog instructions of your own, join them to
|
|
34
46
|
`RUDRA_RECOMMENDATIONS_INSTRUCTIONS`.
|
|
35
47
|
|
|
@@ -47,13 +59,16 @@ export const agentCatalog = new Catalog(
|
|
|
47
59
|
);
|
|
48
60
|
```
|
|
49
61
|
|
|
50
|
-
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.
|
|
51
63
|
|
|
52
64
|
### Your endpoint
|
|
53
65
|
|
|
54
|
-
`shopperFor` and `candidatesFor` stand for the session and catalog code you already have.
|
|
55
|
-
`provider: null` calls no model, so pass your own provider.
|
|
56
|
-
|
|
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'`.
|
|
57
72
|
|
|
58
73
|
```ts
|
|
59
74
|
import { createComponentGenerator, parseTrackingInput } from '@rudra-js/core';
|
|
@@ -92,11 +107,12 @@ export async function POST(request: Request): Promise<Response> {
|
|
|
92
107
|
```
|
|
93
108
|
|
|
94
109
|
- `parseRecommendationRequest` accepts only `currentSku`, `currentCategory`, `searchQuery` and
|
|
95
|
-
`maxItems`. Anything else
|
|
96
|
-
- `fitRecommendationRequest` drops a SKU or category none of your candidates has.
|
|
97
|
-
- Pick candidates on your side, not from the hints.
|
|
98
|
-
|
|
99
|
-
|
|
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)).
|
|
100
116
|
- Send back `input.candidates` and `input.bundles`, not your raw catalog.
|
|
101
117
|
|
|
102
118
|
### The browser
|
|
@@ -131,51 +147,56 @@ const shopCatalog = new Catalog<ReactCatalogComponent>(
|
|
|
131
147
|
export const processor = new MessageProcessor<ReactCatalogComponent>([shopCatalog]);
|
|
132
148
|
```
|
|
133
149
|
|
|
134
|
-
Give the browser catalog the same id as the agent catalog
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
`
|
|
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`.
|
|
138
155
|
|
|
139
156
|
## What the component does
|
|
140
157
|
|
|
141
|
-
- It reads each hint as a literal or from the agent's data model
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
- It
|
|
146
|
-
|
|
147
|
-
-
|
|
148
|
-
- It
|
|
149
|
-
|
|
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.
|
|
150
169
|
- Each component on a surface sends its own request.
|
|
151
170
|
|
|
152
171
|
## Where it runs
|
|
153
172
|
|
|
154
|
-
`@rudra-js/a2ui` holds `createRudraRecommendationsComponent` and its types
|
|
173
|
+
`@rudra-js/a2ui` holds `createRudraRecommendationsComponent` and its types. It loads only in the
|
|
155
174
|
browser, because `@a2ui/react` needs a DOM. The agent catalog and your endpoint import from
|
|
156
|
-
`@rudra-js/a2ui/server`, which runs anywhere.
|
|
157
|
-
|
|
158
|
-
|
|
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.
|
|
159
180
|
|
|
160
|
-
A2UI renders
|
|
181
|
+
A2UI renders in the browser, so a crawler won't see a block an agent places. For a product page,
|
|
161
182
|
render `RudraComponent` on the server, as the
|
|
162
183
|
[`@rudra-js/react` README](https://github.com/clivedsouza1010/rudra-js/tree/main/packages/react)
|
|
163
184
|
describes.
|
|
164
185
|
|
|
165
186
|
## zod
|
|
166
187
|
|
|
167
|
-
A2UI's schemas
|
|
168
|
-
|
|
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.
|
|
169
190
|
|
|
170
|
-
On pnpm, `@a2ui/react` gets core's zod 4 as its zod peer
|
|
171
|
-
|
|
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:
|
|
172
193
|
|
|
173
194
|
```sh
|
|
174
195
|
pnpm add zod@^3.25.76
|
|
175
196
|
```
|
|
176
197
|
|
|
177
|
-
If your app uses zod 4,
|
|
178
|
-
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:
|
|
179
200
|
|
|
180
201
|
```js
|
|
181
202
|
module.exports = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rudra-js/a2ui",
|
|
3
|
-
"version": "0.8.
|
|
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.
|
|
66
|
-
"@rudra-js/react": "^0.8.
|
|
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.
|
|
73
|
-
"@rudra-js/react": "0.8.
|
|
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.
|
|
78
|
-
"react-dom": "^19.3.
|
|
77
|
+
"react": "^19.3.1",
|
|
78
|
+
"react-dom": "^19.3.1"
|
|
79
79
|
}
|
|
80
80
|
}
|