@agent-native/core 0.80.10 → 0.81.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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +53 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +108 -15
- package/corpus/core/src/cli/design-connect.ts +419 -19
- package/corpus/core/src/client/AssistantChat.tsx +123 -26
- package/corpus/core/src/client/ConnectBuilderCard.tsx +1 -0
- package/corpus/core/src/client/chat/index.ts +1 -0
- package/corpus/core/src/client/chat/run-recovery.tsx +9 -7
- package/corpus/core/src/client/chat-view-transition.ts +33 -2
- package/corpus/core/src/client/composer/PromptComposer.tsx +21 -2
- package/corpus/core/src/client/index.ts +1 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +26 -4
- package/corpus/core/src/client/sharing/ShareButton.tsx +3 -3
- package/corpus/core/src/client/sse-event-processor.ts +9 -0
- package/corpus/core/src/client/use-agent-chat-home-handoff.ts +31 -3
- package/corpus/core/src/db/client.ts +29 -2
- package/corpus/core/src/provider-api/index.ts +29 -0
- package/corpus/core/src/server/core-routes-plugin.ts +58 -20
- package/corpus/core/src/styles/agent-native.css +54 -0
- package/corpus/core/src/usage/store.ts +2 -2
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +118 -10
- package/corpus/templates/analytics/app/components/layout/layout-route-policy.ts +7 -0
- package/corpus/templates/analytics/app/global.css +8 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +7 -1
- package/corpus/templates/analytics/app/lib/chat-handoff.ts +34 -0
- package/corpus/templates/analytics/app/pages/Ask.tsx +9 -18
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +2 -2
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +109 -21
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +4 -6
- package/corpus/templates/analytics/changelog/2026-06-30-ask-opens-a-fresh-chat-unless-you-were-just-chatting-and-das.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-dashboard-email-reports-are-more-reliable-and-use-cleaner.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-dashboard-toolbar-controls-use-a-quieter-share-button-and-ve.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-session-replay-rows-show-whole-minute-durations-in-the-playl.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-session-replays-now-render-captured-styling-and-keep-the-eve.md +6 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +16 -3
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +31 -14
- package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +9 -2
- package/corpus/templates/assets/AGENTS.md +4 -0
- package/corpus/templates/assets/actions/_tool-activity.ts +46 -0
- package/corpus/templates/assets/actions/generate-image-batch.ts +26 -5
- package/corpus/templates/assets/actions/generate-image.ts +118 -67
- package/corpus/templates/assets/actions/list-draft-assets.ts +50 -0
- package/corpus/templates/assets/actions/open-asset-picker.ts +9 -0
- package/corpus/templates/assets/actions/rerun-generation-run.ts +52 -31
- package/corpus/templates/assets/app/components/create/RecentDraftsSection.tsx +100 -0
- package/corpus/templates/assets/app/global.css +15 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +4 -0
- package/corpus/templates/assets/app/i18n/zh-TW.ts +7 -0
- package/corpus/templates/assets/app/i18n-data.ts +61 -0
- package/corpus/templates/assets/app/routes/_index.tsx +4 -0
- package/corpus/templates/assets/app/routes/library.tsx +233 -52
- package/corpus/templates/assets/changelog/2026-06-29-image-generation-can-now-render-requested-text-and-respect-b.md +6 -0
- package/corpus/templates/assets/changelog/2026-06-30-image-generation-no-longer-looks-stuck-while-the-provider-is-still-working.md +6 -0
- package/corpus/templates/assets/changelog/2026-06-30-tagged-presets-now-control-the-image-aspect-ratio.md +6 -0
- package/corpus/templates/assets/changelog/2026-06-30-the-assets-picker-now-supports-a-vertical-embedded-layout-fo.md +6 -0
- package/corpus/templates/assets/server/lib/generation.ts +135 -11
- package/corpus/templates/assets/shared/api.ts +4 -0
- package/corpus/templates/clips/actions/finalize-recording.ts +1 -12
- package/corpus/templates/clips/actions/list-ai-requests.ts +60 -0
- package/corpus/templates/clips/app/hooks/use-auto-title.ts +24 -25
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +10 -5
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -8
- package/corpus/templates/clips/changelog/2026-06-30-extension-save-recovery-avoids-false-upload-failures.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-30-longer-chrome-extension-recordings-now-keep-saving-reliably-.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/chrome-extension/src/background.ts +19 -10
- package/corpus/templates/clips/chrome-extension/src/content-script.ts +38 -12
- package/corpus/templates/clips/chrome-extension/src/finalize-recovery.ts +224 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +119 -16
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +16 -0
- package/corpus/templates/clips/server/lib/recording-upload-state.ts +48 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +9 -1
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +63 -13
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/status.get.ts +74 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +32 -0
- package/corpus/templates/design/AGENTS.md +27 -0
- package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +1 -1
- package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +5 -5
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +76 -25
- package/corpus/templates/design/actions/apply-design-state.ts +17 -4
- package/corpus/templates/design/actions/apply-motion-edit.ts +76 -115
- package/corpus/templates/design/actions/apply-shader-fill.ts +148 -56
- package/corpus/templates/design/actions/capture-design-state.ts +27 -4
- package/corpus/templates/design/actions/connect-localhost.ts +59 -22
- package/corpus/templates/design/actions/delete-design.ts +20 -0
- package/corpus/templates/design/actions/export-zip.ts +23 -8
- package/corpus/templates/design/actions/generate-design.ts +53 -1
- package/corpus/templates/design/actions/get-component-details.ts +21 -26
- package/corpus/templates/design/actions/get-motion-timeline.ts +135 -10
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +116 -0
- package/corpus/templates/design/actions/import-design-tokens.ts +521 -0
- package/corpus/templates/design/actions/index-design-tokens.ts +18 -5
- package/corpus/templates/design/actions/insert-design-native-asset.ts +268 -0
- package/corpus/templates/design/actions/insert-figma-library-asset.ts +233 -0
- package/corpus/templates/design/actions/list-design-extensions.ts +32 -10
- package/corpus/templates/design/actions/list-design-native-assets.ts +105 -0
- package/corpus/templates/design/actions/list-design-states.ts +19 -1
- package/corpus/templates/design/actions/list-figma-library-assets.ts +292 -0
- package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +238 -0
- package/corpus/templates/design/actions/navigate.ts +18 -3
- package/corpus/templates/design/actions/open-component-source.ts +7 -2
- package/corpus/templates/design/actions/preview-component-prop-edit.ts +32 -26
- package/corpus/templates/design/actions/preview-shader-fill.ts +9 -11
- package/corpus/templates/design/actions/provider-api-catalog.ts +2 -2
- package/corpus/templates/design/actions/provider-api-docs.ts +1 -1
- package/corpus/templates/design/actions/provider-api-request.ts +3 -3
- package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +48 -0
- package/corpus/templates/design/actions/run-design-audit.ts +74 -10
- package/corpus/templates/design/actions/run-design-extension-action.ts +1 -1
- package/corpus/templates/design/actions/view-screen.ts +1 -1
- package/corpus/templates/design/actions/write-local-file.ts +213 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +244 -3197
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +30 -20
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +795 -289
- package/corpus/templates/design/app/components/design/EditPanel.tsx +635 -234
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +124 -32
- package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +161 -0
- package/corpus/templates/design/app/components/design/MotionDock.tsx +244 -266
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +491 -56
- package/corpus/templates/design/app/components/design/ReviewPanel.tsx +55 -67
- package/corpus/templates/design/app/components/design/StatesPanel.tsx +38 -63
- package/corpus/templates/design/app/components/design/TokensPanel.tsx +264 -8
- package/corpus/templates/design/app/components/design/bridge/codegen.ts +125 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +4037 -0
- package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +62 -0
- package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +272 -0
- package/corpus/templates/design/app/components/design/bridge/nav.bridge.ts +116 -0
- package/corpus/templates/design/app/components/design/bridge/sample.bridge.ts +24 -0
- package/corpus/templates/design/app/components/design/bridge/shader-fill-preview.bridge.ts +78 -0
- package/corpus/templates/design/app/components/design/bridge/tsconfig.json +17 -0
- package/corpus/templates/design/app/components/design/bridge/tweak.bridge.ts +28 -0
- package/corpus/templates/design/app/components/design/bridge/zoom.bridge.ts +43 -0
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +45 -16
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +88 -9
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +94 -9
- package/corpus/templates/design/app/components/layout/Layout.tsx +19 -3
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/design/app/global.css +7 -0
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +23 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +22 -0
- package/corpus/templates/design/app/i18n-data.ts +369 -0
- package/corpus/templates/design/app/lib/pending-generation.ts +1 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +3024 -616
- package/corpus/templates/design/app/pages/Index.tsx +5 -1
- package/corpus/templates/design/changelog/2026-06-30-applying-the-one-click-fix-for-a-small-tap-target-accessibil.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-canvas-creation-screen-dragging-undo-redo-and-image-fill-edi.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-component-prop-edits-and-shader-fills-now-preserve-rapid-sam.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-can-browse-figma-library-components-and-insert-them-i.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-now-has-a-figma-style-left-rail-for-file-agent-assets.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-now-has-native-components-embedded-media-and-figma-im.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-preview-now-includes-a-publish-app-waitlist-option-fr.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-s-left-rail-now-matches-the-sidebar-chrome-and-uses-t.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-s-tools-create-menu-now-stays-compact-instead-of-rend.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-starter-prompts-now-begin-generating-immediately-and-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-token-edits-now-stay-visible-in-previews-and-token-li.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-tools-now-use-a-quieter-figma-style-list-layout.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-drawing-rectangles-on-the-all-screens-canvas-no-longer-flash.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-fixed-code-native-design-studio-edits-so-component-props-mot.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-fixed-visual-editing-hover-overlays-and-spacing-handles-so-s.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-motion-edits-now-save-automatically-without-a-separate-css-a.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-motion-timelines-now-reopen-as-editable-tracks-after-writing.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-new-design-prompts-with-uploaded-screenshots-work-reliably-o.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-screen-previews-in-all-screens-view-now-keep-rounded-outline.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-selection-outlines-now-sit-flush-on-rectangles-drawn-directl.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-share-options-use-a-tighter-design-editor-popover-with-compa.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-collapsed-motion-panel-now-stays-tucked-under-the-left-s.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-design-inspector-now-shows-states-and-review-in-a-tighte.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-sidebar-keeps-the-organization-picker-space-stable-while.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-tokens-can-now-be-imported-from-pasted-notes-code-files-fold.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +94 -2
- package/corpus/templates/design/e2e/helpers.ts +168 -65
- package/corpus/templates/design/package.json +3 -1
- package/corpus/templates/design/server/db/schema.ts +23 -0
- package/corpus/templates/design/server/handlers/uploads.ts +22 -1
- package/corpus/templates/design/server/lib/provider-api.ts +7 -4
- package/corpus/templates/design/server/lib/verify-write-grant.ts +108 -0
- package/corpus/templates/design/server/plugins/db.ts +39 -0
- package/corpus/templates/design/server/register-secrets.ts +38 -0
- package/corpus/templates/design/shared/board-file.ts +228 -0
- package/corpus/templates/design/shared/board-objects.ts +288 -0
- package/corpus/templates/design/shared/code-layer.ts +52 -0
- package/corpus/templates/design/shared/component-model.ts +35 -0
- package/corpus/templates/design/shared/motion-compiler.ts +137 -15
- package/corpus/templates/design/shared/motion-timeline.ts +2 -2
- package/corpus/templates/design/shared/resolve-tweaks.ts +32 -9
- package/corpus/templates/design/tsconfig.json +2 -1
- package/corpus/templates/slides/AGENTS.md +9 -0
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +4 -0
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +4 -24
- package/corpus/templates/slides/app/lib/export-pdf-client.ts +29 -20
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +365 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +12 -9
- package/corpus/templates/slides/app/vite-env.d.ts +18 -0
- package/corpus/templates/slides/changelog/2026-06-30-powerpoint-downloads-now-preserve-the-rendered-slide-layout-.md +6 -0
- package/corpus/templates/slides/changelog/2026-06-30-unavailable-decks-open-in-a-cleaner-full-height-centered-sta.md +6 -0
- package/corpus/templates/slides/package.json +1 -0
- package/corpus/templates/slides/vite.config.ts +1 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +94 -10
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/design-connect.d.ts +25 -0
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +357 -18
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +14 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +115 -22
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
- package/dist/client/ConnectBuilderCard.js +1 -0
- package/dist/client/ConnectBuilderCard.js.map +1 -1
- package/dist/client/chat/index.d.ts +1 -1
- package/dist/client/chat/index.d.ts.map +1 -1
- package/dist/client/chat/index.js +1 -1
- package/dist/client/chat/index.js.map +1 -1
- package/dist/client/chat/run-recovery.d.ts.map +1 -1
- package/dist/client/chat/run-recovery.js +5 -5
- package/dist/client/chat/run-recovery.js.map +1 -1
- package/dist/client/chat-view-transition.d.ts +6 -0
- package/dist/client/chat-view-transition.d.ts.map +1 -1
- package/dist/client/chat-view-transition.js +23 -2
- package/dist/client/chat-view-transition.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +3 -2
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +11 -4
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/sharing/ShareButton.js +3 -3
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +10 -0
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.d.ts +8 -2
- package/dist/client/use-agent-chat-home-handoff.d.ts.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.js +20 -6
- package/dist/client/use-agent-chat-home-handoff.js.map +1 -1
- 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/client.d.ts +1 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +28 -2
- package/dist/db/client.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/index.d.ts +5 -4
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +28 -0
- package/dist/provider-api/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts +25 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +43 -18
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/agent-native.css +54 -0
- package/dist/usage/store.js +2 -2
- package/dist/usage/store.js.map +1 -1
- package/package.json +1 -1
|
@@ -123,6 +123,33 @@ export function pgliteDataDirFromUrl(url: string): string {
|
|
|
123
123
|
return dataDir;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
export function pgliteRuntimeDataDir(dataDir: string): string {
|
|
127
|
+
if (dataDir === "memory://") return dataDir;
|
|
128
|
+
if (!isServerlessRuntime() || path.isAbsolute(dataDir)) return dataDir;
|
|
129
|
+
|
|
130
|
+
const safeParts = dataDir
|
|
131
|
+
.split(/[\\/]+/)
|
|
132
|
+
.filter((part) => part && part !== "." && part !== "..");
|
|
133
|
+
const safeRelative =
|
|
134
|
+
safeParts.length > 0
|
|
135
|
+
? path.join(...safeParts)
|
|
136
|
+
: path.join("data", "pglite");
|
|
137
|
+
return path.join("/tmp", safeRelative);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function preparePgliteDataDir(dataDir: string): Promise<string> {
|
|
141
|
+
const runtimeDataDir = pgliteRuntimeDataDir(dataDir);
|
|
142
|
+
if (runtimeDataDir === "memory://") return runtimeDataDir;
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
const fs = await import("fs");
|
|
146
|
+
fs.mkdirSync(runtimeDataDir, { recursive: true });
|
|
147
|
+
} catch {
|
|
148
|
+
// Edge runtimes may not expose fs. PGlite will surface any real open error.
|
|
149
|
+
}
|
|
150
|
+
return runtimeDataDir;
|
|
151
|
+
}
|
|
152
|
+
|
|
126
153
|
async function importOptionalModule(specifier: string): Promise<any> {
|
|
127
154
|
return import(/* @vite-ignore */ specifier);
|
|
128
155
|
}
|
|
@@ -170,7 +197,7 @@ export async function loadPgliteDrizzle(): Promise<{
|
|
|
170
197
|
const _pgliteClients = new Map<string, Promise<any>>();
|
|
171
198
|
|
|
172
199
|
export async function getPgliteClient(url: string): Promise<any> {
|
|
173
|
-
const dataDir = pgliteDataDirFromUrl(url);
|
|
200
|
+
const dataDir = await preparePgliteDataDir(pgliteDataDirFromUrl(url));
|
|
174
201
|
let ready = _pgliteClients.get(dataDir);
|
|
175
202
|
if (!ready) {
|
|
176
203
|
ready = loadPglitePackage().then(({ PGlite }) => PGlite.create(dataDir));
|
|
@@ -190,7 +217,7 @@ export async function closePgliteClients(): Promise<void> {
|
|
|
190
217
|
}
|
|
191
218
|
|
|
192
219
|
export async function closePgliteClient(url: string): Promise<void> {
|
|
193
|
-
const dataDir = pgliteDataDirFromUrl(url);
|
|
220
|
+
const dataDir = pgliteRuntimeDataDir(pgliteDataDirFromUrl(url));
|
|
194
221
|
const ready = _pgliteClients.get(dataDir);
|
|
195
222
|
_pgliteClients.delete(dataDir);
|
|
196
223
|
if (!ready) return;
|
|
@@ -58,6 +58,7 @@ export const PROVIDER_API_IDS = [
|
|
|
58
58
|
"ga4",
|
|
59
59
|
"gcloud",
|
|
60
60
|
"github",
|
|
61
|
+
"figma",
|
|
61
62
|
"gmail",
|
|
62
63
|
"gong",
|
|
63
64
|
"google_calendar",
|
|
@@ -374,6 +375,7 @@ export interface ProviderApiExample {
|
|
|
374
375
|
label: string;
|
|
375
376
|
method: ProviderApiMethod;
|
|
376
377
|
path: string;
|
|
378
|
+
query?: unknown;
|
|
377
379
|
body?: unknown;
|
|
378
380
|
}
|
|
379
381
|
|
|
@@ -777,6 +779,33 @@ const PROVIDER_CONFIGS: Record<ProviderApiId, ProviderApiConfig> = {
|
|
|
777
779
|
{ label: "Search issues", method: "GET", path: "/search/issues" },
|
|
778
780
|
],
|
|
779
781
|
},
|
|
782
|
+
figma: {
|
|
783
|
+
id: "figma",
|
|
784
|
+
label: "Figma REST API",
|
|
785
|
+
defaultBaseUrl: "https://api.figma.com/v1",
|
|
786
|
+
auth: {
|
|
787
|
+
type: "api-key-header",
|
|
788
|
+
key: "FIGMA_ACCESS_TOKEN",
|
|
789
|
+
header: "X-Figma-Token",
|
|
790
|
+
},
|
|
791
|
+
credentialKeys: ["FIGMA_ACCESS_TOKEN"],
|
|
792
|
+
docsUrls: ["https://www.figma.com/developers/api"],
|
|
793
|
+
allowedHostSuffixes: ["figma.com"],
|
|
794
|
+
templateUses: ["design"],
|
|
795
|
+
examples: [
|
|
796
|
+
{
|
|
797
|
+
label: "List file components",
|
|
798
|
+
method: "GET",
|
|
799
|
+
path: "/files/{fileKey}/components",
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
label: "Render file nodes",
|
|
803
|
+
method: "GET",
|
|
804
|
+
path: "/images/{fileKey}",
|
|
805
|
+
query: { ids: "1:2", format: "svg" },
|
|
806
|
+
},
|
|
807
|
+
],
|
|
808
|
+
},
|
|
780
809
|
gmail: {
|
|
781
810
|
id: "gmail",
|
|
782
811
|
label: "Gmail API",
|
|
@@ -236,6 +236,11 @@ export async function runDbHealthProbe(
|
|
|
236
236
|
const DEFAULT_BUILDER_WAITLIST_FORM_ID = "DYTHuM0jlV";
|
|
237
237
|
const DEFAULT_BUILDER_WAITLIST_FORMS_ORIGIN = "https://forms.agent-native.com";
|
|
238
238
|
const BUILDER_WAITLIST_FORM_SOURCE = "connect_builder_card";
|
|
239
|
+
const BUILDER_WAITLIST_DEFAULT_USE_CASE = "builder_agent_background_coding";
|
|
240
|
+
const BUILDER_WAITLIST_USE_CASES = new Set([
|
|
241
|
+
BUILDER_WAITLIST_DEFAULT_USE_CASE,
|
|
242
|
+
"design_publish_app",
|
|
243
|
+
]);
|
|
239
244
|
const BUILDER_WAITLIST_FORM_TIMEOUT_MS = 8000;
|
|
240
245
|
const BUILDER_WAITLIST_TEXT_LIMIT = 4000;
|
|
241
246
|
|
|
@@ -244,12 +249,13 @@ interface BuilderWaitlistFormTarget {
|
|
|
244
249
|
formsOrigin: string;
|
|
245
250
|
}
|
|
246
251
|
|
|
247
|
-
interface BuilderWaitlistBody {
|
|
252
|
+
export interface BuilderWaitlistBody {
|
|
248
253
|
prompt?: unknown;
|
|
249
254
|
orgName?: unknown;
|
|
250
255
|
appUrl?: unknown;
|
|
251
256
|
pageUrl?: unknown;
|
|
252
257
|
source?: unknown;
|
|
258
|
+
useCase?: unknown;
|
|
253
259
|
}
|
|
254
260
|
|
|
255
261
|
export function resolveFrameworkSseRoutes(sseRoute?: string): string[] {
|
|
@@ -274,6 +280,13 @@ function cleanBuilderWaitlistText(
|
|
|
274
280
|
return trimmed.slice(0, maxLength);
|
|
275
281
|
}
|
|
276
282
|
|
|
283
|
+
function normalizeBuilderWaitlistUseCase(value: unknown): string {
|
|
284
|
+
const useCase = cleanBuilderWaitlistText(value, 100);
|
|
285
|
+
return useCase && BUILDER_WAITLIST_USE_CASES.has(useCase)
|
|
286
|
+
? useCase
|
|
287
|
+
: BUILDER_WAITLIST_DEFAULT_USE_CASE;
|
|
288
|
+
}
|
|
289
|
+
|
|
277
290
|
function normalizeHttpOrigin(value: string): string | null {
|
|
278
291
|
try {
|
|
279
292
|
const url = new URL(value);
|
|
@@ -317,20 +330,45 @@ export function resolveBuilderWaitlistFormTargetForRequest(
|
|
|
317
330
|
return { formId, formsOrigin };
|
|
318
331
|
}
|
|
319
332
|
|
|
320
|
-
|
|
333
|
+
export function buildBuilderWaitlistFormPayload(
|
|
321
334
|
event: H3Event,
|
|
322
335
|
sessionEmail: string,
|
|
323
336
|
body: BuilderWaitlistBody,
|
|
324
|
-
)
|
|
325
|
-
const target = resolveBuilderWaitlistFormTargetForRequest(event);
|
|
326
|
-
if (!target) return { submitted: false };
|
|
327
|
-
|
|
337
|
+
) {
|
|
328
338
|
const appUrl =
|
|
329
339
|
cleanBuilderWaitlistText(body.pageUrl ?? body.appUrl, 2000) ??
|
|
330
340
|
cleanBuilderWaitlistText(getHeader(event, "referer"), 2000) ??
|
|
331
341
|
getOrigin(event);
|
|
332
342
|
const source =
|
|
333
343
|
cleanBuilderWaitlistText(body.source, 100) ?? BUILDER_WAITLIST_FORM_SOURCE;
|
|
344
|
+
const useCase = normalizeBuilderWaitlistUseCase(body.useCase);
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
data: {
|
|
348
|
+
email: sessionEmail,
|
|
349
|
+
orgName: cleanBuilderWaitlistText(body.orgName, 500),
|
|
350
|
+
appUrl,
|
|
351
|
+
prompt: cleanBuilderWaitlistText(body.prompt),
|
|
352
|
+
source,
|
|
353
|
+
useCase,
|
|
354
|
+
},
|
|
355
|
+
_hp: "",
|
|
356
|
+
_meta: {
|
|
357
|
+
submitterEmail: sessionEmail,
|
|
358
|
+
pageUrl: appUrl,
|
|
359
|
+
source,
|
|
360
|
+
useCase,
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
async function submitBuilderWaitlistForm(
|
|
366
|
+
event: H3Event,
|
|
367
|
+
sessionEmail: string,
|
|
368
|
+
body: BuilderWaitlistBody,
|
|
369
|
+
): Promise<{ submitted: boolean; formId?: string }> {
|
|
370
|
+
const target = resolveBuilderWaitlistFormTargetForRequest(event);
|
|
371
|
+
if (!target) return { submitted: false };
|
|
334
372
|
|
|
335
373
|
const controller = new AbortController();
|
|
336
374
|
const timeout = setTimeout(
|
|
@@ -344,20 +382,9 @@ async function submitBuilderWaitlistForm(
|
|
|
344
382
|
{
|
|
345
383
|
method: "POST",
|
|
346
384
|
headers: { "Content-Type": "application/json" },
|
|
347
|
-
body: JSON.stringify(
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
orgName: cleanBuilderWaitlistText(body.orgName, 500),
|
|
351
|
-
appUrl,
|
|
352
|
-
prompt: cleanBuilderWaitlistText(body.prompt),
|
|
353
|
-
source,
|
|
354
|
-
},
|
|
355
|
-
_hp: "",
|
|
356
|
-
_meta: {
|
|
357
|
-
submitterEmail: sessionEmail,
|
|
358
|
-
pageUrl: appUrl,
|
|
359
|
-
},
|
|
360
|
-
}),
|
|
385
|
+
body: JSON.stringify(
|
|
386
|
+
buildBuilderWaitlistFormPayload(event, sessionEmail, body),
|
|
387
|
+
),
|
|
361
388
|
signal: controller.signal,
|
|
362
389
|
},
|
|
363
390
|
);
|
|
@@ -1671,6 +1698,13 @@ export function createCoreRoutesPlugin(
|
|
|
1671
1698
|
}
|
|
1672
1699
|
const body = ((await readBody(event).catch(() => ({}))) ??
|
|
1673
1700
|
{}) as BuilderWaitlistBody;
|
|
1701
|
+
const waitlistPayload = buildBuilderWaitlistFormPayload(
|
|
1702
|
+
event,
|
|
1703
|
+
session.email,
|
|
1704
|
+
body,
|
|
1705
|
+
);
|
|
1706
|
+
const waitlistSource = waitlistPayload.data.source;
|
|
1707
|
+
const waitlistUseCase = waitlistPayload.data.useCase;
|
|
1674
1708
|
let formSubmission: { submitted: boolean; formId?: string };
|
|
1675
1709
|
try {
|
|
1676
1710
|
formSubmission = await submitBuilderWaitlistForm(
|
|
@@ -1686,7 +1720,9 @@ export function createCoreRoutesPlugin(
|
|
|
1686
1720
|
{
|
|
1687
1721
|
reason:
|
|
1688
1722
|
err instanceof Error ? err.message : "unknown_waitlist_error",
|
|
1723
|
+
source: waitlistSource,
|
|
1689
1724
|
stage: "waitlist",
|
|
1725
|
+
useCase: waitlistUseCase,
|
|
1690
1726
|
},
|
|
1691
1727
|
);
|
|
1692
1728
|
setResponseStatus(event, 502);
|
|
@@ -1702,7 +1738,9 @@ export function createCoreRoutesPlugin(
|
|
|
1702
1738
|
{
|
|
1703
1739
|
formId: formSubmission.formId ?? null,
|
|
1704
1740
|
formSubmitted: formSubmission.submitted,
|
|
1741
|
+
source: waitlistSource,
|
|
1705
1742
|
stage: "waitlist",
|
|
1743
|
+
useCase: waitlistUseCase,
|
|
1706
1744
|
},
|
|
1707
1745
|
);
|
|
1708
1746
|
return { ok: true, formSubmitted: formSubmission.submitted };
|
|
@@ -537,6 +537,60 @@
|
|
|
537
537
|
}
|
|
538
538
|
}
|
|
539
539
|
|
|
540
|
+
/* Connect AI card: use the card width, not the viewport, so narrow embedded
|
|
541
|
+
sidebars stack the copy and actions before the secondary button clips. */
|
|
542
|
+
.agent-builder-setup-card {
|
|
543
|
+
min-inline-size: min(18rem, 100%);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
.agent-builder-setup-card--sidebar {
|
|
547
|
+
container-type: inline-size;
|
|
548
|
+
container-name: agent-builder-setup;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
@container agent-builder-setup (max-width: 560px) {
|
|
552
|
+
.agent-builder-setup-card__content {
|
|
553
|
+
align-items: stretch;
|
|
554
|
+
flex-direction: column;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
.agent-builder-setup-card__actions {
|
|
558
|
+
align-items: center;
|
|
559
|
+
flex-direction: row;
|
|
560
|
+
flex-wrap: wrap;
|
|
561
|
+
gap: 0.5rem;
|
|
562
|
+
width: 100%;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
.agent-builder-setup-card__builder-cta {
|
|
566
|
+
align-items: stretch;
|
|
567
|
+
flex: 1 1 11rem;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
.agent-builder-setup-card__builder-button,
|
|
571
|
+
.agent-builder-setup-card__key-button {
|
|
572
|
+
justify-content: center;
|
|
573
|
+
min-width: 0;
|
|
574
|
+
width: 100%;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
.agent-builder-setup-card__key-button {
|
|
578
|
+
border: 1px solid hsl(var(--border));
|
|
579
|
+
background: hsl(var(--background));
|
|
580
|
+
color: hsl(var(--foreground));
|
|
581
|
+
flex: 1 1 8rem;
|
|
582
|
+
height: 2rem;
|
|
583
|
+
padding-inline: 0.75rem;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
@container agent-builder-setup (max-width: 360px) {
|
|
588
|
+
.agent-builder-setup-card__actions {
|
|
589
|
+
align-items: stretch;
|
|
590
|
+
flex-direction: column;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
540
594
|
.agent-composer-area--hero {
|
|
541
595
|
padding-inline: 0;
|
|
542
596
|
padding-block: 0.5rem;
|
|
@@ -112,12 +112,12 @@ const PRICING: Array<{ match: RegExp; pricing: ModelPricing }> = [
|
|
|
112
112
|
// ── Google Gemini ───────────────────────────────────────────────────────────
|
|
113
113
|
// Gemini 3 Pro / 3.1 Pro: ~$1.25/$10 per MTok (approximate; verify on billing)
|
|
114
114
|
{
|
|
115
|
-
match: /gemini-3[
|
|
115
|
+
match: /gemini-3[.-]1-pro/i,
|
|
116
116
|
pricing: { input: 125, output: 1000, cacheRead: 31, cacheWrite: 0 },
|
|
117
117
|
},
|
|
118
118
|
// Gemini 3.5 Flash / 3 Flash: ~$0.15/$0.60 per MTok
|
|
119
119
|
{
|
|
120
|
-
match: /gemini-3[
|
|
120
|
+
match: /gemini-3[.-][0-9]+-flash/i,
|
|
121
121
|
pricing: { input: 15, output: 60, cacheRead: 4, cacheWrite: 0 },
|
|
122
122
|
},
|
|
123
123
|
// Gemini 2.5 Pro/Flash (catch-all for older 2.5)
|
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
import {
|
|
2
|
+
appBasePath,
|
|
2
3
|
AgentSidebar,
|
|
3
4
|
GuidedQuestionFlow,
|
|
4
5
|
focusAgentChat,
|
|
6
|
+
markAgentChatHomeHandoff,
|
|
5
7
|
navigateWithAgentChatViewTransition,
|
|
6
8
|
useAgentChatHomeHandoff,
|
|
7
|
-
useAgentChatHomeHandoffLinks,
|
|
8
9
|
useGuidedQuestionFlow,
|
|
9
10
|
useT,
|
|
10
11
|
} from "@agent-native/core/client";
|
|
11
12
|
import { InvitationBanner } from "@agent-native/core/client/org";
|
|
12
|
-
import { useMemo } from "react";
|
|
13
|
+
import { useEffect, useMemo } from "react";
|
|
13
14
|
import { useLocation, useNavigate } from "react-router";
|
|
14
15
|
|
|
15
16
|
import { useNavigationState } from "@/hooks/use-navigation-state";
|
|
17
|
+
import {
|
|
18
|
+
ANALYTICS_CHAT_STORAGE_KEY,
|
|
19
|
+
hasRecentAnalyticsChat,
|
|
20
|
+
markAnalyticsChatActivity,
|
|
21
|
+
} from "@/lib/chat-handoff";
|
|
16
22
|
import { TAB_ID } from "@/lib/tab-id";
|
|
17
23
|
|
|
18
24
|
import { Header } from "./Header";
|
|
19
25
|
import { HeaderActionsProvider } from "./HeaderActions";
|
|
26
|
+
import {
|
|
27
|
+
isAnalyticsSessionsRoute,
|
|
28
|
+
shouldDefaultOpenAnalyticsSidebar,
|
|
29
|
+
} from "./layout-route-policy";
|
|
20
30
|
import { MobileNav } from "./MobileNav";
|
|
21
31
|
import { Sidebar } from "./Sidebar";
|
|
22
32
|
|
|
@@ -26,6 +36,59 @@ interface LayoutProps {
|
|
|
26
36
|
|
|
27
37
|
const BARE_ROUTES = new Set(["/chart"]);
|
|
28
38
|
|
|
39
|
+
function stripBasePath(path: string): string {
|
|
40
|
+
const basePath = appBasePath();
|
|
41
|
+
if (!basePath) return path;
|
|
42
|
+
if (path === basePath) return "/";
|
|
43
|
+
if (path.startsWith(`${basePath}/`)) return path.slice(basePath.length);
|
|
44
|
+
if (path.startsWith(`${basePath}?`) || path.startsWith(`${basePath}#`)) {
|
|
45
|
+
return `/${path.slice(basePath.length)}`;
|
|
46
|
+
}
|
|
47
|
+
return path;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function pathnameFromLocalPath(path: string): string {
|
|
51
|
+
return path.split(/[?#]/, 1)[0] || "/";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function isFrameworkOrApiPath(pathname: string): boolean {
|
|
55
|
+
return (
|
|
56
|
+
pathname === "/_agent-native" ||
|
|
57
|
+
pathname.startsWith("/_agent-native/") ||
|
|
58
|
+
pathname === "/api" ||
|
|
59
|
+
pathname.startsWith("/api/")
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function isStaticAssetPath(pathname: string): boolean {
|
|
64
|
+
const lastSegment = pathname.split("/").pop() ?? "";
|
|
65
|
+
return /\.[A-Za-z0-9]{1,12}$/.test(lastSegment);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function localPathFromAnchor(anchor: HTMLAnchorElement): string | null {
|
|
69
|
+
if (!anchor.href) return null;
|
|
70
|
+
try {
|
|
71
|
+
const url = new URL(anchor.href);
|
|
72
|
+
if (url.origin !== window.location.origin) return null;
|
|
73
|
+
return stripBasePath(`${url.pathname}${url.search}${url.hash}`);
|
|
74
|
+
} catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function shouldHandleAnchorClick(
|
|
80
|
+
event: MouseEvent,
|
|
81
|
+
anchor: HTMLAnchorElement,
|
|
82
|
+
): boolean {
|
|
83
|
+
if (event.defaultPrevented || event.button !== 0) return false;
|
|
84
|
+
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
if (anchor.target && anchor.target !== "_self") return false;
|
|
88
|
+
if (anchor.hasAttribute("download")) return false;
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
29
92
|
export function Layout({ children }: LayoutProps) {
|
|
30
93
|
useNavigationState();
|
|
31
94
|
const location = useLocation();
|
|
@@ -82,18 +145,60 @@ export function Layout({ children }: LayoutProps) {
|
|
|
82
145
|
const isExtensionsRoute =
|
|
83
146
|
location.pathname === "/extensions" ||
|
|
84
147
|
location.pathname.startsWith("/extensions/");
|
|
148
|
+
const isSessionsRoute = isAnalyticsSessionsRoute(location.pathname);
|
|
85
149
|
const isAskRoute = location.pathname === "/ask";
|
|
86
150
|
const chatHomeHandoffActive = useAgentChatHomeHandoff({
|
|
87
|
-
storageKey:
|
|
151
|
+
storageKey: ANALYTICS_CHAT_STORAGE_KEY,
|
|
88
152
|
activePath: location.pathname,
|
|
89
153
|
enabled: !isAskRoute && !reportScreenshot,
|
|
90
154
|
});
|
|
91
|
-
useAgentChatHomeHandoffLinks({
|
|
92
|
-
storageKey: "analytics",
|
|
93
|
-
chatPath: "/ask",
|
|
94
|
-
});
|
|
95
155
|
const sidebarScope = chatHomeHandoffActive ? null : analyticsScope;
|
|
96
156
|
|
|
157
|
+
useEffect(() => {
|
|
158
|
+
function handleChatRunning(event: Event) {
|
|
159
|
+
const detail = (event as CustomEvent).detail;
|
|
160
|
+
if (typeof detail?.isRunning === "boolean") {
|
|
161
|
+
markAnalyticsChatActivity();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
window.addEventListener("agentNative.chatRunning", handleChatRunning);
|
|
166
|
+
return () =>
|
|
167
|
+
window.removeEventListener("agentNative.chatRunning", handleChatRunning);
|
|
168
|
+
}, []);
|
|
169
|
+
|
|
170
|
+
useEffect(() => {
|
|
171
|
+
if (!isAskRoute) return;
|
|
172
|
+
|
|
173
|
+
function handleClick(event: MouseEvent) {
|
|
174
|
+
const target = event.target;
|
|
175
|
+
if (!(target instanceof Element)) return;
|
|
176
|
+
const anchor = target.closest("a[href]");
|
|
177
|
+
if (!(anchor instanceof HTMLAnchorElement)) return;
|
|
178
|
+
if (!shouldHandleAnchorClick(event, anchor)) return;
|
|
179
|
+
if (anchor.closest(".agent-panel-root")) return;
|
|
180
|
+
|
|
181
|
+
const path = localPathFromAnchor(anchor);
|
|
182
|
+
const pathname = path ? pathnameFromLocalPath(path) : "";
|
|
183
|
+
if (
|
|
184
|
+
!path ||
|
|
185
|
+
pathname === "/ask" ||
|
|
186
|
+
isFrameworkOrApiPath(pathname) ||
|
|
187
|
+
isStaticAssetPath(pathname) ||
|
|
188
|
+
!hasRecentAnalyticsChat()
|
|
189
|
+
) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
event.preventDefault();
|
|
194
|
+
markAgentChatHomeHandoff(ANALYTICS_CHAT_STORAGE_KEY);
|
|
195
|
+
navigateWithAgentChatViewTransition(navigate, path);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
document.addEventListener("click", handleClick, true);
|
|
199
|
+
return () => document.removeEventListener("click", handleClick, true);
|
|
200
|
+
}, [isAskRoute, navigate]);
|
|
201
|
+
|
|
97
202
|
function openAskAgentFullscreen() {
|
|
98
203
|
focusAgentChat();
|
|
99
204
|
navigateWithAgentChatViewTransition(navigate, "/ask");
|
|
@@ -158,11 +263,14 @@ export function Layout({ children }: LayoutProps) {
|
|
|
158
263
|
) : (
|
|
159
264
|
<AgentSidebar
|
|
160
265
|
position="right"
|
|
161
|
-
defaultOpen
|
|
266
|
+
defaultOpen={
|
|
267
|
+
chatHomeHandoffActive &&
|
|
268
|
+
shouldDefaultOpenAnalyticsSidebar(location.pathname)
|
|
269
|
+
}
|
|
162
270
|
chatViewTransition
|
|
163
|
-
storageKey=
|
|
271
|
+
storageKey={ANALYTICS_CHAT_STORAGE_KEY}
|
|
164
272
|
browserTabId={TAB_ID}
|
|
165
|
-
openOnChatRunning={chatHomeHandoffActive}
|
|
273
|
+
openOnChatRunning={chatHomeHandoffActive && !isSessionsRoute}
|
|
166
274
|
onFullscreenRequest={openAskAgentFullscreen}
|
|
167
275
|
emptyStateText={t("chat.emptyState")}
|
|
168
276
|
suggestions={[
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function isAnalyticsSessionsRoute(pathname: string): boolean {
|
|
2
|
+
return pathname === "/sessions" || pathname.startsWith("/sessions/");
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function shouldDefaultOpenAnalyticsSidebar(pathname: string): boolean {
|
|
6
|
+
return !isAnalyticsSessionsRoute(pathname);
|
|
7
|
+
}
|
|
@@ -464,6 +464,10 @@
|
|
|
464
464
|
container: analytics-session-detail / inline-size;
|
|
465
465
|
}
|
|
466
466
|
|
|
467
|
+
.analytics-session-detail-timeline {
|
|
468
|
+
display: none;
|
|
469
|
+
}
|
|
470
|
+
|
|
467
471
|
@container analytics-session-detail (min-width: 760px) {
|
|
468
472
|
.analytics-session-detail-header {
|
|
469
473
|
flex-direction: row;
|
|
@@ -476,6 +480,10 @@
|
|
|
476
480
|
.analytics-session-detail-workbench {
|
|
477
481
|
grid-template-columns: minmax(0, 1fr) 330px;
|
|
478
482
|
}
|
|
483
|
+
|
|
484
|
+
.analytics-session-detail-timeline {
|
|
485
|
+
display: flex;
|
|
486
|
+
}
|
|
479
487
|
}
|
|
480
488
|
|
|
481
489
|
/* The dashboard grid responds to the available content width — which shrinks
|
|
@@ -4,6 +4,10 @@ import {
|
|
|
4
4
|
} from "@agent-native/core/client";
|
|
5
5
|
import { useLocation } from "react-router";
|
|
6
6
|
|
|
7
|
+
import {
|
|
8
|
+
ANALYTICS_CHAT_STORAGE_KEY,
|
|
9
|
+
hasRecentAnalyticsChat,
|
|
10
|
+
} from "@/lib/chat-handoff";
|
|
7
11
|
import { rememberLastOpened } from "@/lib/last-opened";
|
|
8
12
|
import { TAB_ID } from "@/lib/tab-id";
|
|
9
13
|
|
|
@@ -102,7 +106,9 @@ export function useNavigationState() {
|
|
|
102
106
|
},
|
|
103
107
|
onNavigate: (_command, path) => {
|
|
104
108
|
if (location.pathname === "/ask" && pathnameFromPath(path) !== "/ask") {
|
|
105
|
-
|
|
109
|
+
if (hasRecentAnalyticsChat()) {
|
|
110
|
+
markAgentChatHomeHandoff(ANALYTICS_CHAT_STORAGE_KEY);
|
|
111
|
+
}
|
|
106
112
|
}
|
|
107
113
|
},
|
|
108
114
|
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const ANALYTICS_CHAT_STORAGE_KEY = "analytics";
|
|
2
|
+
|
|
3
|
+
export const ANALYTICS_RECENT_CHAT_HANDOFF_TTL_MS = 5 * 60 * 1000;
|
|
4
|
+
|
|
5
|
+
const ANALYTICS_LAST_CHAT_ACTIVITY_KEY =
|
|
6
|
+
"agent-native.analytics.last-chat-activity-at";
|
|
7
|
+
|
|
8
|
+
function readAnalyticsLastChatActivityAt(): number {
|
|
9
|
+
if (typeof window === "undefined") return 0;
|
|
10
|
+
try {
|
|
11
|
+
const raw = window.sessionStorage.getItem(ANALYTICS_LAST_CHAT_ACTIVITY_KEY);
|
|
12
|
+
const parsed = raw ? Number.parseInt(raw, 10) : 0;
|
|
13
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
14
|
+
} catch {
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function markAnalyticsChatActivity(now = Date.now()): void {
|
|
20
|
+
if (typeof window === "undefined") return;
|
|
21
|
+
try {
|
|
22
|
+
window.sessionStorage.setItem(
|
|
23
|
+
ANALYTICS_LAST_CHAT_ACTIVITY_KEY,
|
|
24
|
+
String(now),
|
|
25
|
+
);
|
|
26
|
+
} catch {}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function hasRecentAnalyticsChat(now = Date.now()): boolean {
|
|
30
|
+
const lastChatAt = readAnalyticsLastChatActivityAt();
|
|
31
|
+
return (
|
|
32
|
+
lastChatAt > 0 && now - lastChatAt <= ANALYTICS_RECENT_CHAT_HANDOFF_TTL_MS
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -1,25 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
markAgentChatHomeHandoff,
|
|
4
|
-
useT,
|
|
5
|
-
} from "@agent-native/core/client";
|
|
6
|
-
import { useEffect } from "react";
|
|
1
|
+
import { AgentChatSurface, useT } from "@agent-native/core/client";
|
|
2
|
+
import { useState } from "react";
|
|
7
3
|
|
|
4
|
+
import {
|
|
5
|
+
ANALYTICS_CHAT_STORAGE_KEY,
|
|
6
|
+
hasRecentAnalyticsChat,
|
|
7
|
+
} from "@/lib/chat-handoff";
|
|
8
8
|
import { TAB_ID } from "@/lib/tab-id";
|
|
9
9
|
|
|
10
10
|
export default function AskPage() {
|
|
11
11
|
const t = useT();
|
|
12
|
-
|
|
13
|
-
useEffect(() => {
|
|
14
|
-
function handleChatRunning(event: Event) {
|
|
15
|
-
const detail = (event as CustomEvent).detail;
|
|
16
|
-
if (detail?.isRunning === true) markAgentChatHomeHandoff("analytics");
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
window.addEventListener("agentNative.chatRunning", handleChatRunning);
|
|
20
|
-
return () =>
|
|
21
|
-
window.removeEventListener("agentNative.chatRunning", handleChatRunning);
|
|
22
|
-
}, []);
|
|
12
|
+
const [restoreActiveThread] = useState(() => hasRecentAnalyticsChat());
|
|
23
13
|
|
|
24
14
|
return (
|
|
25
15
|
<div className="analytics-ask-page flex h-full min-h-0 flex-col bg-background">
|
|
@@ -28,7 +18,8 @@ export default function AskPage() {
|
|
|
28
18
|
chatViewTransition
|
|
29
19
|
className="analytics-chat-panel"
|
|
30
20
|
defaultMode="chat"
|
|
31
|
-
storageKey=
|
|
21
|
+
storageKey={ANALYTICS_CHAT_STORAGE_KEY}
|
|
22
|
+
restoreActiveThread={restoreActiveThread}
|
|
32
23
|
browserTabId={TAB_ID}
|
|
33
24
|
showHeader={false}
|
|
34
25
|
showTabBar={false}
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
import {
|
|
29
29
|
IconArchive,
|
|
30
30
|
IconClock,
|
|
31
|
-
|
|
31
|
+
IconDotsVertical,
|
|
32
32
|
IconEye,
|
|
33
33
|
IconEyeOff,
|
|
34
34
|
IconGripVertical,
|
|
@@ -1391,7 +1391,7 @@ export default function SqlDashboardPage() {
|
|
|
1391
1391
|
className="text-muted-foreground hover:text-foreground"
|
|
1392
1392
|
aria-label={t("sqlDashboard.dashboardActions")}
|
|
1393
1393
|
>
|
|
1394
|
-
<
|
|
1394
|
+
<IconDotsVertical className="h-4 w-4" />
|
|
1395
1395
|
</Button>
|
|
1396
1396
|
</DropdownMenuTrigger>
|
|
1397
1397
|
</TooltipTrigger>
|