@agent-native/core-corpus 0.210.2 → 0.211.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/templates/analytics/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +41 -2
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +4 -2
- package/corpus/templates/analytics/CHANGELOG.md +18 -0
- package/corpus/templates/analytics/actions/build-data-index.ts +11 -2
- package/corpus/templates/analytics/actions/configure-content-collection.ts +29 -4
- package/corpus/templates/analytics/actions/configure-first-party-events-model.ts +9 -7
- package/corpus/templates/analytics/actions/create-analytics-public-key.ts +4 -0
- package/corpus/templates/analytics/actions/estimate-content-signups-cost.ts +72 -0
- package/corpus/templates/analytics/actions/estimate-query-cost.ts +16 -134
- package/corpus/templates/analytics/actions/list-sigma-workbooks.ts +123 -42
- package/corpus/templates/analytics/actions/migrate-sigma-workbook.ts +20 -17
- package/corpus/templates/analytics/actions/revoke-analytics-public-key.ts +4 -0
- package/corpus/templates/analytics/app/components/dashboard/SigmaMigrationDialog.tsx +246 -680
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/analytics/app/i18n/en-US.ts +54 -55
- package/corpus/templates/analytics/app/pages/DashboardOverview.tsx +0 -1
- package/corpus/templates/analytics/app/pages/DataSources.tsx +56 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/filter-vars.ts +4 -3
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +26 -8
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/interpolate.ts +3 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/panel-cost-notice.ts +172 -0
- package/corpus/templates/analytics/app/pages/data-sources/SearchConsoleDetail.tsx +441 -0
- package/corpus/templates/analytics/changelog/2026-10-15-a-content-dashboard-lists-every-blog-article-with-its-author.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-15-data-sources-has-a-google-search-console-card-that-shows-the.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-16-the-content-dashboard-can-show-signups-per-blog-article.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-19-creating-or-revoking-a-public-analytics-key-now-asks-you-to-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-19-search-sigma-workbooks-by-name-and-open-ones-a-teammate-alre.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-20-blog-signup-attribution-excludes-signups-before-the-first-vi.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-20-collapsed-analytics-navigation-starts-at-the-top.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-20-content-keeps-successful-coverage-dates-and-missing-day-gaps.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-20-private-github-repositories-can-be-indexed-with-your-connect.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-20-search-console-preserves-backfill-and-paused-collection.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-20-search-console-refreshes-historical-coverage-when-properties.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-20-search-console-setup-keeps-saved-properties-readable-and-sup.md +6 -0
- package/corpus/templates/analytics/seeds/dashboards/content-view.json +182 -0
- package/corpus/templates/analytics/server/db/schema.ts +1 -0
- package/corpus/templates/analytics/server/lib/bi-migration/external-dashboards-store.ts +56 -18
- package/corpus/templates/analytics/server/lib/bi-migration/unfinished-import.ts +64 -0
- package/corpus/templates/analytics/server/lib/builtin-dashboard-pass.ts +17 -2
- package/corpus/templates/analytics/server/lib/content-metrics/collect.ts +2 -0
- package/corpus/templates/analytics/server/lib/content-metrics/config.ts +92 -3
- package/corpus/templates/analytics/server/lib/content-metrics/legacy-content-view.json +172 -0
- package/corpus/templates/analytics/server/lib/content-metrics/migration.ts +2 -0
- package/corpus/templates/analytics/server/lib/content-metrics/steps/daily-metrics.ts +8 -3
- package/corpus/templates/analytics/server/lib/content-metrics/steps/search-console.ts +16 -3
- package/corpus/templates/analytics/server/lib/content-metrics/steps/signups.ts +240 -0
- package/corpus/templates/analytics/server/lib/content-metrics/store.ts +5 -0
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +21 -0
- package/corpus/templates/analytics/server/lib/dashboard-panel-verification.ts +300 -5
- package/corpus/templates/analytics/server/lib/dashboard-seeds.ts +2 -0
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +28 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +128 -24
- package/corpus/templates/analytics/server/lib/google-analytics.ts +56 -16
- package/corpus/templates/analytics/server/lib/index-build-github.ts +5 -0
- package/corpus/templates/analytics/server/lib/provider-credentials.ts +47 -2
- package/corpus/templates/analytics/server/lib/query-cost-estimate.ts +184 -5
- package/corpus/templates/analytics/server/plugins/db.ts +9 -1
- package/corpus/templates/analytics/shared/builtin-dashboard-ids.ts +2 -0
- package/corpus/templates/analytics/shared/search-console-property.ts +78 -0
- package/corpus/templates/assets/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/brain/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/calendar/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/calendar/actions/delete-event.ts +1 -3
- package/corpus/templates/calendar/actions/delete-events.ts +1 -2
- package/corpus/templates/calendar/actions/event-action-helpers.ts +0 -4
- package/corpus/templates/calendar/actions/update-event.ts +2 -6
- package/corpus/templates/chat/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/clips/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/clips/CHANGELOG.md +11 -24
- package/corpus/templates/clips/actions/create-recording-upload.ts +5 -1
- package/corpus/templates/clips/app/components/player/chapter-list.tsx +7 -6
- package/corpus/templates/clips/app/components/player/comment-composer.tsx +5 -1
- package/corpus/templates/clips/app/components/player/player-controls.tsx +1 -0
- package/corpus/templates/clips/app/components/player/scrubber.tsx +4 -2
- package/corpus/templates/clips/app/i18n/en-US.ts +3 -3
- package/corpus/templates/clips/app/lib/extension-auth.ts +70 -0
- package/corpus/templates/clips/app/root.tsx +22 -10
- package/corpus/templates/clips/app/routes/_app.notifications.tsx +3 -0
- package/corpus/templates/clips/app/routes/import.tsx +115 -110
- package/corpus/templates/clips/changelog/2026-10-16-agent-uploads-can-use-free-clips-storage.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-19-agents-see-a-clip-s-frames-as-soon-as-it-finishes-processing.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-19-chapter-list-times-now-match-the-player-s-clock-and-each-cha.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-19-editing-a-comment-puts-the-cursor-after-its-text-and-reply-o.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-19-youtube-import-followups.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-20-locally-saved-desktop-recordings-now-appear-in-the-recovery-.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +29 -186
- package/corpus/templates/clips/desktop/src/components/RecordingRecovery.tsx +171 -16
- package/corpus/templates/clips/desktop/src/lib/record-first.ts +9 -32
- package/corpus/templates/clips/desktop/src/lib/recording-recovery.ts +30 -1
- package/corpus/templates/clips/server/lib/agent-frame-request.ts +5 -2
- package/corpus/templates/clips/server/lib/recording-upload-ticket.ts +8 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +2 -0
- package/corpus/templates/content/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/content/CHANGELOG.md +12 -0
- package/corpus/templates/content/actions/_content-database-personal-view.ts +5 -15
- package/corpus/templates/content/actions/_database-navigation.ts +3 -3
- package/corpus/templates/content/actions/_database-utils.ts +10 -22
- package/corpus/templates/content/actions/_database-view-setup.ts +16 -76
- package/corpus/templates/content/actions/create-comment-ai-suggestion.ts +93 -44
- package/corpus/templates/content/actions/export-document.ts +2 -14
- package/corpus/templates/content/actions/suggest-document-edit.ts +5 -7
- package/corpus/templates/content/actions/update-content-database-view.ts +2 -14
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +86 -30
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +64 -28
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +6 -46
- package/corpus/templates/content/app/components/editor/PageDraftRecovery.tsx +72 -7
- package/corpus/templates/content/app/components/editor/TableHoverControls.tsx +292 -103
- package/corpus/templates/content/app/components/editor/ThreadSuggestion.tsx +147 -40
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +108 -11
- package/corpus/templates/content/app/components/editor/database/ContentTable.tsx +2 -1
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +150 -166
- package/corpus/templates/content/app/components/editor/database/database-cell-comments.tsx +515 -0
- package/corpus/templates/content/app/components/editor/database/database-item-comments.tsx +5 -43
- package/corpus/templates/content/app/components/editor/database/filter-sort.ts +8 -783
- package/corpus/templates/content/app/components/editor/live-editor-session.ts +5 -1
- package/corpus/templates/content/app/components/editor/page-draft-journal.ts +61 -1
- package/corpus/templates/content/app/components/editor/property-comments.tsx +35 -4
- package/corpus/templates/content/app/components/editor/property-date-format.ts +45 -0
- package/corpus/templates/content/app/components/editor/thread-suggestions.ts +30 -0
- package/corpus/templates/content/app/components/editor/useDocumentReconcileRecovery.ts +23 -4
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +36 -10
- package/corpus/templates/content/app/global.css +23 -0
- package/corpus/templates/content/app/i18n-data.ts +1 -0
- package/corpus/templates/content/changelog/2026-10-16-opening-a-page-in-a-new-tab-while-another-tab-is-still-savin.md +6 -0
- package/corpus/templates/content/changelog/2026-10-16-typing-steadily-in-one-tab-no-longer-makes-another-open-tab-.md +6 -0
- package/corpus/templates/content/changelog/2026-10-19-database-views-can-filter-the-same-property-more-than-once-n.md +6 -0
- package/corpus/templates/content/changelog/2026-10-19-edits-made-from-a-block-s-menu-or-a-table-s-row-and-column-m.md +6 -0
- package/corpus/templates/content/changelog/2026-10-19-starting-a-comment-puts-the-cursor-in-the-comment-box-ready-.md +6 -0
- package/corpus/templates/content/changelog/2026-10-19-table-row-and-column-options-now-appear-for-the-row-or-colum.md +6 -0
- package/corpus/templates/content/docs/product/capabilities/content.comment.page-owned.md +5 -1
- package/corpus/templates/content/docs/product/capabilities/content.revision.suggestions.md +3 -1
- package/corpus/templates/content/e2e/helpers.ts +10 -0
- package/corpus/templates/content/shared/api.ts +18 -12
- package/corpus/templates/content/shared/database-query.ts +107 -13
- package/corpus/templates/content/shared/suggestion-diff.ts +35 -0
- package/corpus/templates/crm/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/design/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/design/CHANGELOG.md +2 -0
- package/corpus/templates/design/actions/delete-file.ts +1 -4
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +10 -1
- package/corpus/templates/design/app/components/visual-editor/ReviewCanvasPins.tsx +24 -4
- package/corpus/templates/design/app/pages/design-editor/commands/mode-change.ts +14 -9
- package/corpus/templates/design/app/pages/design-editor/domains/use-editor-modes.ts +23 -2
- package/corpus/templates/design/app/pages/design-editor/tool-state.ts +29 -0
- package/corpus/templates/design/changelog/2026-10-19-reply-and-edit-on-a-comment-in-the-sidebar-or-on-a-canvas-pi.md +6 -0
- package/corpus/templates/design/changelog/2026-10-20-comments-return-to-the-mode-they-came-from-and-layers-search.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +185 -85
- package/corpus/templates/dispatch/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/dispatch/CHANGELOG.md +4 -0
- package/corpus/templates/dispatch/actions/apply-workspace-connection-setup.ts +4 -0
- package/corpus/templates/dispatch/actions/delete-workspace-connection.ts +4 -0
- package/corpus/templates/dispatch/actions/set-workspace-connection-grant.ts +4 -0
- package/corpus/templates/dispatch/actions/upsert-workspace-connection.ts +4 -0
- package/corpus/templates/dispatch/changelog/2026-10-19-vault-secrets-grants-link-tokens-app-access-and-workspace-co.md +6 -0
- package/corpus/templates/factory/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +105 -33
- package/corpus/templates/factory/.agents/skills/review-latest-feedback/references/channel-inventory.md +128 -74
- package/corpus/templates/factory/.agents/skills/review-latest-feedback/references/slack-reaction-replies.md +39 -11
- package/corpus/templates/forms/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/mail/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/mail/.agents/skills/contacts-and-crm/SKILL.md +22 -17
- package/corpus/templates/mail/AGENTS.md +1 -1
- package/corpus/templates/mail/CHANGELOG.md +14 -0
- package/corpus/templates/mail/actions/provider-api-request.ts +3 -3
- package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +211 -54
- package/corpus/templates/mail/app/hooks/use-inbox-threads.ts +26 -2
- package/corpus/templates/mail/app/i18n/en-US.ts +5 -1
- package/corpus/templates/mail/app/lib/gong-connection.ts +27 -0
- package/corpus/templates/mail/app/lib/thread-cache.ts +110 -9
- package/corpus/templates/mail/app/root.tsx +10 -2
- package/corpus/templates/mail/changelog/2026-10-20-connected-gong-settings-now-open-the-shared-integration-mana.md +6 -0
- package/corpus/templates/mail/changelog/2026-10-20-gong-connection-details-now-match-the-call-data-available-in.md +6 -0
- package/corpus/templates/mail/changelog/2026-10-20-improve-gong-setup-with-a-click-to-connect-flow-and-permissi.md +6 -0
- package/corpus/templates/mail/changelog/2026-10-20-mail-lets-you-retry-when-it-cannot-check-your-gong-access.md +6 -0
- package/corpus/templates/mail/changelog/2026-10-20-mail-thread-cache-stays-isolated-when-mailbox-scope-changes.md +6 -0
- package/corpus/templates/mail/changelog/2026-10-20-the-inbox-and-recently-opened-threads-now-open-instantly-fro.md +6 -0
- package/corpus/templates/mail/server/handlers/emails.ts +9 -0
- package/corpus/templates/plan/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/plan/CHANGELOG.md +4 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +173 -33
- package/corpus/templates/plan/changelog/2026-10-19-opening-a-comment-thread-puts-the-cursor-in-the-reply-box-an.md +6 -0
- package/corpus/templates/slides/.agents/skills/actions/references/action-fields.md +5 -3
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +6 -42
- package/corpus/templates/slides/app/components/editor/FloatingToolbar.tsx +3 -7
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +5 -14
- package/corpus/templates/slides/app/i18n/en-US.ts +0 -2
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +27 -33
- package/corpus/templates/slides/scripts/edit-fidelity/run.ts +1 -3
- package/corpus/templates/tasks/.agents/skills/actions/references/action-fields.md +5 -3
- package/package.json +1 -1
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
+
import {
|
|
3
|
+
useCreateMcpServer,
|
|
4
|
+
useMcpServers,
|
|
5
|
+
type CreateMcpServerArgs,
|
|
6
|
+
} from "@agent-native/core/client/resources";
|
|
7
|
+
import { buildSettingsRoute } from "@agent-native/core/navigation";
|
|
2
8
|
import { useSendToAgentChat } from "@agent-native/toolkit/app/chat/composer";
|
|
3
9
|
import { ExtensionSlot } from "@agent-native/toolkit/app/extensions";
|
|
10
|
+
import { McpIntegrationDialog } from "@agent-native/toolkit/app/resources";
|
|
4
11
|
import {
|
|
5
12
|
IconPlus,
|
|
6
13
|
IconCheck,
|
|
@@ -8,8 +15,10 @@ import {
|
|
|
8
15
|
IconChevronLeft,
|
|
9
16
|
IconArrowUp,
|
|
10
17
|
} from "@tabler/icons-react";
|
|
11
|
-
import { useState, useEffect, useRef } from "react";
|
|
18
|
+
import { useCallback, useState, useEffect, useRef } from "react";
|
|
19
|
+
import { useNavigate } from "react-router";
|
|
12
20
|
|
|
21
|
+
import { Button } from "@/components/ui/button";
|
|
13
22
|
import {
|
|
14
23
|
DropdownMenu,
|
|
15
24
|
DropdownMenuTrigger,
|
|
@@ -36,6 +45,10 @@ import {
|
|
|
36
45
|
usePylonContact,
|
|
37
46
|
isAuthError,
|
|
38
47
|
} from "@/hooks/use-integrations";
|
|
48
|
+
import {
|
|
49
|
+
canManageGongConnection,
|
|
50
|
+
hasConnectedGongMcpServer,
|
|
51
|
+
} from "@/lib/gong-connection";
|
|
39
52
|
import type { MailIntegrationStatuses } from "@/lib/integration-status";
|
|
40
53
|
import { isMcpEmbedSurface } from "@/lib/mcp-embed";
|
|
41
54
|
import { cn } from "@/lib/utils";
|
|
@@ -58,9 +71,11 @@ interface IntegrationDef {
|
|
|
58
71
|
id: ProviderId;
|
|
59
72
|
name: string;
|
|
60
73
|
descriptionKey: string;
|
|
61
|
-
keyPlaceholder
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
keyPlaceholder?: string;
|
|
75
|
+
keyPlaceholderKey?: string;
|
|
76
|
+
helpUrl?: string;
|
|
77
|
+
helpSteps?: string[];
|
|
78
|
+
helpStepKeys?: string[];
|
|
64
79
|
logo: React.ReactNode;
|
|
65
80
|
}
|
|
66
81
|
|
|
@@ -131,13 +146,9 @@ const INTEGRATIONS: IntegrationDef[] = [
|
|
|
131
146
|
id: "gong",
|
|
132
147
|
name: "Gong",
|
|
133
148
|
descriptionKey: "mail.integrations.gongDescription",
|
|
134
|
-
|
|
149
|
+
keyPlaceholderKey: "mail.integrations.gongKeyPlaceholder",
|
|
135
150
|
helpUrl: "https://app.gong.io/company/api",
|
|
136
|
-
|
|
137
|
-
"Go to Gong > Company Settings > API",
|
|
138
|
-
"Generate API credentials",
|
|
139
|
-
"Copy the access key (or key:secret)",
|
|
140
|
-
],
|
|
151
|
+
helpStepKeys: ["mail.integrations.gongKeyFormatHint"],
|
|
141
152
|
logo: (
|
|
142
153
|
<svg
|
|
143
154
|
viewBox="0 0 42 42"
|
|
@@ -275,8 +286,35 @@ export function IntegrationsSidebar({
|
|
|
275
286
|
}
|
|
276
287
|
|
|
277
288
|
function IntegrationSetup({ statuses }: { statuses: MailIntegrationStatuses }) {
|
|
289
|
+
const t = useT();
|
|
290
|
+
const navigate = useNavigate();
|
|
278
291
|
const [expanded, setExpanded] = useState(false);
|
|
279
292
|
const [configuring, setConfiguring] = useState<ProviderId | null>(null);
|
|
293
|
+
const [gongDialogOpen, setGongDialogOpen] = useState(false);
|
|
294
|
+
const mcpServersQuery = useMcpServers({ defer: true });
|
|
295
|
+
const createMcpServer = useCreateMcpServer();
|
|
296
|
+
const mcpServers = mcpServersQuery.data;
|
|
297
|
+
const canManageGong = canManageGongConnection(mcpServers);
|
|
298
|
+
const canCreateOrgMcp = Boolean(mcpServers?.orgId && canManageGong);
|
|
299
|
+
const gongConnected = hasConnectedGongMcpServer(mcpServers);
|
|
300
|
+
const canRetryGongAccessCheck =
|
|
301
|
+
mcpServersQuery.isError && (!mcpServers || canManageGong);
|
|
302
|
+
const handleCreateMcpServer = useCallback(
|
|
303
|
+
async (args: CreateMcpServerArgs) => {
|
|
304
|
+
if (args.scope === "org" && !canCreateOrgMcp) {
|
|
305
|
+
throw new Error(t("mail.error.failedToConnect"));
|
|
306
|
+
}
|
|
307
|
+
return createMcpServer.mutateAsync(args);
|
|
308
|
+
},
|
|
309
|
+
[canCreateOrgMcp, createMcpServer, t],
|
|
310
|
+
);
|
|
311
|
+
const gongPermissionError = canRetryGongAccessCheck ? (
|
|
312
|
+
<GongPermissionLookupError
|
|
313
|
+
isRetrying={mcpServersQuery.isFetching}
|
|
314
|
+
onRetry={() => void mcpServersQuery.refetch()}
|
|
315
|
+
/>
|
|
316
|
+
) : null;
|
|
317
|
+
const showGong = canManageGong || statuses.gong || gongConnected;
|
|
280
318
|
|
|
281
319
|
if (configuring) {
|
|
282
320
|
const def = INTEGRATIONS.find((i) => i.id === configuring)!;
|
|
@@ -289,17 +327,19 @@ function IntegrationSetup({ statuses }: { statuses: MailIntegrationStatuses }) {
|
|
|
289
327
|
const connectedCount = [
|
|
290
328
|
statuses.apollo,
|
|
291
329
|
statuses.hubspot,
|
|
292
|
-
statuses.gong,
|
|
330
|
+
statuses.gong || gongConnected,
|
|
293
331
|
statuses.pylon,
|
|
294
332
|
].filter(Boolean).length;
|
|
333
|
+
const visibleIntegrationCount = INTEGRATIONS.length - Number(!showGong);
|
|
295
334
|
return (
|
|
296
335
|
<div className="px-4 py-2">
|
|
336
|
+
{gongPermissionError}
|
|
297
337
|
<button
|
|
298
338
|
onClick={() => setExpanded(true)}
|
|
299
339
|
className="text-[11px] text-muted-foreground/70 hover:text-muted-foreground transition-colors"
|
|
300
340
|
>
|
|
301
341
|
{connectedCount > 0
|
|
302
|
-
? `Integrations (${connectedCount}/${
|
|
342
|
+
? `Integrations (${connectedCount}/${visibleIntegrationCount})`
|
|
303
343
|
: "Add integrations"}
|
|
304
344
|
</button>
|
|
305
345
|
</div>
|
|
@@ -308,6 +348,7 @@ function IntegrationSetup({ statuses }: { statuses: MailIntegrationStatuses }) {
|
|
|
308
348
|
|
|
309
349
|
return (
|
|
310
350
|
<div className="px-4 py-3">
|
|
351
|
+
{gongPermissionError}
|
|
311
352
|
<div className="flex items-center justify-between mb-3">
|
|
312
353
|
<h4 className="text-[11px] font-medium text-muted-foreground uppercase tracking-wider">
|
|
313
354
|
Integrations
|
|
@@ -320,19 +361,74 @@ function IntegrationSetup({ statuses }: { statuses: MailIntegrationStatuses }) {
|
|
|
320
361
|
</button>
|
|
321
362
|
</div>
|
|
322
363
|
<div className="space-y-1.5">
|
|
323
|
-
{INTEGRATIONS.
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
364
|
+
{INTEGRATIONS.filter((def) => def.id !== "gong" || showGong).map(
|
|
365
|
+
(def) => {
|
|
366
|
+
const connected =
|
|
367
|
+
def.id === "gong"
|
|
368
|
+
? statuses.gong || gongConnected
|
|
369
|
+
: statuses[def.id];
|
|
370
|
+
return (
|
|
371
|
+
<IntegrationRow
|
|
372
|
+
key={def.id}
|
|
373
|
+
def={def}
|
|
374
|
+
connected={connected}
|
|
375
|
+
mcpConnected={def.id === "gong" && gongConnected}
|
|
376
|
+
legacyConnected={def.id === "gong" && statuses.gong}
|
|
377
|
+
canManageMcpSetup={def.id !== "gong" || canManageGong}
|
|
378
|
+
onManage={() =>
|
|
379
|
+
void navigate(buildSettingsRoute("integrations"))
|
|
380
|
+
}
|
|
381
|
+
onConfigure={() => {
|
|
382
|
+
if (def.id === "gong") setGongDialogOpen(true);
|
|
383
|
+
else setConfiguring(def.id);
|
|
384
|
+
}}
|
|
385
|
+
onLegacyConfigure={
|
|
386
|
+
def.id === "gong" ? () => setConfiguring("gong") : undefined
|
|
387
|
+
}
|
|
388
|
+
/>
|
|
389
|
+
);
|
|
390
|
+
},
|
|
391
|
+
)}
|
|
334
392
|
<AddIntegrationButton />
|
|
335
393
|
</div>
|
|
394
|
+
<McpIntegrationDialog
|
|
395
|
+
open={gongDialogOpen}
|
|
396
|
+
onOpenChange={setGongDialogOpen}
|
|
397
|
+
initialIntegrationId={gongDialogOpen ? "gong" : null}
|
|
398
|
+
defaultScope="org"
|
|
399
|
+
canCreateOrgMcp={canCreateOrgMcp}
|
|
400
|
+
hasOrg={Boolean(mcpServers?.orgId)}
|
|
401
|
+
onCreateMcpServer={handleCreateMcpServer}
|
|
402
|
+
onCreated={() => void mcpServersQuery.refetch()}
|
|
403
|
+
/>
|
|
404
|
+
</div>
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function GongPermissionLookupError({
|
|
409
|
+
isRetrying,
|
|
410
|
+
onRetry,
|
|
411
|
+
}: {
|
|
412
|
+
isRetrying: boolean;
|
|
413
|
+
onRetry: () => void;
|
|
414
|
+
}) {
|
|
415
|
+
const t = useT();
|
|
416
|
+
|
|
417
|
+
return (
|
|
418
|
+
<div className="mb-2 flex items-center justify-between gap-2" role="alert">
|
|
419
|
+
<p className="text-[11px] text-muted-foreground">
|
|
420
|
+
{t("mail.integrations.gongAccessCheckFailed")}
|
|
421
|
+
</p>
|
|
422
|
+
<Button
|
|
423
|
+
type="button"
|
|
424
|
+
variant="ghost"
|
|
425
|
+
size="sm"
|
|
426
|
+
className="h-auto shrink-0 px-2 py-1 text-[11px]"
|
|
427
|
+
onClick={onRetry}
|
|
428
|
+
disabled={isRetrying}
|
|
429
|
+
>
|
|
430
|
+
{t(isRetrying ? "mail.error.retrying" : "mail.error.tryAgain")}
|
|
431
|
+
</Button>
|
|
336
432
|
</div>
|
|
337
433
|
);
|
|
338
434
|
}
|
|
@@ -450,14 +546,26 @@ function AddIntegrationButton() {
|
|
|
450
546
|
function IntegrationRow({
|
|
451
547
|
def,
|
|
452
548
|
connected,
|
|
549
|
+
mcpConnected = false,
|
|
550
|
+
legacyConnected = false,
|
|
551
|
+
canManageMcpSetup = true,
|
|
552
|
+
onManage,
|
|
453
553
|
onConfigure,
|
|
554
|
+
onLegacyConfigure,
|
|
454
555
|
}: {
|
|
455
556
|
def: IntegrationDef;
|
|
456
557
|
connected: boolean;
|
|
558
|
+
mcpConnected?: boolean;
|
|
559
|
+
legacyConnected?: boolean;
|
|
560
|
+
canManageMcpSetup?: boolean;
|
|
561
|
+
onManage?: () => void;
|
|
457
562
|
onConfigure: () => void;
|
|
563
|
+
onLegacyConfigure?: () => void;
|
|
458
564
|
}) {
|
|
459
565
|
const t = useT();
|
|
460
566
|
const { disconnect } = useIntegration(def.id);
|
|
567
|
+
const showSettings =
|
|
568
|
+
def.id !== "gong" || canManageMcpSetup || legacyConnected;
|
|
461
569
|
|
|
462
570
|
return (
|
|
463
571
|
<div className="flex items-center gap-2.5 py-1.5 group relative">
|
|
@@ -475,32 +583,70 @@ function IntegrationRow({
|
|
|
475
583
|
<div className="h-5 w-5 rounded-full bg-emerald-500/20 flex items-center justify-center">
|
|
476
584
|
<IconCheck className="h-3 w-3 text-emerald-400" />
|
|
477
585
|
</div>
|
|
478
|
-
|
|
479
|
-
<
|
|
480
|
-
<
|
|
481
|
-
<
|
|
482
|
-
<
|
|
483
|
-
<
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
>
|
|
494
|
-
{
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
586
|
+
{showSettings && (
|
|
587
|
+
<DropdownMenu>
|
|
588
|
+
<Tooltip>
|
|
589
|
+
<TooltipTrigger asChild>
|
|
590
|
+
<DropdownMenuTrigger asChild>
|
|
591
|
+
<button
|
|
592
|
+
aria-label={t("mail.toolbar.settings")}
|
|
593
|
+
className="h-5 w-5 flex items-center justify-center rounded text-muted-foreground/30 hover:text-muted-foreground transition-colors"
|
|
594
|
+
>
|
|
595
|
+
<IconSettings className="h-3.5 w-3.5" />
|
|
596
|
+
</button>
|
|
597
|
+
</DropdownMenuTrigger>
|
|
598
|
+
</TooltipTrigger>
|
|
599
|
+
<TooltipContent>{t("mail.toolbar.settings")}</TooltipContent>
|
|
600
|
+
</Tooltip>
|
|
601
|
+
<DropdownMenuContent align="end" className="w-36">
|
|
602
|
+
{def.id === "gong" ? (
|
|
603
|
+
<>
|
|
604
|
+
{canManageMcpSetup && (
|
|
605
|
+
<DropdownMenuItem
|
|
606
|
+
onClick={mcpConnected ? onManage : onConfigure}
|
|
607
|
+
className="text-[12px] text-foreground/70"
|
|
608
|
+
>
|
|
609
|
+
{mcpConnected
|
|
610
|
+
? t("mail.toolbar.settings")
|
|
611
|
+
: t("mail.integrations.connect")}
|
|
612
|
+
</DropdownMenuItem>
|
|
613
|
+
)}
|
|
614
|
+
{legacyConnected && (
|
|
615
|
+
<>
|
|
616
|
+
<DropdownMenuItem
|
|
617
|
+
onClick={onLegacyConfigure}
|
|
618
|
+
className="text-[12px] text-foreground/70"
|
|
619
|
+
>
|
|
620
|
+
{t("mail.integrations.updateKey")}
|
|
621
|
+
</DropdownMenuItem>
|
|
622
|
+
<DropdownMenuItem
|
|
623
|
+
onClick={() => disconnect.mutate()}
|
|
624
|
+
className="text-[12px] text-destructive/80"
|
|
625
|
+
>
|
|
626
|
+
{t("mail.integrations.disconnect")}
|
|
627
|
+
</DropdownMenuItem>
|
|
628
|
+
</>
|
|
629
|
+
)}
|
|
630
|
+
</>
|
|
631
|
+
) : (
|
|
632
|
+
<>
|
|
633
|
+
<DropdownMenuItem
|
|
634
|
+
onClick={() => onConfigure()}
|
|
635
|
+
className="text-[12px] text-foreground/70"
|
|
636
|
+
>
|
|
637
|
+
{t("mail.integrations.updateKey")}
|
|
638
|
+
</DropdownMenuItem>
|
|
639
|
+
<DropdownMenuItem
|
|
640
|
+
onClick={() => disconnect.mutate()}
|
|
641
|
+
className="text-[12px] text-destructive/80"
|
|
642
|
+
>
|
|
643
|
+
{t("mail.integrations.disconnect")}
|
|
644
|
+
</DropdownMenuItem>
|
|
645
|
+
</>
|
|
646
|
+
)}
|
|
647
|
+
</DropdownMenuContent>
|
|
648
|
+
</DropdownMenu>
|
|
649
|
+
)}
|
|
504
650
|
</div>
|
|
505
651
|
) : (
|
|
506
652
|
<button
|
|
@@ -552,7 +698,11 @@ function IntegrationKeyEntry({
|
|
|
552
698
|
setApiKey(e.target.value);
|
|
553
699
|
if (connect.error) connect.reset();
|
|
554
700
|
}}
|
|
555
|
-
placeholder={
|
|
701
|
+
placeholder={
|
|
702
|
+
def.keyPlaceholderKey
|
|
703
|
+
? t(def.keyPlaceholderKey)
|
|
704
|
+
: def.keyPlaceholder
|
|
705
|
+
}
|
|
556
706
|
autoFocus
|
|
557
707
|
className="flex-1 min-w-0 rounded-md border border-border bg-background px-2 py-1 text-[12px] outline-none focus:border-primary/50 placeholder:text-muted-foreground/40"
|
|
558
708
|
/>
|
|
@@ -581,9 +731,12 @@ function IntegrationKeyEntry({
|
|
|
581
731
|
{t("mail.integrations.getApiKey")}
|
|
582
732
|
</p>
|
|
583
733
|
<ol className="text-[11px] text-muted-foreground/50 space-y-0.5 list-decimal ps-3 mb-1.5">
|
|
584
|
-
{def.helpSteps
|
|
734
|
+
{def.helpSteps?.map((step, i) => (
|
|
585
735
|
<li key={i}>{step}</li>
|
|
586
736
|
))}
|
|
737
|
+
{def.helpStepKeys?.map((key) => (
|
|
738
|
+
<li key={key}>{t(key)}</li>
|
|
739
|
+
))}
|
|
587
740
|
</ol>
|
|
588
741
|
<a
|
|
589
742
|
href={def.helpUrl}
|
|
@@ -610,6 +763,7 @@ function IntegrationNotice({
|
|
|
610
763
|
error: unknown;
|
|
611
764
|
providerId: ProviderId;
|
|
612
765
|
}) {
|
|
766
|
+
const t = useT();
|
|
613
767
|
const authErr = isAuthError(error);
|
|
614
768
|
const [reconnecting, setReconnecting] = useState(false);
|
|
615
769
|
const def = INTEGRATIONS.find((i) => i.id === providerId)!;
|
|
@@ -641,7 +795,11 @@ function IntegrationNotice({
|
|
|
641
795
|
setApiKey(e.target.value);
|
|
642
796
|
if (connect.error) connect.reset();
|
|
643
797
|
}}
|
|
644
|
-
placeholder={
|
|
798
|
+
placeholder={
|
|
799
|
+
def.keyPlaceholderKey
|
|
800
|
+
? t(def.keyPlaceholderKey)
|
|
801
|
+
: def.keyPlaceholder
|
|
802
|
+
}
|
|
645
803
|
autoFocus
|
|
646
804
|
className="flex-1 min-w-0 rounded-md border border-border bg-background px-2 py-1 text-[12px] outline-none focus:border-primary/50 placeholder:text-muted-foreground/40"
|
|
647
805
|
/>
|
|
@@ -1037,11 +1195,10 @@ function GongSection({ email }: { email: string }) {
|
|
|
1037
1195
|
|
|
1038
1196
|
if (isLoading) return <SectionLoading />;
|
|
1039
1197
|
if (!calls || calls.length === 0) {
|
|
1040
|
-
if (error)
|
|
1198
|
+
if (error)
|
|
1041
1199
|
return (
|
|
1042
1200
|
<IntegrationNotice email={email} error={error} providerId="gong" />
|
|
1043
1201
|
);
|
|
1044
|
-
}
|
|
1045
1202
|
return null;
|
|
1046
1203
|
}
|
|
1047
1204
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
callActionWithRetry,
|
|
3
|
+
currentActionQueryCacheBinding,
|
|
4
|
+
recordActionQueryBrowserPersist,
|
|
3
5
|
useActionMutation,
|
|
4
6
|
} from "@agent-native/core/client/hooks";
|
|
5
7
|
import { agentNativeApiDisabledReason } from "@agent-native/core/client/host";
|
|
@@ -243,7 +245,20 @@ export function keepInboxProgressOrder(
|
|
|
243
245
|
return { ...incoming, items };
|
|
244
246
|
}
|
|
245
247
|
|
|
246
|
-
|
|
248
|
+
// Pages restored from the persisted query cache keep the ids of the page load
|
|
249
|
+
// that fetched them, so ids start from the clock and any fetch in this load
|
|
250
|
+
// outranks a restored page instead of losing to it.
|
|
251
|
+
const PAGE_LOAD_INBOX_SNAPSHOT_ID = Date.now();
|
|
252
|
+
let nextInboxSnapshotId = PAGE_LOAD_INBOX_SNAPSHOT_ID;
|
|
253
|
+
|
|
254
|
+
/** A restored page paints at once but is refetched on mount; this load's pages stay fresh. */
|
|
255
|
+
export function inboxThreadsStaleTime(query: {
|
|
256
|
+
state: { data?: { clientSnapshotId?: number } };
|
|
257
|
+
}): number {
|
|
258
|
+
return (query.state.data?.clientSnapshotId ?? 0) > PAGE_LOAD_INBOX_SNAPSHOT_ID
|
|
259
|
+
? INBOX_THREADS_STALE_TIME_MS
|
|
260
|
+
: 0;
|
|
261
|
+
}
|
|
247
262
|
|
|
248
263
|
function readInboxQueryParams(key: QueryKey): Record<string, unknown> | null {
|
|
249
264
|
const params = key[2];
|
|
@@ -297,6 +312,9 @@ function fetchInboxThreads(
|
|
|
297
312
|
queryKey: QueryKey,
|
|
298
313
|
): Promise<InboxQueryResult> {
|
|
299
314
|
const clientSnapshotId = ++nextInboxSnapshotId;
|
|
315
|
+
const query = qc.getQueryCache().find({ queryKey, exact: true });
|
|
316
|
+
const cacheBinding = currentActionQueryCacheBinding();
|
|
317
|
+
let response: Response | undefined;
|
|
300
318
|
return callActionWithRetry<ListInboxThreadsResult>(
|
|
301
319
|
"list-inbox-threads",
|
|
302
320
|
input,
|
|
@@ -304,8 +322,14 @@ function fetchInboxThreads(
|
|
|
304
322
|
method: "GET",
|
|
305
323
|
signal,
|
|
306
324
|
timeoutMs: INBOX_THREADS_REQUEST_TIMEOUT_MS,
|
|
325
|
+
onResponse: (next) => {
|
|
326
|
+
response = next;
|
|
327
|
+
},
|
|
307
328
|
},
|
|
308
329
|
).then((data) => {
|
|
330
|
+
if (query && !signal.aborted) {
|
|
331
|
+
recordActionQueryBrowserPersist(query, response, cacheBinding);
|
|
332
|
+
}
|
|
309
333
|
const incoming = { ...data, clientSnapshotId };
|
|
310
334
|
publishInboxOverview(qc, input.accountEmails, {
|
|
311
335
|
tabs: incoming.tabs,
|
|
@@ -361,7 +385,7 @@ export function useInboxThreads(
|
|
|
361
385
|
enabled: (opts?.enabled ?? true) && !agentNativeApiDisabledReason(),
|
|
362
386
|
retry: false,
|
|
363
387
|
refetchInterval: inboxThreadsRefetchInterval,
|
|
364
|
-
staleTime:
|
|
388
|
+
staleTime: inboxThreadsStaleTime,
|
|
365
389
|
select: (data) => applyInboxMutationOverlay(qc, data) as InboxQueryResult,
|
|
366
390
|
});
|
|
367
391
|
}
|
|
@@ -305,7 +305,11 @@ const messages = {
|
|
|
305
305
|
openProviderSettings: "Open {{provider}} Settings",
|
|
306
306
|
apolloDescription: "Contact enrichment & company data",
|
|
307
307
|
hubspotDescription: "CRM contacts, deals & tickets",
|
|
308
|
-
gongDescription: "
|
|
308
|
+
gongDescription: "Gong call history",
|
|
309
|
+
gongAccessCheckFailed: "Couldn't check whether you can connect to Gong.",
|
|
310
|
+
gongKeyPlaceholder: "Gong API key",
|
|
311
|
+
gongKeyFormatHint:
|
|
312
|
+
"Enter the access key and secret as access_key:secret.",
|
|
309
313
|
pylonDescription: "Support issues & account data",
|
|
310
314
|
gongCalls: "Gong Calls",
|
|
311
315
|
deals: "Deals",
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { McpServersList } from "@agent-native/core/client/resources";
|
|
2
|
+
|
|
3
|
+
export function canManageGongConnection(
|
|
4
|
+
servers: McpServersList | undefined,
|
|
5
|
+
): boolean {
|
|
6
|
+
if (!servers) return false;
|
|
7
|
+
if (servers.orgId === null) return true;
|
|
8
|
+
return servers.role === "owner" || servers.role === "admin";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function hasConnectedGongMcpServer(
|
|
12
|
+
servers: McpServersList | undefined,
|
|
13
|
+
): boolean {
|
|
14
|
+
if (!servers) return false;
|
|
15
|
+
return [...servers.user, ...servers.org].some(
|
|
16
|
+
(server) => server.status.state === "connected" && isGongMcpUrl(server.url),
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isGongMcpUrl(value: string): boolean {
|
|
21
|
+
if (!URL.canParse(value)) return false;
|
|
22
|
+
const url = new URL(value);
|
|
23
|
+
return (
|
|
24
|
+
url.origin === "https://mcp.gong.io" &&
|
|
25
|
+
url.pathname.replace(/\/+$/, "") === "/mcp"
|
|
26
|
+
);
|
|
27
|
+
}
|