@agent-native/core 0.77.24 → 0.78.1
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/README.md +2 -2
- package/corpus/core/CHANGELOG.md +20 -0
- package/corpus/core/docs/content/template-analytics.md +5 -0
- package/corpus/core/docs/content/tracking.md +45 -0
- package/corpus/core/package.json +3 -1
- package/corpus/core/src/agent/types.ts +22 -0
- package/corpus/core/src/client/AgentPanel.tsx +34 -18
- package/corpus/core/src/client/AssistantChat.tsx +40 -0
- package/corpus/core/src/client/agent-chat.ts +173 -0
- package/corpus/core/src/client/analytics.ts +141 -5
- package/corpus/core/src/client/composer/TiptapComposer.tsx +316 -60
- package/corpus/core/src/client/composer/extensions/MentionReference.tsx +3 -0
- package/corpus/core/src/client/composer/types.ts +22 -0
- package/corpus/core/src/client/index.ts +14 -0
- package/corpus/core/src/client/session-replay.ts +800 -0
- package/corpus/core/src/db/schema.ts +12 -0
- package/corpus/core/src/deploy/build.ts +75 -0
- package/corpus/core/src/private-blob/index.ts +18 -0
- package/corpus/core/src/private-blob/registry.ts +241 -0
- package/corpus/core/src/private-blob/types.ts +55 -0
- package/corpus/core/src/scripts/utils.ts +34 -6
- package/corpus/core/src/server/agent-chat-plugin.ts +10 -0
- package/corpus/core/src/server/email.ts +5 -0
- package/corpus/core/src/server/index.ts +1 -0
- package/corpus/core/src/styles/agent-native.css +24 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +1 -1
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +43 -0
- package/corpus/templates/analytics/AGENTS.md +32 -1
- package/corpus/templates/analytics/DEVELOPING.md +9 -1
- package/corpus/templates/analytics/actions/delete-dashboard-report-subscription.ts +24 -0
- package/corpus/templates/analytics/actions/get-session-replay-events.ts +50 -0
- package/corpus/templates/analytics/actions/get-session-replay-summary.ts +27 -0
- package/corpus/templates/analytics/actions/list-dashboard-report-subscriptions.ts +24 -0
- package/corpus/templates/analytics/actions/list-session-recordings.ts +59 -0
- package/corpus/templates/analytics/actions/navigate.ts +15 -5
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +2 -2
- package/corpus/templates/analytics/actions/save-dashboard-report-subscription.ts +36 -0
- package/corpus/templates/analytics/actions/send-dashboard-report-now.ts +60 -0
- package/corpus/templates/analytics/actions/view-screen.ts +50 -2
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +51 -2
- package/corpus/templates/analytics/app/components/layout/Header.tsx +4 -1
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +14 -2
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +6 -6
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +35 -6
- package/corpus/templates/analytics/app/i18n-data.ts +1119 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/EmailReportDialog.tsx +437 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +11 -12
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +43 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +136 -43
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/report-filters.ts +26 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +450 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +419 -0
- package/corpus/templates/analytics/app/routes/overview.tsx +13 -6
- package/corpus/templates/analytics/app/routes/sessions.$recordingId.tsx +10 -0
- package/corpus/templates/analytics/app/routes/sessions._index.tsx +10 -0
- package/corpus/templates/analytics/changelog/2026-06-25-analytics-now-opens-directly-to-ask-instead-of-the-old-overv.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-25-dashboard-charts-now-show-reliable-blue-placement-lines-whil.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-26-dashboards-can-now-send-scheduled-daily-email-reports-from-t.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-26-session-replay-browser-sessions-can-now-be-reviewed-from.md +6 -0
- package/corpus/templates/analytics/package.json +5 -2
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +131 -0
- package/corpus/templates/analytics/scripts/seed-session-replay.ts +198 -0
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +140 -27
- package/corpus/templates/analytics/server/db/index.ts +12 -0
- package/corpus/templates/analytics/server/db/schema.ts +131 -0
- package/corpus/templates/analytics/server/handlers/session-replay.ts +281 -0
- package/corpus/templates/analytics/server/handlers/sql-query.ts +8 -348
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +66 -0
- package/corpus/templates/analytics/server/jobs/session-replay-retention.ts +29 -0
- package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +365 -0
- package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +473 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +405 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +63 -18
- package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +98 -26
- package/corpus/templates/analytics/server/lib/session-replay.ts +1645 -0
- package/corpus/templates/analytics/server/plugins/auth.ts +1 -1
- package/corpus/templates/analytics/server/plugins/dashboard-report-jobs.ts +47 -0
- package/corpus/templates/analytics/server/plugins/db.ts +200 -0
- package/corpus/templates/analytics/server/plugins/session-replay-retention-jobs.ts +41 -0
- package/corpus/templates/analytics/server/routes/api/analytics/replay.options.ts +1 -0
- package/corpus/templates/analytics/server/routes/api/analytics/replay.post.ts +1 -0
- package/corpus/templates/analytics/server/routes/api/dashboard-reports/run.post.ts +61 -0
- package/corpus/templates/analytics/server/routes/api/session-replay/recordings/[recordingId]/chunks/[seq].get.ts +1 -0
- package/corpus/templates/analytics/server/routes/api/session-replay/recordings/[recordingId]/events.get.ts +1 -0
- package/corpus/templates/analytics/server/routes/api/session-replay/recordings/[recordingId]/manifest.get.ts +1 -0
- package/corpus/templates/analytics/server/routes/api/session-replay/recordings/[recordingId].get.ts +1 -0
- package/corpus/templates/analytics/server/routes/api/session-replay/recordings.get.ts +1 -0
- package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +10 -2
- package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +14 -7
- package/corpus/templates/assets/.agents/skills/library-management/SKILL.md +12 -0
- package/corpus/templates/assets/AGENTS.md +18 -3
- package/corpus/templates/assets/actions/_image-model-default.ts +24 -0
- package/corpus/templates/assets/actions/dismiss-variant-slots.ts +15 -22
- package/corpus/templates/assets/actions/generate-asset.ts +30 -23
- package/corpus/templates/assets/actions/generate-image-batch.ts +76 -29
- package/corpus/templates/assets/actions/generate-image.ts +46 -30
- package/corpus/templates/assets/actions/generate-video.ts +18 -3
- package/corpus/templates/assets/actions/list-assets.ts +39 -8
- package/corpus/templates/assets/actions/list-libraries.ts +24 -2
- package/corpus/templates/assets/actions/navigate.ts +1 -1
- package/corpus/templates/assets/actions/open-asset-picker.ts +38 -1
- package/corpus/templates/assets/actions/refresh-generation-run.ts +10 -0
- package/corpus/templates/assets/actions/save-generated-image.ts +21 -19
- package/corpus/templates/assets/actions/variant-slots.ts +131 -28
- package/corpus/templates/assets/actions/view-screen.ts +9 -0
- package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +425 -0
- package/corpus/templates/assets/app/components/layout/Header.tsx +3 -1
- package/corpus/templates/assets/app/components/layout/Layout.tsx +5 -0
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +4 -6
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +47 -21
- package/corpus/templates/assets/app/i18n-data.ts +1815 -0
- package/corpus/templates/assets/app/lib/libraries.ts +6 -0
- package/corpus/templates/assets/app/lib/picker-chat-handoff.ts +71 -0
- package/corpus/templates/assets/app/routes/_index.tsx +4 -0
- package/corpus/templates/assets/app/routes/asset.$id.tsx +2 -2
- package/corpus/templates/assets/app/routes/audit.tsx +1 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +1557 -2164
- package/corpus/templates/assets/app/routes/brand-kits._index.tsx +7 -191
- package/corpus/templates/assets/app/routes/brand-kits.tsx +1 -5
- package/corpus/templates/assets/app/routes/libraries.tsx +4 -4
- package/corpus/templates/assets/app/routes/library.$id.tsx +9 -7
- package/corpus/templates/assets/app/routes/library.tsx +1454 -175
- package/corpus/templates/assets/server/db/index.ts +1 -1
- package/corpus/templates/assets/server/lib/generation.ts +86 -15
- package/corpus/templates/assets/server/plugins/agent-chat.ts +196 -0
- package/corpus/templates/assets/server/plugins/db.ts +5 -0
- package/corpus/templates/assets/shared/api.ts +6 -3
- package/dist/agent/types.d.ts +21 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +6 -2
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +10 -4
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +6 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +15 -3
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat.d.ts +32 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +113 -0
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/analytics.d.ts +22 -3
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +96 -4
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +2 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +228 -56
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/extensions/MentionReference.d.ts.map +1 -1
- package/dist/client/composer/extensions/MentionReference.js +3 -0
- package/dist/client/composer/extensions/MentionReference.js.map +1 -1
- package/dist/client/composer/types.d.ts +21 -0
- package/dist/client/composer/types.d.ts.map +1 -1
- package/dist/client/composer/types.js.map +1 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/session-replay.d.ts +41 -0
- package/dist/client/session-replay.d.ts.map +1 -0
- package/dist/client/session-replay.js +595 -0
- package/dist/client/session-replay.js.map +1 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/db/schema.d.ts +3 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +6 -2
- package/dist/db/schema.js.map +1 -1
- package/dist/deploy/build.d.ts +8 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +66 -0
- package/dist/deploy/build.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +8 -8
- package/dist/private-blob/index.d.ts +3 -0
- package/dist/private-blob/index.d.ts.map +1 -0
- package/dist/private-blob/index.js +2 -0
- package/dist/private-blob/index.js.map +1 -0
- package/dist/private-blob/registry.d.ts +10 -0
- package/dist/private-blob/registry.d.ts.map +1 -0
- package/dist/private-blob/registry.js +152 -0
- package/dist/private-blob/registry.js.map +1 -0
- package/dist/private-blob/types.d.ts +51 -0
- package/dist/private-blob/types.d.ts.map +1 -0
- package/dist/private-blob/types.js +2 -0
- package/dist/private-blob/types.js.map +1 -0
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/scripts/utils.d.ts +4 -4
- package/dist/scripts/utils.d.ts.map +1 -1
- package/dist/scripts/utils.js +30 -6
- package/dist/scripts/utils.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +5 -0
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +2 -2
- package/dist/server/email.d.ts +2 -0
- package/dist/server/email.d.ts.map +1 -1
- package/dist/server/email.js +3 -0
- package/dist/server/email.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/agent-native.css +24 -0
- package/docs/content/template-analytics.md +5 -0
- package/docs/content/tracking.md +45 -0
- package/package.json +3 -1
- package/corpus/templates/analytics/app/pages/overview/OverviewPage.tsx +0 -209
package/corpus/README.md
CHANGED
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.78.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 71849f1: Add structured composer reference chips that can be inserted programmatically
|
|
8
|
+
and constrained to one visible value per app-defined slot.
|
|
9
|
+
- 71849f1: Forward chat thread footer slots through AgentSidebar so apps can keep live run
|
|
10
|
+
results attached to chat threads.
|
|
11
|
+
|
|
12
|
+
## 0.78.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- 368e2a7: Add core session replay client primitives and private blob storage abstractions for Agent Native Analytics.
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 368e2a7: Support CID inline attachments in the core email transport.
|
|
21
|
+
- 368e2a7: Keep agent sidebar contents at their full open width while desktop sidebars animate in and out, avoiding text reflow during the transition, and hide the page-level New chat action until a chat has actually started.
|
|
22
|
+
|
|
3
23
|
## 0.77.24
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
|
@@ -91,6 +91,11 @@ pnpm install
|
|
|
91
91
|
pnpm dev
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
The Analytics template's dev script pins `DATABASE_URL` to the local SQLite
|
|
95
|
+
file at `./data/app.db`, so a production `DATABASE_URL` in `.env` will not be
|
|
96
|
+
used during local development. To intentionally point local dev at another
|
|
97
|
+
database, run `ANALYTICS_DATABASE_URL=<your dev database url> pnpm dev`.
|
|
98
|
+
|
|
94
99
|
The CLI prints the local dev URL. Sign in with Google, then open the **Data Sources** page to connect BigQuery, GA4, first-party tracking, HubSpot, Jira, and the rest.
|
|
95
100
|
|
|
96
101
|
### Key features
|
|
@@ -132,6 +132,51 @@ Key differences from the [server `track()`](#track):
|
|
|
132
132
|
|
|
133
133
|
This is distinct from the framework's internal browser telemetry (`trackEvent()` / automatic pageviews — see [Browser defaults](#browser-defaults) below), which powers Agent Native's own product analytics. Use `track()` for your app's own analytics events that should reach your configured providers.
|
|
134
134
|
|
|
135
|
+
## Session replay {#session-replay}
|
|
136
|
+
|
|
137
|
+
Agent Native apps can opt into first-party browser session replay without adding a second analytics SDK. Call `configureTracking()` once in the browser root and pass the Analytics public key plus collector endpoint:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
import { configureTracking } from "@agent-native/core/client";
|
|
141
|
+
|
|
142
|
+
configureTracking({
|
|
143
|
+
key: "anpk_...",
|
|
144
|
+
endpoint: "https://analytics.example.com/api/analytics/track",
|
|
145
|
+
sessionReplay: {
|
|
146
|
+
enabled: true,
|
|
147
|
+
sampleRate: 1,
|
|
148
|
+
},
|
|
149
|
+
getDefaultProps: (_event, props) => ({
|
|
150
|
+
...props,
|
|
151
|
+
app: "my-app",
|
|
152
|
+
template: "my-template",
|
|
153
|
+
}),
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
When `sessionReplay.enabled` is truthy, the client dynamically imports `@rrweb/record` after startup and posts replay chunks to the replay endpoint. If `endpoint` ends in `/api/analytics/track` or `/track`, the replay endpoint is derived automatically as `/api/analytics/replay`. Override it explicitly with `sessionReplay.endpoint` when the replay collector lives somewhere else.
|
|
158
|
+
|
|
159
|
+
Agent Native template roots already call `configureTracking()`, so hosted template deployments can use Vite/Netlify environment variables instead of editing code:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
VITE_AGENT_NATIVE_ANALYTICS_PUBLIC_KEY=anpk_...
|
|
163
|
+
VITE_AGENT_NATIVE_ANALYTICS_ENDPOINT=https://analytics.example.com/api/analytics/track
|
|
164
|
+
VITE_AGENT_NATIVE_SESSION_REPLAY_ENABLED=true
|
|
165
|
+
VITE_AGENT_NATIVE_SESSION_REPLAY_SAMPLE_RATE=1
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Privacy defaults are intentionally conservative but still useful for playback:
|
|
169
|
+
|
|
170
|
+
- Inputs are masked by default (`maskAllInputs: true`).
|
|
171
|
+
- Page text remains visible unless an element is marked with `.an-mask` or `data-an-mask`.
|
|
172
|
+
- Sensitive zones are blocked with selectors such as `[data-sensitive]`, `.an-block`, `.an-private`, `data-an-block`, `data-an-private`, and credit-card/password/SSN-like fields.
|
|
173
|
+
- URLs are scrubbed with the same `scrubUrl()` helper used by browser analytics.
|
|
174
|
+
- Replay capture is web-only and opt-in; it does not record native desktop screens.
|
|
175
|
+
|
|
176
|
+
The Analytics template stores replay metadata in SQL (`session_recordings`) and stores chunks through private blob refs (`session_replay_chunks`). Browsers and agents never receive provider URLs. Playback goes through scoped server routes and the default agent tools return summaries or bounded replay events, not raw chunk table access.
|
|
177
|
+
|
|
178
|
+
For local development only, Analytics can fall back to capped SQL inline chunks when private blob storage is unavailable. Production deployments should configure private or encrypted blob storage rather than relying on Postgres for replay payloads.
|
|
179
|
+
|
|
135
180
|
## Advanced: custom providers & internals {#advanced}
|
|
136
181
|
|
|
137
182
|
Most apps only need `track()` / `identify()` and a built-in provider. The rest of the surface — registering custom providers, the `TrackingProvider` interface, batching internals, and the framework's own browser telemetry — is below.
|
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.78.1",
|
|
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": {
|
|
@@ -101,6 +101,7 @@
|
|
|
101
101
|
"./tools/url-safety": "./dist/extensions/url-safety.js",
|
|
102
102
|
"./file-upload": "./dist/file-upload/index.js",
|
|
103
103
|
"./file-upload/actions/upload-image": "./dist/file-upload/actions/upload-image.js",
|
|
104
|
+
"./private-blob": "./dist/private-blob/index.js",
|
|
104
105
|
"./agent/context-xray/actions/context-manifest-get": "./dist/agent/context-xray/actions/context-manifest-get.js",
|
|
105
106
|
"./agent/context-xray/actions/context-pin": "./dist/agent/context-xray/actions/context-pin.js",
|
|
106
107
|
"./agent/context-xray/actions/context-evict": "./dist/agent/context-xray/actions/context-evict.js",
|
|
@@ -211,6 +212,7 @@
|
|
|
211
212
|
"@react-router/dev": "^8.0.1",
|
|
212
213
|
"@react-router/fs-routes": "^8.0.1",
|
|
213
214
|
"@resvg/resvg-js": "^2.6.2",
|
|
215
|
+
"@rrweb/record": "2.0.1",
|
|
214
216
|
"@sentry/browser": "10.60.0",
|
|
215
217
|
"@sentry/node": "10.60.0",
|
|
216
218
|
"@standard-schema/spec": "^1.1.0",
|
|
@@ -74,6 +74,9 @@ export interface AgentChatReference {
|
|
|
74
74
|
source: string;
|
|
75
75
|
refType?: string;
|
|
76
76
|
refId?: string;
|
|
77
|
+
slotKey?: string;
|
|
78
|
+
slotLabel?: string;
|
|
79
|
+
metadata?: Record<string, unknown>;
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
export interface MentionProviderItem {
|
|
@@ -84,6 +87,25 @@ export interface MentionProviderItem {
|
|
|
84
87
|
refType: string;
|
|
85
88
|
refId?: string;
|
|
86
89
|
refPath?: string;
|
|
90
|
+
slotKey?: string;
|
|
91
|
+
slotLabel?: string;
|
|
92
|
+
metadata?: Record<string, unknown>;
|
|
93
|
+
clearsSlots?: string[];
|
|
94
|
+
relatedReferences?: MentionProviderReference[];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface MentionProviderReference {
|
|
98
|
+
label: string;
|
|
99
|
+
icon?: string;
|
|
100
|
+
source?: string;
|
|
101
|
+
refType: string;
|
|
102
|
+
refId?: string | null;
|
|
103
|
+
refPath?: string | null;
|
|
104
|
+
slotKey?: string;
|
|
105
|
+
slotLabel?: string;
|
|
106
|
+
metadata?: Record<string, unknown>;
|
|
107
|
+
clearsSlots?: string[];
|
|
108
|
+
relatedReferences?: MentionProviderReference[];
|
|
87
109
|
}
|
|
88
110
|
|
|
89
111
|
export interface MentionProvider {
|
|
@@ -179,6 +179,7 @@ const AGENT_PANEL_ROOT_STYLE = {
|
|
|
179
179
|
} satisfies React.CSSProperties;
|
|
180
180
|
type AgentPanelStyle = React.CSSProperties & {
|
|
181
181
|
"--agent-sidebar-closed-transform"?: string;
|
|
182
|
+
"--agent-sidebar-inner-closed-transform"?: string;
|
|
182
183
|
"--agent-sidebar-width"?: string;
|
|
183
184
|
};
|
|
184
185
|
const AGENT_PANEL_HEADER_CLASS =
|
|
@@ -383,11 +384,15 @@ export function shouldShowAgentPanelChatTabBar(
|
|
|
383
384
|
}
|
|
384
385
|
|
|
385
386
|
export function shouldShowAgentPanelPageNewChatButton(
|
|
386
|
-
|
|
387
|
+
tabs: MultiTabAssistantChatHeaderProps["tabs"],
|
|
387
388
|
activeTabId: string,
|
|
388
|
-
|
|
389
|
+
activeTabMessageCount: number,
|
|
389
390
|
) {
|
|
390
|
-
|
|
391
|
+
if (!activeTabId) return false;
|
|
392
|
+
if (activeTabMessageCount > 0) return true;
|
|
393
|
+
|
|
394
|
+
const activeTab = tabs.find((tab) => tab.id === activeTabId);
|
|
395
|
+
return activeTab?.status === "running" || activeTab?.status === "completed";
|
|
391
396
|
}
|
|
392
397
|
|
|
393
398
|
export function shouldShowAgentPanelCliTabBar(cliTabs: string[]) {
|
|
@@ -2333,6 +2338,10 @@ export interface AgentSidebarProps {
|
|
|
2333
2338
|
suggestions?: string[];
|
|
2334
2339
|
/** Context-aware suggestions merged with `suggestions`. Enabled by default. */
|
|
2335
2340
|
dynamicSuggestions?: AssistantChatProps["dynamicSuggestions"];
|
|
2341
|
+
/** Optional controls rendered in the chat composer toolbar. */
|
|
2342
|
+
composerToolbarSlot?: AssistantChatProps["composerToolbarSlot"];
|
|
2343
|
+
/** Optional content rendered at the bottom of the chat thread. */
|
|
2344
|
+
threadFooterSlot?: AssistantChatProps["threadFooterSlot"];
|
|
2336
2345
|
/** Initial sidebar width in pixels. Mount-only; user resize and a saved
|
|
2337
2346
|
* localStorage value override this. Default: 380 */
|
|
2338
2347
|
defaultSidebarWidth?: number;
|
|
@@ -2379,6 +2388,8 @@ export function AgentSidebar({
|
|
|
2379
2388
|
emptyStateText = "How can I help you?",
|
|
2380
2389
|
suggestions,
|
|
2381
2390
|
dynamicSuggestions,
|
|
2391
|
+
composerToolbarSlot,
|
|
2392
|
+
threadFooterSlot,
|
|
2382
2393
|
defaultSidebarWidth,
|
|
2383
2394
|
sidebarWidth,
|
|
2384
2395
|
position = "right",
|
|
@@ -2849,6 +2860,7 @@ export function AgentSidebar({
|
|
|
2849
2860
|
panelStyle = {
|
|
2850
2861
|
...AGENT_PANEL_ROOT_STYLE,
|
|
2851
2862
|
"--agent-sidebar-width": `${width}px`,
|
|
2863
|
+
"--agent-sidebar-inner-closed-transform": `translateX(${isLeft ? "-" : ""}100%)`,
|
|
2852
2864
|
width: desktopAnimationEnabled ? undefined : width,
|
|
2853
2865
|
maxHeight: "100vh",
|
|
2854
2866
|
borderLeft:
|
|
@@ -2894,21 +2906,25 @@ export function AgentSidebar({
|
|
|
2894
2906
|
inert={sidebarAnimationEnabled && !panelOpen ? true : undefined}
|
|
2895
2907
|
aria-hidden={sidebarAnimationEnabled && !panelOpen ? true : undefined}
|
|
2896
2908
|
>
|
|
2897
|
-
<
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2909
|
+
<div className="agent-sidebar-panel-inner flex min-h-0 flex-1 flex-col">
|
|
2910
|
+
<AgentPanel
|
|
2911
|
+
emptyStateText={emptyStateText}
|
|
2912
|
+
suggestions={suggestions}
|
|
2913
|
+
dynamicSuggestions={dynamicSuggestions}
|
|
2914
|
+
composerToolbarSlot={composerToolbarSlot}
|
|
2915
|
+
threadFooterSlot={threadFooterSlot}
|
|
2916
|
+
missingApiKeySetupLayout="sidebar"
|
|
2917
|
+
onCollapse={() => setOpenPersisted(false)}
|
|
2918
|
+
isFullscreen={effectiveFullscreen}
|
|
2919
|
+
onToggleFullscreen={
|
|
2920
|
+
isMobile ? undefined : (onFullscreenRequest ?? toggleFullscreen)
|
|
2921
|
+
}
|
|
2922
|
+
storageKey={storageKey}
|
|
2923
|
+
scope={scope}
|
|
2924
|
+
browserTabId={browserTabId}
|
|
2925
|
+
threadUrlSync={threadUrlSync}
|
|
2926
|
+
/>
|
|
2927
|
+
</div>
|
|
2912
2928
|
</div>
|
|
2913
2929
|
{showResizeHandle && isLeft && (
|
|
2914
2930
|
<ResizeHandle position={position} onDrag={handleDrag} />
|
|
@@ -601,6 +601,13 @@ export interface AssistantChatHandle {
|
|
|
601
601
|
exportThreadSnapshot(): ChatThreadSnapshot | null;
|
|
602
602
|
}
|
|
603
603
|
|
|
604
|
+
export type AssistantChatThreadFooterSlot =
|
|
605
|
+
| React.ReactNode
|
|
606
|
+
| ((context: {
|
|
607
|
+
threadId: string | null;
|
|
608
|
+
tabId: string | null;
|
|
609
|
+
}) => React.ReactNode);
|
|
610
|
+
|
|
604
611
|
export interface AssistantChatAdapterContext {
|
|
605
612
|
apiUrl: string;
|
|
606
613
|
tabId?: string;
|
|
@@ -638,6 +645,8 @@ export interface AssistantChatProps {
|
|
|
638
645
|
suggestions?: string[];
|
|
639
646
|
/** Context-aware suggestions merged with `suggestions`. Enabled by default. */
|
|
640
647
|
dynamicSuggestions?: AgentDynamicSuggestionsOption;
|
|
648
|
+
/** Optional content rendered at the bottom of the scrollable thread, after messages. */
|
|
649
|
+
threadFooterSlot?: AssistantChatThreadFooterSlot;
|
|
641
650
|
/** Optional content rendered in the empty state, above the suggestion buttons. */
|
|
642
651
|
emptyStateAddon?: React.ReactNode;
|
|
643
652
|
/** Whether to show the header bar. Default: true */
|
|
@@ -952,6 +961,7 @@ const AssistantChatInner = forwardRef<
|
|
|
952
961
|
emptyStateText,
|
|
953
962
|
suggestions,
|
|
954
963
|
dynamicSuggestions,
|
|
964
|
+
threadFooterSlot,
|
|
955
965
|
emptyStateAddon,
|
|
956
966
|
showHeader = true,
|
|
957
967
|
onSwitchToCli,
|
|
@@ -2870,6 +2880,14 @@ const AssistantChatInner = forwardRef<
|
|
|
2870
2880
|
isAutoResuming ||
|
|
2871
2881
|
queuedMessages.length > 0 ||
|
|
2872
2882
|
reconnectContent.length > 0;
|
|
2883
|
+
const resolvedThreadFooterSlot =
|
|
2884
|
+
typeof threadFooterSlot === "function"
|
|
2885
|
+
? threadFooterSlot({
|
|
2886
|
+
threadId: threadId ?? null,
|
|
2887
|
+
tabId: tabId ?? null,
|
|
2888
|
+
})
|
|
2889
|
+
: threadFooterSlot;
|
|
2890
|
+
const hasThreadFooterSlot = Boolean(resolvedThreadFooterSlot);
|
|
2873
2891
|
const isFreshEmptyChat =
|
|
2874
2892
|
messages.length === 0 &&
|
|
2875
2893
|
!hasActiveChatWork &&
|
|
@@ -2887,6 +2905,13 @@ const AssistantChatInner = forwardRef<
|
|
|
2887
2905
|
centerComposerWhenEmpty && (isFreshEmptyChat || centeredRestoringState);
|
|
2888
2906
|
const showEmptyState =
|
|
2889
2907
|
messages.length === 0 && !isReconnecting && !hasActiveChatWork;
|
|
2908
|
+
const showInlineEmptyThreadFooterSlot =
|
|
2909
|
+
showEmptyState &&
|
|
2910
|
+
!centeredEmptyState &&
|
|
2911
|
+
!isRestoring &&
|
|
2912
|
+
hasThreadFooterSlot;
|
|
2913
|
+
const showCenteredEmptyThreadFooterSlot =
|
|
2914
|
+
centeredEmptyState && !isRestoring && hasThreadFooterSlot;
|
|
2890
2915
|
const showComposerSlot =
|
|
2891
2916
|
Boolean(composerSlot) && (!centerComposerWhenEmpty || centeredEmptyState);
|
|
2892
2917
|
|
|
@@ -3139,6 +3164,11 @@ const AssistantChatInner = forwardRef<
|
|
|
3139
3164
|
))}
|
|
3140
3165
|
</div>
|
|
3141
3166
|
) : null}
|
|
3167
|
+
{showInlineEmptyThreadFooterSlot ? (
|
|
3168
|
+
<div className="agent-thread-footer-slot agent-thread-footer-slot--empty">
|
|
3169
|
+
{resolvedThreadFooterSlot}
|
|
3170
|
+
</div>
|
|
3171
|
+
) : null}
|
|
3142
3172
|
</div>
|
|
3143
3173
|
) : (
|
|
3144
3174
|
<div className="agent-thread-content flex flex-col gap-4 px-4 py-4">
|
|
@@ -3266,6 +3296,11 @@ const AssistantChatInner = forwardRef<
|
|
|
3266
3296
|
</div>
|
|
3267
3297
|
);
|
|
3268
3298
|
})}
|
|
3299
|
+
{resolvedThreadFooterSlot ? (
|
|
3300
|
+
<div className="agent-thread-footer-slot">
|
|
3301
|
+
{resolvedThreadFooterSlot}
|
|
3302
|
+
</div>
|
|
3303
|
+
) : null}
|
|
3269
3304
|
</div>
|
|
3270
3305
|
)}
|
|
3271
3306
|
</div>
|
|
@@ -3285,6 +3320,11 @@ const AssistantChatInner = forwardRef<
|
|
|
3285
3320
|
)}
|
|
3286
3321
|
|
|
3287
3322
|
{showComposerSlot ? composerSlot : null}
|
|
3323
|
+
{showCenteredEmptyThreadFooterSlot ? (
|
|
3324
|
+
<div className="agent-thread-footer-slot agent-thread-footer-slot--centered-empty">
|
|
3325
|
+
{resolvedThreadFooterSlot}
|
|
3326
|
+
</div>
|
|
3327
|
+
) : null}
|
|
3288
3328
|
{guidedQuestions && guidedQuestions.length > 0 && (
|
|
3289
3329
|
<div className="shrink-0 px-3 pb-2 pt-1">
|
|
3290
3330
|
<div className="rounded-lg border border-border bg-card/60 shadow-sm">
|
|
@@ -117,6 +117,37 @@ export interface AgentChatContextState {
|
|
|
117
117
|
updatedAt: number;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
export interface AgentComposerReference {
|
|
121
|
+
label: string;
|
|
122
|
+
icon?: string;
|
|
123
|
+
source?: string;
|
|
124
|
+
refType: string;
|
|
125
|
+
refId?: string | null;
|
|
126
|
+
refPath?: string | null;
|
|
127
|
+
/** Stable composer slot this reference occupies. Slot references replace older values. */
|
|
128
|
+
slotKey?: string;
|
|
129
|
+
/** Short label shown before the selected value in the composer chip. */
|
|
130
|
+
slotLabel?: string;
|
|
131
|
+
/** Additional app-defined data used by the client for filtering and grouping. */
|
|
132
|
+
metadata?: Record<string, unknown>;
|
|
133
|
+
/** Slots to remove when this reference is inserted or removed. */
|
|
134
|
+
clearsSlots?: string[];
|
|
135
|
+
/** Additional references to insert before this one. */
|
|
136
|
+
relatedReferences?: AgentComposerReference[];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface AgentComposerReferenceInsertOptions {
|
|
140
|
+
/**
|
|
141
|
+
* Whether to open the agent sidebar before inserting the reference.
|
|
142
|
+
* Defaults to false so contextual auto-tags can stay quiet.
|
|
143
|
+
*/
|
|
144
|
+
openSidebar?: boolean;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface AgentComposerReferenceInsertPayload extends AgentComposerReference {
|
|
148
|
+
insertMessageId: string;
|
|
149
|
+
}
|
|
150
|
+
|
|
120
151
|
export interface AgentChatContextMutationOptions {
|
|
121
152
|
/**
|
|
122
153
|
* Whether to open the agent sidebar if it's currently hidden.
|
|
@@ -140,6 +171,10 @@ export const AGENT_CHAT_REMOVE_CONTEXT_MESSAGE_TYPE =
|
|
|
140
171
|
"agentNative.removeChatContext";
|
|
141
172
|
export const AGENT_CHAT_CLEAR_CONTEXT_MESSAGE_TYPE =
|
|
142
173
|
"agentNative.clearChatContext";
|
|
174
|
+
export const AGENT_CHAT_INSERT_REFERENCE_MESSAGE_TYPE =
|
|
175
|
+
"agentNative.insertComposerReference";
|
|
176
|
+
export const AGENT_CHAT_INSERT_REFERENCE_EVENT =
|
|
177
|
+
"agentNative:insert-composer-reference";
|
|
143
178
|
const AGENT_PANEL_PREPARE_EVENT = "agent-panel:prepare";
|
|
144
179
|
|
|
145
180
|
let agentChatContextState: AgentChatContextState = {
|
|
@@ -406,6 +441,82 @@ export function appendAgentChatContextToMessage(
|
|
|
406
441
|
return `${message.trim()}\n\n<context>\n${trimmedContext}\n</context>`;
|
|
407
442
|
}
|
|
408
443
|
|
|
444
|
+
function normalizeStringArray(value: unknown): string[] | undefined {
|
|
445
|
+
if (!Array.isArray(value)) return undefined;
|
|
446
|
+
const normalized = value
|
|
447
|
+
.filter((item): item is string => typeof item === "string")
|
|
448
|
+
.map((item) => item.trim())
|
|
449
|
+
.filter(Boolean);
|
|
450
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function normalizeMetadata(
|
|
454
|
+
value: unknown,
|
|
455
|
+
): Record<string, unknown> | undefined {
|
|
456
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
457
|
+
return undefined;
|
|
458
|
+
}
|
|
459
|
+
return value as Record<string, unknown>;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function normalizeAgentComposerReferenceInternal(
|
|
463
|
+
value: unknown,
|
|
464
|
+
depth: number,
|
|
465
|
+
): AgentComposerReference | null {
|
|
466
|
+
if (typeof value !== "object" || value === null) return null;
|
|
467
|
+
const candidate = value as Partial<AgentComposerReference>;
|
|
468
|
+
const label =
|
|
469
|
+
typeof candidate.label === "string" ? candidate.label.trim() : "";
|
|
470
|
+
const refType =
|
|
471
|
+
typeof candidate.refType === "string" ? candidate.refType.trim() : "";
|
|
472
|
+
if (!label || !refType) return null;
|
|
473
|
+
const normalized: AgentComposerReference = {
|
|
474
|
+
label,
|
|
475
|
+
icon:
|
|
476
|
+
typeof candidate.icon === "string" && candidate.icon.trim()
|
|
477
|
+
? candidate.icon.trim()
|
|
478
|
+
: undefined,
|
|
479
|
+
source:
|
|
480
|
+
typeof candidate.source === "string" && candidate.source.trim()
|
|
481
|
+
? candidate.source.trim()
|
|
482
|
+
: undefined,
|
|
483
|
+
refType,
|
|
484
|
+
refId:
|
|
485
|
+
typeof candidate.refId === "string" && candidate.refId.trim()
|
|
486
|
+
? candidate.refId.trim()
|
|
487
|
+
: null,
|
|
488
|
+
refPath:
|
|
489
|
+
typeof candidate.refPath === "string" && candidate.refPath.trim()
|
|
490
|
+
? candidate.refPath.trim()
|
|
491
|
+
: null,
|
|
492
|
+
};
|
|
493
|
+
const slotKey =
|
|
494
|
+
typeof candidate.slotKey === "string" ? candidate.slotKey.trim() : "";
|
|
495
|
+
if (slotKey) normalized.slotKey = slotKey;
|
|
496
|
+
const slotLabel =
|
|
497
|
+
typeof candidate.slotLabel === "string" ? candidate.slotLabel.trim() : "";
|
|
498
|
+
if (slotLabel) normalized.slotLabel = slotLabel;
|
|
499
|
+
const metadata = normalizeMetadata(candidate.metadata);
|
|
500
|
+
if (metadata) normalized.metadata = metadata;
|
|
501
|
+
const clearsSlots = normalizeStringArray(candidate.clearsSlots);
|
|
502
|
+
if (clearsSlots) normalized.clearsSlots = clearsSlots;
|
|
503
|
+
if (depth < 3 && Array.isArray(candidate.relatedReferences)) {
|
|
504
|
+
const relatedReferences = candidate.relatedReferences
|
|
505
|
+
.map((item) => normalizeAgentComposerReferenceInternal(item, depth + 1))
|
|
506
|
+
.filter((item): item is AgentComposerReference => item !== null);
|
|
507
|
+
if (relatedReferences.length > 0) {
|
|
508
|
+
normalized.relatedReferences = relatedReferences;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return normalized;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
export function normalizeAgentComposerReference(
|
|
515
|
+
value: unknown,
|
|
516
|
+
): AgentComposerReference | null {
|
|
517
|
+
return normalizeAgentComposerReferenceInternal(value, 0);
|
|
518
|
+
}
|
|
519
|
+
|
|
409
520
|
function postAgentChatContextMessage(
|
|
410
521
|
type:
|
|
411
522
|
| typeof AGENT_CHAT_SET_CONTEXT_MESSAGE_TYPE
|
|
@@ -446,6 +557,51 @@ function postAgentChatContextMessage(
|
|
|
446
557
|
}
|
|
447
558
|
}
|
|
448
559
|
|
|
560
|
+
function postAgentChatReferenceMessage(
|
|
561
|
+
payload: AgentComposerReferenceInsertPayload,
|
|
562
|
+
options: { openSidebar: boolean },
|
|
563
|
+
): void {
|
|
564
|
+
if (typeof window === "undefined") return;
|
|
565
|
+
|
|
566
|
+
const message = {
|
|
567
|
+
type: AGENT_CHAT_INSERT_REFERENCE_MESSAGE_TYPE,
|
|
568
|
+
data: payload,
|
|
569
|
+
};
|
|
570
|
+
const targetSelf = isInBuilderFrame() || isDirectMcpAppEmbedSession();
|
|
571
|
+
const target = targetSelf
|
|
572
|
+
? window
|
|
573
|
+
: window.parent !== window
|
|
574
|
+
? window.parent
|
|
575
|
+
: window;
|
|
576
|
+
const targetOrigin = targetSelf
|
|
577
|
+
? window.location.origin
|
|
578
|
+
: getFramePostMessageTargetOrigin() || window.location.origin;
|
|
579
|
+
|
|
580
|
+
if (options.openSidebar) {
|
|
581
|
+
window.dispatchEvent(
|
|
582
|
+
new CustomEvent("agent-panel:set-mode", {
|
|
583
|
+
detail: { mode: "chat" },
|
|
584
|
+
}),
|
|
585
|
+
);
|
|
586
|
+
window.dispatchEvent(new CustomEvent("agent-panel:open"));
|
|
587
|
+
} else {
|
|
588
|
+
window.dispatchEvent(new CustomEvent(AGENT_PANEL_PREPARE_EVENT));
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
window.dispatchEvent(
|
|
592
|
+
new CustomEvent(AGENT_CHAT_INSERT_REFERENCE_EVENT, {
|
|
593
|
+
detail: payload,
|
|
594
|
+
}),
|
|
595
|
+
);
|
|
596
|
+
|
|
597
|
+
const postToTarget = () => target.postMessage(message, targetOrigin);
|
|
598
|
+
if (target === window) {
|
|
599
|
+
setTimeout(postToTarget, 0);
|
|
600
|
+
} else {
|
|
601
|
+
postToTarget();
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
449
605
|
function isMcpAppChatBridgeEnabled(): boolean {
|
|
450
606
|
if (typeof window === "undefined" || window.parent === window) return false;
|
|
451
607
|
if (readEmbedMcpChatBridgeFlagFromUrl()) markEmbedMcpChatBridgeActive();
|
|
@@ -685,6 +841,23 @@ export const setContextToAgentChat = setAgentChatContextItem;
|
|
|
685
841
|
/** @deprecated Use `setAgentChatContextItem` instead. */
|
|
686
842
|
export const addContextToAgentChat = setAgentChatContextItem;
|
|
687
843
|
|
|
844
|
+
export function insertAgentComposerReference(
|
|
845
|
+
ref: AgentComposerReference,
|
|
846
|
+
options: AgentComposerReferenceInsertOptions = {},
|
|
847
|
+
): void {
|
|
848
|
+
const normalized = normalizeAgentComposerReference(ref);
|
|
849
|
+
if (!normalized || typeof window === "undefined") return;
|
|
850
|
+
postAgentChatReferenceMessage(
|
|
851
|
+
{
|
|
852
|
+
...normalized,
|
|
853
|
+
insertMessageId: `reference-${Date.now()}-${Math.random()
|
|
854
|
+
.toString(36)
|
|
855
|
+
.slice(2, 8)}`,
|
|
856
|
+
},
|
|
857
|
+
{ openSidebar: options.openSidebar === true },
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
|
|
688
861
|
export function removeAgentChatContextItem(
|
|
689
862
|
keyOrOpts: string | AgentChatContextRemoveOptions,
|
|
690
863
|
): void {
|