@agent-native/core 0.153.6 → 0.153.9
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/corpus/templates/slides/app/components/editor/SlideEditor.tsx +5 -3
- package/dist/agent/run-store.d.ts +14 -1
- package/dist/agent/run-store.js +40 -7
- package/dist/client/hooks/index.d.ts +1 -1
- package/dist/client/hooks/index.js +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/progress/routes.d.ts +1 -1
- package/dist/server/agent-chat-plugin.js +4 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/docs/content/client-advanced.mdx +200 -0
- package/docs/content/client-agent-chat.mdx +313 -0
- package/docs/content/client-data.mdx +432 -0
- package/docs/content/client-entry-points.mdx +27 -0
- package/docs/content/client-overview.mdx +206 -0
- package/docs/content/client-routing.mdx +121 -0
- package/docs/content/client-sync-internals.mdx +124 -0
- package/docs/content/context-awareness.mdx +1 -1
- package/docs/content/docs-components.mdx +201 -0
- package/docs/content/drop-in-agent.mdx +1 -1
- package/docs/content/internationalization.mdx +1 -1
- package/docs/content/key-concepts.mdx +4 -0
- package/docs/content/notifications.mdx +1 -1
- package/docs/content/progress.mdx +2 -2
- package/docs/content/real-time-collaboration.mdx +2 -2
- package/docs/content/template-chat-developers.mdx +1 -1
- package/docs/content/toolkit-command-navigation.mdx +1 -1
- package/package.json +1 -1
- package/docs/content/client.mdx +0 -486
- package/docs/content/routing.mdx +0 -119
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Routing"
|
|
3
|
+
description: "File-based routing for agent-native apps with React Router v8: pages, dynamic params, and navigation."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Routing
|
|
7
|
+
|
|
8
|
+
Agent-native apps use **React Router v8** with file-based routing via `flatRoutes()` from `@react-router/fs-routes`. Every file in `app/routes/` becomes a URL. Templates use the dot-notation convention. Dots separate URL segments inside a single filename.
|
|
9
|
+
|
|
10
|
+
This page covers client routes, the pages rendered in the browser from `app/routes/`. Server routes are a separate system: Nitro file routes under `server/routes/`, plus the framework's own `/_agent-native/*` endpoints. Those live on the [Routes](/docs/server-routes) page. The two don't share a directory, a naming convention, or a router, so a `server/routes/` file never becomes a page here and an `app/routes/` file never becomes a server endpoint.
|
|
11
|
+
|
|
12
|
+
<Diagram id="doc-block-client-routing-1" title="File name → URL" summary="Each file in app/routes/ becomes a URL. Dots become slashes, and a $ segment becomes a dynamic param.">
|
|
13
|
+
|
|
14
|
+
```html
|
|
15
|
+
<div class="diagram-filemap">
|
|
16
|
+
<div class="diagram-filemap-row">
|
|
17
|
+
<span class="diagram-node">_index.tsx</span>
|
|
18
|
+
<span class="diagram-arrow diagram-muted" aria-hidden="true">→</span>
|
|
19
|
+
<span class="diagram-pill accent">/</span>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="diagram-filemap-row">
|
|
22
|
+
<span class="diagram-node">dashboard.tsx</span>
|
|
23
|
+
<span class="diagram-arrow diagram-muted" aria-hidden="true">→</span>
|
|
24
|
+
<span class="diagram-pill accent">/dashboard</span>
|
|
25
|
+
</div>
|
|
26
|
+
<div class="diagram-filemap-row">
|
|
27
|
+
<span class="diagram-node">dashboard_.$ticketId.tsx</span>
|
|
28
|
+
<span class="diagram-arrow diagram-muted" aria-hidden="true">→</span>
|
|
29
|
+
<span class="diagram-pill accent">/dashboard/:ticketId</span>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```css
|
|
35
|
+
.diagram-filemap {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
gap: 10px;
|
|
39
|
+
}
|
|
40
|
+
.diagram-filemap-row {
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
gap: 10px;
|
|
44
|
+
flex-wrap: wrap;
|
|
45
|
+
}
|
|
46
|
+
.diagram-filemap-row .diagram-arrow {
|
|
47
|
+
font-size: 18px;
|
|
48
|
+
line-height: 1;
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
</Diagram>
|
|
53
|
+
|
|
54
|
+
## File-based routing {#file-based-routing}
|
|
55
|
+
|
|
56
|
+
### File → URL mapping
|
|
57
|
+
|
|
58
|
+
| File | URL | Notes |
|
|
59
|
+
| -------------------------- | ---------------------- | ------------------------------------------------------------------------- |
|
|
60
|
+
| `_index.tsx` | `/` | Index route |
|
|
61
|
+
| `dashboard.tsx` | `/dashboard` | Simple page |
|
|
62
|
+
| `extensions.$id.tsx` | `/extensions/:id` | Nests inside `extensions.tsx`'s `<Outlet/>`. `$` is a dynamic param |
|
|
63
|
+
| `dashboard_.$ticketId.tsx` | `/dashboard/:ticketId` | Trailing `_` skips nesting under `dashboard.tsx`, so this is its own page |
|
|
64
|
+
| `_app.tsx` | (no URL segment) | Pathless layout. Prefix with `_` |
|
|
65
|
+
| `inbox/route.tsx` | `/inbox` | Folder form. `route.tsx` is the index |
|
|
66
|
+
|
|
67
|
+
Prefix a segment with `$` for a dynamic param. Prefix with `_` to make it a pathless layout route (no URL segment), or add a trailing `_` before a dot to opt a nested-looking path out of nesting under its parent's layout. Templates use `flatRoutes()`. The dot-notation file above is primary. The nested-folder form `inbox/route.tsx` also works.
|
|
68
|
+
|
|
69
|
+
## Adding a new page {#adding-a-page}
|
|
70
|
+
|
|
71
|
+
Create the file and export a default component:
|
|
72
|
+
|
|
73
|
+
```tsx filename="app/routes/settings.tsx"
|
|
74
|
+
export function meta() {
|
|
75
|
+
return [{ title: "Settings" }];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default function SettingsPage() {
|
|
79
|
+
return <div>Settings</div>;
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
That's it. The dev server reads route files at startup. If `pnpm dev` is already running, restart it after adding the file. No registration is needed.
|
|
84
|
+
|
|
85
|
+
## Dynamic params {#dynamic-params}
|
|
86
|
+
|
|
87
|
+
```tsx filename="app/routes/dashboard_.$ticketId.tsx"
|
|
88
|
+
import { useParams } from "react-router";
|
|
89
|
+
|
|
90
|
+
export default function TicketDetailPage() {
|
|
91
|
+
const { ticketId } = useParams();
|
|
92
|
+
return <div>Ticket: {ticketId}</div>;
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The trailing `_` before the dot keeps this page from nesting inside `dashboard.tsx`'s `<Outlet/>`, so it renders as its own full page at `/dashboard/:ticketId` instead of appearing inside the ticket queue's layout.
|
|
97
|
+
|
|
98
|
+
## Navigation {#navigation}
|
|
99
|
+
|
|
100
|
+
Use `<Link>` for client-side navigation and `useNavigate()` for programmatic navigation:
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { Link, useNavigate } from "react-router";
|
|
104
|
+
|
|
105
|
+
// In JSX
|
|
106
|
+
<Link to="/dashboard">Dashboard</Link>;
|
|
107
|
+
|
|
108
|
+
// Programmatic
|
|
109
|
+
const navigate = useNavigate();
|
|
110
|
+
navigate(`/dashboard/${ticketId}`);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Neither of these tells the agent what the user is looking at on their own. That's a separate concern, handled by `useAgentRouteState()` writing the current route into application state. See [Context Awareness](/docs/context-awareness).
|
|
114
|
+
|
|
115
|
+
## What's next
|
|
116
|
+
|
|
117
|
+
- [**Overview**](/docs/client-overview) — where `app/routes/` fits among the rest of `app/` and `public/`
|
|
118
|
+
- [**Data & Sync**](/docs/client-data) — reading and writing data from inside a route
|
|
119
|
+
- [**Agent Chat**](/docs/client-agent-chat) — sending prompts and staging context from a route
|
|
120
|
+
- [**Routes**](/docs/server-routes) — the separate server-routing system: file routes under `server/routes/` and the framework's `/_agent-native/` namespace
|
|
121
|
+
- [**Context Awareness**](/docs/context-awareness) — how the agent learns the current route and selection
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Sync Internals"
|
|
3
|
+
description: "The change-version mechanism behind useDbSync: useChangeVersion/useChangeVersions for syncing a raw useQuery, and the two latency paths a refetch can take."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Sync Internals
|
|
7
|
+
|
|
8
|
+
[Live Sync](/docs/key-concepts#polling-sync) covers the mental model: an agent write becomes a change event, `useDbSync()` picks it up, and affected queries refetch. This page covers the mechanism underneath that most apps never touch directly: the change-version counters `useDbSync()` bumps, and how to fold them into a raw `useQuery()` call that isn't going through `useActionQuery()`.
|
|
9
|
+
|
|
10
|
+
`useActionQuery()` already refetches automatically when a mutating action completes (see [Data & Sync](/docs/client-data#fetching-mutating)). Reach for `useChangeVersion()`/`useChangeVersions()` only when you're syncing a raw `useQuery()` call outside that path, such as a low-level client helper reading integration status.
|
|
11
|
+
|
|
12
|
+
## How change versions work {#how-it-works}
|
|
13
|
+
|
|
14
|
+
When a server-side database mutation occurs, the server records a change event tagged with a `source` key. `useDbSync()` receives that event and bumps a local counter for that source. Folding the counter into a React Query key makes the query refetch automatically whenever the backend reports new activity for that source.
|
|
15
|
+
|
|
16
|
+
## useChangeVersion / useChangeVersions {#use-change-version}
|
|
17
|
+
|
|
18
|
+
<Signature
|
|
19
|
+
id="doc-block-client-sync-internals-1"
|
|
20
|
+
name="useChangeVersion"
|
|
21
|
+
params={[
|
|
22
|
+
{
|
|
23
|
+
name: "source",
|
|
24
|
+
type: "string",
|
|
25
|
+
description: 'The change-event source to watch, e.g. `"dashboards"`.',
|
|
26
|
+
},
|
|
27
|
+
]}
|
|
28
|
+
returns={{
|
|
29
|
+
type: "number",
|
|
30
|
+
description:
|
|
31
|
+
"A counter that increments whenever the given source is mutated.",
|
|
32
|
+
}}
|
|
33
|
+
/>
|
|
34
|
+
|
|
35
|
+
<Signature
|
|
36
|
+
id="doc-block-client-sync-internals-2"
|
|
37
|
+
name="useChangeVersions"
|
|
38
|
+
params={[
|
|
39
|
+
{
|
|
40
|
+
name: "sources",
|
|
41
|
+
type: "readonly string[]",
|
|
42
|
+
description: "Multiple change-event sources to watch at once.",
|
|
43
|
+
},
|
|
44
|
+
]}
|
|
45
|
+
returns={{
|
|
46
|
+
type: "number",
|
|
47
|
+
description: "The sum of the version counters for every given source.",
|
|
48
|
+
}}
|
|
49
|
+
/>
|
|
50
|
+
|
|
51
|
+
In the example below, a raw `useQuery()` call reads a dashboard directly, folding the `"dashboards"` source's version counter into its query key so it refetches whenever that source changes:
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { useQuery } from "@tanstack/react-query";
|
|
55
|
+
import { useChangeVersion } from "@agent-native/core/client/hooks";
|
|
56
|
+
|
|
57
|
+
function DashboardView({ id }) {
|
|
58
|
+
const version = useChangeVersion("dashboards");
|
|
59
|
+
|
|
60
|
+
const { data } = useQuery({
|
|
61
|
+
queryKey: ["dashboard", id, version],
|
|
62
|
+
queryFn: () => fetchDashboard(id),
|
|
63
|
+
placeholderData: (prev) => prev,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return <div>{data?.title}</div>;
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`placeholderData: (prev) => prev` keeps the previous data on screen during the refetch, so the view doesn't flicker to a loading state.
|
|
71
|
+
|
|
72
|
+
## Two paths to a refetch {#latency-models}
|
|
73
|
+
|
|
74
|
+
A mutation reaches the UI one of two ways, and they have different latency.
|
|
75
|
+
|
|
76
|
+
A local mutation, one your own `useActionMutation()` call just made, fires a `source: "action"` event as soon as it succeeds. Every query depending on that action refetches immediately. There's no round-trip delay, since the tab that made the write already knows about it.
|
|
77
|
+
|
|
78
|
+
A remote mutation, from the agent, a webhook, another tab, or another user, has to reach this tab first. `useDbSync()` picks it up over SSE almost immediately, or over the polling fallback within about two seconds if SSE isn't available. Only once that event arrives does the relevant version counter bump and the query refetch in the background.
|
|
79
|
+
|
|
80
|
+
<Diagram id="doc-block-client-sync-internals-3" title="Two paths to a refetch" summary="A local mutation invalidates its own caches instantly. A remote write reaches this tab over SSE, or the polling tick as a fallback.">
|
|
81
|
+
|
|
82
|
+
```html
|
|
83
|
+
<div class="diagram-latency">
|
|
84
|
+
<div class="diagram-col">
|
|
85
|
+
<div class="diagram-card" data-rough>
|
|
86
|
+
<span class="diagram-pill ok">This tab</span
|
|
87
|
+
><strong>useActionMutation</strong
|
|
88
|
+
><small class="diagram-muted"
|
|
89
|
+
>fires source: "action" on success → instant local refetch</small
|
|
90
|
+
>
|
|
91
|
+
</div>
|
|
92
|
+
<div class="diagram-card" data-rough>
|
|
93
|
+
<span class="diagram-pill accent">Agent · webhook · other tab</span
|
|
94
|
+
><strong>Remote write</strong
|
|
95
|
+
><small class="diagram-muted"
|
|
96
|
+
>SSE push, or the ~2s polling tick as fallback → version bumps
|
|
97
|
+
→ background refetch</small
|
|
98
|
+
>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```css
|
|
105
|
+
.diagram-latency .diagram-col {
|
|
106
|
+
display: flex;
|
|
107
|
+
flex-direction: column;
|
|
108
|
+
gap: 12px;
|
|
109
|
+
}
|
|
110
|
+
.diagram-latency .diagram-card {
|
|
111
|
+
display: flex;
|
|
112
|
+
flex-direction: column;
|
|
113
|
+
gap: 4px;
|
|
114
|
+
padding: 14px 16px;
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
</Diagram>
|
|
119
|
+
|
|
120
|
+
## What's next
|
|
121
|
+
|
|
122
|
+
- [**Live Sync**](/docs/key-concepts#polling-sync) — the conceptual mental model this page goes underneath
|
|
123
|
+
- [**Data & Sync**](/docs/client-data) — `useActionQuery`/`useDbSync`, which most pages should use instead of these primitives
|
|
124
|
+
- [**Advanced**](/docs/client-advanced) — the other lower-level client primitives and escape hatches
|
|
@@ -486,5 +486,5 @@ How it works:
|
|
|
486
486
|
- [**Agent Mentions**](/docs/agent-mentions) — `@`-mention files and agents into a turn instead of relying on ambient context
|
|
487
487
|
- [**Drop-in Agent**](/docs/drop-in-agent) — mount the panel that reads and writes this state
|
|
488
488
|
- [**Real-Time Collaboration**](/docs/real-time-collaboration) — keep app state in sync when the agent and users edit together
|
|
489
|
-
- [**
|
|
489
|
+
- [**Application State**](/docs/client-advanced#application-state) — the full `application-state` and client helper reference
|
|
490
490
|
- [**Toolkit piece: Context & Knowledge**](/docs/toolkit-context-knowledge) — the Context X-Ray presentation built on this state
|
|
@@ -330,6 +330,204 @@ Add more `###` sections to get 3 or 4 columns (max 4). The red/green label accen
|
|
|
330
330
|
|
|
331
331
|
---
|
|
332
332
|
|
|
333
|
+
## Image
|
|
334
|
+
|
|
335
|
+
<Image
|
|
336
|
+
src="/screenshots/dispatch.png"
|
|
337
|
+
alt="Dispatch app screenshot showing the run history sidebar"
|
|
338
|
+
align="left"
|
|
339
|
+
width={320}
|
|
340
|
+
caption="Dispatch's run history sidebar."
|
|
341
|
+
>
|
|
342
|
+
|
|
343
|
+
Aligning an image left or right turns it into a two-column row. The image sits on that side, and this markdown is the paired text on the other side. Leave `align` unset, or set it to `"full"`, for a normal full-width image with no paired text.
|
|
344
|
+
|
|
345
|
+
</Image>
|
|
346
|
+
|
|
347
|
+
```mdx
|
|
348
|
+
<Image
|
|
349
|
+
src="/screenshots/dispatch.png"
|
|
350
|
+
alt="Dispatch app screenshot showing the run history sidebar"
|
|
351
|
+
align="left"
|
|
352
|
+
width={320}
|
|
353
|
+
caption="Dispatch's run history sidebar."
|
|
354
|
+
>
|
|
355
|
+
|
|
356
|
+
Aligning an image left or right turns it into a two-column row. The image sits on that side, and this markdown is the paired text on the other side. Leave `align` unset, or set it to `"full"`, for a normal full-width image with no paired text.
|
|
357
|
+
|
|
358
|
+
</Image>
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
`alt` is required. `align` is `"full"` (the default), `"left"`, or `"right"`. `width` is an optional pixel hint for the image column when aligned, and has no effect on `"full"`. `caption` renders in small muted text under the image. Anything between the open and close tags is markdown, and becomes the paired text next to the image when aligned, or plain content below it when full width. Omit the children entirely for a self-closing `<Image ... />` with no paired text.
|
|
362
|
+
|
|
363
|
+
Hovering the image reveals a top-right expand button that opens it in a larger popup. If the image has paired text (or a caption), the popup stacks it below the image instead of beside it, since the two-column layout only makes sense at the inline aligned size.
|
|
364
|
+
|
|
365
|
+
For a plain full-width image with no paired text, omit `align` (or set it to `"full"`) and skip the children entirely:
|
|
366
|
+
|
|
367
|
+
<Image
|
|
368
|
+
src="/screenshots/mail.png"
|
|
369
|
+
alt="Mail app screenshot showing the inbox and reading pane"
|
|
370
|
+
caption="The default inbox view."
|
|
371
|
+
/>
|
|
372
|
+
|
|
373
|
+
```mdx
|
|
374
|
+
<Image
|
|
375
|
+
src="/screenshots/mail.png"
|
|
376
|
+
alt="Mail app screenshot showing the inbox and reading pane"
|
|
377
|
+
caption="The default inbox view."
|
|
378
|
+
/>
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
## Video
|
|
384
|
+
|
|
385
|
+
No sample video ships in this repo, so this section shows syntax only rather than a live-rendered example. Swap `src` for a real `.mp4`/`.webm` file under `public/` to see it rendered.
|
|
386
|
+
|
|
387
|
+
```mdx
|
|
388
|
+
<Video
|
|
389
|
+
src="/videos/product-tour.mp4"
|
|
390
|
+
alt="A short screen recording of creating a new action from the CLI"
|
|
391
|
+
align="right"
|
|
392
|
+
width={320}
|
|
393
|
+
caption="Creating an action from the CLI."
|
|
394
|
+
>
|
|
395
|
+
|
|
396
|
+
Same shape as `Image`, aligned the other way this time. The video sits on the right, and this text sits on the left. `src` must be a direct video file, mp4 or webm. Third-party embed links like YouTube or Loom aren't supported, since that would need an `<iframe>`, which the docs system doesn't allow for security reasons.
|
|
397
|
+
|
|
398
|
+
</Video>
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
Identical attributes to `Image` (`src`, `alt`, `align`, `width`, `caption`, and paired markdown children), except `src` must point to a direct video file rather than an embed link. `alt` becomes the video's `aria-label`, since `<video>` has no native `alt` attribute.
|
|
402
|
+
|
|
403
|
+
Pass `autoplay` to play the video automatically once it's visible. It always forces `muted` alongside it, since browsers block autoplay with sound regardless of the attribute. It also never autoplays for a viewer with `prefers-reduced-motion: reduce` set. That viewer instead gets a normal paused player, and pressing play themselves gives them full, unmuted playback rather than a silently-muted one.
|
|
404
|
+
|
|
405
|
+
Pass `loop` to restart the video from the beginning once it ends. It's independent of `autoplay`, so a looping video that isn't set to autoplay just loops once the viewer presses play themselves.
|
|
406
|
+
|
|
407
|
+
The same full-width form applies here too, omit `align` and the children for a plain full-width video:
|
|
408
|
+
|
|
409
|
+
```mdx
|
|
410
|
+
<Video
|
|
411
|
+
src="/videos/product-tour.mp4"
|
|
412
|
+
alt="A full walkthrough recording of building an action end to end"
|
|
413
|
+
caption="Building an action end to end."
|
|
414
|
+
/>
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## Signature
|
|
420
|
+
|
|
421
|
+
<Signature
|
|
422
|
+
id="docs-components-signature"
|
|
423
|
+
name="askUserQuestion"
|
|
424
|
+
params={[
|
|
425
|
+
{
|
|
426
|
+
name: "input",
|
|
427
|
+
type: "AskUserQuestionInput",
|
|
428
|
+
description: "The question, its options, and how it should behave.",
|
|
429
|
+
fields: [
|
|
430
|
+
{
|
|
431
|
+
name: "question",
|
|
432
|
+
type: "string",
|
|
433
|
+
description:
|
|
434
|
+
"The complete question. Clear, specific, ends with a question mark.",
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
name: "header",
|
|
438
|
+
type: "string",
|
|
439
|
+
optional: true,
|
|
440
|
+
description:
|
|
441
|
+
'Very short chip/heading, about 12 characters, e.g. `"Date range"`.',
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
name: "options",
|
|
445
|
+
type: "AskUserQuestionOption[]",
|
|
446
|
+
description: "2-4 distinct options.",
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
name: "allowFreeText",
|
|
450
|
+
type: "boolean",
|
|
451
|
+
optional: true,
|
|
452
|
+
default: "true",
|
|
453
|
+
description: 'Adds a free-text "Other" option.',
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
name: "allowMultiple",
|
|
457
|
+
type: "boolean",
|
|
458
|
+
optional: true,
|
|
459
|
+
default: "false",
|
|
460
|
+
description: "Multi-select instead of single-select.",
|
|
461
|
+
},
|
|
462
|
+
],
|
|
463
|
+
},
|
|
464
|
+
]}
|
|
465
|
+
returns={{
|
|
466
|
+
type: "Promise<AskUserQuestionResult>",
|
|
467
|
+
description:
|
|
468
|
+
'The picked value, `value[]` when `allowMultiple`, the typed "Other" text, or `null` if skipped.',
|
|
469
|
+
}}
|
|
470
|
+
/>
|
|
471
|
+
|
|
472
|
+
```mdx
|
|
473
|
+
<Signature
|
|
474
|
+
id="docs-components-signature"
|
|
475
|
+
name="askUserQuestion"
|
|
476
|
+
params={[
|
|
477
|
+
{
|
|
478
|
+
name: "input",
|
|
479
|
+
type: "AskUserQuestionInput",
|
|
480
|
+
description: "The question, its options, and how it should behave.",
|
|
481
|
+
fields: [
|
|
482
|
+
{
|
|
483
|
+
name: "question",
|
|
484
|
+
type: "string",
|
|
485
|
+
description:
|
|
486
|
+
"The complete question. Clear, specific, ends with a question mark.",
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
name: "header",
|
|
490
|
+
type: "string",
|
|
491
|
+
optional: true,
|
|
492
|
+
description:
|
|
493
|
+
'Very short chip/heading, about 12 characters, e.g. `"Date range"`.',
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
name: "options",
|
|
497
|
+
type: "AskUserQuestionOption[]",
|
|
498
|
+
description: "2-4 distinct options.",
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
name: "allowFreeText",
|
|
502
|
+
type: "boolean",
|
|
503
|
+
optional: true,
|
|
504
|
+
default: "true",
|
|
505
|
+
description: 'Adds a free-text "Other" option.',
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
name: "allowMultiple",
|
|
509
|
+
type: "boolean",
|
|
510
|
+
optional: true,
|
|
511
|
+
default: "false",
|
|
512
|
+
description: "Multi-select instead of single-select.",
|
|
513
|
+
},
|
|
514
|
+
],
|
|
515
|
+
},
|
|
516
|
+
]}
|
|
517
|
+
returns={{
|
|
518
|
+
type: "Promise<AskUserQuestionResult>",
|
|
519
|
+
description:
|
|
520
|
+
'The picked value, `value[]` when `allowMultiple`, the typed "Other" text, or `null` if skipped.',
|
|
521
|
+
}}
|
|
522
|
+
/>
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
`Signature` is self-closing. `name` plus `params` build the code-style call line shown at the top (an optional param renders as `name?: type`). Each param is `{ name, type, optional?, default?, description }`, matching a plain field. An object-shaped param (like `input` above) can add a nested `fields` array of the same shape to break down its properties, so one block replaces both a hand-written signature line and a separate options table. `returns` is optional and takes the same `{ type, description? }` shape. Descriptions render through the normal markdown pipeline, so backticks and bold work.
|
|
526
|
+
|
|
527
|
+
Use this over a hand-written `ts` fence plus a prose bullet list whenever a reference page documents a specific function, hook, or action's call shape, per the `writing-reference-docs` skill.
|
|
528
|
+
|
|
529
|
+
---
|
|
530
|
+
|
|
333
531
|
## kbd — keyboard shortcut
|
|
334
532
|
|
|
335
533
|
Press [[⌘K]] to open the command palette. Save with [[Ctrl+S]] before running the dev server. Navigate fields with [[Tab]] and [[Shift+Tab]].
|
|
@@ -606,5 +804,8 @@ Like `TabsBlock`, `Columns` is self-closing with a single JSON `columns` attribu
|
|
|
606
804
|
| Same task in multiple tools or frameworks | `Tabs` |
|
|
607
805
|
| Side-by-side code (labeled columns) | `Columns` |
|
|
608
806
|
| Project directory structure | `FileTree` |
|
|
807
|
+
| A function/hook/action's call shape | `Signature` |
|
|
808
|
+
| An image, full width or with paired text | `Image` |
|
|
809
|
+
| A video, full width or with paired text | `Video` |
|
|
609
810
|
| Inline keyboard shortcut | `[[Key]]` |
|
|
610
811
|
| Architecture or flow diagram | Mermaid fence |
|
|
@@ -237,7 +237,7 @@ conversation itself belongs in the AgentSidebar composer.
|
|
|
237
237
|
|
|
238
238
|
When the same route is embedded as an MCP App, submitted
|
|
239
239
|
`sendToAgentChat()` calls are forwarded to the host chat where supported; see
|
|
240
|
-
[
|
|
240
|
+
[Agent Chat](/docs/client-agent-chat#sendtoagentchat) for the MCP App bridge behavior.
|
|
241
241
|
|
|
242
242
|
If you want a loading state, use the `useSendToAgentChat()` hook — it returns both `send` and `isGenerating`:
|
|
243
243
|
|
|
@@ -148,6 +148,6 @@ names.
|
|
|
148
148
|
|
|
149
149
|
## What's next
|
|
150
150
|
|
|
151
|
-
- [**
|
|
151
|
+
- [**Overview**](/docs/client-overview#app-shell) — the `AppProviders` wrapper and other browser hooks i18n builds on
|
|
152
152
|
- [**Toolkit: Settings**](/docs/toolkit-settings) — put `<LanguagePicker>` on the standard settings page
|
|
153
153
|
- [**Getting Started**](/docs/getting-started) — build your first app on a template that already ships localized catalogs
|
|
@@ -511,6 +511,10 @@ The vision and philosophy behind these rules.
|
|
|
511
511
|
|
|
512
512
|
Navigation state, view-screen, and navigate commands in depth.
|
|
513
513
|
|
|
514
|
+
### [Sync Internals](/docs/client-sync-internals)
|
|
515
|
+
|
|
516
|
+
The change-version mechanism behind live sync, for syncing a raw `useQuery`.
|
|
517
|
+
|
|
514
518
|
### [Skills Guide](/docs/skills-guide)
|
|
515
519
|
|
|
516
520
|
Framework skills, domain skills, and creating custom skills.
|
|
@@ -366,7 +366,7 @@ Automations can chain off this — e.g. _"if a critical notification fires, also
|
|
|
366
366
|
## How it works {#internals}
|
|
367
367
|
|
|
368
368
|
- **Owner scoping** — every row has an `owner` column; every query filters on it; every route uses the authenticated session's email. Users never see each other's notifications.
|
|
369
|
-
- **Poll integration** — every mutation calls `recordChange()` so templates using [`useDbSync`](/docs/client) auto-invalidate without any extra wiring.
|
|
369
|
+
- **Poll integration** — every mutation calls `recordChange()` so templates using [`useDbSync`](/docs/client-data#usedbsync) auto-invalidate without any extra wiring.
|
|
370
370
|
- **Best-effort fan-out** — channel errors are caught and logged; one failing channel does not block others or the inbox write.
|
|
371
371
|
- **Fire-and-forget** — `notify()` returns after the inbox write completes; custom channels run in the background.
|
|
372
372
|
|
|
@@ -244,7 +244,7 @@ Notify me that run {{runId}} has failed.
|
|
|
244
244
|
## How it works {#internals}
|
|
245
245
|
|
|
246
246
|
- **Owner scoping** — every row has an `owner` column; every query filters on it. Users see only their own runs.
|
|
247
|
-
- **Poll integration** — every mutation calls `recordChange()` so templates using [`useDbSync`](/docs/client) auto-invalidate without any extra wiring.
|
|
247
|
+
- **Poll integration** — every mutation calls `recordChange()` so templates using [`useDbSync`](/docs/client-data#usedbsync) auto-invalidate without any extra wiring.
|
|
248
248
|
- **Table name** — the framework also has an `agent_runs` table for internal agent-chat turn lifecycle tracking. The progress primitive uses `progress_runs` to keep the two concerns separate.
|
|
249
249
|
- **Percent clamping** — values are clamped to `[0, 100]` and rounded to an integer on write.
|
|
250
250
|
|
|
@@ -252,4 +252,4 @@ Notify me that run {{runId}} has failed.
|
|
|
252
252
|
|
|
253
253
|
- [**Notifications**](/docs/notifications) — pair with `manage-progress` (`action=complete`) to tell the user when work finishes
|
|
254
254
|
- [**Automations**](/docs/automations) — watchdog slow runs via `run.progress.updated`
|
|
255
|
-
- [**
|
|
255
|
+
- [**Data & Sync**](/docs/client-data) — `useDbSync` for real-time cache invalidation
|
|
@@ -39,7 +39,7 @@ deployment environments including serverless and edge).
|
|
|
39
39
|
|
|
40
40
|
<Callout tone="info">
|
|
41
41
|
|
|
42
|
-
**Just need the UI to refresh, not character-level co-editing?** Use [`useDbSync`](/docs/client#usedbsync) instead — it's for reacting to SQL writes from the agent or other users. This page covers real-time character-level co-editing of a single rich-text document (shared cursors, conflict-free merging). Both ride the same `/_agent-native/poll` channel.
|
|
42
|
+
**Just need the UI to refresh, not character-level co-editing?** Use [`useDbSync`](/docs/client-data#usedbsync) instead — it's for reacting to SQL writes from the agent or other users. This page covers real-time character-level co-editing of a single rich-text document (shared cursors, conflict-free merging). Both ride the same `/_agent-native/poll` channel.
|
|
43
43
|
|
|
44
44
|
</Callout>
|
|
45
45
|
|
|
@@ -780,7 +780,7 @@ Key properties:
|
|
|
780
780
|
|
|
781
781
|
## What's next {#whats-next}
|
|
782
782
|
|
|
783
|
-
- [
|
|
783
|
+
- [Sync Internals](/docs/client-sync-internals) — the `useDbSync` + `useChangeVersion`
|
|
784
784
|
system that delivers the `updatedAt` bump driving editor reconciliation.
|
|
785
785
|
- [Security](/docs/security) — `registerShareableResource`, `resolveAccess`,
|
|
786
786
|
and `assertAccess` for resource-scoped collaboration.
|
|
@@ -11,7 +11,7 @@ This page is for developers who need to know what runs under the hood in [Chat](
|
|
|
11
11
|
|
|
12
12
|
Chat adds no domain tables of its own (see [What's not in it](/docs/template-chat#not-in-it)). It runs entirely on the framework's core tables: chat threads and messages, `application_state`, `settings`, sessions, resources, and run history.
|
|
13
13
|
|
|
14
|
-
`useDbSync()` is already wired into the app shell: when the agent (or anyone else) writes to SQL, the client receives the change over SSE, or the 2-second polling fallback, and invalidates the matching React Query caches — no manual refresh, no websocket you have to manage yourself. See [`useDbSync`](/docs/client#usedbsync) for the full hook API.
|
|
14
|
+
`useDbSync()` is already wired into the app shell: when the agent (or anyone else) writes to SQL, the client receives the change over SSE, or the 2-second polling fallback, and invalidates the matching React Query caches — no manual refresh, no websocket you have to manage yourself. See [`useDbSync`](/docs/client-data#usedbsync) for the full hook API.
|
|
15
15
|
|
|
16
16
|
`server/plugins/agent-chat.ts` is where the chat runtime itself is configured: it registers every action in `actions/` as a callable tool (`loadActionsFromStaticRegistry`), resolves the current org for scoping (`resolveOrgId`), sets the system prompt, and declares which tools the model sees on the very first turn (`initialToolNames`) — see [Your first feature in Chat](/docs/template-chat-first-edits#first-edits) for what that last part means when you add a new action.
|
|
17
17
|
|
|
@@ -104,7 +104,7 @@ Use a small predictable route set:
|
|
|
104
104
|
|
|
105
105
|
## What's next
|
|
106
106
|
|
|
107
|
-
- [**Routing**](/docs/routing) — the file-route conventions the route standard
|
|
107
|
+
- [**Routing**](/docs/client-routing) — the file-route conventions the route standard
|
|
108
108
|
builds on.
|
|
109
109
|
- [**Context Awareness**](/docs/context-awareness) — how `view-screen` and
|
|
110
110
|
navigation state stay in sync.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.153.
|
|
3
|
+
"version": "0.153.9",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|