@runtypelabs/persona 1.48.0 → 2.1.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 +140 -8
- package/dist/index.cjs +90 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1098 -24
- package/dist/index.d.ts +1098 -24
- package/dist/index.global.js +134 -83
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +90 -39
- package/dist/index.js.map +1 -1
- package/dist/install.global.js +1 -1
- package/dist/install.global.js.map +1 -1
- package/dist/widget.css +849 -513
- package/package.json +1 -1
- package/src/artifacts-session.test.ts +80 -0
- package/src/client.test.ts +20 -21
- package/src/client.ts +153 -4
- package/src/components/approval-bubble.ts +45 -42
- package/src/components/artifact-card.ts +91 -0
- package/src/components/artifact-pane.ts +501 -0
- package/src/components/composer-builder.ts +32 -27
- package/src/components/event-stream-view.ts +40 -40
- package/src/components/feedback.ts +36 -36
- package/src/components/forms.ts +11 -11
- package/src/components/header-builder.test.ts +32 -0
- package/src/components/header-builder.ts +55 -36
- package/src/components/header-layouts.ts +58 -125
- package/src/components/launcher.ts +36 -21
- package/src/components/message-bubble.ts +92 -65
- package/src/components/messages.ts +2 -2
- package/src/components/panel.ts +42 -11
- package/src/components/reasoning-bubble.ts +23 -23
- package/src/components/registry.ts +4 -0
- package/src/components/suggestions.ts +1 -1
- package/src/components/tool-bubble.ts +32 -32
- package/src/defaults.ts +30 -4
- package/src/index.ts +80 -2
- package/src/install.ts +22 -0
- package/src/plugins/types.ts +23 -0
- package/src/postprocessors.ts +2 -2
- package/src/runtime/host-layout.ts +174 -0
- package/src/runtime/init.test.ts +236 -0
- package/src/runtime/init.ts +114 -55
- package/src/session.ts +135 -2
- package/src/styles/tailwind.css +1 -1
- package/src/styles/widget.css +849 -513
- package/src/types/theme.ts +376 -0
- package/src/types.ts +338 -15
- package/src/ui.docked.test.ts +104 -0
- package/src/ui.ts +940 -227
- package/src/utils/artifact-gate.test.ts +255 -0
- package/src/utils/artifact-gate.ts +142 -0
- package/src/utils/artifact-resize.test.ts +64 -0
- package/src/utils/artifact-resize.ts +67 -0
- package/src/utils/attachment-manager.ts +10 -10
- package/src/utils/code-generators.test.ts +52 -0
- package/src/utils/code-generators.ts +40 -36
- package/src/utils/dock.ts +17 -0
- package/src/utils/dom-context.test.ts +504 -0
- package/src/utils/dom-context.ts +896 -0
- package/src/utils/dom.ts +12 -1
- package/src/utils/message-fingerprint.test.ts +187 -0
- package/src/utils/message-fingerprint.ts +105 -0
- package/src/utils/migration.ts +220 -0
- package/src/utils/morph.ts +1 -1
- package/src/utils/plugins.ts +175 -0
- package/src/utils/positioning.ts +4 -4
- package/src/utils/theme.test.ts +157 -0
- package/src/utils/theme.ts +224 -60
- package/src/utils/tokens.ts +701 -0
package/README.md
CHANGED
|
@@ -64,6 +64,24 @@ const controller = initAgentWidget({
|
|
|
64
64
|
document.querySelector('#dark-mode')?.addEventListener('click', () => {
|
|
65
65
|
controller.update({ theme: { surface: '#0f172a', primary: '#f8fafc' } });
|
|
66
66
|
});
|
|
67
|
+
|
|
68
|
+
// Docked panel that wraps a concrete workspace container
|
|
69
|
+
const docked = initAgentWidget({
|
|
70
|
+
target: '#workspace-main',
|
|
71
|
+
config: {
|
|
72
|
+
...DEFAULT_WIDGET_CONFIG,
|
|
73
|
+
apiUrl: proxyUrl,
|
|
74
|
+
launcher: {
|
|
75
|
+
...DEFAULT_WIDGET_CONFIG.launcher,
|
|
76
|
+
mountMode: 'docked',
|
|
77
|
+
dock: {
|
|
78
|
+
side: 'right',
|
|
79
|
+
width: '420px',
|
|
80
|
+
collapsedWidth: '72px'
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
67
85
|
```
|
|
68
86
|
|
|
69
87
|
### Initialization options
|
|
@@ -78,6 +96,8 @@ document.querySelector('#dark-mode')?.addEventListener('click', () => {
|
|
|
78
96
|
| `onReady` | `() => void` | Callback fired when widget is initialized. |
|
|
79
97
|
| `windowKey` | `string` | If provided, stores the controller on `window[windowKey]` for global access. Automatically cleaned up on `destroy()`. |
|
|
80
98
|
|
|
99
|
+
When `config.launcher.mountMode` is `'docked'`, `target` is treated as the page container that Persona should wrap. Use a concrete element such as `#workspace-main`; `body` and `html` are rejected.
|
|
100
|
+
|
|
81
101
|
> **Security note:** When you return HTML from `postprocessMessage`, make sure you sanitise it before injecting into the page. The provided postprocessors (`markdownPostprocessor`, `directivePostprocessor`) do not perform sanitisation.
|
|
82
102
|
|
|
83
103
|
|
|
@@ -324,6 +344,71 @@ const chat = initAgentWidget({ /* ... */ })
|
|
|
324
344
|
window.chatController = chat
|
|
325
345
|
```
|
|
326
346
|
|
|
347
|
+
### Enriched DOM context
|
|
348
|
+
|
|
349
|
+
Use `collectEnrichedPageContext` and `formatEnrichedContext` to summarize the visible page for tools or metadata (selectors, roles, text, and optional structured card summaries). By default the collector runs in **structured** mode: it gathers candidates, scores them with built-in `ParseRule` definitions in `defaultParseRules` (product/result-style cards), suppresses redundant descendants, then applies `maxElements`. Pass `options: { mode: "simple" }` for the legacy path (traverse with an early cap only, no rules or `formattedSummary`).
|
|
350
|
+
|
|
351
|
+
```ts
|
|
352
|
+
import {
|
|
353
|
+
collectEnrichedPageContext,
|
|
354
|
+
formatEnrichedContext,
|
|
355
|
+
defaultParseRules
|
|
356
|
+
} from '@runtypelabs/persona';
|
|
357
|
+
|
|
358
|
+
const elements = collectEnrichedPageContext({
|
|
359
|
+
options: {
|
|
360
|
+
mode: 'structured',
|
|
361
|
+
maxElements: 80,
|
|
362
|
+
excludeSelector: '.persona-host',
|
|
363
|
+
maxTextLength: 200,
|
|
364
|
+
visibleOnly: true
|
|
365
|
+
},
|
|
366
|
+
rules: defaultParseRules
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
const pageContext = formatEnrichedContext(elements);
|
|
370
|
+
// Structured mode: "Structured summaries:" blocks for matched cards, then grouped interactivity sections.
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
- Omit both `options` and `rules` → structured defaults (`defaultParseRules`, sensible limits).
|
|
374
|
+
- `options: { mode: 'structured' }` → explicit structured behavior (same as default).
|
|
375
|
+
- `rules: [...]` → custom rules with default options.
|
|
376
|
+
- `options: { mode: 'simple' }` → no relation-based scoring or rule-owned formatting. If you also pass `rules`, they are ignored and a console warning is emitted.
|
|
377
|
+
|
|
378
|
+
Pass `formatEnrichedContext(elements, { mode: 'simple' })` to ignore any `formattedSummary` fields on elements (for example when re-formatting data collected earlier).
|
|
379
|
+
|
|
380
|
+
**Where things live:** `defaultParseRules` and the rule/config types are part of the public package API — import them from `@runtypelabs/persona` (same entry as `collectEnrichedPageContext`). Exported names you will use most often:
|
|
381
|
+
|
|
382
|
+
| Export | Role |
|
|
383
|
+
| --- | --- |
|
|
384
|
+
| `defaultParseRules` | Built-in `ParseRule[]` (commerce-style cards + generic result rows). |
|
|
385
|
+
| `ParseRule` | Type for a custom rule: `id`, `scoreElement`, optional `shouldSuppressDescendant`, optional `formatSummary`. |
|
|
386
|
+
| `RuleScoringContext` | Argument to rule hooks (`doc`, `maxTextLength`). |
|
|
387
|
+
| `ParseOptionsConfig` | `mode`, `maxElements`, `maxCandidates`, `excludeSelector`, `maxTextLength`, `visibleOnly`, `root`. |
|
|
388
|
+
| `DomContextOptions` | What you pass to `collectEnrichedPageContext` (`options`, `rules`, plus legacy top-level limits). |
|
|
389
|
+
| `FormatEnrichedContextOptions` | Second argument to `formatEnrichedContext` (`mode`). |
|
|
390
|
+
| `EnrichedPageElement` | One collected node; optional `formattedSummary` in structured mode. |
|
|
391
|
+
|
|
392
|
+
Use **Go to definition** (or open `node_modules/@runtypelabs/persona/dist/index.d.ts` after install) for the authoritative field list and JSDoc. Implementation source in this repo: `packages/widget/src/utils/dom-context.ts`.
|
|
393
|
+
|
|
394
|
+
Custom rule sketch:
|
|
395
|
+
|
|
396
|
+
```ts
|
|
397
|
+
import type { ParseRule } from '@runtypelabs/persona';
|
|
398
|
+
|
|
399
|
+
const myRules: ParseRule[] = [
|
|
400
|
+
{
|
|
401
|
+
id: 'kpi-tile',
|
|
402
|
+
scoreElement: (el, enriched, ctx) =>
|
|
403
|
+
el.classList.contains('kpi-tile') ? 2000 : 0,
|
|
404
|
+
formatSummary: (el, enriched, ctx) =>
|
|
405
|
+
el.classList.contains('kpi-tile')
|
|
406
|
+
? `${enriched.text.trim()}\nselector: ${enriched.selector}`
|
|
407
|
+
: null
|
|
408
|
+
}
|
|
409
|
+
];
|
|
410
|
+
```
|
|
411
|
+
|
|
327
412
|
### DOM Events
|
|
328
413
|
|
|
329
414
|
The widget dispatches custom DOM events that you can listen to for integration with your application:
|
|
@@ -1337,10 +1422,21 @@ Use agent loop execution instead of flow dispatch. Mutually exclusive with `flow
|
|
|
1337
1422
|
|
|
1338
1423
|
| Property | Type | Description |
|
|
1339
1424
|
| --- | --- | --- |
|
|
1340
|
-
| `
|
|
1341
|
-
| `
|
|
1425
|
+
| `maxTurns` | `number` | Maximum number of agent turns (1-100). The loop continues while the model calls tools. |
|
|
1426
|
+
| `maxCost` | `number?` | Maximum cost budget in USD. Agent stops when exceeded. |
|
|
1342
1427
|
| `enableReflection` | `boolean?` | Enable periodic reflection during execution. |
|
|
1343
|
-
| `reflectionInterval` | `number?` | Number of iterations between reflections. |
|
|
1428
|
+
| `reflectionInterval` | `number?` | Number of iterations between reflections (1-50). |
|
|
1429
|
+
|
|
1430
|
+
**`AgentToolsConfig`**
|
|
1431
|
+
|
|
1432
|
+
| Property | Type | Description |
|
|
1433
|
+
| --- | --- | --- |
|
|
1434
|
+
| `toolIds` | `string[]?` | Tool IDs to enable (e.g., `"builtin:exa"`, `"builtin:dalle"`). |
|
|
1435
|
+
| `toolConfigs` | `Record<string, Record<string, unknown>>?` | Per-tool configuration overrides keyed by tool ID. |
|
|
1436
|
+
| `runtimeTools` | `Array<Record<string, unknown>>?` | Inline tool definitions for runtime-defined tools. |
|
|
1437
|
+
| `mcpServers` | `Array<Record<string, unknown>>?` | Custom MCP server connections. |
|
|
1438
|
+
| `maxToolCalls` | `number?` | Maximum number of tool invocations per execution. |
|
|
1439
|
+
| `approval` | `{ require: string[] \| boolean; timeout?: number }?` | Tool approval configuration for human-in-the-loop workflows. |
|
|
1344
1440
|
|
|
1345
1441
|
**`AgentRequestOptions`**
|
|
1346
1442
|
|
|
@@ -1354,10 +1450,11 @@ Use agent loop execution instead of flow dispatch. Mutually exclusive with `flow
|
|
|
1354
1450
|
```typescript
|
|
1355
1451
|
config: {
|
|
1356
1452
|
agent: {
|
|
1357
|
-
name: 'Assistant',
|
|
1358
|
-
model: '
|
|
1359
|
-
systemPrompt: 'You are a
|
|
1360
|
-
|
|
1453
|
+
name: 'Research Assistant',
|
|
1454
|
+
model: 'qwen/qwen3-8b',
|
|
1455
|
+
systemPrompt: 'You are a research assistant with access to web search.',
|
|
1456
|
+
tools: { toolIds: ['builtin:exa'] },
|
|
1457
|
+
loopConfig: { maxTurns: 5 }
|
|
1361
1458
|
},
|
|
1362
1459
|
agentOptions: { streamResponse: true, recordMode: 'virtual' },
|
|
1363
1460
|
iterationDisplay: 'merged'
|
|
@@ -1393,6 +1490,8 @@ Controls the floating launcher button and panel.
|
|
|
1393
1490
|
| `subtitle` | `string?` | Launcher header subtitle text. |
|
|
1394
1491
|
| `iconUrl` | `string?` | URL for the launcher icon image. |
|
|
1395
1492
|
| `position` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'?` | Screen corner position. |
|
|
1493
|
+
| `mountMode` | `'floating' \| 'docked'?` | Mount as the existing floating launcher or wrap the target with a docked side panel. Default: `'floating'`. |
|
|
1494
|
+
| `dock` | `{ side?: 'left' \| 'right'; width?: string; collapsedWidth?: string }?` | Docked panel sizing and side. Defaults: right / `420px` / `72px`. |
|
|
1396
1495
|
| `width` | `string?` | Width of the launcher button. |
|
|
1397
1496
|
| `fullHeight` | `boolean?` | Fill the full height of the container. Default: `false`. |
|
|
1398
1497
|
| `sidebarMode` | `boolean?` | Flush sidebar layout with no border-radius or margins. Default: `false`. |
|
|
@@ -1402,6 +1501,8 @@ Controls the floating launcher button and panel.
|
|
|
1402
1501
|
| `border` | `string?` | Border style for the launcher button. Default: `'1px solid #e5e7eb'`. |
|
|
1403
1502
|
| `shadow` | `string?` | Box shadow for the launcher button. |
|
|
1404
1503
|
|
|
1504
|
+
In docked mode, `position`, `fullHeight`, and `sidebarMode` are ignored because the widget fills the dock slot created around the target container.
|
|
1505
|
+
|
|
1405
1506
|
#### Layout
|
|
1406
1507
|
|
|
1407
1508
|
| Option | Type | Description |
|
|
@@ -1422,7 +1523,7 @@ Controls the floating launcher button and panel.
|
|
|
1422
1523
|
|
|
1423
1524
|
| Property | Type | Description |
|
|
1424
1525
|
| --- | --- | --- |
|
|
1425
|
-
| `layout` | `'default' \| 'minimal'
|
|
1526
|
+
| `layout` | `'default' \| 'minimal'?` | Header preset. |
|
|
1426
1527
|
| `showIcon` | `boolean?` | Show/hide the header icon. |
|
|
1427
1528
|
| `showTitle` | `boolean?` | Show/hide the title. |
|
|
1428
1529
|
| `showSubtitle` | `boolean?` | Show/hide the subtitle. |
|
|
@@ -1662,6 +1763,37 @@ config: {
|
|
|
1662
1763
|
| `showToolCalls` | `boolean?` | Show tool usage bubbles. Default: `true`. |
|
|
1663
1764
|
| `showEventStreamToggle` | `boolean?` | Show the event stream inspector toggle in the header. Default: `false`. |
|
|
1664
1765
|
| `eventStream` | `EventStreamConfig?` | Event stream inspector configuration: `badgeColors`, `timestampFormat`, `showSequenceNumbers`, `maxEvents`, `descriptionFields`, `classNames`. |
|
|
1766
|
+
| `artifacts` | `AgentWidgetArtifactsFeature?` | Artifact sidebar: `enabled`, `allowedTypes`, optional `layout` (see below). |
|
|
1767
|
+
|
|
1768
|
+
**`features.artifacts`** — `AgentWidgetArtifactsFeature`
|
|
1769
|
+
|
|
1770
|
+
| Property | Type | Description |
|
|
1771
|
+
| --- | --- | --- |
|
|
1772
|
+
| `enabled` | `boolean?` | When `true`, shows the artifact pane and handles `artifact_*` SSE events. |
|
|
1773
|
+
| `allowedTypes` | `('markdown' \| 'component')[]?` | If set, other artifact kinds are ignored client-side. |
|
|
1774
|
+
| `layout` | `AgentWidgetArtifactsLayoutConfig?` | Split/drawer sizing and launcher widen behavior. |
|
|
1775
|
+
|
|
1776
|
+
**`features.artifacts.layout`** — `AgentWidgetArtifactsLayoutConfig`
|
|
1777
|
+
|
|
1778
|
+
| Property | Type | Description |
|
|
1779
|
+
| --- | --- | --- |
|
|
1780
|
+
| `splitGap` | `string?` | CSS gap between chat column and artifact pane. Default: `0.5rem`. |
|
|
1781
|
+
| `paneWidth` | `string?` | Artifact column width in split mode. Default: `40%`. |
|
|
1782
|
+
| `paneMaxWidth` | `string?` | Max width of artifact column. Default: `28rem`. |
|
|
1783
|
+
| `paneMinWidth` | `string?` | Optional min width of artifact column. |
|
|
1784
|
+
| `narrowHostMaxWidth` | `number?` | If the **panel** is at most this many px wide, artifacts use an in-panel drawer instead of split. Default: `520`. |
|
|
1785
|
+
| `expandLauncherPanelWhenOpen` | `boolean?` | When not `false`, the floating panel grows while artifacts are visible (not user-dismissed). Default: widens for launcher mode. |
|
|
1786
|
+
| `expandedPanelWidth` | `string?` | CSS width when expanded. Default: `min(720px, calc(100vw - 24px))`. |
|
|
1787
|
+
| `resizable` | `boolean?` | When `true`, draggable handle between chat and artifact in desktop split mode. Default: `false`. |
|
|
1788
|
+
| `resizableMinWidth` | `string?` | Min artifact width while resizing; `px` only (e.g. `"200px"`). Default: `200px`. |
|
|
1789
|
+
| `resizableMaxWidth` | `string?` | Optional max artifact width cap (`px` only); layout still limits by panel width. |
|
|
1790
|
+
| `paneAppearance` | `'panel' \| 'seamless'?` | `panel` (default) — bordered sidebar with left border, gap, and shadow. `seamless` — flush with chat: no border or shadow, container background, zero gap (with `resizable`, the drag handle overlays the seam). |
|
|
1791
|
+
| `paneBorderRadius` | `string?` | Border radius on the artifact pane. Works with any `paneAppearance`. |
|
|
1792
|
+
| `paneShadow` | `string?` | CSS `box-shadow` on the artifact pane. Set `"none"` to suppress the default shadow. |
|
|
1793
|
+
| `paneBorder` | `string?` | Full CSS `border` shorthand on the artifact pane (e.g. `"1px solid #cccccc"`). Overrides default/`rounded` borders. If set, `paneBorderLeft` is ignored. |
|
|
1794
|
+
| `paneBorderLeft` | `string?` | `border-left` shorthand only — typical for the split edge next to chat (works with or without `resizable`). Example: `"1px solid #cccccc"`. |
|
|
1795
|
+
| `unifiedSplitChrome` | `boolean?` | Desktop split only: square the main chat card’s **top-right / bottom-right** radii and round the artifact pane’s **top-right / bottom-right** to match the panel (`--persona-radius-lg`) so both columns read as one shell. |
|
|
1796
|
+
| `unifiedSplitOuterRadius` | `string?` | Outer-right radius on the artifact side when `unifiedSplitChrome` is true. If omitted, uses `--persona-radius-lg`, or `paneBorderRadius` when `paneAppearance: 'rounded'`. |
|
|
1665
1797
|
|
|
1666
1798
|
#### State & Storage
|
|
1667
1799
|
|