@agent-native/core 0.95.0 → 0.96.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 +2 -2
- package/corpus/core/CHANGELOG.md +35 -0
- package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +13 -0
- package/corpus/core/docs/content/locales/de-DE/template-design.mdx +18 -0
- package/corpus/core/docs/content/locales/es-ES/template-design.mdx +16 -0
- package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +17 -0
- package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +16 -0
- package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +17 -0
- package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +15 -0
- package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +16 -0
- package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +11 -0
- package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +12 -0
- package/corpus/core/docs/content/template-design.mdx +16 -0
- package/corpus/core/package.json +4 -2
- package/corpus/core/src/a2a/client.ts +11 -1
- package/corpus/core/src/agent/production-agent.ts +107 -27
- package/corpus/core/src/agent/thread-data-builder.ts +48 -22
- package/corpus/core/src/chat-threads/store.ts +20 -1
- package/corpus/core/src/cli/code-agent-executor.ts +1 -0
- package/corpus/core/src/cli/code-agent-runs.ts +14 -0
- package/corpus/core/src/client/AgentPanel.tsx +32 -25
- package/corpus/core/src/client/AssistantChat.tsx +286 -45
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +141 -90
- package/corpus/core/src/client/chat/ChatHistoryList.tsx +404 -0
- package/corpus/core/src/client/chat/index.ts +6 -0
- package/corpus/core/src/client/chat/tool-call-display.tsx +38 -4
- package/corpus/core/src/client/chat/use-reconnect-reader-owner.ts +28 -0
- package/corpus/core/src/client/code-agent-chat-adapter.ts +72 -4
- package/corpus/core/src/client/composer/RealtimeVoiceMode.tsx +52 -11
- package/corpus/core/src/client/composer/TiptapComposer.tsx +157 -20
- package/corpus/core/src/client/composer/VoiceButton.tsx +28 -0
- package/corpus/core/src/client/composer/useRealtimeVoiceMode.tsx +5 -0
- package/corpus/core/src/client/conversation/code-agent-transcript.ts +4 -5
- package/corpus/core/src/client/guided-questions.tsx +11 -2
- package/corpus/core/src/client/index.ts +11 -0
- package/corpus/core/src/client/integrations/IntegrationsPanel.tsx +6 -7
- package/corpus/core/src/client/sse-event-processor.ts +90 -21
- package/corpus/core/src/client/use-chat-threads.ts +10 -1
- package/corpus/core/src/client/voice-provider-status.ts +44 -0
- package/corpus/core/src/code-agents/transcript-normalizer.ts +76 -0
- package/corpus/core/src/connections/catalog.ts +2 -2
- package/corpus/core/src/deploy/build.ts +12 -8
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +35 -5
- package/corpus/core/src/integrations/adapters/slack.ts +74 -21
- package/corpus/core/src/integrations/catalog.ts +2 -2
- package/corpus/core/src/integrations/webhook-handler.ts +14 -0
- package/corpus/core/src/localization/default-messages.ts +6 -0
- package/corpus/core/src/observability/hosted-model-experiment.ts +118 -0
- package/corpus/core/src/observability/routes.ts +17 -0
- package/corpus/core/src/observability/store.ts +4 -1
- package/corpus/core/src/observability/traces.ts +41 -2
- package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +19 -1
- package/corpus/core/src/scripts/call-agent.ts +53 -3
- package/corpus/core/src/scripts/chat/search-chats.ts +11 -8
- package/corpus/core/src/secrets/register-framework-secrets.ts +1 -1
- package/corpus/core/src/server/agent-chat-plugin.ts +41 -6
- package/corpus/core/src/server/auth.ts +1 -1
- package/corpus/core/src/server/core-routes-plugin.ts +15 -0
- package/corpus/core/src/server/credential-provider.ts +7 -3
- package/corpus/core/src/server/realtime-voice.ts +71 -24
- package/corpus/core/src/server/voice-providers-status.ts +4 -3
- package/corpus/core/src/shared/cache-control.ts +4 -4
- package/corpus/core/src/styles/agent-native.css +1 -0
- package/corpus/core/src/styles/chat-history-list.css +313 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
- package/corpus/core/src/vite/client.ts +1 -0
- package/corpus/templates/analytics/AGENTS.md +7 -0
- package/corpus/templates/analytics/actions/bigquery.ts +26 -2
- package/corpus/templates/analytics/actions/data-source-status.ts +18 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +5 -4
- package/corpus/templates/analytics/app/global.css +10 -0
- package/corpus/templates/analytics/app/lib/data-sources.ts +5 -4
- package/corpus/templates/analytics/app/pages/Ask.tsx +25 -2
- package/corpus/templates/analytics/changelog/2026-07-10-analytics-answers-simple-time-bounded-metrics-without-unnece.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-analytics-chat-reliably-uses-connected-data-sources-across-s.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-chat-threads-now-stay-clear-of-top-actions-and-fade-smoothly.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-context-chips-can-now-be-selected-and-removed-one-at-a-time-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-slack-token-setup-marked-legacy.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-the-ask-composer-no-longer-carries-dashboard-or-panel-contex.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-the-ask-section-stays-highlighted-while-its-chat-history-is-.md +6 -0
- package/corpus/templates/analytics/server/lib/bigquery.ts +90 -14
- package/corpus/templates/analytics/server/lib/credential-keys.ts +6 -2
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +82 -7
- package/corpus/templates/brain/changelog/2026-07-10-slack-backfill-token-marked-legacy.md +6 -0
- package/corpus/templates/brain/server/register-secrets.ts +2 -2
- package/corpus/templates/clips/app/components/library/library-layout.tsx +7 -1
- package/corpus/templates/clips/app/components/library/page-header.tsx +19 -3
- package/corpus/templates/clips/app/routes/_app.library._index.tsx +16 -12
- package/corpus/templates/clips/changelog/2026-07-10-new-recording-appears-once-when-the-library-sidebar-is-open.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-10-slack-token-fallback-guidance.md +6 -0
- package/corpus/templates/clips/server/register-secrets.ts +1 -1
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +0 -66
- package/corpus/templates/content/app/routes/_app.local-files.tsx +7 -47
- package/corpus/templates/content/changelog/2026-07-10-local-folders-now-wait-for-an-explicit-pull-before-content-r.md +6 -0
- package/corpus/templates/content/package.json +1 -1
- package/corpus/templates/design/actions/generate-design.ts +128 -31
- package/corpus/templates/design/actions/present-design-variants.ts +37 -9
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +9 -3
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +32 -10
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +2 -2
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +9 -1
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +7 -5
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +3 -0
- package/corpus/templates/design/app/global.css +10 -0
- package/corpus/templates/design/app/hooks/use-question-flow.ts +9 -2
- package/corpus/templates/design/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/design/app/i18n-data.ts +21 -11
- package/corpus/templates/design/changelog/2026-07-10-editor-panels-are-easier-to-distinguish-and-design-intake-qu.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-interact-mode-now-stays-on-the-full-canvas-matches-edit-visu.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-new-web-designs-open-at-desktop-size-and-adapt-across-mobile.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-tweaks-now-link-to-full-documentation.md +6 -0
- package/corpus/templates/design/server/plugins/agent-chat.ts +2 -0
- package/corpus/templates/mail/app/i18n/ar-SA.ts +3 -3
- package/corpus/templates/mail/app/i18n/de-DE.ts +3 -3
- package/corpus/templates/mail/app/i18n/en-US.ts +4 -3
- package/corpus/templates/mail/app/i18n/es-ES.ts +3 -3
- package/corpus/templates/mail/app/i18n/fr-FR.ts +3 -3
- package/corpus/templates/mail/app/i18n/hi-IN.ts +3 -3
- package/corpus/templates/mail/app/i18n/ja-JP.ts +3 -3
- package/corpus/templates/mail/app/i18n/ko-KR.ts +3 -3
- package/corpus/templates/mail/app/i18n/pt-BR.ts +3 -3
- package/corpus/templates/mail/app/i18n/zh-CN.ts +3 -3
- package/corpus/templates/mail/app/i18n/zh-TW.ts +3 -3
- package/corpus/templates/mail/changelog/2026-07-10-slack-intake-marked-legacy.md +6 -0
- package/corpus/templates/mail/server/lib/env-config.ts +5 -4
- package/corpus/templates/plan/package.json +1 -1
- package/dist/a2a/client.d.ts +7 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +2 -1
- package/dist/a2a/client.js.map +1 -1
- package/dist/agent/production-agent.d.ts +6 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +83 -26
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts +1 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +42 -23
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/chat-threads/store.d.ts +10 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +6 -0
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/code-agent-executor.d.ts.map +1 -1
- package/dist/cli/code-agent-executor.js +1 -0
- package/dist/cli/code-agent-executor.js.map +1 -1
- package/dist/cli/code-agent-runs.d.ts +12 -0
- package/dist/cli/code-agent-runs.d.ts.map +1 -1
- package/dist/cli/code-agent-runs.js +1 -0
- package/dist/cli/code-agent-runs.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +3 -3
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +14 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +207 -32
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +83 -10
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/chat/ChatHistoryList.d.ts +88 -0
- package/dist/client/chat/ChatHistoryList.d.ts.map +1 -0
- package/dist/client/chat/ChatHistoryList.js +83 -0
- package/dist/client/chat/ChatHistoryList.js.map +1 -0
- package/dist/client/chat/index.d.ts +1 -0
- package/dist/client/chat/index.d.ts.map +1 -1
- package/dist/client/chat/index.js +1 -0
- package/dist/client/chat/index.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +13 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +11 -3
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/chat/use-reconnect-reader-owner.d.ts +11 -0
- package/dist/client/chat/use-reconnect-reader-owner.d.ts.map +1 -0
- package/dist/client/chat/use-reconnect-reader-owner.js +21 -0
- package/dist/client/chat/use-reconnect-reader-owner.js.map +1 -0
- package/dist/client/code-agent-chat-adapter.d.ts +17 -1
- package/dist/client/code-agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/code-agent-chat-adapter.js +47 -3
- package/dist/client/code-agent-chat-adapter.js.map +1 -1
- package/dist/client/composer/RealtimeVoiceMode.d.ts +11 -1
- package/dist/client/composer/RealtimeVoiceMode.d.ts.map +1 -1
- package/dist/client/composer/RealtimeVoiceMode.js +5 -3
- package/dist/client/composer/RealtimeVoiceMode.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +25 -2
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +96 -5
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/VoiceButton.d.ts.map +1 -1
- package/dist/client/composer/VoiceButton.js +21 -1
- package/dist/client/composer/VoiceButton.js.map +1 -1
- package/dist/client/composer/useRealtimeVoiceMode.d.ts.map +1 -1
- package/dist/client/composer/useRealtimeVoiceMode.js +5 -0
- package/dist/client/composer/useRealtimeVoiceMode.js.map +1 -1
- package/dist/client/conversation/code-agent-transcript.d.ts +2 -0
- package/dist/client/conversation/code-agent-transcript.d.ts.map +1 -1
- package/dist/client/conversation/code-agent-transcript.js +3 -5
- package/dist/client/conversation/code-agent-transcript.js.map +1 -1
- package/dist/client/guided-questions.d.ts.map +1 -1
- package/dist/client/guided-questions.js +7 -2
- package/dist/client/guided-questions.js.map +1 -1
- package/dist/client/index.d.ts +3 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.js +5 -7
- package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +67 -20
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +9 -1
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/client/voice-provider-status.d.ts +10 -0
- package/dist/client/voice-provider-status.d.ts.map +1 -0
- package/dist/client/voice-provider-status.js +32 -0
- package/dist/client/voice-provider-status.js.map +1 -0
- package/dist/code-agents/transcript-normalizer.d.ts +29 -0
- package/dist/code-agents/transcript-normalizer.d.ts.map +1 -1
- package/dist/code-agents/transcript-normalizer.js +55 -0
- package/dist/code-agents/transcript-normalizer.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +2 -2
- package/dist/connections/catalog.js +2 -2
- package/dist/connections/catalog.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +12 -8
- package/dist/deploy/build.js.map +1 -1
- package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +25 -5
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +55 -21
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/catalog.js +2 -2
- package/dist/integrations/catalog.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +11 -0
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/localization/default-messages.d.ts +5 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +5 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/observability/hosted-model-experiment.d.ts +39 -0
- package/dist/observability/hosted-model-experiment.d.ts.map +1 -0
- package/dist/observability/hosted-model-experiment.js +90 -0
- package/dist/observability/hosted-model-experiment.js.map +1 -0
- package/dist/observability/routes.d.ts.map +1 -1
- package/dist/observability/routes.js +16 -0
- package/dist/observability/routes.js.map +1 -1
- package/dist/observability/store.d.ts.map +1 -1
- package/dist/observability/store.js +4 -1
- package/dist/observability/store.js.map +1 -1
- package/dist/observability/traces.d.ts +6 -0
- package/dist/observability/traces.d.ts.map +1 -1
- package/dist/observability/traces.js +28 -2
- package/dist/observability/traces.js.map +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +19 -1
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +43 -3
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/scripts/chat/search-chats.d.ts +1 -1
- package/dist/scripts/chat/search-chats.d.ts.map +1 -1
- package/dist/scripts/chat/search-chats.js +11 -8
- package/dist/scripts/chat/search-chats.js.map +1 -1
- package/dist/secrets/register-framework-secrets.js +1 -1
- package/dist/secrets/register-framework-secrets.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +11 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +27 -6
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/auth.js +1 -1
- package/dist/server/auth.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +3 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +13 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +5 -3
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +7 -3
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/realtime-voice.d.ts.map +1 -1
- package/dist/server/realtime-voice.js +55 -21
- package/dist/server/realtime-voice.js.map +1 -1
- package/dist/server/voice-providers-status.d.ts.map +1 -1
- package/dist/server/voice-providers-status.js +2 -3
- package/dist/server/voice-providers-status.js.map +1 -1
- package/dist/shared/cache-control.d.ts +6 -6
- package/dist/shared/cache-control.d.ts.map +1 -1
- package/dist/shared/cache-control.js +3 -3
- package/dist/shared/cache-control.js.map +1 -1
- package/dist/styles/agent-native.css +1 -0
- package/dist/styles/chat-history-list.css +313 -0
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
- package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +1 -0
- package/dist/vite/client.js.map +1 -1
- package/docs/content/locales/ar-SA/template-design.mdx +13 -0
- package/docs/content/locales/de-DE/template-design.mdx +18 -0
- package/docs/content/locales/es-ES/template-design.mdx +16 -0
- package/docs/content/locales/fr-FR/template-design.mdx +17 -0
- package/docs/content/locales/hi-IN/template-design.mdx +16 -0
- package/docs/content/locales/ja-JP/template-design.mdx +17 -0
- package/docs/content/locales/ko-KR/template-design.mdx +15 -0
- package/docs/content/locales/pt-BR/template-design.mdx +16 -0
- package/docs/content/locales/zh-CN/template-design.mdx +11 -0
- package/docs/content/locales/zh-TW/template-design.mdx +12 -0
- package/docs/content/template-design.mdx +16 -0
- package/package.json +4 -2
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
- package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
|
@@ -149,6 +149,16 @@
|
|
|
149
149
|
background-color: hsl(var(--background)) !important;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
.analytics-chat-panel .agent-thread-content {
|
|
153
|
+
padding-top: 4.5rem;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.analytics-chat-panel
|
|
157
|
+
[data-agent-page-chat-scrolled]
|
|
158
|
+
[data-agent-page-chat-fade] {
|
|
159
|
+
opacity: 1;
|
|
160
|
+
}
|
|
161
|
+
|
|
152
162
|
@media (max-width: 767px) {
|
|
153
163
|
.analytics-chat-panel [data-agent-page-new-chat] {
|
|
154
164
|
display: none;
|
|
@@ -748,14 +748,15 @@ export const dataSources: DataSource[] = [
|
|
|
748
748
|
{
|
|
749
749
|
id: "slack",
|
|
750
750
|
name: "Slack",
|
|
751
|
-
description:
|
|
751
|
+
description:
|
|
752
|
+
"Channel history and workspace search. Prefer a Slack workspace integration from Settings > Connections; a local bot token remains available as a legacy fallback.",
|
|
752
753
|
category: "communication",
|
|
753
754
|
icon: IconMessage,
|
|
754
755
|
envKeys: ["SLACK_BOT_TOKEN"],
|
|
755
756
|
docsUrl: "https://api.slack.com/methods",
|
|
756
757
|
walkthroughSteps: [
|
|
757
758
|
{
|
|
758
|
-
title: "Create a Slack App",
|
|
759
|
+
title: "Create a Slack App for local fallback access",
|
|
759
760
|
description:
|
|
760
761
|
"Go to api.slack.com/apps, create a new app, and add OAuth scopes: channels:read, channels:history, search:read.",
|
|
761
762
|
url: "https://api.slack.com/apps",
|
|
@@ -767,10 +768,10 @@ export const dataSources: DataSource[] = [
|
|
|
767
768
|
'Under "OAuth & Permissions", install the app and copy the Bot User OAuth Token.',
|
|
768
769
|
},
|
|
769
770
|
{
|
|
770
|
-
title: "Enter your Bot Token",
|
|
771
|
+
title: "Enter your local fallback Bot Token",
|
|
771
772
|
description: 'Paste the Bot User OAuth Token (starts with "xoxb-").',
|
|
772
773
|
inputKey: "SLACK_BOT_TOKEN",
|
|
773
|
-
inputLabel: "Bot Token",
|
|
774
|
+
inputLabel: "Bot Token (legacy local fallback)",
|
|
774
775
|
inputPlaceholder: "xoxb-...",
|
|
775
776
|
inputType: "password",
|
|
776
777
|
},
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
AgentChatSurface,
|
|
3
|
+
useAgentChatContext,
|
|
4
|
+
useT,
|
|
5
|
+
} from "@agent-native/core/client";
|
|
6
|
+
import { useEffect, useMemo, useState } from "react";
|
|
3
7
|
|
|
4
8
|
import {
|
|
5
9
|
ANALYTICS_CHAT_STORAGE_KEY,
|
|
@@ -7,9 +11,28 @@ import {
|
|
|
7
11
|
} from "@/lib/chat-handoff";
|
|
8
12
|
import { TAB_ID } from "@/lib/tab-id";
|
|
9
13
|
|
|
14
|
+
const DASHBOARD_CONTEXT_KEYS = new Set([
|
|
15
|
+
"analytics-selected-dashboard",
|
|
16
|
+
"analytics-selected-dashboard-panel",
|
|
17
|
+
]);
|
|
18
|
+
|
|
10
19
|
export default function AskPage() {
|
|
11
20
|
const t = useT();
|
|
12
21
|
const [restoreActiveThread] = useState(() => hasRecentAnalyticsChat());
|
|
22
|
+
const { items: chatContextItems, remove: removeChatContextItem } =
|
|
23
|
+
useAgentChatContext();
|
|
24
|
+
const staleDashboardContextKey = useMemo(
|
|
25
|
+
() =>
|
|
26
|
+
chatContextItems.find((item) => DASHBOARD_CONTEXT_KEYS.has(item.key))
|
|
27
|
+
?.key ?? null,
|
|
28
|
+
[chatContextItems],
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (staleDashboardContextKey) {
|
|
33
|
+
removeChatContextItem(staleDashboardContextKey);
|
|
34
|
+
}
|
|
35
|
+
}, [removeChatContextItem, staleDashboardContextKey]);
|
|
13
36
|
|
|
14
37
|
return (
|
|
15
38
|
<div className="analytics-ask-page flex h-full min-h-0 flex-col bg-background">
|
|
@@ -241,6 +241,15 @@ export interface QueryResult {
|
|
|
241
241
|
cached?: boolean;
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
+
export interface RunQueryOptions {
|
|
245
|
+
/**
|
|
246
|
+
* The current agent run's abort signal. This cancels in-flight BigQuery
|
|
247
|
+
* requests and, importantly, stops the one-second job polling wait without
|
|
248
|
+
* starting another request after the parent run has ended.
|
|
249
|
+
*/
|
|
250
|
+
signal?: AbortSignal;
|
|
251
|
+
}
|
|
252
|
+
|
|
244
253
|
interface BigQueryField {
|
|
245
254
|
name: string;
|
|
246
255
|
type: string;
|
|
@@ -265,6 +274,57 @@ interface BigQueryGetQueryResultsResponse {
|
|
|
265
274
|
totalBytesProcessed?: string;
|
|
266
275
|
}
|
|
267
276
|
|
|
277
|
+
function createAbortError(): Error {
|
|
278
|
+
if (typeof DOMException !== "undefined") {
|
|
279
|
+
return new DOMException("BigQuery query aborted", "AbortError");
|
|
280
|
+
}
|
|
281
|
+
const error = new Error("BigQuery query aborted");
|
|
282
|
+
error.name = "AbortError";
|
|
283
|
+
return error;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function throwIfAborted(signal?: AbortSignal): void {
|
|
287
|
+
if (signal?.aborted) throw createAbortError();
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function waitForPollInterval(signal?: AbortSignal): Promise<void> {
|
|
291
|
+
throwIfAborted(signal);
|
|
292
|
+
return new Promise((resolve, reject) => {
|
|
293
|
+
const timeout = setTimeout(() => {
|
|
294
|
+
signal?.removeEventListener("abort", onAbort);
|
|
295
|
+
resolve();
|
|
296
|
+
}, 1000);
|
|
297
|
+
const onAbort = () => {
|
|
298
|
+
clearTimeout(timeout);
|
|
299
|
+
signal?.removeEventListener("abort", onAbort);
|
|
300
|
+
reject(createAbortError());
|
|
301
|
+
};
|
|
302
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
async function cancelQueryJob(
|
|
307
|
+
projectId: string,
|
|
308
|
+
jobId: string,
|
|
309
|
+
token: string,
|
|
310
|
+
): Promise<void> {
|
|
311
|
+
try {
|
|
312
|
+
await fetch(
|
|
313
|
+
`https://bigquery.googleapis.com/bigquery/v2/projects/${projectId}/jobs/${jobId}/cancel`,
|
|
314
|
+
{
|
|
315
|
+
method: "POST",
|
|
316
|
+
headers: {
|
|
317
|
+
Authorization: `Bearer ${token}`,
|
|
318
|
+
"Content-Type": "application/json",
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
);
|
|
322
|
+
} catch {
|
|
323
|
+
// The caller is already aborting. Cancellation is best-effort and must not
|
|
324
|
+
// hide the original abort reason if BigQuery or the network is unavailable.
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
268
328
|
/**
|
|
269
329
|
* Convert BigQuery REST API row format to plain objects.
|
|
270
330
|
* BigQuery returns rows as { f: [{ v: value }, ...] } arrays
|
|
@@ -361,7 +421,12 @@ export async function dryRunQuery(sql: string): Promise<string | null> {
|
|
|
361
421
|
return `BigQuery validation failed (${res.status})`;
|
|
362
422
|
}
|
|
363
423
|
|
|
364
|
-
export async function runQuery(
|
|
424
|
+
export async function runQuery(
|
|
425
|
+
sql: string,
|
|
426
|
+
options: RunQueryOptions = {},
|
|
427
|
+
): Promise<QueryResult> {
|
|
428
|
+
const { signal } = options;
|
|
429
|
+
throwIfAborted(signal);
|
|
365
430
|
const { projectId, cacheScope, appEventsTable } = await getProjectInfo();
|
|
366
431
|
const resolvedSql = await resolveTablePlaceholder(
|
|
367
432
|
sql,
|
|
@@ -383,8 +448,10 @@ export async function runQuery(sql: string): Promise<QueryResult> {
|
|
|
383
448
|
const token = await getAccessToken();
|
|
384
449
|
const url = `https://bigquery.googleapis.com/bigquery/v2/projects/${projectId}/queries`;
|
|
385
450
|
|
|
451
|
+
throwIfAborted(signal);
|
|
386
452
|
const res = await fetch(url, {
|
|
387
453
|
method: "POST",
|
|
454
|
+
...(signal ? { signal } : {}),
|
|
388
455
|
headers: {
|
|
389
456
|
Authorization: `Bearer ${token}`,
|
|
390
457
|
"Content-Type": "application/json",
|
|
@@ -409,20 +476,29 @@ export async function runQuery(sql: string): Promise<QueryResult> {
|
|
|
409
476
|
const resultsUrl = `https://bigquery.googleapis.com/bigquery/v2/projects/${projectId}/queries/${jobId}`;
|
|
410
477
|
|
|
411
478
|
let attempts = 0;
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
479
|
+
try {
|
|
480
|
+
while (!data.jobComplete && attempts < 60) {
|
|
481
|
+
await waitForPollInterval(signal);
|
|
482
|
+
throwIfAborted(signal);
|
|
483
|
+
const pollRes = await fetch(resultsUrl, {
|
|
484
|
+
...(signal ? { signal } : {}),
|
|
485
|
+
headers: {
|
|
486
|
+
Authorization: `Bearer ${token}`,
|
|
487
|
+
"Content-Type": "application/json",
|
|
488
|
+
},
|
|
489
|
+
});
|
|
490
|
+
if (!pollRes.ok) {
|
|
491
|
+
const text = await pollRes.text();
|
|
492
|
+
throw new Error(`BigQuery poll error ${pollRes.status}: ${text}`);
|
|
493
|
+
}
|
|
494
|
+
data = (await pollRes.json()) as BigQueryGetQueryResultsResponse;
|
|
495
|
+
attempts++;
|
|
496
|
+
}
|
|
497
|
+
} catch (error) {
|
|
498
|
+
if (signal?.aborted) {
|
|
499
|
+
await cancelQueryJob(projectId, jobId, token);
|
|
423
500
|
}
|
|
424
|
-
|
|
425
|
-
attempts++;
|
|
501
|
+
throw error;
|
|
426
502
|
}
|
|
427
503
|
|
|
428
504
|
if (!data.jobComplete) {
|
|
@@ -107,10 +107,14 @@ export const credentialKeys: CredentialKeyConfig[] = [
|
|
|
107
107
|
required: false,
|
|
108
108
|
},
|
|
109
109
|
// Slack
|
|
110
|
-
{
|
|
110
|
+
{
|
|
111
|
+
key: "SLACK_BOT_TOKEN",
|
|
112
|
+
label: "Slack Bot Token (legacy local fallback)",
|
|
113
|
+
required: false,
|
|
114
|
+
},
|
|
111
115
|
{
|
|
112
116
|
key: "SLACK_BOT_TOKEN_2",
|
|
113
|
-
label: "Slack Bot Token (secondary)",
|
|
117
|
+
label: "Slack Bot Token (legacy secondary fallback)",
|
|
114
118
|
required: false,
|
|
115
119
|
},
|
|
116
120
|
// Notion
|
|
@@ -34,6 +34,18 @@ import {
|
|
|
34
34
|
const DATA_DICT_PREFIX = "data-dict-";
|
|
35
35
|
const ANALYTICS_BACKGROUND_RUN_SOFT_TIMEOUT_MS = 13 * 60_000;
|
|
36
36
|
|
|
37
|
+
export const SIMPLE_TIME_BOUNDED_METRIC_FAST_PATH_GUIDANCE =
|
|
38
|
+
"SIMPLE TIME-BOUNDED METRIC FAST PATH — When the data dictionary or a known canonical source identifies the metric, run one bounded aggregate. Once it returns a valid result, answer the explicit question immediately with the source, time window, row count, and only necessary caveats. Do not schema-discover, retry, enrich, cross-check, or add breakdowns after that successful result unless the query failed or the result conflicts with the known metric definition. This does not waive the real-data requirement: never answer from a guess, stale value, or unverified result. ";
|
|
39
|
+
|
|
40
|
+
export function analyticsSourceGuidanceOpening(): string {
|
|
41
|
+
return (
|
|
42
|
+
"<data-source-guidance>\n" +
|
|
43
|
+
"Apply real-data requirements only when presenting analytics results, source records, or derived metrics. Do not call data-source tools for workflow migration, recurring-job setup, UI/code fixes, settings help, conceptual planning, or other non-data tasks unless the user explicitly asks for data. " +
|
|
44
|
+
SIMPLE_TIME_BOUNDED_METRIC_FAST_PATH_GUIDANCE +
|
|
45
|
+
"SURFACE DIFFERENTIATION — You are the analytics assistant for definitions, deep-dive analysis, and action. For questions about what a metric, model, or table means, use the Data Dictionary and configured schema tools first. For trends, comparisons, anomalies, current data, or anything that requires querying live data, answer directly in chat with the relevant provider query, dashboard analysis, and inline charts when useful. "
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
37
49
|
export {
|
|
38
50
|
applyAnalyticsPlanModePolicy,
|
|
39
51
|
INITIAL_TOOL_NAMES,
|
|
@@ -55,7 +67,61 @@ function latestUserText(
|
|
|
55
67
|
return "";
|
|
56
68
|
}
|
|
57
69
|
|
|
58
|
-
function
|
|
70
|
+
function configuredDataSourceLabels(
|
|
71
|
+
toolResults: AgentLoopFinalResponseGuardContext["toolResults"],
|
|
72
|
+
): string[] {
|
|
73
|
+
const labels = new Set<string>();
|
|
74
|
+
for (const result of toolResults ?? []) {
|
|
75
|
+
const normalizedName = String(result.name ?? "")
|
|
76
|
+
.trim()
|
|
77
|
+
.toLowerCase()
|
|
78
|
+
.replace(/[\s_]+/g, "-");
|
|
79
|
+
if (normalizedName !== "data-source-status" || result.isError) continue;
|
|
80
|
+
|
|
81
|
+
let parsed: Record<string, unknown>;
|
|
82
|
+
try {
|
|
83
|
+
const value = JSON.parse(String(result.content ?? ""));
|
|
84
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) continue;
|
|
85
|
+
parsed = value as Record<string, unknown>;
|
|
86
|
+
} catch {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const compactSources = Array.isArray(parsed.configuredDataSources)
|
|
91
|
+
? parsed.configuredDataSources
|
|
92
|
+
: [];
|
|
93
|
+
for (const source of compactSources) {
|
|
94
|
+
if (!source || typeof source !== "object" || Array.isArray(source)) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const record = source as Record<string, unknown>;
|
|
98
|
+
const label = record.label ?? record.provider;
|
|
99
|
+
if (typeof label === "string" && label.trim()) labels.add(label.trim());
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Backward compatibility for runs against deployments that predate the
|
|
103
|
+
// compact configuredDataSources summary.
|
|
104
|
+
const providers = Array.isArray(parsed.providers) ? parsed.providers : [];
|
|
105
|
+
for (const provider of providers) {
|
|
106
|
+
if (
|
|
107
|
+
!provider ||
|
|
108
|
+
typeof provider !== "object" ||
|
|
109
|
+
Array.isArray(provider)
|
|
110
|
+
) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const record = provider as Record<string, unknown>;
|
|
114
|
+
if (record.configured !== true) continue;
|
|
115
|
+
const label = record.label ?? record.provider;
|
|
116
|
+
if (typeof label === "string" && label.trim()) labels.add(label.trim());
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return [...labels];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function realDataFinalGuard(
|
|
123
|
+
context: AgentLoopFinalResponseGuardContext,
|
|
124
|
+
) {
|
|
59
125
|
if ((context as { executionMode?: string }).executionMode === "plan") {
|
|
60
126
|
return null;
|
|
61
127
|
}
|
|
@@ -125,11 +191,22 @@ function realDataFinalGuard(context: AgentLoopFinalResponseGuardContext) {
|
|
|
125
191
|
};
|
|
126
192
|
}
|
|
127
193
|
|
|
194
|
+
const configuredSources = configuredDataSourceLabels(context.toolResults);
|
|
195
|
+
const configuredSourceGuidance = configuredSources.length
|
|
196
|
+
? ` \`data-source-status\` already confirmed these connected sources: ${configuredSources.join(", ")}. Do not claim that no sources are connected and do not ask the user to reconnect them. Immediately call the relevant query action for one of those sources.`
|
|
197
|
+
: "";
|
|
128
198
|
return {
|
|
129
199
|
retryMessage:
|
|
130
|
-
"This looks like an analytics result request, but no real source query ran. If you are making data claims, run one relevant data-source action or connected provider MCP tool now and answer from that result.
|
|
131
|
-
|
|
132
|
-
"
|
|
200
|
+
"This looks like an analytics result request, but no real source query ran. If you are making data claims, run one relevant data-source action or connected provider MCP tool now and answer from that result." +
|
|
201
|
+
configuredSourceGuidance +
|
|
202
|
+
" If the right response is a clarification, plan, or explicit unavailable/credentials-missing message with no metrics or source-record claims, finalize that directly instead.",
|
|
203
|
+
fallbackMessage: configuredSources.length
|
|
204
|
+
? `I found connected data sources (${configuredSources.join(", ")}), but the model still did not run a real source query. Please retry the request; you do not need to reconnect those sources.`
|
|
205
|
+
: "I can't provide a grounded analytics result yet because no real data-source query ran successfully. Tell me which source to use or connect the missing source, and I'll run it before giving numbers or source-record conclusions.",
|
|
206
|
+
// Some models use separate turns for status, schema discovery, and the
|
|
207
|
+
// actual query. One corrective turn was enough for Sonnet but caused Luna
|
|
208
|
+
// to hit the fallback before it reached the query.
|
|
209
|
+
maxRetries: 2,
|
|
133
210
|
};
|
|
134
211
|
}
|
|
135
212
|
|
|
@@ -159,9 +236,7 @@ export default createAgentChatPlugin({
|
|
|
159
236
|
// The generic template can ship provider actions without every deployment
|
|
160
237
|
// having credentials or workspace-specific schemas configured.
|
|
161
238
|
const sourceGuidance =
|
|
162
|
-
|
|
163
|
-
"Apply real-data requirements only when presenting analytics results, source records, or derived metrics. Do not call data-source tools for workflow migration, recurring-job setup, UI/code fixes, settings help, conceptual planning, or other non-data tasks unless the user explicitly asks for data. " +
|
|
164
|
-
"SURFACE DIFFERENTIATION — You are the analytics assistant for definitions, deep-dive analysis, and action. For questions about what a metric, model, or table means, use the Data Dictionary and configured schema tools first. For trends, comparisons, anomalies, current data, or anything that requires querying live data, answer directly in chat with the relevant provider query, dashboard analysis, and inline charts when useful. " +
|
|
239
|
+
analyticsSourceGuidanceOpening() +
|
|
165
240
|
"DASHBOARD CREATION RULE — You may create dashboards, analyses, SQL panels, or other resources only when the user explicitly asks you to (e.g. 'build me a dashboard for...', 'create a new analysis', 'add a chart for...'). Never create any resource proactively during research, trend analysis, or answering questions. If you think a dashboard would be useful, suggest it and wait for explicit confirmation before creating anything. Never add new items to the sidebar or modify existing dashboards without an explicit user directive. " +
|
|
166
241
|
"DASHBOARD MUTATION RULE — For dashboard edits, default to `mutate-dashboard` with the typed `dashboard.*` script API so the main payload is a string and avoids native-array serialization traps. It can move panels by id, edit titles/SQL/config, insert, duplicate, remove, and patch dashboard fields in one atomic save. The script API is constrained: no variables/imports/loops/functions, only JSON-compatible arguments on documented dashboard methods. Do not count shifting `/panels/<index>` positions for ordinary dashboard edits unless the user specifically asks for low-level JSON-pointer operations. " +
|
|
167
242
|
"DASHBOARD READ RULE — `get-sql-dashboard` is compact by default: use its `panels` summaries plus `layout.panelOrder`, `layout.firstPanelIds`, and `layout.groups[].rows[].rowNumber/panelIds` for orientation and verification. Pass `includeConfig: true` only when you truly need full panel SQL/config. " +
|
|
@@ -2,9 +2,9 @@ import { registerRequiredSecret } from "@agent-native/core/secrets";
|
|
|
2
2
|
|
|
3
3
|
registerRequiredSecret({
|
|
4
4
|
key: "SLACK_BOT_TOKEN",
|
|
5
|
-
label: "Slack Bot Token",
|
|
5
|
+
label: "Slack Bot Token (local fallback)",
|
|
6
6
|
description:
|
|
7
|
-
"Optional
|
|
7
|
+
"Optional local fallback for Brain channel backfills. Prefer a Slack workspace integration in Settings > Connections. Brain only scans allow-listed channels and never enumerates DMs.",
|
|
8
8
|
docsUrl: "https://api.slack.com/authentication/token-types",
|
|
9
9
|
scope: "workspace",
|
|
10
10
|
kind: "api-key",
|
|
@@ -154,6 +154,9 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
|
|
|
154
154
|
);
|
|
155
155
|
const [headerSlot, setHeaderSlot] = useState<HTMLElement | null>(null);
|
|
156
156
|
const showCollapsedSidebar = sidebarCollapsed && !isMobile;
|
|
157
|
+
const sidebarHasNewRecordingAction = isMobile
|
|
158
|
+
? sidebarOpen
|
|
159
|
+
: !sidebarCollapsed;
|
|
157
160
|
|
|
158
161
|
// Routes whose page renders its own h-12 toolbar. Layout still mounts Sidebar
|
|
159
162
|
// + AgentSidebar, but skips its own header so there's no double-header.
|
|
@@ -603,7 +606,10 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
|
|
|
603
606
|
</div>
|
|
604
607
|
)}
|
|
605
608
|
<main className="agent-native-app-main flex min-h-0 flex-1 flex-col overflow-y-auto">
|
|
606
|
-
<PageHeaderSlotProvider
|
|
609
|
+
<PageHeaderSlotProvider
|
|
610
|
+
slot={headerSlot}
|
|
611
|
+
sidebarHasNewRecordingAction={sidebarHasNewRecordingAction}
|
|
612
|
+
>
|
|
607
613
|
{children}
|
|
608
614
|
</PageHeaderSlotProvider>
|
|
609
615
|
</main>
|
|
@@ -7,24 +7,40 @@ import {
|
|
|
7
7
|
} from "react";
|
|
8
8
|
import { createPortal } from "react-dom";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface PageHeaderSlotContextValue {
|
|
11
|
+
slot: HTMLElement | null;
|
|
12
|
+
sidebarHasNewRecordingAction: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const PageHeaderSlotContext = createContext<PageHeaderSlotContextValue>({
|
|
16
|
+
slot: null,
|
|
17
|
+
sidebarHasNewRecordingAction: false,
|
|
18
|
+
});
|
|
11
19
|
|
|
12
20
|
export function PageHeaderSlotProvider({
|
|
13
21
|
slot,
|
|
22
|
+
sidebarHasNewRecordingAction,
|
|
14
23
|
children,
|
|
15
24
|
}: {
|
|
16
25
|
slot: HTMLElement | null;
|
|
26
|
+
sidebarHasNewRecordingAction: boolean;
|
|
17
27
|
children: ReactNode;
|
|
18
28
|
}) {
|
|
19
29
|
return (
|
|
20
|
-
<PageHeaderSlotContext.Provider
|
|
30
|
+
<PageHeaderSlotContext.Provider
|
|
31
|
+
value={{ slot, sidebarHasNewRecordingAction }}
|
|
32
|
+
>
|
|
21
33
|
{children}
|
|
22
34
|
</PageHeaderSlotContext.Provider>
|
|
23
35
|
);
|
|
24
36
|
}
|
|
25
37
|
|
|
38
|
+
export function usePageHeaderLayout() {
|
|
39
|
+
return useContext(PageHeaderSlotContext);
|
|
40
|
+
}
|
|
41
|
+
|
|
26
42
|
export function PageHeader({ children }: { children: ReactNode }) {
|
|
27
|
-
const slot =
|
|
43
|
+
const { slot } = usePageHeaderLayout();
|
|
28
44
|
const [ready, setReady] = useState(false);
|
|
29
45
|
useEffect(() => setReady(true), []);
|
|
30
46
|
if (!ready || !slot) return null;
|
|
@@ -4,6 +4,7 @@ import { IconPlayerRecord } from "@tabler/icons-react";
|
|
|
4
4
|
import { NavLink } from "react-router";
|
|
5
5
|
|
|
6
6
|
import { LibraryGrid } from "@/components/library/library-grid";
|
|
7
|
+
import { usePageHeaderLayout } from "@/components/library/page-header";
|
|
7
8
|
|
|
8
9
|
const SEO_TITLE =
|
|
9
10
|
"Agent-Native Clips - Open Source, agent-friendly Loom alternative";
|
|
@@ -24,24 +25,27 @@ export function meta() {
|
|
|
24
25
|
|
|
25
26
|
export default function LibraryIndexRoute() {
|
|
26
27
|
const t = useT();
|
|
28
|
+
const { sidebarHasNewRecordingAction } = usePageHeaderLayout();
|
|
27
29
|
return (
|
|
28
30
|
<LibraryGrid
|
|
29
31
|
view="library"
|
|
30
32
|
folderId={null}
|
|
31
33
|
title="Library"
|
|
32
34
|
extraActions={
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
35
|
+
!sidebarHasNewRecordingAction && (
|
|
36
|
+
<Button
|
|
37
|
+
className="gap-1.5 bg-primary text-primary-foreground shadow-sm hover:bg-primary/90"
|
|
38
|
+
size="sm"
|
|
39
|
+
asChild
|
|
40
|
+
>
|
|
41
|
+
<NavLink to="/record" aria-label={t("navigation.newRecording")}>
|
|
42
|
+
<IconPlayerRecord className="h-4 w-4" />
|
|
43
|
+
<span className="hidden sm:inline">
|
|
44
|
+
{t("navigation.newRecording")}
|
|
45
|
+
</span>
|
|
46
|
+
</NavLink>
|
|
47
|
+
</Button>
|
|
48
|
+
)
|
|
45
49
|
}
|
|
46
50
|
/>
|
|
47
51
|
);
|
|
@@ -212,7 +212,7 @@ registerRequiredSecret({
|
|
|
212
212
|
key: "SLACK_BOT_TOKEN",
|
|
213
213
|
label: "Slack Bot Token (legacy)",
|
|
214
214
|
description:
|
|
215
|
-
"Legacy single-workspace bot token fallback for Clips link unfurls. New installs should use the Slack
|
|
215
|
+
"Legacy single-workspace bot token fallback for Clips link unfurls. New installs should use the Clips Slack workspace connection; new messaging automations should connect Slack in Settings > Messaging.",
|
|
216
216
|
docsUrl: "https://api.slack.com/apps",
|
|
217
217
|
scope: "workspace",
|
|
218
218
|
kind: "api-key",
|