begeniux 0.1.0 → 0.2.0
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 +278 -189
- package/dist/copilotkit.cjs +138 -0
- package/dist/copilotkit.cjs.map +1 -0
- package/dist/copilotkit.d.cts +20 -0
- package/dist/copilotkit.d.ts +20 -0
- package/dist/copilotkit.js +102 -0
- package/dist/copilotkit.js.map +1 -0
- package/dist/index.cjs +656 -320
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +266 -47
- package/dist/index.d.ts +266 -47
- package/dist/index.js +652 -315
- package/dist/index.js.map +1 -1
- package/package.json +20 -5
package/README.md
CHANGED
|
@@ -1,119 +1,110 @@
|
|
|
1
1
|
# begeniux
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Drop-in adaptive UI engine. Tracks user behavior, asks an agent for a CSS-level adaptation plan, mutates the live DOM in real time.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Today's UX cycle is slow: research → mock → ship → iterate. begeniux short-circuits it: install the library on an existing app, the agent observes how each user actually behaves, and the UI re-shapes itself live to match — accent colors, density, emphasis, microcopy. No variants pre-baked. No design committee. Personalization happens *during the session*.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
```bash
|
|
8
|
+
npm install begeniux
|
|
9
|
+
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
```tsx
|
|
12
|
+
<CopilotKitProvider runtimeUrl="/api/copilotkit">
|
|
13
|
+
<BeGenProvider designSystem={designSystem} pageContext={{ route: "/" }}>
|
|
14
|
+
<CopilotKitAdapter />
|
|
15
|
+
<App /> {/* unmodified existing app */}
|
|
16
|
+
</BeGenProvider>
|
|
17
|
+
</CopilotKitProvider>
|
|
18
|
+
```
|
|
12
19
|
|
|
13
|
-
|
|
20
|
+
That's the whole integration. The library tracks behavior universally, hands a behavior summary + your design system + a DOM snapshot to your LangGraph (or any) agent, and applies the agent's `apply_adaptations` tool calls to the live DOM with full reversibility.
|
|
14
21
|
|
|
15
|
-
|
|
16
|
-
- **Shallow ML** needed huge population-level traffic to converge — too slow for a single session.
|
|
17
|
-
- **A/B tests** optimize *populations*, not *individuals* — the wrong granularity.
|
|
22
|
+
---
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
## Why this exists
|
|
20
25
|
|
|
21
26
|
```mermaid
|
|
22
27
|
flowchart LR
|
|
23
28
|
subgraph Trad["Today's generative UI"]
|
|
24
29
|
direction LR
|
|
25
|
-
P["💬
|
|
30
|
+
P["💬 Prompt"] --> M1["LLM"] --> U1["Generated UI"]
|
|
26
31
|
end
|
|
27
32
|
subgraph Be["BeGeniux"]
|
|
28
33
|
direction LR
|
|
29
|
-
B["🖱️ Behavioral trace<br/>clicks ·
|
|
34
|
+
B["🖱️ Behavioral trace<br/>clicks · dwell · scroll · hover<br/>focus · input · errors · rage clicks"] --> M2["Agent<br/>(your LangGraph)"] --> U2["Live DOM mutation<br/>session-granular"]
|
|
30
35
|
end
|
|
31
36
|
Trad ~~~ Be
|
|
32
37
|
```
|
|
33
38
|
|
|
34
|
-
>
|
|
35
|
-
|
|
36
|
-
### The goal
|
|
39
|
+
> Most generative UI today reacts to *prompts*. begeniux reacts to *behavioral traces*. The contribution is the combination: **interaction traces as the input modality**, **LLM agents as the policy** (not hand-coded rules), **session-granularity adaptation** (not population A/B tests), and **mutation of the existing UI** (not replacement of pre-built variants) — under developer-declared design-system invariants that keep the agent honest.
|
|
37
40
|
|
|
38
|
-
|
|
41
|
+
The first three are 2024+ technology that finally make 30 years of adaptive UI research tractable. The fourth is what makes it *drop-in*.
|
|
39
42
|
|
|
40
43
|
---
|
|
41
44
|
|
|
42
45
|
## How it works
|
|
43
46
|
|
|
44
|
-
Every `<BeGenSurface>` runs a tight loop, scoped to its own DOM region:
|
|
45
|
-
|
|
46
47
|
```mermaid
|
|
47
48
|
sequenceDiagram
|
|
48
49
|
autonumber
|
|
49
50
|
participant U as User
|
|
50
|
-
participant T as
|
|
51
|
-
participant
|
|
52
|
-
participant
|
|
53
|
-
participant
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
T
|
|
58
|
-
T->>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
51
|
+
participant T as Behavior tracker
|
|
52
|
+
participant P as BeGenProvider
|
|
53
|
+
participant A as Agent (your LangGraph)
|
|
54
|
+
participant E as AdaptationEngine
|
|
55
|
+
participant D as Live DOM
|
|
56
|
+
|
|
57
|
+
U->>T: clicks · scrolls · hovers · dwells · focuses · inputs · errors
|
|
58
|
+
Note over T: Ring buffer · 12 event kinds · plug-in extension API
|
|
59
|
+
T->>T: every N events / M ms → BehaviorSummary
|
|
60
|
+
T->>P: summary
|
|
61
|
+
P->>P: rate-limit gate (≥5s default) + change detection
|
|
62
|
+
P->>A: { summary, designSystem, dom: visibleSelectors }
|
|
63
|
+
Note over A: Agent reasons over signal,<br/>your design system tokens,<br/>and what's visible on the page
|
|
64
|
+
A-->>E: apply_adaptations(plan)
|
|
65
|
+
Note over E: Validates against scope.allow / deny.<br/>Reverts previous plan first.<br/>Tracks every mutation for clean rollback.
|
|
66
|
+
E->>D: set CSS var · add class · set style · set attribute
|
|
67
|
+
D->>U: UI shifts in real time
|
|
65
68
|
```
|
|
66
69
|
|
|
67
70
|
Three things keep this honest:
|
|
68
71
|
|
|
69
|
-
1. **Listeners scoped to the container
|
|
70
|
-
2. **
|
|
71
|
-
3. **
|
|
72
|
+
1. **Listeners scoped to the provider's container** (default `document.body`). Universal coverage, opt-in narrower scope via `containerRef`.
|
|
73
|
+
2. **CSS-only mutations.** No `display`, no `position`, no structural reshuffles in v0.2 — the engine refuses them. Layout cannot break.
|
|
74
|
+
3. **Plan-level reversibility.** Every new plan reverts the previous one before applying. Mutations never accumulate. Provider unmount restores the page completely.
|
|
72
75
|
|
|
73
76
|
---
|
|
74
77
|
|
|
75
78
|
## Where it fits in your stack
|
|
76
79
|
|
|
77
|
-
The library is one layer. You bring your variants and your policy:
|
|
78
|
-
|
|
79
80
|
```mermaid
|
|
80
81
|
flowchart TB
|
|
81
|
-
subgraph YourApp["Your application"]
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
subgraph Lib["begeniux (this package)"]
|
|
92
|
-
direction TB
|
|
93
|
-
Surface["<BeGenSurface>"]
|
|
94
|
-
Provider["<BeGenProvider>"]
|
|
95
|
-
Tracker["useBehaviorTracker"]
|
|
96
|
-
Ctx["BeGenContext"]
|
|
97
|
-
Surface -.uses.-> Tracker
|
|
98
|
-
Surface -.publishes to.-> Ctx
|
|
99
|
-
Provider -.exposes.-> Ctx
|
|
82
|
+
subgraph YourApp["Your application (drop-in)"]
|
|
83
|
+
Page["Pages / Components"]
|
|
84
|
+
Provider["BeGenProvider"]
|
|
85
|
+
Adapter["CopilotKitAdapter<br/>(or HTTP adapter)"]
|
|
86
|
+
Page --> Provider
|
|
87
|
+
Provider -.contains.-> Tracker["useBehaviorTracker"]
|
|
88
|
+
Provider -.contains.-> Engine["AdaptationEngine"]
|
|
89
|
+
Provider -.contains.-> Snapshot["domSnapshot"]
|
|
90
|
+
Adapter --> Provider
|
|
100
91
|
end
|
|
101
92
|
|
|
102
|
-
subgraph
|
|
93
|
+
subgraph Stack["Agent layer (your choice)"]
|
|
103
94
|
direction TB
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
Heur["createHeuristicClassifier<br/>(zero-dep fallback)"]
|
|
95
|
+
CK["CopilotKit Runtime<br/>+ LangGraph"]
|
|
96
|
+
HTTP["Custom HTTP route<br/>(any framework)"]
|
|
97
|
+
Other["Anything that satisfies<br/>ClassifyFn"]
|
|
108
98
|
end
|
|
109
99
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
Classify -.-> Heur
|
|
100
|
+
Adapter -.canonical.-> CK
|
|
101
|
+
Adapter -.escape hatch.-> HTTP
|
|
102
|
+
Adapter -.also fine.-> Other
|
|
114
103
|
```
|
|
115
104
|
|
|
116
|
-
**
|
|
105
|
+
The library has **zero opinions** about your agent backend. CopilotKit + LangGraph + Gemini is the canonical hackathon stack and the easiest path; the HTTP adapter and the `useBehaviorTracker` / `AdaptationEngine` escape hatches let you wire anything else.
|
|
106
|
+
|
|
107
|
+
Peer-deps: `react`, `react-dom` (>=18). `@copilotkit/react-core` and `zod` are **optional** peers, only needed if you import the CopilotKit adapter.
|
|
117
108
|
|
|
118
109
|
---
|
|
119
110
|
|
|
@@ -121,190 +112,288 @@ flowchart TB
|
|
|
121
112
|
|
|
122
113
|
Three types are the entire boundary between your code and the library:
|
|
123
114
|
|
|
124
|
-
```mermaid
|
|
125
|
-
flowchart LR
|
|
126
|
-
E["BehaviorEvent[]<br/><i>click · scroll · hover · dwell</i>"]
|
|
127
|
-
S["BehaviorSummary<br/><i>clicks_per_min, avg_dwell_ms,<br/>scroll_depth, hover_count,<br/>events_seen, page_context</i>"]
|
|
128
|
-
D["AgentDirective<br/><i>variant · confidence · reasoning</i>"]
|
|
129
|
-
V["Rendered variant"]
|
|
130
|
-
|
|
131
|
-
E -->|tracker aggregates| S
|
|
132
|
-
S -->|ClassifyFn = your policy| D
|
|
133
|
-
D -->|surface selects| V
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
In code:
|
|
137
|
-
|
|
138
115
|
```ts
|
|
139
|
-
type ClassifyFn =
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
events_seen: number; // saturates at 50
|
|
147
|
-
page_context: { route: string; visible_product_ids: string[] };
|
|
116
|
+
type ClassifyFn<TContext = { route: string }> =
|
|
117
|
+
(input: AdaptInput<TContext>) => Promise<AdaptationPlan>;
|
|
118
|
+
|
|
119
|
+
type AdaptInput<TContext> = {
|
|
120
|
+
summary: BehaviorSummary<TContext>; // 12 event kinds, aggregated
|
|
121
|
+
designSystem: DesignSystem; // your vocabulary (CSS vars + classes)
|
|
122
|
+
dom: { visibleSelectors: string[]; route: string }; // what's on screen
|
|
148
123
|
};
|
|
149
124
|
|
|
150
|
-
type
|
|
151
|
-
|
|
152
|
-
confidence: number;
|
|
153
|
-
reasoning: string;
|
|
125
|
+
type AdaptationPlan = {
|
|
126
|
+
adaptations: Adaptation[];
|
|
127
|
+
confidence: number; // 0..1; engine skips below threshold
|
|
128
|
+
reasoning: string;
|
|
154
129
|
};
|
|
130
|
+
|
|
131
|
+
type Adaptation =
|
|
132
|
+
| { kind: "set-css-var"; selector: string; name: string; value: string }
|
|
133
|
+
| { kind: "add-class"; selector: string; className: string }
|
|
134
|
+
| { kind: "remove-class"; selector: string; className: string }
|
|
135
|
+
| { kind: "set-style"; selector: string; property: string; value: string }
|
|
136
|
+
| { kind: "set-attribute"; selector: string; name: string; value: string }
|
|
137
|
+
| { kind: "set-aria-label"; selector: string; value: string };
|
|
155
138
|
```
|
|
156
139
|
|
|
157
|
-
|
|
140
|
+
The full type contract — including `BehaviorSummary`, `DesignSystem`, `BeGenProviderProps` — lives in [`src/types.ts`](./src/types.ts).
|
|
158
141
|
|
|
159
142
|
---
|
|
160
143
|
|
|
161
|
-
##
|
|
144
|
+
## Quick start (CopilotKit + LangGraph)
|
|
162
145
|
|
|
163
|
-
|
|
164
|
-
|
|
146
|
+
The canonical wiring. See [`examples/with-copilotkit/`](./examples/with-copilotkit/README.md) for the full snippet, including the LangGraph node side.
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
import { CopilotKitProvider } from "@copilotkit/react-core/v2";
|
|
150
|
+
import { BeGenProvider, type DesignSystem } from "begeniux";
|
|
151
|
+
import { CopilotKitAdapter } from "begeniux/copilotkit";
|
|
152
|
+
|
|
153
|
+
const designSystem: DesignSystem = {
|
|
154
|
+
cssVariables: {
|
|
155
|
+
"--accent": { description: "Action color", type: "color", defaultValue: "#7c3aed" },
|
|
156
|
+
"--density": { description: "Layout density", type: "length", defaultValue: "16px" },
|
|
157
|
+
},
|
|
158
|
+
classes: {
|
|
159
|
+
"is-engaged": "High-engagement treatment",
|
|
160
|
+
"is-skimming": "Low-engagement treatment",
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
export default function App() {
|
|
165
|
+
return (
|
|
166
|
+
<CopilotKitProvider runtimeUrl="/api/copilotkit">
|
|
167
|
+
<BeGenProvider designSystem={designSystem} pageContext={{ route: "/" }}>
|
|
168
|
+
<CopilotKitAdapter />
|
|
169
|
+
<YourApp />
|
|
170
|
+
</BeGenProvider>
|
|
171
|
+
</CopilotKitProvider>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
165
174
|
```
|
|
166
175
|
|
|
167
|
-
|
|
176
|
+
The agent gets a frontend tool called `apply_adaptations`. Whenever it decides the UI should change, it calls the tool — begeniux applies the plan, the DOM shifts, the user sees a different UI without a reload.
|
|
177
|
+
|
|
178
|
+
---
|
|
168
179
|
|
|
169
|
-
## Quick start
|
|
180
|
+
## Quick start (HTTP — any backend)
|
|
181
|
+
|
|
182
|
+
Don't use CopilotKit? Wire any HTTP endpoint:
|
|
170
183
|
|
|
171
184
|
```tsx
|
|
172
|
-
import {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const classify = createGeminiClassifier({
|
|
179
|
-
apiKey: process.env.NEXT_PUBLIC_GEMINI_KEY!,
|
|
185
|
+
import { BeGenProvider, createHttpAdapter } from "begeniux";
|
|
186
|
+
|
|
187
|
+
const classify = createHttpAdapter({
|
|
188
|
+
url: "/api/begen/adapt", // your endpoint
|
|
189
|
+
// POST { summary, designSystem, dom } → { adaptations, confidence, reasoning }
|
|
180
190
|
});
|
|
181
191
|
|
|
182
|
-
|
|
192
|
+
<BeGenProvider designSystem={designSystem} pageContext={{ route: "/" }} classify={classify}>
|
|
193
|
+
<YourApp />
|
|
194
|
+
</BeGenProvider>
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Your endpoint can call Gemini, Claude, OpenAI, a Python service, anything. You shape the response into `AdaptationPlan` and the library handles the rest.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Quick start (no agent — heuristic / offline / demo)
|
|
202
|
+
|
|
203
|
+
Pass a function inline. No network, no LLM. Useful for demos, tests, offline dev:
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
const classify: ClassifyFn = async ({ summary }) => {
|
|
207
|
+
const engaged = summary.clicks_per_min > 6;
|
|
208
|
+
return {
|
|
209
|
+
adaptations: [
|
|
210
|
+
{
|
|
211
|
+
kind: "set-css-var",
|
|
212
|
+
selector: ":root",
|
|
213
|
+
name: "--accent",
|
|
214
|
+
value: engaged ? "#dc2626" : "#2563eb",
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
confidence: 0.8,
|
|
218
|
+
reasoning: engaged ? "Fast pace" : "Calm pace",
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
See [`examples/basic/`](./examples/basic/) for a complete runnable demo using this pattern.
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Reading state from children
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
import { useBeGenContext } from "begeniux";
|
|
231
|
+
|
|
232
|
+
function Telemetry() {
|
|
233
|
+
const { summary, lastPlan, appliedAdaptations } = useBeGenContext();
|
|
183
234
|
return (
|
|
184
|
-
<
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}}
|
|
191
|
-
variantProps={{ products }}
|
|
192
|
-
classify={classify}
|
|
193
|
-
pageContext={{
|
|
194
|
-
route: "/products",
|
|
195
|
-
visible_product_ids: products.map((p) => p.id),
|
|
196
|
-
}}
|
|
197
|
-
/>
|
|
198
|
-
</BeGenProvider>
|
|
235
|
+
<pre>
|
|
236
|
+
events: {summary?.events_seen} ·
|
|
237
|
+
clicks/min: {summary?.clicks_per_min} ·
|
|
238
|
+
reasoning: {lastPlan?.reasoning} ·
|
|
239
|
+
mutations: {appliedAdaptations.length}
|
|
240
|
+
</pre>
|
|
199
241
|
);
|
|
200
242
|
}
|
|
201
243
|
```
|
|
202
244
|
|
|
203
|
-
|
|
245
|
+
Use it for debug overlays, telemetry strips, analytics pipelines, or to make components react to the agent's reasoning.
|
|
204
246
|
|
|
205
|
-
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## API surface
|
|
206
250
|
|
|
207
251
|
| Export | What it does |
|
|
208
252
|
|---|---|
|
|
209
|
-
|
|
|
210
|
-
|
|
211
|
-
| `
|
|
212
|
-
| `useBeGenContext()` |
|
|
213
|
-
| `
|
|
214
|
-
| `
|
|
215
|
-
| `
|
|
253
|
+
| Export | Where | What it does |
|
|
254
|
+
|---|---|---|
|
|
255
|
+
| `<BeGenProvider>` | `begeniux` | The provider. Tracks behavior, holds the engine, gates triggers, runs `classify`, exposes context. Drop-in. |
|
|
256
|
+
| `useBeGenContext()` | `begeniux` | Read the latest summary, last plan, applied adaptations, plus an `applyPlan(plan)` escape hatch. |
|
|
257
|
+
| `createHttpAdapter(opts)` | `begeniux` | Returns a `ClassifyFn` that posts the `AdaptInput` to your URL. Generic transport. |
|
|
258
|
+
| `useBehaviorTracker(opts)` | `begeniux` | Low-level hook used by the provider. Reach for it if you need a tracker outside a provider context. |
|
|
259
|
+
| `AdaptationEngine` | `begeniux` | Low-level class. Apply, revert, query mutations directly if you don't want a provider at all. |
|
|
260
|
+
| `snapshotVisibleSelectors(root, opts)` | `begeniux` | Returns a list of stable CSS selectors visible in the viewport. Useful when building your own classify fn. |
|
|
261
|
+
| `<CopilotKitAdapter />` | `begeniux/copilotkit` | Mount inside `<BeGenProvider>` to register `apply_adaptations` as a CopilotKit frontend tool. |
|
|
262
|
+
| `useCopilotKitAdapter(opts)` | `begeniux/copilotkit` | Hook variant of `<CopilotKitAdapter />`. |
|
|
263
|
+
|
|
264
|
+
The `/copilotkit` subpath is split out so consumers who don't use CopilotKit don't pull `@copilotkit/react-core` (and its transitive deps like KaTeX) into their bundle.
|
|
216
265
|
|
|
217
|
-
|
|
266
|
+
All exports are documented in [`src/index.ts`](./src/index.ts).
|
|
218
267
|
|
|
219
|
-
|
|
268
|
+
---
|
|
220
269
|
|
|
221
|
-
|
|
270
|
+
## What goes in the design system
|
|
222
271
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
272
|
+
The design system is the **vocabulary the agent is allowed to speak**. Two tiers:
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
const designSystem: DesignSystem = {
|
|
276
|
+
cssVariables: {
|
|
277
|
+
"--accent": { description: "Action color", type: "color", defaultValue: "#7c3aed" },
|
|
278
|
+
"--density": { description: "Layout density", type: "length", defaultValue: "16px" },
|
|
279
|
+
"--font-scale": {
|
|
280
|
+
description: "Font multiplier",
|
|
281
|
+
type: "number",
|
|
282
|
+
range: [0.8, 1.4],
|
|
283
|
+
defaultValue: "1",
|
|
284
|
+
},
|
|
285
|
+
"--surface-emphasis": {
|
|
286
|
+
description: "Which surface gets visual emphasis",
|
|
287
|
+
type: "enum",
|
|
288
|
+
values: ["price", "reviews", "imagery", "specs"],
|
|
289
|
+
defaultValue: "price",
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
classes: {
|
|
293
|
+
"is-engaged": "Visual treatment for engaged users",
|
|
294
|
+
"is-skimming": "Visual treatment for low-engagement",
|
|
295
|
+
"is-cta-prominent": "Boost CTA emphasis",
|
|
296
|
+
},
|
|
297
|
+
examples: [
|
|
298
|
+
{
|
|
299
|
+
adaptations: [
|
|
300
|
+
{ kind: "set-css-var", selector: ":root", name: "--density", value: "10px" },
|
|
301
|
+
],
|
|
302
|
+
confidence: 0.85,
|
|
303
|
+
reasoning: "Compact dense view for engaged user.",
|
|
304
|
+
},
|
|
305
|
+
],
|
|
231
306
|
};
|
|
232
307
|
```
|
|
233
308
|
|
|
234
|
-
|
|
309
|
+
The agent receives this manifest as part of every `AdaptInput`, so it knows exactly which knobs are turnable and what each means. **Anything not declared here is invisible to the agent.** That's your safety net.
|
|
310
|
+
|
|
311
|
+
---
|
|
235
312
|
|
|
236
|
-
##
|
|
313
|
+
## Safety + scope
|
|
237
314
|
|
|
238
|
-
|
|
315
|
+
By default the provider tracks behavior on `document.body` and the agent can target any selector under it. You can narrow:
|
|
239
316
|
|
|
240
317
|
```tsx
|
|
241
|
-
<
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
318
|
+
<BeGenProvider
|
|
319
|
+
designSystem={designSystem}
|
|
320
|
+
pageContext={{ route: "/" }}
|
|
321
|
+
scope={{
|
|
322
|
+
allow: ["[data-begen-adapt]", ".product-card", ":root"],
|
|
323
|
+
deny: ["[data-checkout]", ".payment-form"],
|
|
324
|
+
}}
|
|
325
|
+
>
|
|
247
326
|
```
|
|
248
327
|
|
|
249
|
-
|
|
328
|
+
`scope.deny` is a hard veto — the engine refuses any adaptation whose selector matches a deny pattern. Use it to protect critical paths.
|
|
250
329
|
|
|
251
|
-
|
|
330
|
+
CSS-only invariants in v0.2:
|
|
252
331
|
|
|
253
|
-
|
|
332
|
+
- The engine refuses `set-style` for `display`, `position`, `visibility`, `float`, `clear`, `z-index`, `overflow*`, `transform-origin`. Use CSS variables and classes instead.
|
|
333
|
+
- The engine reverts every previous plan before applying a new one — mutations never accumulate.
|
|
334
|
+
- On unmount, every applied mutation is reverted. The page is restored.
|
|
335
|
+
- Identical consecutive plans are skipped (cheap deterministic hash).
|
|
336
|
+
- Empty plans are no-ops.
|
|
254
337
|
|
|
255
|
-
|
|
256
|
-
function TelemetryStrip() {
|
|
257
|
-
const { variant, directive, summary } = useBeGenContext();
|
|
258
|
-
return (
|
|
259
|
-
<div>
|
|
260
|
-
Mode: {variant}
|
|
261
|
-
{directive && ` · ${directive.reasoning}`}
|
|
262
|
-
{summary && ` · ${summary.events_seen} events`}
|
|
263
|
-
</div>
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
Nice for debugging, demo overlays, or analytics.
|
|
338
|
+
---
|
|
269
339
|
|
|
270
340
|
## Local development
|
|
271
341
|
|
|
272
342
|
```bash
|
|
273
|
-
git clone
|
|
274
|
-
cd
|
|
343
|
+
git clone https://github.com/WagnerAgent/BeGeniux
|
|
344
|
+
cd BeGeniux
|
|
275
345
|
npm install
|
|
276
|
-
npm run build
|
|
277
|
-
npm run dev
|
|
346
|
+
npm run build # one-shot build → dist/
|
|
347
|
+
npm run dev # tsup --watch
|
|
278
348
|
|
|
349
|
+
# Smoke test
|
|
279
350
|
cd examples/basic
|
|
280
351
|
npm install
|
|
281
|
-
npm run dev
|
|
352
|
+
npm run dev # http://localhost:5180
|
|
282
353
|
```
|
|
283
354
|
|
|
284
|
-
The example imports from `../../src/index.ts` via a Vite alias, so source changes hot-reload.
|
|
355
|
+
The example imports from `../../src/index.ts` via a Vite alias, so source changes hot-reload. No CopilotKit / LangGraph / API keys needed — the example uses an inline mock classifier.
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## Migrating from v0.1
|
|
360
|
+
|
|
361
|
+
v0.1 was a variant-picker — you handed the library `{decisive, deliberate, neutral}` components and an LLM picked one. v0.2 deletes that model entirely:
|
|
362
|
+
|
|
363
|
+
- `BeGenSurface` → removed. `BeGenProvider` is now the entire library entrypoint.
|
|
364
|
+
- `Variant` / `AgentDirective` → removed. `AdaptationPlan` is what the agent returns.
|
|
365
|
+
- `createGeminiClassifier` → removed. Browser-side LLM calls were the wrong shape; use the CopilotKit adapter or a server-side HTTP endpoint.
|
|
366
|
+
- `createHeuristicClassifier` → removed. It's a 5-line `ClassifyFn` if you still want one.
|
|
367
|
+
- `PERSONAS` → removed. `seedTrace` on the provider takes any `BehaviorEvent[]`; bring your own.
|
|
368
|
+
|
|
369
|
+
If you've already integrated v0.1, stay on v0.1.x — it's still on npm. Upgrade to v0.2 when you're ready to switch from variant-picking to live adaptation.
|
|
370
|
+
|
|
371
|
+
---
|
|
285
372
|
|
|
286
373
|
## Research lineages
|
|
287
374
|
|
|
288
|
-
|
|
375
|
+
- **Adaptive UIs** — Gajos & Weld, *SUPPLE: Automatically Generating User Interfaces* (IUI 2004)
|
|
376
|
+
- **Contextual bandits** — Li et al., *A Contextual-Bandit Approach to Personalized News Article Recommendation* (WWW 2010)
|
|
377
|
+
- **Implicit feedback** — Joachims et al., *Accurately Interpreting Clickthrough Data as Implicit Feedback* (SIGIR 2005)
|
|
378
|
+
- **In-context learning as policy** — Brown et al., *Language Models are Few-Shot Learners* (NeurIPS 2020)
|
|
289
379
|
|
|
290
|
-
|
|
291
|
-
- **Contextual bandits** — Li et al., *A Contextual-Bandit Approach to Personalized News Article Recommendation* (WWW 2010).
|
|
292
|
-
- **Implicit feedback / behavior modeling** — Joachims et al., *Accurately Interpreting Clickthrough Data as Implicit Feedback* (SIGIR 2005).
|
|
293
|
-
- **In-context learning as policy** — Brown et al., *Language Models are Few-Shot Learners* (NeurIPS 2020).
|
|
380
|
+
The novel contribution is the combination: behavioral traces as input, LLM agents as policy, session-granularity adaptation, **live DOM mutation** as output, with developer-declared design-system invariants.
|
|
294
381
|
|
|
295
|
-
|
|
382
|
+
---
|
|
296
383
|
|
|
297
384
|
## Roadmap
|
|
298
385
|
|
|
299
|
-
-
|
|
300
|
-
- **
|
|
301
|
-
-
|
|
302
|
-
|
|
303
|
-
|
|
386
|
+
- **v0.3** — Tool-calling agent loop (agent inspects DOM iteratively); structural mutations (insert, reorder, hide/show under invariant constraints); streaming AdaptationPlan events.
|
|
387
|
+
- **v0.4** — Component replacement primitive; an invariant DSL ("checkout always reachable in ≤2 clicks"); replay traces + counterfactual scoring.
|
|
388
|
+
- **v0.5** — Cross-session memory (with explicit consent); behavioral embeddings; multi-armed bandit policies as a non-LLM fallback.
|
|
389
|
+
|
|
390
|
+
---
|
|
304
391
|
|
|
305
392
|
## Contributing
|
|
306
393
|
|
|
307
|
-
PRs welcome. Keep the public
|
|
394
|
+
PRs welcome. Keep the public API minimal — anything not exported from `src/index.ts` is internal. Don't bundle React or CopilotKit. Don't assume Next.js. The library should drop into Vite, CRA, Remix, Next, or anywhere React 18+ runs.
|
|
395
|
+
|
|
396
|
+
If you're working in this repo with Claude Code (or another agent), the [`.claude/skills/`](./.claude/) directory has prebaked domain knowledge about CopilotKit, AG-UI, MCP, and LangGraph integrations — read the relevant `SKILL.md` before touching adapter code.
|
|
308
397
|
|
|
309
398
|
## License
|
|
310
399
|
|