@agent-native/core 0.108.0 → 0.109.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 +18 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/client.ts +140 -17
- package/corpus/core/src/a2a/handlers.ts +60 -0
- package/corpus/core/src/a2a/index.ts +6 -1
- package/corpus/core/src/a2a/invoke.ts +68 -1
- package/corpus/core/src/a2a/server.ts +13 -1
- package/corpus/core/src/a2a/types.ts +16 -0
- package/corpus/core/src/action.ts +3 -2
- package/corpus/core/src/agent/production-agent.ts +10 -4
- package/corpus/core/src/client/AssistantChat.tsx +648 -603
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +31 -4
- package/corpus/core/src/client/agent-chat-adapter.ts +23 -37
- package/corpus/core/src/client/agent-sidebar-state.ts +4 -0
- package/corpus/core/src/client/analytics.ts +84 -0
- package/corpus/core/src/client/chat/message-components.tsx +94 -22
- package/corpus/core/src/client/chat/tool-call-display.tsx +170 -47
- package/corpus/core/src/client/chat/use-agent-chat-lifecycle-tracking.ts +74 -0
- package/corpus/core/src/client/chat-thread-url.ts +11 -0
- package/corpus/core/src/client/error-capture.ts +12 -0
- package/corpus/core/src/client/extensions/ExtensionSlot.tsx +37 -1
- package/corpus/core/src/client/index.ts +2 -0
- package/corpus/core/src/client/route-chunk-recovery.ts +20 -8
- package/corpus/core/src/client/session-replay.ts +31 -0
- package/corpus/core/src/extensions/actions.ts +2 -14
- package/corpus/core/src/extensions/store.ts +1 -1
- package/corpus/core/src/localization/default-messages.ts +3 -0
- package/corpus/core/src/mcp/build-server.ts +2 -2
- package/corpus/core/src/progress/actions.ts +4 -2
- package/corpus/core/src/provider-api/index.ts +205 -105
- package/corpus/core/src/scripts/call-agent.ts +137 -17
- package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +40 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +31 -0
- package/corpus/core/src/styles/agent-conversation.css +7 -0
- package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/de-DE.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/en-US.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/es-ES.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +19 -0
- package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +19 -0
- package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +19 -0
- package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +19 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +28 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +5 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +13 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +29 -10
- package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +54 -23
- package/corpus/templates/analytics/.builder/skills/apollo/SKILL.md +19 -41
- package/corpus/templates/analytics/.builder/skills/commonroom/SKILL.md +20 -35
- package/corpus/templates/analytics/.builder/skills/github/SKILL.md +23 -67
- package/corpus/templates/analytics/.builder/skills/pylon/SKILL.md +25 -43
- package/corpus/templates/analytics/AGENTS.md +22 -13
- package/corpus/templates/analytics/actions/account-deep-dive.ts +1 -0
- package/corpus/templates/analytics/actions/configure-gong-native-insights.ts +29 -0
- package/corpus/templates/analytics/actions/content-calendar-schema.ts +8 -4
- package/corpus/templates/analytics/actions/content-calendar.ts +12 -4
- package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +2 -1
- package/corpus/templates/analytics/actions/gong-calls.ts +113 -22
- package/corpus/templates/analytics/actions/gong-native-insights.ts +166 -0
- package/corpus/templates/analytics/actions/hubspot-deals.ts +190 -46
- package/corpus/templates/analytics/actions/pylon-issues.ts +123 -0
- package/corpus/templates/analytics/actions/slack-messages.ts +179 -27
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +48 -152
- package/corpus/templates/analytics/app/components/ui/chart.tsx +1 -1
- package/corpus/templates/analytics/app/hooks/use-chart-tooltip-flip.ts +21 -6
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +13 -0
- package/corpus/templates/analytics/app/i18n-data.ts +134 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +181 -30
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +6 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +4 -3
- package/corpus/templates/analytics/changelog/2026-07-17-dashboard-editors-can-add-shared-extensions-or-opt-into-per-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-dashboard-extensions-show-a-loading-skeleton.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-errors-now-group-repeat-failures-consistently-and-keep-priva.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-gong-transcript-reviews-now-batch-bounded-call-windows-for-f.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-hubspot-deal-filters-now-run-in-hubspot-before-paging-result.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-notion-content-calendars-now-discover-the-matching-database-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-pylon-dashboard-reads-now-use-the-paginated-issue-search-api.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-slack-reads-no-longer-join-channels-and-report-pagination-coverage.md +6 -0
- package/corpus/templates/analytics/server/handlers/notion.ts +14 -3
- package/corpus/templates/analytics/server/handlers/slack.ts +182 -29
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +2 -6
- package/corpus/templates/analytics/server/lib/analytics-connector-catalog.ts +6 -2
- package/corpus/templates/analytics/server/lib/error-capture.ts +75 -8
- package/corpus/templates/analytics/server/lib/gong-native-policy.ts +72 -0
- package/corpus/templates/analytics/server/lib/gong.ts +54 -66
- package/corpus/templates/analytics/server/lib/hubspot.ts +40 -3
- package/corpus/templates/analytics/server/lib/notion.ts +83 -8
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +4 -0
- package/corpus/templates/analytics/server/lib/slack.ts +242 -90
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +3 -3
- package/corpus/templates/analytics/server/routes/api/pylon/accounts.get.ts +42 -1
- package/corpus/templates/analytics/server/routes/api/pylon/issues.get.ts +71 -1
- package/corpus/templates/analytics/server/routes/api/test-connection.post.ts +44 -4
- package/corpus/templates/clips/app/components/library/bulk-action-toolbar.tsx +19 -1
- package/corpus/templates/clips/app/components/library/create-folder-dialog.tsx +123 -0
- package/corpus/templates/clips/app/components/library/library-grid.tsx +42 -4
- package/corpus/templates/clips/app/components/library/recording-card.tsx +30 -0
- package/corpus/templates/clips/app/entry.client.tsx +6 -1
- package/corpus/templates/clips/app/i18n/ar-SA.ts +12 -1
- package/corpus/templates/clips/app/i18n/de-DE.ts +12 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +12 -1
- package/corpus/templates/clips/app/i18n/es-ES.ts +11 -1
- package/corpus/templates/clips/app/i18n/fr-FR.ts +11 -1
- package/corpus/templates/clips/app/i18n/hi-IN.ts +10 -1
- package/corpus/templates/clips/app/i18n/ja-JP.ts +12 -1
- package/corpus/templates/clips/app/i18n/ko-KR.ts +11 -1
- package/corpus/templates/clips/app/i18n/pt-BR.ts +11 -1
- package/corpus/templates/clips/app/i18n/zh-CN.ts +11 -1
- package/corpus/templates/clips/app/i18n/zh-TW.ts +11 -1
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +72 -1
- package/corpus/templates/clips/changelog/2026-07-17-choose-which-workspace-receives-new-clips-recordings-and-des.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-17-create-folders-directly-from-the-move-menu.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-17-failed-desktop-uploads-now-offer-a-direct-way-to-reopen-clip.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +1 -1
- package/corpus/templates/content/app/entry.client.tsx +6 -1
- package/corpus/templates/dispatch/AGENTS.md +5 -0
- package/corpus/templates/dispatch/changelog/2026-07-17-apps-page-links-to-other-available-apps.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-17-curated-template-remixes.md +6 -0
- package/corpus/templates/mail/app/entry.client.tsx +6 -1
- package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +11 -7
- package/corpus/templates/slides/.env.example +0 -1
- package/corpus/templates/slides/AGENTS.md +4 -0
- package/corpus/templates/slides/DEVELOPING.md +2 -2
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +1 -1
- package/corpus/templates/slides/actions/logo-config.ts +6 -7
- package/corpus/templates/slides/actions/search-images.ts +11 -39
- package/corpus/templates/slides/actions/search-logos.ts +5 -52
- package/corpus/templates/slides/app/components/editor/ImageSearchPanel.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/LogoSearchPanel.tsx +16 -26
- package/corpus/templates/slides/app/entry.client.tsx +6 -1
- package/corpus/templates/slides/server/lib/media-search-providers.ts +216 -0
- package/corpus/templates/slides/server/register-secrets.ts +30 -0
- package/dist/a2a/client.d.ts +38 -1
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +81 -12
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +47 -0
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/index.d.ts +4 -4
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +2 -2
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/invoke.d.ts +26 -2
- package/dist/a2a/invoke.d.ts.map +1 -1
- package/dist/a2a/invoke.js +30 -1
- package/dist/a2a/invoke.js.map +1 -1
- package/dist/a2a/server.d.ts.map +1 -1
- package/dist/a2a/server.js +14 -1
- package/dist/a2a/server.js.map +1 -1
- package/dist/a2a/types.d.ts +12 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/types.js.map +1 -1
- package/dist/action.d.ts +3 -2
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js.map +1 -1
- package/dist/agent/production-agent.d.ts +5 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +5 -3
- package/dist/agent/production-agent.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 +158 -136
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +27 -4
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +21 -39
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-sidebar-state.d.ts +1 -0
- package/dist/client/agent-sidebar-state.d.ts.map +1 -1
- package/dist/client/agent-sidebar-state.js +4 -0
- package/dist/client/agent-sidebar-state.js.map +1 -1
- package/dist/client/analytics.d.ts +14 -0
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +67 -0
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/chat/message-components.d.ts +8 -0
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +62 -19
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +6 -0
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +83 -14
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/chat/use-agent-chat-lifecycle-tracking.d.ts +8 -0
- package/dist/client/chat/use-agent-chat-lifecycle-tracking.d.ts.map +1 -0
- package/dist/client/chat/use-agent-chat-lifecycle-tracking.js +51 -0
- package/dist/client/chat/use-agent-chat-lifecycle-tracking.js.map +1 -0
- package/dist/client/chat-thread-url.d.ts +2 -0
- package/dist/client/chat-thread-url.d.ts.map +1 -0
- package/dist/client/chat-thread-url.js +12 -0
- package/dist/client/chat-thread-url.js.map +1 -0
- package/dist/client/error-capture.d.ts.map +1 -1
- package/dist/client/error-capture.js +7 -0
- package/dist/client/error-capture.js.map +1 -1
- package/dist/client/extensions/ExtensionSlot.d.ts +3 -1
- package/dist/client/extensions/ExtensionSlot.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionSlot.js +28 -3
- package/dist/client/extensions/ExtensionSlot.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/route-chunk-recovery.d.ts.map +1 -1
- package/dist/client/route-chunk-recovery.js +14 -9
- package/dist/client/route-chunk-recovery.js.map +1 -1
- package/dist/client/session-replay.d.ts +15 -0
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +20 -0
- package/dist/client/session-replay.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +2 -10
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/store.js +1 -1
- package/dist/extensions/store.js.map +1 -1
- package/dist/localization/default-messages.d.ts +3 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +3 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp/build-server.d.ts +2 -0
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +2 -2
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +1 -1
- package/dist/progress/actions.d.ts.map +1 -1
- package/dist/progress/actions.js +3 -2
- package/dist/progress/actions.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +91 -8
- package/dist/provider-api/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +107 -16
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/server/agent-chat/action-filters-a2a.d.ts +6 -0
- package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
- package/dist/server/agent-chat/action-filters-a2a.js +27 -0
- package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +27 -1
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/agent-conversation.css +7 -0
- package/dist/templates/default/app/i18n/ar-SA.ts +20 -0
- package/dist/templates/default/app/i18n/de-DE.ts +20 -0
- package/dist/templates/default/app/i18n/en-US.ts +20 -0
- package/dist/templates/default/app/i18n/es-ES.ts +20 -0
- package/dist/templates/default/app/i18n/fr-FR.ts +21 -0
- package/dist/templates/default/app/i18n/hi-IN.ts +19 -0
- package/dist/templates/default/app/i18n/ja-JP.ts +20 -0
- package/dist/templates/default/app/i18n/ko-KR.ts +19 -0
- package/dist/templates/default/app/i18n/pt-BR.ts +20 -0
- package/dist/templates/default/app/i18n/zh-CN.ts +19 -0
- package/dist/templates/default/app/i18n/zh-TW.ts +19 -0
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +28 -0
- package/dist/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +13 -0
- package/package.json +1 -1
- package/src/templates/default/app/i18n/ar-SA.ts +20 -0
- package/src/templates/default/app/i18n/de-DE.ts +20 -0
- package/src/templates/default/app/i18n/en-US.ts +20 -0
- package/src/templates/default/app/i18n/es-ES.ts +20 -0
- package/src/templates/default/app/i18n/fr-FR.ts +21 -0
- package/src/templates/default/app/i18n/hi-IN.ts +19 -0
- package/src/templates/default/app/i18n/ja-JP.ts +20 -0
- package/src/templates/default/app/i18n/ko-KR.ts +19 -0
- package/src/templates/default/app/i18n/pt-BR.ts +20 -0
- package/src/templates/default/app/i18n/zh-CN.ts +19 -0
- package/src/templates/default/app/i18n/zh-TW.ts +19 -0
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +28 -0
- package/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +13 -0
- package/corpus/templates/analytics/server/handlers/github.ts +0 -200
- package/corpus/templates/analytics/server/handlers/pylon.ts +0 -43
- package/corpus/templates/analytics/server/lib/apollo.ts +0 -167
- package/corpus/templates/analytics/server/lib/commonroom.ts +0 -149
- package/corpus/templates/analytics/server/lib/github.ts +0 -660
- package/corpus/templates/analytics/server/lib/mixpanel.ts +0 -156
- package/corpus/templates/analytics/server/lib/posthog.ts +0 -194
- package/corpus/templates/analytics/server/lib/pylon.ts +0 -109
- package/corpus/templates/analytics/server/routes/api/github/graphql.post.ts +0 -1
- package/corpus/templates/analytics/server/routes/api/github/issue.get.ts +0 -1
- package/corpus/templates/analytics/server/routes/api/github/org-prs.get.ts +0 -1
- package/corpus/templates/analytics/server/routes/api/github/pr.get.ts +0 -1
- package/corpus/templates/analytics/server/routes/api/github/prs.get.ts +0 -1
- package/corpus/templates/analytics/server/routes/api/github/search.get.ts +0 -1
- package/corpus/templates/slides/actions/fetch-logos.ts +0 -90
- package/corpus/templates/slides/actions/image-search.ts +0 -64
- package/corpus/templates/slides/actions/import-github.ts +0 -182
- package/corpus/templates/slides/actions/logo-lookup.ts +0 -113
|
@@ -4,9 +4,8 @@ import { z } from "zod";
|
|
|
4
4
|
import {
|
|
5
5
|
getChannelHistory,
|
|
6
6
|
getTeamInfo,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
searchMessages,
|
|
7
|
+
listChannelsWithCoverage,
|
|
8
|
+
resolveUsersWithCoverage,
|
|
10
9
|
type SlackMessage,
|
|
11
10
|
type Workspace,
|
|
12
11
|
} from "../server/lib/slack";
|
|
@@ -41,7 +40,7 @@ function enrichMessages(messages: SlackMessage[]): SlackMessage[] {
|
|
|
41
40
|
|
|
42
41
|
export default defineAction({
|
|
43
42
|
description:
|
|
44
|
-
"Query the analytics app's configured Slack workspace: team info, channels, channel history, multi-channel history
|
|
43
|
+
"Query the analytics app's configured Slack workspace: team info, channels, channel history, or multi-channel history. Slack messages returned by this action are real source evidence; you may count mentions, code themes, classify sentiment, and summarize qualitative patterns from them while stating the sample size. The legacy search mode is preserved for compatibility but returns migration guidance because the configured bot credential cannot call Slack global search; use the Slack provider corpus recipe for channel-scoped exhaustive search.",
|
|
45
44
|
schema: z.object({
|
|
46
45
|
mode: z
|
|
47
46
|
.enum(["team", "channels", "history", "multi-history", "search"])
|
|
@@ -68,7 +67,10 @@ export default defineAction({
|
|
|
68
67
|
.max(200)
|
|
69
68
|
.default(50)
|
|
70
69
|
.describe("Message limit for history"),
|
|
71
|
-
cursor: z
|
|
70
|
+
cursor: z
|
|
71
|
+
.string()
|
|
72
|
+
.optional()
|
|
73
|
+
.describe("Slack history/latest timestamp or channel-list cursor"),
|
|
72
74
|
cursors: z
|
|
73
75
|
.record(z.string(), z.string())
|
|
74
76
|
.optional()
|
|
@@ -99,12 +101,31 @@ export default defineAction({
|
|
|
99
101
|
const userIds = messages
|
|
100
102
|
.map((message) => message.user)
|
|
101
103
|
.filter((id): id is string => !!id);
|
|
102
|
-
const
|
|
104
|
+
const resolution = await resolveUsersWithCoverage(
|
|
105
|
+
workspace,
|
|
106
|
+
userIds,
|
|
107
|
+
messages,
|
|
108
|
+
);
|
|
103
109
|
return {
|
|
104
110
|
messages,
|
|
105
|
-
users,
|
|
111
|
+
users: resolution.users,
|
|
106
112
|
has_more: result.has_more,
|
|
107
113
|
next_cursor: result.next_cursor,
|
|
114
|
+
truncated: result.truncated,
|
|
115
|
+
pagination: result.pagination,
|
|
116
|
+
coverage: {
|
|
117
|
+
...result.coverage,
|
|
118
|
+
coverage_complete:
|
|
119
|
+
result.coverage.coverage_complete &&
|
|
120
|
+
resolution.coverage.coverage_complete,
|
|
121
|
+
truncated:
|
|
122
|
+
result.coverage.truncated || resolution.coverage.truncated,
|
|
123
|
+
truncation_reasons: [
|
|
124
|
+
...result.coverage.truncation_reasons,
|
|
125
|
+
...resolution.coverage.truncation_reasons,
|
|
126
|
+
],
|
|
127
|
+
authors: resolution.coverage,
|
|
128
|
+
},
|
|
108
129
|
};
|
|
109
130
|
}
|
|
110
131
|
|
|
@@ -113,57 +134,188 @@ export default defineAction({
|
|
|
113
134
|
const channelIds = args.channels.split(",").filter(Boolean);
|
|
114
135
|
const channelNames = args.names ? args.names.split(",") : channelIds;
|
|
115
136
|
const pageSize = Math.min(args.limit, 200);
|
|
116
|
-
const
|
|
117
|
-
channelIds.map((
|
|
118
|
-
getChannelHistory(
|
|
137
|
+
const channelResults = await Promise.allSettled(
|
|
138
|
+
channelIds.map((channelId) =>
|
|
139
|
+
getChannelHistory(
|
|
140
|
+
workspace,
|
|
141
|
+
channelId,
|
|
142
|
+
pageSize,
|
|
143
|
+
args.cursors?.[channelId],
|
|
144
|
+
),
|
|
119
145
|
),
|
|
120
146
|
);
|
|
147
|
+
const successfulResults = channelResults.flatMap((entry, index) =>
|
|
148
|
+
entry.status === "fulfilled"
|
|
149
|
+
? [{ channelId: channelIds[index], result: entry.value }]
|
|
150
|
+
: [],
|
|
151
|
+
);
|
|
152
|
+
const failedChannelIds = channelResults.flatMap((entry, index) =>
|
|
153
|
+
entry.status === "rejected" ? [channelIds[index]] : [],
|
|
154
|
+
);
|
|
121
155
|
|
|
122
|
-
const allMessages: (SlackMessage & {
|
|
156
|
+
const allMessages: (SlackMessage & {
|
|
157
|
+
channel_id: string;
|
|
158
|
+
channel_name: string;
|
|
159
|
+
})[] = [];
|
|
123
160
|
const perChannelHasMore: Record<string, boolean> = {};
|
|
124
161
|
const nextCursors: Record<string, string> = {};
|
|
125
162
|
|
|
126
|
-
|
|
127
|
-
const channelId = channelIds[idx];
|
|
163
|
+
successfulResults.forEach(({ channelId, result }) => {
|
|
128
164
|
perChannelHasMore[channelId] = result.has_more;
|
|
129
|
-
if (result.next_cursor) nextCursors[channelId] = result.next_cursor;
|
|
130
165
|
for (const message of result.messages) {
|
|
131
166
|
allMessages.push({
|
|
132
167
|
...message,
|
|
133
|
-
|
|
168
|
+
channel_id: channelId,
|
|
169
|
+
channel_name:
|
|
170
|
+
channelNames[channelIds.indexOf(channelId)] || channelId,
|
|
134
171
|
});
|
|
135
172
|
}
|
|
136
173
|
});
|
|
174
|
+
failedChannelIds.forEach((channelId) => {
|
|
175
|
+
perChannelHasMore[channelId] = true;
|
|
176
|
+
});
|
|
137
177
|
|
|
138
178
|
allMessages.sort((a, b) => parseFloat(b.ts) - parseFloat(a.ts));
|
|
139
|
-
const
|
|
179
|
+
const pageMessages = allMessages.slice(0, pageSize);
|
|
180
|
+
const emittedByChannel = new Map<string, SlackMessage[]>();
|
|
181
|
+
for (const message of pageMessages) {
|
|
182
|
+
const emitted = emittedByChannel.get(message.channel_id) ?? [];
|
|
183
|
+
emitted.push(message);
|
|
184
|
+
emittedByChannel.set(message.channel_id, emitted);
|
|
185
|
+
}
|
|
186
|
+
for (const channelId of channelIds) {
|
|
187
|
+
const emitted = emittedByChannel.get(channelId);
|
|
188
|
+
const nextCursor = emitted?.[emitted.length - 1]?.ts;
|
|
189
|
+
if (nextCursor) nextCursors[channelId] = nextCursor;
|
|
190
|
+
else if (args.cursors?.[channelId]) {
|
|
191
|
+
nextCursors[channelId] = args.cursors[channelId];
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const messages = pageMessages.map((message) => {
|
|
196
|
+
const enriched = enrichMessages([message])[0] ?? message;
|
|
197
|
+
const { channel_id: _channelId, ...rest } =
|
|
198
|
+
enriched as typeof message;
|
|
199
|
+
return rest;
|
|
200
|
+
});
|
|
140
201
|
const userIds = messages
|
|
141
202
|
.map((message) => message.user)
|
|
142
203
|
.filter((id): id is string => !!id);
|
|
143
|
-
const
|
|
204
|
+
const resolution = await resolveUsersWithCoverage(
|
|
205
|
+
workspace,
|
|
206
|
+
userIds,
|
|
207
|
+
messages,
|
|
208
|
+
);
|
|
209
|
+
const providerTruncated = successfulResults.some(
|
|
210
|
+
({ result }) => result.truncated,
|
|
211
|
+
);
|
|
212
|
+
const mergedResultTruncated = allMessages.length > pageSize;
|
|
213
|
+
const truncated =
|
|
214
|
+
providerTruncated ||
|
|
215
|
+
mergedResultTruncated ||
|
|
216
|
+
failedChannelIds.length > 0;
|
|
217
|
+
const truncationReasons = [
|
|
218
|
+
...(providerTruncated ? ["provider_has_more"] : []),
|
|
219
|
+
...(mergedResultTruncated ? ["merged_result_limit"] : []),
|
|
220
|
+
...failedChannelIds.map(
|
|
221
|
+
(channelId) => `channel_fetch_failed:${channelId}`,
|
|
222
|
+
),
|
|
223
|
+
];
|
|
224
|
+
const channelPagination = Object.fromEntries(
|
|
225
|
+
channelResults.map((entry, index) => [
|
|
226
|
+
channelIds[index],
|
|
227
|
+
entry.status === "fulfilled"
|
|
228
|
+
? entry.value.pagination
|
|
229
|
+
: {
|
|
230
|
+
cursor_type: "latest_ts" as const,
|
|
231
|
+
...(args.cursors?.[channelIds[index]]
|
|
232
|
+
? { request_cursor: args.cursors[channelIds[index]] }
|
|
233
|
+
: {}),
|
|
234
|
+
},
|
|
235
|
+
]),
|
|
236
|
+
);
|
|
237
|
+
const channelCoverage = Object.fromEntries(
|
|
238
|
+
channelResults.map((entry, index) => [
|
|
239
|
+
channelIds[index],
|
|
240
|
+
entry.status === "fulfilled"
|
|
241
|
+
? entry.value.coverage
|
|
242
|
+
: {
|
|
243
|
+
requested: pageSize,
|
|
244
|
+
fetched: 0,
|
|
245
|
+
returned: 0,
|
|
246
|
+
pages_fetched: 0,
|
|
247
|
+
coverage_complete: false,
|
|
248
|
+
truncated: true,
|
|
249
|
+
truncation_reasons: [
|
|
250
|
+
`channel_fetch_failed:${channelIds[index]}`,
|
|
251
|
+
],
|
|
252
|
+
},
|
|
253
|
+
]),
|
|
254
|
+
);
|
|
144
255
|
return {
|
|
145
256
|
messages,
|
|
146
|
-
users,
|
|
257
|
+
users: resolution.users,
|
|
147
258
|
has_more:
|
|
148
259
|
Object.values(perChannelHasMore).some(Boolean) ||
|
|
149
|
-
allMessages.length > pageSize
|
|
260
|
+
allMessages.length > pageSize ||
|
|
261
|
+
failedChannelIds.length > 0,
|
|
150
262
|
next_cursors: nextCursors,
|
|
151
263
|
total: allMessages.length,
|
|
264
|
+
truncated,
|
|
265
|
+
pagination: {
|
|
266
|
+
cursor_type: "per_channel_latest_ts",
|
|
267
|
+
request_cursors: args.cursors ?? {},
|
|
268
|
+
next_cursors: nextCursors,
|
|
269
|
+
channels: channelPagination,
|
|
270
|
+
},
|
|
271
|
+
coverage: {
|
|
272
|
+
requested: channelIds.length * pageSize,
|
|
273
|
+
fetched: allMessages.length,
|
|
274
|
+
returned: messages.length,
|
|
275
|
+
pages_fetched: successfulResults.length,
|
|
276
|
+
coverage_complete:
|
|
277
|
+
!truncated && resolution.coverage.coverage_complete,
|
|
278
|
+
truncated: truncated || resolution.coverage.truncated,
|
|
279
|
+
truncation_reasons: [
|
|
280
|
+
...truncationReasons,
|
|
281
|
+
...resolution.coverage.truncation_reasons,
|
|
282
|
+
],
|
|
283
|
+
channels: channelCoverage,
|
|
284
|
+
authors: resolution.coverage,
|
|
285
|
+
},
|
|
152
286
|
};
|
|
153
287
|
}
|
|
154
288
|
|
|
155
289
|
if (args.mode === "search") {
|
|
156
290
|
if (!args.query) return { error: "query is required" };
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
291
|
+
return {
|
|
292
|
+
messages: [],
|
|
293
|
+
users: {},
|
|
294
|
+
total: 0,
|
|
295
|
+
unsupported: true,
|
|
296
|
+
truncated: true,
|
|
297
|
+
coverage: {
|
|
298
|
+
requested: 0,
|
|
299
|
+
fetched: 0,
|
|
300
|
+
returned: 0,
|
|
301
|
+
pages_fetched: 0,
|
|
302
|
+
coverage_complete: false,
|
|
303
|
+
truncated: true,
|
|
304
|
+
truncation_reasons: ["bot_token_global_search_unsupported"],
|
|
305
|
+
},
|
|
306
|
+
guidance:
|
|
307
|
+
"Slack global search is not available with the configured bot credential. Resolve a channel id, then use provider-api-catalog(provider='slack') and provider-corpus-job with the Slack conversations.history corpus recipe so cursor pages are fetched inside one resumable operation.",
|
|
308
|
+
};
|
|
163
309
|
}
|
|
164
310
|
|
|
165
|
-
const
|
|
166
|
-
return {
|
|
311
|
+
const result = await listChannelsWithCoverage(workspace, args.cursor);
|
|
312
|
+
return {
|
|
313
|
+
channels: result.channels,
|
|
314
|
+
total: result.total,
|
|
315
|
+
truncated: result.truncated,
|
|
316
|
+
pagination: result.pagination,
|
|
317
|
+
coverage: result.coverage,
|
|
318
|
+
};
|
|
167
319
|
} catch (err) {
|
|
168
320
|
return providerError(err);
|
|
169
321
|
}
|
|
@@ -19,14 +19,12 @@ import {
|
|
|
19
19
|
useCallback,
|
|
20
20
|
useContext,
|
|
21
21
|
useEffect,
|
|
22
|
-
useLayoutEffect,
|
|
23
22
|
useMemo,
|
|
24
23
|
useRef,
|
|
25
24
|
useState,
|
|
26
25
|
type CSSProperties,
|
|
27
26
|
type ReactNode,
|
|
28
27
|
} from "react";
|
|
29
|
-
import { createPortal } from "react-dom";
|
|
30
28
|
import { Link } from "react-router";
|
|
31
29
|
import {
|
|
32
30
|
Area,
|
|
@@ -61,6 +59,7 @@ import {
|
|
|
61
59
|
SelectValue,
|
|
62
60
|
} from "@/components/ui/select";
|
|
63
61
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
62
|
+
import { useChartTooltipFlip } from "@/hooks/use-chart-tooltip-flip";
|
|
64
63
|
|
|
65
64
|
const PAGE_SIZE_OPTIONS = [10, 25, 50, 100];
|
|
66
65
|
import { createDemoChartTrendRows } from "@/lib/demo-chart-trend";
|
|
@@ -90,11 +89,6 @@ const CHART_TOOLTIP_WRAPPER_STYLE: CSSProperties = {
|
|
|
90
89
|
pointerEvents: "none",
|
|
91
90
|
};
|
|
92
91
|
|
|
93
|
-
const PORTAL_GUTTER_PADDING = 12;
|
|
94
|
-
const PORTAL_CURSOR_OFFSET = 24;
|
|
95
|
-
const useBrowserLayoutEffect =
|
|
96
|
-
typeof window === "undefined" ? useEffect : useLayoutEffect;
|
|
97
|
-
|
|
98
92
|
const CHART_TOOLTIP_PROPS = {
|
|
99
93
|
allowEscapeViewBox: { x: true, y: true },
|
|
100
94
|
wrapperStyle: CHART_TOOLTIP_WRAPPER_STYLE,
|
|
@@ -598,7 +592,7 @@ export function SeriesLegend({
|
|
|
598
592
|
if (!shouldShowLegend(panel, keys.length)) return null;
|
|
599
593
|
|
|
600
594
|
return (
|
|
601
|
-
<div className="mt-
|
|
595
|
+
<div className="mt-1 max-h-16 overflow-y-auto overflow-x-hidden pr-1 text-[11px] leading-4 text-muted-foreground">
|
|
602
596
|
<div className="flex flex-wrap gap-x-3 gap-y-1">
|
|
603
597
|
{keys.map((key, i) => {
|
|
604
598
|
const hidden = hiddenKeys?.has(key) ?? false;
|
|
@@ -612,7 +606,7 @@ export function SeriesLegend({
|
|
|
612
606
|
>
|
|
613
607
|
<PopoverAnchor asChild>
|
|
614
608
|
<div
|
|
615
|
-
className="inline-flex min-h-
|
|
609
|
+
className="inline-flex min-h-6 max-w-[14rem] items-center"
|
|
616
610
|
onPointerDown={(event) => {
|
|
617
611
|
if (!hasLegendActions || event.pointerType === "mouse") {
|
|
618
612
|
return;
|
|
@@ -648,7 +642,7 @@ export function SeriesLegend({
|
|
|
648
642
|
}
|
|
649
643
|
aria-haspopup={hasLegendActions ? "menu" : undefined}
|
|
650
644
|
data-chart-legend-item={key}
|
|
651
|
-
className={`inline-flex min-h-
|
|
645
|
+
className={`inline-flex min-h-6 max-w-[14rem] min-w-0 items-center gap-1.5 rounded-md px-1.5 text-left transition-[opacity,color] touch-manipulation hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring ${
|
|
652
646
|
hidden ? "opacity-35" : "opacity-100"
|
|
653
647
|
} ${onToggleKey ? "cursor-pointer" : "cursor-default"}`}
|
|
654
648
|
title={label}
|
|
@@ -680,18 +674,18 @@ export function SeriesLegend({
|
|
|
680
674
|
align="center"
|
|
681
675
|
sideOffset={8}
|
|
682
676
|
collisionPadding={12}
|
|
683
|
-
className="w-
|
|
677
|
+
className="w-auto max-w-[calc(100vw-1.5rem)] rounded-lg p-1 shadow-lg"
|
|
684
678
|
onPointerEnter={clearCloseTimeout}
|
|
685
679
|
onPointerLeave={scheduleCloseLegendActions}
|
|
686
680
|
onFocusCapture={clearCloseTimeout}
|
|
687
681
|
>
|
|
688
|
-
<div className="flex
|
|
682
|
+
<div className="flex items-center gap-0.5">
|
|
689
683
|
{onFilterKey && (
|
|
690
684
|
<button
|
|
691
685
|
type="button"
|
|
692
686
|
data-chart-legend-action="filter"
|
|
693
687
|
aria-label={`${t("sqlDashboard.filterSeries")} ${label}`}
|
|
694
|
-
className="min-h-
|
|
688
|
+
className="min-h-8 rounded-md px-2.5 py-1 text-xs font-medium whitespace-nowrap text-popover-foreground outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground"
|
|
695
689
|
onClick={() => {
|
|
696
690
|
onFilterKey(key);
|
|
697
691
|
setOpenKey(null);
|
|
@@ -706,7 +700,7 @@ export function SeriesLegend({
|
|
|
706
700
|
data-chart-legend-action="hide"
|
|
707
701
|
aria-label={`${t("sqlDashboard.hide")} ${label}`}
|
|
708
702
|
disabled={hidden}
|
|
709
|
-
className="min-h-
|
|
703
|
+
className="min-h-8 rounded-md px-2.5 py-1 text-xs font-medium whitespace-nowrap text-popover-foreground outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground disabled:pointer-events-none disabled:opacity-40"
|
|
710
704
|
onClick={() => {
|
|
711
705
|
onToggleKey(key);
|
|
712
706
|
setOpenKey(null);
|
|
@@ -886,9 +880,9 @@ function SqlChartLoadingSkeleton({ panel }: { panel: SqlPanel }) {
|
|
|
886
880
|
<Skeleton
|
|
887
881
|
className={`w-full ${fill ? "h-full min-h-[250px] flex-1" : "h-[250px]"}`}
|
|
888
882
|
/>
|
|
889
|
-
<div className="mt-
|
|
890
|
-
{Array.from({ length:
|
|
891
|
-
<div key={index} className="flex items-center gap-1.5">
|
|
883
|
+
<div className="mt-1 flex min-h-6 flex-wrap gap-x-3 gap-y-1 overflow-hidden pr-1">
|
|
884
|
+
{Array.from({ length: 3 }).map((_, index) => (
|
|
885
|
+
<div key={index} className="flex min-h-6 items-center gap-1.5">
|
|
892
886
|
<Skeleton className="h-2.5 w-3 shrink-0 rounded-sm" />
|
|
893
887
|
<Skeleton className="h-3 w-20 min-w-0" />
|
|
894
888
|
</div>
|
|
@@ -898,7 +892,7 @@ function SqlChartLoadingSkeleton({ panel }: { panel: SqlPanel }) {
|
|
|
898
892
|
);
|
|
899
893
|
}
|
|
900
894
|
|
|
901
|
-
function ChartTooltip({
|
|
895
|
+
export function ChartTooltip({
|
|
902
896
|
active,
|
|
903
897
|
payload,
|
|
904
898
|
label,
|
|
@@ -918,12 +912,7 @@ function ChartTooltip({
|
|
|
918
912
|
seriesNameFormatter?: (value: string) => string;
|
|
919
913
|
valueFormatter?: (value: number) => string;
|
|
920
914
|
}) {
|
|
921
|
-
const
|
|
922
|
-
const portalRef = useRef<HTMLDivElement | null>(null);
|
|
923
|
-
const [portalPosition, setPortalPosition] = useState<{
|
|
924
|
-
left: number;
|
|
925
|
-
top: number;
|
|
926
|
-
} | null>(null);
|
|
915
|
+
const tooltipRef = useChartTooltipFlip<HTMLDivElement>(active);
|
|
927
916
|
const items = useMemo(
|
|
928
917
|
() =>
|
|
929
918
|
sortTooltipPayloadItems(
|
|
@@ -932,11 +921,6 @@ function ChartTooltip({
|
|
|
932
921
|
),
|
|
933
922
|
[payload],
|
|
934
923
|
);
|
|
935
|
-
const portalVisible = portalPosition !== null;
|
|
936
|
-
const clearPortalPosition = useCallback(
|
|
937
|
-
() => setPortalPosition((prev) => (prev === null ? prev : null)),
|
|
938
|
-
[],
|
|
939
|
-
);
|
|
940
924
|
|
|
941
925
|
const labelText =
|
|
942
926
|
label == null
|
|
@@ -945,96 +929,14 @@ function ChartTooltip({
|
|
|
945
929
|
? labelFormatter(String(label))
|
|
946
930
|
: String(label);
|
|
947
931
|
|
|
948
|
-
useBrowserLayoutEffect(() => {
|
|
949
|
-
if (!active || items.length === 0 || typeof window === "undefined") {
|
|
950
|
-
clearPortalPosition();
|
|
951
|
-
return;
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
const anchor = anchorRef.current;
|
|
955
|
-
const wrapper = anchor?.parentElement;
|
|
956
|
-
if (!anchor || !wrapper) return;
|
|
957
|
-
|
|
958
|
-
let frame = 0;
|
|
959
|
-
const apply = () => {
|
|
960
|
-
frame = 0;
|
|
961
|
-
if (!(wrapper as HTMLElement).style.transform) return;
|
|
962
|
-
|
|
963
|
-
const anchorRect = anchor.getBoundingClientRect();
|
|
964
|
-
const portalRect = portalRef.current?.getBoundingClientRect();
|
|
965
|
-
const width = portalRect?.width || anchorRect.width;
|
|
966
|
-
const height = portalRect?.height || anchorRect.height;
|
|
967
|
-
if (width === 0 || height === 0) return;
|
|
968
|
-
|
|
969
|
-
const sidebar = document.querySelector(".agent-sidebar-panel");
|
|
970
|
-
const sidebarRect = sidebar?.getBoundingClientRect();
|
|
971
|
-
const rightLimit =
|
|
972
|
-
sidebarRect && sidebarRect.width > 0 && sidebarRect.left > 0
|
|
973
|
-
? sidebarRect.left - PORTAL_GUTTER_PADDING
|
|
974
|
-
: window.innerWidth - PORTAL_GUTTER_PADDING;
|
|
975
|
-
const bottomLimit = window.innerHeight - PORTAL_GUTTER_PADDING;
|
|
976
|
-
|
|
977
|
-
let left = anchorRect.left;
|
|
978
|
-
let top = anchorRect.top;
|
|
979
|
-
|
|
980
|
-
if (left + width > rightLimit) {
|
|
981
|
-
left = anchorRect.left - width - PORTAL_CURSOR_OFFSET;
|
|
982
|
-
}
|
|
983
|
-
left = Math.max(
|
|
984
|
-
PORTAL_GUTTER_PADDING,
|
|
985
|
-
Math.min(left, rightLimit - width),
|
|
986
|
-
);
|
|
987
|
-
|
|
988
|
-
if (top + height > bottomLimit) {
|
|
989
|
-
top = bottomLimit - height;
|
|
990
|
-
}
|
|
991
|
-
top = Math.max(PORTAL_GUTTER_PADDING, top);
|
|
992
|
-
|
|
993
|
-
setPortalPosition((prev) =>
|
|
994
|
-
prev &&
|
|
995
|
-
Math.abs(prev.left - left) < 0.5 &&
|
|
996
|
-
Math.abs(prev.top - top) < 0.5
|
|
997
|
-
? prev
|
|
998
|
-
: { left, top },
|
|
999
|
-
);
|
|
1000
|
-
};
|
|
1001
|
-
|
|
1002
|
-
const schedule = () => {
|
|
1003
|
-
if (frame) return;
|
|
1004
|
-
frame = window.requestAnimationFrame(apply);
|
|
1005
|
-
};
|
|
1006
|
-
|
|
1007
|
-
schedule();
|
|
1008
|
-
|
|
1009
|
-
const mutationObserver = new MutationObserver(schedule);
|
|
1010
|
-
mutationObserver.observe(wrapper, {
|
|
1011
|
-
attributes: true,
|
|
1012
|
-
attributeFilter: ["style", "class"],
|
|
1013
|
-
});
|
|
1014
|
-
|
|
1015
|
-
const resizeObserver =
|
|
1016
|
-
typeof ResizeObserver === "undefined"
|
|
1017
|
-
? null
|
|
1018
|
-
: new ResizeObserver(schedule);
|
|
1019
|
-
resizeObserver?.observe(anchor);
|
|
1020
|
-
if (portalRef.current) resizeObserver?.observe(portalRef.current);
|
|
1021
|
-
|
|
1022
|
-
window.addEventListener("resize", schedule);
|
|
1023
|
-
window.addEventListener("scroll", schedule, true);
|
|
1024
|
-
|
|
1025
|
-
return () => {
|
|
1026
|
-
if (frame) window.cancelAnimationFrame(frame);
|
|
1027
|
-
mutationObserver.disconnect();
|
|
1028
|
-
resizeObserver?.disconnect();
|
|
1029
|
-
window.removeEventListener("resize", schedule);
|
|
1030
|
-
window.removeEventListener("scroll", schedule, true);
|
|
1031
|
-
};
|
|
1032
|
-
}, [active, clearPortalPosition, items.length, portalVisible]);
|
|
1033
|
-
|
|
1034
932
|
if (!active || items.length === 0) return null;
|
|
1035
933
|
|
|
1036
934
|
const tooltip = (
|
|
1037
|
-
<div
|
|
935
|
+
<div
|
|
936
|
+
ref={tooltipRef}
|
|
937
|
+
role="tooltip"
|
|
938
|
+
className="min-w-40 max-w-[280px] rounded-md border border-border bg-card px-3 py-2 text-xs text-foreground shadow-lg"
|
|
939
|
+
>
|
|
1038
940
|
{labelText && (
|
|
1039
941
|
<div className="mb-1.5 truncate font-medium text-foreground">
|
|
1040
942
|
{labelText}
|
|
@@ -1068,31 +970,7 @@ function ChartTooltip({
|
|
|
1068
970
|
</div>
|
|
1069
971
|
);
|
|
1070
972
|
|
|
1071
|
-
return
|
|
1072
|
-
<>
|
|
1073
|
-
<div ref={anchorRef} aria-hidden="true" className="invisible">
|
|
1074
|
-
{tooltip}
|
|
1075
|
-
</div>
|
|
1076
|
-
{portalPosition && typeof document !== "undefined"
|
|
1077
|
-
? createPortal(
|
|
1078
|
-
<div
|
|
1079
|
-
ref={portalRef}
|
|
1080
|
-
role="tooltip"
|
|
1081
|
-
style={{
|
|
1082
|
-
position: "fixed",
|
|
1083
|
-
left: portalPosition.left,
|
|
1084
|
-
top: portalPosition.top,
|
|
1085
|
-
zIndex: 1000,
|
|
1086
|
-
pointerEvents: "none",
|
|
1087
|
-
}}
|
|
1088
|
-
>
|
|
1089
|
-
{tooltip}
|
|
1090
|
-
</div>,
|
|
1091
|
-
document.body,
|
|
1092
|
-
)
|
|
1093
|
-
: null}
|
|
1094
|
-
</>
|
|
1095
|
-
);
|
|
973
|
+
return tooltip;
|
|
1096
974
|
}
|
|
1097
975
|
|
|
1098
976
|
function detectKeys(
|
|
@@ -1434,16 +1312,33 @@ function DashboardExtensionPanel({
|
|
|
1434
1312
|
// dashboard report screenshots don't capture a blank extension panel.
|
|
1435
1313
|
const [ready, setReady] = useState(false);
|
|
1436
1314
|
const [unavailable, setUnavailable] = useState(false);
|
|
1315
|
+
const loadingSkeleton = !ready ? (
|
|
1316
|
+
<Skeleton
|
|
1317
|
+
data-dashboard-extension-loading="true"
|
|
1318
|
+
className="absolute inset-0 z-10 h-full min-h-[180px] w-full rounded-md"
|
|
1319
|
+
aria-hidden="true"
|
|
1320
|
+
/>
|
|
1321
|
+
) : null;
|
|
1437
1322
|
|
|
1438
1323
|
if (slotId) {
|
|
1439
1324
|
return (
|
|
1440
|
-
<
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1325
|
+
<div
|
|
1326
|
+
className="relative min-h-[180px] w-full"
|
|
1327
|
+
aria-busy={!ready}
|
|
1328
|
+
data-dashboard-report-loading={ready ? undefined : "true"}
|
|
1329
|
+
>
|
|
1330
|
+
{loadingSkeleton}
|
|
1331
|
+
<div className={ready ? "opacity-100" : "opacity-0"}>
|
|
1332
|
+
<ExtensionSlot
|
|
1333
|
+
id={slotId}
|
|
1334
|
+
context={context}
|
|
1335
|
+
showEmptyAffordance
|
|
1336
|
+
onReady={() => setReady(true)}
|
|
1337
|
+
className="min-h-[120px] w-full"
|
|
1338
|
+
toolClassName="w-full"
|
|
1339
|
+
/>
|
|
1340
|
+
</div>
|
|
1341
|
+
</div>
|
|
1447
1342
|
);
|
|
1448
1343
|
}
|
|
1449
1344
|
|
|
@@ -1462,15 +1357,16 @@ function DashboardExtensionPanel({
|
|
|
1462
1357
|
|
|
1463
1358
|
return (
|
|
1464
1359
|
<div
|
|
1465
|
-
className="w-full"
|
|
1360
|
+
className="relative min-h-[180px] w-full"
|
|
1361
|
+
aria-busy={!ready}
|
|
1466
1362
|
data-dashboard-report-loading={ready ? undefined : "true"}
|
|
1467
1363
|
>
|
|
1364
|
+
{loadingSkeleton}
|
|
1468
1365
|
<EmbeddedExtension
|
|
1469
1366
|
extensionId={extensionId!}
|
|
1470
1367
|
slotId={`dashboard-panel-${panelId}`}
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
// receive the dashboard's filters/variables/date range as `context`.
|
|
1368
|
+
context={context}
|
|
1369
|
+
className={ready ? "w-full opacity-100" : "w-full opacity-0"}
|
|
1474
1370
|
initialHeight={180}
|
|
1475
1371
|
onReady={() => setReady(true)}
|
|
1476
1372
|
onUnavailable={() => {
|
|
@@ -136,7 +136,7 @@ const ChartTooltipContent = React.forwardRef<
|
|
|
136
136
|
ref,
|
|
137
137
|
) => {
|
|
138
138
|
const { config } = useChart();
|
|
139
|
-
const flipRef = useChartTooltipFlip<HTMLDivElement>();
|
|
139
|
+
const flipRef = useChartTooltipFlip<HTMLDivElement>(active);
|
|
140
140
|
const setRefs = React.useCallback(
|
|
141
141
|
(node: HTMLDivElement | null) => {
|
|
142
142
|
flipRef.current = node;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEffect, useRef } from "react";
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const VIEWPORT_GUTTER_PADDING = 12;
|
|
4
4
|
const FLIP_CURSOR_OFFSET = 24;
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -10,10 +10,11 @@ const FLIP_CURSOR_OFFSET = 24;
|
|
|
10
10
|
* `transform` (cursor moves) and translate the content left when its right
|
|
11
11
|
* edge would land inside `.agent-sidebar-panel`.
|
|
12
12
|
*/
|
|
13
|
-
export function useChartTooltipFlip<T extends HTMLElement>() {
|
|
13
|
+
export function useChartTooltipFlip<T extends HTMLElement>(active = true) {
|
|
14
14
|
const ref = useRef<T | null>(null);
|
|
15
15
|
|
|
16
16
|
useEffect(() => {
|
|
17
|
+
if (!active) return;
|
|
17
18
|
const el = ref.current;
|
|
18
19
|
if (!el) return;
|
|
19
20
|
const wrapper = el.parentElement;
|
|
@@ -32,11 +33,25 @@ export function useChartTooltipFlip<T extends HTMLElement>() {
|
|
|
32
33
|
sidebarRect && sidebarRect.width > 0 && sidebarRect.left > 0
|
|
33
34
|
? sidebarRect.left
|
|
34
35
|
: window.innerWidth;
|
|
35
|
-
const
|
|
36
|
+
const rightLimit = gutterLeft - VIEWPORT_GUTTER_PADDING;
|
|
37
|
+
const bottomLimit = window.innerHeight - VIEWPORT_GUTTER_PADDING;
|
|
38
|
+
let translateX = 0;
|
|
39
|
+
let translateY = 0;
|
|
36
40
|
|
|
37
|
-
if (rect.right >
|
|
38
|
-
|
|
41
|
+
if (rect.right > rightLimit) {
|
|
42
|
+
translateX = -(rect.width + FLIP_CURSOR_OFFSET);
|
|
39
43
|
}
|
|
44
|
+
if (rect.bottom > bottomLimit) {
|
|
45
|
+
translateY = bottomLimit - rect.bottom;
|
|
46
|
+
} else if (rect.top < VIEWPORT_GUTTER_PADDING) {
|
|
47
|
+
translateY = VIEWPORT_GUTTER_PADDING - rect.top;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const transforms = [
|
|
51
|
+
translateX ? `translateX(${translateX}px)` : "",
|
|
52
|
+
translateY ? `translateY(${translateY}px)` : "",
|
|
53
|
+
].filter(Boolean);
|
|
54
|
+
node.style.transform = transforms.join(" ");
|
|
40
55
|
};
|
|
41
56
|
|
|
42
57
|
apply();
|
|
@@ -46,7 +61,7 @@ export function useChartTooltipFlip<T extends HTMLElement>() {
|
|
|
46
61
|
attributeFilter: ["style"],
|
|
47
62
|
});
|
|
48
63
|
return () => observer.disconnect();
|
|
49
|
-
}, []);
|
|
64
|
+
}, [active]);
|
|
50
65
|
|
|
51
66
|
return ref;
|
|
52
67
|
}
|