@affectively/aeon-pages-runtime 0.5.2 → 0.7.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 +399 -0
- package/dist/chunk-439mqgjz.js +667 -0
- package/dist/chunk-7zbxm162.js +5251 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +26 -2
- package/dist/router/esi-react.d.ts +2 -0
- package/dist/router/esi-translate-observer.d.ts +153 -0
- package/dist/router/esi-translate-react.d.ts +155 -0
- package/dist/router/index.d.ts +8 -1
- package/dist/router/index.js +64 -2
- package/dist/router/merkle-capability.d.ts +145 -0
- package/dist/server.js +2 -2
- package/dist/types.d.ts +80 -1
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
# @affectively/aeon-pages-runtime
|
|
2
|
+
|
|
3
|
+
Edge-first rendering runtime for Aeon-Flux with Edge Side Inference (ESI), hyperpersonalized routing, and real-time collaboration.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @affectively/aeon-pages-runtime
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
### Edge Side Inference (ESI)
|
|
14
|
+
|
|
15
|
+
AI-powered personalization at render time. Components that adapt to user context before reaching the browser.
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { ESI, ESIProvider } from '@affectively/aeon-pages-runtime/router';
|
|
19
|
+
|
|
20
|
+
function App() {
|
|
21
|
+
return (
|
|
22
|
+
<ESIProvider>
|
|
23
|
+
{/* AI-generated personalized greeting */}
|
|
24
|
+
<ESI.Infer prompt="Greet the user based on time of day">
|
|
25
|
+
{(greeting) => <h1>{greeting}</h1>}
|
|
26
|
+
</ESI.Infer>
|
|
27
|
+
|
|
28
|
+
{/* Tier-gated content */}
|
|
29
|
+
<ESI.TierGate tier="premium">
|
|
30
|
+
<PremiumFeatures />
|
|
31
|
+
</ESI.TierGate>
|
|
32
|
+
|
|
33
|
+
{/* Emotion-aware content */}
|
|
34
|
+
<ESI.EmotionGate emotions={['calm', 'content']}>
|
|
35
|
+
<RelaxingContent />
|
|
36
|
+
</ESI.EmotionGate>
|
|
37
|
+
</ESIProvider>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### AI Translation
|
|
43
|
+
|
|
44
|
+
Automatic translation at the edge. Supports 33 languages with LLM-based translation.
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { ESI, TranslationProvider } from '@affectively/aeon-pages-runtime/router';
|
|
48
|
+
|
|
49
|
+
// App-wide translation with user's preferred language
|
|
50
|
+
function App() {
|
|
51
|
+
return (
|
|
52
|
+
<TranslationProvider defaultLanguage="es">
|
|
53
|
+
<ESI.Translate>Welcome to our platform</ESI.Translate>
|
|
54
|
+
{/* Renders: "Bienvenido a nuestra plataforma" */}
|
|
55
|
+
</TranslationProvider>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Explicit target language
|
|
60
|
+
<ESI.Translate targetLanguage="ja">Hello world</ESI.Translate>
|
|
61
|
+
// Renders: "こんにちは世界"
|
|
62
|
+
|
|
63
|
+
// With context for better translation quality
|
|
64
|
+
<ESI.Translate
|
|
65
|
+
targetLanguage="fr"
|
|
66
|
+
context="emotional wellness app"
|
|
67
|
+
>
|
|
68
|
+
We're here to help you understand your feelings.
|
|
69
|
+
</ESI.Translate>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
#### Data-Attribute Translation
|
|
73
|
+
|
|
74
|
+
Automatically translate any element with `data-translate`:
|
|
75
|
+
|
|
76
|
+
```html
|
|
77
|
+
<p data-translate data-target-lang="es">Hello world</p>
|
|
78
|
+
<!-- Becomes: "Hola mundo" -->
|
|
79
|
+
|
|
80
|
+
<span data-translate data-translate-context="formal, business">
|
|
81
|
+
Please review the attached document.
|
|
82
|
+
</span>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import { useTranslationObserver } from '@affectively/aeon-pages-runtime/router';
|
|
87
|
+
|
|
88
|
+
function App() {
|
|
89
|
+
// Automatically translates all data-translate elements
|
|
90
|
+
useTranslationObserver({ defaultTargetLanguage: 'es' });
|
|
91
|
+
|
|
92
|
+
return <div data-translate>Hello</div>;
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
#### Language Configuration Priority
|
|
97
|
+
|
|
98
|
+
1. `ESI.Translate` `targetLanguage` prop
|
|
99
|
+
2. `TranslationProvider` context
|
|
100
|
+
3. `window.__AEON_ESI_STATE__.preferences.language`
|
|
101
|
+
4. `<meta name="aeon-language" content="es">`
|
|
102
|
+
5. User preferences
|
|
103
|
+
6. Browser `navigator.language`
|
|
104
|
+
|
|
105
|
+
#### Supported Languages
|
|
106
|
+
|
|
107
|
+
`en`, `es`, `fr`, `de`, `it`, `pt`, `nl`, `pl`, `ru`, `zh`, `ja`, `ko`, `ar`, `hi`, `bn`, `vi`, `th`, `tr`, `id`, `ms`, `tl`, `sv`, `da`, `no`, `fi`, `cs`, `el`, `he`, `uk`, `ro`, `hu`, `ca`, `hy`
|
|
108
|
+
|
|
109
|
+
### Hyperpersonalized Routing
|
|
110
|
+
|
|
111
|
+
Routes adapt to user context: time, location, emotion state, and tier.
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
import { HeuristicAdapter } from '@affectively/aeon-pages-runtime/router';
|
|
115
|
+
|
|
116
|
+
const adapter = new HeuristicAdapter({
|
|
117
|
+
tierFeatures: {
|
|
118
|
+
free: { maxAIInferences: 5 },
|
|
119
|
+
premium: { maxAIInferences: 100 },
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Route decision based on user context
|
|
124
|
+
const decision = await adapter.decide(userContext, '/dashboard');
|
|
125
|
+
// Returns: layout, theme, skeleton hints, prefetch suggestions
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Speculative Pre-rendering
|
|
129
|
+
|
|
130
|
+
Pages render before you click. Zero perceived latency.
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
import { SpeculationManager, autoInitSpeculation } from '@affectively/aeon-pages-runtime/router';
|
|
134
|
+
|
|
135
|
+
// Auto-initialize based on browser support
|
|
136
|
+
autoInitSpeculation();
|
|
137
|
+
|
|
138
|
+
// Or manual control
|
|
139
|
+
const speculation = new SpeculationManager({
|
|
140
|
+
prefetchUrls: ['/dashboard', '/settings'],
|
|
141
|
+
prerenderUrls: ['/about'],
|
|
142
|
+
});
|
|
143
|
+
speculation.start();
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### ESI Control Components
|
|
147
|
+
|
|
148
|
+
Declarative control flow with AI-powered conditions.
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
import { ESI } from '@affectively/aeon-pages-runtime/router';
|
|
152
|
+
|
|
153
|
+
// Conditional rendering
|
|
154
|
+
<ESI.If condition="user.tier === 'premium'">
|
|
155
|
+
<PremiumBadge />
|
|
156
|
+
</ESI.If>
|
|
157
|
+
|
|
158
|
+
// Pattern matching
|
|
159
|
+
<ESI.Match value={userEmotion}>
|
|
160
|
+
<ESI.Case when="happy"><HappyContent /></ESI.Case>
|
|
161
|
+
<ESI.Case when="sad"><SupportContent /></ESI.Case>
|
|
162
|
+
<ESI.Default><NeutralContent /></ESI.Default>
|
|
163
|
+
</ESI.Match>
|
|
164
|
+
|
|
165
|
+
// Time-based gates
|
|
166
|
+
<ESI.TimeGate hours={{ start: 9, end: 17 }}>
|
|
167
|
+
<BusinessHoursContent />
|
|
168
|
+
</ESI.TimeGate>
|
|
169
|
+
|
|
170
|
+
// A/B Testing
|
|
171
|
+
<ESI.ABTest variants={['control', 'variant-a', 'variant-b']}>
|
|
172
|
+
{(variant) => <Component variant={variant} />}
|
|
173
|
+
</ESI.ABTest>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Cyrano Whisper Channel
|
|
177
|
+
|
|
178
|
+
AI assistant guidance with contextual awareness.
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
import { esiCyrano, esiHalo } from '@affectively/aeon-pages-runtime/router';
|
|
182
|
+
|
|
183
|
+
// Generate AI whisper for user guidance
|
|
184
|
+
const whisper = esiCyrano({
|
|
185
|
+
intent: 'guide',
|
|
186
|
+
tone: 'warm',
|
|
187
|
+
context: sessionContext,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Halo insights for behavioral patterns
|
|
191
|
+
const insight = esiHalo({
|
|
192
|
+
observation: 'user-hesitation',
|
|
193
|
+
action: 'offer-help',
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Merkle-Based UCAN Capabilities
|
|
198
|
+
|
|
199
|
+
Fine-grained access control to component nodes using Merkle hashes. Integrates with UCAN tokens for cryptographic authorization.
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
import {
|
|
203
|
+
createNodeCapabilityVerifier,
|
|
204
|
+
createNodeReadCapability,
|
|
205
|
+
createTreeCapability,
|
|
206
|
+
checkNodeAccess,
|
|
207
|
+
} from '@affectively/aeon-pages-runtime';
|
|
208
|
+
|
|
209
|
+
// Create capabilities for specific nodes by Merkle hash
|
|
210
|
+
const readCapability = createNodeReadCapability('a1b2c3d4e5f6');
|
|
211
|
+
// { can: 'aeon:node:read', with: 'merkle:a1b2c3d4e5f6' }
|
|
212
|
+
|
|
213
|
+
// Create tree capability (grants access to node and all descendants)
|
|
214
|
+
const treeCapability = createTreeCapability('a1b2c3d4e5f6');
|
|
215
|
+
// { can: 'aeon:node:*', with: 'tree:a1b2c3d4e5f6' }
|
|
216
|
+
|
|
217
|
+
// Create path-based capability (grants access to all nodes on a route)
|
|
218
|
+
const pathCapability = createPathCapability('/dashboard/*');
|
|
219
|
+
// { can: 'aeon:node:*', with: 'path:/dashboard/*' }
|
|
220
|
+
|
|
221
|
+
// Verify access to a specific node
|
|
222
|
+
const canAccess = checkNodeAccess(
|
|
223
|
+
userCapabilities,
|
|
224
|
+
{ merkleHash: 'a1b2c3d4e5f6', routePath: '/dashboard' },
|
|
225
|
+
'read'
|
|
226
|
+
);
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### Resource Formats
|
|
230
|
+
|
|
231
|
+
| Format | Example | Description |
|
|
232
|
+
|--------|---------|-------------|
|
|
233
|
+
| `merkle:<hash>` | `merkle:a1b2c3d4e5f6` | Exact match on Merkle hash |
|
|
234
|
+
| `tree:<hash>` | `tree:a1b2c3d4e5f6` | Match node or any ancestor |
|
|
235
|
+
| `path:<route>` | `path:/dashboard/*` | All nodes on a route (wildcards) |
|
|
236
|
+
| `*` | `*` | Match any node (wildcard) |
|
|
237
|
+
|
|
238
|
+
#### Capability Actions
|
|
239
|
+
|
|
240
|
+
| Action | Description |
|
|
241
|
+
|--------|-------------|
|
|
242
|
+
| `aeon:node:read` | Read access to node |
|
|
243
|
+
| `aeon:node:write` | Write access to node |
|
|
244
|
+
| `aeon:node:*` | Full access to node |
|
|
245
|
+
|
|
246
|
+
#### Creating a Verifier from UCAN Token
|
|
247
|
+
|
|
248
|
+
```tsx
|
|
249
|
+
import { createNodeCapabilityVerifier } from '@affectively/aeon-pages-runtime';
|
|
250
|
+
|
|
251
|
+
const verifier = createNodeCapabilityVerifier(token, {
|
|
252
|
+
extractCapabilities: async (t) => {
|
|
253
|
+
const decoded = await decodeUCAN(t);
|
|
254
|
+
return decoded.capabilities;
|
|
255
|
+
},
|
|
256
|
+
verifyToken: async (t) => {
|
|
257
|
+
return await verifyUCANSignature(t);
|
|
258
|
+
},
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// Check if user can read a specific node
|
|
262
|
+
const canRead = await verifier(
|
|
263
|
+
{ merkleHash: 'a1b2c3d4e5f6' },
|
|
264
|
+
'read'
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
// Check with full tree path context
|
|
268
|
+
const canWrite = await verifier(
|
|
269
|
+
{
|
|
270
|
+
merkleHash: 'a1b2c3d4e5f6',
|
|
271
|
+
treePath: ['root', 'layout', 'header', 'button'],
|
|
272
|
+
ancestorHashes: ['f1e2d3c4b5a6', 'b2c3d4e5f6a1'],
|
|
273
|
+
routePath: '/dashboard',
|
|
274
|
+
},
|
|
275
|
+
'write'
|
|
276
|
+
);
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### Integration with Analytics
|
|
280
|
+
|
|
281
|
+
Merkle capabilities integrate seamlessly with `@affectively/aeon-pages-analytics`:
|
|
282
|
+
|
|
283
|
+
```tsx
|
|
284
|
+
import { buildMerkleTreeSync } from '@affectively/aeon-pages-analytics';
|
|
285
|
+
import { checkNodeAccess } from '@affectively/aeon-pages-runtime';
|
|
286
|
+
|
|
287
|
+
// Build Merkle tree from component tree
|
|
288
|
+
const merkleTree = buildMerkleTreeSync(componentTree);
|
|
289
|
+
|
|
290
|
+
// Check access for each node
|
|
291
|
+
for (const [nodeId, merkleNode] of merkleTree) {
|
|
292
|
+
const canEdit = checkNodeAccess(
|
|
293
|
+
userCapabilities,
|
|
294
|
+
{
|
|
295
|
+
merkleHash: merkleNode.hash,
|
|
296
|
+
treePath: merkleNode.path,
|
|
297
|
+
routePath: currentRoute,
|
|
298
|
+
},
|
|
299
|
+
'write'
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
if (canEdit) {
|
|
303
|
+
// Show edit controls for this node
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## API Reference
|
|
309
|
+
|
|
310
|
+
### Components
|
|
311
|
+
|
|
312
|
+
| Component | Description |
|
|
313
|
+
|-----------|-------------|
|
|
314
|
+
| `ESI.Provider` | Root ESI context provider |
|
|
315
|
+
| `ESI.Infer` | AI inference at render time |
|
|
316
|
+
| `ESI.Translate` | Automatic translation |
|
|
317
|
+
| `ESI.TranslationProvider` | App-wide translation context |
|
|
318
|
+
| `ESI.TierGate` | Tier-based content gating |
|
|
319
|
+
| `ESI.EmotionGate` | Emotion-based content gating |
|
|
320
|
+
| `ESI.TimeGate` | Time-based content gating |
|
|
321
|
+
| `ESI.If` / `ESI.Show` / `ESI.Hide` | Conditional rendering |
|
|
322
|
+
| `ESI.Match` / `ESI.Case` | Pattern matching |
|
|
323
|
+
| `ESI.ABTest` | A/B testing |
|
|
324
|
+
| `ESI.ForEach` | AI-powered iteration |
|
|
325
|
+
| `ESI.Select` | AI-powered selection |
|
|
326
|
+
|
|
327
|
+
### Hooks
|
|
328
|
+
|
|
329
|
+
| Hook | Description |
|
|
330
|
+
|------|-------------|
|
|
331
|
+
| `useESI()` | Access ESI context and processing |
|
|
332
|
+
| `useESIInfer()` | AI inference hook |
|
|
333
|
+
| `useTranslation()` | Translation context access |
|
|
334
|
+
| `useTranslationObserver()` | Auto-translate data-attribute elements |
|
|
335
|
+
| `useGlobalESIState()` | Access global ESI state |
|
|
336
|
+
| `useESITier()` | Get current user tier |
|
|
337
|
+
| `useESIEmotionState()` | Get current emotion state |
|
|
338
|
+
|
|
339
|
+
### Functions
|
|
340
|
+
|
|
341
|
+
| Function | Description |
|
|
342
|
+
|----------|-------------|
|
|
343
|
+
| `esiTranslate()` | Create translation directive |
|
|
344
|
+
| `translateWithAIGateway()` | Direct AI Gateway translation |
|
|
345
|
+
| `normalizeLanguageCode()` | Normalize language code |
|
|
346
|
+
| `getSupportedLanguages()` | Get list of supported languages |
|
|
347
|
+
| `initTranslationObserver()` | Auto-init DOM translation observer |
|
|
348
|
+
|
|
349
|
+
### Merkle Capability Functions
|
|
350
|
+
|
|
351
|
+
| Function | Description |
|
|
352
|
+
|----------|-------------|
|
|
353
|
+
| `createNodeReadCapability(hash)` | Create read capability for a Merkle hash |
|
|
354
|
+
| `createNodeWriteCapability(hash)` | Create write capability for a Merkle hash |
|
|
355
|
+
| `createTreeCapability(hash, action)` | Create tree capability (node + descendants) |
|
|
356
|
+
| `createPathCapability(path, action)` | Create path-based capability |
|
|
357
|
+
| `createWildcardNodeCapability(action)` | Create wildcard capability (all nodes) |
|
|
358
|
+
| `createNodeCapabilityVerifier(token, opts)` | Create verifier from UCAN token |
|
|
359
|
+
| `checkNodeAccess(caps, request, action)` | Check if capabilities grant access |
|
|
360
|
+
| `filterAccessibleNodes(nodes, caps, action)` | Filter nodes by access |
|
|
361
|
+
| `getMostSpecificCapability(caps, request)` | Get most specific matching capability |
|
|
362
|
+
| `parseResource(resource)` | Parse resource identifier |
|
|
363
|
+
| `formatResource(type, value)` | Format resource identifier |
|
|
364
|
+
| `capabilityGrantsAccess(cap, request, action)` | Check single capability |
|
|
365
|
+
|
|
366
|
+
## Configuration
|
|
367
|
+
|
|
368
|
+
### Head Meta Tags
|
|
369
|
+
|
|
370
|
+
```html
|
|
371
|
+
<!-- Default translation language -->
|
|
372
|
+
<meta name="aeon-language" content="es">
|
|
373
|
+
|
|
374
|
+
<!-- Translation endpoint -->
|
|
375
|
+
<meta name="aeon-translation-endpoint" content="https://ai-gateway.example.com">
|
|
376
|
+
|
|
377
|
+
<!-- Cache TTL in seconds -->
|
|
378
|
+
<meta name="aeon-translation-cache-ttl" content="86400">
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### ESI State
|
|
382
|
+
|
|
383
|
+
Global state is available at `window.__AEON_ESI_STATE__`:
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
interface GlobalESIState {
|
|
387
|
+
tier: 'free' | 'premium' | 'enterprise';
|
|
388
|
+
emotion: EmotionState;
|
|
389
|
+
preferences: {
|
|
390
|
+
language: string;
|
|
391
|
+
theme: 'light' | 'dark' | 'system';
|
|
392
|
+
};
|
|
393
|
+
features: Record<string, boolean>;
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
## License
|
|
398
|
+
|
|
399
|
+
MIT
|